mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/CodeEditor
synced 2024-11-27 16:40:07 +00:00
CodeEditor ext: Add an experimental demo (off by default) mode to edit SyntaxHighlight_GeSHi sections inline using Ace editor
Not ready for prime-time. :) Doesn't actually save pages (just updates the live view), and seems to have problems when invoked multiple times. Not all GeSHi languages are supported. Colors of course are different. Set $wgCodeEditorGeshiIntegration = true to enable; adds a 'section edit link' on source bits.
This commit is contained in:
parent
7f9abd7b7b
commit
bf67581924
Notes:
Brion Vibber
2011-08-04 22:33:59 +00:00
|
@ -8,4 +8,12 @@ class CodeEditorHooks {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function onBeforePageDisplay( $out, $skin ) {
|
||||
global $wgCodeEditorGeshiIntegration;
|
||||
if ( $wgCodeEditorGeshiIntegration ) {
|
||||
$out->addModules( 'ext.codeEditor.geshi' );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ $wgAutoloadClasses['CodeEditorHooks'] = $dir . '/CodeEditor.hooks.php';
|
|||
$wgExtensionMessagesFiles['CodeEditor'] = $dir . '/CodeEditor.i18n.php';
|
||||
|
||||
$wgHooks['EditPage::showEditForm:initial'][] = 'CodeEditorHooks::editPageShowEditFormInitial';
|
||||
$wgHooks['BeforePageDisplay'][] = 'CodeEditorHooks::onBeforePageDisplay';
|
||||
|
||||
$tpl = array(
|
||||
'localBasePath' => dirname( __FILE__ ) . '/modules',
|
||||
|
@ -51,9 +52,46 @@ $wgResourceModules['jquery.codeEditor'] = array(
|
|||
|
||||
// Minimal bundling of a couple bits of Ace
|
||||
$wgResourceModules['ext.codeEditor.ace'] = array(
|
||||
'group' => 'ext.codeEditor.ace',
|
||||
'scripts' => array(
|
||||
'ace/ace-uncompressed.js',
|
||||
'ace/mode-javascript.js',
|
||||
'ace/mode-css.js',
|
||||
),
|
||||
) + $tpl;
|
||||
|
||||
// Extra highlighting modes to match some availabel GeSHi highlighting languages
|
||||
$wgResourceModules['ext.codeEditor.ace.modes'] = array(
|
||||
'group' => 'ext.codeEditor.ace',
|
||||
'scripts' => array(
|
||||
'ace/mode-c_cpp.js',
|
||||
'ace/mode-clojure.js',
|
||||
'ace/mode-csharp.js',
|
||||
'ace/mode-coffee.js',
|
||||
'ace/mode-groovy.js',
|
||||
'ace/mode-html.js',
|
||||
'ace/mode-java.js',
|
||||
'ace/mode-ocaml.js',
|
||||
'ace/mode-perl.js',
|
||||
'ace/mode-php.js',
|
||||
'ace/mode-python.js',
|
||||
'ace/mode-ruby.js',
|
||||
'ace/mode-scala.js',
|
||||
),
|
||||
'dependencies' => 'ext.codeEditor.ace',
|
||||
) + $tpl;
|
||||
|
||||
// Helper to add inline [edit] links to <source> sections
|
||||
$wgResourceModules['ext.codeEditor.geshi'] = array(
|
||||
'scripts' => array(
|
||||
'ext.codeEditor.geshi.js'
|
||||
),
|
||||
'messages' => array(
|
||||
'editsection',
|
||||
'editsection-brackets',
|
||||
'savearticle'
|
||||
)
|
||||
) + $tpl;
|
||||
|
||||
// Experimental feature; not ready yet.
|
||||
$wgCodeEditorGeshiIntegration = false;
|
||||
|
|
148
modules/ext.codeEditor.geshi.js
Normal file
148
modules/ext.codeEditor.geshi.js
Normal file
|
@ -0,0 +1,148 @@
|
|||
/**
|
||||
* This is experimental and does not yet actually save anything back.
|
||||
* Has to be manually enabled.
|
||||
* Needs some code de-dup with the full-page JS/CSS page editing.
|
||||
*/
|
||||
|
||||
$(function() {
|
||||
var $sources = $('.mw-geshi');
|
||||
if ($sources.length > 0) {
|
||||
var setupEditor = function($div) {
|
||||
var $link = $('<a>')
|
||||
.text(mediaWiki.msg('editsection'))
|
||||
.attr('href', '#')
|
||||
.attr('title', 'Edit this code section')
|
||||
.click(function(event) {
|
||||
openEditor($div)
|
||||
event.preventDefault();
|
||||
});
|
||||
var $edit = $('<span>')
|
||||
.css('float', 'right')
|
||||
.append('[')
|
||||
.append($link)
|
||||
.append(']'); // @fixme use the editsection-brackets msg
|
||||
$div.prepend($edit);
|
||||
};
|
||||
var openEditor = function($div) {
|
||||
var $main = $div.find('div'),
|
||||
geshiLang = null,
|
||||
matches = /(?:^| )source-([a-z0-9_-]+)/.exec($main.attr('class'));
|
||||
if (matches) {
|
||||
geshiLang = matches[1];
|
||||
}
|
||||
mediaWiki.loader.using('ext.codeEditor.ace.modes', function() {
|
||||
// @fixme de-duplicate
|
||||
var map = {
|
||||
c: 'c_cpp',
|
||||
cpp: 'c_cpp',
|
||||
clojure: 'clojure',
|
||||
csharp: 'csharp',
|
||||
css: 'css',
|
||||
coffeescript: 'coffee',
|
||||
groovy: 'groovy',
|
||||
html4strict: 'html',
|
||||
html5: 'html',
|
||||
java: 'java',
|
||||
java5: 'java',
|
||||
javascript: 'javascript',
|
||||
jquery: 'javascript',
|
||||
ocaml: 'ocaml',
|
||||
perl: 'perl',
|
||||
php: 'php',
|
||||
python: 'python',
|
||||
ruby: 'ruby',
|
||||
scala: 'scala',
|
||||
xml: 'xml'
|
||||
};
|
||||
|
||||
|
||||
// Disable some annoying commands
|
||||
var canon = require('pilot/canon');
|
||||
canon.removeCommand('replace'); // ctrl+R
|
||||
canon.removeCommand('transposeletters'); // ctrl+T
|
||||
canon.removeCommand('gotoline'); // ctrl+L
|
||||
|
||||
var $container = $('<div>')
|
||||
.attr('style', 'top: 32px; left: 0px; right: 0px; bottom: 0px; border: 1px solid gray')
|
||||
.text($main.text()); // quick hack :D
|
||||
|
||||
var $label = $('<label>').text('Source language: ');
|
||||
var $langDropDown = $('<select>');
|
||||
$.each(map, function(geshiLang, aceLang) {
|
||||
var $opt = $('<option>')
|
||||
.text(geshiLang)
|
||||
.val(geshiLang)
|
||||
.appendTo($langDropDown);
|
||||
});
|
||||
$langDropDown
|
||||
.val(geshiLang)
|
||||
.appendTo($label)
|
||||
.change(function(event) {
|
||||
setLanguage($(this).val());
|
||||
});
|
||||
var $save = $('<button>')
|
||||
.text(mediaWiki.msg('savearticle'))
|
||||
.click(function(event) {
|
||||
// horrible hack ;)
|
||||
var src = codeEditor.getSession().getValue();
|
||||
var tag = '<source lang="' + geshiLang + '">' + src + '</source>';
|
||||
|
||||
$.ajax(wgScriptPath + '/api' + wgScriptExtension, {
|
||||
data: {
|
||||
action: 'parse',
|
||||
text: tag,
|
||||
format: 'json'
|
||||
},
|
||||
type: 'POST',
|
||||
success: function(data, xhr) {
|
||||
var $html = $(data.parse.text['*']);
|
||||
$div.replaceWith($html)
|
||||
setupEditor($html);
|
||||
|
||||
|
||||
closeEditor();
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
});
|
||||
var $cancel = $('<button>')
|
||||
.text('Close').click(function(event) {
|
||||
$xcontainer.remove();
|
||||
$div.css('display', 'block');
|
||||
event.preventDefault();
|
||||
});
|
||||
var $controls = $('<div>')
|
||||
.append($label)
|
||||
.append($save)
|
||||
.append($cancel);
|
||||
var $xcontainer = $('<div style="position: relative"></div>')
|
||||
.append($controls)
|
||||
.append($container);
|
||||
$xcontainer.width($main.width())
|
||||
.height($main.height() * 1.1 + 64 + 32);
|
||||
|
||||
$div.css('display', 'none');
|
||||
$xcontainer.insertAfter($div);
|
||||
|
||||
var codeEditor = ace.edit($container[0]);
|
||||
|
||||
var setLanguage = function(lang) {
|
||||
geshiLang = lang;
|
||||
var aceLang = map[geshiLang];
|
||||
codeEditor.getSession().setMode(new (require("ace/mode/" + aceLang).Mode));
|
||||
};
|
||||
setLanguage(geshiLang);
|
||||
|
||||
var closeEditor = function() {
|
||||
$xcontainer.remove();
|
||||
$div.css('display', 'block');
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
$sources.each(function(i, div) {
|
||||
var $div = $(div);
|
||||
setupEditor($div);
|
||||
});
|
||||
}
|
||||
});
|
Loading…
Reference in a new issue