Эффективное редактирование вики-текстов — плагин CodeEditor

From Wiki4Intranet
Jump to: navigation, search
This wikilog article is a draft, it was not published yet.
Line 15: Line 15:
 
Осталось чуть настроить его, чтобы было удобней русскоязычным пользователям MediaWiki (да, без этого будет не оч)
 
Осталось чуть настроить его, чтобы было удобней русскоязычным пользователям MediaWiki (да, без этого будет не оч)
  
<source code="javascript">
+
<source code="C">
 
/**
 
/**
 
  * @type {Context}
 
  * @type {Context}

Revision as of 10:00, 10 April 2024

Вики-статьи, с их возможностью включений, шаблонов, макросов отлично подходят для формирования целостной, самособираемой технической документации по различным проектам. Ведь альтернативы:

  • Офисные форматы с слабыми возможностями включения документов (OpenOffice, Word) — не дотягивают по гибкости.
  • SGML Docbook — было неплохо для 90ых, но протухло и сдохло.
  • LaTeX — неплохо, но наследие ужасной разметки и слабая генерация html-контента — не то.
  • Pandoc-стек с Markdown — очень перспективно, но до сих пор нет стандарта на включение документов (куча фильтров, у каждого свои проблемы).

Основные проблемы написания технических документов с вики-системами и вообще любыми веб-CMS — не очень удобно использовать стандартную textare для разметки, хочется заюзать все пространство вкладки браузера, и возможности нормального редактора, типа VS Code. Есть всякие такие интеграторы с VS Code, но все-таки не особо удобно, отдельно VS Code с его мешаниной вкладок, отдельно броузер с его вкладками, особенно когда редактируешь кучу документов — надо бы чтобы это было встроено в броузер, чтобы как-то рулить ими («Tree Style Tab» — почему еще не все с этим живут?).

Для последний версий MediaWiki уже есть https://www.mediawiki.org/wiki/Extension:CodeEditor — очень похоже на то что надо, но наша сборка пока еще (все сил нет обновлять) на замороженных старых версиях MediaWiki, наверно не сработает.

С другой стороны, а почему бы не поставить экстенш прямо в броузер? Собственно более умные редакторы textarea всегда были тем, что хотелось опытным пользователям (сам в нулевых писал на первом механизме FF extensionнов интеграцию с notepad++…), и вот, есть расширение https://addons.mozilla.org/en-US/firefox/addon/code-editor/ , которое затаскивает «почти VS Code» (ну вернее «Monaco Editor», на котором он основан), прямо в Firefox.

Осталось чуть настроить его, чтобы было удобней русскоязычным пользователям MediaWiki (да, без этого будет не оч)

Invalid language.

You need to specify a language like this: <source lang="html4strict">...</source>

Supported languages for syntax highlighting:

4cs, 6502acme, 6502kickass, 6502tasm, 68000devpac, abap, actionscript, actionscript3, ada, aimms, algol68, apache, applescript, arm, asm, asp, asymptote, autoconf, autohotkey, autoit, avisynth, awk, bascomavr, bash, basic4gl, bf, bibtex, blitzbasic, bnf, boo, c, caddcl, cadlisp, cfdg, cfm, chaiscript, chapel, cil, clojure, cmake, cobol, coffeescript, cpp, csharp, css, cuesheet, d, dart, dcl, dcpu16, dcs, delphi, diff, div, dos, dot, e, ecmascript, eiffel, email, epc, erlang, euphoria, ezt, f1, falcon, fo, fortran, freebasic, freeswitch, fsharp, gambas, gdb, genero, genie, gettext, glsl, gml, gnuplot, go, groovy, gwbasic, haskell, haxe, hicest, hq9plus, html4strict, html5, icon, idl, ini, inno, intercal, io, ispfpanel, j, java, java5, javascript, jcl, jquery, kixtart, klonec, klonecpp, latex, lb, ldif, lisp, llvm, locobasic, logtalk, lolcode, lotusformulas, lotusscript, lscript, lsl2, lua, m68k, magiksf, make, mapbasic, matlab, mirc, mmix, modula2, modula3, mpasm, mxml, mysql, nagios, netrexx, newlisp, nginx, nimrod, nsis, oberon2, objc, objeck, ocaml, octave, oobas, oorexx, oracle11, oracle8, oxygene, oz, parasail, parigp, pascal, pcre, per, perl, perl6, pf, php, pic16, pike, pixelbender, pli, plsql, postgresql, postscript, povray, powerbuilder, powershell, proftpd, progress, prolog, properties, providex, purebasic, pycon, pys60, python, q, qbasic, qml, racket, rails, rbs, rebol, reg, rexx, robots, rpmspec, rsplus, ruby, rust, sas, scala, scheme, scilab, scl, sdlbasic, smalltalk, smarty, spark, sparql, sql, standardml, stonescript, systemverilog, tcl, teraterm, text, thinbasic, tsql, typoscript, unicon, upc, urbi, uscript, vala, vb, vbnet, vbscript, vedit, verilog, vhdl, vim, visualfoxpro, visualprolog, whitespace, whois, winbatch, xbasic, xml, xpp, yaml, z80, zxbasic


/**
 * @type {Context}
 */
({
    /**
     * {@link https://microsoft.github.io/monaco-editor/docs.html#interfaces/editor.IStandaloneEditorConstructionOptions.html}
     * {@link https://microsoft.github.io/monaco-editor/docs.html#interfaces/editor.IStandaloneDiffEditorConstructionOptions.html}
     */
    options: {
        minimap: {
            enabled: false,
        },
        unicodeHighlight: {
            ambiguousCharacters: false,
        },        
        theme: "vs",
        language: "plaintext",
        wordWrap: "off",
        accessibilitySupport: "on",
        accessibilityPageSize: 20,
        scrollBeyondLastLine: true,
        ignoreTrimWhitespace: true,
        useInlineViewWhenSpaceIsLimited: true,
    },
    /**
     * {@link https://microsoft.github.io/monaco-editor/docs.html#interfaces/editor.IActionDescriptor.html}
     */
    actions: {
        "user.toggleWordWarp": {
            label: "Toggle Word Wrap",
            keybindings: [
                "Alt+KeyZ",
            ],
            contextMenuGroupId: "view",
            contextMenuOrder: 4.5,
            run(editor) {
                let wrappingInfo = editor.getOption(monaco.editor.EditorOption.wrappingInfo);
                editor.updateOptions({
                    wordWrapOverride2: wrappingInfo.wrappingColumn == -1 ? 'on' : 'off',
                });
            },
        },
        "user.toggleIgnoreTrimWhitespace": {
            label: "Toggle Show Trim Whitespace Diff",
            precondition: "isInDiffEditor",
            contextMenuGroupId: "view",
            contextMenuOrder: 4.6,
            run() {
                let editor = editorUtil.editor;
                let value = editor._options?.ignoreTrimWhitespace?.value;
                editor.updateOptions({
                    ignoreTrimWhitespace: !value,
                });
            },
        },
    },
    init: [
        {
            func() {
                // console.log("ext-code-editor.init");
            },
            args: [],
            injectImmediately: false,
        },
        {
            injectImmediately: true,
            func() {
                let addTouchTools = () => {
                    self.removeEventListener('touchstart', addTouchTools, true);
                    console.debug('addTouchTools');
                    editorUtil.addActions({
                        "user.undo": {
                            label: "Undo",
                            precondition: "textInputFocus && !editorReadonly",
                            contextMenuGroupId: " 1_modification",
                            contextMenuOrder: 11,
                            run(editor) {
                                editor.trigger("", "undo");
                            },
                        },
                        "user.redo": {
                            label: "Redo",
                            precondition: "textInputFocus && !editorReadonly",
                            contextMenuGroupId: " 1_modification",
                            contextMenuOrder: 12,
                            run(editor) {
                                editor.trigger("", "redo");
                            },
                        },
                        "user.paste": {
                            label: "Paste Clipboard Text",
                            precondition: "textInputFocus && !editorReadonly",
                            contextMenuGroupId: "9_cutcopypaste",
                            contextMenuOrder: 4,
                            async run(editor) {
                                // Requires ACCESS_LEVEL >=30
                                if (self.browser) {
                                    try {
                                        await browser.permissions.request({ permissions: ['clipboardRead'] });
                                    } catch (e) {
                                        console.warn(e);
                                    }
                                }
                                try {
                                    let text = await navigator.clipboard.readText();
                                    if (!text) return;
                                    editor.executeEdits("", [{
                                        forceMoveMarkers: true,
                                        range: editor.getSelection(),
                                        text,
                                    }]);
                                } catch (e) {
                                    console.warn(e);
                                } finally {
                                    // await browser.permissions.remove({ permissions: ['clipboardRead'] });
                                }
                            },
                        },
                        "user.delete": {
                            label: "Delete",
                            precondition: "!editorReadonly && editorHasSelection",
                            contextMenuGroupId: "9_cutcopypaste",
                            contextMenuOrder: 5,
                            run(editor) {
                                editor.executeEdits("", [{
                                    forceMoveMarkers: true,
                                    range: editor.getSelection(),
                                    text: "",
                                }]);
                            },
                        },
                        "user.selectAll": {
                            label: "Select All",
                            precondition: "textInputFocus",
                            contextMenuGroupId: "9_cutcopypaste",
                            contextMenuOrder: 6,
                            run(editor) {
                                editor.setSelection(editor.getModel().getFullModelRange());
                            },
                        },
                        "user.find": {
                            label: "Find...",
                            precondition: "textInputFocus && !findWidgetVisible",
                            contextMenuGroupId: "view",
                            contextMenuOrder: 4.9,
                            run() {
                                editor.trigger("", "actions.find");
                            },
                        },
                    });
                };
                self.addEventListener('touchstart', addTouchTools, true);
            },
        },
    ],
})