Skip to content

Conversation

@natemoo-re
Copy link
Member

@natemoo-re natemoo-re commented Jan 31, 2022

Changes

  • Adds a function named parse which can emit an AST
  • Adds @astrojs/compiler/utils with a walk function and is type guards.
  • Adds fully typed AST Nodes
    Example
import { parse } from '@astrojs/compiler';
import { walk, is } from '@astrojs/compiler/utils';

const result = await parse(source, {
  position: false, // defaults to `true`
});

walk(result.ast, (node) => {
  // `tag` nodes are `element` | `custom-element` | `component`
  if (is.tag(node)) {
    console.log(node.name);
  }
})

Testing

  • Minimal Go test scaffolded out
  • Simple JS test added

Docs

README has been updated. Docs should probably remain internal for a while until this is stabilized.

@changeset-bot
Copy link

changeset-bot bot commented Jan 31, 2022

🦋 Changeset detected

Latest commit: ecdc90e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@astrojs/compiler Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Contributor

@jonathantneal jonathantneal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can’t possibly fathom it all without a walk thru, but this looks phenomenal.

Co-authored-by: Jonathan Neal <jonathantneal@hotmail.com>
Copy link
Member Author

@natemoo-re natemoo-re left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving some comments for reference

doc.AppendChild(n)
}

result := printer.PrintToJSON(source, doc, parseOptions)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very similar to the Transform function other than the way we print. Instead of generating a JS module from our AST, we have a new printer that generates stringified JSON.

Comment on lines +55 to +106
func (n ASTNode) String() string {
str := fmt.Sprintf(`{"type":"%s"`, n.Type)
if n.Kind != "" {
str += fmt.Sprintf(`,"kind":"%s"`, n.Kind)
}
if n.Name != "" {
str += fmt.Sprintf(`,"name":"%s"`, escapeForJSON(n.Name))
}
if n.Value != "" || n.Type == "attribute" {
str += fmt.Sprintf(`,"value":"%s"`, escapeForJSON(n.Value))
}
if len(n.Attributes) > 0 {
str += `,"attributes":[`
for i, attr := range n.Attributes {
str += attr.String()
if i < len(n.Attributes)-1 {
str += ","
}
}
str += `]`
}
if len(n.Directives) > 0 {
str += `,"directives":[`
for i, attr := range n.Directives {
str += attr.String()
if i < len(n.Directives)-1 {
str += ","
}
}
str += `]`
}
if len(n.Children) > 0 {
str += `,"children":[`
for i, node := range n.Children {
str += node.String()
if i < len(n.Children)-1 {
str += ","
}
}
str += `]`
}
if n.Position.Start.Line != 0 {
str += `,"position":{`
str += fmt.Sprintf(`"start":{"line":%d,"column":%d,"offset":%d}`, n.Position.Start.Line, n.Position.Start.Column, n.Position.Start.Offset)
if n.Position.End.Line != 0 {
str += fmt.Sprintf(`,"end":{"line":%d,"column":%d,"offset":%d}`, n.Position.End.Line, n.Position.End.Column, n.Position.End.Offset)
}
str += "}"
}
str += "}"
return str
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just want to note that our String() function is implemented manually, but recurses through the AST just fine.

I had originally used json.Marshal but it relies heavily on Reflection which is not well supported in tinygo. This is more performant, anyway.

}
var node ASTNode

node.Position = positionAt(p, n, opts)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Position data is not super robust at the moment and might be wrong in some places. This should work but we'll need a cleanup pass to normalize this data in the parser.

Comment on lines +16 to +29
export interface BaseNode {
type: string;
position?: Position;
}

export interface ParentLikeNode extends BaseNode {
type: 'element' | 'component' | 'custom-element' | 'expression' | 'root';
children: Node[];
}

export interface LiteralNode extends BaseNode {
type: 'text' | 'doctype' | 'comment' | 'frontmatter';
value: string;
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a pretty good approximation of our AST! Intentionally very close to rehype which is built on unist.

Comment on lines +35 to +44
export interface AttributeNode extends BaseNode {
type: 'attribute';
kind: 'quoted' | 'empty' | 'expression' | 'spread' | 'shorthand' | 'template-literal';
name: string;
value: string;
}

export interface DirectiveNode extends Omit<AttributeNode, 'type'> {
type: 'directive';
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One choice worth calling out—I've split attributes and directives into two separate nodes. This should make it easy to find and validate official directive without needing to loop through all the existing attributes. The compiler filters them out for you.

Copy link
Contributor

@matthewp matthewp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@natemoo-re natemoo-re merged commit 0ce2f67 into next Jan 31, 2022
@natemoo-re natemoo-re deleted the feat/parse branch January 31, 2022 19:04
natemoo-re added a commit that referenced this pull request Jan 31, 2022
* feat: implement Astro.self (#270)

* feat: add parser

* chore: lint

* Update lib/compiler/README.md

Co-authored-by: Jonathan Neal <jonathantneal@hotmail.com>

Co-authored-by: Jonathan Neal <jonathantneal@hotmail.com>
natemoo-re added a commit that referenced this pull request Feb 15, 2022
* feat: implement Astro.self (#270)

* feat: add parser

* chore: lint

* Update lib/compiler/README.md

Co-authored-by: Jonathan Neal <jonathantneal@hotmail.com>

Co-authored-by: Jonathan Neal <jonathantneal@hotmail.com>
natemoo-re added a commit that referenced this pull request Feb 16, 2022
* feat: implement Astro.self (#270)

* feat: add parser

* chore: lint

* Update lib/compiler/README.md

Co-authored-by: Jonathan Neal <jonathantneal@hotmail.com>

Co-authored-by: Jonathan Neal <jonathantneal@hotmail.com>
natemoo-re added a commit that referenced this pull request Feb 22, 2022
* feat: implement Astro.self (#270)

* feat: add parser

* chore: lint

* Update lib/compiler/README.md

Co-authored-by: Jonathan Neal <jonathantneal@hotmail.com>

Co-authored-by: Jonathan Neal <jonathantneal@hotmail.com>
natemoo-re added a commit that referenced this pull request Feb 22, 2022
* feat: implement Astro.self (#270)

* feat: add parser

* chore: lint

* Update lib/compiler/README.md

Co-authored-by: Jonathan Neal <jonathantneal@hotmail.com>

Co-authored-by: Jonathan Neal <jonathantneal@hotmail.com>
natemoo-re added a commit that referenced this pull request Feb 24, 2022
* feat: implement Astro.self (#270)

* feat: add parser

* chore: lint

* Update lib/compiler/README.md

Co-authored-by: Jonathan Neal <jonathantneal@hotmail.com>

Co-authored-by: Jonathan Neal <jonathantneal@hotmail.com>
natemoo-re added a commit that referenced this pull request Mar 11, 2022
* chore: enter pre

* Treat all documents as fragments which generate no implicit tags (#264)

* feat: remove "as", treat all documents as fragments with no implicit tags

* test: fix failing tests

* lint: remove unused utils

* [DO NOT MERGE] add `renderHead` util to output (#265)

* feat: add renderHead util to output

* chore: update ci to run on `next`

* test: update tests

* chore: add changeset

* fix transform output

* Add `parse` function, emit AST (#274)

* feat: implement Astro.self (#270)

* feat: add parser

* chore: lint

* Update lib/compiler/README.md

Co-authored-by: Jonathan Neal <jonathantneal@hotmail.com>

Co-authored-by: Jonathan Neal <jonathantneal@hotmail.com>

* chore: add changeset

* test: update tests for no implicit tags

* test: update tests for no implicit tags

* chore: update tests for no implicit tags

* chore: update build script

* chore: update node bindings

* chore: update wasm file

* feat: expose AST types

* chore: update tests for no implicit tags

* [ci] release (next) (#288)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* chore: update exposed types

* [ci] release (next) (#304)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Warn when using an expression on hoist `src` attr (#303)

* Warn when using an expression on hoist `src` attr

* Adds a changeset

* Update the warning based on feedback

* [ci] release (next) (#305)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* fix: export `./types`

* [ci] release (next) (#306)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* fix: export all shared types

* fix: export named types

* [ci] release (next) (#307)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Client only metadata (#308)

* Include metadata on client:only components

* Adds a changeset

* [ci] release (next) (#309)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Fix next `head` behavior (#310)

* feat: update WASM tests

* fix: prefer astro.Parse to astro.ParseFragment

* fix: prefer `Parse` to `ParseFragment`

* fix: update parse test

* chore: add changeset

* test: add parse-ii test

* [ci] release (next) (#311)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Add `fragment` to AST (#312)

* feat: add fragment node to AST output

* fix: edge case with Fragment parsing in <head>

* chore: add changeset

* chore(lint): fix lint

* chore(lint): fix lint

* [ci] release (next) (#313)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Improve `renderHead` behavior (#315)

* feat: improve render-head behavior

* chore: add changeset

* chore: fix wasm test

* [ci] release (next) (#317)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Refactor WASM tests (#316)

* refactor: switch tests to uvu

* chore(ci): update test script

* chore(lint): fix

* test: enable head placeholder test

* test: fix head placeholder test

* refactor: remove escapeHTML usage, fix slot in head behavior

* [ci] release (next) (#320)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* fix: failing test

* feat: expose fragment to AST (#314)

Co-authored-by: Jonathan Neal <jonathantneal@hotmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Matthew Phillips <matthew@skypack.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants