refactor(core): CORE-05 separate typed defaults and resolved options

This commit is contained in:
Harvey Zhao committed 2026-09-11 01:00:15 +08:00
1 parent 4eec8112fa
commit 97d320bd74
27 files changed
+2278 -240

No files matched your search

+41
View File
@@ -4,6 +4,47 @@ ArtPlayer keeps its existing constructor, player mixins, plugins and DOM/CSS hoo
The production entry is still `src/index.js`; this document marks actual migrated
boundaries rather than describing the entire core as TypeScript.
## Input and resolved configuration
`src/option/defaults.ts` creates fresh defaults on every Artplayer.option access,
including nested objects, arrays and the identity onVttLoad callback. It reads browser
language at the same getter call and retains the existing Safari preload decision.
The entry passes Artplayer.option to `option/resolve.ts`, which performs the existing
deep merge, restores input.container by reference and invokes the same option-validator
function. Allocation of the instance id still precedes validation; DOM mounting follows it.
`option/types.ts` reuses the public Option as the typed input contract. ResolvedOption
requires top-level defaults and subtitle/thumbnail defaults, while explicitly allowing
proxy to remain undefined. ResolvedInput preserves extra typed application fields without
adding a global any index signature. The one assertion after validation connects the
existing dynamic merge to a successfully resolved typed input; this function is not an
unknown-to-safe-object guard. Arbitrary JS still passes through runtime validation,
and permissive nested map/extension data needs checks in its consuming module.
`src/scheme/index.ts` preserves the mutable runtime schema, shared ComponentOption
objects and callback validation messages. Its keys are checked against Option at compile
time. `types/option-validator.d.ts` at the repository root describes the installed 2.0.6
identity validator, callback paths and kindOf; it adds no runtime wrapper or dependency.
Root/core strict configs include that declaration and lint covers root declaration files.
The public Artplayer.validator and scheme references remain available as before.
Merge behavior includes unknown own keys, collection item references, two reads of an
enumerable input container getter, and restoration of an inherited container. Explicit
undefined can still fail the existing schema instead of being silently defaulted. This
task changes neither validation rules nor public consumer declarations.
Two verified declaration gaps are tracked as BASE-TYPE-06 for CORE-07: existing JS can
omit url and use numeric control HTML, while the current public types reject those forms.
The historical rejection fixtures must become positive consumer checks when reconciled.
Other permissive validator cases are not blanket guarantees that later DOM/media code
can consume every accepted value. Preserve failure stages while migrating those consumers.
Run `yarn test:unit` for published/current defaults, merge and error comparisons, and
`yarn typecheck` for required resolved fields and retained callback/application types.
`options.spec.js` exercises actual candidate construction, invalid input timing and
real-media customType/ready callbacks in the three browser engines. Keep those cases
when changing defaults, schema or resolution; also rerun installed-package validation.
## Current TypeScript boundary: utilities
| Module | Responsibility and constraints |
+1 -1
View File
@@ -4,4 +4,4 @@
* (c) 2017-2026 Harvey Zhao
* Released under the MIT License.
*/
!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.Artplayer=e(),define(function(){return t.Artplayer})):(t="undefined"!==typeof globalThis?globalThis:t||self).Artplayer=e()}(this,function(){"use strict";function t(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var e,r={exports:{}};var o=(e||(e=1,r.exports=function(){function t(e){return(t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(e)}var e=Object.prototype.toString,r=function(r){if(void 0===r)return"undefined";if(null===r)return"null";var a=t(r);if("boolean"===a)return"boolean";if("string"===a)return"string";if("number"===a)return"number";if("symbol"===a)return"symbol";if("function"===a)return"GeneratorFunction"===o(r)?"generatorfunction":"function";if(function(t){return Array.isArray?Array.isArray(t):t instanceof Array}(r))return"array";if(function(t){return!(!t.constructor||"function"!=typeof t.constructor.isBuffer)&&t.constructor.isBuffer(t)}(r))return"buffer";if(function(t){try{if("number"==typeof t.length&&"function"==typeof t.callee)return!0}catch(e){if(-1!==e.message.indexOf("callee"))return!0}return!1}(r))return"arguments";if(function(t){return t instanceof Date||"function"==typeof t.toDateString&&"function"==typeof t.getDate&&"function"==typeof t.setDate}(r))return"date";if(function(t){return t instanceof Error||"string"==typeof t.message&&t.constructor&&"number"==typeof t.constructor.stackTraceLimit}(r))return"error";if(function(t){return t instanceof RegExp||"string"==typeof t.flags&&"boolean"==typeof t.ignoreCase&&"boolean"==typeof t.multiline&&"boolean"==typeof t.global}(r))return"regexp";switch(o(r)){case"Symbol":return"symbol";case"Promise":return"promise";case"WeakMap":return"weakmap";case"WeakSet":return"weakset";case"Map":return"map";case"Set":return"set";case"Int8Array":return"int8array";case"Uint8Array":return"uint8array";case"Uint8ClampedArray":return"uint8clampedarray";case"Int16Array":return"int16array";case"Uint16Array":return"uint16array";case"Int32Array":return"int32array";case"Uint32Array":return"uint32array";case"Float32Array":return"float32array";case"Float64Array":return"float64array"}if(function(t){return"function"==typeof t.throw&&"function"==typeof t.return&&"function"==typeof t.next}(r))return"generator";switch(a=e.call(r)){case"[object Object]":return"object";case"[object Map Iterator]":return"mapiterator";case"[object Set Iterator]":return"setiterator";case"[object String Iterator]":return"stringiterator";case"[object Array Iterator]":return"arrayiterator"}return a.slice(8,-1).toLowerCase().replace(/\s/g,"")};function o(t){return t.constructor?t.constructor.name:null}function a(t,e){var o=2<arguments.length&&void 0!==arguments[2]?arguments[2]:["option"];return n(t,e,o),i(t,e,o),function(t,e,o){var s=r(e),l=r(t);if("object"===s){if("object"!==l)throw new Error("[Type Error]: '".concat(o.join("."),"' require 'object' type, but got '").concat(l,"'"));Object.keys(e).forEach(function(r){var s=t[r],l=e[r],c=o.slice();c.push(r),n(s,l,c),i(s,l,c),a(s,l,c)})}if("array"===s){if("array"!==l)throw new Error("[Type Error]: '".concat(o.join("."),"' require 'array' type, but got '").concat(l,"'"));t.forEach(function(r,s){var l=t[s],c=e[s]||e[0],d=o.slice();d.push(s),n(l,c,d),i(l,c,d),a(l,c,d)})}}(t,e,o),t}function n(t,e,o){if("string"===r(e)){var a=r(t);if("?"===e[0]&&(e=e.slice(1)+"|undefined"),!(-1<e.indexOf("|")?e.split("|").map(function(t){return t.toLowerCase().trim()}).filter(Boolean).some(function(t){return a===t}):e.toLowerCase().trim()===a))throw new Error("[Type Error]: '".concat(o.join("."),"' require '").concat(e,"' type, but got '").concat(a,"'"))}}function i(t,e,o){if("function"===r(e)){var a=e(t,r(t),o);if(!0!==a){var n=r(a);throw"string"===n?new Error(a):"error"===n?a:new Error("[Validator Error]: The scheme for '".concat(o.join("."),"' validator require return true, but got '").concat(a,"'"))}}}return a.kindOf=r,a}()),r.exports);const a=t(o),n="5.4.1",i={properties:["audioTracks","autoplay","buffered","controller","controls","crossOrigin","currentSrc","currentTime","defaultMuted","defaultPlaybackRate","duration","ended","error","loop","mediaGroup","muted","networkState","paused","playbackRate","played","preload","readyState","seekable","seeking","src","startDate","textTracks","videoTracks","volume"],methods:["addTextTrack","canPlayType","load","play","pause"],events:["abort","canplay","canplaythrough","durationchange","emptied","ended","error","loadeddata","loadedmetadata","loadstart","pause","play","playing","progress","ratechange","seeked","seeking","stalled","suspend","timeupdate","volumechange","waiting"],prototypes:["width","height","videoWidth","videoHeight","poster","webkitDecodedFrameCount","webkitDroppedFrameCount","playsInline","webLine truncated
!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.Artplayer=e(),define(function(){return t.Artplayer})):(t="undefined"!==typeof globalThis?globalThis:t||self).Artplayer=e()}(this,function(){"use strict";function t(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var e,r={exports:{}};var o=(e||(e=1,r.exports=function(){function t(e){return(t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(e)}var e=Object.prototype.toString,r=function(r){if(void 0===r)return"undefined";if(null===r)return"null";var a=t(r);if("boolean"===a)return"boolean";if("string"===a)return"string";if("number"===a)return"number";if("symbol"===a)return"symbol";if("function"===a)return"GeneratorFunction"===o(r)?"generatorfunction":"function";if(function(t){return Array.isArray?Array.isArray(t):t instanceof Array}(r))return"array";if(function(t){return!(!t.constructor||"function"!=typeof t.constructor.isBuffer)&&t.constructor.isBuffer(t)}(r))return"buffer";if(function(t){try{if("number"==typeof t.length&&"function"==typeof t.callee)return!0}catch(e){if(-1!==e.message.indexOf("callee"))return!0}return!1}(r))return"arguments";if(function(t){return t instanceof Date||"function"==typeof t.toDateString&&"function"==typeof t.getDate&&"function"==typeof t.setDate}(r))return"date";if(function(t){return t instanceof Error||"string"==typeof t.message&&t.constructor&&"number"==typeof t.constructor.stackTraceLimit}(r))return"error";if(function(t){return t instanceof RegExp||"string"==typeof t.flags&&"boolean"==typeof t.ignoreCase&&"boolean"==typeof t.multiline&&"boolean"==typeof t.global}(r))return"regexp";switch(o(r)){case"Symbol":return"symbol";case"Promise":return"promise";case"WeakMap":return"weakmap";case"WeakSet":return"weakset";case"Map":return"map";case"Set":return"set";case"Int8Array":return"int8array";case"Uint8Array":return"uint8array";case"Uint8ClampedArray":return"uint8clampedarray";case"Int16Array":return"int16array";case"Uint16Array":return"uint16array";case"Int32Array":return"int32array";case"Uint32Array":return"uint32array";case"Float32Array":return"float32array";case"Float64Array":return"float64array"}if(function(t){return"function"==typeof t.throw&&"function"==typeof t.return&&"function"==typeof t.next}(r))return"generator";switch(a=e.call(r)){case"[object Object]":return"object";case"[object Map Iterator]":return"mapiterator";case"[object Set Iterator]":return"setiterator";case"[object String Iterator]":return"stringiterator";case"[object Array Iterator]":return"arrayiterator"}return a.slice(8,-1).toLowerCase().replace(/\s/g,"")};function o(t){return t.constructor?t.constructor.name:null}function a(t,e){var o=2<arguments.length&&void 0!==arguments[2]?arguments[2]:["option"];return n(t,e,o),i(t,e,o),function(t,e,o){var s=r(e),l=r(t);if("object"===s){if("object"!==l)throw new Error("[Type Error]: '".concat(o.join("."),"' require 'object' type, but got '").concat(l,"'"));Object.keys(e).forEach(function(r){var s=t[r],l=e[r],c=o.slice();c.push(r),n(s,l,c),i(s,l,c),a(s,l,c)})}if("array"===s){if("array"!==l)throw new Error("[Type Error]: '".concat(o.join("."),"' require 'array' type, but got '").concat(l,"'"));t.forEach(function(r,s){var l=t[s],c=e[s]||e[0],d=o.slice();d.push(s),n(l,c,d),i(l,c,d),a(l,c,d)})}}(t,e,o),t}function n(t,e,o){if("string"===r(e)){var a=r(t);if("?"===e[0]&&(e=e.slice(1)+"|undefined"),!(-1<e.indexOf("|")?e.split("|").map(function(t){return t.toLowerCase().trim()}).filter(Boolean).some(function(t){return a===t}):e.toLowerCase().trim()===a))throw new Error("[Type Error]: '".concat(o.join("."),"' require '").concat(e,"' type, but got '").concat(a,"'"))}}function i(t,e,o){if("function"===r(e)){var a=e(t,r(t),o);if(!0!==a){var n=r(a);throw"string"===n?new Error(a):"error"===n?a:new Error("[Validator Error]: The scheme for '".concat(o.join("."),"' validator require return true, but got '").concat(a,"'"))}}}return a.kindOf=r,a}()),r.exports);const a=t(o),n="5.4.1",i={properties:["audioTracks","autoplay","buffered","controller","controls","crossOrigin","currentSrc","currentTime","defaultMuted","defaultPlaybackRate","duration","ended","error","loop","mediaGroup","muted","networkState","paused","playbackRate","played","preload","readyState","seekable","seeking","src","startDate","textTracks","videoTracks","volume"],methods:["addTextTrack","canPlayType","load","play","pause"],events:["abort","canplay","canplaythrough","durationchange","emptied","ended","error","loadeddata","loadedmetadata","loadstart","pause","play","playing","progress","ratechange","seeked","seeking","stalled","suspend","timeupdate","volumechange","waiting"],prototypes:["width","height","videoWidth","videoHeight","poster","webkitDecodedFrameCount","webkitDroppedFrameCount","playsInline","webLine truncated
+1 -1
View File
@@ -4,4 +4,4 @@
* (c) 2017-2026 Harvey Zhao
* Released under the MIT License.
*/
!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.Artplayer=e(),define(function(){return t.Artplayer})):(t="undefined"!==typeof globalThis?globalThis:t||self).Artplayer=e()}(this,function(){"use strict";var t,e=Object.defineProperty,r=Object.defineProperties,o=Object.getOwnPropertyDescriptors,a=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable,s=(t,r,o)=>r in t?e(t,r,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[r]=o,l=(t,e)=>{for(var r in e||(e={}))n.call(e,r)&&s(t,r,e[r]);if(a)for(var r of a(e))i.call(e,r)&&s(t,r,e[r]);return t},c=(t,e)=>r(t,o(e)),d=(t,e,r)=>new Promise((o,a)=>{var n=t=>{try{s(r.next(t))}catch(e){a(e)}},i=t=>{try{s(r.throw(t))}catch(e){a(e)}},s=t=>t.done?o(t.value):Promise.resolve(t.value).then(n,i);s((r=r.apply(t,e)).next())});function p(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var h,u={exports:{}};var m=(h||(h=1,u.exports=function(){function t(e){return(t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(e)}var e=Object.prototype.toString,r=function(r){if(void 0===r)return"undefined";if(null===r)return"null";var a=t(r);if("boolean"===a)return"boolean";if("string"===a)return"string";if("number"===a)return"number";if("symbol"===a)return"symbol";if("function"===a)return"GeneratorFunction"===o(r)?"generatorfunction":"function";if(function(t){return Array.isArray?Array.isArray(t):t instanceof Array}(r))return"array";if(function(t){return!(!t.constructor||"function"!=typeof t.constructor.isBuffer)&&t.constructor.isBuffer(t)}(r))return"buffer";if(function(t){try{if("number"==typeof t.length&&"function"==typeof t.callee)return!0}catch(e){if(-1!==e.message.indexOf("callee"))return!0}return!1}(r))return"arguments";if(function(t){return t instanceof Date||"function"==typeof t.toDateString&&"function"==typeof t.getDate&&"function"==typeof t.setDate}(r))return"date";if(function(t){return t instanceof Error||"string"==typeof t.message&&t.constructor&&"number"==typeof t.constructor.stackTraceLimit}(r))return"error";if(function(t){return t instanceof RegExp||"string"==typeof t.flags&&"boolean"==typeof t.ignoreCase&&"boolean"==typeof t.multiline&&"boolean"==typeof t.global}(r))return"regexp";switch(o(r)){case"Symbol":return"symbol";case"Promise":return"promise";case"WeakMap":return"weakmap";case"WeakSet":return"weakset";case"Map":return"map";case"Set":return"set";case"Int8Array":return"int8array";case"Uint8Array":return"uint8array";case"Uint8ClampedArray":return"uint8clampedarray";case"Int16Array":return"int16array";case"Uint16Array":return"uint16array";case"Int32Array":return"int32array";case"Uint32Array":return"uint32array";case"Float32Array":return"float32array";case"Float64Array":return"float64array"}if(function(t){return"function"==typeof t.throw&&"function"==typeof t.return&&"function"==typeof t.next}(r))return"generator";switch(a=e.call(r)){case"[object Object]":return"object";case"[object Map Iterator]":return"mapiterator";case"[object Set Iterator]":return"setiterator";case"[object String Iterator]":return"stringiterator";case"[object Array Iterator]":return"arrayiterator"}return a.slice(8,-1).toLowerCase().replace(/\s/g,"")};function o(t){return t.constructor?t.constructor.name:null}function a(t,e){var o=2<arguments.length&&void 0!==arguments[2]?arguments[2]:["option"];return n(t,e,o),i(t,e,o),function(t,e,o){var s=r(e),l=r(t);if("object"===s){if("object"!==l)throw new Error("[Type Error]: '".concat(o.join("."),"' require 'object' type, but got '").concat(l,"'"));Object.keys(e).forEach(function(r){var s=t[r],l=e[r],c=o.slice();c.push(r),n(s,l,c),i(s,l,c),a(s,l,c)})}if("array"===s){if("array"!==l)throw new Error("[Type Error]: '".concat(o.join("."),"' require 'array' type, but got '").concat(l,"'"));t.forEach(function(r,s){var l=t[s],c=e[s]||e[0],d=o.slice();d.push(s),n(l,c,d),i(l,c,d),a(l,c,d)})}}(t,e,o),t}function n(t,e,o){if("string"===r(e)){var a=r(t);if("?"===e[0]&&(e=e.slice(1)+"|undefined"),!(-1<e.indexOf("|")?e.split("|").map(function(t){return t.toLowerCase().trim()}).filter(Boolean).some(function(t){return a===t}):e.toLowerCase().trim()===a))throw new Error("[Type Error]: '".concat(o.join("."),"' require '").concat(e,"' type, but got '").concat(a,"'"))}}function i(t,e,o){if("function"===r(e)){var a=e(t,r(t),o);if(!0!==a){var n=r(a);throw"string"===n?new Error(a):"error"===n?a:new Error("[Validator Error]: The scheme for '".concat(o.join("."),"' validator require return true, but got '").concat(a,"'"))}}}return a.kindOf=r,a}()),u.exports);const f=p(m),g="5.4.1",v={properties:["audioTracks","autoplay","buffered","controller","controls","crossOrigin","currentSrc","currentTime","defaultMuted","defaultPlaybackRate","duration","ended","error","loop","meLine truncated
!function(t,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"==typeof define&&define.amd?(t.Artplayer=e(),define(function(){return t.Artplayer})):(t="undefined"!==typeof globalThis?globalThis:t||self).Artplayer=e()}(this,function(){"use strict";var t,e=Object.defineProperty,r=Object.defineProperties,o=Object.getOwnPropertyDescriptors,a=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable,s=(t,r,o)=>r in t?e(t,r,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[r]=o,l=(t,e)=>{for(var r in e||(e={}))n.call(e,r)&&s(t,r,e[r]);if(a)for(var r of a(e))i.call(e,r)&&s(t,r,e[r]);return t},c=(t,e)=>r(t,o(e)),d=(t,e,r)=>new Promise((o,a)=>{var n=t=>{try{s(r.next(t))}catch(e){a(e)}},i=t=>{try{s(r.throw(t))}catch(e){a(e)}},s=t=>t.done?o(t.value):Promise.resolve(t.value).then(n,i);s((r=r.apply(t,e)).next())});function p(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var h,u={exports:{}};var m=(h||(h=1,u.exports=function(){function t(e){return(t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(e)}var e=Object.prototype.toString,r=function(r){if(void 0===r)return"undefined";if(null===r)return"null";var a=t(r);if("boolean"===a)return"boolean";if("string"===a)return"string";if("number"===a)return"number";if("symbol"===a)return"symbol";if("function"===a)return"GeneratorFunction"===o(r)?"generatorfunction":"function";if(function(t){return Array.isArray?Array.isArray(t):t instanceof Array}(r))return"array";if(function(t){return!(!t.constructor||"function"!=typeof t.constructor.isBuffer)&&t.constructor.isBuffer(t)}(r))return"buffer";if(function(t){try{if("number"==typeof t.length&&"function"==typeof t.callee)return!0}catch(e){if(-1!==e.message.indexOf("callee"))return!0}return!1}(r))return"arguments";if(function(t){return t instanceof Date||"function"==typeof t.toDateString&&"function"==typeof t.getDate&&"function"==typeof t.setDate}(r))return"date";if(function(t){return t instanceof Error||"string"==typeof t.message&&t.constructor&&"number"==typeof t.constructor.stackTraceLimit}(r))return"error";if(function(t){return t instanceof RegExp||"string"==typeof t.flags&&"boolean"==typeof t.ignoreCase&&"boolean"==typeof t.multiline&&"boolean"==typeof t.global}(r))return"regexp";switch(o(r)){case"Symbol":return"symbol";case"Promise":return"promise";case"WeakMap":return"weakmap";case"WeakSet":return"weakset";case"Map":return"map";case"Set":return"set";case"Int8Array":return"int8array";case"Uint8Array":return"uint8array";case"Uint8ClampedArray":return"uint8clampedarray";case"Int16Array":return"int16array";case"Uint16Array":return"uint16array";case"Int32Array":return"int32array";case"Uint32Array":return"uint32array";case"Float32Array":return"float32array";case"Float64Array":return"float64array"}if(function(t){return"function"==typeof t.throw&&"function"==typeof t.return&&"function"==typeof t.next}(r))return"generator";switch(a=e.call(r)){case"[object Object]":return"object";case"[object Map Iterator]":return"mapiterator";case"[object Set Iterator]":return"setiterator";case"[object String Iterator]":return"stringiterator";case"[object Array Iterator]":return"arrayiterator"}return a.slice(8,-1).toLowerCase().replace(/\s/g,"")};function o(t){return t.constructor?t.constructor.name:null}function a(t,e){var o=2<arguments.length&&void 0!==arguments[2]?arguments[2]:["option"];return n(t,e,o),i(t,e,o),function(t,e,o){var s=r(e),l=r(t);if("object"===s){if("object"!==l)throw new Error("[Type Error]: '".concat(o.join("."),"' require 'object' type, but got '").concat(l,"'"));Object.keys(e).forEach(function(r){var s=t[r],l=e[r],c=o.slice();c.push(r),n(s,l,c),i(s,l,c),a(s,l,c)})}if("array"===s){if("array"!==l)throw new Error("[Type Error]: '".concat(o.join("."),"' require 'array' type, but got '").concat(l,"'"));t.forEach(function(r,s){var l=t[s],c=e[s]||e[0],d=o.slice();d.push(s),n(l,c,d),i(l,c,d),a(l,c,d)})}}(t,e,o),t}function n(t,e,o){if("string"===r(e)){var a=r(t);if("?"===e[0]&&(e=e.slice(1)+"|undefined"),!(-1<e.indexOf("|")?e.split("|").map(function(t){return t.toLowerCase().trim()}).filter(Boolean).some(function(t){return a===t}):e.toLowerCase().trim()===a))throw new Error("[Type Error]: '".concat(o.join("."),"' require '").concat(e,"' type, but got '").concat(a,"'"))}}function i(t,e,o){if("function"===r(e)){var a=e(t,r(t),o);if(!0!==a){var n=r(a);throw"string"===n?new Error(a):"error"===n?a:new Error("[Validator Error]: The scheme for '".concat(o.join("."),"' validator require return true, but got '").concat(a,"'"))}}}return a.kindOf=r,a}()),u.exports);const f=p(m),g="5.4.1",v={properties:["audioTracks","autoplay","buffered","controller","controls","crossOrigin","currentSrc","currentTime","defaultMuted","defaultPlaybackRate","duration","ended","error","loop","meLine truncated
+80 -74
View File
@@ -735,7 +735,7 @@ const scheme = {
position: (value, _, paths) => {
const position = ["top", "left", "right"];
return errorHandle(
position.includes(value),
typeof value === "string" && position.includes(value),
`${paths.join(".")} only accept ${position.toString()} as parameters`
);
}
@@ -2533,6 +2533,83 @@ class Notice {
return $player.classList.contains("art-notice-show");
}
}
function createDefaults() {
return {
id: "",
container: "#artplayer",
url: "",
poster: "",
type: "",
theme: "#f00",
volume: 0.7,
isLive: false,
muted: false,
autoplay: false,
autoSize: false,
autoMini: false,
loop: false,
flip: false,
playbackRate: false,
aspectRatio: false,
screenshot: false,
setting: false,
hotkey: true,
pip: false,
mutex: true,
backdrop: true,
fullscreen: false,
fullscreenWeb: false,
subtitleOffset: false,
miniProgressBar: false,
useSSR: false,
playsInline: true,
lock: false,
gesture: true,
fastForward: false,
autoPlayback: false,
autoOrientation: false,
airplay: false,
proxy: void 0,
layers: [],
contextmenu: [],
controls: [],
settings: [],
quality: [],
highlight: [],
plugins: [],
thumbnails: {
url: "",
number: 60,
column: 10,
width: 0,
height: 0,
scale: 1
},
subtitle: {
url: "",
type: "",
style: {},
name: "",
escape: true,
encoding: "utf-8",
onVttLoad: (vtt) => vtt
},
moreVideoAttr: {
controls: false,
preload: isSafari ? "auto" : "metadata"
},
i18n: {},
icons: {},
cssVar: {},
customType: {},
lang: navigator?.language.toLowerCase()
};
}
function resolveOption(input, defaults) {
const merged = mergeDeep(defaults, input);
merged.container = input.container;
return validator(merged, scheme);
}
function airplayMix(art) {
const {
i18n,
@@ -5085,9 +5162,7 @@ class Artplayer extends Emitter {
throw new Error("Artplayer can only be used in the browser environment");
}
this.id = ++id;
const mergeOption = mergeDeep(Artplayer.option, option);
mergeOption.container = option.container;
this.option = validator(mergeOption, scheme);
this.option = resolveOption(option, Artplayer.option);
this.isLock = false;
this.isReady = false;
this.isFocus = false;
@@ -5164,76 +5239,7 @@ class Artplayer extends Emitter {
return Template.html;
}
static get option() {
return {
id: "",
container: "#artplayer",
url: "",
poster: "",
type: "",
theme: "#f00",
volume: 0.7,
isLive: false,
muted: false,
autoplay: false,
autoSize: false,
autoMini: false,
loop: false,
flip: false,
playbackRate: false,
aspectRatio: false,
screenshot: false,
setting: false,
hotkey: true,
pip: false,
mutex: true,
backdrop: true,
fullscreen: false,
fullscreenWeb: false,
subtitleOffset: false,
miniProgressBar: false,
useSSR: false,
playsInline: true,
lock: false,
gesture: true,
fastForward: false,
autoPlayback: false,
autoOrientation: false,
airplay: false,
proxy: void 0,
layers: [],
contextmenu: [],
controls: [],
settings: [],
quality: [],
highlight: [],
plugins: [],
thumbnails: {
url: "",
number: 60,
column: 10,
width: 0,
height: 0,
scale: 1
},
subtitle: {
url: "",
type: "",
style: {},
name: "",
escape: true,
encoding: "utf-8",
onVttLoad: (vtt) => vtt
},
moreVideoAttr: {
controls: false,
preload: isSafari ? "auto" : "metadata"
},
i18n: {},
icons: {},
cssVar: {},
customType: {},
lang: navigator?.language.toLowerCase()
};
return createDefaults();
}
get proxy() {
return this.events.proxy;
+4 -74
View File
@@ -13,6 +13,8 @@ import { beginLifecycle, destroyInstance, finishLifecycle, getScope } from './li
import Loading from './loading'
import Mask from './mask'
import Notice from './notice'
import createDefaults from './option/defaults'
import resolveOption from './option/resolve'
import Player from './player'
import Plugins from './plugins'
import scheme from './scheme'
@@ -36,10 +38,7 @@ export default class Artplayer extends Emitter {
this.id = ++id
const mergeOption = utils.mergeDeep(Artplayer.option, option)
mergeOption.container = option.container
this.option = validator(mergeOption, scheme)
this.option = resolveOption(option, Artplayer.option)
this.isLock = false
this.isReady = false
@@ -135,76 +134,7 @@ export default class Artplayer extends Emitter {
}
static get option() {
return {
id: '',
container: '#artplayer',
url: '',
poster: '',
type: '',
theme: '#f00',
volume: 0.7,
isLive: false,
muted: false,
autoplay: false,
autoSize: false,
autoMini: false,
loop: false,
flip: false,
playbackRate: false,
aspectRatio: false,
screenshot: false,
setting: false,
hotkey: true,
pip: false,
mutex: true,
backdrop: true,
fullscreen: false,
fullscreenWeb: false,
subtitleOffset: false,
miniProgressBar: false,
useSSR: false,
playsInline: true,
lock: false,
gesture: true,
fastForward: false,
autoPlayback: false,
autoOrientation: false,
airplay: false,
proxy: undefined,
layers: [],
contextmenu: [],
controls: [],
settings: [],
quality: [],
highlight: [],
plugins: [],
thumbnails: {
url: '',
number: 60,
column: 10,
width: 0,
height: 0,
scale: 1,
},
subtitle: {
url: '',
type: '',
style: {},
name: '',
escape: true,
encoding: 'utf-8',
onVttLoad: vtt => vtt,
},
moreVideoAttr: {
controls: false,
preload: utils.isSafari ? 'auto' : 'metadata',
},
i18n: {},
icons: {},
cssVar: {},
customType: {},
lang: navigator?.language.toLowerCase(),
}
return createDefaults()
}
get proxy() {
+75
View File
@@ -0,0 +1,75 @@
import type { ResolvedOption } from './types'
import { isSafari } from '../utils/compatibility'
export default function createDefaults(): ResolvedOption {
return {
id: '',
container: '#artplayer',
url: '',
poster: '',
type: '',
theme: '#f00',
volume: 0.7,
isLive: false,
muted: false,
autoplay: false,
autoSize: false,
autoMini: false,
loop: false,
flip: false,
playbackRate: false,
aspectRatio: false,
screenshot: false,
setting: false,
hotkey: true,
pip: false,
mutex: true,
backdrop: true,
fullscreen: false,
fullscreenWeb: false,
subtitleOffset: false,
miniProgressBar: false,
useSSR: false,
playsInline: true,
lock: false,
gesture: true,
fastForward: false,
autoPlayback: false,
autoOrientation: false,
airplay: false,
proxy: undefined,
layers: [],
contextmenu: [],
controls: [],
settings: [],
quality: [],
highlight: [],
plugins: [],
thumbnails: {
url: '',
number: 60,
column: 10,
width: 0,
height: 0,
scale: 1,
},
subtitle: {
url: '',
type: '',
style: {},
name: '',
escape: true,
encoding: 'utf-8',
onVttLoad: vtt => vtt,
},
moreVideoAttr: {
controls: false,
preload: isSafari ? 'auto' : 'metadata',
},
i18n: {},
icons: {},
cssVar: {},
customType: {},
lang: navigator?.language.toLowerCase(),
}
}
+11
View File
@@ -0,0 +1,11 @@
import type { Option, ResolvedInput, ResolvedOption } from './types'
import validator from 'option-validator'
import scheme from '../scheme'
import { mergeDeep } from '../utils/property'
export default function resolveOption<Input extends Option>(input: Input, defaults: ResolvedOption): ResolvedInput<Input> {
const merged = mergeDeep(defaults, input)
merged.container = input.container
// Keep the existing runtime validator. It checks the known schema, not extension data.
return validator(merged, scheme) as ResolvedInput<Input>
}
+13
View File
@@ -0,0 +1,13 @@
import type { Option, Thumbnails } from '../../types/option'
import type { Subtitle } from '../../types/subtitle'
export type { Option } from '../../types/option'
// A successfully merged typed input, not a general guard for arbitrary JS objects.
export interface ResolvedOption extends Omit<Required<Option>, 'proxy' | 'subtitle' | 'thumbnails'> {
proxy: Option['proxy']
subtitle: Required<Subtitle>
thumbnails: Required<Thumbnails>
}
export type ResolvedInput<Input extends Option> = ResolvedOption & Omit<Input, keyof Option>
@@ -1,3 +1,5 @@
import type { Scheme, ValidatorPath } from 'option-validator'
import type { Option } from '../option/types'
import { errorHandle } from '../utils'
const a = 'array'
@@ -7,7 +9,7 @@ const n = 'number'
const o = 'object'
const f = 'function'
function validElement(value, type, paths) {
function validElement(value: unknown, type: string, paths: ValidatorPath) {
return errorHandle(
type === s || type === n || value instanceof Element,
`${paths.join('.')} require '${s}' or 'Element' type`,
@@ -33,7 +35,7 @@ export const ComponentOption = {
onChange: `?${f}`,
}
export default {
const scheme = {
id: s,
container: validElement,
url: s,
@@ -77,10 +79,10 @@ export default {
controls: [
{
...ComponentOption,
position: (value, _, paths) => {
position: (value: unknown, _: string, paths: ValidatorPath) => {
const position = ['top', 'left', 'right']
return errorHandle(
position.includes(value),
typeof value === 'string' && position.includes(value),
`${paths.join('.')} only accept ${position.toString()} as parameters`,
)
},
@@ -121,4 +123,6 @@ export default {
icons: o,
cssVar: o,
customType: o,
}
} satisfies Record<keyof Option, Scheme>
export default scheme
+11 -1
View File
@@ -1,4 +1,14 @@
{
"extends": "../../tsconfig.base.json",
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.mts", "src/**/*.cts", "types/**/*.d.ts", "types/**/*.d.mts", "types/**/*.d.cts", "../../types/assets.d.ts"]
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.mts",
"src/**/*.cts",
"types/**/*.d.ts",
"types/**/*.d.mts",
"types/**/*.d.cts",
"../../types/assets.d.ts",
"../../types/option-validator.d.ts"
]
}
+10
View File
@@ -26,3 +26,13 @@ When changing types, run `yarn typecheck`, `yarn test:baseline` and
chapter/legacy factories, language data, invalid inputs, NodeNext/Bundler and old
TS 4.3.5 consumers. Run `yarn build:ts` to refresh editor declarations. Full editor
behavior and other core declaration/runtime mismatches have CORE-07/SITE tasks.
## Configuration migration boundary
CORE-05 keeps the public Option unchanged. Internal src/option/types.ts distinguishes
typed input from defaults-filled ResolvedOption; it is not a new public export. The
existing public url requirement and exclusion of numeric control HTML differ from
verified JS behavior (BASE-TYPE-06, CORE-07). test/types/options-source.ts records the
current rejection; replace those two negative cases with positive consumer coverage
when expanding the public declarations. Do not change runtime validation to match a
narrower historical declaration. Other optional fields and callback signatures remain
subject to the existing public compatibility contract.