1
0
This repository has been archived on 2024-06-01. You can view files and clone it, but cannot push or open issues or pull requests.
mediawiki-extensions-monaco.../assets/js/scripts.js
2020-09-20 04:35:53 +03:00

416 lines
21 KiB
JavaScript

// @see https://microsoft.github.io/monaco-editor/playground.html#interacting-with-the-editor-adding-an-action-to-an-editor-instance
(function(){
let init = function() {
let MediaWikiTokenizer = (function () {
function MediaWikiTokenizer() {
this.ignorecase = true;
this.empty = [
'area', 'base', 'basefont', 'br', 'col', 'frame',
'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param'
];
// escape codes for javascript/CSS strings
this.escapes = /\\(?:[btnfr\\"']|[0-7][0-7]?|[0-3][0-7]{2})/;
this.tokenizer = {
root: [
{ include: '@whitespace' },
// Link reference
[/\[\[/, { token: 'string.quote', bracket: '@open', next: '@linkReferenceBlock' }],
// Template usage
[/{{/, { token: 'type.type-$1', bracket: '@open', next: '@templateBlock.$1' }],
[/}}/, { token: 'type.type-$1', bracket: '@close' }],
// Bold
[/'''/, { token: 'bold.quote', bracket: '@open', next: '@boldBlock' }],
// Italic
[/''/, { token: 'italic.quote', bracket: '@open', next: '@italicBlock' }],
// HTML-Style blocks
[/<(\w+)\/>/, 'tag.tag-$1'],
[/<(\w+)/, {
cases: {
'@empty': { token: 'tag.tag-$1', next: '@tag.$1', log: 'Push stack to tag.$1' },
'@default': { token: 'tag.tag-$1', bracket: '@open', next: '@tag.$1', log: 'Push stack to tag.$1, bracket open' }
}
}],
[/<\/(\w+)\s*>/, { token: 'tag.tag-$1', bracket: '@close', log: 'Close bracket of tag.$1' }],
[/&\w+;/, 'string.escape']
],
boldBlock: [
[/'''/, { token: 'bold.quote', bracket: '@close', next: '@pop' }],
[/[^''']+/, { token: 'bold' }],
// Nested italic + bold, need a style to present both
[/''/, { token: "italic.quote", bracket: "@open", next: "@italicBlock" }]
],
italicBlock: [
[/''/, { token: "italic.quote", bracket: "@close", next: "@pop" }],
[/[^'']+/, { token: "italic" }]
],
linkReferenceBlock: [
[/\]\]/, { token: "string.quote", bracket: "@close", next: "@pop" }],
[/[^\]\]]+/, { token: "string" }]
],
templateBlock: [
[/{{/, { token: 'type.type-$1', bracket: '@open', next: '@templateBlock.$1' }],
[/}}/, { token: 'type.type-$2', next: '@pop' }],
[/\[\[/, { token: 'string.quote', bracket: '@open', next: '@linkReferenceBlock' }],
[/'''/, { token: 'bold.quote', bracket: '@open', next: '@boldBlock' }],
[/''/, { token: 'italic.quote', bracket: '@open', next: '@italicBlock' }]
],
// Tags
tag: [
[/[ \t\r\n]+/, 'white'],
[/(type)(\s*=\s*)(")([^"]+)(")/, ['attribute.name', 'delimiter', 'attribute.value',
{ token: 'attribute.value', switchTo: '@tag.$S2.$4' },
'attribute.value']],
[/(type)(\s*=\s*)(')([^']+)(')/, ['attribute.name', 'delimiter', 'attribute.value',
{ token: 'attribute.value', switchTo: '@tag.$S2.$4' },
'attribute.value']],
[/(\w+)(\s*=\s*)("[^"]*"|'[^']*')/, ['attribute.name', 'delimiter', 'attribute.value']],
[/\w+/, 'attribute.name'],
[/\/>/, 'tag.tag-$S2', '@pop'],
[/>/, {
cases: {
'$S2==style': { token: 'tag.tag-$S2', switchTo: '@inlineStyle.$S2', nextEmbedded: 'text/css', log: 'Entering CSS section ($S2)' },
'$S2==script': {
cases: {
'$S3': { token: 'tag.tag-$S2', switchTo: '@inlineScript.$S2', nextEmbedded: '$S3' },
'@default': { token: 'tag.tag-$S2', switchTo: '@inlineScript.$S2', nextEmbedded: 'javascript', log: 'Entering JS section ($S2)' }
}
},
'@default': { token: 'tag.tag-$S2', next: '@pop', log: 'Entering $S2 section' }
}
}],
],
inlineStyle: [
[/<\/style\s*>/, { token: '@rematch', next: '@pop', nextEmbedded: '@pop', log: 'Pop stack ($S2)' }]
],
inlineScript: [
[/<\/script\s*>/, { token: '@rematch', next: '@pop', nextEmbedded: '@pop', log: 'Pop stack ($S2)' }]
],
// scan embedded strings in javascript or css
// string.<delimiter>
string: [
[/[^\\"']+/, 'string'],
[/@escapes/, 'string.escape'],
[/\\./, 'string.escape.invalid'],
[/["']/, {
cases: {
'$#==$S2': { token: 'string', next: '@pop' },
'@default': 'string'
}
}]
],
whitespace: [
[/[ \t\r\n]+/, 'white'],
[/<!--/, 'comment', '@comment']
],
comment: [
[/[^<\-]+/, 'comment.content'],
[/-->/, 'comment', '@pop'],
[/<!--/, 'comment.content.invalid'],
[/[<\-]/, 'comment.content']
]
};
this.tokenPostfix = "";
}
return MediaWikiTokenizer;
}());
window.require.config({ paths: { 'vs': '/extensions/MonacoEditor/node_modules/monaco-editor/min/vs' }});
window.require(['vs/editor/editor.main'], function() {
let el_stock_editor = document.getElementById("wpTextbox1");
el_stock_editor.style.display = "none";
// Register a new language
monaco.languages.register({ id: 'wikitext' });
// Register a tokens provider for the language
monaco.languages.setMonarchTokensProvider('wikitext', new MediaWikiTokenizer());
// Register a completion item provider for the new language
monaco.languages.registerCompletionItemProvider('wikitext', {
provideCompletionItems: () => {
var suggestions = [{
label: 'syntax',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'<syntaxhighlight lang="$1">',
'$2',
'</syntaxhighlight>'
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'syntax inline',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'<syntaxhighlight lang="$1" inline>$2</syntaxhighlight>',
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'code',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'<code>$1</code>',
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'poem',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'<poem>$1</poem>',
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'bullet list',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'* $1',
''
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'numbered list',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'# $1',
''
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'bold',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
"'''$1'''",
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'italic',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
"''$1''",
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'heading 1',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
"= $1 =",
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'heading 2',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'== $1 ==',
''
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'heading 3',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'=== $1 ===',
''
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'heading 4',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'==== $1 ====',
''
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'heading 5',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'===== $1 =====',
''
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'heading 6',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'====== $1 ======',
''
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'category',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'[[Category:$1]]',
''
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'internal link',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'[[$1]]',
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'external link',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'[$1 $2]',
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'comment',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'<!--',
'$1',
'-->',
''
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'inline comment',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'<!-- $1 -->',
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'template',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'{{$1}}',
''
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'chunk: references',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'== References ==',
'{{Reflist}}',
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'reference',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'<ref>$1</ref>',
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'reference internal link',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'<ref>[[$1]]</ref>',
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'reference external link',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'<ref>[$1 $2]</ref>',
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'expanded quote',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'{{Quote | $1 | $2 | $3}}',
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'quote',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'{{Quote | $1 || $2}}',
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'expandable content',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'{{Expandable content | $1}}',
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'nowiki',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'<nowiki>$1</nowiki>',
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'horizontal rule',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'----',
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}, {
label: 'related article',
kind: monaco.languages.CompletionItemKind.Snippet,
insertText: [
'{{#related:$1}}',
].join('\n'),
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
}];
return { suggestions: suggestions };
}
});
let language = 'wikitext';
if (typeof RLCONF.wgPageContentModel !== 'undefined') {
switch (RLCONF.wgPageContentModel) {
case 'css':
language = 'css';
break;
case 'javascript':
language = 'javascript';
break;
}
}
// Create new editor
let monaco_editor_container = document.createElement('div');
monaco_editor_container.id = 'monaco-editor'
monaco_editor_container.style["min-height"] = '35em';
monaco_editor_container.style["max-height"] = '100vh';
el_stock_editor.after(monaco_editor_container);
window.monaco_editor = monaco.editor.create(document.getElementById('monaco-editor'), {
value: el_stock_editor.value,
scrollBeyondLastLine: false,
wordWrap: 'on',
fontSize: '13px',
language: language,
// theme: "vs-dark",
});
// On preview
let el_btn_preview = document.querySelector('#wpPreview');
el_btn_preview.addEventListener('click', event => {
el_stock_editor.value = window.monaco_editor.getValue();
});
// On save
let el_btn_save = document.querySelector('#wpSave');
el_btn_save.addEventListener('click', event => {
el_stock_editor.value = window.monaco_editor.getValue();
});
});
};
function initializer() {
if (typeof window.require !== 'undefined') {
init();
} else {
setTimeout(initializer, 20);
}
}
initializer();
})();