@taloswork/ose-shared 0.0.2 → 0.0.4
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/mcp/gen/mcp.json +26 -0
- package/package.json +3 -3
- package/skills/document/SKILL.md +11 -7
- package/skills/document/assets/fonts/Anton-Regular.woff2 +0 -0
- package/skills/document/bin/doc-convert.cjs +983 -936
- package/skills/document/bin/doc-gen.cjs +52 -4
- package/skills/document/bin/html2pptx.cjs +34 -10
- package/skills/document/content-pipeline.md +4 -3
- package/skills/document/layouts/README.md +9 -0
- package/skills/document/layouts/bento.tpl +1 -1
- package/skills/document/layouts/big-stat.tpl +1 -1
- package/skills/document/layouts/blocks-2x2.tpl +3 -3
- package/skills/document/layouts/brand-values.tpl +1 -1
- package/skills/document/layouts/cards-3.tpl +1 -1
- package/skills/document/layouts/cards-grid.tpl +1 -1
- package/skills/document/layouts/chart-full.tpl +1 -1
- package/skills/document/layouts/chart-kpi.tpl +1 -1
- package/skills/document/layouts/color-palette.tpl +6 -6
- package/skills/document/layouts/comparison.tpl +2 -2
- package/skills/document/layouts/concept-hub.tpl +1 -1
- package/skills/document/layouts/cover-centered.tpl +1 -1
- package/skills/document/layouts/cover-image.tpl +1 -1
- package/skills/document/layouts/cover-minimal.tpl +1 -1
- package/skills/document/layouts/cover-statement.tpl +1 -1
- package/skills/document/layouts/cover.tpl +1 -1
- package/skills/document/layouts/data-table.tpl +1 -1
- package/skills/document/layouts/dos-donts.tpl +1 -1
- package/skills/document/layouts/editorial-panel.tpl +5 -5
- package/skills/document/layouts/ending-contact.tpl +1 -1
- package/skills/document/layouts/ending.tpl +1 -1
- package/skills/document/layouts/funnel.tpl +1 -1
- package/skills/document/layouts/gantt.tpl +2 -2
- package/skills/document/layouts/hero.tpl +1 -1
- package/skills/document/layouts/icon-row.tpl +1 -1
- package/skills/document/layouts/image-grid.tpl +1 -1
- package/skills/document/layouts/image-left.tpl +1 -1
- package/skills/document/layouts/list.tpl +1 -1
- package/skills/document/layouts/logo-guidelines.tpl +3 -3
- package/skills/document/layouts/map-distribution.tpl +1 -1
- package/skills/document/layouts/map-quad.tpl +1 -1
- package/skills/document/layouts/matrix-2x2.tpl +1 -1
- package/skills/document/layouts/numbered-brief.tpl +3 -3
- package/skills/document/layouts/org-tree.tpl +1 -1
- package/skills/document/layouts/problem-solution-banner.tpl +12 -0
- package/skills/document/layouts/problem-solution.tpl +2 -2
- package/skills/document/layouts/pyramid.tpl +1 -1
- package/skills/document/layouts/quote.tpl +1 -1
- package/skills/document/layouts/radar.tpl +1 -1
- package/skills/document/layouts/ring-progress.tpl +1 -1
- package/skills/document/layouts/section-fullbleed.tpl +8 -0
- package/skills/document/layouts/section-image.tpl +1 -1
- package/skills/document/layouts/section-stat.tpl +1 -1
- package/skills/document/layouts/section.tpl +1 -1
- package/skills/document/layouts/slots.json +763 -1
- package/skills/document/layouts/split-two-col.tpl +1 -1
- package/skills/document/layouts/stats-chart.tpl +2 -2
- package/skills/document/layouts/steps-serpentine.tpl +19 -0
- package/skills/document/layouts/steps-vertical.tpl +1 -1
- package/skills/document/layouts/steps.tpl +1 -1
- package/skills/document/layouts/team-row.tpl +6 -6
- package/skills/document/layouts/three-kpi.tpl +1 -1
- package/skills/document/layouts/timeline.tpl +1 -1
- package/skills/document/layouts/title-meta.tpl +1 -1
- package/skills/document/layouts/title.tpl +1 -1
- package/skills/document/layouts/toc-agenda.tpl +1 -1
- package/skills/document/layouts/toc-panel.tpl +3 -3
- package/skills/document/layouts/toc.tpl +1 -1
- package/skills/document/layouts/transition.tpl +1 -1
- package/skills/document/layouts/two-kpi.tpl +1 -1
- package/skills/document/layouts/type-specimen.tpl +3 -3
- package/skills/document/layouts/versus.tpl +1 -1
- package/skills/document/styles/README.md +42 -6
- package/skills/document/styles/_backdrops/arch.html +5 -0
- package/skills/document/styles/_backdrops/aurora.html +6 -0
- package/skills/document/styles/_backdrops/beam.html +5 -0
- package/skills/document/styles/_backdrops/bloom.html +5 -0
- package/skills/document/styles/_backdrops/duotone.html +6 -0
- package/skills/document/styles/_backdrops/frosted.html +4 -0
- package/skills/document/styles/_backdrops/rimlight.html +7 -0
- package/skills/document/styles/_backdrops/shared.html +5 -0
- package/skills/document/styles/_samples/anthropic.webp +0 -0
- package/skills/document/styles/_samples/apple.webp +0 -0
- package/skills/document/styles/_samples/black-gold.webp +0 -0
- package/skills/document/styles/_samples/branding.webp +0 -0
- package/skills/document/styles/_samples/cinereel.webp +0 -0
- package/skills/document/styles/_samples/cool.webp +0 -0
- package/skills/document/styles/_samples/hand-drawn.webp +0 -0
- package/skills/document/styles/_samples/ivory-gold.webp +0 -0
- package/skills/document/styles/_samples/magazine-ink.webp +0 -0
- package/skills/document/styles/_samples/mckinsey.webp +0 -0
- package/skills/document/styles/_samples/mono.webp +0 -0
- package/skills/document/styles/_samples/olive-gold.webp +0 -0
- package/skills/document/styles/_samples/swiss-grid.webp +0 -0
- package/skills/document/styles/anthropic/skin.css +1 -1
- package/skills/document/styles/apple/skin.css +1 -1
- package/skills/document/styles/black-gold/skin.css +1 -1
- package/skills/document/styles/cinereel/backdrop.html +2 -0
- package/skills/document/styles/cinereel/skin.css +133 -0
- package/skills/document/styles/cool/skin.css +1 -1
- package/skills/document/styles/hand-drawn/skin.css +1 -1
- package/skills/document/styles/ivory-gold/backdrop.html +15 -0
- package/skills/document/styles/ivory-gold/skin.css +137 -0
- package/skills/document/styles/magazine-ink/backdrop.html +12 -0
- package/skills/document/styles/magazine-ink/skin.css +121 -0
- package/skills/document/styles/mckinsey/skin.css +1 -1
- package/skills/document/styles/mono/skin.css +1 -1
- package/skills/document/styles/swiss-grid/backdrop.html +2 -0
- package/skills/document/styles/swiss-grid/skin.css +117 -0
- package/skills/document/themes/README.md +5 -1
- package/skills/document/themes/cinereel.json +24 -0
- package/skills/document/themes/ivory-gold.json +24 -0
- package/skills/document/themes/magazine-ink.json +24 -0
- package/skills/document/themes/swiss-grid.json +24 -0
- package/mcp/Linear/mcp.json +0 -17
- package/skills/document/styles/anthropic/backdrop-arch.html +0 -3
- package/skills/document/styles/anthropic/backdrop-shared.html +0 -3
- package/skills/document/styles/apple/backdrop-shared.html +0 -3
- package/skills/document/styles/cool/backdrop-spotlight.html +0 -3
- package/skills/document/styles/mckinsey/backdrop-shared.html +0 -3
- /package/skills/document/styles/{apple/backdrop-spotlight.html → _backdrops/spotlight.html} +0 -0
|
@@ -148977,7 +148977,7 @@ var import_node_path2 = require("node:path");
|
|
|
148977
148977
|
var import_promises2 = require("node:fs/promises");
|
|
148978
148978
|
|
|
148979
148979
|
// packages/core/dist/fs/doc-convert.js
|
|
148980
|
-
var
|
|
148980
|
+
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
148981
148981
|
var import_mammoth2 = __toESM(require_lib6(), 1);
|
|
148982
148982
|
|
|
148983
148983
|
// packages/core/dist/fs/office-converter.js
|
|
@@ -149052,722 +149052,244 @@ function imageRefsFromRels(relsXml) {
|
|
|
149052
149052
|
return [...relsXml.matchAll(/Type="[^"]*\/image"\s+Target="([^"]+)"/g)].map((m) => m[1]);
|
|
149053
149053
|
}
|
|
149054
149054
|
|
|
149055
|
-
//
|
|
149056
|
-
var
|
|
149057
|
-
|
|
149058
|
-
|
|
149059
|
-
|
|
149060
|
-
|
|
149061
|
-
|
|
149062
|
-
|
|
149063
|
-
|
|
149064
|
-
|
|
149065
|
-
|
|
149066
|
-
|
|
149067
|
-
|
|
149068
|
-
|
|
149069
|
-
|
|
149070
|
-
|
|
149071
|
-
page: { size: "A4", margin: "20mm", header: "", footer: "" },
|
|
149072
|
-
heading: {
|
|
149073
|
-
h1: { size: 20, color: "text", bold: true, spaceAfter: 12 },
|
|
149074
|
-
h2: { size: 15, color: "text", bold: true, spaceAfter: 8 },
|
|
149075
|
-
h3: { size: 13, color: "text", bold: true, spaceAfter: 6 },
|
|
149076
|
-
h4: { size: 11, color: "text", bold: true, spaceAfter: 6 }
|
|
149077
|
-
},
|
|
149078
|
-
body: { size: 11, lineHeight: 1.6, justify: true },
|
|
149079
|
-
cover: { enabled: false, subtitle: "", date: "", logo: "" },
|
|
149080
|
-
pptx: {
|
|
149081
|
-
background: "#ffffff",
|
|
149082
|
-
titleColor: "#1a1a1a",
|
|
149083
|
-
textColor: "",
|
|
149084
|
-
titleSize: 24,
|
|
149085
|
-
bodySize: 16,
|
|
149086
|
-
logo: "",
|
|
149087
|
-
logoPos: { x: 12.2, y: 0.25, w: 0.8, h: 0.8 },
|
|
149088
|
-
footer: "",
|
|
149089
|
-
slideNumber: false,
|
|
149090
|
-
motif: "none",
|
|
149091
|
-
bgWash: false,
|
|
149092
|
-
depth: false
|
|
149055
|
+
// node_modules/docx/dist/index.mjs
|
|
149056
|
+
var __create2 = Object.create;
|
|
149057
|
+
var __defProp2 = Object.defineProperty;
|
|
149058
|
+
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
149059
|
+
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
149060
|
+
var __getProtoOf2 = Object.getPrototypeOf;
|
|
149061
|
+
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
149062
|
+
var __esmMin = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
149063
|
+
var __commonJSMin = (cb2, mod) => () => (mod || (cb2((mod = { exports: {} }).exports, mod), cb2 = null), mod.exports);
|
|
149064
|
+
var __copyProps2 = (to, from, except, desc) => {
|
|
149065
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys2 = __getOwnPropNames2(from), i = 0, n = keys2.length, key; i < n; i++) {
|
|
149066
|
+
key = keys2[i];
|
|
149067
|
+
if (!__hasOwnProp2.call(to, key) && key !== except) __defProp2(to, key, {
|
|
149068
|
+
get: ((k) => from[k]).bind(null, key),
|
|
149069
|
+
enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable
|
|
149070
|
+
});
|
|
149093
149071
|
}
|
|
149072
|
+
return to;
|
|
149094
149073
|
};
|
|
149095
|
-
var
|
|
149096
|
-
|
|
149097
|
-
|
|
149098
|
-
|
|
149074
|
+
var __toESM2 = (mod, isNodeMode, target) => (target = mod != null ? __create2(__getProtoOf2(mod)) : {}, __copyProps2(isNodeMode || !mod || !mod.__esModule ? __defProp2(target, "default", {
|
|
149075
|
+
value: mod,
|
|
149076
|
+
enumerable: true
|
|
149077
|
+
}) : target, mod));
|
|
149078
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) {
|
|
149079
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
149080
|
+
throw Error('Calling `require` for "' + x + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
|
|
149081
|
+
});
|
|
149082
|
+
function _typeof(o) {
|
|
149083
|
+
"@babel/helpers - typeof";
|
|
149084
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o2) {
|
|
149085
|
+
return typeof o2;
|
|
149086
|
+
} : function(o2) {
|
|
149087
|
+
return o2 && "function" == typeof Symbol && o2.constructor === Symbol && o2 !== Symbol.prototype ? "symbol" : typeof o2;
|
|
149088
|
+
}, _typeof(o);
|
|
149099
149089
|
}
|
|
149100
|
-
function
|
|
149101
|
-
if (
|
|
149102
|
-
|
|
149103
|
-
|
|
149104
|
-
|
|
149090
|
+
function toPrimitive(t, r) {
|
|
149091
|
+
if ("object" != _typeof(t) || !t) return t;
|
|
149092
|
+
var e = t[Symbol.toPrimitive];
|
|
149093
|
+
if (void 0 !== e) {
|
|
149094
|
+
var i = e.call(t, r || "default");
|
|
149095
|
+
if ("object" != _typeof(i)) return i;
|
|
149096
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
149097
|
+
}
|
|
149098
|
+
return ("string" === r ? String : Number)(t);
|
|
149105
149099
|
}
|
|
149106
|
-
function
|
|
149107
|
-
|
|
149108
|
-
|
|
149109
|
-
|
|
149110
|
-
|
|
149111
|
-
|
|
149112
|
-
|
|
149113
|
-
|
|
149114
|
-
|
|
149100
|
+
function toPropertyKey(t) {
|
|
149101
|
+
var i = toPrimitive(t, "string");
|
|
149102
|
+
return "symbol" == _typeof(i) ? i : i + "";
|
|
149103
|
+
}
|
|
149104
|
+
function _defineProperty(e, r, t) {
|
|
149105
|
+
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
149106
|
+
value: t,
|
|
149107
|
+
enumerable: true,
|
|
149108
|
+
configurable: true,
|
|
149109
|
+
writable: true
|
|
149110
|
+
}) : e[r] = t, e;
|
|
149111
|
+
}
|
|
149112
|
+
var BaseXmlComponent = class {
|
|
149113
|
+
/**
|
|
149114
|
+
* Creates a new BaseXmlComponent with the specified XML element name.
|
|
149115
|
+
*
|
|
149116
|
+
* @param rootKey - The XML element name (e.g., "w:p", "w:r", "w:t")
|
|
149117
|
+
*/
|
|
149118
|
+
constructor(rootKey) {
|
|
149119
|
+
_defineProperty(
|
|
149120
|
+
this,
|
|
149121
|
+
/** The XML element name for this component (e.g., "w:p" for paragraph). */
|
|
149122
|
+
"rootKey",
|
|
149123
|
+
void 0
|
|
149124
|
+
);
|
|
149125
|
+
this.rootKey = rootKey;
|
|
149115
149126
|
}
|
|
149116
|
-
|
|
149117
|
-
|
|
149118
|
-
|
|
149119
|
-
|
|
149120
|
-
|
|
149121
|
-
|
|
149122
|
-
|
|
149123
|
-
|
|
149124
|
-
|
|
149125
|
-
|
|
149126
|
-
|
|
149127
|
-
|
|
149128
|
-
|
|
149129
|
-
|
|
149130
|
-
|
|
149131
|
-
|
|
149132
|
-
|
|
149133
|
-
|
|
149134
|
-
|
|
149135
|
-
|
|
149136
|
-
|
|
149137
|
-
|
|
149138
|
-
return v;
|
|
149139
|
-
warnings.push(`${path}: expected number in [${min2}, ${max2}]`);
|
|
149140
|
-
return void 0;
|
|
149141
|
-
};
|
|
149142
|
-
const bool = (v, path) => {
|
|
149143
|
-
if (v === void 0)
|
|
149144
|
-
return void 0;
|
|
149145
|
-
if (typeof v === "boolean")
|
|
149146
|
-
return v;
|
|
149147
|
-
warnings.push(`${path}: expected boolean`);
|
|
149148
|
-
return void 0;
|
|
149149
|
-
};
|
|
149150
|
-
t.bestFor = str(src.bestFor, "bestFor") ?? t.bestFor;
|
|
149151
|
-
t.fonts.heading = str(src.fonts?.heading, "fonts.heading") ?? t.fonts.heading;
|
|
149152
|
-
t.fonts.body = str(src.fonts?.body, "fonts.body") ?? t.fonts.body;
|
|
149153
|
-
const colorSet = /* @__PURE__ */ new Set();
|
|
149154
|
-
for (const k of ["primary", "accent", "secondary", "text", "muted", "tableHeaderBg", "tableBorder"]) {
|
|
149155
|
-
const v = src.colors?.[k];
|
|
149156
|
-
if (v === void 0)
|
|
149157
|
-
continue;
|
|
149158
|
-
if (typeof v === "string" && HEX_RE.test(v)) {
|
|
149159
|
-
t.colors[k] = v;
|
|
149160
|
-
colorSet.add(k);
|
|
149161
|
-
} else
|
|
149162
|
-
warnings.push(`colors.${k}: expected "#rrggbb"`);
|
|
149127
|
+
};
|
|
149128
|
+
var EMPTY_OBJECT = Object.seal({});
|
|
149129
|
+
var XmlComponent = class extends BaseXmlComponent {
|
|
149130
|
+
/**
|
|
149131
|
+
* Creates a new XmlComponent.
|
|
149132
|
+
*
|
|
149133
|
+
* @param rootKey - The XML element name (e.g., "w:p", "w:r", "w:t")
|
|
149134
|
+
*/
|
|
149135
|
+
constructor(rootKey) {
|
|
149136
|
+
super(rootKey);
|
|
149137
|
+
_defineProperty(
|
|
149138
|
+
this,
|
|
149139
|
+
/**
|
|
149140
|
+
* Array of child components, text nodes, and attributes.
|
|
149141
|
+
*
|
|
149142
|
+
* This array forms the content of the XML element. It can contain other
|
|
149143
|
+
* XmlComponents, string values (text nodes), or attribute components.
|
|
149144
|
+
*/
|
|
149145
|
+
"root",
|
|
149146
|
+
void 0
|
|
149147
|
+
);
|
|
149148
|
+
this.root = new Array();
|
|
149163
149149
|
}
|
|
149164
|
-
|
|
149165
|
-
|
|
149166
|
-
|
|
149167
|
-
|
|
149168
|
-
|
|
149169
|
-
|
|
149170
|
-
|
|
149171
|
-
|
|
149172
|
-
|
|
149150
|
+
/**
|
|
149151
|
+
* Prepares this component and its children for XML serialization.
|
|
149152
|
+
*
|
|
149153
|
+
* This method is called by the Formatter to convert the component tree into
|
|
149154
|
+
* an object structure compatible with the xml library (https://www.npmjs.com/package/xml).
|
|
149155
|
+
* It recursively processes all children and handles special cases like
|
|
149156
|
+
* attribute-only elements and empty elements.
|
|
149157
|
+
*
|
|
149158
|
+
* The method can be overridden by subclasses to customize XML representation
|
|
149159
|
+
* or execute side effects during serialization (e.g., creating relationships).
|
|
149160
|
+
*
|
|
149161
|
+
* @param context - The serialization context containing document state
|
|
149162
|
+
* @returns The XML-serializable object, or undefined to exclude from output
|
|
149163
|
+
*
|
|
149164
|
+
* @example
|
|
149165
|
+
* ```typescript
|
|
149166
|
+
* // Override to add custom serialization logic
|
|
149167
|
+
* prepForXml(context: IContext): IXmlableObject | undefined {
|
|
149168
|
+
* // Custom logic here
|
|
149169
|
+
* return super.prepForXml(context);
|
|
149170
|
+
* }
|
|
149171
|
+
* ```
|
|
149172
|
+
*/
|
|
149173
|
+
prepForXml(context) {
|
|
149174
|
+
var _children$;
|
|
149175
|
+
context.stack.push(this);
|
|
149176
|
+
const children = this.root.map((comp) => {
|
|
149177
|
+
if (comp instanceof BaseXmlComponent) return comp.prepForXml(context);
|
|
149178
|
+
return comp;
|
|
149179
|
+
}).filter((comp) => comp !== void 0);
|
|
149180
|
+
context.stack.pop();
|
|
149181
|
+
return { [this.rootKey]: children.length ? children.length === 1 && ((_children$ = children[0]) === null || _children$ === void 0 ? void 0 : _children$._attr) ? children[0] : children : EMPTY_OBJECT };
|
|
149173
149182
|
}
|
|
149174
|
-
|
|
149175
|
-
|
|
149176
|
-
|
|
149177
|
-
|
|
149178
|
-
|
|
149183
|
+
/**
|
|
149184
|
+
* Adds a child element to this component.
|
|
149185
|
+
*
|
|
149186
|
+
* @deprecated Do not use this method. It is only used internally by the library. It will be removed in a future version.
|
|
149187
|
+
* @param child - The child component or text string to add
|
|
149188
|
+
* @returns This component (for chaining)
|
|
149189
|
+
*/
|
|
149190
|
+
addChildElement(child) {
|
|
149191
|
+
this.root.push(child);
|
|
149192
|
+
return this;
|
|
149179
149193
|
}
|
|
149180
|
-
|
|
149181
|
-
|
|
149182
|
-
|
|
149183
|
-
|
|
149184
|
-
|
|
149185
|
-
|
|
149186
|
-
if (typeof h !== "object" || h === null) {
|
|
149187
|
-
warnings.push(`heading.${lvl}: expected object`);
|
|
149188
|
-
continue;
|
|
149189
|
-
}
|
|
149190
|
-
t.heading[lvl].size = num(h.size, `heading.${lvl}.size`, 6, 96) ?? t.heading[lvl].size;
|
|
149191
|
-
t.heading[lvl].color = color(h.color, `heading.${lvl}.color`) ?? t.heading[lvl].color;
|
|
149192
|
-
t.heading[lvl].bold = bool(h.bold, `heading.${lvl}.bold`) ?? t.heading[lvl].bold;
|
|
149193
|
-
t.heading[lvl].spaceAfter = num(h.spaceAfter, `heading.${lvl}.spaceAfter`, 0, 96) ?? t.heading[lvl].spaceAfter;
|
|
149194
|
+
};
|
|
149195
|
+
var IgnoreIfEmptyXmlComponent = class extends XmlComponent {
|
|
149196
|
+
constructor(rootKey, includeIfEmpty) {
|
|
149197
|
+
super(rootKey);
|
|
149198
|
+
_defineProperty(this, "includeIfEmpty", void 0);
|
|
149199
|
+
this.includeIfEmpty = includeIfEmpty;
|
|
149194
149200
|
}
|
|
149195
|
-
|
|
149196
|
-
|
|
149197
|
-
|
|
149198
|
-
|
|
149199
|
-
|
|
149200
|
-
|
|
149201
|
-
|
|
149202
|
-
|
|
149203
|
-
|
|
149204
|
-
if (typeof
|
|
149205
|
-
|
|
149206
|
-
|
|
149207
|
-
|
|
149208
|
-
|
|
149209
|
-
|
|
149210
|
-
|
|
149211
|
-
|
|
149212
|
-
|
|
149213
|
-
|
|
149214
|
-
warnings.push(`pptx.${k}: expected "#rrggbb"`);
|
|
149215
|
-
}
|
|
149216
|
-
t.pptx.titleSize = num(p.titleSize, "pptx.titleSize", 8, 60) ?? t.pptx.titleSize;
|
|
149217
|
-
t.pptx.bodySize = num(p.bodySize, "pptx.bodySize", 8, 48) ?? t.pptx.bodySize;
|
|
149218
|
-
t.pptx.logo = str(p.logo, "pptx.logo") ?? t.pptx.logo;
|
|
149219
|
-
if (p.logoPos !== void 0) {
|
|
149220
|
-
const lp = p.logoPos;
|
|
149221
|
-
if (lp && [lp.x, lp.y, lp.w, lp.h].every((v) => isFiniteNum(v) && v >= 0 && v <= 14)) {
|
|
149222
|
-
t.pptx.logoPos = { x: lp.x, y: lp.y, w: lp.w, h: lp.h };
|
|
149223
|
-
} else
|
|
149224
|
-
warnings.push("pptx.logoPos: expected {x,y,w,h} inches within the slide");
|
|
149225
|
-
}
|
|
149226
|
-
t.pptx.footer = str(p.footer, "pptx.footer") ?? t.pptx.footer;
|
|
149227
|
-
t.pptx.slideNumber = bool(p.slideNumber, "pptx.slideNumber") ?? t.pptx.slideNumber;
|
|
149228
|
-
if (p.motif !== void 0) {
|
|
149229
|
-
if (p.motif === "none" || p.motif === "corner" || p.motif === "sidebar")
|
|
149230
|
-
t.pptx.motif = p.motif;
|
|
149231
|
-
else
|
|
149232
|
-
warnings.push('pptx.motif: expected "none" | "corner" | "sidebar"');
|
|
149233
|
-
}
|
|
149234
|
-
t.pptx.bgWash = bool(p.bgWash, "pptx.bgWash") ?? t.pptx.bgWash;
|
|
149235
|
-
t.pptx.depth = bool(p.depth, "pptx.depth") ?? t.pptx.depth;
|
|
149236
|
-
}
|
|
149201
|
+
/**
|
|
149202
|
+
* Prepares the component for XML serialization, excluding it if empty.
|
|
149203
|
+
*
|
|
149204
|
+
* @param context - The serialization context
|
|
149205
|
+
* @returns The XML-serializable object, or undefined if empty
|
|
149206
|
+
*/
|
|
149207
|
+
prepForXml(context) {
|
|
149208
|
+
const result2 = super.prepForXml(context);
|
|
149209
|
+
if (this.includeIfEmpty) return result2;
|
|
149210
|
+
if (result2 && (typeof result2[this.rootKey] !== "object" || Object.keys(result2[this.rootKey]).length)) return result2;
|
|
149211
|
+
}
|
|
149212
|
+
};
|
|
149213
|
+
function ownKeys(e, r) {
|
|
149214
|
+
var t = Object.keys(e);
|
|
149215
|
+
if (Object.getOwnPropertySymbols) {
|
|
149216
|
+
var o = Object.getOwnPropertySymbols(e);
|
|
149217
|
+
r && (o = o.filter(function(r2) {
|
|
149218
|
+
return Object.getOwnPropertyDescriptor(e, r2).enumerable;
|
|
149219
|
+
})), t.push.apply(t, o);
|
|
149237
149220
|
}
|
|
149238
149221
|
return t;
|
|
149239
149222
|
}
|
|
149240
|
-
function
|
|
149241
|
-
|
|
149242
|
-
}
|
|
149243
|
-
|
|
149244
|
-
|
|
149245
|
-
}
|
|
149246
|
-
|
|
149247
|
-
|
|
149248
|
-
var FONT_STACK = 'TalosCJK, "Helvetica Neue", Helvetica, Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", "WenQuanYi Zen Hei", sans-serif';
|
|
149249
|
-
|
|
149250
|
-
// packages/core/dist/fs/doc-convert.js
|
|
149251
|
-
var PRINT_STYLE = `
|
|
149252
|
-
@page { size: A4; margin: 20mm 18mm; }
|
|
149253
|
-
* { box-sizing: border-box; }
|
|
149254
|
-
html { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
|
|
149255
|
-
body { font-family: ${FONT_STACK}; font-size: 11pt; line-height: 1.55; color: #1a1a1a; margin: 0; }
|
|
149256
|
-
h1 { font-size: 20pt; margin: 0 0 10pt; line-height: 1.3; }
|
|
149257
|
-
h2 { font-size: 15.5pt; margin: 14pt 0 6pt; }
|
|
149258
|
-
h3 { font-size: 13pt; margin: 12pt 0 5pt; }
|
|
149259
|
-
h4, h5, h6 { font-size: 11.5pt; margin: 10pt 0 4pt; }
|
|
149260
|
-
p { margin: 0 0 7pt; overflow-wrap: break-word; }
|
|
149261
|
-
ul, ol { margin: 0 0 7pt; padding-left: 22pt; }
|
|
149262
|
-
li { margin: 0 0 3pt; }
|
|
149263
|
-
table { border-collapse: collapse; width: 100%; margin: 8pt 0; font-size: 10.5pt; }
|
|
149264
|
-
th, td { border: 1px solid #b9b9b9; padding: 4pt 8pt; text-align: left; vertical-align: top; }
|
|
149265
|
-
th { background: #f2f2f2; font-weight: 700; }
|
|
149266
|
-
img { max-width: 100%; }
|
|
149267
|
-
.slide { page-break-after: always; }
|
|
149268
|
-
.slide:last-child { page-break-after: auto; }
|
|
149269
|
-
.slide-no { color: #999; font-size: 8pt; margin: 0 0 6pt; }
|
|
149270
|
-
`.trim();
|
|
149271
|
-
function htmlShell(bodyHtml, title) {
|
|
149272
|
-
const head = `<meta charset="utf-8">` + (title ? `<title>${escapeHtml(title)}</title>` : "") + `<style>${PRINT_STYLE}</style>`;
|
|
149273
|
-
return `<!doctype html><html lang="zh"><head>${head}</head><body>${bodyHtml}</body></html>`;
|
|
149274
|
-
}
|
|
149275
|
-
function escapeHtml(s) {
|
|
149276
|
-
return s.replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c]);
|
|
149277
|
-
}
|
|
149278
|
-
function titleFromFilename(filename) {
|
|
149279
|
-
const base = filename.split(/[\\/]/).pop() ?? filename;
|
|
149280
|
-
const stem = base.replace(/\.[^.]+$/, "").trim();
|
|
149281
|
-
return stem || void 0;
|
|
149282
|
-
}
|
|
149283
|
-
function htmlToParagraphs(html) {
|
|
149284
|
-
const text = html.replace(/<\/(h[1-6]|p|li|tr)>/gi, "\n").replace(/<br[^>]*\/?>/gi, "\n").replace(/<\/t[dh]>/gi, " ").replace(/<[^>]+>/g, "").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/&/g, "&").replace(/ /g, " ");
|
|
149285
|
-
return text.split(/\n+/).map((line) => line.replace(/\t+/g, " ").trim()).filter((line) => line.length > 0);
|
|
149286
|
-
}
|
|
149287
|
-
async function convertDocxToHtml(buffer, filename) {
|
|
149288
|
-
const result2 = await import_mammoth2.default.convertToHtml({ buffer: Buffer.from(buffer) }, {
|
|
149289
|
-
convertImage: import_mammoth2.default.images.imgElement(async (image) => ({
|
|
149290
|
-
src: `data:${image.contentType};base64,${await image.read("base64")}`
|
|
149291
|
-
}))
|
|
149292
|
-
});
|
|
149293
|
-
const bodyHtml = result2.value;
|
|
149294
|
-
return {
|
|
149295
|
-
kind: "docx",
|
|
149296
|
-
html: htmlShell(bodyHtml, titleFromFilename(filename)),
|
|
149297
|
-
fallbackSpec: { title: titleFromFilename(filename), paragraphs: htmlToParagraphs(bodyHtml) },
|
|
149298
|
-
warnings: (result2.messages ?? []).map((m) => `${m.type ?? "warning"}: ${m.message ?? ""}`)
|
|
149299
|
-
};
|
|
149300
|
-
}
|
|
149301
|
-
async function convertPptxToHtml(buffer, filename) {
|
|
149302
|
-
const zip = await import_jszip2.default.loadAsync(buffer);
|
|
149303
|
-
const slideFiles = Object.keys(zip.files).filter((f) => /^ppt\/slides\/slide\d+\.xml$/.test(f)).sort((a, b) => slideNumber(a) - slideNumber(b));
|
|
149304
|
-
const sections = [];
|
|
149305
|
-
const fallbackParagraphs = [];
|
|
149306
|
-
for (const slidePath of slideFiles) {
|
|
149307
|
-
const num = slideNumber(slidePath);
|
|
149308
|
-
const xml = await zip.file(slidePath).async("string");
|
|
149309
|
-
const paragraphs = extractSlideText(xml).split("\n").filter(Boolean);
|
|
149310
|
-
const imgs = [];
|
|
149311
|
-
const relsPath = `ppt/slides/_rels/slide${num}.xml.rels`;
|
|
149312
|
-
const relsFile = zip.file(relsPath);
|
|
149313
|
-
if (relsFile) {
|
|
149314
|
-
for (const ref of imageRefsFromRels(await relsFile.async("string"))) {
|
|
149315
|
-
const mediaPath = resolveRelTarget(relsPath, ref);
|
|
149316
|
-
const media = zip.file(mediaPath);
|
|
149317
|
-
if (!media)
|
|
149318
|
-
continue;
|
|
149319
|
-
imgs.push(`<img src="data:${mimeFromPath(mediaPath)};base64,${await media.async("base64")}" alt="">`);
|
|
149320
|
-
}
|
|
149321
|
-
}
|
|
149322
|
-
sections.push(`<section class="slide"><div class="slide-no">${num} / ${slideFiles.length}</div>` + paragraphs.map((p) => `<p>${escapeHtml(p)}</p>`).join("") + imgs.join("") + `</section>`);
|
|
149323
|
-
fallbackParagraphs.push(`[\u5E7B\u706F\u7247 ${num}]`, ...paragraphs);
|
|
149223
|
+
function _objectSpread2(e) {
|
|
149224
|
+
for (var r = 1; r < arguments.length; r++) {
|
|
149225
|
+
var t = null != arguments[r] ? arguments[r] : {};
|
|
149226
|
+
r % 2 ? ownKeys(Object(t), true).forEach(function(r2) {
|
|
149227
|
+
_defineProperty(e, r2, t[r2]);
|
|
149228
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r2) {
|
|
149229
|
+
Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
|
|
149230
|
+
});
|
|
149324
149231
|
}
|
|
149325
|
-
return
|
|
149326
|
-
kind: "pptx",
|
|
149327
|
-
html: htmlShell(sections.join("\n"), titleFromFilename(filename)),
|
|
149328
|
-
fallbackSpec: { title: titleFromFilename(filename), paragraphs: fallbackParagraphs },
|
|
149329
|
-
warnings: ["pptx conversion is one page per slide (text + images); in-slide layout is not reproduced"]
|
|
149330
|
-
};
|
|
149232
|
+
return e;
|
|
149331
149233
|
}
|
|
149332
|
-
|
|
149333
|
-
|
|
149334
|
-
|
|
149335
|
-
|
|
149336
|
-
|
|
149234
|
+
var XmlAttributeComponent = class extends BaseXmlComponent {
|
|
149235
|
+
/**
|
|
149236
|
+
* Creates a new attribute component.
|
|
149237
|
+
*
|
|
149238
|
+
* @param root - The attribute data object
|
|
149239
|
+
*/
|
|
149240
|
+
constructor(root2) {
|
|
149241
|
+
super("_attr");
|
|
149242
|
+
_defineProperty(this, "root", void 0);
|
|
149243
|
+
_defineProperty(
|
|
149244
|
+
this,
|
|
149245
|
+
/** Optional mapping from property names to XML attribute names. */
|
|
149246
|
+
"xmlKeys",
|
|
149247
|
+
void 0
|
|
149248
|
+
);
|
|
149249
|
+
this.root = root2;
|
|
149337
149250
|
}
|
|
149338
|
-
|
|
149339
|
-
|
|
149340
|
-
|
|
149341
|
-
|
|
149342
|
-
|
|
149343
|
-
|
|
149344
|
-
|
|
149251
|
+
/**
|
|
149252
|
+
* Converts the attribute data to an XML-serializable object.
|
|
149253
|
+
*
|
|
149254
|
+
* This method transforms the property names using xmlKeys (if defined)
|
|
149255
|
+
* and filters out undefined values.
|
|
149256
|
+
*
|
|
149257
|
+
* @param _ - Context (unused for attributes)
|
|
149258
|
+
* @returns Object with _attr key containing the mapped attributes
|
|
149259
|
+
*/
|
|
149260
|
+
prepForXml(_4) {
|
|
149261
|
+
const attrs = {};
|
|
149262
|
+
Object.entries(this.root).forEach(([key, value]) => {
|
|
149263
|
+
if (value !== void 0) {
|
|
149264
|
+
const newKey = this.xmlKeys && this.xmlKeys[key] || key;
|
|
149265
|
+
attrs[newKey] = value;
|
|
149266
|
+
}
|
|
149267
|
+
});
|
|
149268
|
+
return { _attr: attrs };
|
|
149345
149269
|
}
|
|
149346
|
-
|
|
149347
|
-
|
|
149348
|
-
|
|
149349
|
-
|
|
149350
|
-
|
|
149351
|
-
|
|
149352
|
-
|
|
149353
|
-
|
|
149270
|
+
};
|
|
149271
|
+
var NextAttributeComponent = class extends BaseXmlComponent {
|
|
149272
|
+
/**
|
|
149273
|
+
* Creates a new NextAttributeComponent.
|
|
149274
|
+
*
|
|
149275
|
+
* @param root - Attribute payload with explicit key-value mappings
|
|
149276
|
+
*/
|
|
149277
|
+
constructor(root2) {
|
|
149278
|
+
super("_attr");
|
|
149279
|
+
_defineProperty(this, "root", void 0);
|
|
149280
|
+
this.root = root2;
|
|
149354
149281
|
}
|
|
149355
|
-
|
|
149356
|
-
|
|
149357
|
-
|
|
149358
|
-
|
|
149359
|
-
|
|
149360
|
-
|
|
149361
|
-
|
|
149362
|
-
|
|
149363
|
-
|
|
149364
|
-
|
|
149365
|
-
|
|
149366
|
-
var import_node_path = require("node:path");
|
|
149367
|
-
var import_node_url = require("node:url");
|
|
149368
|
-
var MAC_CANDIDATES = ["/Applications/LibreOffice.app/Contents/MacOS/soffice"];
|
|
149369
|
-
var WIN_CANDIDATES = [
|
|
149370
|
-
"C:\\Program Files\\LibreOffice\\program\\soffice.com",
|
|
149371
|
-
"C:\\Program Files (x86)\\LibreOffice\\program\\soffice.com"
|
|
149372
|
-
];
|
|
149373
|
-
var PATH_NAMES = {
|
|
149374
|
-
win32: ["soffice.com", "soffice.exe"],
|
|
149375
|
-
darwin: ["soffice"],
|
|
149376
|
-
linux: ["soffice", "libreoffice"]
|
|
149377
|
-
};
|
|
149378
|
-
var SOFFICE_DISABLE_VALUES = /* @__PURE__ */ new Set(["off", "none", "0", "false", "disabled"]);
|
|
149379
|
-
function resolveSoffice(deps = {}) {
|
|
149380
|
-
const env2 = deps.env ?? process.env;
|
|
149381
|
-
const platform = deps.platform ?? process.platform;
|
|
149382
|
-
const exists = deps.exists ?? import_node_fs.existsSync;
|
|
149383
|
-
const override = env2.TALOS_SOFFICE;
|
|
149384
|
-
if (override && SOFFICE_DISABLE_VALUES.has(override.trim().toLowerCase()))
|
|
149385
|
-
return null;
|
|
149386
|
-
if (override && exists(override))
|
|
149387
|
-
return override;
|
|
149388
|
-
const installed = platform === "darwin" ? MAC_CANDIDATES : platform === "win32" ? WIN_CANDIDATES : [];
|
|
149389
|
-
for (const c of installed)
|
|
149390
|
-
if (exists(c))
|
|
149391
|
-
return c;
|
|
149392
|
-
const pathMod = platform === "win32" ? import_node_path.win32 : import_node_path.posix;
|
|
149393
|
-
const names = PATH_NAMES[platform] ?? PATH_NAMES.linux;
|
|
149394
|
-
for (const dir of (env2.PATH ?? "").split(pathMod.delimiter)) {
|
|
149395
|
-
if (!dir)
|
|
149396
|
-
continue;
|
|
149397
|
-
for (const name of names) {
|
|
149398
|
-
const p = pathMod.join(dir, name);
|
|
149399
|
-
if (exists(p))
|
|
149400
|
-
return p;
|
|
149401
|
-
}
|
|
149402
|
-
}
|
|
149403
|
-
return null;
|
|
149404
|
-
}
|
|
149405
|
-
var PDF_FILTER_BY_EXT = {
|
|
149406
|
-
".docx": "writer_pdf_Export",
|
|
149407
|
-
".doc": "writer_pdf_Export",
|
|
149408
|
-
".odt": "writer_pdf_Export",
|
|
149409
|
-
".rtf": "writer_pdf_Export",
|
|
149410
|
-
".txt": "writer_pdf_Export",
|
|
149411
|
-
".html": "writer_pdf_Export",
|
|
149412
|
-
".htm": "writer_pdf_Export",
|
|
149413
|
-
".pptx": "impress_pdf_Export",
|
|
149414
|
-
".ppt": "impress_pdf_Export",
|
|
149415
|
-
".odp": "impress_pdf_Export",
|
|
149416
|
-
".xlsx": "calc_pdf_Export",
|
|
149417
|
-
".xls": "calc_pdf_Export",
|
|
149418
|
-
".ods": "calc_pdf_Export",
|
|
149419
|
-
".csv": "calc_pdf_Export"
|
|
149420
|
-
};
|
|
149421
|
-
var PDF_EXPORT_FILTER_DATA = { EmbedStandardFonts: { type: "boolean", value: "true" } };
|
|
149422
|
-
function pdfExportArg(inputPath) {
|
|
149423
|
-
const filter2 = PDF_FILTER_BY_EXT[(0, import_node_path.extname)(inputPath).toLowerCase()];
|
|
149424
|
-
if (!filter2)
|
|
149425
|
-
return "pdf";
|
|
149426
|
-
return `pdf:${filter2}:${JSON.stringify(PDF_EXPORT_FILTER_DATA)}`;
|
|
149427
|
-
}
|
|
149428
|
-
function sofficeTimeoutMs(bytes) {
|
|
149429
|
-
const base = 9e4;
|
|
149430
|
-
const perMb = 12e3;
|
|
149431
|
-
const mb = Math.max(0, bytes) / (1024 * 1024);
|
|
149432
|
-
return Math.min(6e5, Math.round(base + mb * perMb));
|
|
149433
|
-
}
|
|
149434
|
-
function pickConvertedPdf(pdfNames, inputPath) {
|
|
149435
|
-
if (pdfNames.length === 0)
|
|
149436
|
-
return null;
|
|
149437
|
-
const stem = (0, import_node_path.basename)(inputPath, (0, import_node_path.extname)(inputPath)).toLowerCase();
|
|
149438
|
-
const nameStem = (n) => (0, import_node_path.basename)(n, (0, import_node_path.extname)(n)).toLowerCase();
|
|
149439
|
-
const exact = pdfNames.find((n) => nameStem(n) === stem);
|
|
149440
|
-
if (exact)
|
|
149441
|
-
return exact;
|
|
149442
|
-
if (pdfNames.length === 1)
|
|
149443
|
-
return pdfNames[0];
|
|
149444
|
-
const related = pdfNames.find((n) => nameStem(n).startsWith(stem) || stem.startsWith(nameStem(n)));
|
|
149445
|
-
return related ?? [...pdfNames].sort()[0];
|
|
149446
|
-
}
|
|
149447
|
-
async function convertToPdfViaSoffice(inputPath, options = {}) {
|
|
149448
|
-
const soffice = options.sofficePath ?? resolveSoffice();
|
|
149449
|
-
if (!soffice)
|
|
149450
|
-
throw new Error("LibreOffice (soffice) not found");
|
|
149451
|
-
if (!(0, import_node_fs.existsSync)(inputPath))
|
|
149452
|
-
throw new Error(`input not found: ${inputPath}`);
|
|
149453
|
-
const profileDir = await (0, import_promises.mkdtemp)((0, import_node_path.join)((0, import_node_os.tmpdir)(), "talos-lo-profile-"));
|
|
149454
|
-
const outDir = await (0, import_promises.mkdtemp)((0, import_node_path.join)((0, import_node_os.tmpdir)(), "talos-lo-out-"));
|
|
149455
|
-
try {
|
|
149456
|
-
await runSoffice(soffice, [
|
|
149457
|
-
"--headless",
|
|
149458
|
-
"--norestore",
|
|
149459
|
-
"--nolockcheck",
|
|
149460
|
-
"--nodefault",
|
|
149461
|
-
"--nofirststartwizard",
|
|
149462
|
-
`-env:UserInstallation=${(0, import_node_url.pathToFileURL)(profileDir).href}`,
|
|
149463
|
-
"--convert-to",
|
|
149464
|
-
pdfExportArg(inputPath),
|
|
149465
|
-
"--outdir",
|
|
149466
|
-
outDir,
|
|
149467
|
-
inputPath
|
|
149468
|
-
], options.timeoutMs ?? sofficeTimeoutMs((0, import_node_fs.statSync)(inputPath).size));
|
|
149469
|
-
const pdfs = (await (0, import_promises.readdir)(outDir)).filter((f) => f.toLowerCase().endsWith(".pdf"));
|
|
149470
|
-
const chosen = pickConvertedPdf(pdfs, inputPath);
|
|
149471
|
-
if (!chosen)
|
|
149472
|
-
throw new Error("LibreOffice produced no PDF (unsupported input?)");
|
|
149473
|
-
return await (0, import_promises.readFile)((0, import_node_path.join)(outDir, chosen));
|
|
149474
|
-
} finally {
|
|
149475
|
-
await (0, import_promises.rm)(profileDir, { recursive: true, force: true }).catch(() => {
|
|
149476
|
-
});
|
|
149477
|
-
await (0, import_promises.rm)(outDir, { recursive: true, force: true }).catch(() => {
|
|
149478
|
-
});
|
|
149479
|
-
}
|
|
149480
|
-
}
|
|
149481
|
-
function runSoffice(bin, args, timeoutMs) {
|
|
149482
|
-
return new Promise((resolve, reject2) => {
|
|
149483
|
-
const child = (0, import_node_child_process.spawn)(bin, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
149484
|
-
let stderr = "";
|
|
149485
|
-
const timer = setTimeout(() => {
|
|
149486
|
-
child.kill("SIGKILL");
|
|
149487
|
-
reject2(new Error(`LibreOffice timed out after ${timeoutMs}ms`));
|
|
149488
|
-
}, timeoutMs);
|
|
149489
|
-
child.stderr?.on("data", (c) => {
|
|
149490
|
-
if (stderr.length < 4096)
|
|
149491
|
-
stderr += String(c);
|
|
149492
|
-
});
|
|
149493
|
-
child.on("error", (err) => {
|
|
149494
|
-
clearTimeout(timer);
|
|
149495
|
-
reject2(err);
|
|
149496
|
-
});
|
|
149497
|
-
child.on("close", (code) => {
|
|
149498
|
-
clearTimeout(timer);
|
|
149499
|
-
if (code === 0)
|
|
149500
|
-
resolve();
|
|
149501
|
-
else
|
|
149502
|
-
reject2(new Error(`LibreOffice exited ${code}${stderr ? `: ${stderr.trim()}` : ""}`));
|
|
149503
|
-
});
|
|
149504
|
-
});
|
|
149505
|
-
}
|
|
149506
|
-
|
|
149507
|
-
// packages/core/dist/fs/office-service.js
|
|
149508
|
-
async function convertViaOfficeService(bytes, filename, url, options = {}) {
|
|
149509
|
-
const doFetch = options.fetchImpl ?? fetch;
|
|
149510
|
-
const view = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
|
|
149511
|
-
const part = new Uint8Array(view.byteLength);
|
|
149512
|
-
part.set(view);
|
|
149513
|
-
const form = new FormData();
|
|
149514
|
-
form.append("files", new Blob([part]), filename);
|
|
149515
|
-
const controller = new AbortController();
|
|
149516
|
-
const timer = options.timeoutMs && options.timeoutMs > 0 ? setTimeout(() => controller.abort(), options.timeoutMs) : void 0;
|
|
149517
|
-
try {
|
|
149518
|
-
const res = await doFetch(url, {
|
|
149519
|
-
method: "POST",
|
|
149520
|
-
headers: options.token ? { authorization: `Bearer ${options.token}` } : {},
|
|
149521
|
-
body: form,
|
|
149522
|
-
signal: controller.signal
|
|
149523
|
-
});
|
|
149524
|
-
if (!res.ok)
|
|
149525
|
-
throw new Error(`office service HTTP ${res.status}`);
|
|
149526
|
-
return new Uint8Array(await res.arrayBuffer());
|
|
149527
|
-
} finally {
|
|
149528
|
-
if (timer)
|
|
149529
|
-
clearTimeout(timer);
|
|
149530
|
-
}
|
|
149531
|
-
}
|
|
149532
|
-
|
|
149533
|
-
// node_modules/docx/dist/index.mjs
|
|
149534
|
-
var __create2 = Object.create;
|
|
149535
|
-
var __defProp2 = Object.defineProperty;
|
|
149536
|
-
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
149537
|
-
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
149538
|
-
var __getProtoOf2 = Object.getPrototypeOf;
|
|
149539
|
-
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
149540
|
-
var __esmMin = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
149541
|
-
var __commonJSMin = (cb2, mod) => () => (mod || (cb2((mod = { exports: {} }).exports, mod), cb2 = null), mod.exports);
|
|
149542
|
-
var __copyProps2 = (to, from, except, desc) => {
|
|
149543
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys2 = __getOwnPropNames2(from), i = 0, n = keys2.length, key; i < n; i++) {
|
|
149544
|
-
key = keys2[i];
|
|
149545
|
-
if (!__hasOwnProp2.call(to, key) && key !== except) __defProp2(to, key, {
|
|
149546
|
-
get: ((k) => from[k]).bind(null, key),
|
|
149547
|
-
enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable
|
|
149548
|
-
});
|
|
149549
|
-
}
|
|
149550
|
-
return to;
|
|
149551
|
-
};
|
|
149552
|
-
var __toESM2 = (mod, isNodeMode, target) => (target = mod != null ? __create2(__getProtoOf2(mod)) : {}, __copyProps2(isNodeMode || !mod || !mod.__esModule ? __defProp2(target, "default", {
|
|
149553
|
-
value: mod,
|
|
149554
|
-
enumerable: true
|
|
149555
|
-
}) : target, mod));
|
|
149556
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) {
|
|
149557
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
149558
|
-
throw Error('Calling `require` for "' + x + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
|
|
149559
|
-
});
|
|
149560
|
-
function _typeof(o) {
|
|
149561
|
-
"@babel/helpers - typeof";
|
|
149562
|
-
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o2) {
|
|
149563
|
-
return typeof o2;
|
|
149564
|
-
} : function(o2) {
|
|
149565
|
-
return o2 && "function" == typeof Symbol && o2.constructor === Symbol && o2 !== Symbol.prototype ? "symbol" : typeof o2;
|
|
149566
|
-
}, _typeof(o);
|
|
149567
|
-
}
|
|
149568
|
-
function toPrimitive(t, r) {
|
|
149569
|
-
if ("object" != _typeof(t) || !t) return t;
|
|
149570
|
-
var e = t[Symbol.toPrimitive];
|
|
149571
|
-
if (void 0 !== e) {
|
|
149572
|
-
var i = e.call(t, r || "default");
|
|
149573
|
-
if ("object" != _typeof(i)) return i;
|
|
149574
|
-
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
149575
|
-
}
|
|
149576
|
-
return ("string" === r ? String : Number)(t);
|
|
149577
|
-
}
|
|
149578
|
-
function toPropertyKey(t) {
|
|
149579
|
-
var i = toPrimitive(t, "string");
|
|
149580
|
-
return "symbol" == _typeof(i) ? i : i + "";
|
|
149581
|
-
}
|
|
149582
|
-
function _defineProperty(e, r, t) {
|
|
149583
|
-
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
149584
|
-
value: t,
|
|
149585
|
-
enumerable: true,
|
|
149586
|
-
configurable: true,
|
|
149587
|
-
writable: true
|
|
149588
|
-
}) : e[r] = t, e;
|
|
149589
|
-
}
|
|
149590
|
-
var BaseXmlComponent = class {
|
|
149591
|
-
/**
|
|
149592
|
-
* Creates a new BaseXmlComponent with the specified XML element name.
|
|
149593
|
-
*
|
|
149594
|
-
* @param rootKey - The XML element name (e.g., "w:p", "w:r", "w:t")
|
|
149595
|
-
*/
|
|
149596
|
-
constructor(rootKey) {
|
|
149597
|
-
_defineProperty(
|
|
149598
|
-
this,
|
|
149599
|
-
/** The XML element name for this component (e.g., "w:p" for paragraph). */
|
|
149600
|
-
"rootKey",
|
|
149601
|
-
void 0
|
|
149602
|
-
);
|
|
149603
|
-
this.rootKey = rootKey;
|
|
149604
|
-
}
|
|
149605
|
-
};
|
|
149606
|
-
var EMPTY_OBJECT = Object.seal({});
|
|
149607
|
-
var XmlComponent = class extends BaseXmlComponent {
|
|
149608
|
-
/**
|
|
149609
|
-
* Creates a new XmlComponent.
|
|
149610
|
-
*
|
|
149611
|
-
* @param rootKey - The XML element name (e.g., "w:p", "w:r", "w:t")
|
|
149612
|
-
*/
|
|
149613
|
-
constructor(rootKey) {
|
|
149614
|
-
super(rootKey);
|
|
149615
|
-
_defineProperty(
|
|
149616
|
-
this,
|
|
149617
|
-
/**
|
|
149618
|
-
* Array of child components, text nodes, and attributes.
|
|
149619
|
-
*
|
|
149620
|
-
* This array forms the content of the XML element. It can contain other
|
|
149621
|
-
* XmlComponents, string values (text nodes), or attribute components.
|
|
149622
|
-
*/
|
|
149623
|
-
"root",
|
|
149624
|
-
void 0
|
|
149625
|
-
);
|
|
149626
|
-
this.root = new Array();
|
|
149627
|
-
}
|
|
149628
|
-
/**
|
|
149629
|
-
* Prepares this component and its children for XML serialization.
|
|
149630
|
-
*
|
|
149631
|
-
* This method is called by the Formatter to convert the component tree into
|
|
149632
|
-
* an object structure compatible with the xml library (https://www.npmjs.com/package/xml).
|
|
149633
|
-
* It recursively processes all children and handles special cases like
|
|
149634
|
-
* attribute-only elements and empty elements.
|
|
149635
|
-
*
|
|
149636
|
-
* The method can be overridden by subclasses to customize XML representation
|
|
149637
|
-
* or execute side effects during serialization (e.g., creating relationships).
|
|
149638
|
-
*
|
|
149639
|
-
* @param context - The serialization context containing document state
|
|
149640
|
-
* @returns The XML-serializable object, or undefined to exclude from output
|
|
149641
|
-
*
|
|
149642
|
-
* @example
|
|
149643
|
-
* ```typescript
|
|
149644
|
-
* // Override to add custom serialization logic
|
|
149645
|
-
* prepForXml(context: IContext): IXmlableObject | undefined {
|
|
149646
|
-
* // Custom logic here
|
|
149647
|
-
* return super.prepForXml(context);
|
|
149648
|
-
* }
|
|
149649
|
-
* ```
|
|
149650
|
-
*/
|
|
149651
|
-
prepForXml(context) {
|
|
149652
|
-
var _children$;
|
|
149653
|
-
context.stack.push(this);
|
|
149654
|
-
const children = this.root.map((comp) => {
|
|
149655
|
-
if (comp instanceof BaseXmlComponent) return comp.prepForXml(context);
|
|
149656
|
-
return comp;
|
|
149657
|
-
}).filter((comp) => comp !== void 0);
|
|
149658
|
-
context.stack.pop();
|
|
149659
|
-
return { [this.rootKey]: children.length ? children.length === 1 && ((_children$ = children[0]) === null || _children$ === void 0 ? void 0 : _children$._attr) ? children[0] : children : EMPTY_OBJECT };
|
|
149660
|
-
}
|
|
149661
|
-
/**
|
|
149662
|
-
* Adds a child element to this component.
|
|
149663
|
-
*
|
|
149664
|
-
* @deprecated Do not use this method. It is only used internally by the library. It will be removed in a future version.
|
|
149665
|
-
* @param child - The child component or text string to add
|
|
149666
|
-
* @returns This component (for chaining)
|
|
149667
|
-
*/
|
|
149668
|
-
addChildElement(child) {
|
|
149669
|
-
this.root.push(child);
|
|
149670
|
-
return this;
|
|
149671
|
-
}
|
|
149672
|
-
};
|
|
149673
|
-
var IgnoreIfEmptyXmlComponent = class extends XmlComponent {
|
|
149674
|
-
constructor(rootKey, includeIfEmpty) {
|
|
149675
|
-
super(rootKey);
|
|
149676
|
-
_defineProperty(this, "includeIfEmpty", void 0);
|
|
149677
|
-
this.includeIfEmpty = includeIfEmpty;
|
|
149678
|
-
}
|
|
149679
|
-
/**
|
|
149680
|
-
* Prepares the component for XML serialization, excluding it if empty.
|
|
149681
|
-
*
|
|
149682
|
-
* @param context - The serialization context
|
|
149683
|
-
* @returns The XML-serializable object, or undefined if empty
|
|
149684
|
-
*/
|
|
149685
|
-
prepForXml(context) {
|
|
149686
|
-
const result2 = super.prepForXml(context);
|
|
149687
|
-
if (this.includeIfEmpty) return result2;
|
|
149688
|
-
if (result2 && (typeof result2[this.rootKey] !== "object" || Object.keys(result2[this.rootKey]).length)) return result2;
|
|
149689
|
-
}
|
|
149690
|
-
};
|
|
149691
|
-
function ownKeys(e, r) {
|
|
149692
|
-
var t = Object.keys(e);
|
|
149693
|
-
if (Object.getOwnPropertySymbols) {
|
|
149694
|
-
var o = Object.getOwnPropertySymbols(e);
|
|
149695
|
-
r && (o = o.filter(function(r2) {
|
|
149696
|
-
return Object.getOwnPropertyDescriptor(e, r2).enumerable;
|
|
149697
|
-
})), t.push.apply(t, o);
|
|
149698
|
-
}
|
|
149699
|
-
return t;
|
|
149700
|
-
}
|
|
149701
|
-
function _objectSpread2(e) {
|
|
149702
|
-
for (var r = 1; r < arguments.length; r++) {
|
|
149703
|
-
var t = null != arguments[r] ? arguments[r] : {};
|
|
149704
|
-
r % 2 ? ownKeys(Object(t), true).forEach(function(r2) {
|
|
149705
|
-
_defineProperty(e, r2, t[r2]);
|
|
149706
|
-
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r2) {
|
|
149707
|
-
Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
|
|
149708
|
-
});
|
|
149709
|
-
}
|
|
149710
|
-
return e;
|
|
149711
|
-
}
|
|
149712
|
-
var XmlAttributeComponent = class extends BaseXmlComponent {
|
|
149713
|
-
/**
|
|
149714
|
-
* Creates a new attribute component.
|
|
149715
|
-
*
|
|
149716
|
-
* @param root - The attribute data object
|
|
149717
|
-
*/
|
|
149718
|
-
constructor(root2) {
|
|
149719
|
-
super("_attr");
|
|
149720
|
-
_defineProperty(this, "root", void 0);
|
|
149721
|
-
_defineProperty(
|
|
149722
|
-
this,
|
|
149723
|
-
/** Optional mapping from property names to XML attribute names. */
|
|
149724
|
-
"xmlKeys",
|
|
149725
|
-
void 0
|
|
149726
|
-
);
|
|
149727
|
-
this.root = root2;
|
|
149728
|
-
}
|
|
149729
|
-
/**
|
|
149730
|
-
* Converts the attribute data to an XML-serializable object.
|
|
149731
|
-
*
|
|
149732
|
-
* This method transforms the property names using xmlKeys (if defined)
|
|
149733
|
-
* and filters out undefined values.
|
|
149734
|
-
*
|
|
149735
|
-
* @param _ - Context (unused for attributes)
|
|
149736
|
-
* @returns Object with _attr key containing the mapped attributes
|
|
149737
|
-
*/
|
|
149738
|
-
prepForXml(_4) {
|
|
149739
|
-
const attrs = {};
|
|
149740
|
-
Object.entries(this.root).forEach(([key, value]) => {
|
|
149741
|
-
if (value !== void 0) {
|
|
149742
|
-
const newKey = this.xmlKeys && this.xmlKeys[key] || key;
|
|
149743
|
-
attrs[newKey] = value;
|
|
149744
|
-
}
|
|
149745
|
-
});
|
|
149746
|
-
return { _attr: attrs };
|
|
149747
|
-
}
|
|
149748
|
-
};
|
|
149749
|
-
var NextAttributeComponent = class extends BaseXmlComponent {
|
|
149750
|
-
/**
|
|
149751
|
-
* Creates a new NextAttributeComponent.
|
|
149752
|
-
*
|
|
149753
|
-
* @param root - Attribute payload with explicit key-value mappings
|
|
149754
|
-
*/
|
|
149755
|
-
constructor(root2) {
|
|
149756
|
-
super("_attr");
|
|
149757
|
-
_defineProperty(this, "root", void 0);
|
|
149758
|
-
this.root = root2;
|
|
149759
|
-
}
|
|
149760
|
-
/**
|
|
149761
|
-
* Converts the attribute payload to an XML-serializable object.
|
|
149762
|
-
*
|
|
149763
|
-
* Extracts the key and value from each property and filters out
|
|
149764
|
-
* undefined values.
|
|
149765
|
-
*
|
|
149766
|
-
* @param _ - Context (unused for attributes)
|
|
149767
|
-
* @returns Object with _attr key containing the attributes
|
|
149768
|
-
*/
|
|
149769
|
-
prepForXml(_4) {
|
|
149770
|
-
return { _attr: Object.values(this.root).filter(({ value }) => value !== void 0).reduce((acc, { key, value }) => _objectSpread2(_objectSpread2({}, acc), {}, { [key]: value }), {}) };
|
|
149282
|
+
/**
|
|
149283
|
+
* Converts the attribute payload to an XML-serializable object.
|
|
149284
|
+
*
|
|
149285
|
+
* Extracts the key and value from each property and filters out
|
|
149286
|
+
* undefined values.
|
|
149287
|
+
*
|
|
149288
|
+
* @param _ - Context (unused for attributes)
|
|
149289
|
+
* @returns Object with _attr key containing the attributes
|
|
149290
|
+
*/
|
|
149291
|
+
prepForXml(_4) {
|
|
149292
|
+
return { _attr: Object.values(this.root).filter(({ value }) => value !== void 0).reduce((acc, { key, value }) => _objectSpread2(_objectSpread2({}, acc), {}, { [key]: value }), {}) };
|
|
149771
149293
|
}
|
|
149772
149294
|
};
|
|
149773
149295
|
var Attributes = class extends XmlAttributeComponent {
|
|
@@ -168581,11 +168103,203 @@ var findPatchKeys = (text) => {
|
|
|
168581
168103
|
|
|
168582
168104
|
// packages/core/dist/fs/doc-gen.js
|
|
168583
168105
|
var import_exceljs = __toESM(require_excel(), 1);
|
|
168584
|
-
var
|
|
168106
|
+
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
168585
168107
|
var import_pptxgenjs = __toESM(require_pptxgen_cjs(), 1);
|
|
168586
168108
|
var import_pdf_lib = __toESM(require_cjs(), 1);
|
|
168587
168109
|
var import_fontkit = __toESM(require_fontkit_umd(), 1);
|
|
168588
|
-
var
|
|
168110
|
+
var import_node_fs = require("node:fs");
|
|
168111
|
+
|
|
168112
|
+
// packages/core/dist/fs/doc-theme.js
|
|
168113
|
+
var DEFAULT_THEME = {
|
|
168114
|
+
bestFor: "",
|
|
168115
|
+
fonts: { heading: "", body: "" },
|
|
168116
|
+
// empty → engine's built-in stack
|
|
168117
|
+
colors: {
|
|
168118
|
+
primary: "#1a1a1a",
|
|
168119
|
+
accent: "#1a1a1a",
|
|
168120
|
+
// kept in sync with primary when the theme defines neither
|
|
168121
|
+
secondary: "#666666",
|
|
168122
|
+
// kept in sync with muted when the theme defines neither
|
|
168123
|
+
text: "#1a1a1a",
|
|
168124
|
+
muted: "#666666",
|
|
168125
|
+
tableHeaderBg: "#f3f3f3",
|
|
168126
|
+
tableBorder: "#bbbbbb"
|
|
168127
|
+
},
|
|
168128
|
+
page: { size: "A4", margin: "20mm", header: "", footer: "" },
|
|
168129
|
+
heading: {
|
|
168130
|
+
h1: { size: 20, color: "text", bold: true, spaceAfter: 12 },
|
|
168131
|
+
h2: { size: 15, color: "text", bold: true, spaceAfter: 8 },
|
|
168132
|
+
h3: { size: 13, color: "text", bold: true, spaceAfter: 6 },
|
|
168133
|
+
h4: { size: 11, color: "text", bold: true, spaceAfter: 6 }
|
|
168134
|
+
},
|
|
168135
|
+
body: { size: 11, lineHeight: 1.6, justify: true },
|
|
168136
|
+
cover: { enabled: false, subtitle: "", date: "", logo: "" },
|
|
168137
|
+
pptx: {
|
|
168138
|
+
background: "#ffffff",
|
|
168139
|
+
titleColor: "#1a1a1a",
|
|
168140
|
+
textColor: "",
|
|
168141
|
+
titleSize: 24,
|
|
168142
|
+
bodySize: 16,
|
|
168143
|
+
logo: "",
|
|
168144
|
+
logoPos: { x: 12.2, y: 0.25, w: 0.8, h: 0.8 },
|
|
168145
|
+
footer: "",
|
|
168146
|
+
slideNumber: false,
|
|
168147
|
+
motif: "none",
|
|
168148
|
+
bgWash: false,
|
|
168149
|
+
depth: false
|
|
168150
|
+
}
|
|
168151
|
+
};
|
|
168152
|
+
var HEX_RE = /^#[0-9a-fA-F]{6}$/;
|
|
168153
|
+
var CSS_LEN_RE = /^\d+(\.\d+)?(mm|cm|in|pt|px)$/;
|
|
168154
|
+
function isFiniteNum(v) {
|
|
168155
|
+
return typeof v === "number" && Number.isFinite(v);
|
|
168156
|
+
}
|
|
168157
|
+
function resolveColor(theme, ref) {
|
|
168158
|
+
if (HEX_RE.test(ref))
|
|
168159
|
+
return ref;
|
|
168160
|
+
const palette = theme.colors;
|
|
168161
|
+
return palette[ref] ?? theme.colors.text;
|
|
168162
|
+
}
|
|
168163
|
+
function resolveTheme(raw) {
|
|
168164
|
+
const warnings = [];
|
|
168165
|
+
const t = structuredClone(DEFAULT_THEME);
|
|
168166
|
+
t.warnings = warnings;
|
|
168167
|
+
if (raw == null)
|
|
168168
|
+
return t;
|
|
168169
|
+
if (typeof raw !== "object" || Array.isArray(raw)) {
|
|
168170
|
+
warnings.push("theme must be a JSON object; using defaults");
|
|
168171
|
+
return t;
|
|
168172
|
+
}
|
|
168173
|
+
const src = raw;
|
|
168174
|
+
const str = (v, path) => {
|
|
168175
|
+
if (v === void 0)
|
|
168176
|
+
return void 0;
|
|
168177
|
+
if (typeof v === "string")
|
|
168178
|
+
return v;
|
|
168179
|
+
warnings.push(`${path}: expected string`);
|
|
168180
|
+
return void 0;
|
|
168181
|
+
};
|
|
168182
|
+
const color = (v, path) => {
|
|
168183
|
+
const s = str(v, path);
|
|
168184
|
+
if (s === void 0)
|
|
168185
|
+
return void 0;
|
|
168186
|
+
if (HEX_RE.test(s) || /^[a-zA-Z][a-zA-Z]*$/.test(s))
|
|
168187
|
+
return s;
|
|
168188
|
+
warnings.push(`${path}: expected "#rrggbb" or a palette key`);
|
|
168189
|
+
return void 0;
|
|
168190
|
+
};
|
|
168191
|
+
const num = (v, path, min2, max2) => {
|
|
168192
|
+
if (v === void 0)
|
|
168193
|
+
return void 0;
|
|
168194
|
+
if (isFiniteNum(v) && v >= min2 && v <= max2)
|
|
168195
|
+
return v;
|
|
168196
|
+
warnings.push(`${path}: expected number in [${min2}, ${max2}]`);
|
|
168197
|
+
return void 0;
|
|
168198
|
+
};
|
|
168199
|
+
const bool = (v, path) => {
|
|
168200
|
+
if (v === void 0)
|
|
168201
|
+
return void 0;
|
|
168202
|
+
if (typeof v === "boolean")
|
|
168203
|
+
return v;
|
|
168204
|
+
warnings.push(`${path}: expected boolean`);
|
|
168205
|
+
return void 0;
|
|
168206
|
+
};
|
|
168207
|
+
t.bestFor = str(src.bestFor, "bestFor") ?? t.bestFor;
|
|
168208
|
+
t.fonts.heading = str(src.fonts?.heading, "fonts.heading") ?? t.fonts.heading;
|
|
168209
|
+
t.fonts.body = str(src.fonts?.body, "fonts.body") ?? t.fonts.body;
|
|
168210
|
+
const colorSet = /* @__PURE__ */ new Set();
|
|
168211
|
+
for (const k of ["primary", "accent", "secondary", "text", "muted", "tableHeaderBg", "tableBorder"]) {
|
|
168212
|
+
const v = src.colors?.[k];
|
|
168213
|
+
if (v === void 0)
|
|
168214
|
+
continue;
|
|
168215
|
+
if (typeof v === "string" && HEX_RE.test(v)) {
|
|
168216
|
+
t.colors[k] = v;
|
|
168217
|
+
colorSet.add(k);
|
|
168218
|
+
} else
|
|
168219
|
+
warnings.push(`colors.${k}: expected "#rrggbb"`);
|
|
168220
|
+
}
|
|
168221
|
+
if (!colorSet.has("accent"))
|
|
168222
|
+
t.colors.accent = t.colors.primary;
|
|
168223
|
+
if (!colorSet.has("secondary"))
|
|
168224
|
+
t.colors.secondary = t.colors.muted;
|
|
168225
|
+
if (src.page?.size !== void 0) {
|
|
168226
|
+
if (src.page.size === "A4" || src.page.size === "Letter")
|
|
168227
|
+
t.page.size = src.page.size;
|
|
168228
|
+
else
|
|
168229
|
+
warnings.push('page.size: expected "A4" | "Letter"');
|
|
168230
|
+
}
|
|
168231
|
+
if (src.page?.margin !== void 0) {
|
|
168232
|
+
if (typeof src.page.margin === "string" && CSS_LEN_RE.test(src.page.margin))
|
|
168233
|
+
t.page.margin = src.page.margin;
|
|
168234
|
+
else
|
|
168235
|
+
warnings.push('page.margin: expected a CSS length like "20mm"');
|
|
168236
|
+
}
|
|
168237
|
+
t.page.header = str(src.page?.header, "page.header") ?? t.page.header;
|
|
168238
|
+
t.page.footer = str(src.page?.footer, "page.footer") ?? t.page.footer;
|
|
168239
|
+
for (const lvl of ["h1", "h2", "h3", "h4"]) {
|
|
168240
|
+
const h = src.heading?.[lvl];
|
|
168241
|
+
if (h === void 0)
|
|
168242
|
+
continue;
|
|
168243
|
+
if (typeof h !== "object" || h === null) {
|
|
168244
|
+
warnings.push(`heading.${lvl}: expected object`);
|
|
168245
|
+
continue;
|
|
168246
|
+
}
|
|
168247
|
+
t.heading[lvl].size = num(h.size, `heading.${lvl}.size`, 6, 96) ?? t.heading[lvl].size;
|
|
168248
|
+
t.heading[lvl].color = color(h.color, `heading.${lvl}.color`) ?? t.heading[lvl].color;
|
|
168249
|
+
t.heading[lvl].bold = bool(h.bold, `heading.${lvl}.bold`) ?? t.heading[lvl].bold;
|
|
168250
|
+
t.heading[lvl].spaceAfter = num(h.spaceAfter, `heading.${lvl}.spaceAfter`, 0, 96) ?? t.heading[lvl].spaceAfter;
|
|
168251
|
+
}
|
|
168252
|
+
t.body.size = num(src.body?.size, "body.size", 6, 48) ?? t.body.size;
|
|
168253
|
+
t.body.lineHeight = num(src.body?.lineHeight, "body.lineHeight", 1, 3) ?? t.body.lineHeight;
|
|
168254
|
+
t.body.justify = bool(src.body?.justify, "body.justify") ?? t.body.justify;
|
|
168255
|
+
t.cover.enabled = bool(src.cover?.enabled, "cover.enabled") ?? t.cover.enabled;
|
|
168256
|
+
t.cover.subtitle = str(src.cover?.subtitle, "cover.subtitle") ?? t.cover.subtitle;
|
|
168257
|
+
t.cover.date = str(src.cover?.date, "cover.date") ?? t.cover.date;
|
|
168258
|
+
t.cover.logo = str(src.cover?.logo, "cover.logo") ?? t.cover.logo;
|
|
168259
|
+
const p = src.pptx;
|
|
168260
|
+
if (p !== void 0) {
|
|
168261
|
+
if (typeof p !== "object" || p === null)
|
|
168262
|
+
warnings.push("pptx: expected object");
|
|
168263
|
+
else {
|
|
168264
|
+
for (const k of ["background", "titleColor", "textColor"]) {
|
|
168265
|
+
const v = p[k];
|
|
168266
|
+
if (v === void 0)
|
|
168267
|
+
continue;
|
|
168268
|
+
if (typeof v === "string" && HEX_RE.test(v))
|
|
168269
|
+
t.pptx[k] = v;
|
|
168270
|
+
else
|
|
168271
|
+
warnings.push(`pptx.${k}: expected "#rrggbb"`);
|
|
168272
|
+
}
|
|
168273
|
+
t.pptx.titleSize = num(p.titleSize, "pptx.titleSize", 8, 60) ?? t.pptx.titleSize;
|
|
168274
|
+
t.pptx.bodySize = num(p.bodySize, "pptx.bodySize", 8, 48) ?? t.pptx.bodySize;
|
|
168275
|
+
t.pptx.logo = str(p.logo, "pptx.logo") ?? t.pptx.logo;
|
|
168276
|
+
if (p.logoPos !== void 0) {
|
|
168277
|
+
const lp = p.logoPos;
|
|
168278
|
+
if (lp && [lp.x, lp.y, lp.w, lp.h].every((v) => isFiniteNum(v) && v >= 0 && v <= 14)) {
|
|
168279
|
+
t.pptx.logoPos = { x: lp.x, y: lp.y, w: lp.w, h: lp.h };
|
|
168280
|
+
} else
|
|
168281
|
+
warnings.push("pptx.logoPos: expected {x,y,w,h} inches within the slide");
|
|
168282
|
+
}
|
|
168283
|
+
t.pptx.footer = str(p.footer, "pptx.footer") ?? t.pptx.footer;
|
|
168284
|
+
t.pptx.slideNumber = bool(p.slideNumber, "pptx.slideNumber") ?? t.pptx.slideNumber;
|
|
168285
|
+
if (p.motif !== void 0) {
|
|
168286
|
+
if (p.motif === "none" || p.motif === "corner" || p.motif === "sidebar")
|
|
168287
|
+
t.pptx.motif = p.motif;
|
|
168288
|
+
else
|
|
168289
|
+
warnings.push('pptx.motif: expected "none" | "corner" | "sidebar"');
|
|
168290
|
+
}
|
|
168291
|
+
t.pptx.bgWash = bool(p.bgWash, "pptx.bgWash") ?? t.pptx.bgWash;
|
|
168292
|
+
t.pptx.depth = bool(p.depth, "pptx.depth") ?? t.pptx.depth;
|
|
168293
|
+
}
|
|
168294
|
+
}
|
|
168295
|
+
return t;
|
|
168296
|
+
}
|
|
168297
|
+
function interpolateTitle(template2, title) {
|
|
168298
|
+
return template2.replaceAll("{title}", title ?? "");
|
|
168299
|
+
}
|
|
168300
|
+
function asTheme(themeInput) {
|
|
168301
|
+
return themeInput && typeof themeInput === "object" && "warnings" in themeInput ? themeInput : resolveTheme(themeInput);
|
|
168302
|
+
}
|
|
168589
168303
|
|
|
168590
168304
|
// packages/core/dist/fs/doc-palette.js
|
|
168591
168305
|
var PALETTE_LIBRARY = [
|
|
@@ -168883,6 +168597,13 @@ function iconSvgDataUri(name, colorHex) {
|
|
|
168883
168597
|
function bareHex(c) {
|
|
168884
168598
|
return c.replace("#", "").toUpperCase();
|
|
168885
168599
|
}
|
|
168600
|
+
function assertTextDocumentSpec(spec) {
|
|
168601
|
+
if (!spec || typeof spec !== "object")
|
|
168602
|
+
return;
|
|
168603
|
+
if (Object.prototype.hasOwnProperty.call(spec, "section")) {
|
|
168604
|
+
throw new Error("unsupported document field: section (use blocks for DOCX/PDF content; section is PPTX-only)");
|
|
168605
|
+
}
|
|
168606
|
+
}
|
|
168886
168607
|
var HEADINGS = [HeadingLevel.HEADING_1, HeadingLevel.HEADING_2, HeadingLevel.HEADING_3, HeadingLevel.HEADING_4];
|
|
168887
168608
|
var ORDERED_REF = "ol";
|
|
168888
168609
|
var DOCX_TABLE_WIDTH_TWIPS = 9026;
|
|
@@ -168960,6 +168681,7 @@ function westFont(name) {
|
|
|
168960
168681
|
return name ? { font: { ascii: name, hAnsi: name, cs: name } } : {};
|
|
168961
168682
|
}
|
|
168962
168683
|
async function generateDocx(spec, themeInput) {
|
|
168684
|
+
assertTextDocumentSpec(spec);
|
|
168963
168685
|
const theme = asTheme(themeInput);
|
|
168964
168686
|
const children = [];
|
|
168965
168687
|
if (theme.cover.enabled && spec.title) {
|
|
@@ -169826,7 +169548,7 @@ function shiftHex(hex, amt) {
|
|
|
169826
169548
|
}
|
|
169827
169549
|
async function injectMasterBranding(bytes, backgroundHex, opts = {}) {
|
|
169828
169550
|
const { bgWash = false, depth = false, primaryHex } = opts;
|
|
169829
|
-
const zip = await
|
|
169551
|
+
const zip = await import_jszip2.default.loadAsync(Buffer.from(bytes));
|
|
169830
169552
|
const fill = bgWash ? `<a:gradFill><a:gsLst><a:gs pos="0"><a:srgbClr val="${backgroundHex}"/></a:gs><a:gs pos="100000"><a:srgbClr val="${shiftHex(backgroundHex, 0.12)}"/></a:gs></a:gsLst><a:lin ang="5400000" scaled="1"/></a:gradFill>` : `<a:solidFill><a:srgbClr val="${backgroundHex}"/></a:solidFill>`;
|
|
169831
169553
|
const bgXml = `<p:bg><p:bgPr>${fill}<a:effectLst/></p:bgPr></p:bg>`;
|
|
169832
169554
|
const bgRe = /<p:bg>[\s\S]*?<\/p:bg>/;
|
|
@@ -169863,257 +169585,582 @@ async function injectMasterBranding(bytes, backgroundHex, opts = {}) {
|
|
|
169863
169585
|
}
|
|
169864
169586
|
}
|
|
169865
169587
|
}
|
|
169866
|
-
const out = await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" });
|
|
169867
|
-
return new Uint8Array(out);
|
|
169868
|
-
}
|
|
169869
|
-
async function finalizePptx(bytes) {
|
|
169870
|
-
return stripDanglingOverrides(await normalizeChartParts(bytes));
|
|
169588
|
+
const out = await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" });
|
|
169589
|
+
return new Uint8Array(out);
|
|
169590
|
+
}
|
|
169591
|
+
async function finalizePptx(bytes) {
|
|
169592
|
+
return stripDanglingOverrides(await normalizeChartParts(bytes));
|
|
169593
|
+
}
|
|
169594
|
+
async function normalizeChartParts(bytes) {
|
|
169595
|
+
const zip = await import_jszip2.default.loadAsync(Buffer.from(bytes));
|
|
169596
|
+
const pres = zip.file("ppt/presentation.xml");
|
|
169597
|
+
if (pres) {
|
|
169598
|
+
let xml = await pres.async("string");
|
|
169599
|
+
const notes = xml.match(/<p:notesMasterIdLst>[\s\S]*?<\/p:notesMasterIdLst>/);
|
|
169600
|
+
const sldIdx = xml.indexOf("<p:sldIdLst>");
|
|
169601
|
+
if (notes && sldIdx >= 0 && xml.indexOf(notes[0]) > sldIdx) {
|
|
169602
|
+
xml = xml.replace(notes[0], "");
|
|
169603
|
+
xml = xml.replace("<p:sldIdLst>", `${notes[0]}<p:sldIdLst>`);
|
|
169604
|
+
zip.file("ppt/presentation.xml", xml);
|
|
169605
|
+
}
|
|
169606
|
+
}
|
|
169607
|
+
const parts = Object.keys(zip.files).filter((n) => /^(ppt|word|xl)\/charts\/chart\d+\.xml$/.test(n));
|
|
169608
|
+
if (!parts.length && !pres)
|
|
169609
|
+
return bytes;
|
|
169610
|
+
for (const name of parts) {
|
|
169611
|
+
let xml = await zip.file(name).async("string");
|
|
169612
|
+
const isLineArea = /<c:(line|area)Chart>/.test(xml);
|
|
169613
|
+
for (const ct of ["lineChart", "areaChart"]) {
|
|
169614
|
+
xml = xml.replace(new RegExp(`<c:${ct}>(?!\\s*<c:grouping)`, "g"), `<c:${ct}><c:grouping val="standard"/>`);
|
|
169615
|
+
}
|
|
169616
|
+
if (isLineArea) {
|
|
169617
|
+
xml = xml.replace(/<c:invertIfNegative[^>]*\/>/g, "");
|
|
169618
|
+
xml = xml.replace(/<c:ser>[\s\S]*?<\/c:ser>/g, (ser) => {
|
|
169619
|
+
const m = ser.match(/<c:marker>[\s\S]*?<\/c:marker>|<c:marker\s*\/>/);
|
|
169620
|
+
const dpos = ser.indexOf("<c:dLbls");
|
|
169621
|
+
if (!m || dpos < 0 || ser.indexOf(m[0]) < dpos)
|
|
169622
|
+
return ser;
|
|
169623
|
+
const without = ser.replace(m[0], "");
|
|
169624
|
+
const at = without.indexOf("<c:dLbls");
|
|
169625
|
+
return without.slice(0, at) + m[0] + without.slice(at);
|
|
169626
|
+
});
|
|
169627
|
+
}
|
|
169628
|
+
xml = xml.replace(/<c:ser>[\s\S]*?<\/c:ser>/g, (ser) => {
|
|
169629
|
+
const dPts = ser.match(/<c:dPt>[\s\S]*?<\/c:dPt>/g);
|
|
169630
|
+
if (!dPts)
|
|
169631
|
+
return ser;
|
|
169632
|
+
const stripped = ser.replace(/<c:dPt>[\s\S]*?<\/c:dPt>/g, "");
|
|
169633
|
+
for (const anchor of ["<c:dLbls", "<c:trendline", "<c:errBars", "<c:cat>", "<c:val>", "</c:ser>"]) {
|
|
169634
|
+
const pos = stripped.indexOf(anchor);
|
|
169635
|
+
if (pos >= 0)
|
|
169636
|
+
return stripped.slice(0, pos) + dPts.join("") + stripped.slice(pos);
|
|
169637
|
+
}
|
|
169638
|
+
return ser;
|
|
169639
|
+
});
|
|
169640
|
+
const declared = new Set([...xml.matchAll(/<c:(?:catAx|valAx|serAx|dateAx)>\s*<c:axId val="(\d+)"\/>/g)].map((m) => m[1]));
|
|
169641
|
+
xml = xml.replace(/<c:axId val="(\d+)"\/>/g, (m, id) => declared.has(id) ? m : "");
|
|
169642
|
+
zip.file(name, xml);
|
|
169643
|
+
}
|
|
169644
|
+
const out = await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" });
|
|
169645
|
+
return new Uint8Array(out);
|
|
169646
|
+
}
|
|
169647
|
+
async function stripDanglingOverrides(bytes) {
|
|
169648
|
+
const zip = await import_jszip2.default.loadAsync(Buffer.from(bytes));
|
|
169649
|
+
const ctFile = zip.file("[Content_Types].xml");
|
|
169650
|
+
if (!ctFile)
|
|
169651
|
+
return bytes;
|
|
169652
|
+
const ct = await ctFile.async("string");
|
|
169653
|
+
const cleaned = ct.replace(/<Override\b[^>]*PartName="\/([^"]+)"[^>]*\/>/g, (m, part) => zip.file(part) ? m : "");
|
|
169654
|
+
if (cleaned === ct)
|
|
169655
|
+
return bytes;
|
|
169656
|
+
zip.file("[Content_Types].xml", cleaned);
|
|
169657
|
+
return new Uint8Array(await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" }));
|
|
169658
|
+
}
|
|
169659
|
+
function dataUri(b64) {
|
|
169660
|
+
return b64.startsWith("data:") ? b64 : `data:image/png;base64,${b64}`;
|
|
169661
|
+
}
|
|
169662
|
+
var SYSTEM_UNICODE_FONTS = [
|
|
169663
|
+
"/System/Library/Fonts/Supplemental/Arial Unicode.ttf",
|
|
169664
|
+
// macOS — broad CJK
|
|
169665
|
+
"C:\\Windows\\Fonts\\arialuni.ttf",
|
|
169666
|
+
"C:\\Windows\\Fonts\\msyh.ttc",
|
|
169667
|
+
"C:\\Windows\\Fonts\\simsun.ttc",
|
|
169668
|
+
"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
|
|
169669
|
+
"/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc"
|
|
169670
|
+
];
|
|
169671
|
+
function resolveUnicodeFontPath(spec) {
|
|
169672
|
+
const explicit = spec.fontPath || process.env.TALOS_PDF_FONT;
|
|
169673
|
+
if (explicit)
|
|
169674
|
+
return explicit;
|
|
169675
|
+
return SYSTEM_UNICODE_FONTS.find((p) => (0, import_node_fs.existsSync)(p));
|
|
169676
|
+
}
|
|
169677
|
+
function canEncode(font, text) {
|
|
169678
|
+
try {
|
|
169679
|
+
font.encodeText(text);
|
|
169680
|
+
return true;
|
|
169681
|
+
} catch {
|
|
169682
|
+
return false;
|
|
169683
|
+
}
|
|
169684
|
+
}
|
|
169685
|
+
var PAGE_W = 595.28;
|
|
169686
|
+
var PAGE_H = 841.89;
|
|
169687
|
+
var MARGIN = 56;
|
|
169688
|
+
var CONTENT_W = PAGE_W - MARGIN * 2;
|
|
169689
|
+
function isCjk(cp) {
|
|
169690
|
+
return cp >= 11904 && cp <= 12351 || cp >= 12352 && cp <= 12543 || cp >= 13312 && cp <= 19903 || cp >= 19968 && cp <= 40959 || cp >= 63744 && cp <= 64255 || cp >= 65280 && cp <= 65519 || cp >= 131072 && cp <= 195103;
|
|
169691
|
+
}
|
|
169692
|
+
function foldFullwidthAlnum(s) {
|
|
169693
|
+
return s.replace(/[0-9A-Za-z]/g, (c) => String.fromCharCode(c.charCodeAt(0) - 65248)).replace(/ /g, " ");
|
|
169694
|
+
}
|
|
169695
|
+
function atomize(text) {
|
|
169696
|
+
const chars = [...text];
|
|
169697
|
+
const atoms = [];
|
|
169698
|
+
for (let i = 0; i < chars.length; ) {
|
|
169699
|
+
const ch = chars[i];
|
|
169700
|
+
if (ch === " " || ch === " ") {
|
|
169701
|
+
atoms.push({ kind: "space" });
|
|
169702
|
+
i++;
|
|
169703
|
+
continue;
|
|
169704
|
+
}
|
|
169705
|
+
if (isCjk(ch.codePointAt(0))) {
|
|
169706
|
+
atoms.push({ kind: "cjk", text: ch });
|
|
169707
|
+
i++;
|
|
169708
|
+
continue;
|
|
169709
|
+
}
|
|
169710
|
+
let j = i;
|
|
169711
|
+
while (j < chars.length && chars[j] !== " " && chars[j] !== " " && !isCjk(chars[j].codePointAt(0)))
|
|
169712
|
+
j++;
|
|
169713
|
+
atoms.push({ kind: "latin", text: chars.slice(i, j).join("") });
|
|
169714
|
+
i = j;
|
|
169715
|
+
}
|
|
169716
|
+
return atoms;
|
|
169717
|
+
}
|
|
169718
|
+
function layoutSegment(segment, style, fonts) {
|
|
169719
|
+
const latin = style.bold ? fonts.latinBold : fonts.latin;
|
|
169720
|
+
const w = (t, f) => f.widthOfTextAtSize(t, style.size);
|
|
169721
|
+
const pick = (a) => a.kind === "cjk" ? fonts.cjk ?? latin : fonts.cjk && !canEncode(latin, a.text) ? fonts.cjk : latin;
|
|
169722
|
+
const lines = [];
|
|
169723
|
+
let cur = [];
|
|
169724
|
+
let curW = 0;
|
|
169725
|
+
const flush = () => {
|
|
169726
|
+
lines.push(cur);
|
|
169727
|
+
cur = [];
|
|
169728
|
+
curW = 0;
|
|
169729
|
+
};
|
|
169730
|
+
const add = (t, f) => {
|
|
169731
|
+
const width = w(t, f);
|
|
169732
|
+
const last2 = cur[cur.length - 1];
|
|
169733
|
+
if (last2 && last2.font === f) {
|
|
169734
|
+
last2.text += t;
|
|
169735
|
+
last2.width += width;
|
|
169736
|
+
} else
|
|
169737
|
+
cur.push({ text: t, font: f, width });
|
|
169738
|
+
curW += width;
|
|
169739
|
+
};
|
|
169740
|
+
for (const a of atomize(segment)) {
|
|
169741
|
+
if (a.kind === "space") {
|
|
169742
|
+
if (curW === 0)
|
|
169743
|
+
continue;
|
|
169744
|
+
const sw = w(" ", latin);
|
|
169745
|
+
if (curW + sw > CONTENT_W) {
|
|
169746
|
+
flush();
|
|
169747
|
+
continue;
|
|
169748
|
+
}
|
|
169749
|
+
add(" ", latin);
|
|
169750
|
+
continue;
|
|
169751
|
+
}
|
|
169752
|
+
const f = pick(a);
|
|
169753
|
+
if (curW > 0 && curW + w(a.text, f) > CONTENT_W)
|
|
169754
|
+
flush();
|
|
169755
|
+
add(a.text, f);
|
|
169756
|
+
}
|
|
169757
|
+
flush();
|
|
169758
|
+
return lines;
|
|
169759
|
+
}
|
|
169760
|
+
function hexRgb(c) {
|
|
169761
|
+
const n = parseInt(c.replace("#", ""), 16);
|
|
169762
|
+
return (0, import_pdf_lib.rgb)((n >> 16 & 255) / 255, (n >> 8 & 255) / 255, (n & 255) / 255);
|
|
169763
|
+
}
|
|
169764
|
+
async function generatePdf(spec, themeInput) {
|
|
169765
|
+
assertTextDocumentSpec(spec);
|
|
169766
|
+
const theme = asTheme(themeInput);
|
|
169767
|
+
const doc = await import_pdf_lib.PDFDocument.create();
|
|
169768
|
+
const fonts = {
|
|
169769
|
+
latin: await doc.embedFont(import_pdf_lib.StandardFonts.Helvetica),
|
|
169770
|
+
latinBold: await doc.embedFont(import_pdf_lib.StandardFonts.HelveticaBold)
|
|
169771
|
+
};
|
|
169772
|
+
const headingStyle = {
|
|
169773
|
+
size: theme.heading.h1.size,
|
|
169774
|
+
bold: theme.heading.h1.bold,
|
|
169775
|
+
lineHeight: Math.round(theme.heading.h1.size * 1.35),
|
|
169776
|
+
spaceAfter: theme.heading.h1.spaceAfter
|
|
169777
|
+
};
|
|
169778
|
+
const bodyStyle = {
|
|
169779
|
+
size: theme.body.size,
|
|
169780
|
+
bold: false,
|
|
169781
|
+
lineHeight: Math.round(theme.body.size * theme.body.lineHeight),
|
|
169782
|
+
spaceAfter: 8
|
|
169783
|
+
};
|
|
169784
|
+
const headingColor = hexRgb(resolveColor(theme, theme.heading.h1.color));
|
|
169785
|
+
const textColor = hexRgb(theme.colors.text);
|
|
169786
|
+
const blocks = [];
|
|
169787
|
+
if (spec.title)
|
|
169788
|
+
blocks.push({ text: foldFullwidthAlnum(String(spec.title)), style: headingStyle, color: headingColor });
|
|
169789
|
+
for (const p of spec.paragraphs ?? [])
|
|
169790
|
+
blocks.push({ text: foldFullwidthAlnum(String(p)), style: bodyStyle, color: textColor });
|
|
169791
|
+
for (const block of spec.blocks ?? []) {
|
|
169792
|
+
switch (block.type) {
|
|
169793
|
+
case "heading": {
|
|
169794
|
+
const level = Math.min(Math.max(block.level ?? 1, 1), 4);
|
|
169795
|
+
const key = `h${level}`;
|
|
169796
|
+
const h = theme.heading[key];
|
|
169797
|
+
blocks.push({
|
|
169798
|
+
text: foldFullwidthAlnum(String(block.text)),
|
|
169799
|
+
style: { size: h.size, bold: h.bold, lineHeight: Math.round(h.size * 1.35), spaceAfter: h.spaceAfter },
|
|
169800
|
+
color: hexRgb(resolveColor(theme, h.color))
|
|
169801
|
+
});
|
|
169802
|
+
break;
|
|
169803
|
+
}
|
|
169804
|
+
case "paragraph":
|
|
169805
|
+
blocks.push({ text: foldFullwidthAlnum(String(block.text)), style: { ...bodyStyle, bold: Boolean(block.bold) }, color: textColor });
|
|
169806
|
+
break;
|
|
169807
|
+
case "list":
|
|
169808
|
+
for (const [index, item] of (block.items ?? []).entries()) {
|
|
169809
|
+
blocks.push({
|
|
169810
|
+
// Use an ASCII marker here: the fallback may have no Unicode font
|
|
169811
|
+
// available, while the Chromium HTML path renders real list markers.
|
|
169812
|
+
text: foldFullwidthAlnum(`${block.ordered ? `${index + 1}.` : "-"} ${String(item)}`),
|
|
169813
|
+
style: bodyStyle,
|
|
169814
|
+
color: textColor
|
|
169815
|
+
});
|
|
169816
|
+
}
|
|
169817
|
+
break;
|
|
169818
|
+
case "table":
|
|
169819
|
+
for (const row of block.rows ?? []) {
|
|
169820
|
+
blocks.push({ text: foldFullwidthAlnum(row.map(String).join(" ")), style: bodyStyle, color: textColor });
|
|
169821
|
+
}
|
|
169822
|
+
break;
|
|
169823
|
+
case "image":
|
|
169824
|
+
break;
|
|
169825
|
+
default:
|
|
169826
|
+
throw new Error(`unhandled block type: ${block.type}`);
|
|
169827
|
+
}
|
|
169828
|
+
}
|
|
169829
|
+
const segments = blocks.flatMap((b) => b.text.split(/\r?\n/));
|
|
169830
|
+
if (segments.some((s) => !canEncode(fonts.latin, s))) {
|
|
169831
|
+
const fontPath = resolveUnicodeFontPath(spec);
|
|
169832
|
+
if (!fontPath) {
|
|
169833
|
+
throw new Error("PDF text needs a Unicode font (non-Latin / CJK) but none was found. Set TALOS_PDF_FONT (or spec.fontPath) to a .ttf/.otf covering it, or generate a .docx instead.");
|
|
169834
|
+
}
|
|
169835
|
+
let bytes;
|
|
169836
|
+
try {
|
|
169837
|
+
bytes = (0, import_node_fs.readFileSync)(fontPath);
|
|
169838
|
+
} catch (e) {
|
|
169839
|
+
throw new Error(`cannot read PDF font at ${fontPath}: ${e.message}`);
|
|
169840
|
+
}
|
|
169841
|
+
doc.registerFontkit(import_fontkit.default);
|
|
169842
|
+
fonts.cjk = await doc.embedFont(bytes, { subset: true });
|
|
169843
|
+
}
|
|
169844
|
+
let page = doc.addPage([PAGE_W, PAGE_H]);
|
|
169845
|
+
let y = PAGE_H - MARGIN;
|
|
169846
|
+
for (const block of blocks) {
|
|
169847
|
+
for (const seg of block.text.split(/\r?\n/)) {
|
|
169848
|
+
for (const runs of layoutSegment(seg, block.style, fonts)) {
|
|
169849
|
+
if (y - block.style.lineHeight < MARGIN) {
|
|
169850
|
+
page = doc.addPage([PAGE_W, PAGE_H]);
|
|
169851
|
+
y = PAGE_H - MARGIN;
|
|
169852
|
+
}
|
|
169853
|
+
let x = MARGIN;
|
|
169854
|
+
const baseline = y - block.style.size;
|
|
169855
|
+
for (const run of runs) {
|
|
169856
|
+
page.drawText(run.text, { x, y: baseline, size: block.style.size, font: run.font, color: block.color });
|
|
169857
|
+
x += run.width;
|
|
169858
|
+
}
|
|
169859
|
+
y -= block.style.lineHeight;
|
|
169860
|
+
}
|
|
169861
|
+
}
|
|
169862
|
+
y -= block.style.spaceAfter;
|
|
169863
|
+
}
|
|
169864
|
+
return doc.save();
|
|
169871
169865
|
}
|
|
169872
|
-
async function
|
|
169873
|
-
|
|
169874
|
-
|
|
169875
|
-
|
|
169876
|
-
|
|
169877
|
-
|
|
169878
|
-
|
|
169879
|
-
|
|
169880
|
-
|
|
169881
|
-
|
|
169882
|
-
|
|
169883
|
-
|
|
169884
|
-
}
|
|
169885
|
-
const parts = Object.keys(zip.files).filter((n) => /^(ppt|word|xl)\/charts\/chart\d+\.xml$/.test(n));
|
|
169886
|
-
if (!parts.length && !pres)
|
|
169887
|
-
return bytes;
|
|
169888
|
-
for (const name of parts) {
|
|
169889
|
-
let xml = await zip.file(name).async("string");
|
|
169890
|
-
const isLineArea = /<c:(line|area)Chart>/.test(xml);
|
|
169891
|
-
for (const ct of ["lineChart", "areaChart"]) {
|
|
169892
|
-
xml = xml.replace(new RegExp(`<c:${ct}>(?!\\s*<c:grouping)`, "g"), `<c:${ct}><c:grouping val="standard"/>`);
|
|
169893
|
-
}
|
|
169894
|
-
if (isLineArea) {
|
|
169895
|
-
xml = xml.replace(/<c:invertIfNegative[^>]*\/>/g, "");
|
|
169896
|
-
xml = xml.replace(/<c:ser>[\s\S]*?<\/c:ser>/g, (ser) => {
|
|
169897
|
-
const m = ser.match(/<c:marker>[\s\S]*?<\/c:marker>|<c:marker\s*\/>/);
|
|
169898
|
-
const dpos = ser.indexOf("<c:dLbls");
|
|
169899
|
-
if (!m || dpos < 0 || ser.indexOf(m[0]) < dpos)
|
|
169900
|
-
return ser;
|
|
169901
|
-
const without = ser.replace(m[0], "");
|
|
169902
|
-
const at = without.indexOf("<c:dLbls");
|
|
169903
|
-
return without.slice(0, at) + m[0] + without.slice(at);
|
|
169904
|
-
});
|
|
169905
|
-
}
|
|
169906
|
-
xml = xml.replace(/<c:ser>[\s\S]*?<\/c:ser>/g, (ser) => {
|
|
169907
|
-
const dPts = ser.match(/<c:dPt>[\s\S]*?<\/c:dPt>/g);
|
|
169908
|
-
if (!dPts)
|
|
169909
|
-
return ser;
|
|
169910
|
-
const stripped = ser.replace(/<c:dPt>[\s\S]*?<\/c:dPt>/g, "");
|
|
169911
|
-
for (const anchor of ["<c:dLbls", "<c:trendline", "<c:errBars", "<c:cat>", "<c:val>", "</c:ser>"]) {
|
|
169912
|
-
const pos = stripped.indexOf(anchor);
|
|
169913
|
-
if (pos >= 0)
|
|
169914
|
-
return stripped.slice(0, pos) + dPts.join("") + stripped.slice(pos);
|
|
169915
|
-
}
|
|
169916
|
-
return ser;
|
|
169917
|
-
});
|
|
169918
|
-
const declared = new Set([...xml.matchAll(/<c:(?:catAx|valAx|serAx|dateAx)>\s*<c:axId val="(\d+)"\/>/g)].map((m) => m[1]));
|
|
169919
|
-
xml = xml.replace(/<c:axId val="(\d+)"\/>/g, (m, id) => declared.has(id) ? m : "");
|
|
169920
|
-
zip.file(name, xml);
|
|
169866
|
+
async function generateDocument(kind, spec, theme) {
|
|
169867
|
+
switch (kind) {
|
|
169868
|
+
case "docx":
|
|
169869
|
+
return generateDocx(spec, theme);
|
|
169870
|
+
case "xlsx":
|
|
169871
|
+
return generateXlsx(spec);
|
|
169872
|
+
case "pptx":
|
|
169873
|
+
return generatePptx(spec, theme);
|
|
169874
|
+
case "pdf":
|
|
169875
|
+
return generatePdf(spec, theme);
|
|
169876
|
+
default:
|
|
169877
|
+
throw new Error(`unsupported kind: ${String(kind)}`);
|
|
169921
169878
|
}
|
|
169922
|
-
const out = await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" });
|
|
169923
|
-
return new Uint8Array(out);
|
|
169924
169879
|
}
|
|
169925
|
-
|
|
169926
|
-
|
|
169927
|
-
|
|
169928
|
-
|
|
169929
|
-
|
|
169930
|
-
|
|
169931
|
-
|
|
169932
|
-
|
|
169933
|
-
|
|
169934
|
-
|
|
169935
|
-
|
|
169880
|
+
|
|
169881
|
+
// packages/core/dist/fs/doc-html.js
|
|
169882
|
+
var FONT_STACK = 'TalosCJK, "Helvetica Neue", Helvetica, Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", "WenQuanYi Zen Hei", sans-serif';
|
|
169883
|
+
|
|
169884
|
+
// packages/core/dist/fs/doc-convert.js
|
|
169885
|
+
var PRINT_STYLE = `
|
|
169886
|
+
@page { size: A4; margin: 20mm 18mm; }
|
|
169887
|
+
* { box-sizing: border-box; }
|
|
169888
|
+
html { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
|
|
169889
|
+
body { font-family: ${FONT_STACK}; font-size: 11pt; line-height: 1.55; color: #1a1a1a; margin: 0; }
|
|
169890
|
+
h1 { font-size: 20pt; margin: 0 0 10pt; line-height: 1.3; }
|
|
169891
|
+
h2 { font-size: 15.5pt; margin: 14pt 0 6pt; }
|
|
169892
|
+
h3 { font-size: 13pt; margin: 12pt 0 5pt; }
|
|
169893
|
+
h4, h5, h6 { font-size: 11.5pt; margin: 10pt 0 4pt; }
|
|
169894
|
+
p { margin: 0 0 7pt; overflow-wrap: break-word; }
|
|
169895
|
+
ul, ol { margin: 0 0 7pt; padding-left: 22pt; }
|
|
169896
|
+
li { margin: 0 0 3pt; }
|
|
169897
|
+
table { border-collapse: collapse; width: 100%; margin: 8pt 0; font-size: 10.5pt; }
|
|
169898
|
+
th, td { border: 1px solid #b9b9b9; padding: 4pt 8pt; text-align: left; vertical-align: top; }
|
|
169899
|
+
th { background: #f2f2f2; font-weight: 700; }
|
|
169900
|
+
img { max-width: 100%; }
|
|
169901
|
+
.slide { page-break-after: always; }
|
|
169902
|
+
.slide:last-child { page-break-after: auto; }
|
|
169903
|
+
.slide-no { color: #999; font-size: 8pt; margin: 0 0 6pt; }
|
|
169904
|
+
`.trim();
|
|
169905
|
+
function htmlShell(bodyHtml, title) {
|
|
169906
|
+
const head = `<meta charset="utf-8">` + (title ? `<title>${escapeHtml(title)}</title>` : "") + `<style>${PRINT_STYLE}</style>`;
|
|
169907
|
+
return `<!doctype html><html lang="zh"><head>${head}</head><body>${bodyHtml}</body></html>`;
|
|
169936
169908
|
}
|
|
169937
|
-
function
|
|
169938
|
-
return
|
|
169909
|
+
function escapeHtml(s) {
|
|
169910
|
+
return s.replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c]);
|
|
169939
169911
|
}
|
|
169940
|
-
|
|
169941
|
-
|
|
169942
|
-
|
|
169943
|
-
|
|
169944
|
-
"C:\\Windows\\Fonts\\msyh.ttc",
|
|
169945
|
-
"C:\\Windows\\Fonts\\simsun.ttc",
|
|
169946
|
-
"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
|
|
169947
|
-
"/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc"
|
|
169948
|
-
];
|
|
169949
|
-
function resolveUnicodeFontPath(spec) {
|
|
169950
|
-
const explicit = spec.fontPath || process.env.TALOS_PDF_FONT;
|
|
169951
|
-
if (explicit)
|
|
169952
|
-
return explicit;
|
|
169953
|
-
return SYSTEM_UNICODE_FONTS.find((p) => (0, import_node_fs2.existsSync)(p));
|
|
169912
|
+
function titleFromFilename(filename) {
|
|
169913
|
+
const base = filename.split(/[\\/]/).pop() ?? filename;
|
|
169914
|
+
const stem = base.replace(/\.[^.]+$/, "").trim();
|
|
169915
|
+
return stem || void 0;
|
|
169954
169916
|
}
|
|
169955
|
-
function
|
|
169917
|
+
function htmlToParagraphs(html) {
|
|
169918
|
+
const text = html.replace(/<\/(h[1-6]|p|li|tr)>/gi, "\n").replace(/<br[^>]*\/?>/gi, "\n").replace(/<\/t[dh]>/gi, " ").replace(/<[^>]+>/g, "").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/&/g, "&").replace(/ /g, " ");
|
|
169919
|
+
return text.split(/\n+/).map((line) => line.replace(/\t+/g, " ").trim()).filter((line) => line.length > 0);
|
|
169920
|
+
}
|
|
169921
|
+
async function convertDocxToHtml(buffer, filename) {
|
|
169922
|
+
const result2 = await import_mammoth2.default.convertToHtml({ buffer: Buffer.from(buffer) }, {
|
|
169923
|
+
convertImage: import_mammoth2.default.images.imgElement(async (image) => ({
|
|
169924
|
+
src: `data:${image.contentType};base64,${await image.read("base64")}`
|
|
169925
|
+
}))
|
|
169926
|
+
});
|
|
169927
|
+
const bodyHtml = result2.value;
|
|
169928
|
+
return {
|
|
169929
|
+
kind: "docx",
|
|
169930
|
+
html: htmlShell(bodyHtml, titleFromFilename(filename)),
|
|
169931
|
+
fallbackSpec: { title: titleFromFilename(filename), paragraphs: htmlToParagraphs(bodyHtml) },
|
|
169932
|
+
warnings: (result2.messages ?? []).map((m) => `${m.type ?? "warning"}: ${m.message ?? ""}`)
|
|
169933
|
+
};
|
|
169934
|
+
}
|
|
169935
|
+
async function convertPptxToHtml(buffer, filename) {
|
|
169936
|
+
const zip = await import_jszip3.default.loadAsync(buffer);
|
|
169937
|
+
const slideFiles = Object.keys(zip.files).filter((f) => /^ppt\/slides\/slide\d+\.xml$/.test(f)).sort((a, b) => slideNumber(a) - slideNumber(b));
|
|
169938
|
+
const sections = [];
|
|
169939
|
+
const fallbackParagraphs = [];
|
|
169940
|
+
for (const slidePath of slideFiles) {
|
|
169941
|
+
const num = slideNumber(slidePath);
|
|
169942
|
+
const xml = await zip.file(slidePath).async("string");
|
|
169943
|
+
const paragraphs = extractSlideText(xml).split("\n").filter(Boolean);
|
|
169944
|
+
const imgs = [];
|
|
169945
|
+
const relsPath = `ppt/slides/_rels/slide${num}.xml.rels`;
|
|
169946
|
+
const relsFile = zip.file(relsPath);
|
|
169947
|
+
if (relsFile) {
|
|
169948
|
+
for (const ref of imageRefsFromRels(await relsFile.async("string"))) {
|
|
169949
|
+
const mediaPath = resolveRelTarget(relsPath, ref);
|
|
169950
|
+
const media = zip.file(mediaPath);
|
|
169951
|
+
if (!media)
|
|
169952
|
+
continue;
|
|
169953
|
+
imgs.push(`<img src="data:${mimeFromPath(mediaPath)};base64,${await media.async("base64")}" alt="">`);
|
|
169954
|
+
}
|
|
169955
|
+
}
|
|
169956
|
+
sections.push(`<section class="slide"><div class="slide-no">${num} / ${slideFiles.length}</div>` + paragraphs.map((p) => `<p>${escapeHtml(p)}</p>`).join("") + imgs.join("") + `</section>`);
|
|
169957
|
+
fallbackParagraphs.push(`[\u5E7B\u706F\u7247 ${num}]`, ...paragraphs);
|
|
169958
|
+
}
|
|
169959
|
+
return {
|
|
169960
|
+
kind: "pptx",
|
|
169961
|
+
html: htmlShell(sections.join("\n"), titleFromFilename(filename)),
|
|
169962
|
+
fallbackSpec: { title: titleFromFilename(filename), paragraphs: fallbackParagraphs },
|
|
169963
|
+
warnings: ["pptx conversion is one page per slide (text + images); in-slide layout is not reproduced"]
|
|
169964
|
+
};
|
|
169965
|
+
}
|
|
169966
|
+
async function convertOfficeToPrintable(buffer, filename) {
|
|
169967
|
+
if (buffer.byteLength < 4)
|
|
169968
|
+
return { error: `\u65E0\u6CD5\u8BC6\u522B ${filename} \u7684\u6587\u4EF6\u683C\u5F0F\uFF08\u6587\u4EF6\u8FC7\u5C0F\uFF09` };
|
|
169969
|
+
if (isCompoundDocMagic(buffer)) {
|
|
169970
|
+
return { error: `\u4E0D\u652F\u6301\u65E7\u7248 .doc/.ppt\uFF0C\u8BF7\u5148\u5728\u5BF9\u5E94\u5E94\u7528\u4E2D\u53E6\u5B58\u4E3A .docx/.pptx \u518D\u8F6C\u6362` };
|
|
169971
|
+
}
|
|
169972
|
+
if (!isZipMagic(buffer))
|
|
169973
|
+
return { error: `\u4E0D\u652F\u6301 ${filename} \u7684\u6587\u4EF6\u683C\u5F0F\uFF08doc-convert \u53EA\u652F\u6301 .docx/.pptx\uFF09` };
|
|
169974
|
+
let zip;
|
|
169956
169975
|
try {
|
|
169957
|
-
|
|
169958
|
-
return true;
|
|
169976
|
+
zip = await import_jszip3.default.loadAsync(buffer);
|
|
169959
169977
|
} catch {
|
|
169960
|
-
return
|
|
169978
|
+
return { error: `\u65E0\u6CD5\u89E3\u6790 ${filename}\uFF1AZIP \u7ED3\u6784\u635F\u574F` };
|
|
169961
169979
|
}
|
|
169980
|
+
const format = await detectZipFormat(zip);
|
|
169981
|
+
try {
|
|
169982
|
+
if (format === "docx")
|
|
169983
|
+
return await convertDocxToHtml(buffer, filename);
|
|
169984
|
+
if (format === "pptx")
|
|
169985
|
+
return await convertPptxToHtml(buffer, filename);
|
|
169986
|
+
} catch (e) {
|
|
169987
|
+
return { error: `\u8F6C\u6362 ${filename} \u5931\u8D25\uFF1A${String(e)}` };
|
|
169988
|
+
}
|
|
169989
|
+
if (format === "xlsx") {
|
|
169990
|
+
return { error: `.xlsx \u65E0 HTML \u515C\u5E95\uFF1Axlsx\u2192PDF \u9700 LibreOffice\uFF08\u672C\u673A\u6216 sidecar\uFF09\uFF0C\u6570\u636E\u67E5\u8BE2\u7528 xlsx-query\u3001\u4EA7\u51FA\u62A5\u544A\u7528 doc-gen` };
|
|
169991
|
+
}
|
|
169992
|
+
return { error: `\u4E0D\u652F\u6301 ${filename} \u7684\u6587\u4EF6\u683C\u5F0F\uFF08doc-convert \u53EA\u652F\u6301 .docx/.pptx\uFF09` };
|
|
169962
169993
|
}
|
|
169963
|
-
|
|
169964
|
-
|
|
169965
|
-
var
|
|
169966
|
-
var
|
|
169967
|
-
|
|
169968
|
-
|
|
169969
|
-
|
|
169970
|
-
|
|
169971
|
-
|
|
169972
|
-
|
|
169973
|
-
|
|
169974
|
-
|
|
169975
|
-
|
|
169976
|
-
|
|
169977
|
-
|
|
169978
|
-
|
|
169979
|
-
|
|
169980
|
-
|
|
169981
|
-
|
|
169982
|
-
|
|
169983
|
-
|
|
169984
|
-
|
|
169985
|
-
|
|
169994
|
+
|
|
169995
|
+
// packages/core/dist/fs/soffice.js
|
|
169996
|
+
var import_node_child_process = require("node:child_process");
|
|
169997
|
+
var import_node_fs2 = require("node:fs");
|
|
169998
|
+
var import_promises = require("node:fs/promises");
|
|
169999
|
+
var import_node_os = require("node:os");
|
|
170000
|
+
var import_node_path = require("node:path");
|
|
170001
|
+
var import_node_url = require("node:url");
|
|
170002
|
+
var MAC_CANDIDATES = ["/Applications/LibreOffice.app/Contents/MacOS/soffice"];
|
|
170003
|
+
var WIN_CANDIDATES = [
|
|
170004
|
+
"C:\\Program Files\\LibreOffice\\program\\soffice.com",
|
|
170005
|
+
"C:\\Program Files (x86)\\LibreOffice\\program\\soffice.com"
|
|
170006
|
+
];
|
|
170007
|
+
var PATH_NAMES = {
|
|
170008
|
+
win32: ["soffice.com", "soffice.exe"],
|
|
170009
|
+
darwin: ["soffice"],
|
|
170010
|
+
linux: ["soffice", "libreoffice"]
|
|
170011
|
+
};
|
|
170012
|
+
var SOFFICE_DISABLE_VALUES = /* @__PURE__ */ new Set(["off", "none", "0", "false", "disabled"]);
|
|
170013
|
+
function resolveSoffice(deps = {}) {
|
|
170014
|
+
const env2 = deps.env ?? process.env;
|
|
170015
|
+
const platform = deps.platform ?? process.platform;
|
|
170016
|
+
const exists = deps.exists ?? import_node_fs2.existsSync;
|
|
170017
|
+
const override = env2.TALOS_SOFFICE;
|
|
170018
|
+
if (override && SOFFICE_DISABLE_VALUES.has(override.trim().toLowerCase()))
|
|
170019
|
+
return null;
|
|
170020
|
+
if (override && exists(override))
|
|
170021
|
+
return override;
|
|
170022
|
+
const installed = platform === "darwin" ? MAC_CANDIDATES : platform === "win32" ? WIN_CANDIDATES : [];
|
|
170023
|
+
for (const c of installed)
|
|
170024
|
+
if (exists(c))
|
|
170025
|
+
return c;
|
|
170026
|
+
const pathMod = platform === "win32" ? import_node_path.win32 : import_node_path.posix;
|
|
170027
|
+
const names = PATH_NAMES[platform] ?? PATH_NAMES.linux;
|
|
170028
|
+
for (const dir of (env2.PATH ?? "").split(pathMod.delimiter)) {
|
|
170029
|
+
if (!dir)
|
|
169986
170030
|
continue;
|
|
170031
|
+
for (const name of names) {
|
|
170032
|
+
const p = pathMod.join(dir, name);
|
|
170033
|
+
if (exists(p))
|
|
170034
|
+
return p;
|
|
169987
170035
|
}
|
|
169988
|
-
let j = i;
|
|
169989
|
-
while (j < chars.length && chars[j] !== " " && chars[j] !== " " && !isCjk(chars[j].codePointAt(0)))
|
|
169990
|
-
j++;
|
|
169991
|
-
atoms.push({ kind: "latin", text: chars.slice(i, j).join("") });
|
|
169992
|
-
i = j;
|
|
169993
170036
|
}
|
|
169994
|
-
return
|
|
170037
|
+
return null;
|
|
169995
170038
|
}
|
|
169996
|
-
|
|
169997
|
-
|
|
169998
|
-
|
|
169999
|
-
|
|
170000
|
-
|
|
170001
|
-
|
|
170002
|
-
|
|
170003
|
-
|
|
170004
|
-
|
|
170005
|
-
|
|
170006
|
-
|
|
170007
|
-
|
|
170008
|
-
|
|
170009
|
-
|
|
170010
|
-
|
|
170011
|
-
|
|
170012
|
-
|
|
170013
|
-
|
|
170014
|
-
|
|
170015
|
-
|
|
170016
|
-
|
|
170017
|
-
}
|
|
170018
|
-
for (const a of atomize(segment)) {
|
|
170019
|
-
if (a.kind === "space") {
|
|
170020
|
-
if (curW === 0)
|
|
170021
|
-
continue;
|
|
170022
|
-
const sw = w(" ", latin);
|
|
170023
|
-
if (curW + sw > CONTENT_W) {
|
|
170024
|
-
flush();
|
|
170025
|
-
continue;
|
|
170026
|
-
}
|
|
170027
|
-
add(" ", latin);
|
|
170028
|
-
continue;
|
|
170029
|
-
}
|
|
170030
|
-
const f = pick(a);
|
|
170031
|
-
if (curW > 0 && curW + w(a.text, f) > CONTENT_W)
|
|
170032
|
-
flush();
|
|
170033
|
-
add(a.text, f);
|
|
170034
|
-
}
|
|
170035
|
-
flush();
|
|
170036
|
-
return lines;
|
|
170039
|
+
var PDF_FILTER_BY_EXT = {
|
|
170040
|
+
".docx": "writer_pdf_Export",
|
|
170041
|
+
".doc": "writer_pdf_Export",
|
|
170042
|
+
".odt": "writer_pdf_Export",
|
|
170043
|
+
".rtf": "writer_pdf_Export",
|
|
170044
|
+
".txt": "writer_pdf_Export",
|
|
170045
|
+
".html": "writer_pdf_Export",
|
|
170046
|
+
".htm": "writer_pdf_Export",
|
|
170047
|
+
".pptx": "impress_pdf_Export",
|
|
170048
|
+
".ppt": "impress_pdf_Export",
|
|
170049
|
+
".odp": "impress_pdf_Export",
|
|
170050
|
+
".xlsx": "calc_pdf_Export",
|
|
170051
|
+
".xls": "calc_pdf_Export",
|
|
170052
|
+
".ods": "calc_pdf_Export",
|
|
170053
|
+
".csv": "calc_pdf_Export"
|
|
170054
|
+
};
|
|
170055
|
+
var PDF_EXPORT_FILTER_DATA = { EmbedStandardFonts: { type: "boolean", value: "true" } };
|
|
170056
|
+
function pdfExportArg(inputPath) {
|
|
170057
|
+
const filter2 = PDF_FILTER_BY_EXT[(0, import_node_path.extname)(inputPath).toLowerCase()];
|
|
170058
|
+
if (!filter2)
|
|
170059
|
+
return "pdf";
|
|
170060
|
+
return `pdf:${filter2}:${JSON.stringify(PDF_EXPORT_FILTER_DATA)}`;
|
|
170037
170061
|
}
|
|
170038
|
-
function
|
|
170039
|
-
const
|
|
170040
|
-
|
|
170062
|
+
function sofficeTimeoutMs(bytes) {
|
|
170063
|
+
const base = 9e4;
|
|
170064
|
+
const perMb = 12e3;
|
|
170065
|
+
const mb = Math.max(0, bytes) / (1024 * 1024);
|
|
170066
|
+
return Math.min(6e5, Math.round(base + mb * perMb));
|
|
170041
170067
|
}
|
|
170042
|
-
|
|
170043
|
-
|
|
170044
|
-
|
|
170045
|
-
const
|
|
170046
|
-
|
|
170047
|
-
|
|
170048
|
-
|
|
170049
|
-
|
|
170050
|
-
|
|
170051
|
-
|
|
170052
|
-
|
|
170053
|
-
|
|
170054
|
-
|
|
170055
|
-
|
|
170056
|
-
|
|
170057
|
-
|
|
170058
|
-
|
|
170059
|
-
|
|
170060
|
-
|
|
170061
|
-
const
|
|
170062
|
-
const
|
|
170063
|
-
|
|
170064
|
-
|
|
170065
|
-
|
|
170066
|
-
|
|
170067
|
-
|
|
170068
|
-
|
|
170069
|
-
|
|
170070
|
-
|
|
170071
|
-
|
|
170072
|
-
|
|
170073
|
-
|
|
170074
|
-
|
|
170075
|
-
|
|
170076
|
-
|
|
170077
|
-
|
|
170078
|
-
|
|
170079
|
-
|
|
170080
|
-
|
|
170081
|
-
|
|
170082
|
-
}
|
|
170083
|
-
|
|
170084
|
-
|
|
170085
|
-
|
|
170086
|
-
|
|
170087
|
-
for (const runs of layoutSegment(seg, block.style, fonts)) {
|
|
170088
|
-
if (y - block.style.lineHeight < MARGIN) {
|
|
170089
|
-
page = doc.addPage([PAGE_W, PAGE_H]);
|
|
170090
|
-
y = PAGE_H - MARGIN;
|
|
170091
|
-
}
|
|
170092
|
-
let x = MARGIN;
|
|
170093
|
-
const baseline = y - block.style.size;
|
|
170094
|
-
for (const run of runs) {
|
|
170095
|
-
page.drawText(run.text, { x, y: baseline, size: block.style.size, font: run.font, color: block.color });
|
|
170096
|
-
x += run.width;
|
|
170097
|
-
}
|
|
170098
|
-
y -= block.style.lineHeight;
|
|
170099
|
-
}
|
|
170100
|
-
}
|
|
170101
|
-
y -= block.style.spaceAfter;
|
|
170068
|
+
function pickConvertedPdf(pdfNames, inputPath) {
|
|
170069
|
+
if (pdfNames.length === 0)
|
|
170070
|
+
return null;
|
|
170071
|
+
const stem = (0, import_node_path.basename)(inputPath, (0, import_node_path.extname)(inputPath)).toLowerCase();
|
|
170072
|
+
const nameStem = (n) => (0, import_node_path.basename)(n, (0, import_node_path.extname)(n)).toLowerCase();
|
|
170073
|
+
const exact = pdfNames.find((n) => nameStem(n) === stem);
|
|
170074
|
+
if (exact)
|
|
170075
|
+
return exact;
|
|
170076
|
+
if (pdfNames.length === 1)
|
|
170077
|
+
return pdfNames[0];
|
|
170078
|
+
const related = pdfNames.find((n) => nameStem(n).startsWith(stem) || stem.startsWith(nameStem(n)));
|
|
170079
|
+
return related ?? [...pdfNames].sort()[0];
|
|
170080
|
+
}
|
|
170081
|
+
async function convertToPdfViaSoffice(inputPath, options = {}) {
|
|
170082
|
+
const soffice = options.sofficePath ?? resolveSoffice();
|
|
170083
|
+
if (!soffice)
|
|
170084
|
+
throw new Error("LibreOffice (soffice) not found");
|
|
170085
|
+
if (!(0, import_node_fs2.existsSync)(inputPath))
|
|
170086
|
+
throw new Error(`input not found: ${inputPath}`);
|
|
170087
|
+
const profileDir = await (0, import_promises.mkdtemp)((0, import_node_path.join)((0, import_node_os.tmpdir)(), "talos-lo-profile-"));
|
|
170088
|
+
const outDir = await (0, import_promises.mkdtemp)((0, import_node_path.join)((0, import_node_os.tmpdir)(), "talos-lo-out-"));
|
|
170089
|
+
try {
|
|
170090
|
+
await runSoffice(soffice, [
|
|
170091
|
+
"--headless",
|
|
170092
|
+
"--norestore",
|
|
170093
|
+
"--nolockcheck",
|
|
170094
|
+
"--nodefault",
|
|
170095
|
+
"--nofirststartwizard",
|
|
170096
|
+
`-env:UserInstallation=${(0, import_node_url.pathToFileURL)(profileDir).href}`,
|
|
170097
|
+
"--convert-to",
|
|
170098
|
+
pdfExportArg(inputPath),
|
|
170099
|
+
"--outdir",
|
|
170100
|
+
outDir,
|
|
170101
|
+
inputPath
|
|
170102
|
+
], options.timeoutMs ?? sofficeTimeoutMs((0, import_node_fs2.statSync)(inputPath).size));
|
|
170103
|
+
const pdfs = (await (0, import_promises.readdir)(outDir)).filter((f) => f.toLowerCase().endsWith(".pdf"));
|
|
170104
|
+
const chosen = pickConvertedPdf(pdfs, inputPath);
|
|
170105
|
+
if (!chosen)
|
|
170106
|
+
throw new Error("LibreOffice produced no PDF (unsupported input?)");
|
|
170107
|
+
return await (0, import_promises.readFile)((0, import_node_path.join)(outDir, chosen));
|
|
170108
|
+
} finally {
|
|
170109
|
+
await (0, import_promises.rm)(profileDir, { recursive: true, force: true }).catch(() => {
|
|
170110
|
+
});
|
|
170111
|
+
await (0, import_promises.rm)(outDir, { recursive: true, force: true }).catch(() => {
|
|
170112
|
+
});
|
|
170102
170113
|
}
|
|
170103
|
-
return doc.save();
|
|
170104
170114
|
}
|
|
170105
|
-
|
|
170106
|
-
|
|
170107
|
-
|
|
170108
|
-
|
|
170109
|
-
|
|
170110
|
-
|
|
170111
|
-
|
|
170112
|
-
|
|
170113
|
-
|
|
170114
|
-
|
|
170115
|
-
|
|
170116
|
-
|
|
170115
|
+
function runSoffice(bin, args, timeoutMs) {
|
|
170116
|
+
return new Promise((resolve, reject2) => {
|
|
170117
|
+
const child = (0, import_node_child_process.spawn)(bin, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
170118
|
+
let stderr = "";
|
|
170119
|
+
const timer = setTimeout(() => {
|
|
170120
|
+
child.kill("SIGKILL");
|
|
170121
|
+
reject2(new Error(`LibreOffice timed out after ${timeoutMs}ms`));
|
|
170122
|
+
}, timeoutMs);
|
|
170123
|
+
child.stderr?.on("data", (c) => {
|
|
170124
|
+
if (stderr.length < 4096)
|
|
170125
|
+
stderr += String(c);
|
|
170126
|
+
});
|
|
170127
|
+
child.on("error", (err) => {
|
|
170128
|
+
clearTimeout(timer);
|
|
170129
|
+
reject2(err);
|
|
170130
|
+
});
|
|
170131
|
+
child.on("close", (code) => {
|
|
170132
|
+
clearTimeout(timer);
|
|
170133
|
+
if (code === 0)
|
|
170134
|
+
resolve();
|
|
170135
|
+
else
|
|
170136
|
+
reject2(new Error(`LibreOffice exited ${code}${stderr ? `: ${stderr.trim()}` : ""}`));
|
|
170137
|
+
});
|
|
170138
|
+
});
|
|
170139
|
+
}
|
|
170140
|
+
|
|
170141
|
+
// packages/core/dist/fs/office-service.js
|
|
170142
|
+
async function convertViaOfficeService(bytes, filename, url, options = {}) {
|
|
170143
|
+
const doFetch = options.fetchImpl ?? fetch;
|
|
170144
|
+
const view = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
|
|
170145
|
+
const part = new Uint8Array(view.byteLength);
|
|
170146
|
+
part.set(view);
|
|
170147
|
+
const form = new FormData();
|
|
170148
|
+
form.append("files", new Blob([part]), filename);
|
|
170149
|
+
const controller = new AbortController();
|
|
170150
|
+
const timer = options.timeoutMs && options.timeoutMs > 0 ? setTimeout(() => controller.abort(), options.timeoutMs) : void 0;
|
|
170151
|
+
try {
|
|
170152
|
+
const res = await doFetch(url, {
|
|
170153
|
+
method: "POST",
|
|
170154
|
+
headers: options.token ? { authorization: `Bearer ${options.token}` } : {},
|
|
170155
|
+
body: form,
|
|
170156
|
+
signal: controller.signal
|
|
170157
|
+
});
|
|
170158
|
+
if (!res.ok)
|
|
170159
|
+
throw new Error(`office service HTTP ${res.status}`);
|
|
170160
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
170161
|
+
} finally {
|
|
170162
|
+
if (timer)
|
|
170163
|
+
clearTimeout(timer);
|
|
170117
170164
|
}
|
|
170118
170165
|
}
|
|
170119
170166
|
|