@thegetty/quire-cli 1.0.0-rc.44 → 1.0.0-rc.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -36
- package/README.md +0 -9
- package/bin/cli.js +1 -46
- package/package.json +9 -25
- package/src/Command.js +6 -26
- package/src/commands/README.md +122 -213
- package/src/commands/build.js +37 -45
- package/src/commands/clean.js +19 -33
- package/src/commands/conf.js +43 -0
- package/src/commands/create.js +14 -42
- package/src/commands/epub.js +31 -67
- package/src/commands/index.js +2 -9
- package/src/commands/info.js +86 -88
- package/src/commands/pdf.js +82 -63
- package/src/commands/preview.js +31 -32
- package/src/commands/validate.js +20 -64
- package/src/commands/version.js +43 -0
- package/src/errors/validation/validation-error.js +11 -20
- package/src/helpers/clean.js +1 -1
- package/src/helpers/is-quire.js +31 -0
- package/src/helpers/test-cwd.js +6 -5
- package/src/helpers/which.js +4 -10
- package/src/lib/11ty/README.md +19 -135
- package/src/lib/11ty/api.js +93 -235
- package/src/lib/11ty/cli.js +37 -112
- package/src/lib/11ty/index.js +5 -64
- package/src/lib/11ty/paths.js +103 -0
- package/src/lib/README.md +0 -330
- package/src/lib/conf/README.md +69 -86
- package/src/lib/conf/config.js +3 -5
- package/src/lib/conf/defaults.js +0 -65
- package/src/lib/conf/schema.js +9 -103
- package/src/lib/epub/README.md +2 -133
- package/src/lib/epub/epub.js +11 -36
- package/src/lib/epub/index.js +21 -111
- package/src/lib/epub/pandoc.js +4 -33
- package/src/lib/git/README.md +2 -151
- package/src/lib/git/index.js +13 -217
- package/src/lib/i18n/README.md +3 -0
- package/src/lib/i18n/config.js +53 -0
- package/src/lib/i18n/index.js +43 -0
- package/src/lib/i18n/localeService.js +58 -0
- package/src/lib/pdf/README.md +0 -131
- package/src/lib/pdf/index.js +21 -124
- package/src/lib/pdf/paged.js +52 -100
- package/src/lib/pdf/prince.js +37 -115
- package/src/lib/pdf/split.js +33 -61
- package/src/lib/quire/README.md +19 -0
- package/src/lib/quire/index.js +353 -0
- package/src/lib/reporter/README.md +2 -211
- package/src/lib/reporter/index.js +0 -607
- package/src/main.js +48 -221
- package/src/packageConfig.js +0 -17
- package/src/validators/utils.js +1 -2
- package/schemas/config.schema.json +0 -194
- package/schemas/figures.schema.json +0 -56
- package/schemas/layout.schema.json +0 -5
- package/schemas/objects.schema.json +0 -62
- package/schemas/publication.schema.json +0 -140
- package/schemas/references.schema.json +0 -29
- package/src/Command.spec.js +0 -99
- package/src/commands/build.spec.js +0 -113
- package/src/commands/build.test.js +0 -397
- package/src/commands/clean.spec.js +0 -118
- package/src/commands/clean.test.js +0 -382
- package/src/commands/config.js +0 -238
- package/src/commands/config.spec.js +0 -107
- package/src/commands/config.test.js +0 -845
- package/src/commands/create.spec.js +0 -112
- package/src/commands/create.test.js +0 -415
- package/src/commands/doctor.js +0 -251
- package/src/commands/doctor.spec.js +0 -115
- package/src/commands/doctor.test.js +0 -1409
- package/src/commands/epub.spec.js +0 -114
- package/src/commands/epub.test.js +0 -503
- package/src/commands/help.js +0 -60
- package/src/commands/help.test.js +0 -132
- package/src/commands/info.spec.js +0 -72
- package/src/commands/info.test.js +0 -512
- package/src/commands/pdf.spec.js +0 -114
- package/src/commands/pdf.test.js +0 -464
- package/src/commands/preview.spec.js +0 -97
- package/src/commands/preview.test.js +0 -250
- package/src/commands/use.js +0 -56
- package/src/commands/use.spec.js +0 -61
- package/src/commands/use.test.js +0 -280
- package/src/commands/validate.spec.js +0 -90
- package/src/commands/validate.test.js +0 -378
- package/src/commands/workflows.js +0 -70
- package/src/errors/build/build-failed-error.js +0 -19
- package/src/errors/build/config-field-missing-error.js +0 -20
- package/src/errors/build/config-file-not-found-error.js +0 -20
- package/src/errors/build/index.js +0 -11
- package/src/errors/help/help-topic-not-found-error.js +0 -30
- package/src/errors/help/index.js +0 -8
- package/src/errors/index.js +0 -58
- package/src/errors/input/index.js +0 -8
- package/src/errors/input/invalid-input-error.js +0 -21
- package/src/errors/install/dependency-install-error.js +0 -19
- package/src/errors/install/directory-not-empty-error.js +0 -25
- package/src/errors/install/index.js +0 -12
- package/src/errors/install/invalid-path-error.js +0 -31
- package/src/errors/install/invalid-starter-error.js +0 -27
- package/src/errors/install/version-not-found-error.js +0 -35
- package/src/errors/output/epub-generation-error.js +0 -19
- package/src/errors/output/index.js +0 -14
- package/src/errors/output/invalid-epub-library-error.js +0 -20
- package/src/errors/output/invalid-pdf-library-error.js +0 -20
- package/src/errors/output/missing-build-output-error.js +0 -21
- package/src/errors/output/pdf-generation-error.js +0 -24
- package/src/errors/output/tool-not-found-error.js +0 -37
- package/src/errors/project/index.js +0 -10
- package/src/errors/project/not-in-project-error.js +0 -20
- package/src/errors/project/project-create-error.js +0 -21
- package/src/errors/quire-error.js +0 -27
- package/src/errors/validation/index.js +0 -3
- package/src/errors/validation/unknown-config-key-error.js +0 -27
- package/src/errors/validation/unknown-config-operation-error.js +0 -24
- package/src/helpers/docs-url.js +0 -32
- package/src/helpers/pager.js +0 -59
- package/src/helpers/pager.test.js +0 -85
- package/src/helpers/suggest-similar.js +0 -124
- package/src/helpers/suggest-similar.test.js +0 -108
- package/src/helpers/test-cwd.test.js +0 -192
- package/src/lib/11ty/index.test.js +0 -655
- package/src/lib/commander/index.js +0 -103
- package/src/lib/commander/index.test.js +0 -86
- package/src/lib/commander/options.js +0 -237
- package/src/lib/commander/options.test.js +0 -205
- package/src/lib/conf/build-status.js +0 -103
- package/src/lib/conf/build-status.test.js +0 -247
- package/src/lib/conf/config.test.js +0 -281
- package/src/lib/conf/format.js +0 -60
- package/src/lib/conf/format.test.js +0 -106
- package/src/lib/conf/helpers.js +0 -91
- package/src/lib/conf/helpers.test.js +0 -136
- package/src/lib/conf/index.js +0 -22
- package/src/lib/constants.js +0 -28
- package/src/lib/doctor/README.md +0 -667
- package/src/lib/doctor/checks/environment/cli-version.js +0 -62
- package/src/lib/doctor/checks/environment/cli-version.test.js +0 -132
- package/src/lib/doctor/checks/environment/git-available.js +0 -77
- package/src/lib/doctor/checks/environment/git-available.test.js +0 -52
- package/src/lib/doctor/checks/environment/index.js +0 -13
- package/src/lib/doctor/checks/environment/node-version.js +0 -66
- package/src/lib/doctor/checks/environment/node-version.test.js +0 -17
- package/src/lib/doctor/checks/environment/npm-available.js +0 -66
- package/src/lib/doctor/checks/environment/npm-available.test.js +0 -52
- package/src/lib/doctor/checks/environment/os-info.js +0 -48
- package/src/lib/doctor/checks/environment/os-info.test.js +0 -81
- package/src/lib/doctor/checks/environment/runtime-info.js +0 -51
- package/src/lib/doctor/checks/environment/runtime-info.test.js +0 -132
- package/src/lib/doctor/checks/outputs/epub-output.js +0 -119
- package/src/lib/doctor/checks/outputs/epub-output.test.js +0 -277
- package/src/lib/doctor/checks/outputs/index.js +0 -10
- package/src/lib/doctor/checks/outputs/pdf-output.js +0 -144
- package/src/lib/doctor/checks/outputs/pdf-output.test.js +0 -377
- package/src/lib/doctor/checks/outputs/stale-build.js +0 -122
- package/src/lib/doctor/checks/outputs/stale-build.test.js +0 -282
- package/src/lib/doctor/checks/project/data-files.js +0 -56
- package/src/lib/doctor/checks/project/data-files.test.js +0 -125
- package/src/lib/doctor/checks/project/dependencies.js +0 -53
- package/src/lib/doctor/checks/project/dependencies.test.js +0 -71
- package/src/lib/doctor/checks/project/index.js +0 -11
- package/src/lib/doctor/checks/project/quire-11ty.js +0 -98
- package/src/lib/doctor/checks/project/quire-11ty.test.js +0 -170
- package/src/lib/doctor/checks/project/quire-project.js +0 -38
- package/src/lib/doctor/checks/project/quire-project.test.js +0 -47
- package/src/lib/doctor/checks/tools/index.js +0 -10
- package/src/lib/doctor/checks/tools/pandoc-available.js +0 -82
- package/src/lib/doctor/checks/tools/pandoc-available.test.js +0 -73
- package/src/lib/doctor/checks/tools/prince-available.js +0 -81
- package/src/lib/doctor/checks/tools/prince-available.test.js +0 -73
- package/src/lib/doctor/constants.js +0 -39
- package/src/lib/doctor/formatDuration.js +0 -108
- package/src/lib/doctor/formatDuration.test.js +0 -76
- package/src/lib/doctor/formatters/human.js +0 -257
- package/src/lib/doctor/formatters/human.test.js +0 -463
- package/src/lib/doctor/formatters/index.js +0 -8
- package/src/lib/doctor/formatters/json.js +0 -78
- package/src/lib/doctor/formatters/json.test.js +0 -174
- package/src/lib/doctor/formatters/shared.js +0 -129
- package/src/lib/doctor/formatters/shared.test.js +0 -194
- package/src/lib/doctor/index.js +0 -271
- package/src/lib/doctor/index.test.js +0 -797
- package/src/lib/epub/engines.js +0 -46
- package/src/lib/epub/index.test.js +0 -518
- package/src/lib/epub/pandoc.test.js +0 -122
- package/src/lib/epub/schema.js +0 -21
- package/src/lib/error/README.md +0 -170
- package/src/lib/error/handler.js +0 -107
- package/src/lib/git/index.spec.js +0 -80
- package/src/lib/git/index.test.js +0 -453
- package/src/lib/help/frontmatter.js +0 -77
- package/src/lib/help/frontmatter.test.js +0 -139
- package/src/lib/help/index.js +0 -146
- package/src/lib/help/index.test.js +0 -188
- package/src/lib/help/topics/configuration.md +0 -77
- package/src/lib/help/topics/debugging.md +0 -69
- package/src/lib/help/topics/epub.md +0 -74
- package/src/lib/help/topics/pdf.md +0 -74
- package/src/lib/help/topics/publishing.md +0 -80
- package/src/lib/help/topics/workflows.md +0 -50
- package/src/lib/installer/index.js +0 -309
- package/src/lib/installer/index.spec.js +0 -83
- package/src/lib/installer/index.test.js +0 -545
- package/src/lib/logger/README.md +0 -424
- package/src/lib/logger/debug.js +0 -132
- package/src/lib/logger/debug.spec.js +0 -130
- package/src/lib/logger/debug.test.js +0 -128
- package/src/lib/logger/index.js +0 -228
- package/src/lib/logger/index.spec.js +0 -131
- package/src/lib/logger/index.test.js +0 -578
- package/src/lib/npm/README.md +0 -127
- package/src/lib/npm/index.js +0 -198
- package/src/lib/npm/index.spec.js +0 -60
- package/src/lib/npm/index.test.js +0 -355
- package/src/lib/pdf/engines.js +0 -46
- package/src/lib/pdf/index.test.js +0 -708
- package/src/lib/pdf/paged.test.js +0 -366
- package/src/lib/pdf/prince.test.js +0 -202
- package/src/lib/pdf/schema.js +0 -21
- package/src/lib/pdf/split.test.js +0 -445
- package/src/lib/platform.js +0 -95
- package/src/lib/process/manager.js +0 -110
- package/src/lib/process/manager.test.js +0 -55
- package/src/lib/project/build.js +0 -162
- package/src/lib/project/build.test.js +0 -275
- package/src/lib/project/config.js +0 -48
- package/src/lib/project/config.test.js +0 -134
- package/src/lib/project/detect.js +0 -47
- package/src/lib/project/detect.test.js +0 -157
- package/src/lib/project/index.js +0 -56
- package/src/lib/project/output-paths.js +0 -87
- package/src/lib/project/output-paths.test.js +0 -66
- package/src/lib/project/paths.js +0 -272
- package/src/lib/project/version.js +0 -110
- package/src/lib/project/version.test.js +0 -350
- package/src/lib/reporter/index.test.js +0 -862
- package/src/main.spec.js +0 -61
- package/src/main.test.js +0 -347
- package/src/validators/validate-data-files.js +0 -154
- package/src/validators/validate-data-files.test.js +0 -217
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Node.js runtime info check
|
|
3
|
-
*
|
|
4
|
-
* Reports V8 heap limit and environment variables relevant to
|
|
5
|
-
* troubleshooting (NODE_OPTIONS, shell, locale). This is an
|
|
6
|
-
* informational check that always passes.
|
|
7
|
-
*
|
|
8
|
-
* @module lib/doctor/checks/environment/runtime-info
|
|
9
|
-
*/
|
|
10
|
-
import v8 from 'node:v8'
|
|
11
|
-
import createDebug from '#debug'
|
|
12
|
-
import { getPlatform, Platform } from '#lib/platform.js'
|
|
13
|
-
|
|
14
|
-
const debug = createDebug('lib:doctor:runtime-info')
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Report Node.js runtime information
|
|
18
|
-
*
|
|
19
|
-
* Surfaces the V8 heap size limit (which determines when large Quire
|
|
20
|
-
* builds hit OOM errors) and environment variables that affect CLI
|
|
21
|
-
* behavior: NODE_OPTIONS, shell, and locale.
|
|
22
|
-
*
|
|
23
|
-
* @returns {import('../../index.js').CheckResult}
|
|
24
|
-
*/
|
|
25
|
-
export function checkRuntimeInfo() {
|
|
26
|
-
const heapStats = v8.getHeapStatistics()
|
|
27
|
-
const heapLimitMB = Math.round(heapStats.heap_size_limit / 1024 / 1024)
|
|
28
|
-
|
|
29
|
-
const platform = getPlatform()
|
|
30
|
-
const shell = platform === Platform.WINDOWS
|
|
31
|
-
? process.env.COMSPEC || '(not set)'
|
|
32
|
-
: process.env.SHELL || '(not set)'
|
|
33
|
-
const nodeOptions = process.env.NODE_OPTIONS || '(not set)'
|
|
34
|
-
const locale = process.env.LANG || process.env.LC_ALL || '(not set)'
|
|
35
|
-
|
|
36
|
-
debug('Heap limit: %d MB, NODE_OPTIONS: %s, Shell: %s, Locale: %s', heapLimitMB, nodeOptions, shell, locale)
|
|
37
|
-
|
|
38
|
-
const detailParts = [
|
|
39
|
-
`NODE_OPTIONS: ${nodeOptions}`,
|
|
40
|
-
`Shell: ${shell}`,
|
|
41
|
-
`Locale: ${locale}`,
|
|
42
|
-
]
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
ok: true,
|
|
46
|
-
message: `Heap limit: ${heapLimitMB} MB`,
|
|
47
|
-
details: detailParts.join(', '),
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export default checkRuntimeInfo
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import test from 'ava'
|
|
2
|
-
import sinon from 'sinon'
|
|
3
|
-
import esmock from 'esmock'
|
|
4
|
-
|
|
5
|
-
test.beforeEach((t) => {
|
|
6
|
-
t.context.sandbox = sinon.createSandbox()
|
|
7
|
-
})
|
|
8
|
-
|
|
9
|
-
test.afterEach.always((t) => {
|
|
10
|
-
t.context.sandbox.restore()
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
test('checkRuntimeInfo returns ok with heap limit', async (t) => {
|
|
14
|
-
const { sandbox } = t.context
|
|
15
|
-
|
|
16
|
-
const { checkRuntimeInfo } = await esmock('./runtime-info.js', {
|
|
17
|
-
'node:v8': {
|
|
18
|
-
getHeapStatistics: sandbox.stub().returns({
|
|
19
|
-
heap_size_limit: 4 * 1024 * 1024 * 1024, // 4 GB
|
|
20
|
-
}),
|
|
21
|
-
},
|
|
22
|
-
'#lib/platform.js': {
|
|
23
|
-
getPlatform: sandbox.stub().returns('macos'),
|
|
24
|
-
Platform: { MACOS: 'macos', WINDOWS: 'windows', LINUX: 'linux' },
|
|
25
|
-
},
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
const result = checkRuntimeInfo()
|
|
29
|
-
|
|
30
|
-
t.true(result.ok)
|
|
31
|
-
t.regex(result.message, /Heap limit: 4096 MB/)
|
|
32
|
-
t.is(typeof result.details, 'string')
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
test('checkRuntimeInfo includes NODE_OPTIONS in details', async (t) => {
|
|
36
|
-
const { sandbox } = t.context
|
|
37
|
-
|
|
38
|
-
const { checkRuntimeInfo } = await esmock('./runtime-info.js', {
|
|
39
|
-
'node:v8': {
|
|
40
|
-
getHeapStatistics: sandbox.stub().returns({
|
|
41
|
-
heap_size_limit: 8 * 1024 * 1024 * 1024,
|
|
42
|
-
}),
|
|
43
|
-
},
|
|
44
|
-
'#lib/platform.js': {
|
|
45
|
-
getPlatform: sandbox.stub().returns('macos'),
|
|
46
|
-
Platform: { MACOS: 'macos', WINDOWS: 'windows', LINUX: 'linux' },
|
|
47
|
-
},
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
const result = checkRuntimeInfo()
|
|
51
|
-
|
|
52
|
-
// NODE_OPTIONS should appear in details (either the actual value or '(not set)')
|
|
53
|
-
t.true(result.details.includes('NODE_OPTIONS:'))
|
|
54
|
-
t.true(result.details.includes('Shell:'))
|
|
55
|
-
t.true(result.details.includes('Locale:'))
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
test('checkRuntimeInfo shows (not set) for missing env vars', async (t) => {
|
|
59
|
-
const { sandbox } = t.context
|
|
60
|
-
|
|
61
|
-
const originalNodeOptions = process.env.NODE_OPTIONS
|
|
62
|
-
const originalShell = process.env.SHELL
|
|
63
|
-
const originalLang = process.env.LANG
|
|
64
|
-
const originalLcAll = process.env.LC_ALL
|
|
65
|
-
|
|
66
|
-
delete process.env.NODE_OPTIONS
|
|
67
|
-
delete process.env.SHELL
|
|
68
|
-
delete process.env.LANG
|
|
69
|
-
delete process.env.LC_ALL
|
|
70
|
-
|
|
71
|
-
try {
|
|
72
|
-
const { checkRuntimeInfo } = await esmock('./runtime-info.js', {
|
|
73
|
-
'node:v8': {
|
|
74
|
-
getHeapStatistics: sandbox.stub().returns({
|
|
75
|
-
heap_size_limit: 4 * 1024 * 1024 * 1024,
|
|
76
|
-
}),
|
|
77
|
-
},
|
|
78
|
-
'#lib/platform.js': {
|
|
79
|
-
getPlatform: sandbox.stub().returns('linux'),
|
|
80
|
-
Platform: { MACOS: 'macos', WINDOWS: 'windows', LINUX: 'linux' },
|
|
81
|
-
},
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
const result = checkRuntimeInfo()
|
|
85
|
-
|
|
86
|
-
t.true(result.details.includes('NODE_OPTIONS: (not set)'))
|
|
87
|
-
t.true(result.details.includes('Shell: (not set)'))
|
|
88
|
-
t.true(result.details.includes('Locale: (not set)'))
|
|
89
|
-
} finally {
|
|
90
|
-
if (originalNodeOptions !== undefined) process.env.NODE_OPTIONS = originalNodeOptions
|
|
91
|
-
if (originalShell !== undefined) process.env.SHELL = originalShell
|
|
92
|
-
if (originalLang !== undefined) process.env.LANG = originalLang
|
|
93
|
-
if (originalLcAll !== undefined) process.env.LC_ALL = originalLcAll
|
|
94
|
-
}
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
test('checkRuntimeInfo uses COMSPEC on Windows', async (t) => {
|
|
98
|
-
const { sandbox } = t.context
|
|
99
|
-
|
|
100
|
-
const originalShell = process.env.SHELL
|
|
101
|
-
const originalComspec = process.env.COMSPEC
|
|
102
|
-
|
|
103
|
-
delete process.env.SHELL
|
|
104
|
-
process.env.COMSPEC = 'C:\\Windows\\System32\\cmd.exe'
|
|
105
|
-
|
|
106
|
-
try {
|
|
107
|
-
const { checkRuntimeInfo } = await esmock('./runtime-info.js', {
|
|
108
|
-
'node:v8': {
|
|
109
|
-
getHeapStatistics: sandbox.stub().returns({
|
|
110
|
-
heap_size_limit: 4 * 1024 * 1024 * 1024,
|
|
111
|
-
}),
|
|
112
|
-
},
|
|
113
|
-
'#lib/platform.js': {
|
|
114
|
-
getPlatform: sandbox.stub().returns('windows'),
|
|
115
|
-
Platform: { MACOS: 'macos', WINDOWS: 'windows', LINUX: 'linux' },
|
|
116
|
-
},
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
const result = checkRuntimeInfo()
|
|
120
|
-
|
|
121
|
-
t.true(result.details.includes('Shell: C:\\Windows\\System32\\cmd.exe'))
|
|
122
|
-
} finally {
|
|
123
|
-
if (originalShell !== undefined) {
|
|
124
|
-
process.env.SHELL = originalShell
|
|
125
|
-
}
|
|
126
|
-
if (originalComspec !== undefined) {
|
|
127
|
-
process.env.COMSPEC = originalComspec
|
|
128
|
-
} else {
|
|
129
|
-
delete process.env.COMSPEC
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
})
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* EPUB output check
|
|
3
|
-
*
|
|
4
|
-
* Checks for EPUB output files using the same path resolution logic as the
|
|
5
|
-
* EPUB generation command.
|
|
6
|
-
*
|
|
7
|
-
* @module lib/doctor/checks/outputs/epub-output
|
|
8
|
-
*/
|
|
9
|
-
import fs from 'node:fs'
|
|
10
|
-
import path from 'node:path'
|
|
11
|
-
import createDebug from '#debug'
|
|
12
|
-
import { getEpubOutputPaths } from '#lib/project/output-paths.js'
|
|
13
|
-
import config from '#lib/conf/config.js'
|
|
14
|
-
import { getStatus } from '#lib/conf/build-status.js'
|
|
15
|
-
import { DOCS_BASE_URL, resolveStaleThreshold } from '#lib/doctor/constants.js'
|
|
16
|
-
import { formatDuration } from '#lib/doctor/formatDuration.js'
|
|
17
|
-
|
|
18
|
-
const debug = createDebug('lib:doctor:epub-output')
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Check if EPUB output exists and is up to date with _site
|
|
22
|
-
*
|
|
23
|
-
* EPUB output is a final .epub file ({engine}.epub, e.g. epubjs.epub,
|
|
24
|
-
* pandoc.epub). Uses the same path resolution as `commands/epub.js`.
|
|
25
|
-
*
|
|
26
|
-
* @returns {import('../../index.js').CheckResult}
|
|
27
|
-
*/
|
|
28
|
-
export function checkEpubOutput() {
|
|
29
|
-
const candidatePaths = getEpubOutputPaths()
|
|
30
|
-
debug('candidate EPUB paths: %o', candidatePaths)
|
|
31
|
-
|
|
32
|
-
// Find which .epub files actually exist
|
|
33
|
-
const existingEpubs = candidatePaths.filter((p) => fs.existsSync(p))
|
|
34
|
-
|
|
35
|
-
// No EPUB output
|
|
36
|
-
if (existingEpubs.length === 0) {
|
|
37
|
-
debug('No EPUB files found, checking stored epub status')
|
|
38
|
-
|
|
39
|
-
const status = getStatus(process.cwd(), 'epub')
|
|
40
|
-
if (status?.status === 'failed') {
|
|
41
|
-
debug('Last epub generation failed (stored status)')
|
|
42
|
-
return {
|
|
43
|
-
ok: false,
|
|
44
|
-
message: 'Last EPUB generation failed',
|
|
45
|
-
remediation: `The last "quire epub" run failed. Check the output for errors and try again.
|
|
46
|
-
• Run "quire epub --debug" for detailed error output`,
|
|
47
|
-
docsUrl: `${DOCS_BASE_URL}/quire-commands/#epub`,
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return {
|
|
52
|
-
ok: true,
|
|
53
|
-
level: 'na',
|
|
54
|
-
message: 'No EPUB output found',
|
|
55
|
-
remediation: `Run "quire epub" to generate an EPUB.
|
|
56
|
-
• If you already ran "quire epub" and it failed, check the output for errors`,
|
|
57
|
-
docsUrl: `${DOCS_BASE_URL}/quire-commands/#epub`,
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Use basenames for display
|
|
62
|
-
const existingNames = existingEpubs.map((p) => path.basename(p))
|
|
63
|
-
debug('found EPUB files: %o', existingNames)
|
|
64
|
-
|
|
65
|
-
// Check if _site exists for staleness comparison
|
|
66
|
-
if (!fs.existsSync('_site')) {
|
|
67
|
-
debug('_site directory not found')
|
|
68
|
-
return {
|
|
69
|
-
ok: true,
|
|
70
|
-
message: `${existingNames.join(', ')} exists (no _site to compare)`,
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Get _site last modified time
|
|
75
|
-
const { mtimeMs: siteLastModified } = fs.statSync('_site')
|
|
76
|
-
debug('_site lastModified: %d', siteLastModified)
|
|
77
|
-
|
|
78
|
-
// Check each .epub file for staleness beyond the configured threshold
|
|
79
|
-
const thresholdMs = resolveStaleThreshold(config.get('staleThreshold'))
|
|
80
|
-
const staleFiles = []
|
|
81
|
-
let oldestEpubLastModified = Infinity
|
|
82
|
-
|
|
83
|
-
for (const epubFile of existingEpubs) {
|
|
84
|
-
const { mtimeMs: epubLastModified } = fs.statSync(epubFile)
|
|
85
|
-
debug('%s lastModified: %d', path.basename(epubFile), epubLastModified)
|
|
86
|
-
|
|
87
|
-
const staleDelta = siteLastModified - epubLastModified
|
|
88
|
-
if (staleDelta > thresholdMs) {
|
|
89
|
-
staleFiles.push(epubFile)
|
|
90
|
-
if (epubLastModified < oldestEpubLastModified) {
|
|
91
|
-
oldestEpubLastModified = epubLastModified
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (staleFiles.length > 0) {
|
|
97
|
-
const staleDuration = formatDuration(siteLastModified - oldestEpubLastModified)
|
|
98
|
-
const staleNames = staleFiles.map((p) => path.basename(p))
|
|
99
|
-
const fileList = staleNames.join(', ')
|
|
100
|
-
return {
|
|
101
|
-
ok: false,
|
|
102
|
-
level: 'warn',
|
|
103
|
-
message: `${fileList} is ${staleDuration} older than _site`,
|
|
104
|
-
remediation: `Your EPUB may not reflect recent build changes.
|
|
105
|
-
• Run "quire epub" to regenerate the EPUB
|
|
106
|
-
• Or delete the old EPUB files and run "quire epub"`,
|
|
107
|
-
docsUrl: `${DOCS_BASE_URL}/quire-commands/#epub`,
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// All EPUBs are up to date
|
|
112
|
-
const fileList = existingNames.join(', ')
|
|
113
|
-
return {
|
|
114
|
-
ok: true,
|
|
115
|
-
message: `${fileList} up to date`,
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export default checkEpubOutput
|
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
import test from 'ava'
|
|
2
|
-
import sinon from 'sinon'
|
|
3
|
-
import esmock from 'esmock'
|
|
4
|
-
|
|
5
|
-
const TWO_MINUTES = 120000
|
|
6
|
-
const TEN_MINUTES = 600000
|
|
7
|
-
const ONE_HOUR = 3600000
|
|
8
|
-
const TWO_HOURS = 7200000
|
|
9
|
-
|
|
10
|
-
const configMock = { default: { get: () => 'HOURLY' } }
|
|
11
|
-
const buildStatusMock = { getStatus: () => undefined }
|
|
12
|
-
|
|
13
|
-
test.beforeEach((t) => {
|
|
14
|
-
t.context.sandbox = sinon.createSandbox()
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
test.afterEach.always((t) => {
|
|
18
|
-
t.context.sandbox.restore()
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
test('checkEpubOutput returns N/A when no EPUB files exist', async (t) => {
|
|
22
|
-
const { sandbox } = t.context
|
|
23
|
-
|
|
24
|
-
const { checkEpubOutput } = await esmock('./epub-output.js', {
|
|
25
|
-
'node:fs': {
|
|
26
|
-
existsSync: sandbox.stub().returns(false),
|
|
27
|
-
},
|
|
28
|
-
'#lib/project/output-paths.js': {
|
|
29
|
-
getEpubOutputPaths: () => ['epubjs.epub', 'pandoc.epub'],
|
|
30
|
-
},
|
|
31
|
-
'#lib/conf/config.js': configMock,
|
|
32
|
-
'#lib/conf/build-status.js': buildStatusMock,
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
const result = checkEpubOutput()
|
|
36
|
-
|
|
37
|
-
t.true(result.ok)
|
|
38
|
-
t.is(result.level, 'na', 'should return N/A level when no EPUB output')
|
|
39
|
-
t.regex(result.message, /No EPUB output found/)
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
test('checkEpubOutput includes remediation when no output found', async (t) => {
|
|
43
|
-
const { sandbox } = t.context
|
|
44
|
-
|
|
45
|
-
const { checkEpubOutput } = await esmock('./epub-output.js', {
|
|
46
|
-
'node:fs': {
|
|
47
|
-
existsSync: sandbox.stub().returns(false),
|
|
48
|
-
},
|
|
49
|
-
'#lib/project/output-paths.js': {
|
|
50
|
-
getEpubOutputPaths: () => ['epubjs.epub', 'pandoc.epub'],
|
|
51
|
-
},
|
|
52
|
-
'#lib/conf/config.js': configMock,
|
|
53
|
-
'#lib/conf/build-status.js': buildStatusMock,
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
const result = checkEpubOutput()
|
|
57
|
-
|
|
58
|
-
t.truthy(result.remediation)
|
|
59
|
-
t.regex(result.remediation, /quire epub/)
|
|
60
|
-
t.regex(result.remediation, /failed/)
|
|
61
|
-
t.truthy(result.docsUrl)
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
test('checkEpubOutput returns failure when last EPUB generation failed and no output exists', async (t) => {
|
|
65
|
-
const { sandbox } = t.context
|
|
66
|
-
|
|
67
|
-
const { checkEpubOutput } = await esmock('./epub-output.js', {
|
|
68
|
-
'node:fs': {
|
|
69
|
-
existsSync: sandbox.stub().returns(false),
|
|
70
|
-
},
|
|
71
|
-
'#lib/project/output-paths.js': {
|
|
72
|
-
getEpubOutputPaths: () => ['epubjs.epub', 'pandoc.epub'],
|
|
73
|
-
},
|
|
74
|
-
'#lib/conf/config.js': configMock,
|
|
75
|
-
'#lib/conf/build-status.js': {
|
|
76
|
-
getStatus: () => ({ status: 'failed', timestamp: Date.now() }),
|
|
77
|
-
},
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
const result = checkEpubOutput()
|
|
81
|
-
|
|
82
|
-
t.false(result.ok)
|
|
83
|
-
t.is(result.level, undefined)
|
|
84
|
-
t.regex(result.message, /Last EPUB generation failed/)
|
|
85
|
-
t.truthy(result.remediation)
|
|
86
|
-
t.regex(result.remediation, /quire epub --debug/)
|
|
87
|
-
t.truthy(result.docsUrl)
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
test('checkEpubOutput returns ok when .epub exists but no _site', async (t) => {
|
|
91
|
-
const { sandbox } = t.context
|
|
92
|
-
|
|
93
|
-
const existsSync = sandbox.stub()
|
|
94
|
-
existsSync.withArgs('epubjs.epub').returns(true)
|
|
95
|
-
existsSync.withArgs('pandoc.epub').returns(false)
|
|
96
|
-
existsSync.withArgs('_site').returns(false)
|
|
97
|
-
|
|
98
|
-
const { checkEpubOutput } = await esmock('./epub-output.js', {
|
|
99
|
-
'node:fs': {
|
|
100
|
-
existsSync,
|
|
101
|
-
},
|
|
102
|
-
'#lib/project/output-paths.js': {
|
|
103
|
-
getEpubOutputPaths: () => ['epubjs.epub', 'pandoc.epub'],
|
|
104
|
-
},
|
|
105
|
-
'#lib/conf/config.js': configMock,
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
const result = checkEpubOutput()
|
|
109
|
-
|
|
110
|
-
t.true(result.ok)
|
|
111
|
-
t.regex(result.message, /epubjs\.epub exists/)
|
|
112
|
-
t.regex(result.message, /no _site to compare/)
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
test('checkEpubOutput returns ok when .epub is up to date', async (t) => {
|
|
116
|
-
const { sandbox } = t.context
|
|
117
|
-
|
|
118
|
-
const now = Date.now()
|
|
119
|
-
const epubTime = now // EPUB is current
|
|
120
|
-
const siteTime = now - TEN_MINUTES // _site is older
|
|
121
|
-
|
|
122
|
-
const existsSync = sandbox.stub()
|
|
123
|
-
existsSync.withArgs('epubjs.epub').returns(true)
|
|
124
|
-
existsSync.withArgs('pandoc.epub').returns(false)
|
|
125
|
-
existsSync.withArgs('_site').returns(true)
|
|
126
|
-
|
|
127
|
-
const statSync = sandbox.stub()
|
|
128
|
-
statSync.withArgs('_site').returns({ mtimeMs: siteTime })
|
|
129
|
-
statSync.withArgs('epubjs.epub').returns({ mtimeMs: epubTime })
|
|
130
|
-
|
|
131
|
-
const { checkEpubOutput } = await esmock('./epub-output.js', {
|
|
132
|
-
'node:fs': {
|
|
133
|
-
existsSync,
|
|
134
|
-
statSync,
|
|
135
|
-
},
|
|
136
|
-
'#lib/project/output-paths.js': {
|
|
137
|
-
getEpubOutputPaths: () => ['epubjs.epub', 'pandoc.epub'],
|
|
138
|
-
},
|
|
139
|
-
'#lib/conf/config.js': configMock,
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
const result = checkEpubOutput()
|
|
143
|
-
|
|
144
|
-
t.true(result.ok)
|
|
145
|
-
t.regex(result.message, /epubjs\.epub up to date/)
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
test('checkEpubOutput returns warning when .epub is stale beyond threshold', async (t) => {
|
|
149
|
-
const { sandbox } = t.context
|
|
150
|
-
|
|
151
|
-
const epubTime = Date.now() - TWO_HOURS // 2 hours ago
|
|
152
|
-
const siteTime = Date.now() // now
|
|
153
|
-
|
|
154
|
-
const existsSync = sandbox.stub()
|
|
155
|
-
existsSync.withArgs('epubjs.epub').returns(true)
|
|
156
|
-
existsSync.withArgs('pandoc.epub').returns(false)
|
|
157
|
-
existsSync.withArgs('_site').returns(true)
|
|
158
|
-
|
|
159
|
-
const statSync = sandbox.stub()
|
|
160
|
-
statSync.withArgs('_site').returns({ mtimeMs: siteTime })
|
|
161
|
-
statSync.withArgs('epubjs.epub').returns({ mtimeMs: epubTime })
|
|
162
|
-
|
|
163
|
-
const { checkEpubOutput } = await esmock('./epub-output.js', {
|
|
164
|
-
'node:fs': {
|
|
165
|
-
existsSync,
|
|
166
|
-
statSync,
|
|
167
|
-
},
|
|
168
|
-
'#lib/project/output-paths.js': {
|
|
169
|
-
getEpubOutputPaths: () => ['epubjs.epub', 'pandoc.epub'],
|
|
170
|
-
},
|
|
171
|
-
'#lib/conf/config.js': configMock,
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
const result = checkEpubOutput()
|
|
175
|
-
|
|
176
|
-
t.false(result.ok)
|
|
177
|
-
t.is(result.level, 'warn')
|
|
178
|
-
t.regex(result.message, /epubjs\.epub/)
|
|
179
|
-
t.regex(result.message, /older than _site/)
|
|
180
|
-
t.truthy(result.remediation)
|
|
181
|
-
t.truthy(result.docsUrl)
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
test('checkEpubOutput returns ok when .epub is stale but within threshold', async (t) => {
|
|
185
|
-
const { sandbox } = t.context
|
|
186
|
-
|
|
187
|
-
const epubTime = Date.now() - TWO_MINUTES // 2 minutes ago
|
|
188
|
-
const siteTime = Date.now()
|
|
189
|
-
|
|
190
|
-
const existsSync = sandbox.stub()
|
|
191
|
-
existsSync.withArgs('epubjs.epub').returns(true)
|
|
192
|
-
existsSync.withArgs('pandoc.epub').returns(false)
|
|
193
|
-
existsSync.withArgs('_site').returns(true)
|
|
194
|
-
|
|
195
|
-
const statSync = sandbox.stub()
|
|
196
|
-
statSync.withArgs('_site').returns({ mtimeMs: siteTime })
|
|
197
|
-
statSync.withArgs('epubjs.epub').returns({ mtimeMs: epubTime })
|
|
198
|
-
|
|
199
|
-
const { checkEpubOutput } = await esmock('./epub-output.js', {
|
|
200
|
-
'node:fs': {
|
|
201
|
-
existsSync,
|
|
202
|
-
statSync,
|
|
203
|
-
},
|
|
204
|
-
'#lib/project/output-paths.js': {
|
|
205
|
-
getEpubOutputPaths: () => ['epubjs.epub', 'pandoc.epub'],
|
|
206
|
-
},
|
|
207
|
-
'#lib/conf/config.js': configMock,
|
|
208
|
-
})
|
|
209
|
-
|
|
210
|
-
const result = checkEpubOutput()
|
|
211
|
-
|
|
212
|
-
t.true(result.ok)
|
|
213
|
-
t.regex(result.message, /epubjs\.epub up to date/)
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
test('checkEpubOutput includes remediation with epub command', async (t) => {
|
|
217
|
-
const { sandbox } = t.context
|
|
218
|
-
|
|
219
|
-
const epubTime = Date.now() - TWO_HOURS
|
|
220
|
-
const siteTime = Date.now()
|
|
221
|
-
|
|
222
|
-
const existsSync = sandbox.stub()
|
|
223
|
-
existsSync.withArgs('epubjs.epub').returns(true)
|
|
224
|
-
existsSync.withArgs('pandoc.epub').returns(false)
|
|
225
|
-
existsSync.withArgs('_site').returns(true)
|
|
226
|
-
|
|
227
|
-
const statSync = sandbox.stub()
|
|
228
|
-
statSync.withArgs('_site').returns({ mtimeMs: siteTime })
|
|
229
|
-
statSync.withArgs('epubjs.epub').returns({ mtimeMs: epubTime })
|
|
230
|
-
|
|
231
|
-
const { checkEpubOutput } = await esmock('./epub-output.js', {
|
|
232
|
-
'node:fs': {
|
|
233
|
-
existsSync,
|
|
234
|
-
statSync,
|
|
235
|
-
},
|
|
236
|
-
'#lib/project/output-paths.js': {
|
|
237
|
-
getEpubOutputPaths: () => ['epubjs.epub', 'pandoc.epub'],
|
|
238
|
-
},
|
|
239
|
-
'#lib/conf/config.js': configMock,
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
const result = checkEpubOutput()
|
|
243
|
-
|
|
244
|
-
t.false(result.ok)
|
|
245
|
-
t.regex(result.remediation, /quire epub/)
|
|
246
|
-
})
|
|
247
|
-
|
|
248
|
-
test('checkEpubOutput uses correct docsUrl', async (t) => {
|
|
249
|
-
const { sandbox } = t.context
|
|
250
|
-
|
|
251
|
-
const epubTime = Date.now() - TWO_HOURS
|
|
252
|
-
const siteTime = Date.now()
|
|
253
|
-
|
|
254
|
-
const existsSync = sandbox.stub()
|
|
255
|
-
existsSync.withArgs('epubjs.epub').returns(true)
|
|
256
|
-
existsSync.withArgs('pandoc.epub').returns(false)
|
|
257
|
-
existsSync.withArgs('_site').returns(true)
|
|
258
|
-
|
|
259
|
-
const statSync = sandbox.stub()
|
|
260
|
-
statSync.withArgs('_site').returns({ mtimeMs: siteTime })
|
|
261
|
-
statSync.withArgs('epubjs.epub').returns({ mtimeMs: epubTime })
|
|
262
|
-
|
|
263
|
-
const { checkEpubOutput } = await esmock('./epub-output.js', {
|
|
264
|
-
'node:fs': {
|
|
265
|
-
existsSync,
|
|
266
|
-
statSync,
|
|
267
|
-
},
|
|
268
|
-
'#lib/project/output-paths.js': {
|
|
269
|
-
getEpubOutputPaths: () => ['epubjs.epub', 'pandoc.epub'],
|
|
270
|
-
},
|
|
271
|
-
'#lib/conf/config.js': configMock,
|
|
272
|
-
})
|
|
273
|
-
|
|
274
|
-
const result = checkEpubOutput()
|
|
275
|
-
|
|
276
|
-
t.regex(result.docsUrl, /epub/)
|
|
277
|
-
})
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Outputs checks
|
|
3
|
-
*
|
|
4
|
-
* Checks for build outputs and artifacts.
|
|
5
|
-
*
|
|
6
|
-
* @module lib/doctor/checks/outputs
|
|
7
|
-
*/
|
|
8
|
-
export { checkStaleBuild } from './stale-build.js'
|
|
9
|
-
export { checkPdfOutput } from './pdf-output.js'
|
|
10
|
-
export { checkEpubOutput } from './epub-output.js'
|