From bffb92ae183c758cf4fe4bb56c80793279303edf Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Thu, 6 Jul 2023 18:34:42 -0400 Subject: [PATCH 1/3] fix(#796): add raw attribute values to AST --- internal/printer/print-to-json.go | 24 +++++++++++++++++++++-- packages/compiler/src/browser/utils.ts | 2 +- packages/compiler/src/node/utils.ts | 2 +- packages/compiler/src/shared/ast.ts | 1 + packages/compiler/test/parse/serialize.ts | 7 +++++++ 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/internal/printer/print-to-json.go b/internal/printer/print-to-json.go index 37ed9c83f..f9308e555 100644 --- a/internal/printer/print-to-json.go +++ b/internal/printer/print-to-json.go @@ -34,6 +34,7 @@ type ASTNode struct { // Attributes only Kind string `json:"kind,omitempty"` + Raw string `json:"raw,omitempty"` } func escapeForJSON(value string) string { @@ -65,6 +66,9 @@ func (n ASTNode) String() string { if n.Value != "" || n.Type == "attribute" { str += fmt.Sprintf(`,"value":"%s"`, escapeForJSON(n.Value)) } + if n.Raw != "" || n.Type == "attribute" { + str += fmt.Sprintf(`,"raw":"%s"`, escapeForJSON(n.Raw)) + } if len(n.Attributes) > 0 { str += `,"attributes":[` for i, attr := range n.Attributes { @@ -103,7 +107,8 @@ func (n ASTNode) String() string { func PrintToJSON(sourcetext string, n *Node, opts t.ParseOptions) PrintResult { p := &printer{ - builder: sourcemap.MakeChunkBuilder(nil, sourcemap.GenerateLineOffsetTables(sourcetext, len(strings.Split(sourcetext, "\n")))), + builder: sourcemap.MakeChunkBuilder(nil, sourcemap.GenerateLineOffsetTables(sourcetext, len(strings.Split(sourcetext, "\n")))), + sourcetext: sourcetext, } root := ASTNode{} renderNode(p, &root, n, opts) @@ -223,12 +228,27 @@ func renderNode(p *printer, parent *ASTNode, n *Node, opts t.ParseOptions) { if attr.Namespace != "" { name = fmt.Sprintf("%s:%s", attr.Namespace, attr.Key) } + position := attrPositionAt(p, &attr, opts) + raw := "" + if attr.Type == QuotedAttribute { + start := attr.ValLoc.Start - 1 + end := attr.ValLoc.Start + len(attr.Val) + + char := p.sourcetext[start] + if char == '=' { + start += 1 + } else { + end += 1 + } + raw = strings.TrimSpace(p.sourcetext[start:end]) + } attrNode := ASTNode{ Type: "attribute", Kind: attr.Type.String(), - Position: attrPositionAt(p, &attr, opts), + Position: position, Name: name, Value: attr.Val, + Raw: raw, } node.Attributes = append(node.Attributes, attrNode) } diff --git a/packages/compiler/src/browser/utils.ts b/packages/compiler/src/browser/utils.ts index 45c88df99..a3a149a8f 100644 --- a/packages/compiler/src/browser/utils.ts +++ b/packages/compiler/src/browser/utils.ts @@ -82,7 +82,7 @@ function serializeAttributes(node: TagLikeNode): string { break; } case 'quoted': { - output += `${attr.name}="${attr.value}"`; + output += `${attr.name}=${attr.raw}`; break; } case 'template-literal': { diff --git a/packages/compiler/src/node/utils.ts b/packages/compiler/src/node/utils.ts index 1dda804bc..b80308861 100644 --- a/packages/compiler/src/node/utils.ts +++ b/packages/compiler/src/node/utils.ts @@ -82,7 +82,7 @@ function serializeAttributes(node: TagLikeNode): string { break; } case 'quoted': { - output += `${attr.name}="${attr.value}"`; + output += `${attr.name}=${attr.raw}`; break; } case 'template-literal': { diff --git a/packages/compiler/src/shared/ast.ts b/packages/compiler/src/shared/ast.ts index c80baff99..1f7e6d19a 100644 --- a/packages/compiler/src/shared/ast.ts +++ b/packages/compiler/src/shared/ast.ts @@ -38,6 +38,7 @@ export interface AttributeNode extends BaseNode { kind: 'quoted' | 'empty' | 'expression' | 'spread' | 'shorthand' | 'template-literal'; name: string; value: string; + raw?: string; } export interface TextNode extends ValueNode { diff --git a/packages/compiler/test/parse/serialize.ts b/packages/compiler/test/parse/serialize.ts index 2df140b70..2ab2f1afa 100644 --- a/packages/compiler/test/parse/serialize.ts +++ b/packages/compiler/test/parse/serialize.ts @@ -50,4 +50,11 @@ test('self-close elements', async () => { assert.equal(selfClosedOutput, input, `Expected serialized output to equal ${input}`); }); +test('raw attributes', async () => { + const input = `
`; + const { ast } = await parse(input); + const output = serialize(ast); + assert.equal(output, input, `Expected serialized output to equal ${input}`); +}); + test.run(); From d42308656e5af7fe5f59893bf21c4bfa149327be Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Thu, 6 Jul 2023 18:35:01 -0400 Subject: [PATCH 2/3] chore: add changeset --- .changeset/orange-kangaroos-dress.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/orange-kangaroos-dress.md diff --git a/.changeset/orange-kangaroos-dress.md b/.changeset/orange-kangaroos-dress.md new file mode 100644 index 000000000..3b7841e6e --- /dev/null +++ b/.changeset/orange-kangaroos-dress.md @@ -0,0 +1,5 @@ +--- +'@astrojs/compiler': patch +--- + +[AST] add raw attribute values to AST From 8a539cc62897d9ec48bf01d3b294174474a37b3a Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Fri, 7 Jul 2023 09:01:36 -0400 Subject: [PATCH 3/3] chore: update tests --- internal/printer/printer_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/printer/printer_test.go b/internal/printer/printer_test.go index fda603b56..f5f57243a 100644 --- a/internal/printer/printer_test.go +++ b/internal/printer/printer_test.go @@ -3014,7 +3014,7 @@ const c = '\'' { name: "Preserve namespaces", source: ``, - want: []ASTNode{{Type: "element", Name: "svg", Attributes: []ASTNode{{Type: "attribute", Kind: "quoted", Name: "xmlns", Value: "http://www.w3.org/2000/svg"}, {Type: "attribute", Kind: "quoted", Name: "xmlns:xlink", Value: "http://www.w3.org/1999/xlink"}}, Children: []ASTNode{{Type: "element", Name: "rect", Attributes: []ASTNode{{Type: "attribute", Kind: "quoted", Name: "xlink:href", Value: "#id"}}}}}}, + want: []ASTNode{{Type: "element", Name: "svg", Attributes: []ASTNode{{Type: "attribute", Kind: "quoted", Name: "xmlns", Value: "http://www.w3.org/2000/svg", Raw: `"http://www.w3.org/2000/svg"`}, {Type: "attribute", Kind: "quoted", Name: "xmlns:xlink", Value: "http://www.w3.org/1999/xlink", Raw: `"http://www.w3.org/1999/xlink"`}}, Children: []ASTNode{{Type: "element", Name: "rect", Attributes: []ASTNode{{Type: "attribute", Kind: "quoted", Name: "xlink:href", Value: "#id", Raw: `"#id"`}}}}}}, }, { name: "style before html",