@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
package/src/lib/pdf/split.js
CHANGED
|
@@ -1,89 +1,61 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
+
|
|
2
3
|
import { PDFDocument } from 'pdf-lib'
|
|
3
4
|
import { paths } from '#lib/11ty/index.js'
|
|
4
|
-
|
|
5
|
-
import createDebug from '#debug'
|
|
6
|
-
|
|
7
|
-
const debug = createDebug('lib:pdf:split')
|
|
8
|
-
|
|
5
|
+
|
|
9
6
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* @function splitPdf(file,pageMap) -- sections out individual PDFs from `file` according to `pageMap`
|
|
8
|
+
*
|
|
12
9
|
* @param {ArrayBuffer} file - PDF file to split
|
|
13
|
-
* @param {
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* @throws {PdfGenerationError} When PDF loading or manipulation fails
|
|
10
|
+
* @param {Object} pageMap - page map to split PDf by
|
|
11
|
+
*
|
|
12
|
+
* Creates individual PDFs from by copying `file` (so boxes are already set) and stripping pages out of the range (in reverse order to retain the index sequence)
|
|
13
|
+
* Returns a map of file paths to PDF binary data for serialization
|
|
18
14
|
*/
|
|
19
|
-
export async function splitPdf(file, coversFile, pageMap, pdfConfig) {
|
|
20
15
|
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
export async function splitPdf(file,coversFile,pageMap,pdfConfig) {
|
|
17
|
+
|
|
18
|
+
if (!pdfConfig) {
|
|
23
19
|
return {}
|
|
24
20
|
}
|
|
25
21
|
|
|
26
22
|
const { filename, outputDir } = pdfConfig
|
|
27
23
|
|
|
28
|
-
|
|
29
|
-
let pdfDoc
|
|
30
|
-
try {
|
|
31
|
-
pdfDoc = await PDFDocument.load(file)
|
|
32
|
-
} catch (error) {
|
|
33
|
-
throw new PdfGenerationError('pdf-lib', 'load main PDF', error.message)
|
|
34
|
-
}
|
|
35
|
-
debug('main PDF loaded: %d pages', pdfDoc.getPageCount())
|
|
24
|
+
const pdfDoc = await PDFDocument.load(file)
|
|
36
25
|
|
|
37
|
-
|
|
38
|
-
if (coversFile !== undefined) {
|
|
39
|
-
debug('loading covers PDF')
|
|
40
|
-
try {
|
|
41
|
-
coversDoc = await PDFDocument.load(coversFile)
|
|
42
|
-
} catch (error) {
|
|
43
|
-
throw new PdfGenerationError('pdf-lib', 'load covers PDF', error.message)
|
|
44
|
-
}
|
|
45
|
-
debug('covers PDF loaded: %d pages', coversDoc.getPageCount())
|
|
46
|
-
}
|
|
26
|
+
const coversDoc = (coversFile !== undefined) ? await PDFDocument.load(coversFile) : undefined
|
|
47
27
|
|
|
48
28
|
let resultFiles = {}
|
|
49
|
-
const pageEntries = Object.entries(pageMap)
|
|
50
|
-
debug('splitting into %d sections', pageEntries.length)
|
|
51
29
|
|
|
52
|
-
for (const [pageId, pageConfig] of
|
|
30
|
+
for ( const [pageId, pageConfig] of Object.entries(pageMap) ) {
|
|
53
31
|
const { endPage, startPage, coverPage } = pageConfig
|
|
54
32
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const sectionDoc = await pdfDoc.copy()
|
|
33
|
+
// TODO: Set the PDF's sectional doc metadata
|
|
34
|
+
|
|
35
|
+
const sectionDoc = await pdfDoc.copy()
|
|
59
36
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
37
|
+
for (let p=pdfDoc.getPageCount() - 1; p > endPage; --p) {
|
|
38
|
+
sectionDoc.removePage(p)
|
|
39
|
+
}
|
|
40
|
+
for (let q=startPage - 1; q >= 0; --q) {
|
|
41
|
+
sectionDoc.removePage(q)
|
|
42
|
+
}
|
|
66
43
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
44
|
+
if (coversDoc && coverPage !== undefined && coverPage >= 0) {
|
|
45
|
+
// NB: `copyPages()` sets page sizing + other metadata on the way into the target PDF
|
|
46
|
+
const cover = await sectionDoc.copyPages(coversDoc,[coverPage])
|
|
47
|
+
sectionDoc.insertPage(0,cover[0])
|
|
48
|
+
}
|
|
72
49
|
|
|
73
|
-
|
|
50
|
+
const section = await sectionDoc.save()
|
|
74
51
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
52
|
+
const sectionId = pageId.replace(/^page-/g,'')
|
|
53
|
+
const sectionFn = `${filename}-${sectionId}.pdf`
|
|
54
|
+
const sectionFp = path.join( paths.output, outputDir, sectionFn )
|
|
78
55
|
|
|
79
|
-
|
|
80
|
-
debug('extracted section %s (pages %d-%d)', sectionId, startPage, endPage)
|
|
81
|
-
} catch (error) {
|
|
82
|
-
throw new PdfGenerationError('pdf-lib', `extract section '${pageId}'`, error.message)
|
|
83
|
-
}
|
|
56
|
+
resultFiles[sectionFp] = section
|
|
84
57
|
}
|
|
85
58
|
|
|
86
|
-
debug('split complete: %d files', Object.keys(resultFiles).length)
|
|
87
59
|
return resultFiles
|
|
88
60
|
}
|
|
89
61
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
## CLI Quire Module
|
|
2
|
+
|
|
3
|
+
The primary concern of the Quire CLI `quire` module is to decouple the `11ty` package from the publication content templates and manage the version of the [Quire/11ty package](packages/11ty) that is used to build a Quire project.
|
|
4
|
+
|
|
5
|
+
The [Quire/11ty package](packages/11ty) contains the Eleventy [configuration](packages/11ty/.eleventy.js), [includes](packages/11ty/_includes), [layouts](packages/11ty/_layouts), and [plugins](packages/11ty/_plugins) for [universal template shortcodes](packages/11ty/_plugins/shortcodes) and [components](packages/11ty/_includes/components) to build Quire publications.
|
|
6
|
+
|
|
7
|
+
When the Quire CLI is installed the latest version of the [11ty package](packages/11ty) is installed in in the `cli/quire/versions/` directory.
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
cli/
|
|
11
|
+
quire/
|
|
12
|
+
versions/
|
|
13
|
+
1.0.0/
|
|
14
|
+
_includes/
|
|
15
|
+
_layouts/
|
|
16
|
+
_plugins/
|
|
17
|
+
.eleventy.js
|
|
18
|
+
package.json
|
|
19
|
+
```
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import { IS_WINDOWS } from '#helpers/os-utils.js'
|
|
2
|
+
import { chdir, cwd } from 'node:process'
|
|
3
|
+
import { execa, execaCommand } from 'execa'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
import { isEmpty } from '#helpers/is-empty.js'
|
|
6
|
+
import config from '#lib/conf/config.js'
|
|
7
|
+
import fetch from 'node-fetch'
|
|
8
|
+
import fs from 'fs-extra'
|
|
9
|
+
import git from '#lib/git/index.js'
|
|
10
|
+
import packageConfig from '#src/packageConfig.js'
|
|
11
|
+
import path from 'node:path'
|
|
12
|
+
import semver from 'semver'
|
|
13
|
+
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
15
|
+
const __dirname = path.dirname(__filename)
|
|
16
|
+
|
|
17
|
+
// Version install path is relative to process working directory
|
|
18
|
+
const INSTALL_PATH = path.join('src', 'lib', 'quire', 'versions')
|
|
19
|
+
const PACKAGE_NAME = '@thegetty/quire-11ty'
|
|
20
|
+
|
|
21
|
+
const QUIRE_VERSION = config.get('quireVersion')
|
|
22
|
+
const VERSION_FILE = config.get('versionFile')
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Return an absolute path to an installed quire-11ty version
|
|
26
|
+
*
|
|
27
|
+
* @return {String} path to installed quire-11ty version
|
|
28
|
+
*/
|
|
29
|
+
function getPath(version=QUIRE_VERSION) {
|
|
30
|
+
const absolutePath = path.relative('/', path.join(INSTALL_PATH, version))
|
|
31
|
+
if (!fs.existsSync(absolutePath)) {
|
|
32
|
+
console.error(`[CLI:quire] quire-11ty@${version} is not installed`)
|
|
33
|
+
return null
|
|
34
|
+
}
|
|
35
|
+
console.debug(`[CLI:quire] %s`, absolutePath)
|
|
36
|
+
return absolutePath
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Read the required quire-11ty version for the quire version file
|
|
41
|
+
*
|
|
42
|
+
* @param {String} projectPath Absolute system path to the project root
|
|
43
|
+
*
|
|
44
|
+
* @return {String} version Quire-11ty semantic version
|
|
45
|
+
*/
|
|
46
|
+
function getVersion(projectPath) {
|
|
47
|
+
projectPath = projectPath || path.resolve(cwd())
|
|
48
|
+
const version = fs.readFileSync(path.join(projectPath, VERSION_FILE), { encoding:'utf8' })
|
|
49
|
+
const projectName = path.basename(projectPath)
|
|
50
|
+
console.debug(`${projectName} set to use quire-11ty@${version}`)
|
|
51
|
+
return version
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Read required quire-11ty and starter versions from starter peerDependencies
|
|
56
|
+
*
|
|
57
|
+
* @param {String} projectPath Absolute system path to the project root
|
|
58
|
+
*
|
|
59
|
+
* @return {Object}
|
|
60
|
+
* @property {String} quire11tyVersion Latest compatible Quire-11ty semantic version
|
|
61
|
+
* @property {String} starterVersion Starter project version defined in the starter package.json
|
|
62
|
+
*/
|
|
63
|
+
async function getVersionsFromStarter(projectPath) {
|
|
64
|
+
const projectPackageConfig = fs.readFileSync(path.join(projectPath, 'package.json'), { encoding:'utf8' })
|
|
65
|
+
const { peerDependencies, version: starterVersion } = JSON.parse(projectPackageConfig)
|
|
66
|
+
const quire11tyVersion = peerDependencies[PACKAGE_NAME]
|
|
67
|
+
return { quire11tyVersion, starterVersion }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Clone or copy a Quire starter project
|
|
72
|
+
*
|
|
73
|
+
* @param {String} starter A repository URL or an absolute path to local starter
|
|
74
|
+
* @TODO resolve both absolute and relative paths to local starter repositories
|
|
75
|
+
* @param {String} projectPath Absolute system path to the project root
|
|
76
|
+
*
|
|
77
|
+
* @return {String} quireVersion A string indicating the current version
|
|
78
|
+
* of quire being used with a new project
|
|
79
|
+
*/
|
|
80
|
+
async function initStarter (starter, projectPath, options) {
|
|
81
|
+
projectPath = projectPath || cwd()
|
|
82
|
+
|
|
83
|
+
// ensure that the target path exists
|
|
84
|
+
fs.ensureDirSync(projectPath)
|
|
85
|
+
|
|
86
|
+
// if the target directory exists it must be empty
|
|
87
|
+
if (!isEmpty(projectPath)) {
|
|
88
|
+
const location = projectPath === '.' ? 'the current directory' : projectPath
|
|
89
|
+
console.error(`[CLI] cannot create a starter project in ${location} because it is not empty`)
|
|
90
|
+
// @TODO cleanup directories from failed new command
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
console.debug('[CLI:quire] init-starter',
|
|
95
|
+
`\n project: ${path.join(__dirname, projectPath)}`,
|
|
96
|
+
`\n starter: ${starter}`
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Clone starter project repository
|
|
101
|
+
* @todo pipe `git clone` status to stdout for better UX
|
|
102
|
+
*/
|
|
103
|
+
await git
|
|
104
|
+
.cwd(projectPath)
|
|
105
|
+
.clone(starter, '.')
|
|
106
|
+
.catch((error) => console.error('[CLI:error] ', error))
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Determine the quire-11ty version to use in the new project,
|
|
110
|
+
* from the quireVersion option or as required by the starter project.
|
|
111
|
+
*
|
|
112
|
+
* Uses 'latest' to get the latest semantic version compatible with version ranges
|
|
113
|
+
*/
|
|
114
|
+
const { quire11tyVersion, starterVersion } = await getVersionsFromStarter(projectPath)
|
|
115
|
+
const quireVersion = await latest(options.quireVersion || quire11tyVersion)
|
|
116
|
+
setVersion(projectPath, quireVersion)
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Write quire-11ty, quire-cli, starter versions to the version file
|
|
120
|
+
*/
|
|
121
|
+
const versionInfo = {
|
|
122
|
+
cli: packageConfig.version,
|
|
123
|
+
starter: `${starter}@${starterVersion}`,
|
|
124
|
+
}
|
|
125
|
+
fs.writeFileSync(path.join(projectPath, VERSION_FILE), JSON.stringify(versionInfo))
|
|
126
|
+
|
|
127
|
+
// Re-initialize project directory as a new git repository
|
|
128
|
+
await fs.remove(path.join(projectPath, '.git'))
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Remove the starter repository package config file
|
|
132
|
+
* and create a new package config for the project
|
|
133
|
+
* (this is necessary for Eleventy to resolve project paths)
|
|
134
|
+
* @todo allow interactive init using a custom questionnaire
|
|
135
|
+
* @see https://docs.npmjs.com/creating-a-package-json-file#customizing-the-packagejson-questionnaire
|
|
136
|
+
*/
|
|
137
|
+
await fs.remove(path.join(projectPath, 'package.json'))
|
|
138
|
+
await execaCommand('npm init --yes', { cwd: projectPath })
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Create an initial commit of files in new repository
|
|
142
|
+
* @todo use a localized string for the commit message
|
|
143
|
+
*/
|
|
144
|
+
const projectFiles = fs.readdirSync(projectPath)
|
|
145
|
+
await git.init().add(projectFiles).commit('Initial Commit')
|
|
146
|
+
return quireVersion
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Install `quire-11ty` directly into a quire project
|
|
151
|
+
*
|
|
152
|
+
* @TODO refactor this to use the install method with pre and post-install hooks
|
|
153
|
+
* or steps to prepare the working directory and cleanup on error and completion
|
|
154
|
+
*
|
|
155
|
+
* @param {String} projectPath Absolute system path to the project root
|
|
156
|
+
* @param {Object} options options passed from `quire new` command
|
|
157
|
+
* @return {Promise}
|
|
158
|
+
*/
|
|
159
|
+
async function installInProject(projectPath, quireVersion, options = {}) {
|
|
160
|
+
const { quirePath } = options
|
|
161
|
+
const quire11tyPackage = `${PACKAGE_NAME}@${quireVersion}`
|
|
162
|
+
|
|
163
|
+
console.debug(`[CLI:quire] installing ${quire11tyPackage} into ${projectPath}`)
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Delete the starter project package configuration so that it can be replaced
|
|
167
|
+
* with the `@thegetty/quire-11ty` configuration
|
|
168
|
+
* @TODO If a user runs quire eject at a later date we may want to merge their
|
|
169
|
+
* package.json with the `quire-11ty` dev dependencies, scripts, etc
|
|
170
|
+
*/
|
|
171
|
+
await git
|
|
172
|
+
.cwd(projectPath)
|
|
173
|
+
.rm(['package.json'])
|
|
174
|
+
.catch((error) => console.error('[CLI:error] ', error))
|
|
175
|
+
|
|
176
|
+
const temp11tyDirectory = '.temp'
|
|
177
|
+
const tempDir = path.join(projectPath,temp11tyDirectory)
|
|
178
|
+
fs.mkdirSync(tempDir)
|
|
179
|
+
|
|
180
|
+
// Copy if passed a path and it exists, otherwise attempt to download the tarball for this pathspec
|
|
181
|
+
if (fs.existsSync(quirePath)) {
|
|
182
|
+
fs.cpSync(quirePath, tempDir, {recursive: true})
|
|
183
|
+
} else {
|
|
184
|
+
await execaCommand(`npm pack ${ options.debug ? '--debug' : '--quiet' } --pack-destination ${tempDir} ${quire11tyPackage}`)
|
|
185
|
+
|
|
186
|
+
// Extract only the package dir from the tar bar and strip it from the extracted path
|
|
187
|
+
const tarballPath = path.join(tempDir, `thegetty-quire-11ty-${quireVersion}.tgz`)
|
|
188
|
+
await execaCommand(`tar -xzf ${tarballPath} -C ${tempDir} --strip-components=1 package/`)
|
|
189
|
+
|
|
190
|
+
fs.rmSync(tarballPath)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Copy `.temp` to projectPath
|
|
194
|
+
fs.cpSync(tempDir, projectPath, {recursive: true})
|
|
195
|
+
|
|
196
|
+
console.debug('[CLI:quire] installing dev dependencies into quire project')
|
|
197
|
+
/**
|
|
198
|
+
* Manually install necessary dev dependencies to run 11ty;
|
|
199
|
+
* these must be `devDependencies` so that they are not bundled into
|
|
200
|
+
* the final `_site` package when running `quire build`
|
|
201
|
+
*/
|
|
202
|
+
await execaCommand('npm cache clean --force', { cwd: projectPath })
|
|
203
|
+
try {
|
|
204
|
+
await execaCommand('npm install --save-dev', { cwd: projectPath })
|
|
205
|
+
} catch(error) {
|
|
206
|
+
console.warn(`[CLI:error]`, error)
|
|
207
|
+
fs.rmSync(projectPath, {recursive: true})
|
|
208
|
+
return
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const eleventyFilesToCommit = fs
|
|
212
|
+
.readdirSync(tempDir)
|
|
213
|
+
.filter((filePath) => filePath !== 'node_modules')
|
|
214
|
+
|
|
215
|
+
eleventyFilesToCommit.push('package-lock.json')
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Create an additional commit of new `@thegetty/quire-11ty` files in repository
|
|
219
|
+
* @todo use a localized string for the commit message
|
|
220
|
+
*/
|
|
221
|
+
await git.add(eleventyFilesToCommit).commit('Adds `@thegetty/quire-11ty` files')
|
|
222
|
+
|
|
223
|
+
// remove temporary 11ty install directory
|
|
224
|
+
fs.rmSync(path.join(projectPath, temp11tyDirectory), {recursive: true})
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Retrieve latest published version of the `quire-11ty` package
|
|
229
|
+
* or the latest compatible version with the provided semantic version string
|
|
230
|
+
*
|
|
231
|
+
* @param {String} version A semantic version string, i.e `^1.0.0-pre-release.0`
|
|
232
|
+
*
|
|
233
|
+
* @return {String} `quire-11ty@latest` semantic version string
|
|
234
|
+
*/
|
|
235
|
+
async function latest(version) {
|
|
236
|
+
let quireVersion;
|
|
237
|
+
if (!version || version === 'latest') {
|
|
238
|
+
const { stdout } =
|
|
239
|
+
await execa('npm', ['view', PACKAGE_NAME, 'version'])
|
|
240
|
+
quireVersion = stdout
|
|
241
|
+
} else {
|
|
242
|
+
const response = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}`)
|
|
243
|
+
const json = await response.json()
|
|
244
|
+
const versions = Object.keys(json.versions)
|
|
245
|
+
quireVersion = semver.maxSatisfying(versions, version)
|
|
246
|
+
}
|
|
247
|
+
if (!quireVersion) {
|
|
248
|
+
throw new Error(`[CLI:quire] Sorry, we couldn't find a version of quire-11ty compatible with the version "${version}". You can set the quire-11ty version in the starter project's package.json or specify a version when running \`quire new\` with the \`--quire-version\` flag. You can run \`npm view @thegetty/quire-11ty versions\` to view all versions.`)
|
|
249
|
+
}
|
|
250
|
+
return quireVersion
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* List installed versions of the `quire-11ty` package
|
|
255
|
+
*/
|
|
256
|
+
function list() {
|
|
257
|
+
return fs.readdirSync(INSTALL_PATH)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Removes the installed version of `quire-11ty`
|
|
262
|
+
*
|
|
263
|
+
* @param {String} `quire-11ty` semantic version
|
|
264
|
+
* @return {Promise}
|
|
265
|
+
*/
|
|
266
|
+
async function remove(version) {
|
|
267
|
+
if (!version) {
|
|
268
|
+
console.error('No version specified.')
|
|
269
|
+
}
|
|
270
|
+
const dir = `${INSTALL_PATH}/${version}`
|
|
271
|
+
fs.rmdir(dir, { recursive: true }, (error) => {
|
|
272
|
+
if (error) {
|
|
273
|
+
throw error
|
|
274
|
+
}
|
|
275
|
+
console.info(`deleted ${dir}`)
|
|
276
|
+
})
|
|
277
|
+
symlinkLatest()
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Sets the quire-11ty version for a project
|
|
282
|
+
*
|
|
283
|
+
* @param {String} version a version identifier or distribution tag
|
|
284
|
+
*/
|
|
285
|
+
function setVersion(projectPath, version) {
|
|
286
|
+
const projectName = path.basename(projectPath)
|
|
287
|
+
console.info(`${projectName} set to use quire-11ty@${version}`)
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Update symbolic link to the latest _installed_ version of `quire-11ty`
|
|
292
|
+
*
|
|
293
|
+
* @todo why does this not work using `fs-extra` `createSymlinkSync()`
|
|
294
|
+
*/
|
|
295
|
+
function symlinkLatest() {
|
|
296
|
+
const latestInstalledVersion = fs
|
|
297
|
+
.readdirSync(path.join(__dirname, 'versions'))
|
|
298
|
+
.filter((dirent) => semver.valid(semver.coerce(dirent)))
|
|
299
|
+
.sort(semver.rcompare)[0]
|
|
300
|
+
const target = path.join(__dirname, 'versions', latestInstalledVersion)
|
|
301
|
+
const source = path.join(__dirname, 'versions', 'latest')
|
|
302
|
+
const type = IS_WINDOWS ? 'junction' : 'dir'
|
|
303
|
+
|
|
304
|
+
console.debug('[CLI:quire] symlinking latest installed version')
|
|
305
|
+
|
|
306
|
+
try {
|
|
307
|
+
return fs.symlinkSync(target, source, type)
|
|
308
|
+
} catch (error) {
|
|
309
|
+
switch (error.code) {
|
|
310
|
+
case 'EEXIST':
|
|
311
|
+
case 'EISDIR':
|
|
312
|
+
// if the target file already exists proceed...
|
|
313
|
+
break
|
|
314
|
+
case 'ENOENT':
|
|
315
|
+
try {
|
|
316
|
+
fs.mkdirSync(path.dirname(source))
|
|
317
|
+
} catch (mkdirError) {
|
|
318
|
+
mkdirError.message = `Error trying to symlink ${target} to ${source}`
|
|
319
|
+
throw mkdirError
|
|
320
|
+
}
|
|
321
|
+
// do we need to symlink in this case?
|
|
322
|
+
// return fs.symlinkSync(target, source, type)
|
|
323
|
+
break
|
|
324
|
+
default:
|
|
325
|
+
console.error('[CLI:quire] unable to symlink latest installed version')
|
|
326
|
+
throw error
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
fs.unlinkSync(source)
|
|
331
|
+
return fs.symlinkSync(target, source, type)
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Get an array of published `quire-11ty` package versions
|
|
336
|
+
*
|
|
337
|
+
* @return {Array<String>} published versions
|
|
338
|
+
*/
|
|
339
|
+
async function versions() {
|
|
340
|
+
return await execa('npm', ['show', PACKAGE_NAME, 'versions'])
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export const quire = {
|
|
344
|
+
getPath,
|
|
345
|
+
getVersion,
|
|
346
|
+
initStarter,
|
|
347
|
+
installInProject,
|
|
348
|
+
latest,
|
|
349
|
+
list,
|
|
350
|
+
remove,
|
|
351
|
+
setVersion,
|
|
352
|
+
versions,
|
|
353
|
+
}
|