CLI: Support template for Tailwind CSS + Next Docs MDX

This commit is contained in:
SonMooSans
2023-12-30 23:22:05 +08:00
parent db840c2893
commit 579ecaacb5
39 changed files with 760 additions and 155 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'create-next-docs-app': minor
---
Support template for Tailwind CSS + Next Docs MDX
@@ -33,7 +33,6 @@ yarn create next-docs-app
### Options
You can choose one of two examples: `simple` and `advanced`.
You can choose a built-in content source, including Contentlayer and Next Docs MDX.
- Simple: with Typescript and Next.js
- Advanced: with Tailwind CSS, Typescript and Next.js
It can also configure Tailwind CSS for styling.
+1
View File
@@ -24,6 +24,7 @@
"@vercel/style-guide": "^5.1.0",
"concurrently": "^8.2.1",
"prettier": "^3.0.3",
"rimraf": "^5.0.5",
"tsup": "8.0.1",
"turbo": "1.11.2",
"typescript": "5.3.3",
+1 -1
View File
@@ -1,4 +1,4 @@
module.exports = {
extends: ['custom/library'],
ignorePatterns: ['./templates/**/*'],
ignorePatterns: ['/template/**/*'],
};
-4
View File
@@ -9,7 +9,3 @@ pnpx create-next-docs-app
#or
yarn create next-docs-app
```
## Examples
The examples are automatically generated from `./examples`
+3 -4
View File
@@ -14,16 +14,15 @@
"author": "Fuma Nama",
"bin": "./dist/index.js",
"files": [
"templates/*",
"template/*",
"static/*",
"dist/*"
],
"scripts": {
"build": "pnpm sync && tsup",
"clean": "rmdir /q/s dist && rmdir /q/s templates",
"build": "tsup",
"clean": "rimraf dist",
"dev": "tsup --watch",
"lint": "eslint .",
"sync": "node ./scripts/sync.js",
"types:check": "tsc --noEmit"
},
"dependencies": {
-47
View File
@@ -1,47 +0,0 @@
const fs = require('node:fs');
const path = require('node:path');
const { globSync } = require('fast-glob');
const pc = require('picocolors');
const sources = ['simple', 'advanced', 'simple-mdx'];
const cwd = process.cwd();
for (const source of sources) {
console.log(pc.bgBlue(`Copying ${source}`));
console.log(pc.bgRed('Deleting old files'));
fs.rmSync(`./templates/${source}`, { recursive: true, force: true });
const sourceDir = path.resolve(cwd, `../../examples/${source}`);
const sourceFiles = globSync(
[
'**/*',
'!content',
'!node_modules',
'!pnpm-lock.yaml',
'!next-env.d.ts',
],
{ dot: false, cwd: sourceDir },
);
Promise.all(
sourceFiles.map(async (p) => {
const dirname = path.dirname(p);
const basename = path.basename(p);
const from = path.resolve(sourceDir, p);
const to = path.join(
path.resolve(cwd, `./templates/${source}`),
dirname,
basename,
);
console.log(p);
// Ensure the destination directory exists
await fs.promises.mkdir(path.dirname(to), { recursive: true });
return fs.promises.copyFile(from, to);
}),
);
}
+130 -74
View File
@@ -5,6 +5,7 @@ import path from 'node:path';
import {
cancel,
confirm,
group,
intro,
isCancel,
outro,
@@ -13,46 +14,53 @@ import {
text,
} from '@clack/prompts';
import * as color from 'picocolors';
import packagePackageJson from '../package.json';
import { autoInstall, getPackageManager } from './auto-install';
const cwd = process.cwd();
const sourceDir = path.resolve(__dirname, '../');
const manager = getPackageManager();
async function main(): Promise<void> {
const cwd = process.cwd();
const sourceDir = path.resolve(__dirname, '../');
intro(color.bgCyan(color.bold('Create Next Docs')));
const inputName = await text({
message: 'Project name',
placeholder: 'my-app',
defaultValue: 'my-app',
});
const options = await group(
{
name: () =>
text({
message: 'Project name',
placeholder: 'my-app',
defaultValue: 'my-app',
}),
type: () =>
select({
message: 'Choose a content source',
initialValue: 'next-docs-mdx' as Source,
options: [
{ value: 'next-docs-mdx', label: 'Next Docs MDX' },
{ value: 'contentlayer', label: 'Contentlayer' },
],
}),
tailwindcss: () => confirm({ message: 'Use Tailwind CSS for styling?' }),
autoInstall: () =>
confirm({
message: `Do you want to install packages automatically? (detected as ${manager})`,
}),
},
{
onCancel: () => {
cancel('Installation Stopped.');
process.exit(0);
},
},
);
if (isCancel(inputName)) {
cancel();
return;
}
const pathname = inputName.toLowerCase().replace(/\s/, '-');
const dest = path.resolve(cwd, pathname);
const name = path.basename(dest);
const type = await select({
message: 'Which example you want to install?',
initialValue: 'simple',
options: [
{ value: 'simple', label: 'Default (Contentlayer)' },
{ value: 'advanced', label: 'Advanced (Contentlayer)' },
{ value: 'simple-mdx', label: 'Default (Next Docs MDX)' },
],
});
if (isCancel(type)) {
cancel();
return;
}
const projectName = options.name.toLowerCase().replace(/\s/, '-');
const dest = path.resolve(cwd, projectName);
if (existsSync(dest)) {
const del = await confirm({
message: `${pathname} already exists, do you want to delete it?`,
message: `${projectName} already exists, do you want to delete it?`,
});
if (isCancel(del)) {
@@ -62,35 +70,43 @@ async function main(): Promise<void> {
if (del) {
const info = spinner();
info.start(`Deleting ${pathname}`);
info.start(`Deleting ${projectName}`);
await fs.rm(dest, {
recursive: true,
force: true,
});
info.stop(`Deleted ${pathname}`);
info.stop(`Deleted ${projectName}`);
}
}
const info = spinner();
info.start(`Copying files to ${pathname}`);
info.start(`Copying files to ${projectName}`);
await copy(path.join(sourceDir, `templates/${type}`), dest);
await copy(path.join(sourceDir, `template/${options.type}`), dest);
await copy(
path.join(sourceDir, 'static/content'),
path.join(dest, 'content/docs'),
);
info.message('Updating package.json');
await updatePackageJson(path.join(dest, 'package.json'), name);
if (options.tailwindcss) {
await copy(path.join(sourceDir, `template/+tailwindcss`), dest);
}
info.message('Writing package.json');
const packageJson = createPackageJson(
projectName,
options.type,
options.tailwindcss,
);
await fs.writeFile(path.join(dest, 'package.json'), packageJson);
info.message('Updating README.md');
await generateReadme(
path.join(sourceDir, 'static/README.md'),
path.join(dest, 'README.md'),
name,
);
const readMe = await getReadme(projectName);
await fs.writeFile(path.join(dest, 'README.md'), readMe);
info.message('Adding .gitignore');
await fs.copyFile(
@@ -98,28 +114,23 @@ async function main(): Promise<void> {
path.join(dest, '.gitignore'),
);
info.stop('Project Generated');
const manager = getPackageManager();
const shouldInstall = await confirm({
message: `Do you want to install packages automatically? (detected as ${manager})`,
});
if (isCancel(shouldInstall)) cancel();
if (shouldInstall) {
if (options.autoInstall) {
info.message('Installing dependencies');
await autoInstall(manager, dest);
}
info.stop('Project Generated');
outro(color.bgGreen(color.bold('Done')));
if (type === 'advanced') {
if (options.tailwindcss) {
console.log('✔ Tailwind CSS');
}
console.log('✔ Typescript');
console.log(color.bold('\nOpen the project'));
console.log(color.cyan(`cd ${pathname}`));
console.log(color.cyan(`cd ${projectName}`));
console.log(color.bold('\nRun Development Server'));
console.log(color.cyan('npm run dev | pnpm run dev | yarn dev'));
@@ -131,30 +142,75 @@ async function main(): Promise<void> {
process.exit(0);
}
async function updatePackageJson(
fileName: string,
projectName: string,
): Promise<void> {
const packageJson = JSON.parse(
(await fs.readFile(fileName)).toString(),
) as Record<string, unknown>;
async function getReadme(projectName: string): Promise<string> {
const template = await fs
.readFile(path.join(sourceDir, 'static/README.md'))
.then((res) => res.toString());
packageJson.name = projectName;
await fs.writeFile(fileName, JSON.stringify(packageJson, undefined, 2));
return `# ${projectName}\n\n${template}`;
}
async function generateReadme(
templatePath: string,
destination: string,
projectName: string,
): Promise<void> {
const template = await fs
.readFile(templatePath)
.then((res) => res.toString());
const content = `# ${projectName}\n\n${template}`;
type Source = 'contentlayer' | 'next-docs-mdx';
await fs.writeFile(destination, content);
function createPackageJson(
name: string,
source: Source,
tailwindCss: boolean,
): string {
const nextDocsVersion = packagePackageJson.version;
const packageJson = {
name,
version: '0.0.0',
private: true,
scripts: {
build: 'next build',
dev: 'next dev',
start: 'next start',
},
dependencies: {
next: '14.0.4',
'next-docs-ui': nextDocsVersion,
'next-docs-zeta': nextDocsVersion,
react: '18.2.0',
'react-dom': '18.2.0',
},
devDependencies: {
'@types/react': '18.2.0',
'@types/react-dom': '18.2.1',
typescript: '5.3.3',
},
};
if (source === 'contentlayer') {
Object.assign(packageJson.dependencies, {
contentlayer: '0.3.4',
'next-contentlayer': '0.3.4',
});
Object.assign(packageJson, {
overrides: {
unified: '^11.0.4',
'mdx-bundler': '^10.0.1',
},
});
}
if (source === 'next-docs-mdx') {
Object.assign(packageJson.dependencies, {
'next-docs-mdx': nextDocsVersion,
});
}
if (tailwindCss) {
Object.assign(packageJson.devDependencies, {
autoprefixer: '10.4.16',
postcss: '8.4.32',
tailwindcss: '3.3.7',
});
}
return JSON.stringify(packageJson, undefined, 2);
}
async function copy(
@@ -3,9 +3,9 @@ title: Hello World
description: Your first document
---
Hey there!
Welcome to the docs! You can start writing documents in `/content/docs`.
## Heading
## What is Next?
<Cards>
<Card title="Learn more about Next.js" href="https://nextjs.org/docs" />
@@ -14,7 +14,3 @@ Hey there!
href="https://next-docs-zeta.vercel.app"
/>
</Cards>
### Heading
#### Heading
@@ -1,11 +1,15 @@
---
title: Hello World
description: Your first document
title: Components
description: Components
---
Hey there!
## Code Block
## Heading
```js
console.log('Hello World');
```
## Cards
<Cards>
<Card title="Learn more about Next.js" href="https://nextjs.org/docs" />
@@ -14,11 +18,3 @@ Hey there!
href="https://next-docs-zeta.vercel.app"
/>
</Cards>
### Heading
```js
console.log('Hello World');
```
#### Heading
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@@ -0,0 +1,18 @@
import './global.css';
import { RootProvider } from 'next-docs-ui/provider';
import { Inter } from 'next/font/google';
import type { ReactNode } from 'react';
const inter = Inter({
subsets: ['latin'],
});
export default function Layout({ children }: { children: ReactNode }) {
return (
<html lang="en" className={inter.className}>
<body>
<RootProvider>{children}</RootProvider>
</body>
</html>
);
}
@@ -0,0 +1,16 @@
import Link from 'next/link';
export default function HomePage() {
return (
<main className="flex h-screen flex-col justify-center text-center">
<h1 className="mb-4 text-2xl font-bold">Hello World</h1>
<p className="text-muted-foreground">
You can open{' '}
<Link href="/docs" className="text-foreground font-semibold underline">
/docs
</Link>{' '}
and see the documentation.
</p>
</main>
);
}
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
@@ -0,0 +1,13 @@
const { docsUi, docsUiPlugins } = require('next-docs-ui/tailwind-plugin');
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./content/**/*.{md,mdx}',
'./mdx-components.{ts,tsx}',
'./node_modules/next-docs-ui/dist/**/*.js',
],
plugins: [...docsUiPlugins, docsUi],
};
@@ -0,0 +1,11 @@
import { getPages } from '@/app/source';
import { createSearchAPI } from 'next-docs-zeta/search/server';
export const { GET } = createSearchAPI('advanced', {
indexes: getPages()!.map((page) => ({
id: page.data._id,
title: page.data.title,
url: page.url,
structuredData: page.data.structuredData,
})),
});
@@ -0,0 +1,14 @@
'use client';
import { useMDXComponent } from 'next-contentlayer/hooks';
import defaultComponents from 'next-docs-ui/mdx/default-client';
const components = {
...defaultComponents,
};
export function Content({ code }: { code: string }) {
const MDX = useMDXComponent(code);
return <MDX components={components} />;
}
@@ -0,0 +1,45 @@
import { Content } from './content';
import { getPage, getPages, pageTree } from '@/app/source';
import type { Metadata } from 'next';
import { DocsPage, DocsBody } from 'next-docs-ui/page';
import { notFound } from 'next/navigation';
export default async function Page({
params,
}: {
params: { slug?: string[] };
}) {
const page = getPage(params.slug);
if (page == null) {
notFound();
}
return (
<DocsPage url={page.url} tree={pageTree} toc={page.data.toc}>
<DocsBody>
<h1>{page.data.title}</h1>
<Content code={page.data.body.code} />
</DocsBody>
</DocsPage>
);
}
export async function generateStaticParams(): Promise<{ slug: string[] }[]> {
return (
getPages()?.map((page) => ({
slug: page.slugs,
})) ?? []
);
}
export function generateMetadata({ params }: { params: { slug?: string[] } }) {
const page = getPage(params.slug);
if (page == null) notFound();
return {
title: page.data.title,
description: page.data.description,
} satisfies Metadata;
}
@@ -0,0 +1,11 @@
import { pageTree } from '../source';
import { DocsLayout } from 'next-docs-ui/layout';
import type { ReactNode } from 'react';
export default function RootDocsLayout({ children }: { children: ReactNode }) {
return (
<DocsLayout tree={pageTree} nav={{ title: 'My App' }}>
{children}
</DocsLayout>
);
}
@@ -0,0 +1,18 @@
import { RootProvider } from 'next-docs-ui/provider';
import 'next-docs-ui/style.css';
import { Inter } from 'next/font/google';
import type { ReactNode } from 'react';
const inter = Inter({
subsets: ['latin'],
});
export default function Layout({ children }: { children: ReactNode }) {
return (
<html lang="en" className={inter.className}>
<body>
<RootProvider>{children}</RootProvider>
</body>
</html>
);
}
@@ -0,0 +1,38 @@
import Link from 'next/link';
export default function HomePage() {
return (
<main
style={{
height: '100vh',
display: 'flex',
flexDirection: 'column',
textAlign: 'center',
justifyContent: 'center',
}}
>
<h1
style={{
fontSize: '2rem',
fontWeight: 'bold',
marginBottom: '1rem',
}}
>
Hello World
</h1>
<p>
You can open{' '}
<Link
href="/docs"
style={{
fontWeight: '600',
textDecoration: 'underline',
}}
>
/docs
</Link>{' '}
and see the documentation.
</p>
</main>
);
}
@@ -0,0 +1,9 @@
import { allDocs, allMeta } from 'contentlayer/generated';
import { createContentlayerSource } from 'next-docs-zeta/contentlayer';
import { loader } from 'next-docs-zeta/source';
export const { getPage, pageTree, getPages } = loader({
baseUrl: '/docs',
rootDir: 'docs',
source: createContentlayerSource(allMeta, allDocs),
});
@@ -0,0 +1,4 @@
import { makeSource } from 'contentlayer/source-files';
import { defaultConfig } from 'next-docs-zeta/contentlayer/configuration';
export default makeSource(defaultConfig);
@@ -0,0 +1,8 @@
/** @type {import('next').NextConfig} */
const config = {
reactStrictMode: true,
};
const { withContentlayer } = require('next-contentlayer');
module.exports = withContentlayer(config);
@@ -0,0 +1,35 @@
{
"compilerOptions": {
"baseUrl": ".",
"target": "ESNext",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"paths": {
"@/*": ["./*"],
"contentlayer/generated": ["./.contentlayer/generated"]
},
"plugins": [
{
"name": "next"
}
]
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".contentlayer/generated"
],
"exclude": ["node_modules"]
}
@@ -0,0 +1,11 @@
import { getPages } from '@/app/source';
import { createSearchAPI } from 'next-docs-zeta/search/server';
export const { GET } = createSearchAPI('advanced', {
indexes: getPages()!.map((page) => ({
title: page.data.title,
structuredData: page.data.exports.structuredData,
id: page.url,
url: page.url,
})),
});
@@ -0,0 +1,44 @@
import { getPage, getPages, tree } from '@/app/source';
import type { Metadata } from 'next';
import { DocsPage, DocsBody } from 'next-docs-ui/page';
import { notFound } from 'next/navigation';
export default async function Page({
params,
}: {
params: { slug?: string[] };
}) {
const page = getPage(params.slug);
if (page == null) {
notFound();
}
const MDX = page.data.exports.default;
return (
<DocsPage url={page.url} tree={tree} toc={page.data.exports.toc}>
<DocsBody>
<h1>{page.data.title}</h1>
<MDX />
</DocsBody>
</DocsPage>
);
}
export async function generateStaticParams() {
return getPages()!.map((page) => ({
slug: page.slugs,
}));
}
export function generateMetadata({ params }: { params: { slug?: string[] } }) {
const page = getPage(params.slug);
if (page == null) notFound();
return {
title: page.data.title,
description: page.data.description,
} satisfies Metadata;
}
@@ -0,0 +1,11 @@
import { tree } from '../source';
import { DocsLayout } from 'next-docs-ui/layout';
import type { ReactNode } from 'react';
export default function RootDocsLayout({ children }: { children: ReactNode }) {
return (
<DocsLayout tree={tree} nav={{ title: 'My App' }}>
{children}
</DocsLayout>
);
}
@@ -0,0 +1,18 @@
import { RootProvider } from 'next-docs-ui/provider';
import 'next-docs-ui/style.css';
import { Inter } from 'next/font/google';
import type { ReactNode } from 'react';
const inter = Inter({
subsets: ['latin'],
});
export default function Layout({ children }: { children: ReactNode }) {
return (
<html lang="en" className={inter.className}>
<body>
<RootProvider>{children}</RootProvider>
</body>
</html>
);
}
@@ -0,0 +1,38 @@
import Link from 'next/link';
export default function HomePage() {
return (
<main
style={{
height: '100vh',
display: 'flex',
flexDirection: 'column',
textAlign: 'center',
justifyContent: 'center',
}}
>
<h1
style={{
fontSize: '2rem',
fontWeight: 'bold',
marginBottom: '1rem',
}}
>
Hello World
</h1>
<p>
You can open{' '}
<Link
href="/docs"
style={{
fontWeight: '600',
textDecoration: 'underline',
}}
>
/docs
</Link>{' '}
and see the documentation.
</p>
</main>
);
}
@@ -0,0 +1,13 @@
import { map } from '@/.map';
import { createMDXSource } from 'next-docs-mdx';
import { loader } from 'next-docs-zeta/source';
export const {
getPage,
getPages,
pageTree: tree,
} = loader({
baseUrl: '/docs',
rootDir: 'docs',
source: createMDXSource(map),
});
@@ -0,0 +1,9 @@
import type { MDXComponents } from 'mdx/types';
import defaultComponents from 'next-docs-ui/mdx/default';
export function useMDXComponents(components: MDXComponents): MDXComponents {
return {
...defaultComponents,
...components,
};
}
@@ -0,0 +1,10 @@
import createNextDocsMDX from 'next-docs-mdx/config';
const withMDX = createNextDocsMDX();
/** @type {import('next').NextConfig} */
const config = {
reactStrictMode: true,
};
export default withMDX(config);
@@ -0,0 +1,29 @@
{
"compilerOptions": {
"baseUrl": ".",
"target": "ESNext",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"paths": {
"@/*": ["./*"]
},
"plugins": [
{
"name": "next"
}
]
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
+1 -1
View File
@@ -5,5 +5,5 @@
"@/*": ["./src/*"]
}
},
"exclude": ["node_modules", "templates", "scripts", "dist"]
"exclude": ["node_modules", "template", "dist"]
}
+1 -1
View File
@@ -123,7 +123,7 @@
],
"scripts": {
"build": "tsup",
"clean": "rmdir /q/s dist",
"clean": "rimraf dist",
"dev": "tsup --watch",
"lint": "eslint .",
"test": "vitest",
+1 -1
View File
@@ -35,7 +35,7 @@
],
"scripts": {
"build": "tsup",
"clean": "rmdir /q/s dist",
"clean": "rimraf dist",
"dev": "tsup --watch",
"lint": "eslint .",
"types:check": "tsc --noEmit"
+1 -1
View File
@@ -51,7 +51,7 @@
],
"scripts": {
"build": "tsup && postcss css/styles.css -o ./dist/style.css",
"clean": "rmdir /q/s dist",
"clean": "rimraf dist",
"dev": "concurrently \"pnpm dev:layout\" \"pnpm dev:tailwind\"",
"dev:layout": "tsup --watch",
"dev:tailwind": "postcss css/styles.css -o ./dist/style.css --watch",
+172
View File
@@ -30,6 +30,9 @@ importers:
prettier:
specifier: ^3.0.3
version: 3.0.3
rimraf:
specifier: ^5.0.5
version: 5.0.5
tsup:
specifier: 8.0.1
version: 8.0.1([email protected])
@@ -195,6 +198,49 @@ importers:
specifier: 5.3.3
version: 5.3.3
examples/my-app:
dependencies:
contentlayer:
specifier: 0.3.4
version: 0.3.4
next:
specifier: 14.0.4
version: 14.0.4(@babel/[email protected])([email protected])([email protected])
next-contentlayer:
specifier: 0.3.4
version: 0.3.4([email protected])([email protected])([email protected])([email protected])
next-docs-ui:
specifier: 6.1.0
version: link:../../packages/ui
next-docs-zeta:
specifier: 6.1.0
version: link:../../packages/headless
react:
specifier: 18.2.0
version: 18.2.0
react-dom:
specifier: 18.2.0
version: 18.2.0([email protected])
devDependencies:
'@types/react':
specifier: 18.2.0
version: 18.2.0
'@types/react-dom':
specifier: 18.2.1
version: 18.2.1
autoprefixer:
specifier: 10.4.16
version: 10.4.16([email protected])
postcss:
specifier: 8.4.32
version: 8.4.32
tailwindcss:
specifier: 3.3.7
version: 3.3.7
typescript:
specifier: 5.3.3
version: 5.3.3
examples/simple:
dependencies:
contentlayer:
@@ -1551,6 +1597,18 @@ packages:
resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
dev: true
/@isaacs/[email protected]:
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
engines: {node: '>=12'}
dependencies:
string-width: 5.1.2
string-width-cjs: /[email protected]
strip-ansi: 7.1.0
strip-ansi-cjs: /[email protected]
wrap-ansi: 8.1.0
wrap-ansi-cjs: /[email protected]
dev: true
/@jest/[email protected]:
resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -2034,6 +2092,13 @@ packages:
resolution: {integrity: sha512-+fguCd2d8d2qruk0H0DsCEy2CTK3t0Tugg7MhZ/UQMvmewbZLNnJ6heSYyzIZWG5IPfAXzoj4f4F/qpM7l4VBA==}
engines: {node: '>=14'}
/@pkgjs/[email protected]:
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
requiresBuild: true
dev: true
optional: true
/@pkgr/[email protected]:
resolution: {integrity: sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
@@ -3774,6 +3839,11 @@ packages:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
/[email protected]:
resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
engines: {node: '>=12'}
dev: true
/[email protected]:
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
engines: {node: '>=4'}
@@ -3791,6 +3861,11 @@ packages:
engines: {node: '>=10'}
dev: true
/[email protected]:
resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
engines: {node: '>=12'}
dev: true
/[email protected]:
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
@@ -4003,6 +4078,12 @@ packages:
balanced-match: 1.0.2
concat-map: 0.0.1
/[email protected]:
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
dependencies:
balanced-match: 1.0.2
dev: true
/[email protected]:
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
engines: {node: '>=8'}
@@ -4604,6 +4685,10 @@ packages:
stream-shift: 1.0.1
dev: true
/[email protected]:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
dev: true
/[email protected]:
resolution: {integrity: sha512-Frfus2VpYADsrh1lB3v/ft/WVFlVzOIm+Q0p7U7VqHI6qr7NWHYKe+Wif3W50n7JAFoBsWVsoU0+qDks6WQ60g==}
@@ -5448,6 +5533,14 @@ packages:
is-callable: 1.2.7
dev: true
/[email protected]:
resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==}
engines: {node: '>=14'}
dependencies:
cross-spawn: 7.0.3
signal-exit: 4.1.0
dev: true
/[email protected]:
resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==}
engines: {node: '>=0.4.x'}
@@ -5609,6 +5702,18 @@ packages:
/[email protected]:
resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
/[email protected]:
resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==}
engines: {node: '>=16 || 14 >=14.17'}
hasBin: true
dependencies:
foreground-child: 3.1.1
jackspeak: 2.3.6
minimatch: 9.0.3
minipass: 7.0.4
path-scurry: 1.10.1
dev: true
/[email protected]:
resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==}
dependencies:
@@ -6491,6 +6596,15 @@ packages:
set-function-name: 2.0.1
dev: true
/[email protected]:
resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==}
engines: {node: '>=14'}
dependencies:
'@isaacs/cliui': 8.0.2
optionalDependencies:
'@pkgjs/parseargs': 0.11.0
dev: true
/[email protected]:
resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
engines: {node: '>= 10.13.0'}
@@ -6854,6 +6968,11 @@ packages:
dependencies:
tslib: 2.6.2
/[email protected]:
resolution: {integrity: sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==}
engines: {node: 14 || >=16.14}
dev: true
/[email protected]:
resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==}
dependencies:
@@ -7768,6 +7887,13 @@ packages:
dependencies:
brace-expansion: 1.1.11
/[email protected]:
resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==}
engines: {node: '>=16 || 14 >=14.17'}
dependencies:
brace-expansion: 2.0.1
dev: true
/[email protected]:
resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==}
engines: {node: '>= 6'}
@@ -7780,6 +7906,11 @@ packages:
/[email protected]:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
/[email protected]:
resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==}
engines: {node: '>=16 || 14 >=14.17'}
dev: true
/[email protected]:
resolution: {integrity: sha512-VC5fg6ySUscaWUpI4gxCBTQMH2RdUpNrk+MsbpCYtIvf9SBJdiUey4qE7BXviJsJR4nDQxCZ+3yaYNW3guz/Pw==}
engines: {node: '>= 8.0.0'}
@@ -8239,6 +8370,14 @@ packages:
/[email protected]:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
/[email protected]:
resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==}
engines: {node: '>=16 || 14 >=14.17'}
dependencies:
lru-cache: 10.1.0
minipass: 7.0.4
dev: true
/[email protected]:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
@@ -9029,6 +9168,14 @@ packages:
glob: 7.2.3
dev: true
/[email protected]:
resolution: {integrity: sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==}
engines: {node: '>=14'}
hasBin: true
dependencies:
glob: 10.3.10
dev: true
/[email protected]:
resolution: {integrity: sha512-41xsWhzxqjMDASCxH5ibw1mXk+3c4TNI2UjKbLxe6iEzrSQnqOzmmK8/3mufCPbzHNJ2e04Fc1ddI35hHy+8zg==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@@ -9388,6 +9535,15 @@ packages:
is-fullwidth-code-point: 3.0.0
strip-ansi: 6.0.1
/[email protected]:
resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
engines: {node: '>=12'}
dependencies:
eastasianwidth: 0.2.0
emoji-regex: 9.2.2
strip-ansi: 7.1.0
dev: true
/[email protected]:
resolution: {integrity: sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==}
dependencies:
@@ -9449,6 +9605,13 @@ packages:
dependencies:
ansi-regex: 5.0.1
/[email protected]:
resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
engines: {node: '>=12'}
dependencies:
ansi-regex: 6.0.1
dev: true
/[email protected]:
resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==}
engines: {node: '>=0.10.0'}
@@ -10583,6 +10746,15 @@ packages:
string-width: 4.2.3
strip-ansi: 6.0.1
/[email protected]:
resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
engines: {node: '>=12'}
dependencies:
ansi-styles: 6.2.1
string-width: 5.1.2
strip-ansi: 7.1.0
dev: true
/[email protected]:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}