Skip to content

Commit

Permalink
support nested script and style tags
Browse files Browse the repository at this point in the history
fixes #30
  • Loading branch information
jamesbirtles committed May 26, 2019
1 parent f0d57a6 commit 47becfa
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 21 deletions.
19 changes: 13 additions & 6 deletions src/embed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,14 @@ export function embed(

switch (node.type) {
case 'Script':
return embedTag(path, print, textToDoc, node, 'typescript');
return embedTag('script', path, print, textToDoc, node);
case 'Style':
return embedTag(path, print, textToDoc, node, 'css');
return embedTag('style', path, print, textToDoc, node);
case 'Element': {
if (node.name === 'script' || node.name === 'style') {
return embedTag(node.name, path, print, textToDoc, node, true)
}
}
}

return null;
Expand Down Expand Up @@ -81,12 +86,14 @@ function nukeLastLine(doc: Doc): Doc {
}

function embedTag(
tag: string,
path: FastPath,
print: PrintFn,
textToDoc: (text: string, options: object) => Doc,
node: Node & { attributes: Node[] },
parser: string,
inline: boolean,
) {
const parser = tag === 'script' ? 'typescript' : 'css';
const contentAttribute = (node.attributes as AttributeNode[]).find(
n => n.name === '✂prettier:content✂',
);
Expand All @@ -104,15 +111,15 @@ function embedTag(
return group(
concat([
'<',
node.type.toLowerCase(),
tag,
indent(group(concat(path.map(childPath => childPath.call(print), 'attributes')))),
'>',
indent(concat([hardline, nukeLastLine(textToDoc(content, { parser }))])),
hardline,
'</',
node.type.toLowerCase(),
tag,
'>',
hardline,
inline ? '' : hardline,
]),
);
}
8 changes: 3 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,9 @@ export const parsers: Record<string, Parser> = {
}
},
preprocess: text => {
let styles: string[] = [];
let scripts: string[] = [];
[text, styles] = snipTagContent('style', text);
[text, scripts] = snipTagContent('script', text, '{}');
return [text.trim(), ...styles, ...scripts].join('');
text = snipTagContent('style', text);
text = snipTagContent('script', text, '{}');
return text.trim();
},
locStart,
locEnd,
Expand Down
26 changes: 18 additions & 8 deletions src/lib/snipTagContent.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
export function snipTagContent(tagName: string, source: string, placeholder = ''): [string, string[]] {
const regex = new RegExp(`<${tagName}([^]*?)>([^]*?)<\/${tagName}>`, 'gi');
const tags: string[] = [];
const text = source.replace(regex, (_, attributes, content) => {
const encodedContext = Buffer.from(content).toString('base64');
tags.push(`<${tagName}${attributes} ✂prettier:content✂="${encodedContext}">${placeholder}</${tagName}>`);
return '';
export function snipTagContent(tagName: string, source: string, placeholder = ''): string {
const regex = new RegExp(`[\s\n]*<${tagName}([^]*?)>([^]*?)<\/${tagName}>[\s\n]*`, 'gi');
return source.replace(regex, (_, attributes, content) => {
const encodedContent = Buffer.from(content).toString('base64');
return `<${tagName}${attributes} ✂prettier:content✂="${encodedContent}">${placeholder}</${tagName}>`;
});
return [text, tags];
}

export function hasSnippedContent(text: string) {
return text.includes('✂prettier:content✂');
}

export function unsnipContent(text: string): string {
const regex = /(<\w+.*?)\s*✂prettier:content✂="(.*?)">.*?(?=<\/)/gi
return text.replace(regex, (_, start, encodedContent) => {
const content = Buffer.from(encodedContent, 'base64').toString('utf8');
return `${start}>${content}`;
});
return text;
}
11 changes: 9 additions & 2 deletions src/print/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { isASTNode } from './helpers';
import { extractAttributes } from '../lib/extractAttributes';
import { getText } from '../lib/getText';
import { parseSortOrder, SortOrderPart } from '../options';
import { hasSnippedContent, unsnipContent } from '../lib/snipTagContent';
const {
concat,
join,
Expand Down Expand Up @@ -333,8 +334,14 @@ export function print(path: FastPath, options: ParserOptions, print: PrintFn): D
]);
case 'Ref':
return concat([line, 'ref:', node.name]);
case 'Comment':
return group(concat(['<!--', node.data, '-->']));
case 'Comment': {
let text = node.data;
if (hasSnippedContent(text)) {
text = unsnipContent(text);
}

return group(concat(['<!--', text, '-->']));
}
case 'Transition':
const kind = node.intro && node.outro ? 'transition' : node.intro ? 'in' : 'out';
return concat([
Expand Down
1 change: 1 addition & 0 deletions test/printer/samples/script-inside-comment.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!-- <script>alert(1)</script> -->
5 changes: 5 additions & 0 deletions test/printer/samples/script-inside-element.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div>
<script>
alert(1);
</script>
</div>
1 change: 1 addition & 0 deletions test/printer/samples/style-inside-comment.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!-- <style>div { color: red }</style> -->
7 changes: 7 additions & 0 deletions test/printer/samples/style-inside-element.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<div>
<style>
div {
color: red;
}
</style>
</div>

0 comments on commit 47becfa

Please sign in to comment.