diff --git a/src/ui/js/diff2html-ui.js b/src/ui/js/diff2html-ui.js
index fb18f2b..5b4daa4 100644
--- a/src/ui/js/diff2html-ui.js
+++ b/src/ui/js/diff2html-ui.js
@@ -12,6 +12,8 @@
(function() {
+ var highlightJS = require('./highlight.js-internals.js').HighlightJS;
+
var diffJson = null;
var defaultTarget = "body";
var currentSelectionColumnId = -1;
@@ -71,7 +73,7 @@
// collect all the diff files and execute the highlight on their lines
var $files = $target.find(".d2h-file-wrapper");
- $files.map(function(i, file) {
+ $files.map(function(_i, file) {
var oldLinesState;
var newLinesState;
var $file = $(file);
@@ -79,7 +81,7 @@
// collect all the code lines and execute the highlight on them
var $codeLines = $file.find(".d2h-code-line-ctn");
- $codeLines.map(function(i, line) {
+ $codeLines.map(function(_j, line) {
var $line = $(line);
var text = line.textContent;
var lineParent = line.parentNode;
@@ -102,11 +104,11 @@
newLinesState = result.top;
}
- var originalStream = nodeStream(line);
+ var originalStream = highlightJS.nodeStream(line);
if (originalStream.length) {
var resultNode = document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
resultNode.innerHTML = result.value;
- result.value = mergeStreams(originalStream, nodeStream(resultNode), text);
+ result.value = highlightJS.mergeStreams(originalStream, highlightJS.nodeStream(resultNode), text);
}
$line.addClass("hljs");
@@ -198,129 +200,6 @@
return text;
};
- /*
- * Copied from Highlight.js Private API
- * Will be removed when this part of the API is exposed
- */
-
- /* Utility functions */
-
- function escape(value) {
- return value.replace(/&/gm, '&').replace(//gm, '>');
- }
-
- function tag(node) {
- return node.nodeName.toLowerCase();
- }
-
- /* Stream merging */
-
- function nodeStream(node) {
- var result = [];
- (function _nodeStream(node, offset) {
- for (var child = node.firstChild; child; child = child.nextSibling) {
- if (child.nodeType == 3)
- offset += child.nodeValue.length;
- else if (child.nodeType == 1) {
- result.push({
- event: 'start',
- offset: offset,
- node: child
- });
- offset = _nodeStream(child, offset);
- // Prevent void elements from having an end tag that would actually
- // double them in the output. There are more void elements in HTML
- // but we list only those realistically expected in code display.
- if (!tag(child).match(/br|hr|img|input/)) {
- result.push({
- event: 'stop',
- offset: offset,
- node: child
- });
- }
- }
- }
- return offset;
- })(node, 0);
- return result;
- }
-
- function mergeStreams(original, highlighted, value) {
- var processed = 0;
- var result = '';
- var 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;
- }
-
- function open(node) {
- function attrStr(a) {
- return ' ' + a.nodeName + '="' + escape(a.value) + '"';
- }
-
- result += '<' + tag(node) + Array.prototype.map.call(node.attributes, attrStr).join('') + '>';
- }
-
- function close(node) {
- result += '' + tag(node) + '>';
- }
-
- function render(event) {
- (event.event == 'start' ? open : close)(event.node);
- }
-
- while (original.length || highlighted.length) {
- var stream = selectStream();
- result += escape(value.substr(processed, stream[0].offset - processed));
- 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 + escape(value.substr(processed));
- }
-
- /* **** Highlight.js Private API **** */
-
module.exports.Diff2HtmlUI = Diff2HtmlUI;
// Expose diff2html in the browser
diff --git a/src/ui/js/highlight.js-internals.js b/src/ui/js/highlight.js-internals.js
new file mode 100644
index 0000000..8bac6b4
--- /dev/null
+++ b/src/ui/js/highlight.js-internals.js
@@ -0,0 +1,139 @@
+/*
+ *
+ * highlight.js
+ * Author: isagalaev
+ *
+ */
+
+(function() {
+
+ function HighlightJS() {
+ }
+
+ /*
+ * Copied from Highlight.js Private API
+ * Will be removed when this part of the API is exposed
+ */
+
+ /* Utility functions */
+
+ function escape(value) {
+ return value.replace(/&/gm, '&').replace(//gm, '>');
+ }
+
+ function tag(node) {
+ return node.nodeName.toLowerCase();
+ }
+
+ /* Stream merging */
+
+ HighlightJS.prototype.nodeStream = function(node) {
+ var result = [];
+ (function _nodeStream(node, offset) {
+ for (var child = node.firstChild; child; child = child.nextSibling) {
+ if (child.nodeType == 3)
+ offset += child.nodeValue.length;
+ else if (child.nodeType == 1) {
+ result.push({
+ event: 'start',
+ offset: offset,
+ node: child
+ });
+ offset = _nodeStream(child, offset);
+ // Prevent void elements from having an end tag that would actually
+ // double them in the output. There are more void elements in HTML
+ // but we list only those realistically expected in code display.
+ if (!tag(child).match(/br|hr|img|input/)) {
+ result.push({
+ event: 'stop',
+ offset: offset,
+ node: child
+ });
+ }
+ }
+ }
+ return offset;
+ })(node, 0);
+ return result;
+ };
+
+ HighlightJS.prototype.mergeStreams = function(original, highlighted, value) {
+ var processed = 0;
+ var result = '';
+ var 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;
+ }
+
+ function open(node) {
+ function attrStr(a) {
+ return ' ' + a.nodeName + '="' + escape(a.value) + '"';
+ }
+
+ result += '<' + tag(node) + Array.prototype.map.call(node.attributes, attrStr).join('') + '>';
+ }
+
+ function close(node) {
+ result += '' + tag(node) + '>';
+ }
+
+ function render(event) {
+ (event.event == 'start' ? open : close)(event.node);
+ }
+
+ while (original.length || highlighted.length) {
+ var stream = selectStream();
+ result += escape(value.substr(processed, stream[0].offset - processed));
+ 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 + escape(value.substr(processed));
+ };
+
+ /* **** Highlight.js Private API **** */
+
+ module.exports.HighlightJS = new HighlightJS();
+
+})();