From 3e349d24f9f6787ba4d79ee8b0e343f7007a859d Mon Sep 17 00:00:00 2001 From: Joe Heffernan Date: Tue, 20 Jan 2026 10:15:44 -0800 Subject: [PATCH 01/14] add dev script --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index d8e5f13..d4e3e5a 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,8 @@ "develop": "npm run clean && gatsby develop", "serve": "gatsby serve", "format": "prettier --trailing-comma es5 --no-semi --single-quote --write \"{gatsby-*.js,src/**/*.js}\"", - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "dev": "npx concurrently \"npx netlify-cms-proxy-server\" \"npm start -- --progress\"" }, "devDependencies": { "@types/antd": "^1.0.0", From 489bf39f666883217b72a815d2f05fbf68cb4a67 Mon Sep 17 00:00:00 2001 From: Joe Heffernan Date: Tue, 20 Jan 2026 11:52:00 -0800 Subject: [PATCH 02/14] show related posts in tag popover component --- src/components/IdeaRoll.tsx | 5 +- src/components/TagPopover.tsx | 91 ++++++++++++++++++++++++++++++++ src/style/tag-popover.module.css | 36 +++++++++++++ src/templates/idea-post.tsx | 11 +++- src/types/css-modules.d.ts | 4 ++ src/types/index.ts | 3 ++ 6 files changed, 145 insertions(+), 5 deletions(-) create mode 100644 src/components/TagPopover.tsx create mode 100644 src/style/tag-popover.module.css create mode 100644 src/types/css-modules.d.ts diff --git a/src/components/IdeaRoll.tsx b/src/components/IdeaRoll.tsx index 650d672..88bffcc 100644 --- a/src/components/IdeaRoll.tsx +++ b/src/components/IdeaRoll.tsx @@ -5,6 +5,7 @@ import { MessageOutlined, StarOutlined } from "@ant-design/icons"; import { useLocation } from "@reach/router"; import { MaterialsAndMethods } from "../types"; import { IconText } from "./IconText"; +import { TagPopover } from "./TagPopover"; const { container } = require("../style/idea-roll.module.css"); @@ -84,9 +85,7 @@ const IdeaRollTemplate = (props: { key="list-vertical-message" />, ...item.tags.map((tag) => ( - - {tag} - + )), ]} // extra={ diff --git a/src/components/TagPopover.tsx b/src/components/TagPopover.tsx new file mode 100644 index 0000000..42015dc --- /dev/null +++ b/src/components/TagPopover.tsx @@ -0,0 +1,91 @@ +import React from "react"; +import { Tag, Popover } from "antd"; +import { Link, useStaticQuery, graphql } from "gatsby"; + +import * as styles from "../style/tag-popover.module.css"; + +interface PostForTags { + node: { + id: string; + fields: { + slug: string; + } | null; + frontmatter: { + title: string; + tags?: string[] | null; + } | null; + }; +} + +interface TagPopoverQuery { + allMarkdownRemark: { + edges: PostForTags[]; + }; +} + +interface TagPopoverProps { + tag: string; + currentSlug?: string; +} + +export const TagPopover: React.FC = ({ tag, currentSlug }) => { + const data: TagPopoverQuery = useStaticQuery(graphql` + query AllIdeasForTags { + allMarkdownRemark( + filter: { frontmatter: { templateKey: { eq: "idea-post" } } } + ) { + edges { + node { + id + fields { + slug + } + frontmatter { + title + tags + } + } + } + } + } + `); + + const postsWithTag = data.allMarkdownRemark.edges + .filter( + (edge: PostForTags) => + edge.node.frontmatter!.tags?.includes(tag) && + edge.node.fields!.slug !== currentSlug + ) + .map((post: any) => ( +
  • + + {post.node.frontmatter.title} + +
  • + )); + + const headerText = + postsWithTag.length > 0 + ? `${postsWithTag.length} other post${ + postsWithTag.length !== 1 ? "s" : "" + } tagged with "${tag}"` + : "No other posts with this tag"; + + const content = ( +
    +
    + {headerText} +
    +
      {postsWithTag}
    +
    + Browse all tags +
    +
    + ); + + return ( + + {tag} + + ); +}; diff --git a/src/style/tag-popover.module.css b/src/style/tag-popover.module.css new file mode 100644 index 0000000..a3a7984 --- /dev/null +++ b/src/style/tag-popover.module.css @@ -0,0 +1,36 @@ +.post-link { + padding: 0.25rem 0; + border-bottom: 1px solid var(--OFF_WHITE); +} + +.popover-content { + max-width: 400px; + max-height: 400px; + overflow-y: auto; +} + +.header { + margin-bottom: 0.5rem; +} + +.post-list { + list-style: none; + padding: 0; + margin: 0; +} + +.post-link:last-child { + border-bottom: none; +} + +.post-link a { + color: var(--link-color); +} + +.post-link a:hover { + text-decoration: underline; +} + +.tag { + cursor: pointer; +} \ No newline at end of file diff --git a/src/templates/idea-post.tsx b/src/templates/idea-post.tsx index 06ecd1a..0a114f3 100644 --- a/src/templates/idea-post.tsx +++ b/src/templates/idea-post.tsx @@ -13,6 +13,7 @@ import Content, { HTMLContent } from "../components/Content"; import IconText from "../components/IconText"; import { IdeaPostNode, MaterialsAndMethods } from "../types"; import { MaterialsAndMethodsComponent } from "../components/MaterialsAndMethods"; +import { TagPopover } from "../components/TagPopover"; const Header = AntdLayout.Header; @@ -39,9 +40,11 @@ interface IdeaPostTemplateProps { title: string; helmet?: React.ReactNode; materialsAndMethods?: MaterialsAndMethods; + currentSlug?: string; } export const IdeaPostTemplate: React.FC = ({ + currentSlug, tags, title, helmet, @@ -56,8 +59,8 @@ export const IdeaPostTemplate: React.FC = ({ return (
      {tags.map((tag) => ( -
    • -
      {tag}
      +
    • +
    • ))}
    @@ -140,6 +143,7 @@ const IdeaPost = ({ data }: QueryResult) => { tags={post.frontmatter.tags} title={post.frontmatter.title} materialsAndMethods={post.frontmatter.materialsAndMethods} + currentSlug={post.fields?.slug} /> ); @@ -152,6 +156,9 @@ export const pageQuery = graphql` markdownRemark(id: { eq: $id }) { id html + fields { + slug + } frontmatter { date(formatString: "MMMM DD, YYYY") title diff --git a/src/types/css-modules.d.ts b/src/types/css-modules.d.ts new file mode 100644 index 0000000..ef8d961 --- /dev/null +++ b/src/types/css-modules.d.ts @@ -0,0 +1,4 @@ +declare module "*.module.css" { + const classes: { readonly [key: string]: string }; + export = classes; +} diff --git a/src/types/index.ts b/src/types/index.ts index 6c9c611..f092dd3 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -62,5 +62,8 @@ export interface IdeaFrontmatter { export interface IdeaPostNode { id: string; html: string; + fields: { + slug: string; + } frontmatter: IdeaFrontmatter; } \ No newline at end of file From 7e48bf65576f5d68480c0d4e2532d16209220027 Mon Sep 17 00:00:00 2001 From: Joe Heffernan Date: Wed, 21 Jan 2026 10:40:16 -0800 Subject: [PATCH 03/14] Update src/components/IdeaRoll.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/components/IdeaRoll.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/IdeaRoll.tsx b/src/components/IdeaRoll.tsx index 88bffcc..61f3ae0 100644 --- a/src/components/IdeaRoll.tsx +++ b/src/components/IdeaRoll.tsx @@ -85,7 +85,7 @@ const IdeaRollTemplate = (props: { key="list-vertical-message" />, ...item.tags.map((tag) => ( - + )), ]} // extra={ From 2e32af0e2f9f2940980d556b59261ee4ece775bd Mon Sep 17 00:00:00 2001 From: Joe Heffernan Date: Wed, 21 Jan 2026 10:41:34 -0800 Subject: [PATCH 04/14] Update src/components/TagPopover.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/components/TagPopover.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/TagPopover.tsx b/src/components/TagPopover.tsx index 42015dc..a9cddae 100644 --- a/src/components/TagPopover.tsx +++ b/src/components/TagPopover.tsx @@ -56,7 +56,7 @@ export const TagPopover: React.FC = ({ tag, currentSlug }) => { edge.node.frontmatter!.tags?.includes(tag) && edge.node.fields!.slug !== currentSlug ) - .map((post: any) => ( + .map((post: PostForTags) => (
  • {post.node.frontmatter.title} From f961a521b936aaf81865ff5d4fe4dd64648a8753 Mon Sep 17 00:00:00 2001 From: Joe Heffernan Date: Wed, 21 Jan 2026 10:45:04 -0800 Subject: [PATCH 05/14] add non null assertions to fields --- src/components/TagPopover.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/TagPopover.tsx b/src/components/TagPopover.tsx index a9cddae..7097fee 100644 --- a/src/components/TagPopover.tsx +++ b/src/components/TagPopover.tsx @@ -58,8 +58,8 @@ export const TagPopover: React.FC = ({ tag, currentSlug }) => { ) .map((post: PostForTags) => (
  • - - {post.node.frontmatter.title} + + {post.node!.frontmatter!.title}
  • )); From 81d0ab58bec161859693ca024fc1fafb5ce85c6a Mon Sep 17 00:00:00 2001 From: Joe Heffernan Date: Fri, 23 Jan 2026 13:28:53 -0800 Subject: [PATCH 06/14] use generated types with tag popover --- gatsby-node.js | 16 +++++++++++++++- src/components/TagPopover.tsx | 33 +++++++-------------------------- src/templates/idea-post.tsx | 17 +++++++---------- src/types/index.ts | 13 +++++++++---- 4 files changed, 38 insertions(+), 41 deletions(-) diff --git a/gatsby-node.js b/gatsby-node.js index 075affa..0886a79 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -22,7 +22,14 @@ const DATA_ONLY_PAGES = [ exports.createSchemaCustomization = ({ actions, schema }) => { const { createTypes } = actions; const typeDefs = [ - `type MarkdownRemark implements Node { frontmatter: Frontmatter } + `type MarkdownRemarkFields { + slug: String! + } + + type MarkdownRemark implements Node { + frontmatter: Frontmatter! + fields: MarkdownRemarkFields! + } """ Shared frontmatter fields for idea posts (and other markdown). @@ -73,6 +80,13 @@ exports.createSchemaCustomization = ({ actions, schema }) => { */ exports.createResolvers = ({ createResolvers }) => { createResolvers({ + MarkdownRemark: { + fields: { + resolve: (source) => ({ + slug: source.fields?.slug || "/", + }), + }, + }, Frontmatter: { description: { resolve: (source) => diff --git a/src/components/TagPopover.tsx b/src/components/TagPopover.tsx index 7097fee..3d2db5c 100644 --- a/src/components/TagPopover.tsx +++ b/src/components/TagPopover.tsx @@ -4,32 +4,13 @@ import { Link, useStaticQuery, graphql } from "gatsby"; import * as styles from "../style/tag-popover.module.css"; -interface PostForTags { - node: { - id: string; - fields: { - slug: string; - } | null; - frontmatter: { - title: string; - tags?: string[] | null; - } | null; - }; -} - -interface TagPopoverQuery { - allMarkdownRemark: { - edges: PostForTags[]; - }; -} - interface TagPopoverProps { tag: string; currentSlug?: string; } export const TagPopover: React.FC = ({ tag, currentSlug }) => { - const data: TagPopoverQuery = useStaticQuery(graphql` + const data: Queries.AllIdeasForTagsQuery = useStaticQuery(graphql` query AllIdeasForTags { allMarkdownRemark( filter: { frontmatter: { templateKey: { eq: "idea-post" } } } @@ -52,14 +33,14 @@ export const TagPopover: React.FC = ({ tag, currentSlug }) => { const postsWithTag = data.allMarkdownRemark.edges .filter( - (edge: PostForTags) => - edge.node.frontmatter!.tags?.includes(tag) && - edge.node.fields!.slug !== currentSlug + (edge) => + edge.node.frontmatter.tags?.includes(tag) && + edge.node.fields.slug !== currentSlug ) - .map((post: PostForTags) => ( + .map((post) => (
  • - - {post.node!.frontmatter!.title} + + {post.node.frontmatter.title}
  • )); diff --git a/src/templates/idea-post.tsx b/src/templates/idea-post.tsx index 45d99a3..52f4a25 100644 --- a/src/templates/idea-post.tsx +++ b/src/templates/idea-post.tsx @@ -11,7 +11,7 @@ import { import Layout from "../components/Layout"; import IconText from "../components/IconText"; import { MaterialsAndMethodsComponent } from "../components/MaterialsAndMethods"; -import { IdeaFrontmatter, IdeaPostNode, IdeaPostQuery } from "../types"; +import { IdeaFields, IdeaFrontmatter, IdeaPostQuery } from "../types"; import { TagPopover } from "../components/TagPopover"; const Header = AntdLayout.Header; @@ -25,10 +25,8 @@ const { actionIcons, } = require("../style/idea-post.module.css"); - - -export const IdeaPostTemplate: React.FC = ({ - currentSlug, +export const IdeaPostTemplate: React.FC = ({ + slug, tags, title, materialsAndMethods, @@ -43,7 +41,7 @@ export const IdeaPostTemplate: React.FC
      {tags.map((tag) => (
    • - +
    • ))}
    @@ -97,8 +95,8 @@ export const IdeaPostTemplate: React.FC const IdeaPost: React.FC> = ({ data }) => { const markdownRemark = data.markdownRemark; - // Runtime guard against missing data - if (!markdownRemark || !markdownRemark.frontmatter) { + // Runtime guard - markdownRemark can be null if query doesn't find matching ID + if (!markdownRemark) { return (

    Post not found.

    @@ -107,7 +105,6 @@ const IdeaPost: React.FC> = ({ data }) => { } const { title, description } = markdownRemark.frontmatter; - const currentSlug = markdownRemark.fields?.slug || ""; return ( @@ -116,7 +113,7 @@ const IdeaPost: React.FC> = ({ data }) => { - + ); }; diff --git a/src/types/index.ts b/src/types/index.ts index afc199e..492fa0f 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,17 +1,22 @@ /** - * Types are derived from the schema customization in gastby-node.js + * Types are derived from the schema customization in gatsby-node.js * and generated by running `gatsby develop` after editing the schema. * These generated types are accessed on the Queries object in the global * namespace as in Queries.DataByIdQuery for a page query called DataByIdQuery. - * + * * To ensure data safety and avoid excess non-null assertions, - * derived non-nullable types are added here, and used in conjuction with - * resolvers that ensure fields are present. + * derived non-nullable types are added here, and used in conjunction with + * resolvers that ensure fields are present. + * + * After updating schema customization, run `gatsby develop` to regenerate types. */ export type IdeaPostQuery = Queries.IdeaPostByIDQuery; export type IdeaPostNode = NonNullable; export type IdeaFrontmatter = NonNullable; +export type IdeaFields = NonNullable; export type MaterialsAndMethods = NonNullable; export type CellLine = MaterialsAndMethods["cellLines"][number]; export type SoftwareTool = MaterialsAndMethods["software"][number]; + +export type IdeasForTags = Queries.AllIdeasForTagsQuery["allMarkdownRemark"]["edges"]; \ No newline at end of file From da8984720247b9db3e244e763af62b118f3f0a96 Mon Sep 17 00:00:00 2001 From: Joe Heffernan Date: Fri, 23 Jan 2026 14:29:32 -0800 Subject: [PATCH 07/14] install slugify and vitest --- package.json | 6 +- yarn.lock | 554 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 554 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index d4e3e5a..570992f 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,9 @@ "react-dom": "^18.3.1", "react-helmet-async": "^2.0.5", "sass": "^1.43.2", - "uuid": "^8.0.0" + "slugify": "^1.6.6", + "uuid": "^8.0.0", + "vitest": "^4.0.18" }, "keywords": [ "gatsby" @@ -47,7 +49,7 @@ "develop": "npm run clean && gatsby develop", "serve": "gatsby serve", "format": "prettier --trailing-comma es5 --no-semi --single-quote --write \"{gatsby-*.js,src/**/*.js}\"", - "test": "echo \"Error: no test specified\" && exit 1", + "test": "vitest", "dev": "npx concurrently \"npx netlify-cms-proxy-server\" \"npm start -- --progress\"" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index decd3bb..35df2a7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1353,6 +1353,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz#830d6476cbbca0c005136af07303646b419f1162" integrity sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q== +"@esbuild/aix-ppc64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz#521cbd968dcf362094034947f76fa1b18d2d403c" + integrity sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw== + "@esbuild/android-arm64@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.11.tgz#b45d000017385c9051a4f03e17078abb935be220" @@ -1368,6 +1373,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz#d11d4fc299224e729e2190cacadbcc00e7a9fd67" integrity sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A== +"@esbuild/android-arm64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz#61ea550962d8aa12a9b33194394e007657a6df57" + integrity sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA== + "@esbuild/android-arm@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.11.tgz#f46f55414e1c3614ac682b29977792131238164c" @@ -1383,6 +1393,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.4.tgz#5660bd25080553dd2a28438f2a401a29959bd9b1" integrity sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ== +"@esbuild/android-arm@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.27.2.tgz#554887821e009dd6d853f972fde6c5143f1de142" + integrity sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA== + "@esbuild/android-x64@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.11.tgz#bfc01e91740b82011ef503c48f548950824922b2" @@ -1398,6 +1413,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.4.tgz#18ddde705bf984e8cd9efec54e199ac18bc7bee1" integrity sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ== +"@esbuild/android-x64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.27.2.tgz#a7ce9d0721825fc578f9292a76d9e53334480ba2" + integrity sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A== + "@esbuild/darwin-arm64@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.11.tgz#533fb7f5a08c37121d82c66198263dcc1bed29bf" @@ -1413,6 +1433,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz#b0b7fb55db8fc6f5de5a0207ae986eb9c4766e67" integrity sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g== +"@esbuild/darwin-arm64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz#2cb7659bd5d109803c593cfc414450d5430c8256" + integrity sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg== + "@esbuild/darwin-x64@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.11.tgz#62f3819eff7e4ddc656b7c6815a31cf9a1e7d98e" @@ -1428,6 +1453,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz#e6813fdeba0bba356cb350a4b80543fbe66bf26f" integrity sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A== +"@esbuild/darwin-x64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz#e741fa6b1abb0cd0364126ba34ca17fd5e7bf509" + integrity sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA== + "@esbuild/freebsd-arm64@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.11.tgz#d478b4195aa3ca44160272dab85ef8baf4175b4a" @@ -1443,6 +1473,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz#dc11a73d3ccdc308567b908b43c6698e850759be" integrity sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ== +"@esbuild/freebsd-arm64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz#2b64e7116865ca172d4ce034114c21f3c93e397c" + integrity sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g== + "@esbuild/freebsd-x64@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.11.tgz#7bdcc1917409178257ca6a1a27fe06e797ec18a2" @@ -1458,6 +1493,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz#91da08db8bd1bff5f31924c57a81dab26e93a143" integrity sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ== +"@esbuild/freebsd-x64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz#e5252551e66f499e4934efb611812f3820e990bb" + integrity sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA== + "@esbuild/linux-arm64@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.11.tgz#58ad4ff11685fcc735d7ff4ca759ab18fcfe4545" @@ -1473,6 +1513,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz#efc15e45c945a082708f9a9f73bfa8d4db49728a" integrity sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ== +"@esbuild/linux-arm64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz#dc4acf235531cd6984f5d6c3b13dbfb7ddb303cb" + integrity sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw== + "@esbuild/linux-arm@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.11.tgz#ce82246d873b5534d34de1e5c1b33026f35e60e3" @@ -1488,6 +1533,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz#9b93c3e54ac49a2ede6f906e705d5d906f6db9e8" integrity sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ== +"@esbuild/linux-arm@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz#56a900e39240d7d5d1d273bc053daa295c92e322" + integrity sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw== + "@esbuild/linux-ia32@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.11.tgz#cbae1f313209affc74b80f4390c4c35c6ab83fa4" @@ -1503,6 +1553,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz#be8ef2c3e1d99fca2d25c416b297d00360623596" integrity sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ== +"@esbuild/linux-ia32@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz#d4a36d473360f6870efcd19d52bbfff59a2ed1cc" + integrity sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w== + "@esbuild/linux-loong64@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.11.tgz#5f32aead1c3ec8f4cccdb7ed08b166224d4e9121" @@ -1518,6 +1573,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz#b0840a2707c3fc02eec288d3f9defa3827cd7a87" integrity sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA== +"@esbuild/linux-loong64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz#fcf0ab8c3eaaf45891d0195d4961cb18b579716a" + integrity sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg== + "@esbuild/linux-mips64el@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.11.tgz#38eecf1cbb8c36a616261de858b3c10d03419af9" @@ -1533,6 +1593,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz#2a198e5a458c9f0e75881a4e63d26ba0cf9df39f" integrity sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg== +"@esbuild/linux-mips64el@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz#598b67d34048bb7ee1901cb12e2a0a434c381c10" + integrity sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw== + "@esbuild/linux-ppc64@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.11.tgz#9c5725a94e6ec15b93195e5a6afb821628afd912" @@ -1548,6 +1613,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz#64f4ae0b923d7dd72fb860b9b22edb42007cf8f5" integrity sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag== +"@esbuild/linux-ppc64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz#3846c5df6b2016dab9bc95dde26c40f11e43b4c0" + integrity sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ== + "@esbuild/linux-riscv64@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.11.tgz#2dc4486d474a2a62bbe5870522a9a600e2acb916" @@ -1563,6 +1633,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz#fb2844b11fdddd39e29d291c7cf80f99b0d5158d" integrity sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA== +"@esbuild/linux-riscv64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz#173d4475b37c8d2c3e1707e068c174bb3f53d07d" + integrity sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA== + "@esbuild/linux-s390x@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.11.tgz#4ad8567df48f7dd4c71ec5b1753b6f37561a65a8" @@ -1578,6 +1653,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz#1466876e0aa3560c7673e63fdebc8278707bc750" integrity sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g== +"@esbuild/linux-s390x@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz#f7a4790105edcab8a5a31df26fbfac1aa3dacfab" + integrity sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w== + "@esbuild/linux-x64@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.11.tgz#b7390c4d5184f203ebe7ddaedf073df82a658766" @@ -1593,11 +1673,21 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz#c10fde899455db7cba5f11b3bccfa0e41bf4d0cd" integrity sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA== +"@esbuild/linux-x64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz#2ecc1284b1904aeb41e54c9ddc7fcd349b18f650" + integrity sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA== + "@esbuild/netbsd-arm64@0.25.4": version "0.25.4" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz#02e483fbcbe3f18f0b02612a941b77be76c111a4" integrity sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ== +"@esbuild/netbsd-arm64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz#e2863c2cd1501845995cb11adf26f7fe4be527b0" + integrity sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw== + "@esbuild/netbsd-x64@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.11.tgz#d633c09492a1721377f3bccedb2d821b911e813d" @@ -1613,11 +1703,21 @@ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz#ec401fb0b1ed0ac01d978564c5fc8634ed1dc2ed" integrity sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw== +"@esbuild/netbsd-x64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz#93f7609e2885d1c0b5a1417885fba8d1fcc41272" + integrity sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA== + "@esbuild/openbsd-arm64@0.25.4": version "0.25.4" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz#f272c2f41cfea1d91b93d487a51b5c5ca7a8c8c4" integrity sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A== +"@esbuild/openbsd-arm64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz#a1985604a203cdc325fd47542e106fafd698f02e" + integrity sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA== + "@esbuild/openbsd-x64@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.11.tgz#17388c76e2f01125bf831a68c03a7ffccb65d1a2" @@ -1633,6 +1733,16 @@ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz#2e25950bc10fa9db1e5c868e3d50c44f7c150fd7" integrity sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw== +"@esbuild/openbsd-x64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz#8209e46c42f1ffbe6e4ef77a32e1f47d404ad42a" + integrity sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg== + +"@esbuild/openharmony-arm64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz#8fade4441893d9cc44cbd7dcf3776f508ab6fb2f" + integrity sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag== + "@esbuild/sunos-x64@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.11.tgz#e320636f00bb9f4fdf3a80e548cb743370d41767" @@ -1648,6 +1758,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz#cd596fa65a67b3b7adc5ecd52d9f5733832e1abd" integrity sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q== +"@esbuild/sunos-x64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz#980d4b9703a16f0f07016632424fc6d9a789dfc2" + integrity sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg== + "@esbuild/win32-arm64@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.11.tgz#c778b45a496e90b6fc373e2a2bb072f1441fe0ee" @@ -1663,6 +1778,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz#b4dbcb57b21eeaf8331e424c3999b89d8951dc88" integrity sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ== +"@esbuild/win32-arm64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz#1c09a3633c949ead3d808ba37276883e71f6111a" + integrity sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg== + "@esbuild/win32-ia32@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.11.tgz#481a65fee2e5cce74ec44823e6b09ecedcc5194c" @@ -1678,6 +1798,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz#410842e5d66d4ece1757634e297a87635eb82f7a" integrity sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg== +"@esbuild/win32-ia32@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz#1b1e3a63ad4bef82200fef4e369e0fff7009eee5" + integrity sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ== + "@esbuild/win32-x64@0.19.11": version "0.19.11" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz#a5d300008960bb39677c46bf16f53ec70d8dee04" @@ -1693,6 +1818,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz#0b17ec8a70b2385827d52314c1253160a0b9bacc" integrity sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ== +"@esbuild/win32-x64@0.27.2": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz#9e585ab6086bef994c6e8a5b3a0481219ada862b" + integrity sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ== + "@eslint-community/eslint-utils@^4.2.0": version "4.7.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz#607084630c6c033992a082de6e6fbc1a8b52175a" @@ -2080,6 +2210,11 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== +"@jridgewell/sourcemap-codec@^1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + "@jridgewell/trace-mapping@0.3.9": version "0.3.9" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" @@ -3406,6 +3541,131 @@ estree-walker "^2.0.2" picomatch "^4.0.2" +"@rollup/rollup-android-arm-eabi@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.56.0.tgz#067cfcd81f1c1bfd92aefe3ad5ef1523549d5052" + integrity sha512-LNKIPA5k8PF1+jAFomGe3qN3bbIgJe/IlpDBwuVjrDKrJhVWywgnJvflMt/zkbVNLFtF1+94SljYQS6e99klnw== + +"@rollup/rollup-android-arm64@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.56.0.tgz#85e39a44034d7d4e4fee2a1616f0bddb85a80517" + integrity sha512-lfbVUbelYqXlYiU/HApNMJzT1E87UPGvzveGg2h0ktUNlOCxKlWuJ9jtfvs1sKHdwU4fzY7Pl8sAl49/XaEk6Q== + +"@rollup/rollup-darwin-arm64@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.56.0.tgz#17d92fe98f2cc277b91101eb1528b7c0b6c00c54" + integrity sha512-EgxD1ocWfhoD6xSOeEEwyE7tDvwTgZc8Bss7wCWe+uc7wO8G34HHCUH+Q6cHqJubxIAnQzAsyUsClt0yFLu06w== + +"@rollup/rollup-darwin-x64@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.56.0.tgz#89ae6c66b1451609bd1f297da9384463f628437d" + integrity sha512-1vXe1vcMOssb/hOF8iv52A7feWW2xnu+c8BV4t1F//m9QVLTfNVpEdja5ia762j/UEJe2Z1jAmEqZAK42tVW3g== + +"@rollup/rollup-freebsd-arm64@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.56.0.tgz#cdbdb9947b26e76c188a31238c10639347413628" + integrity sha512-bof7fbIlvqsyv/DtaXSck4VYQ9lPtoWNFCB/JY4snlFuJREXfZnm+Ej6yaCHfQvofJDXLDMTVxWscVSuQvVWUQ== + +"@rollup/rollup-freebsd-x64@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.56.0.tgz#9b1458d07b6e040be16ee36d308a2c9520f7f7cc" + integrity sha512-KNa6lYHloW+7lTEkYGa37fpvPq+NKG/EHKM8+G/g9WDU7ls4sMqbVRV78J6LdNuVaeeK5WB9/9VAFbKxcbXKYg== + +"@rollup/rollup-linux-arm-gnueabihf@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.56.0.tgz#1d50ded7c965d5f125f5832c971ad5b287befef7" + integrity sha512-E8jKK87uOvLrrLN28jnAAAChNq5LeCd2mGgZF+fGF5D507WlG/Noct3lP/QzQ6MrqJ5BCKNwI9ipADB6jyiq2A== + +"@rollup/rollup-linux-arm-musleabihf@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.56.0.tgz#53597e319b7e65990d3bc2a5048097384814c179" + integrity sha512-jQosa5FMYF5Z6prEpTCCmzCXz6eKr/tCBssSmQGEeozA9tkRUty/5Vx06ibaOP9RCrW1Pvb8yp3gvZhHwTDsJw== + +"@rollup/rollup-linux-arm64-gnu@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.56.0.tgz#597002909dec198ca4bdccb25f043d32db3d6283" + integrity sha512-uQVoKkrC1KGEV6udrdVahASIsaF8h7iLG0U0W+Xn14ucFwi6uS539PsAr24IEF9/FoDtzMeeJXJIBo5RkbNWvQ== + +"@rollup/rollup-linux-arm64-musl@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.56.0.tgz#286f0e0f799545ce288bdc5a7c777261fcba3d54" + integrity sha512-vLZ1yJKLxhQLFKTs42RwTwa6zkGln+bnXc8ueFGMYmBTLfNu58sl5/eXyxRa2RarTkJbXl8TKPgfS6V5ijNqEA== + +"@rollup/rollup-linux-loong64-gnu@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.56.0.tgz#1fab07fa1a4f8d3697735b996517f1bae0ba101b" + integrity sha512-FWfHOCub564kSE3xJQLLIC/hbKqHSVxy8vY75/YHHzWvbJL7aYJkdgwD/xGfUlL5UV2SB7otapLrcCj2xnF1dg== + +"@rollup/rollup-linux-loong64-musl@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.56.0.tgz#efc2cb143d6c067f95205482afb177f78ed9ea3d" + integrity sha512-z1EkujxIh7nbrKL1lmIpqFTc/sr0u8Uk0zK/qIEFldbt6EDKWFk/pxFq3gYj4Bjn3aa9eEhYRlL3H8ZbPT1xvA== + +"@rollup/rollup-linux-ppc64-gnu@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.56.0.tgz#e8de8bd3463f96b92b7dfb7f151fd80ffe8a937c" + integrity sha512-iNFTluqgdoQC7AIE8Q34R3AuPrJGJirj5wMUErxj22deOcY7XwZRaqYmB6ZKFHoVGqRcRd0mqO+845jAibKCkw== + +"@rollup/rollup-linux-ppc64-musl@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.56.0.tgz#8c508fe28a239da83b3a9da75bcf093186e064b4" + integrity sha512-MtMeFVlD2LIKjp2sE2xM2slq3Zxf9zwVuw0jemsxvh1QOpHSsSzfNOTH9uYW9i1MXFxUSMmLpeVeUzoNOKBaWg== + +"@rollup/rollup-linux-riscv64-gnu@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.56.0.tgz#ff6d51976e0830732880770a9e18553136b8d92b" + integrity sha512-in+v6wiHdzzVhYKXIk5U74dEZHdKN9KH0Q4ANHOTvyXPG41bajYRsy7a8TPKbYPl34hU7PP7hMVHRvv/5aCSew== + +"@rollup/rollup-linux-riscv64-musl@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.56.0.tgz#325fb35eefc7e81d75478318f0deee1e4a111493" + integrity sha512-yni2raKHB8m9NQpI9fPVwN754mn6dHQSbDTwxdr9SE0ks38DTjLMMBjrwvB5+mXrX+C0npX0CVeCUcvvvD8CNQ== + +"@rollup/rollup-linux-s390x-gnu@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.56.0.tgz#37410fabb5d3ba4ad34abcfbe9ba9b6288413f30" + integrity sha512-zhLLJx9nQPu7wezbxt2ut+CI4YlXi68ndEve16tPc/iwoylWS9B3FxpLS2PkmfYgDQtosah07Mj9E0khc3Y+vQ== + +"@rollup/rollup-linux-x64-gnu@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.56.0.tgz#8ef907a53b2042068fc03fcc6a641e2b02276eca" + integrity sha512-MVC6UDp16ZSH7x4rtuJPAEoE1RwS8N4oK9DLHy3FTEdFoUTCFVzMfJl/BVJ330C+hx8FfprA5Wqx4FhZXkj2Kw== + +"@rollup/rollup-linux-x64-musl@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.56.0.tgz#61b9ba09ea219e0174b3f35a6ad2afc94bdd5662" + integrity sha512-ZhGH1eA4Qv0lxaV00azCIS1ChedK0V32952Md3FtnxSqZTBTd6tgil4nZT5cU8B+SIw3PFYkvyR4FKo2oyZIHA== + +"@rollup/rollup-openbsd-x64@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.56.0.tgz#fc4e54133134c1787d0b016ffdd5aeb22a5effd3" + integrity sha512-O16XcmyDeFI9879pEcmtWvD/2nyxR9mF7Gs44lf1vGGx8Vg2DRNx11aVXBEqOQhWb92WN4z7fW/q4+2NYzCbBA== + +"@rollup/rollup-openharmony-arm64@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.56.0.tgz#959ae225b1eeea0cc5b7c9f88e4834330fb6cd09" + integrity sha512-LhN/Reh+7F3RCgQIRbgw8ZMwUwyqJM+8pXNT6IIJAqm2IdKkzpCh/V9EdgOMBKuebIrzswqy4ATlrDgiOwbRcQ== + +"@rollup/rollup-win32-arm64-msvc@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.56.0.tgz#842acd38869fa1cbdbc240c76c67a86f93444c27" + integrity sha512-kbFsOObXp3LBULg1d3JIUQMa9Kv4UitDmpS+k0tinPBz3watcUiV2/LUDMMucA6pZO3WGE27P7DsfaN54l9ing== + +"@rollup/rollup-win32-ia32-msvc@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.56.0.tgz#7ab654def4042df44cb29f8ed9d5044e850c66d5" + integrity sha512-vSSgny54D6P4vf2izbtFm/TcWYedw7f8eBrOiGGecyHyQB9q4Kqentjaj8hToe+995nob/Wv48pDqL5a62EWtg== + +"@rollup/rollup-win32-x64-gnu@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.56.0.tgz#7426cdec1b01d2382ffd5cda83cbdd1c8efb3ca6" + integrity sha512-FeCnkPCTHQJFbiGG49KjV5YGW/8b9rrXAM2Mz2kiIoktq2qsJxRD5giEMEOD2lPdgs72upzefaUvS+nc8E3UzQ== + +"@rollup/rollup-win32-x64-msvc@4.56.0": + version "4.56.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.56.0.tgz#9eec0212732a432c71bde0350bc40b673d15b2db" + integrity sha512-H8AE9Ur/t0+1VXujj90w0HrSOuv0Nq9r1vSZF2t5km20NTfosQsGGUXDaKdQZzwuLts7IyL1fYT4hM95TI9c4g== + "@rtsao/scc@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" @@ -3495,6 +3755,11 @@ string-width "^4.2.3" strip-ansi "^6.0.1" +"@standard-schema/spec@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.1.0.tgz#a79b55dbaf8604812f52d140b2c9ab41bc150bb8" + integrity sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w== + "@swc/helpers@^0.4.12": version "0.4.37" resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.37.tgz#36c6083077fd8003e50661d2ed8a65b05b9fe86f" @@ -3571,6 +3836,14 @@ "@types/node" "*" "@types/responselike" "^1.0.0" +"@types/chai@^5.2.2": + version "5.2.3" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-5.2.3.tgz#8e9cd9e1c3581fa6b341a5aed5588eb285be0b4a" + integrity sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA== + dependencies: + "@types/deep-eql" "*" + assertion-error "^2.0.1" + "@types/common-tags@^1.8.1": version "1.8.4" resolved "https://registry.yarnpkg.com/@types/common-tags/-/common-tags-1.8.4.tgz#3b31fcb5952cd326a55cabe9dbe6c5be3c1671a0" @@ -3598,6 +3871,11 @@ resolved "https://registry.yarnpkg.com/@types/debug/-/debug-0.0.30.tgz#dc1e40f7af3b9c815013a7860e6252f6352a84df" integrity sha512-orGL5LXERPYsLov6CWs3Fh6203+dXzJkR7OnddIr2514Hsecwc8xRpzCapshBbKFImCsvS/mk6+FWiN5LyZJAQ== +"@types/deep-eql@*": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/deep-eql/-/deep-eql-4.0.2.tgz#334311971d3a07121e7eb91b684a605e7eea9cbd" + integrity sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw== + "@types/escape-html@^1.0.0": version "1.0.4" resolved "https://registry.yarnpkg.com/@types/escape-html/-/escape-html-1.0.4.tgz#dc7c166b76c7b03b27e32f80edf01d91eb5d9af2" @@ -3632,6 +3910,11 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.7.tgz#4158d3105276773d5b7695cd4834b1722e4f37a8" integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ== +"@types/estree@1.0.8": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + "@types/get-port@^3.2.0": version "3.2.0" resolved "https://registry.yarnpkg.com/@types/get-port/-/get-port-3.2.0.tgz#f9e0a11443cc21336470185eae3dfba4495d29bc" @@ -4030,6 +4313,64 @@ dependencies: resolve "^1.10.0" +"@vitest/expect@4.0.18": + version "4.0.18" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-4.0.18.tgz#361510d99fbf20eb814222e4afcb8539d79dc94d" + integrity sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ== + dependencies: + "@standard-schema/spec" "^1.0.0" + "@types/chai" "^5.2.2" + "@vitest/spy" "4.0.18" + "@vitest/utils" "4.0.18" + chai "^6.2.1" + tinyrainbow "^3.0.3" + +"@vitest/mocker@4.0.18": + version "4.0.18" + resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-4.0.18.tgz#b9735da114ef65ea95652c5bdf13159c6fab4865" + integrity sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ== + dependencies: + "@vitest/spy" "4.0.18" + estree-walker "^3.0.3" + magic-string "^0.30.21" + +"@vitest/pretty-format@4.0.18": + version "4.0.18" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-4.0.18.tgz#fbccd4d910774072ec15463553edb8ca5ce53218" + integrity sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw== + dependencies: + tinyrainbow "^3.0.3" + +"@vitest/runner@4.0.18": + version "4.0.18" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-4.0.18.tgz#c2c0a3ed226ec85e9312f9cc8c43c5b3a893a8b1" + integrity sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw== + dependencies: + "@vitest/utils" "4.0.18" + pathe "^2.0.3" + +"@vitest/snapshot@4.0.18": + version "4.0.18" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-4.0.18.tgz#bcb40fd6d742679c2ac927ba295b66af1c6c34c5" + integrity sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA== + dependencies: + "@vitest/pretty-format" "4.0.18" + magic-string "^0.30.21" + pathe "^2.0.3" + +"@vitest/spy@4.0.18": + version "4.0.18" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-4.0.18.tgz#ba0f20503fb6d08baf3309d690b3efabdfa88762" + integrity sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw== + +"@vitest/utils@4.0.18": + version "4.0.18" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-4.0.18.tgz#9636b16d86a4152ec68a8d6859cff702896433d4" + integrity sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA== + dependencies: + "@vitest/pretty-format" "4.0.18" + tinyrainbow "^3.0.3" + "@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": version "1.14.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.14.1.tgz#a9f6a07f2b03c95c8d38c4536a1fdfb521ff55b6" @@ -4938,6 +5279,11 @@ ascii-table@0.0.9: resolved "https://registry.yarnpkg.com/ascii-table/-/ascii-table-0.0.9.tgz#06a6604d6a55d4bf41a9a47d9872d7a78da31e73" integrity sha512-xpkr6sCDIYTPqzvjG8M3ncw1YOTaloWZOyrUmicoEifBEKzQzt+ooUpRpQ/AbOoJfO/p2ZKiyp79qHThzJDulQ== +assertion-error@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" + integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== + ast-module-types@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/ast-module-types/-/ast-module-types-5.0.0.tgz#32b2b05c56067ff38e95df66f11d6afd6c9ba16b" @@ -5653,6 +5999,11 @@ ccount@^1.0.0, ccount@^1.0.3: resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== +chai@^6.2.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/chai/-/chai-6.2.2.tgz#ae41b52c9aca87734505362717f3255facda360e" + integrity sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg== + chain-function@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/chain-function/-/chain-function-1.0.1.tgz#c63045e5b4b663fb86f1c6e186adaf1de402a1cc" @@ -8006,7 +8357,7 @@ es-iterator-helpers@^1.2.1: iterator.prototype "^1.1.4" safe-array-concat "^1.1.3" -es-module-lexer@^1.0.0, es-module-lexer@^1.2.1: +es-module-lexer@^1.0.0, es-module-lexer@^1.2.1, es-module-lexer@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.7.0.tgz#9159601561880a85f2734560a9099b2c31e5372a" integrity sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA== @@ -8180,6 +8531,38 @@ esbuild@0.25.4: "@esbuild/win32-ia32" "0.25.4" "@esbuild/win32-x64" "0.25.4" +esbuild@^0.27.0: + version "0.27.2" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.27.2.tgz#d83ed2154d5813a5367376bb2292a9296fc83717" + integrity sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw== + optionalDependencies: + "@esbuild/aix-ppc64" "0.27.2" + "@esbuild/android-arm" "0.27.2" + "@esbuild/android-arm64" "0.27.2" + "@esbuild/android-x64" "0.27.2" + "@esbuild/darwin-arm64" "0.27.2" + "@esbuild/darwin-x64" "0.27.2" + "@esbuild/freebsd-arm64" "0.27.2" + "@esbuild/freebsd-x64" "0.27.2" + "@esbuild/linux-arm" "0.27.2" + "@esbuild/linux-arm64" "0.27.2" + "@esbuild/linux-ia32" "0.27.2" + "@esbuild/linux-loong64" "0.27.2" + "@esbuild/linux-mips64el" "0.27.2" + "@esbuild/linux-ppc64" "0.27.2" + "@esbuild/linux-riscv64" "0.27.2" + "@esbuild/linux-s390x" "0.27.2" + "@esbuild/linux-x64" "0.27.2" + "@esbuild/netbsd-arm64" "0.27.2" + "@esbuild/netbsd-x64" "0.27.2" + "@esbuild/openbsd-arm64" "0.27.2" + "@esbuild/openbsd-x64" "0.27.2" + "@esbuild/openharmony-arm64" "0.27.2" + "@esbuild/sunos-x64" "0.27.2" + "@esbuild/win32-arm64" "0.27.2" + "@esbuild/win32-ia32" "0.27.2" + "@esbuild/win32-x64" "0.27.2" + escalade@^3.1.1, escalade@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" @@ -8473,6 +8856,13 @@ estree-walker@2.0.2, estree-walker@^2.0.2: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== +estree-walker@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" + integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== + dependencies: + "@types/estree" "^1.0.0" + esutils@^2.0.2, esutils@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -8586,6 +8976,11 @@ expand-template@^2.0.3: resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== +expect-type@^1.2.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.3.0.tgz#0d58ed361877a31bbc4dd6cf71bbfef7faf6bd68" + integrity sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA== + express-http-proxy@^1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/express-http-proxy/-/express-http-proxy-1.6.3.tgz#f3ef139ffd49a7962e7af0462bbcca557c913175" @@ -8860,6 +9255,11 @@ fdir@^6.0.1: resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.4.tgz#1cfcf86f875a883e19a8fab53622cfe992e8d2f9" integrity sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg== +fdir@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" + integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + fecha@^4.2.0: version "4.2.3" resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" @@ -9269,7 +9669,7 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@~2.3.2: +fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== @@ -12510,6 +12910,13 @@ macos-release@^3.1.0: resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-3.3.0.tgz#92cb67bc66d67c3fde4a9e14f5f909afa418b072" integrity sha512-tPJQ1HeyiU2vRruNGhZ+VleWuMQRro8iFtJxYgnS4NQe+EukKF6aGiIT+7flZhISAt2iaXBCfFGvAyif7/f8nQ== +magic-string@^0.30.21: + version "0.30.21" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" + integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.5" + make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -13278,7 +13685,7 @@ nan@^2.16.0: resolved "https://registry.yarnpkg.com/nan/-/nan-2.22.2.tgz#6b504fd029fb8f38c0990e52ad5c26772fdacfbb" integrity sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ== -nanoid@^3.3.8: +nanoid@^3.3.11, nanoid@^3.3.8: version "3.3.11" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== @@ -13825,6 +14232,11 @@ objectFitPolyfill@^2.3.5: resolved "https://registry.yarnpkg.com/objectFitPolyfill/-/objectFitPolyfill-2.3.5.tgz#be8c83064aabfa4e88780f776c2013c48ce1f745" integrity sha512-8Quz071ZmGi0QWEG4xB3Bv5Lpw6K0Uca87FLoLMKMWjB6qIq9IyBegP3b/VLNxv2WYvIMGoeUQ+c6ibUkNa8TA== +obug@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/obug/-/obug-2.1.1.tgz#2cba74ff241beb77d63055ddf4cd1e9f90b538be" + integrity sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ== + ofetch@^1.3.3, ofetch@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.4.1.tgz#b6bf6b0d75ba616cef6519dd8b6385a8bae480ec" @@ -14487,7 +14899,7 @@ pathe@^1.1.1, pathe@^1.1.2: resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ== -pathe@^2.0.1: +pathe@^2.0.1, pathe@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== @@ -14535,6 +14947,11 @@ picomatch@^4.0.2: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== +picomatch@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" + integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== + pify@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" @@ -14913,6 +15330,15 @@ postcss@^8.0.0, postcss@^8.2.15, postcss@^8.2.9, postcss@^8.3.11, postcss@^8.3.5 picocolors "^1.1.1" source-map-js "^1.2.1" +postcss@^8.5.6: + version "8.5.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" + integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== + dependencies: + nanoid "^3.3.11" + picocolors "^1.1.1" + source-map-js "^1.2.1" + prebuild-install@^7.1.1: version "7.1.3" resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.3.tgz#d630abad2b147443f20a212917beae68b8092eec" @@ -16644,6 +17070,40 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +rollup@^4.43.0: + version "4.56.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.56.0.tgz#65959d13cfbd7e48b8868c05165b1738f0143862" + integrity sha512-9FwVqlgUHzbXtDg9RCMgodF3Ua4Na6Gau+Sdt9vyCN4RhHfVKX2DCHy3BjMLTDd47ITDhYAnTwGulWTblJSDLg== + dependencies: + "@types/estree" "1.0.8" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.56.0" + "@rollup/rollup-android-arm64" "4.56.0" + "@rollup/rollup-darwin-arm64" "4.56.0" + "@rollup/rollup-darwin-x64" "4.56.0" + "@rollup/rollup-freebsd-arm64" "4.56.0" + "@rollup/rollup-freebsd-x64" "4.56.0" + "@rollup/rollup-linux-arm-gnueabihf" "4.56.0" + "@rollup/rollup-linux-arm-musleabihf" "4.56.0" + "@rollup/rollup-linux-arm64-gnu" "4.56.0" + "@rollup/rollup-linux-arm64-musl" "4.56.0" + "@rollup/rollup-linux-loong64-gnu" "4.56.0" + "@rollup/rollup-linux-loong64-musl" "4.56.0" + "@rollup/rollup-linux-ppc64-gnu" "4.56.0" + "@rollup/rollup-linux-ppc64-musl" "4.56.0" + "@rollup/rollup-linux-riscv64-gnu" "4.56.0" + "@rollup/rollup-linux-riscv64-musl" "4.56.0" + "@rollup/rollup-linux-s390x-gnu" "4.56.0" + "@rollup/rollup-linux-x64-gnu" "4.56.0" + "@rollup/rollup-linux-x64-musl" "4.56.0" + "@rollup/rollup-openbsd-x64" "4.56.0" + "@rollup/rollup-openharmony-arm64" "4.56.0" + "@rollup/rollup-win32-arm64-msvc" "4.56.0" + "@rollup/rollup-win32-ia32-msvc" "4.56.0" + "@rollup/rollup-win32-x64-gnu" "4.56.0" + "@rollup/rollup-win32-x64-msvc" "4.56.0" + fsevents "~2.3.2" + run-async@^2.2.0, run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" @@ -17078,6 +17538,11 @@ side-channel@^1.0.6, side-channel@^1.1.0: side-channel-map "^1.0.1" side-channel-weakmap "^1.0.2" +siginfo@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30" + integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g== + signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" @@ -17424,6 +17889,11 @@ stack-trace@0.0.x, stack-trace@^0.0.10: resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== +stackback@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" + integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== + stackframe@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310" @@ -17444,6 +17914,11 @@ statuses@2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== +std-env@^3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.10.0.tgz#d810b27e3a073047b2b5e40034881f5ea6f9c83b" + integrity sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg== + std-env@^3.7.0: version "3.9.0" resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.9.0.tgz#1a6f7243b339dca4c9fd55e1c7504c77ef23e8f1" @@ -18148,11 +18623,34 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.3: resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== +tinybench@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b" + integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg== + tinycolor2@^1.4.1: version "1.6.0" resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e" integrity sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw== +tinyexec@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-1.0.2.tgz#bdd2737fe2ba40bd6f918ae26642f264b99ca251" + integrity sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg== + +tinyglobby@^0.2.15: + version "0.2.15" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.15.tgz#e228dd1e638cea993d2fdb4fcd2d4602a79951c2" + integrity sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ== + dependencies: + fdir "^6.5.0" + picomatch "^4.0.3" + +tinyrainbow@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-3.0.3.tgz#984a5b1c1b25854a9b6bccbe77964d0593d1ea42" + integrity sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q== + title-case@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/title-case/-/title-case-3.0.3.tgz#bc689b46f02e411f1d1e1d081f7c3deca0489982" @@ -19075,6 +19573,46 @@ vfile@^4.0.0: unist-util-stringify-position "^2.0.0" vfile-message "^2.0.0" +"vite@^6.0.0 || ^7.0.0": + version "7.3.1" + resolved "https://registry.yarnpkg.com/vite/-/vite-7.3.1.tgz#7f6cfe8fb9074138605e822a75d9d30b814d6507" + integrity sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA== + dependencies: + esbuild "^0.27.0" + fdir "^6.5.0" + picomatch "^4.0.3" + postcss "^8.5.6" + rollup "^4.43.0" + tinyglobby "^0.2.15" + optionalDependencies: + fsevents "~2.3.3" + +vitest@^4.0.18: + version "4.0.18" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-4.0.18.tgz#56f966353eca0b50f4df7540cd4350ca6d454a05" + integrity sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ== + dependencies: + "@vitest/expect" "4.0.18" + "@vitest/mocker" "4.0.18" + "@vitest/pretty-format" "4.0.18" + "@vitest/runner" "4.0.18" + "@vitest/snapshot" "4.0.18" + "@vitest/spy" "4.0.18" + "@vitest/utils" "4.0.18" + es-module-lexer "^1.7.0" + expect-type "^1.2.2" + magic-string "^0.30.21" + obug "^2.1.1" + pathe "^2.0.3" + picomatch "^4.0.3" + std-env "^3.10.0" + tinybench "^2.9.0" + tinyexec "^1.0.2" + tinyglobby "^0.2.15" + tinyrainbow "^3.0.3" + vite "^6.0.0 || ^7.0.0" + why-is-node-running "^2.3.0" + wait-port@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/wait-port/-/wait-port-1.1.0.tgz#e5d64ee071118d985e2b658ae7ad32b2ce29b6b5" @@ -19328,6 +19866,14 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +why-is-node-running@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04" + integrity sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w== + dependencies: + siginfo "^2.0.0" + stackback "0.0.2" + wide-align@^1.1.2: version "1.1.5" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" From f52f2b876abe89c501cd87c5abaff910f4d96e42 Mon Sep 17 00:00:00 2001 From: Joe Heffernan Date: Fri, 23 Jan 2026 14:30:41 -0800 Subject: [PATCH 08/14] rename timelapse-feature-explorer markdown file --- src/pages/software/{tfe.md => timelapse-feature-explorer.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/pages/software/{tfe.md => timelapse-feature-explorer.md} (100%) diff --git a/src/pages/software/tfe.md b/src/pages/software/timelapse-feature-explorer.md similarity index 100% rename from src/pages/software/tfe.md rename to src/pages/software/timelapse-feature-explorer.md From 01a10e428c0a64e7ca7e75eb90300456023a3b8b Mon Sep 17 00:00:00 2001 From: Joe Heffernan Date: Fri, 23 Jan 2026 14:32:32 -0800 Subject: [PATCH 09/14] add link and description to emt dataset markdown --- src/pages/dataset/released-emt-dataset.md | 3 ++- src/pages/ideas/dev-example.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pages/dataset/released-emt-dataset.md b/src/pages/dataset/released-emt-dataset.md index e4ac9c7..e736390 100644 --- a/src/pages/dataset/released-emt-dataset.md +++ b/src/pages/dataset/released-emt-dataset.md @@ -1,7 +1,8 @@ --- templateKey: dataset name: Released EMT dataset -link: test +link: "https://www.biorxiv.org/content/10.1101/2024.08.16.608353v1.full" +description: Description for released EMT dataset in the markdown file for the dataset. status: Public date: 2025-06-02T16:11:00.000Z --- diff --git a/src/pages/ideas/dev-example.md b/src/pages/ideas/dev-example.md index cfddcfd..5a72562 100644 --- a/src/pages/ideas/dev-example.md +++ b/src/pages/ideas/dev-example.md @@ -36,7 +36,7 @@ materialsAndMethods: link: https://allencell.org/cell-catalog software: - softwareTool: Simularium - customDescription: CUSTOM DESCRIPTION Used to visualize 3D trajectories and other cool stuff. + customDescription: Custom description in the markdown file for the idea, not in the software file markdown. - softwareTool: Timelapse Feature Explorer nextSteps: - "Expand analysis to all EMT datasets and stratify by treatment." From ade267c7f1ca81c22a1d02c008b58bcc3e5293b3 Mon Sep 17 00:00:00 2001 From: Joe Heffernan Date: Fri, 23 Jan 2026 14:41:47 -0800 Subject: [PATCH 10/14] use link directive and slugs to map foreign key relationships --- gatsby-config.js | 3 - gatsby-node.js | 15 +-- gatsbyutils/constants.js | 7 ++ gatsbyutils/gatsby-resolver-utils.js | 64 +++++++++- .../test/gatsby-resolver-utils.test.js | 109 ++++++++++++++++++ 5 files changed, 187 insertions(+), 11 deletions(-) create mode 100644 gatsbyutils/constants.js create mode 100644 gatsbyutils/test/gatsby-resolver-utils.test.js diff --git a/gatsby-config.js b/gatsby-config.js index 9b7224d..30de248 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -79,7 +79,4 @@ module.exports = { }, // must be after other CSS plugins "gatsby-plugin-netlify", // make sure to keep it last in the array ], - mapping: { - "MarkdownRemark.frontmatter.dataset": `MarkdownRemark.frontmatter.name`, - }, }; diff --git a/gatsby-node.js b/gatsby-node.js index 0886a79..10cc70f 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -4,7 +4,10 @@ const { createFilePath } = require("gatsby-source-filesystem"); const { stringWithDefault, resolveToArray, + resolveSlug, + resolveSoftwareTools, } = require("./gatsbyutils/gatsby-resolver-utils"); +const { DATASET_PATH } = require("./gatsbyutils/constants"); /** * Markdown in /src/pages/ with these templateKeys are data-only @@ -47,7 +50,7 @@ exports.createSchemaCustomization = ({ actions, schema }) => { Nested materials and methods block for idea posts. """ type MaterialsAndMethods { - dataset: MarkdownRemark @link(by: "frontmatter.name") + dataset: MarkdownRemark @link(by: "fields.slug") protocols: [ProtocolItem!]! cellLines: [CellLineItem!]! software: [SoftwareTool!]! @@ -66,7 +69,7 @@ exports.createSchemaCustomization = ({ actions, schema }) => { Software tool reference with optional custom description. """ type SoftwareTool { - softwareTool: MarkdownRemark @link(by: "frontmatter.name") + softwareTool: MarkdownRemark @link(by: "fields.slug") customDescription: String }`, ]; @@ -113,13 +116,11 @@ exports.createResolvers = ({ createResolvers }) => { return current; } - current.dataset = stringWithDefault( - raw.dataset, - current.dataset - ); + const resolvedDatasetSlug = resolveSlug(raw.dataset, DATASET_PATH); + current.dataset = resolvedDatasetSlug; current.cellLines = resolveToArray(raw.cellLines); current.protocols = resolveToArray(raw.protocols); - current.software = resolveToArray(raw.software); + current.software = resolveSoftwareTools(raw.software); return current; }, diff --git a/gatsbyutils/constants.js b/gatsbyutils/constants.js new file mode 100644 index 0000000..b29e5d7 --- /dev/null +++ b/gatsbyutils/constants.js @@ -0,0 +1,7 @@ +const DATASET_PATH = `dataset`; +const SOFTWARE_PATH = `software`; + +module.exports = { + DATASET_PATH, + SOFTWARE_PATH, +}; \ No newline at end of file diff --git a/gatsbyutils/gatsby-resolver-utils.js b/gatsbyutils/gatsby-resolver-utils.js index 11fde71..440feb0 100644 --- a/gatsbyutils/gatsby-resolver-utils.js +++ b/gatsbyutils/gatsby-resolver-utils.js @@ -1,9 +1,24 @@ +const { SOFTWARE_PATH } = require("../gatsbyutils/constants"); +const slugify = require("slugify"); + +/** + * Returns the raw value if it's a non-empty string, otherwise returns the fallback. + * @param {unknown} rawValue - The value to check + * @param {T} fallback - The fallback value to return if rawValue is not a valid string + * @returns {string|T} The raw string value or the fallback + * @template T + */ function stringWithDefault(rawValue, fallback) { if (typeof rawValue !== "string") return fallback; if (rawValue.trim() === "") return fallback; return rawValue; } +/** + * Ensures the value is returned as an array. + * @param {unknown} value - The value to convert to an array + * @returns {Array} The original array if value is an array, otherwise an empty array + */ function resolveToArray(value) { if (Array.isArray(value)) { return value; @@ -11,7 +26,54 @@ function resolveToArray(value) { return []; } +/** + * Prepares software tool references for Gatsby's @link directive. + * Transforms tool names into slug paths that @link(by: "fields.slug") uses + * to resolve the actual MarkdownRemark nodes. Filters out invalid entries + * and preserves custom descriptions. + * @param {Array<{softwareTool?: string, customDescription?: string}>|unknown} rawSoftware - Array of software tool objects from frontmatter + * @returns {Array<{softwareTool: string|null, customDescription: string|null}>} Array with slug keys for @link resolution + */ +const resolveSoftwareTools = (rawSoftware) => { + if (!Array.isArray(rawSoftware)) { + return []; + } + return rawSoftware + .map((item) => { + if (item && typeof item === "object" && item.softwareTool) { + return { + softwareTool: resolveSlug(item.softwareTool, SOFTWARE_PATH), + customDescription: stringWithDefault( + item.customDescription, + null + ), + }; + } + return null; + }) + .filter((item) => item !== null); +}; + +/** + * Builds slugs from directory paths and ids/names. + * Uses slugs in place of names to prevent namespace + * collisions when using @link directive in Gatsby schema. + * @param {string|null|undefined} id - The identifier to slugify (e.g., "My Dataset") + * @param {string} directory - The directory prefix (e.g., "dataset", "software") + * @returns {string|null} The full slug path (e.g., "/dataset/my-dataset/") or null if id is falsy + */ +const resolveSlug = (id, directory) => { + if (!id) return null; + const slugPart = slugify(id, { lower: true, strict: true }).replace( + /^\/+|\/+$/g, + "" + ); // Slugify and remove leading/trailing slashes + return `/${directory}/${slugPart}/`; +}; + module.exports = { stringWithDefault, resolveToArray, -}; + resolveSlug, + resolveSoftwareTools, +}; \ No newline at end of file diff --git a/gatsbyutils/test/gatsby-resolver-utils.test.js b/gatsbyutils/test/gatsby-resolver-utils.test.js new file mode 100644 index 0000000..12a7640 --- /dev/null +++ b/gatsbyutils/test/gatsby-resolver-utils.test.js @@ -0,0 +1,109 @@ +import { describe, it, expect } from 'vitest'; +import { resolveSlug, resolveSoftwareTools } from '../gatsby-resolver-utils'; +import { DATASET_PATH, SOFTWARE_PATH } from '../constants'; + +describe('resolveSlug', () => { + it('should return null when id is falsy', () => { + expect(resolveSlug(null, 'software')).toBe(null); + expect(resolveSlug(undefined, 'software')).toBe(null); + expect(resolveSlug('', 'software')).toBe(null); + }); + + it('should build a slug from id and directory', () => { + expect(resolveSlug("released-emt-dataset", DATASET_PATH)).toBe( + "/dataset/released-emt-dataset/" + ); + }); + + it('should slugify the id to lowercase', () => { + expect(resolveSlug("UPPERCASE", DATASET_PATH)).toBe( + "/dataset/uppercase/" + ); + }); + + it('should handle special characters in id', () => { + expect(resolveSlug("Tool & Library", SOFTWARE_PATH)).toBe( + "/software/tool-and-library/" + ); + expect(resolveSlug("Some/Path/Name", SOFTWARE_PATH)).toBe( + "/software/somepathname/" + ); + }); + + it('should handle ids with leading/trailing spaces', () => { + expect(resolveSlug(' trimmed ', 'software')).toBe('/software/trimmed/'); + }); +}); + +describe('resolveSoftwareTools', () => { + it('should return empty array for non-array inputs', () => { + expect(resolveSoftwareTools(null)).toEqual([]); + expect(resolveSoftwareTools(undefined)).toEqual([]); + expect(resolveSoftwareTools('string')).toEqual([]); + expect(resolveSoftwareTools({})).toEqual([]); + expect(resolveSoftwareTools(123)).toEqual([]); + }); + + it('should return empty array for empty array', () => { + expect(resolveSoftwareTools([])).toEqual([]); + }); + + it('should filter out invalid items', () => { + const input = [null, undefined, 'string', {}, { other: 'prop' }]; + expect(resolveSoftwareTools(input)).toEqual([]); + }); + + it('should transform valid items with softwareTool', () => { + const input = [{ softwareTool: 'Simularium' }]; + expect(resolveSoftwareTools(input)).toEqual([ + { + softwareTool: '/software/simularium/', + customDescription: null, + }, + ]); + }); + + it('should preserve customDescription when provided', () => { + const input = [ + { + softwareTool: 'Simularium', + customDescription: 'Custom description here', + }, + ]; + expect(resolveSoftwareTools(input)).toEqual([ + { + softwareTool: '/software/simularium/', + customDescription: 'Custom description here', + }, + ]); + }); + + it('should return null for empty customDescription', () => { + const input = [{ softwareTool: 'Simularium', customDescription: '' }]; + expect(resolveSoftwareTools(input)).toEqual([ + { + softwareTool: '/software/simularium/', + customDescription: null, + }, + ]); + }); + + it('should handle mixed valid and invalid items', () => { + const input = [ + null, + { softwareTool: 'Simularium' }, + { other: 'invalid' }, + { softwareTool: 'TFE', customDescription: 'Time explorer' }, + ]; + expect(resolveSoftwareTools(input)).toEqual([ + { + softwareTool: '/software/simularium/', + customDescription: null, + }, + { + softwareTool: '/software/tfe/', + customDescription: 'Time explorer', + }, + ]); + }); +}); \ No newline at end of file From 8fbfe52f0e55e35e91363883c600a67ab7c089b4 Mon Sep 17 00:00:00 2001 From: Joe Heffernan Date: Fri, 23 Jan 2026 14:58:46 -0800 Subject: [PATCH 11/14] use a gql file for some gatsby schema types --- gatsby-node.js | 27 +++++---------------------- gatsby/schema/base.gql | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 22 deletions(-) create mode 100644 gatsby/schema/base.gql diff --git a/gatsby-node.js b/gatsby-node.js index 10cc70f..9235eaf 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -1,4 +1,5 @@ const _ = require("lodash"); +const fs = require("fs"); const path = require("path"); const { createFilePath } = require("gatsby-source-filesystem"); const { @@ -9,6 +10,8 @@ const { } = require("./gatsbyutils/gatsby-resolver-utils"); const { DATASET_PATH } = require("./gatsbyutils/constants"); +const read = (p) => fs.readFileSync(path.join(__dirname, p), "utf8"); + /** * Markdown in /src/pages/ with these templateKeys are data-only * and do not get their own pages. @@ -25,28 +28,7 @@ const DATA_ONLY_PAGES = [ exports.createSchemaCustomization = ({ actions, schema }) => { const { createTypes } = actions; const typeDefs = [ - `type MarkdownRemarkFields { - slug: String! - } - - type MarkdownRemark implements Node { - frontmatter: Frontmatter! - fields: MarkdownRemarkFields! - } - - """ - Shared frontmatter fields for idea posts (and other markdown). - """ - type Frontmatter { - date: Date @dateformat - title: String! - description: String - draft: Boolean - tags: [String!] - materialsAndMethods: MaterialsAndMethods! - } - - """ + `""" Nested materials and methods block for idea posts. """ type MaterialsAndMethods { @@ -73,6 +55,7 @@ exports.createSchemaCustomization = ({ actions, schema }) => { customDescription: String }`, ]; + createTypes(read("gatsby/schema/base.gql")); createTypes(typeDefs); }; diff --git a/gatsby/schema/base.gql b/gatsby/schema/base.gql new file mode 100644 index 0000000..b995d33 --- /dev/null +++ b/gatsby/schema/base.gql @@ -0,0 +1,18 @@ +type MarkdownRemarkFields { + slug: String! +} + +type MarkdownRemark implements Node { + frontmatter: Frontmatter! + fields: MarkdownRemarkFields! +} + +# Shared frontmatter fields for idea posts (and other markdown). +type Frontmatter { + date: Date @dateformat + title: String! + description: String + draft: Boolean + tags: [String!] + materialsAndMethods: MaterialsAndMethods! +} From 9f096a5f9588c562f18c842c2fe476389760ffc6 Mon Sep 17 00:00:00 2001 From: Joe Heffernan Date: Fri, 23 Jan 2026 15:11:49 -0800 Subject: [PATCH 12/14] reorganize gatsby related file structure --- gatsby-node.js | 4 ++-- {gatsbyutils => gatsby}/constants.js | 0 {gatsbyutils => gatsby/utils}/gatsby-resolver-utils.js | 2 +- .../utils}/test/gatsby-resolver-utils.test.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename {gatsbyutils => gatsby}/constants.js (100%) rename {gatsbyutils => gatsby/utils}/gatsby-resolver-utils.js (97%) rename {gatsbyutils => gatsby/utils}/test/gatsby-resolver-utils.test.js (98%) diff --git a/gatsby-node.js b/gatsby-node.js index 9235eaf..674044b 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -7,8 +7,8 @@ const { resolveToArray, resolveSlug, resolveSoftwareTools, -} = require("./gatsbyutils/gatsby-resolver-utils"); -const { DATASET_PATH } = require("./gatsbyutils/constants"); +} = require("./gatsby/utils/gatsby-resolver-utils"); +const { DATASET_PATH } = require("./gatsby/constants"); const read = (p) => fs.readFileSync(path.join(__dirname, p), "utf8"); diff --git a/gatsbyutils/constants.js b/gatsby/constants.js similarity index 100% rename from gatsbyutils/constants.js rename to gatsby/constants.js diff --git a/gatsbyutils/gatsby-resolver-utils.js b/gatsby/utils/gatsby-resolver-utils.js similarity index 97% rename from gatsbyutils/gatsby-resolver-utils.js rename to gatsby/utils/gatsby-resolver-utils.js index 440feb0..0b62d94 100644 --- a/gatsbyutils/gatsby-resolver-utils.js +++ b/gatsby/utils/gatsby-resolver-utils.js @@ -1,4 +1,4 @@ -const { SOFTWARE_PATH } = require("../gatsbyutils/constants"); +const { SOFTWARE_PATH } = require("../constants"); const slugify = require("slugify"); /** diff --git a/gatsbyutils/test/gatsby-resolver-utils.test.js b/gatsby/utils/test/gatsby-resolver-utils.test.js similarity index 98% rename from gatsbyutils/test/gatsby-resolver-utils.test.js rename to gatsby/utils/test/gatsby-resolver-utils.test.js index 12a7640..3411564 100644 --- a/gatsbyutils/test/gatsby-resolver-utils.test.js +++ b/gatsby/utils/test/gatsby-resolver-utils.test.js @@ -1,6 +1,6 @@ import { describe, it, expect } from 'vitest'; import { resolveSlug, resolveSoftwareTools } from '../gatsby-resolver-utils'; -import { DATASET_PATH, SOFTWARE_PATH } from '../constants'; +import { DATASET_PATH, SOFTWARE_PATH } from '../../constants'; describe('resolveSlug', () => { it('should return null when id is falsy', () => { From f8d5d0ee7c552aed9f1edf39a2bd50616c16f344 Mon Sep 17 00:00:00 2001 From: Joe Heffernan Date: Fri, 20 Feb 2026 13:53:31 -0800 Subject: [PATCH 13/14] remove duplicate import --- gatsby-node.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/gatsby-node.js b/gatsby-node.js index 25396fb..7ffede0 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -7,8 +7,6 @@ const { resolveToArray, resolveSlug, resolveSoftwareTools, - resolveSlug, - resolveSoftwareTools, } = require("./gatsbyutils/gatsby-resolver-utils"); const { DATASET_PATH } = require("./gatsbyutils/constants"); From f211c7d85e3a4881bf4df443e74e83f5e895c95e Mon Sep 17 00:00:00 2001 From: Joe Heffernan Date: Mon, 23 Feb 2026 13:25:32 -0800 Subject: [PATCH 14/14] fix gatsby paths --- gatsby-node.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gatsby-node.js b/gatsby-node.js index 8ccc58a..7a1404e 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -7,8 +7,8 @@ const { resolveToArray, resolveSlug, resolveSoftwareTools, -} = require('./gatsbyutils/gatsby-resolver-utils') -const { DATASET_PATH } = require('./gatsbyutils/constants') +} = require('./gatsby/utils/gatsby-resolver-utils') +const { DATASET_PATH } = require('./gatsby/constants') const read = (p) => fs.readFileSync(path.join(__dirname, p), 'utf8')