UNPKG

fractive

Version:

Fractive is a hypertext authoring tool, primarily intended for the creation of interactive fiction.

914 lines 87.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); require("source-map-support").install(); var fs = require("fs"); var path = require("path"); var util = require("util"); var XRegExp = require("XRegExp"); var commonmark = require("commonmark"); var beautifier = require("js-beautify"); var minifier = require("html-minifier"); var ajv = require("ajv"); var overrideJSON = require("json-override"); exports.ProjectDefaults = { title: "Untitled", author: "Anonymous", description: "An interactive story written in Fractive", website: "", twitter: "", markdown: ["source/**/*.md"], javascript: ["source/**/*.js"], assets: ["assets/**"], ignore: [], aliases: [], template: "template.html", output: "build", outputFormat: "prettify", linkTooltips: false, linkTags: { external: { html: "", prepend: false }, inline: { html: "", prepend: false }, section: { html: "", prepend: false }, function: { html: "", prepend: false } }, includeBackButton: true, backButtonHtml: "Back", hardLineBreaks: true, smartPunctuation: true }; var globby = require("globby"); var clc = require("cli-color"); var Compiler; (function (Compiler) { var project = null; var projectPath = ""; var nextInlineID = 0; var sectionCount = 0; var sections = {}; var markdownReader = null; var markdownWriter = null; function ApplyTemplate(basePath, html, javascript) { var templatePath = ""; if (project.template.indexOf("{examples}") == 0) { templatePath = project.template.replace("{examples}", __dirname + "/../templates"); } else { templatePath = path.resolve(basePath, project.template); } if (!fs.existsSync(templatePath)) { console.log("Template file not found: \"" + templatePath + "\""); process.exit(1); } if (!fs.lstatSync(templatePath).isFile()) { console.log("Template \"" + templatePath + "\" is not a file"); process.exit(1); } var template = fs.readFileSync(templatePath, "utf8"); var scriptSection = "<script>"; scriptSection += "var exports = {};"; if (project.outputFormat === 'prettify') { javascript = beautifier.js_beautify(javascript); } scriptSection += "" + javascript; scriptSection += "</script>"; template = InsertHtmlAtMark(scriptSection, template, 'script'); template = InsertHtmlAtMark(html, template, 'story'); if (project.includeBackButton) { var backButtonHtml = '<a href="javascript:Core.GotoPreviousSection();">' + project.backButtonHtml + '</a>'; template = InsertHtmlAtMark(backButtonHtml, template, 'backButton', false); } var openGraphHtml = "<meta property=\"og:title\" content=\"" + project.title + "\"/>\n"; openGraphHtml += "<meta property=\"og:description\" content=\"" + project.description + "\"/>\n"; openGraphHtml += "<meta name=\"twitter:card\" content=\"summary\"/>\n"; if (project.twitter.length > 0) { if (project.twitter[0] !== '@') { project.twitter = "@" + project.twitter; } openGraphHtml += "<meta name=\"twitter:creator\" content=\"" + project.twitter + "\"/>\n"; } template = InsertHtmlAtMark(openGraphHtml, template, 'opengraph', false); template = InsertHtmlAtMark(project.title, template, 'title', false); template += "<script>Core.BeginStory();</script>"; if (project.outputFormat === 'minify') { return minifier.minify(template, { caseSensitive: true, collapseWhitespace: true, log: OnMinifierLog, minifyCSS: true, minifyJS: true, removeAttributeQuotes: true, removeComments: true, removeEmptyAttributes: true, removeEmptyElements: false, removeRedundantAttributes: true }); } else if (project.outputFormat === 'prettify') { return beautifier.html(template); } else { return template; } } function CleanDirectoryRecursive(targetPath, options) { if (fs.lstatSync(targetPath).isDirectory()) { var files = fs.readdirSync(targetPath, "utf8"); for (var i = 0; i < files.length; i++) { CleanDirectoryRecursive(path.resolve(targetPath, files[i]), options); } if (!options.dryRun) { fs.rmdirSync(targetPath); } } else { if (!options.dryRun) { fs.unlinkSync(targetPath); } } } function Compile(buildPath, options) { projectPath = path.dirname(buildPath); var targetProject = JSON.parse(fs.readFileSync(buildPath, "utf8")); var validator = new ajv(); var valid = validator.validate(JSON.parse(fs.readFileSync(path.join(__dirname, "../src/ProjectSchema.json"), "utf8")), targetProject); if (!valid) { LogError(" " + buildPath + ": Failed validating JSON"); for (var i = 0; i < validator.errors.length; i++) { LogError(" " + validator.errors[i].dataPath + " " + validator.errors[i].message + " " + util.inspect(validator.errors[i].params)); } process.exit(1); } project = overrideJSON(exports.ProjectDefaults, targetProject, true); if (project.markdown.length < 1) { LogError("No Markdown input patterns were given (check the 'markdown' property in your fractive.json)"); process.exit(1); } if (project.output.length < 1) { LogError("No output directory was given (check the 'output' property in your fractive.json)"); process.exit(1); } if (options.dryRun) { console.log(clc.red("\n(This is a dry run. No output files will be written.)\n")); } var cleanDir = path.resolve(projectPath, project.output); if (!fs.existsSync(cleanDir)) { CreateDirectoryRecursive(cleanDir); } else { CleanDirectoryRecursive(cleanDir, options); } sections = {}; markdownReader = new commonmark.Parser({ smart: project.smartPunctuation }); markdownWriter = new commonmark.HtmlRenderer({ softbreak: (project.hardLineBreaks ? "<br/>" : "\n") }); var globOptions = { cwd: projectPath, expandDirectories: true, ignore: project.ignore.concat(project.output + "/**"), matchBase: true, nodir: true, nomount: true }; var targets = { markdownFiles: globby.sync(project.markdown, globOptions), javascriptFiles: globby.sync(project.javascript, globOptions), assetFiles: globby.sync(project.assets, globOptions) }; var errorCount = 0; var html = ""; for (var i = 0; i < targets.markdownFiles.length; i++) { if (options.verbose || options.dryRun) { LogAction(targets.markdownFiles[i], "render"); } var rendered = RenderFile(path.resolve(projectPath, targets.markdownFiles[i]), options); if (rendered === null) { errorCount++; } else { html += "<!-- " + targets.markdownFiles[i] + " -->\n" + rendered + "\n"; } } if (errorCount > 0) { process.exit(1); } var javascript = ImportFile(path.resolve(__dirname, "Core.js")); for (var i = 0; i < targets.javascriptFiles.length; i++) { if (options.verbose || options.dryRun) { LogAction(targets.javascriptFiles[i], "import"); } javascript += "// " + targets.javascriptFiles[i] + "\n" + ImportFile(path.resolve(projectPath, targets.javascriptFiles[i])) + "\n"; } html = ApplyTemplate(projectPath, html, javascript); var outputDir = path.resolve(projectPath, project.output); if (!fs.existsSync(outputDir)) { CreateDirectoryRecursive(outputDir); } for (var i = 0; i < targets.assetFiles.length; i++) { if (options.verbose || options.dryRun) { LogAction(targets.assetFiles[i], "copy"); } if (!options.dryRun) { var sourcePath = path.resolve(projectPath, targets.assetFiles[i]); var destPath = path.resolve(outputDir, targets.assetFiles[i]); var destDir = path.dirname(destPath); if (!fs.existsSync(destDir)) { CreateDirectoryRecursive(destDir); } fs.copyFileSync(sourcePath, destPath); } } var indexPath = path.resolve(outputDir, "index.html"); if (options.verbose || options.dryRun) { LogAction(indexPath.split(path.resolve(projectPath)).join(""), "output"); } if (!options.dryRun) { fs.writeFileSync(indexPath, html, "utf8"); } } Compiler.Compile = Compile; function CreateDirectoryRecursive(targetPath) { var separator = path.sep; var initDir = (path.isAbsolute(targetPath) ? separator : ""); targetPath.split(separator).reduce(function (parentDir, childDir) { var currentPath = path.resolve(parentDir, childDir); if (!fs.existsSync(currentPath)) { fs.mkdirSync(currentPath); } return currentPath; }, initDir); } function GetLinkText(node) { if (node.type !== "link") { console.log("GetLinkText received a node of type " + node.type + ", which is illegal and will be skipped"); return null; } var html = markdownWriter.render(node); for (var i = 0; i < html.length; i++) { if (html[i] === ">") { html = html.substring(i + 1, html.length - 4); break; } } return html; } function ImportFile(filepath) { if (!fs.existsSync(filepath)) { console.log("File not found: \"" + filepath + "\""); process.exit(1); } if (!fs.lstatSync(filepath).isFile()) { console.log("\"" + filepath + " is not a file"); process.exit(1); } return fs.readFileSync(filepath, "utf8"); } function InsertHtmlAtMark(snippet, template, mark, required) { if (required === void 0) { required = true; } var markComment = "<!--{" + mark + "}-->"; if (template.indexOf(markComment) === -1 && required) { LogError("Template file does not contain mark " + markComment); process.exit(1); } return template.split(markComment).join(snippet); } function InsertHtmlIntoNode(rootNode, startIndex, endIndex, dataAttrs) { var preContent = rootNode.literal.substring(0, startIndex); var postContent = rootNode.literal.substring(endIndex); rootNode.literal = preContent; var htmlNode = new commonmark.Node("html_inline", rootNode.sourcepos); var attrs = ""; for (var i = 0; i < dataAttrs.length; i++) { attrs += " data-" + dataAttrs[i].attr + "=\"" + dataAttrs[i].value + "\""; } switch (rootNode.type) { case "code": { htmlNode.literal = "<code><span" + attrs + "></span></code>"; break; } case "code_block": { htmlNode.literal = "<pre><code><span" + attrs + "></span></code></pre>"; break; } default: { htmlNode.literal = "<span" + attrs + "></span>"; break; } } rootNode.insertAfter(htmlNode); if (rootNode.literal === "") { rootNode.unlink(); } if (postContent && postContent.length > 0) { var postNode = new commonmark.Node(rootNode.type, rootNode.sourcepos); postNode.literal = postContent; htmlNode.insertAfter(postNode); } return htmlNode; } function IsExternalLink(url) { var tokens = url.split("/"); switch (tokens[0].toLowerCase()) { case "http:": case "https:": case "mailto:": { return true; } } return false; } function LogAction(filePath, action) { console.log(" " + clc.green(action) + " " + path.relative(projectPath, filePath)); } function LogAST(ast) { if (ast === null) { return; } var indent = 0; var getIndent = function (indent) { var result = ''; for (var i = 0; i < indent; i++) { result += ' '; } return result; }; var walker = ast.walker(); var event; while ((event = walker.next())) { if (event.node.isContainer && !event.entering) { indent--; } if (!event.node.isContainer || event.entering) { console.log(clc.blue("" + getIndent(indent) + event.node.type + ": " + (event.node.literal ? event.node.literal.split('\n').join('\\n') : ''))); } if (event.node.isContainer && event.entering) { indent++; } } } function LogError(text) { console.error(clc.red(text)); } function LogParseError(text, filePath, node, lineOffset, columnOffset) { if (node && node.sourcepos) { var line = node.sourcepos[0][0] + (lineOffset !== undefined ? lineOffset : 0); var column = node.sourcepos[0][1] + (columnOffset !== undefined ? columnOffset : 0); LogError(path.relative(projectPath, filePath) + " (" + line + "," + column + "): " + text); } else { LogError(path.relative(projectPath, filePath) + ": " + text); } } function OnMinifierLog(data) { switch (typeof (data)) { case "string": { if (data.indexOf("minified in:") < 0) { console.log(clc.yellow("Minifier: " + data)); } break; } case "object": { if (data.message) { console.log(clc.yellow("Minifier: " + data.message + "\nThis isn't fatal; it just means Javascript was not minified.\nTry running CLI uglifyjs on the .js file(s) to narrow down the error.")); } else { console.log(clc.yellow("\"Minifier: Unrecognized object format in log... raw object follows:")); console.log(data); } break; } default: { console.log(clc.yellow("\"Minifier: Unhandled data type '" + typeof (data) + "' in log... raw data follows:")); console.log(data); break; } } } function RenderFile(filepath, options) { if (!fs.existsSync(filepath)) { console.log("File not found: " + filepath); process.exit(1); } var markdown = ReplaceAliases(fs.readFileSync(filepath, "utf8")); var ast = markdownReader.parse(markdown); if (options.debug) { console.log("\nRAW AST\n"); LogAST(ast); } var walker = ast.walker(); var event, node, prevNode; while ((event = walker.next())) { node = event.node; if (node.type === "text" && prevNode && prevNode.type === "text") { if (node.literal) { prevNode.literal += node.literal; } node.unlink(); } else { prevNode = node; } } if (options.debug) { console.log("\nCONSOLIDATED AST\n"); LogAST(ast); } sectionCount = 0; walker = ast.walker(); while ((event = walker.next())) { node = event.node; switch (node.type) { case "link": { if (!RenderLink(walker, event, filepath)) { return null; } break; } case "text": case "code": case "code_block": case "html_inline": case "html_block": { if (!RenderText(walker, event, filepath)) { return null; } break; } case "image": { if (!RenderImage(walker, event, filepath)) { return null; } break; } } } walker = ast.walker(); var firstEvent = walker.next(); var closingNode = new commonmark.Node("html_inline"); closingNode.literal = "</div>"; firstEvent.node.appendChild(closingNode); if (options.debug) { console.log("\nFINAL AST\n"); LogAST(ast); } return markdownWriter.render(ast); } function RenderImage(walker, event, filepath) { if (!walker || !event) { LogError("RenderImage received an invalid state"); return false; } if (event.node.type !== "image") { LogError("RenderImage was passed a " + event.node.type + " node, which is illegal"); return false; } var node = event.node; var alt = ""; if (node.firstChild && node.firstChild.type == "text") { alt = node.firstChild.literal; node.firstChild.unlink(); } var url = node.destination; url = url.replace("%7B", "{").replace("%7D", "}"); if (url[0] !== "{") { var newNode = new commonmark.Node("html_inline"); newNode.literal = "<img src=\"" + url + "\" alt=\"" + alt + "\" title=\"" + alt + "\">"; node.insertBefore(newNode); node.unlink(); walker.resumeAt(newNode); } else { if (url[url.length - 1] !== "}") { LogParseError("Unterminated macro " + url + " in image URL", filepath, node); return false; } switch (url[1]) { case "@": { LogParseError("Invalid macro " + url + " in image URL (section macros cannot be used as image sources)", filepath, node); return false; } case "#": case "$": { var newNode = new commonmark.Node("html_inline"); newNode.literal = "<img data-image-source-macro=\"" + url.substring(1, url.length - 1) + "\" src=\"#\" alt=\"" + alt + "\" title=\"" + alt + "\">"; node.insertBefore(newNode); node.unlink(); walker.resumeAt(newNode); break; } default: { LogParseError("Unknown macro " + url + " in image URL", filepath, node); return false; } } } return true; } function RenderLink(walker, event, filepath) { if (!walker || !event) { LogError("RenderLink received an invalid state"); return false; } if (event.node.type !== "link") { LogError("RenderLink received a " + event.node.type + " node, which is illegal"); return false; } var url = event.node.destination; url = url.replace("%7B", "{").replace("%7D", "}"); if (url[0] !== "{") { if (IsExternalLink(url)) { if (event.entering) { var newNode = new commonmark.Node("html_inline", event.node.sourcepos); newNode.literal = project.linkTags.external.html; if (project.linkTags.external.prepend) { event.node.prependChild(newNode); walker.resumeAt(newNode); } else { event.node.appendChild(newNode); } return true; } else { return RewriteLinkNode(event.node, [ { "attr": "target", "value": "_blank" }, { "attr": "href", "value": event.node.destination } ], null); } } else { return true; } } if (url[url.length - 1] !== "}") { LogParseError("Unterminated macro in link destination " + url, filepath, event.node); return false; } var tokens = url.substring(1, url.length - 1).split(":"); url = tokens[0]; var modifier = (tokens.length > 1 ? tokens[1] : ""); switch (modifier) { case "inline": { if (event.entering) { var newNode = new commonmark.Node("html_inline", event.node.sourcepos); newNode.literal = project.linkTags.inline.html; if (project.linkTags.inline.prepend) { event.node.prependChild(newNode); walker.resumeAt(newNode); } else { event.node.appendChild(newNode); } return true; } else { var attrs = [ { attr: "href", value: "javascript:;" }, { attr: "data-replace-with", value: url } ]; return RewriteLinkNode(event.node, attrs, "inline-" + nextInlineID++); } } default: { switch (url[0]) { case "@": { if (event.entering) { var newNode = new commonmark.Node("html_inline", event.node.sourcepos); newNode.literal = project.linkTags.section.html; if (project.linkTags.section.prepend) { event.node.prependChild(newNode); walker.resumeAt(newNode); } else { event.node.appendChild(newNode); } return true; } else { var attrs = [ { attr: "href", value: "javascript:;" }, { attr: "data-goto-section", value: url.substring(1) } ]; return RewriteLinkNode(event.node, attrs, null); } } case "#": { if (event.entering) { var newNode = new commonmark.Node("html_inline", event.node.sourcepos); newNode.literal = project.linkTags.function.html; if (project.linkTags.function.prepend) { event.node.prependChild(newNode); walker.resumeAt(newNode); } else { event.node.appendChild(newNode); } return true; } else { var attrs = [ { attr: "href", value: "javascript:;" }, { attr: "data-call-function", value: url.substring(1) } ]; return RewriteLinkNode(event.node, attrs, null); } } case "$": { LogParseError("Variable macros can't be used as link destinations: {" + url + "}", filepath, event.node); return false; } default: { LogParseError("Unrecognized macro in link destination: {" + url + "}", filepath, event.node); return false; } } } } } function RenderText(walker, event, filepath) { if (!walker || !event) { LogError("RenderText received an invalid state"); return false; } var node = event.node; var lineOffset = 0; var columnOffset = 0; for (var i = 0; i < node.literal.length; i++) { if (node.literal[i] === '\\') { i = SkipEscapedSubstring(node.literal, i); continue; } else if (node.literal[i] === '{') { var insertedNode = null; var macro = null; var braceCount = 1; for (var j_1 = i + 1; j_1 < node.literal.length; j_1++) { if (node.literal[j_1] === '{') { braceCount++; } else if (node.literal[j_1] === '}') { if (--braceCount == 0) { macro = node.literal.substring(i, j_1 + 1); break; } } } if (macro === null) { LogParseError("Unterminated macro near \"" + node.literal.substring(i, i + 10) + "\" in text", filepath, node, lineOffset, columnOffset); return false; } switch (macro[1]) { case "{": { if (node.parent) { var macroContents = macro.substring(2, macro.length - 2); var sectionName = macroContents; var tags = []; if (macroContents.indexOf(":") !== -1) { sectionName = macroContents.substring(0, macroContents.indexOf(":")).trim(); var tagDeclarations = macroContents.substring(macroContents.indexOf(":") + 1); var tagTokens = tagDeclarations.split(','); for (var j = 0; j < tagTokens.length; ++j) { tags.push(tagTokens[j].trim()); } } if (sections[sectionName] !== undefined) { LogParseError("Section \"" + sectionName + "\" was already defined in \"" + sections[sectionName].sourceFile + "\" on line \"" + sections[sectionName].lineNumber + "\"", filepath, node, lineOffset, columnOffset); return false; } else { sections[sectionName] = { sourceFile: path.relative(projectPath, filepath), lineNumber: lineOffset }; } insertedNode = new commonmark.Node("html_inline", node.sourcepos); insertedNode.literal = (sectionCount > 0 ? "</div>\n" : "") + "<div id=\"" + sectionName + "\" data-tags=\"" + tags.toString() + "\" class=\"section\" hidden=\"true\">"; if (node.prev) { LogParseError("Section macro \"" + macro + "\" must be defined in its own paragraph/on its own line", filepath, node, lineOffset, columnOffset); return false; } else if (node.parent.type === "paragraph") { node.parent.insertAfter(insertedNode); var newParagraph = new commonmark.Node("paragraph", node.sourcepos); var nodesMoved = 0; var bSkippedFirstBreak = false; while ((event = walker.next())) { if (event.node.type === "paragraph" && !event.entering) { break; } if (event.node.type === "softbreak" && !bSkippedFirstBreak) { bSkippedFirstBreak = true; continue; } newParagraph.appendChild(event.node); ++nodesMoved; } var remainderNode = new commonmark.Node("text", node.sourcepos); remainderNode.literal = StripLeadingWhitespace(node.literal.substring(macro.length)); newParagraph.prependChild(remainderNode); if (nodesMoved > 0 || remainderNode.literal.length > 0) { insertedNode.insertAfter(newParagraph); } node.parent.unlink(); } else { LogParseError("Section macro \"" + macro + "\" cannot be defined inside another block element", filepath, node, lineOffset, columnOffset); return false; } sectionCount++; } else { LogParseError("Node for \"" + macro + "\" has no parent", filepath, node, lineOffset, columnOffset); return false; } break; } case "@": case "#": case "$": { insertedNode = InsertHtmlIntoNode(node, i, i + macro.length, [{ attr: "expand-macro", value: macro.substring(1, macro.length - 1) }]); break; } default: { LogParseError("Unrecognized macro \"" + macro + "\" in text", filepath, node.parent, lineOffset, columnOffset); return false; } } walker.resumeAt(insertedNode); break; } else if (node.literal[i] === '\n') { lineOffset++; columnOffset = -1; } columnOffset++; } if (node.literal) { node.literal = node.literal.split('\\{').join('{'); } return true; } function ReplaceAliases(source) { if (project.aliases.length < 1) { return source; } var markdown = source; for (var i = 0; i < markdown.length; i++) { if (markdown[i] === '\\') { i = SkipEscapedSubstring(markdown, i); continue; } else if (markdown[i] === '{') { var bIsEnd = (markdown[i + 1] === '/'); for (var j = i + 1; j < markdown.length; j++) { if (markdown[j] === '{') { i = j; break; } else if (markdown[j] === '}') { var macro = markdown.substring(i, j + 1); var macroName = macro.substring(bIsEnd ? 2 : 1, macro.length - 1); var replacement = null; var regexp = null; var regexpToReplace = null; var regexpReplacement = null; for (var k = 0; k < project.aliases.length; k++) { var alias = project.aliases[k]; if (alias.hasOwnProperty('alias') && macroName === alias.alias) { replacement = (bIsEnd ? alias.end : alias.replaceWith); break; } else if (alias.hasOwnProperty('regex')) { regexp = XRegExp(alias.regex); if (alias.debug) { console.log("Checking macro " + macroName + " against regex " + alias.regex); } regexpToReplace = XRegExp('{' + (bIsEnd ? '/' : '') + alias.regex + '}'); if (regexp.exec(macroName)) { if (alias.debug) { console.log("Replacing macro " + macroName + " with " + regexpReplacement); } regexpReplacement = (bIsEnd ? alias.end : alias.replaceWith); break; } } } if (replacement !== null) { markdown = markdown.split(macro).join(replacement); i += replacement.length - 1; } else if (regexpReplacement !== null) { replacement = XRegExp.replace(regexpToReplace, regexpToReplace, regexpReplacement); markdown = XRegExp.replace(markdown, regexpToReplace, regexpReplacement, 'all'); i += replacement.length - 1; } break; } } } } return markdown; } function RewriteLinkNode(node, attributes, id) { if (node.type != "link") { console.log("RewriteLinkNode received a node of type " + node.type + ", which is illegal and will be skipped"); return false; } var newNode = new commonmark.Node("html_inline", node.sourcepos); var title = "title=\"" + (project.linkTooltips ? node.destination.replace("%7B", "{").replace("%7D", "}") : "") + "\""; var attrs = ""; for (var i = 0; i < attributes.length; i++) { attrs += " " + attributes[i].attr + "=\"" + attributes[i].value + "\""; } newNode.literal = "<a " + title + attrs; if (id !== null) { newNode.literal += " id=\"" + id + "\""; } newNode.literal += ">" + GetLinkText(node) + "</a>"; node.insertBefore(newNode); node.unlink(); return true; } function ShowUsage() { console.log(""); console.log("Usage:"); console.log(clc.green("node lib/CLI.js compile") + " " + clc.blue("<storyDirectory|configFilePath>") + " " + clc.yellow("[options]")); console.log(""); console.log(clc.blue("storyDirectory:") + " The folder path where the story source files are located. Looks for fractive.json in the root."); console.log(clc.blue("configFilePath:") + " If you want to build with a different config, specify the config.json path directly."); console.log(""); console.log(clc.yellow("--dry-run:") + " Log what would've been done, but don't actually touch any files."); console.log(clc.yellow("--verbose:") + " Log more detailed build information"); console.log(clc.yellow("--debug:") + " Log debugging information during the build"); console.log(""); console.log(clc.green("node lib/CLI.js compile /Users/Desktop/MyStory") + " " + clc.yellow("--verbose")); console.log(""); } Compiler.ShowUsage = ShowUsage; function SkipEscapedSubstring(s, startIndex) { if (s[startIndex] !== '\\') { return startIndex; } if (s[startIndex + 1] === '\\') { return startIndex; } if (s[startIndex + 1] !== '{') { return startIndex + 1; } var braceCount = 0; for (var i = startIndex + 1; i < s.length; i++) { if (s[i] === '{') { ++braceCount; } else if (s[i] === '}' && --braceCount === 0) { return i; } } return startIndex + 1; } function StripLeadingWhitespace(s) { for (var i = 0; i < s.length; i++) { if (s[i] !== " " && s[i] !== "\t" && s[i] !== "\n") { return s.substring(i); } } return ""; } })(Compiler = exports.Compiler || (exports.Compiler = {})); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tcGlsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvQ29tcGlsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFzQkEsT0FBTyxDQUFDLG9CQUFvQixDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFHeEMsdUJBQXlCO0FBQ3pCLDJCQUE2QjtBQUM3QiwyQkFBNkI7QUFHN0IsaUNBQW1DO0FBR25DLHVDQUF5QztBQUd6Qyx3Q0FBMEM7QUFDMUMsd0NBQTBDO0FBRzFDLHlCQUEyQjtBQUMzQiw0Q0FBOEM7QUFFbkMsUUFBQSxlQUFlLEdBQXFCO0lBQzlDLEtBQUssRUFBRSxVQUFVO0lBQ2pCLE1BQU0sRUFBRSxXQUFXO0lBQ25CLFdBQVcsRUFBRSwwQ0FBMEM7SUFDdkQsT0FBTyxFQUFFLEVBQUU7SUFDWCxPQUFPLEVBQUUsRUFBRTtJQUNYLFFBQVEsRUFBRSxDQUFFLGdCQUFnQixDQUFFO0lBQzlCLFVBQVUsRUFBRSxDQUFFLGdCQUFnQixDQUFFO0lBQ2hDLE1BQU0sRUFBRSxDQUFFLFdBQVcsQ0FBRTtJQUN2QixNQUFNLEVBQUUsRUFBRTtJQUNWLE9BQU8sRUFBRSxFQUFFO0lBQ1gsUUFBUSxFQUFFLGVBQWU7SUFDekIsTUFBTSxFQUFFLE9BQU87SUFDZixZQUFZLEVBQUUsVUFBVTtJQUN4QixZQUFZLEVBQUUsS0FBSztJQUNuQixRQUFRLEVBQUU7UUFDVCxRQUFRLEVBQUU7WUFDVCxJQUFJLEVBQUUsRUFBRTtZQUNSLE9BQU8sRUFBRSxLQUFLO1NBQ2Q7UUFDRCxNQUFNLEVBQUU7WUFDUCxJQUFJLEVBQUUsRUFBRTtZQUNSLE9BQU8sRUFBRSxLQUFLO1NBQ2Q7UUFDRCxPQUFPLEVBQUU7WUFDUixJQUFJLEVBQUUsRUFBRTtZQUNSLE9BQU8sRUFBRSxLQUFLO1NBQ2Q7UUFDRCxRQUFRLEVBQUU7WUFDVCxJQUFJLEVBQUUsRUFBRTtZQUNSLE9BQU8sRUFBRSxLQUFLO1NBQ2Q7S0FDRDtJQUNELGlCQUFpQixFQUFFLElB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