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:
parent
19dd921127
commit
978d32eca3
2 changed files with 176 additions and 42 deletions
85
demo/static-highlighter/client-noconflict.html
Normal file
85
demo/static-highlighter/client-noconflict.html
Normal 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>
|
||||
|
|
@ -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
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue