Skip to content

Commit

Permalink
fix(tsx): Collect multibytes characters in skipped script and styles (#…
Browse files Browse the repository at this point in the history
…1033)

* fix(tsx): Collect multibytes characters in skipped script and styles

* chore: changeset
  • Loading branch information
Princesseuh authored Jul 31, 2024
1 parent 0ebfc96 commit af471f5
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 16 deletions.
5 changes: 5 additions & 0 deletions .changeset/two-ghosts-fly.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@astrojs/compiler": patch
---

Fixes positions for extracted tags being wrong when using IncludeStyles and IncludeScripts set to false
19 changes: 12 additions & 7 deletions internal/printer/print-to-tsx.go
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,8 @@ declare const Astro: Readonly<import('astro').AstroGlobal<%s, typeof %s`, propsI
p.printTextWithSourcemap(n.Data, n.Loc[0])
p.addNilSourceMapping()
p.print("}}\n")
} else {
p.collectMultiByteCharacters(n.Data)
}
p.addSourceMapping(loc.Loc{Start: n.Loc[0].Start + len(n.Data)})
} else if textType == StyleText || textType == JsonScriptText || textType == RawText || textType == UnknownScriptText {
Expand All @@ -465,6 +467,8 @@ declare const Astro: Readonly<import('astro').AstroGlobal<%s, typeof %s`, propsI
p.printTextWithSourcemap(escapeText(n.Data), n.Loc[0])
p.addNilSourceMapping()
p.print("`}")
} else {
p.collectMultiByteCharacters(n.Data)
}
p.addSourceMapping(loc.Loc{Start: n.Loc[0].Start + len(n.Data)})
} else {
Expand Down Expand Up @@ -768,6 +772,14 @@ declare const Astro: Readonly<import('astro').AstroGlobal<%s, typeof %s`, propsI
}
}

if len(n.Loc) > 1 {
endLoc = n.Loc[1].Start - 2
} else if n.LastChild != nil && n.LastChild.Expression {
if len(n.LastChild.Loc) > 1 {
endLoc = n.LastChild.Loc[1].Start + 1
}
}

if n.FirstChild != nil && (n.DataAtom == atom.Script || n.DataAtom == atom.Style) {
if n.DataAtom == atom.Script {
p.addTSXScript(startTagEnd, endLoc-p.bytesToSkip, n.FirstChild.Data, getScriptTypeFromAttrs(n.Attr))
Expand All @@ -783,13 +795,6 @@ declare const Astro: Readonly<import('astro').AstroGlobal<%s, typeof %s`, propsI
return
}

if len(n.Loc) > 1 {
endLoc = n.Loc[1].Start - 2
} else if n.LastChild != nil && n.LastChild.Expression {
if len(n.LastChild.Loc) > 1 {
endLoc = n.LastChild.Loc[1].Start + 1
}
}
p.addSourceMapping(loc.Loc{Start: endLoc})
p.print("</")
if !isSelfClosing {
Expand Down
10 changes: 10 additions & 0 deletions internal/printer/printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,16 @@ func (p *printer) printEscapedJSXTextWithSourcemap(text string, l loc.Loc) {
}
}

// We normally collect multi-byte characters while printing, but this method can be used for skipped text
func (p *printer) collectMultiByteCharacters(text string) {
for pos := range text {
_, nextCharByteSize := utf8.DecodeRuneInString(text[pos:])
if nextCharByteSize > 1 {
p.bytesToSkip += nextCharByteSize - 1
}
}
}

func (p *printer) printInternalImports(importSpecifier string, opts *RenderOptions) {
if p.hasInternalImports {
return
Expand Down
76 changes: 67 additions & 9 deletions packages/compiler/test/tsx/meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ test('extract scripts', async () => {
{
position: {
start: 22,
end: 87,
end: 54,
},
type: 'module',
content: 'console.log({ test: `literal` })',
Expand All @@ -57,7 +57,7 @@ test('extract scripts', async () => {
{
position: {
start: 93,
end: 158,
end: 125,
},
type: 'inline',
content: 'console.log({ test: `literal` })',
Expand All @@ -66,7 +66,7 @@ test('extract scripts', async () => {
{
position: {
start: 169,
end: 188,
end: 178,
},
type: 'json',
content: '{"a":"b"}',
Expand All @@ -75,7 +75,7 @@ test('extract scripts', async () => {
{
position: {
start: 205,
end: 246,
end: 225,
},
type: 'inline',
content: 'console.log("hello")',
Expand All @@ -93,7 +93,7 @@ test('extract scripts', async () => {
{
position: {
start: 281,
end: 346,
end: 313,
},
type: 'processed-module',
content: 'console.log({ test: `literal` })',
Expand All @@ -102,7 +102,7 @@ test('extract scripts', async () => {
{
position: {
start: 337,
end: 358,
end: 347,
},
type: 'raw',
content: 'something;',
Expand All @@ -123,7 +123,7 @@ test('extract styles', async () => {
{
position: {
start: 7,
end: 48,
end: 27,
},
type: 'tag',
content: 'body { color: red; }',
Expand All @@ -141,7 +141,7 @@ test('extract styles', async () => {
{
position: {
start: 86,
end: 127,
end: 106,
},
type: 'tag',
content: 'body { color: red; }',
Expand All @@ -150,7 +150,7 @@ test('extract styles', async () => {
{
position: {
start: 133,
end: 174,
end: 153,
},
type: 'tag',
content: 'body { color: red; }',
Expand All @@ -161,4 +161,62 @@ test('extract styles', async () => {
);
});

test('extract scripts and styles with multibyte characters', async () => {
const scripts = "<script>console.log('🦄')</script><script>console.log('Hey');</script>";
const styles =
"<style>body { background: url('🦄.png'); }</style><style>body { background: url('Hey');";

const input = `${scripts}${styles}`;
const { metaRanges } = await convertToTSX(input, { sourcemap: 'external' });

assert.equal(
metaRanges.scripts,
[
{
position: {
start: 8,
end: 24,
},
type: 'processed-module',
content: "console.log('🦄')",
lang: '',
},
{
position: {
start: 41,
end: 60,
},
type: 'processed-module',
content: "console.log('Hey');",
lang: '',
},
],
'expected metaRanges.scripts to match snapshot'
);
assert.equal(
metaRanges.styles,
[
{
position: {
start: 76,
end: 110,
},
type: 'tag',
content: "body { background: url('🦄.png'); }",
lang: 'css',
},
{
position: {
start: 125,
end: 186,
},
type: 'tag',
content: "body { background: url('Hey');",
lang: 'css',
},
],
'expected metaRanges.styles to match snapshot'
);
});

test.run();

0 comments on commit af471f5

Please sign in to comment.