Include content from other files with automatic updates and edit protection.
Virtual Include is a powerful VS Code extension that allows you to include content from other files directly in your code. Unlike traditional includes which require preprocessing, Virtual Include works with any language and automatically updates content when source files change.
- β Language Agnostic: Works with JavaScript, TypeScript, Python, Ruby, C#, Java, HTML, CSS, and more
- β Live Updates: Content automatically updates when source files change
- β Protected Content: Included content is protected from accidental edits
- β Visual Feedback: Error indicators for missing files and status bar integration
- β Multiple Languages: Adapts to each language's comment style
- β Navigation Links: Code lens above include directives to quickly open source files
- Open VS Code
- Press
Ctrl+P(orCmd+Pon Mac) - Type
ext install artworkad.vscode-virtual-include - Press Enter
- Add a virtual include directive in your code using your language's comment style
- Reference the file you want to include
- Save the document
The extension will automatically process the include directive and insert the content from the referenced file. The included content is protected from edits - if you want to change it, edit the source file instead!
The include directive follows this format:
[comment style] virtualInclude '[path]'
Where:
[comment style]is the comment syntax for your language[path]is the path to the file you want to include (relative to the current file or absolute)
JavaScript/TypeScript:
// virtualInclude 'utils/helper.js'Python:
# virtualInclude 'models/user.py'HTML:
<!-- virtualInclude 'components/header.html' -->CSS:
/* virtualInclude 'styles/variables.css' */C/C++/Java/C#:
// virtualInclude 'common/math.h'Ruby:
# virtualInclude 'lib/utilities.rb'When you save the file, the extension will process the include directive and insert the content from the referenced file. The included content will be wrapped between start and end markers:
// virtualInclude 'utils/helper.js'
// virtualIncludeStart - DO NOT EDIT CONTENT BELOW
function helperFunction() {
return "Hello, world!";
}
// virtualIncludeEnd - DO NOT EDIT CONTENT ABOVEThe extension automatically preserves the indentation from the include directive line, so included content will match your code style:
function example() {
// virtualInclude 'utils/helper.js'
// virtualIncludeStart - DO NOT EDIT CONTENT BELOW
function helperFunction() {
return "Hello, world!";
}
// virtualIncludeEnd - DO NOT EDIT CONTENT ABOVE
}If a referenced file cannot be found, the extension will show an error indicator (red squiggly line) under the include directive. Hovering over it will show the specific error message.
The extension adds a status bar item that shows the current state:
- π Virtual Include: Normal state
- π Processing Includes: When the extension is processing includes
β οΈ Virtual Include (X issues): When there are problems with includes
You can click the status bar item to manually trigger include processing.
The extension adds a clickable code lens above each virtual include directive. When you hover over an include directive, you'll see an "Open included file" link that allows you to quickly navigate to the source file without having to manually locate it.
This feature makes it easy to:
- Jump directly to source files when working with includes
- Navigate between related files in your project
- Quickly check the content of included files
The code lens can be disabled in settings if preferred:
"virtualInclude.showCodeLens": falseWhen a source file changes, the extension will show a notification with options to:
- Show affected files
- Save all affected files
You can customize the extension's behavior through VS Code settings:
"virtualInclude": {
"defaultCommentStyle": "#",
"languageSettings": {
"javascript": {
"includeDirectivePattern": "\/\/\\s*virtualInclude\\s+[\"'](.+?)[\"']",
"startMarkerTemplate": "// virtualIncludeStart - DO NOT EDIT CONTENT BELOW",
"endMarkerTemplate": "// virtualIncludeEnd - DO NOT EDIT CONTENT ABOVE"
}
}
}virtualInclude.defaultCommentStyle: Default comment style for languages without specific settings (defaults to#)virtualInclude.languageSettings: Override settings for specific languages with custom patterns and markers
The extension handles nested includes in a special way to prevent infinite inclusion loops:
-
When a file (A) includes another file (B) that itself contains include directives
-
The include directives from file B are neutralized when inserted into file A
-
These nested include directives are transformed to a non-processing format:
// virtualInclude 'file.js' β // virtualInclude-nested (edit source file to modify) 'file.js'
Why this happens: This prevents an infinite cycle of inclusions that would cause the editor to freeze or crash. Without this protection, include directives in included content would be processed again and again with each save.
How to work with nested includes: If you need to modify the content from a nested include, you should:
- Open and edit the source file directly
- Save the source file - all files including it will be automatically updated
Virtual Include supports including content from one language in files of another language. This is especially useful for:
- Including lua-resty-template code in YAML files (for APISIX configurations)
- Including JavaScript in HTML files (beyond the standard
<script>tag support) - Including SQL queries in Python, PHP, or JavaScript files
- Including any language in templates or configuration files
There are three ways to use cross-language includes:
You can explicitly specify the comment style to use:
# In a YAML file, but we need lua-resty-template comment style
template: >-
{# virtualInclude 'transform.lua' with '{#' #}This tells the extension to use {# #} (lua-resty-template comment style) for
both the include directive and the markers.
By default, the extension will automatically detect the appropriate language based on the included file's extension:
template: >-
{# virtualInclude 'transform.lua' #}The .lua extension will be recognized, but since it's in a YAML template
section, the extension will use lua-resty-template comment style ({# #}) for
the markers.
For more complex files, you can define specific sections that should use different comment styles:
"virtualInclude.languageOverrides": [
{
"fileType": "yaml",
"pattern": "template:\\s*>-\\s*$", // Matches YAML template: >- lines
"commentStyle": "{#", // Use lua-resty-template comment style start
"commentEnd": "#}", // Use lua-resty-template comment style end
"continueUntil": "^\\S" // Continue until a non-indented line
}
]This configuration automatically applies lua-resty-template comment style to any includes found within YAML template sections.
You can customize the include directive pattern, start marker, and end marker for each language using the settings:
"virtualInclude.languageSettings": {
"python": {
"includeDirectivePattern": "#\\s*import\\s+[\"'](.+?)[\"']",
"startMarkerTemplate": "# BEGIN IMPORT - DO NOT EDIT",
"endMarkerTemplate": "# END IMPORT - DO NOT EDIT"
}
}With these settings, Python includes would look like:
# import 'models/user.py'
# BEGIN IMPORT - DO NOT EDIT
class User:
def __init__(self, name):
self.name = name
# END IMPORT - DO NOT EDITInclude common configuration settings across multiple files:
// config.js
// virtualInclude 'common-config.js'Include common code snippets:
# api.py
# virtualInclude 'error-handling.py'Include documentation sections:
<!-- README.md -->
<!-- virtualInclude 'installation.md' -->Include common HTML templates:
<!-- index.html -->
<!-- virtualInclude 'header.html' -->The extension contributes the following commands:
- Process Virtual Includes: Manually process all virtual includes in the current file
You can access this command from:
- Right-click context menu in the editor
- Command palette (
Ctrl+Shift+PorCmd+Shift+Pon Mac) - Clicking the Virtual Include status bar item
Solution: Make sure file watchers are enabled in your environment. Some network drives may not support file watching.
Solution: Check that the path is correct and relative to the current file, not the workspace root.
Solution: Try manually saving the file to trigger include processing, or use the "Process Virtual Includes" command from the context menu.
- VS Code ^1.98.0
Contributions are welcome! Please feel free to submit a Pull Request.
Published by artworkad