Skip to content

Commit 3c4e987

Browse files
committed
Preserve support for XHTML/HTML tags; bracket folding inside <? tags
1 parent bcb4090 commit 3c4e987

5 files changed

Lines changed: 103 additions & 83 deletions

File tree

out/extension.js

Lines changed: 42 additions & 36 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

out/extension.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "jxml-support",
33
"displayName": "JXML Support",
44
"description": "VS Code extension for JXML: code folding for <? ... ?> and <?jxml ... ?> tags, NodeJS/JavaScript syntax highlighting and code hinting within those tags, and HTML highlighting outside.",
5-
"version": "0.0.1",
5+
"version": "0.0.2",
66
"publisher": "Virtuosoft",
77
"repository": {
88
"type": "git",

src/extension.ts

Lines changed: 59 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -23,51 +23,65 @@ export function activate(context: vscode.ExtensionContext) {
2323

2424
// Register a folding range provider for jxml
2525
context.subscriptions.push(
26-
vscode.languages.registerFoldingRangeProvider('jxml', {
27-
provideFoldingRanges(document, context, token) {
28-
console.log('Folding provider called for', document.fileName);
29-
const foldingRanges: vscode.FoldingRange[] = [];
30-
const startRegex = /<\?(jxml)?/;
31-
const endRegex = /\?>/;
32-
let startLine: number | null = null;
33-
let inScript = false;
34-
// Track JS block folding inside <? ... ?>
35-
let jsBlockStack: number[] = [];
36-
for (let i = 0; i < document.lineCount; i++) {
37-
const line = document.lineAt(i).text;
38-
if (!inScript && startRegex.test(line)) {
39-
startLine = i;
40-
inScript = true;
41-
continue;
42-
}
43-
if (inScript && endRegex.test(line)) {
44-
if (startLine !== null) {
45-
foldingRanges.push(new vscode.FoldingRange(startLine, i));
46-
console.log(`Folding range: ${startLine} to ${i}`);
47-
}
48-
startLine = null;
49-
inScript = false;
50-
jsBlockStack = [];
51-
continue;
52-
}
53-
if (inScript) {
54-
// Custom JS block folding for { ... }
55-
if (line.includes('{')) {
56-
jsBlockStack.push(i);
57-
}
58-
if (line.includes('}')) {
59-
const blockStart = jsBlockStack.pop();
60-
if (blockStart !== undefined && blockStart < i) {
61-
foldingRanges.push(new vscode.FoldingRange(blockStart, i));
62-
console.log(`JS block folding: ${blockStart} to ${i}`);
63-
}
64-
}
65-
}
66-
}
67-
return foldingRanges;
68-
}
69-
})
70-
);
26+
vscode.languages.registerFoldingRangeProvider('jxml', {
27+
async provideFoldingRanges(document, token) {
28+
// Create a virtual document to get HTML folding ranges
29+
const virtualDoc = await vscode.workspace.openTextDocument({
30+
language: 'html',
31+
content: document.getText()
32+
});
33+
const htmlRanges = await vscode.commands.executeCommand<vscode.FoldingRange[]>(
34+
'vscode.executeFoldingRangeProvider',
35+
virtualDoc.uri
36+
) || [];
37+
38+
// --- Custom JXML and JavaScript folding logic ---
39+
const jxmlAndJsRanges: vscode.FoldingRange[] = [];
40+
const text = document.getText();
41+
const startRegex = /<\?(jxml)?/g;
42+
const endRegex = /\?>/g;
43+
let startMatch;
44+
45+
while ((startMatch = startRegex.exec(text)) !== null) {
46+
endRegex.lastIndex = startMatch.index + startMatch[0].length;
47+
const endMatch = endRegex.exec(text);
48+
if (endMatch) {
49+
const startPos = document.positionAt(startMatch.index);
50+
const endPos = document.positionAt(endMatch.index + endMatch[0].length);
51+
52+
// 1. Fold the entire <? ... ?> block
53+
if (startPos.line < endPos.line) {
54+
jxmlAndJsRanges.push(new vscode.FoldingRange(startPos.line, endPos.line, vscode.FoldingRangeKind.Region));
55+
}
56+
57+
// 2. Find and fold {...} blocks within the JXML block
58+
const blockContentStartIndex = startMatch.index + startMatch[0].length;
59+
const blockContentEndIndex = endMatch.index;
60+
const openBraceStack: number[] = [];
61+
62+
for (let i = blockContentStartIndex; i < blockContentEndIndex; i++) {
63+
if (text[i] === '{') {
64+
openBraceStack.push(i);
65+
} else if (text[i] === '}' && openBraceStack.length > 0) {
66+
const openBraceIndex = openBraceStack.pop();
67+
if (openBraceIndex) {
68+
const jsStartPos = document.positionAt(openBraceIndex);
69+
const jsEndPos = document.positionAt(i);
70+
if (jsStartPos.line < jsEndPos.line) {
71+
jxmlAndJsRanges.push(new vscode.FoldingRange(jsStartPos.line, jsEndPos.line));
72+
}
73+
}
74+
}
75+
}
76+
startRegex.lastIndex = endMatch.index + endMatch[0].length;
77+
}
78+
}
79+
80+
// Combine all the folding ranges
81+
return [...htmlRanges, ...jxmlAndJsRanges];
82+
}
83+
})
84+
);
7185
}
7286

7387
// This method is called when your extension is deactivated

0 commit comments

Comments
 (0)