Create client-noconflict.html

Is this the right way to use the static highlighter with the 
noconflict build?

Edit as necessary. This is about as good as I can get it...

loads modules from script tags

makes div visible after highlighting

fixes display (sort of)

codeEl margin & padding 0

editor overflow auto, gutter position relative

replace code element with div

mode can be specified as a string

mode and theme may be specified as strings

This preserves the behavior of this method when specifying mode and
theme as objects. It adds the ability to specify mode and theme as
module paths. When specifying mode and / or theme as a module path you
must provide a callback function. The callback function will receive the
same value as the return value previously returned when specifying mode
and theme as objects.

Good stuff.

multiple elements with different modes and themes

The example shows multiple elements highlighted with different modes and
themes all in the same page. The pre element isn't ideal.

The example shows how to transfer the computed width and height of the
element into its inline style so that it won't dramatically change shape
and disrupt the page once it's had highlighting applied. It would
probably be better to replace the elements entirely and apply sizing
styles to the replacement elements but that isn't always an option.
This commit is contained in:
nightwing 2013-04-13 19:41:53 +04:00
commit 978d32eca3
2 changed files with 176 additions and 42 deletions

View file

@ -0,0 +1,85 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Static Code highlighter using Ace</title>
<meta name="author" content="Matthew Kastor">
<style type="text/css">
.code {
width: 50%;
position: relative;
white-space: pre-wrap;
}
</style>
</head>
<body>
<h2>Client Side Syntax Highlighting</h2>
<p>Syntax highlighting using Ace language modes and themes.</p>
<div class="code" ace-mode="ace/mode/css" ace-theme="ace/theme/chrome">
.code {
width: 50%;
position: relative;
white-space: pre-wrap;
}
</div>
<pre class="code" ace-mode="ace/mode/javascript" ace-theme="ace/theme/twilight">
function wobble (flam) {
return flam.wobbled = true;
}
// I'm not exactly sure how to
// turn on softwrap like effects.
var longString = 'this will not wrap ******************************************';
// the scrollbars are from overflow auto on .ace_editor.
</pre>
<script src="../../build/src-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="../../build/src-noconflict/ext-static_highlight.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
(function () {
ace.require([
"ace/ext/static_highlight",
"ace/lib/dom"
], function(highlighter, dom) {
var codeEls = Array.prototype.slice.call(
document.getElementsByClassName('code')
);
codeEls.forEach(function (codeEl) {
var cs = getComputedStyle(codeEl);
codeEl.style.cssText = codeEl.style.cssText +
'width: ' + cs.width + ';' +
'height: ' + cs.height + ';';
var mode = codeEl.getAttribute('ace-mode');
var theme = codeEl.getAttribute('ace-theme');
var data = codeEl.textContent.trim();
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>
</body>
</html>

View file

@ -34,55 +34,104 @@ define(function(require, exports, module) {
var EditSession = require("../edit_session").EditSession;
var TextLayer = require("../layer/text").Text;
var baseStyles = require("../requirejs/text!./static.css");
var config = require("../config");
/**
* Transforms a given input code snippet into HTML using the given mode
*
* @param {string} input Code snippet
* @param {string|mode} mode String specifying the mode to load such as
* `ace/mode/javascript` or, a mode loaded from `/ace/mode`
* (use 'ServerSideHiglighter.getMode').
* @param {string|theme} theme String specifying the theme to load such as
* `ace/theme/twilight` or, a theme loaded from `/ace/theme`.
* @param {number} lineStart A number indicating the first line number. Defaults
* to 1.
* @param {boolean} disableGutter Specifies whether or not to disable the gutter.
* `true` disables the gutter, `false` enables the gutter. Defaults to `false`.
* @param {function} callback When specifying the mode or theme as a string,
* this method has no return value and you must specify a callback function. The
* callback will receive the rendered object containing the properties `html`
* and `css`.
* @returns {object} An object containing the properties `html` and `css`.
*/
/* Transforms a given input code snippet into HTML using the given mode
*
* @param {string} input Code snippet
* @param {mode} mode Mode loaded from /ace/mode (use 'ServerSideHiglighter.getMode')
* @param {string} r Code snippet
* @returns {object} An object containing: html, css
*/
exports.render = function(input, mode, theme, lineStart, disableGutter) {
exports.render = function(input, mode, theme, lineStart, disableGutter, callback) {
lineStart = parseInt(lineStart || 1, 10);
var session = new EditSession("");
session.setMode(mode);
session.setUseWorker(false);
var textLayer = new TextLayer(document.createElement("div"));
textLayer.setSession(session);
textLayer.config = {
characterWidth: 10,
lineHeight: 20
};
session.setValue(input);
var stringBuilder = [];
var length = session.getLength();
for(var ix = 0; ix < length; ix++) {
stringBuilder.push("<div class='ace_line'>");
if (!disableGutter)
stringBuilder.push("<span class='ace_gutter ace_gutter-cell' unselectable='on'>" + (ix + lineStart) + "</span>");
textLayer.$renderLine(stringBuilder, ix, true, false);
stringBuilder.push("</div>");
// if theme and mode are both objects return the expected object.
// preserves current behavior of giving mode and theme objects
if(typeof theme !== 'string' && typeof mode !== 'string') {
return renderer(mode, theme);
}
// let's prepare the whole html
var html = "<div class=':cssClass'>\
<div class='ace_editor ace_scroller ace_text-layer'>\
:code\
</div>\
</div>".replace(/:cssClass/, theme.cssClass).replace(/:code/, stringBuilder.join(""));
// if either the theme or the mode were specified as objects
// then we need to lazily load them.
// loads or passes the specified theme module then loads the mode.
if (typeof theme == "string") {
config.loadModule(['theme', theme], function (theme) {
checkMode(theme);
});
} else {
// if theme was given as an object pass it through.
checkMode(theme);
}
// loads or passes the specified mode module then calls renderer
function checkMode (theme) {
if (typeof mode == "string") {
config.loadModule(['mode', mode], function (mode) {
callback(renderer(new mode.Mode(), theme));
});
} else {
// if mode was given as an object pass it through.
callback(renderer(mode, theme));
}
}
// this was previously the body of exports.render
// exports.render does the same thing it did before but now
// if you give it mode or theme as strings you must specify a callback
// which will receive the return value of renderer.
// specifying the mode or theme as a string did not work before.
function renderer (mode, theme) {
var session = new EditSession("");
session.setMode(mode);
session.setUseWorker(false);
var textLayer = new TextLayer(document.createElement("div"));
textLayer.setSession(session);
textLayer.config = {
characterWidth: 10,
lineHeight: 20
};
textLayer.destroy();
session.setValue(input);
var stringBuilder = [];
var length = session.getLength();
for(var ix = 0; ix < length; ix++) {
stringBuilder.push("<div class='ace_line'>");
if (!disableGutter)
stringBuilder.push("<span class='ace_gutter ace_gutter-cell' unselectable='on'>" + (ix + lineStart) + "</span>");
textLayer.$renderLine(stringBuilder, ix, true, false);
stringBuilder.push("</div>");
}
// let's prepare the whole html
var html = "<div class=':cssClass'>\
<div class='ace_editor ace_scroller ace_text-layer'>\
:code\
</div>\
</div>".replace(/:cssClass/, theme.cssClass).replace(/:code/, stringBuilder.join(""));
return {
css: baseStyles + theme.cssText,
html: html
};
textLayer.destroy();
return {
css: baseStyles + theme.cssText,
html: html
};
}
};
});