1 // If we run from a Safari instance, we don't
2 // have a Controller object. Instead, we fake it by
4 if (typeof Controller == 'undefined') {
6 Controller.log_ = console.log;
9 var highlightDiff = function(diff, element, callbacks) {
10 if (!diff || diff == "")
15 var start = new Date().getTime();
16 element.className = "diff"
17 var content = diff.escapeHTML().replace(/\t/g, " ");;
26 var finalContent = "";
27 var lines = content.split('\n');
29 var mode_change = false;
33 var hunk_start_line_1 = -1;
34 var hunk_start_line_2 = -1;
38 var finishContent = function()
46 if (callbacks["newfile"])
47 callbacks["newfile"](startname, endname, "file_index_" + (file_index - 1), mode_change, old_mode, new_mode);
49 var title = startname;
50 var binaryname = endname;
51 if (endname == "/dev/null") {
52 binaryname = startname;
55 else if (startname == "/dev/null")
57 else if (startname != endname)
58 title = startname + " renamed to " + endname;
60 if (binary && endname == "/dev/null") { // in cases of a deleted binary file, there is no diff/file to display
67 return; // so printing the filename in the file-list is enough
70 if (diffContent != "" || binary) {
71 finalContent += '<div class="file" id="file_index_' + (file_index - 1) + '">' +
72 '<div class="fileHeader">' + title + '</div>';
75 if (!binary && (diffContent != "")) {
76 finalContent += '<div class="diffContent">' +
77 '<div class="lineno">' + line1 + "</div>" +
78 '<div class="lineno">' + line2 + "</div>" +
79 '<div class="lines">' + diffContent + "</div>" +
84 if (callbacks["binaryFile"])
85 finalContent += callbacks["binaryFile"](binaryname);
87 finalContent += "<div>Binary file differs</div>";
91 if (diffContent != "" || binary)
92 finalContent += '</div>';
101 for (var lineno = 0; lineno < lines.length; lineno++) {
102 var l = lines[lineno];
104 var firstChar = l.charAt(0);
106 if (firstChar == "d" && l.charAt(1) == "i") { // "diff", i.e. new file, we have to reset everything
107 header = true; // diff always starts with a header
109 finishContent(); // Finish last file
114 if(match = l.match(/^diff --git (a\/)+(.*) (b\/)+(.*)$/)) { // there are cases when we need to capture filenames from
115 startname = match[2]; // the diff line, like with mode-changes.
116 endname = match[4]; // this can get overwritten later if there is a diff or if
117 } // the file is binary
123 if (firstChar == "n") {
124 if (l.match(/^new file mode .*$/))
125 startname = "/dev/null";
127 if (match = l.match(/^new mode (.*)$/)) {
133 if (firstChar == "o") {
134 if (match = l.match(/^old mode (.*)$/)) {
141 if (firstChar == "d") {
142 if (l.match(/^deleted file mode .*$/))
143 endname = "/dev/null";
146 if (firstChar == "-") {
147 if (match = l.match(/^--- (a\/)?(.*)$/))
148 startname = match[2];
151 if (firstChar == "+") {
152 if (match = l.match(/^\+\+\+ (b\/)?(.*)$/))
156 // If it is a complete rename, we don't know the name yet
157 // We can figure this out from the 'rename from.. rename to.. thing
158 if (firstChar == 'r')
160 if (match = l.match(/^rename (from|to) (.*)$/))
162 if (match[1] == "from")
163 startname = match[2];
169 if (firstChar == "B") // "Binary files .. and .. differ"
172 // We might not have a diff from the binary file if it's new.
173 // So, we use a regex to figure that out
175 if (match = l.match(/^Binary files (a\/)?(.*) and (b\/)?(.*) differ$/))
177 startname = match[2];
183 if (firstChar == "@")
189 if (firstChar == "+") {
190 // Highlight trailing whitespace
191 if (m = l.match(/\s+$/))
192 l = l.replace(/\s+$/, "<span class='whitespace'>" + m + "</span>");
195 line2 += ++hunk_start_line_2 + "\n";
196 diffContent += "<div class='addline'>" + l + "</div>";
197 } else if (firstChar == "-") {
198 line1 += ++hunk_start_line_1 + "\n";
200 diffContent += "<div class='delline'>" + l + "</div>";
201 } else if (firstChar == "@") {
206 if (m = l.match(/@@ \-([0-9]+),?\d* \+(\d+),?\d* @@/))
208 hunk_start_line_1 = parseInt(m[1]) - 1;
209 hunk_start_line_2 = parseInt(m[2]) - 1;
213 diffContent += "<div class='hunkheader'>" + l + "</div>";
214 } else if (firstChar == " ") {
215 line1 += ++hunk_start_line_1 + "\n";
216 line2 += ++hunk_start_line_2 + "\n";
217 diffContent += "<div class='noopline'>" + l + "</div>";
223 // This takes about 7ms
224 element.innerHTML = finalContent;
226 // TODO: Replace this with a performance pref call
228 Controller.log_("Total time:" + (new Date().getTime() - start));