Skip to content

Commit bb1206e

Browse files
committed
feat: support tag import shorthands in ts files
1 parent 96d9ec5 commit bb1206e

File tree

5 files changed

+50
-5
lines changed

5 files changed

+50
-5
lines changed

.changeset/witty-ghosts-pump.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@marko/language-server": patch
3+
"@marko/type-check": patch
4+
"marko-vscode": patch
5+
---
6+
7+
Support resolving tag import shorthands in typescript files.

packages/language-server/src/service/marko/complete/Import.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
1-
import type { Node } from "@marko/language-tools";
1+
import { type Node, NodeType } from "@marko/language-tools";
22
import { CompletionItem, TextEdit } from "vscode-languageserver";
33

44
import getTagNameCompletion from "../util/get-tag-name-completion";
55
import type { CompletionMeta, CompletionResult } from ".";
66

7+
const staticImportReg = /^\s*(?:static|client|server) import\b/;
78
const importTagReg = /(['"])<((?:[^'"\\>]|\\.)*)>?\1/;
89

910
export function Import({
1011
node,
1112
file: { parsed, filename, lookup },
12-
}: CompletionMeta<Node.Import>): CompletionResult {
13-
// check for import statement
13+
}: CompletionMeta<Node.Import | Node.Static>): CompletionResult {
1414
const value = parsed.read(node);
15+
if (node.type === NodeType.Static && !staticImportReg.test(value)) {
16+
// Checks for `static import`, `client import` and `server import`.
17+
return;
18+
}
19+
1520
const match = importTagReg.exec(value);
1621
if (match) {
1722
const [{ length }] = match;

packages/language-server/src/service/marko/complete/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const handlers: Record<
2626
AttrName,
2727
AttrValue,
2828
Import,
29+
Static: Import,
2930
};
3031

3132
export const doComplete: Plugin["doComplete"] = async (doc, params) => {

packages/language-server/src/ts-plugin/host.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ import {
33
getExt,
44
isDefinitionFile,
55
Processors,
6+
Project,
67
} from "@marko/language-tools";
78
import path from "path";
89
import type ts from "typescript/lib/tsserverlibrary";
910

1011
const fsPathReg = /^(?:[./\\]|[A-Z]:)/i;
1112
const modulePartsReg = /^((?:@(?:[^/]+)\/)?(?:[^/]+))(.*)$/;
13+
const importTagReg = /<([^>]+)>/;
1214

1315
export interface ExtractedSnapshot extends Extracted {
1416
snapshot: ts.IScriptSnapshot;
@@ -151,7 +153,21 @@ export function patch(
151153

152154
for (let i = 0; i < moduleLiterals.length; i++) {
153155
const moduleLiteral = moduleLiterals[i];
154-
const moduleName = moduleLiteral.text;
156+
let moduleName = moduleLiteral.text;
157+
158+
const tagNameMatch = importTagReg.exec(moduleName);
159+
if (tagNameMatch) {
160+
// Try to resolve `import Tag from "<tag>"` style imports.
161+
const [, tagName] = tagNameMatch;
162+
const tagDef = Project.getTagLookup(
163+
path.dirname(containingFile),
164+
).getTag(tagName);
165+
const tagFileName = tagDef && (tagDef.template || tagDef.renderer);
166+
if (tagFileName) {
167+
moduleName = tagFileName;
168+
}
169+
}
170+
155171
const processor =
156172
moduleName[0] !== "*" ? getProcessor(moduleName) : undefined;
157173
if (processor) {

packages/type-check/src/run.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
isDefinitionFile,
88
type Location,
99
Processors,
10+
Project,
1011
} from "@marko/language-tools";
1112
import crypto from "crypto";
1213
import color from "kleur";
@@ -37,6 +38,7 @@ const getCanonicalFileName = ts.sys.useCaseSensitiveFileNames
3738
? (fileName: string) => fileName
3839
: (fileName: string) => fileName.toLowerCase();
3940
const fsPathReg = /^(?:[./\\]|[A-Z]:)/i;
41+
const importTagReg = /<([^>]+)>/;
4042
const modulePartsReg = /^((?:@(?:[^/]+)\/)?(?:[^/]+))(.*)$/;
4143
const isRemapExtensionReg = /\.ts$/;
4244
const isSourceMapExtensionReg = /\.map$/;
@@ -187,7 +189,21 @@ export default function run(opts: Options) {
187189

188190
for (let i = 0; i < moduleLiterals.length; i++) {
189191
const moduleLiteral = moduleLiterals[i];
190-
const moduleName = moduleLiteral.text;
192+
let moduleName = moduleLiteral.text;
193+
194+
const tagNameMatch = importTagReg.exec(moduleName);
195+
if (tagNameMatch) {
196+
// Try to resolve `import Tag from "<tag>"` style imports.
197+
const [, tagName] = tagNameMatch;
198+
const tagDef = Project.getTagLookup(
199+
path.dirname(containingFile),
200+
).getTag(tagName);
201+
const tagFileName = tagDef && (tagDef.template || tagDef.renderer);
202+
if (tagFileName) {
203+
moduleName = tagFileName;
204+
}
205+
}
206+
191207
const processor =
192208
moduleName[0] !== "*" ? getProcessor(moduleName) : undefined;
193209
if (processor) {

0 commit comments

Comments
 (0)