function mergeStreams(original, highlighted, value) {
		let processed = 0;
		let result = '';
		const nodeStack = [];

		function selectStream() {
			if (!original.length || !highlighted.length) {
			return original.length ? original : highlighted;
			}
			if (original[0].offset !== highlighted[0].offset) {
			return (original[0].offset < highlighted[0].offset) ? original : highlighted;
			}

			/*
			To avoid starting the stream just before it should stop the order is
			ensured that original always starts first and closes last:

			if (event1 == 'start' && event2 == 'start')
			return original;
			if (event1 == 'start' && event2 == 'stop')
			return highlighted;
			if (event1 == 'stop' && event2 == 'start')
			return original;
			if (event1 == 'stop' && event2 == 'stop')
			return highlighted;

			... which is collapsed to:
			*/
			return highlighted[0].event === 'start' ? original : highlighted;
		}

		/**
		 * @param {Node} node
		 */
		function open(node) {
			/** @param {Attr} attr */
			function attributeString(attr) {
			return ' ' + attr.nodeName + '="' + escapeHTML(attr.value) + '"';
			}
			// @ts-ignore
			result += '<' + tag(node) + [].map.call(node.attributes, attributeString).join('') + '>';
		}

		/**
		 * @param {Node} node
		 */
		function close(node) {
			result += '</' + tag(node) + '>';
		}

		/**
		 * @param {Event} event
		 */
		function render(event) {
			(event.event === 'start' ? open : close)(event.node);
		}

		while (original.length || highlighted.length) {
			let stream = selectStream();
			result += escapeHTML(value.substring(processed, stream[0].offset));
			processed = stream[0].offset;
			if (stream === original) {
			/*
			On any opening or closing tag of the original markup we first close
			the entire highlighted node stack, then render the original tag along
			with all the following original tags at the same offset and then
			reopen all the tags on the highlighted stack.
			*/
			nodeStack.reverse().forEach(close);
			do {
				render(stream.splice(0, 1)[0]);
				stream = selectStream();
			} while (stream === original && stream.length && stream[0].offset === processed);
			nodeStack.reverse().forEach(open);
			} else {
			if (stream[0].event === 'start') {
				nodeStack.push(stream[0].node);
			} else {
				nodeStack.pop();
			}
			render(stream.splice(0, 1)[0]);
			}
		}
		return result + escapeHTML(value.substr(processed));
		}
@param {any} original - the original stream
@param {any} highlighted - stream of the highlighted source
@param {string} value - the original source itself