Skip to content

Commit 9de977f

Browse files
committed
Treat astro code fences as JS
1 parent ce98ac2 commit 9de977f

File tree

5 files changed

+132
-4
lines changed

5 files changed

+132
-4
lines changed

packages/tailwindcss-language-service/src/util/find.test.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
findClassNameAtPosition,
55
findHelperFunctionsInDocument,
66
} from './find'
7-
import { js, html, pug, createDocument, css } from './test-utils'
7+
import { js, html, pug, createDocument, css, astro } from './test-utils'
88
import type { Range } from 'vscode-languageserver-textdocument'
99

1010
const range = (startLine: number, startCol: number, endLine: number, endCol: number): Range => ({
@@ -1044,3 +1044,40 @@ test('Can find helper functions in CSS', async ({ expect }) => {
10441044
},
10451045
])
10461046
})
1047+
1048+
test('class functions work inside astro code fences', async ({ expect }) => {
1049+
let file = createDocument({
1050+
name: 'file.astro',
1051+
lang: 'astro',
1052+
settings: {
1053+
tailwindCSS: {
1054+
classFunctions: ['clsx'],
1055+
},
1056+
},
1057+
content: astro`
1058+
---
1059+
let x = clsx("relative flex bg-red-500")
1060+
---
1061+
<div class="relative flex bg-red-500"></div>
1062+
`,
1063+
})
1064+
1065+
let classLists = await findClassListsInHtmlRange(file.state, file.doc, 'html')
1066+
1067+
expect(classLists).toEqual([
1068+
{
1069+
classList: 'relative flex bg-red-500',
1070+
range: {
1071+
start: { line: 3, character: 12 },
1072+
end: { line: 3, character: 36 },
1073+
},
1074+
},
1075+
{
1076+
classList: 'relative flex bg-red-500',
1077+
range: {
1078+
start: { line: 1, character: 14 },
1079+
end: { line: 1, character: 38 },
1080+
},
1081+
},
1082+
])
1083+
})

packages/tailwindcss-language-service/src/util/getLanguageBoundaries.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Range } from 'vscode-languageserver'
22
import type { TextDocument } from 'vscode-languageserver-textdocument'
3-
import { isVueDoc, isHtmlDoc, isSvelteDoc } from './html'
3+
import { isVueDoc, isHtmlDoc, isSvelteDoc, isAstroDoc } from './html'
44
import type { State } from './state'
55
import { indexToPosition } from './find'
66
import { isJsDoc } from './js'
@@ -134,8 +134,21 @@ let vueStates = {
134134
},
135135
}
136136

137+
let astroStates = {
138+
...states,
139+
main: {
140+
frontmatterBlockStart: { match: /^[\s\n]*---/, push: 'frontmatterScript' },
141+
...states.main,
142+
},
143+
frontmatterScript: {
144+
frontmatterBlockEnd: { match: /\s*---(?=\s)/, pop: 1 },
145+
...text,
146+
},
147+
}
148+
137149
let defaultLexer = moo.states(states)
138150
let vueLexer = moo.states(vueStates)
151+
let astroLexer = moo.states(astroStates)
139152

140153
let cache = new Cache<string, LanguageBoundary[] | null>({ max: 25, maxAge: 1000 })
141154

@@ -161,7 +174,7 @@ export function getLanguageBoundaries(
161174

162175
if (isVueDoc(doc)) {
163176
defaultType = 'none'
164-
} else if (isHtmlDoc(state, doc) || isSvelteDoc(doc)) {
177+
} else if (isHtmlDoc(state, doc) || isSvelteDoc(doc) || isAstroDoc(doc)) {
165178
defaultType = 'html'
166179
} else if (isJs) {
167180
defaultType = 'jsx'
@@ -180,6 +193,10 @@ export function getLanguageBoundaries(
180193
if (isVueDoc(doc)) {
181194
lexer = vueLexer
182195
}
196+
} else if (defaultType === 'html') {
197+
if (isAstroDoc(doc)) {
198+
lexer = astroLexer
199+
}
183200
}
184201

185202
lexer.reset(text)
@@ -199,6 +216,11 @@ export function getLanguageBoundaries(
199216
boundaries[boundaries.length - 1].range.end = position
200217
}
201218
type = token.type.replace(/BlockStart$/, '')
219+
220+
if (lexer === astroLexer && type === 'frontmatter') {
221+
type = 'js'
222+
}
223+
202224
boundaries.push({ type, range: { start: position, end: undefined } })
203225
} else if (token.type.endsWith('BlockEnd')) {
204226
let position = indexToPosition(text, offset)

packages/tailwindcss-language-service/src/util/html.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ export function isSvelteDoc(doc: TextDocument): boolean {
2020
return doc.languageId === 'svelte'
2121
}
2222

23+
export function isAstroDoc(doc: TextDocument): boolean {
24+
return doc.languageId === 'astro'
25+
}
26+
2327
export function isHtmlContext(state: State, doc: TextDocument, position: Position): boolean {
2428
let str = doc.getText({
2529
start: { line: 0, character: 0 },

packages/tailwindcss-language-service/src/util/language-boundaries.test.ts

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { test } from 'vitest'
22
import { getLanguageBoundaries } from './getLanguageBoundaries'
3-
import { jsx, createDocument, html } from './test-utils'
3+
import { jsx, createDocument, html, astro } from './test-utils'
44

55
test('regex literals are ignored when determining language boundaries', ({ expect }) => {
66
let file = createDocument({
@@ -189,3 +189,67 @@ test('Vue files detect <template>, <script>, and <style> as separate boundaries'
189189
},
190190
])
191191
})
192+
193+
test('Astro files default to HTML', ({ expect }) => {
194+
let file = createDocument({
195+
name: 'file.astro',
196+
lang: 'astro',
197+
content: html`<div class="border-gray-200"></div>`,
198+
})
199+
200+
let boundaries = getLanguageBoundaries(file.state, file.doc)
201+
202+
expect(boundaries).toEqual([
203+
{
204+
type: 'html',
205+
range: {
206+
start: { line: 0, character: 0 },
207+
end: { line: 0, character: 35 },
208+
},
209+
},
210+
])
211+
})
212+
213+
test('Astro files front matter is pared as JS', ({ expect }) => {
214+
let file = createDocument({
215+
name: 'file.astro',
216+
lang: 'astro',
217+
content: astro`
218+
---
219+
console.log('test')
220+
---
221+
<div class="border-gray-200"></div>
222+
`,
223+
})
224+
225+
let boundaries = getLanguageBoundaries(file.state, file.doc)
226+
227+
expect(boundaries).toEqual([
228+
// This block just shouldn't be here
229+
{
230+
type: 'html',
231+
range: {
232+
start: { line: 0, character: 0 },
233+
end: { line: 0, character: 0 },
234+
},
235+
},
236+
{
237+
type: 'js',
238+
range: {
239+
// This should probably be 0:3 instead of 0:0
240+
start: { line: 0, character: 0 },
241+
242+
// This should probably be 2:0 instead of 1:19
243+
end: { line: 1, character: 19 },
244+
},
245+
},
246+
{
247+
type: 'html',
248+
range: {
249+
// This should probably be 2:3 instead of 1:19
250+
start: { line: 1, character: 19 },
251+
end: { line: 3, character: 35 },
252+
},
253+
},
254+
])
255+
})

packages/tailwindcss-language-service/src/util/test-utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export const ts: Dedent = dedent
99
export const tsx: Dedent = dedent
1010
export const css: Dedent = dedent
1111
export const html: Dedent = dedent
12+
export const astro: Dedent = dedent
1213
export const pug: Dedent = dedent
1314

1415
export function createDocument({

0 commit comments

Comments
 (0)