Compare changes

Choose any two refs to compare.

+8
.changeset/README.md
··· 1 + # Changesets 2 + 3 + Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 + with multi-package repos, or single-package repos to help you version and publish your code. You can 5 + find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 + 7 + We have a quick list of common questions to get you started engaging with this project in 8 + [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": "main", 9 + "updateInternalDependencies": "patch", 10 + "ignore": [] 11 + }
+5
.changeset/sweet-rockets-fetch.md
··· 1 + --- 2 + "@nulfrost/leaflet-loader-astro": patch 3 + --- 4 + 5 + Add JSDoc comments for available loader options for leafletStaticLoader and leafletLiveLoader
+5
.changeset/tired-suits-double.md
··· 1 + --- 2 + "@nulfrost/leaflet-loader-astro": minor 3 + --- 4 + 5 + Add support for blockquotes
+64
.github/workflows/ci.yml
··· 1 + name: CI 2 + 3 + on: 4 + push: 5 + branches: 6 + - main 7 + pull_request: 8 + branches: ["main"] 9 + 10 + 11 + concurrency: 12 + group: ${{ github.workflow }}-${{ github.ref }} 13 + cancel-in-progress: true 14 + 15 + jobs: 16 + lint: 17 + runs-on: ubuntu-latest 18 + steps: 19 + - uses: actions/checkout@v4 20 + - name: Install PNPM 21 + uses: pnpm/action-setup@v4 22 + with: 23 + version: 10 24 + - name: Setup Node 25 + uses: actions/setup-node@v4 26 + with: 27 + cache: "pnpm" 28 + - name: Install dependencies 29 + run: pnpm install 30 + - name: Lint 31 + run: pnpm lint 32 + test: 33 + runs-on: ubuntu-latest 34 + steps: 35 + - uses: actions/checkout@v4 36 + - name: Install PNPM 37 + uses: pnpm/action-setup@v4 38 + with: 39 + version: 10 40 + - name: Setup Node 41 + uses: actions/setup-node@v4 42 + with: 43 + cache: "pnpm" 44 + - name: Install dependencies 45 + run: pnpm install 46 + - name: Test 47 + run: pnpm test 48 + format: 49 + needs: [lint, test] 50 + runs-on: ubuntu-latest 51 + steps: 52 + - uses: actions/checkout@v4 53 + - name: Install PNPM 54 + uses: pnpm/action-setup@v4 55 + with: 56 + version: 10 57 + - name: Setup Node 58 + uses: actions/setup-node@v4 59 + with: 60 + cache: "pnpm" 61 + - name: Install dependencies 62 + run: pnpm install 63 + - name: Lint 64 + run: pnpm lint
-33
.github/workflows/lint.yml
··· 1 - name: Linting and Formatting 2 - 3 - on: 4 - push: 5 - branches: 6 - - main 7 - pull_request: 8 - branches: ["main"] 9 - 10 - 11 - concurrency: 12 - group: ${{ github.workflow }}-${{ github.ref }} 13 - cancel-in-progress: true 14 - 15 - jobs: 16 - lint: 17 - runs-on: ubuntu-latest 18 - steps: 19 - - uses: actions/checkout@v4 20 - - name: Install PNPM 21 - uses: pnpm/action-setup@v4 22 - with: 23 - version: 10 24 - - name: Setup Node 25 - uses: actions/setup-node@v4 26 - with: 27 - cache: "pnpm" 28 - - name: Install dependencies 29 - run: pnpm install 30 - - name: Lint 31 - run: pnpm lint 32 - - name: Format 33 - run: pnpm format
+34
.github/workflows/publish.yml
··· 1 + name: Publish 2 + on: 3 + workflow_run: 4 + workflows: [CI] 5 + branches: [main] 6 + types: [completed] 7 + 8 + concurrency: ${{ github.workflow }}-${{ github.ref }} 9 + 10 + permissions: 11 + contents: write 12 + pull-requests: write 13 + 14 + jobs: 15 + publish: 16 + if: ${{ github.event.workflow_run.conclusion == 'success' }} 17 + runs-on: ubuntu-latest 18 + steps: 19 + - uses: actions/checkout@v4 20 + - uses: pnpm/action-setup@v2 21 + with: 22 + version: 10 23 + - uses: actions/setup-node@v4 24 + with: 25 + cache: "pnpm" 26 + - run: pnpm install --frozen-lockfile 27 + - name: Create Release Pull Request or Publish 28 + id: changesets 29 + uses: changesets/action@v1 30 + with: 31 + publish: pnpm run release 32 + env: 33 + GITHUB_TOKEN: ${{ secrets.GHA_TOKEN }} 34 + NPM_TOKEN: ${{ secrets.LEAFLET_PUBLISHING_TOKEN }}
-31
.github/workflows/test.yml
··· 1 - name: Testing 2 - 3 - on: 4 - push: 5 - branches: 6 - - main 7 - pull_request: 8 - branches: ["main"] 9 - 10 - 11 - concurrency: 12 - group: ${{ github.workflow }}-${{ github.ref }} 13 - cancel-in-progress: true 14 - 15 - jobs: 16 - lint: 17 - runs-on: ubuntu-latest 18 - steps: 19 - - uses: actions/checkout@v4 20 - - name: Install PNPM 21 - uses: pnpm/action-setup@v4 22 - with: 23 - version: 10 24 - - name: Setup Node 25 - uses: actions/setup-node@v4 26 - with: 27 - cache: "pnpm" 28 - - name: Install dependencies 29 - run: pnpm install 30 - - name: Test 31 - run: pnpm test
+34
CHANGELOG.md
··· 1 + # leaflet-loader-astro 2 + 3 + ## 1.1.0 4 + 5 + ### Minor Changes 6 + 7 + - 6d70cc6: Added support for these leaflet blocks: 8 + 9 + - ul/li 10 + - math 11 + - code 12 + - img 13 + - hr 14 + 15 + the only remaining block to implement is "website", though I haven't thought of a good way to output that yet. stay tuned for a further release 16 + 17 + - 5524ce5: Added the ability to use a handle or did when specifying a repo for leafletStaticLoader and leafletLiveLoader 18 + 19 + ```ts 20 + import { defineLiveCollection } from "astro:content"; 21 + import { leafletLiveLoader } from "leaflet-loader-astro"; 22 + 23 + const documents = defineLiveCollection({ 24 + loader: leafletLiveLoader({ repo: "dane.computer" }), // or repo: did:plc:qttsv4e7pu2jl3ilanfgc3zn, both work! 25 + }); 26 + 27 + export const collections = { documents }; 28 + ``` 29 + 30 + ## 1.0.0 31 + 32 + ### Major Changes 33 + 34 + - b4309c0: This is the initial release for `leaflet-loader-astro`
+204 -2
README.md
··· 1 - # An astro loader for leaflet.pub 1 + # Leaflet Astro Loader 2 + 3 + This loader is for [leaflet.pub](https://leaflet.pub/). It fetches leaflet document records from your personal data server to then be used on your astro site. 4 + 5 + There are two different types of loaders you can use from this package: 6 + 7 + - **Static Loader:** Fetches data at build time and is served statically on your website 8 + - **Live Loader (experimental astro feature):** Fetches data on each request. **Note**: This package does not provide any caching mechanisms for the live loader. So to avoid slamming your PDS (or someone elses PDS) with requests it's probably a good idea to set up some sort of cache either using cache headers or some other means. 9 + 10 + ## Installation 11 + 12 + ```bash 13 + npm install @nulfrost/leaflet-loader-astro 14 + ``` 15 + 16 + ## Usage 17 + 18 + <details> 19 + <summary>Build-time loader: leafletStaticLoader **(recommended)**</summary> 20 + 21 + ```ts 22 + // src/content.config.ts 23 + import { defineCollection, z } from "astro:content"; 24 + import { leafletStaticLoader } from "@nulfrost/leaflet-loader-astro"; 25 + 26 + const documents = defineCollection({ 27 + loader: leafletStaticLoader({ repo: "did:plc:qttsv4e7pu2jl3ilanfgc3zn" }), // or repo: dane.is.extraordinarily.cool 28 + }); 29 + 30 + export const collections = { documents }; 31 + ``` 32 + 33 + ```ts 34 + // src/pages/index.astro 35 + --- 36 + import { getCollection } from "astro:content"; 37 + 38 + const documents = await getCollection("documents"); 39 + --- 40 + 41 + <html lang="en"> 42 + <head> 43 + <meta charset="utf-8" /> 44 + <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> 45 + <meta name="viewport" content="width=device-width" /> 46 + <meta name="generator" content={Astro.generator} /> 47 + <title>Astro</title> 48 + </head> 49 + <body> 50 + <h1>Astro + Leaflet.pub</h1> 51 + <ul> 52 + {documents.map(document => <li> 53 + <a href={`/blogs/${document.id}`}>{document.data.title}</a> 54 + </li>)} 55 + </ul> 56 + </body> 57 + </html> 58 + ``` 59 + 60 + ```ts 61 + // src/pages/blog/[blog].astro 62 + --- 63 + import { getCollection, getEntry } from "astro:content"; 64 + import { render } from "astro:content"; 65 + 66 + export async function getStaticPaths() { 67 + const documents = await getCollection("documents"); 68 + return documents.map((document) => ({ 69 + params: { blog: document.id }, 70 + props: document, 71 + })); 72 + } 73 + 74 + const document = await getEntry("documents", Astro.params.blog); 75 + 76 + if (!document) { 77 + throw new Error(`Document with id "${Astro.params.blog}" not found`); 78 + } 79 + 80 + const { Content } = await render(document); 81 + --- 82 + 83 + <Content /> 84 + ``` 85 + </details> 86 + 87 + <details> 88 + <summary>Live loader: leafletLiveLoader</summary> 89 + 90 + ```ts 91 + // astro.config.mjs 2 92 3 - TODO 93 + // @ts-check 94 + import { defineConfig } from "astro/config"; 95 + 96 + // https://astro.build/config 97 + export default defineConfig({ 98 + experimental: { 99 + liveContentCollections: true, // make sure to enable this 100 + }, 101 + }); 102 + ``` 103 + 104 + ```ts 105 + // src/live.config.ts 106 + import { defineLiveCollection, z } from "astro:content"; 107 + import { leafletLiveLoader } from "@nulfrost/leaflet-loader-astro"; 108 + 109 + const documents = defineLiveCollection({ 110 + loader: leafletLiveLoader({ repo: "did:plc:qttsv4e7pu2jl3ilanfgc3zn" }), // or repo: dane.is.extraordinarily.cool 111 + }); 112 + 113 + export const collections = { documents }; 114 + ``` 115 + 116 + ```ts 117 + // src/pages/index.astro 118 + --- 119 + import { getLiveCollection } from "astro:content"; 120 + 121 + export const prerender = false; 122 + 123 + const documents = await getLiveCollection("documents"); 124 + --- 125 + 126 + <html lang="en"> 127 + <head> 128 + <meta charset="utf-8" /> 129 + <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> 130 + <meta name="viewport" content="width=device-width" /> 131 + <meta name="generator" content={Astro.generator} /> 132 + <title>Astro</title> 133 + </head> 134 + <body> 135 + <h1>Astro + Leaflet.pub</h1> 136 + <ul> 137 + {documents.map(document => <li> 138 + <a href={`/blogs/${document.id}`}>{document.data.title}</a> 139 + </li>)} 140 + </ul> 141 + </body> 142 + </html> 143 + ``` 144 + 145 + ```ts 146 + // src/pages/blog/[blog].astro 147 + --- 148 + import { getLiveEntry } from "astro:content"; 149 + import { render } from "astro:content"; 150 + 151 + export const prerender = false; 152 + 153 + const document = await getLiveEntry("documents", Astro.params.blog); 154 + 155 + if (!document) { 156 + throw new Error(`Document with id "${Astro.params.blog}" not found`); 157 + } 158 + 159 + const { Content } = await render(document?.entry); 160 + --- 161 + 162 + <Content /> 163 + ``` 164 + 165 + </details> 166 + 167 + ## Loader Options 168 + 169 + ### Static Loader 170 + 171 + ```ts 172 + leafletStaticLoader() 173 + ``` 174 + 175 + `repo`: This can be either your DID (did:plc:qttsv4e7pu2jl3ilanfgc3zn) or your handle (dane.is.extraordinarily.cool) 176 + 177 + `limit`: How many leaflet documents to return when calling `getCollection`. The default is 50 and the range is from 1 to 100. 178 + 179 + `reverse`: Whether or not to return the leaflet documents in reverse order. By default this is false. 180 + 181 + ### Live Loader 182 + 183 + ```ts 184 + leafletLiveLoader() 185 + ``` 186 + 187 + `repo`: This can be either your DID (did:plc:qttsv4e7pu2jl3ilanfgc3zn) or your handle (dane.is.extraordinarily.cool) 188 + 189 + > [!NOTE] 190 + > `getLiveCollection` supports a second argument where you can add additional filters, similar to the options you have access to for `leafletStaticLoader` 191 + 192 + ```ts 193 + getLiveCollection() 194 + ``` 195 + 196 + `limit`: How many leaflet documents to return when calling `getCollection`. The default is 50 and the range is from 1 to 100. 197 + 198 + `reverse`: Whether or not to return the leaflet documents in reverse order. By default this is false. 199 + 200 + 201 + ## License 202 + 203 + MIT 204 + 205 + For questions, contributions, and support, please open an issue on GitHub.
+1 -1
lex.config.js
··· 2 2 3 3 export default defineLexiconConfig({ 4 4 files: ["lexicons/**/*.json"], 5 - outdir: "src/lexicons/", 5 + outdir: "lib/lexicons/", 6 6 });
+22
lexicons/pub/leaflet/blocks/blockquote.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.blocks.blockquote", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "required": ["plaintext"], 8 + "properties": { 9 + "plaintext": { 10 + "type": "string" 11 + }, 12 + "facets": { 13 + "type": "array", 14 + "items": { 15 + "type": "ref", 16 + "ref": "pub.leaflet.richtext.facet" 17 + } 18 + } 19 + } 20 + } 21 + } 22 + }
+11
lexicons/pub/leaflet/blocks/horizontalRule.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "pub.leaflet.blocks.horizontalRule", 4 + "defs": { 5 + "main": { 6 + "type": "object", 7 + "required": [], 8 + "properties": {} 9 + } 10 + } 11 + }
+24 -19
lib/leaflet-live-loader.ts
··· 1 - import { Agent } from "@atproto/api"; 2 - import { isDid } from "@atproto/did"; 1 + import { Client, simpleFetchHandler } from "@atcute/client"; 2 + import { isHandle } from "@atcute/lexicons/syntax"; 3 3 import type { LiveLoader } from "astro/loaders"; 4 4 import type { 5 5 CollectionFilter, ··· 11 11 import { 12 12 getLeafletDocuments, 13 13 getSingleLeafletDocument, 14 + isPlcDid, 14 15 leafletBlocksToHTML, 15 16 leafletDocumentRecordToView, 16 17 LiveLoaderError, ··· 35 36 ); 36 37 } 37 38 38 - // not a valid did 39 - if (!isDid(repo)) { 40 - throw new LiveLoaderError("invalid did", "INVALID_DID"); 39 + // not a valid handle, check if valid did 40 + if (!isHandle(repo)) { 41 + // not a valid handle or did, throw 42 + if (!isPlcDid(repo)) { 43 + throw new LiveLoaderError( 44 + "invalid handle or did", 45 + "INVALID_HANDLE_OR_DID", 46 + ); 47 + } 41 48 } 42 49 43 50 return { 44 51 name: "leaflet-loader-astro", 45 52 loadCollection: async ({ filter }) => { 46 53 try { 47 - const pds_url = await resolveMiniDoc(repo); 48 - const agent = new Agent({ service: pds_url }); 54 + const { pds, did } = await resolveMiniDoc(repo); 55 + const handler = simpleFetchHandler({ service: pds }); 56 + const rpc = new Client({ handler }); 49 57 50 58 const { documents } = await getLeafletDocuments({ 51 - agent, 59 + rpc, 52 60 repo, 53 61 reverse: filter?.reverse, 54 62 cursor: filter?.cursor, ··· 67 75 }), 68 76 rendered: { 69 77 html: leafletBlocksToHTML({ 70 - id, 71 - uri: document.uri, 72 - cid: document.cid, 73 - value: document.value as unknown as LeafletDocumentRecord, 78 + record: document.value as unknown as LeafletDocumentRecord, 79 + did, 74 80 }), 75 81 }, 76 82 }; ··· 95 101 }; 96 102 } 97 103 try { 98 - const pds_url = await resolveMiniDoc(repo); 99 - const agent = new Agent({ service: pds_url }); 104 + const { pds, did } = await resolveMiniDoc(repo); 105 + const handler = simpleFetchHandler({ service: pds }); 106 + const rpc = new Client({ handler }); 100 107 const document = await getSingleLeafletDocument({ 101 - agent, 108 + rpc, 102 109 id: filter.id, 103 110 repo, 104 111 }); ··· 114 121 }), 115 122 rendered: { 116 123 html: leafletBlocksToHTML({ 117 - id: filter.id, 118 - uri: document.uri, 119 - cid, 120 - value: document.value as unknown as LeafletDocumentRecord, 124 + record: document.value as unknown as LeafletDocumentRecord, 125 + did, 121 126 }), 122 127 }, 123 128 };
+24 -17
lib/leaftlet-static-loader.ts
··· 1 - import { Agent } from "@atproto/api"; 2 - import { isDid } from "@atproto/did"; 1 + import { Client, simpleFetchHandler } from "@atcute/client"; 2 + import { isHandle } from "@atcute/lexicons/syntax"; 3 3 import type { Loader, LoaderContext } from "astro/loaders"; 4 4 import { LeafletDocumentSchema } from "schema.js"; 5 5 import type { ··· 7 7 StaticLeafletLoaderOptions, 8 8 } from "types.js"; 9 9 import { 10 + getLeafletDocuments, 11 + isPlcDid, 12 + leafletBlocksToHTML, 13 + leafletDocumentRecordToView, 10 14 LiveLoaderError, 11 15 resolveMiniDoc, 12 - getLeafletDocuments, 13 16 uriToRkey, 14 - leafletDocumentRecordToView, 15 - leafletBlocksToHTML, 16 17 } from "utils.js"; 17 18 18 19 export function leafletStaticLoader( 19 20 options: StaticLeafletLoaderOptions, 20 21 ): Loader { 21 - const { repo, limit } = options; 22 + const { repo, limit, reverse } = options; 22 23 23 24 if (!repo || typeof repo !== "string") { 24 25 throw new LiveLoaderError( ··· 27 28 ); 28 29 } 29 30 30 - // not a valid did 31 - if (!isDid(repo)) { 32 - throw new LiveLoaderError("invalid did", "INVALID_DID"); 31 + // not a valid handle, check if valid did 32 + if (!isHandle(repo)) { 33 + // not a valid handle or did, throw 34 + if (!isPlcDid(repo)) { 35 + throw new LiveLoaderError( 36 + "invalid handle or did", 37 + "INVALID_HANDLE_OR_DID", 38 + ); 39 + } 33 40 } 34 41 35 42 return { ··· 43 50 }: LoaderContext) => { 44 51 try { 45 52 logger.info("fetching latest leaflet documents"); 46 - const pds_url = await resolveMiniDoc(repo); 47 - const agent = new Agent({ service: pds_url }); 53 + const { pds, did } = await resolveMiniDoc(repo); 54 + const handler = simpleFetchHandler({ service: pds }); 55 + const rpc = new Client({ handler }); 48 56 49 57 let cursor: string | undefined; 50 58 let count = 0; ··· 52 60 fetching: do { 53 61 const { documents, cursor: documentsCursor } = 54 62 await getLeafletDocuments({ 55 - agent, 63 + rpc, 56 64 repo, 57 65 cursor, 58 - limit: 100, 66 + reverse, 67 + limit: 50, 59 68 }); 60 69 for (const document of documents) { 61 70 if (limit && count >= limit) { ··· 83 92 digest, 84 93 rendered: { 85 94 html: leafletBlocksToHTML({ 86 - id, 87 - uri: document.uri, 88 - cid: document.cid, 89 - value: document.value as unknown as LeafletDocumentRecord, 95 + record: document.value as unknown as LeafletDocumentRecord, 96 + did, 90 97 }), 91 98 }, 92 99 });
+2
lib/lexicons/index.ts
··· 1 1 export * as ComAtprotoRepoStrongRef from "./types/com/atproto/repo/strongRef.js"; 2 + export * as PubLeafletBlocksBlockquote from "./types/pub/leaflet/blocks/blockquote.js"; 2 3 export * as PubLeafletBlocksCode from "./types/pub/leaflet/blocks/code.js"; 3 4 export * as PubLeafletBlocksHeader from "./types/pub/leaflet/blocks/header.js"; 5 + export * as PubLeafletBlocksHorizontalRule from "./types/pub/leaflet/blocks/horizontalRule.js"; 4 6 export * as PubLeafletBlocksImage from "./types/pub/leaflet/blocks/image.js"; 5 7 export * as PubLeafletBlocksMath from "./types/pub/leaflet/blocks/math.js"; 6 8 export * as PubLeafletBlocksText from "./types/pub/leaflet/blocks/text.js";
+23
lib/lexicons/types/pub/leaflet/blocks/blockquote.ts
··· 1 + import type {} from "@atcute/lexicons"; 2 + import * as v from "@atcute/lexicons/validations"; 3 + import * as PubLeafletRichtextFacet from "../richtext/facet.js"; 4 + 5 + const _mainSchema = /*#__PURE__*/ v.object({ 6 + $type: /*#__PURE__*/ v.optional( 7 + /*#__PURE__*/ v.literal("pub.leaflet.blocks.blockquote"), 8 + ), 9 + get facets() { 10 + return /*#__PURE__*/ v.optional( 11 + /*#__PURE__*/ v.array(PubLeafletRichtextFacet.mainSchema), 12 + ); 13 + }, 14 + plaintext: /*#__PURE__*/ v.string(), 15 + }); 16 + 17 + type main$schematype = typeof _mainSchema; 18 + 19 + export interface mainSchema extends main$schematype {} 20 + 21 + export const mainSchema = _mainSchema as mainSchema; 22 + 23 + export interface Main extends v.InferInput<typeof mainSchema> {}
+16
lib/lexicons/types/pub/leaflet/blocks/horizontalRule.ts
··· 1 + import type {} from "@atcute/lexicons"; 2 + import * as v from "@atcute/lexicons/validations"; 3 + 4 + const _mainSchema = /*#__PURE__*/ v.object({ 5 + $type: /*#__PURE__*/ v.optional( 6 + /*#__PURE__*/ v.literal("pub.leaflet.blocks.horizontalRule"), 7 + ), 8 + }); 9 + 10 + type main$schematype = typeof _mainSchema; 11 + 12 + export interface mainSchema extends main$schematype {} 13 + 14 + export const mainSchema = _mainSchema as mainSchema; 15 + 16 + export interface Main extends v.InferInput<typeof mainSchema> {}
+21 -8
lib/types.ts
··· 1 - import type { Agent } from "@atproto/api"; 1 + import type { Client } from "@atcute/client"; 2 + import type { ActorIdentifier } from "@atcute/lexicons"; 3 + import type { XRPCProcedures, XRPCQueries } from "@atcute/lexicons/ambient"; 2 4 import type { PubLeafletRichtextFacet } from "./lexicons/index.js"; 3 5 4 6 export interface LiveLeafletLoaderOptions { 5 7 /** 6 - * @description Your repo is your DID (did:plc... or did:web...). You can find this information using: https://pdsls.dev 8 + * @description Your repo is your DID (did:plc... or did:web...) or handle (username.bsky.social). You can find this information using: https://pdsls.dev 7 9 */ 8 10 repo: string; 9 11 } 10 12 11 13 export interface StaticLeafletLoaderOptions { 12 14 /** 13 - * @description Your repo is your DID (did:plc... or did:web...). You can find this information using: https://pdsls.dev 15 + * @description Your repo is your DID (did:plc... or did:web...) or handle (username.bsky.social). You can find this information using: https://pdsls.dev 14 16 */ 15 17 repo: string; 16 - filter?: string; 17 18 /** 19 + * @description The number of records leaflet records to return for getCollection, the default being 50. The range can be from 1 to 100. 18 20 * @default 50 19 21 */ 20 22 limit?: number; 23 + /** 24 + * @description Whether or not the records should be returned in reverse order. 25 + * @default undefined 26 + */ 27 + reverse?: boolean; 21 28 } 22 29 23 30 export interface LeafletDocumentRecord { ··· 58 65 } 59 66 60 67 export interface GetLeafletDocumentsParams { 61 - repo: string; 62 - agent: Agent; 68 + repo: ActorIdentifier; 69 + rpc: Client<XRPCQueries, XRPCProcedures>; 63 70 cursor?: string; 64 71 limit?: number; 65 72 reverse?: boolean; 66 73 } 67 74 68 75 export interface GetSingleLeafletDocumentParams { 69 - repo: string; 70 - agent: Agent; 76 + repo: ActorIdentifier; 77 + rpc: Client<XRPCQueries, XRPCProcedures>; 71 78 id: string; 72 79 } 73 80 ··· 76 83 text: string; 77 84 facet?: Exclude<Facet["features"], { $type: string }>; 78 85 } 86 + 87 + // yoinked from: https://github.com/mary-ext/atcute/blob/trunk/packages/lexicons/lexicons/lib/syntax/handle.ts 88 + /** 89 + * represents a decentralized identifier (DID). 90 + */ 91 + export type Did<Method extends string = string> = `did:${Method}:${string}`;
+207 -107
lib/utils.ts
··· 1 + import type {} from "@atcute/atproto"; 1 2 import { is } from "@atcute/lexicons"; 2 3 import { AtUri, UnicodeString } from "@atproto/api"; 4 + import katex from "katex"; 3 5 import sanitizeHTML from "sanitize-html"; 4 6 import { 7 + PubLeafletBlocksBlockquote, 8 + PubLeafletBlocksCode, 5 9 PubLeafletBlocksHeader, 10 + PubLeafletBlocksHorizontalRule, 11 + PubLeafletBlocksImage, 12 + PubLeafletBlocksMath, 6 13 PubLeafletBlocksText, 14 + PubLeafletBlocksUnorderedList, 7 15 PubLeafletPagesLinearDocument, 8 16 } from "./lexicons/index.js"; 9 17 import type { 18 + Did, 10 19 Facet, 11 20 GetLeafletDocumentsParams, 12 21 GetSingleLeafletDocumentParams, ··· 29 38 export function uriToRkey(uri: string): string { 30 39 const u = AtUri.make(uri); 31 40 if (!u.rkey) { 32 - throw new Error("Failed to get rkey from uri."); 41 + throw new Error("failed to get rkey"); 33 42 } 34 43 return u.rkey; 35 44 } ··· 47 56 } 48 57 const data = (await response.json()) as MiniDoc; 49 58 50 - return data.pds; 59 + return { 60 + pds: data.pds, 61 + did: data.did, 62 + }; 51 63 } catch { 52 64 throw new Error(`failed to resolve handle: ${handleOrDid}`); 53 65 } ··· 57 69 repo, 58 70 reverse, 59 71 cursor, 60 - agent, 72 + rpc, 61 73 limit, 62 74 }: GetLeafletDocumentsParams) { 63 - const response = await agent.com.atproto.repo.listRecords({ 64 - repo, 65 - collection: "pub.leaflet.document", 66 - cursor, 67 - reverse, 68 - limit, 75 + const { ok, data } = await rpc.get("com.atproto.repo.listRecords", { 76 + params: { 77 + collection: "pub.leaflet.document", 78 + cursor, 79 + reverse, 80 + limit, 81 + repo, 82 + }, 69 83 }); 70 84 71 - if (response.success === false) { 85 + if (!ok) { 72 86 throw new LiveLoaderError( 73 87 "error fetching leaflet documents", 74 88 "DOCUMENT_FETCH_ERROR", ··· 76 90 } 77 91 78 92 return { 79 - documents: response?.data?.records, 80 - cursor: response?.data?.cursor, 93 + documents: data?.records, 94 + cursor: data?.cursor, 81 95 }; 82 96 } 83 97 84 98 export async function getSingleLeafletDocument({ 85 - agent, 99 + rpc, 86 100 repo, 87 101 id, 88 102 }: GetSingleLeafletDocumentParams) { 89 - const response = await agent.com.atproto.repo.getRecord({ 90 - repo, 91 - collection: "pub.leaflet.document", 92 - rkey: id, 103 + const { ok, data } = await rpc.get("com.atproto.repo.getRecord", { 104 + params: { 105 + collection: "pub.leaflet.document", 106 + repo, 107 + rkey: id, 108 + }, 93 109 }); 94 110 95 - if (response.success === false) { 111 + if (!ok) { 96 112 throw new LiveLoaderError( 97 113 "error fetching single document", 98 114 "DOCUMENT_FETCH_ERROR", 99 115 ); 100 116 } 101 117 102 - return response?.data; 118 + return data; 103 119 } 104 120 105 121 export function leafletDocumentRecordToView({ ··· 122 138 }; 123 139 } 124 140 125 - export function leafletBlocksToHTML(record: { 126 - id: string; 127 - uri: string; 128 - cid: string; 129 - value: LeafletDocumentRecord; 141 + export function leafletBlocksToHTML({ 142 + record, 143 + did, 144 + }: { 145 + record: LeafletDocumentRecord; 146 + did: string; 130 147 }) { 131 148 let html = ""; 132 - const firstPage = record.value.pages[0]; 149 + const firstPage = record.pages[0]; 133 150 let blocks: PubLeafletPagesLinearDocument.Block[] = []; 151 + 134 152 if (is(PubLeafletPagesLinearDocument.mainSchema, firstPage)) { 135 153 blocks = firstPage.blocks || []; 136 154 } 137 155 138 156 for (const block of blocks) { 139 - if (is(PubLeafletBlocksText.mainSchema, block.block)) { 140 - const rt = new RichText({ 141 - text: block.block.plaintext, 142 - facets: block.block.facets || [], 143 - }); 144 - const children = []; 145 - for (const segment of rt.segments()) { 146 - const link = segment.facet?.find( 147 - (segment) => segment.$type === "pub.leaflet.richtext.facet#link", 148 - ); 149 - const isBold = segment.facet?.find( 150 - (segment) => segment.$type === "pub.leaflet.richtext.facet#bold", 151 - ); 152 - const isCode = segment.facet?.find( 153 - (segment) => segment.$type === "pub.leaflet.richtext.facet#code", 154 - ); 155 - const isStrikethrough = segment.facet?.find( 156 - (segment) => 157 - segment.$type === "pub.leaflet.richtext.facet#strikethrough", 158 - ); 159 - const isUnderline = segment.facet?.find( 160 - (segment) => segment.$type === "pub.leaflet.richtext.facet#underline", 161 - ); 162 - const isItalic = segment.facet?.find( 163 - (segment) => segment.$type === "pub.leaflet.richtext.facet#italic", 164 - ); 165 - if (isCode) { 166 - children.push(` <code> 167 - ${segment.text} 168 - </code>`); 169 - } else if (link) { 170 - children.push( 171 - ` <a 172 - href="${link.uri}" 173 - target="_blank" 174 - > 175 - ${segment.text} 176 - </a>`, 177 - ); 178 - } else if (isBold) { 179 - children.push(`<b>${segment.text}</b>`); 180 - } else if (isStrikethrough) { 181 - children.push(`<s>${segment.text}</s>`); 182 - } else if (isUnderline) { 183 - children.push( 184 - `<span style="text-decoration:underline;">${segment.text}</span>`, 185 - ); 186 - } else if (isItalic) { 187 - children.push(`<i>${segment.text}</i>`); 188 - } else { 189 - children.push( 190 - ` 191 - ${segment.text} 192 - `, 193 - ); 194 - } 195 - } 196 - html += `<p>${children.join("\n")}</p>`; 197 - } 198 - 199 - if (is(PubLeafletBlocksHeader.mainSchema, block.block)) { 200 - if (block.block.level === 1) { 201 - html += `<h2>${block.block.plaintext}</h2>`; 202 - } 203 - } 204 - if (is(PubLeafletBlocksHeader.mainSchema, block.block)) { 205 - if (block.block.level === 2) { 206 - html += `<h3>${block.block.plaintext}</h3>`; 207 - } 208 - } 209 - if (is(PubLeafletBlocksHeader.mainSchema, block.block)) { 210 - if (block.block.level === 3) { 211 - html += `<h4>${block.block.plaintext}</h4>`; 212 - } 213 - } 214 - if (is(PubLeafletBlocksHeader.mainSchema, block.block)) { 215 - if (!block.block.level) { 216 - html += `<h6>${block.block.plaintext}</h6>`; 217 - } 218 - } 157 + html += parseBlocks({ block, did }); 219 158 } 220 159 221 - return sanitizeHTML(html); 160 + return sanitizeHTML(html, { 161 + allowedAttributes: { 162 + "*": ["class", "style"], 163 + img: ["src", "height", "width", "alt"], 164 + a: ["href", "target", "rel"], 165 + }, 166 + allowedTags: [ 167 + "img", 168 + "pre", 169 + "code", 170 + "p", 171 + "a", 172 + "b", 173 + "s", 174 + "ul", 175 + "li", 176 + "i", 177 + "h1", 178 + "h2", 179 + "h3", 180 + "h4", 181 + "h5", 182 + "h6", 183 + "hr", 184 + "div", 185 + "span", 186 + "blockquote", 187 + ], 188 + selfClosing: ["img"], 189 + }); 222 190 } 223 191 224 192 export class RichText { 225 193 unicodeText: UnicodeString; 226 194 facets?: Facet[]; 227 - 228 195 constructor(props: { text: string; facets: Facet[] }) { 229 196 this.unicodeText = new UnicodeString(props.text); 230 197 this.facets = props.facets; ··· 278 245 } 279 246 } 280 247 } 248 + 249 + export function parseTextBlock(block: PubLeafletBlocksText.Main) { 250 + let html = ""; 251 + const rt = new RichText({ 252 + text: block.plaintext, 253 + facets: block.facets || [], 254 + }); 255 + const children = []; 256 + for (const segment of rt.segments()) { 257 + const link = segment.facet?.find( 258 + (segment) => segment.$type === "pub.leaflet.richtext.facet#link", 259 + ); 260 + const isBold = segment.facet?.find( 261 + (segment) => segment.$type === "pub.leaflet.richtext.facet#bold", 262 + ); 263 + const isCode = segment.facet?.find( 264 + (segment) => segment.$type === "pub.leaflet.richtext.facet#code", 265 + ); 266 + const isStrikethrough = segment.facet?.find( 267 + (segment) => segment.$type === "pub.leaflet.richtext.facet#strikethrough", 268 + ); 269 + const isUnderline = segment.facet?.find( 270 + (segment) => segment.$type === "pub.leaflet.richtext.facet#underline", 271 + ); 272 + const isItalic = segment.facet?.find( 273 + (segment) => segment.$type === "pub.leaflet.richtext.facet#italic", 274 + ); 275 + if (isCode) { 276 + children.push(`<pre><code>${segment.text}</code></pre>`); 277 + } else if (link) { 278 + children.push( 279 + `<a href="${link.uri}" target="_blank" rel="noopener noreferrer">${segment.text}</a>`, 280 + ); 281 + } else if (isBold) { 282 + children.push(`<b>${segment.text}</b>`); 283 + } else if (isStrikethrough) { 284 + children.push(`<s>${segment.text}</s>`); 285 + } else if (isUnderline) { 286 + children.push( 287 + `<span style="text-decoration:underline;">${segment.text}</span>`, 288 + ); 289 + } else if (isItalic) { 290 + children.push(`<i>${segment.text}</i>`); 291 + } else { 292 + children.push(`${segment.text}`); 293 + } 294 + } 295 + html += `<p>${children.join("")}</p>`; 296 + 297 + return html.trim(); 298 + } 299 + 300 + export function parseBlocks({ 301 + block, 302 + did, 303 + }: { 304 + block: PubLeafletPagesLinearDocument.Block; 305 + did: string; 306 + }): string { 307 + let html = ""; 308 + 309 + if (is(PubLeafletBlocksText.mainSchema, block.block)) { 310 + html += parseTextBlock(block.block); 311 + } 312 + 313 + if (is(PubLeafletBlocksHeader.mainSchema, block.block)) { 314 + if (block.block.level === 1) { 315 + html += `<h2>${block.block.plaintext}</h2>`; 316 + } 317 + } 318 + if (is(PubLeafletBlocksHeader.mainSchema, block.block)) { 319 + if (block.block.level === 2) { 320 + html += `<h3>${block.block.plaintext}</h3>`; 321 + } 322 + } 323 + if (is(PubLeafletBlocksHeader.mainSchema, block.block)) { 324 + if (block.block.level === 3) { 325 + html += `<h4>${block.block.plaintext}</h4>`; 326 + } 327 + } 328 + if (is(PubLeafletBlocksHeader.mainSchema, block.block)) { 329 + if (!block.block.level) { 330 + html += `<h6>${block.block.plaintext}</h6>`; 331 + } 332 + } 333 + 334 + if (is(PubLeafletBlocksHorizontalRule.mainSchema, block.block)) { 335 + html += `<hr />`; 336 + } 337 + if (is(PubLeafletBlocksUnorderedList.mainSchema, block.block)) { 338 + html += `<ul>${block.block.children.map((child) => renderListItem({ item: child, did })).join("")}</ul>`; 339 + } 340 + 341 + if (is(PubLeafletBlocksMath.mainSchema, block.block)) { 342 + html += `<div>${katex.renderToString(block.block.tex, { displayMode: true, output: "html", throwOnError: false })}</div>`; 343 + } 344 + 345 + if (is(PubLeafletBlocksCode.mainSchema, block.block)) { 346 + html += `<pre><code data-language=${block.block.language}>${block.block.plaintext}</code></pre>`; 347 + } 348 + 349 + if (is(PubLeafletBlocksImage.mainSchema, block.block)) { 350 + // @ts-ignore 351 + html += `<div><img src="https://cdn.bsky.app/img/feed_fullsize/plain/${did}/${block.block.image.ref.$link}@jpeg" height="${block.block.aspectRatio.height}" width="${block.block.aspectRatio.width}" alt="${block.block.alt}" /></div>`; 352 + } 353 + 354 + if (is(PubLeafletBlocksBlockquote.mainSchema, block.block)) { 355 + html += `<blockquote>${parseTextBlock(block.block)}</blockquote>`; 356 + } 357 + 358 + return html.trim(); 359 + } 360 + 361 + export function renderListItem({ 362 + item, 363 + did, 364 + }: { 365 + item: PubLeafletBlocksUnorderedList.ListItem; 366 + did: string; 367 + }): string { 368 + const children: string | null = item.children?.length 369 + ? `<ul>${item.children.map((child) => renderListItem({ item: child, did }))}</ul>` 370 + : ""; 371 + 372 + return `<li>${parseBlocks({ block: { block: item.content }, did })}${children}</li>`; 373 + } 374 + 375 + // yoinked from: https://github.com/mary-ext/atcute/blob/trunk/packages/lexicons/lexicons/lib/syntax/handle.ts 376 + const PLC_DID_RE = /^did:plc:([a-z2-7]{24})$/; 377 + 378 + export const isPlcDid = (input: string): input is Did<"plc"> => { 379 + return input.length === 32 && PLC_DID_RE.test(input); 380 + };
+17 -7
package.json
··· 1 1 { 2 - "name": "leaflet-loader-astro", 3 - "version": "0.0.1", 2 + "name": "@nulfrost/leaflet-loader-astro", 3 + "version": "1.1.0", 4 4 "description": "A leaflet.pub astro collection loader", 5 5 "keywords": [ 6 6 "astro", ··· 12 12 "bugs": { 13 13 "url": "https://github.com/nulfrost/leaflet-loader-astro/issues" 14 14 }, 15 - "author": "Dane Miller", 15 + "author": "Dane Miller <me@dane.computer>", 16 16 "repository": { 17 17 "type": "git", 18 18 "url": "git+https://github.com/nulfrost/leaflet-loader-astro.git" ··· 23 23 "lex": "lex-cli generate -c ./lex.config.js", 24 24 "test": "vitest --run", 25 25 "typecheck": "tsc", 26 - "build": "rm -rf dist && tsup", 27 - "pack": "pnpm build && pnpm pack" 26 + "release": "pnpm run build && changeset publish", 27 + "build": "rm -rf dist && tsup --format esm --dts", 28 + "pack": "rm -rf *.tgz && pnpm build && pnpm pack" 28 29 }, 29 30 "license": "MIT", 30 31 "files": [ 31 32 "dist" 32 33 ], 34 + "publishConfig": { 35 + "access": "public" 36 + }, 33 37 "type": "module", 34 38 "main": "dist/index.js", 39 + "module": "dist/index.js", 40 + "types": "dist/index.d.ts", 35 41 "exports": { 36 42 ".": { 37 43 "import": "./dist/index.js", ··· 39 45 } 40 46 }, 41 47 "devDependencies": { 48 + "@atcute/atproto": "^3.1.1", 42 49 "@atcute/lex-cli": "^2.1.1", 43 50 "@biomejs/biome": "2.1.3", 51 + "@changesets/cli": "^2.29.5", 52 + "@types/bun": "^1.2.19", 44 53 "@types/sanitize-html": "^2.16.0", 45 54 "astro": "^5.12.8", 46 55 "tsup": "^8.5.0", ··· 48 57 "vitest": "^3.2.4" 49 58 }, 50 59 "dependencies": { 60 + "@atcute/client": "^4.0.3", 51 61 "@atcute/lexicons": "^1.1.0", 52 - "@atproto/api": "^0.16.1", 53 - "@atproto/did": "^0.1.5", 62 + "@atproto/api": "^0.16.2", 63 + "katex": "^0.16.22", 54 64 "sanitize-html": "^2.17.0" 55 65 } 56 66 }
+823 -48
pnpm-lock.yaml
··· 8 8 9 9 .: 10 10 dependencies: 11 + '@atcute/client': 12 + specifier: ^4.0.3 13 + version: 4.0.3 11 14 '@atcute/lexicons': 12 15 specifier: ^1.1.0 13 16 version: 1.1.0 14 17 '@atproto/api': 15 - specifier: ^0.16.1 16 - version: 0.16.1 17 - '@atproto/did': 18 - specifier: ^0.1.5 19 - version: 0.1.5 18 + specifier: ^0.16.2 19 + version: 0.16.2 20 + katex: 21 + specifier: ^0.16.22 22 + version: 0.16.22 20 23 sanitize-html: 21 24 specifier: ^2.17.0 22 25 version: 2.17.0 23 26 devDependencies: 27 + '@atcute/atproto': 28 + specifier: ^3.1.1 29 + version: 3.1.1 24 30 '@atcute/lex-cli': 25 31 specifier: ^2.1.1 26 32 version: 2.1.1 27 33 '@biomejs/biome': 28 34 specifier: 2.1.3 29 35 version: 2.1.3 36 + '@changesets/cli': 37 + specifier: ^2.29.5 38 + version: 2.29.5 39 + '@types/bun': 40 + specifier: ^1.2.19 41 + version: 1.2.19(@types/react@19.1.9) 30 42 '@types/sanitize-html': 31 43 specifier: ^2.16.0 32 44 version: 2.16.0 33 45 astro: 34 46 specifier: ^5.12.8 35 - version: 5.12.8(@types/node@24.2.0)(rollup@4.46.2)(typescript@5.9.2) 47 + version: 5.12.9(@types/node@24.2.1)(rollup@4.46.2)(typescript@5.9.2) 36 48 tsup: 37 49 specifier: ^8.5.0 38 50 version: 8.5.0(postcss@8.5.6)(typescript@5.9.2) ··· 41 53 version: 5.9.2 42 54 vitest: 43 55 specifier: ^3.2.4 44 - version: 3.2.4(@types/debug@4.1.12)(@types/node@24.2.0) 56 + version: 3.2.4(@types/debug@4.1.12)(@types/node@24.2.1) 45 57 46 58 packages: 47 59 ··· 62 74 resolution: {integrity: sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==} 63 75 engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0} 64 76 77 + '@atcute/atproto@3.1.1': 78 + resolution: {integrity: sha512-D+RLTIPF0xLu7BPZY8KSewAPemJFh+3n3zeQ3ROsLxbTtCHbrTDMAmAFexaVRAPGcPYrwXaBUlv7yZjScJolMg==} 79 + 80 + '@atcute/client@4.0.3': 81 + resolution: {integrity: sha512-RIOZWFVLca/HiPAAUDqQPOdOreCxTbL5cb+WUf5yqQOKIu5yEAP3eksinmlLmgIrlr5qVOE7brazUUzaskFCfw==} 82 + 83 + '@atcute/identity@1.0.3': 84 + resolution: {integrity: sha512-mNMxbKHFGys03A8JXKk0KfMBzdd0vrYMzZZWjpw1nYTs0+ea6bo5S1hwqVUZxHdo1gFHSe/t63jxQIF4yL9aKw==} 85 + 65 86 '@atcute/lex-cli@2.1.1': 66 87 resolution: {integrity: sha512-QaR0sOP8Z24opGHKsSfleDbP/ahUb6HECkVaOqSwG7ORZzbLK1w0265o1BRjCVr2dT6FxlsMUa2Ge85JMA9bxg==} 67 88 hasBin: true ··· 72 93 '@atcute/lexicons@1.1.0': 73 94 resolution: {integrity: sha512-LFqwnria78xLYb62Ri/+WwQpUTgZp2DuyolNGIIOV1dpiKhFFFh//nscHMA6IExFLQRqWDs3tTjy7zv0h3sf1Q==} 74 95 75 - '@atproto/api@0.16.1': 76 - resolution: {integrity: sha512-w48BlTmzKym7nZETWxgiuUX/wwRXU3xsLLKORWo/xtGnwlvpchUFnHKI3k4ttYJ2/JQE59+/4C16BaLzDyiU2w==} 96 + '@atproto/api@0.16.2': 97 + resolution: {integrity: sha512-sSTg31J8ws8DNaoiizp+/uJideRxRaJsq+Nyl8rnSxGw0w3oCvoeRU19iRWh2t0jZEmiRJAGkveGu23NKmPYEQ==} 77 98 78 99 '@atproto/common-web@0.4.2': 79 100 resolution: {integrity: sha512-vrXwGNoFGogodjQvJDxAeP3QbGtawgZute2ed1XdRO0wMixLk3qewtikZm06H259QDJVu6voKC5mubml+WgQUw==} 80 - 81 - '@atproto/did@0.1.5': 82 - resolution: {integrity: sha512-8+1D08QdGE5TF0bB0vV8HLVrVZJeLNITpRTUVEoABNMRaUS7CoYSVb0+JNQDeJIVmqMjOL8dOjvCUDkp3gEaGQ==} 83 101 84 102 '@atproto/lexicon@0.4.12': 85 103 resolution: {integrity: sha512-fcEvEQ1GpQYF5igZ4IZjPWEoWVpsEF22L9RexxLS3ptfySXLflEyH384e7HITzO/73McDeaJx3lqHIuqn9ulnw==} ··· 102 120 resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==} 103 121 engines: {node: '>=6.0.0'} 104 122 hasBin: true 123 + 124 + '@babel/runtime@7.28.2': 125 + resolution: {integrity: sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==} 126 + engines: {node: '>=6.9.0'} 105 127 106 128 '@babel/types@7.28.2': 107 129 resolution: {integrity: sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==} ··· 166 188 167 189 '@capsizecss/unpack@2.4.0': 168 190 resolution: {integrity: sha512-GrSU71meACqcmIUxPYOJvGKF0yryjN/L1aCuE9DViCTJI7bfkjgYDPD1zbNDcINJwSSP6UaBZY9GAbYDO7re0Q==} 191 + 192 + '@changesets/apply-release-plan@7.0.12': 193 + resolution: {integrity: sha512-EaET7As5CeuhTzvXTQCRZeBUcisoYPDDcXvgTE/2jmmypKp0RC7LxKj/yzqeh/1qFTZI7oDGFcL1PHRuQuketQ==} 194 + 195 + '@changesets/assemble-release-plan@6.0.9': 196 + resolution: {integrity: sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ==} 197 + 198 + '@changesets/changelog-git@0.2.1': 199 + resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} 200 + 201 + '@changesets/cli@2.29.5': 202 + resolution: {integrity: sha512-0j0cPq3fgxt2dPdFsg4XvO+6L66RC0pZybT9F4dG5TBrLA3jA/1pNkdTXH9IBBVHkgsKrNKenI3n1mPyPlIydg==} 203 + hasBin: true 204 + 205 + '@changesets/config@3.1.1': 206 + resolution: {integrity: sha512-bd+3Ap2TKXxljCggI0mKPfzCQKeV/TU4yO2h2C6vAihIo8tzseAn2e7klSuiyYYXvgu53zMN1OeYMIQkaQoWnA==} 207 + 208 + '@changesets/errors@0.2.0': 209 + resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} 210 + 211 + '@changesets/get-dependents-graph@2.1.3': 212 + resolution: {integrity: sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==} 213 + 214 + '@changesets/get-release-plan@4.0.13': 215 + resolution: {integrity: sha512-DWG1pus72FcNeXkM12tx+xtExyH/c9I1z+2aXlObH3i9YA7+WZEVaiHzHl03thpvAgWTRaH64MpfHxozfF7Dvg==} 216 + 217 + '@changesets/get-version-range-type@0.4.0': 218 + resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} 219 + 220 + '@changesets/git@3.0.4': 221 + resolution: {integrity: sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==} 222 + 223 + '@changesets/logger@0.1.1': 224 + resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} 225 + 226 + '@changesets/parse@0.4.1': 227 + resolution: {integrity: sha512-iwksMs5Bf/wUItfcg+OXrEpravm5rEd9Bf4oyIPL4kVTmJQ7PNDSd6MDYkpSJR1pn7tz/k8Zf2DhTCqX08Ou+Q==} 228 + 229 + '@changesets/pre@2.0.2': 230 + resolution: {integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==} 231 + 232 + '@changesets/read@0.6.5': 233 + resolution: {integrity: sha512-UPzNGhsSjHD3Veb0xO/MwvasGe8eMyNrR/sT9gR8Q3DhOQZirgKhhXv/8hVsI0QpPjR004Z9iFxoJU6in3uGMg==} 234 + 235 + '@changesets/should-skip-package@0.1.2': 236 + resolution: {integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==} 237 + 238 + '@changesets/types@4.1.0': 239 + resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} 240 + 241 + '@changesets/types@6.1.0': 242 + resolution: {integrity: sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==} 243 + 244 + '@changesets/write@0.4.0': 245 + resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} 169 246 170 247 '@emnapi/runtime@1.4.5': 171 248 resolution: {integrity: sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==} ··· 453 530 '@jridgewell/trace-mapping@0.3.29': 454 531 resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==} 455 532 533 + '@manypkg/find-root@1.1.0': 534 + resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} 535 + 536 + '@manypkg/get-packages@1.1.3': 537 + resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} 538 + 539 + '@nodelib/fs.scandir@2.1.5': 540 + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 541 + engines: {node: '>= 8'} 542 + 543 + '@nodelib/fs.stat@2.0.5': 544 + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 545 + engines: {node: '>= 8'} 546 + 547 + '@nodelib/fs.walk@1.2.8': 548 + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 549 + engines: {node: '>= 8'} 550 + 456 551 '@oslojs/encoding@1.1.0': 457 552 resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} 458 553 ··· 593 688 '@swc/helpers@0.5.17': 594 689 resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} 595 690 691 + '@types/bun@1.2.19': 692 + resolution: {integrity: sha512-d9ZCmrH3CJ2uYKXQIUuZ/pUnTqIvLDS0SK7pFmbx8ma+ziH/FRMoAq5bYpRG7y+w1gl+HgyNZbtqgMq4W4e2Lg==} 693 + 596 694 '@types/chai@5.2.2': 597 695 resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} 598 696 ··· 620 718 '@types/nlcst@2.0.3': 621 719 resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==} 622 720 623 - '@types/node@24.2.0': 624 - resolution: {integrity: sha512-3xyG3pMCq3oYCNg7/ZP+E1ooTaGB4cG8JWRsqqOYQdbWNY4zbaV0Ennrd7stjiJEFZCaybcIgpTjJWHRfBSIDw==} 721 + '@types/node@12.20.55': 722 + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} 723 + 724 + '@types/node@24.2.1': 725 + resolution: {integrity: sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ==} 726 + 727 + '@types/react@19.1.9': 728 + resolution: {integrity: sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA==} 625 729 626 730 '@types/sanitize-html@2.16.0': 627 731 resolution: {integrity: sha512-l6rX1MUXje5ztPT0cAFtUayXF06DqPhRyfVXareEN5gGCFaP/iwsxIyKODr9XDhfxPpN6vXUFNfo5kZMXCxBtw==} ··· 669 773 ansi-align@3.0.1: 670 774 resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} 671 775 776 + ansi-colors@4.1.3: 777 + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} 778 + engines: {node: '>=6'} 779 + 672 780 ansi-regex@5.0.1: 673 781 resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 674 782 engines: {node: '>=8'} ··· 692 800 resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} 693 801 engines: {node: '>= 8'} 694 802 803 + argparse@1.0.10: 804 + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} 805 + 695 806 argparse@2.0.1: 696 807 resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 697 808 ··· 702 813 array-iterate@2.0.1: 703 814 resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==} 704 815 816 + array-union@2.1.0: 817 + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} 818 + engines: {node: '>=8'} 819 + 705 820 assertion-error@2.0.1: 706 821 resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} 707 822 engines: {node: '>=12'} 708 823 709 - astro@5.12.8: 710 - resolution: {integrity: sha512-KkJ7FR+c2SyZYlpakm48XBiuQcRsrVtdjG5LN5an0givI/tLik+ePJ4/g3qrAVhYMjJOxBA2YgFQxANPiWB+Mw==} 824 + astro@5.12.9: 825 + resolution: {integrity: sha512-cZ7kZ61jyE5nwSrFKSRyf5Gds+uJELqQxJFqMkcgiWQvhWZJUSShn8Uz3yc9WLyLw5Kim5P5un9SkJSGogfEZQ==} 711 826 engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'} 712 827 hasBin: true 713 828 ··· 729 844 730 845 base64-js@1.5.1: 731 846 resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} 847 + 848 + better-path-resolve@1.0.0: 849 + resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} 850 + engines: {node: '>=4'} 732 851 733 852 blob-to-buffer@1.2.9: 734 853 resolution: {integrity: sha512-BF033y5fN6OCofD3vgHmNtwZWRcq9NLyyxyILx9hfMy1sXYy4ojFl765hJ2lP0YaN2fuxPaLO2Vzzoxy0FLFFA==} ··· 740 859 brace-expansion@2.0.2: 741 860 resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} 742 861 862 + braces@3.0.3: 863 + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 864 + engines: {node: '>=8'} 865 + 743 866 brotli@1.3.3: 744 867 resolution: {integrity: sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==} 868 + 869 + bun-types@1.2.19: 870 + resolution: {integrity: sha512-uAOTaZSPuYsWIXRpj7o56Let0g/wjihKCkeRqUBhlLVM/Bt+Fj9xTo+LhC1OV1XDaGkz4hNC80et5xgy+9KTHQ==} 871 + peerDependencies: 872 + '@types/react': ^19 745 873 746 874 bundle-require@5.1.0: 747 875 resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} ··· 777 905 character-entities@2.0.2: 778 906 resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} 779 907 908 + chardet@0.7.0: 909 + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} 910 + 780 911 check-error@2.1.1: 781 912 resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} 782 913 engines: {node: '>= 16'} ··· 785 916 resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} 786 917 engines: {node: '>= 14.16.0'} 787 918 919 + ci-info@3.9.0: 920 + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} 921 + engines: {node: '>=8'} 922 + 788 923 ci-info@4.3.0: 789 924 resolution: {integrity: sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==} 790 925 engines: {node: '>=8'} ··· 821 956 commander@4.1.1: 822 957 resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} 823 958 engines: {node: '>= 6'} 959 + 960 + commander@8.3.0: 961 + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} 962 + engines: {node: '>= 12'} 824 963 825 964 common-ancestor-path@1.0.1: 826 965 resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} ··· 858 997 engines: {node: '>=4'} 859 998 hasBin: true 860 999 1000 + csstype@3.1.3: 1001 + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} 1002 + 861 1003 debug@4.4.1: 862 1004 resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} 863 1005 engines: {node: '>=6.0'} ··· 887 1029 888 1030 destr@2.0.5: 889 1031 resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} 1032 + 1033 + detect-indent@6.1.0: 1034 + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} 1035 + engines: {node: '>=8'} 890 1036 891 1037 detect-libc@2.0.4: 892 1038 resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} ··· 909 1055 resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} 910 1056 engines: {node: '>=0.3.1'} 911 1057 1058 + dir-glob@3.0.1: 1059 + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} 1060 + engines: {node: '>=8'} 1061 + 912 1062 dlv@1.1.3: 913 1063 resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} 914 1064 ··· 941 1091 emoji-regex@9.2.2: 942 1092 resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} 943 1093 1094 + enquirer@2.4.1: 1095 + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} 1096 + engines: {node: '>=8.6'} 1097 + 944 1098 entities@4.5.0: 945 1099 resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} 946 1100 engines: {node: '>=0.12'} ··· 967 1121 968 1122 esm-env@1.2.2: 969 1123 resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} 1124 + 1125 + esprima@4.0.1: 1126 + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} 1127 + engines: {node: '>=4'} 1128 + hasBin: true 970 1129 971 1130 estree-walker@2.0.2: 972 1131 resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} ··· 984 1143 extend@3.0.2: 985 1144 resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} 986 1145 1146 + extendable-error@0.1.7: 1147 + resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} 1148 + 1149 + external-editor@3.1.0: 1150 + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} 1151 + engines: {node: '>=4'} 1152 + 987 1153 fast-deep-equal@3.1.3: 988 1154 resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 1155 + 1156 + fast-glob@3.3.3: 1157 + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} 1158 + engines: {node: '>=8.6.0'} 1159 + 1160 + fastq@1.19.1: 1161 + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} 989 1162 990 1163 fdir@6.4.6: 991 1164 resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} ··· 995 1168 picomatch: 996 1169 optional: true 997 1170 1171 + fill-range@7.1.1: 1172 + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 1173 + engines: {node: '>=8'} 1174 + 1175 + find-up@4.1.0: 1176 + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} 1177 + engines: {node: '>=8'} 1178 + 998 1179 fix-dts-default-cjs-exports@1.0.1: 999 1180 resolution: {integrity: sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==} 1000 1181 ··· 1012 1193 resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} 1013 1194 engines: {node: '>=14'} 1014 1195 1196 + fs-extra@7.0.1: 1197 + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} 1198 + engines: {node: '>=6 <7 || >=8'} 1199 + 1200 + fs-extra@8.1.0: 1201 + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} 1202 + engines: {node: '>=6 <7 || >=8'} 1203 + 1015 1204 fsevents@2.3.3: 1016 1205 resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 1017 1206 engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} ··· 1023 1212 1024 1213 github-slugger@2.0.0: 1025 1214 resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} 1215 + 1216 + glob-parent@5.1.2: 1217 + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 1218 + engines: {node: '>= 6'} 1026 1219 1027 1220 glob@10.4.5: 1028 1221 resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} 1029 1222 hasBin: true 1223 + 1224 + globby@11.1.0: 1225 + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} 1226 + engines: {node: '>=10'} 1227 + 1228 + graceful-fs@4.2.11: 1229 + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} 1030 1230 1031 1231 graphemer@1.4.0: 1032 1232 resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} ··· 1076 1276 http-cache-semantics@4.2.0: 1077 1277 resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} 1078 1278 1279 + human-id@4.1.1: 1280 + resolution: {integrity: sha512-3gKm/gCSUipeLsRYZbbdA1BD83lBoWUkZ7G9VFrhWPAU76KwYo5KR8V28bpoPm/ygy0x5/GCbpRQdY7VLYCoIg==} 1281 + hasBin: true 1282 + 1283 + iconv-lite@0.4.24: 1284 + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} 1285 + engines: {node: '>=0.10.0'} 1286 + 1287 + ignore@5.3.2: 1288 + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} 1289 + engines: {node: '>= 4'} 1290 + 1079 1291 import-meta-resolve@4.1.0: 1080 1292 resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} 1081 1293 ··· 1090 1302 engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 1091 1303 hasBin: true 1092 1304 1305 + is-extglob@2.1.1: 1306 + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 1307 + engines: {node: '>=0.10.0'} 1308 + 1093 1309 is-fullwidth-code-point@3.0.0: 1094 1310 resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 1095 1311 engines: {node: '>=8'} 1096 1312 1313 + is-glob@4.0.3: 1314 + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 1315 + engines: {node: '>=0.10.0'} 1316 + 1097 1317 is-inside-container@1.0.0: 1098 1318 resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} 1099 1319 engines: {node: '>=14.16'} 1100 1320 hasBin: true 1101 1321 1322 + is-number@7.0.0: 1323 + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 1324 + engines: {node: '>=0.12.0'} 1325 + 1102 1326 is-plain-obj@4.1.0: 1103 1327 resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} 1104 1328 engines: {node: '>=12'} ··· 1107 1331 resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} 1108 1332 engines: {node: '>=0.10.0'} 1109 1333 1334 + is-subdir@1.2.0: 1335 + resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} 1336 + engines: {node: '>=4'} 1337 + 1338 + is-windows@1.0.2: 1339 + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} 1340 + engines: {node: '>=0.10.0'} 1341 + 1110 1342 is-wsl@3.1.0: 1111 1343 resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} 1112 1344 engines: {node: '>=16'} ··· 1127 1359 js-tokens@9.0.1: 1128 1360 resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} 1129 1361 1362 + js-yaml@3.14.1: 1363 + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} 1364 + hasBin: true 1365 + 1130 1366 js-yaml@4.1.0: 1131 1367 resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} 1132 1368 hasBin: true 1133 1369 1370 + jsonfile@4.0.0: 1371 + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} 1372 + 1373 + katex@0.16.22: 1374 + resolution: {integrity: sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==} 1375 + hasBin: true 1376 + 1134 1377 kleur@3.0.3: 1135 1378 resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} 1136 1379 engines: {node: '>=6'} ··· 1150 1393 resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} 1151 1394 engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 1152 1395 1396 + locate-path@5.0.0: 1397 + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} 1398 + engines: {node: '>=8'} 1399 + 1153 1400 lodash.sortby@4.7.0: 1154 1401 resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} 1155 1402 1403 + lodash.startcase@4.4.0: 1404 + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} 1405 + 1156 1406 longest-streak@3.1.0: 1157 1407 resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} 1158 1408 ··· 1212 1462 1213 1463 mdn-data@2.12.2: 1214 1464 resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} 1465 + 1466 + merge2@1.4.1: 1467 + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 1468 + engines: {node: '>= 8'} 1215 1469 1216 1470 micromark-core-commonmark@2.0.3: 1217 1471 resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} ··· 1297 1551 micromark@4.0.2: 1298 1552 resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} 1299 1553 1554 + micromatch@4.0.8: 1555 + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 1556 + engines: {node: '>=8.6'} 1557 + 1300 1558 minimatch@9.0.5: 1301 1559 resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} 1302 1560 engines: {node: '>=16 || 14 >=14.17'} ··· 1307 1565 1308 1566 mlly@1.7.4: 1309 1567 resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} 1568 + 1569 + mri@1.2.0: 1570 + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} 1571 + engines: {node: '>=4'} 1310 1572 1311 1573 mrmime@2.0.1: 1312 1574 resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} ··· 1368 1630 oniguruma-to-es@4.3.3: 1369 1631 resolution: {integrity: sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg==} 1370 1632 1633 + os-tmpdir@1.0.2: 1634 + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} 1635 + engines: {node: '>=0.10.0'} 1636 + 1637 + outdent@0.5.0: 1638 + resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} 1639 + 1640 + p-filter@2.1.0: 1641 + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} 1642 + engines: {node: '>=8'} 1643 + 1644 + p-limit@2.3.0: 1645 + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} 1646 + engines: {node: '>=6'} 1647 + 1371 1648 p-limit@6.2.0: 1372 1649 resolution: {integrity: sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==} 1373 1650 engines: {node: '>=18'} 1374 1651 1652 + p-locate@4.1.0: 1653 + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} 1654 + engines: {node: '>=8'} 1655 + 1656 + p-map@2.1.0: 1657 + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} 1658 + engines: {node: '>=6'} 1659 + 1375 1660 p-queue@8.1.0: 1376 1661 resolution: {integrity: sha512-mxLDbbGIBEXTJL0zEx8JIylaj3xQ7Z/7eEVjcF9fJX4DBiH9oqe+oahYnlKKxm0Ci9TlWTyhSHgygxMxjIB2jw==} 1377 1662 engines: {node: '>=18'} ··· 1379 1664 p-timeout@6.1.4: 1380 1665 resolution: {integrity: sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==} 1381 1666 engines: {node: '>=14.16'} 1667 + 1668 + p-try@2.2.0: 1669 + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} 1670 + engines: {node: '>=6'} 1382 1671 1383 1672 package-json-from-dist@1.0.1: 1384 1673 resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} 1385 1674 1675 + package-manager-detector@0.2.11: 1676 + resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==} 1677 + 1386 1678 package-manager-detector@1.3.0: 1387 1679 resolution: {integrity: sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==} 1388 1680 ··· 1398 1690 parse5@7.3.0: 1399 1691 resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} 1400 1692 1693 + path-exists@4.0.0: 1694 + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 1695 + engines: {node: '>=8'} 1696 + 1401 1697 path-key@3.1.1: 1402 1698 resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1403 1699 engines: {node: '>=8'} ··· 1405 1701 path-scurry@1.11.1: 1406 1702 resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} 1407 1703 engines: {node: '>=16 || 14 >=14.18'} 1704 + 1705 + path-type@4.0.0: 1706 + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} 1707 + engines: {node: '>=8'} 1408 1708 1409 1709 pathe@2.0.3: 1410 1710 resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} ··· 1424 1724 resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} 1425 1725 engines: {node: '>=12'} 1426 1726 1727 + pify@4.0.1: 1728 + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} 1729 + engines: {node: '>=6'} 1730 + 1427 1731 pirates@4.0.7: 1428 1732 resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} 1429 1733 engines: {node: '>= 6'} ··· 1452 1756 postcss@8.5.6: 1453 1757 resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} 1454 1758 engines: {node: ^10 || ^12 || >=14} 1759 + 1760 + prettier@2.8.8: 1761 + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} 1762 + engines: {node: '>=10.13.0'} 1763 + hasBin: true 1455 1764 1456 1765 prettier@3.6.2: 1457 1766 resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} ··· 1476 1785 resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 1477 1786 engines: {node: '>=6'} 1478 1787 1788 + quansync@0.2.10: 1789 + resolution: {integrity: sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==} 1790 + 1791 + queue-microtask@1.2.3: 1792 + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1793 + 1479 1794 radix3@1.1.2: 1480 1795 resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} 1796 + 1797 + read-yaml-file@1.1.0: 1798 + resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} 1799 + engines: {node: '>=6'} 1481 1800 1482 1801 readdirp@4.1.2: 1483 1802 resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} ··· 1538 1857 1539 1858 retext@9.0.0: 1540 1859 resolution: {integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==} 1860 + 1861 + reusify@1.1.0: 1862 + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} 1863 + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1541 1864 1542 1865 rollup@4.46.2: 1543 1866 resolution: {integrity: sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==} 1544 1867 engines: {node: '>=18.0.0', npm: '>=8.0.0'} 1545 1868 hasBin: true 1546 1869 1870 + run-parallel@1.2.0: 1871 + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1872 + 1873 + safer-buffer@2.1.2: 1874 + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} 1875 + 1547 1876 sanitize-html@2.17.0: 1548 1877 resolution: {integrity: sha512-dLAADUSS8rBwhaevT12yCezvioCA+bmUTPH/u57xKPT8d++voeYE6HeluA/bPbQ15TwDBG2ii+QZIEmYx8VdxA==} 1549 1878 ··· 1580 1909 sisteransi@1.0.5: 1581 1910 resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} 1582 1911 1583 - smol-toml@1.4.1: 1584 - resolution: {integrity: sha512-CxdwHXyYTONGHThDbq5XdwbFsuY4wlClRGejfE2NtwUtiHYsP1QtNsHb/hnj31jKYSchztJsaA8pSQoVzkfCFg==} 1912 + slash@3.0.0: 1913 + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} 1914 + engines: {node: '>=8'} 1915 + 1916 + smol-toml@1.4.2: 1917 + resolution: {integrity: sha512-rInDH6lCNiEyn3+hH8KVGFdbjc099j47+OSgbMrfDYX1CmXLfdKd7qi6IfcWj2wFxvSVkuI46M+wPGYfEOEj6g==} 1585 1918 engines: {node: '>= 18'} 1586 1919 1587 1920 source-map-js@1.2.1: ··· 1596 1929 space-separated-tokens@2.0.2: 1597 1930 resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} 1598 1931 1932 + spawndamnit@3.0.1: 1933 + resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} 1934 + 1935 + sprintf-js@1.0.3: 1936 + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} 1937 + 1599 1938 stackback@0.0.2: 1600 1939 resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} 1601 1940 ··· 1625 1964 resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} 1626 1965 engines: {node: '>=12'} 1627 1966 1967 + strip-bom@3.0.0: 1968 + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} 1969 + engines: {node: '>=4'} 1970 + 1628 1971 strip-literal@3.0.0: 1629 1972 resolution: {integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==} 1630 1973 ··· 1633 1976 engines: {node: '>=16 || 14 >=14.17'} 1634 1977 hasBin: true 1635 1978 1979 + term-size@2.2.1: 1980 + resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} 1981 + engines: {node: '>=8'} 1982 + 1636 1983 thenify-all@1.6.0: 1637 1984 resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} 1638 1985 engines: {node: '>=0.8'} ··· 1669 2016 resolution: {integrity: sha512-AldGGlDP0PNgwppe2quAvuBl18UcjuNtOnDuUkqhd6ipPqrYYBt3aTxK1QTsBVknk97lS2JcafWMghjGWFtunw==} 1670 2017 hasBin: true 1671 2018 2019 + tmp@0.0.33: 2020 + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} 2021 + engines: {node: '>=0.6.0'} 2022 + 2023 + to-regex-range@5.0.1: 2024 + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 2025 + engines: {node: '>=8.0'} 2026 + 1672 2027 tr46@0.0.3: 1673 2028 resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} 1674 2029 ··· 1783 2138 unist-util-visit@5.0.0: 1784 2139 resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} 1785 2140 2141 + universalify@0.1.2: 2142 + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} 2143 + engines: {node: '>= 4.0.0'} 2144 + 1786 2145 unstorage@1.16.1: 1787 2146 resolution: {integrity: sha512-gdpZ3guLDhz+zWIlYP1UwQ259tG5T5vYRzDaHMkQ1bBY1SQPutvZnrRjTFaWUUpseErJIgAZS51h6NOcZVZiqQ==} 1788 2147 peerDependencies: ··· 1896 2255 yaml: 1897 2256 optional: true 1898 2257 1899 - vite@7.0.6: 1900 - resolution: {integrity: sha512-MHFiOENNBd+Bd9uvc8GEsIzdkn1JxMmEeYX35tI3fv0sJBUTfW5tQsoaOwuY4KhBI09A3dUJ/DXf2yxPVPUceg==} 2258 + vite@7.1.1: 2259 + resolution: {integrity: sha512-yJ+Mp7OyV+4S+afWo+QyoL9jFWD11QFH0i5i7JypnfTcA1rmgxCbiA8WwAICDEtZ1Z1hzrVhN8R8rGTqkTY8ZQ==} 1901 2260 engines: {node: ^20.19.0 || >=22.12.0} 1902 2261 hasBin: true 1903 2262 peerDependencies: ··· 2076 2435 remark-rehype: 11.1.2 2077 2436 remark-smartypants: 3.0.2 2078 2437 shiki: 3.9.2 2079 - smol-toml: 1.4.1 2438 + smol-toml: 1.4.2 2080 2439 unified: 11.0.5 2081 2440 unist-util-remove-position: 5.0.0 2082 2441 unist-util-visit: 5.0.0 ··· 2101 2460 transitivePeerDependencies: 2102 2461 - supports-color 2103 2462 2463 + '@atcute/atproto@3.1.1': 2464 + dependencies: 2465 + '@atcute/lexicons': 1.1.0 2466 + 2467 + '@atcute/client@4.0.3': 2468 + dependencies: 2469 + '@atcute/identity': 1.0.3 2470 + '@atcute/lexicons': 1.1.0 2471 + 2472 + '@atcute/identity@1.0.3': 2473 + dependencies: 2474 + '@atcute/lexicons': 1.1.0 2475 + '@badrap/valita': 0.4.6 2476 + 2104 2477 '@atcute/lex-cli@2.1.1': 2105 2478 dependencies: 2106 2479 '@atcute/lexicon-doc': 1.0.3 ··· 2117 2490 dependencies: 2118 2491 esm-env: 1.2.2 2119 2492 2120 - '@atproto/api@0.16.1': 2493 + '@atproto/api@0.16.2': 2121 2494 dependencies: 2122 2495 '@atproto/common-web': 0.4.2 2123 2496 '@atproto/lexicon': 0.4.12 ··· 2133 2506 graphemer: 1.4.0 2134 2507 multiformats: 9.9.0 2135 2508 uint8arrays: 3.0.0 2136 - zod: 3.25.76 2137 - 2138 - '@atproto/did@0.1.5': 2139 - dependencies: 2140 2509 zod: 3.25.76 2141 2510 2142 2511 '@atproto/lexicon@0.4.12': ··· 2161 2530 '@babel/parser@7.28.0': 2162 2531 dependencies: 2163 2532 '@babel/types': 7.28.2 2533 + 2534 + '@babel/runtime@7.28.2': {} 2164 2535 2165 2536 '@babel/types@7.28.2': 2166 2537 dependencies: ··· 2212 2583 transitivePeerDependencies: 2213 2584 - encoding 2214 2585 2586 + '@changesets/apply-release-plan@7.0.12': 2587 + dependencies: 2588 + '@changesets/config': 3.1.1 2589 + '@changesets/get-version-range-type': 0.4.0 2590 + '@changesets/git': 3.0.4 2591 + '@changesets/should-skip-package': 0.1.2 2592 + '@changesets/types': 6.1.0 2593 + '@manypkg/get-packages': 1.1.3 2594 + detect-indent: 6.1.0 2595 + fs-extra: 7.0.1 2596 + lodash.startcase: 4.4.0 2597 + outdent: 0.5.0 2598 + prettier: 2.8.8 2599 + resolve-from: 5.0.0 2600 + semver: 7.7.2 2601 + 2602 + '@changesets/assemble-release-plan@6.0.9': 2603 + dependencies: 2604 + '@changesets/errors': 0.2.0 2605 + '@changesets/get-dependents-graph': 2.1.3 2606 + '@changesets/should-skip-package': 0.1.2 2607 + '@changesets/types': 6.1.0 2608 + '@manypkg/get-packages': 1.1.3 2609 + semver: 7.7.2 2610 + 2611 + '@changesets/changelog-git@0.2.1': 2612 + dependencies: 2613 + '@changesets/types': 6.1.0 2614 + 2615 + '@changesets/cli@2.29.5': 2616 + dependencies: 2617 + '@changesets/apply-release-plan': 7.0.12 2618 + '@changesets/assemble-release-plan': 6.0.9 2619 + '@changesets/changelog-git': 0.2.1 2620 + '@changesets/config': 3.1.1 2621 + '@changesets/errors': 0.2.0 2622 + '@changesets/get-dependents-graph': 2.1.3 2623 + '@changesets/get-release-plan': 4.0.13 2624 + '@changesets/git': 3.0.4 2625 + '@changesets/logger': 0.1.1 2626 + '@changesets/pre': 2.0.2 2627 + '@changesets/read': 0.6.5 2628 + '@changesets/should-skip-package': 0.1.2 2629 + '@changesets/types': 6.1.0 2630 + '@changesets/write': 0.4.0 2631 + '@manypkg/get-packages': 1.1.3 2632 + ansi-colors: 4.1.3 2633 + ci-info: 3.9.0 2634 + enquirer: 2.4.1 2635 + external-editor: 3.1.0 2636 + fs-extra: 7.0.1 2637 + mri: 1.2.0 2638 + p-limit: 2.3.0 2639 + package-manager-detector: 0.2.11 2640 + picocolors: 1.1.1 2641 + resolve-from: 5.0.0 2642 + semver: 7.7.2 2643 + spawndamnit: 3.0.1 2644 + term-size: 2.2.1 2645 + 2646 + '@changesets/config@3.1.1': 2647 + dependencies: 2648 + '@changesets/errors': 0.2.0 2649 + '@changesets/get-dependents-graph': 2.1.3 2650 + '@changesets/logger': 0.1.1 2651 + '@changesets/types': 6.1.0 2652 + '@manypkg/get-packages': 1.1.3 2653 + fs-extra: 7.0.1 2654 + micromatch: 4.0.8 2655 + 2656 + '@changesets/errors@0.2.0': 2657 + dependencies: 2658 + extendable-error: 0.1.7 2659 + 2660 + '@changesets/get-dependents-graph@2.1.3': 2661 + dependencies: 2662 + '@changesets/types': 6.1.0 2663 + '@manypkg/get-packages': 1.1.3 2664 + picocolors: 1.1.1 2665 + semver: 7.7.2 2666 + 2667 + '@changesets/get-release-plan@4.0.13': 2668 + dependencies: 2669 + '@changesets/assemble-release-plan': 6.0.9 2670 + '@changesets/config': 3.1.1 2671 + '@changesets/pre': 2.0.2 2672 + '@changesets/read': 0.6.5 2673 + '@changesets/types': 6.1.0 2674 + '@manypkg/get-packages': 1.1.3 2675 + 2676 + '@changesets/get-version-range-type@0.4.0': {} 2677 + 2678 + '@changesets/git@3.0.4': 2679 + dependencies: 2680 + '@changesets/errors': 0.2.0 2681 + '@manypkg/get-packages': 1.1.3 2682 + is-subdir: 1.2.0 2683 + micromatch: 4.0.8 2684 + spawndamnit: 3.0.1 2685 + 2686 + '@changesets/logger@0.1.1': 2687 + dependencies: 2688 + picocolors: 1.1.1 2689 + 2690 + '@changesets/parse@0.4.1': 2691 + dependencies: 2692 + '@changesets/types': 6.1.0 2693 + js-yaml: 3.14.1 2694 + 2695 + '@changesets/pre@2.0.2': 2696 + dependencies: 2697 + '@changesets/errors': 0.2.0 2698 + '@changesets/types': 6.1.0 2699 + '@manypkg/get-packages': 1.1.3 2700 + fs-extra: 7.0.1 2701 + 2702 + '@changesets/read@0.6.5': 2703 + dependencies: 2704 + '@changesets/git': 3.0.4 2705 + '@changesets/logger': 0.1.1 2706 + '@changesets/parse': 0.4.1 2707 + '@changesets/types': 6.1.0 2708 + fs-extra: 7.0.1 2709 + p-filter: 2.1.0 2710 + picocolors: 1.1.1 2711 + 2712 + '@changesets/should-skip-package@0.1.2': 2713 + dependencies: 2714 + '@changesets/types': 6.1.0 2715 + '@manypkg/get-packages': 1.1.3 2716 + 2717 + '@changesets/types@4.1.0': {} 2718 + 2719 + '@changesets/types@6.1.0': {} 2720 + 2721 + '@changesets/write@0.4.0': 2722 + dependencies: 2723 + '@changesets/types': 6.1.0 2724 + fs-extra: 7.0.1 2725 + human-id: 4.1.1 2726 + prettier: 2.8.8 2727 + 2215 2728 '@emnapi/runtime@1.4.5': 2216 2729 dependencies: 2217 2730 tslib: 2.8.1 ··· 2397 2910 '@jridgewell/resolve-uri': 3.1.2 2398 2911 '@jridgewell/sourcemap-codec': 1.5.4 2399 2912 2913 + '@manypkg/find-root@1.1.0': 2914 + dependencies: 2915 + '@babel/runtime': 7.28.2 2916 + '@types/node': 12.20.55 2917 + find-up: 4.1.0 2918 + fs-extra: 8.1.0 2919 + 2920 + '@manypkg/get-packages@1.1.3': 2921 + dependencies: 2922 + '@babel/runtime': 7.28.2 2923 + '@changesets/types': 4.1.0 2924 + '@manypkg/find-root': 1.1.0 2925 + fs-extra: 8.1.0 2926 + globby: 11.1.0 2927 + read-yaml-file: 1.1.0 2928 + 2929 + '@nodelib/fs.scandir@2.1.5': 2930 + dependencies: 2931 + '@nodelib/fs.stat': 2.0.5 2932 + run-parallel: 1.2.0 2933 + 2934 + '@nodelib/fs.stat@2.0.5': {} 2935 + 2936 + '@nodelib/fs.walk@1.2.8': 2937 + dependencies: 2938 + '@nodelib/fs.scandir': 2.1.5 2939 + fastq: 1.19.1 2940 + 2400 2941 '@oslojs/encoding@1.1.0': {} 2401 2942 2402 2943 '@pkgjs/parseargs@0.11.0': ··· 2507 3048 dependencies: 2508 3049 tslib: 2.8.1 2509 3050 3051 + '@types/bun@1.2.19(@types/react@19.1.9)': 3052 + dependencies: 3053 + bun-types: 1.2.19(@types/react@19.1.9) 3054 + transitivePeerDependencies: 3055 + - '@types/react' 3056 + 2510 3057 '@types/chai@5.2.2': 2511 3058 dependencies: 2512 3059 '@types/deep-eql': 4.0.2 ··· 2521 3068 2522 3069 '@types/fontkit@2.0.8': 2523 3070 dependencies: 2524 - '@types/node': 24.2.0 3071 + '@types/node': 24.2.1 2525 3072 2526 3073 '@types/hast@3.0.4': 2527 3074 dependencies: ··· 2537 3084 dependencies: 2538 3085 '@types/unist': 3.0.3 2539 3086 2540 - '@types/node@24.2.0': 3087 + '@types/node@12.20.55': {} 3088 + 3089 + '@types/node@24.2.1': 2541 3090 dependencies: 2542 3091 undici-types: 7.10.0 2543 3092 3093 + '@types/react@19.1.9': 3094 + dependencies: 3095 + csstype: 3.1.3 3096 + 2544 3097 '@types/sanitize-html@2.16.0': 2545 3098 dependencies: 2546 3099 htmlparser2: 8.0.2 ··· 2557 3110 chai: 5.2.1 2558 3111 tinyrainbow: 2.0.0 2559 3112 2560 - '@vitest/mocker@3.2.4(vite@7.0.6(@types/node@24.2.0))': 3113 + '@vitest/mocker@3.2.4(vite@7.1.1(@types/node@24.2.1))': 2561 3114 dependencies: 2562 3115 '@vitest/spy': 3.2.4 2563 3116 estree-walker: 3.0.3 2564 3117 magic-string: 0.30.17 2565 3118 optionalDependencies: 2566 - vite: 7.0.6(@types/node@24.2.0) 3119 + vite: 7.1.1(@types/node@24.2.1) 2567 3120 2568 3121 '@vitest/pretty-format@3.2.4': 2569 3122 dependencies: ··· 2597 3150 dependencies: 2598 3151 string-width: 4.2.3 2599 3152 3153 + ansi-colors@4.1.3: {} 3154 + 2600 3155 ansi-regex@5.0.1: {} 2601 3156 2602 3157 ansi-regex@6.1.0: {} ··· 2614 3169 normalize-path: 3.0.0 2615 3170 picomatch: 2.3.1 2616 3171 3172 + argparse@1.0.10: 3173 + dependencies: 3174 + sprintf-js: 1.0.3 3175 + 2617 3176 argparse@2.0.1: {} 2618 3177 2619 3178 aria-query@5.3.2: {} 2620 3179 2621 3180 array-iterate@2.0.1: {} 2622 3181 3182 + array-union@2.1.0: {} 3183 + 2623 3184 assertion-error@2.0.1: {} 2624 3185 2625 - astro@5.12.8(@types/node@24.2.0)(rollup@4.46.2)(typescript@5.9.2): 3186 + astro@5.12.9(@types/node@24.2.1)(rollup@4.46.2)(typescript@5.9.2): 2626 3187 dependencies: 2627 3188 '@astrojs/compiler': 2.12.2 2628 3189 '@astrojs/internal-helpers': 0.7.1 ··· 2669 3230 rehype: 13.0.2 2670 3231 semver: 7.7.2 2671 3232 shiki: 3.9.2 2672 - smol-toml: 1.4.1 3233 + smol-toml: 1.4.2 2673 3234 tinyexec: 0.3.2 2674 3235 tinyglobby: 0.2.14 2675 3236 tsconfck: 3.1.6(typescript@5.9.2) ··· 2678 3239 unist-util-visit: 5.0.0 2679 3240 unstorage: 1.16.1 2680 3241 vfile: 6.0.3 2681 - vite: 6.3.5(@types/node@24.2.0) 2682 - vitefu: 1.1.1(vite@6.3.5(@types/node@24.2.0)) 3242 + vite: 6.3.5(@types/node@24.2.1) 3243 + vitefu: 1.1.1(vite@6.3.5(@types/node@24.2.1)) 2683 3244 xxhash-wasm: 1.1.0 2684 3245 yargs-parser: 21.1.1 2685 3246 yocto-spinner: 0.2.3 ··· 2735 3296 2736 3297 base64-js@1.5.1: {} 2737 3298 3299 + better-path-resolve@1.0.0: 3300 + dependencies: 3301 + is-windows: 1.0.2 3302 + 2738 3303 blob-to-buffer@1.2.9: {} 2739 3304 2740 3305 boxen@8.0.1: ··· 2752 3317 dependencies: 2753 3318 balanced-match: 1.0.2 2754 3319 3320 + braces@3.0.3: 3321 + dependencies: 3322 + fill-range: 7.1.1 3323 + 2755 3324 brotli@1.3.3: 2756 3325 dependencies: 2757 3326 base64-js: 1.5.1 2758 3327 3328 + bun-types@1.2.19(@types/react@19.1.9): 3329 + dependencies: 3330 + '@types/node': 24.2.1 3331 + '@types/react': 19.1.9 3332 + 2759 3333 bundle-require@5.1.0(esbuild@0.25.8): 2760 3334 dependencies: 2761 3335 esbuild: 0.25.8 ··· 2783 3357 2784 3358 character-entities@2.0.2: {} 2785 3359 3360 + chardet@0.7.0: {} 3361 + 2786 3362 check-error@2.1.1: {} 2787 3363 2788 3364 chokidar@4.0.3: 2789 3365 dependencies: 2790 3366 readdirp: 4.1.2 2791 3367 3368 + ci-info@3.9.0: {} 3369 + 2792 3370 ci-info@4.3.0: {} 2793 3371 2794 3372 cli-boxes@3.0.0: {} ··· 2818 3396 comma-separated-tokens@2.0.3: {} 2819 3397 2820 3398 commander@4.1.1: {} 3399 + 3400 + commander@8.3.0: {} 2821 3401 2822 3402 common-ancestor-path@1.0.1: {} 2823 3403 ··· 2852 3432 2853 3433 cssesc@3.0.0: {} 2854 3434 3435 + csstype@3.1.3: {} 3436 + 2855 3437 debug@4.4.1: 2856 3438 dependencies: 2857 3439 ms: 2.1.3 ··· 2870 3452 2871 3453 destr@2.0.5: {} 2872 3454 3455 + detect-indent@6.1.0: {} 3456 + 2873 3457 detect-libc@2.0.4: 2874 3458 optional: true 2875 3459 ··· 2887 3471 2888 3472 diff@5.2.0: {} 2889 3473 3474 + dir-glob@3.0.1: 3475 + dependencies: 3476 + path-type: 4.0.0 3477 + 2890 3478 dlv@1.1.3: {} 2891 3479 2892 3480 dom-serializer@2.0.0: ··· 2916 3504 emoji-regex@8.0.0: {} 2917 3505 2918 3506 emoji-regex@9.2.2: {} 3507 + 3508 + enquirer@2.4.1: 3509 + dependencies: 3510 + ansi-colors: 4.1.3 3511 + strip-ansi: 6.0.1 2919 3512 2920 3513 entities@4.5.0: {} 2921 3514 ··· 2958 3551 2959 3552 esm-env@1.2.2: {} 2960 3553 3554 + esprima@4.0.1: {} 3555 + 2961 3556 estree-walker@2.0.2: {} 2962 3557 2963 3558 estree-walker@3.0.3: ··· 2970 3565 2971 3566 extend@3.0.2: {} 2972 3567 3568 + extendable-error@0.1.7: {} 3569 + 3570 + external-editor@3.1.0: 3571 + dependencies: 3572 + chardet: 0.7.0 3573 + iconv-lite: 0.4.24 3574 + tmp: 0.0.33 3575 + 2973 3576 fast-deep-equal@3.1.3: {} 2974 3577 3578 + fast-glob@3.3.3: 3579 + dependencies: 3580 + '@nodelib/fs.stat': 2.0.5 3581 + '@nodelib/fs.walk': 1.2.8 3582 + glob-parent: 5.1.2 3583 + merge2: 1.4.1 3584 + micromatch: 4.0.8 3585 + 3586 + fastq@1.19.1: 3587 + dependencies: 3588 + reusify: 1.1.0 3589 + 2975 3590 fdir@6.4.6(picomatch@4.0.3): 2976 3591 optionalDependencies: 2977 3592 picomatch: 4.0.3 3593 + 3594 + fill-range@7.1.1: 3595 + dependencies: 3596 + to-regex-range: 5.0.1 3597 + 3598 + find-up@4.1.0: 3599 + dependencies: 3600 + locate-path: 5.0.0 3601 + path-exists: 4.0.0 2978 3602 2979 3603 fix-dts-default-cjs-exports@1.0.1: 2980 3604 dependencies: ··· 3006 3630 cross-spawn: 7.0.6 3007 3631 signal-exit: 4.1.0 3008 3632 3633 + fs-extra@7.0.1: 3634 + dependencies: 3635 + graceful-fs: 4.2.11 3636 + jsonfile: 4.0.0 3637 + universalify: 0.1.2 3638 + 3639 + fs-extra@8.1.0: 3640 + dependencies: 3641 + graceful-fs: 4.2.11 3642 + jsonfile: 4.0.0 3643 + universalify: 0.1.2 3644 + 3009 3645 fsevents@2.3.3: 3010 3646 optional: true 3011 3647 ··· 3013 3649 3014 3650 github-slugger@2.0.0: {} 3015 3651 3652 + glob-parent@5.1.2: 3653 + dependencies: 3654 + is-glob: 4.0.3 3655 + 3016 3656 glob@10.4.5: 3017 3657 dependencies: 3018 3658 foreground-child: 3.3.1 ··· 3022 3662 package-json-from-dist: 1.0.1 3023 3663 path-scurry: 1.11.1 3024 3664 3665 + globby@11.1.0: 3666 + dependencies: 3667 + array-union: 2.1.0 3668 + dir-glob: 3.0.1 3669 + fast-glob: 3.3.3 3670 + ignore: 5.3.2 3671 + merge2: 1.4.1 3672 + slash: 3.0.0 3673 + 3674 + graceful-fs@4.2.11: {} 3675 + 3025 3676 graphemer@1.4.0: {} 3026 3677 3027 3678 h3@1.15.4: ··· 3136 3787 3137 3788 http-cache-semantics@4.2.0: {} 3138 3789 3790 + human-id@4.1.1: {} 3791 + 3792 + iconv-lite@0.4.24: 3793 + dependencies: 3794 + safer-buffer: 2.1.2 3795 + 3796 + ignore@5.3.2: {} 3797 + 3139 3798 import-meta-resolve@4.1.0: {} 3140 3799 3141 3800 iron-webcrypto@1.2.1: {} ··· 3145 3804 3146 3805 is-docker@3.0.0: {} 3147 3806 3807 + is-extglob@2.1.1: {} 3808 + 3148 3809 is-fullwidth-code-point@3.0.0: {} 3149 3810 3811 + is-glob@4.0.3: 3812 + dependencies: 3813 + is-extglob: 2.1.1 3814 + 3150 3815 is-inside-container@1.0.0: 3151 3816 dependencies: 3152 3817 is-docker: 3.0.0 3153 3818 3819 + is-number@7.0.0: {} 3820 + 3154 3821 is-plain-obj@4.1.0: {} 3155 3822 3156 3823 is-plain-object@5.0.0: {} 3157 3824 3825 + is-subdir@1.2.0: 3826 + dependencies: 3827 + better-path-resolve: 1.0.0 3828 + 3829 + is-windows@1.0.2: {} 3830 + 3158 3831 is-wsl@3.1.0: 3159 3832 dependencies: 3160 3833 is-inside-container: 1.0.0 ··· 3173 3846 3174 3847 js-tokens@9.0.1: {} 3175 3848 3849 + js-yaml@3.14.1: 3850 + dependencies: 3851 + argparse: 1.0.10 3852 + esprima: 4.0.1 3853 + 3176 3854 js-yaml@4.1.0: 3177 3855 dependencies: 3178 3856 argparse: 2.0.1 3179 3857 3858 + jsonfile@4.0.0: 3859 + optionalDependencies: 3860 + graceful-fs: 4.2.11 3861 + 3862 + katex@0.16.22: 3863 + dependencies: 3864 + commander: 8.3.0 3865 + 3180 3866 kleur@3.0.3: {} 3181 3867 3182 3868 kleur@4.1.5: {} ··· 3187 3873 3188 3874 load-tsconfig@0.2.5: {} 3189 3875 3876 + locate-path@5.0.0: 3877 + dependencies: 3878 + p-locate: 4.1.0 3879 + 3190 3880 lodash.sortby@4.7.0: {} 3881 + 3882 + lodash.startcase@4.4.0: {} 3191 3883 3192 3884 longest-streak@3.1.0: {} 3193 3885 ··· 3328 4020 '@types/mdast': 4.0.4 3329 4021 3330 4022 mdn-data@2.12.2: {} 4023 + 4024 + merge2@1.4.1: {} 3331 4025 3332 4026 micromark-core-commonmark@2.0.3: 3333 4027 dependencies: ··· 3520 4214 transitivePeerDependencies: 3521 4215 - supports-color 3522 4216 4217 + micromatch@4.0.8: 4218 + dependencies: 4219 + braces: 3.0.3 4220 + picomatch: 2.3.1 4221 + 3523 4222 minimatch@9.0.5: 3524 4223 dependencies: 3525 4224 brace-expansion: 2.0.2 ··· 3532 4231 pathe: 2.0.3 3533 4232 pkg-types: 1.3.1 3534 4233 ufo: 1.6.1 4234 + 4235 + mri@1.2.0: {} 3535 4236 3536 4237 mrmime@2.0.1: {} 3537 4238 ··· 3581 4282 regex: 6.0.1 3582 4283 regex-recursion: 6.0.2 3583 4284 4285 + os-tmpdir@1.0.2: {} 4286 + 4287 + outdent@0.5.0: {} 4288 + 4289 + p-filter@2.1.0: 4290 + dependencies: 4291 + p-map: 2.1.0 4292 + 4293 + p-limit@2.3.0: 4294 + dependencies: 4295 + p-try: 2.2.0 4296 + 3584 4297 p-limit@6.2.0: 3585 4298 dependencies: 3586 4299 yocto-queue: 1.2.1 3587 4300 4301 + p-locate@4.1.0: 4302 + dependencies: 4303 + p-limit: 2.3.0 4304 + 4305 + p-map@2.1.0: {} 4306 + 3588 4307 p-queue@8.1.0: 3589 4308 dependencies: 3590 4309 eventemitter3: 5.0.1 ··· 3592 4311 3593 4312 p-timeout@6.1.4: {} 3594 4313 4314 + p-try@2.2.0: {} 4315 + 3595 4316 package-json-from-dist@1.0.1: {} 3596 4317 4318 + package-manager-detector@0.2.11: 4319 + dependencies: 4320 + quansync: 0.2.10 4321 + 3597 4322 package-manager-detector@1.3.0: {} 3598 4323 3599 4324 pako@0.2.9: {} ··· 3613 4338 dependencies: 3614 4339 entities: 6.0.1 3615 4340 4341 + path-exists@4.0.0: {} 4342 + 3616 4343 path-key@3.1.1: {} 3617 4344 3618 4345 path-scurry@1.11.1: 3619 4346 dependencies: 3620 4347 lru-cache: 10.4.3 3621 4348 minipass: 7.1.2 4349 + 4350 + path-type@4.0.0: {} 3622 4351 3623 4352 pathe@2.0.3: {} 3624 4353 ··· 3630 4359 3631 4360 picomatch@4.0.3: {} 3632 4361 4362 + pify@4.0.1: {} 4363 + 3633 4364 pirates@4.0.7: {} 3634 4365 3635 4366 pkg-types@1.3.1: ··· 3649 4380 nanoid: 3.3.11 3650 4381 picocolors: 1.1.1 3651 4382 source-map-js: 1.2.1 4383 + 4384 + prettier@2.8.8: {} 3652 4385 3653 4386 prettier@3.6.2: {} 3654 4387 ··· 3665 4398 3666 4399 punycode@2.3.1: {} 3667 4400 4401 + quansync@0.2.10: {} 4402 + 4403 + queue-microtask@1.2.3: {} 4404 + 3668 4405 radix3@1.1.2: {} 4406 + 4407 + read-yaml-file@1.1.0: 4408 + dependencies: 4409 + graceful-fs: 4.2.11 4410 + js-yaml: 3.14.1 4411 + pify: 4.0.1 4412 + strip-bom: 3.0.0 3669 4413 3670 4414 readdirp@4.1.2: {} 3671 4415 ··· 3774 4518 retext-stringify: 4.0.0 3775 4519 unified: 11.0.5 3776 4520 4521 + reusify@1.1.0: {} 4522 + 3777 4523 rollup@4.46.2: 3778 4524 dependencies: 3779 4525 '@types/estree': 1.0.8 ··· 3800 4546 '@rollup/rollup-win32-x64-msvc': 4.46.2 3801 4547 fsevents: 2.3.3 3802 4548 4549 + run-parallel@1.2.0: 4550 + dependencies: 4551 + queue-microtask: 1.2.3 4552 + 4553 + safer-buffer@2.1.2: {} 4554 + 3803 4555 sanitize-html@2.17.0: 3804 4556 dependencies: 3805 4557 deepmerge: 4.3.1 ··· 3866 4618 3867 4619 sisteransi@1.0.5: {} 3868 4620 3869 - smol-toml@1.4.1: {} 4621 + slash@3.0.0: {} 4622 + 4623 + smol-toml@1.4.2: {} 3870 4624 3871 4625 source-map-js@1.2.1: {} 3872 4626 ··· 3875 4629 whatwg-url: 7.1.0 3876 4630 3877 4631 space-separated-tokens@2.0.2: {} 4632 + 4633 + spawndamnit@3.0.1: 4634 + dependencies: 4635 + cross-spawn: 7.0.6 4636 + signal-exit: 4.1.0 4637 + 4638 + sprintf-js@1.0.3: {} 3878 4639 3879 4640 stackback@0.0.2: {} 3880 4641 ··· 3911 4672 dependencies: 3912 4673 ansi-regex: 6.1.0 3913 4674 4675 + strip-bom@3.0.0: {} 4676 + 3914 4677 strip-literal@3.0.0: 3915 4678 dependencies: 3916 4679 js-tokens: 9.0.1 ··· 3924 4687 mz: 2.7.0 3925 4688 pirates: 4.0.7 3926 4689 ts-interface-checker: 0.1.13 4690 + 4691 + term-size@2.2.1: {} 3927 4692 3928 4693 thenify-all@1.6.0: 3929 4694 dependencies: ··· 3951 4716 tinyspy@4.0.3: {} 3952 4717 3953 4718 tlds@1.259.0: {} 4719 + 4720 + tmp@0.0.33: 4721 + dependencies: 4722 + os-tmpdir: 1.0.2 4723 + 4724 + to-regex-range@5.0.1: 4725 + dependencies: 4726 + is-number: 7.0.0 3954 4727 3955 4728 tr46@0.0.3: {} 3956 4729 ··· 4084 4857 unist-util-is: 6.0.0 4085 4858 unist-util-visit-parents: 6.0.1 4086 4859 4860 + universalify@0.1.2: {} 4861 + 4087 4862 unstorage@1.16.1: 4088 4863 dependencies: 4089 4864 anymatch: 3.1.3 ··· 4110 4885 '@types/unist': 3.0.3 4111 4886 vfile-message: 4.0.3 4112 4887 4113 - vite-node@3.2.4(@types/node@24.2.0): 4888 + vite-node@3.2.4(@types/node@24.2.1): 4114 4889 dependencies: 4115 4890 cac: 6.7.14 4116 4891 debug: 4.4.1 4117 4892 es-module-lexer: 1.7.0 4118 4893 pathe: 2.0.3 4119 - vite: 7.0.6(@types/node@24.2.0) 4894 + vite: 7.1.1(@types/node@24.2.1) 4120 4895 transitivePeerDependencies: 4121 4896 - '@types/node' 4122 4897 - jiti ··· 4131 4906 - tsx 4132 4907 - yaml 4133 4908 4134 - vite@6.3.5(@types/node@24.2.0): 4909 + vite@6.3.5(@types/node@24.2.1): 4135 4910 dependencies: 4136 4911 esbuild: 0.25.8 4137 4912 fdir: 6.4.6(picomatch@4.0.3) ··· 4140 4915 rollup: 4.46.2 4141 4916 tinyglobby: 0.2.14 4142 4917 optionalDependencies: 4143 - '@types/node': 24.2.0 4918 + '@types/node': 24.2.1 4144 4919 fsevents: 2.3.3 4145 4920 4146 - vite@7.0.6(@types/node@24.2.0): 4921 + vite@7.1.1(@types/node@24.2.1): 4147 4922 dependencies: 4148 4923 esbuild: 0.25.8 4149 4924 fdir: 6.4.6(picomatch@4.0.3) ··· 4152 4927 rollup: 4.46.2 4153 4928 tinyglobby: 0.2.14 4154 4929 optionalDependencies: 4155 - '@types/node': 24.2.0 4930 + '@types/node': 24.2.1 4156 4931 fsevents: 2.3.3 4157 4932 4158 - vitefu@1.1.1(vite@6.3.5(@types/node@24.2.0)): 4933 + vitefu@1.1.1(vite@6.3.5(@types/node@24.2.1)): 4159 4934 optionalDependencies: 4160 - vite: 6.3.5(@types/node@24.2.0) 4935 + vite: 6.3.5(@types/node@24.2.1) 4161 4936 4162 - vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.2.0): 4937 + vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.2.1): 4163 4938 dependencies: 4164 4939 '@types/chai': 5.2.2 4165 4940 '@vitest/expect': 3.2.4 4166 - '@vitest/mocker': 3.2.4(vite@7.0.6(@types/node@24.2.0)) 4941 + '@vitest/mocker': 3.2.4(vite@7.1.1(@types/node@24.2.1)) 4167 4942 '@vitest/pretty-format': 3.2.4 4168 4943 '@vitest/runner': 3.2.4 4169 4944 '@vitest/snapshot': 3.2.4 ··· 4181 4956 tinyglobby: 0.2.14 4182 4957 tinypool: 1.1.1 4183 4958 tinyrainbow: 2.0.0 4184 - vite: 7.0.6(@types/node@24.2.0) 4185 - vite-node: 3.2.4(@types/node@24.2.0) 4959 + vite: 7.1.1(@types/node@24.2.1) 4960 + vite-node: 3.2.4(@types/node@24.2.1) 4186 4961 why-is-node-running: 2.3.0 4187 4962 optionalDependencies: 4188 4963 '@types/debug': 4.1.12 4189 - '@types/node': 24.2.0 4964 + '@types/node': 24.2.1 4190 4965 transitivePeerDependencies: 4191 4966 - jiti 4192 4967 - less
-5
pnpm-workspace.yaml
··· 1 - ignoredBuiltDependencies: 2 - - sharp 3 - 4 - onlyBuiltDependencies: 5 - - esbuild
+189
tests/parse-blocks.test.ts
··· 1 + import { expect, test } from "vitest"; 2 + import { parseBlocks } from "../lib/utils"; 3 + 4 + test("should correctly parse an h1 block to an h2 tag", () => { 5 + const html = parseBlocks({ 6 + block: { 7 + $type: "pub.leaflet.pages.linearDocument#block", 8 + block: { 9 + $type: "pub.leaflet.blocks.header", 10 + level: 1, 11 + facets: [], 12 + plaintext: "heading 1", 13 + }, 14 + }, 15 + did: "did:plc:qttsv4e7pu2jl3ilanfgc3zn", 16 + }); 17 + 18 + expect(html).toMatchInlineSnapshot(`"<h2>heading 1</h2>"`); 19 + }); 20 + 21 + test("should correctly parse an h2 block to an h3 tag", () => { 22 + const html = parseBlocks({ 23 + block: { 24 + $type: "pub.leaflet.pages.linearDocument#block", 25 + block: { 26 + $type: "pub.leaflet.blocks.header", 27 + level: 2, 28 + facets: [], 29 + plaintext: "heading 2", 30 + }, 31 + }, 32 + did: "did:plc:qttsv4e7pu2jl3ilanfgc3zn", 33 + }); 34 + 35 + expect(html).toMatchInlineSnapshot(`"<h3>heading 2</h3>"`); 36 + }); 37 + 38 + test("should correctly parse an h3 block to an h4 tag", () => { 39 + const html = parseBlocks({ 40 + block: { 41 + $type: "pub.leaflet.pages.linearDocument#block", 42 + block: { 43 + $type: "pub.leaflet.blocks.header", 44 + level: 3, 45 + facets: [], 46 + plaintext: "heading 3", 47 + }, 48 + }, 49 + did: "did:plc:qttsv4e7pu2jl3ilanfgc3zn", 50 + }); 51 + 52 + expect(html).toMatchInlineSnapshot(`"<h4>heading 3</h4>"`); 53 + }); 54 + 55 + test("should correctly parse a block with no level to an h6 tag", () => { 56 + const html = parseBlocks({ 57 + block: { 58 + $type: "pub.leaflet.pages.linearDocument#block", 59 + block: { 60 + $type: "pub.leaflet.blocks.header", 61 + facets: [], 62 + plaintext: "heading 6", 63 + }, 64 + }, 65 + did: "did:plc:qttsv4e7pu2jl3ilanfgc3zn", 66 + }); 67 + 68 + expect(html).toMatchInlineSnapshot(`"<h6>heading 6</h6>"`); 69 + }); 70 + 71 + test("should correctly parse an unordered list block", () => { 72 + const html = parseBlocks({ 73 + block: { 74 + $type: "pub.leaflet.pages.linearDocument#block", 75 + block: { 76 + $type: "pub.leaflet.blocks.unorderedList", 77 + children: [ 78 + { 79 + $type: "pub.leaflet.blocks.unorderedList#listItem", 80 + content: { 81 + $type: "pub.leaflet.blocks.text", 82 + facets: [ 83 + { 84 + index: { 85 + byteEnd: 18, 86 + byteStart: 0, 87 + }, 88 + features: [ 89 + { 90 + uri: "https://pdsls.dev/", 91 + $type: "pub.leaflet.richtext.facet#link", 92 + }, 93 + ], 94 + }, 95 + { 96 + index: { 97 + byteEnd: 28, 98 + byteStart: 22, 99 + }, 100 + features: [ 101 + { 102 + uri: "https://bsky.app/profile/juli.ee", 103 + $type: "pub.leaflet.richtext.facet#link", 104 + }, 105 + ], 106 + }, 107 + ], 108 + plaintext: "https://pdsls.dev/ by Juliet", 109 + }, 110 + children: [], 111 + }, 112 + { 113 + $type: "pub.leaflet.blocks.unorderedList#listItem", 114 + content: { 115 + $type: "pub.leaflet.blocks.text", 116 + facets: [ 117 + { 118 + index: { 119 + byteEnd: 34, 120 + byteStart: 0, 121 + }, 122 + features: [ 123 + { 124 + uri: "https://github.com/mary-ext/atcute", 125 + $type: "pub.leaflet.richtext.facet#link", 126 + }, 127 + ], 128 + }, 129 + { 130 + index: { 131 + byteEnd: 42, 132 + byteStart: 38, 133 + }, 134 + features: [ 135 + { 136 + uri: "https://bsky.app/profile/mary.my.id", 137 + $type: "pub.leaflet.richtext.facet#link", 138 + }, 139 + ], 140 + }, 141 + ], 142 + plaintext: "https://github.com/mary-ext/atcute by mary", 143 + }, 144 + children: [], 145 + }, 146 + { 147 + $type: "pub.leaflet.blocks.unorderedList#listItem", 148 + content: { 149 + $type: "pub.leaflet.blocks.text", 150 + facets: [ 151 + { 152 + index: { 153 + byteEnd: 27, 154 + byteStart: 0, 155 + }, 156 + features: [ 157 + { 158 + uri: "https://www.microcosm.blue/", 159 + $type: "pub.leaflet.richtext.facet#link", 160 + }, 161 + ], 162 + }, 163 + { 164 + index: { 165 + byteEnd: 35, 166 + byteStart: 31, 167 + }, 168 + features: [ 169 + { 170 + uri: "https://bsky.app/profile/bad-example.com", 171 + $type: "pub.leaflet.richtext.facet#link", 172 + }, 173 + ], 174 + }, 175 + ], 176 + plaintext: "https://www.microcosm.blue/ by phil", 177 + }, 178 + children: [], 179 + }, 180 + ], 181 + }, 182 + }, 183 + did: "did:plc:qttsv4e7pu2jl3ilanfgc3zn", 184 + }); 185 + 186 + expect(html).toMatchInlineSnapshot( 187 + `"<ul><li><p><a href="https://pdsls.dev/" target="_blank" rel="noopener noreferrer">https://pdsls.dev/</a> by <a href="https://bsky.app/profile/juli.ee" target="_blank" rel="noopener noreferrer">Juliet</a></p></li><li><p><a href="https://github.com/mary-ext/atcute" target="_blank" rel="noopener noreferrer">https://github.com/mary-ext/atcute</a> by <a href="https://bsky.app/profile/mary.my.id" target="_blank" rel="noopener noreferrer">mary</a></p></li><li><p><a href="https://www.microcosm.blue/" target="_blank" rel="noopener noreferrer">https://www.microcosm.blue/</a> by <a href="https://bsky.app/profile/bad-example.com" target="_blank" rel="noopener noreferrer">phil</a></p></li></ul>"`, 188 + ); 189 + });
+133
tests/parse-text-blocks.test.ts
··· 1 + import { expect, test } from "vitest"; 2 + import { parseTextBlock } from "../lib/utils"; 3 + 4 + test("should correctly parse a text block without facets", () => { 5 + const html = parseTextBlock({ 6 + $type: "pub.leaflet.blocks.text", 7 + facets: [], 8 + plaintext: "just plaintext no facets", 9 + }); 10 + 11 + expect(html).toMatchInlineSnapshot(`"<p>just plaintext no facets</p>"`); 12 + }); 13 + 14 + test("should correctly parse a text block with bolded text", () => { 15 + const html = parseTextBlock({ 16 + $type: "pub.leaflet.blocks.text", 17 + facets: [ 18 + { 19 + index: { 20 + byteEnd: 11, 21 + byteStart: 0, 22 + }, 23 + features: [ 24 + { 25 + $type: "pub.leaflet.richtext.facet#bold", 26 + }, 27 + ], 28 + }, 29 + ], 30 + plaintext: "bolded text with some plaintext", 31 + }); 32 + 33 + expect(html).toMatchInlineSnapshot( 34 + `"<p><b>bolded text</b> with some plaintext</p>"`, 35 + ); 36 + }); 37 + 38 + test("should correctly parse a text block with an inline link", () => { 39 + const html = parseTextBlock({ 40 + $type: "pub.leaflet.blocks.text", 41 + facets: [ 42 + { 43 + index: { 44 + byteEnd: 27, 45 + byteStart: 0, 46 + }, 47 + features: [ 48 + { 49 + uri: "https://blacksky.community/", 50 + $type: "pub.leaflet.richtext.facet#link", 51 + }, 52 + ], 53 + }, 54 + ], 55 + plaintext: "https://blacksky.community/", 56 + }); 57 + 58 + expect(html).toMatchInlineSnapshot( 59 + `"<p><a href="https://blacksky.community/" target="_blank" rel="noopener noreferrer">https://blacksky.community/</a></p>"`, 60 + ); 61 + }); 62 + 63 + test("should correctly parse a text block with strikethrough text", () => { 64 + const html = parseTextBlock({ 65 + $type: "pub.leaflet.blocks.text", 66 + facets: [ 67 + { 68 + index: { 69 + byteEnd: 13, 70 + byteStart: 0, 71 + }, 72 + features: [ 73 + { 74 + $type: "pub.leaflet.richtext.facet#strikethrough", 75 + }, 76 + ], 77 + }, 78 + ], 79 + plaintext: "strikethrough text with some plaintext", 80 + }); 81 + 82 + expect(html).toMatchInlineSnapshot( 83 + `"<p><s>strikethrough</s> text with some plaintext</p>"`, 84 + ); 85 + }); 86 + 87 + test("should correctly parse a text block with underlined text", () => { 88 + const html = parseTextBlock({ 89 + $type: "pub.leaflet.blocks.text", 90 + facets: [ 91 + { 92 + index: { 93 + byteEnd: 10, 94 + byteStart: 0, 95 + }, 96 + features: [ 97 + { 98 + $type: "pub.leaflet.richtext.facet#underline", 99 + }, 100 + ], 101 + }, 102 + ], 103 + plaintext: "underlined text with some plaintext", 104 + }); 105 + 106 + expect(html).toMatchInlineSnapshot( 107 + `"<p><span style="text-decoration:underline;">underlined</span> text with some plaintext</p>"`, 108 + ); 109 + }); 110 + 111 + test("should correctly parse a text block with italicized text", () => { 112 + const html = parseTextBlock({ 113 + $type: "pub.leaflet.blocks.text", 114 + facets: [ 115 + { 116 + index: { 117 + byteEnd: 10, 118 + byteStart: 0, 119 + }, 120 + features: [ 121 + { 122 + $type: "pub.leaflet.richtext.facet#italic", 123 + }, 124 + ], 125 + }, 126 + ], 127 + plaintext: "italicized text with some plaintext", 128 + }); 129 + 130 + expect(html).toMatchInlineSnapshot( 131 + `"<p><i>italicized</i> text with some plaintext</p>"`, 132 + ); 133 + });
+4
tests/uri-to-rkey.test.ts
··· 12 12 ), 13 13 ).toBe("3lvl7m6jd4s2e"); 14 14 }); 15 + 16 + test("should not pass if invalid uri is passed in", () => { 17 + expect(() => uriToRkey("invalid")).toThrowError(/failed to get rkey/i); 18 + });