The Node.js® Website

major: full dynamic pages and plain next.js (#5426)

* feat: introduce dynamic rendering of pages

* major: full dynamic pages and plain next.js (#2)

* chore: do not resort blog posts

* fix: sort by post date

* chore: apply code-review changes

Co-authored-by: Brian Muenzenmeyer <brian.muenzenmeyer@gmail.com>
Signed-off-by: Claudio Wunder <cwunder@gnome.org>

* chore: some code review changes

---------

Signed-off-by: Claudio Wunder <cwunder@gnome.org>
Co-authored-by: Brian Muenzenmeyer <brian.muenzenmeyer@gmail.com>

authored by Claudio Wunder Brian Muenzenmeyer and committed by GitHub 2dc6293a 6e335137

+8 -8
.github/ISSUE_TEMPLATE/01-bug-report.yml
··· 1 name: Report a Technical/Visual Issue on the Node.js Website 2 - description: "Is something not working as expected? Did you encounter a glitch or a bug with the Website?" 3 labels: [bug] 4 body: 5 - type: markdown ··· 11 for us to fix it when you attach a screenshot as well. 12 - type: input 13 attributes: 14 - label: "URL:" 15 description: The URL of the page you are reporting an issue on. 16 placeholder: https://nodejs.org/en/ 17 validations: 18 required: true 19 - type: input 20 attributes: 21 - label: "Browser Name:" 22 description: What kind of browser are you using? 23 placeholder: Chrome 24 validations: 25 required: true 26 - type: input 27 attributes: 28 - label: "Browser Version:" 29 description: What version of browser are you using? 30 - placeholder: "103.0.5060.134" 31 validations: 32 required: true 33 - type: input 34 attributes: 35 - label: "Operating System:" 36 description: What kind of operation system are you using 37 (Write it in full, with version number)? 38 - placeholder: "Windows 10, 21H2, 19044.1826" 39 validations: 40 required: true 41 - type: textarea 42 attributes: 43 - label: "How to reproduce the issue:" 44 placeholder: | 45 1. What I did. 46 2. What I expected to happen.
··· 1 name: Report a Technical/Visual Issue on the Node.js Website 2 + description: 'Is something not working as expected? Did you encounter a glitch or a bug with the Website?' 3 labels: [bug] 4 body: 5 - type: markdown ··· 11 for us to fix it when you attach a screenshot as well. 12 - type: input 13 attributes: 14 + label: 'URL:' 15 description: The URL of the page you are reporting an issue on. 16 placeholder: https://nodejs.org/en/ 17 validations: 18 required: true 19 - type: input 20 attributes: 21 + label: 'Browser Name:' 22 description: What kind of browser are you using? 23 placeholder: Chrome 24 validations: 25 required: true 26 - type: input 27 attributes: 28 + label: 'Browser Version:' 29 description: What version of browser are you using? 30 + placeholder: '103.0.5060.134' 31 validations: 32 required: true 33 - type: input 34 attributes: 35 + label: 'Operating System:' 36 description: What kind of operation system are you using 37 (Write it in full, with version number)? 38 + placeholder: 'Windows 10, 21H2, 19044.1826' 39 validations: 40 required: true 41 - type: textarea 42 attributes: 43 + label: 'How to reproduce the issue:' 44 placeholder: | 45 1. What I did. 46 2. What I expected to happen.
+1 -1
.github/ISSUE_TEMPLATE/02-feature-request.yml
··· 1 name: Suggest a new feature or improvement for the Node.js Website 2 - description: "Do you have an idea or a suggestion and you want to share?" 3 labels: [feature request] 4 body: 5 - type: markdown
··· 1 name: Suggest a new feature or improvement for the Node.js Website 2 + description: 'Do you have an idea or a suggestion and you want to share?' 3 labels: [feature request] 4 body: 5 - type: markdown
+2 -2
.github/ISSUE_TEMPLATE/config.yml
··· 2 contact_links: 3 - name: Report an API Docs Issue on the Node.js Website 4 url: https://github.com/nodejs/node/issues/new?assignees=&labels=doc&template=3-api-ref-docs-problem.yml 5 - about: "Is something wrong with the API Docs? Did you face a bug with the API Docs?" 6 - name: Report a Translation Issue on the Node.js Website 7 url: https://crowdin.com/project/nodejs-website 8 - about: "Is something wrong in a specific translation? Do you believe a language can get improved? Do you have suggestions?" 9 - name: Need help with Node.js? 10 url: https://github.com/nodejs/help/issues/ 11 about: "Struggling with Node.js? You're not sure how to code?"
··· 2 contact_links: 3 - name: Report an API Docs Issue on the Node.js Website 4 url: https://github.com/nodejs/node/issues/new?assignees=&labels=doc&template=3-api-ref-docs-problem.yml 5 + about: 'Is something wrong with the API Docs? Did you face a bug with the API Docs?' 6 - name: Report a Translation Issue on the Node.js Website 7 url: https://crowdin.com/project/nodejs-website 8 + about: 'Is something wrong in a specific translation? Do you believe a language can get improved? Do you have suggestions?' 9 - name: Need help with Node.js? 10 url: https://github.com/nodejs/help/issues/ 11 about: "Struggling with Node.js? You're not sure how to code?"
+2 -2
.github/workflows/pull-request.yml
··· 60 os: [ubuntu-latest, windows-latest] 61 62 steps: 63 - - name: "Use GNU tar instead BSD tar" 64 if: matrix.os == 'windows-latest' 65 shell: cmd 66 run: echo C:\Program Files\Git\usr\bin>>"%GITHUB_PATH%" ··· 122 os: [ubuntu-latest, windows-latest] 123 124 steps: 125 - - name: "Use GNU tar instead BSD tar" 126 if: matrix.os == 'windows-latest' 127 shell: cmd 128 run: echo C:\Program Files\Git\usr\bin>>"%GITHUB_PATH%"
··· 60 os: [ubuntu-latest, windows-latest] 61 62 steps: 63 + - name: 'Use GNU tar instead BSD tar' 64 if: matrix.os == 'windows-latest' 65 shell: cmd 66 run: echo C:\Program Files\Git\usr\bin>>"%GITHUB_PATH%" ··· 122 os: [ubuntu-latest, windows-latest] 123 124 steps: 125 + - name: 'Use GNU tar instead BSD tar' 126 if: matrix.os == 'windows-latest' 127 shell: cmd 128 run: echo C:\Program Files\Git\usr\bin>>"%GITHUB_PATH%"
-1
.gitignore
··· 16 public/robots.txt 17 public/sitemap.xml 18 public/en/feed/*.xml 19 - pages/en/blog/year-[0-9][0-9][0-9][0-9].md 20 21 # Jest 22 coverage
··· 16 public/robots.txt 17 public/sitemap.xml 18 public/en/feed/*.xml 19 20 # Jest 21 coverage
+6
.husky/pre-commit
··· 3 4 DIR=$(cd `dirname $0` && pwd -P) 5 6 echo "[]" > $DIR/../public/node-releases-data.json 7 8 git add --sparse $DIR/../public/node-releases-data.json
··· 3 4 DIR=$(cd `dirname $0` && pwd -P) 5 6 + # resets the node release data file 7 echo "[]" > $DIR/../public/node-releases-data.json 8 9 + # resets the blog post data file 10 + echo "{\"pagination\": [],\"categories\": [],\"posts\": []}" > $DIR/../public/blog-posts-data.json 11 + 12 + # adds these changes to be part of the current commit 13 git add --sparse $DIR/../public/node-releases-data.json 14 + git add --sparse $DIR/../public/blog-posts-data.json
+5 -14
.storybook/preview.tsx
··· 1 import type { Preview } from '@storybook/react'; 2 import NextImage from 'next/image'; 3 - import { ThemeProvider } from 'next-themes'; 4 - import { NodeReleasesProvider } from '../providers/nodeReleasesProvider'; 5 - import { LocaleProvider } from '../providers/localeProvider'; 6 import { openSans } from '../util/nextFonts'; 7 - import BaseApp, { setAppFont } from '../next.app'; 8 9 import '../styles/index.scss'; 10 ··· 26 }, 27 }; 28 29 - setAppFont(openSans.style.fontFamily); 30 31 export const decorators = [ 32 Story => ( 33 <BaseApp> 34 - <ThemeProvider> 35 - <LocaleProvider> 36 - <NodeReleasesProvider> 37 - <div data-test-id="story-root"> 38 - <Story /> 39 - </div> 40 - </NodeReleasesProvider> 41 - </LocaleProvider> 42 - </ThemeProvider> 43 </BaseApp> 44 ), 45 ];
··· 1 import type { Preview } from '@storybook/react'; 2 import NextImage from 'next/image'; 3 import { openSans } from '../util/nextFonts'; 4 + import BaseApp, { setAppFonts } from '../next.app'; 5 6 import '../styles/index.scss'; 7 ··· 23 }, 24 }; 25 26 + setAppFonts([openSans.style.fontFamily]); 27 28 export const decorators = [ 29 Story => ( 30 <BaseApp> 31 + <div data-test-id="story-root"> 32 + <Story /> 33 + </div> 34 </BaseApp> 35 ), 36 ];
+1 -1
COLLABORATOR_GUIDE.md
··· 235 [`react-intl`]: https://formatjs.io/docs/react-intl/ 236 [Next.js]: https://nextjs.org/ 237 [MDX]: https://mdxjs.com/ 238 - [SCSS]: https://sass-lang.com/
··· 235 [`react-intl`]: https://formatjs.io/docs/react-intl/ 236 [Next.js]: https://nextjs.org/ 237 [MDX]: https://mdxjs.com/ 238 + [SCSS]: https://sass-lang.com/
+54 -56
CONTRIBUTING.md
··· 32 is a formality that comes with obligations. 33 34 If you're an active contributor seeking to become a member we recommend reaching out to one of the existing Team Members for guidance. 35 - 36 <details> 37 <summary><b>What's the process for becoming a Collaborator?</b></summary> 38 39 - - You must be actively contributing to this repository. 40 - - Contributions must include significant code reviews or code contributions. 41 - - A nomination must be done by an existing Team Member of the Website Team with an Issue 42 - - The Issue must explain and describe why the nominated person is a good addition to the team 43 - - The Issue must contain links to relevant contributions through: 44 - - Code Reviews 45 - - Comments on Issues and PRs 46 - - Authoring of PRs or Issues 47 - - Comments or Authoring of Discussions 48 - - The nomination must have at least 3 existing members of the Website Team to be in agreement with the nomination. 49 - - This can be done through commenting with "agreement" (showing support) or reacting to the Issue with a :+1: (Thumbs-up Emoji) 50 - - The Issue must be open for at least 72 hours without an objection from an existing member of the Website Team 51 - - The nomination cannot pass until all open discordances/objections are resolved. 52 - - Objections coming from the TSC or Core Collaborators are also counted as valid objections. 53 </details> 54 55 # Getting started ··· 60 1. Click the fork button in the top right to clone the [nodejs.org repository](https://github.com/nodejs/nodejs.org/fork) 61 2. Clone your fork using SSH, GitHub CLI, or HTTPS. 62 63 - ```bash 64 - git clone git@github.com:<YOUR_GITHUB_USERNAME>/nodejs.org.git # SSH 65 - git clone https://github.com/<GITHUB_ID>/nodejs.org.git # HTTPS 66 - gh repo clone <GITHUB_ID>/nodejs.org # GitHub CLI 67 - ``` 68 69 3. Change into the nodejs.org directory. 70 71 - ```bash 72 - cd nodejs.org 73 - ``` 74 75 4. Create a remote for keeping your fork as well as your local clone up-to-date. 76 77 - ```bash 78 - git remote add upstream git@github.com:nodejs/nodejs.org.git # SSH 79 - git remote add upstream https://github.com/nodejs/nodejs.org.git # HTTPS 80 - gh repo sync nodejs/nodejs.org # GitHub CLI 81 - ``` 82 83 5. Create a new branch for your work. 84 85 - ```bash 86 - git checkout -b name-of-your-branch 87 - ``` 88 89 6. Run the following to install the dependencies and start a local preview of your work. 90 91 - ```bash 92 - npm ci # installs this project's dependencies 93 - npx turbo serve # starts a preview of your local changes 94 - ``` 95 96 7. Perform a merge to sync your current branch with the upstream branch. 97 98 - ```bash 99 - git fetch upstream 100 - git merge upstream/main 101 - ``` 102 103 8. Run `npx turbo format` to confirm that linting, and formatting are passing. 104 105 - ```bash 106 - npx turbo format 107 - ``` 108 109 - 9. Once you're happy with your changes, add and commit them to your branch, then push the branch to your fork. 110 111 - ```bash 112 - cd ~/nodejs.org 113 - git add . 114 - git commit -m "some message" 115 - git push -u origin name-of-your-branch 116 - ``` 117 118 10. Create a Pull Request. 119 ··· 126 <details> 127 <summary>Commands for Running & Building the Website</summary> 128 129 - - `npx turbo serve` runs Next.js's Local Development Server, listening by default on `http://localhost:3000/`. 130 - - `npx turbo build` builds the Application on Production mode. The output is by default within `.next` folder. 131 - - This is used for the Node.js Vercel Deployments (Preview & Production) 132 - - `npx turbo deploy` builds the Application on Export Production Mode. The output is by default within `build` folder. 133 - - This is used for the Node.js Legacy Website Server (DigitalOcean) 134 - - `npx turbo start` starts a web server running serving the built content from `npx turbo build` 135 </details> 136 137 <details> ··· 186 - The person that is fast-tracking the PR (adding the label) must also comment on the PR that they're requesting the PR to be fast-tracked 187 - The comment must mention `@nodejs/website` and must have at least one 👍 (or any other sort of approval reaction) if the person fast-tracking the PR is the author of the PR. 188 - Fast-tracking is only allowed for small bug fixes, small feature changes, localisation changes, or other sorts of non-critical/highly-impacting changes that are not covered by the previous rule that allows PRs to be merged immediately. 189 - - Fast-tracking cannot be used for updates on the `COLLABORATOR_GUIDE.md`, CONTRIBUTING.md` guide, `CODEOWNERS`, GitHub Actions or any security-impacting file or document that changes the governing policies of this repository. 190 - There must be no objections after a 48-hour period (Or 72 hours if the PR was authored on the weekend). 191 - At least one approval is required for any PR to be merged. 192 - Tests must be included in Pull Requests for new features or bug fixes. If any test(s) are failing, you are responsible for fixing them.
··· 32 is a formality that comes with obligations. 33 34 If you're an active contributor seeking to become a member we recommend reaching out to one of the existing Team Members for guidance. 35 + 36 <details> 37 <summary><b>What's the process for becoming a Collaborator?</b></summary> 38 39 + - You must be actively contributing to this repository. 40 + - Contributions must include significant code reviews or code contributions. 41 + - A nomination must be done by an existing Team Member of the Website Team with an Issue 42 + - The Issue must explain and describe why the nominated person is a good addition to the team 43 + - The Issue must contain links to relevant contributions through: 44 + - Code Reviews 45 + - Comments on Issues and PRs 46 + - Authoring of PRs or Issues 47 + - Comments or Authoring of Discussions 48 + - The nomination must have at least 3 existing members of the Website Team to be in agreement with the nomination. 49 + - This can be done through commenting with "agreement" (showing support) or reacting to the Issue with a :+1: (Thumbs-up Emoji) 50 + - The Issue must be open for at least 72 hours without an objection from an existing member of the Website Team - The nomination cannot pass until all open discordances/objections are resolved. - Objections coming from the TSC or Core Collaborators are also counted as valid objections. 51 </details> 52 53 # Getting started ··· 58 1. Click the fork button in the top right to clone the [nodejs.org repository](https://github.com/nodejs/nodejs.org/fork) 59 2. Clone your fork using SSH, GitHub CLI, or HTTPS. 60 61 + ```bash 62 + git clone git@github.com:<YOUR_GITHUB_USERNAME>/nodejs.org.git # SSH 63 + git clone https://github.com/<YOUR_GITHUB_USERNAME>/nodejs.org.git # HTTPS 64 + gh repo clone <YOUR_GITHUB_USERNAME>/nodejs.org # GitHub CLI 65 + ``` 66 67 3. Change into the nodejs.org directory. 68 69 + ```bash 70 + cd nodejs.org 71 + ``` 72 73 4. Create a remote for keeping your fork as well as your local clone up-to-date. 74 75 + ```bash 76 + git remote add upstream git@github.com:nodejs/nodejs.org.git # SSH 77 + git remote add upstream https://github.com/nodejs/nodejs.org.git # HTTPS 78 + gh repo sync nodejs/nodejs.org # GitHub CLI 79 + ``` 80 81 5. Create a new branch for your work. 82 83 + ```bash 84 + git checkout -b name-of-your-branch 85 + ``` 86 87 6. Run the following to install the dependencies and start a local preview of your work. 88 89 + ```bash 90 + npm ci # installs this project's dependencies 91 + npx turbo serve # starts a preview of your local changes 92 + ``` 93 94 7. Perform a merge to sync your current branch with the upstream branch. 95 96 + ```bash 97 + git fetch upstream 98 + git merge upstream/main 99 + ``` 100 101 8. Run `npx turbo format` to confirm that linting, and formatting are passing. 102 103 + ```bash 104 + npx turbo format 105 + ``` 106 107 + 9. Once you're happy with your changes, add and commit them to your branch, then push the branch to your fork. 108 109 + ```bash 110 + cd ~/nodejs.org 111 + git add . 112 + git commit -m "some message" 113 + git push -u origin name-of-your-branch 114 + ``` 115 116 10. Create a Pull Request. 117 ··· 124 <details> 125 <summary>Commands for Running & Building the Website</summary> 126 127 + - `npx turbo serve` runs Next.js's Local Development Server, listening by default on `http://localhost:3000/`. 128 + - `npx turbo build` builds the Application on Production mode. The output is by default within `.next` folder. 129 + - This is used for the Node.js Vercel Deployments (Preview & Production) 130 + - `npx turbo deploy` builds the Application on Export Production Mode. The output is by default within `build` folder. 131 + - This is used for the Node.js Legacy Website Server (DigitalOcean) 132 + - `npx turbo start` starts a web server running serving the built content from `npx turbo build` 133 </details> 134 135 <details> ··· 184 - The person that is fast-tracking the PR (adding the label) must also comment on the PR that they're requesting the PR to be fast-tracked 185 - The comment must mention `@nodejs/website` and must have at least one 👍 (or any other sort of approval reaction) if the person fast-tracking the PR is the author of the PR. 186 - Fast-tracking is only allowed for small bug fixes, small feature changes, localisation changes, or other sorts of non-critical/highly-impacting changes that are not covered by the previous rule that allows PRs to be merged immediately. 187 + - Fast-tracking cannot be used for updates on the `COLLABORATOR_GUIDE.md`, `CONTRIBUTING.md` guide, `CODEOWNERS`, GitHub Actions, or any security-impacting file or document that changes the governing policies of this repository. 188 - There must be no objections after a 48-hour period (Or 72 hours if the PR was authored on the weekend). 189 - At least one approval is required for any PR to be merged. 190 - Tests must be included in Pull Requests for new features or bug fixes. If any test(s) are failing, you are responsible for fixing them.
+2 -2
README.md
··· 9 </p> 10 11 <p align="center"> 12 - <a href="https://nodejs.org">nodejs.org</a> website built using Nextra (Next.js) with TypeScript, SCSS and MDXv2 13 </p> 14 15 <p align="center"> ··· 31 32 ## What is this repo? 33 34 - [Nodejs.org](https://nodejs.org/) by the [OpenJS Foundation](https://openjsf.org/) is the official website for the Node.js® JavaScript runtime. This repo is the source code for the website. It is build using [Nextra](https://nextra.site), a Next.js based static site generator. 35 36 ### Quick-Start Locally 37
··· 9 </p> 10 11 <p align="center"> 12 + <a href="https://nodejs.org">nodejs.org</a> website built using Next.js with TypeScript, SCSS and MDXv2 13 </p> 14 15 <p align="center"> ··· 31 32 ## What is this repo? 33 34 + [Nodejs.org](https://nodejs.org/) by the [OpenJS Foundation](https://openjsf.org/) is the official website for the Node.js® JavaScript runtime. This repo is the source code for the website. It is build using [Next.js](https://nextjs.org) a React Framework. 35 36 ### Quick-Start Locally 37
+21
app/en/feed/[feed]/route.ts
···
··· 1 + import { basename } from 'node:path'; 2 + import { NextResponse } from 'next/server'; 3 + import * as nextJson from '@/next.json.mjs'; 4 + import * as nextData from '@/next-data/index.mjs'; 5 + 6 + // loads all the data from the blog-posts-data.json file 7 + const websiteFeeds = nextData.generateWebsiteFeeds(nextJson.blogData); 8 + 9 + export async function GET(request: Request) { 10 + const { pathname } = new URL(request.url); 11 + 12 + const feed = basename(pathname); 13 + 14 + if (websiteFeeds.has(feed)) { 15 + return new NextResponse(websiteFeeds.get(feed)?.rss2(), { 16 + headers: { 'Content-Type': 'application/xml' }, 17 + }); 18 + } 19 + 20 + return new NextResponse(null, { status: 404 }); 21 + }
+1 -1
components/Blog/BlogCard/index.tsx
··· 8 const getBlogCategoryUrl = (category: string): string => 9 `${navigation.blog.link}/${category}/`; 10 11 - type BlogCardProps = Omit<BlogPost, 'file'>; 12 13 const BlogCard: FC<BlogCardProps> = ({ 14 title,
··· 8 const getBlogCategoryUrl = (category: string): string => 9 `${navigation.blog.link}/${category}/`; 10 11 + type BlogCardProps = BlogPost & { readingTime: string }; 12 13 const BlogCard: FC<BlogCardProps> = ({ 14 title,
+3 -3
components/Downloads/PrimaryDownloadMatrix.tsx
··· 2 import semVer from 'semver'; 3 import LocalizedLink from '../LocalizedLink'; 4 import { useDetectOS } from '../../hooks/useDetectOS'; 5 - import { useNextraContext } from '../../hooks/useNextraContext'; 6 import type { LegacyDownloadsFrontMatter, NodeRelease } from '../../types'; 7 import type { FC } from 'react'; 8 ··· 14 isLts, 15 npm, 16 }) => { 17 - const nextraContext = useNextraContext(); 18 19 const { bitness } = useDetectOS(); 20 21 - const { downloads } = nextraContext.frontMatter as LegacyDownloadsFrontMatter; 22 const hasWindowsArm64 = semVer.satisfies(version, '>= 19.9.0'); 23 24 const getIsVersionClassName = (isCurrent: boolean) =>
··· 2 import semVer from 'semver'; 3 import LocalizedLink from '../LocalizedLink'; 4 import { useDetectOS } from '../../hooks/useDetectOS'; 5 + import { useLayoutContext } from '../../hooks/useLayoutContext'; 6 import type { LegacyDownloadsFrontMatter, NodeRelease } from '../../types'; 7 import type { FC } from 'react'; 8 ··· 14 isLts, 15 npm, 16 }) => { 17 + const { frontMatter } = useLayoutContext(); 18 19 const { bitness } = useDetectOS(); 20 21 + const { downloads } = frontMatter as LegacyDownloadsFrontMatter; 22 const hasWindowsArm64 = semVer.satisfies(version, '>= 19.9.0'); 23 24 const getIsVersionClassName = (isCurrent: boolean) =>
+3 -4
components/Downloads/SecondaryDownloadMatrix.tsx
··· 1 import DownloadList from './DownloadList'; 2 - import { useNextraContext } from '../../hooks/useNextraContext'; 3 import { WithNodeRelease } from '../../providers/withNodeRelease'; 4 import type { LegacyDownloadsFrontMatter, NodeRelease } from '../../types'; 5 import type { FC } from 'react'; ··· 10 versionWithPrefix, 11 status, 12 }) => { 13 - const nextraContext = useNextraContext(); 14 15 - const { additional } = 16 - nextraContext.frontMatter as LegacyDownloadsFrontMatter; 17 18 return ( 19 <section>
··· 1 import DownloadList from './DownloadList'; 2 + import { useLayoutContext } from '../../hooks/useLayoutContext'; 3 import { WithNodeRelease } from '../../providers/withNodeRelease'; 4 import type { LegacyDownloadsFrontMatter, NodeRelease } from '../../types'; 5 import type { FC } from 'react'; ··· 10 versionWithPrefix, 11 status, 12 }) => { 13 + const { frontMatter } = useLayoutContext(); 14 15 + const { additional } = frontMatter as LegacyDownloadsFrontMatter; 16 17 return ( 18 <section>
+9 -8
components/Home/HomeDownloadButton.tsx
··· 1 import LocalizedLink from '../LocalizedLink'; 2 import { useDetectOS } from '../../hooks/useDetectOS'; 3 - import { useNextraContext } from '../../hooks/useNextraContext'; 4 import { downloadUrlByOS } from '../../util/downloadUrlByOS'; 5 import { getNodejsChangelog } from '../../util/getNodeJsChangelog'; 6 import type { FC } from 'react'; ··· 14 }) => { 15 const { 16 frontMatter: { labels }, 17 - } = useNextraContext(); 18 19 const { os, bitness } = useDetectOS(); 20 ··· 22 const nodeApiLink = `https://nodejs.org/dist/latest-v${major}.x/docs/api/`; 23 const nodeAllDownloadsLink = `/download${isLts ? '/' : '/current'}`; 24 const nodeDownloadTitle = 25 - `${labels.download} ${version}` + ` ${labels[isLts ? 'lts' : 'current']}`; 26 27 return ( 28 <div className="home-downloadblock"> ··· 32 title={nodeDownloadTitle} 33 data-version={versionWithPrefix} 34 > 35 - {version} {labels[isLts ? 'lts' : 'current']} 36 - <small>{labels[`tagline-${isLts ? 'lts' : 'current'}`]}</small> 37 </a> 38 39 <ul className="list-divider-pipe home-secondary-links"> 40 <li> 41 <LocalizedLink href={nodeAllDownloadsLink}> 42 - {labels['other-downloads']} 43 </LocalizedLink> 44 </li> 45 <li> 46 <LocalizedLink href={getNodejsChangelog(versionWithPrefix)}> 47 - {labels.changelog} 48 </LocalizedLink> 49 </li> 50 <li> 51 - <LocalizedLink href={nodeApiLink}>{labels.api}</LocalizedLink> 52 </li> 53 </ul> 54 </div>
··· 1 import LocalizedLink from '../LocalizedLink'; 2 import { useDetectOS } from '../../hooks/useDetectOS'; 3 + import { useLayoutContext } from '../../hooks/useLayoutContext'; 4 import { downloadUrlByOS } from '../../util/downloadUrlByOS'; 5 import { getNodejsChangelog } from '../../util/getNodeJsChangelog'; 6 import type { FC } from 'react'; ··· 14 }) => { 15 const { 16 frontMatter: { labels }, 17 + } = useLayoutContext(); 18 19 const { os, bitness } = useDetectOS(); 20 ··· 22 const nodeApiLink = `https://nodejs.org/dist/latest-v${major}.x/docs/api/`; 23 const nodeAllDownloadsLink = `/download${isLts ? '/' : '/current'}`; 24 const nodeDownloadTitle = 25 + `${labels?.download} ${version}` + 26 + ` ${labels?.[isLts ? 'lts' : 'current']}`; 27 28 return ( 29 <div className="home-downloadblock"> ··· 33 title={nodeDownloadTitle} 34 data-version={versionWithPrefix} 35 > 36 + {version} {labels?.[isLts ? 'lts' : 'current']} 37 + <small>{labels?.[`tagline-${isLts ? 'lts' : 'current'}`]}</small> 38 </a> 39 40 <ul className="list-divider-pipe home-secondary-links"> 41 <li> 42 <LocalizedLink href={nodeAllDownloadsLink}> 43 + {labels?.['other-downloads']} 44 </LocalizedLink> 45 </li> 46 <li> 47 <LocalizedLink href={getNodejsChangelog(versionWithPrefix)}> 48 + {labels?.changelog} 49 </LocalizedLink> 50 </li> 51 <li> 52 + <LocalizedLink href={nodeApiLink}>{labels?.api}</LocalizedLink> 53 </li> 54 </ul> 55 </div>
+3 -3
components/Pagination.tsx
··· 2 import LocalizedLink from './LocalizedLink'; 3 import type { FC } from 'react'; 4 5 - type PaginationProps = { prevSlug?: string; nextSlug?: string }; 6 7 const Pagination: FC<PaginationProps> = ({ nextSlug, prevSlug }) => ( 8 <nav aria-label="pagination" className="pagination"> 9 {nextSlug && ( 10 - <LocalizedLink href={nextSlug}> 11 &lt; <FormattedMessage id="components.pagination.next" /> 12 </LocalizedLink> 13 )} 14 15 {prevSlug && ( 16 - <LocalizedLink href={prevSlug}> 17 <FormattedMessage id="components.pagination.previous" /> &gt; 18 </LocalizedLink> 19 )}
··· 2 import LocalizedLink from './LocalizedLink'; 3 import type { FC } from 'react'; 4 5 + type PaginationProps = { prevSlug?: number; nextSlug?: number }; 6 7 const Pagination: FC<PaginationProps> = ({ nextSlug, prevSlug }) => ( 8 <nav aria-label="pagination" className="pagination"> 9 {nextSlug && ( 10 + <LocalizedLink href={`/blog/year-${nextSlug}`}> 11 &lt; <FormattedMessage id="components.pagination.next" /> 12 </LocalizedLink> 13 )} 14 15 {prevSlug && ( 16 + <LocalizedLink href={`/blog/year-${prevSlug}`}> 17 <FormattedMessage id="components.pagination.previous" /> &gt; 18 </LocalizedLink> 19 )}
-3
global.d.ts
··· 1 declare global { 2 - // @TODO: Update this to use the correct type 3 - var __nextra_pageContext__: Record<string, any>; 4 - 5 interface Window { 6 startLegacyApp: Function; 7 }
··· 1 declare global { 2 interface Window { 3 startLegacyApp: Function; 4 }
+54
hooks/useBlogData.ts
···
··· 1 + import { useCallback, useContext, useMemo } from 'react'; 2 + import { useRouter } from './useRouter'; 3 + import { BlogDataContext } from '../providers/blogDataProvider'; 4 + 5 + export const useBlogData = () => { 6 + const { asPath } = useRouter(); 7 + 8 + const { posts, pagination, categories } = useContext(BlogDataContext); 9 + 10 + const getPostsByCategory = useCallback( 11 + (category: string) => posts.filter(post => post.category === category), 12 + [posts] 13 + ); 14 + 15 + const getPostsByYear = useCallback( 16 + (year: number) => 17 + posts.filter(post => new Date(post.date).getFullYear() === year), 18 + [posts] 19 + ); 20 + 21 + const getPagination = useCallback( 22 + (currentYear: number) => ({ 23 + next: pagination.includes(currentYear + 1) ? currentYear + 1 : undefined, 24 + prev: pagination.includes(currentYear - 1) ? currentYear - 1 : undefined, 25 + }), 26 + [pagination] 27 + ); 28 + 29 + const currentCategory = useMemo(() => { 30 + // We split the pathname to retrieve the blog category from it 31 + // since the URL is usually /{languageCode}/blog/{category} 32 + // the third path piece is usually the category name 33 + const [, , pathname, category] = asPath.split('/'); 34 + 35 + if (pathname === 'blog' && category && category.length) { 36 + return category; 37 + } 38 + 39 + // if either the pathname does not match to a blog page 40 + // which should not happen (as this hook should only be used in blog pages) 41 + // or if there is no category in the URL we return the current year as category name 42 + // which is always the default category (for example, the blog index) 43 + return new Date().getFullYear().toString(); 44 + }, [asPath]); 45 + 46 + return { 47 + posts, 48 + categories, 49 + currentCategory, 50 + getPostsByCategory, 51 + getPostsByYear, 52 + getPagination, 53 + }; 54 + };
+4
hooks/useLayoutContext.ts
···
··· 1 + import { useContext } from 'react'; 2 + import { LayoutContext } from '../providers/layoutProvider'; 3 + 4 + export const useLayoutContext = () => useContext(LayoutContext);
+6 -4
hooks/useNavigation.tsx
··· 1 import { FormattedMessage } from 'react-intl'; 2 - import navigation from '../navigation.json'; 3 - 4 import type { NavigationEntry, NavigationKeys } from '../types'; 5 6 // Translation Context for FormattedMessage ··· 33 }; 34 35 return { 36 - navigationItems: mapNavigationEntries(navigation), 37 getSideNavigation: (section: NavigationKeys, context?: Context) => 38 mapNavigationEntries( 39 // We need the parent and their items when making a side navigation 40 - { [section]: navigation[section], ...navigation[section].items }, 41 context 42 ), 43 };
··· 1 import { FormattedMessage } from 'react-intl'; 2 + import * as nextJson from '../next.json.mjs'; 3 import type { NavigationEntry, NavigationKeys } from '../types'; 4 5 // Translation Context for FormattedMessage ··· 32 }; 33 34 return { 35 + navigationItems: mapNavigationEntries(nextJson.siteNavigation), 36 getSideNavigation: (section: NavigationKeys, context?: Context) => 37 mapNavigationEntries( 38 // We need the parent and their items when making a side navigation 39 + { 40 + [section]: nextJson.siteNavigation[section], 41 + ...nextJson.siteNavigation[section].items, 42 + }, 43 context 44 ), 45 };
-8
hooks/useNextraContext.ts
··· 1 - import { useContext } from 'react'; 2 - import { LayoutContext } from '../providers/layoutProvider'; 3 - 4 - export const useNextraContext = () => { 5 - const { pageOpts, pageProps } = useContext(LayoutContext); 6 - 7 - return { ...pageOpts, ...pageProps }; 8 - };
···
+23 -9
layouts/BlogIndexLayout.tsx
··· 1 import { FormattedMessage } from 'react-intl'; 2 import BaseLayout from './BaseLayout'; 3 import Pagination from '../components/Pagination'; 4 import LocalizedLink from '../components/LocalizedLink'; 5 - import { useNextraContext } from '../hooks/useNextraContext'; 6 import { getTimeComponent } from '../util/getTimeComponent'; 7 import type { FC, PropsWithChildren } from 'react'; 8 9 const BlogIndexLayout: FC<PropsWithChildren> = ({ children }) => { 10 - const { blogData } = useNextraContext(); 11 12 - const currentYear = blogData?.currentCategory.replace('year-', ''); 13 14 return ( 15 <BaseLayout> ··· 21 /> 22 23 <ul className="blog-index"> 24 - {blogData?.posts.map(post => ( 25 <li key={post.slug}> 26 - {getTimeComponent(post.date, '%d %b')} 27 <LocalizedLink href={post.slug}>{post.title}</LocalizedLink> 28 </li> 29 ))} 30 </ul> 31 32 - <Pagination 33 - prevSlug={blogData?.pagination.prev} 34 - nextSlug={blogData?.pagination.next} 35 - /> 36 37 {children} 38 </div>
··· 1 + import { useMemo } from 'react'; 2 import { FormattedMessage } from 'react-intl'; 3 import BaseLayout from './BaseLayout'; 4 import Pagination from '../components/Pagination'; 5 import LocalizedLink from '../components/LocalizedLink'; 6 + import { useBlogData } from '../hooks/useBlogData'; 7 import { getTimeComponent } from '../util/getTimeComponent'; 8 import type { FC, PropsWithChildren } from 'react'; 9 + import type { BlogPost } from '../types'; 10 11 const BlogIndexLayout: FC<PropsWithChildren> = ({ children }) => { 12 + const { getPagination, getPostsByYear, currentCategory } = useBlogData(); 13 14 + const currentYear = useMemo( 15 + () => 16 + Number( 17 + currentCategory.startsWith('year-') 18 + ? currentCategory.replace('year-', '') 19 + : new Date().getFullYear() 20 + ), 21 + [currentCategory] 22 + ); 23 + 24 + const { posts, pagination } = useMemo(() => { 25 + return { 26 + posts: getPostsByYear(currentYear), 27 + pagination: getPagination(currentYear), 28 + }; 29 + }, [currentYear, getPagination, getPostsByYear]); 30 31 return ( 32 <BaseLayout> ··· 38 /> 39 40 <ul className="blog-index"> 41 + {posts.map((post: BlogPost) => ( 42 <li key={post.slug}> 43 + {getTimeComponent(post.date.toString(), '%d %b')} 44 <LocalizedLink href={post.slug}>{post.title}</LocalizedLink> 45 </li> 46 ))} 47 </ul> 48 49 + <Pagination prevSlug={pagination.prev} nextSlug={pagination.next} /> 50 51 {children} 52 </div>
+3 -4
layouts/BlogPostLayout.tsx
··· 1 import { FormattedMessage } from 'react-intl'; 2 import BaseLayout from './BaseLayout'; 3 - import { useNextraContext } from '../hooks/useNextraContext'; 4 import { getTimeComponent } from '../util/getTimeComponent'; 5 import type { FC, PropsWithChildren } from 'react'; 6 import type { LegacyBlogFrontMatter } from '../types'; 7 8 const BlogPostLayout: FC<PropsWithChildren> = ({ children }) => { 9 - const nextraContext = useNextraContext(); 10 11 - const { title, author, date } = 12 - nextraContext.frontMatter as LegacyBlogFrontMatter; 13 14 return ( 15 <BaseLayout>
··· 1 import { FormattedMessage } from 'react-intl'; 2 import BaseLayout from './BaseLayout'; 3 + import { useLayoutContext } from '../hooks/useLayoutContext'; 4 import { getTimeComponent } from '../util/getTimeComponent'; 5 import type { FC, PropsWithChildren } from 'react'; 6 import type { LegacyBlogFrontMatter } from '../types'; 7 8 const BlogPostLayout: FC<PropsWithChildren> = ({ children }) => { 9 + const { frontMatter } = useLayoutContext(); 10 11 + const { title, author, date } = frontMatter as LegacyBlogFrontMatter; 12 13 return ( 14 <BaseLayout>
+13 -4
layouts/CategoryIndexLayout.tsx
··· 1 import BaseLayout from './BaseLayout'; 2 import LocalizedLink from '../components/LocalizedLink'; 3 - import { useNextraContext } from '../hooks/useNextraContext'; 4 import { getTimeComponent } from '../util/getTimeComponent'; 5 import type { FC, PropsWithChildren } from 'react'; 6 7 const CategoryIndexLayout: FC<PropsWithChildren> = ({ children }) => { 8 - const { blogData, frontMatter } = useNextraContext(); 9 10 return ( 11 <BaseLayout> ··· 13 <h2>{frontMatter.title}</h2> 14 15 <ul className="blog-index"> 16 - {blogData?.posts.map(post => ( 17 <li key={post.slug}> 18 - {getTimeComponent(post.date, '%d %b %y')} 19 <LocalizedLink href={post.slug}>{post.title}</LocalizedLink> 20 </li> 21 ))}
··· 1 + import { useMemo } from 'react'; 2 import BaseLayout from './BaseLayout'; 3 import LocalizedLink from '../components/LocalizedLink'; 4 + import { useLayoutContext } from '../hooks/useLayoutContext'; 5 + import { useBlogData } from '../hooks/useBlogData'; 6 import { getTimeComponent } from '../util/getTimeComponent'; 7 import type { FC, PropsWithChildren } from 'react'; 8 + import type { BlogPost } from '../types'; 9 10 const CategoryIndexLayout: FC<PropsWithChildren> = ({ children }) => { 11 + const { frontMatter } = useLayoutContext(); 12 + const { getPostsByCategory, currentCategory } = useBlogData(); 13 + 14 + const posts = useMemo( 15 + () => getPostsByCategory(currentCategory), 16 + [currentCategory, getPostsByCategory] 17 + ); 18 19 return ( 20 <BaseLayout> ··· 22 <h2>{frontMatter.title}</h2> 23 24 <ul className="blog-index"> 25 + {posts.map((post: BlogPost) => ( 26 <li key={post.slug}> 27 + {getTimeComponent(post.date.toString(), '%d %b %y')} 28 <LocalizedLink href={post.slug}>{post.title}</LocalizedLink> 29 </li> 30 ))}
+3 -3
layouts/DownloadCurrentLayout.tsx
··· 1 import BaseLayout from './BaseLayout'; 2 import PrimaryDownloadMatrix from '../components/Downloads/PrimaryDownloadMatrix'; 3 import SecondaryDownloadMatrix from '../components/Downloads/SecondaryDownloadMatrix'; 4 - import { useNextraContext } from '../hooks/useNextraContext'; 5 import { WithNodeRelease } from '../providers/withNodeRelease'; 6 import type { FC, PropsWithChildren } from 'react'; 7 import type { LegacyDownloadsFrontMatter } from '../types'; 8 9 const DownloadCurrentLayout: FC<PropsWithChildren> = ({ children }) => { 10 - const nextraContext = useNextraContext(); 11 12 - const { downloads } = nextraContext.frontMatter as LegacyDownloadsFrontMatter; 13 14 return ( 15 <BaseLayout>
··· 1 import BaseLayout from './BaseLayout'; 2 import PrimaryDownloadMatrix from '../components/Downloads/PrimaryDownloadMatrix'; 3 import SecondaryDownloadMatrix from '../components/Downloads/SecondaryDownloadMatrix'; 4 + import { useLayoutContext } from '../hooks/useLayoutContext'; 5 import { WithNodeRelease } from '../providers/withNodeRelease'; 6 import type { FC, PropsWithChildren } from 'react'; 7 import type { LegacyDownloadsFrontMatter } from '../types'; 8 9 const DownloadCurrentLayout: FC<PropsWithChildren> = ({ children }) => { 10 + const { frontMatter } = useLayoutContext(); 11 12 + const { downloads } = frontMatter as LegacyDownloadsFrontMatter; 13 14 return ( 15 <BaseLayout>
+3 -3
layouts/DownloadLayout.tsx
··· 1 import BaseLayout from './BaseLayout'; 2 import PrimaryDownloadMatrix from '../components/Downloads/PrimaryDownloadMatrix'; 3 import SecondaryDownloadMatrix from '../components/Downloads/SecondaryDownloadMatrix'; 4 - import { useNextraContext } from '../hooks/useNextraContext'; 5 import { WithNodeRelease } from '../providers/withNodeRelease'; 6 import type { FC, PropsWithChildren } from 'react'; 7 import type { LegacyDownloadsFrontMatter } from '../types'; 8 9 const DownloadLayout: FC<PropsWithChildren> = ({ children }) => { 10 - const nextraContext = useNextraContext(); 11 12 - const { downloads } = nextraContext.frontMatter as LegacyDownloadsFrontMatter; 13 14 return ( 15 <BaseLayout>
··· 1 import BaseLayout from './BaseLayout'; 2 import PrimaryDownloadMatrix from '../components/Downloads/PrimaryDownloadMatrix'; 3 import SecondaryDownloadMatrix from '../components/Downloads/SecondaryDownloadMatrix'; 4 + import { useLayoutContext } from '../hooks/useLayoutContext'; 5 import { WithNodeRelease } from '../providers/withNodeRelease'; 6 import type { FC, PropsWithChildren } from 'react'; 7 import type { LegacyDownloadsFrontMatter } from '../types'; 8 9 const DownloadLayout: FC<PropsWithChildren> = ({ children }) => { 10 + const { frontMatter } = useLayoutContext(); 11 12 + const { downloads } = frontMatter as LegacyDownloadsFrontMatter; 13 14 return ( 15 <BaseLayout>
+3 -4
layouts/DownloadReleasesLayout.tsx
··· 1 import { useMemo } from 'react'; 2 import { sanitize } from 'isomorphic-dompurify'; 3 import BaseLayout from './BaseLayout'; 4 - import { useNextraContext } from '../hooks/useNextraContext'; 5 import DownloadReleasesTable from '../components/Downloads/DownloadReleasesTable'; 6 import type { FC, PropsWithChildren } from 'react'; 7 import type { LegacyDownloadsReleasesFrontMatter } from '../types'; 8 9 const DownloadReleasesLayout: FC<PropsWithChildren> = ({ children }) => { 10 - const nextraContext = useNextraContext(); 11 12 - const { modules, title } = 13 - nextraContext.frontMatter as LegacyDownloadsReleasesFrontMatter; 14 15 // @TODO: Remove this once we migrate to `nodejs/nodejs.dev` codebase as this is unsafe 16 // And completely not recommended
··· 1 import { useMemo } from 'react'; 2 import { sanitize } from 'isomorphic-dompurify'; 3 import BaseLayout from './BaseLayout'; 4 + import { useLayoutContext } from '../hooks/useLayoutContext'; 5 import DownloadReleasesTable from '../components/Downloads/DownloadReleasesTable'; 6 import type { FC, PropsWithChildren } from 'react'; 7 import type { LegacyDownloadsReleasesFrontMatter } from '../types'; 8 9 const DownloadReleasesLayout: FC<PropsWithChildren> = ({ children }) => { 10 + const { frontMatter } = useLayoutContext(); 11 12 + const { modules, title } = frontMatter as LegacyDownloadsReleasesFrontMatter; 13 14 // @TODO: Remove this once we migrate to `nodejs/nodejs.dev` codebase as this is unsafe 15 // And completely not recommended
+6 -5
layouts/IndexLayout.tsx
··· 2 import Banner from '../components/Home/Banner'; 3 import HomeDownloadButton from '../components/Home/HomeDownloadButton'; 4 import { useDetectOS } from '../hooks/useDetectOS'; 5 - import { useNextraContext } from '../hooks/useNextraContext'; 6 import { WithNodeRelease } from '../providers/withNodeRelease'; 7 import type { FC, PropsWithChildren } from 'react'; 8 import type { UserOS } from '../types/userOS'; ··· 23 const IndexLayout: FC<PropsWithChildren> = ({ children }) => { 24 const { 25 frontMatter: { labels }, 26 - } = useNextraContext(); 27 28 const { os, bitness } = useDetectOS(); 29 30 const downloadHeadTextPrefix = 31 - os === 'OTHER' ? labels['download'] : labels['download-for']; 32 const downloadHeadText = `${downloadHeadTextPrefix}${getDownloadHeadTextOS( 33 os, 34 bitness ··· 53 </WithNodeRelease> 54 55 <p> 56 - {labels['version-schedule-prompt']}{' '} 57 <a href="https://github.com/nodejs/release#release-schedule"> 58 - {labels['version-schedule-prompt-link-text']} 59 </a> 60 . 61 </p>
··· 2 import Banner from '../components/Home/Banner'; 3 import HomeDownloadButton from '../components/Home/HomeDownloadButton'; 4 import { useDetectOS } from '../hooks/useDetectOS'; 5 + import { useLayoutContext } from '../hooks/useLayoutContext'; 6 import { WithNodeRelease } from '../providers/withNodeRelease'; 7 import type { FC, PropsWithChildren } from 'react'; 8 import type { UserOS } from '../types/userOS'; ··· 23 const IndexLayout: FC<PropsWithChildren> = ({ children }) => { 24 const { 25 frontMatter: { labels }, 26 + } = useLayoutContext(); 27 28 const { os, bitness } = useDetectOS(); 29 30 const downloadHeadTextPrefix = 31 + os === 'OTHER' ? labels?.['download'] : labels?.['download-for']; 32 + 33 const downloadHeadText = `${downloadHeadTextPrefix}${getDownloadHeadTextOS( 34 os, 35 bitness ··· 54 </WithNodeRelease> 55 56 <p> 57 + {labels?.['version-schedule-prompt']}{' '} 58 <a href="https://github.com/nodejs/release#release-schedule"> 59 + {labels?.['version-schedule-prompt-link-text']} 60 </a> 61 . 62 </p>
-1
layouts/New/.gitkeep
··· 1 - !.gitignore
···
-1
middleware.ts
··· 4 const nextMiddleware = createMiddleware(NextResponse); 5 6 const { middleware, matcher } = nextMiddleware([ 7 - // eslint-disable-next-line @typescript-eslint/no-var-requires 8 require('./middlewares/detectLanguage').default, 9 ]); 10
··· 4 const nextMiddleware = createMiddleware(NextResponse); 5 6 const { middleware, matcher } = nextMiddleware([ 7 require('./middlewares/detectLanguage').default, 8 ]); 9
+79
next-data/generateBlogPostsData.mjs
···
··· 1 + 'use strict'; 2 + 3 + import { readFile, writeFile } from 'node:fs/promises'; 4 + import { basename, dirname, extname, join } from 'node:path'; 5 + import graymatter from 'gray-matter'; 6 + import * as helpers from './helpers.mjs'; 7 + 8 + // gets the current blog path based on local module path 9 + const blogPath = join(process.cwd(), 'pages/en/blog'); 10 + 11 + // this is the destination path for where the JSON file will be written 12 + const jsonFilePath = join(process.cwd(), 'public/blog-posts-data.json'); 13 + 14 + /** 15 + * This contains the metadata of all available blog categories and 16 + * available pagination entries (years) 17 + * 18 + * @type {{ pagination: Set<number>; categories: Set<string>}} 19 + */ 20 + const blogMetadata = { pagination: new Set(), categories: new Set() }; 21 + 22 + /** 23 + * This method parses the source (raw) Markdown content into Frontmatter 24 + * and returns basic information for blog posts 25 + * 26 + * @param {string} filename the filename related to the blogpost 27 + * @param {string} source the source markdown content of the blog post 28 + */ 29 + const getFrontMatter = (filename, source) => { 30 + const { 31 + title = 'Untitled', 32 + author = 'The Node.js Project', 33 + date = new Date(), 34 + category = 'uncategorized', 35 + } = graymatter(source).data; 36 + 37 + // we add the year to the pagination set 38 + blogMetadata.pagination.add(new Date(date).getFullYear()); 39 + 40 + // we add the category to the categories set 41 + blogMetadata.categories.add(category); 42 + 43 + // this is the url used for the blog post it based on the category and filename 44 + const slug = `/blog/${category}/${basename(filename, extname(filename))}`; 45 + 46 + return { title, author, date, category, slug }; 47 + }; 48 + 49 + /** 50 + * This method is used to generate the JSON file 51 + */ 52 + const generateBlogPostsData = async () => { 53 + // we retrieve all the filenames of all blog posts 54 + const filenames = await helpers.getMarkdownFiles( 55 + process.cwd(), 56 + 'pages/en/blog', 57 + ['**/index.md', '**/pagination.md'] 58 + ); 59 + 60 + // we gather all the information of all the blog posts by reading each individual file 61 + // and then parsing the frontmatter and source content and returning a minified object 62 + const postsPromise = filenames 63 + .map(name => ({ name, file: readFile(join(blogPath, name)) })) 64 + .map(({ name, file }) => file.then(source => getFrontMatter(name, source))); 65 + 66 + // we await for all the work to be concluded and return a nice blog posts object 67 + const posts = await Promise.all(postsPromise); 68 + 69 + return writeFile( 70 + jsonFilePath, 71 + JSON.stringify({ 72 + pagination: [...blogMetadata.pagination].sort(), 73 + categories: [...blogMetadata.categories].sort(), 74 + posts: posts.sort((a, b) => b.date - a.date), 75 + }) 76 + ); 77 + }; 78 + 79 + export default generateBlogPostsData;
+48
next-data/generateWebsiteFeeds.mjs
···
··· 1 + 'use strict'; 2 + 3 + import { Feed } from 'feed'; 4 + import * as nextJson from '../next.json.mjs'; 5 + import * as nextConstants from '../next.constants.mjs'; 6 + 7 + /** 8 + * This method generates RSS website feeds based on the current website configuration 9 + * and the current blog data that is available 10 + * 11 + * @param {import('../types').BlogData} blogData 12 + */ 13 + const generateWebsiteFeeds = ({ posts }) => { 14 + /** 15 + * This generates all the Website RSS Feeds that are used for the website 16 + * 17 + * @type {[string, Feed][]} 18 + */ 19 + const websiteFeeds = nextJson.siteConfig.rssFeeds.map( 20 + ({ category, title, description, file }) => { 21 + const feed = new Feed({ 22 + id: file, 23 + title: title, 24 + language: 'en', 25 + link: `${nextConstants.BASE_PATH}/en/feed/${file}`, 26 + description: description || nextJson.siteConfig.description, 27 + }); 28 + 29 + const blogFeedEntries = posts 30 + .filter(post => !category || post.category === category) 31 + .map(post => ({ 32 + id: post.slug, 33 + title: post.title, 34 + author: post.author, 35 + date: new Date(post.date), 36 + link: `${nextConstants.BASE_PATH}/en${post.slug}`, 37 + })); 38 + 39 + blogFeedEntries.forEach(entry => feed.addItem(entry)); 40 + 41 + return [file, feed]; 42 + } 43 + ); 44 + 45 + return new Map(websiteFeeds); 46 + }; 47 + 48 + export default generateWebsiteFeeds;
+60
next-data/helpers.mjs
···
··· 1 + 'use strict'; 2 + 3 + import { existsSync } from 'node:fs'; 4 + import { fileURLToPath } from 'node:url'; 5 + import { glob } from 'glob'; 6 + 7 + /** 8 + * We create a locale cache of Glob Promises 9 + * to avoid reading the file system multiple times 10 + * this is done since we don't need to constantly re-run the glob 11 + * query as it is only needed once 12 + * 13 + * @type {Map<string, Promise<string>>} */ 14 + const globCacheByPath = new Map(); 15 + 16 + export const getMatchingRoutes = (route = '', matches = []) => 17 + matches.some(match => route === match); 18 + 19 + /** 20 + * This method is responsible for reading all immediate subdirectories of a directory 21 + * 22 + * @param {string} root the root directory to search from 23 + * @param {string} cwd the current working directory 24 + * @returns {Promise<string[]>} a promise containing an array of directories 25 + */ 26 + export const getDirectories = async (root, cwd) => { 27 + return glob('*', { root, cwd, withFileTypes: true }) 28 + .then(d => d.filter(e => e.isDirectory())) 29 + .then(d => d.map(e => e.name)); 30 + }; 31 + 32 + /** 33 + * This gets the relative path from `import.meta.url` 34 + * 35 + * @param {string} path the current import path 36 + * @returns {string} the relative path from import 37 + */ 38 + export const getRelativePath = path => fileURLToPath(new URL('.', path)); 39 + 40 + /** 41 + * This method is responsible for retrieving a glob of all files that exist 42 + * within a given language directory 43 + * 44 + * Note that we ignore the blog directory for static builds as otherwise generating 45 + * that many pages would be too much for the build process to handle. 46 + * 47 + * @param {string} root the root directory to search from 48 + * @param {string} cwd the given locale code 49 + * @param {string[]} ignore an array of glob patterns to ignore 50 + * @returns {Promise<string[]>} a promise containing an array of paths 51 + */ 52 + export const getMarkdownFiles = async (root, cwd, ignore = []) => { 53 + const cacheKey = `${root}${cwd}${ignore.join('')}`; 54 + 55 + if (!globCacheByPath.has(cacheKey)) { 56 + globCacheByPath.set(cacheKey, glob('**/*.{md,mdx}', { root, cwd, ignore })); 57 + } 58 + 59 + return globCacheByPath.get(cacheKey); 60 + };
+13
next-data/index.mjs
···
··· 1 + 'use strict'; 2 + 3 + import generateWebsiteFeeds from './generateWebsiteFeeds.mjs'; 4 + import generateBlogPostsData from './generateBlogPostsData.mjs'; 5 + import generateNodeReleasesJson from './generateNodeReleasesJson.mjs'; 6 + import * as helpers from './helpers.mjs'; 7 + 8 + export { 9 + generateWebsiteFeeds, 10 + generateBlogPostsData, 11 + generateNodeReleasesJson, 12 + helpers, 13 + };
+1
next-env.d.ts
··· 1 /// <reference types="next" /> 2 /// <reference types="next/image-types/global" /> 3 4 // NOTE: This file should not be edited 5 // see https://nextjs.org/docs/basic-features/typescript for more information.
··· 1 /// <reference types="next" /> 2 /// <reference types="next/image-types/global" /> 3 + /// <reference types="next/navigation-types/compat/navigation" /> 4 5 // NOTE: This file should not be edited 6 // see https://nextjs.org/docs/basic-features/typescript for more information.
+6 -6
next-sitemap.config.mjs
··· 1 - // This is used for telling Next.js to to a Static Export Build of the Website 2 - // We use this within this config file to determine the output directory of this generated sitemap files 3 - const enableStaticExport = process.env.NEXT_STATIC_EXPORT === 'true'; 4 5 /** @type {import('next-sitemap').IConfig} */ 6 const sitemapConfig = { ··· 9 trailingSlash: false, 10 generateRobotsTxt: true, 11 generateIndexSitemap: false, 12 - outDir: enableStaticExport ? 'build' : 'public', 13 - sourceDir: enableStaticExport ? 'build' : '.next', 14 - output: enableStaticExport ? 'export' : undefined, 15 robotsTxtOptions: { 16 policies: [ 17 {
··· 1 + 'use strict'; 2 + 3 + import * as nextConstants from './next.constants.mjs'; 4 5 /** @type {import('next-sitemap').IConfig} */ 6 const sitemapConfig = { ··· 9 trailingSlash: false, 10 generateRobotsTxt: true, 11 generateIndexSitemap: false, 12 + outDir: nextConstants.ENABLE_STATIC_EXPORT ? 'build' : 'public', 13 + sourceDir: nextConstants.ENABLE_STATIC_EXPORT ? 'build' : '.next', 14 + output: nextConstants.ENABLE_STATIC_EXPORT ? 'export' : undefined, 15 robotsTxtOptions: { 16 policies: [ 17 {
+11 -3
next.app.tsx
··· 1 import { MotionConfig } from 'framer-motion'; 2 import { ThemeProvider, createTheme } from '@mui/material/styles'; 3 import { SiteProvider } from './providers/siteProvider'; 4 import type { FC, PropsWithChildren } from 'react'; 5 6 const defaultTypography = [ ··· 16 typography: { fontFamily: defaultTypography.join(',') }, 17 }); 18 19 - export const setAppFont = (font: string) => { 20 - theme.typography.fontFamily = [font, ...defaultTypography].join(','); 21 }; 22 23 const BaseApp: FC<PropsWithChildren> = ({ children }) => ( 24 <SiteProvider> 25 <MotionConfig reducedMotion="user"> 26 <ThemeProvider theme={theme}> 27 <style jsx global> 28 {` 29 body { ··· 31 } 32 `} 33 </style> 34 - {children} 35 </ThemeProvider> 36 </MotionConfig> 37 </SiteProvider>
··· 1 import { MotionConfig } from 'framer-motion'; 2 import { ThemeProvider, createTheme } from '@mui/material/styles'; 3 import { SiteProvider } from './providers/siteProvider'; 4 + import { LocaleProvider } from './providers/localeProvider'; 5 + import { BlogDataProvider } from './providers/blogDataProvider'; 6 + import { NodeReleasesProvider } from './providers/nodeReleasesProvider'; 7 import type { FC, PropsWithChildren } from 'react'; 8 9 const defaultTypography = [ ··· 19 typography: { fontFamily: defaultTypography.join(',') }, 20 }); 21 22 + export const setAppFonts = (fonts: string[]) => { 23 + theme.typography.fontFamily = [...fonts, ...defaultTypography].join(','); 24 }; 25 26 const BaseApp: FC<PropsWithChildren> = ({ children }) => ( 27 <SiteProvider> 28 <MotionConfig reducedMotion="user"> 29 <ThemeProvider theme={theme}> 30 + <NodeReleasesProvider> 31 + <BlogDataProvider> 32 + <LocaleProvider>{children}</LocaleProvider> 33 + </BlogDataProvider> 34 + </NodeReleasesProvider> 35 + 36 <style jsx global> 37 {` 38 body { ··· 40 } 41 `} 42 </style> 43 </ThemeProvider> 44 </MotionConfig> 45 </SiteProvider>
+23 -34
next.config.mjs
··· 1 - import nextra from 'nextra'; 2 - import remarkGfm from 'remark-gfm'; 3 - import getNextData from './next.data.mjs'; 4 5 - const withNextra = nextra({ 6 - theme: 'theme.tsx', 7 - flexsearch: false, 8 - codeHighlight: false, 9 - mdxOptions: { format: 'detect', remarkPlugins: [remarkGfm] }, 10 - transform: getNextData, 11 - transformPageOpts: pageOpts => { 12 - delete pageOpts.pageMap; 13 - delete pageOpts.headings; 14 - delete pageOpts.timestamp; 15 16 - return pageOpts; 17 - }, 18 - }); 19 20 - // This is used for telling Next.js to to a Static Export Build of the Website 21 - // This is used for static/without a Node.js server hosting, such as on our 22 - // legacy Website Build Environment on Node.js's DigitalOcean Droplet. 23 - // Note.: Image optimization is also disabled through this process 24 - const enableStaticExport = process.env.NEXT_STATIC_EXPORT === 'true'; 25 26 - // Supports a manuall override of the base path of the website 27 - // This is useful when running the deployment on a subdirectory 28 - // of a domain, such as when hosted on GitHub Pages. 29 - const basePath = String(process.env.NEXT_BASE_PATH || ''); 30 - 31 - export default withNextra({ 32 - basePath, 33 trailingSlash: false, 34 - outputFileTracing: false, 35 - distDir: enableStaticExport ? 'build' : '.next', 36 - output: enableStaticExport ? 'export' : undefined, 37 - images: { unoptimized: enableStaticExport }, 38 eslint: { dirs: ['.'] }, 39 - i18n: null, 40 - });
··· 1 + 'use strict'; 2 3 + import * as nextConstants from './next.constants.mjs'; 4 + import * as nextData from './next-data/index.mjs'; 5 6 + // generate the node.js releases json file 7 + await nextData.generateNodeReleasesJson(); 8 9 + // generate the data from blog posts 10 + await nextData.generateBlogPostsData(); 11 12 + /** @type {import('next').NextConfig} */ 13 + const nextConfig = { 14 + i18n: null, 15 + swcMinify: true, 16 trailingSlash: false, 17 eslint: { dirs: ['.'] }, 18 + basePath: nextConstants.BASE_PATH, 19 + images: { unoptimized: nextConstants.ENABLE_STATIC_EXPORT }, 20 + distDir: nextConstants.ENABLE_STATIC_EXPORT ? 'build' : '.next', 21 + output: nextConstants.ENABLE_STATIC_EXPORT ? 'export' : undefined, 22 + experimental: { 23 + nextScriptWorkers: true, 24 + largePageDataBytes: 128 * 100000, 25 + swcPlugins: [['next-superjson-plugin', {}]], 26 + }, 27 + }; 28 + 29 + export default nextConfig;
+102
next.constants.mjs
···
··· 1 + 'use strict'; 2 + 3 + import * as nextJson from './next.json.mjs'; 4 + import * as nextLocales from './next.locales.mjs'; 5 + 6 + /** 7 + * This is used for telling Next.js to to a Static Export Build of the Website 8 + * 9 + * This is used for static/without a Node.js server hosting, such as on our 10 + * legacy Website Build Environment on Node.js's DigitalOcean Droplet. 11 + */ 12 + export const ENABLE_STATIC_EXPORT = 13 + process.env.NEXT_STATIC_EXPORT === 'true' || 14 + process.env.NEXT_STATIC_EXPORT === true; 15 + 16 + /** 17 + * Supports a manual override of the base path of the Website 18 + * 19 + * This is useful when running the deployment on a subdirectory 20 + * of a domain, such as when hosted on GitHub Pages. 21 + */ 22 + export const BASE_PATH = String(process.env.NEXT_BASE_PATH || ''); 23 + 24 + /** 25 + * This ReGeX is used to remove the `index.md(x)` suffix of a name and to remove 26 + * the `.md(x)` extensions of a filename. 27 + * 28 + * This RegEx is used to transform the file system pathnames into acceptable 29 + * Route Segments for Next.js Dynamic Routes on `pages/[...path].tsx` 30 + */ 31 + export const MD_EXTENSION_REGEX = /((\/)?(index))?\.mdx?$/i; 32 + 33 + /** 34 + * This is a shorthand to the Default Locale if you're only interested 35 + * on the Locale Code. 36 + * 37 + * This should only be used outside of the Next.js Application itself 38 + * as within React context the `useLocale` hook should be used instead. 39 + */ 40 + export const DEFAULT_LOCALE_CODE = nextLocales.defaultLocale.code; 41 + 42 + /** 43 + * This indicates the path to the Legacy JavaScript File that is used 44 + * on the legacy Website. 45 + * 46 + * @deprecated The Legacy Website is due to be removed soon and this file 47 + * and its usages should be removed 48 + */ 49 + export const LEGACY_JAVASCRIPT_FILE = `${BASE_PATH}/static/js/legacyMain.js`; 50 + 51 + /** 52 + * This is a list of all static routes or pages from the Website that we do not 53 + * want to allow to be statically built on our Static Export Build. 54 + * 55 + * @type {((route: import('./types').RouteSegment) => boolean)[]} A list of Ignored Routes by Regular Expressions 56 + */ 57 + export const STATIC_ROUTES_IGNORES = [ 58 + // This is used to ignore is used to ignore all blog routes except for the English language 59 + route => !route.localised && /^blog\//.test(route.pathname), 60 + // This is used to ignore the blog/pagination meta route 61 + route => /^blog\/pagination/.test(route.pathname), 62 + // This is used to ignore all 404 localised routes 63 + route => /^404/.test(route.pathname), 64 + ]; 65 + 66 + /** 67 + * This is a list of all dynamic routes or pages from the Website that we do not 68 + * want to allow to be dynamically access by our Dynamic Route Engine 69 + * 70 + * @type {RegExp[]} A list of Ignored Routes by Regular Expressions 71 + */ 72 + export const DYNAMIC_ROUTES_IGNORES = [ 73 + // This is used to ignore the blog/pagination route 74 + /^blog\/pagination/, 75 + // This is used to ignore all 404 routes 76 + /^404/, 77 + ]; 78 + 79 + /** 80 + * This is a list of all static routes that we want to rewrite their pathnames 81 + * into something else. This is useful when you want to have the current pathname in the route 82 + * but replace the actual Markdown file that is being loaded by the Dynamic Route to something else 83 + * 84 + * @type {[RegexExp, (pathname: string) => string][]} 85 + */ 86 + export const DYNAMIC_ROUTES_REWRITES = [ 87 + [/^blog\/year-/, () => 'blog/pagination'], 88 + ]; 89 + 90 + /** 91 + * This is a constant that should be used during runtime by (`getStaticPaths`) on `pages/[...path].tsx` 92 + * 93 + * This function is used to provide an extra set of routes that are not provided by `next.dynamic.mjs` 94 + * static route discovery. This can happen when we have dynamic routes that **must** be provided 95 + * within the static export (static build) of the website. This constant usually would be used along 96 + * with a matching pathname on `DYNAMIC_ROUTES_REWRITES`. 97 + * 98 + * @returns {string[]} A list of all the Dynamic Routes that are generated by the Website 99 + */ 100 + export const DYNAMIC_GENERATED_ROUTES = () => [ 101 + ...nextJson.blogData.pagination.map(year => `en/blog/year-${year}`), 102 + ];
-26
next.data.mjs
··· 1 - import * as nextData from './scripts/next-data/index.mjs'; 2 - 3 - const cachedBlogData = nextData.getBlogData(); 4 - 5 - nextData.generateNodeReleasesJson(); 6 - 7 - // generates pre-build files for blog year pages (pagination) 8 - nextData.generateBlogYearPages(cachedBlogData); 9 - nextData.generateWebsiteFeeds(cachedBlogData); 10 - 11 - const getNextData = async (content, { route }) => { 12 - const blogData = await cachedBlogData(route); 13 - 14 - const staticProps = { ...blogData }; 15 - 16 - return ` 17 - // add the mdx file content 18 - ${content} 19 - 20 - export const getStaticProps = () => { 21 - return { props: ${JSON.stringify(staticProps)} }; 22 - } 23 - `; 24 - }; 25 - 26 - export default getNextData;
···
+161
next.dynamic.mjs
···
··· 1 + 'use strict'; 2 + 3 + import { join } from 'node:path'; 4 + import { readFileSync } from 'node:fs'; 5 + import remarkGfm from 'remark-gfm'; 6 + import { serialize } from 'next-mdx-remote/serialize'; 7 + import * as nextLocales from './next.locales.mjs'; 8 + import * as nextConstants from './next.constants.mjs'; 9 + import * as nextData from './next-data/index.mjs'; 10 + 11 + // allows us to run a glob to get markdown files based on a language folder 12 + const getPathsByLanguage = async ( 13 + locale = nextConstants.DEFAULT_LOCALE_CODE, 14 + ignored = [] 15 + ) => 16 + nextData.helpers.getMarkdownFiles(process.cwd(), `pages/${locale}`, ignored); 17 + 18 + /** 19 + * This method is responsible for generating a Collection of all available paths that 20 + * are served by the Website dynamically based on the Markdown pages on `pages/` folder. 21 + * 22 + * Each Collection is associated to its Locale Code and contains a subset of Dictionaries 23 + * that inform which pages are provided by that language and which not. 24 + * 25 + * The non-localised pages will still be served but our runtime Markdown loader `getMarkdownFile` 26 + * will recognise that the requested route should be provided via the fallback language. 27 + */ 28 + const getAllPaths = async () => { 29 + // during full static build we don't want to cover blog posts 30 + // as otherwise they will all get built as static pages during build time 31 + const sourcePages = await getPathsByLanguage( 32 + nextConstants.DEFAULT_LOCALE_CODE 33 + ); 34 + 35 + /** 36 + * This method is used to provide the list of pages that are provided by a given locale 37 + * and what pages require fallback to the default locale. 38 + */ 39 + const mergePathsWithFallback = 40 + (locale = '') => 41 + (files = []) => 42 + sourcePages.map(filename => { 43 + const path = filename.replace(nextConstants.MD_EXTENSION_REGEX, ''); 44 + 45 + return { 46 + pathname: path, 47 + filename: filename, 48 + localised: files.includes(filename), 49 + routeWithLocale: `${locale}/${path}`, 50 + }; 51 + }); 52 + 53 + /** 54 + * This creates an index with the information for each language 55 + * and the pages that they provide in relation to the source pages 56 + * and the pages that are missing in relation to the source pages. 57 + * 58 + * @type {[string, import('./types').RouteSegment[]][]} 59 + */ 60 + const allAvailableMarkdownPaths = nextLocales.availableLocales.map( 61 + ({ code }) => 62 + getPathsByLanguage(code) 63 + .then(mergePathsWithFallback(code)) 64 + .then(files => [code, files]) 65 + ); 66 + 67 + return Promise.all(allAvailableMarkdownPaths); 68 + }; 69 + 70 + // A Map containing all the dynamic paths and their information 71 + export const allPaths = new Map(await getAllPaths()); 72 + 73 + /** 74 + * This method attempts to find a matching file in the fileystem provided originally 75 + * by `getStaticPaths` and returns the file source and filename. 76 + * 77 + * Note that this method is safe as it is always provided by paths determined by the server 78 + * that are non-localized pages that exist on the English locale. 79 + * 80 + * Hence we don't fallback for non-existing pages as it should never fall into this scenario. 81 + * Next.js will already protect against common attack vectors 82 + * such as `/../../` on the URL pathname and other methodologies 83 + * 84 + * @param {string} locale the locale code to be used 85 + * @param {string} pathname the pathname string 86 + * @returns {{ source: string, filename: string }} the source and filename 87 + * @throws {Error} if the file does not exist, which should never happen 88 + */ 89 + export const getMarkdownFile = ( 90 + locale = nextConstants.DEFAULT_LOCALE_CODE, 91 + pathname = '' 92 + ) => { 93 + const metadata = { source: '', filename: '' }; 94 + 95 + const routes = allPaths.get(locale); 96 + 97 + // We verify if the file exists within the list of allowed pages 98 + // which prevents any malicious attempts to access non-allowed pages 99 + // or other files that do not belong to the `sourcePages` 100 + if (routes && routes.length) { 101 + const route = routes.find(route => route.pathname === pathname); 102 + 103 + if (route && route.filename) { 104 + // this determines if we should be using the fallback rendering to the default locale 105 + // or if we can use the current locale 106 + const localeToUse = !route.localised 107 + ? nextConstants.DEFAULT_LOCALE_CODE 108 + : locale; 109 + 110 + // gets the full pathname for the file (absolute path) 111 + metadata.filename = join( 112 + process.cwd(), 113 + 'pages', 114 + localeToUse, 115 + route.filename 116 + ); 117 + 118 + // Since we always will only read files that we know exist 119 + // we don't need to handle a possibility of an error being thrown 120 + // as any other case is if we don't have file system access and that should 121 + // then be thrown and reported 122 + metadata.source = readFileSync(metadata.filename, 'utf8'); 123 + } 124 + } 125 + 126 + return metadata; 127 + }; 128 + 129 + /** 130 + * This Method gathers the Markdown Source and the source filename 131 + * and processes the data (parses the markdown) and generate props 132 + * for the application to consume (`getStaticProps`) 133 + * 134 + * @returns {Promise<{ notFound: boolean, props: any; revalidate: number | boolean }>} the props for the page 135 + */ 136 + export const getStaticProps = async (source = '', filename = '') => { 137 + // by default a page is not found if there's no source or filename 138 + const staticProps = { notFound: true, props: {}, revalidate: false }; 139 + 140 + // We only attempt to serialize data if the `source` has content and `filename` has content 141 + // otherwise we return a 404 since this means that it is not a valid file or a file we should care about 142 + if (source.length && filename.length) { 143 + // This act as a MDX "compiler" but, lightweight. It parses the Markdown 144 + // string source into a React Component tree, and then it serializes it 145 + // it also supports Remark plugins, and MDX components 146 + // Note.: We use the filename extension to define the mode of execution 147 + const content = await serialize(source, { 148 + parseFrontmatter: true, 149 + mdxOptions: { 150 + remarkPlugins: [remarkGfm], 151 + format: filename.includes('.mdx') ? 'mdx' : 'md', 152 + }, 153 + }); 154 + 155 + // this defines the basic props that should be passed back to the `DynamicPage` component 156 + staticProps.props = { content }; 157 + staticProps.notFound = false; 158 + } 159 + 160 + return staticProps; 161 + };
+15
next.json.mjs
···
··· 1 + 'use strict'; 2 + 3 + // This is the static Site Configuration 4 + import siteConfig from './site.json' assert { type: 'json' }; 5 + 6 + // This is the static Site Navigation (legacy website) 7 + import siteNavigation from './navigation.json' assert { type: 'json' }; 8 + 9 + // This is the Website i18n Configuration 10 + import localeConfig from './i18n/config.json' assert { type: 'json' }; 11 + 12 + // This is the generated blog data for the Node.js Website 13 + import blogData from './public/blog-posts-data.json' assert { type: 'json' }; 14 + 15 + export { siteConfig, siteNavigation, localeConfig, blogData };
+3 -4
next.locales.mjs
··· 1 - // Imports the global i18n config as a static import 2 - import localeConfig from './i18n/config.json' assert { type: 'json' }; 3 4 - // Import the full Translation manifest for the Application 5 import translations from './i18n/locales/index.mjs'; 6 7 // As set of available and enabled locales for the website 8 // This is used for allowing us to redirect the user to any 9 // of the available locales that we have enabled on the website 10 - const availableLocales = localeConfig.filter(locale => locale.enabled); 11 12 // This provides the default locale information for the Next.js Application 13 // This is marked by the unique `locale.default` property on the `en` locale
··· 1 + 'use strict'; 2 3 + import * as nextJson from './next.json.mjs'; 4 import translations from './i18n/locales/index.mjs'; 5 6 // As set of available and enabled locales for the website 7 // This is used for allowing us to redirect the user to any 8 // of the available locales that we have enabled on the website 9 + const availableLocales = nextJson.localeConfig.filter(locale => locale.enabled); 10 11 // This provides the default locale information for the Next.js Application 12 // This is marked by the unique `locale.default` property on the `en` locale
+272 -1677
package-lock.json
··· 18 "classnames": "^2.3.2", 19 "cross-env": "^7.0.3", 20 "framer-motion": "^10.12.16", 21 "highlight.js": "^11.8.0", 22 "isomorphic-dompurify": "^1.5.0", 23 "next": "^13.4.3", 24 "next-themes": "^0.2.1", 25 - "nextra": "^2.6.1", 26 "prismjs": "^1.29.0", 27 "react": "^18.2.0", 28 "react-dom": "^18.2.0", ··· 33 "semver": "^7.5.1", 34 "sharp": "^0.32.1", 35 "strftime": "^0.10.1", 36 "swr": "^2.1.5", 37 - "turbo": "^1.9.9" 38 }, 39 "devDependencies": { 40 "@storybook/addon-controls": "^7.0.17", 41 "@storybook/addon-interactions": "^7.0.17", 42 "@storybook/nextjs": "^7.0.17", ··· 2504 "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", 2505 "dev": true 2506 }, 2507 - "node_modules/@braintree/sanitize-url": { 2508 - "version": "6.0.2", 2509 - "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.2.tgz", 2510 - "integrity": "sha512-Tbsj02wXCbqGmzdnXNk0SOF19ChhRU70BsroIi4Pm6Ehp56in6vch94mfbdQ17DozxkL3BAVjbZ4Qc1a0HFRAg==" 2511 }, 2512 "node_modules/@colors/colors": { 2513 "version": "1.5.0", ··· 3320 "version": "8.0.2", 3321 "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", 3322 "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", 3323 - "dev": true, 3324 "dependencies": { 3325 "string-width": "^5.1.2", 3326 "string-width-cjs": "npm:string-width@^4.2.0", ··· 3337 "version": "6.0.1", 3338 "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", 3339 "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", 3340 - "dev": true, 3341 "engines": { 3342 "node": ">=12" 3343 }, ··· 3349 "version": "6.2.1", 3350 "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", 3351 "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", 3352 - "dev": true, 3353 "engines": { 3354 "node": ">=12" 3355 }, ··· 3361 "version": "5.1.2", 3362 "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", 3363 "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", 3364 - "dev": true, 3365 "dependencies": { 3366 "eastasianwidth": "^0.2.0", 3367 "emoji-regex": "^9.2.2", ··· 3378 "version": "7.1.0", 3379 "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", 3380 "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", 3381 - "dev": true, 3382 "dependencies": { 3383 "ansi-regex": "^6.0.1" 3384 }, ··· 3393 "version": "8.1.0", 3394 "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", 3395 "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", 3396 - "dev": true, 3397 "dependencies": { 3398 "ansi-styles": "^6.1.0", 3399 "string-width": "^5.0.1", ··· 4862 "react": "^17.0.0 || ^18.0.0" 4863 } 4864 }, 4865 - "node_modules/@napi-rs/simple-git": { 4866 - "version": "0.1.8", 4867 - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git/-/simple-git-0.1.8.tgz", 4868 - "integrity": "sha512-BvOMdkkofTz6lEE35itJ/laUokPhr/5ToMGlOH25YnhLD2yN1KpRAT4blW9tT8281/1aZjW3xyi73bs//IrDKA==", 4869 - "engines": { 4870 - "node": ">= 10" 4871 - }, 4872 - "optionalDependencies": { 4873 - "@napi-rs/simple-git-android-arm-eabi": "0.1.8", 4874 - "@napi-rs/simple-git-android-arm64": "0.1.8", 4875 - "@napi-rs/simple-git-darwin-arm64": "0.1.8", 4876 - "@napi-rs/simple-git-darwin-x64": "0.1.8", 4877 - "@napi-rs/simple-git-linux-arm-gnueabihf": "0.1.8", 4878 - "@napi-rs/simple-git-linux-arm64-gnu": "0.1.8", 4879 - "@napi-rs/simple-git-linux-arm64-musl": "0.1.8", 4880 - "@napi-rs/simple-git-linux-x64-gnu": "0.1.8", 4881 - "@napi-rs/simple-git-linux-x64-musl": "0.1.8", 4882 - "@napi-rs/simple-git-win32-arm64-msvc": "0.1.8", 4883 - "@napi-rs/simple-git-win32-x64-msvc": "0.1.8" 4884 - } 4885 - }, 4886 - "node_modules/@napi-rs/simple-git-android-arm-eabi": { 4887 - "version": "0.1.8", 4888 - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-android-arm-eabi/-/simple-git-android-arm-eabi-0.1.8.tgz", 4889 - "integrity": "sha512-JJCejHBB1G6O8nxjQLT4quWCcvLpC3oRdJJ9G3MFYSCoYS8i1bWCWeU+K7Br+xT+D6s1t9q8kNJAwJv9Ygpi0g==", 4890 - "cpu": [ 4891 - "arm" 4892 - ], 4893 - "optional": true, 4894 - "os": [ 4895 - "android" 4896 - ], 4897 - "engines": { 4898 - "node": ">= 10" 4899 - } 4900 - }, 4901 - "node_modules/@napi-rs/simple-git-android-arm64": { 4902 - "version": "0.1.8", 4903 - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-android-arm64/-/simple-git-android-arm64-0.1.8.tgz", 4904 - "integrity": "sha512-mraHzwWBw3tdRetNOS5KnFSjvdAbNBnjFLA8I4PwTCPJj3Q4txrigcPp2d59cJ0TC51xpnPXnZjYdNwwSI9g6g==", 4905 - "cpu": [ 4906 - "arm64" 4907 - ], 4908 - "optional": true, 4909 - "os": [ 4910 - "android" 4911 - ], 4912 - "engines": { 4913 - "node": ">= 10" 4914 - } 4915 - }, 4916 - "node_modules/@napi-rs/simple-git-darwin-arm64": { 4917 - "version": "0.1.8", 4918 - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-darwin-arm64/-/simple-git-darwin-arm64-0.1.8.tgz", 4919 - "integrity": "sha512-ufy/36eI/j4UskEuvqSH7uXtp3oXeLDmjQCfKJz3u5Vx98KmOMKrqAm2H81AB2WOtCo5mqS6PbBeUXR8BJX8lQ==", 4920 - "cpu": [ 4921 - "arm64" 4922 - ], 4923 - "optional": true, 4924 - "os": [ 4925 - "darwin" 4926 - ], 4927 - "engines": { 4928 - "node": ">= 10" 4929 - } 4930 - }, 4931 - "node_modules/@napi-rs/simple-git-darwin-x64": { 4932 - "version": "0.1.8", 4933 - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-darwin-x64/-/simple-git-darwin-x64-0.1.8.tgz", 4934 - "integrity": "sha512-Vb21U+v3tPJNl+8JtIHHT8HGe6WZ8o1Tq3f6p+Jx9Cz71zEbcIiB9FCEMY1knS/jwQEOuhhlI9Qk7d4HY+rprA==", 4935 - "cpu": [ 4936 - "x64" 4937 - ], 4938 - "optional": true, 4939 - "os": [ 4940 - "darwin" 4941 - ], 4942 - "engines": { 4943 - "node": ">= 10" 4944 - } 4945 - }, 4946 - "node_modules/@napi-rs/simple-git-linux-arm-gnueabihf": { 4947 - "version": "0.1.8", 4948 - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-arm-gnueabihf/-/simple-git-linux-arm-gnueabihf-0.1.8.tgz", 4949 - "integrity": "sha512-6BPTJ7CzpSm2t54mRLVaUr3S7ORJfVJoCk2rQ8v8oDg0XAMKvmQQxOsAgqKBo9gYNHJnqrOx3AEuEgvB586BuQ==", 4950 - "cpu": [ 4951 - "arm" 4952 - ], 4953 - "optional": true, 4954 - "os": [ 4955 - "linux" 4956 - ], 4957 - "engines": { 4958 - "node": ">= 10" 4959 - } 4960 - }, 4961 - "node_modules/@napi-rs/simple-git-linux-arm64-gnu": { 4962 - "version": "0.1.8", 4963 - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-arm64-gnu/-/simple-git-linux-arm64-gnu-0.1.8.tgz", 4964 - "integrity": "sha512-qfESqUCAA/XoQpRXHptSQ8gIFnETCQt1zY9VOkplx6tgYk9PCeaX4B1Xuzrh3eZamSCMJFn+1YB9Ut8NwyGgAA==", 4965 - "cpu": [ 4966 - "arm64" 4967 - ], 4968 - "hasInstallScript": true, 4969 - "optional": true, 4970 - "os": [ 4971 - "linux" 4972 - ], 4973 - "engines": { 4974 - "node": ">= 10" 4975 - } 4976 - }, 4977 - "node_modules/@napi-rs/simple-git-linux-arm64-musl": { 4978 - "version": "0.1.8", 4979 - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-arm64-musl/-/simple-git-linux-arm64-musl-0.1.8.tgz", 4980 - "integrity": "sha512-G80BQPpaRmQpn8dJGHp4I2/YVhWDUNJwcCrJAtAdbKFDCMyCHJBln2ERL/+IEUlIAT05zK/c1Z5WEprvXEdXow==", 4981 - "cpu": [ 4982 - "arm64" 4983 - ], 4984 - "hasInstallScript": true, 4985 - "optional": true, 4986 - "os": [ 4987 - "linux" 4988 - ], 4989 - "engines": { 4990 - "node": ">= 10" 4991 - } 4992 - }, 4993 - "node_modules/@napi-rs/simple-git-linux-x64-gnu": { 4994 - "version": "0.1.8", 4995 - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-x64-gnu/-/simple-git-linux-x64-gnu-0.1.8.tgz", 4996 - "integrity": "sha512-NI6o1sZYEf6vPtNWJAm9w8BxJt+LlSFW0liSjYe3lc3e4dhMfV240f0ALeqlwdIldRPaDFwZSJX5/QbS7nMzhw==", 4997 - "cpu": [ 4998 - "x64" 4999 - ], 5000 - "hasInstallScript": true, 5001 - "optional": true, 5002 - "os": [ 5003 - "linux" 5004 - ], 5005 - "engines": { 5006 - "node": ">= 10" 5007 - } 5008 - }, 5009 - "node_modules/@napi-rs/simple-git-linux-x64-musl": { 5010 - "version": "0.1.8", 5011 - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-linux-x64-musl/-/simple-git-linux-x64-musl-0.1.8.tgz", 5012 - "integrity": "sha512-wljGAEOW41er45VTiU8kXJmO480pQKzsgRCvPlJJSCaEVBbmo6XXbFIXnZy1a2J3Zyy2IOsRB4PVkUZaNuPkZQ==", 5013 - "cpu": [ 5014 - "x64" 5015 - ], 5016 - "hasInstallScript": true, 5017 - "optional": true, 5018 - "os": [ 5019 - "linux" 5020 - ], 5021 - "engines": { 5022 - "node": ">= 10" 5023 - } 5024 - }, 5025 - "node_modules/@napi-rs/simple-git-win32-arm64-msvc": { 5026 - "version": "0.1.8", 5027 - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-win32-arm64-msvc/-/simple-git-win32-arm64-msvc-0.1.8.tgz", 5028 - "integrity": "sha512-QuV4QILyKPfbWHoQKrhXqjiCClx0SxbCTVogkR89BwivekqJMd9UlMxZdoCmwLWutRx4z9KmzQqokvYI5QeepA==", 5029 - "cpu": [ 5030 - "arm64" 5031 - ], 5032 - "optional": true, 5033 - "os": [ 5034 - "win32" 5035 - ], 5036 - "engines": { 5037 - "node": ">= 10" 5038 - } 5039 - }, 5040 - "node_modules/@napi-rs/simple-git-win32-x64-msvc": { 5041 - "version": "0.1.8", 5042 - "resolved": "https://registry.npmjs.org/@napi-rs/simple-git-win32-x64-msvc/-/simple-git-win32-x64-msvc-0.1.8.tgz", 5043 - "integrity": "sha512-UzNS4JtjhZhZ5hRLq7BIUq+4JOwt1ThIKv11CsF1ag2l99f0123XvfEpjczKTaa94nHtjXYc2Mv9TjccBqYOew==", 5044 - "cpu": [ 5045 - "x64" 5046 - ], 5047 - "optional": true, 5048 - "os": [ 5049 - "win32" 5050 - ], 5051 - "engines": { 5052 - "node": ">= 10" 5053 - } 5054 - }, 5055 "node_modules/@ndelangen/get-tarball": { 5056 "version": "3.0.9", 5057 "resolved": "https://registry.npmjs.org/@ndelangen/get-tarball/-/get-tarball-3.0.9.tgz", ··· 5335 "balanced-match": "^1.0.0" 5336 } 5337 }, 5338 - "node_modules/@npmcli/map-workspaces/node_modules/foreground-child": { 5339 - "version": "3.1.1", 5340 - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", 5341 - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", 5342 - "dev": true, 5343 - "dependencies": { 5344 - "cross-spawn": "^7.0.0", 5345 - "signal-exit": "^4.0.1" 5346 - }, 5347 - "engines": { 5348 - "node": ">=14" 5349 - }, 5350 - "funding": { 5351 - "url": "https://github.com/sponsors/isaacs" 5352 - } 5353 - }, 5354 - "node_modules/@npmcli/map-workspaces/node_modules/glob": { 5355 - "version": "10.3.0", 5356 - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.0.tgz", 5357 - "integrity": "sha512-AQ1/SB9HH0yCx1jXAT4vmCbTOPe5RQ+kCurjbel5xSCGhebumUv+GJZfa1rEqor3XIViqwSEmlkZCQD43RWrBg==", 5358 - "dev": true, 5359 - "dependencies": { 5360 - "foreground-child": "^3.1.0", 5361 - "jackspeak": "^2.0.3", 5362 - "minimatch": "^9.0.1", 5363 - "minipass": "^5.0.0 || ^6.0.2", 5364 - "path-scurry": "^1.7.0" 5365 - }, 5366 - "bin": { 5367 - "glob": "dist/cjs/src/bin.js" 5368 - }, 5369 - "engines": { 5370 - "node": ">=16 || 14 >=14.17" 5371 - }, 5372 - "funding": { 5373 - "url": "https://github.com/sponsors/isaacs" 5374 - } 5375 - }, 5376 "node_modules/@npmcli/map-workspaces/node_modules/minimatch": { 5377 "version": "9.0.2", 5378 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.2.tgz", ··· 5388 "url": "https://github.com/sponsors/isaacs" 5389 } 5390 }, 5391 - "node_modules/@npmcli/map-workspaces/node_modules/signal-exit": { 5392 - "version": "4.0.2", 5393 - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", 5394 - "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", 5395 - "dev": true, 5396 - "engines": { 5397 - "node": ">=14" 5398 - }, 5399 - "funding": { 5400 - "url": "https://github.com/sponsors/isaacs" 5401 - } 5402 - }, 5403 "node_modules/@npmcli/name-from-folder": { 5404 "version": "2.0.0", 5405 "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-2.0.0.tgz", ··· 5413 "version": "0.11.0", 5414 "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", 5415 "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", 5416 - "dev": true, 5417 "optional": true, 5418 "engines": { 5419 "node": ">=14" ··· 6348 "integrity": "sha512-8egDX8dE50XyXWH6C6PRCNkTP106DuUrvdrednFouDSmCi7IOvrqr0frznfZaHifHH/3aq/7a7v9N4wdXMqhBQ==", 6349 "dev": true 6350 }, 6351 "node_modules/@storybook/core-events": { 6352 "version": "7.0.23", 6353 "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.0.23.tgz", ··· 7310 "@babel/core": "^7.0.0" 7311 } 7312 }, 7313 "node_modules/@storybook/test-runner/node_modules/camelcase": { 7314 "version": "6.3.0", 7315 "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", ··· 7345 }, 7346 "engines": { 7347 "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" 7348 } 7349 }, 7350 "node_modules/@storybook/test-runner/node_modules/jest": { ··· 8023 "@testing-library/dom": ">=7.21.4" 8024 } 8025 }, 8026 - "node_modules/@theguild/remark-mermaid": { 8027 - "version": "0.0.3", 8028 - "resolved": "https://registry.npmjs.org/@theguild/remark-mermaid/-/remark-mermaid-0.0.3.tgz", 8029 - "integrity": "sha512-fccVR6o4UPUztrBjdUhM4ahwx+X7YHhoxsUoXv2vI07vz4dq+I03Ot0SjuZzDA/H7engxcb8ZxzCUEkZgGr/2g==", 8030 - "dependencies": { 8031 - "mermaid": "^10.2.2", 8032 - "unist-util-visit": "^4.1.2" 8033 - }, 8034 - "peerDependencies": { 8035 - "react": "^18.2.0" 8036 - } 8037 - }, 8038 "node_modules/@tootallnate/once": { 8039 "version": "2.0.0", 8040 "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", ··· 8370 "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", 8371 "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", 8372 "dev": true 8373 - }, 8374 - "node_modules/@types/katex": { 8375 - "version": "0.14.0", 8376 - "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.14.0.tgz", 8377 - "integrity": "sha512-+2FW2CcT0K3P+JMR8YG846bmDwplKUTsWgT2ENwdQ1UdVfRk3GQrh6Mi4sTopy30gI8Uau5CEqHTDZ6YvWIUPA==" 8378 }, 8379 "node_modules/@types/lodash": { 8380 "version": "4.14.195", ··· 9257 "version": "5.0.1", 9258 "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 9259 "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 9260 - "dev": true, 9261 "engines": { 9262 "node": ">=8" 9263 } 9264 }, 9265 - "node_modules/ansi-sequence-parser": { 9266 - "version": "1.1.0", 9267 - "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz", 9268 - "integrity": "sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==" 9269 - }, 9270 "node_modules/ansi-styles": { 9271 "version": "4.3.0", 9272 "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 9273 "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 9274 - "dev": true, 9275 "dependencies": { 9276 "color-convert": "^2.0.1" 9277 }, ··· 9318 "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", 9319 "dev": true 9320 }, 9321 - "node_modules/arch": { 9322 - "version": "2.2.0", 9323 - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", 9324 - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", 9325 - "funding": [ 9326 - { 9327 - "type": "github", 9328 - "url": "https://github.com/sponsors/feross" 9329 - }, 9330 - { 9331 - "type": "patreon", 9332 - "url": "https://www.patreon.com/feross" 9333 - }, 9334 - { 9335 - "type": "consulting", 9336 - "url": "https://feross.org/support" 9337 - } 9338 - ] 9339 - }, 9340 "node_modules/archy": { 9341 "version": "1.0.0", 9342 "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", ··· 9355 "engines": { 9356 "node": ">=10" 9357 } 9358 - }, 9359 - "node_modules/arg": { 9360 - "version": "1.0.0", 9361 - "resolved": "https://registry.npmjs.org/arg/-/arg-1.0.0.tgz", 9362 - "integrity": "sha512-Wk7TEzl1KqvTGs/uyhmHO/3XLd3t1UeU4IstvPXVzGPM522cTjqjNZ99esCkcL52sjqjo8e8CTBcWhkxvGzoAw==" 9363 }, 9364 "node_modules/argparse": { 9365 "version": "2.0.1", ··· 9883 "node_modules/balanced-match": { 9884 "version": "1.0.2", 9885 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 9886 - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 9887 - "dev": true 9888 }, 9889 "node_modules/base64-js": { 9890 "version": "1.5.1", ··· 10716 "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", 10717 "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" 10718 }, 10719 - "node_modules/clipboardy": { 10720 - "version": "1.2.2", 10721 - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-1.2.2.tgz", 10722 - "integrity": "sha512-16KrBOV7bHmHdxcQiCvfUFYVFyEah4FI8vYT1Fr7CGSA4G+xBWMEfUEQJS1hxeHGtI9ju1Bzs9uXSbj5HZKArw==", 10723 - "dependencies": { 10724 - "arch": "^2.1.0", 10725 - "execa": "^0.8.0" 10726 - }, 10727 - "engines": { 10728 - "node": ">=4" 10729 - } 10730 - }, 10731 - "node_modules/clipboardy/node_modules/cross-spawn": { 10732 - "version": "5.1.0", 10733 - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", 10734 - "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", 10735 - "dependencies": { 10736 - "lru-cache": "^4.0.1", 10737 - "shebang-command": "^1.2.0", 10738 - "which": "^1.2.9" 10739 - } 10740 - }, 10741 - "node_modules/clipboardy/node_modules/execa": { 10742 - "version": "0.8.0", 10743 - "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", 10744 - "integrity": "sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA==", 10745 - "dependencies": { 10746 - "cross-spawn": "^5.0.1", 10747 - "get-stream": "^3.0.0", 10748 - "is-stream": "^1.1.0", 10749 - "npm-run-path": "^2.0.0", 10750 - "p-finally": "^1.0.0", 10751 - "signal-exit": "^3.0.0", 10752 - "strip-eof": "^1.0.0" 10753 - }, 10754 - "engines": { 10755 - "node": ">=4" 10756 - } 10757 - }, 10758 - "node_modules/clipboardy/node_modules/get-stream": { 10759 - "version": "3.0.0", 10760 - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", 10761 - "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", 10762 - "engines": { 10763 - "node": ">=4" 10764 - } 10765 - }, 10766 - "node_modules/clipboardy/node_modules/is-stream": { 10767 - "version": "1.1.0", 10768 - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 10769 - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", 10770 - "engines": { 10771 - "node": ">=0.10.0" 10772 - } 10773 - }, 10774 - "node_modules/clipboardy/node_modules/lru-cache": { 10775 - "version": "4.1.5", 10776 - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", 10777 - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", 10778 - "dependencies": { 10779 - "pseudomap": "^1.0.2", 10780 - "yallist": "^2.1.2" 10781 - } 10782 - }, 10783 - "node_modules/clipboardy/node_modules/npm-run-path": { 10784 - "version": "2.0.2", 10785 - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", 10786 - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", 10787 - "dependencies": { 10788 - "path-key": "^2.0.0" 10789 - }, 10790 - "engines": { 10791 - "node": ">=4" 10792 - } 10793 - }, 10794 - "node_modules/clipboardy/node_modules/path-key": { 10795 - "version": "2.0.1", 10796 - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", 10797 - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", 10798 - "engines": { 10799 - "node": ">=4" 10800 - } 10801 - }, 10802 - "node_modules/clipboardy/node_modules/shebang-command": { 10803 - "version": "1.2.0", 10804 - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 10805 - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", 10806 - "dependencies": { 10807 - "shebang-regex": "^1.0.0" 10808 - }, 10809 - "engines": { 10810 - "node": ">=0.10.0" 10811 - } 10812 - }, 10813 - "node_modules/clipboardy/node_modules/shebang-regex": { 10814 - "version": "1.0.0", 10815 - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 10816 - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", 10817 - "engines": { 10818 - "node": ">=0.10.0" 10819 - } 10820 - }, 10821 - "node_modules/clipboardy/node_modules/which": { 10822 - "version": "1.3.1", 10823 - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 10824 - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 10825 - "dependencies": { 10826 - "isexe": "^2.0.0" 10827 - }, 10828 - "bin": { 10829 - "which": "bin/which" 10830 - } 10831 - }, 10832 - "node_modules/clipboardy/node_modules/yallist": { 10833 - "version": "2.1.2", 10834 - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", 10835 - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" 10836 - }, 10837 "node_modules/cliui": { 10838 "version": "8.0.1", 10839 "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", ··· 11223 "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 11224 "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", 11225 "dev": true 11226 }, 11227 "node_modules/core-js-compat": { 11228 "version": "3.31.0", ··· 11254 "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", 11255 "dev": true 11256 }, 11257 - "node_modules/cose-base": { 11258 - "version": "1.0.3", 11259 - "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", 11260 - "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", 11261 - "dependencies": { 11262 - "layout-base": "^1.0.0" 11263 - } 11264 - }, 11265 "node_modules/cosmiconfig": { 11266 "version": "7.1.0", 11267 "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", ··· 11574 "node": ">=0.8" 11575 } 11576 }, 11577 - "node_modules/cytoscape": { 11578 - "version": "3.25.0", 11579 - "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.25.0.tgz", 11580 - "integrity": "sha512-7MW3Iz57mCUo6JQCho6CmPBCbTlJr7LzyEtIkutG255HLVd4XuBg2I9BkTZLI/e4HoaOB/BiAzXuQybQ95+r9Q==", 11581 - "dependencies": { 11582 - "heap": "^0.2.6", 11583 - "lodash": "^4.17.21" 11584 - }, 11585 - "engines": { 11586 - "node": ">=0.10" 11587 - } 11588 - }, 11589 - "node_modules/cytoscape-cose-bilkent": { 11590 - "version": "4.1.0", 11591 - "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", 11592 - "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", 11593 - "dependencies": { 11594 - "cose-base": "^1.0.0" 11595 - }, 11596 - "peerDependencies": { 11597 - "cytoscape": "^3.2.0" 11598 - } 11599 - }, 11600 - "node_modules/cytoscape-fcose": { 11601 - "version": "2.2.0", 11602 - "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", 11603 - "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", 11604 - "dependencies": { 11605 - "cose-base": "^2.2.0" 11606 - }, 11607 - "peerDependencies": { 11608 - "cytoscape": "^3.2.0" 11609 - } 11610 - }, 11611 - "node_modules/cytoscape-fcose/node_modules/cose-base": { 11612 - "version": "2.2.0", 11613 - "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", 11614 - "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", 11615 - "dependencies": { 11616 - "layout-base": "^2.0.0" 11617 - } 11618 - }, 11619 - "node_modules/cytoscape-fcose/node_modules/layout-base": { 11620 - "version": "2.0.1", 11621 - "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", 11622 - "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==" 11623 - }, 11624 - "node_modules/d3": { 11625 - "version": "7.8.5", 11626 - "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.5.tgz", 11627 - "integrity": "sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==", 11628 - "dependencies": { 11629 - "d3-array": "3", 11630 - "d3-axis": "3", 11631 - "d3-brush": "3", 11632 - "d3-chord": "3", 11633 - "d3-color": "3", 11634 - "d3-contour": "4", 11635 - "d3-delaunay": "6", 11636 - "d3-dispatch": "3", 11637 - "d3-drag": "3", 11638 - "d3-dsv": "3", 11639 - "d3-ease": "3", 11640 - "d3-fetch": "3", 11641 - "d3-force": "3", 11642 - "d3-format": "3", 11643 - "d3-geo": "3", 11644 - "d3-hierarchy": "3", 11645 - "d3-interpolate": "3", 11646 - "d3-path": "3", 11647 - "d3-polygon": "3", 11648 - "d3-quadtree": "3", 11649 - "d3-random": "3", 11650 - "d3-scale": "4", 11651 - "d3-scale-chromatic": "3", 11652 - "d3-selection": "3", 11653 - "d3-shape": "3", 11654 - "d3-time": "3", 11655 - "d3-time-format": "4", 11656 - "d3-timer": "3", 11657 - "d3-transition": "3", 11658 - "d3-zoom": "3" 11659 - }, 11660 - "engines": { 11661 - "node": ">=12" 11662 - } 11663 - }, 11664 - "node_modules/d3-array": { 11665 - "version": "3.2.4", 11666 - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", 11667 - "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", 11668 - "dependencies": { 11669 - "internmap": "1 - 2" 11670 - }, 11671 - "engines": { 11672 - "node": ">=12" 11673 - } 11674 - }, 11675 - "node_modules/d3-axis": { 11676 - "version": "3.0.0", 11677 - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", 11678 - "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", 11679 - "engines": { 11680 - "node": ">=12" 11681 - } 11682 - }, 11683 - "node_modules/d3-brush": { 11684 - "version": "3.0.0", 11685 - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", 11686 - "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", 11687 - "dependencies": { 11688 - "d3-dispatch": "1 - 3", 11689 - "d3-drag": "2 - 3", 11690 - "d3-interpolate": "1 - 3", 11691 - "d3-selection": "3", 11692 - "d3-transition": "3" 11693 - }, 11694 - "engines": { 11695 - "node": ">=12" 11696 - } 11697 - }, 11698 - "node_modules/d3-chord": { 11699 - "version": "3.0.1", 11700 - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", 11701 - "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", 11702 - "dependencies": { 11703 - "d3-path": "1 - 3" 11704 - }, 11705 - "engines": { 11706 - "node": ">=12" 11707 - } 11708 - }, 11709 - "node_modules/d3-color": { 11710 - "version": "3.1.0", 11711 - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", 11712 - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", 11713 - "engines": { 11714 - "node": ">=12" 11715 - } 11716 - }, 11717 - "node_modules/d3-contour": { 11718 - "version": "4.0.2", 11719 - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", 11720 - "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", 11721 - "dependencies": { 11722 - "d3-array": "^3.2.0" 11723 - }, 11724 - "engines": { 11725 - "node": ">=12" 11726 - } 11727 - }, 11728 - "node_modules/d3-delaunay": { 11729 - "version": "6.0.4", 11730 - "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", 11731 - "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", 11732 - "dependencies": { 11733 - "delaunator": "5" 11734 - }, 11735 - "engines": { 11736 - "node": ">=12" 11737 - } 11738 - }, 11739 - "node_modules/d3-dispatch": { 11740 - "version": "3.0.1", 11741 - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", 11742 - "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", 11743 - "engines": { 11744 - "node": ">=12" 11745 - } 11746 - }, 11747 - "node_modules/d3-drag": { 11748 - "version": "3.0.0", 11749 - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", 11750 - "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", 11751 - "dependencies": { 11752 - "d3-dispatch": "1 - 3", 11753 - "d3-selection": "3" 11754 - }, 11755 - "engines": { 11756 - "node": ">=12" 11757 - } 11758 - }, 11759 - "node_modules/d3-dsv": { 11760 - "version": "3.0.1", 11761 - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", 11762 - "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", 11763 - "dependencies": { 11764 - "commander": "7", 11765 - "iconv-lite": "0.6", 11766 - "rw": "1" 11767 - }, 11768 - "bin": { 11769 - "csv2json": "bin/dsv2json.js", 11770 - "csv2tsv": "bin/dsv2dsv.js", 11771 - "dsv2dsv": "bin/dsv2dsv.js", 11772 - "dsv2json": "bin/dsv2json.js", 11773 - "json2csv": "bin/json2dsv.js", 11774 - "json2dsv": "bin/json2dsv.js", 11775 - "json2tsv": "bin/json2dsv.js", 11776 - "tsv2csv": "bin/dsv2dsv.js", 11777 - "tsv2json": "bin/dsv2json.js" 11778 - }, 11779 - "engines": { 11780 - "node": ">=12" 11781 - } 11782 - }, 11783 - "node_modules/d3-dsv/node_modules/commander": { 11784 - "version": "7.2.0", 11785 - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", 11786 - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", 11787 - "engines": { 11788 - "node": ">= 10" 11789 - } 11790 - }, 11791 - "node_modules/d3-dsv/node_modules/iconv-lite": { 11792 - "version": "0.6.3", 11793 - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 11794 - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 11795 - "dependencies": { 11796 - "safer-buffer": ">= 2.1.2 < 3.0.0" 11797 - }, 11798 - "engines": { 11799 - "node": ">=0.10.0" 11800 - } 11801 - }, 11802 - "node_modules/d3-ease": { 11803 - "version": "3.0.1", 11804 - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", 11805 - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", 11806 - "engines": { 11807 - "node": ">=12" 11808 - } 11809 - }, 11810 - "node_modules/d3-fetch": { 11811 - "version": "3.0.1", 11812 - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", 11813 - "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", 11814 - "dependencies": { 11815 - "d3-dsv": "1 - 3" 11816 - }, 11817 - "engines": { 11818 - "node": ">=12" 11819 - } 11820 - }, 11821 - "node_modules/d3-force": { 11822 - "version": "3.0.0", 11823 - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", 11824 - "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", 11825 - "dependencies": { 11826 - "d3-dispatch": "1 - 3", 11827 - "d3-quadtree": "1 - 3", 11828 - "d3-timer": "1 - 3" 11829 - }, 11830 - "engines": { 11831 - "node": ">=12" 11832 - } 11833 - }, 11834 - "node_modules/d3-format": { 11835 - "version": "3.1.0", 11836 - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", 11837 - "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", 11838 - "engines": { 11839 - "node": ">=12" 11840 - } 11841 - }, 11842 - "node_modules/d3-geo": { 11843 - "version": "3.1.0", 11844 - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz", 11845 - "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==", 11846 - "dependencies": { 11847 - "d3-array": "2.5.0 - 3" 11848 - }, 11849 - "engines": { 11850 - "node": ">=12" 11851 - } 11852 - }, 11853 - "node_modules/d3-hierarchy": { 11854 - "version": "3.1.2", 11855 - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", 11856 - "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", 11857 - "engines": { 11858 - "node": ">=12" 11859 - } 11860 - }, 11861 - "node_modules/d3-interpolate": { 11862 - "version": "3.0.1", 11863 - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", 11864 - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", 11865 - "dependencies": { 11866 - "d3-color": "1 - 3" 11867 - }, 11868 - "engines": { 11869 - "node": ">=12" 11870 - } 11871 - }, 11872 - "node_modules/d3-path": { 11873 - "version": "3.1.0", 11874 - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", 11875 - "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", 11876 - "engines": { 11877 - "node": ">=12" 11878 - } 11879 - }, 11880 - "node_modules/d3-polygon": { 11881 - "version": "3.0.1", 11882 - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", 11883 - "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", 11884 - "engines": { 11885 - "node": ">=12" 11886 - } 11887 - }, 11888 - "node_modules/d3-quadtree": { 11889 - "version": "3.0.1", 11890 - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", 11891 - "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", 11892 - "engines": { 11893 - "node": ">=12" 11894 - } 11895 - }, 11896 - "node_modules/d3-random": { 11897 - "version": "3.0.1", 11898 - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", 11899 - "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", 11900 - "engines": { 11901 - "node": ">=12" 11902 - } 11903 - }, 11904 - "node_modules/d3-scale": { 11905 - "version": "4.0.2", 11906 - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", 11907 - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", 11908 - "dependencies": { 11909 - "d3-array": "2.10.0 - 3", 11910 - "d3-format": "1 - 3", 11911 - "d3-interpolate": "1.2.0 - 3", 11912 - "d3-time": "2.1.1 - 3", 11913 - "d3-time-format": "2 - 4" 11914 - }, 11915 - "engines": { 11916 - "node": ">=12" 11917 - } 11918 - }, 11919 - "node_modules/d3-scale-chromatic": { 11920 - "version": "3.0.0", 11921 - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", 11922 - "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==", 11923 - "dependencies": { 11924 - "d3-color": "1 - 3", 11925 - "d3-interpolate": "1 - 3" 11926 - }, 11927 - "engines": { 11928 - "node": ">=12" 11929 - } 11930 - }, 11931 - "node_modules/d3-selection": { 11932 - "version": "3.0.0", 11933 - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", 11934 - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", 11935 - "engines": { 11936 - "node": ">=12" 11937 - } 11938 - }, 11939 - "node_modules/d3-shape": { 11940 - "version": "3.2.0", 11941 - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", 11942 - "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", 11943 - "dependencies": { 11944 - "d3-path": "^3.1.0" 11945 - }, 11946 - "engines": { 11947 - "node": ">=12" 11948 - } 11949 - }, 11950 - "node_modules/d3-time": { 11951 - "version": "3.1.0", 11952 - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", 11953 - "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", 11954 - "dependencies": { 11955 - "d3-array": "2 - 3" 11956 - }, 11957 - "engines": { 11958 - "node": ">=12" 11959 - } 11960 - }, 11961 - "node_modules/d3-time-format": { 11962 - "version": "4.1.0", 11963 - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", 11964 - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", 11965 - "dependencies": { 11966 - "d3-time": "1 - 3" 11967 - }, 11968 - "engines": { 11969 - "node": ">=12" 11970 - } 11971 - }, 11972 - "node_modules/d3-timer": { 11973 - "version": "3.0.1", 11974 - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", 11975 - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", 11976 - "engines": { 11977 - "node": ">=12" 11978 - } 11979 - }, 11980 - "node_modules/d3-transition": { 11981 - "version": "3.0.1", 11982 - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", 11983 - "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", 11984 - "dependencies": { 11985 - "d3-color": "1 - 3", 11986 - "d3-dispatch": "1 - 3", 11987 - "d3-ease": "1 - 3", 11988 - "d3-interpolate": "1 - 3", 11989 - "d3-timer": "1 - 3" 11990 - }, 11991 - "engines": { 11992 - "node": ">=12" 11993 - }, 11994 - "peerDependencies": { 11995 - "d3-selection": "2 - 3" 11996 - } 11997 - }, 11998 - "node_modules/d3-zoom": { 11999 - "version": "3.0.0", 12000 - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", 12001 - "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", 12002 - "dependencies": { 12003 - "d3-dispatch": "1 - 3", 12004 - "d3-drag": "2 - 3", 12005 - "d3-interpolate": "1 - 3", 12006 - "d3-selection": "2 - 3", 12007 - "d3-transition": "2 - 3" 12008 - }, 12009 - "engines": { 12010 - "node": ">=12" 12011 - } 12012 - }, 12013 - "node_modules/dagre-d3-es": { 12014 - "version": "7.0.10", 12015 - "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.10.tgz", 12016 - "integrity": "sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==", 12017 - "dependencies": { 12018 - "d3": "^7.8.2", 12019 - "lodash-es": "^4.17.21" 12020 - } 12021 - }, 12022 "node_modules/damerau-levenshtein": { 12023 "version": "1.0.8", 12024 "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", ··· 12054 "url": "https://opencollective.com/date-fns" 12055 } 12056 }, 12057 - "node_modules/dayjs": { 12058 - "version": "1.11.8", 12059 - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.8.tgz", 12060 - "integrity": "sha512-LcgxzFoWMEPO7ggRv1Y2N31hUf2R0Vj7fuy/m+Bg1K8rr+KAs1AEy4y9jd5DXe8pbHgX+srkHNS7TH6Q6ZhYeQ==" 12061 - }, 12062 "node_modules/debug": { 12063 "version": "4.3.4", 12064 "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", ··· 12434 "url": "https://github.com/sponsors/sindresorhus" 12435 } 12436 }, 12437 - "node_modules/delaunator": { 12438 - "version": "5.0.0", 12439 - "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", 12440 - "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==", 12441 - "dependencies": { 12442 - "robust-predicates": "^3.0.0" 12443 - } 12444 - }, 12445 "node_modules/delayed-stream": { 12446 "version": "1.0.0", 12447 "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", ··· 12802 "node_modules/eastasianwidth": { 12803 "version": "0.2.0", 12804 "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", 12805 - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", 12806 - "dev": true 12807 }, 12808 "node_modules/ee-first": { 12809 "version": "1.1.1", ··· 12831 "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.440.tgz", 12832 "integrity": "sha512-r6dCgNpRhPwiWlxbHzZQ/d9swfPaEJGi8ekqRBwQYaR3WmA5VkqQfBWSDDjuJU1ntO+W9tHx8OHV/96Q8e0dVw==", 12833 "dev": true 12834 - }, 12835 - "node_modules/elkjs": { 12836 - "version": "0.8.2", 12837 - "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.8.2.tgz", 12838 - "integrity": "sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==" 12839 }, 12840 "node_modules/elliptic": { 12841 "version": "6.5.4", ··· 12873 "node_modules/emoji-regex": { 12874 "version": "9.2.2", 12875 "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", 12876 - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", 12877 - "dev": true 12878 }, 12879 "node_modules/emojis-list": { 12880 "version": "3.0.0", ··· 13846 "version": "4.0.1", 13847 "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 13848 "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 13849 "bin": { 13850 "esparse": "bin/esparse.js", 13851 "esvalidate": "bin/esvalidate.js" ··· 13963 "node": ">= 8" 13964 } 13965 }, 13966 - "node_modules/estree-util-value-to-estree": { 13967 - "version": "1.3.0", 13968 - "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-1.3.0.tgz", 13969 - "integrity": "sha512-Y+ughcF9jSUJvncXwqRageavjrNPAI+1M/L3BI3PyLp1nmgYTGUXU6t5z1Y7OWuThoDdhPME07bQU+d5LxdJqw==", 13970 - "dependencies": { 13971 - "is-plain-obj": "^3.0.0" 13972 - }, 13973 - "engines": { 13974 - "node": ">=12.0.0" 13975 - } 13976 - }, 13977 "node_modules/estree-util-visit": { 13978 "version": "1.2.1", 13979 "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-1.2.1.tgz", ··· 14201 "version": "2.0.1", 14202 "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 14203 "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", 14204 "dependencies": { 14205 "is-extendable": "^0.1.0" 14206 }, ··· 15102 "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", 15103 "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" 15104 }, 15105 - "node_modules/github-slugger": { 15106 - "version": "2.0.0", 15107 - "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", 15108 - "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==" 15109 - }, 15110 "node_modules/glob": { 15111 - "version": "8.1.0", 15112 - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", 15113 - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", 15114 - "dev": true, 15115 "dependencies": { 15116 - "fs.realpath": "^1.0.0", 15117 - "inflight": "^1.0.4", 15118 - "inherits": "2", 15119 - "minimatch": "^5.0.1", 15120 - "once": "^1.3.0" 15121 }, 15122 "engines": { 15123 - "node": ">=12" 15124 }, 15125 "funding": { 15126 "url": "https://github.com/sponsors/isaacs" ··· 15138 "node": ">=10.13.0" 15139 } 15140 }, 15141 - "node_modules/glob-promise": { 15142 - "version": "6.0.3", 15143 - "resolved": "https://registry.npmjs.org/glob-promise/-/glob-promise-6.0.3.tgz", 15144 - "integrity": "sha512-m+kxywR5j/2Z2V9zvHKfwwL5Gp7gIFEBX+deTB9w2lJB+wSuw9kcS43VfvTAMk8TXL5JCl/cCjsR+tgNVspGyA==", 15145 - "dev": true, 15146 - "dependencies": { 15147 - "@types/glob": "^8.0.0" 15148 - }, 15149 - "engines": { 15150 - "node": ">=16" 15151 - }, 15152 - "funding": { 15153 - "type": "individual", 15154 - "url": "https://github.com/sponsors/ahmadnassri" 15155 - }, 15156 - "peerDependencies": { 15157 - "glob": "^8.0.3" 15158 - } 15159 - }, 15160 "node_modules/glob-to-regexp": { 15161 "version": "0.4.1", 15162 "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", ··· 15166 "version": "2.0.1", 15167 "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 15168 "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 15169 - "dev": true, 15170 "dependencies": { 15171 "balanced-match": "^1.0.0" 15172 } 15173 }, 15174 "node_modules/glob/node_modules/minimatch": { 15175 - "version": "5.1.6", 15176 - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", 15177 - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", 15178 - "dev": true, 15179 "dependencies": { 15180 "brace-expansion": "^2.0.1" 15181 }, 15182 "engines": { 15183 - "node": ">=10" 15184 } 15185 }, 15186 "node_modules/global-modules": { ··· 15304 "version": "4.0.3", 15305 "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", 15306 "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", 15307 "dependencies": { 15308 "js-yaml": "^3.13.1", 15309 "kind-of": "^6.0.2", ··· 15318 "version": "1.0.10", 15319 "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 15320 "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 15321 "dependencies": { 15322 "sprintf-js": "~1.0.2" 15323 } ··· 15326 "version": "3.14.1", 15327 "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", 15328 "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", 15329 "dependencies": { 15330 "argparse": "^1.0.7", 15331 "esprima": "^4.0.0" ··· 15505 "node": ">=4" 15506 } 15507 }, 15508 - "node_modules/hash-obj": { 15509 - "version": "4.0.0", 15510 - "resolved": "https://registry.npmjs.org/hash-obj/-/hash-obj-4.0.0.tgz", 15511 - "integrity": "sha512-FwO1BUVWkyHasWDW4S8o0ssQXjvyghLV2rfVhnN36b2bbcj45eGiuzdn9XOvOpjV3TKQD7Gm2BWNXdE9V4KKYg==", 15512 - "dependencies": { 15513 - "is-obj": "^3.0.0", 15514 - "sort-keys": "^5.0.0", 15515 - "type-fest": "^1.0.2" 15516 - }, 15517 - "engines": { 15518 - "node": ">=12" 15519 - }, 15520 - "funding": { 15521 - "url": "https://github.com/sponsors/sindresorhus" 15522 - } 15523 - }, 15524 - "node_modules/hash-obj/node_modules/type-fest": { 15525 - "version": "1.4.0", 15526 - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", 15527 - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", 15528 - "engines": { 15529 - "node": ">=10" 15530 - }, 15531 - "funding": { 15532 - "url": "https://github.com/sponsors/sindresorhus" 15533 - } 15534 - }, 15535 "node_modules/hash.js": { 15536 "version": "1.1.7", 15537 "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", ··· 15567 "node": ">=8" 15568 } 15569 }, 15570 - "node_modules/hast-util-from-dom": { 15571 - "version": "4.2.0", 15572 - "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-4.2.0.tgz", 15573 - "integrity": "sha512-t1RJW/OpJbCAJQeKi3Qrj1cAOLA0+av/iPFori112+0X7R3wng+jxLA+kXec8K4szqPRGI8vPxbbpEYvvpwaeQ==", 15574 - "dependencies": { 15575 - "hastscript": "^7.0.0", 15576 - "web-namespaces": "^2.0.0" 15577 - }, 15578 - "funding": { 15579 - "type": "opencollective", 15580 - "url": "https://opencollective.com/unified" 15581 - } 15582 - }, 15583 - "node_modules/hast-util-from-html": { 15584 - "version": "1.0.2", 15585 - "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-1.0.2.tgz", 15586 - "integrity": "sha512-LhrTA2gfCbLOGJq2u/asp4kwuG0y6NhWTXiPKP+n0qNukKy7hc10whqqCFfyvIA1Q5U5d0sp9HhNim9gglEH4A==", 15587 - "dependencies": { 15588 - "@types/hast": "^2.0.0", 15589 - "hast-util-from-parse5": "^7.0.0", 15590 - "parse5": "^7.0.0", 15591 - "vfile": "^5.0.0", 15592 - "vfile-message": "^3.0.0" 15593 - }, 15594 - "funding": { 15595 - "type": "opencollective", 15596 - "url": "https://opencollective.com/unified" 15597 - } 15598 - }, 15599 - "node_modules/hast-util-from-html-isomorphic": { 15600 - "version": "1.0.0", 15601 - "resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-1.0.0.tgz", 15602 - "integrity": "sha512-Yu480AKeOEN/+l5LA674a+7BmIvtDj24GvOt7MtQWuhzUwlaaRWdEPXAh3Qm5vhuthpAipFb2vTetKXWOjmTvw==", 15603 - "dependencies": { 15604 - "@types/hast": "^2.0.0", 15605 - "hast-util-from-dom": "^4.0.0", 15606 - "hast-util-from-html": "^1.0.0", 15607 - "unist-util-remove-position": "^4.0.0" 15608 - }, 15609 - "funding": { 15610 - "type": "opencollective", 15611 - "url": "https://opencollective.com/unified" 15612 - } 15613 - }, 15614 - "node_modules/hast-util-from-parse5": { 15615 - "version": "7.1.2", 15616 - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz", 15617 - "integrity": "sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==", 15618 - "dependencies": { 15619 - "@types/hast": "^2.0.0", 15620 - "@types/unist": "^2.0.0", 15621 - "hastscript": "^7.0.0", 15622 - "property-information": "^6.0.0", 15623 - "vfile": "^5.0.0", 15624 - "vfile-location": "^4.0.0", 15625 - "web-namespaces": "^2.0.0" 15626 - }, 15627 - "funding": { 15628 - "type": "opencollective", 15629 - "url": "https://opencollective.com/unified" 15630 - } 15631 - }, 15632 - "node_modules/hast-util-is-element": { 15633 - "version": "2.1.3", 15634 - "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-2.1.3.tgz", 15635 - "integrity": "sha512-O1bKah6mhgEq2WtVMk+Ta5K7pPMqsBBlmzysLdcwKVrqzZQ0CHqUPiIVspNhAG1rvxpvJjtGee17XfauZYKqVA==", 15636 - "dependencies": { 15637 - "@types/hast": "^2.0.0", 15638 - "@types/unist": "^2.0.0" 15639 - }, 15640 - "funding": { 15641 - "type": "opencollective", 15642 - "url": "https://opencollective.com/unified" 15643 - } 15644 - }, 15645 - "node_modules/hast-util-parse-selector": { 15646 - "version": "3.1.1", 15647 - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", 15648 - "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", 15649 - "dependencies": { 15650 - "@types/hast": "^2.0.0" 15651 - }, 15652 - "funding": { 15653 - "type": "opencollective", 15654 - "url": "https://opencollective.com/unified" 15655 - } 15656 - }, 15657 "node_modules/hast-util-to-estree": { 15658 "version": "2.3.3", 15659 "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-2.3.3.tgz", ··· 15685 "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", 15686 "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" 15687 }, 15688 - "node_modules/hast-util-to-text": { 15689 - "version": "3.1.2", 15690 - "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-3.1.2.tgz", 15691 - "integrity": "sha512-tcllLfp23dJJ+ju5wCCZHVpzsQQ43+moJbqVX3jNWPB7z/KFC4FyZD6R7y94cHL6MQ33YtMZL8Z0aIXXI4XFTw==", 15692 - "dependencies": { 15693 - "@types/hast": "^2.0.0", 15694 - "@types/unist": "^2.0.0", 15695 - "hast-util-is-element": "^2.0.0", 15696 - "unist-util-find-after": "^4.0.0" 15697 - }, 15698 - "funding": { 15699 - "type": "opencollective", 15700 - "url": "https://opencollective.com/unified" 15701 - } 15702 - }, 15703 "node_modules/hast-util-whitespace": { 15704 "version": "2.0.1", 15705 "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", ··· 15709 "url": "https://opencollective.com/unified" 15710 } 15711 }, 15712 - "node_modules/hastscript": { 15713 - "version": "7.2.0", 15714 - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", 15715 - "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", 15716 - "dependencies": { 15717 - "@types/hast": "^2.0.0", 15718 - "comma-separated-tokens": "^2.0.0", 15719 - "hast-util-parse-selector": "^3.0.0", 15720 - "property-information": "^6.0.0", 15721 - "space-separated-tokens": "^2.0.0" 15722 - }, 15723 - "funding": { 15724 - "type": "opencollective", 15725 - "url": "https://opencollective.com/unified" 15726 - } 15727 - }, 15728 "node_modules/he": { 15729 "version": "1.2.0", 15730 "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", ··· 15733 "bin": { 15734 "he": "bin/he" 15735 } 15736 - }, 15737 - "node_modules/heap": { 15738 - "version": "0.2.7", 15739 - "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", 15740 - "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==" 15741 }, 15742 "node_modules/highlight.js": { 15743 "version": "11.8.0", ··· 16226 "node": ">= 0.4" 16227 } 16228 }, 16229 - "node_modules/internmap": { 16230 - "version": "2.0.3", 16231 - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", 16232 - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", 16233 - "engines": { 16234 - "node": ">=12" 16235 - } 16236 - }, 16237 "node_modules/interpret": { 16238 "version": "1.4.0", 16239 "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", ··· 16468 "version": "0.1.1", 16469 "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", 16470 "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", 16471 "engines": { 16472 "node": ">=0.10.0" 16473 } ··· 16484 "version": "3.0.0", 16485 "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 16486 "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 16487 - "dev": true, 16488 "engines": { 16489 "node": ">=8" 16490 } ··· 16645 "url": "https://github.com/sponsors/ljharb" 16646 } 16647 }, 16648 - "node_modules/is-obj": { 16649 - "version": "3.0.0", 16650 - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-3.0.0.tgz", 16651 - "integrity": "sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==", 16652 - "engines": { 16653 - "node": ">=12" 16654 - }, 16655 - "funding": { 16656 - "url": "https://github.com/sponsors/sindresorhus" 16657 - } 16658 - }, 16659 "node_modules/is-path-cwd": { 16660 "version": "2.2.0", 16661 "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", ··· 16672 "dev": true, 16673 "engines": { 16674 "node": ">=8" 16675 - } 16676 - }, 16677 - "node_modules/is-plain-obj": { 16678 - "version": "3.0.0", 16679 - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", 16680 - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", 16681 - "engines": { 16682 - "node": ">=10" 16683 - }, 16684 - "funding": { 16685 - "url": "https://github.com/sponsors/sindresorhus" 16686 } 16687 }, 16688 "node_modules/is-plain-object": { ··· 16857 "url": "https://github.com/sponsors/ljharb" 16858 } 16859 }, 16860 "node_modules/is-windows": { 16861 "version": "1.0.2", 16862 "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", ··· 17056 "version": "2.2.1", 17057 "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", 17058 "integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==", 17059 - "dev": true, 17060 "dependencies": { 17061 "@isaacs/cliui": "^8.0.2" 17062 }, ··· 19994 "node": ">=6" 19995 } 19996 }, 19997 - "node_modules/jsonc-parser": { 19998 - "version": "3.2.0", 19999 - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", 20000 - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==" 20001 - }, 20002 "node_modules/jsonfile": { 20003 "version": "6.1.0", 20004 "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", ··· 20024 "node": ">=4.0" 20025 } 20026 }, 20027 - "node_modules/katex": { 20028 - "version": "0.16.8", 20029 - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.8.tgz", 20030 - "integrity": "sha512-ftuDnJbcbOckGY11OO+zg3OofESlbR5DRl2cmN8HeWeeFIV7wTXvAOx8kEjZjobhA+9wh2fbKeO6cdcA9Mnovg==", 20031 - "funding": [ 20032 - "https://opencollective.com/katex", 20033 - "https://github.com/sponsors/katex" 20034 - ], 20035 - "dependencies": { 20036 - "commander": "^8.3.0" 20037 - }, 20038 - "bin": { 20039 - "katex": "cli.js" 20040 - } 20041 - }, 20042 - "node_modules/katex/node_modules/commander": { 20043 - "version": "8.3.0", 20044 - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", 20045 - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", 20046 - "engines": { 20047 - "node": ">= 12" 20048 - } 20049 - }, 20050 - "node_modules/khroma": { 20051 - "version": "2.0.0", 20052 - "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.0.0.tgz", 20053 - "integrity": "sha512-2J8rDNlQWbtiNYThZRvmMv5yt44ZakX+Tz5ZIp/mN1pt4snn+m030Va5Z4v8xA0cQFDXBwO/8i42xL4QPsVk3g==" 20054 - }, 20055 "node_modules/kind-of": { 20056 "version": "6.0.3", 20057 "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", 20058 "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", 20059 "engines": { 20060 "node": ">=0.10.0" 20061 } ··· 20098 "dependencies": { 20099 "language-subtag-registry": "~0.3.2" 20100 } 20101 - }, 20102 - "node_modules/layout-base": { 20103 - "version": "1.0.2", 20104 - "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", 20105 - "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==" 20106 }, 20107 "node_modules/lazy-universal-dotenv": { 20108 "version": "4.0.0", ··· 20195 "node_modules/lodash": { 20196 "version": "4.17.21", 20197 "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 20198 - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 20199 - }, 20200 - "node_modules/lodash-es": { 20201 - "version": "4.17.21", 20202 - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", 20203 - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" 20204 }, 20205 "node_modules/lodash.debounce": { 20206 "version": "4.0.8", ··· 20214 "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", 20215 "dev": true 20216 }, 20217 - "node_modules/lodash.get": { 20218 - "version": "4.4.2", 20219 - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", 20220 - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" 20221 - }, 20222 "node_modules/lodash.merge": { 20223 "version": "4.6.2", 20224 "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", ··· 20731 "dev": true, 20732 "dependencies": { 20733 "@types/mdast": "^3.0.0" 20734 - }, 20735 - "funding": { 20736 - "type": "opencollective", 20737 - "url": "https://opencollective.com/unified" 20738 - } 20739 - }, 20740 - "node_modules/mdast-util-math": { 20741 - "version": "2.0.2", 20742 - "resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-2.0.2.tgz", 20743 - "integrity": "sha512-8gmkKVp9v6+Tgjtq6SYx9kGPpTf6FVYRa53/DLh479aldR9AyP48qeVOgNZ5X7QUK7nOy4yw7vg6mbiGcs9jWQ==", 20744 - "dependencies": { 20745 - "@types/mdast": "^3.0.0", 20746 - "longest-streak": "^3.0.0", 20747 - "mdast-util-to-markdown": "^1.3.0" 20748 }, 20749 "funding": { 20750 "type": "opencollective", ··· 21436 "node": ">= 8" 21437 } 21438 }, 21439 - "node_modules/mermaid": { 21440 - "version": "10.2.3", 21441 - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.2.3.tgz", 21442 - "integrity": "sha512-cMVE5s9PlQvOwfORkyVpr5beMsLdInrycAosdr+tpZ0WFjG4RJ/bUHST7aTgHNJbujHkdBRAm+N50P3puQOfPw==", 21443 - "dependencies": { 21444 - "@braintree/sanitize-url": "^6.0.2", 21445 - "cytoscape": "^3.23.0", 21446 - "cytoscape-cose-bilkent": "^4.1.0", 21447 - "cytoscape-fcose": "^2.1.0", 21448 - "d3": "^7.4.0", 21449 - "dagre-d3-es": "7.0.10", 21450 - "dayjs": "^1.11.7", 21451 - "dompurify": "3.0.3", 21452 - "elkjs": "^0.8.2", 21453 - "khroma": "^2.0.0", 21454 - "lodash-es": "^4.17.21", 21455 - "mdast-util-from-markdown": "^1.3.0", 21456 - "non-layered-tidy-tree-layout": "^2.0.2", 21457 - "stylis": "^4.1.3", 21458 - "ts-dedent": "^2.2.0", 21459 - "uuid": "^9.0.0", 21460 - "web-worker": "^1.2.0" 21461 - } 21462 - }, 21463 - "node_modules/mermaid/node_modules/mdast-util-from-markdown": { 21464 - "version": "1.3.1", 21465 - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz", 21466 - "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==", 21467 - "dependencies": { 21468 - "@types/mdast": "^3.0.0", 21469 - "@types/unist": "^2.0.0", 21470 - "decode-named-character-reference": "^1.0.0", 21471 - "mdast-util-to-string": "^3.1.0", 21472 - "micromark": "^3.0.0", 21473 - "micromark-util-decode-numeric-character-reference": "^1.0.0", 21474 - "micromark-util-decode-string": "^1.0.0", 21475 - "micromark-util-normalize-identifier": "^1.0.0", 21476 - "micromark-util-symbol": "^1.0.0", 21477 - "micromark-util-types": "^1.0.0", 21478 - "unist-util-stringify-position": "^3.0.0", 21479 - "uvu": "^0.5.0" 21480 - }, 21481 - "funding": { 21482 - "type": "opencollective", 21483 - "url": "https://opencollective.com/unified" 21484 - } 21485 - }, 21486 - "node_modules/mermaid/node_modules/mdast-util-to-string": { 21487 - "version": "3.2.0", 21488 - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", 21489 - "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", 21490 - "dependencies": { 21491 - "@types/mdast": "^3.0.0" 21492 - }, 21493 - "funding": { 21494 - "type": "opencollective", 21495 - "url": "https://opencollective.com/unified" 21496 - } 21497 - }, 21498 - "node_modules/mermaid/node_modules/micromark": { 21499 - "version": "3.2.0", 21500 - "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", 21501 - "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==", 21502 - "funding": [ 21503 - { 21504 - "type": "GitHub Sponsors", 21505 - "url": "https://github.com/sponsors/unifiedjs" 21506 - }, 21507 - { 21508 - "type": "OpenCollective", 21509 - "url": "https://opencollective.com/unified" 21510 - } 21511 - ], 21512 - "dependencies": { 21513 - "@types/debug": "^4.0.0", 21514 - "debug": "^4.0.0", 21515 - "decode-named-character-reference": "^1.0.0", 21516 - "micromark-core-commonmark": "^1.0.1", 21517 - "micromark-factory-space": "^1.0.0", 21518 - "micromark-util-character": "^1.0.0", 21519 - "micromark-util-chunked": "^1.0.0", 21520 - "micromark-util-combine-extensions": "^1.0.0", 21521 - "micromark-util-decode-numeric-character-reference": "^1.0.0", 21522 - "micromark-util-encode": "^1.0.0", 21523 - "micromark-util-normalize-identifier": "^1.0.0", 21524 - "micromark-util-resolve-all": "^1.0.0", 21525 - "micromark-util-sanitize-uri": "^1.0.0", 21526 - "micromark-util-subtokenize": "^1.0.0", 21527 - "micromark-util-symbol": "^1.0.0", 21528 - "micromark-util-types": "^1.0.1", 21529 - "uvu": "^0.5.0" 21530 - } 21531 - }, 21532 - "node_modules/mermaid/node_modules/unist-util-stringify-position": { 21533 - "version": "3.0.3", 21534 - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", 21535 - "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", 21536 - "dependencies": { 21537 - "@types/unist": "^2.0.0" 21538 - }, 21539 - "funding": { 21540 - "type": "opencollective", 21541 - "url": "https://opencollective.com/unified" 21542 - } 21543 - }, 21544 "node_modules/methods": { 21545 "version": "1.1.2", 21546 "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", ··· 21716 "type": "opencollective", 21717 "url": "https://opencollective.com/unified" 21718 } 21719 - }, 21720 - "node_modules/micromark-extension-math": { 21721 - "version": "2.1.2", 21722 - "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-2.1.2.tgz", 21723 - "integrity": "sha512-es0CcOV89VNS9wFmyn+wyFTKweXGW4CEvdaAca6SWRWPyYCbBisnjaHLjWO4Nszuiud84jCpkHsqAJoa768Pvg==", 21724 - "dependencies": { 21725 - "@types/katex": "^0.16.0", 21726 - "katex": "^0.16.0", 21727 - "micromark-factory-space": "^1.0.0", 21728 - "micromark-util-character": "^1.0.0", 21729 - "micromark-util-symbol": "^1.0.0", 21730 - "micromark-util-types": "^1.0.0", 21731 - "uvu": "^0.5.0" 21732 - }, 21733 - "funding": { 21734 - "type": "opencollective", 21735 - "url": "https://opencollective.com/unified" 21736 - } 21737 - }, 21738 - "node_modules/micromark-extension-math/node_modules/@types/katex": { 21739 - "version": "0.16.0", 21740 - "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.0.tgz", 21741 - "integrity": "sha512-hz+S3nV6Mym5xPbT9fnO8dDhBFQguMYpY0Ipxv06JMi1ORgnEM4M1ymWDUhUNer3ElLmT583opRo4RzxKmh9jw==" 21742 }, 21743 "node_modules/micromark-extension-mdx-expression": { 21744 "version": "1.0.8", ··· 22428 "version": "5.0.0", 22429 "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", 22430 "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", 22431 - "dev": true, 22432 "engines": { 22433 "node": ">=8" 22434 } ··· 22639 "next": "*" 22640 } 22641 }, 22642 "node_modules/next-themes": { 22643 "version": "0.2.1", 22644 "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.2.1.tgz", ··· 22670 }, 22671 "engines": { 22672 "node": "^10 || ^12 || >=14" 22673 - } 22674 - }, 22675 - "node_modules/nextra": { 22676 - "version": "2.8.0", 22677 - "resolved": "https://registry.npmjs.org/nextra/-/nextra-2.8.0.tgz", 22678 - "integrity": "sha512-WyRNzw1IM/eF3M1H3LSsbZH97QsYYgj8upjx0f8hY6GspmPyPRAvBBscmXRt+7vye2oIYjfVwSiD1rj9amqq9Q==", 22679 - "dependencies": { 22680 - "@mdx-js/mdx": "^2.3.0", 22681 - "@mdx-js/react": "^2.3.0", 22682 - "@napi-rs/simple-git": "^0.1.8", 22683 - "@theguild/remark-mermaid": "^0.0.3", 22684 - "clsx": "^1.2.1", 22685 - "github-slugger": "^2.0.0", 22686 - "graceful-fs": "^4.2.11", 22687 - "gray-matter": "^4.0.3", 22688 - "katex": "^0.16.7", 22689 - "lodash.get": "^4.4.2", 22690 - "next-mdx-remote": "^4.2.1", 22691 - "p-limit": "^3.1.0", 22692 - "rehype-katex": "^6.0.3", 22693 - "rehype-pretty-code": "0.9.9", 22694 - "remark-gfm": "^3.0.1", 22695 - "remark-math": "^5.1.1", 22696 - "remark-reading-time": "^2.0.1", 22697 - "shiki": "^0.14.2", 22698 - "slash": "^3.0.0", 22699 - "title": "^3.5.3", 22700 - "unist-util-remove": "^3.1.1", 22701 - "unist-util-visit": "^4.1.1", 22702 - "zod": "^3.20.2" 22703 - }, 22704 - "engines": { 22705 - "node": ">=16" 22706 - }, 22707 - "peerDependencies": { 22708 - "next": ">=9.5.3", 22709 - "react": ">=16.13.1", 22710 - "react-dom": ">=16.13.1" 22711 } 22712 }, 22713 "node_modules/no-case": { ··· 22879 "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", 22880 "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==", 22881 "dev": true 22882 - }, 22883 - "node_modules/non-layered-tidy-tree-layout": { 22884 - "version": "2.0.2", 22885 - "resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", 22886 - "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==" 22887 }, 22888 "node_modules/nopt": { 22889 "version": "7.2.0", ··· 23471 "node": ">=0.10.0" 23472 } 23473 }, 23474 - "node_modules/p-finally": { 23475 - "version": "1.0.0", 23476 - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", 23477 - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", 23478 - "engines": { 23479 - "node": ">=4" 23480 - } 23481 - }, 23482 "node_modules/p-limit": { 23483 "version": "3.1.0", 23484 "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 23485 "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 23486 "dependencies": { 23487 "yocto-queue": "^0.1.0" 23488 }, ··· 23632 "url": "https://github.com/sponsors/sindresorhus" 23633 } 23634 }, 23635 - "node_modules/parse-numeric-range": { 23636 - "version": "1.3.0", 23637 - "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", 23638 - "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" 23639 - }, 23640 "node_modules/parse-passwd": { 23641 "version": "1.0.0", 23642 "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", ··· 23728 "version": "1.9.2", 23729 "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.9.2.tgz", 23730 "integrity": "sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==", 23731 - "dev": true, 23732 "dependencies": { 23733 "lru-cache": "^9.1.1", 23734 "minipass": "^5.0.0 || ^6.0.2" ··· 23744 "version": "9.1.2", 23745 "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.2.tgz", 23746 "integrity": "sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==", 23747 - "dev": true, 23748 "engines": { 23749 "node": "14 || >=16.14" 23750 } ··· 24380 "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", 24381 "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", 24382 "dev": true 24383 - }, 24384 - "node_modules/pseudomap": { 24385 - "version": "1.0.2", 24386 - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", 24387 - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" 24388 }, 24389 "node_modules/psl": { 24390 "version": "1.9.0", ··· 25016 "node": ">=8.10.0" 25017 } 25018 }, 25019 - "node_modules/reading-time": { 25020 - "version": "1.5.0", 25021 - "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", 25022 - "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==" 25023 - }, 25024 "node_modules/recast": { 25025 "version": "0.23.2", 25026 "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.2.tgz", ··· 25176 "jsesc": "bin/jsesc" 25177 } 25178 }, 25179 - "node_modules/rehype-katex": { 25180 - "version": "6.0.3", 25181 - "resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-6.0.3.tgz", 25182 - "integrity": "sha512-ByZlRwRUcWegNbF70CVRm2h/7xy7jQ3R9LaY4VVSvjnoVWwWVhNL60DiZsBpC5tSzYQOCvDbzncIpIjPZWodZA==", 25183 - "dependencies": { 25184 - "@types/hast": "^2.0.0", 25185 - "@types/katex": "^0.14.0", 25186 - "hast-util-from-html-isomorphic": "^1.0.0", 25187 - "hast-util-to-text": "^3.1.0", 25188 - "katex": "^0.16.0", 25189 - "unist-util-visit": "^4.0.0" 25190 - }, 25191 - "funding": { 25192 - "type": "opencollective", 25193 - "url": "https://opencollective.com/unified" 25194 - } 25195 - }, 25196 - "node_modules/rehype-pretty-code": { 25197 - "version": "0.9.9", 25198 - "resolved": "https://registry.npmjs.org/rehype-pretty-code/-/rehype-pretty-code-0.9.9.tgz", 25199 - "integrity": "sha512-mlU2Qgupn9MMK31CTmWk0Ie5Vp0od+jh2vCkGDBMlPAMeAvYASn6Ois6xRmosutMT4yH/COc3R4r/PELpuUoWg==", 25200 - "dependencies": { 25201 - "@types/hast": "^2.0.0", 25202 - "hash-obj": "^4.0.0", 25203 - "parse-numeric-range": "^1.3.0" 25204 - }, 25205 - "engines": { 25206 - "node": ">=16" 25207 - }, 25208 - "peerDependencies": { 25209 - "shiki": "*" 25210 - } 25211 - }, 25212 "node_modules/relateurl": { 25213 "version": "0.2.7", 25214 "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", ··· 26057 "unist-util-generated": "^2.0.0", 26058 "unist-util-position": "^4.0.0", 26059 "unist-util-visit": "^4.0.0" 26060 - }, 26061 - "funding": { 26062 - "type": "opencollective", 26063 - "url": "https://opencollective.com/unified" 26064 - } 26065 - }, 26066 - "node_modules/remark-math": { 26067 - "version": "5.1.1", 26068 - "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-5.1.1.tgz", 26069 - "integrity": "sha512-cE5T2R/xLVtfFI4cCePtiRn+e6jKMtFDR3P8V3qpv8wpKjwvHoBA4eJzvX+nVrnlNy0911bdGmuspCSwetfYHw==", 26070 - "dependencies": { 26071 - "@types/mdast": "^3.0.0", 26072 - "mdast-util-math": "^2.0.0", 26073 - "micromark-extension-math": "^2.0.0", 26074 - "unified": "^10.0.0" 26075 }, 26076 "funding": { 26077 "type": "opencollective", ··· 26290 "prettier": ">=1.0.0" 26291 } 26292 }, 26293 - "node_modules/remark-reading-time": { 26294 - "version": "2.0.1", 26295 - "resolved": "https://registry.npmjs.org/remark-reading-time/-/remark-reading-time-2.0.1.tgz", 26296 - "integrity": "sha512-fy4BKy9SRhtYbEHvp6AItbRTnrhiDGbqLQTSYVbQPGuRCncU1ubSsh9p/W5QZSxtYcUXv8KGL0xBgPLyNJA1xw==", 26297 - "dependencies": { 26298 - "estree-util-is-identifier-name": "^2.0.0", 26299 - "estree-util-value-to-estree": "^1.3.0", 26300 - "reading-time": "^1.3.0", 26301 - "unist-util-visit": "^3.1.0" 26302 - } 26303 - }, 26304 - "node_modules/remark-reading-time/node_modules/unist-util-visit": { 26305 - "version": "3.1.0", 26306 - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-3.1.0.tgz", 26307 - "integrity": "sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA==", 26308 - "dependencies": { 26309 - "@types/unist": "^2.0.0", 26310 - "unist-util-is": "^5.0.0", 26311 - "unist-util-visit-parents": "^4.0.0" 26312 - }, 26313 - "funding": { 26314 - "type": "opencollective", 26315 - "url": "https://opencollective.com/unified" 26316 - } 26317 - }, 26318 - "node_modules/remark-reading-time/node_modules/unist-util-visit-parents": { 26319 - "version": "4.1.1", 26320 - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-4.1.1.tgz", 26321 - "integrity": "sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw==", 26322 - "dependencies": { 26323 - "@types/unist": "^2.0.0", 26324 - "unist-util-is": "^5.0.0" 26325 - }, 26326 - "funding": { 26327 - "type": "opencollective", 26328 - "url": "https://opencollective.com/unified" 26329 - } 26330 - }, 26331 "node_modules/remark-rehype": { 26332 "version": "10.1.0", 26333 "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-10.1.0.tgz", ··· 26716 "inherits": "^2.0.1" 26717 } 26718 }, 26719 - "node_modules/robust-predicates": { 26720 - "version": "3.0.2", 26721 - "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", 26722 - "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" 26723 - }, 26724 "node_modules/rrweb-cssom": { 26725 "version": "0.6.0", 26726 "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", ··· 26764 "queue-microtask": "^1.2.2" 26765 } 26766 }, 26767 - "node_modules/rw": { 26768 - "version": "1.3.3", 26769 - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", 26770 - "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" 26771 - }, 26772 "node_modules/rxjs": { 26773 "version": "7.8.1", 26774 "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", ··· 26928 "version": "1.0.0", 26929 "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", 26930 "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", 26931 "dependencies": { 26932 "extend-shallow": "^2.0.1", 26933 "kind-of": "^6.0.0" ··· 27193 "url": "https://github.com/sponsors/isaacs" 27194 } 27195 }, 27196 - "node_modules/shiki": { 27197 - "version": "0.14.3", 27198 - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.3.tgz", 27199 - "integrity": "sha512-U3S/a+b0KS+UkTyMjoNojvTgrBHjgp7L6ovhFVZsXmBGnVdQ4K4U9oK0z63w538S91ATngv1vXigHCSWOwnr+g==", 27200 - "dependencies": { 27201 - "ansi-sequence-parser": "^1.1.0", 27202 - "jsonc-parser": "^3.2.0", 27203 - "vscode-oniguruma": "^1.7.0", 27204 - "vscode-textmate": "^8.0.0" 27205 - } 27206 - }, 27207 "node_modules/side-channel": { 27208 "version": "1.0.4", 27209 "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", ··· 27221 "node_modules/signal-exit": { 27222 "version": "3.0.7", 27223 "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", 27224 - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" 27225 }, 27226 "node_modules/simple-concat": { 27227 "version": "1.0.1", ··· 27310 "version": "3.0.0", 27311 "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", 27312 "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", 27313 "engines": { 27314 "node": ">=8" 27315 } ··· 27337 "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA==", 27338 "dev": true 27339 }, 27340 - "node_modules/sort-keys": { 27341 - "version": "5.0.0", 27342 - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-5.0.0.tgz", 27343 - "integrity": "sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw==", 27344 - "dependencies": { 27345 - "is-plain-obj": "^4.0.0" 27346 - }, 27347 - "engines": { 27348 - "node": ">=12" 27349 - }, 27350 - "funding": { 27351 - "url": "https://github.com/sponsors/sindresorhus" 27352 - } 27353 - }, 27354 - "node_modules/sort-keys/node_modules/is-plain-obj": { 27355 - "version": "4.1.0", 27356 - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", 27357 - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", 27358 - "engines": { 27359 - "node": ">=12" 27360 - }, 27361 - "funding": { 27362 - "url": "https://github.com/sponsors/sindresorhus" 27363 - } 27364 - }, 27365 "node_modules/source-map": { 27366 "version": "0.5.7", 27367 "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", ··· 27476 "node_modules/sprintf-js": { 27477 "version": "1.0.3", 27478 "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 27479 - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" 27480 }, 27481 "node_modules/stack-utils": { 27482 "version": "2.0.6", ··· 27618 "version": "4.2.3", 27619 "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 27620 "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 27621 - "dev": true, 27622 "dependencies": { 27623 "emoji-regex": "^8.0.0", 27624 "is-fullwidth-code-point": "^3.0.0", ··· 27633 "version": "4.2.3", 27634 "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 27635 "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 27636 - "dev": true, 27637 "dependencies": { 27638 "emoji-regex": "^8.0.0", 27639 "is-fullwidth-code-point": "^3.0.0", ··· 27646 "node_modules/string-width-cjs/node_modules/emoji-regex": { 27647 "version": "8.0.0", 27648 "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 27649 - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 27650 - "dev": true 27651 }, 27652 "node_modules/string-width/node_modules/emoji-regex": { 27653 "version": "8.0.0", 27654 "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 27655 - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 27656 - "dev": true 27657 }, 27658 "node_modules/string.prototype.matchall": { 27659 "version": "4.0.8", ··· 27745 "version": "6.0.1", 27746 "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 27747 "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 27748 - "dev": true, 27749 "dependencies": { 27750 "ansi-regex": "^5.0.1" 27751 }, ··· 27758 "version": "6.0.1", 27759 "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 27760 "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 27761 - "dev": true, 27762 "dependencies": { 27763 "ansi-regex": "^5.0.1" 27764 }, ··· 27779 "version": "1.0.0", 27780 "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", 27781 "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", 27782 - "engines": { 27783 - "node": ">=0.10.0" 27784 - } 27785 - }, 27786 - "node_modules/strip-eof": { 27787 - "version": "1.0.0", 27788 - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", 27789 - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", 27790 "engines": { 27791 "node": ">=0.10.0" 27792 } ··· 28069 "version": "4.2.0", 28070 "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", 28071 "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" 28072 }, 28073 "node_modules/supports-color": { 28074 "version": "7.2.0", ··· 28589 "node": ">=0.6.0" 28590 } 28591 }, 28592 - "node_modules/title": { 28593 - "version": "3.5.3", 28594 - "resolved": "https://registry.npmjs.org/title/-/title-3.5.3.tgz", 28595 - "integrity": "sha512-20JyowYglSEeCvZv3EZ0nZ046vLarO37prvV0mbtQV7C8DJPGgN967r8SJkqd3XK3K3lD3/Iyfp3avjfil8Q2Q==", 28596 - "dependencies": { 28597 - "arg": "1.0.0", 28598 - "chalk": "2.3.0", 28599 - "clipboardy": "1.2.2", 28600 - "titleize": "1.0.0" 28601 - }, 28602 - "bin": { 28603 - "title": "bin/title.js" 28604 - } 28605 - }, 28606 - "node_modules/title/node_modules/ansi-styles": { 28607 - "version": "3.2.1", 28608 - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 28609 - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 28610 - "dependencies": { 28611 - "color-convert": "^1.9.0" 28612 - }, 28613 - "engines": { 28614 - "node": ">=4" 28615 - } 28616 - }, 28617 - "node_modules/title/node_modules/chalk": { 28618 - "version": "2.3.0", 28619 - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", 28620 - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", 28621 - "dependencies": { 28622 - "ansi-styles": "^3.1.0", 28623 - "escape-string-regexp": "^1.0.5", 28624 - "supports-color": "^4.0.0" 28625 - }, 28626 - "engines": { 28627 - "node": ">=4" 28628 - } 28629 - }, 28630 - "node_modules/title/node_modules/color-convert": { 28631 - "version": "1.9.3", 28632 - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 28633 - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 28634 - "dependencies": { 28635 - "color-name": "1.1.3" 28636 - } 28637 - }, 28638 - "node_modules/title/node_modules/color-name": { 28639 - "version": "1.1.3", 28640 - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 28641 - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" 28642 - }, 28643 - "node_modules/title/node_modules/escape-string-regexp": { 28644 - "version": "1.0.5", 28645 - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 28646 - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", 28647 - "engines": { 28648 - "node": ">=0.8.0" 28649 - } 28650 - }, 28651 - "node_modules/title/node_modules/has-flag": { 28652 - "version": "2.0.0", 28653 - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", 28654 - "integrity": "sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng==", 28655 - "engines": { 28656 - "node": ">=0.10.0" 28657 - } 28658 - }, 28659 - "node_modules/title/node_modules/supports-color": { 28660 - "version": "4.5.0", 28661 - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", 28662 - "integrity": "sha512-ycQR/UbvI9xIlEdQT1TQqwoXtEldExbCEAJgRo5YXlmSKjv6ThHnP9/vwGa1gr19Gfw+LkFd7KqYMhzrRC5JYw==", 28663 - "dependencies": { 28664 - "has-flag": "^2.0.0" 28665 - }, 28666 - "engines": { 28667 - "node": ">=4" 28668 - } 28669 - }, 28670 - "node_modules/titleize": { 28671 - "version": "1.0.0", 28672 - "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.0.tgz", 28673 - "integrity": "sha512-TARUb7z1pGvlLxgPk++7wJ6aycXF3GJ0sNSBTAsTuJrQG5QuZlkUQP+zl+nbjAh4gMX9yDw9ZYklMd7vAfJKEw==", 28674 - "engines": { 28675 - "node": ">=0.10.0" 28676 - } 28677 - }, 28678 "node_modules/tmpl": { 28679 "version": "1.0.5", 28680 "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", ··· 28796 "version": "2.2.0", 28797 "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", 28798 "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", 28799 "engines": { 28800 "node": ">=6.10" 28801 } ··· 29238 "url": "https://opencollective.com/unified" 29239 } 29240 }, 29241 "node_modules/unified-engine/node_modules/concat-stream": { 29242 "version": "2.0.0", 29243 "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", ··· 29253 "typedarray": "^0.0.6" 29254 } 29255 }, 29256 "node_modules/unified-engine/node_modules/is-plain-obj": { 29257 "version": "4.1.0", 29258 "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", ··· 29274 "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 29275 } 29276 }, 29277 "node_modules/unified-engine/node_modules/parse-json": { 29278 "version": "6.0.2", 29279 "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-6.0.2.tgz", ··· 29387 "node": ">=8" 29388 } 29389 }, 29390 - "node_modules/unist-util-find-after": { 29391 - "version": "4.0.1", 29392 - "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-4.0.1.tgz", 29393 - "integrity": "sha512-QO/PuPMm2ERxC6vFXEPtmAutOopy5PknD+Oq64gGwxKtk4xwo9Z97t9Av1obPmGU0IyTa6EKYUfTrK2QJS3Ozw==", 29394 - "dependencies": { 29395 - "@types/unist": "^2.0.0", 29396 - "unist-util-is": "^5.0.0" 29397 - }, 29398 - "funding": { 29399 - "type": "opencollective", 29400 - "url": "https://opencollective.com/unified" 29401 - } 29402 - }, 29403 "node_modules/unist-util-generated": { 29404 "version": "2.0.1", 29405 "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.1.tgz", ··· 29458 "url": "https://opencollective.com/unified" 29459 } 29460 }, 29461 - "node_modules/unist-util-remove": { 29462 - "version": "3.1.1", 29463 - "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-3.1.1.tgz", 29464 - "integrity": "sha512-kfCqZK5YVY5yEa89tvpl7KnBBHu2c6CzMkqHUrlOqaRgGOMp0sMvwWOVrbAtj03KhovQB7i96Gda72v/EFE0vw==", 29465 - "dependencies": { 29466 - "@types/unist": "^2.0.0", 29467 - "unist-util-is": "^5.0.0", 29468 - "unist-util-visit-parents": "^5.0.0" 29469 - }, 29470 - "funding": { 29471 - "type": "opencollective", 29472 - "url": "https://opencollective.com/unified" 29473 - } 29474 - }, 29475 "node_modules/unist-util-remove-position": { 29476 "version": "4.0.2", 29477 "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-4.0.2.tgz", ··· 29680 "version": "9.0.0", 29681 "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", 29682 "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", 29683 "bin": { 29684 "uuid": "dist/bin/uuid" 29685 } ··· 29761 "version": "4.1.0", 29762 "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.1.0.tgz", 29763 "integrity": "sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==", 29764 "dependencies": { 29765 "@types/unist": "^2.0.0", 29766 "vfile": "^5.0.0" ··· 29944 "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", 29945 "dev": true 29946 }, 29947 - "node_modules/vscode-oniguruma": { 29948 - "version": "1.7.0", 29949 - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", 29950 - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==" 29951 - }, 29952 - "node_modules/vscode-textmate": { 29953 - "version": "8.0.0", 29954 - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", 29955 - "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==" 29956 - }, 29957 "node_modules/w3c-xmlserializer": { 29958 "version": "4.0.0", 29959 "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", ··· 30114 "defaults": "^1.0.3" 30115 } 30116 }, 30117 - "node_modules/web-namespaces": { 30118 - "version": "2.0.1", 30119 - "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", 30120 - "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", 30121 - "funding": { 30122 - "type": "github", 30123 - "url": "https://github.com/sponsors/wooorm" 30124 - } 30125 - }, 30126 - "node_modules/web-worker": { 30127 - "version": "1.2.0", 30128 - "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz", 30129 - "integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==" 30130 - }, 30131 "node_modules/webidl-conversions": { 30132 "version": "7.0.0", 30133 "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", ··· 30471 "version": "7.0.0", 30472 "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 30473 "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 30474 - "dev": true, 30475 "dependencies": { 30476 "ansi-styles": "^4.0.0", 30477 "string-width": "^4.1.0", ··· 30651 "version": "0.1.0", 30652 "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 30653 "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 30654 "engines": { 30655 "node": ">=10" 30656 },
··· 18 "classnames": "^2.3.2", 19 "cross-env": "^7.0.3", 20 "framer-motion": "^10.12.16", 21 + "glob": "^10.2.7", 22 "highlight.js": "^11.8.0", 23 "isomorphic-dompurify": "^1.5.0", 24 "next": "^13.4.3", 25 + "next-mdx-remote": "^4.4.1", 26 + "next-superjson-plugin": "^0.5.8", 27 "next-themes": "^0.2.1", 28 "prismjs": "^1.29.0", 29 "react": "^18.2.0", 30 "react-dom": "^18.2.0", ··· 35 "semver": "^7.5.1", 36 "sharp": "^0.32.1", 37 "strftime": "^0.10.1", 38 + "superjson": "^1.12.3", 39 "swr": "^2.1.5", 40 + "turbo": "^1.10.3" 41 }, 42 "devDependencies": { 43 + "@builder.io/partytown": "^0.8.0", 44 "@storybook/addon-controls": "^7.0.17", 45 "@storybook/addon-interactions": "^7.0.17", 46 "@storybook/nextjs": "^7.0.17", ··· 2508 "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", 2509 "dev": true 2510 }, 2511 + "node_modules/@builder.io/partytown": { 2512 + "version": "0.8.0", 2513 + "resolved": "https://registry.npmjs.org/@builder.io/partytown/-/partytown-0.8.0.tgz", 2514 + "integrity": "sha512-M6H7nSMwW2dHd1/MQ+9J1Jqdw22uhl1nKv90kIiL9G7gjFVqqouQp4qSS1oZclmtW1XjAa4Q5UnbHB4iytmxZA==", 2515 + "dev": true, 2516 + "bin": { 2517 + "partytown": "bin/partytown.cjs" 2518 + } 2519 }, 2520 "node_modules/@colors/colors": { 2521 "version": "1.5.0", ··· 3328 "version": "8.0.2", 3329 "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", 3330 "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", 3331 "dependencies": { 3332 "string-width": "^5.1.2", 3333 "string-width-cjs": "npm:string-width@^4.2.0", ··· 3344 "version": "6.0.1", 3345 "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", 3346 "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", 3347 "engines": { 3348 "node": ">=12" 3349 }, ··· 3355 "version": "6.2.1", 3356 "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", 3357 "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", 3358 "engines": { 3359 "node": ">=12" 3360 }, ··· 3366 "version": "5.1.2", 3367 "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", 3368 "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", 3369 "dependencies": { 3370 "eastasianwidth": "^0.2.0", 3371 "emoji-regex": "^9.2.2", ··· 3382 "version": "7.1.0", 3383 "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", 3384 "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", 3385 "dependencies": { 3386 "ansi-regex": "^6.0.1" 3387 }, ··· 3396 "version": "8.1.0", 3397 "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", 3398 "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", 3399 "dependencies": { 3400 "ansi-styles": "^6.1.0", 3401 "string-width": "^5.0.1", ··· 4864 "react": "^17.0.0 || ^18.0.0" 4865 } 4866 }, 4867 "node_modules/@ndelangen/get-tarball": { 4868 "version": "3.0.9", 4869 "resolved": "https://registry.npmjs.org/@ndelangen/get-tarball/-/get-tarball-3.0.9.tgz", ··· 5147 "balanced-match": "^1.0.0" 5148 } 5149 }, 5150 "node_modules/@npmcli/map-workspaces/node_modules/minimatch": { 5151 "version": "9.0.2", 5152 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.2.tgz", ··· 5162 "url": "https://github.com/sponsors/isaacs" 5163 } 5164 }, 5165 "node_modules/@npmcli/name-from-folder": { 5166 "version": "2.0.0", 5167 "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-2.0.0.tgz", ··· 5175 "version": "0.11.0", 5176 "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", 5177 "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", 5178 "optional": true, 5179 "engines": { 5180 "node": ">=14" ··· 6109 "integrity": "sha512-8egDX8dE50XyXWH6C6PRCNkTP106DuUrvdrednFouDSmCi7IOvrqr0frznfZaHifHH/3aq/7a7v9N4wdXMqhBQ==", 6110 "dev": true 6111 }, 6112 + "node_modules/@storybook/core-common/node_modules/brace-expansion": { 6113 + "version": "2.0.1", 6114 + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 6115 + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 6116 + "dev": true, 6117 + "dependencies": { 6118 + "balanced-match": "^1.0.0" 6119 + } 6120 + }, 6121 + "node_modules/@storybook/core-common/node_modules/glob": { 6122 + "version": "8.1.0", 6123 + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", 6124 + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", 6125 + "dev": true, 6126 + "dependencies": { 6127 + "fs.realpath": "^1.0.0", 6128 + "inflight": "^1.0.4", 6129 + "inherits": "2", 6130 + "minimatch": "^5.0.1", 6131 + "once": "^1.3.0" 6132 + }, 6133 + "engines": { 6134 + "node": ">=12" 6135 + }, 6136 + "funding": { 6137 + "url": "https://github.com/sponsors/isaacs" 6138 + } 6139 + }, 6140 + "node_modules/@storybook/core-common/node_modules/glob-promise": { 6141 + "version": "6.0.3", 6142 + "resolved": "https://registry.npmjs.org/glob-promise/-/glob-promise-6.0.3.tgz", 6143 + "integrity": "sha512-m+kxywR5j/2Z2V9zvHKfwwL5Gp7gIFEBX+deTB9w2lJB+wSuw9kcS43VfvTAMk8TXL5JCl/cCjsR+tgNVspGyA==", 6144 + "dev": true, 6145 + "dependencies": { 6146 + "@types/glob": "^8.0.0" 6147 + }, 6148 + "engines": { 6149 + "node": ">=16" 6150 + }, 6151 + "funding": { 6152 + "type": "individual", 6153 + "url": "https://github.com/sponsors/ahmadnassri" 6154 + }, 6155 + "peerDependencies": { 6156 + "glob": "^8.0.3" 6157 + } 6158 + }, 6159 + "node_modules/@storybook/core-common/node_modules/minimatch": { 6160 + "version": "5.1.6", 6161 + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", 6162 + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", 6163 + "dev": true, 6164 + "dependencies": { 6165 + "brace-expansion": "^2.0.1" 6166 + }, 6167 + "engines": { 6168 + "node": ">=10" 6169 + } 6170 + }, 6171 "node_modules/@storybook/core-events": { 6172 "version": "7.0.23", 6173 "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.0.23.tgz", ··· 7130 "@babel/core": "^7.0.0" 7131 } 7132 }, 7133 + "node_modules/@storybook/test-runner/node_modules/brace-expansion": { 7134 + "version": "2.0.1", 7135 + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 7136 + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 7137 + "dev": true, 7138 + "dependencies": { 7139 + "balanced-match": "^1.0.0" 7140 + } 7141 + }, 7142 "node_modules/@storybook/test-runner/node_modules/camelcase": { 7143 "version": "6.3.0", 7144 "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", ··· 7174 }, 7175 "engines": { 7176 "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" 7177 + } 7178 + }, 7179 + "node_modules/@storybook/test-runner/node_modules/glob": { 7180 + "version": "8.1.0", 7181 + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", 7182 + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", 7183 + "dev": true, 7184 + "dependencies": { 7185 + "fs.realpath": "^1.0.0", 7186 + "inflight": "^1.0.4", 7187 + "inherits": "2", 7188 + "minimatch": "^5.0.1", 7189 + "once": "^1.3.0" 7190 + }, 7191 + "engines": { 7192 + "node": ">=12" 7193 + }, 7194 + "funding": { 7195 + "url": "https://github.com/sponsors/isaacs" 7196 + } 7197 + }, 7198 + "node_modules/@storybook/test-runner/node_modules/glob/node_modules/minimatch": { 7199 + "version": "5.1.6", 7200 + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", 7201 + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", 7202 + "dev": true, 7203 + "dependencies": { 7204 + "brace-expansion": "^2.0.1" 7205 + }, 7206 + "engines": { 7207 + "node": ">=10" 7208 } 7209 }, 7210 "node_modules/@storybook/test-runner/node_modules/jest": { ··· 7883 "@testing-library/dom": ">=7.21.4" 7884 } 7885 }, 7886 "node_modules/@tootallnate/once": { 7887 "version": "2.0.0", 7888 "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", ··· 8218 "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", 8219 "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", 8220 "dev": true 8221 }, 8222 "node_modules/@types/lodash": { 8223 "version": "4.14.195", ··· 9100 "version": "5.0.1", 9101 "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 9102 "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 9103 "engines": { 9104 "node": ">=8" 9105 } 9106 }, 9107 "node_modules/ansi-styles": { 9108 "version": "4.3.0", 9109 "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 9110 "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 9111 "dependencies": { 9112 "color-convert": "^2.0.1" 9113 }, ··· 9154 "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", 9155 "dev": true 9156 }, 9157 "node_modules/archy": { 9158 "version": "1.0.0", 9159 "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", ··· 9172 "engines": { 9173 "node": ">=10" 9174 } 9175 }, 9176 "node_modules/argparse": { 9177 "version": "2.0.1", ··· 9695 "node_modules/balanced-match": { 9696 "version": "1.0.2", 9697 "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 9698 + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 9699 }, 9700 "node_modules/base64-js": { 9701 "version": "1.5.1", ··· 10527 "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", 10528 "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" 10529 }, 10530 "node_modules/cliui": { 10531 "version": "8.0.1", 10532 "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", ··· 10916 "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 10917 "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", 10918 "dev": true 10919 + }, 10920 + "node_modules/copy-anything": { 10921 + "version": "3.0.5", 10922 + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", 10923 + "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", 10924 + "dependencies": { 10925 + "is-what": "^4.1.8" 10926 + }, 10927 + "engines": { 10928 + "node": ">=12.13" 10929 + }, 10930 + "funding": { 10931 + "url": "https://github.com/sponsors/mesqueeb" 10932 + } 10933 }, 10934 "node_modules/core-js-compat": { 10935 "version": "3.31.0", ··· 10961 "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", 10962 "dev": true 10963 }, 10964 "node_modules/cosmiconfig": { 10965 "version": "7.1.0", 10966 "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", ··· 11273 "node": ">=0.8" 11274 } 11275 }, 11276 "node_modules/damerau-levenshtein": { 11277 "version": "1.0.8", 11278 "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", ··· 11308 "url": "https://opencollective.com/date-fns" 11309 } 11310 }, 11311 "node_modules/debug": { 11312 "version": "4.3.4", 11313 "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", ··· 11683 "url": "https://github.com/sponsors/sindresorhus" 11684 } 11685 }, 11686 "node_modules/delayed-stream": { 11687 "version": "1.0.0", 11688 "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", ··· 12043 "node_modules/eastasianwidth": { 12044 "version": "0.2.0", 12045 "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", 12046 + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" 12047 }, 12048 "node_modules/ee-first": { 12049 "version": "1.1.1", ··· 12071 "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.440.tgz", 12072 "integrity": "sha512-r6dCgNpRhPwiWlxbHzZQ/d9swfPaEJGi8ekqRBwQYaR3WmA5VkqQfBWSDDjuJU1ntO+W9tHx8OHV/96Q8e0dVw==", 12073 "dev": true 12074 }, 12075 "node_modules/elliptic": { 12076 "version": "6.5.4", ··· 12108 "node_modules/emoji-regex": { 12109 "version": "9.2.2", 12110 "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", 12111 + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" 12112 }, 12113 "node_modules/emojis-list": { 12114 "version": "3.0.0", ··· 13080 "version": "4.0.1", 13081 "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 13082 "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 13083 + "dev": true, 13084 "bin": { 13085 "esparse": "bin/esparse.js", 13086 "esvalidate": "bin/esvalidate.js" ··· 13198 "node": ">= 8" 13199 } 13200 }, 13201 "node_modules/estree-util-visit": { 13202 "version": "1.2.1", 13203 "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-1.2.1.tgz", ··· 13425 "version": "2.0.1", 13426 "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 13427 "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", 13428 + "dev": true, 13429 "dependencies": { 13430 "is-extendable": "^0.1.0" 13431 }, ··· 14327 "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", 14328 "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" 14329 }, 14330 "node_modules/glob": { 14331 + "version": "10.3.0", 14332 + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.0.tgz", 14333 + "integrity": "sha512-AQ1/SB9HH0yCx1jXAT4vmCbTOPe5RQ+kCurjbel5xSCGhebumUv+GJZfa1rEqor3XIViqwSEmlkZCQD43RWrBg==", 14334 "dependencies": { 14335 + "foreground-child": "^3.1.0", 14336 + "jackspeak": "^2.0.3", 14337 + "minimatch": "^9.0.1", 14338 + "minipass": "^5.0.0 || ^6.0.2", 14339 + "path-scurry": "^1.7.0" 14340 + }, 14341 + "bin": { 14342 + "glob": "dist/cjs/src/bin.js" 14343 }, 14344 "engines": { 14345 + "node": ">=16 || 14 >=14.17" 14346 }, 14347 "funding": { 14348 "url": "https://github.com/sponsors/isaacs" ··· 14360 "node": ">=10.13.0" 14361 } 14362 }, 14363 "node_modules/glob-to-regexp": { 14364 "version": "0.4.1", 14365 "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", ··· 14369 "version": "2.0.1", 14370 "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 14371 "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 14372 "dependencies": { 14373 "balanced-match": "^1.0.0" 14374 } 14375 }, 14376 + "node_modules/glob/node_modules/foreground-child": { 14377 + "version": "3.1.1", 14378 + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", 14379 + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", 14380 + "dependencies": { 14381 + "cross-spawn": "^7.0.0", 14382 + "signal-exit": "^4.0.1" 14383 + }, 14384 + "engines": { 14385 + "node": ">=14" 14386 + }, 14387 + "funding": { 14388 + "url": "https://github.com/sponsors/isaacs" 14389 + } 14390 + }, 14391 "node_modules/glob/node_modules/minimatch": { 14392 + "version": "9.0.2", 14393 + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.2.tgz", 14394 + "integrity": "sha512-PZOT9g5v2ojiTL7r1xF6plNHLtOeTpSlDI007As2NlA2aYBMfVom17yqa6QzhmDP8QOhn7LjHTg7DFCVSSa6yg==", 14395 "dependencies": { 14396 "brace-expansion": "^2.0.1" 14397 }, 14398 "engines": { 14399 + "node": ">=16 || 14 >=14.17" 14400 + }, 14401 + "funding": { 14402 + "url": "https://github.com/sponsors/isaacs" 14403 + } 14404 + }, 14405 + "node_modules/glob/node_modules/signal-exit": { 14406 + "version": "4.0.2", 14407 + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", 14408 + "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", 14409 + "engines": { 14410 + "node": ">=14" 14411 + }, 14412 + "funding": { 14413 + "url": "https://github.com/sponsors/isaacs" 14414 } 14415 }, 14416 "node_modules/global-modules": { ··· 14534 "version": "4.0.3", 14535 "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", 14536 "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", 14537 + "dev": true, 14538 "dependencies": { 14539 "js-yaml": "^3.13.1", 14540 "kind-of": "^6.0.2", ··· 14549 "version": "1.0.10", 14550 "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 14551 "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 14552 + "dev": true, 14553 "dependencies": { 14554 "sprintf-js": "~1.0.2" 14555 } ··· 14558 "version": "3.14.1", 14559 "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", 14560 "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", 14561 + "dev": true, 14562 "dependencies": { 14563 "argparse": "^1.0.7", 14564 "esprima": "^4.0.0" ··· 14738 "node": ">=4" 14739 } 14740 }, 14741 "node_modules/hash.js": { 14742 "version": "1.1.7", 14743 "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", ··· 14773 "node": ">=8" 14774 } 14775 }, 14776 "node_modules/hast-util-to-estree": { 14777 "version": "2.3.3", 14778 "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-2.3.3.tgz", ··· 14804 "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", 14805 "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" 14806 }, 14807 "node_modules/hast-util-whitespace": { 14808 "version": "2.0.1", 14809 "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", ··· 14813 "url": "https://opencollective.com/unified" 14814 } 14815 }, 14816 "node_modules/he": { 14817 "version": "1.2.0", 14818 "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", ··· 14821 "bin": { 14822 "he": "bin/he" 14823 } 14824 }, 14825 "node_modules/highlight.js": { 14826 "version": "11.8.0", ··· 15309 "node": ">= 0.4" 15310 } 15311 }, 15312 "node_modules/interpret": { 15313 "version": "1.4.0", 15314 "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", ··· 15543 "version": "0.1.1", 15544 "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", 15545 "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", 15546 + "dev": true, 15547 "engines": { 15548 "node": ">=0.10.0" 15549 } ··· 15560 "version": "3.0.0", 15561 "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 15562 "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 15563 "engines": { 15564 "node": ">=8" 15565 } ··· 15720 "url": "https://github.com/sponsors/ljharb" 15721 } 15722 }, 15723 "node_modules/is-path-cwd": { 15724 "version": "2.2.0", 15725 "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", ··· 15736 "dev": true, 15737 "engines": { 15738 "node": ">=8" 15739 } 15740 }, 15741 "node_modules/is-plain-object": { ··· 15910 "url": "https://github.com/sponsors/ljharb" 15911 } 15912 }, 15913 + "node_modules/is-what": { 15914 + "version": "4.1.15", 15915 + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.15.tgz", 15916 + "integrity": "sha512-uKua1wfy3Yt+YqsD6mTUEa2zSi3G1oPlqTflgaPJ7z63vUGN5pxFpnQfeSLMFnJDEsdvOtkp1rUWkYjB4YfhgA==", 15917 + "engines": { 15918 + "node": ">=12.13" 15919 + }, 15920 + "funding": { 15921 + "url": "https://github.com/sponsors/mesqueeb" 15922 + } 15923 + }, 15924 "node_modules/is-windows": { 15925 "version": "1.0.2", 15926 "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", ··· 16120 "version": "2.2.1", 16121 "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", 16122 "integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==", 16123 "dependencies": { 16124 "@isaacs/cliui": "^8.0.2" 16125 }, ··· 19057 "node": ">=6" 19058 } 19059 }, 19060 "node_modules/jsonfile": { 19061 "version": "6.1.0", 19062 "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", ··· 19082 "node": ">=4.0" 19083 } 19084 }, 19085 "node_modules/kind-of": { 19086 "version": "6.0.3", 19087 "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", 19088 "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", 19089 + "dev": true, 19090 "engines": { 19091 "node": ">=0.10.0" 19092 } ··· 19129 "dependencies": { 19130 "language-subtag-registry": "~0.3.2" 19131 } 19132 }, 19133 "node_modules/lazy-universal-dotenv": { 19134 "version": "4.0.0", ··· 19221 "node_modules/lodash": { 19222 "version": "4.17.21", 19223 "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 19224 + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 19225 + "dev": true 19226 }, 19227 "node_modules/lodash.debounce": { 19228 "version": "4.0.8", ··· 19236 "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", 19237 "dev": true 19238 }, 19239 "node_modules/lodash.merge": { 19240 "version": "4.6.2", 19241 "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", ··· 19748 "dev": true, 19749 "dependencies": { 19750 "@types/mdast": "^3.0.0" 19751 }, 19752 "funding": { 19753 "type": "opencollective", ··· 20439 "node": ">= 8" 20440 } 20441 }, 20442 "node_modules/methods": { 20443 "version": "1.1.2", 20444 "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", ··· 20614 "type": "opencollective", 20615 "url": "https://opencollective.com/unified" 20616 } 20617 }, 20618 "node_modules/micromark-extension-mdx-expression": { 20619 "version": "1.0.8", ··· 21303 "version": "5.0.0", 21304 "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", 21305 "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", 21306 "engines": { 21307 "node": ">=8" 21308 } ··· 21513 "next": "*" 21514 } 21515 }, 21516 + "node_modules/next-superjson-plugin": { 21517 + "version": "0.5.8", 21518 + "resolved": "https://registry.npmjs.org/next-superjson-plugin/-/next-superjson-plugin-0.5.8.tgz", 21519 + "integrity": "sha512-a6znMUzHWRAaxmQNHkgANJORdI0gjSC0JvsxRRKba6vb4BJRs/i2KpwEg/s91JYDhHsnZS+tkeb3MDCJWXJY4w==", 21520 + "dependencies": { 21521 + "hoist-non-react-statics": "^3.3.2" 21522 + }, 21523 + "peerDependencies": { 21524 + "next": "^13", 21525 + "superjson": "^1" 21526 + } 21527 + }, 21528 "node_modules/next-themes": { 21529 "version": "0.2.1", 21530 "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.2.1.tgz", ··· 21556 }, 21557 "engines": { 21558 "node": "^10 || ^12 || >=14" 21559 } 21560 }, 21561 "node_modules/no-case": { ··· 21727 "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", 21728 "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==", 21729 "dev": true 21730 }, 21731 "node_modules/nopt": { 21732 "version": "7.2.0", ··· 22314 "node": ">=0.10.0" 22315 } 22316 }, 22317 "node_modules/p-limit": { 22318 "version": "3.1.0", 22319 "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 22320 "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 22321 + "dev": true, 22322 "dependencies": { 22323 "yocto-queue": "^0.1.0" 22324 }, ··· 22468 "url": "https://github.com/sponsors/sindresorhus" 22469 } 22470 }, 22471 "node_modules/parse-passwd": { 22472 "version": "1.0.0", 22473 "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", ··· 22559 "version": "1.9.2", 22560 "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.9.2.tgz", 22561 "integrity": "sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==", 22562 "dependencies": { 22563 "lru-cache": "^9.1.1", 22564 "minipass": "^5.0.0 || ^6.0.2" ··· 22574 "version": "9.1.2", 22575 "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.2.tgz", 22576 "integrity": "sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==", 22577 "engines": { 22578 "node": "14 || >=16.14" 22579 } ··· 23209 "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", 23210 "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", 23211 "dev": true 23212 }, 23213 "node_modules/psl": { 23214 "version": "1.9.0", ··· 23840 "node": ">=8.10.0" 23841 } 23842 }, 23843 "node_modules/recast": { 23844 "version": "0.23.2", 23845 "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.2.tgz", ··· 23995 "jsesc": "bin/jsesc" 23996 } 23997 }, 23998 "node_modules/relateurl": { 23999 "version": "0.2.7", 24000 "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", ··· 24843 "unist-util-generated": "^2.0.0", 24844 "unist-util-position": "^4.0.0", 24845 "unist-util-visit": "^4.0.0" 24846 }, 24847 "funding": { 24848 "type": "opencollective", ··· 25061 "prettier": ">=1.0.0" 25062 } 25063 }, 25064 "node_modules/remark-rehype": { 25065 "version": "10.1.0", 25066 "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-10.1.0.tgz", ··· 25449 "inherits": "^2.0.1" 25450 } 25451 }, 25452 "node_modules/rrweb-cssom": { 25453 "version": "0.6.0", 25454 "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", ··· 25492 "queue-microtask": "^1.2.2" 25493 } 25494 }, 25495 "node_modules/rxjs": { 25496 "version": "7.8.1", 25497 "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", ··· 25651 "version": "1.0.0", 25652 "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", 25653 "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", 25654 + "dev": true, 25655 "dependencies": { 25656 "extend-shallow": "^2.0.1", 25657 "kind-of": "^6.0.0" ··· 25917 "url": "https://github.com/sponsors/isaacs" 25918 } 25919 }, 25920 "node_modules/side-channel": { 25921 "version": "1.0.4", 25922 "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", ··· 25934 "node_modules/signal-exit": { 25935 "version": "3.0.7", 25936 "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", 25937 + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", 25938 + "dev": true 25939 }, 25940 "node_modules/simple-concat": { 25941 "version": "1.0.1", ··· 26024 "version": "3.0.0", 26025 "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", 26026 "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", 26027 + "dev": true, 26028 "engines": { 26029 "node": ">=8" 26030 } ··· 26052 "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA==", 26053 "dev": true 26054 }, 26055 "node_modules/source-map": { 26056 "version": "0.5.7", 26057 "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", ··· 26166 "node_modules/sprintf-js": { 26167 "version": "1.0.3", 26168 "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 26169 + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", 26170 + "dev": true 26171 }, 26172 "node_modules/stack-utils": { 26173 "version": "2.0.6", ··· 26309 "version": "4.2.3", 26310 "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 26311 "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 26312 "dependencies": { 26313 "emoji-regex": "^8.0.0", 26314 "is-fullwidth-code-point": "^3.0.0", ··· 26323 "version": "4.2.3", 26324 "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 26325 "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 26326 "dependencies": { 26327 "emoji-regex": "^8.0.0", 26328 "is-fullwidth-code-point": "^3.0.0", ··· 26335 "node_modules/string-width-cjs/node_modules/emoji-regex": { 26336 "version": "8.0.0", 26337 "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 26338 + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 26339 }, 26340 "node_modules/string-width/node_modules/emoji-regex": { 26341 "version": "8.0.0", 26342 "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 26343 + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 26344 }, 26345 "node_modules/string.prototype.matchall": { 26346 "version": "4.0.8", ··· 26432 "version": "6.0.1", 26433 "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 26434 "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 26435 "dependencies": { 26436 "ansi-regex": "^5.0.1" 26437 }, ··· 26444 "version": "6.0.1", 26445 "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 26446 "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 26447 "dependencies": { 26448 "ansi-regex": "^5.0.1" 26449 }, ··· 26464 "version": "1.0.0", 26465 "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", 26466 "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", 26467 + "dev": true, 26468 "engines": { 26469 "node": ">=0.10.0" 26470 } ··· 26747 "version": "4.2.0", 26748 "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", 26749 "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" 26750 + }, 26751 + "node_modules/superjson": { 26752 + "version": "1.12.4", 26753 + "resolved": "https://registry.npmjs.org/superjson/-/superjson-1.12.4.tgz", 26754 + "integrity": "sha512-vkpPQAxdCg9SLfPv5GPC5fnGrui/WryktoN9O5+Zif/14QIMjw+RITf/5LbBh+9QpBFb3KNvJth+puz2H8o6GQ==", 26755 + "dependencies": { 26756 + "copy-anything": "^3.0.2" 26757 + }, 26758 + "engines": { 26759 + "node": ">=10" 26760 + } 26761 }, 26762 "node_modules/supports-color": { 26763 "version": "7.2.0", ··· 27278 "node": ">=0.6.0" 27279 } 27280 }, 27281 "node_modules/tmpl": { 27282 "version": "1.0.5", 27283 "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", ··· 27399 "version": "2.2.0", 27400 "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", 27401 "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", 27402 + "dev": true, 27403 "engines": { 27404 "node": ">=6.10" 27405 } ··· 27842 "url": "https://opencollective.com/unified" 27843 } 27844 }, 27845 + "node_modules/unified-engine/node_modules/brace-expansion": { 27846 + "version": "2.0.1", 27847 + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 27848 + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 27849 + "dev": true, 27850 + "dependencies": { 27851 + "balanced-match": "^1.0.0" 27852 + } 27853 + }, 27854 "node_modules/unified-engine/node_modules/concat-stream": { 27855 "version": "2.0.0", 27856 "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", ··· 27866 "typedarray": "^0.0.6" 27867 } 27868 }, 27869 + "node_modules/unified-engine/node_modules/glob": { 27870 + "version": "8.1.0", 27871 + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", 27872 + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", 27873 + "dev": true, 27874 + "dependencies": { 27875 + "fs.realpath": "^1.0.0", 27876 + "inflight": "^1.0.4", 27877 + "inherits": "2", 27878 + "minimatch": "^5.0.1", 27879 + "once": "^1.3.0" 27880 + }, 27881 + "engines": { 27882 + "node": ">=12" 27883 + }, 27884 + "funding": { 27885 + "url": "https://github.com/sponsors/isaacs" 27886 + } 27887 + }, 27888 "node_modules/unified-engine/node_modules/is-plain-obj": { 27889 "version": "4.1.0", 27890 "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", ··· 27906 "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 27907 } 27908 }, 27909 + "node_modules/unified-engine/node_modules/minimatch": { 27910 + "version": "5.1.6", 27911 + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", 27912 + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", 27913 + "dev": true, 27914 + "dependencies": { 27915 + "brace-expansion": "^2.0.1" 27916 + }, 27917 + "engines": { 27918 + "node": ">=10" 27919 + } 27920 + }, 27921 "node_modules/unified-engine/node_modules/parse-json": { 27922 "version": "6.0.2", 27923 "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-6.0.2.tgz", ··· 28031 "node": ">=8" 28032 } 28033 }, 28034 "node_modules/unist-util-generated": { 28035 "version": "2.0.1", 28036 "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.1.tgz", ··· 28089 "url": "https://opencollective.com/unified" 28090 } 28091 }, 28092 "node_modules/unist-util-remove-position": { 28093 "version": "4.0.2", 28094 "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-4.0.2.tgz", ··· 28297 "version": "9.0.0", 28298 "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", 28299 "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", 28300 + "dev": true, 28301 "bin": { 28302 "uuid": "dist/bin/uuid" 28303 } ··· 28379 "version": "4.1.0", 28380 "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.1.0.tgz", 28381 "integrity": "sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==", 28382 + "dev": true, 28383 "dependencies": { 28384 "@types/unist": "^2.0.0", 28385 "vfile": "^5.0.0" ··· 28563 "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", 28564 "dev": true 28565 }, 28566 "node_modules/w3c-xmlserializer": { 28567 "version": "4.0.0", 28568 "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", ··· 28723 "defaults": "^1.0.3" 28724 } 28725 }, 28726 "node_modules/webidl-conversions": { 28727 "version": "7.0.0", 28728 "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", ··· 29066 "version": "7.0.0", 29067 "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 29068 "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 29069 "dependencies": { 29070 "ansi-styles": "^4.0.0", 29071 "string-width": "^4.1.0", ··· 29245 "version": "0.1.0", 29246 "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 29247 "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 29248 + "dev": true, 29249 "engines": { 29250 "node": ">=10" 29251 },
+8 -4
package.json
··· 45 "classnames": "^2.3.2", 46 "cross-env": "^7.0.3", 47 "framer-motion": "^10.12.16", 48 "highlight.js": "^11.8.0", 49 "isomorphic-dompurify": "^1.5.0", 50 "next": "^13.4.3", 51 "next-themes": "^0.2.1", 52 - "nextra": "^2.6.1", 53 "prismjs": "^1.29.0", 54 "react": "^18.2.0", 55 "react-dom": "^18.2.0", ··· 60 "semver": "^7.5.1", 61 "sharp": "^0.32.1", 62 "strftime": "^0.10.1", 63 "swr": "^2.1.5", 64 - "turbo": "^1.9.9" 65 }, 66 "devDependencies": { 67 "@storybook/addon-controls": "^7.0.17", 68 "@storybook/addon-interactions": "^7.0.17", 69 "@storybook/nextjs": "^7.0.17", ··· 92 "feed": "^4.2.2", 93 "gray-matter": "^4.0.3", 94 "handlebars": "^4.7.7", 95 "jest": "^29.5.0", 96 "jest-environment-jsdom": "^29.5.0", 97 "next-sitemap": "^4.1.3", ··· 106 "stylelint-selector-bem-pattern": "^2.1.1", 107 "typescript": "^5.0.4", 108 "user-agent-data-types": "^0.3.1", 109 - "wait-on": "^7.0.1", 110 - "husky": "^8.0.0" 111 } 112 }
··· 45 "classnames": "^2.3.2", 46 "cross-env": "^7.0.3", 47 "framer-motion": "^10.12.16", 48 + "glob": "^10.2.7", 49 "highlight.js": "^11.8.0", 50 "isomorphic-dompurify": "^1.5.0", 51 "next": "^13.4.3", 52 + "next-mdx-remote": "^4.4.1", 53 + "next-superjson-plugin": "^0.5.8", 54 "next-themes": "^0.2.1", 55 "prismjs": "^1.29.0", 56 "react": "^18.2.0", 57 "react-dom": "^18.2.0", ··· 62 "semver": "^7.5.1", 63 "sharp": "^0.32.1", 64 "strftime": "^0.10.1", 65 + "superjson": "^1.12.3", 66 "swr": "^2.1.5", 67 + "turbo": "^1.10.3" 68 }, 69 "devDependencies": { 70 + "@builder.io/partytown": "^0.8.0", 71 "@storybook/addon-controls": "^7.0.17", 72 "@storybook/addon-interactions": "^7.0.17", 73 "@storybook/nextjs": "^7.0.17", ··· 96 "feed": "^4.2.2", 97 "gray-matter": "^4.0.3", 98 "handlebars": "^4.7.7", 99 + "husky": "^8.0.0", 100 "jest": "^29.5.0", 101 "jest-environment-jsdom": "^29.5.0", 102 "next-sitemap": "^4.1.3", ··· 111 "stylelint-selector-bem-pattern": "^2.1.1", 112 "typescript": "^5.0.4", 113 "user-agent-data-types": "^0.3.1", 114 + "wait-on": "^7.0.1" 115 } 116 }
-14
pages/404.mdx
··· 1 - import { FormattedMessage } from 'react-intl'; 2 - 3 - export default function NotFound() { 4 - return ( 5 - <> 6 - <h2> 7 - <FormattedMessage id="pages.404.title" /> 8 - </h2> 9 - <h3> 10 - <FormattedMessage id="pages.404.description" /> 11 - </h3> 12 - </> 13 - ); 14 - }
···
+15
pages/404.tsx
···
··· 1 + import { FormattedMessage } from 'react-intl'; 2 + import Theme from '../theme'; 3 + 4 + const NotFound = () => ( 5 + <Theme> 6 + <h2> 7 + <FormattedMessage id="pages.404.title" /> 8 + </h2> 9 + <h3> 10 + <FormattedMessage id="pages.404.description" /> 11 + </h3> 12 + </Theme> 13 + ); 14 + 15 + export default NotFound;
+89
pages/[...path].tsx
···
··· 1 + import Theme from '../theme'; 2 + import * as nextDynamic from '../next.dynamic.mjs'; 3 + import * as nextConstants from '../next.constants.mjs'; 4 + import type { GetStaticPaths, GetStaticProps } from 'next'; 5 + import type { MDXRemoteSerializeResult } from 'next-mdx-remote'; 6 + 7 + type StaticParams = { path: string[] }; 8 + type StaticProps = { content: MDXRemoteSerializeResult }; 9 + 10 + // This is a small utility that allows us to quickly separate locale from the remaning pathname 11 + const getLocaleAndPathname = ([locale, ...path]: string[] = []) => [ 12 + locale, 13 + path.join('/'), 14 + ]; 15 + 16 + // This tests if the current pathname matches any expression that belongs 17 + // to the list of ignored routes and if it does we return `true` to indicate that 18 + const shouldIgnoreRoute = (pathname: string) => 19 + (pathname.length && 20 + nextConstants.DYNAMIC_ROUTES_IGNORES.some(e => e.test(pathname))) || 21 + false; 22 + 23 + // This tests if the current pathname matches any sort of rewrite rule 24 + // and if it does we return a the replacement expression for the pathname 25 + const getRouteWrite = (pathname: string) => 26 + (pathname.length && 27 + nextConstants.DYNAMIC_ROUTES_REWRITES.find(([e]) => e.test(pathname))) || 28 + []; 29 + 30 + // This maps a pathname into an actual route object that can be used 31 + const mapPathnameToRoute = (pathname: string) => ({ 32 + params: { path: pathname.split('/') }, 33 + }); 34 + 35 + // This method receives the props from `getStaticProps` and renders/builds the Markdown 36 + // content on demand by loading the file on the server-side and serializing the Markdown/MDX content 37 + export const getStaticProps: GetStaticProps< 38 + StaticProps, 39 + StaticParams 40 + > = async ({ params = { path: [] } }) => { 41 + const [locale, pathname] = getLocaleAndPathname(params.path); 42 + 43 + // Retrieves and rewriting rule if the pathname matches any rule 44 + const [, rewriteRule] = getRouteWrite(pathname); 45 + 46 + // We retrieve the source of the Markdown file by doing an educated guess 47 + // of what possible files could be the source of the page, since the extension 48 + // context is lost from `getStaticProps` as a limitation of Next.js itself 49 + const { source, filename } = nextDynamic.getMarkdownFile( 50 + locale, 51 + rewriteRule ? rewriteRule(pathname) : pathname 52 + ); 53 + 54 + // This parses the actual Markdown content and returns a full set of props 55 + // to be passed to the base page (`DynamicPage`) which will render the Markdown 56 + const staticProps = await nextDynamic.getStaticProps(source, filename); 57 + 58 + // This checks if either we already determined the route does not exist or if we should ignore 59 + // this route because it's on our ignored list 60 + staticProps.notFound = staticProps.notFound || shouldIgnoreRoute(pathname); 61 + 62 + // We add the extra `params` to the props as they're used within the `DynamicPage` 63 + return staticProps; 64 + }; 65 + 66 + // This method is used to retrieve all native statically supported pages (SCR) that 67 + // we want to provide during build-time + allow fallback for dynamic pages during (ISR) 68 + export const getStaticPaths: GetStaticPaths<StaticParams> = async () => { 69 + const paths = []; 70 + 71 + // Retrieves all the dynamic generated paths 72 + const dynamicRoutes = nextConstants.DYNAMIC_GENERATED_ROUTES(); 73 + 74 + // Retrieves all the static paths (from next.dynamic.mjs) 75 + const staticPaths = [...nextDynamic.allPaths.values()] 76 + .flat() 77 + .filter(route => nextConstants.STATIC_ROUTES_IGNORES.every(e => !e(route))) 78 + .map(route => route.routeWithLocale); 79 + 80 + if (nextConstants.ENABLE_STATIC_EXPORT) { 81 + paths.push(...staticPaths); 82 + 83 + paths.push(...dynamicRoutes); 84 + } 85 + 86 + return { paths: paths.sort().map(mapPathnameToRoute), fallback: 'blocking' }; 87 + }; 88 + 89 + export default Theme;
-21
pages/_app.mdx
··· 1 - import { Analytics } from '@vercel/analytics/react'; 2 - import { NodeReleasesProvider } from '../providers/nodeReleasesProvider'; 3 - import { LocaleProvider } from '../providers/localeProvider'; 4 - import { sourceSans } from '../util/nextFonts'; 5 - import BaseApp, { setAppFont } from '../next.app'; 6 - 7 - import '../styles/old/index.scss'; 8 - 9 - export default function App({ Component, pageProps }) { 10 - setAppFont(sourceSans.style.fontFamily); 11 - return ( 12 - <BaseApp> 13 - <LocaleProvider> 14 - <NodeReleasesProvider> 15 - <Component {...pageProps} /> 16 - <Analytics /> 17 - </NodeReleasesProvider> 18 - </LocaleProvider> 19 - </BaseApp> 20 - ); 21 - }
···
+17
pages/_app.tsx
···
··· 1 + import { Analytics } from '@vercel/analytics/react'; 2 + import { sourceSans } from '../util/nextFonts'; 3 + import BaseApp, { setAppFonts } from '../next.app'; 4 + import type { AppProps } from 'next/app'; 5 + 6 + import '../styles/old/index.scss'; 7 + 8 + setAppFonts([sourceSans.style.fontFamily]); 9 + 10 + const App = ({ Component, pageProps }: AppProps) => ( 11 + <BaseApp> 12 + <Component {...pageProps} /> 13 + <Analytics /> 14 + </BaseApp> 15 + ); 16 + 17 + export default App;
+5 -6
pages/_document.tsx
··· 1 import Script from 'next/script'; 2 import { Html, Head, Main, NextScript } from 'next/document'; 3 - 4 - // current application base path (temporary workaround) 5 - const basePath = process.env.NEXT_BASE_PATH || ''; 6 7 - // @TODO: The custom scripts should be removed in the future when switching over `nodejs/nodejs.dev` codebase 8 - // Note.: Some of these scripts will also be completely removed from the codebase such as jQuery 9 const Document = () => ( 10 <Html> 11 <Head /> 12 <body> 13 <Main /> 14 <NextScript /> 15 <Script 16 strategy="beforeInteractive" 17 - src={`${basePath}/static/js/legacyMain.js`} 18 /> 19 <a rel="me" href="https://social.lfx.dev/@nodejs" /> 20 </body> 21 </Html>
··· 1 import Script from 'next/script'; 2 import { Html, Head, Main, NextScript } from 'next/document'; 3 + import * as nextConstants from '../next.constants.mjs'; 4 5 const Document = () => ( 6 <Html> 7 <Head /> 8 <body> 9 <Main /> 10 + 11 <NextScript /> 12 + 13 <Script 14 strategy="beforeInteractive" 15 + src={nextConstants.LEGACY_JAVASCRIPT_FILE} 16 /> 17 + 18 <a rel="me" href="https://social.lfx.dev/@nodejs" /> 19 </body> 20 </Html>
+5
pages/en/blog/pagination.md
···
··· 1 + --- 2 + layout: blog-index.hbs 3 + title: News from 4 + paginate: blog 5 + ---
+16
providers/blogDataProvider.tsx
···
··· 1 + import { createContext, useMemo } from 'react'; 2 + import blogData from '../public/blog-posts-data.json'; 3 + import type { FC, PropsWithChildren } from 'react'; 4 + import type { BlogData } from '../types'; 5 + 6 + export const BlogDataContext = createContext<BlogData>({ 7 + posts: [], 8 + pagination: [], 9 + categories: [], 10 + }); 11 + 12 + export const BlogDataProvider: FC<PropsWithChildren> = ({ children }) => ( 13 + <BlogDataContext.Provider value={blogData}> 14 + {children} 15 + </BlogDataContext.Provider> 16 + );
+19 -21
providers/layoutProvider.tsx
··· 1 - import { createContext } from 'react'; 2 import AboutLayout from '../layouts/AboutLayout'; 3 import BlogIndexLayout from '../layouts/BlogIndexLayout'; 4 import BlogPostLayout from '../layouts/BlogPostLayout'; ··· 10 import DownloadCurrentLayout from '../layouts/DownloadCurrentLayout'; 11 import DownloadReleasesLayout from '../layouts/DownloadReleasesLayout'; 12 import IndexLayout from '../layouts/IndexLayout'; 13 - import type { PageOpts } from 'nextra'; 14 - import type { PropsWithChildren } from 'react'; 15 - 16 - import type { LegacyLayouts, NextraAppProps } from '../types'; 17 18 - type LayoutProviderProps = PropsWithChildren<{ 19 - pageOpts: PageOpts; 20 - pageProps: NextraAppProps['pageProps']; 21 - }>; 22 23 - export const LayoutContext = createContext<{ 24 - layout: LegacyLayouts; 25 - pageOpts: PageOpts; 26 - pageProps: NextraAppProps['pageProps']; 27 - // @TODO: Initialize the Layout Provider with a default value 28 - }>(undefined as any); 29 30 const getLegacyLayout = (layout: LegacyLayouts) => { 31 switch (layout) { ··· 54 } 55 }; 56 57 - // In this case we want to separate the children prop from the remaining ones 58 - 59 - export const LayoutProvider = ({ children, ...props }: LayoutProviderProps) => { 60 - const layout = props.pageOpts.frontMatter.layout; 61 62 - const LayoutComponent = getLegacyLayout(layout); 63 64 return ( 65 - <LayoutContext.Provider value={{ layout, ...props }}> 66 <LayoutComponent>{children}</LayoutComponent> 67 </LayoutContext.Provider> 68 );
··· 1 + import { createContext, useMemo } from 'react'; 2 import AboutLayout from '../layouts/AboutLayout'; 3 import BlogIndexLayout from '../layouts/BlogIndexLayout'; 4 import BlogPostLayout from '../layouts/BlogPostLayout'; ··· 10 import DownloadCurrentLayout from '../layouts/DownloadCurrentLayout'; 11 import DownloadReleasesLayout from '../layouts/DownloadReleasesLayout'; 12 import IndexLayout from '../layouts/IndexLayout'; 13 + import type { FC, PropsWithChildren } from 'react'; 14 + import type { LegacyFrontMatter, LegacyLayouts } from '../types'; 15 16 + type LayoutContextProps = { 17 + frontMatter: LegacyFrontMatter; 18 + }; 19 20 + export const LayoutContext = createContext<LayoutContextProps>({ 21 + frontMatter: {}, 22 + }); 23 24 const getLegacyLayout = (layout: LegacyLayouts) => { 25 switch (layout) { ··· 48 } 49 }; 50 51 + type LayoutProviderProps = PropsWithChildren<LayoutContextProps>; 52 53 + export const LayoutProvider: FC<LayoutProviderProps> = ({ 54 + children, 55 + frontMatter, 56 + }) => { 57 + const LayoutComponent = useMemo( 58 + () => getLegacyLayout(frontMatter.layout || 'page.hbs'), 59 + [frontMatter.layout] 60 + ); 61 62 return ( 63 + <LayoutContext.Provider value={{ frontMatter }}> 64 <LayoutComponent>{children}</LayoutComponent> 65 </LayoutContext.Provider> 66 );
+34
providers/mdxProvider.tsx
···
··· 1 + import { useEffect } from 'react'; 2 + import { MDXProvider as BaseMDXProvider } from '@mdx-js/react'; 3 + import highlightJs from 'highlight.js/lib/common'; 4 + import AnchoredHeading from '../components/AnchoredHeading'; 5 + import NodeApiVersionLinks from '../components/Docs/NodeApiVersionLinks'; 6 + import { useRouter } from '../hooks/useRouter'; 7 + import type { FC, PropsWithChildren } from 'react'; 8 + import type { MDXComponents } from 'mdx/types'; 9 + 10 + const mdxComponents: MDXComponents = { 11 + NodeApiVersionLinks: NodeApiVersionLinks, 12 + h1: props => <AnchoredHeading level={1} {...props} />, 13 + h2: props => <AnchoredHeading level={2} {...props} />, 14 + h3: props => <AnchoredHeading level={3} {...props} />, 15 + h4: props => <AnchoredHeading level={4} {...props} />, 16 + h5: props => <AnchoredHeading level={5} {...props} />, 17 + h6: props => <AnchoredHeading level={6} {...props} />, 18 + blockquote: ({ children }) => <div className="highlight-box">{children}</div>, 19 + }; 20 + 21 + export const MDXProvider: FC<PropsWithChildren> = ({ children }) => { 22 + const { asPath } = useRouter(); 23 + 24 + // Re-highlights the pages on route change 25 + useEffect(() => highlightJs.highlightAll(), [asPath]); 26 + 27 + useEffect(() => window.startLegacyApp(), []); 28 + 29 + return ( 30 + <BaseMDXProvider components={mdxComponents} disableParentContext> 31 + {children} 32 + </BaseMDXProvider> 33 + ); 34 + };
+5 -3
providers/siteProvider.tsx
··· 1 import { createContext } from 'react'; 2 - import siteConfig from '../site.json'; 3 import type { FC, PropsWithChildren } from 'react'; 4 import type { SiteConfig } from '../types'; 5 6 - export const SiteContext = createContext<SiteConfig>(siteConfig); 7 8 export const SiteProvider: FC<PropsWithChildren> = ({ children }) => ( 9 - <SiteContext.Provider value={siteConfig}>{children}</SiteContext.Provider> 10 );
··· 1 import { createContext } from 'react'; 2 + import * as nextJson from '../next.json.mjs'; 3 import type { FC, PropsWithChildren } from 'react'; 4 import type { SiteConfig } from '../types'; 5 6 + export const SiteContext = createContext<SiteConfig>(nextJson.siteConfig); 7 8 export const SiteProvider: FC<PropsWithChildren> = ({ children }) => ( 9 + <SiteContext.Provider value={nextJson.siteConfig}> 10 + {children} 11 + </SiteContext.Provider> 12 );
+1
public/blog-posts-data.json
···
··· 1 + {"pagination": [],"categories": [],"posts": []}
-1
public/en/feed/.gitkeep
··· 1 - !.gitignore
···
-16
scripts/next-data/_helpers.mjs
··· 1 - 'use strict'; 2 - 3 - import { readdir } from 'node:fs/promises'; 4 - import { fileURLToPath } from 'url'; 5 - 6 - export const getMatchingRoutes = (route = '', matches = []) => 7 - matches.some(match => route === match); 8 - 9 - // reads all immediate subdirectories of a directory 10 - export const getDirectories = source => { 11 - return readdir(source, { withFileTypes: true }).then(d => 12 - d.filter(e => e.isDirectory()).map(e => e.name) 13 - ); 14 - }; 15 - 16 - export const getRelativePath = path => fileURLToPath(new URL('.', path));
···
+6 -6
scripts/next-data/generateNodeReleasesJson.mjs next-data/generateNodeReleasesJson.mjs
··· 2 import { join } from 'node:path'; 3 import nodevu from '@nodevu/core'; 4 5 - import { getRelativePath } from './_helpers.mjs'; 6 - 7 - const __dirname = getRelativePath(import.meta.url); 8 - const jsonFilePath = join(__dirname, '../../public/node-releases-data.json'); 9 10 - export const generateNodeReleasesJson = async () => { 11 - const nodevuOutput = await nodevu(); 12 13 // Filter out those without documented support 14 // Basically those not in schedule.json ··· 49 ) 50 ); 51 };
··· 2 import { join } from 'node:path'; 3 import nodevu from '@nodevu/core'; 4 5 + // this is the destination path for where the JSON file will be written 6 + const jsonFilePath = join(process.cwd(), 'public/node-releases-data.json'); 7 8 + const generateNodeReleasesJson = async () => { 9 + const nodevuOutput = await nodevu({ fetch: fetch }); 10 11 // Filter out those without documented support 12 // Basically those not in schedule.json ··· 47 ) 48 ); 49 }; 50 + 51 + export default generateNodeReleasesJson;
-60
scripts/next-data/generatePreBuildFiles.mjs
··· 1 - 'use strict'; 2 - 3 - // @TODO: This is a temporary hack until we migrate to the `nodejs/nodejs.dev` codebase 4 - import { writeFile } from 'node:fs/promises'; 5 - import { join } from 'node:path'; 6 - import { Feed } from 'feed'; 7 - 8 - import { getRelativePath } from './_helpers.mjs'; 9 - 10 - // imports the global site config 11 - import siteConfig from '../../site.json' assert { type: 'json' }; 12 - 13 - // this allows us to get the current module working directory 14 - const __dirname = getRelativePath(import.meta.url); 15 - 16 - // gets the current blog path based on local module path 17 - const blogPath = join(__dirname, '../../pages/en/blog'); 18 - 19 - const publicFeedPath = join(__dirname, '../../public/en/feed'); 20 - 21 - // creates a markdown file for the blog year 22 - const createBlogYearFile = year => 23 - writeFile( 24 - join(blogPath, `year-${year}.md`), 25 - `---\nlayout: blog-index.hbs\ntitle: News from ${year}\npaginate: blog\n---\n` 26 - ); 27 - 28 - export const generateBlogYearPages = cachedBlogData => 29 - cachedBlogData('', true) 30 - .then(({ blogData }) => blogData.posts.map(p => p.date.getFullYear())) 31 - .then(data => [...new Set(data)]) 32 - .then(data => data.forEach(createBlogYearFile)); 33 - 34 - export const generateWebsiteFeeds = cachedBlogData => 35 - siteConfig.rssFeeds.forEach(metadata => { 36 - const feed = new Feed({ 37 - title: metadata.title, 38 - description: metadata.description || siteConfig.description, 39 - id: metadata.link, 40 - link: metadata.link, 41 - language: 'en', 42 - }); 43 - 44 - const blogCategoryOrAll = metadata.blogCategory 45 - ? `/en/blog/${metadata.blogCategory}` 46 - : '/en/blog'; 47 - 48 - const mapBlogPostToFeed = post => 49 - feed.addItem({ 50 - title: post.title, 51 - id: `https://nodejs.org/en${post.slug}`, 52 - link: `https://nodejs.org/en${post.slug}`, 53 - author: post.author, 54 - date: new Date(post.date), 55 - }); 56 - 57 - cachedBlogData(blogCategoryOrAll) 58 - .then(({ blogData }) => blogData.posts.forEach(mapBlogPostToFeed)) 59 - .then(() => writeFile(join(publicFeedPath, metadata.file), feed.rss2())); 60 - });
···
-127
scripts/next-data/getBlogData.mjs
··· 1 - 'use strict'; 2 - 3 - import { readFile, readdir } from 'node:fs/promises'; 4 - import { basename, extname, join } from 'node:path'; 5 - import graymatter from 'gray-matter'; 6 - 7 - import { 8 - getDirectories, 9 - getMatchingRoutes, 10 - getRelativePath, 11 - } from './_helpers.mjs'; 12 - 13 - // this allows us to get the current module working directory 14 - const __dirname = getRelativePath(import.meta.url); 15 - 16 - // gets the current blog path based on local module path 17 - const blogPath = join(__dirname, '../../pages/en/blog'); 18 - 19 - // gathers only the frontmatter fields that are relevant to us 20 - const getMatter = name => content => { 21 - const { title, author, date, category } = graymatter(content).data; 22 - 23 - // we only want the actual name of the file without the extension 24 - // and then prepend the category name to it 25 - const slug = `/blog/${category}/${basename(name, extname(name))}`; 26 - 27 - return { title, author, date, category, slug, file: basename(name) }; 28 - }; 29 - 30 - const getPost = category => post => 31 - readFile(join(blogPath, category, post)).then(getMatter(post)); 32 - 33 - const getPosts = (category, posts) => 34 - posts.then(posts => Promise.all(posts.map(getPost(category)))); 35 - 36 - const currentYear = new Date().getFullYear(); 37 - 38 - // Note.: This current structure is coupled to the current way how we do pagination and categories 39 - // This will definitely change over time once we start migrating to the `nodejs/nodejs.dev` codebase 40 - export const getBlogData = () => { 41 - const blogCategories = getDirectories(blogPath).then(c => 42 - c.map(s => [s, readdir(join(blogPath, s))]) 43 - ); 44 - 45 - const categoriesPosts = blogCategories.then(c => 46 - c.map(([s, f]) => [s, getPosts(s, f)]) 47 - ); 48 - 49 - return (route = '/', getAllAvailablePosts = false) => { 50 - const [, , subDirectory, category = `year-${currentYear}`, blogPostSlug] = 51 - route.split('/'); 52 - 53 - const generatedBlogData = (posts, hasNext, hasPrev) => ({ 54 - blogData: { 55 - posts: posts.sort((a, b) => b.date - a.date), 56 - currentCategory: category, 57 - pagination: { next: hasNext || null, prev: hasPrev || null }, 58 - }, 59 - }); 60 - 61 - // we don't want to generate blog data within a blog post 62 - if (blogPostSlug && blogPostSlug.length > 0) { 63 - return {}; 64 - } 65 - 66 - if (getMatchingRoutes(subDirectory, ['blog'])) { 67 - return categoriesPosts.then(categories => { 68 - // yearly pagination posts (doesn't accept category pagination) 69 - if (category && category.startsWith('year-')) { 70 - const selectedYear = Number(category.replace('year-', '')); 71 - 72 - // get only the post ingredient from the category array 73 - const allPosts = categories.map(([, f]) => f); 74 - 75 - const generatedBlog = posts => 76 - generatedBlogData( 77 - posts.filter(p => p.date.getFullYear() === selectedYear), 78 - posts.some(p => p.date.getFullYear() === selectedYear + 1) && 79 - `/blog/year-${selectedYear + 1}`, 80 - posts.some(p => p.date.getFullYear() === selectedYear - 1) && 81 - `/blog/year-${selectedYear - 1}` 82 - ); 83 - 84 - return Promise.all(allPosts) 85 - .then(s => Promise.all(s.flat())) 86 - .then(s => s.filter(p => p.date && p.file !== 'index.md')) 87 - .then(generatedBlog); 88 - } 89 - 90 - // attempts to find a category that matches the current route category 91 - const currentCategory = categories.find(([c]) => c === category); 92 - 93 - if (category && currentCategory) { 94 - // extract the posts part of the current category 95 - const [, categoryPosts] = currentCategory; 96 - 97 - const generatedBlog = posts => generatedBlogData(posts); 98 - 99 - // get all posts from current category instead of traversing all categories 100 - return categoryPosts 101 - .then(posts => posts.flat()) 102 - .then(posts => posts.filter(p => p.file !== 'index.md')) 103 - .then(generatedBlog); 104 - } 105 - 106 - // this should not happen or means the category is non-existent 107 - return {}; 108 - }); 109 - } 110 - 111 - if (getAllAvailablePosts) { 112 - return categoriesPosts.then(categories => { 113 - // get only the post ingredient from the category array 114 - const allPosts = categories.map(([, f]) => f); 115 - 116 - const generatedBlog = posts => generatedBlogData(posts); 117 - 118 - return Promise.all(allPosts) 119 - .then(s => Promise.all(s.flat())) 120 - .then(s => s.filter(p => p.date && p.file !== 'index.md')) 121 - .then(generatedBlog); 122 - }); 123 - } 124 - 125 - return {}; 126 - }; 127 - };
···
-3
scripts/next-data/index.mjs
··· 1 - export * from './generatePreBuildFiles.mjs'; 2 - export * from './generateNodeReleasesJson.mjs'; 3 - export * from './getBlogData.mjs';
···
+2 -2
site.json
··· 23 { 24 "title": "Node.js Blog: Releases", 25 "file": "releases.xml", 26 - "blogCategory": "release" 27 }, 28 { 29 "title": "Node.js Blog: Vulnerability Reports", 30 "file": "vulnerability.xml", 31 - "blogCategory": "vulnerability" 32 } 33 ], 34 "websiteBanners": {
··· 23 { 24 "title": "Node.js Blog: Releases", 25 "file": "releases.xml", 26 + "category": "release" 27 }, 28 { 29 "title": "Node.js Blog: Vulnerability Reports", 30 "file": "vulnerability.xml", 31 + "category": "vulnerability" 32 } 33 ], 34 "websiteBanners": {
+16 -49
theme.tsx
··· 1 - import { useEffect } from 'react'; 2 - import { MDXProvider } from '@mdx-js/react'; 3 - import highlightJs from 'highlight.js/lib/common'; 4 import HtmlHead from './components/HtmlHead'; 5 - import AnchoredHeading from './components/AnchoredHeading'; 6 - import NodeApiVersionLinks from './components/Docs/NodeApiVersionLinks'; 7 - import { LayoutProvider } from './providers/layoutProvider'; 8 - import { useRouter } from './hooks/useRouter'; 9 import type { FC, PropsWithChildren } from 'react'; 10 - import type { NextraThemeLayoutProps } from 'nextra'; 11 - import type { MDXComponents } from 'mdx/types'; 12 - import type { LegacyFrontMatter } from './types'; 13 14 - type LayoutProps = PropsWithChildren<{ 15 - pageOpts: NextraThemeLayoutProps['pageOpts']; 16 }>; 17 18 - const mdxComponents: MDXComponents = { 19 - NodeApiVersionLinks: NodeApiVersionLinks, 20 - h1: props => <AnchoredHeading level={1} {...props} />, 21 - h2: props => <AnchoredHeading level={2} {...props} />, 22 - h3: props => <AnchoredHeading level={3} {...props} />, 23 - h4: props => <AnchoredHeading level={4} {...props} />, 24 - h5: props => <AnchoredHeading level={5} {...props} />, 25 - h6: props => <AnchoredHeading level={6} {...props} />, 26 - blockquote: ({ children }) => <div className="highlight-box">{children}</div>, 27 - }; 28 29 - const Content: FC<LayoutProps> = ({ children }) => { 30 - const { asPath } = useRouter(); 31 - 32 - // Re-highlights the pages on route change 33 - useEffect(() => highlightJs.highlightAll(), [asPath]); 34 - 35 - useEffect(() => window.startLegacyApp(), []); 36 37 - return ( 38 - <MDXProvider components={mdxComponents} disableParentContext> 39 - {children} 40 - </MDXProvider> 41 ); 42 }; 43 - 44 - // @TODO: Nextra should provide better customization to FrontMatter Props 45 - type ThemeProps = { 46 - pageOpts: Omit<NextraThemeLayoutProps['pageOpts'], 'frontMatter'> & { 47 - frontMatter: LegacyFrontMatter; 48 - }; 49 - } & NextraThemeLayoutProps; 50 - 51 - const Theme: FC<ThemeProps> = ({ pageOpts, pageProps, children }) => ( 52 - <> 53 - <HtmlHead frontMatter={pageOpts.frontMatter} /> 54 - <LayoutProvider pageOpts={pageOpts} pageProps={pageProps}> 55 - <Content pageOpts={pageOpts}>{children}</Content> 56 - </LayoutProvider> 57 - </> 58 - ); 59 60 export default Theme;
··· 1 + import { MDXRemote } from 'next-mdx-remote'; 2 + import { LayoutProvider } from './providers/layoutProvider'; 3 + import { MDXProvider } from './providers/mdxProvider'; 4 import HtmlHead from './components/HtmlHead'; 5 import type { FC, PropsWithChildren } from 'react'; 6 + import type { MDXRemoteSerializeResult } from 'next-mdx-remote'; 7 8 + type ThemeProps = PropsWithChildren<{ 9 + content?: MDXRemoteSerializeResult; 10 }>; 11 12 + const Theme: FC<ThemeProps> = ({ content, children }) => { 13 + const frontMatter = content?.frontmatter || {}; 14 15 + return ( 16 + <> 17 + <HtmlHead frontMatter={frontMatter} /> 18 + <LayoutProvider frontMatter={frontMatter}> 19 + <MDXProvider>{content && <MDXRemote {...content} />}</MDXProvider> 20 21 + {children} 22 + </LayoutProvider> 23 + </> 24 ); 25 }; 26 27 export default Theme;
+7 -2
tsconfig.json
··· 16 "incremental": true, 17 "paths": { 18 "@/*": ["./*"] 19 - } 20 }, 21 - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 22 "exclude": ["node_modules"] 23 }
··· 16 "incremental": true, 17 "paths": { 18 "@/*": ["./*"] 19 + }, 20 + "plugins": [ 21 + { 22 + "name": "next" 23 + } 24 + ] 25 }, 26 + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 27 "exclude": ["node_modules"] 28 }
+11 -22
turbo.json
··· 17 }, 18 "lint": { 19 "inputs": [ 20 - "{components,hooks,layouts,providers,types,util}/**/*.{ts,tsx}", 21 "{components,layouts,pages,styles}/**/*.{css,sass,scss}", 22 "*.{md,mdx,json,ts,tsx,mjs,js}", 23 - "pages/**/*.{tsx,ts,mdx,md}", 24 - "scripts/**/*.{js,mjs}", 25 "i18n/**/.json", 26 ".eslintrc", 27 ".eslintignore", ··· 49 }, 50 "build": { 51 "inputs": [ 52 - "{components,hooks,layouts,providers,types,util}/**/*.{ts,tsx}", 53 "{components,layouts,pages,styles}/**/*.{css,sass,scss}", 54 - "pages/**/*.{tsx,ts,mdx,md}", 55 - "scripts/**/*.{js,mjs}", 56 - "tsconfig.json", 57 - "next.config.mjs", 58 - "next.data.mjs", 59 - "next-sitemap.config.mjs", 60 - "theme.tsx", 61 - "middleware.ts" 62 ], 63 "outputs": [".next/**", "!.next/cache/**"] 64 }, ··· 67 }, 68 "deploy": { 69 "inputs": [ 70 - "{components,hooks,layouts,providers,types,util}/**/*.{ts,tsx}", 71 "{components,layouts,pages,styles}/**/*.{css,sass,scss}", 72 - "pages/**/*.{tsx,ts,mdx,md}", 73 - "scripts/**/*.{js,mjs}", 74 - "tsconfig.json", 75 - "next.config.mjs", 76 - "next.data.mjs", 77 - "next-sitemap.config.mjs", 78 - "theme.tsx", 79 - "middleware.ts" 80 ], 81 "outputs": [".next/**", "!.next/cache/**"] 82 }, ··· 86 "storybook:build": { 87 "inputs": [ 88 "{components,hooks,layouts,providers,types,util}/**/*.{ts,tsx}", 89 - "{components,layouts,pages,styles}/**/*.{css,sass,scss}" 90 ], 91 "outputs": ["storybook-static/**"] 92 }
··· 17 }, 18 "lint": { 19 "inputs": [ 20 + "{components,hooks,layouts,providers,types,util,middlewares,app,pages}/**/*.{ts,tsx}", 21 "{components,layouts,pages,styles}/**/*.{css,sass,scss}", 22 + "{scripts,next-data}/**/*.{js,mjs}", 23 "*.{md,mdx,json,ts,tsx,mjs,js}", 24 + "pages/**/*.{mdx,md}", 25 "i18n/**/.json", 26 ".eslintrc", 27 ".eslintignore", ··· 49 }, 50 "build": { 51 "inputs": [ 52 + "{components,hooks,layouts,providers,types,util,middlewares,app,pages}/**/*.{ts,tsx}", 53 "{components,layouts,pages,styles}/**/*.{css,sass,scss}", 54 + "{scripts,next-data}/**/*.{js,mjs}", 55 + "*.{md,mdx,json,ts,tsx,mjs,js}", 56 + "pages/**/*.{mdx,md}" 57 ], 58 "outputs": [".next/**", "!.next/cache/**"] 59 }, ··· 62 }, 63 "deploy": { 64 "inputs": [ 65 + "{components,hooks,layouts,providers,types,util,middlewares,app,pages}/**/*.{ts,tsx}", 66 "{components,layouts,pages,styles}/**/*.{css,sass,scss}", 67 + "*.{md,mdx,json,ts,tsx,mjs,js}", 68 + "pages/**/*.{mdx,md}" 69 ], 70 "outputs": [".next/**", "!.next/cache/**"] 71 }, ··· 75 "storybook:build": { 76 "inputs": [ 77 "{components,hooks,layouts,providers,types,util}/**/*.{ts,tsx}", 78 + "{components,layouts,styles}/**/*.{css,sass,scss}" 79 ], 80 "outputs": ["storybook-static/**"] 81 }
+3 -5
types/blog.ts
··· 1 export interface BlogPost { 2 title: string; 3 - author?: string; 4 date: string; 5 category: string; 6 slug: string; 7 - readingTime?: string; // TODO: verify this works when implementing blog 8 - file: string; 9 } 10 11 export interface BlogData { 12 posts: BlogPost[]; 13 - currentCategory: string; 14 - pagination: { prev?: string; next?: string }; 15 }
··· 1 export interface BlogPost { 2 title: string; 3 + author: string; 4 date: string; 5 category: string; 6 slug: string; 7 } 8 9 export interface BlogData { 10 posts: BlogPost[]; 11 + pagination: number[]; 12 + categories: string[]; 13 }
+1 -1
types/frontmatter.ts
··· 4 // this is going to be done via a script that replaces layouts 5 // Note.: The current legacy pages have other frontmatter entries but they're irrelevant 6 export interface LegacyFrontMatter { 7 - layout: LegacyLayouts; 8 title?: string; 9 robots?: string; 10 labels?: Record<string, string>;
··· 4 // this is going to be done via a script that replaces layouts 5 // Note.: The current legacy pages have other frontmatter entries but they're irrelevant 6 export interface LegacyFrontMatter { 7 + layout?: LegacyLayouts; 8 title?: string; 9 robots?: string; 10 labels?: Record<string, string>;
-11
types/index.ts
··· 1 - import type { AppProps as DefaultAppProps } from 'next/app'; 2 - 3 - import type { BlogData } from './blog'; 4 - 5 export * from './api'; 6 export * from './blog'; 7 export * from './config'; ··· 14 export * from './prevNextLink'; 15 export * from './releases'; 16 export * from './middlewares'; 17 - 18 - export interface AppProps { 19 - blogData?: BlogData; 20 - statusCode?: number; 21 - } 22 - 23 - export type NextraAppProps = DefaultAppProps<AppProps>;
··· 1 export * from './api'; 2 export * from './blog'; 3 export * from './config'; ··· 10 export * from './prevNextLink'; 11 export * from './releases'; 12 export * from './middlewares';
+8 -1
types/middlewares.ts
··· 13 locale: NextMiddlewareLocale 14 ) => Promise<NextResponse>; 15 matcher: (request: NextRequest, locale: NextMiddlewareLocale) => boolean; 16 - routes: string[]; 17 };
··· 13 locale: NextMiddlewareLocale 14 ) => Promise<NextResponse>; 15 matcher: (request: NextRequest, locale: NextMiddlewareLocale) => boolean; 16 + routes: (string | RegExp)[]; 17 + }; 18 + 19 + export type RouteSegment = { 20 + filename: string; 21 + localised: boolean; 22 + routeWithLocale: string; 23 + pathname: string; 24 };
+9 -3
types/navigation.ts
··· 1 - import type navigation from '../navigation.json'; 2 - 3 - export type NavigationKeys = keyof typeof navigation; 4 5 export interface NavigationEntry { 6 translationId: string;
··· 1 + export type NavigationKeys = 2 + | 'home' 3 + | 'about' 4 + | 'download' 5 + | 'docs' 6 + | 'getInvolved' 7 + | 'security' 8 + | 'certification' 9 + | 'blog'; 10 11 export interface NavigationEntry { 12 translationId: string;
-9
util/openSans.ts
··· 1 - import { Open_Sans } from 'next/font/google'; 2 - 3 - const openSans = Open_Sans({ 4 - weight: ['300', '400', '600'], 5 - display: 'fallback', 6 - subsets: ['latin'], 7 - }); 8 - 9 - export default openSans;
···