@docpensieve/core 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docpensieve/core",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "DocPensieve engine: loading, MDX compilation, structured data, site generation",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -20,7 +20,7 @@
20
20
  "types"
21
21
  ],
22
22
  "dependencies": {
23
- "@docpensieve/shared": "^0.1.0",
23
+ "@docpensieve/shared": "0.1.2",
24
24
  "@mdx-js/mdx": "^3.1.1",
25
25
  "@shikijs/rehype": "^4.4.3",
26
26
  "gray-matter": "^4.0.3",
package/src/config.js CHANGED
@@ -1,5 +1,6 @@
1
1
  /**
2
- * Loading and normalisation of `docpensieve.config.js`.
2
+ * Loading and normalisation of the configuration file,
3
+ * `docpensieve.config.mjs`.
3
4
  * @module @docpensieve/core/config
4
5
  */
5
6
 
@@ -9,6 +10,7 @@ import { pathToFileURL } from 'node:url';
9
10
 
10
11
  import {
11
12
  CONFIG_FILENAME,
13
+ CONFIG_FILENAMES,
12
14
  ConfigError,
13
15
  DEFAULT_OUT_DIR,
14
16
  NotImplementedError,
@@ -39,6 +41,7 @@ import {
39
41
  * @property {boolean} scrollToTop Back-to-top button on every page.
40
42
  * @property {{ enabled: boolean }} jsonld
41
43
  * @property {string} [rootDir] Project root, set by `loadConfig`.
44
+ * @property {string} [configFile] Path of the configuration file, set by `loadConfig`.
42
45
  * @property {string} [lang] Document language, `'en'` by default.
43
46
  */
44
47
 
@@ -215,31 +218,59 @@ export function normalizeConfig(userConfig) {
215
218
  }
216
219
 
217
220
  /**
218
- * Loads `docpensieve.config.js` from a project folder.
221
+ * Loads the configuration file of a project folder.
222
+ *
223
+ * `docpensieve.config.mjs` is looked for first, then `docpensieve.config.js`,
224
+ * which a project whose package.json declares "type": "module" can still use.
219
225
  *
220
226
  * @param {string} [cwd] Project root. Default: `process.cwd()`.
221
227
  * @returns {Promise<DocPensieveConfig>} Normalised config.
222
- * @throws {ConfigError} When the file is missing or exports no object.
228
+ * @throws {ConfigError} When no file, or two, are found, or when the file does
229
+ * not load or exports no object.
223
230
  */
224
231
  export async function loadConfig(cwd = process.cwd()) {
225
- const configPath = path.resolve(cwd, CONFIG_FILENAME);
232
+ const found = CONFIG_FILENAMES.map((name) => path.resolve(cwd, name)).filter((file) =>
233
+ existsSync(file),
234
+ );
226
235
 
227
- if (!existsSync(configPath)) {
236
+ if (found.length === 0) {
228
237
  throw new ConfigError(`No ${CONFIG_FILENAME} found in ${cwd}.`, {
229
- hint: `Create a ${CONFIG_FILENAME} at the project root.`,
238
+ hint: `Create a ${CONFIG_FILENAME} at the project root, or run "docpensieve init".`,
239
+ });
240
+ }
241
+ // Picking one silently would leave the other edited in vain.
242
+ if (found.length > 1) {
243
+ throw new ConfigError(`Two configuration files in ${cwd}: ${CONFIG_FILENAMES.join(' and ')}.`, {
244
+ hint: `Keep only one of them — ${CONFIG_FILENAME} reads the same in any project.`,
230
245
  });
231
246
  }
232
247
 
248
+ const [configPath] = found;
249
+ const name = path.basename(configPath);
250
+
233
251
  let module;
234
252
  try {
235
253
  // pathToFileURL: on Windows, a raw path is not a valid specifier.
236
254
  module = await import(pathToFileURL(configPath).href);
237
255
  } catch (cause) {
238
- throw new ConfigError(`Could not load ${CONFIG_FILENAME}.`, { cause });
256
+ // The reason is the useful part: a syntax error in the file, a missing
257
+ // module it imports. "Could not load" alone left the author guessing.
258
+ const reason = cause instanceof Error ? cause.message : String(cause);
259
+ throw new ConfigError(`Could not load ${name}: ${reason}`, {
260
+ cause,
261
+ // Node reads a .js file as an ES module only when the nearest
262
+ // package.json says so; "npm init -y" now writes "type": "commonjs",
263
+ // and "export default" then does not even parse.
264
+ hint:
265
+ name.endsWith('.js') && cause instanceof SyntaxError
266
+ ? `A .js file is read as an ES module only when the nearest package.json declares "type": "module". Rename it ${CONFIG_FILENAME}.`
267
+ : undefined,
268
+ });
239
269
  }
240
270
 
241
271
  const normalized = normalizeConfig(module.default);
242
272
  normalized.rootDir = cwd;
273
+ normalized.configFile = configPath;
243
274
  return normalized;
244
275
  }
245
276
 
package/src/loader.js CHANGED
@@ -103,7 +103,7 @@ export class DocLoader {
103
103
  } catch (cause) {
104
104
  throw new LoaderError(`Documentation folder not found: ${root}.`, {
105
105
  cause,
106
- hint: 'Check the "folder" field of the version in docpensieve.config.js.',
106
+ hint: 'Check the "folder" field of the version in the configuration file.',
107
107
  });
108
108
  }
109
109
  if (!stats.isDirectory()) {
package/types/config.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /**
2
- * Loading and normalisation of `docpensieve.config.js`.
2
+ * Loading and normalisation of the configuration file,
3
+ * `docpensieve.config.mjs`.
3
4
  * @module @docpensieve/core/config
4
5
  */
5
6
  export type Version = {
@@ -73,6 +74,10 @@ export type DocPensieveConfig = {
73
74
  * Project root, set by `loadConfig`.
74
75
  */
75
76
  rootDir?: string;
77
+ /**
78
+ * Path of the configuration file, set by `loadConfig`.
79
+ */
80
+ configFile?: string;
76
81
  /**
77
82
  * Document language, `'en'` by default.
78
83
  */
@@ -101,6 +106,7 @@ export type DocPensieveConfig = {
101
106
  * @property {boolean} scrollToTop Back-to-top button on every page.
102
107
  * @property {{ enabled: boolean }} jsonld
103
108
  * @property {string} [rootDir] Project root, set by `loadConfig`.
109
+ * @property {string} [configFile] Path of the configuration file, set by `loadConfig`.
104
110
  * @property {string} [lang] Document language, `'en'` by default.
105
111
  */
106
112
  /**
@@ -131,11 +137,15 @@ export declare function defineConfig<T>(config: T): T;
131
137
  */
132
138
  export declare function normalizeConfig(userConfig: Record<string, unknown>): DocPensieveConfig;
133
139
  /**
134
- * Loads `docpensieve.config.js` from a project folder.
140
+ * Loads the configuration file of a project folder.
141
+ *
142
+ * `docpensieve.config.mjs` is looked for first, then `docpensieve.config.js`,
143
+ * which a project whose package.json declares "type": "module" can still use.
135
144
  *
136
145
  * @param {string} [cwd] Project root. Default: `process.cwd()`.
137
146
  * @returns {Promise<DocPensieveConfig>} Normalised config.
138
- * @throws {ConfigError} When the file is missing or exports no object.
147
+ * @throws {ConfigError} When no file, or two, are found, or when the file does
148
+ * not load or exports no object.
139
149
  */
140
150
  export declare function loadConfig(cwd?: string): Promise<DocPensieveConfig>;
141
151
  /**