vite-plugin-decap-cms 0.3.0 → 0.4.0

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/dist/index.cjs CHANGED
@@ -54,19 +54,25 @@ __export(src_exports, {
54
54
  createFile: () => createFile,
55
55
  createFileCollection: () => createFileCollection,
56
56
  createFolderCollection: () => createFolderCollection,
57
+ createOverwriteableField: () => createOverwriteableField,
58
+ createSharedCollectionOptions: () => createSharedCollectionOptions,
57
59
  default: () => VitePluginDecapCMS,
60
+ fieldToSnakeCase: () => fieldToSnakeCase,
58
61
  getGitData: () => getGitData
59
62
  });
60
63
  module.exports = __toCommonJS(src_exports);
61
- var import_child_process2 = require("child_process");
64
+
65
+ // src/update.ts
66
+ var import_promises = require("fs/promises");
67
+ var import_node_path = require("path");
62
68
  var import_yaml = require("yaml");
63
69
 
64
- // src/util.ts
65
- var import_child_process = require("child_process");
70
+ // src/utils/git.ts
71
+ var import_node_child_process = require("child_process");
66
72
  function getGitData() {
67
73
  const executeGit = (command) => {
68
74
  try {
69
- return (0, import_child_process.execSync)(command).toString("utf8").replace(/[\n\r\s]+$/, "");
75
+ return (0, import_node_child_process.execSync)(command).toString("utf8").replace(/[\n\r\s]+$/, "");
70
76
  } catch (e) {
71
77
  }
72
78
  };
@@ -79,6 +85,299 @@ function getGitData() {
79
85
  }
80
86
  };
81
87
  }
88
+
89
+ // src/utils/object.ts
90
+ var objToSnakeCase = (obj) => {
91
+ const ignoredKeys = ["i18n"];
92
+ const camelToSnakeCase = (str) => str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
93
+ return Object.fromEntries(
94
+ Object.entries(obj).map(([k, v]) => [ignoredKeys.includes(k) ? k : camelToSnakeCase(k), v])
95
+ );
96
+ };
97
+ var keyof = (obj) => Object.keys(obj);
98
+ function filterUndefined(item) {
99
+ return item != void 0;
100
+ }
101
+ function omit(obj, keys) {
102
+ if (!obj) return {};
103
+ const validEntries = Object.entries(obj).filter(([key]) => !keys.includes(key));
104
+ return Object.fromEntries(validEntries);
105
+ }
106
+ function pick(obj, keys) {
107
+ if (!obj) return {};
108
+ const validEntries = Object.entries(obj).filter(([key]) => keys.includes(key));
109
+ return Object.fromEntries(validEntries);
110
+ }
111
+
112
+ // src/files/config.ts
113
+ function getBooleanFromEnv(value, command) {
114
+ return value === "dev" ? command === "serve" : value === "prod" ? command === "build" : value != null ? value : false;
115
+ }
116
+ function resolveBackend(options, command) {
117
+ const _a = options, { local, name } = _a, backend = __objRest(_a, ["local", "name"]);
118
+ const git = getGitData();
119
+ const branch = "useCurrentBranch" in options && getBooleanFromEnv(options.useCurrentBranch, command) ? git.getBranch() : "branch" in backend ? backend.branch : void 0;
120
+ delete backend.useCurrentBranch;
121
+ const resolved = {
122
+ local_backend: typeof local === "object" ? objToSnakeCase(local) : getBooleanFromEnv(local, command),
123
+ backend: __spreadProps(__spreadValues({}, objToSnakeCase(backend)), {
124
+ branch,
125
+ name
126
+ })
127
+ };
128
+ return resolved;
129
+ }
130
+ function createConfigFile(config, command, log) {
131
+ const _a = config, { backend, collections } = _a, options = __objRest(_a, ["backend", "collections"]);
132
+ return __spreadProps(__spreadValues(__spreadValues({}, resolveBackend(backend, command)), objToSnakeCase(options)), {
133
+ collections: collections.map((col) => {
134
+ if ("fields" in col) {
135
+ const _a2 = col, { fields } = _a2, data = __objRest(_a2, ["fields"]);
136
+ return __spreadProps(__spreadValues({}, objToSnakeCase(data)), {
137
+ fields: fields.map(objToSnakeCase)
138
+ });
139
+ } else if ("files" in col) {
140
+ const _b = col, { files } = _b, data = __objRest(_b, ["files"]);
141
+ return __spreadProps(__spreadValues({}, objToSnakeCase(data)), {
142
+ files: files.map((file) => {
143
+ const _a3 = file, { fields } = _a3, _data = __objRest(_a3, ["fields"]);
144
+ return __spreadProps(__spreadValues({}, objToSnakeCase(_data)), {
145
+ fields: fields.map(objToSnakeCase)
146
+ });
147
+ })
148
+ });
149
+ } else log("config", "stderr", "Missing either fields or files property in collection");
150
+ })
151
+ });
152
+ }
153
+
154
+ // src/script.ts
155
+ function createCmsFunction(method, items, createParams, options) {
156
+ var _a;
157
+ const create = (params) => {
158
+ var _a2;
159
+ return `${(_a2 = options == null ? void 0 : options.base) != null ? _a2 : "CMS"}.${method}(${params})`;
160
+ };
161
+ return (items != null ? items : []).map((item) => {
162
+ const params = createParams(item);
163
+ if (!params) return null;
164
+ else return create(params);
165
+ }).filter(Boolean).join((_a = options == null ? void 0 : options.joinChar) != null ? _a : "\n");
166
+ }
167
+ function createScript(options) {
168
+ const _a = options, {
169
+ useManualInitialization,
170
+ markdownEditorComponents,
171
+ formatters,
172
+ previewStylesheets,
173
+ onGenerated: onGenerated,
174
+ onInitialized
175
+ } = _a, eventHooks = __objRest(_a, [
176
+ "useManualInitialization",
177
+ "markdownEditorComponents",
178
+ "formatters",
179
+ "previewStylesheets",
180
+ // previewTemplates,
181
+ // widgets,
182
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
183
+ "onGenerated",
184
+ "onInitialized"
185
+ ]);
186
+ const events = createCmsFunction("registerEventListener", Object.keys(eventHooks), (hookName) => {
187
+ const hook = eventHooks[hookName];
188
+ if (!hook) return null;
189
+ else {
190
+ const name = hookName.slice(2)[0].toLowerCase() + hookName.slice(3);
191
+ return `{ name: '${name}', handler: data => { function ${hook.toString()}; ${hookName}({ app: CMS, ...data }) } }`;
192
+ }
193
+ });
194
+ const customFormatters = createCmsFunction("registerCustomFormat", formatters, ({ name, extension, formatter }) => {
195
+ return `'${name}', '${extension}', ${formatter.toString()}`;
196
+ });
197
+ const customStyles = createCmsFunction("registerPreviewStyle", previewStylesheets, (style) => {
198
+ return typeof style === "string" ? style : `${style.style}, { raw: ${style.options.raw} }`;
199
+ });
200
+ const editorComponents = createCmsFunction("registerEditorComponent", markdownEditorComponents, (item) => {
201
+ const _a2 = item, { pattern, toPreview, toBlock, fromBlock } = _a2, component = __objRest(_a2, ["pattern", "toPreview", "toBlock", "fromBlock"]);
202
+ return `{ pattern: ${pattern}, toPreview: ${toPreview.toString()}, toBlock: ${toBlock.toString()}, fromBlock: ${fromBlock.toString()}, ...${JSON.stringify(component)}}`;
203
+ });
204
+ return `
205
+ <script>
206
+ ${useManualInitialization ? "window.CMS_MANUAL_INIT = true;" : ""}
207
+ ${onInitialized != void 0 ? `window.onload = () => { function ${onInitialized.toString()}; onInitialized({ app: CMS }) }` : ""}
208
+ ${customFormatters}
209
+ ${customStyles}
210
+ ${events}
211
+ ${editorComponents}
212
+ </script>`;
213
+ }
214
+
215
+ // src/files/index.ts
216
+ var defaultDecapCmsCdnVersion = "3.1.11";
217
+ var defaultNetlifyIdentityVersion = "1";
218
+ var addSlash = (path, slash = "/") => path.endsWith(slash) ? path : path + slash;
219
+ function resolveCdnRoute(options) {
220
+ const getUrl = (host = "https://unpkg.com/", version = defaultDecapCmsCdnVersion) => {
221
+ return `${addSlash(host)}decap-cms@^${version}/dist/decap-cms.js`;
222
+ };
223
+ return typeof options === "boolean" ? options ? getUrl() : void 0 : typeof options === "string" ? options : options != void 0 ? getUrl(options.base, options.version) : void 0;
224
+ }
225
+ function resolveHead(head) {
226
+ return head.reduce((output, config) => {
227
+ if (typeof config === "string") return output.concat(config);
228
+ if ("skip" in config) {
229
+ if (config.skip) return output;
230
+ if (typeof config.head === "string") return output.concat(config.head);
231
+ }
232
+ const item = "head" in config ? config.head : config;
233
+ let str = `<${item[0]}`;
234
+ for (const key in item[1]) {
235
+ str += ` ${key}="${item[1][key]}"`;
236
+ }
237
+ str += item[0] === "meta" ? "/>" : ">";
238
+ if (item[2] == void 0) return output.concat(str);
239
+ str += item[2] + `</${item[0]}>`;
240
+ return output.concat(str);
241
+ }, []);
242
+ }
243
+ function getIndexFeatures(config, loadOptions) {
244
+ var _a;
245
+ const configRoute = config.dir ? addSlash(config.dir) + "config.yml" : void 0;
246
+ return {
247
+ cdn_route: resolveCdnRoute(loadOptions == void 0 || loadOptions.method === "cdn" ? (_a = loadOptions == null ? void 0 : loadOptions.options) != null ? _a : true : void 0),
248
+ custom_logo: "logoUrl" in config ? config.logoUrl != void 0 : "logo_url" in config ? config.logo_url != void 0 : false,
249
+ head: (options) => {
250
+ var _a2, _b, _c;
251
+ return resolveHead([
252
+ ["meta", { charset: "utf-8" }],
253
+ ["meta", { name: "viewport", content: "width=device-width, initial-scale=1.0" }],
254
+ ["meta", { name: "robots", content: "noindex" }],
255
+ ...(_a2 = options == null ? void 0 : options.head) != null ? _a2 : [],
256
+ ["title", {}, (_b = options == null ? void 0 : options.title) != null ? _b : "Content Manager"],
257
+ {
258
+ head: ["link", { rel: "favicon", ref: (_c = options == null ? void 0 : options.icon) != null ? _c : "" }],
259
+ skip: (options == null ? void 0 : options.icon) == void 0
260
+ },
261
+ {
262
+ head: ["script", { src: `https://identity.netlify.com/v${defaultNetlifyIdentityVersion}/netlify-identity-widget.js` }],
263
+ skip: config.backend.name !== "git-gateway"
264
+ },
265
+ {
266
+ head: ["link", { type: "text/yaml", rel: "cms-config-url", href: configRoute }],
267
+ skip: configRoute == void 0
268
+ }
269
+ ]);
270
+ }
271
+ };
272
+ }
273
+ function createIndexFile(pluginOptions) {
274
+ var _a, _b;
275
+ const { config, load, login: options, script } = pluginOptions;
276
+ if (options == null ? void 0 : options.html) return options.html;
277
+ const features = getIndexFeatures(config, load);
278
+ return `<!DOCTYPE html>
279
+ <html>
280
+ <head>
281
+ ${features.head(options).join("\n" + " ".repeat(8))}
282
+ </head>
283
+ <body>
284
+ ${features.cdn_route ? `<script src="${features.cdn_route}"></script>` : ""}
285
+ ${script ? createScript(script) : ""}
286
+ ${((_a = pluginOptions.login) == null ? void 0 : _a.additionalHtml) ? `${(_b = pluginOptions.login) == null ? void 0 : _b.additionalHtml}
287
+
288
+ <div id="nc-root"></div>` : ""}
289
+ </body>
290
+ </html>${features.custom_logo ? `
291
+
292
+ <style>
293
+ span[class*='CustomIconWrapper'] {
294
+ width: auto;
295
+ }
296
+ </style>` : ""}`;
297
+ }
298
+
299
+ // src/proxy.ts
300
+ var import_node_child_process2 = require("child_process");
301
+ function runProxy(options, log) {
302
+ var _a, _b, _c, _d, _e;
303
+ const port = ((_a = options == null ? void 0 : options.port) != null ? _a : 8081).toString();
304
+ log("proxy", "debug", `Starting decap-server on port ${port}`);
305
+ const proxy = (0, import_node_child_process2.exec)("npx decap-server", __spreadProps(__spreadValues({}, (_b = options == null ? void 0 : options.process) != null ? _b : {}), {
306
+ env: __spreadValues({
307
+ PORT: port,
308
+ MODE: options == null ? void 0 : options.mode,
309
+ LOG_LEVEL: options == null ? void 0 : options.logLevel,
310
+ GIT_REPO_DIRECTORY: options == null ? void 0 : options.gitRepoDirectory
311
+ }, (_d = (_c = options == null ? void 0 : options.process) == null ? void 0 : _c.env) != null ? _d : {})
312
+ }));
313
+ if (log("proxy", "stdout")) (_e = proxy.stdout) == null ? void 0 : _e.pipe(process.stdout);
314
+ proxy.on("error", (err) => {
315
+ if ("code" in err && err.code === "EADDRINUSE") {
316
+ log("proxy", "stderr", `Port ${port} for decap-server is already used by another process`);
317
+ } else throw err;
318
+ });
319
+ process.on("beforeExit", () => proxy.kill());
320
+ }
321
+
322
+ // src/update.ts
323
+ function resolveDir(publicDir, dir) {
324
+ return dir ? (0, import_node_path.isAbsolute)(dir) ? dir : (0, import_node_path.resolve)(dir) : publicDir;
325
+ }
326
+ async function writeToFolder(folder, options) {
327
+ const dir = folder + (options.subfolder ? import_node_path.sep + options.subfolder : "");
328
+ await (0, import_promises.mkdir)(dir, { recursive: true });
329
+ for (const file of options.files.filter((f) => !f.skip)) {
330
+ await (0, import_promises.writeFile)(dir + import_node_path.sep + file.name, file.content, {
331
+ encoding: "utf-8"
332
+ });
333
+ }
334
+ }
335
+ function validateLoadOptions(options, log) {
336
+ var _a;
337
+ const valid = ["npm", "cdn"].includes((_a = options == null ? void 0 : options.method) != null ? _a : "cdn");
338
+ if (!valid) log("config", "stderr", "Invalid load options for decap-cms provided");
339
+ }
340
+ async function updateConfig(options, config, log) {
341
+ var _a, _b, _c, _d, _e, _f, _g, _h;
342
+ validateLoadOptions(options.load, log);
343
+ const configFile = createConfigFile(options.config, config.command, log);
344
+ await writeToFolder(
345
+ resolveDir(config.publicDir, options.dir),
346
+ {
347
+ subfolder: "admin",
348
+ files: [
349
+ { name: "index.html", content: createIndexFile(options) },
350
+ { name: "config.yml", content: (0, import_yaml.stringify)(configFile, (_a = options.yml) == null ? void 0 : _a.replacer, (_b = options.yml) == null ? void 0 : _b.options) }
351
+ // { name: 'npm.js', content: createCustomScript(), skip: options.load?.method !== 'npm' },
352
+ ]
353
+ }
354
+ );
355
+ if (config.command === "serve" && configFile.local_backend !== false && ((_d = (_c = options.proxy) == null ? void 0 : _c.enabled) != null ? _d : true)) {
356
+ runProxy(options.proxy, log);
357
+ }
358
+ await ((_f = (_e = options.script) == null ? void 0 : _e.onConfigUpdated) == null ? void 0 : _f.call(_e));
359
+ if (config.command === "build") {
360
+ await ((_h = (_g = options.script) == null ? void 0 : _g.onGenerated) == null ? void 0 : _h.call(_g));
361
+ }
362
+ }
363
+
364
+ // src/utils/log.ts
365
+ function createLogger(options) {
366
+ return function(type, pipe, ...data) {
367
+ if (options == void 0 || options === false) {
368
+ if (!data.length) return false;
369
+ else return;
370
+ }
371
+ if (!data.length) return true;
372
+ const fn = pipe === "stderr" ? "error" : pipe === "debug" ? "debug" : "log";
373
+ const pipeDefined = ["debug", "stdout", "stderr"].includes(pipe);
374
+ for (const msg of pipeDefined ? data : [pipe, ...data]) {
375
+ console[fn](`[Vite Decap] - [${type.toUpperCase()}] ` + msg);
376
+ }
377
+ };
378
+ }
379
+
380
+ // src/utils/collection.ts
82
381
  function createField(widget, data) {
83
382
  return __spreadProps(__spreadValues({}, data), {
84
383
  widget
@@ -93,6 +392,52 @@ function createFile(data) {
93
392
  function createFileCollection(data) {
94
393
  return data;
95
394
  }
395
+ function fieldToSnakeCase(field) {
396
+ return objToSnakeCase(field);
397
+ }
398
+ function createSharedCollectionOptions(shared, options) {
399
+ return function(collection) {
400
+ const isSharedOptions = (value) => {
401
+ return value != void 0 && typeof value === "object" && "value" in value && !("field" in value);
402
+ };
403
+ const combinedWithShared = keyof(collection).reduce((output, key) => {
404
+ var _a, _b;
405
+ const collectionValue = collection[key];
406
+ const sharedValue = shared[key];
407
+ if (sharedValue != void 0) {
408
+ if (isSharedOptions(sharedValue)) {
409
+ const sharedOptions = sharedValue;
410
+ const action = (_b = (_a = sharedOptions.action) != null ? _a : options == null ? void 0 : options.action) != null ? _b : "overwrite";
411
+ if (action === "overwrite") {
412
+ output[key] = collectionValue;
413
+ return output;
414
+ } else if (action === "append") {
415
+ if (typeof collectionValue === "string") {
416
+ output[key] = sharedOptions.value + collectionValue;
417
+ } else if (Array.isArray(collectionValue)) {
418
+ output[key] = sharedOptions.value.concat(collectionValue);
419
+ }
420
+ return output;
421
+ }
422
+ }
423
+ }
424
+ output[key] = collectionValue;
425
+ return output;
426
+ }, {});
427
+ const sharedRaw = keyof(shared).reduce((output, key) => {
428
+ const value = shared[key];
429
+ if (isSharedOptions(value)) {
430
+ output[key] = value.value;
431
+ } else {
432
+ output[key] = value;
433
+ }
434
+ return output;
435
+ }, {});
436
+ return __spreadValues(__spreadValues({}, sharedRaw), combinedWithShared);
437
+ };
438
+ }
439
+
440
+ // src/utils/overwrites.ts
96
441
  function createOverwriteableField(widget, data, overwrites) {
97
442
  if (overwrites != void 0) {
98
443
  const toAdd = (key) => {
@@ -110,13 +455,31 @@ function createOverwriteableField(widget, data, overwrites) {
110
455
  widget
111
456
  });
112
457
  }
113
- function filterUndefined(item) {
114
- return item != void 0;
115
- }
116
- function omit(obj, keys) {
117
- if (!obj) return void 0;
118
- const validEntries = Object.entries(obj).filter(([key]) => !keys.includes(key));
119
- return Object.fromEntries(validEntries);
458
+
459
+ // src/vitepress.ts
460
+ var overwriteKeys = [
461
+ "comment",
462
+ "deleted",
463
+ "hidden",
464
+ "hint",
465
+ "label",
466
+ "media_folder",
467
+ "i18n",
468
+ "pattern",
469
+ "public_folder",
470
+ "required"
471
+ ];
472
+ function mergeOverwrites(main, parent) {
473
+ var _a;
474
+ if (parent == void 0) return main != null ? main : {};
475
+ else if (main == void 0) return (_a = pick(parent != null ? parent : {}, overwriteKeys)) != null ? _a : {};
476
+ else {
477
+ return overwriteKeys.reduce((combined, key) => {
478
+ if ((main == null ? void 0 : main[key]) != void 0) combined[key] = main[key];
479
+ else if ((parent == null ? void 0 : parent[key]) != void 0) combined[key] = parent[key];
480
+ return combined;
481
+ }, {});
482
+ }
120
483
  }
121
484
  var VitePress = class {
122
485
  /**
@@ -141,59 +504,51 @@ var VitePress = class {
141
504
  createOverwriteableField("string", {
142
505
  name: "layout",
143
506
  label: "Layout",
144
- required: false,
145
- default: "doc"
146
- }),
507
+ required: false
508
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.layout, overwrites)),
147
509
  createOverwriteableField("boolean", {
148
510
  name: "navbar",
149
511
  label: "Whether to display the navbar",
150
- default: true,
151
512
  required: false
152
- }, overwrites == null ? void 0 : overwrites.navbar),
513
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.navbar, overwrites)),
153
514
  createOverwriteableField("boolean", {
154
515
  name: "sidebar",
155
516
  label: "Whether to display the sidebar",
156
- default: true,
157
517
  required: false
158
- }, overwrites == null ? void 0 : overwrites.sidebar),
518
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.sidebar, overwrites)),
159
519
  // TODO: add aside 'left' option
160
520
  createOverwriteableField("boolean", {
161
521
  name: "aside",
162
522
  label: "Whether to display the aside container",
163
- default: true,
164
523
  required: false
165
- }, overwrites == null ? void 0 : overwrites.aside),
524
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.aside, overwrites)),
166
525
  // TODO: add support for [number, number] | 'deep' | false
167
526
  createOverwriteableField("number", {
168
527
  name: "outline",
169
528
  label: "The header levels in the outline",
170
- default: 2,
171
529
  required: false
172
- }, overwrites == null ? void 0 : overwrites.outline),
530
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.outline, overwrites)),
173
531
  // TODO: add support for Date
174
532
  createOverwriteableField("boolean", {
175
533
  name: "lastUpdated",
176
534
  label: "Whether to display last updated text",
177
- default: true,
178
535
  required: false
179
- }, overwrites == null ? void 0 : overwrites.lastUpdated),
536
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.lastUpdated, overwrites)),
180
537
  createOverwriteableField("boolean", {
181
538
  name: "editLink",
182
539
  label: "Whether to display edit link text",
183
- default: true,
184
540
  required: false
185
- }, overwrites == null ? void 0 : overwrites.editLink),
541
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.editLink, overwrites)),
186
542
  createOverwriteableField("boolean", {
187
543
  name: "footer",
188
544
  label: "Whether to display footer text",
189
- default: true,
190
545
  required: false
191
- }, overwrites == null ? void 0 : overwrites.footer),
546
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.footer, overwrites)),
192
547
  createOverwriteableField("string", {
193
548
  name: "pageClass",
194
549
  label: "Page class",
195
550
  required: false
196
- }, overwrites == null ? void 0 : overwrites.pageClass)
551
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.pageClass, overwrites))
197
552
  ].filter(filterUndefined);
198
553
  }
199
554
  /**
@@ -202,36 +557,37 @@ var VitePress = class {
202
557
  * - titleTemplate
203
558
  * - description
204
559
  * - head
560
+ * - body (field for writing the markdown in the file)
205
561
  * @param options.overwrites Overwrite data, such as labels, for the fields
206
562
  * @see https://vitepress.dev/reference/frontmatter-config
207
563
  */
208
564
  static createDefaultPageFields(options) {
209
- var _a, _b;
565
+ var _a, _b, _c;
210
566
  const { additionalFields, overwrites } = options != null ? options : {};
211
567
  const fields = [
212
568
  createOverwriteableField("string", {
213
569
  name: "title",
214
570
  label: "Title"
215
- }, overwrites == null ? void 0 : overwrites.title),
571
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.title, overwrites)),
216
572
  createOverwriteableField("string", {
217
573
  name: "titleTemplate",
218
574
  label: "Title template",
219
575
  required: false
220
- }, overwrites == null ? void 0 : overwrites.titleTemplate),
576
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.titleTemplate, overwrites)),
221
577
  createOverwriteableField("text", {
222
578
  name: "description",
223
579
  label: "Description",
224
580
  required: false
225
- }, overwrites == null ? void 0 : overwrites.description),
581
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.description, overwrites)),
226
582
  createOverwriteableField("list", {
227
583
  name: "head",
228
584
  label: "Head"
229
- }, overwrites == null ? void 0 : overwrites.head)
585
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.head, overwrites))
230
586
  ].filter(filterUndefined);
231
- return fields.concat(additionalFields != null ? additionalFields : []).concat((_b = createOverwriteableField("markdown", __spreadProps(__spreadValues({}, (_a = options == null ? void 0 : options.markdownOptions) != null ? _a : {}), {
587
+ return fields.concat((_a = additionalFields == null ? void 0 : additionalFields.map(fieldToSnakeCase)) != null ? _a : []).concat((_c = createOverwriteableField("markdown", __spreadProps(__spreadValues({}, (_b = options == null ? void 0 : options.markdownOptions) != null ? _b : {}), {
232
588
  name: "body",
233
589
  label: "Page content"
234
- }), overwrites == null ? void 0 : overwrites.body)) != null ? _b : []).filter(filterUndefined);
590
+ }), mergeOverwrites(overwrites == null ? void 0 : overwrites.body, overwrites))) != null ? _c : []).filter(filterUndefined);
235
591
  }
236
592
  /**
237
593
  * Create fields for:
@@ -242,8 +598,13 @@ var VitePress = class {
242
598
  * The object fields (`features`, `hero`, `heroActions`) can not be hidden and deleted.
243
599
  */
244
600
  static createHomePageFields(options) {
601
+ var _a;
245
602
  const { overwrites } = options != null ? options : {};
246
603
  const keys = ["hidden", "deleted"];
604
+ function addAdditionalFields(fields) {
605
+ var _a2;
606
+ return (_a2 = fields == null ? void 0 : fields.map(fieldToSnakeCase)) != null ? _a2 : [];
607
+ }
247
608
  return [
248
609
  createField("hidden", {
249
610
  name: "layout",
@@ -257,19 +618,19 @@ var VitePress = class {
257
618
  createOverwriteableField("string", {
258
619
  name: "name",
259
620
  required: false
260
- }, overwrites == null ? void 0 : overwrites.heroName),
621
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.heroName, overwrites)),
261
622
  createOverwriteableField("string", {
262
623
  name: "text"
263
- }, overwrites == null ? void 0 : overwrites.heroText),
624
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.heroText, overwrites)),
264
625
  createOverwriteableField("string", {
265
626
  name: "tagline",
266
627
  required: false
267
- }, overwrites == null ? void 0 : overwrites.heroTagline),
628
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.heroTagline, overwrites)),
268
629
  // TODO: add support for object options
269
630
  createOverwriteableField("image", {
270
631
  name: "image",
271
632
  required: false
272
- }, overwrites == null ? void 0 : overwrites.heroImage),
633
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.heroImage, overwrites)),
273
634
  createOverwriteableField("list", {
274
635
  name: "actions",
275
636
  label: "Action buttons",
@@ -278,10 +639,10 @@ var VitePress = class {
278
639
  fields: [
279
640
  createOverwriteableField("string", {
280
641
  name: "text"
281
- }, overwrites == null ? void 0 : overwrites.heroActionText),
642
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.heroActionText, overwrites)),
282
643
  createOverwriteableField("string", {
283
644
  name: "link"
284
- }, overwrites == null ? void 0 : overwrites.heroActionLink),
645
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.heroActionLink, overwrites)),
285
646
  createOverwriteableField("select", {
286
647
  name: "theme",
287
648
  required: false,
@@ -290,19 +651,21 @@ var VitePress = class {
290
651
  "brand",
291
652
  "alt"
292
653
  ]
293
- }, overwrites == null ? void 0 : overwrites.heroActionTheme),
654
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.heroActionTheme, overwrites)),
294
655
  createOverwriteableField("string", {
295
656
  name: "target",
296
657
  required: false
297
- }, overwrites == null ? void 0 : overwrites.heroActionTarget),
658
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.heroActionTarget, overwrites)),
298
659
  createOverwriteableField("string", {
299
660
  name: "rel",
300
661
  required: false
301
- }, overwrites == null ? void 0 : overwrites.heroActionRel)
662
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.heroActionRel, overwrites)),
663
+ ...addAdditionalFields(options == null ? void 0 : options.additionalHeroActionFields)
302
664
  ].filter(filterUndefined)
303
- }, omit(overwrites == null ? void 0 : overwrites.heroActions, keys))
665
+ }, omit(mergeOverwrites(overwrites == null ? void 0 : overwrites.heroActions, overwrites), keys)),
666
+ ...addAdditionalFields(options == null ? void 0 : options.additionalHeroFields)
304
667
  ].filter(filterUndefined)
305
- }, omit(overwrites == null ? void 0 : overwrites.hero, keys)),
668
+ }, omit(mergeOverwrites(overwrites == null ? void 0 : overwrites.hero, overwrites), keys)),
306
669
  createOverwriteableField("list", {
307
670
  name: "features",
308
671
  label: "Features",
@@ -313,37 +676,38 @@ var VitePress = class {
313
676
  createOverwriteableField("string", {
314
677
  name: "title",
315
678
  required: true
316
- }, overwrites == null ? void 0 : overwrites.featuresTitle),
679
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.featuresTitle, overwrites)),
317
680
  createOverwriteableField("string", {
318
681
  name: "details",
319
682
  required: false
320
- }, overwrites == null ? void 0 : overwrites.featuresDetails),
683
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.featuresDetails, overwrites)),
321
684
  // TODO: add support for object options
322
685
  createOverwriteableField("string", {
323
686
  name: "icon",
324
687
  required: false
325
- }, overwrites == null ? void 0 : overwrites.featuresIcon),
688
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.featuresIcon, overwrites)),
326
689
  createOverwriteableField("string", {
327
690
  name: "link",
328
691
  required: false
329
- }, overwrites == null ? void 0 : overwrites.featuresLink),
692
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.featuresLink, overwrites)),
330
693
  createOverwriteableField("string", {
331
694
  name: "linkText",
332
695
  label: "Link text",
333
696
  required: false
334
- }, overwrites == null ? void 0 : overwrites.featuresLinkText),
697
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.featuresLinkText, overwrites)),
335
698
  createOverwriteableField("string", {
336
699
  name: "target",
337
700
  label: "Target",
338
701
  required: false
339
- }, overwrites == null ? void 0 : overwrites.featuresTarget),
702
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.featuresTarget, overwrites)),
340
703
  createOverwriteableField("string", {
341
704
  name: "rel",
342
705
  required: false
343
- }, overwrites == null ? void 0 : overwrites.featuresRel)
706
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.featuresRel, overwrites)),
707
+ ...addAdditionalFields((_a = options == null ? void 0 : options.additionalFeatureFields) != null ? _a : [])
344
708
  ].filter(filterUndefined)
345
- }, omit(overwrites == null ? void 0 : overwrites.features, keys))
346
- ];
709
+ }, omit(mergeOverwrites(overwrites == null ? void 0 : overwrites.features, overwrites), keys))
710
+ ].filter(filterUndefined);
347
711
  }
348
712
  static createDefaultPageFolderCollection(name, folder, options) {
349
713
  const _a = options != null ? options : {}, { collection } = _a, fieldsOptions = __objRest(_a, ["collection"]);
@@ -378,276 +742,20 @@ var VitePress = class {
378
742
  }
379
743
  };
380
744
 
381
- // src/files/config.ts
382
- var objToSnakeCase = (obj) => {
383
- const ignoredKeys = ["i18n"];
384
- const camelToSnakeCase = (str) => str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
385
- return Object.fromEntries(
386
- Object.entries(obj).map(([k, v]) => [ignoredKeys.includes(k) ? k : camelToSnakeCase(k), v])
387
- );
388
- };
389
- function getBooleanFromEnv(value, command) {
390
- return value === "dev" ? command === "serve" : value === "prod" ? command === "build" : value != null ? value : false;
391
- }
392
- function resolveBackend(options, command) {
393
- const _a = options, { local, name } = _a, backend = __objRest(_a, ["local", "name"]);
394
- const git = getGitData();
395
- const branch = "useCurrentBranch" in options && getBooleanFromEnv(options.useCurrentBranch, command) ? git.getBranch() : "branch" in backend ? backend.branch : void 0;
396
- delete backend.useCurrentBranch;
397
- const resolved = {
398
- local_backend: typeof local === "object" ? objToSnakeCase(local) : getBooleanFromEnv(local, command),
399
- backend: __spreadProps(__spreadValues({}, objToSnakeCase(backend)), {
400
- branch,
401
- name
402
- })
403
- };
404
- return resolved;
405
- }
406
- function createConfigFile(config, command) {
407
- const _a = config, { backend, collections } = _a, options = __objRest(_a, ["backend", "collections"]);
408
- return __spreadProps(__spreadValues(__spreadValues({}, resolveBackend(backend, command)), objToSnakeCase(options)), {
409
- collections: collections.map((col) => {
410
- if ("fields" in col) {
411
- const _a2 = col, { fields } = _a2, data = __objRest(_a2, ["fields"]);
412
- return __spreadProps(__spreadValues({}, objToSnakeCase(data)), {
413
- fields: fields.map(objToSnakeCase)
414
- });
415
- } else if ("files" in col) {
416
- const _b = col, { files } = _b, data = __objRest(_b, ["files"]);
417
- return __spreadProps(__spreadValues({}, objToSnakeCase(data)), {
418
- files: files.map((file) => {
419
- const _a3 = file, { fields } = _a3, _data = __objRest(_a3, ["fields"]);
420
- return __spreadProps(__spreadValues({}, objToSnakeCase(_data)), {
421
- fields: fields.map(objToSnakeCase)
422
- });
423
- })
424
- });
425
- } else throw new Error("Missing either fields or files property in collection");
426
- })
427
- });
428
- }
429
-
430
- // src/script.ts
431
- function createCmsFunction(method, items, createParams, options) {
432
- var _a;
433
- const create = (params) => {
434
- var _a2;
435
- return `${(_a2 = options == null ? void 0 : options.base) != null ? _a2 : "CMS"}.${method}(${params})`;
436
- };
437
- return (items != null ? items : []).map((item) => {
438
- const params = createParams(item);
439
- if (!params) return null;
440
- else return create(params);
441
- }).filter(Boolean).join((_a = options == null ? void 0 : options.joinChar) != null ? _a : "\n");
442
- }
443
- function createScript(options) {
444
- const _a = options, {
445
- useManualInitialization,
446
- markdownEditorComponents,
447
- formatters,
448
- previewStylesheets,
449
- onGenerated: onGenerated,
450
- onInitialized
451
- } = _a, eventHooks = __objRest(_a, [
452
- "useManualInitialization",
453
- "markdownEditorComponents",
454
- "formatters",
455
- "previewStylesheets",
456
- // previewTemplates,
457
- // widgets,
458
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
459
- "onGenerated",
460
- "onInitialized"
461
- ]);
462
- const events = createCmsFunction("registerEventListener", Object.keys(eventHooks), (hookName) => {
463
- const hook = eventHooks[hookName];
464
- if (!hook) return null;
465
- else {
466
- const name = hookName.slice(2)[0].toLowerCase() + hookName.slice(3);
467
- return `{ name: '${name}', handler: data => { function ${hook.toString()}; ${hookName}({ app: CMS, ...data }) } }`;
468
- }
469
- });
470
- const customFormatters = createCmsFunction("registerCustomFormat", formatters, ({ name, extension, formatter }) => {
471
- return `'${name}', '${extension}', ${formatter.toString()}`;
472
- });
473
- const customStyles = createCmsFunction("registerPreviewStyle", previewStylesheets, (style) => {
474
- return typeof style === "string" ? style : `${style.style}, { raw: ${style.options.raw} }`;
475
- });
476
- const editorComponents = createCmsFunction("registerEditorComponent", markdownEditorComponents, (item) => {
477
- const _a2 = item, { pattern, toPreview, toBlock, fromBlock } = _a2, component = __objRest(_a2, ["pattern", "toPreview", "toBlock", "fromBlock"]);
478
- return `{ pattern: ${pattern}, toPreview: ${toPreview.toString()}, toBlock: ${toBlock.toString()}, fromBlock: ${fromBlock.toString()}, ...${JSON.stringify(component)}}`;
479
- });
480
- return `
481
- <script>
482
- ${useManualInitialization ? "window.CMS_MANUAL_INIT = true;" : ""}
483
- ${onInitialized != void 0 ? `window.onload = () => { function ${onInitialized.toString()}; onInitialized({ app: CMS }) }` : ""}
484
- ${customFormatters}
485
- ${customStyles}
486
- ${events}
487
- ${editorComponents}
488
- </script>`;
489
- }
490
-
491
- // src/files/index.ts
492
- var defaultDecapCmsCdnVersion = "3.1.11";
493
- var defaultNetlifyIdentityVersion = "1";
494
- var addSlash = (path, slash = "/") => path.endsWith(slash) ? path : path + slash;
495
- function resolveCdnRoute(options) {
496
- const getUrl = (host = "https://unpkg.com/", version = defaultDecapCmsCdnVersion) => {
497
- return `${addSlash(host)}decap-cms@^${version}/dist/decap-cms.js`;
498
- };
499
- return typeof options === "boolean" ? options ? getUrl() : void 0 : typeof options === "string" ? options : options != void 0 ? getUrl(options.base, options.version) : void 0;
500
- }
501
- function resolveHead(head) {
502
- return head.reduce((output, config) => {
503
- if (typeof config === "string") return output.concat(config);
504
- if ("skip" in config) {
505
- if (config.skip) return output;
506
- if (typeof config.head === "string") return output.concat(config.head);
507
- }
508
- const item = "head" in config ? config.head : config;
509
- let str = `<${item[0]}`;
510
- for (const key in item[1]) {
511
- str += ` ${key}="${item[1][key]}"`;
512
- }
513
- str += item[0] === "meta" ? "/>" : ">";
514
- if (item[2] == void 0) return output.concat(str);
515
- str += item[2] + `</${item[0]}>`;
516
- return output.concat(str);
517
- }, []);
518
- }
519
- function getIndexFeatures(config, loadOptions) {
520
- var _a;
521
- const configRoute = config.dir ? addSlash(config.dir) + "config.yml" : void 0;
522
- return {
523
- cdn_route: resolveCdnRoute(loadOptions == void 0 || loadOptions.method === "cdn" ? (_a = loadOptions == null ? void 0 : loadOptions.options) != null ? _a : true : void 0),
524
- custom_logo: "logoUrl" in config ? config.logoUrl != void 0 : "logo_url" in config ? config.logo_url != void 0 : false,
525
- head: (options) => {
526
- var _a2, _b, _c;
527
- return resolveHead([
528
- ["meta", { charset: "utf-8" }],
529
- ["meta", { name: "viewport", content: "width=device-width, initial-scale=1.0" }],
530
- ["meta", { name: "robots", content: "noindex" }],
531
- ...(_a2 = options == null ? void 0 : options.head) != null ? _a2 : [],
532
- ["title", {}, (_b = options == null ? void 0 : options.title) != null ? _b : "Content Manager"],
533
- {
534
- head: ["link", { rel: "favicon", ref: (_c = options == null ? void 0 : options.icon) != null ? _c : "" }],
535
- skip: (options == null ? void 0 : options.icon) == void 0
536
- },
537
- {
538
- head: ["script", { src: `https://identity.netlify.com/v${defaultNetlifyIdentityVersion}/netlify-identity-widget.js` }],
539
- skip: config.backend.name !== "git-gateway"
540
- },
541
- {
542
- head: ["link", { type: "text/yaml", rel: "cms-config-url", href: configRoute }],
543
- skip: configRoute == void 0
544
- }
545
- ]);
546
- }
547
- };
548
- }
549
- function createIndexFile(pluginOptions) {
550
- var _a, _b;
551
- const { config, load, login: options, script } = pluginOptions;
552
- if (options == null ? void 0 : options.html) return options.html;
553
- const features = getIndexFeatures(config, load);
554
- return `<!DOCTYPE html>
555
- <html>
556
- <head>
557
- ${features.head(options).join("\n" + " ".repeat(8))}
558
- </head>
559
- <body>
560
- ${features.cdn_route ? `<script src="${features.cdn_route}"></script>` : ""}
561
- ${script ? createScript(script) : ""}
562
- ${((_a = pluginOptions.login) == null ? void 0 : _a.additionalHtml) ? `${(_b = pluginOptions.login) == null ? void 0 : _b.additionalHtml}
563
-
564
- <div id="nc-root"></div>` : ""}
565
- </body>
566
- </html>${features.custom_logo ? `
567
-
568
- <style>
569
- span[class*='CustomIconWrapper'] {
570
- width: auto;
571
- }
572
- </style>` : ""}`;
573
- }
574
-
575
- // src/files.ts
576
- var import_promises = require("fs/promises");
577
- var import_path = require("path");
578
- function resolveDir(publicDir, dir) {
579
- return dir ? (0, import_path.isAbsolute)(dir) ? dir : (0, import_path.resolve)(dir) : publicDir;
580
- }
581
- async function writeToFolder(folder, options) {
582
- const dir = folder + (options.subfolder ? import_path.sep + options.subfolder : "");
583
- await (0, import_promises.mkdir)(dir, { recursive: true });
584
- for (const file of options.files.filter((f) => !f.skip)) {
585
- await (0, import_promises.writeFile)(dir + import_path.sep + file.name, file.content, {
586
- encoding: "utf-8"
587
- });
588
- }
589
- }
590
-
591
745
  // src/index.ts
592
- function validateLoadOptions(options) {
593
- var _a;
594
- const valid = ["npm", "cdn"].includes((_a = options == null ? void 0 : options.method) != null ? _a : "cdn");
595
- if (!valid) throw new Error("Invalid load options for decap-cms provided");
596
- }
597
- function runProxy(options) {
598
- var _a, _b, _c, _d, _e;
599
- const proxy = (0, import_child_process2.exec)("npx decap-server", __spreadProps(__spreadValues({}, (_a = options == null ? void 0 : options.process) != null ? _a : {}), {
600
- env: __spreadProps(__spreadValues({}, (_c = (_b = options == null ? void 0 : options.process) == null ? void 0 : _b.env) != null ? _c : {}), {
601
- PORT: ((_d = options == null ? void 0 : options.port) != null ? _d : 8081).toString()
602
- })
603
- }));
604
- (_e = proxy.stdout) == null ? void 0 : _e.pipe(process.stdout);
605
- proxy.on("error", (err) => {
606
- if ("code" in err && err.code === "EADDRINUSE") {
607
- console.log("[PROXY] Port is already used");
608
- } else throw err;
609
- });
610
- process.on("beforeExit", () => proxy.kill());
611
- }
612
- async function updateConfig(options, config) {
613
- var _a, _b, _c, _d, _e, _f, _g, _h;
614
- validateLoadOptions(options.load);
615
- const loginFile = createIndexFile(options);
616
- const configFile = createConfigFile(options.config, config.command);
617
- await writeToFolder(
618
- resolveDir(config.publicDir, options.dir),
619
- {
620
- subfolder: "admin",
621
- files: [
622
- { name: "index.html", content: loginFile },
623
- { name: "config.yml", content: (0, import_yaml.stringify)(configFile, (_a = options.yml) == null ? void 0 : _a.replacer, (_b = options.yml) == null ? void 0 : _b.options) }
624
- // { name: 'npm.js', content: createCustomScript(), skip: options.load?.method !== 'npm' },
625
- ]
626
- }
627
- );
628
- if (config.command === "serve" && configFile.local_backend !== false && ((_d = (_c = options.proxy) == null ? void 0 : _c.enabled) != null ? _d : true)) {
629
- runProxy(options.proxy);
630
- }
631
- await ((_f = (_e = options.script) == null ? void 0 : _e.onConfigUpdated) == null ? void 0 : _f.call(_e));
632
- if (config.command === "build") {
633
- await ((_h = (_g = options.script) == null ? void 0 : _g.onGenerated) == null ? void 0 : _h.call(_g));
634
- }
635
- }
636
746
  function VitePluginDecapCMS(options) {
637
747
  let stored = null;
638
- const debug = (...str) => {
639
- if (options.debug) console.debug(str);
640
- };
641
748
  return {
642
749
  name: "vite-plugin-decap-cms",
643
750
  async configResolved(config) {
644
- const isUpdated = stored != null ? stored.command !== config.command || stored.publicDir !== config.publicDir : true;
645
- if (isUpdated) {
646
- await updateConfig(options, config);
751
+ const needsUpdate = stored != null ? stored.command !== config.command || stored.publicDir !== config.publicDir : true;
752
+ const log = createLogger(options.debug);
753
+ if (needsUpdate) {
754
+ await updateConfig(options, config, log);
647
755
  stored = config;
648
- debug("\nUpdated Decap CMS configuration");
756
+ log("config", "debug", "Updated Decap CMS configuration files");
649
757
  } else {
650
- debug("\nSkipped updating Decap CMS");
758
+ log("config", "debug", "Skipped updating Decap CMS configuration files");
651
759
  }
652
760
  }
653
761
  };
@@ -659,5 +767,8 @@ function VitePluginDecapCMS(options) {
659
767
  createFile,
660
768
  createFileCollection,
661
769
  createFolderCollection,
770
+ createOverwriteableField,
771
+ createSharedCollectionOptions,
772
+ fieldToSnakeCase,
662
773
  getGitData
663
774
  });