Files
rspade_system/node_modules/@jqhtml/vscode-extension/out/formatter.js
root f6fac6c4bc Fix bin/publish: copy docs.dist from project root
Fix bin/publish: use correct .env path for rspade_system
Fix bin/publish script: prevent grep exit code 1 from terminating script

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-21 02:08:33 +00:00

313 lines
13 KiB
JavaScript
Executable File

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.JqhtmlFormattingEditProvider = void 0;
const vscode = __importStar(require("vscode"));
class JqhtmlFormattingEditProvider {
constructor() {
this.indentSize = 2;
// IMPORTANT: DO NOT USE REGEX FOR PARSING IN THIS FORMATTER
// This formatter uses string manipulation and indexOf for reliability
// Regex should only be used in the syntax highlighter, not here
// Based on the RS3 formatter (reformat_html.php) logic
// Patterns that increase indent on the NEXT line
this.indentIncrease = [': %>', ': ?>', '{ %>', '{ ?>'];
// Patterns that decrease indent
this.indentDecrease = [
'<% end; %>',
'<% endif; %>',
'<% endfor; %>',
'<% endforeach; %>',
'<% endfunction; %>',
'<% } %>',
'<% }); %>',
'<% } else',
'<% else'
];
// Known self-closing HTML tags
this.selfClosingTags = [
'area', 'base', 'br', 'embed', 'hr', 'iframe',
'img', 'input', 'link', 'meta', 'param', 'source', 'track'
];
}
provideDocumentFormattingEdits(document, options) {
this.indentSize = options.tabSize || 2;
const formatted = this.formatDocument(document);
const fullRange = new vscode.Range(document.positionAt(0), document.positionAt(document.getText().length));
return [vscode.TextEdit.replace(fullRange, formatted)];
}
formatDocument(document) {
const text = document.getText();
const safeCode = [];
let working = text;
let reading = text;
// Step 1: Escape HTML comments
working = '';
while (reading.indexOf('<!--') !== -1) {
const pos = reading.indexOf('<!--');
working += reading.substring(0, pos);
reading = reading.substring(pos);
const closePos = reading.indexOf('-->');
if (closePos === -1) {
// Parse error, return original
return text;
}
safeCode.push(reading.substring(0, closePos + 3));
reading = reading.substring(closePos + 3);
working += '@@__SAFE__(' + (safeCode.length - 1) + ')';
}
working += reading;
reading = working;
// Step 2: Escape multiline <% %> blocks
working = '';
while (reading.indexOf('<%') !== -1) {
const pos = reading.indexOf('<%');
working += reading.substring(0, pos);
reading = reading.substring(pos);
const closePos = reading.indexOf('%>');
if (closePos === -1) {
// Parse error, return original
return text;
}
const nlPos = reading.indexOf('\n');
if (nlPos === -1 || nlPos > closePos) {
// Not multiline, keep it
working += reading.substring(0, closePos + 2);
reading = reading.substring(closePos + 2);
continue;
}
// It's multiline, escape it
safeCode.push(reading.substring(0, closePos + 2));
reading = reading.substring(closePos + 2);
working += '@@__SAFE__(' + (safeCode.length - 1) + ')';
}
working += reading;
// Step 3: Split into lines with indent levels
const lines = [];
const splitLines = working.split('\n');
for (const line of splitLines) {
lines.push([0, line.trim()]);
}
// Step 4: Handle JS/control flow indents (if:, endif;, etc)
let jsIndent = 0;
for (let i = 0; i < lines.length; i++) {
const trimmedLine = lines[i][1];
let plus = 0;
let minus = 0;
// Check for indent increase patterns
for (const pattern of this.indentIncrease) {
if (trimmedLine.indexOf(pattern) !== -1) {
plus++;
}
}
// Check for indent decrease patterns
for (const pattern of this.indentDecrease) {
if (trimmedLine.indexOf(pattern) !== -1) {
minus++;
}
}
// Apply indent changes
if (plus > minus) {
lines[i][0] = jsIndent;
jsIndent += plus;
jsIndent -= minus;
}
else {
jsIndent += plus;
jsIndent -= minus;
lines[i][0] = jsIndent;
}
// Special handling for else statements
if (trimmedLine.startsWith('<% else') ||
trimmedLine.startsWith('<% } else')) {
lines[i][0]--;
}
}
// Step 5: Escape remaining single-line code blocks
for (let i = 0; i < lines.length; i++) {
reading = lines[i][1];
working = '';
// Escape <% %> blocks
while (reading.indexOf('<%') !== -1) {
const pos = reading.indexOf('<%');
working += reading.substring(0, pos);
reading = reading.substring(pos);
const closePos = reading.indexOf('%>');
if (closePos === -1) {
working += reading;
reading = '';
continue;
}
safeCode.push(reading.substring(0, closePos + 2));
reading = reading.substring(closePos + 2);
working += '@@__SAFE__(' + (safeCode.length - 1) + ')';
}
working += reading;
lines[i][1] = working;
}
// Step 6: Handle HTML tag indents
let htmlIndent = 0;
for (let i = 0; i < lines.length; i++) {
const line = lines[i][1];
let thisIndent = 0;
// Count opening tags
thisIndent += this.countOccurrences(line, '<');
// Subtract self-closing tags
thisIndent -= this.countOccurrences(line, '/>');
// Subtract closing tags (count double)
thisIndent -= this.countOccurrences(line, '</') * 2;
// Handle known self-closing tags
for (const tag of this.selfClosingTags) {
const searchStr = '<' + tag;
if (line.indexOf(searchStr) !== -1) {
// Split by this tag and check each occurrence
const parts = line.split(searchStr);
for (let j = 1; j < parts.length; j++) {
// Check if it's not self-closed with />
if (parts[j].indexOf('/>') === -1 && parts[j].indexOf('>') !== -1) {
thisIndent--;
}
else if (parts[j].indexOf('/>') !== -1 &&
parts[j].indexOf('>') !== -1 &&
parts[j].indexOf('/>') > parts[j].indexOf('>')) {
// Has both > and />, but > comes first
thisIndent--;
}
}
}
}
// Special case for DOCTYPE
if (line.indexOf('<!DOCTYPE') !== -1) {
thisIndent--;
}
// Apply indent changes
if (thisIndent < 0) {
// Negative change - apply before this line
htmlIndent += thisIndent;
lines[i][0] += htmlIndent;
}
else {
// Positive/zero change - apply after this line
lines[i][0] += htmlIndent;
htmlIndent += thisIndent;
}
// Multiline self-closing tag (line has /> but no <)
if (line.indexOf('/>') !== -1 && line.indexOf('<') === -1) {
lines[i][0]++;
}
}
// Step 7: Build result with proper indentation
let result = '';
for (const [indent, line] of lines) {
const finalIndent = Math.max(0, indent);
if (line.length > 0) {
result += ' '.repeat(finalIndent * this.indentSize) + line + '\n';
}
else {
result += '\n';
}
}
// Step 8: Restore safe blocks
for (let attempt = 0; attempt < 10; attempt++) {
let hasChanges = false;
for (let i = 0; i < safeCode.length; i++) {
const placeholder = '@@__SAFE__(' + i + ')';
if (result.indexOf(placeholder) !== -1) {
result = result.replace(placeholder, safeCode[i]);
hasChanges = true;
}
}
if (!hasChanges || result.indexOf('@@__SAFE__') === -1) {
break;
}
}
// Step 9: Add blank lines around Define tag contents
result = this.addDefineTagSpacing(result);
return result.trim();
}
addDefineTagSpacing(text) {
const lines = text.split('\n');
const resultLines = [];
for (let i = 0; i < lines.length; i++) {
const currentLine = lines[i];
const trimmedCurrent = currentLine.trim();
// Check if this is an opening Define tag
if (trimmedCurrent.startsWith('<Define:') && trimmedCurrent.endsWith('>') && !trimmedCurrent.includes('</')) {
resultLines.push(currentLine);
// Check if next line exists and is not already blank
if (i + 1 < lines.length) {
const nextLine = lines[i + 1];
const trimmedNext = nextLine.trim();
// Only add blank line if:
// 1. Next line is not already blank
// 2. Next line is not the closing Define tag
if (trimmedNext.length > 0 && !trimmedNext.startsWith('</Define:')) {
resultLines.push('');
}
}
}
// Check if this is a closing Define tag
else if (trimmedCurrent.startsWith('</Define:') && trimmedCurrent.endsWith('>')) {
// Check if previous line exists and is not already blank
if (i > 0) {
const prevLine = lines[i - 1];
const trimmedPrev = prevLine.trim();
// Only add blank line if:
// 1. Previous line is not already blank
// 2. Previous line is not the opening Define tag
if (trimmedPrev.length > 0 && !trimmedPrev.startsWith('<Define:') && resultLines[resultLines.length - 1].trim().length > 0) {
resultLines.push('');
}
}
resultLines.push(currentLine);
}
else {
resultLines.push(currentLine);
}
}
return resultLines.join('\n');
}
countOccurrences(str, search) {
let count = 0;
let pos = 0;
while ((pos = str.indexOf(search, pos)) !== -1) {
count++;
pos += search.length;
}
return count;
}
}
exports.JqhtmlFormattingEditProvider = JqhtmlFormattingEditProvider;
//# sourceMappingURL=formatter.js.map