@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.
Files changed (243) hide show
  1. package/CHANGELOG.md +0 -36
  2. package/README.md +0 -9
  3. package/bin/cli.js +1 -46
  4. package/package.json +9 -25
  5. package/src/Command.js +6 -26
  6. package/src/commands/README.md +122 -213
  7. package/src/commands/build.js +37 -45
  8. package/src/commands/clean.js +19 -33
  9. package/src/commands/conf.js +43 -0
  10. package/src/commands/create.js +14 -42
  11. package/src/commands/epub.js +31 -67
  12. package/src/commands/index.js +2 -9
  13. package/src/commands/info.js +86 -88
  14. package/src/commands/pdf.js +82 -63
  15. package/src/commands/preview.js +31 -32
  16. package/src/commands/validate.js +20 -64
  17. package/src/commands/version.js +43 -0
  18. package/src/errors/validation/validation-error.js +11 -20
  19. package/src/helpers/clean.js +1 -1
  20. package/src/helpers/is-quire.js +31 -0
  21. package/src/helpers/test-cwd.js +6 -5
  22. package/src/helpers/which.js +4 -10
  23. package/src/lib/11ty/README.md +19 -135
  24. package/src/lib/11ty/api.js +93 -235
  25. package/src/lib/11ty/cli.js +37 -112
  26. package/src/lib/11ty/index.js +5 -64
  27. package/src/lib/11ty/paths.js +103 -0
  28. package/src/lib/README.md +0 -330
  29. package/src/lib/conf/README.md +69 -86
  30. package/src/lib/conf/config.js +3 -5
  31. package/src/lib/conf/defaults.js +0 -65
  32. package/src/lib/conf/schema.js +9 -103
  33. package/src/lib/epub/README.md +2 -133
  34. package/src/lib/epub/epub.js +11 -36
  35. package/src/lib/epub/index.js +21 -111
  36. package/src/lib/epub/pandoc.js +4 -33
  37. package/src/lib/git/README.md +2 -151
  38. package/src/lib/git/index.js +13 -217
  39. package/src/lib/i18n/README.md +3 -0
  40. package/src/lib/i18n/config.js +53 -0
  41. package/src/lib/i18n/index.js +43 -0
  42. package/src/lib/i18n/localeService.js +58 -0
  43. package/src/lib/pdf/README.md +0 -131
  44. package/src/lib/pdf/index.js +21 -124
  45. package/src/lib/pdf/paged.js +52 -100
  46. package/src/lib/pdf/prince.js +37 -115
  47. package/src/lib/pdf/split.js +33 -61
  48. package/src/lib/quire/README.md +19 -0
  49. package/src/lib/quire/index.js +353 -0
  50. package/src/lib/reporter/README.md +2 -211
  51. package/src/lib/reporter/index.js +0 -607
  52. package/src/main.js +48 -221
  53. package/src/packageConfig.js +0 -17
  54. package/src/validators/utils.js +1 -2
  55. package/schemas/config.schema.json +0 -194
  56. package/schemas/figures.schema.json +0 -56
  57. package/schemas/layout.schema.json +0 -5
  58. package/schemas/objects.schema.json +0 -62
  59. package/schemas/publication.schema.json +0 -140
  60. package/schemas/references.schema.json +0 -29
  61. package/src/Command.spec.js +0 -99
  62. package/src/commands/build.spec.js +0 -113
  63. package/src/commands/build.test.js +0 -397
  64. package/src/commands/clean.spec.js +0 -118
  65. package/src/commands/clean.test.js +0 -382
  66. package/src/commands/config.js +0 -238
  67. package/src/commands/config.spec.js +0 -107
  68. package/src/commands/config.test.js +0 -845
  69. package/src/commands/create.spec.js +0 -112
  70. package/src/commands/create.test.js +0 -415
  71. package/src/commands/doctor.js +0 -251
  72. package/src/commands/doctor.spec.js +0 -115
  73. package/src/commands/doctor.test.js +0 -1409
  74. package/src/commands/epub.spec.js +0 -114
  75. package/src/commands/epub.test.js +0 -503
  76. package/src/commands/help.js +0 -60
  77. package/src/commands/help.test.js +0 -132
  78. package/src/commands/info.spec.js +0 -72
  79. package/src/commands/info.test.js +0 -512
  80. package/src/commands/pdf.spec.js +0 -114
  81. package/src/commands/pdf.test.js +0 -464
  82. package/src/commands/preview.spec.js +0 -97
  83. package/src/commands/preview.test.js +0 -250
  84. package/src/commands/use.js +0 -56
  85. package/src/commands/use.spec.js +0 -61
  86. package/src/commands/use.test.js +0 -280
  87. package/src/commands/validate.spec.js +0 -90
  88. package/src/commands/validate.test.js +0 -378
  89. package/src/commands/workflows.js +0 -70
  90. package/src/errors/build/build-failed-error.js +0 -19
  91. package/src/errors/build/config-field-missing-error.js +0 -20
  92. package/src/errors/build/config-file-not-found-error.js +0 -20
  93. package/src/errors/build/index.js +0 -11
  94. package/src/errors/help/help-topic-not-found-error.js +0 -30
  95. package/src/errors/help/index.js +0 -8
  96. package/src/errors/index.js +0 -58
  97. package/src/errors/input/index.js +0 -8
  98. package/src/errors/input/invalid-input-error.js +0 -21
  99. package/src/errors/install/dependency-install-error.js +0 -19
  100. package/src/errors/install/directory-not-empty-error.js +0 -25
  101. package/src/errors/install/index.js +0 -12
  102. package/src/errors/install/invalid-path-error.js +0 -31
  103. package/src/errors/install/invalid-starter-error.js +0 -27
  104. package/src/errors/install/version-not-found-error.js +0 -35
  105. package/src/errors/output/epub-generation-error.js +0 -19
  106. package/src/errors/output/index.js +0 -14
  107. package/src/errors/output/invalid-epub-library-error.js +0 -20
  108. package/src/errors/output/invalid-pdf-library-error.js +0 -20
  109. package/src/errors/output/missing-build-output-error.js +0 -21
  110. package/src/errors/output/pdf-generation-error.js +0 -24
  111. package/src/errors/output/tool-not-found-error.js +0 -37
  112. package/src/errors/project/index.js +0 -10
  113. package/src/errors/project/not-in-project-error.js +0 -20
  114. package/src/errors/project/project-create-error.js +0 -21
  115. package/src/errors/quire-error.js +0 -27
  116. package/src/errors/validation/index.js +0 -3
  117. package/src/errors/validation/unknown-config-key-error.js +0 -27
  118. package/src/errors/validation/unknown-config-operation-error.js +0 -24
  119. package/src/helpers/docs-url.js +0 -32
  120. package/src/helpers/pager.js +0 -59
  121. package/src/helpers/pager.test.js +0 -85
  122. package/src/helpers/suggest-similar.js +0 -124
  123. package/src/helpers/suggest-similar.test.js +0 -108
  124. package/src/helpers/test-cwd.test.js +0 -192
  125. package/src/lib/11ty/index.test.js +0 -655
  126. package/src/lib/commander/index.js +0 -103
  127. package/src/lib/commander/index.test.js +0 -86
  128. package/src/lib/commander/options.js +0 -237
  129. package/src/lib/commander/options.test.js +0 -205
  130. package/src/lib/conf/build-status.js +0 -103
  131. package/src/lib/conf/build-status.test.js +0 -247
  132. package/src/lib/conf/config.test.js +0 -281
  133. package/src/lib/conf/format.js +0 -60
  134. package/src/lib/conf/format.test.js +0 -106
  135. package/src/lib/conf/helpers.js +0 -91
  136. package/src/lib/conf/helpers.test.js +0 -136
  137. package/src/lib/conf/index.js +0 -22
  138. package/src/lib/constants.js +0 -28
  139. package/src/lib/doctor/README.md +0 -667
  140. package/src/lib/doctor/checks/environment/cli-version.js +0 -62
  141. package/src/lib/doctor/checks/environment/cli-version.test.js +0 -132
  142. package/src/lib/doctor/checks/environment/git-available.js +0 -77
  143. package/src/lib/doctor/checks/environment/git-available.test.js +0 -52
  144. package/src/lib/doctor/checks/environment/index.js +0 -13
  145. package/src/lib/doctor/checks/environment/node-version.js +0 -66
  146. package/src/lib/doctor/checks/environment/node-version.test.js +0 -17
  147. package/src/lib/doctor/checks/environment/npm-available.js +0 -66
  148. package/src/lib/doctor/checks/environment/npm-available.test.js +0 -52
  149. package/src/lib/doctor/checks/environment/os-info.js +0 -48
  150. package/src/lib/doctor/checks/environment/os-info.test.js +0 -81
  151. package/src/lib/doctor/checks/environment/runtime-info.js +0 -51
  152. package/src/lib/doctor/checks/environment/runtime-info.test.js +0 -132
  153. package/src/lib/doctor/checks/outputs/epub-output.js +0 -119
  154. package/src/lib/doctor/checks/outputs/epub-output.test.js +0 -277
  155. package/src/lib/doctor/checks/outputs/index.js +0 -10
  156. package/src/lib/doctor/checks/outputs/pdf-output.js +0 -144
  157. package/src/lib/doctor/checks/outputs/pdf-output.test.js +0 -377
  158. package/src/lib/doctor/checks/outputs/stale-build.js +0 -122
  159. package/src/lib/doctor/checks/outputs/stale-build.test.js +0 -282
  160. package/src/lib/doctor/checks/project/data-files.js +0 -56
  161. package/src/lib/doctor/checks/project/data-files.test.js +0 -125
  162. package/src/lib/doctor/checks/project/dependencies.js +0 -53
  163. package/src/lib/doctor/checks/project/dependencies.test.js +0 -71
  164. package/src/lib/doctor/checks/project/index.js +0 -11
  165. package/src/lib/doctor/checks/project/quire-11ty.js +0 -98
  166. package/src/lib/doctor/checks/project/quire-11ty.test.js +0 -170
  167. package/src/lib/doctor/checks/project/quire-project.js +0 -38
  168. package/src/lib/doctor/checks/project/quire-project.test.js +0 -47
  169. package/src/lib/doctor/checks/tools/index.js +0 -10
  170. package/src/lib/doctor/checks/tools/pandoc-available.js +0 -82
  171. package/src/lib/doctor/checks/tools/pandoc-available.test.js +0 -73
  172. package/src/lib/doctor/checks/tools/prince-available.js +0 -81
  173. package/src/lib/doctor/checks/tools/prince-available.test.js +0 -73
  174. package/src/lib/doctor/constants.js +0 -39
  175. package/src/lib/doctor/formatDuration.js +0 -108
  176. package/src/lib/doctor/formatDuration.test.js +0 -76
  177. package/src/lib/doctor/formatters/human.js +0 -257
  178. package/src/lib/doctor/formatters/human.test.js +0 -463
  179. package/src/lib/doctor/formatters/index.js +0 -8
  180. package/src/lib/doctor/formatters/json.js +0 -78
  181. package/src/lib/doctor/formatters/json.test.js +0 -174
  182. package/src/lib/doctor/formatters/shared.js +0 -129
  183. package/src/lib/doctor/formatters/shared.test.js +0 -194
  184. package/src/lib/doctor/index.js +0 -271
  185. package/src/lib/doctor/index.test.js +0 -797
  186. package/src/lib/epub/engines.js +0 -46
  187. package/src/lib/epub/index.test.js +0 -518
  188. package/src/lib/epub/pandoc.test.js +0 -122
  189. package/src/lib/epub/schema.js +0 -21
  190. package/src/lib/error/README.md +0 -170
  191. package/src/lib/error/handler.js +0 -107
  192. package/src/lib/git/index.spec.js +0 -80
  193. package/src/lib/git/index.test.js +0 -453
  194. package/src/lib/help/frontmatter.js +0 -77
  195. package/src/lib/help/frontmatter.test.js +0 -139
  196. package/src/lib/help/index.js +0 -146
  197. package/src/lib/help/index.test.js +0 -188
  198. package/src/lib/help/topics/configuration.md +0 -77
  199. package/src/lib/help/topics/debugging.md +0 -69
  200. package/src/lib/help/topics/epub.md +0 -74
  201. package/src/lib/help/topics/pdf.md +0 -74
  202. package/src/lib/help/topics/publishing.md +0 -80
  203. package/src/lib/help/topics/workflows.md +0 -50
  204. package/src/lib/installer/index.js +0 -309
  205. package/src/lib/installer/index.spec.js +0 -83
  206. package/src/lib/installer/index.test.js +0 -545
  207. package/src/lib/logger/README.md +0 -424
  208. package/src/lib/logger/debug.js +0 -132
  209. package/src/lib/logger/debug.spec.js +0 -130
  210. package/src/lib/logger/debug.test.js +0 -128
  211. package/src/lib/logger/index.js +0 -228
  212. package/src/lib/logger/index.spec.js +0 -131
  213. package/src/lib/logger/index.test.js +0 -578
  214. package/src/lib/npm/README.md +0 -127
  215. package/src/lib/npm/index.js +0 -198
  216. package/src/lib/npm/index.spec.js +0 -60
  217. package/src/lib/npm/index.test.js +0 -355
  218. package/src/lib/pdf/engines.js +0 -46
  219. package/src/lib/pdf/index.test.js +0 -708
  220. package/src/lib/pdf/paged.test.js +0 -366
  221. package/src/lib/pdf/prince.test.js +0 -202
  222. package/src/lib/pdf/schema.js +0 -21
  223. package/src/lib/pdf/split.test.js +0 -445
  224. package/src/lib/platform.js +0 -95
  225. package/src/lib/process/manager.js +0 -110
  226. package/src/lib/process/manager.test.js +0 -55
  227. package/src/lib/project/build.js +0 -162
  228. package/src/lib/project/build.test.js +0 -275
  229. package/src/lib/project/config.js +0 -48
  230. package/src/lib/project/config.test.js +0 -134
  231. package/src/lib/project/detect.js +0 -47
  232. package/src/lib/project/detect.test.js +0 -157
  233. package/src/lib/project/index.js +0 -56
  234. package/src/lib/project/output-paths.js +0 -87
  235. package/src/lib/project/output-paths.test.js +0 -66
  236. package/src/lib/project/paths.js +0 -272
  237. package/src/lib/project/version.js +0 -110
  238. package/src/lib/project/version.test.js +0 -350
  239. package/src/lib/reporter/index.test.js +0 -862
  240. package/src/main.spec.js +0 -61
  241. package/src/main.test.js +0 -347
  242. package/src/validators/validate-data-files.js +0 -154
  243. package/src/validators/validate-data-files.test.js +0 -217
@@ -1,10 +1,6 @@
1
1
  import Command from '#src/Command.js'
2
- import { Option } from 'commander'
3
- import { withOutputModes } from '#lib/commander/index.js'
4
2
  import fs from 'fs-extra'
5
- import { installer } from '#lib/installer/index.js'
6
- import { DirectoryNotEmptyError, ProjectCreateError } from '#src/errors/index.js'
7
- import reporter from '#lib/reporter/index.js'
3
+ import { quire } from '#src/lib/quire/index.js'
8
4
 
9
5
  /**
10
6
  * Quire CLI `new` Command
@@ -17,17 +13,10 @@ import reporter from '#lib/reporter/index.js'
17
13
  * @extends {Command}
18
14
  */
19
15
  export default class CreateCommand extends Command {
20
- static definition = withOutputModes({
16
+ static definition = {
21
17
  name: 'new',
22
18
  description: 'Start a new Quire project from a template.',
23
19
  summary: 'create a new project',
24
- docsLink: 'quire-commands/#start-and-preview-projects',
25
- helpText: `
26
- Examples:
27
- quire new my-project Use default starter
28
- quire new my-project --quire-version 1.0.0 Pin quire-11ty version
29
- quire new my-project --verbose Create with detailed progress
30
- `,
31
20
  version: '1.0.0',
32
21
  args: [
33
22
  [ '[projectPath]', 'local path to the new project', '.' ],
@@ -36,10 +25,10 @@ Examples:
36
25
  options: [
37
26
  [ '--quire-path <path>', 'local path to quire-11ty package' ],
38
27
  [ '--quire-version <version>', 'quire-11ty version to install' ],
39
- // Use Option object syntax to configure this as a hidden option
40
- new Option('--clean-cache', 'force clean the npm cache').default(false).hideHelp(),
28
+ // [ '--eject', 'install quire-11ty into the project directory', true ],
29
+ [ '--debug', 'debug the `quire new` command', false ],
41
30
  ],
42
- })
31
+ }
43
32
 
44
33
  constructor() {
45
34
  super(CreateCommand.definition)
@@ -52,16 +41,15 @@ Examples:
52
41
  * @return {Promise}
53
42
  */
54
43
  async action(projectPath, starter, options = {}) {
55
- this.debug('called with options %O', options)
56
-
57
- // Configure reporter for this command
58
- reporter.configure({ quiet: options.quiet, verbose: options.verbose })
44
+ if (options.debug) {
45
+ console.info('Command \'%s\' called with options %o', CreateCommand.name, options)
46
+ }
59
47
 
60
48
  starter = starter || this.config.get('projectTemplate')
61
49
 
62
50
  if (!projectPath && !starter) {
63
51
  // @TODO implement this case of interactively selecting starter templates
64
- // from available subtrees in `lib/installer` module
52
+ // from available subtrees in `lib/quire` module
65
53
 
66
54
  // await interactivePrompt()
67
55
  // list sub-repositories in '@thegetty/quire/packages/starters'
@@ -77,30 +65,14 @@ Examples:
77
65
  */
78
66
  let quireVersion
79
67
  try {
80
- quireVersion = await installer.initStarter(starter, projectPath, options)
68
+ quireVersion = await quire.initStarter(starter, projectPath, options)
81
69
  } catch (error) {
82
- reporter.fail('Failed to initialize project')
83
- this.logger.error(error.message)
84
- /**
85
- * Nota bene: Auto-deletion of projectPath is disabled to prevent accidental data loss.
86
- * @TODO implement safe cleaup that either tracks whether quire created the directory,
87
- * or prompt the user for confirmation before deleting any files.
88
- */
89
- // if (!(error instanceof DirectoryNotEmptyError)) {
90
- // fs.removeSync(projectPath)
91
- // }
92
- throw new ProjectCreateError(projectPath, error.message)
93
- }
94
-
95
- // Check if initStarter returned without a version
96
- if (!quireVersion) {
97
- // Nota bene: Auto-deletion disabled - see comment above
98
- // fs.removeSync(projectPath)
99
- throw new ProjectCreateError(projectPath, 'Failed to determine Quire version')
70
+ console.error(error.message)
71
+ fs.removeSync(projectPath)
72
+ return
100
73
  }
101
74
 
102
- await installer.installInProject(projectPath, quireVersion, options)
103
- reporter.succeed('Project created successfully')
75
+ await quire.installInProject(projectPath, quireVersion, options)
104
76
  }
105
77
  }
106
78
  }
@@ -1,17 +1,12 @@
1
1
  import Command from '#src/Command.js'
2
- import { withOutputModes } from '#lib/commander/index.js'
3
- import paths, { hasEpubOutput } from '#lib/project/index.js'
4
- import eleventy from '#lib/11ty/index.js'
2
+ import { paths, projectRoot } from '#lib/11ty/index.js'
5
3
  import fs from 'fs-extra'
6
- import generateEpub, { ENGINES } from '#lib/epub/index.js'
4
+ import libEpub from '#lib/epub/index.js'
7
5
  import open from 'open'
8
- import { recordStatus } from '#lib/conf/build-status.js'
9
- import reporter from '#lib/reporter/index.js'
10
- import testcwd from '#helpers/test-cwd.js'
11
- import { MissingBuildOutputError } from '#src/errors/index.js'
6
+ import path from 'node:path'
12
7
 
13
8
  /**
14
- * Quire CLI `epub` Command
9
+ * Quire CLI `build epub` Command
15
10
  *
16
11
  * Generate EPUB from Eleventy `build` output.
17
12
  *
@@ -19,84 +14,53 @@ import { MissingBuildOutputError } from '#src/errors/index.js'
19
14
  * @extends {Command}
20
15
  */
21
16
  export default class EpubCommand extends Command {
22
- static definition = withOutputModes({
17
+ static definition = {
23
18
  name: 'epub',
24
19
  description: 'Generate publication EPUB',
25
- summary: 'generate EPUB e-book',
26
- docsLink: 'quire-commands/#output-files',
27
- helpText: `
28
- Examples:
29
- quire epub Generate EPUB using default engine
30
- quire epub --engine pandoc Generate EPUB using Pandoc
31
- quire epub --open Generate and open EPUB
32
- quire epub --build Build site first, then generate EPUB
33
- quire epub --output my-book.epub Generate EPUB with custom output path
34
- `,
20
+ summary: 'run build epub',
35
21
  version: '1.0.0',
22
+ args: [],
36
23
  options: [
37
- [ '--build', 'run build first if output is missing' ],
38
- [ '--open', 'open EPUB in default application' ],
39
- [ '-o, --output <path>', 'output file path (default: {engine}.epub)' ],
40
- [
41
- '--engine <name>', 'EPUB engine to use (default: from config or epubjs)',
42
- { choices: ENGINES }
43
- ],
44
24
  [
45
- '--lib <name>', 'deprecated alias for --engine option',
46
- { hidden: true, choices: ENGINES, conflicts: 'engine' }
25
+ '--lib <module>', 'use the specified epub library', 'epubjs',
26
+ { choices: ['epubjs', 'pandoc'], default: 'epubjs' }
47
27
  ],
28
+ [ '--open', 'open EPUB in default application' ],
29
+ [ '--debug', 'run epub with debug output' ],
48
30
  ],
49
- })
31
+ }
50
32
 
51
33
  constructor() {
52
34
  super(EpubCommand.definition)
53
35
  }
54
36
 
55
37
  async action(options, command) {
56
- this.debug('called with options %O', options)
57
-
58
- // Configure reporter for this command
59
- reporter.configure({ quiet: options.quiet, verbose: options.verbose })
60
-
61
- // Resolve engine: CLI --engine > deprecated --lib > config epubEngine > default
62
- if (!options.engine) {
63
- if (options.lib) {
64
- // Support deprecated --lib option
65
- options.engine = options.lib
66
- } else {
67
- // Use config setting or fallback to default
68
- options.engine = this.config.get('epubEngine') || 'epubjs'
69
- }
38
+ if (options.debug) {
39
+ console.debug('[CLI] Command \'%s\' called with options %o', this.name(), options)
70
40
  }
71
41
 
72
- // Run build first if --build flag is set and output is missing
73
- if (options.build && !hasEpubOutput()) {
74
- this.debug('running build before epub generation')
75
- reporter.start('Building site...', { showElapsed: true })
76
- await eleventy.build({ debug: options.debug })
77
- }
42
+ const input = path.join(projectRoot, paths.epub)
78
43
 
79
- // Check for build output (will throw if missing)
80
- // TODO: Add interactive prompt when build output missing and --build not used
81
- if (!hasEpubOutput()) {
82
- throw new MissingBuildOutputError('EPUB', paths.getEpubDir())
44
+ if (!fs.existsSync(input)) {
45
+ console.error(`Unable to find Epub input at ${input}\nPlease first run the 'quire build' command.`)
46
+ return
83
47
  }
84
48
 
85
- // Pass engine as lib (matching lib/pdf interface)
86
- // Reporter lifecycle is owned by the façade (lib/epub/index.js)
87
- const epubOptions = { ...options, lib: options.engine }
49
+ const output = path.join(projectRoot, `${options.lib}.epub`)
88
50
 
89
- try {
90
- const output = await generateEpub(epubOptions)
91
- recordStatus(paths.getProjectRoot(), 'epub', 'ok')
92
- if (fs.existsSync(output) && options.open) open(output)
93
- } catch (error) {
94
- recordStatus(paths.getProjectRoot(), 'epub', 'failed')
95
- throw error
96
- }
51
+ const epubLib = await libEpub(options.lib, { debug: options.debug })
52
+ await epubLib(input, output)
53
+
54
+ if (fs.existsSync(output) && options.open) open(output)
97
55
  }
98
56
 
99
- preAction(thisCommand, actionCommand) {
100
- testcwd(thisCommand)
57
+ /**
58
+ * @todo test if build site has already be run and output can be reused
59
+ */
60
+ preAction(command) {
61
+ const options = command.opts()
62
+ if (options.debug) {
63
+ console.debug('[CLI] Calling \'epub\' command pre-action with options', options)
64
+ }
101
65
  }
102
66
  }
@@ -8,21 +8,14 @@ const __dirname = path.dirname(__filename)
8
8
 
9
9
  const thisfile = path.basename(__filename)
10
10
 
11
- /**
12
- * Filter out files that are not command modules
13
- * @param directory entry
14
- * @returns Boolean
15
- */
16
- const filterEntries = (entry) => entry !== thisfile && entry.match(/^.*(?<!spec|test)\.js$/)
17
-
18
11
  /**
19
12
  * Dynamically import command modules in parallel
20
13
  * and call the class constuctor for each command
21
14
  */
22
15
  const commands = await Promise.all(
23
16
  fs.readdirSync(__dirname)
24
- .filter((entry) => filterEntries(entry))
25
- .map(async (entry) => await dynamicImport(path.resolve(__dirname, entry)))
17
+ .filter((file) => file !== thisfile && file.match(/^.*\.js$/))
18
+ .map(async (file) => await dynamicImport(path.resolve(__dirname, file)))
26
19
  ).then((modules) => {
27
20
  return modules.map(({ default: CommandClass }) => new CommandClass())
28
21
  })
@@ -1,59 +1,44 @@
1
1
  import Command from '#src/Command.js'
2
- import { withOutputModes } from '#lib/commander/index.js'
3
- import { binPath } from '#src/packageConfig.js'
2
+ import { execaCommand } from 'execa'
4
3
  import fs from 'node:fs'
4
+ import os from 'node:os'
5
5
  import path from 'node:path'
6
6
  import testcwd from '#helpers/test-cwd.js'
7
7
 
8
8
  /**
9
9
  * Quire CLI `info` Command
10
10
  *
11
- * Display version information for the current Quire project.
12
- * Shows the versions of quire-cli and quire-11ty that the project was
13
- * created with, plus the starter template version.
14
- *
15
- * With --debug, also shows the full filesystem path to the quire-cli
16
- * executable.
17
- *
18
- * For system environment information (OS, Node.js, npm, Git),
19
- * use the `quire doctor` command instead.
11
+ * Runs the Eleventy `info` command to list the quire-cli, quire-11ty, node, and npm versions.
20
12
  *
21
13
  * @class InfoCommand
22
14
  * @extends {Command}
23
15
  */
24
16
  export default class InfoCommand extends Command {
25
- static definition = withOutputModes({
17
+ static definition = {
26
18
  name: 'info',
27
- description: 'Display version information for the current project',
28
- summary: 'show project version information',
29
- docsLink: 'quire-commands/#get-help',
30
- helpText: `
31
- Shows the versions used when this project was created:
32
- • quire-cli version that created the project
33
- • quire-11ty version installed in the project
34
- • starter template version (if available)
35
-
36
- For system environment checks (OS, Node.js, npm, Git),
37
- use 'quire doctor' instead.
38
-
39
- Example:
40
- quire info Show project versions
41
- quire info --debug Include installation paths
42
- quire info --json Output version information as JSON
43
- quire doctor Check environment and project health
44
- `,
19
+ description: 'List Quire cli, quire-11ty, and node versions',
20
+ summary: 'list info',
45
21
  version: '1.0.0',
22
+ args: [],
46
23
  options: [
47
- ['--json', 'output version information as JSON'],
24
+ ['--debug', 'include os versions in output']
48
25
  ],
49
- })
26
+ }
50
27
 
51
28
  constructor() {
52
29
  super(InfoCommand.definition)
53
30
  }
54
31
 
55
32
  async action(options, command) {
56
- this.debug('called with options %O', options)
33
+ if (options.debug) {
34
+ console.debug(
35
+ '[CLI] Command \'%s\' called with options %o',
36
+ this.name(),
37
+ options
38
+ )
39
+ } else {
40
+ console.debug('[CLI] Command \'%s\' called', this.name())
41
+ }
57
42
 
58
43
  // Load filename from config with a default constraint if it doesn't exist
59
44
  const versionFileName = this.config.get('versionFile')
@@ -61,72 +46,85 @@ Example:
61
46
 
62
47
  try {
63
48
  const versionFileData = fs.readFileSync(versionFileName, { encoding: 'utf8' })
64
- versionInfo = JSON.parse(versionFileData)
49
+
50
+ versionInfo = JSON.parse(versionFileData)
65
51
  } catch (error) {
66
- this.logger.warn(
52
+ console.warn(
67
53
  `This project was generated with the quire-cli prior to version 1.0.0.rc-8. Updating the version file to the new format, though this project's version file will not contain specific starter version information.`
68
54
  )
55
+
69
56
  fs.writeFileSync(versionFileName, JSON.stringify(versionInfo))
70
57
  }
71
58
 
72
59
  const { name: projectDirectory } = path.parse(process.cwd())
73
60
 
74
- // Read quire-11ty version from project's package.json
75
- let quire11tyVersion = 'unknown'
76
- try {
77
- const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'))
78
- quire11tyVersion = packageJson.version
79
- } catch {
80
- this.debug('Could not read package.json')
81
- }
82
-
83
- if (options.json) {
84
- const result = {
85
- project: {
86
- directory: projectDirectory,
87
- cli: versionInfo.cli,
88
- quire11ty: quire11tyVersion,
89
- starter: versionInfo.starter || null,
90
- },
91
- }
92
- console.log(JSON.stringify(result, null, 2))
93
- return
94
- }
95
-
96
- const lines = [
97
- `Project: ${projectDirectory}`,
98
- '',
99
- ` quire-cli ${versionInfo.cli || 'unknown'}`,
100
- ` quire-11ty ${quire11tyVersion}`,
61
+ const versions = [
62
+ {
63
+ title: `[${projectDirectory}]`,
64
+ items: [
65
+ {
66
+ name: 'quire-cli',
67
+ get: () => versionInfo.cli,
68
+ },
69
+ {
70
+ name: 'quire-11ty',
71
+ get: () => {
72
+ const { version } = JSON.parse(fs.readFileSync('./package.json'))
73
+ return version
74
+ },
75
+ },
76
+ {
77
+ name: 'starter',
78
+ get: () => versionInfo.starter,
79
+ },
80
+ ],
81
+ },
82
+ {
83
+ title: '[System]',
84
+ items: [
85
+ {
86
+ name: 'quire-cli',
87
+ get: async () => {
88
+ const { stdout } = await execaCommand('quire --version')
89
+ return stdout
90
+ },
91
+ },
92
+ {
93
+ debug: true,
94
+ name: 'node',
95
+ get: () => process.version,
96
+ },
97
+ {
98
+ debug: true,
99
+ name: 'npm',
100
+ get: async () => {
101
+ const { stdout } = await execaCommand('npm --version')
102
+ return stdout
103
+ },
104
+ },
105
+ {
106
+ debug: true,
107
+ name: 'os',
108
+ get: () => `${os.type()} ${os.release()}`,
109
+ },
110
+ ],
111
+ },
101
112
  ]
102
113
 
103
- if (versionInfo.starter) {
104
- lines.push(` starter ${versionInfo.starter}`)
105
- }
106
-
107
- if (options.debug) {
108
- lines.push('')
109
- lines.push(this.resolveCliPath())
110
- }
111
-
112
- lines.push('')
113
- lines.push('Tip: Run \'quire doctor\' for system environment checks')
114
-
115
- this.logger.info(lines.join('\n'))
116
- }
117
-
118
- /**
119
- * Resolve the full filesystem path to the quire CLI executable
120
- * @returns {string} Formatted path line
121
- */
122
- resolveCliPath() {
123
- const resolved = binPath()
124
- return resolved
125
- ? ` quire-cli ${resolved}`
126
- : ' quire-cli not found in PATH'
114
+ /**
115
+ * Filter the command output based on `debug` settings
116
+ */
117
+ versions.forEach(async ({ items, title }) => {
118
+ const versions = await Promise.all(
119
+ items
120
+ .filter(({ debug }) => !debug || (options.debug && debug))
121
+ .map(async ({ name, get }) => `${name} ${await get()}`)
122
+ )
123
+ console.info(`${title}\n ${versions.join('\n ')}`)
124
+ })
127
125
  }
128
126
 
129
- preAction(thisCommand, actionCommand) {
130
- testcwd(thisCommand)
127
+ preAction(command) {
128
+ testcwd(command)
131
129
  }
132
130
  }
@@ -1,14 +1,50 @@
1
+ import { paths, projectRoot } from '#lib/11ty/index.js'
1
2
  import Command from '#src/Command.js'
2
- import { withOutputModes } from '#lib/commander/index.js'
3
- import paths, { hasSiteOutput } from '#lib/project/index.js'
4
- import eleventy from '#lib/11ty/index.js'
5
- import generatePdf, { ENGINES } from '#lib/pdf/index.js'
3
+ import fs from 'fs-extra'
4
+ import libPdf from '#lib/pdf/index.js'
6
5
  import open from 'open'
7
6
  import path from 'node:path'
8
- import { recordStatus } from '#lib/conf/build-status.js'
9
- import reporter from '#lib/reporter/index.js'
10
- import testcwd from '#helpers/test-cwd.js'
11
- import { MissingBuildOutputError } from '#src/errors/index.js'
7
+ import { pathToFileURL } from 'node:url'
8
+ import yaml from 'js-yaml'
9
+
10
+ /**
11
+ * @function loadConfig(path) - loads and validates quire config, returns an empty object if not found
12
+ *
13
+ * @param {path} string - file path to config file
14
+ *
15
+ * @return {Object|undefined} User configuration object or undefined
16
+ *
17
+ * @todo consider hardcoding a version check against .quire / project's package.json ver
18
+ */
19
+ async function loadConfig(configPath) {
20
+ if (!fs.existsSync(configPath)) {
21
+ return undefined
22
+ }
23
+
24
+ const data = fs.readFileSync(configPath)
25
+ let config = yaml.load(data)
26
+
27
+ // NB: Schemas and validators are specific to the 11ty version of the project being built
28
+ const schemaPath = path.join(projectRoot,'_plugins','schemas','config.json')
29
+ const validatorPath = path.join(projectRoot, '_plugins', 'globalData', 'validator.js')
30
+
31
+ if (fs.existsSync(schemaPath) && fs.existsSync(validatorPath)) {
32
+
33
+ const { validateUserConfig } = await import(pathToFileURL(validatorPath))
34
+
35
+ const schemaJSON = fs.readFileSync(schemaPath)
36
+ const schema = JSON.parse(schemaJSON)
37
+
38
+ try {
39
+ config = validateUserConfig('config', config, { config: schema })
40
+ } catch (error) {
41
+ console.error(error)
42
+ process.exit(1)
43
+ }
44
+ }
45
+
46
+ return config
47
+ }
12
48
 
13
49
  /**
14
50
  * Quire CLI `pdf` Command
@@ -19,83 +55,66 @@ import { MissingBuildOutputError } from '#src/errors/index.js'
19
55
  * @extends {Command}
20
56
  */
21
57
  export default class PDFCommand extends Command {
22
- static definition = withOutputModes({
58
+ static definition = {
23
59
  name: 'pdf',
24
60
  description: 'Generate publication PDF',
25
- summary: 'generate print-ready PDF',
26
- docsLink: 'quire-commands/#output-files',
27
- helpText: `
28
- Examples:
29
- quire pdf Generate PDF using default engine
30
- quire pdf --engine prince Generate PDF using PrinceXML
31
- quire pdf --build Build site first, then generate PDF
32
- quire pdf --output my-book.pdf Generate PDF with custom output path
33
- quire pdf --verbose Generate with detailed progress
34
- `,
61
+ summary: 'run build pdf',
35
62
  version: '1.0.0',
63
+ args: [
64
+ ],
36
65
  options: [
37
- [ '--build', 'run build first if output is missing' ],
38
- [ '--open', 'open PDF in default application' ],
39
- [ '-o, --output <path>', 'output file path (default: from project config)' ],
40
66
  [
41
- '--engine <name>', 'PDF engine to use (default: from config or pagedjs)',
42
- { choices: ENGINES }
43
- ],
44
- [
45
- '--lib <name>', 'deprecated alias for --engine option',
46
- { hidden: true, choices: ENGINES, conflicts: 'engine' }
67
+ '--lib <module>', 'use the specified pdf module', 'pagedjs',
68
+ { choices: ['pagedjs', 'prince'], default: 'pagedjs' }
47
69
  ],
70
+ [ '--open', 'open PDF in default application' ],
71
+ [ '--debug', 'run build with debug output to console' ],
48
72
  ],
49
- })
73
+ }
50
74
 
51
75
  constructor() {
52
76
  super(PDFCommand.definition)
53
77
  }
54
78
 
55
79
  async action(options, command) {
56
- this.debug('called with options %O', options)
57
- /**
58
- * Configure reporter for this command
59
- * reporter lifecycle (start/succeed/fail) is handled by the façade,
60
- * not by the command.
61
- */
62
- reporter.configure({ quiet: options.quiet, verbose: options.verbose })
63
-
64
- // Resolve engine: CLI --engine > deprecated --lib > config pdfEngine > default
65
- if (!options.engine) {
66
- if (options.lib) {
67
- // Support deprecated --lib option
68
- options.engine = options.lib
69
- } else {
70
- // Use config setting or fallback to default
71
- options.engine = this.config.get('pdfEngine') || 'pagedjs'
72
- }
80
+ if (options.debug) {
81
+ console.debug('[CLI] Command \'%s\' called with options %o', this.name(), options)
82
+ }
83
+
84
+ const publicationInput = path.join(projectRoot, paths.output, 'pdf.html')
85
+ const coversInput = path.join(projectRoot, paths.output, 'pdf-covers.html')
86
+
87
+ const quireConfig = await loadConfig(path.join(projectRoot,'content','_data','config.yaml'))
88
+
89
+ if (quireConfig === undefined) {
90
+ console.error(`[quire pdf]: ERROR Unable to find a configuration file at ${path.join(projectRoot,'content','_data','config.yaml')}\nIs the command being run in a quire project?`)
91
+ process.exit(1)
73
92
  }
74
93
 
75
- // Run build first if --build flag is set and output is missing
76
- if (options.build && !hasSiteOutput()) {
77
- this.debug('running build before pdf generation')
78
- reporter.start('Building site...', { showElapsed: true })
79
- await eleventy.build({ debug: options.debug })
80
- reporter.succeed('Build complete')
94
+ if (!fs.existsSync(publicationInput)) {
95
+ console.error(`[quire pdf]: ERROR Unable to find PDF input at ${publicationInput}\nPlease first run the 'quire build' command.`)
96
+ process.exit(1)
81
97
  }
82
98
 
83
- // Generate PDF - façade handles validation, progress, and errors
84
- const pdfOptions = { ...options, lib: options.engine }
99
+ const output = quireConfig.pdf !== undefined
100
+ ? path.join(paths.output, quireConfig.pdf.outputDir, `${quireConfig.pdf.filename}.pdf`)
101
+ : path.join(projectRoot, `${options.lib}.pdf`)
102
+
103
+ const pdfLib = await libPdf(options.lib, { ...options, pdfConfig: quireConfig.pdf })
104
+ await pdfLib(publicationInput, coversInput, output)
85
105
 
86
106
  try {
87
- const output = await generatePdf(pdfOptions)
88
- recordStatus(paths.getProjectRoot(), 'pdf', 'ok')
89
- if (options.open) {
90
- open(output)
91
- }
107
+ if (fs.existsSync(output) && options.open) open(output)
92
108
  } catch (error) {
93
- recordStatus(paths.getProjectRoot(), 'pdf', 'failed')
94
- throw error
109
+ console.error(`[quire pdf]: ERROR`,error)
110
+ process.exit(1)
95
111
  }
96
112
  }
97
113
 
98
- preAction(thisCommand, actionCommand) {
99
- testcwd(thisCommand)
114
+ /**
115
+ * @todo test if build has already be run and output can be reused
116
+ */
117
+ preAction(command) {
118
+ // testcwd(command)
100
119
  }
101
120
  }