var fs = require("fs"); var path = require("path"); var util = require("util"); var cssParse = require("css-parse"); var cssStringify = require("css-stringify"); var parseString = require("plist").parseString; function parseTheme(themeXml, callback) { parseString(themeXml, function(_, theme) { callback(theme[0]) }); } var unsupportedScopes = { }; var supportedScopes = { "keyword": "keyword", "keyword.operator": "keyword.operator", "keyword.other.unit": "keyword.other.unit", "constant": "constant", "constant.language": "constant.language", "constant.library": "constant.library", "constant.numeric": "constant.numeric", "constant.character" : "constant.character", "constant.character.escape" : "constant.character.escape", "constant.character.entity": "constant.character.entity", "constant.other" : "constant.other", "support": "support", "support.function": "support.function", "support.function.dom": "support.function.dom", "support.function.firebug": "support.firebug", "support.function.constant": "support.function.constant", "support.constant": "support.constant", "support.constant.property-value": "support.constant.property-value", "support.class": "support.class", "support.type": "support.type", "support.other": "support.other", "function": "function", "function.buildin": "function.buildin", "storage": "storage", "storage.type": "storage.type", "invalid": "invalid", "invalid.illegal": "invalid.illegal", "invalid.deprecated": "invalid.deprecated", "string": "string", "string.regexp": "string.regexp", "comment": "comment", "comment.documentation": "comment.doc", "comment.documentation.tag": "comment.doc.tag", "variable": "variable", "variable.language": "variable.language", "variable.parameter": "variable.parameter", "meta": "meta", "meta.tag.sgml.doctype": "xml-pe", "meta.tag": "meta.tag", "meta.selector": "meta.selector", "entity.other.attribute-name": "entity.other.attribute-name", "entity.name.function": "entity.name.function", "entity.name": "entity.name", "entity.name.tag": "entity.name.tag", "markup.heading": "markup.heading", "markup.heading.1": "markup.heading.1", "markup.heading.2": "markup.heading.2", "markup.heading.3": "markup.heading.3", "markup.heading.4": "markup.heading.4", "markup.heading.5": "markup.heading.5", "markup.heading.6": "markup.heading.6", "markup.list": "markup.list", "collab.user1": "collab.user1" }; var fallbackScopes = { "keyword": "meta", "support.type": "storage.type", "variable": "entity.name.function" }; // Taken from .ace-tm var defaultGlobals = { "printMargin": "#e8e8e8", "background": "#ffffff", "foreground": "#000000", "gutter": "#f0f0f0", "selection": "rgb(181, 213, 255)", "step": "rgb(198, 219, 174)", "bracket": "rgb(192, 192, 192)", "active_line": "rgba(0, 0, 0, 0.07)", "cursor": "#000000", "invisible": "rgb(191, 191, 191)", "fold": "#6b72e6" }; function extractStyles(theme) { var globalSettings = theme.settings[0].settings; var colors = { "printMargin": defaultGlobals.printMargin, "background": parseColor(globalSettings.background) || defaultGlobals.background, "foreground": parseColor(globalSettings.foreground) || defaultGlobals.foreground, "gutter": defaultGlobals.gutter, "selection": parseColor(globalSettings.selection) || defaultGlobals.selection, "step": defaultGlobals.step, "bracket": parseColor(globalSettings.invisibles) || defaultGlobals.bracket, "active_line": parseColor(globalSettings.lineHighlight) || defaultGlobals.active_line, "cursor": parseColor(globalSettings.caret) || defaultGlobals.cursor, "invisible": "color: " + (parseColor(globalSettings.invisibles) || defaultGlobals.invisible) + ";" }; for (var i=1; i.css rules, // (because some exist, for collab1 and ace_indentation_guide try { var outThemeCss = fs.readFileSync(outputDirectory + "/" + name + ".css"); var oldRules = cssParse(outThemeCss).stylesheet.rules; var newRules = cssParse(css).stylesheet.rules; for (var i = 0; i < newRules.length; i++) { var newSelectors = newRules[i].selectors; for (var j = 0; j < oldRules.length; j++) { var oldSelectors = oldRules[j].selectors; newSelectors = newSelectors.filter(function(s) { return oldSelectors.indexOf(s) == -1; }) if (!newSelectors.length) break; } if (newSelectors.length) { newRules[i].selectors = newSelectors; console.log("Adding NEW rule: ", newRules[i]) oldRules.splice(i, 0, newRules[i]); } } oldRules = normalizeStylesheet(oldRules); css = cssStringify({stylesheet: {rules: oldRules}}, { compress: false }); } catch(e) { console.log("Creating new file: " + name + ".css") css = cssStringify(cssParse(css), { compress: false }); } var js = fillTemplate(jsTemplate, { name: name, css: 'require("../requirejs/text!./' + name + '.css")', // quoteString(css), // cssClass: "ace-" + hyphenate(name), isDark: styles.isDark }); fs.writeFileSync(outputDirectory + "/" + name + ".js", js); fs.writeFileSync(outputDirectory + "/" + name + ".css", css); }) } if (process.argv.length > 2) { var args = process.argv.splice(2); if (args.length < 3) { console.error("Usage: node tmtheme.js [theme_name, path/to/theme.tmTheme path/to/output/directory]"); process.exit(1); } var name = args[0]; var themePath = args[1]; var outputDirectory = args[2]; convertTheme(name, themePath, outputDirectory); } else { for (var name in themes) { convertBuiltinTheme(name); } } if (Object.keys(unsupportedScopes).length > 0) { var sortedUnsupportedScopes = {}; for (var u in unsupportedScopes) { var value = unsupportedScopes[u]; if (sortedUnsupportedScopes[value] === undefined) { sortedUnsupportedScopes[value] = []; } sortedUnsupportedScopes[value].push(u); } console.log("I found these unsupported scopes:"); console.log(sortedUnsupportedScopes); console.log("It's safe to ignore these, but they may affect your syntax highlighting if your mode depends on any of these rules."); console.log("Refer to the docs on ace.ajax.org for information on how to add a scope to the CSS generator."); } /*** TODO: generate images for indent guides in node var indentGuideColor = "#2D2D2D" var canvas = document.createElement("canvas") canvas.width = 1; canvas.height = 2; var ctx = canvas.getContext("2d") imageData = ctx.getImageData(0,0,1,2) function getColor(color) { ctx.fillStyle = color; ctx.fillRect(0,0,1,2); return Array.slice(ctx.getImageData(0,0,1,2).data).slice(0,4) } bgColor = getComputedStyle(ace.renderer.scroller).backgroundColor var a = [].concat(getColor(bgColor), getColor(indentGuideColor)); a.forEach(function(val,i){imageData.data[i] = val}) ctx.putImageData(imageData,0,0) image = canvas.toDataURL("png") var rule = "."+ace.renderer.$theme +" .ace_indent-guide {\n\ background: url(" + image +") right repeat-y;\n\ }" console.log(rule) require("ace/lib/dom").importCssString(rule) */