@inshapardaz/likhari-converters 0.1.45-dev.334 → 0.1.45-dev.335

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,6 +11,8 @@ export interface MergePagesOptions {
11
11
  inputFormat?: FormatId;
12
12
  /** The format of the combined document. */
13
13
  outputFormat: FormatId;
14
+ /** Leave out pages with no content: nothing, whitespace, or only empty paragraphs. Off by default. */
15
+ skipBlankPages?: boolean;
14
16
  /** Passed to every parse and to the final serialize (image URL resolver and the like). */
15
17
  context?: ConverterContext;
16
18
  /** Defaults to the registry with all four built-in formats. */
@@ -23,6 +25,8 @@ export declare function mergePagesToState(pages: PageInput[], options?: Omit<Mer
23
25
  * with a page break between each pair of pages, in the requested output format. Needs no
24
26
  * editor or DOM, so it can run in a server, a worker or a build script.
25
27
  *
28
+ * With `skipBlankPages`, blank pages are left out and no break is added for them.
29
+ *
26
30
  * Footnote ids are only unique within a page, so a page whose footnote ids clash with an
27
31
  * earlier page's gets them renamed (`1` becomes `1-2`), in references and notes alike; the
28
32
  * notes of all pages end up in one list at the end of the document.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/merge/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAyB,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAG3D,kGAAkG;AAClG,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,QAAQ,CAAA;CAAE,CAAC;AAExE,MAAM,WAAW,iBAAiB;IAChC,+EAA+E;IAC/E,WAAW,CAAC,EAAE,QAAQ,CAAC;IACvB,2CAA2C;IAC3C,YAAY,EAAE,QAAQ,CAAC;IACvB,0FAA0F;IAC1F,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,mGAAmG;AACnG,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,OAAO,GAAE,IAAI,CAAC,iBAAiB,EAAE,cAAc,CAAM,GAAG,qBAAqB,CA4BlI;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAGjF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/merge/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAyB,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAG3D,kGAAkG;AAClG,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,QAAQ,CAAA;CAAE,CAAC;AAExE,MAAM,WAAW,iBAAiB;IAChC,+EAA+E;IAC/E,WAAW,CAAC,EAAE,QAAQ,CAAC;IACvB,2CAA2C;IAC3C,YAAY,EAAE,QAAQ,CAAC;IACvB,sGAAsG;IACtG,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,0FAA0F;IAC1F,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,mGAAmG;AACnG,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,OAAO,GAAE,IAAI,CAAC,iBAAiB,EAAE,cAAc,CAAM,GAAG,qBAAqB,CAgClI;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAGjF"}
@@ -2,10 +2,11 @@ import { defaultFormatRegistry } from '../registry.js';
2
2
  import { elementBase, makeState, rootChildren } from '../shared/serialized.js';
3
3
  /** Parses each page and returns the combined document as Lexical state, without serializing it. */
4
4
  export function mergePagesToState(pages, options = {}) {
5
- const { inputFormat = 'markdown', context, registry = defaultFormatRegistry } = options;
5
+ const { inputFormat = 'markdown', skipBlankPages = false, context, registry = defaultFormatRegistry } = options;
6
6
  const body = [];
7
7
  const footnotes = [];
8
8
  const takenFootnoteIds = new Set();
9
+ let kept = 0;
9
10
  pages.forEach((page, index) => {
10
11
  const { content, format = inputFormat } = typeof page === 'string' ? { content: page } : page;
11
12
  let blocks;
@@ -16,14 +17,17 @@ export function mergePagesToState(pages, options = {}) {
16
17
  const reason = error instanceof Error ? error.message : String(error);
17
18
  throw new Error(`mergePages: page ${index + 1} is not valid ${format}: ${reason}`);
18
19
  }
20
+ if (skipBlankPages && blocks.every(isBlank))
21
+ return;
19
22
  // Each page brings its own footnote list; they are combined into one at the end.
20
23
  const pageLists = blocks.filter((block) => block.type === 'footnote-list');
21
24
  const pageBody = blocks.filter((block) => block.type !== 'footnote-list');
22
25
  uniquifyFootnoteIds([...pageBody, ...pageLists], takenFootnoteIds);
23
26
  for (const list of pageLists)
24
27
  footnotes.push(...(list.children ?? []));
25
- if (index > 0)
28
+ if (kept > 0)
26
29
  body.push({ type: 'page-break', version: 1 });
30
+ kept += 1;
27
31
  body.push(...pageBody);
28
32
  });
29
33
  return makeState(footnotes.length > 0 ? [...body, elementBase('footnote-list', footnotes)] : body);
@@ -33,6 +37,8 @@ export function mergePagesToState(pages, options = {}) {
33
37
  * with a page break between each pair of pages, in the requested output format. Needs no
34
38
  * editor or DOM, so it can run in a server, a worker or a build script.
35
39
  *
40
+ * With `skipBlankPages`, blank pages are left out and no break is added for them.
41
+ *
36
42
  * Footnote ids are only unique within a page, so a page whose footnote ids clash with an
37
43
  * earlier page's gets them renamed (`1` becomes `1-2`), in references and notes alike; the
38
44
  * notes of all pages end up in one list at the end of the document.
@@ -41,6 +47,12 @@ export function mergePages(pages, options) {
41
47
  const registry = options.registry ?? defaultFormatRegistry;
42
48
  return registry.serialize(options.outputFormat, mergePagesToState(pages, options), options.context);
43
49
  }
50
+ /** A block with nothing in it: a paragraph holding only whitespace and line breaks. Anything else (an image, a rule, a table, a break) is content. */
51
+ function isBlank(block) {
52
+ if (block.type !== 'paragraph')
53
+ return false;
54
+ return (block.children ?? []).every((child) => (child.type === 'text' ? String(child.text ?? '').trim() === '' : child.type === 'linebreak'));
55
+ }
44
56
  /** Renames this page's footnote ids that an earlier page already uses, then claims all its ids. */
45
57
  function uniquifyFootnoteIds(blocks, taken) {
46
58
  const nodes = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inshapardaz/likhari-converters",
3
- "version": "0.1.45-dev.334",
3
+ "version": "0.1.45-dev.335",
4
4
  "description": "Format transformers (Markdown/HTML/plain-text/Lexical JSON) against the canonical Lexical EditorState, isolated from UI.",
5
5
  "license": "MIT",
6
6
  "repository": {