fix static highlight bugs

#1681 #1682
This commit is contained in:
nightwing 2013-11-13 22:03:11 +04:00
commit 9e5dda2334
4 changed files with 69 additions and 67 deletions

View file

@ -19,9 +19,10 @@
<p>Syntax highlighting using Ace language modes and themes.</p> <p>Syntax highlighting using Ace language modes and themes.</p>
<div class="code" ace-mode="ace/mode/css" ace-theme="ace/theme/chrome"> <div class="code" ace-mode="ace/mode/css" ace-theme="ace/theme/chrome" ace-gutter="true">
.code { .code {
width: 50%; width: 50%;
position: relative; position: relative;
white-space: pre-wrap; white-space: pre-wrap;
} }
@ -41,28 +42,20 @@ function wobble (flam) {
<script src="../../build/src-noconflict/ext-static_highlight.js"></script> <script src="../../build/src-noconflict/ext-static_highlight.js"></script>
<script> <script>
var highlighter = ace.require("ace/ext/static_highlight") var highlight = ace.require("ace/ext/static_highlight")
var dom = ace.require("ace/lib/dom") var dom = ace.require("ace/lib/dom")
function qsa(sel) { function qsa(sel) {
return [].slice.call(document.querySelectorAll(sel)); return [].slice.call(document.querySelectorAll(sel));
} }
qsa(".code").forEach(function (codeEl) { qsa(".code").forEach(function (codeEl) {
var cs = getComputedStyle(codeEl); highlight(codeEl, {
codeEl.style.cssText = codeEl.style.cssText + mode: codeEl.getAttribute('ace-mode'),
'width: ' + cs.width + ';' + theme: codeEl.getAttribute('ace-theme'),
'height: ' + cs.height + ';'; startLineNumber: 1,
var mode = codeEl.getAttribute('ace-mode'); showGutter: codeEl.getAttribute("ace-gutter"),
var theme = codeEl.getAttribute('ace-theme'); trim: true
var data = codeEl.textContent.trim(); }, function (highlighted) {
highlighter.render(data, mode, theme, 1, false, function (highlighted) {
dom.importCssString(highlighted.css, "ace_highlight");
dom.importCssString('.ace_editor { overflow: auto; ' +
'position:absolute; top:0; bottom:0; right:0; left:0; }' +
'.ace_gutter { position: relative; }',
'atropa_hial');
codeEl.innerHTML = highlighted.html;
}); });
}); });
</script> </script>

View file

@ -231,10 +231,6 @@
border-left-width: 1px; border-left-width: 1px;
} }
.ace_line {
white-space: nowrap;
}
.ace_marker-layer .ace_step, .ace_marker-layer .ace_stack { .ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {
position: absolute; position: absolute;
z-index: 3; z-index: 3;

View file

@ -36,6 +36,49 @@ var TextLayer = require("../layer/text").Text;
var baseStyles = require("../requirejs/text!./static.css"); var baseStyles = require("../requirejs/text!./static.css");
var config = require("../config"); var config = require("../config");
var dom = require("../lib/dom"); var dom = require("../lib/dom");
var highlight = function(el, opts, callback) {
var m = el.className.match(/lang-(\w+)/);
var mode = opts.mode || m && ("ace/mode/" + m[1]);
if (!mode)
return false;
var theme = opts.theme || "ace/theme/textmate";
var data = "";
var nodes = [];
if (el.firstElementChild) {
var textLen = 0;
for (var i = 0; i < el.childNodes.length; i++) {
var ch = el.childNodes[i];
if (ch.nodeType == 3) {
textLen += ch.data.length;
data += ch.data;
} else {
nodes.push(textLen, ch);
}
}
} else {
data = dom.getInnerText(el);
if (opts.trim)
data = data.trim();
}
highlight.render(data, mode, theme, opts.firstLineNumber, !opts.showGutter, function (highlighted) {
dom.importCssString(highlighted.css, "ace_highlight");
el.innerHTML = highlighted.html;
var container = el.firstChild.firstChild;
for (var i = 0; i < nodes.length; i += 2) {
var pos = highlighted.session.doc.indexToPosition(nodes[i]);
var node = nodes[i + 1];
var lineEl = container.children[pos.row];
lineEl && lineEl.appendChild(node);
}
callback && callback();
});
};
/** /**
* Transforms a given input code snippet into HTML using the given mode * Transforms a given input code snippet into HTML using the given mode
* *
@ -56,7 +99,7 @@ var dom = require("../lib/dom");
* @returns {object} An object containing the properties `html` and `css`. * @returns {object} An object containing the properties `html` and `css`.
*/ */
exports.render = function(input, mode, theme, lineStart, disableGutter, callback) { highlight.render = function(input, mode, theme, lineStart, disableGutter, callback) {
var waiting = 0; var waiting = 0;
var modeCache = EditSession.prototype.$modes; var modeCache = EditSession.prototype.$modes;
@ -81,7 +124,7 @@ exports.render = function(input, mode, theme, lineStart, disableGutter, callback
// loads or passes the specified mode module then calls renderer // loads or passes the specified mode module then calls renderer
function done() { function done() {
var result = exports.renderSync(input, mode, theme, lineStart, disableGutter); var result = highlight.renderSync(input, mode, theme, lineStart, disableGutter);
return callback ? callback(result) : result; return callback ? callback(result) : result;
} }
return waiting || done(); return waiting || done();
@ -95,7 +138,7 @@ exports.render = function(input, mode, theme, lineStart, disableGutter, callback
* @returns {object} An object containing: html, css * @returns {object} An object containing: html, css
*/ */
exports.renderSync = function(input, mode, theme, lineStart, disableGutter) { highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) {
lineStart = parseInt(lineStart || 1, 10); lineStart = parseInt(lineStart || 1, 10);
var session = new EditSession(""); var session = new EditSession("");
@ -119,7 +162,7 @@ exports.renderSync = function(input, mode, theme, lineStart, disableGutter) {
if (!disableGutter) if (!disableGutter)
stringBuilder.push("<span class='ace_gutter ace_gutter-cell' unselectable='on'>" + (ix + lineStart) + "</span>"); stringBuilder.push("<span class='ace_gutter ace_gutter-cell' unselectable='on'>" + (ix + lineStart) + "</span>");
textLayer.$renderLine(stringBuilder, ix, true, false); textLayer.$renderLine(stringBuilder, ix, true, false);
stringBuilder.push("</div>"); stringBuilder.push("\n</div>");
} }
// let's prepare the whole html // let's prepare the whole html
@ -133,48 +176,11 @@ exports.renderSync = function(input, mode, theme, lineStart, disableGutter) {
return { return {
css: baseStyles + theme.cssText, css: baseStyles + theme.cssText,
html: html html: html,
session: session
}; };
}; };
module.exports = highlight;
module.exports.highlight =highlight;
exports.highlight = function(el, opts, callback) {
var m = el.className.match(/lang-(\w+)/);
var mode = opts.mode || m && ("ace/mode/" + m[1]);
if (!mode)
return false;
var theme = opts.theme || "ace/theme/textmate";
var data = "";
var nodes = [];
if (el.firstElementChild) {
var textLen = 0;
for (var i = 0; i < el.childNodes.length; i++) {
var ch = el.childNodes[i];
if (ch.nodeType == 3) {
textLen += ch.data.length;
data += ch.data;
} else {
nodes.push(textLen, ch);
}
}
} else {
data = dom.getInnerText(el);
}
exports.render(data, mode, theme, 1, true, function (highlighted) {
dom.importCssString(highlighted.css, "ace_highlight");
el.innerHTML = highlighted.html;
var container = el.firstChild.firstChild
for (var i = 0; i < nodes.length; i += 2) {
var pos = highlighted.session.doc.indexToPosition(nodes[i])
var node = nodes[i + 1];
var lineEl = container.children[pos.row];
lineEl && lineEl.appendChild(nodes[i+1]);
}
callback && callback();
});
};
}); });

View file

@ -28,7 +28,14 @@ module.exports = {
var mode = new JavaScriptMode(); var mode = new JavaScriptMode();
var result = highlighter.render(snippet, mode, theme); var result = highlighter.render(snippet, mode, theme);
assert.equal(result.html, "<div class='ace-tomorrow'><div class='ace_static_highlight'><div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'>1</span><span class='ace_comment ace_doc'>/**\xa0this\xa0is\xa0a\xa0function</span></div><div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'>2</span><span class='ace_comment ace_doc'>*</span></div><div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'>3</span><span class='ace_comment ace_doc'>*/</span></div><div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'>4</span><span class='ace_storage ace_type'>function</span>\xa0<span class='ace_entity ace_name ace_function'>hello</span>\xa0<span class='ace_paren ace_lparen'>(</span><span class='ace_variable ace_parameter'>a</span><span class='ace_punctuation ace_operator'>,\xa0</span><span class='ace_variable ace_parameter'>b</span><span class='ace_punctuation ace_operator'>,\xa0</span><span class='ace_variable ace_parameter'>c</span><span class='ace_paren ace_rparen'>)</span>\xa0<span class='ace_paren ace_lparen'>{</span></div><div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'>5</span>\xa0\xa0\xa0\xa0<span class='ace_storage ace_type'>console</span><span class='ace_punctuation ace_operator'>.</span><span class='ace_support ace_function ace_firebug'>log</span><span class='ace_paren ace_lparen'>(</span><span class='ace_identifier'>a</span>\xa0<span class='ace_keyword ace_operator'>*</span>\xa0<span class='ace_identifier'>b</span>\xa0<span class='ace_keyword ace_operator'>+</span>\xa0<span class='ace_identifier'>c</span>\xa0<span class='ace_keyword ace_operator'>+</span>\xa0<span class='ace_string'>'sup$'</span><span class='ace_paren ace_rparen'>)</span><span class='ace_punctuation ace_operator'>;</span></div><div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'>6</span><span class='ace_paren ace_rparen'>}</span></div></div></div>"); assert.equal(result.html, "<div class='ace-tomorrow'><div class='ace_static_highlight'>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'>1</span><span class='ace_comment ace_doc'>/**\xa0this\xa0is\xa0a\xa0function</span>\n</div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'>2</span><span class='ace_comment ace_doc'>*</span>\n</div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'>3</span><span class='ace_comment ace_doc'>*/</span>\n</div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'>4</span><span class='ace_storage ace_type'>function</span>\xa0<span class='ace_entity ace_name ace_function'>hello</span>\xa0<span class='ace_paren ace_lparen'>(</span><span class='ace_variable ace_parameter'>a</span><span class='ace_punctuation ace_operator'>,\xa0</span><span class='ace_variable ace_parameter'>b</span><span class='ace_punctuation ace_operator'>,\xa0</span><span class='ace_variable ace_parameter'>c</span><span class='ace_paren ace_rparen'>)</span>\xa0<span class='ace_paren ace_lparen'>{</span>\n</div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'>5</span>\xa0\xa0\xa0\xa0<span class='ace_storage ace_type'>console</span><span class='ace_punctuation ace_operator'>.</span><span class='ace_support ace_function ace_firebug'>log</span><span class='ace_paren ace_lparen'>(</span><span class='ace_identifier'>a</span>\xa0<span class='ace_keyword ace_operator'>*</span>\xa0<span class='ace_identifier'>b</span>\xa0<span class='ace_keyword ace_operator'>+</span>\xa0<span class='ace_identifier'>c</span>\xa0<span class='ace_keyword ace_operator'>+</span>\xa0<span class='ace_string'>'sup$'</span><span class='ace_paren ace_rparen'>)</span><span class='ace_punctuation ace_operator'>;</span>\n</div>"
+ "<div class='ace_line'><span class='ace_gutter ace_gutter-cell' unselectable='on'>6</span><span class='ace_paren ace_rparen'>}</span>\n</div>"
+ "</div></div>");
assert.ok(!!result.css); assert.ok(!!result.css);
next(); next();
}, },