LanguageService - bhsd-harry/wikiparser-node GitHub Wiki

目录

Other Languages

简介

LanguageService 对象由 Parser.createLanguageService 方法创建,用于语言服务。

以下所有属性和方法在 Mini 版本中均可用。

🌐 在 Browser 版本中可用。

Properties

include

🌐 展开

加入的版本:1.17.1

type: boolean
是否作为嵌入解析,默认为 true

// include
(async () => {
	var lsp = Parser.createLanguageService(),
		wikitext = `<includeonly>
{
</includeonly>`;
	assert.deepStrictEqual(
		await lsp.provideDiagnostics(wikitext),
		[
			{
				range: {
					start: {line: 1, character: 0},
					end: {line: 1, character: 1},
				},
				severity: 2,
				source: "WikiLint",
				code: "lonely-bracket",
				message: 'lonely "{"',
				data: [],
			},
		],
	);
	lsp.include = false;
	assert.deepStrictEqual(await lsp.provideDiagnostics(wikitext), []);
})();

lilypond

展开

type: string
LilyPond 路径。

Methods

destroy

🌐 展开

销毁实例。

returns: Promise<void>

// destroy
(async () => {
	var lsp = Parser.createLanguageService();
	await lsp.destroy();
	assert.strictEqual(lsp.provideDiagnostics, undefined);
})();

provideDocumentColors

🌐 展开

param: (s: string) => [number, number, number, number] | [] 解析颜色字符串的函数。
param: string 维基文本内容。
returns: Promise<ColorInformation[]>
列出文档中找到的所有颜色。

// provideDocumentColors
(async () => {
	const rgba = (await import("color-rgba")).default;
	const lsp = Parser.createLanguageService();
	assert.deepStrictEqual(
		await lsp.provideDocumentColors(
			rgba,
			'<p style="color: rgba(255, 0, 0, .7)">',
		),
		[
			{
				range: {
					start: {line: 0, character: 17},
					end: {line: 0, character: 36},
				},
				color: {red: 1, green: 0, blue: 0, alpha: 0.7},
			},
		],
	);
	assert.deepStrictEqual(
		await lsp.provideDocumentColors(
			rgba,
			'<poem style="color: #00ff00ff"/>',
		),
		[
			{
				range: {
					start: {line: 0, character: 20},
					end: {line: 0, character: 29},
				},
				color: {red: 0, green: 1, blue: 0, alpha: 1},
			},
		],
	);
	assert.deepStrictEqual(
		await lsp.provideDocumentColors(
			rgba,
			"{{#tag:font|color=#f000}}",
		),
		[
			{
				range: {
					start: {line: 0, character: 18},
					end: {line: 0, character: 23},
				},
				color: {red: 1, green: 0, blue: 0, alpha: 0},
			},
		],
	);
	assert.deepStrictEqual(
		await lsp.provideDocumentColors(
			rgba,
			"{{color|rgb(0 0 255 / 50%)}}",
		),
		[
			{
				range: {
					start: {line: 0, character: 8},
					end: {line: 0, character: 26},
				},
				color: {red: 0, green: 0, blue: 1, alpha: 0.5},
			},
		],
	);
	assert.deepStrictEqual(
		await lsp.provideDocumentColors(
			rgba,
			"{{color|1=hsla(0, 100%, 50%, 0.5)}}",
		),
		[
			{
				range: {
					start: {line: 0, character: 10},
					end: {line: 0, character: 33},
				},
				color: {red: 1, green: 0, blue: 0, alpha: 0.5},
			},
		],
	);
	assert.deepStrictEqual(
		await lsp.provideDocumentColors(
			rgba,
			"{{{|hsl(0deg 100 50)}}}",
		),
		[
			{
				range: {
					start: {line: 0, character: 4},
					end: {line: 0, character: 20},
				},
				color: {red: 1, green: 0, blue: 0, alpha: 1},
			},
		],
	);
})();
// provideDocumentColors (Node.js)
(async () => {
	const rgba = (await import("color-rgba")).default;
	const lsp = Parser.createLanguageService();
	assert.deepStrictEqual(
		await lsp.provideDocumentColors(
			rgba,
			'<p style="color:<!---->blue">',
		),
		[
			{
				range: {
					start: {line: 0, character: 23},
					end: {line: 0, character: 27},
				},
				color: {red: 0, green: 0, blue: 1, alpha: 1},
			},
		],
	);
	assert.deepStrictEqual(
		await lsp.provideDocumentColors(
			rgba,
			"{|style=color:red",
		),
		[
			{
				range: {
					start: {line: 0, character: 14},
					end: {line: 0, character: 17},
				},
				color: {red: 1, green: 0, blue: 0, alpha: 1},
			},
		],
	);
})();

provideColorPresentations

🌐 展开

param: ColorPresentationParams
returns: ColorPresentation[]
获取给定位置的颜色值。

// provideColorPresentations
var lsp = Parser.createLanguageService(),
	range = {
		start: {line: 0, character: 0},
		end: {line: 0, character: 1},
	};
assert.deepStrictEqual(
	lsp.provideColorPresentations({
		color: {red: 1, green: 0, blue: 0, alpha: 0.5},
		range,
	}),
	[
		{
			label: "rgba(255,0,0,0.5)",
			textEdit: {range, newText: "rgba(255,0,0,0.5)"},
		},
	],
);
assert.deepStrictEqual(
	lsp.provideColorPresentations({
		color: {red: 0, green: 0.9, blue: 0, alpha: 1},
		range,
	}),
	[
		{
			label: "#00e600",
			textEdit: {range, newText: "#00e600"},
		},
	],
);

provideCompletionItems

🌐 展开

param: string 维基文本内容。
param: Position
returns: Promise<CompletionItem[] | undefined>
计算给定光标位置的自动补全项。

// provideCompletionItems
(async () => {
	const lsp = Parser.createLanguageService();
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems("<Im", {line: 0, character: 3}))
			?.filter(({label}) => label.startsWith("im")),
		[
			{
				label: "imagemap",
				kind: "Class",
				textEdit: {
					range: {
						start: {line: 0, character: 1},
						end: {line: 0, character: 3},
					},
					newText: "imagemap",
				},
			},
			{
				label: "img",
				kind: "Class",
				textEdit: {
					range: {
						start: {line: 0, character: 1},
						end: {line: 0, character: 3},
					},
					newText: "img",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems("</Im", {line: 0, character: 4}))
			?.filter(({label}) => label.startsWith("im")),
		[
			{
				label: "imagemap",
				kind: "Class",
				textEdit: {
					range: {
						start: {line: 0, character: 2},
						end: {line: 0, character: 4},
					},
					newText: "imagemap>",
				},
			},
			{
				label: "img",
				kind: "Class",
				textEdit: {
					range: {
						start: {line: 0, character: 2},
						end: {line: 0, character: 4},
					},
					newText: "img>",
				},
			},
		],
	);
	assert.deepStrictEqual(
		await lsp.provideCompletionItems(
			"{{{ a }}}{{{1}}}",
			{line: 0, character: 5},
		),
		[
			{
				label: "1",
				kind: "Variable",
				textEdit: {
					range: {
						start: {line: 0, character: 4},
						end: {line: 0, character: 5},
					},
					newText: "1",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems(
			"[[ a ]][[:AA]]",
			{line: 0, character: 4},
		))?.filter(({label}) => /^a/iu.test(label)),
		[
			{
				label: "AA",
				kind: "Folder",
				textEdit: {
					range: {
						start: {line: 0, character: 3},
						end: {line: 0, character: 4},
					},
					newText: "AA",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems(
			"[[ : file : b ]][[ file : c | 100px ]]",
			{line: 0, character: 11},
		))?.filter(({label}) => /^file:/iu.test(label)),
		[
			{
				label: "File:C",
				kind: "Folder",
				textEdit: {
					range: {
						start: {line: 0, character: 5},
						end: {line: 0, character: 11},
					},
					newText: "File:C",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems(
			"{{ #Ifexp",
			{line: 0, character: 9},
		))?.filter(({label}) => /^#ifexp/iu.test(label))
			.map(({label, kind, textEdit}) => ({label, kind, textEdit})),
		[
			{
				label: "#ifexpr",
				kind: "Function",
				textEdit: {
					range: {
						start: {line: 0, character: 3},
						end: {line: 0, character: 9},
					},
					newText: "#ifexpr",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems(
			"{{ pagenamee }}{{PageNamee}}",
			{line: 0, character: 12},
		))?.filter(({label}) => /^pagenamee/iu.test(label))
			.map(({label, kind, textEdit}) => ({label, kind, textEdit})),
		[
			{
				label: "PAGENAMEE",
				kind: "Function",
				textEdit: {
					range: {
						start: {line: 0, character: 3},
						end: {line: 0, character: 12},
					},
					newText: "PAGENAMEE",
				},
			},
			{
				label: "PageNamee",
				kind: "Folder",
				textEdit: {
					range: {
						start: {line: 0, character: 3},
						end: {line: 0, character: 12},
					},
					newText: "PageNamee",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems("__T", {line: 0, character: 3}))
			?.filter(({label}) => /^__t/iu.test(label))
			.map(({label, kind, textEdit}) => ({label, kind, textEdit})),
		[
			{
				label: "__toc__",
				kind: "Constant",
				textEdit: {
					range: {
						start: {line: 0, character: 0},
						end: {line: 0, character: 3},
					},
					newText: "__toc__",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems("[Gi", {line: 0, character: 3}))
			?.filter(({label}) => label.startsWith("gi")),
		[
			{
				label: "git://",
				kind: "Reference",
				textEdit: {
					range: {
						start: {line: 0, character: 1},
						end: {line: 0, character: 3},
					},
					newText: "git://",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems(
			"[[ file : c | Thumbnail | 100x100px ]]",
			{line: 0, character: 20},
		))?.filter(({label}) => label.startsWith("thumbn")),
		[
			{
				label: "thumbnail",
				kind: "Property",
				textEdit: {
					range: {
						start: {line: 0, character: 14},
						end: {line: 0, character: 20},
					},
					newText: "thumbnail",
				},
			},
			{
				label: "thumbnail=",
				kind: "Property",
				textEdit: {
					range: {
						start: {line: 0, character: 14},
						end: {line: 0, character: 20},
					},
					newText: "thumbnail=",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems(
			`[[ file : c | Thumbnail | 100x100px ]]
[[ file : c | 100px ]]`,
			{line: 1, character: 15},
		))?.filter(({label}) => label.startsWith("1")),
		[
			{
				label: "100x100px",
				kind: "Unit",
				textEdit: {
					range: {
						start: {line: 1, character: 14},
						end: {line: 1, character: 15},
					},
					newText: "100x100px",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems("<poem C", {line: 0, character: 7}))
			?.filter(({label}) => label.startsWith("c")),
		[
			{
				label: "compact",
				kind: "Field",
				textEdit: {
					range: {
						start: {line: 0, character: 6},
						end: {line: 0, character: 7},
					},
					newText: "compact",
				},
			},
			{
				label: "class",
				kind: "Property",
				textEdit: {
					range: {
						start: {line: 0, character: 6},
						end: {line: 0, character: 7},
					},
					newText: "class",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems("<ref n", {line: 0, character: 6}))
			?.filter(({label}) => label.startsWith("n")),
		[
			{
				label: "name",
				kind: "Field",
				textEdit: {
					range: {
						start: {line: 0, character: 5},
						end: {line: 0, character: 6},
					},
					newText: "name",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems("<p Da", {line: 0, character: 5}))
			?.filter(({label}) => label.startsWith("da")),
		[
			{
				label: "datatype",
				kind: "Property",
				textEdit: {
					range: {
						start: {line: 0, character: 3},
						end: {line: 0, character: 5},
					},
					newText: "datatype",
				},
			},
			{
				label: "data-",
				kind: "Variable",
				textEdit: {
					range: {
						start: {line: 0, character: 3},
						end: {line: 0, character: 5},
					},
					newText: "data-",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems(
			"{{ c | ca= | CC = }}",
			{line: 0, character: 8},
		))?.filter(({label}) => /^c/iu.test(label)),
		[
			{
				label: "CC",
				kind: "Variable",
				textEdit: {
					range: {
						start: {line: 0, character: 7},
						end: {line: 0, character: 8},
					},
					newText: "CC",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems(
			'{| style="" dir=l',
			{line: 0, character: 5},
		))?.filter(({label}) => label.startsWith("st")),
		[
			{
				label: "style",
				kind: "Property",
				textEdit: {
					range: {
						start: {line: 0, character: 3},
						end: {line: 0, character: 5},
					},
					newText: "style",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems(
			'{| style="" dir=l',
			{line: 0, character: 17},
		))?.filter(({label}) => label.startsWith("l")),
		[
			{
				label: "ltr",
				kind: "Value",
				textEdit: {
					range: {
						start: {line: 0, character: 16},
						end: {line: 0, character: 17},
					},
					newText: "ltr",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems(
			"<inputbox>t</inputbox>",
			{line: 0, character: 11},
		))?.filter(({label}) => label.startsWith("t")),
		[
			{
				label: "type",
				kind: "Property",
				textEdit: {
					range: {
						start: {line: 0, character: 10},
						end: {line: 0, character: 11},
					},
					newText: "type",
				},
			},
			{
				label: "tour",
				kind: "Property",
				textEdit: {
					range: {
						start: {line: 0, character: 10},
						end: {line: 0, character: 11},
					},
					newText: "tour",
				},
			},
		],
	);
})();
// provideCompletionItems (Node.js)
(async () => {
	const lsp = Parser.createLanguageService();
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems(
			"<p style=user-select:none;us>",
			{line: 0, character: 11},
		))?.filter(({label}) => label.startsWith("us"))
			.map(({label, kind, textEdit}) => ({label, kind, textEdit})),
		[
			{
				label: "user-select",
				kind: 10,
				textEdit: {
					range: {
						start: {line: 0, character: 9},
						end: {line: 0, character: 20},
					},
					newText: "user-select",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems(
			"<p style=user-select:none;us>",
			{line: 0, character: 28},
		))?.filter(({label}) => label.startsWith("us"))
			.map(({label, kind, textEdit}) => ({label, kind, textEdit})),
		[
			{
				label: "user-select",
				kind: 10,
				textEdit: {
					range: {
						start: {line: 0, character: 26},
						end: {line: 0, character: 28},
					},
					newText: "user-select:$0;",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems(
			"<p style=user-select:none;us>",
			{line: 0, character: 21},
		))?.filter(({label}) => label.startsWith("n"))
			.map(({label, kind, textEdit}) => ({label, kind, textEdit})),
		[
			{
				label: "none",
				kind: 12,
				textEdit: {
					range: {
						start: {line: 0, character: 21},
						end: {line: 0, character: 25},
					},
					newText: "none",
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems(
			'<templatedata>{"d":""}</templatedata>',
			{line: 0, character: 17},
		))?.filter(({label}) => label.startsWith("d"))
			.map(({label, kind, textEdit}) => ({label, kind, textEdit})),
		[
			{
				label: "description",
				kind: 10,
				textEdit: {
					range: {
						start: {line: 0, character: 15},
						end: {line: 0, character: 18},
					},
					newText: '"description"',
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems("__T", {line: 0, character: 3}))
			?.filter(({label}) => /^__t/iu.test(label)),
		[
			{
				label: "__toc__",
				kind: "Constant",
				textEdit: {
					range: {
						start: {line: 0, character: 0},
						end: {line: 0, character: 3},
					},
					newText: "__toc__",
				},
				documentation: {
					kind: "markdown",
					value: `Places a table of contents at the word's current position (overriding \`__NOTOC__\`). If this is used multiple times, the table of contents will appear at the first word's position.`,
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems(
			"{{ #Ifexp",
			{line: 0, character: 9},
		))?.filter(({label}) => /^#ifexp/iu.test(label)),
		[
			{
				label: "#ifexpr",
				kind: "Function",
				textEdit: {
					range: {
						start: {line: 0, character: 3},
						end: {line: 0, character: 9},
					},
					newText: "#ifexpr",
				},
				documentation: {
					kind: "markdown",
					value: `This function evaluates a mathematical expression and returns one of two strings depending on the boolean value of the result.

The \`expression\` input is evaluated exactly as for \`#expr\`, with the same operators being available. The output is then evaluated as a boolean expression.

An empty input expression evaluates to \`false\`.

An empty or wrong input expression (an error message is treated as an empty string; it is not equal to zero, so we get \`value if true\`).`,
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems(
			String.raw`<score>\rel</score>`,
			{line: 0, character: 11},
		))?.filter(({label}) => /^\\rel/iu.test(label)),
		[
			{
				label: String.raw`\relative`,
				kind: "Function",
				textEdit: {
					range: {
						start: {line: 0, character: 7},
						end: {line: 0, character: 11},
					},
					newText: String.raw`\relative`,
				},
			},
		],
	);
	assert.deepStrictEqual(
		(await lsp.provideCompletionItems(
			String.raw`<math chem>\ce</math>`,
			{line: 0, character: 14},
		))?.filter(({label}) => /^\\ce/iu.test(label)),
		[
			{
				label: String.raw`\ce`,
				kind: "Function",
				textEdit: {
					range: {
						start: {line: 0, character: 11},
						end: {line: 0, character: 14},
					},
					newText: String.raw`\ce`,
				},
			},
			{
				label: String.raw`\centerdot`,
				kind: "Function",
				textEdit: {
					range: {
						start: {line: 0, character: 11},
						end: {line: 0, character: 14},
					},
					newText: String.raw`\centerdot`,
				},
			},
		],
	);
})();

provideFoldingRanges

🌐 展开

param: string 维基文本内容。
returns: Promise<FoldingRange[]>
返回在给定文档中找到的所有折叠范围。

// provideFoldingRanges
(async () => {
	const lsp = Parser.createLanguageService(),
		wikitext = `
<!--

-->= 1 =

<!-- -->

<!-- -->== 2 ==



===== 3 ===== <!--

--> 

x {{a|
====== 4_<!--
-->2 ====== 
y }} z

== 4 ==


= 4 =

 : {|
|
=== 4 ===
 |} x

`;
	assert.deepStrictEqual(
		await lsp.provideFoldingRanges(wikitext),
		[
			{startLine: 15, endLine: 17, kind: "region"},
			{startLine: 7, endLine: 19, kind: "region"},
			{startLine: 11, endLine: 19, kind: "region"},
			{startLine: 17, endLine: 19, kind: "region"},
			{startLine: 3, endLine: 22, kind: "region"},
			{startLine: 20, endLine: 22, kind: "region"},
			{startLine: 25, endLine: 27, kind: "region"},
			{startLine: 23, endLine: 30, kind: "region"},
			{startLine: 27, endLine: 30, kind: "region"},
		],
	);
})();
// provideFoldingRanges (Node.js)
(async () => {
	const lsp = Parser.createLanguageService(),
		wikitext = `
<templatedata>{
	"paramOrder": [
		"a",
		"b"
	]
}</templatedata>`;
	assert.deepStrictEqual(
		await lsp.provideFoldingRanges(wikitext),
		[
			{startLine: 2, endLine: 4, kind: "array"},
			{startLine: 1, endLine: 5, kind: "object"},
		],
	);
})();

provideLinks

🌐 展开

param: string 维基文本内容。
returns: Promise<DocumentLink[]>
请求文档中链接的位置。

// provideLinks
(async () => {
	const lsp = Parser.createLanguageService(),
		wikitext = `
[[ : help : a#a ]]
{{ b }}
{{ #invoke: c | c }}
RFC 1
PMID 1
ISBN 1-2-3-4-5-6-7-8-9-0
[//d d]
News:e
<templatestyles src = f />
<q cite = "HTTPS://G/G">
[[file:a|link=a]]
[[file:a|link=//a]]
{{filepath: h }}
`,
		results = [
			{
				range: {
					start: {line: 1, character: 2},
					end: {line: 1, character: 16},
				},
				target: "https://mediawiki.org/wiki/Help%3AA#a",
			},
			{
				range: {
					start: {line: 2, character: 2},
					end: {line: 2, character: 5},
				},
				target: "https://mediawiki.org/wiki/Template%3AB",
			},
			{
				range: {
					start: {line: 3, character: 11},
					end: {line: 3, character: 14},
				},
				target: "https://mediawiki.org/wiki/Module%3AC",
			},
			{
				range: {
					start: {line: 4, character: 0},
					end: {line: 4, character: 5},
				},
				target: "https://datatracker.ietf.org/doc/html/rfc1",
			},
			{
				range: {
					start: {line: 5, character: 0},
					end: {line: 5, character: 6},
				},
				target: "https://pubmed.ncbi.nlm.nih.gov/1",
			},
			{
				range: {
					start: {line: 6, character: 0},
					end: {line: 6, character: 24},
				},
				// eslint-disable-next-line @stylistic/max-len
				target: "https://mediawiki.org/wiki/Special%3ABookSources%2F1234567890",
			},
			{
				range: {
					start: {line: 7, character: 1},
					end: {line: 7, character: 4},
				},
				target: "https://d/",
			},
			{
				range: {
					start: {line: 8, character: 0},
					end: {line: 8, character: 6},
				},
				target: "news:e",
			},
			{
				range: {
					start: {line: 9, character: 22},
					end: {line: 9, character: 23},
				},
				target: "https://mediawiki.org/wiki/Template%3AF",
			},
			{
				range: {
					start: {line: 10, character: 11},
					end: {line: 10, character: 22},
				},
				target: "https://g/G",
			},
			{
				range: {
					start: {line: 11, character: 2},
					end: {line: 11, character: 8},
				},
				target: "https://mediawiki.org/wiki/File%3AA",
			},
			{
				range: {
					start: {line: 11, character: 14},
					end: {line: 11, character: 15},
				},
				target: "https://mediawiki.org/wiki/A",
			},
			{
				range: {
					start: {line: 12, character: 2},
					end: {line: 12, character: 8},
				},
				target: "https://mediawiki.org/wiki/File%3AA",
			},
			{
				range: {
					start: {line: 12, character: 14},
					end: {line: 12, character: 17},
				},
				target: "https://a/",
			},
			{
				range: {
					start: {line: 13, character: 11},
					end: {line: 13, character: 14},
				},
				target: "https://mediawiki.org/wiki/File%3AH",
			},
		].reverse();
	Parser.getConfig();
	Parser.config.articlePath = "https://mediawiki.org/wiki/$1";
	assert.deepStrictEqual(await lsp.provideLinks(wikitext), results);
	Parser.config.articlePath = "https://mediawiki.org/wiki/";
	assert.deepStrictEqual(await lsp.provideLinks(wikitext), results);
	Parser.config.articlePath = "https://mediawiki.org/wiki";
	assert.deepStrictEqual(await lsp.provideLinks(wikitext), results);
	Parser.config.articlePath = "//mediawiki.org/wiki/$1";
	assert.deepStrictEqual(await lsp.provideLinks(wikitext), results);
})();

provideReferences

🌐 展开

param: string 维基文本内容。
param: Position
returns: Promise<Omit<Location, 'uri'>[] | undefined>
找出文档给定位置处符号的引用。

// provideReferences
(async () => {
	const lsp = Parser.createLanguageService();
	assert.deepStrictEqual(
		await lsp.provideReferences(
			`{{{ a }}}
{{{a|}}}`,
			{line: 0, character: 4},
		),
		[
			{
				range: {
					start: {line: 0, character: 3},
					end: {line: 0, character: 6},
				},
			},
			{
				range: {
					start: {line: 1, character: 3},
					end: {line: 1, character: 4},
				},
			},
		].reverse(),
	);
	assert.deepStrictEqual(
		await lsp.provideReferences(
			`{{ b }}
{{ : template : b |b=}}`,
			{line: 0, character: 4},
		),
		[
			{
				range: {
					start: {line: 0, character: 2},
					end: {line: 0, character: 5},
				},
			},
			{
				range: {
					start: {line: 1, character: 2},
					end: {line: 1, character: 18},
				},
			},
		].reverse(),
	);
	assert.deepStrictEqual(
		await lsp.provideReferences(
			`{{ PAGENAME }}
{{PAGENAME:c}}`,
			{line: 0, character: 4},
		),
		[
			{
				range: {
					start: {line: 0, character: 2},
					end: {line: 0, character: 12},
				},
			},
			{
				range: {
					start: {line: 1, character: 2},
					end: {line: 1, character: 10},
				},
			},
		].reverse(),
	);
	assert.deepStrictEqual(
		await lsp.provideReferences(
			`[[ file : d | thumb ]]
[[ :file:d ]]`,
			{line: 0, character: 4},
		),
		[
			{
				range: {
					start: {line: 0, character: 2},
					end: {line: 0, character: 12},
				},
			},
			{
				range: {
					start: {line: 1, character: 2},
					end: {line: 1, character: 11},
				},
			},
		].reverse(),
	);
	assert.deepStrictEqual(
		await lsp.provideReferences(
			`{{ e | e = }}
{{Template:E|e=}}`,
			{line: 0, character: 8},
		),
		[
			{
				range: {
					start: {line: 0, character: 6},
					end: {line: 0, character: 11},
				},
			},
			{
				range: {
					start: {line: 1, character: 13},
					end: {line: 1, character: 15},
				},
			},
		].reverse(),
	);
	assert.deepStrictEqual(
		await lsp.provideReferences(
			`<ref group = f name = f > </ref>
<ref group = " f " follow = ' f ' />`,
			{line: 0, character: 4},
		),
		[
			{
				range: {
					start: {line: 0, character: 0},
					end: {line: 0, character: 32},
				},
			},
			{
				range: {
					start: {line: 1, character: 0},
					end: {line: 1, character: 36},
				},
			},
		].reverse(),
	);
	assert.deepStrictEqual(
		await lsp.provideReferences(
			"<b ></b>",
			{line: 0, character: 2},
		),
		[
			{
				range: {
					start: {line: 0, character: 0},
					end: {line: 0, character: 4},
				},
			},
			{
				range: {
					start: {line: 0, character: 4},
					end: {line: 0, character: 8},
				},
			},
		].reverse(),
	);
	assert.deepStrictEqual(
		await lsp.provideReferences(
			`<ref group = f name = f > </ref>
<ref group = " f " follow = ' f ' />
<references group = f />`,
			{line: 0, character: 6},
		),
		[
			{
				range: {
					start: {line: 0, character: 5},
					end: {line: 0, character: 10},
				},
			},
			{
				range: {
					start: {line: 1, character: 5},
					end: {line: 1, character: 10},
				},
			},
			{
				range: {
					start: {line: 2, character: 12},
					end: {line: 2, character: 17},
				},
			},
		].reverse(),
	);
	assert.deepStrictEqual(
		await lsp.provideReferences(
			`[[ file : d | thumb ]]
[[file:g|thumbnail]]`,
			{line: 1, character: 10},
		),
		[
			{
				range: {
					start: {line: 0, character: 13},
					end: {line: 0, character: 20},
				},
			},
			{
				range: {
					start: {line: 1, character: 9},
					end: {line: 1, character: 18},
				},
			},
		].reverse(),
	);
	assert.deepStrictEqual(
		await lsp.provideReferences(
			`== h ==
== i ==`,
			{line: 0, character: 4},
		),
		[
			{
				range: {
					start: {line: 0, character: 0},
					end: {line: 0, character: 7},
				},
			},
			{
				range: {
					start: {line: 1, character: 0},
					end: {line: 1, character: 7},
				},
			},
		].reverse(),
	);
	assert.deepStrictEqual(
		await lsp.provideReferences(
			`== h ==
== i ==`,
			{line: 0, character: 1},
		),
		[
			{
				range: {
					start: {line: 0, character: 0},
					end: {line: 0, character: 7},
				},
			},
			{
				range: {
					start: {line: 1, character: 0},
					end: {line: 1, character: 7},
				},
			},
		].reverse(),
	);
	assert.deepStrictEqual(
		await lsp.provideReferences(
			`<ref group = f name = f > </ref>
<ref group = " f " follow = ' f ' />`,
			{line: 0, character: 23},
		),
		[
			{
				range: {
					start: {line: 0, character: 22},
					end: {line: 0, character: 23},
				},
			},
			{
				range: {
					start: {line: 1, character: 29},
					end: {line: 1, character: 32},
				},
			},
		].reverse(),
	);
	assert.deepStrictEqual(
		await lsp.provideReferences(
			`<ref group = f name = f > </ref>
<ref group = " f " follow = ' f ' />
<references group = f />`,
			{line: 0, character: 14},
		),
		[
			{
				range: {
					start: {line: 0, character: 13},
					end: {line: 0, character: 14},
				},
			},
			{
				range: {
					start: {line: 1, character: 14},
					end: {line: 1, character: 17},
				},
			},
			{
				range: {
					start: {line: 2, character: 20},
					end: {line: 2, character: 21},
				},
			},
		].reverse(),
	);
})();

provideDefinition

🌐 展开

param: string 维基文本内容。
param: Position
returns: Promise<Omit<Location, 'uri'>[] | undefined>
找出文档给定位置处符号的定义。

// provideDefinition
(async () => {
	const lsp = Parser.createLanguageService(),
		wikitext = `
<ref group = f name = f > </ref>
<ref name = f > </ref>
<ref name = ' f ' />
`;
	assert.deepStrictEqual(
		await lsp.provideDefinition(wikitext, {line: 3, character: 14}),
		[
			{
				range: {
					start: {line: 2, character: 15},
					end: {line: 2, character: 16},
				},
			},
		],
	);
})();

resolveRenameLocation

🌐 展开

param: string 维基文本内容。
param: Position
returns: Promise<Range | undefined>
测试给定位置的变量更名操作的有效性。

// resolveRenameLocation
(async () => {
	const lsp = Parser.createLanguageService();
	assert.deepStrictEqual(
		await lsp.resolveRenameLocation("{{{ a }}}", {line: 0, character: 4}),
		{
			start: {line: 0, character: 3},
			end: {line: 0, character: 6},
		},
	);
	assert.deepStrictEqual(
		await lsp.resolveRenameLocation("{{ b }}", {line: 0, character: 4}),
		{
			start: {line: 0, character: 2},
			end: {line: 0, character: 5},
		},
	);
	assert.deepStrictEqual(
		await lsp.resolveRenameLocation(
			"[[ :file:d ]]",
			{line: 0, character: 4},
		),
		{
			start: {line: 0, character: 2},
			end: {line: 0, character: 11},
		},
	);
	assert.deepStrictEqual(
		await lsp.resolveRenameLocation(
			"{{ e | e = }}",
			{line: 0, character: 8},
		),
		{
			start: {line: 0, character: 6},
			end: {line: 0, character: 9},
		},
	);
	assert.deepStrictEqual(
		await lsp.resolveRenameLocation(
			"<ref group = f name = f > </ref>",
			{line: 0, character: 23},
		),
		{
			start: {line: 0, character: 22},
			end: {line: 0, character: 23},
		},
	);
	assert.deepStrictEqual(
		await lsp.resolveRenameLocation(
			"<ref group = f name = f > </ref>",
			{line: 0, character: 14},
		),
		{
			start: {line: 0, character: 13},
			end: {line: 0, character: 14},
		},
	);
})();

provideRenameEdits

🌐 展开

param: string 维基文本内容。
param: Position
param: string 新的变量名。
returns: Promise<WorkspaceEdit | undefined>
计算对符号进行文档范围重命名的更改。

// provideRenameEdits
(async () => {
	const lsp = Parser.createLanguageService();
	assert.deepStrictEqual(
		await lsp.provideRenameEdits(
			`{{{ a }}}
{{{a|}}}`,
			{line: 0, character: 4},
			"x",
		),
		{
			changes: {
				"": [
					{
						range: {
							start: {line: 0, character: 3},
							end: {line: 0, character: 6},
						},
						newText: "x",
					},
					{
						range: {
							start: {line: 1, character: 3},
							end: {line: 1, character: 4},
						},
						newText: "x",
					},
				].reverse(),
			},
		},
	);
	assert.deepStrictEqual(
		await lsp.provideRenameEdits(
			`{{ b }}
{{ : template : b |b=}}`,
			{line: 0, character: 4},
			"x",
		),
		{
			changes: {
				"": [
					{
						range: {
							start: {line: 0, character: 2},
							end: {line: 0, character: 5},
						},
						newText: "x",
					},
					{
						range: {
							start: {line: 1, character: 2},
							end: {line: 1, character: 18},
						},
						newText: "x",
					},
				].reverse(),
			},
		},
	);
	assert.deepStrictEqual(
		await lsp.provideRenameEdits(
			`[[ :file:d ]]
[[ file : d | thumb ]]`,
			{line: 0, character: 4},
			"x",
		),
		{
			changes: {
				"": [
					{
						range: {
							start: {line: 0, character: 2},
							end: {line: 0, character: 11},
						},
						newText: "x",
					},
				],
			},
		},
	);
	assert.deepStrictEqual(
		await lsp.provideRenameEdits(
			`{{ e | e = }}
{{Template:E|e=}}`,
			{line: 0, character: 8},
			"x",
		),
		{
			changes: {
				"": [
					{
						range: {
							start: {line: 0, character: 6},
							end: {line: 0, character: 9},
						},
						newText: "x",
					},
					{
						range: {
							start: {line: 1, character: 13},
							end: {line: 1, character: 14},
						},
						newText: "x",
					},
				].reverse(),
			},
		},
	);

	// 以下内容需要站点配置启用Extension:Cite
	assert.ok(Parser.getConfig().ext.includes("ref"));
	assert.deepStrictEqual(
		await lsp.provideRenameEdits(
			`<ref group = f name = f > </ref>
<ref group = " f " follow = ' f ' /><ref name=f/>`,
			{line: 0, character: 23},
			"x",
		),
		{
			changes: {
				"": [
					{
						range: {
							start: {line: 0, character: 22},
							end: {line: 0, character: 23},
						},
						newText: "x",
					},
					{
						range: {
							start: {line: 1, character: 29},
							end: {line: 1, character: 32},
						},
						newText: "x",
					},
				].reverse(),
			},
		},
	);
	assert.deepStrictEqual(
		await lsp.provideRenameEdits(
			`<ref group = f name = f > </ref>
<ref group = " f " follow = ' f ' /><ref name=f/>
<references group = f />`,
			{line: 0, character: 14},
			"x",
		),
		{
			changes: {
				"": [
					{
						range: {
							start: {line: 0, character: 13},
							end: {line: 0, character: 14},
						},
						newText: "x",
					},
					{
						range: {
							start: {line: 1, character: 14},
							end: {line: 1, character: 17},
						},
						newText: "x",
					},
					{
						range: {
							start: {line: 2, character: 20},
							end: {line: 2, character: 21},
						},
						newText: "x",
					},
				].reverse(),
			},
		},
	);
})();

provideDiagnostics

🌐 展开

param: string 维基文本内容。
param: boolean 是否包含警告。
returns: Promise<Diagnostic[]>
对给定文档进行语法诊断。

// provideDiagnostics
(async () => {
	const lsp = Parser.createLanguageService();
	assert.deepStrictEqual(
		await lsp.provideDiagnostics("http://a]"),
		[
			{
				range: {
					start: {line: 0, character: 8},
					end: {line: 0, character: 9},
				},
				severity: 1,
				source: "WikiLint",
				code: "lonely-bracket",
				message: 'lonely "]"',
				data: [
					{
						range: {
							start: {line: 0, character: 0},
							end: {line: 0, character: 0},
						},
						newText: "[",
						title: "Suggestion: opening bracket",
						fix: false,
					},
				],
			},
		],
	);
	assert.deepStrictEqual(
		await lsp.provideDiagnostics("</br>"),
		[
			{
				range: {
					start: {line: 0, character: 0},
					end: {line: 0, character: 5},
				},
				severity: 1,
				source: "WikiLint",
				code: "unmatched-tag",
				message: "tag that is both closing and self-closing",
				data: [
					{
						range: {
							start: {line: 0, character: 1},
							end: {line: 0, character: 2},
						},
						newText: "",
						title: "Fix: open",
						fix: true,
					},
				],
			},
		],
	);
	assert.deepStrictEqual(
		await lsp.provideDiagnostics("["),
		[
			{
				range: {
					start: {line: 0, character: 0},
					end: {line: 0, character: 1},
				},
				severity: 2,
				source: "WikiLint",
				code: "lonely-bracket",
				message: 'lonely "["',
				data: [],
			},
		],
	);
	assert.deepStrictEqual(
		await lsp.provideDiagnostics("[", false),
		[],
	);
})();
// provideDiagnostics (Node.js)
var {execSync} = require("child_process");
(async () => {
	const lsp = Parser.createLanguageService();
	assert.deepStrictEqual(
		await lsp.provideDiagnostics("<templatedata>a</templatedata>"),
		[
			{
				range: {
					start: {line: 0, character: 14},
					end: {line: 0, character: 15},
				},
				severity: 1,
				source: "json",
				code: 0,
				message: "Expected a JSON object, array or literal.",
			},
		],
	);
	assert.deepStrictEqual(
		await lsp.provideDiagnostics(`<mapframe width=300 height=300>[
0, // comment
]</mapframe>`),
		[
			{
				range: {
					start: {line: 1, character: 0},
					end: {line: 1, character: 1},
				},
				severity: 2,
				source: "json",
				message: 'Incorrect type. Expected "object".',
			},
			{
				range: {
					start: {line: 1, character: 0},
					end: {line: 1, character: 1},
				},
				severity: 2,
				source: "json",
				message:
					"Matches multiple schemas when only one must validate.",
			},
		],
	);
	assert.deepStrictEqual(
		await lsp.provideDiagnostics(`<maplink width=300 height=300>{
"type":"Point",
"type":"Feature"
}</maplink>`),
		[
			{
				range: {
					start: {line: 1, character: 0},
					end: {line: 1, character: 6},
				},
				severity: 2,
				source: "json",
				code: 520,
				message: "Duplicate object key",
			},
			{
				range: {
					start: {line: 2, character: 0},
					end: {line: 2, character: 6},
				},
				severity: 2,
				source: "json",
				code: 520,
				message: "Duplicate object key",
			},
			{
				range: {
					start: {line: 0, character: 30},
					end: {line: 0, character: 31},
				},
				severity: 2,
				source: "json",
				message: 'Missing property "geometry".',
			},
		].reverse(),
	);
	assert.deepStrictEqual(
		await lsp.provideDiagnostics('<poem style="-moz-border-radius:0"/>'),
		[
			{
				range: {
					start: {line: 0, character: 13},
					end: {line: 0, character: 31},
				},
				severity: 2,
				source: "css",
				code: "vendorPrefix",
				message: `Also define the standard property 'border-radius' for compatibility`,
				data: [],
			},
		],
	);
	assert.deepStrictEqual(
		await lsp.provideDiagnostics("<br style=left:0;left:1>"),
		[
			{
				range: {
					start: {line: 0, character: 10},
					end: {line: 0, character: 14},
				},
				severity: 1,
				source: "Stylelint",
				code: "declaration-block-no-duplicate-properties",
				message: 'Duplicate property "left"',
				data: [
					{
						range: {
							start: {line: 0, character: 10},
							end: {line: 0, character: 17},
						},
						newText: "",
						title: "Fix: declaration-block-no-duplicate-properties",
						fix: true,
					},
				],
			},
			{
				range: {
					start: {line: 0, character: 22},
					end: {line: 0, character: 23},
				},
				severity: 1,
				source: "Stylelint",
				code: "declaration-property-value-no-unknown",
				message: 'Unknown value "1" for property "left"',
			},
		],
	);
	assert.deepStrictEqual(
		await lsp.provideDiagnostics(
			String.raw`<math>#</math>
<chem>
\frac{a}
</chem>
<math>
\begin{matrix} a \\ b
</math>
<math>\ce{H}</math>
<ce>\x</ce>`,
		),
		[
			{
				range: {
					start: {line: 0, character: 6},
					end: {line: 0, character: 7},
				},
				severity: 1,
				source: "texvc",
				code: "invalid-math",
				message:
					String.raw`Expected "\\", "\\begin", "\\begin{", "]", "^", "_", "{", "}", [ \t\n\r], [!'*-\-0-;=?A-Za-z], [%$], [(-).-/[|], or [><~] but "#" found.`,
				data: [],
			},
			{
				range: {
					start: {line: 3, character: 0},
					end: {line: 3, character: 0},
				},
				severity: 1,
				source: "texvc",
				code: "invalid-math",
				message:
					String.raw`Expected "\\", "\\begin", "\\begin{", "{", [ \t\n\r], [!'*-\-0-;=?A-Za-z], [%$], [(-).-/[|], or [><~] but "}" found.`,
				data: [],
			},
			{
				range: {
					start: {line: 5, character: 0},
					end: {line: 5, character: 14},
				},
				severity: 1,
				source: "texvc",
				code: "invalid-math",
				message: "Illegal TeX function",
				data: [],
			},
			{
				range: {
					start: {line: 7, character: 6},
					end: {line: 7, character: 12},
				},
				severity: 1,
				source: "texvc",
				code: "invalid-math",
				message: "chem attribute required",
				data: [],
			},
			{
				range: {
					start: {line: 8, character: 4},
					end: {line: 8, character: 6},
				},
				severity: 1,
				source: "texvc",
				code: "invalid-math",
				message: "Illegal TeX function",
				data: [],
			},
		],
	);
	try {
		lsp.lilypond = execSync("which lilypond", {encoding: "utf8"}).trim();
		assert.deepStrictEqual(
			await lsp.provideDiagnostics("<score raw>{ c'4 e'5 g' }</score>"),
			[
				{
					range: {
						start: {line: 0, character: 19},
						end: {line: 0, character: 19},
					},
					severity: 1,
					source: "LilyPond",
					message: "not a duration",
				},
			],
		);
		assert.deepStrictEqual(
			await lsp.provideDiagnostics(String.raw`<score>\score {
\relative c'
}</score>`),
			[
				{
					range: {
						start: {line: 0, character: 7},
						end: {line: 0, character: 7},
					},
					severity: 1,
					source: "LilyPond",
					message: String.raw`Missing music in \score`,
				},
				{
					range: {
						start: {line: 0, character: 7},
						end: {line: 0, character: 7},
					},
					severity: 1,
					source: "LilyPond",
					message: String.raw`syntax error, unexpected \score, expecting '}'`,
				},
			],
		);
	} catch (e) {
		if (e instanceof assert.AssertionError) {
			throw e;
		}
	}
})();

provideHover

🌐 展开

param: string 维基文本内容。
param: Position
returns: Promise<Hover | undefined>
在给定文档位置请求悬停信息。

// provideHover (Node.js)
(async () => {
	const lsp = Parser.createLanguageService();
	assert.deepStrictEqual(
		await lsp.provideHover("__NOTOC__", {line: 0, character: 0}),
		{
			contents: {
				kind: "markdown",
				value: "Hides the table of contents (TOC).",
			},
			range: {
				start: {line: 0, character: 0},
				end: {line: 0, character: 9},
			},
		},
	);
	assert.deepStrictEqual(
		await lsp.provideHover("{{ #LEN: }}", {line: 0, character: 2}),
		{
			contents: {
				kind: "markdown",
				value: `- **{{ #LEN:** *string* **}}**

The #len function returns the length of the given string.`,
			},
			range: {
				start: {line: 0, character: 2},
				end: {line: 0, character: 7},
			},
		},
	);
	assert.deepStrictEqual(
		await lsp.provideHover(
			"{{ subst: NUMBEROFPAGES }}",
			{line: 0, character: 10},
		),
		{
			contents: {
				kind: "markdown",
				value: `- **{{ NUMBEROFPAGES** **}}**
- **{{ NUMBEROFPAGES:** R **}}**

Number of wiki pages.`,
			},
			range: {
				start: {line: 0, character: 10},
				end: {line: 0, character: 24},
			},
		},
	);
	assert.deepStrictEqual(
		await lsp.provideHover(
			"{{ subst: NUMBEROFPAGES }}",
			{line: 0, character: 2},
		),
		{
			contents: {
				kind: "markdown",
				value: `- **{{ subst:** *xyz* **}}**

In the wikitext, the tag is substituted by the content (single-level evaluation only), see [Help:Templates](https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Templates#Usage).`,
			},
			range: {
				start: {line: 0, character: 2},
				end: {line: 0, character: 8},
			},
		},
	);
	assert.deepStrictEqual(
		await lsp.provideHover("{{ = }}", {line: 0, character: 0}),
		{
			contents: {
				kind: "markdown",
				value: `Used to include an equal sign.

See [help](https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Extension:ParserFunctions#Raw_equal_signs) for further explanation.`,
			},
			range: {
				start: {line: 0, character: 0},
				end: {line: 0, character: 7},
			},
		},
	);
	assert.deepStrictEqual(
		await lsp.provideHover(
			"<p style=box-sizing:border-box>",
			{line: 0, character: 11},
		),
		{
			contents: {
				kind: "markdown",
				value: String.raw`Specifies the behavior of the 'width' and 'height' properties\.

![Baseline icon](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTgiIGhlaWdodD0iMTAiIHZpZXdCb3g9IjAgMCA1NDAgMzAwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxzdHlsZT4KICAgIC5ncmVlbi1zaGFwZSB7CiAgICAgIGZpbGw6ICNDNEVFRDA7IC8qIExpZ2h0IG1vZGUgKi8KICAgIH0KCiAgICBAbWVkaWEgKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKSB7CiAgICAgIC5ncmVlbi1zaGFwZSB7CiAgICAgICAgZmlsbDogIzEyNTIyNTsgLyogRGFyayBtb2RlICovCiAgICAgIH0KICAgIH0KICA8L3N0eWxlPgogIDxwYXRoIGQ9Ik00MjAgMzBMMzkwIDYwTDQ4MCAxNTBMMzkwIDI0MEwzMzAgMTgwTDMwMCAyMTBMMzkwIDMwMEw1NDAgMTUwTDQyMCAzMFoiIGNsYXNzPSJncmVlbi1zaGFwZSIvPgogIDxwYXRoIGQ9Ik0xNTAgMEwzMCAxMjBMNjAgMTUwTDE1MCA2MEwyMTAgMTIwTDI0MCA5MEwxNTAgMFoiIGNsYXNzPSJncmVlbi1zaGFwZSIvPgogIDxwYXRoIGQ9Ik0zOTAgMEw0MjAgMzBMMTUwIDMwMEwwIDE1MEwzMCAxMjBMMTUwIDI0MEwzOTAgMFoiIGZpbGw9IiMxRUE0NDYiLz4KPC9zdmc+) _Widely available across major browsers (Baseline since 2015)_

Syntax: content\-box | border\-box

[MDN Reference](https://developer.mozilla.org/docs/Web/CSS/Reference/Properties/box-sizing)`,
			},
			range: {
				start: {line: 0, character: 9},
				end: {line: 0, character: 30},
			},
		},
	);
	assert.deepStrictEqual(
		await lsp.provideHover(
			'<templatedata>{"description":null}</templatedata>',
			{line: 0, character: 17},
		),
		{
			contents: [`A brief description of the template. **It must be in plain text.** Once filled, it can be displayed as caption when editing a single template and perhaps in search results when users pick one of many. The default is \`null\`.`],
			range: {
				start: {line: 0, character: 15},
				end: {line: 0, character: 28},
			},
		},
	);
	assert.deepStrictEqual(
		await lsp.provideHover(
			"<p style=box-sizing:border-box>",
			{line: 0, character: 1},
		),
		{
			contents: {
				kind: "markdown",
				value: "The p element represents a paragraph.",
			},
			range: {
				start: {line: 0, character: 0},
				end: {line: 0, character: 2},
			},
		},
	);
	assert.deepStrictEqual(
		await lsp.provideHover(
			"<p style=box-sizing:border-box>",
			{line: 0, character: 3},
		),
		{
			contents: {
				kind: "markdown",
				value: `Contains [CSS](https://developer.mozilla.org/docs/Web/CSS) styling declarations to be applied to the element. Note that it is recommended for styles to be defined in a separate file or files. This attribute and the [\`<style>\`](https://developer.mozilla.org/docs/Web/HTML/Element/style "The HTML <style> element contains style information for a document, or part of a document.") element have mainly the purpose of allowing for quick styling, for example for testing purposes.`,
			},
			range: {
				start: {line: 0, character: 3},
				end: {line: 0, character: 8},
			},
		},
	);
})();

provideSignatureHelp

🌐 展开

param: string 维基文本内容。
param: Position
returns: Promise<SignatureHelp | undefined>
在给定光标位置请求魔术字的签名信息。

// provideSignatureHelp (Node.js)
(async () => {
	const lsp = Parser.createLanguageService();
	assert.deepStrictEqual(
		await lsp.provideSignatureHelp(
			"{{ #invoke: a | b | c | d }}",
			{line: 0, character: 12},
		),
		{
			signatures: [
				{
					label: "{{#invoke:module name|function name|args}}",
					parameters: [
						{label: "module name"},
						{label: "function name"},
						{label: "args"},
					],
					activeParameter: 0,
				},
			],
			activeParameter: 0,
		},
	);
	assert.deepStrictEqual(
		await lsp.provideSignatureHelp(
			"{{ #invoke: a | b | c | d }}",
			{line: 0, character: 16},
		),
		{
			signatures: [
				{
					label: "{{#invoke:module name|function name|args}}",
					parameters: [
						{label: "module name"},
						{label: "function name"},
						{label: "args"},
					],
					activeParameter: 1,
				},
			],
			activeParameter: 1,
		},
	);
	assert.deepStrictEqual(
		await lsp.provideSignatureHelp(
			"{{ #invoke: a | b | c | d }}",
			{line: 0, character: 25},
		),
		{
			signatures: [
				{
					label: "{{#invoke:module name|function name|args}}",
					parameters: [
						{label: "module name"},
						{label: "function name"},
						{label: "args"},
					],
					activeParameter: 2,
				},
			],
			activeParameter: 3,
		},
	);
	assert.deepStrictEqual(
		await lsp.provideSignatureHelp(
			"{{ PAGENAME: }}",
			{line: 0, character: 2},
		),
		{
			signatures: [
				{
					label: "{{PAGENAME:page name}}",
					parameters: [{label: "page name"}],
				},
			],
			activeParameter: -1,
		},
	);
	assert.deepStrictEqual(
		await lsp.provideSignatureHelp(
			"{{ PAGESIZE: a | R }}",
			{line: 0, character: 13},
		),
		{
			signatures: [
				{
					label: "{{PAGESIZE:page name|R}}",
					parameters: [
						{label: "page name"},
						{label: "R", documentation: "Predefined parameter"},
					],
				},
			],
			activeParameter: 0,
		},
	);
	assert.deepStrictEqual(
		await lsp.provideSignatureHelp(
			"{{ PAGESIZE: a | R }}",
			{line: 0, character: 17},
		),
		{
			signatures: [
				{
					label: "{{PAGESIZE:page name|R}}",
					parameters: [
						{label: "page name"},
						{label: "R", documentation: "Predefined parameter"},
					],
				},
			],
			activeParameter: 1,
		},
	);
})();

provideInlayHints

🌐 展开

加入的版本:1.16.3

param: string 维基文本内容。
returns: Promise<InlayHint[]>
计算给定文档的内联提示,这些提示可能会在编辑器中与其他文本一起呈现。

// provideInlayHints
(async () => {
	const lsp = Parser.createLanguageService();
	assert.deepStrictEqual(
		await lsp.provideInlayHints("{{a|b=|c}}"),
		[
			{
				position: {line: 0, character: 7},
				kind: 2,
				label: "1=",
			},
		],
	);
	assert.deepStrictEqual(
		await lsp.provideInlayHints("{{#invoke:a|b|c}}"),
		[
			{
				position: {line: 0, character: 14},
				kind: 2,
				label: "1=",
			},
		].reverse(),
	);
})();

provideRefactoringAction

🌐 展开

加入的版本:1.24.1

param: string 维基文本内容。
param: Range 重构范围。
returns: Promise<CodeAction[]>
计算给定文档和范围的命令,这些命令可用于重构代码。

// provideRefactoringAction
(async () => {
	const lsp = Parser.createLanguageService(),
		text = `{{a
|[//example.net/?query=1]
|
{|
|-
| table cell
|}
}}`;
	assert.deepStrictEqual(
		await lsp.provideRefactoringAction(text, {
			start: {line: 1, character: 1},
			end: {line: 1, character: 25},
		}),
		[
			{
				title: "Escape with magic words",
				kind: "refactor.rewrite",
				edit: {
					changes: {
						"": [
							{
								range: {
									start: {line: 1, character: 1},
									end: {line: 1, character: 25},
								},
								newText: "[//example.net/?query{{=}}1]",
							},
						],
					},
				},
			},
		],
	);
	assert.deepStrictEqual(
		await lsp.provideRefactoringAction(text, {
			start: {line: 3, character: 0},
			end: {line: 6, character: 2},
		}),
		[
			{
				title: "Escape with magic words",
				kind: "refactor.rewrite",
				edit: {
					changes: {
						"": [
							{
								range: {
									start: {line: 3, character: 0},
									end: {line: 6, character: 2},
								},
								newText: `{{{!}}
{{!}}-
{{!}} table cell
{{!}}}`,
							},
						],
					},
				},
			},
		],
	);
})();

provideCodeAction

展开

param: Diagnostic[]
returns: CodeAction[]
对给定文档和语法诊断提供快速修复命令。

// provideCodeAction (Node.js)
(async () => {
	const lsp = Parser.createLanguageService();
	let diagnostics = await lsp.provideDiagnostics("http://a]");
	assert.deepStrictEqual(
		lsp.provideCodeAction(diagnostics),
		[
			{
				title: "Suggestion: opening bracket",
				kind: "quickfix",
				diagnostics: [diagnostics[0]],
				isPreferred: false,
				edit: {
					changes: {"": diagnostics[0].data},
				},
			},
		],
	);
	diagnostics = await lsp.provideDiagnostics("</br>");
	assert.deepStrictEqual(
		lsp.provideCodeAction(diagnostics),
		[
			{
				title: "Fix: open",
				kind: "quickfix",
				diagnostics: [diagnostics[0]],
				isPreferred: true,
				edit: {
					changes: {"": diagnostics[0].data},
				},
			},
			{
				title: "Fix all: unmatched-tag",
				kind: "source.fixAll",
				diagnostics: [diagnostics[0]],
				isPreferred: true,
				data: {rule: "unmatched-tag"},
			},
			{
				title: "Fix all: WikiLint",
				kind: "source.fixAll",
				diagnostics: [diagnostics[0]],
				isPreferred: true,
				data: {},
			},
		],
	);
})();

resolveCodeAction

🌐 展开

加入的版本:1.24.1

param: CodeAction
returns: CodeAction
计算修复全部错误的命令。

// resolveCodeAction (Node.js)
(async () => {
	const lsp = Parser.createLanguageService(),
		diagnostics = await lsp.provideDiagnostics("</br></p/>[[%2c]]"),
		actions = lsp.provideCodeAction(diagnostics)
			.filter(({kind}) => kind === "source.fixAll");
	assert.deepStrictEqual(
		actions[0],
		{
			title: "Fix all: unmatched-tag",
			kind: "source.fixAll",
			diagnostics: diagnostics.slice(0, 2),
			isPreferred: true,
			data: {rule: "unmatched-tag"},
		},
	);
	assert.deepStrictEqual(
		lsp.resolveCodeAction(actions[0]),
		{
			title: "Fix all: unmatched-tag",
			kind: "source.fixAll",
			diagnostics: diagnostics.slice(0, 2),
			isPreferred: true,
			data: {rule: "unmatched-tag"},
			edit: {
				changes: {
					"": [
						{
							range: {
								start: {line: 0, character: 0},
								end: {line: 0, character: 17},
							},
							newText: "<br></p>[[%2c]]",
						},
					],
				},
			},
		},
	);
	assert.deepStrictEqual(
		actions[1],
		{
			title: "Fix all: url-encoding",
			kind: "source.fixAll",
			diagnostics: diagnostics.slice(2),
			isPreferred: true,
			data: {rule: "url-encoding"},
		},
	);
	assert.deepStrictEqual(
		lsp.resolveCodeAction(actions[1]),
		{
			title: "Fix all: url-encoding",
			kind: "source.fixAll",
			diagnostics: diagnostics.slice(2),
			isPreferred: true,
			data: {rule: "url-encoding"},
			edit: {
				changes: {
					"": [
						{
							range: {
								start: {line: 0, character: 0},
								end: {line: 0, character: 17},
							},
							newText: "</br></p/>[[,]]",
						},
					],
				},
			},
		},
	);
	assert.deepStrictEqual(
		actions[2],
		{
			title: "Fix all: WikiLint",
			kind: "source.fixAll",
			diagnostics,
			isPreferred: true,
			data: {},
		},
	);
	assert.deepStrictEqual(
		lsp.resolveCodeAction(actions[2]),
		{
			title: "Fix all: WikiLint",
			kind: "source.fixAll",
			diagnostics,
			isPreferred: true,
			data: {},
			edit: {
				changes: {
					"": [
						{
							range: {
								start: {line: 0, character: 0},
								end: {line: 0, character: 17},
							},
							newText: "<br></p>[[,]]",
						},
					],
				},
			},
		},
	);
})();

provideDocumentSymbols

展开

param: string 维基文本内容。
returns: Promise<DocumentSymbol[]>
返回在给定文档中找到的章节层次结构。

// provideDocumentSymbols (Node.js)
(async () => {
	const lsp = Parser.createLanguageService(),
		wikitext = `
<!--

-->= 1 =

<!-- -->

<!-- -->== 2 ==



===== 3 ===== <!--

--> 

x {{a|
====== 4_<!--
-->2 ====== 
y }} z
 
== 4 ==


= 4 =

 : {|
|
=== 4 ===
 |} x

`;
	assert.deepStrictEqual(
		await lsp.provideDocumentSymbols(wikitext),
		[
			{
				name: "1",
				kind: 15,
				range: {
					start: {line: 3, character: 3},
					end: {line: 22, character: 0},
				},
				selectionRange: {
					start: {line: 3, character: 3},
					end: {line: 3, character: 8},
				},
				children: [
					{
						name: "2",
						kind: 15,
						range: {
							start: {line: 7, character: 8},
							end: {line: 19, character: 1},
						},
						selectionRange: {
							start: {line: 7, character: 8},
							end: {line: 7, character: 15},
						},
						children: [
							{
								name: "3",
								kind: 15,
								range: {
									start: {line: 11, character: 0},
									end: {line: 19, character: 1},
								},
								selectionRange: {
									start: {line: 11, character: 0},
									end: {line: 11, character: 13},
								},
								children: [
									{
										name: "4_2",
										kind: 15,
										range: {
											start: {line: 16, character: 0},
											end: {line: 19, character: 1},
										},
										selectionRange: {
											start: {line: 16, character: 0},
											end: {line: 17, character: 11},
										},
									},
								],
							},
						],
					},
					{
						name: "4",
						kind: 15,
						range: {
							start: {line: 20, character: 0},
							end: {line: 22, character: 0},
						},
						selectionRange: {
							start: {line: 20, character: 0},
							end: {line: 20, character: 7},
						},
					},
				],
			},
			{
				name: "4_3",
				kind: 15,
				range: {
					start: {line: 23, character: 0},
					end: {line: 30, character: 0},
				},
				selectionRange: {
					start: {line: 23, character: 0},
					end: {line: 23, character: 5},
				},
				children: [
					{
						name: "4_4",
						kind: 15,
						range: {
							start: {line: 27, character: 0},
							end: {line: 30, character: 0},
						},
						selectionRange: {
							start: {line: 27, character: 0},
							end: {line: 27, character: 9},
						},
					},
				],
			},
		],
	);
})();

setTargetWikipedia

展开

加入的版本:1.18.1

param: string 目标维基百科的网址。
param: string 维基用户页面地址或用户的电子邮件地址。
更新解析器配置以针对特定维基百科。不支持其他 MediaWiki 站点。

// setTargetWikipedia (Node.js)
(async () => {
	const lsp = Parser.createLanguageService();
	await lsp.setTargetWikipedia(
		"https://en.wikipedia.org",
		"[email protected]",
	);
	assert.strictEqual(
		lsp.config.articlePath,
		"https://en.wikipedia.org/wiki/",
	);
})();
⚠️ **GitHub.com Fallback** ⚠️