altcha 3.0.11 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/external/altcha.js +2 -4
- package/dist/external/altcha.min.js +1 -1
- package/dist/external/altcha.umd.cjs +2 -4
- package/dist/external/altcha.umd.min.cjs +1 -1
- package/dist/i18n/af.js +109 -3
- package/dist/i18n/af.umd.cjs +109 -3
- package/dist/i18n/africa.js +115 -21
- package/dist/i18n/africa.umd.cjs +115 -21
- package/dist/i18n/all.js +169 -183
- package/dist/i18n/all.umd.cjs +169 -183
- package/dist/i18n/am.js +109 -3
- package/dist/i18n/am.umd.cjs +109 -3
- package/dist/i18n/americas.js +111 -9
- package/dist/i18n/americas.umd.cjs +111 -9
- package/dist/i18n/ar.js +109 -3
- package/dist/i18n/ar.umd.cjs +109 -3
- package/dist/i18n/asia.js +132 -72
- package/dist/i18n/asia.umd.cjs +132 -72
- package/dist/i18n/az.js +109 -3
- package/dist/i18n/az.umd.cjs +109 -3
- package/dist/i18n/be.js +109 -3
- package/dist/i18n/be.umd.cjs +109 -3
- package/dist/i18n/bg.js +109 -3
- package/dist/i18n/bg.umd.cjs +109 -3
- package/dist/i18n/bn.js +109 -3
- package/dist/i18n/bn.umd.cjs +109 -3
- package/dist/i18n/bs.js +109 -3
- package/dist/i18n/bs.umd.cjs +109 -3
- package/dist/i18n/ca.js +109 -3
- package/dist/i18n/ca.umd.cjs +109 -3
- package/dist/i18n/cs.js +109 -3
- package/dist/i18n/cs.umd.cjs +109 -3
- package/dist/i18n/da.js +109 -3
- package/dist/i18n/da.umd.cjs +109 -3
- package/dist/i18n/de.js +109 -3
- package/dist/i18n/de.umd.cjs +109 -3
- package/dist/i18n/el.js +109 -3
- package/dist/i18n/el.umd.cjs +109 -3
- package/dist/i18n/en.js +109 -3
- package/dist/i18n/en.umd.cjs +109 -3
- package/dist/i18n/es-419.js +109 -3
- package/dist/i18n/es-419.umd.cjs +109 -3
- package/dist/i18n/es-es.js +109 -3
- package/dist/i18n/es-es.umd.cjs +109 -3
- package/dist/i18n/et.js +109 -3
- package/dist/i18n/et.umd.cjs +109 -3
- package/dist/i18n/eu.js +109 -3
- package/dist/i18n/eu.umd.cjs +109 -3
- package/dist/i18n/europe.js +145 -111
- package/dist/i18n/europe.umd.cjs +145 -111
- package/dist/i18n/fa.js +109 -3
- package/dist/i18n/fa.umd.cjs +109 -3
- package/dist/i18n/fi.js +109 -3
- package/dist/i18n/fi.umd.cjs +109 -3
- package/dist/i18n/fr-ca.js +109 -3
- package/dist/i18n/fr-ca.umd.cjs +109 -3
- package/dist/i18n/fr-fr.js +109 -3
- package/dist/i18n/fr-fr.umd.cjs +109 -3
- package/dist/i18n/ga.js +109 -3
- package/dist/i18n/ga.umd.cjs +109 -3
- package/dist/i18n/he.js +109 -3
- package/dist/i18n/he.umd.cjs +109 -3
- package/dist/i18n/hi.js +109 -3
- package/dist/i18n/hi.umd.cjs +109 -3
- package/dist/i18n/hr.js +109 -3
- package/dist/i18n/hr.umd.cjs +109 -3
- package/dist/i18n/hu.js +109 -3
- package/dist/i18n/hu.umd.cjs +109 -3
- package/dist/i18n/hy.js +109 -3
- package/dist/i18n/hy.umd.cjs +109 -3
- package/dist/i18n/id.js +109 -3
- package/dist/i18n/id.umd.cjs +109 -3
- package/dist/i18n/is.js +109 -3
- package/dist/i18n/is.umd.cjs +109 -3
- package/dist/i18n/it.js +109 -3
- package/dist/i18n/it.umd.cjs +109 -3
- package/dist/i18n/ja.js +109 -3
- package/dist/i18n/ja.umd.cjs +109 -3
- package/dist/i18n/ka.js +109 -3
- package/dist/i18n/ka.umd.cjs +109 -3
- package/dist/i18n/kk.js +109 -3
- package/dist/i18n/kk.umd.cjs +109 -3
- package/dist/i18n/ko.js +109 -3
- package/dist/i18n/ko.umd.cjs +109 -3
- package/dist/i18n/lb.js +109 -3
- package/dist/i18n/lb.umd.cjs +109 -3
- package/dist/i18n/lt.js +109 -3
- package/dist/i18n/lt.umd.cjs +109 -3
- package/dist/i18n/lv.js +109 -3
- package/dist/i18n/lv.umd.cjs +109 -3
- package/dist/i18n/me.js +109 -3
- package/dist/i18n/me.umd.cjs +109 -3
- package/dist/i18n/mk.js +109 -3
- package/dist/i18n/mk.umd.cjs +109 -3
- package/dist/i18n/mr.js +109 -3
- package/dist/i18n/mr.umd.cjs +109 -3
- package/dist/i18n/mt.js +109 -3
- package/dist/i18n/mt.umd.cjs +109 -3
- package/dist/i18n/nb.js +109 -3
- package/dist/i18n/nb.umd.cjs +109 -3
- package/dist/i18n/nl.js +109 -3
- package/dist/i18n/nl.umd.cjs +109 -3
- package/dist/i18n/pl.js +109 -3
- package/dist/i18n/pl.umd.cjs +109 -3
- package/dist/i18n/pt-br.js +109 -3
- package/dist/i18n/pt-br.umd.cjs +109 -3
- package/dist/i18n/pt-pt.js +109 -3
- package/dist/i18n/pt-pt.umd.cjs +109 -3
- package/dist/i18n/ro.js +109 -3
- package/dist/i18n/ro.umd.cjs +109 -3
- package/dist/i18n/ru.js +109 -3
- package/dist/i18n/ru.umd.cjs +109 -3
- package/dist/i18n/sk.js +109 -3
- package/dist/i18n/sk.umd.cjs +109 -3
- package/dist/i18n/sl.js +109 -3
- package/dist/i18n/sl.umd.cjs +109 -3
- package/dist/i18n/sq.js +109 -3
- package/dist/i18n/sq.umd.cjs +109 -3
- package/dist/i18n/sr.js +109 -3
- package/dist/i18n/sr.umd.cjs +109 -3
- package/dist/i18n/sv.js +109 -3
- package/dist/i18n/sv.umd.cjs +109 -3
- package/dist/i18n/sw.js +109 -3
- package/dist/i18n/sw.umd.cjs +109 -3
- package/dist/i18n/ta.js +109 -3
- package/dist/i18n/ta.umd.cjs +109 -3
- package/dist/i18n/te.js +109 -3
- package/dist/i18n/te.umd.cjs +109 -3
- package/dist/i18n/th.js +109 -3
- package/dist/i18n/th.umd.cjs +109 -3
- package/dist/i18n/tk.js +109 -3
- package/dist/i18n/tk.umd.cjs +109 -3
- package/dist/i18n/tr.js +109 -3
- package/dist/i18n/tr.umd.cjs +109 -3
- package/dist/i18n/uk.js +109 -3
- package/dist/i18n/uk.umd.cjs +109 -3
- package/dist/i18n/ur.js +109 -3
- package/dist/i18n/ur.umd.cjs +109 -3
- package/dist/i18n/uz.js +109 -3
- package/dist/i18n/uz.umd.cjs +109 -3
- package/dist/i18n/vi.js +109 -3
- package/dist/i18n/vi.umd.cjs +109 -3
- package/dist/i18n/yo.js +109 -3
- package/dist/i18n/yo.umd.cjs +109 -3
- package/dist/i18n/zh-cn.js +109 -3
- package/dist/i18n/zh-cn.umd.cjs +109 -3
- package/dist/i18n/zh-hk.js +109 -3
- package/dist/i18n/zh-hk.umd.cjs +109 -3
- package/dist/i18n/zh-tw.js +109 -3
- package/dist/i18n/zh-tw.umd.cjs +109 -3
- package/dist/lib/index.js +2 -0
- package/dist/lib/index.min.js +1 -1
- package/dist/lib/index.umd.cjs +2 -0
- package/dist/lib/index.umd.min.cjs +1 -1
- package/dist/main/altcha.i18n.js +67 -187
- package/dist/main/altcha.i18n.min.js +1 -1
- package/dist/main/altcha.i18n.umd.cjs +67 -187
- package/dist/main/altcha.i18n.umd.min.cjs +1 -1
- package/dist/main/altcha.js +6 -4
- package/dist/main/altcha.min.js +1 -1
- package/dist/main/altcha.umd.cjs +6 -4
- package/dist/main/altcha.umd.min.cjs +1 -1
- package/dist/plugins/obfuscation.plugin.js +3 -0
- package/dist/plugins/obfuscation.plugin.min.js +1 -1
- package/dist/plugins/obfuscation.plugin.umd.cjs +3 -0
- package/dist/plugins/obfuscation.plugin.umd.min.cjs +1 -1
- package/dist/types/jsx.d.ts +10 -1
- package/dist/types/react.d.ts +4 -7
- package/dist/types/svelte.d.ts +2 -3
- package/dist/workers/argon2id.js +2 -0
- package/dist/workers/pbkdf2.js +2 -0
- package/dist/workers/scrypt.js +2 -0
- package/dist/workers/sha.js +2 -0
- package/package.json +8 -5
|
@@ -110,6 +110,7 @@ class BasePlugin {
|
|
|
110
110
|
constructor(host) {
|
|
111
111
|
this.host = host;
|
|
112
112
|
}
|
|
113
|
+
host;
|
|
113
114
|
static register(pluginClass) {
|
|
114
115
|
if ("$altcha" in globalThis && !globalThis.$altcha.plugins.has(pluginClass)) {
|
|
115
116
|
globalThis.$altcha.plugins.add(pluginClass);
|
|
@@ -250,6 +251,8 @@ class PasswordBuffer {
|
|
|
250
251
|
this.buffer.set(this.nonce, 0);
|
|
251
252
|
this.dataView = new DataView(this.buffer.buffer);
|
|
252
253
|
}
|
|
254
|
+
nonce;
|
|
255
|
+
mode;
|
|
253
256
|
COUNTER_BYTES = 4;
|
|
254
257
|
buffer;
|
|
255
258
|
dataView;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=()=>{};function t(t,r,n){if(null==t)return r(void 0),e;const a=function(e){var t=o;try{return o=!0,e()}finally{o=t}}(()=>t.subscribe(r,n));return a.unsubscribe?()=>a.unsubscribe():a}const r=[];function n(t,n=e){let a=null;const o=new Set;function i(e){if(i=e,((n=t)!=n?i==i:n!==i||null!==n&&"object"==typeof n||"function"==typeof n)&&(t=e,a)){const e=!r.length;for(const e of o)e[1](),r.push(e,t);if(e){for(let e=0;e<r.length;e+=2)r[e][0](r[e+1]);r.length=0}}var n,i}function s(e){i(e(t))}return{set:i,update:s,subscribe:function(r,c=e){const l=[r,c];return o.add(l),1===o.size&&(a=n(i,s)||e),r(t),()=>{o.delete(l),0===o.size&&a&&(a(),a=null)}}}}function a(e){let r;return t(e,e=>r=e)(),r}let o=!1;function i(e){const t={get:e=>a(t.store)[e],set:(e,r)=>{"string"==typeof e?Object.assign(a(t.store),{[e]:r}):Object.assign(a(t.store),e),t.store.set(a(t.store))},store:n(e)};return t}globalThis.$altcha=globalThis.$altcha||{algorithms:new Map,defaults:i({}),i18n:i({}),instances:new Set,plugins:new Set};class s{constructor(e){this.host=e}static register(e){"$altcha"in globalThis&&!globalThis.$altcha.plugins.has(e)&&globalThis.$altcha.plugins.add(e)}async onFetchChallenge(e){}async onRequestServerVerification(e,t){}async onVerify(e){}}function c(e){switch(e){case"PBKDF2/SHA-512":return"SHA-512";case"PBKDF2/SHA-384":return"SHA-384";default:return"SHA-256"}}async function l(e,t,r){const{algorithm:n,cost:a,keyLength:o=32}=e,i=await crypto.subtle.importKey("raw",r,{name:"PBKDF2"},!1,["deriveKey"]),s=await crypto.subtle.deriveKey({name:"PBKDF2",salt:t,iterations:a,hash:c(n)},i,{name:"AES-GCM",length:8*o},!0,["encrypt"]);return{derivedKey:new Uint8Array(await crypto.subtle.exportKey("raw",s))}}function u(e,t){if(t.length>e.length)return!1;for(let r=0;r<t.length;r++)if(e[r]!==t[r])return!1;return!0}function h(e){return Array.from(new Uint8Array(e)).map(e=>e.toString(16).padStart(2,"0")).join("")}function f(e){if(e.length%2!=0)throw new Error(`Hex string must have an even length. Got: ${e}`);const t=new ArrayBuffer(e.length/2),r=new DataView(t);for(let t=0;t<e.length;t+=2){const n=e.substring(t,t+2),a=parseInt(n,16);r.setUint8(t/2,a)}return new Uint8Array(t)}async function y(e){await new Promise(t=>setTimeout(t,e))}async function g(e,t,r){const n=await crypto.subtle.importKey("raw",(new TextEncoder).encode(r),{name:"HMAC",hash:{name:e}},!1,["sign","verify"]),a=await crypto.subtle.sign("HMAC",n,"string"==typeof t?(new TextEncoder).encode(t):t);return new Uint8Array(a)}function d(e){return"object"!=typeof e||null===e||Array.isArray(e)?e:Object.keys(e).sort().reduce((t,r)=>{const n=e[r];return void 0!==n&&(t[r]=d(n)),t},{})}function m(e){return Math.floor(10*(performance.now()-e))/10}var w=(e=>(e.SHA_256="SHA-256",e.SHA_384="SHA-384",e.SHA_512="SHA-512",e))(w||{}),p=(e=>(e.CODE="code",e.ERROR="error",e.VERIFIED="verified",e.VERIFYING="verifying",e.UNVERIFIED="unverified",e.EXPIRED="expired",e))(p||{});class b{constructor(e,t="uint32"){this.nonce=e,this.mode=t,this.buffer=new Uint8Array(this.nonce.length+this.COUNTER_BYTES),this.buffer.set(this.nonce,0),this.dataView=new DataView(this.buffer.buffer)}COUNTER_BYTES=4;buffer;dataView;encoder=new TextEncoder;setCounter(e){return"string"===this.mode?function(e,t){const r=new Uint8Array(e.length+t.length);return r.set(e,0),r.set(t,e.length),r}(this.nonce,this.encoder.encode(e.toString())):(this.dataView.setUint32(this.nonce.length,e,!1),this.buffer)}}async function S(e){const{algorithm:t,counter:r,counterMode:n="uint32",cost:a,deriveKey:o,data:i,expiresAt:s,hmacAlgorithm:c=w.SHA_256,hmacKeySignatureSecret:l,hmacSignatureSecret:u,keyLength:y=32,keyPrefix:m="00",keyPrefixLength:p=y/2,memoryCost:S,parallelism:v}=e,A={algorithm:t,nonce:h(crypto.getRandomValues(new Uint8Array(16))),salt:h(crypto.getRandomValues(new Uint8Array(16))),cost:a,keyLength:y,memoryCost:S,parallelism:v,keyPrefix:m,expiresAt:s instanceof Date?Math.floor(s.getTime()/1e3):s,data:i};let E=null;if(void 0!==r){const e=f(A.nonce);E=await o(A,f(A.salt),new b(e,n).setCounter(r)),E.parameters&&Object.assign(A,E.parameters),A.keyPrefix=h(E.derivedKey.slice(0,p))}return u?async function(e,t,r,n,a){r&&a&&(t.keySignature=h(await g(e,r,a)));return t=d(t),{parameters:t,signature:h(await g(e,JSON.stringify(t),n))}}(c,A,E?.derivedKey,u,l):{parameters:d(A)}}async function v(e){const{challenge:t,concurrency:r=navigator.hardwareConcurrency,controller:n=new AbortController,createWorker:a,onOutOfMemory:o=e=>e>1?Math.floor(e/2):0,counterMode:i,timeout:s=9e4}=e,c=Math.min(16,Math.max(1,r)),l=[],u=()=>{for(const e of l)e.terminate()};for(let e=0;e<c;e++)l.push(await a(t.parameters.algorithm));let h=null;try{h=await Promise.race(l.map((e,r)=>(n.signal.addEventListener("abort",()=>{e.postMessage({type:"abort"})}),new Promise((n,a)=>{e.addEventListener("error",e=>{a(e)}),e.addEventListener("message",t=>{if(t.data){for(const t of l)t!==e&&t.postMessage({type:"abort"});if(t.data.error)return a(new Error(t.data.error))}n(t.data)}),e.postMessage({challenge:t,counterMode:i,counterStart:r,counterStep:c,timeout:s,type:"work"})}))))}catch(r){if(r instanceof Error&&!!r?.message?.includes("Out of memory")&&o){u();const r=o(c);if(r)return v({...e,challenge:t,controller:n,concurrency:r,createWorker:a})}throw r}finally{u()}return n.signal.aborted?null:h||null}async function A(e,t={}){let{concurrency:r=Math.max(1,Math.min(4,navigator.hardwareConcurrency)),createWorker:n,deriveKey:a=l}=t,o=null;try{o=JSON.parse(atob(e))}catch{throw new Error("Unable to parse obfuscated data.")}if(!o||"object"!=typeof o||!("parameters"in o)||!("cipher"in o))throw new Error("Invalid obfuscated data format.");const i=o.cipher;let s=null;if(!n&&"$altcha"in globalThis&&(n=globalThis.$altcha.algorithms.get(o.parameters.algorithm)),s=n?await v({challenge:o,concurrency:r,createWorker:n}):await async function(e){const{challenge:t,controller:r,counterMode:n="uint32",counterStart:a=0,counterStep:o=1,deriveKey:i,timeout:s=9e4}=e,{nonce:c,keyPrefix:l,salt:g}=t.parameters,d=f(c),w=f(g),p=l.length%2==0?f(l):null,S=new b(d,n),v=performance.now();let A=a,E=0,T="",x=v;for(;;){if(r?.signal.aborted||s&&E%10==0&&performance.now()-v>s)return null;const{derivedKey:e}=await i(t.parameters,w,S.setCounter(A));if(E%10==0&&performance.now()-x>200&&(await y(0),x=performance.now()),p?u(e,p):h(e).startsWith(l)){T=h(e);break}A+=o,E+=1}return{counter:A,derivedKey:T,time:m(v)}}({challenge:o,deriveKey:a}),!s)throw new Error("Unable to find solution.");const c=await crypto.subtle.importKey("raw",f(s.derivedKey),{name:"AES-GCM"},!1,["decrypt"]),g=await crypto.subtle.decrypt({name:"AES-GCM",iv:f(i.iv)},c,f(i.data));return(new TextDecoder).decode(g)}async function E(e,t={}){const{deriveKey:r=l}=t,n=t?.counterMin||20,a=t?.counterMax||200,{parameters:o}=await S({algorithm:"PBKDF2/SHA-256",cost:5e3,deriveKey:r,counter:Math.floor(Math.random()*(a-n+1))+n,keyPrefixLength:32,...t}),i=await crypto.subtle.importKey("raw",f(o.keyPrefix),{name:"AES-GCM"},!1,["encrypt"]),s=crypto.getRandomValues(new Uint8Array(12)),c=await crypto.subtle.encrypt({name:"AES-GCM",iv:s},i,(new TextEncoder).encode(e));return btoa(JSON.stringify({parameters:{...o,keyPrefix:o.keyPrefix.slice(0,o.keyLength||32)},cipher:{iv:h(s),data:h(c)}}))}s.register(class extends s{static deobfuscate=A;static obfuscate=E;elTrigger=null;activate(){this.elTrigger=this.host.querySelector("button"),this.elTrigger&&(this.elTrigger.addEventListener("click",this.onTriggerClick.bind(this)),this.host.configure({floatingAnchor:this.elTrigger}))}destroy(){}async onVerify(e){const{minDuration:t=500}=e,r=performance.now(),n=this.host.getAttribute("data-obfuscated");if(n){this.host.reset(p.VERIFYING);try{const e=await A(n);await this.#e(Math.max(0,t-(performance.now()-r))),this.#t(e)}catch(e){this.host.setState(p.ERROR,String(e))}finally{this.host.setState(p.VERIFIED)}return null}}onTriggerClick(e){e.preventDefault(),this.host.show(),this.host.verify().then(()=>{this.host.hide()})}#t(e){let t;if(e.match(/^(mailto|tel|sms|https?):/)){const[r]=e.slice(e.indexOf(":")+1).replace(/^\/\//,"").split("?");t=document.createElement("a"),t.href=e,t.innerText=r}else t=document.createTextNode(e);this.elTrigger&&t&&(this.elTrigger.after(t),this.elTrigger.parentElement?.removeChild(this.elTrigger))}async#e(e){await new Promise(t=>setTimeout(t,e))}});
|
|
1
|
+
const e=()=>{};function t(t,r,n){if(null==t)return r(void 0),e;const a=function(e){var t=o;try{return o=!0,e()}finally{o=t}}(()=>t.subscribe(r,n));return a.unsubscribe?()=>a.unsubscribe():a}const r=[];function n(t,n=e){let a=null;const o=new Set;function i(e){if(i=e,((n=t)!=n?i==i:n!==i||null!==n&&"object"==typeof n||"function"==typeof n)&&(t=e,a)){const e=!r.length;for(const e of o)e[1](),r.push(e,t);if(e){for(let e=0;e<r.length;e+=2)r[e][0](r[e+1]);r.length=0}}var n,i}function s(e){i(e(t))}return{set:i,update:s,subscribe:function(r,c=e){const l=[r,c];return o.add(l),1===o.size&&(a=n(i,s)||e),r(t),()=>{o.delete(l),0===o.size&&a&&(a(),a=null)}}}}function a(e){let r;return t(e,e=>r=e)(),r}let o=!1;function i(e){const t={get:e=>a(t.store)[e],set:(e,r)=>{"string"==typeof e?Object.assign(a(t.store),{[e]:r}):Object.assign(a(t.store),e),t.store.set(a(t.store))},store:n(e)};return t}globalThis.$altcha=globalThis.$altcha||{algorithms:new Map,defaults:i({}),i18n:i({}),instances:new Set,plugins:new Set};class s{constructor(e){this.host=e}host;static register(e){"$altcha"in globalThis&&!globalThis.$altcha.plugins.has(e)&&globalThis.$altcha.plugins.add(e)}async onFetchChallenge(e){}async onRequestServerVerification(e,t){}async onVerify(e){}}function c(e){switch(e){case"PBKDF2/SHA-512":return"SHA-512";case"PBKDF2/SHA-384":return"SHA-384";default:return"SHA-256"}}async function l(e,t,r){const{algorithm:n,cost:a,keyLength:o=32}=e,i=await crypto.subtle.importKey("raw",r,{name:"PBKDF2"},!1,["deriveKey"]),s=await crypto.subtle.deriveKey({name:"PBKDF2",salt:t,iterations:a,hash:c(n)},i,{name:"AES-GCM",length:8*o},!0,["encrypt"]);return{derivedKey:new Uint8Array(await crypto.subtle.exportKey("raw",s))}}function u(e,t){if(t.length>e.length)return!1;for(let r=0;r<t.length;r++)if(e[r]!==t[r])return!1;return!0}function h(e){return Array.from(new Uint8Array(e)).map(e=>e.toString(16).padStart(2,"0")).join("")}function f(e){if(e.length%2!=0)throw new Error(`Hex string must have an even length. Got: ${e}`);const t=new ArrayBuffer(e.length/2),r=new DataView(t);for(let t=0;t<e.length;t+=2){const n=e.substring(t,t+2),a=parseInt(n,16);r.setUint8(t/2,a)}return new Uint8Array(t)}async function y(e){await new Promise(t=>setTimeout(t,e))}async function g(e,t,r){const n=await crypto.subtle.importKey("raw",(new TextEncoder).encode(r),{name:"HMAC",hash:{name:e}},!1,["sign","verify"]),a=await crypto.subtle.sign("HMAC",n,"string"==typeof t?(new TextEncoder).encode(t):t);return new Uint8Array(a)}function d(e){return"object"!=typeof e||null===e||Array.isArray(e)?e:Object.keys(e).sort().reduce((t,r)=>{const n=e[r];return void 0!==n&&(t[r]=d(n)),t},{})}function m(e){return Math.floor(10*(performance.now()-e))/10}var w=(e=>(e.SHA_256="SHA-256",e.SHA_384="SHA-384",e.SHA_512="SHA-512",e))(w||{}),p=(e=>(e.CODE="code",e.ERROR="error",e.VERIFIED="verified",e.VERIFYING="verifying",e.UNVERIFIED="unverified",e.EXPIRED="expired",e))(p||{});class b{constructor(e,t="uint32"){this.nonce=e,this.mode=t,this.buffer=new Uint8Array(this.nonce.length+this.COUNTER_BYTES),this.buffer.set(this.nonce,0),this.dataView=new DataView(this.buffer.buffer)}nonce;mode;COUNTER_BYTES=4;buffer;dataView;encoder=new TextEncoder;setCounter(e){return"string"===this.mode?function(e,t){const r=new Uint8Array(e.length+t.length);return r.set(e,0),r.set(t,e.length),r}(this.nonce,this.encoder.encode(e.toString())):(this.dataView.setUint32(this.nonce.length,e,!1),this.buffer)}}async function S(e){const{algorithm:t,counter:r,counterMode:n="uint32",cost:a,deriveKey:o,data:i,expiresAt:s,hmacAlgorithm:c=w.SHA_256,hmacKeySignatureSecret:l,hmacSignatureSecret:u,keyLength:y=32,keyPrefix:m="00",keyPrefixLength:p=y/2,memoryCost:S,parallelism:v}=e,A={algorithm:t,nonce:h(crypto.getRandomValues(new Uint8Array(16))),salt:h(crypto.getRandomValues(new Uint8Array(16))),cost:a,keyLength:y,memoryCost:S,parallelism:v,keyPrefix:m,expiresAt:s instanceof Date?Math.floor(s.getTime()/1e3):s,data:i};let E=null;if(void 0!==r){const e=f(A.nonce);E=await o(A,f(A.salt),new b(e,n).setCounter(r)),E.parameters&&Object.assign(A,E.parameters),A.keyPrefix=h(E.derivedKey.slice(0,p))}return u?async function(e,t,r,n,a){r&&a&&(t.keySignature=h(await g(e,r,a)));return t=d(t),{parameters:t,signature:h(await g(e,JSON.stringify(t),n))}}(c,A,E?.derivedKey,u,l):{parameters:d(A)}}async function v(e){const{challenge:t,concurrency:r=navigator.hardwareConcurrency,controller:n=new AbortController,createWorker:a,onOutOfMemory:o=e=>e>1?Math.floor(e/2):0,counterMode:i,timeout:s=9e4}=e,c=Math.min(16,Math.max(1,r)),l=[],u=()=>{for(const e of l)e.terminate()};for(let e=0;e<c;e++)l.push(await a(t.parameters.algorithm));let h=null;try{h=await Promise.race(l.map((e,r)=>(n.signal.addEventListener("abort",()=>{e.postMessage({type:"abort"})}),new Promise((n,a)=>{e.addEventListener("error",e=>{a(e)}),e.addEventListener("message",t=>{if(t.data){for(const t of l)t!==e&&t.postMessage({type:"abort"});if(t.data.error)return a(new Error(t.data.error))}n(t.data)}),e.postMessage({challenge:t,counterMode:i,counterStart:r,counterStep:c,timeout:s,type:"work"})}))))}catch(r){if(r instanceof Error&&!!r?.message?.includes("Out of memory")&&o){u();const r=o(c);if(r)return v({...e,challenge:t,controller:n,concurrency:r,createWorker:a})}throw r}finally{u()}return n.signal.aborted?null:h||null}async function A(e,t={}){let{concurrency:r=Math.max(1,Math.min(4,navigator.hardwareConcurrency)),createWorker:n,deriveKey:a=l}=t,o=null;try{o=JSON.parse(atob(e))}catch{throw new Error("Unable to parse obfuscated data.")}if(!o||"object"!=typeof o||!("parameters"in o)||!("cipher"in o))throw new Error("Invalid obfuscated data format.");const i=o.cipher;let s=null;if(!n&&"$altcha"in globalThis&&(n=globalThis.$altcha.algorithms.get(o.parameters.algorithm)),s=n?await v({challenge:o,concurrency:r,createWorker:n}):await async function(e){const{challenge:t,controller:r,counterMode:n="uint32",counterStart:a=0,counterStep:o=1,deriveKey:i,timeout:s=9e4}=e,{nonce:c,keyPrefix:l,salt:g}=t.parameters,d=f(c),w=f(g),p=l.length%2==0?f(l):null,S=new b(d,n),v=performance.now();let A=a,E=0,T="",x=v;for(;;){if(r?.signal.aborted||s&&E%10==0&&performance.now()-v>s)return null;const{derivedKey:e}=await i(t.parameters,w,S.setCounter(A));if(E%10==0&&performance.now()-x>200&&(await y(0),x=performance.now()),p?u(e,p):h(e).startsWith(l)){T=h(e);break}A+=o,E+=1}return{counter:A,derivedKey:T,time:m(v)}}({challenge:o,deriveKey:a}),!s)throw new Error("Unable to find solution.");const c=await crypto.subtle.importKey("raw",f(s.derivedKey),{name:"AES-GCM"},!1,["decrypt"]),g=await crypto.subtle.decrypt({name:"AES-GCM",iv:f(i.iv)},c,f(i.data));return(new TextDecoder).decode(g)}async function E(e,t={}){const{deriveKey:r=l}=t,n=t?.counterMin||20,a=t?.counterMax||200,{parameters:o}=await S({algorithm:"PBKDF2/SHA-256",cost:5e3,deriveKey:r,counter:Math.floor(Math.random()*(a-n+1))+n,keyPrefixLength:32,...t}),i=await crypto.subtle.importKey("raw",f(o.keyPrefix),{name:"AES-GCM"},!1,["encrypt"]),s=crypto.getRandomValues(new Uint8Array(12)),c=await crypto.subtle.encrypt({name:"AES-GCM",iv:s},i,(new TextEncoder).encode(e));return btoa(JSON.stringify({parameters:{...o,keyPrefix:o.keyPrefix.slice(0,o.keyLength||32)},cipher:{iv:h(s),data:h(c)}}))}s.register(class extends s{static deobfuscate=A;static obfuscate=E;elTrigger=null;activate(){this.elTrigger=this.host.querySelector("button"),this.elTrigger&&(this.elTrigger.addEventListener("click",this.onTriggerClick.bind(this)),this.host.configure({floatingAnchor:this.elTrigger}))}destroy(){}async onVerify(e){const{minDuration:t=500}=e,r=performance.now(),n=this.host.getAttribute("data-obfuscated");if(n){this.host.reset(p.VERIFYING);try{const e=await A(n);await this.#e(Math.max(0,t-(performance.now()-r))),this.#t(e)}catch(e){this.host.setState(p.ERROR,String(e))}finally{this.host.setState(p.VERIFIED)}return null}}onTriggerClick(e){e.preventDefault(),this.host.show(),this.host.verify().then(()=>{this.host.hide()})}#t(e){let t;if(e.match(/^(mailto|tel|sms|https?):/)){const[r]=e.slice(e.indexOf(":")+1).replace(/^\/\//,"").split("?");t=document.createElement("a"),t.href=e,t.innerText=r}else t=document.createTextNode(e);this.elTrigger&&t&&(this.elTrigger.after(t),this.elTrigger.parentElement?.removeChild(this.elTrigger))}async#e(e){await new Promise(t=>setTimeout(t,e))}});
|
|
@@ -114,6 +114,7 @@
|
|
|
114
114
|
constructor(host) {
|
|
115
115
|
this.host = host;
|
|
116
116
|
}
|
|
117
|
+
host;
|
|
117
118
|
static register(pluginClass) {
|
|
118
119
|
if ("$altcha" in globalThis && !globalThis.$altcha.plugins.has(pluginClass)) {
|
|
119
120
|
globalThis.$altcha.plugins.add(pluginClass);
|
|
@@ -254,6 +255,8 @@
|
|
|
254
255
|
this.buffer.set(this.nonce, 0);
|
|
255
256
|
this.dataView = new DataView(this.buffer.buffer);
|
|
256
257
|
}
|
|
258
|
+
nonce;
|
|
259
|
+
mode;
|
|
257
260
|
COUNTER_BYTES = 4;
|
|
258
261
|
buffer;
|
|
259
262
|
dataView;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e){"function"==typeof define&&define.amd?define(e):e()}(function(){"use strict";const e=()=>{};function t(t,r,n){if(null==t)return r(void 0),e;const a=function(e){var t=
|
|
1
|
+
!function(e){"function"==typeof define&&define.amd?define(e):e()}(function(){"use strict";const e=()=>{};function t(t,r,n){if(null==t)return r(void 0),e;const a=function(e){var t=o;try{return o=!0,e()}finally{o=t}}(()=>t.subscribe(r,n));return a.unsubscribe?()=>a.unsubscribe():a}const r=[];function n(t,n=e){let a=null;const o=new Set;function i(e){if(i=e,((n=t)!=n?i==i:n!==i||null!==n&&"object"==typeof n||"function"==typeof n)&&(t=e,a)){const e=!r.length;for(const e of o)e[1](),r.push(e,t);if(e){for(let e=0;e<r.length;e+=2)r[e][0](r[e+1]);r.length=0}}var n,i}function s(e){i(e(t))}return{set:i,update:s,subscribe:function(r,c=e){const l=[r,c];return o.add(l),1===o.size&&(a=n(i,s)||e),r(t),()=>{o.delete(l),0===o.size&&a&&(a(),a=null)}}}}function a(e){let r;return t(e,e=>r=e)(),r}let o=!1;function i(e){const t={get:e=>a(t.store)[e],set:(e,r)=>{"string"==typeof e?Object.assign(a(t.store),{[e]:r}):Object.assign(a(t.store),e),t.store.set(a(t.store))},store:n(e)};return t}globalThis.$altcha=globalThis.$altcha||{algorithms:new Map,defaults:i({}),i18n:i({}),instances:new Set,plugins:new Set};class s{constructor(e){this.host=e}host;static register(e){"$altcha"in globalThis&&!globalThis.$altcha.plugins.has(e)&&globalThis.$altcha.plugins.add(e)}async onFetchChallenge(e){}async onRequestServerVerification(e,t){}async onVerify(e){}}function c(e){switch(e){case"PBKDF2/SHA-512":return"SHA-512";case"PBKDF2/SHA-384":return"SHA-384";default:return"SHA-256"}}async function l(e,t,r){const{algorithm:n,cost:a,keyLength:o=32}=e,i=await crypto.subtle.importKey("raw",r,{name:"PBKDF2"},!1,["deriveKey"]),s=await crypto.subtle.deriveKey({name:"PBKDF2",salt:t,iterations:a,hash:c(n)},i,{name:"AES-GCM",length:8*o},!0,["encrypt"]);return{derivedKey:new Uint8Array(await crypto.subtle.exportKey("raw",s))}}function u(e,t){if(t.length>e.length)return!1;for(let r=0;r<t.length;r++)if(e[r]!==t[r])return!1;return!0}function h(e){return Array.from(new Uint8Array(e)).map(e=>e.toString(16).padStart(2,"0")).join("")}function f(e){if(e.length%2!=0)throw new Error(`Hex string must have an even length. Got: ${e}`);const t=new ArrayBuffer(e.length/2),r=new DataView(t);for(let t=0;t<e.length;t+=2){const n=e.substring(t,t+2),a=parseInt(n,16);r.setUint8(t/2,a)}return new Uint8Array(t)}async function y(e){await new Promise(t=>setTimeout(t,e))}async function g(e,t,r){const n=await crypto.subtle.importKey("raw",(new TextEncoder).encode(r),{name:"HMAC",hash:{name:e}},!1,["sign","verify"]),a=await crypto.subtle.sign("HMAC",n,"string"==typeof t?(new TextEncoder).encode(t):t);return new Uint8Array(a)}function d(e){return"object"!=typeof e||null===e||Array.isArray(e)?e:Object.keys(e).sort().reduce((t,r)=>{const n=e[r];return void 0!==n&&(t[r]=d(n)),t},{})}function m(e){return Math.floor(10*(performance.now()-e))/10}var w=(e=>(e.SHA_256="SHA-256",e.SHA_384="SHA-384",e.SHA_512="SHA-512",e))(w||{}),p=(e=>(e.CODE="code",e.ERROR="error",e.VERIFIED="verified",e.VERIFYING="verifying",e.UNVERIFIED="unverified",e.EXPIRED="expired",e))(p||{});class b{constructor(e,t="uint32"){this.nonce=e,this.mode=t,this.buffer=new Uint8Array(this.nonce.length+this.COUNTER_BYTES),this.buffer.set(this.nonce,0),this.dataView=new DataView(this.buffer.buffer)}nonce;mode;COUNTER_BYTES=4;buffer;dataView;encoder=new TextEncoder;setCounter(e){return"string"===this.mode?function(e,t){const r=new Uint8Array(e.length+t.length);return r.set(e,0),r.set(t,e.length),r}(this.nonce,this.encoder.encode(e.toString())):(this.dataView.setUint32(this.nonce.length,e,!1),this.buffer)}}async function S(e){const{algorithm:t,counter:r,counterMode:n="uint32",cost:a,deriveKey:o,data:i,expiresAt:s,hmacAlgorithm:c=w.SHA_256,hmacKeySignatureSecret:l,hmacSignatureSecret:u,keyLength:y=32,keyPrefix:m="00",keyPrefixLength:p=y/2,memoryCost:S,parallelism:v}=e,A={algorithm:t,nonce:h(crypto.getRandomValues(new Uint8Array(16))),salt:h(crypto.getRandomValues(new Uint8Array(16))),cost:a,keyLength:y,memoryCost:S,parallelism:v,keyPrefix:m,expiresAt:s instanceof Date?Math.floor(s.getTime()/1e3):s,data:i};let E=null;if(void 0!==r){const e=f(A.nonce);E=await o(A,f(A.salt),new b(e,n).setCounter(r)),E.parameters&&Object.assign(A,E.parameters),A.keyPrefix=h(E.derivedKey.slice(0,p))}return u?async function(e,t,r,n,a){r&&a&&(t.keySignature=h(await g(e,r,a)));return t=d(t),{parameters:t,signature:h(await g(e,JSON.stringify(t),n))}}(c,A,E?.derivedKey,u,l):{parameters:d(A)}}async function v(e){const{challenge:t,concurrency:r=navigator.hardwareConcurrency,controller:n=new AbortController,createWorker:a,onOutOfMemory:o=e=>e>1?Math.floor(e/2):0,counterMode:i,timeout:s=9e4}=e,c=Math.min(16,Math.max(1,r)),l=[],u=()=>{for(const e of l)e.terminate()};for(let e=0;e<c;e++)l.push(await a(t.parameters.algorithm));let h=null;try{h=await Promise.race(l.map((e,r)=>(n.signal.addEventListener("abort",()=>{e.postMessage({type:"abort"})}),new Promise((n,a)=>{e.addEventListener("error",e=>{a(e)}),e.addEventListener("message",t=>{if(t.data){for(const t of l)t!==e&&t.postMessage({type:"abort"});if(t.data.error)return a(new Error(t.data.error))}n(t.data)}),e.postMessage({challenge:t,counterMode:i,counterStart:r,counterStep:c,timeout:s,type:"work"})}))))}catch(r){if(r instanceof Error&&!!r?.message?.includes("Out of memory")&&o){u();const r=o(c);if(r)return v({...e,challenge:t,controller:n,concurrency:r,createWorker:a})}throw r}finally{u()}return n.signal.aborted?null:h||null}async function A(e,t={}){let{concurrency:r=Math.max(1,Math.min(4,navigator.hardwareConcurrency)),createWorker:n,deriveKey:a=l}=t,o=null;try{o=JSON.parse(atob(e))}catch{throw new Error("Unable to parse obfuscated data.")}if(!o||"object"!=typeof o||!("parameters"in o)||!("cipher"in o))throw new Error("Invalid obfuscated data format.");const i=o.cipher;let s=null;if(!n&&"$altcha"in globalThis&&(n=globalThis.$altcha.algorithms.get(o.parameters.algorithm)),s=n?await v({challenge:o,concurrency:r,createWorker:n}):await async function(e){const{challenge:t,controller:r,counterMode:n="uint32",counterStart:a=0,counterStep:o=1,deriveKey:i,timeout:s=9e4}=e,{nonce:c,keyPrefix:l,salt:g}=t.parameters,d=f(c),w=f(g),p=l.length%2==0?f(l):null,S=new b(d,n),v=performance.now();let A=a,E=0,T="",x=v;for(;;){if(r?.signal.aborted||s&&E%10==0&&performance.now()-v>s)return null;const{derivedKey:e}=await i(t.parameters,w,S.setCounter(A));if(E%10==0&&performance.now()-x>200&&(await y(0),x=performance.now()),p?u(e,p):h(e).startsWith(l)){T=h(e);break}A+=o,E+=1}return{counter:A,derivedKey:T,time:m(v)}}({challenge:o,deriveKey:a}),!s)throw new Error("Unable to find solution.");const c=await crypto.subtle.importKey("raw",f(s.derivedKey),{name:"AES-GCM"},!1,["decrypt"]),g=await crypto.subtle.decrypt({name:"AES-GCM",iv:f(i.iv)},c,f(i.data));return(new TextDecoder).decode(g)}async function E(e,t={}){const{deriveKey:r=l}=t,n=t?.counterMin||20,a=t?.counterMax||200,{parameters:o}=await S({algorithm:"PBKDF2/SHA-256",cost:5e3,deriveKey:r,counter:Math.floor(Math.random()*(a-n+1))+n,keyPrefixLength:32,...t}),i=await crypto.subtle.importKey("raw",f(o.keyPrefix),{name:"AES-GCM"},!1,["encrypt"]),s=crypto.getRandomValues(new Uint8Array(12)),c=await crypto.subtle.encrypt({name:"AES-GCM",iv:s},i,(new TextEncoder).encode(e));return btoa(JSON.stringify({parameters:{...o,keyPrefix:o.keyPrefix.slice(0,o.keyLength||32)},cipher:{iv:h(s),data:h(c)}}))}s.register(class extends s{static deobfuscate=A;static obfuscate=E;elTrigger=null;activate(){this.elTrigger=this.host.querySelector("button"),this.elTrigger&&(this.elTrigger.addEventListener("click",this.onTriggerClick.bind(this)),this.host.configure({floatingAnchor:this.elTrigger}))}destroy(){}async onVerify(e){const{minDuration:t=500}=e,r=performance.now(),n=this.host.getAttribute("data-obfuscated");if(n){this.host.reset(p.VERIFYING);try{const e=await A(n);await this.#e(Math.max(0,t-(performance.now()-r))),this.#t(e)}catch(e){this.host.setState(p.ERROR,String(e))}finally{this.host.setState(p.VERIFIED)}return null}}onTriggerClick(e){e.preventDefault(),this.host.show(),this.host.verify().then(()=>{this.host.hide()})}#t(e){let t;if(e.match(/^(mailto|tel|sms|https?):/)){const[r]=e.slice(e.indexOf(":")+1).replace(/^\/\//,"").split("?");t=document.createElement("a"),t.href=e,t.innerText=r}else t=document.createTextNode(e);this.elTrigger&&t&&(this.elTrigger.after(t),this.elTrigger.parentElement?.removeChild(this.elTrigger))}async#e(e){await new Promise(t=>setTimeout(t,e))}})});
|
package/dist/types/jsx.d.ts
CHANGED
|
@@ -2,7 +2,16 @@ import './global';
|
|
|
2
2
|
import type { CSSVariables, WidgetAttributes } from './';
|
|
3
3
|
export {};
|
|
4
4
|
interface AltchaWidgetJSX extends WidgetAttributes {
|
|
5
|
-
|
|
5
|
+
class?: string;
|
|
6
|
+
className?: string;
|
|
7
|
+
hidden?: boolean;
|
|
8
|
+
id?: string;
|
|
9
|
+
role?: string;
|
|
10
|
+
slot?: string;
|
|
11
|
+
style?: string | Partial<CSSVariables>;
|
|
12
|
+
tabindex?: number | string;
|
|
13
|
+
tabIndex?: number;
|
|
14
|
+
title?: string;
|
|
6
15
|
}
|
|
7
16
|
declare global {
|
|
8
17
|
namespace JSX {
|
package/dist/types/react.d.ts
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import './global';
|
|
2
|
+
import type { CSSProperties, HTMLAttributes, Ref } from 'react';
|
|
2
3
|
import type { CSSVariables, WidgetAttributes } from './';
|
|
3
4
|
export {};
|
|
4
|
-
interface AltchaWidgetReact extends WidgetAttributes {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
style?: Partial<CSSVariables>;
|
|
5
|
+
interface AltchaWidgetReact extends WidgetAttributes, HTMLAttributes<HTMLElement> {
|
|
6
|
+
ref?: Ref<HTMLElement>;
|
|
7
|
+
style?: CSSProperties & Partial<CSSVariables>;
|
|
8
8
|
suppressHydrationWarning?: boolean;
|
|
9
9
|
}
|
|
10
|
-
interface AltchaWidgetReactRefObject<T> {
|
|
11
|
-
current: T | null;
|
|
12
|
-
}
|
|
13
10
|
declare global {
|
|
14
11
|
namespace React {
|
|
15
12
|
namespace JSX {
|
package/dist/types/svelte.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import './global';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
3
|
import type { CodeChallenge, ServerVerificationResult, State, WidgetAttributes } from './';
|
|
3
4
|
export {};
|
|
4
|
-
interface AltchaWidgetSvelte extends WidgetAttributes {
|
|
5
|
+
interface AltchaWidgetSvelte extends WidgetAttributes, HTMLAttributes<HTMLElement> {
|
|
5
6
|
oncodechallenge?: (ev: CustomEvent<{
|
|
6
7
|
codeChallenge: CodeChallenge;
|
|
7
8
|
}>) => void;
|
|
8
9
|
onexpired?: (ev: CustomEvent<unknown>) => void;
|
|
9
|
-
onload?: (ev: CustomEvent<unknown>) => void;
|
|
10
10
|
onstatechange?: (e: CustomEvent<{
|
|
11
11
|
payload?: string;
|
|
12
12
|
state: State;
|
|
@@ -15,7 +15,6 @@ interface AltchaWidgetSvelte extends WidgetAttributes {
|
|
|
15
15
|
onverified?: (e: CustomEvent<{
|
|
16
16
|
payload: string;
|
|
17
17
|
}>) => void;
|
|
18
|
-
style?: string;
|
|
19
18
|
}
|
|
20
19
|
declare global {
|
|
21
20
|
namespace svelteHTML {
|
package/dist/workers/argon2id.js
CHANGED
package/dist/workers/pbkdf2.js
CHANGED
package/dist/workers/scrypt.js
CHANGED
package/dist/workers/sha.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "altcha",
|
|
3
3
|
"description": "Privacy-first CAPTCHA widget, compliant with global regulations (GDPR/HIPAA/CCPA/LGDP/DPDPA/PIPL) and WCAG accessible. No tracking, self-verifying.",
|
|
4
|
-
"version": "3.0
|
|
4
|
+
"version": "3.2.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Daniel Regeci",
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
"lint": "prettier --check .",
|
|
108
108
|
"format": "prettier --write .",
|
|
109
109
|
"test": "vitest",
|
|
110
|
-
"test:e2e": "
|
|
110
|
+
"test:e2e": "vitest run --config vite.config.e2e.ts",
|
|
111
111
|
"prepare": "husky"
|
|
112
112
|
},
|
|
113
113
|
"devDependencies": {
|
|
@@ -119,11 +119,13 @@
|
|
|
119
119
|
"@types/node": "^24.10.1",
|
|
120
120
|
"@types/react": "^19.2.10",
|
|
121
121
|
"@types/react-dom": "^19.2.3",
|
|
122
|
+
"@vitest/browser-playwright": "4.1.8",
|
|
122
123
|
"cssnano": "^7.1.2",
|
|
123
124
|
"daisyui": "^5.5.14",
|
|
124
125
|
"dts-bundle-generator": "^9.5.1",
|
|
125
126
|
"glob": "^13.0.0",
|
|
126
127
|
"husky": "^9.1.7",
|
|
128
|
+
"playwright": "1.60.0",
|
|
127
129
|
"prettier": "^3.8.1",
|
|
128
130
|
"prettier-plugin-svelte": "^3.4.1",
|
|
129
131
|
"prettier-plugin-tailwindcss": "^0.7.2",
|
|
@@ -133,16 +135,17 @@
|
|
|
133
135
|
"svelte-check": "^4.3.4",
|
|
134
136
|
"tailwindcss": "^4.1.18",
|
|
135
137
|
"terser": "^5.44.1",
|
|
136
|
-
"testcafe": "^3.7.4",
|
|
137
138
|
"typescript": "~5.9.3",
|
|
138
|
-
"vite": "^7.3.
|
|
139
|
+
"vite": "^7.3.5",
|
|
139
140
|
"vite-plugin-markdown": "^2.2.0",
|
|
140
|
-
"vitest": "^4.
|
|
141
|
+
"vitest": "^4.1.8"
|
|
141
142
|
},
|
|
142
143
|
"dependencies": {
|
|
143
144
|
"hash-wasm": "^4.12.0"
|
|
144
145
|
},
|
|
145
146
|
"overrides": {
|
|
147
|
+
"esbuild": "^0.28.1",
|
|
148
|
+
"markdown-it": "^14.2.0",
|
|
146
149
|
"tmp": "^0.2.7",
|
|
147
150
|
"underscore": "^1.13.8"
|
|
148
151
|
}
|