Skip to content

Commit

Permalink
(fix) don't snip tag inside other tag (#220)
Browse files Browse the repository at this point in the history
Fixes #219
Fixes the comment case of #70
Closes #72
  • Loading branch information
dummdidumm committed May 10, 2021
1 parent 1adbc87 commit 7bfe5a9
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 11 deletions.
5 changes: 2 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { SupportLanguage, Parser, Printer } from 'prettier';
import { print } from './print';
import { ASTNode } from './print/nodes';
import { embed } from './embed';
import { snipTagContent } from './lib/snipTagContent';
import { snipScriptAndStyleTagContent } from './lib/snipTagContent';

function locStart(node: any) {
return node.start;
Expand Down Expand Up @@ -40,8 +40,7 @@ export const parsers: Record<string, Parser> = {
}
},
preprocess: (text, options) => {
text = snipTagContent('style', text);
text = snipTagContent('script', text, '{}');
text = snipScriptAndStyleTagContent(text);
text = text.trim();
// Prettier sets the preprocessed text as the originalText in case
// the Svelte formatter is called directly. In case it's called
Expand Down
56 changes: 48 additions & 8 deletions src/lib/snipTagContent.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,54 @@
export const snippedTagContentAttribute = '✂prettier:content✂';

export function snipTagContent(tagName: string, source: string, placeholder = ''): string {
const regex = new RegExp(`<!--[^]*?-->|<${tagName}([^]*?)>([^]*?)<\/${tagName}>`, 'g');
return source.replace(regex, (match, attributes, content) => {
if (match.startsWith('<!--')) {
return match;
export function snipScriptAndStyleTagContent(source: string): string {
const scriptMatchSpans = getMatchIndexes('script');
const styleMatchSpans = getMatchIndexes('style');

return snipTagContent(
snipTagContent(source, 'script', '{}', scriptMatchSpans, styleMatchSpans),
'style',
'',
styleMatchSpans,
scriptMatchSpans,
);

function getMatchIndexes(tagName: string) {
const regex = getRegexp(tagName);
const indexes: [number, number][] = [];
let match = null;
while ((match = regex.exec(source)) != null) {
indexes.push([match.index, regex.lastIndex]);
}
const encodedContent = Buffer.from(content).toString('base64');
return `<${tagName}${attributes} ${snippedTagContentAttribute}="${encodedContent}">${placeholder}</${tagName}>`;
});
return indexes;
}

function snipTagContent(
_source: string,
tagName: string,
placeholder: string,
ownSpans: [number, number][],
otherSpans: [number, number][],
) {
const regex = getRegexp(tagName);
let idx = 0;
return _source.replace(regex, (match, attributes, content) => {
if (match.startsWith('<!--') || withinOtherSpan(idx)) {
return match;
}
const encodedContent = Buffer.from(content).toString('base64');
return `<${tagName}${attributes} ${snippedTagContentAttribute}="${encodedContent}">${placeholder}</${tagName}>`;
});

function withinOtherSpan(idx: number) {
return otherSpans.some(
(otherSpan) => ownSpans[idx][0] > otherSpan[0] && ownSpans[idx][1] < otherSpan[1],
);
}
}

function getRegexp(tagName: string) {
return new RegExp(`<!--[^]*?-->|<${tagName}([^]*?)>([^]*?)<\/${tagName}>`, 'g');
}
}

export function hasSnippedContent(text: string) {
Expand Down
3 changes: 3 additions & 0 deletions test/printer/samples/style-inside-script.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<script>
const str = "<style> .foo { color: blue; } </style>";
</script>
5 changes: 5 additions & 0 deletions test/printer/samples/style-unclosed-inside-script.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<script>
//<style>
</script>

<style></style>

0 comments on commit 7bfe5a9

Please sign in to comment.