diff --git a/.changeset/config.json b/.changeset/config.json index 1013eb6d..db35bc78 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -7,5 +7,5 @@ "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", - "ignore": ["playground"] + "ignore": ["playground","starlight-playground"] } diff --git a/.changeset/six-mice-build.md b/.changeset/six-mice-build.md new file mode 100644 index 00000000..a3f3813d --- /dev/null +++ b/.changeset/six-mice-build.md @@ -0,0 +1,5 @@ +--- +"@matthiesenxyz/starlight-ghostcms": patch +--- + +Initial Public Release, Added Readme, Basics Working, Ready Set GO! diff --git a/package.json b/package.json index 5615cae1..ad52c7b5 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ }, "scripts": { "dev": "pnpm --filter playground dev", + "starlight:dev": "pnpm --filter starlight-playground dev", "lint": "biome check .", "lint:fix": "biome check --apply .", "ci:version": "pnpm changeset version", @@ -15,7 +16,10 @@ "test:api": "pnpm --filter astro-ghostcms test", "test:api:watch": "pnpm --filter astro-ghostcms test:watch", "test:api:coverage": "pnpm --filter astro-ghostcms test:coverage", - "test:create": "pnpm --filter create-astro-ghostcms test" + "test:create": "pnpm --filter create-astro-ghostcms test", + "test:slg": "pnpm --filter starlight-ghostcms test", + "test:slg:watch": "pnpm --filter starlight-ghostcms test:watch", + "test:slg:coverage": "pnpm --filter starlight-ghostcms test:coverage" }, "devDependencies": { "@biomejs/biome": "1.5.3", diff --git a/packages/starlight-ghostcms/README.md b/packages/starlight-ghostcms/README.md new file mode 100644 index 00000000..7f2fa88a --- /dev/null +++ b/packages/starlight-ghostcms/README.md @@ -0,0 +1,75 @@ + + +# Welcome to Starlight-GhostCMS by [Astro-GhostCMS](https://astro-ghostcms.xyz) + +Starlight-GhostCMS is a [Starlight](https://starlight.astro.build/) plugin to add a blog to your documentation site. + +- Customizable Header link *(Defaults to "Blog")* +- Pulls all the Posts from your GhostCMS install +- Pulls all Authors & Featured Images and adds then to your Posts +- Creates a custom section on your website linkable from the Header + +For a full always up to date documentation please checkout [Our Website](https://astro-ghostcms.xyz) + +- [Starlight Demo **COMING SOON**](#) +- [Astro-GhostCMS Website](https://astro-ghostcms.xyz) Check the website for the most up-to-date Documentation! +- [Ghost.org](https://ghost.org) Get your own Ghost[^1] Install + +*Need help but don't have Github? Email us at [issues@astro-ghostcms.xyz](mailto:issues@astroghostcms.xyz) to create an issue here on github! Or join our [Discord](https://discord.gg/u7NZqUyeAR)* + +Astro minimum Version: **Starlight v0.19 & Astro v4** + +## Installation + +### Prerequisites: + +1. You will need to have a Starlight Website Setup. If you dont have one yet, you can follow the ["Getting Started"](https://starlight.astro.build/getting-started) guide in the Starlight docs to create one. +2. You will need a GhostCMS server, and your `CONTENT_API_KEY` & `CONTENT_API_URL`. Your GhostCMS server must also support the `v5` Version of the GhostAPI. If you dont already have your Key and Url, you can find out how to get those on the Ghost docs [HERE](https://ghost.org/docs/content-api/) + +### Install the plugin + +Starlight GhostCMS is a Starlight [plugin](https://starlight.astro.build/reference/plugins/). Install it using your favorite package manager. Below is 3 examples of what to run. **CHOOSE ONE**. + +``` +npm install @matthiesenxyz/starlight-ghostcms +pnpm add @matthiesenxyz/starlight-ghostcms +yarn add @matthiesenxyz/starlight-ghostcms +``` + +### Configure the pluign + +The Starlight GhostCMS plugin can be configured in your Starlight [configuration](https://starlight.astro.build/reference/configuration/#plugins) in the `astro.config.mjs` file. + +```ts +import starlight from '@astrojs/starlight' +import { defineConfig } from 'astro/config' +import starlightGhostCMS from '@matthiesenxyz/starlight-ghostcms'; + +export default defineConfig({ + integrations: [ + starlight({ + plugins: [starlightGhostCMS()], + title: 'My Docs', + }), + ], +}) +``` + +### Set your GhostCMS ENV Variables + +You must also create 2 environment variables in a `.env` file with the following: + +```env +CONTENT_API_KEY=a33da3965a3a9fb2c6b3f63b48 +CONTENT_API_URL=https://ghostdemo.matthiesen.xyz +``` + +**When you deploy your install dont forget to set the above ENVIRONMENT VARIABLES on your provider!** + + +For more information and to see the docs please check our website: [Astro-GhostCMS.xyz](https://astro-ghostcms.xyz) + +# Foot Notes & Credits + +[^1]: Ghost.org, Ghost.io, Ghost are all trademarks of [The Ghost Foundation](https://ghost.org/). This project is Open Source and not directly related to or provided by The Ghost Foundation and is intended to help create a easier method to utilize their provided JavaScript tools to link a Headless GhostCMS install in to your Astro project. + diff --git a/packages/starlight-ghostcms/index.ts b/packages/starlight-ghostcms/index.ts new file mode 100644 index 00000000..10d7d42a --- /dev/null +++ b/packages/starlight-ghostcms/index.ts @@ -0,0 +1,66 @@ +import type { StarlightPlugin, StarlightUserConfig } from '@astrojs/starlight/types' +import type { AstroIntegrationLogger } from 'astro' +import { type StarlightGhostConfig, validateConfig } from './src/schemas/config' +import { vitePluginStarlightGhostConfig } from './src/integrations/vite' + +export type { StarlightGhostConfig } + +export default function starlightGhostCMS(userConfig?: StarlightGhostConfig): StarlightPlugin { + const config: StarlightGhostConfig = validateConfig(userConfig) + + return { + name: '@matthiesenxyz/starlight-ghostcms-plugin', + hooks: { + setup({ addIntegration, config: starlightConfig, logger, updateConfig: updateStarlightConfig }) { + updateStarlightConfig({ + components: { + ...starlightConfig.components, + ...overrideStarlightComponent(starlightConfig.components, logger, 'MarkdownContent'), + ...overrideStarlightComponent(starlightConfig.components, logger, 'Sidebar'), + ...overrideStarlightComponent(starlightConfig.components, logger, "SiteTitle"), + } + }) + + addIntegration({ + name: '@matthiesenxyz/starlight-ghostcms', + hooks: { + 'astro:config:setup': ({ injectRoute, updateConfig }) => { + injectRoute({ + pattern: '/blog', + entrypoint: '@matthiesenxyz/starlight-ghostcms/routes/index.astro' + }) + injectRoute({ + pattern: '/blog/[slug]', + entrypoint: '@matthiesenxyz/starlight-ghostcms/routes/[slug].astro' + }) + + updateConfig({ + vite: { + plugins: [vitePluginStarlightGhostConfig(config)], + }, + }) + } + } + }) + } + }, + } +} + +function overrideStarlightComponent( + components: StarlightUserConfig['components'], + logger: AstroIntegrationLogger, + component: keyof NonNullable, + ) { + if (components?.[component]) { + logger.warn(`It looks like you already have a \`${component}\` component override in your Starlight configuration.`) + logger.warn(`To use \`starlight-ghostcms\`, remove the override for the \`${component}\` component.\n`) + logger.warn("This Warning can be ignored if you know what your doing ;)") + + return {} + } + + return { + [component]: `@matthiesenxyz/starlight-ghostcms/overrides/${component}.astro`, + } + } \ No newline at end of file diff --git a/packages/starlight-ghostcms/package.json b/packages/starlight-ghostcms/package.json new file mode 100644 index 00000000..433e32c2 --- /dev/null +++ b/packages/starlight-ghostcms/package.json @@ -0,0 +1,72 @@ +{ + "name": "@matthiesenxyz/starlight-ghostcms", + "description": "Starlight GhostCMS plugin to allow easier importing of GhostCMS Content into your starlight website", + "version": "0.0.1", + "homepage": "https://astro-ghostcms.xyz/", + "type": "module", + "license": "MIT", + "publishConfig": { + "access": "public" + }, + "sideEffects": false, + "author": { + "email": "adam@matthiesen.xyz", + "name": "Adam Matthiesen - MatthiesenXYZ", + "url": "https://matthiesen.xyz" + }, + "keywords": [ + "starlight", + "starlight-plugin", + "astro", + "plugin", + "blog", + "content", + "ghost", + "ghostcms" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/MatthiesenXYZ/astro-ghostcms.git" + }, + "bugs": { + "url": "https://github.com/MatthiesenXYZ/astro-ghostcms/issues", + "email": "issues@astro-ghostcms.xyz" + }, + "main": "index.ts", + "types": "index.ts", + "files": [ + "src", + "index.ts", + "tsconfig.json", + "types.d.ts" + ], + "exports": { + ".": "./index.ts", + "./overrides/MarkdownContent.astro": "./src/overrides/MarkdownContent.astro", + "./overrides/Sidebar.astro": "./src/overrides/Sidebar.astro", + "./overrides/SiteTitle.astro": "./src/overrides/SiteTitle.astro", + "./routes/index.astro": "./src/routes/index.astro", + "./routes/[slug].astro": "./src/routes/[slug].astro", + "./schema": "./src/schemas/config.ts" + }, + "scripts": { + "test": "vitest run", + "test:watch": "vitest", + "test:coverage": "vitest run --coverage", + "test:ci": "vitest run --coverage.enabled --coverage.reporter='text-summary'" + }, + "devDependencies": { + "@astrojs/starlight": "0.19.0", + "@ts-ghost/core-api": "5.1.2", + "@ts-ghost/tsconfig": "workspace:*", + "astro": "4.4.0", + "vite": "^5.1.2", + "vite-tsconfig-paths": "^4.2.2", + "vitest": "^1.2.2", + "vitest-fetch-mock": "^0.2.2" + }, + "peerdependencies": { + "@astrojs/starlight": ">=0.19.0", + "astro": ">=4.3.7" + } +} diff --git a/packages/starlight-ghostcms/src/components/Author.astro b/packages/starlight-ghostcms/src/components/Author.astro new file mode 100644 index 00000000..bbf982a7 --- /dev/null +++ b/packages/starlight-ghostcms/src/components/Author.astro @@ -0,0 +1,60 @@ +--- +import type { Author } from '../schemas/authors' + +interface Props { + author: Author +} + +const { author } = Astro.props + +const isLink = author.website !== undefined +const Element = isLink ? 'a' : 'div' +--- + + + {author.profile_image && {author.name}} +
+
{author.name}
+ {author.bio &&
{author.bio}
} +
+
+ + diff --git a/packages/starlight-ghostcms/src/components/Metadata.astro b/packages/starlight-ghostcms/src/components/Metadata.astro new file mode 100644 index 00000000..f3de8cba --- /dev/null +++ b/packages/starlight-ghostcms/src/components/Metadata.astro @@ -0,0 +1,59 @@ +--- +import type { Post } from '../schemas/posts' +import Author from './Author.astro' + +interface Props { + entry: Post +} + +const { entry } = Astro.props +const { authors, published_at, created_at } = entry + +const dateC = new Date(published_at?published_at:created_at) +const dateISO = dateC.toISOString() +const dateLocal = dateC + .toLocaleDateString( + "en-US", { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: '2-digit', + minute: '2-digit' + } + ) + +const hasAuthors = authors !== undefined +--- + +
+ + { + hasAuthors ? ( +
+ {authors.map((author: any) => ( + + ))} +
+ ) : null + } +
+ + diff --git a/packages/starlight-ghostcms/src/components/Page.astro b/packages/starlight-ghostcms/src/components/Page.astro new file mode 100644 index 00000000..da654d56 --- /dev/null +++ b/packages/starlight-ghostcms/src/components/Page.astro @@ -0,0 +1,17 @@ +--- +import StarlightPage, { type StarlightPageProps as Props } from '@astrojs/starlight/components/StarlightPage.astro' +--- + + + + + + diff --git a/packages/starlight-ghostcms/src/components/Posts.astro b/packages/starlight-ghostcms/src/components/Posts.astro new file mode 100644 index 00000000..8e15c1c5 --- /dev/null +++ b/packages/starlight-ghostcms/src/components/Posts.astro @@ -0,0 +1,22 @@ +--- +import Preview from './Preview.astro' +import type { Post } from '../schemas/posts' + +interface Props { + entries: Post[] +} + +const { entries } = Astro.props +--- + +
+ {entries.map((entry) => )} +
+ + diff --git a/packages/starlight-ghostcms/src/components/Preview.astro b/packages/starlight-ghostcms/src/components/Preview.astro new file mode 100644 index 00000000..dcd5be13 --- /dev/null +++ b/packages/starlight-ghostcms/src/components/Preview.astro @@ -0,0 +1,40 @@ +--- +import type { Post } from '../schemas/posts' +import Metadata from './Metadata.astro' + +interface Props { + entry: Post +} + +const { entry } = Astro.props + +const Excerpt = entry.excerpt +--- + +
+
+

+ {entry.title} +

+ +
+
+ {typeof Excerpt === 'string' ? Excerpt : entry.excerpt} +
+
+ + diff --git a/packages/starlight-ghostcms/src/integrations/vite.ts b/packages/starlight-ghostcms/src/integrations/vite.ts new file mode 100644 index 00000000..7ccb3d43 --- /dev/null +++ b/packages/starlight-ghostcms/src/integrations/vite.ts @@ -0,0 +1,22 @@ +import type { ViteUserConfig } from 'astro' + +import type { StarlightGhostConfig } from '../schemas/config.ts' + +// Expose the starlight-blog plugin configuration. +export function vitePluginStarlightGhostConfig(config: StarlightGhostConfig): VitePlugin { + const moduleId = 'virtual:starlight-ghost-config' + const resolvedModuleId = `\0${moduleId}` + const moduleContent = `export default ${JSON.stringify(config)}` + + return { + name: 'vite-plugin-starlight-ghost-config', + load(id) { + return id === resolvedModuleId ? moduleContent : undefined + }, + resolveId(id) { + return id === moduleId ? resolvedModuleId : undefined + }, + } +} + +type VitePlugin = NonNullable[number] diff --git a/packages/starlight-ghostcms/src/overrides/MarkdownContent.astro b/packages/starlight-ghostcms/src/overrides/MarkdownContent.astro new file mode 100644 index 00000000..80c0151b --- /dev/null +++ b/packages/starlight-ghostcms/src/overrides/MarkdownContent.astro @@ -0,0 +1,33 @@ +--- +import StarlightMarkdownContent from '@astrojs/starlight/components/MarkdownContent.astro' +import type { Props } from '@astrojs/starlight/props' + +import { isAnyBlogPostPage } from '../utils/page' +import Metadata from '../components/Metadata.astro' +import type { Post } from '../schemas/posts' + +const isBlogPost = isAnyBlogPostPage(Astro.props.slug) +let blogEntry: Post | undefined = undefined + +--- + + + {isBlogPost && blogEntry ? : null} + + + { + isBlogPost && blogEntry ? ( + + ) : null + } + + + diff --git a/packages/starlight-ghostcms/src/overrides/Sidebar.astro b/packages/starlight-ghostcms/src/overrides/Sidebar.astro new file mode 100644 index 00000000..9e091e04 --- /dev/null +++ b/packages/starlight-ghostcms/src/overrides/Sidebar.astro @@ -0,0 +1,71 @@ +--- +import StarlightSidebar from '@astrojs/starlight/components/Sidebar.astro' +import type { Props } from '@astrojs/starlight/props' +import config from 'virtual:starlight-ghost-config' +import { isBlogPostPage, isBlogRoot } from '../utils/page' +import { getAllPosts } from '../utils/api' + +export async function getRecentBlogEntries(){ + const entries = await getAllPosts() + return entries.slice(0, config.recentPostCount) +} + +export function checkpath(path: string){ + if ( path.slice(0, 5) === "/blog" ){ + return true + } else { return false } +} +const isBlog = checkpath(Astro.url.pathname) +const recentEntries = isBlog ? await getRecentBlogEntries() : [] + +const blogSidebar: Props['sidebar'] = isBlog + ? [ + { + attrs: {}, + badge: undefined, + href: '/blog', + isCurrent: isBlogRoot(Astro.props.slug), + label: 'All posts', + type: 'link', + }, + { + badge: undefined, + collapsed: false, + entries: recentEntries.map((blogEntry) => ({ + attrs: {}, + badge: undefined, + href: `/blog/${blogEntry.slug}`, + isCurrent: isBlogPostPage(Astro.props.slug, `blog/${blogEntry.slug}`), + label: blogEntry.title, + type: 'link', + })), + label: 'Recent posts', + type: 'group', + }, + ] + : [] +--- + +{ + !isBlog && ( +
+ Blog +
+ ) +} + + + diff --git a/packages/starlight-ghostcms/src/overrides/SiteTitle.astro b/packages/starlight-ghostcms/src/overrides/SiteTitle.astro new file mode 100644 index 00000000..3f5dd01a --- /dev/null +++ b/packages/starlight-ghostcms/src/overrides/SiteTitle.astro @@ -0,0 +1,32 @@ +--- +import type { Props } from "@astrojs/starlight/props"; +import AstrolightSiteTitle from "@astrojs/starlight/components/SiteTitle.astro"; +import config from 'virtual:starlight-ghost-config' +--- + + +
+ {config.title} +
+ + \ No newline at end of file diff --git a/packages/starlight-ghostcms/src/routes/[slug].astro b/packages/starlight-ghostcms/src/routes/[slug].astro new file mode 100644 index 00000000..6ae03dd2 --- /dev/null +++ b/packages/starlight-ghostcms/src/routes/[slug].astro @@ -0,0 +1,60 @@ +--- +import config from 'virtual:starlight-ghost-config' +import { Image } from "astro:assets"; +import Page from '../components/Page.astro' +import { getPageProps } from '../utils/page' +import { getAllPosts } from '../utils/api' +import Metadata from '../components/Metadata.astro' + + +export async function getStaticPaths() { + const entries = await getAllPosts(); + return entries.map((post) => ({ + params: { slug: post.slug }, + props: { post, slug:post.slug }, + })); +} + +const { post } = Astro.props +const pageProps = getPageProps(post.title) +--- + + + {config.supportGhost && ( +
Powered by Ghost
+ )} + +
+ + {post.feature_image && ( +
+ {post.feature_image_alt?post.feature_image_alt:""} +
+ +
+
+ )} +
+
+ + +
+
+
+ + \ No newline at end of file diff --git a/packages/starlight-ghostcms/src/routes/index.astro b/packages/starlight-ghostcms/src/routes/index.astro new file mode 100644 index 00000000..dea5b647 --- /dev/null +++ b/packages/starlight-ghostcms/src/routes/index.astro @@ -0,0 +1,37 @@ +--- +//import type { InferGetStaticPropsType } from 'astro' +import config from 'virtual:starlight-ghost-config' + +import Page from '../components/Page.astro' +import Posts from '../components/Posts.astro' +//import PrevNextLinks from '../components/PrevNextLinks.astro' +import { getPageProps } from '../utils/page' +import { getAllPosts } from '../utils/api' + +const entries = await getAllPosts(); + +//const { entries, nextLink, prevLink } = Astro.props + +const pageProps = getPageProps(config.title) +--- + + + {config.supportGhost && ( +
Powered by Ghost
+ )} + +
+ +
+
+ + \ No newline at end of file diff --git a/packages/starlight-ghostcms/src/schemas/authors.ts b/packages/starlight-ghostcms/src/schemas/authors.ts new file mode 100644 index 00000000..c5df9eba --- /dev/null +++ b/packages/starlight-ghostcms/src/schemas/authors.ts @@ -0,0 +1,37 @@ +import { + ghostIdentitySchema, + ghostMetaSchema, + ghostMetadataSchema, +} from "@ts-ghost/core-api"; +import { z } from "astro/zod"; + +export const authorsSchema = z.object({ + ...ghostIdentitySchema.shape, + ...ghostMetadataSchema.shape, + name: z.string(), + profile_image: z.string().nullable(), + cover_image: z.string().nullable(), + bio: z.string().nullable(), + website: z.string().nullable(), + location: z.string().nullable(), + facebook: z.string().nullable(), + twitter: z.string().nullable(), + count: z + .object({ + posts: z.number(), + }) + .optional(), + url: z.string(), +}); + +export type Author = z.infer; + +export const ghostFetchAuthorsSchema = z.object({ + meta: ghostMetaSchema, + authors: z.array(authorsSchema), +}); + +export const authorsIncludeSchema = z.object({ + "count.posts": z.literal(true).optional(), +}); +export type AuthorsIncludeSchema = z.infer; diff --git a/packages/starlight-ghostcms/src/schemas/config.ts b/packages/starlight-ghostcms/src/schemas/config.ts new file mode 100644 index 00000000..0421a092 --- /dev/null +++ b/packages/starlight-ghostcms/src/schemas/config.ts @@ -0,0 +1,46 @@ +import { AstroError } from 'astro/errors' +import { z } from 'astro/zod' + +const configSchema = z + .object({ + /** + * The number of blog posts to display per page in the blog post list. + */ + postCount: z.number().min(1).default(5), + /** + * The number of recent blog posts to display in the sidebar. + */ + recentPostCount: z.number().min(1).default(10), + /** + * The title of the blog. + */ + title: z.string().default('Blog'), + /** + * Turn on and off "Powered by Ghost" + */ + supportGhost: z.boolean().default(true), + }) + .default({}) + +export function validateConfig(userConfig: unknown): StarlightGhostConfig { + const config = configSchema.safeParse(userConfig) + + if (!config.success) { + const errors = config.error.flatten() + + throw new AstroError( + `Invalid starlight-GhostCMS configuration: + +${errors.formErrors.map((formError) => ` - ${formError}`).join('\n')} +${Object.entries(errors.fieldErrors) + .map(([fieldName, fieldErrors]) => ` - ${fieldName}: ${fieldErrors.join(' - ')}`) + .join('\n')} + `, + "See the error report above for more informations.\n\nIf you believe this is a bug, please file an issue at https://github.com/matthiesenxyz/astro-ghostcms/issues/new/choose", + ) + } + + return config.data +} + +export type StarlightGhostConfig = z.infer diff --git a/packages/starlight-ghostcms/src/schemas/posts.ts b/packages/starlight-ghostcms/src/schemas/posts.ts new file mode 100644 index 00000000..cb514ed8 --- /dev/null +++ b/packages/starlight-ghostcms/src/schemas/posts.ts @@ -0,0 +1,54 @@ +import { + ghostCodeInjectionSchema, + ghostIdentitySchema, + ghostMetadataSchema, + ghostSocialMediaSchema, + ghostVisibilitySchema, +} from "@ts-ghost/core-api"; +import { z } from "astro/zod"; + +import { authorsSchema } from "./authors"; +import { tagsSchema } from "./tags"; + +const postsAuthorSchema = authorsSchema.extend({ + url: z.string().nullish(), +}); +export const postsSchema = z.object({ + ...ghostIdentitySchema.shape, + ...ghostMetadataSchema.shape, + title: z.string(), + html: z.string().catch(""), + plaintext: z.string().nullish(), + comment_id: z.string().nullable(), + feature_image: z.string().nullable(), + feature_image_alt: z.string().nullable(), + feature_image_caption: z.string().nullable(), + featured: z.boolean(), + custom_excerpt: z.string().nullable(), + ...ghostCodeInjectionSchema.shape, + ...ghostSocialMediaSchema.shape, + visibility: ghostVisibilitySchema, + custom_template: z.string().nullable(), + canonical_url: z.string().nullable(), + authors: z.array(postsAuthorSchema).optional(), + tags: z.array(tagsSchema).optional(), + primary_author: postsAuthorSchema.nullish(), + primary_tag: tagsSchema.nullish(), + url: z.string(), + excerpt: z.string().catch(""), + reading_time: z.number().optional().default(0), + created_at: z.string(), + updated_at: z.string().nullish(), + published_at: z.string().nullish(), + access: z.boolean(), + comments: z.boolean(), + email_subject: z.string().nullish(), +}); + +export type Post = z.infer; + +export const postsIncludeSchema = z.object({ + authors: z.literal(true).optional(), + tags: z.literal(true).optional(), +}); +export type PostsIncludeSchema = z.infer; diff --git a/packages/starlight-ghostcms/src/schemas/tags.ts b/packages/starlight-ghostcms/src/schemas/tags.ts new file mode 100644 index 00000000..9344112d --- /dev/null +++ b/packages/starlight-ghostcms/src/schemas/tags.ts @@ -0,0 +1,34 @@ +import { + ghostCodeInjectionSchema, + ghostIdentitySchema, + ghostMetadataSchema, + ghostSocialMediaSchema, + ghostVisibilitySchema, +} from "@ts-ghost/core-api"; +import { z } from "astro/zod"; + +export const tagsSchema = z.object({ + ...ghostIdentitySchema.shape, + ...ghostMetadataSchema.shape, + ...ghostCodeInjectionSchema.shape, + ...ghostSocialMediaSchema.shape, + name: z.string(), + description: z.string().nullable(), + feature_image: z.string().nullable(), + visibility: ghostVisibilitySchema, + canonical_url: z.string().nullable(), + accent_color: z.string().nullable(), + url: z.string(), + count: z + .object({ + posts: z.number(), + }) + .optional(), +}); + +export type Tag = z.infer; + +export const tagsIncludeSchema = z.object({ + "count.posts": z.literal(true).optional(), +}); +export type TagsIncludeSchema = z.infer; diff --git a/packages/starlight-ghostcms/src/utils/api/api-functions.ts b/packages/starlight-ghostcms/src/utils/api/api-functions.ts new file mode 100644 index 00000000..57fa7b7f --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/api-functions.ts @@ -0,0 +1,146 @@ +import { TS_API } from "./content-api"; +import type { Page, Post } from "./content-api/schemas"; +import type { ContentAPICredentials } from './content-api/content-api' +// LOAD ENVIRONMENT VARIABLES +import { loadEnv } from "vite"; +import { invariant } from "./invariant.js"; + +const { CONTENT_API_KEY, CONTENT_API_URL } = loadEnv( + "all", + process.cwd(), + "CONTENT_", +); + +invariant( + CONTENT_API_KEY, + "CONTENT_API_KEY Missing from .env" + ) +invariant( + CONTENT_API_URL, + "CONTENT_API_URL Missing from .env" + ) + +const key:ContentAPICredentials["key"] = CONTENT_API_KEY; +const url:ContentAPICredentials["url"] = CONTENT_API_URL; +const version = "v5.0"; +const api = new TS_API(url, key, version); + +export const getAllAuthors = async () => { + const results = await api.authors + .browse() + .include({ "count.posts": true }) + .fetch(); + if (!results.success) { + throw new Error(results.errors.map((e) => e.message).join(", ")); + } + return { + authors: results.data, + meta: results.meta, + }; +}; + +export const getPosts = async () => { + const results = await api.posts + .browse() + .include({ + authors: true, + tags: true, + }) + .fetch(); + if (!results.success) { + throw new Error(results.errors.map((e) => e.message).join(", ")); + } + return { + posts: results.data, + meta: results.meta, + }; +}; + +export const getAllPosts = async () => { + const posts: Post[] = []; + let cursor = await api.posts + .browse() + .include({ + authors: true, + tags: true, + }) + .paginate(); + if (cursor.current.success) posts.push(...cursor.current.data); + while (cursor.next) { + cursor = await cursor.next.paginate(); + if (cursor.current.success) posts.push(...cursor.current.data); + } + return posts; +}; + +export const getSluggedPost = async (slug:string) => { + const results = await api.posts + .read({slug: slug}) + .include({ + authors: true, + tags: true, + }).fetch() + + if (!results.success) { + throw new Error(results.errors.map((e) => e.message).join(", ")); + } + return { + post: results.data, + }; +}; + +export const getAllPages = async () => { + const pages: Page[] = []; + let cursor = await api.pages + .browse() + .include({ + authors: true, + tags: true, + }) + .paginate(); + if (cursor.current.success) pages.push(...cursor.current.data); + while (cursor.next) { + cursor = await cursor.next.paginate(); + if (cursor.current.success) pages.push(...cursor.current.data); + } + return pages; +}; + +export const getSettings = async () => { + const res = await api.settings.fetch(); + if (res.success) { + return res.data; + } + return null; +}; + +export const getAllTags = async () => { + const results = await api.tags + .browse() + .include({ "count.posts": true }) + .fetch(); + if (!results.success) { + throw new Error(results.errors.map((e) => e.message).join(", ")); + } + return { + tags: results.data, + meta: results.meta, + }; +}; + +export const getFeaturedPosts = async () => { + const results = await api.posts + .browse({ filter: "featured:true" }) + .include({ + authors: true, + tags: true, + }) + .fetch(); + if (!results.success) { + throw new Error(results.errors.map((e) => e.message).join(", ")); + } + return { + posts: results.data, + meta: results.meta, + }; +}; diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/content-api.test.ts b/packages/starlight-ghostcms/src/utils/api/content-api/content-api.test.ts new file mode 100644 index 00000000..e47ec835 --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/content-api.test.ts @@ -0,0 +1,84 @@ +import { assert, beforeEach, describe, expect, test } from "vitest"; + +import TS_API from "./content-api"; + +describe("content-api", () => { + let api: TS_API; + beforeEach(() => { + api = new TS_API("https://ghost.org", "59d4bf56c73c04a18c867dc3ba", "v5.0"); + }); + + test("content-api", () => { + expect(api).toBeDefined(); + }); + + test("content-api shouldn't instantiate with an incorrect url", () => { + assert.throws(() => { + const api = new TS_API("ghost.org", "59d4bf56c73c04a18c867dc3ba", "v5.0"); + api.settings; + }); + }); + + test("content-api shouldn't instantiate with an incorrect key", () => { + assert.throws(() => { + const api = new TS_API("https://ghost.org", "a", "v5.0"); + api.settings; + }); + }); + + test("content-api shouldn't instantiate with an incorrect version", () => { + assert.throws(() => { + const api = new TS_API( + "https://ghost.org", + "1efedd9db174adee2d23d982:4b74dca0219bad629852191af326a45037346c2231240e0f7aec1f9371cc14e8", + // @ts-expect-error + "v4.0", + ); + api.settings; + }); + }); + + test("content-api.posts", () => { + expect(api.posts).toBeDefined(); + expect(api.posts.browse).toBeDefined(); + expect(api.posts.read).toBeDefined(); + }); + + test("content-api.pages", () => { + expect(api.pages).toBeDefined(); + expect(api.pages.browse).toBeDefined(); + expect(api.pages.read).toBeDefined(); + }); + + test("content-api.tags", () => { + expect(api.tags).toBeDefined(); + expect(api.tags.browse).toBeDefined(); + expect(api.tags.read).toBeDefined(); + }); + + test("content-api.tiers", () => { + expect(api.tiers).toBeDefined(); + expect(api.tiers.browse).toBeDefined(); + expect(api.tiers.read).toBeDefined(); + }); + + test("content-api.authors", () => { + expect(api.authors).toBeDefined(); + expect(api.authors.browse).toBeDefined(); + expect(api.authors.read).toBeDefined(); + // @ts-expect-error + expect(api.authors.add).toBeUndefined(); + // @ts-expect-error + expect(api.authors.edit).toBeUndefined(); + expect(api.authors).toBeDefined(); + }); + + test("content-api.settings", () => { + expect(api.settings).toBeDefined(); + expect(api.settings.fetch).toBeDefined(); + // @ts-expect-error + expect(api.settings.read).toBeUndefined(); + // @ts-expect-error + expect(api.settings.browse).toBeUndefined(); + }); +}); diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/content-api.ts b/packages/starlight-ghostcms/src/utils/api/content-api/content-api.ts new file mode 100644 index 00000000..6035e96a --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/content-api.ts @@ -0,0 +1,116 @@ +import { + APIComposer, + BasicFetcher, + HTTPClient, + contentAPICredentialsSchema, + slugOrIdSchema, +} from "@ts-ghost/core-api"; + +import { + authorsIncludeSchema, + authorsSchema, + pagesIncludeSchema, + pagesSchema, + postsIncludeSchema, + postsSchema, + settingsSchema, + tagsIncludeSchema, + tagsSchema, + tiersIncludeSchema, + tiersSchema, +} from "./schemas"; + +export type { ContentAPICredentials, APIVersions } from "@ts-ghost/core-api"; + +export enum BrowseEndpointType { + authors = "authors", + tiers = "tiers", + posts = "posts", + pages = "pages", + tags = "tags", + settings = "settings", +} + +export default class TS_API { + private httpClient: HTTPClient; + + constructor( + protected readonly url: string, + protected readonly key: string, + protected readonly version: Version, + ) { + const apiCredentials = contentAPICredentialsSchema.parse({ + key, + version, + url, + }); + this.httpClient = new HTTPClient({ + ...apiCredentials, + endpoint: "content", + }); + } + + get authors() { + return new APIComposer( + "authors", + { + schema: authorsSchema, + identitySchema: slugOrIdSchema, + include: authorsIncludeSchema, + }, + this.httpClient, + ).access(["read", "browse"]); + } + get tiers() { + return new APIComposer( + "tiers", + { + schema: tiersSchema, + identitySchema: slugOrIdSchema, + include: tiersIncludeSchema, + }, + this.httpClient, + ).access(["browse", "read"]); + } + get posts() { + return new APIComposer( + "posts", + { + schema: postsSchema, + identitySchema: slugOrIdSchema, + include: postsIncludeSchema, + }, + this.httpClient, + ).access(["browse", "read"]); + } + get pages() { + return new APIComposer( + "pages", + { + schema: pagesSchema, + identitySchema: slugOrIdSchema, + include: pagesIncludeSchema, + }, + this.httpClient, + ).access(["browse", "read"]); + } + get tags() { + return new APIComposer( + "tags", + { + schema: tagsSchema, + identitySchema: slugOrIdSchema, + include: tagsIncludeSchema, + }, + this.httpClient, + ).access(["browse", "read"]); + } + + get settings() { + return new BasicFetcher( + "settings", + { output: settingsSchema }, + this.httpClient, + ); + } +} diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/index.ts b/packages/starlight-ghostcms/src/utils/api/content-api/index.ts new file mode 100644 index 00000000..fb09f087 --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/index.ts @@ -0,0 +1,8 @@ +export { default as TS_API } from "./content-api"; +export * from "./schemas"; + +export type { + InferFetcherDataShape, + InferResponseDataShape, + BrowseParams, +} from "@ts-ghost/core-api"; diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/schemas/authors/authors.test.ts b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/authors/authors.test.ts new file mode 100644 index 00000000..1d24851f --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/authors/authors.test.ts @@ -0,0 +1,164 @@ +import { afterEach, beforeEach, describe, expect, test, vi } from "vitest"; +import createFetchMock from "vitest-fetch-mock"; + +import TS_API from "../../content-api"; + +const fetchMocker = createFetchMock(vi); + +describe("authors api .browse() Args Type-safety", () => { + const url = process.env.VITE_GHOST_URL || "https://my-ghost-blog.com"; + const key = + process.env.VITE_GHOST_CONTENT_API_KEY || "59d4bf56c73c04a18c867dc3ba"; + const api = new TS_API(url, key, "v5.0"); + test(".browse() params shouldnt accept invalid params", () => { + // @ts-expect-error - shouldnt accept invalid params + const browse = api.authors.browse({ pp: 2 }); + expect(browse.getParams().browseParams).toStrictEqual({}); + }); + + test(".browse() 'order' params should ony accept fields values", () => { + // @ts-expect-error - order should ony contain field + expect(() => api.authors.browse({ order: "foo ASC" })).toThrow(); + // valid + expect( + api.authors.browse({ order: "name ASC" }).getParams().browseParams, + ).toStrictEqual({ + order: "name ASC", + }); + expect( + api.authors.browse({ order: "name ASC,slug DESC" }).getParams() + .browseParams, + ).toStrictEqual({ + order: "name ASC,slug DESC", + }); + expect( + api.authors + .browse({ order: "name ASC,slug DESC,location ASC" }) + .getParams().browseParams, + ).toStrictEqual({ + order: "name ASC,slug DESC,location ASC", + }); + // @ts-expect-error - order should ony contain field (There is a typo in location) + expect(() => + api.authors.browse({ order: "name ASC,slug DESC,locaton ASC" }), + ).toThrow(); + }); + + test(".browse() 'filter' params should ony accept valid field", () => { + expect(() => + api.authors.browse({ + // @ts-expect-error - order should ony contain field + filter: "foo:bar", + }), + ).toThrow(); + expect( + api.authors + .browse({ + filter: "name:bar", + }) + .getParams().browseParams, + ).toStrictEqual({ + filter: "name:bar", + }); + expect( + api.authors + .browse({ + filter: "name:bar+slug:-test", + }) + .getParams().browseParams, + ).toStrictEqual({ + filter: "name:bar+slug:-test", + }); + }); + + test(".browse 'fields' argument should ony accept valid fields", () => { + expect( + api.authors + .browse() + .fields({ + // @ts-expect-error - order should ony contain field + foo: true, + }) + .getOutputFields(), + ).toEqual([]); + + expect( + api.authors.browse().fields({ location: true }).getOutputFields(), + ).toEqual(["location"]); + expect( + api.authors + .browse() + .fields({ name: true, website: true }) + .getOutputFields(), + ).toEqual(["name", "website"]); + }); +}); + +describe("authors resource mocked", () => { + let api: TS_API; + + beforeEach(() => { + api = new TS_API( + "https://my-ghost-blog.com", + "59d4bf56c73c04a18c867dc3ba", + "v5.0", + ); + fetchMocker.enableMocks(); + }); + afterEach(() => { + vi.restoreAllMocks(); + }); + + test("aouthors should be fetched correctly", async () => { + const authors = api.authors; + expect(authors).not.toBeUndefined(); + const browseQuery = authors + .browse({ + page: 2, + }) + .fields({ + name: true, + id: true, + }); + expect(browseQuery).not.toBeUndefined(); + expect(browseQuery.getOutputFields()).toStrictEqual(["name", "id"]); + + fetchMocker.doMockOnce( + JSON.stringify({ + authors: [ + { + name: "foo", + id: "eaoizdjoa1321123", + }, + ], + meta: { + pagination: { + page: 1, + limit: 15, + pages: 1, + total: 1, + next: null, + prev: null, + }, + }, + }), + ); + const result = await browseQuery.fetch(); + expect(fetchMocker).toHaveBeenCalledTimes(1); + expect(fetchMocker).toHaveBeenCalledWith( + "https://my-ghost-blog.com/ghost/api/content/authors/?page=2&fields=name%2Cid&key=59d4bf56c73c04a18c867dc3ba", + { + headers: { + "Content-Type": "application/json", + "Accept-Version": "v5.0", + }, + }, + ); + expect(result).not.toBeUndefined(); + if (result.success) { + expect(result.data.length).toBe(1); + expect(result.data[0].name).toBe("foo"); + expect(result.data[0].id).toBe("eaoizdjoa1321123"); + } + }); +}); diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/schemas/authors/authors.ts b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/authors/authors.ts new file mode 100644 index 00000000..c5df9eba --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/authors/authors.ts @@ -0,0 +1,37 @@ +import { + ghostIdentitySchema, + ghostMetaSchema, + ghostMetadataSchema, +} from "@ts-ghost/core-api"; +import { z } from "astro/zod"; + +export const authorsSchema = z.object({ + ...ghostIdentitySchema.shape, + ...ghostMetadataSchema.shape, + name: z.string(), + profile_image: z.string().nullable(), + cover_image: z.string().nullable(), + bio: z.string().nullable(), + website: z.string().nullable(), + location: z.string().nullable(), + facebook: z.string().nullable(), + twitter: z.string().nullable(), + count: z + .object({ + posts: z.number(), + }) + .optional(), + url: z.string(), +}); + +export type Author = z.infer; + +export const ghostFetchAuthorsSchema = z.object({ + meta: ghostMetaSchema, + authors: z.array(authorsSchema), +}); + +export const authorsIncludeSchema = z.object({ + "count.posts": z.literal(true).optional(), +}); +export type AuthorsIncludeSchema = z.infer; diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/schemas/authors/index.ts b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/authors/index.ts new file mode 100644 index 00000000..f9adb07f --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/authors/index.ts @@ -0,0 +1 @@ +export * from "./authors"; diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/schemas/helpers/index.ts b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/helpers/index.ts new file mode 100644 index 00000000..f4fb9f52 --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/helpers/index.ts @@ -0,0 +1 @@ +export * from "./socials"; diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/schemas/helpers/socials.ts b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/helpers/socials.ts new file mode 100644 index 00000000..95dc9a9b --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/helpers/socials.ts @@ -0,0 +1,32 @@ +// Transformed to TypeScript, original Code by Ghost Foundation, License: +// MIT License + +// Copyright (c) 2013-2022 Ghost Foundation + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +export const twitter = (username: string) => { + // Creates the canonical twitter URL without the '@' + return `https://twitter.com/${username.replace(/^@/, "")}`; +}; + +export const facebook = (username: string) => { + // Handles a starting slash, this shouldn't happen, but just in case + return `https://www.facebook.com/${username.replace(/^\//, "")}`; +}; diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/schemas/index.ts b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/index.ts new file mode 100644 index 00000000..88bfc1b9 --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/index.ts @@ -0,0 +1,7 @@ +export * from "./authors"; +export * from "./helpers"; +export * from "./pages"; +export * from "./posts"; +export * from "./settings"; +export * from "./tags"; +export * from "./tiers"; diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/schemas/pages/index.ts b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/pages/index.ts new file mode 100644 index 00000000..c4e34b27 --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/pages/index.ts @@ -0,0 +1 @@ +export * from "./pages"; diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/schemas/pages/pages.ts b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/pages/pages.ts new file mode 100644 index 00000000..2fcd9655 --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/pages/pages.ts @@ -0,0 +1,55 @@ +import { + ghostCodeInjectionSchema, + ghostIdentitySchema, + ghostMetadataSchema, + ghostSocialMediaSchema, + ghostVisibilitySchema, +} from "@ts-ghost/core-api"; +import { z } from "astro/zod"; + +import { authorsSchema } from "../authors"; +import { tagsSchema } from "../tags"; + +const postsAuthorSchema = authorsSchema.extend({ + url: z.string().nullish(), +}); + +export const pagesSchema = z.object({ + ...ghostIdentitySchema.shape, + ...ghostMetadataSchema.shape, + title: z.string(), + html: z.string().catch(""), + plaintext: z.string().nullish(), + comment_id: z.string().nullable(), + feature_image: z.string().nullable(), + feature_image_alt: z.string().nullable(), + feature_image_caption: z.string().nullable(), + featured: z.boolean(), + custom_excerpt: z.string().nullable(), + ...ghostCodeInjectionSchema.shape, + ...ghostSocialMediaSchema.shape, + visibility: ghostVisibilitySchema, + custom_template: z.string().nullable(), + canonical_url: z.string().nullable(), + authors: z.array(postsAuthorSchema).optional(), + tags: z.array(tagsSchema).optional(), + primary_author: postsAuthorSchema.nullish(), + primary_tag: tagsSchema.nullish(), + url: z.string(), + excerpt: z.string().catch(""), + reading_time: z.number().optional().default(0), + created_at: z.string(), + updated_at: z.string(), + published_at: z.string(), + access: z.boolean(), + comments: z.boolean(), + email_subject: z.string().nullish(), +}); + +export type Page = z.infer; + +export const pagesIncludeSchema = z.object({ + authors: z.literal(true).optional(), + tags: z.literal(true).optional(), +}); +export type PagesIncludeSchema = z.infer; diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/schemas/posts/index.ts b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/posts/index.ts new file mode 100644 index 00000000..4f89127a --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/posts/index.ts @@ -0,0 +1 @@ +export * from "./posts"; diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/schemas/posts/posts.test.ts b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/posts/posts.test.ts new file mode 100644 index 00000000..b2dfbbe3 --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/posts/posts.test.ts @@ -0,0 +1,69 @@ +import { describe, expect, test } from "vitest"; + +import TS_API from "../../content-api"; +import type { Post } from "./posts"; + +const url = process.env.VITE_GHOST_URL || "https://my-ghost-blog.com"; +const key = + process.env.VITE_GHOST_CONTENT_API_KEY || "59d4bf56c73c04a18c867dc3ba"; + +describe("posts api .browse() Args Type-safety", () => { + const api = new TS_API(url, key, "v5.0"); + test(".browse() params shouldnt accept invalid params", () => { + // @ts-expect-error - shouldnt accept invalid params + const browse = api.posts.browse({ pp: 2 }); + expect(browse.getParams().browseParams).toStrictEqual({}); + + const outputFields = { + slug: true, + title: true, + // @ts-expect-error - shouldnt accept invalid params + foo: true, + } satisfies { [k in keyof Post]?: true | undefined }; + + // biome-ignore lint/style/useConst: + let test = api.posts + .browse() + // @ts-expect-error - shouldnt accept invalid params + .fields(outputFields); + expect(test.getOutputFields()).toEqual(["slug", "title"]); + + const fields = ["slug", "title", "foo"] as const; + const unknownOriginFields = fields.reduce( + (acc, k) => { + acc[k as keyof Post] = true; + return acc; + }, + {} as { [k in keyof Post]?: true | undefined }, + ); + const result = api.posts.browse().fields(unknownOriginFields); + expect(result.getOutputFields()).toEqual(["slug", "title"]); + }); + test(".browse() params, output fields declare const", () => { + const outputFields = { + slug: true, + title: true, + } satisfies { [k in keyof Post]?: true | undefined }; + + // biome-ignore lint/style/useConst: + let test = api.posts.browse().fields(outputFields); + expect(test.getOutputFields()).toEqual(["slug", "title"]); + + // @ts-expect-error - shouldnt accept invalid params + expect(() => api.posts.browse({ filter: "slugg:test" })).toThrow(); + // @ts-expect-error - shouldnt accept invalid params + expect(() => + api.posts.browse({ filter: "slug:test,foo:-[bar,baz]" }), + ).toThrow(); + expect( + api.posts.browse({ filter: "slug:test,tags:-[bar,baz]" }), + ).toBeDefined(); + expect( + api.posts.browse({ filter: "slug:test,tags:[bar,baz]" }), + ).toBeDefined(); + // @ts-expect-error - shouldnt accept invalid params + expect(() => + api.posts.browse({ filter: "slug:test,food:-[bar,baz]" }), + ).toThrow(); + }); +}); diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/schemas/posts/posts.ts b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/posts/posts.ts new file mode 100644 index 00000000..b479ee17 --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/posts/posts.ts @@ -0,0 +1,54 @@ +import { + ghostCodeInjectionSchema, + ghostIdentitySchema, + ghostMetadataSchema, + ghostSocialMediaSchema, + ghostVisibilitySchema, +} from "@ts-ghost/core-api"; +import { z } from "astro/zod"; + +import { authorsSchema } from "../authors"; +import { tagsSchema } from "../tags"; + +const postsAuthorSchema = authorsSchema.extend({ + url: z.string().nullish(), +}); +export const postsSchema = z.object({ + ...ghostIdentitySchema.shape, + ...ghostMetadataSchema.shape, + title: z.string(), + html: z.string().catch(""), + plaintext: z.string().nullish(), + comment_id: z.string().nullable(), + feature_image: z.string().nullable(), + feature_image_alt: z.string().nullable(), + feature_image_caption: z.string().nullable(), + featured: z.boolean(), + custom_excerpt: z.string().nullable(), + ...ghostCodeInjectionSchema.shape, + ...ghostSocialMediaSchema.shape, + visibility: ghostVisibilitySchema, + custom_template: z.string().nullable(), + canonical_url: z.string().nullable(), + authors: z.array(postsAuthorSchema).optional(), + tags: z.array(tagsSchema).optional(), + primary_author: postsAuthorSchema.nullish(), + primary_tag: tagsSchema.nullish(), + url: z.string(), + excerpt: z.string().catch(""), + reading_time: z.number().optional().default(0), + created_at: z.string(), + updated_at: z.string().nullish(), + published_at: z.string().nullish(), + access: z.boolean(), + comments: z.boolean(), + email_subject: z.string().nullish(), +}); + +export type Post = z.infer; + +export const postsIncludeSchema = z.object({ + authors: z.literal(true).optional(), + tags: z.literal(true).optional(), +}); +export type PostsIncludeSchema = z.infer; diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/schemas/settings/index.ts b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/settings/index.ts new file mode 100644 index 00000000..dcf101b0 --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/settings/index.ts @@ -0,0 +1 @@ +export * from "./settings"; diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/schemas/settings/settings.ts b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/settings/settings.ts new file mode 100644 index 00000000..4417b8ae --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/settings/settings.ts @@ -0,0 +1,40 @@ +import { z } from "astro/zod"; + +export const settingsSchema = z.object({ + title: z.string(), + description: z.string(), + logo: z.string().nullable(), + icon: z.string().nullable(), + accent_color: z.string().nullable(), + cover_image: z.string().nullable(), + facebook: z.string().nullable(), + twitter: z.string().nullable(), + lang: z.string(), + timezone: z.string(), + codeinjection_head: z.string().nullable(), + codeinjection_foot: z.string().nullable(), + navigation: z.array( + z.object({ + label: z.string(), + url: z.string(), + }), + ), + secondary_navigation: z.array( + z.object({ + label: z.string(), + url: z.string(), + }), + ), + meta_title: z.string().nullable(), + meta_description: z.string().nullable(), + og_image: z.string().nullable(), + og_title: z.string().nullable(), + og_description: z.string().nullable(), + twitter_image: z.string().nullable(), + twitter_title: z.string().nullable(), + twitter_description: z.string().nullable(), + members_support_address: z.string(), + url: z.string(), +}); + +export type Settings = z.infer; diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/schemas/tags/index.ts b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/tags/index.ts new file mode 100644 index 00000000..006f4bf5 --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/tags/index.ts @@ -0,0 +1 @@ +export * from "./tags"; diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/schemas/tags/tags.ts b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/tags/tags.ts new file mode 100644 index 00000000..9344112d --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/tags/tags.ts @@ -0,0 +1,34 @@ +import { + ghostCodeInjectionSchema, + ghostIdentitySchema, + ghostMetadataSchema, + ghostSocialMediaSchema, + ghostVisibilitySchema, +} from "@ts-ghost/core-api"; +import { z } from "astro/zod"; + +export const tagsSchema = z.object({ + ...ghostIdentitySchema.shape, + ...ghostMetadataSchema.shape, + ...ghostCodeInjectionSchema.shape, + ...ghostSocialMediaSchema.shape, + name: z.string(), + description: z.string().nullable(), + feature_image: z.string().nullable(), + visibility: ghostVisibilitySchema, + canonical_url: z.string().nullable(), + accent_color: z.string().nullable(), + url: z.string(), + count: z + .object({ + posts: z.number(), + }) + .optional(), +}); + +export type Tag = z.infer; + +export const tagsIncludeSchema = z.object({ + "count.posts": z.literal(true).optional(), +}); +export type TagsIncludeSchema = z.infer; diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/schemas/tiers/index.ts b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/tiers/index.ts new file mode 100644 index 00000000..aec8c265 --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/tiers/index.ts @@ -0,0 +1 @@ +export * from "./tiers"; diff --git a/packages/starlight-ghostcms/src/utils/api/content-api/schemas/tiers/tiers.ts b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/tiers/tiers.ts new file mode 100644 index 00000000..1dff9462 --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/content-api/schemas/tiers/tiers.ts @@ -0,0 +1,40 @@ +import { ghostIdentitySchema, ghostVisibilitySchema } from "@ts-ghost/core-api"; +import { z } from "astro/zod"; + +export const tiersSchema = z.object({ + ...ghostIdentitySchema.shape, + name: z.string(), + description: z.string().nullable(), + active: z.boolean(), + type: z.union([z.literal("free"), z.literal("paid")]), + welcome_page_url: z.string().nullable(), + created_at: z.string(), + updated_at: z.string().nullable(), + stripe_prices: z + .array(z.number()) + .optional() + .transform((v) => (v?.length ? v : [])), + monthly_price: z + .number() + .nullable() + .optional() + .transform((v) => (v ? v : null)), + yearly_price: z + .number() + .nullable() + .optional() + .transform((v) => (v ? v : null)), + benefits: z.array(z.string()), + visibility: ghostVisibilitySchema, + currency: z.string().nullish(), + trial_days: z.number().default(0), +}); + +export type Tier = z.infer; + +export const tiersIncludeSchema = z.object({ + monthly_price: z.literal(true).optional(), + yearly_price: z.literal(true).optional(), + benefits: z.literal(true).optional(), +}); +export type TiersIncludeSchema = z.infer; diff --git a/packages/starlight-ghostcms/src/utils/api/index.ts b/packages/starlight-ghostcms/src/utils/api/index.ts new file mode 100644 index 00000000..91557560 --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/index.ts @@ -0,0 +1,3 @@ +export * from "./api-functions"; +export * from "./content-api/schemas"; +export * from "./invariant"; diff --git a/packages/starlight-ghostcms/src/utils/api/invariant.test.ts b/packages/starlight-ghostcms/src/utils/api/invariant.test.ts new file mode 100644 index 00000000..20c887b9 --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/invariant.test.ts @@ -0,0 +1,32 @@ +import { describe, expect, it } from "vitest"; + +// Modified version of invariant script to allow tests +const isProduction = false; +const prefix: string = "Invariant failed"; +function invariant(condition: any, message?: string | (() => string)) { + if (condition) { + return; + } + if (isProduction) { + throw new Error(prefix); + } + const provided: string | undefined = + typeof message === "function" ? message() : message; + const value: string = provided ? `${prefix}: ${provided}` : prefix; + return value; +} + +// TEST SECTION +const testTrue = true; +const testFalse = false; +describe("test invariant", () => { + it("Test `true` value", () => { + invariant(testTrue, "This should not error"); + expect(null); + }); + + it("Test `false` value", () => { + invariant(testFalse, "This should Error"); + expect(String("Invariant failed")); + }); +}); diff --git a/packages/starlight-ghostcms/src/utils/api/invariant.ts b/packages/starlight-ghostcms/src/utils/api/invariant.ts new file mode 100644 index 00000000..787f7935 --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/api/invariant.ts @@ -0,0 +1,48 @@ +/** MIT License + +Copyright (c) 2019 Alexander Reardon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +const tinyinvariant = "merged"; +const isProduction: boolean = process.env.NODE_ENV === "production"; +const prefix: string = "Invariant failed"; + +/** Throw an error if the condition is false + * @example + * import { invariant } from '@matthiesenxyz/astro-ghostcms/api'; + * invariant(var, "var is false but its not supposed to be!") + */ +export function invariant( + condition: any, + message?: string | (() => string), +): asserts condition { + if (condition) { + return; + } + if (isProduction) { + throw new Error(prefix); + } + + const provided: string | undefined = + typeof message === "function" ? message() : message; + + const value: string = provided ? `${prefix}: ${provided}` : prefix; + throw new Error(value); +} diff --git a/packages/starlight-ghostcms/src/utils/page.ts b/packages/starlight-ghostcms/src/utils/page.ts new file mode 100644 index 00000000..472aa6d2 --- /dev/null +++ b/packages/starlight-ghostcms/src/utils/page.ts @@ -0,0 +1,33 @@ +export function isAnyBlogPage(slug: string) { + return slug.match(/^blog(\/?$|\/.+\/?$)/) !== null +} + +export function isBlogRoot(slug: string) { + return slug === 'blog' +} + +export function isAnyBlogPostPage(slug: string) { + return slug.match(/^blog\/(?!(\d+\/?|tags\/.+)$).+$/) !== null +} + +export function isBlogPostPage(slug: string, postSlug: string) { + return slug === postSlug +} + +export function isBlogTagsPage(slug: string, tag: string) { + return slug === `blog/tags/${tag}` +} + +export function getPageProps(title: string): StarlightPageProps { + return { + frontmatter: { + title, + }, + } +} + +interface StarlightPageProps { + frontmatter: { + title: string + } +} diff --git a/packages/starlight-ghostcms/starlight.d.ts b/packages/starlight-ghostcms/starlight.d.ts new file mode 100644 index 00000000..532e47fc --- /dev/null +++ b/packages/starlight-ghostcms/starlight.d.ts @@ -0,0 +1,5 @@ +declare module 'virtual:starlight/user-config' { + const Config: import('@astrojs/starlight/types').StarlightConfig + + export default Config +} diff --git a/packages/starlight-ghostcms/tsconfig.json b/packages/starlight-ghostcms/tsconfig.json new file mode 100644 index 00000000..73727041 --- /dev/null +++ b/packages/starlight-ghostcms/tsconfig.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "allowUnreachableCode": false, + "allowUnusedLabels": false, + "esModuleInterop": true, + "exactOptionalPropertyTypes": true, + "forceConsistentCasingInFileNames": true, + "incremental": true, + "jsx": "react-jsx", + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "module": "ESNext", + "moduleResolution": "bundler", + "noFallthroughCasesInSwitch": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noPropertyAccessFromIndexSignature": true, + "noUncheckedIndexedAccess": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "target": "ESNext", + "useDefineForClassFields": true, + "verbatimModuleSyntax": true + } + } \ No newline at end of file diff --git a/packages/starlight-ghostcms/virtual.d.ts b/packages/starlight-ghostcms/virtual.d.ts new file mode 100644 index 00000000..d69104e9 --- /dev/null +++ b/packages/starlight-ghostcms/virtual.d.ts @@ -0,0 +1,5 @@ +declare module 'virtual:starlight-ghost-config' { + const StarlightGhostConfig: import('./src/schemas/config').StarlightGhostConfig + + export default StarlightGhostConfig +} diff --git a/packages/starlight-ghostcms/vitest.config.ts b/packages/starlight-ghostcms/vitest.config.ts new file mode 100644 index 00000000..deec7256 --- /dev/null +++ b/packages/starlight-ghostcms/vitest.config.ts @@ -0,0 +1,15 @@ +/// +/// + +import tsconfigPaths from "vite-tsconfig-paths"; +import { defineProject } from "vitest/config"; + +export default defineProject({ + plugins: [tsconfigPaths()], + test: { + globals: true, + include: ["./**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"], + watchExclude: [".*\\/node_modules\\/.*", ".*\\/build\\/.*"], + exclude: ["node_modules", "dist", ".idea", ".git", ".cache"], + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 836e7f73..bb799b2e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,7 +33,7 @@ importers: specifier: ^3.0.5 version: 3.0.5 '@matthiesenxyz/astro-ghostcms-theme-default': - specifier: ^0.1.12 + specifier: ^0.1.13 version: link:../astro-ghostcms-theme-default '@resvg/resvg-js': specifier: ^2.6.0 @@ -127,10 +127,10 @@ importers: specifier: ^1.1.8 version: 1.1.8 '@matthiesenxyz/astro-ghostcms': - specifier: ^3.2.8 + specifier: ^3.2.9 version: link:../astro-ghostcms '@matthiesenxyz/astro-ghostcms-rendercontent': - specifier: ^0.0.6 + specifier: ^0.0.7 version: link:../astro-ghostcms-rendercontent '@unocss/astro': specifier: ^0.58.5 @@ -185,7 +185,7 @@ importers: specifier: ^5.0.16 version: 5.0.16 '@matthiesenxyz/astro-ghostcms': - specifier: ^3.2.8 + specifier: ^3.2.9 version: link:../astro-ghostcms '@tailwindcss/typography': specifier: ^0.5.10 @@ -219,7 +219,7 @@ importers: packages/astro-ghostcms-theme-default: dependencies: '@matthiesenxyz/astro-ghostcms': - specifier: ^3.2.7 + specifier: ^3.2.9 version: link:../astro-ghostcms astro: specifier: ^4.2.1 @@ -302,6 +302,33 @@ importers: specifier: ^1.3.0 version: 1.3.0(@types/node@20.11.19)(@vitest/ui@1.3.0) + packages/starlight-ghostcms: + devDependencies: + '@astrojs/starlight': + specifier: 0.19.0 + version: 0.19.0(astro@4.4.0) + '@ts-ghost/core-api': + specifier: 5.1.2 + version: 5.1.2 + '@ts-ghost/tsconfig': + specifier: workspace:* + version: link:../tsconfig + astro: + specifier: 4.4.0 + version: 4.4.0(typescript@5.3.3) + vite: + specifier: ^5.1.2 + version: 5.1.2 + vite-tsconfig-paths: + specifier: ^4.2.2 + version: 4.3.1(vite@5.1.2) + vitest: + specifier: ^1.2.2 + version: 1.2.2(@vitest/ui@1.3.0) + vitest-fetch-mock: + specifier: ^0.2.2 + version: 0.2.2(vitest@1.2.2) + packages/tsconfig: {} playground: @@ -341,6 +368,21 @@ importers: specifier: ^0.58.5 version: 0.58.5(postcss@8.4.35)(vite@5.1.3) + starlight-playground: + dependencies: + '@astrojs/starlight': + specifier: ^0.19.0 + version: 0.19.0(astro@4.4.0) + '@matthiesenxyz/starlight-ghostcms': + specifier: workspace:* + version: link:../packages/starlight-ghostcms + astro: + specifier: ^4.4.0 + version: 4.4.0(typescript@5.3.3) + sharp: + specifier: ^0.32.5 + version: 0.32.6 + packages: /@aashutoshrathi/word-wrap@1.2.6: @@ -447,6 +489,31 @@ packages: transitivePeerDependencies: - supports-color + /@astrojs/mdx@2.1.1(astro@4.4.0): + resolution: {integrity: sha512-AgGFdE7HOGmoFooGvMSatkA9FiSKwyVW7ImHot/bXJ6uAbFfu6iG2ht18Cf1pT22Hda/6iSCGWusFvBv0/EnKQ==} + engines: {node: '>=18.14.1'} + peerDependencies: + astro: ^4.0.0 + dependencies: + '@astrojs/markdown-remark': 4.2.1 + '@mdx-js/mdx': 3.0.1 + acorn: 8.11.3 + astro: 4.4.0(typescript@5.3.3) + es-module-lexer: 1.4.1 + estree-util-visit: 2.0.0 + github-slugger: 2.0.0 + gray-matter: 4.0.3 + hast-util-to-html: 9.0.0 + kleur: 4.1.5 + rehype-raw: 7.0.0 + remark-gfm: 4.0.0 + remark-smartypants: 2.1.0 + source-map: 0.7.4 + unist-util-visit: 5.0.0 + vfile: 6.0.1 + transitivePeerDependencies: + - supports-color + /@astrojs/prism@3.0.0: resolution: {integrity: sha512-g61lZupWq1bYbcBnYZqdjndShr/J3l/oFobBKPA3+qMat146zce3nz2kdO4giGbhYDt4gYdhmoBz0vZJ4sIurQ==} engines: {node: '>=18.14.1'} @@ -465,7 +532,33 @@ packages: dependencies: sitemap: 7.1.1 zod: 3.22.4 - dev: false + + /@astrojs/starlight@0.19.0(astro@4.4.0): + resolution: {integrity: sha512-izNZLs99d4AAoN5eV6Ek71SVKEAs8N/GjT+n9J0Q8q1Zgtk/qcv3KzuPXBZmiAbPl/9E2+BG8f4dpdoc+F4U3g==} + peerDependencies: + astro: ^4.2.7 + dependencies: + '@astrojs/mdx': 2.1.1(astro@4.4.0) + '@astrojs/sitemap': 3.0.5 + '@pagefind/default-ui': 1.0.4 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.3 + astro: 4.4.0(typescript@5.3.3) + astro-expressive-code: 0.32.4(astro@4.4.0) + bcp-47: 2.1.0 + hast-util-select: 6.0.2 + hastscript: 8.0.0 + mdast-util-directive: 3.0.0 + mdast-util-to-markdown: 2.1.0 + pagefind: 1.0.4 + rehype: 13.0.1 + remark-directive: 3.0.0 + unified: 11.0.4 + unist-util-remove: 4.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.1 + transitivePeerDependencies: + - supports-color /@astrojs/tailwind@5.1.0(astro@4.3.7)(tailwindcss@3.4.1): resolution: {integrity: sha512-BJoCDKuWhU9FT2qYg+fr6Nfb3qP4ShtyjXGHKA/4mHN94z7BGcmauQK23iy+YH5qWvTnhqkd6mQPQ1yTZTe9Ig==} @@ -1089,6 +1182,10 @@ packages: bundledDependencies: - is-unicode-supported + /@ctrl/tinycolor@3.6.1: + resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} + engines: {node: '>=10'} + /@eliancodes/brutal-ui@0.2.3: resolution: {integrity: sha512-HbxNDI7Ud+mREpckXSCaL6ntvUGJLq8Gc9XO/iH2ndZWeuBw0nBOzduKGgbJIQWt55bKmQiGkCr8V9VqxgzGQA==} dependencies: @@ -1329,6 +1426,34 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true + /@expressive-code/core@0.32.4: + resolution: {integrity: sha512-S0OwgZCy29OCcwFUBTLDrShUovIUWZcQn3EvSoKsGfzf/wTisK7XqZ1uH0Y7Mlof3Hf9uJMjOhJZvxTLtQUdSQ==} + dependencies: + '@ctrl/tinycolor': 3.6.1 + hast-util-to-html: 8.0.4 + hastscript: 7.2.0 + postcss: 8.4.35 + postcss-nested: 6.0.1(postcss@8.4.35) + + /@expressive-code/plugin-frames@0.32.4: + resolution: {integrity: sha512-XOQrLqlVEy5JbqsBhDcSJQinceQ5j/Z8cE0/27Lnlcj4oXRdiQNjMVtstC/xZUeWEbm+FI9ZZP4Z9yihol61Aw==} + dependencies: + '@expressive-code/core': 0.32.4 + hastscript: 7.2.0 + + /@expressive-code/plugin-shiki@0.32.4: + resolution: {integrity: sha512-zZzTXFFTpG+fmBG6C+4KzIyh1nFPdn4gLJ8E9LhBVufmRkn3gZplkE99lulfillsKyUZTRw3+dC3xYZWEZKzPw==} + dependencies: + '@expressive-code/core': 0.32.4 + shikiji: 0.8.7 + + /@expressive-code/plugin-text-markers@0.32.4: + resolution: {integrity: sha512-lFlo3uwTp7vUmfXtLPn2aXs0CPFqdFvKiR3y8gtNzmBeYWPqVahF4RFUCN9ZpztCmXp5V8p2ADvNHzoNwCBwzA==} + dependencies: + '@expressive-code/core': 0.32.4 + hastscript: 7.2.0 + unist-util-visit-parents: 5.1.3 + /@fontsource-variable/inter@5.0.16: resolution: {integrity: sha512-k+BUNqksTL+AN+o+OV7ILeiE9B5M5X+/jA7LWvCwjbV9ovXTqZyKRhA/x7uYv/ml8WQ0XNLBM7cRFIx4jW0/hg==} dev: false @@ -1443,6 +1568,35 @@ packages: globby: 11.1.0 read-yaml-file: 1.1.0 + /@mdx-js/mdx@3.0.1: + resolution: {integrity: sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==} + dependencies: + '@types/estree': 1.0.5 + '@types/estree-jsx': 1.0.4 + '@types/hast': 3.0.4 + '@types/mdx': 2.0.11 + collapse-white-space: 2.1.0 + devlop: 1.1.0 + estree-util-build-jsx: 3.0.1 + estree-util-is-identifier-name: 3.0.0 + estree-util-to-js: 2.0.0 + estree-walker: 3.0.3 + hast-util-to-estree: 3.1.0 + hast-util-to-jsx-runtime: 2.3.0 + markdown-extensions: 2.0.0 + periscopic: 3.1.0 + remark-mdx: 3.0.1 + remark-parse: 11.0.0 + remark-rehype: 11.1.0 + source-map: 0.7.4 + unified: 11.0.4 + unist-util-position-from-estree: 2.0.0 + unist-util-stringify-position: 4.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.1 + transitivePeerDependencies: + - supports-color + /@medv/finder@3.1.0: resolution: {integrity: sha512-ojkXjR3K0Zz3jnCR80tqPL+0yvbZk/lEodb6RIVjLz7W8RVA2wrw8ym/CzCpXO9SYVUIKHFUpc7jvf8UKfIM3w==} @@ -1464,6 +1618,44 @@ packages: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 + /@pagefind/darwin-arm64@1.0.4: + resolution: {integrity: sha512-2OcthvceX2xhm5XbgOmW+lT45oLuHqCmvFeFtxh1gsuP5cO8vcD8ZH8Laj4pXQFCcK6eAdSShx+Ztx/LsQWZFQ==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + + /@pagefind/darwin-x64@1.0.4: + resolution: {integrity: sha512-xkdvp0D9Ld/ZKsjo/y1bgfhTEU72ITimd2PMMQtts7jf6JPIOJbsiErCvm37m/qMFuPGEq/8d+fZ4pydOj08HQ==} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + + /@pagefind/default-ui@1.0.4: + resolution: {integrity: sha512-edkcaPSKq67C49Vehjo+LQCpT615v4d7JRhfGzFPccePvdklaL+VXrfghN/uIfsdoG+HoLI1PcYy2iFcB9CTkw==} + + /@pagefind/linux-arm64@1.0.4: + resolution: {integrity: sha512-jGBrcCzIrMnNxLKVtogaQyajVfTAXM59KlBEwg6vTn8NW4fQ6nuFbbhlG4dTIsaamjEM5e8ZBEAKZfTB/qd9xw==} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + /@pagefind/linux-x64@1.0.4: + resolution: {integrity: sha512-LIn/QcvcEtLEBqKe5vpSbSC2O3fvqbRCWOTIklslqSORisCsvzsWbP6j+LYxE9q0oWIfkdMoWV1vrE/oCKRxHg==} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + /@pagefind/windows-x64@1.0.4: + resolution: {integrity: sha512-QlBCVeZfj9fc9sbUgdOz76ZDbeK4xZihOBAFqGuRJeChfM8pnVeH9iqSnXgO3+m9oITugTf7PicyRUFAG76xeQ==} + cpu: [x64] + os: [win32] + requiresBuild: true + optional: true + /@pkgjs/parseargs@0.11.0: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -1639,92 +1831,92 @@ packages: estree-walker: 2.0.2 picomatch: 2.3.1 - /@rollup/rollup-android-arm-eabi@4.12.0: - resolution: {integrity: sha512-+ac02NL/2TCKRrJu2wffk1kZ+RyqxVUlbjSagNgPm94frxtr+XDL12E5Ll1enWskLrtrZ2r8L3wED1orIibV/w==} + /@rollup/rollup-android-arm-eabi@4.11.0: + resolution: {integrity: sha512-BV+u2QSfK3i1o6FucqJh5IK9cjAU6icjFFhvknzFgu472jzl0bBojfDAkJLBEsHFMo+YZg6rthBvBBt8z12IBQ==} cpu: [arm] os: [android] requiresBuild: true optional: true - /@rollup/rollup-android-arm64@4.12.0: - resolution: {integrity: sha512-OBqcX2BMe6nvjQ0Nyp7cC90cnumt8PXmO7Dp3gfAju/6YwG0Tj74z1vKrfRz7qAv23nBcYM8BCbhrsWqO7PzQQ==} + /@rollup/rollup-android-arm64@4.11.0: + resolution: {integrity: sha512-0ij3iw7sT5jbcdXofWO2NqDNjSVVsf6itcAkV2I6Xsq4+6wjW1A8rViVB67TfBEan7PV2kbLzT8rhOVWLI2YXw==} cpu: [arm64] os: [android] requiresBuild: true optional: true - /@rollup/rollup-darwin-arm64@4.12.0: - resolution: {integrity: sha512-X64tZd8dRE/QTrBIEs63kaOBG0b5GVEd3ccoLtyf6IdXtHdh8h+I56C2yC3PtC9Ucnv0CpNFJLqKFVgCYe0lOQ==} + /@rollup/rollup-darwin-arm64@4.11.0: + resolution: {integrity: sha512-yPLs6RbbBMupArf6qv1UDk6dzZvlH66z6NLYEwqTU0VHtss1wkI4UYeeMS7TVj5QRVvaNAWYKP0TD/MOeZ76Zg==} cpu: [arm64] os: [darwin] requiresBuild: true optional: true - /@rollup/rollup-darwin-x64@4.12.0: - resolution: {integrity: sha512-cc71KUZoVbUJmGP2cOuiZ9HSOP14AzBAThn3OU+9LcA1+IUqswJyR1cAJj3Mg55HbjZP6OLAIscbQsQLrpgTOg==} + /@rollup/rollup-darwin-x64@4.11.0: + resolution: {integrity: sha512-OvqIgwaGAwnASzXaZEeoJY3RltOFg+WUbdkdfoluh2iqatd090UeOG3A/h0wNZmE93dDew9tAtXgm3/+U/B6bw==} cpu: [x64] os: [darwin] requiresBuild: true optional: true - /@rollup/rollup-linux-arm-gnueabihf@4.12.0: - resolution: {integrity: sha512-a6w/Y3hyyO6GlpKL2xJ4IOh/7d+APaqLYdMf86xnczU3nurFTaVN9s9jOXQg97BE4nYm/7Ga51rjec5nfRdrvA==} + /@rollup/rollup-linux-arm-gnueabihf@4.11.0: + resolution: {integrity: sha512-X17s4hZK3QbRmdAuLd2EE+qwwxL8JxyVupEqAkxKPa/IgX49ZO+vf0ka69gIKsaYeo6c1CuwY3k8trfDtZ9dFg==} cpu: [arm] os: [linux] requiresBuild: true optional: true - /@rollup/rollup-linux-arm64-gnu@4.12.0: - resolution: {integrity: sha512-0fZBq27b+D7Ar5CQMofVN8sggOVhEtzFUwOwPppQt0k+VR+7UHMZZY4y+64WJ06XOhBTKXtQB/Sv0NwQMXyNAA==} + /@rollup/rollup-linux-arm64-gnu@4.11.0: + resolution: {integrity: sha512-673Lu9EJwxVB9NfYeA4AdNu0FOHz7g9t6N1DmT7bZPn1u6bTF+oZjj+fuxUcrfxWXE0r2jxl5QYMa9cUOj9NFg==} cpu: [arm64] os: [linux] requiresBuild: true optional: true - /@rollup/rollup-linux-arm64-musl@4.12.0: - resolution: {integrity: sha512-eTvzUS3hhhlgeAv6bfigekzWZjaEX9xP9HhxB0Dvrdbkk5w/b+1Sxct2ZuDxNJKzsRStSq1EaEkVSEe7A7ipgQ==} + /@rollup/rollup-linux-arm64-musl@4.11.0: + resolution: {integrity: sha512-yFW2msTAQNpPJaMmh2NpRalr1KXI7ZUjlN6dY/FhWlOclMrZezm5GIhy3cP4Ts2rIAC+IPLAjNibjp1BsxCVGg==} cpu: [arm64] os: [linux] requiresBuild: true optional: true - /@rollup/rollup-linux-riscv64-gnu@4.12.0: - resolution: {integrity: sha512-ix+qAB9qmrCRiaO71VFfY8rkiAZJL8zQRXveS27HS+pKdjwUfEhqo2+YF2oI+H/22Xsiski+qqwIBxVewLK7sw==} + /@rollup/rollup-linux-riscv64-gnu@4.11.0: + resolution: {integrity: sha512-kKT9XIuhbvYgiA3cPAGntvrBgzhWkGpBMzuk1V12Xuoqg7CI41chye4HU0vLJnGf9MiZzfNh4I7StPeOzOWJfA==} cpu: [riscv64] os: [linux] requiresBuild: true optional: true - /@rollup/rollup-linux-x64-gnu@4.12.0: - resolution: {integrity: sha512-TenQhZVOtw/3qKOPa7d+QgkeM6xY0LtwzR8OplmyL5LrgTWIXpTQg2Q2ycBf8jm+SFW2Wt/DTn1gf7nFp3ssVA==} + /@rollup/rollup-linux-x64-gnu@4.11.0: + resolution: {integrity: sha512-6q4ESWlyTO+erp1PSCmASac+ixaDv11dBk1fqyIuvIUc/CmRAX2Zk+2qK1FGo5q7kyDcjHCFVwgGFCGIZGVwCA==} cpu: [x64] os: [linux] requiresBuild: true optional: true - /@rollup/rollup-linux-x64-musl@4.12.0: - resolution: {integrity: sha512-LfFdRhNnW0zdMvdCb5FNuWlls2WbbSridJvxOvYWgSBOYZtgBfW9UGNJG//rwMqTX1xQE9BAodvMH9tAusKDUw==} + /@rollup/rollup-linux-x64-musl@4.11.0: + resolution: {integrity: sha512-vIAQUmXeMLmaDN78HSE4Kh6xqof2e3TJUKr+LPqXWU4NYNON0MDN9h2+t4KHrPAQNmU3w1GxBQ/n01PaWFwa5w==} cpu: [x64] os: [linux] requiresBuild: true optional: true - /@rollup/rollup-win32-arm64-msvc@4.12.0: - resolution: {integrity: sha512-JPDxovheWNp6d7AHCgsUlkuCKvtu3RB55iNEkaQcf0ttsDU/JZF+iQnYcQJSk/7PtT4mjjVG8N1kpwnI9SLYaw==} + /@rollup/rollup-win32-arm64-msvc@4.11.0: + resolution: {integrity: sha512-LVXo9dDTGPr0nezMdqa1hK4JeoMZ02nstUxGYY/sMIDtTYlli1ZxTXBYAz3vzuuvKO4X6NBETciIh7N9+abT1g==} cpu: [arm64] os: [win32] requiresBuild: true optional: true - /@rollup/rollup-win32-ia32-msvc@4.12.0: - resolution: {integrity: sha512-fjtuvMWRGJn1oZacG8IPnzIV6GF2/XG+h71FKn76OYFqySXInJtseAqdprVTDTyqPxQOG9Exak5/E9Z3+EJ8ZA==} + /@rollup/rollup-win32-ia32-msvc@4.11.0: + resolution: {integrity: sha512-xZVt6K70Gr3I7nUhug2dN6VRR1ibot3rXqXS3wo+8JP64t7djc3lBFyqO4GiVrhNaAIhUCJtwQ/20dr0h0thmQ==} cpu: [ia32] os: [win32] requiresBuild: true optional: true - /@rollup/rollup-win32-x64-msvc@4.12.0: - resolution: {integrity: sha512-ZYmr5mS2wd4Dew/JjT0Fqi2NPB/ZhZ2VvPp7SmvPZb4Y1CG/LRcS6tcRo2cYU7zLK5A7cdbhWnnWmUjoI4qapg==} + /@rollup/rollup-win32-x64-msvc@4.11.0: + resolution: {integrity: sha512-f3I7h9oTg79UitEco9/2bzwdciYkWr8pITs3meSDSlr1TdvQ7IxkQaaYN2YqZXX5uZhiYL+VuYDmHwNzhx+HOg==} cpu: [x64] os: [win32] requiresBuild: true @@ -1772,7 +1964,11 @@ packages: dependencies: jose: 5.2.2 zod: 3.22.4 - dev: false + + /@types/acorn@4.0.6: + resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} + dependencies: + '@types/estree': 1.0.5 /@types/babel__core@7.20.5: resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -1804,6 +2000,11 @@ packages: dependencies: '@types/ms': 0.7.34 + /@types/estree-jsx@1.0.4: + resolution: {integrity: sha512-5idy3hvI9lAMqsyilBM+N+boaCf1MgoefbDxN6KEO5aK17TOHwFAYT9sjxzeKAiIWRUBgLxmZ9mPcnzZXtTcRQ==} + dependencies: + '@types/estree': 1.0.5 + /@types/estree@1.0.5: resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} @@ -1820,6 +2021,11 @@ packages: '@types/node': 20.11.19 dev: true + /@types/hast@2.3.10: + resolution: {integrity: sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==} + dependencies: + '@types/unist': 2.0.10 + /@types/hast@3.0.4: resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} dependencies: @@ -1848,6 +2054,9 @@ packages: dependencies: '@types/unist': 3.0.2 + /@types/mdx@2.0.11: + resolution: {integrity: sha512-HM5bwOaIQJIQbAYfax35HCKxx7a3KrK3nBtIqJgSOitivTD1y3oW9P3rxY9RkXYPUk7y/AjAohfHKmFpGE79zw==} + /@types/minimist@1.2.5: resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} @@ -1864,7 +2073,6 @@ packages: /@types/node@17.0.45: resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} - dev: false /@types/node@20.11.19: resolution: {integrity: sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==} @@ -1874,11 +2082,13 @@ packages: /@types/normalize-package-data@2.4.4: resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + /@types/parse5@6.0.3: + resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==} + /@types/sax@1.2.7: resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} dependencies: '@types/node': 20.11.19 - dev: false /@types/semver@7.5.7: resolution: {integrity: sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==} @@ -2248,6 +2458,14 @@ packages: transitivePeerDependencies: - rollup + /@vitest/expect@1.2.2: + resolution: {integrity: sha512-3jpcdPAD7LwHUUiT2pZTj2U82I2Tcgg2oVPvKxhn6mDI2On6tfvPQTjAI4628GUGDZrCm4Zna9iQHm5cEexOAg==} + dependencies: + '@vitest/spy': 1.2.2 + '@vitest/utils': 1.2.2 + chai: 4.4.1 + dev: true + /@vitest/expect@1.3.0: resolution: {integrity: sha512-7bWt0vBTZj08B+Ikv70AnLRicohYwFgzNjFqo9SxxqHHxSlUJGSXmCRORhOnRMisiUryKMdvsi1n27Bc6jL9DQ==} dependencies: @@ -2256,6 +2474,14 @@ packages: chai: 4.4.1 dev: true + /@vitest/runner@1.2.2: + resolution: {integrity: sha512-JctG7QZ4LSDXr5CsUweFgcpEvrcxOV1Gft7uHrvkQ+fsAVylmWQvnaAr/HDp3LAH1fztGMQZugIheTWjaGzYIg==} + dependencies: + '@vitest/utils': 1.2.2 + p-limit: 5.0.0 + pathe: 1.1.2 + dev: true + /@vitest/runner@1.3.0: resolution: {integrity: sha512-1Jb15Vo/Oy7mwZ5bXi7zbgszsdIBNjc4IqP8Jpr/8RdBC4nF1CTzIAn2dxYvpF1nGSseeL39lfLQ2uvs5u1Y9A==} dependencies: @@ -2264,6 +2490,14 @@ packages: pathe: 1.1.2 dev: true + /@vitest/snapshot@1.2.2: + resolution: {integrity: sha512-SmGY4saEw1+bwE1th6S/cZmPxz/Q4JWsl7LvbQIky2tKE35US4gd0Mjzqfr84/4OD0tikGWaWdMja/nWL5NIPA==} + dependencies: + magic-string: 0.30.7 + pathe: 1.1.2 + pretty-format: 29.7.0 + dev: true + /@vitest/snapshot@1.3.0: resolution: {integrity: sha512-swmktcviVVPYx9U4SEQXLV6AEY51Y6bZ14jA2yo6TgMxQ3h+ZYiO0YhAHGJNp0ohCFbPAis1R9kK0cvN6lDPQA==} dependencies: @@ -2272,6 +2506,12 @@ packages: pretty-format: 29.7.0 dev: true + /@vitest/spy@1.2.2: + resolution: {integrity: sha512-k9Gcahssw8d7X3pSLq3e3XEu/0L78mUkCjivUqCQeXJm9clfXR/Td8+AP+VC1O6fKPIDLcHDTAmBOINVuv6+7g==} + dependencies: + tinyspy: 2.2.1 + dev: true + /@vitest/spy@1.3.0: resolution: {integrity: sha512-AkCU0ThZunMvblDpPKgjIi025UxR8V7MZ/g/EwmAGpjIujLVV2X6rGYGmxE2D4FJbAy0/ijdROHMWa2M/6JVMw==} dependencies: @@ -2293,6 +2533,15 @@ packages: vitest: 1.3.0(@vitest/ui@1.3.0) dev: true + /@vitest/utils@1.2.2: + resolution: {integrity: sha512-WKITBHLsBHlpjnDQahr+XK6RE7MiAsgrIkr0pGhQ9ygoxBfUeG0lUG5iLlzqjmKSlBv3+j5EGsriBzh+C3Tq9g==} + dependencies: + diff-sequences: 29.6.3 + estree-walker: 3.0.3 + loupe: 2.3.7 + pretty-format: 29.7.0 + dev: true + /@vitest/utils@1.3.0: resolution: {integrity: sha512-/LibEY/fkaXQufi4GDlQZhikQsPO2entBKtfuyIpr1jV4DpaeasqkeHjhdOhU24vSHshcSuEyVlWdzvv2XmYCw==} dependencies: @@ -2380,7 +2629,6 @@ packages: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: acorn: 8.11.3 - dev: true /acorn-walk@8.3.2: resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} @@ -2452,7 +2700,6 @@ packages: /arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} - dev: false /argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -2558,6 +2805,10 @@ packages: resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} dev: true + /astring@1.8.6: + resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==} + hasBin: true + /astro-eslint-parser@0.16.3: resolution: {integrity: sha512-CGaBseNtunAV2DCpwBXqTKq8+9Tw65XZetMaC0FsMoZuLj0gxNIkbCf2QyKYScVrNOU7/ayfNdVw8ZCSHBiqCg==} engines: {node: ^14.18.0 || >=16.0.0} @@ -2575,6 +2826,15 @@ packages: - supports-color dev: true + /astro-expressive-code@0.32.4(astro@4.4.0): + resolution: {integrity: sha512-/Kq8wLMz0X2gbLWGmPryqEdFV/om/GROsoLtPFqLrLCRD5CpwxXAW185BIGZKf4iYsyJim1vvcpQm5Y9hV5B1g==} + peerDependencies: + astro: ^3.3.0 || ^4.0.0-beta + dependencies: + astro: 4.4.0(typescript@5.3.3) + hast-util-to-html: 8.0.4 + remark-expressive-code: 0.32.4 + /astro-font@0.0.77: resolution: {integrity: sha512-dh5TX2uxwqdFq15DF9cbRZgEdE9o8q522MP6xZYs+rnd3dexfDsIJMeEIDNVO7rkRxwJ7sphhCqTmdWvUJaiDg==} dev: false @@ -2906,7 +3166,6 @@ packages: /b4a@1.6.6: resolution: {integrity: sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==} requiresBuild: true - optional: true /bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} @@ -2952,6 +3211,16 @@ packages: /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + /bcp-47-match@2.0.3: + resolution: {integrity: sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==} + + /bcp-47@2.1.0: + resolution: {integrity: sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==} + dependencies: + is-alphabetical: 2.0.1 + is-alphanumerical: 2.0.1 + is-decimal: 2.0.1 + /better-path-resolve@1.0.0: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} @@ -2969,7 +3238,6 @@ packages: buffer: 5.7.1 inherits: 2.0.4 readable-stream: 3.6.2 - optional: true /bl@5.1.0: resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} @@ -2978,6 +3246,9 @@ packages: inherits: 2.0.4 readable-stream: 3.6.2 + /boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + /boxen@7.1.1: resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==} engines: {node: '>=14.16'} @@ -3030,7 +3301,6 @@ packages: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 - optional: true /buffer@6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} @@ -3147,6 +3417,9 @@ packages: /character-entities@2.0.2: resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + /character-reference-invalid@2.0.1: + resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + /chardet@0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} @@ -3173,7 +3446,6 @@ packages: /chownr@1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} requiresBuild: true - optional: true /ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} @@ -3220,6 +3492,9 @@ packages: resolution: {integrity: sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==} engines: {node: '>=6'} + /collapse-white-space@2.1.0: + resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==} + /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -3243,7 +3518,6 @@ packages: dependencies: color-name: 1.1.4 simple-swizzle: 0.2.2 - optional: true /color@4.2.3: resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} @@ -3252,7 +3526,6 @@ packages: dependencies: color-convert: 2.0.1 color-string: 1.9.1 - optional: true /colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} @@ -3326,6 +3599,9 @@ packages: engines: {node: '>=4'} dev: false + /css-selector-parser@3.0.4: + resolution: {integrity: sha512-pnmS1dbKsz6KA4EW4BznyPL2xxkNDRg62hcD0v8g6DEw2W7hxOln5M953jsp9hmw5Dg57S6o/A8GOn37mbAgcQ==} + /css-to-react-native@3.2.0: resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==} dependencies: @@ -3432,7 +3708,6 @@ packages: /deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} - requiresBuild: true /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -3482,7 +3757,6 @@ packages: resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} engines: {node: '>=8'} requiresBuild: true - optional: true /deterministic-object-hash@2.0.2: resolution: {integrity: sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==} @@ -3517,6 +3791,10 @@ packages: dependencies: path-type: 4.0.0 + /direction@2.0.1: + resolution: {integrity: sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==} + hasBin: true + /dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} @@ -3567,7 +3845,6 @@ packages: requiresBuild: true dependencies: once: 1.4.0 - optional: true /enhanced-resolve@5.15.0: resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==} @@ -4002,6 +4279,35 @@ packages: engines: {node: '>=4.0'} dev: true + /estree-util-attach-comments@3.0.0: + resolution: {integrity: sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==} + dependencies: + '@types/estree': 1.0.5 + + /estree-util-build-jsx@3.0.1: + resolution: {integrity: sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==} + dependencies: + '@types/estree-jsx': 1.0.4 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + estree-walker: 3.0.3 + + /estree-util-is-identifier-name@3.0.0: + resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} + + /estree-util-to-js@2.0.0: + resolution: {integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==} + dependencies: + '@types/estree-jsx': 1.0.4 + astring: 1.8.6 + source-map: 0.7.4 + + /estree-util-visit@2.0.0: + resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==} + dependencies: + '@types/estree-jsx': 1.0.4 + '@types/unist': 3.0.2 + /estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} @@ -4050,7 +4356,14 @@ packages: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} requiresBuild: true - optional: true + + /expressive-code@0.32.4: + resolution: {integrity: sha512-r+yUP2JV181tVR2EyYked7lT2W8bvL9o7xpdKU6q60FMU7Wh/DbGtH0jg+WmDxKK1C57iXF9chbBv+BsDPlUEQ==} + dependencies: + '@expressive-code/core': 0.32.4 + '@expressive-code/plugin-frames': 0.32.4 + '@expressive-code/plugin-shiki': 0.32.4 + '@expressive-code/plugin-text-markers': 0.32.4 /extend-shallow@2.0.1: resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} @@ -4079,7 +4392,6 @@ packages: /fast-fifo@1.3.2: resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} requiresBuild: true - optional: true /fast-glob@3.3.2: resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} @@ -4199,7 +4511,6 @@ packages: /fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} requiresBuild: true - optional: true /fs-extra@11.2.0: resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} @@ -4303,7 +4614,6 @@ packages: /github-from-package@0.0.0: resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} requiresBuild: true - optional: true /github-slugger@2.0.0: resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} @@ -4475,6 +4785,17 @@ packages: vfile: 6.0.1 vfile-message: 4.0.2 + /hast-util-from-parse5@7.1.2: + resolution: {integrity: sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==} + dependencies: + '@types/hast': 2.3.10 + '@types/unist': 2.0.10 + hastscript: 7.2.0 + property-information: 6.4.1 + vfile: 5.3.7 + vfile-location: 4.1.0 + web-namespaces: 2.0.1 + /hast-util-from-parse5@8.0.1: resolution: {integrity: sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==} dependencies: @@ -4487,11 +4808,36 @@ packages: vfile-location: 5.0.2 web-namespaces: 2.0.1 + /hast-util-has-property@3.0.0: + resolution: {integrity: sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==} + dependencies: + '@types/hast': 3.0.4 + + /hast-util-parse-selector@3.1.1: + resolution: {integrity: sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==} + dependencies: + '@types/hast': 2.3.10 + /hast-util-parse-selector@4.0.0: resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} dependencies: '@types/hast': 3.0.4 + /hast-util-raw@7.2.3: + resolution: {integrity: sha512-RujVQfVsOrxzPOPSzZFiwofMArbQke6DJjnFfceiEbFh7S05CbPt0cYN+A5YeD3pso0JQk6O1aHBnx9+Pm2uqg==} + dependencies: + '@types/hast': 2.3.10 + '@types/parse5': 6.0.3 + hast-util-from-parse5: 7.1.2 + hast-util-to-parse5: 7.1.0 + html-void-elements: 2.0.1 + parse5: 6.0.1 + unist-util-position: 4.0.4 + unist-util-visit: 4.1.2 + vfile: 5.3.7 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + /hast-util-raw@9.0.2: resolution: {integrity: sha512-PldBy71wO9Uq1kyaMch9AHIghtQvIwxBUkv823pKmkTM3oV1JxtsTNYdevMxvUHqcnOAuO65JKU2+0NOxc2ksA==} dependencies: @@ -4509,6 +4855,63 @@ packages: web-namespaces: 2.0.1 zwitch: 2.0.4 + /hast-util-select@6.0.2: + resolution: {integrity: sha512-hT/SD/d/Meu+iobvgkffo1QecV8WeKWxwsNMzcTJsKw1cKTQKSR/7ArJeURLNJF9HDjp9nVoORyNNJxrvBye8Q==} + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.2 + bcp-47-match: 2.0.3 + comma-separated-tokens: 2.0.3 + css-selector-parser: 3.0.4 + devlop: 1.1.0 + direction: 2.0.1 + hast-util-has-property: 3.0.0 + hast-util-to-string: 3.0.0 + hast-util-whitespace: 3.0.0 + not: 0.1.0 + nth-check: 2.1.1 + property-information: 6.4.1 + space-separated-tokens: 2.0.2 + unist-util-visit: 5.0.0 + zwitch: 2.0.4 + + /hast-util-to-estree@3.1.0: + resolution: {integrity: sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw==} + dependencies: + '@types/estree': 1.0.5 + '@types/estree-jsx': 1.0.4 + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + estree-util-attach-comments: 3.0.0 + estree-util-is-identifier-name: 3.0.0 + hast-util-whitespace: 3.0.0 + mdast-util-mdx-expression: 2.0.0 + mdast-util-mdx-jsx: 3.1.0 + mdast-util-mdxjs-esm: 2.0.1 + property-information: 6.4.1 + space-separated-tokens: 2.0.2 + style-to-object: 0.4.4 + unist-util-position: 5.0.0 + zwitch: 2.0.4 + transitivePeerDependencies: + - supports-color + + /hast-util-to-html@8.0.4: + resolution: {integrity: sha512-4tpQTUOr9BMjtYyNlt0P50mH7xj0Ks2xpo8M943Vykljf99HW6EzulIoJP1N3eKOSScEHzyzi9dm7/cn0RfGwA==} + dependencies: + '@types/hast': 2.3.10 + '@types/unist': 2.0.10 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-raw: 7.2.3 + hast-util-whitespace: 2.0.1 + html-void-elements: 2.0.1 + property-information: 6.4.1 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.3 + zwitch: 2.0.4 + /hast-util-to-html@9.0.0: resolution: {integrity: sha512-IVGhNgg7vANuUA2XKrT6sOIIPgaYZnmLx3l/CCOAK0PtgfoHrZwX7jCSYyFxHTrGmC6S9q8aQQekjp4JPZF+cw==} dependencies: @@ -4525,6 +4928,37 @@ packages: stringify-entities: 4.0.3 zwitch: 2.0.4 + /hast-util-to-jsx-runtime@2.3.0: + resolution: {integrity: sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==} + dependencies: + '@types/estree': 1.0.5 + '@types/hast': 3.0.4 + '@types/unist': 3.0.2 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + hast-util-whitespace: 3.0.0 + mdast-util-mdx-expression: 2.0.0 + mdast-util-mdx-jsx: 3.1.0 + mdast-util-mdxjs-esm: 2.0.1 + property-information: 6.4.1 + space-separated-tokens: 2.0.2 + style-to-object: 1.0.5 + unist-util-position: 5.0.0 + vfile-message: 4.0.2 + transitivePeerDependencies: + - supports-color + + /hast-util-to-parse5@7.1.0: + resolution: {integrity: sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==} + dependencies: + '@types/hast': 2.3.10 + comma-separated-tokens: 2.0.3 + property-information: 6.4.1 + space-separated-tokens: 2.0.2 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + /hast-util-to-parse5@8.0.0: resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==} dependencies: @@ -4536,11 +4970,28 @@ packages: web-namespaces: 2.0.1 zwitch: 2.0.4 + /hast-util-to-string@3.0.0: + resolution: {integrity: sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==} + dependencies: + '@types/hast': 3.0.4 + + /hast-util-whitespace@2.0.1: + resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==} + /hast-util-whitespace@3.0.0: resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} dependencies: '@types/hast': 3.0.4 + /hastscript@7.2.0: + resolution: {integrity: sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==} + dependencies: + '@types/hast': 2.3.10 + comma-separated-tokens: 2.0.3 + hast-util-parse-selector: 3.1.1 + property-information: 6.4.1 + space-separated-tokens: 2.0.2 + /hastscript@8.0.0: resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==} dependencies: @@ -4561,6 +5012,9 @@ packages: /html-escaper@3.0.3: resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==} + /html-void-elements@2.0.1: + resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==} + /html-void-elements@3.0.0: resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} @@ -4635,6 +5089,12 @@ packages: /ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + /inline-style-parser@0.1.1: + resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} + + /inline-style-parser@0.2.2: + resolution: {integrity: sha512-EcKzdTHVe8wFVOGEYXiW9WmJXPjqi1T+234YpJr98RiFYKHV3cdy1+3mkTE+KHTHxFFLH51SfaGOoUdW+v7ViQ==} + /internal-slot@1.0.7: resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} engines: {node: '>= 0.4'} @@ -4643,6 +5103,15 @@ packages: hasown: 2.0.1 side-channel: 1.0.5 + /is-alphabetical@2.0.1: + resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} + + /is-alphanumerical@2.0.1: + resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + dependencies: + is-alphabetical: 2.0.1 + is-decimal: 2.0.1 + /is-array-buffer@3.0.4: resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} engines: {node: '>= 0.4'} @@ -4656,7 +5125,6 @@ packages: /is-arrayish@0.3.2: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} requiresBuild: true - optional: true /is-async-function@2.0.0: resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} @@ -4702,6 +5170,9 @@ packages: dependencies: has-tostringtag: 1.0.2 + /is-decimal@2.0.1: + resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + /is-docker@3.0.0: resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -4738,6 +5209,9 @@ packages: dependencies: is-extglob: 2.1.1 + /is-hexadecimal@2.0.1: + resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + /is-inside-container@1.0.0: resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} engines: {node: '>=14.16'} @@ -4780,6 +5254,11 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} + /is-reference@3.0.2: + resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} + dependencies: + '@types/estree': 1.0.5 + /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -4889,7 +5368,6 @@ packages: /jose@5.2.2: resolution: {integrity: sha512-/WByRr4jDcsKlvMd1dRJnPfS1GVO3WuKyaurJ/vvXcOaUQO8rnNObCQMlv/5uCceVQIq5Q4WLF44ohsdiTohdg==} - dev: false /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -5129,6 +5607,10 @@ packages: resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} engines: {node: '>=8'} + /markdown-extensions@2.0.0: + resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==} + engines: {node: '>=16'} + /markdown-table@3.0.3: resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} @@ -5139,6 +5621,20 @@ packages: '@types/unist': 3.0.2 unist-util-visit: 5.0.0 + /mdast-util-directive@3.0.0: + resolution: {integrity: sha512-JUpYOqKI4mM3sZcNxmF/ox04XYFFkNwr0CFlrQIkCwbvH0xzMCqkMqAde9wRd80VAhaUrwFwKm2nxretdT1h7Q==} + dependencies: + '@types/mdast': 4.0.3 + '@types/unist': 3.0.2 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + parse-entities: 4.0.1 + stringify-entities: 4.0.3 + unist-util-visit-parents: 6.0.1 + transitivePeerDependencies: + - supports-color + /mdast-util-find-and-replace@3.0.1: resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} dependencies: @@ -5228,6 +5724,60 @@ packages: transitivePeerDependencies: - supports-color + /mdast-util-mdx-expression@2.0.0: + resolution: {integrity: sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==} + dependencies: + '@types/estree-jsx': 1.0.4 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.3 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + + /mdast-util-mdx-jsx@3.1.0: + resolution: {integrity: sha512-A8AJHlR7/wPQ3+Jre1+1rq040fX9A4Q1jG8JxmSNp/PLPHg80A6475wxTp3KzHpApFH6yWxFotHrJQA3dXP6/w==} + dependencies: + '@types/estree-jsx': 1.0.4 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.3 + '@types/unist': 3.0.2 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + parse-entities: 4.0.1 + stringify-entities: 4.0.3 + unist-util-remove-position: 5.0.0 + unist-util-stringify-position: 4.0.0 + vfile-message: 4.0.2 + transitivePeerDependencies: + - supports-color + + /mdast-util-mdx@3.0.0: + resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==} + dependencies: + mdast-util-from-markdown: 2.0.0 + mdast-util-mdx-expression: 2.0.0 + mdast-util-mdx-jsx: 3.1.0 + mdast-util-mdxjs-esm: 2.0.1 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + + /mdast-util-mdxjs-esm@2.0.1: + resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==} + dependencies: + '@types/estree-jsx': 1.0.4 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.3 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + /mdast-util-phrasing@4.1.0: resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} dependencies: @@ -5309,6 +5859,17 @@ packages: micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 + /micromark-extension-directive@3.0.0: + resolution: {integrity: sha512-61OI07qpQrERc+0wEysLHMvoiO3s2R56x5u7glHq2Yqq6EHbH4dW25G9GfDdGCDYqA21KE6DWgNSzxSwHc2hSg==} + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.0 + micromark-factory-whitespace: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + parse-entities: 4.0.1 + /micromark-extension-gfm-autolink-literal@2.0.0: resolution: {integrity: sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg==} dependencies: @@ -5374,6 +5935,62 @@ packages: micromark-util-combine-extensions: 2.0.0 micromark-util-types: 2.0.0 + /micromark-extension-mdx-expression@3.0.0: + resolution: {integrity: sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ==} + dependencies: + '@types/estree': 1.0.5 + devlop: 1.1.0 + micromark-factory-mdx-expression: 2.0.1 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-events-to-acorn: 2.0.2 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + /micromark-extension-mdx-jsx@3.0.0: + resolution: {integrity: sha512-uvhhss8OGuzR4/N17L1JwvmJIpPhAd8oByMawEKx6NVdBCbesjH4t+vjEp3ZXft9DwvlKSD07fCeI44/N0Vf2w==} + dependencies: + '@types/acorn': 4.0.6 + '@types/estree': 1.0.5 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + micromark-factory-mdx-expression: 2.0.1 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + vfile-message: 4.0.2 + + /micromark-extension-mdx-md@2.0.0: + resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==} + dependencies: + micromark-util-types: 2.0.0 + + /micromark-extension-mdxjs-esm@3.0.0: + resolution: {integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==} + dependencies: + '@types/estree': 1.0.5 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-events-to-acorn: 2.0.2 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.2 + + /micromark-extension-mdxjs@3.0.0: + resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==} + dependencies: + acorn: 8.11.3 + acorn-jsx: 5.3.2(acorn@8.11.3) + micromark-extension-mdx-expression: 3.0.0 + micromark-extension-mdx-jsx: 3.0.0 + micromark-extension-mdx-md: 2.0.0 + micromark-extension-mdxjs-esm: 3.0.0 + micromark-util-combine-extensions: 2.0.0 + micromark-util-types: 2.0.0 + /micromark-factory-destination@2.0.0: resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==} dependencies: @@ -5389,6 +6006,18 @@ packages: micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 + /micromark-factory-mdx-expression@2.0.1: + resolution: {integrity: sha512-F0ccWIUHRLRrYp5TC9ZYXmZo+p2AM13ggbsW4T0b5CRKP8KHVRB8t4pwtBgTxtjRmwrK0Irwm7vs2JOZabHZfg==} + dependencies: + '@types/estree': 1.0.5 + devlop: 1.1.0 + micromark-util-character: 2.1.0 + micromark-util-events-to-acorn: 2.0.2 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.2 + /micromark-factory-space@2.0.0: resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==} dependencies: @@ -5451,6 +6080,18 @@ packages: /micromark-util-encode@2.0.0: resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} + /micromark-util-events-to-acorn@2.0.2: + resolution: {integrity: sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA==} + dependencies: + '@types/acorn': 4.0.6 + '@types/estree': 1.0.5 + '@types/unist': 3.0.2 + devlop: 1.1.0 + estree-util-visit: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + vfile-message: 4.0.2 + /micromark-util-html-tag-name@2.0.0: resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==} @@ -5531,7 +6172,6 @@ packages: /mimic-response@3.1.0: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} - requiresBuild: true /mimic-response@4.0.0: resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} @@ -5577,7 +6217,6 @@ packages: /mkdirp-classic@0.5.3: resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} requiresBuild: true - optional: true /mlly@1.5.0: resolution: {integrity: sha512-NPVQvAY1xr1QoVeG0cy8yUYC7FQcOx6evl/RjT1wL5FvzPnzOysoqB/jmx/DhssT2dYa8nxECLAaFI/+gVLhDQ==} @@ -5620,7 +6259,6 @@ packages: /napi-build-utils@1.0.2: resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} requiresBuild: true - optional: true /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -5649,12 +6287,10 @@ packages: requiresBuild: true dependencies: semver: 7.6.0 - optional: true /node-addon-api@6.1.0: resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==} requiresBuild: true - optional: true /node-fetch-native@1.6.2: resolution: {integrity: sha512-69mtXOFZ6hSkYiXAVB5SqaRvrbITC/NPyqv7yuu/qw0nmgPyYbIMYYNIDhNtwPrzk0ptrimrLz/hhjvm4w5Z+w==} @@ -5696,6 +6332,9 @@ packages: engines: {node: '>=14.16'} dev: false + /not@0.1.0: + resolution: {integrity: sha512-5PDmaAsVfnWUgTUbJ3ERwn7u79Z0dYxN9ErxCpVJJqe2RK0PJ3z+iFUxuqjwtlDDegXvtWoxD/3Fzxox7tFGWA==} + /npm-run-path@4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} @@ -5708,6 +6347,11 @@ packages: dependencies: path-key: 4.0.0 + /nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + dependencies: + boolbase: 1.0.0 + /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -5898,6 +6542,16 @@ packages: semver: 7.6.0 dev: false + /pagefind@1.0.4: + resolution: {integrity: sha512-oRIizYe+zSI2Jw4zcMU0ebDZm27751hRFiSOBLwc1OIYMrsZKk+3m8p9EVaOmc6zZdtqwwdilNUNxXvBeHcP9w==} + hasBin: true + optionalDependencies: + '@pagefind/darwin-arm64': 1.0.4 + '@pagefind/darwin-x64': 1.0.4 + '@pagefind/linux-arm64': 1.0.4 + '@pagefind/linux-x64': 1.0.4 + '@pagefind/windows-x64': 1.0.4 + /pako@0.2.9: resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} dev: false @@ -5916,6 +6570,18 @@ packages: hex-rgb: 4.3.0 dev: false + /parse-entities@4.0.1: + resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==} + dependencies: + '@types/unist': 2.0.10 + character-entities: 2.0.2 + character-entities-legacy: 3.0.0 + character-reference-invalid: 2.0.1 + decode-named-character-reference: 1.0.2 + is-alphanumerical: 2.0.1 + is-decimal: 2.0.1 + is-hexadecimal: 2.0.1 + /parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} @@ -5932,6 +6598,9 @@ packages: unist-util-modify-children: 3.1.1 unist-util-visit-children: 2.0.2 + /parse5@6.0.1: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + /parse5@7.1.2: resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} dependencies: @@ -5985,6 +6654,13 @@ packages: /perfect-debounce@1.0.0: resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + /periscopic@3.1.0: + resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} + dependencies: + '@types/estree': 1.0.5 + estree-walker: 3.0.3 + is-reference: 3.0.2 + /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} @@ -6066,7 +6742,6 @@ packages: dependencies: postcss: 8.4.35 postcss-selector-parser: 6.0.15 - dev: false /postcss-selector-parser@6.0.10: resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} @@ -6113,7 +6788,6 @@ packages: simple-get: 4.0.1 tar-fs: 2.1.1 tunnel-agent: 0.6.0 - optional: true /preferred-pm@3.1.2: resolution: {integrity: sha512-nk7dKrcW8hfCZ4H6klWcdRknBOXWzNQByJ0oJyX97BOupsYD+FzLS4hflgEu/uPUEHZCuRfMxzCBsuWd7OzT8Q==} @@ -6193,7 +6867,6 @@ packages: dependencies: end-of-stream: 1.4.4 once: 1.4.0 - optional: true /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} @@ -6206,7 +6879,6 @@ packages: /queue-tick@1.0.1: resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} requiresBuild: true - optional: true /quick-lru@4.0.1: resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} @@ -6351,6 +7023,23 @@ packages: rehype-stringify: 10.0.0 unified: 11.0.4 + /remark-directive@3.0.0: + resolution: {integrity: sha512-l1UyWJ6Eg1VPU7Hm/9tt0zKtReJQNOA4+iDMAxTyZNWnJnFlbS/7zhiel/rogTLQ2vMYwDzSJa4BiVNqGlqIMA==} + dependencies: + '@types/mdast': 4.0.3 + mdast-util-directive: 3.0.0 + micromark-extension-directive: 3.0.0 + unified: 11.0.4 + transitivePeerDependencies: + - supports-color + + /remark-expressive-code@0.32.4: + resolution: {integrity: sha512-khV7fVBpVDOyz9EXU+6MFwLj7BtY3DLVlNMMJYQcfp9ksLMxG/i83rIJbMUZCRof9bDBmFFlrF0VDvqJ0/MNeQ==} + dependencies: + expressive-code: 0.32.4 + hast-util-to-html: 8.0.4 + unist-util-visit: 4.1.2 + /remark-gfm@4.0.0: resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==} dependencies: @@ -6363,6 +7052,14 @@ packages: transitivePeerDependencies: - supports-color + /remark-mdx@3.0.1: + resolution: {integrity: sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==} + dependencies: + mdast-util-mdx: 3.0.0 + micromark-extension-mdxjs: 3.0.0 + transitivePeerDependencies: + - supports-color + /remark-parse@11.0.0: resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} dependencies: @@ -6488,26 +7185,26 @@ packages: glob: 7.2.3 dev: true - /rollup@4.12.0: - resolution: {integrity: sha512-wz66wn4t1OHIJw3+XU7mJJQV/2NAfw5OAk6G6Hoo3zcvz/XOfQ52Vgi+AN4Uxoxi0KBBwk2g8zPrTDA4btSB/Q==} + /rollup@4.11.0: + resolution: {integrity: sha512-2xIbaXDXjf3u2tajvA5xROpib7eegJ9Y/uPlSFhXLNpK9ampCczXAhLEb5yLzJyG3LAdI1NWtNjDXiLyniNdjQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true dependencies: '@types/estree': 1.0.5 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.12.0 - '@rollup/rollup-android-arm64': 4.12.0 - '@rollup/rollup-darwin-arm64': 4.12.0 - '@rollup/rollup-darwin-x64': 4.12.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.12.0 - '@rollup/rollup-linux-arm64-gnu': 4.12.0 - '@rollup/rollup-linux-arm64-musl': 4.12.0 - '@rollup/rollup-linux-riscv64-gnu': 4.12.0 - '@rollup/rollup-linux-x64-gnu': 4.12.0 - '@rollup/rollup-linux-x64-musl': 4.12.0 - '@rollup/rollup-win32-arm64-msvc': 4.12.0 - '@rollup/rollup-win32-ia32-msvc': 4.12.0 - '@rollup/rollup-win32-x64-msvc': 4.12.0 + '@rollup/rollup-android-arm-eabi': 4.11.0 + '@rollup/rollup-android-arm64': 4.11.0 + '@rollup/rollup-darwin-arm64': 4.11.0 + '@rollup/rollup-darwin-x64': 4.11.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.11.0 + '@rollup/rollup-linux-arm64-gnu': 4.11.0 + '@rollup/rollup-linux-arm64-musl': 4.11.0 + '@rollup/rollup-linux-riscv64-gnu': 4.11.0 + '@rollup/rollup-linux-x64-gnu': 4.11.0 + '@rollup/rollup-linux-x64-musl': 4.11.0 + '@rollup/rollup-win32-arm64-msvc': 4.11.0 + '@rollup/rollup-win32-ia32-msvc': 4.11.0 + '@rollup/rollup-win32-x64-msvc': 4.11.0 fsevents: 2.3.3 /run-parallel@1.2.0: @@ -6529,6 +7226,7 @@ packages: /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + requiresBuild: true /safe-regex-test@1.0.3: resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} @@ -6579,7 +7277,6 @@ packages: /sax@1.3.0: resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==} - dev: false /section-matter@1.0.0: resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} @@ -6641,7 +7338,6 @@ packages: simple-get: 4.0.1 tar-fs: 3.0.5 tunnel-agent: 0.6.0 - optional: true /shebang-command@1.2.0: resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} @@ -6666,6 +7362,11 @@ packages: /shikiji-core@0.9.19: resolution: {integrity: sha512-AFJu/vcNT21t0e6YrfadZ+9q86gvPum6iywRyt1OtIPjPFe25RQnYJyxHQPMLKCCWA992TPxmEmbNcOZCAJclw==} + /shikiji@0.8.7: + resolution: {integrity: sha512-j5usxwI0yHkDTHOuhuSJl9+wT5CNYeYO82dJMSJBlJ/NYT5SIebGcPoL6y9QOyH15wGrJC4LOP2nz5k8mUDGRQ==} + dependencies: + hast-util-to-html: 9.0.0 + /shikiji@0.9.19: resolution: {integrity: sha512-Kw2NHWktdcdypCj1GkKpXH4o6Vxz8B8TykPlPuLHOGSV8VkhoCLcFOH4k19K4LXAQYRQmxg+0X/eM+m2sLhAkg==} dependencies: @@ -6694,7 +7395,6 @@ packages: /simple-concat@1.0.1: resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} requiresBuild: true - optional: true /simple-get@4.0.1: resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} @@ -6703,14 +7403,12 @@ packages: decompress-response: 6.0.0 once: 1.4.0 simple-concat: 1.0.1 - optional: true /simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} requiresBuild: true dependencies: is-arrayish: 0.3.2 - optional: true /sirv@2.0.4: resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} @@ -6732,7 +7430,6 @@ packages: '@types/sax': 1.2.7 arg: 5.0.2 sax: 1.3.0 - dev: false /slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} @@ -6754,6 +7451,10 @@ packages: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} + /source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + /space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} @@ -6819,7 +7520,6 @@ packages: queue-tick: 1.0.1 optionalDependencies: bare-events: 2.2.0 - optional: true /string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} @@ -6881,6 +7581,7 @@ packages: /string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + requiresBuild: true dependencies: safe-buffer: 5.2.1 @@ -6927,13 +7628,18 @@ packages: /strip-json-comments@2.0.1: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} - requiresBuild: true /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} dev: true + /strip-literal@1.3.0: + resolution: {integrity: sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==} + dependencies: + acorn: 8.11.3 + dev: true + /strip-literal@2.0.0: resolution: {integrity: sha512-f9vHgsCWBq2ugHAkGMiiYY+AYG0D/cbloKKg0nhaaaSNsujdGIpVXCNsrJpCKr5M0f4aI31mr13UjY6GAuXCKA==} dependencies: @@ -6944,6 +7650,16 @@ packages: resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} dev: false + /style-to-object@0.4.4: + resolution: {integrity: sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==} + dependencies: + inline-style-parser: 0.1.1 + + /style-to-object@1.0.5: + resolution: {integrity: sha512-rDRwHtoDD3UMMrmZ6BzOW0naTjMsVZLIjsGleSKS/0Oz+cgCfAPRspaqJuE8rDzpKha/nEvnM0IF4seEAZUTKQ==} + dependencies: + inline-style-parser: 0.2.2 + /sucrase@3.35.0: resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} engines: {node: '>=16 || 14 >=14.17'} @@ -7031,7 +7747,6 @@ packages: mkdirp-classic: 0.5.3 pump: 3.0.0 tar-stream: 2.2.0 - optional: true /tar-fs@3.0.5: resolution: {integrity: sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg==} @@ -7042,7 +7757,6 @@ packages: optionalDependencies: bare-fs: 2.1.5 bare-path: 2.1.0 - optional: true /tar-stream@2.2.0: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} @@ -7054,7 +7768,6 @@ packages: fs-constants: 1.0.0 inherits: 2.0.4 readable-stream: 3.6.2 - optional: true /tar-stream@3.1.7: resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} @@ -7063,7 +7776,6 @@ packages: b4a: 1.6.6 fast-fifo: 1.3.2 streamx: 2.15.8 - optional: true /term-size@2.2.1: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} @@ -7194,7 +7906,6 @@ packages: requiresBuild: true dependencies: safe-buffer: 5.2.1 - optional: true /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} @@ -7350,11 +8061,34 @@ packages: '@types/unist': 2.0.10 array-iterate: 2.0.1 + /unist-util-position-from-estree@2.0.0: + resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==} + dependencies: + '@types/unist': 3.0.2 + + /unist-util-position@4.0.4: + resolution: {integrity: sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==} + dependencies: + '@types/unist': 2.0.10 + /unist-util-position@5.0.0: resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} dependencies: '@types/unist': 3.0.2 + /unist-util-remove-position@5.0.0: + resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} + dependencies: + '@types/unist': 3.0.2 + unist-util-visit: 5.0.0 + + /unist-util-remove@4.0.0: + resolution: {integrity: sha512-b4gokeGId57UVRX/eVKej5gXqGlc9+trkORhFJpu9raqZkZhU0zm8Doi05+HaiBsMEIJowL+2WtQ5ItjsngPXg==} + dependencies: + '@types/unist': 3.0.2 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + /unist-util-stringify-position@3.0.3: resolution: {integrity: sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==} dependencies: @@ -7475,6 +8209,12 @@ packages: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 + /vfile-location@4.1.0: + resolution: {integrity: sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==} + dependencies: + '@types/unist': 2.0.10 + vfile: 5.3.7 + /vfile-location@5.0.2: resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==} dependencies: @@ -7508,6 +8248,27 @@ packages: unist-util-stringify-position: 4.0.0 vfile-message: 4.0.2 + /vite-node@1.2.2: + resolution: {integrity: sha512-1as4rDTgVWJO3n1uHmUYqq7nsFgINQ9u+mRcXpjeOMJUmviqNKjcZB7UfRZrlM7MjYXMKpuWp5oGkjaFLnjawg==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.3.4 + pathe: 1.1.2 + picocolors: 1.0.0 + vite: 5.1.3(sass@1.71.0) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + /vite-node@1.3.0: resolution: {integrity: sha512-D/oiDVBw75XMnjAXne/4feCkCEwcbr2SU1bjAhCcfI5Bq3VoOHji8/wCPAfUkDIeohJ5nSZ39fNxM3dNZ6OBOA==} engines: {node: ^18.0.0 || >=20.0.0} @@ -7566,6 +8327,58 @@ packages: - supports-color - typescript + /vite-tsconfig-paths@4.3.1(vite@5.1.2): + resolution: {integrity: sha512-cfgJwcGOsIxXOLU/nELPny2/LUD/lcf1IbfyeKTv2bsupVbTH/xpFtdQlBmIP1GEK2CjjLxYhFfB+QODFAx5aw==} + peerDependencies: + vite: '*' + peerDependenciesMeta: + vite: + optional: true + dependencies: + debug: 4.3.4 + globrex: 0.1.2 + tsconfck: 3.0.2(typescript@5.3.3) + vite: 5.1.2 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /vite@5.1.2: + resolution: {integrity: sha512-uwiFebQbTWRIGbCaTEBVAfKqgqKNKMJ2uPXsXeLIZxM8MVMjoS3j0cG8NrPxdDIadaWnPSjrkLWffLSC+uiP3Q==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + esbuild: 0.19.12 + postcss: 8.4.35 + rollup: 4.11.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + /vite@5.1.3(@types/node@20.11.19): resolution: {integrity: sha512-UfmUD36DKkqhi/F75RrxvPpry+9+tTkrXfMNZD+SboZqBCMsxKtO52XeGzzuh7ioz+Eo/SYDBbdb0Z7vgcDJew==} engines: {node: ^18.0.0 || >=20.0.0} @@ -7597,7 +8410,7 @@ packages: '@types/node': 20.11.19 esbuild: 0.19.12 postcss: 8.4.35 - rollup: 4.12.0 + rollup: 4.11.0 optionalDependencies: fsevents: 2.3.3 @@ -7631,7 +8444,7 @@ packages: dependencies: esbuild: 0.19.12 postcss: 8.4.35 - rollup: 4.12.0 + rollup: 4.11.0 sass: 1.71.0 optionalDependencies: fsevents: 2.3.3 @@ -7646,6 +8459,18 @@ packages: dependencies: vite: 5.1.3(@types/node@20.11.19) + /vitest-fetch-mock@0.2.2(vitest@1.2.2): + resolution: {integrity: sha512-XmH6QgTSjCWrqXoPREIdbj40T7i1xnGmAsTAgfckoO75W1IEHKR8hcPCQ7SO16RsdW1t85oUm6pcQRLeBgjVYQ==} + engines: {node: '>=14.14.0'} + peerDependencies: + vitest: '>=0.16.0' + dependencies: + cross-fetch: 3.1.8 + vitest: 1.2.2(@vitest/ui@1.3.0) + transitivePeerDependencies: + - encoding + dev: true + /vitest-fetch-mock@0.2.2(vitest@1.3.0): resolution: {integrity: sha512-XmH6QgTSjCWrqXoPREIdbj40T7i1xnGmAsTAgfckoO75W1IEHKR8hcPCQ7SO16RsdW1t85oUm6pcQRLeBgjVYQ==} engines: {node: '>=14.14.0'} @@ -7653,11 +8478,68 @@ packages: vitest: '>=0.16.0' dependencies: cross-fetch: 3.1.8 - vitest: 1.3.0(@types/node@20.11.19)(@vitest/ui@1.3.0) + vitest: 1.3.0(@vitest/ui@1.3.0) transitivePeerDependencies: - encoding dev: true + /vitest@1.2.2(@vitest/ui@1.3.0): + resolution: {integrity: sha512-d5Ouvrnms3GD9USIK36KG8OZ5bEvKEkITFtnGv56HFaSlbItJuYr7hv2Lkn903+AvRAgSixiamozUVfORUekjw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': ^1.0.0 + '@vitest/ui': ^1.0.0 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@vitest/expect': 1.2.2 + '@vitest/runner': 1.2.2 + '@vitest/snapshot': 1.2.2 + '@vitest/spy': 1.2.2 + '@vitest/ui': 1.3.0(vitest@1.3.0) + '@vitest/utils': 1.2.2 + acorn-walk: 8.3.2 + cac: 6.7.14 + chai: 4.4.1 + debug: 4.3.4 + execa: 8.0.1 + local-pkg: 0.5.0 + magic-string: 0.30.7 + pathe: 1.1.2 + picocolors: 1.0.0 + std-env: 3.7.0 + strip-literal: 1.3.0 + tinybench: 2.6.0 + tinypool: 0.8.2 + vite: 5.1.3(sass@1.71.0) + vite-node: 1.2.2 + why-is-node-running: 2.2.2 + transitivePeerDependencies: + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + /vitest@1.3.0(@types/node@20.11.19)(@vitest/ui@1.3.0): resolution: {integrity: sha512-V9qb276J1jjSx9xb75T2VoYXdO1UKi+qfflY7V7w93jzX7oA/+RtYE6TcifxksxsZvygSSMwu2Uw6di7yqDMwg==} engines: {node: ^18.0.0 || >=20.0.0} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 52a4d051..a2aec9a0 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,4 @@ packages: - "packages/*" - - "playground" \ No newline at end of file + - "playground" + - "starlight-playground" \ No newline at end of file diff --git a/starlight-playground/.gitignore b/starlight-playground/.gitignore new file mode 100644 index 00000000..bffa11f0 --- /dev/null +++ b/starlight-playground/.gitignore @@ -0,0 +1,21 @@ +# build output +dist/ +# generated types +.astro/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store \ No newline at end of file diff --git a/starlight-playground/.vscode/extensions.json b/starlight-playground/.vscode/extensions.json new file mode 100644 index 00000000..8ce5285f --- /dev/null +++ b/starlight-playground/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + "recommendations": ["astro-build.astro-vscode"], + "unwantedRecommendations": [] +} \ No newline at end of file diff --git a/starlight-playground/.vscode/launch.json b/starlight-playground/.vscode/launch.json new file mode 100644 index 00000000..42bfb220 --- /dev/null +++ b/starlight-playground/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "command": "./node_modules/.bin/astro dev", + "name": "Development server", + "request": "launch", + "type": "node-terminal" + } + ] +} \ No newline at end of file diff --git a/starlight-playground/astro.config.mjs b/starlight-playground/astro.config.mjs new file mode 100644 index 00000000..ec11f355 --- /dev/null +++ b/starlight-playground/astro.config.mjs @@ -0,0 +1,29 @@ +import { defineConfig } from 'astro/config'; +import starlight from '@astrojs/starlight'; +import starlightGhostCMS from '@matthiesenxyz/starlight-ghostcms'; + +// https://astro.build/config +export default defineConfig({ + integrations: [ + starlight({ + title: 'My Docs', + plugins: [starlightGhostCMS()], + social: { + github: 'https://github.com/withastro/starlight', + }, + sidebar: [ + { + label: 'Guides', + items: [ + // Each item here is one entry in the navigation menu. + { label: 'Example Guide', link: '/guides/example/' }, + ], + }, + { + label: 'Reference', + autogenerate: { directory: 'reference' }, + }, + ], + }), + ], +}); \ No newline at end of file diff --git a/starlight-playground/package.json b/starlight-playground/package.json new file mode 100644 index 00000000..1dcc513f --- /dev/null +++ b/starlight-playground/package.json @@ -0,0 +1,22 @@ +{ + "name": "starlight-playground", + "type": "module", + "version": "0.0.1", + "private": true, + "sideEffects": false, + "scripts": { + "dev": "astro dev", + "start": "astro dev", + "build": "astro build", + "preview": "astro preview", + "astro": "astro" + }, + "devDependencies": { + }, + "dependencies": { + "@astrojs/starlight": "^0.19.0", + "@matthiesenxyz/starlight-ghostcms": "workspace:*", + "astro": "^4.4.0", + "sharp": "^0.32.5" + } + } \ No newline at end of file diff --git a/starlight-playground/public/favicon.svg b/starlight-playground/public/favicon.svg new file mode 100644 index 00000000..cba5ac14 --- /dev/null +++ b/starlight-playground/public/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/starlight-playground/src/assets/houston.webp b/starlight-playground/src/assets/houston.webp new file mode 100644 index 00000000..930c1649 Binary files /dev/null and b/starlight-playground/src/assets/houston.webp differ diff --git a/starlight-playground/src/content/config.ts b/starlight-playground/src/content/config.ts new file mode 100644 index 00000000..4c3d67cb --- /dev/null +++ b/starlight-playground/src/content/config.ts @@ -0,0 +1,6 @@ +import { defineCollection } from 'astro:content'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ schema: docsSchema() }), +}; \ No newline at end of file diff --git a/starlight-playground/src/content/docs/guides/example.md b/starlight-playground/src/content/docs/guides/example.md new file mode 100644 index 00000000..2caa37b8 --- /dev/null +++ b/starlight-playground/src/content/docs/guides/example.md @@ -0,0 +1,11 @@ +--- +title: Example Guide +description: A guide in my new Starlight docs site. +--- + +Guides lead a user through a specific task they want to accomplish, often with a sequence of steps. +Writing a good guide requires thinking about what your users are trying to do. + +## Further reading + +- Read [about how-to guides](https://diataxis.fr/how-to-guides/) in the Diátaxis framework \ No newline at end of file diff --git a/starlight-playground/src/content/docs/index.mdx b/starlight-playground/src/content/docs/index.mdx new file mode 100644 index 00000000..5957aa43 --- /dev/null +++ b/starlight-playground/src/content/docs/index.mdx @@ -0,0 +1,36 @@ +--- +title: Welcome to Starlight +description: Get started building your docs site with Starlight. +template: splash +hero: + tagline: Congrats on setting up a new Starlight project! + image: + file: ../../assets/houston.webp + actions: + - text: Example Guide + link: /guides/example/ + icon: right-arrow + variant: primary + - text: Read the Starlight docs + link: https://starlight.astro.build + icon: external +--- + +import { Card, CardGrid } from '@astrojs/starlight/components'; + +## Next steps + + + + Edit `src/content/docs/index.mdx` to see this page change. + + + Add Markdown or MDX files to `src/content/docs` to create new pages. + + + Edit your `sidebar` and other config in `astro.config.mjs`. + + + Learn more in [the Starlight Docs](https://starlight.astro.build/). + + \ No newline at end of file diff --git a/starlight-playground/src/content/docs/reference/example.md b/starlight-playground/src/content/docs/reference/example.md new file mode 100644 index 00000000..98d32d75 --- /dev/null +++ b/starlight-playground/src/content/docs/reference/example.md @@ -0,0 +1,11 @@ +--- +title: Example Reference +description: A reference page in my new Starlight docs site. +--- + +Reference pages are ideal for outlining how things work in terse and clear terms. +Less concerned with telling a story or addressing a specific use case, they should give a comprehensive outline of what you're documenting. + +## Further reading + +- Read [about reference](https://diataxis.fr/reference/) in the Diátaxis framework \ No newline at end of file diff --git a/starlight-playground/src/env.d.ts b/starlight-playground/src/env.d.ts new file mode 100644 index 00000000..c13bd73c --- /dev/null +++ b/starlight-playground/src/env.d.ts @@ -0,0 +1,2 @@ +/// +/// \ No newline at end of file diff --git a/starlight-playground/tsconfig.json b/starlight-playground/tsconfig.json new file mode 100644 index 00000000..c02b48a3 --- /dev/null +++ b/starlight-playground/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "astro/tsconfigs/strict" +} \ No newline at end of file