diff --git a/packages/monaco/index.html b/packages/monaco/index.html new file mode 100644 index 0000000..82b74ac --- /dev/null +++ b/packages/monaco/index.html @@ -0,0 +1,11 @@ + + + + + + Document + + + + + diff --git a/packages/monaco/package.json b/packages/monaco/package.json new file mode 100644 index 0000000..5e6b7b1 --- /dev/null +++ b/packages/monaco/package.json @@ -0,0 +1,41 @@ +{ + "name": "inpageedit-plugin-monaco", + "description": "Monaco Editor for InPageEdit", + "version": "1.0.0", + "private": true, + "type": "module", + "module": "./dist/index.mjs", + "files": [ + "dist" + ], + "exports": { + ".": { + "import": "./dist/index.mjs" + } + }, + "scripts": { + "dev": "vite", + "build": "vite build" + }, + "$ipe": { + "name": "Monaco Editor", + "categories": [], + "loader": { + "kind": "module", + "entry": "dist/index.mjs", + "styles": [], + "main_export": "default" + }, + "dev_loader": { + "entry": "src/index.ts", + "styles": [] + } + }, + "dependencies": { + "modern-monaco": "^0.2.2" + }, + "devDependencies": { + "rolldown": "1.0.0-beta.47", + "vite": "npm:rolldown-vite@latest" + } +} \ No newline at end of file diff --git a/packages/monaco/src/index.ts b/packages/monaco/src/index.ts new file mode 100644 index 0000000..8236a42 --- /dev/null +++ b/packages/monaco/src/index.ts @@ -0,0 +1,112 @@ +import { BasePlugin } from '~~/defineIPEPlugin.js' +import type { Events, InPageEdit } from '@inpageedit/core' +import type {} from '@inpageedit/core/services/WikiTitleService' +import type {} from '@inpageedit/core/plugins/toolbox/index' +import type {} from '@inpageedit/core/plugins/quick-edit/index' +import { IWikiPage } from '@inpageedit/core/dist/models/WikiPage/index.js' + +export class PluginMonaco extends BasePlugin { + constructor(ctx: InPageEdit) { + super(ctx, {}, 'monaco-editor') + ctx.set('plugin:monaco-editor', true) + } + + protected async start() { + this.ctx.on('quick-edit/wiki-page', this.onQuickEditWikiPage.bind(this)) + } + + async onQuickEditWikiPage( + payload: Parameters[0] + ) { + const { init } = await import('modern-monaco') + + const { modal, wikiPage } = payload + const textarea = modal + .get$content() + .querySelector('textarea[name="text"]') + const wrapper = modal + .get$content() + .querySelector('.ipe-quickEdit__content') + if (!textarea || !wrapper) return + + const language = + wikiPage.contentmodel || + this.guessLangByTitle(wikiPage.title) || + 'wikitext' + const monaco = await init({}) + const container = document.createElement('div') + container.style.width = wrapper.clientWidth + 'px' + container.style.height = '65lvh' + wrapper.appendChild(container) + const editor = monaco.editor.create(container, { + theme: 'vs-dark', + automaticLayout: true, + language, + tabSize: 2, + glyphMargin: true, + wordWrap: language === 'wikitext' ? 'on' : 'off', + wordBreak: language === 'wikitext' ? 'keepAll' : 'normal', + unicodeHighlight: + language === 'wikitext' + ? { + ambiguousCharacters: false, + } + : undefined, + }) + const model = this.createModel(monaco, wikiPage) + editor.setModel(model) + model.onDidChangeAttached(() => { + textarea.value = model.getValue() + textarea.dispatchEvent(new Event('input')) + textarea.dispatchEvent(new Event('change')) + }) + } + + guessLangByTitle(input = '') { + const title = this.ctx.wikiTitle.newTitle(input) + const nsNumber = title.getNamespaceId() + const pageName = title.getMainText() + const ext = pageName.split('.').pop() + if (ext === 'js') { + return 'javascript' + } else if (ext === 'css') { + return 'css' + } + // NS_MODULE + else if (nsNumber === 828 && !pageName.endsWith('/doc')) { + return 'lua' + } + // NS_WIDGET + else if (nsNumber === 274) { + return 'html' + } else if (ext === 'json') { + return 'json' + } + return 'wikitext' + } + + async createWorkspace(wikiPage: IWikiPage) { + const { Workspace } = await import('modern-monaco') + const workspace = new Workspace({ + name: wikiPage.title, + initialFiles: { + [wikiPage.title]: wikiPage.revisions?.[0]?.content || '', + }, + entryFile: wikiPage.title, + }) + workspace.openTextDocument(wikiPage.title) + return workspace + } + + createModel( + monaco: Awaited>, + wikiPage: IWikiPage + ) { + return monaco.editor.createModel( + wikiPage.revisions?.[0]?.content || '', + wikiPage.contentmodel || + this.guessLangByTitle(wikiPage.title) || + 'wikitext' + ) + } +} diff --git a/packages/monaco/vite.config.ts b/packages/monaco/vite.config.ts new file mode 100644 index 0000000..8703ec8 --- /dev/null +++ b/packages/monaco/vite.config.ts @@ -0,0 +1,24 @@ +import { resolve } from 'node:path' +import { defineConfig } from 'vite' + +export default defineConfig({ + build: { + lib: { + entry: 'src/index.ts', + formats: ['es'], + fileName: () => 'index.mjs', + cssFileName: 'style.css', + }, + sourcemap: true, + rollupOptions: { + output: { + inlineDynamicImports: false, + }, + }, + }, + resolve: { + alias: { + '~~': resolve(import.meta.dirname, '../../common'), + }, + }, +})