@valbuild/core 0.102.0 → 0.105.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.
Files changed (48) hide show
  1. package/dist/declarations/src/index.d.ts +13 -11
  2. package/dist/declarations/src/initSchema.d.ts +27 -14
  3. package/dist/declarations/src/initVal.d.ts +0 -6
  4. package/dist/declarations/src/module.d.ts +1 -4
  5. package/dist/declarations/src/preview.d.ts +98 -0
  6. package/dist/declarations/src/render.d.ts +29 -93
  7. package/dist/declarations/src/schema/array.d.ts +22 -23
  8. package/dist/declarations/src/schema/boolean.d.ts +2 -2
  9. package/dist/declarations/src/schema/color.d.ts +2 -2
  10. package/dist/declarations/src/schema/date.d.ts +2 -2
  11. package/dist/declarations/src/schema/datetime.d.ts +2 -2
  12. package/dist/declarations/src/schema/file.d.ts +19 -19
  13. package/dist/declarations/src/schema/image.d.ts +17 -8
  14. package/dist/declarations/src/schema/index.d.ts +7 -7
  15. package/dist/declarations/src/schema/keyOf.d.ts +2 -2
  16. package/dist/declarations/src/schema/literal.d.ts +2 -2
  17. package/dist/declarations/src/schema/number.d.ts +2 -2
  18. package/dist/declarations/src/schema/object.d.ts +2 -2
  19. package/dist/declarations/src/schema/record.d.ts +19 -31
  20. package/dist/declarations/src/schema/remote.d.ts +0 -10
  21. package/dist/declarations/src/schema/richtext.d.ts +2 -2
  22. package/dist/declarations/src/schema/route.d.ts +2 -2
  23. package/dist/declarations/src/schema/string.d.ts +28 -17
  24. package/dist/declarations/src/schema/union.d.ts +2 -2
  25. package/dist/declarations/src/selector/SelectorProxy.d.ts +9 -2
  26. package/dist/declarations/src/selector/index.d.ts +3 -7
  27. package/dist/declarations/src/source/file.d.ts +6 -24
  28. package/dist/declarations/src/source/index.d.ts +3 -7
  29. package/dist/declarations/src/source/json.d.ts +1 -1
  30. package/dist/declarations/src/source/media.d.ts +98 -0
  31. package/dist/declarations/src/source/remote.d.ts +0 -14
  32. package/dist/declarations/src/source/richtext.d.ts +5 -7
  33. package/dist/declarations/src/val/index.d.ts +2 -5
  34. package/dist/{index-30ecb49c.cjs.dev.js → index-730a5254.cjs.dev.js} +980 -901
  35. package/dist/{index-796fd204.esm.js → index-d7cc2231.esm.js} +980 -900
  36. package/dist/{index-ca1bbeb2.cjs.prod.js → index-e990b6ad.cjs.prod.js} +980 -901
  37. package/dist/{result-4bd63123.esm.js → result-daff1cae.esm.js} +1 -1
  38. package/dist/valbuild-core.cjs.dev.js +3 -4
  39. package/dist/valbuild-core.cjs.prod.js +3 -4
  40. package/dist/valbuild-core.esm.js +2 -2
  41. package/fp/dist/valbuild-core-fp.esm.js +1 -1
  42. package/package.json +1 -1
  43. package/patch/dist/valbuild-core-patch.cjs.dev.js +1 -1
  44. package/patch/dist/valbuild-core-patch.cjs.prod.js +1 -1
  45. package/patch/dist/valbuild-core-patch.esm.js +3 -3
  46. package/dist/declarations/src/selector/file.d.ts +0 -10
  47. package/dist/declarations/src/selector/image.d.ts +0 -3
  48. package/dist/declarations/src/source/image.d.ts +0 -19
@@ -2,6 +2,46 @@
2
2
 
3
3
  var result = require('./result-787e35f6.cjs.prod.js');
4
4
 
5
+ function _arrayWithHoles(r) {
6
+ if (Array.isArray(r)) return r;
7
+ }
8
+
9
+ function _iterableToArrayLimit(r, l) {
10
+ var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
11
+ if (null != t) {
12
+ var e,
13
+ n,
14
+ i,
15
+ u,
16
+ a = [],
17
+ f = !0,
18
+ o = !1;
19
+ try {
20
+ if (i = (t = t.call(r)).next, 0 === l) {
21
+ if (Object(t) !== t) return;
22
+ f = !1;
23
+ } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
24
+ } catch (r) {
25
+ o = !0, n = r;
26
+ } finally {
27
+ try {
28
+ if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
29
+ } finally {
30
+ if (o) throw n;
31
+ }
32
+ }
33
+ return a;
34
+ }
35
+ }
36
+
37
+ function _nonIterableRest() {
38
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
39
+ }
40
+
41
+ function _slicedToArray(r, e) {
42
+ return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || result._unsupportedIterableToArray(r, e) || _nonIterableRest();
43
+ }
44
+
5
45
  function _arrayWithoutHoles(r) {
6
46
  if (Array.isArray(r)) return result._arrayLikeToArray(r);
7
47
  }
@@ -53,82 +93,69 @@ function _defineProperty(e, r, t) {
53
93
  }) : e[r] = t, e;
54
94
  }
55
95
 
56
- function ownKeys(e, r) {
57
- var t = Object.keys(e);
58
- if (Object.getOwnPropertySymbols) {
59
- var o = Object.getOwnPropertySymbols(e);
60
- r && (o = o.filter(function (r) {
61
- return Object.getOwnPropertyDescriptor(e, r).enumerable;
62
- })), t.push.apply(t, o);
63
- }
64
- return t;
96
+ function _classCallCheck(a, n) {
97
+ if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
65
98
  }
66
- function _objectSpread2(e) {
67
- for (var r = 1; r < arguments.length; r++) {
68
- var t = null != arguments[r] ? arguments[r] : {};
69
- r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
70
- _defineProperty(e, r, t[r]);
71
- }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
72
- Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
73
- });
99
+
100
+ function _defineProperties(e, r) {
101
+ for (var t = 0; t < r.length; t++) {
102
+ var o = r[t];
103
+ o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o);
74
104
  }
75
- return e;
105
+ }
106
+ function _createClass(e, r, t) {
107
+ return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", {
108
+ writable: !1
109
+ }), e;
76
110
  }
77
111
 
78
- function _arrayWithHoles(r) {
79
- if (Array.isArray(r)) return r;
112
+ function _getPrototypeOf(t) {
113
+ return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) {
114
+ return t.__proto__ || Object.getPrototypeOf(t);
115
+ }, _getPrototypeOf(t);
80
116
  }
81
117
 
82
- function _iterableToArrayLimit(r, l) {
83
- var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
84
- if (null != t) {
85
- var e,
86
- n,
87
- i,
88
- u,
89
- a = [],
90
- f = !0,
91
- o = !1;
92
- try {
93
- if (i = (t = t.call(r)).next, 0 === l) {
94
- if (Object(t) !== t) return;
95
- f = !1;
96
- } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
97
- } catch (r) {
98
- o = !0, n = r;
99
- } finally {
100
- try {
101
- if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
102
- } finally {
103
- if (o) throw n;
104
- }
105
- }
106
- return a;
107
- }
118
+ function _isNativeReflectConstruct() {
119
+ try {
120
+ var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
121
+ } catch (t) {}
122
+ return (_isNativeReflectConstruct = function () {
123
+ return !!t;
124
+ })();
108
125
  }
109
126
 
110
- function _nonIterableRest() {
111
- throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
127
+ function _assertThisInitialized(e) {
128
+ if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
129
+ return e;
112
130
  }
113
131
 
114
- function _slicedToArray(r, e) {
115
- return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || result._unsupportedIterableToArray(r, e) || _nonIterableRest();
132
+ function _possibleConstructorReturn(t, e) {
133
+ if (e && ("object" == typeof e || "function" == typeof e)) return e;
134
+ if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined");
135
+ return _assertThisInitialized(t);
116
136
  }
117
137
 
118
- function _classCallCheck(a, n) {
119
- if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
138
+ function _callSuper(t, o, e) {
139
+ return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e));
120
140
  }
121
141
 
122
- function _defineProperties(e, r) {
123
- for (var t = 0; t < r.length; t++) {
124
- var o = r[t];
125
- o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o);
126
- }
142
+ function _setPrototypeOf(t, e) {
143
+ return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) {
144
+ return t.__proto__ = e, t;
145
+ }, _setPrototypeOf(t, e);
127
146
  }
128
- function _createClass(e, r, t) {
129
- return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", {
147
+
148
+ function _inherits(t, e) {
149
+ if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function");
150
+ t.prototype = Object.create(e && e.prototype, {
151
+ constructor: {
152
+ value: t,
153
+ writable: !0,
154
+ configurable: !0
155
+ }
156
+ }), Object.defineProperty(t, "prototype", {
130
157
  writable: !1
131
- }), e;
158
+ }), e && _setPrototypeOf(t, e);
132
159
  }
133
160
 
134
161
  // import { RemoteCompatibleSource, RemoteSource } from "../source/remote";
@@ -255,55 +282,6 @@ var Schema = /*#__PURE__*/function () {
255
282
 
256
283
  // TODO: SourceError<"Could not determine type of Schema">
257
284
 
258
- function _getPrototypeOf(t) {
259
- return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) {
260
- return t.__proto__ || Object.getPrototypeOf(t);
261
- }, _getPrototypeOf(t);
262
- }
263
-
264
- function _isNativeReflectConstruct() {
265
- try {
266
- var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
267
- } catch (t) {}
268
- return (_isNativeReflectConstruct = function () {
269
- return !!t;
270
- })();
271
- }
272
-
273
- function _assertThisInitialized(e) {
274
- if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
275
- return e;
276
- }
277
-
278
- function _possibleConstructorReturn(t, e) {
279
- if (e && ("object" == typeof e || "function" == typeof e)) return e;
280
- if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined");
281
- return _assertThisInitialized(t);
282
- }
283
-
284
- function _callSuper(t, o, e) {
285
- return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e));
286
- }
287
-
288
- function _setPrototypeOf(t, e) {
289
- return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) {
290
- return t.__proto__ = e, t;
291
- }, _setPrototypeOf(t, e);
292
- }
293
-
294
- function _inherits(t, e) {
295
- if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function");
296
- t.prototype = Object.create(e && e.prototype, {
297
- constructor: {
298
- value: t,
299
- writable: !0,
300
- configurable: !0
301
- }
302
- }), Object.defineProperty(t, "prototype", {
303
- writable: !1
304
- }), e && _setPrototypeOf(t, e);
305
- }
306
-
307
285
  // Identity symbols are registered in the global Symbol registry so that
308
286
  // multiple bundled copies of @valbuild/core (e.g. the editor SPA bundle vs.
309
287
  // the host Next.js bundle) resolve to the same Symbol instance. Without
@@ -345,73 +323,6 @@ function getSchema(selector) {
345
323
  return selector[GetSchema];
346
324
  }
347
325
 
348
- /* Branded extension types: file, remote, i18n */
349
- var VAL_EXTENSION = "_type";
350
-
351
- /**
352
- * A phantom type parameter is one that doesn't show up at runtime, but is checked statically (and only) at compile time.
353
- *
354
- * An example where this is useful is remote types, where the type of the remote source is known at compile time,
355
- * but the value is not there before it is fetched.
356
- *
357
- * @example
358
- * type Example<T> = string & PhantomType<T>;
359
- *
360
- **/
361
-
362
- var FILE_REF_PROP = "_ref";
363
- var FILE_REF_SUBTYPE_TAG = "_tag"; // TODO: used earlier by c.rt.image, when we remove c.rt we can remove this
364
-
365
- /**
366
- * A file source represents the path to a (local) file.
367
- *
368
- * It will be resolved into a Asset object.
369
- *
370
- */
371
-
372
- var initFile = function initFile(config) {
373
- var _config$files$directo, _config$files;
374
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
375
- (_config$files$directo = config === null || config === void 0 || (_config$files = config.files) === null || _config$files === void 0 ? void 0 : _config$files.directory) !== null && _config$files$directo !== void 0 ? _config$files$directo : "/public/val";
376
- function file(ref, metadata) {
377
- return _defineProperty(_defineProperty(_defineProperty({}, FILE_REF_PROP, ref), VAL_EXTENSION, "file"), "metadata", metadata);
378
- }
379
- return file;
380
- };
381
-
382
- // type Directory =
383
- // | (typeof config extends { files: { directory: infer D } } ? D : never)
384
- // | `/public/val`;
385
- // console.log("path", config);
386
- // const userSpecifiedDirectory: Directory = config ?? "/public/val";
387
-
388
- // const directory = userSpecifiedDirectory;
389
-
390
- // export function file<Metadata extends { readonly [key: string]: Json }>(
391
- // ref: `${typeof directory}/${string}`,
392
- // metadata: Metadata
393
- // ): FileSource<Metadata>;
394
- // export function file(
395
- // ref: `${typeof directory}/${string}`,
396
- // metadata?: undefined
397
- // ): FileSource<undefined>;
398
- // export function file<
399
- // Metadata extends { readonly [key: string]: Json } | undefined
400
- // >(
401
- // ref: `${typeof directory}/${string}`,
402
- // metadata?: Metadata
403
- // ): FileSource<Metadata> {
404
- // return {
405
- // [FILE_REF_PROP]: ref,
406
- // [VAL_EXTENSION]: "file",
407
- // metadata,
408
- // } as FileSource<Metadata>;
409
- // }
410
-
411
- function isFile(obj) {
412
- return _typeof(obj) === "object" && obj !== null && VAL_EXTENSION in obj && obj[VAL_EXTENSION] === "file" && FILE_REF_PROP in obj && typeof obj[FILE_REF_PROP] === "string";
413
- }
414
-
415
326
  function isVal(val) {
416
327
  return _typeof(val) === "object" && val !== null && val !== undefined && Path in val && "val" in val;
417
328
  }
@@ -438,290 +349,21 @@ function isVal(val) {
438
349
  */
439
350
 
440
351
  /**
441
- * The patchId of the parent patch, or "head" if there is no parent patch.
442
- */
443
-
444
- function getValPath(valOrSelector) {
445
- return valOrSelector[Path];
446
- }
447
-
448
- var FileSchema = /*#__PURE__*/function (_Schema) {
449
- function FileSchema(options) {
450
- var _this;
451
- var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
452
- var isRemote = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
453
- var customValidateFunctions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
454
- var moduleMetadata = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
455
- var isReadonly = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
456
- var isHidden = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;
457
- var description = arguments.length > 7 ? arguments[7] : undefined;
458
- _classCallCheck(this, FileSchema);
459
- _this = _callSuper(this, FileSchema);
460
- _this.options = options;
461
- _this.opt = opt;
462
- _this.isRemote = isRemote;
463
- _this.customValidateFunctions = customValidateFunctions;
464
- _this.moduleMetadata = moduleMetadata;
465
- _this.isReadonly = isReadonly;
466
- _this.isHidden = isHidden;
467
- _this.description = description;
468
- return _this;
469
- }
470
- _inherits(FileSchema, _Schema);
471
- return _createClass(FileSchema, [{
472
- key: "describe",
473
- value: function describe(description) {
474
- return new FileSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined);
475
- }
476
- }, {
477
- key: "remote",
478
- value: function remote() {
479
- return new FileSchema(this.options, this.opt, true, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, this.isHidden, this.description);
480
- }
481
- }, {
482
- key: "validate",
483
- value: function validate(validationFunction) {
484
- return new FileSchema(this.options, this.opt, this.isRemote, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]), this.moduleMetadata, this.isReadonly, this.isHidden, this.description);
485
- }
486
- }, {
487
- key: "executeValidate",
488
- value: function executeValidate(path, src) {
489
- var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
490
- path: path
491
- });
492
- if (this.opt && (src === null || src === undefined)) {
493
- return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
494
- }
495
- if (src === null || src === undefined) {
496
- return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
497
- message: "Non-optional file was null or undefined.",
498
- value: src
499
- }]));
500
- }
501
- if (typeof src[FILE_REF_PROP] !== "string") {
502
- return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
503
- message: "File did not have a file reference string. Got: ".concat(_typeof(src[FILE_REF_PROP])),
504
- value: src
505
- }]));
506
- }
507
- if (this.isRemote && src[VAL_EXTENSION] !== "remote") {
508
- return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
509
- message: "Expected a remote file, but got a local file.",
510
- value: src,
511
- fixes: ["file:upload-remote"]
512
- }]));
513
- }
514
- if (this.isRemote && src[VAL_EXTENSION] === "remote") {
515
- return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
516
- message: "Remote file was not checked.",
517
- value: src,
518
- fixes: ["file:check-remote"]
519
- }]));
520
- }
521
- if (!this.isRemote && src[VAL_EXTENSION] === "remote") {
522
- return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
523
- message: "Expected locale file, but found remote.",
524
- value: src,
525
- fixes: ["file:download-remote"]
526
- }]));
527
- }
528
- if (src[VAL_EXTENSION] !== "file") {
529
- return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
530
- message: "File did not have the valid file extension type. Got: ".concat(src[VAL_EXTENSION]),
531
- value: src
532
- }]));
533
- }
534
- var _ref8 = this.options || {},
535
- accept = _ref8.accept;
536
- var _ref9 = src.metadata || {},
537
- mimeType = _ref9.mimeType;
538
- if (accept && mimeType && !mimeType.includes("/")) {
539
- return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
540
- message: "Invalid mime type format. Got: ".concat(mimeType),
541
- value: src
542
- }]));
543
- }
544
- if (accept && mimeType && mimeType.includes("/")) {
545
- var acceptedTypes = accept.split(",").map(function (type) {
546
- return type.trim();
547
- });
548
- var isValidMimeType = acceptedTypes.some(function (acceptedType) {
549
- if (acceptedType === "*/*") {
550
- return true;
551
- }
552
- if (acceptedType.endsWith("/*")) {
553
- var baseType = acceptedType.slice(0, -2);
554
- return mimeType.startsWith(baseType);
555
- }
556
- return acceptedType === mimeType;
557
- });
558
- if (!isValidMimeType) {
559
- return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
560
- message: "Mime type mismatch. Found '".concat(mimeType, "' but schema accepts '").concat(accept, "'"),
561
- value: src
562
- }]));
563
- }
564
- }
565
- var fileMimeType = Internal.filenameToMimeType(src[FILE_REF_PROP]);
566
- if (!fileMimeType) {
567
- return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
568
- message: "Could not determine mime type from file extension. Got: ".concat(src[FILE_REF_PROP]),
569
- value: src
570
- }]));
571
- }
572
- if (fileMimeType !== mimeType) {
573
- return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
574
- message: "Mime type and file extension not matching. Mime type is '".concat(mimeType, "' but file extension is '").concat(fileMimeType, "'"),
575
- value: src
576
- }]));
577
- }
578
- if (src.metadata) {
579
- return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
580
- message: "Found metadata, but it could not be validated. File metadata must be an object with the mimeType.",
581
- // These validation errors will have to be picked up by logic outside of this package and revalidated. Reasons: 1) we have to read files to verify the metadata, which is handled differently in different runtimes (Browser, QuickJS, Node.js); 2) we want to keep this package dependency free.
582
- value: src,
583
- fixes: ["file:check-metadata"]
584
- }]));
585
- }
586
- return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
587
- message: "Missing File metadata.",
588
- value: src,
589
- fixes: ["file:add-metadata"]
590
- }]));
591
- }
592
- }, {
593
- key: "executeAssert",
594
- value: function executeAssert(path, src) {
595
- if (this.opt && src === null) {
596
- return {
597
- success: true,
598
- data: src
599
- };
600
- }
601
- if (src === null) {
602
- return {
603
- success: false,
604
- errors: _defineProperty({}, path, [{
605
- message: "Expected 'object', got 'null'",
606
- typeError: true
607
- }])
608
- };
609
- }
610
- if (_typeof(src) !== "object") {
611
- return {
612
- success: false,
613
- errors: _defineProperty({}, path, [{
614
- message: "Expected object, got '".concat(_typeof(src), "'"),
615
- typeError: true
616
- }])
617
- };
618
- }
619
- if (!(FILE_REF_PROP in src)) {
620
- return {
621
- success: false,
622
- errors: _defineProperty({}, path, [{
623
- message: "Value of this schema must use: 'c.file' (error type: missing_ref_prop)",
624
- typeError: true
625
- }])
626
- };
627
- }
628
- if (!(VAL_EXTENSION in src && src[VAL_EXTENSION] === "file")) {
629
- return {
630
- success: false,
631
- errors: _defineProperty({}, path, [{
632
- message: "Value of this schema must use: 'c.file' (error type: missing_file_extension)",
633
- typeError: true
634
- }])
635
- };
636
- }
637
- return {
638
- success: true,
639
- data: src
640
- };
641
- }
642
- }, {
643
- key: "nullable",
644
- value: function nullable() {
645
- return new FileSchema(this.options, true, this.isRemote, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, this.isHidden, this.description);
646
- }
647
- }, {
648
- key: "readonly",
649
- value: function readonly() {
650
- return new FileSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, true, this.isHidden, this.description);
651
- }
652
- }, {
653
- key: "hidden",
654
- value: function hidden() {
655
- return new FileSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, true, this.description);
656
- }
657
- }, {
658
- key: "executeCustomValidateAt",
659
- value: function executeCustomValidateAt(path, src) {
660
- return this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
661
- path: path
662
- });
663
- }
664
- }, {
665
- key: "executeSerialize",
666
- value: function executeSerialize() {
667
- var _this$customValidateF;
668
- var modulePaths = this.moduleMetadata ? Object.keys(this.moduleMetadata) : [];
669
- return {
670
- type: "file",
671
- options: this.options,
672
- opt: this.opt,
673
- remote: this.isRemote,
674
- customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
675
- referencedModule: modulePaths.length > 0 ? modulePaths[0] : undefined,
676
- readonly: this.isReadonly,
677
- hidden: this.isHidden,
678
- description: this.description
679
- };
680
- }
681
- }, {
682
- key: "executeRender",
683
- value: function executeRender() {
684
- return {};
685
- }
686
- }]);
687
- }(Schema);
688
- var file = function file(options) {
689
- var isModule = !!options && !!Internal.getValPath(options);
690
- if (isModule) {
691
- var allModules = {};
692
- for (var _i = 0, _arr = [options]; _i < _arr.length; _i++) {
693
- var valModule = _arr[_i];
694
- var modulePath = getValPath(valModule);
695
- if (modulePath === undefined) {
696
- throw new Error("Invalid argument passed to s.file(). Expected a ValModule constructed through c.define, but got an object without a valid module path.");
697
- }
698
- allModules[modulePath] = getSource(valModule);
699
- }
700
- return new FileSchema({}, false, false, [], allModules);
701
- }
702
- return new FileSchema(options);
703
- };
704
- function convertFileSource(src) {
705
- // TODO: /public should be configurable
706
- if (!src[FILE_REF_PROP].startsWith("/public")) {
707
- return {
708
- url: src[FILE_REF_PROP] + (src.patch_id ? "?patch_id=".concat(src["patch_id"]) : ""),
709
- metadata: src.metadata
710
- };
711
- }
712
- if (src.patch_id) {
713
- return {
714
- url: "/api/val/files" + src[FILE_REF_PROP] + "?patch_id=".concat(src["patch_id"]),
715
- metadata: src.metadata
716
- };
717
- }
718
- return {
719
- url: src[FILE_REF_PROP].slice("/public".length),
720
- metadata: src.metadata
721
- };
352
+ * The patchId of the parent patch, or "head" if there is no parent patch.
353
+ */
354
+
355
+ function getValPath(valOrSelector) {
356
+ return valOrSelector[Path];
722
357
  }
723
358
 
724
- function createValPathOfItem(arrayPath, prop) {
359
+ function createValPathOfItem(
360
+ /**
361
+ * `ModuleFilePath` is accepted because the no-separator branch below is
362
+ * exactly that case: a path with no `?p=` yet gets one, and the key becomes
363
+ * the first module-path segment. Callers walking a module from its root had
364
+ * to widen the type themselves, and hand-rolled the concatenation instead.
365
+ */
366
+ arrayPath, prop) {
725
367
  if (_typeof(prop) === "symbol") {
726
368
  throw Error("Cannot create val path of array item with symbol prop: ".concat(prop.toString()));
727
369
  }
@@ -748,6 +390,28 @@ function unsafeCreateSourcePath(path, itemKey) {
748
390
  return "".concat(path).concat(Internal.ModuleFilePathSep).concat(JSON.stringify(itemKey));
749
391
  }
750
392
 
393
+ function ownKeys(e, r) {
394
+ var t = Object.keys(e);
395
+ if (Object.getOwnPropertySymbols) {
396
+ var o = Object.getOwnPropertySymbols(e);
397
+ r && (o = o.filter(function (r) {
398
+ return Object.getOwnPropertyDescriptor(e, r).enumerable;
399
+ })), t.push.apply(t, o);
400
+ }
401
+ return t;
402
+ }
403
+ function _objectSpread2(e) {
404
+ for (var r = 1; r < arguments.length; r++) {
405
+ var t = null != arguments[r] ? arguments[r] : {};
406
+ r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
407
+ _defineProperty(e, r, t[r]);
408
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
409
+ Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
410
+ });
411
+ }
412
+ return e;
413
+ }
414
+
751
415
  var StringSchema = /*#__PURE__*/function (_Schema) {
752
416
  function StringSchema(options) {
753
417
  var _this;
@@ -919,10 +583,10 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
919
583
  }, {
920
584
  key: "executeSerialize",
921
585
  value: function executeSerialize() {
922
- var _this$options4, _this$options5, _this$options6, _this$customValidateF, _this$customValidateF2;
586
+ var _this$renderInput, _this$options4, _this$options5, _this$options6, _this$customValidateF, _this$customValidateF2;
923
587
  return {
924
588
  type: "string",
925
- render: this.renderInput ? true : undefined,
589
+ render: (_this$renderInput = this.renderInput) !== null && _this$renderInput !== void 0 ? _this$renderInput : undefined,
926
590
  options: {
927
591
  maxLength: (_this$options4 = this.options) === null || _this$options4 === void 0 ? void 0 : _this$options4.maxLength,
928
592
  minLength: (_this$options5 = this.options) === null || _this$options5 === void 0 ? void 0 : _this$options5.minLength,
@@ -941,36 +605,28 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
941
605
  description: this.description
942
606
  };
943
607
  }
608
+
609
+ /**
610
+ * How this field is laid out in the editor: a textarea, or a code editor for
611
+ * the given language.
612
+ *
613
+ * Static configuration, not a callback — see `render.ts`. What a CONTAINER
614
+ * shows for its items is a `preview`, which is a different thing entirely.
615
+ */
944
616
  }, {
945
617
  key: "render",
946
618
  value: function render(input) {
947
619
  return new StringSchema(this.options, this.opt, this.isRaw, this.customValidateFunctions, input, this.isReadonly, this.isHidden, this.description);
948
620
  }
621
+
622
+ /**
623
+ * Nothing: a string has no items, so there is nothing to preview. Its layout
624
+ * is a `render`, which travels in the serialized schema instead of through
625
+ * this pipeline.
626
+ */
949
627
  }, {
950
- key: "executeRender",
951
- value: function executeRender(sourcePath, src,
952
- // Accepted and unused: a string's render is a static layout hint
953
- // (`{as:"textarea"}` / `{as:"code",language}`) with no closure behind it, so
954
- // there is nothing a scope could prune. Declared so the signature is uniform
955
- // across every schema rather than something a reader has to check.
956
- _scope) {
957
- if (this.renderInput) {
958
- if (this.renderInput.as === "code") {
959
- return _defineProperty({}, sourcePath, {
960
- status: "success",
961
- data: {
962
- layout: this.renderInput.as,
963
- language: this.renderInput.language
964
- }
965
- });
966
- }
967
- return _defineProperty({}, sourcePath, {
968
- status: "success",
969
- data: {
970
- layout: this.renderInput.as
971
- }
972
- });
973
- }
628
+ key: "executePreview",
629
+ value: function executePreview() {
974
630
  return {};
975
631
  }
976
632
  }]);
@@ -1165,8 +821,8 @@ var ObjectSchema = /*#__PURE__*/function (_Schema) {
1165
821
  };
1166
822
  }
1167
823
  }, {
1168
- key: "executeRender",
1169
- value: function executeRender(sourcePath, src, scope) {
824
+ key: "executePreview",
825
+ value: function executePreview(sourcePath, src, scope) {
1170
826
  var res = {};
1171
827
  if (src === null) {
1172
828
  return res;
@@ -1177,13 +833,13 @@ var ObjectSchema = /*#__PURE__*/function (_Schema) {
1177
833
  continue;
1178
834
  }
1179
835
  var subPath = unsafeCreateSourcePath(sourcePath, _key3);
1180
- // An object produces no render of its own, so it is pure recursion — and
836
+ // An object produces no preview of its own, so it is pure recursion — and
1181
837
  // pruning it is the whole contribution: a field deep in one branch stops
1182
- // paying for every sibling branch's renders.
838
+ // paying for every sibling branch's previews.
1183
839
  if (scope !== undefined && !scope.wantsUnder(subPath)) {
1184
840
  continue;
1185
841
  }
1186
- var itemResult = this.items[_key3]["executeRender"](subPath, itemSrc, scope);
842
+ var itemResult = this.items[_key3]["executePreview"](subPath, itemSrc, scope);
1187
843
  for (var keyS in itemResult) {
1188
844
  var _key4 = keyS;
1189
845
  res[_key4] = itemResult[_key4];
@@ -1210,7 +866,7 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
1210
866
  var isReadonly = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
1211
867
  var isHidden = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
1212
868
  var description = arguments.length > 5 ? arguments[5] : undefined;
1213
- var renderInput = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null;
869
+ var previewInput = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null;
1214
870
  _classCallCheck(this, ArraySchema);
1215
871
  _this = _callSuper(this, ArraySchema);
1216
872
  _this.item = item;
@@ -1219,19 +875,19 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
1219
875
  _this.isReadonly = isReadonly;
1220
876
  _this.isHidden = isHidden;
1221
877
  _this.description = description;
1222
- _this.renderInput = renderInput;
878
+ _this.previewInput = previewInput;
1223
879
  return _this;
1224
880
  }
1225
881
  _inherits(ArraySchema, _Schema);
1226
882
  return _createClass(ArraySchema, [{
1227
883
  key: "describe",
1228
884
  value: function describe(description) {
1229
- return new ArraySchema(this.item, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput);
885
+ return new ArraySchema(this.item, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.previewInput);
1230
886
  }
1231
887
  }, {
1232
888
  key: "validate",
1233
889
  value: function validate(validationFunction) {
1234
- return new ArraySchema(this.item, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]), this.isReadonly, this.isHidden, this.description, this.renderInput);
890
+ return new ArraySchema(this.item, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]), this.isReadonly, this.isHidden, this.description, this.previewInput);
1235
891
  }
1236
892
  }, {
1237
893
  key: "executeValidate",
@@ -1298,17 +954,17 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
1298
954
  }, {
1299
955
  key: "nullable",
1300
956
  value: function nullable() {
1301
- return new ArraySchema(this.item, true, [], this.isReadonly, this.isHidden, this.description, this.renderInput);
957
+ return new ArraySchema(this.item, true, [], this.isReadonly, this.isHidden, this.description, this.previewInput);
1302
958
  }
1303
959
  }, {
1304
960
  key: "readonly",
1305
961
  value: function readonly() {
1306
- return new ArraySchema(this.item, this.opt, this.customValidateFunctions, true, this.isHidden, this.description, this.renderInput);
962
+ return new ArraySchema(this.item, this.opt, this.customValidateFunctions, true, this.isHidden, this.description, this.previewInput);
1307
963
  }
1308
964
  }, {
1309
965
  key: "hidden",
1310
966
  value: function hidden() {
1311
- return new ArraySchema(this.item, this.opt, this.customValidateFunctions, this.isReadonly, true, this.description, this.renderInput);
967
+ return new ArraySchema(this.item, this.opt, this.customValidateFunctions, this.isReadonly, true, this.description, this.previewInput);
1312
968
  }
1313
969
  }, {
1314
970
  key: "executeCustomValidateAt",
@@ -1325,7 +981,7 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
1325
981
  type: "array",
1326
982
  item: this.item["executeSerialize"](),
1327
983
  opt: this.opt,
1328
- render: this.renderInput ? true : undefined,
984
+ preview: this.previewInput ? true : undefined,
1329
985
  customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
1330
986
  readonly: this.isReadonly,
1331
987
  hidden: this.isHidden,
@@ -1333,8 +989,8 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
1333
989
  };
1334
990
  }
1335
991
  }, {
1336
- key: "executeRender",
1337
- value: function executeRender(sourcePath, src, scope) {
992
+ key: "executePreview",
993
+ value: function executePreview(sourcePath, src, scope) {
1338
994
  var res = {};
1339
995
  if (src === null) {
1340
996
  return res;
@@ -1349,26 +1005,18 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
1349
1005
  if (scope !== undefined && !scope.wantsUnder(subPath)) {
1350
1006
  continue;
1351
1007
  }
1352
- var itemResult = this.item["executeRender"](subPath, itemSrc, scope);
1008
+ var itemResult = this.item["executePreview"](subPath, itemSrc, scope);
1353
1009
  for (var keyS in itemResult) {
1354
1010
  var _key = keyS;
1355
1011
  res[_key] = itemResult[_key];
1356
1012
  }
1357
1013
  }
1358
- if (this.renderInput) {
1359
- var _this$renderInput = this.renderInput,
1360
- select = _this$renderInput.select,
1361
- layout = _this$renderInput.as;
1362
- if (layout !== "list") {
1363
- res[sourcePath] = {
1364
- status: "error",
1365
- message: "Unknown layout type: " + layout
1366
- };
1367
- }
1014
+ if (this.previewInput) {
1015
+ var select = this.previewInput;
1368
1016
  // The whole list when the LIST is what is being shown; only the wanted
1369
- // rows when it is not. `select` is the user's closure and the real expense
1370
- // — a list view asks for the container and gets every row, a single field
1371
- // asks for its own path and costs one call.
1017
+ // rows when it is not. The user's closure is the real expense — a list
1018
+ // view asks for the container and gets every row, a single field asks for
1019
+ // its own path and costs one call.
1372
1020
  // Non-null once, as a value, rather than a boolean the compiler cannot
1373
1021
  // tie back to `scope`: no scope and a scope that wants this exact path
1374
1022
  // both mean the whole list, and anything else is a window.
@@ -1378,10 +1026,10 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
1378
1026
  if (window !== null && !window.wantsUnder(unsafeCreateSourcePath(sourcePath, index))) {
1379
1027
  continue;
1380
1028
  }
1381
- // Per ITEM, not per list, matching what `record` already does: `select`
1382
- // is user code, and one row whose data trips it up must not take out the
1383
- // whole list. Before scoping, one throwing row produced an error at the
1384
- // container and no items at all.
1029
+ // Per ITEM, not per list, matching what `record` already does: the
1030
+ // closure is user code, and one row whose data trips it up must not take
1031
+ // out the whole list. Before scoping, one throwing row produced an error
1032
+ // at the container and no items at all.
1385
1033
  try {
1386
1034
  // NB NB: display is actually defined by the user
1387
1035
  var _select = select({
@@ -1405,7 +1053,6 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
1405
1053
  res[sourcePath] = {
1406
1054
  status: "success",
1407
1055
  data: {
1408
- layout: "list",
1409
1056
  parent: "array",
1410
1057
  items: items
1411
1058
  }
@@ -1413,10 +1060,18 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
1413
1060
  }
1414
1061
  return res;
1415
1062
  }
1063
+
1064
+ /**
1065
+ * What the editor shows for each ITEM of this array: a title, and optionally a
1066
+ * subtitle and an image.
1067
+ *
1068
+ * `select` is your own code over the item's source, so it is run on demand for
1069
+ * the rows that are actually being looked at — see `PreviewScope`.
1070
+ */
1416
1071
  }, {
1417
- key: "render",
1418
- value: function render(input) {
1419
- return new ArraySchema(this.item, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, input);
1072
+ key: "preview",
1073
+ value: function preview(select) {
1074
+ return new ArraySchema(this.item, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, select);
1420
1075
  }
1421
1076
  }]);
1422
1077
  }(Schema);
@@ -1548,8 +1203,8 @@ var LiteralSchema = /*#__PURE__*/function (_Schema) {
1548
1203
  };
1549
1204
  }
1550
1205
  }, {
1551
- key: "executeRender",
1552
- value: function executeRender() {
1206
+ key: "executePreview",
1207
+ value: function executePreview() {
1553
1208
  return {};
1554
1209
  }
1555
1210
  }]);
@@ -1982,8 +1637,8 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
1982
1637
  };
1983
1638
  }
1984
1639
  }, {
1985
- key: "executeRender",
1986
- value: function executeRender(sourcePath, src, scope) {
1640
+ key: "executePreview",
1641
+ value: function executePreview(sourcePath, src, scope) {
1987
1642
  var res = {};
1988
1643
  if (src === null) {
1989
1644
  return res;
@@ -2005,7 +1660,7 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
2005
1660
  return false;
2006
1661
  });
2007
1662
  if (thisSchema) {
2008
- var itemResult = thisSchema["executeRender"](sourcePath, src, scope);
1663
+ var itemResult = thisSchema["executePreview"](sourcePath, src, scope);
2009
1664
  for (var keyS in itemResult) {
2010
1665
  var _key3 = keyS;
2011
1666
  res[_key3] = itemResult[_key3];
@@ -2032,6 +1687,170 @@ var union = function union(key) {
2032
1687
  return new UnionSchema(key, objects);
2033
1688
  };
2034
1689
 
1690
+ var RegEx = /^(https?:\/\/[^/]+)\/file\/p\/([^/]+)\/b\/([^/]+)\/v\/([^/]+)\/h\/([^/]+)\/f\/([^/]+)\/p\/(.+)$/;
1691
+ function splitRemoteRef(ref) {
1692
+ if (ref[0] === "/") {
1693
+ return {
1694
+ status: "error",
1695
+ error: "Not a remote ref: " + ref
1696
+ };
1697
+ }
1698
+ var match = ref.match(RegEx);
1699
+ if (!match) {
1700
+ return {
1701
+ status: "error",
1702
+ error: "Invalid remote ref: " + ref
1703
+ };
1704
+ }
1705
+ if (match[7].indexOf("public/") !== 0) {
1706
+ return {
1707
+ status: "error",
1708
+ error: "Invalid remote ref: " + ref
1709
+ };
1710
+ }
1711
+ if (match[7].split("/").some(function (segment) {
1712
+ return segment === "." || segment === "..";
1713
+ })) {
1714
+ return {
1715
+ status: "error",
1716
+ error: "Invalid remote ref: " + ref
1717
+ };
1718
+ }
1719
+ return {
1720
+ status: "success",
1721
+ remoteHost: match[1],
1722
+ projectId: match[2],
1723
+ bucket: match[3],
1724
+ version: match[4],
1725
+ validationHash: match[5],
1726
+ fileHash: match[6],
1727
+ filePath: match[7]
1728
+ };
1729
+ }
1730
+
1731
+ /** What must stay in frame when a page crops an image. */
1732
+
1733
+ /**
1734
+ * The authored fields of a gallery-backed image (`s.image(galleryModule)`):
1735
+ * `width`/`height`/`mimeType` live in the gallery, so they are not repeated
1736
+ * here. One place per fact.
1737
+ */
1738
+
1739
+ /**
1740
+ * The structural supertype of every media source.
1741
+ *
1742
+ * It is a named member of the `Source` / `SelectorSource` unions rather than
1743
+ * "just an object" because `SourceObject` is `{[key: string]: Source}` and
1744
+ * `Source` excludes `undefined` — an object with optional properties does not
1745
+ * satisfy it.
1746
+ */
1747
+
1748
+ /** A path is remote unless it is under `/public`. */
1749
+ function isRemoteMediaPath(path) {
1750
+ return !path.startsWith("/public");
1751
+ }
1752
+
1753
+ /**
1754
+ * Where the bytes of a media source are actually served from.
1755
+ *
1756
+ * Two states, and conflating them is the recurring bug: uncommitted bytes live
1757
+ * in the patch directory and are served by the API with the `patch_id` that put
1758
+ * them there; committed bytes live at the path itself, with `/public` stripped.
1759
+ */
1760
+ function mediaUrl(src) {
1761
+ var path = src.path;
1762
+ // TODO: /public should be configurable
1763
+ if (!isRemoteMediaPath(path)) {
1764
+ if (src.patch_id) {
1765
+ return "/api/val/files".concat(path, "?patch_id=").concat(src.patch_id);
1766
+ }
1767
+ return path.slice("/public".length);
1768
+ }
1769
+ if (src.patch_id) {
1770
+ var splitRemoteRefRes = splitRemoteRef(path);
1771
+ if (splitRemoteRefRes.status === "success") {
1772
+ return "/api/val/files/".concat(splitRemoteRefRes.filePath, "?patch_id=").concat(src.patch_id, "&remote=true&ref=").concat(encodeURIComponent(path));
1773
+ }
1774
+ // Not a remote ref either — an absolute path outside /public. Serve it as
1775
+ // written, but keep the patch id so a draft still resolves.
1776
+ return "".concat(path, "?patch_id=").concat(src.patch_id);
1777
+ }
1778
+ return path;
1779
+ }
1780
+
1781
+ /**
1782
+ * A media source plus the URL its bytes are served from.
1783
+ *
1784
+ * `url` is the only generated field: everything else the consumer sees was
1785
+ * either authored or filled in from the gallery.
1786
+ */
1787
+ function resolveMedia(src) {
1788
+ return _objectSpread2(_objectSpread2({}, src), {}, {
1789
+ url: mediaUrl(src)
1790
+ });
1791
+ }
1792
+ function isMediaSchema(schema) {
1793
+ return _typeof(schema) === "object" && schema !== null && "type" in schema && (schema.type === "image" || schema.type === "file");
1794
+ }
1795
+
1796
+ /**
1797
+ * Fill in what a gallery-backed field does not carry itself.
1798
+ *
1799
+ * `s.image(galleryModule)` stores only `{path, alt?, hotspot?}` — the
1800
+ * dimensions and mime type live in the gallery module, keyed by path. This is
1801
+ * the single implementation of that lookup; core, stega/RSC and the Studio all
1802
+ * call it rather than each rolling their own.
1803
+ *
1804
+ * `alt` is filled in too, because a gallery holds the alt text an editor typed
1805
+ * once for a file used in several places — but only when the field does not
1806
+ * have its own, so a per-image override wins. A gallery whose `alt` schema is a
1807
+ * locale record holds an object rather than a string; that is left alone rather
1808
+ * than copied into a field typed `string`, and making the override
1809
+ * locale-shaped is a separate change.
1810
+ *
1811
+ * The double lookup is load-bearing: a remote gallery keys its entries by the
1812
+ * remote URL while the file itself stays on disk under its local path.
1813
+ */
1814
+ function fillFromGallery(src, schema, getModuleSource) {
1815
+ if (!isMediaSchema(schema) || !schema.referencedModule) {
1816
+ return src;
1817
+ }
1818
+ var moduleSource = getModuleSource(schema.referencedModule);
1819
+ if (!moduleSource || _typeof(moduleSource) !== "object" || Array.isArray(moduleSource)) {
1820
+ return src;
1821
+ }
1822
+ var entries = moduleSource;
1823
+ var key = src.path in entries ? src.path : null;
1824
+ if (key === null) {
1825
+ var splitRemoteRefRes = splitRemoteRef(src.path);
1826
+ if (splitRemoteRefRes.status === "success" && splitRemoteRefRes.filePath in entries) {
1827
+ key = splitRemoteRefRes.filePath;
1828
+ }
1829
+ }
1830
+ if (key === null) {
1831
+ return src;
1832
+ }
1833
+ var entry = entries[key];
1834
+ if (!entry || _typeof(entry) !== "object" || Array.isArray(entry)) {
1835
+ return src;
1836
+ }
1837
+ var _ref = entry,
1838
+ width = _ref.width,
1839
+ height = _ref.height,
1840
+ mimeType = _ref.mimeType,
1841
+ alt = _ref.alt;
1842
+ var hasOwnAlt = typeof src.alt === "string";
1843
+ return _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, src), width !== undefined ? {
1844
+ width: width
1845
+ } : {}), height !== undefined ? {
1846
+ height: height
1847
+ } : {}), mimeType !== undefined ? {
1848
+ mimeType: mimeType
1849
+ } : {}), !hasOwnAlt && typeof alt === "string" ? {
1850
+ alt: alt
1851
+ } : {});
1852
+ }
1853
+
2035
1854
  var ImageSchema = /*#__PURE__*/function (_Schema) {
2036
1855
  function ImageSchema(options) {
2037
1856
  var _this;
@@ -2073,7 +1892,7 @@ var ImageSchema = /*#__PURE__*/function (_Schema) {
2073
1892
  }, {
2074
1893
  key: "executeValidate",
2075
1894
  value: function executeValidate(path, src) {
2076
- var _src$metadata$mimeTyp, _src$metadata;
1895
+ var _src$mimeType;
2077
1896
  var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
2078
1897
  path: path
2079
1898
  });
@@ -2086,42 +1905,68 @@ var ImageSchema = /*#__PURE__*/function (_Schema) {
2086
1905
  value: src
2087
1906
  }]));
2088
1907
  }
2089
- if (this.isRemote && src[VAL_EXTENSION] !== "remote") {
1908
+ if (typeof src.path !== "string") {
1909
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1910
+ message: "Image did not have a path string. Got: ".concat(_typeof(src.path)),
1911
+ value: src
1912
+ }]));
1913
+ }
1914
+ // Remote-ness is a property of the path, not of a marker on the value:
1915
+ // anything outside /public is remote.
1916
+ var isRemotePath = isRemoteMediaPath(src.path);
1917
+ if (this.isRemote && !isRemotePath) {
2090
1918
  return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
2091
1919
  message: "Expected a remote image, but got a local image.",
2092
1920
  value: src,
2093
1921
  fixes: ["image:upload-remote"]
2094
1922
  }]));
2095
1923
  }
2096
- if (this.isRemote && src[VAL_EXTENSION] === "remote") {
1924
+ if (this.isRemote && isRemotePath) {
2097
1925
  return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
2098
1926
  message: "Remote image was not checked.",
2099
1927
  value: src,
2100
1928
  fixes: ["image:check-remote"]
2101
1929
  }]));
2102
1930
  }
2103
- if (!this.isRemote && src[VAL_EXTENSION] === "remote") {
1931
+ if (!this.isRemote && isRemotePath) {
2104
1932
  return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
2105
- message: "Expected locale image, but found remote.",
1933
+ message: "Expected local image, but found remote.",
2106
1934
  value: src,
2107
1935
  fixes: ["image:download-remote"]
2108
1936
  }]));
2109
1937
  }
2110
- if (typeof src[FILE_REF_PROP] !== "string") {
2111
- return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
2112
- message: "Image did not have a file reference string. Got: ".concat(_typeof(src[FILE_REF_PROP])),
2113
- value: src
2114
- }]));
1938
+ if (src.hotspot !== undefined) {
1939
+ if (_typeof(src.hotspot) !== "object" || src.hotspot === null || typeof src.hotspot.x !== "number" || typeof src.hotspot.y !== "number") {
1940
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1941
+ message: "Hotspot must be an object with x and y as numbers.",
1942
+ value: src
1943
+ }]));
1944
+ }
2115
1945
  }
2116
- if (src[VAL_EXTENSION] !== "file") {
2117
- return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
2118
- message: "Image did not have the valid file extension type. Got: ".concat(src[VAL_EXTENSION]),
2119
- value: src
2120
- }]));
1946
+ var galleryEntries = this.galleryEntries();
1947
+ if (galleryEntries) {
1948
+ // The dimensions and mime type of a gallery image are stored once, in the
1949
+ // gallery. Repeating them on the field is how the two get to disagree.
1950
+ var repeated = ["width", "height", "mimeType"].filter(function (key) {
1951
+ return src[key] !== undefined;
1952
+ });
1953
+ if (repeated.length > 0) {
1954
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1955
+ message: "An image from a gallery must not carry its own ".concat(repeated.join(", "), ": ").concat(repeated.length === 1 ? "it is" : "they are", " stored in the gallery module."),
1956
+ value: src
1957
+ }]));
1958
+ }
1959
+ if (!(src.path in galleryEntries)) {
1960
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1961
+ message: "The gallery does not have an image at '".concat(src.path, "'."),
1962
+ value: src
1963
+ }]));
1964
+ }
1965
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
2121
1966
  }
2122
- var _ref8 = this.options || {},
2123
- accept = _ref8.accept;
2124
- var mimeType = (_src$metadata$mimeTyp = (_src$metadata = src.metadata) === null || _src$metadata === void 0 ? void 0 : _src$metadata.mimeType) !== null && _src$metadata$mimeTyp !== void 0 ? _src$metadata$mimeTyp : "";
1967
+ var _ref1 = this.options || {},
1968
+ accept = _ref1.accept;
1969
+ var mimeType = (_src$mimeType = src.mimeType) !== null && _src$mimeType !== void 0 ? _src$mimeType : "";
2125
1970
  if (accept && mimeType && !mimeType.includes("/")) {
2126
1971
  return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
2127
1972
  message: "Invalid mime type format. Got: '".concat(mimeType, "'"),
@@ -2151,10 +1996,10 @@ var ImageSchema = /*#__PURE__*/function (_Schema) {
2151
1996
  }]));
2152
1997
  }
2153
1998
  }
2154
- var fileMimeType = Internal.filenameToMimeType(src[FILE_REF_PROP]);
1999
+ var fileMimeType = Internal.filenameToMimeType(src.path);
2155
2000
  if (!fileMimeType) {
2156
2001
  return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
2157
- message: "Could not determine mime type from file extension. Got: ".concat(src[FILE_REF_PROP]),
2002
+ message: "Could not determine mime type from file extension. Got: ".concat(src.path),
2158
2003
  value: src,
2159
2004
  fixes: ["image:check-metadata"]
2160
2005
  }]));
@@ -2166,35 +2011,37 @@ var ImageSchema = /*#__PURE__*/function (_Schema) {
2166
2011
  fixes: ["image:check-metadata"]
2167
2012
  }]));
2168
2013
  }
2169
- if (src.metadata) {
2170
- if (src.metadata.hotspot) {
2171
- if (_typeof(src.metadata.hotspot) !== "object" || typeof src.metadata.hotspot.x !== "number" || typeof src.metadata.hotspot.y !== "number") {
2172
- return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
2173
- message: "Hotspot must be an object with x and y as numbers.",
2174
- value: src
2175
- }]));
2176
- }
2177
- }
2014
+
2015
+ // Whether the dimensions match the bytes can only be answered by reading
2016
+ // the file, which this package deliberately cannot do — so it is always
2017
+ // handed on as a fix.
2018
+ if (src.width !== undefined || src.height !== undefined || src.mimeType !== undefined) {
2178
2019
  return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
2179
- message: "Found metadata, but it could not be validated. Image metadata must be an object with the required props: width (positive number), height (positive number) and the mime type.",
2180
- // These validation errors will have to be picked up by logic outside of this package and revalidated. Reasons: 1) we have to read files to verify the metadata, which is handled differently in different runtimes (Browser, QuickJS, Node.js); 2) we want to keep this package dependency free.
2020
+ message: "Found image metadata, but it could not be validated. An image must have a width (positive number), a height (positive number) and a mime type.",
2181
2021
  value: src,
2182
2022
  fixes: ["image:check-metadata"]
2183
2023
  }]));
2184
2024
  }
2185
- var isReferencedModule = Object.keys(this.moduleMetadata).length > 0;
2186
- if (src.metadata === undefined && isReferencedModule) {
2187
- if (customValidationErrors.length === 0) {
2188
- return false;
2189
- }
2190
- return _defineProperty({}, path, _toConsumableArray(customValidationErrors));
2191
- }
2192
2025
  return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
2193
2026
  message: "Could not validate Image metadata.",
2194
2027
  value: src,
2195
2028
  fixes: ["image:add-metadata"]
2196
2029
  }]));
2197
2030
  }
2031
+
2032
+ /**
2033
+ * The entries of the gallery this field points at, or null when it is a
2034
+ * standalone field.
2035
+ */
2036
+ }, {
2037
+ key: "galleryEntries",
2038
+ value: function galleryEntries() {
2039
+ var modulePaths = Object.keys(this.moduleMetadata);
2040
+ if (modulePaths.length === 0) {
2041
+ return null;
2042
+ }
2043
+ return this.moduleMetadata[modulePaths[0]];
2044
+ }
2198
2045
  }, {
2199
2046
  key: "executeAssert",
2200
2047
  value: function executeAssert(path, src) {
@@ -2222,20 +2069,11 @@ var ImageSchema = /*#__PURE__*/function (_Schema) {
2222
2069
  }])
2223
2070
  };
2224
2071
  }
2225
- if (!(FILE_REF_PROP in src)) {
2226
- return {
2227
- success: false,
2228
- errors: _defineProperty({}, path, [{
2229
- message: "Value of this schema must use: 'c.image' (error type: missing_ref_prop)",
2230
- typeError: true
2231
- }])
2232
- };
2233
- }
2234
- if (!(VAL_EXTENSION in src && src[VAL_EXTENSION] === "file")) {
2072
+ if (!("path" in src) || typeof src.path !== "string") {
2235
2073
  return {
2236
2074
  success: false,
2237
2075
  errors: _defineProperty({}, path, [{
2238
- message: "Value of this schema must use: 'c.image' (error type: missing_file_extension)",
2076
+ message: "An image must be an object with a 'path' (error type: missing_path)",
2239
2077
  typeError: true
2240
2078
  }])
2241
2079
  };
@@ -2285,13 +2123,21 @@ var ImageSchema = /*#__PURE__*/function (_Schema) {
2285
2123
  };
2286
2124
  }
2287
2125
  }, {
2288
- key: "executeRender",
2289
- value: function executeRender() {
2126
+ key: "executePreview",
2127
+ value: function executePreview() {
2290
2128
  return {};
2291
2129
  }
2292
2130
  }]);
2293
2131
  }(Schema);
2294
- var image = function image(options) {
2132
+
2133
+ /**
2134
+ * An image picked from a gallery. Its dimensions and mime type live in the
2135
+ * gallery, so the field carries only what a person typed.
2136
+ */
2137
+
2138
+ /** An image of its own, carrying its own dimensions and mime type. */
2139
+
2140
+ function image(options) {
2295
2141
  var isModule = !!options && !!Internal.getValPath(options);
2296
2142
  if (isModule) {
2297
2143
  var allModules = {};
@@ -2306,7 +2152,7 @@ var image = function image(options) {
2306
2152
  return new ImageSchema({}, false, false, [], allModules);
2307
2153
  }
2308
2154
  return new ImageSchema(options);
2309
- };
2155
+ }
2310
2156
 
2311
2157
  var RouteSchema = /*#__PURE__*/function (_Schema) {
2312
2158
  function RouteSchema(options) {
@@ -2474,8 +2320,8 @@ var RouteSchema = /*#__PURE__*/function (_Schema) {
2474
2320
  };
2475
2321
  }
2476
2322
  }, {
2477
- key: "executeRender",
2478
- value: function executeRender() {
2323
+ key: "executePreview",
2324
+ value: function executePreview() {
2479
2325
  return {};
2480
2326
  }
2481
2327
  }]);
@@ -3033,8 +2879,8 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
3033
2879
  };
3034
2880
  }
3035
2881
  }, {
3036
- key: "executeRender",
3037
- value: function executeRender() {
2882
+ key: "executePreview",
2883
+ value: function executePreview() {
3038
2884
  return {};
3039
2885
  }
3040
2886
  }]);
@@ -3179,6 +3025,20 @@ function _asyncToGenerator(n) {
3179
3025
  };
3180
3026
  }
3181
3027
 
3028
+ /* Branded extension types: file, remote, i18n */
3029
+ var VAL_EXTENSION = "_type";
3030
+
3031
+ /**
3032
+ * A phantom type parameter is one that doesn't show up at runtime, but is checked statically (and only) at compile time.
3033
+ *
3034
+ * An example where this is useful is remote types, where the type of the remote source is known at compile time,
3035
+ * but the value is not there before it is fetched.
3036
+ *
3037
+ * @example
3038
+ * type Example<T> = string & PhantomType<T>;
3039
+ *
3040
+ **/
3041
+
3182
3042
  /**
3183
3043
  * The string used as the `_type` discriminator of a {@link JsonSource}.
3184
3044
  */
@@ -3327,47 +3187,6 @@ function _resolveJsonValues() {
3327
3187
  return _resolveJsonValues.apply(this, arguments);
3328
3188
  }
3329
3189
 
3330
- var RegEx = /^(https?:\/\/[^/]+)\/file\/p\/([^/]+)\/b\/([^/]+)\/v\/([^/]+)\/h\/([^/]+)\/f\/([^/]+)\/p\/(.+)$/;
3331
- function splitRemoteRef(ref) {
3332
- if (ref[0] === "/") {
3333
- return {
3334
- status: "error",
3335
- error: "Not a remote ref: " + ref
3336
- };
3337
- }
3338
- var match = ref.match(RegEx);
3339
- if (!match) {
3340
- return {
3341
- status: "error",
3342
- error: "Invalid remote ref: " + ref
3343
- };
3344
- }
3345
- if (match[7].indexOf("public/") !== 0) {
3346
- return {
3347
- status: "error",
3348
- error: "Invalid remote ref: " + ref
3349
- };
3350
- }
3351
- if (match[7].split("/").some(function (segment) {
3352
- return segment === "." || segment === "..";
3353
- })) {
3354
- return {
3355
- status: "error",
3356
- error: "Invalid remote ref: " + ref
3357
- };
3358
- }
3359
- return {
3360
- status: "success",
3361
- remoteHost: match[1],
3362
- projectId: match[2],
3363
- bucket: match[3],
3364
- version: match[4],
3365
- validationHash: match[5],
3366
- fileHash: match[6],
3367
- filePath: match[7]
3368
- };
3369
- }
3370
-
3371
3190
  /**
3372
3191
  * The source type of a `.jsonValues()` record: every entry value is EITHER a
3373
3192
  * lazily loaded {@link JsonSource} whose resolved content is the (loosened, see
@@ -3394,7 +3213,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
3394
3213
  var isHidden = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;
3395
3214
  var description = arguments.length > 8 ? arguments[8] : undefined;
3396
3215
  var isJsonValues = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false;
3397
- var renderInput = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : null;
3216
+ var previewInput = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : null;
3398
3217
  _classCallCheck(this, RecordSchema);
3399
3218
  _this = _callSuper(this, RecordSchema);
3400
3219
  _this.item = item;
@@ -3407,19 +3226,19 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
3407
3226
  _this.isHidden = isHidden;
3408
3227
  _this.description = description;
3409
3228
  _this.isJsonValues = isJsonValues;
3410
- _this.renderInput = renderInput;
3229
+ _this.previewInput = previewInput;
3411
3230
  return _this;
3412
3231
  }
3413
3232
  _inherits(RecordSchema, _Schema);
3414
3233
  return _createClass(RecordSchema, [{
3415
3234
  key: "describe",
3416
3235
  value: function describe(description) {
3417
- return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.isJsonValues, this.renderInput);
3236
+ return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.isJsonValues, this.previewInput);
3418
3237
  }
3419
3238
  }, {
3420
3239
  key: "validate",
3421
3240
  value: function validate(validationFunction) {
3422
- return new RecordSchema(this.item, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]), this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.renderInput);
3241
+ return new RecordSchema(this.item, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]), this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.previewInput);
3423
3242
  }
3424
3243
  }, {
3425
3244
  key: "executeValidate",
@@ -3778,29 +3597,29 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
3778
3597
  }, {
3779
3598
  key: "nullable",
3780
3599
  value: function nullable() {
3781
- return new RecordSchema(this.item, true, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.renderInput);
3600
+ return new RecordSchema(this.item, true, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.previewInput);
3782
3601
  }
3783
3602
  }, {
3784
3603
  key: "readonly",
3785
3604
  value: function readonly() {
3786
- return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, true, this.isHidden, this.description, this.isJsonValues, this.renderInput);
3605
+ return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, true, this.isHidden, this.description, this.isJsonValues, this.previewInput);
3787
3606
  }
3788
3607
  }, {
3789
3608
  key: "hidden",
3790
3609
  value: function hidden() {
3791
- return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, true, this.description, this.isJsonValues, this.renderInput);
3610
+ return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, true, this.description, this.isJsonValues, this.previewInput);
3792
3611
  }
3793
3612
  }, {
3794
3613
  key: "router",
3795
3614
  value: function router(_router) {
3796
- return new RecordSchema(this.item, this.opt, this.customValidateFunctions, _router, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.renderInput);
3615
+ return new RecordSchema(this.item, this.opt, this.customValidateFunctions, _router, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.previewInput);
3797
3616
  }
3798
3617
  }, {
3799
3618
  key: "remote",
3800
3619
  value: function remote() {
3801
3620
  return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions ? _objectSpread2(_objectSpread2({}, this.mediaOptions), {}, {
3802
3621
  remote: true
3803
- }) : undefined, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.renderInput);
3622
+ }) : undefined, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.previewInput);
3804
3623
  }
3805
3624
 
3806
3625
  /**
@@ -3832,7 +3651,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
3832
3651
  }
3833
3652
  return new RecordSchema(this.item, this.opt,
3834
3653
  // Empty by construction: the guard above rejects any that were registered.
3835
- [], this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, true, this.renderInput);
3654
+ [], this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, true, this.previewInput);
3836
3655
  }
3837
3656
  }, {
3838
3657
  key: "getRouterValidations",
@@ -3892,7 +3711,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
3892
3711
  item: this.item["executeSerialize"](),
3893
3712
  key: (_this$keySchema = this.keySchema) === null || _this$keySchema === void 0 ? void 0 : _this$keySchema["executeSerialize"](),
3894
3713
  opt: this.opt,
3895
- render: this.renderInput ? true : undefined,
3714
+ preview: this.previewInput ? true : undefined,
3896
3715
  router: (_this$currentRouter = this.currentRouter) === null || _this$currentRouter === void 0 ? void 0 : _this$currentRouter.getRouterId(),
3897
3716
  customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
3898
3717
  jsonValues: this.isJsonValues ? true : undefined,
@@ -3924,8 +3743,8 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
3924
3743
  return this.item["executeValidate"](path, content);
3925
3744
  }
3926
3745
  }, {
3927
- key: "executeRender",
3928
- value: function executeRender(sourcePath, src, scope) {
3746
+ key: "executePreview",
3747
+ value: function executePreview(sourcePath, src, scope) {
3929
3748
  var res = {};
3930
3749
  if (src === null) {
3931
3750
  return res;
@@ -3937,31 +3756,23 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
3937
3756
  }
3938
3757
  if (isJson(itemSrc)) {
3939
3758
  // An un-loaded `.jsonValues()` entry: an opaque marker, not the item this
3940
- // schema describes. Skipping it is what makes rendering a partially
3759
+ // schema describes. Skipping it is what makes previewing a partially
3941
3760
  // loaded record work — the result comes out covering exactly the loaded
3942
- // keys, and the caller renders a placeholder for the rest.
3761
+ // keys, and the caller shows a placeholder for the rest.
3943
3762
  continue;
3944
3763
  }
3945
3764
  var subPath = unsafeCreateSourcePath(sourcePath, _key);
3946
3765
  if (scope !== undefined && !scope.wantsUnder(subPath)) {
3947
3766
  continue;
3948
3767
  }
3949
- var itemResult = this.item["executeRender"](subPath, itemSrc, scope);
3768
+ var itemResult = this.item["executePreview"](subPath, itemSrc, scope);
3950
3769
  for (var keyS in itemResult) {
3951
3770
  var _key2 = keyS;
3952
3771
  res[_key2] = itemResult[_key2];
3953
3772
  }
3954
3773
  }
3955
- if (this.renderInput) {
3956
- var _this$renderInput = this.renderInput,
3957
- prepare = _this$renderInput.select,
3958
- layout = _this$renderInput.layout;
3959
- if (layout !== "list") {
3960
- res[sourcePath] = {
3961
- status: "error",
3962
- message: "Unknown layout type: " + layout
3963
- };
3964
- }
3774
+ if (this.previewInput) {
3775
+ var prepare = this.previewInput;
3965
3776
  // See the same block in `array`: the whole record when the record is what
3966
3777
  // is being shown, only the wanted entries when it is not.
3967
3778
  var window = scope !== undefined && !scope.wants(sourcePath) ? scope : null;
@@ -3976,7 +3787,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
3976
3787
  if (window !== null && !window.wantsUnder(unsafeCreateSourcePath(sourcePath, _key3))) {
3977
3788
  continue;
3978
3789
  }
3979
- // Per KEY, not per record: `select` is user code, and one entry whose
3790
+ // Per KEY, not per record: the closure is user code, and one entry whose
3980
3791
  // data trips it up must not take out the whole list.
3981
3792
  try {
3982
3793
  // NB NB: display is actually defined by the user
@@ -4002,7 +3813,6 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
4002
3813
  res[sourcePath] = {
4003
3814
  status: "success",
4004
3815
  data: {
4005
- layout: "list",
4006
3816
  parent: "record",
4007
3817
  items: items
4008
3818
  }
@@ -4010,13 +3820,19 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
4010
3820
  }
4011
3821
  return res;
4012
3822
  }
4013
- }, {
4014
- key: "render",
4015
- value: function render(input) {
4016
- return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, {
4017
- layout: input.as,
4018
- select: input.select
4019
- });
3823
+
3824
+ /**
3825
+ * What the editor shows for each ENTRY of this record: a title, and optionally
3826
+ * a subtitle and an image.
3827
+ *
3828
+ * `select` is your own code over the entry's key and source, so it is run on
3829
+ * demand for the entries that are actually being looked at — see
3830
+ * `PreviewScope`.
3831
+ */
3832
+ }, {
3833
+ key: "preview",
3834
+ value: function preview(select) {
3835
+ return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, select);
4020
3836
  }
4021
3837
  }]);
4022
3838
  }(Schema);
@@ -4709,8 +4525,8 @@ var NumberSchema = /*#__PURE__*/function (_Schema) {
4709
4525
  };
4710
4526
  }
4711
4527
  }, {
4712
- key: "executeRender",
4713
- value: function executeRender() {
4528
+ key: "executePreview",
4529
+ value: function executePreview() {
4714
4530
  return {};
4715
4531
  }
4716
4532
  }]);
@@ -4829,8 +4645,8 @@ var BooleanSchema = /*#__PURE__*/function (_Schema) {
4829
4645
  };
4830
4646
  }
4831
4647
  }, {
4832
- key: "executeRender",
4833
- value: function executeRender() {
4648
+ key: "executePreview",
4649
+ value: function executePreview() {
4834
4650
  return {};
4835
4651
  }
4836
4652
  }]);
@@ -4883,48 +4699,378 @@ var KeyOfSchema = /*#__PURE__*/function (_Schema) {
4883
4699
  message: "Schema not found for module. keyOf must be used with a Val Module"
4884
4700
  }]));
4885
4701
  }
4886
- var serializedSchema = this.schema;
4887
- if (!(serializedSchema.type === "object" || serializedSchema.type === "record")) {
4702
+ var serializedSchema = this.schema;
4703
+ if (!(serializedSchema.type === "object" || serializedSchema.type === "record")) {
4704
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
4705
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4706
+ message: "Schema in keyOf must be an 'object' or 'record'. Found '".concat(serializedSchema.type || "unknown", "'")
4707
+ }]));
4708
+ }
4709
+ if (serializedSchema.opt && (src === null || src === undefined)) {
4710
+ return false;
4711
+ }
4712
+ if (serializedSchema.type === "record" && typeof src !== "string") {
4713
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
4714
+ message: "Type of value in keyof (record) must be 'string'"
4715
+ }]));
4716
+ }
4717
+ if (serializedSchema.type === "object") {
4718
+ var keys = serializedSchema.keys;
4719
+ if (!keys.includes(src)) {
4720
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
4721
+ message: "Value of keyOf (object) must be: ".concat(keys.join(", "), ". Found: ").concat(src)
4722
+ }]));
4723
+ }
4724
+ }
4725
+ if (serializedSchema.type === "record") {
4726
+ if (typeof src !== "string") {
4727
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
4728
+ message: "Value of keyOf (record) must be 'string'. Found: ".concat(_typeof(src))
4729
+ }]));
4730
+ }
4731
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
4732
+ fixes: ["keyof:check-keys"],
4733
+ message: "Did not validate keyOf (record). This error (keyof:check-keys) should typically be processed by Val internally. Seeing this error most likely means you have a Val version mismatch.",
4734
+ value: {
4735
+ key: src,
4736
+ sourcePath: this.sourcePath
4737
+ }
4738
+ }]));
4739
+ }
4740
+ if (customValidationErrors.length > 0) {
4741
+ return _defineProperty({}, path, customValidationErrors);
4742
+ }
4743
+ return false;
4744
+ }
4745
+ }, {
4746
+ key: "executeAssert",
4747
+ value: function executeAssert(path, src) {
4748
+ if (this.opt && src === null) {
4749
+ return {
4750
+ success: true,
4751
+ data: src
4752
+ };
4753
+ }
4754
+ if (src === null) {
4755
+ return {
4756
+ success: false,
4757
+ errors: _defineProperty({}, path, [{
4758
+ message: "Expected 'string', got 'null'",
4759
+ typeError: true
4760
+ }])
4761
+ };
4762
+ }
4763
+ var schema = this.schema;
4764
+ if (!schema) {
4765
+ return {
4766
+ success: false,
4767
+ errors: _defineProperty({}, path, [{
4768
+ message: "Neither key nor schema was found. keyOf is missing an argument.",
4769
+ typeError: true
4770
+ }])
4771
+ };
4772
+ }
4773
+ var serializedSchema = schema;
4774
+ if (!(serializedSchema.type === "object" || serializedSchema.type === "record")) {
4775
+ return {
4776
+ success: false,
4777
+ errors: _defineProperty({}, path, [{
4778
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4779
+ message: "Schema of first argument must be either: 'array', 'object' or 'record'. Found '".concat(serializedSchema.type || "unknown", "'"),
4780
+ typeError: true
4781
+ }])
4782
+ };
4783
+ }
4784
+ if (serializedSchema.type === "record" && typeof src !== "string") {
4785
+ return {
4786
+ success: false,
4787
+ errors: _defineProperty({}, path, [{
4788
+ message: "Value of keyOf (record) must be 'string', got '".concat(_typeof(src), "'"),
4789
+ typeError: true
4790
+ }])
4791
+ };
4792
+ }
4793
+ // We check actual value here, since TypeScript also does this. Literals are used in other types (unions),
4794
+ // and there it also makes sense to check the actual string values (i.e. that it is not just a string) since
4795
+ // missing one would lead to a runtime error. At least this is what we are thinking currently.
4796
+ if (serializedSchema.type === "object") {
4797
+ var keys = serializedSchema.keys;
4798
+ if (!keys.includes(src)) {
4799
+ return {
4800
+ success: false,
4801
+ errors: _defineProperty({}, path, [{
4802
+ message: "Value of keyOf (object) must be: ".concat(keys.join(", "), ". Found: ").concat(src),
4803
+ typeError: true
4804
+ }])
4805
+ };
4806
+ }
4807
+ }
4808
+ return {
4809
+ success: true,
4810
+ data: src
4811
+ };
4812
+ }
4813
+ }, {
4814
+ key: "nullable",
4815
+ value: function nullable() {
4816
+ return new KeyOfSchema(this.schema, this.sourcePath, true, [], this.isReadonly, this.isHidden, this.description);
4817
+ }
4818
+ }, {
4819
+ key: "readonly",
4820
+ value: function readonly() {
4821
+ return new KeyOfSchema(this.schema, this.sourcePath, this.opt, this.customValidateFunctions, true, this.isHidden, this.description);
4822
+ }
4823
+ }, {
4824
+ key: "hidden",
4825
+ value: function hidden() {
4826
+ return new KeyOfSchema(this.schema, this.sourcePath, this.opt, this.customValidateFunctions, this.isReadonly, true, this.description);
4827
+ }
4828
+ }, {
4829
+ key: "executeCustomValidateAt",
4830
+ value: function executeCustomValidateAt(path, src) {
4831
+ return this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
4832
+ path: path
4833
+ });
4834
+ }
4835
+ }, {
4836
+ key: "executeSerialize",
4837
+ value: function executeSerialize() {
4838
+ var _this$customValidateF;
4839
+ var path = this.sourcePath;
4840
+ if (!path) {
4841
+ throw new Error("Cannot serialize keyOf schema with empty selector. TIP: keyOf must be used with a Val Module of record schema.");
4842
+ }
4843
+ var serializedSchema = this.schema;
4844
+ if (!serializedSchema) {
4845
+ throw new Error("Cannot serialize keyOf schema with empty selector.");
4846
+ }
4847
+ var values;
4848
+ switch (serializedSchema.type) {
4849
+ case "record":
4850
+ values = "string";
4851
+ break;
4852
+ case "object":
4853
+ values = serializedSchema.keys;
4854
+ break;
4855
+ default:
4856
+ throw new Error(// eslint-disable-next-line @typescript-eslint/no-explicit-any
4857
+ "Cannot serialize keyOf schema with selector of type '".concat(serializedSchema.type || "unknown", "'"));
4858
+ }
4859
+ return {
4860
+ type: "keyOf",
4861
+ path: path,
4862
+ schema: serializedSchema,
4863
+ opt: this.opt,
4864
+ values: values,
4865
+ customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
4866
+ readonly: this.isReadonly,
4867
+ hidden: this.isHidden,
4868
+ description: this.description
4869
+ };
4870
+ }
4871
+ }, {
4872
+ key: "executePreview",
4873
+ value: function executePreview() {
4874
+ return {};
4875
+ }
4876
+ }]);
4877
+ }(Schema);
4878
+ var keyOf = function keyOf(valModule) {
4879
+ var refSchema = valModule === null || valModule === void 0 ? void 0 : valModule[GetSchema];
4880
+ var serializedRefSchema = undefined;
4881
+ if (refSchema instanceof ObjectSchema) {
4882
+ var keys = [];
4883
+ try {
4884
+ keys = Object.keys((refSchema === null || refSchema === void 0 ? void 0 : refSchema["items"]) || {});
4885
+ } catch (e) {
4886
+ // ignore this error here
4887
+ }
4888
+ serializedRefSchema = {
4889
+ type: "object",
4890
+ keys: keys,
4891
+ opt: refSchema === null || refSchema === void 0 ? void 0 : refSchema["opt"]
4892
+ };
4893
+ } else if (refSchema instanceof RecordSchema) {
4894
+ serializedRefSchema = {
4895
+ type: "record",
4896
+ opt: refSchema === null || refSchema === void 0 ? void 0 : refSchema["opt"]
4897
+ };
4898
+ }
4899
+ return new KeyOfSchema(serializedRefSchema, getValPath(valModule));
4900
+ };
4901
+
4902
+ var FileSchema = /*#__PURE__*/function (_Schema) {
4903
+ function FileSchema(options) {
4904
+ var _this;
4905
+ var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
4906
+ var isRemote = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
4907
+ var customValidateFunctions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
4908
+ var moduleMetadata = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
4909
+ var isReadonly = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
4910
+ var isHidden = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;
4911
+ var description = arguments.length > 7 ? arguments[7] : undefined;
4912
+ _classCallCheck(this, FileSchema);
4913
+ _this = _callSuper(this, FileSchema);
4914
+ _this.options = options;
4915
+ _this.opt = opt;
4916
+ _this.isRemote = isRemote;
4917
+ _this.customValidateFunctions = customValidateFunctions;
4918
+ _this.moduleMetadata = moduleMetadata;
4919
+ _this.isReadonly = isReadonly;
4920
+ _this.isHidden = isHidden;
4921
+ _this.description = description;
4922
+ return _this;
4923
+ }
4924
+ _inherits(FileSchema, _Schema);
4925
+ return _createClass(FileSchema, [{
4926
+ key: "describe",
4927
+ value: function describe(description) {
4928
+ return new FileSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined);
4929
+ }
4930
+ }, {
4931
+ key: "remote",
4932
+ value: function remote() {
4933
+ return new FileSchema(this.options, this.opt, true, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, this.isHidden, this.description);
4934
+ }
4935
+ }, {
4936
+ key: "validate",
4937
+ value: function validate(validationFunction) {
4938
+ return new FileSchema(this.options, this.opt, this.isRemote, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]), this.moduleMetadata, this.isReadonly, this.isHidden, this.description);
4939
+ }
4940
+ }, {
4941
+ key: "executeValidate",
4942
+ value: function executeValidate(path, src) {
4943
+ var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
4944
+ path: path
4945
+ });
4946
+ if (this.opt && (src === null || src === undefined)) {
4947
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
4948
+ }
4949
+ if (src === null || src === undefined) {
4950
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
4951
+ message: "Non-optional file was null or undefined.",
4952
+ value: src
4953
+ }]));
4954
+ }
4955
+ if (typeof src.path !== "string") {
4956
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
4957
+ message: "File did not have a path string. Got: ".concat(_typeof(src.path)),
4958
+ value: src
4959
+ }]));
4960
+ }
4961
+ // Remote-ness is a property of the path, not of a marker on the value:
4962
+ // anything outside /public is remote.
4963
+ var isRemotePath = isRemoteMediaPath(src.path);
4964
+ if (this.isRemote && !isRemotePath) {
4888
4965
  return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
4889
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
4890
- message: "Schema in keyOf must be an 'object' or 'record'. Found '".concat(serializedSchema.type || "unknown", "'")
4966
+ message: "Expected a remote file, but got a local file.",
4967
+ value: src,
4968
+ fixes: ["file:upload-remote"]
4891
4969
  }]));
4892
4970
  }
4893
- if (serializedSchema.opt && (src === null || src === undefined)) {
4894
- return false;
4971
+ if (this.isRemote && isRemotePath) {
4972
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
4973
+ message: "Remote file was not checked.",
4974
+ value: src,
4975
+ fixes: ["file:check-remote"]
4976
+ }]));
4895
4977
  }
4896
- if (serializedSchema.type === "record" && typeof src !== "string") {
4978
+ if (!this.isRemote && isRemotePath) {
4897
4979
  return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
4898
- message: "Type of value in keyof (record) must be 'string'"
4980
+ message: "Expected local file, but found remote.",
4981
+ value: src,
4982
+ fixes: ["file:download-remote"]
4899
4983
  }]));
4900
4984
  }
4901
- if (serializedSchema.type === "object") {
4902
- var keys = serializedSchema.keys;
4903
- if (!keys.includes(src)) {
4985
+ var galleryEntries = this.galleryEntries();
4986
+ if (galleryEntries) {
4987
+ if (src.mimeType !== undefined) {
4904
4988
  return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
4905
- message: "Value of keyOf (object) must be: ".concat(keys.join(", "), ". Found: ").concat(src)
4989
+ message: "A file from a gallery must not carry its own mimeType: it is stored in the gallery module.",
4990
+ value: src
4906
4991
  }]));
4907
4992
  }
4908
- }
4909
- if (serializedSchema.type === "record") {
4910
- if (typeof src !== "string") {
4993
+ if (!(src.path in galleryEntries)) {
4911
4994
  return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
4912
- message: "Value of keyOf (record) must be 'string'. Found: ".concat(_typeof(src))
4995
+ message: "The gallery does not have a file at '".concat(src.path, "'."),
4996
+ value: src
4913
4997
  }]));
4914
4998
  }
4999
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
5000
+ }
5001
+ var _ref0 = this.options || {},
5002
+ accept = _ref0.accept;
5003
+ var mimeType = src.mimeType;
5004
+ if (accept && mimeType && !mimeType.includes("/")) {
4915
5005
  return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
4916
- fixes: ["keyof:check-keys"],
4917
- message: "Did not validate keyOf (record). This error (keyof:check-keys) should typically be processed by Val internally. Seeing this error most likely means you have a Val version mismatch.",
4918
- value: {
4919
- key: src,
4920
- sourcePath: this.sourcePath
5006
+ message: "Invalid mime type format. Got: ".concat(mimeType),
5007
+ value: src
5008
+ }]));
5009
+ }
5010
+ if (accept && mimeType && mimeType.includes("/")) {
5011
+ var acceptedTypes = accept.split(",").map(function (type) {
5012
+ return type.trim();
5013
+ });
5014
+ var isValidMimeType = acceptedTypes.some(function (acceptedType) {
5015
+ if (acceptedType === "*/*") {
5016
+ return true;
5017
+ }
5018
+ if (acceptedType.endsWith("/*")) {
5019
+ var baseType = acceptedType.slice(0, -2);
5020
+ return mimeType.startsWith(baseType);
4921
5021
  }
5022
+ return acceptedType === mimeType;
5023
+ });
5024
+ if (!isValidMimeType) {
5025
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
5026
+ message: "Mime type mismatch. Found '".concat(mimeType, "' but schema accepts '").concat(accept, "'"),
5027
+ value: src
5028
+ }]));
5029
+ }
5030
+ }
5031
+ var fileMimeType = Internal.filenameToMimeType(src.path);
5032
+ if (!fileMimeType) {
5033
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
5034
+ message: "Could not determine mime type from file extension. Got: ".concat(src.path),
5035
+ value: src
4922
5036
  }]));
4923
5037
  }
4924
- if (customValidationErrors.length > 0) {
4925
- return _defineProperty({}, path, customValidationErrors);
5038
+ if (fileMimeType !== mimeType) {
5039
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
5040
+ message: "Mime type and file extension not matching. Mime type is '".concat(mimeType, "' but file extension is '").concat(fileMimeType, "'"),
5041
+ value: src
5042
+ }]));
4926
5043
  }
4927
- return false;
5044
+
5045
+ // The mime type read so far came from the filename. Whether it matches the
5046
+ // bytes can only be answered by reading the file, which this package
5047
+ // deliberately cannot do — so it is always handed on as a fix.
5048
+ if (mimeType !== undefined) {
5049
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
5050
+ message: "Found mimeType, but it could not be validated.",
5051
+ value: src,
5052
+ fixes: ["file:check-metadata"]
5053
+ }]));
5054
+ }
5055
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
5056
+ message: "Missing File mimeType.",
5057
+ value: src,
5058
+ fixes: ["file:add-metadata"]
5059
+ }]));
5060
+ }
5061
+
5062
+ /**
5063
+ * The entries of the gallery this field points at, or null when it is a
5064
+ * standalone field.
5065
+ */
5066
+ }, {
5067
+ key: "galleryEntries",
5068
+ value: function galleryEntries() {
5069
+ var modulePaths = Object.keys(this.moduleMetadata);
5070
+ if (modulePaths.length === 0) {
5071
+ return null;
5072
+ }
5073
+ return this.moduleMetadata[modulePaths[0]];
4928
5074
  }
4929
5075
  }, {
4930
5076
  key: "executeAssert",
@@ -4939,56 +5085,29 @@ var KeyOfSchema = /*#__PURE__*/function (_Schema) {
4939
5085
  return {
4940
5086
  success: false,
4941
5087
  errors: _defineProperty({}, path, [{
4942
- message: "Expected 'string', got 'null'",
4943
- typeError: true
4944
- }])
4945
- };
4946
- }
4947
- var schema = this.schema;
4948
- if (!schema) {
4949
- return {
4950
- success: false,
4951
- errors: _defineProperty({}, path, [{
4952
- message: "Neither key nor schema was found. keyOf is missing an argument.",
5088
+ message: "Expected 'object', got 'null'",
4953
5089
  typeError: true
4954
5090
  }])
4955
5091
  };
4956
5092
  }
4957
- var serializedSchema = schema;
4958
- if (!(serializedSchema.type === "object" || serializedSchema.type === "record")) {
5093
+ if (_typeof(src) !== "object") {
4959
5094
  return {
4960
5095
  success: false,
4961
5096
  errors: _defineProperty({}, path, [{
4962
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
4963
- message: "Schema of first argument must be either: 'array', 'object' or 'record'. Found '".concat(serializedSchema.type || "unknown", "'"),
5097
+ message: "Expected object, got '".concat(_typeof(src), "'"),
4964
5098
  typeError: true
4965
5099
  }])
4966
5100
  };
4967
5101
  }
4968
- if (serializedSchema.type === "record" && typeof src !== "string") {
5102
+ if (!("path" in src) || typeof src.path !== "string") {
4969
5103
  return {
4970
5104
  success: false,
4971
5105
  errors: _defineProperty({}, path, [{
4972
- message: "Value of keyOf (record) must be 'string', got '".concat(_typeof(src), "'"),
5106
+ message: "A file must be an object with a 'path' (error type: missing_path)",
4973
5107
  typeError: true
4974
5108
  }])
4975
5109
  };
4976
5110
  }
4977
- // We check actual value here, since TypeScript also does this. Literals are used in other types (unions),
4978
- // and there it also makes sense to check the actual string values (i.e. that it is not just a string) since
4979
- // missing one would lead to a runtime error. At least this is what we are thinking currently.
4980
- if (serializedSchema.type === "object") {
4981
- var keys = serializedSchema.keys;
4982
- if (!keys.includes(src)) {
4983
- return {
4984
- success: false,
4985
- errors: _defineProperty({}, path, [{
4986
- message: "Value of keyOf (object) must be: ".concat(keys.join(", "), ". Found: ").concat(src),
4987
- typeError: true
4988
- }])
4989
- };
4990
- }
4991
- }
4992
5111
  return {
4993
5112
  success: true,
4994
5113
  data: src
@@ -4997,17 +5116,17 @@ var KeyOfSchema = /*#__PURE__*/function (_Schema) {
4997
5116
  }, {
4998
5117
  key: "nullable",
4999
5118
  value: function nullable() {
5000
- return new KeyOfSchema(this.schema, this.sourcePath, true, [], this.isReadonly, this.isHidden, this.description);
5119
+ return new FileSchema(this.options, true, this.isRemote, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, this.isHidden, this.description);
5001
5120
  }
5002
5121
  }, {
5003
5122
  key: "readonly",
5004
5123
  value: function readonly() {
5005
- return new KeyOfSchema(this.schema, this.sourcePath, this.opt, this.customValidateFunctions, true, this.isHidden, this.description);
5124
+ return new FileSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, true, this.isHidden, this.description);
5006
5125
  }
5007
5126
  }, {
5008
5127
  key: "hidden",
5009
5128
  value: function hidden() {
5010
- return new KeyOfSchema(this.schema, this.sourcePath, this.opt, this.customValidateFunctions, this.isReadonly, true, this.description);
5129
+ return new FileSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, true, this.description);
5011
5130
  }
5012
5131
  }, {
5013
5132
  key: "executeCustomValidateAt",
@@ -5020,68 +5139,50 @@ var KeyOfSchema = /*#__PURE__*/function (_Schema) {
5020
5139
  key: "executeSerialize",
5021
5140
  value: function executeSerialize() {
5022
5141
  var _this$customValidateF;
5023
- var path = this.sourcePath;
5024
- if (!path) {
5025
- throw new Error("Cannot serialize keyOf schema with empty selector. TIP: keyOf must be used with a Val Module of record schema.");
5026
- }
5027
- var serializedSchema = this.schema;
5028
- if (!serializedSchema) {
5029
- throw new Error("Cannot serialize keyOf schema with empty selector.");
5030
- }
5031
- var values;
5032
- switch (serializedSchema.type) {
5033
- case "record":
5034
- values = "string";
5035
- break;
5036
- case "object":
5037
- values = serializedSchema.keys;
5038
- break;
5039
- default:
5040
- throw new Error(// eslint-disable-next-line @typescript-eslint/no-explicit-any
5041
- "Cannot serialize keyOf schema with selector of type '".concat(serializedSchema.type || "unknown", "'"));
5042
- }
5142
+ var modulePaths = this.moduleMetadata ? Object.keys(this.moduleMetadata) : [];
5043
5143
  return {
5044
- type: "keyOf",
5045
- path: path,
5046
- schema: serializedSchema,
5144
+ type: "file",
5145
+ options: this.options,
5047
5146
  opt: this.opt,
5048
- values: values,
5147
+ remote: this.isRemote,
5049
5148
  customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
5149
+ referencedModule: modulePaths.length > 0 ? modulePaths[0] : undefined,
5050
5150
  readonly: this.isReadonly,
5051
5151
  hidden: this.isHidden,
5052
5152
  description: this.description
5053
5153
  };
5054
5154
  }
5055
5155
  }, {
5056
- key: "executeRender",
5057
- value: function executeRender() {
5156
+ key: "executePreview",
5157
+ value: function executePreview() {
5058
5158
  return {};
5059
5159
  }
5060
5160
  }]);
5061
5161
  }(Schema);
5062
- var keyOf = function keyOf(valModule) {
5063
- var refSchema = valModule === null || valModule === void 0 ? void 0 : valModule[GetSchema];
5064
- var serializedRefSchema = undefined;
5065
- if (refSchema instanceof ObjectSchema) {
5066
- var keys = [];
5067
- try {
5068
- keys = Object.keys((refSchema === null || refSchema === void 0 ? void 0 : refSchema["items"]) || {});
5069
- } catch (e) {
5070
- // ignore this error here
5162
+
5163
+ /**
5164
+ * A file picked from a gallery. Its mime type lives in the gallery, so the
5165
+ * field carries only the path.
5166
+ */
5167
+
5168
+ /** A file of its own, carrying its own mime type. */
5169
+
5170
+ function file(options) {
5171
+ var isModule = !!options && !!Internal.getValPath(options);
5172
+ if (isModule) {
5173
+ var allModules = {};
5174
+ for (var _i = 0, _arr = [options]; _i < _arr.length; _i++) {
5175
+ var valModule = _arr[_i];
5176
+ var modulePath = getValPath(valModule);
5177
+ if (modulePath === undefined) {
5178
+ throw new Error("Invalid argument passed to s.file(). Expected a ValModule constructed through c.define, but got an object without a valid module path.");
5179
+ }
5180
+ allModules[modulePath] = getSource(valModule);
5071
5181
  }
5072
- serializedRefSchema = {
5073
- type: "object",
5074
- keys: keys,
5075
- opt: refSchema === null || refSchema === void 0 ? void 0 : refSchema["opt"]
5076
- };
5077
- } else if (refSchema instanceof RecordSchema) {
5078
- serializedRefSchema = {
5079
- type: "record",
5080
- opt: refSchema === null || refSchema === void 0 ? void 0 : refSchema["opt"]
5081
- };
5182
+ return new FileSchema({}, false, false, [], allModules);
5082
5183
  }
5083
- return new KeyOfSchema(serializedRefSchema, getValPath(valModule));
5084
- };
5184
+ return new FileSchema(options);
5185
+ }
5085
5186
 
5086
5187
  /**
5087
5188
  * Options for s.files()
@@ -5283,8 +5384,8 @@ var DateSchema = /*#__PURE__*/function (_Schema) {
5283
5384
  };
5284
5385
  }
5285
5386
  }, {
5286
- key: "executeRender",
5287
- value: function executeRender() {
5387
+ key: "executePreview",
5388
+ value: function executePreview() {
5288
5389
  return {};
5289
5390
  }
5290
5391
  }]);
@@ -5487,8 +5588,8 @@ var DateTimeSchema = /*#__PURE__*/function (_Schema) {
5487
5588
  };
5488
5589
  }
5489
5590
  }, {
5490
- key: "executeRender",
5491
- value: function executeRender() {
5591
+ key: "executePreview",
5592
+ value: function executePreview() {
5492
5593
  return {};
5493
5594
  }
5494
5595
  }]);
@@ -6128,8 +6229,8 @@ var ColorSchema = /*#__PURE__*/function (_Schema) {
6128
6229
  };
6129
6230
  }
6130
6231
  }, {
6131
- key: "executeRender",
6132
- value: function executeRender() {
6232
+ key: "executePreview",
6233
+ value: function executePreview() {
6133
6234
  return {};
6134
6235
  }
6135
6236
  }]);
@@ -6236,88 +6337,6 @@ function initSchema() {
6236
6337
  };
6237
6338
  }
6238
6339
 
6239
- /**
6240
- * A image source represents the path to a (local) image.
6241
- *
6242
- */
6243
-
6244
- var initImage = function initImage(config) {
6245
- var _config$files$directo, _config$files;
6246
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
6247
- (_config$files$directo = config === null || config === void 0 || (_config$files = config.files) === null || _config$files === void 0 ? void 0 : _config$files.directory) !== null && _config$files$directo !== void 0 ? _config$files$directo : "/public/val";
6248
-
6249
- /**
6250
- * Define the source of an image file.
6251
- *
6252
- * @example
6253
- * c.image("/public/val/example.png", {
6254
- * width: 944,
6255
- * height: 944,
6256
- * mimeType: "image/png",
6257
- *})
6258
- *
6259
- * @param ref /public/val/example.png
6260
- * @param metadata Image metadata: width, height, mimeType and optionally a hotspot.
6261
- */
6262
-
6263
- /**
6264
- * Define the source of an image file.
6265
- *
6266
- * NOTE: this will **not** validate since metadata has not been defined.
6267
- *
6268
- * Run `npx -p @valbuild/cli val validate --fix` to automatically add metadata.
6269
- *
6270
- * @example
6271
- * c.image("/public/val/example.png")
6272
- *
6273
- * @param ref /public/val/example.png
6274
- * @param metadata Image metadata: width, height, mimeType and optionally a hotspot.
6275
- */
6276
-
6277
- /**
6278
- * Define the source of an image file.
6279
- *
6280
- * @example
6281
- * c.image("/public/val/example.png", {
6282
- * width: 944,
6283
- * height: 944,
6284
- * mimeType: "image/png",
6285
- *})
6286
- *
6287
- * @param ref /public/val/example.png
6288
- * @param metadata Image metadata: width, height, mimeType and optionally a hotspot.
6289
- */
6290
- function image(ref, metadata) {
6291
- return _defineProperty(_defineProperty(_defineProperty(_defineProperty({}, FILE_REF_PROP, ref), VAL_EXTENSION, "file"), FILE_REF_SUBTYPE_TAG, "image"), "metadata", metadata);
6292
- }
6293
- return image;
6294
- };
6295
-
6296
- /**
6297
- * A remote source represents data that is not stored locally.
6298
- */
6299
-
6300
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
6301
- var initRemote = function initRemote(config) {
6302
- function remote(ref, metadata) {
6303
- return _defineProperty(_defineProperty(_defineProperty({}, FILE_REF_PROP, ref), VAL_EXTENSION, "remote"), "metadata", metadata);
6304
- }
6305
- return remote;
6306
- };
6307
-
6308
- // NOTE: the segments must match the ref built by createRemoteRef below and the RegEx in splitRemoteRef.
6309
-
6310
- function createRemoteRef(remoteHost, _ref2) {
6311
- var publicProjectId = _ref2.publicProjectId,
6312
- coreVersion = _ref2.coreVersion,
6313
- validationHash = _ref2.validationHash,
6314
- fileHash = _ref2.fileHash,
6315
- filePath = _ref2.filePath,
6316
- bucket = _ref2.bucket;
6317
- // NOTE: the core version is part of the validation hash, but it is also in the uri to make it easier to understand which version the remote file was validated against.
6318
- return "".concat(remoteHost, "/file/p/").concat(publicProjectId, "/b/").concat(bucket, "/v/").concat(coreVersion, "/h/").concat(validationHash, "/f/").concat(fileHash, "/p/").concat(filePath);
6319
- }
6320
-
6321
6340
  // import { i18n, I18n } from "./source/future/i18n";
6322
6341
  // import { remote } from "./source/future/remote";
6323
6342
 
@@ -6354,9 +6373,6 @@ var initVal = function initVal(config) {
6354
6373
  },
6355
6374
  c: {
6356
6375
  define: define,
6357
- remote: initRemote(),
6358
- file: initFile(config),
6359
- image: initImage(config),
6360
6376
  json: json
6361
6377
  },
6362
6378
  s: s,
@@ -7073,23 +7089,6 @@ function hasRemoteFileSchema(schema) {
7073
7089
  }
7074
7090
 
7075
7091
  var DEFAULT_VAL_REMOTE_HOST = "https://remote.val.build";
7076
- function convertRemoteSource(src) {
7077
- if (src !== null && src !== void 0 && src.patch_id) {
7078
- var splitRemoteRefDataRes = splitRemoteRef(src[FILE_REF_PROP]);
7079
- if (splitRemoteRefDataRes.status === "success") {
7080
- return {
7081
- url: "/api/val/files/" + splitRemoteRefDataRes.filePath + "?patch_id=".concat(src["patch_id"], "&remote=true&ref=").concat(encodeURIComponent(src[FILE_REF_PROP])),
7082
- metadata: src.metadata
7083
- };
7084
- } else {
7085
- console.warn("Internal Val error: failed to split remote ref: ".concat(src[FILE_REF_PROP], ". The data format is different than what is expected. Check Val versions for mismatches."), splitRemoteRefDataRes.error);
7086
- }
7087
- }
7088
- return {
7089
- url: src[FILE_REF_PROP],
7090
- metadata: src.metadata
7091
- };
7092
- }
7093
7092
 
7094
7093
  var PatchError = /*#__PURE__*/_createClass(function PatchError(message) {
7095
7094
  _classCallCheck(this, PatchError);
@@ -7159,14 +7158,15 @@ function derefPatch(patch, document, ops) {
7159
7158
  var maybeValue = ops.get(document, dereffedPath);
7160
7159
  if (result.isOk(maybeValue)) {
7161
7160
  var value = maybeValue.value;
7162
- if (isFile(value)) {
7161
+ var mediaPath = mediaPathOf(value);
7162
+ if (mediaPath !== null) {
7163
7163
  if (referencedPath.length > 0) {
7164
7164
  return result.err(new PatchError("Cannot sub-reference file reference at path: ".concat(dereffedPath.join("/"))));
7165
7165
  }
7166
7166
  if (typeof op.value !== "string") {
7167
7167
  return result.err(new PatchError("Expected base64 encoded string value for file reference, got ".concat(JSON.stringify(op.value))));
7168
7168
  }
7169
- fileUpdates[value[FILE_REF_PROP]] = op.value;
7169
+ fileUpdates[mediaPath] = op.value;
7170
7170
  // } else if (isRemote(value)) {
7171
7171
  // if (!remotePatches[value[REMOTE_REF_PROP]]) {
7172
7172
  // remotePatches[value[REMOTE_REF_PROP]] = [];
@@ -7217,6 +7217,21 @@ function derefPatch(patch, document, ops) {
7217
7217
  });
7218
7218
  }
7219
7219
 
7220
+ /**
7221
+ * The path of a media value, or null when it is not media.
7222
+ *
7223
+ * A `$` deref op names its target explicitly, so there is no schema in hand
7224
+ * here — the shape is all there is to go on. Everywhere a schema IS available,
7225
+ * media is recognised from it instead.
7226
+ */
7227
+ function mediaPathOf(value) {
7228
+ if (_typeof(value) !== "object" || value === null || Array.isArray(value)) {
7229
+ return null;
7230
+ }
7231
+ var path = value.path;
7232
+ return typeof path === "string" ? path : null;
7233
+ }
7234
+
7220
7235
  var EXT_TO_MIME_TYPES = {
7221
7236
  x3d: "application/vnd.hzn-3d-crossword",
7222
7237
  "3gp": "video/3gpp",
@@ -7940,6 +7955,19 @@ function filenameToMimeType(filename) {
7940
7955
  }
7941
7956
  }
7942
7957
 
7958
+ // NOTE: the segments must match the ref built by createRemoteRef below and the RegEx in splitRemoteRef.
7959
+
7960
+ function createRemoteRef(remoteHost, _ref) {
7961
+ var publicProjectId = _ref.publicProjectId,
7962
+ coreVersion = _ref.coreVersion,
7963
+ validationHash = _ref.validationHash,
7964
+ fileHash = _ref.fileHash,
7965
+ filePath = _ref.filePath,
7966
+ bucket = _ref.bucket;
7967
+ // NOTE: the core version is part of the validation hash, but it is also in the uri to make it easier to understand which version the remote file was validated against.
7968
+ return "".concat(remoteHost, "/file/p/").concat(publicProjectId, "/b/").concat(bucket, "/v/").concat(coreVersion, "/h/").concat(validationHash, "/f/").concat(fileHash, "/p/").concat(filePath);
7969
+ }
7970
+
7943
7971
  /**
7944
7972
  * The validation basis is used in remote refs to determine if the remote content needs to be re-validated.
7945
7973
  *
@@ -7981,13 +8009,16 @@ function deserializeSchema(serialized) {
7981
8009
  return schema;
7982
8010
  }
7983
8011
  function deserializeSchemaImpl(serialized) {
7984
- var _serialized$options, _serialized$options2, _serialized$accept, _serialized$directory, _serialized$remote, _serialized$jsonValue;
8012
+ var _serialized$options, _serialized$options2, _serialized$render, _serialized$accept, _serialized$directory, _serialized$remote, _serialized$jsonValue;
7985
8013
  switch (serialized.type) {
7986
8014
  case "string":
7987
8015
  return new StringSchema(_objectSpread2(_objectSpread2({}, serialized.options), {}, {
7988
8016
  regexp: ((_serialized$options = serialized.options) === null || _serialized$options === void 0 ? void 0 : _serialized$options.regexp) && new RegExp(serialized.options.regexp.source, serialized.options.regexp.flags),
7989
8017
  regExpMessage: (_serialized$options2 = serialized.options) === null || _serialized$options2 === void 0 || (_serialized$options2 = _serialized$options2.regexp) === null || _serialized$options2 === void 0 ? void 0 : _serialized$options2.message
7990
- }), serialized.opt, serialized.raw, [], null, false, false, serialized.description);
8018
+ }), serialized.opt, serialized.raw, [], // A render is static data, so it survives serialization and must be
8019
+ // carried back: it is the schema's own configuration now, not something
8020
+ // recomputed from an instance.
8021
+ (_serialized$render = serialized.render) !== null && _serialized$render !== void 0 ? _serialized$render : null, false, false, serialized.description);
7991
8022
  case "literal":
7992
8023
  return new LiteralSchema(serialized.value, serialized.opt, [], false, false, serialized.description);
7993
8024
  case "boolean":
@@ -8064,31 +8095,46 @@ function deserializeSchemaImpl(serialized) {
8064
8095
  }
8065
8096
  }
8066
8097
 
8067
- // TODO: we want to change layout -> as to be more consistent across the board
8068
-
8069
- // Main render type:
8098
+ /**
8099
+ * What a container shows for ONE of its items: the user's `preview` callback
8100
+ * returns this, and the Studio draws a row from it.
8101
+ *
8102
+ * NB: {@link ArrayPreview} / {@link RecordPreview} name the DATA a container
8103
+ * previews with. The Studio also has React components called `ArrayPreview` /
8104
+ * `RecordPreview` (the fallback rendering of an array / record field, part of
8105
+ * the `<Type>Preview` convention in `components/Preview.tsx`). They do not
8106
+ * collide today because no file needs both - if one ever does, alias this type
8107
+ * at the import rather than renaming that convention.
8108
+ */
8070
8109
 
8071
- //
8110
+ /**
8111
+ * Main preview type.
8112
+ *
8113
+ * Deliberately not exported: `parent` is the discriminant, and every consumer
8114
+ * narrows on it rather than on the union as a whole. There is no `layout` here
8115
+ * on purpose - how a preview is laid out is the editor's business, not the
8116
+ * schema's.
8117
+ */
8072
8118
 
8073
8119
  /**
8074
- * Which paths a render is being computed FOR.
8120
+ * Which paths a preview is being computed FOR.
8075
8121
  *
8076
- * `executeRender` takes a whole module, so one request has always walked every
8077
- * node in it and run every `select` closure — for `handboka`, with `select` at
8122
+ * `executePreview` takes a whole module, so one request has always walked every
8123
+ * node in it and run every `preview` closure - for `handboka`, with `preview` at
8078
8124
  * two nested array levels, that is every chapter and every section to serve one
8079
8125
  * visible row. A scope is what makes the walk proportional to what is being
8080
8126
  * looked at instead of to the project.
8081
8127
  *
8082
8128
  * Two questions, because a container and its items need different answers:
8083
8129
  *
8084
- * - {@link RenderScope.wants} — is a render AT this exact path wanted? A
8130
+ * - {@link PreviewScope.wants} - is a preview AT this exact path wanted? A
8085
8131
  * container answers `true` here when the whole of it is being shown, and its
8086
- * list render is then computed in full.
8087
- * - {@link RenderScope.wantsUnder} — could anything at or below this path be
8132
+ * preview is then computed in full.
8133
+ * - {@link PreviewScope.wantsUnder} - could anything at or below this path be
8088
8134
  * wanted? Recursion is pruned where this is `false`, and a container whose own
8089
- * path is not wanted but which has wanted descendants renders a WINDOW: only
8135
+ * path is not wanted but which has wanted descendants previews a WINDOW: only
8090
8136
  * the items that were asked for. That is the case a single visible row is, and
8091
- * it is why {@link ListArrayRender} carries indices.
8137
+ * it is why {@link ArrayPreview} carries indices.
8092
8138
  *
8093
8139
  * Absent scope means the whole module, which is what every existing caller
8094
8140
  * passes and what every existing caller got.
@@ -8100,10 +8146,10 @@ function deserializeSchemaImpl(serialized) {
8100
8146
  * Compares SEGMENTS rather than string prefixes. A source path's module path is
8101
8147
  * a quoted, dot-joined encoding (`?p="a".1."b"`), so `startsWith` gets the
8102
8148
  * ancestor test wrong wherever a key is a prefix of a sibling key or contains a
8103
- * dot or a quote — `"title"` against `"titles"` being the cheapest example.
8149
+ * dot or a quote - `"title"` against `"titles"` being the cheapest example.
8104
8150
  * Segments are parsed once here, not per comparison.
8105
8151
  */
8106
- function renderScope(paths) {
8152
+ function previewScope(paths) {
8107
8153
  var wanted = paths.map(function (path) {
8108
8154
  var _splitModuleFilePathA = splitModuleFilePathAndModulePath(path),
8109
8155
  _splitModuleFilePathA2 = _slicedToArray(_splitModuleFilePathA, 2),
@@ -8152,6 +8198,37 @@ function renderScope(paths) {
8152
8198
 
8153
8199
  // TODO: improve this so that we do not get RawString and string, only string. Are there other things?
8154
8200
 
8201
+ /**
8202
+ * A RENDER is how one field is laid out in the editor: `s.string().render({ as:
8203
+ * "textarea" })`, `.render({ as: "code", language })`.
8204
+ *
8205
+ * It is static configuration - plain data, with no closure behind it and no
8206
+ * dependency on source - which is why it lives in the SERIALIZED schema
8207
+ * (`SerializedStringSchema.render`) and is read straight off it where the field
8208
+ * is drawn. There is no render pipeline, no store and no host round-trip.
8209
+ *
8210
+ * That "static" is an ASSUMPTION we are taking deliberately, for simplicity,
8211
+ * not a law. A future render could plausibly want to depend on source - a
8212
+ * layout that varies with the value, a callback of its own. If that day comes,
8213
+ * the shape it needs back is `executePreview`'s, and the honest move is to give
8214
+ * `render` its own execute/store pair again. It is NOT to re-merge the two:
8215
+ * conflating them is what this file was split up to undo.
8216
+ *
8217
+ * The dynamic, source-dependent, demand-scoped thing - what a container shows
8218
+ * for its items - is a PREVIEW. See `preview.ts`.
8219
+ */
8220
+ /**
8221
+ * The list is the declaration and {@link CodeLanguage} is derived from it, so
8222
+ * that a validator elsewhere (`shared`'s zod schema) can enumerate the same
8223
+ * languages without a second copy that drifts. Same shape as `COLOR_FORMATS`.
8224
+ */
8225
+ var CODE_LANGUAGES = ["typescript", "javascript", "javascriptreact", "typescriptreact", "json", "java", "html", "css", "xml", "markdown", "sql", "python", "rust", "php", "go", "cpp", "sass", "vue", "angular"];
8226
+
8227
+ /**
8228
+ * What `s.string().render(...)` takes, and what the serialized schema carries
8229
+ * verbatim.
8230
+ */
8231
+
8155
8232
  var externalPageRouter = {
8156
8233
  getRouterId: function getRouterId() {
8157
8234
  return "external-url-router";
@@ -8414,8 +8491,12 @@ var Internal = {
8414
8491
  }
8415
8492
  }()
8416
8493
  },
8417
- convertFileSource: convertFileSource,
8418
- convertRemoteSource: convertRemoteSource,
8494
+ mediaUrl: mediaUrl,
8495
+ resolveMedia: resolveMedia,
8496
+ isRemoteMediaPath: isRemoteMediaPath,
8497
+ media: {
8498
+ fillFromGallery: fillFromGallery
8499
+ },
8419
8500
  getSchema: getSchema,
8420
8501
  getValPath: getValPath,
8421
8502
  getSource: getSource,
@@ -8445,7 +8526,6 @@ var Internal = {
8445
8526
  return val && ((_getSchema = getSchema(val)) === null || _getSchema === void 0 ? void 0 : _getSchema["executeValidate"](path, src));
8446
8527
  },
8447
8528
  isVal: isVal,
8448
- isFile: isFile,
8449
8529
  isJson: isJson,
8450
8530
  getJsonImport: getJsonImport,
8451
8531
  resolveJsonValues: resolveJsonValues,
@@ -8514,6 +8594,7 @@ function tryJsonParse(str) {
8514
8594
 
8515
8595
  exports.ArraySchema = ArraySchema;
8516
8596
  exports.BooleanSchema = BooleanSchema;
8597
+ exports.CODE_LANGUAGES = CODE_LANGUAGES;
8517
8598
  exports.COLOR_FORMATS = COLOR_FORMATS;
8518
8599
  exports.ColorSchema = ColorSchema;
8519
8600
  exports.DEFAULT_APP_HOST = DEFAULT_APP_HOST;
@@ -8523,8 +8604,6 @@ exports.DEFAULT_VAL_REMOTE_HOST = DEFAULT_VAL_REMOTE_HOST;
8523
8604
  exports.DateSchema = DateSchema;
8524
8605
  exports.DateTimeSchema = DateTimeSchema;
8525
8606
  exports.FATAL_ERROR_TYPES = FATAL_ERROR_TYPES;
8526
- exports.FILE_REF_PROP = FILE_REF_PROP;
8527
- exports.FILE_REF_SUBTYPE_TAG = FILE_REF_SUBTYPE_TAG;
8528
8607
  exports.FileSchema = FileSchema;
8529
8608
  exports.GenericSelector = GenericSelector;
8530
8609
  exports.ImageSchema = ImageSchema;
@@ -8554,5 +8633,5 @@ exports.getSourcePathFromRoute = getSourcePathFromRoute;
8554
8633
  exports.hasRemoteFileSchema = hasRemoteFileSchema;
8555
8634
  exports.initVal = initVal;
8556
8635
  exports.modules = modules;
8557
- exports.renderScope = renderScope;
8636
+ exports.previewScope = previewScope;
8558
8637
  exports.splitModuleFilePathAndModulePath = splitModuleFilePathAndModulePath;