Index: trunk/extensions/ParserPlayground/ParserPlayground.php |
— | — | @@ -63,6 +63,7 @@ |
64 | 64 | 'scripts' => array( |
65 | 65 | 'lib.jsdiff.js', |
66 | 66 | 'lib.pegjs.js', |
| 67 | + 'jquery.nodetree.js', |
67 | 68 | 'ext.parserPlayground.hashMap.js', |
68 | 69 | 'ext.parserPlayground.fakeParser.js', |
69 | 70 | 'ext.parserPlayground.classicParser.js', |
— | — | @@ -70,6 +71,7 @@ |
71 | 72 | 'ext.parserPlayground.js', |
72 | 73 | ), |
73 | 74 | 'styles' => array( |
| 75 | + 'jquery.nodetree.css', |
74 | 76 | 'ext.parserPlayground.css', |
75 | 77 | ), |
76 | 78 | 'dependencies' => array( |
Index: trunk/extensions/ParserPlayground/modules/jquery.nodetree.css |
— | — | @@ -0,0 +1,11 @@ |
| 2 | + |
| 3 | +.mw-nodetree .el { |
| 4 | + color: #808; |
| 5 | +} |
| 6 | +.mw-nodetree .attr { |
| 7 | + color: #008; |
| 8 | +} |
| 9 | +.mw-nodetree li { |
| 10 | + white-space: pre-wrap; |
| 11 | + font-family: monospace; |
| 12 | +} |
Property changes on: trunk/extensions/ParserPlayground/modules/jquery.nodetree.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 13 | + native |
Index: trunk/extensions/ParserPlayground/modules/ext.parserPlayground.js |
— | — | @@ -20,112 +20,7 @@ |
21 | 21 | */ |
22 | 22 | (function( $ ) { |
23 | 23 | |
24 | | -function htmlEscape(str) { |
25 | | - return mw.html.escape( str ); |
26 | | -} |
27 | 24 | |
28 | | -/** |
29 | | - * Render an XML tree into this thingy. |
30 | | - * @param {DOMNode} node |
31 | | - * @param {jQuery} dest a list object! |
32 | | - * @param {HashMap} inspectorMap |
33 | | - */ |
34 | | -function renderXmlTree(node, dest, inspectorMap) { |
35 | | - if (node.nodeType == Node.ELEMENT_NODE) { |
36 | | - var base = '<span style="color:#808">' + htmlEscape(node.nodeName) + '</span>', |
37 | | - str = '<' + base, |
38 | | - closer; |
39 | | - $.each(node.attributes, function(i, attr) { |
40 | | - str += ' ' + htmlEscape(attr.nodeName) + '=<span style="color:#008">"' + htmlEscape(htmlEscape(attr.nodeValue)) + '"</span>'; |
41 | | - }); |
42 | | - if (node.childNodes.length == 0) { |
43 | | - str += ' />'; |
44 | | - dest.append('<li>' + str + '</li>'); |
45 | | - } else { |
46 | | - str += '>'; |
47 | | - closer = '</' + base + '>'; |
48 | | - var chunk = $('<li>' + |
49 | | - '<div class="mw-pp-node">' + str + '</div>' + |
50 | | - '<ul></ul>' + |
51 | | - '<div class="mw-pp-node">' + closer + '</div>' + |
52 | | - '</li>'); |
53 | | - var sublist = chunk.find('ul'); |
54 | | - dest.append(chunk); |
55 | | - $.each(node.childNodes, function(i, child) { |
56 | | - renderXmlTree(child, sublist); |
57 | | - }); |
58 | | - } |
59 | | - } else if (node.nodeType == Node.TEXT_NODE) { |
60 | | - dest.append($('<li style="white-space: pre-wrap; font-family: monospace"></li>').text(node.textContent)); |
61 | | - } |
62 | | -} |
63 | | - |
64 | | -/** |
65 | | - * Render a JSON tree into this thingy. |
66 | | - * @param {mixed} node |
67 | | - * @param {jQuery} dest a list object! |
68 | | - * @param {HashMap} inspectorMap |
69 | | - */ |
70 | | -function renderJsonTree(node, dest, inspectorMap) { |
71 | | - var type = (typeof node); |
72 | | - var chunk, item, sublist; |
73 | | - if (type == 'object' && node === null) { |
74 | | - dest.append('null'); |
75 | | - } else if (type == 'object' && node instanceof Array) { |
76 | | - chunk = $('<div>' + |
77 | | - '<span class="mw-pp-node">[</span>' + |
78 | | - '<ul></ul>' + |
79 | | - '<span class="mw-pp-node">]</span>' + |
80 | | - '</div>'); |
81 | | - sublist = chunk.find('ul'); |
82 | | - $.each(node, function(i, val) { |
83 | | - item = $('<li></li>'); |
84 | | - renderJsonTree(val, item, inspectorMap); |
85 | | - sublist.append(item); |
86 | | - }); |
87 | | - dest.append(chunk); |
88 | | - } else if (type == 'object') { |
89 | | - chunk = $('<div class="parseNode">' + |
90 | | - '<span class="mw-pp-node">{</span>' + |
91 | | - '<ul></ul>' + |
92 | | - '<span class="mw-pp-node">}</span>' + |
93 | | - '</div>'); |
94 | | - chunk.data('parseNode', node); // assign the node for the tree inspector |
95 | | - if (inspectorMap) { |
96 | | - // save reverse lookup for the inspector |
97 | | - inspectorMap.put(node, chunk[0]); |
98 | | - } |
99 | | - sublist = chunk.find('ul'); // hack |
100 | | - $.each(node, function(key, val) { |
101 | | - var item = $('<li><span style="color:#808">' + htmlEscape('' + key) + '</span>: </li>'); |
102 | | - renderJsonTree(val, item, inspectorMap); |
103 | | - sublist.append(item); |
104 | | - }); |
105 | | - dest.append(chunk); |
106 | | - } else if (type == 'string') { |
107 | | - dest.append(htmlEscape(JSON.stringify(node))); // easy way to escape :) |
108 | | - } else { |
109 | | - dest.append(htmlEscape('' + node)); |
110 | | - } |
111 | | -} |
112 | | - |
113 | | -/** |
114 | | - * Render a JSON or XML tree into this thingy. |
115 | | - * @param {mixed} node |
116 | | - * @param {jQuery} dest a list object! |
117 | | - * @param {HashMap} inspectorMap |
118 | | - */ |
119 | | -function renderTree(node, dest, inspectorMap) { |
120 | | - var render; |
121 | | - if (node instanceof Node) { |
122 | | - render = renderXmlTree; |
123 | | - } else { |
124 | | - render = renderJsonTree; |
125 | | - } |
126 | | - render(node, dest, inspectorMap); |
127 | | -} |
128 | | - |
129 | | - |
130 | 25 | var onResize = null; |
131 | 26 | $(window).resize(function() { |
132 | 27 | if (onResize) { |
— | — | @@ -242,8 +137,7 @@ |
243 | 138 | render: function(src, dest) { |
244 | 139 | var parser = new parserClass(); |
245 | 140 | parser.parseToTree(src, function(tree, err) { |
246 | | - var target = $('<ul><li></li></ul>').appendTo(dest); |
247 | | - renderTree(tree, target.find('li')); |
| 141 | + $(dest).nodeTree( tree ); |
248 | 142 | }); |
249 | 143 | } |
250 | 144 | }; |
— | — | @@ -269,7 +163,9 @@ |
270 | 164 | parser.parseToTree(src, function(tree, err) { |
271 | 165 | var target = makeInspectorColumns(dest); |
272 | 166 | var left = target.find('.left'), right = target.find('.right'); |
273 | | - renderTree(tree, left, treeMap); |
| 167 | + left.nodeTree( tree, function( node, el ) { |
| 168 | + treeMap.put( node, el ); |
| 169 | + }); |
274 | 170 | parser.treeToHtml(tree, function(node, err) { |
275 | 171 | right.append(node); |
276 | 172 | setupInspector(left, right, treeMap, renderMap); |
Index: trunk/extensions/ParserPlayground/modules/jquery.nodetree.js |
— | — | @@ -0,0 +1,124 @@ |
| 2 | +/** |
| 3 | + * Node-tree display widget for XML and JSON-style data |
| 4 | + * Helper bits for ParserPlayground parser + editor experiments |
| 5 | + * |
| 6 | + * (c) 2011 Brion Vibber <brion @ wikimedia.org> |
| 7 | + */ |
| 8 | + |
| 9 | +(function(mw, $) { |
| 10 | + |
| 11 | + |
| 12 | +function htmlEscape(str) { |
| 13 | + return mw.html.escape( str ); |
| 14 | +} |
| 15 | + |
| 16 | +/** |
| 17 | + * Render an XML tree into this thingy. |
| 18 | + * @param {DOMNode} node |
| 19 | + * @param {jQuery} dest a list object! |
| 20 | + * @param {function} walkCallback (optional) |
| 21 | + */ |
| 22 | +function renderXmlTree(node, dest, walkCallback) { |
| 23 | + if (node.nodeType == Node.ELEMENT_NODE) { |
| 24 | + var base = '<span class="el">' + htmlEscape(node.nodeName) + '</span>', |
| 25 | + str = '<' + base, |
| 26 | + closer; |
| 27 | + $.each(node.attributes, function(i, attr) { |
| 28 | + str += ' ' + htmlEscape(attr.nodeName) + '=<span class="attr">"' + htmlEscape(htmlEscape(attr.nodeValue)) + '"</span>'; |
| 29 | + }); |
| 30 | + if (node.childNodes.length == 0) { |
| 31 | + str += ' />'; |
| 32 | + dest.append('<li>' + str + '</li>'); |
| 33 | + } else { |
| 34 | + str += '>'; |
| 35 | + closer = '</' + base + '>'; |
| 36 | + var chunk = $('<li>' + |
| 37 | + '<div class="mw-pp-node">' + str + '</div>' + |
| 38 | + '<ul></ul>' + |
| 39 | + '<div class="mw-pp-node">' + closer + '</div>' + |
| 40 | + '</li>'); |
| 41 | + var sublist = chunk.find('ul'); |
| 42 | + dest.append(chunk); |
| 43 | + $.each(node.childNodes, function(i, child) { |
| 44 | + renderXmlTree(child, sublist); |
| 45 | + }); |
| 46 | + } |
| 47 | + } else if (node.nodeType == Node.TEXT_NODE) { |
| 48 | + dest.append($('<li></li>').text(node.textContent)); |
| 49 | + } |
| 50 | +} |
| 51 | + |
| 52 | +/** |
| 53 | + * Render a JSON tree into this thingy. |
| 54 | + * @param {mixed} node |
| 55 | + * @param {jQuery} dest a list object! |
| 56 | + * @param {function} walkCallback (optional) |
| 57 | + */ |
| 58 | +function renderJsonTree(node, dest, walkCallback) { |
| 59 | + var type = (typeof node); |
| 60 | + var chunk, item, sublist; |
| 61 | + if (type == 'object' && node === null) { |
| 62 | + dest.append('null'); |
| 63 | + } else if (type == 'object' && node instanceof Array) { |
| 64 | + chunk = $('<div>' + |
| 65 | + '<span class="mw-pp-node">[</span>' + |
| 66 | + '<ul></ul>' + |
| 67 | + '<span class="mw-pp-node">]</span>' + |
| 68 | + '</div>'); |
| 69 | + sublist = chunk.find('ul'); |
| 70 | + $.each(node, function(i, val) { |
| 71 | + item = $('<li></li>'); |
| 72 | + renderJsonTree(val, item, walkCallback); |
| 73 | + sublist.append(item); |
| 74 | + }); |
| 75 | + dest.append(chunk); |
| 76 | + } else if (type == 'object') { |
| 77 | + chunk = $('<div class="parseNode">' + |
| 78 | + '<span class="mw-pp-node">{</span>' + |
| 79 | + '<ul></ul>' + |
| 80 | + '<span class="mw-pp-node">}</span>' + |
| 81 | + '</div>'); |
| 82 | + chunk.data('parseNode', node); // assign the node for the tree inspector |
| 83 | + if (walkCallback) { |
| 84 | + // Let caller associate source & display nodes |
| 85 | + walkCallback( node, chunk[0] ); |
| 86 | + } |
| 87 | + sublist = chunk.find('ul'); // hack |
| 88 | + $.each(node, function(key, val) { |
| 89 | + var item = $('<li><span class="el">' + htmlEscape('' + key) + '</span>: </li>'); |
| 90 | + renderJsonTree(val, item, walkCallback); |
| 91 | + sublist.append(item); |
| 92 | + }); |
| 93 | + dest.append(chunk); |
| 94 | + } else if (type == 'string') { |
| 95 | + dest.append(htmlEscape(JSON.stringify(node))); // easy way to escape :) |
| 96 | + } else { |
| 97 | + dest.append(htmlEscape('' + node)); |
| 98 | + } |
| 99 | +} |
| 100 | + |
| 101 | +/** |
| 102 | + * Render a JSON or XML tree into this thingy. |
| 103 | + * @param {mixed} node |
| 104 | + * @param {jQuery} dest a list object! |
| 105 | + * @param {function} walkCallback (optional) |
| 106 | + */ |
| 107 | +var renderTree = function(node, dest, walkCallback) { |
| 108 | + var render; |
| 109 | + if (node instanceof Node) { |
| 110 | + render = renderXmlTree; |
| 111 | + } else { |
| 112 | + render = renderJsonTree; |
| 113 | + } |
| 114 | + render(node, dest, walkCallback); |
| 115 | +} |
| 116 | + |
| 117 | +$.fn.nodeTree = function( data, walkCallback ) { |
| 118 | + var target = $('<ul class="mw-nodetree"><li></li></ul>').appendTo( this ); |
| 119 | + renderTree( data, target.find('li'), walkCallback ); |
| 120 | + |
| 121 | + // Chain out! |
| 122 | + return this; |
| 123 | +}; |
| 124 | + |
| 125 | +})(mediaWiki, jQuery); |
Property changes on: trunk/extensions/ParserPlayground/modules/jquery.nodetree.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 126 | + native |