fix(dpip): [PKG-DPIP-04] preserve factory type and export compatibility

This commit is contained in:
Harvey Zhao committed 2026-09-12 14:53:05 +08:00
1 parent 80d37d66f8
commit ef976136a1
31 files changed
+1067 -68

No files matched your search

+49 -18
View File
@@ -1,22 +1,53 @@
interface Option {
width?: number
height?: number
placeholder?: string
fallbackToVideoPiP?: boolean
// Generated from the package public declaration by yarn build:ts. Do not edit.
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
declare namespace artplayerPluginDocumentPipDefinitions {
export interface Option {
/** Requested window width. @default 480 */
width?: number
/** Requested window height. @default 270 */
height?: number
/** Text displayed in the original player container while the window is active. */
placeholder?: string
/** Use the core video PiP property when Document PiP is unavailable. @default true */
fallbackToVideoPiP?: boolean
}
/** Historical assignable result; preserved for direct and extracted return types. */
export interface Result {
name: 'artplayerPluginDocumentPip'
/** Runtime is a readonly capability snapshot; the published field stays assignable. */
isSupported: boolean
/** Runtime is a readonly live getter; the published field stays assignable. */
isActive: boolean
/** Runtime returns Promise<void>; the published void action remains assignable here. */
open: () => void
/** Runtime returns Promise<void>; the published void action remains assignable here. */
close: () => void
toggle: () => void
}
/** Exact view of an unmodified runtime result. */
export interface AsyncResult extends Omit<Result, 'isSupported' | 'isActive' | 'open' | 'close'> {
readonly isSupported: boolean
readonly isActive: boolean
open: () => Promise<void>
close: () => Promise<void>
}
/** Exact published factory signature, including compatibility with replacement functions. */
export type Factory = (option: Option) => (art: Artplayer) => Result
/** Opt-in runtime view with omitted options, self default and precise async actions. */
export interface RuntimeFactory {
(option?: Option): (art: Artplayer) => AsyncResult
readonly default: RuntimeFactory
}
/** Keep the published callable type; use RuntimeFactory explicitly for its broader runtime shape. */
export function artplayerPluginDocumentPip(option: Option): (art: Artplayer) => Result
}
interface Result {
name: 'artplayerPluginDocumentPip'
isSupported: boolean
isActive: boolean
open: () => void
close: () => void
toggle: () => void
declare const artplayerPluginDocumentPip: typeof artplayerPluginDocumentPipDefinitions.artplayerPluginDocumentPip
declare namespace artplayerPluginDocumentPip {
export type Option = artplayerPluginDocumentPipDefinitions.Option
export type Result = artplayerPluginDocumentPipDefinitions.Result
export type AsyncResult = artplayerPluginDocumentPipDefinitions.AsyncResult
export type Factory = artplayerPluginDocumentPipDefinitions.Factory
export type RuntimeFactory = artplayerPluginDocumentPipDefinitions.RuntimeFactory
}
declare const artplayerPluginDocumentPip: (option: Option) => (art: Artplayer) => Result
export default artplayerPluginDocumentPip
export = artplayerPluginDocumentPip
export as namespace artplayerPluginDocumentPip;
@@ -4,4 +4,4 @@
* (c) 2017-2026 Harvey Zhao
* Released under the MIT License.
*/
!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerPluginDocumentPip=t(),define(function(){return e.artplayerPluginDocumentPip})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginDocumentPip=t()}(this,function(){"use strict";function e(e){const t=[];for(const o of e)try{o()}catch(n){t.push(n)}return t}const t=".artplayer-document-pip.art-video-player{width:100%!important;height:100%!important}";function n(t){let n=!1,o=0,i=null,r=null,c=null;const l=()=>!n&&t.alive(),s=e=>e===o&&l();function u(){o++,r?.finish(),r=null,c?.cancel(),c=null}function a(t){const n=e(t.releases.splice(0));return n.push(...e([()=>t.window.close()])),n}async function d(e){if(!s(e))return;const n=function(){let e;const t=new Promise(t=>{e=t});let n=setTimeout(()=>{n=null,e()},100);return{promise:t,cancel(){null!==n&&clearTimeout(n),n=null,e()}}}();c=n,await n.promise,c===n&&(c=null),s(e)&&t.resize()}async function p(){u();const e=o,n=i;if(i=null,!n)return;const r=a(n);if(n.announced)try{t.activate(!1)}catch(c){r.push(c)}r.length&&l()&&t.report("close",r[0]),s(e)&&await d(e)}return{get active(){return null!==i},get opening(){return null!==r},open:async function(){if(!l()||i)return;if(r)return r.promise;u();const n=o;let c,f;const m=new Promise((e,t)=>{c=e,f=t}),h={promise:m,finish:c};r=h;const y=()=>{r===h&&(r=null),c()},g=o=>{if(s(n)){const n=i;i=null,n&&(a(n),n.announced&&e([()=>t.activate(!1)]));try{t.report("open",o)}catch(r){f(r)}}},v=async o=>{if(!s(n))return void(i?.window!==o&&e([()=>o.close()]));const r={window:o,releases:[],announced:!1};i=r;try{const e=t.project(o.document);if(r.releases.push(e.destroy),e.mount(),!s(n))return void a(r);for(const[i,c]of[["resize",()=>{s(n)&&t.nativeResize()}],["pagehide",()=>{p()}],["unload",()=>{p()}]])if(r.releases.unshift(()=>o.removeEventListener(i,c)),o.addEventListener(i,c),!s(n))return void a(r);r.announced=!0,t.activate(!0),await d(n)}catch(c){g(c)}};try{const e=t.request();Promise.resolve(e).then(v,g).then(y,e=>{s(n)&&f(e),y()})}catch(w){try{g(w)}finally{y()}}return m},close:p,destroy(){n||(n=!0,p().catch(()=>{}))}}}return"undefined"!==typeof document&&function(e){const n="artplayer-plugin-document-pip",o=e.getElementById(n);if(o)return void(o.textContent=t);const i=e.createElement("style");i.id=n,i.textContent=t;const r=()=>{e.removeEventListener("DOMContentLoaded",r);const o=e.getElementById(n);o?o.textContent=t:(e.head||e.documentElement).appendChild(i)};"loading"===e.readyState?e.addEventListener("DOMContentLoaded",r):r()}(document),function(t={}){const o={width:480,height:270,fallbackToVideoPiP:!0,placeholder:"Playing in Document Picture-in-Picture",...t};return t=>{const i=window,r="documentPictureInPicture"in i&&"function"===typeof i.documentPictureInPicture?.requestWindow;let c=t,l=t.template.$player,s=t.isDestroy;const u=t.constructor.utils,a=()=>!s&&!!c&&!c.isDestroy,d=n({alive:a,request:()=>i.documentPictureInPicture.requestWindow({width:o.width,height:o.height}),project:t=>function(t,n,o){const i=t.ownerDocument,r=t.parentNode,c=t.nextSibling;if(!r)throw new Error("Document Picture-in-Picture requires a mounted player");const l=i.createElement("div");l.className="artplayer-document-pip-placeholder",l.style.cssText="display:flex;justify-content:center;align-items:center;width:100%;height:100%;",l.textContent=o??"";const s=n.createElement("div");s.id="__art_dpip_root";const u=[];let a=!1;const d=()=>{const e=l.parentNode===r?l:c?.parentNode===r?c:null;if(t.parentNode!==r||t.nextSibling!==e)try{r.insertBefore(t,e)}catch(n){throw i.body.appendChild(t),n}},p=()=>{const t=e([d,()=>l.remove(),...u.splice(0).map(e=>()=>e.remove()),()=>s.remove()]);if(t.length)throw t[0]};return{mount(){if(!a){if(r.insertBefore(l,c?.parentNode===r?c:null),a||n.body.appendChild(s),a||function(e,t,n,o){const i=e=>{o()&&(n(e),t.head.appendChild(e),o()||e.remove())},r=t.createElement("style");if(r.textContent="\n html, body { margin:0; padding:0; width:100%; height:100%; background:#000; overflow:hidden; }\n #__art_dpip_root { position:absolute; inset:0; display:flex; }\n #__art_dpip_root > * { width:100% !important; height:100% !important; }\n ",i(r),!t.querySelector('meta[name="viewport"]')){const e=t.createElement("meta");e.name="viewport",e.content="width=device-width,initial-scale=1",i(e)}try{e.querySelectorAll('link[rel="stylesheet"]').forEach(e=>{const n=t.createElement("link");n.rel="stylesheet",n.href=e.href,e.media&&(n.media=e.media),e.crossOrigin&&(n.crossOrigin=e.crossOrigin),e.referrerPolicy&&(n.referrerPolicy=e.referrerPolicy),i(n)})}catch{}try{e.querySelectorAll("style").forEach(e=>{const n=t.createElement("style");n.textContent=e.textContent,i(n)})}catch{}}(i,n,e=>u.push(e),()=>!a),!a){const e=n.adoptNode(t);a||s.appendChild(e)}a&&p()}},destroy(){a||(a=!0,p())}}}(l,t,o.placeholder),activate(e){c&&l&&(e?u.addClass(l,"artplayer-document-pip"):u.removeClass(l,"artplayerLine truncated
!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerPluginDocumentPip=t(),define(function(){return e.artplayerPluginDocumentPip})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginDocumentPip=t()}(this,function(){"use strict";function e(e){const t=[];for(const o of e)try{o()}catch(n){t.push(n)}return t}const t=".artplayer-document-pip.art-video-player{width:100%!important;height:100%!important}";function n(t){let n=!1,o=0,i=null,r=null,c=null;const l=()=>!n&&t.alive(),s=e=>e===o&&l();function u(){o++,r?.finish(),r=null,c?.cancel(),c=null}function a(t){const n=e(t.releases.splice(0));return n.push(...e([()=>t.window.close()])),n}async function d(e){if(!s(e))return;const n=function(){let e;const t=new Promise(t=>{e=t});let n=setTimeout(()=>{n=null,e()},100);return{promise:t,cancel(){null!==n&&clearTimeout(n),n=null,e()}}}();c=n,await n.promise,c===n&&(c=null),s(e)&&t.resize()}async function p(){u();const e=o,n=i;if(i=null,!n)return;const r=a(n);if(n.announced)try{t.activate(!1)}catch(c){r.push(c)}r.length&&l()&&t.report("close",r[0]),s(e)&&await d(e)}return{get active(){return null!==i},get opening(){return null!==r},open:async function(){if(!l()||i)return;if(r)return r.promise;u();const n=o;let c,f;const m=new Promise((e,t)=>{c=e,f=t}),h={promise:m,finish:c};r=h;const y=()=>{r===h&&(r=null),c()},g=o=>{if(s(n)){const n=i;i=null,n&&(a(n),n.announced&&e([()=>t.activate(!1)]));try{t.report("open",o)}catch(r){f(r)}}},v=async o=>{if(!s(n))return void(i?.window!==o&&e([()=>o.close()]));const r={window:o,releases:[],announced:!1};i=r;try{const e=t.project(o.document);if(r.releases.push(e.destroy),e.mount(),!s(n))return void a(r);for(const[i,c]of[["resize",()=>{s(n)&&t.nativeResize()}],["pagehide",()=>{p()}],["unload",()=>{p()}]])if(r.releases.unshift(()=>o.removeEventListener(i,c)),o.addEventListener(i,c),!s(n))return void a(r);r.announced=!0,t.activate(!0),await d(n)}catch(c){g(c)}};try{const e=t.request();Promise.resolve(e).then(v,g).then(y,e=>{s(n)&&f(e),y()})}catch(w){try{g(w)}finally{y()}}return m},close:p,destroy(){n||(n=!0,p().catch(()=>{}))}}}function o(t={}){const o={width:480,height:270,fallbackToVideoPiP:!0,placeholder:"Playing in Document Picture-in-Picture",...t};return t=>{const i=window,r="documentPictureInPicture"in i&&"function"===typeof i.documentPictureInPicture?.requestWindow;let c=t,l=t.template.$player,s=t.isDestroy;const u=t.constructor.utils,a=()=>!s&&!!c&&!c.isDestroy,d=n({alive:a,request:()=>i.documentPictureInPicture.requestWindow({width:o.width,height:o.height}),project:t=>function(t,n,o){const i=t.ownerDocument,r=t.parentNode,c=t.nextSibling;if(!r)throw new Error("Document Picture-in-Picture requires a mounted player");const l=i.createElement("div");l.className="artplayer-document-pip-placeholder",l.style.cssText="display:flex;justify-content:center;align-items:center;width:100%;height:100%;",l.textContent=o??"";const s=n.createElement("div");s.id="__art_dpip_root";const u=[];let a=!1;const d=()=>{const e=l.parentNode===r?l:c?.parentNode===r?c:null;if(t.parentNode!==r||t.nextSibling!==e)try{r.insertBefore(t,e)}catch(n){throw i.body.appendChild(t),n}},p=()=>{const t=e([d,()=>l.remove(),...u.splice(0).map(e=>()=>e.remove()),()=>s.remove()]);if(t.length)throw t[0]};return{mount(){if(!a){if(r.insertBefore(l,c?.parentNode===r?c:null),a||n.body.appendChild(s),a||function(e,t,n,o){const i=e=>{o()&&(n(e),t.head.appendChild(e),o()||e.remove())},r=t.createElement("style");if(r.textContent="\n html, body { margin:0; padding:0; width:100%; height:100%; background:#000; overflow:hidden; }\n #__art_dpip_root { position:absolute; inset:0; display:flex; }\n #__art_dpip_root > * { width:100% !important; height:100% !important; }\n ",i(r),!t.querySelector('meta[name="viewport"]')){const e=t.createElement("meta");e.name="viewport",e.content="width=device-width,initial-scale=1",i(e)}try{e.querySelectorAll('link[rel="stylesheet"]').forEach(e=>{const n=t.createElement("link");n.rel="stylesheet",n.href=e.href,e.media&&(n.media=e.media),e.crossOrigin&&(n.crossOrigin=e.crossOrigin),e.referrerPolicy&&(n.referrerPolicy=e.referrerPolicy),i(n)})}catch{}try{e.querySelectorAll("style").forEach(e=>{const n=t.createElement("style");n.textContent=e.textContent,i(n)})}catch{}}(i,n,e=>u.push(e),()=>!a),!a){const e=n.adoptNode(t);a||s.appendChild(e)}a&&p()}},destroy(){a||(a=!0,p())}}}(l,t,o.placeholder),activate(e){c&&l&&(e?u.addClass(l,"artplayer-document-pip"):u.removeClass(l,"artplayer-document-pip"),a()&&(c.events.bindGlobalEvents?.(),a()&&c.emit("document-pip",e)))},resize:()=>{a()&&c.emit("resize")},nativeResize:()=>{a()&&c.resize?.()},report(e,t){a()&&(c.notice.show=`Document Picture-in-Picture ${e} failed`,console.warn(`[artplayer-plugin-document-pip] ${e} failed:`,t))}});async function p(){if(a())return!r&&o.fallbackToVideoPiP?(c.pip=!0,void console.warn("[artplayer-plugin-document-pip] Document PiLine truncated
@@ -4,4 +4,4 @@
* (c) 2017-2026 Harvey Zhao
* Released under the MIT License.
*/
!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerPluginDocumentPip=t(),define(function(){return e.artplayerPluginDocumentPip})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginDocumentPip=t()}(this,function(){"use strict";var e=Object.defineProperty,t=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,o=Object.prototype.propertyIsEnumerable,r=(t,n,o)=>n in t?e(t,n,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[n]=o,i=(e,t,n)=>new Promise((o,r)=>{var i=e=>{try{c(n.next(e))}catch(t){r(t)}},l=e=>{try{c(n.throw(e))}catch(t){r(t)}},c=e=>e.done?o(e.value):Promise.resolve(e.value).then(i,l);c((n=n.apply(e,t)).next())});function l(e){const t=[];for(const o of e)try{o()}catch(n){t.push(n)}return t}const c=".artplayer-document-pip.art-video-player{width:100%!important;height:100%!important}";function u(e){let t=!1,n=0,o=null,r=null,c=null;const u=()=>!t&&e.alive(),s=e=>e===n&&u();function a(){n++,null==r||r.finish(),r=null,null==c||c.cancel(),c=null}function d(e){const t=l(e.releases.splice(0));return t.push(...l([()=>e.window.close()])),t}function p(t){return i(this,null,function*(){if(!s(t))return;const n=function(){let e;const t=new Promise(t=>{e=t});let n=setTimeout(()=>{n=null,e()},100);return{promise:t,cancel(){null!==n&&clearTimeout(n),n=null,e()}}}();c=n,yield n.promise,c===n&&(c=null),s(t)&&e.resize()})}function f(){return i(this,null,function*(){a();const t=n,r=o;if(o=null,!r)return;const i=d(r);if(r.announced)try{e.activate(!1)}catch(l){i.push(l)}i.length&&u()&&e.report("close",i[0]),s(t)&&(yield p(t))})}return{get active(){return null!==o},get opening(){return null!==r},open:function(){return i(this,null,function*(){if(!u()||o)return;if(r)return r.promise;a();const t=n;let c,m;const h=new Promise((e,t)=>{c=e,m=t}),y={promise:h,finish:c};r=y;const v=()=>{r===y&&(r=null),c()},g=n=>{if(s(t)){const t=o;o=null,t&&(d(t),t.announced&&l([()=>e.activate(!1)]));try{e.report("open",n)}catch(r){m(r)}}},P=n=>i(null,null,function*(){if(!s(t))return void((null==o?void 0:o.window)!==n&&l([()=>n.close()]));const r={window:n,releases:[],announced:!1};o=r;try{const o=e.project(n.document);if(r.releases.push(o.destroy),o.mount(),!s(t))return void d(r);for(const[i,l]of[["resize",()=>{s(t)&&e.nativeResize()}],["pagehide",()=>{f()}],["unload",()=>{f()}]])if(r.releases.unshift(()=>n.removeEventListener(i,l)),n.addEventListener(i,l),!s(t))return void d(r);r.announced=!0,e.activate(!0),yield p(t)}catch(i){g(i)}});try{const n=e.request();Promise.resolve(n).then(P,g).then(v,e=>{s(t)&&m(e),v()})}catch(w){try{g(w)}finally{v()}}return h})},close:f,destroy(){t||(t=!0,f().catch(()=>{}))}}}return"undefined"!==typeof document&&function(e){const t="artplayer-plugin-document-pip",n=e.getElementById(t);if(n)return void(n.textContent=c);const o=e.createElement("style");o.id=t,o.textContent=c;const r=()=>{e.removeEventListener("DOMContentLoaded",r);const n=e.getElementById(t);n?n.textContent=c:(e.head||e.documentElement).appendChild(o)};"loading"===e.readyState?e.addEventListener("DOMContentLoaded",r):r()}(document),function(e={}){const c=((e,i)=>{for(var l in i||(i={}))n.call(i,l)&&r(e,l,i[l]);if(t)for(var l of t(i))o.call(i,l)&&r(e,l,i[l]);return e})({width:480,height:270,fallbackToVideoPiP:!0,placeholder:"Playing in Document Picture-in-Picture"},e);return e=>{var t;const n=window,o="documentPictureInPicture"in n&&"function"===typeof(null==(t=n.documentPictureInPicture)?void 0:t.requestWindow);let r=e,s=e.template.$player,a=e.isDestroy;const d=e.constructor.utils,p=()=>!a&&!!r&&!r.isDestroy,f=u({alive:p,request:()=>n.documentPictureInPicture.requestWindow({width:c.width,height:c.height}),project:e=>function(e,t,n){const o=e.ownerDocument,r=e.parentNode,i=e.nextSibling;if(!r)throw new Error("Document Picture-in-Picture requires a mounted player");const c=o.createElement("div");c.className="artplayer-document-pip-placeholder",c.style.cssText="display:flex;justify-content:center;align-items:center;width:100%;height:100%;",c.textContent=null!=n?n:"";const u=t.createElement("div");u.id="__art_dpip_root";const s=[];let a=!1;const d=()=>{const t=c.parentNode===r?c:(null==i?void 0:i.parentNode)===r?i:null;if(e.parentNode!==r||e.nextSibling!==t)try{r.insertBefore(e,t)}catch(n){throw o.body.appendChild(e),n}},p=()=>{const e=l([d,()=>c.remove(),...s.splice(0).map(e=>()=>e.remove()),()=>u.remove()]);if(e.length)throw e[0]};return{mount(){if(!a){if(r.insertBefore(c,(null==i?void 0:i.parentNode)===r?i:null),a||t.body.appendChild(u),a||function(e,t,n,o){const r=e=>{o()&&(n(e),t.head.appendChild(e),o()||e.remove())},i=t.createElement("style");if(i.textContent="\n html, body { margin:0; padding:0; width:100%; height:100%; background:#000; overflow:hidden; }\n #__art_dpip_root { position:absolute; inset:0; display:flex; }\n #__art_dpip_root > * { width:100% !important; height:100% !important; }\n ",r(i),!t.querySelectorLine truncated
!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerPluginDocumentPip=t(),define(function(){return e.artplayerPluginDocumentPip})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginDocumentPip=t()}(this,function(){"use strict";var e=Object.defineProperty,t=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,o=Object.prototype.propertyIsEnumerable,r=(t,n,o)=>n in t?e(t,n,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[n]=o,i=(e,t,n)=>new Promise((o,r)=>{var i=e=>{try{c(n.next(e))}catch(t){r(t)}},l=e=>{try{c(n.throw(e))}catch(t){r(t)}},c=e=>e.done?o(e.value):Promise.resolve(e.value).then(i,l);c((n=n.apply(e,t)).next())});function l(e){const t=[];for(const o of e)try{o()}catch(n){t.push(n)}return t}const c=".artplayer-document-pip.art-video-player{width:100%!important;height:100%!important}";function u(e){let t=!1,n=0,o=null,r=null,c=null;const u=()=>!t&&e.alive(),s=e=>e===n&&u();function a(){n++,null==r||r.finish(),r=null,null==c||c.cancel(),c=null}function d(e){const t=l(e.releases.splice(0));return t.push(...l([()=>e.window.close()])),t}function p(t){return i(this,null,function*(){if(!s(t))return;const n=function(){let e;const t=new Promise(t=>{e=t});let n=setTimeout(()=>{n=null,e()},100);return{promise:t,cancel(){null!==n&&clearTimeout(n),n=null,e()}}}();c=n,yield n.promise,c===n&&(c=null),s(t)&&e.resize()})}function f(){return i(this,null,function*(){a();const t=n,r=o;if(o=null,!r)return;const i=d(r);if(r.announced)try{e.activate(!1)}catch(l){i.push(l)}i.length&&u()&&e.report("close",i[0]),s(t)&&(yield p(t))})}return{get active(){return null!==o},get opening(){return null!==r},open:function(){return i(this,null,function*(){if(!u()||o)return;if(r)return r.promise;a();const t=n;let c,m;const h=new Promise((e,t)=>{c=e,m=t}),y={promise:h,finish:c};r=y;const v=()=>{r===y&&(r=null),c()},g=n=>{if(s(t)){const t=o;o=null,t&&(d(t),t.announced&&l([()=>e.activate(!1)]));try{e.report("open",n)}catch(r){m(r)}}},P=n=>i(null,null,function*(){if(!s(t))return void((null==o?void 0:o.window)!==n&&l([()=>n.close()]));const r={window:n,releases:[],announced:!1};o=r;try{const o=e.project(n.document);if(r.releases.push(o.destroy),o.mount(),!s(t))return void d(r);for(const[i,l]of[["resize",()=>{s(t)&&e.nativeResize()}],["pagehide",()=>{f()}],["unload",()=>{f()}]])if(r.releases.unshift(()=>n.removeEventListener(i,l)),n.addEventListener(i,l),!s(t))return void d(r);r.announced=!0,e.activate(!0),yield p(t)}catch(i){g(i)}});try{const n=e.request();Promise.resolve(n).then(P,g).then(v,e=>{s(t)&&m(e),v()})}catch(w){try{g(w)}finally{v()}}return h})},close:f,destroy(){t||(t=!0,f().catch(()=>{}))}}}function s(e={}){const c=((e,i)=>{for(var l in i||(i={}))n.call(i,l)&&r(e,l,i[l]);if(t)for(var l of t(i))o.call(i,l)&&r(e,l,i[l]);return e})({width:480,height:270,fallbackToVideoPiP:!0,placeholder:"Playing in Document Picture-in-Picture"},e);return e=>{var t;const n=window,o="documentPictureInPicture"in n&&"function"===typeof(null==(t=n.documentPictureInPicture)?void 0:t.requestWindow);let r=e,s=e.template.$player,a=e.isDestroy;const d=e.constructor.utils,p=()=>!a&&!!r&&!r.isDestroy,f=u({alive:p,request:()=>n.documentPictureInPicture.requestWindow({width:c.width,height:c.height}),project:e=>function(e,t,n){const o=e.ownerDocument,r=e.parentNode,i=e.nextSibling;if(!r)throw new Error("Document Picture-in-Picture requires a mounted player");const c=o.createElement("div");c.className="artplayer-document-pip-placeholder",c.style.cssText="display:flex;justify-content:center;align-items:center;width:100%;height:100%;",c.textContent=null!=n?n:"";const u=t.createElement("div");u.id="__art_dpip_root";const s=[];let a=!1;const d=()=>{const t=c.parentNode===r?c:(null==i?void 0:i.parentNode)===r?i:null;if(e.parentNode!==r||e.nextSibling!==t)try{r.insertBefore(e,t)}catch(n){throw o.body.appendChild(e),n}},p=()=>{const e=l([d,()=>c.remove(),...s.splice(0).map(e=>()=>e.remove()),()=>u.remove()]);if(e.length)throw e[0]};return{mount(){if(!a){if(r.insertBefore(c,(null==i?void 0:i.parentNode)===r?i:null),a||t.body.appendChild(u),a||function(e,t,n,o){const r=e=>{o()&&(n(e),t.head.appendChild(e),o()||e.remove())},i=t.createElement("style");if(i.textContent="\n html, body { margin:0; padding:0; width:100%; height:100%; background:#000; overflow:hidden; }\n #__art_dpip_root { position:absolute; inset:0; display:flex; }\n #__art_dpip_root > * { width:100% !important; height:100% !important; }\n ",r(i),!t.querySelector('meta[name="viewport"]')){const e=t.createElement("meta");e.name="viewport",e.content="width=device-width,initial-scale=1",r(e)}try{e.querySelectorAll('link[rel="stylesheet"]').forEach(e=>{const n=t.createElement("link");n.rel="stylesheet",n.href=e.href,e.media&&(n.media=e.media),e.crossOrigin&&(n.crossOrigin=e.crossOrigin),e.referrerPolicy&&(n.referrerPolicy=e.referrerPolicy),r(n)})}catch(l){}try{e.querySelectorAll("styleLine truncated
@@ -473,8 +473,9 @@ function artplayerPluginDocumentPip(userOptions = {}) {
return result;
};
}
const index = Object.assign(artplayerPluginDocumentPip, { default: artplayerPluginDocumentPip });
if (typeof document !== "undefined")
installStyle(document);
export {
artplayerPluginDocumentPip as default
index as default
};
+2 -1
View File
@@ -74,7 +74,8 @@
"test:ambilight-types-package": "node refactor/scripts/ambilight-package-types.mjs",
"test:canvas": "node --test test/canvas.test.js test/canvas-lifecycle.test.js",
"test:canvas-types-package": "node refactor/scripts/canvas-package-types.mjs",
"test:dpip": "node --test test/dpip.test.js test/dpip-lifecycle.test.js"
"test:dpip": "node --test test/dpip.test.js test/dpip-lifecycle.test.js",
"test:dpip-types-package": "node refactor/scripts/dpip-package-types.mjs"
},
"browserslist": "last 1 Chrome version",
"devDependencies": {
@@ -3,8 +3,14 @@
The public factory still returns a synchronous plugin initializer. Its result has
`name`, readonly runtime getters `isSupported`/`isActive`, async `open`/`close`
returning `Promise<void>`, and synchronous `toggle` returning `undefined`.
The published declarations currently describe void actions and writable flags;
public declaration compatibility is tracked separately in PKG-DPIP-04.
The public `Result` preserves published void actions and writable flags for legacy
assignments. `AsyncResult` is an opt-in precise view for an unmodified runtime
result, and the implementation is checked against it. The default factory keeps
its exact published required-argument signature, including plain replacement
function assignments. RuntimeFactory explicitly describes omitted options and
self `.default` access. `.d.mts` and `.d.cts` wrappers map ESM/CJS consumers; old resolvers
use the base declaration and legacy typesVersions path. A self `.default` alias
supports the two historical runtime export shapes without adding named exports.
| File | Responsibility |
| --- | --- |
@@ -68,5 +74,7 @@ file for browser verification and never silently falls back to source.
The iframe matrix uses real DOM with controlled window APIs. It does not prove
native Document PiP activation, window focus/keyboard, continuous playback or
device support. Native video/Canvas/Mediabunny combinations and the observed
WebKit dimension reports remain PKG-DPIP-05. Full archive/demo/type acceptance is
PKG-DPIP-04/06. See the repository `refactor/dpip-validation.md` for exact evidence.
WebKit dimension reports remain PKG-DPIP-05. Full archive/demo acceptance is
PKG-DPIP-06. Installed type consumers are verified by `yarn test:dpip-types-package`;
historical missing runtime/type entry errors are exact negative cases, not waived
candidate failures. See the repository `refactor/dpip-validation.md` for evidence.
@@ -6,6 +6,59 @@ Document PIP plugin for ArtPlayer
[https://artplayer.org](https://artplayer.org/?libs=./uncompiled/artplayer-plugin-document-pip/index.js&example=document.pip)
## TypeScript and module formats
```ts
import Artplayer from 'artplayer'
import type { AsyncResult } from 'artplayer-plugin-document-pip'
import documentPip from 'artplayer-plugin-document-pip'
const art = new Artplayer({
container: '#player',
url: 'video.mp4',
plugins: [documentPip({ width: 480, height: 270 })],
})
// Use this view for an unmodified plugin result when precise Promise types are needed.
const pip = art.plugins.artplayerPluginDocumentPip as AsyncResult
await pip.open()
await pip.close()
```
At runtime, options may be omitted. Width and height default to 480 and 270, and
`fallbackToVideoPiP` defaults to true. `placeholder` sets the text left in the
original player container while its document window is active.
The default `Result` retains the published writable boolean fields and void
actions so old assignments and inferred initializer types still compile.
At runtime, `isSupported` and `isActive` are readonly getters, `open` and `close`
return `Promise<void>`, and `toggle` returns `undefined`. The opt-in `AsyncResult`
describes those runtime values; it should not be applied to a mock or a result
whose methods have been replaced. It does not change any runtime behavior.
The default factory declaration keeps the exact published required-argument
signature, including assignment of an old replacement function to `typeof
documentPip`. Automatically adding an optional overload or a required `.default`
property would break such assignments. `Option`, `Result`, `AsyncResult`, `Factory`
and `RuntimeFactory` are available as named types. Use the explicit runtime view
to type omitted options, self `.default` access and precise async results:
```ts
import type { RuntimeFactory } from 'artplayer-plugin-document-pip'
const runtimeFactory = documentPip as RuntimeFactory
runtimeFactory() // precise initializer for the unmodified runtime factory
```
ESM uses the default import. CommonJS supports both `require(package)(options)`
and the historical `require(package).default(options)` shape; `.default` is the
same factory. The `/legacy` entry and generated browser editor declarations have
matching types. These syntax targets do not add native Document PiP support to
browsers that lack the API.
The historical TypeScript `import plugin = require(package)` module view retains
`plugin.default(options)`. Direct CommonJS calls are available at runtime; use
`RuntimeFactory` for an explicitly typed direct-call view.
## Maintenance
Source is split into strict TypeScript modules for window ownership, DOM migration,
@@ -4,4 +4,4 @@
* (c) 2017-2026 Harvey Zhao
* Released under the MIT License.
*/
!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerPluginDocumentPip=t(),define(function(){return e.artplayerPluginDocumentPip})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginDocumentPip=t()}(this,function(){"use strict";function e(e){const t=[];for(const o of e)try{o()}catch(n){t.push(n)}return t}const t=".artplayer-document-pip.art-video-player{width:100%!important;height:100%!important}";function n(t){let n=!1,o=0,i=null,r=null,c=null;const l=()=>!n&&t.alive(),s=e=>e===o&&l();function u(){o++,r?.finish(),r=null,c?.cancel(),c=null}function a(t){const n=e(t.releases.splice(0));return n.push(...e([()=>t.window.close()])),n}async function d(e){if(!s(e))return;const n=function(){let e;const t=new Promise(t=>{e=t});let n=setTimeout(()=>{n=null,e()},100);return{promise:t,cancel(){null!==n&&clearTimeout(n),n=null,e()}}}();c=n,await n.promise,c===n&&(c=null),s(e)&&t.resize()}async function p(){u();const e=o,n=i;if(i=null,!n)return;const r=a(n);if(n.announced)try{t.activate(!1)}catch(c){r.push(c)}r.length&&l()&&t.report("close",r[0]),s(e)&&await d(e)}return{get active(){return null!==i},get opening(){return null!==r},open:async function(){if(!l()||i)return;if(r)return r.promise;u();const n=o;let c,f;const m=new Promise((e,t)=>{c=e,f=t}),h={promise:m,finish:c};r=h;const y=()=>{r===h&&(r=null),c()},g=o=>{if(s(n)){const n=i;i=null,n&&(a(n),n.announced&&e([()=>t.activate(!1)]));try{t.report("open",o)}catch(r){f(r)}}},v=async o=>{if(!s(n))return void(i?.window!==o&&e([()=>o.close()]));const r={window:o,releases:[],announced:!1};i=r;try{const e=t.project(o.document);if(r.releases.push(e.destroy),e.mount(),!s(n))return void a(r);for(const[i,c]of[["resize",()=>{s(n)&&t.nativeResize()}],["pagehide",()=>{p()}],["unload",()=>{p()}]])if(r.releases.unshift(()=>o.removeEventListener(i,c)),o.addEventListener(i,c),!s(n))return void a(r);r.announced=!0,t.activate(!0),await d(n)}catch(c){g(c)}};try{const e=t.request();Promise.resolve(e).then(v,g).then(y,e=>{s(n)&&f(e),y()})}catch(w){try{g(w)}finally{y()}}return m},close:p,destroy(){n||(n=!0,p().catch(()=>{}))}}}return"undefined"!==typeof document&&function(e){const n="artplayer-plugin-document-pip",o=e.getElementById(n);if(o)return void(o.textContent=t);const i=e.createElement("style");i.id=n,i.textContent=t;const r=()=>{e.removeEventListener("DOMContentLoaded",r);const o=e.getElementById(n);o?o.textContent=t:(e.head||e.documentElement).appendChild(i)};"loading"===e.readyState?e.addEventListener("DOMContentLoaded",r):r()}(document),function(t={}){const o={width:480,height:270,fallbackToVideoPiP:!0,placeholder:"Playing in Document Picture-in-Picture",...t};return t=>{const i=window,r="documentPictureInPicture"in i&&"function"===typeof i.documentPictureInPicture?.requestWindow;let c=t,l=t.template.$player,s=t.isDestroy;const u=t.constructor.utils,a=()=>!s&&!!c&&!c.isDestroy,d=n({alive:a,request:()=>i.documentPictureInPicture.requestWindow({width:o.width,height:o.height}),project:t=>function(t,n,o){const i=t.ownerDocument,r=t.parentNode,c=t.nextSibling;if(!r)throw new Error("Document Picture-in-Picture requires a mounted player");const l=i.createElement("div");l.className="artplayer-document-pip-placeholder",l.style.cssText="display:flex;justify-content:center;align-items:center;width:100%;height:100%;",l.textContent=o??"";const s=n.createElement("div");s.id="__art_dpip_root";const u=[];let a=!1;const d=()=>{const e=l.parentNode===r?l:c?.parentNode===r?c:null;if(t.parentNode!==r||t.nextSibling!==e)try{r.insertBefore(t,e)}catch(n){throw i.body.appendChild(t),n}},p=()=>{const t=e([d,()=>l.remove(),...u.splice(0).map(e=>()=>e.remove()),()=>s.remove()]);if(t.length)throw t[0]};return{mount(){if(!a){if(r.insertBefore(l,c?.parentNode===r?c:null),a||n.body.appendChild(s),a||function(e,t,n,o){const i=e=>{o()&&(n(e),t.head.appendChild(e),o()||e.remove())},r=t.createElement("style");if(r.textContent="\n html, body { margin:0; padding:0; width:100%; height:100%; background:#000; overflow:hidden; }\n #__art_dpip_root { position:absolute; inset:0; display:flex; }\n #__art_dpip_root > * { width:100% !important; height:100% !important; }\n ",i(r),!t.querySelector('meta[name="viewport"]')){const e=t.createElement("meta");e.name="viewport",e.content="width=device-width,initial-scale=1",i(e)}try{e.querySelectorAll('link[rel="stylesheet"]').forEach(e=>{const n=t.createElement("link");n.rel="stylesheet",n.href=e.href,e.media&&(n.media=e.media),e.crossOrigin&&(n.crossOrigin=e.crossOrigin),e.referrerPolicy&&(n.referrerPolicy=e.referrerPolicy),i(n)})}catch{}try{e.querySelectorAll("style").forEach(e=>{const n=t.createElement("style");n.textContent=e.textContent,i(n)})}catch{}}(i,n,e=>u.push(e),()=>!a),!a){const e=n.adoptNode(t);a||s.appendChild(e)}a&&p()}},destroy(){a||(a=!0,p())}}}(l,t,o.placeholder),activate(e){c&&l&&(e?u.addClass(l,"artplayer-document-pip"):u.removeClass(l,"artplayerLine truncated
!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerPluginDocumentPip=t(),define(function(){return e.artplayerPluginDocumentPip})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginDocumentPip=t()}(this,function(){"use strict";function e(e){const t=[];for(const o of e)try{o()}catch(n){t.push(n)}return t}const t=".artplayer-document-pip.art-video-player{width:100%!important;height:100%!important}";function n(t){let n=!1,o=0,i=null,r=null,c=null;const l=()=>!n&&t.alive(),s=e=>e===o&&l();function u(){o++,r?.finish(),r=null,c?.cancel(),c=null}function a(t){const n=e(t.releases.splice(0));return n.push(...e([()=>t.window.close()])),n}async function d(e){if(!s(e))return;const n=function(){let e;const t=new Promise(t=>{e=t});let n=setTimeout(()=>{n=null,e()},100);return{promise:t,cancel(){null!==n&&clearTimeout(n),n=null,e()}}}();c=n,await n.promise,c===n&&(c=null),s(e)&&t.resize()}async function p(){u();const e=o,n=i;if(i=null,!n)return;const r=a(n);if(n.announced)try{t.activate(!1)}catch(c){r.push(c)}r.length&&l()&&t.report("close",r[0]),s(e)&&await d(e)}return{get active(){return null!==i},get opening(){return null!==r},open:async function(){if(!l()||i)return;if(r)return r.promise;u();const n=o;let c,f;const m=new Promise((e,t)=>{c=e,f=t}),h={promise:m,finish:c};r=h;const y=()=>{r===h&&(r=null),c()},g=o=>{if(s(n)){const n=i;i=null,n&&(a(n),n.announced&&e([()=>t.activate(!1)]));try{t.report("open",o)}catch(r){f(r)}}},v=async o=>{if(!s(n))return void(i?.window!==o&&e([()=>o.close()]));const r={window:o,releases:[],announced:!1};i=r;try{const e=t.project(o.document);if(r.releases.push(e.destroy),e.mount(),!s(n))return void a(r);for(const[i,c]of[["resize",()=>{s(n)&&t.nativeResize()}],["pagehide",()=>{p()}],["unload",()=>{p()}]])if(r.releases.unshift(()=>o.removeEventListener(i,c)),o.addEventListener(i,c),!s(n))return void a(r);r.announced=!0,t.activate(!0),await d(n)}catch(c){g(c)}};try{const e=t.request();Promise.resolve(e).then(v,g).then(y,e=>{s(n)&&f(e),y()})}catch(w){try{g(w)}finally{y()}}return m},close:p,destroy(){n||(n=!0,p().catch(()=>{}))}}}function o(t={}){const o={width:480,height:270,fallbackToVideoPiP:!0,placeholder:"Playing in Document Picture-in-Picture",...t};return t=>{const i=window,r="documentPictureInPicture"in i&&"function"===typeof i.documentPictureInPicture?.requestWindow;let c=t,l=t.template.$player,s=t.isDestroy;const u=t.constructor.utils,a=()=>!s&&!!c&&!c.isDestroy,d=n({alive:a,request:()=>i.documentPictureInPicture.requestWindow({width:o.width,height:o.height}),project:t=>function(t,n,o){const i=t.ownerDocument,r=t.parentNode,c=t.nextSibling;if(!r)throw new Error("Document Picture-in-Picture requires a mounted player");const l=i.createElement("div");l.className="artplayer-document-pip-placeholder",l.style.cssText="display:flex;justify-content:center;align-items:center;width:100%;height:100%;",l.textContent=o??"";const s=n.createElement("div");s.id="__art_dpip_root";const u=[];let a=!1;const d=()=>{const e=l.parentNode===r?l:c?.parentNode===r?c:null;if(t.parentNode!==r||t.nextSibling!==e)try{r.insertBefore(t,e)}catch(n){throw i.body.appendChild(t),n}},p=()=>{const t=e([d,()=>l.remove(),...u.splice(0).map(e=>()=>e.remove()),()=>s.remove()]);if(t.length)throw t[0]};return{mount(){if(!a){if(r.insertBefore(l,c?.parentNode===r?c:null),a||n.body.appendChild(s),a||function(e,t,n,o){const i=e=>{o()&&(n(e),t.head.appendChild(e),o()||e.remove())},r=t.createElement("style");if(r.textContent="\n html, body { margin:0; padding:0; width:100%; height:100%; background:#000; overflow:hidden; }\n #__art_dpip_root { position:absolute; inset:0; display:flex; }\n #__art_dpip_root > * { width:100% !important; height:100% !important; }\n ",i(r),!t.querySelector('meta[name="viewport"]')){const e=t.createElement("meta");e.name="viewport",e.content="width=device-width,initial-scale=1",i(e)}try{e.querySelectorAll('link[rel="stylesheet"]').forEach(e=>{const n=t.createElement("link");n.rel="stylesheet",n.href=e.href,e.media&&(n.media=e.media),e.crossOrigin&&(n.crossOrigin=e.crossOrigin),e.referrerPolicy&&(n.referrerPolicy=e.referrerPolicy),i(n)})}catch{}try{e.querySelectorAll("style").forEach(e=>{const n=t.createElement("style");n.textContent=e.textContent,i(n)})}catch{}}(i,n,e=>u.push(e),()=>!a),!a){const e=n.adoptNode(t);a||s.appendChild(e)}a&&p()}},destroy(){a||(a=!0,p())}}}(l,t,o.placeholder),activate(e){c&&l&&(e?u.addClass(l,"artplayer-document-pip"):u.removeClass(l,"artplayer-document-pip"),a()&&(c.events.bindGlobalEvents?.(),a()&&c.emit("document-pip",e)))},resize:()=>{a()&&c.emit("resize")},nativeResize:()=>{a()&&c.resize?.()},report(e,t){a()&&(c.notice.show=`Document Picture-in-Picture ${e} failed`,console.warn(`[artplayer-plugin-document-pip] ${e} failed:`,t))}});async function p(){if(a())return!r&&o.fallbackToVideoPiP?(c.pip=!0,void console.warn("[artplayer-plugin-document-pip] Document PiLine truncated
@@ -4,4 +4,4 @@
* (c) 2017-2026 Harvey Zhao
* Released under the MIT License.
*/
!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerPluginDocumentPip=t(),define(function(){return e.artplayerPluginDocumentPip})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginDocumentPip=t()}(this,function(){"use strict";var e=Object.defineProperty,t=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,o=Object.prototype.propertyIsEnumerable,r=(t,n,o)=>n in t?e(t,n,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[n]=o,i=(e,t,n)=>new Promise((o,r)=>{var i=e=>{try{c(n.next(e))}catch(t){r(t)}},l=e=>{try{c(n.throw(e))}catch(t){r(t)}},c=e=>e.done?o(e.value):Promise.resolve(e.value).then(i,l);c((n=n.apply(e,t)).next())});function l(e){const t=[];for(const o of e)try{o()}catch(n){t.push(n)}return t}const c=".artplayer-document-pip.art-video-player{width:100%!important;height:100%!important}";function u(e){let t=!1,n=0,o=null,r=null,c=null;const u=()=>!t&&e.alive(),s=e=>e===n&&u();function a(){n++,null==r||r.finish(),r=null,null==c||c.cancel(),c=null}function d(e){const t=l(e.releases.splice(0));return t.push(...l([()=>e.window.close()])),t}function p(t){return i(this,null,function*(){if(!s(t))return;const n=function(){let e;const t=new Promise(t=>{e=t});let n=setTimeout(()=>{n=null,e()},100);return{promise:t,cancel(){null!==n&&clearTimeout(n),n=null,e()}}}();c=n,yield n.promise,c===n&&(c=null),s(t)&&e.resize()})}function f(){return i(this,null,function*(){a();const t=n,r=o;if(o=null,!r)return;const i=d(r);if(r.announced)try{e.activate(!1)}catch(l){i.push(l)}i.length&&u()&&e.report("close",i[0]),s(t)&&(yield p(t))})}return{get active(){return null!==o},get opening(){return null!==r},open:function(){return i(this,null,function*(){if(!u()||o)return;if(r)return r.promise;a();const t=n;let c,m;const h=new Promise((e,t)=>{c=e,m=t}),y={promise:h,finish:c};r=y;const v=()=>{r===y&&(r=null),c()},g=n=>{if(s(t)){const t=o;o=null,t&&(d(t),t.announced&&l([()=>e.activate(!1)]));try{e.report("open",n)}catch(r){m(r)}}},P=n=>i(null,null,function*(){if(!s(t))return void((null==o?void 0:o.window)!==n&&l([()=>n.close()]));const r={window:n,releases:[],announced:!1};o=r;try{const o=e.project(n.document);if(r.releases.push(o.destroy),o.mount(),!s(t))return void d(r);for(const[i,l]of[["resize",()=>{s(t)&&e.nativeResize()}],["pagehide",()=>{f()}],["unload",()=>{f()}]])if(r.releases.unshift(()=>n.removeEventListener(i,l)),n.addEventListener(i,l),!s(t))return void d(r);r.announced=!0,e.activate(!0),yield p(t)}catch(i){g(i)}});try{const n=e.request();Promise.resolve(n).then(P,g).then(v,e=>{s(t)&&m(e),v()})}catch(w){try{g(w)}finally{v()}}return h})},close:f,destroy(){t||(t=!0,f().catch(()=>{}))}}}return"undefined"!==typeof document&&function(e){const t="artplayer-plugin-document-pip",n=e.getElementById(t);if(n)return void(n.textContent=c);const o=e.createElement("style");o.id=t,o.textContent=c;const r=()=>{e.removeEventListener("DOMContentLoaded",r);const n=e.getElementById(t);n?n.textContent=c:(e.head||e.documentElement).appendChild(o)};"loading"===e.readyState?e.addEventListener("DOMContentLoaded",r):r()}(document),function(e={}){const c=((e,i)=>{for(var l in i||(i={}))n.call(i,l)&&r(e,l,i[l]);if(t)for(var l of t(i))o.call(i,l)&&r(e,l,i[l]);return e})({width:480,height:270,fallbackToVideoPiP:!0,placeholder:"Playing in Document Picture-in-Picture"},e);return e=>{var t;const n=window,o="documentPictureInPicture"in n&&"function"===typeof(null==(t=n.documentPictureInPicture)?void 0:t.requestWindow);let r=e,s=e.template.$player,a=e.isDestroy;const d=e.constructor.utils,p=()=>!a&&!!r&&!r.isDestroy,f=u({alive:p,request:()=>n.documentPictureInPicture.requestWindow({width:c.width,height:c.height}),project:e=>function(e,t,n){const o=e.ownerDocument,r=e.parentNode,i=e.nextSibling;if(!r)throw new Error("Document Picture-in-Picture requires a mounted player");const c=o.createElement("div");c.className="artplayer-document-pip-placeholder",c.style.cssText="display:flex;justify-content:center;align-items:center;width:100%;height:100%;",c.textContent=null!=n?n:"";const u=t.createElement("div");u.id="__art_dpip_root";const s=[];let a=!1;const d=()=>{const t=c.parentNode===r?c:(null==i?void 0:i.parentNode)===r?i:null;if(e.parentNode!==r||e.nextSibling!==t)try{r.insertBefore(e,t)}catch(n){throw o.body.appendChild(e),n}},p=()=>{const e=l([d,()=>c.remove(),...s.splice(0).map(e=>()=>e.remove()),()=>u.remove()]);if(e.length)throw e[0]};return{mount(){if(!a){if(r.insertBefore(c,(null==i?void 0:i.parentNode)===r?i:null),a||t.body.appendChild(u),a||function(e,t,n,o){const r=e=>{o()&&(n(e),t.head.appendChild(e),o()||e.remove())},i=t.createElement("style");if(i.textContent="\n html, body { margin:0; padding:0; width:100%; height:100%; background:#000; overflow:hidden; }\n #__art_dpip_root { position:absolute; inset:0; display:flex; }\n #__art_dpip_root > * { width:100% !important; height:100% !important; }\n ",r(i),!t.querySelectorLine truncated
!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerPluginDocumentPip=t(),define(function(){return e.artplayerPluginDocumentPip})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginDocumentPip=t()}(this,function(){"use strict";var e=Object.defineProperty,t=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,o=Object.prototype.propertyIsEnumerable,r=(t,n,o)=>n in t?e(t,n,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[n]=o,i=(e,t,n)=>new Promise((o,r)=>{var i=e=>{try{c(n.next(e))}catch(t){r(t)}},l=e=>{try{c(n.throw(e))}catch(t){r(t)}},c=e=>e.done?o(e.value):Promise.resolve(e.value).then(i,l);c((n=n.apply(e,t)).next())});function l(e){const t=[];for(const o of e)try{o()}catch(n){t.push(n)}return t}const c=".artplayer-document-pip.art-video-player{width:100%!important;height:100%!important}";function u(e){let t=!1,n=0,o=null,r=null,c=null;const u=()=>!t&&e.alive(),s=e=>e===n&&u();function a(){n++,null==r||r.finish(),r=null,null==c||c.cancel(),c=null}function d(e){const t=l(e.releases.splice(0));return t.push(...l([()=>e.window.close()])),t}function p(t){return i(this,null,function*(){if(!s(t))return;const n=function(){let e;const t=new Promise(t=>{e=t});let n=setTimeout(()=>{n=null,e()},100);return{promise:t,cancel(){null!==n&&clearTimeout(n),n=null,e()}}}();c=n,yield n.promise,c===n&&(c=null),s(t)&&e.resize()})}function f(){return i(this,null,function*(){a();const t=n,r=o;if(o=null,!r)return;const i=d(r);if(r.announced)try{e.activate(!1)}catch(l){i.push(l)}i.length&&u()&&e.report("close",i[0]),s(t)&&(yield p(t))})}return{get active(){return null!==o},get opening(){return null!==r},open:function(){return i(this,null,function*(){if(!u()||o)return;if(r)return r.promise;a();const t=n;let c,m;const h=new Promise((e,t)=>{c=e,m=t}),y={promise:h,finish:c};r=y;const v=()=>{r===y&&(r=null),c()},g=n=>{if(s(t)){const t=o;o=null,t&&(d(t),t.announced&&l([()=>e.activate(!1)]));try{e.report("open",n)}catch(r){m(r)}}},P=n=>i(null,null,function*(){if(!s(t))return void((null==o?void 0:o.window)!==n&&l([()=>n.close()]));const r={window:n,releases:[],announced:!1};o=r;try{const o=e.project(n.document);if(r.releases.push(o.destroy),o.mount(),!s(t))return void d(r);for(const[i,l]of[["resize",()=>{s(t)&&e.nativeResize()}],["pagehide",()=>{f()}],["unload",()=>{f()}]])if(r.releases.unshift(()=>n.removeEventListener(i,l)),n.addEventListener(i,l),!s(t))return void d(r);r.announced=!0,e.activate(!0),yield p(t)}catch(i){g(i)}});try{const n=e.request();Promise.resolve(n).then(P,g).then(v,e=>{s(t)&&m(e),v()})}catch(w){try{g(w)}finally{v()}}return h})},close:f,destroy(){t||(t=!0,f().catch(()=>{}))}}}function s(e={}){const c=((e,i)=>{for(var l in i||(i={}))n.call(i,l)&&r(e,l,i[l]);if(t)for(var l of t(i))o.call(i,l)&&r(e,l,i[l]);return e})({width:480,height:270,fallbackToVideoPiP:!0,placeholder:"Playing in Document Picture-in-Picture"},e);return e=>{var t;const n=window,o="documentPictureInPicture"in n&&"function"===typeof(null==(t=n.documentPictureInPicture)?void 0:t.requestWindow);let r=e,s=e.template.$player,a=e.isDestroy;const d=e.constructor.utils,p=()=>!a&&!!r&&!r.isDestroy,f=u({alive:p,request:()=>n.documentPictureInPicture.requestWindow({width:c.width,height:c.height}),project:e=>function(e,t,n){const o=e.ownerDocument,r=e.parentNode,i=e.nextSibling;if(!r)throw new Error("Document Picture-in-Picture requires a mounted player");const c=o.createElement("div");c.className="artplayer-document-pip-placeholder",c.style.cssText="display:flex;justify-content:center;align-items:center;width:100%;height:100%;",c.textContent=null!=n?n:"";const u=t.createElement("div");u.id="__art_dpip_root";const s=[];let a=!1;const d=()=>{const t=c.parentNode===r?c:(null==i?void 0:i.parentNode)===r?i:null;if(e.parentNode!==r||e.nextSibling!==t)try{r.insertBefore(e,t)}catch(n){throw o.body.appendChild(e),n}},p=()=>{const e=l([d,()=>c.remove(),...s.splice(0).map(e=>()=>e.remove()),()=>u.remove()]);if(e.length)throw e[0]};return{mount(){if(!a){if(r.insertBefore(c,(null==i?void 0:i.parentNode)===r?i:null),a||t.body.appendChild(u),a||function(e,t,n,o){const r=e=>{o()&&(n(e),t.head.appendChild(e),o()||e.remove())},i=t.createElement("style");if(i.textContent="\n html, body { margin:0; padding:0; width:100%; height:100%; background:#000; overflow:hidden; }\n #__art_dpip_root { position:absolute; inset:0; display:flex; }\n #__art_dpip_root > * { width:100% !important; height:100% !important; }\n ",r(i),!t.querySelector('meta[name="viewport"]')){const e=t.createElement("meta");e.name="viewport",e.content="width=device-width,initial-scale=1",r(e)}try{e.querySelectorAll('link[rel="stylesheet"]').forEach(e=>{const n=t.createElement("link");n.rel="stylesheet",n.href=e.href,e.media&&(n.media=e.media),e.crossOrigin&&(n.crossOrigin=e.crossOrigin),e.referrerPolicy&&(n.referrerPolicy=e.referrerPolicy),r(n)})}catch(l){}try{e.querySelectorAll("styleLine truncated
@@ -473,8 +473,9 @@ function artplayerPluginDocumentPip(userOptions = {}) {
return result;
};
}
const index = Object.assign(artplayerPluginDocumentPip, { default: artplayerPluginDocumentPip });
if (typeof document !== "undefined")
installStyle(document);
export {
artplayerPluginDocumentPip as default
index as default
};
@@ -19,19 +19,36 @@
],
"exports": {
".": {
"types": "./types/artplayer-plugin-document-pip.d.ts",
"import": "./dist/artplayer-plugin-document-pip.mjs",
"require": "./dist/artplayer-plugin-document-pip.js"
"import": {
"types": "./types/artplayer-plugin-document-pip.d.mts",
"default": "./dist/artplayer-plugin-document-pip.mjs"
},
"require": {
"types": "./types/artplayer-plugin-document-pip.d.cts",
"default": "./dist/artplayer-plugin-document-pip.js"
}
},
"./legacy": {
"types": "./types/artplayer-plugin-document-pip.d.ts",
"import": "./dist/artplayer-plugin-document-pip.legacy.js",
"require": "./dist/artplayer-plugin-document-pip.legacy.js"
"import": {
"types": "./types/artplayer-plugin-document-pip.d.mts",
"default": "./dist/artplayer-plugin-document-pip.legacy.js"
},
"require": {
"types": "./types/artplayer-plugin-document-pip.d.cts",
"default": "./dist/artplayer-plugin-document-pip.legacy.js"
}
}
},
"main": "./dist/artplayer-plugin-document-pip.js",
"module": "./dist/artplayer-plugin-document-pip.mjs",
"types": "./types/artplayer-plugin-document-pip.d.ts",
"legacy": "./dist/artplayer-plugin-document-pip.legacy.js",
"browserslist": "last 1 Chrome version"
"browserslist": "last 1 Chrome version",
"typesVersions": {
"*": {
"legacy": [
"types/artplayer-plugin-document-pip.d.ts"
]
}
}
}
@@ -1,5 +1,5 @@
import type Artplayer from 'artplayer'
import type PublicPlugin from '../types/artplayer-plugin-document-pip'
import type { AsyncResult, Option } from '../types/artplayer-plugin-document-pip'
import type { WindowApi } from './window-session'
import { createControl } from './control'
import { createProjection } from './projection'
@@ -7,9 +7,7 @@ import { releaseAll } from './resources'
import { installStyle } from './styles'
import { createWindowSession } from './window-session'
type Option = Parameters<typeof PublicPlugin>[0]
export default function artplayerPluginDocumentPip(userOptions: Option = {}) {
function artplayerPluginDocumentPip(userOptions: Option = {}) {
const options = { width: 480, height: 270, fallbackToVideoPiP: true, placeholder: 'Playing in Document Picture-in-Picture', ...userOptions }
return (art: Artplayer) => {
const browser = window as Window & { documentPictureInPicture?: WindowApi }
@@ -83,7 +81,7 @@ export default function artplayerPluginDocumentPip(userOptions: Option = {}) {
if (errors.length)
console.warn('[artplayer-plugin-document-pip] cleanup failed:', errors[0])
}
const result = {
const result: AsyncResult = {
name: 'artplayerPluginDocumentPip' as const,
get isSupported() { return isSupported },
get isActive() { return session.active },
@@ -111,5 +109,7 @@ export default function artplayerPluginDocumentPip(userOptions: Option = {}) {
}
}
export default Object.assign(artplayerPluginDocumentPip, { default: artplayerPluginDocumentPip })
if (typeof document !== 'undefined')
installStyle(document)
@@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": { "allowJs": false },
"include": ["src/**/*.ts", "types/**/*.d.ts", "../../types/assets.d.ts"]
"include": ["src/**/*.ts", "types/**/*.d.ts", "types/**/*.d.mts", "types/**/*.d.cts", "../../types/assets.d.ts"]
}
@@ -0,0 +1,5 @@
import type { Factory } from './artplayer-plugin-document-pip.js'
declare const artplayerPluginDocumentPip: Factory
export default artplayerPluginDocumentPip
export type { AsyncResult, Factory, Option, Result, RuntimeFactory } from './artplayer-plugin-document-pip.js'
@@ -0,0 +1,5 @@
import type { Factory } from './artplayer-plugin-document-pip.js'
declare const artplayerPluginDocumentPip: Factory
export default artplayerPluginDocumentPip
export type { AsyncResult, Factory, Option, Result, RuntimeFactory } from './artplayer-plugin-document-pip.js'
@@ -1,21 +1,47 @@
import type Artplayer from 'artplayer'
interface Option {
export interface Option {
/** Requested window width. @default 480 */
width?: number
/** Requested window height. @default 270 */
height?: number
/** Text displayed in the original player container while the window is active. */
placeholder?: string
/** Use the core video PiP property when Document PiP is unavailable. @default true */
fallbackToVideoPiP?: boolean
}
interface Result {
/** Historical assignable result; preserved for direct and extracted return types. */
export interface Result {
name: 'artplayerPluginDocumentPip'
/** Runtime is a readonly capability snapshot; the published field stays assignable. */
isSupported: boolean
/** Runtime is a readonly live getter; the published field stays assignable. */
isActive: boolean
/** Runtime returns Promise<void>; the published void action remains assignable here. */
open: () => void
/** Runtime returns Promise<void>; the published void action remains assignable here. */
close: () => void
toggle: () => void
}
declare const artplayerPluginDocumentPip: (option: Option) => (art: Artplayer) => Result
/** Exact view of an unmodified runtime result. */
export interface AsyncResult extends Omit<Result, 'isSupported' | 'isActive' | 'open' | 'close'> {
readonly isSupported: boolean
readonly isActive: boolean
open: () => Promise<void>
close: () => Promise<void>
}
/** Exact published factory signature, including compatibility with replacement functions. */
export type Factory = (option: Option) => (art: Artplayer) => Result
/** Opt-in runtime view with omitted options, self default and precise async actions. */
export interface RuntimeFactory {
(option?: Option): (art: Artplayer) => AsyncResult
readonly default: RuntimeFactory
}
/** Keep the published callable type; use RuntimeFactory explicitly for its broader runtime shape. */
declare function artplayerPluginDocumentPip(option: Option): (art: Artplayer) => Result
export default artplayerPluginDocumentPip
@@ -0,0 +1,360 @@
{
"schemaVersion": 1,
"task": "PKG-DPIP-04",
"status": "done",
"checks": [
{
"command": "node --test refactor/scripts/dpip-types.test.mjs",
"result": "pass",
"tests": 4,
"scope": "five compiler modes, whole factory/direct and extracted Result replacements, four real historical declarations, fourteen invalid uses, semantic editor globals and actual three-format exports"
},
{
"command": "yarn build:ts && yarn build artplayer-plugin-document-pip",
"result": "pass",
"formats": [
"main",
"legacy",
"esm"
]
},
{
"command": "yarn test:dpip-types-package",
"result": "pass-with-exact-historical-controls",
"cases": 27,
"candidateZeroDiagnostic": 7,
"historicalZeroDiagnostic": 12,
"historicalFailureCases": 8,
"candidateInvalidUsesPerMode": 14,
"report": "refactor/.cache/dpip-package-types-2bH82Z/report.json",
"missingRuntime": "Published1.0.0 require verified as MODULE_NOT_FOUND; never substituted with Git source"
},
{
"command": "ARTPLAYER_DPIP_ARTIFACT=<main> playwright test test/browser/dpip-lifecycle.spec.js",
"result": "pass",
"tests": 18,
"skipped": 0,
"browsers": [
{
"project": "chromium",
"version": "153.0.8010.12",
"platform": "win32"
},
{
"project": "firefox",
"version": "155.0",
"platform": "win32"
},
{
"project": "webkit",
"version": "26.6",
"platform": "win32"
}
],
"scope": "Main hash matches final build after declaration-only revisions; two cores and three engines use native iframe DOM with controlled window APIs, not native Document PiP"
},
{
"command": "focused eslint --no-fix",
"result": "pass"
},
{
"command": "yarn ci:check",
"result": "pass",
"tests": {
"unit": 1006,
"engineering": 14,
"baseline": 120,
"mainTotal": 1140,
"repeatedContractExecutions": 44
},
"strictProductionTypeScriptFiles": 290
}
],
"limitations": [
"Default factory retains its exact required-argument shape to preserve whole-factory replacement assignability. RuntimeFactory explicitly provides optional options, self default and precise async results. Canvas/Ambilight factory regressions are a separate open PKG-FACTORY-01 release dependency.",
"Default Result deliberately retains published writable fields and void action inference; exact async/readonly behavior is available via the explicit AsyncResult view.",
"The 27 installed compiler cases include eight exact historical failures; candidate cases must all compile without diagnostics.",
"Published 1.0.0 runtime remains absent and is verified as MODULE_NOT_FOUND, not repaired in place.",
"Browser iframe validation controls window APIs and does not prove native Document PiP activation, media continuity, devices or proxy combinations; task05 remains.",
"Full demo and distribution acceptance remains task06."
],
"parentCommit": "80d37d66f8797ed89feff554a25d623943571974",
"inputs": [
{
"file": "packages/artplayer-plugin-document-pip/src/index.ts",
"sha256LF": "28ba9b809589f4c58acc7d36bc2bb11b75832e8e6e009487c741c5b47dc4a590"
},
{
"file": "packages/artplayer-plugin-document-pip/package.json",
"sha256LF": "5f3671f759364be52faf3810e1534a7711270f975f06d3489d95982fbae0eafb"
},
{
"file": "packages/artplayer-plugin-document-pip/tsconfig.json",
"sha256LF": "583e4ac1afa99e3a29c7f899df9fdeefcbd14d3847d69143e3fa6a8facac6d99"
},
{
"file": "packages/artplayer-plugin-document-pip/README.md",
"sha256LF": "8a6b5ff395b92dce960d92b0681640d94c7de44f1181cd02408724964d51cf48"
},
{
"file": "packages/artplayer-plugin-document-pip/ARCHITECTURE.md",
"sha256LF": "422cd5847c8c8dffece1b619644a5e441af84ddb7d727d6f03d433f9d7117af9"
},
{
"file": "packages/artplayer-plugin-document-pip/types/artplayer-plugin-document-pip.d.ts",
"sha256LF": "bea8feeec01c0711a7f669f65f18ecdc299f89101ec75ea8c001bb9a218b0663"
},
{
"file": "packages/artplayer-plugin-document-pip/types/artplayer-plugin-document-pip.d.mts",
"sha256LF": "0dd487fba4fbe05614d6d00bb6e275e9211da3bd8e8c1296e5c89a4306ed5a73"
},
{
"file": "packages/artplayer-plugin-document-pip/types/artplayer-plugin-document-pip.d.cts",
"sha256LF": "0dd487fba4fbe05614d6d00bb6e275e9211da3bd8e8c1296e5c89a4306ed5a73"
},
{
"file": "test/types/dpip.ts",
"sha256LF": "3571e661790f845e4a7d293325cb261d5cf2e57c2bccb5d05c75fb70ef150525"
},
{
"file": "refactor/fixtures/consumers/dpip-published.ts",
"sha256LF": "184e29c1e4074f786d7c582cd7a251a42ce20b34ad1baf98b5b2a2480f9e7088"
},
{
"file": "refactor/scripts/dpip-types.test.mjs",
"sha256LF": "90fcef9d140ca3cf63e97cb089fb53c4965e4d2b54741a15b15b4a7b836e86f6"
},
{
"file": "refactor/scripts/dpip-package-types.mjs",
"sha256LF": "85ef013a770e609399d84fbaf8ec559fa1771d6c66d2f99514060d9fa2425fe2"
},
{
"file": "scripts/build-ts.js",
"sha256LF": "24ea26bb5a244cbc09485c36c917a4c511d3da1dd1a3e1e14d9b0f4711b9dda6"
},
{
"file": "scripts/typecheck.mjs",
"sha256LF": "82300d2b6c9aaffac17448a09168c0a6b4ff7f9f9ff61b3106b1ac9d5db81519"
},
{
"file": "package.json",
"sha256LF": "c1414a62bc6c02d0712db43bbf4de68d22d2ed36de9e66378fe193ba3bc0b733"
},
{
"file": "docs/assets/ts/artplayer-plugin-document-pip.d.ts",
"sha256LF": "42faa0a6549149efd01b46c3c59246bd4dc33f2383b63b04e9f5376de29fdb8e"
}
],
"artifacts": [
{
"file": "packages/artplayer-plugin-document-pip/dist/artplayer-plugin-document-pip.js",
"sha256LF": "56440aad3ed06be55ec3a57d781f7de239e9aecf40a067e88f2cffcd01a86d6a"
},
{
"file": "docs/compiled/artplayer-plugin-document-pip.js",
"sha256LF": "56440aad3ed06be55ec3a57d781f7de239e9aecf40a067e88f2cffcd01a86d6a"
},
{
"file": "packages/artplayer-plugin-document-pip/dist/artplayer-plugin-document-pip.legacy.js",
"sha256LF": "67dd14de3cc16a04ae6c1938dcba61b1355f4a15e5fa06f62a41b18d14d4d356"
},
{
"file": "docs/compiled/artplayer-plugin-document-pip.legacy.js",
"sha256LF": "67dd14de3cc16a04ae6c1938dcba61b1355f4a15e5fa06f62a41b18d14d4d356"
},
{
"file": "packages/artplayer-plugin-document-pip/dist/artplayer-plugin-document-pip.mjs",
"sha256LF": "541b4ad6e1cbadd9156ee1f317559c97b9fddae37668ef32046f1fa47c392ec2"
},
{
"file": "docs/compiled/artplayer-plugin-document-pip.mjs",
"sha256LF": "541b4ad6e1cbadd9156ee1f317559c97b9fddae37668ef32046f1fa47c392ec2"
}
],
"logs": [
{
"file": "refactor/.cache/dpip04-installed-first.log",
"sha256": "8e67d5ebc1febaad102c362743589af8be40c2cd2bcb26e72b933842c00ed656"
},
{
"file": "refactor/.cache/dpip04-installed-final.log",
"sha256": "00bf798308821d08c5b7b73c646314ae0826ea52f9ca83d6edf2a138129626c0"
},
{
"file": "refactor/.cache/dpip04-installed-variance.log",
"sha256": "6410a24d45bda348ed9fe2e17479241d1aa9d3e1eb4525f6151a1527c40b1fcd"
},
{
"file": "refactor/.cache/dpip04-factory-replacement-regression.log",
"sha256": "cf07a16de8e07f3cd6c2ba60cf232e87cc519aab3638e80566f2b120c88e6e13"
},
{
"file": "refactor/.cache/dpip04-types-variance.log",
"sha256": "031fde27eb07f3ee61ff89db137afd6726f2482779a86c51d8ac0a21406bd6e9"
},
{
"file": "refactor/.cache/dpip04-editor-variance.log",
"sha256": "34114a66ac839a9fcb76de7cf13a5cce3bfd6adf12f9829cd0d58683028f910b"
},
{
"file": "refactor/.cache/dpip04-build-variance.log",
"sha256": "dc2aa2fe5a7979faa11e7c913ba13ad7ad66697c3d3e827fa93b1f5389c60391"
},
{
"file": "refactor/.cache/dpip04-lint-variance-final.log",
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
{
"file": "refactor/.cache/dpip04-browser-final.log",
"sha256": "91ce0c3f58faef0fef43987a088154147dc1eaeb4ebcf9ef32870dda763221b7"
},
{
"file": "refactor/.cache/dpip04-ci-final.log",
"sha256": "c7b406fa037e15578b848c39a1eace715b16d25a6784a432257b36f71092cb65"
},
{
"file": "refactor/.cache/dpip-package-types-2bH82Z/report.json",
"sha256": "f7a7e0c139931f1a5b91fa50853f0097bcf2762e0604c17acf1c3ac99f001f7f"
},
{
"file": "refactor/.cache/dpip04-final-results/report.json",
"sha256": "8b4b1bf68d717e9e4edcac8e15b43c149f2693b68547c534938decab96a3e5e1"
}
],
"installedPackages": [
{
"name": "artplayer",
"archive": "D:\\github\\ArtPlayer\\refactor\\.cache\\dpip-package-types-2bH82Z\\artplayer.tgz",
"sha256": "2139af017670a4f30f667bf5fdc1aa680f3e03b9c8d3cb767fc92d6345aedff5",
"files": {
"package/ARCHITECTURE.md": "7ebedaee4d06925e0f7bf2ad4a2e6093aa416c91ea4d6154015854baf507e95e",
"package/README.md": "1e185e65f67fc2081b4182bbc6c4558ea05b6e3fa3acc5dd0c3ac7df1d542b09",
"package/THIRD_PARTY_NOTICES": "b77b5b46b79fa0cda850b0781f78c3b1112c4ed9672fa291956fe8eff53098e7",
"package/dist/artplayer.cts": "0e91e907d021db02a68004603e6190505fdc0806d873ebb6af171aa089a81da7",
"package/dist/artplayer.js": "dc1460b77abdd401158e098b25a1abf280c53bb92d401fc387a4864dc7b18357",
"package/dist/artplayer.legacy.js": "49781a25f3d680c7964eec066b792966da71f03ccc3e7936cd5e0e9563e83008",
"package/dist/artplayer.mjs": "ad4e69b1a7a9584ab79204b871f51f4ae6561dc2dece2c64fa9c4884acd36154",
"package/dist/artplayer.mts": "f6292596a9ccb1d43a6d6a12c35f859b1889ad15924c5ae0f9f280941aade313",
"package/dist/artplayer.ts": "26a42ac66811e70f68a8ebe62cbf304eb1993451b3e658961be98e7106162527",
"package/dist/component.ts": "aa1c43be67322781b4b355b143bc69d9f29d22e578e4974d6a13e957a7c0334f",
"package/dist/config.ts": "c4fd8681bf32b10c743e3e561c532520c8f32e43fd765524850b15e55cb91c72",
"package/dist/cssVar.ts": "e027d82fb4f01c9ce7559cf679b2d5ee1962d3f7e5b4dd64ca21f472b933efb6",
"package/dist/emitter.ts": "9c62551cdcc6dd3966bed8a7a85dd477435db977c91a294d2ac8f162f9592537",
"package/dist/events.ts": "af191f862af4ec8933b09113b8c074603ae254a8b70460d0f3006646cd74ae42",
"package/dist/i18n.ts": "34b0c684668044f7600c80b9d3979f8fb730138007b7cb4e7034326b340156fb",
"package/dist/i18n/ar.js": "bd0bef65f4f7dc3f8ed562904cc6fa9071ff4537fb64c1e0fc3d554141bcd3cb",
"package/dist/i18n/ar.mjs": "59310b7bbeea83bbb7d73aadc5ca82a6ec269c3530d19aa741c94d5c64fc5da8",
"package/dist/i18n/cs.js": "6e2c93daba24c2e48dfa206bcf4f2f2a8a02713b856e404d2e4e4ecd8309ca2f",
"package/dist/i18n/cs.mjs": "c73fba18797d62d7b2581e67fe7340c35fe84510b2250ff1ecaad253d9cabbac",
"package/dist/i18n/es.js": "f4133ac6ea06b69a474b33c4a1809a4066e2376bb9464a3f3aa8330f01f1944a",
"package/dist/i18n/es.mjs": "1390bca3def2be115e811de337df0a0c3f63998e51359f283023246245c552a7",
"package/dist/i18n/fa.js": "8d3ef2e0f0cc0ea480c2167b6fcb87cdf444e90759c3519e8daa139fec576da4",
"package/dist/i18n/fa.mjs": "ab441e8a2d79043b29ceca87c783bf06874bb9d3a149c1604bc167eb481be2a9",
"package/dist/i18n/fr.js": "89dc4194a6c0a962b9ce756b52c90401c1acf3b159f265f3bc0d7d6d7d987f03",
"package/dist/i18n/fr.mjs": "99491878430fb7b6f2b7bf93da0588a831704b412e01116f23ba1d9d45863816",
"package/dist/i18n/id.js": "4c6dc86db741bcc2857df55a9d037e82e91d375fa6fd22e0562809ff621b92db",
"package/dist/i18n/id.mjs": "383e5803a6b6686c6de4e867770241de75b6f517dcca2bdedc6f2004bf6e1fb3",
"package/dist/i18n/pl.js": "3a38828b1c3d719c0aca9906cf6a46c23555a8411f8d57645f0e0ce8147dc664",
"package/dist/i18n/pl.mjs": "079ed96732979035297af387c64a7b99519b5a43107fb86735a654ea4fe8e9b5",
"package/dist/i18n/ru.js": "62fac9dddb302eb16382e6e9301fc4b2c66f5f69d4a358a26b67026a5fa4e787",
"package/dist/i18n/ru.mjs": "a893aeaee1d79409db72e324fbff200e3864f33ed168f04d91d25f7cf2efa765",
"package/dist/i18n/tr.js": "1492c36b069a7d73db4f3913bd18085faff7afd8b3c158138fe264e31600e38c",
"package/dist/i18n/tr.mjs": "a90478cac078836b76c2a98261907610fee07f3e4b28671b8e7dbf533778f918",
"package/dist/i18n/vi.js": "c7216ef7e608a79b7e2c479a07bf310d4ab79577947ac4a62d676faaced0e9cf",
"package/dist/i18n/vi.mjs": "66270fdfa0b5da396322d1769169b7df37a030ba15ac18eb30bd87b3af8074ec",
"package/dist/i18n/zh-tw.js": "11c49857d6d40a5ffd224ffa59c9026e71621b345f63c5a086326db80a22371a",
"package/dist/i18n/zh-tw.mjs": "a38e630cb96de96c15d824686aec750e25cf6c8ada01285a292442a81566314f",
"package/dist/icons.ts": "0d8e8e52e52130dd4a29bab551dd7a2a954797e42e92a6e068c85d583e23e6a4",
"package/dist/language.cts": "2248040d86a8e34626755c4ecf53ea0174706c653073cf0e15884a030d173120",
"package/dist/language.mts": "c391e863012c77769e661afbf8fa949e9373aa88d17f58cbba7f5696edb8077f",
"package/dist/legacy/language.ts": "c452ffd764ff9b29b819b3475c42395d2ea7a33560d8c186ef5df3844b9524c3",
"package/dist/option.ts": "850e5264219b8b438c80694402225b690b131786677a5da0d22739ec2352d263",
"package/dist/playback.ts": "1ceaed3aa1cef511fe8b20f4874647f6065c723ad805b742a0a9247e16bb1bb5",
"package/dist/player.ts": "f1e50257df2ea592d0a0e1f36078dda77eaf2cf3b3d795307501396562d99f28",
"package/dist/plugin.ts": "2a57e148fda00ee687da5036b890b0f611cb94bb403a1ed52602179060259d35",
"package/dist/quality.ts": "7ed6ed78cea52991b2f6ddd2bd3b7bd8c5146fdfff7486fe8b814c3e632f1567",
"package/dist/runtime.cts": "52cfff1daeb6841a90212c8fa8d46ca46d6650bb7ed1b59b62115d854b8ad652",
"package/dist/runtime.mts": "1b09bc0ee0f0ee2f788689eaff441bdeda1fab0ce783e71b61b9792d81072b03",
"package/dist/runtime.ts": "ec4b1d56993eb482a77eb0f94b701047549d009e6ba6433f27e7d464fef30c2b",
"package/dist/runtime/component.ts": "840213299c942fe058eb5436977ceec066b9dccda24c55ae9f464b399c979e39",
"package/dist/runtime/construction.ts": "24cc5cda1f614314db382271a9b0d5583b781894cfdf6c548700b1b5270467ee",
"package/dist/runtime/events.ts": "52848f57d35eb1037cf74c8877521edf99a015bcd77f30ef6bbcba1807a99bfe",
"package/dist/runtime/media.ts": "8828f80953aec3e95328cefe691661e8897cb27cb309483cf806ec45a8549ae3",
"package/dist/runtime/option.ts": "bb672e49ffe74a6fc78543217f6de80d7d738890146df0857c709d4dc283e4ce",
"package/dist/runtime/player.ts": "a4a24794e26cfb9e4310bf0f459a7a407e85bf81b4f3a4feb6294331af8036fb",
"package/dist/runtime/plugin.ts": "9ad482f2a77914a91450419680b8af6b314b926f0831c2f7f6d7c466690f95c9",
"package/dist/runtime/services.ts": "8e4648d8c61bff47343f9e1c2b995af69fc00947264b826109ceadcbaf553254",
"package/dist/runtime/setting.ts": "c48d20957b57f79f985ef76a2950cc8a5cfa25dafa8ec5939e562661778e6218",
"package/dist/runtime/subtitle.ts": "13241c4f9a87517aa2cf7b3e0bb8cedaa12fa0b4d3f8934285797583b752557e",
"package/dist/runtime/template.ts": "da9975513a1938e7f386f4f65f718f0fc595164bfeac8f0cd99a3e97a54919a1",
"package/dist/runtime/utils.ts": "cab9916f5224a3b047812b9f759cc9cc62105662599744067a6955020ab36916",
"package/dist/setting.ts": "d12a75b656fff70cbb30be4bffec46d9c4273636e8722bce971a4d2b188712a1",
"package/dist/subtitle.ts": "d25b470e47d6a9bd696d9c1ad8adb58e56a208f05695186d513bc8c43c2e8acf",
"package/dist/template.ts": "68aed9e97d006d6be4fabb8504ca84dafab770b0925f4d6e7319e67c82f21b0d",
"package/dist/utils.ts": "494ec447ab467a07ddd7a2c2abf778b3fce69fd28a09aaa8ced9759f8de2e3f6",
"package/package.json": "82e92699e7c29847f32ac6767ece0401290e7d7a12854722bdbcfd09b90b7954",
"package/types/COMPATIBILITY.md": "a7da9e102a116104b513df4f7451247b7759bc502d3375f30bd5b14a541826e0",
"package/types/README.md": "1bd9868e773610e6312fd48a1c5aa20772d29df0af40c3db66e75b7ab4a1aee0",
"package/types/artplayer.d.cts": "3685065e4263abcfd9d953176e461d5b3eb990b0363b54689a7f55deba770fef",
"package/types/artplayer.d.mts": "b664fec51ee5c5381f2ceab25d99d52aee56feab04a2ee7b4ea5b2145ea5fa0e",
"package/types/artplayer.d.ts": "5d0162adf7ac6d0f2bb9b5cfe361f28657c4d9c540cadbf36eba3cc954ce50f8",
"package/types/component.d.ts": "ae5bc1ddeaa1ee1ebbc62573e32423993727079205c64751a5a314170e588a32",
"package/types/config.d.ts": "36f9a84cd436f17701a0d11d3417fc1fe0414e0c52c80083b94a85dfc329e37e",
"package/types/cssVar.d.ts": "93217860fff2ebf750f606d95ddd22220a58837119e63bdf2f5f78fd7488458b",
"package/types/emitter.d.ts": "7e1f9a2a8ce65feb95734f1ed52d1334e57aa388bbef2a43d8bc53a9b6f6623c",
"package/types/events.d.ts": "f83624c9268a284477e8bd793fe3562a2363b72f2a44d5c64fe8c6a6cede8830",
"package/types/i18n.d.ts": "f4f2f05bdfda73c74fef34767cb18ee8e11b743120b1c4598e9714d7846018e5",
"package/types/icons.d.ts": "326a67ba7bdcf52862c5b2a269e540140aff98d05c7b96196485a77f84fe5960",
"package/types/language.d.cts": "f7928e108cf7b7814c2d75cb0a525333e95873fca6cd6d89a740450656b9c1cd",
"package/types/language.d.mts": "6619a26d604b7cccbe2f596243d87ae37cfaae33b8b52874ec071d9787446f9e",
"package/types/legacy/language.d.ts": "c7abda4d506fd933c350e9030290bf9e64347a921d683a66115da1995ebe0a81",
"package/types/option.d.ts": "ccf2c8ddc537dc65c9682d39f044726e23bff18f476b622512d7e6a4b949b5f6",
"package/types/playback.d.ts": "58705c273df6e76a77a6575e769a9ec6c013785c25080f2551aa22415788d870",
"package/types/player.d.ts": "92b00211b70ac71336e495899df972a0519dd138111846044fe4e0f967966177",
"package/types/plugin.d.ts": "fc3594a41c51d8248713e33c486fb1f6a518ac5c7ce31be6988a6cd8d052c5f3",
"package/types/quality.d.ts": "1ac1a48b4f74ff9ba1ce60443e1463d50d1c6a2e5d87d63dc7d2a8eb7f4c2c34",
"package/types/runtime.d.cts": "7ee988dfea9a0ac71a34a656f96f7b74e78aa92547cfdfab7ff7e1139a77d4a3",
"package/types/runtime.d.mts": "dcb85f59a8b7714918ced0c1d18c2bb24e8b80b56d8c594e019dcbdb5ad88b08",
"package/types/runtime.d.ts": "9c6ccd39a1be293f17ae46dae8ea077053e12635ee79d73a5e3b3a559230fcff",
"package/types/runtime/component.d.ts": "1b4c0cee44568649e80140fe778febfcae88af0ac85515f1cbeff78ab0c6d14f",
"package/types/runtime/construction.d.ts": "7a87bedf6f7ffff0c46078aa5f1551e0077d35574e286516121f5f935e2d9ce4",
"package/types/runtime/events.d.ts": "a1e2f9d387475453eaf95c2a5ee79e228636c0bb859bda3fcc46da46574a0c31",
"package/types/runtime/media.d.ts": "8fc89401be7fe25542c169d07dd5675f10916ed20be8493e19695966cf3864a8",
"package/types/runtime/option.d.ts": "6e334e1a76fdcc40b4665c02523bd31c3994d96078fadeb40e23422aa54c1a1d",
"package/types/runtime/player.d.ts": "8ac6383502e4872e83659838844856903031a81a0adc8e8535feb78453aa042c",
"package/types/runtime/plugin.d.ts": "8528f2b17843149f42f9cc16d6fd70baa238c9dc2c329b67d2c38096799c69bd",
"package/types/runtime/services.d.ts": "604c9f8e4b6c0da818f96576bf9f4b0e96085a9003927b2f7ba30027b1ba237e",
"package/types/runtime/setting.d.ts": "349c1fcb205ad312916bd3ee55e6bf241ea8a569fb2ab6c80822e69fc518f7d7",
"package/types/runtime/subtitle.d.ts": "269ff84678d327b3a9dc2f5bc6cc0d731d1e081b85422e474621d5d792efb153",
"package/types/runtime/template.d.ts": "7a62f968a38b4bf9109a4439557c02074eb1d62ba1f6e21a8eb194e91f0badfe",
"package/types/runtime/utils.d.ts": "6bf731705d86853e066dbaf3b8d4003b6548423fe615b7412b722bd0d3a6e48b",
"package/types/setting.d.ts": "08305a75dff96f06490430e099338b463df471b550c1d0dac3abc8995b39eb09",
"package/types/subtitle.d.ts": "b18314e2d64efdb6045830b6e12f615ae2ed585416130e562329ad3ea337f6ce",
"package/types/template.d.ts": "4792bc0c2cbcb7966e4375118bd34b326166e0831862e94ace4cf6b1bbe6a8c8",
"package/types/utils.d.ts": "fca0d3d814df94a25f9eb067c86fa0cf272e2791bac793b91229d57680797712"
}
},
{
"name": "artplayer-plugin-document-pip",
"archive": "D:\\github\\ArtPlayer\\refactor\\.cache\\dpip-package-types-2bH82Z\\artplayer-plugin-document-pip.tgz",
"sha256": "8e7b16e5735b5e83251b3102e228d202b67bd16e52104a328bf1d50903bd32a3",
"files": {
"package/ARCHITECTURE.md": "422cd5847c8c8dffece1b619644a5e441af84ddb7d727d6f03d433f9d7117af9",
"package/README.md": "3a9553f9f8d9d12f0f76582d54d301d99b64f1836540e0f7b00bf20eb4e3d8f7",
"package/dist/artplayer-plugin-document-pip.js": "56440aad3ed06be55ec3a57d781f7de239e9aecf40a067e88f2cffcd01a86d6a",
"package/dist/artplayer-plugin-document-pip.legacy.js": "67dd14de3cc16a04ae6c1938dcba61b1355f4a15e5fa06f62a41b18d14d4d356",
"package/dist/artplayer-plugin-document-pip.mjs": "541b4ad6e1cbadd9156ee1f317559c97b9fddae37668ef32046f1fa47c392ec2",
"package/package.json": "5f3671f759364be52faf3810e1534a7711270f975f06d3489d95982fbae0eafb",
"package/types/artplayer-plugin-document-pip.d.cts": "0dd487fba4fbe05614d6d00bb6e275e9211da3bd8e8c1296e5c89a4306ed5a73",
"package/types/artplayer-plugin-document-pip.d.mts": "0dd487fba4fbe05614d6d00bb6e275e9211da3bd8e8c1296e5c89a4306ed5a73",
"package/types/artplayer-plugin-document-pip.d.ts": "bea8feeec01c0711a7f669f65f18ecdc299f89101ec75ea8c001bb9a218b0663"
}
}
],
"browserArtifacts": [
{
"file": "refactor/.cache/dpip04-final-results/results/.last-run.json",
"sha256": "91d1c43004802cd49950d78eb11c8fa7d05da8ffffe219a8b13b2f561bc00903"
}
]
}
@@ -0,0 +1,36 @@
{
"compiler": "5.9.3",
"records": [
{
"name": "artplayer-proxy-canvas",
"version": "1.1.0",
"source": "import Artplayer from 'artplayer'; import plugin from 'artplayer-proxy-canvas'; const replacement: typeof plugin = (_option?: Parameters<typeof plugin>[0]) => (_art: Artplayer) => document.createElement('canvas'); void replacement;",
"historical": [],
"current": [
{
"file": "test/types/consumer.ts",
"code": 2741,
"line": 1,
"message": "Property 'default' is missing in type '(_option?: Parameters<typeof plugin>[0]) => (_art: Artplayer) => HTMLCanvasElement' but required in type 'Factory'."
}
]
},
{
"name": "artplayer-plugin-ambilight",
"version": "1.1.0",
"source": "import Artplayer from 'artplayer'; import plugin from 'artplayer-plugin-ambilight'; const replacement: typeof plugin = (_option?: Parameters<typeof plugin>[0]) => (_art: Artplayer) => ({ name: 'artplayerPluginAmbilight' as const, start() {}, stop() {} }); void replacement;",
"historical": [],
"current": [
{
"file": "test/types/consumer.ts",
"code": 2741,
"line": 1,
"message": "Property 'default' is missing in type '(_option?: Option | undefined) => (_art: Artplayer) => { name: \"artplayerPluginAmbilight\"; start(): void; stop(): void; }' but required in type 'Factory'."
}
]
}
],
"introducedBy": "PKG-DPIP-04",
"followup": "PKG-FACTORY-01",
"scope": "Exact supplied consumer source passes actual published declarations and fails current declarations with missing required default property. Historical declaration bytes are frozen by each package release baseline."
}
@@ -0,0 +1,48 @@
# PKG-DPIP-04 公开类型与两代导出
公开命名类型统一Option、Result、AsyncResult、Factory、RuntimeFactory。默认Result保留
可写boolean与void动作,不改变旧调用直接推导的返回值、initializer可赋值性或
ReturnType结果;默认工厂保持完整的必填参数函数形状,包括typeof工厂的替换赋值和
Parameters必填tuple。RuntimeFactory显式描述省略options、self.default与AsyncResult。
不能简单把旧void动作改成Promise,因为用户可以
合法创建Result或覆盖方法为`() => {}`。AsyncResult供未修改的实际结果显式断言,
准确描述readonly getter和Promise<void>动作;生产入口也用此类型检查实现。
这是兼容视图与精确视图并存,不把Ads的推导修正授权用于此插件。
main/legacy的.default自别名兼容1.0.1/1.0.2 namespace.default与1.1.0直接工厂。
ESM仍只有default运行时出口。新增.d.mts/.d.cts和import/require条件声明,typesVersions
保持旧编译器legacy解析。编辑器声明由语义生成器更新,README/ARCHITECTURE解释
真实异步语义、默认旧推导及何时用AsyncResult。声明仅增加类型出口,不增加运行时API。
四组专项验证五个编译器/模块模式、14项非法用法、四份实际发布声明、生成全局声明
以及实际三格式出口。历史源码/声明用例能创建Result、替换open/close及整个工厂;候选也必须
继续编译,不能只验证readonly精确视图而漏掉这类合法旧代码。
仓库外真实安装矩阵共27场景(四发布×5 + 候选7),都经过offline安装、frozen重装、
完整归档成员哈希核对,确认不是workspace链接,类型解析不得逃逸到仓库。候选7场景
和历史12场景零诊断;另外8个精确历史失败:
- 1.0.0:NodeNext CJS/ESM和bundler均2307。运行时require另验证MODULE_NOT_FOUND,
不用Git代码补齐缺失归档。旧node解析还能找到types,与现代exports失败分开记录。
- 1.0.1:同三种现代解析均7016;声明在tarball里,但exports中没有对应类型路径。
- 1.0.2和1.1.0:NodeNext ESM各7个精确诊断,顺序为
2322/2344/2349/2349/2344/2344/2349,默认导入被解释成不可调用的CJS namespace,
连带Parameters/ReturnType错误。其他所测模式保持正常。
候选每种模式均拒绝14项非法用法;历史负例不是8项候选豁免,27场景也不代表全零错误。
首次安装遇到1.0.0现代解析2307,第二次进一步观察到1.0.2的Parameters赋值never产生
额外2322;两份中间诊断完整保留,最终检查用精确版本/模式/诊断列表,不接受任意错误。
额外反向赋值审查复现了首版声明的2741:为默认工厂增加必需.default类型属性,会让
旧的普通替换函数无法赋值;仅保留末重载的Parameters还不够。最终默认声明改为旧的
完整必填函数形状,精确/可选调用只通过显式RuntimeFactory视图提供。CommonJS声明
保留旧import=模块.default访问,ESM声明单独指定默认可调用类型以避免namespace错误。
运行时仍同时支持直接require与.default。此项没有请求用户接受类型破坏。
结果与哈希见[证据](../baselines/dpip-types-validation.json),维护说明见[入口](../dpip-validation.md)。
05原生文档窗口/设备/代理组合和06完整分发/demo仍继续;不推送、发布或升级版本。
回退需要同时回退types、条件入口、运行时.default和对应生成产物,保留历史归档。
横向复查也证明Canvas/Ambilight的实际发布声明接受旧工厂替换,而当前声明各出现2741。新增PKG-FACTORY-01紧接本任务修复,并加入两包05与REL-01依赖;FACTORY-TYPE-01保持open,复现源码与结果见baselines/factory-assignment-gaps.json。此前完成记录保留为历史检查点,不冒充此新用法已通过。
最终四组专项、编辑器/三格式构建、27安装场景(19零诊断+8精确历史失败)及最终main哈希对应的18浏览器通过。完整CI1140项(1006单元+14工程+120基线),另44重复契约、290生产TS严格检查通过。任务done并独立提交;下一步PKG-FACTORY-01,DPIP05/06继续。
+13
View File
@@ -42,3 +42,16 @@ test/helpers/dpip.js是受控DOM/window边界:验证ownerDocument、节点身
选择明确构建文件(不fallback);最终产物证据与宽矩阵历史证据分开保存。
本阶段保留原生窗口和媒体/代理验收门槛,详见[03记录](changes/2026-09-12-PKG-DPIP-03-lifecycle.md)
及[03证据](baselines/dpip-lifecycle-validation.json)。04继续公开类型/导出/安装消费者。
## 公开类型和真实安装(04)
`node --test refactor/scripts/dpip-types.test.mjs`验证默认Result旧推导、显式AsyncResult、
完整旧工厂形状、四历史声明、编辑器与实际产物。合法旧工厂/initializer和
void方法替换必须继续编译;RuntimeFactory显式提供可选options和精确返回,不改变默认
函数的反向可赋值性。14项非法用法在五个仓库
编译模式及七个安装消费者模式均需被拒绝。
`yarn test:dpip-types-package`在仓库外安装四实际发布和候选,offline/frozen重装并逐文件
校验字节。27模式包含8历史失败:1.0.0现代解析三项2307、1.0.1三项7016、1.0.2和
1.1.0各一项NodeNext ESM七诊断;候选7项全部零诊断。1.0.0的require必须复现缺失运行时,
不能称作可执行版本。详见[04记录](changes/2026-09-12-PKG-DPIP-04-types.md)和
[04证据](baselines/dpip-types-validation.json)。05/06的原生设备、demo和分发门槛保留。
@@ -0,0 +1,16 @@
import Artplayer from 'artplayer'
import dpip from 'artplayer-plugin-document-pip'
const options: Parameters<typeof dpip>[0] = { width: 640, height: 360, placeholder: 'Active', fallbackToVideoPiP: true }
const art = new Artplayer({ container: '#player', url: 'video.mp4', plugins: [dpip(options)] })
const result = dpip(options)(art)
const returned: void = result.open()
result.open = () => {}
result.close = () => {}
const fake: ReturnType<ReturnType<typeof dpip>> = { name: 'artplayerPluginDocumentPip', isSupported: true, isActive: false, open() {}, close() {}, toggle() {} }
fake.isActive = true
fake.isSupported = false
const initializer: ReturnType<typeof dpip> = () => fake
const inferredInitializer = dpip(options)
const oldReplacement: typeof inferredInitializer = () => fake
void [returned, initializer, inferredInitializer, oldReplacement]
+16 -8
View File
@@ -2,9 +2,9 @@
> 由 tasks.json 生成。请修改数据后运行 `node refactor/scripts/plan.mjs --write`,不要手改本表。
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 221 项,范围 22 个包及工作区/示例。
基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 222 项,范围 22 个包及工作区/示例。
状态:todo 119 / doing 6 / blocked 0 / done 96 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
状态:todo 119 / doing 6 / blocked 0 / done 97 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。
前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。
@@ -16,7 +16,7 @@
| --- | --- | --- |
| artplayer | 5.4.1 | CORE-01, CORE-02, CORE-03, CORE-04, CORE-05, CORE-06, CORE-07, CORE-08, CORE-09, CORE-10, CORE-11, CORE-12, CORE-13, CORE-14, CORE-15, CORE-16, CORE-17, CORE-18, CORE-19, CORE-20, CORE-21, CORE-23, CORE-22, CORE-24 |
| artplayer-plugin-ads | 2.1.0 | PKG-ADS-01, PKG-ADS-02, PKG-ADS-03, PKG-ADS-04, PKG-ADS-05, PKG-ADS-06 |
| artplayer-plugin-ambilight | 1.1.0 | PKG-AMBILIGHT-01, PKG-AMBILIGHT-02, PKG-AMBILIGHT-03, PKG-AMBILIGHT-04, PKG-AMBILIGHT-PROXY-01, PKG-AMBILIGHT-05, PKG-AMBILIGHT-06 |
| artplayer-plugin-ambilight | 1.1.0 | PKG-AMBILIGHT-01, PKG-AMBILIGHT-02, PKG-AMBILIGHT-03, PKG-AMBILIGHT-04, PKG-AMBILIGHT-PROXY-01, PKG-AMBILIGHT-05, PKG-AMBILIGHT-06, PKG-FACTORY-01 |
| artplayer-plugin-asr | 2.1.0 | PKG-ASR-01, PKG-ASR-02, PKG-ASR-03, PKG-ASR-04, PKG-ASR-05, PKG-ASR-06 |
| artplayer-plugin-audio-track | 1.1.0 | PKG-AUDIO-01, PKG-AUDIO-02, PKG-AUDIO-03, PKG-AUDIO-04, PKG-AUDIO-05, PKG-AUDIO-06 |
| artplayer-plugin-auto-thumbnail | 1.1.0 | PKG-AUTO-THUMB-01, PKG-AUTO-THUMB-02, PKG-AUTO-THUMB-03, PKG-AUTO-THUMB-04, PKG-AUTO-THUMB-05, PKG-AUTO-THUMB-06 |
@@ -31,7 +31,7 @@
| artplayer-plugin-multiple-subtitles | 1.2.0 | PKG-MULTI-SUB-01, PKG-MULTI-SUB-02, PKG-MULTI-SUB-03, PKG-MULTI-SUB-04, PKG-MULTI-SUB-05, PKG-MULTI-SUB-06 |
| artplayer-plugin-vast | 1.2.0 | PKG-VAST-01, PKG-VAST-02, PKG-VAST-03, PKG-VAST-04, PKG-VAST-05, PKG-VAST-06 |
| artplayer-plugin-vtt-thumbnail | 1.1.0 | PKG-VTT-THUMB-01, PKG-VTT-THUMB-02, PKG-VTT-THUMB-03, PKG-VTT-THUMB-04, PKG-VTT-THUMB-05, PKG-VTT-THUMB-06 |
| artplayer-proxy-canvas | 1.1.0 | PKG-AMBILIGHT-PROXY-01, PKG-CANVAS-01, PKG-CANVAS-02, PKG-CANVAS-03, PKG-CANVAS-04, PKG-CANVAS-05, PKG-CANVAS-06 |
| artplayer-proxy-canvas | 1.1.0 | PKG-AMBILIGHT-PROXY-01, PKG-CANVAS-01, PKG-CANVAS-02, PKG-CANVAS-03, PKG-CANVAS-04, PKG-CANVAS-05, PKG-CANVAS-06, PKG-FACTORY-01 |
| artplayer-proxy-mediabunny | 1.2.0 | PKG-MB-01, PKG-MB-02, PKG-MB-03, PKG-MB-04, PKG-MB-05, PKG-MB-06, PKG-MB-07, PKG-MB-08, PKG-MB-09, PKG-MB-10 |
| artplayer-tool-iframe | 1.1.0 | PKG-IFRAME-01, PKG-IFRAME-02, PKG-IFRAME-03, PKG-IFRAME-04, PKG-IFRAME-05, PKG-IFRAME-06 |
| artplayer-tool-thumbnail | 4.4.0 | PKG-TOOL-THUMB-01, PKG-TOOL-THUMB-02, PKG-TOOL-THUMB-03, PKG-TOOL-THUMB-04, PKG-TOOL-THUMB-05, PKG-TOOL-THUMB-06 |
@@ -153,7 +153,7 @@
| PKG-AMBILIGHT-03 | artplayer-plugin-ambilight<br>整理内部职责与资源 | PKG-AMBILIGHT-02, CORE-03, CORE-12 | 取色计算与绘帧分离,统一 RAF 和 DOM 清理 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | M | done |
| PKG-AMBILIGHT-04 | artplayer-plugin-ambilight<br>迁移自有源码和公开类型 | PKG-AMBILIGHT-03, ENG-04, ENG-06, CORE-07 | canvas 上下文、参数及 start/stop 的明确类型 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | M | done |
| PKG-AMBILIGHT-PROXY-01 | artplayer-plugin-ambilight, artplayer-proxy-canvas<br>修复Canvas代理输出尺寸与取色区域 | PKG-AMBILIGHT-04, CORE-22 | 按Canvas实际输出buffer取色,原生video保留intrinsic尺寸,明确5.1.7没有proxy配置 | 旧错误复现、三引擎实际代理九色区域对照及原生视频回归通过;不把本子项当作最终代理/设备验收 | M | done |
| PKG-AMBILIGHT-05 | artplayer-plugin-ambilight<br>验证新旧核心和组合 | PKG-AMBILIGHT-04, CORE-22, PKG-AMBILIGHT-PROXY-01, PKG-CANVAS-04 | 原生 video、canvas proxy 的能力边界及销毁无帧循环 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | M | todo |
| PKG-AMBILIGHT-05 | artplayer-plugin-ambilight<br>验证新旧核心和组合 | PKG-AMBILIGHT-04, CORE-22, PKG-AMBILIGHT-PROXY-01, PKG-CANVAS-04, PKG-FACTORY-01 | 原生 video、canvas proxy 的能力边界及销毁无帧循环 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | M | todo |
| PKG-AMBILIGHT-06 | artplayer-plugin-ambilight<br>验证分发并同步文档 | PKG-AMBILIGHT-05, ENG-07 | ambilight.js 示例及样式/分发验证 | tarball 入口/资源、类型、8082 demo 和 README 一致,有回退记录 | M | todo |
## 5 包迁移:artplayer-plugin-audio-track
@@ -296,7 +296,7 @@
| PKG-DPIP-01 | artplayer-plugin-document-pip<br>核对包契约与历史用法 | BASE-05 | width/height/placeholder/fallbackToVideoPiP、open/close/toggle 返回 | 源码/声明/README/demo/发布包差异已登记;公开形状和版本范围冻结 | H | done |
| PKG-DPIP-02 | artplayer-plugin-document-pip<br>建立特有行为与错误测试 | PKG-DPIP-01, ENG-03, ENG-05 | 不支持/拒绝、重复打开、pagehide、核心销毁和视频 PiP fallback | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | H | done |
| PKG-DPIP-03 | artplayer-plugin-document-pip<br>整理内部职责与资源 | PKG-DPIP-02, CORE-16, CORE-17 | 窗口生命周期、DOM 迁移、样式与事件 document 重绑分离 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | H | done |
| PKG-DPIP-04 | artplayer-plugin-document-pip<br>迁移自有源码和公开类型 | PKG-DPIP-03, ENG-04, ENG-06, CORE-07 | Document PiP 可选能力和真实状态/返回类型 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | H | todo |
| PKG-DPIP-04 | artplayer-plugin-document-pip<br>迁移自有源码和公开类型 | PKG-DPIP-03, ENG-04, ENG-06, CORE-07 | Document PiP 可选能力和真实状态/返回类型 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | H | done |
| PKG-DPIP-05 | artplayer-plugin-document-pip<br>验证新旧核心和组合 | PKG-DPIP-04, CORE-22, PKG-CANVAS-04, PKG-MB-04 | 原生视频及两个 proxy、键盘/焦点/全屏与关闭还原 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | H | todo |
| PKG-DPIP-06 | artplayer-plugin-document-pip<br>验证分发并同步文档 | PKG-DPIP-05, ENG-07 | document.pip.js、浏览器能力矩阵、旧接口与恢复证据 | tarball 入口/资源、类型、8082 demo 和 README 一致,有回退记录 | H | todo |
@@ -322,7 +322,7 @@
| PKG-CANVAS-02 | artplayer-proxy-canvas<br>建立特有行为与错误测试 | PKG-CANVAS-01, ENG-03, ENG-05 | ready/loadeddata/canplay、play/seek、回调、resize 与销毁 | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | H | done |
| PKG-CANVAS-03 | artplayer-proxy-canvas<br>整理内部职责与资源 | PKG-CANVAS-02, CORE-06, CORE-11, CORE-16 | video adapter/原 canvas 方法/RAF 绘制/事件订阅分离 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | H | done |
| PKG-CANVAS-04 | artplayer-proxy-canvas<br>迁移自有源码和公开类型 | PKG-CANVAS-03, ENG-04, ENG-06, CORE-07 | canvas 与媒体能力的精确组合类型,保持 Result | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | H | done |
| PKG-CANVAS-05 | artplayer-proxy-canvas<br>验证新旧核心和组合 | PKG-CANVAS-04, CORE-22, PKG-DPIP-04 | 真实 video/canvas 绘制、字幕和 document PiP 恢复 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | H | todo |
| PKG-CANVAS-05 | artplayer-proxy-canvas<br>验证新旧核心和组合 | PKG-CANVAS-04, CORE-22, PKG-DPIP-04, PKG-FACTORY-01 | 真实 video/canvas 绘制、字幕和 document PiP 恢复 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | H | todo |
| PKG-CANVAS-06 | artplayer-proxy-canvas<br>验证分发并同步文档 | PKG-CANVAS-05, ENG-07 | canvas.js、三种产物、调用兼容与资源证据 | tarball 入口/资源、类型、8082 demo 和 README 一致,有回退记录 | H | todo |
## 5 包迁移:artplayer-proxy-mediabunny
@@ -391,7 +391,7 @@
| ID | 范围 / 步骤 | 前置依赖 | 交付物 | 验收条件 | 风险 | 状态 |
| --- | --- | --- | --- | --- | --- | --- |
| REL-08 | workspace<br>提前建立逐包发布准入台账 | BASE-08, ENG-07 | 每批包/版本/源码/锁文件/工具/tarball integrity、必需测试/设备证据、限制和回退映射 | 受影响能力缺证据明确阻止对应批次;无关批次可独立准备,旧证据在候选内容变化后失效;站点采用真实构建/URL/资源验收,npm 分发依据历史核实,不从版本清单推断新增发布范围;关联 risks.json 和 third-party.json;受影响 bundle/worker/WASM/font/模型的来源与许可通知缺口必须有审查结论,未决项阻止对应批次 | H | todo |
| REL-01 | workspace<br>提前确定分包版本与差异方案 | REL-08, CORE-21, SITE-03, PKG-CHAPTER-04, PKG-AMBILIGHT-04, PKG-AUDIO-04, PKG-AUTO-THUMB-04, PKG-VTT-THUMB-04, PKG-HLS-04, PKG-DASH-04, PKG-MULTI-SUB-04, PKG-JASSUB-04, PKG-MASK-04, PKG-ASR-04, PKG-ADS-04, PKG-VAST-04, PKG-CAST-04, PKG-DPIP-04, PKG-CANVAS-04, PKG-IFRAME-04, PKG-TOOL-THUMB-04, PKG-DANMUKU-06, PKG-MB-08 | 每包版本/变更日志/依赖/类型差异方案和独立准入状态;按 version-policy.md 冻结各包下一 major(minor/patch 归零)并核实 registry 占用 | 所有包有方案和剩余门槛,未决项明确阻止相应发布;本步骤不声称已经可发布;全部包有 major 目标,版本冲突明确处理,独立准备任务同步 manifest/锁/依赖/日志;按 BASE-05 区分 21 库与文档站分发,不机械把文档站当库上传 npm | H | todo |
| REL-01 | workspace<br>提前确定分包版本与差异方案 | REL-08, CORE-21, SITE-03, PKG-CHAPTER-04, PKG-AMBILIGHT-04, PKG-AUDIO-04, PKG-AUTO-THUMB-04, PKG-VTT-THUMB-04, PKG-HLS-04, PKG-DASH-04, PKG-MULTI-SUB-04, PKG-JASSUB-04, PKG-MASK-04, PKG-ASR-04, PKG-ADS-04, PKG-VAST-04, PKG-CAST-04, PKG-DPIP-04, PKG-CANVAS-04, PKG-IFRAME-04, PKG-TOOL-THUMB-04, PKG-DANMUKU-06, PKG-MB-08, PKG-FACTORY-01 | 每包版本/变更日志/依赖/类型差异方案和独立准入状态;按 version-policy.md 冻结各包下一 major(minor/patch 归零)并核实 registry 占用 | 所有包有方案和剩余门槛,未决项明确阻止相应发布;本步骤不声称已经可发布;全部包有 major 目标,版本冲突明确处理,独立准备任务同步 manifest/锁/依赖/日志;按 BASE-05 区分 21 库与文档站分发,不机械把文档站当库上传 npm | H | todo |
| REL-09 | workspace<br>落实全包下一 major 版本及依赖元数据 | REL-01, DOC-11 | 22 包版本目标落实、适用锁文件/依赖范围/示例/变更日志同步,核实 registry 版本占用 | 版本与 policy 一致,旧核心支持保留;必要拆子任务各自提交,候选构建前完成,不执行 publish | H | todo |
| REL-02 | workspace<br>生成候选 tarball 并验证新旧组合 | REL-01, CORE-22, ENG-07, REL-09 | 各候选本地 tarball/integrity 与新旧核心/插件消费者验证报告,外部门槛单独标注 | 隔离安装和可自动化组合通过;设备结论不伪造,最终发布绑定同一候选内容;在目标 major 版本确定后构建 pack,不在测试后改版本 | H | todo |
| REL-03 | workspace<br>完成真机、外部 SDK 与压力验收 | REL-02, EX-03, SITE-06, MOD-05 | Safari/移动/PiP/Cast/IMA/模型/长播放完整报告 | 包集成与全项目真机/SDK/压力结论齐全才完成本汇总;独立批次先建立自己的完整门槛子任务 | H | todo |
@@ -408,6 +408,12 @@
| REVIEW-02 | workspace<br>第二轮真实浏览器与生态集成复盘 | REVIEW-01, REL-03 | Chrome 交互、自动浏览器、新旧组合、真机/SDK/性能/资源的全范围报告 | 所需环境证据齐全,前轮修复再次核对;本轮阻断项关闭,无关 mock 不替代真实验收 | H | todo |
| REVIEW-03 | workspace<br>第三轮 npm 候选内容与发布准备复盘 | REVIEW-02, REL-04, CI-04 | 实际候选 integrity、干净安装构建/消费者、入口/许可/版本/tag/回退及前轮证据汇总 | 最终候选完整检查通过,发布阻断项为零;准备可审阅的批次报告,不自动执行 publish;逐包核对 major 目标,不能用大版本豁免旧 API 兼容 | H | todo |
## 5 工厂类型兼容补审
| ID | 范围 / 步骤 | 前置依赖 | 交付物 | 验收条件 | 风险 | 状态 |
| --- | --- | --- | --- | --- | --- | --- |
| PKG-FACTORY-01 | artplayer-proxy-canvas, artplayer-plugin-ambilight<br>修复已迁移工厂的反向赋值兼容 | PKG-CANVAS-04, PKG-AMBILIGHT-04, PKG-DPIP-04 | 复现两包旧typeof工厂替换与新.default/可选重载冲突,修复公开类型并补安装消费者、产物和文档 | 默认工厂的历史合法反向赋值继续通过;既有类型/运行时导出逐版本核对,不能只验证Parameters或直接调用 | H | todo |
## 完成证据与阻塞
- DOC-01: [记录](progress.md)
@@ -509,7 +515,9 @@
- PKG-DPIP-01: [记录](changes/2026-09-12-PKG-DPIP-01-contract.md) [记录](baselines/dpip-release.json) [记录](baselines/dpip-contract.md) [记录](baselines/dpip-contract-validation.json) [记录](dpip-validation.md)
- PKG-DPIP-02: [记录](changes/2026-09-12-PKG-DPIP-02-tests.md) [记录](baselines/dpip-behavior-validation.json) [记录](dpip-validation.md)
- PKG-DPIP-03: [记录](changes/2026-09-12-PKG-DPIP-03-lifecycle.md) [记录](baselines/dpip-lifecycle-validation.json) [记录](dpip-validation.md)
- PKG-DPIP-04: [记录](changes/2026-09-12-PKG-DPIP-04-types.md) [记录](baselines/dpip-types-validation.json) [记录](dpip-validation.md)
- PKG-CANVAS-01: [记录](changes/2026-09-12-PKG-CANVAS-01-contract.md) [记录](baselines/canvas-contract.md) [记录](baselines/canvas-release.json) [记录](canvas-validation.md) [记录](baselines/canvas-contract-validation.json)
- PKG-CANVAS-02: [记录](changes/2026-09-12-PKG-CANVAS-02-tests.md) [记录](baselines/canvas-behavior-validation.json) [记录](canvas-validation.md)
- PKG-CANVAS-03: [记录](changes/2026-09-12-PKG-CANVAS-03-lifecycle.md) [记录](baselines/canvas-lifecycle-validation.json) [记录](canvas-validation.md)
- PKG-CANVAS-04: [记录](changes/2026-09-12-PKG-CANVAS-04-types.md) [记录](baselines/canvas-types-validation.json) [记录](canvas-validation.md)
- PKG-FACTORY-01: [记录](baselines/factory-assignment-gaps.json)
+11
View File
@@ -1,5 +1,16 @@
# 进度与证据
## 最新完成:Document PiP-04 类型、工厂赋值与导出兼容
默认工厂完整保留旧必填签名与可替换性;Result保持void/可写字段,显式RuntimeFactory
和AsyncResult描述实际可选调用、self.default和异步只读状态。27安装场景含候选7及历史
12零诊断,另8个精确历史错误对照;1.0.0缺运行时单独保留。四组专项、三格式/编辑器
构建、最终main哈希对应的18浏览器检查与完整CI1140项通过,另44重复契约,290生产TS。
横向复查确认Canvas/Ambilight也有旧工厂替换2741,新增PKG-FACTORY-01紧接修复,并
加入两包05及REL-01依赖;该风险保持open。当前222项:97 done、6 doing、119 todo。
见[本步记录](changes/2026-09-12-PKG-DPIP-04-types.md)和[证据](baselines/dpip-types-validation.json)。
Document PiP原生组合05与完整demo/分发06仍未完成;独立本地提交,无推送/发布。
## 最新完成:Document PiP-03 严格TS与窗口资源修复
6个模块分离窗口申请/终态、DOM还原、样式、控件与延迟资源。20候选用例在旧源码
+4 -2
View File
@@ -160,9 +160,11 @@
| CANVAS-DIST-01 | resolved / 已复现 | Canvas proxy published CommonJS namespace differs from current callable export | PKG-CANVAS-04, PKG-CANVAS-06 |
| CANVAS-PIXEL-01 | resolved / 已复现 | Historical Canvas proxy produces transparent frames with detached native video in tested WebKit | PKG-CANVAS-03, PKG-CANVAS-05 |
| DPIP-PACK-01 | open / 已复现 | Published Document PiP 1.0.0 tarball omits every declared runtime entry | PKG-DPIP-06 |
| DPIP-DIST-01 | open / 已复现 | Document PiP namespace.default in 1.0.1/1.0.2 differs from callable 1.1.0 export | PKG-DPIP-04, PKG-DPIP-06 |
| DPIP-TYPE-01 | open / 已复现 | Document PiP requires options and declares void actions and writable flags that differ from runtime | PKG-DPIP-04 |
| DPIP-DIST-01 | resolved / 已复现 | Document PiP namespace.default in 1.0.1/1.0.2 differs from callable 1.1.0 export | PKG-DPIP-04, PKG-DPIP-06 |
| DPIP-TYPE-01 | resolved / 已复现 | Document PiP requires options and declares void actions and writable flags that differ from runtime | PKG-DPIP-04 |
| DPIP-LIFE-01 | open / 已复现 | Document PiP has no separate ownership for pending window requests and delayed post-transition callbacks | PKG-DPIP-02, PKG-DPIP-03, PKG-DPIP-05 |
| DPIP-DOM-01 | open / 已复现 | Document PiP copies global-document styles and retains original parent without transactional rollback | PKG-DPIP-02, PKG-DPIP-03, PKG-DPIP-05 |
| DPIP-STYLE-01 | resolved / 已复现 | Document PiP 1.1.0 and frozen source duplicate style IDs when evaluated before DOMContentLoaded | PKG-DPIP-03 |
| DPIP-MEDIA-01 | open / 已复现 | WebKit reports styled width640 for width320 media in the controlled Document PiP iframe matrix | PKG-DPIP-05 |
| DPIP-RESOLVE-01 | resolved / 已复现 | Historical Document PiP exports hide declarations or infer an uncallable CommonJS namespace in modern resolution | PKG-DPIP-04, PKG-DPIP-06 |
| FACTORY-TYPE-01 | open / 已复现 | Canvas and Ambilight default self property narrows assignability of historical factory replacements | PKG-FACTORY-01 |
+56 -6
View File
@@ -3460,12 +3460,19 @@
],
"compatibleResolution": "Support old default namespace access and new callable factory without changing runtime names or entrypoints.",
"closureCriteria": "Actual candidate root/legacy/global/ESM and installed consumers verify both access shapes.",
"status": "open",
"status": "resolved",
"evidence": [
"refactor/baselines/dpip-release.json",
"refactor/baselines/dpip-contract.md",
"refactor/changes/2026-09-12-PKG-DPIP-01-contract.md"
]
"refactor/changes/2026-09-12-PKG-DPIP-01-contract.md",
"refactor/changes/2026-09-12-PKG-DPIP-04-types.md",
"refactor/baselines/dpip-types-validation.json"
],
"resolutionEvidence": [
"refactor/changes/2026-09-12-PKG-DPIP-04-types.md",
"refactor/baselines/dpip-types-validation.json"
],
"resolutionRationale": "Actual main/legacy/global/ESM and real isolated installed root/legacy consumers verify direct callable and self default identities. Conditional declaration wrappers and old resolver legacy mapping are verified; full demo/archive and device scopes remain tasks05/06."
},
{
"id": "DPIP-TYPE-01",
@@ -3476,12 +3483,19 @@
],
"compatibleResolution": "Verify historical legal callers and extraction before providing precise async and readonly capabilities; do not reuse unrelated Ads approval.",
"closureCriteria": "Old/current consumer matrix and runtime/type distinctions are verified and documented without silently narrowing historical consumers.",
"status": "open",
"status": "resolved",
"evidence": [
"refactor/baselines/dpip-release.json",
"refactor/baselines/dpip-contract.md",
"refactor/changes/2026-09-12-PKG-DPIP-01-contract.md"
]
"refactor/changes/2026-09-12-PKG-DPIP-01-contract.md",
"refactor/changes/2026-09-12-PKG-DPIP-04-types.md",
"refactor/baselines/dpip-types-validation.json"
],
"resolutionEvidence": [
"refactor/changes/2026-09-12-PKG-DPIP-04-types.md",
"refactor/baselines/dpip-types-validation.json"
],
"resolutionRationale": "Exact required default factory signature and direct/extracted Result remain assignable, including whole-factory replacements. Named AsyncResult and RuntimeFactory describe unmodified runtime values explicitly. Historical import= module.default access is preserved by CJS declarations; source checks its precise result."
},
{
"id": "DPIP-LIFE-01",
@@ -3566,6 +3580,42 @@
"refactor/changes/2026-09-12-PKG-DPIP-02-tests.md",
"refactor/baselines/dpip-behavior-validation.json"
]
},
{
"id": "DPIP-RESOLVE-01",
"title": "Historical Document PiP exports hide declarations or infer an uncallable CommonJS namespace in modern resolution",
"status": "resolved",
"confirmation": "reproduced",
"owners": [
"PKG-DPIP-04",
"PKG-DPIP-06"
],
"compatibleResolution": "Use format-specific declaration wrappers and explicit types conditions while preserving old resolver paths and exact historical negative controls.",
"closureCriteria": "All candidate installed modes compile with exact invalid-use rejection; each historical missing type/default namespace failure stays recorded by version and mode.",
"evidence": [
"refactor/changes/2026-09-12-PKG-DPIP-04-types.md",
"refactor/baselines/dpip-types-validation.json"
],
"resolutionEvidence": [
"refactor/changes/2026-09-12-PKG-DPIP-04-types.md",
"refactor/baselines/dpip-types-validation.json"
],
"resolutionRationale": "27 isolated installed modes preserve eight exact historical failure cases; all seven candidate modes and twelve historical modes are zero-diagnostic. Published1.0.0 runtime absence is retained separately, not fixed in place."
},
{
"id": "FACTORY-TYPE-01",
"title": "Canvas and Ambilight default self property narrows assignability of historical factory replacements",
"status": "open",
"confirmation": "reproduced",
"owners": [
"PKG-FACTORY-01"
],
"compatibleResolution": "Preserve historical complete factory assignments while modeling actual export variants explicitly; do not equate unchanged Parameters with complete callable compatibility.",
"closureCriteria": "Both historical and candidate replacement fixtures, all supported export/declaration paths and installed consumers verified; unresolved variant conflicts require an explicit decision rather than silent narrowing.",
"evidence": [
"refactor/baselines/factory-assignment-gaps.json",
"refactor/changes/2026-09-12-PKG-DPIP-04-types.md"
]
}
]
}
+114
View File
@@ -0,0 +1,114 @@
import assert from 'node:assert/strict'
import fs from 'node:fs'
import path from 'node:path'
import process from 'node:process'
import ts from 'typescript'
import compat from 'typescript-compat'
import { checkFiles, packedFiles } from '../../scripts/package-check.mjs'
import { consumerDirectory, removeConsumer, run, workspace, writeJson } from '../../scripts/package-consumer.mjs'
import { verifyDpipContract } from './dpip-contract.mjs'
import { hash, readMember } from './releases.mjs'
async function main() {
assert.equal(process.env.npm_config_user_agent?.split(' ')[0], 'yarn/1.22.22', 'Use yarn test:dpip-types-package')
const yarn = process.env.npm_execpath
assert(yarn && fs.existsSync(yarn))
const output = fs.mkdtempSync(path.join(workspace, 'refactor/.cache/dpip-package-types-'))
console.log(`Document PiP isolated package evidence: ${output}`)
const contract = await verifyDpipContract()
const packages = []
for (const name of ['artplayer', 'artplayer-plugin-document-pip']) {
const archive = path.join(output, `${name}.tgz`)
fs.writeFileSync(path.join(output, `${name}-pack.log`), run([yarn, 'pack', '--filename', archive], path.join(workspace, 'packages', name)))
const manifest = JSON.parse(readMember(archive, 'package/package.json'))
const files = packedFiles(archive)
checkFiles(manifest, files, name === contract.baseline.release.name ? Object.keys(contract.baseline.release.files) : [])
packages.push({ name, archive, sha256: hash(fs.readFileSync(archive)), files: Object.fromEntries(files.map(member => [member, hash(readMember(archive, member))])) })
}
const matrix = []
const core = packages[0]
const candidates = [
...[...contract.baseline.previous].reverse().concat(contract.baseline.release).map(release => ({ ...release, archive: contract.archives.get(release.version), label: `published-${release.version}` })),
{ ...packages[1], label: 'candidate' },
]
for (const plugin of candidates) {
const consumer = consumerDirectory()
try {
writeJson(path.join(consumer, 'package.json'), { name: 'dpip-isolated-consumer', private: true, dependencies: Object.fromEntries([core, plugin].map(pkg => [pkg.name, `file:${pkg.archive.replaceAll('\\', '/')}`])) })
fs.copyFileSync(path.join(workspace, 'yarn.lock'), path.join(consumer, 'yarn.lock'))
fs.writeFileSync(path.join(output, `${plugin.label}-install.log`), run([yarn, 'install', '--offline', '--ignore-scripts', '--non-interactive'], consumer))
const lock = fs.readFileSync(path.join(consumer, 'yarn.lock'))
fs.writeFileSync(path.join(output, `${plugin.label}-frozen-install.log`), run([yarn, 'install', '--offline', '--frozen-lockfile', '--ignore-scripts', '--non-interactive'], consumer))
assert.deepEqual(fs.readFileSync(path.join(consumer, 'yarn.lock')), lock)
fs.writeFileSync(path.join(output, `${plugin.label}-yarn.lock`), lock)
for (const pkg of [core, plugin]) {
const root = path.join(consumer, 'node_modules', pkg.name)
assert.equal(fs.realpathSync(root), root, 'Installed package must not be a workspace link')
for (const [member, expected] of Object.entries(pkg.files))
assert.equal(hash(fs.readFileSync(path.join(root, member.slice(8)))), expected, `Installed bytes differ: ${member}`)
}
const runtimeFile = path.join(consumer, 'exports.cjs')
fs.writeFileSync(runtimeFile, plugin.label === 'candidate'
? `const assert = require('node:assert/strict');
for (const name of ['artplayer-plugin-document-pip', 'artplayer-plugin-document-pip/legacy']) { const factory = require(name); assert.equal(typeof factory, 'function'); assert.equal(factory.default, factory); assert.equal(typeof factory(), 'function'); }
import('artplayer-plugin-document-pip').then(module => { assert.deepEqual(Object.keys(module), ['default']); assert.equal(module.default.default, module.default); }).catch(error => { console.error(error); process.exitCode = 1; });`
: plugin.version === '1.0.0'
? `const assert = require('node:assert/strict'); assert.throws(() => require('artplayer-plugin-document-pip'), error => error.code === 'MODULE_NOT_FOUND' && error.message.includes('artplayer-plugin-document-pip')); console.log('Expected historical 1.0.0 missing runtime preserved');`
: `const assert = require('node:assert/strict'); const value = require('artplayer-plugin-document-pip'); assert.equal(typeof value, '${plugin.version === '1.1.0' ? 'function' : 'object'}'); assert.equal(typeof (value.default || value)({}), 'function');`)
fs.writeFileSync(path.join(output, `${plugin.label}-runtime.log`), run([runtimeFile], consumer))
const modes = [[ts, 'node10-commonjs'], [ts, 'nodenext-cjs'], [ts, 'nodenext-esm'], [ts, 'bundler-esm'], [compat, 'node10-commonjs']]
if (plugin.label === 'candidate')
modes.push([ts, 'node10-commonjs-no-interop'], [compat, 'node10-commonjs-no-interop'])
for (const [compiler, mode] of modes) {
const next = mode.startsWith('nodenext')
const extension = next ? mode.endsWith('-cjs') ? 'cts' : 'mts' : 'ts'
const source = fs.readFileSync(path.join(workspace, plugin.label === 'candidate' ? 'test/types/dpip.ts' : 'refactor/fixtures/consumers/dpip-published.ts'), 'utf8')
const filename = path.join(consumer, `consumer.${extension}`)
const historical = path.join(consumer, `historical.${extension}`)
fs.copyFileSync(path.join(workspace, 'refactor/fixtures/consumers/dpip-published.ts'), historical)
const files = plugin.label === 'candidate' ? [filename, historical] : [filename]
if (mode === 'nodenext-cjs' && plugin.label === 'candidate') {
const commonjs = path.join(consumer, 'commonjs.cts')
fs.writeFileSync(commonjs, `import dpip = require('artplayer-plugin-document-pip'); import legacy = require('artplayer-plugin-document-pip/legacy'); dpip.default({ width: 640 }); legacy.default({});`)
files.push(commonjs)
}
const options = { strict: true, noEmit: true, skipLibCheck: false, types: [], esModuleInterop: !mode.endsWith('-no-interop'), target: compiler.ScriptTarget.ES2020, lib: ['lib.es2020.d.ts', 'lib.dom.d.ts'], module: next ? compiler.ModuleKind.NodeNext : mode === 'bundler-esm' ? compiler.ModuleKind.ESNext : compiler.ModuleKind.CommonJS, moduleResolution: next ? compiler.ModuleResolutionKind.NodeNext : mode === 'bundler-esm' ? compiler.ModuleResolutionKind.Bundler : compiler.ModuleResolutionKind.NodeJs }
function compile(code) {
fs.writeFileSync(filename, code)
const program = compiler.createProgram(files, options)
for (const file of program.getSourceFiles()) {
const actual = fs.realpathSync(file.fileName)
assert(actual.startsWith(fs.realpathSync(consumer) + path.sep) || (program.isSourceFileDefaultLibrary(file) && path.dirname(actual) === fs.realpathSync(path.dirname(compiler.sys.getExecutingFilePath()))), `Types escaped installed consumer: ${actual}`)
}
return compiler.getPreEmitDiagnostics(program).map(item => ({ code: item.code, message: compiler.flattenDiagnosticMessageText(item.messageText, '\n') }))
}
const diagnostics = compile(source)
const modernResolution = next || mode === 'bundler-esm'
const expected = plugin.label === 'published-1.0.0' && modernResolution
? [2307]
: plugin.label === 'published-1.0.1' && modernResolution
? [7016]
: ['published-1.0.2', 'published-1.1.0'].includes(plugin.label) && mode === 'nodenext-esm'
? [2322, 2344, 2349, 2349, 2344, 2344, 2349]
: []
const historicalFailure = expected.length !== 0
writeJson(path.join(output, `${plugin.label}-${compiler.version}-${mode}-diagnostics.json`), { diagnostics, historicalFailure })
assert.deepEqual(diagnostics.map(item => item.code), expected, `${plugin.label} ${compiler.version} ${mode}`)
const invalid = plugin.label === 'candidate' ? compile(source.replaceAll(/\/\/ @ts-expect-error[^\n]*\n/g, '')) : []
if (plugin.label === 'candidate')
assert.equal(invalid.length, 14, 'Installed declarations must reject all invalid uses')
matrix.push({ plugin: plugin.label, compiler: compiler.version, mode, historicalFailure, diagnostics, invalid })
}
}
finally {
removeConsumer(consumer)
}
}
writeJson(path.join(output, 'report.json'), { suite: 'dpip-isolated-package-types', introducedBy: 'PKG-DPIP-04', scope: 'Four actual published packages and packed candidate installed outside workspace with packed candidate core; offline and frozen reinstall, exact bytes, compiler/default/import= contracts. Candidate keeps required Parameters and assignable void Result while offering opt-in AsyncResult. Published 1.0.0 missing runtime is an explicit negative control; historical NodeNext ESM diagnostics are retained. This is not native Document PiP or complete distribution/device acceptance.', packages, published: candidates.slice(0, 4).map(pkg => ({ label: pkg.label, archive: pkg.archive, sha256: hash(fs.readFileSync(pkg.archive)), missingEntrypoints: pkg.missingEntrypoints })), matrix })
console.log(`Document PiP installed types passed: ${matrix.length} cases; ${output}`)
}
main().catch((error) => {
console.error(error)
process.exitCode = 1
})
+98
View File
@@ -0,0 +1,98 @@
import assert from 'node:assert/strict'
import fs from 'node:fs'
import path from 'node:path'
// eslint-disable-next-line test/no-import-node-test -- Node compatibility baseline runner.
import test from 'node:test'
import vm from 'node:vm'
import { ESLint } from 'eslint'
import ts from 'typescript'
import compat from 'typescript-compat'
import { checkPluginEditorDeclaration, generatePluginEditorDeclaration } from '../../scripts/plugin-editor-types.mjs'
import { checkConsumer } from '../../scripts/typecheck.mjs'
import { verifyDpipContract } from './dpip-contract.mjs'
import { readMember } from './releases.mjs'
const modes = [[ts, 'node10-commonjs'], [ts, 'nodenext-cjs'], [ts, 'nodenext-esm'], [ts, 'bundler-esm'], [compat, 'node10-commonjs']]
test('Document PiP types retain required extraction and assignable void results alongside an opt-in precise view', () => {
const source = fs.readFileSync('test/types/dpip.ts', 'utf8')
for (const [compiler, mode] of modes) {
assert.deepEqual(checkConsumer(compiler, mode, source), [], `${compiler.version} ${mode}`)
assert.equal(checkConsumer(compiler, mode, source.replaceAll(/\/\/ @ts-expect-error[^\n]*\n/g, '')).length, 14)
}
assert.deepEqual(checkConsumer(ts, 'nodenext-cjs', `import dpip = require('artplayer-plugin-document-pip'); import legacy = require('artplayer-plugin-document-pip/legacy');
const options: dpip.Option = { width: 640 }; dpip.default(options); legacy.default(options);`), [])
})
test('Document PiP all four published declarations accept the same old result replacements and required Parameters', async () => {
const contract = await verifyDpipContract()
const source = fs.readFileSync('refactor/fixtures/consumers/dpip-published.ts', 'utf8')
for (const version of ['1.0.0', '1.0.1', '1.0.2', '1.1.0']) {
const old = readMember(contract.archives.get(version), 'package/types/artplayer-plugin-document-pip.d.ts').toString()
for (const compiler of [ts, compat]) {
const filename = path.resolve('test/types/dpip-history.ts')
const declaration = path.resolve('test/types/dpip-history.d.ts')
function historical(code) {
const host = compiler.createCompilerHost({})
const original = host.getSourceFile.bind(host)
host.getSourceFile = (file, language, ...rest) => path.resolve(file) === filename
? compiler.createSourceFile(file, code.replace('from \'artplayer-plugin-document-pip\'', 'from \'./dpip-history\''), language, true)
: path.resolve(file) === declaration ? compiler.createSourceFile(file, old, language, true) : original(file, language, ...rest)
const exists = host.fileExists.bind(host)
host.fileExists = file => path.resolve(file) === declaration || exists(file)
const program = compiler.createProgram([filename, declaration], { strict: true, noEmit: true, skipLibCheck: false, types: [], esModuleInterop: true, module: compiler.ModuleKind.CommonJS, moduleResolution: compiler.ModuleResolutionKind.NodeJs, target: compiler.ScriptTarget.ES2020, lib: ['lib.es2020.d.ts', 'lib.dom.d.ts'] }, host)
assert(program.getSourceFile(declaration))
return compiler.getPreEmitDiagnostics(program).map(item => item.code)
}
const replacements = `${source}\nconst replacement: typeof dpip = (_option: Parameters<typeof dpip>[0]) => (_art: Artplayer) => fake;`
assert.deepEqual(historical(replacements), [])
assert.deepEqual(checkConsumer(compiler, 'node10-commonjs', replacements), [])
assert.deepEqual(historical(`${source}\ndpip();`), [2554])
assert.deepEqual(historical(`${source}\nconst missing: Parameters<typeof dpip>[0] = undefined;`), [2322])
assert.deepEqual(checkConsumer(compiler, 'node10-commonjs', `${source}\ndpip();`).map(item => item.code), [2554])
assert.deepEqual(checkConsumer(compiler, 'node10-commonjs', `${source}\nconst missing: Parameters<typeof dpip>[0] = undefined;`).map(item => item.code), [2322])
}
}
})
test('Document PiP editor globals preserve legacy results and explicitly expose readonly async actions', async () => {
const source = fs.readFileSync('packages/artplayer-plugin-document-pip/types/artplayer-plugin-document-pip.d.ts', 'utf8')
const generated = generatePluginEditorDeclaration(source, 'artplayerPluginDocumentPip')
const file = 'docs/assets/ts/artplayer-plugin-document-pip.d.ts'
const [formatted] = await new ESLint({ fix: true, fixTypes: ['layout'] }).lintText(generated, { filePath: file })
assert.equal(formatted.errorCount, 0)
assert.equal(fs.readFileSync(file, 'utf8').replaceAll('\r\n', '\n'), formatted.output || generated)
const core = fs.readFileSync('docs/assets/ts/artplayer.d.ts', 'utf8')
const consumer = `artplayerPluginDocumentPip({ width: 640 });
const factory = artplayerPluginDocumentPip as artplayerPluginDocumentPip.RuntimeFactory; factory(); factory.default();
declare const runtime: artplayerPluginDocumentPip.AsyncResult;
const opening: Promise<void> = runtime.open(); const old: artplayerPluginDocumentPip.Result = runtime;
old.open = () => {};
// @ts-expect-error Precise runtime capability is readonly.
runtime.isSupported = false;
// @ts-expect-error Dimensions remain numeric.
artplayerPluginDocumentPip({ width: '640' });`
for (const compiler of [ts, compat]) {
assert.deepEqual(checkPluginEditorDeclaration(generated, core, consumer, compiler), [])
assert.equal(checkPluginEditorDeclaration(generated, core, consumer.replaceAll(/\/\/ @ts-expect-error[^\n]*\n/g, ''), compiler).length, 2)
}
})
test('Document PiP production main, legacy, globals and native ESM preserve callable and default identities', async () => {
for (const suffix of ['js', 'legacy.js']) {
const source = fs.readFileSync(`packages/artplayer-plugin-document-pip/dist/artplayer-plugin-document-pip.${suffix}`, 'utf8')
const module = { exports: {} }
vm.runInNewContext(source, { module, exports: module.exports, window: {} })
assert.equal(typeof module.exports, 'function')
assert.equal(module.exports.default, module.exports)
assert.equal(typeof module.exports.default(), 'function')
const global = { window: {} }
vm.runInNewContext(source, global)
const factory = global.artplayerPluginDocumentPip || global.window.artplayerPluginDocumentPip
assert.equal(factory.default, factory)
}
const source = fs.readFileSync('packages/artplayer-plugin-document-pip/dist/artplayer-plugin-document-pip.mjs', 'utf8')
const module = await import(`data:text/javascript,${encodeURIComponent(source)}`)
assert.deepEqual(Object.keys(module), ['default'])
assert.equal(module.default.default, module.default)
})
+33 -5
View File
@@ -1569,7 +1569,8 @@
"PKG-AMBILIGHT-04",
"CORE-22",
"PKG-AMBILIGHT-PROXY-01",
"PKG-CANVAS-04"
"PKG-CANVAS-04",
"PKG-FACTORY-01"
],
"status": "todo",
"risk": "M",
@@ -3054,11 +3055,15 @@
"ENG-06",
"CORE-07"
],
"status": "todo",
"status": "done",
"risk": "H",
"deliverable": "Document PiP 可选能力和真实状态/返回类型",
"acceptance": "严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容",
"evidence": []
"evidence": [
"changes/2026-09-12-PKG-DPIP-04-types.md",
"baselines/dpip-types-validation.json",
"dpip-validation.md"
]
},
{
"id": "PKG-DPIP-05",
@@ -3350,7 +3355,8 @@
"dependsOn": [
"PKG-CANVAS-04",
"CORE-22",
"PKG-DPIP-04"
"PKG-DPIP-04",
"PKG-FACTORY-01"
],
"status": "todo",
"risk": "H",
@@ -4083,7 +4089,8 @@
"PKG-IFRAME-04",
"PKG-TOOL-THUMB-04",
"PKG-DANMUKU-06",
"PKG-MB-08"
"PKG-MB-08",
"PKG-FACTORY-01"
],
"status": "todo",
"risk": "H",
@@ -4269,6 +4276,27 @@
"deliverable": "最终任务/设计/证据归档和维护指南",
"acceptance": "全范围任务有结论、无未解释兼容缺口;遗留项有明确后续责任",
"evidence": []
},
{
"id": "PKG-FACTORY-01",
"phase": "5 工厂类型兼容补审",
"title": "修复已迁移工厂的反向赋值兼容",
"scope": [
"artplayer-proxy-canvas",
"artplayer-plugin-ambilight"
],
"dependsOn": [
"PKG-CANVAS-04",
"PKG-AMBILIGHT-04",
"PKG-DPIP-04"
],
"status": "todo",
"risk": "H",
"deliverable": "复现两包旧typeof工厂替换与新.default/可选重载冲突,修复公开类型并补安装消费者、产物和文档",
"acceptance": "默认工厂的历史合法反向赋值继续通过;既有类型/运行时导出逐版本核对,不能只验证Parameters或直接调用",
"evidence": [
"baselines/factory-assignment-gaps.json"
]
}
]
}
+1 -1
View File
@@ -43,7 +43,7 @@ console.log(`✨ Built ${artplayerTSoutput}`);
const type = pluginsTS[index]
const { name, file } = parsePluginInfo(type)
const source = String(fs.readFileSync(type))
const semanticPlugin = ['artplayerPluginHlsControl', 'artplayerPluginAudioTrack', 'artplayerPluginDashControl', 'artplayerPluginAds', 'artplayerPluginAmbilight', 'artplayerProxyCanvas'].includes(name)
const semanticPlugin = ['artplayerPluginHlsControl', 'artplayerPluginAudioTrack', 'artplayerPluginDashControl', 'artplayerPluginAds', 'artplayerPluginAmbilight', 'artplayerProxyCanvas', 'artplayerPluginDocumentPip'].includes(name)
const code = semanticPlugin
? generatePluginEditorDeclaration(source, name)
: `${source.replace(reg, '')}\nexport = ${name};\nexport as namespace ${name};\n`
+1 -1
View File
@@ -76,7 +76,7 @@ export function runTypechecks() {
for (const fixture of ['test/types/public.ts', 'test/types/declaration-inputs.ts', 'test/types/declaration-legacy.ts', 'test/types/plugins-public.ts', 'test/types/playback-public.ts', 'test/types/chapter-options.ts', 'test/types/chapter-exports.ts', 'test/types/hls-control.ts', 'test/types/dash-control.ts', 'test/types/ads.ts', 'refactor/fixtures/consumers/ads-published.ts', 'refactor/fixtures/consumers/ads-workspace.ts', 'refactor/fixtures/consumers/dash-control-legacy.ts', 'test/types/audio-track.ts', 'test/types/language-value.ts', 'refactor/fixtures/consumers/language.ts', 'refactor/fixtures/consumers/legacy-plugin.ts']) {
assert.deepEqual(checkConsumer(compiler, mode, fs.readFileSync(path.join(root, fixture), 'utf8')), [], `Consumer failed: TS ${compiler.version} ${mode} ${fixture}`)
}
for (const fixture of ['test/types/ambilight.ts', 'refactor/fixtures/consumers/ambilight-published.ts', 'test/types/canvas.ts', 'refactor/fixtures/consumers/canvas-published.ts'])
for (const fixture of ['test/types/ambilight.ts', 'refactor/fixtures/consumers/ambilight-published.ts', 'test/types/canvas.ts', 'refactor/fixtures/consumers/canvas-published.ts', 'test/types/dpip.ts', 'refactor/fixtures/consumers/dpip-published.ts'])
assert.deepEqual(checkConsumer(compiler, mode, fs.readFileSync(path.join(root, fixture), 'utf8')), [], `Consumer failed: TS ${compiler.version} ${mode} ${fixture}`)
if (mode === 'nodenext-cjs')
assert.deepEqual(checkConsumer(compiler, mode, fs.readFileSync(path.join(root, 'test/types/commonjs.cts'), 'utf8')), [], 'CommonJS export assignment consumer failed')
+67
View File
@@ -0,0 +1,67 @@
import type { AsyncResult, Factory, Option, Result, RuntimeFactory } from 'artplayer-plugin-document-pip'
import Artplayer from 'artplayer'
import dpip from 'artplayer-plugin-document-pip'
import legacy from 'artplayer-plugin-document-pip/legacy'
type Equal<A, B> = (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2) ? true : false
type Assert<T extends true> = T
type ExactParameters = Assert<Equal<Parameters<typeof dpip>, [option: Option]>>
type ExactResult = Assert<Equal<ReturnType<ReturnType<typeof dpip>>, Result>>
type ExactOpen = Assert<Equal<ReturnType<Result['open']>, void>>
type ExactDirectOpen = Assert<Equal<ReturnType<typeof result.open>, void>>
type ExactFactory = Assert<Equal<typeof dpip, (option: Option) => (art: Artplayer) => Result>>
const options: Option = { width: 640, height: 360, placeholder: 'Active', fallbackToVideoPiP: false }
const art = new Artplayer({ container: '#player', url: 'video.mp4', plugins: [dpip(options)] })
const runtimeFactory = dpip as RuntimeFactory
runtimeFactory()
runtimeFactory(undefined)
runtimeFactory.default(options)
legacy(options)
declare const optional: Option | undefined
runtimeFactory(optional)
const factory: Factory = dpip
const result = factory(options)(art)
result.open = () => {}
result.close = () => {}
const mutable: Result = { name: 'artplayerPluginDocumentPip', isSupported: true, isActive: false, open() {}, close() {}, toggle() {} }
mutable.isActive = true
mutable.isSupported = false
const oldFactoryReplacement: typeof dpip = (_options: Option) => (_art: Artplayer) => mutable
const returned: void = result.open()
const asyncResult: AsyncResult = runtimeFactory()(art)
const opening: Promise<void> = asyncResult.open()
const closing: Promise<void> = asyncResult.close()
const toggled: void = asyncResult.toggle()
const snapshot: boolean = asyncResult.isSupported
const historical: Result = asyncResult
// @ts-expect-error Parameters extraction keeps the historical required option.
const missing: Parameters<typeof dpip>[0] = undefined
// @ts-expect-error Width is numeric.
dpip({ width: '640' })
// @ts-expect-error Height is numeric.
dpip({ height: '360' })
// @ts-expect-error Placeholder is text.
dpip({ placeholder: 1 })
// @ts-expect-error Fallback is boolean.
dpip({ fallbackToVideoPiP: 'yes' })
// @ts-expect-error Null was never a typed option.
dpip(null)
// @ts-expect-error Unknown options remain errors.
dpip({ arbitrary: true })
// @ts-expect-error Registration requires its Artplayer host.
dpip({})()
// @ts-expect-error Plugin registration remains synchronous.
const asyncRegistration: Promise<Result> = dpip({})(art)
// @ts-expect-error The opt-in runtime state is readonly.
asyncResult.isActive = true
// @ts-expect-error The opt-in capability snapshot is readonly.
asyncResult.isSupported = true
// @ts-expect-error Exact async actions cannot be replaced with void actions in this view.
asyncResult.open = () => {}
// @ts-expect-error Legacy void defaults do not falsely promise an awaitable return.
const wrongPromise: Promise<void> = result.open()
// @ts-expect-error Self default identity is readonly in declarations.
runtimeFactory.default = runtimeFactory
void [oldFactoryReplacement, returned, opening, closing, toggled, snapshot, historical, missing, asyncRegistration, wrongPromise]
export type { ExactDirectOpen, ExactFactory, ExactOpen, ExactParameters, ExactResult }