Skip to content

Commit

Permalink
Maintain whitespace before tag close (#822)
Browse files Browse the repository at this point in the history
* fix(#801): TSX preserves trailing spaces before tag close

* chore: add changeset

* feat: improve mapping for many spaces
  • Loading branch information
natemoo-re authored Jul 10, 2023
1 parent 2e805bd commit 3d69f4e
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .changeset/seven-moons-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/compiler': patch
---

[TSX] maintain trailing whitespace before an element is closed, fixing TypeScript completion in some cases
20 changes: 13 additions & 7 deletions internal/printer/print-to-tsx.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ declare const Astro: Readonly<import('astro').AstroGlobal<%s>>`, props.Ident)
p.print("<")
p.addSourceMapping(loc.Loc{Start: n.Loc[0].Start})
p.print(n.Data)
p.addSourceMapping(loc.Loc{Start: n.Loc[0].Start + len(n.Data)})

invalidTSXAttributes := make([]Attribute, 0)
endLoc := n.Loc[0].Start + len(n.Data)
Expand Down Expand Up @@ -375,15 +376,13 @@ declare const Astro: Readonly<import('astro').AstroGlobal<%s>>`, props.Ident)
p.print(`:`)
p.addSourceMapping(loc.Loc{Start: eqStart + 1})
p.print(`"` + encodeDoubleQuote(a.Val) + `"`)
endLoc = eqStart + 1 + len(a.Val) + 2
case astro.EmptyAttribute:
p.print(a.Key)
p.print(`"`)
p.addNilSourceMapping()
p.print(`:`)
p.addSourceMapping(a.KeyLoc)
p.print(`true`)
endLoc = a.KeyLoc.Start + len(a.Key)
case astro.ExpressionAttribute:
p.print(a.Key)
p.print(`"`)
Expand All @@ -394,7 +393,6 @@ declare const Astro: Readonly<import('astro').AstroGlobal<%s>>`, props.Ident)
p.printTextWithSourcemap(a.Val, loc.Loc{Start: eqStart + 2})
p.addSourceMapping(loc.Loc{Start: eqStart + 2 + len(a.Val)})
p.print(`)`)
endLoc = eqStart + len(a.Val) + 2
case astro.SpreadAttribute:
// noop
case astro.ShorthandAttribute:
Expand All @@ -404,14 +402,12 @@ declare const Astro: Readonly<import('astro').AstroGlobal<%s>>`, props.Ident)
}
p.addSourceMapping(a.KeyLoc)
p.print(a.Key)
endLoc = a.KeyLoc.Start + len(a.Key)
case astro.TemplateLiteralAttribute:
p.addSourceMapping(a.KeyLoc)
p.print(a.Key)
p.print(`":`)
p.addSourceMapping(a.ValLoc)
p.print(fmt.Sprintf("`%s`", a.Val))
endLoc = a.ValLoc.Start + len(a.Val) + 2
}
if i == len(invalidTSXAttributes)-1 {
p.addNilSourceMapping()
Expand All @@ -425,7 +421,9 @@ declare const Astro: Readonly<import('astro').AstroGlobal<%s>>`, props.Ident)
endLoc = 0
}
isSelfClosing := false
hasLeadingSpace := false
tmpLoc := endLoc
leadingSpaceLoc := endLoc
if len(p.sourcetext) > tmpLoc {
for i := 0; i < len(p.sourcetext[tmpLoc:]); i++ {
c := p.sourcetext[endLoc : endLoc+1][0]
Expand All @@ -436,6 +434,10 @@ declare const Astro: Readonly<import('astro').AstroGlobal<%s>>`, props.Ident)
p.addSourceMapping(loc.Loc{Start: endLoc})
endLoc++
break
} else if unicode.IsSpace(rune(c)) {
hasLeadingSpace = true
leadingSpaceLoc = endLoc
endLoc++
} else {
endLoc++
}
Expand All @@ -444,13 +446,17 @@ declare const Astro: Readonly<import('astro').AstroGlobal<%s>>`, props.Ident)
endLoc++
}

if hasLeadingSpace {
p.addSourceMapping(loc.Loc{Start: leadingSpaceLoc})
p.print(" ")
p.addSourceMapping(loc.Loc{Start: leadingSpaceLoc + 1})
}

if voidElements[n.Data] && n.FirstChild == nil {
p.print("/>")
return
}
if isSelfClosing && n.FirstChild == nil {
p.addSourceMapping(loc.Loc{Start: endLoc - 1})
p.print(" ")
p.addSourceMapping(loc.Loc{Start: endLoc})
p.print("/>")
return
Expand Down
15 changes: 15 additions & 0 deletions packages/compiler/test/tsx-sourcemaps/tags.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { test } from 'uvu';
import * as assert from 'uvu/assert';
import { convertToTSX } from '@astrojs/compiler';
import { generatedPositionFor, TraceMap } from '@jridgewell/trace-mapping';
import { testTSXSourcemap } from '../utils';

test('tag close', async () => {
Expand All @@ -14,4 +16,17 @@ test('tag close', async () => {
});
});

test('tag with spaces', async () => {
const input = `<Button ></Button>`;
const { map } = await convertToTSX(input, { sourcemap: 'both', filename: 'index.astro' });
const tracer = new TraceMap(map);

const generated = generatedPositionFor(tracer, { source: 'index.astro', line: 1, column: 14 });

assert.equal(generated, {
line: 2,
column: 9,
});
});

test.run();
30 changes: 30 additions & 0 deletions packages/compiler/test/tsx/basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,4 +214,34 @@ export default function __AstroComponent_(_props: Record<string, any>): any {}\n
assert.snapshot(code, output, `expected code to match snapshot`);
});

test('preserves spaces in tag', async () => {
const input = '<Button ></Button>';
const output = `<Fragment>
<Button ></Button>
</Fragment>
export default function __AstroComponent_(_props: Record<string, any>): any {}\n`;
const { code } = await convertToTSX(input, { sourcemap: 'external' });
assert.snapshot(code, output, `expected code to match snapshot`);
});

test('preserves spaces after attributes in tag', async () => {
const input = '<Button a="b" ></Button>';
const output = `<Fragment>
<Button a="b" ></Button>
</Fragment>
export default function __AstroComponent_(_props: Record<string, any>): any {}\n`;
const { code } = await convertToTSX(input, { sourcemap: 'external' });
assert.snapshot(code, output, `expected code to match snapshot`);
});

test('preserves spaces in tag', async () => {
const input = '<Button >';
const output = `<Fragment>
<Button ></Button>
</Fragment>
export default function __AstroComponent_(_props: Record<string, any>): any {}\n`;
const { code } = await convertToTSX(input, { sourcemap: 'external' });
assert.snapshot(code, output, `expected code to match snapshot`);
});

test.run();

0 comments on commit 3d69f4e

Please sign in to comment.