From 237c0f22cbd26ac737187b8a195bc08665dcc450 Mon Sep 17 00:00:00 2001 From: Hufe921 Date: Sun, 7 May 2023 19:45:30 +0800 Subject: [PATCH] feat: get catalog api --- src/editor/core/command/Command.ts | 7 ++ src/editor/core/command/CommandAdapt.ts | 5 ++ src/editor/core/worker/WorkerManager.ts | 20 +++++ src/editor/core/worker/works/catalog.ts | 104 ++++++++++++++++++++++++ src/editor/interface/Catalog.ts | 10 +++ 5 files changed, 146 insertions(+) create mode 100644 src/editor/core/worker/works/catalog.ts create mode 100644 src/editor/interface/Catalog.ts diff --git a/src/editor/core/command/Command.ts b/src/editor/core/command/Command.ts index 31f38af..a092408 100644 --- a/src/editor/core/command/Command.ts +++ b/src/editor/core/command/Command.ts @@ -1,6 +1,7 @@ import { IElement, ImageDisplay, INavigateInfo, ListStyle, ListType, TableBorder, TitleLevel, VerticalAlign } from '../..' import { EditorMode, PageMode, PaperDirection } from '../../dataset/enum/Editor' import { RowFlex } from '../../dataset/enum/Row' +import { ICatalog } from '../../interface/Catalog' import { IDrawImagePayload, IPainterOptions } from '../../interface/Draw' import { IEditorResult } from '../../interface/Editor' import { IMargin } from '../../interface/Margin' @@ -85,6 +86,7 @@ export class Command { private static insertElementList: CommandAdapt['insertElementList'] private static removeControl: CommandAdapt['removeControl'] private static setLocale: CommandAdapt['setLocale'] + private static getCatalog: CommandAdapt['getCatalog'] constructor(adapt: CommandAdapt) { Command.mode = adapt.mode.bind(adapt) @@ -163,6 +165,7 @@ export class Command { Command.insertElementList = adapt.insertElementList.bind(adapt) Command.removeControl = adapt.removeControl.bind(adapt) Command.setLocale = adapt.setLocale.bind(adapt) + Command.getCatalog = adapt.getCatalog.bind(adapt) } // 全局命令 @@ -476,4 +479,8 @@ export class Command { return Command.setLocale(payload) } + public getCatalog(): Promise { + return Command.getCatalog() + } + } \ No newline at end of file diff --git a/src/editor/core/command/CommandAdapt.ts b/src/editor/core/command/CommandAdapt.ts index 2ffe1ef..0c0d139 100644 --- a/src/editor/core/command/CommandAdapt.ts +++ b/src/editor/core/command/CommandAdapt.ts @@ -11,6 +11,7 @@ import { RowFlex } from '../../dataset/enum/Row' import { TableBorder } from '../../dataset/enum/table/Table' import { TitleLevel } from '../../dataset/enum/Title' import { VerticalAlign } from '../../dataset/enum/VerticalAlign' +import { ICatalog } from '../../interface/Catalog' import { IDrawImagePayload, IPainterOptions } from '../../interface/Draw' import { IEditorOption, IEditorResult } from '../../interface/Editor' import { IElement, IElementStyle } from '../../interface/Element' @@ -1655,4 +1656,8 @@ export class CommandAdapt { this.i18n.setLocale(payload) } + public getCatalog(): Promise { + return this.workerManager.getCatalog() + } + } \ No newline at end of file diff --git a/src/editor/core/worker/WorkerManager.ts b/src/editor/core/worker/WorkerManager.ts index 6bba1e7..32ca255 100644 --- a/src/editor/core/worker/WorkerManager.ts +++ b/src/editor/core/worker/WorkerManager.ts @@ -1,14 +1,19 @@ import { Draw } from '../draw/Draw' import WordCountWorker from './works/wordCount?worker&inline' +import CatalogWorker from './works/catalog?worker&inline' +import { ICatalog } from '../../interface/Catalog' + export class WorkerManager { private draw: Draw private wordCountWorker: Worker + private catalogWorker: Worker constructor(draw: Draw) { this.draw = draw this.wordCountWorker = new WordCountWorker() + this.catalogWorker = new CatalogWorker() } public getWordCount(): Promise { @@ -26,4 +31,19 @@ export class WorkerManager { }) } + public getCatalog(): Promise { + return new Promise((resolve, reject) => { + this.catalogWorker.onmessage = (evt) => { + resolve(evt.data) + } + + this.catalogWorker.onerror = (evt) => { + reject(evt) + } + + const elementList = this.draw.getOriginalMainElementList() + this.catalogWorker.postMessage(elementList) + }) + } + } \ No newline at end of file diff --git a/src/editor/core/worker/works/catalog.ts b/src/editor/core/worker/works/catalog.ts new file mode 100644 index 0000000..c300c06 --- /dev/null +++ b/src/editor/core/worker/works/catalog.ts @@ -0,0 +1,104 @@ +import { ICatalog, ICatalogItem } from '../../../interface/Catalog' +import { IElement } from '../../../interface/Element' + +enum ElementType { + TITLE = 'title' +} + +enum TitleLevel { + FIRST = 'first', + SECOND = 'second', + THIRD = 'third', + FOURTH = 'fourth', + FIFTH = 'fifth', + SIXTH = 'sixth' +} + +const titleOrderNumberMapping: Record = { + [TitleLevel.FIRST]: 1, + [TitleLevel.SECOND]: 2, + [TitleLevel.THIRD]: 3, + [TitleLevel.FOURTH]: 4, + [TitleLevel.FIFTH]: 5, + [TitleLevel.SIXTH]: 6 +} + +const ZERO = '\u200B' + +function getCatalog(elementList: IElement[]): ICatalog | null { + // 筛选标题 + const titleElementList: IElement[] = [] + let t = 0 + while (t < elementList.length) { + const element = elementList[t] + if (element.titleId) { + const titleId = element.titleId + const level = element.level + const titleElement: IElement = { + type: ElementType.TITLE, + value: '', + level, + titleId + } + const valueList: IElement[] = [] + while (t < elementList.length) { + const titleE = elementList[t] + if (titleId !== titleE.titleId) { + t-- + break + } + valueList.push(titleE) + t++ + } + titleElement.value = valueList.map(s => s.value) + .join('') + .replace(new RegExp(ZERO, 'g'), '') + titleElementList.push(titleElement) + } + t++ + } + if (!titleElementList.length) return null + // 查找到比最新元素大的标题时终止 + const recursiveInsert = (title: IElement, catalogItem: ICatalogItem) => { + const subCatalogItem = catalogItem.subCatalog[catalogItem.subCatalog.length - 1] + const catalogItemLevel = titleOrderNumberMapping[subCatalogItem?.level] + const titleLevel = titleOrderNumberMapping[title.level!] + if (subCatalogItem && titleLevel > catalogItemLevel) { + recursiveInsert(title, subCatalogItem) + } else { + catalogItem.subCatalog.push({ + id: title.titleId!, + name: title.value, + level: title.level!, + subCatalog: [] + }) + } + } + // 循环标题组 + // 如果当前列表级别小于标题组最新标题级别:则递归查找最小级别并追加 + // 如果大于:则直接追加至当前标题组 + const catalog: ICatalog = [] + for (let e = 0; e < titleElementList.length; e++) { + const title = titleElementList[e] + const catalogItem = catalog[catalog.length - 1] + const catalogItemLevel = titleOrderNumberMapping[catalogItem?.level] + const titleLevel = titleOrderNumberMapping[title.level!] + if (catalogItem && titleLevel > catalogItemLevel) { + recursiveInsert(title, catalogItem) + } else { + catalog.push({ + id: title.titleId!, + name: title.value, + level: title.level!, + subCatalog: [] + }) + } + } + return catalog +} + +onmessage = (evt) => { + const elementList = evt.data + const catalog = getCatalog(elementList) + postMessage(catalog) +} diff --git a/src/editor/interface/Catalog.ts b/src/editor/interface/Catalog.ts new file mode 100644 index 0000000..c9bf6c1 --- /dev/null +++ b/src/editor/interface/Catalog.ts @@ -0,0 +1,10 @@ +import { TitleLevel } from '../dataset/enum/Title' + +export interface ICatalogItem { + id: string; + name: string; + level: TitleLevel; + subCatalog: ICatalogItem[]; +} + +export type ICatalog = ICatalogItem[] \ No newline at end of file