From 5a808ac6a8d5658d9e68d1541cab1bd6975fdd74 Mon Sep 17 00:00:00 2001 From: Jan Jongboom Date: Wed, 12 Oct 2011 18:14:38 +0200 Subject: [PATCH] Highlighting feature of ace as a server side node module! --- lib/ace/serversidehighlighter.js | 91 +++++++++++++++++++++++ lib/ace/serversidehighlighter_test.js | 101 ++++++++++++++++++++++++++ lib/ace/theme/tomorrow.js | 7 +- 3 files changed, 193 insertions(+), 6 deletions(-) create mode 100644 lib/ace/serversidehighlighter.js create mode 100644 lib/ace/serversidehighlighter_test.js diff --git a/lib/ace/serversidehighlighter.js b/lib/ace/serversidehighlighter.js new file mode 100644 index 00000000..c1ef873a --- /dev/null +++ b/lib/ace/serversidehighlighter.js @@ -0,0 +1,91 @@ +if (typeof process !== "undefined") { + require("../../support/paths"); + require("ace/test/mockdom"); +} + +var theme = require("ace/theme/tomorrow"); +var EditSession = require("ace/edit_session").EditSession; +var Editor = require("ace/editor").Editor; +var MockRenderer = require("ace/test/mockrenderer").MockRenderer; +var TextLayer = require("ace/layer/text").Text; + +/** Ace highlighting but server side + */ +var ServerSideHighlighter = module.exports = function() { +}; + +(function () { + + /** Returns a mode from /ace/mode based on a filename + * + * @param {string} fileName name of the file without directory information + * @returns {mode} A mode that can highlight the given file, or TextMode if nothing matched + */ + function getMode (fileName) { + var extension = fileName.match(/\.(\w+)$/)[1]; + + switch (extension) { + case "js": + var JavascriptMode = require("ace/mode/javascript").Mode; + return new JavascriptMode(); + default: + var TextMode = require("ace/mode/text").Mode; + return new TextMode(); + } + } + + /** 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 + */ + function render (input, mode, theme) { + var session = new EditSession(""); + session.setMode(mode);// || new JavaScriptMode()); + + var editor = new Editor(new MockRenderer(), session); + var textLayer = new TextLayer(document.createElement("div")); + textLayer.setSession(session); + textLayer.config = { + characterWidth: 10, + lineHeight: 20 + }; + + session.setValue(input); + + var stringBuilder = [], length = session.getLength(); + var tokens = session.getTokens(0, length - 1); + + for(var ix = 0; ix < length; ix++) { + var lineTokens = tokens[ix].tokens; + stringBuilder.push("" + (ix+1) + ""); + textLayer.$renderLine(stringBuilder, 0, lineTokens, true); + stringBuilder.push("
"); + } + + // let's prepare the whole html + var html = "
\ +
\ + :code\ +
\ +
".replace(/:cssClass/, theme.cssClass).replace(/:code/, stringBuilder.join("")); + + return { + css: theme.cssText, + html: html + }; + } + + this.getMode = getMode; + this.render = render; +}).call(ServerSideHighlighter.prototype); + +//"/**\n\ +// * juhu\n\ +// * kinner \n\ +// */\n\ +// function a(b) {\n\ +// return b;\n\ +// }" \ No newline at end of file diff --git a/lib/ace/serversidehighlighter_test.js b/lib/ace/serversidehighlighter_test.js new file mode 100644 index 00000000..cf461bfb --- /dev/null +++ b/lib/ace/serversidehighlighter_test.js @@ -0,0 +1,101 @@ +require("../../support/paths"); + +var assert = require("assert"); +var ServerSideHighlighter = require("./serversidehighlighter"); + +// Execution ORDER: test.setUpSuite, setUp, testFn, tearDown, test.tearDownSuite +module.exports = { + timeout: 10000, + + dispatcher: null, + req: null, + res: null, + highlighter: null, + + setUpSuite: function (next) { + this.highlighter = new ServerSideHighlighter(); + next(); + }, + + setUp: function(next) { + next(); + }, + + tearDown: function(next) { + next(); + }, + + "test extension js": function(next) { + var JavascriptMode = require("ace/mode/javascript").Mode + assert.equal(this.highlighter.getMode("jan.js") instanceof JavascriptMode, true); + next(); + }, + + "test extension unknown": function(next) { + var TextMode = require("ace/mode/text").Mode + assert.equal(this.highlighter.getMode("jan.unknown") instanceof TextMode, true); + next(); + }, + + "test simple snippet": function(next) { + var theme = require("ace/theme/tomorrow"); + var snippet = "/** this is a function\n\ +*\n\ +*/\n\ +function hello (a, b, c) {\n\ + console.log(a * b + c + 'sup?');\n\ +}"; + var mode = this.highlighter.getMode("some.js"); + + var isError = false, result; + try { + result = this.highlighter.render(snippet, mode, theme); + } + catch (e) { + console.log(e); + isError = true; + } + // todo: write something more meaningful + assert.equal(isError, false); + + next(); + }, + + "test css from theme is used": function(next) { + var theme = require("ace/theme/tomorrow"); + var snippet = "/** this is a function\n\ +*\n\ +*/\n\ +function hello (a, b, c) {\n\ + console.log(a * b + c + 'sup?');\n\ +}"; + var mode = this.highlighter.getMode("some.js"); + + var isError = false, result; + result = this.highlighter.render(snippet, mode, theme); + + assert.equal(result.css, theme.cssText); + + next(); + }, + + "test theme classname should be in output html": function (next) { + var theme = require("ace/theme/tomorrow"); + var snippet = "/** this is a function\n\ +*\n\ +*/\n\ +function hello (a, b, c) {\n\ + console.log(a * b + c + 'sup?');\n\ +}"; + var mode = this.highlighter.getMode("some.js"); + + var isError = false, result; + result = this.highlighter.render(snippet, mode, theme); + + assert.equal(!!result.html.match(/
/), true); + + next(); + } +}; + +!module.parent && require("asyncjs").test.testcase(module.exports, "ServerSideHighlighter").exec(); diff --git a/lib/ace/theme/tomorrow.js b/lib/ace/theme/tomorrow.js index 977c4d33..e91cd3c5 100644 --- a/lib/ace/theme/tomorrow.js +++ b/lib/ace/theme/tomorrow.js @@ -37,9 +37,7 @@ define(function(require, exports, module) { - var dom = require("pilot/dom"); - - var cssText = ".ace-tomorrow .ace_editor {\ + exports.cssText = ".ace-tomorrow .ace_editor {\ border: 2px solid rgb(159, 159, 159);\ }\ \ @@ -254,8 +252,5 @@ background-color:#8959A8;\ \ }"; - // import CSS once - dom.importCssString(cssText); - exports.cssClass = "ace-tomorrow"; }); \ No newline at end of file