UNPKG

@bookbox/core

Version:

Bookbox — e-book format

239 lines (238 loc) 7.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getSchemaFromLinkedList = exports.getLinkedLeafList = exports.getBookLinkedSchema = exports.getBookLinkedItem = exports.getPageLinkedItem = exports.getTextLinkedItem = exports.getElementView = void 0; const utils_1 = require("../utils"); const elements_1 = require("./elements"); const onlyBlocks = new Set(["image"]); function getElementView(item) { if (typeof item === "string") { return "inline"; } const { props: userProps, name } = item; const props = Object.assign({ block: elements_1.defaultBlockNames.has(name) }, userProps); if (props.inline) { return "inline"; } if (props.block) { return "block"; } return props.position === "inline" ? "inline" : "block"; } exports.getElementView = getElementView; const getTextLinkedItem = (text) => ({ bookElementSchema: { name: "text", props: {}, children: [], }, raw: text, previous: null, next: null, previousLeaf: null, nextLeaf: null, parent: null, firstChild: null, lastChild: null, view: "inline", }); exports.getTextLinkedItem = getTextLinkedItem; const getPageLinkedItem = (count) => { const text = `${count}`; const textItem = (0, exports.getTextLinkedItem)(text); return { bookElementSchema: { name: "page", props: { count, key: `page-${count}` }, children: [], }, raw: text, previous: null, next: null, previousLeaf: null, nextLeaf: null, parent: null, firstChild: textItem, lastChild: textItem, view: "inline", }; }; exports.getPageLinkedItem = getPageLinkedItem; function bindList(items) { for (let i = 1; i < items.length; i++) { const prev = items[i - 1]; const current = items[i]; current.previous = prev; prev.next = current; } } function bindLeafList(items) { for (let i = 1; i < items.length; i++) { const prev = items[i - 1]; const current = items[i]; current.previousLeaf = prev; prev.nextLeaf = current; } } function bindParent(items, parent) { var _a, _b; for (const childItem of items) { childItem.parent = parent; } parent.firstChild = (_a = items[0]) !== null && _a !== void 0 ? _a : null; parent.lastChild = (_b = items[items.length - 1]) !== null && _b !== void 0 ? _b : null; } const isNotEmpty = (text) => text !== ""; function getBookLinkedItem(item) { if (typeof item === "string") { const textItem = (0, exports.getTextLinkedItem)(item); const children = (0, utils_1.getTextTokens)(item) .filter(isNotEmpty) .map(exports.getTextLinkedItem); bindList(children); bindParent(children, textItem); return textItem; } const linkedItem = { bookElementSchema: item, firstChild: null, lastChild: null, raw: null, previous: null, next: null, previousLeaf: null, nextLeaf: null, parent: null, view: getElementView(item), }; const children = getBookLinkedSchema(item.children).tree; bindList(children); bindParent(children, linkedItem); return linkedItem; } exports.getBookLinkedItem = getBookLinkedItem; function getLinkedItemList(start, end) { if (!start) { return []; } const result = []; let current = start; while (current && current !== end) { result.push(current); current = current.next; } if (end) { result.push(end); } return result; } function getLeafListLinkedItem(linkedItems) { const list = []; for (const item of linkedItems) { if (item.firstChild === null) { list.push(item); } else { list.push(...getLeafListLinkedItem(getLinkedItemList(item.firstChild, item.lastChild))); } } return list; } function getBookLinkedSchema(schema, root) { const linkedSchema = { start: null, end: null, tree: schema.filter(isNotEmpty).map(getBookLinkedItem), }; bindList(linkedSchema.tree); if (schema.length === 0 || !root) { return linkedSchema; } const leafList = getLeafListLinkedItem(linkedSchema.tree); bindLeafList(leafList); putPages(leafList); linkedSchema.start = leafList[0]; linkedSchema.end = leafList[leafList.length - 1]; linkedSchema.tree = getLinkedItemList(linkedSchema.tree[0], null); return linkedSchema; } exports.getBookLinkedSchema = getBookLinkedSchema; function getLinkedLeafList(linkedSchema) { const list = []; let current = linkedSchema.start; while (current !== null) { list.push(current); current = current.nextLeaf; } return list; } exports.getLinkedLeafList = getLinkedLeafList; function getSchemaFromLinkedList(linkedList) { const schema = []; for (const item of linkedList) { const { bookElementSchema, raw, firstChild, lastChild } = item; const { name, props } = bookElementSchema; if (name === "text" && raw && firstChild === null) { schema.push(raw); } else if (name === "text") { schema.push(...getSchemaFromLinkedList(getLinkedItemList(firstChild, lastChild))); } else { schema.push({ name: name, props: props, children: getSchemaFromLinkedList(getLinkedItemList(firstChild, lastChild)), }); } } return schema; } exports.getSchemaFromLinkedList = getSchemaFromLinkedList; function putAfterItem(sourceItem, targetItem) { const { next, nextLeaf, parent } = sourceItem; targetItem.next = next; if (next) { next.previous = targetItem; } targetItem.nextLeaf = nextLeaf; if (nextLeaf) { nextLeaf.previousLeaf = targetItem; } sourceItem.next = targetItem; targetItem.previous = sourceItem; sourceItem.nextLeaf = targetItem; targetItem.previousLeaf = sourceItem; targetItem.parent = parent; if (parent && parent.lastChild === sourceItem) { parent.lastChild = targetItem; } } const PAGE_SIZE = 500; const NEW_LINE_SIZE = 10; const NEW_LINE_LONG_SIZE = 50; function putPages(items) { var _a; if (items.length === 0) { return; } let pageCount = 0; let currentBlockCount = PAGE_SIZE; for (const item of items) { const { raw, view } = item; const isBlock = view === "block"; let increment = 0; if (!isBlock && raw) { const newLines = (_a = raw.match(/\n\n*/g)) !== null && _a !== void 0 ? _a : []; const newLineCount = newLines.reduce((s, e) => s + e.length, 0); const newLineSize = newLines.reduce((s, e) => s + (e.length > 1 ? NEW_LINE_LONG_SIZE : NEW_LINE_SIZE), 0); const rawSize = raw.length - newLineCount; increment = rawSize + newLineSize; } currentBlockCount += increment; if (isBlock || currentBlockCount >= PAGE_SIZE) { currentBlockCount = 0; const pageItem = (0, exports.getPageLinkedItem)(pageCount++); putAfterItem(item, pageItem); } } }