(stream1, stream2, value)
| 228 | } |
| 229 | |
| 230 | function mergeStreams(stream1, stream2, value) { |
| 231 | var processed = 0; |
| 232 | var result = ''; |
| 233 | var nodeStack = []; |
| 234 | |
| 235 | function selectStream() { |
| 236 | if (stream1.length && stream2.length) { |
| 237 | if (stream1[0].offset != stream2[0].offset) |
| 238 | return (stream1[0].offset < stream2[0].offset) ? stream1 : stream2; |
| 239 | else { |
| 240 | /* |
| 241 | To avoid starting the stream just before it should stop the order is |
| 242 | ensured that stream1 always starts first and closes last: |
| 243 | |
| 244 | if (event1 == 'start' && event2 == 'start') |
| 245 | return stream1; |
| 246 | if (event1 == 'start' && event2 == 'stop') |
| 247 | return stream2; |
| 248 | if (event1 == 'stop' && event2 == 'start') |
| 249 | return stream1; |
| 250 | if (event1 == 'stop' && event2 == 'stop') |
| 251 | return stream2; |
| 252 | |
| 253 | ... which is collapsed to: |
| 254 | */ |
| 255 | return stream2[0].event == 'start' ? stream1 : stream2; |
| 256 | } |
| 257 | } else { |
| 258 | return stream1.length ? stream1 : stream2; |
| 259 | } |
| 260 | } |
| 261 | |
| 262 | function open(node) { |
| 263 | var result = '<' + node.nodeName.toLowerCase(); |
| 264 | for (var i = 0; i < node.attributes.length; i++) { |
| 265 | var attribute = node.attributes[i]; |
| 266 | result += ' ' + attribute.nodeName.toLowerCase(); |
| 267 | if (attribute.value !== undefined && attribute.value !== false && attribute.value !== null) { |
| 268 | result += '="' + escape(attribute.value) + '"'; |
| 269 | } |
| 270 | } |
| 271 | return result + '>'; |
| 272 | } |
| 273 | |
| 274 | while (stream1.length || stream2.length) { |
| 275 | var current = selectStream().splice(0, 1)[0]; |
| 276 | result += escape(value.substr(processed, current.offset - processed)); |
| 277 | processed = current.offset; |
| 278 | if ( current.event == 'start') { |
| 279 | result += open(current.node); |
| 280 | nodeStack.push(current.node); |
| 281 | } else if (current.event == 'stop') { |
| 282 | var node, i = nodeStack.length; |
| 283 | do { |
| 284 | i--; |
| 285 | node = nodeStack[i]; |
| 286 | result += ('</' + node.nodeName.toLowerCase() + '>'); |
| 287 | } while (node != current.node); |
no test coverage detected
searching dependent graphs…