Partway through integrating CodeEditor more closely with WikiEditor. Special character insertions now work! Bold, link etc will insert their sample text, which is less useful but hey.

This commit is contained in:
Brion Vibber 2011-06-10 01:11:18 +00:00
parent e3f5ab3f2e
commit 18af202a72
Notes: Brion Vibber 2011-06-10 01:11:18 +00:00
3 changed files with 223 additions and 53 deletions

View file

@ -27,13 +27,21 @@ $wgHooks['EditPage::showEditForm:initial'][] = 'CodeEditorHooks::editPageShowEdi
$tpl = array( $tpl = array(
'localBasePath' => dirname( __FILE__ ) . '/modules', 'localBasePath' => dirname( __FILE__ ) . '/modules',
'remoteExtPath' => 'CodeEditor/modules', 'remoteExtPath' => 'CodeEditor/modules',
'group' => 'ext.codeEditor', 'group' => 'ext.wikiEditor',
); );
$wgResourceModules['ext.codeEditor'] = array( $wgResourceModules['ext.codeEditor'] = array(
'scripts' => 'ext.codeEditor.js', 'scripts' => 'ext.codeEditor.js',
'dependencies' => array( 'dependencies' => array(
'ext.wikiEditor', 'ext.wikiEditor',
'jquery.codeEditor'
),
) + $tpl;
$wgResourceModules['jquery.codeEditor'] = array(
'scripts' => 'jquery.codeEditor.js',
'dependencies' => array(
'jquery.wikiEditor',
'ext.codeEditor.ace', 'ext.codeEditor.ace',
), ),
) + $tpl; ) + $tpl;

View file

@ -35,56 +35,11 @@
* - ctrl+R, ctrl+L, ctrl+T are taken over by the editor, which is SUPER annoying * - ctrl+R, ctrl+L, ctrl+T are taken over by the editor, which is SUPER annoying
* https://github.com/ajaxorg/ace/issues/210 * https://github.com/ajaxorg/ace/issues/210
*/ */
(function(mw, $) { /*
// This should point to a checkout of Ace source. * JavaScript for WikiEditor Table of Contents
var editorBase = mw.config.get('wgExtensionAssetsPath') + '/CodeEditor/modules/ace/'; */
$(function() { $( document ).ready( function() {
var box = $('#wpTextbox1'); // Add code editor module
if (box.length > 0) { $( '#wpTextbox1' ).wikiEditor( 'addModule', 'codeEditor' );
var matches = /\.(js|css)$/.exec(wgTitle); } );
if (matches && (wgNamespaceNumber == 2 /* User: */ || wgNamespaceNumber == 8 /* MediaWiki: */)) {
var ext = matches[1];
var map = {js: 'javascript', css: 'css'};
var lang = map[ext];
// Ace doesn't like replacing a textarea directly.
// We'll stub this out to sit on top of it...
// line-height is needed to compensate for oddity in WikiEditor extension, which zeroes the line-height on a parent container
var container = $('<div style="position: relative"><div class="editor" style="line-height: 1.5em; top: 0px; left: 0px; right: 0px; bottom: 0px; border: 1px solid gray"></div></div>').insertAfter(box);
var editdiv = container.find('.editor');
box.css('display', 'none');
container.width(box.width())
.height(box.height());
editdiv.text(box.val());
var editor = ace.edit(editdiv[0]);
box.closest('form').submit(function(event) {
box.val(editor.getSession().getValue());
});
editor.getSession().setMode(new (require("ace/mode/" + lang).Mode));
// Force the box to resize horizontally to match in future :D
var resize = function() {
container.width(box.width());
};
$(window).resize(resize);
// Use jquery.ui.resizable so user can make the box taller too
container.resizable({
handles: 's',
minHeight: box.height(),
resize: function() {
editor.resize();
}
});
var summary = $('#wpSummary');
if (summary.val() == '') {
summary.val('/* using [[mw:CodeEditor|CodeEditor]] */ ');
}
}
}
});
})(mediaWiki, jQuery);

View file

@ -0,0 +1,207 @@
/* Ace syntax-highlighting code editor extension for wikiEditor */
( function( $ ) {
$.wikiEditor.modules.codeEditor = {
/**
* Core Requirements
*/
'req': [ 'codeEditor' ],
/**
* Configuration
*/
cfg: {
//
},
/**
* API accessible functions
*/
api: {
//
},
/**
* Event handlers
*/
evt: {
//
},
/**
* Internally used functions
*/
fn: {
}
};
$.wikiEditor.extensions.codeEditor = function( context ) {
/*
* Event Handlers
*
* These act as filters returning false if the event should be ignored or returning true if it should be passed
* on to all modules. This is also where we can attach some extra information to the events.
*/
context.evt = $.extend( context.evt, {
/**
* Filters change events, which occur when the user interacts with the contents of the iframe. The goal of this
* function is to both classify the scope of changes as 'division' or 'character' and to prevent further
* processing of events which did not actually change the content of the iframe.
*/
'keydown': function( event ) {
},
'change': function( event ) {
},
'delayedChange': function( event ) {
},
'cut': function( event ) {
},
'paste': function( event ) {
},
'ready': function( event ) {
}
} );
/**
* Internally used functions
*/
context.fn = $.extend( context.fn, {
'saveCursorAndScrollTop': function() {
// Stub out textarea behavior
return;
},
'restoreCursorAndScrollTop': function() {
// Stub out textarea behavior
return;
},
'saveSelection': function() {
},
'restoreSelection': function() {
},
/**
* Sets up the iframe in place of the textarea to allow more advanced operations
*/
'setupCodeEditor': function() {
var box = context.$textarea;
var matches = /\.(js|css)$/.exec(wgTitle);
if (matches && (wgNamespaceNumber == 2 /* User: */ || wgNamespaceNumber == 8 /* MediaWiki: */)) {
var ext = matches[1];
var map = {js: 'javascript', css: 'css'};
var lang = map[ext];
// Ace doesn't like replacing a textarea directly.
// We'll stub this out to sit on top of it...
// line-height is needed to compensate for oddity in WikiEditor extension, which zeroes the line-height on a parent container
var container = $('<div style="position: relative"><div class="editor" style="line-height: 1.5em; top: 0px; left: 0px; right: 0px; bottom: 0px; border: 1px solid gray"></div></div>').insertAfter(box);
var editdiv = container.find('.editor');
box.css('display', 'none');
container.width(box.width())
.height(box.height());
editdiv.text(box.val());
context.codeEditor = ace.edit(editdiv[0]);
// fakeout for bug 29328
context.$iframe = [
{
contentWindow: {
focus: function() {
context.codeEditor.focus();
}
}
}
];
box.closest('form').submit(function(event) {
box.val(context.codeEditor.getSession().getValue());
});
context.codeEditor.getSession().setMode(new (require("ace/mode/" + lang).Mode));
// Force the box to resize horizontally to match in future :D
var resize = function() {
container.width(box.width());
};
$(window).resize(resize);
// Use jquery.ui.resizable so user can make the box taller too
container.resizable({
handles: 's',
minHeight: box.height(),
resize: function() {
context.codeEditor.resize();
}
});
var summary = $('#wpSummary');
if (summary.val() == '') {
summary.val('/* using [[mw:CodeEditor|CodeEditor]] */ ');
}
// Let modules know we're ready to start working with the content
context.fn.trigger( 'ready' );
}
},
/*
* Compatibility with the $.textSelection jQuery plug-in. When the iframe is in use, these functions provide
* equivilant functionality to the otherwise textarea-based functionality.
*/
'getElementAtCursor': function() {
},
/**
* Gets the currently selected text in the content
* DO NOT CALL THIS DIRECTLY, use $.textSelection( 'functionname', options ) instead
*/
'getSelection': function() {
return context.$codeEditor.getSelectionRange();
},
/**
* Inserts text at the begining and end of a text selection, optionally inserting text at the caret when
* selection is empty.
* DO NOT CALL THIS DIRECTLY, use $.textSelection( 'functionname', options ) instead
*/
'encapsulateSelection': function( options ) {
// Hack! Handle actual selection logic.
var text = options.pre + options.peri + options.post;
context.codeEditor.insert( text );
},
/**
* Gets the position (in resolution of bytes not nessecarily characters) in a textarea
* DO NOT CALL THIS DIRECTLY, use $.textSelection( 'functionname', options ) instead
*/
'getCaretPosition': function( options ) {
},
/**
* Sets the selection of the content
* DO NOT CALL THIS DIRECTLY, use $.textSelection( 'functionname', options ) instead
*
* @param start Character offset of selection start
* @param end Character offset of selection end
* @param startContainer Element in iframe to start selection in. If not set, start is a character offset
* @param endContainer Element in iframe to end selection in. If not set, end is a character offset
*/
'setSelection': function( options ) {
},
/**
* Scroll a textarea to the current cursor position. You can set the cursor position with setSelection()
* DO NOT CALL THIS DIRECTLY, use $.textSelection( 'functionname', options ) instead
*/
'scrollToCaretPosition': function( options ) {
//context.fn.scrollToTop( context.fn.getElementAtCursor(), true );
},
/**
* Scroll an element to the top of the iframe
* DO NOT CALL THIS DIRECTLY, use $.textSelection( 'functionname', options ) instead
*
* @param $element jQuery object containing an element in the iframe
* @param force If true, scroll the element even if it's already visible
*/
'scrollToTop': function( $element, force ) {
}
} );
/* Setup the editor */
context.fn.setupCodeEditor();
} } )( jQuery );