JQHTML VS Code Extension
Syntax highlighting and language support for JQHTML template files.
Introduction
JQHTML is a component templating system built on jQuery. It lets you compose logical
concepts in HTML rather than assembling visual primitives with cryptic class names.
What JQHTML Is
JQHTML provides:
- Component-based architecture without virtual DOM
- Template compilation to efficient JavaScript
- Deterministic lifecycle (create -> render -> load -> ready)
- Direct jQuery integration - components ARE jQuery objects
Full documentation lives at jqhtml.org.
Features
Syntax Highlighting
Full syntax highlighting for all JQHTML constructs:
- Component Definitions:
<Define:ComponentName>
- Template Expressions:
<%= expression %>
- Control Flow:
<% if (condition) { %> ... <% } %>
- Slots:
<Slot:slotname> for both definition and content
- Data Bindings:
:property="value"
- Event Handlers:
@click="handler"
- Special Attributes:
$sid="name", $property="value"
- Components:
<MyComponent />
- Comments:
<%-- comment --%>
Language Configuration
- Auto-closing pairs: Automatically close tags, brackets, and quotes
- Bracket matching: Highlight matching brackets and tags
- Code folding: Fold component definitions
- Smart indentation: Handles control flow
- Comment toggling: Use standard VS Code shortcuts to toggle comments
Code Snippets
Snippets for common template patterns, in .jqhtml files:
| Prefix |
Description |
define |
Component definition |
definecomp |
Component with structure |
if{ |
If statement (brace style) |
for{ |
For loop (brace style) |
exp |
Expression <%= %> |
expraw |
Unescaped expression <%!= %> |
expbr |
Expression with nl2br <%br= %> |
$id |
Scoped ID attribute |
:prop |
Property binding |
@event |
Event handler |
slot |
Named slot |
slotself |
Self-closing slot |
comment |
Comment block |
comp |
Component usage |
compslot |
Component with slot content |
And for component classes, in JavaScript and TypeScript files:
| Prefix |
Description |
jqcomponent |
Component class with the common lifecycle hooks |
jqon_create |
on_create() hook |
jqon_load |
on_load() hook |
jqon_loaded |
on_loaded() hook |
jqon_render |
on_render() hook |
jqon_ready |
on_ready() hook |
jqon_stop |
on_stop() hook |
jqon_viewport_resize |
on_viewport_resize() hook |
jqgate_load |
gate_load() call |
jqon |
Event listener |
jqonce |
One-shot event listener |
jqtrigger |
Trigger an event |
jqload_only |
_load_only lifecycle flag |
jqload_render_only |
_load_render_only lifecycle flag |
jqforce_initial_render |
_force_initial_render lifecycle flag |
Usage
The extension automatically activates for .jqhtml files. Features include:
Syntax Highlighting
All JQHTML syntax is highlighted with semantic colors:
<Define:UserCard>
<div class="user-card" $sid="card">
<h2><%= this.data.name %></h2>
<% if (this.data.isAdmin) { %>
<span class="admin">Admin</span>
<% } %>
<button @click="handleClick">Click Me</button>
<% for (const skill of this.data.skills) { %>
<div class="skill"><%= skill %></div>
<% } %>
</div>
</Define:UserCard>
IntelliSense
Basic HTML tag and attribute completion is provided through VS Code's built-in HTML support. In addition, the extension ships custom, JQHTML-aware providers:
- Go to Definition - Jump from a component tag,
$ attribute reference, extends="" attribute, or Slot: name to where it's defined, backed by a workspace-wide component index. Slot names are ordinary identifiers, so <Slot:header> navigates just like <Slot:Header>; a $attr=this.member reference resolves against the enclosing <Define:> component and is looked up in JavaScript only (no PHP lookup, and no standalone-function fallback). Other $ references try PHP classes first, then JavaScript classes, then standalone JavaScript functions, asking the installed language servers before falling back to scanning the workspace.
- Hover - Hover over a component name for JQHTML-specific information, using the same component index.
Code Folding
Component definitions can be folded at the <Define:> level:
▼ <Define:MyComponent>
...
</Define:MyComponent>
The extension ships a custom, JQHTML-aware document formatter (not VS Code's generic HTML formatter). Run it via Format Document, Format Selection, or your usual format-on-save setting.
- Indents by HTML nesting and by the braces in
<% %> code, including if / else chains split across blocks
- Multi-line
<% %> blocks and <%-- --%> comments keep their internal layout and sit one level under the line that opens them
<pre> and <textarea> bodies are never touched
- Multi-line tags get their attributes indented under the tag
- Honours your
tabSize / insertSpaces settings and the file's existing line endings
- Never rewrites content - only leading whitespace changes
If a document cannot be formatted (an unterminated <%, <%-- or <!--), the formatter leaves it alone and says why.
Laravel Blade Support
The extension also registers a blade language (for .blade.php files) and injects JQHTML component highlighting into it, so JQHTML components used inside Laravel Blade templates get highlighted too. This includes:
- Component tag names and the
tag="" attribute highlighted via a dedicated semantic tokens provider
- Blade-aware indentation/auto-indent rules
- Auto-spacing inside Blade tags as you type -
{{ expands to {{ | }}, {!! to {!! | !!}, and {{-- to {{-- | --}} (cursor at |)
Two settings control this behavior:
| Setting |
Default |
Description |
jqhtml.enableBladeSupport |
true |
Enable JQHTML component highlighting in Laravel Blade (.blade.php) files |
jqhtml.enableBladeAutoSpacing |
true |
Automatically add spaces inside Blade tags when typing |
Output and Diagnostics
Everything the extension has to say goes to the JQHTML output channel (View -> Output, then pick JQHTML from the dropdown) rather than to the developer console: the workspace index summary, duplicate-component warnings and errors are always recorded there. Setting jqhtml.debug to true adds verbose tracing - every Go to Definition decision, the indexing steps, and what the component index contains - which is what to turn on before reporting a navigation problem. It defaults to false.
Configuration
The extension sets these defaults for JQHTML files:
{
"[jqhtml]": {
"editor.wordWrap": "on",
"editor.quickSuggestions": {
"other": true,
"comments": false,
"strings": true
}
}
}
You can override these in your VS Code settings.
Theme Support
The extension uses standard TextMate scopes and works with all VS Code themes. For best results, use a theme with good HTML/JavaScript support.
Testing
From packages/vscode-extension, after ./build.sh --dev:
npm test # all three tiers
npm run test:unit # formatter fixtures + provider unit tests (sub-second)
npm run test:grammar # TextMate tokenisation snapshots
npm run test:host # a real VS Code extension host
JQHTML_FAST=1 npm test # tiers 1 and 2; the extension host tier prints SKIPPED
- Tier 1 loads the compiled
out/*.js with the vscode module replaced by
an in-memory stub, and covers the formatter, the component index, Go to
Definition, hovers, Blade semantic tokens and Blade auto-spacing.
- Tier 2 tokenises fixtures with the same TextMate engine VS Code runs and
compares every token against a checked-in snapshot.
- Tier 3 launches a real VS Code, opens a fixture workspace and drives the
extension through VS Code's own commands. It downloads VS Code (~1 GB) into
~/.cache/jqhtml-vscode-test/ on first run (override with JQHTML_VSCODE_CACHE) and needs a display (it uses xvfb-run
automatically when DISPLAY is unset).
License
MIT — Copyright (c) 2026 HansonXyz
Changelog
See CHANGELOG.md.