Index: trunk/extensions/CodeEditor/CodeEditor.i18n.php |
— | — | @@ -12,7 +12,8 @@ |
13 | 13 | * @author Brion Vibber |
14 | 14 | */ |
15 | 15 | $messages['en'] = array( |
16 | | - 'codeeditor-desc' => 'Syntax-highlighted editing for JavaScript and CSS pages using [http://ace.ajax.org/ Ace editor]' |
| 16 | + 'codeeditor-desc' => 'Syntax-highlighted editing for JavaScript and CSS pages using [http://ace.ajax.org/ Ace editor]', |
| 17 | + 'codeeditor-toolbar-toggle' => 'Toggle syntax highlighting', |
17 | 18 | ); |
18 | 19 | |
19 | 20 | /** Afrikaans (Afrikaans) |
Index: trunk/extensions/CodeEditor/images/comment.svg |
— | — | @@ -0,0 +1,80 @@ |
| 2 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
| 3 | +<!-- Created with Inkscape (http://www.inkscape.org/) --> |
| 4 | + |
| 5 | +<svg |
| 6 | + xmlns:dc="http://purl.org/dc/elements/1.1/" |
| 7 | + xmlns:cc="http://creativecommons.org/ns#" |
| 8 | + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
| 9 | + xmlns:svg="http://www.w3.org/2000/svg" |
| 10 | + xmlns="http://www.w3.org/2000/svg" |
| 11 | + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
| 12 | + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
| 13 | + width="22" |
| 14 | + height="22" |
| 15 | + id="svg2985" |
| 16 | + version="1.1" |
| 17 | + inkscape:version="0.48.1 r9760" |
| 18 | + sodipodi:docname="comment.svg" |
| 19 | + inkscape:export-filename="/var/www/trunk/extensions/CodeEditor/images/code-selected.png" |
| 20 | + inkscape:export-xdpi="90" |
| 21 | + inkscape:export-ydpi="90"> |
| 22 | + <defs |
| 23 | + id="defs2987" /> |
| 24 | + <sodipodi:namedview |
| 25 | + id="base" |
| 26 | + pagecolor="#ffffff" |
| 27 | + bordercolor="#666666" |
| 28 | + borderopacity="1.0" |
| 29 | + inkscape:pageopacity="0.0" |
| 30 | + inkscape:pageshadow="2" |
| 31 | + inkscape:zoom="11.197802" |
| 32 | + inkscape:cx="-0.29784131" |
| 33 | + inkscape:cy="19.57213" |
| 34 | + inkscape:current-layer="layer1" |
| 35 | + showgrid="true" |
| 36 | + inkscape:grid-bbox="true" |
| 37 | + inkscape:document-units="px" |
| 38 | + inkscape:window-width="1920" |
| 39 | + inkscape:window-height="1056" |
| 40 | + inkscape:window-x="1920" |
| 41 | + inkscape:window-y="24" |
| 42 | + inkscape:window-maximized="1" /> |
| 43 | + <metadata |
| 44 | + id="metadata2990"> |
| 45 | + <rdf:RDF> |
| 46 | + <cc:Work |
| 47 | + rdf:about=""> |
| 48 | + <dc:format>image/svg+xml</dc:format> |
| 49 | + <dc:type |
| 50 | + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
| 51 | + <dc:title></dc:title> |
| 52 | + </cc:Work> |
| 53 | + </rdf:RDF> |
| 54 | + </metadata> |
| 55 | + <g |
| 56 | + id="layer1" |
| 57 | + inkscape:label="Layer 1" |
| 58 | + inkscape:groupmode="layer" |
| 59 | + transform="translate(0,-10)"> |
| 60 | + <rect |
| 61 | + style="opacity:0.50000000000000000;fill:#ffffff;fill-opacity:1;stroke:#808080;stroke-opacity:1" |
| 62 | + id="rect3188" |
| 63 | + width="21" |
| 64 | + height="21" |
| 65 | + x="0.53581941" |
| 66 | + y="10.567223" |
| 67 | + rx="3" /> |
| 68 | + <text |
| 69 | + xml:space="preserve" |
| 70 | + style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#2a7fff;fill-opacity:1;stroke:none;font-family:Monospace;-inkscape-font-specification:Monospace" |
| 71 | + x="3.393523" |
| 72 | + y="26.73111" |
| 73 | + id="text2993" |
| 74 | + sodipodi:linespacing="125%"><tspan |
| 75 | + sodipodi:role="line" |
| 76 | + x="3.393523" |
| 77 | + y="26.73111" |
| 78 | + id="tspan2997" |
| 79 | + style="font-size:18px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Sans;-inkscape-font-specification:Sans Bold">/*</tspan></text> |
| 80 | + </g> |
| 81 | +</svg> |
Index: trunk/extensions/CodeEditor/images/code-selected.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/CodeEditor/images/code-selected.png |
___________________________________________________________________ |
Added: svn:mime-type |
1 | 82 | + image/png |
Index: trunk/extensions/CodeEditor/images/comment-off.svg |
— | — | @@ -0,0 +1,72 @@ |
| 2 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
| 3 | +<!-- Created with Inkscape (http://www.inkscape.org/) --> |
| 4 | + |
| 5 | +<svg |
| 6 | + xmlns:dc="http://purl.org/dc/elements/1.1/" |
| 7 | + xmlns:cc="http://creativecommons.org/ns#" |
| 8 | + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
| 9 | + xmlns:svg="http://www.w3.org/2000/svg" |
| 10 | + xmlns="http://www.w3.org/2000/svg" |
| 11 | + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
| 12 | + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
| 13 | + width="22" |
| 14 | + height="22" |
| 15 | + id="svg2985" |
| 16 | + version="1.1" |
| 17 | + inkscape:version="0.48.1 r9760" |
| 18 | + sodipodi:docname="comment.svg" |
| 19 | + inkscape:export-filename="/var/www/trunk/extensions/CodeEditor/images/code-selected.png" |
| 20 | + inkscape:export-xdpi="90" |
| 21 | + inkscape:export-ydpi="90"> |
| 22 | + <defs |
| 23 | + id="defs2987" /> |
| 24 | + <sodipodi:namedview |
| 25 | + id="base" |
| 26 | + pagecolor="#ffffff" |
| 27 | + bordercolor="#666666" |
| 28 | + borderopacity="1.0" |
| 29 | + inkscape:pageopacity="0.0" |
| 30 | + inkscape:pageshadow="2" |
| 31 | + inkscape:zoom="11.197802" |
| 32 | + inkscape:cx="-0.29784131" |
| 33 | + inkscape:cy="19.57213" |
| 34 | + inkscape:current-layer="layer1" |
| 35 | + showgrid="true" |
| 36 | + inkscape:grid-bbox="true" |
| 37 | + inkscape:document-units="px" |
| 38 | + inkscape:window-width="1920" |
| 39 | + inkscape:window-height="1056" |
| 40 | + inkscape:window-x="1920" |
| 41 | + inkscape:window-y="24" |
| 42 | + inkscape:window-maximized="1" /> |
| 43 | + <metadata |
| 44 | + id="metadata2990"> |
| 45 | + <rdf:RDF> |
| 46 | + <cc:Work |
| 47 | + rdf:about=""> |
| 48 | + <dc:format>image/svg+xml</dc:format> |
| 49 | + <dc:type |
| 50 | + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
| 51 | + <dc:title></dc:title> |
| 52 | + </cc:Work> |
| 53 | + </rdf:RDF> |
| 54 | + </metadata> |
| 55 | + <g |
| 56 | + id="layer1" |
| 57 | + inkscape:label="Layer 1" |
| 58 | + inkscape:groupmode="layer" |
| 59 | + transform="translate(0,-10)"> |
| 60 | + <text |
| 61 | + xml:space="preserve" |
| 62 | + style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Monospace;-inkscape-font-specification:Monospace" |
| 63 | + x="3.393523" |
| 64 | + y="26.73111" |
| 65 | + id="text2993" |
| 66 | + sodipodi:linespacing="125%"><tspan |
| 67 | + sodipodi:role="line" |
| 68 | + x="3.393523" |
| 69 | + y="26.73111" |
| 70 | + id="tspan2997" |
| 71 | + style="font-size:18px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Sans;-inkscape-font-specification:Sans Bold;fill:#000000">/*</tspan></text> |
| 72 | + </g> |
| 73 | +</svg> |
Index: trunk/extensions/CodeEditor/images/code.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/CodeEditor/images/code.png |
___________________________________________________________________ |
Added: svn:mime-type |
1 | 74 | + image/png |
Index: trunk/extensions/CodeEditor/CodeEditor.php |
— | — | @@ -44,6 +44,9 @@ |
45 | 45 | 'jquery.wikiEditor', |
46 | 46 | 'ext.codeEditor.ace', |
47 | 47 | ), |
| 48 | + 'messages' => array( |
| 49 | + 'codeeditor-toolbar-toggle' |
| 50 | + ) |
48 | 51 | ) + $tpl; |
49 | 52 | |
50 | 53 | // Minimal bundling of a couple bits of Ace |
Index: trunk/extensions/CodeEditor/modules/jquery.codeEditor.js |
— | — | @@ -62,24 +62,66 @@ |
63 | 63 | } |
64 | 64 | } ); |
65 | 65 | |
| 66 | +var cookieEnabled = $.cookie('wikiEditor-' + context.instance + '-codeEditor-enabled'); |
| 67 | +context.codeEditorActive = (cookieEnabled != '0'); |
| 68 | + |
66 | 69 | /** |
67 | 70 | * Internally used functions |
68 | 71 | */ |
69 | 72 | context.fn = $.extend( context.fn, { |
70 | | - 'saveCursorAndScrollTop': function() { |
71 | | - // Stub out textarea behavior |
72 | | - return; |
| 73 | + 'codeEditorToolbarIcon': function() { |
| 74 | + var iconPath = wgExtensionAssetsPath + '/CodeEditor/images/'; |
| 75 | + return iconPath + (context.codeEditorActive ? 'code-selected.png' : 'code.png'); |
73 | 76 | }, |
74 | | - 'restoreCursorAndScrollTop': function() { |
75 | | - // Stub out textarea behavior |
76 | | - return; |
| 77 | + 'setupCodeEditorToolbar': function() { |
| 78 | + // Drop out some formatting that isn't relevant on these pages... |
| 79 | + context.api.removeFromToolbar(context, { |
| 80 | + 'section': 'main', |
| 81 | + 'group': 'format', |
| 82 | + 'tool': 'bold' |
| 83 | + }); |
| 84 | + context.api.removeFromToolbar(context, { |
| 85 | + 'section': 'main', |
| 86 | + 'group': 'format', |
| 87 | + 'tool': 'italic' |
| 88 | + }); |
| 89 | + var callback = function( context ) { |
| 90 | + context.codeEditorActive = !context.codeEditorActive; |
| 91 | + $.cookie( |
| 92 | + 'wikiEditor-' + context.instance + '-codeEditor-enabled', |
| 93 | + context.codeEditorActive ? 1 : 0, |
| 94 | + { expires: 30, path: '/' } |
| 95 | + ); |
| 96 | + context.fn.toggleCodeEditorToolbar(); |
| 97 | + |
| 98 | + if (context.codeEditorActive) { |
| 99 | + // set it back up! |
| 100 | + context.fn.setupCodeEditor(); |
| 101 | + } else { |
| 102 | + context.fn.disableCodeEditor(); |
| 103 | + } |
| 104 | + } |
| 105 | + context.api.addToToolbar( context, { |
| 106 | + 'section': 'main', |
| 107 | + 'group': 'format', |
| 108 | + 'tools': { |
| 109 | + 'codeEditor': { |
| 110 | + 'labelMsg': 'codeeditor-toolbar-toggle', |
| 111 | + 'type': 'button', |
| 112 | + 'icon': context.fn.codeEditorToolbarIcon(), |
| 113 | + 'action': { |
| 114 | + 'type': 'callback', |
| 115 | + 'execute': callback |
| 116 | + } |
| 117 | + } |
| 118 | + } |
| 119 | + } ); |
77 | 120 | }, |
78 | | - 'saveSelection': function() { |
79 | | - mw.log('codeEditor stub function saveSelection called'); |
| 121 | + 'toggleCodeEditorToolbar': function() { |
| 122 | + var target = 'img.tool[rel=codeEditor]'; |
| 123 | + var $img = context.modules.toolbar.$toolbar.find( target ); |
| 124 | + $img.attr('src', context.fn.codeEditorToolbarIcon()); |
80 | 125 | }, |
81 | | - 'restoreSelection': function() { |
82 | | - mw.log('codeEditor stub function restoreSelection called'); |
83 | | - }, |
84 | 126 | /** |
85 | 127 | * Sets up the iframe in place of the textarea to allow more advanced operations |
86 | 128 | */ |
— | — | @@ -104,7 +146,7 @@ |
105 | 147 | // Ace doesn't like replacing a textarea directly. |
106 | 148 | // We'll stub this out to sit on top of it... |
107 | 149 | // line-height is needed to compensate for oddity in WikiEditor extension, which zeroes the line-height on a parent container |
108 | | - 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); |
| 150 | + var container = context.$codeEditorContainer = $('<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); |
109 | 151 | var editdiv = container.find('.editor'); |
110 | 152 | |
111 | 153 | box.css('display', 'none'); |
— | — | @@ -152,6 +194,85 @@ |
153 | 195 | } |
154 | 196 | }, |
155 | 197 | |
| 198 | + /* |
| 199 | + * Turn off the code editor view and return to the plain textarea. |
| 200 | + * May be needed by some folks with funky browsers, or just to compare. |
| 201 | + */ |
| 202 | + 'disableCodeEditor': function() { |
| 203 | + // Kills it! |
| 204 | + |
| 205 | + // Save contents |
| 206 | + context.$textarea.val(context.fn.getContents()); |
| 207 | + |
| 208 | + // @todo fetch cursor, scroll position |
| 209 | + |
| 210 | + // Drop the fancy editor widget... |
| 211 | + context.$codeEditorContainer.remove(); |
| 212 | + context.$codeEditorContainer = undefined; |
| 213 | + context.$iframe = undefined; |
| 214 | + context.codeEditor = undefined; |
| 215 | + |
| 216 | + // Restore textarea |
| 217 | + context.$textarea.show(); |
| 218 | + |
| 219 | + // @todo restore cursor, scroll position |
| 220 | + } |
| 221 | +}); |
| 222 | + |
| 223 | +/** |
| 224 | + * Override the base functions in a way that lets |
| 225 | + * us fall back to the originals when we turn off. |
| 226 | + */ |
| 227 | +var saveAndExtend = function( base, extended ) { |
| 228 | + var saved = {}; |
| 229 | + $.map( extended, function( func, name ) { |
| 230 | + if ( name in base ) { |
| 231 | + var orig = base[name]; |
| 232 | + base[name] = function() { |
| 233 | + if (context.codeEditorActive) { |
| 234 | + return func.apply(this, arguments); |
| 235 | + } else { |
| 236 | + return orig.apply(this, arguments); |
| 237 | + } |
| 238 | + } |
| 239 | + } else { |
| 240 | + base[name] = func; |
| 241 | + } |
| 242 | + }); |
| 243 | +}; |
| 244 | + |
| 245 | +saveAndExtend( context.fn, { |
| 246 | + 'saveCursorAndScrollTop': function() { |
| 247 | + if ( context.codeEditor ) { |
| 248 | + // Stub out textarea behavior |
| 249 | + return; |
| 250 | + } else { |
| 251 | + context.codeEditorStubs.saveCursorAndScrollTop.apply(this); |
| 252 | + } |
| 253 | + }, |
| 254 | + 'restoreCursorAndScrollTop': function() { |
| 255 | + if ( context.codeEditor ) { |
| 256 | + // Stub out textarea behavior |
| 257 | + return; |
| 258 | + } else { |
| 259 | + context.codeEditorStubs.saveCursorAndScrollTop.apply(this); |
| 260 | + } |
| 261 | + }, |
| 262 | + 'saveSelection': function() { |
| 263 | + if ( context.codeEditor ) { |
| 264 | + mw.log('codeEditor stub function saveSelection called'); |
| 265 | + } else { |
| 266 | + context.codeEditorStubs.saveCursorAndScrollTop.apply(this); |
| 267 | + } |
| 268 | + }, |
| 269 | + 'restoreSelection': function() { |
| 270 | + if ( context.codeEditor ) { |
| 271 | + mw.log('codeEditor stub function restoreSelection called'); |
| 272 | + } else { |
| 273 | + context.codeEditorStubs.saveCursorAndScrollTop.apply(this); |
| 274 | + } |
| 275 | + }, |
| 276 | + |
156 | 277 | /* Needed for search/replace */ |
157 | 278 | 'getContents': function() { |
158 | 279 | return context.codeEditor.getSession().getValue(); |
— | — | @@ -266,6 +387,9 @@ |
267 | 388 | } ); |
268 | 389 | |
269 | 390 | /* Setup the editor */ |
270 | | -context.fn.setupCodeEditor(); |
| 391 | +context.fn.setupCodeEditorToolbar(); |
| 392 | +if (context.codeEditorActive) { |
| 393 | + context.fn.setupCodeEditor(); |
| 394 | +} |
271 | 395 | |
272 | 396 | } } )( jQuery ); |
Index: trunk/extensions/CodeEditor/modules/ext.codeEditor.js |
— | — | @@ -19,12 +19,10 @@ |
20 | 20 | * https://github.com/ajaxorg/ace/issues/37 |
21 | 21 | * |
22 | 22 | * Known issues: |
23 | | - * - with both classic & enhanced toolbar, toolbar buttons have no effect. |
24 | | - * - do we need an interface for regular actions to work on custom editors, or should it replace the toolbar too? |
25 | | - * - something keeps trying to load a background worker thread from wrong URL, but seems to fail gracefully. |
| 23 | + * - extension version doesn't have optional bits correct |
| 24 | + * - ties into WikiEditor, so doesn't work on classic toolbar |
| 25 | + * - background worker for JS syntax check doesn't load in non-debug mode (probably also fails if extension assets are offsite) |
26 | 26 | * - copy/paste not available from context menu (Firefox, Chrome on Linux -- kbd & main menu commands ok) |
27 | | - * - libs are loaded from toolserver over HTTP; should at least check for HTTPS (toolserver.org's cert is for *.toolserver.org, so fails on https://toolserver.org) |
28 | | - * - unlike the textarea in many browsers, the widget isn't automatically resizable; jquery.ui.resizable on the container should fix that |
29 | 27 | * - accessibility: tab/shift-tab are overridden. is there a consistent alternative for keyboard-reliant users? |
30 | 28 | * - accessibility: accesskey on the original textarea needs to be moved over or otherwise handled |
31 | 29 | * - 'discard your changes?' check on tab close doesn't trigger |