Index: trunk/parsers/wikidom/tests/hype/es.DocumentModel.js |
— | — | @@ -0,0 +1,176 @@ |
| 2 | +/* |
| 3 | + * Sample plain object (WikiDom). |
| 4 | + * |
| 5 | + * There are two kinds of nodes in WikiDom: |
| 6 | + * |
| 7 | + * {Object} ElementNode |
| 8 | + * type: {String} Symbolic node type name |
| 9 | + * [attributes]: {Object} List of symbolic attribute name and literal value pairs |
| 10 | + * [content]: {Object} Content node (not defined if node has children) |
| 11 | + * [children]: {Object[]} Child nodes (not defined if node has content) |
| 12 | + * |
| 13 | + * {Object} ContentNode |
| 14 | + * text: {String} Plain text data of content |
| 15 | + * [annotations]: {Object[]} List of annotation objects that can be used to render text |
| 16 | + * type: {String} Symbolic name of annotation type |
| 17 | + * start: {Integer} Offset within text to begin annotation |
| 18 | + * end: {Integer} Offset within text to end annotation |
| 19 | + * [data]: {Object} Additional information, only used by more complex annotations |
| 20 | + */ |
| 21 | +var obj = { |
| 22 | + 'type': 'document', |
| 23 | + 'children': [ |
| 24 | + { |
| 25 | + 'type': 'paragraph', |
| 26 | + 'content': { |
| 27 | + 'text': 'abc', |
| 28 | + 'annotations': [ |
| 29 | + { |
| 30 | + 'type': 'bold', |
| 31 | + 'start': 1, |
| 32 | + 'end': 2 |
| 33 | + }, |
| 34 | + { |
| 35 | + 'type': 'italic', |
| 36 | + 'start': 2, |
| 37 | + 'end': 3 |
| 38 | + } |
| 39 | + ] |
| 40 | + } |
| 41 | + }, |
| 42 | + { |
| 43 | + 'type': 'table', |
| 44 | + 'children': [ |
| 45 | + { |
| 46 | + 'type': 'row', |
| 47 | + 'children': [ |
| 48 | + { |
| 49 | + 'type': 'cell', |
| 50 | + 'children': [ |
| 51 | + { |
| 52 | + 'type': 'paragraph', |
| 53 | + 'content': { |
| 54 | + 'text': 'a' |
| 55 | + } |
| 56 | + }, |
| 57 | + { |
| 58 | + 'type': 'list', |
| 59 | + 'children': [ |
| 60 | + { |
| 61 | + 'type': 'listItem', |
| 62 | + 'attributes': { |
| 63 | + 'styles': ['bullet'] |
| 64 | + } |
| 65 | + 'content': { |
| 66 | + 'text': 'a' |
| 67 | + } |
| 68 | + }, |
| 69 | + { |
| 70 | + 'type': 'listItem', |
| 71 | + 'attributes': { |
| 72 | + 'styles': ['bullet', 'bullet'] |
| 73 | + } |
| 74 | + 'content': { |
| 75 | + 'text': 'b' |
| 76 | + } |
| 77 | + }, |
| 78 | + { |
| 79 | + 'type': 'listItem', |
| 80 | + 'attributes': { |
| 81 | + 'styles': ['number'] |
| 82 | + } |
| 83 | + 'content': { |
| 84 | + 'text': 'c' |
| 85 | + } |
| 86 | + }, |
| 87 | + ] |
| 88 | + } |
| 89 | + ] |
| 90 | + } |
| 91 | + ] |
| 92 | + } |
| 93 | + ] |
| 94 | + }, |
| 95 | + { |
| 96 | + 'type': 'paragraph', |
| 97 | + 'content': { |
| 98 | + 'text': 'a' |
| 99 | + } |
| 100 | + }, |
| 101 | + ] |
| 102 | +}; |
| 103 | + |
| 104 | +/* |
| 105 | + * Sample content data. |
| 106 | + * |
| 107 | + * There are three types of components in content data: |
| 108 | + * |
| 109 | + * {String} Plain text character |
| 110 | + * |
| 111 | + * {Array} Annotated character |
| 112 | + * {String} Character |
| 113 | + * {Object}... List of annotation object references |
| 114 | + * |
| 115 | + * {Object} Opening or closing structural element |
| 116 | + * type: {String} Symbolic node type name, if closing element first character will be "/" |
| 117 | + * node: {Object} Reference to model tree node |
| 118 | + * [attributes]: {Object} List of symbolic attribute name and literal value pairs |
| 119 | + */ |
| 120 | +var data = [ |
| 121 | + // 0 - Beginning of paragraph |
| 122 | + { 'type': 'paragraph', 'node': {} }, |
| 123 | + // 1 - Plain content |
| 124 | + 'a', |
| 125 | + // 2 - Annotated content |
| 126 | + ['b', { 'type': 'bold' }], |
| 127 | + // 3 - Annotated content |
| 128 | + ['c', { 'type': 'italic' }], |
| 129 | + // 4 - End of paragraph |
| 130 | + { 'type': '/paragraph', 'node': {} } |
| 131 | + // 5 - Beginning of table |
| 132 | + { 'type': 'table', 'node': {} }, |
| 133 | + // 6 - Beginning of row |
| 134 | + { 'type': 'row', 'node': {} }, |
| 135 | + // 7 - Beginning of cell |
| 136 | + { 'type': 'cell', 'node': {} }, |
| 137 | + // 8 - Beginning of paragraph |
| 138 | + { 'type': 'paragraph', 'node': {} }, |
| 139 | + // 9 - Plain content |
| 140 | + 'a', |
| 141 | + // 10 - End of paragraph |
| 142 | + { 'type': '/paragraph', 'node': {} }, |
| 143 | + // 11 - Beginning of list |
| 144 | + { 'type': 'list', 'node': {} }, |
| 145 | + // 12 - Beginning of bullet list item |
| 146 | + { 'type': 'listItem', 'attributes': { 'styles': ['bullet'] }, 'node': {} }, |
| 147 | + // 13 - Plain content |
| 148 | + 'a', |
| 149 | + // 14 - End of item |
| 150 | + { 'type': '/listItem', 'node': {} }, |
| 151 | + // 15 - Beginning of nested bullet list item |
| 152 | + { 'type': 'listItem', 'attributes': { 'styles': ['bullet', 'bullet'] }, 'node': {} }, |
| 153 | + // 16 - Plain content |
| 154 | + 'b', |
| 155 | + // 17 - End of item |
| 156 | + { 'type': '/listItem', 'node': {} }, |
| 157 | + // 18 - Beginning of numbered list item |
| 158 | + { 'type': 'listItem', 'attributes': { 'styles': ['number'] }, 'node': {} }, |
| 159 | + // 19 - Plain content |
| 160 | + 'c', |
| 161 | + // 20 - End of item |
| 162 | + { 'type': '/listItem', 'node': {} }, |
| 163 | + // 21 - End of list |
| 164 | + { 'type': '/list', 'node': {} }, |
| 165 | + // 22 - End of cell |
| 166 | + { 'type': '/cell', 'node': {} } |
| 167 | + // 23 - End of row |
| 168 | + { 'type': '/row', 'node': {} } |
| 169 | + // 24 - End of table |
| 170 | + { 'type': '/table', 'node': {} } |
| 171 | + // 25 - Beginning of paragraph |
| 172 | + { 'type': 'paragraph', 'node': {} }, |
| 173 | + // 26 - Plain content |
| 174 | + 'a' |
| 175 | + // 27 - End of paragraph |
| 176 | + { 'type': '/paragraph', 'node': {} }, |
| 177 | +]; |
Index: trunk/parsers/wikidom/lib/hype/models/es.DocumentModel.js |
— | — | @@ -43,6 +43,18 @@ |
44 | 44 | }; |
45 | 45 | |
46 | 46 | /** |
| 47 | + * Creates a document model from a plain object. |
| 48 | + * |
| 49 | + * @static |
| 50 | + * @method |
| 51 | + * @param {Object} obj Object to create new document model from |
| 52 | + * @returns {es.DocumentModel} Document model created from obj |
| 53 | + */ |
| 54 | +es.DocumentModel.newFromPlainObject = function( obj ) { |
| 55 | + return new es.DocumentModel( es.DocumentModel.flattenPlainObjectNode( obj ) ); |
| 56 | +}; |
| 57 | + |
| 58 | +/** |
47 | 59 | * Flatten a plain node object into a data array, recursively. |
48 | 60 | * |
49 | 61 | * TODO: where do we document this whole structure - aka "WikiDom"? |
— | — | @@ -98,7 +110,7 @@ |
99 | 111 | * |
100 | 112 | * @method |
101 | 113 | * @param {es.DocumentModelNode} node Node to get offset of |
102 | | - * @param {Boolean} deep Whether to scan recursively |
| 114 | + * @param {Boolean} [deep=false] Whether to scan recursively |
103 | 115 | * @param {es.DocumentModelNode} [from=this] Node to look within |
104 | 116 | * @returns {Integer|false} Offset of node or null of node was not found |
105 | 117 | */ |
— | — | @@ -127,7 +139,7 @@ |
128 | 140 | * |
129 | 141 | * @method |
130 | 142 | * @param {es.DocumentModelNode} node Node to get element object for |
131 | | - * @param {Boolean} deep Whether to scan recursively |
| 143 | + * @param {Boolean} [deep=false] Whether to scan recursively |
132 | 144 | * @returns {Object|null} Element object |
133 | 145 | */ |
134 | 146 | es.DocumentModel.prototype.getElement = function( node, deep ) { |
— | — | @@ -143,7 +155,7 @@ |
144 | 156 | * |
145 | 157 | * @method |
146 | 158 | * @param {es.DocumentModelNode} node Node to get content data for |
147 | | - * @param {Boolean} deep Whether to scan recursively |
| 159 | + * @param {Boolean} [deep=false] Whether to scan recursively |
148 | 160 | * @returns {Array|null} List of content and elements inside node or null if node is not found |
149 | 161 | */ |
150 | 162 | es.DocumentModel.prototype.getContent = function( node, deep ) { |
— | — | @@ -161,7 +173,7 @@ |
162 | 174 | * @param {Array} data |
163 | 175 | * @returns {es.Transaction} |
164 | 176 | */ |
165 | | -es.DocumentModel.prototype.prepareInsert = function( offset, data ) { |
| 177 | +es.DocumentModel.prototype.prepareInsertion = function( offset, data ) { |
166 | 178 | // |
167 | 179 | }; |
168 | 180 | |
— | — | @@ -171,7 +183,7 @@ |
172 | 184 | * @param {es.Range} range |
173 | 185 | * @returns {es.Transaction} |
174 | 186 | */ |
175 | | -es.DocumentModel.prototype.prepareRemove = function( range ) { |
| 187 | +es.DocumentModel.prototype.prepareRemoval = function( range ) { |
176 | 188 | // |
177 | 189 | }; |
178 | 190 | |
— | — | @@ -179,7 +191,7 @@ |
180 | 192 | * |
181 | 193 | * @returns {es.Transaction} |
182 | 194 | */ |
183 | | -es.DocumentModel.prototype.prepareAnnotateContent = function( range, method, annotation ) { |
| 195 | +es.DocumentModel.prototype.prepareContentAnnotation = function( range, method, annotation ) { |
184 | 196 | // |
185 | 197 | }; |
186 | 198 | |
— | — | @@ -187,7 +199,7 @@ |
188 | 200 | * |
189 | 201 | * @returns {es.Transaction} |
190 | 202 | */ |
191 | | -es.DocumentModel.prototype.prepareAnnotateElement = function( index, method, annotation ) { |
| 203 | +es.DocumentModel.prototype.prepareElementAttributeChange = function( index, method, annotation ) { |
192 | 204 | // |
193 | 205 | }; |
194 | 206 | |
— | — | @@ -208,189 +220,3 @@ |
209 | 221 | /* Inheritance */ |
210 | 222 | |
211 | 223 | es.extend( es.DocumentModel, es.DocumentModelNode ); |
212 | | - |
213 | | -/* |
214 | | - * SCRATCH CODE |
215 | | - * |
216 | | -es.DocumentModel.prototype.toPlainObject = function() { |
217 | | - |
218 | | -}; |
219 | | - |
220 | | -es.DocumentModel.prototype.insertContent = function( offset, content ) { |
221 | | - this.data = this.data.slice( 0, offset ).concat( content ).concat( this.data.slice( offset ) ); |
222 | | -}; |
223 | | - |
224 | | -es.DocumentModel.prototype.removeContent = function( range ) { |
225 | | - this.data.splice( range.start, range.end - range.start ); |
226 | | -}; |
227 | | - |
228 | | -es.DocumentModel.prototype.annotateContent = function( range, annotations ) { |
229 | | - for ( var i = 0; i < annotations.length; i++ ) { |
230 | | - var annotation = annotations[i]; |
231 | | - if ( annotation.action = 'add' ) { |
232 | | - // this.data[i][?] |
233 | | - } else if ( annotation.action = 'remove' ) { |
234 | | - // this.data[i][?] |
235 | | - } |
236 | | - } |
237 | | -}; |
238 | | - |
239 | | -es.DocumentModel.prototype.insertElement = function( offset, element ) { |
240 | | - this.data.splice( offset, 0, element ); |
241 | | -}; |
242 | | - |
243 | | -es.DocumentModel.prototype.removeElement = function( offset ) { |
244 | | - this.data.splice( offset, 1 ); |
245 | | -}; |
246 | | - |
247 | | -es.DocumentModel.prototype.annotateElement = function( offset, annotations ) { |
248 | | - for ( var i = 0; i < annotations.length; i++ ) { |
249 | | - var annotation = annotations[i]; |
250 | | - if ( annotation.action = 'add' ) { |
251 | | - // this.data[i].annotations[?] |
252 | | - } else if ( annotation.action = 'remove' ) { |
253 | | - // this.data[i].annotations[?] |
254 | | - } |
255 | | - } |
256 | | -}; |
257 | | -*/ |
258 | | - |
259 | | -es.DocumentModel.newFromPlainObject = function( obj ) { |
260 | | - return new es.DocumentModel( es.DocumentModel.flattenPlainObjectNode( obj ) ); |
261 | | -}; |
262 | | - |
263 | | -/* |
264 | | - * Example of content data |
265 | | - * |
266 | | - * Content data is an array made up of 3 kinds of values: |
267 | | - * String: Plain text character |
268 | | - * Array: Annotated character |
269 | | - * Object: Opening or closing structural element |
270 | | - */ |
271 | | -var data = [ |
272 | | - // 0 - Beginning of paragraph |
273 | | - { 'type': 'paragraph', 'node': {} }, |
274 | | - // 1 - Plain content |
275 | | - 'a', |
276 | | - // 2 - Annotated content |
277 | | - ['b', { 'type': 'bold' }], |
278 | | - // 3 - Annotated content |
279 | | - ['c', { 'type': 'italic' }], |
280 | | - // 4 - End of paragraph |
281 | | - { 'type': '/paragraph', 'node': {} } |
282 | | - // 5 - Beginning of table |
283 | | - { 'type': 'table', 'node': {} }, |
284 | | - // 6 - Beginning of row |
285 | | - { 'type': 'row', 'node': {} }, |
286 | | - // 7 - Beginning of cell |
287 | | - { 'type': 'cell', 'node': {} }, |
288 | | - // 8 - Beginning of paragraph |
289 | | - { 'type': 'paragraph', 'node': {} }, |
290 | | - // 9 - Plain content |
291 | | - 'a', |
292 | | - // 10 - End of paragraph |
293 | | - { 'type': '/paragraph', 'node': {} }, |
294 | | - // 11 - Beginning of list |
295 | | - { 'type': 'list', 'node': {} }, |
296 | | - // 12 - Beginning of bullet list item |
297 | | - { 'type': 'item', 'styles': ['bullet'], 'node': {} }, |
298 | | - // 13 - Plain content |
299 | | - 'a', |
300 | | - // 14 - End of item |
301 | | - { 'type': '/item', 'node': {} }, |
302 | | - // 15 - Beginning of nested bullet list item |
303 | | - { 'type': 'item', 'styles': ['bullet', 'bullet'], 'node': {} }, |
304 | | - // 16 - Plain content |
305 | | - 'b', |
306 | | - // 17 - End of item |
307 | | - { 'type': '/item', 'node': {} }, |
308 | | - // 18 - Beginning of numbered list item |
309 | | - { 'type': 'item', 'styles': ['number'], 'node': {} }, |
310 | | - // 19 - Plain content |
311 | | - 'c', |
312 | | - // 20 - End of item |
313 | | - { 'type': '/item', 'node': {} }, |
314 | | - // 21 - End of list |
315 | | - { 'type': '/list', 'node': {} }, |
316 | | - // 22 - End of cell |
317 | | - { 'type': '/cell', 'node': {} } |
318 | | - // 23 - End of row |
319 | | - { 'type': '/row', 'node': {} } |
320 | | - // 24 - End of table |
321 | | - { 'type': '/table', 'node': {} } |
322 | | - // 25 - Beginning of paragraph |
323 | | - { 'type': 'paragraph', 'node': {} }, |
324 | | - // 26 - Plain content |
325 | | - 'a' |
326 | | - // 27 - End of paragraph |
327 | | - { 'type': '/paragraph', 'node': {} }, |
328 | | -]; |
329 | | - |
330 | | -/* |
331 | | - * Example of content tree |
332 | | - * |
333 | | - * Content trees are kept in sync with content data, providing a mapping between a structured user |
334 | | - * interface and a flat content model. They are made up of nodes which have some common properties: |
335 | | - * type: Symbolic name of a block or sub-block component |
336 | | - * length: Number of elements in content data between the element start and end |
337 | | - * items: Information about the content between the element start and end |
338 | | - */ |
339 | | -var tree = [ |
340 | | - { |
341 | | - 'type': 'paragraph', |
342 | | - 'length': 5, |
343 | | - //'content': ['a', ['b', { 'type': 'bold' }], ['c', { 'type': 'italic' }]], |
344 | | - }, |
345 | | - { |
346 | | - 'type': 'table', |
347 | | - 'length': 19, |
348 | | - 'items': [ |
349 | | - { |
350 | | - 'type': 'row', |
351 | | - 'length': 17, |
352 | | - 'items': [ |
353 | | - { |
354 | | - 'type': 'cell', |
355 | | - 'length': 15, |
356 | | - 'items': { |
357 | | - { |
358 | | - 'type': 'paragraph', |
359 | | - 'length': 3 |
360 | | - //'content': ['a'] |
361 | | - }, |
362 | | - { |
363 | | - 'type': 'list', |
364 | | - 'length': 12, |
365 | | - 'items': [ |
366 | | - { |
367 | | - 'type': 'item', |
368 | | - 'styles': ['bullet'], |
369 | | - 'length': 3, |
370 | | - //'content': ['a'] |
371 | | - }, |
372 | | - { |
373 | | - 'type': 'item', |
374 | | - 'styles': ['bullet', 'bullet'], |
375 | | - 'length': 3, |
376 | | - //'content': ['b'] |
377 | | - }, |
378 | | - { |
379 | | - 'type': 'item', |
380 | | - 'styles': ['number'], |
381 | | - 'length': 3, |
382 | | - //'content': ['c'] |
383 | | - } |
384 | | - ] |
385 | | - } |
386 | | - } |
387 | | - } |
388 | | - ] |
389 | | - } |
390 | | - ] |
391 | | - }, |
392 | | - { |
393 | | - 'type': 'paragraph', |
394 | | - 'length': 3, |
395 | | - //'content': ['a'] |
396 | | - } |
397 | | -]; |