注意:在保存之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。
?_=1
来访问最新页面。https://zh.moegirl.org.cn/User:%E6%9C%BA%E6%99%BA%E7%9A%84%E5%B0%8F%E9%B1%BC%E5%90%9B/gadget/MonacoEditor.js?_=1
/** * MediaWiki Gadget MonacoEditor * @author Dragon-Fish <dragon-fish@qq.com> * @license MIT */ ;(async () => { const textarea = document.querySelector('textarea#wpTextbox1') const language = getLangFromContentModel() if (!textarea || !language) return const initialValue = textarea.value const MONACO_CDN_BASE = window.MONACO_CDN_BASE || 'https://cdn.jsdelivr.net/npm/monaco-editor@0.44.0/min' const MONACO_EXTRA_LIBS = [ ...[window.MONACO_EXTRA_LIBS || []], [ 'https://cdn.jsdelivr.net/npm/@wikimedia/types-wikimedia@0.4.1/MediaWiki.d.ts', 'MediaWiki.d.ts', ], [ 'https://cdn.jsdelivr.net/npm/@types/jquery/JQuery.d.ts', 'jquery/JQuery.d.ts', ], [ 'https://cdn.jsdelivr.net/npm/@types/jquery/JQueryStatic.d.ts', 'jquery/JQueryStatic.d.ts', ], ['declare const $: JQueryStatic', 'jquery/JQueryGlobal.d.ts'], ] window.MonacoEnvironment = { ...window.MonacoEnvironment, baseUrl: MONACO_CDN_BASE, getWorkerUrl(workerId, label) { let path = 'base/worker/workerMain.js' if (label === 'json') { path = 'language/json/jsonWorker.js' } else if (label === 'css' || label === 'scss' || label === 'less') { path = 'language/css/cssWorker.js' } else if ( label === 'html' || label === 'handlebars' || label === 'razor' ) { path = 'language/html/htmlWorker.js' } else if (label === 'typescript' || label === 'javascript') { path = 'language/typescript/tsWorker.js' } return `data:text/javascript;charset=utf-8,${encodeURIComponent(` self.MonacoEnvironment = { baseUrl: '${MONACO_CDN_BASE}' } importScripts('${MONACO_CDN_BASE}/vs/${path}') `)}` }, } await loadScript(`${MONACO_CDN_BASE}/vs/loader.js`) const require = window.require require.config({ paths: { vs: `${MONACO_CDN_BASE}/vs`, }, }) require(['vs/editor/editor.main'], () => { mw?.hook('monaco').fire(monaco) const container = document.createElement('div') container.style.width = '100%' container.style.height = '75vh' document .querySelector('form#editform .editOptions') ?.insertAdjacentElement('beforebegin', container) document.querySelector('form#editform .wikiEditor-ui').style.display = 'none' textarea.style.display = 'none' const model = monaco.editor.createModel(initialValue, language) const editor = monaco.editor.create(container, { model, automaticLayout: true, theme: 'vs-dark', tabSize: 2, }) model.onDidChangeContent(() => { textarea.value = model.getValue() }) console.info('[MONACO] Rendered', editor, model) mw?.hook('monaco.editor').fire({ monaco, editor, model, language, addExtraLib: (...args) => addExtraLib(monaco, model, ...args), addExternalExtraLib: (...args) => addExternalExtraLib(monaco, model, ...args), }) if (language === 'javascript') { addBatchExtraLibs(monaco, model, MONACO_EXTRA_LIBS) } }) async function loadScript(src = '') { return new Promise((resolve, reject) => { const s = document.createElement('script') s.src = src document.body.appendChild(s) s.addEventListener('load', resolve) s.addEventListener('error', reject) }) } function getLangFromContentModel() { const nsNumber = mw.config.get('wgNamespaceNumber') const pageName = mw.config.get('wgPageName') const contentModel = mw.config.get('wgPageContentModel', '').toLowerCase() if (pageName.endsWith('.js') || contentModel === 'javascript') { return 'javascript' } else if (pageName.endsWith('.css') || contentModel === 'css') { return 'css' } else if ( (nsNumber === 828 || ['scribunto', 'lua'].includes(contentModel)) && !pageName.endsWith('/doc') ) { return 'lua' } else if (nsNumber === 274) { return 'html' } else if (pageName.endsWith('.json')) { return 'json' } } /** * @param monaco * @param model * @param {string} libSource * @param {string?} fileName */ function addExtraLib(monaco, model, libSource, fileName = '') { const URI_NS = 'ts:mw' fileName = fileName || `${crypto.randomUUID()}.d.ts` monaco.languages.typescript.javascriptDefaults.addExtraLib( libSource, `${URI_NS}/${fileName}` ) model.updateOptions({ uri: monaco.Uri.parse(`${URI_NS}/main.js`), }) } /** * @param monaco * @param model * @param {string} libUrl * @param {string?} fileName */ async function addExternalExtraLib(monaco, model, libUrl, fileName) { const libSource = await fetch(libUrl).then((i) => i.text()) fileName = fileName || libSource.split('/').pop()?.split('?')[0] return addExtraLib(monaco, model, libSource, fileName) } /** * internal helper function * @param {(string | [string, string])[]} libs */ async function addBatchExtraLibs(monaco, model, libs = []) { return Promise.all( libs.map((lib) => { if (typeof lib === 'string') { lib = [lib] } if (!Array.isArray(lib)) return Promise.resolve(null) if (typeof lib?.[0] !== 'string') return Promise.resolve(null) const helper = lib[0]?.startsWith('http') ? addExternalExtraLib : addExtraLib return helper(monaco, model, lib[0], lib[1]) }) ) } })()