@ingcreators/annot-product-docs-xlsx 0.2.0 → 0.2.2
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/CHANGELOG.md +19 -0
- package/dist/extract.d.ts +30 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +185 -145
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @ingcreators/annot-product-docs-xlsx
|
|
2
2
|
|
|
3
|
+
## 0.2.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [b5d52f6]
|
|
8
|
+
- Updated dependencies [fa712fd]
|
|
9
|
+
- Updated dependencies [f09a6b1]
|
|
10
|
+
- Updated dependencies [0d19345]
|
|
11
|
+
- @ingcreators/annot-product-docs@0.4.0
|
|
12
|
+
|
|
13
|
+
## 0.2.1
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Updated dependencies [5778902]
|
|
18
|
+
- Updated dependencies [96e7625]
|
|
19
|
+
- Updated dependencies [85d40e6]
|
|
20
|
+
- @ingcreators/annot-product-docs@0.3.0
|
|
21
|
+
|
|
3
22
|
## 0.2.0
|
|
4
23
|
|
|
5
24
|
### Minor Changes
|
package/dist/extract.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AnnotFrontmatter, HistoryEntrySpec, OverlaySpec, ParsedMdx } from '@ingcreators/annot-product-docs';
|
|
1
|
+
import { AnnotationsFile, AnnotFrontmatter, HistoryEntrySpec, OverlaySpec, ParsedMdx } from '@ingcreators/annot-product-docs';
|
|
2
2
|
export interface ExcelMdxBundle {
|
|
3
3
|
/** Absolute or cwd-relative path to the source `.mdx` file. */
|
|
4
4
|
mdxPath: string;
|
|
@@ -34,15 +34,43 @@ export interface NormalisedOverlay {
|
|
|
34
34
|
/** Markdown body — caller renders to rich text. */
|
|
35
35
|
body: string;
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Optional context for {@link extractFromParsed}. Phase 3d of
|
|
39
|
+
* `docs/plans/living-spec-authoring-roadmap.md`. When a `<Screen>`
|
|
40
|
+
* carries `annotations="…"`, the row generator wants the resolved
|
|
41
|
+
* yaml content — but we don't want `extractFromParsed` to do file
|
|
42
|
+
* I/O. The caller (`extractMdxFile`) pre-loads + parses each yaml
|
|
43
|
+
* keyed by the `annotations` path (relative to the MDX) and passes
|
|
44
|
+
* the map here. When the map is missing an entry (or this context
|
|
45
|
+
* isn't supplied), the extractor falls back to the legacy inline
|
|
46
|
+
* `<Overlay>` rows for that screen.
|
|
47
|
+
*
|
|
48
|
+
* `annotations[]` entries in the yaml are deliberately NOT
|
|
49
|
+
* surfaced as rows — they're image-only visual marking. The
|
|
50
|
+
* Astro Image Service composes them onto the PNG; the Excel
|
|
51
|
+
* adapter renders the resulting image in the spreadsheet's
|
|
52
|
+
* picture column and the items table stays scoped to overlays.
|
|
53
|
+
*/
|
|
54
|
+
export interface ExtractFromParsedOptions {
|
|
55
|
+
/** Pre-loaded annotation yaml content keyed by the screen's `annotations` value. */
|
|
56
|
+
annotationsYamlByPath?: ReadonlyMap<string, AnnotationsFile>;
|
|
57
|
+
}
|
|
37
58
|
/**
|
|
38
59
|
* Extract a normalised bundle from a parsed MDX. Used directly
|
|
39
60
|
* by `extractMdxFile` and re-exposed so tests can drive it
|
|
40
61
|
* without filesystem I/O.
|
|
41
62
|
*/
|
|
42
|
-
export declare function extractFromParsed(parsed: ParsedMdx, mdxPath: string): ExcelMdxBundle;
|
|
63
|
+
export declare function extractFromParsed(parsed: ParsedMdx, mdxPath: string, options?: ExtractFromParsedOptions): ExcelMdxBundle;
|
|
43
64
|
/**
|
|
44
65
|
* Convenience: parse the MDX file and normalise. Returns `null`
|
|
45
66
|
* for files without `annot:` frontmatter so the bulk-extract
|
|
46
67
|
* caller can keep its glob noise-free.
|
|
68
|
+
*
|
|
69
|
+
* Phase 3d: when the MDX contains `<Screen annotations="…">`
|
|
70
|
+
* blocks, the matching yaml files are loaded + parsed from disk
|
|
71
|
+
* before {@link extractFromParsed} runs. Missing yaml files are
|
|
72
|
+
* a loud failure (`throw`) — the same behaviour the Astro Image
|
|
73
|
+
* Service uses, on the same "explicit reference, but file gone"
|
|
74
|
+
* reasoning.
|
|
47
75
|
*/
|
|
48
76
|
export declare function extractMdxFile(mdxPath: string): Promise<ExcelMdxBundle | null>;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export type { CliOptions } from './cli.js';
|
|
|
2
2
|
export { main, main as cliMain } from './cli.js';
|
|
3
3
|
export type { ApplyDefaultLayoutInput } from './default-layout.js';
|
|
4
4
|
export { applyDefaultLayout, sanitiseSheetName, sortBundlesForLayout, } from './default-layout.js';
|
|
5
|
-
export type { ExcelMdxBundle, NormalisedOverlay, NormalisedScreen, } from './extract.js';
|
|
5
|
+
export type { ExcelMdxBundle, ExtractFromParsedOptions, NormalisedOverlay, NormalisedScreen, } from './extract.js';
|
|
6
6
|
export { extractFromParsed, extractMdxFile } from './extract.js';
|
|
7
7
|
export type { NamedRangeWriteInput } from './named-range.js';
|
|
8
8
|
export { applyNamedRanges } from './named-range.js';
|
package/dist/index.js
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import { mkdir as e,
|
|
2
|
-
import { join as
|
|
3
|
-
import { pathToFileURL as
|
|
4
|
-
import { parseMdxFile as
|
|
5
|
-
import
|
|
1
|
+
import { mkdir as e, readFile as t, readdir as n, writeFile as r } from "node:fs/promises";
|
|
2
|
+
import { dirname as i, isAbsolute as a, join as o, resolve as s } from "node:path";
|
|
3
|
+
import { pathToFileURL as c } from "node:url";
|
|
4
|
+
import { parseAnnotationsYaml as l, parseMdxFile as u } from "@ingcreators/annot-product-docs";
|
|
5
|
+
import d from "exceljs";
|
|
6
6
|
//#region src/default-layout.ts
|
|
7
|
-
var
|
|
7
|
+
var f = {
|
|
8
8
|
cover: 1,
|
|
9
9
|
history: 2,
|
|
10
10
|
list: 3,
|
|
11
11
|
screen: 4,
|
|
12
12
|
reference: 5
|
|
13
13
|
};
|
|
14
|
-
function
|
|
15
|
-
let t =
|
|
14
|
+
function p(e) {
|
|
15
|
+
let t = m(e.bundles);
|
|
16
16
|
for (let n of t) {
|
|
17
|
-
let t = n.frontmatter.xlsx?.role ?? "screen", r =
|
|
17
|
+
let t = n.frontmatter.xlsx?.role ?? "screen", r = te(n, t), i = e.workbook.addWorksheet(r);
|
|
18
18
|
switch (t) {
|
|
19
19
|
case "cover":
|
|
20
|
-
|
|
20
|
+
h(i, n);
|
|
21
21
|
break;
|
|
22
22
|
case "history":
|
|
23
|
-
|
|
23
|
+
g(i, n);
|
|
24
24
|
break;
|
|
25
25
|
case "list":
|
|
26
|
-
|
|
26
|
+
_(i, e.bundles);
|
|
27
27
|
break;
|
|
28
28
|
case "reference":
|
|
29
|
-
|
|
29
|
+
v(i, n);
|
|
30
30
|
break;
|
|
31
|
-
default:
|
|
31
|
+
default: ee(i, n);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
-
function
|
|
35
|
+
function m(e) {
|
|
36
36
|
return [...e].sort((e, t) => {
|
|
37
|
-
let n =
|
|
37
|
+
let n = f[e.frontmatter.xlsx?.role ?? "screen"] ?? 99, r = f[t.frontmatter.xlsx?.role ?? "screen"] ?? 99;
|
|
38
38
|
if (n !== r) return n - r;
|
|
39
39
|
let i = e.frontmatter.xlsx?.order ?? 100, a = t.frontmatter.xlsx?.order ?? 100;
|
|
40
40
|
return i === a ? e.mdxPath.localeCompare(t.mdxPath) : i - a;
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
|
-
function
|
|
43
|
+
function h(e, t) {
|
|
44
44
|
let n = t.frontmatter;
|
|
45
45
|
if (e.columns = [{
|
|
46
46
|
key: "label",
|
|
@@ -63,7 +63,7 @@ function d(e, t) {
|
|
|
63
63
|
});
|
|
64
64
|
e.getColumn(1).font = { bold: !0 };
|
|
65
65
|
}
|
|
66
|
-
function
|
|
66
|
+
function g(e, t) {
|
|
67
67
|
e.columns = [
|
|
68
68
|
{
|
|
69
69
|
header: "Version",
|
|
@@ -94,7 +94,7 @@ function f(e, t) {
|
|
|
94
94
|
});
|
|
95
95
|
e.getRow(1).font = { bold: !0 };
|
|
96
96
|
}
|
|
97
|
-
function
|
|
97
|
+
function _(e, t) {
|
|
98
98
|
e.columns = [
|
|
99
99
|
{
|
|
100
100
|
header: "ID",
|
|
@@ -125,7 +125,7 @@ function p(e, t) {
|
|
|
125
125
|
});
|
|
126
126
|
e.getRow(1).font = { bold: !0 };
|
|
127
127
|
}
|
|
128
|
-
function
|
|
128
|
+
function ee(e, t) {
|
|
129
129
|
let n = t.frontmatter;
|
|
130
130
|
e.addRow(["ID", n.id]), e.addRow(["Title", n.title ?? ""]), n.purpose && e.addRow(["Purpose", n.purpose]), e.addRow([]), e.addRow([
|
|
131
131
|
"#",
|
|
@@ -145,97 +145,137 @@ function m(e, t) {
|
|
|
145
145
|
]);
|
|
146
146
|
e.getColumn(1).width = 6, e.getColumn(2).width = 14, e.getColumn(3).width = 24, e.getColumn(4).width = 12, e.getColumn(5).width = 60, e.getColumn(1).font = { bold: !0 };
|
|
147
147
|
}
|
|
148
|
-
function
|
|
148
|
+
function v(e, t) {
|
|
149
149
|
e.addRow(["ID", t.frontmatter.id]), e.addRow(["Title", t.frontmatter.title ?? ""]), t.frontmatter.purpose && e.addRow(["Purpose", t.frontmatter.purpose]);
|
|
150
150
|
}
|
|
151
|
-
function
|
|
151
|
+
function te(e, t) {
|
|
152
152
|
let n = e.frontmatter.xlsx;
|
|
153
|
-
return typeof n?.sheet == "string" && n.sheet.length > 0 ?
|
|
153
|
+
return typeof n?.sheet == "string" && n.sheet.length > 0 ? y(n.sheet) : t === "cover" ? "Cover" : t === "history" ? "Revision history" : t === "list" ? "Screen list" : y(t === "reference" ? e.frontmatter.id : e.frontmatter.title ?? e.frontmatter.id);
|
|
154
154
|
}
|
|
155
|
-
function
|
|
155
|
+
function y(e) {
|
|
156
156
|
let t = e.replace(/[\\/?*[\]:]/g, "_").slice(0, 31);
|
|
157
157
|
return t.length > 0 ? t : "Sheet";
|
|
158
158
|
}
|
|
159
159
|
//#endregion
|
|
160
160
|
//#region src/extract.ts
|
|
161
|
-
function
|
|
162
|
-
let n = e.screens.map((e) => ({
|
|
161
|
+
function b(e, t, n = {}) {
|
|
162
|
+
let r = n.annotationsYamlByPath, i = e.screens.map((e) => ({
|
|
163
163
|
id: e.id,
|
|
164
164
|
src: e.src,
|
|
165
|
-
overlayCount: e
|
|
166
|
-
})),
|
|
165
|
+
overlayCount: ne(e, r)
|
|
166
|
+
})), a = [];
|
|
167
167
|
for (let t of e.screens) {
|
|
168
|
-
let e =
|
|
169
|
-
for (let n of
|
|
170
|
-
let
|
|
171
|
-
|
|
168
|
+
let e = S(t, r);
|
|
169
|
+
if (e) for (let n of e) {
|
|
170
|
+
let e = t.callouts.find((e) => e.for === n.id);
|
|
171
|
+
a.push({
|
|
172
172
|
screenId: t.id,
|
|
173
|
-
number:
|
|
173
|
+
number: n.number,
|
|
174
174
|
intent: n.intent,
|
|
175
|
-
matchLabel:
|
|
175
|
+
matchLabel: T(n),
|
|
176
176
|
matchRole: n.match.role,
|
|
177
177
|
matchName: n.match.name,
|
|
178
|
-
body:
|
|
178
|
+
body: e?.body ?? ""
|
|
179
179
|
});
|
|
180
180
|
}
|
|
181
|
+
else {
|
|
182
|
+
let e = 1;
|
|
183
|
+
for (let n of t.overlays) {
|
|
184
|
+
let r = n.number ?? e++;
|
|
185
|
+
a.push({
|
|
186
|
+
screenId: t.id,
|
|
187
|
+
number: r,
|
|
188
|
+
intent: n.intent,
|
|
189
|
+
matchLabel: w(n),
|
|
190
|
+
matchRole: n.match.role,
|
|
191
|
+
matchName: n.match.name,
|
|
192
|
+
body: n.body
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
181
196
|
}
|
|
182
197
|
return {
|
|
183
198
|
mdxPath: t,
|
|
184
199
|
source: e.source,
|
|
185
200
|
frontmatter: e.frontmatter,
|
|
186
|
-
screens:
|
|
187
|
-
overlays:
|
|
201
|
+
screens: i,
|
|
202
|
+
overlays: a,
|
|
188
203
|
history: e.history,
|
|
189
204
|
snapshotYaml: e.commentBlocks.snapshot ?? "",
|
|
190
205
|
attributesYaml: e.commentBlocks.attributes ?? ""
|
|
191
206
|
};
|
|
192
207
|
}
|
|
193
|
-
async function
|
|
194
|
-
let t = await
|
|
195
|
-
return t ?
|
|
208
|
+
async function x(e) {
|
|
209
|
+
let t = await u(e);
|
|
210
|
+
return t ? b(t, e, { annotationsYamlByPath: await C(t, e) }) : null;
|
|
211
|
+
}
|
|
212
|
+
function ne(e, t) {
|
|
213
|
+
let n = S(e, t);
|
|
214
|
+
return n ? n.length : e.overlays.length;
|
|
215
|
+
}
|
|
216
|
+
function S(e, t) {
|
|
217
|
+
return !t || !e.annotations ? null : t.get(e.annotations)?.overlays ?? null;
|
|
196
218
|
}
|
|
197
|
-
function
|
|
219
|
+
async function C(e, n) {
|
|
220
|
+
let r = /* @__PURE__ */ new Map(), o = i(n);
|
|
221
|
+
for (let n of e.screens) {
|
|
222
|
+
if (!n.annotations || r.has(n.annotations)) continue;
|
|
223
|
+
let e = a(n.annotations) ? n.annotations : s(o, n.annotations), i;
|
|
224
|
+
try {
|
|
225
|
+
i = await t(e, "utf8");
|
|
226
|
+
} catch (t) {
|
|
227
|
+
throw Error(`extractMdxFile: <Screen annotations="${n.annotations}"> — failed to read ${e}: ${t.message}`);
|
|
228
|
+
}
|
|
229
|
+
r.set(n.annotations, l(i));
|
|
230
|
+
}
|
|
231
|
+
return r;
|
|
232
|
+
}
|
|
233
|
+
function w(e) {
|
|
234
|
+
let t = `${e.match.role} "${e.match.name}"`;
|
|
235
|
+
return e.match.under ? `${t} under ${e.match.under.role} "${e.match.under.name}"` : t;
|
|
236
|
+
}
|
|
237
|
+
function T(e) {
|
|
198
238
|
let t = `${e.match.role} "${e.match.name}"`;
|
|
199
239
|
return e.match.under ? `${t} under ${e.match.under.role} "${e.match.under.name}"` : t;
|
|
200
240
|
}
|
|
201
241
|
//#endregion
|
|
202
242
|
//#region src/placeholder.ts
|
|
203
|
-
var
|
|
204
|
-
function
|
|
243
|
+
var E = /\{([^{}]+)\}/g, D = "annot:";
|
|
244
|
+
function O(e, t, n = {}) {
|
|
205
245
|
let r = n.totalSheets ?? e.worksheets.length;
|
|
206
246
|
e.worksheets.forEach((e, i) => {
|
|
207
|
-
|
|
247
|
+
k(e, t, {
|
|
208
248
|
...n,
|
|
209
249
|
sheetIndex: n.sheetIndex ?? i + 1,
|
|
210
250
|
totalSheets: r
|
|
211
251
|
});
|
|
212
252
|
});
|
|
213
253
|
}
|
|
214
|
-
function
|
|
254
|
+
function k(e, t, n = {}) {
|
|
215
255
|
e.eachRow({ includeEmpty: !1 }, (e) => {
|
|
216
256
|
e.eachCell({ includeEmpty: !1 }, (e) => {
|
|
217
257
|
let r = e.value;
|
|
218
258
|
if (typeof r != "string") return;
|
|
219
|
-
let i =
|
|
259
|
+
let i = A(r, t, n);
|
|
220
260
|
i !== r && (e.value = i);
|
|
221
261
|
});
|
|
222
262
|
});
|
|
223
263
|
}
|
|
224
|
-
function
|
|
225
|
-
return e.replace(
|
|
226
|
-
let { key: i, format: a } =
|
|
227
|
-
return o === void 0 ? e : a ?
|
|
264
|
+
function A(e, t, n = {}) {
|
|
265
|
+
return e.replace(E, (e, r) => {
|
|
266
|
+
let { key: i, format: a } = j(r), o = M(i, t, n);
|
|
267
|
+
return o === void 0 ? e : a ? N(o, a) : o;
|
|
228
268
|
});
|
|
229
269
|
}
|
|
230
|
-
function
|
|
270
|
+
function j(e) {
|
|
231
271
|
let t = e.trim();
|
|
232
|
-
if (t.startsWith(
|
|
272
|
+
if (t.startsWith(D)) {
|
|
233
273
|
let e = t.slice(6), n = e.indexOf(":");
|
|
234
274
|
return n < 0 ? {
|
|
235
275
|
key: t,
|
|
236
276
|
format: void 0
|
|
237
277
|
} : {
|
|
238
|
-
key:
|
|
278
|
+
key: D + e.slice(0, n),
|
|
239
279
|
format: e.slice(n + 1)
|
|
240
280
|
};
|
|
241
281
|
}
|
|
@@ -248,11 +288,11 @@ function w(e) {
|
|
|
248
288
|
format: t.slice(n + 1)
|
|
249
289
|
};
|
|
250
290
|
}
|
|
251
|
-
function
|
|
252
|
-
if (e.startsWith(
|
|
291
|
+
function M(e, t, n) {
|
|
292
|
+
if (e.startsWith(D)) {
|
|
253
293
|
let t = e.slice(6), r = n.renderTime ?? /* @__PURE__ */ new Date();
|
|
254
294
|
switch (t) {
|
|
255
|
-
case "date": return
|
|
295
|
+
case "date": return F(r, "yyyy-MM-dd");
|
|
256
296
|
case "datetime": return r.toISOString();
|
|
257
297
|
case "sheetIndex": return n.sheetIndex === void 0 ? void 0 : String(n.sheetIndex);
|
|
258
298
|
case "totalSheets": return n.totalSheets === void 0 ? void 0 : String(n.totalSheets);
|
|
@@ -269,24 +309,24 @@ function T(e, t, n) {
|
|
|
269
309
|
let r = n.projectMeta?.[e];
|
|
270
310
|
if (r !== void 0) return String(r);
|
|
271
311
|
}
|
|
272
|
-
function
|
|
273
|
-
let n =
|
|
274
|
-
return n ?
|
|
312
|
+
function N(e, t) {
|
|
313
|
+
let n = P(e);
|
|
314
|
+
return n ? F(n, t) : e;
|
|
275
315
|
}
|
|
276
|
-
function
|
|
316
|
+
function P(e) {
|
|
277
317
|
let t = e.trim(), n = t.match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
|
278
318
|
if (n) return new Date(Number.parseInt(n[1], 10), Number.parseInt(n[2], 10) - 1, Number.parseInt(n[3], 10));
|
|
279
319
|
let r = new Date(t);
|
|
280
320
|
return Number.isNaN(r.getTime()) ? null : r;
|
|
281
321
|
}
|
|
282
|
-
function
|
|
322
|
+
function F(e, t) {
|
|
283
323
|
let n = String(e.getFullYear()).padStart(4, "0"), r = String(e.getMonth() + 1).padStart(2, "0"), i = String(e.getDate()).padStart(2, "0"), a = String(e.getHours()).padStart(2, "0"), o = String(e.getMinutes()).padStart(2, "0"), s = String(e.getSeconds()).padStart(2, "0");
|
|
284
324
|
return t.replace(/yyyy/g, n).replace(/MM/g, r).replace(/dd/g, i).replace(/HH/g, a).replace(/mm/g, o).replace(/ss/g, s);
|
|
285
325
|
}
|
|
286
326
|
//#endregion
|
|
287
327
|
//#region src/template.ts
|
|
288
|
-
function
|
|
289
|
-
let t =
|
|
328
|
+
function I(e) {
|
|
329
|
+
let t = m(e.bundles);
|
|
290
330
|
for (let n of t) {
|
|
291
331
|
let t = n.frontmatter.xlsx?.role ?? "screen", r = e.bookConfig.templateSheets?.[t];
|
|
292
332
|
if (!r) continue;
|
|
@@ -295,18 +335,18 @@ function k(e) {
|
|
|
295
335
|
let a = n.frontmatter.xlsx?.sheets;
|
|
296
336
|
if (a) {
|
|
297
337
|
let t = Object.entries(a);
|
|
298
|
-
for (let [, r] of t)
|
|
338
|
+
for (let [, r] of t) k(R(e.workbook, i, y(r)), n, e.substitute ?? {});
|
|
299
339
|
continue;
|
|
300
340
|
}
|
|
301
|
-
let o =
|
|
302
|
-
|
|
341
|
+
let o = y(n.frontmatter.xlsx?.sheet ?? n.frontmatter.title ?? n.frontmatter.id);
|
|
342
|
+
k(R(e.workbook, i, o), n, e.substitute ?? {});
|
|
303
343
|
}
|
|
304
344
|
}
|
|
305
|
-
async function
|
|
306
|
-
let t = new
|
|
345
|
+
async function L(e) {
|
|
346
|
+
let t = new d.Workbook();
|
|
307
347
|
return await t.xlsx.readFile(e), t;
|
|
308
348
|
}
|
|
309
|
-
function
|
|
349
|
+
function R(e, t, n) {
|
|
310
350
|
let r = e.addWorksheet(n);
|
|
311
351
|
r.columns = t.columns.map((e) => ({
|
|
312
352
|
header: e.header,
|
|
@@ -320,23 +360,23 @@ function j(e, t, n) {
|
|
|
320
360
|
r.value = e.value, e.style && (r.style = e.style);
|
|
321
361
|
}), e.height !== void 0 && (n.height = e.height), n.commit();
|
|
322
362
|
});
|
|
323
|
-
for (let e of Object.values(
|
|
363
|
+
for (let e of Object.values(z(t))) r.mergeCells(e);
|
|
324
364
|
return r;
|
|
325
365
|
}
|
|
326
|
-
function
|
|
366
|
+
function z(e) {
|
|
327
367
|
return e._merges ?? {};
|
|
328
368
|
}
|
|
329
369
|
//#endregion
|
|
330
370
|
//#region src/workbook.ts
|
|
331
|
-
function
|
|
332
|
-
let t = new
|
|
371
|
+
function B(e) {
|
|
372
|
+
let t = new d.Workbook();
|
|
333
373
|
return t.creator = "@ingcreators/annot-product-docs-xlsx", t.created = /* @__PURE__ */ new Date(), t.title = e.book, t;
|
|
334
374
|
}
|
|
335
|
-
async function
|
|
375
|
+
async function V(e) {
|
|
336
376
|
let t = await e.xlsx.writeBuffer();
|
|
337
377
|
return t instanceof Buffer ? new Uint8Array(t.buffer, t.byteOffset, t.byteLength) : new Uint8Array(t);
|
|
338
378
|
}
|
|
339
|
-
function
|
|
379
|
+
function H(e, t) {
|
|
340
380
|
let n = /* @__PURE__ */ new Map();
|
|
341
381
|
for (let r of e) {
|
|
342
382
|
let e = r.frontmatter.xlsx?.book ?? t;
|
|
@@ -348,7 +388,7 @@ function F(e, t) {
|
|
|
348
388
|
}
|
|
349
389
|
//#endregion
|
|
350
390
|
//#region src/cli.ts
|
|
351
|
-
var
|
|
391
|
+
var U = [
|
|
352
392
|
"annot-docs-xlsx <command> [options]",
|
|
353
393
|
"",
|
|
354
394
|
"Commands:",
|
|
@@ -361,17 +401,17 @@ var I = [
|
|
|
361
401
|
" --config <file> Path to annot-docs.config.ts (default: ./annot-docs.config.ts)",
|
|
362
402
|
" --help Show this help"
|
|
363
403
|
].join("\n");
|
|
364
|
-
async function
|
|
404
|
+
async function W(e, t = {}) {
|
|
365
405
|
let n = t.stdout ?? ((e) => process.stdout.write(`${e}\n`)), r = t.stderr ?? ((e) => process.stderr.write(`${e}\n`)), i = t.cwd ?? process.cwd(), [, , a, ...o] = e;
|
|
366
|
-
if (a !== "render") return r(
|
|
367
|
-
let s =
|
|
406
|
+
if (a !== "render") return r(U), +!!a;
|
|
407
|
+
let s = G(o);
|
|
368
408
|
try {
|
|
369
|
-
return await
|
|
409
|
+
return await K(i, s, n);
|
|
370
410
|
} catch (e) {
|
|
371
411
|
return r(`annot-docs-xlsx render: ${e.message}`), 1;
|
|
372
412
|
}
|
|
373
413
|
}
|
|
374
|
-
function
|
|
414
|
+
function G(e) {
|
|
375
415
|
let t = "docs", n = "dist/xlsx", r, i = "annot-docs.config.ts";
|
|
376
416
|
for (let a = 0; a < e.length; a++) {
|
|
377
417
|
let o = e[a];
|
|
@@ -384,99 +424,99 @@ function R(e) {
|
|
|
384
424
|
config: i
|
|
385
425
|
};
|
|
386
426
|
}
|
|
387
|
-
async function
|
|
388
|
-
let
|
|
389
|
-
if (c.length === 0) return
|
|
390
|
-
let
|
|
391
|
-
await e(
|
|
392
|
-
let
|
|
393
|
-
for (let [e, c] of
|
|
394
|
-
if (
|
|
395
|
-
let
|
|
427
|
+
async function K(t, n, i) {
|
|
428
|
+
let a = await q(s(t, n.config), i), c = await J(await re(s(t, n.root)));
|
|
429
|
+
if (c.length === 0) return i(`annot-docs-xlsx render: no MDX files with \`annot:\` frontmatter under ${n.root}.`), 0;
|
|
430
|
+
let l = H(c, a.xlsx?.defaultBook), u = s(t, n.out);
|
|
431
|
+
await e(u, { recursive: !0 });
|
|
432
|
+
let d = 0;
|
|
433
|
+
for (let [e, c] of l.entries()) {
|
|
434
|
+
if (n.book && e !== n.book) continue;
|
|
435
|
+
let l = B({
|
|
396
436
|
book: e,
|
|
397
437
|
bundles: c
|
|
398
|
-
}),
|
|
399
|
-
m ?
|
|
400
|
-
workbook:
|
|
401
|
-
template: await
|
|
402
|
-
bookConfig:
|
|
438
|
+
}), f = a.xlsx?.books?.[e], m = f?.template;
|
|
439
|
+
m ? I({
|
|
440
|
+
workbook: l,
|
|
441
|
+
template: await L(s(t, m)),
|
|
442
|
+
bookConfig: f,
|
|
403
443
|
bundles: c,
|
|
404
444
|
substitute: {
|
|
405
|
-
projectMeta:
|
|
445
|
+
projectMeta: a.meta,
|
|
406
446
|
renderTime: /* @__PURE__ */ new Date()
|
|
407
447
|
}
|
|
408
|
-
}) :
|
|
409
|
-
workbook:
|
|
448
|
+
}) : p({
|
|
449
|
+
workbook: l,
|
|
410
450
|
bundles: c
|
|
411
451
|
});
|
|
412
|
-
let h = await
|
|
413
|
-
await
|
|
452
|
+
let h = await V(l), g = o(u, `${Y(e)}.xlsx`);
|
|
453
|
+
await r(g, h), i(` wrote ${g} (${c.length} MDX file(s))`), d++;
|
|
414
454
|
}
|
|
415
|
-
return
|
|
455
|
+
return n.book && d === 0 ? (i(`annot-docs-xlsx render: book "${n.book}" not found (had: ${[...l.keys()].join(", ")}).`), 1) : (i(`annot-docs-xlsx render: emitted ${d} workbook(s) to ${n.out}`), 0);
|
|
416
456
|
}
|
|
417
|
-
async function
|
|
457
|
+
async function q(e, t) {
|
|
418
458
|
try {
|
|
419
|
-
let t = await import(
|
|
459
|
+
let t = await import(c(e).href);
|
|
420
460
|
return t.default ?? t;
|
|
421
461
|
} catch (n) {
|
|
422
462
|
if (n.code === "ERR_MODULE_NOT_FOUND") return t(`annot-docs-xlsx render: no config at ${e} — using defaults.`), {};
|
|
423
463
|
throw n;
|
|
424
464
|
}
|
|
425
465
|
}
|
|
426
|
-
async function
|
|
427
|
-
let
|
|
428
|
-
for (;
|
|
429
|
-
let e =
|
|
466
|
+
async function re(e) {
|
|
467
|
+
let t = [], r = [e];
|
|
468
|
+
for (; r.length > 0;) {
|
|
469
|
+
let e = r.pop(), i;
|
|
430
470
|
try {
|
|
431
|
-
|
|
471
|
+
i = await n(e, { withFileTypes: !0 });
|
|
432
472
|
} catch (e) {
|
|
433
473
|
if (e.code === "ENOENT") continue;
|
|
434
474
|
throw e;
|
|
435
475
|
}
|
|
436
|
-
for (let
|
|
437
|
-
let
|
|
438
|
-
if (
|
|
439
|
-
if (
|
|
440
|
-
|
|
441
|
-
} else
|
|
476
|
+
for (let n of i) {
|
|
477
|
+
let i = o(e, n.name);
|
|
478
|
+
if (n.isDirectory()) {
|
|
479
|
+
if (n.name === "node_modules" || n.name.startsWith(".")) continue;
|
|
480
|
+
r.push(i);
|
|
481
|
+
} else n.isFile() && n.name.endsWith(".mdx") && t.push(i);
|
|
442
482
|
}
|
|
443
483
|
}
|
|
444
|
-
return
|
|
484
|
+
return t.sort();
|
|
445
485
|
}
|
|
446
|
-
async function
|
|
486
|
+
async function J(e) {
|
|
447
487
|
let t = [];
|
|
448
488
|
for (let n of e) try {
|
|
449
|
-
let e = await
|
|
450
|
-
e && t.push(
|
|
489
|
+
let e = await u(n);
|
|
490
|
+
e && t.push(b(e, n));
|
|
451
491
|
} catch {}
|
|
452
492
|
return t;
|
|
453
493
|
}
|
|
454
|
-
function
|
|
494
|
+
function Y(e) {
|
|
455
495
|
return e.replace(/[\\/?*[\]:<>|"]/g, "_");
|
|
456
496
|
}
|
|
457
497
|
//#endregion
|
|
458
498
|
//#region src/named-range.ts
|
|
459
|
-
var
|
|
460
|
-
function
|
|
461
|
-
for (let t of
|
|
499
|
+
var X = "annot";
|
|
500
|
+
function ie(e) {
|
|
501
|
+
for (let t of fe(e.workbook)) ae(e, t);
|
|
462
502
|
}
|
|
463
|
-
function
|
|
464
|
-
let [n, r] =
|
|
503
|
+
function ae(e, t) {
|
|
504
|
+
let [n, r] = oe(t.name.replace(/^annot/, ""));
|
|
465
505
|
switch (n) {
|
|
466
506
|
case "Image":
|
|
467
|
-
|
|
507
|
+
se(e, t, r);
|
|
468
508
|
return;
|
|
469
509
|
case "ItemTable":
|
|
470
|
-
|
|
510
|
+
ce(t, e.bundle);
|
|
471
511
|
return;
|
|
472
512
|
case "Transitions":
|
|
473
|
-
|
|
513
|
+
le(t, e.bundle);
|
|
474
514
|
return;
|
|
475
515
|
case "History":
|
|
476
|
-
|
|
516
|
+
ue(t, e.bundle);
|
|
477
517
|
return;
|
|
478
518
|
case "List":
|
|
479
|
-
|
|
519
|
+
de(t, e.allBundles ?? [e.bundle]);
|
|
480
520
|
return;
|
|
481
521
|
case "Snapshot":
|
|
482
522
|
Q(t, e.bundle.snapshotYaml);
|
|
@@ -486,11 +526,11 @@ function K(e, t) {
|
|
|
486
526
|
return;
|
|
487
527
|
}
|
|
488
528
|
}
|
|
489
|
-
function
|
|
529
|
+
function oe(e) {
|
|
490
530
|
let t = e.indexOf("_");
|
|
491
531
|
return t < 0 ? [e, void 0] : [e.slice(0, t), e.slice(t + 1)];
|
|
492
532
|
}
|
|
493
|
-
function
|
|
533
|
+
function se(e, t, n) {
|
|
494
534
|
let r = n ? e.imagesByScreenId?.[n] : e.defaultImage ?? e.imagesByScreenId?.[e.bundle.screens[0]?.id ?? ""];
|
|
495
535
|
if (!r) return;
|
|
496
536
|
let i = e.workbook.addImage({
|
|
@@ -499,7 +539,7 @@ function J(e, t, n) {
|
|
|
499
539
|
});
|
|
500
540
|
t.sheet.addImage(i, t.address);
|
|
501
541
|
}
|
|
502
|
-
function
|
|
542
|
+
function Z(e, t, n) {
|
|
503
543
|
let { sheet: r, box: i } = e;
|
|
504
544
|
for (let e = 0; e < t.length; e++) {
|
|
505
545
|
let n = r.getCell(i.startRow, i.startCol + e);
|
|
@@ -511,8 +551,8 @@ function Y(e, t, n) {
|
|
|
511
551
|
for (let e = 0; e < t.length; e++) r.getCell(a, i.startCol + e).value = t[e] ?? "";
|
|
512
552
|
}
|
|
513
553
|
}
|
|
514
|
-
function
|
|
515
|
-
|
|
554
|
+
function ce(e, t) {
|
|
555
|
+
Z(e, [
|
|
516
556
|
"#",
|
|
517
557
|
"Role",
|
|
518
558
|
"Name",
|
|
@@ -526,16 +566,16 @@ function X(e, t) {
|
|
|
526
566
|
e.body
|
|
527
567
|
]));
|
|
528
568
|
}
|
|
529
|
-
function
|
|
530
|
-
|
|
569
|
+
function le(e, t) {
|
|
570
|
+
Z(e, [
|
|
531
571
|
"Trigger",
|
|
532
572
|
"Event",
|
|
533
573
|
"Target",
|
|
534
574
|
"Notes"
|
|
535
575
|
], []);
|
|
536
576
|
}
|
|
537
|
-
function
|
|
538
|
-
|
|
577
|
+
function ue(e, t) {
|
|
578
|
+
Z(e, [
|
|
539
579
|
"Version",
|
|
540
580
|
"Date",
|
|
541
581
|
"Author",
|
|
@@ -547,8 +587,8 @@ function ne(e, t) {
|
|
|
547
587
|
e.body
|
|
548
588
|
]));
|
|
549
589
|
}
|
|
550
|
-
function
|
|
551
|
-
|
|
590
|
+
function de(e, t) {
|
|
591
|
+
Z(e, [
|
|
552
592
|
"ID",
|
|
553
593
|
"Title",
|
|
554
594
|
"Screens",
|
|
@@ -567,13 +607,13 @@ function Q(e, t) {
|
|
|
567
607
|
vertical: "top"
|
|
568
608
|
};
|
|
569
609
|
}
|
|
570
|
-
function
|
|
610
|
+
function fe(e) {
|
|
571
611
|
let t = /* @__PURE__ */ new Map();
|
|
572
612
|
for (let n of e.worksheets) n.eachRow({ includeEmpty: !0 }, (e, r) => {
|
|
573
613
|
e.eachCell({ includeEmpty: !0 }, (e, i) => {
|
|
574
|
-
let a =
|
|
614
|
+
let a = pe(e);
|
|
575
615
|
for (let e of a) {
|
|
576
|
-
if (!e.startsWith(
|
|
616
|
+
if (!e.startsWith(X)) continue;
|
|
577
617
|
let a = `${n.name}|${e}`, o = t.get(a);
|
|
578
618
|
o || (o = {
|
|
579
619
|
sheet: n,
|
|
@@ -601,7 +641,7 @@ function ie(e) {
|
|
|
601
641
|
};
|
|
602
642
|
});
|
|
603
643
|
}
|
|
604
|
-
function
|
|
644
|
+
function pe(e) {
|
|
605
645
|
return e.names ?? [];
|
|
606
646
|
}
|
|
607
647
|
function $(e) {
|
|
@@ -613,4 +653,4 @@ function $(e) {
|
|
|
613
653
|
return n;
|
|
614
654
|
}
|
|
615
655
|
//#endregion
|
|
616
|
-
export {
|
|
656
|
+
export { p as applyDefaultLayout, ie as applyNamedRanges, O as applyPlaceholders, k as applyPlaceholdersToSheet, I as applyTemplateLayout, B as buildEmptyWorkbook, W as cliMain, W as main, b as extractFromParsed, x as extractMdxFile, H as groupBundlesByBook, L as loadTemplateWorkbook, A as resolvePlaceholders, y as sanitiseSheetName, m as sortBundlesForLayout, V as writeWorkbookToBytes };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ingcreators/annot-product-docs-xlsx",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Excel adapter for `@ingcreators/annot-product-docs`. Walks MDX files with `annot:` frontmatter, fills customer-supplied Excel templates via `{var}` placeholders + named ranges, and emits one `.xlsx` per book. Phase 3 of docs/plans/living-product-docs.md.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "ingcreators",
|
|
@@ -47,12 +47,12 @@
|
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"typescript": "^6.0.3",
|
|
50
|
-
"vite": "^8.0.
|
|
51
|
-
"vite-plugin-dts": "^5.0.
|
|
50
|
+
"vite": "^8.0.16",
|
|
51
|
+
"vite-plugin-dts": "^5.0.3"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"exceljs": "^4.4.0",
|
|
55
|
-
"@ingcreators/annot-product-docs": "0.
|
|
55
|
+
"@ingcreators/annot-product-docs": "0.4.0"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
58
|
"build": "vite build",
|