Index: trunk/extensions/ParserPlayground/modules/images/inspector-active.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/ParserPlayground/modules/images/inspector-active.png |
___________________________________________________________________ |
Added: svn:mime-type |
1 | 1 | + image/png |
Index: trunk/extensions/ParserPlayground/modules/images/inspector.svg |
— | — | @@ -0,0 +1,74 @@ |
| 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="inspector-active.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="-16.595683" |
| 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="fill:none;stroke:#000000;stroke-opacity:1" |
| 62 | + id="rect3826" |
| 63 | + width="15.360157" |
| 64 | + height="5.6261044" |
| 65 | + x="3.3042197" |
| 66 | + y="13.24632" |
| 67 | + rx="0.5" /> |
| 68 | + <path |
| 69 | + style="fill:#000000;stroke:#ffffff;stroke-width:1.35400056999999996px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" |
| 70 | + d="m 7.8190728,28.218242 0,-12.614219 8.9202452,7.883887 -2.955534,1.391511 1.750094,2.611078 -3.040418,1.602107 -1.540246,-2.675053 z" |
| 71 | + id="path3828" |
| 72 | + inkscape:connector-curvature="0" |
| 73 | + sodipodi:nodetypes="cccccccc" /> |
| 74 | + </g> |
| 75 | +</svg> |
Index: trunk/extensions/ParserPlayground/modules/images/inspector.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/ParserPlayground/modules/images/inspector.png |
___________________________________________________________________ |
Added: svn:mime-type |
1 | 76 | + image/png |
Index: trunk/extensions/ParserPlayground/modules/images/inspector-active.svg |
— | — | @@ -0,0 +1,82 @@ |
| 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="-16.595683" |
| 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 | + <rect |
| 69 | + style="fill:none;stroke:#2a7fff;stroke-opacity:1" |
| 70 | + id="rect3826" |
| 71 | + width="15.360157" |
| 72 | + height="5.6261044" |
| 73 | + x="3.3042197" |
| 74 | + y="13.24632" |
| 75 | + rx="0.5" /> |
| 76 | + <path |
| 77 | + style="fill:#2a7fff;stroke:#ffffff;stroke-width:1.35400057px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" |
| 78 | + d="m 7.8190728,28.218242 0,-12.614219 8.9202452,7.883887 -2.955534,1.391511 1.750094,2.611078 -3.040418,1.602107 -1.540246,-2.675053 z" |
| 79 | + id="path3828" |
| 80 | + inkscape:connector-curvature="0" |
| 81 | + sodipodi:nodetypes="cccccccc" /> |
| 82 | + </g> |
| 83 | +</svg> |
Index: trunk/extensions/ParserPlayground/modules/ext.parserPlayground.css |
— | — | @@ -1,7 +1,9 @@ |
2 | | -#mw-parser-popup .parseNode { |
| 2 | +#mw-parser-popup .parseNode, |
| 3 | +#mw-parser-inspector .parseNode { |
3 | 4 | border: solid 1px transparent; |
4 | 5 | } |
5 | | -#mw-parser-popup .parseNodeHighlight { |
| 6 | +#mw-parser-popup .parseNodeHighlight, |
| 7 | +#mw-parser-inspector .parseNodeHighlight { |
6 | 8 | border: solid 1px blue; |
7 | 9 | } |
8 | 10 | |
Index: trunk/extensions/ParserPlayground/modules/ext.parserPlayground.js |
— | — | @@ -40,12 +40,13 @@ |
41 | 41 | $('#mw-parser-popup').remove(); |
42 | 42 | // line-height is needed to compensate for oddity in WikiEditor extension, which zeroes the line-height on a parent container |
43 | 43 | var box = $('#wpTextbox1'); |
44 | | - var target = $('<div id="mw-parser-popup" style="position: relative; z-index: 9999; overflow: auto; background: white"><div class="editor" style="line-height: 1.5em; top: 0px; left: 0px; right: 0px; bottom: 0px; border: 1px solid gray">' + inside + '</div></div>').insertAfter(box); |
| 44 | + var target = $('<div id="mw-parser-popup" style="width: 100%; overflow-y: auto; background: white"><div class="editor" style="line-height: 1.5em; top: 0px; left: 0px; right: 0px; bottom: 0px; border: 1px solid gray">' + inside + '</div></div>').insertAfter(box); |
45 | 45 | $('#wpTextbox1').css('display', 'none'); |
46 | 46 | |
47 | 47 | onResize = function() { |
48 | | - target.width(box.width()) |
49 | | - .height(box.height()); |
| 48 | + //target.width(box.width()) |
| 49 | + // .height(box.height()); |
| 50 | + target.height(box.height()); |
50 | 51 | }; |
51 | 52 | onResize(); |
52 | 53 | return target; |
— | — | @@ -85,15 +86,17 @@ |
86 | 87 | callback(aNode, bNode); |
87 | 88 | }; |
88 | 89 | a.delegate('.parseNode', 'mouseenter', function(event) { |
| 90 | + $('.parseNodeHighlight').removeClass('parseNodeHighlight'); |
89 | 91 | match(this, function(node, other) { |
90 | 92 | $(node).addClass('parseNodeHighlight'); |
91 | 93 | $(other).addClass('parseNodeHighlight'); |
92 | 94 | }); |
| 95 | + event.preventDefault(); |
| 96 | + return false; |
93 | 97 | }).delegate('.parseNode', 'mouseleave', function(event) { |
94 | | - match(this, function(node, other) { |
95 | | - $(node).removeClass('parseNodeHighlight'); |
96 | | - $(other).removeClass('parseNodeHighlight'); |
97 | | - }); |
| 98 | + $('.parseNodeHighlight').removeClass('parseNodeHighlight'); |
| 99 | + event.preventDefault(); |
| 100 | + return false; |
98 | 101 | }).delegate('.parseNode', 'click', function(event) { |
99 | 102 | match(this, function(node, other) { |
100 | 103 | if (other) { |
— | — | @@ -118,61 +121,16 @@ |
119 | 122 | }; |
120 | 123 | |
121 | 124 | var addParserModes = function(modes, parserClass, className, detail) { |
122 | | - detail = detail || ''; |
123 | | - modes[className] = { |
124 | | - label: className, |
125 | | - desc: '<p>Showing the page rendered with ' + className + '.</p>' + detail, |
126 | | - render: function(src, dest) { |
127 | | - var parser = new parserClass(); |
128 | | - parser.parseToTree(src, function(tree, err) { |
129 | | - parser.treeToHtml(tree, function(node, err) { |
130 | | - dest.append(node); |
131 | | - }); |
132 | | - }); |
133 | | - } |
| 125 | + modes[className] = { |
| 126 | + 'label': className, |
| 127 | + 'action': { |
| 128 | + 'type': 'callback', |
| 129 | + 'execute': function( context ) { |
| 130 | + context.parserPlayground.parser = new parserClass(); |
| 131 | + context.parserPlayground.fn.initDisplay(); |
| 132 | + } |
| 133 | + } |
134 | 134 | }; |
135 | | - modes[className + '-tree'] = { |
136 | | - label: className + ' tree', |
137 | | - desc: '<p>Showing the page broken down to parse tree with ' + className + '.</p>' + detail, |
138 | | - render: function(src, dest) { |
139 | | - var parser = new parserClass(); |
140 | | - parser.parseToTree(src, function(tree, err) { |
141 | | - $(dest).nodeTree( tree ); |
142 | | - }); |
143 | | - } |
144 | | - }; |
145 | | - modes[className + '-roundtrip'] = { |
146 | | - label: className + ' round-trip', |
147 | | - desc: '<p>Showing the page as parsed, then returned to source via ' + className + '.</p>' + detail, |
148 | | - render: function(src, dest) { |
149 | | - var parser = new parserClass(); |
150 | | - parser.parseToTree(src, function(tree, err) { |
151 | | - parser.treeToSource(tree, function(src2, err) { |
152 | | - var target = $('<div style="white-space: pre-wrap; font-family: monospace">').appendTo(dest); |
153 | | - target.html(diffString(src, src2)); |
154 | | - }); |
155 | | - }); |
156 | | - } |
157 | | - }; |
158 | | - modes[className + '-inspect'] = { |
159 | | - label: className + ' inspect', |
160 | | - desc: '<p>Shows ' + className + '\'s HTML output and parse tree side-by-side.</p>' + detail, |
161 | | - render: function(src, dest) { |
162 | | - var parser = new parserClass(); |
163 | | - var treeMap = new HashMap(), renderMap = new HashMap(); |
164 | | - parser.parseToTree(src, function(tree, err) { |
165 | | - var target = makeInspectorColumns(dest); |
166 | | - var left = target.find('.left'), right = target.find('.right'); |
167 | | - left.nodeTree( tree, function( node, el ) { |
168 | | - treeMap.put( node, el ); |
169 | | - }); |
170 | | - parser.treeToHtml(tree, function(node, err) { |
171 | | - right.append(node); |
172 | | - setupInspector(left, right, treeMap, renderMap); |
173 | | - }, renderMap); |
174 | | - }); |
175 | | - } |
176 | | - }; |
177 | 135 | }; |
178 | 136 | |
179 | 137 | $(document).ready( function() { |
— | — | @@ -180,60 +138,123 @@ |
181 | 139 | var editor = $('#wpTextbox1'); |
182 | 140 | if (editor.length > 0 && typeof $.fn.wikiEditor === 'function') { |
183 | 141 | //$('#wpTextbox1').bind('wikiEditor-toolbar-buildSection-main', function() { |
184 | | - var modes = { |
185 | | - 'source': { |
186 | | - label: 'Source', |
187 | | - desc: 'Showing the page\'s original wikitext source code, as you are used to editing it.', |
188 | | - render: false |
189 | | - } |
| 142 | + var listItems = { |
| 143 | + 'sourceView': { |
| 144 | + 'label': 'Source', |
| 145 | + 'action': { |
| 146 | + 'type': 'callback', |
| 147 | + 'execute': function( context ) { |
| 148 | + context.parserPlayground.parser = undefined; |
| 149 | + context.parserPlayground.tree = undefined; |
| 150 | + context.parserPlayground.fn.hide(); |
| 151 | + } |
| 152 | + } |
| 153 | + } |
190 | 154 | }; |
191 | | - addParserModes(modes, MediaWikiParser, 'MediaWikiParser'); |
192 | | - addParserModes(modes, FakeParser, 'FakeParser'); |
193 | | - addParserModes(modes, PegParser, 'PegParser', '<p>Peg-based parser plus FakeParser\'s output. <a href="http://pegjs.majda.cz/documentation">pegjs documentation</a>; edit and reselect to reparse with updated parser</p>'); |
| 155 | + addParserModes(listItems, MediaWikiParser, 'MediaWikiParser'); |
| 156 | + addParserModes(listItems, FakeParser, 'FakeParser'); |
| 157 | + addParserModes(listItems, PegParser, 'PegParser', '<p>Peg-based parser plus FakeParser\'s output. <a href="http://pegjs.majda.cz/documentation">pegjs documentation</a>; edit and reselect to reparse with updated parser</p>'); |
194 | 158 | |
195 | 159 | window.setTimeout(function() { |
196 | | - // Great, now let's hook the booklet buttons... (explicit callbacks would be better) |
197 | | - var hook = function(key, callback) { |
198 | | - // using live since they haven't been created yet... |
199 | | - // 'mouseup' as a hack since the upstream click handler cancels other event handlers |
200 | | - $('#wikiEditor-ui-toolbar .sections .section-parser .index div[rel=' + key + ']').live('mouseup', callback); |
201 | | - }; |
202 | | - var pages = {}; |
203 | | - $.each(modes, function(name, mode) { |
204 | | - pages[name] = { |
205 | | - 'layout': 'table', |
206 | | - 'label': mode.label, |
207 | | - 'rows': [ |
208 | | - { |
209 | | - 'desc': { 'html': mode.desc } |
| 160 | + var context = editor.data('wikiEditor-context'); |
| 161 | + context.parserPlayground = { |
| 162 | + parser: new FakeParser(), |
| 163 | + tree: undefined, |
| 164 | + useInspector: true, |
| 165 | + fn: { |
| 166 | + initDisplay: function() { |
| 167 | + if (context.$parserContainer) { |
| 168 | + context.parserPlayground.fn.hide(); |
210 | 169 | } |
211 | | - ] |
212 | | - }; |
213 | | - var render = mode.render; |
214 | | - hook(name, function() { |
215 | | - $('#pegparser-source').hide(); // it'll reshow; others won't need it |
216 | | - if (mode.render) { |
217 | | - var target = makeMagicBox(''); |
| 170 | + var $target = makeMagicBox(''); |
| 171 | + $('#mw-parser-inspector').remove(); |
| 172 | + var $inspector = $('<div id="mw-parser-inspector" style="position: relative; width: 100%; overflow-y: auto; height: 200px"></div>'); |
| 173 | + $inspector.insertAfter($target); |
| 174 | + if (!context.parserPlayground.useInspector) { |
| 175 | + $inspector.hide(); |
| 176 | + } |
| 177 | + |
| 178 | + context.$parserContainer = $target; |
| 179 | + context.$parserInspector = $inspector; |
| 180 | + |
218 | 181 | var src = $('#wpTextbox1').val(); |
219 | | - var dest = target.find('div'); |
220 | | - render(src, dest); |
221 | | - } else { |
222 | | - $('#mw-parser-popup').remove(); |
223 | | - onResize = null; |
224 | | - $('#wpTextbox1').css('display', 'block'); |
225 | | - } |
226 | | - }); |
227 | | - }); |
228 | | - editor.wikiEditor( 'addToToolbar', { |
229 | | - 'sections': { |
230 | | - 'parser': { |
231 | | - 'label': 'Parser', |
232 | | - 'type': 'booklet', |
233 | | - 'pages': pages |
| 182 | + var $dest = $target.find('div'); |
| 183 | + |
| 184 | + var parser = context.parserPlayground.parser; |
| 185 | + var treeMap = context.parserPlayground.treeMap = new HashMap(), |
| 186 | + renderMap = new HashMap(); |
| 187 | + parser.parseToTree(src, function(tree, err) { |
| 188 | + context.parserPlayground.tree = tree; |
| 189 | + if (context.parserPlayground.useInspector) { |
| 190 | + $inspector.nodeTree( tree, function( node, el ) { |
| 191 | + treeMap.put( node, el ); |
| 192 | + }); |
| 193 | + } |
| 194 | + parser.treeToHtml(tree, function(node, err) { |
| 195 | + $dest.append(node); |
| 196 | + setupInspector($target, $inspector, renderMap, treeMap); |
| 197 | + }, renderMap); |
| 198 | + }); |
| 199 | + }, |
| 200 | + hide: function() { |
| 201 | + $('#pegparser-source').hide(); // it'll reshow; others won't need it |
| 202 | + context.$iframe = undefined; |
| 203 | + context.$parserContainer.remove(); |
| 204 | + context.$parserContainer = undefined; |
| 205 | + context.$parserInspector.remove(); |
| 206 | + context.$parserInspector = undefined; |
| 207 | + context.$textarea.show(); |
| 208 | + }, |
| 209 | + toggleInspector: function() { |
| 210 | + if (context.parserPlayground.useInspector) { |
| 211 | + context.parserPlayground.useInspector = false; |
| 212 | + context.$parserInspector.hide(); |
| 213 | + } else if ( context.parserPlayground.parser ) { |
| 214 | + context.parserPlayground.useInspector = true; |
| 215 | + context.$parserInspector.empty().show(); |
| 216 | + context.$parserInspector.nodeTree( context.parserPlayground.tree, function( node, el ) { |
| 217 | + context.parserPlayground.treeMap.put( node, el ); |
| 218 | + }); |
| 219 | + } |
| 220 | + var target = 'img.tool[rel=inspector]'; |
| 221 | + var $img = context.modules.toolbar.$toolbar.find( target ); |
| 222 | + $img.attr('src', context.parserPlayground.fn.inspectorToolbarIcon()); |
| 223 | + }, |
| 224 | + inspectorToolbarIcon: function() { |
| 225 | + // When loaded as a gadget, one may need to override the wiki's own assets path. |
| 226 | + var iconPath = mw.config.get('wgParserPlaygroundAssetsPath', mw.config.get('wgExtensionAssetsPath')) + '/ParserPlayground/modules/images/'; |
| 227 | + return iconPath + (context.parserPlayground.useInspector ? 'inspector-active.png' : 'inspector.png'); |
234 | 228 | } |
235 | 229 | } |
236 | | - } ); |
237 | | - |
| 230 | + } |
| 231 | + editor.wikiEditor( 'addToToolbar', { |
| 232 | + 'sections': { |
| 233 | + 'richedit': { |
| 234 | + 'label': 'Rich editor', |
| 235 | + 'type': 'toolbar', |
| 236 | + 'groups': { |
| 237 | + 'mode': { |
| 238 | + 'tools': { |
| 239 | + 'mode': { |
| 240 | + 'label': 'Mode', |
| 241 | + 'type': 'select', |
| 242 | + 'list': listItems |
| 243 | + }, |
| 244 | + 'inspector': { |
| 245 | + 'label': 'Toggle inspector', |
| 246 | + 'type': 'button', |
| 247 | + 'icon': context.parserPlayground.fn.inspectorToolbarIcon(), |
| 248 | + 'action': { |
| 249 | + 'type': 'callback', |
| 250 | + 'execute': context.parserPlayground.fn.toggleInspector |
| 251 | + } |
| 252 | + } |
| 253 | + } |
| 254 | + } |
| 255 | + } |
| 256 | + } |
| 257 | + } |
| 258 | + } ); |
238 | 259 | }, 500 ); |
239 | 260 | } else { |
240 | 261 | mw.log('No wiki editor'); |