custom element for embedding Bluesky posts and feeds mary-ext.github.io/bluesky-embed
typescript npm bluesky atcute

Compare changes

Choose any two refs to compare.

Changed files
+25 -10527
.changeset
.vscode
assets
packages
bluesky-post-embed
bluesky-profile-card-embed
bluesky-profile-feed-embed
internal
svelte-site
patches
themes
-9
.changeset/README.md
··· 1 - # Changesets 2 - 3 - Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool 4 - that works with multi-package repos, or single-package repos to help you version and publish your 5 - code. You can find the full documentation for it 6 - [in our repository](https://github.com/changesets/changesets) 7 - 8 - We have a quick list of common questions to get you started engaging with this project in 9 - [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
-11
.changeset/config.json
··· 1 - { 2 - "$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json", 3 - "changelog": "@changesets/cli/changelog", 4 - "commit": false, 5 - "fixed": [], 6 - "linked": [], 7 - "access": "restricted", 8 - "baseBranch": "trunk", 9 - "updateInternalDependencies": "patch", 10 - "ignore": ["svelte-site"] 11 - }
-8
.changeset/six-rabbits-admire.md
··· 1 - --- 2 - 'bluesky-profile-card-embed': patch 3 - 'bluesky-profile-feed-embed': patch 4 - 'bluesky-post-embed': patch 5 - 'internal': patch 6 - --- 7 - 8 - upgrade atcute dependencies
-13
.gitignore
··· 1 - node_modules/ 2 - dist/ 3 - 4 - .npm-*.log 5 - .pnpm-*.log 6 - .yarn-*.log 7 - npm-*.log 8 - pnpm-*.log 9 - yarn-*.log 10 - 11 - *.local 12 - 13 - *.tsbuildinfo
.nojekyll

This is a binary file and will not be displayed.

-8
.prettierignore
··· 1 - pnpm-lock.yaml 2 - 3 - dist/ 4 - 5 - /packages/svelte-site/pages/ 6 - /packages/bluesky-post-embed/themes/ 7 - /packages/bluesky-profile-card-embed/themes/ 8 - /packages/bluesky-profile-feed-embed/themes/
-25
.prettierrc
··· 1 - { 2 - "trailingComma": "all", 3 - "useTabs": true, 4 - "tabWidth": 2, 5 - "printWidth": 110, 6 - "semi": true, 7 - "singleQuote": true, 8 - "bracketSpacing": true, 9 - "plugins": ["prettier-plugin-svelte", "prettier-plugin-css-order"], 10 - "overrides": [ 11 - { 12 - "files": ["tsconfig.json", "jsconfig.json", "tsconfig.*.json"], 13 - "options": { 14 - "parser": "jsonc" 15 - } 16 - }, 17 - { 18 - "files": ["*.md"], 19 - "options": { 20 - "printWidth": 100, 21 - "proseWrap": "always" 22 - } 23 - } 24 - ] 25 - }
-3
.vscode/extensions.json
··· 1 - { 2 - "recommendations": ["svelte.svelte-vscode"] 3 - }
-4
.vscode/settings.json
··· 1 - { 2 - "editor.defaultFormatter": "prettier.prettier-vscode", 3 - "typescript.tsdk": "node_modules/typescript/lib" 4 - }
-17
LICENSE
··· 1 - Permission is hereby granted, free of charge, to any person obtaining a copy 2 - of this software and associated documentation files (the "Software"), to deal 3 - in the Software without restriction, including without limitation the rights 4 - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 5 - copies of the Software, and to permit persons to whom the Software is 6 - furnished to do so, subject to the following conditions: 7 - 8 - The above copyright notice and this permission notice shall be included in all 9 - copies or substantial portions of the Software. 10 - 11 - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 - SOFTWARE.
-15
README.md
··· 1 - # <bluesky-embed> 2 - 3 - A custom element for embedding Bluesky posts. 4 - 5 - - **Lightweight**, the entire package + dependencies is only ~20 KB (~6 KB gzipped) 6 - - **Standalone**, no middleman involved, directly calls Bluesky's API 7 - - **Server-side rendering possible**, allows for no-JavaScript usage 8 - 9 - | Packages | 10 - | ------------------------------------------------------------------------------------------------ | 11 - | [`bluesky-post-embed`](./packages/bluesky-post-embed): displays a post embed | 12 - | [`bluesky-profile-card-embed`](./packages/bluesky-profile-card-embed): displays a user's profile | 13 - | [`bluesky-profile-feed-embed`](./packages/bluesky-profile-feed-embed): displays a user's feed | 14 - 15 - ![image](https://github.com/user-attachments/assets/fbe19e25-bcc8-4fd5-ac9d-568badbbb238)
+1
assets/GuideInstructions-B8N7RzmZ.css
··· 1 + .code-block.svelte-ipr7k2{display:flex;gap:12px;border:1px solid #d1d5db;border-radius:4px;background:#f9fafb;padding:12px;overflow:hidden;overflow-x:auto;pre:where(.svelte-ipr7k2){flex-grow:1;margin:0;font-size:.75rem;line-height:1.25rem}}.actions.svelte-ipr7k2{position:sticky;top:0;right:0}.action-button.svelte-ipr7k2{display:flex;justify-content:center;align-items:center;cursor:pointer;box-shadow:0 1px 3px #0000001a,0 1px 2px -1px #0000001a;border:1px solid #d1d5db;border-radius:4px;background:#fff;padding:0;width:32px;height:32px;color:#4b5563;@media(pointer:fine){opacity:0;transition:75ms ease-in;.code-block:where(.svelte-ipr7k2):hover &,.code-block:where(.svelte-ipr7k2):focus-within &{opacity:1}&:hover{border-color:#9ca3af;background:#e5e7eb;color:#1f2937}}&:active{border-color:#9ca3af;background:#e5e7eb;color:#1f2937}}.icon.svelte-ipr7k2{width:16px;height:16px}.guide.svelte-1wxv0ke{margin:36px 0 0;border-top:1px solid #d1d5db}.guide-header.svelte-1wxv0ke{margin:36px 0 16px}.guide-instructions.svelte-mki4x9{margin:24px 0 0;padding:0 0 0 22px;font-size:.875rem;line-height:1.25rem;li+li{margin:24px 0 0}}
+1
assets/GuideInstructions-CTis8QB-.js
··· 1 + import{t as e,m as t,r as s,n as r,o as n,q as a,v as o,w as i,x as c,p as l,f as d,k as p,c as h,i as u,a as f,b as v,y,z as g}from"./index-CD_0uzJz.js";function w(e){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function b(o,i,c=!1,l=!1,d=!1){var p=o,h="";e(()=>{var e=t;if(h!==(h=i()??"")&&(null!==e.nodes&&(s(e.nodes.start,e.nodes.end),e.nodes=null),""!==h)){var o=h+"";c?o=`<svg>${o}</svg>`:l&&(o=`<math>${o}</math>`);var d=r(o);if((c||l)&&(d=a(d)),n(a(d),d.lastChild),c||l)for(;a(d);)p.before(a(d));else p.before(d)}})}function k(e){null===o&&w(),function(e){null===o&&w(),i(()=>{const t=c(e);if("function"==typeof t)return t})}(()=>()=>c(e))}const x=({service:e,fetch:t=fetch})=>async(s,r)=>{const n=new URL(s,e);return await t(n,r)},m=(e,t)=>{let s;for(const r in t){const n=t[r];null!==n&&(s??=new Headers(e),s.has(r)||s.set(r,n))}return s??e};class j extends Error{constructor(e,{kind:t=`HTTP error ${e}`,description:s="Unspecified error description",headers:r,cause:n}={}){super(`${t} > ${s}`,{cause:n}),this.name="XRPCError",this.status=e,this.kind=t,this.description=s,this.headers=r||{}}}class ${constructor({handler:e,proxy:t}){this.handle=(e=>"object"==typeof e?e.handle.bind(e):e)(e),this.proxy=t}get(e,t){return this.request({type:"get",nsid:e,...t})}call(e,t){return this.request({type:"post",nsid:e,...t})}async request(e){const t=e.data,s=`/xrpc/${e.nsid}`+O(e.params),r=q(t),n=await this.handle(s,{method:e.type,signal:e.signal,body:r?JSON.stringify(t):t,headers:m(e.headers,{"content-type":r?"application/json":null,"atproto-proxy":C(this.proxy)})}),a=n.status,o=Object.fromEntries(n.headers),i=o["content-type"];let c,l;i&&(i.startsWith("application/json")?c=n.json():i.startsWith("text/")&&(c=n.text()));try{l=await(c||n.arrayBuffer().then(e=>new Uint8Array(e)))}catch(d){throw new j(2,{cause:d,kind:"InvalidResponse",description:"Failed to parse response body",headers:o})}if(200===a)return{data:l,headers:o};if(A(l))throw new j(a,{kind:l.error,description:l.message,headers:o});throw new j(a,{headers:o})}}const C=e=>e?`${e.service}#${e.type}`:null,O=e=>{let t;for(const s in e){const r=e[s];if(void 0!==r)if(t??=new URLSearchParams,Array.isArray(r))for(let e=0,n=r.length;e<n;e++){const n=r[e];t.append(s,""+n)}else t.set(s,""+r)}return t?"?"+t.toString():""},q=e=>{if("object"!=typeof e||null===e)return!1;if("toJSON"in e)return!0;const t=Object.getPrototypeOf(e);return null===t||t===Object.prototype},A=e=>{if("object"!=typeof e||null===e)return!1;const t=typeof e.error,s=typeof e.message;return!("undefined"!==t&&"string"!==t||"undefined"!==s&&"string"!==s)},E=e=>e.replace(/[<"&]/g,e=>"&#"+e.charCodeAt(0)+";");var H=d('<div class="code-block svelte-ipr7k2"><pre class="svelte-ipr7k2"><code> </code></pre> <div class="actions svelte-ipr7k2"><button title="Copy" aria-label="Copy" class="action-button svelte-ipr7k2"><svg class="icon svelte-ipr7k2" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="square" stroke-width="2" d="M15 5h4v16H5V5h4m0-2h6v4H9V3Z"></path></svg></button></div></div>');function P(t,s){l(s,!0);var r=H(),n=h(r),a=h(n),o=h(a),i=p(n,2);h(i).__click=()=>{navigator.clipboard.writeText(s.code).catch(()=>alert("Failed to copy to clipboard"))},e(()=>u(o,s.code)),f(t,r),v()}y(["click"]);var R=d('<div class="guide svelte-1wxv0ke"><h4 class="guide-header svelte-1wxv0ke"> </h4> <!></div>');function S(t,s){var r=R(),n=h(r),a=h(n),o=p(n,2);g(o,()=>s.children),e(()=>u(a,s.title)),f(t,r)}var U=d('<ol class="guide-instructions svelte-mki4x9"><!></ol>');function _(e,t){var s=U(),r=h(s);g(r,()=>t.children),f(e,s)}export{P as C,S as G,$ as X,j as a,_ as b,E as e,b as h,k as o,x as s};
+1
assets/PostDisplay-CqTUAVla.js
··· 1 + import{p as e,f as s,t as a,s as t,a as i,b as r,c as l,d as n,e as p,g as d,B as o,h as c,i as h,j as u,k as m,l as f,u as v,C as b}from"./index-CD_0uzJz.js";import{X as k,s as y,a as g,h as $,o as w,G as x,b as z,C as q,e as Z}from"./GuideInstructions-CTis8QB-.js";import{s as A}from"./index-Cr8Vao8y.js";const F=/[&"<]/g,C=/[&<]/g;function M(e,s){const a=String(e??""),t=s?F:C;t.lastIndex=0;let i="",r=0;for(;t.test(a);){const e=t.lastIndex-1,s=a[e];i+=a.substring(r,e)+("&"===s?"&amp;":'"'===s?"&quot;":"&lt;"),r=e+1}return i+a.substring(r)}function N(e,s,a=!1){if("hidden"===e&&"until-found"!==s&&(a=!0),null==s||!s&&a)return"";return` ${e}${a?"":`="${M(s,!0)}"`}`}function _(e,s,a){var t=function(e,s){var a=null==e?"":""+e;return s&&(a=a?a+" "+s:s),""===a?null:a}(e,s);return t?` class="${M(t,!0)}"`:""}function B(e,s){var a=function(e){return null==e?null:String(e)}(e);return a?` style="${M(a,!0)}"`:""}function S(e,s){const{children:a}=s;e.push('<div class="bluesky-embed s-3olstj">'),a(e),e.push("</div>")}const U=e=>`https://bsky.app/profile/${e}`,T=(e,s)=>`https://bsky.app/profile/${e}/post/${s}`,I=e=>`https://bsky.app/hashtag/${e}`,R=(e,s)=>`https://bsky.app/profile/${e}/feed/${s}`;let D=0,H=0;const j=new Intl.DateTimeFormat("en-US",{dateStyle:"long",timeStyle:"short"}),P=new Intl.DateTimeFormat("en-US",{dateStyle:"medium"}),V=new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric"}),G=e=>{const s=new Date(e),a=s.getTime();if(isNaN(a))return"N/A";const t=Date.now();if(t>H){const e=new Date(t);e.setMonth(0,1),e.setHours(0,0,0),D=e.getTime(),e.setFullYear(e.getFullYear()+1,0,0),e.setHours(23,59,59,999),H=e.getTime()}return a>=D&&a<=H?V.format(s):P.format(s)},L=e=>{const s=new Date(e);return isNaN(s.getTime())?"N/A":j.format(s)},W={"!hide":{name:"Hidden by moderators",flags:1},"!warn":{name:"Content warning",flags:1},porn:{name:"Adult content",flags:0},sexual:{name:"Sexually suggestive",flags:0},"graphic-media":{name:"Graphic media",flags:0},nudity:{name:"Nudity",flags:0}},E=(e,s)=>{if(e?.length)for(let a=0,t=e.length;a<t;a++){const t=e[a],i=t.val;if(!(i in W))continue;const r=W[i];if(!(1&r.flags&&t.src===s))return r}},Y=new Intl.NumberFormat("en-US"),J=new Intl.NumberFormat("en-US",{notation:"compact"}),K=e=>e<1e3?""+e:e<1e5?Y.format(e):J.format(e),X=e=>Y.format(e),O=/^at:\/\/((?:did:[a-zA-Z0-9._:%-]+)|(?:[a-zA-Z0-9][a-zA-Z0-9-.]*))(?:\/([a-zA-Z0-9.-]+)(?:\/([a-zA-Z0-9_~.:-]{1,512}))?)?\/?(?:\?([^#\s]*))?(?:#([^\s]*))?$/,Q=e=>{const s=O.exec(e);if(!s)throw new ee(`invalid at-uri: ${e}`);return{repo:s[1],collection:s[2]??"",rkey:s[3]??"",query:s[4]??"",fragment:s[5]??""}};let ee=class extends Error{};function se(e,s){{const{embed:a}=s,t=a.external,i=(e=>{let s;if("parse"in URL)s=URL.parse(e);else try{s=new URL(e)}catch{}return!s||"https:"!==s.protocol&&"http:"!==s.protocol?null:s})(t.uri)?.host;e.push(`<a target="_blank"${N("href",i&&t.uri)} rel="noopener noreferrer nofollow" class="external-embed s-rtbqd8">`),t.thumb&&e.push(`<img loading="lazy"${N("src",t.thumb)} alt="" class="thumbnail s-rtbqd8"/>`),e.push(` <div class="meta s-rtbqd8"><p class="title s-rtbqd8">${M(t.title)}</p> <p class="description s-rtbqd8">${M(t.description)}</p> `),i&&e.push(`<div class="domain s-rtbqd8"><svg class="icon" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="m4.172 8.07 3.94 2.957.977-1.941 3.887-.978 1.15-4.6M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-6.078 4.865.973-1.946-2.869-1.928-1.89-.12-1.08 1.075 1.947 2.919h2.919Z"></path></svg> <span class="domain-name">${M(i)}</span></div>`),e.push("</div></a>")}}const ae={width:16,height:9};function te(e,s){{const{embed:a,borderless:t,standalone:i,blur:r}=s,l=a.images,n=l.length;function p(e,s){const a=l[s];e.push(`<img loading="lazy"${N("src",a.thumb)}${N("alt",a.alt)}${_("image"+(r?" is-blurred":""),"s-t3k6fc")}/>`)}if(e.push(`<div${_("image-embed"+(t?"":" is-bordered")+(i&&1===n?" is-aligned":""),"s-t3k6fc")}>`),4===n)e.push('<div class="grid s-t3k6fc"><div class="col s-t3k6fc"><div class="item wide tl s-t3k6fc">'),p(e,0),e.push('</div> <div class="item wide bl s-t3k6fc">'),p(e,2),e.push('</div></div> <div class="col s-t3k6fc"><div class="item wide tr s-t3k6fc">'),p(e,1),e.push('</div> <div class="item wide br s-t3k6fc">'),p(e,3),e.push("</div></div></div>");else if(3===n)e.push('<div class="grid s-t3k6fc"><div class="col square s-t3k6fc"><div class="item tl bl s-t3k6fc">'),p(e,0),e.push('</div></div> <div class="col square s-t3k6fc"><div class="item tr s-t3k6fc">'),p(e,1),e.push('</div> <div class="item br s-t3k6fc">'),p(e,2),e.push("</div></div></div>");else if(2===n)e.push('<div class="grid s-t3k6fc"><div class="col s-t3k6fc"><div class="item square tl bl s-t3k6fc">'),p(e,0),e.push('</div></div> <div class="col s-t3k6fc"><div class="item square tr br s-t3k6fc">'),p(e,1),e.push("</div></div></div>");else if(1===n){const d=i&&(l[0].aspectRatio||ae);e.push(`<div${_("single-item tl tr bl br"+(d?" is-standalone":""),"s-t3k6fc")}${B(d?`aspect-ratio: ${d.width}/${d.height}`:"")}>`),p(e,0),e.push(" "),d&&e.push('<div class="placeholder s-t3k6fc"></div>'),e.push("</div>")}e.push("</div>")}}function ie(e,s){{const{post:a,embed:t,borderless:i,standalone:r,blur:l}=s,n=r&&t.aspectRatio,p=a&&T(a.author.did,Q(a.uri).rkey);function d(e){e.push(`<img loading="lazy"${N("src",t.thumbnail)} alt=""${_("thumbnail"+(l?" is-blurred":""),"s-1azk58e")}/> `),n&&e.push('<div class="placeholder s-1azk58e"></div>'),e.push(' <div class="play s-1azk58e"><svg class="icon s-1azk58e" fill="none" viewBox="0 0 24 24"><path fill="currentColor" d="M22 12 5 2v20l17-10Z"></path></svg></div>')}r?(e.push(`<a target="_blank"${N("href",p)}${_("video-embed"+(i?"":" is-bordered")+(r?" is-standalone":""),"s-1azk58e")}><div class="constrainer s-1azk58e"${B(n?`aspect-ratio: ${n.width}/${n.height}`:"")}>`),d(e),e.push("</div></a>")):(e.push(`<div${_("video-embed"+(i?"":" is-bordered"),"s-1azk58e")}${B(n?`aspect-ratio: ${n.width}/${n.height}`:"")}>`),d(e),e.push("</div>"))}}const re=e=>{if(e){if("app.bsky.embed.images#view"===e.$type)return e;if("app.bsky.embed.recordWithMedia#view"===e.$type)return re(e.media)}},le=e=>{if(e){if("app.bsky.embed.video#view"===e.$type)return e;if("app.bsky.embed.recordWithMedia#view"===e.$type)return le(e.media)}};function ne(e,s){e.push(`<div class="message s-azdpbr">${M(s)}</div>`)}function pe(e,s){{const{post:a,embed:t,large:i=!1}=s;function r(e,s){!function(e,s){{const{warning:a,children:t}=s;a?(e.push(`<details class="content-hider s-q6x07m"><summary class="gate s-q6x07m"><svg class="icon s-q6x07m" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="square" stroke-width="2" d="M11 11h1v5m9-4a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"></path><path fill="currentColor" stroke="currentColor" stroke-width=".5" d="M11.5 7.25h-.25v1.5h1.5v-1.5H11.5Z"></path></svg> <span class="label s-q6x07m">${M(a.name)}</span> <span class="action s-q6x07m"></span></summary> `),t(e),e.push("</details>")):t(e)}}(e,{warning:a&&E(a.labels,a.author.did),children:e=>{"app.bsky.embed.external#view"===s.$type?se(e,{embed:s}):"app.bsky.embed.images#view"===s.$type?te(e,{embed:s,standalone:!0}):"app.bsky.embed.video#view"===s.$type?ie(e,{post:a,embed:s,standalone:!0}):ne(e,"Unsupported media embed")}})}function l(e,s){const a=s.record;if("app.bsky.embed.record#viewRecord"===a.$type)!function(e,s){{const{embed:a,large:t=!1}=s,i=a.value,r=i.text.trim(),l=a.author,n=l.displayName?.trim(),p=a.embeds?.[0],d=re(p),o=le(p),c=T(l.did,Q(a.uri).rkey),h=!!E(a.labels,l.did);e.push(`<a target="_blank"${N("href",c)} class="quote-embed s-za6fip"><div class="meta s-za6fip"><div class="avatar-wrapper s-za6fip">`),l.avatar&&e.push(`<img loading="lazy"${N("src",l.avatar)} alt="" class="avatar s-za6fip"/>`),e.push('</div> <span class="name-wrapper s-za6fip">'),n&&e.push(`<bdi class="display-name-wrapper s-za6fip"><span class="display-name s-za6fip">${M(n)}</span></bdi>`),e.push(` <span class="handle s-za6fip">@${M(l.handle)}</span></span> <span aria-hidden="true" class="dot s-za6fip">ยท</span> <time${N("datetime",i.createdAt)} class="date s-za6fip">${M(G(i.createdAt))}</time></div> `),r?(e.push('<div class="body s-za6fip">'),t||(d?(e.push('<div class="aside s-za6fip">'),te(e,{embed:d,blur:h}),e.push("</div>")):o&&(e.push('<div class="aside s-za6fip">'),ie(e,{embed:o,blur:h}),e.push("</div>"))),e.push(` <p class="text s-za6fip">${M(r)}</p></div>`)):e.push('<div class="divide s-za6fip"></div>'),e.push(" "),!t&&r||(d?te(e,{embed:d,borderless:!0,blur:h}):o&&ie(e,{embed:o,borderless:!0,blur:h})),e.push("</a>")}}(e,{embed:a,large:i});else if("app.bsky.feed.defs#generatorView"===a.$type)!function(e,s){{const{embed:a}=s,t=a.creator,i=R(t.did,Q(a.uri).rkey);e.push(`<a target="_blank"${N("href",i)} class="feed-embed s-156tlwp"><div class="main s-156tlwp"><div class="avatar-wrapper s-156tlwp">`),a.avatar?e.push(`<img loading="lazy"${N("src",a.avatar)} alt="" class="avatar s-156tlwp"/>`):e.push('<svg viewBox="0 0 32 32" class="avatar s-156tlwp"><path fill="#0070FF" d="M0 0h32v32H0z"></path><path fill="#fff" d="M22.153 22.354a9.328 9.328 0 0 0 3.837-.491 3.076 3.076 0 0 0-4.802-2.79m.965 3.281a6.128 6.128 0 0 0-.965-3.28Zm-11.342-3.28a3.077 3.077 0 0 0-4.801 2.79 9.21 9.21 0 0 0 3.835.49m.966-3.28a6.127 6.127 0 0 0-.966 3.28Zm8.265-8.997a3.076 3.076 0 1 1-6.153 0 3.076 3.076 0 0 1 6.153 0Zm6.154 3.077a2.307 2.307 0 1 1-4.615 0 2.307 2.307 0 0 1 4.615 0Zm-13.847 0a2.307 2.307 0 1 1-4.614 0 2.307 2.307 0 0 1 4.614 0Z"></path><path fill="#fff" d="M22 22c0 3.314-2.686 3.5-6 3.5s-6-.186-6-3.5a6 6 0 0 1 12 0Z"></path></svg>'),e.push(`</div> <div class="info"><p class="name s-156tlwp">${M(a.displayName)}</p> <p class="creator s-156tlwp">Feed by @${M(t.handle)}</p></div></div> <p class="description s-156tlwp">${M(a.description)}</p></a>`)}}(e,{embed:a});else if("app.bsky.graph.defs#listView"===a.$type)!function(e,s){{const{embed:a}=s,t=a.creator,i=R(t.did,Q(a.uri).rkey);e.push(`<a target="_blank"${N("href",i)} class="list-embed s-6uize5"><div class="main s-6uize5"><div class="avatar-wrapper s-6uize5">`),a.avatar?e.push(`<img loading="lazy"${N("src",a.avatar)} alt="" class="avatar s-6uize5"/>`):e.push('<svg viewBox="0 0 32 32" class="avatar s-6uize5"><path fill="#0070FF" d="M0 0h32v32H0z"></path><path fill="#fff" d="M22.153 22.354a9.328 9.328 0 0 0 3.837-.491 3.076 3.076 0 0 0-4.802-2.79m.965 3.281a6.128 6.128 0 0 0-.965-3.28Zm-11.342-3.28a3.077 3.077 0 0 0-4.801 2.79 9.21 9.21 0 0 0 3.835.49m.966-3.28a6.127 6.127 0 0 0-.966 3.28Zm8.265-8.997a3.076 3.076 0 1 1-6.153 0 3.076 3.076 0 0 1 6.153 0Zm6.154 3.077a2.307 2.307 0 1 1-4.615 0 2.307 2.307 0 0 1 4.615 0Zm-13.847 0a2.307 2.307 0 1 1-4.614 0 2.307 2.307 0 0 1 4.614 0Z"></path><path fill="#fff" d="M22 22c0 3.314-2.686 3.5-6 3.5s-6-.186-6-3.5a6 6 0 0 1 12 0Z"></path></svg>'),e.push(`</div> <div class="info"><p class="name s-6uize5">${M(a.name)}</p> <p class="creator s-6uize5">${M((e=>{switch(e){case"app.bsky.graph.defs#curatelist":return"User list";case"app.bsky.graph.defs#modlist":return"Moderation list"}return"Unknown list"})(a.purpose))} by @${M(t.handle)}</p></div></div> <p class="description s-6uize5">${M(a.description)}</p></a>`)}}(e,{embed:a});else if("app.bsky.graph.defs#starterPackViewBasic"===a.$type)!function(e,s){{const{embed:a,large:t=!1}=s,i=a.record,r=a.creator,l=r.did,n=Q(a.uri).rkey,p=((e,s)=>`https://bsky.app/starter-pack/${e}/${s}`)(l,n);if(e.push(`<a target="_blank"${N("href",p)} class="starterpack-embed s-15v965v">`),t){const s=((e,s)=>`https://ogcard.cdn.bsky.app/start/${e}/${s}`)(l,n);e.push(`<img loading="lazy"${N("src",s)} alt="" class="banner s-15v965v"/>`)}e.push(` <div class="meta s-15v965v"><div class="main s-15v965v"><svg fill="none" viewBox="0 0 24 24" class="avatar s-15v965v"><defs><linearGradient id="a" x1="0" x2="100%" y1="0" y2="0" gradientTransform="rotate(45)"><stop offset="0" stop-color="#0A7AFF"></stop><stop offset="1" stop-color="#59B9FF"></stop></linearGradient></defs><path fill="url(#a)" fill-rule="evenodd" d="M11.26 5.227 5.02 6.899c-.734.197-1.17.95-.973 1.685l1.672 6.24c.197.734.951 1.17 1.685.973l6.24-1.672a1.376 1.376 0 0 0 .973-1.685L12.945 6.2a1.375 1.375 0 0 0-1.685-.973Zm-6.566.459a2.632 2.632 0 0 0-1.86 3.223l1.672 6.24a2.632 2.632 0 0 0 3.223 1.861l6.24-1.672a2.631 2.631 0 0 0 1.861-3.223l-1.672-6.24a2.632 2.632 0 0 0-3.223-1.861l-6.24 1.672Z" clip-rule="evenodd"></path><path fill="url(#a)" fill-rule="evenodd" d="M15.138 18.411a4.606 4.606 0 1 0 0-9.211 4.606 4.606 0 0 0 0 9.211Zm0 1.257a5.862 5.862 0 1 0 0-11.724 5.862 5.862 0 0 0 0 11.724Z" clip-rule="evenodd"></path></svg> <div class="info"><p class="name s-15v965v">${M(i.name)}</p> <p class="creator s-15v965v">Starter pack by @${M(r.handle)}</p></div></div> <p class="description s-15v965v">${M(i.description)}</p></div></a>`)}}(e,{embed:a,large:i});else{const s=(e=>{switch(e){case"app.bsky.feed.post":return"post";case"app.bsky.feed.generator":return"feed";case"app.bsky.graph.list":return"list";case"app.bsky.graph.starterpack":return"starter pack";case"app.bsky.labeler.service":return"labeler"}return null})(Q(a.uri).collection);ne(e,s&&("app.bsky.embed.record#viewNotFound"===a.$type||"app.bsky.embed.record#viewBlocked"===a.$type||"app.bsky.embed.record#viewDetached"===a.$type)?`This ${s} is unavailable`:"Unsupported record embed")}}e.push('<div class="embeds s-azdpbr">'),"app.bsky.embed.recordWithMedia#view"===t.$type?(r(e,t.media),e.push(" "),l(e,t.record)):"app.bsky.embed.record#view"===t.$type?l(e,t):r(e,t),e.push("</div>")}}const de=e=>e?.find(e=>"app.bsky.richtext.facet#link"===e.$type||"app.bsky.richtext.facet#mention"===e.$type||"app.bsky.richtext.facet#tag"===e.$type);function oe(e,s){{const{text:a,facets:t,large:i}=s;e.push(`<p${_("rich-text"+(i?" is-large":" is-small"),"s-1lecfnd")}>`);const r=A(a,t);for(let s=0,l=r.length;s<l;s++){let a=r[s];const t=de(a.features);t?"app.bsky.richtext.facet#link"===t.$type?e.push(`<a target="_blank"${N("href",t.uri)} rel="noopener nofollow" class="link s-1lecfnd">${M(a.text)}</a>`):"app.bsky.richtext.facet#mention"===t.$type?e.push(`<a target="_blank"${N("href",U(t.did))} class="mention s-1lecfnd">${M(a.text)}</a>`):"app.bsky.richtext.facet#tag"===t.$type&&e.push(`<a target="_blank"${N("href",I(t.tag))} class="hashtag s-1lecfnd">${M(a.text)}</a>`):e.push(`${M(a.text)}`)}e.push("</p>")}}function ce(e,s){{const{post:a,parent:t,prev:i=!1}=s,r=a.author,l=U(r.did),n=r.displayName?.trim(),p=a.record,d=T(r.did,Q(a.uri).rkey),o=a.replyCount||0,c=a.likeCount||0,h=(a.repostCount||0)+(a.quoteCount||0),u=!!E(r.labels,r.did);if(e.push(`<div class="highlighted-post s-hik11q"><div class="meta s-hik11q"><a${N("href",l)} target="_blank" class="avatar-wrapper s-hik11q">`),r.avatar&&e.push(`<img loading="lazy"${N("src",r.avatar)} alt=""${_("avatar"+(u?" is-blurred":""),"s-hik11q")}/>`),e.push(`</a> <a${N("href",l)} target="_blank" class="name-wrapper s-hik11q">`),n&&e.push(`<bdi class="display-name-wrapper s-hik11q"><span class="display-name s-hik11q">${M(n)}</span></bdi>`),e.push(` <span class="handle s-hik11q">@${M(r.handle)}</span></a> `),i||e.push('<svg class="logo s-hik11q" fill="none" viewBox="0 0 320 286"><path fill="#0A7AFF" d="M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z"></path></svg>'),e.push("</div> "),!i&&p.reply){if(e.push('<p class="context s-hik11q">'),t){const s=t.author;e.push(`Replying to <a target="_blank"${N("href",U(s.did))} dir="auto" class="s-hik11q">${M(s.displayName?.trim()||`@${s.handle}`)}</a>`)}else e.push("Replying to an unknown post");e.push("</p>")}e.push(" "),oe(e,{text:p.text,facets:p.facets,large:!0}),e.push(" "),a.embed&&pe(e,{post:a,embed:a.embed,large:!0}),e.push(` <time${N("datetime",p.createdAt)} class="date s-hik11q">${M(L(p.createdAt))}</time> <div class="stats s-hik11q"><span class="stat s-hik11q"${N("title",1===c?`${X(c)} like`:`${X(c)} likes`)}><svg class="icon" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-width="2" d="M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z"></path></svg> <span>${M(K(c))}</span></span> <span class="stat s-hik11q"${N("title",1===h?`${X(h)} repost`:`${X(h)} reposts`)}><svg class="icon" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="square" stroke-width="2" d="m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15"></path></svg> <span>${M(K(h))}</span></span> <div class="gap s-hik11q"></div> <a${N("href",d)} target="_blank" class="permalink s-hik11q"><span>${M(o?1===o?`Read ${K(o)} reply on Bluesky`:`Read ${K(o)} replies on Bluesky`:"View on Bluesky")}</span></a></div></div>`)}}function he(e,s){{const{post:a,parent:t,prev:i}=s,r=a.author,l=U(r.did),n=r.displayName?.trim(),p=a.record,d=T(r.did,Q(a.uri).rkey),o=!!E(r.labels,r.did);if(e.push('<div class="post s-12mzi62">'),i||e.push('<svg class="logo s-12mzi62" fill="none" viewBox="0 0 320 286"><path fill="#0A7AFF" d="M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z"></path></svg>'),e.push(` <div class="aside s-12mzi62"><a target="_blank"${N("href",l)} class="avatar-wrapper s-12mzi62">`),r.avatar&&e.push(`<img loading="lazy"${N("src",r.avatar)} alt=""${_("avatar"+(o?" is-blurred":""),"s-12mzi62")}/>`),e.push(`</a> <div class="line s-12mzi62"></div></div> <div class="main s-12mzi62"><div class="meta s-12mzi62"><a${N("href",l)} target="_blank" class="name-wrapper s-12mzi62">`),n&&e.push(`<bdi class="display-name-wrapper s-12mzi62"><span class="display-name s-12mzi62">${M(n)}</span></bdi>`),e.push(` <span class="handle s-12mzi62">@${M(r.handle)}</span></a> <span aria-hidden="true" class="dot s-12mzi62">ยท</span> <a target="_blank"${N("href",d)}${N("title",L(p.createdAt))} class="date s-12mzi62"><time${N("datetime",p.createdAt)}>${M(G(p.createdAt))}</time></a></div> `),!i&&p.reply){if(e.push('<p class="context s-12mzi62">'),t){const s=t.author;e.push(`Replying to <a target="_blank"${N("href",U(s.did))} dir="auto" class="s-12mzi62">${M(s.displayName?.trim()||`@${s.handle}`)}</a>`)}else e.push("Replying to an unknown post");e.push("</p>")}e.push(" "),oe(e,{text:p.text,facets:p.facets}),e.push(" "),a.embed&&pe(e,{post:a,embed:a.embed}),e.push("</div></div>")}}function ue(e,s){S(e,{children:e=>{e.push(`<div class="message s-1q9cbx0">${M(s)}</div>`)}})}function me(e,s){{const{thread:a,contextless:t,allowUnauthenticated:i}=s,r=!i&&null!==a&&"app.bsky.feed.defs#threadViewPost"===a.$type&&a.post.author.labels?.some(e=>"!no-unauthenticated"===e.val);if(null===a)ue(e,"The post can't be found, it may have been deleted.");else if(r)ue(e,"The author has requested for their posts to not be displayed on external sites.");else{const s=((e,s,a)=>{const t=[];let i=0,r=s?1:2,l=e;for(;l&&"app.bsky.feed.defs#notFoundPost"!==l.$type&&"app.bsky.feed.defs#blockedPost"!==l.$type;){const e=l.post;if(0!==i&&(t[i-1].parent=e),++i>r)break;const s=e.author;if(!a&&s.labels?.some(e=>"!no-unauthenticated"===e.val))break;t.push({post:e,parent:null}),l=l.parent}return t.reverse()})(a,t,i);S(e,{children:e=>{const a=s;for(let t=0,i=a.length;t<i;t++){let{post:i,parent:r}=a[t];const l=0!==t;t===s.length-1?ce(e,{post:i,parent:r,prev:l}):he(e,{post:i,parent:r,prev:l})}}})}}}const fe=new Intl.DateTimeFormat("en-US",{dateStyle:"long",timeStyle:"short"}),ve=/^at:\/\/((?:did:[a-zA-Z0-9._:%-]+)|(?:[a-zA-Z0-9][a-zA-Z0-9-.]*))(?:\/([a-zA-Z0-9.-]+)(?:\/([a-zA-Z0-9_~.:-]{1,512}))?)?\/?(?:\?([^#\s]*))?(?:#([^\s]*))?$/;class be extends Error{}var ke=s("<bluesky-post><!></bluesky-post>",2);function ye(s,n){e(n,!0);var p=ke();a(()=>t(p,"src",n.data.thread?.post.uri));var d=l(p);$(d,()=>function(e,s={}){let a="";return me({push(e){a+=e}},s.props??{}),{body:a}}(0,{props:n.data}).body),i(s,p),r()}var ge=s('Doing server-side rendering? Check out examples for <a href="https://github.com/mary-ext/bluesky-embed-astro">Astro</a> and <a href="https://github.com/mary-ext/bluesky-embed-sveltekit">SvelteKit</a>.',1),$e=s("<li><p>Insert the following scripts and stylesheets to the <code>&lt;head&gt;</code> of your website.</p> <!></li> <li><p>Insert the following markup in wherever you want the post to be.</p> <!></li>",1),we=s("<!> <!>",1),xe=s("<!> <!>",1);function ze(s,t){let $;e(t,!0);const A=v(()=>{$?.abort(),$=new AbortController;const e=$.signal;return(async e=>{const s=new k({handler:y({service:e.serviceUri??"https://public.api.bsky.app"})}),a=e.contextless??!1,{data:t}=await s.get("app.bsky.feed.getPostThread",{signal:e.signal,params:{uri:e.uri,parentHeight:a?1:2,depth:0}}).catch(e=>e instanceof g&&"NotFound"===e.kind?{data:null}:Promise.reject(e));return{thread:"app.bsky.feed.defs#threadViewPost"===t?.thread.$type?t.thread:null,contextless:a,allowUnauthenticated:e.allowUnauthenticated??!1}})({uri:`at://${t.matched.author}/app.bsky.feed.post/${t.matched.rkey}`,signal:e})});w(()=>{$?.abort()});const F="https://cdn.jsdelivr.net/npm/bluesky-post-embed@^1.0.0",C=()=>`\x3c!-- Core web component and styling --\x3e\n<script type="module" src="${F}/+esm"><\/script>\n<link rel="stylesheet" href="${F}/dist/core.min.css">\n\n\x3c!-- Built-in themes --\x3e\n<link rel="stylesheet" href="${F}/themes/light.min.css" media="(prefers-color-scheme: light)">\n<link rel="stylesheet" href="${F}/themes/dim.min.css" media="(prefers-color-scheme: dark)">\n\n\x3c!-- Fallback/placeholder elements if JS script is taking a while to load or is failing --\x3e\n<style>\n .bluesky-post-fallback {\n margin: 16px 0;\n border-left: 3px solid var(--divider);\n padding: 4px 8px;\n white-space: pre-wrap;\n overflow-wrap: break-word;\n }\n .bluesky-post-fallback p {\n margin: 0 0 8px 0;\n }\n</style>\n`,M=e=>{const s=e.author,a=e.record;return`<bluesky-post src="${Z(e.uri)}">\n <blockquote class="bluesky-post-fallback">\n <p dir="auto">${Z(a.text)}</p>\n โ€” ${s.displayName?.trim()?`${Z(s.displayName)} (@${Z(s.handle)})`:`@${Z(s.handle)}`}\n <a href="${Z(((e,s)=>`https://bsky.app/profile/${e}/post/${s}`)(s.did,(e=>{const s=ve.exec(e);if(!s)throw new be(`invalid at-uri: ${e}`);return{repo:s[1],collection:s[2]??"",rkey:s[3]??"",query:s[4]??"",fragment:s[5]??""}})(e.uri).rkey))}">${(e=>{const s=new Date(e);return isNaN(s.getTime())?"N/A":fe.format(s)})(e.indexedAt)}</a>\n </blockquote>\n</bluesky-post>\n`};var N=n(),_=p(N);d(_,()=>u(A),e=>{b(e)},(e,s)=>{var a=xe(),t=p(a);ye(t,{get data(){return u(s)}});var r=m(t,2),n=e=>{x(e,{title:"How do I embed this to my website?",children:(e,a)=>{var t=we(),r=p(t);o(r,{type:"inform",children:(e,s)=>{var a=ge();i(e,a)}});var n=m(r,2);z(n,{children:(e,a)=>{var t=$e(),r=p(t),n=m(l(r),2);{let e=v(C);q(n,{get code(){return u(e)}})}var d=m(r,2),o=m(l(d),2);{let e=v(()=>M(u(s).thread.post));q(o,{get code(){return u(e)}})}i(e,t)}}),i(e,t)}})};f(r,e=>{u(s).thread&&e(n)}),i(e,a)},(e,s)=>{o(e,{type:"alert",children:(e,t)=>{var r=c();a(()=>h(r,""+u(s))),i(e,r)}})}),i(s,N),r()}export{ze as default};
+1
assets/PostDisplay-yMSDBkol.css
··· 1 + .bluesky-embed.s-3olstj{position:relative;box-sizing:border-box;margin:0 auto;border:1px solid var(--divider);border-radius:8px;background:var(--background-primary);min-width:250px;max-width:550px;overflow:hidden;color:var(--text-primary);font-weight:400;font-size:calc(var(--font-size) * .875);line-height:calc(var(--font-size) * 1.25);font-family:var(--font-family);:where(*),:where(*:before),:where(*:after){box-sizing:border-box;margin:0;padding:0}:where(a){color:inherit;text-decoration:none}:where(.icon){flex-shrink:0;width:1em;height:1em}}.gate.s-q6x07m{display:flex;align-items:center;gap:12px;cursor:pointer;border:1px solid var(--divider);border-radius:6px;padding:0 12px;height:44px;.content-hider[open]:where(.s-q6x07m) &{margin-bottom:12px}&:hover{border-color:var(--divider-hover)}}.icon.s-q6x07m{width:18px;height:18px;color:var(--text-secondary)}.label.s-q6x07m{flex-grow:1;overflow:hidden;font-weight:500;user-select:none;text-overflow:ellipsis}.action.s-q6x07m{color:var(--text-link);font-weight:500;font-size:calc(var(--font-size) * .8125);line-height:calc(var(--font-size) * 1.25);&:before{content:"Show"}.content-hider[open]:where(.s-q6x07m) &:before{content:"Hide"}}.external-embed.s-rtbqd8{display:block;border:1px solid var(--divider);border-radius:6px;overflow:hidden;&:hover{border-color:var(--divider-hover)}}.thumbnail.s-rtbqd8{display:block;border-bottom:1px solid var(--divider);background:#000;aspect-ratio:1.91;width:100%;.external-embed:where(.s-rtbqd8):hover &{border-color:var(--divider-hover)}}.meta.s-rtbqd8{padding:12px}.title.s-rtbqd8{display:-webkit-box;overflow:hidden;font-weight:700;white-space:pre-wrap;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow-wrap:break-word;&:empty{display:none}}.description.s-rtbqd8{display:-webkit-box;overflow:hidden;color:var(--text-secondary);font-size:calc(var(--font-size) * .8125);white-space:pre-wrap;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow-wrap:break-word;&:empty{display:none}}.domain.s-rtbqd8{display:flex;align-items:center;gap:6px;margin:6px 0 0;color:var(--text-secondary);font-weight:500;font-size:calc(var(--font-size) * .75)}.feed-embed.s-156tlwp{display:flex;flex-direction:column;gap:12px;border:1px solid var(--divider);border-radius:6px;padding:12px;&:hover{border-color:var(--divider-hover)}}.main.s-156tlwp{display:flex;gap:12px}.avatar-wrapper.s-156tlwp{margin:2px 0 0;border-radius:6px;background:var(--background-secondary);width:36px;height:36px;overflow:hidden}.avatar.s-156tlwp{width:100%;height:100%;object-fit:cover}.name.s-156tlwp{font-weight:700}.creator.s-156tlwp{color:var(--text-secondary);font-size:calc(var(--font-size) * .8125)}.description.s-156tlwp{display:-webkit-box;overflow:hidden;font-size:calc(var(--font-size) * .8125);white-space:pre-wrap;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow-wrap:break-word;&:empty{display:none}}.is-aligned.s-t3k6fc{align-self:baseline;max-width:100%}.grid.s-t3k6fc{display:flex;gap:2px}.col.s-t3k6fc{display:flex;flex:1;flex-direction:column;gap:2px}.square.s-t3k6fc{aspect-ratio:1}.wide.s-t3k6fc{aspect-ratio:1.5}.item.s-t3k6fc{position:relative;flex-grow:1;flex-shrink:0;overflow:hidden}.is-bordered.s-t3k6fc{.tl:where(.s-t3k6fc),.tr:where(.s-t3k6fc),.bl:where(.s-t3k6fc),.br:where(.s-t3k6fc){border:1px solid var(--divider)}.tl:where(.s-t3k6fc){border-top-left-radius:6px}.tr:where(.s-t3k6fc){border-top-right-radius:6px}.bl:where(.s-t3k6fc){border-bottom-left-radius:6px}.br:where(.s-t3k6fc){border-bottom-right-radius:6px}}.single-item.s-t3k6fc{position:relative;aspect-ratio:16 / 9;overflow:hidden;.image:where(.s-t3k6fc){object-fit:contain}}.is-standalone.s-t3k6fc{min-width:64px;max-width:100%;min-height:64px;max-height:320px}.image.s-t3k6fc{position:absolute;inset:0;background:#000;width:100%;height:100%;object-fit:cover;font-size:0px}.is-blurred.s-t3k6fc{scale:125%;filter:blur(24px)}.placeholder.s-t3k6fc{width:100vw;height:100vh}.list-embed.s-6uize5{display:flex;flex-direction:column;gap:12px;border:1px solid var(--divider);border-radius:6px;padding:12px;&:hover{border-color:var(--divider-hover)}}.main.s-6uize5{display:flex;gap:12px}.avatar-wrapper.s-6uize5{margin:2px 0 0;border-radius:6px;background:var(--background-secondary);width:36px;height:36px;overflow:hidden}.avatar.s-6uize5{width:100%;height:100%;object-fit:cover}.name.s-6uize5{font-weight:700}.creator.s-6uize5{color:var(--text-secondary);font-size:calc(var(--font-size) * .8125)}.description.s-6uize5{display:-webkit-box;overflow:hidden;font-size:calc(var(--font-size) * .8125);white-space:pre-wrap;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow-wrap:break-word;&:empty{display:none}}.video-embed.s-1azk58e{display:block;position:relative;background:#000;aspect-ratio:16 / 9;overflow:hidden}.is-bordered.s-1azk58e{border:1px solid var(--divider);border-radius:6px}.is-standalone.s-1azk58e{align-self:baseline;aspect-ratio:auto;max-width:100%}.constrainer.s-1azk58e{min-width:64px;max-width:100%;min-height:64px;max-height:320px}.thumbnail.s-1azk58e{width:100%;height:100%;object-fit:contain}.is-blurred.s-1azk58e{scale:125%;filter:blur(24px)}.placeholder.s-1azk58e{width:100vw;height:100vh}.play.s-1azk58e{display:grid;position:absolute;top:50%;left:50%;place-items:center;translate:-50% -50%;border-radius:50%;background:#40404099;aspect-ratio:1 / 1;height:40%;max-height:48px;color:#fff;font-size:20px;.icon:where(.s-1azk58e){width:40%;height:40%}.is-standalone:where(.s-1azk58e) &:hover{background:#404040cc}}.quote-embed.s-za6fip{display:block;border:1px solid var(--divider);border-radius:6px;overflow:hidden;&:hover{border-color:var(--divider-hover)}}.meta.s-za6fip{display:flex;padding:12px 12px 0;color:var(--text-secondary);.avatar-wrapper:where(.s-za6fip){flex-shrink:0;margin:0 8px 0 0;border-radius:9999px;background:var(--background-secondary);width:20px;height:20px;overflow:hidden}.avatar:where(.s-za6fip){width:100%;height:100%}.name-wrapper:where(.s-za6fip){display:flex;gap:4px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.display-name-wrapper:where(.s-za6fip){overflow:hidden;text-overflow:ellipsis}.display-name:where(.s-za6fip){color:var(--text-primary);font-weight:700}.handle:where(.s-za6fip){display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dot:where(.s-za6fip){flex-shrink:0;margin:0 6px}.date:where(.s-za6fip){white-space:nowrap}}.body.s-za6fip{display:flex;align-items:flex-start}.aside.s-za6fip{flex-grow:1;flex-basis:0;margin:8px 0 12px 12px;max-width:20%}.text.s-za6fip{display:-webkit-box;margin:8px 12px 12px;overflow:hidden;-webkit-box-orient:vertical;-webkit-line-clamp:6;line-clamp:6;flex-grow:4;flex-basis:0px;min-width:0px;white-space:pre-wrap;overflow-wrap:break-word}.divide.s-za6fip{padding:6px 0}.starterpack-embed.s-15v965v{display:block;border:1px solid var(--divider);border-radius:6px;overflow:hidden;&:hover{border-color:var(--divider-hover)}}.banner.s-15v965v{display:block;aspect-ratio:1.91;width:100%}.meta.s-15v965v{display:flex;flex-direction:column;gap:12px;padding:12px}.main.s-15v965v{display:flex;gap:12px}.avatar.s-15v965v{margin:2px;width:36px;height:36px}.name.s-15v965v{font-weight:700}.creator.s-15v965v{color:var(--text-secondary);font-size:calc(var(--font-size) * .8125)}.description.s-15v965v{display:-webkit-box;overflow:hidden;font-size:calc(var(--font-size) * .8125);white-space:pre-wrap;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow-wrap:break-word;&:empty{display:none}}.embeds.s-azdpbr{display:flex;flex-direction:column;gap:12px;margin:12px 0 0}.message.s-azdpbr{border:1px solid var(--divider);border-radius:6px;padding:12px;color:var(--text-secondary)}.rich-text.s-1lecfnd{overflow:hidden;white-space:pre-wrap;overflow-wrap:break-word;&:empty{display:none}}.is-large.s-1lecfnd{font-size:calc(var(--font-size) * 1);line-height:calc(var(--font-size) * 1.5)}.link.s-1lecfnd,.mention.s-1lecfnd,.hashtag.s-1lecfnd{color:var(--text-link);&:hover{text-decoration:underline}}.highlighted-post.s-hik11q{padding:16px}.meta.s-hik11q{display:flex;align-items:center;gap:12px;margin:0 0 12px;color:var(--text-secondary)}.avatar-wrapper.s-hik11q{display:block;flex-shrink:0;border-radius:9999px;background:var(--background-secondary);width:40px;height:40px;overflow:hidden;&:hover{filter:brightness(.85)}}.avatar.s-hik11q{width:100%;height:100%;object-fit:cover}.is-blurred.s-hik11q{scale:125%;filter:blur(4px)}.name-wrapper.s-hik11q{display:block;flex-grow:1;max-width:100%;overflow:hidden;color:inherit;text-overflow:ellipsis;white-space:nowrap}.display-name-wrapper.s-hik11q{overflow:hidden;text-overflow:ellipsis;.name-wrapper:where(.s-hik11q):hover &{text-decoration:underline}}.display-name.s-hik11q{color:var(--text-primary);font-weight:700}.handle.s-hik11q{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.logo.s-hik11q{width:32px;height:32px}.context.s-hik11q{overflow:hidden;color:var(--text-secondary);font-size:calc(var(--font-size) * .8125);text-overflow:ellipsis;white-space:nowrap;a:where(.s-hik11q){color:inherit;font-weight:500;&:hover{text-decoration:underline}}}.date.s-hik11q{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:12px 0 0;border-bottom:1px solid var(--divider);padding:0 0 12px;color:var(--text-secondary)}.stats.s-hik11q{display:flex;flex-wrap:wrap;align-items:center;gap:8px 16px;margin:0 0 -16px;padding:12px 0;color:var(--text-secondary);.gap:where(.s-hik11q){flex:1 1 auto}.permalink:where(.s-hik11q){display:flex;align-items:center;gap:4px;color:var(--text-link);font-weight:700;&:hover{text-decoration:underline}}}.stat.s-hik11q{display:flex;align-items:center;gap:8px;font-weight:500}.post.s-12mzi62{display:flex;position:relative;gap:12px;padding:12px 16px 0}.logo.s-12mzi62{position:absolute;top:12px;right:12px;width:24px;height:24px}.aside.s-12mzi62{flex-shrink:0}.avatar-wrapper.s-12mzi62{display:block;border-radius:9999px;background:var(--background-secondary);width:40px;height:40px;overflow:hidden;&:hover{filter:brightness(.85)}}.avatar.s-12mzi62{width:100%;height:100%;object-fit:cover}.is-blurred.s-12mzi62{scale:125%;filter:blur(4px)}.line.s-12mzi62{position:absolute;top:56px;bottom:-12px;left:35px;border-left:2px solid var(--divider)}.main.s-12mzi62{display:flex;flex-grow:1;flex-direction:column;min-width:0px}.meta.s-12mzi62{display:flex;align-items:center;margin:0 0 2px;padding:0 32px 0 0;color:var(--text-secondary);.name-wrapper:where(.s-12mzi62){display:flex;gap:4px;max-width:100%;overflow:hidden;color:inherit;text-decoration:none;text-overflow:ellipsis;white-space:nowrap}.display-name-wrapper:where(.s-12mzi62){overflow:hidden;text-overflow:ellipsis;.name-wrapper:where(.s-12mzi62):hover &{text-decoration:underline}}.display-name:where(.s-12mzi62){color:var(--text-primary);font-weight:700}.handle:where(.s-12mzi62){display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dot:where(.s-12mzi62){flex-shrink:0;margin:0 6px}.date:where(.s-12mzi62){color:inherit;text-decoration:none;white-space:nowrap;&:hover{text-decoration:underline}}}.context.s-12mzi62{overflow:hidden;color:var(--text-secondary);font-size:calc(var(--font-size) * .8125);text-overflow:ellipsis;white-space:nowrap;a:where(.s-12mzi62){color:inherit;font-weight:500;&:hover{text-decoration:underline}}}.message.s-1q9cbx0{margin:0 auto;padding:32px 16px;max-width:380px;color:var(--text-secondary);text-align:center}
+1
assets/ProfileCardDisplay-BpCMWdM3.js
··· 1 + import{p as e,f as s,t,s as a,c as n,a as r,b as l,d as o,e as i,g as c,B as p,h as d,i as u,j as f,k as h,l as m,u as b,C as g}from"./index-CD_0uzJz.js";import{X as w,s as y,a as v,h as $,o as k,G as x,b as q,C,e as F}from"./GuideInstructions-CTis8QB-.js";const I=/^[@๏ผ ]([a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*(?:\.[a-zA-Z]{2,}))($|\s|\p{P})/u,N=/^(?:#(?!\ufe0f|\u20e3)|๏ผƒ)([\p{N}]*[\p{L}\p{M}\p{Pc}][\p{L}\p{M}\p{Pc}\p{N}]*)($|\s|\p{P})/u,A=/^:([\w-]+):/,P=/^https?:\/\/[\S]+/,B=/(?:(?<!\(.*)\))?[.,;]*$/,U=/^\[((?:\[(?:\\.|[^\[\]\\])*\]|\\.|[^\[\]\\])*?)\]\((.*?)\)/,_=/^\\([@๏ผ #:\\\[])/,j=/^.+?(?:(?=$|[:\\\[]|https?:\/\/)|(?<=\s|[(){}\/\\\[\]\-|:;'".,=+])(?=[@๏ผ #๏ผƒ]))/s,z=e=>{const s=I.exec(e);if(s&&"@"!==s[2]){const e=s[2].length;return{type:"mention",raw:e>0?s[0].slice(0,-e):s[0],handle:s[1]}}},S=e=>{const s=N.exec(e);if(s&&"#"!==s[2]){const e=s[2].length;return{type:"topic",raw:e>0?s[0].slice(0,-e):s[0],name:s[1]}}},M=e=>{const s=A.exec(e);if(s)return{type:"emote",raw:s[0],name:s[1]}},Z=e=>{const s=P.exec(e);if(s){const e=s[0].replace(B,"");return{type:"autolink",raw:e,url:e}}},G=e=>{const s=U.exec(e);if(s)return{type:"link",raw:s[0],text:s[1],url:s[2]}},H=e=>{const s=_.exec(e);if(s)return{type:"escape",raw:s[0],escaped:s[1]}},L=e=>{const s=j.exec(e);if(s)return{type:"text",raw:s[0],text:s[0]}},T=/[&"<]/g,E=/[&<]/g;function R(e,s){const t=String(e??""),a=s?T:E;a.lastIndex=0;let n="",r=0;for(;a.test(t);){const e=a.lastIndex-1,s=t[e];n+=t.substring(r,e)+("&"===s?"&amp;":'"'===s?"&quot;":"&lt;"),r=e+1}return n+t.substring(r)}function X(e,s,t=!1){if("hidden"===e&&"until-found"!==s&&(t=!0),null==s||!s&&t)return"";return` ${e}${t?"":`="${R(s,!0)}"`}`}function D(e,s,t){var a=function(e,s){var t=null==e?"":""+e;return""===(t=t?t+" "+s:s)?null:t}(e,s);return a?` class="${R(a,!0)}"`:""}function J(e,s){const{children:t}=s;e.push('<div class="bluesky-embed s-dgn7w7">'),t(e),e.push("</div>")}const K=e=>`https://bsky.app/profile/${e}`,O=e=>`https://bsky.app/hashtag/${e}`,Q={"!hide":{name:"Hidden by moderators",flags:1},"!warn":{name:"Content warning",flags:1},porn:{name:"Adult content",flags:0},sexual:{name:"Sexually suggestive",flags:0},"graphic-media":{name:"Graphic media",flags:0},nudity:{name:"Nudity",flags:0}},V=new Intl.NumberFormat("en-US"),W=new Intl.NumberFormat("en-US",{notation:"compact"}),Y=e=>e<1e3?""+e:e<1e5?V.format(e):W.format(e),ee=/^https?:\/\//;function se(e,s){{const{text:t}=s;e.push('<p class="rich-text is-small s-1ea7h2m">');const a=(e=>{const s=[];let t,a;for(;e;)if(t=a,a=H(e)||Z(e)||z(e)||S(e)||M(e)||G(e))e=e.slice(a.raw.length),s.push(a);else if(a=L(e))e=e.slice(a.raw.length),t&&"text"===t.type?(t.raw+=a.raw,t.text+=a.text,a=t):s.push(a);else if(e)throw new Error("infinite loop encountered");return s})(t);for(let s=0,n=a.length;s<n;s++){let t=a[s];"autolink"===t.type?e.push(`<a target="_blank"${X("href",t.url)} rel="noopener nofollow" class="link s-1ea7h2m">${R(t.raw.replace(ee,""))}</a>`):"mention"===t.type?e.push(`<a target="_blank"${X("href",K(t.handle))} class="mention s-1ea7h2m">${R(t.raw)}</a>`):"topic"===t.type?e.push(`<a target="_blank"${X("href",O(t.name))} class="hashtag s-1ea7h2m">${R(t.raw)}</a>`):e.push(`${R(t.raw)}`)}e.push("</p>")}}function te(e,s){{const{profile:t}=s,a=K(t.did),n=((e,s)=>{if(e?.length)for(let t=0,a=e.length;t<a;t++){const a=e[t],n=a.val;if(!(n in Q))continue;const r=Q[n];if(!(1&r.flags&&a.src===s))return r}})(t.labels,t.did);e.push('<div class="profile-card has-banner s-2b3fq6"><div class="banner-wrapper s-2b3fq6">'),t.banner&&e.push(`<img loading="lazy"${X("src",t.banner)} alt=""${D("banner"+(n?" is-blurred":""),"s-2b3fq6")}/>`),e.push(`</div> <div class="contents s-2b3fq6"><div class="header s-2b3fq6"><a${X("href",a)} target="_blank" class="avatar-wrapper s-2b3fq6">`),t.avatar&&e.push(`<img loading="lazy"${X("src",t.avatar)} alt=""${D("avatar"+(n?" is-blurred":""),"s-2b3fq6")}/>`),e.push(`</a> <div class="actions s-2b3fq6"><a${X("href",a)} target="_blank" class="follow-button s-2b3fq6"><svg class="icon s-2b3fq6" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="square" stroke-width="2" d="M12 4v8m0 0v8m0-8H4m8 0h8"></path></svg> <span>Follow</span></a> <svg class="logo s-2b3fq6" fill="none" viewBox="0 0 320 286"><path fill="#0A7AFF" d="M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z"></path></svg></div></div> <div class="name-wrapper"><p dir="auto" class="display-name s-2b3fq6">${R(t.displayName?.trim()||t.handle.slice(0,64))}</p> <p class="handle s-2b3fq6">@${R(t.handle)}</p></div> <div class="stats s-2b3fq6"><span class="stat-entry s-2b3fq6"><span class="stat-count s-2b3fq6">${R(Y(t.followersCount||0))}</span> <span>${R(1===t.followersCount?"Follower":"Followers")}</span></span> <span class="stat-entry s-2b3fq6"><span class="stat-count s-2b3fq6">${R(Y(t.followsCount||0))}</span> <span>Following</span></span></div> `),t.description?.trim()&&se(e,{text:t.description}),e.push("</div></div>")}}function ae(e,s){J(e,{children:e=>{e.push(`<div class="message s-ibmh3w">${R(s)}</div>`)}})}function ne(e,s){{const{profile:t,allowUnauthenticated:a}=s,n=!a&&t?.labels?.some(e=>"!no-unauthenticated"===e.val);null===t?ae(e,"The profile can't be found, it may have been deleted."):n?ae(e,"The user has requested for their profile to not be displayed on external sites."):J(e,{children:e=>{te(e,{profile:t})}})}}var re=s("<bluesky-profile-card><!></bluesky-profile-card>",2);function le(s,o){e(o,!0);var i=re();t(()=>a(i,"actor",o.data.profile?.did));var c=n(i);$(c,()=>function(e,s={}){let t="";return ne({push(e){t+=e}},s.props??{}),{body:t}}(0,{props:o.data}).body),r(s,i),l()}var oe=s("<li><p>Insert the following scripts and stylesheets to the <code>&lt;head&gt;</code> of your website.</p> <!></li> <li><p>Insert the following markup in wherever you want the profile feed to be.</p> <!></li>",1),ie=s("<!> <!>",1);function ce(s,a){let $;e(a,!0);const I=b(()=>{$?.abort(),$=new AbortController;const e=$.signal;return(async e=>{const s=e.actor,t=e.allowUnauthenticated??!1,a=new w({handler:y({service:e.serviceUri??"https://public.api.bsky.app"})}),{data:n}=await a.get("app.bsky.actor.getProfile",{signal:e.signal,params:{actor:s}}).catch(e=>e instanceof v&&"InvalidRequest"===e.kind&&"Profile not found"===e.description?{data:null}:Promise.reject(e));return{profile:n,allowUnauthenticated:t}})({actor:a.matched.actor,signal:e})});k(()=>{$?.abort()});const N=()=>{const e="https://cdn.jsdelivr.net/npm/bluesky-profile-card-embed@^1.0.0";return`\x3c!-- Core web component and styling --\x3e\n<script type="module" src="${e}/+esm"><\/script>\n<link rel="stylesheet" href="${e}/dist/core.min.css">\n\n\x3c!-- Built-in themes --\x3e\n<link rel="stylesheet" href="${e}/themes/light.min.css" media="(prefers-color-scheme: light)">\n<link rel="stylesheet" href="${e}/themes/dim.min.css" media="(prefers-color-scheme: dark)">\n`};var A=o(),P=i(A);c(P,()=>f(I),e=>{g(e)},(e,s)=>{var t=ie(),a=i(t);le(a,{get data(){return f(s)}});var l=h(a,2),o=e=>{x(e,{title:"How do I embed this to my website?",children:(e,t)=>{q(e,{children:(e,t)=>{var a=oe(),l=i(a),o=h(n(l),2);{let e=b(N);C(o,{get code(){return f(e)}})}var c=h(l,2),p=h(n(c),2);{let e=b(()=>(e=>{const s=`https://bsky.app/profile/${e.did}`;return`<bluesky-profile-card actor="${F(e.did)}">\n <a target="_blank" href="${F(s)}" class="bluesky-profile-card-fallback">\n ${e.displayName?.trim()?`Follow ${F(e.displayName)} (@${F(e.handle)}) on Bluesky`:`Follow @${F(e.handle)} on Bluesky`}\n </a>\n</bluesky-profile-card>\n`})(f(s).profile));C(p,{get code(){return f(e)}})}r(e,a)}})}})};m(l,e=>{f(s).profile&&e(o)}),r(e,t)},(e,s)=>{p(e,{type:"alert",children:(e,a)=>{var n=d();t(()=>u(n,""+f(s))),r(e,n)}})}),r(s,A),l()}export{ce as default};
+1
assets/ProfileCardDisplay-D4FwjqsR.css
··· 1 + .bluesky-embed.s-dgn7w7{position:relative;box-sizing:border-box;margin:0 auto;border:1px solid var(--divider);border-radius:8px;background:var(--background-primary);min-width:250px;max-width:550px;overflow:hidden;color:var(--text-primary);font-weight:400;font-size:calc(var(--font-size) * .875);line-height:calc(var(--font-size) * 1.25);font-family:var(--font-family);:where(*),:where(*:before),:where(*:after){box-sizing:border-box;margin:0;padding:0}:where(a){color:inherit;text-decoration:none}:where(.icon){flex-shrink:0;width:1em;height:1em}}.rich-text.s-1ea7h2m{overflow:hidden;white-space:pre-wrap;overflow-wrap:break-word;&:empty{display:none}}.link.s-1ea7h2m,.mention.s-1ea7h2m,.hashtag.s-1ea7h2m{color:var(--text-link);&:hover{text-decoration:underline}}.profile-card.s-2b3fq6{display:flex;flex-direction:column}.is-blurred.s-2b3fq6{scale:125%;filter:blur(4px)}.banner-wrapper.s-2b3fq6{background:var(--background-secondary);aspect-ratio:3 / 1;overflow:hidden}.banner.s-2b3fq6{width:100%;height:100%;object-fit:cover}.contents.s-2b3fq6{display:flex;position:relative;flex-direction:column;gap:8px;padding:12px 16px 16px}.logo.s-2b3fq6{width:24px;height:24px}.header.s-2b3fq6{display:flex;justify-content:space-between;align-items:end}.actions.s-2b3fq6{display:flex;align-items:center;gap:16px}.avatar-wrapper.s-2b3fq6{display:block;flex-shrink:0;outline:2px solid var(--background-primary);border-radius:9999px;background:var(--background-secondary);width:90px;height:90px;overflow:hidden;.has-banner:where(.s-2b3fq6) &{margin-top:-56px}}.avatar.s-2b3fq6{width:100%;height:100%;object-fit:cover;.avatar-wrapper:where(.s-2b3fq6):hover &{filter:brightness(.85);&.is-blurred{filter:brightness(.85) blur(4px)}}}.follow-button.s-2b3fq6{display:flex;align-items:center;gap:6px;border-radius:9999px;background:var(--button);padding:9px 12px;color:var(--button-text);font-weight:600;font-size:calc(var(--font-size) * .8125);line-height:calc(var(--font-size) * 1);user-select:none;.icon:where(.s-2b3fq6){font-size:16px}&:hover{background:var(--button-hover)}}.display-name.s-2b3fq6{font-weight:700;font-size:calc(var(--font-size) * 1.25);line-height:calc(var(--font-size) * 1.75);overflow-wrap:break-word}.handle.s-2b3fq6{color:var(--text-secondary);overflow-wrap:break-word}.stats.s-2b3fq6{display:flex;flex-wrap:wrap;gap:20px;min-width:0}.stat-entry.s-2b3fq6{color:var(--text-secondary)}.stat-count.s-2b3fq6{color:var(--text-primary);font-weight:700}.message.s-ibmh3w{margin:0 auto;padding:32px 16px;max-width:380px;color:var(--text-secondary);text-align:center}
+1
assets/ProfileFeedDisplay-DOw9fkTH.css
··· 1 + .bluesky-embed.s-1pz15a1{position:relative;box-sizing:border-box;margin:0 auto;border:1px solid var(--divider);border-radius:8px;background:var(--background-primary);min-width:250px;max-width:550px;overflow:hidden;color:var(--text-primary);font-weight:400;font-size:calc(var(--font-size) * .875);line-height:calc(var(--font-size) * 1.25);font-family:var(--font-family);:where(*),:where(*:before),:where(*:after){box-sizing:border-box;margin:0;padding:0}:where(a){color:inherit;text-decoration:none}:where(.icon){flex-shrink:0;width:1em;height:1em}}.gate.s-1se5tqk{display:flex;align-items:center;gap:12px;cursor:pointer;border:1px solid var(--divider);border-radius:6px;padding:0 12px;height:44px;.content-hider[open]:where(.s-1se5tqk) &{margin-bottom:12px}&:hover{border-color:var(--divider-hover)}}.icon.s-1se5tqk{width:18px;height:18px;color:var(--text-secondary)}.label.s-1se5tqk{flex-grow:1;overflow:hidden;font-weight:500;user-select:none;text-overflow:ellipsis}.action.s-1se5tqk{color:var(--text-link);font-weight:500;font-size:calc(var(--font-size) * .8125);line-height:calc(var(--font-size) * 1.25);&:before{content:"Show"}.content-hider[open]:where(.s-1se5tqk) &:before{content:"Hide"}}.external-embed.s-au8a8u{display:block;border:1px solid var(--divider);border-radius:6px;overflow:hidden;&:hover{border-color:var(--divider-hover)}}.thumbnail.s-au8a8u{display:block;border-bottom:1px solid var(--divider);background:#000;aspect-ratio:1.91;width:100%;.external-embed:where(.s-au8a8u):hover &{border-color:var(--divider-hover)}}.meta.s-au8a8u{padding:12px}.title.s-au8a8u{display:-webkit-box;overflow:hidden;font-weight:700;white-space:pre-wrap;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow-wrap:break-word;&:empty{display:none}}.description.s-au8a8u{display:-webkit-box;overflow:hidden;color:var(--text-secondary);font-size:calc(var(--font-size) * .8125);white-space:pre-wrap;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow-wrap:break-word;&:empty{display:none}}.domain.s-au8a8u{display:flex;align-items:center;gap:6px;margin:6px 0 0;color:var(--text-secondary);font-weight:500;font-size:calc(var(--font-size) * .75)}.feed-embed.s-1c1phtf{display:flex;flex-direction:column;gap:12px;border:1px solid var(--divider);border-radius:6px;padding:12px;&:hover{border-color:var(--divider-hover)}}.main.s-1c1phtf{display:flex;gap:12px}.avatar-wrapper.s-1c1phtf{margin:2px 0 0;border-radius:6px;background:var(--background-secondary);width:36px;height:36px;overflow:hidden}.avatar.s-1c1phtf{width:100%;height:100%;object-fit:cover}.name.s-1c1phtf{font-weight:700}.creator.s-1c1phtf{color:var(--text-secondary);font-size:calc(var(--font-size) * .8125)}.description.s-1c1phtf{display:-webkit-box;overflow:hidden;font-size:calc(var(--font-size) * .8125);white-space:pre-wrap;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow-wrap:break-word;&:empty{display:none}}.is-aligned.s-1d339cy{align-self:baseline;max-width:100%}.grid.s-1d339cy{display:flex;gap:2px}.col.s-1d339cy{display:flex;flex:1;flex-direction:column;gap:2px}.square.s-1d339cy{aspect-ratio:1}.wide.s-1d339cy{aspect-ratio:1.5}.item.s-1d339cy{position:relative;flex-grow:1;flex-shrink:0;overflow:hidden}.is-bordered.s-1d339cy{.tl:where(.s-1d339cy),.tr:where(.s-1d339cy),.bl:where(.s-1d339cy),.br:where(.s-1d339cy){border:1px solid var(--divider)}.tl:where(.s-1d339cy){border-top-left-radius:6px}.tr:where(.s-1d339cy){border-top-right-radius:6px}.bl:where(.s-1d339cy){border-bottom-left-radius:6px}.br:where(.s-1d339cy){border-bottom-right-radius:6px}}.single-item.s-1d339cy{position:relative;aspect-ratio:16 / 9;overflow:hidden;.image:where(.s-1d339cy){object-fit:contain}}.is-standalone.s-1d339cy{min-width:64px;max-width:100%;min-height:64px;max-height:320px}.image.s-1d339cy{position:absolute;inset:0;background:#000;width:100%;height:100%;object-fit:cover;font-size:0px}.is-blurred.s-1d339cy{scale:125%;filter:blur(24px)}.placeholder.s-1d339cy{width:100vw;height:100vh}.list-embed.s-1mo1e33{display:flex;flex-direction:column;gap:12px;border:1px solid var(--divider);border-radius:6px;padding:12px;&:hover{border-color:var(--divider-hover)}}.main.s-1mo1e33{display:flex;gap:12px}.avatar-wrapper.s-1mo1e33{margin:2px 0 0;border-radius:6px;background:var(--background-secondary);width:36px;height:36px;overflow:hidden}.avatar.s-1mo1e33{width:100%;height:100%;object-fit:cover}.name.s-1mo1e33{font-weight:700}.creator.s-1mo1e33{color:var(--text-secondary);font-size:calc(var(--font-size) * .8125)}.description.s-1mo1e33{display:-webkit-box;overflow:hidden;font-size:calc(var(--font-size) * .8125);white-space:pre-wrap;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow-wrap:break-word;&:empty{display:none}}.video-embed.s-1h3cnsw{display:block;position:relative;background:#000;aspect-ratio:16 / 9;overflow:hidden}.is-bordered.s-1h3cnsw{border:1px solid var(--divider);border-radius:6px}.is-standalone.s-1h3cnsw{align-self:baseline;aspect-ratio:auto;max-width:100%}.constrainer.s-1h3cnsw{min-width:64px;max-width:100%;min-height:64px;max-height:320px}.thumbnail.s-1h3cnsw{width:100%;height:100%;object-fit:contain}.is-blurred.s-1h3cnsw{scale:125%;filter:blur(24px)}.placeholder.s-1h3cnsw{width:100vw;height:100vh}.play.s-1h3cnsw{display:grid;position:absolute;top:50%;left:50%;place-items:center;translate:-50% -50%;border-radius:50%;background:#40404099;aspect-ratio:1 / 1;height:40%;max-height:48px;color:#fff;font-size:20px;.icon:where(.s-1h3cnsw){width:40%;height:40%}.is-standalone:where(.s-1h3cnsw) &:hover{background:#404040cc}}.quote-embed.s-vbjlyj{display:block;border:1px solid var(--divider);border-radius:6px;overflow:hidden;&:hover{border-color:var(--divider-hover)}}.meta.s-vbjlyj{display:flex;padding:12px 12px 0;color:var(--text-secondary);.avatar-wrapper:where(.s-vbjlyj){flex-shrink:0;margin:0 8px 0 0;border-radius:9999px;background:var(--background-secondary);width:20px;height:20px;overflow:hidden}.avatar:where(.s-vbjlyj){width:100%;height:100%}.name-wrapper:where(.s-vbjlyj){display:flex;gap:4px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.display-name-wrapper:where(.s-vbjlyj){overflow:hidden;text-overflow:ellipsis}.display-name:where(.s-vbjlyj){color:var(--text-primary);font-weight:700}.handle:where(.s-vbjlyj){display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dot:where(.s-vbjlyj){flex-shrink:0;margin:0 6px}.date:where(.s-vbjlyj){white-space:nowrap}}.body.s-vbjlyj{display:flex;align-items:flex-start}.aside.s-vbjlyj{flex-grow:1;flex-basis:0;margin:8px 0 12px 12px;max-width:20%}.text.s-vbjlyj{display:-webkit-box;margin:8px 12px 12px;overflow:hidden;-webkit-box-orient:vertical;-webkit-line-clamp:6;line-clamp:6;flex-grow:4;flex-basis:0px;min-width:0px;white-space:pre-wrap;overflow-wrap:break-word}.divide.s-vbjlyj{padding:6px 0}.starterpack-embed.s-whpa2l{display:block;border:1px solid var(--divider);border-radius:6px;overflow:hidden;&:hover{border-color:var(--divider-hover)}}.banner.s-whpa2l{display:block;aspect-ratio:1.91;width:100%}.meta.s-whpa2l{display:flex;flex-direction:column;gap:12px;padding:12px}.main.s-whpa2l{display:flex;gap:12px}.avatar.s-whpa2l{margin:2px;width:36px;height:36px}.name.s-whpa2l{font-weight:700}.creator.s-whpa2l{color:var(--text-secondary);font-size:calc(var(--font-size) * .8125)}.description.s-whpa2l{display:-webkit-box;overflow:hidden;font-size:calc(var(--font-size) * .8125);white-space:pre-wrap;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow-wrap:break-word;&:empty{display:none}}.embeds.s-1nks9gp{display:flex;flex-direction:column;gap:12px;margin:12px 0 0}.message.s-1nks9gp{border:1px solid var(--divider);border-radius:6px;padding:12px;color:var(--text-secondary)}.rich-text.s-10xqaeb{overflow:hidden;white-space:pre-wrap;overflow-wrap:break-word;&:empty{display:none}}.is-large.s-10xqaeb{font-size:calc(var(--font-size) * 1);line-height:calc(var(--font-size) * 1.5)}.link.s-10xqaeb,.mention.s-10xqaeb,.hashtag.s-10xqaeb{color:var(--text-link);&:hover{text-decoration:underline}}.feed-post.s-1c3lek9{padding:0 16px}.is-leaf.s-1c3lek9{border-bottom:1px solid var(--divider)}.ascendant-line-wrapper.s-1c3lek9{display:flex;flex-direction:column;align-items:center;width:36px;.line:where(.s-1c3lek9){position:absolute;top:0;bottom:4px;flex-grow:1;border-left:2px solid var(--divider)}}.descendant-line.s-1c3lek9{flex-grow:1;margin-top:4px;border-left:2px solid var(--divider)}.contexts.s-1c3lek9{display:flex;position:relative;flex-direction:column;padding:8px 0 4px}.context.s-1c3lek9{display:flex;align-items:center;gap:12px;color:var(--text-secondary);font-size:.8125rem;line-height:1.25rem;.aside:where(.s-1c3lek9){display:flex;flex-shrink:0;justify-content:flex-end;width:36px}.main:where(.s-1c3lek9){display:flex;min-width:0px;&:hover{text-decoration-line:underline}}.name:where(.s-1c3lek9){overflow:hidden;font-weight:500;text-overflow:ellipsis;white-space:nowrap}.affix:where(.s-1c3lek9){flex-shrink:0;white-space:pre}}.content.s-1c3lek9{display:flex;gap:12px;.aside:where(.s-1c3lek9){display:flex;flex-shrink:0;flex-direction:column;align-items:center}.main:where(.s-1c3lek9){flex-grow:1;padding-bottom:12px;min-width:0}}.avatar-wrapper.s-1c3lek9{display:block;border-radius:9999px;background:var(--background-secondary);width:36px;height:36px;overflow:hidden;&:hover{filter:brightness(.85)}}.avatar.s-1c3lek9{width:100%;height:100%;object-fit:cover}.meta.s-1c3lek9{display:flex;align-items:center;margin:0 0 2px;color:var(--text-secondary);.name-wrapper:where(.s-1c3lek9){display:flex;gap:4px;max-width:100%;overflow:hidden;color:inherit;text-decoration:none;text-overflow:ellipsis;white-space:nowrap}.display-name-wrapper:where(.s-1c3lek9){overflow:hidden;text-overflow:ellipsis;.name-wrapper:where(.s-1c3lek9):hover &{text-decoration:underline}}.display-name:where(.s-1c3lek9){color:var(--text-primary);font-weight:700}.handle:where(.s-1c3lek9){display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dot:where(.s-1c3lek9){flex-shrink:0;margin:0 6px}.date:where(.s-1c3lek9){color:inherit;text-decoration:none;white-space:nowrap;&:hover{text-decoration:underline}}}.reply-context.s-1c3lek9{overflow:hidden;color:var(--text-secondary);font-size:calc(var(--font-size) * .8125);text-overflow:ellipsis;white-space:nowrap;a:where(.s-1c3lek9){color:inherit;font-weight:500;&:hover{text-decoration:underline}}}.metrics.s-1c3lek9{display:flex;align-items:center;gap:16px;margin-top:12px;color:var(--text-secondary)}.stat.s-1c3lek9{display:flex;align-items:center;gap:8px;min-width:0px;max-width:100%;.count:where(.s-1c3lek9){padding-right:8px;overflow:hidden;font-size:calc(var(--font-size) * .8125);line-height:calc(var(--font-size) * 1.25);text-overflow:ellipsis;white-space:nowrap}}.profile-feed-header.s-1xh30xs{display:flex;justify-content:space-between;align-items:center;gap:16px;container-type:inline-size;border-bottom:1px solid var(--divider);padding:12px 16px}.title.s-1xh30xs{padding:4px 0;min-width:0;overflow:hidden;font-weight:600;font-size:calc(var(--font-size) * 1);line-height:calc(var(--font-size) * 1.5);text-overflow:ellipsis;white-space:nowrap;&:hover{text-decoration:underline}}.logo.s-1xh30xs{width:24px;height:24px}.message.s-f12rvk{margin:0 auto;padding:32px 16px;max-width:380px;color:var(--text-secondary);text-align:center}.feed.s-f12rvk{max-height:var(--max-feed-height);overflow-y:auto}.end-marker.s-f12rvk{display:grid;place-items:center;height:48px;.dot:where(.s-f12rvk){border-radius:50%;background:var(--text-secondary);width:4px;height:4px}}
+1
assets/ProfileFeedDisplay-QaaAcc9o.js
··· 1 + import{p as e,f as s,t as a,s as t,c as i,a as l,b as r,d as n,e as d,g as p,B as c,h as o,i as h,j as u,k as v,l as f,u as m,C as b}from"./index-CD_0uzJz.js";import{X as y,s as k,a as g,h as $,o as w,G as x,b as j,C as Z,e as M}from"./GuideInstructions-CTis8QB-.js";import{s as q}from"./index-Cr8Vao8y.js";const C=/[&"<]/g,A=/[&<]/g;function F(e,s){const a=String(e??""),t=s?C:A;t.lastIndex=0;let i="",l=0;for(;t.test(a);){const e=t.lastIndex-1,s=a[e];i+=a.substring(l,e)+("&"===s?"&amp;":'"'===s?"&quot;":"&lt;"),l=e+1}return i+a.substring(l)}function _(e,s,a=!1){if("hidden"===e&&"until-found"!==s&&(a=!0),null==s||!s&&a)return"";return` ${e}${a?"":`="${F(s,!0)}"`}`}function B(e,s,a){var t=function(e,s){var a=null==e?"":""+e;return s&&(a=a?a+" "+s:s),""===a?null:a}(e,s);return t?` class="${F(t,!0)}"`:""}function N(e,s){var a=function(e){return null==e?null:String(e)}(e);return a?` style="${F(a,!0)}"`:""}const z="!no-unauthenticated";function U(e,s){const{children:a}=s;e.push('<div class="bluesky-embed s-1pz15a1">'),a(e),e.push("</div>")}const P=e=>`https://bsky.app/profile/${e}`,I=(e,s)=>`https://bsky.app/profile/${e}/post/${s}`,R=e=>`https://bsky.app/hashtag/${e}`,S=(e,s)=>`https://bsky.app/profile/${e}/feed/${s}`;let T=0,H=0;const V=new Intl.DateTimeFormat("en-US",{dateStyle:"long",timeStyle:"short"}),L=new Intl.DateTimeFormat("en-US",{dateStyle:"medium"}),D=new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric"}),G=e=>{const s=new Date(e),a=s.getTime();if(isNaN(a))return"N/A";const t=Date.now();if(t>H){const e=new Date(t);e.setMonth(0,1),e.setHours(0,0,0),T=e.getTime(),e.setFullYear(e.getFullYear()+1,0,0),e.setHours(23,59,59,999),H=e.getTime()}return a>=T&&a<=H?D.format(s):L.format(s)},W=/^at:\/\/((?:did:[a-zA-Z0-9._:%-]+)|(?:[a-zA-Z0-9][a-zA-Z0-9-.]*))(?:\/([a-zA-Z0-9.-]+)(?:\/([a-zA-Z0-9_~.:-]{1,512}))?)?\/?(?:\?([^#\s]*))?(?:#([^\s]*))?$/,Y=e=>{const s=W.exec(e);if(!s)throw new E(`invalid at-uri: ${e}`);return{repo:s[1],collection:s[2]??"",rkey:s[3]??"",query:s[4]??"",fragment:s[5]??""}};class E extends Error{}const X=new Intl.NumberFormat("en-US"),J=new Intl.NumberFormat("en-US",{notation:"compact"}),K=e=>e<1e3?""+e:e<1e5?X.format(e):J.format(e),O=e=>X.format(e),Q={"!hide":{name:"Hidden by moderators",flags:1},"!warn":{name:"Content warning",flags:1},porn:{name:"Adult content",flags:0},sexual:{name:"Sexually suggestive",flags:0},"graphic-media":{name:"Graphic media",flags:0},nudity:{name:"Nudity",flags:0}},ee=(e,s)=>{if(e?.length)for(let a=0,t=e.length;a<t;a++){const t=e[a],i=t.val;if(!(i in Q))continue;const l=Q[i];if(!(1&l.flags&&t.src===s))return l}};function se(e,s){{const{embed:a}=s,t=a.external,i=(e=>{let s;if("parse"in URL)s=URL.parse(e);else try{s=new URL(e)}catch{}return!s||"https:"!==s.protocol&&"http:"!==s.protocol?null:s})(t.uri)?.host;e.push(`<a target="_blank"${_("href",i&&t.uri)} rel="noopener noreferrer nofollow" class="external-embed s-au8a8u">`),t.thumb&&e.push(`<img loading="lazy"${_("src",t.thumb)} alt="" class="thumbnail s-au8a8u"/>`),e.push(` <div class="meta s-au8a8u"><p class="title s-au8a8u">${F(t.title)}</p> <p class="description s-au8a8u">${F(t.description)}</p> `),i&&e.push(`<div class="domain s-au8a8u"><svg class="icon" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="m4.172 8.07 3.94 2.957.977-1.941 3.887-.978 1.15-4.6M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-6.078 4.865.973-1.946-2.869-1.928-1.89-.12-1.08 1.075 1.947 2.919h2.919Z"></path></svg> <span class="domain-name">${F(i)}</span></div>`),e.push("</div></a>")}}const ae={width:16,height:9};function te(e,s){{const{embed:a,borderless:t,standalone:i,blur:l}=s,r=a.images,n=r.length;function d(e,s){const a=r[s];e.push(`<img loading="lazy"${_("src",a.thumb)}${_("alt",a.alt)}${B("image"+(l?" is-blurred":""),"s-1d339cy")}/>`)}if(e.push(`<div${B("image-embed"+(t?"":" is-bordered")+(i&&1===n?" is-aligned":""),"s-1d339cy")}>`),4===n)e.push('<div class="grid s-1d339cy"><div class="col s-1d339cy"><div class="item wide tl s-1d339cy">'),d(e,0),e.push('</div> <div class="item wide bl s-1d339cy">'),d(e,2),e.push('</div></div> <div class="col s-1d339cy"><div class="item wide tr s-1d339cy">'),d(e,1),e.push('</div> <div class="item wide br s-1d339cy">'),d(e,3),e.push("</div></div></div>");else if(3===n)e.push('<div class="grid s-1d339cy"><div class="col square s-1d339cy"><div class="item tl bl s-1d339cy">'),d(e,0),e.push('</div></div> <div class="col square s-1d339cy"><div class="item tr s-1d339cy">'),d(e,1),e.push('</div> <div class="item br s-1d339cy">'),d(e,2),e.push("</div></div></div>");else if(2===n)e.push('<div class="grid s-1d339cy"><div class="col s-1d339cy"><div class="item square tl bl s-1d339cy">'),d(e,0),e.push('</div></div> <div class="col s-1d339cy"><div class="item square tr br s-1d339cy">'),d(e,1),e.push("</div></div></div>");else if(1===n){const p=i&&(r[0].aspectRatio||ae);e.push(`<div${B("single-item tl tr bl br"+(p?" is-standalone":""),"s-1d339cy")}${N(p?`aspect-ratio: ${p.width}/${p.height}`:"")}>`),d(e,0),e.push(" "),p&&e.push('<div class="placeholder s-1d339cy"></div>'),e.push("</div>")}e.push("</div>")}}function ie(e,s){{const{post:a,embed:t,borderless:i,standalone:l,blur:r}=s,n=l&&t.aspectRatio,d=a&&I(a.author.did,Y(a.uri).rkey);function p(e){e.push(`<img loading="lazy"${_("src",t.thumbnail)} alt=""${B("thumbnail"+(r?" is-blurred":""),"s-1h3cnsw")}/> `),n&&e.push('<div class="placeholder s-1h3cnsw"></div>'),e.push(' <div class="play s-1h3cnsw"><svg class="icon s-1h3cnsw" fill="none" viewBox="0 0 24 24"><path fill="currentColor" d="M22 12 5 2v20l17-10Z"></path></svg></div>')}l?(e.push(`<a target="_blank"${_("href",d)}${B("video-embed"+(i?"":" is-bordered")+(l?" is-standalone":""),"s-1h3cnsw")}><div class="constrainer s-1h3cnsw"${N(n?`aspect-ratio: ${n.width}/${n.height}`:"")}>`),p(e),e.push("</div></a>")):(e.push(`<div${B("video-embed"+(i?"":" is-bordered"),"s-1h3cnsw")}${N(n?`aspect-ratio: ${n.width}/${n.height}`:"")}>`),p(e),e.push("</div>"))}}const le=e=>{if(e){if("app.bsky.embed.images#view"===e.$type)return e;if("app.bsky.embed.recordWithMedia#view"===e.$type)return le(e.media)}},re=e=>{if(e){if("app.bsky.embed.video#view"===e.$type)return e;if("app.bsky.embed.recordWithMedia#view"===e.$type)return re(e.media)}};function ne(e,s){e.push(`<div class="message s-1nks9gp">${F(s)}</div>`)}function de(e,s){{const{post:a,embed:t,large:i=!1}=s;function l(e,s){!function(e,s){{const{warning:a,children:t}=s;a?(e.push(`<details class="content-hider s-1se5tqk"><summary class="gate s-1se5tqk"><svg class="icon s-1se5tqk" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="square" stroke-width="2" d="M11 11h1v5m9-4a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"></path><path fill="currentColor" stroke="currentColor" stroke-width=".5" d="M11.5 7.25h-.25v1.5h1.5v-1.5H11.5Z"></path></svg> <span class="label s-1se5tqk">${F(a.name)}</span> <span class="action s-1se5tqk"></span></summary> `),t(e),e.push("</details>")):t(e)}}(e,{warning:a&&ee(a.labels,a.author.did),children:e=>{"app.bsky.embed.external#view"===s.$type?se(e,{embed:s}):"app.bsky.embed.images#view"===s.$type?te(e,{embed:s,standalone:!0}):"app.bsky.embed.video#view"===s.$type?ie(e,{post:a,embed:s,standalone:!0}):ne(e,"Unsupported media embed")}})}function r(e,s){const a=s.record;if("app.bsky.embed.record#viewRecord"===a.$type)!function(e,s){{const{embed:a,large:t=!1}=s,i=a.value,l=i.text.trim(),r=a.author,n=r.displayName?.trim(),d=a.embeds?.[0],p=le(d),c=re(d),o=I(r.did,Y(a.uri).rkey),h=!!ee(a.labels,r.did);e.push(`<a target="_blank"${_("href",o)} class="quote-embed s-vbjlyj"><div class="meta s-vbjlyj"><div class="avatar-wrapper s-vbjlyj">`),r.avatar&&e.push(`<img loading="lazy"${_("src",r.avatar)} alt="" class="avatar s-vbjlyj"/>`),e.push('</div> <span class="name-wrapper s-vbjlyj">'),n&&e.push(`<bdi class="display-name-wrapper s-vbjlyj"><span class="display-name s-vbjlyj">${F(n)}</span></bdi>`),e.push(` <span class="handle s-vbjlyj">@${F(r.handle)}</span></span> <span aria-hidden="true" class="dot s-vbjlyj">ยท</span> <time${_("datetime",i.createdAt)} class="date s-vbjlyj">${F(G(i.createdAt))}</time></div> `),l?(e.push('<div class="body s-vbjlyj">'),t||(p?(e.push('<div class="aside s-vbjlyj">'),te(e,{embed:p,blur:h}),e.push("</div>")):c&&(e.push('<div class="aside s-vbjlyj">'),ie(e,{embed:c,blur:h}),e.push("</div>"))),e.push(` <p class="text s-vbjlyj">${F(l)}</p></div>`)):e.push('<div class="divide s-vbjlyj"></div>'),e.push(" "),!t&&l||(p?te(e,{embed:p,borderless:!0,blur:h}):c&&ie(e,{embed:c,borderless:!0,blur:h})),e.push("</a>")}}(e,{embed:a,large:i});else if("app.bsky.feed.defs#generatorView"===a.$type)!function(e,s){{const{embed:a}=s,t=a.creator,i=S(t.did,Y(a.uri).rkey);e.push(`<a target="_blank"${_("href",i)} class="feed-embed s-1c1phtf"><div class="main s-1c1phtf"><div class="avatar-wrapper s-1c1phtf">`),a.avatar?e.push(`<img loading="lazy"${_("src",a.avatar)} alt="" class="avatar s-1c1phtf"/>`):e.push('<svg viewBox="0 0 32 32" class="avatar s-1c1phtf"><path fill="#0070FF" d="M0 0h32v32H0z"></path><path fill="#fff" d="M22.153 22.354a9.328 9.328 0 0 0 3.837-.491 3.076 3.076 0 0 0-4.802-2.79m.965 3.281a6.128 6.128 0 0 0-.965-3.28Zm-11.342-3.28a3.077 3.077 0 0 0-4.801 2.79 9.21 9.21 0 0 0 3.835.49m.966-3.28a6.127 6.127 0 0 0-.966 3.28Zm8.265-8.997a3.076 3.076 0 1 1-6.153 0 3.076 3.076 0 0 1 6.153 0Zm6.154 3.077a2.307 2.307 0 1 1-4.615 0 2.307 2.307 0 0 1 4.615 0Zm-13.847 0a2.307 2.307 0 1 1-4.614 0 2.307 2.307 0 0 1 4.614 0Z"></path><path fill="#fff" d="M22 22c0 3.314-2.686 3.5-6 3.5s-6-.186-6-3.5a6 6 0 0 1 12 0Z"></path></svg>'),e.push(`</div> <div class="info"><p class="name s-1c1phtf">${F(a.displayName)}</p> <p class="creator s-1c1phtf">Feed by @${F(t.handle)}</p></div></div> <p class="description s-1c1phtf">${F(a.description)}</p></a>`)}}(e,{embed:a});else if("app.bsky.graph.defs#listView"===a.$type)!function(e,s){{const{embed:a}=s,t=a.creator,i=S(t.did,Y(a.uri).rkey);e.push(`<a target="_blank"${_("href",i)} class="list-embed s-1mo1e33"><div class="main s-1mo1e33"><div class="avatar-wrapper s-1mo1e33">`),a.avatar?e.push(`<img loading="lazy"${_("src",a.avatar)} alt="" class="avatar s-1mo1e33"/>`):e.push('<svg viewBox="0 0 32 32" class="avatar s-1mo1e33"><path fill="#0070FF" d="M0 0h32v32H0z"></path><path fill="#fff" d="M22.153 22.354a9.328 9.328 0 0 0 3.837-.491 3.076 3.076 0 0 0-4.802-2.79m.965 3.281a6.128 6.128 0 0 0-.965-3.28Zm-11.342-3.28a3.077 3.077 0 0 0-4.801 2.79 9.21 9.21 0 0 0 3.835.49m.966-3.28a6.127 6.127 0 0 0-.966 3.28Zm8.265-8.997a3.076 3.076 0 1 1-6.153 0 3.076 3.076 0 0 1 6.153 0Zm6.154 3.077a2.307 2.307 0 1 1-4.615 0 2.307 2.307 0 0 1 4.615 0Zm-13.847 0a2.307 2.307 0 1 1-4.614 0 2.307 2.307 0 0 1 4.614 0Z"></path><path fill="#fff" d="M22 22c0 3.314-2.686 3.5-6 3.5s-6-.186-6-3.5a6 6 0 0 1 12 0Z"></path></svg>'),e.push(`</div> <div class="info"><p class="name s-1mo1e33">${F(a.name)}</p> <p class="creator s-1mo1e33">${F((e=>{switch(e){case"app.bsky.graph.defs#curatelist":return"User list";case"app.bsky.graph.defs#modlist":return"Moderation list"}return"Unknown list"})(a.purpose))} by @${F(t.handle)}</p></div></div> <p class="description s-1mo1e33">${F(a.description)}</p></a>`)}}(e,{embed:a});else if("app.bsky.graph.defs#starterPackViewBasic"===a.$type)!function(e,s){{const{embed:a,large:t=!1}=s,i=a.record,l=a.creator,r=l.did,n=Y(a.uri).rkey,d=((e,s)=>`https://bsky.app/starter-pack/${e}/${s}`)(r,n);if(e.push(`<a target="_blank"${_("href",d)} class="starterpack-embed s-whpa2l">`),t){const s=((e,s)=>`https://ogcard.cdn.bsky.app/start/${e}/${s}`)(r,n);e.push(`<img loading="lazy"${_("src",s)} alt="" class="banner s-whpa2l"/>`)}e.push(` <div class="meta s-whpa2l"><div class="main s-whpa2l"><svg fill="none" viewBox="0 0 24 24" class="avatar s-whpa2l"><defs><linearGradient id="a" x1="0" x2="100%" y1="0" y2="0" gradientTransform="rotate(45)"><stop offset="0" stop-color="#0A7AFF"></stop><stop offset="1" stop-color="#59B9FF"></stop></linearGradient></defs><path fill="url(#a)" fill-rule="evenodd" d="M11.26 5.227 5.02 6.899c-.734.197-1.17.95-.973 1.685l1.672 6.24c.197.734.951 1.17 1.685.973l6.24-1.672a1.376 1.376 0 0 0 .973-1.685L12.945 6.2a1.375 1.375 0 0 0-1.685-.973Zm-6.566.459a2.632 2.632 0 0 0-1.86 3.223l1.672 6.24a2.632 2.632 0 0 0 3.223 1.861l6.24-1.672a2.631 2.631 0 0 0 1.861-3.223l-1.672-6.24a2.632 2.632 0 0 0-3.223-1.861l-6.24 1.672Z" clip-rule="evenodd"></path><path fill="url(#a)" fill-rule="evenodd" d="M15.138 18.411a4.606 4.606 0 1 0 0-9.211 4.606 4.606 0 0 0 0 9.211Zm0 1.257a5.862 5.862 0 1 0 0-11.724 5.862 5.862 0 0 0 0 11.724Z" clip-rule="evenodd"></path></svg> <div class="info"><p class="name s-whpa2l">${F(i.name)}</p> <p class="creator s-whpa2l">Starter pack by @${F(l.handle)}</p></div></div> <p class="description s-whpa2l">${F(i.description)}</p></div></a>`)}}(e,{embed:a,large:i});else{const s=(e=>{switch(e){case"app.bsky.feed.post":return"post";case"app.bsky.feed.generator":return"feed";case"app.bsky.graph.list":return"list";case"app.bsky.graph.starterpack":return"starter pack";case"app.bsky.labeler.service":return"labeler"}return null})(Y(a.uri).collection);ne(e,s&&("app.bsky.embed.record#viewNotFound"===a.$type||"app.bsky.embed.record#viewBlocked"===a.$type||"app.bsky.embed.record#viewDetached"===a.$type)?`This ${s} is unavailable`:"Unsupported record embed")}}e.push('<div class="embeds s-1nks9gp">'),"app.bsky.embed.recordWithMedia#view"===t.$type?(l(e,t.media),e.push(" "),r(e,t.record)):"app.bsky.embed.record#view"===t.$type?r(e,t):l(e,t),e.push("</div>")}}const pe=e=>e?.find(e=>"app.bsky.richtext.facet#link"===e.$type||"app.bsky.richtext.facet#mention"===e.$type||"app.bsky.richtext.facet#tag"===e.$type);function ce(e,s){{const{item:a,prev:t=!1,next:i=!1}=s,l=a.reason,r=a.post,n=a.reply?.parent,d=r.author,p=P(d.did),c=d.displayName?.trim(),o=r.record,h=I(d.did,Y(r.uri).rkey),u=r.replyCount||0,v=r.likeCount||0,f=(r.repostCount||0)+(r.quoteCount||0);if(e.push(`<div${B("feed-post"+(i?"":" is-leaf"),"s-1c3lek9")}><div class="contexts s-1c3lek9">`),t&&e.push('<div class="ascendant-line-wrapper s-1c3lek9"><div class="line s-1c3lek9"></div></div>'),e.push(" "),l)if("app.bsky.feed.defs#reasonRepost"===l.$type){const s=l.by;e.push(`<div class="context s-1c3lek9"><div class="aside s-1c3lek9"><svg class="icon" viewBox="0 0 24 24" fill="none"><path d="M17 3L20 6L17 9M7 21L4 18L7 15M5 18H20V13M4 11V6H19" stroke="currentColor" stroke-width="2" stroke-linecap="square"></path></svg></div> <a${_("href",P(s.did))} class="main s-1c3lek9"><span dir="auto" class="name s-1c3lek9">${F(s.displayName)}</span> <span class="affix s-1c3lek9"> reposted</span></a></div>`)}else"app.bsky.feed.defs#reasonPin"===l.$type&&e.push('<div class="context s-1c3lek9"><div class="aside s-1c3lek9"><svg class="icon" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="square" stroke-width="2" d="M12 15H5v-2.5l.377-.377A7.25 7.25 0 0 0 7.5 6.997V3h9v3.997a7.25 7.25 0 0 0 2.123 5.127L19 12.5V15h-7Zm0 0v6"></path></svg></div> <span class="main s-1c3lek9">Pinned</span></div>');if(e.push(`</div> <div class="content s-1c3lek9"><div class="aside s-1c3lek9"><a target="_blank"${_("href",p)} class="avatar-wrapper s-1c3lek9">`),d.avatar&&e.push(`<img loading="lazy"${_("src",d.avatar)} alt="" class="avatar s-1c3lek9"/>`),e.push("</a> "),i&&e.push('<div class="descendant-line s-1c3lek9"></div>'),e.push(`</div> <div class="main s-1c3lek9"><div class="meta s-1c3lek9"><a${_("href",p)} target="_blank" class="name-wrapper s-1c3lek9">`),c&&e.push(`<bdi class="display-name-wrapper s-1c3lek9"><span class="display-name s-1c3lek9">${F(c)}</span></bdi>`),e.push(` <span class="handle s-1c3lek9">@${F(d.handle)}</span></a> <span aria-hidden="true" class="dot s-1c3lek9">ยท</span> <a target="_blank"${_("href",h)}${_("title",(e=>{const s=new Date(e);return isNaN(s.getTime())?"N/A":V.format(s)})(o.createdAt))} class="date s-1c3lek9"><time${_("datetime",o.createdAt)}>${F(G(o.createdAt))}</time></a></div> `),!t&&o.reply){if(e.push('<p class="reply-context s-1c3lek9">'),n&&"app.bsky.feed.defs#postView"===n.$type){const s=n.author;e.push(`Replying to <a target="_blank"${_("href",P(s.did))} dir="auto" class="s-1c3lek9">${F(s.displayName?.trim()||`@${s.handle}`)}</a>`)}else e.push("Replying to an unknown post");e.push("</p>")}e.push(" "),function(e,s){{const{text:a,facets:t,large:i}=s;e.push(`<p${B("rich-text"+(i?" is-large":" is-small"),"s-10xqaeb")}>`);const l=q(a,t);for(let s=0,r=l.length;s<r;s++){let a=l[s];const t=pe(a.features);t?"app.bsky.richtext.facet#link"===t.$type?e.push(`<a target="_blank"${_("href",t.uri)} rel="noopener nofollow" class="link s-10xqaeb">${F(a.text)}</a>`):"app.bsky.richtext.facet#mention"===t.$type?e.push(`<a target="_blank"${_("href",P(t.did))} class="mention s-10xqaeb">${F(a.text)}</a>`):"app.bsky.richtext.facet#tag"===t.$type&&e.push(`<a target="_blank"${_("href",R(t.tag))} class="hashtag s-10xqaeb">${F(a.text)}</a>`):e.push(`${F(a.text)}`)}e.push("</p>")}}(e,{text:o.text,facets:o.facets}),e.push(" "),r.embed&&de(e,{post:r,embed:r.embed}),e.push(` <div class="metrics s-1c3lek9"><div${_("title",1===u?`${O(u)} reply`:`${O(u)} replies`)} class="stat s-1c3lek9"><svg class="icon" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="square" stroke-width="2" d="M3.002 4h18v14h-9l-5 3v-3h-4V4Z"></path></svg> <span class="count s-1c3lek9">${F(K(u))}</span></div> <div${_("title",1===f?`${O(f)} repost`:`${O(f)} reposts`)} class="stat s-1c3lek9"><svg class="icon" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="square" stroke-width="2" d="m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15"></path></svg> <span class="count s-1c3lek9">${F(K(f))}</span></div> <div${_("title",1===v?`${O(v)} like`:`${O(v)} likes`)} class="stat s-1c3lek9"><svg class="icon" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-width="2" d="M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z"></path></svg> <span class="count s-1c3lek9">${F(K(v))}</span></div></div></div></div></div>`)}}function oe(e,s){U(e,{children:e=>{e.push(`<div class="message s-f12rvk">${F(s)}</div>`)}})}function he(e,s){{const{profile:a,feed:t,allowUnauthenticated:i}=s,l=!i&&a?.labels?.some(e=>e.val===z),r=t.filter(e=>{if(!a)return!1;const s=e.reason;if(s){if("app.bsky.feed.defs#reasonPin"===s.$type)return!0;if("app.bsky.feed.defs#reasonRepost"===s.$type){const s=e.post.author;return s.did===a.did||(i||!s.labels?.some(e=>e.val===z))}return!1}return!e.reply});null===a?oe(e,"The profile can't be found, it may have been deleted."):l?oe(e,"The user has requested for their posts to not be displayed on external sites."):U(e,{children:e=>{if(function(e,s){{const{profile:a}=s;e.push(`<div class="profile-feed-header s-1xh30xs"><a target="_blank"${_("href",P(a.did))} class="title s-1xh30xs">Posts from @${F(a.handle)}</a> <svg class="logo s-1xh30xs" fill="none" viewBox="0 0 320 286"><path fill="#0A7AFF" d="M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z"></path></svg></div>`)}}(e,{profile:a}),e.push(" "),r.length>0){e.push('<div class="feed s-f12rvk">');const s=r;for(let a=0,t=s.length;a<t;a++){ce(e,{item:s[a]})}e.push(' <div class="end-marker s-f12rvk"><div class="dot s-f12rvk"></div></div></div>')}else e.push('<div class="message s-f12rvk">This user has not made any posts.</div>')}})}}var ue=s("<bluesky-profile-feed><!></bluesky-profile-feed>",2);function ve(s,n){e(n,!0);var d=ue();a(()=>t(d,"actor",n.data.profile?.did));var p=i(d);$(p,()=>function(e,s={}){let a="";return he({push(e){a+=e}},s.props??{}),{body:a}}(0,{props:n.data}).body),l(s,d),r()}var fe=s("<li><p>Insert the following scripts and stylesheets to the <code>&lt;head&gt;</code> of your website.</p> <!></li> <li><p>Insert the following markup in wherever you want the profile feed to be.</p> <!></li>",1),me=s("<!> <!>",1);function be(s,t){let $;e(t,!0);const q=m(()=>{$?.abort(),$=new AbortController;const e=$.signal;return(async e=>{const s=e.actor,a=e.allowUnauthenticated??!1,t=new y({handler:k({service:e.serviceUri??"https://public.api.bsky.app"})}),[{data:i},{data:l}]=await Promise.all([t.get("app.bsky.actor.getProfile",{signal:e.signal,params:{actor:s}}).catch(e=>e instanceof g&&"InvalidRequest"===e.kind&&"Profile not found"===e.description?{data:null}:Promise.reject(e)),t.get("app.bsky.feed.getAuthorFeed",{signal:e.signal,params:{actor:s,filter:"posts_no_replies",includePins:e.includePins,limit:30}}).catch(e=>e instanceof g&&"InvalidRequest"===e.kind&&"Profile not found"===e.description?{data:{feed:[]}}:Promise.reject(e))]);return{profile:i,feed:l.feed,allowUnauthenticated:a}})({actor:t.matched.actor,signal:e})});w(()=>{$?.abort()});const C=()=>{const e="https://cdn.jsdelivr.net/npm/bluesky-profile-feed-embed@^1.0.0";return`\x3c!-- Core web component and styling --\x3e\n<script type="module" src="${e}/+esm"><\/script>\n<link rel="stylesheet" href="${e}/dist/core.min.css">\n\n\x3c!-- Built-in themes --\x3e\n<link rel="stylesheet" href="${e}/themes/light.min.css" media="(prefers-color-scheme: light)">\n<link rel="stylesheet" href="${e}/themes/dim.min.css" media="(prefers-color-scheme: dark)">\n`};var A=n(),F=d(A);p(F,()=>u(q),e=>{b(e)},(e,s)=>{var a=me(),t=d(a);ve(t,{get data(){return u(s)}});var r=v(t,2),n=e=>{x(e,{title:"How do I embed this to my website?",children:(e,a)=>{j(e,{children:(e,a)=>{var t=fe(),r=d(t),n=v(i(r),2);{let e=m(C);Z(n,{get code(){return u(e)}})}var p=v(r,2),c=v(i(p),2);{let e=m(()=>(e=>{const s=`https://bsky.app/profile/${e.did}`;return`<bluesky-profile-feed actor="${M(e.did)}" include-pins>\n <a target="_blank" href="${M(s)}" class="bluesky-profile-feed-fallback">\n ${e.displayName?.trim()?`Posts by ${M(e.displayName)} (@${M(e.handle)})`:`Posts by @${M(e.handle)}`}\n </a>\n</bluesky-profile-feed>\n`})(u(s).profile));Z(c,{get code(){return u(e)}})}l(e,t)}})}})};f(r,e=>{u(s).profile&&e(n)}),l(e,a)},(e,s)=>{c(e,{type:"alert",children:(e,t)=>{var i=o();a(()=>h(i,""+u(s))),l(e,i)}})}),l(s,A),r()}export{be as default};
+1
assets/index-B_9yoyg2.css
··· 1 + *,:before,:after{box-sizing:border-box}html{line-height:1.15;font-family:Inter,Roboto,ui-sans-serif,sans-serif,"Noto Color Emoji",Twemoji Mozilla;-webkit-text-size-adjust:100%;tab-size:4}body{margin:0}b,strong{font-weight:bolder}code,kbd,samp,pre{font-size:1em;font-family:JetBrains Mono NL,ui-monospace,monospace}small{font-size:80%}sub,sup{position:relative;vertical-align:baseline;font-size:75%;line-height:0}sub{bottom:-.25em}sup{top:-.5em}table{border-color:currentcolor}button,input,optgroup,select,textarea{margin:0;font-size:100%;line-height:1.15;font-family:inherit}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}legend{padding:0}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}.bluesky-embed{--font-size: 16px;--font-family: system-ui, "Segoe UI", "Roboto", "Helvetica", "Arial", sans-serif, "Apple Color Emoji", "Segoe UI Emoji";--max-feed-height: 600px}.bluesky-embed{--text-primary: #000000;--text-secondary: #455668;--text-link: #1083fe;--background-primary: #ffffff;--background-secondary: #455668;--divider-hover: #a9b7c5;--divider: #d4dbe2;--button: #1083fe;--button-text: #ffffff;--button-hover: #0168d5}.banner.svelte-4gizvm{border:1px solid;border-radius:4px;padding:10px 12px;font-weight:500;font-size:.875rem;line-height:1.25rem;a{color:inherit;font-weight:600}}.type-alert.svelte-4gizvm{border-color:#fca5a5;background:#fee2e2;color:#991b1b}.type-inform.svelte-4gizvm{border-color:#bfdbfe;background:#dbeafe;color:#1e40af}.circular-spinner.svelte-rq8vha{display:block;animation:svelte-rq8vha-spin 1s linear infinite;margin:0 auto;width:24px;height:24px}@keyframes svelte-rq8vha-spin{to{transform:rotate(360deg)}}.accented.svelte-rq8vha{stroke:#2563eb}.background.svelte-rq8vha{stroke:#2563eb;opacity:20%}.field.svelte-1wzaqos{display:flex;flex-direction:column;gap:8px}.input-wrapper.svelte-1wzaqos{display:contents}.label.svelte-1wzaqos{color:#4b5563;font-weight:600;font-size:.875rem;line-height:1.25rem}.text-input.svelte-1e5va0l{outline:2px none #2563eb;outline-offset:-1px;border:1px solid #9ca3af;border-radius:4px;padding:8px 12px;font-size:.875rem;line-height:1.25rem;&::placeholder{color:#9ca3af}&:focus{outline-style:solid}}.app.svelte-1n46o8q{margin:0 auto;padding:36px 16px;width:100%;max-width:582px}.header.svelte-1n46o8q{margin:24px 0}.main.svelte-1n46o8q{margin:36px 0}.choices.svelte-1n46o8q{display:flex;flex-direction:column;gap:8px;margin:16px 0 36px;border:0;padding:0}.choice.svelte-1n46o8q{display:flex;align-items:center;gap:8px;font-size:.875rem;line-height:1.25rem;input:where(.svelte-1n46o8q){appearance:none;outline:2px none #2563eb;outline-offset:2px;border:1px solid #9ca3af;border-radius:8px;width:16px;height:16px;&:checked{border:0;background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");background-color:#2563eb}&:focus{outline-style:solid}}}.footer.svelte-1n46o8q{display:flex;flex-wrap:wrap;gap:.5rem;margin:36px 0 0;border-top:1px solid #d1d5db;padding:36px 0 0;color:#4b5563;font-size:.875rem;line-height:1.25rem;a:where(.svelte-1n46o8q){color:#2563eb}}
+2
assets/index-CD_0uzJz.js
··· 1 + const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./PostDisplay-CqTUAVla.js","./GuideInstructions-CTis8QB-.js","./GuideInstructions-B8N7RzmZ.css","./index-Cr8Vao8y.js","./PostDisplay-yMSDBkol.css","./ProfileCardDisplay-BpCMWdM3.js","./ProfileCardDisplay-D4FwjqsR.css","./ProfileFeedDisplay-QaaAcc9o.js","./ProfileFeedDisplay-DOw9fkTH.css"])))=>i.map(i=>d[i]); 2 + !function(){const e=document.createElement("link").relList;if(!(e&&e.supports&&e.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))t(e);new MutationObserver(e=>{for(const n of e)if("childList"===n.type)for(const e of n.addedNodes)"LINK"===e.tagName&&"modulepreload"===e.rel&&t(e)}).observe(document,{childList:!0,subtree:!0})}function t(e){if(e.ep)return;e.ep=!0;const t=function(e){const t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),"use-credentials"===e.crossOrigin?t.credentials="include":"anonymous"===e.crossOrigin?t.credentials="omit":t.credentials="same-origin",t}(e);fetch(e.href,t)}}();const e=!1;var t=Array.isArray,n=Array.prototype.indexOf,r=Array.from,i=Object.defineProperty,l=Object.getOwnPropertyDescriptor,s=Object.getOwnPropertyDescriptors,o=Object.prototype,a=Array.prototype,f=Object.getPrototypeOf,c=Object.isExtensible;const u=()=>{};function d(){var e,t;return{promise:new Promise((n,r)=>{e=n,t=r}),resolve:e,reject:t}}const h=16,v=32,p=64,_=128,g=512,m=1024,y=2048,b=4096,w=8192,k=16384,x=32768,E=65536,P=1<<17,S=1<<18,A=1<<19,q=32768,j=1<<21,O=1<<23,L=Symbol("$state"),z=Symbol("legacy props"),N=Symbol(""),$=new class extends Error{name="StaleReactionError";message="The reaction that called `getAbortSignal()` was re-run or destroyed"};const M=Symbol(),D="http://www.w3.org/1999/xhtml";function R(e){return e===this.v}let C=null;function T(e){C=e}function I(e,t=!1,n){C={p:C,i:!1,c:null,e:null,s:e,x:null,l:null}}function U(e){var t=C,n=t.e;if(null!==n)for(var r of(t.e=null,n))Ge(r);return t.i=!0,C=t.p,{}}let Z=[];function B(){var e=Z;Z=[],function(e){for(var t=0;t<e.length;t++)e[t]()}(e)}function V(e){if(0===Z.length&&!te){var t=Z;queueMicrotask(()=>{t===Z&&B()})}Z.push(e)}function W(){for(;Z.length>0;)B()}function F(e){var t=gt;if(null===t)return vt.f|=O,e;if(0===(t.f&x)){if(0===(t.f&_))throw e;t.b.error(e)}else K(e,t)}function K(e,t){for(;null!==t;){if(0!==(t.f&_))try{return void t.b.error(e)}catch(n){e=n}t=t.parent}throw e}const H=new Set;let G=null,J=null,Q=null,X=[],Y=null,ee=!1,te=!1;class ne{committed=!1;current=new Map;previous=new Map;#e=new Set;#t=new Set;#n=0;#r=0;#i=null;#l=[];#s=[];skipped_effects=new Set;is_fork=!1;is_deferred(){return this.is_fork||this.#r>0}process(e){X=[],J=null,this.apply();var t={parent:null,effect:null,effects:[],render_effects:[],block_effects:[]};for(const n of e)this.#o(n,t);this.is_fork||this.#a(),this.is_deferred()?(this.#f(t.effects),this.#f(t.render_effects),this.#f(t.block_effects)):(J=this,G=null,oe(t.render_effects),oe(t.effects),J=null,this.#i?.resolve()),Q=null}#o(e,t){e.f^=m;for(var n=e.first;null!==n;){var r=n.f,i=!!(96&r),l=i&&0!==(r&m)||0!==(r&w)||this.skipped_effects.has(n);if(0!==(n.f&_)&&n.b?.is_pending()&&(t={parent:t,effect:n,effects:[],render_effects:[],block_effects:[]}),!l&&null!==n.fn){i?n.f^=m:4&r?t.effects.push(n):jt(n)&&(0!==(n.f&h)&&t.block_effects.push(n),$t(n));var s=n.first;if(null!==s){n=s;continue}}var o=n.parent;for(n=n.next;null===n&&null!==o;)o===t.effect&&(this.#f(t.effects),this.#f(t.render_effects),this.#f(t.block_effects),t=t.parent),n=o.next,o=o.parent}}#f(e){for(const t of e){(0!==(t.f&y)?this.#l:this.#s).push(t),this.#c(t.deps),It(t,m)}}#c(e){if(null!==e)for(const t of e)2&t.f&&0!==(t.f&q)&&(t.f^=q,this.#c(t.deps))}capture(e,t){this.previous.has(e)||this.previous.set(e,t),0===(e.f&O)&&(this.current.set(e,e.v),Q?.set(e,e.v))}activate(){G=this,this.apply()}deactivate(){G===this&&(G=null,Q=null)}flush(){if(this.activate(),X.length>0){if(ie(),null!==G&&G!==this)return}else 0===this.#n&&this.process([]);this.deactivate()}discard(){for(const e of this.#t)e(this);this.#t.clear()}#a(){if(0===this.#r){for(const e of this.#e)e();this.#e.clear()}0===this.#n&&this.#u()}#u(){if(H.size>1){this.previous.clear();var e=Q,t=!0,n={parent:null,effect:null,effects:[],render_effects:[],block_effects:[]};for(const e of H){if(e===this){t=!1;continue}const i=[];for(const[n,r]of this.current){if(e.current.has(n)){if(!t||r===e.current.get(n))continue;e.current.set(n,r)}i.push(n)}if(0===i.length)continue;const l=[...e.current.keys()].filter(e=>!this.current.has(e));if(l.length>0){var r=X;X=[];const t=new Set,s=new Map;for(const e of i)ae(e,l,t,s);if(X.length>0){G=e,e.apply();for(const t of X)e.#o(t,n);e.deactivate()}X=r}}G=null,Q=e}this.committed=!0,H.delete(this)}increment(e){this.#n+=1,e&&(this.#r+=1)}decrement(e){this.#n-=1,e&&(this.#r-=1),this.revive()}revive(){for(const e of this.#l)It(e,y),ce(e);for(const e of this.#s)It(e,b),ce(e);this.#l=[],this.#s=[],this.flush()}oncommit(e){this.#e.add(e)}ondiscard(e){this.#t.add(e)}settled(){return(this.#i??=d()).promise}static ensure(){if(null===G){const e=G=new ne;H.add(G),te||ne.enqueue(()=>{G===e&&e.flush()})}return G}static enqueue(e){V(e)}apply(){}}function re(e){var t=te;te=!0;try{for(;;){if(W(),0===X.length&&(G?.flush(),0===X.length))return void(Y=null);ie()}}finally{te=t}}function ie(){var t=ct;ee=!0;try{var n=0;for(ut(!0);X.length>0;){var r=ne.ensure();if(n++>1e3)e,le();r.process(X),we.clear()}}finally{ee=!1,ut(t),Y=null}}function le(){try{!function(){throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}()}catch(e){K(e,Y)}}let se=null;function oe(e){var t=e.length;if(0!==t){for(var n=0;n<t;){var r=e[n++];if(!(24576&r.f)&&jt(r)&&(se=new Set,$t(r),null===r.deps&&null===r.first&&null===r.nodes&&(null===r.teardown&&null===r.ac?it(r):r.fn=null),se?.size>0)){we.clear();for(const e of se){if(24576&e.f)continue;const t=[e];let n=e.parent;for(;null!==n;)se.has(n)&&(se.delete(n),t.push(n)),n=n.parent;for(let e=t.length-1;e>=0;e--){const n=t[e];24576&n.f||$t(n)}}se.clear()}}se=null}}function ae(e,t,n,r){if(!n.has(e)&&(n.add(e),null!==e.reactions))for(const i of e.reactions){const e=i.f;2&e?ae(i,t,n,r):4194320&e&&0===(e&y)&&fe(i,t,r)&&(It(i,y),ce(i))}}function fe(e,t,n){const r=n.get(e);if(void 0!==r)return r;if(null!==e.deps)for(const i of e.deps){if(t.includes(i))return!0;if(2&i.f&&fe(i,t,n))return n.set(i,!0),!0}return n.set(e,!1),!1}function ce(e){for(var t=Y=e;null!==t.parent;){var n=(t=t.parent).f;if(ee&&t===gt&&0!==(n&h)&&0===(n&S))return;if(96&n){if(0===(n&m))return;t.f^=m}}X.push(t)}class ue{parent;#n=!1;#d;#h=null;#v;#p;#_;#g=null;#m=null;#y=null;#b=null;#w=null;#k=0;#x=0;#E=!1;#P=null;#S=function(e){let t,n=0,r=xe(0);return()=>{Fe()&&(Mt(r),Je(()=>(0===n&&(t=Ct(()=>e(()=>Ae(r)))),n+=1,()=>{V(()=>{n-=1,0===n&&(t?.(),t=void 0,Ae(r))})})))}}(()=>(this.#P=xe(this.#k),()=>{this.#P=null}));constructor(e,t,n){this.#d=e,this.#v=t,this.#p=n,this.parent=gt.b,this.#n=!!this.#v.pending,this.#_=Xe(()=>{gt.b=this;var e=this.#A();try{this.#g=Ye(()=>n(e))}catch(t){this.error(t)}return this.#x>0?this.#q():this.#n=!1,()=>{this.#w?.remove()}},589952)}#j(){try{this.#g=Ye(()=>this.#p(this.#d))}catch(e){this.error(e)}this.#n=!1}#O(){const e=this.#v.pending;e&&(this.#m=Ye(()=>e(this.#d)),ne.enqueue(()=>{var e=this.#A();this.#g=this.#L(()=>(ne.ensure(),Ye(()=>this.#p(e)))),this.#x>0?this.#q():(lt(this.#m,()=>{this.#m=null}),this.#n=!1)}))}#A(){var e=this.#d;return this.#n&&(this.#w=Me(),this.#d.before(this.#w),e=this.#w),e}is_pending(){return this.#n||!!this.parent&&this.parent.is_pending()}has_pending_snippet(){return!!this.#v.pending}#L(e){var t=gt,n=vt,r=C;mt(this.#_),_t(this.#_),T(this.#_.ctx);try{return e()}catch(i){return F(i),null}finally{mt(t),_t(n),T(r)}}#q(){const e=this.#v.pending;null!==this.#g&&(this.#b=document.createDocumentFragment(),this.#b.append(this.#w),ft(this.#g,this.#b)),null===this.#m&&(this.#m=Ye(()=>e(this.#d)))}#z(e){this.has_pending_snippet()?(this.#x+=e,0===this.#x&&(this.#n=!1,this.#m&&lt(this.#m,()=>{this.#m=null}),this.#b&&(this.#d.before(this.#b),this.#b=null))):this.parent&&this.parent.#z(e)}update_pending_count(e){this.#z(e),this.#k+=e,this.#P&&Se(this.#P,this.#k)}get_effect_pending(){return this.#S(),Mt(this.#P)}error(e){var t=this.#v.onerror;let n=this.#v.failed;if(this.#E||!t&&!n)throw e;this.#g&&(nt(this.#g),this.#g=null),this.#m&&(nt(this.#m),this.#m=null),this.#y&&(nt(this.#y),this.#y=null);var r=!1,i=!1;const l=()=>{r?console.warn("https://svelte.dev/e/svelte_boundary_reset_noop"):(r=!0,i&&function(){throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}(),ne.ensure(),this.#k=0,null!==this.#y&&lt(this.#y,()=>{this.#y=null}),this.#n=this.has_pending_snippet(),this.#g=this.#L(()=>(this.#E=!1,Ye(()=>this.#p(this.#d)))),this.#x>0?this.#q():this.#n=!1)};var s=vt;try{_t(null),i=!0,t?.(e,l),i=!1}catch(e){K(e,this.#_&&this.#_.parent)}finally{_t(s)}n&&V(()=>{this.#y=this.#L(()=>{ne.ensure(),this.#E=!0;try{return Ye(()=>{n(this.#d,()=>e,()=>l)})}catch(e){return K(e,this.#_.parent),null}finally{this.#E=!1}})})}}function de(e,t,n,r){const i=pe;if(0!==n.length||0!==e.length){var l=G,s=gt,o=he();e.length>0?Promise.all(e).then(()=>{o();try{return a()}finally{l?.deactivate(),ve()}}):a()}else r(t.map(i));function a(){Promise.all(n.map(e=>function(e){let t=gt;null===t&&function(){throw new Error("https://svelte.dev/e/async_derived_orphan")}();var n=t.b,r=void 0,i=xe(M),l=!vt,s=new Map;return function(e){We(4718592,e,!0)}(()=>{var t=d();r=t.promise;try{Promise.resolve(e()).then(t.resolve,t.reject).then(()=>{o===G&&o.committed&&o.deactivate(),ve()})}catch(c){t.reject(c),ve()}var o=G;if(l){var a=!n.is_pending();n.update_pending_count(1),o.increment(a),s.get(o)?.reject($),s.delete(o),s.set(o,t)}const f=(e,t=void 0)=>{if(o.activate(),t)t!==$&&(i.f|=O,Se(i,t));else{0!==(i.f&O)&&(i.f^=O),Se(i,e);for(const[e,t]of s){if(s.delete(e),e===o)break;t.reject($)}}l&&(n.update_pending_count(-1),o.decrement(a))};t.promise.then(f,e=>f(null,e||"unknown"))}),Ke(()=>{for(const e of s.values())e.reject($)}),new Promise(e=>{function t(n){function l(){n===r?e(i):t(r)}n.then(l,l)}t(r)})}(e))).then(e=>{o();try{r([...t.map(i),...e])}catch(n){0===(s.f&k)&&K(n,s)}l?.deactivate(),ve()}).catch(e=>{K(e,s)})}}function he(){var e=gt,t=vt,n=C,r=G;return function(i=!0){mt(e),_t(t),T(n),i&&r?.activate()}}function ve(){mt(null),_t(null),T(null)}function pe(e){var t=null!==vt&&2&vt.f?vt:null;null!==gt&&(gt.f|=A);return{ctx:C,deps:null,effects:null,equals:R,f:2050,fn:e,reactions:null,rv:0,v:M,wv:0,parent:t??gt,ac:null}}function _e(e){const t=pe(e);return bt(t),t}function ge(e){var t=e.effects;if(null!==t){e.effects=null;for(var n=0;n<t.length;n+=1)nt(t[n])}}function me(e){var t,n=gt;mt(function(e){for(var t=e.parent;null!==t;){if(!(2&t.f))return 0===(t.f&k)?t:null;t=t.parent}return null}(e));try{e.f&=-32769,ge(e),t=Lt(e)}finally{mt(n)}return t}function ye(e){var t=me(e);(e.equals(t)||(G?.is_fork||(e.v=t),e.wv=qt()),dt)||(null!==Q?(Fe()||G?.is_fork)&&Q.set(e,t):It(e,0===(e.f&g)?b:m))}let be=new Set;const we=new Map;let ke=!1;function xe(e,t){return{f:0,v:e,reactions:null,equals:R,rv:0,wv:0}}function Ee(e,t){const n=xe(e);return bt(n),n}function Pe(e,t,n=!1){return null===vt||pt&&0===(vt.f&P)||!(4325394&vt.f)||yt?.includes(e)||function(){throw new Error("https://svelte.dev/e/state_unsafe_mutation")}(),Se(e,n?je(t):t)}function Se(e,t){if(!e.equals(t)){var n=e.v;dt?we.set(e,t):we.set(e,n),e.v=t;var r=ne.ensure();r.capture(e,n),2&e.f&&(0!==(e.f&y)&&me(e),It(e,0!==(e.f&g)?m:b)),e.wv=qt(),qe(e,y),null===gt||0===(gt.f&m)||96&gt.f||(null===xt?function(e){xt=e}([e]):xt.push(e)),!r.is_fork&&be.size>0&&!ke&&function(){ke=!1;var e=ct;ut(!0);const t=Array.from(be);try{for(const e of t)0!==(e.f&m)&&It(e,b),jt(e)&&$t(e)}finally{ut(e)}be.clear()}()}return t}function Ae(e){Pe(e,e.v+1)}function qe(e,t){var n=e.reactions;if(null!==n)for(var r=n.length,i=0;i<r;i++){var l=n[i],s=l.f,o=0===(s&y);if(o&&It(l,t),2&s){var a=l;Q?.delete(a),0===(s&q)&&(s&g&&(l.f|=q),qe(a,b))}else o&&(0!==(s&h)&&null!==se&&se.add(l),ce(l))}}function je(e){if("object"!=typeof e||null===e||L in e)return e;const n=f(e);if(n!==o&&n!==a)return e;var r=new Map,i=t(e),s=Ee(0),c=St,u=e=>{if(St===c)return e();var t=vt,n=St;_t(null),At(c);var r=e();return _t(t),At(n),r};return i&&r.set("length",Ee(e.length)),new Proxy(e,{defineProperty(e,t,n){"value"in n&&!1!==n.configurable&&!1!==n.enumerable&&!1!==n.writable||function(){throw new Error("https://svelte.dev/e/state_descriptors_fixed")}();var i=r.get(t);return void 0===i?i=u(()=>{var e=Ee(n.value);return r.set(t,e),e}):Pe(i,n.value,!0),!0},deleteProperty(e,t){var n=r.get(t);if(void 0===n){if(t in e){const e=u(()=>Ee(M));r.set(t,e),Ae(s)}}else Pe(n,M),Ae(s);return!0},get(t,n,i){if(n===L)return e;var s=r.get(n),o=n in t;if(void 0!==s||o&&!l(t,n)?.writable||(s=u(()=>Ee(je(o?t[n]:M))),r.set(n,s)),void 0!==s){var a=Mt(s);return a===M?void 0:a}return Reflect.get(t,n,i)},getOwnPropertyDescriptor(e,t){var n=Reflect.getOwnPropertyDescriptor(e,t);if(n&&"value"in n){var i=r.get(t);i&&(n.value=Mt(i))}else if(void 0===n){var l=r.get(t),s=l?.v;if(void 0!==l&&s!==M)return{enumerable:!0,configurable:!0,value:s,writable:!0}}return n},has(e,t){if(t===L)return!0;var n=r.get(t),i=void 0!==n&&n.v!==M||Reflect.has(e,t);if((void 0!==n||null!==gt&&(!i||l(e,t)?.writable))&&(void 0===n&&(n=u(()=>Ee(i?je(e[t]):M)),r.set(t,n)),Mt(n)===M))return!1;return i},set(e,t,n,o){var a=r.get(t),f=t in e;if(i&&"length"===t)for(var c=n;c<a.v;c+=1){var d=r.get(c+"");void 0!==d?Pe(d,M):c in e&&(d=u(()=>Ee(M)),r.set(c+"",d))}void 0===a?f&&!l(e,t)?.writable||(Pe(a=u(()=>Ee(void 0)),je(n)),r.set(t,a)):(f=a.v!==M,Pe(a,u(()=>je(n))));var h=Reflect.getOwnPropertyDescriptor(e,t);if(h?.set&&h.set.call(o,n),!f){if(i&&"string"==typeof t){var v=r.get("length"),p=Number(t);Number.isInteger(p)&&p>=v.v&&Pe(v,p+1)}Ae(s)}return!0},ownKeys(e){Mt(s);var t=Reflect.ownKeys(e).filter(e=>{var t=r.get(e);return void 0===t||t.v!==M});for(var[n,i]of r)i.v===M||n in e||t.push(n);return t},setPrototypeOf(){!function(){throw new Error("https://svelte.dev/e/state_prototype_fixed")}()}})}function Oe(e){try{if(null!==e&&"object"==typeof e&&L in e)return e[L]}catch{}return e}var Le,ze,Ne,$e;function Me(e=""){return document.createTextNode(e)}function De(e){return Ne.call(e)}function Re(e){return $e.call(e)}function Ce(e,t){return De(e)}function Te(e,t=!1){var n=De(e);return n instanceof Comment&&""===n.data?Re(n):n}function Ie(e,t=1,n=!1){let r=e;for(;t--;)r=Re(r);return r}let Ue=!1;function Ze(e){var t=vt,n=gt;_t(null),mt(null);try{return e()}finally{_t(t),mt(n)}}function Be(e,t,n,r=n){e.addEventListener(t,()=>Ze(n));const i=e.__on_r;e.__on_r=i?()=>{i(),r(!0)}:()=>r(!0),Ue||(Ue=!0,document.addEventListener("reset",e=>{Promise.resolve().then(()=>{if(!e.defaultPrevented)for(const t of e.target.elements)t.__on_r?.()})},{capture:!0}))}function Ve(e){null===gt&&(null===vt&&function(){throw new Error("https://svelte.dev/e/effect_orphan")}(),function(){throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}()),dt&&function(){throw new Error("https://svelte.dev/e/effect_in_teardown")}()}function We(e,t,n){var r=gt;null!==r&&0!==(r.f&w)&&(e|=w);var i={ctx:C,deps:null,nodes:null,f:e|y|g,first:null,fn:t,last:null,next:null,parent:r,b:r&&r.b,prev:null,teardown:null,wv:0,ac:null};if(n)try{$t(i),i.f|=x}catch(l){throw nt(i),l}else null!==t&&ce(i);var l=i;if(n&&null===l.deps&&null===l.teardown&&null===l.nodes&&l.first===l.last&&0===(l.f&A)&&(l=l.first,0!==(e&h)&&0!==(e&E)&&null!==l&&(l.f|=E)),null!==l&&(l.parent=r,null!==r&&function(e,t){var n=t.last;null===n?t.last=t.first=e:(n.next=e,e.prev=n,t.last=e)}(l,r),null!==vt&&2&vt.f&&0===(e&p))){var s=vt;(s.effects??=[]).push(l)}return i}function Fe(){return null!==vt&&!pt}function Ke(e){const t=We(8,null,!1);return It(t,m),t.teardown=e,t}function He(e){Ve();var t=gt.f;if(!(!vt&&0!==(t&v)&&0===(t&x)))return Ge(e);var n=C;(n.e??=[]).push(e)}function Ge(e){return We(1048580,e,!1)}function Je(e,t=0){return We(8|t,e,!0)}function Qe(e,t=[],n=[],r=[]){de(r,t,n,t=>{We(8,()=>e(...t.map(Mt)),!0)})}function Xe(e,t=0){return We(h|t,e,!0)}function Ye(e){return We(524320,e,!0)}function et(e){var t=e.teardown;if(null!==t){const e=dt,n=vt;ht(!0),_t(null);try{t.call(null)}finally{ht(e),_t(n)}}}function tt(e,t=!1){var n=e.first;for(e.first=e.last=null;null!==n;){const e=n.ac;null!==e&&Ze(()=>{e.abort($)});var r=n.next;0!==(n.f&p)?n.parent=null:nt(n,t),n=r}}function nt(e,t=!0){var n=!1;!t&&0===(e.f&S)||null===e.nodes||null===e.nodes.end||(rt(e.nodes.start,e.nodes.end),n=!0),tt(e,t&&!n),Nt(e,0),It(e,k);var r=e.nodes&&e.nodes.t;if(null!==r)for(const l of r)l.stop();et(e);var i=e.parent;null!==i&&null!==i.first&&it(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=null}function rt(e,t){for(;null!==e;){var n=e===t?null:Re(e);e.remove(),e=n}}function it(e){var t=e.parent,n=e.prev,r=e.next;null!==n&&(n.next=r),null!==r&&(r.prev=n),null!==t&&(t.first===e&&(t.first=r),t.last===e&&(t.last=n))}function lt(e,t,n=!0){var r=[];st(e,r,!0);var i=()=>{n&&nt(e),t&&t()},l=r.length;if(l>0){var s=()=>--l||i();for(var o of r)o.out(s)}else i()}function st(e,t,n){if(0===(e.f&w)){e.f^=w;var r=e.nodes&&e.nodes.t;if(null!==r)for(const e of r)(e.is_global||n)&&t.push(e);for(var i=e.first;null!==i;){var l=i.next;st(i,t,!!(0!==(i.f&E)||0!==(i.f&v)&&0!==(e.f&h))&&n),i=l}}}function ot(e){at(e,!0)}function at(e,t){if(0!==(e.f&w)){e.f^=w,0===(e.f&m)&&(It(e,y),ce(e));for(var n=e.first;null!==n;){var r=n.next;at(n,!!(0!==(n.f&E)||0!==(n.f&v))&&t),n=r}var i=e.nodes&&e.nodes.t;if(null!==i)for(const e of i)(e.is_global||t)&&e.in()}}function ft(e,t){if(e.nodes)for(var n=e.nodes.start,r=e.nodes.end;null!==n;){var i=n===r?null:Re(n);t.append(n),n=i}}let ct=!1;function ut(e){ct=e}let dt=!1;function ht(e){dt=e}let vt=null,pt=!1;function _t(e){vt=e}let gt=null;function mt(e){gt=e}let yt=null;function bt(e){null!==vt&&(null===yt?yt=[e]:yt.push(e))}let wt=null,kt=0,xt=null;let Et=1,Pt=0,St=Pt;function At(e){St=e}function qt(){return++Et}function jt(e){var t=e.f;if(0!==(t&y))return!0;if(2&t&&(e.f&=-32769),0!==(t&b)){var n=e.deps;if(null!==n)for(var r=n.length,i=0;i<r;i++){var l=n[i];if(jt(l)&&ye(l),l.wv>e.wv)return!0}0!==(t&g)&&null===Q&&It(e,m)}return!1}function Ot(e,t,n=!0){var r=e.reactions;if(null!==r&&!yt?.includes(e))for(var i=0;i<r.length;i++){var l=r[i];2&l.f?Ot(l,t,!1):t===l&&(n?It(l,y):0!==(l.f&m)&&It(l,b),ce(l))}}function Lt(e){var t=wt,n=kt,r=xt,i=vt,l=yt,s=C,o=pt,a=St,f=e.f;wt=null,kt=0,xt=null,vt=96&f?null:e,yt=null,T(e.ctx),pt=!1,St=++Pt,null!==e.ac&&(Ze(()=>{e.ac.abort($)}),e.ac=null);try{e.f|=j;var c=(0,e.fn)(),u=e.deps;if(null!==wt){var d;if(Nt(e,kt),null!==u&&kt>0)for(u.length=kt+wt.length,d=0;d<wt.length;d++)u[kt+d]=wt[d];else e.deps=u=wt;if(Fe()&&0!==(e.f&g))for(d=kt;d<u.length;d++)(u[d].reactions??=[]).push(e)}else null!==u&&kt<u.length&&(Nt(e,kt),u.length=kt);if(!(null===xt||pt||null===u||6146&e.f))for(d=0;d<xt.length;d++)Ot(xt[d],e);return null!==i&&i!==e&&(Pt++,null!==xt&&(null===r?r=xt:r.push(...xt))),0!==(e.f&O)&&(e.f^=O),c}catch(h){return F(h)}finally{e.f^=j,wt=t,kt=n,xt=r,vt=i,yt=l,T(s),pt=o,St=a}}function zt(e,t){let r=t.reactions;if(null!==r){var i=n.call(r,e);if(-1!==i){var l=r.length-1;0===l?r=t.reactions=null:(r[i]=r[l],r.pop())}}null===r&&2&t.f&&(null===wt||!wt.includes(t))&&(It(t,b),0!==(t.f&g)&&(t.f^=g,t.f&=-32769),ge(t),Nt(t,0))}function Nt(e,t){var n=e.deps;if(null!==n)for(var r=t;r<n.length;r++)zt(e,n[r])}function $t(e){var t=e.f;if(0===(t&k)){It(e,m);var n=gt,r=ct;gt=e,ct=!0;try{16777232&t?function(e){for(var t=e.first;null!==t;){var n=t.next;0===(t.f&v)&&nt(t),t=n}}(e):tt(e),et(e);var i=Lt(e);e.teardown="function"==typeof i?i:null,e.wv=Et}finally{ct=r,gt=n}}}function Mt(e){var t=!!(2&e.f);if(null!==vt&&!pt&&(!(null!==gt&&0!==(gt.f&k))&&!yt?.includes(e))){var n=vt.deps;if(0!==(vt.f&j))e.rv<Pt&&(e.rv=Pt,null===wt&&null!==n&&n[kt]===e?kt++:null===wt?wt=[e]:wt.includes(e)||wt.push(e));else{(vt.deps??=[]).push(e);var r=e.reactions;null===r?e.reactions=[vt]:r.includes(vt)||r.push(vt)}}if(dt){if(we.has(e))return we.get(e);if(t){var i=e,l=i.v;return(0===(i.f&m)&&null!==i.reactions||Rt(i))&&(l=me(i)),we.set(i,l),l}}else t&&(!Q?.has(e)||G?.is_fork&&!Fe())&&(jt(i=e)&&ye(i),ct&&Fe()&&0===(i.f&g)&&Dt(i));if(Q?.has(e))return Q.get(e);if(0!==(e.f&O))throw e.v;return e.v}function Dt(e){if(null!==e.deps){e.f^=g;for(const t of e.deps)(t.reactions??=[]).push(e),2&t.f&&0===(t.f&g)&&Dt(t)}}function Rt(e){if(e.v===M)return!0;if(null===e.deps)return!1;for(const t of e.deps){if(we.has(t))return!0;if(2&t.f&&Rt(t))return!0}return!1}function Ct(e){var t=pt;try{return pt=!0,e()}finally{pt=t}}const Tt=-7169;function It(e,t){e.f=e.f&Tt|t}const Ut=["touchstart","touchmove"];function Zt(e){return Ut.includes(e)}const Bt=new Set,Vt=new Set;function Wt(e){for(var t=0;t<e.length;t++)Bt.add(e[t]);for(var n of Vt)n(e)}let Ft=null;function Kt(e){var t=this,n=t.ownerDocument,r=e.type,l=e.composedPath?.()||[],s=l[0]||e.target;Ft=e;var o=0,a=Ft===e&&e.__root;if(a){var f=l.indexOf(a);if(-1!==f&&(t===document||t===window))return void(e.__root=t);var c=l.indexOf(t);if(-1===c)return;f<=c&&(o=f)}if((s=l[o]||e.target)!==t){i(e,"currentTarget",{configurable:!0,get:()=>s||n});var u=vt,d=gt;_t(null),mt(null);try{for(var h,v=[];null!==s;){var p=s.assignedSlot||s.parentNode||s.host||null;try{var _=s["__"+r];null==_||s.disabled&&e.target!==s||_.call(s,e)}catch(g){h?v.push(g):h=g}if(e.cancelBubble||p===t||null===p)break;s=p}if(h){for(let e of v)queueMicrotask(()=>{throw e});throw h}}finally{e.__root=t,delete e.currentTarget,_t(u),mt(d)}}}function Ht(e){var t=document.createElement("template");return t.innerHTML=e.replaceAll("<!>","\x3c!----\x3e"),t.content}function Gt(e,t){var n=gt;null===n.nodes&&(n.nodes={start:e,end:t,a:null,t:null})}function Jt(e,t){var n,r=!!(1&t),i=!!(2&t),l=!e.startsWith("<!>");return()=>{void 0===n&&(n=Ht(l?e:"<!>"+e),r||(n=De(n)));var t=i||ze?document.importNode(n,!0):n.cloneNode(!0);r?Gt(De(t),t.lastChild):Gt(t,t);return t}}function Qt(e=""){var t=Me(e+"");return Gt(t,t),t}function Xt(){var e=document.createDocumentFragment(),t=document.createComment(""),n=Me();return e.append(t,n),Gt(t,n),e}function Yt(e,t){null!==e&&e.before(t)}function en(e,t){var n=null==t?"":"object"==typeof t?t+"":t;n!==(e.__t??=e.nodeValue)&&(e.__t=n,e.nodeValue=n+"")}const tn=new Map;let nn=new WeakMap;class rn{anchor;#N=new Map;#$=new Map;#M=new Map;#D=new Set;#R=!0;constructor(e,t=!0){this.anchor=e,this.#R=t}#u=()=>{var e=G;if(this.#N.has(e)){var t=this.#N.get(e),n=this.#$.get(t);if(n)ot(n),this.#D.delete(t);else{var r=this.#M.get(t);r&&(this.#$.set(t,r.effect),this.#M.delete(t),r.fragment.lastChild.remove(),this.anchor.before(r.fragment),n=r.effect)}for(const[t,n]of this.#N){if(this.#N.delete(t),t===e)break;const r=this.#M.get(n);r&&(nt(r.effect),this.#M.delete(n))}for(const[e,r]of this.#$){if(e===t||this.#D.has(e))continue;const i=()=>{if(Array.from(this.#N.values()).includes(e)){var t=document.createDocumentFragment();ft(r,t),t.append(Me()),this.#M.set(e,{effect:r,fragment:t})}else nt(r);this.#D.delete(e),this.#$.delete(e)};this.#R||!n?(this.#D.add(e),lt(r,i,!1)):i()}}};#C=e=>{this.#N.delete(e);const t=Array.from(this.#N.values());for(const[n,r]of this.#M)t.includes(n)||(nt(r.effect),this.#M.delete(n))};ensure(e,t){var n=G;!t||this.#$.has(e)||this.#M.has(e)||this.#$.set(e,Ye(()=>t(this.anchor)));this.#N.set(n,e),this.#u()}}function ln(e,t,n,r,i){var l=M,s=xe(l),o=xe(l),a=new rn(e);Xe(()=>{var e=t(),l=!1;if(function(e){return"function"==typeof e?.then}(e)){var f=he(),c=!1;const t=e=>{if(!l){c=!0,f(!1),ne.ensure();try{e()}finally{ve(),te||re()}}};e.then(e=>{t(()=>{Se(s,e),a.ensure(1,r&&(e=>r(e,s)))})},e=>{t(()=>{if(Se(o,e),a.ensure(1,i&&(e=>i(e,o))),!i)throw o.v})}),V(()=>{c||t(()=>{a.ensure(0,n)})})}else Se(s,e),a.ensure(1,r&&(e=>r(e,s)));return()=>{l=!0}})}function sn(e,t,n=!1){var r=new rn(e);function i(e,t){r.ensure(e,t)}Xe(()=>{var e=!1;t((t,n=!0)=>{e=!0,i(n,t)}),e||i(!1,null)},n?E:0)}function on(e,t,...n){var r=new rn(e);Xe(()=>{const e=t()??null;r.ensure(e,e&&(t=>e(t,...n)))},E)}function an(e,t,n){var r=new rn(e);Xe(()=>{var e=t()??null;r.ensure(e,e&&(t=>n(t,e)))},E)}const fn=[..." \t\n\r\fย \v\ufeff"];function cn(e,t,n,r,i,l){var s=e.__className;if(s!==n||void 0===s){var o=function(e,t,n){var r=""+e;if(n)for(var i in n)if(n[i])r=r?r+" "+i:i;else if(r.length)for(var l=i.length,s=0;(s=r.indexOf(i,s))>=0;){var o=s+l;0!==s&&!fn.includes(r[s-1])||o!==r.length&&!fn.includes(r[o])?s=o:r=(0===s?"":r.substring(0,s))+r.substring(o+1)}return""===r?null:r}(n,0,l);null==o?e.removeAttribute("class"):e.className=o,e.__className=n}else if(l&&i!==l)for(var a in l){var f=!!l[a];null!=i&&f===!!i[a]||e.classList.toggle(a,f)}return l}const un=Symbol("is custom element"),dn=Symbol("is html");function hn(e,t,n,r){var i=function(e){return e.__attributes??={[un]:e.nodeName.includes("-"),[dn]:e.namespaceURI===D}}(e);i[t]!==(i[t]=n)&&("loading"===t&&(e[N]=n),null==n?e.removeAttribute(t):"string"!=typeof n&&_n(e).includes(t)?e[t]=n:e.setAttribute(t,n))}function vn(e,t,n){var r=vt,i=gt;_t(null),mt(null);try{"style"!==t&&(pn.has(e.getAttribute("is")||e.nodeName)||!customElements||customElements.get(e.getAttribute("is")||e.tagName.toLowerCase())?_n(e).includes(t):n&&"object"==typeof n)?e[t]=n:hn(e,t,null==n?n:String(n))}finally{_t(r),mt(i)}}var pn=new Map;function _n(e){var t,n=e.getAttribute("is")||e.nodeName,r=pn.get(n);if(r)return r;pn.set(n,r=[]);for(var i=e,l=Element.prototype;l!==i;){for(var o in t=s(i))t[o].set&&r.push(o);i=f(i)}return r}function gn(e,t,n=t){var r=new WeakSet;Be(e,"input",async i=>{var l=i?e.defaultValue:e.value;if(l=bn(e)?wn(l):l,n(l),null!==G&&r.add(G),await async function(){await Promise.resolve(),re()}(),l!==(l=t())){var s=e.selectionStart,o=e.selectionEnd,a=e.value.length;if(e.value=l??"",null!==o){var f=e.value.length;s===o&&o===a&&f>a?(e.selectionStart=f,e.selectionEnd=f):(e.selectionStart=s,e.selectionEnd=Math.min(o,f))}}}),null==Ct(t)&&e.value&&(n(bn(e)?wn(e.value):e.value),null!==G&&r.add(G)),Je(()=>{var n=t();if(e===document.activeElement){var i=J??G;if(r.has(i))return}bn(e)&&n===wn(e.value)||("date"!==e.type||n||e.value)&&n!==e.value&&(e.value=n??"")})}const mn=new Set;function yn(e,t,n,r,i=r){var l="checkbox"===n.getAttribute("type"),s=e;if(null!==t)for(var o of t)s=s[o]??=[];s.push(n),Be(n,"change",()=>{var e=n.__value;l&&(e=function(e,t,n){for(var r=new Set,i=0;i<e.length;i+=1)e[i].checked&&r.add(e[i].__value);n||r.delete(t);return Array.from(r)}(s,e,n.checked)),i(e)},()=>i(l?[]:null)),Je(()=>{var e,t,i=r();l?(i=i||[],n.checked=i.includes(n.__value)):n.checked=(e=n.__value,t=i,Object.is(Oe(e),Oe(t)))}),Ke(()=>{var e=s.indexOf(n);-1!==e&&s.splice(e,1)}),mn.has(s)||(mn.add(s),V(()=>{s.sort((e,t)=>4===e.compareDocumentPosition(t)?-1:1),mn.delete(s)})),V(()=>{})}function bn(e){var t=e.type;return"number"===t||"range"===t}function wn(e){return""===e?null:+e}let kn=!1;function xn(e,t,n,r){var i,s,o=r,a=!0,f=L in e||z in e;i=l(e,t)?.set??(f&&t in e?n=>e[t]=n:void 0);var c,u=!1;if([s,u]=function(e){var t=kn;try{return kn=!1,[e(),kn]}finally{kn=t}}(()=>e[t]),c=()=>{var n=e[t];return void 0===n?(a&&(a=!1,o=r),o):(a=!0,n)},i){var d=e.$$legacy;return function(e,t){return arguments.length>0?((!t||d||u)&&i(t?c():e),e):c()}}var h=!1,v=pe(()=>(h=!1,c()));Mt(v);var p=gt;return function(e,t){if(arguments.length>0){const n=t?Mt(v):je(e);return Pe(v,n),h=!0,void 0!==o&&(o=n),e}return dt&&h||0!==(p.f&k)?v.v:Mt(v)}}const En={},Pn=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){const e=document.getElementsByTagName("link"),l=document.querySelector("meta[property=csp-nonce]"),s=l?.nonce||l?.getAttribute("nonce");i=t.map(t=>{if(t=function(e,t){return new URL(e,t).href}(t,n),t in En)return;En[t]=!0;const r=t.endsWith(".css"),i=r?'[rel="stylesheet"]':"";if(n)for(let n=e.length-1;n>=0;n--){const i=e[n];if(i.href===t&&(!r||"stylesheet"===i.rel))return}else if(document.querySelector(`link[href="${t}"]${i}`))return;const l=document.createElement("link");return l.rel=r?"stylesheet":"modulepreload",r||(l.as="script"),l.crossOrigin="",l.href=t,s&&l.setAttribute("nonce",s),document.head.appendChild(l),r?new Promise((e,n)=>{l.addEventListener("load",e),l.addEventListener("error",()=>n(new Error(`Unable to preload CSS for ${t}`)))}):void 0}),r=Promise.all(i.map(e=>Promise.resolve(e).then(e=>({status:"fulfilled",value:e}),e=>({status:"rejected",reason:e}))))}var i;function l(e){const t=new Event("vite:preloadError",{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(const e of t||[])"rejected"===e.status&&l(e.reason);return e().catch(l)})};"undefined"!=typeof window&&((window.__svelte??={}).v??=new Set).add("5");const Sn=/^[234567abcdefghij][234567abcdefghijklmnopqrstuvwxyz]{12}$/,An=/^did:([a-z]+):([a-zA-Z0-9._:%-]*[a-zA-Z0-9._-])$/,qn=/^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/,jn=e=>(e=>e.length>=7&&e.length<=2048&&An.test(e))(e)||(e=>e.length>=3&&e.length<=253&&qn.test(e))(e),On=e=>{const t=Ln(e);if(!t)return null;let n;if("bsky.app"===t.host||"staging.bsky.app"===t.host||"main.bsky.dev"===t.host){if(n=/^\/profile\/([^/]+)\/post\/([^/]+)\/?$/.exec(t.pathname))return jn(n[1])&&(e=>13===e.length&&Sn.test(e))(n[2])?{type:"post",author:n[1],rkey:n[2]}:null;if(n=/^\/profile\/([^/]+)\/?$/.exec(t.pathname))return jn(n[1])?{type:"profile",actor:n[1]}:null}return null},Ln=e=>{let t;if("parse"in URL)t=URL.parse(e);else try{t=new URL(e)}catch{}return!t||"https:"!==t.protocol&&"http:"!==t.protocol?null:t};var zn=Jt("<div><!></div>");function Nn(e,t){var n=zn();let r;on(Ce(n),()=>t.children),Qe(()=>r=cn(n,0,"banner svelte-4gizvm",0,r,{"type-alert":"alert"===t.type,"type-inform":"inform"===t.type})),Yt(e,n)}var $n=function(e,t,n="svg"){var r,i=`<${n}>${e.startsWith("<!>")?"<!>"+e:e}</${n}>`;return()=>{if(!r){var e=De(Ht(i));r=De(e)}var t=r.cloneNode(!0);return Gt(t,t),t}}('<svg viewBox="0 0 32 32" class="circular-spinner svelte-rq8vha"><circle cx="16" cy="16" fill="none" r="14" stroke-width="4" class="background svelte-rq8vha"></circle><circle cx="16" cy="16" fill="none" r="14" stroke-width="4" stroke-dasharray="80px" stroke-dashoffset="60px" class="accented svelte-rq8vha"></circle></svg>',0,"svg");function Mn(e,t){Yt(e,$n())}var Dn=Jt('<div class="field svelte-1wzaqos"><label class="input-wrapper svelte-1wzaqos"><span class="label svelte-1wzaqos"> </span> <!></label></div>');const Rn=new WeakMap;function Cn(e,t){I(t,!0);const n=_e(()=>(e=>{let t=Rn.get(e);return void 0===t&&Rn.set(e,t=e().then(e=>e.default)),t})(t.loader));var r=Xt();ln(Te(r),()=>Mt(n),e=>{var n=Xt();on(Te(n),()=>t.fallback),Yt(e,n)},(e,n)=>{var r=Xt();on(Te(r),()=>t.children,()=>Mt(n)),Yt(e,r)},(e,n)=>{var r=Xt();on(Te(r),()=>t.boundary,()=>Mt(n)),Yt(e,r)}),Yt(e,r),U()}var Tn=Jt('<input class="text-input svelte-1e5va0l"/>');const In=e=>{Mn(e)},Un=(e,t=u)=>{Nn(e,{type:"alert",children:(e,n)=>{var r=Qt();Qe(()=>en(r,""+t())),Yt(e,r)}})},Zn=()=>Pn(()=>import("./PostDisplay-CqTUAVla.js"),__vite__mapDeps([0,1,2,3,4]),import.meta.url),Bn=()=>Pn(()=>import("./ProfileCardDisplay-BpCMWdM3.js"),__vite__mapDeps([5,1,2,6]),import.meta.url),Vn=()=>Pn(()=>import("./ProfileFeedDisplay-QaaAcc9o.js"),__vite__mapDeps([7,1,2,3,8]),import.meta.url);var Wn=Jt('<fieldset class="choices svelte-1n46o8q"><label class="choice svelte-1n46o8q"><input type="radio" name="profile-type" class="svelte-1n46o8q"/> <span>Profile feed</span></label> <label class="choice svelte-1n46o8q"><input type="radio" name="profile-type" class="svelte-1n46o8q"/> <span>Profile card</span></label></fieldset>'),Fn=Jt('<div class="app svelte-1n46o8q"><h1 class="header svelte-1n46o8q"><code>&lt;bluesky-embed&gt;</code></h1> <!> <!> <main class="main svelte-1n46o8q"><!></main> <footer class="footer svelte-1n46o8q"><span>made with โค๏ธ by <a href="https://bsky.app/profile/did:plc:ia76kvnndjutgedggx2ibrem" class="svelte-1n46o8q">@mary.my.id</a></span> <span aria-hidden="true">ยท</span> <span><a href="https://github.com/mary-ext/bluesky-embed" class="svelte-1n46o8q">source code</a></span> <span aria-hidden="true">ยท</span> <span>MIT License</span></footer></div>');!function(e,t){(function(e,{target:t,anchor:n,props:i={},events:s,context:o,intro:a=!0}){!function(){if(void 0===Le){Le=window,ze=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,n=Text.prototype;Ne=l(t,"firstChild").get,$e=l(t,"nextSibling").get,c(e)&&(e.__click=void 0,e.__className=void 0,e.__attributes=null,e.__style=void 0,e.__e=void 0),c(n)&&(n.__t=void 0)}}();var f=new Set,u=e=>{for(var n=0;n<e.length;n++){var r=e[n];if(!f.has(r)){f.add(r);var i=Zt(r);t.addEventListener(r,Kt,{passive:i});var l=tn.get(r);void 0===l?(document.addEventListener(r,Kt,{passive:i}),tn.set(r,1)):tn.set(r,l+1)}}};u(r(Bt)),Vt.add(u);var d=void 0,h=function(e){ne.ensure();const t=We(524352,e,!0);return(e={})=>new Promise(n=>{e.outro?lt(t,()=>{nt(t),n(void 0)}):(nt(t),n(void 0))})}(()=>{var r=n??t.appendChild(Me());return function(e,t,n){new ue(e,t,n)}(r,{pending:()=>{}},t=>{o&&(I({}),C.c=o);s&&(i.$$events=s),d=e(t,i)||{},o&&U()}),()=>{for(var e of f){t.removeEventListener(e,Kt);var i=tn.get(e);0===--i?(document.removeEventListener(e,Kt),tn.delete(e)):tn.set(e,i)}Vt.delete(u),r!==n&&r.parentNode?.removeChild(r)}});nn.set(d,h)})(e,t)}(function(e,t){I(t,!0);const n=[],r="https://bsky.app/profile/did:plc:ragtjsm2j2vknwkz3zp4oxrd/post/3kj2umze7zj2n";let i=Ee(""),l=Ee("feed");const s=_e(()=>On(Mt(i)||r));var o=Fn(),a=Ie(Ce(o),2);!function(e,t){var n=Dn(),r=Ce(n),i=Ce(r),l=Ce(i);on(Ie(i,2),()=>t.children),Qe(()=>en(l,t.label)),Yt(e,n)}(a,{label:"Bluesky post or profile URL",children:(e,t)=>{!function(e,t){I(t,!0);let n=xn(t,"value");var r=Tn();Qe(()=>{hn(r,"type",t.type),hn(r,"placeholder",t.placeholder)}),gn(r,n),Yt(e,r),U()}(e,{type:"url",placeholder:r,get value(){return Mt(i)},set value(e){Pe(i,e,!0)}})}});var f=Ie(a,2),c=e=>{var t=Wn(),r=Ce(t),i=Ce(r);i.value=i.__value="feed";var s=Ce(Ie(r,2));s.value=s.__value="card",yn(n,[],i,()=>Mt(l),e=>Pe(l,e)),yn(n,[],s,()=>Mt(l),e=>Pe(l,e)),Yt(e,t)};sn(f,e=>{Mt(s)&&"profile"===Mt(s).type&&e(c)});var d=Ce(Ie(f,2)),h=e=>{Nn(e,{type:"alert",children:(e,t)=>{Yt(e,Qt("Invalid URL, did you type it correctly?"))}})},v=e=>{var t=Xt(),n=Te(t),r=e=>{{const t=(e,t=u)=>{var n=Xt();an(Te(n),t,(e,t)=>{t(e,{get matched(){return Mt(s)}})}),Yt(e,n)};Cn(e,{loader:Zn,get fallback(){return In},get boundary(){return Un},children:t,$$slots:{default:!0}})}},i=e=>{var t=Xt(),n=Te(t),r=e=>{{const t=(e,t=u)=>{var n=Xt();an(Te(n),t,(e,t)=>{t(e,{get matched(){return Mt(s)}})}),Yt(e,n)};let n=_e(()=>"card"===Mt(l)?Bn:Vn);Cn(e,{get loader(){return Mt(n)},get fallback(){return In},get boundary(){return Un},children:t,$$slots:{default:!0}})}};sn(n,e=>{"profile"===Mt(s).type&&e(r)},!0),Yt(e,t)};sn(n,e=>{"post"===Mt(s).type?e(r):e(i,!1)},!0),Yt(e,t)};sn(d,e=>{Mt(s)?e(v,!1):e(h)}),Yt(e,o),U()},{target:document.getElementById("app")});export{Nn as B,Mn as C,Yt as a,U as b,Ce as c,Xt as d,Te as e,Jt as f,ln as g,Qt as h,en as i,Mt as j,Ie as k,sn as l,gt as m,Ht as n,Gt as o,I as p,De as q,rt as r,vn as s,Qe as t,_e as u,C as v,He as w,Ct as x,Wt as y,on as z};
+1
assets/index-Cr8Vao8y.js
··· 1 + const t=(t,e)=>({text:t,features:t.length>0?e:void 0}),e=(e,o)=>{if(void 0===o||0===o.length)return[t(e,void 0)];const r=[],c=e.length;let h=0,d=0;const n=(t,o)=>{let r=t;if(e.charCodeAt(r)<128)for(r+=1,d+=1;d+8<=o&&r+8<=c;){if(!((e.charCodeAt(r)|e.charCodeAt(r+1)|e.charCodeAt(r+2)|e.charCodeAt(r+3)|e.charCodeAt(r+4)|e.charCodeAt(r+5)|e.charCodeAt(r+6)|e.charCodeAt(r+7))<128))break;r+=8,d+=8}for(;d<o&&r<c;){const t=e.charCodeAt(r);t<128?(r+=1,d+=1):t<2048?(r+=1,d+=2):t<55296||t>56319?(r+=1,d+=3):(r+=2,d+=4)}return r};for(let s=0,a=o.length;s<a;s++){const c=o[s],{byteStart:a,byteEnd:i}=c.index,l=c.features;if(!(a>i||0===l.length)){if(d<a){const o=n(h,a);o>h&&r.push(t(e.slice(h,o),void 0)),h=o}{const o=n(h,i);o>h&&r.push(t(e.slice(h,o),l)),h=o}}}return h<c&&r.push(t(e.slice(h),void 0)),r};export{e as s};
+13
index.html
··· 1 + <!doctype html> 2 + <html lang="en"> 3 + <head> 4 + <meta charset="UTF-8" /> 5 + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 + <title>Bluesky embed</title> 7 + <script type="module" crossorigin src="./assets/index-CD_0uzJz.js"></script> 8 + <link rel="stylesheet" crossorigin href="./assets/index-B_9yoyg2.css"> 9 + </head> 10 + <body> 11 + <div id="app"></div> 12 + </body> 13 + </html>
-3
mise.toml
··· 1 - [tools] 2 - node = "latest" 3 - pnpm = "latest"
-18
package.json
··· 1 - { 2 - "private": true, 3 - "scripts": { 4 - "fmt": "prettier --cache --write ." 5 - }, 6 - "devDependencies": { 7 - "@changesets/cli": "^2.29.8", 8 - "prettier": "^3.7.4", 9 - "prettier-plugin-css-order": "^2.1.2", 10 - "prettier-plugin-svelte": "^3.4.0", 11 - "typescript": "~5.8.3" 12 - }, 13 - "pnpm": { 14 - "patchedDependencies": { 15 - "svelte": "patches/svelte.patch" 16 - } 17 - } 18 - }
-1
packages/bluesky-post-embed/.gitignore
··· 1 - themes/
-83
packages/bluesky-post-embed/README.md
··· 1 - # &lt;bluesky-post-embed> 2 - 3 - A custom element for embedding Bluesky posts. 4 - 5 - ## Installation 6 - 7 - ### via npm 8 - 9 - ``` 10 - npm install bluesky-post-embed 11 - ``` 12 - 13 - then, import the package on your app. 14 - 15 - ```js 16 - import 'bluesky-post-embed'; 17 - 18 - import 'bluesky-post-embed/style.css'; 19 - import 'bluesky-post-embed/themes/light.css'; 20 - ``` 21 - 22 - ## Usage 23 - 24 - ```html 25 - <bluesky-post src="at://did:plc:ragtjsm2j2vknwkz3zp4oxrd/app.bsky.feed.post/3kj2umze7zj2n"> 26 - <blockquote class="bluesky-post-fallback"> 27 - <p dir="auto">angel mode</p> 28 - โ€” Paul Frazee (@pfrazee.com) 29 - <a href="https://bsky.app/profile/did:plc:ragtjsm2j2vknwkz3zp4oxrd/post/3kj2umze7zj2n" 30 - >January 16, 2024 at 9:11 AM</a 31 - > 32 - </blockquote> 33 - </bluesky-post> 34 - ``` 35 - 36 - ### Attributes 37 - 38 - - `src` **Required** 39 - AT-URI of the post record 40 - - `contextless` **Optional** 41 - Whether to show the post without any context (no parent reply) 42 - - `allow-unauthenticated` **Optional** 43 - Whether to allow unauthenticated viewing 44 - - `service-uri` **Optional** 45 - URL to an AppView service, defaults to `https://public.api.bsky.app` 46 - 47 - ### Events 48 - 49 - - `loaded` 50 - Fired when the embed has successfully loaded the post 51 - - `error` 52 - Fired when the embed fails to load the post 53 - 54 - ## SSR usage 55 - 56 - The embeds are powered by a static HTML renderer, this renderer can be used directly in your 57 - server-rendering framework of choice for a zero-JS experience. 58 - 59 - ```tsx 60 - import { fetchPost, renderPost } from 'bluesky-post-embed/core'; 61 - 62 - import 'bluesky-post-embed/style.css'; 63 - import 'bluesky-post-embed/themes/light.css'; 64 - 65 - // fetch the post 66 - const controller = new AbortController(); 67 - const data = await fetchPost({ 68 - src: `at://did:plc:ragtjsm2j2vknwkz3zp4oxrd/app.bsky.feed.post/3kj2umze7zj2n`, 69 - signal: controller.signal, 70 - }); 71 - 72 - // render the post 73 - const html = renderPost(data); 74 - return ( 75 - <bluesky-post 76 - src={data.thread?.post.uri} 77 - dangerouslySetInnerHTML={{ __html: html }} 78 - ></bluesky-post> 79 - ); 80 - ``` 81 - 82 - Check out examples for [Astro](https://github.com/mary-ext/bluesky-embed-astro) and 83 - [SvelteKit](https://github.com/mary-ext/bluesky-embed-sveltekit).
-11
packages/bluesky-post-embed/index.html
··· 1 - <!doctype html> 2 - <html lang="en"> 3 - <head> 4 - <meta charset="utf-8" /> 5 - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 - <title>Bluesky post embed</title> 7 - </head> 8 - <body> 9 - <script type="module" src="./src/main.tsx"></script> 10 - </body> 11 - </html>
-95
packages/bluesky-post-embed/lib/bluesky-post.svelte
··· 1 - <script lang="ts" module> 2 - import type { AppBskyFeedDefs, AppBskyFeedGetPostThread } from '@atcute/client/lexicons'; 3 - 4 - type ThreadData = AppBskyFeedGetPostThread.Output['thread']; 5 - type PostView = AppBskyFeedDefs.PostView; 6 - 7 - const unwrapPostThread = (data: ThreadData, contextless: boolean, allowUnauthenticated: boolean) => { 8 - const items: { post: PostView; parent: PostView | null }[] = []; 9 - 10 - let i = 0; 11 - let il = contextless ? 1 : 2; 12 - 13 - let curr: typeof data | undefined = data; 14 - while (curr) { 15 - if ( 16 - curr.$type === 'app.bsky.feed.defs#notFoundPost' || 17 - curr.$type === 'app.bsky.feed.defs#blockedPost' 18 - ) { 19 - break; 20 - } 21 - 22 - const post = curr.post; 23 - 24 - if (i !== 0) { 25 - items[i - 1].parent = post; 26 - } 27 - 28 - if (++i > il) { 29 - break; 30 - } 31 - 32 - const author = post.author; 33 - if (!allowUnauthenticated && author.labels?.some((def) => def.val === '!no-unauthenticated')) { 34 - break; 35 - } 36 - 37 - items.push({ post: post, parent: null }); 38 - curr = curr.parent; 39 - } 40 - return items.reverse(); 41 - }; 42 - </script> 43 - 44 - <script lang="ts"> 45 - import EmbedFrame from 'internal/components/embed-frame.svelte'; 46 - import HighlightedPost from 'internal/components/highlighted-post.svelte'; 47 - import Post from 'internal/components/post.svelte'; 48 - 49 - import { NO_UNAUTHENTICATED_LABEL } from 'internal/utils/constants.js'; 50 - import type { PostData } from 'internal/types/post.js'; 51 - 52 - const { thread, contextless, allowUnauthenticated }: PostData = $props(); 53 - 54 - const isPwiForbidden = 55 - !allowUnauthenticated && 56 - thread !== null && 57 - thread.$type === 'app.bsky.feed.defs#threadViewPost' && 58 - thread.post.author.labels?.some((label) => label.val === NO_UNAUTHENTICATED_LABEL); 59 - </script> 60 - 61 - {#if thread === null} 62 - {@render Message(`The post can't be found, it may have been deleted.`)} 63 - {:else if isPwiForbidden} 64 - {@render Message(`The author has requested for their posts to not be displayed on external sites.`)} 65 - {:else} 66 - {@const posts = unwrapPostThread(thread, contextless, allowUnauthenticated)} 67 - 68 - <EmbedFrame> 69 - {#each posts as { post, parent }, idx} 70 - {@const hasPrevious = idx !== 0} 71 - 72 - {#if idx === posts.length - 1} 73 - <HighlightedPost {post} {parent} prev={hasPrevious} /> 74 - {:else} 75 - <Post {post} {parent} prev={hasPrevious} /> 76 - {/if} 77 - {/each} 78 - </EmbedFrame> 79 - {/if} 80 - 81 - {#snippet Message(msg: string)} 82 - <EmbedFrame> 83 - <div class="message">{msg}</div> 84 - </EmbedFrame> 85 - {/snippet} 86 - 87 - <style> 88 - .message { 89 - margin: 0 auto; 90 - padding: 32px 16px; 91 - max-width: 380px; 92 - color: var(--text-secondary); 93 - text-align: center; 94 - } 95 - </style>
-70
packages/bluesky-post-embed/lib/core.ts
··· 1 - import '@atcute/bluesky/lexicons'; 2 - 3 - import { simpleFetchHandler, XRPC, XRPCError } from '@atcute/client'; 4 - import type { At } from '@atcute/client/lexicons'; 5 - import { render } from 'svelte/server'; 6 - 7 - import type { PostData } from 'internal/types/post.js'; 8 - import { DEFAULT_APPVIEW_URL } from 'internal/utils/constants.js'; 9 - 10 - import BlueskyPost from './bluesky-post.svelte'; 11 - 12 - export type { PostData }; 13 - 14 - export interface PostFetchOptions { 15 - /** 16 - * AT-URI of the post in question 17 - */ 18 - uri: string; 19 - /** 20 - * Abort signal to cancel the request 21 - */ 22 - signal?: AbortSignal; 23 - /** 24 - * Whether to fetch post without context (no parent replies) 25 - * @default false 26 - */ 27 - contextless?: boolean; 28 - /** 29 - * Whether to allow unauthenticated viewing 30 - * @default false 31 - */ 32 - allowUnauthenticated?: boolean; 33 - /** 34 - * AppView service to use 35 - * @default "https://public.api.bsky.app" 36 - */ 37 - serviceUri?: string; 38 - } 39 - 40 - export const fetchPost = async (opts: PostFetchOptions): Promise<PostData> => { 41 - const rpc = new XRPC({ handler: simpleFetchHandler({ service: opts.serviceUri ?? DEFAULT_APPVIEW_URL }) }); 42 - const contextless = opts.contextless ?? false; 43 - 44 - const { data } = await rpc 45 - .get('app.bsky.feed.getPostThread', { 46 - signal: opts.signal, 47 - params: { 48 - uri: opts.uri as At.ResourceUri, 49 - parentHeight: !contextless ? 2 : 1, 50 - depth: 0, 51 - }, 52 - }) 53 - .catch((err) => { 54 - if (err instanceof XRPCError) { 55 - if (err.kind === 'NotFound') { 56 - return { data: null }; 57 - } 58 - } 59 - 60 - return Promise.reject(err); 61 - }); 62 - 63 - const thread = data?.thread.$type === 'app.bsky.feed.defs#threadViewPost' ? data.thread : null; 64 - 65 - return { thread, contextless, allowUnauthenticated: opts.allowUnauthenticated ?? false }; 66 - }; 67 - 68 - export const renderPost = (data: PostData): string => { 69 - return render(BlueskyPost, { props: data }).body; 70 - };
-59
packages/bluesky-post-embed/lib/wc.ts
··· 1 - import { fetchPost, renderPost } from './core'; 2 - 3 - export class BlueskyPost extends HTMLElement { 4 - connectedCallback() { 5 - this.load().then( 6 - () => this.dispatchEvent(new CustomEvent('loaded')), 7 - (err) => { 8 - const defaulted = this.dispatchEvent(new CustomEvent('error', { detail: err })); 9 - if (defaulted) { 10 - throw err; 11 - } 12 - }, 13 - ); 14 - } 15 - 16 - async load() { 17 - const src = this.getAttribute('src')!; 18 - const serviceUri = this.getAttribute('service-uri') || undefined; 19 - const contextless = this.getAttribute('contextless') !== null; 20 - const allowUnauthenticated = this.getAttribute('allow-unauthenticated') !== null; 21 - const silent = this.getAttribute('silent') !== null; 22 - 23 - const data = await fetchPost({ uri: src, contextless, allowUnauthenticated, serviceUri }).catch( 24 - (error) => { 25 - if (silent) { 26 - console.warn('Failed to fetch post:', error); 27 - return null; 28 - } 29 - throw error; 30 - }, 31 - ); 32 - 33 - if (data === null) { 34 - return; 35 - } 36 - 37 - const html = renderPost(data); 38 - 39 - const root = this.shadowRoot; 40 - 41 - if (!root) { 42 - this.innerHTML = html; 43 - } else { 44 - const template = document.createElement('template'); 45 - template.innerHTML = html; 46 - 47 - const fragment = template.content; 48 - const slot = root.querySelector('slot'); 49 - 50 - if (slot) { 51 - slot.replaceWith(fragment); 52 - } else { 53 - root.appendChild(fragment); 54 - } 55 - } 56 - } 57 - } 58 - 59 - customElements.define('bluesky-post', BlueskyPost);
-45
packages/bluesky-post-embed/package.json
··· 1 - { 2 - "type": "module", 3 - "name": "bluesky-post-embed", 4 - "description": "Custom element for embedding Bluesky posts", 5 - "version": "1.0.6", 6 - "author": "externdefs", 7 - "license": "MIT", 8 - "repository": { 9 - "type": "git", 10 - "url": "https://github.com/mary-ext/bluesky-embed", 11 - "directory": "packages/bluesky-post-embed" 12 - }, 13 - "files": [ 14 - "dist/", 15 - "themes/" 16 - ], 17 - "exports": { 18 - ".": "./dist/wc.js", 19 - "./core": "./dist/core.js", 20 - "./style.css": "./dist/core.css", 21 - "./themes/*": "./themes/*" 22 - }, 23 - "scripts": { 24 - "dev": "vite", 25 - "build": "pnpm run check && vite build && rsync -aHAX --delete ../../themes/ themes/", 26 - "check": "svelte-check --tsconfig ./tsconfig.json && tsc -p tsconfig.node.json", 27 - "prepack": "pnpm run build" 28 - }, 29 - "dependencies": { 30 - "@atcute/bluesky": "^2.1.1", 31 - "@atcute/bluesky-richtext-segmenter": "^2.0.4", 32 - "@atcute/client": "^3.1.0" 33 - }, 34 - "devDependencies": { 35 - "@preact/preset-vite": "^2.10.2", 36 - "@tsconfig/svelte": "^5.0.6", 37 - "@types/node": "^24.10.1", 38 - "internal": "workspace:^", 39 - "preact": "^10.28.0", 40 - "svelte": "catalog:", 41 - "svelte-check": "^4.3.4", 42 - "vite": "^7.2.6", 43 - "vite-plugin-dts": "^4.5.4" 44 - } 45 - }
-53
packages/bluesky-post-embed/src/app.tsx
··· 1 - import { useEffect, useMemo, useState } from 'preact/hooks'; 2 - 3 - import type { PostData } from 'internal/types/post.js'; 4 - import { fetchPost, renderPost } from '../lib/core'; 5 - 6 - const uri = `at://did:plc:ragtjsm2j2vknwkz3zp4oxrd/app.bsky.feed.post/3kj2umze7zj2n`; 7 - 8 - const App = () => { 9 - const [state, setState] = useState<{ uri: string; data: PostData }>(); 10 - 11 - useEffect(() => { 12 - if (state && state.uri === uri) { 13 - return; 14 - } 15 - 16 - const controller = new AbortController(); 17 - const promise = fetchPost({ 18 - uri: uri, 19 - signal: controller.signal, 20 - allowUnauthenticated: true, 21 - }); 22 - 23 - promise.then((data) => { 24 - setState({ uri, data }); 25 - }); 26 - 27 - return () => { 28 - controller.abort(); 29 - }; 30 - }, [uri]); 31 - 32 - return <div class="app">{state && <BlueskyPost data={state.data} />}</div>; 33 - }; 34 - 35 - export default App; 36 - 37 - const BlueskyPost = ({ data }: { data: PostData }) => { 38 - const html = useMemo(() => renderPost(data), [data]); 39 - 40 - return <bluesky-post src={data.thread?.post.uri} dangerouslySetInnerHTML={{ __html: html }}></bluesky-post>; 41 - }; 42 - 43 - declare module 'preact' { 44 - namespace JSX { 45 - interface BlueskyPostAttributes extends HTMLAttributes<HTMLElement> { 46 - src?: string; 47 - } 48 - 49 - interface IntrinsicElements { 50 - 'bluesky-post': BlueskyPostAttributes; 51 - } 52 - } 53 - }
-8
packages/bluesky-post-embed/src/main.tsx
··· 1 - import { render } from 'preact'; 2 - 3 - import App from './app'; 4 - 5 - import '../../../themes/light.css'; 6 - import './styles/main.css'; 7 - 8 - render(<App />, document.body);
-8
packages/bluesky-post-embed/src/styles/main.css
··· 1 - @import './normalize.css'; 2 - 3 - .app { 4 - margin: 0 auto; 5 - padding: 36px 16px; 6 - width: 100%; 7 - max-width: calc(550px + (16 * 2px)); 8 - }
-199
packages/bluesky-post-embed/src/styles/normalize.css
··· 1 - /*! modern-normalize v3.0.1 | MIT License | https://github.com/sindresorhus/modern-normalize */ 2 - 3 - /* 4 - Document 5 - ======== 6 - */ 7 - 8 - /** 9 - Use a better box model (opinionated). 10 - */ 11 - 12 - *, 13 - ::before, 14 - ::after { 15 - box-sizing: border-box; 16 - } 17 - 18 - html { 19 - line-height: 1.15; /* 1. Correct the line height in all browsers. */ 20 - /* Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3) */ 21 - font-family: 'Inter', 'Roboto', ui-sans-serif, sans-serif, 'Noto Color Emoji', 'Twemoji Mozilla'; 22 - -webkit-text-size-adjust: 100%; /* 2. Prevent adjustments of font size after orientation changes in iOS. */ 23 - tab-size: 4; /* 3. Use a more readable tab size (opinionated). */ 24 - } 25 - 26 - /* 27 - Sections 28 - ======== 29 - */ 30 - 31 - body { 32 - margin: 0; /* Remove the margin in all browsers. */ 33 - } 34 - 35 - /* 36 - Text-level semantics 37 - ==================== 38 - */ 39 - 40 - /** 41 - Add the correct font weight in Chrome and Safari. 42 - */ 43 - 44 - b, 45 - strong { 46 - font-weight: bolder; 47 - } 48 - 49 - /** 50 - 1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3) 51 - 2. Correct the odd 'em' font sizing in all browsers. 52 - */ 53 - 54 - code, 55 - kbd, 56 - samp, 57 - pre { 58 - font-size: 1em; /* 2 */ 59 - font-family: 'JetBrains Mono NL', ui-monospace, monospace; /* 1 */ 60 - } 61 - 62 - /** 63 - Add the correct font size in all browsers. 64 - */ 65 - 66 - small { 67 - font-size: 80%; 68 - } 69 - 70 - /** 71 - Prevent 'sub' and 'sup' elements from affecting the line height in all browsers. 72 - */ 73 - 74 - sub, 75 - sup { 76 - position: relative; 77 - vertical-align: baseline; 78 - font-size: 75%; 79 - line-height: 0; 80 - } 81 - 82 - sub { 83 - bottom: -0.25em; 84 - } 85 - 86 - sup { 87 - top: -0.5em; 88 - } 89 - 90 - /* 91 - Tabular data 92 - ============ 93 - */ 94 - 95 - /** 96 - Correct table border color inheritance in Chrome and Safari. (https://issues.chromium.org/issues/40615503, https://bugs.webkit.org/show_bug.cgi?id=195016) 97 - */ 98 - 99 - table { 100 - border-color: currentcolor; 101 - } 102 - 103 - /* 104 - Forms 105 - ===== 106 - */ 107 - 108 - /** 109 - 1. Change the font styles in all browsers. 110 - 2. Remove the margin in Firefox and Safari. 111 - */ 112 - 113 - button, 114 - input, 115 - optgroup, 116 - select, 117 - textarea { 118 - margin: 0; /* 2 */ 119 - font-size: 100%; /* 1 */ 120 - line-height: 1.15; /* 1 */ 121 - font-family: inherit; /* 1 */ 122 - } 123 - 124 - /** 125 - Correct the inability to style clickable types in iOS and Safari. 126 - */ 127 - 128 - button, 129 - [type='button'], 130 - [type='reset'], 131 - [type='submit'] { 132 - -webkit-appearance: button; 133 - } 134 - 135 - /** 136 - Remove the padding so developers are not caught out when they zero out 'fieldset' elements in all browsers. 137 - */ 138 - 139 - legend { 140 - padding: 0; 141 - } 142 - 143 - /** 144 - Add the correct vertical alignment in Chrome and Firefox. 145 - */ 146 - 147 - progress { 148 - vertical-align: baseline; 149 - } 150 - 151 - /** 152 - Correct the cursor style of increment and decrement buttons in Safari. 153 - */ 154 - 155 - ::-webkit-inner-spin-button, 156 - ::-webkit-outer-spin-button { 157 - height: auto; 158 - } 159 - 160 - /** 161 - 1. Correct the odd appearance in Chrome and Safari. 162 - 2. Correct the outline style in Safari. 163 - */ 164 - 165 - [type='search'] { 166 - -webkit-appearance: textfield; /* 1 */ 167 - outline-offset: -2px; /* 2 */ 168 - } 169 - 170 - /** 171 - Remove the inner padding in Chrome and Safari on macOS. 172 - */ 173 - 174 - ::-webkit-search-decoration { 175 - -webkit-appearance: none; 176 - } 177 - 178 - /** 179 - 1. Correct the inability to style clickable types in iOS and Safari. 180 - 2. Change font properties to 'inherit' in Safari. 181 - */ 182 - 183 - ::-webkit-file-upload-button { 184 - -webkit-appearance: button; /* 1 */ 185 - font: inherit; /* 2 */ 186 - } 187 - 188 - /* 189 - Interactive 190 - =========== 191 - */ 192 - 193 - /* 194 - Add the correct display in Chrome and Safari. 195 - */ 196 - 197 - summary { 198 - display: list-item; 199 - }
-8
packages/bluesky-post-embed/svelte.config.js
··· 1 - export default { 2 - compilerOptions: { 3 - warningFilter: (warning) => { 4 - if (warning.code === 'state_referenced_locally') return false; 5 - return true; 6 - }, 7 - }, 8 - };
-14
packages/bluesky-post-embed/tsconfig.build.json
··· 1 - { 2 - "extends": "@tsconfig/svelte/tsconfig.json", 3 - "compilerOptions": { 4 - "types": [], 5 - "target": "ESNext", 6 - "useDefineForClassFields": true, 7 - "module": "ESNext", 8 - "resolveJsonModule": true, 9 - "isolatedModules": true, 10 - "moduleDetection": "force", 11 - "noEmit": true, 12 - }, 13 - "include": ["lib"], 14 - }
-17
packages/bluesky-post-embed/tsconfig.json
··· 1 - { 2 - "extends": "@tsconfig/svelte/tsconfig.json", 3 - "compilerOptions": { 4 - "types": [], 5 - "target": "ESNext", 6 - "useDefineForClassFields": true, 7 - "module": "ESNext", 8 - "resolveJsonModule": true, 9 - "isolatedModules": true, 10 - "moduleDetection": "force", 11 - "noEmit": true, 12 - "jsx": "react-jsx", 13 - "jsxImportSource": "preact", 14 - }, 15 - "include": ["lib", "src"], 16 - "references": [{ "path": "./tsconfig.node.json" }], 17 - }
-14
packages/bluesky-post-embed/tsconfig.node.json
··· 1 - { 2 - "compilerOptions": { 3 - "composite": true, 4 - "types": ["node"], 5 - "skipLibCheck": true, 6 - "module": "ESNext", 7 - "target": "ESNext", 8 - "moduleResolution": "Bundler", 9 - "strict": true, 10 - "noEmit": true, 11 - "noUncheckedSideEffectImports": true, 12 - }, 13 - "include": ["vite.config.ts"], 14 - }
-103
packages/bluesky-post-embed/vite.config.ts
··· 1 - import * as path from 'node:path'; 2 - 3 - import { compile as compileSvelte } from 'svelte/compiler'; 4 - import { type Plugin, createFilter, defineConfig } from 'vite'; 5 - 6 - import preact from '@preact/preset-vite'; 7 - import dts from 'vite-plugin-dts'; 8 - 9 - export default defineConfig({ 10 - base: './', 11 - build: { 12 - outDir: 'dist/', 13 - target: 'esnext', 14 - minify: false, 15 - cssMinify: false, 16 - cssCodeSplit: true, 17 - lib: { 18 - entry: { 19 - core: 'lib/core.ts', 20 - wc: 'lib/wc.ts', 21 - }, 22 - formats: ['es'], 23 - }, 24 - rollupOptions: { 25 - external: ['@atcute/client', '@atcute/bluesky-richtext-segmenter'], 26 - }, 27 - }, 28 - esbuild: { 29 - target: 'esnext', 30 - }, 31 - plugins: [ 32 - svelte(), 33 - preact(), 34 - dts({ 35 - rollupTypes: true, 36 - tsconfigPath: 'tsconfig.build.json', 37 - beforeWriteFile(filePath, content) { 38 - if (filePath.endsWith('/core.d.ts')) { 39 - // Make sure the relevant types are present 40 - return { content: `import '@atcute/bluesky/lexicons';\n${content}` }; 41 - } 42 - }, 43 - }), 44 - ], 45 - }); 46 - 47 - function svelte(): Plugin { 48 - const filter = createFilter('**/*.svelte'); 49 - const stylesheets = new Map<string, string>(); 50 - 51 - return { 52 - name: 'svelte', 53 - resolveId(id) { 54 - return stylesheets.has(id) ? id : null; 55 - }, 56 - load(id) { 57 - const css = stylesheets.get(id); 58 - if (css !== undefined) { 59 - this.addWatchFile(id.slice(0, -4)); 60 - return { code: css }; 61 - } 62 - 63 - return null; 64 - }, 65 - transform(source, id) { 66 - if (!filter(id)) { 67 - return null; 68 - } 69 - 70 - const result = compileSvelte(source, { 71 - generate: 'server', 72 - css: 'external', 73 - cssHash({ hash, filename }) { 74 - const prefix = `github:mary-ext/bluesky-post-embed/`; 75 - return `s-` + hash(prefix + path.relative(__dirname, filename)); 76 - }, 77 - runes: true, 78 - filename: id, 79 - }); 80 - 81 - { 82 - const { js, css, warnings } = result; 83 - 84 - let jsCode = js.code; 85 - 86 - if (css) { 87 - const cssId = `${id}.css`; 88 - jsCode = jsCode + `\nimport ${JSON.stringify(cssId)};\n`; 89 - stylesheets.set(cssId, css.code); 90 - } 91 - 92 - for (const warn of warnings) { 93 - if (warn.code === 'state_referenced_locally') { 94 - continue; 95 - } 96 - this.warn(warn); 97 - } 98 - 99 - return { code: jsCode }; 100 - } 101 - }, 102 - }; 103 - }
-1
packages/bluesky-profile-card-embed/.gitignore
··· 1 - themes/
-81
packages/bluesky-profile-card-embed/README.md
··· 1 - # &lt;bluesky-profile-card-embed> 2 - 3 - A custom element for embedding Bluesky profile cards. 4 - 5 - ## Installation 6 - 7 - ### via npm 8 - 9 - ``` 10 - npm install bluesky-profile-card-embed 11 - ``` 12 - 13 - then, import the package on your app. 14 - 15 - ```js 16 - import 'bluesky-profile-card-embed'; 17 - 18 - import 'bluesky-profile-card-embed/style.css'; 19 - import 'bluesky-profile-card-embed/themes/light.css'; 20 - ``` 21 - 22 - ## Usage 23 - 24 - ```html 25 - <bluesky-profile-card actor="did:plc:2gkh62xvzokhlf6li4ol3b3d"> 26 - <a 27 - target="_blank" 28 - href="https://bsky.app/profile/did:plc:2gkh62xvzokhlf6li4ol3b3d" 29 - class="bluesky-profile-card-fallback" 30 - > 31 - @patak.dev's Bluesky profile 32 - </a> 33 - </bluesky-profile-card> 34 - ``` 35 - 36 - ### Attributes 37 - 38 - - `actor` **Required** 39 - DID or handle of the account 40 - - `allow-unauthenticated` **Optional** 41 - Whether to allow unauthenticated viewing 42 - - `service-uri` **Optional** 43 - URL to an AppView service, defaults to `https://public.api.bsky.app` 44 - 45 - ### Events 46 - 47 - - `loaded` 48 - Fired when the embed has successfully loaded the profile card 49 - - `error` 50 - Fired when the embed fails to load the profile card 51 - 52 - ## SSR usage 53 - 54 - The embeds are powered by a static HTML renderer, this renderer can be used directly in your 55 - server-rendering framework of choice for a zero-JS experience. 56 - 57 - ```tsx 58 - import { fetchProfileCard, renderProfileCard } from 'bluesky-profile-card-embed/core'; 59 - 60 - import 'bluesky-profile-card-embed/style.css'; 61 - import 'bluesky-profile-card-embed/themes/light.css'; 62 - 63 - // fetch the profile 64 - const controller = new AbortController(); 65 - const data = await fetchProfileCard({ 66 - actor: `did:plc:ragtjsm2j2vknwkz3zp4oxrd`, 67 - signal: controller.signal, 68 - }); 69 - 70 - // render the profile 71 - const html = renderProfileCard(data); 72 - return ( 73 - <bluesky-profile-card 74 - actor={data.profile?.did} 75 - dangerouslySetInnerHTML={{ __html: html }} 76 - ></bluesky-profile-card> 77 - ); 78 - ``` 79 - 80 - Check out examples for [Astro](https://github.com/mary-ext/bluesky-embed-astro) and 81 - [SvelteKit](https://github.com/mary-ext/bluesky-embed-sveltekit).
-11
packages/bluesky-profile-card-embed/index.html
··· 1 - <!doctype html> 2 - <html lang="en"> 3 - <head> 4 - <meta charset="utf-8" /> 5 - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 - <title>Bluesky profile card embed</title> 7 - </head> 8 - <body> 9 - <script type="module" src="./src/main.tsx"></script> 10 - </body> 11 - </html>
-38
packages/bluesky-profile-card-embed/lib/bluesky-profile-card.svelte
··· 1 - <script lang="ts"> 2 - import EmbedFrame from 'internal/components/embed-frame.svelte'; 3 - import ProfileCard from 'internal/components/profile-card.svelte'; 4 - 5 - import type { ProfileCardData } from 'internal/types/profile-card.js'; 6 - import { NO_UNAUTHENTICATED_LABEL } from 'internal/utils/constants.js'; 7 - 8 - const { profile, allowUnauthenticated }: ProfileCardData = $props(); 9 - 10 - const isPwiForbidden = 11 - !allowUnauthenticated && profile?.labels?.some((label) => label.val === NO_UNAUTHENTICATED_LABEL); 12 - </script> 13 - 14 - {#if profile === null} 15 - {@render Message(`The profile can't be found, it may have been deleted.`)} 16 - {:else if isPwiForbidden} 17 - {@render Message(`The user has requested for their profile to not be displayed on external sites.`)} 18 - {:else} 19 - <EmbedFrame> 20 - <ProfileCard {profile} /> 21 - </EmbedFrame> 22 - {/if} 23 - 24 - {#snippet Message(msg: string)} 25 - <EmbedFrame> 26 - <div class="message">{msg}</div> 27 - </EmbedFrame> 28 - {/snippet} 29 - 30 - <style> 31 - .message { 32 - margin: 0 auto; 33 - padding: 32px 16px; 34 - max-width: 380px; 35 - color: var(--text-secondary); 36 - text-align: center; 37 - } 38 - </style>
-61
packages/bluesky-profile-card-embed/lib/core.ts
··· 1 - import '@atcute/bluesky/lexicons'; 2 - 3 - import { simpleFetchHandler, XRPC, XRPCError } from '@atcute/client'; 4 - import type { At } from '@atcute/client/lexicons'; 5 - import { render } from 'svelte/server'; 6 - 7 - import type { ProfileCardData } from 'internal/types/profile-card.js'; 8 - import { DEFAULT_APPVIEW_URL } from 'internal/utils/constants.js'; 9 - 10 - import BlueskyProfileCard from './bluesky-profile-card.svelte'; 11 - 12 - export type { ProfileCardData }; 13 - 14 - export interface ProfileCardFetchOptions { 15 - /** 16 - * Handle or DID identifier of the user 17 - */ 18 - actor: string; 19 - /** 20 - * Abort signal to cancel the request 21 - */ 22 - signal?: AbortSignal; 23 - /** 24 - * Allow unauthenticated viewing 25 - * @default false 26 - */ 27 - allowUnauthenticated?: boolean; 28 - /** 29 - * AppView service to use 30 - * @default "https://public.api.bsky.app" 31 - */ 32 - serviceUri?: string; 33 - } 34 - 35 - export const fetchProfileCard = async (opts: ProfileCardFetchOptions): Promise<ProfileCardData> => { 36 - const actor = opts.actor; 37 - const allowUnauthenticated = opts.allowUnauthenticated ?? false; 38 - 39 - const rpc = new XRPC({ handler: simpleFetchHandler({ service: opts.serviceUri ?? DEFAULT_APPVIEW_URL }) }); 40 - 41 - const { data: profile } = await rpc 42 - .get('app.bsky.actor.getProfile', { 43 - signal: opts.signal, 44 - params: { actor: actor as At.Identifier }, 45 - }) 46 - .catch((err) => { 47 - if (err instanceof XRPCError) { 48 - if (err.kind === 'InvalidRequest' && err.description === 'Profile not found') { 49 - return { data: null }; 50 - } 51 - } 52 - 53 - return Promise.reject(err); 54 - }); 55 - 56 - return { profile: profile, allowUnauthenticated }; 57 - }; 58 - 59 - export const renderProfileCard = (data: ProfileCardData): string => { 60 - return render(BlueskyProfileCard, { props: data }).body; 61 - };
-56
packages/bluesky-profile-card-embed/lib/wc.ts
··· 1 - import { fetchProfileCard, renderProfileCard } from './core'; 2 - 3 - export class BlueskyProfileCard extends HTMLElement { 4 - connectedCallback() { 5 - this.load().then( 6 - () => this.dispatchEvent(new CustomEvent('loaded')), 7 - (err) => { 8 - const defaulted = this.dispatchEvent(new CustomEvent('error', { detail: err })); 9 - if (defaulted) { 10 - throw err; 11 - } 12 - }, 13 - ); 14 - } 15 - 16 - async load() { 17 - const actor = this.getAttribute('actor')!; 18 - const serviceUri = this.getAttribute('service-uri') || undefined; 19 - const allowUnauthenticated = this.getAttribute('allow-unauthenticated') !== null; 20 - const silent = this.getAttribute('silent') !== null; 21 - 22 - const data = await fetchProfileCard({ actor, allowUnauthenticated, serviceUri }).catch((error) => { 23 - if (silent) { 24 - console.warn('Failed to fetch profile card:', error); 25 - return null; 26 - } 27 - throw error; 28 - }); 29 - 30 - if (data === null) { 31 - return; 32 - } 33 - 34 - const html = renderProfileCard(data); 35 - 36 - const root = this.shadowRoot; 37 - 38 - if (!root) { 39 - this.innerHTML = html; 40 - } else { 41 - const template = document.createElement('template'); 42 - template.innerHTML = html; 43 - 44 - const fragment = template.content; 45 - const slot = root.querySelector('slot'); 46 - 47 - if (slot) { 48 - slot.replaceWith(fragment); 49 - } else { 50 - root.appendChild(fragment); 51 - } 52 - } 53 - } 54 - } 55 - 56 - customElements.define('bluesky-profile-card', BlueskyProfileCard);
-45
packages/bluesky-profile-card-embed/package.json
··· 1 - { 2 - "type": "module", 3 - "name": "bluesky-profile-card-embed", 4 - "description": "Custom element for embedding Bluesky profile cards", 5 - "version": "1.0.1", 6 - "author": "externdefs", 7 - "license": "MIT", 8 - "repository": { 9 - "type": "git", 10 - "url": "https://github.com/mary-ext/bluesky-embed", 11 - "directory": "packages/bluesky-profile-card-embed" 12 - }, 13 - "files": [ 14 - "dist/", 15 - "themes/" 16 - ], 17 - "exports": { 18 - ".": "./dist/wc.js", 19 - "./core": "./dist/core.js", 20 - "./style.css": "./dist/core.css", 21 - "./themes/*": "./themes/*" 22 - }, 23 - "scripts": { 24 - "dev": "vite", 25 - "build": "pnpm run check && vite build && rsync -aHAX --delete ../../themes/ themes/", 26 - "check": "svelte-check --tsconfig ./tsconfig.json && tsc -p tsconfig.node.json", 27 - "prepack": "pnpm run build" 28 - }, 29 - "dependencies": { 30 - "@atcute/bluesky": "^2.1.1", 31 - "@atcute/bluesky-richtext-parser": "^1.0.7", 32 - "@atcute/client": "^3.1.0" 33 - }, 34 - "devDependencies": { 35 - "@preact/preset-vite": "^2.10.2", 36 - "@tsconfig/svelte": "^5.0.6", 37 - "@types/node": "^24.10.1", 38 - "internal": "workspace:^", 39 - "preact": "^10.28.0", 40 - "svelte": "catalog:", 41 - "svelte-check": "^4.3.4", 42 - "vite": "^7.2.6", 43 - "vite-plugin-dts": "^4.5.4" 44 - } 45 - }
-58
packages/bluesky-profile-card-embed/src/app.tsx
··· 1 - import { useEffect, useMemo, useState } from 'preact/hooks'; 2 - 3 - import type { ProfileCardData } from 'internal/types/profile-card.js'; 4 - import { fetchProfileCard, renderProfileCard } from '../lib/core'; 5 - 6 - const actor = `patak.dev`; 7 - 8 - const App = () => { 9 - const [state, setState] = useState<{ actor: string; data: ProfileCardData }>(); 10 - 11 - useEffect(() => { 12 - if (state && state.actor === actor) { 13 - return; 14 - } 15 - 16 - const controller = new AbortController(); 17 - const promise = fetchProfileCard({ 18 - actor: actor, 19 - signal: controller.signal, 20 - allowUnauthenticated: true, 21 - }); 22 - 23 - promise.then((data) => { 24 - setState({ actor, data }); 25 - }); 26 - 27 - return () => { 28 - controller.abort(); 29 - }; 30 - }, [actor]); 31 - 32 - return <div class="app">{state && <BlueskyProfileCard data={state.data} />}</div>; 33 - }; 34 - 35 - export default App; 36 - 37 - const BlueskyProfileCard = ({ data }: { data: ProfileCardData }) => { 38 - const html = useMemo(() => renderProfileCard(data), [data, renderProfileCard]); 39 - 40 - return ( 41 - <bluesky-profile-card 42 - actor={data.profile?.did} 43 - dangerouslySetInnerHTML={{ __html: html }} 44 - ></bluesky-profile-card> 45 - ); 46 - }; 47 - 48 - declare module 'preact' { 49 - namespace JSX { 50 - interface BlueskyProfileCardAttributes extends HTMLAttributes<HTMLElement> { 51 - actor?: string; 52 - } 53 - 54 - interface IntrinsicElements { 55 - 'bluesky-profile-card': BlueskyProfileCardAttributes; 56 - } 57 - } 58 - }
-8
packages/bluesky-profile-card-embed/src/main.tsx
··· 1 - import { render } from 'preact'; 2 - 3 - import App from './app'; 4 - 5 - import '../../../themes/light.css'; 6 - import './styles/main.css'; 7 - 8 - render(<App />, document.body);
-8
packages/bluesky-profile-card-embed/src/styles/main.css
··· 1 - @import './normalize.css'; 2 - 3 - .app { 4 - margin: 0 auto; 5 - padding: 36px 16px; 6 - width: 100%; 7 - max-width: calc(550px + (16 * 2px)); 8 - }
-199
packages/bluesky-profile-card-embed/src/styles/normalize.css
··· 1 - /*! modern-normalize v3.0.1 | MIT License | https://github.com/sindresorhus/modern-normalize */ 2 - 3 - /* 4 - Document 5 - ======== 6 - */ 7 - 8 - /** 9 - Use a better box model (opinionated). 10 - */ 11 - 12 - *, 13 - ::before, 14 - ::after { 15 - box-sizing: border-box; 16 - } 17 - 18 - html { 19 - line-height: 1.15; /* 1. Correct the line height in all browsers. */ 20 - /* Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3) */ 21 - font-family: 'Inter', 'Roboto', ui-sans-serif, sans-serif, 'Noto Color Emoji', 'Twemoji Mozilla'; 22 - -webkit-text-size-adjust: 100%; /* 2. Prevent adjustments of font size after orientation changes in iOS. */ 23 - tab-size: 4; /* 3. Use a more readable tab size (opinionated). */ 24 - } 25 - 26 - /* 27 - Sections 28 - ======== 29 - */ 30 - 31 - body { 32 - margin: 0; /* Remove the margin in all browsers. */ 33 - } 34 - 35 - /* 36 - Text-level semantics 37 - ==================== 38 - */ 39 - 40 - /** 41 - Add the correct font weight in Chrome and Safari. 42 - */ 43 - 44 - b, 45 - strong { 46 - font-weight: bolder; 47 - } 48 - 49 - /** 50 - 1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3) 51 - 2. Correct the odd 'em' font sizing in all browsers. 52 - */ 53 - 54 - code, 55 - kbd, 56 - samp, 57 - pre { 58 - font-size: 1em; /* 2 */ 59 - font-family: 'JetBrains Mono NL', ui-monospace, monospace; /* 1 */ 60 - } 61 - 62 - /** 63 - Add the correct font size in all browsers. 64 - */ 65 - 66 - small { 67 - font-size: 80%; 68 - } 69 - 70 - /** 71 - Prevent 'sub' and 'sup' elements from affecting the line height in all browsers. 72 - */ 73 - 74 - sub, 75 - sup { 76 - position: relative; 77 - vertical-align: baseline; 78 - font-size: 75%; 79 - line-height: 0; 80 - } 81 - 82 - sub { 83 - bottom: -0.25em; 84 - } 85 - 86 - sup { 87 - top: -0.5em; 88 - } 89 - 90 - /* 91 - Tabular data 92 - ============ 93 - */ 94 - 95 - /** 96 - Correct table border color inheritance in Chrome and Safari. (https://issues.chromium.org/issues/40615503, https://bugs.webkit.org/show_bug.cgi?id=195016) 97 - */ 98 - 99 - table { 100 - border-color: currentcolor; 101 - } 102 - 103 - /* 104 - Forms 105 - ===== 106 - */ 107 - 108 - /** 109 - 1. Change the font styles in all browsers. 110 - 2. Remove the margin in Firefox and Safari. 111 - */ 112 - 113 - button, 114 - input, 115 - optgroup, 116 - select, 117 - textarea { 118 - margin: 0; /* 2 */ 119 - font-size: 100%; /* 1 */ 120 - line-height: 1.15; /* 1 */ 121 - font-family: inherit; /* 1 */ 122 - } 123 - 124 - /** 125 - Correct the inability to style clickable types in iOS and Safari. 126 - */ 127 - 128 - button, 129 - [type='button'], 130 - [type='reset'], 131 - [type='submit'] { 132 - -webkit-appearance: button; 133 - } 134 - 135 - /** 136 - Remove the padding so developers are not caught out when they zero out 'fieldset' elements in all browsers. 137 - */ 138 - 139 - legend { 140 - padding: 0; 141 - } 142 - 143 - /** 144 - Add the correct vertical alignment in Chrome and Firefox. 145 - */ 146 - 147 - progress { 148 - vertical-align: baseline; 149 - } 150 - 151 - /** 152 - Correct the cursor style of increment and decrement buttons in Safari. 153 - */ 154 - 155 - ::-webkit-inner-spin-button, 156 - ::-webkit-outer-spin-button { 157 - height: auto; 158 - } 159 - 160 - /** 161 - 1. Correct the odd appearance in Chrome and Safari. 162 - 2. Correct the outline style in Safari. 163 - */ 164 - 165 - [type='search'] { 166 - -webkit-appearance: textfield; /* 1 */ 167 - outline-offset: -2px; /* 2 */ 168 - } 169 - 170 - /** 171 - Remove the inner padding in Chrome and Safari on macOS. 172 - */ 173 - 174 - ::-webkit-search-decoration { 175 - -webkit-appearance: none; 176 - } 177 - 178 - /** 179 - 1. Correct the inability to style clickable types in iOS and Safari. 180 - 2. Change font properties to 'inherit' in Safari. 181 - */ 182 - 183 - ::-webkit-file-upload-button { 184 - -webkit-appearance: button; /* 1 */ 185 - font: inherit; /* 2 */ 186 - } 187 - 188 - /* 189 - Interactive 190 - =========== 191 - */ 192 - 193 - /* 194 - Add the correct display in Chrome and Safari. 195 - */ 196 - 197 - summary { 198 - display: list-item; 199 - }
-8
packages/bluesky-profile-card-embed/svelte.config.js
··· 1 - export default { 2 - compilerOptions: { 3 - warningFilter: (warning) => { 4 - if (warning.code === 'state_referenced_locally') return false; 5 - return true; 6 - }, 7 - }, 8 - };
-14
packages/bluesky-profile-card-embed/tsconfig.build.json
··· 1 - { 2 - "extends": "@tsconfig/svelte/tsconfig.json", 3 - "compilerOptions": { 4 - "types": [], 5 - "target": "ESNext", 6 - "useDefineForClassFields": true, 7 - "module": "ESNext", 8 - "resolveJsonModule": true, 9 - "isolatedModules": true, 10 - "moduleDetection": "force", 11 - "noEmit": true, 12 - }, 13 - "include": ["lib"], 14 - }
-17
packages/bluesky-profile-card-embed/tsconfig.json
··· 1 - { 2 - "extends": "@tsconfig/svelte/tsconfig.json", 3 - "compilerOptions": { 4 - "types": [], 5 - "target": "ESNext", 6 - "useDefineForClassFields": true, 7 - "module": "ESNext", 8 - "resolveJsonModule": true, 9 - "isolatedModules": true, 10 - "moduleDetection": "force", 11 - "noEmit": true, 12 - "jsx": "react-jsx", 13 - "jsxImportSource": "preact", 14 - }, 15 - "include": ["lib", "src"], 16 - "references": [{ "path": "./tsconfig.node.json" }], 17 - }
-14
packages/bluesky-profile-card-embed/tsconfig.node.json
··· 1 - { 2 - "compilerOptions": { 3 - "composite": true, 4 - "types": ["node"], 5 - "skipLibCheck": true, 6 - "module": "ESNext", 7 - "target": "ESNext", 8 - "moduleResolution": "Bundler", 9 - "strict": true, 10 - "noEmit": true, 11 - "noUncheckedSideEffectImports": true, 12 - }, 13 - "include": ["vite.config.ts"], 14 - }
-103
packages/bluesky-profile-card-embed/vite.config.ts
··· 1 - import * as path from 'node:path'; 2 - 3 - import { compile as compileSvelte } from 'svelte/compiler'; 4 - import { type Plugin, createFilter, defineConfig } from 'vite'; 5 - 6 - import preact from '@preact/preset-vite'; 7 - import dts from 'vite-plugin-dts'; 8 - 9 - export default defineConfig({ 10 - base: './', 11 - build: { 12 - outDir: 'dist/', 13 - target: 'esnext', 14 - minify: false, 15 - cssMinify: false, 16 - cssCodeSplit: true, 17 - lib: { 18 - entry: { 19 - core: 'lib/core.ts', 20 - wc: 'lib/wc.ts', 21 - }, 22 - formats: ['es'], 23 - }, 24 - rollupOptions: { 25 - external: ['@atcute/client', '@atcute/bluesky-richtext-parser'], 26 - }, 27 - }, 28 - esbuild: { 29 - target: 'esnext', 30 - }, 31 - plugins: [ 32 - svelte(), 33 - preact(), 34 - dts({ 35 - rollupTypes: true, 36 - tsconfigPath: 'tsconfig.build.json', 37 - beforeWriteFile(filePath, content) { 38 - if (filePath.endsWith('/core.d.ts')) { 39 - // Make sure the relevant types are present 40 - return { content: `import '@atcute/bluesky/lexicons';\n${content}` }; 41 - } 42 - }, 43 - }), 44 - ], 45 - }); 46 - 47 - function svelte(): Plugin { 48 - const filter = createFilter('**/*.svelte'); 49 - const stylesheets = new Map<string, string>(); 50 - 51 - return { 52 - name: 'svelte', 53 - resolveId(id) { 54 - return stylesheets.has(id) ? id : null; 55 - }, 56 - load(id) { 57 - const css = stylesheets.get(id); 58 - if (css !== undefined) { 59 - this.addWatchFile(id.slice(0, -4)); 60 - return { code: css }; 61 - } 62 - 63 - return null; 64 - }, 65 - transform(source, id) { 66 - if (!filter(id)) { 67 - return null; 68 - } 69 - 70 - const result = compileSvelte(source, { 71 - generate: 'server', 72 - css: 'external', 73 - cssHash({ hash, filename }) { 74 - const prefix = `github:mary-ext/bluesky-profile-card-embed/`; 75 - return `s-` + hash(prefix + path.relative(__dirname, filename)); 76 - }, 77 - runes: true, 78 - filename: id, 79 - }); 80 - 81 - { 82 - const { js, css, warnings } = result; 83 - 84 - let jsCode = js.code; 85 - 86 - if (css) { 87 - const cssId = `${id}.css`; 88 - jsCode = jsCode + `\nimport ${JSON.stringify(cssId)};\n`; 89 - stylesheets.set(cssId, css.code); 90 - } 91 - 92 - for (const warn of warnings) { 93 - if (warn.code === 'state_referenced_locally') { 94 - continue; 95 - } 96 - this.warn(warn); 97 - } 98 - 99 - return { code: jsCode }; 100 - } 101 - }, 102 - }; 103 - }
-1
packages/bluesky-profile-feed-embed/.gitignore
··· 1 - themes/
-84
packages/bluesky-profile-feed-embed/README.md
··· 1 - # &lt;bluesky-profile-feed-embed> 2 - 3 - A custom element for embedding Bluesky profile feeds. 4 - 5 - ## Installation 6 - 7 - ### via npm 8 - 9 - ``` 10 - npm install bluesky-profile-feed-embed 11 - ``` 12 - 13 - then, import the package on your app. 14 - 15 - ```js 16 - import 'bluesky-profile-feed-embed'; 17 - 18 - import 'bluesky-profile-feed-embed/style.css'; 19 - import 'bluesky-profile-feed-embed/themes/light.css'; 20 - ``` 21 - 22 - ## Usage 23 - 24 - ```html 25 - <bluesky-profile-feed actor="did:plc:ragtjsm2j2vknwkz3zp4oxrd" include-pins> 26 - <a 27 - target="_blank" 28 - href="https://bsky.app/profile/did:plc:ragtjsm2j2vknwkz3zp4oxrd" 29 - class="bluesky-profile-feed-fallback" 30 - > 31 - Posts by Paul Frazee (@pfrazee.com) 32 - </a> 33 - </bluesky-profile-feed> 34 - ``` 35 - 36 - ### Attributes 37 - 38 - - `actor` **Required** 39 - DID or handle of the account 40 - - `include-pins` **Optional** 41 - Whether to show pinned posts 42 - - `allow-unauthenticated` **Optional** 43 - Whether to allow unauthenticated viewing 44 - - `service-uri` **Optional** 45 - URL to an AppView service, defaults to `https://public.api.bsky.app` 46 - 47 - ### Events 48 - 49 - - `loaded` 50 - Fired when the embed has successfully loaded the post 51 - - `error` 52 - Fired when the embed fails to load the post 53 - 54 - ## SSR usage 55 - 56 - The embeds are powered by a static HTML renderer, this renderer can be used directly in your 57 - server-rendering framework of choice for a zero-JS experience. 58 - 59 - ```tsx 60 - import { fetchProfileFeed, renderProfileFeed } from 'bluesky-profile-feed-embed/core'; 61 - 62 - import 'bluesky-post-embed/style.css'; 63 - import 'bluesky-post-embed/themes/light.css'; 64 - 65 - // fetch the profile 66 - const controller = new AbortController(); 67 - const data = await fetchProfileFeed({ 68 - actor: `did:plc:ragtjsm2j2vknwkz3zp4oxrd`, 69 - includePins: true, 70 - signal: controller.signal, 71 - }); 72 - 73 - // render the profile 74 - const html = renderProfileFeed(data); 75 - return ( 76 - <bluesky-profile-feed 77 - src={data.thread?.post.uri} 78 - dangerouslySetInnerHTML={{ __html: html }} 79 - ></bluesky-profile-feed> 80 - ); 81 - ``` 82 - 83 - Check out examples for [Astro](https://github.com/mary-ext/bluesky-embed-astro) and 84 - [SvelteKit](https://github.com/mary-ext/bluesky-embed-sveltekit).
-100
packages/bluesky-profile-feed-embed/lib/bluesky-profile-feed.svelte
··· 1 - <script lang="ts"> 2 - import EmbedFrame from 'internal/components/embed-frame.svelte'; 3 - import FeedPost from 'internal/components/feed-post.svelte'; 4 - import ProfileFeedHeader from 'internal/components/profile-feed-header.svelte'; 5 - 6 - import type { ProfileFeedData } from 'internal/types/profile-feed.js'; 7 - import { NO_UNAUTHENTICATED_LABEL } from 'internal/utils/constants.js'; 8 - 9 - const { profile, feed, allowUnauthenticated }: ProfileFeedData = $props(); 10 - 11 - const isPwiForbidden = 12 - !allowUnauthenticated && profile?.labels?.some((label) => label.val === NO_UNAUTHENTICATED_LABEL); 13 - 14 - const items = feed.filter((item) => { 15 - if (!profile) { 16 - return false; 17 - } 18 - 19 - const reason = item.reason; 20 - if (reason) { 21 - if (reason.$type === 'app.bsky.feed.defs#reasonPin') { 22 - return true; 23 - } 24 - 25 - if (reason.$type === 'app.bsky.feed.defs#reasonRepost') { 26 - const author = item.post.author; 27 - 28 - if (author.did !== profile.did) { 29 - return ( 30 - allowUnauthenticated || !author.labels?.some((label) => label.val === NO_UNAUTHENTICATED_LABEL) 31 - ); 32 - } 33 - 34 - return true; 35 - } 36 - 37 - // Don't show anything we don't recognize 38 - return false; 39 - } 40 - 41 - return !item.reply; 42 - }); 43 - </script> 44 - 45 - {#if profile === null} 46 - {@render Message(`The profile can't be found, it may have been deleted.`)} 47 - {:else if isPwiForbidden} 48 - {@render Message(`The user has requested for their posts to not be displayed on external sites.`)} 49 - {:else} 50 - <EmbedFrame> 51 - <ProfileFeedHeader {profile} /> 52 - 53 - {#if items.length > 0} 54 - <div class="feed"> 55 - {#each items as item} 56 - <FeedPost {item} /> 57 - {/each} 58 - 59 - <div class="end-marker"> 60 - <div class="dot"></div> 61 - </div> 62 - </div> 63 - {:else} 64 - <div class="message">This user has not made any posts.</div> 65 - {/if} 66 - </EmbedFrame> 67 - {/if} 68 - 69 - {#snippet Message(msg: string)} 70 - <EmbedFrame> 71 - <div class="message">{msg}</div> 72 - </EmbedFrame> 73 - {/snippet} 74 - 75 - <style> 76 - .message { 77 - margin: 0 auto; 78 - padding: 32px 16px; 79 - max-width: 380px; 80 - color: var(--text-secondary); 81 - text-align: center; 82 - } 83 - 84 - .feed { 85 - max-height: var(--max-feed-height); 86 - overflow-y: auto; 87 - } 88 - .end-marker { 89 - display: grid; 90 - place-items: center; 91 - height: 48px; 92 - 93 - .dot { 94 - border-radius: 50%; 95 - background: var(--text-secondary); 96 - width: 4px; 97 - height: 4px; 98 - } 99 - } 100 - </style>
-87
packages/bluesky-profile-feed-embed/lib/core.ts
··· 1 - import '@atcute/bluesky/lexicons'; 2 - 3 - import { simpleFetchHandler, XRPC, XRPCError } from '@atcute/client'; 4 - import type { At } from '@atcute/client/lexicons'; 5 - import { render } from 'svelte/server'; 6 - 7 - import type { ProfileFeedData } from 'internal/types/profile-feed.js'; 8 - import { DEFAULT_APPVIEW_URL } from 'internal/utils/constants.js'; 9 - 10 - import BlueskyProfileFeed from './bluesky-profile-feed.svelte'; 11 - 12 - export type { ProfileFeedData }; 13 - 14 - export interface ProfileFeedFetchOptions { 15 - /** 16 - * Handle or DID identifier of the user 17 - */ 18 - actor: string; 19 - /** 20 - * Abort signal to cancel the request 21 - */ 22 - signal?: AbortSignal; 23 - /** 24 - * Include pinned posts 25 - * @default false 26 - */ 27 - includePins?: boolean; 28 - /** 29 - * Allow unauthenticated viewing 30 - * @default false 31 - */ 32 - allowUnauthenticated?: boolean; 33 - /** 34 - * AppView service to use 35 - * @default "https://public.api.bsky.app" 36 - */ 37 - serviceUri?: string; 38 - } 39 - 40 - export const fetchProfileFeed = async (opts: ProfileFeedFetchOptions): Promise<ProfileFeedData> => { 41 - const actor = opts.actor as At.Identifier; 42 - const allowUnauthenticated = opts.allowUnauthenticated ?? false; 43 - 44 - const rpc = new XRPC({ handler: simpleFetchHandler({ service: opts.serviceUri ?? DEFAULT_APPVIEW_URL }) }); 45 - 46 - const [{ data: profile }, { data: timeline }] = await Promise.all([ 47 - rpc 48 - .get('app.bsky.actor.getProfile', { 49 - signal: opts.signal, 50 - params: { actor: actor as At.Identifier }, 51 - }) 52 - .catch((err) => { 53 - if (err instanceof XRPCError) { 54 - if (err.kind === 'InvalidRequest' && err.description === 'Profile not found') { 55 - return { data: null }; 56 - } 57 - } 58 - 59 - return Promise.reject(err); 60 - }), 61 - rpc 62 - .get('app.bsky.feed.getAuthorFeed', { 63 - signal: opts.signal, 64 - params: { 65 - actor, 66 - filter: 'posts_no_replies', 67 - includePins: opts.includePins, 68 - limit: 30, 69 - }, 70 - }) 71 - .catch((err) => { 72 - if (err instanceof XRPCError) { 73 - if (err.kind === 'InvalidRequest' && err.description === 'Profile not found') { 74 - return { data: { feed: [] } }; 75 - } 76 - } 77 - 78 - return Promise.reject(err); 79 - }), 80 - ]); 81 - 82 - return { profile: profile, feed: timeline.feed, allowUnauthenticated }; 83 - }; 84 - 85 - export const renderProfileFeed = (data: ProfileFeedData): string => { 86 - return render(BlueskyProfileFeed, { props: data }).body; 87 - };
-59
packages/bluesky-profile-feed-embed/lib/wc.ts
··· 1 - import { fetchProfileFeed, renderProfileFeed } from './core'; 2 - 3 - export class BlueskyProfileFeed extends HTMLElement { 4 - connectedCallback() { 5 - this.load().then( 6 - () => this.dispatchEvent(new CustomEvent('loaded')), 7 - (err) => { 8 - const defaulted = this.dispatchEvent(new CustomEvent('error', { detail: err })); 9 - if (defaulted) { 10 - throw err; 11 - } 12 - }, 13 - ); 14 - } 15 - 16 - async load() { 17 - const actor = this.getAttribute('actor')!; 18 - const serviceUri = this.getAttribute('service-uri') || undefined; 19 - const allowUnauthenticated = this.getAttribute('allow-unauthenticated') !== null; 20 - const includePins = this.getAttribute('include-pins') !== null; 21 - const silent = this.getAttribute('silent') !== null; 22 - 23 - const data = await fetchProfileFeed({ actor, allowUnauthenticated, includePins, serviceUri }).catch( 24 - (error) => { 25 - if (silent) { 26 - console.warn('Failed to fetch profile feed:', error); 27 - return null; 28 - } 29 - throw error; 30 - }, 31 - ); 32 - 33 - if (data === null) { 34 - return; 35 - } 36 - 37 - const html = renderProfileFeed(data); 38 - 39 - const root = this.shadowRoot; 40 - 41 - if (!root) { 42 - this.innerHTML = html; 43 - } else { 44 - const template = document.createElement('template'); 45 - template.innerHTML = html; 46 - 47 - const fragment = template.content; 48 - const slot = root.querySelector('slot'); 49 - 50 - if (slot) { 51 - slot.replaceWith(fragment); 52 - } else { 53 - root.appendChild(fragment); 54 - } 55 - } 56 - } 57 - } 58 - 59 - customElements.define('bluesky-profile-feed', BlueskyProfileFeed);
-43
packages/bluesky-profile-feed-embed/package.json
··· 1 - { 2 - "type": "module", 3 - "name": "bluesky-profile-feed-embed", 4 - "description": "Custom element for embedding Bluesky profile feeds", 5 - "version": "1.0.4", 6 - "author": "externdefs", 7 - "license": "MIT", 8 - "repository": { 9 - "type": "git", 10 - "url": "https://github.com/mary-ext/bluesky-embed", 11 - "directory": "packages/bluesky-profile-feed-embed" 12 - }, 13 - "files": [ 14 - "dist/", 15 - "themes/" 16 - ], 17 - "exports": { 18 - ".": "./dist/wc.js", 19 - "./core": "./dist/core.js", 20 - "./style.css": "./dist/core.css", 21 - "./themes/*": "./themes/*" 22 - }, 23 - "scripts": { 24 - "dev": "vite", 25 - "build": "pnpm run check && vite build && rsync -aHAX --delete ../../themes/ themes/", 26 - "check": "svelte-check --tsconfig ./tsconfig.json && tsc -p tsconfig.node.json", 27 - "prepack": "pnpm run build" 28 - }, 29 - "dependencies": { 30 - "@atcute/bluesky": "^2.1.1", 31 - "@atcute/bluesky-richtext-segmenter": "^2.0.4", 32 - "@atcute/client": "^3.1.0" 33 - }, 34 - "devDependencies": { 35 - "@tsconfig/svelte": "^5.0.6", 36 - "@types/node": "^24.10.1", 37 - "internal": "workspace:^", 38 - "svelte": "catalog:", 39 - "svelte-check": "^4.3.4", 40 - "vite": "^7.2.6", 41 - "vite-plugin-dts": "^4.5.4" 42 - } 43 - }
-8
packages/bluesky-profile-feed-embed/svelte.config.js
··· 1 - export default { 2 - compilerOptions: { 3 - warningFilter: (warning) => { 4 - if (warning.code === 'state_referenced_locally') return false; 5 - return true; 6 - }, 7 - }, 8 - };
-15
packages/bluesky-profile-feed-embed/tsconfig.json
··· 1 - { 2 - "extends": "@tsconfig/svelte/tsconfig.json", 3 - "compilerOptions": { 4 - "types": [], 5 - "target": "ESNext", 6 - "useDefineForClassFields": true, 7 - "module": "ESNext", 8 - "resolveJsonModule": true, 9 - "isolatedModules": true, 10 - "moduleDetection": "force", 11 - "noEmit": true, 12 - }, 13 - "include": ["lib"], 14 - "references": [{ "path": "./tsconfig.node.json" }], 15 - }
-14
packages/bluesky-profile-feed-embed/tsconfig.node.json
··· 1 - { 2 - "compilerOptions": { 3 - "composite": true, 4 - "types": ["node"], 5 - "skipLibCheck": true, 6 - "module": "ESNext", 7 - "target": "ESNext", 8 - "moduleResolution": "Bundler", 9 - "strict": true, 10 - "noEmit": true, 11 - "noUncheckedSideEffectImports": true, 12 - }, 13 - "include": ["vite.config.ts"], 14 - }
-100
packages/bluesky-profile-feed-embed/vite.config.ts
··· 1 - import * as path from 'node:path'; 2 - 3 - import { compile as compileSvelte } from 'svelte/compiler'; 4 - import { type Plugin, createFilter, defineConfig } from 'vite'; 5 - 6 - import dts from 'vite-plugin-dts'; 7 - 8 - export default defineConfig({ 9 - base: './', 10 - build: { 11 - outDir: 'dist/', 12 - target: 'esnext', 13 - minify: false, 14 - cssMinify: false, 15 - cssCodeSplit: true, 16 - lib: { 17 - entry: { 18 - core: 'lib/core.ts', 19 - wc: 'lib/wc.ts', 20 - }, 21 - formats: ['es'], 22 - }, 23 - rollupOptions: { 24 - external: ['@atcute/client', '@atcute/bluesky-richtext-segmenter'], 25 - }, 26 - }, 27 - esbuild: { 28 - target: 'esnext', 29 - }, 30 - plugins: [ 31 - svelte(), 32 - dts({ 33 - rollupTypes: true, 34 - beforeWriteFile(filePath, content) { 35 - if (filePath.endsWith('/core.d.ts')) { 36 - // Make sure the relevant types are present 37 - return { content: `import '@atcute/bluesky/lexicons';\n${content}` }; 38 - } 39 - }, 40 - }), 41 - ], 42 - }); 43 - 44 - function svelte(): Plugin { 45 - const filter = createFilter('**/*.svelte'); 46 - const stylesheets = new Map<string, string>(); 47 - 48 - return { 49 - name: 'svelte', 50 - resolveId(id) { 51 - return stylesheets.has(id) ? id : null; 52 - }, 53 - load(id) { 54 - const css = stylesheets.get(id); 55 - if (css !== undefined) { 56 - this.addWatchFile(id.slice(0, -4)); 57 - return { code: css }; 58 - } 59 - 60 - return null; 61 - }, 62 - transform(source, id) { 63 - if (!filter(id)) { 64 - return null; 65 - } 66 - 67 - const result = compileSvelte(source, { 68 - generate: 'server', 69 - css: 'external', 70 - cssHash({ hash, filename }) { 71 - const prefix = `github:mary-ext/bluesky-profile-feed-embed/`; 72 - return `s-` + hash(prefix + path.relative(__dirname, filename)); 73 - }, 74 - runes: true, 75 - filename: id, 76 - }); 77 - 78 - { 79 - const { js, css, warnings } = result; 80 - 81 - let jsCode = js.code; 82 - 83 - if (css) { 84 - const cssId = `${id}.css`; 85 - jsCode = jsCode + `\nimport ${JSON.stringify(cssId)};\n`; 86 - stylesheets.set(cssId, css.code); 87 - } 88 - 89 - for (const warn of warnings) { 90 - if (warn.code === 'state_referenced_locally') { 91 - continue; 92 - } 93 - this.warn(warn); 94 - } 95 - 96 - return { code: jsCode }; 97 - } 98 - }, 99 - }; 100 - }
-88
packages/internal/components/content-hider.svelte
··· 1 - <script lang="ts"> 2 - import type { Snippet } from 'svelte'; 3 - import type { LabelDefinition } from '../utils/labels'; 4 - 5 - interface Props { 6 - warning: LabelDefinition | undefined; 7 - children: Snippet; 8 - } 9 - 10 - const { warning, children }: Props = $props(); 11 - </script> 12 - 13 - {#if !warning} 14 - {@render children()} 15 - {:else} 16 - <details class="content-hider"> 17 - <summary class="gate"> 18 - <svg class="icon" fill="none" viewBox="0 0 24 24"> 19 - <path 20 - stroke="currentColor" 21 - stroke-linecap="square" 22 - stroke-width="2" 23 - d="M11 11h1v5m9-4a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" 24 - /> 25 - <path 26 - fill="currentColor" 27 - stroke="currentColor" 28 - stroke-width=".5" 29 - d="M11.5 7.25h-.25v1.5h1.5v-1.5H11.5Z" 30 - /> 31 - </svg> 32 - 33 - <span class="label">{warning.name}</span> 34 - 35 - <span class="action"></span> 36 - </summary> 37 - 38 - {@render children()} 39 - </details> 40 - {/if} 41 - 42 - <style> 43 - .gate { 44 - display: flex; 45 - align-items: center; 46 - gap: 12px; 47 - cursor: pointer; 48 - border: 1px solid var(--divider); 49 - border-radius: 6px; 50 - padding: 0 12px; 51 - height: 44px; 52 - 53 - .content-hider[open] & { 54 - margin-bottom: 12px; 55 - } 56 - 57 - &:hover { 58 - border-color: var(--divider-hover); 59 - } 60 - } 61 - 62 - .icon { 63 - width: 18px; 64 - height: 18px; 65 - color: var(--text-secondary); 66 - } 67 - .label { 68 - flex-grow: 1; 69 - overflow: hidden; 70 - font-weight: 500; 71 - user-select: none; 72 - text-overflow: ellipsis; 73 - } 74 - 75 - .action { 76 - color: var(--text-link); 77 - font-weight: 500; 78 - font-size: calc(var(--font-size) * 0.8125); 79 - line-height: calc(var(--font-size) * 1.25); 80 - 81 - &::before { 82 - content: 'Show'; 83 - } 84 - .content-hider[open] &::before { 85 - content: 'Hide'; 86 - } 87 - } 88 - </style>
-50
packages/internal/components/embed-frame.svelte
··· 1 - <script lang="ts"> 2 - import type { Snippet } from 'svelte'; 3 - 4 - interface Props { 5 - children: Snippet; 6 - } 7 - 8 - const { children }: Props = $props(); 9 - </script> 10 - 11 - <div class="bluesky-embed"> 12 - {@render children()} 13 - </div> 14 - 15 - <style> 16 - .bluesky-embed { 17 - position: relative; 18 - box-sizing: border-box; 19 - margin: 0 auto; 20 - border: 1px solid var(--divider); 21 - border-radius: 8px; 22 - background: var(--background-primary); 23 - min-width: 250px; 24 - max-width: 550px; 25 - overflow: hidden; 26 - color: var(--text-primary); 27 - font-weight: 400; 28 - font-size: calc(var(--font-size) * 0.875); 29 - line-height: calc(var(--font-size) * 1.25); 30 - font-family: var(--font-family); 31 - 32 - :global(:where(*)), 33 - :global(:where(*::before)), 34 - :global(:where(*::after)) { 35 - box-sizing: border-box; 36 - margin: 0; 37 - padding: 0; 38 - } 39 - :global(:where(a)) { 40 - color: inherit; 41 - text-decoration: none; 42 - } 43 - 44 - :global(:where(.icon)) { 45 - flex-shrink: 0; 46 - width: 1em; 47 - height: 1em; 48 - } 49 - } 50 - </style>
-126
packages/internal/components/embeds/embeds.svelte
··· 1 - <script lang="ts" module> 2 - const collectionToLabel = (collection: string): string | null => { 3 - switch (collection) { 4 - case 'app.bsky.feed.post': 5 - return 'post'; 6 - case 'app.bsky.feed.generator': 7 - return 'feed'; 8 - case 'app.bsky.graph.list': 9 - return 'list'; 10 - case 'app.bsky.graph.starterpack': 11 - return 'starter pack'; 12 - case 'app.bsky.labeler.service': 13 - return 'labeler'; 14 - } 15 - 16 - return null; 17 - }; 18 - </script> 19 - 20 - <script lang="ts"> 21 - import type { 22 - AppBskyEmbedExternal, 23 - AppBskyEmbedImages, 24 - AppBskyEmbedRecord, 25 - AppBskyEmbedVideo, 26 - AppBskyFeedDefs, 27 - Brand, 28 - } from '@atcute/client/lexicons'; 29 - 30 - import { findLabel } from '../../utils/labels'; 31 - import { parseAtUri } from '../../utils/syntax/at-url'; 32 - 33 - import ContentHider from '../content-hider.svelte'; 34 - 35 - import ExternalEmbed from './external-embed.svelte'; 36 - import FeedEmbed from './feed-embed.svelte'; 37 - import ImageEmbed from './image-embed.svelte'; 38 - import ListEmbed from './list-embed.svelte'; 39 - import QuoteEmbed from './quote-embed.svelte'; 40 - import StarterpackEmbed from './starterpack-embed.svelte'; 41 - import VideoEmbed from './video-embed.svelte'; 42 - 43 - type Embed = NonNullable<AppBskyFeedDefs.PostView['embed']>; 44 - type MediaEmbed = Brand.Union<AppBskyEmbedExternal.View | AppBskyEmbedImages.View | AppBskyEmbedVideo.View>; 45 - type RecordEmbed = AppBskyEmbedRecord.View; 46 - 47 - interface Props { 48 - post?: AppBskyFeedDefs.PostView; 49 - embed: Embed; 50 - large?: boolean; 51 - } 52 - 53 - const { post, embed, large = false }: Props = $props(); 54 - </script> 55 - 56 - <div class="embeds"> 57 - {#if embed.$type === 'app.bsky.embed.recordWithMedia#view'} 58 - {@render Media(embed.media)} 59 - {@render Record(embed.record)} 60 - {:else if embed.$type === 'app.bsky.embed.record#view'} 61 - {@render Record(embed)} 62 - {:else} 63 - {@render Media(embed)} 64 - {/if} 65 - </div> 66 - 67 - {#snippet Media(embed: MediaEmbed)} 68 - {@const warning = post && findLabel(post.labels, post.author.did)} 69 - 70 - <ContentHider {warning}> 71 - {#if embed.$type === 'app.bsky.embed.external#view'} 72 - <ExternalEmbed {embed} /> 73 - {:else if embed.$type === 'app.bsky.embed.images#view'} 74 - <ImageEmbed {embed} standalone /> 75 - {:else if embed.$type === 'app.bsky.embed.video#view'} 76 - <VideoEmbed {post} {embed} standalone /> 77 - {:else} 78 - {@render Message(`Unsupported media embed`)} 79 - {/if} 80 - </ContentHider> 81 - {/snippet} 82 - 83 - {#snippet Record(embed: RecordEmbed)} 84 - {@const record = embed.record} 85 - 86 - {#if record.$type === 'app.bsky.embed.record#viewRecord'} 87 - <QuoteEmbed embed={record} {large} /> 88 - {:else if record.$type === 'app.bsky.feed.defs#generatorView'} 89 - <FeedEmbed embed={record} /> 90 - {:else if record.$type === 'app.bsky.graph.defs#listView'} 91 - <ListEmbed embed={record} /> 92 - {:else if record.$type === 'app.bsky.graph.defs#starterPackViewBasic'} 93 - <StarterpackEmbed embed={record} {large} /> 94 - {:else} 95 - {@const uri = parseAtUri(record.uri)} 96 - {@const resource = collectionToLabel(uri.collection)} 97 - 98 - {@const isUnavailable = 99 - resource && 100 - (record.$type === 'app.bsky.embed.record#viewNotFound' || 101 - record.$type === 'app.bsky.embed.record#viewBlocked' || 102 - record.$type === 'app.bsky.embed.record#viewDetached')} 103 - 104 - {@render Message(isUnavailable ? `This ${resource} is unavailable` : `Unsupported record embed`)} 105 - {/if} 106 - {/snippet} 107 - 108 - {#snippet Message(message: string)} 109 - <div class="message">{message}</div> 110 - {/snippet} 111 - 112 - <style> 113 - .embeds { 114 - display: flex; 115 - flex-direction: column; 116 - gap: 12px; 117 - margin: 12px 0 0 0; 118 - } 119 - 120 - .message { 121 - border: 1px solid var(--divider); 122 - border-radius: 6px; 123 - padding: 12px; 124 - color: var(--text-secondary); 125 - } 126 - </style>
-129
packages/internal/components/embeds/external-embed.svelte
··· 1 - <script lang="ts" module> 2 - const safeParseUrl = (str: string): URL | null => { 3 - let url: URL | null | undefined; 4 - if ('parse' in URL) { 5 - url = URL.parse(str); 6 - } else { 7 - try { 8 - // @ts-expect-error: `'parse' in URL` is giving truthy 9 - url = new URL(str); 10 - } catch {} 11 - } 12 - 13 - if (url && (url.protocol === 'https:' || url.protocol === 'http:')) { 14 - return url; 15 - } 16 - 17 - return null; 18 - }; 19 - </script> 20 - 21 - <script lang="ts"> 22 - import type { AppBskyEmbedExternal } from '@atcute/client/lexicons'; 23 - 24 - interface Props { 25 - embed: AppBskyEmbedExternal.View; 26 - } 27 - 28 - const { embed }: Props = $props(); 29 - 30 - const external = embed.external; 31 - 32 - const domain = safeParseUrl(external.uri)?.host; 33 - </script> 34 - 35 - <a target="_blank" href={domain && external.uri} rel="noopener noreferrer nofollow" class="external-embed"> 36 - {#if external.thumb} 37 - <img loading="lazy" src={external.thumb} alt="" class="thumbnail" /> 38 - {/if} 39 - 40 - <div class="meta"> 41 - <p class="title">{external.title}</p> 42 - <p class="description">{external.description}</p> 43 - 44 - {#if domain} 45 - <div class="domain"> 46 - <!-- earth --> 47 - <svg class="icon" fill="none" viewBox="0 0 24 24"> 48 - <path 49 - stroke="currentColor" 50 - stroke-linecap="round" 51 - stroke-width="2" 52 - d="m4.172 8.07 3.94 2.957.977-1.941 3.887-.978 1.15-4.6M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-6.078 4.865.973-1.946-2.869-1.928-1.89-.12-1.08 1.075 1.947 2.919h2.919Z" 53 - /> 54 - </svg> 55 - 56 - <span class="domain-name">{domain}</span> 57 - </div> 58 - {/if} 59 - </div> 60 - </a> 61 - 62 - <style> 63 - .external-embed { 64 - display: block; 65 - border: 1px solid var(--divider); 66 - border-radius: 6px; 67 - overflow: hidden; 68 - 69 - &:hover { 70 - border-color: var(--divider-hover); 71 - } 72 - } 73 - 74 - .thumbnail { 75 - display: block; 76 - border-bottom: 1px solid var(--divider); 77 - background: #000000; 78 - aspect-ratio: 1.91; 79 - width: 100%; 80 - 81 - .external-embed:hover & { 82 - border-color: var(--divider-hover); 83 - } 84 - } 85 - 86 - .meta { 87 - padding: 12px; 88 - } 89 - 90 - .title { 91 - display: -webkit-box; 92 - overflow: hidden; 93 - font-weight: 700; 94 - white-space: pre-wrap; 95 - -webkit-box-orient: vertical; 96 - -webkit-line-clamp: 2; 97 - line-clamp: 2; 98 - overflow-wrap: break-word; 99 - 100 - &:empty { 101 - display: none; 102 - } 103 - } 104 - .description { 105 - display: -webkit-box; 106 - overflow: hidden; 107 - color: var(--text-secondary); 108 - font-size: calc(var(--font-size) * 0.8125); 109 - white-space: pre-wrap; 110 - -webkit-box-orient: vertical; 111 - -webkit-line-clamp: 2; 112 - line-clamp: 2; 113 - overflow-wrap: break-word; 114 - 115 - &:empty { 116 - display: none; 117 - } 118 - } 119 - 120 - .domain { 121 - display: flex; 122 - align-items: center; 123 - gap: 6px; 124 - margin: 6px 0 0 0; 125 - color: var(--text-secondary); 126 - font-weight: 500; 127 - font-size: calc(var(--font-size) * 0.75); 128 - } 129 - </style>
-100
packages/internal/components/embeds/feed-embed.svelte
··· 1 - <script lang="ts"> 2 - import type { AppBskyFeedDefs } from '@atcute/client/lexicons'; 3 - 4 - import { getFeedUrl } from '../../utils/bsky-url'; 5 - import { parseAtUri } from '../../utils/syntax/at-url'; 6 - 7 - interface Props { 8 - embed: AppBskyFeedDefs.GeneratorView; 9 - } 10 - 11 - const { embed: feed }: Props = $props(); 12 - 13 - const creator = feed.creator; 14 - 15 - const feedUrl = getFeedUrl(creator.did, parseAtUri(feed.uri).rkey); 16 - </script> 17 - 18 - <a target="_blank" href={feedUrl} class="feed-embed"> 19 - <div class="main"> 20 - <div class="avatar-wrapper"> 21 - {#if feed.avatar} 22 - <img loading="lazy" src={feed.avatar} alt="" class="avatar" /> 23 - {:else} 24 - <svg viewBox="0 0 32 32" class="avatar"> 25 - <path fill="#0070FF" d="M0 0h32v32H0z" /> 26 - <path 27 - fill="#fff" 28 - d="M22.153 22.354a9.328 9.328 0 0 0 3.837-.491 3.076 3.076 0 0 0-4.802-2.79m.965 3.281a6.128 6.128 0 0 0-.965-3.28Zm-11.342-3.28a3.077 3.077 0 0 0-4.801 2.79 9.21 9.21 0 0 0 3.835.49m.966-3.28a6.127 6.127 0 0 0-.966 3.28Zm8.265-8.997a3.076 3.076 0 1 1-6.153 0 3.076 3.076 0 0 1 6.153 0Zm6.154 3.077a2.307 2.307 0 1 1-4.615 0 2.307 2.307 0 0 1 4.615 0Zm-13.847 0a2.307 2.307 0 1 1-4.614 0 2.307 2.307 0 0 1 4.614 0Z" 29 - /> 30 - <path fill="#fff" d="M22 22c0 3.314-2.686 3.5-6 3.5s-6-.186-6-3.5a6 6 0 0 1 12 0Z" /> 31 - </svg> 32 - {/if} 33 - </div> 34 - 35 - <div class="info"> 36 - <p class="name">{feed.displayName}</p> 37 - <p class="creator">Feed by @{creator.handle}</p> 38 - </div> 39 - </div> 40 - 41 - <p class="description">{feed.description}</p> 42 - </a> 43 - 44 - <style> 45 - .feed-embed { 46 - display: flex; 47 - flex-direction: column; 48 - gap: 12px; 49 - border: 1px solid var(--divider); 50 - border-radius: 6px; 51 - padding: 12px; 52 - 53 - &:hover { 54 - border-color: var(--divider-hover); 55 - } 56 - } 57 - 58 - .main { 59 - display: flex; 60 - gap: 12px; 61 - } 62 - 63 - .avatar-wrapper { 64 - margin: 2px 0 0 0; 65 - border-radius: 6px; 66 - background: var(--background-secondary); 67 - width: 36px; 68 - height: 36px; 69 - overflow: hidden; 70 - } 71 - .avatar { 72 - width: 100%; 73 - height: 100%; 74 - object-fit: cover; 75 - } 76 - 77 - .name { 78 - font-weight: 700; 79 - } 80 - 81 - .creator { 82 - color: var(--text-secondary); 83 - font-size: calc(var(--font-size) * 0.8125); 84 - } 85 - 86 - .description { 87 - display: -webkit-box; 88 - overflow: hidden; 89 - font-size: calc(var(--font-size) * 0.8125); 90 - white-space: pre-wrap; 91 - -webkit-box-orient: vertical; 92 - -webkit-line-clamp: 2; 93 - line-clamp: 2; 94 - overflow-wrap: break-word; 95 - 96 - &:empty { 97 - display: none; 98 - } 99 - } 100 - </style>
-183
packages/internal/components/embeds/image-embed.svelte
··· 1 - <script lang="ts" module> 2 - const DEFAULT_RATIO = { width: 16, height: 9 }; 3 - </script> 4 - 5 - <script lang="ts"> 6 - import type { AppBskyEmbedImages } from '@atcute/client/lexicons'; 7 - 8 - interface Props { 9 - embed: AppBskyEmbedImages.View; 10 - borderless?: boolean; 11 - standalone?: boolean; 12 - blur?: boolean; 13 - } 14 - 15 - const { embed, borderless, standalone, blur }: Props = $props(); 16 - 17 - const images = embed.images; 18 - const length = images.length; 19 - </script> 20 - 21 - <div 22 - class={'image-embed' + 23 - (!borderless ? ` is-bordered` : ``) + 24 - (standalone && length === 1 ? ` is-aligned` : ``)} 25 - > 26 - {#if length === 4} 27 - <div class="grid"> 28 - <div class="col"> 29 - <div class="item wide tl"> 30 - {@render Image(0)} 31 - </div> 32 - <div class="item wide bl"> 33 - {@render Image(2)} 34 - </div> 35 - </div> 36 - <div class="col"> 37 - <div class="item wide tr"> 38 - {@render Image(1)} 39 - </div> 40 - <div class="item wide br"> 41 - {@render Image(3)} 42 - </div> 43 - </div> 44 - </div> 45 - {:else if length === 3} 46 - <div class="grid"> 47 - <div class="col square"> 48 - <div class="item tl bl"> 49 - {@render Image(0)} 50 - </div> 51 - </div> 52 - <div class="col square"> 53 - <div class="item tr"> 54 - {@render Image(1)} 55 - </div> 56 - <div class="item br"> 57 - {@render Image(2)} 58 - </div> 59 - </div> 60 - </div> 61 - {:else if length === 2} 62 - <div class="grid"> 63 - <div class="col"> 64 - <div class="item square tl bl"> 65 - {@render Image(0)} 66 - </div> 67 - </div> 68 - <div class="col"> 69 - <div class="item square tr br"> 70 - {@render Image(1)} 71 - </div> 72 - </div> 73 - </div> 74 - {:else if length === 1} 75 - {@const ratio = standalone && (images[0].aspectRatio || DEFAULT_RATIO)} 76 - 77 - <div 78 - class={`single-item tl tr bl br` + (ratio ? ` is-standalone` : ``)} 79 - style={ratio ? `aspect-ratio: ${ratio.width}/${ratio.height}` : ``} 80 - > 81 - {@render Image(0)} 82 - 83 - {#if ratio} 84 - <div class="placeholder"></div> 85 - {/if} 86 - </div> 87 - {/if} 88 - </div> 89 - 90 - {#snippet Image(index: number)} 91 - {@const image = images[index]} 92 - 93 - <img loading="lazy" src={image.thumb} alt={image.alt} class={`image` + (blur ? ` is-blurred` : ``)} /> 94 - {/snippet} 95 - 96 - <style> 97 - .is-aligned { 98 - align-self: baseline; 99 - max-width: 100%; 100 - } 101 - 102 - .grid { 103 - display: flex; 104 - gap: 2px; 105 - } 106 - .col { 107 - display: flex; 108 - flex: 1; 109 - flex-direction: column; 110 - gap: 2px; 111 - } 112 - 113 - .square { 114 - aspect-ratio: 1; 115 - } 116 - .wide { 117 - aspect-ratio: 1.5; 118 - } 119 - 120 - .item { 121 - position: relative; 122 - flex-grow: 1; 123 - flex-shrink: 0; 124 - overflow: hidden; 125 - } 126 - 127 - .is-bordered { 128 - .tl, 129 - .tr, 130 - .bl, 131 - .br { 132 - border: 1px solid var(--divider); 133 - } 134 - 135 - .tl { 136 - border-top-left-radius: 6px; 137 - } 138 - .tr { 139 - border-top-right-radius: 6px; 140 - } 141 - .bl { 142 - border-bottom-left-radius: 6px; 143 - } 144 - .br { 145 - border-bottom-right-radius: 6px; 146 - } 147 - } 148 - 149 - .single-item { 150 - position: relative; 151 - aspect-ratio: 16 / 9; 152 - overflow: hidden; 153 - 154 - .image { 155 - object-fit: contain; 156 - } 157 - } 158 - .is-standalone { 159 - min-width: 64px; 160 - max-width: 100%; 161 - min-height: 64px; 162 - max-height: 320px; 163 - } 164 - 165 - .image { 166 - position: absolute; 167 - inset: 0; 168 - background: #000000; 169 - width: 100%; 170 - height: 100%; 171 - object-fit: cover; 172 - font-size: 0px; 173 - } 174 - .is-blurred { 175 - scale: 125%; 176 - filter: blur(24px); 177 - } 178 - 179 - .placeholder { 180 - width: 100vw; 181 - height: 100vh; 182 - } 183 - </style>
-113
packages/internal/components/embeds/list-embed.svelte
··· 1 - <script lang="ts" module> 2 - const getPurpose = (purpose: AppBskyGraphDefs.ListPurpose) => { 3 - switch (purpose) { 4 - case 'app.bsky.graph.defs#curatelist': 5 - return `User list`; 6 - case 'app.bsky.graph.defs#modlist': 7 - return `Moderation list`; 8 - } 9 - 10 - return `Unknown list`; 11 - }; 12 - </script> 13 - 14 - <script lang="ts"> 15 - import type { AppBskyGraphDefs } from '@atcute/client/lexicons'; 16 - 17 - import { getFeedUrl } from '../../utils/bsky-url'; 18 - import { parseAtUri } from '../../utils/syntax/at-url'; 19 - 20 - interface Props { 21 - embed: AppBskyGraphDefs.ListView; 22 - } 23 - 24 - const { embed: list }: Props = $props(); 25 - 26 - const creator = list.creator; 27 - 28 - const listUrl = getFeedUrl(creator.did, parseAtUri(list.uri).rkey); 29 - </script> 30 - 31 - <a target="_blank" href={listUrl} class="list-embed"> 32 - <div class="main"> 33 - <div class="avatar-wrapper"> 34 - {#if list.avatar} 35 - <img loading="lazy" src={list.avatar} alt="" class="avatar" /> 36 - {:else} 37 - <svg viewBox="0 0 32 32" class="avatar"> 38 - <path fill="#0070FF" d="M0 0h32v32H0z" /> 39 - <path 40 - fill="#fff" 41 - d="M22.153 22.354a9.328 9.328 0 0 0 3.837-.491 3.076 3.076 0 0 0-4.802-2.79m.965 3.281a6.128 6.128 0 0 0-.965-3.28Zm-11.342-3.28a3.077 3.077 0 0 0-4.801 2.79 9.21 9.21 0 0 0 3.835.49m.966-3.28a6.127 6.127 0 0 0-.966 3.28Zm8.265-8.997a3.076 3.076 0 1 1-6.153 0 3.076 3.076 0 0 1 6.153 0Zm6.154 3.077a2.307 2.307 0 1 1-4.615 0 2.307 2.307 0 0 1 4.615 0Zm-13.847 0a2.307 2.307 0 1 1-4.614 0 2.307 2.307 0 0 1 4.614 0Z" 42 - /> 43 - <path fill="#fff" d="M22 22c0 3.314-2.686 3.5-6 3.5s-6-.186-6-3.5a6 6 0 0 1 12 0Z" /> 44 - </svg> 45 - {/if} 46 - </div> 47 - 48 - <div class="info"> 49 - <p class="name">{list.name}</p> 50 - <p class="creator">{getPurpose(list.purpose)} by @{creator.handle}</p> 51 - </div> 52 - </div> 53 - 54 - <p class="description">{list.description}</p> 55 - </a> 56 - 57 - <style> 58 - .list-embed { 59 - display: flex; 60 - flex-direction: column; 61 - gap: 12px; 62 - border: 1px solid var(--divider); 63 - border-radius: 6px; 64 - padding: 12px; 65 - 66 - &:hover { 67 - border-color: var(--divider-hover); 68 - } 69 - } 70 - 71 - .main { 72 - display: flex; 73 - gap: 12px; 74 - } 75 - 76 - .avatar-wrapper { 77 - margin: 2px 0 0 0; 78 - border-radius: 6px; 79 - background: var(--background-secondary); 80 - width: 36px; 81 - height: 36px; 82 - overflow: hidden; 83 - } 84 - .avatar { 85 - width: 100%; 86 - height: 100%; 87 - object-fit: cover; 88 - } 89 - 90 - .name { 91 - font-weight: 700; 92 - } 93 - 94 - .creator { 95 - color: var(--text-secondary); 96 - font-size: calc(var(--font-size) * 0.8125); 97 - } 98 - 99 - .description { 100 - display: -webkit-box; 101 - overflow: hidden; 102 - font-size: calc(var(--font-size) * 0.8125); 103 - white-space: pre-wrap; 104 - -webkit-box-orient: vertical; 105 - -webkit-line-clamp: 2; 106 - line-clamp: 2; 107 - overflow-wrap: break-word; 108 - 109 - &:empty { 110 - display: none; 111 - } 112 - } 113 - </style>
-213
packages/internal/components/embeds/quote-embed.svelte
··· 1 - <script lang="ts" module> 2 - const getPostImage = (embed: AppBskyFeedDefs.PostView['embed']): AppBskyEmbedImages.View | undefined => { 3 - if (embed) { 4 - if (embed.$type === 'app.bsky.embed.images#view') { 5 - return embed; 6 - } 7 - 8 - if (embed.$type === 'app.bsky.embed.recordWithMedia#view') { 9 - return getPostImage(embed.media); 10 - } 11 - } 12 - }; 13 - 14 - const getPostVideo = (embed: AppBskyFeedDefs.PostView['embed']): AppBskyEmbedVideo.View | undefined => { 15 - if (embed) { 16 - if (embed.$type === 'app.bsky.embed.video#view') { 17 - return embed; 18 - } 19 - 20 - if (embed.$type === 'app.bsky.embed.recordWithMedia#view') { 21 - return getPostVideo(embed.media); 22 - } 23 - } 24 - }; 25 - </script> 26 - 27 - <script lang="ts"> 28 - import type { 29 - AppBskyEmbedImages, 30 - AppBskyEmbedRecord, 31 - AppBskyEmbedVideo, 32 - AppBskyFeedDefs, 33 - AppBskyFeedPost, 34 - } from '@atcute/client/lexicons'; 35 - 36 - import { getPostUrl } from '../../utils/bsky-url'; 37 - import { formatShortDate } from '../../utils/date'; 38 - import { findLabel } from '../../utils/labels'; 39 - import { parseAtUri } from '../../utils/syntax/at-url'; 40 - 41 - import ImageEmbed from './image-embed.svelte'; 42 - import VideoEmbed from './video-embed.svelte'; 43 - 44 - interface Props { 45 - embed: AppBskyEmbedRecord.ViewRecord; 46 - large?: boolean; 47 - } 48 - 49 - const { embed: quote, large = false }: Props = $props(); 50 - 51 - const record = quote.value as AppBskyFeedPost.Record; 52 - const text = record.text.trim(); 53 - 54 - const author = quote.author; 55 - const authorName = author.displayName?.trim(); 56 - 57 - const embed = quote.embeds?.[0]; 58 - const image = getPostImage(embed); 59 - const video = getPostVideo(embed); 60 - 61 - const postUrl = getPostUrl(author.did, parseAtUri(quote.uri).rkey); 62 - 63 - const isMediaBlurred = !!findLabel(quote.labels, author.did); 64 - </script> 65 - 66 - <a target="_blank" href={postUrl} class="quote-embed"> 67 - <div class="meta"> 68 - <div class="avatar-wrapper"> 69 - {#if author.avatar} 70 - <img loading="lazy" src={author.avatar} alt="" class="avatar" /> 71 - {/if} 72 - </div> 73 - 74 - <span class="name-wrapper"> 75 - {#if authorName} 76 - <bdi class="display-name-wrapper"> 77 - <span class="display-name">{authorName}</span> 78 - </bdi> 79 - {/if} 80 - 81 - <span class="handle">@{author.handle}</span> 82 - </span> 83 - 84 - <span aria-hidden="true" class="dot">ยท</span> 85 - 86 - <time datetime={record.createdAt} class="date"> 87 - {formatShortDate(record.createdAt)} 88 - </time> 89 - </div> 90 - 91 - {#if text} 92 - <div class="body"> 93 - {#if !large} 94 - {#if image} 95 - <div class="aside"> 96 - <ImageEmbed embed={image} blur={isMediaBlurred} /> 97 - </div> 98 - {:else if video} 99 - <div class="aside"> 100 - <VideoEmbed embed={video} blur={isMediaBlurred} /> 101 - </div> 102 - {/if} 103 - {/if} 104 - 105 - <p class="text">{text}</p> 106 - </div> 107 - {:else} 108 - <div class="divide"></div> 109 - {/if} 110 - 111 - {#if large || !text} 112 - {#if image} 113 - <ImageEmbed embed={image} borderless blur={isMediaBlurred} /> 114 - {:else if video} 115 - <VideoEmbed embed={video} borderless blur={isMediaBlurred} /> 116 - {/if} 117 - {/if} 118 - </a> 119 - 120 - <style> 121 - .quote-embed { 122 - display: block; 123 - border: 1px solid var(--divider); 124 - border-radius: 6px; 125 - overflow: hidden; 126 - 127 - &:hover { 128 - border-color: var(--divider-hover); 129 - } 130 - } 131 - 132 - .meta { 133 - display: flex; 134 - padding: 12px 12px 0 12px; 135 - color: var(--text-secondary); 136 - 137 - .avatar-wrapper { 138 - flex-shrink: 0; 139 - margin: 0 8px 0 0; 140 - border-radius: 9999px; 141 - background: var(--background-secondary); 142 - width: 20px; 143 - height: 20px; 144 - overflow: hidden; 145 - } 146 - .avatar { 147 - width: 100%; 148 - height: 100%; 149 - } 150 - 151 - .name-wrapper { 152 - display: flex; 153 - gap: 4px; 154 - max-width: 100%; 155 - overflow: hidden; 156 - text-overflow: ellipsis; 157 - white-space: nowrap; 158 - } 159 - .display-name-wrapper { 160 - overflow: hidden; 161 - text-overflow: ellipsis; 162 - } 163 - .display-name { 164 - color: var(--text-primary); 165 - font-weight: 700; 166 - } 167 - .handle { 168 - display: block; 169 - overflow: hidden; 170 - text-overflow: ellipsis; 171 - white-space: nowrap; 172 - } 173 - 174 - .dot { 175 - flex-shrink: 0; 176 - margin: 0 6px; 177 - } 178 - 179 - .date { 180 - white-space: nowrap; 181 - } 182 - } 183 - 184 - .body { 185 - display: flex; 186 - align-items: flex-start; 187 - } 188 - 189 - .aside { 190 - flex-grow: 1; 191 - flex-basis: 0; 192 - margin: 8px 0 12px 12px; 193 - max-width: 20%; 194 - } 195 - 196 - .text { 197 - display: -webkit-box; 198 - margin: 8px 12px 12px 12px; 199 - overflow: hidden; 200 - -webkit-box-orient: vertical; 201 - flex-grow: 4; 202 - flex-basis: 0px; 203 - min-width: 0px; 204 - -webkit-line-clamp: 6; 205 - line-clamp: 6; 206 - white-space: pre-wrap; 207 - overflow-wrap: break-word; 208 - } 209 - 210 - .divide { 211 - padding: 6px 0; 212 - } 213 - </style>
-122
packages/internal/components/embeds/starterpack-embed.svelte
··· 1 - <script lang="ts"> 2 - import type { AppBskyGraphDefs, AppBskyGraphStarterpack } from '@atcute/client/lexicons'; 3 - 4 - import { getStarterpackImgUrl, getStarterpackUrl } from '../../utils/bsky-url'; 5 - import { parseAtUri } from '../../utils/syntax/at-url'; 6 - 7 - interface Props { 8 - embed: AppBskyGraphDefs.StarterPackViewBasic; 9 - large?: boolean; 10 - } 11 - 12 - const { embed: pack, large = false }: Props = $props(); 13 - 14 - const record = pack.record as AppBskyGraphStarterpack.Record; 15 - 16 - const creator = pack.creator; 17 - const creatorDid = creator.did; 18 - 19 - const rkey = parseAtUri(pack.uri).rkey; 20 - const packUrl = getStarterpackUrl(creatorDid, rkey); 21 - </script> 22 - 23 - <a target="_blank" href={packUrl} class="starterpack-embed"> 24 - {#if large} 25 - {@const imageUrl = getStarterpackImgUrl(creatorDid, rkey)} 26 - 27 - <img loading="lazy" src={imageUrl} alt="" class="banner" /> 28 - {/if} 29 - 30 - <div class="meta"> 31 - <div class="main"> 32 - <svg fill="none" viewBox="0 0 24 24" class="avatar"> 33 - <defs> 34 - <linearGradient id="a" x1="0" x2="100%" y1="0" y2="0" gradientTransform="rotate(45)"> 35 - <stop offset="0" stop-color="#0A7AFF" /> 36 - <stop offset="1" stop-color="#59B9FF" /> 37 - </linearGradient> 38 - </defs> 39 - <path 40 - fill="url(#a)" 41 - fill-rule="evenodd" 42 - d="M11.26 5.227 5.02 6.899c-.734.197-1.17.95-.973 1.685l1.672 6.24c.197.734.951 1.17 1.685.973l6.24-1.672a1.376 1.376 0 0 0 .973-1.685L12.945 6.2a1.375 1.375 0 0 0-1.685-.973Zm-6.566.459a2.632 2.632 0 0 0-1.86 3.223l1.672 6.24a2.632 2.632 0 0 0 3.223 1.861l6.24-1.672a2.631 2.631 0 0 0 1.861-3.223l-1.672-6.24a2.632 2.632 0 0 0-3.223-1.861l-6.24 1.672Z" 43 - clip-rule="evenodd" 44 - /> 45 - <path 46 - fill="url(#a)" 47 - fill-rule="evenodd" 48 - d="M15.138 18.411a4.606 4.606 0 1 0 0-9.211 4.606 4.606 0 0 0 0 9.211Zm0 1.257a5.862 5.862 0 1 0 0-11.724 5.862 5.862 0 0 0 0 11.724Z" 49 - clip-rule="evenodd" 50 - /> 51 - </svg> 52 - 53 - <div class="info"> 54 - <p class="name">{record.name}</p> 55 - <p class="creator">Starter pack by @{creator.handle}</p> 56 - </div> 57 - </div> 58 - 59 - <p class="description">{record.description}</p> 60 - </div> 61 - </a> 62 - 63 - <style> 64 - .starterpack-embed { 65 - display: block; 66 - border: 1px solid var(--divider); 67 - border-radius: 6px; 68 - overflow: hidden; 69 - 70 - &:hover { 71 - border-color: var(--divider-hover); 72 - } 73 - } 74 - 75 - .banner { 76 - display: block; 77 - aspect-ratio: 1.91; 78 - width: 100%; 79 - } 80 - 81 - .meta { 82 - display: flex; 83 - flex-direction: column; 84 - gap: 12px; 85 - padding: 12px; 86 - } 87 - 88 - .main { 89 - display: flex; 90 - gap: 12px; 91 - } 92 - 93 - .avatar { 94 - margin: 2px; 95 - width: 36px; 96 - height: 36px; 97 - } 98 - 99 - .name { 100 - font-weight: 700; 101 - } 102 - 103 - .creator { 104 - color: var(--text-secondary); 105 - font-size: calc(var(--font-size) * 0.8125); 106 - } 107 - 108 - .description { 109 - display: -webkit-box; 110 - overflow: hidden; 111 - font-size: calc(var(--font-size) * 0.8125); 112 - white-space: pre-wrap; 113 - -webkit-box-orient: vertical; 114 - -webkit-line-clamp: 2; 115 - line-clamp: 2; 116 - overflow-wrap: break-word; 117 - 118 - &:empty { 119 - display: none; 120 - } 121 - } 122 - </style>
-120
packages/internal/components/embeds/video-embed.svelte
··· 1 - <script lang="ts"> 2 - import type { AppBskyEmbedVideo, AppBskyFeedDefs } from '@atcute/client/lexicons'; 3 - 4 - import { getPostUrl } from '../../utils/bsky-url'; 5 - import { parseAtUri } from '../../utils/syntax/at-url'; 6 - 7 - interface Props { 8 - post?: AppBskyFeedDefs.PostView; 9 - embed: AppBskyEmbedVideo.View; 10 - borderless?: boolean; 11 - standalone?: boolean; 12 - blur?: boolean; 13 - } 14 - 15 - const { post, embed: video, borderless, standalone, blur }: Props = $props(); 16 - 17 - const ratio = standalone && video.aspectRatio; 18 - 19 - const postUrl = post && getPostUrl(post.author.did, parseAtUri(post.uri).rkey); 20 - </script> 21 - 22 - {#if standalone} 23 - <a 24 - target="_blank" 25 - href={postUrl} 26 - class={`video-embed` + (!borderless ? ` is-bordered` : ``) + (standalone ? ` is-standalone` : ``)} 27 - > 28 - <div class="constrainer" style={ratio ? `aspect-ratio: ${ratio.width}/${ratio.height}` : ``}> 29 - {@render Content()} 30 - </div> 31 - </a> 32 - {:else} 33 - <div 34 - class={`video-embed` + (!borderless ? ` is-bordered` : ``)} 35 - style={ratio ? `aspect-ratio: ${ratio.width}/${ratio.height}` : ``} 36 - > 37 - {@render Content()} 38 - </div> 39 - {/if} 40 - 41 - {#snippet Content()} 42 - <img loading="lazy" src={video.thumbnail} alt="" class={`thumbnail` + (blur ? ` is-blurred` : ``)} /> 43 - 44 - {#if ratio} 45 - <div class="placeholder"></div> 46 - {/if} 47 - 48 - <div class="play"> 49 - <!-- play --> 50 - <svg class="icon" fill="none" viewBox="0 0 24 24"> 51 - <path fill="currentColor" d="M22 12 5 2v20l17-10Z" /> 52 - </svg> 53 - </div> 54 - {/snippet} 55 - 56 - <style> 57 - .video-embed { 58 - display: block; 59 - position: relative; 60 - background: #000000; 61 - aspect-ratio: 16 / 9; 62 - overflow: hidden; 63 - } 64 - .is-bordered { 65 - border: 1px solid var(--divider); 66 - border-radius: 6px; 67 - } 68 - .is-standalone { 69 - align-self: baseline; 70 - aspect-ratio: auto; 71 - max-width: 100%; 72 - } 73 - 74 - .constrainer { 75 - min-width: 64px; 76 - max-width: 100%; 77 - min-height: 64px; 78 - max-height: 320px; 79 - } 80 - 81 - .thumbnail { 82 - width: 100%; 83 - height: 100%; 84 - object-fit: contain; 85 - } 86 - .is-blurred { 87 - scale: 125%; 88 - filter: blur(24px); 89 - } 90 - 91 - .placeholder { 92 - width: 100vw; 93 - height: 100vh; 94 - } 95 - 96 - .play { 97 - display: grid; 98 - position: absolute; 99 - top: 50%; 100 - left: 50%; 101 - place-items: center; 102 - translate: -50% -50%; 103 - border-radius: 50%; 104 - background: rgba(64, 64, 64, 0.6); 105 - aspect-ratio: 1 / 1; 106 - height: 40%; 107 - max-height: 48px; 108 - color: #ffffff; 109 - font-size: 20px; 110 - 111 - .icon { 112 - width: 40%; 113 - height: 40%; 114 - } 115 - 116 - .is-standalone &:hover { 117 - background: rgba(64, 64, 64, 0.8); 118 - } 119 - } 120 - </style>
-400
packages/internal/components/feed-post.svelte
··· 1 - <script lang="ts"> 2 - import type { AppBskyFeedDefs, AppBskyFeedPost } from '@atcute/client/lexicons'; 3 - 4 - import { getPostUrl, getProfileUrl } from '../utils/bsky-url'; 5 - import { formatLongDate, formatShortDate } from '../utils/date'; 6 - import { parseAtUri } from '../utils/syntax/at-url'; 7 - 8 - import { formatCompactNumber, formatLongNumber } from '../utils/number'; 9 - import Embeds from './embeds/embeds.svelte'; 10 - import RichtextRenderer from './richtext-renderer.svelte'; 11 - 12 - interface Props { 13 - item: AppBskyFeedDefs.FeedViewPost; 14 - prev?: boolean; 15 - next?: boolean; 16 - } 17 - 18 - const { item, prev = false, next = false }: Props = $props(); 19 - 20 - const reason = item.reason; 21 - const post = item.post; 22 - const parent = item.reply?.parent; 23 - 24 - const author = post.author; 25 - const authorUrl = getProfileUrl(author.did); 26 - const authorName = author.displayName?.trim(); 27 - 28 - const record = post.record as AppBskyFeedPost.Record; 29 - const postUrl = getPostUrl(author.did, parseAtUri(post.uri).rkey); 30 - 31 - const replyCount = post.replyCount || 0; 32 - const likeCount = post.likeCount || 0; 33 - const repostCount = (post.repostCount || 0) + (post.quoteCount || 0); 34 - </script> 35 - 36 - <div class={`feed-post` + (!next ? ` is-leaf` : ``)}> 37 - <div class="contexts"> 38 - {#if prev} 39 - <div class="ascendant-line-wrapper"> 40 - <div class="line"></div> 41 - </div> 42 - {/if} 43 - 44 - {#if reason} 45 - {#if reason.$type === 'app.bsky.feed.defs#reasonRepost'} 46 - {@const by = reason.by} 47 - 48 - <div class="context"> 49 - <div class="aside"> 50 - <svg class="icon" viewBox="0 0 24 24" fill="none"> 51 - <path 52 - d="M17 3L20 6L17 9M7 21L4 18L7 15M5 18H20V13M4 11V6H19" 53 - stroke="currentColor" 54 - stroke-width="2" 55 - stroke-linecap="square" 56 - /> 57 - </svg> 58 - </div> 59 - <a href={getProfileUrl(by.did)} class="main"> 60 - <span dir="auto" class="name">{by.displayName}</span> 61 - <span class="affix">{' '}reposted</span> 62 - </a> 63 - </div> 64 - {:else if reason.$type === 'app.bsky.feed.defs#reasonPin'} 65 - <div class="context"> 66 - <div class="aside"> 67 - <svg class="icon" fill="none" viewBox="0 0 24 24"> 68 - <path 69 - stroke="currentColor" 70 - stroke-linecap="square" 71 - stroke-width="2" 72 - d="M12 15H5v-2.5l.377-.377A7.25 7.25 0 0 0 7.5 6.997V3h9v3.997a7.25 7.25 0 0 0 2.123 5.127L19 12.5V15h-7Zm0 0v6" 73 - /> 74 - </svg> 75 - </div> 76 - <span class="main">Pinned</span> 77 - </div> 78 - {/if} 79 - {/if} 80 - </div> 81 - 82 - <div class="content"> 83 - <div class="aside"> 84 - <a target="_blank" href={authorUrl} class="avatar-wrapper"> 85 - {#if author.avatar} 86 - <img loading="lazy" src={author.avatar} alt="" class="avatar" /> 87 - {/if} 88 - </a> 89 - 90 - {#if next} 91 - <div class="descendant-line"></div> 92 - {/if} 93 - </div> 94 - 95 - <div class="main"> 96 - <div class="meta"> 97 - <a href={authorUrl} target="_blank" class="name-wrapper"> 98 - {#if authorName} 99 - <bdi class="display-name-wrapper"> 100 - <span class="display-name">{authorName}</span> 101 - </bdi> 102 - {/if} 103 - 104 - <span class="handle">@{author.handle}</span> 105 - </a> 106 - 107 - <span aria-hidden="true" class="dot"> ยท </span> 108 - 109 - <a target="_blank" href={postUrl} title={formatLongDate(record.createdAt)} class="date"> 110 - <time datetime={record.createdAt}>{formatShortDate(record.createdAt)}</time> 111 - </a> 112 - </div> 113 - 114 - {#if !prev && record.reply} 115 - <p class="reply-context"> 116 - {#if parent && parent.$type === 'app.bsky.feed.defs#postView'} 117 - {@const author = parent.author} 118 - 119 - Replying to 120 - <a target="_blank" href={getProfileUrl(author.did)} dir="auto"> 121 - {author.displayName?.trim() || `@${author.handle}`} 122 - </a> 123 - {:else} 124 - Replying to an unknown post 125 - {/if} 126 - </p> 127 - {/if} 128 - 129 - <RichtextRenderer text={record.text} facets={record.facets} /> 130 - 131 - {#if post.embed} 132 - <Embeds {post} embed={post.embed} /> 133 - {/if} 134 - 135 - <div class="metrics"> 136 - <div 137 - title={replyCount === 1 138 - ? `${formatLongNumber(replyCount)} reply` 139 - : `${formatLongNumber(replyCount)} replies`} 140 - class="stat" 141 - > 142 - <svg class="icon" fill="none" viewBox="0 0 24 24"> 143 - <path 144 - stroke="currentColor" 145 - stroke-linecap="square" 146 - stroke-width="2" 147 - d="M3.002 4h18v14h-9l-5 3v-3h-4V4Z" 148 - /> 149 - </svg> 150 - 151 - <span class="count"> 152 - {formatCompactNumber(replyCount)} 153 - </span> 154 - </div> 155 - 156 - <div 157 - title={repostCount === 1 158 - ? `${formatLongNumber(repostCount)} repost` 159 - : `${formatLongNumber(repostCount)} reposts`} 160 - class="stat" 161 - > 162 - <svg class="icon" fill="none" viewBox="0 0 24 24"> 163 - <path 164 - stroke="currentColor" 165 - stroke-linecap="square" 166 - stroke-width="2" 167 - d="m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15" 168 - /> 169 - </svg> 170 - 171 - <span class="count"> 172 - {formatCompactNumber(repostCount)} 173 - </span> 174 - </div> 175 - 176 - <div 177 - title={likeCount === 1 178 - ? `${formatLongNumber(likeCount)} like` 179 - : `${formatLongNumber(likeCount)} likes`} 180 - class="stat" 181 - > 182 - <svg class="icon" fill="none" viewBox="0 0 24 24"> 183 - <path 184 - stroke="currentColor" 185 - stroke-width="2" 186 - d="M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z" 187 - /> 188 - </svg> 189 - 190 - <span class="count"> 191 - {formatCompactNumber(likeCount)} 192 - </span> 193 - </div> 194 - </div> 195 - </div> 196 - </div> 197 - </div> 198 - 199 - <style> 200 - .feed-post { 201 - padding: 0 16px; 202 - } 203 - .is-leaf { 204 - border-bottom: 1px solid var(--divider); 205 - } 206 - 207 - .ascendant-line-wrapper { 208 - display: flex; 209 - flex-direction: column; 210 - align-items: center; 211 - width: 36px; 212 - 213 - .line { 214 - position: absolute; 215 - top: 0; 216 - bottom: 4px; 217 - flex-grow: 1; 218 - border-left: 2px solid var(--divider); 219 - } 220 - } 221 - .descendant-line { 222 - flex-grow: 1; 223 - margin-top: 4px; 224 - border-left: 2px solid var(--divider); 225 - } 226 - 227 - .contexts { 228 - display: flex; 229 - position: relative; 230 - flex-direction: column; 231 - padding: 8px 0 4px 0; 232 - } 233 - .context { 234 - display: flex; 235 - align-items: center; 236 - gap: 12px; 237 - color: var(--text-secondary); 238 - font-size: 0.8125rem; 239 - line-height: 1.25rem; 240 - 241 - .aside { 242 - display: flex; 243 - flex-shrink: 0; 244 - justify-content: flex-end; 245 - width: 36px; 246 - } 247 - 248 - .main { 249 - display: flex; 250 - min-width: 0px; 251 - 252 - &:hover { 253 - text-decoration-line: underline; 254 - } 255 - } 256 - 257 - .name { 258 - overflow: hidden; 259 - font-weight: 500; 260 - text-overflow: ellipsis; 261 - white-space: nowrap; 262 - } 263 - 264 - .affix { 265 - flex-shrink: 0; 266 - white-space: pre; 267 - } 268 - } 269 - 270 - .content { 271 - display: flex; 272 - gap: 12px; 273 - 274 - .aside { 275 - display: flex; 276 - flex-shrink: 0; 277 - flex-direction: column; 278 - align-items: center; 279 - } 280 - 281 - .main { 282 - flex-grow: 1; 283 - padding-bottom: 12px; 284 - min-width: 0; 285 - } 286 - } 287 - 288 - .avatar-wrapper { 289 - display: block; 290 - border-radius: 9999px; 291 - background: var(--background-secondary); 292 - width: 36px; 293 - height: 36px; 294 - overflow: hidden; 295 - 296 - &:hover { 297 - filter: brightness(0.85); 298 - } 299 - } 300 - .avatar { 301 - width: 100%; 302 - height: 100%; 303 - object-fit: cover; 304 - } 305 - 306 - .meta { 307 - display: flex; 308 - align-items: center; 309 - margin: 0 0 2px 0; 310 - color: var(--text-secondary); 311 - 312 - .name-wrapper { 313 - display: flex; 314 - gap: 4px; 315 - max-width: 100%; 316 - overflow: hidden; 317 - color: inherit; 318 - text-decoration: none; 319 - text-overflow: ellipsis; 320 - white-space: nowrap; 321 - } 322 - 323 - .display-name-wrapper { 324 - overflow: hidden; 325 - text-overflow: ellipsis; 326 - 327 - .name-wrapper:hover & { 328 - text-decoration: underline; 329 - } 330 - } 331 - 332 - .display-name { 333 - color: var(--text-primary); 334 - font-weight: 700; 335 - } 336 - 337 - .handle { 338 - display: block; 339 - overflow: hidden; 340 - text-overflow: ellipsis; 341 - white-space: nowrap; 342 - } 343 - 344 - .dot { 345 - flex-shrink: 0; 346 - margin: 0 6px; 347 - } 348 - 349 - .date { 350 - color: inherit; 351 - text-decoration: none; 352 - white-space: nowrap; 353 - 354 - &:hover { 355 - text-decoration: underline; 356 - } 357 - } 358 - } 359 - 360 - .reply-context { 361 - overflow: hidden; 362 - color: var(--text-secondary); 363 - font-size: calc(var(--font-size) * 0.8125); 364 - text-overflow: ellipsis; 365 - white-space: nowrap; 366 - 367 - a { 368 - color: inherit; 369 - font-weight: 500; 370 - 371 - &:hover { 372 - text-decoration: underline; 373 - } 374 - } 375 - } 376 - 377 - .metrics { 378 - display: flex; 379 - align-items: center; 380 - gap: 16px; 381 - margin-top: 12px; 382 - color: var(--text-secondary); 383 - } 384 - .stat { 385 - display: flex; 386 - align-items: center; 387 - gap: 8px; 388 - min-width: 0px; 389 - max-width: 100%; 390 - 391 - .count { 392 - padding-right: 8px; 393 - overflow: hidden; 394 - font-size: calc(var(--font-size) * 0.8125); 395 - line-height: calc(var(--font-size) * 1.25); 396 - text-overflow: ellipsis; 397 - white-space: nowrap; 398 - } 399 - } 400 - </style>
-271
packages/internal/components/highlighted-post.svelte
··· 1 - <script lang="ts"> 2 - import type { AppBskyFeedDefs, AppBskyFeedPost } from '@atcute/client/lexicons'; 3 - 4 - import { getPostUrl, getProfileUrl } from '../utils/bsky-url'; 5 - import { formatLongDate } from '../utils/date'; 6 - import { findLabel } from '../utils/labels'; 7 - import { formatCompactNumber, formatLongNumber } from '../utils/number'; 8 - import { parseAtUri } from '../utils/syntax/at-url'; 9 - 10 - import Embeds from './embeds/embeds.svelte'; 11 - import RichTextRenderer from './richtext-renderer.svelte'; 12 - 13 - interface Props { 14 - post: AppBskyFeedDefs.PostView; 15 - parent: AppBskyFeedDefs.PostView | null; 16 - prev?: boolean; 17 - } 18 - 19 - const { post, parent, prev = false }: Props = $props(); 20 - 21 - const author = post.author; 22 - const authorUrl = getProfileUrl(author.did); 23 - const authorName = author.displayName?.trim(); 24 - 25 - const record = post.record as AppBskyFeedPost.Record; 26 - const postUrl = getPostUrl(author.did, parseAtUri(post.uri).rkey); 27 - 28 - const replyCount = post.replyCount || 0; 29 - const likeCount = post.likeCount || 0; 30 - const repostCount = (post.repostCount || 0) + (post.quoteCount || 0); 31 - 32 - const isAuthorBlurred = !!findLabel(author.labels, author.did); 33 - </script> 34 - 35 - <div class="highlighted-post"> 36 - <div class="meta"> 37 - <a href={authorUrl} target="_blank" class="avatar-wrapper"> 38 - {#if author.avatar} 39 - <img 40 - loading="lazy" 41 - src={author.avatar} 42 - alt="" 43 - class={`avatar` + (isAuthorBlurred ? ` is-blurred` : ``)} 44 - /> 45 - {/if} 46 - </a> 47 - 48 - <a href={authorUrl} target="_blank" class="name-wrapper"> 49 - {#if authorName} 50 - <bdi class="display-name-wrapper"> 51 - <span class="display-name">{authorName}</span> 52 - </bdi> 53 - {/if} 54 - <span class="handle">@{author.handle}</span> 55 - </a> 56 - 57 - {#if !prev} 58 - <svg class="logo" fill="none" viewBox="0 0 320 286"> 59 - <path 60 - fill="#0A7AFF" 61 - d="M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z" 62 - /> 63 - </svg> 64 - {/if} 65 - </div> 66 - 67 - {#if !prev && record.reply} 68 - <p class="context"> 69 - {#if parent} 70 - {@const author = parent.author} 71 - 72 - Replying to 73 - <a target="_blank" href={getProfileUrl(author.did)} dir="auto"> 74 - {author.displayName?.trim() || `@${author.handle}`} 75 - </a> 76 - {:else} 77 - Replying to an unknown post 78 - {/if} 79 - </p> 80 - {/if} 81 - 82 - <RichTextRenderer text={record.text} facets={record.facets} large /> 83 - 84 - {#if post.embed} 85 - <Embeds {post} embed={post.embed} large /> 86 - {/if} 87 - 88 - <time datetime={record.createdAt} class="date"> 89 - {formatLongDate(record.createdAt)} 90 - </time> 91 - 92 - <div class="stats"> 93 - <span 94 - class="stat" 95 - title={likeCount === 1 ? `${formatLongNumber(likeCount)} like` : `${formatLongNumber(likeCount)} likes`} 96 - > 97 - <!-- heart-2 --> 98 - <svg class="icon" fill="none" viewBox="0 0 24 24"> 99 - <path 100 - stroke="currentColor" 101 - stroke-width="2" 102 - d="M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z" 103 - /> 104 - </svg> 105 - 106 - <span>{formatCompactNumber(likeCount)}</span> 107 - </span> 108 - 109 - <span 110 - class="stat" 111 - title={repostCount === 1 112 - ? `${formatLongNumber(repostCount)} repost` 113 - : `${formatLongNumber(repostCount)} reposts`} 114 - > 115 - <!-- arrows-repeat-right-left --> 116 - <svg class="icon" fill="none" viewBox="0 0 24 24"> 117 - <path 118 - stroke="currentColor" 119 - stroke-linecap="square" 120 - stroke-width="2" 121 - d="m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15" 122 - /> 123 - </svg> 124 - 125 - <span>{formatCompactNumber(repostCount)}</span> 126 - </span> 127 - 128 - <div class="gap"></div> 129 - 130 - <a href={postUrl} target="_blank" class="permalink"> 131 - <span> 132 - {!replyCount 133 - ? `View on Bluesky` 134 - : replyCount === 1 135 - ? `Read ${formatCompactNumber(replyCount)} reply on Bluesky` 136 - : `Read ${formatCompactNumber(replyCount)} replies on Bluesky`} 137 - </span> 138 - </a> 139 - </div> 140 - </div> 141 - 142 - <style> 143 - .highlighted-post { 144 - padding: 16px; 145 - } 146 - 147 - .meta { 148 - display: flex; 149 - align-items: center; 150 - gap: 12px; 151 - margin: 0 0 12px 0; 152 - color: var(--text-secondary); 153 - } 154 - 155 - .avatar-wrapper { 156 - display: block; 157 - flex-shrink: 0; 158 - border-radius: 9999px; 159 - background: var(--background-secondary); 160 - width: 40px; 161 - height: 40px; 162 - overflow: hidden; 163 - 164 - &:hover { 165 - filter: brightness(0.85); 166 - } 167 - } 168 - 169 - .avatar { 170 - width: 100%; 171 - height: 100%; 172 - object-fit: cover; 173 - } 174 - .is-blurred { 175 - scale: 125%; 176 - filter: blur(4px); 177 - } 178 - 179 - .name-wrapper { 180 - display: block; 181 - flex-grow: 1; 182 - max-width: 100%; 183 - overflow: hidden; 184 - color: inherit; 185 - text-overflow: ellipsis; 186 - white-space: nowrap; 187 - } 188 - .display-name-wrapper { 189 - overflow: hidden; 190 - text-overflow: ellipsis; 191 - 192 - .name-wrapper:hover & { 193 - text-decoration: underline; 194 - } 195 - } 196 - .display-name { 197 - color: var(--text-primary); 198 - font-weight: 700; 199 - } 200 - .handle { 201 - display: block; 202 - overflow: hidden; 203 - text-overflow: ellipsis; 204 - white-space: nowrap; 205 - } 206 - 207 - .logo { 208 - width: 32px; 209 - height: 32px; 210 - } 211 - 212 - .context { 213 - overflow: hidden; 214 - color: var(--text-secondary); 215 - font-size: calc(var(--font-size) * 0.8125); 216 - text-overflow: ellipsis; 217 - white-space: nowrap; 218 - 219 - a { 220 - color: inherit; 221 - font-weight: 500; 222 - 223 - &:hover { 224 - text-decoration: underline; 225 - } 226 - } 227 - } 228 - 229 - .date { 230 - display: flex; 231 - flex-wrap: wrap; 232 - align-items: center; 233 - gap: 8px; 234 - margin: 12px 0 0; 235 - border-bottom: 1px solid var(--divider); 236 - padding: 0 0 12px 0; 237 - color: var(--text-secondary); 238 - } 239 - 240 - .stats { 241 - display: flex; 242 - flex-wrap: wrap; 243 - align-items: center; 244 - gap: 8px 16px; 245 - margin: 0 0 -16px 0; 246 - padding: 12px 0; 247 - color: var(--text-secondary); 248 - 249 - .gap { 250 - flex: 1 1 auto; 251 - } 252 - 253 - .permalink { 254 - display: flex; 255 - align-items: center; 256 - gap: 4px; 257 - color: var(--text-link); 258 - font-weight: 700; 259 - 260 - &:hover { 261 - text-decoration: underline; 262 - } 263 - } 264 - } 265 - .stat { 266 - display: flex; 267 - align-items: center; 268 - gap: 8px; 269 - font-weight: 500; 270 - } 271 - </style>
-226
packages/internal/components/post.svelte
··· 1 - <script lang="ts"> 2 - import type { AppBskyFeedDefs, AppBskyFeedPost } from '@atcute/client/lexicons'; 3 - 4 - import { getPostUrl, getProfileUrl } from '../utils/bsky-url'; 5 - import { formatLongDate, formatShortDate } from '../utils/date'; 6 - import { findLabel } from '../utils/labels'; 7 - import { parseAtUri } from '../utils/syntax/at-url'; 8 - 9 - import Embeds from './embeds/embeds.svelte'; 10 - import RichtextRenderer from './richtext-renderer.svelte'; 11 - 12 - interface Props { 13 - post: AppBskyFeedDefs.PostView; 14 - parent?: AppBskyFeedDefs.PostView | null; 15 - prev?: boolean; 16 - } 17 - 18 - const { post, parent, prev }: Props = $props(); 19 - 20 - const author = post.author; 21 - const authorUrl = getProfileUrl(author.did); 22 - const authorName = author.displayName?.trim(); 23 - 24 - const record = post.record as AppBskyFeedPost.Record; 25 - const postUrl = getPostUrl(author.did, parseAtUri(post.uri).rkey); 26 - 27 - const isAuthorBlurred = !!findLabel(author.labels, author.did); 28 - </script> 29 - 30 - <div class="post"> 31 - {#if !prev} 32 - <svg class="logo" fill="none" viewBox="0 0 320 286"> 33 - <path 34 - fill="#0A7AFF" 35 - d="M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z" 36 - /> 37 - </svg> 38 - {/if} 39 - 40 - <div class="aside"> 41 - <a target="_blank" href={authorUrl} class="avatar-wrapper"> 42 - {#if author.avatar} 43 - <img 44 - loading="lazy" 45 - src={author.avatar} 46 - alt="" 47 - class={`avatar` + (isAuthorBlurred ? ` is-blurred` : ``)} 48 - /> 49 - {/if} 50 - </a> 51 - 52 - <div class="line"></div> 53 - </div> 54 - 55 - <div class="main"> 56 - <div class="meta"> 57 - <a href={authorUrl} target="_blank" class="name-wrapper"> 58 - {#if authorName} 59 - <bdi class="display-name-wrapper"> 60 - <span class="display-name">{authorName}</span> 61 - </bdi> 62 - {/if} 63 - 64 - <span class="handle">@{author.handle}</span> 65 - </a> 66 - 67 - <span aria-hidden="true" class="dot"> ยท </span> 68 - 69 - <a target="_blank" href={postUrl} title={formatLongDate(record.createdAt)} class="date"> 70 - <time datetime={record.createdAt}>{formatShortDate(record.createdAt)}</time> 71 - </a> 72 - </div> 73 - 74 - {#if !prev && record.reply} 75 - <p class="context"> 76 - {#if parent} 77 - {@const author = parent.author} 78 - 79 - Replying to 80 - <a target="_blank" href={getProfileUrl(author.did)} dir="auto"> 81 - {author.displayName?.trim() || `@${author.handle}`} 82 - </a> 83 - {:else} 84 - Replying to an unknown post 85 - {/if} 86 - </p> 87 - {/if} 88 - 89 - <RichtextRenderer text={record.text} facets={record.facets} /> 90 - 91 - {#if post.embed} 92 - <Embeds {post} embed={post.embed} /> 93 - {/if} 94 - </div> 95 - </div> 96 - 97 - <style> 98 - .post { 99 - display: flex; 100 - position: relative; 101 - gap: 12px; 102 - padding: 12px 16px 0 16px; 103 - } 104 - 105 - .logo { 106 - position: absolute; 107 - top: 12px; 108 - right: 12px; 109 - width: 24px; 110 - height: 24px; 111 - } 112 - 113 - .aside { 114 - flex-shrink: 0; 115 - } 116 - 117 - .avatar-wrapper { 118 - display: block; 119 - border-radius: 9999px; 120 - background: var(--background-secondary); 121 - width: 40px; 122 - height: 40px; 123 - overflow: hidden; 124 - 125 - &:hover { 126 - filter: brightness(0.85); 127 - } 128 - } 129 - 130 - .avatar { 131 - width: 100%; 132 - height: 100%; 133 - object-fit: cover; 134 - } 135 - .is-blurred { 136 - scale: 125%; 137 - filter: blur(4px); 138 - } 139 - 140 - .line { 141 - position: absolute; 142 - top: 56px; 143 - bottom: -12px; 144 - left: 35px; 145 - border-left: 2px solid var(--divider); 146 - } 147 - 148 - .main { 149 - display: flex; 150 - flex-grow: 1; 151 - flex-direction: column; 152 - min-width: 0px; 153 - } 154 - 155 - .meta { 156 - display: flex; 157 - align-items: center; 158 - margin: 0 0 2px 0; 159 - padding: 0 calc(24px + 8px) 0 0; 160 - color: var(--text-secondary); 161 - 162 - .name-wrapper { 163 - display: flex; 164 - gap: 4px; 165 - max-width: 100%; 166 - overflow: hidden; 167 - color: inherit; 168 - text-decoration: none; 169 - text-overflow: ellipsis; 170 - white-space: nowrap; 171 - } 172 - 173 - .display-name-wrapper { 174 - overflow: hidden; 175 - text-overflow: ellipsis; 176 - 177 - .name-wrapper:hover & { 178 - text-decoration: underline; 179 - } 180 - } 181 - 182 - .display-name { 183 - color: var(--text-primary); 184 - font-weight: 700; 185 - } 186 - 187 - .handle { 188 - display: block; 189 - overflow: hidden; 190 - text-overflow: ellipsis; 191 - white-space: nowrap; 192 - } 193 - 194 - .dot { 195 - flex-shrink: 0; 196 - margin: 0 6px; 197 - } 198 - 199 - .date { 200 - color: inherit; 201 - text-decoration: none; 202 - white-space: nowrap; 203 - 204 - &:hover { 205 - text-decoration: underline; 206 - } 207 - } 208 - } 209 - 210 - .context { 211 - overflow: hidden; 212 - color: var(--text-secondary); 213 - font-size: calc(var(--font-size) * 0.8125); 214 - text-overflow: ellipsis; 215 - white-space: nowrap; 216 - 217 - a { 218 - color: inherit; 219 - font-weight: 500; 220 - 221 - &:hover { 222 - text-decoration: underline; 223 - } 224 - } 225 - } 226 - </style>
-204
packages/internal/components/profile-card.svelte
··· 1 - <script lang="ts"> 2 - import type { AppBskyActorDefs } from '@atcute/client/lexicons'; 3 - 4 - import { getProfileUrl } from '../utils/bsky-url'; 5 - import { findLabel } from '../utils/labels'; 6 - import { formatCompactNumber } from '../utils/number'; 7 - import RichtextRawRenderer from './richtext-raw-renderer.svelte'; 8 - 9 - interface Props { 10 - profile: AppBskyActorDefs.ProfileViewDetailed; 11 - } 12 - 13 - const { profile }: Props = $props(); 14 - 15 - const url = getProfileUrl(profile.did); 16 - const isBlurred = findLabel(profile.labels, profile.did); 17 - </script> 18 - 19 - <div class="profile-card has-banner"> 20 - <div class="banner-wrapper"> 21 - {#if profile.banner} 22 - <img loading="lazy" src={profile.banner} alt="" class={`banner` + (isBlurred ? ` is-blurred` : ``)} /> 23 - {/if} 24 - </div> 25 - 26 - <div class="contents"> 27 - <div class="header"> 28 - <a href={url} target="_blank" class="avatar-wrapper"> 29 - {#if profile.avatar} 30 - <img 31 - loading="lazy" 32 - src={profile.avatar} 33 - alt="" 34 - class={`avatar` + (isBlurred ? ` is-blurred` : ``)} 35 - /> 36 - {/if} 37 - </a> 38 - 39 - <div class="actions"> 40 - <a href={url} target="_blank" class="follow-button"> 41 - <svg class="icon" fill="none" viewBox="0 0 24 24"> 42 - <path 43 - stroke="currentColor" 44 - stroke-linecap="square" 45 - stroke-width="2" 46 - d="M12 4v8m0 0v8m0-8H4m8 0h8" 47 - /> 48 - </svg> 49 - <span>Follow</span> 50 - </a> 51 - 52 - <svg class="logo" fill="none" viewBox="0 0 320 286"> 53 - <path 54 - fill="#0A7AFF" 55 - d="M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z" 56 - /> 57 - </svg> 58 - </div> 59 - </div> 60 - 61 - <div class="name-wrapper"> 62 - <p dir="auto" class="display-name">{profile.displayName?.trim() || profile.handle.slice(0, 64)}</p> 63 - <p class="handle">@{profile.handle}</p> 64 - </div> 65 - 66 - <div class="stats"> 67 - <span class="stat-entry"> 68 - <span class="stat-count">{formatCompactNumber(profile.followersCount || 0)}</span> 69 - <span> {profile.followersCount === 1 ? `Follower` : `Followers`}</span> 70 - </span> 71 - 72 - <span class="stat-entry"> 73 - <span class="stat-count">{formatCompactNumber(profile.followsCount || 0)}</span> 74 - <span> Following</span> 75 - </span> 76 - </div> 77 - 78 - {#if profile.description?.trim()} 79 - <RichtextRawRenderer text={profile.description} /> 80 - {/if} 81 - </div> 82 - </div> 83 - 84 - <style> 85 - .profile-card { 86 - display: flex; 87 - flex-direction: column; 88 - } 89 - 90 - .is-blurred { 91 - scale: 125%; 92 - filter: blur(4px); 93 - } 94 - 95 - .banner-wrapper { 96 - background: var(--background-secondary); 97 - aspect-ratio: 3 / 1; 98 - overflow: hidden; 99 - } 100 - .banner { 101 - width: 100%; 102 - height: 100%; 103 - object-fit: cover; 104 - } 105 - 106 - .contents { 107 - display: flex; 108 - position: relative; 109 - flex-direction: column; 110 - gap: 8px; 111 - padding: 12px 16px 16px; 112 - } 113 - .logo { 114 - width: 24px; 115 - height: 24px; 116 - } 117 - 118 - .header { 119 - display: flex; 120 - justify-content: space-between; 121 - align-items: end; 122 - } 123 - .actions { 124 - display: flex; 125 - align-items: center; 126 - gap: 16px; 127 - } 128 - 129 - .avatar-wrapper { 130 - display: block; 131 - flex-shrink: 0; 132 - outline: 2px solid var(--background-primary); 133 - border-radius: 9999px; 134 - background: var(--background-secondary); 135 - width: 90px; 136 - height: 90px; 137 - overflow: hidden; 138 - 139 - .has-banner & { 140 - margin-top: calc(-90px + 34px); 141 - } 142 - } 143 - .avatar { 144 - width: 100%; 145 - height: 100%; 146 - object-fit: cover; 147 - 148 - .avatar-wrapper:hover & { 149 - filter: brightness(0.85); 150 - 151 - &.is-blurred { 152 - filter: brightness(0.85) blur(4px); 153 - } 154 - } 155 - } 156 - 157 - .follow-button { 158 - display: flex; 159 - align-items: center; 160 - gap: 6px; 161 - border-radius: 9999px; 162 - background: var(--button); 163 - padding: 9px 12px; 164 - color: var(--button-text); 165 - font-weight: 600; 166 - font-size: calc(var(--font-size) * 0.8125); 167 - line-height: calc(var(--font-size) * 1); 168 - user-select: none; 169 - 170 - .icon { 171 - font-size: 16px; 172 - } 173 - 174 - &:hover { 175 - background: var(--button-hover); 176 - } 177 - } 178 - 179 - .display-name { 180 - font-weight: 700; 181 - font-size: calc(var(--font-size) * 1.25); 182 - line-height: calc(var(--font-size) * 1.75); 183 - overflow-wrap: break-word; 184 - } 185 - .handle { 186 - color: var(--text-secondary); 187 - overflow-wrap: break-word; 188 - } 189 - 190 - .stats { 191 - display: flex; 192 - flex-wrap: wrap; 193 - gap: 20px; 194 - 195 - min-width: 0; 196 - } 197 - .stat-entry { 198 - color: var(--text-secondary); 199 - } 200 - .stat-count { 201 - color: var(--text-primary); 202 - font-weight: 700; 203 - } 204 - </style>
-54
packages/internal/components/profile-feed-header.svelte
··· 1 - <script lang="ts"> 2 - import type { AppBskyActorDefs } from '@atcute/client/lexicons'; 3 - 4 - import { getProfileUrl } from '../utils/bsky-url'; 5 - 6 - interface Props { 7 - profile: AppBskyActorDefs.ProfileViewDetailed; 8 - } 9 - 10 - const { profile }: Props = $props(); 11 - </script> 12 - 13 - <div class="profile-feed-header"> 14 - <a target="_blank" href={getProfileUrl(profile.did)} class="title">Posts from @{profile.handle}</a> 15 - 16 - <svg class="logo" fill="none" viewBox="0 0 320 286"> 17 - <path 18 - fill="#0A7AFF" 19 - d="M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z" 20 - /> 21 - </svg> 22 - </div> 23 - 24 - <style> 25 - .profile-feed-header { 26 - display: flex; 27 - justify-content: space-between; 28 - align-items: center; 29 - gap: 16px; 30 - container-type: inline-size; 31 - border-bottom: 1px solid var(--divider); 32 - padding: 12px 16px; 33 - } 34 - 35 - .title { 36 - padding: 4px 0; 37 - min-width: 0; 38 - overflow: hidden; 39 - font-weight: 600; 40 - font-size: calc(var(--font-size) * 1); 41 - line-height: calc(var(--font-size) * 1.5); 42 - text-overflow: ellipsis; 43 - white-space: nowrap; 44 - 45 - &:hover { 46 - text-decoration: underline; 47 - } 48 - } 49 - 50 - .logo { 51 - width: 24px; 52 - height: 24px; 53 - } 54 - </style>
-53
packages/internal/components/richtext-raw-renderer.svelte
··· 1 - <script lang="ts" module> 2 - const HTTP_RE = /^https?:\/\//; 3 - </script> 4 - 5 - <script lang="ts"> 6 - import { tokenize } from '@atcute/bluesky-richtext-parser'; 7 - 8 - import { getHashtagUrl, getProfileUrl } from '../utils/bsky-url'; 9 - 10 - interface Props { 11 - text: string; 12 - } 13 - 14 - const { text }: Props = $props(); 15 - </script> 16 - 17 - <p class="rich-text is-small"> 18 - {#each tokenize(text) as token} 19 - {#if token.type === 'autolink'} 20 - <a target="_blank" href={token.url} rel="noopener nofollow" class="link"> 21 - {token.raw.replace(HTTP_RE, '')} 22 - </a> 23 - {:else if token.type === 'mention'} 24 - <a target="_blank" href={getProfileUrl(token.handle)} class="mention">{token.raw}</a> 25 - {:else if token.type === 'topic'} 26 - <a target="_blank" href={getHashtagUrl(token.name)} class="hashtag">{token.raw}</a> 27 - {:else} 28 - {token.raw} 29 - {/if} 30 - {/each} 31 - </p> 32 - 33 - <style> 34 - .rich-text { 35 - overflow: hidden; 36 - white-space: pre-wrap; 37 - overflow-wrap: break-word; 38 - 39 - &:empty { 40 - display: none; 41 - } 42 - } 43 - 44 - .link, 45 - .mention, 46 - .hashtag { 47 - color: var(--text-link); 48 - 49 - &:hover { 50 - text-decoration: underline; 51 - } 52 - } 53 - </style>
-66
packages/internal/components/richtext-renderer.svelte
··· 1 - <script lang="ts" module> 2 - import { segmentize, type Facet, type FacetFeature } from '@atcute/bluesky-richtext-segmenter'; 3 - 4 - import { getHashtagUrl, getProfileUrl } from '../utils/bsky-url'; 5 - 6 - const grabFirstSupported = (features: FacetFeature[] | undefined): FacetFeature | undefined => { 7 - return features?.find( 8 - (feature) => 9 - feature.$type === 'app.bsky.richtext.facet#link' || 10 - feature.$type === 'app.bsky.richtext.facet#mention' || 11 - feature.$type === 'app.bsky.richtext.facet#tag', 12 - ); 13 - }; 14 - </script> 15 - 16 - <script lang="ts"> 17 - interface Props { 18 - text: string; 19 - facets?: Facet[]; 20 - large?: boolean; 21 - } 22 - 23 - const { text, facets, large }: Props = $props(); 24 - </script> 25 - 26 - <p class={`rich-text` + (large ? ` is-large` : ` is-small`)}> 27 - {#each segmentize(text, facets) as segment} 28 - {@const feature = grabFirstSupported(segment.features)} 29 - 30 - {#if !feature} 31 - {segment.text} 32 - {:else if feature.$type === 'app.bsky.richtext.facet#link'} 33 - <a target="_blank" href={feature.uri} rel="noopener nofollow" class="link">{segment.text}</a> 34 - {:else if feature.$type === 'app.bsky.richtext.facet#mention'} 35 - <a target="_blank" href={getProfileUrl(feature.did)} class="mention">{segment.text}</a> 36 - {:else if feature.$type === 'app.bsky.richtext.facet#tag'} 37 - <a target="_blank" href={getHashtagUrl(feature.tag)} class="hashtag">{segment.text}</a> 38 - {/if} 39 - {/each} 40 - </p> 41 - 42 - <style> 43 - .rich-text { 44 - overflow: hidden; 45 - white-space: pre-wrap; 46 - overflow-wrap: break-word; 47 - 48 - &:empty { 49 - display: none; 50 - } 51 - } 52 - .is-large { 53 - font-size: calc(var(--font-size) * 1); 54 - line-height: calc(var(--font-size) * 1.5); 55 - } 56 - 57 - .link, 58 - .mention, 59 - .hashtag { 60 - color: var(--text-link); 61 - 62 - &:hover { 63 - text-decoration: underline; 64 - } 65 - } 66 - </style>
-34
packages/internal/package.json
··· 1 - { 2 - "private": true, 3 - "type": "module", 4 - "name": "internal", 5 - "version": "0.1.0", 6 - "exports": { 7 - "./components/*": "./components/*", 8 - "./types/*": "./types/*", 9 - "./utils/*": "./utils/*" 10 - }, 11 - "peerDependencies": { 12 - "@atcute/bluesky": "^1.0.9", 13 - "@atcute/bluesky-richtext-parser": "^1.0.7", 14 - "@atcute/bluesky-richtext-segmenter": "^1.0.5", 15 - "@atcute/client": "^2.0.6", 16 - "svelte": "catalog:" 17 - }, 18 - "peerDependenciesMeta": { 19 - "@atcute/bluesky-richtext-parser": { 20 - "optional": true 21 - }, 22 - "@atcute/bluesky-richtext-segmenter": { 23 - "optional": true 24 - } 25 - }, 26 - "devDependencies": { 27 - "@atcute/bluesky": "^2.1.1", 28 - "@atcute/bluesky-richtext-parser": "^1.0.7", 29 - "@atcute/bluesky-richtext-segmenter": "^2.0.4", 30 - "@atcute/client": "^3.1.0", 31 - "@tsconfig/svelte": "^5.0.6", 32 - "svelte": "catalog:" 33 - } 34 - }
-8
packages/internal/svelte.config.js
··· 1 - export default { 2 - compilerOptions: { 3 - warningFilter: (warning) => { 4 - if (warning.code === 'state_referenced_locally') return false; 5 - return true; 6 - }, 7 - }, 8 - };
-13
packages/internal/tsconfig.json
··· 1 - { 2 - "extends": "@tsconfig/svelte/tsconfig.json", 3 - "compilerOptions": { 4 - "types": ["@atcute/bluesky/lexicons"], 5 - "target": "ESNext", 6 - "useDefineForClassFields": true, 7 - "module": "ESNext", 8 - "resolveJsonModule": true, 9 - "isolatedModules": true, 10 - "moduleDetection": "force", 11 - "noEmit": true, 12 - }, 13 - }
-7
packages/internal/types/post.ts
··· 1 - import type { AppBskyFeedDefs, Brand } from '@atcute/client/lexicons'; 2 - 3 - export interface PostData { 4 - thread: Brand.Union<AppBskyFeedDefs.ThreadViewPost> | null; 5 - contextless: boolean; 6 - allowUnauthenticated: boolean; 7 - }
-6
packages/internal/types/profile-card.ts
··· 1 - import type { AppBskyActorDefs } from '@atcute/client/lexicons'; 2 - 3 - export interface ProfileCardData { 4 - profile: AppBskyActorDefs.ProfileViewDetailed | null; 5 - allowUnauthenticated: boolean; 6 - }
-7
packages/internal/types/profile-feed.ts
··· 1 - import type { AppBskyActorDefs, AppBskyFeedDefs } from '@atcute/client/lexicons'; 2 - 3 - export interface ProfileFeedData { 4 - profile: AppBskyActorDefs.ProfileViewDetailed | null; 5 - feed: AppBskyFeedDefs.FeedViewPost[]; 6 - allowUnauthenticated: boolean; 7 - }
-27
packages/internal/utils/bsky-url.ts
··· 1 - export const getProfileUrl = (author: string): string => { 2 - return `https://bsky.app/profile/${author}`; 3 - }; 4 - 5 - export const getPostUrl = (author: string, rkey: string): string => { 6 - return `https://bsky.app/profile/${author}/post/${rkey}`; 7 - }; 8 - 9 - export const getHashtagUrl = (tag: string): string => { 10 - return `https://bsky.app/hashtag/${tag}`; 11 - }; 12 - 13 - export const getFeedUrl = (author: string, rkey: string): string => { 14 - return `https://bsky.app/profile/${author}/feed/${rkey}`; 15 - }; 16 - 17 - export const getListUrl = (author: string, rkey: string): string => { 18 - return `https://bsky.app/profile/${author}/list/${rkey}`; 19 - }; 20 - 21 - export const getStarterpackUrl = (author: string, rkey: string): string => { 22 - return `https://bsky.app/starter-pack/${author}/${rkey}`; 23 - }; 24 - 25 - export const getStarterpackImgUrl = (author: string, rkey: string): string => { 26 - return `https://ogcard.cdn.bsky.app/start/${author}/${rkey}`; 27 - };
-3
packages/internal/utils/constants.ts
··· 1 - export const DEFAULT_APPVIEW_URL = 'https://public.api.bsky.app'; 2 - 3 - export const NO_UNAUTHENTICATED_LABEL = '!no-unauthenticated';
-44
packages/internal/utils/date.ts
··· 1 - let startOfYear = 0; 2 - let endOfYear = 0; 3 - 4 - const fmtAbsoluteLong = new Intl.DateTimeFormat('en-US', { dateStyle: 'long', timeStyle: 'short' }); 5 - const fmtAbsShortWithYear = new Intl.DateTimeFormat('en-US', { dateStyle: 'medium' }); 6 - const fmtAbsShort = new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric' }); 7 - 8 - export const formatShortDate = (date: string | number): string => { 9 - const inst = new Date(date); 10 - const time = inst.getTime(); 11 - 12 - if (isNaN(time)) { 13 - return 'N/A'; 14 - } 15 - 16 - const now = Date.now(); 17 - if (now > endOfYear) { 18 - const date = new Date(now); 19 - 20 - date.setMonth(0, 1); 21 - date.setHours(0, 0, 0); 22 - startOfYear = date.getTime(); 23 - 24 - date.setFullYear(date.getFullYear() + 1, 0, 0); 25 - date.setHours(23, 59, 59, 999); 26 - endOfYear = date.getTime(); 27 - } 28 - 29 - if (time >= startOfYear && time <= endOfYear) { 30 - return fmtAbsShort.format(inst); 31 - } 32 - 33 - return fmtAbsShortWithYear.format(inst); 34 - }; 35 - 36 - export const formatLongDate = (date: string | number): string => { 37 - const inst = new Date(date); 38 - 39 - if (isNaN(inst.getTime())) { 40 - return 'N/A'; 41 - } 42 - 43 - return fmtAbsoluteLong.format(inst); 44 - };
-60
packages/internal/utils/labels.ts
··· 1 - import type { At, ComAtprotoLabelDefs } from '@atcute/client/lexicons'; 2 - 3 - export const FlagsNone = 0; 4 - export const FlagsNoSelf = 1 << 0; 5 - 6 - type Label = ComAtprotoLabelDefs.Label; 7 - 8 - export interface LabelDefinition { 9 - name: string; 10 - flags: number; 11 - } 12 - 13 - export const LABEL_MAPPING: Record<string, LabelDefinition> = { 14 - '!hide': { 15 - name: `Hidden by moderators`, 16 - flags: FlagsNoSelf, 17 - }, 18 - '!warn': { 19 - name: `Content warning`, 20 - flags: FlagsNoSelf, 21 - }, 22 - 23 - porn: { 24 - name: `Adult content`, 25 - flags: FlagsNone, 26 - }, 27 - sexual: { 28 - name: `Sexually suggestive`, 29 - flags: FlagsNone, 30 - }, 31 - 'graphic-media': { 32 - name: `Graphic media`, 33 - flags: FlagsNone, 34 - }, 35 - nudity: { 36 - name: `Nudity`, 37 - flags: FlagsNone, 38 - }, 39 - }; 40 - 41 - export const findLabel = (labels: Label[] | undefined, authorDid: At.Did): LabelDefinition | undefined => { 42 - if (labels?.length) { 43 - for (let idx = 0, len = labels.length; idx < len; idx++) { 44 - const label = labels[idx]; 45 - const val = label.val; 46 - 47 - if (!(val in LABEL_MAPPING)) { 48 - continue; 49 - } 50 - 51 - const def = LABEL_MAPPING[val]; 52 - 53 - if (def.flags & FlagsNoSelf && label.src === authorDid) { 54 - continue; 55 - } 56 - 57 - return def; 58 - } 59 - } 60 - };
-18
packages/internal/utils/number.ts
··· 1 - const long = new Intl.NumberFormat('en-US'); 2 - const compact = new Intl.NumberFormat('en-US', { notation: 'compact' }); 3 - 4 - export const formatCompactNumber = (value: number) => { 5 - if (value < 1_000) { 6 - return '' + value; 7 - } 8 - 9 - if (value < 100_000) { 10 - return long.format(value); 11 - } 12 - 13 - return compact.format(value); 14 - }; 15 - 16 - export const formatLongNumber = (value: number) => { 17 - return long.format(value); 18 - };
-27
packages/internal/utils/syntax/at-url.ts
··· 1 - export const AT_URI_RE = 2 - /^at:\/\/((?:did:[a-zA-Z0-9._:%-]+)|(?:[a-zA-Z0-9][a-zA-Z0-9-.]*))(?:\/([a-zA-Z0-9.-]+)(?:\/([a-zA-Z0-9_~.:-]{1,512}))?)?\/?(?:\?([^#\s]*))?(?:#([^\s]*))?$/; 3 - 4 - export interface ParsedAtUri { 5 - repo: string; 6 - collection: string; 7 - rkey: string; 8 - query: string; 9 - fragment: string; 10 - } 11 - 12 - export const parseAtUri = (str: string): ParsedAtUri => { 13 - const match = AT_URI_RE.exec(str); 14 - if (!match) { 15 - throw new InvalidAtUriError(`invalid at-uri: ${str}`); 16 - } 17 - 18 - return { 19 - repo: match[1], 20 - collection: match[2] ?? '', 21 - rkey: match[3] ?? '', 22 - query: match[4] ?? '', 23 - fragment: match[5] ?? '', 24 - }; 25 - }; 26 - 27 - export class InvalidAtUriError extends Error {}
-1
packages/svelte-site/.gitignore
··· 1 - pages/
-66
packages/svelte-site/README.md
··· 1 - # Svelte + TS + Vite 2 - 3 - This template should help get you started developing with Svelte and TypeScript in Vite. 4 - 5 - ## Recommended IDE Setup 6 - 7 - [VS Code](https://code.visualstudio.com/) + 8 - [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). 9 - 10 - ## Need an official Svelte framework? 11 - 12 - Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy 13 - anywhere with its serverless-first approach and adapt to various platforms, with out of the box 14 - support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, 15 - Tailwind CSS, and more. 16 - 17 - ## Technical considerations 18 - 19 - **Why use this over SvelteKit?** 20 - 21 - - It brings its own routing solution which might not be preferable for some users. 22 - - It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app. 23 - 24 - This template contains as little as possible to get started with Vite + TypeScript + Svelte, while 25 - taking into account the developer experience with regards to HMR and intellisense. It demonstrates 26 - capabilities on par with the other `create-vite` templates and is a good starting point for 27 - beginners dipping their toes into a Vite + Svelte project. 28 - 29 - Should you later need the extended capabilities and extensibility provided by SvelteKit, the 30 - template has been structured similarly to SvelteKit so that it is easy to migrate. 31 - 32 - **Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?** 33 - 34 - Setting `compilerOptions.types` shuts out all other types not explicitly listed in the 35 - configuration. Using triple-slash references keeps the default TypeScript setting of accepting type 36 - information from the entire workspace, while also adding `svelte` and `vite/client` type 37 - information. 38 - 39 - **Why include `.vscode/extensions.json`?** 40 - 41 - Other templates indirectly recommend extensions via the README, but this file allows VS Code to 42 - prompt the user to install the recommended extension upon opening the project. 43 - 44 - **Why enable `allowJs` in the TS template?** 45 - 46 - While `allowJs: false` would indeed prevent the use of `.js` files in the project, it does not 47 - prevent the use of JavaScript syntax in `.svelte` files. In addition, it would force 48 - `checkJs: false`, bringing the worst of both worlds: not being able to guarantee the entire codebase 49 - is TypeScript, and also having worse typechecking for the existing JavaScript. In addition, there 50 - are valid use cases in which a mixed codebase may be relevant. 51 - 52 - **Why is HMR not preserving my local component state?** 53 - 54 - HMR state preservation comes with a number of gotchas! It has been disabled by default in both 55 - `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read 56 - the details [here](https://github.com/rixo/svelte-hmr#svelte-hmr). 57 - 58 - If you have state that's important to retain within a component, consider creating an external store 59 - which would not be replaced by HMR. 60 - 61 - ```ts 62 - // store.ts 63 - // An extremely simple external store 64 - import { writable } from 'svelte/store'; 65 - export default writable(0); 66 - ```
-12
packages/svelte-site/index.html
··· 1 - <!doctype html> 2 - <html lang="en"> 3 - <head> 4 - <meta charset="UTF-8" /> 5 - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 - <title>Bluesky embed</title> 7 - </head> 8 - <body> 9 - <div id="app"></div> 10 - <script type="module" src="./src/main.ts"></script> 11 - </body> 12 - </html>
-30
packages/svelte-site/package.json
··· 1 - { 2 - "name": "svelte-site", 3 - "private": true, 4 - "version": "0.0.0", 5 - "type": "module", 6 - "scripts": { 7 - "dev": "vite", 8 - "build": "vite build", 9 - "preview": "vite preview", 10 - "check": "svelte-check --tsconfig ./tsconfig.json && tsc -p tsconfig.node.json", 11 - "publish": "pnpm run build && ./scripts/publish.sh" 12 - }, 13 - "dependencies": { 14 - "@atcute/bluesky": "^2.1.1", 15 - "@atcute/client": "^3.1.0", 16 - "bluesky-post-embed": "workspace:^", 17 - "bluesky-profile-card-embed": "workspace:^", 18 - "bluesky-profile-feed-embed": "workspace:^", 19 - "internal": "workspace:^" 20 - }, 21 - "devDependencies": { 22 - "@sveltejs/vite-plugin-svelte": "^6.2.1", 23 - "@tsconfig/svelte": "^5.0.6", 24 - "svelte": "^5.45.5", 25 - "svelte-check": "^4.3.4", 26 - "terser": "^5.44.1", 27 - "tslib": "^2.8.1", 28 - "vite": "^7.2.6" 29 - } 30 - }
-18
packages/svelte-site/scripts/publish.sh
··· 1 - #!/usr/bin/env bash 2 - 3 - set -euo pipefail 4 - 5 - if [[ -n $(git status --porcelain) ]]; then 6 - echo 'Working directory is not clean' 7 - git status --short 8 - exit 1 9 - fi 10 - 11 - GIT_COMMIT=$(git rev-parse HEAD) 12 - 13 - rsync -aHAX --delete --exclude=.git --exclude=.nojekyll dist/ pages/ 14 - touch pages/.nojekyll 15 - 16 - git -C pages/ add . 17 - git -C pages/ commit -m "deploy: ${GIT_COMMIT}" 18 - git -C pages/ push
-159
packages/svelte-site/src/App.svelte
··· 1 - <script lang="ts" module> 2 - const PostDisplay = () => import('./components/display/PostDisplay.svelte'); 3 - const ProfileCardDisplay = () => import('./components/display/ProfileCardDisplay.svelte'); 4 - const ProfileFeedDisplay = () => import('./components/display/ProfileFeedDisplay.svelte'); 5 - </script> 6 - 7 - <script lang="ts"> 8 - import { extract_url } from './lib/matcher'; 9 - 10 - import Banner from './components/Banner.svelte'; 11 - import CircularSpinner from './components/CircularSpinner.svelte'; 12 - import Field from './components/Field.svelte'; 13 - import Lazy from './components/Lazy.svelte'; 14 - import TextInput from './components/TextInput.svelte'; 15 - 16 - const DEFAULT_URL = 'https://bsky.app/profile/did:plc:ragtjsm2j2vknwkz3zp4oxrd/post/3kj2umze7zj2n'; 17 - // const DEFAULT_URL = 'https://bsky.app/profile/did:plc:ragtjsm2j2vknwkz3zp4oxrd'; 18 - 19 - let url = $state(''); 20 - let profile_type = $state<'card' | 'feed'>('feed'); 21 - 22 - const matched = $derived(extract_url(url || DEFAULT_URL)); 23 - </script> 24 - 25 - <div class="app"> 26 - <h1 class="header"> 27 - <code>&lt;bluesky-embed&gt;</code> 28 - </h1> 29 - 30 - <Field label="Bluesky post or profile URL"> 31 - <TextInput type="url" bind:value={url} placeholder={DEFAULT_URL} /> 32 - </Field> 33 - 34 - {#if matched && matched.type === 'profile'} 35 - <fieldset class="choices"> 36 - <label class="choice"> 37 - <input type="radio" name="profile-type" value="feed" bind:group={profile_type} /> 38 - <span>Profile feed</span> 39 - </label> 40 - 41 - <label class="choice"> 42 - <input type="radio" name="profile-type" value="card" bind:group={profile_type} /> 43 - <span>Profile card</span> 44 - </label> 45 - </fieldset> 46 - {/if} 47 - 48 - <main class="main"> 49 - {#if !matched} 50 - <Banner type="alert">Invalid URL, did you type it correctly?</Banner> 51 - {:else if matched.type === 'post'} 52 - <Lazy loader={PostDisplay} fallback={LazyFallback} boundary={LazyBoundary}> 53 - {#snippet children(Component)} 54 - <Component {matched} /> 55 - {/snippet} 56 - </Lazy> 57 - {:else if matched.type === 'profile'} 58 - <Lazy 59 - loader={profile_type === 'card' ? ProfileCardDisplay : ProfileFeedDisplay} 60 - fallback={LazyFallback} 61 - boundary={LazyBoundary} 62 - > 63 - {#snippet children(Component)} 64 - <Component {matched} /> 65 - {/snippet} 66 - </Lazy> 67 - {/if} 68 - </main> 69 - 70 - <footer class="footer"> 71 - <span> 72 - made with โค๏ธ by <a href="https://bsky.app/profile/did:plc:ia76kvnndjutgedggx2ibrem">@mary.my.id</a> 73 - </span> 74 - <span aria-hidden="true"> ยท </span> 75 - <span> 76 - <a href="https://github.com/mary-ext/bluesky-embed">source code</a> 77 - </span> 78 - <span aria-hidden="true"> ยท </span> 79 - <span>MIT License</span> 80 - </footer> 81 - </div> 82 - 83 - {#snippet LazyFallback()} 84 - <CircularSpinner /> 85 - {/snippet} 86 - 87 - {#snippet LazyBoundary(err: unknown)} 88 - <Banner type="alert"> 89 - {'' + err} 90 - </Banner> 91 - {/snippet} 92 - 93 - <style> 94 - .app { 95 - margin: 0 auto; 96 - padding: 36px 16px; 97 - width: 100%; 98 - max-width: calc(550px + (16 * 2px)); 99 - } 100 - 101 - .header { 102 - margin: 24px 0; 103 - } 104 - 105 - .main { 106 - margin: 36px 0; 107 - } 108 - 109 - .choices { 110 - display: flex; 111 - flex-direction: column; 112 - gap: 8px; 113 - margin: 16px 0 36px 0; 114 - border: 0; 115 - padding: 0; 116 - } 117 - .choice { 118 - display: flex; 119 - align-items: center; 120 - gap: 8px; 121 - font-size: 0.875rem; 122 - line-height: 1.25rem; 123 - 124 - input { 125 - appearance: none; 126 - outline: 2px none #2563eb; 127 - outline-offset: 2px; 128 - border: 1px solid #9ca3af; 129 - border-radius: 8px; 130 - width: 16px; 131 - height: 16px; 132 - 133 - &:checked { 134 - border: 0; 135 - background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e"); 136 - background-color: #2563eb; 137 - } 138 - &:focus { 139 - outline-style: solid; 140 - } 141 - } 142 - } 143 - 144 - .footer { 145 - display: flex; 146 - flex-wrap: wrap; 147 - gap: 0.5rem; 148 - margin: 36px 0 0 0; 149 - border-top: 1px solid #d1d5db; 150 - padding: 36px 0 0 0; 151 - color: #4b5563; 152 - font-size: 0.875rem; 153 - line-height: 1.25rem; 154 - 155 - a { 156 - color: #2563eb; 157 - } 158 - } 159 - </style>
-42
packages/svelte-site/src/components/Banner.svelte
··· 1 - <script lang="ts"> 2 - import type { Snippet } from 'svelte'; 3 - 4 - interface Props { 5 - type: 'alert' | 'inform'; 6 - children: Snippet<[]>; 7 - } 8 - 9 - let { type, children }: Props = $props(); 10 - </script> 11 - 12 - <div class="banner" class:type-alert={type === 'alert'} class:type-inform={type === 'inform'}> 13 - {@render children()} 14 - </div> 15 - 16 - <style> 17 - .banner { 18 - border: 1px solid; 19 - border-radius: 4px; 20 - padding: 10px 12px; 21 - font-weight: 500; 22 - font-size: 0.875rem; 23 - line-height: 1.25rem; 24 - 25 - :global(a) { 26 - color: inherit; 27 - font-weight: 600; 28 - } 29 - } 30 - 31 - .type-alert { 32 - border-color: #fca5a5; 33 - background: #fee2e2; 34 - color: #991b1b; 35 - } 36 - 37 - .type-inform { 38 - border-color: #bfdbfe; 39 - background: #dbeafe; 40 - color: #1e40af; 41 - } 42 - </style>
-42
packages/svelte-site/src/components/CircularSpinner.svelte
··· 1 - <script lang="ts"> 2 - interface Props {} 3 - 4 - let {}: Props = $props(); 5 - </script> 6 - 7 - <svg viewBox="0 0 32 32" class="circular-spinner"> 8 - <circle cx="16" cy="16" fill="none" r="14" stroke-width="4" class="background" /> 9 - <circle 10 - cx="16" 11 - cy="16" 12 - fill="none" 13 - r="14" 14 - stroke-width="4" 15 - stroke-dasharray="80px" 16 - stroke-dashoffset="60px" 17 - class="accented" 18 - /> 19 - </svg> 20 - 21 - <style> 22 - .circular-spinner { 23 - display: block; 24 - animation: spin 1s linear infinite; 25 - margin: 0 auto; 26 - width: 24px; 27 - height: 24px; 28 - } 29 - @keyframes spin { 30 - to { 31 - transform: rotate(360deg); 32 - } 33 - } 34 - 35 - .accented { 36 - stroke: #2563eb; 37 - } 38 - .background { 39 - opacity: 20%; 40 - stroke: #2563eb; 41 - } 42 - </style>
-100
packages/svelte-site/src/components/CodeBlock.svelte
··· 1 - <script lang="ts"> 2 - interface Props { 3 - code: string; 4 - } 5 - 6 - let { code }: Props = $props(); 7 - </script> 8 - 9 - <div class="code-block"> 10 - <pre><code>{code}</code></pre> 11 - 12 - <div class="actions"> 13 - <button 14 - title="Copy" 15 - aria-label="Copy" 16 - class="action-button" 17 - onclick={() => { 18 - navigator.clipboard.writeText(code).catch(() => alert(`Failed to copy to clipboard`)); 19 - }} 20 - > 21 - <svg class="icon" fill="none" viewBox="0 0 24 24"> 22 - <path 23 - stroke="currentColor" 24 - stroke-linecap="square" 25 - stroke-width="2" 26 - d="M15 5h4v16H5V5h4m0-2h6v4H9V3Z" 27 - /> 28 - </svg> 29 - </button> 30 - </div> 31 - </div> 32 - 33 - <style> 34 - .code-block { 35 - display: flex; 36 - gap: 12px; 37 - border: 1px solid #d1d5db; 38 - border-radius: 4px; 39 - background: #f9fafb; 40 - padding: 12px; 41 - overflow: hidden; 42 - overflow-x: auto; 43 - 44 - pre { 45 - flex-grow: 1; 46 - margin: 0; 47 - font-size: 0.75rem; 48 - line-height: 1.25rem; 49 - } 50 - } 51 - 52 - .actions { 53 - position: sticky; 54 - top: 0; 55 - right: 0; 56 - } 57 - .action-button { 58 - display: flex; 59 - justify-content: center; 60 - align-items: center; 61 - cursor: pointer; 62 - box-shadow: 63 - 0 1px 3px 0 rgb(0 0 0 / 0.1), 64 - 0 1px 2px -1px rgb(0 0 0 / 0.1); 65 - border: 1px solid #d1d5db; 66 - border-radius: 4px; 67 - background: #ffffff; 68 - padding: 0; 69 - width: 32px; 70 - height: 32px; 71 - color: #4b5563; 72 - 73 - @media (pointer: fine) { 74 - opacity: 0; 75 - transition: 75ms ease-in; 76 - 77 - .code-block:hover &, 78 - .code-block:focus-within & { 79 - opacity: 1; 80 - } 81 - 82 - &:hover { 83 - border-color: #9ca3af; 84 - background: #e5e7eb; 85 - color: #1f2937; 86 - } 87 - } 88 - 89 - &:active { 90 - border-color: #9ca3af; 91 - background: #e5e7eb; 92 - color: #1f2937; 93 - } 94 - } 95 - 96 - .icon { 97 - width: 16px; 98 - height: 16px; 99 - } 100 - </style>
-36
packages/svelte-site/src/components/Field.svelte
··· 1 - <script lang="ts"> 2 - import type { Snippet } from 'svelte'; 3 - 4 - interface Props { 5 - label: string; 6 - children: Snippet; 7 - } 8 - 9 - let { label, children }: Props = $props(); 10 - </script> 11 - 12 - <div class="field"> 13 - <label class="input-wrapper"> 14 - <span class="label">{label}</span> 15 - {@render children()} 16 - </label> 17 - </div> 18 - 19 - <style> 20 - .field { 21 - display: flex; 22 - flex-direction: column; 23 - gap: 8px; 24 - } 25 - 26 - .input-wrapper { 27 - display: contents; 28 - } 29 - 30 - .label { 31 - color: #4b5563; 32 - font-weight: 600; 33 - font-size: 0.875rem; 34 - line-height: 1.25rem; 35 - } 36 - </style>
-37
packages/svelte-site/src/components/Lazy.svelte
··· 1 - <script lang="ts" module> 2 - import type { Snippet, Component } from 'svelte'; 3 - 4 - type SvelteComponentModule<C extends Component = Component> = { default: C }; 5 - type LoaderFunction<C extends Component = Component> = () => Promise<SvelteComponentModule<C>>; 6 - 7 - const map = new WeakMap<LoaderFunction, Promise<Component>>(); 8 - const get_promise = <C extends Component>(fn: LoaderFunction<C>): Promise<C> => { 9 - let promise = map.get(fn) satisfies Promise<Component> | undefined; 10 - if (promise === undefined) { 11 - map.set(fn, (promise = fn().then((mod) => mod.default))); 12 - } 13 - 14 - return promise as Promise<C>; 15 - }; 16 - </script> 17 - 18 - <script lang="ts" generics="C extends Component<any>"> 19 - interface Props { 20 - loader: LoaderFunction<C>; 21 - children: Snippet<[component: C]>; 22 - fallback: Snippet<[]>; 23 - boundary: Snippet<[error: unknown]>; 24 - } 25 - 26 - let { loader, children, fallback, boundary }: Props = $props(); 27 - 28 - const promise = $derived(get_promise(loader)); 29 - </script> 30 - 31 - {#await promise} 32 - {@render fallback()} 33 - {:then component} 34 - {@render children(component)} 35 - {:catch err} 36 - {@render boundary(err)} 37 - {/await}
-30
packages/svelte-site/src/components/TextInput.svelte
··· 1 - <script lang="ts"> 2 - interface Props { 3 - type?: 'text' | 'url'; 4 - value?: string; 5 - placeholder?: string; 6 - } 7 - 8 - let { type, value = $bindable(), placeholder }: Props = $props(); 9 - </script> 10 - 11 - <input {type} {placeholder} bind:value class="text-input" /> 12 - 13 - <style> 14 - .text-input { 15 - outline: 2px none #2563eb; 16 - outline-offset: -1px; 17 - border: 1px solid #9ca3af; 18 - border-radius: 4px; 19 - padding: 8px 12px; 20 - font-size: 0.875rem; 21 - line-height: 1.25rem; 22 - 23 - &::placeholder { 24 - color: #9ca3af; 25 - } 26 - &:focus { 27 - outline-style: solid; 28 - } 29 - } 30 - </style>
-115
packages/svelte-site/src/components/display/PostDisplay.svelte
··· 1 - <script lang="ts"> 2 - import { onDestroy } from 'svelte'; 3 - 4 - import type { AppBskyFeedDefs, AppBskyFeedPost } from '@atcute/client/lexicons'; 5 - import { fetchPost as fetch_post } from 'bluesky-post-embed/core'; 6 - 7 - import { getPostUrl } from 'internal/utils/bsky-url.ts'; 8 - import { formatLongDate } from 'internal/utils/date.ts'; 9 - import { parseAtUri } from 'internal/utils/syntax/at-url.ts'; 10 - 11 - import { escape_html } from '../../lib/html'; 12 - import type { ExtractedPostInfo } from '../../lib/matcher'; 13 - 14 - import Banner from '../Banner.svelte'; 15 - import CircularSpinner from '../CircularSpinner.svelte'; 16 - import CodeBlock from '../CodeBlock.svelte'; 17 - import BlueskyPost from '../embeds/BlueskyPost.svelte'; 18 - import Guide from '../guides/Guide.svelte'; 19 - import GuideInstructions from '../guides/GuideInstructions.svelte'; 20 - 21 - interface Props { 22 - matched: ExtractedPostInfo; 23 - } 24 - 25 - let { matched }: Props = $props(); 26 - 27 - let controller: AbortController | undefined; 28 - const promise = $derived.by(() => { 29 - controller?.abort(); 30 - controller = new AbortController(); 31 - 32 - const signal = controller.signal; 33 - const uri = `at://${matched.author}/app.bsky.feed.post/${matched.rkey}`; 34 - 35 - return fetch_post({ uri, signal }); 36 - }); 37 - 38 - onDestroy(() => { 39 - controller?.abort(); 40 - }); 41 - 42 - const JSDELIVR_URL = `https://cdn.jsdelivr.net/npm/bluesky-post-embed@^1.0.0`; 43 - const get_prerequisite_markup = () => { 44 - return `<!-- Core web component and styling --> 45 - <script type="module" src="${JSDELIVR_URL}/+esm"></${'script'}> 46 - <link rel="stylesheet" href="${JSDELIVR_URL}/dist/core.min.css"> 47 - 48 - <!-- Built-in themes --> 49 - <link rel="stylesheet" href="${JSDELIVR_URL}/themes/light.min.css" media="(prefers-color-scheme: light)"> 50 - <link rel="stylesheet" href="${JSDELIVR_URL}/themes/dim.min.css" media="(prefers-color-scheme: dark)"> 51 - 52 - <!-- Fallback/placeholder elements if JS script is taking a while to load or is failing --> 53 - <style> 54 - .bluesky-post-fallback { 55 - margin: 16px 0; 56 - border-left: 3px solid var(--divider); 57 - padding: 4px 8px; 58 - white-space: pre-wrap; 59 - overflow-wrap: break-word; 60 - } 61 - .bluesky-post-fallback p { 62 - margin: 0 0 8px 0; 63 - } 64 - </${'style'}> 65 - `; 66 - }; 67 - 68 - const get_markup = (post: AppBskyFeedDefs.PostView) => { 69 - const author = post.author; 70 - const record = post.record as AppBskyFeedPost.Record; 71 - 72 - return `<bluesky-post src="${escape_html(post.uri)}"> 73 - <blockquote class="bluesky-post-fallback"> 74 - <p dir="auto">${escape_html(record.text)}</p> 75 - โ€” ${author.displayName?.trim() ? `${escape_html(author.displayName)} (@${escape_html(author.handle)})` : `@${escape_html(author.handle)}`} 76 - <a href="${escape_html(getPostUrl(author.did, parseAtUri(post.uri).rkey))}">${formatLongDate(post.indexedAt)}</a> 77 - </blockquote> 78 - </bluesky-post> 79 - `; 80 - }; 81 - </script> 82 - 83 - {#await promise} 84 - <CircularSpinner /> 85 - {:then data} 86 - <BlueskyPost {data} /> 87 - 88 - {#if data.thread} 89 - <Guide title="How do I embed this to my website?"> 90 - <Banner type="inform"> 91 - Doing server-side rendering? Check out examples for 92 - <a href="https://github.com/mary-ext/bluesky-embed-astro">Astro</a> and 93 - <a href="https://github.com/mary-ext/bluesky-embed-sveltekit">SvelteKit</a>. 94 - </Banner> 95 - 96 - <GuideInstructions> 97 - <li> 98 - <p> 99 - Insert the following scripts and stylesheets to the <code>&lt;head&gt;</code> of your website. 100 - </p> 101 - <CodeBlock code={get_prerequisite_markup()} /> 102 - </li> 103 - 104 - <li> 105 - <p>Insert the following markup in wherever you want the post to be.</p> 106 - <CodeBlock code={get_markup(data.thread.post)} /> 107 - </li> 108 - </GuideInstructions> 109 - </Guide> 110 - {/if} 111 - {:catch err} 112 - <Banner type="alert"> 113 - {'' + err} 114 - </Banner> 115 - {/await}
-93
packages/svelte-site/src/components/display/ProfileCardDisplay.svelte
··· 1 - <script lang="ts"> 2 - import { onDestroy } from 'svelte'; 3 - 4 - import type { AppBskyActorDefs } from '@atcute/client/lexicons'; 5 - import { fetchProfileCard as fetch_profile_card } from 'bluesky-profile-card-embed/core'; 6 - 7 - import { escape_html } from '../../lib/html'; 8 - import type { ExtractedProfileInfo } from '../../lib/matcher'; 9 - 10 - import Banner from '../Banner.svelte'; 11 - import CircularSpinner from '../CircularSpinner.svelte'; 12 - import CodeBlock from '../CodeBlock.svelte'; 13 - import BlueskyProfileCard from '../embeds/BlueskyProfileCard.svelte'; 14 - import Guide from '../guides/Guide.svelte'; 15 - import GuideInstructions from '../guides/GuideInstructions.svelte'; 16 - 17 - interface Props { 18 - matched: ExtractedProfileInfo; 19 - } 20 - 21 - let { matched }: Props = $props(); 22 - 23 - let controller: AbortController | undefined; 24 - const promise = $derived.by(() => { 25 - controller?.abort(); 26 - controller = new AbortController(); 27 - 28 - const signal = controller.signal; 29 - const actor = matched.actor; 30 - 31 - return fetch_profile_card({ actor, signal }); 32 - }); 33 - 34 - onDestroy(() => { 35 - controller?.abort(); 36 - }); 37 - 38 - const get_prerequisite_markup = () => { 39 - const JSDELIVR_URL = `https://cdn.jsdelivr.net/npm/bluesky-profile-card-embed@^1.0.0`; 40 - 41 - return `<!-- Core web component and styling --> 42 - <script type="module" src="${JSDELIVR_URL}/+esm"></${'script'}> 43 - <link rel="stylesheet" href="${JSDELIVR_URL}/dist/core.min.css"> 44 - 45 - <!-- Built-in themes --> 46 - <link rel="stylesheet" href="${JSDELIVR_URL}/themes/light.min.css" media="(prefers-color-scheme: light)"> 47 - <link rel="stylesheet" href="${JSDELIVR_URL}/themes/dim.min.css" media="(prefers-color-scheme: dark)"> 48 - `; 49 - }; 50 - 51 - const get_markup = (profile: AppBskyActorDefs.ProfileViewDetailed) => { 52 - const url = `https://bsky.app/profile/${profile.did}`; 53 - 54 - return `<bluesky-profile-card actor="${escape_html(profile.did)}"> 55 - <a target="_blank" href="${escape_html(url)}" class="bluesky-profile-card-fallback"> 56 - ${ 57 - profile.displayName?.trim() 58 - ? `Follow ${escape_html(profile.displayName)} (@${escape_html(profile.handle)}) on Bluesky` 59 - : `Follow @${escape_html(profile.handle)} on Bluesky` 60 - } 61 - </a> 62 - </bluesky-profile-card> 63 - `; 64 - }; 65 - </script> 66 - 67 - {#await promise} 68 - <CircularSpinner /> 69 - {:then data} 70 - <BlueskyProfileCard {data} /> 71 - 72 - {#if data.profile} 73 - <Guide title="How do I embed this to my website?"> 74 - <GuideInstructions> 75 - <li> 76 - <p> 77 - Insert the following scripts and stylesheets to the <code>&lt;head&gt;</code> of your website. 78 - </p> 79 - <CodeBlock code={get_prerequisite_markup()} /> 80 - </li> 81 - 82 - <li> 83 - <p>Insert the following markup in wherever you want the profile feed to be.</p> 84 - <CodeBlock code={get_markup(data.profile)} /> 85 - </li> 86 - </GuideInstructions> 87 - </Guide> 88 - {/if} 89 - {:catch err} 90 - <Banner type="alert"> 91 - {'' + err} 92 - </Banner> 93 - {/await}
-93
packages/svelte-site/src/components/display/ProfileFeedDisplay.svelte
··· 1 - <script lang="ts"> 2 - import { onDestroy } from 'svelte'; 3 - 4 - import type { AppBskyActorDefs } from '@atcute/client/lexicons'; 5 - import { fetchProfileFeed as fetch_profile_feed } from 'bluesky-profile-feed-embed/core'; 6 - 7 - import { escape_html } from '../../lib/html'; 8 - import type { ExtractedProfileInfo } from '../../lib/matcher'; 9 - 10 - import Banner from '../Banner.svelte'; 11 - import CircularSpinner from '../CircularSpinner.svelte'; 12 - import CodeBlock from '../CodeBlock.svelte'; 13 - import BlueskyProfileFeed from '../embeds/BlueskyProfileFeed.svelte'; 14 - import Guide from '../guides/Guide.svelte'; 15 - import GuideInstructions from '../guides/GuideInstructions.svelte'; 16 - 17 - interface Props { 18 - matched: ExtractedProfileInfo; 19 - } 20 - 21 - let { matched }: Props = $props(); 22 - 23 - let controller: AbortController | undefined; 24 - const promise = $derived.by(() => { 25 - controller?.abort(); 26 - controller = new AbortController(); 27 - 28 - const signal = controller.signal; 29 - const actor = matched.actor; 30 - 31 - return fetch_profile_feed({ actor, signal }); 32 - }); 33 - 34 - onDestroy(() => { 35 - controller?.abort(); 36 - }); 37 - 38 - const get_prerequisite_markup = () => { 39 - const JSDELIVR_URL = `https://cdn.jsdelivr.net/npm/bluesky-profile-feed-embed@^1.0.0`; 40 - 41 - return `<!-- Core web component and styling --> 42 - <script type="module" src="${JSDELIVR_URL}/+esm"></${'script'}> 43 - <link rel="stylesheet" href="${JSDELIVR_URL}/dist/core.min.css"> 44 - 45 - <!-- Built-in themes --> 46 - <link rel="stylesheet" href="${JSDELIVR_URL}/themes/light.min.css" media="(prefers-color-scheme: light)"> 47 - <link rel="stylesheet" href="${JSDELIVR_URL}/themes/dim.min.css" media="(prefers-color-scheme: dark)"> 48 - `; 49 - }; 50 - 51 - const get_markup = (profile: AppBskyActorDefs.ProfileViewDetailed) => { 52 - const url = `https://bsky.app/profile/${profile.did}`; 53 - 54 - return `<bluesky-profile-feed actor="${escape_html(profile.did)}" include-pins> 55 - <a target="_blank" href="${escape_html(url)}" class="bluesky-profile-feed-fallback"> 56 - ${ 57 - profile.displayName?.trim() 58 - ? `Posts by ${escape_html(profile.displayName)} (@${escape_html(profile.handle)})` 59 - : `Posts by @${escape_html(profile.handle)}` 60 - } 61 - </a> 62 - </bluesky-profile-feed> 63 - `; 64 - }; 65 - </script> 66 - 67 - {#await promise} 68 - <CircularSpinner /> 69 - {:then data} 70 - <BlueskyProfileFeed {data} /> 71 - 72 - {#if data.profile} 73 - <Guide title="How do I embed this to my website?"> 74 - <GuideInstructions> 75 - <li> 76 - <p> 77 - Insert the following scripts and stylesheets to the <code>&lt;head&gt;</code> of your website. 78 - </p> 79 - <CodeBlock code={get_prerequisite_markup()} /> 80 - </li> 81 - 82 - <li> 83 - <p>Insert the following markup in wherever you want the profile feed to be.</p> 84 - <CodeBlock code={get_markup(data.profile)} /> 85 - </li> 86 - </GuideInstructions> 87 - </Guide> 88 - {/if} 89 - {:catch err} 90 - <Banner type="alert"> 91 - {'' + err} 92 - </Banner> 93 - {/await}
-12
packages/svelte-site/src/components/embeds/BlueskyPost.svelte
··· 1 - <script lang="ts"> 2 - import { type PostData, renderPost } from 'bluesky-post-embed/core'; 3 - import 'bluesky-post-embed/style.css'; 4 - 5 - interface Props { 6 - data: PostData; 7 - } 8 - 9 - let { data }: Props = $props(); 10 - </script> 11 - 12 - <bluesky-post src={data.thread?.post.uri}>{@html renderPost(data)}</bluesky-post>
-12
packages/svelte-site/src/components/embeds/BlueskyProfileCard.svelte
··· 1 - <script lang="ts"> 2 - import { type ProfileCardData, renderProfileCard } from 'bluesky-profile-card-embed/core'; 3 - import 'bluesky-profile-card-embed/style.css'; 4 - 5 - interface Props { 6 - data: ProfileCardData; 7 - } 8 - 9 - let { data }: Props = $props(); 10 - </script> 11 - 12 - <bluesky-profile-card actor={data.profile?.did}>{@html renderProfileCard(data)}</bluesky-profile-card>
-12
packages/svelte-site/src/components/embeds/BlueskyProfileFeed.svelte
··· 1 - <script lang="ts"> 2 - import { type ProfileFeedData, renderProfileFeed } from 'bluesky-profile-feed-embed/core'; 3 - import 'bluesky-profile-feed-embed/style.css'; 4 - 5 - interface Props { 6 - data: ProfileFeedData; 7 - } 8 - 9 - let { data }: Props = $props(); 10 - </script> 11 - 12 - <bluesky-profile-feed actor={data.profile?.did}>{@html renderProfileFeed(data)}</bluesky-profile-feed>
-26
packages/svelte-site/src/components/guides/Guide.svelte
··· 1 - <script lang="ts"> 2 - import type { Snippet } from 'svelte'; 3 - 4 - interface Props { 5 - title: string; 6 - children: Snippet<[]>; 7 - } 8 - 9 - let { title, children }: Props = $props(); 10 - </script> 11 - 12 - <div class="guide"> 13 - <h4 class="guide-header">{title}</h4> 14 - 15 - {@render children()} 16 - </div> 17 - 18 - <style> 19 - .guide { 20 - margin: 36px 0 0 0; 21 - border-top: 1px solid #d1d5db; 22 - } 23 - .guide-header { 24 - margin: 36px 0 16px 0; 25 - } 26 - </style>
-26
packages/svelte-site/src/components/guides/GuideInstructions.svelte
··· 1 - <script lang="ts"> 2 - import type { Snippet } from 'svelte'; 3 - 4 - interface Props { 5 - children: Snippet<[]>; 6 - } 7 - 8 - let { children }: Props = $props(); 9 - </script> 10 - 11 - <ol class="guide-instructions"> 12 - {@render children()} 13 - </ol> 14 - 15 - <style> 16 - .guide-instructions { 17 - margin: 24px 0 0 0; 18 - padding: 0 0 0 22px; 19 - font-size: 0.875rem; 20 - line-height: 1.25rem; 21 - 22 - :global(li + li) { 23 - margin: 24px 0 0 0; 24 - } 25 - } 26 - </style>
-4
packages/svelte-site/src/lib/component.ts
··· 1 - let uid = 0; 2 - export const use_id = () => { 3 - return `s:${uid++}`; 4 - };
-3
packages/svelte-site/src/lib/html.ts
··· 1 - export const escape_html = (text: string): string => { 2 - return text.replace(/[<"&]/g, (c) => '&#' + c.charCodeAt(0) + ';'); 3 - };
-60
packages/svelte-site/src/lib/matcher.ts
··· 1 - import { is_at_identifier, is_tid } from './strings'; 2 - 3 - export interface ExtractedPostInfo { 4 - type: 'post'; 5 - author: string; 6 - rkey: string; 7 - } 8 - 9 - export interface ExtractedProfileInfo { 10 - type: 'profile'; 11 - actor: string; 12 - } 13 - 14 - export type ExtractedInfo = ExtractedPostInfo | ExtractedProfileInfo; 15 - 16 - export const extract_url = (str: string): ExtractedInfo | null => { 17 - const url = safe_parse_url(str); 18 - if (!url) { 19 - return null; 20 - } 21 - 22 - let match: RegExpExecArray | null | undefined; 23 - if (url.host === 'bsky.app' || url.host === 'staging.bsky.app' || url.host === 'main.bsky.dev') { 24 - if ((match = /^\/profile\/([^/]+)\/post\/([^/]+)\/?$/.exec(url.pathname))) { 25 - if (!is_at_identifier(match[1]) || !is_tid(match[2])) { 26 - return null; 27 - } 28 - 29 - return { type: 'post', author: match[1], rkey: match[2] }; 30 - } 31 - 32 - if ((match = /^\/profile\/([^/]+)\/?$/.exec(url.pathname))) { 33 - if (!is_at_identifier(match[1])) { 34 - return null; 35 - } 36 - 37 - return { type: 'profile', actor: match[1] }; 38 - } 39 - } 40 - 41 - return null; 42 - }; 43 - 44 - const safe_parse_url = (str: string): URL | null => { 45 - let url: URL | null | undefined; 46 - if ('parse' in URL) { 47 - url = URL.parse(str); 48 - } else { 49 - try { 50 - // @ts-expect-error: `'parse' in URL` is giving truthy 51 - url = new URL(str); 52 - } catch {} 53 - } 54 - 55 - if (url && (url.protocol === 'https:' || url.protocol === 'http:')) { 56 - return url; 57 - } 58 - 59 - return null; 60 - };
-28
packages/svelte-site/src/lib/strings.ts
··· 1 - export const RECORD_KEY_RE = /^(?!\.{1,2}$)[a-zA-Z0-9_~.:-]{1,512}$/; 2 - 3 - export const is_record_key = (str: string): boolean => { 4 - return str.length >= 1 && str.length <= 512 && RECORD_KEY_RE.test(str); 5 - }; 6 - 7 - export const TID_RE = /^[234567abcdefghij][234567abcdefghijklmnopqrstuvwxyz]{12}$/; 8 - 9 - export const is_tid = (str: string): boolean => { 10 - return str.length === 13 && TID_RE.test(str); 11 - }; 12 - 13 - export const DID_RE = /^did:([a-z]+):([a-zA-Z0-9._:%-]*[a-zA-Z0-9._-])$/; 14 - 15 - export const is_did = (str: string): boolean => { 16 - return str.length >= 7 && str.length <= 2048 && DID_RE.test(str); 17 - }; 18 - 19 - export const HANDLE_RE = 20 - /^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/; 21 - 22 - export const is_handle = (str: string): boolean => { 23 - return str.length >= 3 && str.length <= 253 && HANDLE_RE.test(str); 24 - }; 25 - 26 - export const is_at_identifier = (str: string): boolean => { 27 - return is_did(str) || is_handle(str); 28 - };
-10
packages/svelte-site/src/main.ts
··· 1 - import { mount } from 'svelte'; 2 - 3 - import './styles/normalize.css'; 4 - import 'bluesky-post-embed/themes/light.css'; 5 - 6 - import App from './App.svelte'; 7 - 8 - mount(App, { 9 - target: document.getElementById('app')!, 10 - });
-199
packages/svelte-site/src/styles/normalize.css
··· 1 - /*! modern-normalize v3.0.1 | MIT License | https://github.com/sindresorhus/modern-normalize */ 2 - 3 - /* 4 - Document 5 - ======== 6 - */ 7 - 8 - /** 9 - Use a better box model (opinionated). 10 - */ 11 - 12 - *, 13 - ::before, 14 - ::after { 15 - box-sizing: border-box; 16 - } 17 - 18 - html { 19 - line-height: 1.15; /* 1. Correct the line height in all browsers. */ 20 - /* Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3) */ 21 - font-family: 'Inter', 'Roboto', ui-sans-serif, sans-serif, 'Noto Color Emoji', 'Twemoji Mozilla'; 22 - -webkit-text-size-adjust: 100%; /* 2. Prevent adjustments of font size after orientation changes in iOS. */ 23 - tab-size: 4; /* 3. Use a more readable tab size (opinionated). */ 24 - } 25 - 26 - /* 27 - Sections 28 - ======== 29 - */ 30 - 31 - body { 32 - margin: 0; /* Remove the margin in all browsers. */ 33 - } 34 - 35 - /* 36 - Text-level semantics 37 - ==================== 38 - */ 39 - 40 - /** 41 - Add the correct font weight in Chrome and Safari. 42 - */ 43 - 44 - b, 45 - strong { 46 - font-weight: bolder; 47 - } 48 - 49 - /** 50 - 1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3) 51 - 2. Correct the odd 'em' font sizing in all browsers. 52 - */ 53 - 54 - code, 55 - kbd, 56 - samp, 57 - pre { 58 - font-size: 1em; /* 2 */ 59 - font-family: 'JetBrains Mono NL', ui-monospace, monospace; /* 1 */ 60 - } 61 - 62 - /** 63 - Add the correct font size in all browsers. 64 - */ 65 - 66 - small { 67 - font-size: 80%; 68 - } 69 - 70 - /** 71 - Prevent 'sub' and 'sup' elements from affecting the line height in all browsers. 72 - */ 73 - 74 - sub, 75 - sup { 76 - position: relative; 77 - vertical-align: baseline; 78 - font-size: 75%; 79 - line-height: 0; 80 - } 81 - 82 - sub { 83 - bottom: -0.25em; 84 - } 85 - 86 - sup { 87 - top: -0.5em; 88 - } 89 - 90 - /* 91 - Tabular data 92 - ============ 93 - */ 94 - 95 - /** 96 - Correct table border color inheritance in Chrome and Safari. (https://issues.chromium.org/issues/40615503, https://bugs.webkit.org/show_bug.cgi?id=195016) 97 - */ 98 - 99 - table { 100 - border-color: currentcolor; 101 - } 102 - 103 - /* 104 - Forms 105 - ===== 106 - */ 107 - 108 - /** 109 - 1. Change the font styles in all browsers. 110 - 2. Remove the margin in Firefox and Safari. 111 - */ 112 - 113 - button, 114 - input, 115 - optgroup, 116 - select, 117 - textarea { 118 - margin: 0; /* 2 */ 119 - font-size: 100%; /* 1 */ 120 - line-height: 1.15; /* 1 */ 121 - font-family: inherit; /* 1 */ 122 - } 123 - 124 - /** 125 - Correct the inability to style clickable types in iOS and Safari. 126 - */ 127 - 128 - button, 129 - [type='button'], 130 - [type='reset'], 131 - [type='submit'] { 132 - -webkit-appearance: button; 133 - } 134 - 135 - /** 136 - Remove the padding so developers are not caught out when they zero out 'fieldset' elements in all browsers. 137 - */ 138 - 139 - legend { 140 - padding: 0; 141 - } 142 - 143 - /** 144 - Add the correct vertical alignment in Chrome and Firefox. 145 - */ 146 - 147 - progress { 148 - vertical-align: baseline; 149 - } 150 - 151 - /** 152 - Correct the cursor style of increment and decrement buttons in Safari. 153 - */ 154 - 155 - ::-webkit-inner-spin-button, 156 - ::-webkit-outer-spin-button { 157 - height: auto; 158 - } 159 - 160 - /** 161 - 1. Correct the odd appearance in Chrome and Safari. 162 - 2. Correct the outline style in Safari. 163 - */ 164 - 165 - [type='search'] { 166 - -webkit-appearance: textfield; /* 1 */ 167 - outline-offset: -2px; /* 2 */ 168 - } 169 - 170 - /** 171 - Remove the inner padding in Chrome and Safari on macOS. 172 - */ 173 - 174 - ::-webkit-search-decoration { 175 - -webkit-appearance: none; 176 - } 177 - 178 - /** 179 - 1. Correct the inability to style clickable types in iOS and Safari. 180 - 2. Change font properties to 'inherit' in Safari. 181 - */ 182 - 183 - ::-webkit-file-upload-button { 184 - -webkit-appearance: button; /* 1 */ 185 - font: inherit; /* 2 */ 186 - } 187 - 188 - /* 189 - Interactive 190 - =========== 191 - */ 192 - 193 - /* 194 - Add the correct display in Chrome and Safari. 195 - */ 196 - 197 - summary { 198 - display: list-item; 199 - }
-2
packages/svelte-site/src/vite-env.d.ts
··· 1 - /// <reference types="svelte" /> 2 - /// <reference types="vite/client" />
-7
packages/svelte-site/svelte.config.js
··· 1 - import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; 2 - 3 - export default { 4 - // Consult https://svelte.dev/docs#compile-time-svelte-preprocess 5 - // for more information about preprocessors 6 - preprocess: vitePreprocess(), 7 - };
-21
packages/svelte-site/tsconfig.json
··· 1 - { 2 - "extends": "@tsconfig/svelte/tsconfig.json", 3 - "compilerOptions": { 4 - "target": "ESNext", 5 - "useDefineForClassFields": true, 6 - "module": "ESNext", 7 - "resolveJsonModule": true, 8 - /** 9 - * Typecheck JS in `.svelte` and `.js` files by default. 10 - * Disable checkJs if you'd like to use dynamic types in JS. 11 - * Note that setting allowJs false does not prevent the use 12 - * of JS in `.svelte` files. 13 - */ 14 - "allowJs": true, 15 - "checkJs": true, 16 - "isolatedModules": true, 17 - "moduleDetection": "force", 18 - }, 19 - "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"], 20 - "references": [{ "path": "./tsconfig.node.json" }], 21 - }
-13
packages/svelte-site/tsconfig.node.json
··· 1 - { 2 - "compilerOptions": { 3 - "composite": true, 4 - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 5 - "skipLibCheck": true, 6 - "module": "ESNext", 7 - "moduleResolution": "bundler", 8 - "strict": true, 9 - "noEmit": true, 10 - "noUncheckedSideEffectImports": true, 11 - }, 12 - "include": ["vite.config.ts"], 13 - }
-15
packages/svelte-site/vite.config.ts
··· 1 - import { defineConfig } from 'vite'; 2 - import { svelte } from '@sveltejs/vite-plugin-svelte'; 3 - 4 - // https://vite.dev/config/ 5 - export default defineConfig({ 6 - base: './', 7 - build: { 8 - target: 'esnext', 9 - minify: 'terser', 10 - }, 11 - esbuild: { 12 - target: 'esnext', 13 - }, 14 - plugins: [svelte()], 15 - });
-1041
patches/svelte.patch
··· 1 - diff --git a/src/compiler/phases/3-transform/server/visitors/AwaitBlock.js b/src/compiler/phases/3-transform/server/visitors/AwaitBlock.js 2 - index b8d2e421440a0f8e5b12c9cb55ed65ab0f5e7a8a..76bb16136e17cb010069eb7fd4d84cb600ad138c 100644 3 - --- a/src/compiler/phases/3-transform/server/visitors/AwaitBlock.js 4 - +++ b/src/compiler/phases/3-transform/server/visitors/AwaitBlock.js 5 - @@ -33,5 +33,5 @@ export function AwaitBlock(node, context) { 6 - ); 7 - } 8 - 9 - - context.state.template.push(statement, block_close); 10 - + context.state.template.push(statement); 11 - } 12 - diff --git a/src/compiler/phases/3-transform/server/visitors/EachBlock.js b/src/compiler/phases/3-transform/server/visitors/EachBlock.js 13 - index 3c0a8c167696960efa186179da60c47eca0db2e2..8e96d467f6f20af90226ddb16db383e4e3be70ed 100644 14 - --- a/src/compiler/phases/3-transform/server/visitors/EachBlock.js 15 - +++ b/src/compiler/phases/3-transform/server/visitors/EachBlock.js 16 - @@ -47,21 +47,16 @@ export function EachBlock(node, context) { 17 - ); 18 - 19 - if (node.fallback) { 20 - - const open = b.stmt(b.call(b.id('$$renderer.push'), block_open)); 21 - - 22 - const fallback = /** @type {BlockStatement} */ (context.visit(node.fallback)); 23 - 24 - - fallback.body.unshift(b.stmt(b.call(b.id('$$renderer.push'), block_open_else))); 25 - - 26 - block.body.push( 27 - b.if( 28 - b.binary('!==', b.member(array_id, 'length'), b.literal(0)), 29 - - b.block([open, for_loop]), 30 - + b.block([for_loop]), 31 - fallback 32 - ) 33 - ); 34 - } else { 35 - - state.template.push(block_open); 36 - block.body.push(for_loop); 37 - } 38 - 39 - @@ -71,10 +66,9 @@ export function EachBlock(node, context) { 40 - block, 41 - node.metadata.expression.blockers(), 42 - node.metadata.expression.has_await 43 - - ), 44 - - block_close 45 - + ) 46 - ); 47 - } else { 48 - - state.template.push(...block.body, block_close); 49 - + state.template.push(...block.body); 50 - } 51 - } 52 - diff --git a/src/compiler/phases/3-transform/server/visitors/Fragment.js b/src/compiler/phases/3-transform/server/visitors/Fragment.js 53 - index ef5bd985ae5d6bcae838a58f68145fd070b73179..bdc556ee8547d4bfccdee0e6c10260a6f9769fba 100644 54 - --- a/src/compiler/phases/3-transform/server/visitors/Fragment.js 55 - +++ b/src/compiler/phases/3-transform/server/visitors/Fragment.js 56 - @@ -36,11 +36,6 @@ export function Fragment(node, context) { 57 - context.visit(node, state); 58 - } 59 - 60 - - if (is_text_first) { 61 - - // insert `<!---->` to prevent this from being glued to the previous fragment 62 - - state.template.push(empty_comment); 63 - - } 64 - - 65 - process_children(trimmed, { ...context, state }); 66 - 67 - if (state.async_consts && state.async_consts.thunks.length > 0) { 68 - diff --git a/src/compiler/phases/3-transform/server/visitors/IfBlock.js b/src/compiler/phases/3-transform/server/visitors/IfBlock.js 69 - index e8418343be9b2fcba39add8762f5139e37cc7e11..3fccb04a180be2e499c2d71e3b6ac250bc7c30b6 100644 70 - --- a/src/compiler/phases/3-transform/server/visitors/IfBlock.js 71 - +++ b/src/compiler/phases/3-transform/server/visitors/IfBlock.js 72 - @@ -16,10 +16,6 @@ export function IfBlock(node, context) { 73 - ? /** @type {BlockStatement} */ (context.visit(node.alternate)) 74 - : b.block([]); 75 - 76 - - consequent.body.unshift(b.stmt(b.call(b.id('$$renderer.push'), block_open))); 77 - - 78 - - alternate.body.unshift(b.stmt(b.call(b.id('$$renderer.push'), block_open_else))); 79 - - 80 - /** @type {Statement} */ 81 - let statement = b.if(test, consequent, alternate); 82 - 83 - @@ -35,5 +31,5 @@ export function IfBlock(node, context) { 84 - ); 85 - } 86 - 87 - - context.state.template.push(statement, block_close); 88 - + context.state.template.push(statement); 89 - } 90 - diff --git a/src/compiler/phases/3-transform/server/visitors/KeyBlock.js b/src/compiler/phases/3-transform/server/visitors/KeyBlock.js 91 - index 1396aa8fada3c5ccbc469a9983af646765bd35e2..02906b5eda4b4a7c2d90243a9d2e28bca606f4d9 100644 92 - --- a/src/compiler/phases/3-transform/server/visitors/KeyBlock.js 93 - +++ b/src/compiler/phases/3-transform/server/visitors/KeyBlock.js 94 - @@ -8,15 +8,7 @@ import { block_close, block_open, empty_comment } from './shared/utils.js'; 95 - * @param {ComponentContext} context 96 - */ 97 - export function KeyBlock(node, context) { 98 - - const is_async = node.metadata.expression.is_async(); 99 - - 100 - - if (is_async) context.state.template.push(block_open); 101 - - 102 - context.state.template.push( 103 - - empty_comment, 104 - /** @type {BlockStatement} */ (context.visit(node.fragment)), 105 - - empty_comment 106 - ); 107 - - 108 - - if (is_async) context.state.template.push(block_close); 109 - } 110 - diff --git a/src/compiler/phases/3-transform/server/visitors/RenderTag.js b/src/compiler/phases/3-transform/server/visitors/RenderTag.js 111 - index 6d7cef0d95a943d6251101289a821537b259162e..9b4576a8e571aed73046e84ebfa47c276eef7439 100644 112 - --- a/src/compiler/phases/3-transform/server/visitors/RenderTag.js 113 - +++ b/src/compiler/phases/3-transform/server/visitors/RenderTag.js 114 - @@ -44,8 +44,4 @@ export function RenderTag(node, context) { 115 - } 116 - 117 - context.state.template.push(statement); 118 - - 119 - - if (!context.state.skip_hydration_boundaries) { 120 - - context.state.template.push(empty_comment); 121 - - } 122 - } 123 - diff --git a/src/compiler/phases/3-transform/server/visitors/SlotElement.js b/src/compiler/phases/3-transform/server/visitors/SlotElement.js 124 - index d0f8e25d021a70589c6fd191139438a1a95bc45c..4455b964948500ab0f8e8468e7f7fd74139f1d1c 100644 125 - --- a/src/compiler/phases/3-transform/server/visitors/SlotElement.js 126 - +++ b/src/compiler/phases/3-transform/server/visitors/SlotElement.js 127 - @@ -73,5 +73,5 @@ export function SlotElement(node, context) { 128 - ) 129 - : b.stmt(slot); 130 - 131 - - context.state.template.push(block_open, statement, block_close); 132 - + context.state.template.push(statement); 133 - } 134 - diff --git a/src/compiler/phases/3-transform/server/visitors/SvelteBoundary.js b/src/compiler/phases/3-transform/server/visitors/SvelteBoundary.js 135 - index 8a30e765c23008f35ba7a5e43d3c0905f309f555..b5f66aea25087751a864ce515f5f021794ce3d01 100644 136 - --- a/src/compiler/phases/3-transform/server/visitors/SvelteBoundary.js 137 - +++ b/src/compiler/phases/3-transform/server/visitors/SvelteBoundary.js 138 - @@ -45,8 +45,8 @@ export function SvelteBoundary(node, context) { 139 - context.state.template.push( 140 - b.if( 141 - callee, 142 - - b.block(build_template([block_open_else, b.stmt(pending), block_close])), 143 - - b.block(build_template([block_open, block, block_close])) 144 - + b.block(build_template([b.stmt(pending)])), 145 - + b.block(build_template([block])) 146 - ) 147 - ); 148 - } else { 149 - @@ -62,10 +62,10 @@ export function SvelteBoundary(node, context) { 150 - b.id('$$renderer') 151 - ) 152 - : /** @type {BlockStatement} */ (context.visit(pending_snippet.body)); 153 - - context.state.template.push(block_open_else, pending, block_close); 154 - + context.state.template.push(pending); 155 - } 156 - } else { 157 - const block = /** @type {BlockStatement} */ (context.visit(node.fragment)); 158 - - context.state.template.push(block_open, block, block_close); 159 - + context.state.template.push(block); 160 - } 161 - } 162 - diff --git a/src/compiler/phases/3-transform/server/visitors/shared/component.js b/src/compiler/phases/3-transform/server/visitors/shared/component.js 163 - index a90b5e41dfb2e746a12c2dbd5f149c9fbcac5d54..846edda2d005f1b1abbfa64029ae90e12f2a2acc 100644 164 - --- a/src/compiler/phases/3-transform/server/visitors/shared/component.js 165 - +++ b/src/compiler/phases/3-transform/server/visitors/shared/component.js 166 - @@ -335,26 +335,13 @@ export function build_inline_component(node, expression, context) { 167 - statement = create_async_block( 168 - b.block([ 169 - optimiser.apply(), 170 - - dynamic && custom_css_props.length === 0 171 - - ? b.stmt(b.call('$$renderer.push', empty_comment)) 172 - - : b.empty, 173 - + b.empty, 174 - statement 175 - ]), 176 - optimiser.blockers(), 177 - optimiser.has_await 178 - ); 179 - - } else if (dynamic && custom_css_props.length === 0) { 180 - - context.state.template.push(empty_comment); 181 - } 182 - 183 - context.state.template.push(statement); 184 - - 185 - - if ( 186 - - !is_async && 187 - - !context.state.skip_hydration_boundaries && 188 - - custom_css_props.length === 0 && 189 - - optimiser.expressions.length === 0 190 - - ) { 191 - - context.state.template.push(empty_comment); 192 - - } 193 - } 194 - diff --git a/src/compiler/phases/3-transform/server/visitors/shared/utils.js b/src/compiler/phases/3-transform/server/visitors/shared/utils.js 195 - index 4736a7c5daf27c6c2dd7c8f0e5136d668f178a95..b2e94a6f257614ed9e2e85f3ff77fa4ed9e3debd 100644 196 - --- a/src/compiler/phases/3-transform/server/visitors/shared/utils.js 197 - +++ b/src/compiler/phases/3-transform/server/visitors/shared/utils.js 198 - @@ -116,6 +116,12 @@ export function build_template(template) { 199 - const statements = []; 200 - 201 - const flush = () => { 202 - + // Skip empty pushes 203 - + if (expressions.length === 0 && strings.every((s) => s === '')) { 204 - + strings = []; 205 - + return; 206 - + } 207 - + 208 - statements.push( 209 - b.stmt( 210 - b.call( 211 - @@ -326,9 +332,11 @@ export function create_push(expression, metadata, needs_hydration_markers = fals 212 - * @returns {Statement} 213 - */ 214 - export function call_component_renderer(body, component_fn_id) { 215 - - return b.stmt( 216 - - b.call('$$renderer.component', b.arrow([b.id('$$renderer')], body, false), component_fn_id) 217 - - ); 218 - + // Just emit the body directly - no component() wrapper needed for sync rendering 219 - + if (body.type === 'BlockStatement') { 220 - + return body; 221 - + } 222 - + return b.stmt(body); 223 - } 224 - 225 - /** 226 - diff --git a/src/internal/server/index.js b/src/internal/server/index.js 227 - index c0dbdbda14f6f6c98d47686e275f91034c1eaa6b..13b18b1625d48820f9960d473a8d0c1d07757f3f 100644 228 - --- a/src/internal/server/index.js 229 - +++ b/src/internal/server/index.js 230 - @@ -17,7 +17,7 @@ import { DEV } from 'esm-env'; 231 - import { EMPTY_COMMENT, BLOCK_CLOSE, BLOCK_OPEN, BLOCK_OPEN_ELSE } from './hydration.js'; 232 - import { validate_store } from '../shared/validate.js'; 233 - import { is_boolean_attribute, is_raw_text_element, is_void } from '../../utils.js'; 234 - -import { Renderer } from './renderer.js'; 235 - +export { render } from './renderer.js'; 236 - 237 - // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 238 - // https://infra.spec.whatwg.org/#noncharacter 239 - @@ -51,17 +51,6 @@ export function element(renderer, tag, attributes_fn = noop, children_fn = noop) 240 - renderer.push('<!---->'); 241 - } 242 - 243 - -/** 244 - - * Only available on the server and when compiling with the `server` option. 245 - - * Takes a component and returns an object with `body` and `head` properties on it, which you can use to populate the HTML when server-rendering your app. 246 - - * @template {Record<string, any>} Props 247 - - * @param {Component<Props> | ComponentType<SvelteComponent<Props>>} component 248 - - * @param {{ props?: Omit<Props, '$$slots' | '$$events'>; context?: Map<any, any>; idPrefix?: string }} [options] 249 - - * @returns {RenderOutput} 250 - - */ 251 - -export function render(component, options = {}) { 252 - - return Renderer.render(/** @type {Component<Props>} */ (component), options); 253 - -} 254 - 255 - /** 256 - * @param {string} hash 257 - @@ -411,12 +400,7 @@ export { await_block as await }; 258 - 259 - /** @param {any} array_like_or_iterator */ 260 - export function ensure_array_like(array_like_or_iterator) { 261 - - if (array_like_or_iterator) { 262 - - return array_like_or_iterator.length !== undefined 263 - - ? array_like_or_iterator 264 - - : Array.from(array_like_or_iterator); 265 - - } 266 - - return []; 267 - + return array_like_or_iterator; 268 - } 269 - 270 - /** 271 - diff --git a/src/internal/server/renderer.js b/src/internal/server/renderer.js 272 - index 0cfb1a7a93518729d04c26214140eaab29de4870..c36c956d1edff831a5d00f214184b882f96e0985 100644 273 - --- a/src/internal/server/renderer.js 274 - +++ b/src/internal/server/renderer.js 275 - @@ -1,741 +1,18 @@ 276 - /** @import { Component } from 'svelte' */ 277 - -/** @import { HydratableContext, RenderOutput, SSRContext, SyncRenderOutput } from './types.js' */ 278 - -/** @import { MaybePromise } from '#shared' */ 279 - -import { async_mode_flag } from '../flags/index.js'; 280 - -import { abort } from './abort-signal.js'; 281 - -import { pop, push, set_ssr_context, ssr_context, save } from './context.js'; 282 - -import * as e from './errors.js'; 283 - -import * as w from './warnings.js'; 284 - -import { BLOCK_CLOSE, BLOCK_OPEN } from './hydration.js'; 285 - -import { attributes } from './index.js'; 286 - -import { get_render_context, with_render_context, init_render_context } from './render-context.js'; 287 - -import { DEV } from 'esm-env'; 288 - - 289 - -/** @typedef {'head' | 'body'} RendererType */ 290 - -/** @typedef {{ [key in RendererType]: string }} AccumulatedContent */ 291 - - 292 - -/** 293 - - * @typedef {string | Renderer} RendererItem 294 - - */ 295 - +/** @import { RenderOutput } from './types.js' */ 296 - 297 - /** 298 - - * Renderers are basically a tree of `string | Renderer`s, where each `Renderer` in the tree represents 299 - - * work that may or may not have completed. A renderer can be {@link collect}ed to aggregate the 300 - - * content from itself and all of its children, but this will throw if any of the children are 301 - - * performing asynchronous work. To asynchronously collect a renderer, just `await` it. 302 - - * 303 - - * The `string` values within a renderer are always associated with the {@link type} of that renderer. To switch types, 304 - - * call {@link child} with a different `type` argument. 305 - + * @template {Record<string, any>} Props 306 - + * @param {Component<Props>} component 307 - + * @param {{ props?: Omit<Props, '$$slots' | '$$events'> }} [options] 308 - + * @returns {RenderOutput} 309 - */ 310 - -export class Renderer { 311 - - /** 312 - - * The contents of the renderer. 313 - - * @type {RendererItem[]} 314 - - */ 315 - - #out = []; 316 - - 317 - - /** 318 - - * Any `onDestroy` callbacks registered during execution of this renderer. 319 - - * @type {(() => void)[] | undefined} 320 - - */ 321 - - #on_destroy = undefined; 322 - - 323 - - /** 324 - - * Whether this renderer is a component body. 325 - - * @type {boolean} 326 - - */ 327 - - #is_component_body = false; 328 - - 329 - - /** 330 - - * The type of string content that this renderer is accumulating. 331 - - * @type {RendererType} 332 - - */ 333 - - type; 334 - - 335 - - /** @type {Renderer | undefined} */ 336 - - #parent; 337 - - 338 - - /** 339 - - * Asynchronous work associated with this renderer 340 - - * @type {Promise<void> | undefined} 341 - - */ 342 - - promise = undefined; 343 - - 344 - - /** 345 - - * State which is associated with the content tree as a whole. 346 - - * It will be re-exposed, uncopied, on all children. 347 - - * @type {SSRState} 348 - - * @readonly 349 - - */ 350 - - global; 351 - - 352 - - /** 353 - - * State that is local to the branch it is declared in. 354 - - * It will be shallow-copied to all children. 355 - - * 356 - - * @type {{ select_value: string | undefined }} 357 - - */ 358 - - local; 359 - - 360 - - /** 361 - - * @param {SSRState} global 362 - - * @param {Renderer | undefined} [parent] 363 - - */ 364 - - constructor(global, parent) { 365 - - this.#parent = parent; 366 - - 367 - - this.global = global; 368 - - this.local = parent ? { ...parent.local } : { select_value: undefined }; 369 - - this.type = parent ? parent.type : 'body'; 370 - - } 371 - - 372 - - /** 373 - - * @param {(renderer: Renderer) => void} fn 374 - - */ 375 - - head(fn) { 376 - - const head = new Renderer(this.global, this); 377 - - head.type = 'head'; 378 - - 379 - - this.#out.push(head); 380 - - head.child(fn); 381 - - } 382 - - 383 - - /** 384 - - * @param {Array<Promise<void>>} blockers 385 - - * @param {(renderer: Renderer) => void} fn 386 - - */ 387 - - async_block(blockers, fn) { 388 - - this.#out.push(BLOCK_OPEN); 389 - - this.async(blockers, fn); 390 - - this.#out.push(BLOCK_CLOSE); 391 - - } 392 - - 393 - - /** 394 - - * @param {Array<Promise<void>>} blockers 395 - - * @param {(renderer: Renderer) => void} fn 396 - - */ 397 - - async(blockers, fn) { 398 - - let callback = fn; 399 - - 400 - - if (blockers.length > 0) { 401 - - const context = ssr_context; 402 - - 403 - - callback = (renderer) => { 404 - - return Promise.all(blockers).then(() => { 405 - - const previous_context = ssr_context; 406 - - 407 - - try { 408 - - set_ssr_context(context); 409 - - return fn(renderer); 410 - - } finally { 411 - - set_ssr_context(previous_context); 412 - - } 413 - - }); 414 - - }; 415 - - } 416 - - 417 - - this.child(callback); 418 - - } 419 - - 420 - - /** 421 - - * @param {Array<() => void>} thunks 422 - - */ 423 - - run(thunks) { 424 - - const context = ssr_context; 425 - - 426 - - let promise = Promise.resolve(thunks[0]()); 427 - - const promises = [promise]; 428 - - 429 - - for (const fn of thunks.slice(1)) { 430 - - promise = promise.then(() => { 431 - - const previous_context = ssr_context; 432 - - set_ssr_context(context); 433 - - 434 - - try { 435 - - return fn(); 436 - - } finally { 437 - - set_ssr_context(previous_context); 438 - - } 439 - - }); 440 - - 441 - - promises.push(promise); 442 - - } 443 - - 444 - - return promises; 445 - - } 446 - - 447 - - /** 448 - - * Create a child renderer. The child renderer inherits the state from the parent, 449 - - * but has its own content. 450 - - * @param {(renderer: Renderer) => MaybePromise<void>} fn 451 - - */ 452 - - child(fn) { 453 - - const child = new Renderer(this.global, this); 454 - - this.#out.push(child); 455 - - 456 - - const parent = ssr_context; 457 - - 458 - - set_ssr_context({ 459 - - ...ssr_context, 460 - - p: parent, 461 - - c: null, 462 - - r: child 463 - - }); 464 - - 465 - - const result = fn(child); 466 - - 467 - - set_ssr_context(parent); 468 - - 469 - - if (result instanceof Promise) { 470 - - if (child.global.mode === 'sync') { 471 - - e.await_invalid(); 472 - - } 473 - - // just to avoid unhandled promise rejections -- we'll end up throwing in `collect_async` if something fails 474 - - result.catch(() => {}); 475 - - child.promise = result; 476 - - } 477 - - 478 - - return child; 479 - - } 480 - - 481 - - /** 482 - - * Create a component renderer. The component renderer inherits the state from the parent, 483 - - * but has its own content. It is treated as an ordering boundary for ondestroy callbacks. 484 - - * @param {(renderer: Renderer) => MaybePromise<void>} fn 485 - - * @param {Function} [component_fn] 486 - - * @returns {void} 487 - - */ 488 - - component(fn, component_fn) { 489 - - push(component_fn); 490 - - const child = this.child(fn); 491 - - child.#is_component_body = true; 492 - - pop(); 493 - - } 494 - - 495 - - /** 496 - - * @param {Record<string, any>} attrs 497 - - * @param {(renderer: Renderer) => void} fn 498 - - * @param {string | undefined} [css_hash] 499 - - * @param {Record<string, boolean> | undefined} [classes] 500 - - * @param {Record<string, string> | undefined} [styles] 501 - - * @param {number | undefined} [flags] 502 - - * @returns {void} 503 - - */ 504 - - select(attrs, fn, css_hash, classes, styles, flags) { 505 - - const { value, ...select_attrs } = attrs; 506 - - 507 - - this.push(`<select${attributes(select_attrs, css_hash, classes, styles, flags)}>`); 508 - - this.child((renderer) => { 509 - - renderer.local.select_value = value; 510 - - fn(renderer); 511 - - }); 512 - - this.push('</select>'); 513 - - } 514 - - 515 - - /** 516 - - * @param {Record<string, any>} attrs 517 - - * @param {string | number | boolean | ((renderer: Renderer) => void)} body 518 - - * @param {string | undefined} [css_hash] 519 - - * @param {Record<string, boolean> | undefined} [classes] 520 - - * @param {Record<string, string> | undefined} [styles] 521 - - * @param {number | undefined} [flags] 522 - - */ 523 - - option(attrs, body, css_hash, classes, styles, flags) { 524 - - this.#out.push(`<option${attributes(attrs, css_hash, classes, styles, flags)}`); 525 - - 526 - - /** 527 - - * @param {Renderer} renderer 528 - - * @param {any} value 529 - - * @param {{ head?: string, body: any }} content 530 - - */ 531 - - const close = (renderer, value, { head, body }) => { 532 - - if ('value' in attrs) { 533 - - value = attrs.value; 534 - - } 535 - - 536 - - if (value === this.local.select_value) { 537 - - renderer.#out.push(' selected'); 538 - - } 539 - - 540 - - renderer.#out.push(`>${body}</option>`); 541 - - 542 - - // super edge case, but may as well handle it 543 - - if (head) { 544 - - renderer.head((child) => child.push(head)); 545 - - } 546 - - }; 547 - - 548 - - if (typeof body === 'function') { 549 - - this.child((renderer) => { 550 - - const r = new Renderer(this.global, this); 551 - - body(r); 552 - - 553 - - if (this.global.mode === 'async') { 554 - - return r.#collect_content_async().then((content) => { 555 - - close(renderer, content.body.replaceAll('<!---->', ''), content); 556 - - }); 557 - - } else { 558 - - const content = r.#collect_content(); 559 - - close(renderer, content.body.replaceAll('<!---->', ''), content); 560 - - } 561 - - }); 562 - - } else { 563 - - close(this, body, { body }); 564 - - } 565 - - } 566 - - 567 - - /** 568 - - * @param {(renderer: Renderer) => void} fn 569 - - */ 570 - - title(fn) { 571 - - const path = this.get_path(); 572 - - 573 - - /** @param {string} head */ 574 - - const close = (head) => { 575 - - this.global.set_title(head, path); 576 - - }; 577 - - 578 - - this.child((renderer) => { 579 - - const r = new Renderer(renderer.global, renderer); 580 - - fn(r); 581 - - 582 - - if (renderer.global.mode === 'async') { 583 - - return r.#collect_content_async().then((content) => { 584 - - close(content.head); 585 - - }); 586 - - } else { 587 - - const content = r.#collect_content(); 588 - - close(content.head); 589 - - } 590 - - }); 591 - - } 592 - - 593 - - /** 594 - - * @param {string | (() => Promise<string>)} content 595 - - */ 596 - - push(content) { 597 - - if (typeof content === 'function') { 598 - - this.child(async (renderer) => renderer.push(await content())); 599 - - } else { 600 - - this.#out.push(content); 601 - - } 602 - - } 603 - - 604 - - /** 605 - - * @param {() => void} fn 606 - - */ 607 - - on_destroy(fn) { 608 - - (this.#on_destroy ??= []).push(fn); 609 - - } 610 - - 611 - - /** 612 - - * @returns {number[]} 613 - - */ 614 - - get_path() { 615 - - return this.#parent ? [...this.#parent.get_path(), this.#parent.#out.indexOf(this)] : []; 616 - - } 617 - - 618 - - /** 619 - - * @deprecated this is needed for legacy component bindings 620 - - */ 621 - - copy() { 622 - - const copy = new Renderer(this.global, this.#parent); 623 - - copy.#out = this.#out.map((item) => (item instanceof Renderer ? item.copy() : item)); 624 - - copy.promise = this.promise; 625 - - return copy; 626 - - } 627 - - 628 - - /** 629 - - * @param {Renderer} other 630 - - * @deprecated this is needed for legacy component bindings 631 - - */ 632 - - subsume(other) { 633 - - if (this.global.mode !== other.global.mode) { 634 - - throw new Error( 635 - - "invariant: A renderer cannot switch modes. If you're seeing this, there's a compiler bug. File an issue!" 636 - - ); 637 - - } 638 - - 639 - - this.local = other.local; 640 - - this.#out = other.#out.map((item) => { 641 - - if (item instanceof Renderer) { 642 - - item.subsume(item); 643 - - } 644 - - return item; 645 - - }); 646 - - this.promise = other.promise; 647 - - this.type = other.type; 648 - - } 649 - - 650 - - get length() { 651 - - return this.#out.length; 652 - - } 653 - - 654 - - /** 655 - - * Only available on the server and when compiling with the `server` option. 656 - - * Takes a component and returns an object with `body` and `head` properties on it, which you can use to populate the HTML when server-rendering your app. 657 - - * @template {Record<string, any>} Props 658 - - * @param {Component<Props>} component 659 - - * @param {{ props?: Omit<Props, '$$slots' | '$$events'>; context?: Map<any, any>; idPrefix?: string }} [options] 660 - - * @returns {RenderOutput} 661 - - */ 662 - - static render(component, options = {}) { 663 - - /** @type {AccumulatedContent | undefined} */ 664 - - let sync; 665 - - /** @type {Promise<AccumulatedContent> | undefined} */ 666 - - let async; 667 - - 668 - - const result = /** @type {RenderOutput} */ ({}); 669 - - // making these properties non-enumerable so that console.logging 670 - - // doesn't trigger a sync render 671 - - Object.defineProperties(result, { 672 - - html: { 673 - - get: () => { 674 - - return (sync ??= Renderer.#render(component, options)).body; 675 - - } 676 - - }, 677 - - head: { 678 - - get: () => { 679 - - return (sync ??= Renderer.#render(component, options)).head; 680 - - } 681 - - }, 682 - - body: { 683 - - get: () => { 684 - - return (sync ??= Renderer.#render(component, options)).body; 685 - - } 686 - - }, 687 - - then: { 688 - - value: 689 - - /** 690 - - * this is not type-safe, but honestly it's the best I can do right now, and it's a straightforward function. 691 - - * 692 - - * @template TResult1 693 - - * @template [TResult2=never] 694 - - * @param { (value: SyncRenderOutput) => TResult1 } onfulfilled 695 - - * @param { (reason: unknown) => TResult2 } onrejected 696 - - */ 697 - - (onfulfilled, onrejected) => { 698 - - if (!async_mode_flag) { 699 - - const result = (sync ??= Renderer.#render(component, options)); 700 - - const user_result = onfulfilled({ 701 - - head: result.head, 702 - - body: result.body, 703 - - html: result.body 704 - - }); 705 - - return Promise.resolve(user_result); 706 - - } 707 - - async ??= init_render_context().then(() => 708 - - with_render_context(() => Renderer.#render_async(component, options)) 709 - - ); 710 - - return async.then((result) => { 711 - - Object.defineProperty(result, 'html', { 712 - - // eslint-disable-next-line getter-return 713 - - get: () => { 714 - - e.html_deprecated(); 715 - - } 716 - - }); 717 - - return onfulfilled(/** @type {SyncRenderOutput} */ (result)); 718 - - }, onrejected); 719 - - } 720 - - } 721 - - }); 722 - - 723 - - return result; 724 - - } 725 - - 726 - - /** 727 - - * Collect all of the `onDestroy` callbacks registered during rendering. In an async context, this is only safe to call 728 - - * after awaiting `collect_async`. 729 - - * 730 - - * Child renderers are "porous" and don't affect execution order, but component body renderers 731 - - * create ordering boundaries. Within a renderer, callbacks run in order until hitting a component boundary. 732 - - * @returns {Iterable<() => void>} 733 - - */ 734 - - *#collect_on_destroy() { 735 - - for (const component of this.#traverse_components()) { 736 - - yield* component.#collect_ondestroy(); 737 - - } 738 - - } 739 - - 740 - - /** 741 - - * Performs a depth-first search of renderers, yielding the deepest components first, then additional components as we backtrack up the tree. 742 - - * @returns {Iterable<Renderer>} 743 - - */ 744 - - *#traverse_components() { 745 - - for (const child of this.#out) { 746 - - if (typeof child !== 'string') { 747 - - yield* child.#traverse_components(); 748 - - } 749 - - } 750 - - if (this.#is_component_body) { 751 - - yield this; 752 - - } 753 - - } 754 - - 755 - - /** 756 - - * @returns {Iterable<() => void>} 757 - - */ 758 - - *#collect_ondestroy() { 759 - - if (this.#on_destroy) { 760 - - for (const fn of this.#on_destroy) { 761 - - yield fn; 762 - - } 763 - - } 764 - - for (const child of this.#out) { 765 - - if (child instanceof Renderer && !child.#is_component_body) { 766 - - yield* child.#collect_ondestroy(); 767 - - } 768 - - } 769 - - } 770 - - 771 - - /** 772 - - * Render a component. Throws if any of the children are performing asynchronous work. 773 - - * 774 - - * @template {Record<string, any>} Props 775 - - * @param {Component<Props>} component 776 - - * @param {{ props?: Omit<Props, '$$slots' | '$$events'>; context?: Map<any, any>; idPrefix?: string }} options 777 - - * @returns {AccumulatedContent} 778 - - */ 779 - - static #render(component, options) { 780 - - var previous_context = ssr_context; 781 - - try { 782 - - const renderer = Renderer.#open_render('sync', component, options); 783 - - 784 - - const content = renderer.#collect_content(); 785 - - return Renderer.#close_render(content, renderer); 786 - - } finally { 787 - - abort(); 788 - - set_ssr_context(previous_context); 789 - - } 790 - - } 791 - - 792 - - /** 793 - - * Render a component. 794 - - * 795 - - * @template {Record<string, any>} Props 796 - - * @param {Component<Props>} component 797 - - * @param {{ props?: Omit<Props, '$$slots' | '$$events'>; context?: Map<any, any>; idPrefix?: string }} options 798 - - * @returns {Promise<AccumulatedContent>} 799 - - */ 800 - - static async #render_async(component, options) { 801 - - const previous_context = ssr_context; 802 - - 803 - - try { 804 - - const renderer = Renderer.#open_render('async', component, options); 805 - - const content = await renderer.#collect_content_async(); 806 - - const hydratables = await renderer.#collect_hydratables(); 807 - - if (hydratables !== null) { 808 - - content.head = hydratables + content.head; 809 - - } 810 - - return Renderer.#close_render(content, renderer); 811 - - } finally { 812 - - set_ssr_context(previous_context); 813 - - abort(); 814 - - } 815 - - } 816 - - 817 - - /** 818 - - * Collect all of the code from the `out` array and return it as a string, or a promise resolving to a string. 819 - - * @param {AccumulatedContent} content 820 - - * @returns {AccumulatedContent} 821 - - */ 822 - - #collect_content(content = { head: '', body: '' }) { 823 - - for (const item of this.#out) { 824 - - if (typeof item === 'string') { 825 - - content[this.type] += item; 826 - - } else if (item instanceof Renderer) { 827 - - item.#collect_content(content); 828 - - } 829 - - } 830 - - 831 - - return content; 832 - - } 833 - - 834 - - /** 835 - - * Collect all of the code from the `out` array and return it as a string. 836 - - * @param {AccumulatedContent} content 837 - - * @returns {Promise<AccumulatedContent>} 838 - - */ 839 - - async #collect_content_async(content = { head: '', body: '' }) { 840 - - await this.promise; 841 - - 842 - - // no danger to sequentially awaiting stuff in here; all of the work is already kicked off 843 - - for (const item of this.#out) { 844 - - if (typeof item === 'string') { 845 - - content[this.type] += item; 846 - - } else if (item instanceof Renderer) { 847 - - await item.#collect_content_async(content); 848 - - } 849 - - } 850 - - 851 - - return content; 852 - - } 853 - - 854 - - async #collect_hydratables() { 855 - - const ctx = get_render_context().hydratable; 856 - - 857 - - for (const [_, key] of ctx.unresolved_promises) { 858 - - // this is a problem -- it means we've finished the render but we're still waiting on a promise to resolve so we can 859 - - // serialize it, so we're blocking the response on useless content. 860 - - w.unresolved_hydratable(key, ctx.lookup.get(key)?.stack ?? '<missing stack trace>'); 861 - - } 862 - - 863 - - for (const comparison of ctx.comparisons) { 864 - - // these reject if there's a mismatch 865 - - await comparison; 866 - - } 867 - - 868 - - return await Renderer.#hydratable_block(ctx); 869 - - } 870 - - 871 - - /** 872 - - * @template {Record<string, any>} Props 873 - - * @param {'sync' | 'async'} mode 874 - - * @param {import('svelte').Component<Props>} component 875 - - * @param {{ props?: Omit<Props, '$$slots' | '$$events'>; context?: Map<any, any>; idPrefix?: string }} options 876 - - * @returns {Renderer} 877 - - */ 878 - - static #open_render(mode, component, options) { 879 - - const renderer = new Renderer( 880 - - new SSRState(mode, options.idPrefix ? options.idPrefix + '-' : '') 881 - - ); 882 - - 883 - - renderer.push(BLOCK_OPEN); 884 - - 885 - - if (options.context) { 886 - - push(); 887 - - /** @type {SSRContext} */ (ssr_context).c = options.context; 888 - - /** @type {SSRContext} */ (ssr_context).r = renderer; 889 - - } 890 - - 891 - - // @ts-expect-error 892 - - component(renderer, options.props ?? {}); 893 - - 894 - - if (options.context) { 895 - - pop(); 896 - - } 897 - - 898 - - renderer.push(BLOCK_CLOSE); 899 - - 900 - - return renderer; 901 - - } 902 - - 903 - - /** 904 - - * @param {AccumulatedContent} content 905 - - * @param {Renderer} renderer 906 - - */ 907 - - static #close_render(content, renderer) { 908 - - for (const cleanup of renderer.#collect_on_destroy()) { 909 - - cleanup(); 910 - - } 911 - - 912 - - let head = content.head + renderer.global.get_title(); 913 - - let body = content.body; 914 - - 915 - - for (const { hash, code } of renderer.global.css) { 916 - - head += `<style id="${hash}">${code}</style>`; 917 - - } 918 - - 919 - - return { 920 - - head, 921 - - body 922 - - }; 923 - - } 924 - - 925 - - /** 926 - - * @param {HydratableContext} ctx 927 - - */ 928 - - static async #hydratable_block(ctx) { 929 - - if (ctx.lookup.size === 0) { 930 - - return null; 931 - - } 932 - - 933 - - let entries = []; 934 - - let has_promises = false; 935 - - 936 - - for (const [k, v] of ctx.lookup) { 937 - - if (v.promises) { 938 - - has_promises = true; 939 - - for (const p of v.promises) await p; 940 - - } 941 - - 942 - - entries.push(`[${JSON.stringify(k)},${v.serialized}]`); 943 - - } 944 - - 945 - - let prelude = `const h = (window.__svelte ??= {}).h ??= new Map();`; 946 - - 947 - - if (has_promises) { 948 - - prelude = `const r = (v) => Promise.resolve(v); 949 - - ${prelude}`; 950 - - } 951 - - 952 - - // TODO csp -- have discussed but not implemented 953 - - return ` 954 - - <script> 955 - - { 956 - - ${prelude} 957 - - 958 - - for (const [k, v] of [ 959 - - ${entries.join(',\n\t\t\t\t\t')} 960 - - ]) { 961 - - h.set(k, v); 962 - - } 963 - - } 964 - - </script>`; 965 - - } 966 - +function render(component, options = {}) { 967 - + let out = ''; 968 - + const renderer = { push(s) { out += s; } }; 969 - + component(renderer, options.props ?? {}); 970 - + return { body: out }; 971 - } 972 - 973 - -export class SSRState { 974 - - /** @readonly @type {'sync' | 'async'} */ 975 - - mode; 976 - - 977 - - /** @readonly @type {() => string} */ 978 - - uid; 979 - - 980 - - /** @readonly @type {Set<{ hash: string; code: string }>} */ 981 - - css = new Set(); 982 - - 983 - - /** @type {{ path: number[], value: string }} */ 984 - - #title = { path: [], value: '' }; 985 - - 986 - - /** 987 - - * @param {'sync' | 'async'} mode 988 - - * @param {string} [id_prefix] 989 - - */ 990 - - constructor(mode, id_prefix = '') { 991 - - this.mode = mode; 992 - - 993 - - let uid = 1; 994 - - this.uid = () => `${id_prefix}s${uid++}`; 995 - - } 996 - - 997 - - get_title() { 998 - - return this.#title.value; 999 - - } 1000 - - 1001 - - /** 1002 - - * Performs a depth-first (lexicographic) comparison using the path. Rejects sets 1003 - - * from earlier than or equal to the current value. 1004 - - * @param {string} value 1005 - - * @param {number[]} path 1006 - - */ 1007 - - set_title(value, path) { 1008 - - const current = this.#title.path; 1009 - - 1010 - - let i = 0; 1011 - - let l = Math.min(path.length, current.length); 1012 - - 1013 - - // skip identical prefixes - [1, 2, 3, ...] === [1, 2, 3, ...] 1014 - - while (i < l && path[i] === current[i]) i += 1; 1015 - - 1016 - - if (path[i] === undefined) return; 1017 - - 1018 - - // replace title if 1019 - - // - incoming path is longer - [7, 8, 9] > [7, 8] 1020 - - // - incoming path is later - [7, 8, 9] > [7, 8, 8] 1021 - - if (current[i] === undefined || path[i] > current[i]) { 1022 - - this.#title.path = path; 1023 - - this.#title.value = value; 1024 - - } 1025 - - } 1026 - -} 1027 - +export { render }; 1028 - +export const Renderer = { render }; 1029 - diff --git a/src/internal/shared/attributes.js b/src/internal/shared/attributes.js 1030 - index 4ad550e8d612e42d1e719dcbfcbce383bbbbb27f..a12fe17a0efd135bd9fd4f1b1594c059a6d12e54 100644 1031 - --- a/src/internal/shared/attributes.js 1032 - +++ b/src/internal/shared/attributes.js 1033 - @@ -27,7 +27,7 @@ export function attr(name, value, is_boolean = false) { 1034 - is_boolean = true; 1035 - } 1036 - if (value == null || (!value && is_boolean)) return ''; 1037 - - const normalized = (name in replacements && replacements[name].get(value)) || value; 1038 - + const normalized = value; 1039 - const assignment = is_boolean ? '' : `="${escape_html(normalized, true)}"`; 1040 - return ` ${name}${assignment}`; 1041 - }
-3169
pnpm-lock.yaml
··· 1 - lockfileVersion: '9.0' 2 - 3 - settings: 4 - autoInstallPeers: true 5 - excludeLinksFromLockfile: false 6 - 7 - catalogs: 8 - default: 9 - svelte: 10 - specifier: ^5.45.5 11 - version: 5.45.5 12 - 13 - patchedDependencies: 14 - svelte: 15 - hash: 0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd 16 - path: patches/svelte.patch 17 - 18 - importers: 19 - 20 - .: 21 - devDependencies: 22 - '@changesets/cli': 23 - specifier: ^2.29.8 24 - version: 2.29.8(@types/node@24.10.1) 25 - prettier: 26 - specifier: ^3.7.4 27 - version: 3.7.4 28 - prettier-plugin-css-order: 29 - specifier: ^2.1.2 30 - version: 2.1.2(postcss@8.5.6)(prettier@3.7.4) 31 - prettier-plugin-svelte: 32 - specifier: ^3.4.0 33 - version: 3.4.0(prettier@3.7.4)(svelte@5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd)) 34 - typescript: 35 - specifier: ~5.8.3 36 - version: 5.8.3 37 - 38 - packages/bluesky-post-embed: 39 - dependencies: 40 - '@atcute/bluesky': 41 - specifier: ^2.1.1 42 - version: 2.1.1(@atcute/client@3.1.0) 43 - '@atcute/bluesky-richtext-segmenter': 44 - specifier: ^2.0.4 45 - version: 2.0.4 46 - '@atcute/client': 47 - specifier: ^3.1.0 48 - version: 3.1.0 49 - devDependencies: 50 - '@preact/preset-vite': 51 - specifier: ^2.10.2 52 - version: 2.10.2(@babel/core@7.28.5)(preact@10.28.0)(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)) 53 - '@tsconfig/svelte': 54 - specifier: ^5.0.6 55 - version: 5.0.6 56 - '@types/node': 57 - specifier: ^24.10.1 58 - version: 24.10.1 59 - internal: 60 - specifier: workspace:^ 61 - version: link:../internal 62 - preact: 63 - specifier: ^10.28.0 64 - version: 10.28.0 65 - svelte: 66 - specifier: 'catalog:' 67 - version: 5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd) 68 - svelte-check: 69 - specifier: ^4.3.4 70 - version: 4.3.4(picomatch@4.0.3)(svelte@5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd))(typescript@5.8.3) 71 - vite: 72 - specifier: ^7.2.6 73 - version: 7.2.6(@types/node@24.10.1)(terser@5.44.1) 74 - vite-plugin-dts: 75 - specifier: ^4.5.4 76 - version: 4.5.4(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.8.3)(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)) 77 - 78 - packages/bluesky-profile-card-embed: 79 - dependencies: 80 - '@atcute/bluesky': 81 - specifier: ^2.1.1 82 - version: 2.1.1(@atcute/client@3.1.0) 83 - '@atcute/bluesky-richtext-parser': 84 - specifier: ^1.0.7 85 - version: 1.0.7 86 - '@atcute/client': 87 - specifier: ^3.1.0 88 - version: 3.1.0 89 - devDependencies: 90 - '@preact/preset-vite': 91 - specifier: ^2.10.2 92 - version: 2.10.2(@babel/core@7.28.5)(preact@10.28.0)(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)) 93 - '@tsconfig/svelte': 94 - specifier: ^5.0.6 95 - version: 5.0.6 96 - '@types/node': 97 - specifier: ^24.10.1 98 - version: 24.10.1 99 - internal: 100 - specifier: workspace:^ 101 - version: link:../internal 102 - preact: 103 - specifier: ^10.28.0 104 - version: 10.28.0 105 - svelte: 106 - specifier: 'catalog:' 107 - version: 5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd) 108 - svelte-check: 109 - specifier: ^4.3.4 110 - version: 4.3.4(picomatch@4.0.3)(svelte@5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd))(typescript@5.8.3) 111 - vite: 112 - specifier: ^7.2.6 113 - version: 7.2.6(@types/node@24.10.1)(terser@5.44.1) 114 - vite-plugin-dts: 115 - specifier: ^4.5.4 116 - version: 4.5.4(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.8.3)(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)) 117 - 118 - packages/bluesky-profile-feed-embed: 119 - dependencies: 120 - '@atcute/bluesky': 121 - specifier: ^2.1.1 122 - version: 2.1.1(@atcute/client@3.1.0) 123 - '@atcute/bluesky-richtext-segmenter': 124 - specifier: ^2.0.4 125 - version: 2.0.4 126 - '@atcute/client': 127 - specifier: ^3.1.0 128 - version: 3.1.0 129 - devDependencies: 130 - '@tsconfig/svelte': 131 - specifier: ^5.0.6 132 - version: 5.0.6 133 - '@types/node': 134 - specifier: ^24.10.1 135 - version: 24.10.1 136 - internal: 137 - specifier: workspace:^ 138 - version: link:../internal 139 - svelte: 140 - specifier: 'catalog:' 141 - version: 5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd) 142 - svelte-check: 143 - specifier: ^4.3.4 144 - version: 4.3.4(picomatch@4.0.3)(svelte@5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd))(typescript@5.8.3) 145 - vite: 146 - specifier: ^7.2.6 147 - version: 7.2.6(@types/node@24.10.1)(terser@5.44.1) 148 - vite-plugin-dts: 149 - specifier: ^4.5.4 150 - version: 4.5.4(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.8.3)(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)) 151 - 152 - packages/internal: 153 - devDependencies: 154 - '@atcute/bluesky': 155 - specifier: ^2.1.1 156 - version: 2.1.1(@atcute/client@3.1.0) 157 - '@atcute/bluesky-richtext-parser': 158 - specifier: ^1.0.7 159 - version: 1.0.7 160 - '@atcute/bluesky-richtext-segmenter': 161 - specifier: ^2.0.4 162 - version: 2.0.4 163 - '@atcute/client': 164 - specifier: ^3.1.0 165 - version: 3.1.0 166 - '@tsconfig/svelte': 167 - specifier: ^5.0.6 168 - version: 5.0.6 169 - svelte: 170 - specifier: 'catalog:' 171 - version: 5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd) 172 - 173 - packages/svelte-site: 174 - dependencies: 175 - '@atcute/bluesky': 176 - specifier: ^2.1.1 177 - version: 2.1.1(@atcute/client@3.1.0) 178 - '@atcute/client': 179 - specifier: ^3.1.0 180 - version: 3.1.0 181 - bluesky-post-embed: 182 - specifier: workspace:^ 183 - version: link:../bluesky-post-embed 184 - bluesky-profile-card-embed: 185 - specifier: workspace:^ 186 - version: link:../bluesky-profile-card-embed 187 - bluesky-profile-feed-embed: 188 - specifier: workspace:^ 189 - version: link:../bluesky-profile-feed-embed 190 - internal: 191 - specifier: workspace:^ 192 - version: link:../internal 193 - devDependencies: 194 - '@sveltejs/vite-plugin-svelte': 195 - specifier: ^6.2.1 196 - version: 6.2.1(svelte@5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd))(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)) 197 - '@tsconfig/svelte': 198 - specifier: ^5.0.6 199 - version: 5.0.6 200 - svelte: 201 - specifier: ^5.45.5 202 - version: 5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd) 203 - svelte-check: 204 - specifier: ^4.3.4 205 - version: 4.3.4(picomatch@4.0.3)(svelte@5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd))(typescript@5.8.3) 206 - terser: 207 - specifier: ^5.44.1 208 - version: 5.44.1 209 - tslib: 210 - specifier: ^2.8.1 211 - version: 2.8.1 212 - vite: 213 - specifier: ^7.2.6 214 - version: 7.2.6(@types/node@24.10.1)(terser@5.44.1) 215 - 216 - packages: 217 - 218 - '@atcute/atproto@3.1.9': 219 - resolution: {integrity: sha512-DyWwHCTdR4hY2BPNbLXgVmm7lI+fceOwWbE4LXbGvbvVtSn+ejSVFaAv01Ra3kWDha0whsOmbJL8JP0QPpf1+w==} 220 - 221 - '@atcute/bluesky-richtext-parser@1.0.7': 222 - resolution: {integrity: sha512-nOvU699OXiGMbyswao7JJnY0C9WkwE7PVC/m5WWt0UN9fsXSOor9IZWw+v9SATp+94BTJoG38XyUomUaJnoQRA==} 223 - 224 - '@atcute/bluesky-richtext-segmenter@2.0.4': 225 - resolution: {integrity: sha512-6m5QEAv4lU3qTy5MeJXJRRG33acipYJnMW1T7W/KrMyThGhQ7jSTTh8Z48quElgivgX7MDj6o/ow1oLUsjsCKw==} 226 - 227 - '@atcute/bluesky@2.1.1': 228 - resolution: {integrity: sha512-wEZfFW58J6yC1SqHcVJOn4qbHENTTzjeCEWthRT5HvKovADLqk54HSMSAuXDMBUbintSTBr0khQNZQ3ZdgzDdQ==} 229 - peerDependencies: 230 - '@atcute/client': ^3.0.0 231 - 232 - '@atcute/bluesky@3.2.11': 233 - resolution: {integrity: sha512-AboS6y4t+zaxIq7E4noue10csSpIuk/Uwo30/l6GgGBDPXrd7STw8Yb5nGZQP+TdG/uC8/c2mm7UnY65SDOh6A==} 234 - 235 - '@atcute/client@3.1.0': 236 - resolution: {integrity: sha512-+rQPsHXSf0DUm8XoHoaH7Y2E8tIpbsW84djyPj7dqAyrFIjvGuJ1X1DvMufwbTIcmLerdy+dzl34iZcz/h3Vhg==} 237 - 238 - '@atcute/lexicons@1.2.5': 239 - resolution: {integrity: sha512-9yO9WdgxW8jZ7SbzUycH710z+JmsQ9W9n5S6i6eghYju32kkluFmgBeS47r8e8p2+Dv4DemS7o/3SUGsX9FR5Q==} 240 - 241 - '@babel/code-frame@7.27.1': 242 - resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} 243 - engines: {node: '>=6.9.0'} 244 - 245 - '@babel/compat-data@7.28.5': 246 - resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} 247 - engines: {node: '>=6.9.0'} 248 - 249 - '@babel/core@7.28.5': 250 - resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} 251 - engines: {node: '>=6.9.0'} 252 - 253 - '@babel/generator@7.28.5': 254 - resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} 255 - engines: {node: '>=6.9.0'} 256 - 257 - '@babel/helper-annotate-as-pure@7.27.3': 258 - resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} 259 - engines: {node: '>=6.9.0'} 260 - 261 - '@babel/helper-compilation-targets@7.27.2': 262 - resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} 263 - engines: {node: '>=6.9.0'} 264 - 265 - '@babel/helper-globals@7.28.0': 266 - resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} 267 - engines: {node: '>=6.9.0'} 268 - 269 - '@babel/helper-module-imports@7.27.1': 270 - resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} 271 - engines: {node: '>=6.9.0'} 272 - 273 - '@babel/helper-module-transforms@7.28.3': 274 - resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} 275 - engines: {node: '>=6.9.0'} 276 - peerDependencies: 277 - '@babel/core': ^7.0.0 278 - 279 - '@babel/helper-plugin-utils@7.27.1': 280 - resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} 281 - engines: {node: '>=6.9.0'} 282 - 283 - '@babel/helper-string-parser@7.27.1': 284 - resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} 285 - engines: {node: '>=6.9.0'} 286 - 287 - '@babel/helper-validator-identifier@7.28.5': 288 - resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} 289 - engines: {node: '>=6.9.0'} 290 - 291 - '@babel/helper-validator-option@7.27.1': 292 - resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} 293 - engines: {node: '>=6.9.0'} 294 - 295 - '@babel/helpers@7.28.4': 296 - resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} 297 - engines: {node: '>=6.9.0'} 298 - 299 - '@babel/parser@7.28.5': 300 - resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} 301 - engines: {node: '>=6.0.0'} 302 - hasBin: true 303 - 304 - '@babel/plugin-syntax-jsx@7.27.1': 305 - resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} 306 - engines: {node: '>=6.9.0'} 307 - peerDependencies: 308 - '@babel/core': ^7.0.0-0 309 - 310 - '@babel/plugin-transform-react-jsx-development@7.27.1': 311 - resolution: {integrity: sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==} 312 - engines: {node: '>=6.9.0'} 313 - peerDependencies: 314 - '@babel/core': ^7.0.0-0 315 - 316 - '@babel/plugin-transform-react-jsx@7.27.1': 317 - resolution: {integrity: sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==} 318 - engines: {node: '>=6.9.0'} 319 - peerDependencies: 320 - '@babel/core': ^7.0.0-0 321 - 322 - '@babel/runtime@7.28.4': 323 - resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} 324 - engines: {node: '>=6.9.0'} 325 - 326 - '@babel/template@7.27.2': 327 - resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} 328 - engines: {node: '>=6.9.0'} 329 - 330 - '@babel/traverse@7.28.5': 331 - resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} 332 - engines: {node: '>=6.9.0'} 333 - 334 - '@babel/types@7.28.5': 335 - resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} 336 - engines: {node: '>=6.9.0'} 337 - 338 - '@changesets/apply-release-plan@7.0.14': 339 - resolution: {integrity: sha512-ddBvf9PHdy2YY0OUiEl3TV78mH9sckndJR14QAt87KLEbIov81XO0q0QAmvooBxXlqRRP8I9B7XOzZwQG7JkWA==} 340 - 341 - '@changesets/assemble-release-plan@6.0.9': 342 - resolution: {integrity: sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ==} 343 - 344 - '@changesets/changelog-git@0.2.1': 345 - resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} 346 - 347 - '@changesets/cli@2.29.8': 348 - resolution: {integrity: sha512-1weuGZpP63YWUYjay/E84qqwcnt5yJMM0tep10Up7Q5cS/DGe2IZ0Uj3HNMxGhCINZuR7aO9WBMdKnPit5ZDPA==} 349 - hasBin: true 350 - 351 - '@changesets/config@3.1.2': 352 - resolution: {integrity: sha512-CYiRhA4bWKemdYi/uwImjPxqWNpqGPNbEBdX1BdONALFIDK7MCUj6FPkzD+z9gJcvDFUQJn9aDVf4UG7OT6Kog==} 353 - 354 - '@changesets/errors@0.2.0': 355 - resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} 356 - 357 - '@changesets/get-dependents-graph@2.1.3': 358 - resolution: {integrity: sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==} 359 - 360 - '@changesets/get-release-plan@4.0.14': 361 - resolution: {integrity: sha512-yjZMHpUHgl4Xl5gRlolVuxDkm4HgSJqT93Ri1Uz8kGrQb+5iJ8dkXJ20M2j/Y4iV5QzS2c5SeTxVSKX+2eMI0g==} 362 - 363 - '@changesets/get-version-range-type@0.4.0': 364 - resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} 365 - 366 - '@changesets/git@3.0.4': 367 - resolution: {integrity: sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==} 368 - 369 - '@changesets/logger@0.1.1': 370 - resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} 371 - 372 - '@changesets/parse@0.4.2': 373 - resolution: {integrity: sha512-Uo5MC5mfg4OM0jU3up66fmSn6/NE9INK+8/Vn/7sMVcdWg46zfbvvUSjD9EMonVqPi9fbrJH9SXHn48Tr1f2yA==} 374 - 375 - '@changesets/pre@2.0.2': 376 - resolution: {integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==} 377 - 378 - '@changesets/read@0.6.6': 379 - resolution: {integrity: sha512-P5QaN9hJSQQKJShzzpBT13FzOSPyHbqdoIBUd2DJdgvnECCyO6LmAOWSV+O8se2TaZJVwSXjL+v9yhb+a9JeJg==} 380 - 381 - '@changesets/should-skip-package@0.1.2': 382 - resolution: {integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==} 383 - 384 - '@changesets/types@4.1.0': 385 - resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} 386 - 387 - '@changesets/types@6.1.0': 388 - resolution: {integrity: sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==} 389 - 390 - '@changesets/write@0.4.0': 391 - resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} 392 - 393 - '@esbuild/aix-ppc64@0.25.12': 394 - resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} 395 - engines: {node: '>=18'} 396 - cpu: [ppc64] 397 - os: [aix] 398 - 399 - '@esbuild/android-arm64@0.25.12': 400 - resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} 401 - engines: {node: '>=18'} 402 - cpu: [arm64] 403 - os: [android] 404 - 405 - '@esbuild/android-arm@0.25.12': 406 - resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} 407 - engines: {node: '>=18'} 408 - cpu: [arm] 409 - os: [android] 410 - 411 - '@esbuild/android-x64@0.25.12': 412 - resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} 413 - engines: {node: '>=18'} 414 - cpu: [x64] 415 - os: [android] 416 - 417 - '@esbuild/darwin-arm64@0.25.12': 418 - resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} 419 - engines: {node: '>=18'} 420 - cpu: [arm64] 421 - os: [darwin] 422 - 423 - '@esbuild/darwin-x64@0.25.12': 424 - resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} 425 - engines: {node: '>=18'} 426 - cpu: [x64] 427 - os: [darwin] 428 - 429 - '@esbuild/freebsd-arm64@0.25.12': 430 - resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} 431 - engines: {node: '>=18'} 432 - cpu: [arm64] 433 - os: [freebsd] 434 - 435 - '@esbuild/freebsd-x64@0.25.12': 436 - resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} 437 - engines: {node: '>=18'} 438 - cpu: [x64] 439 - os: [freebsd] 440 - 441 - '@esbuild/linux-arm64@0.25.12': 442 - resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} 443 - engines: {node: '>=18'} 444 - cpu: [arm64] 445 - os: [linux] 446 - 447 - '@esbuild/linux-arm@0.25.12': 448 - resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} 449 - engines: {node: '>=18'} 450 - cpu: [arm] 451 - os: [linux] 452 - 453 - '@esbuild/linux-ia32@0.25.12': 454 - resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} 455 - engines: {node: '>=18'} 456 - cpu: [ia32] 457 - os: [linux] 458 - 459 - '@esbuild/linux-loong64@0.25.12': 460 - resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} 461 - engines: {node: '>=18'} 462 - cpu: [loong64] 463 - os: [linux] 464 - 465 - '@esbuild/linux-mips64el@0.25.12': 466 - resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} 467 - engines: {node: '>=18'} 468 - cpu: [mips64el] 469 - os: [linux] 470 - 471 - '@esbuild/linux-ppc64@0.25.12': 472 - resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} 473 - engines: {node: '>=18'} 474 - cpu: [ppc64] 475 - os: [linux] 476 - 477 - '@esbuild/linux-riscv64@0.25.12': 478 - resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} 479 - engines: {node: '>=18'} 480 - cpu: [riscv64] 481 - os: [linux] 482 - 483 - '@esbuild/linux-s390x@0.25.12': 484 - resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} 485 - engines: {node: '>=18'} 486 - cpu: [s390x] 487 - os: [linux] 488 - 489 - '@esbuild/linux-x64@0.25.12': 490 - resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} 491 - engines: {node: '>=18'} 492 - cpu: [x64] 493 - os: [linux] 494 - 495 - '@esbuild/netbsd-arm64@0.25.12': 496 - resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} 497 - engines: {node: '>=18'} 498 - cpu: [arm64] 499 - os: [netbsd] 500 - 501 - '@esbuild/netbsd-x64@0.25.12': 502 - resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} 503 - engines: {node: '>=18'} 504 - cpu: [x64] 505 - os: [netbsd] 506 - 507 - '@esbuild/openbsd-arm64@0.25.12': 508 - resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} 509 - engines: {node: '>=18'} 510 - cpu: [arm64] 511 - os: [openbsd] 512 - 513 - '@esbuild/openbsd-x64@0.25.12': 514 - resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} 515 - engines: {node: '>=18'} 516 - cpu: [x64] 517 - os: [openbsd] 518 - 519 - '@esbuild/openharmony-arm64@0.25.12': 520 - resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} 521 - engines: {node: '>=18'} 522 - cpu: [arm64] 523 - os: [openharmony] 524 - 525 - '@esbuild/sunos-x64@0.25.12': 526 - resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} 527 - engines: {node: '>=18'} 528 - cpu: [x64] 529 - os: [sunos] 530 - 531 - '@esbuild/win32-arm64@0.25.12': 532 - resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} 533 - engines: {node: '>=18'} 534 - cpu: [arm64] 535 - os: [win32] 536 - 537 - '@esbuild/win32-ia32@0.25.12': 538 - resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} 539 - engines: {node: '>=18'} 540 - cpu: [ia32] 541 - os: [win32] 542 - 543 - '@esbuild/win32-x64@0.25.12': 544 - resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} 545 - engines: {node: '>=18'} 546 - cpu: [x64] 547 - os: [win32] 548 - 549 - '@inquirer/external-editor@1.0.3': 550 - resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} 551 - engines: {node: '>=18'} 552 - peerDependencies: 553 - '@types/node': '>=18' 554 - peerDependenciesMeta: 555 - '@types/node': 556 - optional: true 557 - 558 - '@isaacs/balanced-match@4.0.1': 559 - resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} 560 - engines: {node: 20 || >=22} 561 - 562 - '@isaacs/brace-expansion@5.0.0': 563 - resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} 564 - engines: {node: 20 || >=22} 565 - 566 - '@jridgewell/gen-mapping@0.3.13': 567 - resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} 568 - 569 - '@jridgewell/remapping@2.3.5': 570 - resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} 571 - 572 - '@jridgewell/resolve-uri@3.1.2': 573 - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} 574 - engines: {node: '>=6.0.0'} 575 - 576 - '@jridgewell/source-map@0.3.11': 577 - resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} 578 - 579 - '@jridgewell/sourcemap-codec@1.5.5': 580 - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} 581 - 582 - '@jridgewell/trace-mapping@0.3.31': 583 - resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} 584 - 585 - '@manypkg/find-root@1.1.0': 586 - resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} 587 - 588 - '@manypkg/get-packages@1.1.3': 589 - resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} 590 - 591 - '@microsoft/api-extractor-model@7.32.1': 592 - resolution: {integrity: sha512-u4yJytMYiUAnhcNQcZDTh/tVtlrzKlyKrQnLOV+4Qr/5gV+cpufWzCYAB1Q23URFqD6z2RoL2UYncM9xJVGNKA==} 593 - 594 - '@microsoft/api-extractor@7.55.1': 595 - resolution: {integrity: sha512-l8Z+8qrLkZFM3HM95Dbpqs6G39fpCa7O5p8A7AkA6hSevxkgwsOlLrEuPv0ADOyj5dI1Af5WVDiwpKG/ya5G3w==} 596 - hasBin: true 597 - 598 - '@microsoft/tsdoc-config@0.18.0': 599 - resolution: {integrity: sha512-8N/vClYyfOH+l4fLkkr9+myAoR6M7akc8ntBJ4DJdWH2b09uVfr71+LTMpNyG19fNqWDg8KEDZhx5wxuqHyGjw==} 600 - 601 - '@microsoft/tsdoc@0.16.0': 602 - resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==} 603 - 604 - '@nodelib/fs.scandir@2.1.5': 605 - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 606 - engines: {node: '>= 8'} 607 - 608 - '@nodelib/fs.stat@2.0.5': 609 - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 610 - engines: {node: '>= 8'} 611 - 612 - '@nodelib/fs.walk@1.2.8': 613 - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 614 - engines: {node: '>= 8'} 615 - 616 - '@preact/preset-vite@2.10.2': 617 - resolution: {integrity: sha512-K9wHlJOtkE+cGqlyQ5v9kL3Ge0Ql4LlIZjkUTL+1zf3nNdF88F9UZN6VTV8jdzBX9Fl7WSzeNMSDG7qECPmSmg==} 618 - peerDependencies: 619 - '@babel/core': 7.x 620 - vite: 2.x || 3.x || 4.x || 5.x || 6.x || 7.x 621 - 622 - '@prefresh/babel-plugin@0.5.2': 623 - resolution: {integrity: sha512-AOl4HG6dAxWkJ5ndPHBgBa49oo/9bOiJuRDKHLSTyH+Fd9x00shTXpdiTj1W41l6oQIwUOAgJeHMn4QwIDpHkA==} 624 - 625 - '@prefresh/core@1.5.9': 626 - resolution: {integrity: sha512-IKBKCPaz34OFVC+adiQ2qaTF5qdztO2/4ZPf4KsRTgjKosWqxVXmEbxCiUydYZRY8GVie+DQlKzQr9gt6HQ+EQ==} 627 - peerDependencies: 628 - preact: ^10.0.0 || ^11.0.0-0 629 - 630 - '@prefresh/utils@1.2.1': 631 - resolution: {integrity: sha512-vq/sIuN5nYfYzvyayXI4C2QkprfNaHUQ9ZX+3xLD8nL3rWyzpxOm1+K7RtMbhd+66QcaISViK7amjnheQ/4WZw==} 632 - 633 - '@prefresh/vite@2.4.11': 634 - resolution: {integrity: sha512-/XjURQqdRiCG3NpMmWqE9kJwrg9IchIOWHzulCfqg2sRe/8oQ1g5De7xrk9lbqPIQLn7ntBkKdqWXIj4E9YXyg==} 635 - peerDependencies: 636 - preact: ^10.4.0 || ^11.0.0-0 637 - vite: '>=2.0.0' 638 - 639 - '@rollup/pluginutils@4.2.1': 640 - resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} 641 - engines: {node: '>= 8.0.0'} 642 - 643 - '@rollup/pluginutils@5.3.0': 644 - resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} 645 - engines: {node: '>=14.0.0'} 646 - peerDependencies: 647 - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 648 - peerDependenciesMeta: 649 - rollup: 650 - optional: true 651 - 652 - '@rollup/rollup-android-arm-eabi@4.53.3': 653 - resolution: {integrity: sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==} 654 - cpu: [arm] 655 - os: [android] 656 - 657 - '@rollup/rollup-android-arm64@4.53.3': 658 - resolution: {integrity: sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==} 659 - cpu: [arm64] 660 - os: [android] 661 - 662 - '@rollup/rollup-darwin-arm64@4.53.3': 663 - resolution: {integrity: sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==} 664 - cpu: [arm64] 665 - os: [darwin] 666 - 667 - '@rollup/rollup-darwin-x64@4.53.3': 668 - resolution: {integrity: sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==} 669 - cpu: [x64] 670 - os: [darwin] 671 - 672 - '@rollup/rollup-freebsd-arm64@4.53.3': 673 - resolution: {integrity: sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==} 674 - cpu: [arm64] 675 - os: [freebsd] 676 - 677 - '@rollup/rollup-freebsd-x64@4.53.3': 678 - resolution: {integrity: sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==} 679 - cpu: [x64] 680 - os: [freebsd] 681 - 682 - '@rollup/rollup-linux-arm-gnueabihf@4.53.3': 683 - resolution: {integrity: sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==} 684 - cpu: [arm] 685 - os: [linux] 686 - 687 - '@rollup/rollup-linux-arm-musleabihf@4.53.3': 688 - resolution: {integrity: sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==} 689 - cpu: [arm] 690 - os: [linux] 691 - 692 - '@rollup/rollup-linux-arm64-gnu@4.53.3': 693 - resolution: {integrity: sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==} 694 - cpu: [arm64] 695 - os: [linux] 696 - 697 - '@rollup/rollup-linux-arm64-musl@4.53.3': 698 - resolution: {integrity: sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==} 699 - cpu: [arm64] 700 - os: [linux] 701 - 702 - '@rollup/rollup-linux-loong64-gnu@4.53.3': 703 - resolution: {integrity: sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==} 704 - cpu: [loong64] 705 - os: [linux] 706 - 707 - '@rollup/rollup-linux-ppc64-gnu@4.53.3': 708 - resolution: {integrity: sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==} 709 - cpu: [ppc64] 710 - os: [linux] 711 - 712 - '@rollup/rollup-linux-riscv64-gnu@4.53.3': 713 - resolution: {integrity: sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==} 714 - cpu: [riscv64] 715 - os: [linux] 716 - 717 - '@rollup/rollup-linux-riscv64-musl@4.53.3': 718 - resolution: {integrity: sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==} 719 - cpu: [riscv64] 720 - os: [linux] 721 - 722 - '@rollup/rollup-linux-s390x-gnu@4.53.3': 723 - resolution: {integrity: sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==} 724 - cpu: [s390x] 725 - os: [linux] 726 - 727 - '@rollup/rollup-linux-x64-gnu@4.53.3': 728 - resolution: {integrity: sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==} 729 - cpu: [x64] 730 - os: [linux] 731 - 732 - '@rollup/rollup-linux-x64-musl@4.53.3': 733 - resolution: {integrity: sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==} 734 - cpu: [x64] 735 - os: [linux] 736 - 737 - '@rollup/rollup-openharmony-arm64@4.53.3': 738 - resolution: {integrity: sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==} 739 - cpu: [arm64] 740 - os: [openharmony] 741 - 742 - '@rollup/rollup-win32-arm64-msvc@4.53.3': 743 - resolution: {integrity: sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==} 744 - cpu: [arm64] 745 - os: [win32] 746 - 747 - '@rollup/rollup-win32-ia32-msvc@4.53.3': 748 - resolution: {integrity: sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==} 749 - cpu: [ia32] 750 - os: [win32] 751 - 752 - '@rollup/rollup-win32-x64-gnu@4.53.3': 753 - resolution: {integrity: sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==} 754 - cpu: [x64] 755 - os: [win32] 756 - 757 - '@rollup/rollup-win32-x64-msvc@4.53.3': 758 - resolution: {integrity: sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==} 759 - cpu: [x64] 760 - os: [win32] 761 - 762 - '@rushstack/node-core-library@5.19.0': 763 - resolution: {integrity: sha512-BxAopbeWBvNJ6VGiUL+5lbJXywTdsnMeOS8j57Cn/xY10r6sV/gbsTlfYKjzVCUBZATX2eRzJHSMCchsMTGN6A==} 764 - peerDependencies: 765 - '@types/node': '*' 766 - peerDependenciesMeta: 767 - '@types/node': 768 - optional: true 769 - 770 - '@rushstack/problem-matcher@0.1.1': 771 - resolution: {integrity: sha512-Fm5XtS7+G8HLcJHCWpES5VmeMyjAKaWeyZU5qPzZC+22mPlJzAsOxymHiWIfuirtPckX3aptWws+K2d0BzniJA==} 772 - peerDependencies: 773 - '@types/node': '*' 774 - peerDependenciesMeta: 775 - '@types/node': 776 - optional: true 777 - 778 - '@rushstack/rig-package@0.6.0': 779 - resolution: {integrity: sha512-ZQmfzsLE2+Y91GF15c65L/slMRVhF6Hycq04D4TwtdGaUAbIXXg9c5pKA5KFU7M4QMaihoobp9JJYpYcaY3zOw==} 780 - 781 - '@rushstack/terminal@0.19.4': 782 - resolution: {integrity: sha512-f4XQk02CrKfrMgyOfhYd3qWI944dLC21S4I/LUhrlAP23GTMDNG6EK5effQtFkISwUKCgD9vMBrJZaPSUquxWQ==} 783 - peerDependencies: 784 - '@types/node': '*' 785 - peerDependenciesMeta: 786 - '@types/node': 787 - optional: true 788 - 789 - '@rushstack/ts-command-line@5.1.4': 790 - resolution: {integrity: sha512-H0I6VdJ6sOUbktDFpP2VW5N29w8v4hRoNZOQz02vtEi6ZTYL1Ju8u+TcFiFawUDrUsx/5MQTUhd79uwZZVwVlA==} 791 - 792 - '@standard-schema/spec@1.0.0': 793 - resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} 794 - 795 - '@sveltejs/acorn-typescript@1.0.8': 796 - resolution: {integrity: sha512-esgN+54+q0NjB0Y/4BomT9samII7jGwNy/2a3wNZbT2A2RpmXsXwUt24LvLhx6jUq2gVk4cWEvcRO6MFQbOfNA==} 797 - peerDependencies: 798 - acorn: ^8.9.0 799 - 800 - '@sveltejs/vite-plugin-svelte-inspector@5.0.1': 801 - resolution: {integrity: sha512-ubWshlMk4bc8mkwWbg6vNvCeT7lGQojE3ijDh3QTR6Zr/R+GXxsGbyH4PExEPpiFmqPhYiVSVmHBjUcVc1JIrA==} 802 - engines: {node: ^20.19 || ^22.12 || >=24} 803 - peerDependencies: 804 - '@sveltejs/vite-plugin-svelte': ^6.0.0-next.0 805 - svelte: ^5.0.0 806 - vite: ^6.3.0 || ^7.0.0 807 - 808 - '@sveltejs/vite-plugin-svelte@6.2.1': 809 - resolution: {integrity: sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ==} 810 - engines: {node: ^20.19 || ^22.12 || >=24} 811 - peerDependencies: 812 - svelte: ^5.0.0 813 - vite: ^6.3.0 || ^7.0.0 814 - 815 - '@tsconfig/svelte@5.0.6': 816 - resolution: {integrity: sha512-yGxYL0I9eETH1/DR9qVJey4DAsCdeau4a9wYPKuXfEhm8lFO8wg+LLYJjIpAm6Fw7HSlhepPhYPDop75485yWQ==} 817 - 818 - '@types/argparse@1.0.38': 819 - resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} 820 - 821 - '@types/estree@1.0.8': 822 - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} 823 - 824 - '@types/node@12.20.55': 825 - resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} 826 - 827 - '@types/node@24.10.1': 828 - resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==} 829 - 830 - '@volar/language-core@2.4.26': 831 - resolution: {integrity: sha512-hH0SMitMxnB43OZpyF1IFPS9bgb2I3bpCh76m2WEK7BE0A0EzpYsRp0CCH2xNKshr7kacU5TQBLYn4zj7CG60A==} 832 - 833 - '@volar/source-map@2.4.26': 834 - resolution: {integrity: sha512-JJw0Tt/kSFsIRmgTQF4JSt81AUSI1aEye5Zl65EeZ8H35JHnTvFGmpDOBn5iOxd48fyGE+ZvZBp5FcgAy/1Qhw==} 835 - 836 - '@volar/typescript@2.4.26': 837 - resolution: {integrity: sha512-N87ecLD48Sp6zV9zID/5yuS1+5foj0DfuYGdQ6KHj/IbKvyKv1zNX6VCmnKYwtmHadEO6mFc2EKISiu3RDPAvA==} 838 - 839 - '@vue/compiler-core@3.5.25': 840 - resolution: {integrity: sha512-vay5/oQJdsNHmliWoZfHPoVZZRmnSWhug0BYT34njkYTPqClh3DNWLkZNJBVSjsNMrg0CCrBfoKkjZQPM/QVUw==} 841 - 842 - '@vue/compiler-dom@3.5.25': 843 - resolution: {integrity: sha512-4We0OAcMZsKgYoGlMjzYvaoErltdFI2/25wqanuTu+S4gismOTRTBPi4IASOjxWdzIwrYSjnqONfKvuqkXzE2Q==} 844 - 845 - '@vue/compiler-vue2@2.7.16': 846 - resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} 847 - 848 - '@vue/language-core@2.2.0': 849 - resolution: {integrity: sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw==} 850 - peerDependencies: 851 - typescript: '*' 852 - peerDependenciesMeta: 853 - typescript: 854 - optional: true 855 - 856 - '@vue/shared@3.5.25': 857 - resolution: {integrity: sha512-AbOPdQQnAnzs58H2FrrDxYj/TJfmeS2jdfEEhgiKINy+bnOANmVizIEgq1r+C5zsbs6l1CCQxtcj71rwNQ4jWg==} 858 - 859 - acorn@8.15.0: 860 - resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} 861 - engines: {node: '>=0.4.0'} 862 - hasBin: true 863 - 864 - ajv-draft-04@1.0.0: 865 - resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} 866 - peerDependencies: 867 - ajv: ^8.5.0 868 - peerDependenciesMeta: 869 - ajv: 870 - optional: true 871 - 872 - ajv-formats@3.0.1: 873 - resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} 874 - peerDependencies: 875 - ajv: ^8.0.0 876 - peerDependenciesMeta: 877 - ajv: 878 - optional: true 879 - 880 - ajv@8.12.0: 881 - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} 882 - 883 - ajv@8.13.0: 884 - resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==} 885 - 886 - alien-signals@0.4.14: 887 - resolution: {integrity: sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==} 888 - 889 - ansi-colors@4.1.3: 890 - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} 891 - engines: {node: '>=6'} 892 - 893 - ansi-regex@5.0.1: 894 - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 895 - engines: {node: '>=8'} 896 - 897 - argparse@1.0.10: 898 - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} 899 - 900 - argparse@2.0.1: 901 - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 902 - 903 - aria-query@5.3.2: 904 - resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} 905 - engines: {node: '>= 0.4'} 906 - 907 - array-union@2.1.0: 908 - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} 909 - engines: {node: '>=8'} 910 - 911 - axobject-query@4.1.0: 912 - resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} 913 - engines: {node: '>= 0.4'} 914 - 915 - babel-plugin-transform-hook-names@1.0.2: 916 - resolution: {integrity: sha512-5gafyjyyBTTdX/tQQ0hRgu4AhNHG/hqWi0ZZmg2xvs2FgRkJXzDNKBZCyoYqgFkovfDrgM8OoKg8karoUvWeCw==} 917 - peerDependencies: 918 - '@babel/core': ^7.12.10 919 - 920 - balanced-match@1.0.2: 921 - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 922 - 923 - baseline-browser-mapping@2.9.0: 924 - resolution: {integrity: sha512-Mh++g+2LPfzZToywfE1BUzvZbfOY52Nil0rn9H1CPC5DJ7fX+Vir7nToBeoiSbB1zTNeGYbELEvJESujgGrzXw==} 925 - hasBin: true 926 - 927 - better-path-resolve@1.0.0: 928 - resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} 929 - engines: {node: '>=4'} 930 - 931 - boolbase@1.0.0: 932 - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} 933 - 934 - brace-expansion@2.0.2: 935 - resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} 936 - 937 - braces@3.0.3: 938 - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 939 - engines: {node: '>=8'} 940 - 941 - browserslist@4.28.1: 942 - resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} 943 - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 944 - hasBin: true 945 - 946 - buffer-from@1.1.2: 947 - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} 948 - 949 - caniuse-lite@1.0.30001759: 950 - resolution: {integrity: sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==} 951 - 952 - chardet@2.1.1: 953 - resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} 954 - 955 - chokidar@4.0.3: 956 - resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} 957 - engines: {node: '>= 14.16.0'} 958 - 959 - ci-info@3.9.0: 960 - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} 961 - engines: {node: '>=8'} 962 - 963 - clsx@2.1.1: 964 - resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} 965 - engines: {node: '>=6'} 966 - 967 - commander@2.20.3: 968 - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} 969 - 970 - compare-versions@6.1.1: 971 - resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} 972 - 973 - confbox@0.1.8: 974 - resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} 975 - 976 - confbox@0.2.2: 977 - resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==} 978 - 979 - convert-source-map@2.0.0: 980 - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} 981 - 982 - cross-spawn@7.0.6: 983 - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} 984 - engines: {node: '>= 8'} 985 - 986 - css-declaration-sorter@7.3.0: 987 - resolution: {integrity: sha512-LQF6N/3vkAMYF4xoHLJfG718HRJh34Z8BnNhd6bosOMIVjMlhuZK5++oZa3uYAgrI5+7x2o27gUqTR2U/KjUOQ==} 988 - engines: {node: ^14 || ^16 || >=18} 989 - peerDependencies: 990 - postcss: ^8.0.9 991 - 992 - css-select@5.2.2: 993 - resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} 994 - 995 - css-what@6.2.2: 996 - resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} 997 - engines: {node: '>= 6'} 998 - 999 - de-indent@1.0.2: 1000 - resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} 1001 - 1002 - debug@4.4.3: 1003 - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} 1004 - engines: {node: '>=6.0'} 1005 - peerDependencies: 1006 - supports-color: '*' 1007 - peerDependenciesMeta: 1008 - supports-color: 1009 - optional: true 1010 - 1011 - deepmerge@4.3.1: 1012 - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} 1013 - engines: {node: '>=0.10.0'} 1014 - 1015 - detect-indent@6.1.0: 1016 - resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} 1017 - engines: {node: '>=8'} 1018 - 1019 - devalue@5.5.0: 1020 - resolution: {integrity: sha512-69sM5yrHfFLJt0AZ9QqZXGCPfJ7fQjvpln3Rq5+PS03LD32Ost1Q9N+eEnaQwGRIriKkMImXD56ocjQmfjbV3w==} 1021 - 1022 - diff@8.0.2: 1023 - resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==} 1024 - engines: {node: '>=0.3.1'} 1025 - 1026 - dir-glob@3.0.1: 1027 - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} 1028 - engines: {node: '>=8'} 1029 - 1030 - dom-serializer@2.0.0: 1031 - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} 1032 - 1033 - domelementtype@2.3.0: 1034 - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} 1035 - 1036 - domhandler@5.0.3: 1037 - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} 1038 - engines: {node: '>= 4'} 1039 - 1040 - domutils@3.2.2: 1041 - resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} 1042 - 1043 - electron-to-chromium@1.5.264: 1044 - resolution: {integrity: sha512-1tEf0nLgltC3iy9wtlYDlQDc5Rg9lEKVjEmIHJ21rI9OcqkvD45K1oyNIRA4rR1z3LgJ7KeGzEBojVcV6m4qjA==} 1045 - 1046 - enquirer@2.4.1: 1047 - resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} 1048 - engines: {node: '>=8.6'} 1049 - 1050 - entities@4.5.0: 1051 - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} 1052 - engines: {node: '>=0.12'} 1053 - 1054 - esbuild@0.25.12: 1055 - resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} 1056 - engines: {node: '>=18'} 1057 - hasBin: true 1058 - 1059 - escalade@3.2.0: 1060 - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} 1061 - engines: {node: '>=6'} 1062 - 1063 - esm-env@1.2.2: 1064 - resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} 1065 - 1066 - esprima@4.0.1: 1067 - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} 1068 - engines: {node: '>=4'} 1069 - hasBin: true 1070 - 1071 - esrap@2.2.1: 1072 - resolution: {integrity: sha512-GiYWG34AN/4CUyaWAgunGt0Rxvr1PTMlGC0vvEov/uOQYWne2bpN03Um+k8jT+q3op33mKouP2zeJ6OlM+qeUg==} 1073 - 1074 - estree-walker@2.0.2: 1075 - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} 1076 - 1077 - exsolve@1.0.8: 1078 - resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==} 1079 - 1080 - extendable-error@0.1.7: 1081 - resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} 1082 - 1083 - fast-deep-equal@3.1.3: 1084 - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 1085 - 1086 - fast-glob@3.3.3: 1087 - resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} 1088 - engines: {node: '>=8.6.0'} 1089 - 1090 - fastq@1.19.1: 1091 - resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} 1092 - 1093 - fdir@6.5.0: 1094 - resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} 1095 - engines: {node: '>=12.0.0'} 1096 - peerDependencies: 1097 - picomatch: ^3 || ^4 1098 - peerDependenciesMeta: 1099 - picomatch: 1100 - optional: true 1101 - 1102 - fill-range@7.1.1: 1103 - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 1104 - engines: {node: '>=8'} 1105 - 1106 - find-up@4.1.0: 1107 - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} 1108 - engines: {node: '>=8'} 1109 - 1110 - fs-extra@11.3.2: 1111 - resolution: {integrity: sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==} 1112 - engines: {node: '>=14.14'} 1113 - 1114 - fs-extra@7.0.1: 1115 - resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} 1116 - engines: {node: '>=6 <7 || >=8'} 1117 - 1118 - fs-extra@8.1.0: 1119 - resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} 1120 - engines: {node: '>=6 <7 || >=8'} 1121 - 1122 - fsevents@2.3.3: 1123 - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 1124 - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 1125 - os: [darwin] 1126 - 1127 - function-bind@1.1.2: 1128 - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 1129 - 1130 - gensync@1.0.0-beta.2: 1131 - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} 1132 - engines: {node: '>=6.9.0'} 1133 - 1134 - glob-parent@5.1.2: 1135 - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 1136 - engines: {node: '>= 6'} 1137 - 1138 - globby@11.1.0: 1139 - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} 1140 - engines: {node: '>=10'} 1141 - 1142 - graceful-fs@4.2.11: 1143 - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} 1144 - 1145 - has-flag@4.0.0: 1146 - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 1147 - engines: {node: '>=8'} 1148 - 1149 - hasown@2.0.2: 1150 - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} 1151 - engines: {node: '>= 0.4'} 1152 - 1153 - he@1.2.0: 1154 - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} 1155 - hasBin: true 1156 - 1157 - human-id@4.1.3: 1158 - resolution: {integrity: sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q==} 1159 - hasBin: true 1160 - 1161 - iconv-lite@0.7.0: 1162 - resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==} 1163 - engines: {node: '>=0.10.0'} 1164 - 1165 - ignore@5.3.2: 1166 - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} 1167 - engines: {node: '>= 4'} 1168 - 1169 - import-lazy@4.0.0: 1170 - resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} 1171 - engines: {node: '>=8'} 1172 - 1173 - is-core-module@2.16.1: 1174 - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} 1175 - engines: {node: '>= 0.4'} 1176 - 1177 - is-extglob@2.1.1: 1178 - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 1179 - engines: {node: '>=0.10.0'} 1180 - 1181 - is-glob@4.0.3: 1182 - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 1183 - engines: {node: '>=0.10.0'} 1184 - 1185 - is-number@7.0.0: 1186 - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 1187 - engines: {node: '>=0.12.0'} 1188 - 1189 - is-reference@3.0.3: 1190 - resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} 1191 - 1192 - is-subdir@1.2.0: 1193 - resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} 1194 - engines: {node: '>=4'} 1195 - 1196 - is-windows@1.0.2: 1197 - resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} 1198 - engines: {node: '>=0.10.0'} 1199 - 1200 - isexe@2.0.0: 1201 - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 1202 - 1203 - jju@1.4.0: 1204 - resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} 1205 - 1206 - js-tokens@4.0.0: 1207 - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} 1208 - 1209 - js-yaml@3.14.2: 1210 - resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} 1211 - hasBin: true 1212 - 1213 - js-yaml@4.1.1: 1214 - resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} 1215 - hasBin: true 1216 - 1217 - jsesc@3.1.0: 1218 - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} 1219 - engines: {node: '>=6'} 1220 - hasBin: true 1221 - 1222 - json-schema-traverse@1.0.0: 1223 - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} 1224 - 1225 - json5@2.2.3: 1226 - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} 1227 - engines: {node: '>=6'} 1228 - hasBin: true 1229 - 1230 - jsonfile@4.0.0: 1231 - resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} 1232 - 1233 - jsonfile@6.2.0: 1234 - resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} 1235 - 1236 - kolorist@1.8.0: 1237 - resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} 1238 - 1239 - local-pkg@1.1.2: 1240 - resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==} 1241 - engines: {node: '>=14'} 1242 - 1243 - locate-character@3.0.0: 1244 - resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} 1245 - 1246 - locate-path@5.0.0: 1247 - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} 1248 - engines: {node: '>=8'} 1249 - 1250 - lodash.startcase@4.4.0: 1251 - resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} 1252 - 1253 - lodash@4.17.21: 1254 - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} 1255 - 1256 - lru-cache@5.1.1: 1257 - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} 1258 - 1259 - lru-cache@6.0.0: 1260 - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} 1261 - engines: {node: '>=10'} 1262 - 1263 - magic-string@0.30.21: 1264 - resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} 1265 - 1266 - merge2@1.4.1: 1267 - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 1268 - engines: {node: '>= 8'} 1269 - 1270 - micromatch@4.0.8: 1271 - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 1272 - engines: {node: '>=8.6'} 1273 - 1274 - minimatch@10.0.3: 1275 - resolution: {integrity: sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==} 1276 - engines: {node: 20 || >=22} 1277 - 1278 - minimatch@9.0.5: 1279 - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} 1280 - engines: {node: '>=16 || 14 >=14.17'} 1281 - 1282 - mlly@1.8.0: 1283 - resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} 1284 - 1285 - mri@1.2.0: 1286 - resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} 1287 - engines: {node: '>=4'} 1288 - 1289 - ms@2.1.3: 1290 - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 1291 - 1292 - muggle-string@0.4.1: 1293 - resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} 1294 - 1295 - nanoid@3.3.11: 1296 - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} 1297 - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1298 - hasBin: true 1299 - 1300 - node-html-parser@6.1.13: 1301 - resolution: {integrity: sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==} 1302 - 1303 - node-releases@2.0.27: 1304 - resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} 1305 - 1306 - nth-check@2.1.1: 1307 - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} 1308 - 1309 - outdent@0.5.0: 1310 - resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} 1311 - 1312 - p-filter@2.1.0: 1313 - resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} 1314 - engines: {node: '>=8'} 1315 - 1316 - p-limit@2.3.0: 1317 - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} 1318 - engines: {node: '>=6'} 1319 - 1320 - p-locate@4.1.0: 1321 - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} 1322 - engines: {node: '>=8'} 1323 - 1324 - p-map@2.1.0: 1325 - resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} 1326 - engines: {node: '>=6'} 1327 - 1328 - p-try@2.2.0: 1329 - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} 1330 - engines: {node: '>=6'} 1331 - 1332 - package-manager-detector@0.2.11: 1333 - resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==} 1334 - 1335 - path-browserify@1.0.1: 1336 - resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} 1337 - 1338 - path-exists@4.0.0: 1339 - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 1340 - engines: {node: '>=8'} 1341 - 1342 - path-key@3.1.1: 1343 - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1344 - engines: {node: '>=8'} 1345 - 1346 - path-parse@1.0.7: 1347 - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1348 - 1349 - path-type@4.0.0: 1350 - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} 1351 - engines: {node: '>=8'} 1352 - 1353 - pathe@2.0.3: 1354 - resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} 1355 - 1356 - picocolors@1.1.1: 1357 - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} 1358 - 1359 - picomatch@2.3.1: 1360 - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1361 - engines: {node: '>=8.6'} 1362 - 1363 - picomatch@4.0.3: 1364 - resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} 1365 - engines: {node: '>=12'} 1366 - 1367 - pify@4.0.1: 1368 - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} 1369 - engines: {node: '>=6'} 1370 - 1371 - pkg-types@1.3.1: 1372 - resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} 1373 - 1374 - pkg-types@2.3.0: 1375 - resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} 1376 - 1377 - postcss-less@6.0.0: 1378 - resolution: {integrity: sha512-FPX16mQLyEjLzEuuJtxA8X3ejDLNGGEG503d2YGZR5Ask1SpDN8KmZUMpzCvyalWRywAn1n1VOA5dcqfCLo5rg==} 1379 - engines: {node: '>=12'} 1380 - peerDependencies: 1381 - postcss: ^8.3.5 1382 - 1383 - postcss-scss@4.0.9: 1384 - resolution: {integrity: sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==} 1385 - engines: {node: '>=12.0'} 1386 - peerDependencies: 1387 - postcss: ^8.4.29 1388 - 1389 - postcss@8.5.6: 1390 - resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} 1391 - engines: {node: ^10 || ^12 || >=14} 1392 - 1393 - preact@10.28.0: 1394 - resolution: {integrity: sha512-rytDAoiXr3+t6OIP3WGlDd0ouCUG1iCWzkcY3++Nreuoi17y6T5i/zRhe6uYfoVcxq6YU+sBtJouuRDsq8vvqA==} 1395 - 1396 - prettier-plugin-css-order@2.1.2: 1397 - resolution: {integrity: sha512-vomxPjHI6pOMYcBuouSJHxxQClJXaUpU9rsV9IAO2wrSTZILRRlrxAAR8t9UF6wtczLkLfNRFUwM+ZbGXOONUA==} 1398 - engines: {node: '>=16'} 1399 - peerDependencies: 1400 - prettier: 3.x 1401 - 1402 - prettier-plugin-svelte@3.4.0: 1403 - resolution: {integrity: sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ==} 1404 - peerDependencies: 1405 - prettier: ^3.0.0 1406 - svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0 1407 - 1408 - prettier@2.8.8: 1409 - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} 1410 - engines: {node: '>=10.13.0'} 1411 - hasBin: true 1412 - 1413 - prettier@3.7.4: 1414 - resolution: {integrity: sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==} 1415 - engines: {node: '>=14'} 1416 - hasBin: true 1417 - 1418 - punycode@2.3.1: 1419 - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 1420 - engines: {node: '>=6'} 1421 - 1422 - quansync@0.2.11: 1423 - resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} 1424 - 1425 - queue-microtask@1.2.3: 1426 - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1427 - 1428 - read-yaml-file@1.1.0: 1429 - resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} 1430 - engines: {node: '>=6'} 1431 - 1432 - readdirp@4.1.2: 1433 - resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} 1434 - engines: {node: '>= 14.18.0'} 1435 - 1436 - require-from-string@2.0.2: 1437 - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} 1438 - engines: {node: '>=0.10.0'} 1439 - 1440 - resolve-from@5.0.0: 1441 - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} 1442 - engines: {node: '>=8'} 1443 - 1444 - resolve@1.22.11: 1445 - resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} 1446 - engines: {node: '>= 0.4'} 1447 - hasBin: true 1448 - 1449 - reusify@1.1.0: 1450 - resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} 1451 - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1452 - 1453 - rollup@4.53.3: 1454 - resolution: {integrity: sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==} 1455 - engines: {node: '>=18.0.0', npm: '>=8.0.0'} 1456 - hasBin: true 1457 - 1458 - run-parallel@1.2.0: 1459 - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1460 - 1461 - sade@1.8.1: 1462 - resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} 1463 - engines: {node: '>=6'} 1464 - 1465 - safer-buffer@2.1.2: 1466 - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} 1467 - 1468 - semver@6.3.1: 1469 - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} 1470 - hasBin: true 1471 - 1472 - semver@7.5.4: 1473 - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} 1474 - engines: {node: '>=10'} 1475 - hasBin: true 1476 - 1477 - semver@7.7.3: 1478 - resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} 1479 - engines: {node: '>=10'} 1480 - hasBin: true 1481 - 1482 - shebang-command@2.0.0: 1483 - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1484 - engines: {node: '>=8'} 1485 - 1486 - shebang-regex@3.0.0: 1487 - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1488 - engines: {node: '>=8'} 1489 - 1490 - signal-exit@4.1.0: 1491 - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 1492 - engines: {node: '>=14'} 1493 - 1494 - simple-code-frame@1.3.0: 1495 - resolution: {integrity: sha512-MB4pQmETUBlNs62BBeRjIFGeuy/x6gGKh7+eRUemn1rCFhqo7K+4slPqsyizCbcbYLnaYqaoZ2FWsZ/jN06D8w==} 1496 - 1497 - slash@3.0.0: 1498 - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} 1499 - engines: {node: '>=8'} 1500 - 1501 - source-map-js@1.2.1: 1502 - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} 1503 - engines: {node: '>=0.10.0'} 1504 - 1505 - source-map-support@0.5.21: 1506 - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} 1507 - 1508 - source-map@0.6.1: 1509 - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} 1510 - engines: {node: '>=0.10.0'} 1511 - 1512 - source-map@0.7.6: 1513 - resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} 1514 - engines: {node: '>= 12'} 1515 - 1516 - spawndamnit@3.0.1: 1517 - resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} 1518 - 1519 - sprintf-js@1.0.3: 1520 - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} 1521 - 1522 - stack-trace@1.0.0-pre2: 1523 - resolution: {integrity: sha512-2ztBJRek8IVofG9DBJqdy2N5kulaacX30Nz7xmkYF6ale9WBVmIy6mFBchvGX7Vx/MyjBhx+Rcxqrj+dbOnQ6A==} 1524 - engines: {node: '>=16'} 1525 - 1526 - string-argv@0.3.2: 1527 - resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} 1528 - engines: {node: '>=0.6.19'} 1529 - 1530 - strip-ansi@6.0.1: 1531 - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 1532 - engines: {node: '>=8'} 1533 - 1534 - strip-bom@3.0.0: 1535 - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} 1536 - engines: {node: '>=4'} 1537 - 1538 - strip-json-comments@3.1.1: 1539 - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} 1540 - engines: {node: '>=8'} 1541 - 1542 - supports-color@8.1.1: 1543 - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} 1544 - engines: {node: '>=10'} 1545 - 1546 - supports-preserve-symlinks-flag@1.0.0: 1547 - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 1548 - engines: {node: '>= 0.4'} 1549 - 1550 - svelte-check@4.3.4: 1551 - resolution: {integrity: sha512-DVWvxhBrDsd+0hHWKfjP99lsSXASeOhHJYyuKOFYJcP7ThfSCKgjVarE8XfuMWpS5JV3AlDf+iK1YGGo2TACdw==} 1552 - engines: {node: '>= 18.0.0'} 1553 - hasBin: true 1554 - peerDependencies: 1555 - svelte: ^4.0.0 || ^5.0.0-next.0 1556 - typescript: '>=5.0.0' 1557 - 1558 - svelte@5.45.5: 1559 - resolution: {integrity: sha512-2074U+vObO5Zs8/qhxtBwdi6ZXNIhEBTzNmUFjiZexLxTdt9vq96D/0pnQELl6YcpLMD7pZ2dhXKByfGS8SAdg==} 1560 - engines: {node: '>=18'} 1561 - 1562 - term-size@2.2.1: 1563 - resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} 1564 - engines: {node: '>=8'} 1565 - 1566 - terser@5.44.1: 1567 - resolution: {integrity: sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==} 1568 - engines: {node: '>=10'} 1569 - hasBin: true 1570 - 1571 - tinyglobby@0.2.15: 1572 - resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} 1573 - engines: {node: '>=12.0.0'} 1574 - 1575 - to-regex-range@5.0.1: 1576 - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1577 - engines: {node: '>=8.0'} 1578 - 1579 - tslib@2.8.1: 1580 - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} 1581 - 1582 - typescript@5.8.2: 1583 - resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} 1584 - engines: {node: '>=14.17'} 1585 - hasBin: true 1586 - 1587 - typescript@5.8.3: 1588 - resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} 1589 - engines: {node: '>=14.17'} 1590 - hasBin: true 1591 - 1592 - ufo@1.6.1: 1593 - resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} 1594 - 1595 - undici-types@7.16.0: 1596 - resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} 1597 - 1598 - universalify@0.1.2: 1599 - resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} 1600 - engines: {node: '>= 4.0.0'} 1601 - 1602 - universalify@2.0.1: 1603 - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} 1604 - engines: {node: '>= 10.0.0'} 1605 - 1606 - update-browserslist-db@1.2.1: 1607 - resolution: {integrity: sha512-R9NcHbbZ45RoWfTdhn1J9SS7zxNvlddv4YRrHTUaFdtjbmfncfedB45EC9IaqJQ97iAR1GZgOfyRQO+ExIF6EQ==} 1608 - hasBin: true 1609 - peerDependencies: 1610 - browserslist: '>= 4.21.0' 1611 - 1612 - uri-js@4.4.1: 1613 - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 1614 - 1615 - vite-plugin-dts@4.5.4: 1616 - resolution: {integrity: sha512-d4sOM8M/8z7vRXHHq/ebbblfaxENjogAAekcfcDCCwAyvGqnPrc7f4NZbvItS+g4WTgerW0xDwSz5qz11JT3vg==} 1617 - peerDependencies: 1618 - typescript: '*' 1619 - vite: '*' 1620 - peerDependenciesMeta: 1621 - vite: 1622 - optional: true 1623 - 1624 - vite-prerender-plugin@0.5.12: 1625 - resolution: {integrity: sha512-EiwhbMn+flg14EysbLTmZSzq8NGTxhytgK3bf4aGRF1evWLGwZiHiUJ1KZDvbxgKbMf2pG6fJWGEa3UZXOnR1g==} 1626 - peerDependencies: 1627 - vite: 5.x || 6.x || 7.x 1628 - 1629 - vite@7.2.6: 1630 - resolution: {integrity: sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==} 1631 - engines: {node: ^20.19.0 || >=22.12.0} 1632 - hasBin: true 1633 - peerDependencies: 1634 - '@types/node': ^20.19.0 || >=22.12.0 1635 - jiti: '>=1.21.0' 1636 - less: ^4.0.0 1637 - lightningcss: ^1.21.0 1638 - sass: ^1.70.0 1639 - sass-embedded: ^1.70.0 1640 - stylus: '>=0.54.8' 1641 - sugarss: ^5.0.0 1642 - terser: ^5.16.0 1643 - tsx: ^4.8.1 1644 - yaml: ^2.4.2 1645 - peerDependenciesMeta: 1646 - '@types/node': 1647 - optional: true 1648 - jiti: 1649 - optional: true 1650 - less: 1651 - optional: true 1652 - lightningcss: 1653 - optional: true 1654 - sass: 1655 - optional: true 1656 - sass-embedded: 1657 - optional: true 1658 - stylus: 1659 - optional: true 1660 - sugarss: 1661 - optional: true 1662 - terser: 1663 - optional: true 1664 - tsx: 1665 - optional: true 1666 - yaml: 1667 - optional: true 1668 - 1669 - vitefu@1.1.1: 1670 - resolution: {integrity: sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==} 1671 - peerDependencies: 1672 - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0 1673 - peerDependenciesMeta: 1674 - vite: 1675 - optional: true 1676 - 1677 - vscode-uri@3.1.0: 1678 - resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} 1679 - 1680 - which@2.0.2: 1681 - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1682 - engines: {node: '>= 8'} 1683 - hasBin: true 1684 - 1685 - yallist@3.1.1: 1686 - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} 1687 - 1688 - yallist@4.0.0: 1689 - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 1690 - 1691 - zimmerframe@1.1.4: 1692 - resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==} 1693 - 1694 - snapshots: 1695 - 1696 - '@atcute/atproto@3.1.9': 1697 - dependencies: 1698 - '@atcute/lexicons': 1.2.5 1699 - 1700 - '@atcute/bluesky-richtext-parser@1.0.7': {} 1701 - 1702 - '@atcute/bluesky-richtext-segmenter@2.0.4': 1703 - dependencies: 1704 - '@atcute/bluesky': 3.2.11 1705 - '@atcute/lexicons': 1.2.5 1706 - 1707 - '@atcute/bluesky@2.1.1(@atcute/client@3.1.0)': 1708 - dependencies: 1709 - '@atcute/client': 3.1.0 1710 - 1711 - '@atcute/bluesky@3.2.11': 1712 - dependencies: 1713 - '@atcute/atproto': 3.1.9 1714 - '@atcute/lexicons': 1.2.5 1715 - 1716 - '@atcute/client@3.1.0': {} 1717 - 1718 - '@atcute/lexicons@1.2.5': 1719 - dependencies: 1720 - '@standard-schema/spec': 1.0.0 1721 - esm-env: 1.2.2 1722 - 1723 - '@babel/code-frame@7.27.1': 1724 - dependencies: 1725 - '@babel/helper-validator-identifier': 7.28.5 1726 - js-tokens: 4.0.0 1727 - picocolors: 1.1.1 1728 - 1729 - '@babel/compat-data@7.28.5': {} 1730 - 1731 - '@babel/core@7.28.5': 1732 - dependencies: 1733 - '@babel/code-frame': 7.27.1 1734 - '@babel/generator': 7.28.5 1735 - '@babel/helper-compilation-targets': 7.27.2 1736 - '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) 1737 - '@babel/helpers': 7.28.4 1738 - '@babel/parser': 7.28.5 1739 - '@babel/template': 7.27.2 1740 - '@babel/traverse': 7.28.5 1741 - '@babel/types': 7.28.5 1742 - '@jridgewell/remapping': 2.3.5 1743 - convert-source-map: 2.0.0 1744 - debug: 4.4.3 1745 - gensync: 1.0.0-beta.2 1746 - json5: 2.2.3 1747 - semver: 6.3.1 1748 - transitivePeerDependencies: 1749 - - supports-color 1750 - 1751 - '@babel/generator@7.28.5': 1752 - dependencies: 1753 - '@babel/parser': 7.28.5 1754 - '@babel/types': 7.28.5 1755 - '@jridgewell/gen-mapping': 0.3.13 1756 - '@jridgewell/trace-mapping': 0.3.31 1757 - jsesc: 3.1.0 1758 - 1759 - '@babel/helper-annotate-as-pure@7.27.3': 1760 - dependencies: 1761 - '@babel/types': 7.28.5 1762 - 1763 - '@babel/helper-compilation-targets@7.27.2': 1764 - dependencies: 1765 - '@babel/compat-data': 7.28.5 1766 - '@babel/helper-validator-option': 7.27.1 1767 - browserslist: 4.28.1 1768 - lru-cache: 5.1.1 1769 - semver: 6.3.1 1770 - 1771 - '@babel/helper-globals@7.28.0': {} 1772 - 1773 - '@babel/helper-module-imports@7.27.1': 1774 - dependencies: 1775 - '@babel/traverse': 7.28.5 1776 - '@babel/types': 7.28.5 1777 - transitivePeerDependencies: 1778 - - supports-color 1779 - 1780 - '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': 1781 - dependencies: 1782 - '@babel/core': 7.28.5 1783 - '@babel/helper-module-imports': 7.27.1 1784 - '@babel/helper-validator-identifier': 7.28.5 1785 - '@babel/traverse': 7.28.5 1786 - transitivePeerDependencies: 1787 - - supports-color 1788 - 1789 - '@babel/helper-plugin-utils@7.27.1': {} 1790 - 1791 - '@babel/helper-string-parser@7.27.1': {} 1792 - 1793 - '@babel/helper-validator-identifier@7.28.5': {} 1794 - 1795 - '@babel/helper-validator-option@7.27.1': {} 1796 - 1797 - '@babel/helpers@7.28.4': 1798 - dependencies: 1799 - '@babel/template': 7.27.2 1800 - '@babel/types': 7.28.5 1801 - 1802 - '@babel/parser@7.28.5': 1803 - dependencies: 1804 - '@babel/types': 7.28.5 1805 - 1806 - '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.5)': 1807 - dependencies: 1808 - '@babel/core': 7.28.5 1809 - '@babel/helper-plugin-utils': 7.27.1 1810 - 1811 - '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.28.5)': 1812 - dependencies: 1813 - '@babel/core': 7.28.5 1814 - '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.5) 1815 - transitivePeerDependencies: 1816 - - supports-color 1817 - 1818 - '@babel/plugin-transform-react-jsx@7.27.1(@babel/core@7.28.5)': 1819 - dependencies: 1820 - '@babel/core': 7.28.5 1821 - '@babel/helper-annotate-as-pure': 7.27.3 1822 - '@babel/helper-module-imports': 7.27.1 1823 - '@babel/helper-plugin-utils': 7.27.1 1824 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.5) 1825 - '@babel/types': 7.28.5 1826 - transitivePeerDependencies: 1827 - - supports-color 1828 - 1829 - '@babel/runtime@7.28.4': {} 1830 - 1831 - '@babel/template@7.27.2': 1832 - dependencies: 1833 - '@babel/code-frame': 7.27.1 1834 - '@babel/parser': 7.28.5 1835 - '@babel/types': 7.28.5 1836 - 1837 - '@babel/traverse@7.28.5': 1838 - dependencies: 1839 - '@babel/code-frame': 7.27.1 1840 - '@babel/generator': 7.28.5 1841 - '@babel/helper-globals': 7.28.0 1842 - '@babel/parser': 7.28.5 1843 - '@babel/template': 7.27.2 1844 - '@babel/types': 7.28.5 1845 - debug: 4.4.3 1846 - transitivePeerDependencies: 1847 - - supports-color 1848 - 1849 - '@babel/types@7.28.5': 1850 - dependencies: 1851 - '@babel/helper-string-parser': 7.27.1 1852 - '@babel/helper-validator-identifier': 7.28.5 1853 - 1854 - '@changesets/apply-release-plan@7.0.14': 1855 - dependencies: 1856 - '@changesets/config': 3.1.2 1857 - '@changesets/get-version-range-type': 0.4.0 1858 - '@changesets/git': 3.0.4 1859 - '@changesets/should-skip-package': 0.1.2 1860 - '@changesets/types': 6.1.0 1861 - '@manypkg/get-packages': 1.1.3 1862 - detect-indent: 6.1.0 1863 - fs-extra: 7.0.1 1864 - lodash.startcase: 4.4.0 1865 - outdent: 0.5.0 1866 - prettier: 2.8.8 1867 - resolve-from: 5.0.0 1868 - semver: 7.7.3 1869 - 1870 - '@changesets/assemble-release-plan@6.0.9': 1871 - dependencies: 1872 - '@changesets/errors': 0.2.0 1873 - '@changesets/get-dependents-graph': 2.1.3 1874 - '@changesets/should-skip-package': 0.1.2 1875 - '@changesets/types': 6.1.0 1876 - '@manypkg/get-packages': 1.1.3 1877 - semver: 7.7.3 1878 - 1879 - '@changesets/changelog-git@0.2.1': 1880 - dependencies: 1881 - '@changesets/types': 6.1.0 1882 - 1883 - '@changesets/cli@2.29.8(@types/node@24.10.1)': 1884 - dependencies: 1885 - '@changesets/apply-release-plan': 7.0.14 1886 - '@changesets/assemble-release-plan': 6.0.9 1887 - '@changesets/changelog-git': 0.2.1 1888 - '@changesets/config': 3.1.2 1889 - '@changesets/errors': 0.2.0 1890 - '@changesets/get-dependents-graph': 2.1.3 1891 - '@changesets/get-release-plan': 4.0.14 1892 - '@changesets/git': 3.0.4 1893 - '@changesets/logger': 0.1.1 1894 - '@changesets/pre': 2.0.2 1895 - '@changesets/read': 0.6.6 1896 - '@changesets/should-skip-package': 0.1.2 1897 - '@changesets/types': 6.1.0 1898 - '@changesets/write': 0.4.0 1899 - '@inquirer/external-editor': 1.0.3(@types/node@24.10.1) 1900 - '@manypkg/get-packages': 1.1.3 1901 - ansi-colors: 4.1.3 1902 - ci-info: 3.9.0 1903 - enquirer: 2.4.1 1904 - fs-extra: 7.0.1 1905 - mri: 1.2.0 1906 - p-limit: 2.3.0 1907 - package-manager-detector: 0.2.11 1908 - picocolors: 1.1.1 1909 - resolve-from: 5.0.0 1910 - semver: 7.7.3 1911 - spawndamnit: 3.0.1 1912 - term-size: 2.2.1 1913 - transitivePeerDependencies: 1914 - - '@types/node' 1915 - 1916 - '@changesets/config@3.1.2': 1917 - dependencies: 1918 - '@changesets/errors': 0.2.0 1919 - '@changesets/get-dependents-graph': 2.1.3 1920 - '@changesets/logger': 0.1.1 1921 - '@changesets/types': 6.1.0 1922 - '@manypkg/get-packages': 1.1.3 1923 - fs-extra: 7.0.1 1924 - micromatch: 4.0.8 1925 - 1926 - '@changesets/errors@0.2.0': 1927 - dependencies: 1928 - extendable-error: 0.1.7 1929 - 1930 - '@changesets/get-dependents-graph@2.1.3': 1931 - dependencies: 1932 - '@changesets/types': 6.1.0 1933 - '@manypkg/get-packages': 1.1.3 1934 - picocolors: 1.1.1 1935 - semver: 7.7.3 1936 - 1937 - '@changesets/get-release-plan@4.0.14': 1938 - dependencies: 1939 - '@changesets/assemble-release-plan': 6.0.9 1940 - '@changesets/config': 3.1.2 1941 - '@changesets/pre': 2.0.2 1942 - '@changesets/read': 0.6.6 1943 - '@changesets/types': 6.1.0 1944 - '@manypkg/get-packages': 1.1.3 1945 - 1946 - '@changesets/get-version-range-type@0.4.0': {} 1947 - 1948 - '@changesets/git@3.0.4': 1949 - dependencies: 1950 - '@changesets/errors': 0.2.0 1951 - '@manypkg/get-packages': 1.1.3 1952 - is-subdir: 1.2.0 1953 - micromatch: 4.0.8 1954 - spawndamnit: 3.0.1 1955 - 1956 - '@changesets/logger@0.1.1': 1957 - dependencies: 1958 - picocolors: 1.1.1 1959 - 1960 - '@changesets/parse@0.4.2': 1961 - dependencies: 1962 - '@changesets/types': 6.1.0 1963 - js-yaml: 4.1.1 1964 - 1965 - '@changesets/pre@2.0.2': 1966 - dependencies: 1967 - '@changesets/errors': 0.2.0 1968 - '@changesets/types': 6.1.0 1969 - '@manypkg/get-packages': 1.1.3 1970 - fs-extra: 7.0.1 1971 - 1972 - '@changesets/read@0.6.6': 1973 - dependencies: 1974 - '@changesets/git': 3.0.4 1975 - '@changesets/logger': 0.1.1 1976 - '@changesets/parse': 0.4.2 1977 - '@changesets/types': 6.1.0 1978 - fs-extra: 7.0.1 1979 - p-filter: 2.1.0 1980 - picocolors: 1.1.1 1981 - 1982 - '@changesets/should-skip-package@0.1.2': 1983 - dependencies: 1984 - '@changesets/types': 6.1.0 1985 - '@manypkg/get-packages': 1.1.3 1986 - 1987 - '@changesets/types@4.1.0': {} 1988 - 1989 - '@changesets/types@6.1.0': {} 1990 - 1991 - '@changesets/write@0.4.0': 1992 - dependencies: 1993 - '@changesets/types': 6.1.0 1994 - fs-extra: 7.0.1 1995 - human-id: 4.1.3 1996 - prettier: 2.8.8 1997 - 1998 - '@esbuild/aix-ppc64@0.25.12': 1999 - optional: true 2000 - 2001 - '@esbuild/android-arm64@0.25.12': 2002 - optional: true 2003 - 2004 - '@esbuild/android-arm@0.25.12': 2005 - optional: true 2006 - 2007 - '@esbuild/android-x64@0.25.12': 2008 - optional: true 2009 - 2010 - '@esbuild/darwin-arm64@0.25.12': 2011 - optional: true 2012 - 2013 - '@esbuild/darwin-x64@0.25.12': 2014 - optional: true 2015 - 2016 - '@esbuild/freebsd-arm64@0.25.12': 2017 - optional: true 2018 - 2019 - '@esbuild/freebsd-x64@0.25.12': 2020 - optional: true 2021 - 2022 - '@esbuild/linux-arm64@0.25.12': 2023 - optional: true 2024 - 2025 - '@esbuild/linux-arm@0.25.12': 2026 - optional: true 2027 - 2028 - '@esbuild/linux-ia32@0.25.12': 2029 - optional: true 2030 - 2031 - '@esbuild/linux-loong64@0.25.12': 2032 - optional: true 2033 - 2034 - '@esbuild/linux-mips64el@0.25.12': 2035 - optional: true 2036 - 2037 - '@esbuild/linux-ppc64@0.25.12': 2038 - optional: true 2039 - 2040 - '@esbuild/linux-riscv64@0.25.12': 2041 - optional: true 2042 - 2043 - '@esbuild/linux-s390x@0.25.12': 2044 - optional: true 2045 - 2046 - '@esbuild/linux-x64@0.25.12': 2047 - optional: true 2048 - 2049 - '@esbuild/netbsd-arm64@0.25.12': 2050 - optional: true 2051 - 2052 - '@esbuild/netbsd-x64@0.25.12': 2053 - optional: true 2054 - 2055 - '@esbuild/openbsd-arm64@0.25.12': 2056 - optional: true 2057 - 2058 - '@esbuild/openbsd-x64@0.25.12': 2059 - optional: true 2060 - 2061 - '@esbuild/openharmony-arm64@0.25.12': 2062 - optional: true 2063 - 2064 - '@esbuild/sunos-x64@0.25.12': 2065 - optional: true 2066 - 2067 - '@esbuild/win32-arm64@0.25.12': 2068 - optional: true 2069 - 2070 - '@esbuild/win32-ia32@0.25.12': 2071 - optional: true 2072 - 2073 - '@esbuild/win32-x64@0.25.12': 2074 - optional: true 2075 - 2076 - '@inquirer/external-editor@1.0.3(@types/node@24.10.1)': 2077 - dependencies: 2078 - chardet: 2.1.1 2079 - iconv-lite: 0.7.0 2080 - optionalDependencies: 2081 - '@types/node': 24.10.1 2082 - 2083 - '@isaacs/balanced-match@4.0.1': {} 2084 - 2085 - '@isaacs/brace-expansion@5.0.0': 2086 - dependencies: 2087 - '@isaacs/balanced-match': 4.0.1 2088 - 2089 - '@jridgewell/gen-mapping@0.3.13': 2090 - dependencies: 2091 - '@jridgewell/sourcemap-codec': 1.5.5 2092 - '@jridgewell/trace-mapping': 0.3.31 2093 - 2094 - '@jridgewell/remapping@2.3.5': 2095 - dependencies: 2096 - '@jridgewell/gen-mapping': 0.3.13 2097 - '@jridgewell/trace-mapping': 0.3.31 2098 - 2099 - '@jridgewell/resolve-uri@3.1.2': {} 2100 - 2101 - '@jridgewell/source-map@0.3.11': 2102 - dependencies: 2103 - '@jridgewell/gen-mapping': 0.3.13 2104 - '@jridgewell/trace-mapping': 0.3.31 2105 - 2106 - '@jridgewell/sourcemap-codec@1.5.5': {} 2107 - 2108 - '@jridgewell/trace-mapping@0.3.31': 2109 - dependencies: 2110 - '@jridgewell/resolve-uri': 3.1.2 2111 - '@jridgewell/sourcemap-codec': 1.5.5 2112 - 2113 - '@manypkg/find-root@1.1.0': 2114 - dependencies: 2115 - '@babel/runtime': 7.28.4 2116 - '@types/node': 12.20.55 2117 - find-up: 4.1.0 2118 - fs-extra: 8.1.0 2119 - 2120 - '@manypkg/get-packages@1.1.3': 2121 - dependencies: 2122 - '@babel/runtime': 7.28.4 2123 - '@changesets/types': 4.1.0 2124 - '@manypkg/find-root': 1.1.0 2125 - fs-extra: 8.1.0 2126 - globby: 11.1.0 2127 - read-yaml-file: 1.1.0 2128 - 2129 - '@microsoft/api-extractor-model@7.32.1(@types/node@24.10.1)': 2130 - dependencies: 2131 - '@microsoft/tsdoc': 0.16.0 2132 - '@microsoft/tsdoc-config': 0.18.0 2133 - '@rushstack/node-core-library': 5.19.0(@types/node@24.10.1) 2134 - transitivePeerDependencies: 2135 - - '@types/node' 2136 - 2137 - '@microsoft/api-extractor@7.55.1(@types/node@24.10.1)': 2138 - dependencies: 2139 - '@microsoft/api-extractor-model': 7.32.1(@types/node@24.10.1) 2140 - '@microsoft/tsdoc': 0.16.0 2141 - '@microsoft/tsdoc-config': 0.18.0 2142 - '@rushstack/node-core-library': 5.19.0(@types/node@24.10.1) 2143 - '@rushstack/rig-package': 0.6.0 2144 - '@rushstack/terminal': 0.19.4(@types/node@24.10.1) 2145 - '@rushstack/ts-command-line': 5.1.4(@types/node@24.10.1) 2146 - diff: 8.0.2 2147 - lodash: 4.17.21 2148 - minimatch: 10.0.3 2149 - resolve: 1.22.11 2150 - semver: 7.5.4 2151 - source-map: 0.6.1 2152 - typescript: 5.8.2 2153 - transitivePeerDependencies: 2154 - - '@types/node' 2155 - 2156 - '@microsoft/tsdoc-config@0.18.0': 2157 - dependencies: 2158 - '@microsoft/tsdoc': 0.16.0 2159 - ajv: 8.12.0 2160 - jju: 1.4.0 2161 - resolve: 1.22.11 2162 - 2163 - '@microsoft/tsdoc@0.16.0': {} 2164 - 2165 - '@nodelib/fs.scandir@2.1.5': 2166 - dependencies: 2167 - '@nodelib/fs.stat': 2.0.5 2168 - run-parallel: 1.2.0 2169 - 2170 - '@nodelib/fs.stat@2.0.5': {} 2171 - 2172 - '@nodelib/fs.walk@1.2.8': 2173 - dependencies: 2174 - '@nodelib/fs.scandir': 2.1.5 2175 - fastq: 1.19.1 2176 - 2177 - '@preact/preset-vite@2.10.2(@babel/core@7.28.5)(preact@10.28.0)(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1))': 2178 - dependencies: 2179 - '@babel/core': 7.28.5 2180 - '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.5) 2181 - '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.28.5) 2182 - '@prefresh/vite': 2.4.11(preact@10.28.0)(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)) 2183 - '@rollup/pluginutils': 4.2.1 2184 - babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.28.5) 2185 - debug: 4.4.3 2186 - picocolors: 1.1.1 2187 - vite: 7.2.6(@types/node@24.10.1)(terser@5.44.1) 2188 - vite-prerender-plugin: 0.5.12(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)) 2189 - transitivePeerDependencies: 2190 - - preact 2191 - - supports-color 2192 - 2193 - '@prefresh/babel-plugin@0.5.2': {} 2194 - 2195 - '@prefresh/core@1.5.9(preact@10.28.0)': 2196 - dependencies: 2197 - preact: 10.28.0 2198 - 2199 - '@prefresh/utils@1.2.1': {} 2200 - 2201 - '@prefresh/vite@2.4.11(preact@10.28.0)(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1))': 2202 - dependencies: 2203 - '@babel/core': 7.28.5 2204 - '@prefresh/babel-plugin': 0.5.2 2205 - '@prefresh/core': 1.5.9(preact@10.28.0) 2206 - '@prefresh/utils': 1.2.1 2207 - '@rollup/pluginutils': 4.2.1 2208 - preact: 10.28.0 2209 - vite: 7.2.6(@types/node@24.10.1)(terser@5.44.1) 2210 - transitivePeerDependencies: 2211 - - supports-color 2212 - 2213 - '@rollup/pluginutils@4.2.1': 2214 - dependencies: 2215 - estree-walker: 2.0.2 2216 - picomatch: 2.3.1 2217 - 2218 - '@rollup/pluginutils@5.3.0(rollup@4.53.3)': 2219 - dependencies: 2220 - '@types/estree': 1.0.8 2221 - estree-walker: 2.0.2 2222 - picomatch: 4.0.3 2223 - optionalDependencies: 2224 - rollup: 4.53.3 2225 - 2226 - '@rollup/rollup-android-arm-eabi@4.53.3': 2227 - optional: true 2228 - 2229 - '@rollup/rollup-android-arm64@4.53.3': 2230 - optional: true 2231 - 2232 - '@rollup/rollup-darwin-arm64@4.53.3': 2233 - optional: true 2234 - 2235 - '@rollup/rollup-darwin-x64@4.53.3': 2236 - optional: true 2237 - 2238 - '@rollup/rollup-freebsd-arm64@4.53.3': 2239 - optional: true 2240 - 2241 - '@rollup/rollup-freebsd-x64@4.53.3': 2242 - optional: true 2243 - 2244 - '@rollup/rollup-linux-arm-gnueabihf@4.53.3': 2245 - optional: true 2246 - 2247 - '@rollup/rollup-linux-arm-musleabihf@4.53.3': 2248 - optional: true 2249 - 2250 - '@rollup/rollup-linux-arm64-gnu@4.53.3': 2251 - optional: true 2252 - 2253 - '@rollup/rollup-linux-arm64-musl@4.53.3': 2254 - optional: true 2255 - 2256 - '@rollup/rollup-linux-loong64-gnu@4.53.3': 2257 - optional: true 2258 - 2259 - '@rollup/rollup-linux-ppc64-gnu@4.53.3': 2260 - optional: true 2261 - 2262 - '@rollup/rollup-linux-riscv64-gnu@4.53.3': 2263 - optional: true 2264 - 2265 - '@rollup/rollup-linux-riscv64-musl@4.53.3': 2266 - optional: true 2267 - 2268 - '@rollup/rollup-linux-s390x-gnu@4.53.3': 2269 - optional: true 2270 - 2271 - '@rollup/rollup-linux-x64-gnu@4.53.3': 2272 - optional: true 2273 - 2274 - '@rollup/rollup-linux-x64-musl@4.53.3': 2275 - optional: true 2276 - 2277 - '@rollup/rollup-openharmony-arm64@4.53.3': 2278 - optional: true 2279 - 2280 - '@rollup/rollup-win32-arm64-msvc@4.53.3': 2281 - optional: true 2282 - 2283 - '@rollup/rollup-win32-ia32-msvc@4.53.3': 2284 - optional: true 2285 - 2286 - '@rollup/rollup-win32-x64-gnu@4.53.3': 2287 - optional: true 2288 - 2289 - '@rollup/rollup-win32-x64-msvc@4.53.3': 2290 - optional: true 2291 - 2292 - '@rushstack/node-core-library@5.19.0(@types/node@24.10.1)': 2293 - dependencies: 2294 - ajv: 8.13.0 2295 - ajv-draft-04: 1.0.0(ajv@8.13.0) 2296 - ajv-formats: 3.0.1(ajv@8.13.0) 2297 - fs-extra: 11.3.2 2298 - import-lazy: 4.0.0 2299 - jju: 1.4.0 2300 - resolve: 1.22.11 2301 - semver: 7.5.4 2302 - optionalDependencies: 2303 - '@types/node': 24.10.1 2304 - 2305 - '@rushstack/problem-matcher@0.1.1(@types/node@24.10.1)': 2306 - optionalDependencies: 2307 - '@types/node': 24.10.1 2308 - 2309 - '@rushstack/rig-package@0.6.0': 2310 - dependencies: 2311 - resolve: 1.22.11 2312 - strip-json-comments: 3.1.1 2313 - 2314 - '@rushstack/terminal@0.19.4(@types/node@24.10.1)': 2315 - dependencies: 2316 - '@rushstack/node-core-library': 5.19.0(@types/node@24.10.1) 2317 - '@rushstack/problem-matcher': 0.1.1(@types/node@24.10.1) 2318 - supports-color: 8.1.1 2319 - optionalDependencies: 2320 - '@types/node': 24.10.1 2321 - 2322 - '@rushstack/ts-command-line@5.1.4(@types/node@24.10.1)': 2323 - dependencies: 2324 - '@rushstack/terminal': 0.19.4(@types/node@24.10.1) 2325 - '@types/argparse': 1.0.38 2326 - argparse: 1.0.10 2327 - string-argv: 0.3.2 2328 - transitivePeerDependencies: 2329 - - '@types/node' 2330 - 2331 - '@standard-schema/spec@1.0.0': {} 2332 - 2333 - '@sveltejs/acorn-typescript@1.0.8(acorn@8.15.0)': 2334 - dependencies: 2335 - acorn: 8.15.0 2336 - 2337 - '@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd))(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)))(svelte@5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd))(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1))': 2338 - dependencies: 2339 - '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd))(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)) 2340 - debug: 4.4.3 2341 - svelte: 5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd) 2342 - vite: 7.2.6(@types/node@24.10.1)(terser@5.44.1) 2343 - transitivePeerDependencies: 2344 - - supports-color 2345 - 2346 - '@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd))(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1))': 2347 - dependencies: 2348 - '@sveltejs/vite-plugin-svelte-inspector': 5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd))(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)))(svelte@5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd))(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)) 2349 - debug: 4.4.3 2350 - deepmerge: 4.3.1 2351 - magic-string: 0.30.21 2352 - svelte: 5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd) 2353 - vite: 7.2.6(@types/node@24.10.1)(terser@5.44.1) 2354 - vitefu: 1.1.1(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)) 2355 - transitivePeerDependencies: 2356 - - supports-color 2357 - 2358 - '@tsconfig/svelte@5.0.6': {} 2359 - 2360 - '@types/argparse@1.0.38': {} 2361 - 2362 - '@types/estree@1.0.8': {} 2363 - 2364 - '@types/node@12.20.55': {} 2365 - 2366 - '@types/node@24.10.1': 2367 - dependencies: 2368 - undici-types: 7.16.0 2369 - 2370 - '@volar/language-core@2.4.26': 2371 - dependencies: 2372 - '@volar/source-map': 2.4.26 2373 - 2374 - '@volar/source-map@2.4.26': {} 2375 - 2376 - '@volar/typescript@2.4.26': 2377 - dependencies: 2378 - '@volar/language-core': 2.4.26 2379 - path-browserify: 1.0.1 2380 - vscode-uri: 3.1.0 2381 - 2382 - '@vue/compiler-core@3.5.25': 2383 - dependencies: 2384 - '@babel/parser': 7.28.5 2385 - '@vue/shared': 3.5.25 2386 - entities: 4.5.0 2387 - estree-walker: 2.0.2 2388 - source-map-js: 1.2.1 2389 - 2390 - '@vue/compiler-dom@3.5.25': 2391 - dependencies: 2392 - '@vue/compiler-core': 3.5.25 2393 - '@vue/shared': 3.5.25 2394 - 2395 - '@vue/compiler-vue2@2.7.16': 2396 - dependencies: 2397 - de-indent: 1.0.2 2398 - he: 1.2.0 2399 - 2400 - '@vue/language-core@2.2.0(typescript@5.8.3)': 2401 - dependencies: 2402 - '@volar/language-core': 2.4.26 2403 - '@vue/compiler-dom': 3.5.25 2404 - '@vue/compiler-vue2': 2.7.16 2405 - '@vue/shared': 3.5.25 2406 - alien-signals: 0.4.14 2407 - minimatch: 9.0.5 2408 - muggle-string: 0.4.1 2409 - path-browserify: 1.0.1 2410 - optionalDependencies: 2411 - typescript: 5.8.3 2412 - 2413 - '@vue/shared@3.5.25': {} 2414 - 2415 - acorn@8.15.0: {} 2416 - 2417 - ajv-draft-04@1.0.0(ajv@8.13.0): 2418 - optionalDependencies: 2419 - ajv: 8.13.0 2420 - 2421 - ajv-formats@3.0.1(ajv@8.13.0): 2422 - optionalDependencies: 2423 - ajv: 8.13.0 2424 - 2425 - ajv@8.12.0: 2426 - dependencies: 2427 - fast-deep-equal: 3.1.3 2428 - json-schema-traverse: 1.0.0 2429 - require-from-string: 2.0.2 2430 - uri-js: 4.4.1 2431 - 2432 - ajv@8.13.0: 2433 - dependencies: 2434 - fast-deep-equal: 3.1.3 2435 - json-schema-traverse: 1.0.0 2436 - require-from-string: 2.0.2 2437 - uri-js: 4.4.1 2438 - 2439 - alien-signals@0.4.14: {} 2440 - 2441 - ansi-colors@4.1.3: {} 2442 - 2443 - ansi-regex@5.0.1: {} 2444 - 2445 - argparse@1.0.10: 2446 - dependencies: 2447 - sprintf-js: 1.0.3 2448 - 2449 - argparse@2.0.1: {} 2450 - 2451 - aria-query@5.3.2: {} 2452 - 2453 - array-union@2.1.0: {} 2454 - 2455 - axobject-query@4.1.0: {} 2456 - 2457 - babel-plugin-transform-hook-names@1.0.2(@babel/core@7.28.5): 2458 - dependencies: 2459 - '@babel/core': 7.28.5 2460 - 2461 - balanced-match@1.0.2: {} 2462 - 2463 - baseline-browser-mapping@2.9.0: {} 2464 - 2465 - better-path-resolve@1.0.0: 2466 - dependencies: 2467 - is-windows: 1.0.2 2468 - 2469 - boolbase@1.0.0: {} 2470 - 2471 - brace-expansion@2.0.2: 2472 - dependencies: 2473 - balanced-match: 1.0.2 2474 - 2475 - braces@3.0.3: 2476 - dependencies: 2477 - fill-range: 7.1.1 2478 - 2479 - browserslist@4.28.1: 2480 - dependencies: 2481 - baseline-browser-mapping: 2.9.0 2482 - caniuse-lite: 1.0.30001759 2483 - electron-to-chromium: 1.5.264 2484 - node-releases: 2.0.27 2485 - update-browserslist-db: 1.2.1(browserslist@4.28.1) 2486 - 2487 - buffer-from@1.1.2: {} 2488 - 2489 - caniuse-lite@1.0.30001759: {} 2490 - 2491 - chardet@2.1.1: {} 2492 - 2493 - chokidar@4.0.3: 2494 - dependencies: 2495 - readdirp: 4.1.2 2496 - 2497 - ci-info@3.9.0: {} 2498 - 2499 - clsx@2.1.1: {} 2500 - 2501 - commander@2.20.3: {} 2502 - 2503 - compare-versions@6.1.1: {} 2504 - 2505 - confbox@0.1.8: {} 2506 - 2507 - confbox@0.2.2: {} 2508 - 2509 - convert-source-map@2.0.0: {} 2510 - 2511 - cross-spawn@7.0.6: 2512 - dependencies: 2513 - path-key: 3.1.1 2514 - shebang-command: 2.0.0 2515 - which: 2.0.2 2516 - 2517 - css-declaration-sorter@7.3.0(postcss@8.5.6): 2518 - dependencies: 2519 - postcss: 8.5.6 2520 - 2521 - css-select@5.2.2: 2522 - dependencies: 2523 - boolbase: 1.0.0 2524 - css-what: 6.2.2 2525 - domhandler: 5.0.3 2526 - domutils: 3.2.2 2527 - nth-check: 2.1.1 2528 - 2529 - css-what@6.2.2: {} 2530 - 2531 - de-indent@1.0.2: {} 2532 - 2533 - debug@4.4.3: 2534 - dependencies: 2535 - ms: 2.1.3 2536 - 2537 - deepmerge@4.3.1: {} 2538 - 2539 - detect-indent@6.1.0: {} 2540 - 2541 - devalue@5.5.0: {} 2542 - 2543 - diff@8.0.2: {} 2544 - 2545 - dir-glob@3.0.1: 2546 - dependencies: 2547 - path-type: 4.0.0 2548 - 2549 - dom-serializer@2.0.0: 2550 - dependencies: 2551 - domelementtype: 2.3.0 2552 - domhandler: 5.0.3 2553 - entities: 4.5.0 2554 - 2555 - domelementtype@2.3.0: {} 2556 - 2557 - domhandler@5.0.3: 2558 - dependencies: 2559 - domelementtype: 2.3.0 2560 - 2561 - domutils@3.2.2: 2562 - dependencies: 2563 - dom-serializer: 2.0.0 2564 - domelementtype: 2.3.0 2565 - domhandler: 5.0.3 2566 - 2567 - electron-to-chromium@1.5.264: {} 2568 - 2569 - enquirer@2.4.1: 2570 - dependencies: 2571 - ansi-colors: 4.1.3 2572 - strip-ansi: 6.0.1 2573 - 2574 - entities@4.5.0: {} 2575 - 2576 - esbuild@0.25.12: 2577 - optionalDependencies: 2578 - '@esbuild/aix-ppc64': 0.25.12 2579 - '@esbuild/android-arm': 0.25.12 2580 - '@esbuild/android-arm64': 0.25.12 2581 - '@esbuild/android-x64': 0.25.12 2582 - '@esbuild/darwin-arm64': 0.25.12 2583 - '@esbuild/darwin-x64': 0.25.12 2584 - '@esbuild/freebsd-arm64': 0.25.12 2585 - '@esbuild/freebsd-x64': 0.25.12 2586 - '@esbuild/linux-arm': 0.25.12 2587 - '@esbuild/linux-arm64': 0.25.12 2588 - '@esbuild/linux-ia32': 0.25.12 2589 - '@esbuild/linux-loong64': 0.25.12 2590 - '@esbuild/linux-mips64el': 0.25.12 2591 - '@esbuild/linux-ppc64': 0.25.12 2592 - '@esbuild/linux-riscv64': 0.25.12 2593 - '@esbuild/linux-s390x': 0.25.12 2594 - '@esbuild/linux-x64': 0.25.12 2595 - '@esbuild/netbsd-arm64': 0.25.12 2596 - '@esbuild/netbsd-x64': 0.25.12 2597 - '@esbuild/openbsd-arm64': 0.25.12 2598 - '@esbuild/openbsd-x64': 0.25.12 2599 - '@esbuild/openharmony-arm64': 0.25.12 2600 - '@esbuild/sunos-x64': 0.25.12 2601 - '@esbuild/win32-arm64': 0.25.12 2602 - '@esbuild/win32-ia32': 0.25.12 2603 - '@esbuild/win32-x64': 0.25.12 2604 - 2605 - escalade@3.2.0: {} 2606 - 2607 - esm-env@1.2.2: {} 2608 - 2609 - esprima@4.0.1: {} 2610 - 2611 - esrap@2.2.1: 2612 - dependencies: 2613 - '@jridgewell/sourcemap-codec': 1.5.5 2614 - 2615 - estree-walker@2.0.2: {} 2616 - 2617 - exsolve@1.0.8: {} 2618 - 2619 - extendable-error@0.1.7: {} 2620 - 2621 - fast-deep-equal@3.1.3: {} 2622 - 2623 - fast-glob@3.3.3: 2624 - dependencies: 2625 - '@nodelib/fs.stat': 2.0.5 2626 - '@nodelib/fs.walk': 1.2.8 2627 - glob-parent: 5.1.2 2628 - merge2: 1.4.1 2629 - micromatch: 4.0.8 2630 - 2631 - fastq@1.19.1: 2632 - dependencies: 2633 - reusify: 1.1.0 2634 - 2635 - fdir@6.5.0(picomatch@4.0.3): 2636 - optionalDependencies: 2637 - picomatch: 4.0.3 2638 - 2639 - fill-range@7.1.1: 2640 - dependencies: 2641 - to-regex-range: 5.0.1 2642 - 2643 - find-up@4.1.0: 2644 - dependencies: 2645 - locate-path: 5.0.0 2646 - path-exists: 4.0.0 2647 - 2648 - fs-extra@11.3.2: 2649 - dependencies: 2650 - graceful-fs: 4.2.11 2651 - jsonfile: 6.2.0 2652 - universalify: 2.0.1 2653 - 2654 - fs-extra@7.0.1: 2655 - dependencies: 2656 - graceful-fs: 4.2.11 2657 - jsonfile: 4.0.0 2658 - universalify: 0.1.2 2659 - 2660 - fs-extra@8.1.0: 2661 - dependencies: 2662 - graceful-fs: 4.2.11 2663 - jsonfile: 4.0.0 2664 - universalify: 0.1.2 2665 - 2666 - fsevents@2.3.3: 2667 - optional: true 2668 - 2669 - function-bind@1.1.2: {} 2670 - 2671 - gensync@1.0.0-beta.2: {} 2672 - 2673 - glob-parent@5.1.2: 2674 - dependencies: 2675 - is-glob: 4.0.3 2676 - 2677 - globby@11.1.0: 2678 - dependencies: 2679 - array-union: 2.1.0 2680 - dir-glob: 3.0.1 2681 - fast-glob: 3.3.3 2682 - ignore: 5.3.2 2683 - merge2: 1.4.1 2684 - slash: 3.0.0 2685 - 2686 - graceful-fs@4.2.11: {} 2687 - 2688 - has-flag@4.0.0: {} 2689 - 2690 - hasown@2.0.2: 2691 - dependencies: 2692 - function-bind: 1.1.2 2693 - 2694 - he@1.2.0: {} 2695 - 2696 - human-id@4.1.3: {} 2697 - 2698 - iconv-lite@0.7.0: 2699 - dependencies: 2700 - safer-buffer: 2.1.2 2701 - 2702 - ignore@5.3.2: {} 2703 - 2704 - import-lazy@4.0.0: {} 2705 - 2706 - is-core-module@2.16.1: 2707 - dependencies: 2708 - hasown: 2.0.2 2709 - 2710 - is-extglob@2.1.1: {} 2711 - 2712 - is-glob@4.0.3: 2713 - dependencies: 2714 - is-extglob: 2.1.1 2715 - 2716 - is-number@7.0.0: {} 2717 - 2718 - is-reference@3.0.3: 2719 - dependencies: 2720 - '@types/estree': 1.0.8 2721 - 2722 - is-subdir@1.2.0: 2723 - dependencies: 2724 - better-path-resolve: 1.0.0 2725 - 2726 - is-windows@1.0.2: {} 2727 - 2728 - isexe@2.0.0: {} 2729 - 2730 - jju@1.4.0: {} 2731 - 2732 - js-tokens@4.0.0: {} 2733 - 2734 - js-yaml@3.14.2: 2735 - dependencies: 2736 - argparse: 1.0.10 2737 - esprima: 4.0.1 2738 - 2739 - js-yaml@4.1.1: 2740 - dependencies: 2741 - argparse: 2.0.1 2742 - 2743 - jsesc@3.1.0: {} 2744 - 2745 - json-schema-traverse@1.0.0: {} 2746 - 2747 - json5@2.2.3: {} 2748 - 2749 - jsonfile@4.0.0: 2750 - optionalDependencies: 2751 - graceful-fs: 4.2.11 2752 - 2753 - jsonfile@6.2.0: 2754 - dependencies: 2755 - universalify: 2.0.1 2756 - optionalDependencies: 2757 - graceful-fs: 4.2.11 2758 - 2759 - kolorist@1.8.0: {} 2760 - 2761 - local-pkg@1.1.2: 2762 - dependencies: 2763 - mlly: 1.8.0 2764 - pkg-types: 2.3.0 2765 - quansync: 0.2.11 2766 - 2767 - locate-character@3.0.0: {} 2768 - 2769 - locate-path@5.0.0: 2770 - dependencies: 2771 - p-locate: 4.1.0 2772 - 2773 - lodash.startcase@4.4.0: {} 2774 - 2775 - lodash@4.17.21: {} 2776 - 2777 - lru-cache@5.1.1: 2778 - dependencies: 2779 - yallist: 3.1.1 2780 - 2781 - lru-cache@6.0.0: 2782 - dependencies: 2783 - yallist: 4.0.0 2784 - 2785 - magic-string@0.30.21: 2786 - dependencies: 2787 - '@jridgewell/sourcemap-codec': 1.5.5 2788 - 2789 - merge2@1.4.1: {} 2790 - 2791 - micromatch@4.0.8: 2792 - dependencies: 2793 - braces: 3.0.3 2794 - picomatch: 2.3.1 2795 - 2796 - minimatch@10.0.3: 2797 - dependencies: 2798 - '@isaacs/brace-expansion': 5.0.0 2799 - 2800 - minimatch@9.0.5: 2801 - dependencies: 2802 - brace-expansion: 2.0.2 2803 - 2804 - mlly@1.8.0: 2805 - dependencies: 2806 - acorn: 8.15.0 2807 - pathe: 2.0.3 2808 - pkg-types: 1.3.1 2809 - ufo: 1.6.1 2810 - 2811 - mri@1.2.0: {} 2812 - 2813 - ms@2.1.3: {} 2814 - 2815 - muggle-string@0.4.1: {} 2816 - 2817 - nanoid@3.3.11: {} 2818 - 2819 - node-html-parser@6.1.13: 2820 - dependencies: 2821 - css-select: 5.2.2 2822 - he: 1.2.0 2823 - 2824 - node-releases@2.0.27: {} 2825 - 2826 - nth-check@2.1.1: 2827 - dependencies: 2828 - boolbase: 1.0.0 2829 - 2830 - outdent@0.5.0: {} 2831 - 2832 - p-filter@2.1.0: 2833 - dependencies: 2834 - p-map: 2.1.0 2835 - 2836 - p-limit@2.3.0: 2837 - dependencies: 2838 - p-try: 2.2.0 2839 - 2840 - p-locate@4.1.0: 2841 - dependencies: 2842 - p-limit: 2.3.0 2843 - 2844 - p-map@2.1.0: {} 2845 - 2846 - p-try@2.2.0: {} 2847 - 2848 - package-manager-detector@0.2.11: 2849 - dependencies: 2850 - quansync: 0.2.11 2851 - 2852 - path-browserify@1.0.1: {} 2853 - 2854 - path-exists@4.0.0: {} 2855 - 2856 - path-key@3.1.1: {} 2857 - 2858 - path-parse@1.0.7: {} 2859 - 2860 - path-type@4.0.0: {} 2861 - 2862 - pathe@2.0.3: {} 2863 - 2864 - picocolors@1.1.1: {} 2865 - 2866 - picomatch@2.3.1: {} 2867 - 2868 - picomatch@4.0.3: {} 2869 - 2870 - pify@4.0.1: {} 2871 - 2872 - pkg-types@1.3.1: 2873 - dependencies: 2874 - confbox: 0.1.8 2875 - mlly: 1.8.0 2876 - pathe: 2.0.3 2877 - 2878 - pkg-types@2.3.0: 2879 - dependencies: 2880 - confbox: 0.2.2 2881 - exsolve: 1.0.8 2882 - pathe: 2.0.3 2883 - 2884 - postcss-less@6.0.0(postcss@8.5.6): 2885 - dependencies: 2886 - postcss: 8.5.6 2887 - 2888 - postcss-scss@4.0.9(postcss@8.5.6): 2889 - dependencies: 2890 - postcss: 8.5.6 2891 - 2892 - postcss@8.5.6: 2893 - dependencies: 2894 - nanoid: 3.3.11 2895 - picocolors: 1.1.1 2896 - source-map-js: 1.2.1 2897 - 2898 - preact@10.28.0: {} 2899 - 2900 - prettier-plugin-css-order@2.1.2(postcss@8.5.6)(prettier@3.7.4): 2901 - dependencies: 2902 - css-declaration-sorter: 7.3.0(postcss@8.5.6) 2903 - postcss-less: 6.0.0(postcss@8.5.6) 2904 - postcss-scss: 4.0.9(postcss@8.5.6) 2905 - prettier: 3.7.4 2906 - transitivePeerDependencies: 2907 - - postcss 2908 - 2909 - prettier-plugin-svelte@3.4.0(prettier@3.7.4)(svelte@5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd)): 2910 - dependencies: 2911 - prettier: 3.7.4 2912 - svelte: 5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd) 2913 - 2914 - prettier@2.8.8: {} 2915 - 2916 - prettier@3.7.4: {} 2917 - 2918 - punycode@2.3.1: {} 2919 - 2920 - quansync@0.2.11: {} 2921 - 2922 - queue-microtask@1.2.3: {} 2923 - 2924 - read-yaml-file@1.1.0: 2925 - dependencies: 2926 - graceful-fs: 4.2.11 2927 - js-yaml: 3.14.2 2928 - pify: 4.0.1 2929 - strip-bom: 3.0.0 2930 - 2931 - readdirp@4.1.2: {} 2932 - 2933 - require-from-string@2.0.2: {} 2934 - 2935 - resolve-from@5.0.0: {} 2936 - 2937 - resolve@1.22.11: 2938 - dependencies: 2939 - is-core-module: 2.16.1 2940 - path-parse: 1.0.7 2941 - supports-preserve-symlinks-flag: 1.0.0 2942 - 2943 - reusify@1.1.0: {} 2944 - 2945 - rollup@4.53.3: 2946 - dependencies: 2947 - '@types/estree': 1.0.8 2948 - optionalDependencies: 2949 - '@rollup/rollup-android-arm-eabi': 4.53.3 2950 - '@rollup/rollup-android-arm64': 4.53.3 2951 - '@rollup/rollup-darwin-arm64': 4.53.3 2952 - '@rollup/rollup-darwin-x64': 4.53.3 2953 - '@rollup/rollup-freebsd-arm64': 4.53.3 2954 - '@rollup/rollup-freebsd-x64': 4.53.3 2955 - '@rollup/rollup-linux-arm-gnueabihf': 4.53.3 2956 - '@rollup/rollup-linux-arm-musleabihf': 4.53.3 2957 - '@rollup/rollup-linux-arm64-gnu': 4.53.3 2958 - '@rollup/rollup-linux-arm64-musl': 4.53.3 2959 - '@rollup/rollup-linux-loong64-gnu': 4.53.3 2960 - '@rollup/rollup-linux-ppc64-gnu': 4.53.3 2961 - '@rollup/rollup-linux-riscv64-gnu': 4.53.3 2962 - '@rollup/rollup-linux-riscv64-musl': 4.53.3 2963 - '@rollup/rollup-linux-s390x-gnu': 4.53.3 2964 - '@rollup/rollup-linux-x64-gnu': 4.53.3 2965 - '@rollup/rollup-linux-x64-musl': 4.53.3 2966 - '@rollup/rollup-openharmony-arm64': 4.53.3 2967 - '@rollup/rollup-win32-arm64-msvc': 4.53.3 2968 - '@rollup/rollup-win32-ia32-msvc': 4.53.3 2969 - '@rollup/rollup-win32-x64-gnu': 4.53.3 2970 - '@rollup/rollup-win32-x64-msvc': 4.53.3 2971 - fsevents: 2.3.3 2972 - 2973 - run-parallel@1.2.0: 2974 - dependencies: 2975 - queue-microtask: 1.2.3 2976 - 2977 - sade@1.8.1: 2978 - dependencies: 2979 - mri: 1.2.0 2980 - 2981 - safer-buffer@2.1.2: {} 2982 - 2983 - semver@6.3.1: {} 2984 - 2985 - semver@7.5.4: 2986 - dependencies: 2987 - lru-cache: 6.0.0 2988 - 2989 - semver@7.7.3: {} 2990 - 2991 - shebang-command@2.0.0: 2992 - dependencies: 2993 - shebang-regex: 3.0.0 2994 - 2995 - shebang-regex@3.0.0: {} 2996 - 2997 - signal-exit@4.1.0: {} 2998 - 2999 - simple-code-frame@1.3.0: 3000 - dependencies: 3001 - kolorist: 1.8.0 3002 - 3003 - slash@3.0.0: {} 3004 - 3005 - source-map-js@1.2.1: {} 3006 - 3007 - source-map-support@0.5.21: 3008 - dependencies: 3009 - buffer-from: 1.1.2 3010 - source-map: 0.6.1 3011 - 3012 - source-map@0.6.1: {} 3013 - 3014 - source-map@0.7.6: {} 3015 - 3016 - spawndamnit@3.0.1: 3017 - dependencies: 3018 - cross-spawn: 7.0.6 3019 - signal-exit: 4.1.0 3020 - 3021 - sprintf-js@1.0.3: {} 3022 - 3023 - stack-trace@1.0.0-pre2: {} 3024 - 3025 - string-argv@0.3.2: {} 3026 - 3027 - strip-ansi@6.0.1: 3028 - dependencies: 3029 - ansi-regex: 5.0.1 3030 - 3031 - strip-bom@3.0.0: {} 3032 - 3033 - strip-json-comments@3.1.1: {} 3034 - 3035 - supports-color@8.1.1: 3036 - dependencies: 3037 - has-flag: 4.0.0 3038 - 3039 - supports-preserve-symlinks-flag@1.0.0: {} 3040 - 3041 - svelte-check@4.3.4(picomatch@4.0.3)(svelte@5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd))(typescript@5.8.3): 3042 - dependencies: 3043 - '@jridgewell/trace-mapping': 0.3.31 3044 - chokidar: 4.0.3 3045 - fdir: 6.5.0(picomatch@4.0.3) 3046 - picocolors: 1.1.1 3047 - sade: 1.8.1 3048 - svelte: 5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd) 3049 - typescript: 5.8.3 3050 - transitivePeerDependencies: 3051 - - picomatch 3052 - 3053 - svelte@5.45.5(patch_hash=0f942ae2231640ac09d0a1e9913071000fffa9bdfe69630d767130d415a78ecd): 3054 - dependencies: 3055 - '@jridgewell/remapping': 2.3.5 3056 - '@jridgewell/sourcemap-codec': 1.5.5 3057 - '@sveltejs/acorn-typescript': 1.0.8(acorn@8.15.0) 3058 - '@types/estree': 1.0.8 3059 - acorn: 8.15.0 3060 - aria-query: 5.3.2 3061 - axobject-query: 4.1.0 3062 - clsx: 2.1.1 3063 - devalue: 5.5.0 3064 - esm-env: 1.2.2 3065 - esrap: 2.2.1 3066 - is-reference: 3.0.3 3067 - locate-character: 3.0.0 3068 - magic-string: 0.30.21 3069 - zimmerframe: 1.1.4 3070 - 3071 - term-size@2.2.1: {} 3072 - 3073 - terser@5.44.1: 3074 - dependencies: 3075 - '@jridgewell/source-map': 0.3.11 3076 - acorn: 8.15.0 3077 - commander: 2.20.3 3078 - source-map-support: 0.5.21 3079 - 3080 - tinyglobby@0.2.15: 3081 - dependencies: 3082 - fdir: 6.5.0(picomatch@4.0.3) 3083 - picomatch: 4.0.3 3084 - 3085 - to-regex-range@5.0.1: 3086 - dependencies: 3087 - is-number: 7.0.0 3088 - 3089 - tslib@2.8.1: {} 3090 - 3091 - typescript@5.8.2: {} 3092 - 3093 - typescript@5.8.3: {} 3094 - 3095 - ufo@1.6.1: {} 3096 - 3097 - undici-types@7.16.0: {} 3098 - 3099 - universalify@0.1.2: {} 3100 - 3101 - universalify@2.0.1: {} 3102 - 3103 - update-browserslist-db@1.2.1(browserslist@4.28.1): 3104 - dependencies: 3105 - browserslist: 4.28.1 3106 - escalade: 3.2.0 3107 - picocolors: 1.1.1 3108 - 3109 - uri-js@4.4.1: 3110 - dependencies: 3111 - punycode: 2.3.1 3112 - 3113 - vite-plugin-dts@4.5.4(@types/node@24.10.1)(rollup@4.53.3)(typescript@5.8.3)(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)): 3114 - dependencies: 3115 - '@microsoft/api-extractor': 7.55.1(@types/node@24.10.1) 3116 - '@rollup/pluginutils': 5.3.0(rollup@4.53.3) 3117 - '@volar/typescript': 2.4.26 3118 - '@vue/language-core': 2.2.0(typescript@5.8.3) 3119 - compare-versions: 6.1.1 3120 - debug: 4.4.3 3121 - kolorist: 1.8.0 3122 - local-pkg: 1.1.2 3123 - magic-string: 0.30.21 3124 - typescript: 5.8.3 3125 - optionalDependencies: 3126 - vite: 7.2.6(@types/node@24.10.1)(terser@5.44.1) 3127 - transitivePeerDependencies: 3128 - - '@types/node' 3129 - - rollup 3130 - - supports-color 3131 - 3132 - vite-prerender-plugin@0.5.12(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)): 3133 - dependencies: 3134 - kolorist: 1.8.0 3135 - magic-string: 0.30.21 3136 - node-html-parser: 6.1.13 3137 - simple-code-frame: 1.3.0 3138 - source-map: 0.7.6 3139 - stack-trace: 1.0.0-pre2 3140 - vite: 7.2.6(@types/node@24.10.1)(terser@5.44.1) 3141 - 3142 - vite@7.2.6(@types/node@24.10.1)(terser@5.44.1): 3143 - dependencies: 3144 - esbuild: 0.25.12 3145 - fdir: 6.5.0(picomatch@4.0.3) 3146 - picomatch: 4.0.3 3147 - postcss: 8.5.6 3148 - rollup: 4.53.3 3149 - tinyglobby: 0.2.15 3150 - optionalDependencies: 3151 - '@types/node': 24.10.1 3152 - fsevents: 2.3.3 3153 - terser: 5.44.1 3154 - 3155 - vitefu@1.1.1(vite@7.2.6(@types/node@24.10.1)(terser@5.44.1)): 3156 - optionalDependencies: 3157 - vite: 7.2.6(@types/node@24.10.1)(terser@5.44.1) 3158 - 3159 - vscode-uri@3.1.0: {} 3160 - 3161 - which@2.0.2: 3162 - dependencies: 3163 - isexe: 2.0.0 3164 - 3165 - yallist@3.1.1: {} 3166 - 3167 - yallist@4.0.0: {} 3168 - 3169 - zimmerframe@1.1.4: {}
-9
pnpm-workspace.yaml
··· 1 - packages: 2 - - packages/internal 3 - - packages/svelte-site 4 - - packages/bluesky-post-embed 5 - - packages/bluesky-profile-card-embed 6 - - packages/bluesky-profile-feed-embed 7 - 8 - catalog: 9 - svelte: ^5.45.5
-19
themes/dark.css
··· 1 - .bluesky-embed { 2 - --font-size: 16px; 3 - --font-family: 4 - system-ui, 'Segoe UI', 'Roboto', 'Helvetica', 'Arial', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'; 5 - --max-feed-height: 600px; 6 - } 7 - 8 - .bluesky-embed { 9 - --text-primary: #f1f3f5; 10 - --text-secondary: #8c9eb2; 11 - --text-link: #1083fe; 12 - --background-primary: #000000; 13 - --background-secondary: #212d3b; 14 - --divider: rgb(37, 51, 66); 15 - --divider-hover: rgb(66, 87, 108); 16 - --button: #208bfe; 17 - --button-text: #ffffff; 18 - --button-hover: #4ca2fe; 19 - }
-19
themes/dim.css
··· 1 - .bluesky-embed { 2 - --font-size: 16px; 3 - --font-family: 4 - system-ui, 'Segoe UI', 'Roboto', 'Helvetica', 'Arial', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'; 5 - --max-feed-height: 600px; 6 - } 7 - 8 - .bluesky-embed { 9 - --text-primary: #f1f3f5; 10 - --text-secondary: #aebbc9; 11 - --text-link: #1083fe; 12 - --background-primary: #161e27; 13 - --background-secondary: #212d3b; 14 - --divider: #2e4052; 15 - --divider-hover: #4a6179; 16 - --button: #208bfe; 17 - --button-text: #ffffff; 18 - --button-hover: #4ca2fe; 19 - }
-19
themes/light.css
··· 1 - .bluesky-embed { 2 - --font-size: 16px; 3 - --font-family: 4 - system-ui, 'Segoe UI', 'Roboto', 'Helvetica', 'Arial', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'; 5 - --max-feed-height: 600px; 6 - } 7 - 8 - .bluesky-embed { 9 - --text-primary: #000000; 10 - --text-secondary: #455668; 11 - --text-link: #1083fe; 12 - --background-primary: #ffffff; 13 - --background-secondary: #455668; 14 - --divider-hover: #a9b7c5; 15 - --divider: #d4dbe2; 16 - --button: #1083fe; 17 - --button-text: #ffffff; 18 - --button-hover: #0168d5; 19 - }