@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,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 }