@thegetty/quire-cli 1.0.0-rc.45 → 1.0.0-rc.47

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 (245) 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 +10 -27
  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/man/quire.1 +0 -341
  56. package/man/quire.1.md +0 -232
  57. package/schemas/config.schema.json +0 -194
  58. package/schemas/figures.schema.json +0 -56
  59. package/schemas/layout.schema.json +0 -5
  60. package/schemas/objects.schema.json +0 -62
  61. package/schemas/publication.schema.json +0 -140
  62. package/schemas/references.schema.json +0 -29
  63. package/src/Command.spec.js +0 -99
  64. package/src/commands/build.spec.js +0 -113
  65. package/src/commands/build.test.js +0 -397
  66. package/src/commands/clean.spec.js +0 -118
  67. package/src/commands/clean.test.js +0 -382
  68. package/src/commands/config.js +0 -238
  69. package/src/commands/config.spec.js +0 -107
  70. package/src/commands/config.test.js +0 -845
  71. package/src/commands/create.spec.js +0 -112
  72. package/src/commands/create.test.js +0 -415
  73. package/src/commands/doctor.js +0 -251
  74. package/src/commands/doctor.spec.js +0 -115
  75. package/src/commands/doctor.test.js +0 -1409
  76. package/src/commands/epub.spec.js +0 -114
  77. package/src/commands/epub.test.js +0 -503
  78. package/src/commands/help.js +0 -60
  79. package/src/commands/help.test.js +0 -132
  80. package/src/commands/info.spec.js +0 -72
  81. package/src/commands/info.test.js +0 -512
  82. package/src/commands/pdf.spec.js +0 -114
  83. package/src/commands/pdf.test.js +0 -464
  84. package/src/commands/preview.spec.js +0 -97
  85. package/src/commands/preview.test.js +0 -250
  86. package/src/commands/use.js +0 -56
  87. package/src/commands/use.spec.js +0 -61
  88. package/src/commands/use.test.js +0 -280
  89. package/src/commands/validate.spec.js +0 -90
  90. package/src/commands/validate.test.js +0 -378
  91. package/src/commands/workflows.js +0 -70
  92. package/src/errors/build/build-failed-error.js +0 -19
  93. package/src/errors/build/config-field-missing-error.js +0 -20
  94. package/src/errors/build/config-file-not-found-error.js +0 -20
  95. package/src/errors/build/index.js +0 -11
  96. package/src/errors/help/help-topic-not-found-error.js +0 -30
  97. package/src/errors/help/index.js +0 -8
  98. package/src/errors/index.js +0 -58
  99. package/src/errors/input/index.js +0 -8
  100. package/src/errors/input/invalid-input-error.js +0 -21
  101. package/src/errors/install/dependency-install-error.js +0 -19
  102. package/src/errors/install/directory-not-empty-error.js +0 -25
  103. package/src/errors/install/index.js +0 -12
  104. package/src/errors/install/invalid-path-error.js +0 -31
  105. package/src/errors/install/invalid-starter-error.js +0 -27
  106. package/src/errors/install/version-not-found-error.js +0 -35
  107. package/src/errors/output/epub-generation-error.js +0 -19
  108. package/src/errors/output/index.js +0 -14
  109. package/src/errors/output/invalid-epub-library-error.js +0 -20
  110. package/src/errors/output/invalid-pdf-library-error.js +0 -20
  111. package/src/errors/output/missing-build-output-error.js +0 -21
  112. package/src/errors/output/pdf-generation-error.js +0 -24
  113. package/src/errors/output/tool-not-found-error.js +0 -37
  114. package/src/errors/project/index.js +0 -10
  115. package/src/errors/project/not-in-project-error.js +0 -20
  116. package/src/errors/project/project-create-error.js +0 -21
  117. package/src/errors/quire-error.js +0 -27
  118. package/src/errors/validation/index.js +0 -3
  119. package/src/errors/validation/unknown-config-key-error.js +0 -27
  120. package/src/errors/validation/unknown-config-operation-error.js +0 -24
  121. package/src/helpers/docs-url.js +0 -32
  122. package/src/helpers/pager.js +0 -59
  123. package/src/helpers/pager.test.js +0 -85
  124. package/src/helpers/suggest-similar.js +0 -124
  125. package/src/helpers/suggest-similar.test.js +0 -108
  126. package/src/helpers/test-cwd.test.js +0 -192
  127. package/src/lib/11ty/index.test.js +0 -655
  128. package/src/lib/commander/index.js +0 -103
  129. package/src/lib/commander/index.test.js +0 -86
  130. package/src/lib/commander/options.js +0 -237
  131. package/src/lib/commander/options.test.js +0 -205
  132. package/src/lib/conf/build-status.js +0 -103
  133. package/src/lib/conf/build-status.test.js +0 -247
  134. package/src/lib/conf/config.test.js +0 -281
  135. package/src/lib/conf/format.js +0 -60
  136. package/src/lib/conf/format.test.js +0 -106
  137. package/src/lib/conf/helpers.js +0 -91
  138. package/src/lib/conf/helpers.test.js +0 -136
  139. package/src/lib/conf/index.js +0 -22
  140. package/src/lib/constants.js +0 -28
  141. package/src/lib/doctor/README.md +0 -667
  142. package/src/lib/doctor/checks/environment/cli-version.js +0 -62
  143. package/src/lib/doctor/checks/environment/cli-version.test.js +0 -132
  144. package/src/lib/doctor/checks/environment/git-available.js +0 -77
  145. package/src/lib/doctor/checks/environment/git-available.test.js +0 -52
  146. package/src/lib/doctor/checks/environment/index.js +0 -13
  147. package/src/lib/doctor/checks/environment/node-version.js +0 -66
  148. package/src/lib/doctor/checks/environment/node-version.test.js +0 -17
  149. package/src/lib/doctor/checks/environment/npm-available.js +0 -66
  150. package/src/lib/doctor/checks/environment/npm-available.test.js +0 -52
  151. package/src/lib/doctor/checks/environment/os-info.js +0 -48
  152. package/src/lib/doctor/checks/environment/os-info.test.js +0 -81
  153. package/src/lib/doctor/checks/environment/runtime-info.js +0 -51
  154. package/src/lib/doctor/checks/environment/runtime-info.test.js +0 -132
  155. package/src/lib/doctor/checks/outputs/epub-output.js +0 -119
  156. package/src/lib/doctor/checks/outputs/epub-output.test.js +0 -277
  157. package/src/lib/doctor/checks/outputs/index.js +0 -10
  158. package/src/lib/doctor/checks/outputs/pdf-output.js +0 -144
  159. package/src/lib/doctor/checks/outputs/pdf-output.test.js +0 -377
  160. package/src/lib/doctor/checks/outputs/stale-build.js +0 -122
  161. package/src/lib/doctor/checks/outputs/stale-build.test.js +0 -282
  162. package/src/lib/doctor/checks/project/data-files.js +0 -56
  163. package/src/lib/doctor/checks/project/data-files.test.js +0 -125
  164. package/src/lib/doctor/checks/project/dependencies.js +0 -53
  165. package/src/lib/doctor/checks/project/dependencies.test.js +0 -71
  166. package/src/lib/doctor/checks/project/index.js +0 -11
  167. package/src/lib/doctor/checks/project/quire-11ty.js +0 -98
  168. package/src/lib/doctor/checks/project/quire-11ty.test.js +0 -170
  169. package/src/lib/doctor/checks/project/quire-project.js +0 -38
  170. package/src/lib/doctor/checks/project/quire-project.test.js +0 -47
  171. package/src/lib/doctor/checks/tools/index.js +0 -10
  172. package/src/lib/doctor/checks/tools/pandoc-available.js +0 -82
  173. package/src/lib/doctor/checks/tools/pandoc-available.test.js +0 -73
  174. package/src/lib/doctor/checks/tools/prince-available.js +0 -81
  175. package/src/lib/doctor/checks/tools/prince-available.test.js +0 -73
  176. package/src/lib/doctor/constants.js +0 -39
  177. package/src/lib/doctor/formatDuration.js +0 -108
  178. package/src/lib/doctor/formatDuration.test.js +0 -76
  179. package/src/lib/doctor/formatters/human.js +0 -257
  180. package/src/lib/doctor/formatters/human.test.js +0 -463
  181. package/src/lib/doctor/formatters/index.js +0 -8
  182. package/src/lib/doctor/formatters/json.js +0 -78
  183. package/src/lib/doctor/formatters/json.test.js +0 -174
  184. package/src/lib/doctor/formatters/shared.js +0 -129
  185. package/src/lib/doctor/formatters/shared.test.js +0 -194
  186. package/src/lib/doctor/index.js +0 -271
  187. package/src/lib/doctor/index.test.js +0 -797
  188. package/src/lib/epub/engines.js +0 -46
  189. package/src/lib/epub/index.test.js +0 -518
  190. package/src/lib/epub/pandoc.test.js +0 -122
  191. package/src/lib/epub/schema.js +0 -21
  192. package/src/lib/error/README.md +0 -170
  193. package/src/lib/error/handler.js +0 -107
  194. package/src/lib/git/index.spec.js +0 -80
  195. package/src/lib/git/index.test.js +0 -453
  196. package/src/lib/help/frontmatter.js +0 -77
  197. package/src/lib/help/frontmatter.test.js +0 -139
  198. package/src/lib/help/index.js +0 -146
  199. package/src/lib/help/index.test.js +0 -188
  200. package/src/lib/help/topics/configuration.md +0 -77
  201. package/src/lib/help/topics/debugging.md +0 -69
  202. package/src/lib/help/topics/epub.md +0 -74
  203. package/src/lib/help/topics/pdf.md +0 -74
  204. package/src/lib/help/topics/publishing.md +0 -80
  205. package/src/lib/help/topics/workflows.md +0 -50
  206. package/src/lib/installer/index.js +0 -309
  207. package/src/lib/installer/index.spec.js +0 -83
  208. package/src/lib/installer/index.test.js +0 -545
  209. package/src/lib/logger/README.md +0 -424
  210. package/src/lib/logger/debug.js +0 -132
  211. package/src/lib/logger/debug.spec.js +0 -130
  212. package/src/lib/logger/debug.test.js +0 -128
  213. package/src/lib/logger/index.js +0 -228
  214. package/src/lib/logger/index.spec.js +0 -131
  215. package/src/lib/logger/index.test.js +0 -578
  216. package/src/lib/npm/README.md +0 -127
  217. package/src/lib/npm/index.js +0 -198
  218. package/src/lib/npm/index.spec.js +0 -60
  219. package/src/lib/npm/index.test.js +0 -355
  220. package/src/lib/pdf/engines.js +0 -46
  221. package/src/lib/pdf/index.test.js +0 -708
  222. package/src/lib/pdf/paged.test.js +0 -366
  223. package/src/lib/pdf/prince.test.js +0 -202
  224. package/src/lib/pdf/schema.js +0 -21
  225. package/src/lib/pdf/split.test.js +0 -445
  226. package/src/lib/platform.js +0 -95
  227. package/src/lib/process/manager.js +0 -110
  228. package/src/lib/process/manager.test.js +0 -55
  229. package/src/lib/project/build.js +0 -162
  230. package/src/lib/project/build.test.js +0 -275
  231. package/src/lib/project/config.js +0 -48
  232. package/src/lib/project/config.test.js +0 -134
  233. package/src/lib/project/detect.js +0 -47
  234. package/src/lib/project/detect.test.js +0 -157
  235. package/src/lib/project/index.js +0 -56
  236. package/src/lib/project/output-paths.js +0 -87
  237. package/src/lib/project/output-paths.test.js +0 -66
  238. package/src/lib/project/paths.js +0 -272
  239. package/src/lib/project/version.js +0 -110
  240. package/src/lib/project/version.test.js +0 -350
  241. package/src/lib/reporter/index.test.js +0 -862
  242. package/src/main.spec.js +0 -61
  243. package/src/main.test.js +0 -347
  244. package/src/validators/validate-data-files.js +0 -154
  245. package/src/validators/validate-data-files.test.js +0 -217
@@ -1,157 +0,0 @@
1
- import test from 'ava'
2
- import { Volume, createFsFromVolume } from 'memfs'
3
- import esmock from 'esmock'
4
-
5
- test.beforeEach((t) => {
6
- // Create in-memory file system
7
- t.context.vol = new Volume()
8
- t.context.fs = createFsFromVolume(t.context.vol)
9
- })
10
-
11
- test.afterEach.always((t) => {
12
- // Clear in-memory file system
13
- t.context.vol.reset()
14
- })
15
-
16
- test('detect should recognize .eleventy.js marker file', async (t) => {
17
- const { fs, vol } = t.context
18
-
19
- // Setup a Quire project directory with .eleventy.js
20
- vol.fromJSON({
21
- '/quire-project/.eleventy.js': 'module.exports = function() {}',
22
- '/quire-project/content/_data/config.yaml': 'title: Test Project'
23
- })
24
-
25
- // Mock node:fs to use memfs
26
- const detect = await esmock('./detect.js', {
27
- 'node:fs': fs
28
- })
29
-
30
- const result = detect('/quire-project')
31
-
32
- t.truthy(result, 'should return truthy value for directory with .eleventy.js')
33
- t.is(result, '.eleventy.js', 'should return the marker file name')
34
- })
35
-
36
- test('detect should recognize eleventy.config.js marker file', async (t) => {
37
- const { fs, vol } = t.context
38
-
39
- // Setup a Quire project directory with eleventy.config.js
40
- vol.fromJSON({
41
- '/quire-project/eleventy.config.js': 'module.exports = function() {}',
42
- '/quire-project/content/_data/config.yaml': 'title: Test Project'
43
- })
44
-
45
- // Mock node:fs to use memfs
46
- const detect = await esmock('./detect.js', {
47
- 'node:fs': fs
48
- })
49
-
50
- const result = detect('/quire-project')
51
-
52
- t.truthy(result, 'should return truthy value for directory with eleventy.config.js')
53
- t.is(result, 'eleventy.config.js', 'should return the marker file name')
54
- })
55
-
56
- test('detect should recognize .quire marker file', async (t) => {
57
- const { fs, vol } = t.context
58
-
59
- // Setup a Quire project directory with .quire marker
60
- vol.fromJSON({
61
- '/quire-project/.quire': '',
62
- '/quire-project/content/index.md': '# Welcome'
63
- })
64
-
65
- // Mock node:fs to use memfs
66
- const detect = await esmock('./detect.js', {
67
- 'node:fs': fs
68
- })
69
-
70
- const result = detect('/quire-project')
71
-
72
- t.truthy(result, 'should return truthy value for directory with .quire')
73
- t.is(result, '.quire', 'should return the marker file name')
74
- })
75
-
76
- test('detect should recognize .quire-11ty marker file', async (t) => {
77
- const { fs, vol } = t.context
78
-
79
- // Setup a Quire project directory with .quire-11ty marker
80
- vol.fromJSON({
81
- '/quire-project/.quire-11ty': '',
82
- '/quire-project/content/index.md': '# Welcome'
83
- })
84
-
85
- // Mock node:fs to use memfs
86
- const detect = await esmock('./detect.js', {
87
- 'node:fs': fs
88
- })
89
-
90
- const result = detect('/quire-project')
91
-
92
- t.truthy(result, 'should return truthy value for directory with .quire-11ty')
93
- t.is(result, '.quire-11ty', 'should return the marker file name')
94
- })
95
-
96
- test('detect should recognize .quire-version marker file', async (t) => {
97
- const { fs, vol } = t.context
98
-
99
- // Setup a Quire project directory with .quire-version marker
100
- vol.fromJSON({
101
- '/quire-project/.quire-version': '1.0.0',
102
- '/quire-project/content/index.md': '# Welcome'
103
- })
104
-
105
- // Mock node:fs to use memfs
106
- const detect = await esmock('./detect.js', {
107
- 'node:fs': fs
108
- })
109
-
110
- const result = detect('/quire-project')
111
-
112
- t.truthy(result, 'should return truthy value for directory with .quire-version')
113
- t.is(result, '.quire-version', 'should return the marker file name')
114
- })
115
-
116
- test('detect should return falsy for non-Quire directory', async (t) => {
117
- const { fs, vol } = t.context
118
-
119
- // Setup a non-Quire directory (no marker files)
120
- vol.fromJSON({
121
- '/non-quire-directory/some-file.txt': 'not a quire project',
122
- '/non-quire-directory/package.json': JSON.stringify({ name: 'some-other-project' })
123
- })
124
-
125
- // Mock node:fs to use memfs
126
- const detect = await esmock('./detect.js', {
127
- 'node:fs': fs
128
- })
129
-
130
- const result = detect('/non-quire-directory')
131
-
132
- t.falsy(result, 'should return falsy value for directory without marker files')
133
- })
134
-
135
- test('detect should return first marker file found when multiple exist', async (t) => {
136
- const { fs, vol } = t.context
137
-
138
- // Setup a Quire project directory with multiple markers
139
- vol.fromJSON({
140
- '/quire-project/.eleventy.js': 'module.exports = function() {}',
141
- '/quire-project/.quire': '',
142
- '/quire-project/.quire-version': '1.0.0'
143
- })
144
-
145
- // Mock node:fs to use memfs
146
- const detect = await esmock('./detect.js', {
147
- 'node:fs': fs
148
- })
149
-
150
- const result = detect('/quire-project')
151
-
152
- t.truthy(result, 'should return truthy value for directory with multiple markers')
153
- t.true(
154
- ['.eleventy.js', '.quire', '.quire-11ty', '.quire-version', 'eleventy.config.js'].includes(result),
155
- 'should return one of the valid marker file names'
156
- )
157
- })
@@ -1,56 +0,0 @@
1
- /**
2
- * Project module
3
- *
4
- * Provides project-level concerns including paths, detection, configuration,
5
- * build status, and version management.
6
- */
7
- import paths, { DATA_DIR, Paths, REQUIRED_DATA_FILES, SOURCE_DIRECTORIES } from './paths.js'
8
- import detect, { PROJECT_MARKERS } from './detect.js'
9
- import { loadProjectConfig } from './config.js'
10
- import {
11
- getBuildInfo,
12
- hasEpubOutput,
13
- hasPdfOutput,
14
- hasSiteOutput,
15
- requireBuildOutput,
16
- } from './build.js'
17
- import {
18
- getPdfOutputPaths,
19
- getEpubOutputPaths,
20
- getEpubBuildDir,
21
- PDF_ENGINES,
22
- EPUB_ENGINES,
23
- } from './output-paths.js'
24
- import {
25
- getVersion,
26
- setVersion,
27
- getVersionsFromStarter,
28
- readVersionFile,
29
- writeVersionFile,
30
- } from './version.js'
31
-
32
- export {
33
- DATA_DIR,
34
- EPUB_ENGINES,
35
- PDF_ENGINES,
36
- PROJECT_MARKERS,
37
- REQUIRED_DATA_FILES,
38
- SOURCE_DIRECTORIES,
39
- detect,
40
- getBuildInfo,
41
- getEpubBuildDir,
42
- getEpubOutputPaths,
43
- getPdfOutputPaths,
44
- hasEpubOutput,
45
- hasPdfOutput,
46
- hasSiteOutput,
47
- loadProjectConfig,
48
- paths as default,
49
- Paths,
50
- requireBuildOutput,
51
- getVersion,
52
- setVersion,
53
- getVersionsFromStarter,
54
- readVersionFile,
55
- writeVersionFile,
56
- }
@@ -1,87 +0,0 @@
1
- /**
2
- * Output path resolution module
3
- *
4
- * Centralizes knowledge of where PDF and EPUB output files are located.
5
- * Used by the doctor command and build detection to find output artifacts
6
- * using the same logic as the generation commands.
7
- *
8
- * @module lib/project/output-paths
9
- */
10
- import path from 'node:path'
11
- import { ENGINES as PDF_ENGINES } from '#lib/pdf/schema.js'
12
- import { ENGINES as EPUB_ENGINES } from '#lib/epub/schema.js'
13
-
14
- export { PDF_ENGINES, EPUB_ENGINES }
15
-
16
- /**
17
- * Get all possible PDF output file paths for a project
18
- *
19
- * PDF output paths depend on configuration:
20
- * - With config.pdf: `{outputDir}/{config.pdf.outputDir}/{config.pdf.filename}.pdf`
21
- * - Without config (default): `{projectRoot}/{engine}.pdf`
22
- *
23
- * This reuses the same resolution logic as `lib/pdf/index.js#getOutputPath`.
24
- *
25
- * @param {Object} [options]
26
- * @param {string} [options.projectRoot=process.cwd()] - Project root directory
27
- * @param {string} [options.outputDir='_site'] - Build output directory (relative)
28
- * @param {Object} [options.pdfConfig] - PDF config from config.yaml (config.pdf)
29
- * @param {string} [options.pdfConfig.outputDir] - PDF output subdirectory
30
- * @param {string} [options.pdfConfig.filename] - PDF filename (without extension)
31
- * @returns {string[]} Array of absolute paths to check for PDF output
32
- */
33
- export function getPdfOutputPaths(options = {}) {
34
- const {
35
- projectRoot = process.cwd(),
36
- outputDir = '_site',
37
- pdfConfig,
38
- } = options
39
-
40
- const paths = []
41
-
42
- if (pdfConfig && pdfConfig.outputDir && pdfConfig.filename) {
43
- // Config-aware path: matches lib/pdf/index.js getOutputPath()
44
- paths.push(
45
- path.join(projectRoot, outputDir, pdfConfig.outputDir, `${pdfConfig.filename}.pdf`)
46
- )
47
- }
48
-
49
- // Default engine-named paths (always check these as fallback)
50
- for (const engine of PDF_ENGINES) {
51
- paths.push(path.join(projectRoot, `${engine}.pdf`))
52
- }
53
-
54
- return paths
55
- }
56
-
57
- /**
58
- * Get all possible EPUB output file paths for a project
59
- *
60
- * EPUB output is at `{projectRoot}/{engine}.epub` for each supported engine.
61
- * The `_epub` directory is an intermediate build artifact, not the final output.
62
- *
63
- * This reuses the same resolution logic as `commands/epub.js`.
64
- *
65
- * @param {Object} [options]
66
- * @param {string} [options.projectRoot=process.cwd()] - Project root directory
67
- * @returns {string[]} Array of absolute paths to check for EPUB output
68
- */
69
- export function getEpubOutputPaths(options = {}) {
70
- const { projectRoot = process.cwd() } = options
71
-
72
- return EPUB_ENGINES.map(
73
- (engine) => path.join(projectRoot, `${engine}.epub`)
74
- )
75
- }
76
-
77
- /**
78
- * Get the intermediate EPUB build directory path
79
- *
80
- * @param {Object} [options]
81
- * @param {string} [options.projectRoot=process.cwd()] - Project root directory
82
- * @returns {string} Absolute path to _epub directory
83
- */
84
- export function getEpubBuildDir(options = {}) {
85
- const { projectRoot = process.cwd() } = options
86
- return path.join(projectRoot, '_epub')
87
- }
@@ -1,66 +0,0 @@
1
- import test from 'ava'
2
- import path from 'node:path'
3
- import { getPdfOutputPaths, getEpubOutputPaths, getEpubBuildDir } from './output-paths.js'
4
-
5
- const projectRoot = '/test-project'
6
-
7
- test('getPdfOutputPaths returns default engine paths', (t) => {
8
- const paths = getPdfOutputPaths({ projectRoot })
9
-
10
- t.true(paths.includes(path.join(projectRoot, 'pagedjs.pdf')))
11
- t.true(paths.includes(path.join(projectRoot, 'prince.pdf')))
12
- })
13
-
14
- test('getPdfOutputPaths includes config-aware path when pdfConfig provided', (t) => {
15
- const pdfConfig = { outputDir: 'pdf', filename: 'my-publication' }
16
- const paths = getPdfOutputPaths({ projectRoot, outputDir: '_site', pdfConfig })
17
-
18
- // Config path should be first
19
- t.is(paths[0], path.join(projectRoot, '_site', 'pdf', 'my-publication.pdf'))
20
- // Default paths should still be present
21
- t.true(paths.includes(path.join(projectRoot, 'pagedjs.pdf')))
22
- t.true(paths.includes(path.join(projectRoot, 'prince.pdf')))
23
- })
24
-
25
- test('getPdfOutputPaths skips config path when pdfConfig is incomplete', (t) => {
26
- // Missing filename
27
- const paths = getPdfOutputPaths({ projectRoot, pdfConfig: { outputDir: 'pdf' } })
28
-
29
- // Should only have default engine paths
30
- t.is(paths.length, 2)
31
- t.true(paths.includes(path.join(projectRoot, 'pagedjs.pdf')))
32
- t.true(paths.includes(path.join(projectRoot, 'prince.pdf')))
33
- })
34
-
35
- test('getPdfOutputPaths uses cwd when no projectRoot provided', (t) => {
36
- const paths = getPdfOutputPaths()
37
-
38
- t.true(paths.includes(path.join(process.cwd(), 'pagedjs.pdf')))
39
- t.true(paths.includes(path.join(process.cwd(), 'prince.pdf')))
40
- })
41
-
42
- test('getEpubOutputPaths returns default engine paths', (t) => {
43
- const paths = getEpubOutputPaths({ projectRoot })
44
-
45
- t.true(paths.includes(path.join(projectRoot, 'epubjs.epub')))
46
- t.true(paths.includes(path.join(projectRoot, 'pandoc.epub')))
47
- })
48
-
49
- test('getEpubOutputPaths uses cwd when no projectRoot provided', (t) => {
50
- const paths = getEpubOutputPaths()
51
-
52
- t.true(paths.includes(path.join(process.cwd(), 'epubjs.epub')))
53
- t.true(paths.includes(path.join(process.cwd(), 'pandoc.epub')))
54
- })
55
-
56
- test('getEpubBuildDir returns _epub path', (t) => {
57
- const dir = getEpubBuildDir({ projectRoot })
58
-
59
- t.is(dir, path.join(projectRoot, '_epub'))
60
- })
61
-
62
- test('getEpubBuildDir uses cwd when no projectRoot provided', (t) => {
63
- const dir = getEpubBuildDir()
64
-
65
- t.is(dir, path.join(process.cwd(), '_epub'))
66
- })
@@ -1,272 +0,0 @@
1
- import { fileURLToPath } from 'node:url'
2
- import fs from 'fs-extra'
3
- import path from 'node:path'
4
-
5
- const __filename = fileURLToPath(import.meta.url)
6
- const __dirname = path.dirname(__filename)
7
-
8
- /**
9
- * Source directories that contain content for building.
10
- *
11
- * These directories are monitored for changes during preview and are used
12
- * to determine if a build is stale. Changes to files in these directories
13
- * indicate the site needs to be rebuilt.
14
- *
15
- * @constant {ReadonlyArray<string>}
16
- *
17
- * @example
18
- * // Check all source directories for changes
19
- * for (const dir of SOURCE_DIRECTORIES) {
20
- * const mtime = getLatestMtime(dir)
21
- * // ...
22
- * }
23
- */
24
- export const SOURCE_DIRECTORIES = Object.freeze([
25
- '_data',
26
- '_includes',
27
- '_layouts',
28
- 'content',
29
- 'static',
30
- ])
31
-
32
- /**
33
- * Path to data files directory (relative to project root)
34
- *
35
- * Contains YAML configuration files for the publication:
36
- * - publication.yaml - Publication metadata
37
- * - config.yaml - Site configuration
38
- * - figures.yaml - Figure definitions
39
- * - objects.yaml - Object catalog entries
40
- * - references.yaml - Bibliography entries
41
- *
42
- * @constant {string}
43
- */
44
- export const DATA_DIR = 'content/_data'
45
-
46
- /**
47
- * Required data files that must exist in a Quire project.
48
- *
49
- * These files are validated by the doctor command and the validate command.
50
- * Missing required files will trigger a warning.
51
- *
52
- * @constant {ReadonlyArray<string>}
53
- */
54
- export const REQUIRED_DATA_FILES = Object.freeze(['publication.yaml'])
55
-
56
- /**
57
- * Project path configuration
58
- *
59
- * Provides accessor methods for project paths, computing values on access
60
- * to ensure they reflect the current working directory state.
61
- *
62
- * Naming convention:
63
- * - methods ending in `Path` or `Root` return absolute paths
64
- * - methods ending in `Dir` return relative directory names
65
- *
66
- * @see https://www.11ty.dev/docs/config/#configuration-options
67
- */
68
- class Paths {
69
- /**
70
- * @param {Object} options
71
- * @param {string} [options.version='latest'] - quire-11ty version to use
72
- */
73
- constructor(options = {}) {
74
- this.cliRoot = path.resolve(__dirname, '..')
75
- this.eleventyConfig = '.eleventy.js'
76
- this.version = options.version || 'latest'
77
- }
78
-
79
- // ─────────────────────────────────────────────────────────────────────────
80
- // Implicit getters for domain-specific grouping of paths
81
- // ─────────────────────────────────────────────────────────────────────────
82
-
83
- /**
84
- * Eleventy configuration paths
85
- */
86
- get eleventy() {
87
- return {
88
- config: this.getConfigPath(),
89
- data: this.getDataDir(),
90
- includes: this.getIncludesDir(),
91
- input: this.getInputDir(),
92
- layouts: this.getLayoutsDir(),
93
- output: this.getOutputDir(),
94
- root: this.getEleventyRoot(),
95
- }
96
- }
97
-
98
- /**
99
- * Output format-specific paths
100
- */
101
- get output() {
102
- return {
103
- site: this.getOutputDir(),
104
- epub: this.getEpubDir(),
105
- public: this.getPublicDir(),
106
- }
107
- }
108
-
109
- /**
110
- * Project root paths (general)
111
- */
112
- get project() {
113
- return {
114
- content: this.getInputPath(),
115
- root: this.getProjectRoot(),
116
- }
117
- }
118
-
119
- // ─────────────────────────────────────────────────────────────────────────
120
- // Absolute paths (method names ends with Path or Root)
121
- // ─────────────────────────────────────────────────────────────────────────
122
-
123
- /**
124
- * Get the absolute path to eleventy config module
125
- * @returns {string} Absolute path to .eleventy.js
126
- */
127
- getConfigPath() {
128
- return path.join(this.getEleventyRoot(), this.eleventyConfig)
129
- }
130
-
131
- /**
132
- * Get the Eleventy root directory
133
- *
134
- * @todo refactor how and *when* the eleventyRoot is determined:
135
- * - we only need eleventyRoot for cli commands that run 11ty
136
- * - paths module is a concern of the `quire` module
137
- * - global quire-cli installation
138
- * - local quire-cli installation
139
- *
140
- * @returns {string} Absolute path to Eleventy root
141
- */
142
- getEleventyRoot() {
143
- return this.getProjectRoot()
144
- }
145
-
146
- /**
147
- * Get the absolute path to content input directory
148
- * @returns {string} Absolute path to content directory
149
- */
150
- getInputPath() {
151
- return path.join(this.getProjectRoot(), 'content')
152
- }
153
-
154
- /**
155
- * Get the path to installed quire-11ty version
156
- * @returns {string} Absolute path to quire-11ty installation
157
- */
158
- getLibQuirePath() {
159
- return path.resolve(
160
- __dirname,
161
- path.join(this.cliRoot, 'lib', 'quire', 'versions', this.version)
162
- )
163
- }
164
-
165
- /**
166
- * Get the current project root directory
167
- * @returns {string} Absolute path to project root
168
- */
169
- getProjectRoot() {
170
- return process.cwd()
171
- }
172
-
173
- // ─────────────────────────────────────────────────────────────────────────
174
- // Relative directory names (method names ends with Dir)
175
- // ─────────────────────────────────────────────────────────────────────────
176
-
177
- /**
178
- * Get data directory relative to input
179
- * @returns {string} Relative directory name for computed data
180
- */
181
- getDataDir() {
182
- return '_computed'
183
- }
184
-
185
- /**
186
- * Get epub output directory relative to eleventy config
187
- * @returns {string} Relative directory name for epub output (_epub)
188
- */
189
- getEpubDir() {
190
- return path.relative(
191
- this.getEleventyRoot(),
192
- path.join(this.getProjectRoot(), '_epub')
193
- )
194
- }
195
-
196
- /**
197
- * Get includes directory relative to input
198
- * @returns {string} Relative directory name for _includes
199
- */
200
- getIncludesDir() {
201
- return path.relative(
202
- this.getInputPath(),
203
- path.join(this.getEleventyRoot(), '_includes')
204
- )
205
- }
206
-
207
- /**
208
- * Get input directory relative to eleventy config
209
- * @returns {string} Relative directory name for 11ty input
210
- */
211
- getInputDir() {
212
- return path.relative(this.getEleventyRoot(), this.getInputPath())
213
- }
214
-
215
- /**
216
- * Get layouts directory relative to input
217
- * @returns {string} Relative directory name for _layouts
218
- */
219
- getLayoutsDir() {
220
- return path.relative(
221
- this.getInputPath(),
222
- path.join(this.getEleventyRoot(), '_layouts')
223
- )
224
- }
225
-
226
- /**
227
- * Get output directory relative to eleventy config
228
- * @returns {string} Relative directory name for 11ty output (_site)
229
- */
230
- getOutputDir() {
231
- return path.relative(
232
- this.getEleventyRoot(),
233
- path.join(this.getProjectRoot(), '_site')
234
- )
235
- }
236
-
237
- /**
238
- * Get public assets directory
239
- * @returns {string} Relative directory name for public assets
240
- */
241
- getPublicDir() {
242
- return './public'
243
- }
244
-
245
- // ─────────────────────────────────────────────────────────────────────────
246
- // Utility methods
247
- // ─────────────────────────────────────────────────────────────────────────
248
-
249
- /**
250
- * Get all paths as an object (for backward compatibility and logging)
251
- * @returns {Object} Object containing all path values
252
- */
253
- toObject() {
254
- return {
255
- config: this.getConfigPath(),
256
- data: this.getDataDir(),
257
- epub: this.getEpubDir(),
258
- includes: this.getIncludesDir(),
259
- input: this.getInputDir(),
260
- layouts: this.getLayoutsDir(),
261
- output: this.getOutputDir(),
262
- public: this.getPublicDir(),
263
- }
264
- }
265
- }
266
-
267
- /**
268
- * Default Paths instance
269
- */
270
- const paths = new Paths()
271
-
272
- export { Paths, paths as default }