@bhsd/codemirror-mediawiki 2.1.11 → 2.1.13
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 +12 -3
- package/dist/codemirror.d.ts +1 -1
- package/dist/main.min.js +12 -12
- package/dist/main.min.js.map +3 -3
- package/dist/mw.min.js +2 -0
- package/dist/mw.min.js.map +7 -0
- package/mediawiki.css +25 -25
- package/mw/base.ts +199 -0
- package/mw/config.ts +148 -0
- package/mw/openLinks.ts +36 -0
- package/mw/textSelection.ts +54 -0
- package/package.json +14 -13
- package/src/codemirror.ts +74 -44
- package/src/mediawiki.ts +1 -1
- package/mw/dist/base.js +0 -265
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.13/dist/main.min.js";var b=mw.loader.getState("ext.CodeMirror")!==null,S=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:a,"case-sensitive":c})=>o.map(s=>({alias:(c?s:s.toLowerCase()).replace(/:$/u,""),name:a}))),r={};for(let{alias:o,name:a}of n)r[o]=a;return r},T=(e,t)=>[!0,!1].map(i=>h(e,t,i)),v=e=>{mw.config.set("extCodeMirrorConfig",e)},x=async()=>{b&&!M&&await mw.loader.using(S);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:a}}=await new mw.Api().get({meta:"siteinfo",siprop:["general","magicwords",...e&&!t?[]:["extensiontags","functionhooks","variables"]],formatversion:"2"}),c=new Set(["msg","raw","msgnw","subst","safesubst"]);if(e&&!t){let{functionSynonyms:[s]}=e;"subst"in s||Object.assign(s,h(n,({name:m})=>c.has(m)))}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 m of r)e.tags[m.slice(1,-1)]=!0;let s=new Set([...o,...a,...c]);e.functionSynonyms=T(n,({name:m})=>s.has(m)),e.doubleUnderscore=T(n,({aliases:m})=>m.some(E=>/^__.+__$/u.test(E)))}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:A,userAgent:H,maxTouchPoints:P,platform:j}=navigator,J=A.includes("Apple Computer")&&(H.includes("Mobile/")||P>2)||j.includes("Mac")?"metaKey":"ctrlKey",l=".cm-mw-template-name, .cm-mw-link-pagename",y=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,g=e=>d.get(e[0]);function Q(e){let{view:{state:{selection:{main:t}}}}=g(this);return e!=null&&e.startAndEnd?[t.from,t.to]:t.head}var k={getContents(){return g(this).view.state.doc.toString()},setContents(e){return g(this).setContent(e),this},getSelection(){let{view:{state:e}}=g(this);return e.sliceDoc(e.selection.main.from,e.selection.main.to)},setSelection({start:e,end:t}){let{view:i}=g(this);return i.dispatch({selection:{anchor:e,head:t!=null?t:e}}),i.focus(),this},replaceSelection(e){let{view:t}=g(this);return t.dispatch(t.state.replaceSelection(e)),this},getCaretPosition:Q,scrollToCaretPosition(){return g(this).view.dispatch({scrollIntoView:!0}),this}};mw.loader.load("https://testingcf.jsdelivr.net/npm/@bhsd/codemirror-mediawiki@2.1.13/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",k),mw.hook("wiki-codemirror6").fire(this)}toggle(t=!this.visible){super.toggle(t),$(this.textarea).data("jquery.textSelection",t&&k)}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 x(),a={...await wikiparse.getConfig(),ext:Object.keys(o.tags),namespaces:mw.config.get("wgFormattedNamespaces"),nsid:o.nsid,doubleUnderscore:o.doubleUnderscore.map(c=>Object.keys(c).map(s=>s.slice(2,-2))),variants:o.variants,protocol:o.urlProtocols.replace(/\\:/gu,":")};if([a.parserFunction[0]]=o.functionSynonyms,!b)for(let[c,s]of Object.entries(o.functionSynonyms[0]))c.startsWith("#")||(a.parserFunction[0][`#${c}`]=s);a.parserFunction[1]=[...Object.keys(o.functionSynonyms[1]),"="];for(let c of Object.keys(o.img))a.img[c]=o.img[c].slice(4);wikiparse.setConfig(a)}}f[n]&&this.lint(f[n])}prefer(t){super.prefer(t),t.includes("openLinks")?(mw.loader.load("mediawiki.Title"),$(this.view.contentDOM).on("click",l,y).css("--codemirror-cursor","pointer")):$(this.view.contentDOM).off("click",l,y).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 x();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 a;let{wgAction:t,wgNamespaceNumber:i,wgPageContentModel:n}=mw.config.get(),r;if(t!=="edit"&&t!=="submit")await mw.loader.using("oojs-ui-windows"),r=(a=await OO.ui.prompt("Language:")||void 0)==null?void 0:a.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}(await w.fromTextArea(e.target,r)).defaultLint(!0,i)})())});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.13/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.13/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[]): void {\n\t\tsuper.prefer(extensions);\n\t\tif (extensions.includes('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\tconst cm = await CodeMirror.fromTextArea(e.target as HTMLTextAreaElement, lang);\n\t\t\tvoid cm.defaultLint(true, wgNamespaceNumber);\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/mediawiki.css
CHANGED
|
@@ -161,85 +161,85 @@
|
|
|
161
161
|
/* backgrounds */
|
|
162
162
|
.cm-mw-tag-pre,
|
|
163
163
|
.cm-mw-tag-nowiki {
|
|
164
|
-
background-color: rgba(
|
|
164
|
+
background-color: rgba(0, 0, 0, .04);
|
|
165
165
|
}
|
|
166
166
|
.cm-mw-template-ground {
|
|
167
|
-
background-color: rgba(
|
|
167
|
+
background-color: rgba(170, 17, 17, .04);
|
|
168
168
|
}
|
|
169
169
|
.cm-mw-template2-ground {
|
|
170
|
-
background-color: rgba(
|
|
170
|
+
background-color: rgba(170, 17, 17, .08);
|
|
171
171
|
}
|
|
172
172
|
.cm-mw-template3-ground {
|
|
173
|
-
background-color: rgba(
|
|
173
|
+
background-color: rgba(170, 17, 17, .12);
|
|
174
174
|
}
|
|
175
175
|
.cm-mw-template-ext-ground,
|
|
176
176
|
.cm-mw-ext-ground,
|
|
177
177
|
.cm-mw-exttag {
|
|
178
|
-
background-color: rgba(
|
|
178
|
+
background-color: rgba(119, 0, 170, .04);
|
|
179
179
|
}
|
|
180
180
|
.cm-mw-template-ext2-ground,
|
|
181
181
|
.cm-mw-ext2-ground {
|
|
182
|
-
background-color: rgba(
|
|
182
|
+
background-color: rgba(119, 0, 170, .08);
|
|
183
183
|
}
|
|
184
184
|
.cm-mw-template-ext3-ground,
|
|
185
185
|
.cm-mw-ext3-ground {
|
|
186
|
-
background-color: rgba(
|
|
186
|
+
background-color: rgba(119, 0, 170, .12);
|
|
187
187
|
}
|
|
188
188
|
.cm-mw-template-link-ground,
|
|
189
189
|
.cm-mw-ext-link-ground,
|
|
190
190
|
.cm-mw-link-ground {
|
|
191
|
-
background-color: rgba(
|
|
191
|
+
background-color: rgba(34, 17, 153, .04);
|
|
192
192
|
}
|
|
193
193
|
.cm-mw-template-ext-link-ground,
|
|
194
194
|
.cm-mw-ext2-link-ground {
|
|
195
|
-
background-color: rgba(
|
|
195
|
+
background-color: rgba(77, 9, 162, .08);
|
|
196
196
|
}
|
|
197
197
|
.cm-mw-template-ext2-link-ground,
|
|
198
198
|
.cm-mw-ext3-link-ground {
|
|
199
|
-
background-color: rgba(
|
|
199
|
+
background-color: rgba(91, 6, 164, .12);
|
|
200
200
|
}
|
|
201
201
|
.cm-mw-template-ext3-link-ground {
|
|
202
|
-
background-color: rgba(
|
|
202
|
+
background-color: rgba(98, 4, 166, .16);
|
|
203
203
|
}
|
|
204
204
|
.cm-mw-template2-ext-ground {
|
|
205
|
-
background-color: rgba(
|
|
205
|
+
background-color: rgba(145, 9, 94, .08);
|
|
206
206
|
}
|
|
207
207
|
.cm-mw-template2-ext2-ground {
|
|
208
|
-
background-color: rgba(
|
|
208
|
+
background-color: rgba(136, 6, 119, .12);
|
|
209
209
|
}
|
|
210
210
|
.cm-mw-template2-ext3-ground {
|
|
211
|
-
background-color: rgba(
|
|
211
|
+
background-color: rgba(132, 4, 132, .16);
|
|
212
212
|
}
|
|
213
213
|
.cm-mw-template2-link-ground {
|
|
214
|
-
background-color: rgba(
|
|
214
|
+
background-color: rgba(102, 17, 85, .08);
|
|
215
215
|
}
|
|
216
216
|
.cm-mw-template2-ext-link-ground {
|
|
217
|
-
background-color: rgba(
|
|
217
|
+
background-color: rgba(108, 11, 113, .12);
|
|
218
218
|
}
|
|
219
219
|
.cm-mw-template2-ext2-link-ground {
|
|
220
|
-
background-color: rgba(
|
|
220
|
+
background-color: rgba(111, 9, 128, .16);
|
|
221
221
|
}
|
|
222
222
|
.cm-mw-template2-ext3-link-ground {
|
|
223
|
-
background-color: rgba(
|
|
223
|
+
background-color: rgba(112, 7, 136, .2);
|
|
224
224
|
}
|
|
225
225
|
.cm-mw-template3-ext-ground {
|
|
226
|
-
background-color: rgba(
|
|
226
|
+
background-color: rgba(153, 11, 68, .12);
|
|
227
227
|
}
|
|
228
228
|
.cm-mw-template3-ext2-ground {
|
|
229
|
-
background-color: rgba(
|
|
229
|
+
background-color: rgba(145, 9, 94, .16);
|
|
230
230
|
}
|
|
231
231
|
.cm-mw-template3-ext3-ground {
|
|
232
|
-
background-color: rgba(
|
|
232
|
+
background-color: rgba(139, 7, 109, .2);
|
|
233
233
|
}
|
|
234
234
|
.cm-mw-template3-link-ground {
|
|
235
|
-
background-color: rgba(
|
|
235
|
+
background-color: rgba(125, 17, 62, .12);
|
|
236
236
|
}
|
|
237
237
|
.cm-mw-template3-ext-link-ground {
|
|
238
|
-
background-color: rgba(
|
|
238
|
+
background-color: rgba(123, 13, 89, .16);
|
|
239
239
|
}
|
|
240
240
|
.cm-mw-template3-ext2-link-ground {
|
|
241
|
-
background-color: rgba(
|
|
241
|
+
background-color: rgba(122, 10, 105, .2);
|
|
242
242
|
}
|
|
243
243
|
.cm-mw-template3-ext3-link-ground {
|
|
244
|
-
background-color: rgba(
|
|
244
|
+
background-color: rgba(122, 9, 116, .24);
|
|
245
245
|
}
|
package/mw/base.ts
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import {CodeMirror6} from 'https://testingcf.jsdelivr.net/npm/@bhsd/codemirror-mediawiki@2.1.13/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.13/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[]): void {
|
|
138
|
+
super.prefer(extensions);
|
|
139
|
+
if (extensions.includes('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
|
+
const cm = await CodeMirror.fromTextArea(e.target as HTMLTextAreaElement, lang);
|
|
194
|
+
void cm.defaultLint(true, wgNamespaceNumber);
|
|
195
|
+
})();
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
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
|
+
};
|
package/mw/openLinks.ts
ADDED
|
@@ -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
|
+
};
|