@bhsd/codemirror-mediawiki 3.9.2 → 3.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -11
- package/dist/bidi.d.ts +4 -8
- package/dist/bidi.js +33 -23
- package/dist/codemirror.js +15 -9
- package/dist/color.d.ts +1 -1
- package/dist/color.js +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.js +1 -0
- package/dist/constants.d.ts +3 -2
- package/dist/constants.js +3 -2
- package/dist/css.js +9 -6
- package/dist/escape.d.ts +1 -1
- package/dist/escape.js +4 -3
- package/dist/fold.d.ts +2 -2
- package/dist/fold.js +106 -39
- package/dist/hover.d.ts +2 -2
- package/dist/hover.js +72 -69
- package/dist/index.d.ts +54 -16
- package/dist/index.js +91 -38
- package/dist/inlay.d.ts +1 -1
- package/dist/inlay.js +26 -25
- package/dist/javascript.js +45 -2
- package/dist/linter.d.ts +15 -2
- package/dist/linter.js +2 -2
- package/dist/lintsource.d.ts +15 -3
- package/dist/lintsource.js +13 -7
- package/dist/lua.d.ts +0 -2
- package/dist/lua.js +32 -26
- package/dist/main.min.js +31 -29
- package/dist/matchTag.js +4 -3
- package/dist/mediawiki.d.ts +4 -2
- package/dist/mediawiki.js +56 -44
- package/dist/mw.min.js +33 -37
- package/dist/mwConfig.js +2 -2
- package/dist/openLinks.d.ts +4 -2
- package/dist/openLinks.js +56 -54
- package/dist/ref.d.ts +1 -1
- package/dist/ref.js +92 -93
- package/dist/signature.d.ts +1 -1
- package/dist/signature.js +50 -49
- package/dist/statusBar.js +9 -8
- package/dist/theme.js +6 -0
- package/dist/token.d.ts +20 -6
- package/dist/token.js +26 -17
- package/dist/util.d.ts +17 -2
- package/dist/util.js +39 -1
- package/dist/wiki.min.js +32 -36
- package/i18n/en.json +2 -2
- package/i18n/zh-hans.json +2 -2
- package/i18n/zh-hant.json +2 -2
- package/package.json +14 -12
package/dist/token.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ declare interface Nesting extends Record<NestCount, number> {
|
|
|
18
18
|
extName: string | false;
|
|
19
19
|
extState: object | false;
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
export interface State extends Nesting {
|
|
22
22
|
readonly stack: Tokenizer[];
|
|
23
23
|
readonly inHtmlTag: string[];
|
|
24
24
|
tokenize: Tokenizer;
|
|
@@ -44,11 +44,12 @@ declare interface Token {
|
|
|
44
44
|
pos: number;
|
|
45
45
|
style: Style;
|
|
46
46
|
}
|
|
47
|
-
|
|
47
|
+
export interface StringStream extends StringStreamBase {
|
|
48
48
|
match(pattern: string, consume?: boolean, caseInsensitive?: boolean): true | null;
|
|
49
49
|
match(pattern: RegExp, consume?: boolean): RegExpMatchArray | null;
|
|
50
50
|
}
|
|
51
|
-
export type
|
|
51
|
+
export type CompletionSectionName = 'Required' | 'Suggested' | 'Optional' | 'Deprecated';
|
|
52
|
+
export type ApiSuggestions<T = string[]> = [T, string?, string?, CompletionSectionName?][] & {
|
|
52
53
|
description?: string;
|
|
53
54
|
};
|
|
54
55
|
/**
|
|
@@ -57,17 +58,17 @@ export type ApiSuggestions = [string, string?][] & {
|
|
|
57
58
|
* @param subpage 是否为子页面
|
|
58
59
|
* @param namespace 命名空间
|
|
59
60
|
*/
|
|
60
|
-
export type ApiSuggest = (search: string, subpage?: boolean, namespace?: number) => ApiSuggestions | Promise<ApiSuggestions
|
|
61
|
+
export type ApiSuggest<T = string[]> = (search: string, subpage?: boolean, namespace?: number) => ApiSuggestions<T> | Promise<ApiSuggestions<T>>;
|
|
61
62
|
export interface MwConfig extends MwConfigBase {
|
|
62
63
|
nsid: Record<string, number>;
|
|
63
64
|
variants?: string[];
|
|
64
65
|
img?: Record<string, string>;
|
|
65
66
|
permittedHtmlTags?: string[];
|
|
66
67
|
implicitlyClosedHtmlTags?: string[];
|
|
67
|
-
|
|
68
|
+
articlePath?: string;
|
|
69
|
+
linkSuggest?: ApiSuggest<string>;
|
|
68
70
|
paramSuggest?: ApiSuggest;
|
|
69
71
|
titleParser?: (state: EditorState, node: SyntaxNode) => string | undefined;
|
|
70
|
-
isbnParser?: (link: string) => string;
|
|
71
72
|
}
|
|
72
73
|
declare class MediaWikiData {
|
|
73
74
|
/** 已解析的节点 */
|
|
@@ -83,6 +84,19 @@ declare class MediaWikiData {
|
|
|
83
84
|
readonly urlProtocols: RegExp;
|
|
84
85
|
constructor(tags: string[], urlProtocols: string);
|
|
85
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* 是否为行首语法
|
|
89
|
+
* @param stream
|
|
90
|
+
* @param table 是否允许表格
|
|
91
|
+
* @param file 是否为文件
|
|
92
|
+
*/
|
|
93
|
+
export declare const isSolSyntax: (stream: StringStream, table?: boolean, file?: boolean) => unknown;
|
|
94
|
+
/**
|
|
95
|
+
* 获取负向先行断言
|
|
96
|
+
* @param chars
|
|
97
|
+
* @param comment 是否仅排除注释
|
|
98
|
+
*/
|
|
99
|
+
export declare const lookahead: (chars: string, comment?: boolean | State) => string;
|
|
86
100
|
/** Adapted from the original CodeMirror 5 stream parser by Pavel Astakhov */
|
|
87
101
|
export declare class MediaWiki {
|
|
88
102
|
readonly config: MwConfig;
|
package/dist/token.js
CHANGED
|
@@ -154,7 +154,7 @@ const pop = (state) => {
|
|
|
154
154
|
* @param table 是否允许表格
|
|
155
155
|
* @param file 是否为文件
|
|
156
156
|
*/
|
|
157
|
-
const isSolSyntax = (stream, table, file) => stream.sol() && (table && stream.match(/^\s*(?::+\s*)?\{\|/u, false)
|
|
157
|
+
export const isSolSyntax = (stream, table, file) => stream.sol() && (table && stream.match(/^\s*(?::+\s*)?\{\|/u, false)
|
|
158
158
|
|| stream.match(/^(?:-{4}|=)/u, false)
|
|
159
159
|
|| !file && /[*#;:]/u.test(stream.peek() || ''));
|
|
160
160
|
/**
|
|
@@ -162,7 +162,7 @@ const isSolSyntax = (stream, table, file) => stream.sol() && (table && stream.ma
|
|
|
162
162
|
* @param chars
|
|
163
163
|
* @param comment 是否仅排除注释
|
|
164
164
|
*/
|
|
165
|
-
const lookahead = (chars, comment) => {
|
|
165
|
+
export const lookahead = (chars, comment) => {
|
|
166
166
|
const table = {
|
|
167
167
|
"'": "'(?!')",
|
|
168
168
|
'{': String.raw `\{(?!\{)`,
|
|
@@ -305,6 +305,11 @@ const getQuote = (stream) => {
|
|
|
305
305
|
* @param t Tokenizer
|
|
306
306
|
*/
|
|
307
307
|
const getEqual = (t) => t.name === 'inTemplateArgument' && t.args[0] ? '=' : '';
|
|
308
|
+
/**
|
|
309
|
+
* 转义字符类中的特殊字符
|
|
310
|
+
* @param chars 字符类
|
|
311
|
+
*/
|
|
312
|
+
const escapeCharClass = (chars) => chars.replace(/[\]-]/gu, String.raw `\$&`);
|
|
308
313
|
/**
|
|
309
314
|
* 下一个字符是否为空白字符
|
|
310
315
|
* @param stream StringStream
|
|
@@ -329,21 +334,21 @@ const syntaxHighlight = new Set(['syntaxhighlight', 'source', 'pre']), pageFunct
|
|
|
329
334
|
'canonicalurle',
|
|
330
335
|
'int',
|
|
331
336
|
'msgnw',
|
|
332
|
-
]), substs = new Set(['subst', 'safesubst']), headerRegex = new RegExp(`^(?:[^&[<{~'
|
|
337
|
+
]), substs = new Set(['subst', 'safesubst']), headerRegex = new RegExp(String.raw `^(?:[^&[<{~'\-]|${lookahead("<{~'-")})+`, 'iu'), templateRegex = new RegExp(`^(?:[^|{}<]|${lookahead('{}<', true)})+`, 'u'), argumentRegex = new RegExp(String.raw `^(?:[^|[&:}{<~'__\-]|${lookahead("}{<~'__-")})+`, 'iu'), styleRegex = new RegExp(String.raw `^(?:[^|[&}{<~'__\-]|${lookahead("}{<~'__-")})+`, 'iu'), wikiRegex = new RegExp(String.raw `^(?:[^&:'{[<~__\-]|${lookahead("'{[<~__-")})+`, 'iu'), tableDefinitionRegex = new RegExp(`^(?:[^&={<]|${lookahead('{<')})+`, 'iu'), tableCellRegex = /^\s*(?:[|!]|\{\{\s*![!)\-+]?\s*\}\})/u, extLinkChars = "[{'<-", tableDefinitionChars = '{<', tableCellChars = "'<~__{-", htmlAttrChars = '{/', freeRegex = [false, true].map(lpar => {
|
|
333
338
|
const punctuations = getPunctuations(lpar), source = getUrlRegex(punctuations);
|
|
334
339
|
return new RegExp(`^(?:${source}|[${punctuations}]+(?=${source}))*`, 'u');
|
|
335
340
|
}), indentedTableRegex = [false, true].map(isTemplate => new RegExp(String.raw `^:*\s*(?=\{${getPipe(isTemplate)})`, 'u')), tableRegex = [false, true]
|
|
336
341
|
.map(isTemplate => new RegExp(String.raw `^${getPipe(isTemplate)}\s*`, 'u')), spacedTableRegex = [false, true].map(isTemplate => new RegExp(String.raw `^\s*(:+\s*)?(?=\{${getPipe(isTemplate)})`, 'u')), linkTextRegex = [false, true].map(file => {
|
|
337
342
|
const chars = `]'{<${file ? '~' : '['}-`;
|
|
338
|
-
return new RegExp(`^(?:[^&${file ? '[|' : ''}
|
|
343
|
+
return new RegExp(`^(?:[^&${file ? '[|' : ''}${escapeCharClass(chars)}]|${lookahead(chars)})+`, 'iu');
|
|
339
344
|
}), linkErrorRegex = [
|
|
340
345
|
new RegExp(String.raw `^(?:[<>{}]|%(?:3[ce]|[57][bd])|${lookahead('[]')})+`, 'iu'),
|
|
341
346
|
new RegExp(String.raw `^(?:\}|${lookahead('[]{')})+`, 'u'),
|
|
342
347
|
new RegExp(String.raw `^(?:[>}]|%(?:3[ce]|[57][bd])|${lookahead('[]{<')})+`, 'iu'),
|
|
343
|
-
], tableDefinitionValueRegex = ['', '='].map(equal => new RegExp(String.raw `^(?:[^\s&${tableDefinitionChars}${equal}]|${lookahead(tableDefinitionChars)})+`, 'iu')), variableRegex = [false, true].map(isDefault => new RegExp(String.raw `^(?:[^|{}<${isDefault ?
|
|
348
|
+
], tableDefinitionValueRegex = ['', '='].map(equal => new RegExp(String.raw `^(?:[^\s&${tableDefinitionChars}${equal}]|${lookahead(tableDefinitionChars)})+`, 'iu')), variableRegex = [false, true].map(isDefault => new RegExp(String.raw `^(?:[^|{}<${isDefault ? String.raw `[&~'__:\-` : ''}]|\}(?!\}\})|${isDefault ? lookahead("{<~'__-") : lookahead('{<', true)})+`, 'iu')), parserFunctionRegex = ['', '[&', '[&:'].map(s => getRegex(chars => new RegExp(`^(?:[^|${s}${escapeCharClass(chars)}]|${lookahead(chars)})+`, 'iu'))), doubleUnderscoreRegex = {
|
|
344
349
|
_: /^[\p{L}\p{N}_]+?__/u,
|
|
345
350
|
'_': /^[\p{L}\p{N}__]+?_{2}/u,
|
|
346
|
-
}, getExtLinkTextRegex = getRegex(pipe => new RegExp(String.raw `^(?:[^\]&${pipe}${extLinkChars}]|${lookahead(extLinkChars)})+`, 'iu')), getExtLinkRegex = getRegex(pipe => new RegExp(`^(?:${getUrlRegex(pipe)})+`, 'u')), getTableDefinitionRegex = getRegex(s => new RegExp(`^(?:[^&${tableDefinitionChars}${s}]|${lookahead(tableDefinitionChars)})+`, 'iu')), getTableCellRegex = getRegex(s => new RegExp(`^(?:[^[&${s}${tableCellChars}]|${lookahead(tableCellChars)})+`, 'iu')), getHtmlAttrRegex = getRegex(s => new RegExp(`^(?:[^<>&${htmlAttrChars}${s}]|${lookahead(htmlAttrChars)})+`, 'u')), getHtmlAttrKeyRegex = getRegex(pipe => new RegExp(`^(?:[^<>&={/${pipe}]|${lookahead('{/')})+`, 'u')), getExtAttrRegex = getRegex(s => new RegExp(`^(?:[^>/${s}]|${lookahead('/')})+`, 'u')), getExtTagCloseRegex = getRegex(name => name === 'onlyinclude'
|
|
351
|
+
}, getExtLinkTextRegex = getRegex(pipe => new RegExp(String.raw `^(?:[^\]&${pipe}${escapeCharClass(extLinkChars)}]|${lookahead(extLinkChars)})+`, 'iu')), getExtLinkRegex = getRegex(pipe => new RegExp(`^(?:${getUrlRegex(pipe)})+`, 'u')), getTableDefinitionRegex = getRegex(s => new RegExp(`^(?:[^&${tableDefinitionChars}${s}]|${lookahead(tableDefinitionChars)})+`, 'iu')), getTableCellRegex = getRegex(s => new RegExp(`^(?:[^[&${s}${escapeCharClass(tableCellChars)}]|${lookahead(tableCellChars)})+`, 'iu')), getHtmlAttrRegex = getRegex(s => new RegExp(`^(?:[^<>&${htmlAttrChars}${s}]|${lookahead(htmlAttrChars)})+`, 'u')), getHtmlAttrKeyRegex = getRegex(pipe => new RegExp(`^(?:[^<>&={/${pipe}]|${lookahead('{/')})+`, 'u')), getExtAttrRegex = getRegex(s => new RegExp(`^(?:[^>/${s}]|${lookahead('/')})+`, 'u')), getExtTagCloseRegex = getRegex(name => name === 'onlyinclude'
|
|
347
352
|
? /<\/onlyinclude(?:>|$)/u
|
|
348
353
|
: new RegExp(String.raw `</${name}\s*(?:>|$)`, 'iu')), getNestedRegex = getRegex(tag => new RegExp(String.raw `^(?:[^<]|<(?!${tag}(?:[\s/>]|$)))+`, 'iu'));
|
|
349
354
|
/** Adapted from the original CodeMirror 5 stream parser by Pavel Astakhov */
|
|
@@ -463,15 +468,18 @@ let MediaWiki = (() => {
|
|
|
463
468
|
this.fileRegex = new RegExp(String.raw `^(?:${Object.entries(nsid).filter(([, id]) => id === 6).map(([ns]) => ns).join('|')})\s*:`, 'iu');
|
|
464
469
|
this.redirectRegex = new RegExp(String.raw `^\s*(?:${redirection.join('|')})(\s*:)?\s*(?=\[\[|$)`, 'iu');
|
|
465
470
|
this.img = Object.keys(img).filter(word => !/\$1./u.test(word));
|
|
471
|
+
const spImgKeys = Object.keys(img).filter(word => word.startsWith('$1'));
|
|
466
472
|
this.imgRegex = new RegExp(String.raw `^(?:${this.img.filter(word => word.endsWith('$1')).map(word => word.slice(0, -2))
|
|
467
|
-
.join('|')}|(?:${this.img.filter(word => !word.endsWith('$1')).join('|')}|(?:\d+x?|\d*x\d+)\s*(?:px)?
|
|
473
|
+
.join('|')}|(?:${this.img.filter(word => !word.endsWith('$1')).join('|')}|(?:(?:\d+x?|\d*x\d+)\s*(?:px)?(?:${spImgKeys.filter(word => img[word] === 'img_width').map(word => word.slice(2))
|
|
474
|
+
.join('|')}))|\d+\s*(?:${spImgKeys.filter(word => img[word] !== 'img_width').map(word => word.slice(2))
|
|
475
|
+
.join('|')}))\s*(?=\||\]\]|$))`, 'u');
|
|
468
476
|
this.tags = [...Object.keys(tags), 'includeonly', 'noinclude', 'onlyinclude'];
|
|
469
|
-
this.convertRegex = new RegExp(String.raw `^(?:[^}|;&='{[<~_
|
|
477
|
+
this.convertRegex = new RegExp(String.raw `^(?:[^}|;&='{[<~__\-]|\}(?!-)|=(?!>)|\[(?!\[|${urlProtocols})|${lookahead("'{<~__-")})+`, 'iu');
|
|
470
478
|
this.convertSemicolon = variants && new RegExp(String.raw `^;\s*(?=(?:[^;]*?=>\s*)?(?:${variants.join('|')})\s*:|(?:$|\}-))`, 'iu');
|
|
471
479
|
this.convertLang = variants
|
|
472
480
|
&& new RegExp(String.raw `^(?:=>\s*)?(?:${variants.join('|')})\s*:`, 'iu');
|
|
473
481
|
this.hasVariants = Boolean(variants?.length);
|
|
474
|
-
this.preRegex = [false, true].map(begin => new RegExp(String.raw `^(?:[
|
|
482
|
+
this.preRegex = [false, true].map(begin => new RegExp(String.raw `^(?:[^<&\-]|-${this.hasVariants ? String.raw `(?!\{)` : ''}|<(?!${begin ? '/' : ''}nowiki>))+`, 'iu'));
|
|
475
483
|
this.substRegex = new RegExp(String.raw `^\s*(?:(${Object.entries(insensitive).filter(([, v]) => substs.has(v))
|
|
476
484
|
.map(([k]) => k + (k.endsWith(':') ? '' : ':'))
|
|
477
485
|
.join('|')})\s*)?`, 'iu');
|
|
@@ -775,7 +783,7 @@ let MediaWiki = (() => {
|
|
|
775
783
|
stream.backUp(1);
|
|
776
784
|
}
|
|
777
785
|
else {
|
|
778
|
-
stream.eatWhile(/[^\p{L}\p{N}__&'{[
|
|
786
|
+
stream.eatWhile(/[^\p{L}\p{N}__&'{[<\-~:]/u);
|
|
779
787
|
}
|
|
780
788
|
const mt = stream.match(this.urlProtocols, false);
|
|
781
789
|
if (mt) {
|
|
@@ -1046,7 +1054,7 @@ let MediaWiki = (() => {
|
|
|
1046
1054
|
return (stream, state) => {
|
|
1047
1055
|
if (stream.sol()) {
|
|
1048
1056
|
stream.eatSpace();
|
|
1049
|
-
const mt = stream.match(/^(?:\||\{\{\s*!([!)
|
|
1057
|
+
const mt = stream.match(/^(?:\||\{\{\s*!([!)\-+])?\s*\}\})/u);
|
|
1050
1058
|
if (mt) {
|
|
1051
1059
|
if (mt[1] === '-' || !mt[1] && stream.eat('-')) {
|
|
1052
1060
|
stream.match(/^-*\s*/u);
|
|
@@ -1648,7 +1656,7 @@ let MediaWiki = (() => {
|
|
|
1648
1656
|
if (expectName
|
|
1649
1657
|
&& stream.match(new RegExp(`^(?:[^=|}{[<]|${lookahead('}{[<', state)})*=`, 'iu'))) {
|
|
1650
1658
|
state.tokenize = this.inTemplateArgument(false, parserFunction);
|
|
1651
|
-
return makeLocalTagStyle('templateArgumentName', state);
|
|
1659
|
+
return makeLocalTagStyle(parserFunction ? 'parserFunctionArgumentName' : 'templateArgumentName', state);
|
|
1652
1660
|
}
|
|
1653
1661
|
else if (isSolSyntax(stream) && stream.peek() !== '=') {
|
|
1654
1662
|
return this.eatWikiText(tag)(stream, state);
|
|
@@ -1684,7 +1692,7 @@ let MediaWiki = (() => {
|
|
|
1684
1692
|
if (stream.match('-{', false)) {
|
|
1685
1693
|
return this.eatWikiText(style)(stream, state);
|
|
1686
1694
|
}
|
|
1687
|
-
stream.match(/^(?:(?:[^}
|
|
1695
|
+
stream.match(/^(?:(?:[^}\-;=]|\}(?!-)|=(?!>)|-(?!\{))+|;|=>)/u);
|
|
1688
1696
|
return makeStyle(style, state);
|
|
1689
1697
|
}
|
|
1690
1698
|
return !isSolSyntax(stream, true) && stream.match(this.convertRegex) || space
|
|
@@ -1782,16 +1790,17 @@ let MediaWiki = (() => {
|
|
|
1782
1790
|
// get token style
|
|
1783
1791
|
stream.start = stream.pos;
|
|
1784
1792
|
const char = stream.peek(), style = state.tokenize(stream, state);
|
|
1785
|
-
if (typeof style === 'string' && style.includes(
|
|
1793
|
+
if (typeof style === 'string' && style.includes('-argument-name')) {
|
|
1794
|
+
const isTemplate = style.includes(tokens.templateArgumentName), argument = tokens[isTemplate ? 'template' : 'parserFunction'], argumentName = tokens[isTemplate ? 'templateArgumentName' : 'parserFunctionArgumentName'], delimiter = tokens[isTemplate ? 'templateDelimiter' : 'parserFunctionDelimiter'];
|
|
1786
1795
|
for (let i = readyTokens.length - 1; i >= 0; i--) {
|
|
1787
1796
|
const token = readyTokens[i];
|
|
1788
1797
|
if (cmpNesting(state, token.state, true)) {
|
|
1789
|
-
const types = typeof token.style === 'string' && token.style.split(' '), j = types && types.indexOf(
|
|
1798
|
+
const types = typeof token.style === 'string' && token.style.split(' '), j = types && types.indexOf(argument);
|
|
1790
1799
|
if (j !== false && j !== -1) {
|
|
1791
|
-
types[j] =
|
|
1800
|
+
types[j] = argumentName;
|
|
1792
1801
|
token.style = types.join(' ');
|
|
1793
1802
|
}
|
|
1794
|
-
else if (types && types.includes(
|
|
1803
|
+
else if (types && types.includes(delimiter)) {
|
|
1795
1804
|
break;
|
|
1796
1805
|
}
|
|
1797
1806
|
}
|
package/dist/util.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { EditorView, TooltipView } from '@codemirror/view';
|
|
2
|
-
import type { Text, EditorState } from '@codemirror/state';
|
|
2
|
+
import type { Text, EditorState, SelectionRange } from '@codemirror/state';
|
|
3
3
|
import type { SyntaxNode } from '@lezer/common';
|
|
4
4
|
import type { Position } from 'vscode-languageserver-types';
|
|
5
|
+
import type { ConfigGetter } from '@bhsd/browser';
|
|
6
|
+
import type { TagName } from './config';
|
|
5
7
|
/**
|
|
6
8
|
* 转义HTML字符串
|
|
7
9
|
* @param text 原字符串
|
|
@@ -25,18 +27,31 @@ export declare const posToIndex: (doc: Text, pos: Position) => number;
|
|
|
25
27
|
* @param innerHTML 提示内容
|
|
26
28
|
*/
|
|
27
29
|
export declare const createTooltipView: (view: EditorView, innerHTML: string) => TooltipView;
|
|
30
|
+
/**
|
|
31
|
+
* 获取节点对应的字符串
|
|
32
|
+
* @param state EditorState 实例
|
|
33
|
+
* @param node 语法树节点
|
|
34
|
+
*/
|
|
35
|
+
export declare const sliceDoc: (state: EditorState, node: SyntaxNode | SelectionRange) => string;
|
|
28
36
|
/**
|
|
29
37
|
* Update the stack of opening (+) or closing (-) brackets
|
|
30
38
|
* @param state
|
|
31
39
|
* @param node 语法树节点
|
|
32
40
|
*/
|
|
33
41
|
export declare const braceStackUpdate: (state: EditorState, node: SyntaxNode) => [number, number];
|
|
42
|
+
/**
|
|
43
|
+
* Find the current template name
|
|
44
|
+
* @param state
|
|
45
|
+
* @param node 语法树节点
|
|
46
|
+
*/
|
|
47
|
+
export declare const findTemplateName: (state: EditorState, node: SyntaxNode) => string | null;
|
|
34
48
|
/**
|
|
35
49
|
* 判断节点是否包含指定类型
|
|
36
50
|
* @param types 节点类型
|
|
37
51
|
* @param names 指定类型
|
|
38
52
|
*/
|
|
39
|
-
export declare const hasTag: (types: Set<string>, names:
|
|
53
|
+
export declare const hasTag: (types: Set<string>, names: TagName | TagName[]) => boolean;
|
|
54
|
+
export declare const toConfigGetter: (configGetter?: ConfigGetter, articlePath?: string) => ConfigGetter | undefined;
|
|
40
55
|
/**
|
|
41
56
|
* 获取字符串开头的空白字符
|
|
42
57
|
* @param str 字符串
|
package/dist/util.js
CHANGED
|
@@ -36,21 +36,59 @@ export const createTooltipView = (view, innerHTML) => {
|
|
|
36
36
|
inner.innerHTML = innerHTML;
|
|
37
37
|
return { dom };
|
|
38
38
|
};
|
|
39
|
+
/**
|
|
40
|
+
* 获取节点对应的字符串
|
|
41
|
+
* @param state EditorState 实例
|
|
42
|
+
* @param node 语法树节点
|
|
43
|
+
*/
|
|
44
|
+
export const sliceDoc = (state, node) => state.sliceDoc(node.from, node.to);
|
|
39
45
|
/**
|
|
40
46
|
* Update the stack of opening (+) or closing (-) brackets
|
|
41
47
|
* @param state
|
|
42
48
|
* @param node 语法树节点
|
|
43
49
|
*/
|
|
44
50
|
export const braceStackUpdate = (state, node) => {
|
|
45
|
-
const brackets =
|
|
51
|
+
const brackets = sliceDoc(state, node);
|
|
46
52
|
return [brackets.split('{{').length - 1, 1 - brackets.split('}}').length];
|
|
47
53
|
};
|
|
54
|
+
/**
|
|
55
|
+
* Find the current template name
|
|
56
|
+
* @param state
|
|
57
|
+
* @param node 语法树节点
|
|
58
|
+
*/
|
|
59
|
+
export const findTemplateName = (state, node) => {
|
|
60
|
+
let stack = -1, { prevSibling } = node,
|
|
61
|
+
/** 可包含`_`、`:`等 */ page = '';
|
|
62
|
+
while (prevSibling) {
|
|
63
|
+
const { name } = prevSibling;
|
|
64
|
+
if (name.includes(tokens.templateBracket)) {
|
|
65
|
+
const [lbrace, rbrace] = braceStackUpdate(state, prevSibling);
|
|
66
|
+
stack += lbrace;
|
|
67
|
+
if (stack >= 0) {
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
stack += rbrace;
|
|
71
|
+
}
|
|
72
|
+
else if (stack === -1 && name.includes(tokens.templateName)) {
|
|
73
|
+
page = sliceDoc(state, prevSibling) + page;
|
|
74
|
+
}
|
|
75
|
+
else if (page && !name.includes(tokens.comment)) {
|
|
76
|
+
prevSibling = null;
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
({ prevSibling } = prevSibling);
|
|
80
|
+
}
|
|
81
|
+
return prevSibling && page;
|
|
82
|
+
};
|
|
48
83
|
/**
|
|
49
84
|
* 判断节点是否包含指定类型
|
|
50
85
|
* @param types 节点类型
|
|
51
86
|
* @param names 指定类型
|
|
52
87
|
*/
|
|
53
88
|
export const hasTag = (types, names) => (Array.isArray(names) ? names : [names]).some(name => types.has(name in tokens ? tokens[name] : name));
|
|
89
|
+
export const toConfigGetter = (configGetter, articlePath) => articlePath
|
|
90
|
+
? async () => Object.assign(await (configGetter ?? wikiparse.getConfig)(), { articlePath })
|
|
91
|
+
: configGetter;
|
|
54
92
|
/**
|
|
55
93
|
* 获取字符串开头的空白字符
|
|
56
94
|
* @param str 字符串
|