Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/beautify/beautify-css.js
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,7 @@ module.exports.InputScanner = InputScanner;
function Directives(start_block_pattern, end_block_pattern) {
start_block_pattern = typeof start_block_pattern === 'string' ? start_block_pattern : start_block_pattern.source;
end_block_pattern = typeof end_block_pattern === 'string' ? end_block_pattern : end_block_pattern.source;
this.__directives_block_pattern = new RegExp(start_block_pattern + / beautify( \w+[:]\w+)+ /.source + end_block_pattern, 'g');
this.__directives_block_pattern = new RegExp(start_block_pattern + /\s*beautify(\s+\w+[:]\w+)+\s*/.source + end_block_pattern, 'g');
this.__directive_pattern = / (\w+)[:](\w+)/g;

this.__directives_end_ignore_pattern = new RegExp(start_block_pattern + /\sbeautify\signore:end\s/.source + end_block_pattern, 'g');
Expand Down
2 changes: 1 addition & 1 deletion src/beautify/beautify-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -1445,7 +1445,7 @@ module.exports.Pattern = Pattern;
function Directives(start_block_pattern, end_block_pattern) {
start_block_pattern = typeof start_block_pattern === 'string' ? start_block_pattern : start_block_pattern.source;
end_block_pattern = typeof end_block_pattern === 'string' ? end_block_pattern : end_block_pattern.source;
this.__directives_block_pattern = new RegExp(start_block_pattern + / beautify( \w+[:]\w+)+ /.source + end_block_pattern, 'g');
this.__directives_block_pattern = new RegExp(start_block_pattern + /\s*beautify(\s+\w+[:]\w+)+\s*/.source + end_block_pattern, 'g');
this.__directive_pattern = / (\w+)[:](\w+)/g;

this.__directives_end_ignore_pattern = new RegExp(start_block_pattern + /\sbeautify\signore:end\s/.source + end_block_pattern, 'g');
Expand Down
47 changes: 46 additions & 1 deletion src/services/htmlFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ export function format(document: TextDocument, range: Range | undefined, options
const tabSize = options.tabSize || 4;
if (range) {
let startOffset = document.offsetAt(range.start);
let endOffset = document.offsetAt(range.end);

// If the range falls within a <!-- beautify ignore:start/end --> block,
// expand the range to include the ignore boundaries so js-beautify can
// recognise them and skip formatting the ignored content.
const ignoreExpanded = expandRangeToIgnoreBlock(value, startOffset, endOffset);
if (ignoreExpanded) {
startOffset = ignoreExpanded.start;
endOffset = ignoreExpanded.end;
}

// include all leading whitespace iff at the beginning of the line
let extendedStart = startOffset;
Expand All @@ -30,7 +40,6 @@ export function format(document: TextDocument, range: Range | undefined, options
}

// include all following whitespace until the end of the line
let endOffset = document.offsetAt(range.end);
let extendedEnd = endOffset;
while (extendedEnd < value.length && isWhitespace(value, extendedEnd)) {
extendedEnd++;
Expand Down Expand Up @@ -174,3 +183,39 @@ function isEOL(text: string, offset: number) {
function isWhitespace(text: string, offset: number) {
return ' \t'.indexOf(text.charAt(offset)) !== -1;
}

const ignoreStartPattern = /<!--\s*beautify\s+ignore:start\s*-->/g;
const ignoreEndPattern = /<!--\s*beautify\s+ignore:end\s*-->/g;

function expandRangeToIgnoreBlock(text: string, startOffset: number, endOffset: number): { start: number; end: number } | null {
// Find all ignore:start markers before (or at) the range start
ignoreStartPattern.lastIndex = 0;
let lastIgnoreStart: RegExpExecArray | null = null;
let match: RegExpExecArray | null;
while ((match = ignoreStartPattern.exec(text)) !== null) {
if (match.index > startOffset) {
break;
}
lastIgnoreStart = match;
}

if (!lastIgnoreStart) {
return null;
}

// Find the matching ignore:end after the ignore:start
ignoreEndPattern.lastIndex = lastIgnoreStart.index + lastIgnoreStart[0].length;
const ignoreEnd = ignoreEndPattern.exec(text);
if (!ignoreEnd) {
return null;
}

const blockEnd = ignoreEnd.index + ignoreEnd[0].length;

// Check that the range falls within this ignore block
if (startOffset >= lastIgnoreStart.index && endOffset <= blockEnd) {
return { start: lastIgnoreStart.index, end: blockEnd };
}

return null;
}
92 changes: 92 additions & 0 deletions src/test/formatter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,98 @@ suite('HTML Formatter', () => {
format(content, expected);
});

test('beautify ignore:start/end - full document', () => {
var content = [
'<html>',
'<body>',
'<!-- beautify ignore:start -->',
'<div class = "x">',
' <p>text</p>',
'</div>',
'<!-- beautify ignore:end -->',
'<div class = "y">',
'</div>',
'</body>',
'</html>'
].join('\n');

var expected = [
'<html>',
'',
'<body>',
' <!-- beautify ignore:start -->',
'<div class = "x">',
' <p>text</p>',
'</div>',
'<!-- beautify ignore:end -->',
' <div class="y">',
' </div>',
'</body>',
'',
'</html>',
].join('\n');

format(content, expected);
});

test('beautify ignore:start/end - range format inside ignore block', () => {
var content = [
'<!-- beautify ignore:start -->',
'|<div class = "x">',
' <p>text</p>',
'</div>|',
'<!-- beautify ignore:end -->'
].join('\n');

var expected = [
'<!-- beautify ignore:start -->',
'<div class = "x">',
' <p>text</p>',
'</div>',
'<!-- beautify ignore:end -->'
].join('\n');

format(content, expected);
});

test('beautify ignore - extra whitespace in comment', () => {
var content = [
'<!-- beautify ignore:start -->',
'<div class = "x">',
'</div>',
'<!-- beautify ignore:end -->'
].join('\n');

var expected = [
'<!-- beautify ignore:start -->',
'<div class = "x">',
'</div>',
'<!-- beautify ignore:end -->'
].join('\n');

format(content, expected);
});

test('beautify ignore - go template syntax preserved', () => {
var content = [
'<!-- beautify ignore:start -->',
'<div {{if .Active}}class="active"{{end}}>',
' {{template "scripts/file-size".}}',
'</div>',
'<!-- beautify ignore:end -->'
].join('\n');

var expected = [
'<!-- beautify ignore:start -->',
'<div {{if .Active}}class="active"{{end}}>',
' {{template "scripts/file-size".}}',
'</div>',
'<!-- beautify ignore:end -->'
].join('\n');

format(content, expected);
});

});

suite('HTML Formatter - Embedded CSS', () => {
Expand Down