Index: trunk/parsers/wikidom/lib/es/es.Surface.css |
— | — | @@ -68,3 +68,16 @@ |
69 | 69 | height: 1.5em; |
70 | 70 | display: none; |
71 | 71 | } |
| 72 | + |
| 73 | +.italic { |
| 74 | + font-style: italic; |
| 75 | +} |
| 76 | + |
| 77 | +.bold { |
| 78 | + font-weight: bold; |
| 79 | +} |
| 80 | + |
| 81 | +.xlink { |
| 82 | + color: blue; |
| 83 | + text-decoration: underline; |
| 84 | +} |
Index: trunk/parsers/wikidom/lib/es/es.Content.js |
— | — | @@ -82,67 +82,110 @@ |
83 | 83 | return this.data.length;
|
84 | 84 | };
|
85 | 85 |
|
86 | | -Content.prototype.render = function( start, end ) {
|
87 | | - if ( start || end ) {
|
88 | | - return this.slice( start, end ).render();
|
| 86 | +Content.annotationRenderers = {
|
| 87 | + 'bold': {
|
| 88 | + 'open': '<span class="bold">',
|
| 89 | + 'close': '</span>',
|
| 90 | + },
|
| 91 | + 'italic': {
|
| 92 | + 'open': '<span class="italic">',
|
| 93 | + 'close': '</span>',
|
| 94 | + },
|
| 95 | + 'xlink': {
|
| 96 | + 'open': function( data ) {
|
| 97 | + return '<span class="xlink" data-href="' + data.href + '">';
|
| 98 | + },
|
| 99 | + 'close': '</span>'
|
89 | 100 | }
|
| 101 | +};
|
90 | 102 |
|
91 | | - // TODO: Find a better place for this function
|
92 | | - function diff( a, b ) {
|
93 | | - var result = [];
|
94 | | - for ( var i = 1; i < b.length; i++ ) {
|
95 | | - if ( a.indexOf( b[i] ) === -1 ) {
|
96 | | - result.push( b[i] );
|
| 103 | +Content.renderAnnotation = function( bias, annotation, stack ) {
|
| 104 | + var renderers = Content.annotationRenderers,
|
| 105 | + type = annotation.type,
|
| 106 | + out = '';
|
| 107 | + if ( type in renderers ) {
|
| 108 | + if ( bias === 'open' ) {
|
| 109 | + // Add annotation to the top of the stack
|
| 110 | + stack.push( annotation );
|
| 111 | + // Open annotation
|
| 112 | + out += typeof renderers[type]['open'] === 'function'
|
| 113 | + ? renderers[type]['open']( annotation.data )
|
| 114 | + : renderers[type]['open'];
|
| 115 | + } else {
|
| 116 | + if ( stack[stack.length - 1] === annotation ) {
|
| 117 | + // Remove annotation from top of the stack
|
| 118 | + stack.pop();
|
| 119 | + // Close annotation
|
| 120 | + out += typeof renderers[type]['close'] === 'function'
|
| 121 | + ? renderers[type]['close']( annotation.data )
|
| 122 | + : renderers[type]['close'];
|
| 123 | + } else {
|
| 124 | + // Find the annotation in the stack
|
| 125 | + var depth = stack.indexOf( annotation );
|
| 126 | + if ( depth === -1 ) {
|
| 127 | + throw 'Invalid stack error. An element is missing from the stack.';
|
| 128 | + }
|
| 129 | + // Close each already opened annotation
|
| 130 | + for ( var i = stack.length - 1; i >= depth + 1; i-- ) {
|
| 131 | + out += typeof renderers[stack[i].type]['close'] === 'function'
|
| 132 | + ? renderers[stack[i].type]['close']( stack[i].data )
|
| 133 | + : renderers[stack[i].type]['close'];
|
| 134 | + }
|
| 135 | + // Close the buried annotation
|
| 136 | + out += typeof renderers[type]['close'] === 'function'
|
| 137 | + ? renderers[type]['close']( annotation.data )
|
| 138 | + : renderers[type]['close'];
|
| 139 | + // Re-open each previously opened annotation
|
| 140 | + for ( var i = depth + 1; i < stack.length; i++ ) {
|
| 141 | + out += typeof renderers[stack[i].type]['open'] === 'function'
|
| 142 | + ? renderers[stack[i].type]['open']( stack[i].data )
|
| 143 | + : renderers[stack[i].type]['open'];
|
| 144 | + }
|
| 145 | + // Remove the annotation from the middle of the stack
|
| 146 | + stack.splice( depth, 1 );
|
97 | 147 | }
|
98 | 148 | }
|
99 | | - return result;
|
100 | 149 | }
|
101 | | -
|
102 | | - function openAnnotations( annotations ) {
|
103 | | - var out = '';
|
104 | | - for ( var i = 0; i < annotations.length; i++ ) {
|
105 | | - switch (annotations[i].type) {
|
106 | | - case 'bold':
|
107 | | - out += '<b>';
|
108 | | - break;
|
109 | | - case 'italic':
|
110 | | - out += '<i>';
|
111 | | - break;
|
112 | | - }
|
113 | | - }
|
114 | | - return out;
|
115 | | - }
|
| 150 | + return out;
|
| 151 | +};
|
116 | 152 |
|
117 | | - function closeAnnotations ( annotations ) {
|
118 | | - var out = '';
|
119 | | - for ( var i = 0; i < annotations.length; i++ ) {
|
120 | | - switch (annotations[i].type) {
|
121 | | - case 'bold':
|
122 | | - out += '</b>';
|
123 | | - break;
|
124 | | - case 'italic':
|
125 | | - out += '</i>';
|
126 | | - break;
|
127 | | - }
|
128 | | - }
|
129 | | - return out;
|
| 153 | +Content.prototype.render = function( start, end ) {
|
| 154 | + if ( start || end ) {
|
| 155 | + return this.slice( start, end ).render();
|
130 | 156 | }
|
131 | | -
|
132 | | - var left = [],
|
| 157 | + var out = '',
|
| 158 | + left = '',
|
133 | 159 | right,
|
134 | | - out = '';
|
135 | | -
|
| 160 | + leftPlain,
|
| 161 | + rightPlain,
|
| 162 | + stack = [];
|
136 | 163 | for ( var i = 0; i < this.data.length; i++ ) {
|
137 | | - right = this.data[i] || [];
|
138 | | -
|
139 | | - if ( typeof right == 'string' ) {
|
140 | | - right = [right];
|
| 164 | + right = this.data[i];
|
| 165 | + leftPlain = typeof left === 'string';
|
| 166 | + rightPlain = typeof right === 'string';
|
| 167 | + if ( !leftPlain && rightPlain ) {
|
| 168 | + // [formatted][plain] pair, close any annotations for left
|
| 169 | + for ( var j = 1; j < left.length; j++ ) {
|
| 170 | + out += Content.renderAnnotation( 'close', left[j], stack );
|
| 171 | + }
|
| 172 | + } else if ( leftPlain && !rightPlain ) {
|
| 173 | + // [plain][formatted] pair, open any annotations for right
|
| 174 | + for ( var j = 1; j < right.length; j++ ) {
|
| 175 | + out += Content.renderAnnotation( 'open', right[j], stack );
|
| 176 | + }
|
| 177 | + } else if ( !leftPlain && !rightPlain ) {
|
| 178 | + // [formatted][formatted] pair, open/close any differences
|
| 179 | + for ( var j = 1; j < left.length; j++ ) {
|
| 180 | + if ( right.indexOf( left[j] ) === -1 ) {
|
| 181 | + out += Content.renderAnnotation( 'close', left[j], stack );
|
| 182 | + }
|
| 183 | + }
|
| 184 | + for ( var j = 1; j < right.length; j++ ) {
|
| 185 | + if ( left.indexOf( right[j] ) === -1 ) {
|
| 186 | + out += Content.renderAnnotation( 'open', right[j], stack );
|
| 187 | + }
|
| 188 | + }
|
141 | 189 | }
|
142 | | -
|
143 | | - var diffout = diff( left, right );
|
144 | | - //debugger;
|
145 | | - out += openAnnotations( diffout );
|
146 | | -
|
147 | 190 | out += right[0]
|
148 | 191 | // Tags
|
149 | 192 | .replace( /&/g, '&' )
|
— | — | @@ -156,7 +199,6 @@ |
157 | 200 | .replace( /\n/g, '<span class="editSurface-whitespace">\\n</span>' )
|
158 | 201 | .replace( /\t/g, '<span class="editSurface-whitespace">\\t</span>' );
|
159 | 202 |
|
160 | | - out += closeAnnotations( diff( right, left ) );
|
161 | 203 | left = right;
|
162 | 204 | }
|
163 | 205 |
|
Index: trunk/parsers/wikidom/demos/es/index.html |
— | — | @@ -31,6 +31,12 @@ |
32 | 32 | { 'type': 'bold', 'range': { 'start': 0, 'end': 15 } }, |
33 | 33 | // "line wrap" should be italic |
34 | 34 | { 'type': 'italic', 'range': { 'start': 17, 'end': 26 } }, |
| 35 | + // "wrap is" should be a link to "#" |
| 36 | + { |
| 37 | + 'type': 'xlink', |
| 38 | + 'range': { 'start': 22, 'end': 29 }, |
| 39 | + 'data': { 'href': './' } |
| 40 | + }, |
35 | 41 | ] |
36 | 42 | }, |
37 | 43 | { 'text': "Word wrap is the additional feature of most text editors, word processors, and web browsers, of breaking lines between and not within words, except when a single word is longer than a line.\n" }, |