@poe-platform/safe-bash 0.1.816 → 0.1.817

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.
Files changed (48) hide show
  1. package/dist/pdf-ast/content/evaluator.d.ts +4 -0
  2. package/dist/pdf-ast/cos/value-parser.d.ts +2 -0
  3. package/dist/pdf-ast/fonts/resolve.d.ts +5 -1
  4. package/dist/pdf-ast/index.js +172 -165
  5. package/dist/safe-bash/command-chunks/biff-KLS4T7FP-UO3CXFFF.js +5581 -0
  6. package/dist/safe-bash/command-chunks/chunk-2J4OQT3F.js +153 -0
  7. package/dist/safe-bash/command-chunks/{chunk-K7VDCBXW.js → chunk-ABL2DPJI.js} +20 -20
  8. package/dist/safe-bash/command-chunks/{chunk-RINR7XPR.js → chunk-E64ZI2YB.js} +121 -4
  9. package/dist/safe-bash/command-chunks/{chunk-GEDO5V32.js → chunk-FSG6UC2N.js} +243 -105
  10. package/dist/safe-bash/command-chunks/{chunk-4QEJPP3K.js → chunk-S5X7PBO4.js} +1 -1
  11. package/dist/safe-bash/command-chunks/{chunk-IHLZ6HNQ.js → chunk-TSKJNCKD.js} +3 -2
  12. package/dist/safe-bash/command-chunks/{chunk-DBZCTL7C.js → chunk-UYZ6EFZE.js} +20 -18
  13. package/dist/safe-bash/command-chunks/{chunk-B2C3UPJS.js → chunk-W42SUPD6.js} +13 -1
  14. package/dist/safe-bash/command-chunks/chunk-ZHHALBM7.js +398 -0
  15. package/dist/safe-bash/command-chunks/{command-engine-GHE6QUHU.js → command-engine-2QXVRRH3.js} +8 -4
  16. package/dist/safe-bash/command-chunks/{engine-RG6HQCCB-FXYZS264.js → engine-T4GP6QOK-ECFKMR5V.js} +1 -1
  17. package/dist/safe-bash/command-chunks/odf-SL5TG4B3-XI3FNOTN.js +3041 -0
  18. package/dist/safe-bash/command-chunks/{xlsx-RE54MFCS-IQ6OXXKK.js → xlsx-RE54MFCS-4UZ5W3U7.js} +1 -1
  19. package/dist/safe-bash-command-apply-patch/apply.js +1 -1
  20. package/dist/safe-bash-command-apply-patch/index.js +1 -1
  21. package/dist/safe-bash-command-csvkit/index.js +1 -1
  22. package/dist/safe-bash-command-diff/diff.js +1 -1
  23. package/dist/safe-bash-command-diff/index.js +1 -1
  24. package/dist/safe-bash-command-pptx/engine.js +1 -1
  25. package/dist/safe-bash-command-ssconvert/index.js +5 -5
  26. package/dist/safe-bash-presentation-engine/index.js +1 -1
  27. package/dist/safe-bash-presentation-engine/retained-tags.d.ts +20 -0
  28. package/dist/safe-bash-presentation-engine/tags.d.ts +2 -0
  29. package/dist/safe-bash-presentation-engine/tags.js +11 -3
  30. package/dist/safe-bash-xml-engine/document.js +2 -2
  31. package/dist/safe-bash-xml-engine/index.js +2 -2
  32. package/dist/safe-bash-xml-engine/stored-document.d.ts +2 -0
  33. package/dist/safe-bash-xml-engine/stored-document.js +1 -1
  34. package/dist/safe-bash-xml-engine/stored-evaluate.js +2 -2
  35. package/dist/safe-bash-xml-engine/stored-namespaces.d.ts +21 -0
  36. package/dist/safe-bash-zip-engine/zip/safety.js +1 -1
  37. package/dist/safe-bash-zip-engine/zip/volumes.js +1 -1
  38. package/dist/spreadsheet-format-xls/biff-properties-merge.js +3 -3
  39. package/dist/spreadsheet-format-xls/biff-properties.d.ts +4 -2
  40. package/dist/spreadsheet-format-xls/biff-properties.js +141 -122
  41. package/dist/spreadsheet-format-xls/biff-property-names.d.ts +24 -0
  42. package/dist/spreadsheet-format-xls/biff-property-names.js +167 -0
  43. package/dist/xlsx-ast/comment-geometry.js +1 -1
  44. package/package.json +3 -2
  45. package/dist/safe-bash/command-chunks/biff-UBP2BZLK-JPODPKS3.js +0 -5448
  46. package/dist/safe-bash/command-chunks/chunk-O2HNOQQG.js +0 -161
  47. package/dist/safe-bash/command-chunks/chunk-ZUP5TBRG.js +0 -99
  48. package/dist/safe-bash/command-chunks/odf-3EA3EVSD-7B5GVNTC.js +0 -3097
@@ -3,7 +3,7 @@ import {
3
3
  createXlsxWriter,
4
4
  probeXlsx,
5
5
  readXlsx
6
- } from "./chunk-4QEJPP3K.js";
6
+ } from "./chunk-S5X7PBO4.js";
7
7
  import "./chunk-ILRQMDY4.js";
8
8
  import "./chunk-37XCUS43.js";
9
9
  import "./chunk-XRIYRWLW.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  execute
3
- } from "../safe-bash/command-chunks/chunk-B2C3UPJS.js";
3
+ } from "../safe-bash/command-chunks/chunk-W42SUPD6.js";
4
4
  import "../safe-bash/command-chunks/chunk-SU26FZLJ.js";
5
5
  import "../safe-bash/command-chunks/chunk-66QPYWEF.js";
6
6
  import "../safe-bash/command-chunks/chunk-5HUICAWD.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  execute
3
- } from "../safe-bash/command-chunks/chunk-B2C3UPJS.js";
3
+ } from "../safe-bash/command-chunks/chunk-W42SUPD6.js";
4
4
  import "../safe-bash/command-chunks/chunk-SU26FZLJ.js";
5
5
  import {
6
6
  settings
@@ -1,4 +1,4 @@
1
- import "../safe-bash/command-chunks/chunk-4QEJPP3K.js";
1
+ import "../safe-bash/command-chunks/chunk-S5X7PBO4.js";
2
2
  import "../safe-bash/command-chunks/chunk-ILRQMDY4.js";
3
3
  import "../safe-bash/command-chunks/chunk-37XCUS43.js";
4
4
  import "../safe-bash/command-chunks/chunk-XRIYRWLW.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  diffCommand
3
- } from "../safe-bash/command-chunks/chunk-GEDO5V32.js";
3
+ } from "../safe-bash/command-chunks/chunk-FSG6UC2N.js";
4
4
  import "../safe-bash/command-chunks/chunk-QFFJN22S.js";
5
5
  import "../safe-bash/command-chunks/chunk-AHZ7UGNB.js";
6
6
  import "../safe-bash/command-chunks/chunk-VXIC7SS3.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  diffCommand
3
- } from "../safe-bash/command-chunks/chunk-GEDO5V32.js";
3
+ } from "../safe-bash/command-chunks/chunk-FSG6UC2N.js";
4
4
  import {
5
5
  evalSyncDiff
6
6
  } from "../safe-bash/command-chunks/chunk-XI2LETBJ.js";
@@ -27,7 +27,7 @@ function createPptxCommandEngine(settings = {}) {
27
27
  };
28
28
  return Object.freeze({
29
29
  async execute(request) {
30
- const mod = await (cachedPptxEngineMod ??= import("../safe-bash/command-chunks/command-engine-GHE6QUHU.js"));
30
+ const mod = await (cachedPptxEngineMod ??= import("../safe-bash/command-chunks/command-engine-2QXVRRH3.js"));
31
31
  return mod.createPptxCommandEngine(ownedSettings).execute(request);
32
32
  }
33
33
  });
@@ -10,7 +10,7 @@ import {
10
10
  gt,
11
11
  j,
12
12
  oe
13
- } from "../safe-bash/command-chunks/chunk-K7VDCBXW.js";
13
+ } from "../safe-bash/command-chunks/chunk-ABL2DPJI.js";
14
14
  import {
15
15
  n as n3,
16
16
  o as o5
@@ -719,18 +719,18 @@ var le;
719
719
  function wr(...u) {
720
720
  return le ??= V({ read: readZipArchiveEntries, write: createStoredZipArchive }), le(...u);
721
721
  }
722
- var H = de(async (u) => (await import("../safe-bash/command-chunks/engine-RG6HQCCB-FXYZS264.js")).createEngine(u), true, wr);
722
+ var H = de(async (u) => (await import("../safe-bash/command-chunks/engine-T4GP6QOK-ECFKMR5V.js")).createEngine(u), true, wr);
723
723
  var Do = H.createSsconvertCommand;
724
724
  var To = H.createSsconvertCommands;
725
725
  var Uo = H.ssconvertCommands;
726
726
  async function Lo(u, c2, i3) {
727
- let x2 = await import("../safe-bash/command-chunks/xlsx-RE54MFCS-IQ6OXXKK.js");
727
+ let x2 = await import("../safe-bash/command-chunks/xlsx-RE54MFCS-4UZ5W3U7.js");
728
728
  return i3 ? x2.readXlsx(u, c2, true) : x2.readXlsx(u, c2);
729
729
  }
730
- var zo = async (...u) => (await import("../safe-bash/command-chunks/xlsx-RE54MFCS-IQ6OXXKK.js")).probeXlsx(...u);
730
+ var zo = async (...u) => (await import("../safe-bash/command-chunks/xlsx-RE54MFCS-4UZ5W3U7.js")).probeXlsx(...u);
731
731
  var Mo = (u = "2006") => async (c2, i3, x2) => {
732
732
  let g2 = (0, T.snapshotXlsxWorkbook)(c2, x2);
733
- return (await import("../safe-bash/command-chunks/xlsx-RE54MFCS-IQ6OXXKK.js")).createXlsxWriter(u)(g2, i3, x2);
733
+ return (await import("../safe-bash/command-chunks/xlsx-RE54MFCS-4UZ5W3U7.js")).createXlsxWriter(u)(g2, i3, x2);
734
734
  };
735
735
  export {
736
736
  r as DEFAULT_SHEET_SIZE,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  mutateTags,
3
3
  readTags
4
- } from "../safe-bash/command-chunks/chunk-O2HNOQQG.js";
4
+ } from "../safe-bash/command-chunks/chunk-ZHHALBM7.js";
5
5
  import {
6
6
  readAnimations
7
7
  } from "../safe-bash/command-chunks/chunk-6YF2QADH.js";
@@ -0,0 +1,20 @@
1
+ import { type StagedOutput } from './retained-output.js';
2
+ import type { ByteSource } from './contracts.js';
3
+ import { type TagOptions, type TagRecord } from './tags.js';
4
+ import type { RetainedPackageArchive, RetainedPackageContext } from './retained-package.js';
5
+ export interface RetainedTagRecord extends Omit<TagRecord, 'name' | 'value'> {
6
+ name(): ByteSource;
7
+ value(): ByteSource;
8
+ }
9
+ /** Tag attributes and ordered records live in caller pages. ZIP-bounded owner
10
+ * and part names are the only strings retained in a record's selector schema. */
11
+ export declare function openRetainedTags(archive: Pick<RetainedPackageArchive, 'parts' | 'has' | 'read' | 'byteLength'>, fingerprint: string, options: TagOptions, settings: RetainedPackageContext): Promise<Readonly<{
12
+ close: () => Promise<void>;
13
+ records(): AsyncGenerator<RetainedTagRecord>;
14
+ }>>;
15
+ /** Stage complete responses before exposing output or retiring metadata. */
16
+ export declare function stageRetainedTags(archive: Pick<RetainedPackageArchive, 'parts' | 'has' | 'read' | 'byteLength'>, fingerprint: string, query: TagOptions, settings: RetainedPackageContext, output: {
17
+ readonly operation: 'tags.list' | 'tags.get';
18
+ readonly json: boolean;
19
+ readonly maxOutputBytes: number;
20
+ }): Promise<StagedOutput>;
@@ -16,9 +16,11 @@ export interface TagOptions {
16
16
  readonly value?: string;
17
17
  readonly allowEmpty?: boolean;
18
18
  }
19
+ export declare function validateTagOptions(options: TagOptions, action?: string): void;
19
20
  export declare function readTags(input: BinaryInput, options: TagOptions, context: SelectionContext): Promise<readonly TagRecord[]>;
20
21
  export declare function mutateTags(input: BinaryInput, action: "add" | "set" | "remove", options: TagOptions, context: SelectionContext): Promise<{
21
22
  bytes: Uint8Array;
22
23
  affected: number;
23
24
  locations: readonly Location[];
24
25
  }>;
26
+ export { openRetainedTags, stageRetainedTags, type RetainedTagRecord } from './retained-tags.js';
@@ -1,7 +1,12 @@
1
1
  import {
2
2
  mutateTags,
3
- readTags
4
- } from "../safe-bash/command-chunks/chunk-O2HNOQQG.js";
3
+ openRetainedTags,
4
+ readTags,
5
+ stageRetainedTags,
6
+ validateTagOptions
7
+ } from "../safe-bash/command-chunks/chunk-ZHHALBM7.js";
8
+ import "../safe-bash/command-chunks/chunk-FB2WPI3M.js";
9
+ import "../safe-bash/command-chunks/chunk-XVEI4HZL.js";
5
10
  import "../safe-bash/command-chunks/chunk-A5SPMSKD.js";
6
11
  import "../safe-bash/command-chunks/chunk-TG2RVQLP.js";
7
12
  import "../safe-bash/command-chunks/chunk-NCNHJRIY.js";
@@ -25,5 +30,8 @@ import "../safe-bash/command-chunks/chunk-E6SK3OU2.js";
25
30
  import "../safe-bash/command-chunks/chunk-65DS4IOB.js";
26
31
  export {
27
32
  mutateTags,
28
- readTags
33
+ openRetainedTags,
34
+ readTags,
35
+ stageRetainedTags,
36
+ validateTagOptions
29
37
  };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  serializeDocument
3
- } from "../safe-bash/command-chunks/chunk-DBZCTL7C.js";
4
- import "../safe-bash/command-chunks/chunk-RINR7XPR.js";
3
+ } from "../safe-bash/command-chunks/chunk-UYZ6EFZE.js";
4
+ import "../safe-bash/command-chunks/chunk-E64ZI2YB.js";
5
5
  import "../safe-bash/command-chunks/chunk-IJE65P52.js";
6
6
  import "../safe-bash/command-chunks/chunk-3I5WTVWZ.js";
7
7
  import "../safe-bash/command-chunks/chunk-65DS4IOB.js";
@@ -3,10 +3,10 @@ import {
3
3
  } from "../safe-bash/command-chunks/chunk-LNKZVU5V.js";
4
4
  import {
5
5
  serializeDocument
6
- } from "../safe-bash/command-chunks/chunk-DBZCTL7C.js";
6
+ } from "../safe-bash/command-chunks/chunk-UYZ6EFZE.js";
7
7
  import {
8
8
  parseStoredXml
9
- } from "../safe-bash/command-chunks/chunk-RINR7XPR.js";
9
+ } from "../safe-bash/command-chunks/chunk-E64ZI2YB.js";
10
10
  import {
11
11
  escape,
12
12
  evaluate,
@@ -1,5 +1,6 @@
1
1
  import { type XmlAttribute, type XmlContent } from "@poe-platform/safe-fs/core";
2
2
  import { PagedStorage, type PagedStorageContext } from "@poe-platform/safe-fs/storage";
3
+ import { StoredNamespaces } from "./stored-namespaces.js";
3
4
  import { XmlBudget } from "./limits.js";
4
5
  export type StoredXmlAttribute = {
5
6
  kind: "attribute";
@@ -24,6 +25,7 @@ export declare class StoredXmlDocument {
24
25
  private append;
25
26
  /** Buffering convenience API; engine traversal uses metadata and attribute links. */
26
27
  node(reference: number): Promise<XmlContent | StoredXmlAttribute>;
28
+ namespaceScope(reference: number): Promise<StoredNamespaces>;
27
29
  metadata(reference: number): Promise<XmlContent | StoredXmlAttribute>;
28
30
  /** Content bodies may span parser fragments or coalesced text tokens.
29
31
  * Replay them without making a concatenated node value. */
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  StoredXmlDocument
3
- } from "../safe-bash/command-chunks/chunk-RINR7XPR.js";
3
+ } from "../safe-bash/command-chunks/chunk-E64ZI2YB.js";
4
4
  import "../safe-bash/command-chunks/chunk-65DS4IOB.js";
5
5
  export {
6
6
  StoredXmlDocument
@@ -82,7 +82,7 @@ var StoredXPath = class {
82
82
  } else yield* this.document.children(reference, attributes);
83
83
  }
84
84
  async select(query, context = this.document.document) {
85
- const root = await this.document.metadata(this.document.root);
85
+ const namespaces = await this.document.namespaceScope(this.document.root);
86
86
  const union = new StoredSelection(this);
87
87
  for (const path of query.paths) {
88
88
  let contexts = new StoredSelection(this);
@@ -90,7 +90,7 @@ var StoredXPath = class {
90
90
  for (const step of path) {
91
91
  const colon = step.name.indexOf(":");
92
92
  const prefix = colon < 0 ? "" : step.name.slice(0, colon);
93
- const namespace = colon < 0 ? "" : root.namespaces.get(prefix);
93
+ const namespace = colon < 0 ? "" : await namespaces.get(prefix);
94
94
  if (namespace === void 0) throw new XmlQueryError(`undefined XPath namespace prefix: ${prefix}`, 10);
95
95
  const localName = colon < 0 ? step.name : step.name.slice(colon + 1);
96
96
  const parents = new StoredSelection(this);
@@ -0,0 +1,21 @@
1
+ import type { PagedStorage } from "@poe-platform/safe-fs/storage";
2
+ import type { XmlBudget } from "./limits.js";
3
+ /** Immutable AVL scopes share unchanged subtrees in caller storage. AVL ancestry
4
+ * is bounded by safe-integer storage addresses (fewer than 80 levels), rather
5
+ * than XML depth or the number of declarations in a scope. Individual namespace
6
+ * names and URIs still have the parser's token cost. */
7
+ export declare class StoredNamespaces {
8
+ private readonly storage;
9
+ private readonly budget;
10
+ readonly reference: number;
11
+ constructor(storage: PagedStorage, budget: XmlBudget, reference?: number);
12
+ private read;
13
+ private write;
14
+ get(prefix: string): Promise<string | undefined>;
15
+ private height;
16
+ private updated;
17
+ private rotate;
18
+ private balance;
19
+ set(prefix: string, uri: string): Promise<StoredNamespaces>;
20
+ [Symbol.asyncIterator](): AsyncGenerator<readonly [string, string]>;
21
+ }
@@ -8,7 +8,7 @@ import {
8
8
  spoolZipSource,
9
9
  stageZip,
10
10
  unchangedZipSource
11
- } from "../../safe-bash/command-chunks/chunk-IHLZ6HNQ.js";
11
+ } from "../../safe-bash/command-chunks/chunk-TSKJNCKD.js";
12
12
  import "../../safe-bash/command-chunks/chunk-65DS4IOB.js";
13
13
  export {
14
14
  ZipScope,
@@ -5,7 +5,7 @@ import {
5
5
  openZipSource,
6
6
  sameZipIdentity,
7
7
  stageZip
8
- } from "../../safe-bash/command-chunks/chunk-IHLZ6HNQ.js";
8
+ } from "../../safe-bash/command-chunks/chunk-TSKJNCKD.js";
9
9
  import {
10
10
  ZipFailure
11
11
  } from "../../safe-bash/command-chunks/chunk-4REP6ZW6.js";
@@ -121,8 +121,8 @@ export async function mergeBiffProperties(book, streams, handled, context, charg
121
121
  const identity = (property) => `${property.stream}:${property.section}:${property.id}`;
122
122
  const readContext = { ...context, limits: { ...context.limits, inputBytes: context.limits.outputBytes } };
123
123
  // Reuse scalar decoding, but do not create another retained hexadecimal copy.
124
- await readBiffProperties(new Map([...snapshots].map(([name, value]) => [name, value.bytes])), readContext, accountText, charge, undefined, property => { admit(1); original.set(identity(property), property); });
125
- await readBiffProperties(streams, readContext, accountText, charge, undefined, property => { admit(1); pending.set(property.key, property); });
124
+ await readBiffProperties(new Map([...snapshots].map(([name, value]) => [name, value.bytes])), readContext, accountText, charge, undefined, property => { admit(1); original.set(identity(property), property); }, false);
125
+ await readBiffProperties(streams, readContext, accountText, charge, undefined, property => { admit(1); pending.set(property.key, property); }, false);
126
126
  const chunks = async function* (source) {
127
127
  for (let at = 0; at < source.size;) {
128
128
  const bytes = await source.read(at, source.size - at);
@@ -456,7 +456,7 @@ export async function mergeBiffProperties(book, streams, handled, context, charg
456
456
  admit(1);
457
457
  if (!Object.hasOwn(book.properties ?? {}, property.key))
458
458
  exposed.add(property.key);
459
- });
459
+ }, false);
460
460
  for (const key of exposed)
461
461
  await warn(key, "opaque property exposes a field absent from the model");
462
462
  }
@@ -7,11 +7,13 @@ export declare const biffPropertyFormats: {
7
7
  };
8
8
  export declare const biffPropertyFields: Map<string, ReadonlyMap<number, string>>;
9
9
  export declare function isBiffKeywordSpace(code: number): boolean;
10
- /** Property offsets are section-relative; dictionaries have no variant header. */
10
+ /** Property offsets are section-relative; dictionaries have no variant header.
11
+ * With collect=false, await observations without retaining a result record; exact
12
+ * duplicate-name checks use bounded caller storage when available. */
11
13
  export declare function readBiffProperties(streams: ReadonlyMap<string, Uint8Array | RangeSource>, context: CapabilityContext, accountText: (text: string) => string, accountWork: (amount: number) => void, retained: UnsupportedRecord[] | undefined, observe?: (property: {
12
14
  stream: string;
13
15
  section: number;
14
16
  id: number;
15
17
  key: string;
16
18
  value: ImportedValue;
17
- }) => void): Promise<Readonly<Record<string, ImportedValue>>>;
19
+ }) => void | Promise<void>, collect?: boolean): Promise<Readonly<Record<string, ImportedValue>>>;
@@ -1,3 +1,4 @@
1
+ import { BiffPropertyNames } from './biff-property-names.js';
1
2
  import { visitBiffPropertyDictionary } from './biff-property-dictionary.js';
2
3
  import { SsconvertError } from "../spreadsheet-engine/contracts.js";
3
4
  import { invalidBiff } from "./biff-binary.js";
@@ -19,9 +20,12 @@ export const biffPropertyFields = new Map([
19
20
  export function isBiffKeywordSpace(code) {
20
21
  return code > 0 && code <= 32 || code >= 0x2000 && code <= 0x200b || code === 0x2028 || code === 0x2029;
21
22
  }
22
- /** Property offsets are section-relative; dictionaries have no variant header. */
23
- export async function readBiffProperties(streams, context, accountText, accountWork, retained, observe) {
23
+ /** Property offsets are section-relative; dictionaries have no variant header.
24
+ * With collect=false, await observations without retaining a result record; exact
25
+ * duplicate-name checks use bounded caller storage when available. */
26
+ export async function readBiffProperties(streams, context, accountText, accountWork, retained, observe, collect = true) {
24
27
  const properties = Object.create(null);
28
+ let names;
25
29
  let nodes = 0;
26
30
  const admit = (count) => {
27
31
  accountWork(count);
@@ -29,138 +33,153 @@ export async function readBiffProperties(streams, context, accountText, accountW
29
33
  if (nodes > (context.limits.workbookNodes ?? context.limits.inputBytes))
30
34
  throw new SsconvertError("resource-limit", "ssconvert BIFF property node limit exceeded");
31
35
  };
32
- for (const target of ["\u0005SummaryInformation", "\u0005DocumentSummaryInformation"]) {
33
- let streamName = target, bytes = streams.get(target);
34
- if (!bytes)
35
- for (const [name, data] of streams) {
36
- accountWork(1);
37
- if (name.toUpperCase() === target.toUpperCase()) {
38
- streamName = name;
39
- bytes = data;
40
- break;
36
+ try {
37
+ for (const target of ["\u0005SummaryInformation", "\u0005DocumentSummaryInformation"]) {
38
+ let streamName = target, bytes = streams.get(target);
39
+ if (!bytes)
40
+ for (const [name, data] of streams) {
41
+ accountWork(1);
42
+ if (name.toUpperCase() === target.toUpperCase()) {
43
+ streamName = name;
44
+ bytes = data;
45
+ break;
46
+ }
41
47
  }
42
- }
43
- if (!bytes)
44
- continue;
45
- const file = propertyRange(bytes, context);
46
- accountWork(file.size);
47
- const sections = readPropertySectionRanges(file, admit, accountWork, context);
48
- let unknown = false;
49
- const modeled = retained ? [] : undefined;
50
- for await (const { guid, offset, end } of sections) {
51
- if (!biffPropertyFields.has(guid) && guid !== custom) {
52
- unknown = true;
48
+ if (!bytes)
53
49
  continue;
54
- }
55
- await withPropertyValueRanges(file.slice(offset, end - offset), admit, accountWork, context, async (values) => {
56
- const cp = await values.get(1);
57
- let codepage = 1252;
58
- if (cp) {
59
- if ((await cp.u32(0)) !== 2)
60
- invalidBiff("invalid property codepage type");
61
- codepage = await cp.u16(4);
50
+ const file = propertyRange(bytes, context);
51
+ accountWork(file.size);
52
+ const sections = readPropertySectionRanges(file, admit, accountWork, context);
53
+ let unknown = false;
54
+ const modeled = retained ? [] : undefined;
55
+ for await (const { guid, offset, end } of sections) {
56
+ if (!biffPropertyFields.has(guid) && guid !== custom) {
57
+ unknown = true;
58
+ continue;
62
59
  }
63
- const dictionary = guid === custom ? await values.get(0) : undefined;
64
- const supported = await visitBiffPropertyDictionary(dictionary, codepage, context, admit, accountText, accountWork, async (getName) => {
65
- for await (const [id, data] of values.entries()) {
66
- context.signal.throwIfAborted();
67
- if (id < 2)
68
- continue;
69
- const key = guid === custom ? await getName(id) : biffPropertyFields.get(guid)?.get(id);
70
- if (key === undefined || Object.hasOwn(properties, key)) {
71
- unknown = true;
72
- continue;
73
- }
74
- let value;
75
- const type = await data.u32(0);
76
- try {
77
- if (type === 30 || type === 31)
78
- value = (await readBiffPropertyText(data, 4, type === 31 ? 1200 : codepage, context, accountText, accountWork)).value;
79
- else if (type === 3)
80
- value = (await data.u32(4)) | 0;
81
- else if (type === 5) {
82
- value = await data.f64(4);
83
- if (!Number.isFinite(value))
84
- invalidBiff("nonfinite property value");
60
+ await withPropertyValueRanges(file.slice(offset, end - offset), admit, accountWork, context, async (values) => {
61
+ const cp = await values.get(1);
62
+ let codepage = 1252;
63
+ if (cp) {
64
+ if ((await cp.u32(0)) !== 2)
65
+ invalidBiff("invalid property codepage type");
66
+ codepage = await cp.u16(4);
67
+ }
68
+ const dictionary = guid === custom ? await values.get(0) : undefined;
69
+ const supported = await visitBiffPropertyDictionary(dictionary, codepage, context, admit, accountText, accountWork, async (getName) => {
70
+ for await (const [id, data] of values.entries()) {
71
+ context.signal.throwIfAborted();
72
+ if (id < 2)
73
+ continue;
74
+ const key = guid === custom ? await getName(id) : biffPropertyFields.get(guid)?.get(id);
75
+ if (key === undefined || (collect ? Object.hasOwn(properties, key) : await (names ??= new BiffPropertyNames(context, accountWork)).has(key))) {
76
+ unknown = true;
77
+ continue;
85
78
  }
86
- else if (type === 11)
87
- value = (await data.u16(4)) !== 0;
88
- else if (type === 64) {
89
- const ticks = BigInt(await data.u32(4)) + (BigInt(await data.u32(8)) << 32n);
90
- if (guid === summary && id === 10) {
91
- const fraction = (ticks % 10000000n).toString().padStart(7, "0");
92
- let end = fraction.length;
93
- while (end && fraction[end - 1] === "0")
94
- end--;
95
- value = `PT${ticks / 600000000n}M${ticks / 10000000n % 60n}${end ? "." + fraction.slice(0, end) : ""}S`;
79
+ let value;
80
+ const type = await data.u32(0);
81
+ try {
82
+ if (type === 30 || type === 31)
83
+ value = (await readBiffPropertyText(data, 4, type === 31 ? 1200 : codepage, context, accountText, accountWork)).value;
84
+ else if (type === 3)
85
+ value = (await data.u32(4)) | 0;
86
+ else if (type === 5) {
87
+ value = await data.f64(4);
88
+ if (!Number.isFinite(value))
89
+ invalidBiff("nonfinite property value");
90
+ }
91
+ else if (type === 11)
92
+ value = (await data.u16(4)) !== 0;
93
+ else if (type === 64) {
94
+ const ticks = BigInt(await data.u32(4)) + (BigInt(await data.u32(8)) << 32n);
95
+ if (guid === summary && id === 10) {
96
+ const fraction = (ticks % 10000000n).toString().padStart(7, "0");
97
+ let end = fraction.length;
98
+ while (end && fraction[end - 1] === "0")
99
+ end--;
100
+ value = `PT${ticks / 600000000n}M${ticks / 10000000n % 60n}${end ? "." + fraction.slice(0, end) : ""}S`;
101
+ }
102
+ else {
103
+ value = new Date(Number(ticks / 10000n) - 11644473600000).toISOString();
104
+ // The workbook model stores timestamps as strings; retain the
105
+ // original property bytes when Date's millisecond precision loses ticks.
106
+ if (ticks % 10000n)
107
+ unknown = true;
108
+ }
109
+ accountText(value);
96
110
  }
97
- else {
98
- value = new Date(Number(ticks / 10000n) - 11644473600000).toISOString();
99
- // The workbook model stores timestamps as strings; retain the
100
- // original property bytes when Date's millisecond precision loses ticks.
101
- if (ticks % 10000n)
102
- unknown = true;
111
+ else if (type === 7) {
112
+ const days = await data.f64(4);
113
+ if (!Number.isFinite(days) || days <= -657435 || days >= 2958466)
114
+ invalidBiff("invalid OLE property date");
115
+ // OLE Automation uses 1899-12-30 and the absolute fractional day.
116
+ // LibreOffice's oleprops DATE path truncates it and uses 1899-12-31;
117
+ // the documented Automation representation governs the stored value.
118
+ value = new Date(-2209161600000 + Math.round((Math.trunc(days) + Math.abs(days % 1)) * 86400000)).toISOString();
119
+ accountText(value);
103
120
  }
104
- accountText(value);
105
121
  }
106
- else if (type === 7) {
107
- const days = await data.f64(4);
108
- if (!Number.isFinite(days) || days <= -657435 || days >= 2958466)
109
- invalidBiff("invalid OLE property date");
110
- // OLE Automation uses 1899-12-30 and the absolute fractional day.
111
- // LibreOffice's oleprops DATE path truncates it and uses 1899-12-31;
112
- // the documented Automation representation governs the stored value.
113
- value = new Date(-2209161600000 + Math.round((Math.trunc(days) + Math.abs(days % 1)) * 86400000)).toISOString();
114
- accountText(value);
122
+ catch (error) {
123
+ if (!(error instanceof SsconvertError) || error.code !== "unsupported-feature")
124
+ throw error;
115
125
  }
126
+ if (value === undefined) {
127
+ unknown = true;
128
+ continue;
129
+ }
130
+ if (guid === summary && id === 5 && typeof value === "string") {
131
+ let count = 1;
132
+ for (const character of value)
133
+ if (character === ",")
134
+ count++;
135
+ admit(count);
136
+ accountWork(value.length);
137
+ value = value.split(",").map(keyword => {
138
+ let start = 0, end = keyword.length;
139
+ while (start < end && isBiffKeywordSpace(keyword.charCodeAt(start)))
140
+ start++;
141
+ while (end > start && isBiffKeywordSpace(keyword.charCodeAt(end - 1)))
142
+ end--;
143
+ return keyword.slice(start, end);
144
+ }).filter(Boolean);
145
+ }
146
+ accountText(key);
147
+ if (collect)
148
+ properties[key] = value;
149
+ else
150
+ await names.add(key);
151
+ modeled?.push([offset, id, key]);
152
+ await observe?.({ stream: streamName, section: offset, id, key, value });
116
153
  }
117
- catch (error) {
118
- if (!(error instanceof SsconvertError) || error.code !== "unsupported-feature")
119
- throw error;
120
- }
121
- if (value === undefined) {
122
- unknown = true;
123
- continue;
124
- }
125
- if (guid === summary && id === 5 && typeof value === "string") {
126
- let count = 1;
127
- for (const character of value)
128
- if (character === ",")
129
- count++;
130
- admit(count);
131
- accountWork(value.length);
132
- value = value.split(",").map(keyword => {
133
- let start = 0, end = keyword.length;
134
- while (start < end && isBiffKeywordSpace(keyword.charCodeAt(start)))
135
- start++;
136
- while (end > start && isBiffKeywordSpace(keyword.charCodeAt(end - 1)))
137
- end--;
138
- return keyword.slice(start, end);
139
- }).filter(Boolean);
140
- }
141
- accountText(key);
142
- properties[key] = value;
143
- modeled?.push([offset, id, key]);
144
- observe?.({ stream: streamName, section: offset, id, key, value });
145
- }
154
+ });
155
+ if (!supported)
156
+ unknown = true;
146
157
  });
147
- if (!supported)
148
- unknown = true;
149
- });
150
- }
151
- if (unknown && retained && modeled) {
152
- if (file.size * 2 > (context.limits.workbookTextBytes ?? context.limits.inputBytes * 2))
153
- throw new SsconvertError("resource-limit", "ssconvert BIFF property retention limit exceeded");
154
- let encoded = "";
155
- for (let at = 0; at < file.size;) {
156
- const chunk = await file.read(at, Math.min(16384, file.size - at));
157
- encoded += Array.from(chunk, byte => byte.toString(16).padStart(2, "0")).join("");
158
- at += chunk.length;
159
158
  }
160
- const hex = accountText(encoded);
161
- retained.push({ source: "biff", kind: "ole-properties", disposition: "retained", data: { stream: streamName, bytes: hex, modeled } });
162
- await context.diagnostic?.({ code: "biff-loss-warning", severity: "warning", message: `BIFF property stream ${streamName.slice(1)} retained with uninterpreted values` });
159
+ if (unknown && retained && modeled) {
160
+ if (file.size * 2 > (context.limits.workbookTextBytes ?? context.limits.inputBytes * 2))
161
+ throw new SsconvertError("resource-limit", "ssconvert BIFF property retention limit exceeded");
162
+ let encoded = "";
163
+ for (let at = 0; at < file.size;) {
164
+ const chunk = await file.read(at, Math.min(16384, file.size - at));
165
+ encoded += Array.from(chunk, byte => byte.toString(16).padStart(2, "0")).join("");
166
+ at += chunk.length;
167
+ }
168
+ const hex = accountText(encoded);
169
+ retained.push({ source: "biff", kind: "ole-properties", disposition: "retained", data: { stream: streamName, bytes: hex, modeled } });
170
+ await context.diagnostic?.({ code: "biff-loss-warning", severity: "warning", message: `BIFF property stream ${streamName.slice(1)} retained with uninterpreted values` });
171
+ }
172
+ }
173
+ }
174
+ catch (error) {
175
+ try {
176
+ await names?.close();
177
+ }
178
+ catch (cleanup) {
179
+ throw new AggregateError([error, cleanup], 'BIFF property observation cleanup failed');
163
180
  }
181
+ throw error;
164
182
  }
183
+ await names?.close();
165
184
  return properties;
166
185
  }