Skip to content

Commit 5409db0

Browse files
authored
fix(vue): handle more edge cases for tags (#1069)
- Allow parsing of attributes to end on `/>`, `>` or a whitespace character. - Consilidate the parsing of the shorthand `@EVENT` to one rule. Do better parsing for its contents by allowing whitespace (`@click="menuVisible = !menuVisible"`) and `EVENT` to contain a dot (`@keyup.enter`). Allow it to not have any condition (`<a @click.stop>`). - Allow `v-` directives to contain a dash. - Move a rule down that captures `v-on:click="doSomething"` as it was included more than it should for the `LiteralString` token. - Add tests that should exhaustively tests these edge cases. They were derived from https://codeberg.org/forgejo/forgejo/src/commit/a18fc8b03702f439845daf22a0cc7fb0f8ea95c3/web_src/js/components/RepoBranchTagSelector.vue#L248-L318 ## Screenshot The syntax highlighting of the input is still not perfect (e.g. HTML comment and `symbol-id=`), but it's a lot better now. ### Before ![image](https://github.com/user-attachments/assets/fc297510-ccfb-4a64-90f6-768afa17459e) ### After ![image](https://github.com/user-attachments/assets/7d9f2adc-263f-4dd1-938d-927de819369c)
1 parent 3ee0984 commit 5409db0

File tree

3 files changed

+96
-21
lines changed

3 files changed

+96
-21
lines changed

lexers/embedded/vue.xml

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -64,25 +64,13 @@
6464
<rule pattern="(-)([\w]+)">
6565
<token type="NameTag"/>
6666
</rule>
67-
<rule pattern="(@[\w]+)(=&#34;[\S]+&#34;)(&gt;)">
67+
<rule pattern="(@[\w.]+)(=&#34;.*?&#34;)?(\/?&gt;|\s)">
6868
<bygroups>
6969
<token type="NameTag"/>
7070
<token type="LiteralString"/>
7171
<token type="Punctuation"/>
7272
</bygroups>
7373
</rule>
74-
<rule pattern="(@[\w]+)(=&#34;[\S]+&#34;)">
75-
<bygroups>
76-
<token type="NameTag"/>
77-
<token type="LiteralString"/>
78-
</bygroups>
79-
</rule>
80-
<rule pattern="(@[\S]+)(=&#34;[\S]+&#34;)">
81-
<bygroups>
82-
<token type="NameTag"/>
83-
<token type="LiteralString"/>
84-
</bygroups>
85-
</rule>
8674
<rule pattern="(:[\S]+)(=)(&#34;[\S]+&#34;)">
8775
<bygroups>
8876
<token type="NameTag"/>
@@ -96,31 +84,31 @@
9684
<rule pattern="(v-b-[\S]+)">
9785
<token type="NameTag"/>
9886
</rule>
99-
<rule pattern="(v-[\w]+)(=&#34;.+)([:][\w]+)(=&#34;[\w]+&#34;)(&gt;)">
87+
<rule pattern="(v-[\w-]+)(=)(&#34;[\S ]+&#34;)(\/?&gt;|\s)">
10088
<bygroups>
10189
<token type="NameTag"/>
102-
<token type="LiteralString"/>
103-
<token type="NameTag"/>
90+
<token type="Operator"/>
10491
<token type="LiteralString"/>
10592
<token type="Punctuation"/>
10693
</bygroups>
10794
</rule>
108-
<rule pattern="(v-[\w]+)(=)(&#34;[\S ]+&#34;)(&gt;|\s)">
95+
<rule pattern="(v-[\w-]+)(\/?&gt;|\s)">
10996
<bygroups>
11097
<token type="NameTag"/>
111-
<token type="Operator"/>
112-
<token type="LiteralString"/>
11398
<token type="Punctuation"/>
11499
</bygroups>
115100
</rule>
116-
<rule pattern="(v-[\w]+)(&gt;)">
101+
<rule pattern="(v-[\w-]+)(=&#34;.+&#34;)(\/?&gt;|\s)">
117102
<bygroups>
118103
<token type="NameTag"/>
104+
<token type="LiteralString"/>
119105
<token type="Punctuation"/>
120106
</bygroups>
121107
</rule>
122-
<rule pattern="(v-[\w]+)(=&#34;.+&#34;)(&gt;)">
108+
<rule pattern="(v-[\w-]+)(=&#34;.+)([:][\w]+)(=&#34;[\w]+&#34;)(\/?&gt;|\s)">
123109
<bygroups>
110+
<token type="NameTag"/>
111+
<token type="LiteralString"/>
124112
<token type="NameTag"/>
125113
<token type="LiteralString"/>
126114
<token type="Punctuation"/>

lexers/testdata/vue.actual

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@
88
</ul-extendded>
99
</template>
1010

11+
<template v-else>
12+
<svg-icon v-if="isViewTag">
13+
<svg-icon v-else-if="isViewTree" name="octicon-git-commit"/>
14+
<svg-icon v-else name="octicon-git-branch"/>
15+
</template>
16+
<template>
17+
<input type="hidden" name="_csrf" :value="csrfToken">
18+
<a @click.stop>
19+
<button @click="menuVisible = !menuVisible" @keyup.enter="menuVisible = !menuVisible"/>
20+
</template>
21+
1122
<script>
1223
export default {
1324
name: "MyButton"

lexers/testdata/vue.expected

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,82 @@
5252
{"type":"Punctuation","value":"\u003e"},
5353
{"type":"Text","value":"\n\n"},
5454
{"type":"Punctuation","value":"\u003c"},
55+
{"type":"NameTag","value":"template"},
56+
{"type":"Text","value":" "},
57+
{"type":"NameTag","value":"v-else"},
58+
{"type":"Punctuation","value":"\u003e"},
59+
{"type":"Text","value":"\n\t"},
60+
{"type":"Punctuation","value":"\u003c"},
61+
{"type":"NameTag","value":"svg-icon"},
62+
{"type":"Text","value":" "},
63+
{"type":"NameTag","value":"v-if"},
64+
{"type":"Operator","value":"="},
65+
{"type":"LiteralString","value":"\"isViewTag\""},
66+
{"type":"Punctuation","value":"\u003e"},
67+
{"type":"Text","value":"\n\t"},
68+
{"type":"Punctuation","value":"\u003c"},
69+
{"type":"NameTag","value":"svg-icon"},
70+
{"type":"Text","value":" "},
71+
{"type":"NameTag","value":"v-else-if"},
72+
{"type":"Operator","value":"="},
73+
{"type":"LiteralString","value":"\"isViewTree\" name=\"octicon-git-commit\""},
74+
{"type":"Punctuation","value":"/\u003e"},
75+
{"type":"Text","value":"\n\t"},
76+
{"type":"Punctuation","value":"\u003c"},
77+
{"type":"NameTag","value":"svg-icon"},
78+
{"type":"Text","value":" "},
79+
{"type":"NameTag","value":"v-else"},
80+
{"type":"Punctuation","value":" "},
81+
{"type":"NameAttribute","value":"name"},
82+
{"type":"Operator","value":"="},
83+
{"type":"LiteralString","value":"\"octicon-git-branch\""},
84+
{"type":"Punctuation","value":"/\u003e"},
85+
{"type":"Text","value":"\n"},
86+
{"type":"Punctuation","value":"\u003c/"},
87+
{"type":"NameTag","value":"template"},
88+
{"type":"Punctuation","value":"\u003e"},
89+
{"type":"Text","value":"\n"},
90+
{"type":"Punctuation","value":"\u003c"},
91+
{"type":"NameTag","value":"template"},
92+
{"type":"Punctuation","value":"\u003e"},
93+
{"type":"Text","value":"\n\t"},
94+
{"type":"Punctuation","value":"\u003c"},
95+
{"type":"NameTag","value":"input"},
96+
{"type":"Text","value":" "},
97+
{"type":"NameAttribute","value":"type"},
98+
{"type":"Operator","value":"="},
99+
{"type":"LiteralString","value":"\"hidden\""},
100+
{"type":"Text","value":" "},
101+
{"type":"NameAttribute","value":"name"},
102+
{"type":"Operator","value":"="},
103+
{"type":"LiteralString","value":"\"_csrf\""},
104+
{"type":"Text","value":" "},
105+
{"type":"NameTag","value":":value"},
106+
{"type":"Operator","value":"="},
107+
{"type":"LiteralString","value":"\"csrfToken\""},
108+
{"type":"Punctuation","value":"\u003e"},
109+
{"type":"Text","value":"\n\t"},
110+
{"type":"Punctuation","value":"\u003c"},
111+
{"type":"NameTag","value":"a"},
112+
{"type":"Text","value":" "},
113+
{"type":"NameTag","value":"@click.stop"},
114+
{"type":"Punctuation","value":"\u003e"},
115+
{"type":"Text","value":"\n "},
116+
{"type":"Punctuation","value":"\u003c"},
117+
{"type":"NameTag","value":"button"},
118+
{"type":"Text","value":" "},
119+
{"type":"NameTag","value":"@click"},
120+
{"type":"LiteralString","value":"=\"menuVisible = !menuVisible\""},
121+
{"type":"Punctuation","value":" "},
122+
{"type":"NameTag","value":"@keyup.enter"},
123+
{"type":"LiteralString","value":"=\"menuVisible = !menuVisible\""},
124+
{"type":"Punctuation","value":"/\u003e"},
125+
{"type":"Text","value":"\n"},
126+
{"type":"Punctuation","value":"\u003c/"},
127+
{"type":"NameTag","value":"template"},
128+
{"type":"Punctuation","value":"\u003e"},
129+
{"type":"Text","value":"\n\n"},
130+
{"type":"Punctuation","value":"\u003c"},
55131
{"type":"NameTag","value":"script"},
56132
{"type":"Punctuation","value":"\u003e"},
57133
{"type":"Text","value":"\n "},

0 commit comments

Comments
 (0)