@json-to-office/core-docx 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/heading.d.ts.map +1 -1
- package/dist/components/paragraph.d.ts.map +1 -1
- package/dist/core/cached-render.d.ts.map +1 -1
- package/dist/core/content.d.ts +3 -0
- package/dist/core/content.d.ts.map +1 -1
- package/dist/core/render.d.ts.map +1 -1
- package/dist/core/structure.d.ts +2 -0
- package/dist/core/structure.d.ts.map +1 -1
- package/dist/index.js +182 -39
- package/dist/index.js.map +1 -1
- package/dist/plugin/example/index.js +175 -38
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/templates/themes/index.d.ts +32 -0
- package/dist/templates/themes/index.d.ts.map +1 -1
- package/dist/templates/themes/minimal.docx.theme.json +1 -1
- package/dist/templates/themes/modern.docx.theme.json +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/revisionUtils.d.ts +50 -0
- package/dist/utils/revisionUtils.d.ts.map +1 -0
- package/package.json +3 -3
|
@@ -225,7 +225,7 @@ var init_minimal_docx_theme = __esm({
|
|
|
225
225
|
size: 11
|
|
226
226
|
},
|
|
227
227
|
mono: {
|
|
228
|
-
family: "
|
|
228
|
+
family: "Menlo",
|
|
229
229
|
size: 10
|
|
230
230
|
},
|
|
231
231
|
light: {
|
|
@@ -543,7 +543,7 @@ var init_modern_docx_theme = __esm({
|
|
|
543
543
|
fonts: {
|
|
544
544
|
heading: { family: "Helvetica", size: 28 },
|
|
545
545
|
body: { family: "Helvetica", size: 11 },
|
|
546
|
-
mono: { family: "
|
|
546
|
+
mono: { family: "Menlo", size: 10 },
|
|
547
547
|
light: { family: "Helvetica", size: 28 }
|
|
548
548
|
},
|
|
549
549
|
page: {
|
|
@@ -2203,7 +2203,8 @@ async function processDocument(document, theme, themeName) {
|
|
|
2203
2203
|
metadata,
|
|
2204
2204
|
sections,
|
|
2205
2205
|
theme: effectiveTheme,
|
|
2206
|
-
themeName
|
|
2206
|
+
themeName,
|
|
2207
|
+
trackRevisions: document.props.trackRevisions
|
|
2207
2208
|
};
|
|
2208
2209
|
}
|
|
2209
2210
|
function createDocumentMetadata(props) {
|
|
@@ -2662,7 +2663,7 @@ Suggestion: ${suggestion}`
|
|
|
2662
2663
|
import {
|
|
2663
2664
|
Document,
|
|
2664
2665
|
Paragraph as Paragraph7,
|
|
2665
|
-
TextRun as
|
|
2666
|
+
TextRun as TextRun6,
|
|
2666
2667
|
AlignmentType as AlignmentType5,
|
|
2667
2668
|
BookmarkStart as BookmarkStart2,
|
|
2668
2669
|
BookmarkEnd as BookmarkEnd2
|
|
@@ -3995,6 +3996,99 @@ var CacheKeyGenerator = class {
|
|
|
3995
3996
|
}
|
|
3996
3997
|
};
|
|
3997
3998
|
|
|
3999
|
+
// src/utils/revisionUtils.ts
|
|
4000
|
+
import { TextRun as TextRun3, InsertedTextRun, DeletedTextRun } from "docx";
|
|
4001
|
+
var DEFAULT_REVISION_AUTHOR = "json-to-office";
|
|
4002
|
+
var DEFAULT_REVISION_DATE = "1970-01-01T00:00:00Z";
|
|
4003
|
+
var RevisionIdRegistry = class {
|
|
4004
|
+
counter = 0;
|
|
4005
|
+
next() {
|
|
4006
|
+
this.counter += 1;
|
|
4007
|
+
return this.counter;
|
|
4008
|
+
}
|
|
4009
|
+
/** Test-only: deterministic ids for snapshot assertions. */
|
|
4010
|
+
clear() {
|
|
4011
|
+
this.counter = 0;
|
|
4012
|
+
}
|
|
4013
|
+
};
|
|
4014
|
+
var globalRevisionIdRegistry = new RevisionIdRegistry();
|
|
4015
|
+
var PLACEHOLDER_PATTERN = /\{[^}]+\}/;
|
|
4016
|
+
function segmentRuns(text, makeRun) {
|
|
4017
|
+
const lines = text.split("\n");
|
|
4018
|
+
return lines.map(
|
|
4019
|
+
(line, index) => makeRun(index === 0 ? { text: line } : { text: line, break: 1 })
|
|
4020
|
+
);
|
|
4021
|
+
}
|
|
4022
|
+
function createRevisionRuns(revision, baseStyle) {
|
|
4023
|
+
const author = revision.author || DEFAULT_REVISION_AUTHOR;
|
|
4024
|
+
const date = revision.date || DEFAULT_REVISION_DATE;
|
|
4025
|
+
const runs = [];
|
|
4026
|
+
for (const segment of revision.segments) {
|
|
4027
|
+
if (!segment.text) continue;
|
|
4028
|
+
const text = normalizeUnicodeText(segment.text);
|
|
4029
|
+
if (segment.type === "insert") {
|
|
4030
|
+
runs.push(
|
|
4031
|
+
...segmentRuns(
|
|
4032
|
+
text,
|
|
4033
|
+
(options) => new InsertedTextRun({
|
|
4034
|
+
...options,
|
|
4035
|
+
...baseStyle,
|
|
4036
|
+
id: globalRevisionIdRegistry.next(),
|
|
4037
|
+
author,
|
|
4038
|
+
date
|
|
4039
|
+
})
|
|
4040
|
+
)
|
|
4041
|
+
);
|
|
4042
|
+
} else if (segment.type === "delete") {
|
|
4043
|
+
runs.push(
|
|
4044
|
+
...segmentRuns(
|
|
4045
|
+
text,
|
|
4046
|
+
(options) => new DeletedTextRun({
|
|
4047
|
+
...options,
|
|
4048
|
+
...baseStyle,
|
|
4049
|
+
id: globalRevisionIdRegistry.next(),
|
|
4050
|
+
author,
|
|
4051
|
+
date
|
|
4052
|
+
})
|
|
4053
|
+
)
|
|
4054
|
+
);
|
|
4055
|
+
} else if (PLACEHOLDER_PATTERN.test(text)) {
|
|
4056
|
+
runs.push(
|
|
4057
|
+
...processTextWithPlaceholders(text, baseStyle, {})
|
|
4058
|
+
);
|
|
4059
|
+
} else {
|
|
4060
|
+
runs.push(
|
|
4061
|
+
...segmentRuns(
|
|
4062
|
+
text,
|
|
4063
|
+
(options) => new TextRun3({ ...options, ...baseStyle })
|
|
4064
|
+
)
|
|
4065
|
+
);
|
|
4066
|
+
}
|
|
4067
|
+
}
|
|
4068
|
+
return runs;
|
|
4069
|
+
}
|
|
4070
|
+
function componentHasRevision(component) {
|
|
4071
|
+
const props = component.props;
|
|
4072
|
+
if (props) {
|
|
4073
|
+
if (props.revision) return true;
|
|
4074
|
+
const items = props.items;
|
|
4075
|
+
if (Array.isArray(items)) {
|
|
4076
|
+
if (items.some(
|
|
4077
|
+
(item) => typeof item === "object" && item !== null && "revision" in item && item.revision
|
|
4078
|
+
)) {
|
|
4079
|
+
return true;
|
|
4080
|
+
}
|
|
4081
|
+
}
|
|
4082
|
+
}
|
|
4083
|
+
const children = component.children;
|
|
4084
|
+
if (Array.isArray(children)) {
|
|
4085
|
+
return children.some(
|
|
4086
|
+
(child) => typeof child === "object" && child !== null && componentHasRevision(child)
|
|
4087
|
+
);
|
|
4088
|
+
}
|
|
4089
|
+
return false;
|
|
4090
|
+
}
|
|
4091
|
+
|
|
3998
4092
|
// src/core/cached-render.ts
|
|
3999
4093
|
import { createHash as createHash2 } from "crypto";
|
|
4000
4094
|
var componentCache = null;
|
|
@@ -4034,7 +4128,7 @@ function initializeComponentCache(cache) {
|
|
|
4034
4128
|
}
|
|
4035
4129
|
}
|
|
4036
4130
|
async function renderComponentWithCache(component, theme, themeName, context, bypassCache = false) {
|
|
4037
|
-
const forceBypassForType = component.name === "toc" || component.name === "section";
|
|
4131
|
+
const forceBypassForType = component.name === "toc" || component.name === "section" || componentHasRevision(component);
|
|
4038
4132
|
if (!componentCache) {
|
|
4039
4133
|
initializeComponentCache();
|
|
4040
4134
|
}
|
|
@@ -4073,7 +4167,7 @@ async function renderComponentWithCache(component, theme, themeName, context, by
|
|
|
4073
4167
|
// src/core/content.ts
|
|
4074
4168
|
import {
|
|
4075
4169
|
Paragraph,
|
|
4076
|
-
TextRun as
|
|
4170
|
+
TextRun as TextRun4,
|
|
4077
4171
|
Table,
|
|
4078
4172
|
TableRow,
|
|
4079
4173
|
TableCell,
|
|
@@ -4223,24 +4317,43 @@ function createText(content, theme, themeName, options = {}) {
|
|
|
4223
4317
|
underline: options.underline ? { type: "single" } : void 0
|
|
4224
4318
|
}
|
|
4225
4319
|
};
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4320
|
+
if (options.revision) {
|
|
4321
|
+
const revisionRuns = createRevisionRuns(options.revision, baseTextStyle);
|
|
4322
|
+
if (options.bookmarkId) {
|
|
4323
|
+
globalBookmarkRegistry.register(
|
|
4324
|
+
options.bookmarkId,
|
|
4325
|
+
normalizedContent,
|
|
4326
|
+
"paragraph"
|
|
4327
|
+
);
|
|
4328
|
+
children.push(
|
|
4329
|
+
new Bookmark({
|
|
4330
|
+
id: options.bookmarkId,
|
|
4331
|
+
children: revisionRuns
|
|
4332
|
+
})
|
|
4333
|
+
);
|
|
4334
|
+
} else {
|
|
4335
|
+
children.push(...revisionRuns);
|
|
4336
|
+
}
|
|
4242
4337
|
} else {
|
|
4243
|
-
|
|
4338
|
+
const textRuns = parseTextWithDecorators(normalizedContent, baseTextStyle, {
|
|
4339
|
+
boldColor: options.boldColor,
|
|
4340
|
+
enableHyperlinks: true
|
|
4341
|
+
});
|
|
4342
|
+
if (options.bookmarkId) {
|
|
4343
|
+
globalBookmarkRegistry.register(
|
|
4344
|
+
options.bookmarkId,
|
|
4345
|
+
normalizedContent,
|
|
4346
|
+
"paragraph"
|
|
4347
|
+
);
|
|
4348
|
+
children.push(
|
|
4349
|
+
new Bookmark({
|
|
4350
|
+
id: options.bookmarkId,
|
|
4351
|
+
children: textRuns
|
|
4352
|
+
})
|
|
4353
|
+
);
|
|
4354
|
+
} else {
|
|
4355
|
+
children.push(...textRuns);
|
|
4356
|
+
}
|
|
4244
4357
|
}
|
|
4245
4358
|
const isFloating = !!options.floating;
|
|
4246
4359
|
const frameOptions = isFloating && options.floating ? mapFrameOptions(options.floating, theme, themeName) : void 0;
|
|
@@ -4361,7 +4474,24 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
4361
4474
|
underline: options.underline ? { type: "single" } : void 0
|
|
4362
4475
|
}
|
|
4363
4476
|
};
|
|
4364
|
-
if (options.
|
|
4477
|
+
if (options.revision) {
|
|
4478
|
+
const revisionRuns = createRevisionRuns(options.revision, baseTextStyle);
|
|
4479
|
+
if (options.bookmarkId) {
|
|
4480
|
+
globalBookmarkRegistry.register(
|
|
4481
|
+
options.bookmarkId,
|
|
4482
|
+
normalizedText,
|
|
4483
|
+
"heading"
|
|
4484
|
+
);
|
|
4485
|
+
children.push(
|
|
4486
|
+
new Bookmark({
|
|
4487
|
+
id: options.bookmarkId,
|
|
4488
|
+
children: revisionRuns
|
|
4489
|
+
})
|
|
4490
|
+
);
|
|
4491
|
+
} else {
|
|
4492
|
+
children.push(...revisionRuns);
|
|
4493
|
+
}
|
|
4494
|
+
} else if (options.bookmarkId) {
|
|
4365
4495
|
globalBookmarkRegistry.register(
|
|
4366
4496
|
options.bookmarkId,
|
|
4367
4497
|
normalizedText,
|
|
@@ -4376,7 +4506,7 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
4376
4506
|
headingTextChildren.push(...textRuns);
|
|
4377
4507
|
} else {
|
|
4378
4508
|
headingTextChildren.push(
|
|
4379
|
-
new
|
|
4509
|
+
new TextRun4({ text: normalizedText, ...baseTextStyle })
|
|
4380
4510
|
);
|
|
4381
4511
|
}
|
|
4382
4512
|
children.push(
|
|
@@ -4393,7 +4523,7 @@ function createHeading(text, level, theme, _themeName, options = {}) {
|
|
|
4393
4523
|
});
|
|
4394
4524
|
children.push(...textRuns);
|
|
4395
4525
|
} else {
|
|
4396
|
-
children.push(new
|
|
4526
|
+
children.push(new TextRun4({ text: normalizedText, ...baseTextStyle }));
|
|
4397
4527
|
}
|
|
4398
4528
|
}
|
|
4399
4529
|
return new Paragraph({
|
|
@@ -4533,10 +4663,11 @@ function createList(items, _theme, _themeName, options = {}) {
|
|
|
4533
4663
|
items.forEach((item, index) => {
|
|
4534
4664
|
const itemText = typeof item === "string" ? item : item.text;
|
|
4535
4665
|
const itemLevel = typeof item === "object" ? item.level || 0 : 0;
|
|
4536
|
-
|
|
4666
|
+
const itemRevision = typeof item === "object" ? item.revision : void 0;
|
|
4667
|
+
if (!itemText.trim() && !itemRevision) {
|
|
4537
4668
|
return;
|
|
4538
4669
|
}
|
|
4539
|
-
const textRuns = parseTextWithDecorators(
|
|
4670
|
+
const textRuns = itemRevision ? createRevisionRuns(itemRevision, {}) : parseTextWithDecorators(
|
|
4540
4671
|
itemText,
|
|
4541
4672
|
{},
|
|
4542
4673
|
{
|
|
@@ -4949,7 +5080,7 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
4949
5080
|
} catch (error) {
|
|
4950
5081
|
const imageSource = imageComp.props.base64 || imageComp.props.path || "unknown";
|
|
4951
5082
|
cellChildren = [
|
|
4952
|
-
new
|
|
5083
|
+
new TextRun4({
|
|
4953
5084
|
text: `[IMAGE: ${imageSource.substring(0, 50)}${imageSource.length > 50 ? "..." : ""}]`,
|
|
4954
5085
|
font: mergedStyle.font,
|
|
4955
5086
|
size: mergedStyle.size,
|
|
@@ -4959,7 +5090,7 @@ async function createTable(columns, tableConfig, theme, themeName, _options = {}
|
|
|
4959
5090
|
}
|
|
4960
5091
|
} else {
|
|
4961
5092
|
cellChildren = [
|
|
4962
|
-
new
|
|
5093
|
+
new TextRun4({
|
|
4963
5094
|
text: `[Unsupported component type: ${cell.name}]`,
|
|
4964
5095
|
font: mergedStyle.font,
|
|
4965
5096
|
size: mergedStyle.size,
|
|
@@ -5356,7 +5487,9 @@ function renderHeadingComponent(component, theme, themeName) {
|
|
|
5356
5487
|
keepNext: config.keepNext,
|
|
5357
5488
|
keepLines: config.keepLines,
|
|
5358
5489
|
// Bookmark ID for internal linking
|
|
5359
|
-
bookmarkId
|
|
5490
|
+
bookmarkId,
|
|
5491
|
+
// Tracked-change segments (rendered as native Word revisions)
|
|
5492
|
+
revision: config.revision
|
|
5360
5493
|
}
|
|
5361
5494
|
);
|
|
5362
5495
|
return [header];
|
|
@@ -5400,7 +5533,7 @@ function parseMarkdownList(text) {
|
|
|
5400
5533
|
function renderParagraphComponent(component, theme, themeName) {
|
|
5401
5534
|
if (!isParagraphComponent(component)) return [];
|
|
5402
5535
|
const resolvedConfig = component.props;
|
|
5403
|
-
const listData = parseMarkdownList(resolvedConfig.text);
|
|
5536
|
+
const listData = resolvedConfig.revision ? null : parseMarkdownList(resolvedConfig.text);
|
|
5404
5537
|
if (listData) {
|
|
5405
5538
|
const reference = globalNumberingRegistry.generateReference("markdown-list");
|
|
5406
5539
|
const levels = [];
|
|
@@ -5477,7 +5610,9 @@ function renderParagraphComponent(component, theme, themeName) {
|
|
|
5477
5610
|
// Pass keepLines property
|
|
5478
5611
|
keepLines: resolvedConfig.keepLines,
|
|
5479
5612
|
// Pass bookmark ID for internal linking
|
|
5480
|
-
bookmarkId: resolvedConfig.id
|
|
5613
|
+
bookmarkId: resolvedConfig.id,
|
|
5614
|
+
// Tracked-change segments (rendered as native Word revisions)
|
|
5615
|
+
revision: resolvedConfig.revision
|
|
5481
5616
|
});
|
|
5482
5617
|
return [text];
|
|
5483
5618
|
}
|
|
@@ -6107,7 +6242,7 @@ import {
|
|
|
6107
6242
|
Paragraph as Paragraph6,
|
|
6108
6243
|
TableOfContents,
|
|
6109
6244
|
AlignmentType as AlignmentType4,
|
|
6110
|
-
TextRun as
|
|
6245
|
+
TextRun as TextRun5,
|
|
6111
6246
|
StyleLevel
|
|
6112
6247
|
} from "docx";
|
|
6113
6248
|
function parseDepthRange(rawDepth, fieldName, defaultFrom = 1, defaultTo = 3) {
|
|
@@ -6162,7 +6297,7 @@ function renderTocComponent(component, theme, context) {
|
|
|
6162
6297
|
paragraphs.push(
|
|
6163
6298
|
new Paragraph6({
|
|
6164
6299
|
children: [
|
|
6165
|
-
new
|
|
6300
|
+
new TextRun5({
|
|
6166
6301
|
text: componentProps.title,
|
|
6167
6302
|
bold: true,
|
|
6168
6303
|
size: 28
|
|
@@ -6460,8 +6595,10 @@ async function renderDocument(structure, layout, options) {
|
|
|
6460
6595
|
styles: createWordStyles(structure.theme),
|
|
6461
6596
|
sections,
|
|
6462
6597
|
features: {
|
|
6463
|
-
updateFields: true
|
|
6598
|
+
updateFields: true,
|
|
6464
6599
|
// Required for TOC fields to update correctly
|
|
6600
|
+
// Word opens the document in review mode (further edits are tracked)
|
|
6601
|
+
...structure.trackRevisions && { trackRevisions: true }
|
|
6465
6602
|
},
|
|
6466
6603
|
// Add numbering configurations if any lists were rendered
|
|
6467
6604
|
...numberingConfigs.length > 0 && {
|
|
@@ -6506,7 +6643,7 @@ async function renderHeaderFooterComponents(components, theme, themeName, _conte
|
|
|
6506
6643
|
elements.push(
|
|
6507
6644
|
new Paragraph7({
|
|
6508
6645
|
children: [
|
|
6509
|
-
new
|
|
6646
|
+
new TextRun6({
|
|
6510
6647
|
text: "[IMAGE: Missing path or base64 property]",
|
|
6511
6648
|
font: getThemeFonts(theme).body.family,
|
|
6512
6649
|
size: 20,
|
|
@@ -6588,7 +6725,7 @@ async function renderHeaderFooterComponents(components, theme, themeName, _conte
|
|
|
6588
6725
|
elements.push(
|
|
6589
6726
|
new Paragraph7({
|
|
6590
6727
|
children: [
|
|
6591
|
-
new
|
|
6728
|
+
new TextRun6({
|
|
6592
6729
|
text: `[IMAGE: ${imageComp.props.path}]`,
|
|
6593
6730
|
font: getThemeFonts(theme).body.family,
|
|
6594
6731
|
size: 20,
|