recital / core / dist / lib / pipeline / 03-fragment-objects / index.js
index.js
Raw
"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.genFragmentObject = exports.genFragmentObjects = exports.genFragmentsForScenes = void 0;
const moo_1 = __importDefault(require("moo"));
const eol_1 = __importDefault(require("eol"));
const expose_meta_1 = require("../../tools/expose-meta");
const parse_toml_meta_1 = require("../../tools/parse-toml-meta");
const parse_inline_meta_1 = require("../../tools/parse-inline-meta");
const FRAGMENT_START_TOKEN = '<>';
const FRAGMENT_END_TOKEN = '</>';
const genFragmentsForScenes = (scenes) => {
    const newScenes = [];
    for (let scene of scenes) {
        const fragments = (0, exports.genFragmentObjects)(scene.raw);
        const newScene = {
            type: 'scene',
            meta: scene.meta,
            id: scene.id,
            classes: scene.classes,
            primary: scene.primary,
            title: scene.title,
            fragments,
        };
        newScenes.push(newScene);
    }
    return newScenes;
};
exports.genFragmentsForScenes = genFragmentsForScenes;
const genFragmentObjects = (raw) => {
    const fragments = [];
    let currentFragment = '';
    const lines = eol_1.default.split(raw);
    for (let line of lines) {
        if (line.trim().startsWith(FRAGMENT_START_TOKEN)) {
            // we start a new fragment
            let trimmedFragment = currentFragment.trim();
            if (trimmedFragment.length) {
                fragments.push((0, exports.genFragmentObject)(currentFragment));
            }
            currentFragment = line + '\n';
            continue;
        }
        if (line.trim() === FRAGMENT_END_TOKEN) {
            // we end the fragment
            currentFragment += line + '\n';
            fragments.push((0, exports.genFragmentObject)(currentFragment));
            currentFragment = '';
            continue;
        }
        // otherwise, we just add the line to the fragment
        currentFragment += line + '\n';
    }
    // make sure we finish off the last fragment
    let trimmedFragment = currentFragment.trim();
    if (trimmedFragment.length) {
        fragments.push((0, exports.genFragmentObject)(currentFragment));
    }
    return fragments;
};
exports.genFragmentObjects = genFragmentObjects;
/**
 * Creates a single fragment out of the given text.
 * @param text text of the fragment. Should start with the opening <> and end with the </>, if available. If we pass in an object without those tags,
 * we assume that we are outside of a fragment.
 */
const genFragmentObject = (text) => {
    // if we
    if (!text.startsWith(FRAGMENT_START_TOKEN)) {
        return {
            type: 'empty',
            raw: text,
        };
    }
    const fragmentObject = {
        type: 'fragment',
        raw: '',
    };
    const lexer = moo_1.default.states({
        start: {
            fragDefStart: { match: FRAGMENT_START_TOKEN, push: 'fragInlineMeta' },
        },
        fragInlineMeta: {
            fragInlineEnd: { match: /\n/, lineBreaks: true, push: 'fragDefinition' },
            inlineMeta: { match: /[^]+?/, lineBreaks: true },
        },
        fragDefinition: {
            tomlStart: { match: '---', push: 'fragToml' },
            tomlStartPlus: { match: '+++', push: 'fragTomlPlus' },
            fragDefEnd: { match: /\n/, lineBreaks: true, push: 'main' },
            text: { match: /[^]+?/, lineBreaks: true },
        },
        fragToml: {
            tomlEnd: { match: '---', push: 'fragDefinition' },
            toml: { match: /[^]+?(?=---)/, lineBreaks: true },
        },
        fragTomlPlus: {
            tomlEnd: { match: '+++', push: 'fragDefinition' },
            toml: { match: /[^]+?(?=\+\+\+)/, lineBreaks: true },
        },
        main: {
            fragTagEnd: { match: new RegExp(`^\s*${FRAGMENT_END_TOKEN.replace('/', '\\/')}\s*$`), push: 'endFragTag' },
            text: { match: /[^]+?/, lineBreaks: true },
        },
        endFragTag: {
            misc: { match: /[^]+?/, lineBreaks: true },
        },
    });
    lexer.reset(eol_1.default.lf(text));
    let inlineMeta = '';
    for (let token of Array.from(lexer)) {
        switch (token.type) {
            case 'toml':
                const tomlObj = (0, parse_toml_meta_1.parseTOMLMeta)(token.value);
                if (tomlObj === undefined) {
                    throw new Error(lexer.formatError(token, 'empty TOML frontmatter in scene.'));
                }
                if (!fragmentObject.meta) {
                    fragmentObject.meta = {};
                }
                fragmentObject.meta = Object.assign(Object.assign({}, fragmentObject.meta), tomlObj);
                (0, expose_meta_1.exposeMeta)(fragmentObject);
                break;
            case 'text':
                fragmentObject.raw += token.value;
                break;
            case 'inlineMeta':
                inlineMeta += token.value;
        }
    }
    // Process any inline meta
    ////////////////////////////
    inlineMeta = inlineMeta.trim();
    if (inlineMeta.length) {
        let inlineMetaObject = (0, parse_inline_meta_1.parseInlineMeta)(inlineMeta);
        fragmentObject.meta = Object.assign(Object.assign({}, inlineMetaObject), fragmentObject.meta);
        (0, expose_meta_1.exposeMeta)(fragmentObject);
    }
    return fragmentObject;
};
exports.genFragmentObject = genFragmentObject;