fractive
Version:
Fractive is a hypertext authoring tool, primarily intended for the creation of interactive fiction.
914 lines • 87.6 kB
JavaScript
"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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