@bhsd/codemirror-mediawiki 2.1.12 → 2.1.15

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/dist/mw.min.js ADDED
@@ -0,0 +1,2 @@
1
+ import{CodeMirror6 as O}from"https://testingcf.jsdelivr.net/npm/@bhsd/codemirror-mediawiki@2.1.15/dist/main.min.js";var b=mw.loader.getState("ext.CodeMirror")!==null,E=mw.loader.getState("ext.CodeMirror.data")?"ext.CodeMirror.data":"ext.CodeMirror",L,p=(L=JSON.parse(localStorage.getItem("InPageEditMwConfig")))!=null?L:{},C=`${mw.config.get("wgServerName")}${mw.config.get("wgScriptPath")}`,u=p[C],M=Number(u==null?void 0:u.time)>Date.now()-86400*1e3*30,h=(e,t,i)=>{let n=e.filter(t).filter(({"case-sensitive":o})=>o!==i).flatMap(({aliases:o,name:c,"case-sensitive":a})=>o.map(s=>({alias:(a?s:s.toLowerCase()).replace(/:$/u,""),name:c}))),r={};for(let{alias:o,name:c}of n)r[o]=c;return r},T=(e,t)=>[!0,!1].map(i=>h(e,t,i)),v=e=>{mw.config.set("extCodeMirrorConfig",e)},y=async()=>{b&&!M&&await mw.loader.using(E);let e=mw.config.get("extCodeMirrorConfig");!e&&M&&({config:e}=u,v(e));let t=e&&Object.values(e.functionSynonyms[0]).includes(!0);if(e!=null&&e.img&&e.variants&&!t)return{...e,nsid:mw.config.get("wgNamespaceIds")};await mw.loader.using("mediawiki.api");let{query:{general:{variants:i},magicwords:n,extensiontags:r,functionhooks:o,variables:c}}=await new mw.Api().get({meta:"siteinfo",siprop:["general","magicwords",...e&&!t?[]:["extensiontags","functionhooks","variables"]],formatversion:"2"}),a=new Set(["msg","raw","msgnw","subst","safesubst"]);if(e&&!t){let{functionSynonyms:[s]}=e;"subst"in s||Object.assign(s,h(n,({name:g})=>a.has(g)))}else{e={tagModes:{tab:"text/mediawiki",indicator:"text/mediawiki",poem:"text/mediawiki",ref:"text/mediawiki",option:"text/mediawiki",combooption:"text/mediawiki",tabs:"text/mediawiki",poll:"text/mediawiki",gallery:"text/mediawiki"},tags:{},urlProtocols:mw.config.get("wgUrlProtocols")};for(let g of r)e.tags[g.slice(1,-1)]=!0;let s=new Set([...o,...c,...a]);e.functionSynonyms=T(n,({name:g})=>s.has(g)),e.doubleUnderscore=T(n,({aliases:g})=>g.some(A=>/^__.+__$/u.test(A)))}return e.img=h(n,({name:s})=>s.startsWith("img_")),e.variants=i?i.map(({code:s})=>s):[],e.nsid=mw.config.get("wgNamespaceIds"),v(e),p[C]={config:e,time:Date.now()},localStorage.setItem("InPageEditMwConfig",JSON.stringify(p)),e};var{vendor:S,userAgent:H,maxTouchPoints:P,platform:j}=navigator,J=S.includes("Apple Computer")&&(H.includes("Mobile/")||P>2)||j.includes("Mac")?"metaKey":"ctrlKey",l=".cm-mw-template-name, .cm-mw-link-pagename",k=function(e){if(!e[J])return;e.preventDefault();let t=this.textContent,{previousSibling:i,nextSibling:n}=this;for(;i&&(i.nodeType===Node.TEXT_NODE||i.matches(l));)t=i.textContent+t,{previousSibling:i}=i;for(;n&&(n.nodeType===Node.TEXT_NODE||n.matches(l));)t+=n.textContent,{nextSibling:n}=n;t=t.trim(),t.startsWith("/")&&(t=`:${mw.config.get("wgPageName")}${t}`),open(new mw.Title(t,this.classList.contains("cm-mw-template-name")?10:0).getUrl(void 0),"_blank")};var d=new WeakMap,m=e=>d.get(e[0]);function Q(e){let{view:{state:{selection:{main:t}}}}=m(this);return e!=null&&e.startAndEnd?[t.from,t.to]:t.head}var x={getContents(){return m(this).view.state.doc.toString()},setContents(e){return m(this).setContent(e),this},getSelection(){let{view:{state:e}}=m(this);return e.sliceDoc(e.selection.main.from,e.selection.main.to)},setSelection({start:e,end:t}){let{view:i}=m(this);return i.dispatch({selection:{anchor:e,head:t!=null?t:e}}),i.focus(),this},replaceSelection(e){let{view:t}=m(this);return t.dispatch(t.state.replaceSelection(e)),this},getCaretPosition:Q,scrollToCaretPosition(){return m(this).view.dispatch({scrollIntoView:!0}),this}};mw.loader.load("https://testingcf.jsdelivr.net/npm/@bhsd/codemirror-mediawiki@2.1.15/mediawiki.min.css","text/css");$.valHooks.textarea={get(e){let t=d.get(e);return t!=null&&t.visible?t.view.state.doc.toString():e.value},set(e,t){let i=d.get(e);i!=null&&i.visible?i.setContent(t):e.value=t}};var f={};mw.loader.addStyleTag(`.wikiEditor-ui-toolbar{z-index:7}${l}{cursor:var(--codemirror-cursor)}`);var w=class e extends O{constructor(t,i,n){super(t,i,n),d.set(t,this),mw.loader.getState("jquery.textSelection")==="ready"&&$(t).data("jquery.textSelection",x),mw.hook("wiki-codemirror6").fire(this)}toggle(t=!this.visible){super.toggle(t),$(this.textarea).data("jquery.textSelection",t&&x)}async getLinter(t){let i=await super.getLinter(t);return f[this.lang]=i,i}async defaultLint(t,i){if(!t){this.lint();return}let{lang:n}=this,r;if(typeof i=="number"?n==="mediawiki"&&(i===10||i===828||i===2)?r={include:!0}:n==="javascript"&&(i===8||i===2300)&&(r={env:{browser:!0,es6:!0},parserOptions:{ecmaVersion:6}}):r=i,n in f)r&&await this.getLinter(r);else{if(n==="mediawiki"){let o=mw.config.get("wgUserLanguage");["zh","zh-hans","zh-cn","zh-sg","zh-my"].includes(o)?r={...r,i18n:"zh-hans"}:["zh-hant","zh-tw","zh-hk","zh-mo"].includes(o)&&(r={...r,i18n:"zh-hant"})}if(await this.getLinter(r),n==="mediawiki"){let o=await y(),c={...await wikiparse.getConfig(),ext:Object.keys(o.tags),namespaces:mw.config.get("wgFormattedNamespaces"),nsid:o.nsid,doubleUnderscore:o.doubleUnderscore.map(a=>Object.keys(a).map(s=>s.slice(2,-2))),variants:o.variants,protocol:o.urlProtocols.replace(/\\:/gu,":")};if([c.parserFunction[0]]=o.functionSynonyms,!b)for(let[a,s]of Object.entries(o.functionSynonyms[0]))a.startsWith("#")||(c.parserFunction[0][`#${a}`]=s);c.parserFunction[1]=[...Object.keys(o.functionSynonyms[1]),"="];for(let a of Object.keys(o.img))c.img[a]=o.img[a].slice(4);wikiparse.setConfig(c)}}f[n]&&this.lint(f[n])}prefer(t){super.prefer(t),(Array.isArray(t)?t.includes("openLinks"):t.openLinks)?(mw.loader.load("mediawiki.Title"),$(this.view.contentDOM).on("click",l,k).css("--codemirror-cursor","pointer")):$(this.view.contentDOM).off("click",l,k).css("--codemirror-cursor","")}static async fromTextArea(t,i){let n=i==="mediawiki"||i==="html",r=new e(t,n?void 0:i);if(n){let o=await y();r.setLanguage(i,o)}return r}};document.body.addEventListener("click",e=>{e.target instanceof HTMLTextAreaElement&&e.shiftKey&&!d.has(e.target)&&(e.preventDefault(),(async()=>{var o;let{wgAction:t,wgNamespaceNumber:i,wgPageContentModel:n}=mw.config.get(),r;if(t!=="edit"&&t!=="submit")await mw.loader.using("oojs-ui-windows"),r=(o=await OO.ui.prompt("Language:")||void 0)==null?void 0:o.toLowerCase();else switch(n){case"css":case"sanitized-css":r="css";break;case"javascript":r="javascript";break;case"json":r="json";break;case"Scribunto":r="lua";break;case"wikitext":r=i===274?"html":"mediawiki";break}w.fromTextArea(e.target,r)})())});Object.assign(window,{CodeMirror6:w});export{w as CodeMirror};
2
+ //# sourceMappingURL=mw.min.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../mw/base.ts", "../mw/config.ts", "../mw/openLinks.ts", "../mw/textSelection.ts"],
4
+ "sourcesContent": ["import {CodeMirror6} from 'https://testingcf.jsdelivr.net/npm/@bhsd/codemirror-mediawiki@2.1.15/dist/main.min.js';\nimport {getMwConfig, USING_LOCAL} from './config';\nimport {openLinks, pageSelector} from './openLinks';\nimport {instances, textSelection} from './textSelection';\nimport type {Config} from 'wikilint';\nimport type {LintSource} from '../src/codemirror';\n\nmw.loader.load(\n\t'https://testingcf.jsdelivr.net/npm/@bhsd/codemirror-mediawiki@2.1.15/mediawiki.min.css',\n\t'text/css',\n);\n\n/**\n * jQuery.val overrides for CodeMirror.\n */\n$.valHooks['textarea'] = {\n\tget(elem: HTMLTextAreaElement): string {\n\t\tconst cm = instances.get(elem);\n\t\treturn cm?.visible ? cm.view.state.doc.toString() : elem.value;\n\t},\n\tset(elem: HTMLTextAreaElement, value: string): void {\n\t\tconst cm = instances.get(elem);\n\t\tif (cm?.visible) {\n\t\t\tcm.setContent(value);\n\t\t} else {\n\t\t\telem.value = value;\n\t\t}\n\t},\n};\n\nconst linters: Record<string, LintSource | undefined> = {};\n\nmw.loader.addStyleTag(`.wikiEditor-ui-toolbar{z-index:7}${pageSelector}{cursor:var(--codemirror-cursor)}`);\n\nexport class CodeMirror extends CodeMirror6 {\n\t/**\n\t * @param textarea \u6587\u672C\u6846\n\t * @param lang \u8BED\u8A00\n\t * @param config \u8BED\u8A00\u8BBE\u7F6E\n\t */\n\tconstructor(textarea: HTMLTextAreaElement, lang?: string, config?: unknown) {\n\t\tsuper(textarea, lang, config);\n\t\tinstances.set(textarea, this);\n\t\tif (mw.loader.getState('jquery.textSelection') === 'ready') {\n\t\t\t$(textarea).data('jquery.textSelection', textSelection);\n\t\t}\n\t\tmw.hook('wiki-codemirror6').fire(this);\n\t}\n\n\toverride toggle(show = !this.visible): void {\n\t\tsuper.toggle(show);\n\t\t$(this.textarea).data('jquery.textSelection', show && textSelection);\n\t}\n\n\toverride async getLinter(opt?: Record<string, unknown>): Promise<LintSource | undefined> {\n\t\tconst linter = await super.getLinter(opt);\n\t\tlinters[this.lang] = linter;\n\t\treturn linter;\n\t}\n\n\t/**\n\t * \u6DFB\u52A0\u6216\u79FB\u9664\u9ED8\u8BA4 linter\n\t * @param on \u662F\u5426\u6DFB\u52A0\n\t * @param opt linter\u9009\u9879\n\t * @param ns \u547D\u540D\u7A7A\u95F4\n\t */\n\tdefaultLint(on: boolean, opt?: Record<string, unknown>): Promise<void>;\n\tdefaultLint(on: boolean, ns: number): Promise<void>;\n\tasync defaultLint(on: boolean, optOrNs?: Record<string, unknown> | number): Promise<void> {\n\t\tif (!on) {\n\t\t\tthis.lint();\n\t\t\treturn;\n\t\t}\n\t\tconst {lang} = this;\n\t\tlet opt: Record<string, unknown> | undefined;\n\t\tif (typeof optOrNs === 'number') {\n\t\t\tif (lang === 'mediawiki' && (optOrNs === 10 || optOrNs === 828 || optOrNs === 2)) {\n\t\t\t\topt = {include: true};\n\t\t\t} else if (lang === 'javascript' && (optOrNs === 8 || optOrNs === 2300)) {\n\t\t\t\topt = {\n\t\t\t\t\tenv: {browser: true, es6: true},\n\t\t\t\t\tparserOptions: {ecmaVersion: 6},\n\t\t\t\t};\n\t\t\t}\n\t\t} else {\n\t\t\topt = optOrNs;\n\t\t}\n\t\tif (!(lang in linters)) {\n\t\t\tif (lang === 'mediawiki') {\n\t\t\t\tconst i18n = mw.config.get('wgUserLanguage');\n\t\t\t\tif (['zh', 'zh-hans', 'zh-cn', 'zh-sg', 'zh-my'].includes(i18n)) {\n\t\t\t\t\topt = {...opt, i18n: 'zh-hans'};\n\t\t\t\t} else if (['zh-hant', 'zh-tw', 'zh-hk', 'zh-mo'].includes(i18n)) {\n\t\t\t\t\topt = {...opt, i18n: 'zh-hant'};\n\t\t\t\t}\n\t\t\t}\n\t\t\tawait this.getLinter(opt);\n\t\t\tif (lang === 'mediawiki') {\n\t\t\t\tconst mwConfig = await getMwConfig(),\n\t\t\t\t\tconfig: Config = {\n\t\t\t\t\t\t...await wikiparse.getConfig(),\n\t\t\t\t\t\text: Object.keys(mwConfig.tags),\n\t\t\t\t\t\tnamespaces: mw.config.get('wgFormattedNamespaces'),\n\t\t\t\t\t\tnsid: mwConfig.nsid,\n\t\t\t\t\t\tdoubleUnderscore: mwConfig.doubleUnderscore.map(\n\t\t\t\t\t\t\tobj => Object.keys(obj).map(s => s.slice(2, -2)),\n\t\t\t\t\t\t) as [string[], string[]],\n\t\t\t\t\t\tvariants: mwConfig.variants!,\n\t\t\t\t\t\tprotocol: mwConfig.urlProtocols.replace(/\\\\:/gu, ':'),\n\t\t\t\t\t};\n\t\t\t\t[config.parserFunction[0]] = mwConfig.functionSynonyms;\n\t\t\t\tif (!USING_LOCAL) {\n\t\t\t\t\tfor (const [key, val] of Object.entries(mwConfig.functionSynonyms[0])) {\n\t\t\t\t\t\tif (!key.startsWith('#')) {\n\t\t\t\t\t\t\tconfig.parserFunction[0][`#${key}`] = val;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconfig.parserFunction[1] = [\n\t\t\t\t\t...Object.keys(mwConfig.functionSynonyms[1]),\n\t\t\t\t\t'=',\n\t\t\t\t];\n\t\t\t\tfor (const key of Object.keys(mwConfig.img!)) {\n\t\t\t\t\tconfig.img[key] = mwConfig.img![key]!.slice(4);\n\t\t\t\t}\n\t\t\t\twikiparse.setConfig(config);\n\t\t\t}\n\t\t} else if (opt) {\n\t\t\tawait this.getLinter(opt);\n\t\t}\n\t\tif (linters[lang]) {\n\t\t\tthis.lint(linters[lang]);\n\t\t}\n\t}\n\n\t/** @override */\n\toverride prefer(extensions: string[] | Record<string, boolean>): void {\n\t\tsuper.prefer(extensions);\n\t\tif (Array.isArray(extensions) ? extensions.includes('openLinks') : extensions['openLinks']) {\n\t\t\tmw.loader.load('mediawiki.Title');\n\t\t\t$(this.view.contentDOM).on('click', pageSelector, openLinks).css('--codemirror-cursor', 'pointer');\n\t\t} else {\n\t\t\t$(this.view.contentDOM).off('click', pageSelector, openLinks).css('--codemirror-cursor', '');\n\t\t}\n\t}\n\n\t/**\n\t * \u5C06 textarea \u66FF\u6362\u4E3A CodeMirror\n\t * @param textarea textarea \u5143\u7D20\n\t * @param lang \u8BED\u8A00\n\t */\n\tstatic async fromTextArea(textarea: HTMLTextAreaElement, lang?: string): Promise<CodeMirror> {\n\t\tconst isWiki = lang === 'mediawiki' || lang === 'html',\n\t\t\tcm = new CodeMirror(textarea, isWiki ? undefined : lang);\n\t\tif (isWiki) {\n\t\t\tconst config = await getMwConfig();\n\t\t\tcm.setLanguage(lang, config);\n\t\t}\n\t\treturn cm;\n\t}\n}\n\ndocument.body.addEventListener('click', e => {\n\tif (e.target instanceof HTMLTextAreaElement && e.shiftKey && !instances.has(e.target)) {\n\t\te.preventDefault();\n\t\t(async () => {\n\t\t\tconst {wgAction, wgNamespaceNumber, wgPageContentModel} = mw.config.get();\n\t\t\tlet lang: string | undefined;\n\t\t\tif (wgAction !== 'edit' && wgAction !== 'submit') {\n\t\t\t\tawait mw.loader.using('oojs-ui-windows');\n\t\t\t\tlang = (await OO.ui.prompt('Language:') || undefined)?.toLowerCase();\n\t\t\t} else {\n\t\t\t\tswitch (wgPageContentModel) {\n\t\t\t\t\tcase 'css':\n\t\t\t\t\tcase 'sanitized-css':\n\t\t\t\t\t\tlang = 'css';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'javascript':\n\t\t\t\t\t\tlang = 'javascript';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'json':\n\t\t\t\t\t\tlang = 'json';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'Scribunto':\n\t\t\t\t\t\tlang = 'lua';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'wikitext':\n\t\t\t\t\t\tlang = wgNamespaceNumber === 274 ? 'html' : 'mediawiki';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t// no default\n\t\t\t\t}\n\t\t\t}\n\t\t\tvoid CodeMirror.fromTextArea(e.target as HTMLTextAreaElement, lang);\n\t\t})();\n\t}\n});\n\nObject.assign(window, {CodeMirror6: CodeMirror});\n", "import type {MwConfig} from '../src/mediawiki';\n\ndeclare interface MagicWord {\n\tname: string;\n\taliases: string[];\n\t'case-sensitive': boolean;\n}\n\nexport const USING_LOCAL = mw.loader.getState('ext.CodeMirror') !== null;\n\n// \u548C\u672C\u5730\u7F13\u5B58\u6709\u5173\u7684\u5E38\u6570\nconst DATA_MODULE = mw.loader.getState('ext.CodeMirror.data') ? 'ext.CodeMirror.data' : 'ext.CodeMirror',\n\tALL_SETTINGS_CACHE: Record<string, {time: number, config: MwConfig}>\n\t\t= JSON.parse(localStorage.getItem('InPageEditMwConfig')!) ?? {},\n\tSITE_ID = `${mw.config.get('wgServerName')}${mw.config.get('wgScriptPath')}`,\n\tSITE_SETTINGS = ALL_SETTINGS_CACHE[SITE_ID],\n\tVALID = Number(SITE_SETTINGS?.time) > Date.now() - 86_400 * 1000 * 30;\n\n/**\n * \u5C06\u9B54\u672F\u5B57\u4FE1\u606F\u8F6C\u6362\u4E3ACodeMirror\u63A5\u53D7\u7684\u8BBE\u7F6E\n * @param magicWords \u5B8C\u6574\u9B54\u672F\u5B57\u5217\u8868\n * @param rule \u8FC7\u6EE4\u51FD\u6570\n * @param flip \u662F\u5426\u53CD\u5411\u7B5B\u9009\u5BF9\u5927\u5C0F\u5199\u654F\u611F\u7684\u9B54\u672F\u5B57\n */\nconst getConfig = (\n\tmagicWords: MagicWord[],\n\trule: (word: MagicWord) => boolean,\n\tflip?: boolean,\n): Record<string, string> => {\n\tconst words = magicWords.filter(rule).filter(({'case-sensitive': i}) => i !== flip)\n\t\t\t.flatMap(({aliases, name, 'case-sensitive': i}) => aliases.map(alias => ({\n\t\t\t\talias: (i ? alias : alias.toLowerCase()).replace(/:$/u, ''),\n\t\t\t\tname,\n\t\t\t}))),\n\t\tobj: Record<string, string> = {};\n\tfor (const {alias, name} of words) {\n\t\tobj[alias] = name;\n\t}\n\treturn obj;\n};\n\n/**\n * \u5C06\u9B54\u672F\u5B57\u4FE1\u606F\u8F6C\u6362\u4E3ACodeMirror\u63A5\u53D7\u7684\u8BBE\u7F6E\n * @param magicWords \u5B8C\u6574\u9B54\u672F\u5B57\u5217\u8868\n * @param rule \u8FC7\u6EE4\u51FD\u6570\n */\nconst getConfigPair = (\n\tmagicWords: MagicWord[],\n\trule: (word: MagicWord) => boolean,\n): [Record<string, string>, Record<string, string>] => [true, false]\n\t.map(bool => getConfig(magicWords, rule, bool)) as [Record<string, string>, Record<string, string>];\n\n/** \u5C06\u8BBE\u7F6E\u4FDD\u5B58\u5230mw.config */\nconst setConfig = (config: MwConfig): void => {\n\tmw.config.set('extCodeMirrorConfig', config);\n};\n\n/** \u52A0\u8F7DCodeMirror\u7684mediawiki\u6A21\u5757\u9700\u8981\u7684\u8BBE\u7F6E */\nexport const getMwConfig = async (): Promise<MwConfig> => {\n\tif (USING_LOCAL && !VALID) { // \u53EA\u5728localStorage\u8FC7\u671F\u65F6\u624D\u4F1A\u91CD\u65B0\u52A0\u8F7Dext.CodeMirror.data\n\t\tawait mw.loader.using(DATA_MODULE);\n\t}\n\n\tlet config = mw.config.get('extCodeMirrorConfig') as MwConfig | null;\n\tif (!config && VALID) {\n\t\t({config} = SITE_SETTINGS!);\n\t\tsetConfig(config);\n\t}\n\tconst isIPE = config && Object.values(config.functionSynonyms[0]).includes(true as unknown as string);\n\t// \u60C5\u5F621\uFF1Aconfig\u5DF2\u66F4\u65B0\uFF0C\u53EF\u80FD\u6765\u81EAlocalStorage\n\tif (config?.img && config.variants && !isIPE) {\n\t\treturn {\n\t\t\t...config,\n\t\t\tnsid: mw.config.get('wgNamespaceIds'),\n\t\t};\n\t}\n\n\t// \u4EE5\u4E0B\u60C5\u5F62\u5747\u9700\u8981\u53D1\u9001API\u8BF7\u6C42\n\t// \u60C5\u5F622\uFF1AlocalStorage\u672A\u8FC7\u671F\u4F46\u4E0D\u5305\u542B\u65B0\u8BBE\u7F6E\n\t// \u60C5\u5F623\uFF1A\u65B0\u52A0\u8F7D\u7684 ext.CodeMirror.data\n\t// \u60C5\u5F624\uFF1A`config === null`\n\tawait mw.loader.using('mediawiki.api');\n\tconst {\n\t\tquery: {general: {variants}, magicwords, extensiontags, functionhooks, variables},\n\t}: {\n\t\tquery: {\n\t\t\tgeneral: {variants?: {code: string}[]};\n\t\t\tmagicwords: MagicWord[];\n\t\t\textensiontags: string[];\n\t\t\tfunctionhooks: string[];\n\t\t\tvariables: string[];\n\t\t};\n\t} = await new mw.Api().get({\n\t\tmeta: 'siteinfo',\n\t\tsiprop: [\n\t\t\t'general',\n\t\t\t'magicwords',\n\t\t\t...config && !isIPE ? [] : ['extensiontags', 'functionhooks', 'variables'],\n\t\t],\n\t\tformatversion: '2',\n\t}) as any; // eslint-disable-line @typescript-eslint/no-explicit-any\n\tconst others = new Set(['msg', 'raw', 'msgnw', 'subst', 'safesubst']);\n\n\t// \u5148\u5904\u7406\u9B54\u672F\u5B57\u548C\u72B6\u6001\u5F00\u5173\n\tif (config && !isIPE) { // \u60C5\u5F622\u62163\n\t\tconst {functionSynonyms: [insensitive]} = config;\n\t\tif (!('subst' in insensitive)) {\n\t\t\tObject.assign(insensitive, getConfig(magicwords, ({name}) => others.has(name)));\n\t\t}\n\t} else { // \u60C5\u5F624\uFF1A`config === null`\n\t\t// @ts-expect-error incomplete properties\n\t\tconfig = {\n\t\t\ttagModes: {\n\t\t\t\ttab: 'text/mediawiki',\n\t\t\t\tindicator: 'text/mediawiki',\n\t\t\t\tpoem: 'text/mediawiki',\n\t\t\t\tref: 'text/mediawiki',\n\t\t\t\toption: 'text/mediawiki',\n\t\t\t\tcombooption: 'text/mediawiki',\n\t\t\t\ttabs: 'text/mediawiki',\n\t\t\t\tpoll: 'text/mediawiki',\n\t\t\t\tgallery: 'text/mediawiki',\n\t\t\t},\n\t\t\ttags: {},\n\t\t\turlProtocols: mw.config.get('wgUrlProtocols'),\n\t\t};\n\t\tfor (const tag of extensiontags) {\n\t\t\tconfig!.tags[tag.slice(1, -1)] = true;\n\t\t}\n\t\tconst functions = new Set([\n\t\t\t...functionhooks,\n\t\t\t...variables,\n\t\t\t...others,\n\t\t]);\n\t\tconfig!.functionSynonyms = getConfigPair(magicwords, ({name}) => functions.has(name));\n\t\tconfig!.doubleUnderscore = getConfigPair(\n\t\t\tmagicwords,\n\t\t\t({aliases}) => aliases.some(alias => /^__.+__$/u.test(alias)),\n\t\t);\n\t}\n\tconfig!.img = getConfig(magicwords, ({name}) => name.startsWith('img_'));\n\tconfig!.variants = variants ? variants.map(({code}) => code) : [];\n\tconfig!.nsid = mw.config.get('wgNamespaceIds');\n\tsetConfig(config!);\n\tALL_SETTINGS_CACHE[SITE_ID] = {config: config!, time: Date.now()};\n\tlocalStorage.setItem('InPageEditMwConfig', JSON.stringify(ALL_SETTINGS_CACHE));\n\treturn config!;\n};\n", "const {vendor, userAgent, maxTouchPoints, platform} = navigator,\n\tmodKey = vendor.includes('Apple Computer') && (userAgent.includes('Mobile/') || maxTouchPoints > 2)\n\t|| platform.includes('Mac')\n\t\t? 'metaKey'\n\t\t: 'ctrlKey';\n\nexport const pageSelector = '.cm-mw-template-name, .cm-mw-link-pagename';\n\n/** \u70B9\u51FB\u65F6\u5728\u65B0\u9875\u9762\u6253\u5F00\u94FE\u63A5\u3001\u6A21\u677F\u7B49 */\nexport const openLinks = function(this: HTMLElement, e: JQuery.ClickEvent): void {\n\tif (!e[modKey]) {\n\t\treturn;\n\t}\n\te.preventDefault();\n\tlet page = this.textContent!,\n\t\t{previousSibling, nextSibling} = this;\n\twhile (\n\t\tpreviousSibling\n\t\t&& (previousSibling.nodeType === Node.TEXT_NODE || (previousSibling as Element).matches(pageSelector))\n\t) {\n\t\tpage = previousSibling.textContent! + page;\n\t\t({previousSibling} = previousSibling);\n\t}\n\twhile (\n\t\tnextSibling\n\t\t&& (nextSibling.nodeType === Node.TEXT_NODE || (nextSibling as Element).matches(pageSelector))\n\t) {\n\t\tpage += nextSibling.textContent!;\n\t\t({nextSibling} = nextSibling);\n\t}\n\tpage = page.trim();\n\tif (page.startsWith('/')) {\n\t\tpage = `:${mw.config.get('wgPageName')}${page}`;\n\t}\n\topen(new mw.Title(page, this.classList.contains('cm-mw-template-name') ? 10 : 0).getUrl(undefined), '_blank');\n};\n", "import type {CodeMirror} from './base';\n\nexport const instances = new WeakMap<HTMLTextAreaElement, CodeMirror>();\n\nconst getInstance = ($ele: JQuery<HTMLTextAreaElement>): CodeMirror => instances.get($ele[0]!)!;\n\nfunction getCaretPosition(this: JQuery<HTMLTextAreaElement>, option: {startAndEnd: true}): [number, number];\nfunction getCaretPosition(this: JQuery<HTMLTextAreaElement>, option?: {startAndEnd?: false}): number;\nfunction getCaretPosition(\n\tthis: JQuery<HTMLTextAreaElement>,\n\toption?: {startAndEnd?: boolean},\n): [number, number] | number {\n\tconst {view: {state: {selection: {main}}}} = getInstance(this);\n\treturn option?.startAndEnd ? [main.from, main.to] : main.head;\n}\n\n/**\n * jQuery.textSelection overrides for CodeMirror.\n * See jQuery.textSelection.js for method documentation\n */\nexport const textSelection = {\n\tgetContents(this: JQuery<HTMLTextAreaElement>): string {\n\t\treturn getInstance(this).view.state.doc.toString();\n\t},\n\tsetContents(this: JQuery<HTMLTextAreaElement>, content: string): JQuery<HTMLTextAreaElement> {\n\t\tgetInstance(this).setContent(content);\n\t\treturn this;\n\t},\n\tgetSelection(this: JQuery<HTMLTextAreaElement>): string {\n\t\tconst {view: {state}} = getInstance(this);\n\t\treturn state.sliceDoc(state.selection.main.from, state.selection.main.to);\n\t},\n\tsetSelection(\n\t\tthis: JQuery<HTMLTextAreaElement>,\n\t\t{start, end}: {start: number, end?: number},\n\t): JQuery<HTMLTextAreaElement> {\n\t\tconst {view} = getInstance(this);\n\t\tview.dispatch({\n\t\t\tselection: {anchor: start, head: end ?? start},\n\t\t});\n\t\tview.focus();\n\t\treturn this;\n\t},\n\treplaceSelection(this: JQuery<HTMLTextAreaElement>, value: string): JQuery<HTMLTextAreaElement> {\n\t\tconst {view} = getInstance(this);\n\t\tview.dispatch(view.state.replaceSelection(value));\n\t\treturn this;\n\t},\n\tgetCaretPosition,\n\tscrollToCaretPosition(this: JQuery<HTMLTextAreaElement>): JQuery<HTMLTextAreaElement> {\n\t\tgetInstance(this).view.dispatch({scrollIntoView: true});\n\t\treturn this;\n\t},\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["CodeMirror6", "USING_LOCAL", "DATA_MODULE", "_a", "ALL_SETTINGS_CACHE", "SITE_ID", "SITE_SETTINGS", "VALID", "getConfig", "magicWords", "rule", "flip", "words", "i", "aliases", "name", "alias", "obj", "getConfigPair", "bool", "setConfig", "config", "getMwConfig", "isIPE", "variants", "magicwords", "extensiontags", "functionhooks", "variables", "others", "insensitive", "tag", "functions", "code", "vendor", "userAgent", "maxTouchPoints", "platform", "modKey", "pageSelector", "openLinks", "page", "previousSibling", "nextSibling", "instances", "getInstance", "$ele", "getCaretPosition", "option", "main", "textSelection", "content", "state", "start", "end", "view", "value", "elem", "cm", "instances", "value", "linters", "pageSelector", "CodeMirror", "_CodeMirror", "CodeMirror6", "textarea", "lang", "config", "textSelection", "show", "opt", "linter", "on", "optOrNs", "i18n", "mwConfig", "getMwConfig", "obj", "USING_LOCAL", "key", "val", "extensions", "openLinks", "isWiki", "_a", "wgAction", "wgNamespaceNumber", "wgPageContentModel"]
7
+ }
package/mw/base.ts ADDED
@@ -0,0 +1,198 @@
1
+ import {CodeMirror6} from 'https://testingcf.jsdelivr.net/npm/@bhsd/codemirror-mediawiki@2.1.15/dist/main.min.js';
2
+ import {getMwConfig, USING_LOCAL} from './config';
3
+ import {openLinks, pageSelector} from './openLinks';
4
+ import {instances, textSelection} from './textSelection';
5
+ import type {Config} from 'wikilint';
6
+ import type {LintSource} from '../src/codemirror';
7
+
8
+ mw.loader.load(
9
+ 'https://testingcf.jsdelivr.net/npm/@bhsd/codemirror-mediawiki@2.1.15/mediawiki.min.css',
10
+ 'text/css',
11
+ );
12
+
13
+ /**
14
+ * jQuery.val overrides for CodeMirror.
15
+ */
16
+ $.valHooks['textarea'] = {
17
+ get(elem: HTMLTextAreaElement): string {
18
+ const cm = instances.get(elem);
19
+ return cm?.visible ? cm.view.state.doc.toString() : elem.value;
20
+ },
21
+ set(elem: HTMLTextAreaElement, value: string): void {
22
+ const cm = instances.get(elem);
23
+ if (cm?.visible) {
24
+ cm.setContent(value);
25
+ } else {
26
+ elem.value = value;
27
+ }
28
+ },
29
+ };
30
+
31
+ const linters: Record<string, LintSource | undefined> = {};
32
+
33
+ mw.loader.addStyleTag(`.wikiEditor-ui-toolbar{z-index:7}${pageSelector}{cursor:var(--codemirror-cursor)}`);
34
+
35
+ export class CodeMirror extends CodeMirror6 {
36
+ /**
37
+ * @param textarea 文本框
38
+ * @param lang 语言
39
+ * @param config 语言设置
40
+ */
41
+ constructor(textarea: HTMLTextAreaElement, lang?: string, config?: unknown) {
42
+ super(textarea, lang, config);
43
+ instances.set(textarea, this);
44
+ if (mw.loader.getState('jquery.textSelection') === 'ready') {
45
+ $(textarea).data('jquery.textSelection', textSelection);
46
+ }
47
+ mw.hook('wiki-codemirror6').fire(this);
48
+ }
49
+
50
+ override toggle(show = !this.visible): void {
51
+ super.toggle(show);
52
+ $(this.textarea).data('jquery.textSelection', show && textSelection);
53
+ }
54
+
55
+ override async getLinter(opt?: Record<string, unknown>): Promise<LintSource | undefined> {
56
+ const linter = await super.getLinter(opt);
57
+ linters[this.lang] = linter;
58
+ return linter;
59
+ }
60
+
61
+ /**
62
+ * 添加或移除默认 linter
63
+ * @param on 是否添加
64
+ * @param opt linter选项
65
+ * @param ns 命名空间
66
+ */
67
+ defaultLint(on: boolean, opt?: Record<string, unknown>): Promise<void>;
68
+ defaultLint(on: boolean, ns: number): Promise<void>;
69
+ async defaultLint(on: boolean, optOrNs?: Record<string, unknown> | number): Promise<void> {
70
+ if (!on) {
71
+ this.lint();
72
+ return;
73
+ }
74
+ const {lang} = this;
75
+ let opt: Record<string, unknown> | undefined;
76
+ if (typeof optOrNs === 'number') {
77
+ if (lang === 'mediawiki' && (optOrNs === 10 || optOrNs === 828 || optOrNs === 2)) {
78
+ opt = {include: true};
79
+ } else if (lang === 'javascript' && (optOrNs === 8 || optOrNs === 2300)) {
80
+ opt = {
81
+ env: {browser: true, es6: true},
82
+ parserOptions: {ecmaVersion: 6},
83
+ };
84
+ }
85
+ } else {
86
+ opt = optOrNs;
87
+ }
88
+ if (!(lang in linters)) {
89
+ if (lang === 'mediawiki') {
90
+ const i18n = mw.config.get('wgUserLanguage');
91
+ if (['zh', 'zh-hans', 'zh-cn', 'zh-sg', 'zh-my'].includes(i18n)) {
92
+ opt = {...opt, i18n: 'zh-hans'};
93
+ } else if (['zh-hant', 'zh-tw', 'zh-hk', 'zh-mo'].includes(i18n)) {
94
+ opt = {...opt, i18n: 'zh-hant'};
95
+ }
96
+ }
97
+ await this.getLinter(opt);
98
+ if (lang === 'mediawiki') {
99
+ const mwConfig = await getMwConfig(),
100
+ config: Config = {
101
+ ...await wikiparse.getConfig(),
102
+ ext: Object.keys(mwConfig.tags),
103
+ namespaces: mw.config.get('wgFormattedNamespaces'),
104
+ nsid: mwConfig.nsid,
105
+ doubleUnderscore: mwConfig.doubleUnderscore.map(
106
+ obj => Object.keys(obj).map(s => s.slice(2, -2)),
107
+ ) as [string[], string[]],
108
+ variants: mwConfig.variants!,
109
+ protocol: mwConfig.urlProtocols.replace(/\\:/gu, ':'),
110
+ };
111
+ [config.parserFunction[0]] = mwConfig.functionSynonyms;
112
+ if (!USING_LOCAL) {
113
+ for (const [key, val] of Object.entries(mwConfig.functionSynonyms[0])) {
114
+ if (!key.startsWith('#')) {
115
+ config.parserFunction[0][`#${key}`] = val;
116
+ }
117
+ }
118
+ }
119
+ config.parserFunction[1] = [
120
+ ...Object.keys(mwConfig.functionSynonyms[1]),
121
+ '=',
122
+ ];
123
+ for (const key of Object.keys(mwConfig.img!)) {
124
+ config.img[key] = mwConfig.img![key]!.slice(4);
125
+ }
126
+ wikiparse.setConfig(config);
127
+ }
128
+ } else if (opt) {
129
+ await this.getLinter(opt);
130
+ }
131
+ if (linters[lang]) {
132
+ this.lint(linters[lang]);
133
+ }
134
+ }
135
+
136
+ /** @override */
137
+ override prefer(extensions: string[] | Record<string, boolean>): void {
138
+ super.prefer(extensions);
139
+ if (Array.isArray(extensions) ? extensions.includes('openLinks') : extensions['openLinks']) {
140
+ mw.loader.load('mediawiki.Title');
141
+ $(this.view.contentDOM).on('click', pageSelector, openLinks).css('--codemirror-cursor', 'pointer');
142
+ } else {
143
+ $(this.view.contentDOM).off('click', pageSelector, openLinks).css('--codemirror-cursor', '');
144
+ }
145
+ }
146
+
147
+ /**
148
+ * 将 textarea 替换为 CodeMirror
149
+ * @param textarea textarea 元素
150
+ * @param lang 语言
151
+ */
152
+ static async fromTextArea(textarea: HTMLTextAreaElement, lang?: string): Promise<CodeMirror> {
153
+ const isWiki = lang === 'mediawiki' || lang === 'html',
154
+ cm = new CodeMirror(textarea, isWiki ? undefined : lang);
155
+ if (isWiki) {
156
+ const config = await getMwConfig();
157
+ cm.setLanguage(lang, config);
158
+ }
159
+ return cm;
160
+ }
161
+ }
162
+
163
+ document.body.addEventListener('click', e => {
164
+ if (e.target instanceof HTMLTextAreaElement && e.shiftKey && !instances.has(e.target)) {
165
+ e.preventDefault();
166
+ (async () => {
167
+ const {wgAction, wgNamespaceNumber, wgPageContentModel} = mw.config.get();
168
+ let lang: string | undefined;
169
+ if (wgAction !== 'edit' && wgAction !== 'submit') {
170
+ await mw.loader.using('oojs-ui-windows');
171
+ lang = (await OO.ui.prompt('Language:') || undefined)?.toLowerCase();
172
+ } else {
173
+ switch (wgPageContentModel) {
174
+ case 'css':
175
+ case 'sanitized-css':
176
+ lang = 'css';
177
+ break;
178
+ case 'javascript':
179
+ lang = 'javascript';
180
+ break;
181
+ case 'json':
182
+ lang = 'json';
183
+ break;
184
+ case 'Scribunto':
185
+ lang = 'lua';
186
+ break;
187
+ case 'wikitext':
188
+ lang = wgNamespaceNumber === 274 ? 'html' : 'mediawiki';
189
+ break;
190
+ // no default
191
+ }
192
+ }
193
+ void CodeMirror.fromTextArea(e.target as HTMLTextAreaElement, lang);
194
+ })();
195
+ }
196
+ });
197
+
198
+ Object.assign(window, {CodeMirror6: CodeMirror});
package/mw/config.ts ADDED
@@ -0,0 +1,148 @@
1
+ import type {MwConfig} from '../src/mediawiki';
2
+
3
+ declare interface MagicWord {
4
+ name: string;
5
+ aliases: string[];
6
+ 'case-sensitive': boolean;
7
+ }
8
+
9
+ export const USING_LOCAL = mw.loader.getState('ext.CodeMirror') !== null;
10
+
11
+ // 和本地缓存有关的常数
12
+ const DATA_MODULE = mw.loader.getState('ext.CodeMirror.data') ? 'ext.CodeMirror.data' : 'ext.CodeMirror',
13
+ ALL_SETTINGS_CACHE: Record<string, {time: number, config: MwConfig}>
14
+ = JSON.parse(localStorage.getItem('InPageEditMwConfig')!) ?? {},
15
+ SITE_ID = `${mw.config.get('wgServerName')}${mw.config.get('wgScriptPath')}`,
16
+ SITE_SETTINGS = ALL_SETTINGS_CACHE[SITE_ID],
17
+ VALID = Number(SITE_SETTINGS?.time) > Date.now() - 86_400 * 1000 * 30;
18
+
19
+ /**
20
+ * 将魔术字信息转换为CodeMirror接受的设置
21
+ * @param magicWords 完整魔术字列表
22
+ * @param rule 过滤函数
23
+ * @param flip 是否反向筛选对大小写敏感的魔术字
24
+ */
25
+ const getConfig = (
26
+ magicWords: MagicWord[],
27
+ rule: (word: MagicWord) => boolean,
28
+ flip?: boolean,
29
+ ): Record<string, string> => {
30
+ const words = magicWords.filter(rule).filter(({'case-sensitive': i}) => i !== flip)
31
+ .flatMap(({aliases, name, 'case-sensitive': i}) => aliases.map(alias => ({
32
+ alias: (i ? alias : alias.toLowerCase()).replace(/:$/u, ''),
33
+ name,
34
+ }))),
35
+ obj: Record<string, string> = {};
36
+ for (const {alias, name} of words) {
37
+ obj[alias] = name;
38
+ }
39
+ return obj;
40
+ };
41
+
42
+ /**
43
+ * 将魔术字信息转换为CodeMirror接受的设置
44
+ * @param magicWords 完整魔术字列表
45
+ * @param rule 过滤函数
46
+ */
47
+ const getConfigPair = (
48
+ magicWords: MagicWord[],
49
+ rule: (word: MagicWord) => boolean,
50
+ ): [Record<string, string>, Record<string, string>] => [true, false]
51
+ .map(bool => getConfig(magicWords, rule, bool)) as [Record<string, string>, Record<string, string>];
52
+
53
+ /** 将设置保存到mw.config */
54
+ const setConfig = (config: MwConfig): void => {
55
+ mw.config.set('extCodeMirrorConfig', config);
56
+ };
57
+
58
+ /** 加载CodeMirror的mediawiki模块需要的设置 */
59
+ export const getMwConfig = async (): Promise<MwConfig> => {
60
+ if (USING_LOCAL && !VALID) { // 只在localStorage过期时才会重新加载ext.CodeMirror.data
61
+ await mw.loader.using(DATA_MODULE);
62
+ }
63
+
64
+ let config = mw.config.get('extCodeMirrorConfig') as MwConfig | null;
65
+ if (!config && VALID) {
66
+ ({config} = SITE_SETTINGS!);
67
+ setConfig(config);
68
+ }
69
+ const isIPE = config && Object.values(config.functionSynonyms[0]).includes(true as unknown as string);
70
+ // 情形1:config已更新,可能来自localStorage
71
+ if (config?.img && config.variants && !isIPE) {
72
+ return {
73
+ ...config,
74
+ nsid: mw.config.get('wgNamespaceIds'),
75
+ };
76
+ }
77
+
78
+ // 以下情形均需要发送API请求
79
+ // 情形2:localStorage未过期但不包含新设置
80
+ // 情形3:新加载的 ext.CodeMirror.data
81
+ // 情形4:`config === null`
82
+ await mw.loader.using('mediawiki.api');
83
+ const {
84
+ query: {general: {variants}, magicwords, extensiontags, functionhooks, variables},
85
+ }: {
86
+ query: {
87
+ general: {variants?: {code: string}[]};
88
+ magicwords: MagicWord[];
89
+ extensiontags: string[];
90
+ functionhooks: string[];
91
+ variables: string[];
92
+ };
93
+ } = await new mw.Api().get({
94
+ meta: 'siteinfo',
95
+ siprop: [
96
+ 'general',
97
+ 'magicwords',
98
+ ...config && !isIPE ? [] : ['extensiontags', 'functionhooks', 'variables'],
99
+ ],
100
+ formatversion: '2',
101
+ }) as any; // eslint-disable-line @typescript-eslint/no-explicit-any
102
+ const others = new Set(['msg', 'raw', 'msgnw', 'subst', 'safesubst']);
103
+
104
+ // 先处理魔术字和状态开关
105
+ if (config && !isIPE) { // 情形2或3
106
+ const {functionSynonyms: [insensitive]} = config;
107
+ if (!('subst' in insensitive)) {
108
+ Object.assign(insensitive, getConfig(magicwords, ({name}) => others.has(name)));
109
+ }
110
+ } else { // 情形4:`config === null`
111
+ // @ts-expect-error incomplete properties
112
+ config = {
113
+ tagModes: {
114
+ tab: 'text/mediawiki',
115
+ indicator: 'text/mediawiki',
116
+ poem: 'text/mediawiki',
117
+ ref: 'text/mediawiki',
118
+ option: 'text/mediawiki',
119
+ combooption: 'text/mediawiki',
120
+ tabs: 'text/mediawiki',
121
+ poll: 'text/mediawiki',
122
+ gallery: 'text/mediawiki',
123
+ },
124
+ tags: {},
125
+ urlProtocols: mw.config.get('wgUrlProtocols'),
126
+ };
127
+ for (const tag of extensiontags) {
128
+ config!.tags[tag.slice(1, -1)] = true;
129
+ }
130
+ const functions = new Set([
131
+ ...functionhooks,
132
+ ...variables,
133
+ ...others,
134
+ ]);
135
+ config!.functionSynonyms = getConfigPair(magicwords, ({name}) => functions.has(name));
136
+ config!.doubleUnderscore = getConfigPair(
137
+ magicwords,
138
+ ({aliases}) => aliases.some(alias => /^__.+__$/u.test(alias)),
139
+ );
140
+ }
141
+ config!.img = getConfig(magicwords, ({name}) => name.startsWith('img_'));
142
+ config!.variants = variants ? variants.map(({code}) => code) : [];
143
+ config!.nsid = mw.config.get('wgNamespaceIds');
144
+ setConfig(config!);
145
+ ALL_SETTINGS_CACHE[SITE_ID] = {config: config!, time: Date.now()};
146
+ localStorage.setItem('InPageEditMwConfig', JSON.stringify(ALL_SETTINGS_CACHE));
147
+ return config!;
148
+ };
@@ -0,0 +1,36 @@
1
+ const {vendor, userAgent, maxTouchPoints, platform} = navigator,
2
+ modKey = vendor.includes('Apple Computer') && (userAgent.includes('Mobile/') || maxTouchPoints > 2)
3
+ || platform.includes('Mac')
4
+ ? 'metaKey'
5
+ : 'ctrlKey';
6
+
7
+ export const pageSelector = '.cm-mw-template-name, .cm-mw-link-pagename';
8
+
9
+ /** 点击时在新页面打开链接、模板等 */
10
+ export const openLinks = function(this: HTMLElement, e: JQuery.ClickEvent): void {
11
+ if (!e[modKey]) {
12
+ return;
13
+ }
14
+ e.preventDefault();
15
+ let page = this.textContent!,
16
+ {previousSibling, nextSibling} = this;
17
+ while (
18
+ previousSibling
19
+ && (previousSibling.nodeType === Node.TEXT_NODE || (previousSibling as Element).matches(pageSelector))
20
+ ) {
21
+ page = previousSibling.textContent! + page;
22
+ ({previousSibling} = previousSibling);
23
+ }
24
+ while (
25
+ nextSibling
26
+ && (nextSibling.nodeType === Node.TEXT_NODE || (nextSibling as Element).matches(pageSelector))
27
+ ) {
28
+ page += nextSibling.textContent!;
29
+ ({nextSibling} = nextSibling);
30
+ }
31
+ page = page.trim();
32
+ if (page.startsWith('/')) {
33
+ page = `:${mw.config.get('wgPageName')}${page}`;
34
+ }
35
+ open(new mw.Title(page, this.classList.contains('cm-mw-template-name') ? 10 : 0).getUrl(undefined), '_blank');
36
+ };
@@ -0,0 +1,54 @@
1
+ import type {CodeMirror} from './base';
2
+
3
+ export const instances = new WeakMap<HTMLTextAreaElement, CodeMirror>();
4
+
5
+ const getInstance = ($ele: JQuery<HTMLTextAreaElement>): CodeMirror => instances.get($ele[0]!)!;
6
+
7
+ function getCaretPosition(this: JQuery<HTMLTextAreaElement>, option: {startAndEnd: true}): [number, number];
8
+ function getCaretPosition(this: JQuery<HTMLTextAreaElement>, option?: {startAndEnd?: false}): number;
9
+ function getCaretPosition(
10
+ this: JQuery<HTMLTextAreaElement>,
11
+ option?: {startAndEnd?: boolean},
12
+ ): [number, number] | number {
13
+ const {view: {state: {selection: {main}}}} = getInstance(this);
14
+ return option?.startAndEnd ? [main.from, main.to] : main.head;
15
+ }
16
+
17
+ /**
18
+ * jQuery.textSelection overrides for CodeMirror.
19
+ * See jQuery.textSelection.js for method documentation
20
+ */
21
+ export const textSelection = {
22
+ getContents(this: JQuery<HTMLTextAreaElement>): string {
23
+ return getInstance(this).view.state.doc.toString();
24
+ },
25
+ setContents(this: JQuery<HTMLTextAreaElement>, content: string): JQuery<HTMLTextAreaElement> {
26
+ getInstance(this).setContent(content);
27
+ return this;
28
+ },
29
+ getSelection(this: JQuery<HTMLTextAreaElement>): string {
30
+ const {view: {state}} = getInstance(this);
31
+ return state.sliceDoc(state.selection.main.from, state.selection.main.to);
32
+ },
33
+ setSelection(
34
+ this: JQuery<HTMLTextAreaElement>,
35
+ {start, end}: {start: number, end?: number},
36
+ ): JQuery<HTMLTextAreaElement> {
37
+ const {view} = getInstance(this);
38
+ view.dispatch({
39
+ selection: {anchor: start, head: end ?? start},
40
+ });
41
+ view.focus();
42
+ return this;
43
+ },
44
+ replaceSelection(this: JQuery<HTMLTextAreaElement>, value: string): JQuery<HTMLTextAreaElement> {
45
+ const {view} = getInstance(this);
46
+ view.dispatch(view.state.replaceSelection(value));
47
+ return this;
48
+ },
49
+ getCaretPosition,
50
+ scrollToCaretPosition(this: JQuery<HTMLTextAreaElement>): JQuery<HTMLTextAreaElement> {
51
+ getInstance(this).view.dispatch({scrollIntoView: true});
52
+ return this;
53
+ },
54
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bhsd/codemirror-mediawiki",
3
- "version": "2.1.12",
3
+ "version": "2.1.15",
4
4
  "description": "Modified CodeMirror mode based on wikimedia/mediawiki-extensions-CodeMirror",
5
5
  "keywords": [
6
6
  "mediawiki",
@@ -16,9 +16,10 @@
16
16
  "!/src/gh-page.ts",
17
17
  "!/src/plugins.ts",
18
18
  "!/src/*.d.ts",
19
+ "/mw/*.ts",
20
+ "!/mw/*.d.ts",
19
21
  "/dist/",
20
- "/mediawiki.css",
21
- "/mw/dist/"
22
+ "/mediawiki.css"
22
23
  ],
23
24
  "browser": "dist/main.min.js",
24
25
  "main": "./dist/main.min.js",
@@ -29,7 +30,7 @@
29
30
  },
30
31
  "scripts": {
31
32
  "build:core": "esbuild ./src/codemirror.ts --bundle --minify --target=es2018 --format=esm --sourcemap --outfile=dist/main.min.js && tsc --emitDeclarationOnly && rm dist/gh-page.d.ts",
32
- "build:mw": "bash build.sh mw/base.ts mw/dist/base.js",
33
+ "build:mw": "esbuild ./mw/base.ts --bundle --minify --target=es2018 --format=esm --sourcemap --outfile=dist/mw.min.js",
33
34
  "build:gh-page": "bash build.sh src/gh-page.ts gh-page.js",
34
35
  "build": "npm run build:core && npm run build:mw",
35
36
  "lint:ts": "tsc --noEmit && tsc --project mw/tsconfig.json --noEmit && eslint --cache .",
package/src/codemirror.ts CHANGED
@@ -66,10 +66,10 @@ const CDN = 'https://testingcf.jsdelivr.net';
66
66
  /**
67
67
  * 使用传统方法加载脚本
68
68
  * @param src 脚本地址
69
- * @param target 脚本全局变量名
69
+ * @param globalConst 脚本全局变量名
70
70
  */
71
- const loadScript = (src: string, target: string): Promise<void> => new Promise(resolve => {
72
- if (target in window) {
71
+ const loadScript = (src: string, globalConst: string): Promise<void> => new Promise(resolve => {
72
+ if (globalConst in window) {
73
73
  resolve();
74
74
  return;
75
75
  }
@@ -91,13 +91,14 @@ const pos = (doc: Text, line: number, column: number): number => doc.line(line).
91
91
 
92
92
  export class CodeMirror6 {
93
93
  readonly #textarea;
94
- readonly #language;
95
- readonly #linter;
96
- readonly #extensions;
97
- readonly #indent;
98
94
  readonly #view;
95
+ readonly #language = new Compartment();
96
+ readonly #linter = new Compartment();
97
+ readonly #extensions = new Compartment();
98
+ readonly #indent = new Compartment();
99
99
  #lang;
100
100
  #visible = false;
101
+ #preferred = new Set<string>();
101
102
 
102
103
  get textarea(): HTMLTextAreaElement {
103
104
  return this.#textarea;
@@ -123,10 +124,6 @@ export class CodeMirror6 {
123
124
  constructor(textarea: HTMLTextAreaElement, lang = 'plain', config?: unknown) {
124
125
  this.#textarea = textarea;
125
126
  this.#lang = lang;
126
- this.#language = new Compartment();
127
- this.#linter = new Compartment();
128
- this.#extensions = new Compartment();
129
- this.#indent = new Compartment();
130
127
  let timer: number | undefined;
131
128
  const extensions = [
132
129
  this.#language.of(languages[lang]!(config)),
@@ -166,7 +163,7 @@ export class CodeMirror6 {
166
163
  const {fontSize, lineHeight} = getComputedStyle(textarea);
167
164
  textarea.parentNode!.insertBefore(this.#view.dom, textarea);
168
165
  this.#minHeight();
169
- this.#view.dom.style.fontSize = fontSize;
166
+ this.#view.scrollDOM.style.fontSize = fontSize;
170
167
  this.#view.scrollDOM.style.lineHeight = lineHeight;
171
168
  this.toggle(true);
172
169
  }
@@ -252,16 +249,23 @@ export class CodeMirror6 {
252
249
  * 添加扩展
253
250
  * @param names 扩展名
254
251
  */
255
- prefer(names: readonly string[]): void {
252
+ prefer(names: string[] | Record<string, boolean>): void {
253
+ if (Array.isArray(names)) {
254
+ this.#preferred = new Set(names.filter(name => avail[name]));
255
+ } else {
256
+ for (const [name, enable] of Object.entries(names)) {
257
+ if (enable && avail[name]) {
258
+ this.#preferred.add(name);
259
+ } else {
260
+ this.#preferred.delete(name);
261
+ }
262
+ }
263
+ }
256
264
  this.#view.dispatch({
257
265
  effects: [
258
- this.#extensions.reconfigure(names.map(name => {
259
- const option = avail[name];
260
- if (option) {
261
- const [extension, configs] = option;
262
- return extension(configs[this.#lang]);
263
- }
264
- return [];
266
+ this.#extensions.reconfigure([...this.#preferred].map(name => {
267
+ const [extension, configs] = avail[name]!;
268
+ return extension(configs[this.#lang]);
265
269
  })),
266
270
  ],
267
271
  });
package/src/mediawiki.ts CHANGED
@@ -951,7 +951,7 @@ class MediaWiki {
951
951
  const isCloseTag = Boolean(stream.eat('/')),
952
952
  mt = stream.match(/^[^>/\s.*,[\]{}$^+?|\\'`~<=!@#%&()-]+/u) as RegExpMatchArray | false;
953
953
  if (mt) {
954
- const tagname = mt[0]!.toLowerCase();
954
+ const tagname = mt[0].toLowerCase();
955
955
  if (tagname in this.config.tags) {
956
956
  // Parser function
957
957
  state.stack.push(state.tokenize);