Skip to content

Commit 4d50880

Browse files
Fix resolution of paths that contain a # (#1225)
Fixes #1221
1 parent 3357165 commit 4d50880

File tree

3 files changed

+125
-1
lines changed

3 files changed

+125
-1
lines changed

packages/tailwindcss-language-server/src/resolver/index.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ export async function createResolver(opts: ResolverOptions): Promise<Resolver> {
196196
id = normalizeYarnPnPDriveLetter(id)
197197
base = normalizeYarnPnPDriveLetter(base)
198198

199-
return new Promise((resolve, reject) => {
199+
let result = await new Promise<string | false>((resolve, reject) => {
200200
resolver.resolve({}, base, id, {}, (err, res) => {
201201
if (err) {
202202
reject(err)
@@ -205,6 +205,21 @@ export async function createResolver(opts: ResolverOptions): Promise<Resolver> {
205205
}
206206
})
207207
})
208+
209+
if (!result) return false
210+
211+
// The `enhanced-resolve` package supports resolving paths with fragment
212+
// identifiers. For example, it can resolve `foo/bar#baz` to `foo/bar.js`
213+
// However, it's also possible that a path contains a `#` character as part
214+
// of the path itself. For example, `foo#bar` might point to a file named
215+
// `foo#bar.js`. The resolver distinguishes between these two cases by
216+
// escaping the `#` character with a NUL byte when it's part of the path.
217+
//
218+
// Since the real path doesn't actually contain NUL bytes, we need to remove
219+
// them to get the correct path otherwise readFileSync will throw an error.
220+
result = result.replace(/\0(.)/g, '$1')
221+
222+
return result
208223
}
209224

210225
async function resolveJsId(id: string, base: string): Promise<string> {

packages/tailwindcss-language-server/tests/env/v4.test.js

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,3 +618,111 @@ defineTest({
618618
})
619619
},
620620
})
621+
622+
defineTest({
623+
name: 'Plugins with a `#` in the name are loadable',
624+
fs: {
625+
'app.css': css`
626+
@import 'tailwindcss';
627+
@plugin './a#b.js';
628+
`,
629+
'a#b.js': js`
630+
export default function ({ addUtilities }) {
631+
addUtilities({
632+
'.example': {
633+
color: 'red',
634+
},
635+
})
636+
}
637+
`,
638+
},
639+
prepare: async ({ root }) => ({ c: await init(root) }),
640+
handle: async ({ c }) => {
641+
let document = await c.openDocument({
642+
lang: 'html',
643+
text: '<div class="example">',
644+
})
645+
646+
// <div class="example">
647+
// ^
648+
let hover = await c.sendRequest(HoverRequest.type, {
649+
textDocument: document,
650+
position: { line: 0, character: 13 },
651+
})
652+
653+
expect(hover).toEqual({
654+
contents: {
655+
language: 'css',
656+
value: dedent`
657+
.example {
658+
color: red;
659+
}
660+
`,
661+
},
662+
range: {
663+
start: { line: 0, character: 12 },
664+
end: { line: 0, character: 19 },
665+
},
666+
})
667+
},
668+
})
669+
670+
defineTest({
671+
name: 'v3: Presets with a `#` in the name are loadable',
672+
fs: {
673+
'package.json': json`
674+
{
675+
"dependencies": {
676+
"tailwindcss": "3.4.17"
677+
}
678+
}
679+
`,
680+
'tailwind.config.js': js`
681+
module.exports = {
682+
presets: [require('./a#b.js').default]
683+
}
684+
`,
685+
'a#b.js': js`
686+
export default {
687+
plugins: [
688+
function ({ addUtilities }) {
689+
addUtilities({
690+
'.example': {
691+
color: 'red',
692+
},
693+
})
694+
}
695+
]
696+
}
697+
`,
698+
},
699+
prepare: async ({ root }) => ({ c: await init(root) }),
700+
handle: async ({ c }) => {
701+
let document = await c.openDocument({
702+
lang: 'html',
703+
text: '<div class="example">',
704+
})
705+
706+
// <div class="example">
707+
// ^
708+
let hover = await c.sendRequest(HoverRequest.type, {
709+
textDocument: document,
710+
position: { line: 0, character: 13 },
711+
})
712+
713+
expect(hover).toEqual({
714+
contents: {
715+
language: 'css',
716+
value: dedent`
717+
.example {
718+
color: red;
719+
}
720+
`,
721+
},
722+
range: {
723+
start: { line: 0, character: 12 },
724+
end: { line: 0, character: 19 },
725+
},
726+
})
727+
},
728+
})

packages/vscode-tailwindcss/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Prerelease
44

55
- LSP: Declare capability for handling workspace folder change notifications ([#1223](https://github.com/tailwindlabs/tailwindcss-intellisense/pull/1223))
6+
- Don't throw when resolving paths containing a `#` character ([#1225](https://github.com/tailwindlabs/tailwindcss-intellisense/pull/1225))
67

78
## 0.14.6
89

0 commit comments

Comments
 (0)