@valbuild/core 0.139.0 → 0.141.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +69 -0
- package/dist/declarations/src/extractValModules.d.ts +14 -0
- package/dist/declarations/src/getSha256.d.ts +55 -0
- package/dist/declarations/src/index.d.ts +21 -4
- package/dist/declarations/src/initSchema.d.ts +75 -55
- package/dist/declarations/src/initVal.d.ts +25 -2
- package/dist/declarations/src/remote/validationBasis.d.ts +3 -2
- package/dist/declarations/src/schema/file.d.ts +7 -0
- package/dist/declarations/src/schema/image.d.ts +9 -2
- package/dist/declarations/src/schema/index.d.ts +2 -1
- package/dist/declarations/src/schema/record.d.ts +16 -2
- package/dist/declarations/src/schema/richtext.d.ts +20 -1
- package/dist/declarations/src/schema/validation/ValidationFix.d.ts +1 -1
- package/dist/declarations/src/schema/video.d.ts +249 -0
- package/dist/declarations/src/schema/videoset.d.ts +141 -0
- package/dist/declarations/src/source/galleries.d.ts +20 -0
- package/dist/declarations/src/source/media.d.ts +172 -12
- package/dist/declarations/src/val/index.d.ts +4 -2
- package/dist/{index-8920ba3f.cjs.prod.js → index-13cf45b1.cjs.prod.js} +1547 -134
- package/dist/{index-d949d13b.esm.js → index-a6c53286.esm.js} +1543 -135
- package/dist/{index-e13b725c.cjs.dev.js → index-fae161b5.cjs.dev.js} +1547 -134
- package/dist/valbuild-core.cjs.dev.js +6 -1
- package/dist/valbuild-core.cjs.prod.js +6 -1
- package/dist/valbuild-core.esm.js +1 -1
- package/package.json +1 -1
- package/patch/dist/valbuild-core-patch.cjs.dev.js +1 -1
- package/patch/dist/valbuild-core-patch.cjs.prod.js +1 -1
- package/patch/dist/valbuild-core-patch.esm.js +2 -2
|
@@ -2754,6 +2754,28 @@ var discriminatedUnion = function discriminatedUnion(key) {
|
|
|
2754
2754
|
return new DiscriminatedUnionSchema(key, objects);
|
|
2755
2755
|
};
|
|
2756
2756
|
|
|
2757
|
+
function _objectWithoutPropertiesLoose(r, e) {
|
|
2758
|
+
if (null == r) return {};
|
|
2759
|
+
var t = {};
|
|
2760
|
+
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
|
2761
|
+
if (-1 !== e.indexOf(n)) continue;
|
|
2762
|
+
t[n] = r[n];
|
|
2763
|
+
}
|
|
2764
|
+
return t;
|
|
2765
|
+
}
|
|
2766
|
+
|
|
2767
|
+
function _objectWithoutProperties(e, t) {
|
|
2768
|
+
if (null == e) return {};
|
|
2769
|
+
var o,
|
|
2770
|
+
r,
|
|
2771
|
+
i = _objectWithoutPropertiesLoose(e, t);
|
|
2772
|
+
if (Object.getOwnPropertySymbols) {
|
|
2773
|
+
var n = Object.getOwnPropertySymbols(e);
|
|
2774
|
+
for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
|
|
2775
|
+
}
|
|
2776
|
+
return i;
|
|
2777
|
+
}
|
|
2778
|
+
|
|
2757
2779
|
var RegEx$1 = /^(https?:\/\/[^/]+)\/file\/p\/([^/]+)\/b\/([^/]+)\/v\/([^/]+)\/h\/([^/]+)\/f\/([^/]+)\/p\/(.+)$/;
|
|
2758
2780
|
function splitRemoteRef(ref) {
|
|
2759
2781
|
if (ref[0] === "/") {
|
|
@@ -2795,6 +2817,8 @@ function splitRemoteRef(ref) {
|
|
|
2795
2817
|
};
|
|
2796
2818
|
}
|
|
2797
2819
|
|
|
2820
|
+
var _excluded = ["poster", "captions"];
|
|
2821
|
+
|
|
2798
2822
|
/** What must stay in frame when a page crops an image. */
|
|
2799
2823
|
|
|
2800
2824
|
/**
|
|
@@ -2803,6 +2827,76 @@ function splitRemoteRef(ref) {
|
|
|
2803
2827
|
* here. One place per fact.
|
|
2804
2828
|
*/
|
|
2805
2829
|
|
|
2830
|
+
/**
|
|
2831
|
+
* The still shown before a video plays — `<video poster>`.
|
|
2832
|
+
*
|
|
2833
|
+
* Derived, like a video's `width` and `height`: the Studio grabs the frame at
|
|
2834
|
+
* {@link VideoSource.posterTime} and uploads it as an image, so a page can show
|
|
2835
|
+
* it without decoding the video. It is a media object of its own (a `path`,
|
|
2836
|
+
* and a `patch_id` while unpublished) because it is a file of its own.
|
|
2837
|
+
*/
|
|
2838
|
+
|
|
2839
|
+
/**
|
|
2840
|
+
* One text track of a video — `<track src srclang label kind default>`.
|
|
2841
|
+
*
|
|
2842
|
+
* `path` is a WebVTT file, uploaded like any other file.
|
|
2843
|
+
*/
|
|
2844
|
+
|
|
2845
|
+
/**
|
|
2846
|
+
* What a video FIELD authors, on top of the file it names: the description,
|
|
2847
|
+
* the crop, the poster, the trim and the caption tracks.
|
|
2848
|
+
*
|
|
2849
|
+
* This is the whole value of a field picked from an `s.videoset()`
|
|
2850
|
+
* (`s.video(videosetVal)`) — the mime type, size and length live in the set,
|
|
2851
|
+
* keyed by `path`, and repeating them here is how two copies of one fact get
|
|
2852
|
+
* to disagree. The poster, captions and times stay with the FIELD: one video
|
|
2853
|
+
* used in two places can be trimmed and captioned differently in each.
|
|
2854
|
+
*
|
|
2855
|
+
* Times are in seconds from the start of the file.
|
|
2856
|
+
*/
|
|
2857
|
+
|
|
2858
|
+
/**
|
|
2859
|
+
* What one page chooses about a video — as opposed to what is true of the
|
|
2860
|
+
* file. A field (`s.video()`) carries these for itself; the entry of a set
|
|
2861
|
+
* (`s.videoset()`) carries them as DEFAULTS, which every field picked from the
|
|
2862
|
+
* set starts from and may override key by key. See {@link fillFromGallery}.
|
|
2863
|
+
*/
|
|
2864
|
+
|
|
2865
|
+
/**
|
|
2866
|
+
* A video: a progressive file (`video/mp4`, `video/webm`) or an HLS stream
|
|
2867
|
+
* (`application/vnd.apple.mpegurl`, whose `path` is the master playlist).
|
|
2868
|
+
*
|
|
2869
|
+
* `mimeType` is REQUIRED on a video of its own: a page has to know which of
|
|
2870
|
+
* the two it is holding before it can play it at all — an `.m3u8` handed to a
|
|
2871
|
+
* `<video src>` plays only in Safari. (What tells a video's TYPE apart from an
|
|
2872
|
+
* image's is its declared keys, see {@link IsVideoSource}, because a field
|
|
2873
|
+
* picked from a set has no `mimeType` of its own.)
|
|
2874
|
+
*
|
|
2875
|
+
* `width`, `height`, `duration` and `mimeType` are read from the bytes;
|
|
2876
|
+
* everything else is authored.
|
|
2877
|
+
*/
|
|
2878
|
+
|
|
2879
|
+
/**
|
|
2880
|
+
* Whether a source TYPE is a video's.
|
|
2881
|
+
*
|
|
2882
|
+
* Every media source is "a `path` plus optional fields", so assignability
|
|
2883
|
+
* cannot tell an image from a video: an image is assignable to a set-backed
|
|
2884
|
+
* video and the other way round. The keys a type DECLARES can — only a video
|
|
2885
|
+
* declares `posterTime` — so the readers' conditional types ask this before
|
|
2886
|
+
* they ask about images.
|
|
2887
|
+
*/
|
|
2888
|
+
|
|
2889
|
+
/** The mime type of an HLS master playlist. */
|
|
2890
|
+
var HLS_MIME_TYPE = "application/vnd.apple.mpegurl";
|
|
2891
|
+
|
|
2892
|
+
/** Whether a video is an HLS stream rather than a single progressive file. */
|
|
2893
|
+
function isHlsVideo(src) {
|
|
2894
|
+
if (src.mimeType !== undefined) {
|
|
2895
|
+
return src.mimeType === HLS_MIME_TYPE || src.mimeType.toLowerCase() === "application/x-mpegurl";
|
|
2896
|
+
}
|
|
2897
|
+
return src.path.split("?")[0].toLowerCase().endsWith(".m3u8");
|
|
2898
|
+
}
|
|
2899
|
+
|
|
2806
2900
|
/**
|
|
2807
2901
|
* The structural supertype of every media source.
|
|
2808
2902
|
*
|
|
@@ -2856,66 +2950,181 @@ function resolveMedia(src) {
|
|
|
2856
2950
|
url: mediaUrl(src)
|
|
2857
2951
|
});
|
|
2858
2952
|
}
|
|
2953
|
+
|
|
2954
|
+
/**
|
|
2955
|
+
* A video as a reader sees it: every file it names — the video itself, its
|
|
2956
|
+
* poster and each caption track — carries the URL its bytes are served from.
|
|
2957
|
+
*
|
|
2958
|
+
* Each gets its own {@link mediaUrl} because each is its own file with its own
|
|
2959
|
+
* `patch_id`: replacing only the poster drafts the poster, and the video keeps
|
|
2960
|
+
* its published URL.
|
|
2961
|
+
*/
|
|
2962
|
+
|
|
2963
|
+
/**
|
|
2964
|
+
* The single implementation of {@link ResolvedVideo}. `url` is passed in as a
|
|
2965
|
+
* function so the reader can tag the video's own URL (stega) without tagging
|
|
2966
|
+
* the poster's and the captions', which are not where an edit lands.
|
|
2967
|
+
*/
|
|
2968
|
+
function resolveVideo(src) {
|
|
2969
|
+
var videoUrl = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : mediaUrl;
|
|
2970
|
+
var poster = src.poster,
|
|
2971
|
+
captions = src.captions,
|
|
2972
|
+
rest = _objectWithoutProperties(src, _excluded);
|
|
2973
|
+
var resolved = _objectSpread2(_objectSpread2({}, rest), {}, {
|
|
2974
|
+
url: videoUrl(src)
|
|
2975
|
+
});
|
|
2976
|
+
if (poster && _typeof(poster) === "object" && typeof poster.path === "string") {
|
|
2977
|
+
return withCaptions(_objectSpread2(_objectSpread2({}, resolved), {}, {
|
|
2978
|
+
poster: _objectSpread2(_objectSpread2({}, poster), {}, {
|
|
2979
|
+
url: mediaUrl(poster)
|
|
2980
|
+
})
|
|
2981
|
+
}), captions);
|
|
2982
|
+
}
|
|
2983
|
+
return withCaptions(resolved, captions);
|
|
2984
|
+
}
|
|
2985
|
+
function withCaptions(resolved, captions) {
|
|
2986
|
+
if (!Array.isArray(captions)) {
|
|
2987
|
+
return resolved;
|
|
2988
|
+
}
|
|
2989
|
+
return _objectSpread2(_objectSpread2({}, resolved), {}, {
|
|
2990
|
+
captions: captions.filter(function (track) {
|
|
2991
|
+
return !!track && _typeof(track) === "object" && typeof track.path === "string";
|
|
2992
|
+
}).map(function (track) {
|
|
2993
|
+
return _objectSpread2(_objectSpread2({}, track), {}, {
|
|
2994
|
+
url: mediaUrl(track)
|
|
2995
|
+
});
|
|
2996
|
+
})
|
|
2997
|
+
});
|
|
2998
|
+
}
|
|
2859
2999
|
function isMediaSchema(schema) {
|
|
2860
|
-
return _typeof(schema) === "object" && schema !== null && "type" in schema && (schema.type === "image" || schema.type === "file");
|
|
3000
|
+
return _typeof(schema) === "object" && schema !== null && "type" in schema && (schema.type === "image" || schema.type === "file" || schema.type === "video");
|
|
2861
3001
|
}
|
|
2862
3002
|
|
|
2863
3003
|
/**
|
|
2864
|
-
*
|
|
2865
|
-
*
|
|
2866
|
-
* `s.image(galleryModule)` stores only `{path, alt?, hotspot?}` — the
|
|
2867
|
-
* dimensions and mime type live in the gallery module, keyed by path. This is
|
|
2868
|
-
* the single implementation of that lookup; core, stega/RSC and the Studio all
|
|
2869
|
-
* call it rather than each rolling their own.
|
|
3004
|
+
* What a gallery entry holds as a DEFAULT for the fields picked from it, in
|
|
3005
|
+
* the groups a field overrides together.
|
|
2870
3006
|
*
|
|
2871
|
-
*
|
|
2872
|
-
*
|
|
2873
|
-
*
|
|
2874
|
-
*
|
|
2875
|
-
|
|
2876
|
-
|
|
3007
|
+
* Per key, not per value: a field that has set its own `startTime` still
|
|
3008
|
+
* takes the gallery's `endTime`. The poster is the one pair — `poster` is the
|
|
3009
|
+
* frame at `posterTime`, so a field with either has chosen its own still, and
|
|
3010
|
+
* taking the other half from the gallery would describe a frame nobody chose.
|
|
3011
|
+
*/
|
|
3012
|
+
var GALLERY_DEFAULT_GROUPS = [["alt"], ["hotspot"], ["poster", "posterTime"], ["startTime"], ["endTime"], ["captions"]];
|
|
3013
|
+
|
|
3014
|
+
/** What is true of the file, and the gallery's alone. */
|
|
3015
|
+
var GALLERY_FILE_FACTS = ["width", "height", "mimeType", "duration"];
|
|
3016
|
+
|
|
3017
|
+
/**
|
|
3018
|
+
* The gallery entry a gallery-backed value names, or `null` when it is not
|
|
3019
|
+
* gallery-backed or the gallery has no such entry.
|
|
2877
3020
|
*
|
|
2878
3021
|
* The double lookup is load-bearing: a remote gallery keys its entries by the
|
|
2879
3022
|
* remote URL while the file itself stays on disk under its local path.
|
|
2880
3023
|
*/
|
|
2881
|
-
function
|
|
3024
|
+
function galleryEntryOf(src, schema, getModuleSource) {
|
|
2882
3025
|
if (!isMediaSchema(schema) || !schema.referencedModule) {
|
|
2883
|
-
return
|
|
3026
|
+
return null;
|
|
2884
3027
|
}
|
|
2885
3028
|
var moduleSource = getModuleSource(schema.referencedModule);
|
|
2886
|
-
if (!
|
|
2887
|
-
return
|
|
3029
|
+
if (!isPlainObject(moduleSource)) {
|
|
3030
|
+
return null;
|
|
2888
3031
|
}
|
|
2889
|
-
var
|
|
2890
|
-
var key = src.path in entries ? src.path : null;
|
|
3032
|
+
var key = src.path in moduleSource ? src.path : null;
|
|
2891
3033
|
if (key === null) {
|
|
2892
3034
|
var splitRemoteRefRes = splitRemoteRef(src.path);
|
|
2893
|
-
if (splitRemoteRefRes.status === "success" && splitRemoteRefRes.filePath in
|
|
3035
|
+
if (splitRemoteRefRes.status === "success" && splitRemoteRefRes.filePath in moduleSource) {
|
|
2894
3036
|
key = splitRemoteRefRes.filePath;
|
|
2895
3037
|
}
|
|
2896
3038
|
}
|
|
2897
3039
|
if (key === null) {
|
|
2898
|
-
return
|
|
3040
|
+
return null;
|
|
2899
3041
|
}
|
|
2900
|
-
var entry =
|
|
2901
|
-
|
|
3042
|
+
var entry = moduleSource[key];
|
|
3043
|
+
return isPlainObject(entry) ? entry : null;
|
|
3044
|
+
}
|
|
3045
|
+
|
|
3046
|
+
/**
|
|
3047
|
+
* The value a gallery-backed field means: its own keys, and the gallery's
|
|
3048
|
+
* where it has none.
|
|
3049
|
+
*
|
|
3050
|
+
* `s.image(galleryModule)` and `s.video(videosModule)` store only what one
|
|
3051
|
+
* page chose — the rest lives in the gallery, keyed by path. Two things come
|
|
3052
|
+
* from there:
|
|
3053
|
+
*
|
|
3054
|
+
* - **What is true of the file** — dimensions, mime type, length. The field
|
|
3055
|
+
* never has these, so they are always the gallery's.
|
|
3056
|
+
* - **The defaults** — description, focal point, a video's poster, start, end
|
|
3057
|
+
* and captions ({@link GALLERY_DEFAULT_GROUPS}). An editor sets them once
|
|
3058
|
+
* on the gallery entry; a field that sets its own wins, KEY BY KEY.
|
|
3059
|
+
*
|
|
3060
|
+
* The single implementation of that merge: core, stega/RSC and the Studio all
|
|
3061
|
+
* call it rather than each rolling their own, so a page and the Studio's
|
|
3062
|
+
* preview of it cannot disagree about which poster a video has.
|
|
3063
|
+
*
|
|
3064
|
+
* A gallery whose `alt` schema is a locale record holds an object rather than
|
|
3065
|
+
* a string; that is left alone rather than copied into a field typed
|
|
3066
|
+
* `string`, and making the override locale-shaped is a separate change.
|
|
3067
|
+
*/
|
|
3068
|
+
function fillFromGallery(src, schema, getModuleSource) {
|
|
3069
|
+
var entry = galleryEntryOf(src, schema, getModuleSource);
|
|
3070
|
+
if (entry === null) {
|
|
2902
3071
|
return src;
|
|
2903
3072
|
}
|
|
2904
|
-
var
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
3073
|
+
var own = _objectSpread2({}, src);
|
|
3074
|
+
var filled = {};
|
|
3075
|
+
var _iterator = result._createForOfIteratorHelper(GALLERY_FILE_FACTS),
|
|
3076
|
+
_step;
|
|
3077
|
+
try {
|
|
3078
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
3079
|
+
var key = _step.value;
|
|
3080
|
+
if (entry[key] !== undefined) {
|
|
3081
|
+
filled[key] = entry[key];
|
|
3082
|
+
}
|
|
3083
|
+
}
|
|
3084
|
+
} catch (err) {
|
|
3085
|
+
_iterator.e(err);
|
|
3086
|
+
} finally {
|
|
3087
|
+
_iterator.f();
|
|
3088
|
+
}
|
|
3089
|
+
var _iterator2 = result._createForOfIteratorHelper(GALLERY_DEFAULT_GROUPS),
|
|
3090
|
+
_step2;
|
|
3091
|
+
try {
|
|
3092
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
3093
|
+
var group = _step2.value;
|
|
3094
|
+
if (group.some(function (key) {
|
|
3095
|
+
return own[key] !== undefined;
|
|
3096
|
+
})) {
|
|
3097
|
+
continue;
|
|
3098
|
+
}
|
|
3099
|
+
var _iterator3 = result._createForOfIteratorHelper(group),
|
|
3100
|
+
_step3;
|
|
3101
|
+
try {
|
|
3102
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
3103
|
+
var _key = _step3.value;
|
|
3104
|
+
var value = entry[_key];
|
|
3105
|
+
if (value === undefined || value === null) {
|
|
3106
|
+
continue;
|
|
3107
|
+
}
|
|
3108
|
+
if (_key === "alt" && typeof value !== "string") {
|
|
3109
|
+
continue;
|
|
3110
|
+
}
|
|
3111
|
+
filled[_key] = value;
|
|
3112
|
+
}
|
|
3113
|
+
} catch (err) {
|
|
3114
|
+
_iterator3.e(err);
|
|
3115
|
+
} finally {
|
|
3116
|
+
_iterator3.f();
|
|
3117
|
+
}
|
|
3118
|
+
}
|
|
3119
|
+
} catch (err) {
|
|
3120
|
+
_iterator2.e(err);
|
|
3121
|
+
} finally {
|
|
3122
|
+
_iterator2.f();
|
|
3123
|
+
}
|
|
3124
|
+
return _objectSpread2(_objectSpread2({}, src), filled);
|
|
3125
|
+
}
|
|
3126
|
+
function isPlainObject(value) {
|
|
3127
|
+
return _typeof(value) === "object" && value !== null && !Array.isArray(value);
|
|
2919
3128
|
}
|
|
2920
3129
|
|
|
2921
3130
|
var EXT_TO_MIME_TYPES = {
|
|
@@ -3446,6 +3655,8 @@ var EXT_TO_MIME_TYPES = {
|
|
|
3446
3655
|
qam: "application/vnd.epson.quickanime",
|
|
3447
3656
|
qfx: "application/vnd.intu.qfx",
|
|
3448
3657
|
mov: "video/quicktime",
|
|
3658
|
+
vtt: "text/vtt",
|
|
3659
|
+
mkv: "video/x-matroska",
|
|
3449
3660
|
rar: "application/x-rar-compressed",
|
|
3450
3661
|
ram: "audio/x-pn-realaudio",
|
|
3451
3662
|
rmp: "audio/x-pn-realaudio-plugin",
|
|
@@ -4097,6 +4308,19 @@ var ImageSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4097
4308
|
/** An image of its own, carrying its own dimensions and mime type. */
|
|
4098
4309
|
|
|
4099
4310
|
function image(options, galleryOptions) {
|
|
4311
|
+
return imageOf(false, options, galleryOptions);
|
|
4312
|
+
}
|
|
4313
|
+
|
|
4314
|
+
/**
|
|
4315
|
+
* `s.image()` for a project whose media is all remote (`files.remote` in
|
|
4316
|
+
* `val.config.ts`): the same schema, with `.remote()` already applied. See
|
|
4317
|
+
* `initSchema`.
|
|
4318
|
+
*/
|
|
4319
|
+
|
|
4320
|
+
function remoteImage(options, galleryOptions) {
|
|
4321
|
+
return imageOf(true, options, galleryOptions);
|
|
4322
|
+
}
|
|
4323
|
+
function imageOf(remote, options, galleryOptions) {
|
|
4100
4324
|
var isModule = !!options && !!Internal.getValPath(options);
|
|
4101
4325
|
if (isModule) {
|
|
4102
4326
|
var allModules = {};
|
|
@@ -4110,9 +4334,9 @@ function image(options, galleryOptions) {
|
|
|
4110
4334
|
}
|
|
4111
4335
|
return new ImageSchema((galleryOptions === null || galleryOptions === void 0 ? void 0 : galleryOptions.encode) !== undefined ? {
|
|
4112
4336
|
encode: galleryOptions.encode
|
|
4113
|
-
} : {}, false,
|
|
4337
|
+
} : {}, false, remote, [], allModules);
|
|
4114
4338
|
}
|
|
4115
|
-
return new ImageSchema(options);
|
|
4339
|
+
return new ImageSchema(options, false, remote);
|
|
4116
4340
|
}
|
|
4117
4341
|
|
|
4118
4342
|
var RouteSchema = /*#__PURE__*/function (_Schema) {
|
|
@@ -4371,6 +4595,7 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4371
4595
|
var isHidden = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
4372
4596
|
var description = arguments.length > 5 ? arguments[5] : undefined;
|
|
4373
4597
|
var previewInput = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null;
|
|
4598
|
+
var imgRemote = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;
|
|
4374
4599
|
_classCallCheck(this, RichTextSchema);
|
|
4375
4600
|
_this = _callSuper(this, RichTextSchema);
|
|
4376
4601
|
_this.options = options;
|
|
@@ -4380,6 +4605,7 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4380
4605
|
_this.isHidden = isHidden;
|
|
4381
4606
|
_this.description = description;
|
|
4382
4607
|
_this.previewInput = previewInput;
|
|
4608
|
+
_this.imgRemote = imgRemote;
|
|
4383
4609
|
return _this;
|
|
4384
4610
|
}
|
|
4385
4611
|
|
|
@@ -4406,7 +4632,7 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4406
4632
|
return _createClass(RichTextSchema, [{
|
|
4407
4633
|
key: "describe",
|
|
4408
4634
|
value: function describe(description) {
|
|
4409
|
-
return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.previewInput);
|
|
4635
|
+
return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.previewInput, this.imgRemote);
|
|
4410
4636
|
}
|
|
4411
4637
|
|
|
4412
4638
|
/**
|
|
@@ -4426,7 +4652,7 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4426
4652
|
value: function maxLength(max) {
|
|
4427
4653
|
return new RichTextSchema(_objectSpread2(_objectSpread2({}, this.options), {}, {
|
|
4428
4654
|
maxLength: max
|
|
4429
|
-
}), this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.previewInput);
|
|
4655
|
+
}), this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.previewInput, this.imgRemote);
|
|
4430
4656
|
}
|
|
4431
4657
|
|
|
4432
4658
|
/**
|
|
@@ -4446,7 +4672,7 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4446
4672
|
value: function minLength(min) {
|
|
4447
4673
|
return new RichTextSchema(_objectSpread2(_objectSpread2({}, this.options), {}, {
|
|
4448
4674
|
minLength: min
|
|
4449
|
-
}), this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.previewInput);
|
|
4675
|
+
}), this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.previewInput, this.imgRemote);
|
|
4450
4676
|
}
|
|
4451
4677
|
|
|
4452
4678
|
/**
|
|
@@ -4474,7 +4700,7 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4474
4700
|
}, {
|
|
4475
4701
|
key: "validate",
|
|
4476
4702
|
value: function validate(validationFunction) {
|
|
4477
|
-
return new RichTextSchema(this.options, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]), this.isReadonly, this.isHidden, this.description, this.previewInput);
|
|
4703
|
+
return new RichTextSchema(this.options, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]), this.isReadonly, this.isHidden, this.description, this.previewInput, this.imgRemote);
|
|
4478
4704
|
}
|
|
4479
4705
|
}, {
|
|
4480
4706
|
key: "executeValidate",
|
|
@@ -4649,7 +4875,7 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4649
4875
|
}
|
|
4650
4876
|
var srcPath = unsafeCreateSourcePath(path, "src");
|
|
4651
4877
|
var imgSchema = _this2.options.img;
|
|
4652
|
-
var imageValidationErrors = _typeof(imgSchema) === "object" ? imgSchema["executeValidate"](srcPath, node.src) : new ImageSchema({}, false,
|
|
4878
|
+
var imageValidationErrors = _typeof(imgSchema) === "object" ? imgSchema["executeValidate"](srcPath, node.src) : new ImageSchema({}, false, _this2.imgRemote)["executeValidate"](srcPath, node.src);
|
|
4653
4879
|
if (imageValidationErrors) {
|
|
4654
4880
|
for (var _validationErrorPathS in imageValidationErrors) {
|
|
4655
4881
|
var _current$_validationE;
|
|
@@ -4918,19 +5144,19 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4918
5144
|
}, {
|
|
4919
5145
|
key: "nullable",
|
|
4920
5146
|
value: function nullable() {
|
|
4921
|
-
return new RichTextSchema(this.options, true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.previewInput);
|
|
5147
|
+
return new RichTextSchema(this.options, true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.previewInput, this.imgRemote);
|
|
4922
5148
|
}
|
|
4923
5149
|
}, {
|
|
4924
5150
|
key: "readonly",
|
|
4925
5151
|
value: function readonly() {
|
|
4926
5152
|
var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
4927
|
-
return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.previewInput);
|
|
5153
|
+
return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.previewInput, this.imgRemote);
|
|
4928
5154
|
}
|
|
4929
5155
|
}, {
|
|
4930
5156
|
key: "hidden",
|
|
4931
5157
|
value: function hidden() {
|
|
4932
5158
|
var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
4933
|
-
return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.previewInput);
|
|
5159
|
+
return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.previewInput, this.imgRemote);
|
|
4934
5160
|
}
|
|
4935
5161
|
}, {
|
|
4936
5162
|
key: "executeCustomValidateAt",
|
|
@@ -4958,7 +5184,7 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4958
5184
|
}, {
|
|
4959
5185
|
key: "preview",
|
|
4960
5186
|
value: function preview(select) {
|
|
4961
|
-
return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, select);
|
|
5187
|
+
return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, select, this.imgRemote);
|
|
4962
5188
|
}
|
|
4963
5189
|
}, {
|
|
4964
5190
|
key: "executePreviewItem",
|
|
@@ -5004,7 +5230,10 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5004
5230
|
ul: this.options.ul,
|
|
5005
5231
|
ol: this.options.ol,
|
|
5006
5232
|
a: serializeAnchorSchema(),
|
|
5007
|
-
img: this.options.img && _typeof(this.options.img) === "object" ? this.options.img["executeSerialize"]() :
|
|
5233
|
+
img: this.options.img && _typeof(this.options.img) === "object" ? this.options.img["executeSerialize"]() :
|
|
5234
|
+
// The Studio decides local or remote by the serialized image
|
|
5235
|
+
// schema, and `true` carries no such answer.
|
|
5236
|
+
this.options.img && this.imgRemote ? new ImageSchema(undefined, false, true)["executeSerialize"]() : this.options.img
|
|
5008
5237
|
};
|
|
5009
5238
|
return {
|
|
5010
5239
|
type: "richtext",
|
|
@@ -5023,6 +5252,14 @@ var richtext = function richtext(options) {
|
|
|
5023
5252
|
return new RichTextSchema(options !== null && options !== void 0 ? options : {});
|
|
5024
5253
|
};
|
|
5025
5254
|
|
|
5255
|
+
/**
|
|
5256
|
+
* `s.richtext()` for a project whose media is all remote (`files.remote` in
|
|
5257
|
+
* `val.config.ts`): `img: true` is a remote image. See `initSchema`.
|
|
5258
|
+
*/
|
|
5259
|
+
var remoteRichtext = function remoteRichtext(options) {
|
|
5260
|
+
return new RichTextSchema(options !== null && options !== void 0 ? options : {}, false, [], false, false, undefined, null, true);
|
|
5261
|
+
};
|
|
5262
|
+
|
|
5026
5263
|
function _regeneratorDefine(e, r, n, t) {
|
|
5027
5264
|
var i = Object.defineProperty;
|
|
5028
5265
|
try {
|
|
@@ -5471,6 +5708,207 @@ function missingDeclaredKeys(declared, present) {
|
|
|
5471
5708
|
});
|
|
5472
5709
|
}
|
|
5473
5710
|
|
|
5711
|
+
/**
|
|
5712
|
+
* The checks of what one page chose about a video — its times, focal point,
|
|
5713
|
+
* poster and captions — shared by the two places those choices are made: a
|
|
5714
|
+
* field (`s.video()`) and the entry of a set (`s.videoset()`), which holds the
|
|
5715
|
+
* same choices as the defaults every field picked from it starts from.
|
|
5716
|
+
*/
|
|
5717
|
+
|
|
5718
|
+
function isRecord(value) {
|
|
5719
|
+
return _typeof(value) === "object" && value !== null && !Array.isArray(value);
|
|
5720
|
+
}
|
|
5721
|
+
function stripQuery$1(path) {
|
|
5722
|
+
return path.split("?")[0];
|
|
5723
|
+
}
|
|
5724
|
+
|
|
5725
|
+
/**
|
|
5726
|
+
* What is checked, typed as what it IS rather than what it should be: a
|
|
5727
|
+
* field's value and a set's entry both reach here from hand-written JSON
|
|
5728
|
+
* that never saw the type.
|
|
5729
|
+
*/
|
|
5730
|
+
|
|
5731
|
+
function isNonNegativeNumber(value) {
|
|
5732
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
5733
|
+
}
|
|
5734
|
+
function validateTimes(src, duration) {
|
|
5735
|
+
var errors = [];
|
|
5736
|
+
var _iterator = result._createForOfIteratorHelper(["posterTime", "startTime", "endTime"]),
|
|
5737
|
+
_step;
|
|
5738
|
+
try {
|
|
5739
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
5740
|
+
var key = _step.value;
|
|
5741
|
+
var value = src[key];
|
|
5742
|
+
if (value === undefined) {
|
|
5743
|
+
continue;
|
|
5744
|
+
}
|
|
5745
|
+
if (!isNonNegativeNumber(value)) {
|
|
5746
|
+
errors.push({
|
|
5747
|
+
message: "'".concat(key, "' must be a number of seconds, 0 or more. Got: ").concat(JSON.stringify(value)),
|
|
5748
|
+
value: src
|
|
5749
|
+
});
|
|
5750
|
+
} else if (duration !== undefined && value > duration) {
|
|
5751
|
+
errors.push({
|
|
5752
|
+
message: "'".concat(key, "' (").concat(value, "s) is after the end of the video (").concat(duration, "s)."),
|
|
5753
|
+
value: src
|
|
5754
|
+
});
|
|
5755
|
+
}
|
|
5756
|
+
}
|
|
5757
|
+
} catch (err) {
|
|
5758
|
+
_iterator.e(err);
|
|
5759
|
+
} finally {
|
|
5760
|
+
_iterator.f();
|
|
5761
|
+
}
|
|
5762
|
+
var startTime = src.startTime,
|
|
5763
|
+
endTime = src.endTime;
|
|
5764
|
+
if (isNonNegativeNumber(startTime) && isNonNegativeNumber(endTime) && startTime >= endTime) {
|
|
5765
|
+
errors.push({
|
|
5766
|
+
message: "'startTime' (".concat(startTime, "s) must be before 'endTime' (").concat(endTime, "s)."),
|
|
5767
|
+
value: src
|
|
5768
|
+
});
|
|
5769
|
+
}
|
|
5770
|
+
return errors;
|
|
5771
|
+
}
|
|
5772
|
+
function validateHotspot(src) {
|
|
5773
|
+
if (src.hotspot === undefined) {
|
|
5774
|
+
return [];
|
|
5775
|
+
}
|
|
5776
|
+
var hotspot = src.hotspot;
|
|
5777
|
+
if (!isRecord(hotspot) || typeof hotspot.x !== "number" || typeof hotspot.y !== "number" || hotspot.x < 0 || hotspot.x > 1 || hotspot.y < 0 || hotspot.y > 1) {
|
|
5778
|
+
return [{
|
|
5779
|
+
message: "'hotspot' must be { x, y } with both between 0 and 1.",
|
|
5780
|
+
value: src
|
|
5781
|
+
}];
|
|
5782
|
+
}
|
|
5783
|
+
return [];
|
|
5784
|
+
}
|
|
5785
|
+
function validatePoster(src) {
|
|
5786
|
+
if (src.poster === undefined) {
|
|
5787
|
+
return [];
|
|
5788
|
+
}
|
|
5789
|
+
var poster = src.poster;
|
|
5790
|
+
if (!isRecord(poster) || typeof poster.path !== "string") {
|
|
5791
|
+
return [{
|
|
5792
|
+
message: "'poster' must be an image object with a 'path'.",
|
|
5793
|
+
value: src
|
|
5794
|
+
}];
|
|
5795
|
+
}
|
|
5796
|
+
var mimeType = filenameToMimeType(stripQuery$1(poster.path));
|
|
5797
|
+
if (!mimeType || !mimeType.startsWith("image/")) {
|
|
5798
|
+
return [{
|
|
5799
|
+
message: "The poster must be an image. Got: ".concat(poster.path),
|
|
5800
|
+
value: src
|
|
5801
|
+
}];
|
|
5802
|
+
}
|
|
5803
|
+
return [];
|
|
5804
|
+
}
|
|
5805
|
+
var CAPTION_KINDS = ["subtitles", "captions"];
|
|
5806
|
+
function validateCaptions(src) {
|
|
5807
|
+
if (src.captions === undefined) {
|
|
5808
|
+
return [];
|
|
5809
|
+
}
|
|
5810
|
+
if (!Array.isArray(src.captions)) {
|
|
5811
|
+
return [{
|
|
5812
|
+
message: "'captions' must be an array.",
|
|
5813
|
+
value: src
|
|
5814
|
+
}];
|
|
5815
|
+
}
|
|
5816
|
+
var errors = [];
|
|
5817
|
+
var defaults = 0;
|
|
5818
|
+
var seen = new Set();
|
|
5819
|
+
src.captions.forEach(function (track, i) {
|
|
5820
|
+
var at = "Caption track ".concat(i + 1);
|
|
5821
|
+
if (!isRecord(track)) {
|
|
5822
|
+
errors.push({
|
|
5823
|
+
message: "".concat(at, " must be an object."),
|
|
5824
|
+
value: src
|
|
5825
|
+
});
|
|
5826
|
+
return;
|
|
5827
|
+
}
|
|
5828
|
+
var t = track;
|
|
5829
|
+
if (typeof t.path !== "string") {
|
|
5830
|
+
errors.push({
|
|
5831
|
+
message: "".concat(at, " has no 'path'."),
|
|
5832
|
+
value: src
|
|
5833
|
+
});
|
|
5834
|
+
} else if (filenameToMimeType(stripQuery$1(t.path)) !== "text/vtt") {
|
|
5835
|
+
errors.push({
|
|
5836
|
+
message: "".concat(at, " must be a WebVTT (.vtt) file. Got: ").concat(t.path),
|
|
5837
|
+
value: src
|
|
5838
|
+
});
|
|
5839
|
+
}
|
|
5840
|
+
if (typeof t.srclang !== "string" || t.srclang.trim() === "") {
|
|
5841
|
+
errors.push({
|
|
5842
|
+
message: "".concat(at, " needs a language ('srclang'), e.g. \"en\"."),
|
|
5843
|
+
value: src
|
|
5844
|
+
});
|
|
5845
|
+
}
|
|
5846
|
+
if (t.label !== undefined && typeof t.label !== "string") {
|
|
5847
|
+
errors.push({
|
|
5848
|
+
message: "".concat(at, ": 'label' must be a string."),
|
|
5849
|
+
value: src
|
|
5850
|
+
});
|
|
5851
|
+
}
|
|
5852
|
+
if (t.kind !== undefined && (typeof t.kind !== "string" || !CAPTION_KINDS.includes(t.kind))) {
|
|
5853
|
+
errors.push({
|
|
5854
|
+
message: "".concat(at, ": 'kind' must be \"subtitles\" or \"captions\"."),
|
|
5855
|
+
value: src
|
|
5856
|
+
});
|
|
5857
|
+
}
|
|
5858
|
+
if (t["default"] !== undefined && typeof t["default"] !== "boolean") {
|
|
5859
|
+
errors.push({
|
|
5860
|
+
message: "".concat(at, ": 'default' must be true or false."),
|
|
5861
|
+
value: src
|
|
5862
|
+
});
|
|
5863
|
+
}
|
|
5864
|
+
if (t["default"] === true) {
|
|
5865
|
+
defaults++;
|
|
5866
|
+
}
|
|
5867
|
+
if (typeof t.srclang === "string") {
|
|
5868
|
+
var _t$kind;
|
|
5869
|
+
var key = "".concat((_t$kind = t.kind) !== null && _t$kind !== void 0 ? _t$kind : "subtitles", ":").concat(t.srclang);
|
|
5870
|
+
if (seen.has(key)) {
|
|
5871
|
+
errors.push({
|
|
5872
|
+
message: "".concat(at, " repeats the language '").concat(t.srclang, "'."),
|
|
5873
|
+
value: src
|
|
5874
|
+
});
|
|
5875
|
+
}
|
|
5876
|
+
seen.add(key);
|
|
5877
|
+
}
|
|
5878
|
+
});
|
|
5879
|
+
if (defaults > 1) {
|
|
5880
|
+
errors.push({
|
|
5881
|
+
message: "At most one caption track can be the default. ".concat(defaults, " are."),
|
|
5882
|
+
value: src
|
|
5883
|
+
});
|
|
5884
|
+
}
|
|
5885
|
+
return errors;
|
|
5886
|
+
}
|
|
5887
|
+
|
|
5888
|
+
function isObject(value) {
|
|
5889
|
+
return _typeof(value) === "object" && value !== null && !Array.isArray(value);
|
|
5890
|
+
}
|
|
5891
|
+
|
|
5892
|
+
/** What a media collection (`s.imageset`, `s.fileset`, `s.videoset`) holds. */
|
|
5893
|
+
|
|
5894
|
+
/**
|
|
5895
|
+
* The fix code a media collection of `type` reports for `check`.
|
|
5896
|
+
*
|
|
5897
|
+
* One function rather than a ternary at each site: there were two kinds of
|
|
5898
|
+
* collection when every site was written as `type === "images" ? … : …`, and
|
|
5899
|
+
* a third kind silently took the files branch.
|
|
5900
|
+
*/
|
|
5901
|
+
function mediaCollectionFix(type, check) {
|
|
5902
|
+
return "".concat(type, ":").concat(check);
|
|
5903
|
+
}
|
|
5904
|
+
|
|
5905
|
+
/** The singular a message uses for one entry of a collection of `type`. */
|
|
5906
|
+
var MEDIA_ENTRY_LABEL = {
|
|
5907
|
+
files: "file",
|
|
5908
|
+
images: "image",
|
|
5909
|
+
videos: "video"
|
|
5910
|
+
};
|
|
5911
|
+
|
|
5474
5912
|
/**
|
|
5475
5913
|
* `.render(...)` is for records whose entries the generic record editor draws.
|
|
5476
5914
|
* A router's entries are pages and a gallery's are media, and both have UIs of
|
|
@@ -5662,7 +6100,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5662
6100
|
_iterator.f();
|
|
5663
6101
|
}
|
|
5664
6102
|
if (this.mediaOptions) {
|
|
5665
|
-
var checkFix = this.mediaOptions.type
|
|
6103
|
+
var checkFix = mediaCollectionFix(this.mediaOptions.type, "check-unique-folder");
|
|
5666
6104
|
var uniqueCheckError = {
|
|
5667
6105
|
message: "Gallery directory '".concat(this.mediaOptions.dir, "' must be unique across all galleries"),
|
|
5668
6106
|
value: {
|
|
@@ -5680,7 +6118,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5680
6118
|
} else {
|
|
5681
6119
|
error = _defineProperty({}, path, [uniqueCheckError]);
|
|
5682
6120
|
}
|
|
5683
|
-
var allFilesCheckFix = this.mediaOptions.type
|
|
6121
|
+
var allFilesCheckFix = mediaCollectionFix(this.mediaOptions.type, "check-all-files");
|
|
5684
6122
|
var allFilesCheckError = {
|
|
5685
6123
|
message: "Directory '".concat(this.mediaOptions.dir, "' may have files not tracked by this gallery"),
|
|
5686
6124
|
value: {
|
|
@@ -5734,7 +6172,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5734
6172
|
_this2.markKeyErrorsAtPath(keyErr, subPath);
|
|
5735
6173
|
}
|
|
5736
6174
|
error = _this2.mergeValidationErrors(error, keyErr);
|
|
5737
|
-
var entryErr = _this2.validateMediaEntry(subPath, elem);
|
|
6175
|
+
var entryErr = _this2.validateMediaEntry(subPath, key, elem);
|
|
5738
6176
|
if (entryErr) {
|
|
5739
6177
|
_this2.markKeyErrorsAtPath(entryErr, subPath);
|
|
5740
6178
|
}
|
|
@@ -5848,8 +6286,8 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5848
6286
|
dir = _this$mediaOptions.dir,
|
|
5849
6287
|
isRemote = _this$mediaOptions.remote,
|
|
5850
6288
|
type = _this$mediaOptions.type;
|
|
5851
|
-
var mediaLabel = type
|
|
5852
|
-
var checkRemoteFix = type
|
|
6289
|
+
var mediaLabel = type;
|
|
6290
|
+
var checkRemoteFix = mediaCollectionFix(type, "check-remote");
|
|
5853
6291
|
var isRemoteUrl = this.isRemoteUrl(key);
|
|
5854
6292
|
var isLocalPath = key === dir || key.startsWith(dir + "/");
|
|
5855
6293
|
if (isRemote) {
|
|
@@ -5882,9 +6320,9 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5882
6320
|
}]);
|
|
5883
6321
|
}
|
|
5884
6322
|
// Local path in a remote gallery: needs to be uploaded to remote.
|
|
5885
|
-
var uploadRemoteFix = type
|
|
6323
|
+
var uploadRemoteFix = mediaCollectionFix(type, "upload-remote");
|
|
5886
6324
|
return _defineProperty({}, path, [{
|
|
5887
|
-
message: "Expected a remote ".concat(type
|
|
6325
|
+
message: "Expected a remote ".concat(MEDIA_ENTRY_LABEL[type], ", but got a local path. Use Val tooling (CLI --fix, VS Code extension, or Val Studio) to upload it. Got: ").concat(key),
|
|
5888
6326
|
value: key,
|
|
5889
6327
|
fixes: [uploadRemoteFix]
|
|
5890
6328
|
}]);
|
|
@@ -5908,7 +6346,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5908
6346
|
}
|
|
5909
6347
|
}, {
|
|
5910
6348
|
key: "validateMediaEntry",
|
|
5911
|
-
value: function validateMediaEntry(path, entry) {
|
|
6349
|
+
value: function validateMediaEntry(path, key, entry) {
|
|
5912
6350
|
if (!this.mediaOptions) {
|
|
5913
6351
|
return false;
|
|
5914
6352
|
}
|
|
@@ -5924,6 +6362,40 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5924
6362
|
}
|
|
5925
6363
|
var entryObj = entry;
|
|
5926
6364
|
var errors = [];
|
|
6365
|
+
if (type === "videos") {
|
|
6366
|
+
// What is read from the bytes. Missing is a fix (the CLI reads them,
|
|
6367
|
+
// from disk or — for a remote entry — over HTTP with Range requests);
|
|
6368
|
+
// present and wrong is an error, because a fix that overwrote an
|
|
6369
|
+
// authored number would be guessing which of the two was right.
|
|
6370
|
+
var missing = ["mimeType", "width", "height", "duration"].filter(function (k) {
|
|
6371
|
+
return entryObj[k] === undefined;
|
|
6372
|
+
});
|
|
6373
|
+
if (missing.length > 0) {
|
|
6374
|
+
return _defineProperty({}, path, [{
|
|
6375
|
+
message: "Video metadata is missing: ".concat(missing.join(", "), "."),
|
|
6376
|
+
value: entry,
|
|
6377
|
+
fixes: ["videos:add-metadata"]
|
|
6378
|
+
}]);
|
|
6379
|
+
}
|
|
6380
|
+
var _iterator3 = result._createForOfIteratorHelper(["width", "height", "duration"]),
|
|
6381
|
+
_step3;
|
|
6382
|
+
try {
|
|
6383
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
6384
|
+
var k = _step3.value;
|
|
6385
|
+
var value = entryObj[k];
|
|
6386
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
6387
|
+
errors.push({
|
|
6388
|
+
message: "Expected '".concat(k, "' to be a positive number, got '").concat(JSON.stringify(value), "'"),
|
|
6389
|
+
value: entry
|
|
6390
|
+
});
|
|
6391
|
+
}
|
|
6392
|
+
}
|
|
6393
|
+
} catch (err) {
|
|
6394
|
+
_iterator3.e(err);
|
|
6395
|
+
} finally {
|
|
6396
|
+
_iterator3.f();
|
|
6397
|
+
}
|
|
6398
|
+
}
|
|
5927
6399
|
if (type === "images") {
|
|
5928
6400
|
// Validate width
|
|
5929
6401
|
if (typeof entryObj.width !== "number" || entryObj.width <= 0) {
|
|
@@ -5948,6 +6420,15 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5948
6420
|
message: "Expected 'mimeType' to be a string, got '".concat(_typeof(entryObj.mimeType), "'"),
|
|
5949
6421
|
value: entry
|
|
5950
6422
|
});
|
|
6423
|
+
} else if (type === "videos" && entryObj.mimeType === HLS_MIME_TYPE) {
|
|
6424
|
+
// A stream is what the Studio made of an upload that WAS accepted, so
|
|
6425
|
+
// `accept` (which is about what may be picked) is not asked about it.
|
|
6426
|
+
if (!key.split("?")[0].toLowerCase().endsWith(".m3u8")) {
|
|
6427
|
+
errors.push({
|
|
6428
|
+
message: "An HLS video must be keyed by its master playlist (.m3u8). Got: ".concat(key),
|
|
6429
|
+
value: entry
|
|
6430
|
+
});
|
|
6431
|
+
}
|
|
5951
6432
|
} else {
|
|
5952
6433
|
var mimeTypeError = this.validateMediaMimeType(entryObj.mimeType, accept);
|
|
5953
6434
|
if (mimeTypeError) {
|
|
@@ -5957,6 +6438,26 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5957
6438
|
});
|
|
5958
6439
|
}
|
|
5959
6440
|
}
|
|
6441
|
+
if (type === "videos") {
|
|
6442
|
+
// The defaults every field picked from the set starts from, checked as
|
|
6443
|
+
// a field's own would be: they are the same choices, made once.
|
|
6444
|
+
var duration = typeof entryObj.duration === "number" && entryObj.duration > 0 ? entryObj.duration : undefined;
|
|
6445
|
+
errors.push.apply(errors, _toConsumableArray(validateTimes(entryObj, duration)).concat(_toConsumableArray(validateHotspot(entryObj)), _toConsumableArray(validatePoster(entryObj)), _toConsumableArray(validateCaptions(entryObj))));
|
|
6446
|
+
var misplaced = this.misplacedEntryFiles(key, entryObj);
|
|
6447
|
+
if (misplaced.length > 0) {
|
|
6448
|
+
var these = misplaced.length === 1 ? "this file is" : "".concat(misplaced.length, " files are");
|
|
6449
|
+
errors.push(this.mediaOptions.remote ? {
|
|
6450
|
+
message: "Expected the entry's files on Val Remote, but ".concat(these, " stored locally: ").concat(misplaced.join(", ")),
|
|
6451
|
+
// The key, as a local key's upload error carries: the fix
|
|
6452
|
+
// rewrites the entry under it.
|
|
6453
|
+
value: key,
|
|
6454
|
+
fixes: ["videos:upload-remote"]
|
|
6455
|
+
} : {
|
|
6456
|
+
message: "Expected the entry's files under ".concat(this.mediaOptions.dir, ", but ").concat(these, " remote: ").concat(misplaced.join(", ")),
|
|
6457
|
+
value: entry
|
|
6458
|
+
});
|
|
6459
|
+
}
|
|
6460
|
+
}
|
|
5960
6461
|
if (type === "images") {
|
|
5961
6462
|
// Validate hotspot if present
|
|
5962
6463
|
if (entryObj.hotspot !== undefined) {
|
|
@@ -5968,7 +6469,8 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5968
6469
|
});
|
|
5969
6470
|
}
|
|
5970
6471
|
}
|
|
5971
|
-
|
|
6472
|
+
}
|
|
6473
|
+
if (type === "images" || type === "videos") {
|
|
5972
6474
|
// Validate alt using the alt schema
|
|
5973
6475
|
var altPath = createValPathOfItem(path, "alt");
|
|
5974
6476
|
if (altPath && altSchema) {
|
|
@@ -5983,16 +6485,59 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5983
6485
|
}
|
|
5984
6486
|
return false;
|
|
5985
6487
|
}
|
|
6488
|
+
|
|
6489
|
+
/**
|
|
6490
|
+
* The poster and caption files of a set's entry that are not where the set
|
|
6491
|
+
* keeps its files. Asked only once the key itself is in place: a local key
|
|
6492
|
+
* in a remote set is reported (and uploaded) as the entry, files and all,
|
|
6493
|
+
* and a second error for its poster would be the same one twice.
|
|
6494
|
+
*/
|
|
5986
6495
|
}, {
|
|
5987
|
-
key: "
|
|
5988
|
-
value: function
|
|
5989
|
-
|
|
5990
|
-
|
|
6496
|
+
key: "misplacedEntryFiles",
|
|
6497
|
+
value: function misplacedEntryFiles(key, entry) {
|
|
6498
|
+
var _this3 = this;
|
|
6499
|
+
if (!this.mediaOptions) {
|
|
6500
|
+
return [];
|
|
5991
6501
|
}
|
|
5992
|
-
|
|
5993
|
-
|
|
6502
|
+
var remote = this.mediaOptions.remote;
|
|
6503
|
+
if (this.isRemoteUrl(key) !== remote) {
|
|
6504
|
+
return [];
|
|
5994
6505
|
}
|
|
5995
|
-
|
|
6506
|
+
var files = [];
|
|
6507
|
+
var poster = entry.poster;
|
|
6508
|
+
if (isObject(poster) && typeof poster.path === "string") {
|
|
6509
|
+
files.push(poster.path);
|
|
6510
|
+
}
|
|
6511
|
+
if (Array.isArray(entry.captions)) {
|
|
6512
|
+
var _iterator4 = result._createForOfIteratorHelper(entry.captions),
|
|
6513
|
+
_step4;
|
|
6514
|
+
try {
|
|
6515
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
6516
|
+
var track = _step4.value;
|
|
6517
|
+
if (isObject(track) && typeof track.path === "string") {
|
|
6518
|
+
files.push(track.path);
|
|
6519
|
+
}
|
|
6520
|
+
}
|
|
6521
|
+
} catch (err) {
|
|
6522
|
+
_iterator4.e(err);
|
|
6523
|
+
} finally {
|
|
6524
|
+
_iterator4.f();
|
|
6525
|
+
}
|
|
6526
|
+
}
|
|
6527
|
+
return files.filter(function (file) {
|
|
6528
|
+
return _this3.isRemoteUrl(file) !== remote;
|
|
6529
|
+
});
|
|
6530
|
+
}
|
|
6531
|
+
}, {
|
|
6532
|
+
key: "validateMediaMimeType",
|
|
6533
|
+
value: function validateMediaMimeType(mimeType, accept) {
|
|
6534
|
+
if (!mimeType.includes("/")) {
|
|
6535
|
+
return "Invalid mime type format. Got: '".concat(mimeType, "'");
|
|
6536
|
+
}
|
|
6537
|
+
if (!mimeTypeMatchesAccept(mimeType, accept)) {
|
|
6538
|
+
return "Mime type mismatch. Found '".concat(mimeType, "' but schema accepts '").concat(accept, "'");
|
|
6539
|
+
}
|
|
6540
|
+
return null;
|
|
5996
6541
|
}
|
|
5997
6542
|
}, {
|
|
5998
6543
|
key: "executeAssert",
|
|
@@ -6346,6 +6891,9 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
6346
6891
|
if (this.mediaOptions.encode !== undefined) {
|
|
6347
6892
|
result.encode = this.mediaOptions.encode;
|
|
6348
6893
|
}
|
|
6894
|
+
if (this.mediaOptions.stream !== undefined) {
|
|
6895
|
+
result.stream = this.mediaOptions.stream;
|
|
6896
|
+
}
|
|
6349
6897
|
if (this.mediaOptions.altSchema) {
|
|
6350
6898
|
result.alt = this.mediaOptions.altSchema["executeSerialize"]();
|
|
6351
6899
|
}
|
|
@@ -10391,7 +10939,472 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
|
|
|
10391
10939
|
if (modulePaths.length === 0) {
|
|
10392
10940
|
return null;
|
|
10393
10941
|
}
|
|
10394
|
-
return this.moduleMetadata[modulePaths[0]];
|
|
10942
|
+
return this.moduleMetadata[modulePaths[0]];
|
|
10943
|
+
}
|
|
10944
|
+
}, {
|
|
10945
|
+
key: "executeAssert",
|
|
10946
|
+
value: function executeAssert(path, src) {
|
|
10947
|
+
if (this.opt && src === null) {
|
|
10948
|
+
return {
|
|
10949
|
+
success: true,
|
|
10950
|
+
data: src
|
|
10951
|
+
};
|
|
10952
|
+
}
|
|
10953
|
+
if (src === null) {
|
|
10954
|
+
return {
|
|
10955
|
+
success: false,
|
|
10956
|
+
errors: _defineProperty({}, path, [{
|
|
10957
|
+
message: "Expected 'object', got 'null'",
|
|
10958
|
+
typeError: true
|
|
10959
|
+
}])
|
|
10960
|
+
};
|
|
10961
|
+
}
|
|
10962
|
+
if (_typeof(src) !== "object") {
|
|
10963
|
+
return {
|
|
10964
|
+
success: false,
|
|
10965
|
+
errors: _defineProperty({}, path, [{
|
|
10966
|
+
message: "Expected object, got '".concat(_typeof(src), "'"),
|
|
10967
|
+
typeError: true
|
|
10968
|
+
}])
|
|
10969
|
+
};
|
|
10970
|
+
}
|
|
10971
|
+
if (!("path" in src) || typeof src.path !== "string") {
|
|
10972
|
+
return {
|
|
10973
|
+
success: false,
|
|
10974
|
+
errors: _defineProperty({}, path, [{
|
|
10975
|
+
message: "A file must be an object with a 'path' (error type: missing_path)",
|
|
10976
|
+
typeError: true
|
|
10977
|
+
}])
|
|
10978
|
+
};
|
|
10979
|
+
}
|
|
10980
|
+
return {
|
|
10981
|
+
success: true,
|
|
10982
|
+
data: src
|
|
10983
|
+
};
|
|
10984
|
+
}
|
|
10985
|
+
}, {
|
|
10986
|
+
key: "nullable",
|
|
10987
|
+
value: function nullable() {
|
|
10988
|
+
return new FileSchema(this.options, true, this.isRemote, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, this.isHidden, this.description, this.previewInput);
|
|
10989
|
+
}
|
|
10990
|
+
}, {
|
|
10991
|
+
key: "readonly",
|
|
10992
|
+
value: function readonly() {
|
|
10993
|
+
var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
10994
|
+
return new FileSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, isReadonly, this.isHidden, this.description, this.previewInput);
|
|
10995
|
+
}
|
|
10996
|
+
}, {
|
|
10997
|
+
key: "hidden",
|
|
10998
|
+
value: function hidden() {
|
|
10999
|
+
var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
11000
|
+
return new FileSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, isHidden, this.description, this.previewInput);
|
|
11001
|
+
}
|
|
11002
|
+
}, {
|
|
11003
|
+
key: "executeCustomValidateAt",
|
|
11004
|
+
value: function executeCustomValidateAt(path, src) {
|
|
11005
|
+
return this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
|
|
11006
|
+
path: path
|
|
11007
|
+
});
|
|
11008
|
+
}
|
|
11009
|
+
|
|
11010
|
+
/**
|
|
11011
|
+
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
11012
|
+
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
11013
|
+
* itself is edited (that is `render`). See `preview.ts`.
|
|
11014
|
+
*
|
|
11015
|
+
* @example
|
|
11016
|
+
* const schema = s.array(
|
|
11017
|
+
* s.file().preview(({ val }) => ({ title: val.path })),
|
|
11018
|
+
* );
|
|
11019
|
+
* export default c.define("/example.val.ts", schema, [
|
|
11020
|
+
* { path: "/public/val/example.pdf", mimeType: "application/pdf" },
|
|
11021
|
+
* ]);
|
|
11022
|
+
*/
|
|
11023
|
+
}, {
|
|
11024
|
+
key: "preview",
|
|
11025
|
+
value: function preview(select) {
|
|
11026
|
+
return new FileSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, this.isHidden, this.description, select);
|
|
11027
|
+
}
|
|
11028
|
+
}, {
|
|
11029
|
+
key: "executePreviewItem",
|
|
11030
|
+
value: function executePreviewItem(src) {
|
|
11031
|
+
if (this.previewInput === null) {
|
|
11032
|
+
return null;
|
|
11033
|
+
}
|
|
11034
|
+
return this.previewInput({
|
|
11035
|
+
val: src
|
|
11036
|
+
});
|
|
11037
|
+
}
|
|
11038
|
+
}, {
|
|
11039
|
+
key: "declaresItemPreview",
|
|
11040
|
+
value: function declaresItemPreview() {
|
|
11041
|
+
return this.previewInput !== null;
|
|
11042
|
+
}
|
|
11043
|
+
}, {
|
|
11044
|
+
key: "executeSerialize",
|
|
11045
|
+
value: function executeSerialize() {
|
|
11046
|
+
var _this$customValidateF;
|
|
11047
|
+
var modulePaths = this.moduleMetadata ? Object.keys(this.moduleMetadata) : [];
|
|
11048
|
+
return {
|
|
11049
|
+
type: "file",
|
|
11050
|
+
preview: this.previewInput ? true : undefined,
|
|
11051
|
+
options: this.options,
|
|
11052
|
+
opt: this.opt,
|
|
11053
|
+
remote: this.isRemote,
|
|
11054
|
+
customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
|
|
11055
|
+
referencedModule: modulePaths.length > 0 ? modulePaths[0] : undefined,
|
|
11056
|
+
readonly: this.isReadonly,
|
|
11057
|
+
hidden: this.isHidden,
|
|
11058
|
+
description: this.description
|
|
11059
|
+
};
|
|
11060
|
+
}
|
|
11061
|
+
}]);
|
|
11062
|
+
}(Schema);
|
|
11063
|
+
|
|
11064
|
+
/**
|
|
11065
|
+
* A file picked from a gallery. Its mime type lives in the gallery, so the
|
|
11066
|
+
* field carries only the path.
|
|
11067
|
+
*/
|
|
11068
|
+
|
|
11069
|
+
/** A file of its own, carrying its own mime type. */
|
|
11070
|
+
|
|
11071
|
+
function file(options) {
|
|
11072
|
+
return fileOf(false, options);
|
|
11073
|
+
}
|
|
11074
|
+
|
|
11075
|
+
/**
|
|
11076
|
+
* `s.file()` for a project whose media is all remote (`files.remote` in
|
|
11077
|
+
* `val.config.ts`): the same schema, with `.remote()` already applied. See
|
|
11078
|
+
* `initSchema`.
|
|
11079
|
+
*/
|
|
11080
|
+
|
|
11081
|
+
function remoteFile(options) {
|
|
11082
|
+
return fileOf(true, options);
|
|
11083
|
+
}
|
|
11084
|
+
function fileOf(remote, options) {
|
|
11085
|
+
var isModule = !!options && !!Internal.getValPath(options);
|
|
11086
|
+
if (isModule) {
|
|
11087
|
+
var allModules = {};
|
|
11088
|
+
for (var _i = 0, _arr = [options]; _i < _arr.length; _i++) {
|
|
11089
|
+
var valModule = _arr[_i];
|
|
11090
|
+
var modulePath = getValPath(valModule);
|
|
11091
|
+
if (modulePath === undefined) {
|
|
11092
|
+
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.");
|
|
11093
|
+
}
|
|
11094
|
+
allModules[modulePath] = getSource(valModule);
|
|
11095
|
+
}
|
|
11096
|
+
return new FileSchema({}, false, remote, [], allModules);
|
|
11097
|
+
}
|
|
11098
|
+
return new FileSchema(options, false, remote);
|
|
11099
|
+
}
|
|
11100
|
+
|
|
11101
|
+
/**
|
|
11102
|
+
* Turn an upload into an HLS stream, in the browser, before it is uploaded.
|
|
11103
|
+
*
|
|
11104
|
+
* The Studio transcodes the picked file with WebCodecs into one rendition per
|
|
11105
|
+
* entry of `renditions` (never upscaled: a 720p upload gets no 1080p
|
|
11106
|
+
* rendition), segments each into CMAF and writes the playlists. What is stored
|
|
11107
|
+
* is a directory beside the other uploads; the field's `path` is its master
|
|
11108
|
+
* playlist. See `architecture/media.md`.
|
|
11109
|
+
*
|
|
11110
|
+
* `type` is required for the same reason it is on `ImageEncodeOptions`: a
|
|
11111
|
+
* second kind of stream would then be additive.
|
|
11112
|
+
*/
|
|
11113
|
+
|
|
11114
|
+
/** `false` (or absent) uploads the file as it was picked. */
|
|
11115
|
+
|
|
11116
|
+
/**
|
|
11117
|
+
* What a SET-BACKED field (`s.video(videosVal)`) may say for itself.
|
|
11118
|
+
*
|
|
11119
|
+
* Not `VideoOptions`: `dir` and `accept` belong to the set. `stream` is the
|
|
11120
|
+
* exception, as `encode` is for an image: it is about what happens to an
|
|
11121
|
+
* upload on its way in, so a field that wants the file as it was picked,
|
|
11122
|
+
* where its set streams, has to be able to say `stream: false`.
|
|
11123
|
+
*/
|
|
11124
|
+
|
|
11125
|
+
/**
|
|
11126
|
+
* The set a field picks from: its entries as they were when the module was
|
|
11127
|
+
* evaluated (the published set — see `GalleryImageSource` for why that is
|
|
11128
|
+
* enough), and whether it stores its videos on Val Remote.
|
|
11129
|
+
*/
|
|
11130
|
+
|
|
11131
|
+
var DEFAULT_VIDEO_ACCEPT = "video/*";
|
|
11132
|
+
var DEFAULT_VIDEO_RENDITIONS = [1080, 720, 480];
|
|
11133
|
+
var DEFAULT_VIDEO_SEGMENT_DURATION = 6;
|
|
11134
|
+
var VideoSchema = /*#__PURE__*/function (_Schema) {
|
|
11135
|
+
function VideoSchema(options) {
|
|
11136
|
+
var _this;
|
|
11137
|
+
var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
11138
|
+
var isRemote = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
11139
|
+
var customValidateFunctions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
|
|
11140
|
+
var isReadonly = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
11141
|
+
var isHidden = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
|
|
11142
|
+
var description = arguments.length > 6 ? arguments[6] : undefined;
|
|
11143
|
+
var renderInput = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null;
|
|
11144
|
+
var previewInput = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : null;
|
|
11145
|
+
var gallery = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : null;
|
|
11146
|
+
_classCallCheck(this, VideoSchema);
|
|
11147
|
+
_this = _callSuper(this, VideoSchema);
|
|
11148
|
+
_this.options = options;
|
|
11149
|
+
_this.opt = opt;
|
|
11150
|
+
_this.isRemote = isRemote;
|
|
11151
|
+
_this.customValidateFunctions = customValidateFunctions;
|
|
11152
|
+
_this.isReadonly = isReadonly;
|
|
11153
|
+
_this.isHidden = isHidden;
|
|
11154
|
+
_this.description = description;
|
|
11155
|
+
_this.renderInput = renderInput;
|
|
11156
|
+
_this.previewInput = previewInput;
|
|
11157
|
+
_this.gallery = gallery;
|
|
11158
|
+
return _this;
|
|
11159
|
+
}
|
|
11160
|
+
|
|
11161
|
+
/**
|
|
11162
|
+
* Describe this field.
|
|
11163
|
+
*
|
|
11164
|
+
* The description is INPUT HELP: it is shown where this field's value is
|
|
11165
|
+
* entered — beside its input in the Val editor, and for a record's key
|
|
11166
|
+
* schema in every form that asks for a key — so it is where you say what an
|
|
11167
|
+
* editor needs to know to fill it in RIGHT, which the field name cannot
|
|
11168
|
+
* carry. It is not a name for the value: that is `.preview(...)`, and it is
|
|
11169
|
+
* read somewhere else. The description also travels in the serialized
|
|
11170
|
+
* schema, which is what the AI assistant and the MCP tools read.
|
|
11171
|
+
*
|
|
11172
|
+
* Pass `null` to clear a description set earlier.
|
|
11173
|
+
*
|
|
11174
|
+
* @example
|
|
11175
|
+
* const schema = s.video().describe("Plays muted behind the headline");
|
|
11176
|
+
* export default c.define("/example.val.ts", schema, {
|
|
11177
|
+
* path: "/public/val/example.mp4",
|
|
11178
|
+
* mimeType: "video/mp4",
|
|
11179
|
+
* });
|
|
11180
|
+
*/
|
|
11181
|
+
_inherits(VideoSchema, _Schema);
|
|
11182
|
+
return _createClass(VideoSchema, [{
|
|
11183
|
+
key: "describe",
|
|
11184
|
+
value: function describe(description) {
|
|
11185
|
+
return new VideoSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput, this.gallery);
|
|
11186
|
+
}
|
|
11187
|
+
|
|
11188
|
+
/**
|
|
11189
|
+
* Store the video on Val's remote content host instead of in your
|
|
11190
|
+
* repository.
|
|
11191
|
+
*
|
|
11192
|
+
* The bytes still go into the patch store when the video is uploaded — the
|
|
11193
|
+
* push to the remote host happens at publish. What changes is where the
|
|
11194
|
+
* published video lives: `path` (and the poster's, and each caption track's)
|
|
11195
|
+
* becomes a remote URL rather than a path under `/public`, so the repository
|
|
11196
|
+
* does not grow with every upload. Upload remote videos in the Studio.
|
|
11197
|
+
*
|
|
11198
|
+
* @example
|
|
11199
|
+
* const schema = s.video().remote();
|
|
11200
|
+
* export default c.define("/example.val.ts", schema, {
|
|
11201
|
+
* path: "https://remote.val.build/file/p/my-project/b/01/v/1.0.0/h/8f2a1c/f/3b9d70/p/public/val/example.mp4",
|
|
11202
|
+
* mimeType: "video/mp4",
|
|
11203
|
+
* });
|
|
11204
|
+
*/
|
|
11205
|
+
}, {
|
|
11206
|
+
key: "remote",
|
|
11207
|
+
value: function remote() {
|
|
11208
|
+
return new VideoSchema(this.options, this.opt, true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput, this.gallery);
|
|
11209
|
+
}
|
|
11210
|
+
|
|
11211
|
+
/**
|
|
11212
|
+
* Add a custom validation rule to this field.
|
|
11213
|
+
*
|
|
11214
|
+
* The function is called with the field's value and returns `false` when the
|
|
11215
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
11216
|
+
* more than once to add more rules — they all run, and every message is
|
|
11217
|
+
* reported.
|
|
11218
|
+
*
|
|
11219
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
11220
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
11221
|
+
*
|
|
11222
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
11223
|
+
* before a publish.
|
|
11224
|
+
*
|
|
11225
|
+
* The second argument carries the `path` of the field being validated, for
|
|
11226
|
+
* when the message needs to say where the problem is.
|
|
11227
|
+
*
|
|
11228
|
+
* @example
|
|
11229
|
+
* const schema = s.video().validate((val) =>
|
|
11230
|
+
* (val.duration ?? 0) <= 30 ? false : "Keep it under 30 seconds",
|
|
11231
|
+
* );
|
|
11232
|
+
* export default c.define("/example.val.ts", schema, {
|
|
11233
|
+
* path: "/public/val/example.mp4",
|
|
11234
|
+
* mimeType: "video/mp4",
|
|
11235
|
+
* duration: 12,
|
|
11236
|
+
* });
|
|
11237
|
+
*/
|
|
11238
|
+
}, {
|
|
11239
|
+
key: "validate",
|
|
11240
|
+
value: function validate(validationFunction) {
|
|
11241
|
+
return new VideoSchema(this.options, this.opt, this.isRemote, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]), this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput, this.gallery);
|
|
11242
|
+
}
|
|
11243
|
+
}, {
|
|
11244
|
+
key: "executeValidate",
|
|
11245
|
+
value: function executeValidate(path, src) {
|
|
11246
|
+
var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
|
|
11247
|
+
path: path
|
|
11248
|
+
});
|
|
11249
|
+
var report = function report(errors) {
|
|
11250
|
+
var all = [].concat(_toConsumableArray(customValidationErrors), _toConsumableArray(errors));
|
|
11251
|
+
return all.length > 0 ? _defineProperty({}, path, all) : false;
|
|
11252
|
+
};
|
|
11253
|
+
if (src === null || src === undefined) {
|
|
11254
|
+
if (this.opt) {
|
|
11255
|
+
return report([]);
|
|
11256
|
+
}
|
|
11257
|
+
return report([{
|
|
11258
|
+
message: "Non-optional video was null or undefined.",
|
|
11259
|
+
value: src
|
|
11260
|
+
}]);
|
|
11261
|
+
}
|
|
11262
|
+
if (_typeof(src) !== "object" || typeof src.path !== "string") {
|
|
11263
|
+
return report([{
|
|
11264
|
+
message: "A video must be an object with a 'path' string.",
|
|
11265
|
+
value: src
|
|
11266
|
+
}]);
|
|
11267
|
+
}
|
|
11268
|
+
if (this.gallery) {
|
|
11269
|
+
return report(this.validateFromGallery(src, this.gallery));
|
|
11270
|
+
}
|
|
11271
|
+
return report(this.validateOwn(src));
|
|
11272
|
+
}
|
|
11273
|
+
|
|
11274
|
+
/**
|
|
11275
|
+
* A set-backed field: the file and what was read from it are the set's,
|
|
11276
|
+
* so the field is checked for what is its own, and for pointing at an
|
|
11277
|
+
* entry the set has.
|
|
11278
|
+
*/
|
|
11279
|
+
}, {
|
|
11280
|
+
key: "validateFromGallery",
|
|
11281
|
+
value: function validateFromGallery(src, gallery) {
|
|
11282
|
+
var own = ownMetadataOf(src);
|
|
11283
|
+
var repeated = ["mimeType", "width", "height", "duration"].filter(function (key) {
|
|
11284
|
+
return own[key] !== undefined;
|
|
11285
|
+
});
|
|
11286
|
+
if (repeated.length > 0) {
|
|
11287
|
+
return [{
|
|
11288
|
+
message: "A video from a set must not carry its own ".concat(repeated.join(", "), ": ").concat(repeated.length === 1 ? "it is" : "they are", " stored in the set."),
|
|
11289
|
+
value: src
|
|
11290
|
+
}];
|
|
11291
|
+
}
|
|
11292
|
+
var entry = gallery.entries === null ? null : gallery.entries[src.path];
|
|
11293
|
+
if (entry === undefined) {
|
|
11294
|
+
return [{
|
|
11295
|
+
message: "The set does not have a video at '".concat(src.path, "'."),
|
|
11296
|
+
value: src
|
|
11297
|
+
}];
|
|
11298
|
+
}
|
|
11299
|
+
// The poster and the captions are the field's own files, and live where
|
|
11300
|
+
// the set keeps its videos. The video itself is the set's to move.
|
|
11301
|
+
var misplaced = filesOfVideoSource(src).slice(1).filter(function (file) {
|
|
11302
|
+
return isRemoteMediaPath(file) !== gallery.remote;
|
|
11303
|
+
});
|
|
11304
|
+
if (misplaced.length > 0) {
|
|
11305
|
+
return [misplacedError(src, misplaced, gallery.remote)];
|
|
11306
|
+
}
|
|
11307
|
+
var duration = entry !== null && typeof entry.duration === "number" && entry.duration > 0 ? entry.duration : undefined;
|
|
11308
|
+
return [].concat(_toConsumableArray(validateTimes(src, duration)), _toConsumableArray(validateMixedTimes(src, entry)), _toConsumableArray(validateHotspot(src)), _toConsumableArray(validatePoster(src)), _toConsumableArray(validateCaptions(src)));
|
|
11309
|
+
}
|
|
11310
|
+
|
|
11311
|
+
/** A video of its own: it carries the file, and what was read from it. */
|
|
11312
|
+
}, {
|
|
11313
|
+
key: "validateOwn",
|
|
11314
|
+
value: function validateOwn(src) {
|
|
11315
|
+
var _this2 = this;
|
|
11316
|
+
var own = ownMetadataOf(src);
|
|
11317
|
+
// Every file the video names has to be where the schema says, and one fix
|
|
11318
|
+
// moves them all — a video on the content host with its poster still in
|
|
11319
|
+
// the repository is half a migration, not a choice. The error is reported
|
|
11320
|
+
// once for the whole video, never per file.
|
|
11321
|
+
var misplaced = filesOfVideoSource(src).filter(function (file) {
|
|
11322
|
+
return isRemoteMediaPath(file) !== _this2.isRemote;
|
|
11323
|
+
});
|
|
11324
|
+
if (misplaced.length > 0) {
|
|
11325
|
+
return [misplacedError(src, misplaced, this.isRemote)];
|
|
11326
|
+
}
|
|
11327
|
+
var errors = [];
|
|
11328
|
+
var isHls = isHlsVideo({
|
|
11329
|
+
path: src.path,
|
|
11330
|
+
mimeType: stringOrUndefined(own.mimeType)
|
|
11331
|
+
});
|
|
11332
|
+
var extensionMimeType = filenameToMimeType(stripQuery(src.path));
|
|
11333
|
+
if (isHls) {
|
|
11334
|
+
if (!stripQuery(src.path).toLowerCase().endsWith(".m3u8")) {
|
|
11335
|
+
errors.push({
|
|
11336
|
+
message: "An HLS video's path must be its master playlist (.m3u8). Got: ".concat(src.path),
|
|
11337
|
+
value: src
|
|
11338
|
+
});
|
|
11339
|
+
}
|
|
11340
|
+
} else if (!extensionMimeType || !extensionMimeType.startsWith("video/")) {
|
|
11341
|
+
errors.push({
|
|
11342
|
+
message: "Could not tell this is a video from its file extension. Got: ".concat(src.path),
|
|
11343
|
+
value: src
|
|
11344
|
+
});
|
|
11345
|
+
} else if (own.mimeType !== undefined && extensionMimeType !== own.mimeType) {
|
|
11346
|
+
errors.push({
|
|
11347
|
+
message: "Mime type and file extension not matching. Mime type is '".concat(String(own.mimeType), "' but file extension is '").concat(extensionMimeType, "'"),
|
|
11348
|
+
value: src
|
|
11349
|
+
});
|
|
11350
|
+
}
|
|
11351
|
+
if (own.mimeType !== undefined && typeof own.mimeType !== "string") {
|
|
11352
|
+
errors.push({
|
|
11353
|
+
message: "'mimeType' must be a string.",
|
|
11354
|
+
value: src
|
|
11355
|
+
});
|
|
11356
|
+
} else if (own.mimeType !== undefined && !isHls) {
|
|
11357
|
+
var _this$options$accept, _this$options;
|
|
11358
|
+
var accept = (_this$options$accept = (_this$options = this.options) === null || _this$options === void 0 ? void 0 : _this$options.accept) !== null && _this$options$accept !== void 0 ? _this$options$accept : DEFAULT_VIDEO_ACCEPT;
|
|
11359
|
+
if (!mimeTypeMatchesAccept(own.mimeType, accept)) {
|
|
11360
|
+
errors.push({
|
|
11361
|
+
message: "Mime type mismatch. Found '".concat(own.mimeType, "' but schema accepts '").concat(accept, "'"),
|
|
11362
|
+
value: src
|
|
11363
|
+
});
|
|
11364
|
+
}
|
|
11365
|
+
}
|
|
11366
|
+
var _iterator = result._createForOfIteratorHelper(["width", "height", "duration"]),
|
|
11367
|
+
_step;
|
|
11368
|
+
try {
|
|
11369
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
11370
|
+
var key = _step.value;
|
|
11371
|
+
var value = own[key];
|
|
11372
|
+
if (value !== undefined && (typeof value !== "number" || !Number.isFinite(value) || value <= 0)) {
|
|
11373
|
+
errors.push({
|
|
11374
|
+
message: "'".concat(key, "' must be a positive number. Got: ").concat(JSON.stringify(value)),
|
|
11375
|
+
value: src
|
|
11376
|
+
});
|
|
11377
|
+
}
|
|
11378
|
+
}
|
|
11379
|
+
} catch (err) {
|
|
11380
|
+
_iterator.e(err);
|
|
11381
|
+
} finally {
|
|
11382
|
+
_iterator.f();
|
|
11383
|
+
}
|
|
11384
|
+
var duration = typeof own.duration === "number" && own.duration > 0 ? own.duration : undefined;
|
|
11385
|
+
errors.push.apply(errors, _toConsumableArray(validateTimes(src, duration)));
|
|
11386
|
+
errors.push.apply(errors, _toConsumableArray(validateHotspot(src)));
|
|
11387
|
+
errors.push.apply(errors, _toConsumableArray(validatePoster(src)));
|
|
11388
|
+
errors.push.apply(errors, _toConsumableArray(validateCaptions(src)));
|
|
11389
|
+
if (errors.length > 0) {
|
|
11390
|
+
return errors;
|
|
11391
|
+
}
|
|
11392
|
+
|
|
11393
|
+
// Everything authored is fine. What is left is what is read from the
|
|
11394
|
+
// bytes, which this package cannot do — so it is handed on as a fix. The
|
|
11395
|
+
// CLI reads a local file's headers from disk and a remote one's over
|
|
11396
|
+
// HTTP, with Range requests, so neither is downloaded whole.
|
|
11397
|
+
var missing = ["mimeType", "width", "height", "duration"].filter(function (key) {
|
|
11398
|
+
return own[key] === undefined;
|
|
11399
|
+
});
|
|
11400
|
+
if (missing.length > 0) {
|
|
11401
|
+
return [{
|
|
11402
|
+
message: "Video metadata is missing: ".concat(missing.join(", "), "."),
|
|
11403
|
+
value: src,
|
|
11404
|
+
fixes: ["video:add-metadata"]
|
|
11405
|
+
}];
|
|
11406
|
+
}
|
|
11407
|
+
return [];
|
|
10395
11408
|
}
|
|
10396
11409
|
}, {
|
|
10397
11410
|
key: "executeAssert",
|
|
@@ -10424,7 +11437,7 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
|
|
|
10424
11437
|
return {
|
|
10425
11438
|
success: false,
|
|
10426
11439
|
errors: _defineProperty({}, path, [{
|
|
10427
|
-
message: "A
|
|
11440
|
+
message: "A video must be an object with a 'path' (error type: missing_path)",
|
|
10428
11441
|
typeError: true
|
|
10429
11442
|
}])
|
|
10430
11443
|
};
|
|
@@ -10437,19 +11450,19 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
|
|
|
10437
11450
|
}, {
|
|
10438
11451
|
key: "nullable",
|
|
10439
11452
|
value: function nullable() {
|
|
10440
|
-
return new
|
|
11453
|
+
return new VideoSchema(this.options, true, this.isRemote, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput, this.gallery);
|
|
10441
11454
|
}
|
|
10442
11455
|
}, {
|
|
10443
11456
|
key: "readonly",
|
|
10444
11457
|
value: function readonly() {
|
|
10445
11458
|
var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
10446
|
-
return new
|
|
11459
|
+
return new VideoSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput, this.gallery);
|
|
10447
11460
|
}
|
|
10448
11461
|
}, {
|
|
10449
11462
|
key: "hidden",
|
|
10450
11463
|
value: function hidden() {
|
|
10451
11464
|
var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
10452
|
-
return new
|
|
11465
|
+
return new VideoSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput, this.gallery);
|
|
10453
11466
|
}
|
|
10454
11467
|
}, {
|
|
10455
11468
|
key: "executeCustomValidateAt",
|
|
@@ -10459,6 +11472,25 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
|
|
|
10459
11472
|
});
|
|
10460
11473
|
}
|
|
10461
11474
|
|
|
11475
|
+
/**
|
|
11476
|
+
* How this field is laid out in the editor when it is the item of an array
|
|
11477
|
+
* or record: `{ as: "inline" }` renders the field itself inside each row,
|
|
11478
|
+
* instead of a preview row that navigates to it.
|
|
11479
|
+
*
|
|
11480
|
+
* Static configuration, not a callback — see `render.ts`.
|
|
11481
|
+
*
|
|
11482
|
+
* @example
|
|
11483
|
+
* const schema = s.array(s.video().render({ as: "inline" }));
|
|
11484
|
+
* export default c.define("/example.val.ts", schema, [
|
|
11485
|
+
* { path: "/public/val/example.mp4", mimeType: "video/mp4" },
|
|
11486
|
+
* ]);
|
|
11487
|
+
*/
|
|
11488
|
+
}, {
|
|
11489
|
+
key: "render",
|
|
11490
|
+
value: function render(input) {
|
|
11491
|
+
return new VideoSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, input, this.previewInput, this.gallery);
|
|
11492
|
+
}
|
|
11493
|
+
|
|
10462
11494
|
/**
|
|
10463
11495
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
10464
11496
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
@@ -10466,16 +11498,19 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
|
|
|
10466
11498
|
*
|
|
10467
11499
|
* @example
|
|
10468
11500
|
* const schema = s.array(
|
|
10469
|
-
* s.
|
|
11501
|
+
* s.video().preview(({ val }) => ({
|
|
11502
|
+
* title: val.alt ?? val.path,
|
|
11503
|
+
* image: val.poster,
|
|
11504
|
+
* })),
|
|
10470
11505
|
* );
|
|
10471
11506
|
* export default c.define("/example.val.ts", schema, [
|
|
10472
|
-
* { path: "/public/val/example.
|
|
11507
|
+
* { path: "/public/val/example.mp4", mimeType: "video/mp4" },
|
|
10473
11508
|
* ]);
|
|
10474
11509
|
*/
|
|
10475
11510
|
}, {
|
|
10476
11511
|
key: "preview",
|
|
10477
11512
|
value: function preview(select) {
|
|
10478
|
-
return new
|
|
11513
|
+
return new VideoSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, select, this.gallery);
|
|
10479
11514
|
}
|
|
10480
11515
|
}, {
|
|
10481
11516
|
key: "executePreviewItem",
|
|
@@ -10495,16 +11530,16 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
|
|
|
10495
11530
|
}, {
|
|
10496
11531
|
key: "executeSerialize",
|
|
10497
11532
|
value: function executeSerialize() {
|
|
10498
|
-
var _this$customValidateF;
|
|
10499
|
-
var modulePaths = this.moduleMetadata ? Object.keys(this.moduleMetadata) : [];
|
|
11533
|
+
var _this$renderInput, _this$customValidateF, _this$gallery;
|
|
10500
11534
|
return {
|
|
10501
|
-
type: "
|
|
11535
|
+
type: "video",
|
|
11536
|
+
render: (_this$renderInput = this.renderInput) !== null && _this$renderInput !== void 0 ? _this$renderInput : undefined,
|
|
10502
11537
|
preview: this.previewInput ? true : undefined,
|
|
10503
11538
|
options: this.options,
|
|
10504
11539
|
opt: this.opt,
|
|
10505
11540
|
remote: this.isRemote,
|
|
10506
11541
|
customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
|
|
10507
|
-
referencedModule:
|
|
11542
|
+
referencedModule: (_this$gallery = this.gallery) === null || _this$gallery === void 0 ? void 0 : _this$gallery.modulePath,
|
|
10508
11543
|
readonly: this.isReadonly,
|
|
10509
11544
|
hidden: this.isHidden,
|
|
10510
11545
|
description: this.description
|
|
@@ -10514,27 +11549,137 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
|
|
|
10514
11549
|
}(Schema);
|
|
10515
11550
|
|
|
10516
11551
|
/**
|
|
10517
|
-
*
|
|
10518
|
-
*
|
|
11552
|
+
* Every file a video value names: the video, its poster and each caption
|
|
11553
|
+
* track. An HLS stream's segments are not here — they are named by its
|
|
11554
|
+
* playlists, not by the value.
|
|
10519
11555
|
*/
|
|
10520
|
-
|
|
10521
|
-
|
|
10522
|
-
|
|
10523
|
-
|
|
10524
|
-
|
|
10525
|
-
if (
|
|
10526
|
-
var
|
|
10527
|
-
|
|
10528
|
-
|
|
10529
|
-
|
|
10530
|
-
|
|
10531
|
-
|
|
11556
|
+
function filesOfVideoSource(src) {
|
|
11557
|
+
var files = [src.path];
|
|
11558
|
+
if (src.poster && _typeof(src.poster) === "object" && typeof src.poster.path === "string") {
|
|
11559
|
+
files.push(src.poster.path);
|
|
11560
|
+
}
|
|
11561
|
+
if (Array.isArray(src.captions)) {
|
|
11562
|
+
var _iterator2 = result._createForOfIteratorHelper(src.captions),
|
|
11563
|
+
_step2;
|
|
11564
|
+
try {
|
|
11565
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
11566
|
+
var track = _step2.value;
|
|
11567
|
+
if (track && _typeof(track) === "object" && typeof track.path === "string") {
|
|
11568
|
+
files.push(track.path);
|
|
11569
|
+
}
|
|
10532
11570
|
}
|
|
10533
|
-
|
|
11571
|
+
} catch (err) {
|
|
11572
|
+
_iterator2.e(err);
|
|
11573
|
+
} finally {
|
|
11574
|
+
_iterator2.f();
|
|
10534
11575
|
}
|
|
10535
|
-
return new FileSchema({}, false, false, [], allModules);
|
|
10536
11576
|
}
|
|
10537
|
-
return
|
|
11577
|
+
return files;
|
|
11578
|
+
}
|
|
11579
|
+
|
|
11580
|
+
/**
|
|
11581
|
+
* What the value says about its file, typed as what it IS rather than what
|
|
11582
|
+
* it should be: a set-backed field's type has none of these, and is checked
|
|
11583
|
+
* for carrying them anyway, because hand-written JSON never saw the type.
|
|
11584
|
+
*/
|
|
11585
|
+
function ownMetadataOf(src) {
|
|
11586
|
+
var value = _objectSpread2({}, src);
|
|
11587
|
+
return {
|
|
11588
|
+
mimeType: value.mimeType,
|
|
11589
|
+
width: value.width,
|
|
11590
|
+
height: value.height,
|
|
11591
|
+
duration: value.duration
|
|
11592
|
+
};
|
|
11593
|
+
}
|
|
11594
|
+
|
|
11595
|
+
/**
|
|
11596
|
+
* A start the field set against an end the set holds, or the reverse: each is
|
|
11597
|
+
* fine alone, and the field's own times and the set's are each checked where
|
|
11598
|
+
* they are written, so what is left is the pair the page will actually play.
|
|
11599
|
+
*/
|
|
11600
|
+
function validateMixedTimes(src, entry) {
|
|
11601
|
+
var _src$startTime, _src$endTime;
|
|
11602
|
+
if (entry === null || src.startTime === undefined === (src.endTime === undefined)) {
|
|
11603
|
+
return [];
|
|
11604
|
+
}
|
|
11605
|
+
var start = (_src$startTime = src.startTime) !== null && _src$startTime !== void 0 ? _src$startTime : entry.startTime;
|
|
11606
|
+
var end = (_src$endTime = src.endTime) !== null && _src$endTime !== void 0 ? _src$endTime : entry.endTime;
|
|
11607
|
+
if (typeof start !== "number" || typeof end !== "number" || start < end) {
|
|
11608
|
+
return [];
|
|
11609
|
+
}
|
|
11610
|
+
var whose = src.startTime === undefined ? "the start is the set's" : "the end is the set's";
|
|
11611
|
+
return [{
|
|
11612
|
+
message: "'startTime' (".concat(start, "s) must be before 'endTime' (").concat(end, "s) \u2014 ").concat(whose, "."),
|
|
11613
|
+
value: src
|
|
11614
|
+
}];
|
|
11615
|
+
}
|
|
11616
|
+
function stringOrUndefined(value) {
|
|
11617
|
+
return typeof value === "string" ? value : undefined;
|
|
11618
|
+
}
|
|
11619
|
+
function misplacedError(src, misplaced, shouldBeRemote) {
|
|
11620
|
+
var these = misplaced.length === 1 ? "this file is" : "".concat(misplaced.length, " files are");
|
|
11621
|
+
return shouldBeRemote ? {
|
|
11622
|
+
message: "Expected a remote video, but ".concat(these, " stored locally: ").concat(misplaced.join(", ")),
|
|
11623
|
+
value: src,
|
|
11624
|
+
fixes: ["video:upload-remote"]
|
|
11625
|
+
} : {
|
|
11626
|
+
message: "Expected a local video (files under /public), but ".concat(these, " remote: ").concat(misplaced.join(", ")),
|
|
11627
|
+
value: src,
|
|
11628
|
+
fixes: ["video:download-remote"]
|
|
11629
|
+
};
|
|
11630
|
+
}
|
|
11631
|
+
function stripQuery(path) {
|
|
11632
|
+
return path.split("?")[0];
|
|
11633
|
+
}
|
|
11634
|
+
|
|
11635
|
+
/**
|
|
11636
|
+
* A video picked from a set (`s.videoset()`). What is true of the file —
|
|
11637
|
+
* its type, size and length — lives in the set; the field carries what one
|
|
11638
|
+
* page chose about it.
|
|
11639
|
+
*/
|
|
11640
|
+
|
|
11641
|
+
/**
|
|
11642
|
+
* Define a video: an `.mp4` / `.webm` file, or an HLS stream the Studio makes
|
|
11643
|
+
* from an upload when `stream` is set.
|
|
11644
|
+
*/
|
|
11645
|
+
|
|
11646
|
+
function video(options, galleryOptions) {
|
|
11647
|
+
return videoOf(options, galleryOptions);
|
|
11648
|
+
}
|
|
11649
|
+
|
|
11650
|
+
/**
|
|
11651
|
+
* `s.video()` for a project whose media is all remote (`files.remote` in
|
|
11652
|
+
* `val.config.ts`): the same schema, with `.remote()` already applied. See
|
|
11653
|
+
* `initSchema`.
|
|
11654
|
+
*/
|
|
11655
|
+
|
|
11656
|
+
function remoteVideo(options, galleryOptions) {
|
|
11657
|
+
return videoOf(options, galleryOptions).remote();
|
|
11658
|
+
}
|
|
11659
|
+
function videoOf(options, galleryOptions) {
|
|
11660
|
+
var _options$GetSchema, _setSchema$remote, _setSchema$remote2;
|
|
11661
|
+
if (options === undefined || !isVideosetModule(options)) {
|
|
11662
|
+
return new VideoSchema(options);
|
|
11663
|
+
}
|
|
11664
|
+
var modulePath = getValPath(options);
|
|
11665
|
+
if (modulePath === undefined) {
|
|
11666
|
+
throw new Error("Invalid argument passed to s.video(). Expected a ValModule constructed through c.define, but got an object without a valid module path.");
|
|
11667
|
+
}
|
|
11668
|
+
var setSchema = (_options$GetSchema = options[GetSchema]) === null || _options$GetSchema === void 0 ? void 0 : _options$GetSchema["executeSerialize"]();
|
|
11669
|
+
if ((setSchema === null || setSchema === void 0 ? void 0 : setSchema.type) !== "record" || setSchema.mediaType !== "videos") {
|
|
11670
|
+
var _setSchema$mediaType, _setSchema$type;
|
|
11671
|
+
throw new Error("s.video(".concat(modulePath, "): the module must be an s.videoset(). Got ").concat((setSchema === null || setSchema === void 0 ? void 0 : setSchema.type) === "record" ? "a record of ".concat((_setSchema$mediaType = setSchema.mediaType) !== null && _setSchema$mediaType !== void 0 ? _setSchema$mediaType : "values") : (_setSchema$type = setSchema === null || setSchema === void 0 ? void 0 : setSchema.type) !== null && _setSchema$type !== void 0 ? _setSchema$type : "no schema", "."));
|
|
11672
|
+
}
|
|
11673
|
+
return new VideoSchema((galleryOptions === null || galleryOptions === void 0 ? void 0 : galleryOptions.stream) !== undefined ? {
|
|
11674
|
+
stream: galleryOptions.stream
|
|
11675
|
+
} : undefined, false, (_setSchema$remote = setSchema.remote) !== null && _setSchema$remote !== void 0 ? _setSchema$remote : false, [], false, false, undefined, null, null, {
|
|
11676
|
+
modulePath: modulePath,
|
|
11677
|
+
entries: getSource(options),
|
|
11678
|
+
remote: (_setSchema$remote2 = setSchema.remote) !== null && _setSchema$remote2 !== void 0 ? _setSchema$remote2 : false
|
|
11679
|
+
});
|
|
11680
|
+
}
|
|
11681
|
+
function isVideosetModule(value) {
|
|
11682
|
+
return GetSchema in value;
|
|
10538
11683
|
}
|
|
10539
11684
|
|
|
10540
11685
|
/**
|
|
@@ -11516,6 +12661,99 @@ var imageset = function imageset(options) {
|
|
|
11516
12661
|
});
|
|
11517
12662
|
};
|
|
11518
12663
|
|
|
12664
|
+
/**
|
|
12665
|
+
* Options for s.videoset()
|
|
12666
|
+
*/
|
|
12667
|
+
|
|
12668
|
+
/** See `ImagesetAltOption`: `alt` is optional only when it is the default. */
|
|
12669
|
+
|
|
12670
|
+
/**
|
|
12671
|
+
* One video of a set, keyed by its file path (an HLS stream by its master
|
|
12672
|
+
* playlist).
|
|
12673
|
+
*
|
|
12674
|
+
* Two kinds of thing are here. What is TRUE OF THE FILE — what it is, how
|
|
12675
|
+
* big, how long — is read from the bytes and is the set's alone. The rest —
|
|
12676
|
+
* the description, focal point, poster, start and end, and captions — is what
|
|
12677
|
+
* a page chooses about a video, and an entry holds it as the DEFAULT: every
|
|
12678
|
+
* field picked from the set (`s.video(videosVal)`) starts from it and may
|
|
12679
|
+
* override it key by key, so a video described and trimmed once is described
|
|
12680
|
+
* and trimmed everywhere it is used. `fillFromGallery` is the one merge.
|
|
12681
|
+
*
|
|
12682
|
+
* The poster is also the set's thumbnail of the entry: there is no separate
|
|
12683
|
+
* still for the gallery, because two stills of one video would disagree.
|
|
12684
|
+
*/
|
|
12685
|
+
|
|
12686
|
+
/**
|
|
12687
|
+
* Define a collection of videos — the video twin of `s.imageset()`.
|
|
12688
|
+
*
|
|
12689
|
+
* A field picks from it with `s.video(videosVal)`. An entry may hold the
|
|
12690
|
+
* description, poster, start and end, focal point and captions as defaults,
|
|
12691
|
+
* and a field overrides any of them by setting its own. Uploading in such a
|
|
12692
|
+
* field adds to the set. Call `.remote()` on the result
|
|
12693
|
+
* to store the set on Val Remote.
|
|
12694
|
+
*
|
|
12695
|
+
* @example
|
|
12696
|
+
* ```typescript
|
|
12697
|
+
* const schema = s.videoset({
|
|
12698
|
+
* dir: "/public/val/videos",
|
|
12699
|
+
* stream: { type: "hls" },
|
|
12700
|
+
* });
|
|
12701
|
+
* export default c.define("/content/videos.val.ts", schema, {
|
|
12702
|
+
* "/public/val/videos/intro_51df2.mp4": {
|
|
12703
|
+
* mimeType: "video/mp4",
|
|
12704
|
+
* width: 1280,
|
|
12705
|
+
* height: 720,
|
|
12706
|
+
* duration: 12.5,
|
|
12707
|
+
* alt: "The team, introducing itself",
|
|
12708
|
+
* startTime: 1.5,
|
|
12709
|
+
* },
|
|
12710
|
+
* });
|
|
12711
|
+
* ```
|
|
12712
|
+
*/
|
|
12713
|
+
var videoset = function videoset(options) {
|
|
12714
|
+
var _options$alt, _options$accept;
|
|
12715
|
+
// The same assertion as in `imageset()`, and sound for the same reason:
|
|
12716
|
+
// `VideosetAltOption` makes `alt` required unless `Alt` is the default.
|
|
12717
|
+
var altSchema = (_options$alt = options.alt) !== null && _options$alt !== void 0 ? _options$alt : string().nullable();
|
|
12718
|
+
var itemSchema = new ObjectSchema({
|
|
12719
|
+
mimeType: new StringSchema({}, false),
|
|
12720
|
+
width: new NumberSchema(undefined, false),
|
|
12721
|
+
height: new NumberSchema(undefined, false),
|
|
12722
|
+
duration: new NumberSchema(undefined, false),
|
|
12723
|
+
alt: altSchema
|
|
12724
|
+
}, false);
|
|
12725
|
+
return new RecordSchema(itemSchema, false, [], null, null, {
|
|
12726
|
+
type: "videos",
|
|
12727
|
+
accept: (_options$accept = options.accept) !== null && _options$accept !== void 0 ? _options$accept : DEFAULT_VIDEO_ACCEPT,
|
|
12728
|
+
dir: options.dir,
|
|
12729
|
+
remote: false,
|
|
12730
|
+
altSchema: altSchema,
|
|
12731
|
+
stream: options.stream
|
|
12732
|
+
});
|
|
12733
|
+
};
|
|
12734
|
+
|
|
12735
|
+
/**
|
|
12736
|
+
* The video schema a set's entry is hashed against, for a remote ref.
|
|
12737
|
+
*
|
|
12738
|
+
* The set's item schema is an object, but a remote ref's validation hash is
|
|
12739
|
+
* computed over a MEDIA schema, so one is synthesized from the set — the one
|
|
12740
|
+
* definition the CLI's upload (`videos:upload-remote`) and the Studio's (the
|
|
12741
|
+
* set's gallery) both use, because two copies are two hashes for the same
|
|
12742
|
+
* file. `stream` is left out: it says what is done to an upload on its way
|
|
12743
|
+
* in, not whether the bytes that arrived are valid.
|
|
12744
|
+
*/
|
|
12745
|
+
function videosetEntryVideoSchema(set) {
|
|
12746
|
+
return {
|
|
12747
|
+
type: "video",
|
|
12748
|
+
opt: false,
|
|
12749
|
+
options: _objectSpread2(_objectSpread2({}, set.accept ? {
|
|
12750
|
+
accept: set.accept
|
|
12751
|
+
} : {}), set.dir ? {
|
|
12752
|
+
dir: set.dir
|
|
12753
|
+
} : {})
|
|
12754
|
+
};
|
|
12755
|
+
}
|
|
12756
|
+
|
|
11519
12757
|
// import type { F } from "ts-toolbelt";
|
|
11520
12758
|
// import { i18n, I18n } from "./schema/future/i18n";
|
|
11521
12759
|
// import { oneOf } from "./schema/future/oneOf";
|
|
@@ -11523,7 +12761,31 @@ var imageset = function imageset(options) {
|
|
|
11523
12761
|
// export type InitSchemaLocalized<Locales extends readonly string[]> = {
|
|
11524
12762
|
// readonly i18n: I18n<Locales>;
|
|
11525
12763
|
// };
|
|
11526
|
-
|
|
12764
|
+
|
|
12765
|
+
function initSchema(options) {
|
|
12766
|
+
var media = (options === null || options === void 0 ? void 0 : options.remote) === true ? {
|
|
12767
|
+
image: remoteImage,
|
|
12768
|
+
file: remoteFile,
|
|
12769
|
+
video: remoteVideo,
|
|
12770
|
+
richtext: remoteRichtext,
|
|
12771
|
+
imageset: function (options) {
|
|
12772
|
+
return imageset(options).remote();
|
|
12773
|
+
},
|
|
12774
|
+
fileset: function (options) {
|
|
12775
|
+
return fileset(options).remote();
|
|
12776
|
+
},
|
|
12777
|
+
videoset: function (options) {
|
|
12778
|
+
return videoset(options).remote();
|
|
12779
|
+
}
|
|
12780
|
+
} : {
|
|
12781
|
+
image: image,
|
|
12782
|
+
file: file,
|
|
12783
|
+
video: video,
|
|
12784
|
+
richtext: richtext,
|
|
12785
|
+
imageset: imageset,
|
|
12786
|
+
fileset: fileset,
|
|
12787
|
+
videoset: videoset
|
|
12788
|
+
};
|
|
11527
12789
|
// locales: F.Narrow<Locales>
|
|
11528
12790
|
return {
|
|
11529
12791
|
string: string,
|
|
@@ -11535,14 +12797,15 @@ function initSchema() {
|
|
|
11535
12797
|
"enum": enumSchema,
|
|
11536
12798
|
union: union,
|
|
11537
12799
|
// oneOf,
|
|
11538
|
-
richtext: richtext,
|
|
11539
|
-
image: image,
|
|
12800
|
+
richtext: media.richtext,
|
|
12801
|
+
image: media.image,
|
|
11540
12802
|
literal: literal,
|
|
11541
12803
|
keyOf: keyOf,
|
|
11542
12804
|
view: view,
|
|
11543
12805
|
record: record,
|
|
11544
|
-
file: file,
|
|
11545
|
-
|
|
12806
|
+
file: media.file,
|
|
12807
|
+
video: media.video,
|
|
12808
|
+
fileset: media.fileset,
|
|
11546
12809
|
date: date,
|
|
11547
12810
|
datetime: datetime,
|
|
11548
12811
|
color: color,
|
|
@@ -11550,7 +12813,8 @@ function initSchema() {
|
|
|
11550
12813
|
locale: locale,
|
|
11551
12814
|
route: route,
|
|
11552
12815
|
router: router,
|
|
11553
|
-
imageset: imageset,
|
|
12816
|
+
imageset: media.imageset,
|
|
12817
|
+
videoset: media.videoset,
|
|
11554
12818
|
settings: settings
|
|
11555
12819
|
// i18n: i18n(locales),
|
|
11556
12820
|
};
|
|
@@ -11568,8 +12832,11 @@ function initSchema() {
|
|
|
11568
12832
|
|
|
11569
12833
|
// TODO: Rename to createValSystem (only to be used by internal things), we can then export * from '@valbuild/core' in the next package then.
|
|
11570
12834
|
var initVal = function initVal(config) {
|
|
12835
|
+
var _config$files;
|
|
11571
12836
|
// const locales = options?.locales;
|
|
11572
|
-
var s = initSchema(
|
|
12837
|
+
var s = initSchema({
|
|
12838
|
+
remote: (config === null || config === void 0 || (_config$files = config.files) === null || _config$files === void 0 ? void 0 : _config$files.remote) === true
|
|
12839
|
+
});
|
|
11573
12840
|
// if (locales?.required) {
|
|
11574
12841
|
// console.error("Locales / i18n currently not implemented");
|
|
11575
12842
|
// return {
|
|
@@ -12359,6 +13626,43 @@ function computeSourcesSha(entries) {
|
|
|
12359
13626
|
}
|
|
12360
13627
|
return sourcesSha;
|
|
12361
13628
|
}
|
|
13629
|
+
|
|
13630
|
+
/**
|
|
13631
|
+
* The `schemaSha` fold on its own: path and serialized schema, in `val.modules`
|
|
13632
|
+
* order.
|
|
13633
|
+
*
|
|
13634
|
+
* Separate for the same reason as {@link computeSourcesSha}: the Studio folds
|
|
13635
|
+
* the schemas of the bundle it is running and compares the answer with the
|
|
13636
|
+
* `schemaSha` on `/stat`, which is how it learns that a new schema has been
|
|
13637
|
+
* deployed under it. One implementation, so that comparison is between two
|
|
13638
|
+
* runs of the same code.
|
|
13639
|
+
*/
|
|
13640
|
+
function computeSchemaSha(entries) {
|
|
13641
|
+
var schemaSha = "";
|
|
13642
|
+
var _iterator2 = result._createForOfIteratorHelper(entries),
|
|
13643
|
+
_step2;
|
|
13644
|
+
try {
|
|
13645
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
13646
|
+
var _step2$value = _step2.value,
|
|
13647
|
+
path = _step2$value.path,
|
|
13648
|
+
serializedSchema = _step2$value.serializedSchema;
|
|
13649
|
+
// The PATH is part of the schema set, not just the schema: renaming a
|
|
13650
|
+
// module while leaving its schema byte-identical still changes which paths
|
|
13651
|
+
// exist, and an open client keyed its schema cache by the old path. Hashing
|
|
13652
|
+
// the schema alone left this SHA unchanged, so with no commitSha to fall
|
|
13653
|
+
// back on the client never refetched /schema.
|
|
13654
|
+
schemaSha = hash(schemaSha + JSON.stringify({
|
|
13655
|
+
path: path,
|
|
13656
|
+
schema: serializedSchema
|
|
13657
|
+
}));
|
|
13658
|
+
}
|
|
13659
|
+
} catch (err) {
|
|
13660
|
+
_iterator2.e(err);
|
|
13661
|
+
} finally {
|
|
13662
|
+
_iterator2.f();
|
|
13663
|
+
}
|
|
13664
|
+
return schemaSha;
|
|
13665
|
+
}
|
|
12362
13666
|
function computeValModuleShas(config, entries, moduleErrors) {
|
|
12363
13667
|
var configSha = hash(JSON.stringify(config));
|
|
12364
13668
|
var sourcesSha = computeSourcesSha(entries);
|
|
@@ -12371,12 +13675,12 @@ function computeValModuleShas(config, entries, moduleErrors) {
|
|
|
12371
13675
|
// `gitCommit: process.env.VERCEL_GIT_COMMIT_SHA` / `gitBranch`, which are
|
|
12372
13676
|
// server-only env vars and therefore `undefined` in the browser. Seeding with
|
|
12373
13677
|
// them made the two sides disagree on every production load.
|
|
12374
|
-
var schemaSha =
|
|
12375
|
-
var
|
|
12376
|
-
|
|
13678
|
+
var schemaSha = computeSchemaSha(entries);
|
|
13679
|
+
var _iterator3 = result._createForOfIteratorHelper(entries),
|
|
13680
|
+
_step3;
|
|
12377
13681
|
try {
|
|
12378
|
-
for (
|
|
12379
|
-
var entry =
|
|
13682
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
13683
|
+
var entry = _step3.value;
|
|
12380
13684
|
var path = entry.path,
|
|
12381
13685
|
source = entry.source,
|
|
12382
13686
|
serializedSchema = entry.serializedSchema;
|
|
@@ -12386,20 +13690,11 @@ function computeValModuleShas(config, entries, moduleErrors) {
|
|
|
12386
13690
|
source: source,
|
|
12387
13691
|
modulesErrors: moduleErrors.slice(0, entry.moduleErrorsAt)
|
|
12388
13692
|
}));
|
|
12389
|
-
// The PATH is part of the schema set, not just the schema: renaming a
|
|
12390
|
-
// module while leaving its schema byte-identical still changes which paths
|
|
12391
|
-
// exist, and an open client keyed its schema cache by the old path. Hashing
|
|
12392
|
-
// the schema alone left this SHA unchanged, so with no commitSha to fall
|
|
12393
|
-
// back on the client never refetched /schema.
|
|
12394
|
-
schemaSha = hash(schemaSha + JSON.stringify({
|
|
12395
|
-
path: path,
|
|
12396
|
-
schema: serializedSchema
|
|
12397
|
-
}));
|
|
12398
13693
|
}
|
|
12399
13694
|
} catch (err) {
|
|
12400
|
-
|
|
13695
|
+
_iterator3.e(err);
|
|
12401
13696
|
} finally {
|
|
12402
|
-
|
|
13697
|
+
_iterator3.f();
|
|
12403
13698
|
}
|
|
12404
13699
|
return {
|
|
12405
13700
|
baseSha: baseSha,
|
|
@@ -12421,7 +13716,7 @@ function extractValModules(_x) {
|
|
|
12421
13716
|
}
|
|
12422
13717
|
function _extractValModules() {
|
|
12423
13718
|
_extractValModules = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(valModules) {
|
|
12424
|
-
var moduleErrors, addModuleError, sources, schemas, serializedSchemas, shaEntries, moduleIdx, module, at, value, path, schema, source, serializedSchema, pathM,
|
|
13719
|
+
var moduleErrors, addModuleError, sources, schemas, serializedSchemas, shaEntries, moduleIdx, module, at, value, path, schema, source, serializedSchema, pathM, _iterator4, _step4, error, _iterator5, _step5, _error, _t, _t2;
|
|
12425
13720
|
return _regenerator().w(function (_context) {
|
|
12426
13721
|
while (1) switch (_context.p = _context.n) {
|
|
12427
13722
|
case 0:
|
|
@@ -12568,10 +13863,10 @@ function _extractValModules() {
|
|
|
12568
13863
|
// Appended AFTER the loop on purpose: each entry's `moduleErrorsAt` is the
|
|
12569
13864
|
// error count at the time it was folded in, so the SHAs stay a function of
|
|
12570
13865
|
// the modules themselves.
|
|
12571
|
-
|
|
13866
|
+
_iterator4 = result._createForOfIteratorHelper(resolveSettingsModule(serializedSchemas).errors);
|
|
12572
13867
|
try {
|
|
12573
|
-
for (
|
|
12574
|
-
error =
|
|
13868
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
13869
|
+
error = _step4.value;
|
|
12575
13870
|
moduleErrors.push(error);
|
|
12576
13871
|
}
|
|
12577
13872
|
// Same kind of rule, same reason it is here: a view cycle is a property of the
|
|
@@ -12579,20 +13874,20 @@ function _extractValModules() {
|
|
|
12579
13874
|
// catches it either — a view stores a pointer, not content, so there is no
|
|
12580
13875
|
// data cycle for a source walk to trip over.
|
|
12581
13876
|
} catch (err) {
|
|
12582
|
-
|
|
13877
|
+
_iterator4.e(err);
|
|
12583
13878
|
} finally {
|
|
12584
|
-
|
|
13879
|
+
_iterator4.f();
|
|
12585
13880
|
}
|
|
12586
|
-
|
|
13881
|
+
_iterator5 = result._createForOfIteratorHelper(viewCycleErrors(serializedSchemas));
|
|
12587
13882
|
try {
|
|
12588
|
-
for (
|
|
12589
|
-
_error =
|
|
13883
|
+
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
13884
|
+
_error = _step5.value;
|
|
12590
13885
|
moduleErrors.push(_error);
|
|
12591
13886
|
}
|
|
12592
13887
|
} catch (err) {
|
|
12593
|
-
|
|
13888
|
+
_iterator5.e(err);
|
|
12594
13889
|
} finally {
|
|
12595
|
-
|
|
13890
|
+
_iterator5.f();
|
|
12596
13891
|
}
|
|
12597
13892
|
return _context.a(2, _objectSpread2(_objectSpread2({
|
|
12598
13893
|
sources: sources,
|
|
@@ -12642,7 +13937,7 @@ function _extractValModules() {
|
|
|
12642
13937
|
* instead would reintroduce exactly the silent skip described above.
|
|
12643
13938
|
*/
|
|
12644
13939
|
function hasRemoteFileSchema(schema) {
|
|
12645
|
-
if (schema.type === "file" || schema.type === "image") {
|
|
13940
|
+
if (schema.type === "file" || schema.type === "image" || schema.type === "video") {
|
|
12646
13941
|
return !!schema.remote;
|
|
12647
13942
|
} else if (schema.type === "richtext") {
|
|
12648
13943
|
var _schema$options;
|
|
@@ -12721,7 +14016,7 @@ function hasRemoteFileSchema(schema) {
|
|
|
12721
14016
|
* already has a data-loss incident attached to it (see above).
|
|
12722
14017
|
*/
|
|
12723
14018
|
function hasMediaSchema(schema) {
|
|
12724
|
-
if (schema.type === "file" || schema.type === "image") {
|
|
14019
|
+
if (schema.type === "file" || schema.type === "image" || schema.type === "video") {
|
|
12725
14020
|
return true;
|
|
12726
14021
|
} else if (schema.type === "richtext") {
|
|
12727
14022
|
var _schema$options2;
|
|
@@ -13087,6 +14382,10 @@ function getValidationBasis(coreVersion, schema, fileExt, metadata, fileHash) {
|
|
|
13087
14382
|
// bytes that arrived are valid. Leaving it in would mean that changing a
|
|
13088
14383
|
// quality setting re-validates every remote file in the project.
|
|
13089
14384
|
delete options.encode;
|
|
14385
|
+
// `stream` likewise: it is what the Studio made of an upload (an HLS
|
|
14386
|
+
// directory instead of one file), and every file it made is validated on its
|
|
14387
|
+
// own merits.
|
|
14388
|
+
delete options.stream;
|
|
13090
14389
|
var schemaValidationBasis = {
|
|
13091
14390
|
type: schema.type,
|
|
13092
14391
|
opt: schema.opt,
|
|
@@ -13106,6 +14405,93 @@ function getFileHash(text) {
|
|
|
13106
14405
|
return hashToRemoteFileHash(getSHA256Hash(new Uint8Array(text)));
|
|
13107
14406
|
}
|
|
13108
14407
|
|
|
14408
|
+
var cache$1 = new WeakMap();
|
|
14409
|
+
|
|
14410
|
+
/**
|
|
14411
|
+
* The PUBLISHED entries of every gallery a module's fields pick from — an
|
|
14412
|
+
* `s.image(galleryVal)`, `s.file(filesVal)` or `s.video(videosVal)` — by the
|
|
14413
|
+
* gallery's module path.
|
|
14414
|
+
*
|
|
14415
|
+
* A gallery-backed value names its file and nothing else that is the
|
|
14416
|
+
* gallery's, so a reader has to look the entry up (`fillFromGallery`). In
|
|
14417
|
+
* draft mode the reader has every module's draft source to look in; outside
|
|
14418
|
+
* it, nothing — and the page got a set-backed video with no type, size,
|
|
14419
|
+
* poster or description, and an image with no dimensions. But the field's
|
|
14420
|
+
* schema was built from the gallery module (`s.video(videosVal)` reads it at
|
|
14421
|
+
* definition), so the published entries are already here, on the schema
|
|
14422
|
+
* instance. This is where they are read from.
|
|
14423
|
+
*
|
|
14424
|
+
* Stops at a view: the module it points at is read on its own, with its own
|
|
14425
|
+
* galleries.
|
|
14426
|
+
*/
|
|
14427
|
+
function galleriesOf(schema) {
|
|
14428
|
+
if (schema === undefined) {
|
|
14429
|
+
return new Map();
|
|
14430
|
+
}
|
|
14431
|
+
var cached = cache$1.get(schema);
|
|
14432
|
+
if (cached) {
|
|
14433
|
+
return cached;
|
|
14434
|
+
}
|
|
14435
|
+
var galleries = new Map();
|
|
14436
|
+
var seen = new Set();
|
|
14437
|
+
function walk(node) {
|
|
14438
|
+
if (_typeof(node) !== "object" || node === null || seen.has(node)) {
|
|
14439
|
+
return;
|
|
14440
|
+
}
|
|
14441
|
+
seen.add(node);
|
|
14442
|
+
if (node instanceof ValViewSchema) {
|
|
14443
|
+
return;
|
|
14444
|
+
}
|
|
14445
|
+
if (node instanceof ImageSchema) {
|
|
14446
|
+
for (var _i = 0, _Object$entries = Object.entries(node["moduleMetadata"]); _i < _Object$entries.length; _i++) {
|
|
14447
|
+
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
|
|
14448
|
+
modulePath = _Object$entries$_i[0],
|
|
14449
|
+
entries = _Object$entries$_i[1];
|
|
14450
|
+
galleries.set(modulePath, entries);
|
|
14451
|
+
}
|
|
14452
|
+
return;
|
|
14453
|
+
}
|
|
14454
|
+
if (node instanceof FileSchema) {
|
|
14455
|
+
for (var _i2 = 0, _Object$entries2 = Object.entries(node["moduleMetadata"]); _i2 < _Object$entries2.length; _i2++) {
|
|
14456
|
+
var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),
|
|
14457
|
+
_modulePath = _Object$entries2$_i[0],
|
|
14458
|
+
_entries = _Object$entries2$_i[1];
|
|
14459
|
+
galleries.set(_modulePath, _entries);
|
|
14460
|
+
}
|
|
14461
|
+
return;
|
|
14462
|
+
}
|
|
14463
|
+
if (node instanceof VideoSchema) {
|
|
14464
|
+
var gallery = node["gallery"];
|
|
14465
|
+
if (gallery && gallery.entries !== null) {
|
|
14466
|
+
galleries.set(gallery.modulePath, gallery.entries);
|
|
14467
|
+
}
|
|
14468
|
+
return;
|
|
14469
|
+
}
|
|
14470
|
+
if (Array.isArray(node)) {
|
|
14471
|
+
var _iterator = result._createForOfIteratorHelper(node),
|
|
14472
|
+
_step;
|
|
14473
|
+
try {
|
|
14474
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
14475
|
+
var item = _step.value;
|
|
14476
|
+
walk(item);
|
|
14477
|
+
}
|
|
14478
|
+
} catch (err) {
|
|
14479
|
+
_iterator.e(err);
|
|
14480
|
+
} finally {
|
|
14481
|
+
_iterator.f();
|
|
14482
|
+
}
|
|
14483
|
+
return;
|
|
14484
|
+
}
|
|
14485
|
+
for (var _i3 = 0, _Object$values = Object.values(node); _i3 < _Object$values.length; _i3++) {
|
|
14486
|
+
var value = _Object$values[_i3];
|
|
14487
|
+
walk(value);
|
|
14488
|
+
}
|
|
14489
|
+
}
|
|
14490
|
+
walk(schema);
|
|
14491
|
+
cache$1.set(schema, galleries);
|
|
14492
|
+
return galleries;
|
|
14493
|
+
}
|
|
14494
|
+
|
|
13109
14495
|
/**
|
|
13110
14496
|
* The variant of a discriminated union that a value takes, by its tag.
|
|
13111
14497
|
*
|
|
@@ -13311,7 +14697,7 @@ function deserializeSchema(serialized) {
|
|
|
13311
14697
|
return schema;
|
|
13312
14698
|
}
|
|
13313
14699
|
function deserializeSchemaImpl(serialized) {
|
|
13314
|
-
var _serialized$options, _serialized$options2, _serialized$multiline, _serialized$render, _serialized$accept, _serialized$dir, _serialized$remote, _serialized$jsonValue, _serialized$render2, _serialized$external, _serialized$render3, _serialized$readonly, _serialized$hidden;
|
|
14700
|
+
var _serialized$options, _serialized$options2, _serialized$multiline, _serialized$render, _serialized$accept, _serialized$dir, _serialized$remote, _serialized$jsonValue, _serialized$render2, _serialized$external, _serialized$render3, _serialized$render4, _serialized$remote2, _serialized$readonly, _serialized$hidden;
|
|
13315
14701
|
switch (serialized.type) {
|
|
13316
14702
|
case "string":
|
|
13317
14703
|
return new StringSchema(_objectSpread2(_objectSpread2({}, serialized.options), {}, {
|
|
@@ -13370,6 +14756,8 @@ function deserializeSchemaImpl(serialized) {
|
|
|
13370
14756
|
accept: (_serialized$accept = serialized.accept) !== null && _serialized$accept !== void 0 ? _serialized$accept : "*/*",
|
|
13371
14757
|
dir: (_serialized$dir = serialized.dir) !== null && _serialized$dir !== void 0 ? _serialized$dir : "/public/val",
|
|
13372
14758
|
remote: (_serialized$remote = serialized.remote) !== null && _serialized$remote !== void 0 ? _serialized$remote : false,
|
|
14759
|
+
encode: serialized.encode,
|
|
14760
|
+
stream: serialized.stream,
|
|
13373
14761
|
altSchema: serialized.alt ? deserializeSchema(serialized.alt) : undefined
|
|
13374
14762
|
} : undefined, false, false, serialized.description, (_serialized$jsonValue = serialized.jsonValues) !== null && _serialized$jsonValue !== void 0 ? _serialized$jsonValue : false,
|
|
13375
14763
|
// The preview closure cannot survive serialization; the render can.
|
|
@@ -13395,6 +14783,12 @@ function deserializeSchemaImpl(serialized) {
|
|
|
13395
14783
|
return new FileSchema(serialized.options, serialized.opt, serialized.remote, [], {}, false, false, serialized.description);
|
|
13396
14784
|
case "image":
|
|
13397
14785
|
return new ImageSchema(serialized.options, serialized.opt, serialized.remote, [], {}, false, false, serialized.description);
|
|
14786
|
+
case "video":
|
|
14787
|
+
return new VideoSchema(serialized.options, serialized.opt, serialized.remote, [], false, false, serialized.description, (_serialized$render4 = serialized.render) !== null && _serialized$render4 !== void 0 ? _serialized$render4 : null, null, serialized.referencedModule ? {
|
|
14788
|
+
modulePath: serialized.referencedModule,
|
|
14789
|
+
entries: null,
|
|
14790
|
+
remote: (_serialized$remote2 = serialized.remote) !== null && _serialized$remote2 !== void 0 ? _serialized$remote2 : false
|
|
14791
|
+
} : null);
|
|
13398
14792
|
case "date":
|
|
13399
14793
|
return new DateSchema(serialized.options, serialized.opt, [], false, false, serialized.description);
|
|
13400
14794
|
case "dateTime":
|
|
@@ -14090,7 +15484,7 @@ function isPageRouter(routerId) {
|
|
|
14090
15484
|
|
|
14091
15485
|
var corePackageJson = {
|
|
14092
15486
|
name: "@valbuild/core",
|
|
14093
|
-
version: "0.
|
|
15487
|
+
version: "0.141.0",
|
|
14094
15488
|
"private": false,
|
|
14095
15489
|
description: "Val - supercharged hard-coded content",
|
|
14096
15490
|
repository: {
|
|
@@ -14179,6 +15573,7 @@ var Internal = {
|
|
|
14179
15573
|
VERSION: {
|
|
14180
15574
|
core: corePackageJson.version
|
|
14181
15575
|
},
|
|
15576
|
+
videosetEntryVideoSchema: videosetEntryVideoSchema,
|
|
14182
15577
|
// A view's read-path plumbing: `Internal` rather than the public surface,
|
|
14183
15578
|
// because an app never builds or unwraps a handle — it passes one to
|
|
14184
15579
|
// `useVal`.
|
|
@@ -14189,9 +15584,15 @@ var Internal = {
|
|
|
14189
15584
|
viewModulesOf: viewModulesOf,
|
|
14190
15585
|
mediaUrl: mediaUrl,
|
|
14191
15586
|
resolveMedia: resolveMedia,
|
|
15587
|
+
resolveVideo: resolveVideo,
|
|
14192
15588
|
isRemoteMediaPath: isRemoteMediaPath,
|
|
14193
15589
|
media: {
|
|
14194
|
-
fillFromGallery: fillFromGallery
|
|
15590
|
+
fillFromGallery: fillFromGallery,
|
|
15591
|
+
galleriesOf: galleriesOf,
|
|
15592
|
+
galleryEntryOf: galleryEntryOf,
|
|
15593
|
+
GALLERY_DEFAULT_GROUPS: GALLERY_DEFAULT_GROUPS,
|
|
15594
|
+
isHlsVideo: isHlsVideo,
|
|
15595
|
+
HLS_MIME_TYPE: HLS_MIME_TYPE
|
|
14195
15596
|
},
|
|
14196
15597
|
getSchema: getSchema,
|
|
14197
15598
|
getValPath: getValPath,
|
|
@@ -14239,6 +15640,13 @@ var Internal = {
|
|
|
14239
15640
|
isExternalFileRef: isExternalFileRef,
|
|
14240
15641
|
createValPathOfItem: createValPathOfItem,
|
|
14241
15642
|
getSHA256Hash: getSHA256Hash,
|
|
15643
|
+
/**
|
|
15644
|
+
* The same hash as `getSHA256Hash`, fed a chunk at a time: what a caller
|
|
15645
|
+
* hashing hundreds of megabytes uses to give the thread back between chunks.
|
|
15646
|
+
*/
|
|
15647
|
+
createSHA256Hash: function createSHA256Hash() {
|
|
15648
|
+
return createHash("sha256");
|
|
15649
|
+
},
|
|
14242
15650
|
initSchema: initSchema,
|
|
14243
15651
|
getMimeType: getMimeType,
|
|
14244
15652
|
mimeTypeToFileExt: mimeTypeToFileExt,
|
|
@@ -14309,6 +15717,9 @@ exports.DEFAULT_COLOR_FORMAT = DEFAULT_COLOR_FORMAT;
|
|
|
14309
15717
|
exports.DEFAULT_CONTENT_HOST = DEFAULT_CONTENT_HOST;
|
|
14310
15718
|
exports.DEFAULT_STATIC_HOST = DEFAULT_STATIC_HOST;
|
|
14311
15719
|
exports.DEFAULT_VAL_REMOTE_HOST = DEFAULT_VAL_REMOTE_HOST;
|
|
15720
|
+
exports.DEFAULT_VIDEO_ACCEPT = DEFAULT_VIDEO_ACCEPT;
|
|
15721
|
+
exports.DEFAULT_VIDEO_RENDITIONS = DEFAULT_VIDEO_RENDITIONS;
|
|
15722
|
+
exports.DEFAULT_VIDEO_SEGMENT_DURATION = DEFAULT_VIDEO_SEGMENT_DURATION;
|
|
14312
15723
|
exports.DateSchema = DateSchema;
|
|
14313
15724
|
exports.DateTimeSchema = DateTimeSchema;
|
|
14314
15725
|
exports.DiscriminatedUnionSchema = DiscriminatedUnionSchema;
|
|
@@ -14338,12 +15749,14 @@ exports.THEME_RADIUS_STEPS = THEME_RADIUS_STEPS;
|
|
|
14338
15749
|
exports.UNSAFE_URL_SCHEMES = UNSAFE_URL_SCHEMES;
|
|
14339
15750
|
exports.VAL_EXTENSION = VAL_EXTENSION;
|
|
14340
15751
|
exports.ValViewSchema = ValViewSchema;
|
|
15752
|
+
exports.VideoSchema = VideoSchema;
|
|
14341
15753
|
exports._classCallCheck = _classCallCheck;
|
|
14342
15754
|
exports._createClass = _createClass;
|
|
14343
15755
|
exports._slicedToArray = _slicedToArray;
|
|
14344
15756
|
exports._toConsumableArray = _toConsumableArray;
|
|
14345
15757
|
exports._typeof = _typeof;
|
|
14346
15758
|
exports.assistantAvailability = assistantAvailability;
|
|
15759
|
+
exports.computeSchemaSha = computeSchemaSha;
|
|
14347
15760
|
exports.computeSourcesSha = computeSourcesSha;
|
|
14348
15761
|
exports.computeValModuleShas = computeValModuleShas;
|
|
14349
15762
|
exports.declaredKeySetOf = declaredKeySetOf;
|