vite-plugin-decap-cms 0.3.1 → 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
  /**
@@ -142,50 +505,50 @@ var VitePress = class {
142
505
  name: "layout",
143
506
  label: "Layout",
144
507
  required: false
145
- }),
508
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.layout, overwrites)),
146
509
  createOverwriteableField("boolean", {
147
510
  name: "navbar",
148
511
  label: "Whether to display the navbar",
149
512
  required: false
150
- }, overwrites == null ? void 0 : overwrites.navbar),
513
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.navbar, overwrites)),
151
514
  createOverwriteableField("boolean", {
152
515
  name: "sidebar",
153
516
  label: "Whether to display the sidebar",
154
517
  required: false
155
- }, overwrites == null ? void 0 : overwrites.sidebar),
518
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.sidebar, overwrites)),
156
519
  // TODO: add aside 'left' option
157
520
  createOverwriteableField("boolean", {
158
521
  name: "aside",
159
522
  label: "Whether to display the aside container",
160
523
  required: false
161
- }, overwrites == null ? void 0 : overwrites.aside),
524
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.aside, overwrites)),
162
525
  // TODO: add support for [number, number] | 'deep' | false
163
526
  createOverwriteableField("number", {
164
527
  name: "outline",
165
528
  label: "The header levels in the outline",
166
529
  required: false
167
- }, overwrites == null ? void 0 : overwrites.outline),
530
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.outline, overwrites)),
168
531
  // TODO: add support for Date
169
532
  createOverwriteableField("boolean", {
170
533
  name: "lastUpdated",
171
534
  label: "Whether to display last updated text",
172
535
  required: false
173
- }, overwrites == null ? void 0 : overwrites.lastUpdated),
536
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.lastUpdated, overwrites)),
174
537
  createOverwriteableField("boolean", {
175
538
  name: "editLink",
176
539
  label: "Whether to display edit link text",
177
540
  required: false
178
- }, overwrites == null ? void 0 : overwrites.editLink),
541
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.editLink, overwrites)),
179
542
  createOverwriteableField("boolean", {
180
543
  name: "footer",
181
544
  label: "Whether to display footer text",
182
545
  required: false
183
- }, overwrites == null ? void 0 : overwrites.footer),
546
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.footer, overwrites)),
184
547
  createOverwriteableField("string", {
185
548
  name: "pageClass",
186
549
  label: "Page class",
187
550
  required: false
188
- }, overwrites == null ? void 0 : overwrites.pageClass)
551
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.pageClass, overwrites))
189
552
  ].filter(filterUndefined);
190
553
  }
191
554
  /**
@@ -194,36 +557,37 @@ var VitePress = class {
194
557
  * - titleTemplate
195
558
  * - description
196
559
  * - head
560
+ * - body (field for writing the markdown in the file)
197
561
  * @param options.overwrites Overwrite data, such as labels, for the fields
198
562
  * @see https://vitepress.dev/reference/frontmatter-config
199
563
  */
200
564
  static createDefaultPageFields(options) {
201
- var _a, _b;
565
+ var _a, _b, _c;
202
566
  const { additionalFields, overwrites } = options != null ? options : {};
203
567
  const fields = [
204
568
  createOverwriteableField("string", {
205
569
  name: "title",
206
570
  label: "Title"
207
- }, overwrites == null ? void 0 : overwrites.title),
571
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.title, overwrites)),
208
572
  createOverwriteableField("string", {
209
573
  name: "titleTemplate",
210
574
  label: "Title template",
211
575
  required: false
212
- }, overwrites == null ? void 0 : overwrites.titleTemplate),
576
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.titleTemplate, overwrites)),
213
577
  createOverwriteableField("text", {
214
578
  name: "description",
215
579
  label: "Description",
216
580
  required: false
217
- }, overwrites == null ? void 0 : overwrites.description),
581
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.description, overwrites)),
218
582
  createOverwriteableField("list", {
219
583
  name: "head",
220
584
  label: "Head"
221
- }, overwrites == null ? void 0 : overwrites.head)
585
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.head, overwrites))
222
586
  ].filter(filterUndefined);
223
- 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 : {}), {
224
588
  name: "body",
225
589
  label: "Page content"
226
- }), overwrites == null ? void 0 : overwrites.body)) != null ? _b : []).filter(filterUndefined);
590
+ }), mergeOverwrites(overwrites == null ? void 0 : overwrites.body, overwrites))) != null ? _c : []).filter(filterUndefined);
227
591
  }
228
592
  /**
229
593
  * Create fields for:
@@ -239,7 +603,7 @@ var VitePress = class {
239
603
  const keys = ["hidden", "deleted"];
240
604
  function addAdditionalFields(fields) {
241
605
  var _a2;
242
- return (_a2 = fields == null ? void 0 : fields.map((f) => objToSnakeCase(f))) != null ? _a2 : [];
606
+ return (_a2 = fields == null ? void 0 : fields.map(fieldToSnakeCase)) != null ? _a2 : [];
243
607
  }
244
608
  return [
245
609
  createField("hidden", {
@@ -254,19 +618,19 @@ var VitePress = class {
254
618
  createOverwriteableField("string", {
255
619
  name: "name",
256
620
  required: false
257
- }, overwrites == null ? void 0 : overwrites.heroName),
621
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.heroName, overwrites)),
258
622
  createOverwriteableField("string", {
259
623
  name: "text"
260
- }, overwrites == null ? void 0 : overwrites.heroText),
624
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.heroText, overwrites)),
261
625
  createOverwriteableField("string", {
262
626
  name: "tagline",
263
627
  required: false
264
- }, overwrites == null ? void 0 : overwrites.heroTagline),
628
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.heroTagline, overwrites)),
265
629
  // TODO: add support for object options
266
630
  createOverwriteableField("image", {
267
631
  name: "image",
268
632
  required: false
269
- }, overwrites == null ? void 0 : overwrites.heroImage),
633
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.heroImage, overwrites)),
270
634
  createOverwriteableField("list", {
271
635
  name: "actions",
272
636
  label: "Action buttons",
@@ -275,10 +639,10 @@ var VitePress = class {
275
639
  fields: [
276
640
  createOverwriteableField("string", {
277
641
  name: "text"
278
- }, overwrites == null ? void 0 : overwrites.heroActionText),
642
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.heroActionText, overwrites)),
279
643
  createOverwriteableField("string", {
280
644
  name: "link"
281
- }, overwrites == null ? void 0 : overwrites.heroActionLink),
645
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.heroActionLink, overwrites)),
282
646
  createOverwriteableField("select", {
283
647
  name: "theme",
284
648
  required: false,
@@ -287,21 +651,21 @@ var VitePress = class {
287
651
  "brand",
288
652
  "alt"
289
653
  ]
290
- }, overwrites == null ? void 0 : overwrites.heroActionTheme),
654
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.heroActionTheme, overwrites)),
291
655
  createOverwriteableField("string", {
292
656
  name: "target",
293
657
  required: false
294
- }, overwrites == null ? void 0 : overwrites.heroActionTarget),
658
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.heroActionTarget, overwrites)),
295
659
  createOverwriteableField("string", {
296
660
  name: "rel",
297
661
  required: false
298
- }, overwrites == null ? void 0 : overwrites.heroActionRel),
662
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.heroActionRel, overwrites)),
299
663
  ...addAdditionalFields(options == null ? void 0 : options.additionalHeroActionFields)
300
664
  ].filter(filterUndefined)
301
- }, omit(overwrites == null ? void 0 : overwrites.heroActions, keys)),
665
+ }, omit(mergeOverwrites(overwrites == null ? void 0 : overwrites.heroActions, overwrites), keys)),
302
666
  ...addAdditionalFields(options == null ? void 0 : options.additionalHeroFields)
303
667
  ].filter(filterUndefined)
304
- }, omit(overwrites == null ? void 0 : overwrites.hero, keys)),
668
+ }, omit(mergeOverwrites(overwrites == null ? void 0 : overwrites.hero, overwrites), keys)),
305
669
  createOverwriteableField("list", {
306
670
  name: "features",
307
671
  label: "Features",
@@ -312,38 +676,38 @@ var VitePress = class {
312
676
  createOverwriteableField("string", {
313
677
  name: "title",
314
678
  required: true
315
- }, overwrites == null ? void 0 : overwrites.featuresTitle),
679
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.featuresTitle, overwrites)),
316
680
  createOverwriteableField("string", {
317
681
  name: "details",
318
682
  required: false
319
- }, overwrites == null ? void 0 : overwrites.featuresDetails),
683
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.featuresDetails, overwrites)),
320
684
  // TODO: add support for object options
321
685
  createOverwriteableField("string", {
322
686
  name: "icon",
323
687
  required: false
324
- }, overwrites == null ? void 0 : overwrites.featuresIcon),
688
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.featuresIcon, overwrites)),
325
689
  createOverwriteableField("string", {
326
690
  name: "link",
327
691
  required: false
328
- }, overwrites == null ? void 0 : overwrites.featuresLink),
692
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.featuresLink, overwrites)),
329
693
  createOverwriteableField("string", {
330
694
  name: "linkText",
331
695
  label: "Link text",
332
696
  required: false
333
- }, overwrites == null ? void 0 : overwrites.featuresLinkText),
697
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.featuresLinkText, overwrites)),
334
698
  createOverwriteableField("string", {
335
699
  name: "target",
336
700
  label: "Target",
337
701
  required: false
338
- }, overwrites == null ? void 0 : overwrites.featuresTarget),
702
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.featuresTarget, overwrites)),
339
703
  createOverwriteableField("string", {
340
704
  name: "rel",
341
705
  required: false
342
- }, overwrites == null ? void 0 : overwrites.featuresRel),
706
+ }, mergeOverwrites(overwrites == null ? void 0 : overwrites.featuresRel, overwrites)),
343
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
  });