Skip to content

Instantly share code, notes, and snippets.

@SethHorsley
Created March 13, 2024 08:09
Show Gist options
  • Save SethHorsley/608af79145da45bdeb91a78f14421f8b to your computer and use it in GitHub Desktop.
Save SethHorsley/608af79145da45bdeb91a78f14421f8b to your computer and use it in GitHub Desktop.

HTML parser and lang parser in one AST

{
  type: 'element',
  tagName: 'div',
  properties: {className: ['foo'], id: 'some-id'},
  children: [
    {
      type: 'element',
      tagName: 'span',
      properties: {},
      children: [
		  {type: 'ruby', value: 'some text'}
	  ]
    },
    {
      type: 'element',
      tagName: 'span',
      properties: {},
      children: [
        {
          type: 'erb-loud', // <- comes from vscode-erb
          value: { //prism return
          type: "InstanceVariableReadNode",
          location: [[1,0],[1,6]]
              name: @posts,
        }
      ]
    },
    {
      type: 'erb-silent',
      location: [[1,0],[1,6]],
      value: {
        
      },
      children: [
        {
          type: "element", tagName: "h1", properties: {},
          children: [
            {type: "erb-loud", value: {}}
          ]
        }
      ]
    },
    {
      type: "element",
      tagName: "span",
      properties: {
        id: '1',
      },
      dynamic_properties: [
        {
          type: "erb-silent",
          children: [
            {
              type: "html-attr",
              key: "class",
              value: []
              value: {
                type: "composed",
                children: [
                  {
                    type: "text",
                    value: "mt-2 "
                  },
                  {
                    type: "erb-loud",
                    value: {/* prism returned value */}
                  }
                ]
              }
            }
          ]
        }
      ]
    }
  ]
}
<span
  id="1"
  <% if post.title.length < 10 %>
    class="mt-2 bg-red-200 border-t-[<%= post.read_percentage %>%]"
  <% else %>
    class="mt-0"
    <%=  %>
  <% end %>
>
  <%= post.description %>
</span>


<span id="1" <% if true %> class="mt-2 <%= post.title %>" <% end %> >
  <%= post.description %>
</span>

<% @posts.each do |post| %>
  <h1>
    <%= post.title %>llll
  </h1>
<% end %>

// 1. ide send file data to lsp server // 2. lsp server parse file data and return tree // 3. ide use tree to provide autocomplete

Parser.parse_html_erb("...") Parser.parse_html_blade("") Parser.oarse_html_ejs("")

<div {{ $attributes->merge(['data-controller' => 'this-should-autocomplete']) }}>
    {{ $message }}
</div>


<div data-controller="autocomplete-works">
	<%= @posts %>
	<%= tag.div "Click", data: { controller: "autocomplete-doesn't-work"} %>
	<%= content_tag(:span, "Click", data: { controller: "autocomplete-doesn't-work"} %>
</div>

HTML parser and lang node to send to lang parser. (only has html ast)

any lang node would be send and the lang ast would be seperate for that node

{
  type: 'element',
  tagName: 'div',
  properties: {className: ['foo'], id: 'some-id'},
  children: [
    {
      type: 'element', // element, text, comment, lang
      tagName: 'span',
      properties: {},
      children: [
      {
        type: "InstanceVariableReadNode",
        location: [[1,0],[1,6]]
        type: 'text',
        value: '<%= @posts %>'
      },
      {
        type: "InstanceVariableReadNode",
        location: [[1,0],[1,6]]
        type: 'text',
        value: '<%= @posts %>'
      }
	  ]
    },
  ]
}
<span <% if true %> class="mt-2 <%= post.title %>" <% end %> >
  <%= post.description %>
</span>

<% @posts.each do |post| %>
  <h1>
    <%= post.title %> -- <%= post.description %>
  </h1>
<% end %>

1. ide send file data to lsp server

2. lsp server parse html file data and send language nodes to be parsed/evaluated

3. ide use html tree to provide html autocomplete and language nodes to provide language autocomplete

{{}}


<div data-controller="autocomplete-works">
	<%= @posts %>
	<%= tag.div "Click", data: { controller: "autocomplete-doesn't-work"} %>
	<%= content_tag(:span, "Click", data: { controller: "autocomplete-doesn't-work"} %>
</div>
@SethHorsley
Copy link
Author

More updated syntax

{
  "type": "Document",
  "children": [
    {
      "type": "Element",
      "tagName": "div",
      "attributes": {
        "class": "foo",
        "id": "some-id"
      },
      "children": [
        {
          "type": "Element",
          "tagName": "span",
          "attributes": {},
          "content": {
            "type": "Text",
            "value": "some text"
          },
          "location": {
            "start": {"line": 2, "column": 3},
            "end": {"line": 2, "column": 34}
          }
        },
        {
          "type": "Element",
          "tagName": "input",
          "attributes": {
            "type": "text",
            "value": "foo"
          },
          "selfClosing": true,
          "location": {
            "start": {"line": 3, "column": 3},
            "end": {"line": 3, "column": 36}
          }
        },
        {
          "type": "Element",
          "tagName": "a",
          "attributes": {
            "class": "alpha bravo charlie",
            "download": true
          },
          "children": [
            {
              "type": "Text",
              "value": "delta echo"
            }
          ],
          "location": {
            "start": {"line": 4, "column": 3},
            "end": {"line": 4, "column": 64}
          }
        }
      ],
      "location": {
        "start": {"line": 1, "column": 1},
        "end": {"line": 5, "column": 6}
      }
    },
    {
      "type": "Element",
      "tagName": "svg",
      "attributes": {
        "xmlns": "http://www.w3.org/2000/svg",
        "viewBox": "0 0 500 500"
      },
      "children": [
        {
          "type": "Element",
          "tagName": "title",
          "children": [
            {
              "type": "Text",
              "value": "SVG `<circle>` element"
            }
          ],
          "location": {
            "start": {"line": 7, "column": 3},
            "end": {"line": 7, "column": 50}
          }
        },
        {
          "type": "Element",
          "tagName": "circle",
          "attributes": {
            "cx": "120",
            "cy": "120",
            "r": "100"
          },
          "selfClosing": true,
          "location": {
            "start": {"line": 8, "column": 3},
            "end": {"line": 8, "column": 44}
          }
        }
      ],
      "location": {
        "start": {"line": 6, "column": 1},
        "end": {"line": 9, "column": 6}
      }
    }
  ],
  "location": {
    "start": {"line": 1, "column": 1},
    "end": {"line": 9, "column": 6}
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment