@vivliostyle/cli 8.17.0 → 9.0.0-next.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/browser.d.ts +12 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +108 -13
- package/dist/browser.js.map +1 -1
- package/dist/commands/build.js +10 -44
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/build.parser.d.ts +0 -5
- package/dist/commands/build.parser.d.ts.map +1 -1
- package/dist/commands/build.parser.js +15 -23
- package/dist/commands/build.parser.js.map +1 -1
- package/dist/commands/cli-flags.d.ts +42 -0
- package/dist/commands/cli-flags.d.ts.map +1 -0
- package/dist/commands/cli-flags.js +58 -0
- package/dist/commands/cli-flags.js.map +1 -0
- package/dist/commands/init.js +4 -12
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/preview.js +4 -37
- package/dist/commands/preview.js.map +1 -1
- package/dist/commands/preview.parser.d.ts.map +1 -1
- package/dist/commands/preview.parser.js +6 -4
- package/dist/commands/preview.parser.js.map +1 -1
- package/dist/config/load.d.ts +7 -0
- package/dist/config/load.d.ts.map +1 -0
- package/dist/config/load.js +72 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/merge.d.ts +4 -0
- package/dist/config/merge.d.ts.map +1 -0
- package/dist/config/merge.js +78 -0
- package/dist/config/merge.js.map +1 -0
- package/dist/{input/config.d.ts → config/resolve.d.ts} +81 -82
- package/dist/config/resolve.d.ts.map +1 -0
- package/dist/config/resolve.js +727 -0
- package/dist/config/resolve.js.map +1 -0
- package/dist/{input → config}/schema.d.ts +6023 -3542
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +562 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/vite.d.ts +53 -0
- package/dist/config/vite.d.ts.map +1 -0
- package/dist/config/vite.js +19 -0
- package/dist/config/vite.js.map +1 -0
- package/dist/const.d.ts +2 -0
- package/dist/const.d.ts.map +1 -1
- package/dist/const.js +2 -0
- package/dist/const.js.map +1 -1
- package/dist/container.d.ts +12 -3
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +130 -30
- package/dist/container.js.map +1 -1
- package/dist/core/build.d.ts +3 -0
- package/dist/core/build.d.ts.map +1 -0
- package/dist/core/build.js +168 -0
- package/dist/core/build.js.map +1 -0
- package/dist/core/init.d.ts +3 -0
- package/dist/core/init.d.ts.map +1 -0
- package/dist/{init.js → core/init.js} +14 -19
- package/dist/core/init.js.map +1 -0
- package/dist/core/preview.d.ts +3 -0
- package/dist/core/preview.d.ts.map +1 -0
- package/dist/core/preview.js +93 -0
- package/dist/core/preview.js.map +1 -0
- package/dist/index.d.ts +32 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -3
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +23 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +161 -0
- package/dist/logger.js.map +1 -0
- package/dist/output/epub.d.ts.map +1 -1
- package/dist/output/epub.js +17 -15
- package/dist/output/epub.js.map +1 -1
- package/dist/output/pdf-postprocess.d.ts +2 -3
- package/dist/output/pdf-postprocess.d.ts.map +1 -1
- package/dist/output/pdf-postprocess.js +94 -29
- package/dist/output/pdf-postprocess.js.map +1 -1
- package/dist/output/pdf.d.ts +4 -7
- package/dist/output/pdf.d.ts.map +1 -1
- package/dist/output/pdf.js +77 -141
- package/dist/output/pdf.js.map +1 -1
- package/dist/output/webbook.d.ts +10 -10
- package/dist/output/webbook.d.ts.map +1 -1
- package/dist/output/webbook.js +44 -62
- package/dist/output/webbook.js.map +1 -1
- package/dist/processor/compile.d.ts +24 -10
- package/dist/processor/compile.d.ts.map +1 -1
- package/dist/processor/compile.js +195 -130
- package/dist/processor/compile.js.map +1 -1
- package/dist/processor/html.d.ts +29 -17
- package/dist/processor/html.d.ts.map +1 -1
- package/dist/processor/html.js +112 -88
- package/dist/processor/html.js.map +1 -1
- package/dist/processor/markdown.d.ts +1 -1
- package/dist/processor/markdown.d.ts.map +1 -1
- package/dist/processor/theme.d.ts +3 -3
- package/dist/processor/theme.d.ts.map +1 -1
- package/dist/processor/theme.js +29 -53
- package/dist/processor/theme.js.map +1 -1
- package/dist/server.d.ts +17 -38
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +76 -102
- package/dist/server.js.map +1 -1
- package/dist/util.d.ts +9 -29
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +54 -158
- package/dist/util.js.map +1 -1
- package/dist/vite/plugin-util.d.ts +6 -0
- package/dist/vite/plugin-util.d.ts.map +1 -0
- package/dist/vite/plugin-util.js +20 -0
- package/dist/vite/plugin-util.js.map +1 -0
- package/dist/vite/vite-plugin-browser.d.ts +8 -0
- package/dist/vite/vite-plugin-browser.d.ts.map +1 -0
- package/dist/vite/vite-plugin-browser.js +57 -0
- package/dist/vite/vite-plugin-browser.js.map +1 -0
- package/dist/vite/vite-plugin-dev-server.d.ts +8 -0
- package/dist/vite/vite-plugin-dev-server.d.ts.map +1 -0
- package/dist/vite/vite-plugin-dev-server.js +267 -0
- package/dist/vite/vite-plugin-dev-server.js.map +1 -0
- package/dist/vite/vite-plugin-static-serve.d.ts +8 -0
- package/dist/vite/vite-plugin-static-serve.d.ts.map +1 -0
- package/dist/vite/vite-plugin-static-serve.js +24 -0
- package/dist/vite/vite-plugin-static-serve.js.map +1 -0
- package/dist/vite/vite-plugin-viewer.d.ts +8 -0
- package/dist/vite/vite-plugin-viewer.d.ts.map +1 -0
- package/dist/vite/vite-plugin-viewer.js +52 -0
- package/dist/vite/vite-plugin-viewer.js.map +1 -0
- package/dist/vite-adapter.d.ts +3 -0
- package/dist/vite-adapter.d.ts.map +1 -0
- package/dist/vite-adapter.js +27 -0
- package/dist/vite-adapter.js.map +1 -0
- package/package.json +13 -15
- package/dist/build.d.ts +0 -21
- package/dist/build.d.ts.map +0 -1
- package/dist/build.js +0 -119
- package/dist/build.js.map +0 -1
- package/dist/init.d.ts +0 -16
- package/dist/init.d.ts.map +0 -1
- package/dist/init.js.map +0 -1
- package/dist/input/config.d.ts.map +0 -1
- package/dist/input/config.js +0 -807
- package/dist/input/config.js.map +0 -1
- package/dist/input/input-types.d.ts +0 -34
- package/dist/input/input-types.d.ts.map +0 -1
- package/dist/input/input-types.js +0 -34
- package/dist/input/input-types.js.map +0 -1
- package/dist/input/schema.d.ts.map +0 -1
- package/dist/input/schema.js +0 -233
- package/dist/input/schema.js.map +0 -1
- package/dist/output/output-types.d.ts +0 -26
- package/dist/output/output-types.d.ts.map +0 -1
- package/dist/output/output-types.js +0 -23
- package/dist/output/output-types.js.map +0 -1
- package/dist/preview.d.ts +0 -11
- package/dist/preview.d.ts.map +0 -1
- package/dist/preview.js +0 -191
- package/dist/preview.js.map +0 -1
package/dist/input/config.js
DELETED
|
@@ -1,807 +0,0 @@
|
|
|
1
|
-
import { VFM } from '@vivliostyle/vfm';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import * as cheerio from 'cheerio';
|
|
4
|
-
import fs from 'fs';
|
|
5
|
-
import { createRequire } from 'node:module';
|
|
6
|
-
import upath from 'upath';
|
|
7
|
-
import { pathToFileURL } from 'url';
|
|
8
|
-
import * as v from 'valibot';
|
|
9
|
-
import { getExecutableBrowserPath } from '../browser.js';
|
|
10
|
-
import { COVER_HTML_FILENAME, COVER_HTML_IMAGE_ALT, EPUB_OUTPUT_VERSION, MANIFEST_FILENAME, TOC_FILENAME, TOC_TITLE, } from '../const.js';
|
|
11
|
-
import { CONTAINER_IMAGE } from '../container.js';
|
|
12
|
-
import { detectInputFormat, detectManuscriptMediaType, } from '../input/input-types.js';
|
|
13
|
-
import { checkOutputFormat, checkPreflightMode, checkRenderMode, detectOutputFormat, } from '../output/output-types.js';
|
|
14
|
-
import { readMarkdownMetadata } from '../processor/markdown.js';
|
|
15
|
-
import { parsePackageName } from '../processor/theme.js';
|
|
16
|
-
import { DetailError, cwd, debug, isUrlString, log, logWarn, openEpubToTmpDirectory, parseJsonc, pathEquals, prettifySchemaError, readJSON, statFileSync, touchTmpFile, } from '../util.js';
|
|
17
|
-
import { VivliostyleConfigSchema, } from './schema.js';
|
|
18
|
-
const DEFAULT_TIMEOUT = 2 * 60 * 1000; // 2 minutes
|
|
19
|
-
const DEFAULT_ASSET_EXTENSIONS = [
|
|
20
|
-
'png',
|
|
21
|
-
'jpg',
|
|
22
|
-
'jpeg',
|
|
23
|
-
'svg',
|
|
24
|
-
'gif',
|
|
25
|
-
'webp',
|
|
26
|
-
'apng',
|
|
27
|
-
'ttf',
|
|
28
|
-
'otf',
|
|
29
|
-
'woff',
|
|
30
|
-
'woff2',
|
|
31
|
-
];
|
|
32
|
-
const require = createRequire(import.meta.url);
|
|
33
|
-
export function validateTimeoutFlag(val) {
|
|
34
|
-
return Number.isFinite(+val) && +val > 0 ? +val * 1000 : DEFAULT_TIMEOUT;
|
|
35
|
-
}
|
|
36
|
-
export function contextResolve(context, loc) {
|
|
37
|
-
return loc && upath.resolve(context, loc);
|
|
38
|
-
}
|
|
39
|
-
function normalizeEntry(e) {
|
|
40
|
-
if (typeof e === 'object') {
|
|
41
|
-
return e;
|
|
42
|
-
}
|
|
43
|
-
return { path: e };
|
|
44
|
-
}
|
|
45
|
-
// parse theme locator
|
|
46
|
-
export function parseTheme({ theme, context, workspaceDir, themesDir, }) {
|
|
47
|
-
const { specifier, import: importPath } = typeof theme === 'string' ? { specifier: theme, import: undefined } : theme;
|
|
48
|
-
// url
|
|
49
|
-
if (isUrlString(specifier)) {
|
|
50
|
-
return {
|
|
51
|
-
type: 'uri',
|
|
52
|
-
name: upath.basename(specifier),
|
|
53
|
-
location: specifier,
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
// bare .css file
|
|
57
|
-
const stylePath = upath.resolve(context, specifier);
|
|
58
|
-
if (fs.existsSync(stylePath) && stylePath.endsWith('.css')) {
|
|
59
|
-
const sourceRelPath = upath.relative(context, stylePath);
|
|
60
|
-
return {
|
|
61
|
-
type: 'file',
|
|
62
|
-
name: upath.basename(specifier),
|
|
63
|
-
source: stylePath,
|
|
64
|
-
location: upath.resolve(workspaceDir, sourceRelPath),
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
// node_modules, local pkg
|
|
68
|
-
const parsed = parsePackageName(specifier, context);
|
|
69
|
-
if (!parsed) {
|
|
70
|
-
throw new Error(`Invalid package name: ${specifier}`);
|
|
71
|
-
}
|
|
72
|
-
// To security reason, Vivliostyle CLI disallow other than npm registry or local file as download source
|
|
73
|
-
// TODO: Add option that user can allow an unofficial registry explicitly
|
|
74
|
-
if (!parsed.registry && parsed.type !== 'directory') {
|
|
75
|
-
throw new Error(`This package specifier is not allowed: ${specifier}`);
|
|
76
|
-
}
|
|
77
|
-
let name = parsed.name;
|
|
78
|
-
let resolvedSpecifier = specifier;
|
|
79
|
-
if (parsed.type === 'directory' && parsed.fetchSpec) {
|
|
80
|
-
const pkgJsonPath = upath.join(parsed.fetchSpec, 'package.json');
|
|
81
|
-
if (fs.existsSync(pkgJsonPath)) {
|
|
82
|
-
const packageJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'));
|
|
83
|
-
name = packageJson.name;
|
|
84
|
-
resolvedSpecifier = parsed.fetchSpec;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
if (!name) {
|
|
88
|
-
throw new Error(`Could not determine the package name: ${specifier}`);
|
|
89
|
-
}
|
|
90
|
-
return {
|
|
91
|
-
type: 'package',
|
|
92
|
-
name,
|
|
93
|
-
specifier: resolvedSpecifier,
|
|
94
|
-
location: upath.join(themesDir, 'packages', name),
|
|
95
|
-
importPath,
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
function parsePageSize(size) {
|
|
99
|
-
const [width, height, ...others] = `${size}`.split(',');
|
|
100
|
-
if (!width || others.length) {
|
|
101
|
-
throw new Error(`Cannot parse size: ${size}`);
|
|
102
|
-
}
|
|
103
|
-
else if (width && height) {
|
|
104
|
-
return {
|
|
105
|
-
width,
|
|
106
|
-
height,
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
return {
|
|
111
|
-
format: width,
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
function parseFileMetadata({ type, sourcePath, workspaceDir, themesDir, }) {
|
|
116
|
-
const sourceDir = upath.dirname(sourcePath);
|
|
117
|
-
let title;
|
|
118
|
-
let themes;
|
|
119
|
-
if (type === 'text/markdown') {
|
|
120
|
-
const metadata = readMarkdownMetadata(sourcePath);
|
|
121
|
-
title = metadata.title;
|
|
122
|
-
if (metadata.vfm?.theme && themesDir) {
|
|
123
|
-
themes = [metadata.vfm.theme]
|
|
124
|
-
.flat()
|
|
125
|
-
.filter((entry) => !!entry && (typeof entry === 'string' || typeof entry === 'object'))
|
|
126
|
-
.map((theme) => parseTheme({
|
|
127
|
-
theme,
|
|
128
|
-
context: sourceDir,
|
|
129
|
-
workspaceDir,
|
|
130
|
-
themesDir,
|
|
131
|
-
}));
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
const $ = cheerio.load(fs.readFileSync(sourcePath, 'utf8'));
|
|
136
|
-
title = $('title')?.text() || undefined;
|
|
137
|
-
}
|
|
138
|
-
return { title, themes };
|
|
139
|
-
}
|
|
140
|
-
export async function collectVivliostyleConfig(cliFlags) {
|
|
141
|
-
const load = async (configPath) => {
|
|
142
|
-
let config;
|
|
143
|
-
let jsonRaw;
|
|
144
|
-
try {
|
|
145
|
-
if (upath.extname(configPath) === '.json') {
|
|
146
|
-
jsonRaw = fs.readFileSync(configPath, 'utf8');
|
|
147
|
-
config = parseJsonc(jsonRaw);
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
// Clear require cache to reload CJS config files
|
|
151
|
-
delete require.cache[require.resolve(configPath)];
|
|
152
|
-
const url = pathToFileURL(configPath);
|
|
153
|
-
// Invalidate cache for ESM config files
|
|
154
|
-
// https://github.com/nodejs/node/issues/49442
|
|
155
|
-
url.search = `version=${Date.now()}`;
|
|
156
|
-
config = (await import(url.href)).default;
|
|
157
|
-
jsonRaw = JSON.stringify(config, null, 2);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
catch (error) {
|
|
161
|
-
const thrownError = error;
|
|
162
|
-
throw new DetailError(`An error occurred on loading a config file: ${configPath}`, thrownError.stack ?? thrownError.message);
|
|
163
|
-
}
|
|
164
|
-
const result = v.safeParse(VivliostyleConfigSchema, config);
|
|
165
|
-
if (result.success) {
|
|
166
|
-
return result.output;
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
const errorString = prettifySchemaError(jsonRaw, result.issues);
|
|
170
|
-
throw new DetailError(`Validation of vivliostyle config failed. Please check the schema: ${configPath}`, errorString);
|
|
171
|
-
}
|
|
172
|
-
};
|
|
173
|
-
let configEntry = {};
|
|
174
|
-
let vivliostyleConfigPath;
|
|
175
|
-
if (cliFlags.configPath) {
|
|
176
|
-
vivliostyleConfigPath = upath.resolve(cwd, cliFlags.configPath);
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
vivliostyleConfigPath = ['.js', '.mjs', '.cjs']
|
|
180
|
-
.map((ext) => upath.join(cwd, `vivliostyle.config${ext}`))
|
|
181
|
-
.find((p) => fs.existsSync(p));
|
|
182
|
-
}
|
|
183
|
-
// let vivliostyleConfig: VivliostyleConfigSchema | undefined;
|
|
184
|
-
if (vivliostyleConfigPath) {
|
|
185
|
-
configEntry = {
|
|
186
|
-
vivliostyleConfigPath,
|
|
187
|
-
vivliostyleConfig: [await load(vivliostyleConfigPath)].flat(),
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
else if (cliFlags.input &&
|
|
191
|
-
upath.basename(cliFlags.input).startsWith('vivliostyle.config')) {
|
|
192
|
-
// Load an input argument as a Vivliostyle config
|
|
193
|
-
try {
|
|
194
|
-
const inputPath = upath.resolve(cwd, cliFlags.input);
|
|
195
|
-
const inputConfig = await load(inputPath);
|
|
196
|
-
cliFlags = {
|
|
197
|
-
...cliFlags,
|
|
198
|
-
input: undefined,
|
|
199
|
-
};
|
|
200
|
-
configEntry = {
|
|
201
|
-
vivliostyleConfigPath: inputPath,
|
|
202
|
-
vivliostyleConfig: [inputConfig].flat(),
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
catch (_err) { }
|
|
206
|
-
}
|
|
207
|
-
if (cliFlags.executableChromium) {
|
|
208
|
-
logWarn(chalk.yellowBright("'--executable-chromium' option was deprecated and will be removed in a future release. Please replace with '--executable-browser' option."));
|
|
209
|
-
cliFlags.executableBrowser = cliFlags.executableChromium;
|
|
210
|
-
}
|
|
211
|
-
if (cliFlags.verbose) {
|
|
212
|
-
logWarn(chalk.yellowBright("'--verbose' option was deprecated and will be removed in a future release. Please replace with '--log-level verbose' option."));
|
|
213
|
-
}
|
|
214
|
-
if (cliFlags.sandbox === false) {
|
|
215
|
-
logWarn(chalk.yellowBright("'--no-sandbox' option was deprecated and will be removed in a future release. It is no longer necessary because the sandbox is disabled by default."));
|
|
216
|
-
}
|
|
217
|
-
const configEntries = (configEntry.vivliostyleConfig ?? []).flat();
|
|
218
|
-
if (configEntries.some((config) => config.includeAssets)) {
|
|
219
|
-
logWarn(chalk.yellowBright("'includeAssets' property of Vivliostyle config was deprecated and will be removed in a future release. Please use 'copyAsset.includes' property instead."));
|
|
220
|
-
}
|
|
221
|
-
if (configEntries.some((config) => config.tocTitle)) {
|
|
222
|
-
logWarn(chalk.yellowBright("'tocTitle' property of Vivliostyle config was deprecated and will be removed in a future release. Please use 'toc.title' property instead."));
|
|
223
|
-
}
|
|
224
|
-
return {
|
|
225
|
-
cliFlags,
|
|
226
|
-
...configEntry,
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
export async function mergeConfig(cliFlags, config, context, prevConfig) {
|
|
230
|
-
debug('context directory', context);
|
|
231
|
-
debug('cliFlags', cliFlags);
|
|
232
|
-
debug('vivliostyle.config.js', config);
|
|
233
|
-
let entryContextDir;
|
|
234
|
-
let workspaceDir;
|
|
235
|
-
if (cliFlags.input && !config && isUrlString(cliFlags.input)) {
|
|
236
|
-
workspaceDir = entryContextDir = cwd;
|
|
237
|
-
}
|
|
238
|
-
else {
|
|
239
|
-
entryContextDir = upath.resolve(cliFlags.input && !config
|
|
240
|
-
? upath.dirname(upath.resolve(context, cliFlags.input))
|
|
241
|
-
: (contextResolve(context, config?.entryContext) ?? context));
|
|
242
|
-
workspaceDir =
|
|
243
|
-
contextResolve(context, config?.workspaceDir) ?? entryContextDir;
|
|
244
|
-
}
|
|
245
|
-
const themesDir = upath.join(workspaceDir, 'themes');
|
|
246
|
-
const language = cliFlags.language ?? config?.language ?? undefined;
|
|
247
|
-
const readingProgression = cliFlags.readingProgression ?? config?.readingProgression ?? undefined;
|
|
248
|
-
const sizeFlag = cliFlags.size ?? config?.size;
|
|
249
|
-
const size = sizeFlag ? parsePageSize(sizeFlag) : undefined;
|
|
250
|
-
const cropMarks = cliFlags.cropMarks ?? false;
|
|
251
|
-
const bleed = cliFlags.bleed;
|
|
252
|
-
const cropOffset = cliFlags.cropOffset;
|
|
253
|
-
const css = cliFlags.css;
|
|
254
|
-
const customStyle = cliFlags.style &&
|
|
255
|
-
(isUrlString(cliFlags.style)
|
|
256
|
-
? cliFlags.style
|
|
257
|
-
: pathToFileURL(cliFlags.style).href);
|
|
258
|
-
const customUserStyle = cliFlags.userStyle &&
|
|
259
|
-
(isUrlString(cliFlags.userStyle)
|
|
260
|
-
? cliFlags.userStyle
|
|
261
|
-
: pathToFileURL(cliFlags.userStyle).href);
|
|
262
|
-
const singleDoc = cliFlags.singleDoc ?? false;
|
|
263
|
-
const quick = cliFlags.quick ?? false;
|
|
264
|
-
const pressReady = cliFlags.pressReady ?? config?.pressReady ?? false;
|
|
265
|
-
const renderMode = cliFlags.renderMode ?? 'local';
|
|
266
|
-
const preflight = cliFlags.preflight ?? (pressReady ? 'press-ready' : null);
|
|
267
|
-
const preflightOption = cliFlags.preflightOption ?? [];
|
|
268
|
-
const documentProcessorFactory = config?.documentProcessor ?? VFM;
|
|
269
|
-
const vfmOptions = {
|
|
270
|
-
...config?.vfm,
|
|
271
|
-
hardLineBreaks: config?.vfm?.hardLineBreaks ?? false,
|
|
272
|
-
disableFormatHtml: config?.vfm?.disableFormatHtml ?? false,
|
|
273
|
-
};
|
|
274
|
-
const timeout = cliFlags.timeout ?? config?.timeout ?? DEFAULT_TIMEOUT;
|
|
275
|
-
const sandbox = cliFlags.sandbox ?? false;
|
|
276
|
-
const browserType = cliFlags.browser ?? config?.browser ?? 'chromium';
|
|
277
|
-
const proxyServer = cliFlags.proxyServer ?? process.env.HTTP_PROXY ?? undefined;
|
|
278
|
-
const proxy = proxyServer
|
|
279
|
-
? {
|
|
280
|
-
server: proxyServer,
|
|
281
|
-
bypass: cliFlags.proxyBypass ?? process.env.NOPROXY ?? undefined,
|
|
282
|
-
username: cliFlags.proxyUser,
|
|
283
|
-
password: cliFlags.proxyPass,
|
|
284
|
-
}
|
|
285
|
-
: undefined;
|
|
286
|
-
const executableBrowser = cliFlags.executableBrowser ?? getExecutableBrowserPath(browserType);
|
|
287
|
-
const image = cliFlags.image ?? config?.image ?? CONTAINER_IMAGE;
|
|
288
|
-
const httpServer = cliFlags.http ?? config?.http ?? false;
|
|
289
|
-
const viewer = cliFlags.viewer ?? config?.viewer ?? undefined;
|
|
290
|
-
const viewerParam = cliFlags.viewerParam ?? config?.viewerParam ?? undefined;
|
|
291
|
-
const logLevel = cliFlags.logLevel ??
|
|
292
|
-
((cliFlags.verbose && 'verbose') || undefined) ??
|
|
293
|
-
'silent';
|
|
294
|
-
const ignoreHttpsErrors = cliFlags.ignoreHttpsErrors ?? false;
|
|
295
|
-
const rootThemes = cliFlags.theme
|
|
296
|
-
? [
|
|
297
|
-
parseTheme({
|
|
298
|
-
theme: cliFlags.theme,
|
|
299
|
-
context: cwd,
|
|
300
|
-
workspaceDir,
|
|
301
|
-
themesDir,
|
|
302
|
-
}),
|
|
303
|
-
]
|
|
304
|
-
: config?.theme
|
|
305
|
-
? [config.theme].flat().map((theme) => parseTheme({
|
|
306
|
-
theme,
|
|
307
|
-
context,
|
|
308
|
-
workspaceDir,
|
|
309
|
-
themesDir,
|
|
310
|
-
}))
|
|
311
|
-
: [];
|
|
312
|
-
const themeIndexes = new Set(rootThemes);
|
|
313
|
-
const outputs = (() => {
|
|
314
|
-
if (cliFlags.targets?.length) {
|
|
315
|
-
return cliFlags.targets.map(({ path: outputPath, format }) => {
|
|
316
|
-
if (format === 'pdf') {
|
|
317
|
-
return {
|
|
318
|
-
path: upath.resolve(outputPath),
|
|
319
|
-
format,
|
|
320
|
-
renderMode,
|
|
321
|
-
preflight,
|
|
322
|
-
preflightOption,
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
else if (format === 'epub') {
|
|
326
|
-
return {
|
|
327
|
-
path: upath.resolve(outputPath),
|
|
328
|
-
format,
|
|
329
|
-
version: EPUB_OUTPUT_VERSION,
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
else {
|
|
333
|
-
return {
|
|
334
|
-
path: upath.resolve(outputPath),
|
|
335
|
-
format,
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
if (config?.output) {
|
|
341
|
-
return (Array.isArray(config.output) ? config.output : [config.output]).map((target) => {
|
|
342
|
-
const targetObj = typeof target === 'string' ? { path: target } : target;
|
|
343
|
-
const outputPath = upath.resolve(context, targetObj.path);
|
|
344
|
-
const format = targetObj.format ?? detectOutputFormat(outputPath);
|
|
345
|
-
if (!checkOutputFormat(format)) {
|
|
346
|
-
throw new Error(`Unknown format: ${format}`);
|
|
347
|
-
}
|
|
348
|
-
if (format === 'pdf') {
|
|
349
|
-
const outputRenderMode = targetObj.renderMode ?? renderMode;
|
|
350
|
-
const outputPreflight = targetObj.preflight ?? preflight;
|
|
351
|
-
if (!checkRenderMode(outputRenderMode)) {
|
|
352
|
-
throw new Error(`Unknown renderMode: ${outputRenderMode}`);
|
|
353
|
-
}
|
|
354
|
-
if (outputPreflight !== null &&
|
|
355
|
-
!checkPreflightMode(outputPreflight)) {
|
|
356
|
-
throw new Error(`Unknown preflight: ${outputPreflight}`);
|
|
357
|
-
}
|
|
358
|
-
return {
|
|
359
|
-
...targetObj,
|
|
360
|
-
path: outputPath,
|
|
361
|
-
format,
|
|
362
|
-
renderMode: outputRenderMode,
|
|
363
|
-
preflight: outputPreflight,
|
|
364
|
-
preflightOption: targetObj.preflightOption ?? preflightOption,
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
|
-
else if (format === 'epub') {
|
|
368
|
-
return {
|
|
369
|
-
...targetObj,
|
|
370
|
-
path: outputPath,
|
|
371
|
-
format,
|
|
372
|
-
version: EPUB_OUTPUT_VERSION,
|
|
373
|
-
};
|
|
374
|
-
}
|
|
375
|
-
else {
|
|
376
|
-
return { ...targetObj, path: outputPath, format };
|
|
377
|
-
}
|
|
378
|
-
});
|
|
379
|
-
}
|
|
380
|
-
// Outputs a pdf file if any output configuration is not set
|
|
381
|
-
const filename = config?.title ? `${config.title}.pdf` : 'output.pdf';
|
|
382
|
-
return [
|
|
383
|
-
{
|
|
384
|
-
path: upath.resolve(context, filename),
|
|
385
|
-
format: 'pdf',
|
|
386
|
-
renderMode,
|
|
387
|
-
preflight,
|
|
388
|
-
preflightOption,
|
|
389
|
-
},
|
|
390
|
-
];
|
|
391
|
-
})();
|
|
392
|
-
const cover = (() => {
|
|
393
|
-
if (!config?.cover) {
|
|
394
|
-
return undefined;
|
|
395
|
-
}
|
|
396
|
-
const obj = typeof config.cover === 'string' ? { src: config.cover } : config.cover;
|
|
397
|
-
if (!('htmlPath' in obj)) {
|
|
398
|
-
obj.htmlPath = COVER_HTML_FILENAME;
|
|
399
|
-
}
|
|
400
|
-
return {
|
|
401
|
-
src: upath.resolve(entryContextDir, obj.src),
|
|
402
|
-
name: obj.name || COVER_HTML_IMAGE_ALT,
|
|
403
|
-
htmlPath: (obj.htmlPath && upath.resolve(workspaceDir, obj.htmlPath)) ||
|
|
404
|
-
undefined,
|
|
405
|
-
};
|
|
406
|
-
})();
|
|
407
|
-
const copyAsset = (() => {
|
|
408
|
-
const { includes: _includes, excludes = [], includeFileExtensions = [], excludeFileExtensions = [], } = config?.copyAsset || {};
|
|
409
|
-
const includes = _includes || [config?.includeAssets ?? []].flat();
|
|
410
|
-
const notAllowedPatternRe = /(^\s*[/\\]|^(.*[/\\])?\s*\.\.\s*([/\\].*)?$)/g;
|
|
411
|
-
// See the special characters of glob pattern
|
|
412
|
-
// https://github.com/micromatch/picomatch
|
|
413
|
-
const notAllowedExtensionRe = /([\\/*?@+!|(){}[\]]|\.\.|^\s*\.)/g;
|
|
414
|
-
Object.entries({ includes, excludes }).forEach(([propName, patterns]) => {
|
|
415
|
-
patterns.forEach((pattern) => {
|
|
416
|
-
if (notAllowedPatternRe.test(pattern)) {
|
|
417
|
-
throw new Error(`Invalid pattern was found in copyAsset.${propName} option: ${pattern}`);
|
|
418
|
-
}
|
|
419
|
-
});
|
|
420
|
-
});
|
|
421
|
-
Object.entries({ includeFileExtensions, excludeFileExtensions }).forEach(([propName, patterns]) => {
|
|
422
|
-
patterns.forEach((pattern) => {
|
|
423
|
-
if (notAllowedExtensionRe.test(pattern)) {
|
|
424
|
-
throw new Error(`Invalid pattern was found in copyAsset.${propName} option: ${pattern}`);
|
|
425
|
-
}
|
|
426
|
-
});
|
|
427
|
-
});
|
|
428
|
-
return {
|
|
429
|
-
includes,
|
|
430
|
-
excludes,
|
|
431
|
-
fileExtensions: [
|
|
432
|
-
...new Set([...DEFAULT_ASSET_EXTENSIONS, ...includeFileExtensions]),
|
|
433
|
-
].filter((ext) => !excludeFileExtensions.includes(ext)),
|
|
434
|
-
};
|
|
435
|
-
})();
|
|
436
|
-
const commonOpts = {
|
|
437
|
-
entryContextDir,
|
|
438
|
-
workspaceDir,
|
|
439
|
-
themesDir,
|
|
440
|
-
copyAsset,
|
|
441
|
-
outputs,
|
|
442
|
-
themeIndexes,
|
|
443
|
-
rootThemes,
|
|
444
|
-
size,
|
|
445
|
-
cropMarks,
|
|
446
|
-
bleed,
|
|
447
|
-
cropOffset,
|
|
448
|
-
css,
|
|
449
|
-
customStyle,
|
|
450
|
-
customUserStyle,
|
|
451
|
-
singleDoc,
|
|
452
|
-
quick,
|
|
453
|
-
language,
|
|
454
|
-
readingProgression,
|
|
455
|
-
documentProcessorFactory,
|
|
456
|
-
vfmOptions,
|
|
457
|
-
cover,
|
|
458
|
-
timeout,
|
|
459
|
-
sandbox,
|
|
460
|
-
executableBrowser,
|
|
461
|
-
browserType,
|
|
462
|
-
proxy,
|
|
463
|
-
image,
|
|
464
|
-
httpServer,
|
|
465
|
-
viewer,
|
|
466
|
-
viewerParam,
|
|
467
|
-
logLevel,
|
|
468
|
-
ignoreHttpsErrors,
|
|
469
|
-
};
|
|
470
|
-
if (!cliFlags.input && !config) {
|
|
471
|
-
throw new Error('No input is set. Please set an appropriate entry or a Vivliostyle config file.');
|
|
472
|
-
}
|
|
473
|
-
const parsedConfig = cliFlags.input
|
|
474
|
-
? await composeSingleInputConfig(commonOpts, cliFlags, config, prevConfig)
|
|
475
|
-
: await composeProjectConfig(commonOpts, cliFlags, config, context, prevConfig);
|
|
476
|
-
debug('parsedConfig', JSON.stringify(parsedConfig, null, 2));
|
|
477
|
-
return parsedConfig;
|
|
478
|
-
}
|
|
479
|
-
async function composeSingleInputConfig(otherConfig, cliFlags, config, prevConfig) {
|
|
480
|
-
debug('entering single entry config mode');
|
|
481
|
-
let sourcePath;
|
|
482
|
-
let input;
|
|
483
|
-
const title = cliFlags.title ?? config?.title;
|
|
484
|
-
const author = cliFlags.author ?? config?.author;
|
|
485
|
-
const workspaceDir = otherConfig.workspaceDir;
|
|
486
|
-
const entries = [];
|
|
487
|
-
const exportAliases = [];
|
|
488
|
-
const tmpPrefix = `.vs-${Date.now()}.`;
|
|
489
|
-
if (cliFlags.input && isUrlString(cliFlags.input)) {
|
|
490
|
-
sourcePath = cliFlags.input;
|
|
491
|
-
input = { format: 'webbook', entry: sourcePath };
|
|
492
|
-
}
|
|
493
|
-
else {
|
|
494
|
-
sourcePath = upath.resolve(cliFlags.input);
|
|
495
|
-
input = detectInputFormat(sourcePath);
|
|
496
|
-
// Check file exists
|
|
497
|
-
statFileSync(sourcePath);
|
|
498
|
-
}
|
|
499
|
-
if (input.format === 'markdown') {
|
|
500
|
-
// Single input file; create temporary file
|
|
501
|
-
const type = detectManuscriptMediaType(sourcePath);
|
|
502
|
-
const metadata = parseFileMetadata({ type, sourcePath, workspaceDir });
|
|
503
|
-
const relDir = upath.relative(otherConfig.entryContextDir, upath.dirname(sourcePath));
|
|
504
|
-
let target;
|
|
505
|
-
if (prevConfig) {
|
|
506
|
-
const prevEntry = prevConfig.entries.find((e) => e.source === sourcePath);
|
|
507
|
-
if (!prevEntry) {
|
|
508
|
-
throw new Error('Failed to reload config');
|
|
509
|
-
}
|
|
510
|
-
target = prevEntry.target;
|
|
511
|
-
}
|
|
512
|
-
else {
|
|
513
|
-
target = upath
|
|
514
|
-
.resolve(workspaceDir, relDir, `${tmpPrefix}${upath.basename(sourcePath)}`)
|
|
515
|
-
.replace(/\.md$/, '.html');
|
|
516
|
-
await touchTmpFile(target);
|
|
517
|
-
}
|
|
518
|
-
const themes = metadata.themes ?? [...otherConfig.rootThemes];
|
|
519
|
-
themes.forEach((t) => otherConfig.themeIndexes.add(t));
|
|
520
|
-
entries.push({
|
|
521
|
-
type,
|
|
522
|
-
source: sourcePath,
|
|
523
|
-
target,
|
|
524
|
-
title: metadata.title,
|
|
525
|
-
themes,
|
|
526
|
-
});
|
|
527
|
-
exportAliases.push({
|
|
528
|
-
source: target,
|
|
529
|
-
target: upath.resolve(upath.dirname(target), upath.basename(sourcePath).replace(/\.md$/, '.html')),
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
let fallbackTitle;
|
|
533
|
-
const manifestDeclaration = await (async () => {
|
|
534
|
-
if (input.format === 'markdown') {
|
|
535
|
-
// create temporary manifest file
|
|
536
|
-
const manifestPath = upath.resolve(workspaceDir, `${tmpPrefix}${MANIFEST_FILENAME}`);
|
|
537
|
-
await touchTmpFile(manifestPath);
|
|
538
|
-
exportAliases.push({
|
|
539
|
-
source: manifestPath,
|
|
540
|
-
target: upath.resolve(workspaceDir, MANIFEST_FILENAME),
|
|
541
|
-
});
|
|
542
|
-
fallbackTitle =
|
|
543
|
-
entries.length === 1 && entries[0].title
|
|
544
|
-
? entries[0].title
|
|
545
|
-
: upath.basename(sourcePath);
|
|
546
|
-
return { manifestPath, needToGenerateManifest: true };
|
|
547
|
-
}
|
|
548
|
-
else if (input.format === 'html' || input.format === 'webbook') {
|
|
549
|
-
const url = isUrlString(input.entry)
|
|
550
|
-
? new URL(input.entry)
|
|
551
|
-
: pathToFileURL(input.entry);
|
|
552
|
-
// Ensures trailing slash or explicit HTML extensions
|
|
553
|
-
if ((url.protocol === 'http:' || url.protocol === 'https:') &&
|
|
554
|
-
!url.pathname.endsWith('/') &&
|
|
555
|
-
!/\.html?$/.test(url.pathname)) {
|
|
556
|
-
url.pathname = `${url.pathname}/`;
|
|
557
|
-
}
|
|
558
|
-
return {
|
|
559
|
-
webbookEntryUrl: url.href,
|
|
560
|
-
};
|
|
561
|
-
}
|
|
562
|
-
else if (input.format === 'pub-manifest') {
|
|
563
|
-
return { manifestPath: input.entry };
|
|
564
|
-
}
|
|
565
|
-
else if (input.format === 'epub-opf') {
|
|
566
|
-
return { epubOpfPath: input.entry };
|
|
567
|
-
}
|
|
568
|
-
else if (input.format === 'epub') {
|
|
569
|
-
const { epubOpfPath } = await openEpubToTmpDirectory(input.entry);
|
|
570
|
-
return { epubOpfPath };
|
|
571
|
-
}
|
|
572
|
-
else {
|
|
573
|
-
throw new Error('Failed to export manifest declaration');
|
|
574
|
-
}
|
|
575
|
-
})();
|
|
576
|
-
return {
|
|
577
|
-
...otherConfig,
|
|
578
|
-
...manifestDeclaration,
|
|
579
|
-
entries,
|
|
580
|
-
input,
|
|
581
|
-
exportAliases,
|
|
582
|
-
title: title || fallbackTitle,
|
|
583
|
-
author: author,
|
|
584
|
-
};
|
|
585
|
-
}
|
|
586
|
-
async function composeProjectConfig(otherConfig, cliFlags, config, context, prevConfig) {
|
|
587
|
-
debug('entering project config mode');
|
|
588
|
-
const { entryContextDir, workspaceDir, themesDir, themeIndexes, rootThemes, outputs, cover, } = otherConfig;
|
|
589
|
-
const pkgJsonPath = upath.resolve(entryContextDir, 'package.json');
|
|
590
|
-
const pkgJson = fs.existsSync(pkgJsonPath)
|
|
591
|
-
? readJSON(pkgJsonPath)
|
|
592
|
-
: undefined;
|
|
593
|
-
if (pkgJson) {
|
|
594
|
-
debug('located package.json path', pkgJsonPath);
|
|
595
|
-
}
|
|
596
|
-
const exportAliases = [];
|
|
597
|
-
const tmpPrefix = `.vs-${Date.now()}.`;
|
|
598
|
-
const tocConfig = (() => {
|
|
599
|
-
const c = typeof config?.toc === 'object'
|
|
600
|
-
? config.toc
|
|
601
|
-
: typeof config?.toc === 'string'
|
|
602
|
-
? { htmlPath: config.toc }
|
|
603
|
-
: {};
|
|
604
|
-
return {
|
|
605
|
-
tocTitle: c.title ?? config?.tocTitle ?? TOC_TITLE,
|
|
606
|
-
target: upath.resolve(workspaceDir, c.htmlPath ?? TOC_FILENAME),
|
|
607
|
-
sectionDepth: c.sectionDepth ?? 0,
|
|
608
|
-
transform: {
|
|
609
|
-
transformDocumentList: c.transformDocumentList,
|
|
610
|
-
transformSectionList: c.transformSectionList,
|
|
611
|
-
},
|
|
612
|
-
};
|
|
613
|
-
})();
|
|
614
|
-
const ensureCoverImage = (src) => {
|
|
615
|
-
const absPath = src && upath.resolve(entryContextDir, src);
|
|
616
|
-
if (absPath) {
|
|
617
|
-
statFileSync(absPath, {
|
|
618
|
-
errorMessage: 'Specified cover image does not exist',
|
|
619
|
-
});
|
|
620
|
-
}
|
|
621
|
-
return absPath;
|
|
622
|
-
};
|
|
623
|
-
const projectTitle = cliFlags.title ?? config?.title ?? pkgJson?.name;
|
|
624
|
-
const projectAuthor = cliFlags.author ?? config?.author ?? pkgJson?.author;
|
|
625
|
-
const isContentsEntry = (entry) => entry.rel === 'contents';
|
|
626
|
-
const isCoverEntry = (entry) => entry.rel === 'cover';
|
|
627
|
-
const isArticleEntry = (entry) => !isContentsEntry(entry) && !isCoverEntry(entry);
|
|
628
|
-
async function parseEntry(entry) {
|
|
629
|
-
const getInputInfo = (entryPath) => {
|
|
630
|
-
const source = upath.resolve(entryContextDir, entryPath);
|
|
631
|
-
if (!isUrlString(source)) {
|
|
632
|
-
statFileSync(source);
|
|
633
|
-
}
|
|
634
|
-
const type = detectManuscriptMediaType(source);
|
|
635
|
-
return {
|
|
636
|
-
...parseFileMetadata({
|
|
637
|
-
type,
|
|
638
|
-
sourcePath: source,
|
|
639
|
-
workspaceDir,
|
|
640
|
-
themesDir,
|
|
641
|
-
}),
|
|
642
|
-
source,
|
|
643
|
-
type,
|
|
644
|
-
};
|
|
645
|
-
};
|
|
646
|
-
const getTargetPath = (source) => upath.resolve(workspaceDir, upath.relative(entryContextDir, source).replace(/\.md$/, '.html'));
|
|
647
|
-
if ((isContentsEntry(entry) || isCoverEntry(entry)) && entry.path) {
|
|
648
|
-
const source = upath.resolve(entryContextDir, entry.path);
|
|
649
|
-
try {
|
|
650
|
-
statFileSync(source);
|
|
651
|
-
/* v8 ignore next 10 */
|
|
652
|
-
}
|
|
653
|
-
catch (error) {
|
|
654
|
-
// For backward compatibility, we allow missing files then assume that option as `output` field.
|
|
655
|
-
logWarn(chalk.yellowBright(`The "path" option is set but the file does not exist: ${source}\nMaybe you want to set the "output" field instead.`));
|
|
656
|
-
entry.output = entry.path;
|
|
657
|
-
entry.path = undefined;
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
if (isContentsEntry(entry)) {
|
|
661
|
-
const inputInfo = entry.path ? getInputInfo(entry.path) : undefined;
|
|
662
|
-
let target = entry.output
|
|
663
|
-
? upath.resolve(workspaceDir, entry.output)
|
|
664
|
-
: inputInfo?.source && getTargetPath(inputInfo.source);
|
|
665
|
-
const themes = entry.theme
|
|
666
|
-
? [entry.theme].flat().map((theme) => parseTheme({
|
|
667
|
-
theme,
|
|
668
|
-
context,
|
|
669
|
-
workspaceDir,
|
|
670
|
-
themesDir,
|
|
671
|
-
}))
|
|
672
|
-
: (inputInfo?.themes ?? [...rootThemes]);
|
|
673
|
-
themes.forEach((t) => themeIndexes.add(t));
|
|
674
|
-
target ??= tocConfig.target;
|
|
675
|
-
if (inputInfo?.source && pathEquals(inputInfo.source, target)) {
|
|
676
|
-
const tmpPath = upath.resolve(upath.dirname(target), `${tmpPrefix}${upath.basename(target)}`);
|
|
677
|
-
exportAliases.push({ source: tmpPath, target });
|
|
678
|
-
await touchTmpFile(tmpPath);
|
|
679
|
-
target = tmpPath;
|
|
680
|
-
}
|
|
681
|
-
const parsedEntry = {
|
|
682
|
-
rel: 'contents',
|
|
683
|
-
...tocConfig,
|
|
684
|
-
target,
|
|
685
|
-
title: entry.title ?? inputInfo?.title ?? projectTitle,
|
|
686
|
-
themes,
|
|
687
|
-
pageBreakBefore: entry.pageBreakBefore,
|
|
688
|
-
pageCounterReset: entry.pageCounterReset,
|
|
689
|
-
...(inputInfo && {
|
|
690
|
-
template: { source: inputInfo.source, type: inputInfo.type },
|
|
691
|
-
}),
|
|
692
|
-
};
|
|
693
|
-
return parsedEntry;
|
|
694
|
-
}
|
|
695
|
-
if (isCoverEntry(entry)) {
|
|
696
|
-
const inputInfo = entry.path ? getInputInfo(entry.path) : undefined;
|
|
697
|
-
let target = entry.output
|
|
698
|
-
? upath.resolve(workspaceDir, entry.output)
|
|
699
|
-
: inputInfo?.source && getTargetPath(inputInfo.source);
|
|
700
|
-
const themes = entry.theme
|
|
701
|
-
? [entry.theme].flat().map((theme) => parseTheme({
|
|
702
|
-
theme,
|
|
703
|
-
context,
|
|
704
|
-
workspaceDir,
|
|
705
|
-
themesDir,
|
|
706
|
-
}))
|
|
707
|
-
: (inputInfo?.themes ?? []); // Don't inherit rootThemes for cover documents
|
|
708
|
-
themes.forEach((t) => themeIndexes.add(t));
|
|
709
|
-
const coverImageSrc = ensureCoverImage(entry.imageSrc || cover?.src);
|
|
710
|
-
if (!coverImageSrc) {
|
|
711
|
-
throw new Error(`A CoverEntryObject is set in the entry list but a location of cover file is not set. Please set 'cover' property in your config file.`);
|
|
712
|
-
}
|
|
713
|
-
target ??= upath.resolve(workspaceDir, entry.path || cover?.htmlPath || COVER_HTML_FILENAME);
|
|
714
|
-
if (inputInfo?.source && pathEquals(inputInfo.source, target)) {
|
|
715
|
-
const tmpPath = upath.resolve(upath.dirname(target), `${tmpPrefix}${upath.basename(target)}`);
|
|
716
|
-
exportAliases.push({ source: tmpPath, target });
|
|
717
|
-
await touchTmpFile(tmpPath);
|
|
718
|
-
target = tmpPath;
|
|
719
|
-
}
|
|
720
|
-
const parsedEntry = {
|
|
721
|
-
rel: 'cover',
|
|
722
|
-
target,
|
|
723
|
-
title: entry.title ?? inputInfo?.title ?? projectTitle,
|
|
724
|
-
themes,
|
|
725
|
-
coverImageSrc,
|
|
726
|
-
coverImageAlt: entry.imageAlt || cover?.name || COVER_HTML_IMAGE_ALT,
|
|
727
|
-
pageBreakBefore: entry.pageBreakBefore,
|
|
728
|
-
...(inputInfo && {
|
|
729
|
-
template: { source: inputInfo.source, type: inputInfo.type },
|
|
730
|
-
}),
|
|
731
|
-
};
|
|
732
|
-
return parsedEntry;
|
|
733
|
-
}
|
|
734
|
-
if (isArticleEntry(entry)) {
|
|
735
|
-
const inputInfo = getInputInfo(entry.path);
|
|
736
|
-
const target = entry.output
|
|
737
|
-
? upath.resolve(workspaceDir, entry.output)
|
|
738
|
-
: getTargetPath(inputInfo.source);
|
|
739
|
-
const themes = entry.theme
|
|
740
|
-
? [entry.theme]
|
|
741
|
-
.flat()
|
|
742
|
-
.map((theme) => parseTheme({ theme, context, workspaceDir, themesDir }))
|
|
743
|
-
: (inputInfo.themes ?? [...rootThemes]);
|
|
744
|
-
themes.forEach((t) => themeIndexes.add(t));
|
|
745
|
-
const parsedEntry = {
|
|
746
|
-
type: inputInfo.type,
|
|
747
|
-
source: inputInfo.source,
|
|
748
|
-
target,
|
|
749
|
-
title: entry.title ?? inputInfo.title ?? projectTitle,
|
|
750
|
-
themes,
|
|
751
|
-
...(entry.rel && { rel: entry.rel }),
|
|
752
|
-
};
|
|
753
|
-
return parsedEntry;
|
|
754
|
-
}
|
|
755
|
-
/* v8 ignore next */
|
|
756
|
-
throw new Error('Unknown entry type');
|
|
757
|
-
}
|
|
758
|
-
const entries = await Promise.all([config?.entry || []].flat().map(normalizeEntry).map(parseEntry));
|
|
759
|
-
if (!entries.length) {
|
|
760
|
-
throw new Error('The entry fields seems to be empty. Make sure your Vivliostyle configuration.');
|
|
761
|
-
}
|
|
762
|
-
let fallbackProjectTitle;
|
|
763
|
-
if (!projectTitle) {
|
|
764
|
-
if (entries.length === 1 && entries[0].title) {
|
|
765
|
-
fallbackProjectTitle = entries[0].title;
|
|
766
|
-
}
|
|
767
|
-
else {
|
|
768
|
-
fallbackProjectTitle = upath.basename(outputs[0].path);
|
|
769
|
-
log(`\n${chalk.yellow('Could not find any appropriate publication title. We set ')}${chalk.bold.yellow(`"${fallbackProjectTitle}"`)}${chalk.yellow(' as a fallback.')}`);
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
if (!!config?.toc && !entries.find(({ rel }) => rel === 'contents')) {
|
|
773
|
-
entries.unshift({
|
|
774
|
-
rel: 'contents',
|
|
775
|
-
...tocConfig,
|
|
776
|
-
themes: [...rootThemes],
|
|
777
|
-
});
|
|
778
|
-
}
|
|
779
|
-
if (cover?.htmlPath && !entries.find(({ rel }) => rel === 'cover')) {
|
|
780
|
-
entries.unshift({
|
|
781
|
-
rel: 'cover',
|
|
782
|
-
target: cover.htmlPath,
|
|
783
|
-
title: projectTitle,
|
|
784
|
-
themes: [], // Don't inherit rootThemes for cover documents
|
|
785
|
-
coverImageSrc: ensureCoverImage(cover.src),
|
|
786
|
-
coverImageAlt: cover.name,
|
|
787
|
-
});
|
|
788
|
-
}
|
|
789
|
-
const coverEntires = entries.filter(({ rel }) => rel === 'cover');
|
|
790
|
-
if (coverEntires.length !== new Set(coverEntires.map((v) => v.target)).size) {
|
|
791
|
-
throw new Error('Multiple cover entries which has same output were found. Each cover entries must have an unique path.');
|
|
792
|
-
}
|
|
793
|
-
return {
|
|
794
|
-
...otherConfig,
|
|
795
|
-
entries,
|
|
796
|
-
input: {
|
|
797
|
-
format: 'pub-manifest',
|
|
798
|
-
entry: upath.join(workspaceDir, MANIFEST_FILENAME),
|
|
799
|
-
},
|
|
800
|
-
exportAliases,
|
|
801
|
-
manifestPath: upath.join(workspaceDir, MANIFEST_FILENAME),
|
|
802
|
-
title: projectTitle || fallbackProjectTitle,
|
|
803
|
-
author: projectAuthor,
|
|
804
|
-
needToGenerateManifest: true,
|
|
805
|
-
};
|
|
806
|
-
}
|
|
807
|
-
//# sourceMappingURL=config.js.map
|