@valbuild/core 0.139.1 → 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 +63 -0
- package/dist/declarations/src/getSha256.d.ts +55 -0
- package/dist/declarations/src/index.d.ts +20 -3
- 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-7d334094.cjs.prod.js → index-13cf45b1.cjs.prod.js} +1535 -151
- package/dist/{index-eb9f6480.esm.js → index-a6c53286.esm.js} +1532 -152
- package/dist/{index-90000f7a.cjs.dev.js → index-fae161b5.cjs.dev.js} +1535 -151
- package/dist/valbuild-core.cjs.dev.js +5 -1
- package/dist/valbuild-core.cjs.prod.js +5 -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
|
@@ -2752,6 +2752,28 @@ var discriminatedUnion = function discriminatedUnion(key) {
|
|
|
2752
2752
|
return new DiscriminatedUnionSchema(key, objects);
|
|
2753
2753
|
};
|
|
2754
2754
|
|
|
2755
|
+
function _objectWithoutPropertiesLoose(r, e) {
|
|
2756
|
+
if (null == r) return {};
|
|
2757
|
+
var t = {};
|
|
2758
|
+
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
|
2759
|
+
if (-1 !== e.indexOf(n)) continue;
|
|
2760
|
+
t[n] = r[n];
|
|
2761
|
+
}
|
|
2762
|
+
return t;
|
|
2763
|
+
}
|
|
2764
|
+
|
|
2765
|
+
function _objectWithoutProperties(e, t) {
|
|
2766
|
+
if (null == e) return {};
|
|
2767
|
+
var o,
|
|
2768
|
+
r,
|
|
2769
|
+
i = _objectWithoutPropertiesLoose(e, t);
|
|
2770
|
+
if (Object.getOwnPropertySymbols) {
|
|
2771
|
+
var n = Object.getOwnPropertySymbols(e);
|
|
2772
|
+
for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
|
|
2773
|
+
}
|
|
2774
|
+
return i;
|
|
2775
|
+
}
|
|
2776
|
+
|
|
2755
2777
|
var RegEx$1 = /^(https?:\/\/[^/]+)\/file\/p\/([^/]+)\/b\/([^/]+)\/v\/([^/]+)\/h\/([^/]+)\/f\/([^/]+)\/p\/(.+)$/;
|
|
2756
2778
|
function splitRemoteRef(ref) {
|
|
2757
2779
|
if (ref[0] === "/") {
|
|
@@ -2793,6 +2815,8 @@ function splitRemoteRef(ref) {
|
|
|
2793
2815
|
};
|
|
2794
2816
|
}
|
|
2795
2817
|
|
|
2818
|
+
var _excluded = ["poster", "captions"];
|
|
2819
|
+
|
|
2796
2820
|
/** What must stay in frame when a page crops an image. */
|
|
2797
2821
|
|
|
2798
2822
|
/**
|
|
@@ -2801,6 +2825,76 @@ function splitRemoteRef(ref) {
|
|
|
2801
2825
|
* here. One place per fact.
|
|
2802
2826
|
*/
|
|
2803
2827
|
|
|
2828
|
+
/**
|
|
2829
|
+
* The still shown before a video plays — `<video poster>`.
|
|
2830
|
+
*
|
|
2831
|
+
* Derived, like a video's `width` and `height`: the Studio grabs the frame at
|
|
2832
|
+
* {@link VideoSource.posterTime} and uploads it as an image, so a page can show
|
|
2833
|
+
* it without decoding the video. It is a media object of its own (a `path`,
|
|
2834
|
+
* and a `patch_id` while unpublished) because it is a file of its own.
|
|
2835
|
+
*/
|
|
2836
|
+
|
|
2837
|
+
/**
|
|
2838
|
+
* One text track of a video — `<track src srclang label kind default>`.
|
|
2839
|
+
*
|
|
2840
|
+
* `path` is a WebVTT file, uploaded like any other file.
|
|
2841
|
+
*/
|
|
2842
|
+
|
|
2843
|
+
/**
|
|
2844
|
+
* What a video FIELD authors, on top of the file it names: the description,
|
|
2845
|
+
* the crop, the poster, the trim and the caption tracks.
|
|
2846
|
+
*
|
|
2847
|
+
* This is the whole value of a field picked from an `s.videoset()`
|
|
2848
|
+
* (`s.video(videosetVal)`) — the mime type, size and length live in the set,
|
|
2849
|
+
* keyed by `path`, and repeating them here is how two copies of one fact get
|
|
2850
|
+
* to disagree. The poster, captions and times stay with the FIELD: one video
|
|
2851
|
+
* used in two places can be trimmed and captioned differently in each.
|
|
2852
|
+
*
|
|
2853
|
+
* Times are in seconds from the start of the file.
|
|
2854
|
+
*/
|
|
2855
|
+
|
|
2856
|
+
/**
|
|
2857
|
+
* What one page chooses about a video — as opposed to what is true of the
|
|
2858
|
+
* file. A field (`s.video()`) carries these for itself; the entry of a set
|
|
2859
|
+
* (`s.videoset()`) carries them as DEFAULTS, which every field picked from the
|
|
2860
|
+
* set starts from and may override key by key. See {@link fillFromGallery}.
|
|
2861
|
+
*/
|
|
2862
|
+
|
|
2863
|
+
/**
|
|
2864
|
+
* A video: a progressive file (`video/mp4`, `video/webm`) or an HLS stream
|
|
2865
|
+
* (`application/vnd.apple.mpegurl`, whose `path` is the master playlist).
|
|
2866
|
+
*
|
|
2867
|
+
* `mimeType` is REQUIRED on a video of its own: a page has to know which of
|
|
2868
|
+
* the two it is holding before it can play it at all — an `.m3u8` handed to a
|
|
2869
|
+
* `<video src>` plays only in Safari. (What tells a video's TYPE apart from an
|
|
2870
|
+
* image's is its declared keys, see {@link IsVideoSource}, because a field
|
|
2871
|
+
* picked from a set has no `mimeType` of its own.)
|
|
2872
|
+
*
|
|
2873
|
+
* `width`, `height`, `duration` and `mimeType` are read from the bytes;
|
|
2874
|
+
* everything else is authored.
|
|
2875
|
+
*/
|
|
2876
|
+
|
|
2877
|
+
/**
|
|
2878
|
+
* Whether a source TYPE is a video's.
|
|
2879
|
+
*
|
|
2880
|
+
* Every media source is "a `path` plus optional fields", so assignability
|
|
2881
|
+
* cannot tell an image from a video: an image is assignable to a set-backed
|
|
2882
|
+
* video and the other way round. The keys a type DECLARES can — only a video
|
|
2883
|
+
* declares `posterTime` — so the readers' conditional types ask this before
|
|
2884
|
+
* they ask about images.
|
|
2885
|
+
*/
|
|
2886
|
+
|
|
2887
|
+
/** The mime type of an HLS master playlist. */
|
|
2888
|
+
var HLS_MIME_TYPE = "application/vnd.apple.mpegurl";
|
|
2889
|
+
|
|
2890
|
+
/** Whether a video is an HLS stream rather than a single progressive file. */
|
|
2891
|
+
function isHlsVideo(src) {
|
|
2892
|
+
if (src.mimeType !== undefined) {
|
|
2893
|
+
return src.mimeType === HLS_MIME_TYPE || src.mimeType.toLowerCase() === "application/x-mpegurl";
|
|
2894
|
+
}
|
|
2895
|
+
return src.path.split("?")[0].toLowerCase().endsWith(".m3u8");
|
|
2896
|
+
}
|
|
2897
|
+
|
|
2804
2898
|
/**
|
|
2805
2899
|
* The structural supertype of every media source.
|
|
2806
2900
|
*
|
|
@@ -2854,66 +2948,181 @@ function resolveMedia(src) {
|
|
|
2854
2948
|
url: mediaUrl(src)
|
|
2855
2949
|
});
|
|
2856
2950
|
}
|
|
2951
|
+
|
|
2952
|
+
/**
|
|
2953
|
+
* A video as a reader sees it: every file it names — the video itself, its
|
|
2954
|
+
* poster and each caption track — carries the URL its bytes are served from.
|
|
2955
|
+
*
|
|
2956
|
+
* Each gets its own {@link mediaUrl} because each is its own file with its own
|
|
2957
|
+
* `patch_id`: replacing only the poster drafts the poster, and the video keeps
|
|
2958
|
+
* its published URL.
|
|
2959
|
+
*/
|
|
2960
|
+
|
|
2961
|
+
/**
|
|
2962
|
+
* The single implementation of {@link ResolvedVideo}. `url` is passed in as a
|
|
2963
|
+
* function so the reader can tag the video's own URL (stega) without tagging
|
|
2964
|
+
* the poster's and the captions', which are not where an edit lands.
|
|
2965
|
+
*/
|
|
2966
|
+
function resolveVideo(src) {
|
|
2967
|
+
var videoUrl = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : mediaUrl;
|
|
2968
|
+
var poster = src.poster,
|
|
2969
|
+
captions = src.captions,
|
|
2970
|
+
rest = _objectWithoutProperties(src, _excluded);
|
|
2971
|
+
var resolved = _objectSpread2(_objectSpread2({}, rest), {}, {
|
|
2972
|
+
url: videoUrl(src)
|
|
2973
|
+
});
|
|
2974
|
+
if (poster && _typeof(poster) === "object" && typeof poster.path === "string") {
|
|
2975
|
+
return withCaptions(_objectSpread2(_objectSpread2({}, resolved), {}, {
|
|
2976
|
+
poster: _objectSpread2(_objectSpread2({}, poster), {}, {
|
|
2977
|
+
url: mediaUrl(poster)
|
|
2978
|
+
})
|
|
2979
|
+
}), captions);
|
|
2980
|
+
}
|
|
2981
|
+
return withCaptions(resolved, captions);
|
|
2982
|
+
}
|
|
2983
|
+
function withCaptions(resolved, captions) {
|
|
2984
|
+
if (!Array.isArray(captions)) {
|
|
2985
|
+
return resolved;
|
|
2986
|
+
}
|
|
2987
|
+
return _objectSpread2(_objectSpread2({}, resolved), {}, {
|
|
2988
|
+
captions: captions.filter(function (track) {
|
|
2989
|
+
return !!track && _typeof(track) === "object" && typeof track.path === "string";
|
|
2990
|
+
}).map(function (track) {
|
|
2991
|
+
return _objectSpread2(_objectSpread2({}, track), {}, {
|
|
2992
|
+
url: mediaUrl(track)
|
|
2993
|
+
});
|
|
2994
|
+
})
|
|
2995
|
+
});
|
|
2996
|
+
}
|
|
2857
2997
|
function isMediaSchema(schema) {
|
|
2858
|
-
return _typeof(schema) === "object" && schema !== null && "type" in schema && (schema.type === "image" || schema.type === "file");
|
|
2998
|
+
return _typeof(schema) === "object" && schema !== null && "type" in schema && (schema.type === "image" || schema.type === "file" || schema.type === "video");
|
|
2859
2999
|
}
|
|
2860
3000
|
|
|
2861
3001
|
/**
|
|
2862
|
-
*
|
|
2863
|
-
*
|
|
2864
|
-
* `s.image(galleryModule)` stores only `{path, alt?, hotspot?}` — the
|
|
2865
|
-
* dimensions and mime type live in the gallery module, keyed by path. This is
|
|
2866
|
-
* the single implementation of that lookup; core, stega/RSC and the Studio all
|
|
2867
|
-
* call it rather than each rolling their own.
|
|
3002
|
+
* What a gallery entry holds as a DEFAULT for the fields picked from it, in
|
|
3003
|
+
* the groups a field overrides together.
|
|
2868
3004
|
*
|
|
2869
|
-
*
|
|
2870
|
-
*
|
|
2871
|
-
*
|
|
2872
|
-
*
|
|
2873
|
-
|
|
2874
|
-
|
|
3005
|
+
* Per key, not per value: a field that has set its own `startTime` still
|
|
3006
|
+
* takes the gallery's `endTime`. The poster is the one pair — `poster` is the
|
|
3007
|
+
* frame at `posterTime`, so a field with either has chosen its own still, and
|
|
3008
|
+
* taking the other half from the gallery would describe a frame nobody chose.
|
|
3009
|
+
*/
|
|
3010
|
+
var GALLERY_DEFAULT_GROUPS = [["alt"], ["hotspot"], ["poster", "posterTime"], ["startTime"], ["endTime"], ["captions"]];
|
|
3011
|
+
|
|
3012
|
+
/** What is true of the file, and the gallery's alone. */
|
|
3013
|
+
var GALLERY_FILE_FACTS = ["width", "height", "mimeType", "duration"];
|
|
3014
|
+
|
|
3015
|
+
/**
|
|
3016
|
+
* The gallery entry a gallery-backed value names, or `null` when it is not
|
|
3017
|
+
* gallery-backed or the gallery has no such entry.
|
|
2875
3018
|
*
|
|
2876
3019
|
* The double lookup is load-bearing: a remote gallery keys its entries by the
|
|
2877
3020
|
* remote URL while the file itself stays on disk under its local path.
|
|
2878
3021
|
*/
|
|
2879
|
-
function
|
|
3022
|
+
function galleryEntryOf(src, schema, getModuleSource) {
|
|
2880
3023
|
if (!isMediaSchema(schema) || !schema.referencedModule) {
|
|
2881
|
-
return
|
|
3024
|
+
return null;
|
|
2882
3025
|
}
|
|
2883
3026
|
var moduleSource = getModuleSource(schema.referencedModule);
|
|
2884
|
-
if (!
|
|
2885
|
-
return
|
|
3027
|
+
if (!isPlainObject(moduleSource)) {
|
|
3028
|
+
return null;
|
|
2886
3029
|
}
|
|
2887
|
-
var
|
|
2888
|
-
var key = src.path in entries ? src.path : null;
|
|
3030
|
+
var key = src.path in moduleSource ? src.path : null;
|
|
2889
3031
|
if (key === null) {
|
|
2890
3032
|
var splitRemoteRefRes = splitRemoteRef(src.path);
|
|
2891
|
-
if (splitRemoteRefRes.status === "success" && splitRemoteRefRes.filePath in
|
|
3033
|
+
if (splitRemoteRefRes.status === "success" && splitRemoteRefRes.filePath in moduleSource) {
|
|
2892
3034
|
key = splitRemoteRefRes.filePath;
|
|
2893
3035
|
}
|
|
2894
3036
|
}
|
|
2895
3037
|
if (key === null) {
|
|
2896
|
-
return
|
|
3038
|
+
return null;
|
|
2897
3039
|
}
|
|
2898
|
-
var entry =
|
|
2899
|
-
|
|
3040
|
+
var entry = moduleSource[key];
|
|
3041
|
+
return isPlainObject(entry) ? entry : null;
|
|
3042
|
+
}
|
|
3043
|
+
|
|
3044
|
+
/**
|
|
3045
|
+
* The value a gallery-backed field means: its own keys, and the gallery's
|
|
3046
|
+
* where it has none.
|
|
3047
|
+
*
|
|
3048
|
+
* `s.image(galleryModule)` and `s.video(videosModule)` store only what one
|
|
3049
|
+
* page chose — the rest lives in the gallery, keyed by path. Two things come
|
|
3050
|
+
* from there:
|
|
3051
|
+
*
|
|
3052
|
+
* - **What is true of the file** — dimensions, mime type, length. The field
|
|
3053
|
+
* never has these, so they are always the gallery's.
|
|
3054
|
+
* - **The defaults** — description, focal point, a video's poster, start, end
|
|
3055
|
+
* and captions ({@link GALLERY_DEFAULT_GROUPS}). An editor sets them once
|
|
3056
|
+
* on the gallery entry; a field that sets its own wins, KEY BY KEY.
|
|
3057
|
+
*
|
|
3058
|
+
* The single implementation of that merge: core, stega/RSC and the Studio all
|
|
3059
|
+
* call it rather than each rolling their own, so a page and the Studio's
|
|
3060
|
+
* preview of it cannot disagree about which poster a video has.
|
|
3061
|
+
*
|
|
3062
|
+
* A gallery whose `alt` schema is a locale record holds an object rather than
|
|
3063
|
+
* a string; that is left alone rather than copied into a field typed
|
|
3064
|
+
* `string`, and making the override locale-shaped is a separate change.
|
|
3065
|
+
*/
|
|
3066
|
+
function fillFromGallery(src, schema, getModuleSource) {
|
|
3067
|
+
var entry = galleryEntryOf(src, schema, getModuleSource);
|
|
3068
|
+
if (entry === null) {
|
|
2900
3069
|
return src;
|
|
2901
3070
|
}
|
|
2902
|
-
var
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
3071
|
+
var own = _objectSpread2({}, src);
|
|
3072
|
+
var filled = {};
|
|
3073
|
+
var _iterator = _createForOfIteratorHelper(GALLERY_FILE_FACTS),
|
|
3074
|
+
_step;
|
|
3075
|
+
try {
|
|
3076
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
3077
|
+
var key = _step.value;
|
|
3078
|
+
if (entry[key] !== undefined) {
|
|
3079
|
+
filled[key] = entry[key];
|
|
3080
|
+
}
|
|
3081
|
+
}
|
|
3082
|
+
} catch (err) {
|
|
3083
|
+
_iterator.e(err);
|
|
3084
|
+
} finally {
|
|
3085
|
+
_iterator.f();
|
|
3086
|
+
}
|
|
3087
|
+
var _iterator2 = _createForOfIteratorHelper(GALLERY_DEFAULT_GROUPS),
|
|
3088
|
+
_step2;
|
|
3089
|
+
try {
|
|
3090
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
3091
|
+
var group = _step2.value;
|
|
3092
|
+
if (group.some(function (key) {
|
|
3093
|
+
return own[key] !== undefined;
|
|
3094
|
+
})) {
|
|
3095
|
+
continue;
|
|
3096
|
+
}
|
|
3097
|
+
var _iterator3 = _createForOfIteratorHelper(group),
|
|
3098
|
+
_step3;
|
|
3099
|
+
try {
|
|
3100
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
3101
|
+
var _key = _step3.value;
|
|
3102
|
+
var value = entry[_key];
|
|
3103
|
+
if (value === undefined || value === null) {
|
|
3104
|
+
continue;
|
|
3105
|
+
}
|
|
3106
|
+
if (_key === "alt" && typeof value !== "string") {
|
|
3107
|
+
continue;
|
|
3108
|
+
}
|
|
3109
|
+
filled[_key] = value;
|
|
3110
|
+
}
|
|
3111
|
+
} catch (err) {
|
|
3112
|
+
_iterator3.e(err);
|
|
3113
|
+
} finally {
|
|
3114
|
+
_iterator3.f();
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
3117
|
+
} catch (err) {
|
|
3118
|
+
_iterator2.e(err);
|
|
3119
|
+
} finally {
|
|
3120
|
+
_iterator2.f();
|
|
3121
|
+
}
|
|
3122
|
+
return _objectSpread2(_objectSpread2({}, src), filled);
|
|
3123
|
+
}
|
|
3124
|
+
function isPlainObject(value) {
|
|
3125
|
+
return _typeof(value) === "object" && value !== null && !Array.isArray(value);
|
|
2917
3126
|
}
|
|
2918
3127
|
|
|
2919
3128
|
var EXT_TO_MIME_TYPES = {
|
|
@@ -3444,6 +3653,8 @@ var EXT_TO_MIME_TYPES = {
|
|
|
3444
3653
|
qam: "application/vnd.epson.quickanime",
|
|
3445
3654
|
qfx: "application/vnd.intu.qfx",
|
|
3446
3655
|
mov: "video/quicktime",
|
|
3656
|
+
vtt: "text/vtt",
|
|
3657
|
+
mkv: "video/x-matroska",
|
|
3447
3658
|
rar: "application/x-rar-compressed",
|
|
3448
3659
|
ram: "audio/x-pn-realaudio",
|
|
3449
3660
|
rmp: "audio/x-pn-realaudio-plugin",
|
|
@@ -4095,6 +4306,19 @@ var ImageSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4095
4306
|
/** An image of its own, carrying its own dimensions and mime type. */
|
|
4096
4307
|
|
|
4097
4308
|
function image(options, galleryOptions) {
|
|
4309
|
+
return imageOf(false, options, galleryOptions);
|
|
4310
|
+
}
|
|
4311
|
+
|
|
4312
|
+
/**
|
|
4313
|
+
* `s.image()` for a project whose media is all remote (`files.remote` in
|
|
4314
|
+
* `val.config.ts`): the same schema, with `.remote()` already applied. See
|
|
4315
|
+
* `initSchema`.
|
|
4316
|
+
*/
|
|
4317
|
+
|
|
4318
|
+
function remoteImage(options, galleryOptions) {
|
|
4319
|
+
return imageOf(true, options, galleryOptions);
|
|
4320
|
+
}
|
|
4321
|
+
function imageOf(remote, options, galleryOptions) {
|
|
4098
4322
|
var isModule = !!options && !!Internal.getValPath(options);
|
|
4099
4323
|
if (isModule) {
|
|
4100
4324
|
var allModules = {};
|
|
@@ -4108,9 +4332,9 @@ function image(options, galleryOptions) {
|
|
|
4108
4332
|
}
|
|
4109
4333
|
return new ImageSchema((galleryOptions === null || galleryOptions === void 0 ? void 0 : galleryOptions.encode) !== undefined ? {
|
|
4110
4334
|
encode: galleryOptions.encode
|
|
4111
|
-
} : {}, false,
|
|
4335
|
+
} : {}, false, remote, [], allModules);
|
|
4112
4336
|
}
|
|
4113
|
-
return new ImageSchema(options);
|
|
4337
|
+
return new ImageSchema(options, false, remote);
|
|
4114
4338
|
}
|
|
4115
4339
|
|
|
4116
4340
|
var RouteSchema = /*#__PURE__*/function (_Schema) {
|
|
@@ -4369,6 +4593,7 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4369
4593
|
var isHidden = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
4370
4594
|
var description = arguments.length > 5 ? arguments[5] : undefined;
|
|
4371
4595
|
var previewInput = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null;
|
|
4596
|
+
var imgRemote = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;
|
|
4372
4597
|
_classCallCheck(this, RichTextSchema);
|
|
4373
4598
|
_this = _callSuper(this, RichTextSchema);
|
|
4374
4599
|
_this.options = options;
|
|
@@ -4378,6 +4603,7 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4378
4603
|
_this.isHidden = isHidden;
|
|
4379
4604
|
_this.description = description;
|
|
4380
4605
|
_this.previewInput = previewInput;
|
|
4606
|
+
_this.imgRemote = imgRemote;
|
|
4381
4607
|
return _this;
|
|
4382
4608
|
}
|
|
4383
4609
|
|
|
@@ -4404,7 +4630,7 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4404
4630
|
return _createClass(RichTextSchema, [{
|
|
4405
4631
|
key: "describe",
|
|
4406
4632
|
value: function describe(description) {
|
|
4407
|
-
return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.previewInput);
|
|
4633
|
+
return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.previewInput, this.imgRemote);
|
|
4408
4634
|
}
|
|
4409
4635
|
|
|
4410
4636
|
/**
|
|
@@ -4424,7 +4650,7 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4424
4650
|
value: function maxLength(max) {
|
|
4425
4651
|
return new RichTextSchema(_objectSpread2(_objectSpread2({}, this.options), {}, {
|
|
4426
4652
|
maxLength: max
|
|
4427
|
-
}), this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.previewInput);
|
|
4653
|
+
}), this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.previewInput, this.imgRemote);
|
|
4428
4654
|
}
|
|
4429
4655
|
|
|
4430
4656
|
/**
|
|
@@ -4444,7 +4670,7 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4444
4670
|
value: function minLength(min) {
|
|
4445
4671
|
return new RichTextSchema(_objectSpread2(_objectSpread2({}, this.options), {}, {
|
|
4446
4672
|
minLength: min
|
|
4447
|
-
}), this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.previewInput);
|
|
4673
|
+
}), this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.previewInput, this.imgRemote);
|
|
4448
4674
|
}
|
|
4449
4675
|
|
|
4450
4676
|
/**
|
|
@@ -4472,7 +4698,7 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4472
4698
|
}, {
|
|
4473
4699
|
key: "validate",
|
|
4474
4700
|
value: function validate(validationFunction) {
|
|
4475
|
-
return new RichTextSchema(this.options, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]), this.isReadonly, this.isHidden, this.description, this.previewInput);
|
|
4701
|
+
return new RichTextSchema(this.options, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]), this.isReadonly, this.isHidden, this.description, this.previewInput, this.imgRemote);
|
|
4476
4702
|
}
|
|
4477
4703
|
}, {
|
|
4478
4704
|
key: "executeValidate",
|
|
@@ -4647,7 +4873,7 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4647
4873
|
}
|
|
4648
4874
|
var srcPath = unsafeCreateSourcePath(path, "src");
|
|
4649
4875
|
var imgSchema = _this2.options.img;
|
|
4650
|
-
var imageValidationErrors = _typeof(imgSchema) === "object" ? imgSchema["executeValidate"](srcPath, node.src) : new ImageSchema({}, false,
|
|
4876
|
+
var imageValidationErrors = _typeof(imgSchema) === "object" ? imgSchema["executeValidate"](srcPath, node.src) : new ImageSchema({}, false, _this2.imgRemote)["executeValidate"](srcPath, node.src);
|
|
4651
4877
|
if (imageValidationErrors) {
|
|
4652
4878
|
for (var _validationErrorPathS in imageValidationErrors) {
|
|
4653
4879
|
var _current$_validationE;
|
|
@@ -4916,19 +5142,19 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4916
5142
|
}, {
|
|
4917
5143
|
key: "nullable",
|
|
4918
5144
|
value: function nullable() {
|
|
4919
|
-
return new RichTextSchema(this.options, true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.previewInput);
|
|
5145
|
+
return new RichTextSchema(this.options, true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.previewInput, this.imgRemote);
|
|
4920
5146
|
}
|
|
4921
5147
|
}, {
|
|
4922
5148
|
key: "readonly",
|
|
4923
5149
|
value: function readonly() {
|
|
4924
5150
|
var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
4925
|
-
return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.previewInput);
|
|
5151
|
+
return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.previewInput, this.imgRemote);
|
|
4926
5152
|
}
|
|
4927
5153
|
}, {
|
|
4928
5154
|
key: "hidden",
|
|
4929
5155
|
value: function hidden() {
|
|
4930
5156
|
var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
4931
|
-
return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.previewInput);
|
|
5157
|
+
return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.previewInput, this.imgRemote);
|
|
4932
5158
|
}
|
|
4933
5159
|
}, {
|
|
4934
5160
|
key: "executeCustomValidateAt",
|
|
@@ -4956,7 +5182,7 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4956
5182
|
}, {
|
|
4957
5183
|
key: "preview",
|
|
4958
5184
|
value: function preview(select) {
|
|
4959
|
-
return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, select);
|
|
5185
|
+
return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, select, this.imgRemote);
|
|
4960
5186
|
}
|
|
4961
5187
|
}, {
|
|
4962
5188
|
key: "executePreviewItem",
|
|
@@ -5002,7 +5228,10 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5002
5228
|
ul: this.options.ul,
|
|
5003
5229
|
ol: this.options.ol,
|
|
5004
5230
|
a: serializeAnchorSchema(),
|
|
5005
|
-
img: this.options.img && _typeof(this.options.img) === "object" ? this.options.img["executeSerialize"]() :
|
|
5231
|
+
img: this.options.img && _typeof(this.options.img) === "object" ? this.options.img["executeSerialize"]() :
|
|
5232
|
+
// The Studio decides local or remote by the serialized image
|
|
5233
|
+
// schema, and `true` carries no such answer.
|
|
5234
|
+
this.options.img && this.imgRemote ? new ImageSchema(undefined, false, true)["executeSerialize"]() : this.options.img
|
|
5006
5235
|
};
|
|
5007
5236
|
return {
|
|
5008
5237
|
type: "richtext",
|
|
@@ -5021,6 +5250,14 @@ var richtext = function richtext(options) {
|
|
|
5021
5250
|
return new RichTextSchema(options !== null && options !== void 0 ? options : {});
|
|
5022
5251
|
};
|
|
5023
5252
|
|
|
5253
|
+
/**
|
|
5254
|
+
* `s.richtext()` for a project whose media is all remote (`files.remote` in
|
|
5255
|
+
* `val.config.ts`): `img: true` is a remote image. See `initSchema`.
|
|
5256
|
+
*/
|
|
5257
|
+
var remoteRichtext = function remoteRichtext(options) {
|
|
5258
|
+
return new RichTextSchema(options !== null && options !== void 0 ? options : {}, false, [], false, false, undefined, null, true);
|
|
5259
|
+
};
|
|
5260
|
+
|
|
5024
5261
|
function _regeneratorDefine(e, r, n, t) {
|
|
5025
5262
|
var i = Object.defineProperty;
|
|
5026
5263
|
try {
|
|
@@ -5469,6 +5706,207 @@ function missingDeclaredKeys(declared, present) {
|
|
|
5469
5706
|
});
|
|
5470
5707
|
}
|
|
5471
5708
|
|
|
5709
|
+
/**
|
|
5710
|
+
* The checks of what one page chose about a video — its times, focal point,
|
|
5711
|
+
* poster and captions — shared by the two places those choices are made: a
|
|
5712
|
+
* field (`s.video()`) and the entry of a set (`s.videoset()`), which holds the
|
|
5713
|
+
* same choices as the defaults every field picked from it starts from.
|
|
5714
|
+
*/
|
|
5715
|
+
|
|
5716
|
+
function isRecord(value) {
|
|
5717
|
+
return _typeof(value) === "object" && value !== null && !Array.isArray(value);
|
|
5718
|
+
}
|
|
5719
|
+
function stripQuery$1(path) {
|
|
5720
|
+
return path.split("?")[0];
|
|
5721
|
+
}
|
|
5722
|
+
|
|
5723
|
+
/**
|
|
5724
|
+
* What is checked, typed as what it IS rather than what it should be: a
|
|
5725
|
+
* field's value and a set's entry both reach here from hand-written JSON
|
|
5726
|
+
* that never saw the type.
|
|
5727
|
+
*/
|
|
5728
|
+
|
|
5729
|
+
function isNonNegativeNumber(value) {
|
|
5730
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
5731
|
+
}
|
|
5732
|
+
function validateTimes(src, duration) {
|
|
5733
|
+
var errors = [];
|
|
5734
|
+
var _iterator = _createForOfIteratorHelper(["posterTime", "startTime", "endTime"]),
|
|
5735
|
+
_step;
|
|
5736
|
+
try {
|
|
5737
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
5738
|
+
var key = _step.value;
|
|
5739
|
+
var value = src[key];
|
|
5740
|
+
if (value === undefined) {
|
|
5741
|
+
continue;
|
|
5742
|
+
}
|
|
5743
|
+
if (!isNonNegativeNumber(value)) {
|
|
5744
|
+
errors.push({
|
|
5745
|
+
message: "'".concat(key, "' must be a number of seconds, 0 or more. Got: ").concat(JSON.stringify(value)),
|
|
5746
|
+
value: src
|
|
5747
|
+
});
|
|
5748
|
+
} else if (duration !== undefined && value > duration) {
|
|
5749
|
+
errors.push({
|
|
5750
|
+
message: "'".concat(key, "' (").concat(value, "s) is after the end of the video (").concat(duration, "s)."),
|
|
5751
|
+
value: src
|
|
5752
|
+
});
|
|
5753
|
+
}
|
|
5754
|
+
}
|
|
5755
|
+
} catch (err) {
|
|
5756
|
+
_iterator.e(err);
|
|
5757
|
+
} finally {
|
|
5758
|
+
_iterator.f();
|
|
5759
|
+
}
|
|
5760
|
+
var startTime = src.startTime,
|
|
5761
|
+
endTime = src.endTime;
|
|
5762
|
+
if (isNonNegativeNumber(startTime) && isNonNegativeNumber(endTime) && startTime >= endTime) {
|
|
5763
|
+
errors.push({
|
|
5764
|
+
message: "'startTime' (".concat(startTime, "s) must be before 'endTime' (").concat(endTime, "s)."),
|
|
5765
|
+
value: src
|
|
5766
|
+
});
|
|
5767
|
+
}
|
|
5768
|
+
return errors;
|
|
5769
|
+
}
|
|
5770
|
+
function validateHotspot(src) {
|
|
5771
|
+
if (src.hotspot === undefined) {
|
|
5772
|
+
return [];
|
|
5773
|
+
}
|
|
5774
|
+
var hotspot = src.hotspot;
|
|
5775
|
+
if (!isRecord(hotspot) || typeof hotspot.x !== "number" || typeof hotspot.y !== "number" || hotspot.x < 0 || hotspot.x > 1 || hotspot.y < 0 || hotspot.y > 1) {
|
|
5776
|
+
return [{
|
|
5777
|
+
message: "'hotspot' must be { x, y } with both between 0 and 1.",
|
|
5778
|
+
value: src
|
|
5779
|
+
}];
|
|
5780
|
+
}
|
|
5781
|
+
return [];
|
|
5782
|
+
}
|
|
5783
|
+
function validatePoster(src) {
|
|
5784
|
+
if (src.poster === undefined) {
|
|
5785
|
+
return [];
|
|
5786
|
+
}
|
|
5787
|
+
var poster = src.poster;
|
|
5788
|
+
if (!isRecord(poster) || typeof poster.path !== "string") {
|
|
5789
|
+
return [{
|
|
5790
|
+
message: "'poster' must be an image object with a 'path'.",
|
|
5791
|
+
value: src
|
|
5792
|
+
}];
|
|
5793
|
+
}
|
|
5794
|
+
var mimeType = filenameToMimeType(stripQuery$1(poster.path));
|
|
5795
|
+
if (!mimeType || !mimeType.startsWith("image/")) {
|
|
5796
|
+
return [{
|
|
5797
|
+
message: "The poster must be an image. Got: ".concat(poster.path),
|
|
5798
|
+
value: src
|
|
5799
|
+
}];
|
|
5800
|
+
}
|
|
5801
|
+
return [];
|
|
5802
|
+
}
|
|
5803
|
+
var CAPTION_KINDS = ["subtitles", "captions"];
|
|
5804
|
+
function validateCaptions(src) {
|
|
5805
|
+
if (src.captions === undefined) {
|
|
5806
|
+
return [];
|
|
5807
|
+
}
|
|
5808
|
+
if (!Array.isArray(src.captions)) {
|
|
5809
|
+
return [{
|
|
5810
|
+
message: "'captions' must be an array.",
|
|
5811
|
+
value: src
|
|
5812
|
+
}];
|
|
5813
|
+
}
|
|
5814
|
+
var errors = [];
|
|
5815
|
+
var defaults = 0;
|
|
5816
|
+
var seen = new Set();
|
|
5817
|
+
src.captions.forEach(function (track, i) {
|
|
5818
|
+
var at = "Caption track ".concat(i + 1);
|
|
5819
|
+
if (!isRecord(track)) {
|
|
5820
|
+
errors.push({
|
|
5821
|
+
message: "".concat(at, " must be an object."),
|
|
5822
|
+
value: src
|
|
5823
|
+
});
|
|
5824
|
+
return;
|
|
5825
|
+
}
|
|
5826
|
+
var t = track;
|
|
5827
|
+
if (typeof t.path !== "string") {
|
|
5828
|
+
errors.push({
|
|
5829
|
+
message: "".concat(at, " has no 'path'."),
|
|
5830
|
+
value: src
|
|
5831
|
+
});
|
|
5832
|
+
} else if (filenameToMimeType(stripQuery$1(t.path)) !== "text/vtt") {
|
|
5833
|
+
errors.push({
|
|
5834
|
+
message: "".concat(at, " must be a WebVTT (.vtt) file. Got: ").concat(t.path),
|
|
5835
|
+
value: src
|
|
5836
|
+
});
|
|
5837
|
+
}
|
|
5838
|
+
if (typeof t.srclang !== "string" || t.srclang.trim() === "") {
|
|
5839
|
+
errors.push({
|
|
5840
|
+
message: "".concat(at, " needs a language ('srclang'), e.g. \"en\"."),
|
|
5841
|
+
value: src
|
|
5842
|
+
});
|
|
5843
|
+
}
|
|
5844
|
+
if (t.label !== undefined && typeof t.label !== "string") {
|
|
5845
|
+
errors.push({
|
|
5846
|
+
message: "".concat(at, ": 'label' must be a string."),
|
|
5847
|
+
value: src
|
|
5848
|
+
});
|
|
5849
|
+
}
|
|
5850
|
+
if (t.kind !== undefined && (typeof t.kind !== "string" || !CAPTION_KINDS.includes(t.kind))) {
|
|
5851
|
+
errors.push({
|
|
5852
|
+
message: "".concat(at, ": 'kind' must be \"subtitles\" or \"captions\"."),
|
|
5853
|
+
value: src
|
|
5854
|
+
});
|
|
5855
|
+
}
|
|
5856
|
+
if (t["default"] !== undefined && typeof t["default"] !== "boolean") {
|
|
5857
|
+
errors.push({
|
|
5858
|
+
message: "".concat(at, ": 'default' must be true or false."),
|
|
5859
|
+
value: src
|
|
5860
|
+
});
|
|
5861
|
+
}
|
|
5862
|
+
if (t["default"] === true) {
|
|
5863
|
+
defaults++;
|
|
5864
|
+
}
|
|
5865
|
+
if (typeof t.srclang === "string") {
|
|
5866
|
+
var _t$kind;
|
|
5867
|
+
var key = "".concat((_t$kind = t.kind) !== null && _t$kind !== void 0 ? _t$kind : "subtitles", ":").concat(t.srclang);
|
|
5868
|
+
if (seen.has(key)) {
|
|
5869
|
+
errors.push({
|
|
5870
|
+
message: "".concat(at, " repeats the language '").concat(t.srclang, "'."),
|
|
5871
|
+
value: src
|
|
5872
|
+
});
|
|
5873
|
+
}
|
|
5874
|
+
seen.add(key);
|
|
5875
|
+
}
|
|
5876
|
+
});
|
|
5877
|
+
if (defaults > 1) {
|
|
5878
|
+
errors.push({
|
|
5879
|
+
message: "At most one caption track can be the default. ".concat(defaults, " are."),
|
|
5880
|
+
value: src
|
|
5881
|
+
});
|
|
5882
|
+
}
|
|
5883
|
+
return errors;
|
|
5884
|
+
}
|
|
5885
|
+
|
|
5886
|
+
function isObject(value) {
|
|
5887
|
+
return _typeof(value) === "object" && value !== null && !Array.isArray(value);
|
|
5888
|
+
}
|
|
5889
|
+
|
|
5890
|
+
/** What a media collection (`s.imageset`, `s.fileset`, `s.videoset`) holds. */
|
|
5891
|
+
|
|
5892
|
+
/**
|
|
5893
|
+
* The fix code a media collection of `type` reports for `check`.
|
|
5894
|
+
*
|
|
5895
|
+
* One function rather than a ternary at each site: there were two kinds of
|
|
5896
|
+
* collection when every site was written as `type === "images" ? … : …`, and
|
|
5897
|
+
* a third kind silently took the files branch.
|
|
5898
|
+
*/
|
|
5899
|
+
function mediaCollectionFix(type, check) {
|
|
5900
|
+
return "".concat(type, ":").concat(check);
|
|
5901
|
+
}
|
|
5902
|
+
|
|
5903
|
+
/** The singular a message uses for one entry of a collection of `type`. */
|
|
5904
|
+
var MEDIA_ENTRY_LABEL = {
|
|
5905
|
+
files: "file",
|
|
5906
|
+
images: "image",
|
|
5907
|
+
videos: "video"
|
|
5908
|
+
};
|
|
5909
|
+
|
|
5472
5910
|
/**
|
|
5473
5911
|
* `.render(...)` is for records whose entries the generic record editor draws.
|
|
5474
5912
|
* A router's entries are pages and a gallery's are media, and both have UIs of
|
|
@@ -5660,7 +6098,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5660
6098
|
_iterator.f();
|
|
5661
6099
|
}
|
|
5662
6100
|
if (this.mediaOptions) {
|
|
5663
|
-
var checkFix = this.mediaOptions.type
|
|
6101
|
+
var checkFix = mediaCollectionFix(this.mediaOptions.type, "check-unique-folder");
|
|
5664
6102
|
var uniqueCheckError = {
|
|
5665
6103
|
message: "Gallery directory '".concat(this.mediaOptions.dir, "' must be unique across all galleries"),
|
|
5666
6104
|
value: {
|
|
@@ -5678,7 +6116,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5678
6116
|
} else {
|
|
5679
6117
|
error = _defineProperty({}, path, [uniqueCheckError]);
|
|
5680
6118
|
}
|
|
5681
|
-
var allFilesCheckFix = this.mediaOptions.type
|
|
6119
|
+
var allFilesCheckFix = mediaCollectionFix(this.mediaOptions.type, "check-all-files");
|
|
5682
6120
|
var allFilesCheckError = {
|
|
5683
6121
|
message: "Directory '".concat(this.mediaOptions.dir, "' may have files not tracked by this gallery"),
|
|
5684
6122
|
value: {
|
|
@@ -5732,7 +6170,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5732
6170
|
_this2.markKeyErrorsAtPath(keyErr, subPath);
|
|
5733
6171
|
}
|
|
5734
6172
|
error = _this2.mergeValidationErrors(error, keyErr);
|
|
5735
|
-
var entryErr = _this2.validateMediaEntry(subPath, elem);
|
|
6173
|
+
var entryErr = _this2.validateMediaEntry(subPath, key, elem);
|
|
5736
6174
|
if (entryErr) {
|
|
5737
6175
|
_this2.markKeyErrorsAtPath(entryErr, subPath);
|
|
5738
6176
|
}
|
|
@@ -5846,8 +6284,8 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5846
6284
|
dir = _this$mediaOptions.dir,
|
|
5847
6285
|
isRemote = _this$mediaOptions.remote,
|
|
5848
6286
|
type = _this$mediaOptions.type;
|
|
5849
|
-
var mediaLabel = type
|
|
5850
|
-
var checkRemoteFix = type
|
|
6287
|
+
var mediaLabel = type;
|
|
6288
|
+
var checkRemoteFix = mediaCollectionFix(type, "check-remote");
|
|
5851
6289
|
var isRemoteUrl = this.isRemoteUrl(key);
|
|
5852
6290
|
var isLocalPath = key === dir || key.startsWith(dir + "/");
|
|
5853
6291
|
if (isRemote) {
|
|
@@ -5880,9 +6318,9 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5880
6318
|
}]);
|
|
5881
6319
|
}
|
|
5882
6320
|
// Local path in a remote gallery: needs to be uploaded to remote.
|
|
5883
|
-
var uploadRemoteFix = type
|
|
6321
|
+
var uploadRemoteFix = mediaCollectionFix(type, "upload-remote");
|
|
5884
6322
|
return _defineProperty({}, path, [{
|
|
5885
|
-
message: "Expected a remote ".concat(type
|
|
6323
|
+
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),
|
|
5886
6324
|
value: key,
|
|
5887
6325
|
fixes: [uploadRemoteFix]
|
|
5888
6326
|
}]);
|
|
@@ -5906,7 +6344,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5906
6344
|
}
|
|
5907
6345
|
}, {
|
|
5908
6346
|
key: "validateMediaEntry",
|
|
5909
|
-
value: function validateMediaEntry(path, entry) {
|
|
6347
|
+
value: function validateMediaEntry(path, key, entry) {
|
|
5910
6348
|
if (!this.mediaOptions) {
|
|
5911
6349
|
return false;
|
|
5912
6350
|
}
|
|
@@ -5922,6 +6360,40 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5922
6360
|
}
|
|
5923
6361
|
var entryObj = entry;
|
|
5924
6362
|
var errors = [];
|
|
6363
|
+
if (type === "videos") {
|
|
6364
|
+
// What is read from the bytes. Missing is a fix (the CLI reads them,
|
|
6365
|
+
// from disk or — for a remote entry — over HTTP with Range requests);
|
|
6366
|
+
// present and wrong is an error, because a fix that overwrote an
|
|
6367
|
+
// authored number would be guessing which of the two was right.
|
|
6368
|
+
var missing = ["mimeType", "width", "height", "duration"].filter(function (k) {
|
|
6369
|
+
return entryObj[k] === undefined;
|
|
6370
|
+
});
|
|
6371
|
+
if (missing.length > 0) {
|
|
6372
|
+
return _defineProperty({}, path, [{
|
|
6373
|
+
message: "Video metadata is missing: ".concat(missing.join(", "), "."),
|
|
6374
|
+
value: entry,
|
|
6375
|
+
fixes: ["videos:add-metadata"]
|
|
6376
|
+
}]);
|
|
6377
|
+
}
|
|
6378
|
+
var _iterator3 = _createForOfIteratorHelper(["width", "height", "duration"]),
|
|
6379
|
+
_step3;
|
|
6380
|
+
try {
|
|
6381
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
6382
|
+
var k = _step3.value;
|
|
6383
|
+
var value = entryObj[k];
|
|
6384
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
6385
|
+
errors.push({
|
|
6386
|
+
message: "Expected '".concat(k, "' to be a positive number, got '").concat(JSON.stringify(value), "'"),
|
|
6387
|
+
value: entry
|
|
6388
|
+
});
|
|
6389
|
+
}
|
|
6390
|
+
}
|
|
6391
|
+
} catch (err) {
|
|
6392
|
+
_iterator3.e(err);
|
|
6393
|
+
} finally {
|
|
6394
|
+
_iterator3.f();
|
|
6395
|
+
}
|
|
6396
|
+
}
|
|
5925
6397
|
if (type === "images") {
|
|
5926
6398
|
// Validate width
|
|
5927
6399
|
if (typeof entryObj.width !== "number" || entryObj.width <= 0) {
|
|
@@ -5946,6 +6418,15 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5946
6418
|
message: "Expected 'mimeType' to be a string, got '".concat(_typeof(entryObj.mimeType), "'"),
|
|
5947
6419
|
value: entry
|
|
5948
6420
|
});
|
|
6421
|
+
} else if (type === "videos" && entryObj.mimeType === HLS_MIME_TYPE) {
|
|
6422
|
+
// A stream is what the Studio made of an upload that WAS accepted, so
|
|
6423
|
+
// `accept` (which is about what may be picked) is not asked about it.
|
|
6424
|
+
if (!key.split("?")[0].toLowerCase().endsWith(".m3u8")) {
|
|
6425
|
+
errors.push({
|
|
6426
|
+
message: "An HLS video must be keyed by its master playlist (.m3u8). Got: ".concat(key),
|
|
6427
|
+
value: entry
|
|
6428
|
+
});
|
|
6429
|
+
}
|
|
5949
6430
|
} else {
|
|
5950
6431
|
var mimeTypeError = this.validateMediaMimeType(entryObj.mimeType, accept);
|
|
5951
6432
|
if (mimeTypeError) {
|
|
@@ -5955,6 +6436,26 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5955
6436
|
});
|
|
5956
6437
|
}
|
|
5957
6438
|
}
|
|
6439
|
+
if (type === "videos") {
|
|
6440
|
+
// The defaults every field picked from the set starts from, checked as
|
|
6441
|
+
// a field's own would be: they are the same choices, made once.
|
|
6442
|
+
var duration = typeof entryObj.duration === "number" && entryObj.duration > 0 ? entryObj.duration : undefined;
|
|
6443
|
+
errors.push.apply(errors, _toConsumableArray(validateTimes(entryObj, duration)).concat(_toConsumableArray(validateHotspot(entryObj)), _toConsumableArray(validatePoster(entryObj)), _toConsumableArray(validateCaptions(entryObj))));
|
|
6444
|
+
var misplaced = this.misplacedEntryFiles(key, entryObj);
|
|
6445
|
+
if (misplaced.length > 0) {
|
|
6446
|
+
var these = misplaced.length === 1 ? "this file is" : "".concat(misplaced.length, " files are");
|
|
6447
|
+
errors.push(this.mediaOptions.remote ? {
|
|
6448
|
+
message: "Expected the entry's files on Val Remote, but ".concat(these, " stored locally: ").concat(misplaced.join(", ")),
|
|
6449
|
+
// The key, as a local key's upload error carries: the fix
|
|
6450
|
+
// rewrites the entry under it.
|
|
6451
|
+
value: key,
|
|
6452
|
+
fixes: ["videos:upload-remote"]
|
|
6453
|
+
} : {
|
|
6454
|
+
message: "Expected the entry's files under ".concat(this.mediaOptions.dir, ", but ").concat(these, " remote: ").concat(misplaced.join(", ")),
|
|
6455
|
+
value: entry
|
|
6456
|
+
});
|
|
6457
|
+
}
|
|
6458
|
+
}
|
|
5958
6459
|
if (type === "images") {
|
|
5959
6460
|
// Validate hotspot if present
|
|
5960
6461
|
if (entryObj.hotspot !== undefined) {
|
|
@@ -5966,7 +6467,8 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5966
6467
|
});
|
|
5967
6468
|
}
|
|
5968
6469
|
}
|
|
5969
|
-
|
|
6470
|
+
}
|
|
6471
|
+
if (type === "images" || type === "videos") {
|
|
5970
6472
|
// Validate alt using the alt schema
|
|
5971
6473
|
var altPath = createValPathOfItem(path, "alt");
|
|
5972
6474
|
if (altPath && altSchema) {
|
|
@@ -5981,16 +6483,59 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5981
6483
|
}
|
|
5982
6484
|
return false;
|
|
5983
6485
|
}
|
|
6486
|
+
|
|
6487
|
+
/**
|
|
6488
|
+
* The poster and caption files of a set's entry that are not where the set
|
|
6489
|
+
* keeps its files. Asked only once the key itself is in place: a local key
|
|
6490
|
+
* in a remote set is reported (and uploaded) as the entry, files and all,
|
|
6491
|
+
* and a second error for its poster would be the same one twice.
|
|
6492
|
+
*/
|
|
5984
6493
|
}, {
|
|
5985
|
-
key: "
|
|
5986
|
-
value: function
|
|
5987
|
-
|
|
5988
|
-
|
|
6494
|
+
key: "misplacedEntryFiles",
|
|
6495
|
+
value: function misplacedEntryFiles(key, entry) {
|
|
6496
|
+
var _this3 = this;
|
|
6497
|
+
if (!this.mediaOptions) {
|
|
6498
|
+
return [];
|
|
5989
6499
|
}
|
|
5990
|
-
|
|
5991
|
-
|
|
6500
|
+
var remote = this.mediaOptions.remote;
|
|
6501
|
+
if (this.isRemoteUrl(key) !== remote) {
|
|
6502
|
+
return [];
|
|
5992
6503
|
}
|
|
5993
|
-
|
|
6504
|
+
var files = [];
|
|
6505
|
+
var poster = entry.poster;
|
|
6506
|
+
if (isObject(poster) && typeof poster.path === "string") {
|
|
6507
|
+
files.push(poster.path);
|
|
6508
|
+
}
|
|
6509
|
+
if (Array.isArray(entry.captions)) {
|
|
6510
|
+
var _iterator4 = _createForOfIteratorHelper(entry.captions),
|
|
6511
|
+
_step4;
|
|
6512
|
+
try {
|
|
6513
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
6514
|
+
var track = _step4.value;
|
|
6515
|
+
if (isObject(track) && typeof track.path === "string") {
|
|
6516
|
+
files.push(track.path);
|
|
6517
|
+
}
|
|
6518
|
+
}
|
|
6519
|
+
} catch (err) {
|
|
6520
|
+
_iterator4.e(err);
|
|
6521
|
+
} finally {
|
|
6522
|
+
_iterator4.f();
|
|
6523
|
+
}
|
|
6524
|
+
}
|
|
6525
|
+
return files.filter(function (file) {
|
|
6526
|
+
return _this3.isRemoteUrl(file) !== remote;
|
|
6527
|
+
});
|
|
6528
|
+
}
|
|
6529
|
+
}, {
|
|
6530
|
+
key: "validateMediaMimeType",
|
|
6531
|
+
value: function validateMediaMimeType(mimeType, accept) {
|
|
6532
|
+
if (!mimeType.includes("/")) {
|
|
6533
|
+
return "Invalid mime type format. Got: '".concat(mimeType, "'");
|
|
6534
|
+
}
|
|
6535
|
+
if (!mimeTypeMatchesAccept(mimeType, accept)) {
|
|
6536
|
+
return "Mime type mismatch. Found '".concat(mimeType, "' but schema accepts '").concat(accept, "'");
|
|
6537
|
+
}
|
|
6538
|
+
return null;
|
|
5994
6539
|
}
|
|
5995
6540
|
}, {
|
|
5996
6541
|
key: "executeAssert",
|
|
@@ -6344,6 +6889,9 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
6344
6889
|
if (this.mediaOptions.encode !== undefined) {
|
|
6345
6890
|
result.encode = this.mediaOptions.encode;
|
|
6346
6891
|
}
|
|
6892
|
+
if (this.mediaOptions.stream !== undefined) {
|
|
6893
|
+
result.stream = this.mediaOptions.stream;
|
|
6894
|
+
}
|
|
6347
6895
|
if (this.mediaOptions.altSchema) {
|
|
6348
6896
|
result.alt = this.mediaOptions.altSchema["executeSerialize"]();
|
|
6349
6897
|
}
|
|
@@ -10340,56 +10888,521 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
|
|
|
10340
10888
|
}]));
|
|
10341
10889
|
}
|
|
10342
10890
|
}
|
|
10343
|
-
var fileMimeType = Internal.filenameToMimeType(src.path);
|
|
10344
|
-
if (!fileMimeType) {
|
|
10345
|
-
return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
|
|
10346
|
-
message: "Could not determine mime type from file extension. Got: ".concat(src.path),
|
|
10347
|
-
value: src
|
|
10348
|
-
}]));
|
|
10891
|
+
var fileMimeType = Internal.filenameToMimeType(src.path);
|
|
10892
|
+
if (!fileMimeType) {
|
|
10893
|
+
return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
|
|
10894
|
+
message: "Could not determine mime type from file extension. Got: ".concat(src.path),
|
|
10895
|
+
value: src
|
|
10896
|
+
}]));
|
|
10897
|
+
}
|
|
10898
|
+
|
|
10899
|
+
// Guarded on `mimeType` being set, as `ImageSchema` guards the same check.
|
|
10900
|
+
// Without it, an absent mimeType reported "Mime type and file extension not
|
|
10901
|
+
// matching. Mime type is 'undefined'" -- with no fix attached, so no quick
|
|
10902
|
+
// fix was offered -- and the `file:add-metadata` branch below could never be
|
|
10903
|
+
// reached for any file whose extension is recognized, which is all of them
|
|
10904
|
+
// that get this far.
|
|
10905
|
+
if (mimeType && fileMimeType !== mimeType) {
|
|
10906
|
+
return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
|
|
10907
|
+
message: "Mime type and file extension not matching. Mime type is '".concat(mimeType, "' but file extension is '").concat(fileMimeType, "'"),
|
|
10908
|
+
value: src
|
|
10909
|
+
}]));
|
|
10910
|
+
}
|
|
10911
|
+
|
|
10912
|
+
// The mime type read so far came from the filename. Whether it matches the
|
|
10913
|
+
// bytes can only be answered by reading the file, which this package
|
|
10914
|
+
// deliberately cannot do — so it is always handed on as a fix.
|
|
10915
|
+
if (mimeType !== undefined) {
|
|
10916
|
+
return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
|
|
10917
|
+
message: "File mimeType has not been checked against the file.",
|
|
10918
|
+
value: src,
|
|
10919
|
+
fixes: ["file:check-metadata"]
|
|
10920
|
+
}]));
|
|
10921
|
+
}
|
|
10922
|
+
return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
|
|
10923
|
+
message: "File metadata is missing: mimeType.",
|
|
10924
|
+
value: src,
|
|
10925
|
+
fixes: ["file:add-metadata"]
|
|
10926
|
+
}]));
|
|
10927
|
+
}
|
|
10928
|
+
|
|
10929
|
+
/**
|
|
10930
|
+
* The entries of the gallery this field points at, or null when it is a
|
|
10931
|
+
* standalone field.
|
|
10932
|
+
*/
|
|
10933
|
+
}, {
|
|
10934
|
+
key: "galleryEntries",
|
|
10935
|
+
value: function galleryEntries() {
|
|
10936
|
+
var modulePaths = Object.keys(this.moduleMetadata);
|
|
10937
|
+
if (modulePaths.length === 0) {
|
|
10938
|
+
return null;
|
|
10939
|
+
}
|
|
10940
|
+
return this.moduleMetadata[modulePaths[0]];
|
|
10941
|
+
}
|
|
10942
|
+
}, {
|
|
10943
|
+
key: "executeAssert",
|
|
10944
|
+
value: function executeAssert(path, src) {
|
|
10945
|
+
if (this.opt && src === null) {
|
|
10946
|
+
return {
|
|
10947
|
+
success: true,
|
|
10948
|
+
data: src
|
|
10949
|
+
};
|
|
10950
|
+
}
|
|
10951
|
+
if (src === null) {
|
|
10952
|
+
return {
|
|
10953
|
+
success: false,
|
|
10954
|
+
errors: _defineProperty({}, path, [{
|
|
10955
|
+
message: "Expected 'object', got 'null'",
|
|
10956
|
+
typeError: true
|
|
10957
|
+
}])
|
|
10958
|
+
};
|
|
10959
|
+
}
|
|
10960
|
+
if (_typeof(src) !== "object") {
|
|
10961
|
+
return {
|
|
10962
|
+
success: false,
|
|
10963
|
+
errors: _defineProperty({}, path, [{
|
|
10964
|
+
message: "Expected object, got '".concat(_typeof(src), "'"),
|
|
10965
|
+
typeError: true
|
|
10966
|
+
}])
|
|
10967
|
+
};
|
|
10968
|
+
}
|
|
10969
|
+
if (!("path" in src) || typeof src.path !== "string") {
|
|
10970
|
+
return {
|
|
10971
|
+
success: false,
|
|
10972
|
+
errors: _defineProperty({}, path, [{
|
|
10973
|
+
message: "A file must be an object with a 'path' (error type: missing_path)",
|
|
10974
|
+
typeError: true
|
|
10975
|
+
}])
|
|
10976
|
+
};
|
|
10977
|
+
}
|
|
10978
|
+
return {
|
|
10979
|
+
success: true,
|
|
10980
|
+
data: src
|
|
10981
|
+
};
|
|
10982
|
+
}
|
|
10983
|
+
}, {
|
|
10984
|
+
key: "nullable",
|
|
10985
|
+
value: function nullable() {
|
|
10986
|
+
return new FileSchema(this.options, true, this.isRemote, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, this.isHidden, this.description, this.previewInput);
|
|
10987
|
+
}
|
|
10988
|
+
}, {
|
|
10989
|
+
key: "readonly",
|
|
10990
|
+
value: function readonly() {
|
|
10991
|
+
var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
10992
|
+
return new FileSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, isReadonly, this.isHidden, this.description, this.previewInput);
|
|
10993
|
+
}
|
|
10994
|
+
}, {
|
|
10995
|
+
key: "hidden",
|
|
10996
|
+
value: function hidden() {
|
|
10997
|
+
var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
10998
|
+
return new FileSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, isHidden, this.description, this.previewInput);
|
|
10999
|
+
}
|
|
11000
|
+
}, {
|
|
11001
|
+
key: "executeCustomValidateAt",
|
|
11002
|
+
value: function executeCustomValidateAt(path, src) {
|
|
11003
|
+
return this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
|
|
11004
|
+
path: path
|
|
11005
|
+
});
|
|
11006
|
+
}
|
|
11007
|
+
|
|
11008
|
+
/**
|
|
11009
|
+
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
11010
|
+
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
11011
|
+
* itself is edited (that is `render`). See `preview.ts`.
|
|
11012
|
+
*
|
|
11013
|
+
* @example
|
|
11014
|
+
* const schema = s.array(
|
|
11015
|
+
* s.file().preview(({ val }) => ({ title: val.path })),
|
|
11016
|
+
* );
|
|
11017
|
+
* export default c.define("/example.val.ts", schema, [
|
|
11018
|
+
* { path: "/public/val/example.pdf", mimeType: "application/pdf" },
|
|
11019
|
+
* ]);
|
|
11020
|
+
*/
|
|
11021
|
+
}, {
|
|
11022
|
+
key: "preview",
|
|
11023
|
+
value: function preview(select) {
|
|
11024
|
+
return new FileSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, this.isHidden, this.description, select);
|
|
11025
|
+
}
|
|
11026
|
+
}, {
|
|
11027
|
+
key: "executePreviewItem",
|
|
11028
|
+
value: function executePreviewItem(src) {
|
|
11029
|
+
if (this.previewInput === null) {
|
|
11030
|
+
return null;
|
|
11031
|
+
}
|
|
11032
|
+
return this.previewInput({
|
|
11033
|
+
val: src
|
|
11034
|
+
});
|
|
11035
|
+
}
|
|
11036
|
+
}, {
|
|
11037
|
+
key: "declaresItemPreview",
|
|
11038
|
+
value: function declaresItemPreview() {
|
|
11039
|
+
return this.previewInput !== null;
|
|
11040
|
+
}
|
|
11041
|
+
}, {
|
|
11042
|
+
key: "executeSerialize",
|
|
11043
|
+
value: function executeSerialize() {
|
|
11044
|
+
var _this$customValidateF;
|
|
11045
|
+
var modulePaths = this.moduleMetadata ? Object.keys(this.moduleMetadata) : [];
|
|
11046
|
+
return {
|
|
11047
|
+
type: "file",
|
|
11048
|
+
preview: this.previewInput ? true : undefined,
|
|
11049
|
+
options: this.options,
|
|
11050
|
+
opt: this.opt,
|
|
11051
|
+
remote: this.isRemote,
|
|
11052
|
+
customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
|
|
11053
|
+
referencedModule: modulePaths.length > 0 ? modulePaths[0] : undefined,
|
|
11054
|
+
readonly: this.isReadonly,
|
|
11055
|
+
hidden: this.isHidden,
|
|
11056
|
+
description: this.description
|
|
11057
|
+
};
|
|
11058
|
+
}
|
|
11059
|
+
}]);
|
|
11060
|
+
}(Schema);
|
|
11061
|
+
|
|
11062
|
+
/**
|
|
11063
|
+
* A file picked from a gallery. Its mime type lives in the gallery, so the
|
|
11064
|
+
* field carries only the path.
|
|
11065
|
+
*/
|
|
11066
|
+
|
|
11067
|
+
/** A file of its own, carrying its own mime type. */
|
|
11068
|
+
|
|
11069
|
+
function file(options) {
|
|
11070
|
+
return fileOf(false, options);
|
|
11071
|
+
}
|
|
11072
|
+
|
|
11073
|
+
/**
|
|
11074
|
+
* `s.file()` for a project whose media is all remote (`files.remote` in
|
|
11075
|
+
* `val.config.ts`): the same schema, with `.remote()` already applied. See
|
|
11076
|
+
* `initSchema`.
|
|
11077
|
+
*/
|
|
11078
|
+
|
|
11079
|
+
function remoteFile(options) {
|
|
11080
|
+
return fileOf(true, options);
|
|
11081
|
+
}
|
|
11082
|
+
function fileOf(remote, options) {
|
|
11083
|
+
var isModule = !!options && !!Internal.getValPath(options);
|
|
11084
|
+
if (isModule) {
|
|
11085
|
+
var allModules = {};
|
|
11086
|
+
for (var _i = 0, _arr = [options]; _i < _arr.length; _i++) {
|
|
11087
|
+
var valModule = _arr[_i];
|
|
11088
|
+
var modulePath = getValPath(valModule);
|
|
11089
|
+
if (modulePath === undefined) {
|
|
11090
|
+
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.");
|
|
11091
|
+
}
|
|
11092
|
+
allModules[modulePath] = getSource(valModule);
|
|
11093
|
+
}
|
|
11094
|
+
return new FileSchema({}, false, remote, [], allModules);
|
|
11095
|
+
}
|
|
11096
|
+
return new FileSchema(options, false, remote);
|
|
11097
|
+
}
|
|
11098
|
+
|
|
11099
|
+
/**
|
|
11100
|
+
* Turn an upload into an HLS stream, in the browser, before it is uploaded.
|
|
11101
|
+
*
|
|
11102
|
+
* The Studio transcodes the picked file with WebCodecs into one rendition per
|
|
11103
|
+
* entry of `renditions` (never upscaled: a 720p upload gets no 1080p
|
|
11104
|
+
* rendition), segments each into CMAF and writes the playlists. What is stored
|
|
11105
|
+
* is a directory beside the other uploads; the field's `path` is its master
|
|
11106
|
+
* playlist. See `architecture/media.md`.
|
|
11107
|
+
*
|
|
11108
|
+
* `type` is required for the same reason it is on `ImageEncodeOptions`: a
|
|
11109
|
+
* second kind of stream would then be additive.
|
|
11110
|
+
*/
|
|
11111
|
+
|
|
11112
|
+
/** `false` (or absent) uploads the file as it was picked. */
|
|
11113
|
+
|
|
11114
|
+
/**
|
|
11115
|
+
* What a SET-BACKED field (`s.video(videosVal)`) may say for itself.
|
|
11116
|
+
*
|
|
11117
|
+
* Not `VideoOptions`: `dir` and `accept` belong to the set. `stream` is the
|
|
11118
|
+
* exception, as `encode` is for an image: it is about what happens to an
|
|
11119
|
+
* upload on its way in, so a field that wants the file as it was picked,
|
|
11120
|
+
* where its set streams, has to be able to say `stream: false`.
|
|
11121
|
+
*/
|
|
11122
|
+
|
|
11123
|
+
/**
|
|
11124
|
+
* The set a field picks from: its entries as they were when the module was
|
|
11125
|
+
* evaluated (the published set — see `GalleryImageSource` for why that is
|
|
11126
|
+
* enough), and whether it stores its videos on Val Remote.
|
|
11127
|
+
*/
|
|
11128
|
+
|
|
11129
|
+
var DEFAULT_VIDEO_ACCEPT = "video/*";
|
|
11130
|
+
var DEFAULT_VIDEO_RENDITIONS = [1080, 720, 480];
|
|
11131
|
+
var DEFAULT_VIDEO_SEGMENT_DURATION = 6;
|
|
11132
|
+
var VideoSchema = /*#__PURE__*/function (_Schema) {
|
|
11133
|
+
function VideoSchema(options) {
|
|
11134
|
+
var _this;
|
|
11135
|
+
var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
11136
|
+
var isRemote = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
11137
|
+
var customValidateFunctions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
|
|
11138
|
+
var isReadonly = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
11139
|
+
var isHidden = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
|
|
11140
|
+
var description = arguments.length > 6 ? arguments[6] : undefined;
|
|
11141
|
+
var renderInput = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null;
|
|
11142
|
+
var previewInput = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : null;
|
|
11143
|
+
var gallery = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : null;
|
|
11144
|
+
_classCallCheck(this, VideoSchema);
|
|
11145
|
+
_this = _callSuper(this, VideoSchema);
|
|
11146
|
+
_this.options = options;
|
|
11147
|
+
_this.opt = opt;
|
|
11148
|
+
_this.isRemote = isRemote;
|
|
11149
|
+
_this.customValidateFunctions = customValidateFunctions;
|
|
11150
|
+
_this.isReadonly = isReadonly;
|
|
11151
|
+
_this.isHidden = isHidden;
|
|
11152
|
+
_this.description = description;
|
|
11153
|
+
_this.renderInput = renderInput;
|
|
11154
|
+
_this.previewInput = previewInput;
|
|
11155
|
+
_this.gallery = gallery;
|
|
11156
|
+
return _this;
|
|
11157
|
+
}
|
|
11158
|
+
|
|
11159
|
+
/**
|
|
11160
|
+
* Describe this field.
|
|
11161
|
+
*
|
|
11162
|
+
* The description is INPUT HELP: it is shown where this field's value is
|
|
11163
|
+
* entered — beside its input in the Val editor, and for a record's key
|
|
11164
|
+
* schema in every form that asks for a key — so it is where you say what an
|
|
11165
|
+
* editor needs to know to fill it in RIGHT, which the field name cannot
|
|
11166
|
+
* carry. It is not a name for the value: that is `.preview(...)`, and it is
|
|
11167
|
+
* read somewhere else. The description also travels in the serialized
|
|
11168
|
+
* schema, which is what the AI assistant and the MCP tools read.
|
|
11169
|
+
*
|
|
11170
|
+
* Pass `null` to clear a description set earlier.
|
|
11171
|
+
*
|
|
11172
|
+
* @example
|
|
11173
|
+
* const schema = s.video().describe("Plays muted behind the headline");
|
|
11174
|
+
* export default c.define("/example.val.ts", schema, {
|
|
11175
|
+
* path: "/public/val/example.mp4",
|
|
11176
|
+
* mimeType: "video/mp4",
|
|
11177
|
+
* });
|
|
11178
|
+
*/
|
|
11179
|
+
_inherits(VideoSchema, _Schema);
|
|
11180
|
+
return _createClass(VideoSchema, [{
|
|
11181
|
+
key: "describe",
|
|
11182
|
+
value: function describe(description) {
|
|
11183
|
+
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);
|
|
11184
|
+
}
|
|
11185
|
+
|
|
11186
|
+
/**
|
|
11187
|
+
* Store the video on Val's remote content host instead of in your
|
|
11188
|
+
* repository.
|
|
11189
|
+
*
|
|
11190
|
+
* The bytes still go into the patch store when the video is uploaded — the
|
|
11191
|
+
* push to the remote host happens at publish. What changes is where the
|
|
11192
|
+
* published video lives: `path` (and the poster's, and each caption track's)
|
|
11193
|
+
* becomes a remote URL rather than a path under `/public`, so the repository
|
|
11194
|
+
* does not grow with every upload. Upload remote videos in the Studio.
|
|
11195
|
+
*
|
|
11196
|
+
* @example
|
|
11197
|
+
* const schema = s.video().remote();
|
|
11198
|
+
* export default c.define("/example.val.ts", schema, {
|
|
11199
|
+
* path: "https://remote.val.build/file/p/my-project/b/01/v/1.0.0/h/8f2a1c/f/3b9d70/p/public/val/example.mp4",
|
|
11200
|
+
* mimeType: "video/mp4",
|
|
11201
|
+
* });
|
|
11202
|
+
*/
|
|
11203
|
+
}, {
|
|
11204
|
+
key: "remote",
|
|
11205
|
+
value: function remote() {
|
|
11206
|
+
return new VideoSchema(this.options, this.opt, true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput, this.gallery);
|
|
11207
|
+
}
|
|
11208
|
+
|
|
11209
|
+
/**
|
|
11210
|
+
* Add a custom validation rule to this field.
|
|
11211
|
+
*
|
|
11212
|
+
* The function is called with the field's value and returns `false` when the
|
|
11213
|
+
* value is fine, or a STRING with the message to show when it is not. Call it
|
|
11214
|
+
* more than once to add more rules — they all run, and every message is
|
|
11215
|
+
* reported.
|
|
11216
|
+
*
|
|
11217
|
+
* Write the check as a ternary, not as `ok || "message"`: that returns `true`
|
|
11218
|
+
* when the value is fine, and `true` is not one of the two answers.
|
|
11219
|
+
*
|
|
11220
|
+
* Validation runs in the Studio as you type, in `npx val validate` and
|
|
11221
|
+
* before a publish.
|
|
11222
|
+
*
|
|
11223
|
+
* The second argument carries the `path` of the field being validated, for
|
|
11224
|
+
* when the message needs to say where the problem is.
|
|
11225
|
+
*
|
|
11226
|
+
* @example
|
|
11227
|
+
* const schema = s.video().validate((val) =>
|
|
11228
|
+
* (val.duration ?? 0) <= 30 ? false : "Keep it under 30 seconds",
|
|
11229
|
+
* );
|
|
11230
|
+
* export default c.define("/example.val.ts", schema, {
|
|
11231
|
+
* path: "/public/val/example.mp4",
|
|
11232
|
+
* mimeType: "video/mp4",
|
|
11233
|
+
* duration: 12,
|
|
11234
|
+
* });
|
|
11235
|
+
*/
|
|
11236
|
+
}, {
|
|
11237
|
+
key: "validate",
|
|
11238
|
+
value: function validate(validationFunction) {
|
|
11239
|
+
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);
|
|
11240
|
+
}
|
|
11241
|
+
}, {
|
|
11242
|
+
key: "executeValidate",
|
|
11243
|
+
value: function executeValidate(path, src) {
|
|
11244
|
+
var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
|
|
11245
|
+
path: path
|
|
11246
|
+
});
|
|
11247
|
+
var report = function report(errors) {
|
|
11248
|
+
var all = [].concat(_toConsumableArray(customValidationErrors), _toConsumableArray(errors));
|
|
11249
|
+
return all.length > 0 ? _defineProperty({}, path, all) : false;
|
|
11250
|
+
};
|
|
11251
|
+
if (src === null || src === undefined) {
|
|
11252
|
+
if (this.opt) {
|
|
11253
|
+
return report([]);
|
|
11254
|
+
}
|
|
11255
|
+
return report([{
|
|
11256
|
+
message: "Non-optional video was null or undefined.",
|
|
11257
|
+
value: src
|
|
11258
|
+
}]);
|
|
11259
|
+
}
|
|
11260
|
+
if (_typeof(src) !== "object" || typeof src.path !== "string") {
|
|
11261
|
+
return report([{
|
|
11262
|
+
message: "A video must be an object with a 'path' string.",
|
|
11263
|
+
value: src
|
|
11264
|
+
}]);
|
|
11265
|
+
}
|
|
11266
|
+
if (this.gallery) {
|
|
11267
|
+
return report(this.validateFromGallery(src, this.gallery));
|
|
11268
|
+
}
|
|
11269
|
+
return report(this.validateOwn(src));
|
|
11270
|
+
}
|
|
11271
|
+
|
|
11272
|
+
/**
|
|
11273
|
+
* A set-backed field: the file and what was read from it are the set's,
|
|
11274
|
+
* so the field is checked for what is its own, and for pointing at an
|
|
11275
|
+
* entry the set has.
|
|
11276
|
+
*/
|
|
11277
|
+
}, {
|
|
11278
|
+
key: "validateFromGallery",
|
|
11279
|
+
value: function validateFromGallery(src, gallery) {
|
|
11280
|
+
var own = ownMetadataOf(src);
|
|
11281
|
+
var repeated = ["mimeType", "width", "height", "duration"].filter(function (key) {
|
|
11282
|
+
return own[key] !== undefined;
|
|
11283
|
+
});
|
|
11284
|
+
if (repeated.length > 0) {
|
|
11285
|
+
return [{
|
|
11286
|
+
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."),
|
|
11287
|
+
value: src
|
|
11288
|
+
}];
|
|
11289
|
+
}
|
|
11290
|
+
var entry = gallery.entries === null ? null : gallery.entries[src.path];
|
|
11291
|
+
if (entry === undefined) {
|
|
11292
|
+
return [{
|
|
11293
|
+
message: "The set does not have a video at '".concat(src.path, "'."),
|
|
11294
|
+
value: src
|
|
11295
|
+
}];
|
|
11296
|
+
}
|
|
11297
|
+
// The poster and the captions are the field's own files, and live where
|
|
11298
|
+
// the set keeps its videos. The video itself is the set's to move.
|
|
11299
|
+
var misplaced = filesOfVideoSource(src).slice(1).filter(function (file) {
|
|
11300
|
+
return isRemoteMediaPath(file) !== gallery.remote;
|
|
11301
|
+
});
|
|
11302
|
+
if (misplaced.length > 0) {
|
|
11303
|
+
return [misplacedError(src, misplaced, gallery.remote)];
|
|
11304
|
+
}
|
|
11305
|
+
var duration = entry !== null && typeof entry.duration === "number" && entry.duration > 0 ? entry.duration : undefined;
|
|
11306
|
+
return [].concat(_toConsumableArray(validateTimes(src, duration)), _toConsumableArray(validateMixedTimes(src, entry)), _toConsumableArray(validateHotspot(src)), _toConsumableArray(validatePoster(src)), _toConsumableArray(validateCaptions(src)));
|
|
11307
|
+
}
|
|
11308
|
+
|
|
11309
|
+
/** A video of its own: it carries the file, and what was read from it. */
|
|
11310
|
+
}, {
|
|
11311
|
+
key: "validateOwn",
|
|
11312
|
+
value: function validateOwn(src) {
|
|
11313
|
+
var _this2 = this;
|
|
11314
|
+
var own = ownMetadataOf(src);
|
|
11315
|
+
// Every file the video names has to be where the schema says, and one fix
|
|
11316
|
+
// moves them all — a video on the content host with its poster still in
|
|
11317
|
+
// the repository is half a migration, not a choice. The error is reported
|
|
11318
|
+
// once for the whole video, never per file.
|
|
11319
|
+
var misplaced = filesOfVideoSource(src).filter(function (file) {
|
|
11320
|
+
return isRemoteMediaPath(file) !== _this2.isRemote;
|
|
11321
|
+
});
|
|
11322
|
+
if (misplaced.length > 0) {
|
|
11323
|
+
return [misplacedError(src, misplaced, this.isRemote)];
|
|
11324
|
+
}
|
|
11325
|
+
var errors = [];
|
|
11326
|
+
var isHls = isHlsVideo({
|
|
11327
|
+
path: src.path,
|
|
11328
|
+
mimeType: stringOrUndefined(own.mimeType)
|
|
11329
|
+
});
|
|
11330
|
+
var extensionMimeType = filenameToMimeType(stripQuery(src.path));
|
|
11331
|
+
if (isHls) {
|
|
11332
|
+
if (!stripQuery(src.path).toLowerCase().endsWith(".m3u8")) {
|
|
11333
|
+
errors.push({
|
|
11334
|
+
message: "An HLS video's path must be its master playlist (.m3u8). Got: ".concat(src.path),
|
|
11335
|
+
value: src
|
|
11336
|
+
});
|
|
11337
|
+
}
|
|
11338
|
+
} else if (!extensionMimeType || !extensionMimeType.startsWith("video/")) {
|
|
11339
|
+
errors.push({
|
|
11340
|
+
message: "Could not tell this is a video from its file extension. Got: ".concat(src.path),
|
|
11341
|
+
value: src
|
|
11342
|
+
});
|
|
11343
|
+
} else if (own.mimeType !== undefined && extensionMimeType !== own.mimeType) {
|
|
11344
|
+
errors.push({
|
|
11345
|
+
message: "Mime type and file extension not matching. Mime type is '".concat(String(own.mimeType), "' but file extension is '").concat(extensionMimeType, "'"),
|
|
11346
|
+
value: src
|
|
11347
|
+
});
|
|
11348
|
+
}
|
|
11349
|
+
if (own.mimeType !== undefined && typeof own.mimeType !== "string") {
|
|
11350
|
+
errors.push({
|
|
11351
|
+
message: "'mimeType' must be a string.",
|
|
11352
|
+
value: src
|
|
11353
|
+
});
|
|
11354
|
+
} else if (own.mimeType !== undefined && !isHls) {
|
|
11355
|
+
var _this$options$accept, _this$options;
|
|
11356
|
+
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;
|
|
11357
|
+
if (!mimeTypeMatchesAccept(own.mimeType, accept)) {
|
|
11358
|
+
errors.push({
|
|
11359
|
+
message: "Mime type mismatch. Found '".concat(own.mimeType, "' but schema accepts '").concat(accept, "'"),
|
|
11360
|
+
value: src
|
|
11361
|
+
});
|
|
11362
|
+
}
|
|
11363
|
+
}
|
|
11364
|
+
var _iterator = _createForOfIteratorHelper(["width", "height", "duration"]),
|
|
11365
|
+
_step;
|
|
11366
|
+
try {
|
|
11367
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
11368
|
+
var key = _step.value;
|
|
11369
|
+
var value = own[key];
|
|
11370
|
+
if (value !== undefined && (typeof value !== "number" || !Number.isFinite(value) || value <= 0)) {
|
|
11371
|
+
errors.push({
|
|
11372
|
+
message: "'".concat(key, "' must be a positive number. Got: ").concat(JSON.stringify(value)),
|
|
11373
|
+
value: src
|
|
11374
|
+
});
|
|
11375
|
+
}
|
|
11376
|
+
}
|
|
11377
|
+
} catch (err) {
|
|
11378
|
+
_iterator.e(err);
|
|
11379
|
+
} finally {
|
|
11380
|
+
_iterator.f();
|
|
10349
11381
|
}
|
|
10350
|
-
|
|
10351
|
-
|
|
10352
|
-
|
|
10353
|
-
|
|
10354
|
-
|
|
10355
|
-
|
|
10356
|
-
|
|
10357
|
-
if (mimeType && fileMimeType !== mimeType) {
|
|
10358
|
-
return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
|
|
10359
|
-
message: "Mime type and file extension not matching. Mime type is '".concat(mimeType, "' but file extension is '").concat(fileMimeType, "'"),
|
|
10360
|
-
value: src
|
|
10361
|
-
}]));
|
|
11382
|
+
var duration = typeof own.duration === "number" && own.duration > 0 ? own.duration : undefined;
|
|
11383
|
+
errors.push.apply(errors, _toConsumableArray(validateTimes(src, duration)));
|
|
11384
|
+
errors.push.apply(errors, _toConsumableArray(validateHotspot(src)));
|
|
11385
|
+
errors.push.apply(errors, _toConsumableArray(validatePoster(src)));
|
|
11386
|
+
errors.push.apply(errors, _toConsumableArray(validateCaptions(src)));
|
|
11387
|
+
if (errors.length > 0) {
|
|
11388
|
+
return errors;
|
|
10362
11389
|
}
|
|
10363
11390
|
|
|
10364
|
-
//
|
|
10365
|
-
// bytes
|
|
10366
|
-
//
|
|
10367
|
-
|
|
10368
|
-
|
|
10369
|
-
|
|
11391
|
+
// Everything authored is fine. What is left is what is read from the
|
|
11392
|
+
// bytes, which this package cannot do — so it is handed on as a fix. The
|
|
11393
|
+
// CLI reads a local file's headers from disk and a remote one's over
|
|
11394
|
+
// HTTP, with Range requests, so neither is downloaded whole.
|
|
11395
|
+
var missing = ["mimeType", "width", "height", "duration"].filter(function (key) {
|
|
11396
|
+
return own[key] === undefined;
|
|
11397
|
+
});
|
|
11398
|
+
if (missing.length > 0) {
|
|
11399
|
+
return [{
|
|
11400
|
+
message: "Video metadata is missing: ".concat(missing.join(", "), "."),
|
|
10370
11401
|
value: src,
|
|
10371
|
-
fixes: ["
|
|
10372
|
-
}]
|
|
10373
|
-
}
|
|
10374
|
-
return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
|
|
10375
|
-
message: "File metadata is missing: mimeType.",
|
|
10376
|
-
value: src,
|
|
10377
|
-
fixes: ["file:add-metadata"]
|
|
10378
|
-
}]));
|
|
10379
|
-
}
|
|
10380
|
-
|
|
10381
|
-
/**
|
|
10382
|
-
* The entries of the gallery this field points at, or null when it is a
|
|
10383
|
-
* standalone field.
|
|
10384
|
-
*/
|
|
10385
|
-
}, {
|
|
10386
|
-
key: "galleryEntries",
|
|
10387
|
-
value: function galleryEntries() {
|
|
10388
|
-
var modulePaths = Object.keys(this.moduleMetadata);
|
|
10389
|
-
if (modulePaths.length === 0) {
|
|
10390
|
-
return null;
|
|
11402
|
+
fixes: ["video:add-metadata"]
|
|
11403
|
+
}];
|
|
10391
11404
|
}
|
|
10392
|
-
return
|
|
11405
|
+
return [];
|
|
10393
11406
|
}
|
|
10394
11407
|
}, {
|
|
10395
11408
|
key: "executeAssert",
|
|
@@ -10422,7 +11435,7 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
|
|
|
10422
11435
|
return {
|
|
10423
11436
|
success: false,
|
|
10424
11437
|
errors: _defineProperty({}, path, [{
|
|
10425
|
-
message: "A
|
|
11438
|
+
message: "A video must be an object with a 'path' (error type: missing_path)",
|
|
10426
11439
|
typeError: true
|
|
10427
11440
|
}])
|
|
10428
11441
|
};
|
|
@@ -10435,19 +11448,19 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
|
|
|
10435
11448
|
}, {
|
|
10436
11449
|
key: "nullable",
|
|
10437
11450
|
value: function nullable() {
|
|
10438
|
-
return new
|
|
11451
|
+
return new VideoSchema(this.options, true, this.isRemote, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput, this.gallery);
|
|
10439
11452
|
}
|
|
10440
11453
|
}, {
|
|
10441
11454
|
key: "readonly",
|
|
10442
11455
|
value: function readonly() {
|
|
10443
11456
|
var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
10444
|
-
return new
|
|
11457
|
+
return new VideoSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput, this.gallery);
|
|
10445
11458
|
}
|
|
10446
11459
|
}, {
|
|
10447
11460
|
key: "hidden",
|
|
10448
11461
|
value: function hidden() {
|
|
10449
11462
|
var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
10450
|
-
return new
|
|
11463
|
+
return new VideoSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput, this.gallery);
|
|
10451
11464
|
}
|
|
10452
11465
|
}, {
|
|
10453
11466
|
key: "executeCustomValidateAt",
|
|
@@ -10457,6 +11470,25 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
|
|
|
10457
11470
|
});
|
|
10458
11471
|
}
|
|
10459
11472
|
|
|
11473
|
+
/**
|
|
11474
|
+
* How this field is laid out in the editor when it is the item of an array
|
|
11475
|
+
* or record: `{ as: "inline" }` renders the field itself inside each row,
|
|
11476
|
+
* instead of a preview row that navigates to it.
|
|
11477
|
+
*
|
|
11478
|
+
* Static configuration, not a callback — see `render.ts`.
|
|
11479
|
+
*
|
|
11480
|
+
* @example
|
|
11481
|
+
* const schema = s.array(s.video().render({ as: "inline" }));
|
|
11482
|
+
* export default c.define("/example.val.ts", schema, [
|
|
11483
|
+
* { path: "/public/val/example.mp4", mimeType: "video/mp4" },
|
|
11484
|
+
* ]);
|
|
11485
|
+
*/
|
|
11486
|
+
}, {
|
|
11487
|
+
key: "render",
|
|
11488
|
+
value: function render(input) {
|
|
11489
|
+
return new VideoSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, input, this.previewInput, this.gallery);
|
|
11490
|
+
}
|
|
11491
|
+
|
|
10460
11492
|
/**
|
|
10461
11493
|
* How this VALUE is shown where a preview of it is needed — a row in a
|
|
10462
11494
|
* sortable list, a reference dropdown, a search hit. Never how the field
|
|
@@ -10464,16 +11496,19 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
|
|
|
10464
11496
|
*
|
|
10465
11497
|
* @example
|
|
10466
11498
|
* const schema = s.array(
|
|
10467
|
-
* s.
|
|
11499
|
+
* s.video().preview(({ val }) => ({
|
|
11500
|
+
* title: val.alt ?? val.path,
|
|
11501
|
+
* image: val.poster,
|
|
11502
|
+
* })),
|
|
10468
11503
|
* );
|
|
10469
11504
|
* export default c.define("/example.val.ts", schema, [
|
|
10470
|
-
* { path: "/public/val/example.
|
|
11505
|
+
* { path: "/public/val/example.mp4", mimeType: "video/mp4" },
|
|
10471
11506
|
* ]);
|
|
10472
11507
|
*/
|
|
10473
11508
|
}, {
|
|
10474
11509
|
key: "preview",
|
|
10475
11510
|
value: function preview(select) {
|
|
10476
|
-
return new
|
|
11511
|
+
return new VideoSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, select, this.gallery);
|
|
10477
11512
|
}
|
|
10478
11513
|
}, {
|
|
10479
11514
|
key: "executePreviewItem",
|
|
@@ -10493,16 +11528,16 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
|
|
|
10493
11528
|
}, {
|
|
10494
11529
|
key: "executeSerialize",
|
|
10495
11530
|
value: function executeSerialize() {
|
|
10496
|
-
var _this$customValidateF;
|
|
10497
|
-
var modulePaths = this.moduleMetadata ? Object.keys(this.moduleMetadata) : [];
|
|
11531
|
+
var _this$renderInput, _this$customValidateF, _this$gallery;
|
|
10498
11532
|
return {
|
|
10499
|
-
type: "
|
|
11533
|
+
type: "video",
|
|
11534
|
+
render: (_this$renderInput = this.renderInput) !== null && _this$renderInput !== void 0 ? _this$renderInput : undefined,
|
|
10500
11535
|
preview: this.previewInput ? true : undefined,
|
|
10501
11536
|
options: this.options,
|
|
10502
11537
|
opt: this.opt,
|
|
10503
11538
|
remote: this.isRemote,
|
|
10504
11539
|
customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
|
|
10505
|
-
referencedModule:
|
|
11540
|
+
referencedModule: (_this$gallery = this.gallery) === null || _this$gallery === void 0 ? void 0 : _this$gallery.modulePath,
|
|
10506
11541
|
readonly: this.isReadonly,
|
|
10507
11542
|
hidden: this.isHidden,
|
|
10508
11543
|
description: this.description
|
|
@@ -10512,27 +11547,137 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
|
|
|
10512
11547
|
}(Schema);
|
|
10513
11548
|
|
|
10514
11549
|
/**
|
|
10515
|
-
*
|
|
10516
|
-
*
|
|
11550
|
+
* Every file a video value names: the video, its poster and each caption
|
|
11551
|
+
* track. An HLS stream's segments are not here — they are named by its
|
|
11552
|
+
* playlists, not by the value.
|
|
10517
11553
|
*/
|
|
10518
|
-
|
|
10519
|
-
|
|
10520
|
-
|
|
10521
|
-
|
|
10522
|
-
|
|
10523
|
-
if (
|
|
10524
|
-
var
|
|
10525
|
-
|
|
10526
|
-
|
|
10527
|
-
|
|
10528
|
-
|
|
10529
|
-
|
|
11554
|
+
function filesOfVideoSource(src) {
|
|
11555
|
+
var files = [src.path];
|
|
11556
|
+
if (src.poster && _typeof(src.poster) === "object" && typeof src.poster.path === "string") {
|
|
11557
|
+
files.push(src.poster.path);
|
|
11558
|
+
}
|
|
11559
|
+
if (Array.isArray(src.captions)) {
|
|
11560
|
+
var _iterator2 = _createForOfIteratorHelper(src.captions),
|
|
11561
|
+
_step2;
|
|
11562
|
+
try {
|
|
11563
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
11564
|
+
var track = _step2.value;
|
|
11565
|
+
if (track && _typeof(track) === "object" && typeof track.path === "string") {
|
|
11566
|
+
files.push(track.path);
|
|
11567
|
+
}
|
|
10530
11568
|
}
|
|
10531
|
-
|
|
11569
|
+
} catch (err) {
|
|
11570
|
+
_iterator2.e(err);
|
|
11571
|
+
} finally {
|
|
11572
|
+
_iterator2.f();
|
|
10532
11573
|
}
|
|
10533
|
-
return new FileSchema({}, false, false, [], allModules);
|
|
10534
11574
|
}
|
|
10535
|
-
return
|
|
11575
|
+
return files;
|
|
11576
|
+
}
|
|
11577
|
+
|
|
11578
|
+
/**
|
|
11579
|
+
* What the value says about its file, typed as what it IS rather than what
|
|
11580
|
+
* it should be: a set-backed field's type has none of these, and is checked
|
|
11581
|
+
* for carrying them anyway, because hand-written JSON never saw the type.
|
|
11582
|
+
*/
|
|
11583
|
+
function ownMetadataOf(src) {
|
|
11584
|
+
var value = _objectSpread2({}, src);
|
|
11585
|
+
return {
|
|
11586
|
+
mimeType: value.mimeType,
|
|
11587
|
+
width: value.width,
|
|
11588
|
+
height: value.height,
|
|
11589
|
+
duration: value.duration
|
|
11590
|
+
};
|
|
11591
|
+
}
|
|
11592
|
+
|
|
11593
|
+
/**
|
|
11594
|
+
* A start the field set against an end the set holds, or the reverse: each is
|
|
11595
|
+
* fine alone, and the field's own times and the set's are each checked where
|
|
11596
|
+
* they are written, so what is left is the pair the page will actually play.
|
|
11597
|
+
*/
|
|
11598
|
+
function validateMixedTimes(src, entry) {
|
|
11599
|
+
var _src$startTime, _src$endTime;
|
|
11600
|
+
if (entry === null || src.startTime === undefined === (src.endTime === undefined)) {
|
|
11601
|
+
return [];
|
|
11602
|
+
}
|
|
11603
|
+
var start = (_src$startTime = src.startTime) !== null && _src$startTime !== void 0 ? _src$startTime : entry.startTime;
|
|
11604
|
+
var end = (_src$endTime = src.endTime) !== null && _src$endTime !== void 0 ? _src$endTime : entry.endTime;
|
|
11605
|
+
if (typeof start !== "number" || typeof end !== "number" || start < end) {
|
|
11606
|
+
return [];
|
|
11607
|
+
}
|
|
11608
|
+
var whose = src.startTime === undefined ? "the start is the set's" : "the end is the set's";
|
|
11609
|
+
return [{
|
|
11610
|
+
message: "'startTime' (".concat(start, "s) must be before 'endTime' (").concat(end, "s) \u2014 ").concat(whose, "."),
|
|
11611
|
+
value: src
|
|
11612
|
+
}];
|
|
11613
|
+
}
|
|
11614
|
+
function stringOrUndefined(value) {
|
|
11615
|
+
return typeof value === "string" ? value : undefined;
|
|
11616
|
+
}
|
|
11617
|
+
function misplacedError(src, misplaced, shouldBeRemote) {
|
|
11618
|
+
var these = misplaced.length === 1 ? "this file is" : "".concat(misplaced.length, " files are");
|
|
11619
|
+
return shouldBeRemote ? {
|
|
11620
|
+
message: "Expected a remote video, but ".concat(these, " stored locally: ").concat(misplaced.join(", ")),
|
|
11621
|
+
value: src,
|
|
11622
|
+
fixes: ["video:upload-remote"]
|
|
11623
|
+
} : {
|
|
11624
|
+
message: "Expected a local video (files under /public), but ".concat(these, " remote: ").concat(misplaced.join(", ")),
|
|
11625
|
+
value: src,
|
|
11626
|
+
fixes: ["video:download-remote"]
|
|
11627
|
+
};
|
|
11628
|
+
}
|
|
11629
|
+
function stripQuery(path) {
|
|
11630
|
+
return path.split("?")[0];
|
|
11631
|
+
}
|
|
11632
|
+
|
|
11633
|
+
/**
|
|
11634
|
+
* A video picked from a set (`s.videoset()`). What is true of the file —
|
|
11635
|
+
* its type, size and length — lives in the set; the field carries what one
|
|
11636
|
+
* page chose about it.
|
|
11637
|
+
*/
|
|
11638
|
+
|
|
11639
|
+
/**
|
|
11640
|
+
* Define a video: an `.mp4` / `.webm` file, or an HLS stream the Studio makes
|
|
11641
|
+
* from an upload when `stream` is set.
|
|
11642
|
+
*/
|
|
11643
|
+
|
|
11644
|
+
function video(options, galleryOptions) {
|
|
11645
|
+
return videoOf(options, galleryOptions);
|
|
11646
|
+
}
|
|
11647
|
+
|
|
11648
|
+
/**
|
|
11649
|
+
* `s.video()` for a project whose media is all remote (`files.remote` in
|
|
11650
|
+
* `val.config.ts`): the same schema, with `.remote()` already applied. See
|
|
11651
|
+
* `initSchema`.
|
|
11652
|
+
*/
|
|
11653
|
+
|
|
11654
|
+
function remoteVideo(options, galleryOptions) {
|
|
11655
|
+
return videoOf(options, galleryOptions).remote();
|
|
11656
|
+
}
|
|
11657
|
+
function videoOf(options, galleryOptions) {
|
|
11658
|
+
var _options$GetSchema, _setSchema$remote, _setSchema$remote2;
|
|
11659
|
+
if (options === undefined || !isVideosetModule(options)) {
|
|
11660
|
+
return new VideoSchema(options);
|
|
11661
|
+
}
|
|
11662
|
+
var modulePath = getValPath(options);
|
|
11663
|
+
if (modulePath === undefined) {
|
|
11664
|
+
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.");
|
|
11665
|
+
}
|
|
11666
|
+
var setSchema = (_options$GetSchema = options[GetSchema]) === null || _options$GetSchema === void 0 ? void 0 : _options$GetSchema["executeSerialize"]();
|
|
11667
|
+
if ((setSchema === null || setSchema === void 0 ? void 0 : setSchema.type) !== "record" || setSchema.mediaType !== "videos") {
|
|
11668
|
+
var _setSchema$mediaType, _setSchema$type;
|
|
11669
|
+
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", "."));
|
|
11670
|
+
}
|
|
11671
|
+
return new VideoSchema((galleryOptions === null || galleryOptions === void 0 ? void 0 : galleryOptions.stream) !== undefined ? {
|
|
11672
|
+
stream: galleryOptions.stream
|
|
11673
|
+
} : undefined, false, (_setSchema$remote = setSchema.remote) !== null && _setSchema$remote !== void 0 ? _setSchema$remote : false, [], false, false, undefined, null, null, {
|
|
11674
|
+
modulePath: modulePath,
|
|
11675
|
+
entries: getSource(options),
|
|
11676
|
+
remote: (_setSchema$remote2 = setSchema.remote) !== null && _setSchema$remote2 !== void 0 ? _setSchema$remote2 : false
|
|
11677
|
+
});
|
|
11678
|
+
}
|
|
11679
|
+
function isVideosetModule(value) {
|
|
11680
|
+
return GetSchema in value;
|
|
10536
11681
|
}
|
|
10537
11682
|
|
|
10538
11683
|
/**
|
|
@@ -11514,6 +12659,99 @@ var imageset = function imageset(options) {
|
|
|
11514
12659
|
});
|
|
11515
12660
|
};
|
|
11516
12661
|
|
|
12662
|
+
/**
|
|
12663
|
+
* Options for s.videoset()
|
|
12664
|
+
*/
|
|
12665
|
+
|
|
12666
|
+
/** See `ImagesetAltOption`: `alt` is optional only when it is the default. */
|
|
12667
|
+
|
|
12668
|
+
/**
|
|
12669
|
+
* One video of a set, keyed by its file path (an HLS stream by its master
|
|
12670
|
+
* playlist).
|
|
12671
|
+
*
|
|
12672
|
+
* Two kinds of thing are here. What is TRUE OF THE FILE — what it is, how
|
|
12673
|
+
* big, how long — is read from the bytes and is the set's alone. The rest —
|
|
12674
|
+
* the description, focal point, poster, start and end, and captions — is what
|
|
12675
|
+
* a page chooses about a video, and an entry holds it as the DEFAULT: every
|
|
12676
|
+
* field picked from the set (`s.video(videosVal)`) starts from it and may
|
|
12677
|
+
* override it key by key, so a video described and trimmed once is described
|
|
12678
|
+
* and trimmed everywhere it is used. `fillFromGallery` is the one merge.
|
|
12679
|
+
*
|
|
12680
|
+
* The poster is also the set's thumbnail of the entry: there is no separate
|
|
12681
|
+
* still for the gallery, because two stills of one video would disagree.
|
|
12682
|
+
*/
|
|
12683
|
+
|
|
12684
|
+
/**
|
|
12685
|
+
* Define a collection of videos — the video twin of `s.imageset()`.
|
|
12686
|
+
*
|
|
12687
|
+
* A field picks from it with `s.video(videosVal)`. An entry may hold the
|
|
12688
|
+
* description, poster, start and end, focal point and captions as defaults,
|
|
12689
|
+
* and a field overrides any of them by setting its own. Uploading in such a
|
|
12690
|
+
* field adds to the set. Call `.remote()` on the result
|
|
12691
|
+
* to store the set on Val Remote.
|
|
12692
|
+
*
|
|
12693
|
+
* @example
|
|
12694
|
+
* ```typescript
|
|
12695
|
+
* const schema = s.videoset({
|
|
12696
|
+
* dir: "/public/val/videos",
|
|
12697
|
+
* stream: { type: "hls" },
|
|
12698
|
+
* });
|
|
12699
|
+
* export default c.define("/content/videos.val.ts", schema, {
|
|
12700
|
+
* "/public/val/videos/intro_51df2.mp4": {
|
|
12701
|
+
* mimeType: "video/mp4",
|
|
12702
|
+
* width: 1280,
|
|
12703
|
+
* height: 720,
|
|
12704
|
+
* duration: 12.5,
|
|
12705
|
+
* alt: "The team, introducing itself",
|
|
12706
|
+
* startTime: 1.5,
|
|
12707
|
+
* },
|
|
12708
|
+
* });
|
|
12709
|
+
* ```
|
|
12710
|
+
*/
|
|
12711
|
+
var videoset = function videoset(options) {
|
|
12712
|
+
var _options$alt, _options$accept;
|
|
12713
|
+
// The same assertion as in `imageset()`, and sound for the same reason:
|
|
12714
|
+
// `VideosetAltOption` makes `alt` required unless `Alt` is the default.
|
|
12715
|
+
var altSchema = (_options$alt = options.alt) !== null && _options$alt !== void 0 ? _options$alt : string().nullable();
|
|
12716
|
+
var itemSchema = new ObjectSchema({
|
|
12717
|
+
mimeType: new StringSchema({}, false),
|
|
12718
|
+
width: new NumberSchema(undefined, false),
|
|
12719
|
+
height: new NumberSchema(undefined, false),
|
|
12720
|
+
duration: new NumberSchema(undefined, false),
|
|
12721
|
+
alt: altSchema
|
|
12722
|
+
}, false);
|
|
12723
|
+
return new RecordSchema(itemSchema, false, [], null, null, {
|
|
12724
|
+
type: "videos",
|
|
12725
|
+
accept: (_options$accept = options.accept) !== null && _options$accept !== void 0 ? _options$accept : DEFAULT_VIDEO_ACCEPT,
|
|
12726
|
+
dir: options.dir,
|
|
12727
|
+
remote: false,
|
|
12728
|
+
altSchema: altSchema,
|
|
12729
|
+
stream: options.stream
|
|
12730
|
+
});
|
|
12731
|
+
};
|
|
12732
|
+
|
|
12733
|
+
/**
|
|
12734
|
+
* The video schema a set's entry is hashed against, for a remote ref.
|
|
12735
|
+
*
|
|
12736
|
+
* The set's item schema is an object, but a remote ref's validation hash is
|
|
12737
|
+
* computed over a MEDIA schema, so one is synthesized from the set — the one
|
|
12738
|
+
* definition the CLI's upload (`videos:upload-remote`) and the Studio's (the
|
|
12739
|
+
* set's gallery) both use, because two copies are two hashes for the same
|
|
12740
|
+
* file. `stream` is left out: it says what is done to an upload on its way
|
|
12741
|
+
* in, not whether the bytes that arrived are valid.
|
|
12742
|
+
*/
|
|
12743
|
+
function videosetEntryVideoSchema(set) {
|
|
12744
|
+
return {
|
|
12745
|
+
type: "video",
|
|
12746
|
+
opt: false,
|
|
12747
|
+
options: _objectSpread2(_objectSpread2({}, set.accept ? {
|
|
12748
|
+
accept: set.accept
|
|
12749
|
+
} : {}), set.dir ? {
|
|
12750
|
+
dir: set.dir
|
|
12751
|
+
} : {})
|
|
12752
|
+
};
|
|
12753
|
+
}
|
|
12754
|
+
|
|
11517
12755
|
// import type { F } from "ts-toolbelt";
|
|
11518
12756
|
// import { i18n, I18n } from "./schema/future/i18n";
|
|
11519
12757
|
// import { oneOf } from "./schema/future/oneOf";
|
|
@@ -11521,7 +12759,31 @@ var imageset = function imageset(options) {
|
|
|
11521
12759
|
// export type InitSchemaLocalized<Locales extends readonly string[]> = {
|
|
11522
12760
|
// readonly i18n: I18n<Locales>;
|
|
11523
12761
|
// };
|
|
11524
|
-
|
|
12762
|
+
|
|
12763
|
+
function initSchema(options) {
|
|
12764
|
+
var media = (options === null || options === void 0 ? void 0 : options.remote) === true ? {
|
|
12765
|
+
image: remoteImage,
|
|
12766
|
+
file: remoteFile,
|
|
12767
|
+
video: remoteVideo,
|
|
12768
|
+
richtext: remoteRichtext,
|
|
12769
|
+
imageset: function (options) {
|
|
12770
|
+
return imageset(options).remote();
|
|
12771
|
+
},
|
|
12772
|
+
fileset: function (options) {
|
|
12773
|
+
return fileset(options).remote();
|
|
12774
|
+
},
|
|
12775
|
+
videoset: function (options) {
|
|
12776
|
+
return videoset(options).remote();
|
|
12777
|
+
}
|
|
12778
|
+
} : {
|
|
12779
|
+
image: image,
|
|
12780
|
+
file: file,
|
|
12781
|
+
video: video,
|
|
12782
|
+
richtext: richtext,
|
|
12783
|
+
imageset: imageset,
|
|
12784
|
+
fileset: fileset,
|
|
12785
|
+
videoset: videoset
|
|
12786
|
+
};
|
|
11525
12787
|
// locales: F.Narrow<Locales>
|
|
11526
12788
|
return {
|
|
11527
12789
|
string: string,
|
|
@@ -11533,14 +12795,15 @@ function initSchema() {
|
|
|
11533
12795
|
"enum": enumSchema,
|
|
11534
12796
|
union: union,
|
|
11535
12797
|
// oneOf,
|
|
11536
|
-
richtext: richtext,
|
|
11537
|
-
image: image,
|
|
12798
|
+
richtext: media.richtext,
|
|
12799
|
+
image: media.image,
|
|
11538
12800
|
literal: literal,
|
|
11539
12801
|
keyOf: keyOf,
|
|
11540
12802
|
view: view,
|
|
11541
12803
|
record: record,
|
|
11542
|
-
file: file,
|
|
11543
|
-
|
|
12804
|
+
file: media.file,
|
|
12805
|
+
video: media.video,
|
|
12806
|
+
fileset: media.fileset,
|
|
11544
12807
|
date: date,
|
|
11545
12808
|
datetime: datetime,
|
|
11546
12809
|
color: color,
|
|
@@ -11548,7 +12811,8 @@ function initSchema() {
|
|
|
11548
12811
|
locale: locale,
|
|
11549
12812
|
route: route,
|
|
11550
12813
|
router: router,
|
|
11551
|
-
imageset: imageset,
|
|
12814
|
+
imageset: media.imageset,
|
|
12815
|
+
videoset: media.videoset,
|
|
11552
12816
|
settings: settings
|
|
11553
12817
|
// i18n: i18n(locales),
|
|
11554
12818
|
};
|
|
@@ -11566,8 +12830,11 @@ function initSchema() {
|
|
|
11566
12830
|
|
|
11567
12831
|
// TODO: Rename to createValSystem (only to be used by internal things), we can then export * from '@valbuild/core' in the next package then.
|
|
11568
12832
|
var initVal = function initVal(config) {
|
|
12833
|
+
var _config$files;
|
|
11569
12834
|
// const locales = options?.locales;
|
|
11570
|
-
var s = initSchema(
|
|
12835
|
+
var s = initSchema({
|
|
12836
|
+
remote: (config === null || config === void 0 || (_config$files = config.files) === null || _config$files === void 0 ? void 0 : _config$files.remote) === true
|
|
12837
|
+
});
|
|
11571
12838
|
// if (locales?.required) {
|
|
11572
12839
|
// console.error("Locales / i18n currently not implemented");
|
|
11573
12840
|
// return {
|
|
@@ -12668,7 +13935,7 @@ function _extractValModules() {
|
|
|
12668
13935
|
* instead would reintroduce exactly the silent skip described above.
|
|
12669
13936
|
*/
|
|
12670
13937
|
function hasRemoteFileSchema(schema) {
|
|
12671
|
-
if (schema.type === "file" || schema.type === "image") {
|
|
13938
|
+
if (schema.type === "file" || schema.type === "image" || schema.type === "video") {
|
|
12672
13939
|
return !!schema.remote;
|
|
12673
13940
|
} else if (schema.type === "richtext") {
|
|
12674
13941
|
var _schema$options;
|
|
@@ -12747,7 +14014,7 @@ function hasRemoteFileSchema(schema) {
|
|
|
12747
14014
|
* already has a data-loss incident attached to it (see above).
|
|
12748
14015
|
*/
|
|
12749
14016
|
function hasMediaSchema(schema) {
|
|
12750
|
-
if (schema.type === "file" || schema.type === "image") {
|
|
14017
|
+
if (schema.type === "file" || schema.type === "image" || schema.type === "video") {
|
|
12751
14018
|
return true;
|
|
12752
14019
|
} else if (schema.type === "richtext") {
|
|
12753
14020
|
var _schema$options2;
|
|
@@ -13113,6 +14380,10 @@ function getValidationBasis(coreVersion, schema, fileExt, metadata, fileHash) {
|
|
|
13113
14380
|
// bytes that arrived are valid. Leaving it in would mean that changing a
|
|
13114
14381
|
// quality setting re-validates every remote file in the project.
|
|
13115
14382
|
delete options.encode;
|
|
14383
|
+
// `stream` likewise: it is what the Studio made of an upload (an HLS
|
|
14384
|
+
// directory instead of one file), and every file it made is validated on its
|
|
14385
|
+
// own merits.
|
|
14386
|
+
delete options.stream;
|
|
13116
14387
|
var schemaValidationBasis = {
|
|
13117
14388
|
type: schema.type,
|
|
13118
14389
|
opt: schema.opt,
|
|
@@ -13132,6 +14403,93 @@ function getFileHash(text) {
|
|
|
13132
14403
|
return hashToRemoteFileHash(getSHA256Hash(new Uint8Array(text)));
|
|
13133
14404
|
}
|
|
13134
14405
|
|
|
14406
|
+
var cache$1 = new WeakMap();
|
|
14407
|
+
|
|
14408
|
+
/**
|
|
14409
|
+
* The PUBLISHED entries of every gallery a module's fields pick from — an
|
|
14410
|
+
* `s.image(galleryVal)`, `s.file(filesVal)` or `s.video(videosVal)` — by the
|
|
14411
|
+
* gallery's module path.
|
|
14412
|
+
*
|
|
14413
|
+
* A gallery-backed value names its file and nothing else that is the
|
|
14414
|
+
* gallery's, so a reader has to look the entry up (`fillFromGallery`). In
|
|
14415
|
+
* draft mode the reader has every module's draft source to look in; outside
|
|
14416
|
+
* it, nothing — and the page got a set-backed video with no type, size,
|
|
14417
|
+
* poster or description, and an image with no dimensions. But the field's
|
|
14418
|
+
* schema was built from the gallery module (`s.video(videosVal)` reads it at
|
|
14419
|
+
* definition), so the published entries are already here, on the schema
|
|
14420
|
+
* instance. This is where they are read from.
|
|
14421
|
+
*
|
|
14422
|
+
* Stops at a view: the module it points at is read on its own, with its own
|
|
14423
|
+
* galleries.
|
|
14424
|
+
*/
|
|
14425
|
+
function galleriesOf(schema) {
|
|
14426
|
+
if (schema === undefined) {
|
|
14427
|
+
return new Map();
|
|
14428
|
+
}
|
|
14429
|
+
var cached = cache$1.get(schema);
|
|
14430
|
+
if (cached) {
|
|
14431
|
+
return cached;
|
|
14432
|
+
}
|
|
14433
|
+
var galleries = new Map();
|
|
14434
|
+
var seen = new Set();
|
|
14435
|
+
function walk(node) {
|
|
14436
|
+
if (_typeof(node) !== "object" || node === null || seen.has(node)) {
|
|
14437
|
+
return;
|
|
14438
|
+
}
|
|
14439
|
+
seen.add(node);
|
|
14440
|
+
if (node instanceof ValViewSchema) {
|
|
14441
|
+
return;
|
|
14442
|
+
}
|
|
14443
|
+
if (node instanceof ImageSchema) {
|
|
14444
|
+
for (var _i = 0, _Object$entries = Object.entries(node["moduleMetadata"]); _i < _Object$entries.length; _i++) {
|
|
14445
|
+
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
|
|
14446
|
+
modulePath = _Object$entries$_i[0],
|
|
14447
|
+
entries = _Object$entries$_i[1];
|
|
14448
|
+
galleries.set(modulePath, entries);
|
|
14449
|
+
}
|
|
14450
|
+
return;
|
|
14451
|
+
}
|
|
14452
|
+
if (node instanceof FileSchema) {
|
|
14453
|
+
for (var _i2 = 0, _Object$entries2 = Object.entries(node["moduleMetadata"]); _i2 < _Object$entries2.length; _i2++) {
|
|
14454
|
+
var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),
|
|
14455
|
+
_modulePath = _Object$entries2$_i[0],
|
|
14456
|
+
_entries = _Object$entries2$_i[1];
|
|
14457
|
+
galleries.set(_modulePath, _entries);
|
|
14458
|
+
}
|
|
14459
|
+
return;
|
|
14460
|
+
}
|
|
14461
|
+
if (node instanceof VideoSchema) {
|
|
14462
|
+
var gallery = node["gallery"];
|
|
14463
|
+
if (gallery && gallery.entries !== null) {
|
|
14464
|
+
galleries.set(gallery.modulePath, gallery.entries);
|
|
14465
|
+
}
|
|
14466
|
+
return;
|
|
14467
|
+
}
|
|
14468
|
+
if (Array.isArray(node)) {
|
|
14469
|
+
var _iterator = _createForOfIteratorHelper(node),
|
|
14470
|
+
_step;
|
|
14471
|
+
try {
|
|
14472
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
14473
|
+
var item = _step.value;
|
|
14474
|
+
walk(item);
|
|
14475
|
+
}
|
|
14476
|
+
} catch (err) {
|
|
14477
|
+
_iterator.e(err);
|
|
14478
|
+
} finally {
|
|
14479
|
+
_iterator.f();
|
|
14480
|
+
}
|
|
14481
|
+
return;
|
|
14482
|
+
}
|
|
14483
|
+
for (var _i3 = 0, _Object$values = Object.values(node); _i3 < _Object$values.length; _i3++) {
|
|
14484
|
+
var value = _Object$values[_i3];
|
|
14485
|
+
walk(value);
|
|
14486
|
+
}
|
|
14487
|
+
}
|
|
14488
|
+
walk(schema);
|
|
14489
|
+
cache$1.set(schema, galleries);
|
|
14490
|
+
return galleries;
|
|
14491
|
+
}
|
|
14492
|
+
|
|
13135
14493
|
/**
|
|
13136
14494
|
* The variant of a discriminated union that a value takes, by its tag.
|
|
13137
14495
|
*
|
|
@@ -13337,7 +14695,7 @@ function deserializeSchema(serialized) {
|
|
|
13337
14695
|
return schema;
|
|
13338
14696
|
}
|
|
13339
14697
|
function deserializeSchemaImpl(serialized) {
|
|
13340
|
-
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;
|
|
14698
|
+
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;
|
|
13341
14699
|
switch (serialized.type) {
|
|
13342
14700
|
case "string":
|
|
13343
14701
|
return new StringSchema(_objectSpread2(_objectSpread2({}, serialized.options), {}, {
|
|
@@ -13396,6 +14754,8 @@ function deserializeSchemaImpl(serialized) {
|
|
|
13396
14754
|
accept: (_serialized$accept = serialized.accept) !== null && _serialized$accept !== void 0 ? _serialized$accept : "*/*",
|
|
13397
14755
|
dir: (_serialized$dir = serialized.dir) !== null && _serialized$dir !== void 0 ? _serialized$dir : "/public/val",
|
|
13398
14756
|
remote: (_serialized$remote = serialized.remote) !== null && _serialized$remote !== void 0 ? _serialized$remote : false,
|
|
14757
|
+
encode: serialized.encode,
|
|
14758
|
+
stream: serialized.stream,
|
|
13399
14759
|
altSchema: serialized.alt ? deserializeSchema(serialized.alt) : undefined
|
|
13400
14760
|
} : undefined, false, false, serialized.description, (_serialized$jsonValue = serialized.jsonValues) !== null && _serialized$jsonValue !== void 0 ? _serialized$jsonValue : false,
|
|
13401
14761
|
// The preview closure cannot survive serialization; the render can.
|
|
@@ -13421,6 +14781,12 @@ function deserializeSchemaImpl(serialized) {
|
|
|
13421
14781
|
return new FileSchema(serialized.options, serialized.opt, serialized.remote, [], {}, false, false, serialized.description);
|
|
13422
14782
|
case "image":
|
|
13423
14783
|
return new ImageSchema(serialized.options, serialized.opt, serialized.remote, [], {}, false, false, serialized.description);
|
|
14784
|
+
case "video":
|
|
14785
|
+
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 ? {
|
|
14786
|
+
modulePath: serialized.referencedModule,
|
|
14787
|
+
entries: null,
|
|
14788
|
+
remote: (_serialized$remote2 = serialized.remote) !== null && _serialized$remote2 !== void 0 ? _serialized$remote2 : false
|
|
14789
|
+
} : null);
|
|
13424
14790
|
case "date":
|
|
13425
14791
|
return new DateSchema(serialized.options, serialized.opt, [], false, false, serialized.description);
|
|
13426
14792
|
case "dateTime":
|
|
@@ -14116,7 +15482,7 @@ function isPageRouter(routerId) {
|
|
|
14116
15482
|
|
|
14117
15483
|
var corePackageJson = {
|
|
14118
15484
|
name: "@valbuild/core",
|
|
14119
|
-
version: "0.
|
|
15485
|
+
version: "0.141.0",
|
|
14120
15486
|
"private": false,
|
|
14121
15487
|
description: "Val - supercharged hard-coded content",
|
|
14122
15488
|
repository: {
|
|
@@ -14205,6 +15571,7 @@ var Internal = {
|
|
|
14205
15571
|
VERSION: {
|
|
14206
15572
|
core: corePackageJson.version
|
|
14207
15573
|
},
|
|
15574
|
+
videosetEntryVideoSchema: videosetEntryVideoSchema,
|
|
14208
15575
|
// A view's read-path plumbing: `Internal` rather than the public surface,
|
|
14209
15576
|
// because an app never builds or unwraps a handle — it passes one to
|
|
14210
15577
|
// `useVal`.
|
|
@@ -14215,9 +15582,15 @@ var Internal = {
|
|
|
14215
15582
|
viewModulesOf: viewModulesOf,
|
|
14216
15583
|
mediaUrl: mediaUrl,
|
|
14217
15584
|
resolveMedia: resolveMedia,
|
|
15585
|
+
resolveVideo: resolveVideo,
|
|
14218
15586
|
isRemoteMediaPath: isRemoteMediaPath,
|
|
14219
15587
|
media: {
|
|
14220
|
-
fillFromGallery: fillFromGallery
|
|
15588
|
+
fillFromGallery: fillFromGallery,
|
|
15589
|
+
galleriesOf: galleriesOf,
|
|
15590
|
+
galleryEntryOf: galleryEntryOf,
|
|
15591
|
+
GALLERY_DEFAULT_GROUPS: GALLERY_DEFAULT_GROUPS,
|
|
15592
|
+
isHlsVideo: isHlsVideo,
|
|
15593
|
+
HLS_MIME_TYPE: HLS_MIME_TYPE
|
|
14221
15594
|
},
|
|
14222
15595
|
getSchema: getSchema,
|
|
14223
15596
|
getValPath: getValPath,
|
|
@@ -14265,6 +15638,13 @@ var Internal = {
|
|
|
14265
15638
|
isExternalFileRef: isExternalFileRef,
|
|
14266
15639
|
createValPathOfItem: createValPathOfItem,
|
|
14267
15640
|
getSHA256Hash: getSHA256Hash,
|
|
15641
|
+
/**
|
|
15642
|
+
* The same hash as `getSHA256Hash`, fed a chunk at a time: what a caller
|
|
15643
|
+
* hashing hundreds of megabytes uses to give the thread back between chunks.
|
|
15644
|
+
*/
|
|
15645
|
+
createSHA256Hash: function createSHA256Hash() {
|
|
15646
|
+
return createHash("sha256");
|
|
15647
|
+
},
|
|
14268
15648
|
initSchema: initSchema,
|
|
14269
15649
|
getMimeType: getMimeType,
|
|
14270
15650
|
mimeTypeToFileExt: mimeTypeToFileExt,
|
|
@@ -14323,4 +15703,4 @@ function tryJsonParse(str) {
|
|
|
14323
15703
|
}
|
|
14324
15704
|
}
|
|
14325
15705
|
|
|
14326
|
-
export {
|
|
15706
|
+
export { discriminatedUnionBranchOf as $, ArraySchema as A, BooleanSchema as B, ASSISTANT_SETTINGS_MAX_LENGTH as C, DEFAULT_CONTENT_HOST as D, THEME_RADIUS_STEPS as E, FATAL_ERROR_TYPES as F, GenericSelector as G, THEME_RADIUS_LENGTHS as H, Internal as I, assistantAvailability as J, SETTINGS_MODULE_CONVENTION as K, isRootModuleFilePath as L, ModuleFilePathSep as M, NumberSchema as N, ObjectSchema as O, PatchError as P, resolveSettingsModule as Q, RecordSchema as R, Schema as S, THEME_LOGO_DIRECTORY as T, localeTagError as U, VAL_EXTENSION as V, localeOfValue as W, LocaleSchema as X, declaredKeySetOf as Y, missingDeclaredKeys as Z, _typeof as _, _slicedToArray as a, ColorSchema as a0, CodeSchema as a1, CODE_LANGUAGES as a2, COLOR_FORMATS as a3, DEFAULT_COLOR_FORMAT as a4, DateTimeSchema as a5, KeyOfSchema as a6, ValViewSchema as a7, isValViewSource as a8, RouteSchema as a9, RichTextSchema as aa, DiscriminatedUnionSchema as ab, EnumSchema as ac, LiteralSchema as ad, deserializeSchema as ae, previewScope as af, isInlineRender as ag, parseNextJsRoutePattern as ah, parseTanStackRoutePattern as ai, tanStackSegmentsOfRoutePath as aj, validateUrlAgainstPattern as ak, getSourcePathFromRoute as al, isPageRouter as am, describeSchemeRejection as an, isCheckableScheme as ao, rejectScheme as ap, schemeOf as aq, UNSAFE_URL_SCHEMES as ar, _createClass as b, _classCallCheck as c, _toConsumableArray as d, DEFAULT_APP_HOST as e, DEFAULT_STATIC_HOST as f, extractValModules as g, computeValModuleShas as h, initVal as i, computeSourcesSha as j, computeSchemaSha as k, hasRemoteFileSchema as l, modules as m, hasMediaSchema as n, DEFAULT_VAL_REMOTE_HOST as o, derefPatch as p, StringSchema as q, ImageSchema as r, splitModuleFilePathAndModulePath as s, FileSchema as t, VideoSchema as u, DEFAULT_VIDEO_ACCEPT as v, DEFAULT_VIDEO_RENDITIONS as w, DEFAULT_VIDEO_SEGMENT_DURATION as x, DateSchema as y, SettingsSchema as z };
|