(stream1, stream2, value)
| 87 | } |
| 88 | |
| 89 | function mergeStreams(stream1, stream2, value) { |
| 90 | var processed = 0; |
| 91 | var result = ''; |
| 92 | var nodeStack = []; |
| 93 | |
| 94 | function selectStream() { |
| 95 | if (stream1.length && stream2.length) { |
| 96 | if (stream1[0].offset != stream2[0].offset) |
| 97 | return (stream1[0].offset < stream2[0].offset) ? stream1 : stream2; |
| 98 | else { |
| 99 | /* |
| 100 | To avoid starting the stream just before it should stop the order is |
| 101 | ensured that stream1 always starts first and closes last: |
| 102 | |
| 103 | if (event1 == 'start' && event2 == 'start') |
| 104 | return stream1; |
| 105 | if (event1 == 'start' && event2 == 'stop') |
| 106 | return stream2; |
| 107 | if (event1 == 'stop' && event2 == 'start') |
| 108 | return stream1; |
| 109 | if (event1 == 'stop' && event2 == 'stop') |
| 110 | return stream2; |
| 111 | |
| 112 | ... which is collapsed to: |
| 113 | */ |
| 114 | return stream2[0].event == 'start' ? stream1 : stream2; |
| 115 | } |
| 116 | } else { |
| 117 | return stream1.length ? stream1 : stream2; |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | function open(node) { |
| 122 | var result = '<' + node.nodeName.toLowerCase(); |
| 123 | for (var i = 0; i < node.attributes.length; i++) { |
| 124 | var attribute = node.attributes[i]; |
| 125 | result += ' ' + attribute.nodeName.toLowerCase(); |
| 126 | if (attribute.nodeValue != undefined) { |
| 127 | result += '="' + escape(attribute.nodeValue) + '"'; |
| 128 | } |
| 129 | } |
| 130 | return result + '>'; |
| 131 | } |
| 132 | |
| 133 | while (stream1.length || stream2.length) { |
| 134 | var current = selectStream().splice(0, 1)[0]; |
| 135 | result += escape(value.substr(processed, current.offset - processed)); |
| 136 | processed = current.offset; |
| 137 | if ( current.event == 'start') { |
| 138 | result += open(current.node); |
| 139 | nodeStack.push(current.node); |
| 140 | } else if (current.event == 'stop') { |
| 141 | var i = nodeStack.length; |
| 142 | do { |
| 143 | i--; |
| 144 | var node = nodeStack[i]; |
| 145 | result += ('</' + node.nodeName.toLowerCase() + '>'); |
| 146 | } while (node != current.node); |
no test coverage detected