diff --git a/apps/nextjs/next.config.mjs b/apps/nextjs/next.config.mjs index 3b0aef7..c6c810b 100644 --- a/apps/nextjs/next.config.mjs +++ b/apps/nextjs/next.config.mjs @@ -7,7 +7,7 @@ const config = { reactStrictMode: true, /** Enables hot reloading for local packages without a build step */ - transpilePackages: [], + transpilePackages: ["@acme/markdoc-base", "@acme/ui"], /** We already do linting and typechecking as separate tasks in CI */ eslint: { ignoreDuringBuilds: true }, typescript: { ignoreBuildErrors: true }, diff --git a/apps/nextjs/src/app/layout.tsx b/apps/nextjs/src/app/layout.tsx index 15234c3..41c01bb 100644 --- a/apps/nextjs/src/app/layout.tsx +++ b/apps/nextjs/src/app/layout.tsx @@ -8,26 +8,9 @@ const fontSans = Inter({ variable: "--font-sans", }); -/** - * Since we're passing `headers()` to the `TRPCReactProvider` we need to - * make the entire app dynamic. You can move the `TRPCReactProvider` further - * down the tree (e.g. /dashboard and onwards) to make part of the app statically rendered. - */ - export const metadata: Metadata = { title: "Create T3 Turbo", description: "Simple monorepo with shared backend for web & mobile apps", - openGraph: { - title: "Create T3 Turbo", - description: "Simple monorepo with shared backend for web & mobile apps", - url: "https://create-t3-turbo.vercel.app", - siteName: "Create T3 Turbo", - }, - twitter: { - card: "summary_large_image", - site: "@jullerino", - creator: "@jullerino", - }, }; export default function Layout({ children }: { children: React.ReactNode }) { diff --git a/apps/nextjs/src/app/page.tsx b/apps/nextjs/src/app/page.tsx index da3abe2..5db98ff 100644 --- a/apps/nextjs/src/app/page.tsx +++ b/apps/nextjs/src/app/page.tsx @@ -1,7 +1,19 @@ -export default function HomePage() { +import path from "path"; +import React from "react"; +import { notFound } from "next/navigation"; + +import { components, Markdoc, parseContent } from "@acme/markdoc-base"; + +export default async function HomePage() { + const filePath = path.join(path.resolve(), "./src/content/test.md"); + + const pageContent = await parseContent(filePath); + + if (!pageContent) notFound(); + return (
- Hello World + {Markdoc.renderers.react(pageContent.content, React, components)}
- ) + ); } diff --git a/apps/nextjs/src/content/test.md b/apps/nextjs/src/content/test.md new file mode 100644 index 0000000..dc45e24 --- /dev/null +++ b/apps/nextjs/src/content/test.md @@ -0,0 +1,47 @@ +--- +title: Hello World +description: A short summary about this awesome page +--- + +Corporis cognosces Peleus tibi + +## Spes terra illis cum silvas gaudere videtque + +Lorem markdownum tu peto? Fessa peteretur tyranni nota aquaticus iussere, io +vivere, conditur meum ut lassaque. Adsiduo perveni Atrides postquam alte illa et +spernenda, late ferarum, modo. Reticere munus sui vertit est nescius adhuc +insuperabile nidos! Tumidam *hospes* ferrum a pulsat inferius: aut es marmoris! + +> Pectore ursaeque, fuit prolisque erit amnesque: nam datis viro caecaque +> resupino notavi. Quoque dolentius multi, has quicquam magni, ruunt omnia +> imagine? Delphice quae illo est cruor adhuc telisque et manu, amor, +> *causamque* te vestes; rerum. + +## Carituraque debet penetrabile alta imagine + +Egerat solent, Iuppiter non rictus, Parnasosque illa; talia. Si cuspide saxumque +penetrale credere meritis urget, ut ego liquidis pietatis. Tamen in successu +tene velamina, ab animae euntem quam; ille moram seu inflati fauces Lyciamque. +Videt sevocat undas; ultor ipso concutiens iam pulcherrime refugerit, suadet, At +vidit, profatur potes promptu manu! + +Cadit **tangit quo** sine valuere nulla, Philemon quoque luctantiaque. [Ante +exsecrantia](http://orant.com/sed.php) alis iam! Fluctusque utinam pennis deum +pocula cum. Tetigit avis aequoreis posses alto Tyriis, voce reor habet solet +postquam *adsuetaque* regnat medium locis. + +## Tanto ortas harenis collaque dant + +Mora dissimulat ac, visa vires sortes inferius **dei quod** frigus, lumina +Samon, mortis. **Parte fluctus** tum, in invitam satis, *nominat retentis +videre* finis tu et mendacia nomen. Huic illic abdita Terram. + +Est verso praedam repetitaque mons esse, mora petenti haec scopulus ille +medioque, ne verumque, ales. Sideraque invidit. Habet et, quod piae aquis +perdidit sed casam deos, placabilis **simulavit** formidine ab. + +Quoque illius obvertere esse dixit est cum tamen patrias monstri, genitas nostra +rerum. Mihi movit Rhodopen dolores refers summo, commonuit vera clamat versa et +uvis **monte summoque rarior**, Venus, Imbreus. Lacer tamen cupit, trans sacras +territaque, custodemque saltem Procne punior. Sparsos debita spes arma asperitas +turis ostendens dixerat! diff --git a/packages/helpers/index.ts b/packages/helpers/index.ts new file mode 100644 index 0000000..6a2d481 --- /dev/null +++ b/packages/helpers/index.ts @@ -0,0 +1 @@ +export { cn } from "./src/cn"; diff --git a/packages/helpers/package.json b/packages/helpers/package.json new file mode 100644 index 0000000..29b9a9f --- /dev/null +++ b/packages/helpers/package.json @@ -0,0 +1,40 @@ +{ + "name": "@acme/helpers", + "private": true, + "version": "0.1.0", + "exports": { + ".": "./index.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/*" + ] + } + }, + "license": "MIT", + "scripts": { + "clean": "rm -rf .turbo node_modules", + "lint": "eslint .", + "format": "prettier --check . --ignore-path ../../.gitignore", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "clsx": "2.0.0", + "tailwindcss": "3.3.6", + "tailwind-merge": "2.1.0" + }, + "devDependencies": { + "@acme/eslint-config": "workspace:0.2.0", + "@acme/prettier-config": "workspace:0.1.0", + "@acme/tsconfig": "workspace:0.1.0", + "eslint": "8.55.0", + "typescript": "5.3.3" + }, + "eslintConfig": { + "extends": [ + "@acme/eslint-config/base" + ] + }, + "prettier": "@acme/prettier-config" +} diff --git a/packages/ui/src/lib/utils.ts b/packages/helpers/src/cn.ts similarity index 100% rename from packages/ui/src/lib/utils.ts rename to packages/helpers/src/cn.ts diff --git a/packages/helpers/tsconfig.json b/packages/helpers/tsconfig.json new file mode 100644 index 0000000..7a26a27 --- /dev/null +++ b/packages/helpers/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "@acme/tsconfig/base.json", + "compilerOptions": { + "tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json" + }, + "include": ["*.ts", "src"], + "exclude": ["node_modules"] +} diff --git a/packages/markdoc-base/index.ts b/packages/markdoc-base/index.ts index 543c554..7226c60 100644 --- a/packages/markdoc-base/index.ts +++ b/packages/markdoc-base/index.ts @@ -2,6 +2,6 @@ import Markdoc from "@markdoc/markdoc"; import { components, config } from "./src"; - - export { Markdoc, config, components }; + +export * from "./src/helpers"; diff --git a/packages/markdoc-base/package.json b/packages/markdoc-base/package.json index e380d3e..966ac64 100644 --- a/packages/markdoc-base/package.json +++ b/packages/markdoc-base/package.json @@ -20,7 +20,12 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@markdoc/markdoc": "0.4.0" + "@markdoc/markdoc": "0.4.0", + "zod": "3.22.4", + "zod-matter": "0.1.1", + "string-strip-html": "13.4.3", + "@acme/markdoc-heading": "workspace:0.1.0", + "@acme/helpers": "workspace:0.1.0" }, "devDependencies": { "@acme/eslint-config": "workspace:0.2.0", diff --git a/packages/markdoc-base/src/frontmatter.ts b/packages/markdoc-base/src/frontmatter.ts new file mode 100644 index 0000000..e4033af --- /dev/null +++ b/packages/markdoc-base/src/frontmatter.ts @@ -0,0 +1,13 @@ +import { z } from "zod"; +import { parse as parseFrontmatter } from "zod-matter"; + +export function getFrontmatter(fileContent: string) { + const frontmatterProps = z.object({ + title: z.string(), + description: z.string().optional(), + }); + + const { data: frontmatter } = parseFrontmatter(fileContent, frontmatterProps); + + return frontmatter; +} diff --git a/packages/markdoc-base/src/helpers.ts b/packages/markdoc-base/src/helpers.ts new file mode 100644 index 0000000..8f66336 --- /dev/null +++ b/packages/markdoc-base/src/helpers.ts @@ -0,0 +1,92 @@ +import type { PathLike } from "node:fs"; +import fs from "node:fs/promises"; +import type { Node as MarkdocNode, Tag } from "@markdoc/markdoc"; +import Markdoc from "@markdoc/markdoc"; +import { stripHtml } from "string-strip-html"; + +import { getFrontmatter } from "./frontmatter"; +import { config } from "./index"; + +interface HeadingNode extends MarkdocNode { + type: "heading"; + attributes: { + level: 1 | 2 | 3 | 4 | 5 | 6; + id: string; + [key: string]: unknown; + }; +} + +export interface TableOfContents { + id: string; + title: string; + level: number; + children?: TableOfContents[]; +} + +export async function getFileContent(filePath: PathLike | fs.FileHandle) { + try { + return await fs.readFile(filePath, { encoding: "utf-8" }); + } catch (e) { + return null; + } +} + +export async function parseContent(filePath: PathLike | fs.FileHandle) { + const fileContent = await getFileContent(filePath); + + if (!fileContent) return; + + const frontmatter = getFrontmatter(fileContent); + + const ast = Markdoc.parse(fileContent); + const content = Markdoc.transform(ast, config); + + // since RenderableTreeNode could be a string + // we use the `Tag` type for content + // otherwise we get some type issues and I have no idea + // how I could solve it + const headings = ((content as Tag).children as Tag[]).filter((ele) => { + return ele.name == "Heading"; + }); + + return { + content, + ...frontmatter, + toc: generateTableOfContents(headings), + }; +} + +export function generateTableOfContents(headings: Tag[]) { + const sections: TableOfContents[] = []; + + for (const heading of headings) { + const attributes = (heading as unknown as HeadingNode).attributes; + + if (attributes.level == 2 || attributes.level == 3) { + const strippedTitle = stripHtml(Markdoc.renderers.html(heading)).result; + + if (attributes.level == 3) { + if (!sections[sections.length - 1]) { + throw new Error( + `Cannot add "h3" to table of contents without a preceding "h2" - Heading Title: ${strippedTitle}`, + ); + } + + sections[sections.length - 1]?.children!.push({ + id: attributes.id, + level: attributes.level, + title: strippedTitle, + }); + } else { + sections.push({ + id: attributes.id, + level: attributes.level, + title: strippedTitle, + children: [], + }); + } + } + } + + return sections; +} diff --git a/packages/markdoc-base/src/index.ts b/packages/markdoc-base/src/index.ts index de828da..29531ba 100644 --- a/packages/markdoc-base/src/index.ts +++ b/packages/markdoc-base/src/index.ts @@ -1,152 +1,139 @@ import type { Config } from "@markdoc/markdoc"; +import { Heading, config as headingConfig } from "@acme/markdoc-heading"; + const config: Config = { - // nodes: { - // paragraph: { - // render: "Paragraph", - // }, - // link: { - // ...markdocNodes.link, - // render: "CustomLink", - // }, - // heading: { - // render: "Heading", - // attributes: { - // id: { type: String }, - // level: { type: Number, required: true }, - // }, - // transform(node, config) { - // const attributes = node.transformAttributes(config) - // const children = node.transformChildren(config) - // const renderedContent = Markdoc.renderers.html(children) - // if (!attributes.id) { - // attributes.id = slugify(renderedContent) - // } - // return new Tag(this.render, attributes, children) - // }, - // }, - // blockquote: { - // render: "Blockquote", - // }, - // list: { - // render: "List", - // attributes: { - // ordered: { type: Boolean, required: false }, - // }, - // }, - // inline: {}, - // table: { render: "Table" }, - // thead: { render: "TableHeader" }, - // th: { render: "TableHead" }, - // tr: { render: "TableRow" }, - // tbody: { render: "TableBody" }, - // td: { render: "TableCell" }, - // fence: { - // render: "Code", - // attributes: { - // content: { - // type: String, - // }, - // language: { - // type: String, - // }, - // id: { - // type: String, - // required: false, - // }, - // lineNumbers: { - // type: Boolean, - // required: false, - // default: true, - // }, - // fileName: { - // type: String, - // required: false, - // }, - // }, - // }, - // }, - // tags: { - // callout: { - // render: "Callout", - // attributes: { - // title: { - // type: String, - // default: "default title", - // }, - // type: { - // type: String, - // default: "default", - // }, - // }, - // }, - // orderedlist: { - // render: "List", - // attributes: { - // ordered: { type: Boolean, required: false, default: true }, - // type: { type: String, required: false }, - // start: { type: Number, required: false }, - // }, - // transform(node, config) { - // const attributes = node.transformAttributes(config) - // const children = node.transformChildren(config) - // const elements = children[0] as any - // if (children.length && elements?.name === "List") { - // elements.attributes = attributes - // } - // return elements - // }, - // }, - // tabs: { - // render: "Tabs", - // children: ["Tab"], - // transform(node, config) { - // const labels = node - // .transformChildren(config) - // .filter((child: any) => child && child.name === "Tab") - // .map((tab: any) => - // typeof tab === "object" ? tab?.attributes?.label : null, - // ) - // const defaultValue = ( - // node - // .transformChildren(config) - // .filter((child: any) => child && child.name === "Tab") - // .find((tab: any) => tab?.attributes?.default == true) as any - // )?.attributes?.label - // return new Tag( - // this.render, - // { labels, defaultValue }, - // node.transformChildren(config), - // ) - // }, - // }, - // tab: { - // render: "Tab", - // attributes: { - // label: { type: String, required: true }, - // default: { type: Boolean, required: false }, - // }, - // }, - // accordion: { - // render: "Accordion", - // children: ["AccordionItem"], - // attributes: { - // type: { type: String }, - // collapsible: { type: Boolean, required: false, default: false }, - // }, - // }, - // accordionitem: { - // render: "AccordionItem", - // attributes: { - // title: { type: String, required: true }, - // }, - // }, - // }, + nodes: { + // paragraph: { + // render: "Paragraph", + // }, + // link: { + // ...markdocNodes.link, + // render: "CustomLink", + // }, + heading: headingConfig, + // blockquote: { + // render: "Blockquote", + // }, + // list: { + // render: "List", + // attributes: { + // ordered: { type: Boolean, required: false }, + // }, + // }, + // inline: {}, + // table: { render: "Table" }, + // thead: { render: "TableHeader" }, + // th: { render: "TableHead" }, + // tr: { render: "TableRow" }, + // tbody: { render: "TableBody" }, + // td: { render: "TableCell" }, + // fence: { + // render: "Code", + // attributes: { + // content: { + // type: String, + // }, + // language: { + // type: String, + // }, + // id: { + // type: String, + // required: false, + // }, + // lineNumbers: { + // type: Boolean, + // required: false, + // default: true, + // }, + // fileName: { + // type: String, + // required: false, + // }, + // }, + // }, + // }, + // tags: { + // callout: { + // render: "Callout", + // attributes: { + // title: { + // type: String, + // default: "default title", + // }, + // type: { + // type: String, + // default: "default", + // }, + // }, + // }, + // orderedlist: { + // render: "List", + // attributes: { + // ordered: { type: Boolean, required: false, default: true }, + // type: { type: String, required: false }, + // start: { type: Number, required: false }, + // }, + // transform(node, config) { + // const attributes = node.transformAttributes(config) + // const children = node.transformChildren(config) + // const elements = children[0] as any + // if (children.length && elements?.name === "List") { + // elements.attributes = attributes + // } + // return elements + // }, + // }, + // tabs: { + // render: "Tabs", + // children: ["Tab"], + // transform(node, config) { + // const labels = node + // .transformChildren(config) + // .filter((child: any) => child && child.name === "Tab") + // .map((tab: any) => + // typeof tab === "object" ? tab?.attributes?.label : null, + // ) + // const defaultValue = ( + // node + // .transformChildren(config) + // .filter((child: any) => child && child.name === "Tab") + // .find((tab: any) => tab?.attributes?.default == true) as any + // )?.attributes?.label + // return new Tag( + // this.render, + // { labels, defaultValue }, + // node.transformChildren(config), + // ) + // }, + // }, + // tab: { + // render: "Tab", + // attributes: { + // label: { type: String, required: true }, + // default: { type: Boolean, required: false }, + // }, + // }, + // accordion: { + // render: "Accordion", + // children: ["AccordionItem"], + // attributes: { + // type: { type: String }, + // collapsible: { type: Boolean, required: false, default: false }, + // }, + // }, + // accordionitem: { + // render: "AccordionItem", + // attributes: { + // title: { type: String, required: true }, + // }, + // }, + }, }; const components = { // Paragraph: TypographyP, - // Heading: Heading, + Heading: Heading, // Blockquote: TypographyBlockquote, // Callout: Callout, // List: TypographyList, diff --git a/packages/markdoc-heading/index.ts b/packages/markdoc-heading/index.ts index 8879d7a..a354859 100644 --- a/packages/markdoc-heading/index.ts +++ b/packages/markdoc-heading/index.ts @@ -1 +1,2 @@ -export * from './src'; \ No newline at end of file +export { config } from "./src/config"; +export { Heading } from "./src/Heading"; diff --git a/packages/markdoc-heading/package.json b/packages/markdoc-heading/package.json index 548d60a..6e345bb 100644 --- a/packages/markdoc-heading/package.json +++ b/packages/markdoc-heading/package.json @@ -19,6 +19,12 @@ "format": "prettier --check . --ignore-path ../../.gitignore", "typecheck": "tsc --noEmit" }, + "dependencies": { + "@markdoc/markdoc": "0.4.0", + "@sindresorhus/slugify": "2.2.1", + "@acme/helpers": "workspace:0.1.0", + "react": "18.2.0" + }, "devDependencies": { "@acme/eslint-config": "workspace:0.2.0", "@acme/prettier-config": "workspace:0.1.0", diff --git a/packages/markdoc-heading/src/Heading.tsx b/packages/markdoc-heading/src/Heading.tsx new file mode 100644 index 0000000..8fab69c --- /dev/null +++ b/packages/markdoc-heading/src/Heading.tsx @@ -0,0 +1,47 @@ +import type { ReactNode } from "react"; + +import { cn } from "@acme/helpers"; + +/** + * Source: https://github.com/dylanmeivis/nextjs13-starter-markdoc + */ + +interface HeadingProps { + children: ReactNode; + level: number; + id: string; +} + +export function Heading({ children, level, id }: HeadingProps) { + let headingClass = "text-base font-semibold"; + + switch (level) { + case 1: + headingClass = "text-4xl font-extrabold lg:text-5xl"; + break; + case 2: + headingClass = + "border-b pb-2 text-3xl font-semibold transition-colors first:mt-0"; + break; + case 3: + headingClass = "text-2xl font-semibold"; + break; + case 4: + headingClass = "text-xl font-semibold"; + break; + case 5: + headingClass = "text-lg font-semibold"; + break; + } + + const HeadingTag = `h${level}` as keyof JSX.IntrinsicElements; + + return ( + + {children} + + ); +} diff --git a/packages/markdoc-heading/src/config.ts b/packages/markdoc-heading/src/config.ts new file mode 100644 index 0000000..c76ede4 --- /dev/null +++ b/packages/markdoc-heading/src/config.ts @@ -0,0 +1,22 @@ +import Markdoc, { Tag } from "@markdoc/markdoc"; +import type { Schema } from "@markdoc/markdoc"; +import { slugifyWithCounter } from "@sindresorhus/slugify"; + +const slugify = slugifyWithCounter(); + +export const config: Schema = { + render: "Heading", + attributes: { + id: { type: String }, + level: { type: Number, required: true }, + }, + transform(node, config) { + const attributes = node.transformAttributes(config); + const children = node.transformChildren(config); + const renderedContent = Markdoc.renderers.html(children); + if (!attributes.id) { + attributes.id = slugify(renderedContent); + } + return new Tag(this.render, attributes, children); + }, +}; diff --git a/packages/markdoc-heading/src/index.ts b/packages/markdoc-heading/src/index.ts deleted file mode 100644 index 14a82c7..0000000 --- a/packages/markdoc-heading/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export const name = 'markdoc-heading'; \ No newline at end of file diff --git a/packages/ui/index.ts b/packages/ui/index.ts index 8879d7a..4d902f6 100644 --- a/packages/ui/index.ts +++ b/packages/ui/index.ts @@ -1 +1,2 @@ -export * from './src'; \ No newline at end of file +export * from "./src"; +export { cn } from "../helpers/src/cn"; diff --git a/packages/ui/package.json b/packages/ui/package.json index 910036c..679bcbc 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -23,10 +23,14 @@ "class-variance-authority": "^0.7.0", "clsx": "2.0.0", "lucide-react": "^0.294.0", + "tailwindcss": "3.3.6", "tailwind-merge": "2.1.0", - "tailwindcss-animate": "1.0.7" + "tailwindcss-animate": "1.0.7", + "@acme/tailwind-config": "workspace:0.1.0", + "@acme/helpers": "workspace:0.1.0" }, "devDependencies": { + "@acme/markdoc-base": "workspace:0.1.0", "@acme/eslint-config": "workspace:0.2.0", "@acme/prettier-config": "workspace:0.1.0", "@acme/tsconfig": "workspace:0.1.0", diff --git a/packages/ui/src/components/table-of-contents.tsx b/packages/ui/src/components/table-of-contents.tsx new file mode 100644 index 0000000..b726196 --- /dev/null +++ b/packages/ui/src/components/table-of-contents.tsx @@ -0,0 +1,104 @@ +// Source: https://github.com/shadcn/ui/blob/main/apps/www/components/toc.tsx +"use client"; + +import * as React from "react"; + +import { cn } from "@acme/helpers"; +import type { TableOfContents } from "@acme/markdoc-base"; + +interface TocProps { + toc: TableOfContents[]; +} + +interface TreeProps { + tree: TableOfContents[]; + level?: number; + activeItem?: string; +} + +export function TableOfContents({ toc }: TocProps) { + const itemIds = React.useMemo( + () => + toc + ? toc + .flatMap((item) => [ + `#${item.id}`, + ...(item?.children?.map((item) => `#${item.id}`) ?? ""), + ]) + .flat() + .filter((ele) => ele !== "") + .map((id) => id.split("#")[1]!) + : [], + [toc], + ); + + const activeHeading = useActiveItem(itemIds); + + return ; +} + +function useActiveItem(itemIds: string[]) { + const [activeId, setActiveId] = React.useState(""); + + React.useEffect(() => { + const observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + setActiveId(entry.target.id); + } + }); + }, + { rootMargin: `0% 0% -80% 0%` }, + ); + + itemIds?.forEach((id) => { + const element = document.getElementById(id); + if (element) { + observer.observe(element); + } + }); + + return () => { + itemIds?.forEach((id) => { + const element = document.getElementById(id); + if (element) { + observer.unobserve(element); + } + }); + }; + }, [itemIds]); + + return activeId; +} + +function Tree({ tree, level = 1, activeItem }: TreeProps) { + return tree?.length ? ( + + ) : null; +} diff --git a/packages/ui/tailwind.config.js b/packages/ui/tailwind.config.js deleted file mode 100644 index 0377ea1..0000000 --- a/packages/ui/tailwind.config.js +++ /dev/null @@ -1,76 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -module.exports = { - darkMode: ["class"], - content: [ - './pages/**/*.{ts,tsx}', - './components/**/*.{ts,tsx}', - './app/**/*.{ts,tsx}', - './src/**/*.{ts,tsx}', - ], - theme: { - container: { - center: true, - padding: "2rem", - screens: { - "2xl": "1400px", - }, - }, - extend: { - colors: { - border: "hsl(var(--border))", - input: "hsl(var(--input))", - ring: "hsl(var(--ring))", - background: "hsl(var(--background))", - foreground: "hsl(var(--foreground))", - primary: { - DEFAULT: "hsl(var(--primary))", - foreground: "hsl(var(--primary-foreground))", - }, - secondary: { - DEFAULT: "hsl(var(--secondary))", - foreground: "hsl(var(--secondary-foreground))", - }, - destructive: { - DEFAULT: "hsl(var(--destructive))", - foreground: "hsl(var(--destructive-foreground))", - }, - muted: { - DEFAULT: "hsl(var(--muted))", - foreground: "hsl(var(--muted-foreground))", - }, - accent: { - DEFAULT: "hsl(var(--accent))", - foreground: "hsl(var(--accent-foreground))", - }, - popover: { - DEFAULT: "hsl(var(--popover))", - foreground: "hsl(var(--popover-foreground))", - }, - card: { - DEFAULT: "hsl(var(--card))", - foreground: "hsl(var(--card-foreground))", - }, - }, - borderRadius: { - lg: "var(--radius)", - md: "calc(var(--radius) - 2px)", - sm: "calc(var(--radius) - 4px)", - }, - keyframes: { - "accordion-down": { - from: { height: 0 }, - to: { height: "var(--radix-accordion-content-height)" }, - }, - "accordion-up": { - from: { height: "var(--radix-accordion-content-height)" }, - to: { height: 0 }, - }, - }, - animation: { - "accordion-down": "accordion-down 0.2s ease-out", - "accordion-up": "accordion-up 0.2s ease-out", - }, - }, - }, - plugins: [require("tailwindcss-animate")], -} \ No newline at end of file diff --git a/packages/ui/tailwind.config.ts b/packages/ui/tailwind.config.ts new file mode 100644 index 0000000..5906f1b --- /dev/null +++ b/packages/ui/tailwind.config.ts @@ -0,0 +1,8 @@ +import type { Config } from "tailwindcss" + +import baseConfig from "@acme/tailwind-config" + +export default { + content: ["./src/**/*.{ts,tsx}"], + presets: [baseConfig], +} satisfies Config diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json index 27b5382..002703b 100644 --- a/packages/ui/tsconfig.json +++ b/packages/ui/tsconfig.json @@ -7,6 +7,6 @@ "@/*": ["./src/*"] } }, - "include": ["*.ts", "src"], + "include": ["*.ts", "src", "../helpers/src/lib", "../helpers/src/cn.ts"], "exclude": ["node_modules"] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fb55d5f..52dd2f6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -85,6 +85,34 @@ importers: specifier: 5.3.3 version: 5.3.3 + packages/helpers: + dependencies: + clsx: + specifier: 2.0.0 + version: 2.0.0 + tailwind-merge: + specifier: 2.1.0 + version: 2.1.0 + tailwindcss: + specifier: 3.3.6 + version: 3.3.6 + devDependencies: + '@acme/eslint-config': + specifier: workspace:0.2.0 + version: link:../../tooling/eslint + '@acme/prettier-config': + specifier: workspace:0.1.0 + version: link:../../tooling/prettier + '@acme/tsconfig': + specifier: workspace:0.1.0 + version: link:../../tooling/typescript + eslint: + specifier: 8.55.0 + version: 8.55.0 + typescript: + specifier: 5.3.3 + version: 5.3.3 + packages/markdoc-accordion: devDependencies: '@acme/eslint-config': @@ -105,9 +133,24 @@ importers: packages/markdoc-base: dependencies: + '@acme/helpers': + specifier: workspace:0.1.0 + version: link:../helpers + '@acme/markdoc-heading': + specifier: workspace:0.1.0 + version: link:../markdoc-heading '@markdoc/markdoc': specifier: 0.4.0 - version: 0.4.0 + version: 0.4.0(react@18.2.0) + string-strip-html: + specifier: 13.4.3 + version: 13.4.3 + zod: + specifier: 3.22.4 + version: 3.22.4 + zod-matter: + specifier: 0.1.1 + version: 0.1.1(gray-matter@4.0.3)(zod@3.22.4) devDependencies: '@acme/eslint-config': specifier: workspace:0.2.0 @@ -180,6 +223,19 @@ importers: version: 5.3.3 packages/markdoc-heading: + dependencies: + '@acme/helpers': + specifier: workspace:0.1.0 + version: link:../helpers + '@markdoc/markdoc': + specifier: 0.4.0 + version: 0.4.0(react@18.2.0) + '@sindresorhus/slugify': + specifier: 2.2.1 + version: 2.2.1 + react: + specifier: 18.2.0 + version: 18.2.0 devDependencies: '@acme/eslint-config': specifier: workspace:0.2.0 @@ -217,6 +273,12 @@ importers: packages/ui: dependencies: + '@acme/helpers': + specifier: workspace:0.1.0 + version: link:../helpers + '@acme/tailwind-config': + specifier: workspace:0.1.0 + version: link:../../tooling/tailwind class-variance-authority: specifier: ^0.7.0 version: 0.7.0 @@ -229,6 +291,9 @@ importers: tailwind-merge: specifier: 2.1.0 version: 2.1.0 + tailwindcss: + specifier: 3.3.6 + version: 3.3.6 tailwindcss-animate: specifier: 1.0.7 version: 1.0.7(tailwindcss@3.3.6) @@ -236,6 +301,9 @@ importers: '@acme/eslint-config': specifier: workspace:0.2.0 version: link:../../tooling/eslint + '@acme/markdoc-base': + specifier: workspace:0.1.0 + version: link:../markdoc-base '@acme/prettier-config': specifier: workspace:0.1.0 version: link:../../tooling/prettier @@ -682,7 +750,7 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true - /@markdoc/markdoc@0.4.0: + /@markdoc/markdoc@0.4.0(react@18.2.0): resolution: {integrity: sha512-fSh4P3Y4E7oaKYc2oNzSIJVPDto7SMzAuQN1Iyx53UxzleA6QzRdNWRxmiPqtVDaDi5dELd2yICoG91csrGrAw==} engines: {node: '>=14.7.0'} peerDependencies: @@ -693,6 +761,8 @@ packages: optional: true react: optional: true + dependencies: + react: 18.2.0 optionalDependencies: '@types/markdown-it': 12.2.3 dev: false @@ -806,6 +876,21 @@ packages: '@nodelib/fs.scandir': 2.1.5 fastq: 1.15.0 + /@sindresorhus/slugify@2.2.1: + resolution: {integrity: sha512-MkngSCRZ8JdSOCHRaYd+D01XhvU3Hjy6MGl06zhOk614hp9EOAp5gIkBeQg7wtmxpitU6eAL4kdiRMcJa2dlrw==} + engines: {node: '>=12'} + dependencies: + '@sindresorhus/transliterate': 1.6.0 + escape-string-regexp: 5.0.0 + dev: false + + /@sindresorhus/transliterate@1.6.0: + resolution: {integrity: sha512-doH1gimEu3A46VX6aVxpHTeHrytJAG6HgdxntYnCFiIFHEM/ZGpG8KiZGBChchjQmG0XFIBL552kBTjVcMZXwQ==} + engines: {node: '>=12'} + dependencies: + escape-string-regexp: 5.0.0 + dev: false + /@swc/helpers@0.5.2: resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==} dependencies: @@ -938,6 +1023,16 @@ packages: dev: false optional: true + /@types/lodash-es@4.17.12: + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + dependencies: + '@types/lodash': 4.14.202 + dev: false + + /@types/lodash@4.14.202: + resolution: {integrity: sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==} + dev: false + /@types/markdown-it@12.2.3: resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==} requiresBuild: true @@ -1215,6 +1310,12 @@ packages: /arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: false + /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -1555,6 +1656,13 @@ packages: engines: {node: '>=6'} dev: false + /codsen-utils@1.6.2: + resolution: {integrity: sha512-L+Cn6c/q0m3nHT6inNIKO1E+BHzeJ1b6McBQLcHvq46gYt7RSPEjYqmq0P5LWZsz+hb+w0tS5WkH6hRvZeHz2A==} + engines: {node: '>=14.18.0'} + dependencies: + rfdc: 1.3.0 + dev: false + /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -1886,6 +1994,11 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} + /escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + dev: false + /escodegen@2.1.0: resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} engines: {node: '>=6.0'} @@ -2127,7 +2240,6 @@ packages: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} hasBin: true - dev: true /esquery@1.5.0: resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} @@ -2164,6 +2276,13 @@ packages: strip-final-newline: 2.0.0 dev: true + /extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + dependencies: + is-extendable: 0.1.1 + dev: false + /external-editor@3.1.0: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} @@ -2439,6 +2558,16 @@ packages: /graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + /gray-matter@4.0.3: + resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} + engines: {node: '>=6.0'} + dependencies: + js-yaml: 3.14.1 + kind-of: 6.0.3 + section-matter: 1.0.0 + strip-bom-string: 1.0.0 + dev: false + /handlebars@4.7.8: resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} engines: {node: '>=0.4.7'} @@ -2500,6 +2629,10 @@ packages: upper-case: 1.1.3 dev: true + /html-entities@2.4.0: + resolution: {integrity: sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==} + dev: false + /http-proxy-agent@7.0.0: resolution: {integrity: sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==} engines: {node: '>= 14'} @@ -2678,6 +2811,11 @@ packages: has-tostringtag: 1.0.0 dev: false + /is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + dev: false + /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -2848,6 +2986,14 @@ packages: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} dev: false + /js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: false + /js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true @@ -2911,6 +3057,11 @@ packages: dependencies: json-buffer: 3.0.1 + /kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: false + /language-subtag-registry@0.3.22: resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} dev: false @@ -2946,6 +3097,10 @@ packages: dependencies: p-locate: 5.0.0 + /lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + dev: false + /lodash.get@4.4.2: resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} dev: true @@ -3577,6 +3732,37 @@ packages: /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + /ranges-apply@7.0.12: + resolution: {integrity: sha512-RsdQnaC0pU+KV69muxE47NMhLCz9XHj3aAL/ykBtUXhtFWaq2/KXWM0wVXCYkBD/lIQRU1ZJhBla4LZPH2ywRQ==} + engines: {node: '>=14.18.0'} + dependencies: + ranges-merge: 9.0.12 + tiny-invariant: 1.3.1 + dev: false + + /ranges-merge@9.0.12: + resolution: {integrity: sha512-Asg92aN9sZebnKu79bAlmU+kcHL9hcQZJ4q1WLX2h65ydKfAVtHZp3KhOT4eBCb+G7cSCHUSSK0hqzd/p02ydA==} + engines: {node: '>=14.18.0'} + dependencies: + ranges-push: 7.0.12 + ranges-sort: 6.0.10 + dev: false + + /ranges-push@7.0.12: + resolution: {integrity: sha512-Jwr/rCIAitwuT+dodq9ISZa09WWWua/mRud4OXPiwA+D7GxObsGgsSkf/v62h6zDxGPJkCuEpryKoOg90sbU6A==} + engines: {node: '>=14.18.0'} + dependencies: + codsen-utils: 1.6.2 + ranges-sort: 6.0.10 + string-collapse-leading-whitespace: 7.0.6 + string-trim-spaces-only: 5.0.9 + dev: false + + /ranges-sort@6.0.10: + resolution: {integrity: sha512-Tts5PiQQW+M8jMIkE/y0VdF5+GYFlv85qYAfQUBtekORbNn+7IVD+wPLJZ3LmfJSFJz/Jm3Wlgz+OpAeeHr5PA==} + engines: {node: '>=14.18.0'} + dev: false + /rc@1.2.8: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true @@ -3699,6 +3885,10 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + /rfdc@1.3.0: + resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} + dev: false + /rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true @@ -3760,6 +3950,14 @@ packages: loose-envify: 1.4.0 dev: false + /section-matter@1.0.0: + resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} + engines: {node: '>=4'} + dependencies: + extend-shallow: 2.0.1 + kind-of: 6.0.3 + dev: false + /semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -3923,11 +4121,46 @@ packages: engines: {node: '>=0.10.0'} dev: true + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: false + /streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} dev: false + /string-collapse-leading-whitespace@7.0.6: + resolution: {integrity: sha512-FqOnt9H0+eeXukBb3Js2qPLLI0T5ebp96TfU0+AwoAuQQidETeoRMYJG6mUYebP4SBYZkap+HbAK6U/wGWxJvA==} + engines: {node: '>=14.18.0'} + dev: false + + /string-left-right@6.0.15: + resolution: {integrity: sha512-f80yIZCFZJnZcnCp8/Mk9zYRs210LHCkpNy668wusUzuh6qhryLA/SfxbFayxnFN12xdPARAvObu/wzYKX57wA==} + engines: {node: '>=14.18.0'} + dependencies: + codsen-utils: 1.6.2 + rfdc: 1.3.0 + dev: false + + /string-strip-html@13.4.3: + resolution: {integrity: sha512-9ketPUGy6MWmHy5tZuy1LSXcEB690MCQ0eTvUlunCjCGGTIUjboHyFa/PADndYHlfvHDcdO9iwzqjheXI/K/jw==} + engines: {node: '>=14.18.0'} + dependencies: + '@types/lodash-es': 4.17.12 + codsen-utils: 1.6.2 + html-entities: 2.4.0 + lodash-es: 4.17.21 + ranges-apply: 7.0.12 + ranges-push: 7.0.12 + string-left-right: 6.0.15 + dev: false + + /string-trim-spaces-only@5.0.9: + resolution: {integrity: sha512-Yl/Ot+1YksCi2PI+I4nw6Mq2U2QV7vsCWFT+1lfWoFGYVS/27JmtWvueYiQW0YTPX4xz4DhV2cQijDakIPTWGg==} + engines: {node: '>=14.18.0'} + dev: false + /string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -3988,6 +4221,11 @@ packages: dependencies: ansi-regex: 5.0.1 + /strip-bom-string@1.0.0: + resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} + engines: {node: '>=0.10.0'} + dev: false + /strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} @@ -4122,6 +4360,10 @@ packages: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} dev: true + /tiny-invariant@1.3.1: + resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==} + dev: false + /tinycolor2@1.6.0: resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} dev: true @@ -4518,6 +4760,17 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + /zod-matter@0.1.1(gray-matter@4.0.3)(zod@3.22.4): + resolution: {integrity: sha512-+GGjzfWhlFtzok6eV5YR7AS3mDYAFgxwX40B5tqfU00ij/gWpBsXy0qQcFkTxFKMiaGYwkMLpS0ckTWe56Qjsg==} + engines: {node: '>=18'} + peerDependencies: + gray-matter: '>=3.0.0' + zod: '>=3.0.0' + dependencies: + gray-matter: 4.0.3 + zod: 3.22.4 + dev: false + /zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} dev: false