kviewer 0.2.2 → 0.2.3

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/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kviewer",
3
3
  "configKey": "kviewer",
4
- "version": "0.2.2",
4
+ "version": "0.2.3",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
@@ -2,7 +2,7 @@ import Konva from 'konva';
2
2
  import type { KonvaEventObject } from 'konva/lib/Node';
3
3
  import type { AnnotationType, IAnnotationContentsObj, IAnnotationStore, IAnnotationStyle, IAnnotationType } from '../types.js';
4
4
  export interface IEditorOptions {
5
- userName: string;
5
+ userName?: string;
6
6
  konvaStage: Konva.Stage;
7
7
  pageNumber: number;
8
8
  annotation: IAnnotationType | null;
@@ -21,7 +21,7 @@ export interface IShapeGroup {
21
21
  annotation?: IAnnotationType;
22
22
  }
23
23
  export declare abstract class Editor {
24
- protected userName: string;
24
+ protected userName?: string;
25
25
  readonly id: string;
26
26
  readonly onAdd: (annotationStore: IAnnotationStore) => void;
27
27
  readonly onChange: (id: string, updates: Partial<IAnnotationStore>) => void;
@@ -21,7 +21,7 @@ function normalizeComment(comment, fallbackTitle) {
21
21
  if (!isString(content)) return null;
22
22
  return {
23
23
  id: isString(comment.id) && comment.id.length > 0 ? comment.id : generateUUID(),
24
- title: isString(comment.title) && comment.title.length > 0 ? comment.title : fallbackTitle,
24
+ title: isString(comment.title) && comment.title.length > 0 ? comment.title : fallbackTitle || void 0,
25
25
  date: isString(comment.date) && comment.date.length > 0 ? comment.date : formatTimestamp(Date.now()),
26
26
  content,
27
27
  status: isString(comment.status) ? comment.status : void 0
@@ -66,7 +66,7 @@ function normalizeAnnotation(raw, fallbackTitle) {
66
66
  pageNumber,
67
67
  konvaString,
68
68
  konvaClientRect: { x, y, width, height },
69
- title: isString(raw.title) && raw.title.length > 0 ? raw.title : fallbackTitle,
69
+ title: isString(raw.title) && raw.title.length > 0 ? raw.title : fallbackTitle || void 0,
70
70
  type,
71
71
  subtype,
72
72
  pdfjsType,
@@ -81,7 +81,7 @@ function normalizeAnnotation(raw, fallbackTitle) {
81
81
  };
82
82
  return normalized;
83
83
  }
84
- export function normalizeImportedAnnotations(input, fallbackTitle = "User") {
84
+ export function normalizeImportedAnnotations(input, fallbackTitle) {
85
85
  if (!Array.isArray(input)) {
86
86
  return { annotations: [], skipped: 0 };
87
87
  }
@@ -29,7 +29,7 @@ export interface PainterCallbacks {
29
29
  getFormFieldPreviewColor?: () => string | undefined;
30
30
  }
31
31
  export declare class Painter {
32
- private userName;
32
+ private userName?;
33
33
  private konvaCanvasStore;
34
34
  private editorStore;
35
35
  private currentAnnotation;
@@ -45,7 +45,7 @@ export declare class Painter {
45
45
  private getReadonly?;
46
46
  private freehandGroupingDelay;
47
47
  constructor({ userName, callbacks, getStylusModeEnabled, getReadonly, freehandGroupingDelay, setExternalGesturesEnabled, }: {
48
- userName: string;
48
+ userName?: string;
49
49
  callbacks: PainterCallbacks;
50
50
  getStylusModeEnabled?: () => boolean;
51
51
  getReadonly?: () => boolean;
@@ -84,7 +84,8 @@ export interface IAnnotationStyle {
84
84
  }
85
85
  export interface IAnnotationComment {
86
86
  id: string;
87
- title: string;
87
+ /** Author name. Undefined when the host app didn't supply a `userName`. */
88
+ title?: string;
88
89
  date: string;
89
90
  content: string;
90
91
  status?: CommentStatus;
@@ -124,7 +125,8 @@ export interface IAnnotationStore {
124
125
  pageNumber: number;
125
126
  konvaString: string;
126
127
  konvaClientRect: IRect;
127
- title: string;
128
+ /** Author name. Undefined when the host app didn't supply a `userName`. */
129
+ title?: string;
128
130
  type: AnnotationType;
129
131
  color?: string | null;
130
132
  subtype: PdfjsAnnotationSubtype;
@@ -125,13 +125,13 @@ function removeOwnedAnnotations(pdfDoc, ownedIds, deletedIds) {
125
125
  page.node.set(annotsKey, context.obj(kept));
126
126
  }
127
127
  }
128
- async function parseAnnotationToPdf(annotation, page, pdfDoc) {
128
+ async function parseAnnotationToPdf(annotation, page, pdfDoc, isModifiedOriginal) {
129
129
  const ParserClass = parserMap[annotation.pdfjsType];
130
130
  if (!ParserClass) {
131
131
  console.warn(`Unsupported annotation type for PDF export: ${annotation.pdfjsType}`);
132
132
  return;
133
133
  }
134
- const parser = new ParserClass(pdfDoc, page, annotation);
134
+ const parser = new ParserClass(pdfDoc, page, annotation, isModifiedOriginal);
135
135
  await parser.parse();
136
136
  }
137
137
  async function embedDataUrlImage(pdfDoc, dataUrl) {
@@ -297,7 +297,8 @@ export async function exportAnnotationsToPdf({
297
297
  console.warn(`Skipping annotation ${annotation.id}; page ${annotation.pageNumber} missing`);
298
298
  continue;
299
299
  }
300
- await parseAnnotationToPdf(annotation, page, pdfDoc);
300
+ const isModifiedOriginal = originalAnnotationIds?.has(annotation.id) ?? false;
301
+ await parseAnnotationToPdf(annotation, page, pdfDoc, isModifiedOriginal);
301
302
  }
302
303
  }
303
304
  return savePdf(pdfDoc);
@@ -4,7 +4,28 @@ export declare abstract class AnnotationParser {
4
4
  protected annotation: IAnnotationStore;
5
5
  protected page: PDFPage;
6
6
  protected pdfDoc: PDFDocument;
7
- constructor(pdfDoc: PDFDocument, page: PDFPage, annotation: IAnnotationStore);
7
+ /**
8
+ * Whether this annotation already existed in the source PDF and is being
9
+ * rewritten because the user edited it. Drives the date key, mirroring
10
+ * pdf.js: `CreationDate` for newly authored annotations, `M` (modification
11
+ * date) for edits to pre-existing ones.
12
+ */
13
+ protected isModifiedOriginal: boolean;
14
+ constructor(pdfDoc: PDFDocument, page: PDFPage, annotation: IAnnotationStore, isModifiedOriginal?: boolean);
15
+ /**
16
+ * Owner (`/T`) and date entries shared by every markup annotation and its
17
+ * reply comments. We align with pdf.js / Firefox here:
18
+ *
19
+ * - `/T` (author) is written ONLY when a real author name is present. When
20
+ * the host app doesn't supply a `userName`, no `/T` is emitted — so
21
+ * archiving systems have no author to burn into the rendered preview.
22
+ * (kviewer previously always wrote `/T`, defaulting to "User".)
23
+ * - The date goes to `/CreationDate` for newly authored annotations and to
24
+ * `/M` when an existing annotation was edited.
25
+ *
26
+ * Spread the result into the annotation's dict literal before `context.obj`.
27
+ */
28
+ protected ownerDateEntries(title: string | undefined, date: string | undefined): Record<string, unknown>;
8
29
  protected addAnnotationToPage(page: PDFPage, annotRef: PDFRef): void;
9
30
  abstract parse(): Promise<void>;
10
31
  }
@@ -1,12 +1,42 @@
1
- import { PDFName } from "pdf-lib";
1
+ import { PDFName, PDFString } from "pdf-lib";
2
+ import { stringToPDFHexString } from "../engine/utils.js";
2
3
  export class AnnotationParser {
3
4
  annotation;
4
5
  page;
5
6
  pdfDoc;
6
- constructor(pdfDoc, page, annotation) {
7
+ /**
8
+ * Whether this annotation already existed in the source PDF and is being
9
+ * rewritten because the user edited it. Drives the date key, mirroring
10
+ * pdf.js: `CreationDate` for newly authored annotations, `M` (modification
11
+ * date) for edits to pre-existing ones.
12
+ */
13
+ isModifiedOriginal;
14
+ constructor(pdfDoc, page, annotation, isModifiedOriginal = false) {
7
15
  this.pdfDoc = pdfDoc;
8
16
  this.page = page;
9
17
  this.annotation = annotation;
18
+ this.isModifiedOriginal = isModifiedOriginal;
19
+ }
20
+ /**
21
+ * Owner (`/T`) and date entries shared by every markup annotation and its
22
+ * reply comments. We align with pdf.js / Firefox here:
23
+ *
24
+ * - `/T` (author) is written ONLY when a real author name is present. When
25
+ * the host app doesn't supply a `userName`, no `/T` is emitted — so
26
+ * archiving systems have no author to burn into the rendered preview.
27
+ * (kviewer previously always wrote `/T`, defaulting to "User".)
28
+ * - The date goes to `/CreationDate` for newly authored annotations and to
29
+ * `/M` when an existing annotation was edited.
30
+ *
31
+ * Spread the result into the annotation's dict literal before `context.obj`.
32
+ */
33
+ ownerDateEntries(title, date) {
34
+ const entries = {};
35
+ if (title) entries.T = stringToPDFHexString(title);
36
+ if (date) {
37
+ entries[this.isModifiedOriginal ? "M" : "CreationDate"] = PDFString.of(date);
38
+ }
39
+ return entries;
10
40
  }
11
41
  addAnnotationToPage(page, annotRef) {
12
42
  const annots = page.node.lookup(PDFName.of("Annots"));
@@ -4,7 +4,6 @@ import { pageTransformFromPdfLibPage } from "../pdf-import/transform.js";
4
4
  import { AnnotationParser } from "./parse.js";
5
5
  import { computeBoundsFromKonvaString } from "./parse_utils.js";
6
6
  import { PRINT_FLAG } from "./annotation-flags.js";
7
- const UNKNOWN_USER = "Unknown user";
8
7
  export class CircleParser extends AnnotationParser {
9
8
  async parse() {
10
9
  const { annotation, page, pdfDoc } = this;
@@ -18,9 +17,8 @@ export class CircleParser extends AnnotationParser {
18
17
  F: PRINT_FLAG,
19
18
  Rect: rect,
20
19
  C: rgbToPdfColor(annotation.color || void 0),
21
- T: stringToPDFHexString(annotation.title || UNKNOWN_USER),
20
+ ...this.ownerDateEntries(annotation.title, annotation.date),
22
21
  Contents: stringToPDFHexString(annotation.contentsObj?.text || ""),
23
- M: PDFString.of(annotation.date || ""),
24
22
  NM: PDFString.of(annotation.id),
25
23
  Border: [0, 0, 1]
26
24
  });
@@ -33,8 +31,7 @@ export class CircleParser extends AnnotationParser {
33
31
  F: PRINT_FLAG,
34
32
  Rect: rect,
35
33
  Contents: stringToPDFHexString(comment.content),
36
- T: stringToPDFHexString(comment.title || UNKNOWN_USER),
37
- M: PDFString.of(comment.date || ""),
34
+ ...this.ownerDateEntries(comment.title, comment.date),
38
35
  C: rgbToPdfColor(annotation.color || void 0),
39
36
  IRT: mainAnnRef,
40
37
  RT: PDFName.of("R"),
@@ -6,7 +6,6 @@ import { formAppearanceMatrix } from "./parse_utils.js";
6
6
  import { encodeWinAnsi, isWinAnsiEncodable } from "./winansi.js";
7
7
  import { getUnicodeFont } from "./unicode-font.js";
8
8
  import { PRINT_FLAG } from "./annotation-flags.js";
9
- const UNKNOWN_USER = "Unknown user";
10
9
  function formatPdfNumber(value) {
11
10
  if (!Number.isFinite(value)) return "0";
12
11
  return Number(value.toFixed(3)).toString();
@@ -134,8 +133,7 @@ export class FreeTextParser extends AnnotationParser {
134
133
  Contents: stringToPDFHexString(text),
135
134
  DA: PDFString.of(da),
136
135
  Q: PDFNumber.of(quadding),
137
- T: stringToPDFHexString(annotation.title || UNKNOWN_USER),
138
- M: PDFString.of(annotation.date || ""),
136
+ ...this.ownerDateEntries(annotation.title, annotation.date),
139
137
  C: context.obj(rgbToPdfColor(annotation.color || void 0)),
140
138
  Border: context.obj([0, 0, 0]),
141
139
  AP: ap
@@ -149,8 +147,7 @@ export class FreeTextParser extends AnnotationParser {
149
147
  F: PRINT_FLAG,
150
148
  Rect: convertKonvaRectToPdfRect(annotation.konvaClientRect, pageTransform),
151
149
  Contents: stringToPDFHexString(comment.content),
152
- T: stringToPDFHexString(comment.title || UNKNOWN_USER),
153
- M: PDFString.of(comment.date || ""),
150
+ ...this.ownerDateEntries(comment.title, comment.date),
154
151
  C: context.obj(rgbToPdfColor(annotation.color || void 0)),
155
152
  IRT: mainAnnRef,
156
153
  RT: PDFName.of("R"),
@@ -7,7 +7,6 @@ import {
7
7
  } from "../pdf-import/transform.js";
8
8
  import { AnnotationParser } from "./parse.js";
9
9
  import { PRINT_FLAG } from "./annotation-flags.js";
10
- const UNKNOWN_USER = "Unknown user";
11
10
  function formatPdfNumber(value) {
12
11
  if (!Number.isFinite(value)) return "0";
13
12
  return Number(value.toFixed(3)).toString();
@@ -120,9 +119,8 @@ export class HighlightParser extends AnnotationParser {
120
119
  Rect: rect,
121
120
  QuadPoints: context.obj(quadPoints),
122
121
  C: context.obj(color),
123
- T: stringToPDFHexString(annotation.title || UNKNOWN_USER),
122
+ ...this.ownerDateEntries(annotation.title, annotation.date),
124
123
  Contents: stringToPDFHexString(annotation.contentsObj?.text || ""),
125
- M: PDFString.of(annotation.date || ""),
126
124
  NM: PDFString.of(annotation.id),
127
125
  CA: PDFNumber.of(0.5),
128
126
  AP: ap
@@ -136,8 +134,7 @@ export class HighlightParser extends AnnotationParser {
136
134
  F: PRINT_FLAG,
137
135
  Rect: convertKonvaRectToPdfRect(annotation.konvaClientRect, pageTransform),
138
136
  Contents: stringToPDFHexString(comment.content),
139
- T: stringToPDFHexString(comment.title || UNKNOWN_USER),
140
- M: PDFString.of(comment.date || ""),
137
+ ...this.ownerDateEntries(comment.title, comment.date),
141
138
  C: rgbToPdfColor(annotation.color || void 0),
142
139
  IRT: mainAnnRef,
143
140
  RT: PDFName.of("R"),
@@ -3,7 +3,6 @@ import { convertKonvaRectToPdfRect, rgbToPdfColor, stringToPDFHexString } from "
3
3
  import { convertCanvasPointToPdf, pageTransformFromPdfLibPage } from "../pdf-import/transform.js";
4
4
  import { AnnotationParser } from "./parse.js";
5
5
  import { PRINT_FLAG } from "./annotation-flags.js";
6
- const UNKNOWN_USER = "Unknown user";
7
6
  function formatPdfNumber(value) {
8
7
  if (!Number.isFinite(value)) return "0";
9
8
  return Number(value.toFixed(3)).toString();
@@ -126,9 +125,8 @@ export class InkParser extends AnnotationParser {
126
125
  Rect: rect,
127
126
  InkList: inkList,
128
127
  C: context.obj([PDFNumber.of(r), PDFNumber.of(g), PDFNumber.of(b)]),
129
- T: stringToPDFHexString(annotation.title || UNKNOWN_USER),
128
+ ...this.ownerDateEntries(annotation.title, annotation.date),
130
129
  Contents: stringToPDFHexString(annotation.contentsObj?.text || ""),
131
- M: PDFString.of(annotation.date || ""),
132
130
  NM: PDFString.of(annotation.id),
133
131
  Border: context.obj([0, 0, 0]),
134
132
  BS: bs,
@@ -144,8 +142,7 @@ export class InkParser extends AnnotationParser {
144
142
  F: PRINT_FLAG,
145
143
  Rect: convertKonvaRectToPdfRect(annotation.konvaClientRect, pageTransform),
146
144
  Contents: stringToPDFHexString(comment.content),
147
- T: stringToPDFHexString(comment.title || UNKNOWN_USER),
148
- M: PDFString.of(comment.date || ""),
145
+ ...this.ownerDateEntries(comment.title, comment.date),
149
146
  C: context.obj([PDFNumber.of(r), PDFNumber.of(g), PDFNumber.of(b)]),
150
147
  IRT: mainAnnRef,
151
148
  RT: PDFName.of("R"),
@@ -3,7 +3,6 @@ import { convertKonvaRectToPdfRect, rgbToPdfColor, stringToPDFHexString } from "
3
3
  import { convertCanvasPointToPdf, pageTransformFromPdfLibPage } from "../pdf-import/transform.js";
4
4
  import { AnnotationParser } from "./parse.js";
5
5
  import { PRINT_FLAG } from "./annotation-flags.js";
6
- const UNKNOWN_USER = "Unknown user";
7
6
  function formatPdfNumber(value) {
8
7
  if (!Number.isFinite(value)) return "0";
9
8
  return Number(value.toFixed(3)).toString();
@@ -164,9 +163,8 @@ export class LineParser extends AnnotationParser {
164
163
  Rect: rect,
165
164
  InkList: inkList,
166
165
  C: context.obj([PDFNumber.of(r), PDFNumber.of(g), PDFNumber.of(b)]),
167
- T: stringToPDFHexString(annotation.title || UNKNOWN_USER),
166
+ ...this.ownerDateEntries(annotation.title, annotation.date),
168
167
  Contents: stringToPDFHexString(annotation.contentsObj?.text || ""),
169
- M: PDFString.of(annotation.date || ""),
170
168
  NM: PDFString.of(annotation.id),
171
169
  Border: context.obj([0, 0, 0]),
172
170
  BS: bs,
@@ -182,8 +180,7 @@ export class LineParser extends AnnotationParser {
182
180
  F: PRINT_FLAG,
183
181
  Rect: convertKonvaRectToPdfRect(annotation.konvaClientRect, pageTransform),
184
182
  Contents: stringToPDFHexString(comment.content),
185
- T: stringToPDFHexString(comment.title || UNKNOWN_USER),
186
- M: PDFString.of(comment.date || ""),
183
+ ...this.ownerDateEntries(comment.title, comment.date),
187
184
  C: context.obj([PDFNumber.of(r), PDFNumber.of(g), PDFNumber.of(b)]),
188
185
  IRT: mainAnnRef,
189
186
  RT: PDFName.of("R"),
@@ -4,7 +4,6 @@ import { convertCanvasPointToPdf, pageTransformFromPdfLibPage } from "../pdf-imp
4
4
  import { AnnotationParser } from "./parse.js";
5
5
  import { computeBoundsFromKonvaString } from "./parse_utils.js";
6
6
  import { PRINT_FLAG } from "./annotation-flags.js";
7
- const UNKNOWN_USER = "Unknown user";
8
7
  function parseSvgPathToPoints(data) {
9
8
  const commands = data.match(/[a-z][^a-z]*/gi) || [];
10
9
  const points = [];
@@ -70,9 +69,8 @@ export class PolylineParser extends AnnotationParser {
70
69
  Rect: convertKonvaRectToPdfRect(computeBoundsFromKonvaString(annotation.konvaString) ?? annotation.konvaClientRect, pageTransform),
71
70
  InkList: inkList,
72
71
  C: context.obj([PDFNumber.of(r), PDFNumber.of(g), PDFNumber.of(b)]),
73
- T: stringToPDFHexString(annotation.title || UNKNOWN_USER),
72
+ ...this.ownerDateEntries(annotation.title, annotation.date),
74
73
  Contents: stringToPDFHexString(annotation.contentsObj?.text || ""),
75
- M: PDFString.of(annotation.date || ""),
76
74
  NM: PDFString.of(annotation.id),
77
75
  Border: context.obj([0, 0, 0]),
78
76
  BS: bs,
@@ -87,8 +85,7 @@ export class PolylineParser extends AnnotationParser {
87
85
  F: PRINT_FLAG,
88
86
  Rect: convertKonvaRectToPdfRect(computeBoundsFromKonvaString(annotation.konvaString) ?? annotation.konvaClientRect, pageTransform),
89
87
  Contents: stringToPDFHexString(comment.content),
90
- T: stringToPDFHexString(comment.title || UNKNOWN_USER),
91
- M: PDFString.of(comment.date || ""),
88
+ ...this.ownerDateEntries(comment.title, comment.date),
92
89
  C: context.obj([PDFNumber.of(r), PDFNumber.of(g), PDFNumber.of(b)]),
93
90
  IRT: mainAnnRef,
94
91
  RT: PDFName.of("R"),
@@ -4,7 +4,6 @@ import { pageTransformFromPdfLibPage } from "../pdf-import/transform.js";
4
4
  import { AnnotationParser } from "./parse.js";
5
5
  import { computeBoundsFromKonvaString } from "./parse_utils.js";
6
6
  import { PRINT_FLAG } from "./annotation-flags.js";
7
- const UNKNOWN_USER = "Unknown user";
8
7
  export class SquareParser extends AnnotationParser {
9
8
  async parse() {
10
9
  const { annotation, page, pdfDoc } = this;
@@ -18,9 +17,8 @@ export class SquareParser extends AnnotationParser {
18
17
  F: PRINT_FLAG,
19
18
  Rect: rect,
20
19
  C: rgbToPdfColor(annotation.color || void 0),
21
- T: stringToPDFHexString(annotation.title || UNKNOWN_USER),
20
+ ...this.ownerDateEntries(annotation.title, annotation.date),
22
21
  Contents: stringToPDFHexString(annotation.contentsObj?.text || ""),
23
- M: PDFString.of(annotation.date || ""),
24
22
  NM: PDFString.of(annotation.id),
25
23
  Border: [0, 0, 1]
26
24
  });
@@ -33,8 +31,7 @@ export class SquareParser extends AnnotationParser {
33
31
  F: PRINT_FLAG,
34
32
  Rect: rect,
35
33
  Contents: stringToPDFHexString(comment.content),
36
- T: stringToPDFHexString(comment.title || UNKNOWN_USER),
37
- M: PDFString.of(comment.date || ""),
34
+ ...this.ownerDateEntries(comment.title, comment.date),
38
35
  C: rgbToPdfColor(annotation.color || void 0),
39
36
  IRT: mainAnnRef,
40
37
  RT: PDFName.of("R"),
@@ -4,7 +4,6 @@ import { pageTransformFromPdfLibPage } from "../pdf-import/transform.js";
4
4
  import { AnnotationParser } from "./parse.js";
5
5
  import { computeBoundsFromKonvaString, formAppearanceMatrix } from "./parse_utils.js";
6
6
  import { PRINT_FLAG, PRINT_LOCKED_FLAG } from "./annotation-flags.js";
7
- const UNKNOWN_USER = "Unknown user";
8
7
  const SVG_RASTER_SCALE = 4;
9
8
  const MAX_RASTER_EDGE = 4096;
10
9
  function extractBase64Image(dataUrl) {
@@ -175,8 +174,7 @@ export class StampParser extends AnnotationParser {
175
174
  Rect: rect,
176
175
  NM: PDFString.of(annotation.id),
177
176
  Contents: stringToPDFHexString(annotation.contentsObj?.text || ""),
178
- T: stringToPDFHexString(annotation.title || UNKNOWN_USER),
179
- M: PDFString.of(annotation.date || ""),
177
+ ...this.ownerDateEntries(annotation.title, annotation.date),
180
178
  Open: false
181
179
  };
182
180
  if (apDict) {
@@ -192,8 +190,7 @@ export class StampParser extends AnnotationParser {
192
190
  F: PRINT_FLAG,
193
191
  Rect: convertKonvaRectToPdfRect(bounds ?? annotation.konvaClientRect, pageTransform),
194
192
  Contents: stringToPDFHexString(comment.content),
195
- T: stringToPDFHexString(comment.title || UNKNOWN_USER),
196
- M: PDFString.of(comment.date || ""),
193
+ ...this.ownerDateEntries(comment.title, comment.date),
197
194
  IRT: stampAnnRef,
198
195
  RT: PDFName.of("R"),
199
196
  NM: PDFString.of(comment.id),
@@ -3,7 +3,6 @@ import { convertKonvaRectToPdfRect, rgbToPdfColor, stringToPDFHexString } from "
3
3
  import { convertCanvasPointToPdf, pageTransformFromPdfLibPage } from "../pdf-import/transform.js";
4
4
  import { AnnotationParser } from "./parse.js";
5
5
  import { PRINT_FLAG } from "./annotation-flags.js";
6
- const UNKNOWN_USER = "Unknown user";
7
6
  function buildQuadPoints(konvaString, t) {
8
7
  const konvaGroup = JSON.parse(konvaString);
9
8
  const rects = (konvaGroup.children ?? []).filter((item) => item.className === "Rect");
@@ -34,9 +33,8 @@ export class StrikeOutParser extends AnnotationParser {
34
33
  Rect: convertKonvaRectToPdfRect(annotation.konvaClientRect, pageTransform),
35
34
  QuadPoints: quadPoints,
36
35
  C: rgbToPdfColor(annotation.color || void 0),
37
- T: stringToPDFHexString(annotation.title || UNKNOWN_USER),
36
+ ...this.ownerDateEntries(annotation.title, annotation.date),
38
37
  Contents: stringToPDFHexString(annotation.contentsObj?.text || ""),
39
- M: PDFString.of(annotation.date || ""),
40
38
  NM: PDFString.of(annotation.id)
41
39
  });
42
40
  const mainAnnRef = context.register(mainAnn);
@@ -48,8 +46,7 @@ export class StrikeOutParser extends AnnotationParser {
48
46
  F: PRINT_FLAG,
49
47
  Rect: convertKonvaRectToPdfRect(annotation.konvaClientRect, pageTransform),
50
48
  Contents: stringToPDFHexString(comment.content),
51
- T: stringToPDFHexString(comment.title || UNKNOWN_USER),
52
- M: PDFString.of(comment.date || ""),
49
+ ...this.ownerDateEntries(comment.title, comment.date),
53
50
  C: rgbToPdfColor(annotation.color || void 0),
54
51
  IRT: mainAnnRef,
55
52
  RT: PDFName.of("R"),
@@ -4,7 +4,6 @@ import { pageTransformFromPdfLibPage } from "../pdf-import/transform.js";
4
4
  import { AnnotationParser } from "./parse.js";
5
5
  import { computeBoundsFromKonvaString } from "./parse_utils.js";
6
6
  import { PRINT_FLAG } from "./annotation-flags.js";
7
- const UNKNOWN_USER = "Unknown user";
8
7
  export class TextParser extends AnnotationParser {
9
8
  async parse() {
10
9
  const { annotation, page, pdfDoc } = this;
@@ -20,8 +19,7 @@ export class TextParser extends AnnotationParser {
20
19
  NM: PDFString.of(annotation.id),
21
20
  Contents: stringToPDFHexString(annotation.contentsObj?.text || ""),
22
21
  Name: PDFName.of("Comment"),
23
- T: stringToPDFHexString(annotation.title || UNKNOWN_USER),
24
- M: PDFString.of(annotation.date || ""),
22
+ ...this.ownerDateEntries(annotation.title, annotation.date),
25
23
  C: rgbToPdfColor(annotation.color || void 0),
26
24
  Open: false
27
25
  });
@@ -34,8 +32,7 @@ export class TextParser extends AnnotationParser {
34
32
  F: PRINT_FLAG,
35
33
  Rect: rect,
36
34
  Contents: stringToPDFHexString(comment.content),
37
- T: stringToPDFHexString(comment.title || UNKNOWN_USER),
38
- M: PDFString.of(comment.date || ""),
35
+ ...this.ownerDateEntries(comment.title, comment.date),
39
36
  C: rgbToPdfColor(annotation.color || void 0),
40
37
  IRT: mainAnnRef,
41
38
  RT: PDFName.of("R"),
@@ -3,7 +3,6 @@ import { convertKonvaRectToPdfRect, rgbToPdfColor, stringToPDFHexString } from "
3
3
  import { convertCanvasPointToPdf, pageTransformFromPdfLibPage } from "../pdf-import/transform.js";
4
4
  import { AnnotationParser } from "./parse.js";
5
5
  import { PRINT_FLAG } from "./annotation-flags.js";
6
- const UNKNOWN_USER = "Unknown user";
7
6
  function buildQuadPoints(konvaString, t) {
8
7
  const konvaGroup = JSON.parse(konvaString);
9
8
  const rects = (konvaGroup.children ?? []).filter((item) => item.className === "Rect");
@@ -34,9 +33,8 @@ export class UnderlineParser extends AnnotationParser {
34
33
  Rect: convertKonvaRectToPdfRect(annotation.konvaClientRect, pageTransform),
35
34
  QuadPoints: quadPoints,
36
35
  C: rgbToPdfColor(annotation.color || void 0),
37
- T: stringToPDFHexString(annotation.title || UNKNOWN_USER),
36
+ ...this.ownerDateEntries(annotation.title, annotation.date),
38
37
  Contents: stringToPDFHexString(annotation.contentsObj?.text || ""),
39
- M: PDFString.of(annotation.date || ""),
40
38
  NM: PDFString.of(annotation.id)
41
39
  });
42
40
  const mainAnnRef = context.register(mainAnn);
@@ -48,8 +46,7 @@ export class UnderlineParser extends AnnotationParser {
48
46
  F: PRINT_FLAG,
49
47
  Rect: convertKonvaRectToPdfRect(annotation.konvaClientRect, pageTransform),
50
48
  Contents: stringToPDFHexString(comment.content),
51
- T: stringToPDFHexString(comment.title || UNKNOWN_USER),
52
- M: PDFString.of(comment.date || ""),
49
+ ...this.ownerDateEntries(comment.title, comment.date),
53
50
  C: rgbToPdfColor(annotation.color || void 0),
54
51
  IRT: mainAnnRef,
55
52
  RT: PDFName.of("R"),
@@ -780,7 +780,7 @@ async function importAnnotations(annotations, options) {
780
780
  const mode = options?.mode ?? "replace";
781
781
  const normalized = normalizeImportedAnnotations(
782
782
  annotations,
783
- props.userName ?? "User"
783
+ props.userName
784
784
  );
785
785
  if (!painter) {
786
786
  return { loaded: 0, skipped: normalized.skipped + normalized.annotations.length };
@@ -65,7 +65,9 @@ export function createAnnotationEngine(viewerState, options) {
65
65
  getFormFieldPreviewColor: options.getFormFieldPreviewColor
66
66
  };
67
67
  const painter = new Painter({
68
- userName: options.userName ?? "User",
68
+ // No fallback: when the host app doesn't supply a userName, annotations
69
+ // carry no author and export omits /T (matches pdf.js / Firefox).
70
+ userName: options.userName,
69
71
  callbacks,
70
72
  getStylusModeEnabled: () => viewerState.stylusMode.value,
71
73
  getReadonly: () => viewerState.readonly.value,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kviewer",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Kabema PDF Editor",
5
5
  "repository": "kabema/kviewer",
6
6
  "license": "MIT",