"use strict"; /** * Copyright (c) 2022 Amorphous * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.genTokenizedFragment = exports.genTokensForScene = void 0; const eol_1 = __importDefault(require("eol")); const moo_1 = __importDefault(require("moo")); const pipe_1 = require("../../tools/pipe"); const split_preserve_whitespace_1 = require("../../tools/split-preserve-whitespace"); const softlines_1 = require("./plugins/softlines"); const command_shorthand_1 = require("../../tools/command-shorthand"); const at_shorthand_1 = require("../../tools/at-shorthand"); const expose_meta_1 = require("../../tools/expose-meta"); const genTokensForScene = (scene) => { const newFragments = []; for (let fragment of scene.fragments) { const newFragment = (0, exports.genTokenizedFragment)(fragment); newFragments.push(newFragment); } return Object.assign(Object.assign({}, scene), { fragments: newFragments }); }; exports.genTokensForScene = genTokensForScene; const genTokenizedFragment = (fragment) => { const trimmedLineSections = (0, split_preserve_whitespace_1.createTrimWhitespaceTokens)(fragment.raw); const tokens = []; for (let section of trimmedLineSections) { if (section.type === 'none') { const newTokens = createTokensForTextSection(section.text); for (let t of newTokens) { tokens.push(t); } continue; } const newToken = { type: 'rawText', text: section.text, startTag: section.startTag, endTag: section.endTag, }; tokens.push(newToken); } const newFragmentObject = Object.assign(Object.assign({}, fragment), { tokens }); return newFragmentObject; }; exports.genTokenizedFragment = genTokenizedFragment; const createTokensForTextSection = (text) => { // first let's preprocess soft lines, so they don't get separated out. const preprocessedString = (0, pipe_1.pipe)(text, [softlines_1.preprocessSoftLines]); const tokens = []; const lexer = moo_1.default.states({ main: { startCommand: { match: /^\$/, next: 'command' }, startAt: { match: /^@/, next: 'at' }, startMetaTag: { match: /(?<!\n)\n<!/, lineBreaks: true, push: 'meta', }, emptyLine: { match: /\n/, lineBreaks: true }, text: { match: /[^]+?/, lineBreaks: true }, }, command: { endCommand: { match: /\n/, lineBreaks: true, next: 'main' }, commandText: { match: /[^]+?/, lineBreaks: true }, }, meta: { endMetaTag: { match: />/, pop: 1, }, meta: { match: /[^]+?/, lineBreaks: true, }, }, at: { colonWithWS: { match: /: /, next: 'main' }, colon: { match: /:/, next: 'main' }, ws: { match: /[ \t]/, next: 'main' }, shorthandText: { match: /.+?/ }, }, }); lexer.reset(eol_1.default.lf(preprocessedString)); let currentBuffer = ''; let existingToken = null; const createParagraphToken = () => { if (existingToken) { existingToken.text = currentBuffer; tokens.push(existingToken); existingToken = null; } else { // create a new paragraph token const newToken = { type: 'paragraph', text: currentBuffer, }; tokens.push(newToken); } }; for (let token of Array.from(lexer)) { switch (token.type) { case 'text': currentBuffer += token.value; break; case 'emptyLine': if (currentBuffer.length) { createParagraphToken(); // reset the buffer currentBuffer = ''; } break; // @-shorthand cases case 'startAt': currentBuffer = '@'; break; case 'shorthandText': currentBuffer += token.value; break; case 'colonWithWS': case 'colon': case 'ws': const meta = (0, at_shorthand_1.separateAtShorthand)(currentBuffer); currentBuffer = ''; existingToken = { type: 'paragraph', meta, text: '', }; (0, expose_meta_1.exposeMeta)(existingToken); break; // command cases case 'startCommand': currentBuffer = '$'; break; case 'commandText': currentBuffer += token.value; break; case 'endCommand': // create a new command token from current buffer const commandToken = (0, command_shorthand_1.createCommandObject)(currentBuffer); tokens.push(commandToken); currentBuffer = ''; break; // meta cases case 'startMetaTag': if (currentBuffer.length) { createParagraphToken(); } currentBuffer = ''; break; case 'meta': currentBuffer += token.value; break; case 'endMetaTag': if (tokens.length === 0) { throw new Error("Created a post-paragraph meta tag that doesn't modify a paragraph"); } let modifiedToken = tokens[tokens.length - 1]; if (!modifiedToken.meta) { modifiedToken.meta = {}; } modifiedToken.meta._ = currentBuffer; currentBuffer = ''; break; } } // finish off the last token. if (currentBuffer.length) { createParagraphToken(); } return tokens; };