Compare commits

..
40 changed files with 1553 additions and 2441 deletions

View file

@ -4,7 +4,6 @@ use App\Http\Middleware\LinkHeadersMiddleware;
use Illuminate\Foundation\Application; use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware; use Illuminate\Foundation\Configuration\Middleware;
use Spatie\LaravelFlare\Facades\Flare;
return Application::configure(basePath: dirname(__DIR__)) return Application::configure(basePath: dirname(__DIR__))
->withRouting( ->withRouting(
@ -25,5 +24,5 @@ return Application::configure(basePath: dirname(__DIR__))
]); ]);
}) })
->withExceptions(function (Exceptions $exceptions) { ->withExceptions(function (Exceptions $exceptions) {
Flare::handles($exceptions); //
})->create(); })->create();

View file

@ -30,7 +30,7 @@
"mf2/mf2": "~0.3", "mf2/mf2": "~0.3",
"phpdocumentor/reflection-docblock": "^5.3", "phpdocumentor/reflection-docblock": "^5.3",
"spatie/commonmark-highlighter": "^3.0", "spatie/commonmark-highlighter": "^3.0",
"spatie/laravel-flare": "^2.2", "spatie/laravel-ignition": "^2.1",
"symfony/html-sanitizer": "^7.0", "symfony/html-sanitizer": "^7.0",
"symfony/property-access": "^7.0", "symfony/property-access": "^7.0",
"symfony/serializer": "^7.0", "symfony/serializer": "^7.0",
@ -46,7 +46,7 @@
"laravel/sail": "^1.18", "laravel/sail": "^1.18",
"mockery/mockery": "^1.4.4", "mockery/mockery": "^1.4.4",
"nunomaduro/collision": "^8.1", "nunomaduro/collision": "^8.1",
"openai-php/client": "^0.17.1", "openai-php/client": "^0.10.1",
"phpunit/php-code-coverage": "^11.0", "phpunit/php-code-coverage": "^11.0",
"phpunit/phpunit": "^11.0", "phpunit/phpunit": "^11.0",
"spatie/laravel-ray": "^1.12", "spatie/laravel-ray": "^1.12",

2110
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -12,7 +12,7 @@ return [
| |
*/ */
'enabled' => false, 'enabled' => null,
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

View file

@ -1,206 +0,0 @@
<?php
use Spatie\FlareClient\Api;
use Spatie\LaravelFlare\AttributesProviders\LaravelUserAttributesProvider;
use Spatie\LaravelFlare\FlareConfig;
return [
/*
|
|--------------------------------------------------------------------------
| Flare API key
|--------------------------------------------------------------------------
|
| Specify Flare's API key below to enable error reporting to the service.
|
| More info: https://flareapp.io/docs/flare/general/getting-started
|
*/
'key' => env('FLARE_KEY'),
/*
|
|--------------------------------------------------------------------------
| Flare Base URL
|--------------------------------------------------------------------------
|
| Which server should be used to send the reports/traces to.
|
*/
'base_url' => env('FLARE_BASE_URL', Api::BASE_URL),
/*
|--------------------------------------------------------------------------
| Collects
|--------------------------------------------------------------------------
|
| Flare will collect a lot of information about your application. You can
| disable some of the collectors here, configure them or add your own.
|
*/
'collects' => FlareConfig::defaultCollects(
ignore: [],
extra: []
),
/*
|--------------------------------------------------------------------------
| Attribute providers
|--------------------------------------------------------------------------
|
| When sending an error report or trace to Flare attributes can be added to
| the report or trace for common entries. An example of such an entry is
| the currently authenticated user. In an attribute provider you can
| specify which attributes should be sent.
|
*/
'attribute_providers' => [
'user' => LaravelUserAttributesProvider::class,
],
/*
|--------------------------------------------------------------------------
| Censor data
|--------------------------------------------------------------------------
|
| It is possible to censor sensitive data from the reports and sent to
| Flare. Below you can specify which fields and header should be
| censored. It is also possible to hide the client's IP address.
|
*/
'censor' => [
'body_fields' => [
'password',
'password_confirmation',
],
'headers' => [
'API-KEY',
'Authorization',
'Cookie',
'Set-Cookie',
'X-CSRF-TOKEN',
'X-XSRF-TOKEN',
],
'client_ips' => false,
],
/*
|--------------------------------------------------------------------------
| Reporting log statements
|--------------------------------------------------------------------------
|
| If this setting is `false` log statements won't be sent as events to Flare,
| no matter which error level you specified in the Flare log channel.
|
*/
'send_logs_as_events' => true,
/*
|--------------------------------------------------------------------------
| Report error levels
|--------------------------------------------------------------------------
| When reporting errors, you can specify which error levels should be
| reported. By default, all error levels are reported by setting
| this value to `null`.
*/
'report_error_levels' => null,
/*
|--------------------------------------------------------------------------
| Share button
|--------------------------------------------------------------------------
|
| Flare automatically adds a Share button to the laravel error page. This
| button allows you to easily share errors with colleagues or friends. It
| is enabled by default, but you can disable it here.
|
*/
'enable_share_button' => true,
/*
|--------------------------------------------------------------------------
| Override grouping
|--------------------------------------------------------------------------
|
| Flare will try to group errors and exceptions as best as possible, that
| being said, sometimes you might want to override the grouping. You can
| do this by adding exception classes to this array which should always
| be grouped by exception class, exception message or exception class
| and message.
|
*/
'overridden_groupings' => [
// Illuminate\Http\Client\ConnectionException::class => Spatie\FlareClient\Enums\OverriddenGrouping::ExceptionMessageAndClass,
],
/*
|--------------------------------------------------------------------------
| Sender
|--------------------------------------------------------------------------
|
| The sender is responsible for sending the error reports and traces to
| Flare it can be configured if needed.
|
*/
'sender' => [
'class' => \Spatie\LaravelFlare\Senders\LaravelHttpSender::class,
'config' => [
'timeout' => 10,
],
],
/*
|--------------------------------------------------------------------------
| Trace
|--------------------------------------------------------------------------
|
| Tracing allows you to see the flow of your application. It shows you
| which parts of your application are slow and which parts are fast.
|
*/
'trace' => env('FLARE_TRACE', false),
/*
|--------------------------------------------------------------------------
| Sampler
|--------------------------------------------------------------------------
|
| The sampler is used to determine which traces should be recorded and
| which traces should be dropped. It is possible to set the rate
| at which traces should be recorded. The default rate is 0.1
| which means that 10% of the traces will be recorded.
|
*/
'sampler' => [
'class' => \Spatie\FlareClient\Sampling\RateSampler::class,
'config' => [
'rate' => 0.1,
],
],
/*
|--------------------------------------------------------------------------
| Trace limits
|--------------------------------------------------------------------------
|
| Limits for the tracing data. These limits are used to prevent
| the tracing data from growing too large.
|
*/
'trace_limits' => [
'max_spans' => 512,
'max_attributes_per_span' => 128,
'max_span_events_per_span' => 128,
'max_attributes_per_span_event' => 128,
],
];

812
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -8,7 +8,7 @@
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.6.0", "@eslint/js": "^9.6.0",
"@stylistic/eslint-plugin": "^5.1.0", "@stylistic/eslint-plugin": "^5.1.0",
"esbuild": "^0.27.1", "esbuild": "^0.25.2",
"eslint": "^9.7.0", "eslint": "^9.7.0",
"globals": "^16.0.0", "globals": "^16.0.0",
"lightningcss": "^1.29.3", "lightningcss": "^1.29.3",
@ -17,18 +17,13 @@
"stylelint-config-standard": "^39.0.0" "stylelint-config-standard": "^39.0.0"
}, },
"scripts": { "scripts": {
"eslint": "eslint resources/js/*.js", "eslint": "eslint public/assets/js/*.js",
"stylelint": "stylelint resources/css/*.css", "stylelint": "stylelint resources/css/*.css",
"lint": "npm run eslint && npm run stylelint", "lint": "npm run eslint && npm run stylelint",
"lightningcss": "lightningcss --output-dir public/assets/css --sourcemap --bundle --minify resources/css/app.css", "lightningcss": "lightningcss --output-dir public/assets/css --sourcemap --bundle --minify resources/css/app.css",
"fix-sourcemap": "./scripts/fix-sourcemap.sh", "fix-sourcemap": "./scripts/fix-sourcemap.sh",
"build-css": "npm run lightningcss && npm run fix-sourcemap", "build-css": "npm run lightningcss && npm run fix-sourcemap",
"build-js": "esbuild resources/js/app.js --bundle --minify --sourcemap --outfile=public/assets/js/app.js",
"compress": "./scripts/compress.sh", "compress": "./scripts/compress.sh",
"build": "npm run lint && npm run build-css && npm run build-js && npm run compress" "build": "npm run lint && npm run compress"
},
"dependencies": {
"@11ty/is-land": "^5.0.0",
"@zachleat/snow-fall": "^1.0.3"
} }
} }

View file

@ -1,2 +1,2 @@
@layer reset{*,:before,:after{box-sizing:border-box}html{-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none}body,h1,h2,h3,h4,p,figure,blockquote,dl,dd{margin-block-end:0}ul[role=list],ol[role=list]{list-style:none}body{line-height:1.5}h1,h2,h3,h4,button,input,label{line-height:1.1}h1,h2,h3,h4{text-wrap:balance}a:not([class]){text-decoration-skip-ink:auto;color:currentColor}img,picture{max-width:100%;display:block}input,button,textarea,select{font-family:inherit;font-size:inherit}textarea:not([rows]){min-height:10em}:target{scroll-margin-block:5ex}@media (prefers-reduced-motion){::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation:none!important}}}@layer base{:root{color-scheme:light dark;--primary-hue:307;--clr-text:light-dark(oklch(5% .1 var(--primary-hue)),oklch(100% .1 var(--primary-hue)));--clr-background:light-dark(oklch(100% .1 var(--primary-hue)),oklch(15% .15 var(--primary-hue)));--clr-border:light-dark(oklch(90% .2 var(--primary-hue)),oklch(25% .1 var(--primary-hue)));--clr-snow-fall:light-dark(oklch(25% .15 var(--primary-hue)),oklch(85% .2 var(--primary-hue)))}body{background-color:var(--clr-background);color:var(--clr-text)}:root{--border-radius:8px}html{font-size:125%}body{grid-template-rows:min-content 1fr min-content;grid-template-columns:1fr min(80ch,95vw) 1fr;padding-inline:4vw;display:grid;&>header{grid-column:1/-1}&>main{grid-column:2/3}&>footer{grid-column:1/-1;margin-block-start:2ex;& search form{flex-direction:row;align-items:center;gap:1ex;display:flex}}}.h-feed{flex-direction:column;gap:2ex;display:flex}}@layer components{body>header{grid-template-rows:auto auto;grid-template-columns:auto 1fr auto;align-items:baseline;gap:1rem;display:grid;& a{text-decoration:none}& h1{text-wrap:nowrap;margin:0}& nav{flex-direction:row;gap:.5rem;display:flex;@media screen and (width<=1100px){flex-wrap:wrap;grid-area:2/1/auto/span 3}}}.h-feed{& .note{border:1px solid var(--clr-border);border-radius:var(--border-radius);flex-direction:column;padding:1ex 2ex;display:flex;& .e-content>p:first-child{margin-block-start:0}}& .reply-to{border:1px solid var(--clr-border);border-top-left-radius:var(--border-radius);border-top-right-radius:var(--border-radius);border-bottom:none;margin-inline:2ex;padding-inline:1ex;font-size:85%}}.pagination{flex-direction:row;justify-content:center;align-items:center;display:flex;& div{flex-direction:row;gap:1ex;display:flex}}#theme-selector{& button{appearance:none;background:0 0;border:none;&:hover{cursor:pointer}}& #theme-selector-dropdown{position-area:block-end span-inline-start;border:2px solid var(--clr-border);background-color:var(--clr-background);color:var(--clr-text);margin:0;position:absolute;& fieldset{border:0;flex-direction:row;gap:1ch;display:flex;& input{display:none}}}@media (prefers-reduced-motion:no-preference){& #theme-selector-dropdown{&:popover-open{opacity:1;transform:translateY(0)scale(1);@starting-style{opacity:0;transform:translateY(30px)scale(0)}}opacity:0;transition:transform,opacity,display allow-discrete,overlay allow-discrete;transform-origin:100% 0;transition-duration:.5s;transform:translateY(0)scale(0)}}}::view-transition-group(changing-theme){animation-duration:1.25s}::view-transition-new(changing-theme),::view-transition-old(changing-theme){mix-blend-mode:normal}::view-transition-new(changing-theme){animation-name:reveal}::view-transition-old(changing-theme){animation:none}@keyframes reveal{0%{clip-path:polygon(-30% 0,-30% 0,-15% 100%,-10% 115%)}to{clip-path:polygon(-30% 0,130% 0,115% 100%,-10% 115%)}}} :root{--font-family-headings:"Rockwell","Rockwell Nova","Roboto Slab","DejaVu Serif","Sitka Small",serif;--font-family-body:"Charter","Bitstream Charter","Sitka Text","Cambria",serif;--font-family-monospace:ui-monospace,"Cascadia Code","Source Code Pro","Menlo","Consolas","DejaVu Sans Mono",monospace;--font-size-sm:.75rem;--font-size-base:1rem;--font-size-md:1.25rem;--font-size-lg:1.5rem;--font-size-xl:1.75rem;--font-size-xxl:2rem;--font-size-xxxl:2.25rem;--color-primary:oklch(36.8% .1 125.505);--color-secondary:oklch(96.3% .1 125.505);--color-link:oklch(48.09% .146 241.41);--color-link-visited:oklch(70.44% .21 304.41);--color-primary-shadow:oklch(19.56% .054 125.505/.4);--rss-color-link:oklch(67.59% .189 42.04);--color-danger:oklch(64.41% .281 23.29);--color-danger-shadow:oklch(64.41% .281 23.29/.1)}body{font-family:var(--font-family-body);font-size:var(--font-size-md)}code{font-family:var(--font-family-monospace)}h1,h2,h3,h4,h5,h6{font-family:var(--font-family-headings)}.grid{grid-template-rows:min-content 1fr min-content;grid-template-columns:5vw 1fr 5vw;row-gap:1rem;display:grid}#site-header{grid-area:1/2/2/3;& .rss-icon{& svg{width:auto;height:1rem}}}main{grid-area:2/2/3/3}.h-feed{flex-direction:column;gap:2rem;display:flex}.h-entry{& p:first-of-type,& h1:first-of-type{margin-block-start:0}}.pagination{margin-block-start:1rem}footer{grid-area:3/2/4/3;& .iwc-logo{max-width:85vw}& .footer-actions{flex-direction:row;gap:1rem;display:flex}}body{background-color:var(--color-secondary);color:var(--color-primary)}a{color:var(--color-link);&:visited{color:var(--color-link-visited)}&.auth:visited{color:var(--color-link)}}#site-header{& a:visited{color:var(--color-link)}& .rss-icon{& svg{color:var(--rss-color-link)}}}.hljs{border-radius:.5rem}.h-card{& .hovercard{z-index:100;box-shadow:0 .5rem .5rem .5rem var(--color-primary-shadow);background-color:var(--color-secondary);opacity:0;border-radius:1rem;flex-direction:column;gap:.5rem;width:fit-content;padding:1rem;transition:opacity .5s ease-in-out;display:none;position:absolute;& .u-photo{max-width:6rem}& .social-icon{width:1rem;height:1rem}}&:hover{& .hovercard{opacity:1;display:flex}}}.h-entry{border-inline-start:1px solid var(--color-primary);padding-inline-start:.5rem;& .reply-to{font-style:italic}& .post-info{& a{text-decoration:none}}& .note-metadata{flex-direction:row;gap:1rem;display:flex;& .replies,& .likes,& .reposts{flex-direction:row;align-items:center;gap:.5rem;display:inline-flex}& .syndication-links{flex-flow:wrap;& a{text-decoration:none;& svg{width:1rem;height:1rem}}}}}.feather{stroke:currentColor;stroke-width:2px;stroke-linecap:round;stroke-linejoin:round;fill:none;width:24px;height:24px}.sr-only{clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}main{&>.u-comment{border-inline-start:1px solid var(--color-primary);margin-block-start:2rem;margin-inline-start:2rem;padding-inline-start:.5rem;& .mini-h-card{flex-direction:row;align-items:baseline;display:inline-flex;& .u-photo{border-radius:50%;width:2rem;height:2rem;margin-block-end:.5rem}}}& .notes-subtitle{font-size:1.2rem;font-weight:600}& .webmentions-author-list{flex-flow:wrap;gap:1rem;display:flex;& img{border-radius:50%;width:4rem;height:4rem}}}.indieauth{& .error{color:var(--color-danger);background-color:var(--color-danger-shadow);border:1px solid var(--color-danger);border-radius:.5rem;width:fit-content;margin-block-end:1rem;padding-block:.5rem;padding-inline:1rem;display:flex}}
/*# sourceMappingURL=/assets/css/app.css.map */ /*# sourceMappingURL=/assets/css/app.css.map */

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -1,2 +1,2 @@
(()=>{var l=class{constructor(){}async register(){let r=await this.getCreateOptions(),e={challenge:this.base64URLStringToBuffer(r.challenge),rp:{id:r.rp.id,name:r.rp.name},user:{id:new TextEncoder().encode(window.atob(r.user.id)),name:r.user.name,displayName:r.user.displayName},pubKeyCredParams:r.pubKeyCredParams,excludeCredentials:[],authenticatorSelection:r.authenticatorSelection,timeout:6e4},t=await navigator.credentials.create({publicKey:e});if(!t)throw new Error("Error generating a passkey");let n={id:t.id?t.id:null,type:t.type?t.type:null,rawId:t.rawId?this.bufferToBase64URLString(t.rawId):null,response:{attestationObject:t.response.attestationObject?this.bufferToBase64URLString(t.response.attestationObject):null,clientDataJSON:t.response.clientDataJSON?this.bufferToBase64URLString(t.response.clientDataJSON):null}};if(!(await window.fetch("/admin/passkeys/register",{method:"POST",body:JSON.stringify(n),cache:"no-cache",headers:{"Content-Type":"application/json","X-CSRF-TOKEN":document.querySelector('meta[name="csrf-token"]').getAttribute("content")}})).ok)throw new Error("Error saving the passkey");window.location.reload()}async getCreateOptions(){return await(await fetch("/admin/passkeys/register",{method:"GET"})).json()}async login(){let r=await this.getLoginData(),e=await navigator.credentials.get({publicKey:{challenge:this.base64URLStringToBuffer(r.challenge),userVerification:r.userVerification,timeout:6e4}});if(!e)throw new Error("Authentication failed");let t={id:e.id?e.id:"",type:e.type?e.type:"",rawId:e.rawId?this.bufferToBase64URLString(e.rawId):"",response:{authenticatorData:e.response.authenticatorData?this.bufferToBase64URLString(e.response.authenticatorData):"",clientDataJSON:e.response.clientDataJSON?this.bufferToBase64URLString(e.response.clientDataJSON):"",signature:e.response.signature?this.bufferToBase64URLString(e.response.signature):"",userHandle:e.response.userHandle?this.bufferToBase64URLString(e.response.userHandle):""}};if(!(await window.fetch("/login/passkey",{method:"POST",body:JSON.stringify(t),headers:{"Content-Type":"application/json","X-CSRF-TOKEN":document.querySelector('meta[name="csrf-token"]').getAttribute("content")}})).ok)throw new Error("Login failed");window.location.assign("/admin")}async getLoginData(){return await(await fetch("/login/passkey",{method:"GET"})).json()}base64URLStringToBuffer(r){let e=r.replace(/-/g,"+").replace(/_/g,"/"),t=(4-e.length%4)%4,n=e.padEnd(e.length+t,"="),a=window.atob(n),o=new ArrayBuffer(a.length),i=new Uint8Array(o);for(let s=0;s<a.length;s++)i[s]=a.charCodeAt(s);return o}bufferToBase64URLString(r){let e=new Uint8Array(r),t="";for(let a of e)t+=String.fromCharCode(a);return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}};var d=class{constructor(){this.widget=document.querySelector("#theme-selector")}setupEventListeners(){this.widget.querySelectorAll("#theme-selector-dropdown input").forEach(r=>r.addEventListener("input",e=>{let t=e.target.value;this.widget.querySelectorAll(".toggle svg").forEach(u=>{u.classList.contains(t)?u.style.display="":u.style.display="none"});let n;switch(t){case"dark":case"light":n=t;break;default:n="light dark"}let a=window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light",o=document.querySelector("html"),i=o.style.getPropertyValue("color-scheme");i===""&&(i="light dark");let s=!1;n!==i&&(n==="light dark"?s=i!==a:i==="light dark"?s=n!==a:s=!0),o.style.viewTransitionName="changing-theme",s&&document.startViewTransition?document.startViewTransition(()=>{document.querySelector("#theme-selector-dropdown").togglePopover(),o.style.setProperty("color-scheme",n)}):(document.querySelector("#theme-selector-dropdown").togglePopover(),o.style.setProperty("color-scheme",n))}))}};var h=new l;document.querySelectorAll(".add-passkey").forEach(c=>{c.addEventListener("click",()=>{h.register()})});document.querySelectorAll(".login-passkey").forEach(c=>{c.addEventListener("click",()=>{h.login()})});var p=new d;p.setupEventListeners();})(); (()=>{var i=class{constructor(){}async register(){let n=await this.getCreateOptions(),e={challenge:this.base64URLStringToBuffer(n.challenge),rp:{id:n.rp.id,name:n.rp.name},user:{id:new TextEncoder().encode(window.atob(n.user.id)),name:n.user.name,displayName:n.user.displayName},pubKeyCredParams:n.pubKeyCredParams,excludeCredentials:[],authenticatorSelection:n.authenticatorSelection,timeout:6e4},t=await navigator.credentials.create({publicKey:e});if(!t)throw new Error("Error generating a passkey");let r={id:t.id?t.id:null,type:t.type?t.type:null,rawId:t.rawId?this.bufferToBase64URLString(t.rawId):null,response:{attestationObject:t.response.attestationObject?this.bufferToBase64URLString(t.response.attestationObject):null,clientDataJSON:t.response.clientDataJSON?this.bufferToBase64URLString(t.response.clientDataJSON):null}};if(!(await window.fetch("/admin/passkeys/register",{method:"POST",body:JSON.stringify(r),cache:"no-cache",headers:{"Content-Type":"application/json","X-CSRF-TOKEN":document.querySelector('meta[name="csrf-token"]').getAttribute("content")}})).ok)throw new Error("Error saving the passkey");window.location.reload()}async getCreateOptions(){return await(await fetch("/admin/passkeys/register",{method:"GET"})).json()}async login(){let n=await this.getLoginData(),e=await navigator.credentials.get({publicKey:{challenge:this.base64URLStringToBuffer(n.challenge),userVerification:n.userVerification,timeout:6e4}});if(!e)throw new Error("Authentication failed");let t={id:e.id?e.id:"",type:e.type?e.type:"",rawId:e.rawId?this.bufferToBase64URLString(e.rawId):"",response:{authenticatorData:e.response.authenticatorData?this.bufferToBase64URLString(e.response.authenticatorData):"",clientDataJSON:e.response.clientDataJSON?this.bufferToBase64URLString(e.response.clientDataJSON):"",signature:e.response.signature?this.bufferToBase64URLString(e.response.signature):"",userHandle:e.response.userHandle?this.bufferToBase64URLString(e.response.userHandle):""}};if(!(await window.fetch("/login/passkey",{method:"POST",body:JSON.stringify(t),headers:{"Content-Type":"application/json","X-CSRF-TOKEN":document.querySelector('meta[name="csrf-token"]').getAttribute("content")}})).ok)throw new Error("Login failed");window.location.assign("/admin")}async getLoginData(){return await(await fetch("/login/passkey",{method:"GET"})).json()}base64URLStringToBuffer(n){let e=n.replace(/-/g,"+").replace(/_/g,"/"),t=(4-e.length%4)%4,r=e.padEnd(e.length+t,"="),a=window.atob(r),c=new ArrayBuffer(a.length),d=new Uint8Array(c);for(let o=0;o<a.length;o++)d[o]=a.charCodeAt(o);return c}bufferToBase64URLString(n){let e=new Uint8Array(n),t="";for(let a of e)t+=String.fromCharCode(a);return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}};var l=new i;document.querySelectorAll(".add-passkey").forEach(s=>{s.addEventListener("click",()=>{l.register()})});document.querySelectorAll(".login-passkey").forEach(s=>{s.addEventListener("click",()=>{l.login()})});})();
//# sourceMappingURL=app.js.map //# sourceMappingURL=app.js.map

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

View file

@ -1,125 +0,0 @@
class Snow extends HTMLElement {
static random(min, max) {
return min + Math.floor(Math.random() * (max - min) + 1);
}
static attrs = {
count: "count", // default: 100
mode: "mode",
text: "text", // text in snow flake (emoji, too)
}
generateCss(mode, count) {
let css = [];
css.push(`
:host([mode="element"]) {
display: block;
position: relative;
overflow: hidden;
}
:host([mode="page"]) {
position: fixed;
top: 0;
left: 0;
right: 0;
}
:host([mode="page"]),
:host([mode="element"]) > * {
pointer-events: none;
}
:host([mode="element"]) ::slotted(*) {
pointer-events: all;
}
* {
position: absolute;
}
:host([text]) * {
font-size: var(--snow-fall-size, 1em);
}
:host(:not([text])) * {
width: var(--snow-fall-size, 10px);
height: var(--snow-fall-size, 10px);
background: var(--snow-fall-color, rgba(255,255,255,.5));
border-radius: 50%;
}
`);
// using vw units (max 100)
let dimensions = { width: 100, height: 100 };
let units = { x: "vw", y: "vh"};
if(mode === "element") {
dimensions = {
width: this.firstElementChild.clientWidth,
height: this.firstElementChild.clientHeight,
};
units = { x: "px", y: "px"};
}
// Thank you @alphardex: https://codepen.io/alphardex/pen/dyPorwJ
for(let j = 1; j<= count; j++ ) {
let x = Snow.random(1, 100) * dimensions.width/100; // vw
let offset = Snow.random(-10, 10) * dimensions.width/100; // vw
let yoyo = Math.round(Snow.random(30, 100)); // % time
let yStart = yoyo * dimensions.height/100; // vh
let yEnd = dimensions.height; // vh
let scale = Snow.random(1, 10000) * .0001;
let duration = Snow.random(10, 30);
let delay = Snow.random(0, 30) * -1;
css.push(`
:nth-child(${j}) {
opacity: ${Snow.random(0, 1000) * 0.001};
transform: translate(${x}${units.x}, -10px) scale(${scale});
animation: fall-${j} ${duration}s ${delay}s linear infinite;
}
@keyframes fall-${j} {
${yoyo}% {
transform: translate(${x + offset}${units.x}, ${yStart}${units.y}) scale(${scale});
}
to {
transform: translate(${x + offset / 2}${units.x}, ${yEnd}${units.y}) scale(${scale});
}
}`)
}
return css.join("\n");
}
connectedCallback() {
// https://caniuse.com/mdn-api_cssstylesheet_replacesync
if(this.shadowRoot || !("replaceSync" in CSSStyleSheet.prototype)) {
return;
}
let count = parseInt(this.getAttribute(Snow.attrs.count)) || 100;
let mode;
if(this.hasAttribute(Snow.attrs.mode)) {
mode = this.getAttribute(Snow.attrs.mode);
} else {
mode = this.firstElementChild ? "element" : "page";
this.setAttribute(Snow.attrs.mode, mode);
}
let sheet = new CSSStyleSheet();
sheet.replaceSync(this.generateCss(mode, count));
let shadowroot = this.attachShadow({ mode: "open" });
shadowroot.adoptedStyleSheets = [sheet];
let d = document.createElement("div");
let text = this.getAttribute(Snow.attrs.text);
d.innerText = text || "";
for(let j = 0, k = count; j<k; j++) {
shadowroot.appendChild(d.cloneNode(true));
}
shadowroot.appendChild(document.createElement("slot"));
}
}
customElements.define("snow-fall", Snow);

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more