Skip to content

Commit 3ea98f0

Browse files
authored
(fix) adjust snipTagContent (#268)
Correctly deal with changing spans Fixes #261
1 parent 4e73ff6 commit 3ea98f0

File tree

3 files changed

+54
-14
lines changed

3 files changed

+54
-14
lines changed

src/lib/snipTagContent.ts

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
export const snippedTagContentAttribute = '✂prettier:content✂';
22

33
export function snipScriptAndStyleTagContent(source: string): string {
4-
const scriptMatchSpans = getMatchIndexes('script');
5-
const styleMatchSpans = getMatchIndexes('style');
4+
let scriptMatchSpans = getMatchIndexes('script');
5+
let styleMatchSpans = getMatchIndexes('style');
66

77
return snipTagContent(
88
snipTagContent(source, 'script', '{}', styleMatchSpans),
@@ -29,32 +29,54 @@ export function snipScriptAndStyleTagContent(source: string): string {
2929
placeholder: string,
3030
otherSpans: [number, number][],
3131
) {
32-
// Replace valid matches
3332
const regex = getRegexp(tagName);
33+
let newScriptMatchSpans = scriptMatchSpans;
34+
let newStyleMatchSpans = styleMatchSpans;
35+
// Replace valid matches
3436
const newSource = _source.replace(regex, (match, attributes, content, index) => {
3537
if (match.startsWith('<!--') || withinOtherSpan(index)) {
3638
return match;
3739
}
3840
const encodedContent = Buffer.from(content).toString('base64');
39-
return `<${tagName}${attributes} ${snippedTagContentAttribute}="${encodedContent}">${placeholder}</${tagName}>`;
41+
const newContent = `<${tagName}${attributes} ${snippedTagContentAttribute}="${encodedContent}">${placeholder}</${tagName}>`;
42+
43+
// Adjust the spans because the source now has a different content length
44+
const lengthDiff = match.length - newContent.length;
45+
newScriptMatchSpans = adjustSpans(scriptMatchSpans, newScriptMatchSpans);
46+
newStyleMatchSpans = adjustSpans(styleMatchSpans, newStyleMatchSpans);
47+
function adjustSpans(
48+
oldSpans: [number, number][],
49+
newSpans: [number, number][],
50+
): [number, number][] {
51+
return oldSpans.map((oldSpan, idx) => {
52+
const newSpan = newSpans[idx];
53+
// Do the check using the old spans because the replace function works
54+
// on the old spans. Replace oldSpans with newSpans afterwards.
55+
if (oldSpan[0] > index) {
56+
// span is after the match -> adjust start and end
57+
return [newSpan[0] - lengthDiff, newSpan[1] - lengthDiff];
58+
} else if (oldSpan[0] === index) {
59+
// span is the match -> adjust end only
60+
return [newSpan[0], newSpan[1] - lengthDiff];
61+
} else {
62+
// span is before the match -> nothing to adjust
63+
return newSpan;
64+
}
65+
});
66+
}
67+
68+
return newContent;
4069
});
4170

42-
// Adjust the spans because the source now has a different content length
43-
adjustSpans(scriptMatchSpans);
44-
adjustSpans(styleMatchSpans);
71+
// Now that the replacement function ran, we can adjust the spans for the next run
72+
scriptMatchSpans = newScriptMatchSpans;
73+
styleMatchSpans = newStyleMatchSpans;
4574

4675
return newSource;
4776

4877
function withinOtherSpan(idx: number) {
4978
return otherSpans.some((otherSpan) => idx > otherSpan[0] && idx < otherSpan[1]);
5079
}
51-
function adjustSpans(spans: [number, number][]) {
52-
const lengthDiff = _source.length - newSource.length;
53-
spans.forEach((span) => {
54-
span[0] -= lengthDiff;
55-
span[1] -= lengthDiff;
56-
});
57-
}
5880
}
5981

6082
function getRegexp(tagName: string) {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script>
2+
import MyFunction from "./this_is_a_long_import_path/this_is_a_long_import_name.svelte";
3+
4+
// a long, and useless comment
5+
</script>
6+
7+
<style>
8+
iframe {
9+
width: 100%;
10+
}
11+
</style>
12+
13+
<svelte:head>
14+
<script></script>
15+
</svelte:head>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"svelteSortOrder": "options-scripts-styles-markup"
3+
}

0 commit comments

Comments
 (0)