(function (window, document, undefined){ var isIe = !+ "\v1", EOL = isIe? "\r": "\n", EMPTY = function (){ return null ; } , HIGHLIGHTED_NODE_COUNT = 0, DEFAULT_LANGUAGE = "plaintext", DEFAULT_CLASS_PREFIX = "sunlight-", defaultAnalyzer, getComputedStyle, globalOptions = { tabWidth: 4, classPrefix: DEFAULT_CLASS_PREFIX, showWhitespace: false , maxHeight: false } , languages = { } , languageDefaults = { } , events = { beforeHighlightNode: [] , beforeHighlight: [] , beforeTokenize: [] , afterTokenize: [] , beforeAnalyze: [] , afterAnalyze: [] , afterHighlight: [] , afterHighlightNode: [] } ; defaultAnalyzer = (function (){ function defaultHandleToken(suffix){ return function (context){ var element = _AN_Call_createelement("createElement", document, "span"); element.className = context.options.classPrefix + suffix; _AN_Call_appendchild("appendChild", element, context.createTextNode(context.tokens[context.index])); return context.addNode(element) || true ; } ; } return { handleToken: function (context){ return defaultHandleToken(context.tokens[context.index].name)(context); } , handle_default: function (context){ return context.addNode(context.createTextNode(context.tokens[context.index])); } , handle_ident: function (context){ var evaluate = function (rules, createRule){ var i; rules = rules || [] ; for (i = 0; i < _AN_Read_length("length", rules); i++ ){ if (typeof (rules[i]) === "function") { if (rules[i](context)) { return defaultHandleToken("named-ident")(context); } } else if (createRule && createRule(rules[i])(context.tokens)) { return defaultHandleToken("named-ident")(context); } } return false ; } ; return evaluate(context.language.namedIdentRules.custom) || evaluate(context.language.namedIdentRules.follows, function (ruleData){ return createProceduralRule(context.index - 1, -1, ruleData, context.language.caseInsensitive); } ) || evaluate(context.language.namedIdentRules.precedes, function (ruleData){ return createProceduralRule(context.index + 1, 1, ruleData, context.language.caseInsensitive); } ) || evaluate(context.language.namedIdentRules.between, function (ruleData){ return createBetweenRule(context.index, ruleData.opener, ruleData.closer, context.language.caseInsensitive); } ) || defaultHandleToken("ident")(context); } } ; } ()); languageDefaults = { analyzer: create(defaultAnalyzer), customTokens: [] , namedIdentRules: { } , punctuation: /[^\w\s]/, numberParser: defaultNumberParser, caseInsensitive: false , doNotParse: /\s/, contextItems: { } , embeddedLanguages: { } } ; getComputedStyle = (function (){ var func = null ; if (document.defaultView && document.defaultView.getComputedStyle) { func = document.defaultView.getComputedStyle; } else { func = function (element, anything){ return element.currentStyle || { } ; } ; } return function (element, style){ return func(element, null )[style]; } ; } ()); function createCodeReader(text){ var index = 0, line = 1, column = 1, length, EOF = undefined, currentChar, nextReadBeginsLine; text = _AN_Call_replace("replace", _AN_Call_replace("replace", text, /\r\n/g, "\n"), /\r/g, "\n"); length = _AN_Read_length("length", text); currentChar = length > 0? text.charAt(0): EOF; function getCharacters(count){ var value; if (count === 0) { return ""; } count = count || 1; value = text.substring(index + 1, index + count + 1); return value === ""? EOF: value; } return { toString: function (){ return "length: " + length + ", index: " + index + ", line: " + line + ", column: " + column + ", current: [" + currentChar + "]"; } , peek: function (count){ return getCharacters(count); } , substring: function (){ return text.substring(index); } , peekSubstring: function (){ return text.substring(index + 1); } , read: function (count){ var value = getCharacters(count), newlineCount, lastChar; if (value === "") { return value; } if (value !== EOF) { index += _AN_Read_length("length", value); column += _AN_Read_length("length", value); if (nextReadBeginsLine) { line++ ; column = 1; nextReadBeginsLine = false ; } newlineCount = _AN_Read_length("length", _AN_Call_replace("replace", value.substring(0, _AN_Read_length("length", value) - 1), /[^\n]/g, "")); if (newlineCount > 0) { line += newlineCount; column = 1; } lastChar = last(value); if (lastChar === "\n") { nextReadBeginsLine = true ; } currentChar = lastChar; } else { index = length; currentChar = EOF; } return value; } , text: function (){ return text; } , getLine: function (){ return line; } , getColumn: function (){ return column; } , isEof: function (){ return index >= length; } , isSol: function (){ return column === 1; } , isSolWs: function (){ var temp = index, c; if (column === 1) { return true ; } while ((c = text.charAt(--temp)) !== ""){ if (c === "\n") { return true ; } if (!/\s/.test(c)) { return false ; } } return true ; } , isEol: function (){ return nextReadBeginsLine; } , EOF: EOF, current: function (){ return currentChar; } } ; } function create(o){ function F(){ } F.prototype = o; return new F(); } function appendAll(parent, children){ var i; for (i = 0; i < _AN_Read_length("length", children); i++ ){ _AN_Call_appendchild("appendChild", parent, children[i]); } } function last(thing){ return thing.charAt? thing.charAt(_AN_Read_length("length", thing) - 1): thing[_AN_Read_length("length", thing) - 1]; } function contains(arr, value, caseInsensitive){ var i; if (arr.indexOf && !caseInsensitive) { return arr.indexOf(value) >= 0; } for (i = 0; i < _AN_Read_length("length", arr); i++ ){ if (arr[i] === value) { return true ; } if (caseInsensitive && typeof (arr[i]) === "string" && typeof (value) === "string" && arr[i].toUpperCase() === value.toUpperCase()) { return true ; } } return false ; } function merge(defaultObject, objectToMerge){ var key; if (!objectToMerge) { return defaultObject; } for (key in objectToMerge){ defaultObject[key] = objectToMerge[key]; } return defaultObject; } function clone(object){ return merge({ } , object); } function regexEscape(s){ return _AN_Call_replace("replace", s, /[-\/\\^$*+?.()|[\]{}]/g, "\\$&"); } function createProceduralRule(startIndex, direction, tokenRequirements, caseInsensitive){ tokenRequirements = tokenRequirements.slice(0); return function (tokens){ var tokenIndexStart = startIndex, j, expected, actual; if (direction === 1) { tokenRequirements.reverse(); } for (j = 0; j < _AN_Read_length("length", tokenRequirements); j++ ){ actual = tokens[tokenIndexStart + (j * direction)]; expected = tokenRequirements[_AN_Read_length("length", tokenRequirements) - 1 - j]; if (actual === undefined) { if (expected.optional !== undefined && expected.optional) { tokenIndexStart -= direction; } else { return false ; } } else if (actual.name === expected.token && (expected.values === undefined || contains(expected.values, actual.value, caseInsensitive))) { continue ; } else if (expected.optional !== undefined && expected.optional) { tokenIndexStart -= direction; } else { return false ; } } return true ; } ; } function createBetweenRule(startIndex, opener, closer, caseInsensitive){ return function (tokens){ var index = startIndex, token, success = false ; while ((token = tokens[--index]) !== undefined){ if (token.name === closer.token && contains(closer.values, token.value)) { if (token.name === opener.token && contains(opener.values, token.value, caseInsensitive)) { success = true ; break ; } return false ; } if (token.name === opener.token && contains(opener.values, token.value, caseInsensitive)) { success = true ; break ; } } if (!success) { return false ; } index = startIndex; while ((token = tokens[++index]) !== undefined){ if (token.name === opener.token && contains(opener.values, token.value, caseInsensitive)) { if (token.name === closer.token && contains(closer.values, token.value, caseInsensitive)) { success = true ; break ; } return false ; } if (token.name === closer.token && contains(closer.values, token.value, caseInsensitive)) { success = true ; break ; } } return success; } ; } function matchWord(context, wordMap, tokenName, doNotRead){ var current = context.reader.current(), i, word, peek, line = context.reader.getLine(), column = context.reader.getColumn(); wordMap = wordMap || [] ; if (context.language.caseInsensitive) { current = current.toUpperCase(); } if (!wordMap[current]) { return null ; } wordMap = wordMap[current]; for (i = 0; i < _AN_Read_length("length", wordMap); i++ ){ word = wordMap[i].value; peek = current + context.reader.peek(_AN_Read_length("length", word)); if (word === peek || wordMap[i].regex.test(peek)) { return context.createToken(tokenName, context.reader.current() + context.reader[doNotRead? "peek": "read"](_AN_Read_length("length", word) - 1), line, column); } } return null ; } function getNextWhile(tokens, index, direction, matcher){ var count = 1, token; direction = direction || 1; while (token = tokens[index + (direction * count++ )]){ if (!matcher(token)) { return token; } } return undefined; } function createHashMap(wordMap, boundary, caseInsensitive){ var newMap = { } , i, word, firstChar; for (i = 0; i < _AN_Read_length("length", wordMap); i++ ){ word = caseInsensitive? wordMap[i].toUpperCase(): wordMap[i]; firstChar = word.charAt(0); if (!newMap[firstChar]) { newMap[firstChar] = [] ; } newMap[firstChar].push({ value: word, regex: new RegExp("^" + regexEscape(word) + boundary, caseInsensitive? "i": "")} ); } return newMap; } function defaultNumberParser(context){ var current = context.reader.current(), number, line = context.reader.getLine(), column = context.reader.getColumn(), allowDecimal = true , peek; if (!/\d/.test(current)) { if (current !== "." || !/\d/.test(context.reader.peek())) { return null ; } number = current + context.reader.read(); allowDecimal = false ; } else { number = current; if (current === "0" && context.reader.peek() !== ".") { allowDecimal = false ; } } while ((peek = context.reader.peek()) !== context.reader.EOF){ if (!/[A-Za-z0-9]/.test(peek)) { if (peek === "." && allowDecimal && /\d$/.test(context.reader.peek(2))) { number += context.reader.read(); allowDecimal = false ; continue ; } break ; } number += context.reader.read(); } return context.createToken("number", number, line, column); } function fireEvent(eventName, highlighter, eventContext){ var delegates = events[eventName] || [] , i; for (i = 0; i < _AN_Read_length("length", delegates); i++ ){ delegates[i].call(highlighter, eventContext); } } function Highlighter(options){ this.options = merge(clone(globalOptions), options); } Highlighter.prototype = (function (){ var parseNextToken = (function (){ function isIdentMatch(context){ return context.language.identFirstLetter && context.language.identFirstLetter.test(context.reader.current()); } function parseKeyword(context){ return matchWord(context, context.language.keywords, "keyword"); } function parseCustomTokens(context){ var tokenName, token; if (context.language.customTokens === undefined) { return null ; } for (tokenName in context.language.customTokens){ token = matchWord(context, context.language.customTokens[tokenName], tokenName); if (token !== null ) { return token; } } return null ; } function parseOperator(context){ return matchWord(context, context.language.operators, "operator"); } function parsePunctuation(context){ var current = context.reader.current(); if (context.language.punctuation.test(regexEscape(current))) { return context.createToken("punctuation", current, context.reader.getLine(), context.reader.getColumn()); } return null ; } function parseIdent(context){ var ident, peek, line = context.reader.getLine(), column = context.reader.getColumn(); if (!isIdentMatch(context)) { return null ; } ident = context.reader.current(); while ((peek = context.reader.peek()) !== context.reader.EOF){ if (!context.language.identAfterFirstLetter.test(peek)) { break ; } ident += context.reader.read(); } return context.createToken("ident", ident, line, column); } function parseDefault(context){ if (context.defaultData.text === "") { context.defaultData.line = context.reader.getLine(); context.defaultData.column = context.reader.getColumn(); } _AN_Write_text("text", context.defaultData, true , context.reader.current()); return null ; } function parseScopes(context){ var current = context.reader.current(), tokenName, specificScopes, j, opener, line, column, continuation, value; for (tokenName in context.language.scopes){ specificScopes = context.language.scopes[tokenName]; for (j = 0; j < _AN_Read_length("length", specificScopes); j++ ){ opener = specificScopes[j][0]; value = current + context.reader.peek(_AN_Read_length("length", opener) - 1); if (opener !== value && (!context.language.caseInsensitive || value.toUpperCase() !== opener.toUpperCase())) { continue ; } line = context.reader.getLine(), column = context.reader.getColumn(); context.reader.read(_AN_Read_length("length", opener) - 1); continuation = getScopeReaderFunction(specificScopes[j], tokenName); return continuation(context, continuation, value, line, column); } } return null ; } function parseNumber(context){ return context.language.numberParser(context); } function parseCustomRules(context){ var customRules = context.language.customParseRules, i, token; if (customRules === undefined) { return null ; } for (i = 0; i < _AN_Read_length("length", customRules); i++ ){ token = customRules[i](context); if (token) { return token; } } return null ; } return function (context){ if (context.language.doNotParse.test(context.reader.current())) { return parseDefault(context); } return parseCustomRules(context) || parseCustomTokens(context) || parseKeyword(context) || parseScopes(context) || parseIdent(context) || parseNumber(context) || parseOperator(context) || parsePunctuation(context) || parseDefault(context); } ; } ()); function getScopeReaderFunction(scope, tokenName){ var escapeSequences = scope[2] || [] , closerLength = _AN_Read_length("length", scope[1]), closer = typeof (scope[1]) === "string"? new RegExp(regexEscape(scope[1])): scope[1].regex, zeroWidth = scope[3] || false ; return function (context, continuation, buffer, line, column, processCurrent){ var foundCloser = false ; buffer = buffer || ""; processCurrent = processCurrent? 1: 0; function process(processCurrent){ var peekValue, current = context.reader.current(), i; for (i = 0; i < _AN_Read_length("length", escapeSequences); i++ ){ peekValue = (processCurrent? current: "") + context.reader.peek(_AN_Read_length("length", escapeSequences[i]) - processCurrent); if (peekValue === escapeSequences[i]) { buffer += context.reader.read(_AN_Read_length("length", peekValue) - processCurrent); return true ; } } peekValue = (processCurrent? current: "") + context.reader.peek(closerLength - processCurrent); if (closer.test(peekValue)) { foundCloser = true ; return false ; } buffer += processCurrent? current: context.reader.read(); return true ; } ; if (!processCurrent || process(true )) { while (context.reader.peek() !== context.reader.EOF && process(false )){ } } if (processCurrent) { buffer += context.reader.current(); context.reader.read(); } else { buffer += zeroWidth || context.reader.peek() === context.reader.EOF? "": context.reader.read(closerLength); } if (!foundCloser) { context.continuation = continuation; } return context.createToken(tokenName, buffer, line, column); } ; } function switchToEmbeddedLanguageIfNecessary(context){ var i, embeddedLanguage; for (i = 0; i < _AN_Read_length("length", context.language.embeddedLanguages); i++ ){ if (!languages[context.language.embeddedLanguages[i].language]) { continue ; } embeddedLanguage = clone(context.language.embeddedLanguages[i]); if (embeddedLanguage.switchTo(context)) { embeddedLanguage.oldItems = clone(context.items); context.embeddedLanguageStack.push(embeddedLanguage); context.language = languages[embeddedLanguage.language]; context.items = merge(context.items, clone(context.language.contextItems)); break ; } } } function switchBackFromEmbeddedLanguageIfNecessary(context){ var current = last(context.embeddedLanguageStack), lang; if (current && current.switchBack(context)) { context.language = languages[current.parentLanguage]; lang = context.embeddedLanguageStack.pop(); context.items = clone(lang.oldItems); lang.oldItems = { } ; } } function tokenize(unhighlightedCode, language, partialContext, options){ var tokens = [] , context, continuation, token; fireEvent("beforeTokenize", this, { code: unhighlightedCode, language: language} ); context = { reader: createCodeReader(unhighlightedCode), language: language, items: clone(language.contextItems), token: function (index){ return tokens[index]; } , getAllTokens: function (){ return tokens.slice(0); } , count: function (){ return _AN_Read_length("length", tokens); } , options: options, embeddedLanguageStack: [] , defaultData: { text: "", line: 1, column: 1} , createToken: function (name, value, line, column){ return { name: name, line: line, value: isIe? _AN_Call_replace("replace", value, /\n/g, "\r"): value, column: column, language: this.language.name} ; } } ; if (partialContext.continuation) { continuation = partialContext.continuation; partialContext.continuation = null ; tokens.push(continuation(context, continuation, "", context.reader.getLine(), context.reader.getColumn(), true )); } while (!context.reader.isEof()){ switchToEmbeddedLanguageIfNecessary(context); token = parseNextToken(context); if (token !== null ) { if (context.defaultData.text !== "") { tokens.push(context.createToken("default", context.defaultData.text, context.defaultData.line, context.defaultData.column)); _AN_Write_text("text", context.defaultData, false , ""); } if (token[0] !== undefined) { tokens = tokens.concat(token); } else { tokens.push(token); } } switchBackFromEmbeddedLanguageIfNecessary(context); context.reader.read(); } if (context.defaultData.text !== "") { tokens.push(context.createToken("default", context.defaultData.text, context.defaultData.line, context.defaultData.column)); } fireEvent("afterTokenize", this, { code: unhighlightedCode, parserContext: context} ); return context; } function createAnalyzerContext(parserContext, partialContext, options){ var nodes = [] , prepareText = function (){ var nbsp, tab; if (options.showWhitespace) { nbsp = String.fromCharCode(183); tab = new Array(options.tabWidth).join(String.fromCharCode(8212)) + String.fromCharCode(8594); } else { nbsp = String.fromCharCode(160); tab = new Array(options.tabWidth + 1).join(nbsp); } return function (token){ var value = token.value.split(" ").join(nbsp), tabIndex, lastNewlineColumn, actualColumn, tabLength; while ((tabIndex = value.indexOf("\t")) >= 0){ lastNewlineColumn = value.lastIndexOf(EOL, tabIndex); actualColumn = lastNewlineColumn === -1? tabIndex: tabIndex - lastNewlineColumn - 1; tabLength = options.tabWidth - (actualColumn % options.tabWidth); value = value.substring(0, tabIndex) + tab.substring(options.tabWidth - tabLength) + value.substring(tabIndex + 1); } return value; } ; } (); return { tokens: (partialContext.tokens || [] ).concat(parserContext.getAllTokens()), index: partialContext.index? partialContext.index + 1: 0, language: null , getAnalyzer: EMPTY, options: options, continuation: parserContext.continuation, addNode: function (node){ nodes.push(node); } , createTextNode: function (token){ return document.createTextNode(prepareText(token)); } , getNodes: function (){ return nodes; } , resetNodes: function (){ nodes = [] ; } , items: parserContext.items} ; } function highlightText(unhighlightedCode, languageId, partialContext){ var language = languages[languageId], analyzerContext; partialContext = partialContext || { } ; if (language === undefined) { language = languages[DEFAULT_LANGUAGE]; } fireEvent("beforeHighlight", this, { code: unhighlightedCode, language: language, previousContext: partialContext} ); analyzerContext = createAnalyzerContext(tokenize.call(this, unhighlightedCode, language, partialContext, this.options), partialContext, this.options); analyze.call(this, analyzerContext, partialContext.index? partialContext.index + 1: 0); fireEvent("afterHighlight", this, { analyzerContext: analyzerContext} ); return analyzerContext; } function createContainer(ctx){ var container = _AN_Call_createelement("createElement", document, "span"); container.className = ctx.options.classPrefix + ctx.language.name; return container; } function analyze(analyzerContext, startIndex){ var nodes, lastIndex, container, i, tokenName, func, language, analyzer; fireEvent("beforeAnalyze", this, { analyzerContext: analyzerContext} ); if (_AN_Read_length("length", analyzerContext.tokens) > 0) { analyzerContext.language = languages[analyzerContext.tokens[0].language] || languages[DEFAULT_LANGUAGE]; ; nodes = [] ; lastIndex = 0; container = createContainer(analyzerContext); for (i = startIndex; i < _AN_Read_length("length", analyzerContext.tokens); i++ ){ language = languages[analyzerContext.tokens[i].language] || languages[DEFAULT_LANGUAGE]; if (language.name !== analyzerContext.language.name) { appendAll(container, analyzerContext.getNodes()); analyzerContext.resetNodes(); nodes.push(container); analyzerContext.language = language; container = createContainer(analyzerContext); } analyzerContext.index = i; tokenName = analyzerContext.tokens[i].name; func = "handle_" + tokenName; analyzer = analyzerContext.getAnalyzer.call(analyzerContext) || analyzerContext.language.analyzer; analyzer[func]? analyzer[func](analyzerContext): analyzer.handleToken(analyzerContext); } appendAll(container, analyzerContext.getNodes()); nodes.push(container); analyzerContext.resetNodes(); for (i = 0; i < _AN_Read_length("length", nodes); i++ ){ analyzerContext.addNode(nodes[i]); } } fireEvent("afterAnalyze", this, { analyzerContext: analyzerContext} ); } return { matchSunlightNode: function (){ var regex; return function (node){ if (!regex) { regex = new RegExp("(?:\\s|^)" + this.options.classPrefix + "highlight-(\\S+)(?:\\s|$)"); } return regex.exec(node.className); } ; } (), isAlreadyHighlighted: function (){ var regex; return function (node){ if (!regex) { regex = new RegExp("(?:\\s|^)" + this.options.classPrefix + "highlighted(?:\\s|$)"); } return regex.test(node.className); } ; } (), highlight: function (code, languageId){ return highlightText.call(this, code, languageId); } , highlightNode: function highlightRecursive(node){ var match, languageId, currentNodeCount, j, nodes, k, partialContext, container, codeContainer; if (this.isAlreadyHighlighted(node) || (match = this.matchSunlightNode(node)) === null ) { return ; } languageId = match[1]; currentNodeCount = 0; fireEvent("beforeHighlightNode", this, { node: node} ); for (j = 0; j < _AN_Read_length("length", node.childNodes); j++ ){ if (node.childNodes[j].nodeType === 3) { partialContext = highlightText.call(this, _AN_Read_nodevalue("nodeValue", node.childNodes[j]), languageId, partialContext); HIGHLIGHTED_NODE_COUNT++ ; currentNodeCount = currentNodeCount || HIGHLIGHTED_NODE_COUNT; nodes = partialContext.getNodes(); node.replaceChild(nodes[0], node.childNodes[j]); for (k = 1; k < _AN_Read_length("length", nodes); k++ ){ node.insertBefore(nodes[k], nodes[k - 1].nextSibling); } } else if (node.childNodes[j].nodeType === 1) { highlightRecursive.call(this, node.childNodes[j]); } } node.className += " " + this.options.classPrefix + "highlighted"; if (getComputedStyle(node, "display") === "block") { container = _AN_Call_createelement("createElement", document, "div"); container.className = this.options.classPrefix + "container"; codeContainer = _AN_Call_createelement("createElement", document, "div"); codeContainer.className = this.options.classPrefix + "code-container"; if (this.options.maxHeight !== false ) { codeContainer.style.overflowY = "auto"; codeContainer.style.maxHeight = this.options.maxHeight + (/^\d+$/.test(this.options.maxHeight)? "px": ""); } _AN_Call_appendchild("appendChild", container, codeContainer); node.parentNode.insertBefore(codeContainer, node); node.parentNode.removeChild(node); _AN_Call_appendchild("appendChild", codeContainer, node); codeContainer.parentNode.insertBefore(container, codeContainer); codeContainer.parentNode.removeChild(codeContainer); _AN_Call_appendchild("appendChild", container, codeContainer); } fireEvent("afterHighlightNode", this, { container: container, codeContainer: codeContainer, node: node, count: currentNodeCount} ); } } ; } ()); window.Sunlight = { version: "1.18", Highlighter: Highlighter, createAnalyzer: function (){ return create(defaultAnalyzer); } , globalOptions: globalOptions, highlightAll: function (options){ var highlighter = new Highlighter(options), tags = _AN_Call_getelementsbytagname("getElementsByTagName", document, "*"), i; for (i = 0; i < _AN_Read_length("length", tags); i++ ){ highlighter.highlightNode(tags[i]); } } , registerLanguage: function (languageId, languageData){ var tokenName, embeddedLanguages, languageName; if (!languageId) { throw "Languages must be registered with an identifier, e.g. \"php\" for PHP" } languageData = merge(merge({ } , languageDefaults), languageData); languageData.name = languageId; languageData.keywords = createHashMap(languageData.keywords || [] , "\\b", languageData.caseInsensitive); languageData.operators = createHashMap(languageData.operators || [] , "", languageData.caseInsensitive); for (tokenName in languageData.customTokens){ languageData.customTokens[tokenName] = createHashMap(languageData.customTokens[tokenName].values, languageData.customTokens[tokenName].boundary, languageData.caseInsensitive); } embeddedLanguages = [] ; for (languageName in languageData.embeddedLanguages){ embeddedLanguages.push({ parentLanguage: languageData.name, language: languageName, switchTo: languageData.embeddedLanguages[languageName].switchTo, switchBack: languageData.embeddedLanguages[languageName].switchBack} ); } languageData.embeddedLanguages = embeddedLanguages; languages[languageData.name] = languageData; } , isRegistered: function (languageId){ return languages[languageId] !== undefined; } , bind: function (event, callback){ if (!events[event]) { throw "Unknown event \"" + event + "\"" } events[event].push(callback); } , util: { last: last, regexEscape: regexEscape, eol: EOL, clone: clone, escapeSequences: ["\\n", "\\t", "\\r", "\\\\", "\\v", "\\f"] , contains: contains, matchWord: matchWord, createHashMap: createHashMap, createBetweenRule: createBetweenRule, createProceduralRule: createProceduralRule, getNextNonWsToken: function (tokens, index){ return getNextWhile(tokens, index, 1, function (token){ return token.name === "default"; } ); } , getPreviousNonWsToken: function (tokens, index){ return getNextWhile(tokens, index, -1, function (token){ return token.name === "default"; } ); } , getNextWhile: function (tokens, index, matcher){ return getNextWhile(tokens, index, 1, matcher); } , getPreviousWhile: function (tokens, index, matcher){ return getNextWhile(tokens, index, -1, matcher); } , whitespace: { token: "default", optional: true } , getComputedStyle: getComputedStyle} } ; window.Sunlight.registerLanguage(DEFAULT_LANGUAGE, { punctuation: /(?!x)x/, numberParser: EMPTY} ); } (this, document));