Sublime Forum

Extending attributes in HTML for sublime-syntax files

#1

I’m new to sublime-syntax development so any feedback is very helpful.

I’m writing support for Vue Component. A copy of my work so far is in this pull request but I’m going to describe my questions in detail here:

Extending HTML attributes in syntax

Vue supports adding expressions as JavaScript, similar to Angular’s ng-model if you’re familiar with it.

<div :expr="3 + 3">Hello</div>
            ^^^^^ formatted as scope:source.js
     ^^^^^ attribute

For this I would do something like (simplified):

- match: ':expr="'
  push:
    - match: '"'
      pop: true
    - include: scope:source.js

The downside is that it’s not treated as purely a HTML attribute. So the result is something like:

<div :expr="3 + 3">
            ^^^^^ formatted as scope:source.js. CORRECT
	Hello :expr="4 + 4"
                 ^^^^^ formatted as scope:source.js. INCORRECT
</div>

If I do something which parses the opening tags, then the other builtin HTML tag features stop working. I will have to re-implement or include things like the HTML tag-stuff. What’s the best approach to solve this?

Implementing basic tag attribute functionality

In vue component files, the top level scope is text.vue. Users can use custom languages in their styles and scripts. So a user can write

<- default scope text.vue
<style lang="sass">
^^^^^^^^^^^^^^^^^^^ <- parsed by my package, not by Sublime's HTML 
	<- new scope: source.sass
	<- new scope: source.sass
	<- new scope: source.sass
</style>

The exact rules I’m using to match this is:

    # 'sass' language
    - match: (<)(style)\b[^>]*(lang)\s*=\s*([\'\"]sass[\'\"])\s*.*(>)
      captures:
        1: punctuation.definition.tag.begin.html
        2: entity.name.tag.script.html
        3: entity.other.attribute-name.html
        4: string.quoted.double.html
        5: meta.tag.script.end.html
      embed: scope:source.sass
      escape: (</)(style).*(>)
      escape_captures: 
        1: punctuation.definition.tag.begin.html
        2: entity.name.tag.script.html
        3: meta.tag.script.end.html

However, with this approach, I’m manually capturing and setting the scopes of the attributes. Realistically vue’s <style> doesn’t support many different attributes except one but but I would like to highlight all attributes similar to the HTML package.

<style lang="sass" foo="bar">
                   ^^^^^^^^^ no scope

Is there a way I can re-use HTML’s attribute matching rules here?

0 Likes

#2

probably this:

yes, don’t match the > in your match pattern, instead push into a new context which will include HTML’s tag-stuff context and upon reaching >, then do your embed. Ofc this will cause problems if lang=… comes after different attributes or on a different line etc. which is again where those YAML macros could come in handy

1 Like