Skip to content

Commit 68b0ebe

Browse files
committed
fix: import tags from installed packages by their resolved name
1 parent 64cb1b0 commit 68b0ebe

6 files changed

Lines changed: 74 additions & 40 deletions

File tree

.changeset/tidy-pears-jam.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@marko/language-tools": patch
3+
---
4+
5+
Import tags from installed packages by the name their taglib was resolved through, fixing the types for tags installed into a virtual store (eg pnpm).

package-lock.json

Lines changed: 26 additions & 29 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/language-server/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,15 @@
4444
},
4545
"dependencies": {
4646
"@luxass/strip-json-comments": "^1.4.0",
47-
"@marko/compiler": "^5.39.66",
47+
"@marko/compiler": "^5.41.0",
4848
"@marko/language-tools": "^2.6.3",
4949
"axe-core": "^4.12.1",
5050
"htmljs-parser": "^5.12.1",
5151
"jsdom": "^29.1.1",
5252
"marko": "^5.39.11",
5353
"prettier": "^3.8.4",
5454
"prettier-plugin-marko": "^4.0.9",
55-
"relative-import-path": "^1.0.0",
55+
"relative-import-path": "^1.0.1",
5656
"typescript": "^6.0.3",
5757
"vscode-css-languageservice": "^6.3.10",
5858
"vscode-languageserver": "^10.0.1",

packages/language-tools/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@
3737
},
3838
"dependencies": {
3939
"@luxass/strip-json-comments": "^1.4.0",
40-
"@marko/compiler": "^5.39.66",
40+
"@marko/compiler": "^5.41.0",
4141
"htmljs-parser": "^5.12.1",
42-
"relative-import-path": "^1.0.0"
42+
"relative-import-path": "^1.0.1"
4343
},
4444
"devDependencies": {
4545
"@types/babel__code-frame": "^7.27.0",

packages/language-tools/src/extractors/script/index.ts

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { types as t } from "@marko/compiler";
22
import type { TagDefinition, TaglibLookup } from "@marko/compiler/babel-utils";
3+
import path from "path";
34
import { relativeImportPath } from "relative-import-path";
45
import type TS from "typescript/lib/tsserverlibrary";
56

@@ -52,6 +53,7 @@ const REG_OBJECT_PROPERTY = /^[_$a-z][_$a-z0-9]*$/i;
5253
// Match https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html#-reference-path- and https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html#ts-check
5354
const REG_COMMENT_PRAGMA = /\/\/(?:\s*@ts-|\/\s*<)/y;
5455
const REG_TAG_NAME_IDENTIFIER = /^[A-Z][a-zA-Z0-9_$]+$/;
56+
const REG_NODE_MODULES = /[\\/]node_modules[\\/]/;
5557
const IF_TAG_ALTERNATES = new WeakMap<IfTag, IfTagAlternates>();
5658
const TAG_ID = new WeakMap<Node.Tag, number>();
5759
const RENDER_VAR = new WeakMap<Node.Tag, string>();
@@ -2182,12 +2184,42 @@ function isValueAttribute(
21822184

21832185
function resolveTagImport(from: string, def: TagDefinition | undefined) {
21842186
const filename = resolveTagFile(def);
2185-
if (filename) {
2186-
// `from` is parsed.filename which is already normalized, but the taglib
2187-
// provided path must use native separators too or relativeImportPath
2188-
// falls back to returning the absolute path.
2189-
return from ? relativeImportPath(from, normalizePath(filename)) : filename;
2190-
}
2187+
if (!def || !filename) return;
2188+
if (!from) return filename;
2189+
2190+
// `from` is parsed.filename which is already normalized, but the taglib
2191+
// provided path must use native separators too or relativeImportPath
2192+
// falls back to returning the absolute path.
2193+
const to = normalizePath(filename);
2194+
return packageImportPath(from, def, to) || relativeImportPath(from, to);
2195+
}
2196+
2197+
/**
2198+
* A tag installed into `node_modules` is imported through the name its package was
2199+
* resolved by, since its path is a realpath which may not be importable at all.
2200+
*/
2201+
function packageImportPath(from: string, def: TagDefinition, filename: string) {
2202+
const { packageName, packageRoot } = def;
2203+
if (!packageName || !packageRoot || !REG_NODE_MODULES.test(filename)) return;
2204+
2205+
// Within the package we stay relative, both because it always resolves and
2206+
// because a self reference would only work if the package exports the tag.
2207+
if (!isWithin(packageRoot, filename) || isWithin(packageRoot, from)) return;
2208+
2209+
const subPath = path.relative(packageRoot, filename);
2210+
return `${packageName}/${subPath.split(path.sep).join("/")}`;
2211+
}
2212+
2213+
function isWithin(dir: string, filename: string) {
2214+
const rel = path.relative(dir, filename);
2215+
// `path.relative` walks out of the dir with `..`, or returns an absolute path
2216+
// when it cannot relate the two at all, eg across windows drives.
2217+
return (
2218+
!!rel &&
2219+
rel !== ".." &&
2220+
!rel.startsWith(`..${path.sep}`) &&
2221+
!path.isAbsolute(rel)
2222+
);
21912223
}
21922224

21932225
function resolveTagFile(def: TagDefinition | undefined): string | undefined {

packages/type-check/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
},
3131
"dependencies": {
3232
"@luxass/strip-json-comments": "^1.4.0",
33-
"@marko/compiler": "^5.39.66",
33+
"@marko/compiler": "^5.41.0",
3434
"@marko/language-tools": "^2.6.3",
3535
"arg": "^5.0.2",
3636
"kleur": "^4.1.5",

0 commit comments

Comments
 (0)