@canopycanopycanopy/b-ber-lib 3.0.8-nav.0 → 3.0.8-next.101

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/index.js ADDED
@@ -0,0 +1,1372 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __exportAll = (all, no_symbols) => {
10
+ let target = {};
11
+ for (var name in all) __defProp(target, name, {
12
+ get: all[name],
13
+ enumerable: true
14
+ });
15
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
16
+ return target;
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
20
+ key = keys[i];
21
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
22
+ get: ((k) => from[k]).bind(null, key),
23
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
24
+ });
25
+ }
26
+ return to;
27
+ };
28
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
29
+ value: mod,
30
+ enumerable: true
31
+ }) : target, mod));
32
+ //#endregion
33
+ let _canopycanopycanopy_b_ber_logger = require("@canopycanopycanopy/b-ber-logger");
34
+ _canopycanopycanopy_b_ber_logger = __toESM(_canopycanopycanopy_b_ber_logger);
35
+ let child_process = require("child_process");
36
+ let command_exists = require("command-exists");
37
+ command_exists = __toESM(command_exists);
38
+ let path = require("path");
39
+ path = __toESM(path);
40
+ let htmlparser2 = require("htmlparser2");
41
+ let crypto = require("crypto");
42
+ crypto = __toESM(crypto);
43
+ let fs_extra = require("fs-extra");
44
+ fs_extra = __toESM(fs_extra);
45
+ let lodash_find_js = require("lodash/find.js");
46
+ lodash_find_js = __toESM(lodash_find_js);
47
+ let lodash_findIndex_js = require("lodash/findIndex.js");
48
+ lodash_findIndex_js = __toESM(lodash_findIndex_js);
49
+ let lodash_get_js = require("lodash/get.js");
50
+ lodash_get_js = __toESM(lodash_get_js);
51
+ let lodash_has_js = require("lodash/has.js");
52
+ lodash_has_js = __toESM(lodash_has_js);
53
+ let lodash_merge_js = require("lodash/merge.js");
54
+ lodash_merge_js = __toESM(lodash_merge_js);
55
+ let lodash_remove_js = require("lodash/remove.js");
56
+ lodash_remove_js = __toESM(lodash_remove_js);
57
+ let lodash_set_js = require("lodash/set.js");
58
+ lodash_set_js = __toESM(lodash_set_js);
59
+ let mime_types = require("mime-types");
60
+ mime_types = __toESM(mime_types);
61
+ let lodash_cloneDeep_js = require("lodash/cloneDeep.js");
62
+ lodash_cloneDeep_js = __toESM(lodash_cloneDeep_js);
63
+ let lodash_defaultsDeep_js = require("lodash/defaultsDeep.js");
64
+ lodash_defaultsDeep_js = __toESM(lodash_defaultsDeep_js);
65
+ let glob = require("glob");
66
+ glob = __toESM(glob);
67
+ let lodash_difference_js = require("lodash/difference.js");
68
+ lodash_difference_js = __toESM(lodash_difference_js);
69
+ let lodash_startCase_js = require("lodash/startCase.js");
70
+ lodash_startCase_js = __toESM(lodash_startCase_js);
71
+ let js_yaml = require("js-yaml");
72
+ js_yaml = __toESM(js_yaml);
73
+ let yawn_yaml_cjs_index_js = require("yawn-yaml/cjs/index.js");
74
+ yawn_yaml_cjs_index_js = __toESM(yawn_yaml_cjs_index_js);
75
+ let _canopycanopycanopy_b_ber_shapes_dublin_core = require("@canopycanopycanopy/b-ber-shapes-dublin-core");
76
+ let layouts = require("layouts");
77
+ layouts = __toESM(layouts);
78
+ let vinyl = require("vinyl");
79
+ vinyl = __toESM(vinyl);
80
+ let lodash_uniq_js = require("lodash/uniq.js");
81
+ lodash_uniq_js = __toESM(lodash_uniq_js);
82
+ //#region src/EbookConvert.ts
83
+ const command = "ebook-convert";
84
+ const defaults = {
85
+ inputPath: "",
86
+ outputPath: "",
87
+ fileType: "",
88
+ fileName: (/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-"),
89
+ flags: []
90
+ };
91
+ function checkForCalibre() {
92
+ return new Promise((resolve, reject) => {
93
+ (0, command_exists.default)(command, (err, ok) => {
94
+ if (err || !ok) return reject(/* @__PURE__ */ new Error("Error: calibre's ebook-convert must be installed. Download calibre here: https://calibre-ebook.com/"));
95
+ resolve();
96
+ });
97
+ });
98
+ }
99
+ function convertDocument({ inputPath, bookPath, flags }) {
100
+ return new Promise((resolve, reject) => {
101
+ (0, child_process.exec)(`${command} ${inputPath} ${bookPath} ${(flags || []).join(" ")}`, { cwd: process.cwd() }, (err, stdout, stderr) => {
102
+ if (err) return reject(err);
103
+ if (stderr !== "") process.stdout.write(stderr);
104
+ if (stdout !== "") process.stdout.write(stdout);
105
+ resolve();
106
+ });
107
+ });
108
+ }
109
+ function convert(options) {
110
+ [
111
+ "inputPath",
112
+ "outputPath",
113
+ "fileType"
114
+ ].forEach((prop) => {
115
+ if (!Object.hasOwn(options, prop)) throw new Error(`Missing required option [${prop}]`);
116
+ });
117
+ const settings = {
118
+ ...defaults,
119
+ ...options,
120
+ bookPath: ""
121
+ };
122
+ const bookName = `${settings.fileName}.${settings.fileType.replace(/^\./, "")}`;
123
+ settings.bookPath = `"${path.default.resolve(settings.outputPath, bookName)}"`;
124
+ return checkForCalibre().then(() => convertDocument(settings)).catch(_canopycanopycanopy_b_ber_logger.default.error);
125
+ }
126
+ var EbookConvert_default = { convert };
127
+ //#endregion
128
+ //#region src/GuideItem.ts
129
+ var GuideItem = class {
130
+ fileName;
131
+ title;
132
+ type;
133
+ constructor({ fileName, title, type }) {
134
+ this.fileName = fileName;
135
+ this.title = title;
136
+ this.type = type;
137
+ }
138
+ };
139
+ //#endregion
140
+ //#region src/Html.ts
141
+ var Html = class {
142
+ static comment(str) {
143
+ return `\n<!-- ${str} -->\n`;
144
+ }
145
+ static escape(str) {
146
+ const str_ = typeof str !== "string" ? String(str) : str;
147
+ const map = {
148
+ "&": "&amp;",
149
+ "<": "&lt;",
150
+ ">": "&gt;",
151
+ "\"": "&quot;",
152
+ "'": "&#39;"
153
+ };
154
+ return str_.replace(/[&<>"']/g, (m) => map[m]);
155
+ }
156
+ };
157
+ //#endregion
158
+ //#region src/Config.ts
159
+ var Config = class {
160
+ defaultOptions = {
161
+ env: process.env.NODE_ENV || "development",
162
+ src: "_project",
163
+ dist: "project",
164
+ cache: true,
165
+ ibooks_specified_fonts: false,
166
+ theme: "b-ber-theme-serif",
167
+ themes_directory: "./themes",
168
+ base_url: "http://localhost:4000/project-web",
169
+ base_path: "/",
170
+ remote_url: "http://localhost:4000/",
171
+ reader_url: "http://localhost:4000/project-reader",
172
+ downloads: [],
173
+ ui_options: { navigation: {
174
+ header_icons: {
175
+ info: true,
176
+ home: true,
177
+ downloads: true,
178
+ toc: true
179
+ },
180
+ footer_icons: {
181
+ chapter: true,
182
+ page: true
183
+ }
184
+ } },
185
+ private: false,
186
+ ignore: [],
187
+ autoprefixer_options: {
188
+ overrideBrowserslist: [
189
+ "defaults",
190
+ "> 1%",
191
+ "not dead",
192
+ "not IE 11"
193
+ ],
194
+ flexbox: "no-2009"
195
+ },
196
+ layout: "columns",
197
+ group_footnotes: true
198
+ };
199
+ constructor(options = {}) {
200
+ const defaultOptionsClone = (0, lodash_cloneDeep_js.default)(this.defaultOptions);
201
+ return (0, lodash_defaultsDeep_js.default)((0, lodash_cloneDeep_js.default)(options), defaultOptionsClone);
202
+ }
203
+ };
204
+ //#endregion
205
+ //#region src/SpineItem.ts
206
+ var SpineItem = class SpineItem {
207
+ fileName;
208
+ pageOrder;
209
+ in_toc;
210
+ linear;
211
+ generated;
212
+ nodes;
213
+ ref;
214
+ title;
215
+ relativePath;
216
+ absolutePath;
217
+ extension;
218
+ name;
219
+ remotePath;
220
+ type;
221
+ static isNavigationDocument(fileName) {
222
+ return fileName === "toc" || fileName === "nav";
223
+ }
224
+ constructor({ fileName, in_toc, linear, generated, pageOrder, buildType, nodes, ref, title }) {
225
+ this.fileName = fileName;
226
+ this.pageOrder = typeof pageOrder === "number" ? pageOrder : -1;
227
+ this.in_toc = typeof in_toc === "boolean" ? in_toc : true;
228
+ this.linear = typeof linear === "boolean" ? linear : true;
229
+ this.generated = Boolean(generated);
230
+ this.nodes = nodes || [];
231
+ this.ref = ref || null;
232
+ this.title = title || (0, lodash_startCase_js.default)(fileName.toLowerCase());
233
+ this.relativePath = SpineItem.isNavigationDocument(this.fileName) ? this.fileName : path.default.join("text", this.fileName);
234
+ this.absolutePath = path.default.resolve(`project-${buildType}`, "OPS", this.relativePath);
235
+ this.extension = path.default.extname(this.fileName);
236
+ this.name = path.default.basename(this.fileName, this.extension);
237
+ this.remotePath = "";
238
+ this.type = "";
239
+ }
240
+ };
241
+ //#endregion
242
+ //#region src/YamlAdaptor.ts
243
+ var YamlAdaptor = class {
244
+ static toYaml(input) {
245
+ if (typeof input === "string") return js_yaml.default.safeDump(input);
246
+ if (typeof input === "object" && input !== null && !Array.isArray(input) || Array.isArray(input)) return js_yaml.default.safeDump(JSON.stringify(input));
247
+ throw new TypeError(`Invalid type: [${typeof input}]`);
248
+ }
249
+ static load(file) {
250
+ let data;
251
+ try {
252
+ data = fs_extra.default.readFileSync(file, "utf-8");
253
+ } catch (err) {
254
+ _canopycanopycanopy_b_ber_logger.default.error(err);
255
+ }
256
+ return data ? js_yaml.default.safeLoad(data) : [];
257
+ }
258
+ static dump(str) {
259
+ return js_yaml.default.safeDump(str, { indent: 2 });
260
+ }
261
+ static parse(str) {
262
+ return js_yaml.default.safeLoad(str);
263
+ }
264
+ };
265
+ //#endregion
266
+ //#region src/Spine.ts
267
+ var Spine = class {
268
+ src;
269
+ buildType;
270
+ frontMatter;
271
+ navigationConfigFile;
272
+ entries;
273
+ nested;
274
+ flattened;
275
+ constructor({ src, buildType, navigationConfigFile }) {
276
+ this.src = src;
277
+ this.buildType = buildType;
278
+ this.frontMatter = /* @__PURE__ */ new Map();
279
+ this.navigationConfigFile = navigationConfigFile;
280
+ this.entries = this.create();
281
+ this.nested = this.build(this.entries);
282
+ this.flattened = this.flattenNodes(this.nested);
283
+ }
284
+ build(entries = []) {
285
+ const { buildType } = this;
286
+ return entries.reduce((acc, curr, index) => {
287
+ let node;
288
+ if (typeof curr === "object" && curr !== null && !Array.isArray(curr)) {
289
+ const { section } = curr;
290
+ if (section) {
291
+ let _index = 0;
292
+ while (acc[index - _index] === void 0 && _index !== acc.length) _index += 1;
293
+ acc[index - _index].nodes = this.build(section);
294
+ return acc;
295
+ }
296
+ const [[fileName, options]] = Object.entries(curr);
297
+ this.frontMatter.set(fileName, {});
298
+ node = new SpineItem({
299
+ fileName,
300
+ buildType,
301
+ ...options
302
+ });
303
+ } else {
304
+ const fileName = curr;
305
+ this.frontMatter.set(fileName, {});
306
+ node = new SpineItem({
307
+ fileName,
308
+ buildType
309
+ });
310
+ }
311
+ return acc.concat(node);
312
+ }, []);
313
+ }
314
+ flattenNodes(arr) {
315
+ return arr.reduce((acc, curr) => {
316
+ const { nodes, ...rest } = curr;
317
+ const acc_ = acc.concat(rest);
318
+ return nodes && nodes.length ? acc_.concat(this.flattenNodes(nodes)) : acc_;
319
+ }, []);
320
+ }
321
+ flattenYAML(data = []) {
322
+ return data.reduce((acc, curr) => {
323
+ if (typeof curr === "object" && curr !== null && !Array.isArray(curr)) {
324
+ if (Object.keys(curr)[0] === "section") return acc.concat(this.flattenYAML(curr.section));
325
+ return acc.concat(Object.keys(curr)[0]);
326
+ }
327
+ return acc.concat(curr);
328
+ }, []);
329
+ }
330
+ create() {
331
+ const pattern = path.default.resolve(this.src, "_markdown", "*.md");
332
+ const declaredFiles = YamlAdaptor.load(this.navigationConfigFile);
333
+ const flattenedFiles = this.flattenYAML(declaredFiles);
334
+ const missingEntries = (0, lodash_difference_js.default)(glob.default.sync(pattern).map((file) => path.default.basename(file, ".md")), flattenedFiles);
335
+ return declaredFiles.concat(missingEntries);
336
+ }
337
+ };
338
+ //#endregion
339
+ //#region src/Yaml.ts
340
+ const interfaces = {
341
+ metadata: {
342
+ term: {
343
+ type: "string",
344
+ required: true
345
+ },
346
+ value: {
347
+ type: "string",
348
+ required: true
349
+ },
350
+ term_property: {
351
+ type: "string",
352
+ required: false
353
+ },
354
+ term_property_value: {
355
+ type: "string",
356
+ required: false
357
+ }
358
+ },
359
+ config: {
360
+ env: {
361
+ type: "string",
362
+ required: false
363
+ },
364
+ src: {
365
+ type: "string",
366
+ required: true
367
+ },
368
+ dist: {
369
+ type: "string",
370
+ required: true
371
+ },
372
+ ibooks_specified_fonts: {
373
+ type: "boolean",
374
+ required: false
375
+ },
376
+ theme: {
377
+ type: "string",
378
+ required: false
379
+ },
380
+ themes_directory: {
381
+ type: "string",
382
+ required: false
383
+ },
384
+ base_url: {
385
+ type: "string",
386
+ required: false
387
+ },
388
+ base_path: {
389
+ type: "string",
390
+ required: false
391
+ },
392
+ remote_url: {
393
+ type: "string",
394
+ required: false
395
+ },
396
+ reader_url: {
397
+ type: "string",
398
+ required: false
399
+ },
400
+ downloads: {
401
+ type: "array",
402
+ required: false
403
+ },
404
+ ui_options: {
405
+ type: "object",
406
+ required: false
407
+ },
408
+ private: {
409
+ type: "boolean",
410
+ required: false
411
+ },
412
+ ignore: {
413
+ type: "array",
414
+ required: false
415
+ },
416
+ autoprefixer_options: {
417
+ type: "object",
418
+ required: false
419
+ },
420
+ layout: {
421
+ type: "string",
422
+ required: false
423
+ },
424
+ group_footnotes: {
425
+ type: "boolean",
426
+ required: false
427
+ }
428
+ },
429
+ media: {}
430
+ };
431
+ const typeCheck = (schema, data = {}) => {
432
+ const errors = [];
433
+ if (!interfaces[schema]) errors.push(/* @__PURE__ */ new Error(`Invalid schema: ${schema}`));
434
+ if (typeof data !== "object" || data === null || Array.isArray(data)) errors.push(/* @__PURE__ */ new Error(`Invalid entry: ${typeof data}`));
435
+ Object.entries(data).forEach(([key, val]) => {
436
+ if (!interfaces[schema]?.[key]) errors.push(/* @__PURE__ */ new Error(`Schema "${schema}" does not support property "${key}"`));
437
+ if (interfaces[schema]?.[key] && interfaces[schema][key].required === true && val === void 0) errors.push(/* @__PURE__ */ new Error(`Schema "${schema}" requires value for"${key}"`));
438
+ });
439
+ if (errors.length) _canopycanopycanopy_b_ber_logger.default.error(errors);
440
+ };
441
+ var Yaml = class {
442
+ data = {
443
+ yaml: "",
444
+ json: () => ({})
445
+ };
446
+ schema = "";
447
+ strict = true;
448
+ constructor(schema, strict) {
449
+ this.strict = strict === void 0 ? this.strict : strict;
450
+ if (this.strict) typeCheck(schema);
451
+ this.schema = schema;
452
+ }
453
+ load = (file) => {
454
+ const data = fs_extra.default.readFileSync(file, "utf8");
455
+ this.data = new yawn_yaml_cjs_index_js.default(data);
456
+ };
457
+ add = (entry) => {
458
+ if (this.strict) typeCheck(this.schema, entry);
459
+ this.data.json = [...this.data.json, entry];
460
+ };
461
+ remove = (key, value) => {
462
+ this.data.json = this.data.json.filter((a) => a[key] === value);
463
+ };
464
+ update = (key, current, object) => {
465
+ const entry = (0, lodash_find_js.default)(this.data.json, { [key]: current });
466
+ this.remove(key, current);
467
+ this.data.json = [...this.data.json, {
468
+ ...entry,
469
+ ...object
470
+ }];
471
+ };
472
+ yaml = () => this.data.yaml;
473
+ json = () => this.data.json;
474
+ };
475
+ //#endregion
476
+ //#region src/State.ts
477
+ const themes = {
478
+ "b-ber-theme-serif": require("@canopycanopycanopy/b-ber-theme-serif"),
479
+ "b-ber-theme-sans": require("@canopycanopycanopy/b-ber-theme-sans")
480
+ };
481
+ const randomHash = () => crypto.default.randomBytes(20).toString("hex");
482
+ const skipInitialization = () => {
483
+ const { argv } = process;
484
+ return argv.includes("--help") || argv.includes("-h") || argv.includes("--version") || argv.includes("-v") || argv.length < 3 || argv.includes("new");
485
+ };
486
+ const SRC_DIR_IMAGES = "_images";
487
+ const SRC_DIR_MARKDOWN = "_markdown";
488
+ const SRC_DIR_STYLESHEETS = "_stylesheets";
489
+ const SRC_DIR_JAVASCRIPTS = "_javascripts";
490
+ const SRC_DIR_FONTS = "_fonts";
491
+ const SRC_DIR_MEDIA = "_media";
492
+ const DIST_DIR_OPS = "OPS";
493
+ const DIST_DIR_TEXT = "text";
494
+ const DIST_DIR_IMAGES = "images";
495
+ const DIST_DIR_STYLESHEETS = "stylesheets";
496
+ const DIST_DIR_JAVASCRIPTS = "javascripts";
497
+ const DIST_DIR_FONTS = "fonts";
498
+ const DIST_DIR_MEDIA = "media";
499
+ var State_default = new class State {
500
+ static get defaults() {
501
+ return {
502
+ build: "epub",
503
+ sequence: [],
504
+ hash: randomHash()
505
+ };
506
+ }
507
+ metadata = { json: () => [{}] };
508
+ theme = {};
509
+ video = [];
510
+ audio = [];
511
+ media = {};
512
+ build = "epub";
513
+ sequence = [];
514
+ hash = randomHash();
515
+ builds = {
516
+ sample: {},
517
+ epub: {},
518
+ mobi: {},
519
+ pdf: {},
520
+ web: {},
521
+ reader: {}
522
+ };
523
+ config;
524
+ version;
525
+ get spine() {
526
+ return this.builds[this.build].spine;
527
+ }
528
+ set spine(val) {
529
+ this.builds[this.build].spine = val;
530
+ }
531
+ get guide() {
532
+ return this.builds[this.build].guide;
533
+ }
534
+ set guide(val) {
535
+ this.builds[this.build].guide = val;
536
+ }
537
+ get figures() {
538
+ return this.builds[this.build].figures;
539
+ }
540
+ set figures(val) {
541
+ this.builds[this.build].figures = val;
542
+ }
543
+ get footnotes() {
544
+ return this.builds[this.build].footnotes;
545
+ }
546
+ set footnotes(val) {
547
+ this.builds[this.build].footnotes = val;
548
+ }
549
+ get cursor() {
550
+ return this.builds[this.build].cursor;
551
+ }
552
+ set cursor(val) {
553
+ this.builds[this.build].cursor = val;
554
+ }
555
+ get toc() {
556
+ return this.builds[this.build].toc;
557
+ }
558
+ set toc(val) {
559
+ this.builds[this.build].toc = val;
560
+ }
561
+ get remoteAssets() {
562
+ return this.builds[this.build].remoteAssets;
563
+ }
564
+ set remoteAssets(val) {
565
+ this.builds[this.build].remoteAssets = val;
566
+ }
567
+ get loi() {
568
+ return this.builds[this.build].loi;
569
+ }
570
+ set loi(val) {
571
+ this.builds[this.build].loi = val;
572
+ }
573
+ get srcDir() {
574
+ return this.config.src;
575
+ }
576
+ set srcDir(val) {
577
+ this.config.src = val;
578
+ }
579
+ get distDir() {
580
+ if (this.build && this.builds && this.builds[this.build]) return this.builds[this.build].dist;
581
+ return this.config.dist;
582
+ }
583
+ set distDir(val) {
584
+ this.config.dist = val;
585
+ }
586
+ get env() {
587
+ return process.env.NODE_ENV || "development";
588
+ }
589
+ set env(val) {
590
+ this.config.env = val;
591
+ }
592
+ src = {
593
+ root: (...args) => path.default.join(this.srcDir, ...args),
594
+ images: (...args) => path.default.join(this.srcDir, SRC_DIR_IMAGES, ...args),
595
+ markdown: (...args) => path.default.join(this.srcDir, SRC_DIR_MARKDOWN, ...args),
596
+ stylesheets: (...args) => path.default.join(this.srcDir, SRC_DIR_STYLESHEETS, ...args),
597
+ javascripts: (...args) => path.default.join(this.srcDir, SRC_DIR_JAVASCRIPTS, ...args),
598
+ fonts: (...args) => path.default.join(this.srcDir, SRC_DIR_FONTS, ...args),
599
+ media: (...args) => path.default.join(this.srcDir, SRC_DIR_MEDIA, ...args)
600
+ };
601
+ dist = {
602
+ root: (...args) => path.default.join(this.distDir, ...args),
603
+ ops: (...args) => path.default.join(this.distDir, DIST_DIR_OPS, ...args),
604
+ text: (...args) => path.default.join(this.distDir, DIST_DIR_OPS, DIST_DIR_TEXT, ...args),
605
+ images: (...args) => path.default.join(this.distDir, DIST_DIR_OPS, DIST_DIR_IMAGES, ...args),
606
+ stylesheets: (...args) => path.default.join(this.distDir, DIST_DIR_OPS, DIST_DIR_STYLESHEETS, ...args),
607
+ javascripts: (...args) => path.default.join(this.distDir, DIST_DIR_OPS, DIST_DIR_JAVASCRIPTS, ...args),
608
+ fonts: (...args) => path.default.join(this.distDir, DIST_DIR_OPS, DIST_DIR_FONTS, ...args),
609
+ media: (...args) => path.default.join(this.distDir, DIST_DIR_OPS, DIST_DIR_MEDIA, ...args)
610
+ };
611
+ constructor() {
612
+ let version;
613
+ try {
614
+ ({version} = fs_extra.default.readJSONSync(require.resolve("./package.json")));
615
+ } catch (err) {
616
+ ({version} = fs_extra.default.readJSONSync(require.resolve("../package.json")));
617
+ }
618
+ (0, lodash_set_js.default)(this, "version", version);
619
+ (0, lodash_set_js.default)(this, "config", new Config());
620
+ this.reset();
621
+ this.loadMetadata();
622
+ this.loadAudioVideo();
623
+ this.loadMedia();
624
+ this.loadBuilds();
625
+ this.loadTheme();
626
+ }
627
+ reset = () => {
628
+ Object.entries(State.defaults).forEach(([key, val]) => (0, lodash_set_js.default)(this, key, val));
629
+ this.loadConfig();
630
+ };
631
+ add = (prop, value) => {
632
+ const prevValue = (0, lodash_get_js.default)(this, prop);
633
+ if (Array.isArray(prevValue)) (0, lodash_set_js.default)(this, prop, [...prevValue, value]);
634
+ else if (typeof prevValue === "object" && prevValue !== null && !Array.isArray(prevValue)) (0, lodash_set_js.default)(this, prop, {
635
+ ...prevValue,
636
+ value
637
+ });
638
+ else if (typeof prevValue === "string") (0, lodash_set_js.default)(this, prop, `${prevValue}${value}`);
639
+ else _canopycanopycanopy_b_ber_logger.default.error(`Cannot add [${value}] to [state.${prop}]`);
640
+ };
641
+ remove = (prop, value) => {
642
+ const prevValue = (0, lodash_get_js.default)(this, prop);
643
+ if (Array.isArray(prevValue)) {
644
+ const arr = [...prevValue];
645
+ (0, lodash_remove_js.default)(arr, value);
646
+ (0, lodash_set_js.default)(this, prop, arr);
647
+ } else if (typeof prevValue === "object" && prevValue !== null && !Array.isArray(prevValue)) {
648
+ const key = value;
649
+ const { [key]: _, ...rest } = prevValue;
650
+ (0, lodash_set_js.default)(this, prop, rest);
651
+ } else _canopycanopycanopy_b_ber_logger.default.error(`Cannot remove [${value}] from [state.${prop}]`);
652
+ };
653
+ merge = (prop, value) => {
654
+ const oldValue = (0, lodash_get_js.default)(this, prop);
655
+ (0, lodash_set_js.default)(this, prop, (0, lodash_merge_js.default)(oldValue, value));
656
+ };
657
+ update = (prop, val) => {
658
+ (0, lodash_set_js.default)(this, prop, val);
659
+ };
660
+ has = (prop) => {
661
+ return (0, lodash_has_js.default)(this, prop);
662
+ };
663
+ contains = (coll, value) => this.indexOf(coll, value) > -1;
664
+ find = (coll, pred) => {
665
+ return (0, lodash_find_js.default)((0, lodash_get_js.default)(this, coll), pred);
666
+ };
667
+ indexOf = (coll, pred) => {
668
+ return (0, lodash_findIndex_js.default)((0, lodash_get_js.default)(this, coll), pred);
669
+ };
670
+ loadConfig = () => {
671
+ if (!fs_extra.default.existsSync(path.default.resolve("config.yml"))) return;
672
+ const config = new Yaml("config");
673
+ config.load(path.default.resolve("config.yml"));
674
+ (0, lodash_set_js.default)(this, "config", new Config(config.json()));
675
+ };
676
+ loadMetadata = () => {
677
+ const fpath = path.default.resolve(this.config.src, "metadata.yml");
678
+ if (!fs_extra.default.existsSync(fpath)) return;
679
+ (0, lodash_set_js.default)(this, "metadata", new Yaml("metadata"));
680
+ this.metadata.load(fpath);
681
+ };
682
+ loadMedia = () => {
683
+ const fpath = path.default.resolve(this.config.src, "media.yml");
684
+ if (!fs_extra.default.existsSync(fpath)) return;
685
+ const mediaYaml = new Yaml("media");
686
+ mediaYaml.load(fpath);
687
+ const media = mediaYaml.json();
688
+ (0, lodash_set_js.default)(this, "media", media);
689
+ };
690
+ loadTheme = () => {
691
+ if (skipInitialization()) return;
692
+ const userThemesPath = path.default.resolve(this.config.themes_directory);
693
+ fs_extra.default.ensureDirSync(userThemesPath);
694
+ module.paths.push(userThemesPath);
695
+ const cwdArr = process.cwd().split("/");
696
+ const modulePaths = new Set([...module.paths]);
697
+ let cwdPath;
698
+ do {
699
+ cwdPath = `${cwdArr.join("/")}/node_modules`;
700
+ if (modulePaths.has(cwdPath)) continue;
701
+ module.paths.push(cwdPath);
702
+ } while (cwdArr.pop());
703
+ const themeName = this.config.theme;
704
+ if (themes[themeName]) {
705
+ (0, lodash_set_js.default)(this, "theme", themes[themeName]);
706
+ _canopycanopycanopy_b_ber_logger.default.info(`Loaded theme [${themeName}]`);
707
+ return;
708
+ }
709
+ try {
710
+ (0, lodash_set_js.default)(this, "theme", require(themeName));
711
+ _canopycanopycanopy_b_ber_logger.default.info(`Loaded theme [${themeName}]`);
712
+ } catch (err) {
713
+ _canopycanopycanopy_b_ber_logger.default.warn(`There was an error during require [${themeName}]`);
714
+ _canopycanopycanopy_b_ber_logger.default.warn("Using default theme [b-ber-theme-serif]");
715
+ _canopycanopycanopy_b_ber_logger.default.warn(err.message);
716
+ (0, lodash_set_js.default)(this, "theme", themes["b-ber-theme-serif"]);
717
+ }
718
+ };
719
+ loadAudioVideo = () => {
720
+ if (skipInitialization()) return;
721
+ const mediaPath = path.default.resolve(this.config.src, "_media");
722
+ fs_extra.default.ensureDirSync(mediaPath);
723
+ const media = fs_extra.default.readdirSync(mediaPath);
724
+ const video = media.filter((a) => /^video/.test(mime_types.default.lookup(a)));
725
+ const audio = media.filter((a) => /^audio/.test(mime_types.default.lookup(a)));
726
+ (0, lodash_set_js.default)(this, "video", video);
727
+ (0, lodash_set_js.default)(this, "audio", audio);
728
+ };
729
+ loadBuildSettings = (type) => {
730
+ if (skipInitialization()) return void 0;
731
+ const src = this.config.src;
732
+ const dist = this.config.dist;
733
+ const projectDir = path.default.resolve(src);
734
+ if (!fs_extra.default.existsSync(projectDir)) _canopycanopycanopy_b_ber_logger.default.error(`Project directory [${projectDir}] does not exist`);
735
+ const navigationConfigFileDefaultPath = path.default.resolve(src, "toc.yml");
736
+ const navigationConfigFilePath = path.default.resolve(src, `${type}.yml`);
737
+ const spine = new Spine({
738
+ src,
739
+ buildType: type,
740
+ navigationConfigFile: fs_extra.default.existsSync(navigationConfigFilePath) ? navigationConfigFilePath : navigationConfigFileDefaultPath
741
+ });
742
+ const config = this.config[type] ? { ...this.config[type] } : {};
743
+ return {
744
+ src,
745
+ dist: `${dist}-${type}`,
746
+ config,
747
+ guide: [],
748
+ spine,
749
+ toc: spine.nested,
750
+ cursor: [],
751
+ figures: [],
752
+ footnotes: [],
753
+ remoteAssets: [],
754
+ loi: []
755
+ };
756
+ };
757
+ loadBuilds = () => {
758
+ [
759
+ "sample",
760
+ "epub",
761
+ "mobi",
762
+ "pdf",
763
+ "web",
764
+ "reader",
765
+ "xml"
766
+ ].forEach((build) => (0, lodash_set_js.default)(this.builds, build, this.loadBuildSettings(build)));
767
+ };
768
+ }();
769
+ //#endregion
770
+ //#region src/HtmlToXml.ts
771
+ var HtmlToXmlParser = class {
772
+ customElementNames;
773
+ inlineElementNames;
774
+ whitelistedAttributes;
775
+ blacklistedTagNames;
776
+ containingTagNames;
777
+ elementAttributeNames;
778
+ elementAttributeTransformers;
779
+ content;
780
+ onEndCallback;
781
+ output;
782
+ tagList;
783
+ constructor({ content, onEndCallback }) {
784
+ this.customElementNames = {
785
+ pullquote: true,
786
+ blockquote: true,
787
+ epigraph: true,
788
+ dialogue: true,
789
+ gallery: true,
790
+ spread: true,
791
+ colophon: true,
792
+ appendix: true,
793
+ subtitle: true,
794
+ frontmatter: true,
795
+ backmatter: true,
796
+ "meta-content": true,
797
+ bibliography: true,
798
+ masthead: true,
799
+ figcaption: true,
800
+ subchapter: true
801
+ };
802
+ this.inlineElementNames = {
803
+ pagebreak: true,
804
+ a: false,
805
+ abbr: true,
806
+ acronym: true,
807
+ audio: false,
808
+ b: true,
809
+ bdi: true,
810
+ bdo: true,
811
+ big: true,
812
+ br: false,
813
+ button: false,
814
+ canvas: true,
815
+ cite: true,
816
+ code: true,
817
+ data: true,
818
+ datalist: true,
819
+ del: true,
820
+ dfn: true,
821
+ em: true,
822
+ embed: false,
823
+ i: true,
824
+ iframe: false,
825
+ img: false,
826
+ input: false,
827
+ ins: true,
828
+ kbd: true,
829
+ label: false,
830
+ map: true,
831
+ mark: true,
832
+ meter: true,
833
+ noscript: false,
834
+ object: false,
835
+ output: true,
836
+ picture: false,
837
+ progress: false,
838
+ q: true,
839
+ ruby: true,
840
+ s: true,
841
+ samp: true,
842
+ script: false,
843
+ select: false,
844
+ slot: true,
845
+ small: true,
846
+ span: true,
847
+ strong: true,
848
+ sub: true,
849
+ sup: true,
850
+ svg: true,
851
+ template: true,
852
+ textarea: false,
853
+ time: true,
854
+ u: true,
855
+ tt: true,
856
+ var: true,
857
+ video: false,
858
+ wbr: true
859
+ };
860
+ this.whitelistedAttributes = {
861
+ src: true,
862
+ href: true,
863
+ "xlink:href": true,
864
+ xmlns: true,
865
+ "xmlns:xlink": true,
866
+ class: true
867
+ };
868
+ this.blacklistedTagNames = {
869
+ html: true,
870
+ head: true,
871
+ title: true,
872
+ meta: true,
873
+ link: true,
874
+ script: true,
875
+ body: true,
876
+ video: true,
877
+ audio: true
878
+ };
879
+ this.containingTagNames = {
880
+ div: true,
881
+ span: true,
882
+ section: true
883
+ };
884
+ this.elementAttributeNames = {
885
+ img: { src: "href" },
886
+ source: { src: "href" }
887
+ };
888
+ this.elementAttributeTransformers = {
889
+ img: { src: (value) => `file://${path.default.resolve(State_default.dist.images(path.default.basename(value)))}` },
890
+ source: { src: (value) => `file://${path.default.resolve(State_default.dist.media(path.default.basename(value)))}` }
891
+ };
892
+ this.content = content;
893
+ this.onEndCallback = onEndCallback;
894
+ this.output = "";
895
+ this.tagList = [];
896
+ this.onopentag = this.onopentag.bind(this);
897
+ this.ontext = this.ontext.bind(this);
898
+ this.onclosetag = this.onclosetag.bind(this);
899
+ this.onend = this.onend.bind(this);
900
+ }
901
+ writePageBreak() {
902
+ this.output += "<pagebreak></pagebreak>";
903
+ }
904
+ writeXMLDeclaration() {
905
+ this.output += "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
906
+ }
907
+ renameAttribute(name, attribute) {
908
+ if (!this.elementAttributeNames[name]) return attribute;
909
+ return this.elementAttributeNames[name][attribute] || attribute;
910
+ }
911
+ transformAttributeValue(name, attribute, value) {
912
+ if (!this.elementAttributeTransformers[name] || !this.elementAttributeTransformers[name][attribute]) return value;
913
+ return this.elementAttributeTransformers[name][attribute](value);
914
+ }
915
+ writeTagOpen(name, attributes = {}) {
916
+ let tag = [name];
917
+ tag = Object.entries(attributes).reduce((acc, [key, val]) => this.whitelistedAttributes[key] ? acc.concat(`${this.renameAttribute(name, key)}="${this.transformAttributeValue(name, key, val)}"`) : acc, tag);
918
+ if (attributes.class) {
919
+ const classNames = new Set(attributes.class.split(" "));
920
+ if (classNames.has("figure__large") && classNames.has("figure__inline") || classNames.has("gallery__item")) this.writePageBreak();
921
+ }
922
+ this.output += `<${tag.join(" ")}>`;
923
+ }
924
+ writeTagClose(name) {
925
+ this.output += `</${name}>`;
926
+ if (!this.inlineElementNames[name]) this.output += "\n";
927
+ }
928
+ addTag(name) {
929
+ this.tagList.push(name);
930
+ }
931
+ removeTag() {
932
+ return this.tagList.pop();
933
+ }
934
+ getTag() {
935
+ if (!this.tagList.length) return null;
936
+ return this.tagList[this.tagList.length - 1];
937
+ }
938
+ onopentag(name, attributes = {}) {
939
+ if (this.blacklistedTagNames[name]) return;
940
+ let tagName = name;
941
+ if (tagName === "body") {
942
+ if (attributes.class) tagName = attributes.class.replace(/\s+/g, "-");
943
+ } else if (tagName === "source") {
944
+ if (!attributes.src || !/\.mp[34]$/i.test(attributes.src)) return;
945
+ } else if (this.containingTagNames[tagName]) {
946
+ if (attributes.class) {
947
+ const classNames = attributes.class.split(" ");
948
+ for (let i = 0; i < classNames.length; i++) if (this.customElementNames[classNames[i]]) tagName = classNames[i];
949
+ }
950
+ }
951
+ this.addTag(tagName);
952
+ this.writeTagOpen(tagName, attributes);
953
+ }
954
+ ontext(text) {
955
+ if (!text.trim()) return;
956
+ const name = this.getTag();
957
+ if (!name || this.blacklistedTagNames[name]) return;
958
+ this.output += text;
959
+ }
960
+ onclosetag() {
961
+ const name = this.removeTag();
962
+ if (name) this.writeTagClose(name);
963
+ }
964
+ onend() {
965
+ this.writeTagClose("body");
966
+ this.onEndCallback(this.output);
967
+ }
968
+ parse() {
969
+ this.writeXMLDeclaration();
970
+ this.writeTagOpen("body");
971
+ const parser = new htmlparser2.Parser({
972
+ onclosetag: this.onclosetag,
973
+ onopentag: this.onopentag,
974
+ ontext: this.ontext,
975
+ onend: this.onend
976
+ }, { decodeEntities: false });
977
+ parser.write(this.content);
978
+ parser.end();
979
+ }
980
+ };
981
+ //#endregion
982
+ //#region src/ManifestItemProperties.ts
983
+ var ManifestItemProperties = class ManifestItemProperties {
984
+ static HTMLMimeTypes = ["text/html", "application/xhtml+xml"];
985
+ static isHTML(file) {
986
+ return ManifestItemProperties.HTMLMimeTypes.includes(mime_types.default.lookup(file.absolutePath));
987
+ }
988
+ static isNav(file) {
989
+ return ManifestItemProperties.isHTML(file) && /^toc\./.test(file.name);
990
+ }
991
+ static isScripted(file) {
992
+ if (!ManifestItemProperties.isHTML(file)) return false;
993
+ if (ManifestItemProperties.isNav(file)) return true;
994
+ return fs_extra.default.readFileSync(file.absolutePath, "utf8").match(/<script/) !== null;
995
+ }
996
+ static isSVG(file) {
997
+ if (!ManifestItemProperties.isHTML(file)) return false;
998
+ return fs_extra.default.readFileSync(file.absolutePath, "utf8").match(/<svg/) !== null;
999
+ }
1000
+ static isDCElement(data) {
1001
+ return Object.hasOwn(data, "term") && _canopycanopycanopy_b_ber_shapes_dublin_core.elements.indexOf(data.term) > -1;
1002
+ }
1003
+ static isDCTerm(data) {
1004
+ return Object.hasOwn(data, "term") && _canopycanopycanopy_b_ber_shapes_dublin_core.terms.indexOf(data.term) > -1;
1005
+ }
1006
+ static hasRemoteResources(file) {
1007
+ if (!ManifestItemProperties.isHTML(file)) return false;
1008
+ return fs_extra.default.readFileSync(file.absolutePath, "utf8").match(/src=(?:['"]{1})?(?:http|\/\/)/) !== null;
1009
+ }
1010
+ static testHTML(file) {
1011
+ const props = [];
1012
+ if (ManifestItemProperties.isNav(file)) props.push("nav");
1013
+ if (ManifestItemProperties.isScripted(file)) props.push("scripted");
1014
+ if (ManifestItemProperties.isSVG(file)) props.push("svg");
1015
+ if (ManifestItemProperties.hasRemoteResources(file)) props.push("remote-resources");
1016
+ return props;
1017
+ }
1018
+ static testMeta(data) {
1019
+ return {
1020
+ term: ManifestItemProperties.isDCTerm(data),
1021
+ element: ManifestItemProperties.isDCElement(data)
1022
+ };
1023
+ }
1024
+ };
1025
+ //#endregion
1026
+ //#region src/Template.ts
1027
+ var Template = class {
1028
+ static render = (contents, template) => (0, layouts.default)(new vinyl.default({
1029
+ path: ".Template",
1030
+ layout: "template",
1031
+ contents: Buffer.from(contents)
1032
+ }), { template }).contents.toString();
1033
+ };
1034
+ //#endregion
1035
+ //#region src/Url.ts
1036
+ var Url = class Url {
1037
+ static trimSlashes(url) {
1038
+ return url.replace(/(^\/+|\/+$)/, "");
1039
+ }
1040
+ static removeTrailingSlash = (str) => {
1041
+ if (typeof str !== "string") return "";
1042
+ return str.replace(/\/+$/, "");
1043
+ };
1044
+ static addTrailingSlash = (str) => {
1045
+ if (typeof str !== "string" || str === "/") return "/";
1046
+ return `${Url.removeTrailingSlash(str)}/`;
1047
+ };
1048
+ static ensureDecoded(str) {
1049
+ let str_ = str;
1050
+ while (decodeURIComponent(str_) !== str_) str_ = decodeURIComponent(str_);
1051
+ return str_;
1052
+ }
1053
+ static encodeQueryString(url) {
1054
+ const parts = url.split("?");
1055
+ const loc = parts[0];
1056
+ let qs = parts[1];
1057
+ if (!qs) return loc;
1058
+ qs = Url.ensureDecoded(qs);
1059
+ qs = encodeURIComponent(qs);
1060
+ return `${loc}?${qs}`;
1061
+ }
1062
+ };
1063
+ //#endregion
1064
+ //#region src/utils/index.ts
1065
+ var utils_exports = /* @__PURE__ */ __exportAll({
1066
+ createUnsupportedInline: () => createUnsupportedInline,
1067
+ ensure: () => ensure,
1068
+ ensurePoster: () => ensurePoster,
1069
+ ensureSource: () => ensureSource,
1070
+ ensureSupportedClassNames: () => ensureSupportedClassNames,
1071
+ fail: () => fail,
1072
+ fileId: () => fileId,
1073
+ generateWebpubManifest: () => generateWebpubManifest,
1074
+ getBookMetadata: () => getBookMetadata,
1075
+ getImageOrientation: () => getImageOrientation,
1076
+ getMediaType: () => getMediaType,
1077
+ getTitle: () => getTitle,
1078
+ opsPath: () => opsPath,
1079
+ renderCaption: () => renderCaption,
1080
+ renderPosterImage: () => renderPosterImage,
1081
+ resolveIntersectingUrl: () => resolveIntersectingUrl,
1082
+ safeWrite: () => safeWrite,
1083
+ validatePosterImage: () => validatePosterImage
1084
+ });
1085
+ const opsPath = (fpath, base) => fpath.replace(new RegExp(`^${base}${path.default.sep}OPS${path.default.sep}?`), "");
1086
+ const fileId = (str) => `_${str.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
1087
+ const getImageOrientation = (w, h) => {
1088
+ const widthToHeight = w / h;
1089
+ let imageType = null;
1090
+ if (widthToHeight < .61) imageType = "portrait-high";
1091
+ if (widthToHeight >= .61 && widthToHeight < 1) imageType = "portrait";
1092
+ if (widthToHeight === 1) imageType = "square";
1093
+ if (widthToHeight > 1) imageType = "landscape";
1094
+ return imageType;
1095
+ };
1096
+ const getTitle = (page) => {
1097
+ if (page.name === "figures-titlepage") return "Figures";
1098
+ const meta = State_default.spine.frontMatter.get(page.name);
1099
+ return meta && meta.title ? meta.title : page.title || page.name;
1100
+ };
1101
+ const getBookMetadata = (term) => {
1102
+ const entry = (0, lodash_find_js.default)(State_default.metadata.json(), { term });
1103
+ if (entry && entry.value) return entry.value;
1104
+ _canopycanopycanopy_b_ber_logger.default.warn(`Could not find metadata value for ${term}`);
1105
+ return "";
1106
+ };
1107
+ const safeWrite = (dest, data) => fs_extra.default.existsSync(dest) ? Promise.resolve() : fs_extra.default.writeFile(dest, data);
1108
+ const fail = (_msg, _err, yargs) => {
1109
+ yargs.showHelp();
1110
+ process.exit(0);
1111
+ };
1112
+ const ensureDirs = (dirs, prefix) => {
1113
+ const cwd = process.cwd();
1114
+ const dirs_ = (0, lodash_uniq_js.default)([
1115
+ `${prefix}/_project`,
1116
+ `${prefix}/_project/_fonts`,
1117
+ `${prefix}/_project/_images`,
1118
+ `${prefix}/_project/_javascripts`,
1119
+ `${prefix}/_project/_markdown`,
1120
+ `${prefix}/_project/_media`,
1121
+ `${prefix}/_project/_stylesheets`,
1122
+ `${prefix}/themes`
1123
+ ].concat(dirs)).map((a) => fs_extra.default.ensureDir(path.default.join(cwd, a)));
1124
+ return Promise.all(dirs_);
1125
+ };
1126
+ const ensureFiles = (files, prefix) => {
1127
+ const files_ = [{
1128
+ absolutePath: path.default.resolve(prefix, "_project", "toc.yml"),
1129
+ content: ""
1130
+ }].filter(({ absolutePath }) => (0, lodash_findIndex_js.default)(files, { absolutePath }) < 0).concat(files).reduce((acc, curr) => fs_extra.default.existsSync(curr.absolutePath) ? acc : acc.concat(fs_extra.default.writeFile(curr.absolutePath, curr.content)), []);
1131
+ return Promise.all(files_);
1132
+ };
1133
+ const ensure = ({ files = [], dirs = [], prefix = "" } = {}) => ensureDirs(dirs, prefix).then(() => ensureFiles(files, prefix)).catch(_canopycanopycanopy_b_ber_logger.default.error);
1134
+ const trimLeadingSlash = (s) => s.replace(/^\//, "");
1135
+ const resolveIntersectingUrl = (u, p) => {
1136
+ let url;
1137
+ try {
1138
+ url = new URL(u);
1139
+ } catch (err) {
1140
+ _canopycanopycanopy_b_ber_logger.default.warn(`${err.message}: "${u}"`);
1141
+ return u;
1142
+ }
1143
+ const { pathname } = url;
1144
+ let urlParts = pathname.split("/").filter(Boolean);
1145
+ let pathParts = p.split("/").filter(Boolean);
1146
+ if (/\./.test(urlParts[urlParts.length - 1])) urlParts.pop();
1147
+ let intersectionIndices = [];
1148
+ for (let i = 0; i < urlParts.length; i++) for (let j = 0; j < pathParts.length; j++) if (urlParts[i] === pathParts[j]) {
1149
+ intersectionIndices = [i, j];
1150
+ break;
1151
+ }
1152
+ const [uIdx, pIdx] = intersectionIndices;
1153
+ urlParts = urlParts.slice(0, uIdx);
1154
+ pathParts = pathParts.slice(pIdx);
1155
+ const intersection = urlParts.concat(pathParts);
1156
+ url.pathname = intersection.join("/");
1157
+ return url.href;
1158
+ };
1159
+ const webpubManifestResource = (base) => (file) => {
1160
+ return {
1161
+ href: resolveIntersectingUrl(base, file),
1162
+ type: mime_types.default.lookup(file)
1163
+ };
1164
+ };
1165
+ const webpubManifestReadingOrderItem = (base) => ({ title, file }) => {
1166
+ return {
1167
+ href: resolveIntersectingUrl(base, file),
1168
+ title,
1169
+ type: "text/xhtml"
1170
+ };
1171
+ };
1172
+ const generateWebpubManifest = (files) => {
1173
+ const remoteURL = Url.trimSlashes(State_default.config.remote_url);
1174
+ const fileMap = new Map(files.map((f) => [path.default.basename(f), f]));
1175
+ const readingOrder = State_default.spine.flattened.reduce((acc, curr) => {
1176
+ const file = fileMap.get(`${curr.fileName}.xhtml`);
1177
+ return !file ? acc : acc.concat({
1178
+ file,
1179
+ title: curr.title
1180
+ });
1181
+ }, []).map(webpubManifestReadingOrderItem(remoteURL));
1182
+ const resources = files.filter((file) => path.default.basename(file).charAt(0) !== ".").map(webpubManifestResource(remoteURL));
1183
+ return {
1184
+ "@context": "https://readium.org/webpub-manifest/context.jsonld",
1185
+ metadata: {
1186
+ "@type": "http://schema.org/Book",
1187
+ title: getBookMetadata("title"),
1188
+ author: getBookMetadata("creator"),
1189
+ identifier: getBookMetadata("identifier"),
1190
+ language: getBookMetadata("language"),
1191
+ publisher: getBookMetadata("publisher"),
1192
+ modified: (/* @__PURE__ */ new Date()).toISOString()
1193
+ },
1194
+ links: [{
1195
+ rel: "self",
1196
+ href: `${remoteURL}/${trimLeadingSlash(State_default.distDir)}/manifest.json`,
1197
+ type: "application/webpub+json"
1198
+ }],
1199
+ readingOrder,
1200
+ resources
1201
+ };
1202
+ };
1203
+ const validatePosterImage = (asset, type) => {
1204
+ const assetPath = State_default.src.images(asset);
1205
+ if (!fs_extra.default.existsSync(assetPath)) _canopycanopycanopy_b_ber_logger.default.error(`bber-directives: Poster image for [${type}] does not exist`);
1206
+ return asset;
1207
+ };
1208
+ const renderPosterImage = (poster) => poster ? `<img src="${poster}" alt="Poster Image"/>` : "";
1209
+ const renderCaption = (caption, mediaType) => caption ? `<p class="caption caption__${mediaType}">${caption}</p>` : "";
1210
+ const getMediaType = (type) => {
1211
+ const index = type.indexOf("-");
1212
+ return index > -1 ? type.substring(0, index) : type;
1213
+ };
1214
+ function createUnsupportedInline({ id, commentStart, commentEnd, attrString, mediaType, poster }) {
1215
+ return `
1216
+ ${commentStart}
1217
+ <section class="${mediaType} figure__large figure__inline">
1218
+ <div id="${id}" ${attrString}>
1219
+ <div class="media__fallback media__fallback__${mediaType} media__fallback--image">
1220
+ <figure>
1221
+ ${renderPosterImage(poster)}
1222
+ </figure>
1223
+ </div>
1224
+ <p class="media__fallback media__fallback__${mediaType} media__fallback--text">Your device does not support embedded media.</p>
1225
+ </div>
1226
+ </section>
1227
+ ${commentEnd}`;
1228
+ }
1229
+ function ensureSource(obj, type, fileName, lineNumber) {
1230
+ if (!obj.source) _canopycanopycanopy_b_ber_logger.default.error(`Directive [${type}] requires a [source] attribute at [${fileName}:${lineNumber}]`);
1231
+ }
1232
+ function ensurePoster(obj, type) {
1233
+ if (!obj.poster) return;
1234
+ validatePosterImage(obj.poster, type);
1235
+ obj.poster = `../images/${encodeURIComponent(path.default.basename(obj.poster))}`;
1236
+ }
1237
+ function ensureSupportedClassNames(obj, supported) {
1238
+ obj.classes += ` embed ${supported(State_default.build) ? "" : "un"}supported`;
1239
+ }
1240
+ //#endregion
1241
+ //#region src/Theme.ts
1242
+ const defaultThemes = {
1243
+ "b-ber-theme-serif": require("@canopycanopycanopy/b-ber-theme-serif"),
1244
+ "b-ber-theme-sans": require("@canopycanopycanopy/b-ber-theme-sans")
1245
+ };
1246
+ const getVendorThemes = () => {
1247
+ const packageJSON = path.default.resolve("package.json");
1248
+ if (!fs_extra.default.existsSync(packageJSON)) return [];
1249
+ let themes = [];
1250
+ const { dependencies, devDependencies } = fs_extra.default.readJSONSync(packageJSON);
1251
+ const deps = dependencies ? Object.keys(dependencies) : [];
1252
+ const devDeps = devDependencies ? Object.keys(devDependencies) : [];
1253
+ themes = themes.concat(deps, devDeps);
1254
+ themes = themes.filter((name) => /^b-ber-theme/.test(name));
1255
+ return themes;
1256
+ };
1257
+ const getUserThemes = () => {
1258
+ const dir = path.default.resolve(State_default.config.themes_directory);
1259
+ if (!fs_extra.default.existsSync(dir)) {
1260
+ _canopycanopycanopy_b_ber_logger.default.warn(`Themes directory [${path.default.basename(dir)}] does not exist`);
1261
+ return [];
1262
+ }
1263
+ return fs_extra.default.readdirSync(dir).reduce((acc, curr) => fs_extra.default.lstatSync(path.default.resolve(dir, curr)).isDirectory() ? acc.concat(curr) : acc, []);
1264
+ };
1265
+ const getThemeList = (themes, current = "") => {
1266
+ const themes_ = (0, lodash_uniq_js.default)(themes);
1267
+ const duplicates = [];
1268
+ return {
1269
+ text: themes_.reduce((acc, curr) => {
1270
+ let curr_ = `${current === curr ? "✓" : "○"} ${curr}`;
1271
+ if (themes.indexOf(curr) !== themes.lastIndexOf(curr)) {
1272
+ duplicates.push(curr);
1273
+ curr_ += " [(duplicate)]";
1274
+ }
1275
+ curr_ += "\n";
1276
+ return acc.concat(curr_);
1277
+ }, "").slice(0, -1),
1278
+ duplicates
1279
+ };
1280
+ };
1281
+ const getThemes = () => {
1282
+ const current = State_default.config.theme ? State_default.config.theme : "";
1283
+ const userThemes = getUserThemes();
1284
+ const vendorThemes = getVendorThemes();
1285
+ return {
1286
+ current,
1287
+ themes: [
1288
+ ...Object.keys(defaultThemes),
1289
+ ...userThemes,
1290
+ ...vendorThemes
1291
+ ]
1292
+ };
1293
+ };
1294
+ const createProjectThemeDirectory = (name) => fs_extra.default.mkdirp(path.default.resolve(State_default.config.src, "_stylesheets", name)).catch(_canopycanopycanopy_b_ber_logger.default.error);
1295
+ const copyThemeAssets = (theme) => {
1296
+ const themePath = path.default.dirname(theme.entry);
1297
+ const themeSettings = path.default.join(themePath, "_settings.scss");
1298
+ const settingsPath = path.default.resolve(State_default.src.stylesheets(theme.name, "_settings.scss"));
1299
+ const overridesPath = path.default.resolve(State_default.src.stylesheets(theme.name, "_overrides.scss"));
1300
+ const fontsPath = path.default.resolve(State_default.src.fonts());
1301
+ const imagesPath = path.default.resolve(State_default.src.images());
1302
+ return fs_extra.default.copy(themeSettings, settingsPath, { overwrite: false }).then(() => safeWrite(overridesPath, "")).then(() => {
1303
+ if (!theme.fonts.length) return;
1304
+ const promises = theme.fonts.map((font) => {
1305
+ const fontPath = path.default.join(themePath, "fonts", font);
1306
+ return fs_extra.default.copy(fontPath, path.default.join(fontsPath, font), { overwrite: false });
1307
+ });
1308
+ return Promise.all(promises);
1309
+ }).then(() => {
1310
+ if (!theme.images.length) return;
1311
+ const promises = theme.images.map((image) => {
1312
+ const imagePath = path.default.join(themePath, "images", image);
1313
+ return fs_extra.default.copy(imagePath, path.default.join(imagesPath, image), { overwrite: false });
1314
+ });
1315
+ return Promise.all(promises);
1316
+ });
1317
+ };
1318
+ const updateConfig = (name) => {
1319
+ const configPath = path.default.resolve("config.yml");
1320
+ const config = YamlAdaptor.load(configPath);
1321
+ config.theme = name;
1322
+ const config_ = YamlAdaptor.dump(config);
1323
+ return fs_extra.default.writeFile(configPath, config_);
1324
+ };
1325
+ var Theme = class {
1326
+ static list = () => {
1327
+ const { current, themes } = getThemes();
1328
+ const { text, duplicates } = getThemeList(themes, current);
1329
+ _canopycanopycanopy_b_ber_logger.default.notice("The following themes are available:", "\n", text);
1330
+ if (duplicates.length) {
1331
+ _canopycanopycanopy_b_ber_logger.default.notice("Duplicate themes have been found in both the [node_modules] and [themes] directory");
1332
+ _canopycanopycanopy_b_ber_logger.default.notice("Resolve this issue by either removing the duplicate directory from [themes] or by running [npm rm <location> <package>]");
1333
+ }
1334
+ };
1335
+ static set = (name, force = false) => {
1336
+ let theme;
1337
+ const cwdArr = process.cwd().split("/");
1338
+ const modulePaths = new Set([...module.paths]);
1339
+ let cwdPath;
1340
+ do {
1341
+ cwdPath = `${cwdArr.join("/")}/node_modules`;
1342
+ if (modulePaths.has(cwdPath)) continue;
1343
+ module.paths.push(cwdPath);
1344
+ } while (cwdArr.pop());
1345
+ if (defaultThemes[name]) theme = defaultThemes[name];
1346
+ else try {
1347
+ theme = require(name);
1348
+ } catch (err) {
1349
+ _canopycanopycanopy_b_ber_logger.default.error(`Could not load theme [${name}]`);
1350
+ }
1351
+ return createProjectThemeDirectory(name).then(() => copyThemeAssets(theme)).then(() => updateConfig(name)).then(() => !force && _canopycanopycanopy_b_ber_logger.default.notice(`Updated theme [${name}]`)).catch(_canopycanopycanopy_b_ber_logger.default.error);
1352
+ };
1353
+ };
1354
+ //#endregion
1355
+ exports.EbookConvert = EbookConvert_default;
1356
+ exports.GuideItem = GuideItem;
1357
+ exports.Html = Html;
1358
+ exports.HtmlToXml = HtmlToXmlParser;
1359
+ exports.ManifestItemProperties = ManifestItemProperties;
1360
+ exports.Spine = Spine;
1361
+ exports.SpineItem = SpineItem;
1362
+ exports.State = State_default;
1363
+ exports.Template = Template;
1364
+ exports.Theme = Theme;
1365
+ exports.Url = Url;
1366
+ exports.YamlAdaptor = YamlAdaptor;
1367
+ Object.defineProperty(exports, "utils", {
1368
+ enumerable: true,
1369
+ get: function() {
1370
+ return utils_exports;
1371
+ }
1372
+ });