UNPKG

bitran

Version:

📜 Highly customizable text processor and transpiler.

260 lines (259 loc) • 9.19 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); import { c as textToStrBlocks, P as ProductLayout, n as normalizeText, B as BlockNode, I as InlinerNode } from "./productNode-C0XZsQy2.js"; import { d as detachMeta, p as parseMeta, s as stringifyMeta } from "./productMeta-DotuXXRl.js"; import { B as BlockParseFactory, g as getIntersection, e as RangeIntersection, T as TextNode } from "./index-DiVYKXTv.js"; import { R as RootNode } from "./root-BUkExl5d.js"; import { E as ErrorNode, B as BlocksNode, I as InlinersNode } from "./shared-B4X4KQeO.js"; class AutoId { constructor() { __publicField(this, "ids", {}); } exists(id) { return id in this.ids; } push(id) { if (id in this.ids) throw new Error(`Duplicate auto id "${id}"!`); this.ids[id] = null; } } class DefaultAutoId extends AutoId { constructor() { super(...arguments); __publicField(this, "nameCounters", {}); } generate(node) { var _a; const name = node.name; (_a = this.nameCounters)[name] || (_a[name] = 0); let autoId = `${name}:${++this.nameCounters[name]}`; return autoId; } finalize(id) { let finalId = id; while (this.exists(finalId)) finalId += "-"; return finalId; } } class Parser { // private blockFactories: Record<string, new () => BlockParseFactory> = {}; // private inlinerFactories: Record<string, new () => InlinerParseFactory> = {}; constructor(coreConfig) { __publicField(this, "coreConfig"); __publicField(this, "blockFactories", []); __publicField(this, "inlinerFactories", []); this.coreConfig = coreConfig; for (const [productName, ProductCore] of Object.entries(coreConfig.products)) { const factories = Array.isArray(ProductCore.Parser) ? ProductCore.Parser : [ProductCore.Parser]; for (const Factory of factories) if (Factory) this[Factory.prototype instanceof BlockParseFactory ? "blockFactories" : "inlinerFactories"].push([productName, Factory]); } } async parse(text, options) { [text, options] = resolveParseArgs(text, options); const root = new RootNode(); const blocks = await this.parseBlocks(text, options); root.setNodes(blocks); return root; } // // Block Parsing // async parseBlocks(text, options) { if (typeof text !== "string") return []; [text, options] = resolveParseArgs(text, options); const blocks = []; for (const strBlock of textToStrBlocks(text)) { const block = await this.parseBlock(strBlock, options); if (!block) continue; blocks.push(block); } return blocks; } async parseBlock(strBlock, options) { [strBlock, options] = resolveParseArgs(strBlock, options); const { meta, restText } = detachMeta(strBlock); for (const [blockName, BlockFactory] of this.blockFactories) { const block = new this.coreConfig.products[blockName].Node(); block.name = blockName; block.meta = meta; const factory = prepareFactory(BlockFactory, this, block, options); if (!factory.canParse(restText)) continue; try { block.parseData = await factory.createParseData(restText); block.generated.autoId = createAutoId(options.autoId, factory, block); options.step && await options.step(block); return block; } catch (error) { return createErrorNode(ProductLayout.Block, blockName, strBlock, error); } } return null; } // // Inliner Parsing // async parseInliners(text, options) { var _a, _b; if (typeof text !== "string") return []; [text, options] = resolveParseArgs(text, options); let rangeFactories = {}; let ranges = []; for (const [inlinerName, InlinerFactory] of this.inlinerFactories) { const factory = prepareFactory(InlinerFactory, this, null, options); const newRanges = factory.outlineRanges(text); for (const newRange of newRanges) { let rangeIndex = 0; let removeIndexes = []; let approved = true; for (const toCompareWithRange of ranges) { switch (getIntersection(newRange, toCompareWithRange)) { case RangeIntersection.Partial: case RangeIntersection.Inside: approved = false; break; case RangeIntersection.Contain: removeIndexes.push(rangeIndex); break; } if (!approved) { removeIndexes = []; break; } rangeIndex += 1; } if (approved) { removeIndexes.forEach((index) => { delete rangeFactories[index]; ranges = ranges.toSpliced(index, 1); }); rangeFactories[ranges.push(newRange) - 1] = { name: inlinerName, factory }; } } } const inliners = []; const pushTextNode = async (text2) => { const textNode = new TextNode(); textNode.parseData = text2; textNode.generated.autoId = createAutoId(options.autoId, null, textNode); options.step && await options.step(textNode); inliners.push(textNode); }; let startText = text.slice(0, ((_a = ranges[0]) == null ? void 0 : _a.start) ?? text.length); if (startText) await pushTextNode(startText); for (let i = 0; i < ranges.length; i++) { const inlinerName = rangeFactories[i].name; const inliner = new this.coreConfig.products[inlinerName].Node(); inliner.name = inlinerName; const factory = rangeFactories[i].factory; factory.productNode = inliner; const range = ranges[i]; let afterText = text.slice(range.end, ((_b = ranges[i + 1]) == null ? void 0 : _b.start) ?? text.length); afterText = afterText.replace(/^{(.+)}/, (match, lineMeta) => { inliner.meta = parseMeta(lineMeta); return ""; }); const parseText = text.slice(range.start, range.end); try { inliner.parseData = await factory.createParseData(parseText); inliner.generated.autoId = createAutoId(options.autoId, factory, inliner); options.step && await options.step(inliner); inliners.push(inliner); } catch (error) { inliners.push(createErrorNode(ProductLayout.Inliner, inlinerName, parseText, error)); } if (afterText) await pushTextNode(afterText); } return inliners; } } function resolveParseArgs(text, options) { if (options == null ? void 0 : options._resolved) return [text, options]; text = normalizeText(text); options || (options = {}); options.autoId || (options.autoId = new DefaultAutoId()); options._resolved = true; return [ text, options ]; } function prepareFactory(Factory, parser, productNode, options) { const factory = new Factory(); factory.parser = parser; factory.parseOptions = options; factory.productNode = productNode; return factory; } function createAutoId(autoId, factory, productNode) { let id = autoId.generate(productNode); if (factory) id = factory.alterAutoId(id); id = autoId.finalize(id); autoId.push(id); return id; } function createErrorNode(layout, name, src, error) { const errorNode = new ErrorNode(); errorNode.layout = layout; errorNode.name = name; errorNode.src = src; errorNode.error = error; return errorNode; } class Stringifier { constructor(coreConfig) { __publicField(this, "factories", {}); for (const [productName, ProductCore] of Object.entries(coreConfig.products)) { const Factory = ProductCore.Stringifier; this.factories[productName] = Factory; } } stringify(node, options = {}) { const withStep = (strNode2) => { options.step && options.step(node, strNode2); return strNode2; }; if (node instanceof ErrorNode) return withStep(node.src); if (node instanceof BlocksNode || node instanceof RootNode) return withStep(node.children.map((childNode) => this.stringify(childNode, options)).join("\n\n")); if (node instanceof InlinersNode) return withStep(node.children.map((childNode) => this.stringify(childNode, options)).join("")); const Factory = this.factories[node.name]; if (!Factory) throw new Error(`Can't stringify unknown node type "${node.name}"!`); const factory = new Factory(); factory.stringifier = this; factory.strOptions = options; factory.node = node; const strNode = factory.stringifyNode(node); if (node instanceof BlockNode) { const strMeta = stringifyMeta(node.meta, true); return withStep(strMeta + (strMeta ? "\n" : "") + strNode); } else if (node instanceof InlinerNode) { return withStep(strNode + stringifyMeta(node.meta, false)); } } } export { AutoId as A, DefaultAutoId as D, Parser as P, Stringifier as S }; //# sourceMappingURL=stringify-BUrbArtT.js.map