@phont-ai/subtitles-core 0.1.10 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -0
- package/dist/browser.d.mts +140 -0
- package/dist/browser.d.ts +140 -0
- package/dist/browser.js +1 -0
- package/dist/browser.mjs +1 -0
- package/dist/index.d.mts +523 -403
- package/dist/index.d.ts +1463 -7
- package/dist/index.js +3 -5414
- package/dist/index.mjs +3 -5347
- package/dist/phont-subtitles.global.js +2 -0
- package/package.json +37 -14
- package/dist/client/PhontClient.d.ts +0 -16
- package/dist/types/registration.d.ts +0 -46
- package/dist/utils/video-handling.d.ts +0 -33
- package/dist/validation/registration.d.ts +0 -64
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var PhontSubtitles=(()=>{var it=Object.defineProperty;var Ft=Object.getOwnPropertyDescriptor;var Pt=Object.getOwnPropertyNames;var Ht=Object.prototype.hasOwnProperty;var It=(t,e)=>{for(var n in e)it(t,n,{get:e[n],enumerable:!0})},Rt=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Pt(e))!Ht.call(t,i)&&i!==n&&it(t,i,{get:()=>e[i],enumerable:!(r=Ft(e,i))||r.enumerable});return t};var Nt=t=>Rt(it({},"__esModule",{value:!0}),t);var Dt={};It(Dt,{attach:()=>vt,decodeAnimationUrl:()=>K,loadMetadataTrack:()=>Tt,sampleAt:()=>tt,version:()=>Xt});function jt(t,e=!1){if(!t)return[];try{return t.split("|").map(n=>{let[r,i]=n.split(","),o=e||typeof i=="string"&&(i.startsWith("#")||i.startsWith("%23")),s;return o?s=i.replace(/%23/g,"#"):s=parseFloat(i),{time:parseFloat(r),value:s}})}catch(n){return console.error("Error decoding points:",n),[]}}function zt(t){if(!t)return"";if(t.includes("://"))try{let e=new URL(t);return e.search.startsWith("?")?e.search.slice(1):e.search}catch{let e=t.indexOf("?");return e!==-1?t.substring(e+1):t}return t.startsWith("?")?t.slice(1):t}function K(t){try{let e=zt(t),n=new URLSearchParams(e),r={parameterStates:{}};if(n.has("name")&&(r.name=n.get("name")||void 0),n.has("user")&&(r.userName=n.get("user")||void 0),n.has("duration")&&(r.duration=parseFloat(n.get("duration")||"0")),n.has("mode")&&(r.animationMode=n.get("mode")||void 0),n.has("text")&&(r.text=n.get("text")||void 0),n.get("format")==="normalized"&&(r.format="normalized"),n.has("font"))try{let o=JSON.parse(n.get("font")||"{}");o&&typeof o=="object"&&(o.style||o.config||o.fontId?r.fontData={style:o.style,config:o.config||null,fontId:o.fontId||null,fontName:o.fontName||null}:r.fontData={style:o,config:null})}catch(o){console.warn("Failed to parse font data:",o)}if(n.has("bg"))try{r.backgroundStyle=JSON.parse(n.get("bg")||"{}")}catch(o){console.warn("Failed to parse background style:",o)}for(let[o,s]of n.entries())if(!["name","user","duration","mode","text","font","bg","v","c","m","p","format"].includes(o)&&(s.includes("|")||s.includes(","))){let l=o==="color"||o==="shadowColor"||o==="outlineColor"||s.includes("%23"),f=jt(s,l);if(f.length>0){let m=l?"#000000":0;r.parameterStates[o]={points:f,currentValue:f[0]?.value||m}}}return r}catch(e){throw console.error("Error decoding animation URL:",e),new Error("Failed to decode animation URL. The link may be invalid or corrupted.")}}function Q(t){if(typeof t!="string")return{r:0,g:0,b:0};let e=t.replace("#","").padStart(6,"0"),n=/^([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return n?{r:parseInt(n[1],16),g:parseInt(n[2],16),b:parseInt(n[3],16)}:{r:0,g:0,b:0}}function ft(t,e,n){let r=i=>{let o=Math.round(Math.max(0,Math.min(255,i))).toString(16);return o.length===1?"0"+o:o};return"#"+r(t)+r(e)+r(n)}function mt(t,e,n){let r=Q(t),i=Q(e),o=Math.max(0,Math.min(1,n)),s=r.r+(i.r-r.r)*o,l=r.g+(i.g-r.g)*o,f=r.b+(i.b-r.b)*o;return ft(s,l,f)}function Yt(t,e,n){if(n===0)return t;let r=Q(t),i=Q(e),o=r.r+(i.r-r.r)*n,s=r.g+(i.g-r.g)*n,l=r.b+(i.b-r.b)*n;return ft(o,s,l)}function Z(t,e,n,r=!1,i=null){if(!t||t.length===0)return null;let o=r?e:e*n,s=null,l=null;for(let f=0;f<t.length;f++){let m=t[f],c=m.time!==void 0?m.time:Array.isArray(m)?m[0]:0;if(c!==void 0&&c<=o&&(s=m),c!==void 0&&c>=o&&!l){l=m;break}}if(!s&&t[0])return(t[0].value!==void 0?t[0].value:Array.isArray(t[0])?t[0][1]:null)??null;if(!l&&s)return(s.value!==void 0?s.value:Array.isArray(s)?s[1]:null)??null;if(s&&l){let f=s.time!==void 0?s.time??0:Array.isArray(s)?s[0]:0,m=l.time!==void 0?l.time??0:Array.isArray(l)?l[0]:0,c=s.value!==void 0?s.value:Array.isArray(s)?s[1]:null,d=l.value!==void 0?l.value:Array.isArray(l)?l[1]:null;if(f===m||c===null||d===null)return c??null;let a=(o-f)/(m-f),y=i==="color"||i==="shadowColor"||i==="outlineColor"||i==="outline2Color"||i==="outline3Color"||i==="outlineShadowColor"||i==="glowColor";if(y&&(typeof c=="string"||typeof d=="string"))return mt(typeof c=="string"?c:"#000000",typeof d=="string"?d:"#000000",a);if(!y&&(typeof c=="string"||typeof d=="string")){let W=typeof c=="string"&&(c.startsWith("#")||/^[0-9a-f]{6}$/i.test(c)),C=typeof d=="string"&&(d.startsWith("#")||/^[0-9a-f]{6}$/i.test(d));if(W&&C){let E=c.startsWith("#")?c:`#${c}`,T=d.startsWith("#")?d:`#${d}`;return mt(E,T,a)}return d??null}return c+(d-c)*a}return null}var st=.7,Bt=.7;function tt(t,e,n,r,i=null,{rawMode:o=!1}={}){if(!t||!t.parameterStates)return null;let s=o?1:e*r/(st*Bt),l=t.duration||2,m=t.format==="normalized"?n:n*l,c=!0,d=t.parameterStates||{},a=(p,w,v=!0,M=null)=>{let dt=M??s,J=Z(d[p]?.points,m,l,c);return J==null?w:v?dt===0?w:w+(J-w)*dt:J},y=a("scale",1),W=a("skew",0),C=a("stretch",1),E=a("translateX",0),T=a("translateY",0),L=a("weight",500),$=a("width",100),I=(t.fontData||{}).style?.fontFamily||"Roboto Flex",V=t.text||"Hello",k=(p,w)=>{let v=Z(d[p]?.points,m,l,c,p);if(v==null)return w;let M=typeof v=="string"?v.startsWith("#")?v:`#${v}`:`#${Math.round(v).toString(16).padStart(6,"0")}`;return s===0?w:Yt(w,M,s)},O=k("color","#ffffff"),A=a("opacity",1),z=a("shadowX",0),u=a("shadowY",0),h=a("shadowBlur",4),g=a("shadowOpacity",.5),b=k("shadowColor","#000000"),R=a("outlineWidth",0),N=k("outlineColor","#000000"),x=p=>d[p]?.points?.length>0,X=x("stretchX")?a("stretchX",1):void 0,D=x("outline2Width")?a("outline2Width",0):void 0,j=x("outline2Color")?k("outline2Color","#000000"):void 0,_=x("outline3Width")?a("outline3Width",0):void 0,U=x("outline3Color")?k("outline3Color","#000000"):void 0,q=x("outlineShadowWidth")?a("outlineShadowWidth",0):void 0,F=x("outlineShadowColor")?k("outlineShadowColor","#000000"):void 0,Y=x("outlineShadowBlur")?a("outlineShadowBlur",0):void 0,P=x("glowIntensity")?a("glowIntensity",0):void 0,G=x("glowColor")?k("glowColor","#ffffff"):void 0,ut=x("snakeWave")?a("snakeWave",0):void 0,ct=x("karaoke")?a("karaoke",0):void 0,Ct=1-.5*Math.min(1,Math.max(0,r)),kt=a("blur",0,!0,o?1:s*Ct),nt=Z(d.thinStroke?.points,m,l,c),rt=Z(d.ascenderHeight?.points,m,l,c),B={};nt!=null&&typeof nt=="number"&&(B.YOPQ=nt),rt!=null&&typeof rt=="number"&&(B.YTAS=rt),L!=null&&(B.wght=L),$!=null&&(B.wdth=$);let H=[];if(z!==0||u!==0||h!==4||g!==.5){let p=typeof b=="string"?b:"#000000",w=parseInt(p.slice(1,3),16),v=parseInt(p.slice(3,5),16),M=parseInt(p.slice(5,7),16);H.push(`${z}px ${u}px ${h}px rgba(${w}, ${v}, ${M}, ${g})`)}else if(b&&typeof b=="string"&&b!=="#000000"){let p=b.startsWith("#")?b:`#${b}`,w=parseInt(p.slice(1,3),16)||0,v=parseInt(p.slice(3,5),16)||0,M=parseInt(p.slice(5,7),16)||0;H.push(`3px 2px 4px rgba(${w}, ${v}, ${M}, 0.5)`)}if(P!=null&&P>0){let p=typeof G=="string"?G:"#ffffff";H.push(`0 0 ${P}px ${p}`),H.push(`0 0 ${P*2}px ${p}`),H.push(`0 0 ${P*4}px ${p}`)}let Et=H.length>0?H.join(", "):"",ot=0;if(d.joy?.points&&d.joy.points.length>0)for(let p of d.joy.points){let w=Array.isArray(p)?p[1]:p.y??p.value??0;typeof w=="number"&&w>ot&&(ot=w)}let At=a("joy",0,!1),Mt=o?At:Math.min(1,ot*s),Wt=a("fear",0),Lt=a("standardEmphasis",0,!1),$t=a("strongEmphasis",0,!1),S={rawIntensity:e,scaleFactor:s,scale:y,slant:W,stretchY:C,translateX:E,translateY:T,weight:L,width:$,fontFamily:I,textColor:O,opacity:A,textShadow:Et,blur:kt,outlineWidth:R,outlineColor:N,letterSpacing:`${Math.max(0,(y-1)*.02)}em`,fontVariationAxes:B,text:V,joy:Mt,fear:Wt,standardEmphasis:Lt,strongEmphasis:$t,joyWaveProgress:m/l*1.5};return X!==void 0&&(S.stretchX=X),D!==void 0&&(S.outline2Width=D),j!==void 0&&(S.outline2Color=j),_!==void 0&&(S.outline3Width=_),U!==void 0&&(S.outline3Color=U),q!==void 0&&(S.outlineShadowWidth=q),F!==void 0&&(S.outlineShadowColor=F),Y!==void 0&&(S.outlineShadowBlur=Y),P!==void 0&&(S.glowIntensity=P),G!==void 0&&(S.glowColor=G),ut!==void 0&&(S.snakeWave=ut),ct!==void 0&&(S.karaoke=ct),S}var pt={},Vt={"Roboto Flex":"family=Roboto+Flex:opsz,wdth,wght,YOPQ,YTAS@8..144,25..151,100..1000,25..125,649..854&display=swap",Rakkas:"family=Rakkas&display=swap",Parkinsans:"family=Parkinsans:wght@300..800&display=swap","Bricolage Grotesque":"family=Bricolage+Grotesque:opsz,wdth,wght@12..96,75..100,200..800&display=swap",Cormorant:"family=Cormorant:wght@300..700&display=block"};function ht(t){if(!t)return;let e=t.replace(/["']/g,"").split(",")[0].trim();if(!e||e==="sans-serif"||e==="serif"||pt[e]||(pt[e]=!0,typeof document>"u"))return;let n=Vt[e],r=document.createElement("link");r.rel="stylesheet",r.href=n?`https://fonts.googleapis.com/css2?${n}`:`https://fonts.googleapis.com/css2?family=${encodeURIComponent(e)}:wght@100..900&display=swap`,document.head.appendChild(r)}function at(t,e,n){let r=t.split(/\s+/).filter(Boolean);if(r.length===0)return[];let i=n-e,o=r.map(f=>f.length+1),s=o.reduce((f,m)=>f+m,0),l=e;return r.map((f,m)=>{let c=o[m]/s*i,d=Math.round(l*1e3)/1e3;return l+=c,{word:f,start:d,end:Math.round(l*1e3)/1e3}})}function gt(t){let e=t.parentElement;if(e&&e.classList.contains("phont-container"))return e;let n=document.createElement("div");return n.className="phont-container",n.style.cssText="position:relative;display:inline-block;width:100%;line-height:0;background:#000;",t.parentNode.insertBefore(n,t),n.appendChild(t),n}function yt(t){let e=document.createElement("div");return e.className="phont-subtitle-overlay",e.style.cssText="position:absolute;left:0;right:0;bottom:8%;display:flex;justify-content:center;align-items:center;pointer-events:none;z-index:10;padding:0 5%;box-sizing:border-box;",t.appendChild(e),e}function bt(t){let e=document.createElement("span");return e.className="phont-subtitle-text",e.style.cssText="display:inline-flex;flex-wrap:wrap;justify-content:center;align-items:baseline;gap:0;text-align:center;word-spacing:normal;",t.appendChild(e),e}function xt(){let t=document.createElement("style");return t.textContent=".phont-container video::-webkit-media-controls-fullscreen-button{display:none!important}.phont-container:fullscreen{background:#000}.phont-container:fullscreen video{width:100%;height:100%;object-fit:contain}",document.head.appendChild(t),t}function wt(t){let e=document.createElement("button");return e.className="phont-fs-btn",e.setAttribute("aria-label","Fullscreen"),e.innerHTML="⛶",e.style.cssText="position:absolute;top:12px;right:12px;z-index:20;background:rgba(0,0,0,0.55);border:none;color:#fff;font-size:18px;width:34px;height:34px;border-radius:6px;cursor:pointer;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s;pointer-events:auto;",t.appendChild(e),e}function lt(t,e){t.innerHTML="";let n=[];for(let r=0;r<e.length;r++){let i=document.createElement("span");i.className="phont-word",i.textContent=e[r].word,i.style.cssText="display:inline-block;white-space:pre;will-change:transform,opacity,margin;transform-origin:center bottom;transition:transform 60ms ease-out,opacity 60ms ease-out,filter 60ms ease-out,color 60ms ease-out,margin 60ms ease-out;",t.appendChild(i),n.push(i),r<e.length-1&&t.appendChild(document.createTextNode(" "))}return n}function Ot(t,e,n,r){t.style.fontSize=r,t.style.fontFamily=e.fontFamily,t.style.fontWeight=String(e.weight),t.style.fontStretch=`${e.width}%`,t.style.fontVariationSettings=`"wght" ${e.weight}, "wdth" ${e.width}`,t.style.color=e.textColor,t.style.transform=`skewX(${e.slant}deg) scaleX(${e.stretchX??1}) scaleY(${e.stretchY}) scale(${e.scale}) translate(${e.translateX}px,${e.translateY}px) translateZ(0)`,t.style.textShadow=e.textShadow||"none",t.style.filter=e.blur>0?`blur(${e.blur}px)`:"none",t.style.letterSpacing=e.letterSpacing,e.outlineWidth>0?(t.style.webkitTextStroke=`${e.outlineWidth}px ${e.outlineColor}`,t.style.paintOrder="stroke fill"):(t.style.webkitTextStroke="",t.style.paintOrder=""),t.style.opacity=String(n?e.opacity:Math.min(.25,e.opacity));let i=e.scale>1.01?(e.scale-1)*(t.textContent?.length||1)*.25:0,o=e.outlineWidth>0?e.outlineWidth*.02:0;t.style.marginLeft=i>0?`${i}em`:"",t.style.marginRight=`${.3+i+o}em`}function St(t,e,n){t.style.fontSize=n,t.style.opacity=e?"1":"0.25",t.style.color="#ffffff",t.style.transform="none",t.style.textShadow="1px 1px 3px rgba(0,0,0,0.7)",t.style.fontWeight="500",t.style.fontStretch="100%",t.style.fontVariationSettings='"wght" 500, "wdth" 100',t.style.filter="none",t.style.webkitTextStroke="",t.style.paintOrder="",t.style.letterSpacing="0em",t.style.marginLeft="",t.style.marginRight="0.3em"}function vt(t,e){let n=e||{},r=typeof t=="string"?document.querySelector(t):t;if(!r)return console.error("[PhontSubtitles] Video element not found:",t),null;let i=r,o=gt(i),s=xt(),l=wt(o),f=yt(o),m=bt(f);o.addEventListener("mouseenter",()=>{l.style.opacity="1"}),o.addEventListener("mouseleave",()=>{l.style.opacity="0"}),l.addEventListener("click",()=>{document.fullscreenElement||document.webkitFullscreenElement?(document.exitFullscreen||document.webkitExitFullscreen).call(document):(o.requestFullscreen||o.webkitRequestFullscreen).call(o)});function c(){let u=document.fullscreenElement||document.webkitFullscreenElement;l.innerHTML=u===o?"✖":"⛶"}document.addEventListener("fullscreenchange",c),document.addEventListener("webkitfullscreenchange",c);let d=null,a=null,y=null,W=.7,C=[],E=null,T=null,L=null;function $(){d=null,a=null,y=null,m.innerHTML="",m.style.opacity="0",C=[]}function et(){if(!d||!y||y.length===0){$();return}m.style.opacity="1";let u=i.currentTime,h=n.fontSize||"clamp(1.2rem, 3vw, 2.4rem)";for(let g=0;g<y.length;g++){let b=y[g],R=C[g];if(!R)continue;let N=b.start,x=b.end,X=Math.max(.01,x-N),D=Math.max(0,Math.min(1,(u-N)/X)),j=u>=N,_=u>=N&&u<x,U=u>=x;if(!a){St(R,j,h);continue}let q=b.gts!==void 0?b.gts:W,F;_?F=D:U?F=1:F=0;let Y=tt(a,st,F,q,null);if(!Y){St(R,j,h);continue}Ot(R,Y,j,h)}}function I(){let u=this;if(!u.activeCues||u.activeCues.length===0){$();return}let h=u.activeCues[0];try{let g=JSON.parse(h.text);if(d=h,g.words&&g.words.length>0?y=g.words:y=at(g.text||"",h.startTime,h.endTime),W=typeof g.gts=="number"?g.gts:.7,g.animation_url){a=K(g.animation_url);let b=a.fontData;ht(b?.style?.fontFamily??b?.fontName??null)}else a=null;C=lt(m,y)}catch{d=h,a=null,y=at(h.text||"",h.startTime,h.endTime),C=lt(m,y)}et()}function V(u){return u.kind!=="metadata"?!1:(u.mode="hidden",u.addEventListener("cuechange",I),T=u,!0)}function k(){if(!T||!T.activeCues)return;let u=T.activeCues;if(u.length===0){d&&$(),L=null;return}let h=u[0],g=`${h.startTime}_${h.endTime}`;g!==L&&(L=g,I.call(T))}function O(){k(),d&&et(),E=requestAnimationFrame(O)}let A=i.textTracks,z=!1;for(let u=0;u<A.length;u++)if(V(A[u])){z=!0;break}if(!z){let u=h=>{h.track&&h.track.kind==="metadata"&&(V(h.track),A.removeEventListener("addtrack",u))};A.addEventListener("addtrack",u)}return E=requestAnimationFrame(O),{overlay:f,wordsContainer:m,destroy(){E&&cancelAnimationFrame(E),T&&T.removeEventListener("cuechange",I);for(let u=0;u<A.length;u++)A[u].removeEventListener("cuechange",I);document.removeEventListener("fullscreenchange",c),document.removeEventListener("webkitfullscreenchange",c),s.parentNode&&s.remove(),l.remove(),f.remove()}}}function Tt(t,e){let n=document.createElement("track");return n.kind="metadata",n.src=e,n.default=!0,t.appendChild(n),n}var Xt="0.3.0";return Nt(Dt);})();
|
|
2
|
+
// Built from @phont-ai/subtitles-core — https://github.com/Phont-ai
|
package/package.json
CHANGED
|
@@ -1,37 +1,60 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phont-ai/subtitles-core",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Core
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"module": "dist/index.mjs",
|
|
7
|
-
"types": "dist/index.d.ts",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "Core subtitle engine for PHONT expressive subtitles - pure TypeScript, framework-agnostic",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
10
11
|
"import": "./dist/index.mjs",
|
|
11
12
|
"require": "./dist/index.js",
|
|
12
|
-
"
|
|
13
|
+
"default": "./dist/index.mjs"
|
|
14
|
+
},
|
|
15
|
+
"./browser": {
|
|
16
|
+
"types": "./dist/browser.d.ts",
|
|
17
|
+
"import": "./dist/browser.mjs",
|
|
18
|
+
"require": "./dist/browser.js",
|
|
19
|
+
"default": "./dist/browser.mjs"
|
|
13
20
|
}
|
|
14
21
|
},
|
|
15
22
|
"files": [
|
|
16
23
|
"dist"
|
|
17
24
|
],
|
|
18
25
|
"scripts": {
|
|
19
|
-
"build": "tsup
|
|
26
|
+
"build": "tsup",
|
|
27
|
+
"dev": "tsup --watch",
|
|
28
|
+
"test": "vitest",
|
|
29
|
+
"lint": "eslint src",
|
|
30
|
+
"typecheck": "tsc --noEmit"
|
|
20
31
|
},
|
|
21
32
|
"keywords": [
|
|
22
33
|
"subtitles",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
34
|
+
"captions",
|
|
35
|
+
"animations",
|
|
36
|
+
"expressive",
|
|
37
|
+
"video",
|
|
38
|
+
"bitmovin",
|
|
39
|
+
"phont"
|
|
26
40
|
],
|
|
27
|
-
"author": "PHONT
|
|
41
|
+
"author": "PHONT",
|
|
28
42
|
"license": "MIT",
|
|
29
43
|
"repository": {
|
|
30
44
|
"type": "git",
|
|
31
|
-
"url": "https://github.com/
|
|
32
|
-
"directory": "packages/core"
|
|
45
|
+
"url": "https://github.com/Phont-ai/phont-ors-poc-frontend.git"
|
|
33
46
|
},
|
|
34
47
|
"publishConfig": {
|
|
35
|
-
"registry": "https://
|
|
48
|
+
"registry": "https://npm.pkg.github.com"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/node": "^20.0.0",
|
|
52
|
+
"tsup": "^8.0.0",
|
|
53
|
+
"typescript": "^5.8.3",
|
|
54
|
+
"vitest": "^1.0.0"
|
|
55
|
+
},
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"bezier-easing": "^2.1.0"
|
|
36
58
|
}
|
|
37
59
|
}
|
|
60
|
+
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Enhanced PhontClient with improved registration validation
|
|
3
|
-
*
|
|
4
|
-
* This file extends the base PhontClient with validation support.
|
|
5
|
-
* Note: This is a reference implementation. The actual PhontClient
|
|
6
|
-
* should be updated to include these improvements.
|
|
7
|
-
*/
|
|
8
|
-
import { RegisterRequestWithConfirm, RegisterResult } from '../types/registration';
|
|
9
|
-
/**
|
|
10
|
-
* Enhanced register method with validation
|
|
11
|
-
*
|
|
12
|
-
* This method validates all registration fields including confirmations
|
|
13
|
-
* before making the API call.
|
|
14
|
-
*/
|
|
15
|
-
export declare function registerWithValidation(client: any, // PhontClient instance
|
|
16
|
-
data: RegisterRequestWithConfirm): Promise<RegisterResult>;
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Enhanced Registration Types
|
|
3
|
-
*
|
|
4
|
-
* Extends the base registration types with validation and confirmation fields
|
|
5
|
-
*/
|
|
6
|
-
export interface RegisterResponse {
|
|
7
|
-
success: boolean;
|
|
8
|
-
tenant_id: string;
|
|
9
|
-
username: string;
|
|
10
|
-
email: string;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Registration request with confirmation fields
|
|
14
|
-
*/
|
|
15
|
-
export interface RegisterRequest {
|
|
16
|
-
username: string;
|
|
17
|
-
email: string;
|
|
18
|
-
password: string;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Registration request with all confirmation fields (for form validation)
|
|
22
|
-
*/
|
|
23
|
-
export interface RegisterRequestWithConfirm {
|
|
24
|
-
username: string;
|
|
25
|
-
usernameConfirm: string;
|
|
26
|
-
email: string;
|
|
27
|
-
emailConfirm: string;
|
|
28
|
-
password: string;
|
|
29
|
-
passwordConfirm: string;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Registration result with validation errors
|
|
33
|
-
*/
|
|
34
|
-
export interface RegisterResult extends RegisterResponse {
|
|
35
|
-
success: boolean;
|
|
36
|
-
error?: string;
|
|
37
|
-
validationErrors?: {
|
|
38
|
-
username?: string;
|
|
39
|
-
usernameConfirm?: string;
|
|
40
|
-
email?: string;
|
|
41
|
-
emailConfirm?: string;
|
|
42
|
-
password?: string;
|
|
43
|
-
passwordConfirm?: string;
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
export { RegisterResponse };
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Video Handling Utilities
|
|
3
|
-
*
|
|
4
|
-
* Utilities for gracefully handling empty video lists and video-related errors
|
|
5
|
-
*/
|
|
6
|
-
export interface VodMetadata {
|
|
7
|
-
_id: string;
|
|
8
|
-
tenant_id: string;
|
|
9
|
-
manifest: string;
|
|
10
|
-
thumbnail?: string;
|
|
11
|
-
audio_url?: string;
|
|
12
|
-
name: string;
|
|
13
|
-
subtitle_available: boolean;
|
|
14
|
-
created_at: string;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Check if video list is empty and handle gracefully
|
|
18
|
-
* Returns empty array if null/undefined, filters out invalid videos
|
|
19
|
-
*/
|
|
20
|
-
export declare function normalizeVideoList(videos: VodMetadata[] | null | undefined): VodMetadata[];
|
|
21
|
-
/**
|
|
22
|
-
* Check if user has any videos
|
|
23
|
-
*/
|
|
24
|
-
export declare function hasVideos(videos: VodMetadata[] | null | undefined): boolean;
|
|
25
|
-
/**
|
|
26
|
-
* Safely get video count
|
|
27
|
-
*/
|
|
28
|
-
export declare function getVideoCount(videos: VodMetadata[] | null | undefined): number;
|
|
29
|
-
/**
|
|
30
|
-
* Handle video fetch errors gracefully
|
|
31
|
-
* Returns empty array instead of throwing
|
|
32
|
-
*/
|
|
33
|
-
export declare function safeVideoFetch(fetchFn: () => Promise<VodMetadata[]>): Promise<VodMetadata[]>;
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Registration Validation Utilities
|
|
3
|
-
*
|
|
4
|
-
* Provides comprehensive validation for registration forms including:
|
|
5
|
-
* - Username validation
|
|
6
|
-
* - Email validation
|
|
7
|
-
* - Password validation and confirmation
|
|
8
|
-
* - Type checking
|
|
9
|
-
*/
|
|
10
|
-
export interface RegistrationFormData {
|
|
11
|
-
username: string;
|
|
12
|
-
usernameConfirm: string;
|
|
13
|
-
email: string;
|
|
14
|
-
emailConfirm: string;
|
|
15
|
-
password: string;
|
|
16
|
-
passwordConfirm: string;
|
|
17
|
-
}
|
|
18
|
-
export interface RegistrationValidationResult {
|
|
19
|
-
isValid: boolean;
|
|
20
|
-
errors: {
|
|
21
|
-
username?: string;
|
|
22
|
-
usernameConfirm?: string;
|
|
23
|
-
email?: string;
|
|
24
|
-
emailConfirm?: string;
|
|
25
|
-
password?: string;
|
|
26
|
-
passwordConfirm?: string;
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Validate username format
|
|
31
|
-
* - 3-20 characters
|
|
32
|
-
* - Alphanumeric, underscore, hyphen only
|
|
33
|
-
* - Must start with letter or number
|
|
34
|
-
*/
|
|
35
|
-
export declare function validateUsername(username: string): string | null;
|
|
36
|
-
/**
|
|
37
|
-
* Validate email format
|
|
38
|
-
*/
|
|
39
|
-
export declare function validateEmail(email: string): string | null;
|
|
40
|
-
/**
|
|
41
|
-
* Validate password strength
|
|
42
|
-
* - Minimum 8 characters
|
|
43
|
-
* - At least one uppercase letter
|
|
44
|
-
* - At least one lowercase letter
|
|
45
|
-
* - At least one number
|
|
46
|
-
* - At least one special character
|
|
47
|
-
*/
|
|
48
|
-
export declare function validatePassword(password: string): string | null;
|
|
49
|
-
/**
|
|
50
|
-
* Validate that two strings match (for confirmation fields)
|
|
51
|
-
*/
|
|
52
|
-
export declare function validateMatch(value: string, confirmValue: string, fieldName: string): string | null;
|
|
53
|
-
/**
|
|
54
|
-
* Comprehensive registration form validation
|
|
55
|
-
*/
|
|
56
|
-
export declare function validateRegistrationForm(data: RegistrationFormData): RegistrationValidationResult;
|
|
57
|
-
/**
|
|
58
|
-
* Type guard to check if a value is a valid string
|
|
59
|
-
*/
|
|
60
|
-
export declare function isString(value: unknown): value is string;
|
|
61
|
-
/**
|
|
62
|
-
* Sanitize input by trimming whitespace
|
|
63
|
-
*/
|
|
64
|
-
export declare function sanitizeInput(input: string): string;
|