-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: regexp issues in syntax highlighting
- Loading branch information
1 parent
5f0ec0d
commit c1f0d97
Showing
7 changed files
with
150 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import type { TaglibLookup } from "@marko/babel-utils"; | ||
import { DocumentLink } from "vscode-languageserver"; | ||
import type { TextDocument } from "vscode-languageserver-textdocument"; | ||
import { URI } from "vscode-uri"; | ||
import { | ||
type Node, | ||
type Range, | ||
type parse, | ||
NodeType, | ||
} from "../../../utils/parser"; | ||
import resolveUrl from "../../../utils/resolve-url"; | ||
|
||
const importTagReg = /(['"])<((?:[^\1\\>]+|\\.)*)>?\1/g; | ||
const linkedAttrs: Record<string, Set<string>> = { | ||
src: new Set([ | ||
"audio", | ||
"embed", | ||
"iframe", | ||
"img", | ||
"input", | ||
"script", | ||
"source", | ||
"track", | ||
"video", | ||
]), | ||
href: new Set(["a", "area", "link"]), | ||
data: new Set(["object"]), | ||
poster: new Set(["video"]), | ||
}; | ||
|
||
/** | ||
* Iterate over the Marko CST and extract all the file links in the document. | ||
*/ | ||
export function extractDocumentLinks( | ||
doc: TextDocument, | ||
parsed: ReturnType<typeof parse>, | ||
lookup: TaglibLookup | ||
): DocumentLink[] { | ||
if (URI.parse(doc.uri).scheme === "untitled") { | ||
return []; | ||
} | ||
|
||
const links: DocumentLink[] = []; | ||
const { program } = parsed; | ||
const code = doc.getText(); | ||
const read = (range: Range) => code.slice(range.start, range.end); | ||
const visit = (node: Node.ChildNode) => { | ||
switch (node.type) { | ||
case NodeType.Tag: | ||
if (node.attrs && node.nameText) { | ||
for (const attr of node.attrs) { | ||
if ( | ||
attr.type === NodeType.AttrNamed && | ||
attr.value?.type === NodeType.AttrValue && | ||
/^['"]$/.test(code[attr.value.value.start]) | ||
) { | ||
const attrName = read(attr.name); | ||
if (linkedAttrs[attrName]?.has(node.nameText)) { | ||
links.push( | ||
DocumentLink.create( | ||
{ | ||
start: parsed.positionAt(attr.value.value.start), | ||
end: parsed.positionAt(attr.value.value.end), | ||
}, | ||
resolveUrl(read(attr.value.value).slice(1, -1), doc.uri) | ||
) | ||
); | ||
} | ||
} | ||
} | ||
} | ||
if (node.body) { | ||
for (const child of node.body) { | ||
visit(child); | ||
} | ||
} | ||
|
||
break; | ||
} | ||
}; | ||
|
||
for (const item of program.static) { | ||
// check for import statement (this currently only support the tag import shorthand). | ||
if (item.type === NodeType.Statement && code[item.start] === "i") { | ||
importTagReg.lastIndex = 0; | ||
const value = parsed.read(item); | ||
const match = importTagReg.exec(value); | ||
if (match) { | ||
const [{ length }, , tagName] = match; | ||
const tagDef = lookup.getTag(tagName); | ||
const fileForTag = tagDef && (tagDef.template || tagDef.renderer); | ||
|
||
if (fileForTag) { | ||
links.push( | ||
DocumentLink.create( | ||
{ | ||
start: parsed.positionAt(item.start + match.index), | ||
end: parsed.positionAt(item.start + match.index + length), | ||
}, | ||
fileForTag | ||
) | ||
); | ||
} | ||
} | ||
} | ||
} | ||
|
||
for (const item of program.body) { | ||
visit(item); | ||
} | ||
|
||
return links; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import type { DocumentLink } from "vscode-languageserver"; | ||
import { getCompilerInfo, parse } from "../../../utils/compiler"; | ||
import type { Plugin } from "../../types"; | ||
import { extractDocumentLinks } from "./extract"; | ||
|
||
const cache = new WeakMap<ReturnType<typeof parse>, DocumentLink[]>(); | ||
|
||
export const findDocumentLinks: Plugin["findDocumentLinks"] = async (doc) => { | ||
const parsed = parse(doc); | ||
let result = cache.get(parsed); | ||
if (!result) { | ||
result = extractDocumentLinks(doc, parsed, getCompilerInfo(doc).lookup); | ||
cache.set(parsed, result); | ||
} | ||
return result; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { fileURLToPath } from "url"; | ||
|
||
export default function resolveUrl(ref: string, baseUrl: string) { | ||
const resolved = new URL(ref, new URL(baseUrl, "resolve://")); | ||
if (resolved.protocol === "resolve:") { | ||
// `baseUrl` is a relative URL. | ||
return resolved.pathname + resolved.search + resolved.hash; | ||
} | ||
|
||
try { | ||
return fileURLToPath(resolved); | ||
} catch { | ||
return undefined; | ||
} | ||
} |