auto-hwpx 0.1.0 → 0.1.1
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/README.md +41 -34
- package/dist/cli-v2.d.ts +3 -0
- package/dist/cli-v2.d.ts.map +1 -0
- package/dist/cli-v2.js +119 -0
- package/dist/cli-v2.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/render-hwpx-v2.d.ts +33 -0
- package/dist/render-hwpx-v2.d.ts.map +1 -0
- package/dist/render-hwpx-v2.js +238 -0
- package/dist/render-hwpx-v2.js.map +1 -0
- package/package.json +5 -8
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -68
- package/dist/cli.js.map +0 -1
- package/dist/render-hwpx.d.ts +0 -16
- package/dist/render-hwpx.d.ts.map +0 -1
- package/dist/render-hwpx.js +0 -518
- package/dist/render-hwpx.js.map +0 -1
package/README.md
CHANGED
|
@@ -6,19 +6,22 @@ TypeScript utility to replace placeholders in `.hwpx` files and emit a new `.hwp
|
|
|
6
6
|
|
|
7
7
|
## Placeholder syntax
|
|
8
8
|
|
|
9
|
-
- Text placeholder:
|
|
10
|
-
- Text placeholder with default:
|
|
11
|
-
- Image placeholder:
|
|
12
|
-
|
|
13
|
-
The renderer supports both raw token form and XML-escaped form (`<@...@>`) inside HWPX XML entries.
|
|
9
|
+
- Text placeholder: `{{key}}`
|
|
10
|
+
- Text placeholder with default: `{{key=default text}}`
|
|
11
|
+
- Image placeholder: `{{@imgKey}}`
|
|
12
|
+
- Image placeholder with default: `{{@imgKey=default}}`
|
|
14
13
|
|
|
15
14
|
## Behavior
|
|
16
15
|
|
|
17
16
|
- Scans `.xml`, `.txt`, and `.hpf` entries in the HWPX zip.
|
|
18
17
|
- For missing text keys:
|
|
19
18
|
- If default exists, default is used.
|
|
20
|
-
- If default does not exist
|
|
21
|
-
-
|
|
19
|
+
- If default does not exist:
|
|
20
|
+
- default mode: placeholder is removed.
|
|
21
|
+
- `-k/--keep-placeholder` mode: placeholder is kept.
|
|
22
|
+
- For image keys (`@key=/path/to/image`):
|
|
23
|
+
- Finds `{{@key}}`, resolves the following image's `binaryItemIDRef`, and replaces matching `BinData/<id>.*` bytes.
|
|
24
|
+
- If image replacement succeeds, `{{@key}}` is removed.
|
|
22
25
|
|
|
23
26
|
## Install
|
|
24
27
|
|
|
@@ -29,10 +32,9 @@ npm install
|
|
|
29
32
|
## Demo script
|
|
30
33
|
|
|
31
34
|
Run a one-command demo that:
|
|
32
|
-
- finds `
|
|
33
|
-
- creates a tiny demo image
|
|
35
|
+
- finds `demo-assets/*.hwpx`
|
|
34
36
|
- fills text + image placeholders
|
|
35
|
-
- writes `demo-output
|
|
37
|
+
- writes to `demo-output/<input-name>.hwpx`
|
|
36
38
|
|
|
37
39
|
```bash
|
|
38
40
|
npm run demo
|
|
@@ -79,42 +81,37 @@ auto-hwpx --help
|
|
|
79
81
|
|
|
80
82
|
```bash
|
|
81
83
|
npm run start -- \
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
--images-json '{"img":"/absolute/path/to/image.png"}'
|
|
84
|
+
demo-assets/example.hwpx \
|
|
85
|
+
-o /tmp/output.hwpx \
|
|
86
|
+
name="홍길동" content="작업 내용" @img1="/absolute/path/to/image.png"
|
|
86
87
|
```
|
|
87
88
|
|
|
88
|
-
|
|
89
|
+
List keys only:
|
|
89
90
|
|
|
90
91
|
```bash
|
|
91
|
-
npm run start --
|
|
92
|
-
--input hwpx-examples/초과근무내역서.example.hwpx \
|
|
93
|
-
--output /tmp/output.hwpx \
|
|
94
|
-
--text-json '{}' \
|
|
95
|
-
--images-json '{"img":"/absolute/path/to/image.png"}' \
|
|
96
|
-
--image-template hwpx-examples/with-img.hwpx
|
|
92
|
+
npm run start -- demo-assets/example.hwpx -l
|
|
97
93
|
```
|
|
98
94
|
|
|
99
|
-
|
|
95
|
+
Keep unresolved placeholders:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
npm run start -- demo-assets/example.hwpx -o /tmp/output.hwpx -k name="홍길동"
|
|
99
|
+
```
|
|
100
100
|
|
|
101
101
|
## Programmatic API
|
|
102
102
|
|
|
103
103
|
```ts
|
|
104
|
-
import {
|
|
104
|
+
import { replaceHwpxPlaceholdersV2 } from "./src/render-hwpx-v2.js";
|
|
105
105
|
|
|
106
|
-
const result = await
|
|
107
|
-
inputPath: "
|
|
106
|
+
const result = await replaceHwpxPlaceholdersV2({
|
|
107
|
+
inputPath: "demo-assets/example.hwpx",
|
|
108
108
|
outputPath: "/tmp/output.hwpx",
|
|
109
109
|
replacements: {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
},
|
|
114
|
-
images: {
|
|
115
|
-
img: "/absolute/path/to/image.png",
|
|
116
|
-
},
|
|
110
|
+
name: "홍길동",
|
|
111
|
+
content: "작업 내용",
|
|
112
|
+
"@img1": "/absolute/path/to/image.png",
|
|
117
113
|
},
|
|
114
|
+
removeUnresolvedPlaceholders: true, // default true
|
|
118
115
|
});
|
|
119
116
|
|
|
120
117
|
console.log(result);
|
|
@@ -123,13 +120,23 @@ console.log(result);
|
|
|
123
120
|
Return shape:
|
|
124
121
|
|
|
125
122
|
```ts
|
|
126
|
-
interface
|
|
127
|
-
|
|
123
|
+
interface ReplaceHwpxV2Result {
|
|
124
|
+
replacements: number;
|
|
128
125
|
imageReplacements: number;
|
|
129
126
|
unresolvedPlaceholders: string[];
|
|
130
127
|
}
|
|
131
128
|
```
|
|
132
129
|
|
|
130
|
+
List keys API:
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
import { listHwpxPlaceholderKeysV2 } from "./src/render-hwpx-v2.js";
|
|
134
|
+
|
|
135
|
+
const keys = await listHwpxPlaceholderKeysV2({
|
|
136
|
+
inputPath: "demo-assets/example.hwpx",
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
133
140
|
## Test
|
|
134
141
|
|
|
135
142
|
```bash
|
package/dist/cli-v2.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-v2.d.ts","sourceRoot":"","sources":["../src/cli-v2.ts"],"names":[],"mappings":""}
|
package/dist/cli-v2.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { promises as fs } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import { listHwpxPlaceholderKeysV2, replaceHwpxPlaceholdersV2, } from "./render-hwpx-v2.js";
|
|
6
|
+
function parseAssignments(values) {
|
|
7
|
+
if (!values || values.length === 0) {
|
|
8
|
+
return {};
|
|
9
|
+
}
|
|
10
|
+
const result = {};
|
|
11
|
+
for (const entry of values) {
|
|
12
|
+
const separatorIndex = entry.indexOf("=");
|
|
13
|
+
if (separatorIndex <= 0) {
|
|
14
|
+
throw new Error(`Invalid assignment "${entry}". Expected key=value format.`);
|
|
15
|
+
}
|
|
16
|
+
const key = entry.slice(0, separatorIndex).trim();
|
|
17
|
+
const value = entry.slice(separatorIndex + 1);
|
|
18
|
+
if (!key) {
|
|
19
|
+
throw new Error(`Invalid assignment "${entry}". Key cannot be empty.`);
|
|
20
|
+
}
|
|
21
|
+
result[key] = value;
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
async function resolveOutputFilePath(inputPath, rawOutputPath) {
|
|
26
|
+
const normalizedOutput = path.resolve(rawOutputPath);
|
|
27
|
+
const looksLikeDirectory = rawOutputPath.endsWith("/") || rawOutputPath.endsWith(path.sep);
|
|
28
|
+
let outputIsDirectory = looksLikeDirectory;
|
|
29
|
+
try {
|
|
30
|
+
const stat = await fs.stat(normalizedOutput);
|
|
31
|
+
outputIsDirectory = stat.isDirectory();
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
if (looksLikeDirectory || path.extname(normalizedOutput) === "") {
|
|
35
|
+
outputIsDirectory = true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (outputIsDirectory) {
|
|
39
|
+
await fs.mkdir(normalizedOutput, { recursive: true });
|
|
40
|
+
return path.join(normalizedOutput, path.basename(inputPath));
|
|
41
|
+
}
|
|
42
|
+
await fs.mkdir(path.dirname(normalizedOutput), { recursive: true });
|
|
43
|
+
return normalizedOutput;
|
|
44
|
+
}
|
|
45
|
+
async function main() {
|
|
46
|
+
const program = new Command();
|
|
47
|
+
program
|
|
48
|
+
.name("auto-hwpx")
|
|
49
|
+
.description("Replace {{key}} text and {{@key}} image placeholders in an .hwpx file.")
|
|
50
|
+
.showHelpAfterError("(Run with --help for usage and examples)")
|
|
51
|
+
.argument("<inputPath>", "Input .hwpx file path")
|
|
52
|
+
.argument("[assignments...]", "Replacement pairs as key=value. Use @key=/path/to/image for image replacement.")
|
|
53
|
+
.option("-o, --output <path>", "Output file path or directory (directories are created automatically)")
|
|
54
|
+
.option("-l, --list-keys", "List all placeholder keys in the input .hwpx and exit.")
|
|
55
|
+
.option("--remove-placeholder", "Remove unresolved placeholders (default behavior).")
|
|
56
|
+
.option("-k, --keep-placeholder", "Keep unresolved placeholders ({{key}} and {{@key}}).")
|
|
57
|
+
.addHelpText("after", `
|
|
58
|
+
Examples:
|
|
59
|
+
# Write to an explicit output file
|
|
60
|
+
$ auto-hwpx ./template.hwpx -o ./out/result.hwpx name="Alice" cost="12000" @img1="./receipt.jpg"
|
|
61
|
+
|
|
62
|
+
# If output is a directory, output file keeps the input file name
|
|
63
|
+
$ auto-hwpx ./template.hwpx -o ./out name="Alice" @img2="./photo.png"
|
|
64
|
+
-> writes ./out/template.hwpx
|
|
65
|
+
|
|
66
|
+
# Keep unresolved placeholders
|
|
67
|
+
$ auto-hwpx ./template.hwpx -o ./out/result.hwpx -k name="Alice"
|
|
68
|
+
|
|
69
|
+
# List all keys from the template
|
|
70
|
+
$ auto-hwpx ./template.hwpx -l
|
|
71
|
+
|
|
72
|
+
Notes:
|
|
73
|
+
- {{@img_key}} placeholder should be placed before the target image.
|
|
74
|
+
- The target image must be configured as "글자처럼 취급".
|
|
75
|
+
`);
|
|
76
|
+
program.parse(process.argv);
|
|
77
|
+
const options = program.opts();
|
|
78
|
+
const inputPath = program.processedArgs[0];
|
|
79
|
+
if (options.listKeys) {
|
|
80
|
+
const listed = await listHwpxPlaceholderKeysV2({ inputPath });
|
|
81
|
+
process.stdout.write(`${JSON.stringify({
|
|
82
|
+
inputPath: path.resolve(inputPath),
|
|
83
|
+
keyCount: listed.allKeys.length,
|
|
84
|
+
keys: listed.allKeys,
|
|
85
|
+
textKeys: listed.textKeys,
|
|
86
|
+
imageKeys: listed.imageKeys,
|
|
87
|
+
}, null, 2)}\n`);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (options.removePlaceholder && options.keepPlaceholder) {
|
|
91
|
+
throw new Error("Use either --remove-placeholder or --keep-placeholder, not both.");
|
|
92
|
+
}
|
|
93
|
+
if (!options.output) {
|
|
94
|
+
throw new Error("Missing required option: -o, --output <path> (or use -l, --list-keys).");
|
|
95
|
+
}
|
|
96
|
+
const removeUnresolvedPlaceholders = options.keepPlaceholder ? false : true;
|
|
97
|
+
const rawAssignments = program.processedArgs[1];
|
|
98
|
+
const assignments = Array.isArray(rawAssignments)
|
|
99
|
+
? rawAssignments
|
|
100
|
+
: program.processedArgs.slice(1);
|
|
101
|
+
const outputFilePath = await resolveOutputFilePath(inputPath, options.output);
|
|
102
|
+
const result = await replaceHwpxPlaceholdersV2({
|
|
103
|
+
inputPath,
|
|
104
|
+
outputPath: outputFilePath,
|
|
105
|
+
replacements: parseAssignments(assignments),
|
|
106
|
+
removeUnresolvedPlaceholders,
|
|
107
|
+
});
|
|
108
|
+
process.stdout.write(`${JSON.stringify({
|
|
109
|
+
outputPath: outputFilePath,
|
|
110
|
+
textReplacements: result.replacements,
|
|
111
|
+
imageReplacements: result.imageReplacements,
|
|
112
|
+
unresolvedPlaceholders: result.unresolvedPlaceholders,
|
|
113
|
+
}, null, 2)}\n`);
|
|
114
|
+
}
|
|
115
|
+
main().catch((error) => {
|
|
116
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
117
|
+
process.exitCode = 1;
|
|
118
|
+
});
|
|
119
|
+
//# sourceMappingURL=cli-v2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-v2.js","sourceRoot":"","sources":["../src/cli-v2.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { findBinaryItemIdRefByImagePlaceholder, listHwpxPlaceholderKeysV2, replaceUnzippedBinDataImage, replaceHwpxPlaceholdersV2, type ListHwpxV2KeysInput, type ListHwpxV2KeysResult, type ReplaceUnzippedBinDataImageInput, type ReplaceUnzippedBinDataImageResult, type ReplaceHwpxV2Input, type ReplaceHwpxV2Result, } from "./render-hwpx-v2.js";
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qCAAqC,EACrC,yBAAyB,EACzB,2BAA2B,EAC3B,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,gCAAgC,EACrC,KAAK,iCAAiC,EACtC,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { findBinaryItemIdRefByImagePlaceholder, listHwpxPlaceholderKeysV2, replaceUnzippedBinDataImage, replaceHwpxPlaceholdersV2, } from "./render-hwpx-v2.js";
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qCAAqC,EACrC,yBAAyB,EACzB,2BAA2B,EAC3B,yBAAyB,GAO1B,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface ReplaceHwpxV2Input {
|
|
2
|
+
inputPath: string;
|
|
3
|
+
outputPath: string;
|
|
4
|
+
replacements: Record<string, string>;
|
|
5
|
+
removeUnresolvedPlaceholders?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface ListHwpxV2KeysInput {
|
|
8
|
+
inputPath: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ListHwpxV2KeysResult {
|
|
11
|
+
allKeys: string[];
|
|
12
|
+
textKeys: string[];
|
|
13
|
+
imageKeys: string[];
|
|
14
|
+
}
|
|
15
|
+
export interface ReplaceHwpxV2Result {
|
|
16
|
+
replacements: number;
|
|
17
|
+
imageReplacements: number;
|
|
18
|
+
unresolvedPlaceholders: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface ReplaceUnzippedBinDataImageInput {
|
|
21
|
+
unzippedRootPath: string;
|
|
22
|
+
binaryItemIdRef: string;
|
|
23
|
+
sourceImagePath: string;
|
|
24
|
+
}
|
|
25
|
+
export interface ReplaceUnzippedBinDataImageResult {
|
|
26
|
+
targetImagePath: string;
|
|
27
|
+
bytesWritten: number;
|
|
28
|
+
}
|
|
29
|
+
export declare function findBinaryItemIdRefByImagePlaceholder(sectionXml: string, imagePlaceholderKey: string): string | null;
|
|
30
|
+
export declare function listHwpxPlaceholderKeysV2(input: ListHwpxV2KeysInput): Promise<ListHwpxV2KeysResult>;
|
|
31
|
+
export declare function replaceUnzippedBinDataImage(input: ReplaceUnzippedBinDataImageInput): Promise<ReplaceUnzippedBinDataImageResult>;
|
|
32
|
+
export declare function replaceHwpxPlaceholdersV2(input: ReplaceHwpxV2Input): Promise<ReplaceHwpxV2Result>;
|
|
33
|
+
//# sourceMappingURL=render-hwpx-v2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-hwpx-v2.d.ts","sourceRoot":"","sources":["../src/render-hwpx-v2.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,4BAA4B,CAAC,EAAE,OAAO,CAAC;CACxC;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,sBAAsB,EAAE,MAAM,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,gCAAgC;IAC/C,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,iCAAiC;IAChD,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB;AAkHD,wBAAgB,qCAAqC,CACnD,UAAU,EAAE,MAAM,EAClB,mBAAmB,EAAE,MAAM,GAC1B,MAAM,GAAG,IAAI,CAaf;AAED,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,oBAAoB,CAAC,CA8B/B;AAED,wBAAsB,2BAA2B,CAC/C,KAAK,EAAE,gCAAgC,GACtC,OAAO,CAAC,iCAAiC,CAAC,CAgC5C;AAED,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CA6G9B"}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import JSZip from "jszip";
|
|
4
|
+
const PLACEHOLDER_RE = /\{\{([^}=\s]+)(?:=([^}]*))?\}\}/g;
|
|
5
|
+
const IMG_BINARY_REF_RE = /<(?:hc|hp):img\b[^>]*\bbinaryItemIDRef=(["'])([^"']+)\1/;
|
|
6
|
+
function isTextEntry(fileName) {
|
|
7
|
+
return (fileName.endsWith(".xml") ||
|
|
8
|
+
fileName.endsWith(".txt") ||
|
|
9
|
+
fileName.endsWith(".hpf"));
|
|
10
|
+
}
|
|
11
|
+
function isSectionEntry(fileName) {
|
|
12
|
+
return /^Contents\/section\d+\.xml$/.test(fileName);
|
|
13
|
+
}
|
|
14
|
+
function splitReplacementEntries(replacements) {
|
|
15
|
+
const textValues = {};
|
|
16
|
+
const imageValues = {};
|
|
17
|
+
for (const [key, value] of Object.entries(replacements)) {
|
|
18
|
+
if (key.startsWith("@")) {
|
|
19
|
+
imageValues[key] = value;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
textValues[key] = value;
|
|
23
|
+
}
|
|
24
|
+
return { textValues, imageValues };
|
|
25
|
+
}
|
|
26
|
+
function replaceTokens(params) {
|
|
27
|
+
let replaced = 0;
|
|
28
|
+
const output = params.input.replaceAll(PLACEHOLDER_RE, (fullMatch, key, defaultValue) => {
|
|
29
|
+
if (key.startsWith("@")) {
|
|
30
|
+
if (defaultValue !== undefined) {
|
|
31
|
+
return fullMatch;
|
|
32
|
+
}
|
|
33
|
+
if (!params.imageKeys.has(key)) {
|
|
34
|
+
params.unresolved.add(key);
|
|
35
|
+
}
|
|
36
|
+
return fullMatch;
|
|
37
|
+
}
|
|
38
|
+
const explicit = params.textValues[key];
|
|
39
|
+
if (explicit !== undefined) {
|
|
40
|
+
replaced += 1;
|
|
41
|
+
return explicit;
|
|
42
|
+
}
|
|
43
|
+
if (defaultValue !== undefined) {
|
|
44
|
+
replaced += 1;
|
|
45
|
+
return defaultValue;
|
|
46
|
+
}
|
|
47
|
+
params.unresolved.add(key);
|
|
48
|
+
return fullMatch;
|
|
49
|
+
});
|
|
50
|
+
return { output, replaced };
|
|
51
|
+
}
|
|
52
|
+
function cleanupPlaceholders(params) {
|
|
53
|
+
return params.input.replaceAll(PLACEHOLDER_RE, (fullMatch, key) => {
|
|
54
|
+
if (key.startsWith("@")) {
|
|
55
|
+
if (params.resolvedImageKeys.has(key)) {
|
|
56
|
+
return "";
|
|
57
|
+
}
|
|
58
|
+
return params.removeUnresolvedPlaceholders ? "" : fullMatch;
|
|
59
|
+
}
|
|
60
|
+
return params.removeUnresolvedPlaceholders ? "" : fullMatch;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
function findBinDataEntryName(zip, binaryItemIdRef) {
|
|
64
|
+
const prefix = `BinData/${binaryItemIdRef}.`;
|
|
65
|
+
const matched = Object.keys(zip.files)
|
|
66
|
+
.filter((fileName) => {
|
|
67
|
+
const entry = zip.files[fileName];
|
|
68
|
+
return !entry.dir && fileName.startsWith(prefix);
|
|
69
|
+
})
|
|
70
|
+
.sort();
|
|
71
|
+
if (matched.length === 0) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
if (matched.length > 1) {
|
|
75
|
+
throw new Error(`Multiple BinData entries found for binaryItemIDRef "${binaryItemIdRef}": ${matched.join(", ")}`);
|
|
76
|
+
}
|
|
77
|
+
return matched[0];
|
|
78
|
+
}
|
|
79
|
+
export function findBinaryItemIdRefByImagePlaceholder(sectionXml, imagePlaceholderKey) {
|
|
80
|
+
const normalizedKey = imagePlaceholderKey.startsWith("@")
|
|
81
|
+
? imagePlaceholderKey
|
|
82
|
+
: `@${imagePlaceholderKey}`;
|
|
83
|
+
const token = `{{${normalizedKey}}}`;
|
|
84
|
+
const tokenIndex = sectionXml.indexOf(token);
|
|
85
|
+
if (tokenIndex < 0) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
const tail = sectionXml.slice(tokenIndex + token.length);
|
|
89
|
+
const imgMatch = IMG_BINARY_REF_RE.exec(tail);
|
|
90
|
+
return imgMatch?.[2] ?? null;
|
|
91
|
+
}
|
|
92
|
+
export async function listHwpxPlaceholderKeysV2(input) {
|
|
93
|
+
const bytes = await fs.readFile(input.inputPath);
|
|
94
|
+
const zip = await JSZip.loadAsync(bytes);
|
|
95
|
+
const keySet = new Set();
|
|
96
|
+
for (const entryName of Object.keys(zip.files)) {
|
|
97
|
+
const entry = zip.file(entryName);
|
|
98
|
+
if (!entry || !isTextEntry(entryName)) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const sourceText = await entry.async("string");
|
|
102
|
+
const matcher = new RegExp(PLACEHOLDER_RE.source, "g");
|
|
103
|
+
for (const match of sourceText.matchAll(matcher)) {
|
|
104
|
+
const key = match[1];
|
|
105
|
+
if (key) {
|
|
106
|
+
keySet.add(key);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const allKeys = [...keySet].sort();
|
|
111
|
+
const imageKeys = allKeys.filter((key) => key.startsWith("@"));
|
|
112
|
+
const textKeys = allKeys.filter((key) => !key.startsWith("@"));
|
|
113
|
+
return {
|
|
114
|
+
allKeys,
|
|
115
|
+
textKeys,
|
|
116
|
+
imageKeys,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
export async function replaceUnzippedBinDataImage(input) {
|
|
120
|
+
const binaryItemIdRef = input.binaryItemIdRef.trim();
|
|
121
|
+
if (!binaryItemIdRef) {
|
|
122
|
+
throw new Error("binaryItemIdRef cannot be empty.");
|
|
123
|
+
}
|
|
124
|
+
const binDataDir = path.join(input.unzippedRootPath, "BinData");
|
|
125
|
+
const entries = await fs.readdir(binDataDir, { withFileTypes: true });
|
|
126
|
+
const matched = entries
|
|
127
|
+
.filter((entry) => entry.isFile() && entry.name.startsWith(`${binaryItemIdRef}.`))
|
|
128
|
+
.map((entry) => entry.name)
|
|
129
|
+
.sort();
|
|
130
|
+
if (matched.length === 0) {
|
|
131
|
+
throw new Error(`No BinData file found for binaryItemIdRef "${binaryItemIdRef}" in ${binDataDir}`);
|
|
132
|
+
}
|
|
133
|
+
if (matched.length > 1) {
|
|
134
|
+
throw new Error(`Multiple BinData files found for binaryItemIdRef "${binaryItemIdRef}": ${matched.join(", ")}`);
|
|
135
|
+
}
|
|
136
|
+
const sourceBytes = await fs.readFile(input.sourceImagePath);
|
|
137
|
+
const targetImagePath = path.join(binDataDir, matched[0]);
|
|
138
|
+
await fs.writeFile(targetImagePath, sourceBytes);
|
|
139
|
+
return {
|
|
140
|
+
targetImagePath,
|
|
141
|
+
bytesWritten: sourceBytes.byteLength,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
export async function replaceHwpxPlaceholdersV2(input) {
|
|
145
|
+
const removeUnresolvedPlaceholders = input.removeUnresolvedPlaceholders ?? true;
|
|
146
|
+
const { textValues, imageValues } = splitReplacementEntries(input.replacements);
|
|
147
|
+
const imageKeys = new Set(Object.keys(imageValues));
|
|
148
|
+
const bytes = await fs.readFile(input.inputPath);
|
|
149
|
+
const zip = await JSZip.loadAsync(bytes);
|
|
150
|
+
const unresolved = new Set();
|
|
151
|
+
const sectionTexts = new Map();
|
|
152
|
+
let textReplacementCount = 0;
|
|
153
|
+
let imageReplacementCount = 0;
|
|
154
|
+
for (const entryName of Object.keys(zip.files)) {
|
|
155
|
+
const entry = zip.file(entryName);
|
|
156
|
+
if (!entry || !isTextEntry(entryName)) {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const sourceText = await entry.async("string");
|
|
160
|
+
const replaced = replaceTokens({
|
|
161
|
+
input: sourceText,
|
|
162
|
+
textValues,
|
|
163
|
+
imageKeys,
|
|
164
|
+
unresolved,
|
|
165
|
+
});
|
|
166
|
+
textReplacementCount += replaced.replaced;
|
|
167
|
+
if (isSectionEntry(entryName)) {
|
|
168
|
+
sectionTexts.set(entryName, replaced.output);
|
|
169
|
+
}
|
|
170
|
+
if (replaced.output !== sourceText) {
|
|
171
|
+
zip.file(entryName, replaced.output);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const sortedSections = [...sectionTexts.entries()].sort(([a], [b]) => a.localeCompare(b));
|
|
175
|
+
const imageBytesCache = new Map();
|
|
176
|
+
const resolvedImageKeys = new Set();
|
|
177
|
+
for (const [imageKey, imagePath] of Object.entries(imageValues)) {
|
|
178
|
+
let binaryItemIdRef = null;
|
|
179
|
+
for (const [, sectionXml] of sortedSections) {
|
|
180
|
+
const found = findBinaryItemIdRefByImagePlaceholder(sectionXml, imageKey);
|
|
181
|
+
if (found) {
|
|
182
|
+
binaryItemIdRef = found;
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (!binaryItemIdRef) {
|
|
187
|
+
unresolved.add(imageKey);
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
const targetEntryName = findBinDataEntryName(zip, binaryItemIdRef);
|
|
191
|
+
if (!targetEntryName) {
|
|
192
|
+
throw new Error(`No BinData entry found for binaryItemIDRef "${binaryItemIdRef}" (placeholder ${imageKey}).`);
|
|
193
|
+
}
|
|
194
|
+
let sourceBytes = imageBytesCache.get(imagePath);
|
|
195
|
+
if (!sourceBytes) {
|
|
196
|
+
try {
|
|
197
|
+
sourceBytes = await fs.readFile(imagePath);
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
throw new Error(`Image file not found for key "${imageKey}": ${imagePath}`, {
|
|
201
|
+
cause: error,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
imageBytesCache.set(imagePath, sourceBytes);
|
|
205
|
+
}
|
|
206
|
+
zip.file(targetEntryName, sourceBytes);
|
|
207
|
+
imageReplacementCount += 1;
|
|
208
|
+
resolvedImageKeys.add(imageKey);
|
|
209
|
+
}
|
|
210
|
+
for (const entryName of Object.keys(zip.files)) {
|
|
211
|
+
const entry = zip.file(entryName);
|
|
212
|
+
if (!entry || !isTextEntry(entryName)) {
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
const sourceText = await entry.async("string");
|
|
216
|
+
const cleaned = cleanupPlaceholders({
|
|
217
|
+
input: sourceText,
|
|
218
|
+
removeUnresolvedPlaceholders,
|
|
219
|
+
resolvedImageKeys,
|
|
220
|
+
});
|
|
221
|
+
if (cleaned !== sourceText) {
|
|
222
|
+
zip.file(entryName, cleaned);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
const outputBytes = await zip.generateAsync({
|
|
226
|
+
type: "nodebuffer",
|
|
227
|
+
compression: "DEFLATE",
|
|
228
|
+
compressionOptions: { level: 9 },
|
|
229
|
+
});
|
|
230
|
+
await fs.mkdir(path.dirname(input.outputPath), { recursive: true });
|
|
231
|
+
await fs.writeFile(input.outputPath, outputBytes);
|
|
232
|
+
return {
|
|
233
|
+
replacements: textReplacementCount,
|
|
234
|
+
imageReplacements: imageReplacementCount,
|
|
235
|
+
unresolvedPlaceholders: [...unresolved].sort(),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=render-hwpx-v2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-hwpx-v2.js","sourceRoot":"","sources":["../src/render-hwpx-v2.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "auto-hwpx",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"description": "TypeScript utility for replacing text and image placeholders in HWPX files.",
|
|
8
8
|
"bin": {
|
|
9
|
-
"auto-hwpx": "./dist/cli.js"
|
|
9
|
+
"auto-hwpx": "./dist/cli-v2.js"
|
|
10
10
|
},
|
|
11
11
|
"main": "./dist/index.js",
|
|
12
12
|
"types": "./dist/index.d.ts",
|
|
@@ -36,16 +36,13 @@
|
|
|
36
36
|
"typecheck": "tsc -p tsconfig.json",
|
|
37
37
|
"test": "vitest run",
|
|
38
38
|
"test:watch": "vitest",
|
|
39
|
-
"start": "node --import tsx src/cli.ts",
|
|
40
|
-
"demo": "
|
|
39
|
+
"start": "node --import tsx src/cli-v2.ts",
|
|
40
|
+
"demo": "./scripts/run-cli-demo-v2.sh",
|
|
41
41
|
"prepublishOnly": "npm run test && npm run build"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@xmldom/xmldom": "^0.8.10",
|
|
45
44
|
"commander": "^13.1.0",
|
|
46
|
-
"
|
|
47
|
-
"jszip": "^3.10.1",
|
|
48
|
-
"xpath": "^0.0.34"
|
|
45
|
+
"jszip": "^3.10.1"
|
|
49
46
|
},
|
|
50
47
|
"devDependencies": {
|
|
51
48
|
"@types/node": "^22.15.18",
|
package/dist/cli.d.ts
DELETED
package/dist/cli.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { promises as fs } from "node:fs";
|
|
3
|
-
import { Command } from "commander";
|
|
4
|
-
import { replaceHwpxPlaceholders } from "./render-hwpx.js";
|
|
5
|
-
function isPlainObject(value) {
|
|
6
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
7
|
-
return false;
|
|
8
|
-
}
|
|
9
|
-
return Object.values(value).every((item) => typeof item === "string");
|
|
10
|
-
}
|
|
11
|
-
async function parseJsonMapInput(raw, label) {
|
|
12
|
-
let source = raw;
|
|
13
|
-
try {
|
|
14
|
-
await fs.access(raw);
|
|
15
|
-
source = await fs.readFile(raw, "utf8");
|
|
16
|
-
}
|
|
17
|
-
catch {
|
|
18
|
-
// Not a file path. Treat as inline JSON text.
|
|
19
|
-
}
|
|
20
|
-
let parsed;
|
|
21
|
-
try {
|
|
22
|
-
parsed = JSON.parse(source);
|
|
23
|
-
}
|
|
24
|
-
catch (error) {
|
|
25
|
-
throw new Error(`Invalid ${label} JSON: ${String(error)}`);
|
|
26
|
-
}
|
|
27
|
-
if (!isPlainObject(parsed)) {
|
|
28
|
-
throw new Error(`${label} must be a JSON object of string values.`);
|
|
29
|
-
}
|
|
30
|
-
return parsed;
|
|
31
|
-
}
|
|
32
|
-
async function main() {
|
|
33
|
-
const program = new Command();
|
|
34
|
-
program
|
|
35
|
-
.name("auto-hwpx")
|
|
36
|
-
.description("Replace text and image placeholders in a .hwpx file.")
|
|
37
|
-
.requiredOption("--input <path>", "Input .hwpx file path")
|
|
38
|
-
.requiredOption("--output <path>", "Output .hwpx file path")
|
|
39
|
-
.option("--text-json <jsonOrPath>", "Text replacement JSON object or path", "{}")
|
|
40
|
-
.option("--images-json <jsonOrPath>", "Image replacement JSON object or path", "{}")
|
|
41
|
-
.option("--image-template <path>", "Template .hwpx containing a donor hp:pic run");
|
|
42
|
-
program.parse(process.argv);
|
|
43
|
-
const options = program.opts();
|
|
44
|
-
const [textReplacements, imageReplacements] = await Promise.all([
|
|
45
|
-
parseJsonMapInput(options.textJson, "--text-json"),
|
|
46
|
-
parseJsonMapInput(options.imagesJson, "--images-json"),
|
|
47
|
-
]);
|
|
48
|
-
const result = await replaceHwpxPlaceholders({
|
|
49
|
-
inputPath: options.input,
|
|
50
|
-
outputPath: options.output,
|
|
51
|
-
replacements: {
|
|
52
|
-
text: textReplacements,
|
|
53
|
-
images: imageReplacements,
|
|
54
|
-
},
|
|
55
|
-
imageTemplatePath: options.imageTemplate,
|
|
56
|
-
});
|
|
57
|
-
process.stdout.write(`${JSON.stringify({
|
|
58
|
-
outputPath: options.output,
|
|
59
|
-
textReplacements: result.textReplacements,
|
|
60
|
-
imageReplacements: result.imageReplacements,
|
|
61
|
-
unresolvedPlaceholders: result.unresolvedPlaceholders,
|
|
62
|
-
}, null, 2)}\n`);
|
|
63
|
-
}
|
|
64
|
-
main().catch((error) => {
|
|
65
|
-
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
66
|
-
process.exitCode = 1;
|
|
67
|
-
});
|
|
68
|
-
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/render-hwpx.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export interface ReplaceHwpxInput {
|
|
2
|
-
inputPath: string;
|
|
3
|
-
outputPath: string;
|
|
4
|
-
replacements: {
|
|
5
|
-
text: Record<string, string>;
|
|
6
|
-
images: Record<string, string>;
|
|
7
|
-
};
|
|
8
|
-
imageTemplatePath?: string;
|
|
9
|
-
}
|
|
10
|
-
export interface ReplaceHwpxResult {
|
|
11
|
-
textReplacements: number;
|
|
12
|
-
imageReplacements: number;
|
|
13
|
-
unresolvedPlaceholders: string[];
|
|
14
|
-
}
|
|
15
|
-
export declare function replaceHwpxPlaceholders(input: ReplaceHwpxInput): Promise<ReplaceHwpxResult>;
|
|
16
|
-
//# sourceMappingURL=render-hwpx.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"render-hwpx.d.ts","sourceRoot":"","sources":["../src/render-hwpx.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAChC,CAAC;IACF,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,sBAAsB,EAAE,MAAM,EAAE,CAAC;CAClC;AAmgBD,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,iBAAiB,CAAC,CA0J5B"}
|
package/dist/render-hwpx.js
DELETED
|
@@ -1,518 +0,0 @@
|
|
|
1
|
-
import { promises as fs } from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import JSZip from "jszip";
|
|
4
|
-
import { DOMParser, XMLSerializer } from "@xmldom/xmldom";
|
|
5
|
-
import { imageSize } from "image-size";
|
|
6
|
-
import xpath from "xpath";
|
|
7
|
-
const DEFAULT_TEMPLATE_PATH = path.resolve(process.cwd(), "hwpx-examples/with-img.hwpx");
|
|
8
|
-
const XML_NS = {
|
|
9
|
-
hp: "http://www.hancom.co.kr/hwpml/2011/paragraph",
|
|
10
|
-
hc: "http://www.hancom.co.kr/hwpml/2011/core",
|
|
11
|
-
opf: "http://www.idpf.org/2007/opf/",
|
|
12
|
-
};
|
|
13
|
-
const select = xpath.useNamespaces(XML_NS);
|
|
14
|
-
const XML_DECLARATION_RE = /^<\?xml[^>]+?>/;
|
|
15
|
-
const PLACEHOLDER_RE = /(?:<|<)@([^=@>\s]+)(?:=([^@]*?))?@(?:>|>)/g;
|
|
16
|
-
const IMAGE_PLACEHOLDER_RE = /^<@([^=@>\s]+)(?:=([^@]*?))?@>$/;
|
|
17
|
-
function parseXml(xmlText) {
|
|
18
|
-
return new DOMParser({
|
|
19
|
-
errorHandler: {
|
|
20
|
-
warning: () => undefined,
|
|
21
|
-
error: (message) => {
|
|
22
|
-
throw new Error(`XML parse error: ${message}`);
|
|
23
|
-
},
|
|
24
|
-
fatalError: (message) => {
|
|
25
|
-
throw new Error(`XML fatal parse error: ${message}`);
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
}).parseFromString(xmlText, "application/xml");
|
|
29
|
-
}
|
|
30
|
-
function serializeXml(doc, originalText) {
|
|
31
|
-
const serialized = new XMLSerializer().serializeToString(doc);
|
|
32
|
-
if (XML_DECLARATION_RE.test(serialized)) {
|
|
33
|
-
return serialized;
|
|
34
|
-
}
|
|
35
|
-
const originalDecl = originalText.match(XML_DECLARATION_RE)?.[0];
|
|
36
|
-
if (originalDecl) {
|
|
37
|
-
return `${originalDecl}${serialized}`;
|
|
38
|
-
}
|
|
39
|
-
return serialized;
|
|
40
|
-
}
|
|
41
|
-
function escapeXmlText(text) {
|
|
42
|
-
return text
|
|
43
|
-
.replaceAll("&", "&")
|
|
44
|
-
.replaceAll("<", "<")
|
|
45
|
-
.replaceAll(">", ">")
|
|
46
|
-
.replaceAll('"', """)
|
|
47
|
-
.replaceAll("'", "'");
|
|
48
|
-
}
|
|
49
|
-
function isTextEntry(fileName) {
|
|
50
|
-
return (fileName.endsWith(".xml") ||
|
|
51
|
-
fileName.endsWith(".txt") ||
|
|
52
|
-
fileName.endsWith(".hpf"));
|
|
53
|
-
}
|
|
54
|
-
function isSectionEntry(fileName) {
|
|
55
|
-
return /^Contents\/section\d+\.xml$/.test(fileName);
|
|
56
|
-
}
|
|
57
|
-
function decodePlaceholderToken(text) {
|
|
58
|
-
return text.replaceAll("<", "<").replaceAll(">", ">");
|
|
59
|
-
}
|
|
60
|
-
function replaceTextPlaceholders(params) {
|
|
61
|
-
const { input, textValues, imageKeys, escapeOutput, unresolved } = params;
|
|
62
|
-
let replaced = 0;
|
|
63
|
-
const output = input.replaceAll(PLACEHOLDER_RE, (fullMatch, key, defaultValue) => {
|
|
64
|
-
if (imageKeys.has(key)) {
|
|
65
|
-
return fullMatch;
|
|
66
|
-
}
|
|
67
|
-
const explicitValue = textValues[key];
|
|
68
|
-
if (explicitValue !== undefined) {
|
|
69
|
-
replaced += 1;
|
|
70
|
-
return escapeOutput ? escapeXmlText(explicitValue) : explicitValue;
|
|
71
|
-
}
|
|
72
|
-
if (defaultValue !== undefined) {
|
|
73
|
-
replaced += 1;
|
|
74
|
-
return escapeOutput ? escapeXmlText(defaultValue) : defaultValue;
|
|
75
|
-
}
|
|
76
|
-
unresolved.add(key);
|
|
77
|
-
return fullMatch;
|
|
78
|
-
});
|
|
79
|
-
return { output, replaced };
|
|
80
|
-
}
|
|
81
|
-
function firstElementByXPath(expr, contextNode) {
|
|
82
|
-
const found = select(expr, contextNode);
|
|
83
|
-
if (found.length === 0) {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
return found[0];
|
|
87
|
-
}
|
|
88
|
-
function listElementsByXPath(expr, contextNode) {
|
|
89
|
-
return select(expr, contextNode).map((node) => node);
|
|
90
|
-
}
|
|
91
|
-
function parseIntAttr(element, attrName) {
|
|
92
|
-
if (!element) {
|
|
93
|
-
return null;
|
|
94
|
-
}
|
|
95
|
-
const raw = element.getAttribute(attrName);
|
|
96
|
-
if (!raw) {
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
const parsed = Number.parseInt(raw, 10);
|
|
100
|
-
return Number.isFinite(parsed) ? parsed : null;
|
|
101
|
-
}
|
|
102
|
-
function setIntAttr(element, attrName, value) {
|
|
103
|
-
if (!element) {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
element.setAttribute(attrName, String(Math.max(1, Math.round(value))));
|
|
107
|
-
}
|
|
108
|
-
function detectImageTypeAndSize(buffer) {
|
|
109
|
-
const details = imageSize(buffer);
|
|
110
|
-
if (!details.width || !details.height || !details.type) {
|
|
111
|
-
throw new Error("Unable to detect image dimensions and format.");
|
|
112
|
-
}
|
|
113
|
-
const normalizedType = details.type.toLowerCase();
|
|
114
|
-
const extensionMap = {
|
|
115
|
-
jpg: "jpg",
|
|
116
|
-
jpeg: "jpeg",
|
|
117
|
-
png: "png",
|
|
118
|
-
gif: "gif",
|
|
119
|
-
bmp: "bmp",
|
|
120
|
-
tiff: "tiff",
|
|
121
|
-
tif: "tif",
|
|
122
|
-
svg: "svg",
|
|
123
|
-
};
|
|
124
|
-
const mediaTypeMap = {
|
|
125
|
-
jpg: "image/jpeg",
|
|
126
|
-
jpeg: "image/jpeg",
|
|
127
|
-
png: "image/png",
|
|
128
|
-
gif: "image/gif",
|
|
129
|
-
bmp: "image/bmp",
|
|
130
|
-
tiff: "image/tiff",
|
|
131
|
-
tif: "image/tiff",
|
|
132
|
-
svg: "image/svg+xml",
|
|
133
|
-
};
|
|
134
|
-
const extension = extensionMap[normalizedType];
|
|
135
|
-
const mediaType = mediaTypeMap[normalizedType];
|
|
136
|
-
if (!extension || !mediaType) {
|
|
137
|
-
throw new Error(`Unsupported image type: ${details.type}`);
|
|
138
|
-
}
|
|
139
|
-
return {
|
|
140
|
-
extension,
|
|
141
|
-
mediaType,
|
|
142
|
-
width: details.width,
|
|
143
|
-
height: details.height,
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
function calculateDisplaySize(params) {
|
|
147
|
-
// HWPX image dimensions in the sample map closely to 75 HWP units per pixel.
|
|
148
|
-
const unitPerPixel = 75;
|
|
149
|
-
const originalWidth = Math.max(1, Math.round(params.pixelWidth * unitPerPixel));
|
|
150
|
-
const originalHeight = Math.max(1, Math.round(params.pixelHeight * unitPerPixel));
|
|
151
|
-
const maxWidth = Math.max(1, Math.round(params.maxWidth));
|
|
152
|
-
const maxHeight = Math.max(1, Math.round(params.maxHeight));
|
|
153
|
-
const scale = Math.min(maxWidth / originalWidth, maxHeight / originalHeight);
|
|
154
|
-
const clampedScale = Number.isFinite(scale) && scale > 0 ? scale : 1;
|
|
155
|
-
return {
|
|
156
|
-
width: Math.max(1, Math.round(originalWidth * clampedScale)),
|
|
157
|
-
height: Math.max(1, Math.round(originalHeight * clampedScale)),
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
function getRunParagraph(runElement) {
|
|
161
|
-
let current = runElement.parentNode;
|
|
162
|
-
while (current) {
|
|
163
|
-
if (current.nodeType === current.ELEMENT_NODE) {
|
|
164
|
-
const element = current;
|
|
165
|
-
if (element.localName === "p" && element.prefix === "hp") {
|
|
166
|
-
return element;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
current = current.parentNode;
|
|
170
|
-
}
|
|
171
|
-
return null;
|
|
172
|
-
}
|
|
173
|
-
function getParentTableCell(runElement) {
|
|
174
|
-
let current = runElement.parentNode;
|
|
175
|
-
while (current) {
|
|
176
|
-
if (current.nodeType === current.ELEMENT_NODE) {
|
|
177
|
-
const element = current;
|
|
178
|
-
if (element.localName === "tc" && element.prefix === "hp") {
|
|
179
|
-
return element;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
current = current.parentNode;
|
|
183
|
-
}
|
|
184
|
-
return null;
|
|
185
|
-
}
|
|
186
|
-
function resolvePlaceholderBox(runElement) {
|
|
187
|
-
const cell = getParentTableCell(runElement);
|
|
188
|
-
if (cell) {
|
|
189
|
-
const cellSize = firstElementByXPath("./hp:cellSz", cell);
|
|
190
|
-
const cellMargin = firstElementByXPath("./hp:cellMargin", cell);
|
|
191
|
-
const width = parseIntAttr(cellSize, "width");
|
|
192
|
-
const height = parseIntAttr(cellSize, "height");
|
|
193
|
-
if (width && height) {
|
|
194
|
-
const marginLeft = parseIntAttr(cellMargin, "left") ?? 0;
|
|
195
|
-
const marginRight = parseIntAttr(cellMargin, "right") ?? 0;
|
|
196
|
-
const marginTop = parseIntAttr(cellMargin, "top") ?? 0;
|
|
197
|
-
const marginBottom = parseIntAttr(cellMargin, "bottom") ?? 0;
|
|
198
|
-
return {
|
|
199
|
-
width: Math.max(1, width - marginLeft - marginRight),
|
|
200
|
-
height: Math.max(1, height - marginTop - marginBottom),
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
const paragraph = getRunParagraph(runElement);
|
|
205
|
-
if (paragraph) {
|
|
206
|
-
const lineSeg = firstElementByXPath("./hp:linesegarray/hp:lineseg", paragraph);
|
|
207
|
-
const width = parseIntAttr(lineSeg, "horzsize");
|
|
208
|
-
const height = parseIntAttr(lineSeg, "textheight");
|
|
209
|
-
if (width && height) {
|
|
210
|
-
return { width, height };
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
return { width: 26280, height: 40980 };
|
|
214
|
-
}
|
|
215
|
-
function setPictureGeometry(picElement, imageResource, displaySize) {
|
|
216
|
-
const originalWidth = imageResource.originalWidth;
|
|
217
|
-
const originalHeight = imageResource.originalHeight;
|
|
218
|
-
const width = displaySize.width;
|
|
219
|
-
const height = displaySize.height;
|
|
220
|
-
const orgSz = firstElementByXPath("./hp:orgSz", picElement);
|
|
221
|
-
setIntAttr(orgSz, "width", width);
|
|
222
|
-
setIntAttr(orgSz, "height", height);
|
|
223
|
-
const sz = firstElementByXPath("./hp:sz", picElement);
|
|
224
|
-
setIntAttr(sz, "width", width);
|
|
225
|
-
setIntAttr(sz, "height", height);
|
|
226
|
-
const rotationInfo = firstElementByXPath("./hp:rotationInfo", picElement);
|
|
227
|
-
setIntAttr(rotationInfo, "centerX", Math.round(width / 2));
|
|
228
|
-
setIntAttr(rotationInfo, "centerY", Math.round(height / 2));
|
|
229
|
-
const imgRef = firstElementByXPath("./hc:img", picElement);
|
|
230
|
-
if (!imgRef) {
|
|
231
|
-
throw new Error("Template picture is missing hc:img node.");
|
|
232
|
-
}
|
|
233
|
-
imgRef.setAttribute("binaryItemIDRef", imageResource.itemId);
|
|
234
|
-
const point0 = firstElementByXPath("./hp:imgRect/hc:pt0", picElement);
|
|
235
|
-
const point1 = firstElementByXPath("./hp:imgRect/hc:pt1", picElement);
|
|
236
|
-
const point2 = firstElementByXPath("./hp:imgRect/hc:pt2", picElement);
|
|
237
|
-
const point3 = firstElementByXPath("./hp:imgRect/hc:pt3", picElement);
|
|
238
|
-
if (!point0 || !point1 || !point2 || !point3) {
|
|
239
|
-
throw new Error("Template picture is missing imgRect points.");
|
|
240
|
-
}
|
|
241
|
-
point0.setAttribute("x", "0");
|
|
242
|
-
point0.setAttribute("y", "0");
|
|
243
|
-
point1.setAttribute("x", String(width));
|
|
244
|
-
point1.setAttribute("y", "0");
|
|
245
|
-
point2.setAttribute("x", String(width));
|
|
246
|
-
point2.setAttribute("y", String(height));
|
|
247
|
-
point3.setAttribute("x", "0");
|
|
248
|
-
point3.setAttribute("y", String(height));
|
|
249
|
-
const clip = firstElementByXPath("./hp:imgClip", picElement);
|
|
250
|
-
if (clip) {
|
|
251
|
-
clip.setAttribute("left", "0");
|
|
252
|
-
clip.setAttribute("top", "0");
|
|
253
|
-
clip.setAttribute("right", String(originalWidth));
|
|
254
|
-
clip.setAttribute("bottom", String(originalHeight));
|
|
255
|
-
}
|
|
256
|
-
const dimension = firstElementByXPath("./hp:imgDim", picElement);
|
|
257
|
-
if (dimension) {
|
|
258
|
-
dimension.setAttribute("dimwidth", String(originalWidth));
|
|
259
|
-
dimension.setAttribute("dimheight", String(originalHeight));
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
function buildRunFromTemplate(params) {
|
|
263
|
-
const doc = parseXml(`<root xmlns:hp="${XML_NS.hp}" xmlns:hc="${XML_NS.hc}">${params.templateRunXml}</root>`);
|
|
264
|
-
const runElement = firstElementByXPath("/root/hp:run", doc);
|
|
265
|
-
if (!runElement) {
|
|
266
|
-
throw new Error("Unable to parse template run XML.");
|
|
267
|
-
}
|
|
268
|
-
if (params.charPrIDRef) {
|
|
269
|
-
runElement.setAttribute("charPrIDRef", params.charPrIDRef);
|
|
270
|
-
}
|
|
271
|
-
const pic = firstElementByXPath("./hp:pic", runElement);
|
|
272
|
-
if (!pic) {
|
|
273
|
-
throw new Error("Template run does not contain hp:pic.");
|
|
274
|
-
}
|
|
275
|
-
pic.setAttribute("id", String(params.picId));
|
|
276
|
-
pic.setAttribute("instid", String(params.instId));
|
|
277
|
-
setPictureGeometry(pic, params.imageResource, params.displaySize);
|
|
278
|
-
if (!firstElementByXPath("./hp:t", runElement)) {
|
|
279
|
-
const emptyText = doc.createElementNS(XML_NS.hp, "hp:t");
|
|
280
|
-
runElement.appendChild(emptyText);
|
|
281
|
-
}
|
|
282
|
-
return runElement;
|
|
283
|
-
}
|
|
284
|
-
function findNextImageIndex(contentDoc) {
|
|
285
|
-
const itemNodes = listElementsByXPath("/opf:package/opf:manifest/opf:item", contentDoc);
|
|
286
|
-
let max = 0;
|
|
287
|
-
for (const item of itemNodes) {
|
|
288
|
-
const id = item.getAttribute("id");
|
|
289
|
-
if (!id) {
|
|
290
|
-
continue;
|
|
291
|
-
}
|
|
292
|
-
const match = /^image(\d+)$/.exec(id);
|
|
293
|
-
if (!match) {
|
|
294
|
-
continue;
|
|
295
|
-
}
|
|
296
|
-
max = Math.max(max, Number.parseInt(match[1], 10));
|
|
297
|
-
}
|
|
298
|
-
return max + 1;
|
|
299
|
-
}
|
|
300
|
-
function ensureManifestItem(contentDoc, itemId, href, mediaType) {
|
|
301
|
-
const manifest = firstElementByXPath("/opf:package/opf:manifest", contentDoc);
|
|
302
|
-
if (!manifest) {
|
|
303
|
-
throw new Error("Contents/content.hpf is missing opf:manifest.");
|
|
304
|
-
}
|
|
305
|
-
const existing = listElementsByXPath("./opf:item", manifest).find((item) => item.getAttribute("id") === itemId);
|
|
306
|
-
if (existing) {
|
|
307
|
-
existing.setAttribute("href", href);
|
|
308
|
-
existing.setAttribute("media-type", mediaType);
|
|
309
|
-
existing.setAttribute("isEmbeded", "1");
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
312
|
-
const item = contentDoc.createElementNS(XML_NS.opf, "opf:item");
|
|
313
|
-
item.setAttribute("id", itemId);
|
|
314
|
-
item.setAttribute("href", href);
|
|
315
|
-
item.setAttribute("media-type", mediaType);
|
|
316
|
-
item.setAttribute("isEmbeded", "1");
|
|
317
|
-
manifest.appendChild(item);
|
|
318
|
-
}
|
|
319
|
-
function collectMaxNumericAttributes(sectionDocs) {
|
|
320
|
-
let maxId = 1;
|
|
321
|
-
let maxInstId = 1;
|
|
322
|
-
for (const doc of sectionDocs) {
|
|
323
|
-
const allElements = listElementsByXPath("//*", doc);
|
|
324
|
-
for (const element of allElements) {
|
|
325
|
-
const idAttr = element.getAttribute("id");
|
|
326
|
-
if (idAttr && /^\d+$/.test(idAttr)) {
|
|
327
|
-
maxId = Math.max(maxId, Number.parseInt(idAttr, 10));
|
|
328
|
-
}
|
|
329
|
-
const instAttr = element.getAttribute("instid");
|
|
330
|
-
if (instAttr && /^\d+$/.test(instAttr)) {
|
|
331
|
-
maxInstId = Math.max(maxInstId, Number.parseInt(instAttr, 10));
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
return { maxId, maxInstId };
|
|
336
|
-
}
|
|
337
|
-
async function loadTemplateRunXml(imageTemplatePath) {
|
|
338
|
-
const templateBytes = await fs.readFile(imageTemplatePath);
|
|
339
|
-
const templateZip = await JSZip.loadAsync(templateBytes);
|
|
340
|
-
const sectionNames = Object.keys(templateZip.files).filter(isSectionEntry).sort();
|
|
341
|
-
for (const sectionName of sectionNames) {
|
|
342
|
-
const sectionFile = templateZip.file(sectionName);
|
|
343
|
-
if (!sectionFile) {
|
|
344
|
-
continue;
|
|
345
|
-
}
|
|
346
|
-
const xml = await sectionFile.async("string");
|
|
347
|
-
const doc = parseXml(xml);
|
|
348
|
-
const run = firstElementByXPath("//hp:run[hp:pic]", doc);
|
|
349
|
-
if (run) {
|
|
350
|
-
return new XMLSerializer().serializeToString(run);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
throw new Error(`No template hp:run with hp:pic was found in image template: ${imageTemplatePath}`);
|
|
354
|
-
}
|
|
355
|
-
function parsePlaceholderInTextNode(text) {
|
|
356
|
-
const decoded = decodePlaceholderToken(text.trim());
|
|
357
|
-
const matched = IMAGE_PLACEHOLDER_RE.exec(decoded);
|
|
358
|
-
if (!matched) {
|
|
359
|
-
return null;
|
|
360
|
-
}
|
|
361
|
-
return { key: matched[1] };
|
|
362
|
-
}
|
|
363
|
-
async function ensureImageResource(params) {
|
|
364
|
-
const cached = params.cache.get(params.imageKey);
|
|
365
|
-
if (cached) {
|
|
366
|
-
return cached;
|
|
367
|
-
}
|
|
368
|
-
let fileBuffer;
|
|
369
|
-
try {
|
|
370
|
-
fileBuffer = await fs.readFile(params.imagePath);
|
|
371
|
-
}
|
|
372
|
-
catch (error) {
|
|
373
|
-
throw new Error(`Image file not found for key "${params.imageKey}": ${params.imagePath}`, { cause: error });
|
|
374
|
-
}
|
|
375
|
-
const details = detectImageTypeAndSize(fileBuffer);
|
|
376
|
-
const itemId = `image${params.nextImageIndexRef.value++}`;
|
|
377
|
-
const fileName = `${itemId}.${details.extension}`;
|
|
378
|
-
const zipEntryPath = `BinData/${fileName}`;
|
|
379
|
-
params.zip.file(zipEntryPath, fileBuffer);
|
|
380
|
-
ensureManifestItem(params.contentDoc, itemId, zipEntryPath, details.mediaType);
|
|
381
|
-
const resource = {
|
|
382
|
-
itemId,
|
|
383
|
-
fileName,
|
|
384
|
-
mediaType: details.mediaType,
|
|
385
|
-
originalWidth: Math.max(1, Math.round(details.width * 75)),
|
|
386
|
-
originalHeight: Math.max(1, Math.round(details.height * 75)),
|
|
387
|
-
};
|
|
388
|
-
params.cache.set(params.imageKey, resource);
|
|
389
|
-
return resource;
|
|
390
|
-
}
|
|
391
|
-
export async function replaceHwpxPlaceholders(input) {
|
|
392
|
-
const imageTemplatePath = input.imageTemplatePath ?? DEFAULT_TEMPLATE_PATH;
|
|
393
|
-
const [inputBytes] = await Promise.all([
|
|
394
|
-
fs.readFile(input.inputPath),
|
|
395
|
-
fs.access(imageTemplatePath),
|
|
396
|
-
]);
|
|
397
|
-
const zip = await JSZip.loadAsync(inputBytes);
|
|
398
|
-
const unresolved = new Set();
|
|
399
|
-
const imageKeys = new Set(Object.keys(input.replacements.images));
|
|
400
|
-
let textReplacements = 0;
|
|
401
|
-
const allEntries = Object.keys(zip.files);
|
|
402
|
-
for (const entryName of allEntries) {
|
|
403
|
-
const entry = zip.file(entryName);
|
|
404
|
-
if (!entry || !isTextEntry(entryName)) {
|
|
405
|
-
continue;
|
|
406
|
-
}
|
|
407
|
-
const sourceText = await entry.async("string");
|
|
408
|
-
const replaced = replaceTextPlaceholders({
|
|
409
|
-
input: sourceText,
|
|
410
|
-
textValues: input.replacements.text,
|
|
411
|
-
imageKeys,
|
|
412
|
-
escapeOutput: entryName.endsWith(".xml") || entryName.endsWith(".hpf"),
|
|
413
|
-
unresolved,
|
|
414
|
-
});
|
|
415
|
-
textReplacements += replaced.replaced;
|
|
416
|
-
if (replaced.output !== sourceText) {
|
|
417
|
-
zip.file(entryName, replaced.output);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
const templateRunXml = await loadTemplateRunXml(imageTemplatePath);
|
|
421
|
-
const contentEntry = zip.file("Contents/content.hpf");
|
|
422
|
-
if (!contentEntry) {
|
|
423
|
-
throw new Error("Input HWPX is missing Contents/content.hpf.");
|
|
424
|
-
}
|
|
425
|
-
const contentText = await contentEntry.async("string");
|
|
426
|
-
const contentDoc = parseXml(contentText);
|
|
427
|
-
const nextImageIndexRef = { value: findNextImageIndex(contentDoc) };
|
|
428
|
-
const imageResourceCache = new Map();
|
|
429
|
-
const sectionNames = allEntries.filter(isSectionEntry).sort();
|
|
430
|
-
const sectionDocs = new Map();
|
|
431
|
-
for (const sectionName of sectionNames) {
|
|
432
|
-
const sectionText = await zip.file(sectionName).async("string");
|
|
433
|
-
sectionDocs.set(sectionName, { original: sectionText, doc: parseXml(sectionText) });
|
|
434
|
-
}
|
|
435
|
-
const initialMax = collectMaxNumericAttributes(Array.from(sectionDocs.values(), (item) => item.doc));
|
|
436
|
-
let nextPicId = initialMax.maxId + 1;
|
|
437
|
-
let nextInstId = initialMax.maxInstId + 1;
|
|
438
|
-
let imageReplacements = 0;
|
|
439
|
-
for (const [sectionName, section] of sectionDocs) {
|
|
440
|
-
const runNodes = listElementsByXPath("//hp:run[hp:t]", section.doc);
|
|
441
|
-
let changed = false;
|
|
442
|
-
for (const runNode of runNodes) {
|
|
443
|
-
const textNode = firstElementByXPath("./hp:t", runNode);
|
|
444
|
-
if (!textNode || textNode.textContent === null) {
|
|
445
|
-
continue;
|
|
446
|
-
}
|
|
447
|
-
const placeholder = parsePlaceholderInTextNode(textNode.textContent);
|
|
448
|
-
if (!placeholder) {
|
|
449
|
-
continue;
|
|
450
|
-
}
|
|
451
|
-
const imagePath = input.replacements.images[placeholder.key];
|
|
452
|
-
if (!imagePath) {
|
|
453
|
-
continue;
|
|
454
|
-
}
|
|
455
|
-
const imageResource = await ensureImageResource({
|
|
456
|
-
zip,
|
|
457
|
-
contentDoc,
|
|
458
|
-
cache: imageResourceCache,
|
|
459
|
-
imageKey: placeholder.key,
|
|
460
|
-
imagePath,
|
|
461
|
-
nextImageIndexRef,
|
|
462
|
-
});
|
|
463
|
-
const box = resolvePlaceholderBox(runNode);
|
|
464
|
-
const displaySize = calculateDisplaySize({
|
|
465
|
-
pixelWidth: Math.max(1, Math.round(imageResource.originalWidth / 75)),
|
|
466
|
-
pixelHeight: Math.max(1, Math.round(imageResource.originalHeight / 75)),
|
|
467
|
-
maxWidth: box.width,
|
|
468
|
-
maxHeight: box.height,
|
|
469
|
-
});
|
|
470
|
-
const newRun = buildRunFromTemplate({
|
|
471
|
-
templateRunXml,
|
|
472
|
-
charPrIDRef: runNode.getAttribute("charPrIDRef"),
|
|
473
|
-
imageResource,
|
|
474
|
-
displaySize,
|
|
475
|
-
picId: nextPicId++,
|
|
476
|
-
instId: nextInstId++,
|
|
477
|
-
});
|
|
478
|
-
const parent = runNode.parentNode;
|
|
479
|
-
if (!parent) {
|
|
480
|
-
continue;
|
|
481
|
-
}
|
|
482
|
-
const importedNode = section.doc.importNode
|
|
483
|
-
? section.doc.importNode(newRun, true)
|
|
484
|
-
: newRun.cloneNode(true);
|
|
485
|
-
parent.replaceChild(importedNode, runNode);
|
|
486
|
-
const paragraph = importedNode.nodeType === importedNode.ELEMENT_NODE
|
|
487
|
-
? getRunParagraph(importedNode)
|
|
488
|
-
: null;
|
|
489
|
-
const lineSeg = paragraph
|
|
490
|
-
? firstElementByXPath("./hp:linesegarray/hp:lineseg", paragraph)
|
|
491
|
-
: null;
|
|
492
|
-
if (lineSeg) {
|
|
493
|
-
lineSeg.setAttribute("horzsize", "0");
|
|
494
|
-
}
|
|
495
|
-
imageReplacements += 1;
|
|
496
|
-
changed = true;
|
|
497
|
-
}
|
|
498
|
-
if (changed) {
|
|
499
|
-
const serialized = serializeXml(section.doc, section.original);
|
|
500
|
-
zip.file(sectionName, serialized);
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
const updatedContent = serializeXml(contentDoc, contentText);
|
|
504
|
-
zip.file("Contents/content.hpf", updatedContent);
|
|
505
|
-
const outputBytes = await zip.generateAsync({
|
|
506
|
-
type: "nodebuffer",
|
|
507
|
-
compression: "DEFLATE",
|
|
508
|
-
compressionOptions: { level: 9 },
|
|
509
|
-
});
|
|
510
|
-
await fs.mkdir(path.dirname(input.outputPath), { recursive: true });
|
|
511
|
-
await fs.writeFile(input.outputPath, outputBytes);
|
|
512
|
-
return {
|
|
513
|
-
textReplacements,
|
|
514
|
-
imageReplacements,
|
|
515
|
-
unresolvedPlaceholders: [...unresolved].sort(),
|
|
516
|
-
};
|
|
517
|
-
}
|
|
518
|
-
//# sourceMappingURL=render-hwpx.js.map
|
package/dist/render-hwpx.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"render-hwpx.js","sourceRoot":"","sources":["../src/render-hwpx.ts"],"names":[],"mappings":"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"}
|