User:Nardog/CodeEditorAssist.js: Difference between revisions

Content deleted Content added
reset mode and readOnly
rm GraphSandbox
 
(7 intermediate revisions by the same user not shown)
Line 1:
mw.loader.using([
$(function codeEditorAssist() {
'user.options', 'ext.visualEditor.desktopArticleTarget.init'
let isEdit = ['edit', 'submit'].includes(mw.config.get('wgAction'));
], function codeEditorAssist() {
let handleEditor = editor => {
let isEdit = mw.config.exists('wgCodeEditorCurrentLanguage') &&
if (isEdit) {
['edit', 'submit'].includes(mw.config.get('wgAction'));
$('#wpTextbox1').wikiEditor('addToToolbar', {
let veAvailable = mw.libs.ve.isVisualAvailable;
let isAf = mw.config.exists('aceConfig');
if (!isEdit && !veAvailable && !isAf) return;
let context, curEditor, defSettingsMap = new WeakMap();
let getSettings = (editor, isDef) => {
let settings = {};
let defSettings = !isDef && defSettingsMap.get(editor);
Object.entries(editor.getOptions()).forEach(([k, v]) => {
if (v === undefined) {
v = null;
}
if (isDef || v !== defSettings[k] ||
k === 'showInvisibles' || k === 'wrap'
) {
settings[k] = v;
}
});
delete settings.mode;
delete settings.readOnly;
delete settings.maxLines;
delete settings.minLines;
delete settings.firstLineNumber;
if (isDef) {
settings.showInvisibles = false;
settings.wrap = 'off';
}
return settings;
};
let updateToolbar = () => {
if (!context) return;
let names = [];
if (curEditor.getShowInvisibles() !== context.showInvisibleChars) {
names.push('invisibleChars');
}
if (curEditor.session.getUseWrapMode() !== context.lineWrappingActive) {
names.push('lineWrapping');
}
names.forEach(name => {
context.modules.toolbar.$toolbar.find(`.tool[rel="${name}"]`)
.data('action').execute(context);
});
};
let saveRemoveHandler = function (e) {
this.disabled = true;
let change = 'userjs-codeeditorassist-settings';
let value;
if (!e.data) {
value = JSON.stringify(getSettings(curEditor));
change += '=' + value;
}
mw.loader.using('mediawiki.api').then(() => (
new mw.Api().postWithEditToken({
action: 'globalpreferences',
change: change
})
)).always(response => {
this.disabled = false;
if (!response || response.globalpreferences !== 'success') {
mw.notify(
e.data
? `Couldn't remove settings from your global preferences`
: `Couldn't save settings to your global preferences`,
{ type: 'error' }
);
return;
}
if (e.data) {
delete mw.user.options.values['userjs-codeeditorassist-settings'];
mw.notify('Removed settings from your global preferences');
} else {
mw.user.options.set('userjs-codeeditorassist-settings', value);
mw.notify('Saved settings to your global preferences');
}
});
};
let observing;
let addButtons = () => {
if (observing) return;
observing = true;
let $buttons = $('<div>').addClass('floatright').append(
$('<button>').text('Save').on('click', saveRemoveHandler),
' ',
$('<button>').text('Remove').on('click', true, saveRemoveHandler),
' ',
$('<button>').text('Reset').on('click', () => {
curEditor.setOptions(defSettingsMap.get(curEditor));
$('#ace_settingsmenu').parent()[0].click();
curEditor.execCommand('showSettingsMenu');
})
);
new MutationObserver(() => {
$buttons.appendTo('#ace_settingsmenu > table > tr:last-child > td');
updateToolbar();
}).observe(document.body, { childList: true });
};
let onFocus = (e, editor) => {
curEditor = editor;
};
let initialize = editor => {
if (!window.ace) return;
if (!(editor instanceof ace.Editor)) {
if (context) {
editor = context.codeEditor;
} else {
let el = document.querySelector('.ace_editor');
if (!el) return;
editor = ace.edit(el);
}
}
if (defSettingsMap.has(editor)) return;
curEditor = editor;
defSettingsMap.set(editor, getSettings(editor, true));
let savedSettings = mw.user.options.get('userjs-codeeditorassist-settings');
if (savedSettings) {
savedSettings = JSON.parse(savedSettings);
editor.setOptions(savedSettings);
updateToolbar();
}
editor.on('focus', onFocus);
addButtons();
};
if (isAf) {
$.when($.ready, mw.loader.using('ext.abuseFilter.ace')).then(initialize);
return;
}
if (veAvailable) {
mw.hook('ve.loadModules').add(addPlugin => {
addPlugin(() => {
let setupEditor = ve.ui.MWAceEditorWidget.prototype.setupEditor;
ve.ui.MWAceEditorWidget.prototype.setupEditor = function () {
setupEditor.apply(this, arguments);
initialize(this.editor);
};
});
});
}
if (!isEdit) return;
mw.loader.load('oojs-ui.styles.icons-interactions');
mw.hook('codeEditor.configure').add(initialize);
let promise = new Promise(resolve => {
mw.hook('codeEditor.configure').add(resolve);
});
mw.hook('wikiEditor.toolbarReady').add($textarea => {
context = $textarea.data('wikiEditorContext');
promise.then(() => {
$textarea.wikiEditor('addToToolbar', {
section: 'main',
group: 'codeeditor-style',
tools: {
'codeeditor-settings': {
label: 'Open code editor settings',
type: 'button',
Line 14 ⟶ 160:
type: 'callback',
execute: () => {
editorcurEditor.execCommand('showSettingsMenu');
}
}
Line 20 ⟶ 166:
}
});
}
let defSettings;
let getSettings = () => {
let settings = editor.getOptions();
if (defSettings) {
delete settings.mode;
delete settings.readOnly;
}
Object.keys(settings).forEach(k => {
if (settings[k] === undefined) settings[k] = null;
if (defSettings && k !== 'showInvisibles' && k !== 'wrap' && settings[k] === defSettings[k])
delete settings[k];
});
return settings;
};
defSettings = getSettings();
defSettings.showInvisibles = false;
defSettings.wrap = 'off';
let invisiblesBtn = isEdit && document.querySelector('.group-codeeditor-style > [rel="invisibleChars"]');
let wrapBtn = isEdit && document.querySelector('.group-codeeditor-style > [rel="lineWrapping"]');
let turnButton = (button, turnsOn) => {
if (button && button.classList.contains('oo-ui-toggleWidget-' + (turnsOn ? 'off' : 'on')))
button.firstElementChild.click();
};
let savedSettings = mw.user.options.get('userjs-codeeditorassist-settings');
if (savedSettings) {
savedSettings = JSON.parse(savedSettings);
turnButton(invisiblesBtn, savedSettings.showInvisibles);
turnButton(wrapBtn, savedSettings.wrap && savedSettings.wrap !== 'off');
editor.setOptions(savedSettings);
}
let api;
let saveRemoveSettings = (button, isRemoval) => {
button.disabled = true;
mw.loader.using('mediawiki.api', () => {
if (!api) api = new mw.Api();
api.postWithEditToken({
action: 'globalpreferences',
// Removing the option somehow doesn't work, so empty it for now (T207448)
change: 'userjs-codeeditorassist-settings=' + (isRemoval ? '' : JSON.stringify(getSettings()))
}).always(response => {
if (response && response.globalpreferences === 'success') {
mw.notify(isRemoval
? 'Removed settings from your global preferences'
: 'Saved settings to your global preferences'
);
} else {
mw.notify(isRemoval
? 'Couldn\'t remove settings from your global preferences'
: 'Couldn\'t save settings to your global preferences',
{ type: 'error' });
}
button.disabled = false;
});
});
};
let $buttons = $('<div class="floatright"></div>')
.append('<input type="submit" value="Save"> <input type="submit" value="Remove"> <input type="submit" value="Reset">');
$buttons.on('click', 'input', e => {
if (e.target.value === 'Reset') {
turnButton(invisiblesBtn);
turnButton(wrapBtn);
editor.setOptions(defSettings);
$('#ace_settingsmenu').parent().detach();
editor.execCommand('showSettingsMenu');
} else {
saveRemoveSettings(e.target, e.target.value === 'Remove');
}
});
});
(new MutationObserver(() => {
$buttons.appendTo('#ace_settingsmenu > table > tr:last-child > td');
})).observe(document.body, { childList: true });
};
let filterEditor = !isEdit && document.querySelector('#wpAceFilterEditor');
if (isEdit && mw.config.get('wgCodeEditorCurrentLanguage') || filterEditor) {
let editor;
let waitForEditor = () => {
if (!editor) editor = filterEditor || document.querySelector('.ace_editor');
if (editor && window.ace) {
let dependencies = ['mediawiki.user'];
if (isEdit) dependencies.push('ext.wikiEditor', 'oojs-ui.styles.icons-interactions');
mw.loader.using(dependencies, () => {
handleEditor(ace.edit(editor));
});
return true;
}
};
if (!waitForEditor()) {
let observer = new MutationObserver(() => {
waitForEditor() && observer.disconnect();
});
observer.observe(document.head, { childList: true });
}
}
});