@portone/docx-editor 0.6.1 → 0.6.2

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @portone/docx-editor
2
2
 
3
+ ## 0.6.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#143](https://github.com/portone-io/docx-editor/pull/143) [`2238131`](https://github.com/portone-io/docx-editor/commit/2238131792ecab86ad544545bc28eae24841cbca) Thanks [@Deea222](https://github.com/Deea222)! - Say which content blocks an export, and where it stands.
8
+
9
+ Every entry `exportProblems`, `documentExportProblems` and a `blocked` `downloadDocx` report now carries a `reason`: a discriminated union naming the situation met and the content it is about, such as `unwritten-story-change` with the story and what was done to it, or `missing-content-types` with the part. It tells apart the situations one code covers, so a host can write the sentence its own user reads instead of matching an English message. The codes and messages are unchanged, so a `switch` over `code` keeps working.
10
+
11
+ A problem about a footnote or an endnote now carries `pos` as well, the first reference to that note in the body, since the note's own text stands nowhere there. A note nothing refers to still has no position.
12
+
13
+ `DocxExportError` carries the entry it was raised for as `problem`, so a `catch` reads the same `reason` and `pos` without asking again. A refusal met while writing that the invariants did not predict leaves it absent.
14
+
15
+ The checks are now asked of every side story an edit reached - a footnote, an endnote, a header, a footer, a comment body - as well as of the body, so an unmatched bookmark, a vertical merge past its table, a placeholder that lost its XML or a paragraph in an undefined list is refused wherever it stands instead of going into the file unchecked. Each such reason carries a `story` saying where, `null` for the body. A story nobody touched goes out as it arrived and is not asked about.
16
+
17
+ Since 0.6.1, `exportBytes` and `exportDocx` refuse a document holding a change nothing writes back - a header or footer story added or removed, an edited footnote or endnote separator - instead of saving the file without it. Check `exportProblems` before writing, or catch `DocxExportError`.
18
+
3
19
  ## 0.6.1
4
20
 
5
21
  ### Patch Changes
package/dist/core.d.ts CHANGED
@@ -19,9 +19,10 @@ export type { ParagraphStyleOption } from "./docx/formatting";
19
19
  export type { DocxBytes, ImportOptions } from "./docx/importDocx";
20
20
  /**
21
21
  * What the writer would refuse the document over, asked ahead of the write. The first entry is
22
- * what `exportDocx` throws, so the two cannot disagree.
22
+ * what `exportDocx` throws, so the two cannot disagree. `reason` tells the situations one code
23
+ * covers apart and names the content each is about.
23
24
  */
24
- export type { ExportProblem } from "./docx/invariants";
25
+ export type { ExportPartName, ExportProblem, ExportProblemReason, ExportProblemStory, ExportStoryKind, } from "./docx/invariants";
25
26
  export { exportProblems } from "./docx/invariants";
26
27
  export type { DocxSession } from "./docx/session";
27
28
  export { documentNumbering, documentPartPath } from "./docx/session";
@@ -29,7 +30,7 @@ export type { CellFormat, CellVerticalAlign, DocumentDefaults, HighlightName, Li
29
30
  export { toCellFormat, toParagraphFormat, toRowFormat, toRunFormat, toTableFormat, toTableWidth, } from "./model/format";
30
31
  export type { LevelAlign, LevelIndent, LevelSuffix, NewList, NewListLevel, NumberFormat, Numbering, NumberingLevel, NumberingList, NumberingOptions, NumberingStyleLinks, ReadLevelRun, } from "./numbering/parseNumbering";
31
32
  export { parseNumbering } from "./numbering/parseNumbering";
32
- export type { DocxExportErrorCode, DocxImportErrorCode, } from "./ooxml/errors";
33
+ export type { DocxExportErrorCode, DocxExportErrorOptions, DocxImportErrorCode, } from "./ooxml/errors";
33
34
  export { DocxExportError, DocxImportError } from "./ooxml/errors";
34
35
  /**
35
36
  * An image node's size is written in EMU, the unit the document itself uses. A builder
@@ -36,7 +36,7 @@ export declare function exportDocx(doc: PMNode, session: DocxSession, options?:
36
36
  *
37
37
  * The first problem `exportProblems` reports is thrown before anything is written, so a refusal a
38
38
  * caller could have asked about ahead of time arrives with the same code and message it would
39
- * have read there.
39
+ * have read there, and carries that entry as the error's `problem`.
40
40
  */
41
41
  export declare function exportDocxReport(doc: PMNode, session: DocxSession, options?: ExportOptions): {
42
42
  bytes: Uint8Array;
@@ -116,7 +116,9 @@ function reportThrough(planners, doc, session, options) {
116
116
  return withXmlParser(options?.xmlParser, () => {
117
117
  const store = sessionOf(session);
118
118
  const problem = problemsOf(doc, store)[0];
119
- if (problem) throw new DocxExportError(problem.code, problem.message);
119
+ if (problem) {
120
+ throw new DocxExportError(problem.code, problem.message, { problem });
121
+ }
120
122
  const approximated = [];
121
123
  const bytes = writeDocx(
122
124
  doc,
@@ -61,6 +61,8 @@ export declare const IDENTITY_RULES: readonly IdentityRule[];
61
61
  export interface IdentityProblem {
62
62
  readonly code: DocxExportErrorCode;
63
63
  readonly message: string;
64
+ /** The node type standing twice, which `docx/invariants` names in the problem's reason */
65
+ readonly node: string;
64
66
  readonly pos: number;
65
67
  }
66
68
  /** The document with every later claimant of a name released, in document order */
@@ -103,6 +103,7 @@ function refusalOf(block, pos) {
103
103
  return {
104
104
  code: "unsupported-content",
105
105
  message: `a preserved block stands in two places (${block.type.name})`,
106
+ node: block.type.name,
106
107
  pos
107
108
  };
108
109
  }
@@ -5,27 +5,30 @@
5
5
  * would throw, so a screen can ask at edit time what `exportDocx` would say. The list is walked in
6
6
  * order and `exportDocx` throws its first entry, which is what keeps the two from disagreeing.
7
7
  *
8
+ * A code covers several situations, so each entry also carries the `ExportProblemReason`
9
+ * (`ooxml/errors`) naming the one that was met and the content it is about. Every place a problem
10
+ * is built names its own, rather than a reader telling them apart by the message.
11
+ *
12
+ * What the writer puts out block by block is the body and every side story a part writer rewrites
13
+ * (`exportScopes`), so the invariants over content are asked of each of those in turn: markup
14
+ * refused in the body is refused just the same out of a footnote or a header.
15
+ *
8
16
  * The checks inspect model attrs and preserved XML without running the writers. Bookmark
9
17
  * fragments and list definitions use the export parser. `assertBookmarkPairs` in `./exportDocx`
10
18
  * and `assertPartsParse` in `./partPlan` remain the final checks over the parts as actually written.
11
19
  */
12
20
  import type { Node as PMNode } from "prosemirror-model";
13
- import type { DocxExportErrorCode } from "../ooxml/errors";
21
+ import type { ExportProblem } from "../ooxml/errors";
14
22
  import type { ExportOptions } from "./exportDocx";
15
23
  import { type DocxSession, type SessionStore } from "./session";
16
- /** One reason the document cannot be written back, with the code `exportDocx` would throw it under */
17
- export interface ExportProblem {
18
- readonly code: DocxExportErrorCode;
19
- readonly message: string;
20
- /** Where the problem stands in the document. Absent for a problem of the package, of the session, or of a side story */
21
- readonly pos?: number;
22
- }
24
+ export type { ExportPartName, ExportProblem, ExportProblemReason, ExportProblemStory, ExportStoryKind, } from "../ooxml/errors";
23
25
  /** The problems as the writer sees them, for a caller already inside the writer's parser scope */
24
26
  export declare function problemsOf(doc: PMNode, session: SessionStore): readonly ExportProblem[];
25
27
  /**
26
28
  * Known reasons writing this document back would be refused, in the order `exportDocx` would
27
- * raise them. An empty list does not rule out failures while writing. Each entry carries the code and message the
28
- * `DocxExportError` would carry, and the position in the document where there is one.
29
+ * raise them. An empty list does not rule out failures while writing. Each entry carries the code
30
+ * and message the `DocxExportError` would carry, the `reason` naming what the refusal is about,
31
+ * and the position in the document where there is one.
29
32
  *
30
33
  * The list definitions are read to tell a new list from one the document already had, so this
31
34
  * needs an XML parser the way `exportDocx` does and takes the same option.