From 88962f9103e78b3d889398497ed12d69f9408b80 Mon Sep 17 00:00:00 2001 From: Saihajpreet Singh Date: Tue, 12 Jul 2022 09:21:34 -0400 Subject: [PATCH] Revert "Revert "New docs and website based on Nextra (#7981)" (#8083)" This reverts commit ed07ffb137bfc2107c4826648584546ebf60659b. --- .gitignore | 17 +- .prettierignore | 12 +- package.json | 5 +- .../plugins/flow/operations/src/config.ts | 6 +- .../other/fragment-matcher/src/index.ts | 8 +- .../plugins/other/introspection/src/index.ts | 2 +- .../plugins/other/schema-ast/src/index.ts | 6 +- packages/plugins/other/time/src/config.ts | 4 +- .../other/urql-introspection/src/index.ts | 2 +- .../src/base-resolvers-visitor.ts | 2 +- .../src/base-types-visitor.ts | 2 +- .../visitor-plugin-common/src/base-visitor.ts | 12 +- .../typescript/typescript/src/config.ts | 2 +- .../presets/gql-tag-operations/src/index.ts | 4 +- packages/presets/import-types/src/index.ts | 4 +- .../presets/near-operation-file/src/index.ts | 12 +- patches/nextra+2.0.0-alpha.56.patch | 1156 +++++++ .../nextra-theme-docs+2.0.0-alpha.59.patch | 2692 +++++++++++++++++ prettier.config.cjs | 3 + website/.babelrc.js | 14 - website/.eslintrc.js | 11 - website/docs-templates/client-note.md | 5 - website/docs-templates/flow-operations.md | 7 - website/docs-templates/import-types-preset.md | 7 - website/docs-templates/introspection.md | 5 - website/docs-templates/java-resolvers.md | 27 - website/docs-templates/java.md | 42 - website/docs-templates/jsdoc.md | 7 - website/docs-templates/schema-ast.md | 19 - website/docs-templates/time.md | 5 - .../docs-templates/typescript-generic-sdk.md | 13 - .../docs-templates/typescript-operations.md | 7 - website/docs-templates/typescript.md | 5 - website/docs-templates/urql-introspection.md | 15 - website/docs/integrations/gatsby.mdx | 14 - website/next-i18next.config.js | 4 - website/next.config.mjs | 55 +- website/package.json | 35 +- website/postcss.config.js | 7 + website/public/config.schema.json | 34 +- website/public/locales/en/common.json | 3 - website/public/style.css | 61 +- website/routes.ts | 87 - website/scripts/algolia-ci.mjs | 33 +- website/src/category-to-packages.mjs | 49 + website/src/components/MDXTabs/MDXTab.tsx | 16 - website/src/components/MDXTabs/MDXTabs.tsx | 101 - .../components/MDXTabsCurrentTabContext.tsx | 28 - website/src/components/MDXWarning.tsx | 17 - website/src/components/index.ts | 2 + .../components/live-demo/CodegenOutput.tsx | 6 +- website/src/components/live-demo/Editor.tsx | 22 +- website/src/components/live-demo/LiveDemo.tsx | 112 +- website/src/components/live-demo/examples.ts | 8 +- website/src/components/live-demo/generate.ts | 6 +- .../components/live-demo/styles.module.css | 43 - website/src/components/package-api-docs.tsx | 89 + website/src/components/package-cmd.tsx | 87 + website/src/components/plugins.tsx | 97 + website/src/components/ui/Markdown.tsx | 5 +- website/src/lib/docs-generator.ts | 3 +- website/src/lib/get-npm-info.tsx | 39 + website/src/lib/plugins.ts | 331 +- website/src/lib/transform.ts | 2 +- website/src/pages/_app.tsx | 184 +- website/src/pages/_document.tsx | 7 +- website/src/pages/docs/[[...slug]].tsx | 34 - .../advanced/generated-files-colocation.mdx | 80 +- .../pages}/docs/advanced/how-does-it-work.mdx | 20 +- website/src/pages/docs/advanced/meta.json | 6 + .../pages}/docs/advanced/profiler.mdx | 9 +- .../docs/advanced/programmatic-usage.mdx | 45 +- .../docs/config-reference/codegen-config.mdx | 99 +- .../docs/config-reference/config-field.mdx | 17 +- .../docs/config-reference/documents-field.mdx | 43 +- .../docs/config-reference/lifecycle-hooks.mdx | 14 +- .../src/pages/docs/config-reference/meta.json | 10 + .../config-reference/multiproject-config.mdx | 19 +- .../config-reference/naming-convention.mdx | 10 +- .../docs/config-reference/require-field.mdx | 21 +- .../docs/config-reference/schema-field.mdx | 72 +- .../docs/custom-codegen/contributing.mdx | 114 +- .../docs/custom-codegen/extend-schema.mdx | 31 +- .../pages}/docs/custom-codegen/index.mdx | 5 +- .../src/pages/docs/custom-codegen/meta.json | 8 + .../docs/custom-codegen/plugin-structure.mdx | 36 +- .../docs/custom-codegen/using-visitor.mdx | 21 +- .../custom-codegen/validate-configuration.mdx | 23 +- .../getting-started/development-workflow.mdx | 24 +- .../pages}/docs/getting-started/index.mdx | 192 +- .../docs/getting-started/installation.mdx | 51 +- .../src/pages/docs/getting-started/meta.json | 5 + .../{ => src/pages}/docs/guides/angular.mdx | 60 +- .../docs/guides/front-end-typescript-only.mdx | 44 +- .../pages}/docs/guides/further-reading.mdx | 26 +- .../pages}/docs/guides/graphql-modules.mdx | 43 +- .../guides/graphql-server-apollo-yoga.mdx | 112 +- website/src/pages/docs/guides/meta.json | 10 + website/{ => src/pages}/docs/guides/react.mdx | 312 +- .../{ => src/pages}/docs/guides/svelte.mdx | 88 +- website/{ => src/pages}/docs/guides/vue.mdx | 99 +- .../docs/integrations/apollo-local-state.mdx | 7 +- .../docs/integrations/create-react-app.mdx | 5 +- .../pages}/docs/integrations/federation.mdx | 9 +- .../src/pages/docs/integrations/gatsby.mdx | 11 + website/src/pages/docs/integrations/meta.json | 8 + .../pages}/docs/integrations/prettier.mdx | 5 +- .../pages}/docs/integrations/vscode.mdx | 5 +- website/src/pages/docs/meta.json | 9 + .../pages}/docs/migration/from-0-13.mdx | 25 +- .../pages}/docs/migration/from-0-18.mdx | 78 +- website/src/pages/docs/migration/meta.json | 4 + website/src/pages/index.mdx | 46 + website/src/pages/index.tsx | 59 - website/src/pages/meta.json | 29 + website/src/pages/plugins/[name].tsx | 200 -- website/src/pages/plugins/[name].tsx.old | 225 ++ .../plugins/c-sharp/c-sharp-operations.mdx} | 13 +- website/src/pages/plugins/c-sharp/meta.json | 3 + .../pages/plugins/flow/flow-operations.mdx | 11 + .../pages/plugins/flow/flow-resolvers.mdx} | 31 +- website/src/pages/plugins/flow/meta.json | 4 + website/src/pages/plugins/index.mdx | 39 + website/src/pages/plugins/index.tsx | 130 - .../plugins/java/java-apollo-android.mdx} | 27 +- .../src/pages/plugins/java/java-resolvers.mdx | 87 + .../pages/plugins/java/java.mdx} | 59 +- .../pages/plugins/java/kotlin.mdx} | 21 +- website/src/pages/plugins/java/meta.json | 6 + website/src/pages/plugins/meta.json | 13 + .../pages/plugins/other/add.mdx} | 21 +- .../pages/plugins/other/fragment-matcher.mdx} | 30 +- .../plugins/other/hasura-allow-list.mdx} | 21 +- .../src/pages/plugins/other/introspection.mdx | 11 + website/src/pages/plugins/other/jsdoc.mdx | 14 + website/src/pages/plugins/other/meta.json | 11 + .../pages/plugins/other/reason-client.mdx} | 13 +- .../src/pages/plugins/other/schema-ast.mdx | 26 + website/src/pages/plugins/other/time.mdx | 11 + .../plugins/other/urql-introspection.mdx | 25 + .../presets/gql-tag-operations-preset.mdx} | 68 +- .../presets/graphql-modules-preset.mdx} | 33 +- .../plugins/presets/import-types-preset.mdx | 14 + website/src/pages/plugins/presets/meta.json | 6 + .../presets/near-operation-file-preset.mdx} | 18 +- .../src/pages/plugins/typescript/meta.json | 29 + .../typescript/named-operations-object.mdx} | 13 +- .../typescript/relay-operation-optimizer.mdx} | 23 +- .../typescript/typed-document-node.mdx} | 25 +- .../typescript/typescript-apollo-angular.mdx} | 21 +- .../typescript-apollo-client-helpers.mdx} | 23 +- .../typescript/typescript-apollo-next.mdx} | 43 +- .../typescript/typescript-document-nodes.mdx} | 10 +- .../typescript/typescript-generic-sdk.mdx | 19 + .../typescript-graphql-files-modules.mdx} | 19 +- .../typescript-graphql-request.mdx} | 14 +- .../typescript/typescript-mongodb.mdx} | 26 +- .../plugins/typescript/typescript-msw.mdx} | 16 +- .../plugins/typescript/typescript-oclif.mdx} | 20 +- .../typescript/typescript-operations.mdx | 11 + .../typescript/typescript-react-apollo.mdx} | 26 +- .../typescript/typescript-react-query.mdx} | 40 +- .../typescript/typescript-resolvers.mdx} | 45 +- .../typescript/typescript-rtk-query.mdx} | 36 +- .../typescript/typescript-stencil-apollo.mdx} | 12 +- .../typescript/typescript-svelte-apollo.mdx} | 15 +- .../typescript/typescript-type-graphql.mdx} | 11 +- .../plugins/typescript/typescript-urql.mdx} | 16 +- .../typescript-validation-schema.mdx} | 15 +- .../typescript-vue-apollo-smart-ops.mdx} | 12 +- .../typescript/typescript-vue-apollo.mdx} | 24 +- .../typescript/typescript-vue-urql.mdx} | 12 +- .../pages/plugins/typescript/typescript.mdx | 11 + website/src/theme/Root.tsx | 15 - website/tailwind.config.cjs | 21 + website/theme.config.tsx | 38 + website/tsconfig.json | 5 +- website/twin.d.ts | 30 - yarn.lock | 2030 ++++++------- 179 files changed, 7606 insertions(+), 4141 deletions(-) create mode 100644 patches/nextra+2.0.0-alpha.56.patch create mode 100644 patches/nextra-theme-docs+2.0.0-alpha.59.patch delete mode 100644 website/.babelrc.js delete mode 100644 website/docs-templates/client-note.md delete mode 100644 website/docs-templates/flow-operations.md delete mode 100644 website/docs-templates/import-types-preset.md delete mode 100644 website/docs-templates/introspection.md delete mode 100644 website/docs-templates/java-resolvers.md delete mode 100644 website/docs-templates/java.md delete mode 100644 website/docs-templates/jsdoc.md delete mode 100644 website/docs-templates/schema-ast.md delete mode 100644 website/docs-templates/time.md delete mode 100644 website/docs-templates/typescript-generic-sdk.md delete mode 100644 website/docs-templates/typescript-operations.md delete mode 100644 website/docs-templates/typescript.md delete mode 100644 website/docs-templates/urql-introspection.md delete mode 100644 website/docs/integrations/gatsby.mdx delete mode 100644 website/next-i18next.config.js create mode 100644 website/postcss.config.js delete mode 100644 website/public/locales/en/common.json create mode 100644 website/src/category-to-packages.mjs delete mode 100644 website/src/components/MDXTabs/MDXTab.tsx delete mode 100644 website/src/components/MDXTabs/MDXTabs.tsx delete mode 100644 website/src/components/MDXTabsCurrentTabContext.tsx delete mode 100644 website/src/components/MDXWarning.tsx create mode 100644 website/src/components/index.ts create mode 100644 website/src/components/package-api-docs.tsx create mode 100644 website/src/components/package-cmd.tsx create mode 100644 website/src/components/plugins.tsx create mode 100644 website/src/lib/get-npm-info.tsx delete mode 100644 website/src/pages/docs/[[...slug]].tsx rename website/{ => src/pages}/docs/advanced/generated-files-colocation.mdx (54%) rename website/{ => src/pages}/docs/advanced/how-does-it-work.mdx (95%) create mode 100644 website/src/pages/docs/advanced/meta.json rename website/{ => src/pages}/docs/advanced/profiler.mdx (82%) rename website/{ => src/pages}/docs/advanced/programmatic-usage.mdx (65%) rename website/{ => src/pages}/docs/config-reference/codegen-config.mdx (84%) rename website/{ => src/pages}/docs/config-reference/config-field.mdx (75%) rename website/{ => src/pages}/docs/config-reference/documents-field.mdx (82%) rename website/{ => src/pages}/docs/config-reference/lifecycle-hooks.mdx (86%) create mode 100644 website/src/pages/docs/config-reference/meta.json rename website/{ => src/pages}/docs/config-reference/multiproject-config.mdx (85%) rename website/{ => src/pages}/docs/config-reference/naming-convention.mdx (96%) rename website/{ => src/pages}/docs/config-reference/require-field.mdx (88%) rename website/{ => src/pages}/docs/config-reference/schema-field.mdx (83%) rename website/{ => src/pages}/docs/custom-codegen/contributing.mdx (69%) rename website/{ => src/pages}/docs/custom-codegen/extend-schema.mdx (60%) rename website/{ => src/pages}/docs/custom-codegen/index.mdx (95%) create mode 100644 website/src/pages/docs/custom-codegen/meta.json rename website/{ => src/pages}/docs/custom-codegen/plugin-structure.mdx (85%) rename website/{ => src/pages}/docs/custom-codegen/using-visitor.mdx (92%) rename website/{ => src/pages}/docs/custom-codegen/validate-configuration.mdx (70%) rename website/{ => src/pages}/docs/getting-started/development-workflow.mdx (90%) rename website/{ => src/pages}/docs/getting-started/index.mdx (82%) rename website/{ => src/pages}/docs/getting-started/installation.mdx (61%) create mode 100644 website/src/pages/docs/getting-started/meta.json rename website/{ => src/pages}/docs/guides/angular.mdx (77%) rename website/{ => src/pages}/docs/guides/front-end-typescript-only.mdx (71%) rename website/{ => src/pages}/docs/guides/further-reading.mdx (74%) rename website/{ => src/pages}/docs/guides/graphql-modules.mdx (73%) rename website/{ => src/pages}/docs/guides/graphql-server-apollo-yoga.mdx (70%) create mode 100644 website/src/pages/docs/guides/meta.json rename website/{ => src/pages}/docs/guides/react.mdx (78%) rename website/{ => src/pages}/docs/guides/svelte.mdx (83%) rename website/{ => src/pages}/docs/guides/vue.mdx (82%) rename website/{ => src/pages}/docs/integrations/apollo-local-state.mdx (95%) rename website/{ => src/pages}/docs/integrations/create-react-app.mdx (87%) rename website/{ => src/pages}/docs/integrations/federation.mdx (78%) create mode 100644 website/src/pages/docs/integrations/gatsby.mdx create mode 100644 website/src/pages/docs/integrations/meta.json rename website/{ => src/pages}/docs/integrations/prettier.mdx (96%) rename website/{ => src/pages}/docs/integrations/vscode.mdx (92%) create mode 100644 website/src/pages/docs/meta.json rename website/{ => src/pages}/docs/migration/from-0-13.mdx (57%) rename website/{ => src/pages}/docs/migration/from-0-18.mdx (73%) create mode 100644 website/src/pages/docs/migration/meta.json create mode 100644 website/src/pages/index.mdx delete mode 100644 website/src/pages/index.tsx create mode 100644 website/src/pages/meta.json delete mode 100644 website/src/pages/plugins/[name].tsx create mode 100644 website/src/pages/plugins/[name].tsx.old rename website/{docs-templates/c-sharp-operations.md => src/pages/plugins/c-sharp/c-sharp-operations.mdx} (66%) create mode 100644 website/src/pages/plugins/c-sharp/meta.json create mode 100644 website/src/pages/plugins/flow/flow-operations.mdx rename website/{docs-templates/flow-resolvers.md => src/pages/plugins/flow/flow-resolvers.mdx} (71%) create mode 100644 website/src/pages/plugins/flow/meta.json create mode 100644 website/src/pages/plugins/index.mdx delete mode 100644 website/src/pages/plugins/index.tsx rename website/{docs-templates/java-apollo-android.md => src/pages/plugins/java/java-apollo-android.mdx} (59%) create mode 100644 website/src/pages/plugins/java/java-resolvers.mdx rename website/{docs-templates/java-installation.md => src/pages/plugins/java/java.mdx} (55%) rename website/{docs-templates/kotlin.md => src/pages/plugins/java/kotlin.mdx} (56%) create mode 100644 website/src/pages/plugins/java/meta.json create mode 100644 website/src/pages/plugins/meta.json rename website/{docs-templates/add.md => src/pages/plugins/other/add.mdx} (66%) rename website/{docs-templates/fragment-matcher.md => src/pages/plugins/other/fragment-matcher.mdx} (54%) rename website/{docs-templates/hasura-allow-list.md => src/pages/plugins/other/hasura-allow-list.mdx} (51%) create mode 100644 website/src/pages/plugins/other/introspection.mdx create mode 100644 website/src/pages/plugins/other/jsdoc.mdx create mode 100644 website/src/pages/plugins/other/meta.json rename website/{docs-templates/reason-client.md => src/pages/plugins/other/reason-client.mdx} (62%) create mode 100644 website/src/pages/plugins/other/schema-ast.mdx create mode 100644 website/src/pages/plugins/other/time.mdx create mode 100644 website/src/pages/plugins/other/urql-introspection.mdx rename website/{docs-templates/gql-tag-operations-preset.md => src/pages/plugins/presets/gql-tag-operations-preset.mdx} (85%) rename website/{docs-templates/graphql-modules-preset.md => src/pages/plugins/presets/graphql-modules-preset.mdx} (72%) create mode 100644 website/src/pages/plugins/presets/import-types-preset.mdx create mode 100644 website/src/pages/plugins/presets/meta.json rename website/{docs-templates/near-operation-file-preset.md => src/pages/plugins/presets/near-operation-file-preset.mdx} (69%) create mode 100644 website/src/pages/plugins/typescript/meta.json rename website/{docs-templates/named-operations-object.md => src/pages/plugins/typescript/named-operations-object.mdx} (85%) rename website/{docs-templates/relay-operation-optimizer.md => src/pages/plugins/typescript/relay-operation-optimizer.mdx} (67%) rename website/{docs-templates/typed-document-node.md => src/pages/plugins/typescript/typed-document-node.mdx} (75%) rename website/{docs-templates/typescript-apollo-angular.md => src/pages/plugins/typescript/typescript-apollo-angular.mdx} (62%) rename website/{docs-templates/typescript-apollo-client-helpers.md => src/pages/plugins/typescript/typescript-apollo-client-helpers.mdx} (62%) rename website/{docs-templates/typescript-apollo-next.md => src/pages/plugins/typescript/typescript-apollo-next.mdx} (90%) rename website/{docs-templates/typescript-document-nodes.md => src/pages/plugins/typescript/typescript-document-nodes.mdx} (62%) create mode 100644 website/src/pages/plugins/typescript/typescript-generic-sdk.mdx rename website/{docs-templates/typescript-graphql-files-modules.md => src/pages/plugins/typescript/typescript-graphql-files-modules.mdx} (71%) rename website/{docs-templates/typescript-graphql-request.md => src/pages/plugins/typescript/typescript-graphql-request.mdx} (85%) rename website/{docs-templates/typescript-mongodb.md => src/pages/plugins/typescript/typescript-mongodb.mdx} (91%) rename website/{docs-templates/typescript-msw.md => src/pages/plugins/typescript/typescript-msw.mdx} (52%) rename website/{docs-templates/typescript-oclif.md => src/pages/plugins/typescript/typescript-oclif.mdx} (94%) create mode 100644 website/src/pages/plugins/typescript/typescript-operations.mdx rename website/{docs-templates/typescript-react-apollo.md => src/pages/plugins/typescript/typescript-react-apollo.mdx} (68%) rename website/{docs-templates/typescript-react-query.md => src/pages/plugins/typescript/typescript-react-query.mdx} (88%) rename website/{docs-templates/typescript-resolvers.md => src/pages/plugins/typescript/typescript-resolvers.mdx} (76%) rename website/{docs-templates/typescript-rtk-query.md => src/pages/plugins/typescript/typescript-rtk-query.mdx} (71%) rename website/{docs-templates/typescript-stencil-apollo.md => src/pages/plugins/typescript/typescript-stencil-apollo.mdx} (53%) rename website/{docs-templates/typescript-svelte-apollo.md => src/pages/plugins/typescript/typescript-svelte-apollo.mdx} (93%) rename website/{docs-templates/typescript-type-graphql.md => src/pages/plugins/typescript/typescript-type-graphql.mdx} (75%) rename website/{docs-templates/typescript-urql.md => src/pages/plugins/typescript/typescript-urql.mdx} (59%) rename website/{docs-templates/typescript-validation-schema.md => src/pages/plugins/typescript/typescript-validation-schema.mdx} (68%) rename website/{docs-templates/typescript-vue-apollo-smart-ops.md => src/pages/plugins/typescript/typescript-vue-apollo-smart-ops.mdx} (82%) rename website/{docs-templates/typescript-vue-apollo.md => src/pages/plugins/typescript/typescript-vue-apollo.mdx} (85%) rename website/{docs-templates/typescript-vue-urql.md => src/pages/plugins/typescript/typescript-vue-urql.mdx} (54%) create mode 100644 website/src/pages/plugins/typescript/typescript.mdx delete mode 100644 website/src/theme/Root.tsx create mode 100644 website/tailwind.config.cjs create mode 100644 website/theme.config.tsx delete mode 100644 website/twin.d.ts diff --git a/.gitignore b/.gitignore index dc97019a8ee..c82ce923f03 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,14 @@ -.idea +.idea/ .npmrc .yarnclean .DS_Store coverage -npm-debug.log -lerna-debug.log -yarn-error.log -node_modules -website/build -website/functions -website/i18n -website/static/live-demo +*.log +node_modules/ temp -test-results/ junit.xml -dist -.bob +dist/ +.bob/ out.txt .cache tsconfig.tsbuildinfo diff --git a/.prettierignore b/.prettierignore index cde3a27fbfe..5be49635241 100644 --- a/.prettierignore +++ b/.prettierignore @@ -9,7 +9,13 @@ CHANGELOG.md .husky/_/ .changeset/*.md -# temporarly ignore follow files because prettier-ignore comments don't work in mdx2 +# temporarily ignore follow files because prettier-ignore comments don't work in mdx2 # see https://github.com/prettier/prettier/pull/12208 -website/docs/advanced/how-does-it-work.mdx -website/docs/getting-started/development-workflow.mdx +website/src/pages/docs/advanced/generated-files-colocation.mdx +website/src/pages/docs/advanced/how-does-it-work.mdx +website/src/pages/docs/config-reference/schema-field.mdx +website/src/pages/docs/getting-started/index.mdx +website/src/pages/docs/guides/graphql-server-apollo-yoga.mdx +website/src/pages/docs/guides/react.mdx +website/src/pages/plugins/index.mdx +website/src/pages/plugins/presets/near-operation-file-preset.mdx diff --git a/package.json b/package.json index d969874a0c4..e1f0a0da6aa 100644 --- a/package.json +++ b/package.json @@ -100,10 +100,7 @@ "packages/**/src/**/*.{ts,tsx}": [ "eslint --fix" ], - "**/*.{ts,tsx,graphql,yml}": [ - "prettier --write" - ], - "**/*.json": [ + "**/*.{js,jsx,cjs,mjs,ts,tsx,graphql,gql,yml,yaml,json,md}": [ "prettier --write" ], "yarn.lock": [ diff --git a/packages/plugins/flow/operations/src/config.ts b/packages/plugins/flow/operations/src/config.ts index 6fba0784203..54f2562836d 100644 --- a/packages/plugins/flow/operations/src/config.ts +++ b/packages/plugins/flow/operations/src/config.ts @@ -13,7 +13,7 @@ export interface FlowDocumentsPluginConfig extends RawDocumentsConfig { * @default true * * @exampleMarkdown - * ```yaml + * ```yaml {6} * generates: * path/to/file.ts: * plugins: @@ -28,7 +28,7 @@ export interface FlowDocumentsPluginConfig extends RawDocumentsConfig { * @default false * * @exampleMarkdown - * ```yaml + * ```yaml {6} * generates: * path/to/file.ts: * plugins: @@ -43,7 +43,7 @@ export interface FlowDocumentsPluginConfig extends RawDocumentsConfig { * @default false * * @exampleMarkdown - * ```yaml + * ```yaml {7} * generates: * path/to/file.ts: * plugins: diff --git a/packages/plugins/other/fragment-matcher/src/index.ts b/packages/plugins/other/fragment-matcher/src/index.ts index 0af78169189..32122a9d94f 100644 --- a/packages/plugins/other/fragment-matcher/src/index.ts +++ b/packages/plugins/other/fragment-matcher/src/index.ts @@ -28,7 +28,7 @@ interface PossibleTypesResultData { * * If you are using `apollo-client` and your schema contains `interface` or `union` declaration, it's recommended to use Apollo's Fragment Matcher and the result generated by the plugin. * - * You can read more about it in `apollo-client` documentation: https://www.apollographql.com/docs/react/data/fragments/#fragments-on-unions-and-interfaces. + * You can read more about it in [`apollo-client` documentation](https://apollographql.com/docs/react/data/fragments/#fragments-on-unions-and-interfaces). * * Fragment Matcher plugin accepts a TypeScript / JavaScript or a JSON file as an output _(`.ts, .tsx, .js, .jsx, .json`)_. * @@ -42,7 +42,7 @@ export interface FragmentMatcherConfig { * @default es2015 * * @exampleMarkdown - * ```yaml + * ```yaml {6} * generates: * path/to/file.json: * plugins: @@ -57,7 +57,7 @@ export interface FragmentMatcherConfig { * @default 3 * * @exampleMarkdown - * ```yaml + * ```yaml {6} * generates: * path/to/file.ts: * plugins: @@ -72,7 +72,7 @@ export interface FragmentMatcherConfig { * @default false * * @exampleMarkdown - * ```yaml + * ```yaml {6} * generates: * path/to/file.ts: * plugins: diff --git a/packages/plugins/other/introspection/src/index.ts b/packages/plugins/other/introspection/src/index.ts index e4945655489..a34c672e8ce 100644 --- a/packages/plugins/other/introspection/src/index.ts +++ b/packages/plugins/other/introspection/src/index.ts @@ -12,7 +12,7 @@ export interface IntrospectionPluginConfig { * @default false * * @exampleMarkdown - * ```yaml + * ```yaml {6} * generates: * introspection.json: * plugins: diff --git a/packages/plugins/other/schema-ast/src/index.ts b/packages/plugins/other/schema-ast/src/index.ts index c929f3d1010..9fe369fdd56 100644 --- a/packages/plugins/other/schema-ast/src/index.ts +++ b/packages/plugins/other/schema-ast/src/index.ts @@ -26,7 +26,7 @@ export interface SchemaASTConfig { * @default false * * @exampleMarkdown - * ```yaml + * ```yaml {8} * schema: * - './src/schema.graphql' * generates: @@ -43,7 +43,7 @@ export interface SchemaASTConfig { * @default false * * @exampleMarkdown - * ```yaml + * ```yaml {8} * schema: * - './src/schema.graphql' * generates: @@ -60,7 +60,7 @@ export interface SchemaASTConfig { * @default false * * @exampleMarkdown - * ```yaml + * ```yaml {7} * schema: http://localhost:3000/graphql * generates: * schema.graphql: diff --git a/packages/plugins/other/time/src/config.ts b/packages/plugins/other/time/src/config.ts index 2632c5e5298..ffb70412298 100644 --- a/packages/plugins/other/time/src/config.ts +++ b/packages/plugins/other/time/src/config.ts @@ -4,7 +4,7 @@ export interface TimePluginConfig { * @default YYYY-MM-DDTHH:mm:ssZ * * @exampleMarkdown - * ```yaml + * ```yaml {4-5} * generates: * path/to/file.ts: * plugins: @@ -18,7 +18,7 @@ export interface TimePluginConfig { * @default 'Generated on' * * @exampleMarkdown - * ```yaml + * ```yaml {4-5} * generates: * path/to/file.ts: * plugins: diff --git a/packages/plugins/other/urql-introspection/src/index.ts b/packages/plugins/other/urql-introspection/src/index.ts index 24e9696d245..81623be69ba 100644 --- a/packages/plugins/other/urql-introspection/src/index.ts +++ b/packages/plugins/other/urql-introspection/src/index.ts @@ -21,7 +21,7 @@ export interface UrqlIntrospectionConfig { * @default es2015 * * @exampleMarkdown - * ```yaml + * ```yaml {6} * generates: * path/to/file.json: * plugins: diff --git a/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts index e03b85c77be..05d3fc349ba 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts @@ -81,7 +81,7 @@ export interface RawResolversConfig extends RawConfig { * @description Adds `_` to generated `Args` types in order to avoid duplicate identifiers. * * @exampleMarkdown - * ```yaml + * ```yaml {2} * config: * addUnderscoreToArgsType: true * ``` diff --git a/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts index fa6326fec64..2b9731dff8b 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts @@ -179,7 +179,7 @@ export interface RawTypesConfig extends RawConfig { * @exampleMarkdown * ## Override all definition types * - * ```yml + * ```yaml * generates: * path/to/file.ts: * plugins: diff --git a/packages/plugins/other/visitor-plugin-common/src/base-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-visitor.ts index eb88c650973..110a26dc194 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-visitor.ts @@ -46,7 +46,7 @@ export interface RawConfig { * @default false * * @exampleMarkdown - * ```yaml + * ```yaml {2} * config: * strictScalars: true * ``` @@ -57,7 +57,7 @@ export interface RawConfig { * @default any * * @exampleMarkdown - * ```yaml + * ```yaml {2} * config: * defaultScalarType: unknown * ``` @@ -123,7 +123,7 @@ export interface RawConfig { * @description Prefixes all the generated types. * * @exampleMarkdown - * ```yaml + * ```yaml {2} * config: * typesPrefix: I * ``` @@ -134,7 +134,7 @@ export interface RawConfig { * @description Suffixes all the generated types. * * @exampleMarkdown - * ```yaml + * ```yaml {2} * config: * typesSuffix: I * ``` @@ -157,7 +157,7 @@ export interface RawConfig { * in the selection set, and makes it non-optional * * @exampleMarkdown - * ```yaml + * ```yaml {2} * config: * nonOptionalTypename: true * ``` @@ -171,7 +171,7 @@ export interface RawConfig { * compatibility with TypeScript's "importsNotUsedAsValues": "error" option * * @example - * ```yaml + * ```yaml {2} * config: * useTypeImports: true * ``` diff --git a/packages/plugins/typescript/typescript/src/config.ts b/packages/plugins/typescript/typescript/src/config.ts index cfdb21dbc3d..5f09a235dcb 100644 --- a/packages/plugins/typescript/typescript/src/config.ts +++ b/packages/plugins/typescript/typescript/src/config.ts @@ -138,7 +138,7 @@ export interface TypeScriptPluginConfig extends RawTypesConfig { * @default false * * @exampleMarkdown Override all definition types - * ```yml + * ```yaml * generates: * path/to/file.ts: * plugins: diff --git a/packages/presets/gql-tag-operations/src/index.ts b/packages/presets/gql-tag-operations/src/index.ts index 61bbc54457b..dd16e3dedff 100644 --- a/packages/presets/gql-tag-operations/src/index.ts +++ b/packages/presets/gql-tag-operations/src/index.ts @@ -28,7 +28,7 @@ export type GqlTagConfig = { * E.g. `graphql-tag` or `@urql/core`. * * @exampleMarkdown - * ```yaml + * ```yaml {5} * generates: * gql/: * preset: gql-tag-operations-preset @@ -50,7 +50,7 @@ export type GqlTagConfig = { * * When using the `augmentedModuleName` option, the unmask function will by default NOT be imported from the same module. It will still be generated to a `index.ts` file. You can, however, specify to resolve the unmasking function from an an augmented module by using the `augmentedModuleName` object sub-config. * @exampleMarkdown - * ```yaml + * ```yaml {6-7} * generates: * gql/: * preset: gql-tag-operations-preset diff --git a/packages/presets/import-types/src/index.ts b/packages/presets/import-types/src/index.ts index 9ce2030f24d..de759652977 100644 --- a/packages/presets/import-types/src/index.ts +++ b/packages/presets/import-types/src/index.ts @@ -8,7 +8,7 @@ export type ImportTypesConfig = { * The key of the output is used a the base path for this file. * * @exampleMarkdown - * ```yaml + * ```yaml {5} * generates: * path/to/file.ts: * preset: import-types @@ -24,7 +24,7 @@ export type ImportTypesConfig = { * @default Types * * @exampleMarkdown - * ```yaml + * ```yaml {6} * generates: * src/: * preset: import-types diff --git a/packages/presets/near-operation-file/src/index.ts b/packages/presets/near-operation-file/src/index.ts index 2b66a9cf779..1661918afab 100644 --- a/packages/presets/near-operation-file/src/index.ts +++ b/packages/presets/near-operation-file/src/index.ts @@ -28,7 +28,7 @@ export type NearOperationFileConfig = { * If you wish to use an NPM package or a local workspace package, make sure to prefix the package name with `~`. * * @exampleMarkdown - * ```yaml + * ```yaml {5} * generates: * src/: * preset: near-operation-file @@ -45,7 +45,7 @@ export type NearOperationFileConfig = { * If you wish to use an NPM package or a local workspace package, make sure to prefix the package name with `~`. * * @exampleMarkdown - * ```yaml + * ```yaml {6} * generates: * src/: * preset: near-operation-file @@ -62,7 +62,7 @@ export type NearOperationFileConfig = { * @default .generated.ts * * @exampleMarkdown - * ```yaml + * ```yaml {6} * generates: * src/: * preset: near-operation-file @@ -80,7 +80,7 @@ export type NearOperationFileConfig = { * @default process.cwd() * * @exampleMarkdown - * ```yaml + * ```yaml {6} * generates: * src/: * preset: near-operation-file @@ -97,7 +97,7 @@ export type NearOperationFileConfig = { * @default '' * * @exampleMarkdown - * ```yaml + * ```yaml {6} * generates: * src/: * preset: near-operation-file @@ -114,7 +114,7 @@ export type NearOperationFileConfig = { * @default Types * * @exampleMarkdown - * ```yaml + * ```yaml {6} * generates: * src/: * preset: near-operation-file diff --git a/patches/nextra+2.0.0-alpha.56.patch b/patches/nextra+2.0.0-alpha.56.patch new file mode 100644 index 00000000000..d986bed578c --- /dev/null +++ b/patches/nextra+2.0.0-alpha.56.patch @@ -0,0 +1,1156 @@ +diff --git a/node_modules/nextra/context.js b/node_modules/nextra/context.js +deleted file mode 100644 +index 77e9dd1..0000000 +--- a/node_modules/nextra/context.js ++++ /dev/null +@@ -1 +0,0 @@ +-module.exports = require('./dist/context') +diff --git a/node_modules/nextra/data.js b/node_modules/nextra/data.js +deleted file mode 100755 +index 9016f08..0000000 +--- a/node_modules/nextra/data.js ++++ /dev/null +@@ -1 +0,0 @@ +-module.exports = require('./dist/ssg') +diff --git a/node_modules/nextra/dist/compile.mjs b/node_modules/nextra/dist/compile.mjs +new file mode 100644 +index 0000000..7fe44de +--- /dev/null ++++ b/node_modules/nextra/dist/compile.mjs +@@ -0,0 +1,555 @@ ++var __defProp = Object.defineProperty; ++var __defProps = Object.defineProperties; ++var __getOwnPropDescs = Object.getOwnPropertyDescriptors; ++var __getOwnPropSymbols = Object.getOwnPropertySymbols; ++var __hasOwnProp = Object.prototype.hasOwnProperty; ++var __propIsEnum = Object.prototype.propertyIsEnumerable; ++var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; ++var __spreadValues = (a, b) => { ++ for (var prop in b || (b = {})) ++ if (__hasOwnProp.call(b, prop)) ++ __defNormalProp(a, prop, b[prop]); ++ if (__getOwnPropSymbols) ++ for (var prop of __getOwnPropSymbols(b)) { ++ if (__propIsEnum.call(b, prop)) ++ __defNormalProp(a, prop, b[prop]); ++ } ++ return a; ++}; ++var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); ++var __async = (__this, __arguments, generator) => { ++ return new Promise((resolve, reject) => { ++ var fulfilled = (value) => { ++ try { ++ step(generator.next(value)); ++ } catch (e) { ++ reject(e); ++ } ++ }; ++ var rejected = (value) => { ++ try { ++ step(generator.throw(value)); ++ } catch (e) { ++ reject(e); ++ } ++ }; ++ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); ++ step((generator = generator.apply(__this, __arguments)).next()); ++ }); ++}; ++ ++// src/compile.ts ++import { createProcessor } from "@mdx-js/mdx"; ++import remarkGfm from "remark-gfm"; ++import rehypePrettyCode from "rehype-pretty-code"; ++import { rehypeMdxTitle } from "rehype-mdx-title"; ++ ++// src/mdx-plugins/static-image.js ++var relative = /^\.{1,2}\//; ++function visit(node, type2, handler) { ++ if (node.type === type2) { ++ handler(node); ++ } ++ if (node.children) { ++ node.children.forEach((n) => visit(n, type2, handler)); ++ } ++} ++function ASTNodeImport(name2, from) { ++ return { ++ type: "mdxjsEsm", ++ value: `import ${name2} from "${from}"`, ++ data: { ++ estree: { ++ type: "Program", ++ body: [ ++ { ++ type: "ImportDeclaration", ++ specifiers: [ ++ { ++ type: "ImportDefaultSpecifier", ++ local: { type: "Identifier", name: name2 } ++ } ++ ], ++ source: { ++ type: "Literal", ++ value: from, ++ raw: `"${from}"` ++ } ++ } ++ ], ++ sourceType: "module" ++ } ++ } ++ }; ++} ++function remarkStaticImage() { ++ return (tree, _file, done) => { ++ const importsToInject = []; ++ visit(tree, "image", visitor); ++ tree.children.unshift(...importsToInject); ++ tree.children.unshift(ASTNodeImport("$NextImageNextra", "next/image")); ++ done(); ++ function visitor(node) { ++ const url = node.url; ++ if (url && relative.test(url)) { ++ const tempVariableName = `$nextraImage${importsToInject.length}`; ++ Object.assign(node, { ++ type: "mdxJsxFlowElement", ++ name: "$NextImageNextra", ++ attributes: [ ++ { ++ type: "mdxJsxAttribute", ++ name: "alt", ++ value: node.alt || "" ++ }, ++ { ++ type: "mdxJsxAttribute", ++ name: "placeholder", ++ value: "blur" ++ }, ++ { ++ type: "mdxJsxAttribute", ++ name: "src", ++ value: { ++ type: "mdxJsxAttributeValueExpression", ++ value: tempVariableName, ++ data: { ++ estree: { ++ type: "Program", ++ body: [ ++ { ++ type: "ExpressionStatement", ++ expression: { ++ type: "Identifier", ++ name: tempVariableName ++ } ++ } ++ ], ++ sourceType: "module" ++ } ++ } ++ } ++ } ++ ], ++ children: [] ++ }); ++ importsToInject.push(ASTNodeImport(tempVariableName, url)); ++ } ++ } ++ }; ++} ++ ++// src/mdx-plugins/remark.ts ++function visit2(node, tester, handler) { ++ if (tester(node)) { ++ handler(node); ++ } ++ if (node.children) { ++ node.children.forEach((n) => visit2(n, tester, handler)); ++ } ++} ++function getFlattenedValue(node) { ++ return node.children.map((child) => "children" in child ? getFlattenedValue(child) : "value" in child ? child.value : "").join(""); ++} ++function remarkHeadings() { ++ const data = this.data(); ++ return (tree, _file, done) => { ++ visit2(tree, (node) => { ++ return node.type === "heading" || node.name === "summary" || node.name === "details"; ++ }, (node) => { ++ if (node.type === "heading") { ++ const heading = __spreadProps(__spreadValues({}, node), { ++ value: getFlattenedValue(node) ++ }); ++ data.headingMeta.headings.push(heading); ++ } else if (node.name === "summary" || node.name === "details") { ++ if (node.data) { ++ delete node.data._mdxExplicitJsx; ++ } ++ } ++ }); ++ done(); ++ }; ++} ++ ++// src/mdx-plugins/structurize.js ++import Slugger from "github-slugger"; ++function cleanup(content) { ++ return content.trim().split("\n").map((line) => line.trim()).join("\n"); ++} ++var structurize_default = (structurizedData, options) => { ++ if (typeof options === "boolean") ++ options = {}; ++ options = Object.assign({ codeblocks: true }, options); ++ const slugger = new Slugger(); ++ let activeSlug = ""; ++ let skip = false; ++ let content = ""; ++ return function stripMarkdown() { ++ return (node) => { ++ walk(node); ++ structurizedData[activeSlug] = cleanup(content); ++ return node; ++ }; ++ function walk(node) { ++ let result = ""; ++ const type2 = node.type; ++ if (type2 === "heading") ++ skip = true; ++ if (["code", "table", "blockquote", "list", "mdxJsxFlowElement"].includes(type2)) { ++ result += "\n"; ++ if (!skip) ++ content += "\n"; ++ } ++ if ("children" in node) { ++ for (let i = 0; i < node.children.length; i++) { ++ result += walk(node.children[i]); ++ } ++ } else if ([ ++ options.codeblocks ? "code" : "", ++ "text", ++ "inlineCode", ++ "tableCell" ++ ].includes(type2)) { ++ result += node.value; ++ if (!skip) ++ content += node.value; ++ } ++ if ([ ++ "code", ++ "table", ++ "blockquote", ++ "list", ++ "listItem", ++ "break", ++ "mdxJsxFlowElement" ++ ].includes(type2)) { ++ result += "\n"; ++ if (!skip) ++ content += "\n"; ++ } ++ if (["tableCell"].includes(type2)) { ++ result += " "; ++ if (!skip) ++ content += " "; ++ } ++ if (type2 === "heading") ++ skip = false; ++ if (type2 === "heading" && node.depth > 1) { ++ structurizedData[activeSlug] = cleanup(content); ++ content = ""; ++ activeSlug = slugger.slug(result) + "#" + result; ++ } ++ return result; ++ } ++ }; ++}; ++ ++// src/mdx-plugins/rehype-handler.js ++import Slugger2 from "github-slugger"; ++function visit3(node, tagNames, handler) { ++ if (tagNames.includes(node.tagName)) { ++ handler(node); ++ return; ++ } ++ if (node.children) { ++ node.children.forEach((n) => visit3(n, tagNames, handler)); ++ } ++} ++function parseMeta() { ++ return (tree) => { ++ visit3(tree, ["pre"], (node) => { ++ var _a, _b, _c; ++ if (Array.isArray(node.children) && node.children.length === 1 && node.children[0].tagName === "code" && typeof node.children[0].properties === "object") { ++ const meta = (_b = (_a = node.children[0].data) == null ? void 0 : _a.meta) != null ? _b : node.children[0].properties.metastring; ++ if (meta) { ++ const filename = (_c = meta.match(/filename="([^"]+)"/)) == null ? void 0 : _c[1]; ++ if (filename) { ++ node.__nextra_filename__ = filename; ++ } ++ } ++ } ++ }); ++ }; ++} ++function attachMeta() { ++ return (tree) => { ++ const slugger = new Slugger2(); ++ visit3(tree, ["div", "h2", "h3", "h4", "h5", "h6"], (node) => { ++ if (node.tagName === "div") { ++ if (!("data-rehype-pretty-code-fragment" in node.properties)) ++ return; ++ node.properties["data-nextra-code"] = ""; ++ if ("__nextra_filename__" in node) { ++ node.properties["data-filename"] = node.__nextra_filename__; ++ } ++ } else { ++ node.properties.id = node.properties.id || slugger.slug(getFlattenedValue(node)); ++ } ++ }); ++ }; ++} ++ ++// src/theme.json ++var name = "css-variables"; ++var type = "light"; ++var colors = { ++ "editor.foreground": "#000001", ++ "editor.background": "#000002" ++}; ++var tokenColors = [ ++ { ++ settings: { ++ foreground: "#000001" ++ } ++ }, ++ { ++ scope: [ ++ "markup.deleted", ++ "meta.diff.header.from-file", ++ "punctuation.definition.deleted" ++ ], ++ settings: { ++ foreground: "#ef6270" ++ } ++ }, ++ { ++ scope: [ ++ "markup.inserted", ++ "meta.diff.header.to-file", ++ "punctuation.definition.inserted" ++ ], ++ settings: { ++ foreground: "#4bb74a" ++ } ++ }, ++ { ++ scope: [ ++ "keyword.operator.accessor", ++ "meta.group.braces.round.function.arguments", ++ "meta.template.expression", ++ "markup.fenced_code meta.embedded.block" ++ ], ++ settings: { ++ foreground: "#000001" ++ } ++ }, ++ { ++ scope: "emphasis", ++ settings: { ++ fontStyle: "italic" ++ } ++ }, ++ { ++ scope: ["strong", "markup.heading.markdown", "markup.bold.markdown"], ++ settings: { ++ fontStyle: "bold" ++ } ++ }, ++ { ++ scope: ["markup.italic.markdown"], ++ settings: { ++ fontStyle: "italic" ++ } ++ }, ++ { ++ scope: "meta.link.inline.markdown", ++ settings: { ++ fontStyle: "underline", ++ foreground: "#000004" ++ } ++ }, ++ { ++ scope: ["string", "markup.fenced_code", "markup.inline"], ++ settings: { ++ foreground: "#000005" ++ } ++ }, ++ { ++ scope: ["comment", "string.quoted.docstring.multi"], ++ settings: { ++ foreground: "#000006" ++ } ++ }, ++ { ++ scope: [ ++ "constant.numeric", ++ "constant.language", ++ "constant.other.placeholder", ++ "constant.character.format.placeholder", ++ "variable.language.this", ++ "variable.other.object", ++ "variable.other.class", ++ "variable.other.constant", ++ "meta.property-name", ++ "meta.property-value", ++ "support" ++ ], ++ settings: { ++ foreground: "#000004" ++ } ++ }, ++ { ++ scope: [ ++ "keyword", ++ "storage.modifier", ++ "storage.type", ++ "storage.control.clojure", ++ "entity.name.function.clojure", ++ "entity.name.tag.yaml", ++ "support.function.node", ++ "support.type.property-name.json", ++ "punctuation.separator.key-value", ++ "punctuation.definition.template-expression" ++ ], ++ settings: { ++ foreground: "#000007" ++ } ++ }, ++ { ++ scope: "variable.parameter.function", ++ settings: { ++ foreground: "#000008" ++ } ++ }, ++ { ++ scope: [ ++ "support.function", ++ "entity.name.type", ++ "entity.other.inherited-class", ++ "meta.function-call", ++ "meta.instance.constructor", ++ "entity.other.attribute-name", ++ "entity.name.function", ++ "constant.keyword.clojure" ++ ], ++ settings: { ++ foreground: "#000009" ++ } ++ }, ++ { ++ scope: [ ++ "entity.name.tag", ++ "string.quoted", ++ "string.regexp", ++ "string.interpolated", ++ "string.template", ++ "string.unquoted.plain.out.yaml", ++ "keyword.other.template" ++ ], ++ settings: { ++ foreground: "#000010" ++ } ++ }, ++ { ++ scope: [ ++ "punctuation.definition.arguments", ++ "punctuation.definition.dict", ++ "punctuation.separator", ++ "meta.function-call.arguments" ++ ], ++ settings: { ++ foreground: "#000011" ++ } ++ }, ++ { ++ name: "[Custom] Markdown links", ++ scope: [ ++ "markup.underline.link", ++ "punctuation.definition.metadata.markdown" ++ ], ++ settings: { ++ foreground: "#000012" ++ } ++ }, ++ { ++ name: "[Custom] Markdown list", ++ scope: ["beginning.punctuation.definition.list.markdown"], ++ settings: { ++ foreground: "#000005" ++ } ++ }, ++ { ++ name: "[Custom] Markdown punctuation definition brackets", ++ scope: [ ++ "punctuation.definition.string.begin.markdown", ++ "punctuation.definition.string.end.markdown", ++ "string.other.link.title.markdown", ++ "string.other.link.description.markdown" ++ ], ++ settings: { ++ foreground: "#000007" ++ } ++ } ++]; ++var theme_default = { ++ name, ++ type, ++ colors, ++ tokenColors ++}; ++ ++// src/compile.ts ++var createCompiler = (mdxOptions) => { ++ const compiler = createProcessor(mdxOptions); ++ compiler.data("headingMeta", { ++ headings: [] ++ }); ++ return compiler; ++}; ++var rehypePrettyCodeOptions = { ++ theme: theme_default, ++ onVisitLine(node) { ++ if (node.children.length === 0) { ++ node.children = [{ type: "text", value: " " }]; ++ } ++ }, ++ onVisitHighlightedLine(node) { ++ node.properties.className.push("highlighted"); ++ }, ++ onVisitHighlightedWord(node) { ++ node.properties.className = ["highlighted"]; ++ } ++}; ++function compileMdx(_0) { ++ return __async(this, arguments, function* (source, mdxOptions = {}, nextraOptions = {}, resourcePath = "") { ++ var _a; ++ const structurizedData = {}; ++ const compiler = createCompiler({ ++ jsx: (_a = mdxOptions.jsx) != null ? _a : true, ++ outputFormat: mdxOptions.outputFormat, ++ providerImportSource: "@mdx-js/react", ++ remarkPlugins: [ ++ ...mdxOptions.remarkPlugins || [], ++ remarkGfm, ++ remarkHeadings, ++ ...nextraOptions.unstable_staticImage ? [remarkStaticImage] : [], ++ ...nextraOptions.unstable_flexsearch ? [structurize_default(structurizedData, nextraOptions.unstable_flexsearch)] : [] ++ ].filter(Boolean), ++ rehypePlugins: [ ++ ...mdxOptions.rehypePlugins || [], ++ parseMeta, ++ [rehypePrettyCode, rehypePrettyCodeOptions], ++ [rehypeMdxTitle, { name: "titleText" }], ++ attachMeta ++ ].filter(Boolean) ++ }); ++ try { ++ const result = yield compiler.process(source); ++ return __spreadProps(__spreadValues({ ++ result: String(result) ++ }, compiler.data("headingMeta")), { ++ structurizedData ++ }); ++ } catch (err) { ++ console.error(` ++Error compiling ${resourcePath} ++${err} ++`); ++ throw err; ++ } ++ }); ++} ++export { ++ compileMdx ++}; +diff --git a/node_modules/nextra/dist/content-dump.d.ts b/node_modules/nextra/dist/content-dump.d.ts +old mode 100644 +new mode 100755 +index 44028fa..77e6504 +--- a/node_modules/nextra/dist/content-dump.d.ts ++++ b/node_modules/nextra/dist/content-dump.d.ts +@@ -4,5 +4,5 @@ export declare function addPage({ fileLocale, route, title, data, structurizedDa + title: string; + data: any; + structurizedData: any; +-}): Promise; ++}): void; + export declare function restoreCache(): Promise; +diff --git a/node_modules/nextra/dist/context.js b/node_modules/nextra/dist/context.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/nextra/dist/filter-route-locale.d.ts b/node_modules/nextra/dist/filter-route-locale.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/nextra/dist/index.js b/node_modules/nextra/dist/index.js +old mode 100644 +new mode 100755 +index d288128..895c186 +--- a/node_modules/nextra/dist/index.js ++++ b/node_modules/nextra/dist/index.js +@@ -65,27 +65,25 @@ function getLocaleFromFilename(name) { + const match = name.match(localeRegex); + if (match) + return match[1]; +- return void 0; + } + function removeExtension(name) { + const match = name.match(/^([^.]+)/); + return match !== null ? match[1] : ""; + } + var parseJsonFile = (content, path4) => { +- let parsed = {}; + try { +- parsed = JSON.parse(content); ++ return JSON.parse(content); + } catch (err) { + console.error(`Error parsing ${path4}, make sure it's a valid JSON + ` + err); ++ return {}; + } +- return parsed; + }; +-var existsSync = (f) => { ++var existsSync = (filePath) => { + try { +- import_fs.default.accessSync(f, import_fs.default.constants.F_OK); ++ import_fs.default.accessSync(filePath, import_fs.default.constants.F_OK); + return true; +- } catch (_) { ++ } catch (e) { + return false; + } + }; +@@ -115,14 +113,14 @@ var cacheDir = import_path2.default.join(process.cwd(), ".next", "cache"); + var assetDir = import_path2.default.join(process.cwd(), ".next", "static", "chunks"); + try { + statSync(assetDir); +-} catch (err) { ++} catch (e) { + mkdirSync(assetDir, { recursive: true }); + } + var cacheDirExist = false; + try { + statSync(cacheDir); + cacheDirExist = true; +-} catch (err) { ++} catch (e) { + mkdirSync(cacheDir, { recursive: true }); + } + function restoreCache() { +@@ -130,7 +128,7 @@ function restoreCache() { + if (cacheDirExist) { + try { + statSync(assetDir); +- } catch (err) { ++ } catch (e) { + mkdirSync(assetDir, { recursive: true }); + } + const files = import_graceful_fs.default.readdirSync(cacheDir); +@@ -216,12 +214,13 @@ var PageMapCache = class { + }; + var pageMapCache = new PageMapCache(); + var NextraPlugin = class { +- constructor(nextraConfig) { +- this.config = nextraConfig; ++ constructor(config) { ++ this.config = config; + } + apply(compiler) { + compiler.hooks.beforeCompile.tapAsync("NextraPlugin", (_, callback) => __async(this, null, function* () { +- if (this.config && this.config.unstable_flexsearch) { ++ var _a; ++ if ((_a = this.config) == null ? void 0 : _a.unstable_flexsearch) { + restoreCache(); + } + const result = yield collectFiles(import_path3.default.join(process.cwd(), findPagesDir()), "/"); +@@ -251,6 +250,7 @@ module.exports = (...args) => (nextConfig = {}) => { + return Object.assign({}, nextConfig, { + pageExtensions, + webpack(config, options) { ++ var _a2, _b2; + const nextra = new NextraPlugin(nextraConfig); + if (!config.plugins) { + config.plugins = [nextra]; +@@ -263,7 +263,12 @@ module.exports = (...args) => (nextConfig = {}) => { + options.defaultLoaders.babel, + { + loader: "nextra/loader", +- options: __spreadProps(__spreadValues({}, nextraConfig), { locales, defaultLocale, pageMapCache }) ++ options: __spreadProps(__spreadValues({}, nextraConfig), { ++ locales, ++ defaultLocale, ++ pageMapCache, ++ newNextLinkBehavior: (_b2 = (_a2 = nextConfig.experimental) == null ? void 0 : _a2.newNextLinkBehavior) != null ? _b2 : false ++ }) + } + ] + }); +diff --git a/node_modules/nextra/dist/loader.mjs b/node_modules/nextra/dist/loader.mjs +index 486c1fb..1eabd7b 100644 +--- a/node_modules/nextra/dist/loader.mjs ++++ b/node_modules/nextra/dist/loader.mjs +@@ -54,14 +54,14 @@ var asset = {}; + var cached = /* @__PURE__ */ new Map(); + try { + statSync(assetDir); +-} catch (err) { ++} catch (e) { + mkdirSync(assetDir, { recursive: true }); + } + var cacheDirExist = false; + try { + statSync(cacheDir); + cacheDirExist = true; +-} catch (err) { ++} catch (e) { + mkdirSync(cacheDir, { recursive: true }); + } + function initFromCache(filename) { +@@ -76,26 +76,22 @@ function initFromCache(filename) { + } + return {}; + } +-function addPage(_0) { +- return __async(this, arguments, function* ({ +- fileLocale, +- route, +- title, +- data, +- structurizedData +- }) { +- const dataFilename = `nextra-data-${fileLocale}.json`; +- if (!asset[fileLocale]) { +- asset[fileLocale] = initFromCache(dataFilename); +- } +- asset[fileLocale][route] = { +- title: title || data.title, +- data: structurizedData +- }; +- const content = JSON.stringify(asset[fileLocale]); +- fs.writeFileSync(path.join(assetDir, dataFilename), content); +- fs.writeFileSync(path.join(cacheDir, dataFilename), content); +- }); ++function addPage({ ++ fileLocale, ++ route, ++ title, ++ data, ++ structurizedData ++}) { ++ const dataFilename = `nextra-data-${fileLocale}.json`; ++ asset[fileLocale] || (asset[fileLocale] = initFromCache(dataFilename)); ++ asset[fileLocale][route] = { ++ title: title || data.title, ++ data: structurizedData ++ }; ++ const content = JSON.stringify(asset[fileLocale]); ++ fs.writeFileSync(path.join(assetDir, dataFilename), content); ++ fs.writeFileSync(path.join(cacheDir, dataFilename), content); + } + + // src/utils.ts +@@ -105,27 +101,25 @@ function getLocaleFromFilename(name2) { + const match = name2.match(localeRegex); + if (match) + return match[1]; +- return void 0; + } + function removeExtension(name2) { + const match = name2.match(/^([^.]+)/); + return match !== null ? match[1] : ""; + } + var parseJsonFile = (content, path5) => { +- let parsed = {}; + try { +- parsed = JSON.parse(content); ++ return JSON.parse(content); + } catch (err) { + console.error(`Error parsing ${path5}, make sure it's a valid JSON + ` + err); ++ return {}; + } +- return parsed; + }; +-var existsSync = (f) => { ++var existsSync = (filePath) => { + try { +- fs2.accessSync(f, fs2.constants.F_OK); ++ fs2.accessSync(filePath, fs2.constants.F_OK); + return true; +- } catch (_) { ++ } catch (e) { + return false; + } + }; +@@ -134,6 +128,7 @@ var existsSync = (f) => { + import { createProcessor } from "@mdx-js/mdx"; + import remarkGfm from "remark-gfm"; + import rehypePrettyCode from "rehype-pretty-code"; ++import { rehypeMdxTitle } from "rehype-mdx-title"; + + // src/mdx-plugins/static-image.js + var relative = /^\.{1,2}\//; +@@ -252,17 +247,7 @@ function remarkHeadings() { + const heading = __spreadProps(__spreadValues({}, node), { + value: getFlattenedValue(node) + }); +- const headingMeta = data.headingMeta; +- if (node.depth === 1) { +- headingMeta.hasH1 = true; +- if (Array.isArray(node.children) && node.children.length === 1) { +- const child = node.children[0]; +- if (child.type === "text") { +- headingMeta.titleText = child.value; +- } +- } +- } +- headingMeta.headings.push(heading); ++ data.headingMeta.headings.push(heading); + } else if (node.name === "summary" || node.name === "details") { + if (node.data) { + delete node.data._mdxExplicitJsx; +@@ -594,34 +579,31 @@ var theme_default = { + var createCompiler = (mdxOptions) => { + const compiler = createProcessor(mdxOptions); + compiler.data("headingMeta", { +- hasH1: false, + headings: [] + }); + return compiler; + }; + var rehypePrettyCodeOptions = { + theme: theme_default, +- onVisitHighlightedLine(node) { +- if (!node.properties.className) { +- node.properties.className = []; ++ onVisitLine(node) { ++ if (node.children.length === 0) { ++ node.children = [{ type: "text", value: " " }]; + } ++ }, ++ onVisitHighlightedLine(node) { + node.properties.className.push("highlighted"); + }, + onVisitHighlightedWord(node) { +- if (!node.properties.className) { +- node.properties.className = []; +- } +- node.properties.className.push("highlighted"); ++ node.properties.className = ["highlighted"]; + } + }; + function compileMdx(_0) { +- return __async(this, arguments, function* (source, mdxOptions = {}, nextraOptions = { +- unstable_staticImage: false, +- unstable_flexsearch: false +- }, resourcePath) { +- let structurizedData = {}; ++ return __async(this, arguments, function* (source, mdxOptions = {}, nextraOptions = {}, resourcePath = "") { ++ var _a; ++ const structurizedData = {}; + const compiler = createCompiler({ +- jsx: true, ++ jsx: (_a = mdxOptions.jsx) != null ? _a : true, ++ outputFormat: mdxOptions.outputFormat, + providerImportSource: "@mdx-js/react", + remarkPlugins: [ + ...mdxOptions.remarkPlugins || [], +@@ -634,6 +616,7 @@ function compileMdx(_0) { + ...mdxOptions.rehypePlugins || [], + parseMeta, + [rehypePrettyCode, rehypePrettyCodeOptions], ++ [rehypeMdxTitle, { name: "titleText" }], + attachMeta + ].filter(Boolean) + }); +@@ -646,8 +629,8 @@ function compileMdx(_0) { + }); + } catch (err) { + console.error(` +-Error compiling ${resourcePath}`); +- console.error(`${err} ++Error compiling ${resourcePath} ++${err} + `); + throw err; + } +@@ -827,16 +810,7 @@ function loader(context, source) { + if (!theme) { + throw new Error("No Nextra theme found!"); + } +- let pageMapResult, fileMap; +- if (isProductionBuild) { +- const data2 = pageMapCache2.get(); +- pageMapResult = data2.items; +- fileMap = data2.fileMap; +- } else { +- const data2 = yield collectFiles(pagesDir, "/"); +- pageMapResult = data2.items; +- fileMap = data2.fileMap; +- } ++ const { items: pageMapResult, fileMap } = isProductionBuild ? pageMapCache2.get() : yield collectFiles(pagesDir, "/"); + const [pageMap, route, title] = getPageMap(resourcePath, pageMapResult, fileMap, defaultLocale); + if (!isProductionBuild) { + context.addContextDependency(pagesDir); +@@ -847,7 +821,7 @@ function loader(context, source) { + } + }); + } +- let { data, content } = grayMatter2(source); ++ const { data, content } = grayMatter2(source); + let layout = theme; + let layoutConfig = themeConfig || null; + if (theme.startsWith(".") || theme.startsWith("/")) { +@@ -859,15 +833,13 @@ function loader(context, source) { + if (isProductionBuild && indexContentEmitted.has(filename)) { + unstable_flexsearch = false; + } +- const { result, titleText, headings, hasH1, structurizedData } = yield compileMdx(content, mdxOptions, { ++ const { result, headings, structurizedData } = yield compileMdx(content, mdxOptions, { + unstable_staticImage, + unstable_flexsearch + }, resourcePath); +- content = result; +- content = content.replace("export default MDXContent;", ""); + if (unstable_flexsearch) { + if (extension2.test(filename) && data.searchable !== false) { +- yield addPage({ ++ addPage({ + fileLocale: fileLocale || "default", + route, + title, +@@ -893,34 +865,45 @@ function loader(context, source) { + } catch (e) { + } + } +- const prefix = `import __nextra_withLayout__ from '${layout}' ++ const loaderOptions = JSON.stringify({ ++ newNextLinkBehavior: options.newNextLinkBehavior ++ }); ++ const layoutConfigImport = layoutConfig ? `import __nextra_layoutConfig__ from '${layoutConfig}'` : ""; ++ return ` ++import __nextra_withLayout__ from '${layout}' + import { withSSG as __nextra_withSSG__ } from 'nextra/ssg' +-${layoutConfig ? `import __nextra_layoutConfig__ from '${layoutConfig}'` : ""} ++${layoutConfigImport} ++${result.replace("export default MDXContent;", "")} + + const __nextra_pageMap__ = ${JSON.stringify(pageMap)} ++ + globalThis.__nextra_internal__ = { + pageMap: __nextra_pageMap__, +- route: ${JSON.stringify(route)}, ++ route: ${JSON.stringify(route)} + } + +- const __nextra_content__ = +- const NextraLayout = __nextra_withSSG__(__nextra_withLayout__({ +- filename: "${slash2(filename)}", +- route: "${slash2(route)}", +- meta: ${JSON.stringify(data)}, +- pageMap: __nextra_pageMap__, +- titleText: ${JSON.stringify(titleText)}, +- headings: ${JSON.stringify(headings)}, +- hasH1: ${JSON.stringify(hasH1)}, +- ${timestamp ? `timestamp: ${timestamp}, ++const NextraLayout = __nextra_withSSG__(__nextra_withLayout__({ ++ filename: "${slash2(filename)}", ++ route: "${slash2(route)}", ++ meta: ${JSON.stringify(data)}, ++ pageMap: __nextra_pageMap__, ++ titleText: typeof titleText === 'string' ? titleText : undefined, ++ headings: ${JSON.stringify(headings)}, ++ ${timestamp ? `timestamp: ${timestamp}, + ` : ""} +- }, ${layoutConfig ? "__nextra_layoutConfig__" : "null"})) +- `; +- const suffix = `export default function NextraPage (props) { +- return {__nextra_content__} ++}, ${layoutConfig ? `{...__nextra_layoutConfig__,...${loaderOptions}}` : loaderOptions})) ++ ++function NextraPage(props) { ++ return ( ++ ++ ++ ++ ) + } +-NextraPage.getLayout = NextraLayout.getLayout`; +- return prefix + "\n\n" + content + "\n\n" + suffix; ++NextraPage.getLayout = NextraLayout.getLayout ++ ++export default NextraPage ++`.trimStart(); + }); + } + function syncLoader(source, callback) { +diff --git a/node_modules/nextra/dist/locales.js b/node_modules/nextra/dist/locales.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/nextra/dist/page-map.d.ts b/node_modules/nextra/dist/page-map.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/nextra/dist/plugin.d.ts b/node_modules/nextra/dist/plugin.d.ts +old mode 100644 +new mode 100755 +index ae1d17f..f7732e7 +--- a/node_modules/nextra/dist/plugin.d.ts ++++ b/node_modules/nextra/dist/plugin.d.ts +@@ -1,4 +1,4 @@ +-import { PageMapItem } from './types'; ++import { NextraConfig, PageMapItem } from './types'; + import { Compiler } from 'webpack'; + export declare function collectFiles(dir: string, route?: string, fileMap?: Record): Promise<{ + items: PageMapItem[]; +@@ -21,9 +21,8 @@ export declare class PageMapCache { + } | null; + } + export declare const pageMapCache: PageMapCache; +-declare class NextraPlugin { +- config: any; +- constructor(nextraConfig: any); ++export declare class NextraPlugin { ++ private config; ++ constructor(config: NextraConfig); + apply(compiler: Compiler): void; + } +-export { NextraPlugin }; +diff --git a/node_modules/nextra/dist/ssg.js b/node_modules/nextra/dist/ssg.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/nextra/dist/types.d.ts b/node_modules/nextra/dist/types.d.ts +old mode 100644 +new mode 100755 +index 9a63bef..189f9bc +--- a/node_modules/nextra/dist/types.d.ts ++++ b/node_modules/nextra/dist/types.d.ts +@@ -1,15 +1,12 @@ + import { Heading as MDASTHeading } from 'mdast'; + import { ProcessorOptions } from '@mdx-js/mdx'; + import { PageMapCache } from './plugin'; +-export interface LoaderOptions { +- theme: Theme; +- themeConfig: string; ++export interface LoaderOptions extends NextraConfig { + locales: string[]; + defaultLocale: string; +- unstable_staticImage: boolean; +- unstable_flexsearch: boolean; + mdxOptions: Pick; + pageMapCache: PageMapCache; ++ newNextLinkBehavior: boolean; + } + export interface PageMapItem { + name: string; +@@ -31,7 +28,6 @@ export interface PageOpt { + pageMap: PageMapItem[]; + titleText: string | null; + headings?: Heading[]; +- hasH1: boolean; + } + export declare type PageMapResult = [ + pageMap: PageMapItem[], +diff --git a/node_modules/nextra/dist/utils.d.ts b/node_modules/nextra/dist/utils.d.ts +old mode 100644 +new mode 100755 +index adf3d93..6ab4e73 +--- a/node_modules/nextra/dist/utils.d.ts ++++ b/node_modules/nextra/dist/utils.d.ts +@@ -1,5 +1,5 @@ +-export declare function getLocaleFromFilename(name: string): string | undefined; ++export declare function getLocaleFromFilename(name: string): string | void; + export declare function removeExtension(name: string): string; + export declare function getFileName(resourcePath: string): string; + export declare const parseJsonFile: (content: string, path: string) => Record; +-export declare const existsSync: (f: string) => boolean; ++export declare const existsSync: (filePath: string) => boolean; +diff --git a/node_modules/nextra/index.js b/node_modules/nextra/index.js +deleted file mode 100755 +index aae5903..0000000 +--- a/node_modules/nextra/index.js ++++ /dev/null +@@ -1 +0,0 @@ +-module.exports = require('./dist/index') +diff --git a/node_modules/nextra/loader.js b/node_modules/nextra/loader.js +index b7d9ded..5283c07 100755 +--- a/node_modules/nextra/loader.js ++++ b/node_modules/nextra/loader.js +@@ -10,7 +10,7 @@ + module.exports = function (code) { + const callback = this.async() + // Note that `import()` caches, so this should be fast enough. +- import('./dist/loader.mjs').then(module => +- module.default.call(this, code, callback) ++ import('./dist/loader.mjs').then(mod => ++ mod.default.call(this, code, callback) + ) + } +diff --git a/node_modules/nextra/locales.js b/node_modules/nextra/locales.js +deleted file mode 100644 +index 0adc2a7..0000000 +--- a/node_modules/nextra/locales.js ++++ /dev/null +@@ -1 +0,0 @@ +-module.exports = require('./dist/locales') +diff --git a/node_modules/nextra/package.json b/node_modules/nextra/package.json +index 47e2096..c7e64f1 100644 +--- a/node_modules/nextra/package.json ++++ b/node_modules/nextra/package.json +@@ -5,19 +5,23 @@ + "main": "index.js", + "files": [ + "dist/*", +- "index.js", +- "ssg.js", +- "data.js", +- "loader.js", +- "locales.js", +- "context.js" ++ "loader.js" + ], ++ "exports": { ++ ".": "./dist/index.js", ++ "./compile": "./dist/compile.mjs", ++ "./context": "./dist/context.js", ++ "./data": "./dist/ssg.js", ++ "./loader": "./loader.js", ++ "./locales": "./dist/locales.js", ++ "./ssg": "./dist/ssg.js" ++ }, + "types": "./dist/types.d.ts", + "repository": "https://github.com/shuding/nextra", + "license": "MIT", + "scripts": { + "build": "node scripts/build.js", +- "dev": "node scripts/dev.js", ++ "dev": "node scripts/build.js --dev", + "types": "tsc --project tsconfig.type.json", + "test": "vitest run", + "prepublishOnly": "rm -rf dist && pnpm build && pnpm types" +@@ -28,7 +32,7 @@ + "github-slugger": "^1.4.0", + "graceful-fs": "^4.2.6", + "gray-matter": "^4.0.3", +- "p-limit": "^4.0.0", ++ "rehype-mdx-title": "^1.0.0", + "rehype-pretty-code": "^0.1.0", + "remark-gfm": "^3.0.1", + "shiki": "0.10.1", +diff --git a/node_modules/nextra/ssg.js b/node_modules/nextra/ssg.js +deleted file mode 100755 +index 9016f08..0000000 +--- a/node_modules/nextra/ssg.js ++++ /dev/null +@@ -1 +0,0 @@ +-module.exports = require('./dist/ssg') diff --git a/patches/nextra-theme-docs+2.0.0-alpha.59.patch b/patches/nextra-theme-docs+2.0.0-alpha.59.patch new file mode 100644 index 00000000000..46e619ca7ed --- /dev/null +++ b/patches/nextra-theme-docs+2.0.0-alpha.59.patch @@ -0,0 +1,2692 @@ +diff --git a/node_modules/nextra-theme-docs/dist/bleed.d.ts b/node_modules/nextra-theme-docs/dist/bleed.d.ts +new file mode 100755 +index 0000000..353f70d +--- /dev/null ++++ b/node_modules/nextra-theme-docs/dist/bleed.d.ts +@@ -0,0 +1,6 @@ ++import React from 'react'; ++declare type BleedProps = { ++ full: boolean; ++}; ++declare const Bleed: React.FC; ++export default Bleed; +diff --git a/node_modules/nextra-theme-docs/dist/bleed.js b/node_modules/nextra-theme-docs/dist/bleed.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/nextra-theme-docs/dist/callout.d.ts b/node_modules/nextra-theme-docs/dist/callout.d.ts +new file mode 100755 +index 0000000..dba3b3e +--- /dev/null ++++ b/node_modules/nextra-theme-docs/dist/callout.d.ts +@@ -0,0 +1,15 @@ ++import React from 'react'; ++declare const themes: { ++ default: string; ++ error: string; ++ info: string; ++ warning: string; ++}; ++declare type CalloutProps = { ++ /** Callout Theme default to 'default' */ ++ type?: keyof typeof themes; ++ /** default emoji 💡*/ ++ emoji: string; ++}; ++declare const Callout: React.FC; ++export default Callout; +diff --git a/node_modules/nextra-theme-docs/dist/callout.js b/node_modules/nextra-theme-docs/dist/callout.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/nextra-theme-docs/dist/components/tabs.js b/node_modules/nextra-theme-docs/dist/components/tabs.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/nextra-theme-docs/dist/index.js b/node_modules/nextra-theme-docs/dist/index.js +old mode 100644 +new mode 100755 +index 0f5435d..0aa53c7 +--- a/node_modules/nextra-theme-docs/dist/index.js ++++ b/node_modules/nextra-theme-docs/dist/index.js +@@ -51,7 +51,7 @@ var __async = (__this, __arguments, generator) => { + }; + + // src/index.tsx +-import React28, { useMemo as useMemo3, useState as useState7 } from "react"; ++import React32, { useMemo as useMemo3, useState as useState7 } from "react"; + import { useRouter as useRouter8 } from "next/router"; + import "focus-visible"; + import { SkipNavContent } from "@reach/skip-nav"; +@@ -77,9 +77,21 @@ var renderComponent = (ComponentOrNode, props, functionOnly) => { + }; + var render_component_default = renderComponent; + ++// src/utils/use-mounted.ts ++import { useEffect, useState } from "react"; ++var useMounted = () => { ++ const [mounted, setMounted] = useState(false); ++ useEffect(() => { ++ setMounted(true); ++ }, []); ++ return mounted; ++}; ++ + // src/config.ts + import React2 from "react"; +-var ThemeConfigContext = React2.createContext({}); ++var ThemeConfigContext = React2.createContext({ ++ newNextLinkBehavior: false ++}); + var useConfig = () => React2.useContext(ThemeConfigContext); + + // src/head.tsx +@@ -87,8 +99,7 @@ function Head({ title, locale, meta }) { + const config = useConfig(); + const { theme, systemTheme } = useTheme(); + const renderedTheme = theme === "system" ? systemTheme : theme; +- const [mounted, setMounted] = React3.useState(false); +- React3.useEffect(() => setMounted(true), []); ++ const mounted = useMounted(); + return /* @__PURE__ */ React3.createElement(NextHead, null, /* @__PURE__ */ React3.createElement("title", null, title, render_component_default(config.titleSuffix, { locale, config, title, meta })), render_component_default(config.head, { locale, config, title, meta }, true), config.unstable_faviconGlyph ? /* @__PURE__ */ React3.createElement("link", { + rel: "icon", + href: `data:image/svg+xml;utf8,${config.unstable_faviconGlyph}` +@@ -110,9 +121,44 @@ function Head({ title, locale, meta }) { + } + + // src/navbar.tsx +-import React8 from "react"; ++import React17 from "react"; + import cn3 from "classnames"; +-import Link3 from "next/link"; ++ ++// src/anchor.tsx ++import React4 from "react"; ++import NextLink from "next/link"; ++function Anchor(_a) { ++ var _b = _a, { ++ href = "", ++ children ++ } = _b, props = __objRest(_b, [ ++ "href", ++ "children" ++ ]); ++ const config = useConfig(); ++ if (!href) { ++ return /* @__PURE__ */ React4.createElement("a", __spreadValues({}, props), children); ++ } ++ const isExternal = href.startsWith("https://"); ++ if (isExternal) { ++ return /* @__PURE__ */ React4.createElement("a", __spreadValues({ ++ target: "_blank", ++ rel: "noreferrer", ++ href ++ }, props), children); ++ } ++ if (config.newNextLinkBehavior) { ++ return /* @__PURE__ */ React4.createElement(NextLink, __spreadValues({ ++ href ++ }, props), children); ++ } ++ return /* @__PURE__ */ React4.createElement(NextLink, { ++ href, ++ passHref: true ++ }, /* @__PURE__ */ React4.createElement("a", __spreadValues({}, props), children)); ++} ++ ++// src/navbar.tsx + import { useRouter as useRouter3 } from "next/router"; + + // src/utils/get-fs-route.ts +@@ -134,33 +180,30 @@ function useMenuContext() { + } + + // src/search.tsx +-import React4, { useMemo, useCallback, useRef, useState, useEffect } from "react"; ++import React5, { useMemo, useCallback, useRef, useState as useState2, useEffect as useEffect2 } from "react"; + import matchSorter from "match-sorter"; + import cn from "classnames"; + import { useRouter } from "next/router"; +-import Link from "next/link"; + var Item = ({ title, active, href, onMouseOver, search }) => { + const highlight = title.toLowerCase().indexOf(search.toLowerCase()); +- return /* @__PURE__ */ React4.createElement("li", { ++ return /* @__PURE__ */ React5.createElement("li", { + className: cn("p-2", { active }) +- }, /* @__PURE__ */ React4.createElement(Link, { ++ }, /* @__PURE__ */ React5.createElement(Anchor, { + href, +- passHref: true +- }, /* @__PURE__ */ React4.createElement("a", { + className: "block no-underline", + onMouseOver +- }, title.substring(0, highlight), /* @__PURE__ */ React4.createElement("span", { ++ }, title.substring(0, highlight), /* @__PURE__ */ React5.createElement("span", { + className: "highlight" +- }, title.substring(highlight, highlight + search.length)), title.substring(highlight + search.length)))); ++ }, title.substring(highlight, highlight + search.length)), title.substring(highlight + search.length))); + }; + var UP = true; + var DOWN = false; + var Search = ({ directories = [] }) => { + const router = useRouter(); + const config = useConfig(); +- const [show, setShow] = useState(false); +- const [search, setSearch] = useState(""); +- const [active, setActive] = useState(null); ++ const [show, setShow] = useState2(false); ++ const [search, setSearch] = useState2(""); ++ const [active, setActive] = useState2(null); + const input = useRef(null); + const results = useMemo(() => { + if (!search) +@@ -192,10 +235,10 @@ var Search = ({ directories = [] }) => { + setShow(false); + } + }, [active]); +- useEffect(() => { ++ useEffect2(() => { + setActive(null); + }, [search]); +- useEffect(() => { ++ useEffect2(() => { + const inputs = ["input", "select", "button", "textarea"]; + const down = (e) => { + var _a; +@@ -212,14 +255,14 @@ var Search = ({ directories = [] }) => { + return () => window.removeEventListener("keydown", down); + }, []); + const renderList = show && results.length > 0; +- return /* @__PURE__ */ React4.createElement("div", { ++ return /* @__PURE__ */ React5.createElement("div", { + className: "relative w-full nextra-search md:w-64" +- }, renderList && /* @__PURE__ */ React4.createElement("div", { ++ }, renderList && /* @__PURE__ */ React5.createElement("div", { + className: "z-10 search-overlay", + onClick: () => setShow(false) +- }), /* @__PURE__ */ React4.createElement("div", { ++ }), /* @__PURE__ */ React5.createElement("div", { + className: "relative flex items-center" +- }, /* @__PURE__ */ React4.createElement("input", { ++ }, /* @__PURE__ */ React5.createElement("input", { + onChange: (e) => { + setSearch(e.target.value); + setShow(true); +@@ -234,14 +277,14 @@ var Search = ({ directories = [] }) => { + onBlur: handleOnBlur, + ref: input, + spellCheck: false +- }), show ? null : /* @__PURE__ */ React4.createElement("div", { ++ }), show ? null : /* @__PURE__ */ React5.createElement("div", { + className: "hidden sm:flex absolute inset-y-0 right-0 py-1.5 pr-1.5 select-none pointer-events-none" +- }, /* @__PURE__ */ React4.createElement("kbd", { ++ }, /* @__PURE__ */ React5.createElement("kbd", { + className: "inline-flex items-center px-1.5 font-mono text-sm font-medium bg-white text-gray-400 dark:text-gray-800 dark:border-gray-400 border rounded" +- }, "/"))), renderList && /* @__PURE__ */ React4.createElement("ul", { ++ }, "/"))), renderList && /* @__PURE__ */ React5.createElement("ul", { + className: "absolute left-0 z-20 w-full p-0 py-2.5 m-0 mt-1 list-none border divide-y rounded shadow-md md:right-0 top-100 md:w-auto" + }, results.map((res, i) => { +- return /* @__PURE__ */ React4.createElement(Item, { ++ return /* @__PURE__ */ React5.createElement(Item, { + key: `search-item-${i}`, + title: res.title, + href: res.route, +@@ -254,19 +297,204 @@ var Search = ({ directories = [] }) => { + var search_default = Search; + + // src/flexsearch.js +-import React5, { ++import React16, { + memo, + useCallback as useCallback2, + useRef as useRef2, +- useState as useState2, +- useEffect as useEffect2, ++ useState as useState3, ++ useEffect as useEffect3, + Fragment + } from "react"; + import Router, { useRouter as useRouter2 } from "next/router"; + import cn2 from "classnames"; +-import Link2 from "next/link"; + import FlexSearch from "flexsearch"; + import { Transition } from "@headlessui/react"; ++ ++// src/icons/arrow-right.tsx ++import React6 from "react"; ++function ArrowRightIcon(props) { ++ return /* @__PURE__ */ React6.createElement("svg", __spreadValues({ ++ fill: "none", ++ viewBox: "0 0 24 24", ++ stroke: "currentColor" ++ }, props), /* @__PURE__ */ React6.createElement("path", { ++ strokeLinecap: "round", ++ strokeLinejoin: "round", ++ strokeWidth: "2", ++ d: "M9 5l7 7-7 7" ++ })); ++} ++ ++// src/icons/check.tsx ++import React7 from "react"; ++function CheckIcon() { ++ return /* @__PURE__ */ React7.createElement("svg", { ++ viewBox: "0 0 20 20", ++ width: "1em", ++ height: "1em", ++ fill: "currentColor" ++ }, /* @__PURE__ */ React7.createElement("path", { ++ fillRule: "evenodd", ++ d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", ++ clipRule: "evenodd" ++ })); ++} ++ ++// src/icons/discord.tsx ++import React8 from "react"; ++function DiscordIcon({ height = 40 }) { ++ return /* @__PURE__ */ React8.createElement("svg", { ++ height, ++ fill: "none", ++ xmlns: "http://www.w3.org/2000/svg", ++ viewBox: "0 0 146 146", ++ "aria-hidden": "true" ++ }, /* @__PURE__ */ React8.createElement("title", null, "Discord"), /* @__PURE__ */ React8.createElement("path", { ++ d: "M107.75 125.001s-4.5-5.375-8.25-10.125c16.375-4.625 22.625-14.875 22.625-14.875-5.125 3.375-10 5.75-14.375 7.375-6.25 2.625-12.25 4.375-18.125 5.375-12 2.25-23 1.625-32.375-.125-7.125-1.375-13.25-3.375-18.375-5.375-2.875-1.125-6-2.5-9.125-4.25-.375-.25-.75-.375-1.125-.625-.25-.125-.375-.25-.5-.375-2.25-1.25-3.5-2.125-3.5-2.125s6 10 21.875 14.75c-3.75 4.75-8.375 10.375-8.375 10.375-27.625-.875-38.125-19-38.125-19 0-40.25 18-72.875 18-72.875 18-13.5 35.125-13.125 35.125-13.125l1.25 1.5c-22.5 6.5-32.875 16.375-32.875 16.375s2.75-1.5 7.375-3.625c13.375-5.875 24-7.5 28.375-7.875.75-.125 1.375-.25 2.125-.25 7.625-1 16.25-1.25 25.25-.25 11.875 1.375 24.625 4.875 37.625 12 0 0-9.875-9.375-31.125-15.875l1.75-2S110 19.626 128 33.126c0 0 18 32.625 18 72.875 0 0-10.625 18.125-38.25 19zM49.625 66.626c-7.125 0-12.75 6.25-12.75 13.875s5.75 13.875 12.75 13.875c7.125 0 12.75-6.25 12.75-13.875.125-7.625-5.625-13.875-12.75-13.875zm45.625 0c-7.125 0-12.75 6.25-12.75 13.875s5.75 13.875 12.75 13.875c7.125 0 12.75-6.25 12.75-13.875s-5.625-13.875-12.75-13.875z", ++ fillRule: "nonzero", ++ fill: "currentColor" ++ })); ++} ++ ++// src/icons/github.tsx ++import React9 from "react"; ++function GitHubIcon({ height = 40 }) { ++ return /* @__PURE__ */ React9.createElement("svg", { ++ height, ++ viewBox: "2 2 20 20", ++ fill: "none", ++ "aria-hidden": "true" ++ }, /* @__PURE__ */ React9.createElement("path", { ++ fillRule: "evenodd", ++ clipRule: "evenodd", ++ d: "M12 3C7.0275 3 3 7.12937 3 12.2276C3 16.3109 5.57625 19.7597 9.15374 20.9824C9.60374 21.0631 9.77249 20.7863 9.77249 20.5441C9.77249 20.3249 9.76125 19.5982 9.76125 18.8254C7.5 19.2522 6.915 18.2602 6.735 17.7412C6.63375 17.4759 6.19499 16.6569 5.8125 16.4378C5.4975 16.2647 5.0475 15.838 5.80124 15.8264C6.51 15.8149 7.01625 16.4954 7.18499 16.7723C7.99499 18.1679 9.28875 17.7758 9.80625 17.5335C9.885 16.9337 10.1212 16.53 10.38 16.2993C8.3775 16.0687 6.285 15.2728 6.285 11.7432C6.285 10.7397 6.63375 9.9092 7.20749 9.26326C7.1175 9.03257 6.8025 8.08674 7.2975 6.81794C7.2975 6.81794 8.05125 6.57571 9.77249 7.76377C10.4925 7.55615 11.2575 7.45234 12.0225 7.45234C12.7875 7.45234 13.5525 7.55615 14.2725 7.76377C15.9937 6.56418 16.7475 6.81794 16.7475 6.81794C17.2424 8.08674 16.9275 9.03257 16.8375 9.26326C17.4113 9.9092 17.76 10.7281 17.76 11.7432C17.76 15.2843 15.6563 16.0687 13.6537 16.2993C13.98 16.5877 14.2613 17.1414 14.2613 18.0065C14.2613 19.2407 14.25 20.2326 14.25 20.5441C14.25 20.7863 14.4188 21.0746 14.8688 20.9824C16.6554 20.364 18.2079 19.1866 19.3078 17.6162C20.4077 16.0457 20.9995 14.1611 21 12.2276C21 7.12937 16.9725 3 12 3Z", ++ fill: "currentColor" ++ })); ++} ++ ++// src/icons/globe.tsx ++import React10 from "react"; ++function GlobeIcon() { ++ return /* @__PURE__ */ React10.createElement("svg", { ++ viewBox: "0 0 20 20", ++ width: "1em", ++ height: "1em", ++ fill: "currentColor" ++ }, /* @__PURE__ */ React10.createElement("path", { ++ fillRule: "evenodd", ++ d: "M4.083 9h1.946c.089-1.546.383-2.97.837-4.118A6.004 6.004 0 004.083 9zM10 2a8 8 0 100 16 8 8 0 000-16zm0 2c-.076 0-.232.032-.465.262-.238.234-.497.623-.737 1.182-.389.907-.673 2.142-.766 3.556h3.936c-.093-1.414-.377-2.649-.766-3.556-.24-.56-.5-.948-.737-1.182C10.232 4.032 10.076 4 10 4zm3.971 5c-.089-1.546-.383-2.97-.837-4.118A6.004 6.004 0 0115.917 9h-1.946zm-2.003 2H8.032c.093 1.414.377 2.649.766 3.556.24.56.5.948.737 1.182.233.23.389.262.465.262.076 0 .232-.032.465-.262.238-.234.498-.623.737-1.182.389-.907.673-2.142.766-3.556zm1.166 4.118c.454-1.147.748-2.572.837-4.118h1.946a6.004 6.004 0 01-2.783 4.118zm-6.268 0C6.412 13.97 6.118 12.546 6.03 11H4.083a6.004 6.004 0 002.783 4.118z", ++ clipRule: "evenodd" ++ })); ++} ++ ++// src/icons/menu.tsx ++import React11 from "react"; ++function MenuIcon({ className }) { ++ return /* @__PURE__ */ React11.createElement("svg", { ++ fill: "none", ++ width: "24", ++ height: "24", ++ viewBox: "0 0 24 24", ++ stroke: "currentColor", ++ className ++ }, /* @__PURE__ */ React11.createElement("g", null, /* @__PURE__ */ React11.createElement("path", { ++ strokeLinecap: "round", ++ strokeLinejoin: "round", ++ strokeWidth: "2", ++ d: "M4 6h16" ++ })), /* @__PURE__ */ React11.createElement("path", { ++ strokeLinecap: "round", ++ strokeLinejoin: "round", ++ strokeWidth: "2", ++ d: "M4 12h16" ++ }), /* @__PURE__ */ React11.createElement("g", null, /* @__PURE__ */ React11.createElement("path", { ++ strokeLinecap: "round", ++ strokeLinejoin: "round", ++ strokeWidth: "2", ++ d: "M4 18h16" ++ }))); ++} ++ ++// src/icons/moon.tsx ++import React12 from "react"; ++function MoonIcon({ className }) { ++ return /* @__PURE__ */ React12.createElement("svg", { ++ fill: "none", ++ viewBox: "0 0 24 24", ++ width: "24", ++ height: "24", ++ stroke: "currentColor", ++ className ++ }, /* @__PURE__ */ React12.createElement("path", { ++ strokeLinecap: "round", ++ strokeLinejoin: "round", ++ strokeWidth: "2", ++ d: "M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" ++ })); ++} ++ ++// src/icons/spinner.tsx ++import React13 from "react"; ++function SpinnerIcon({ ++ className ++}) { ++ return /* @__PURE__ */ React13.createElement("svg", { ++ xmlns: "http://www.w3.org/2000/svg", ++ fill: "none", ++ viewBox: "0 0 24 24", ++ width: "24", ++ height: "24", ++ className ++ }, /* @__PURE__ */ React13.createElement("circle", { ++ className: "opacity-25", ++ cx: "12", ++ cy: "12", ++ r: "10", ++ stroke: "currentColor", ++ strokeWidth: "4" ++ }), /* @__PURE__ */ React13.createElement("path", { ++ className: "opacity-75", ++ fill: "currentColor", ++ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" ++ })); ++} ++ ++// src/icons/sun.tsx ++import React14 from "react"; ++function SunIcon({ className }) { ++ return /* @__PURE__ */ React14.createElement("svg", { ++ fill: "none", ++ viewBox: "0 0 24 24", ++ width: "24", ++ height: "24", ++ stroke: "currentColor", ++ className ++ }, /* @__PURE__ */ React14.createElement("path", { ++ strokeLinecap: "round", ++ strokeLinejoin: "round", ++ strokeWidth: "2", ++ d: "M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" ++ })); ++} ++ ++// src/icons/x.tsx ++import React15 from "react"; ++function XIcon({ className }) { ++ return /* @__PURE__ */ React15.createElement("svg", { ++ xmlns: "http://www.w3.org/2000/svg", ++ width: "20", ++ height: "20", ++ viewBox: "0 0 20 20", ++ fill: "currentColor", ++ className ++ }, /* @__PURE__ */ React15.createElement("path", { ++ fillRule: "evenodd", ++ d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z", ++ clipRule: "evenodd" ++ })); ++} ++ ++// src/flexsearch.js + var Item2 = ({ + page, + first, +@@ -277,21 +505,20 @@ var Item2 = ({ + onClick, + excerpt + }) => { +- return /* @__PURE__ */ React5.createElement(React5.Fragment, null, first ? /* @__PURE__ */ React5.createElement("div", { ++ return /* @__PURE__ */ React16.createElement(React16.Fragment, null, first ? /* @__PURE__ */ React16.createElement("div", { + className: "nextra-search-section mx-2.5 px-2.5 pb-1.5 mb-2 mt-6 first:mt-0 font-semibold uppercase text-xs text-gray-500 select-none dark:text-gray-300" +- }, page) : null, /* @__PURE__ */ React5.createElement(Link2, { +- href: Router.basePath + href +- }, /* @__PURE__ */ React5.createElement("a", { ++ }, page) : null, /* @__PURE__ */ React16.createElement(Anchor, { ++ href: Router.basePath + href, + className: "block no-underline", + onMouseMove: onHover, + onClick +- }, /* @__PURE__ */ React5.createElement("li", { ++ }, /* @__PURE__ */ React16.createElement("li", { + className: cn2({ active }) +- }, /* @__PURE__ */ React5.createElement("div", { ++ }, /* @__PURE__ */ React16.createElement("div", { + className: "font-semibold dark:text-white leading-5" +- }, title), excerpt ? /* @__PURE__ */ React5.createElement("div", { ++ }, title), excerpt ? /* @__PURE__ */ React16.createElement("div", { + className: "excerpt mt-1 text-gray-600 text-sm leading-[1.35rem] dark:text-gray-400" +- }, excerpt) : null)))); ++ }, excerpt) : null))); + }; + var MemoedStringWithMatchHighlights = memo(function StringWithMatchHighlights({ content, search }) { + const splittedText = content.split(""); +@@ -302,16 +529,16 @@ var MemoedStringWithMatchHighlights = memo(function StringWithMatchHighlights({ + let index = 0; + const res = []; + while ((match = regexp.exec(content)) !== null) { +- res.push(/* @__PURE__ */ React5.createElement(Fragment, { ++ res.push(/* @__PURE__ */ React16.createElement(Fragment, { + key: id++ + }, splittedText.splice(0, match.index - index).join(""))); +- res.push(/* @__PURE__ */ React5.createElement("span", { ++ res.push(/* @__PURE__ */ React16.createElement("span", { + className: "highlight", + key: id++ + }, splittedText.splice(0, regexp.lastIndex - match.index).join(""))); + index = regexp.lastIndex; + } +- res.push(/* @__PURE__ */ React5.createElement(Fragment, { ++ res.push(/* @__PURE__ */ React16.createElement(Fragment, { + key: id++ + }, splittedText.join(""))); + return res; +@@ -320,11 +547,11 @@ var indexes = {}; + function Search2() { + const config = useConfig(); + const router = useRouter2(); +- const [loading, setLoading] = useState2(false); +- const [show, setShow] = useState2(false); +- const [search, setSearch] = useState2(""); +- const [active, setActive] = useState2(0); +- const [results, setResults] = useState2([]); ++ const [loading, setLoading] = useState3(false); ++ const [show, setShow] = useState3(false); ++ const [search, setSearch] = useState3(""); ++ const [active, setActive] = useState3(0); ++ const [results, setResults] = useState3([]); + const input = useRef2(null); + const { setMenu } = useMenuContext(); + const finishSearch = () => { +@@ -378,11 +605,11 @@ function Search2() { + first: firstItemOfPage, + route: url, + page: result.doc.title, +- title: /* @__PURE__ */ React5.createElement(MemoedStringWithMatchHighlights, { ++ title: /* @__PURE__ */ React16.createElement(MemoedStringWithMatchHighlights, { + content: section.doc.title, + search + }), +- excerpt: content ? /* @__PURE__ */ React5.createElement(MemoedStringWithMatchHighlights, { ++ excerpt: content ? /* @__PURE__ */ React16.createElement(MemoedStringWithMatchHighlights, { + content, + search + }) : null +@@ -400,7 +627,7 @@ function Search2() { + return a._page_rk - b._page_rk; + })); + }; +- useEffect2(doSearch, [search]); ++ useEffect3(doSearch, [search]); + const handleKeyDown = useCallback2((e) => { + switch (e.key) { + case "ArrowDown": { +@@ -447,7 +674,8 @@ function Search2() { + const localeCode = Router.locale || "default"; + if (!indexes[localeCode] && !loading) { + setLoading(true); +- const data = yield (yield fetch(`${Router.basePath}/_next/static/chunks/nextra-data-${localeCode}.json`)).json(); ++ const response = yield fetch(`${Router.basePath}/_next/static/chunks/nextra-data-${localeCode}.json`); ++ const data = yield response.json(); + const pageIndex = new FlexSearch.Document({ + cache: 100, + tokenize: "full", +@@ -516,10 +744,10 @@ function Search2() { + setSearch((s) => s ? s + " " : s); + } + }); +- useEffect2(() => { ++ useEffect3(() => { + setActive(0); + }, [search]); +- useEffect2(() => { ++ useEffect3(() => { + const inputs = ["input", "select", "button", "textarea"]; + const down = (e) => { + if (document.activeElement && inputs.indexOf(document.activeElement.tagName.toLowerCase()) === -1) { +@@ -536,14 +764,14 @@ function Search2() { + return () => window.removeEventListener("keydown", down); + }, []); + const renderList = show && !!search; +- return /* @__PURE__ */ React5.createElement("div", { ++ return /* @__PURE__ */ React16.createElement("div", { + className: "relative w-full nextra-search nextra-flexsearch md:w-64" +- }, renderList && /* @__PURE__ */ React5.createElement("div", { ++ }, renderList && /* @__PURE__ */ React16.createElement("div", { + className: "z-10 search-overlay", + onClick: () => setShow(false) +- }), /* @__PURE__ */ React5.createElement("div", { ++ }), /* @__PURE__ */ React16.createElement("div", { + className: "relative flex items-center" +- }, /* @__PURE__ */ React5.createElement("input", { ++ }, /* @__PURE__ */ React16.createElement("input", { + onChange: (e) => { + setSearch(e.target.value); + setShow(true); +@@ -560,40 +788,26 @@ function Search2() { + }, + ref: input, + spellCheck: false +- }), renderList ? null : /* @__PURE__ */ React5.createElement("div", { ++ }), !renderList && /* @__PURE__ */ React16.createElement("div", { + className: "hidden sm:flex absolute inset-y-0 right-0 py-1.5 pr-1.5 select-none pointer-events-none" +- }, /* @__PURE__ */ React5.createElement("kbd", { ++ }, /* @__PURE__ */ React16.createElement("kbd", { + className: "inline-flex items-center px-1.5 font-mono text-sm font-medium bg-white dark:bg-dark dark:bg-opacity-50 text-gray-400 dark:text-gray-500 dark:border-gray-100 dark:border-opacity-20 border rounded" +- }, "/"))), /* @__PURE__ */ React5.createElement(Transition, { ++ }, "/"))), /* @__PURE__ */ React16.createElement(Transition, { + show: renderList, +- as: React5.Fragment, ++ as: React16.Fragment, + leave: "transition duration-100", + leaveFrom: "opacity-100", + leaveTo: "opacity-0" +- }, /* @__PURE__ */ React5.createElement("ul", { ++ }, /* @__PURE__ */ React16.createElement("ul", { + className: "absolute z-20 px-0 py-2.5 m-0 mt-2 top-full rounded-xl overflow-hidden overscroll-contain shadow-xl list-none" +- }, loading ? /* @__PURE__ */ React5.createElement("span", { ++ }, loading ? /* @__PURE__ */ React16.createElement("span", { + className: "p-8 text-center text-gray-400 text-sm select-none flex justify-center" +- }, /* @__PURE__ */ React5.createElement("svg", { +- className: "animate-spin -ml-1 mr-2 h-5 w-5 text-gray-400", +- xmlns: "http://www.w3.org/2000/svg", +- fill: "none", +- viewBox: "0 0 24 24" +- }, /* @__PURE__ */ React5.createElement("circle", { +- className: "opacity-25", +- cx: "12", +- cy: "12", +- r: "10", +- stroke: "currentColor", +- strokeWidth: "4" +- }), /* @__PURE__ */ React5.createElement("path", { +- className: "opacity-75", +- fill: "currentColor", +- d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" +- })), /* @__PURE__ */ React5.createElement("span", null, "Loading...")) : results.length === 0 ? render_component_default(config.unstable_searchResultEmpty, { ++ }, /* @__PURE__ */ React16.createElement(SpinnerIcon, { ++ className: "animate-spin -ml-1 mr-2 h-5 w-5 text-gray-400" ++ }), /* @__PURE__ */ React16.createElement("span", null, "Loading...")) : results.length === 0 ? render_component_default(config.unstable_searchResultEmpty, { + locale: router.locale + }) : results.map((res, i) => { +- return /* @__PURE__ */ React5.createElement(Item2, { ++ return /* @__PURE__ */ React16.createElement(Item2, { + first: res.first, + key: `search-item-${i}`, + page: res.page, +@@ -602,47 +816,11 @@ function Search2() { + excerpt: res.excerpt, + active: i === active, + onHover: () => setActive(i), +- onClick: () => { +- finishSearch(); +- } ++ onClick: finishSearch + }); + })))); + } + +-// src/icons/github.tsx +-import React6 from "react"; +-var Github = ({ height = 40 }) => { +- return /* @__PURE__ */ React6.createElement("svg", { +- height, +- viewBox: "2 2 20 20", +- fill: "none", +- "aria-hidden": "true" +- }, /* @__PURE__ */ React6.createElement("path", { +- fillRule: "evenodd", +- clipRule: "evenodd", +- d: "M12 3C7.0275 3 3 7.12937 3 12.2276C3 16.3109 5.57625 19.7597 9.15374 20.9824C9.60374 21.0631 9.77249 20.7863 9.77249 20.5441C9.77249 20.3249 9.76125 19.5982 9.76125 18.8254C7.5 19.2522 6.915 18.2602 6.735 17.7412C6.63375 17.4759 6.19499 16.6569 5.8125 16.4378C5.4975 16.2647 5.0475 15.838 5.80124 15.8264C6.51 15.8149 7.01625 16.4954 7.18499 16.7723C7.99499 18.1679 9.28875 17.7758 9.80625 17.5335C9.885 16.9337 10.1212 16.53 10.38 16.2993C8.3775 16.0687 6.285 15.2728 6.285 11.7432C6.285 10.7397 6.63375 9.9092 7.20749 9.26326C7.1175 9.03257 6.8025 8.08674 7.2975 6.81794C7.2975 6.81794 8.05125 6.57571 9.77249 7.76377C10.4925 7.55615 11.2575 7.45234 12.0225 7.45234C12.7875 7.45234 13.5525 7.55615 14.2725 7.76377C15.9937 6.56418 16.7475 6.81794 16.7475 6.81794C17.2424 8.08674 16.9275 9.03257 16.8375 9.26326C17.4113 9.9092 17.76 10.7281 17.76 11.7432C17.76 15.2843 15.6563 16.0687 13.6537 16.2993C13.98 16.5877 14.2613 17.1414 14.2613 18.0065C14.2613 19.2407 14.25 20.2326 14.25 20.5441C14.25 20.7863 14.4188 21.0746 14.8688 20.9824C16.6554 20.364 18.2079 19.1866 19.3078 17.6162C20.4077 16.0457 20.9995 14.1611 21 12.2276C21 7.12937 16.9725 3 12 3Z", +- fill: "currentColor" +- })); +-}; +-var github_default = Github; +- +-// src/icons/discord.tsx +-import React7 from "react"; +-var DiscordIcon = ({ height = 40 }) => { +- return /* @__PURE__ */ React7.createElement("svg", { +- height, +- fill: "none", +- xmlns: "http://www.w3.org/2000/svg", +- viewBox: "0 0 146 146", +- "aria-hidden": "true" +- }, /* @__PURE__ */ React7.createElement("title", null, "Discord"), /* @__PURE__ */ React7.createElement("path", { +- d: "M107.75 125.001s-4.5-5.375-8.25-10.125c16.375-4.625 22.625-14.875 22.625-14.875-5.125 3.375-10 5.75-14.375 7.375-6.25 2.625-12.25 4.375-18.125 5.375-12 2.25-23 1.625-32.375-.125-7.125-1.375-13.25-3.375-18.375-5.375-2.875-1.125-6-2.5-9.125-4.25-.375-.25-.75-.375-1.125-.625-.25-.125-.375-.25-.5-.375-2.25-1.25-3.5-2.125-3.5-2.125s6 10 21.875 14.75c-3.75 4.75-8.375 10.375-8.375 10.375-27.625-.875-38.125-19-38.125-19 0-40.25 18-72.875 18-72.875 18-13.5 35.125-13.125 35.125-13.125l1.25 1.5c-22.5 6.5-32.875 16.375-32.875 16.375s2.75-1.5 7.375-3.625c13.375-5.875 24-7.5 28.375-7.875.75-.125 1.375-.25 2.125-.25 7.625-1 16.25-1.25 25.25-.25 11.875 1.375 24.625 4.875 37.625 12 0 0-9.875-9.375-31.125-15.875l1.75-2S110 19.626 128 33.126c0 0 18 32.625 18 72.875 0 0-10.625 18.125-38.25 19zM49.625 66.626c-7.125 0-12.75 6.25-12.75 13.875s5.75 13.875 12.75 13.875c7.125 0 12.75-6.25 12.75-13.875.125-7.625-5.625-13.875-12.75-13.875zm45.625 0c-7.125 0-12.75 6.25-12.75 13.875s5.75 13.875 12.75 13.875c7.125 0 12.75-6.25 12.75-13.875s-5.625-13.875-12.75-13.875z", +- fillRule: "nonzero", +- fill: "currentColor" +- })); +-}; +-var discord_default = DiscordIcon; +- + // src/navbar.tsx + function Navbar({ flatDirectories, items }) { + const config = useConfig(); +@@ -650,17 +828,17 @@ function Navbar({ flatDirectories, items }) { + const activeRoute = getFSRoute(asPath, locale); + const { menu, setMenu } = useMenuContext(); + const bannerKey = config.bannerKey || "nextra-banner"; +- return /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement("script", { ++ return /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement("script", { + dangerouslySetInnerHTML: { + __html: `try{if(localStorage.getItem(${JSON.stringify(bannerKey)})==='0'){document.body.classList.add('nextra-banner-hidden')}}catch(e){}` + } +- }), config.banner ? /* @__PURE__ */ React8.createElement("div", { ++ }), config.banner ? /* @__PURE__ */ React17.createElement("div", { + className: "nextra-banner-container text-sm h-10 sticky top-0 md:relative pl-10 flex items-center text-slate-50 bg-neutral-900 dark:text-white z-20 dark:bg-[linear-gradient(1deg,#383838,#212121)]" +- }, /* @__PURE__ */ React8.createElement("div", { ++ }, /* @__PURE__ */ React17.createElement("div", { + className: "max-w-[90rem] mx-auto w-full py-1 text-center font-medium pl-[max(env(safe-area-inset-left),1.5rem)] pr-[max(env(safe-area-inset-right),1.5rem)] truncate whitespace-nowrap" + }, render_component_default(config.banner, { + locale +- })), /* @__PURE__ */ React8.createElement("button", { ++ })), /* @__PURE__ */ React17.createElement("button", { + className: "mr-2 w-8 opacity-80 hover:opacity-100", + onClick: () => { + try { +@@ -669,28 +847,20 @@ function Navbar({ flatDirectories, items }) { + } + document.body.classList.add("nextra-banner-hidden"); + } +- }, /* @__PURE__ */ React8.createElement("svg", { +- xmlns: "http://www.w3.org/2000/svg", +- className: "h-4 w-4 mx-auto", +- viewBox: "0 0 20 20", +- fill: "currentColor" +- }, /* @__PURE__ */ React8.createElement("path", { +- fillRule: "evenodd", +- d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z", +- clipRule: "evenodd" +- })))) : null, /* @__PURE__ */ React8.createElement("div", { ++ }, /* @__PURE__ */ React17.createElement(XIcon, { ++ className: "h4 w-4 mx-auto" ++ }))) : null, /* @__PURE__ */ React17.createElement("div", { + className: "nextra-nav-container z-20 sticky bg-transparent w-full top-0" +- }, /* @__PURE__ */ React8.createElement("div", { ++ }, /* @__PURE__ */ React17.createElement("div", { + className: "nextra-nav-container-blur absolute w-full h-full bg-white dark:bg-dark pointer-events-none" +- }), /* @__PURE__ */ React8.createElement("nav", { ++ }), /* @__PURE__ */ React17.createElement("nav", { + className: "flex gap-2 max-w-[90rem] mx-auto items-center left-0 right-0 h-16 pl-[max(env(safe-area-inset-left),1.5rem)] pr-[max(env(safe-area-inset-right),1.5rem)]" +- }, /* @__PURE__ */ React8.createElement("div", { ++ }, /* @__PURE__ */ React17.createElement("div", { + className: "flex items-center mr-2 flex-auto" +- }, /* @__PURE__ */ React8.createElement(Link3, { +- href: "/" +- }, /* @__PURE__ */ React8.createElement("a", { ++ }, /* @__PURE__ */ React17.createElement(Anchor, { ++ href: "/", + className: "no-underline text-current inline-flex items-center hover:opacity-75" +- }, render_component_default(config.logo, { locale })))), /* @__PURE__ */ React8.createElement("div", { ++ }, render_component_default(config.logo, { locale }))), /* @__PURE__ */ React17.createElement("div", { + className: "flex-1" + }), items ? items.map((page) => { + if (page.hidden) +@@ -700,151 +870,80 @@ function Navbar({ flatDirectories, items }) { + href = (page.withIndexPage ? page.route : page.firstChildRoute) || href; + } + const isActive = page.route === activeRoute || activeRoute.startsWith(page.route + "/"); +- return /* @__PURE__ */ React8.createElement(Link3, { ++ return /* @__PURE__ */ React17.createElement(Anchor, __spreadValues({ ++ key: page.route, + href, +- key: page.route +- }, /* @__PURE__ */ React8.createElement("a", __spreadValues({ + className: cn3("nextra-nav-link", "no-underline whitespace-nowrap p-2 -ml-2 hidden md:inline-block", !isActive || page.newWindow ? "text-gray-600 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-200" : "active text-current font-medium"), + "aria-selected": isActive +- }, page.newWindow ? { ++ }, page.newWindow && { + target: "_blank", + rel: "noopener noreferrer", + "aria-selected": false +- } : {}), page.title)); +- }) : null, /* @__PURE__ */ React8.createElement("div", null, /* @__PURE__ */ React8.createElement("div", { ++ }), page.title); ++ }) : null, /* @__PURE__ */ React17.createElement("div", null, /* @__PURE__ */ React17.createElement("div", { + className: "hidden md:inline-block" +- }, config.customSearch || (config.search ? config.unstable_flexsearch ? /* @__PURE__ */ React8.createElement(Search2, null) : /* @__PURE__ */ React8.createElement(search_default, { ++ }, config.customSearch || (config.search ? config.unstable_flexsearch ? /* @__PURE__ */ React17.createElement(Search2, null) : /* @__PURE__ */ React17.createElement(search_default, { + directories: flatDirectories +- }) : null))), config.projectLink || config.github ? /* @__PURE__ */ React8.createElement("a", { ++ }) : null))), config.projectLink || config.github ? /* @__PURE__ */ React17.createElement("a", { + className: "text-current p-2", + href: config.projectLink || config.github, + target: "_blank", + rel: "noreferrer" +- }, config.projectLinkIcon ? render_component_default(config.projectLinkIcon, { locale }) : /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(github_default, { ++ }, config.projectLinkIcon ? render_component_default(config.projectLinkIcon, { locale }) : /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement(GitHubIcon, { + height: 24 +- }), /* @__PURE__ */ React8.createElement("span", { ++ }), /* @__PURE__ */ React17.createElement("span", { + className: "sr-only" +- }, "GitHub"))) : null, config.projectChatLink ? /* @__PURE__ */ React8.createElement("a", { ++ }, "GitHub"))) : null, config.projectChatLink ? /* @__PURE__ */ React17.createElement("a", { + className: "text-current p-2", + href: config.projectChatLink, + target: "_blank", + rel: "noreferrer" +- }, config.projectChatLinkIcon ? render_component_default(config.projectChatLinkIcon, { locale }) : /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(discord_default, { ++ }, config.projectChatLinkIcon ? render_component_default(config.projectChatLinkIcon, { locale }) : /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement(DiscordIcon, { + height: 24 +- }), /* @__PURE__ */ React8.createElement("span", { ++ }), /* @__PURE__ */ React17.createElement("span", { + className: "sr-only" +- }, "Discord"))) : null, /* @__PURE__ */ React8.createElement("button", { ++ }, "Discord"))) : null, /* @__PURE__ */ React17.createElement("button", { + className: "nextra-menu-icon block md:hidden p-2", + onClick: () => setMenu(!menu) +- }, /* @__PURE__ */ React8.createElement("svg", { +- fill: "none", +- width: "24", +- height: "24", +- viewBox: "0 0 24 24", +- stroke: "currentColor", ++ }, /* @__PURE__ */ React17.createElement(MenuIcon, { + className: cn3({ open: menu }) +- }, /* @__PURE__ */ React8.createElement("g", null, /* @__PURE__ */ React8.createElement("path", { +- strokeLinecap: "round", +- strokeLinejoin: "round", +- strokeWidth: 2, +- d: "M4 6h16" +- })), /* @__PURE__ */ React8.createElement("path", { +- strokeLinecap: "round", +- strokeLinejoin: "round", +- strokeWidth: 2, +- d: "M4 12h16" +- }), /* @__PURE__ */ React8.createElement("g", null, /* @__PURE__ */ React8.createElement("path", { +- strokeLinecap: "round", +- strokeLinejoin: "round", +- strokeWidth: 2, +- d: "M4 18h16" +- }))))))); ++ }))))); + } + + // src/footer.tsx +-import React17 from "react"; ++import React21 from "react"; + import cn5 from "classnames"; +-import Link4 from "next/link"; + import { useRouter as useRouter5 } from "next/router"; + +-// src/icons/arrow-right.tsx +-import React9 from "react"; +-var ArrowRight = (_a) => { +- var _b = _a, { childProps } = _b, props = __objRest(_b, ["childProps"]); +- return /* @__PURE__ */ React9.createElement("svg", __spreadValues({ +- fill: "none", +- viewBox: "0 0 24 24", +- stroke: "currentColor" +- }, props), /* @__PURE__ */ React9.createElement("path", __spreadValues({ +- strokeLinecap: "round", +- strokeLinejoin: "round", +- strokeWidth: 2, +- d: "M9 5l7 7-7 7" +- }, childProps || {}))); +-}; +-var arrow_right_default = ArrowRight; +- + // src/locale-switch.tsx +-import React13 from "react"; ++import React19 from "react"; + import { useRouter as useRouter4 } from "next/router"; + + // src/select.tsx +-import React11 from "react"; ++import React18 from "react"; + import cn4 from "classnames"; + import { Listbox, Transition as Transition2 } from "@headlessui/react"; +- +-// src/icons/check.tsx +-import React10 from "react"; +-function Check() { +- return /* @__PURE__ */ React10.createElement("svg", { +- viewBox: "0 0 20 20", +- width: "1em", +- height: "1em", +- fill: "currentColor" +- }, /* @__PURE__ */ React10.createElement("path", { +- fillRule: "evenodd", +- d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", +- clipRule: "evenodd" +- })); +-} +- +-// src/select.tsx + function Menu({ options, selected, onChange }) { +- return /* @__PURE__ */ React11.createElement(Listbox, { ++ return /* @__PURE__ */ React18.createElement(Listbox, { + value: selected, + onChange +- }, ({ open }) => /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement(Listbox.Button, { ++ }, ({ open }) => /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(Listbox.Button, { + className: cn4("rounded-md px-2 w-full text-left font-medium cursor-default text-xs h-7 transition-colors text-gray-600 dark:text-gray-400 focus:outline-none", open ? "bg-gray-200 dark:bg-primary-100 dark:bg-opacity-10 text-gray-900 dark:text-gray-50" : "hover:bg-gray-100 hover:text-gray-900 dark:hover:bg-primary-100 dark:hover:bg-opacity-5 dark:hover:text-gray-50") +- }, selected.name), /* @__PURE__ */ React11.createElement(Transition2, { ++ }, selected.name), /* @__PURE__ */ React18.createElement(Transition2, { + show: open, +- as: React11.Fragment, ++ as: React18.Fragment, + leave: "transition", + leaveFrom: "opacity-100", + leaveTo: "opacity-0" +- }, /* @__PURE__ */ React11.createElement(Listbox.Options, { ++ }, /* @__PURE__ */ React18.createElement(Listbox.Options, { + className: "menu absolute bottom-[130%] min-w-full z-20 mt-1 bg-white dark:bg-neutral-800 dark:ring-white dark:ring-opacity-20 shadow-lg max-h-64 rounded-md py-1 ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none text-sm" +- }, options.map((option) => /* @__PURE__ */ React11.createElement(Listbox.Option, { ++ }, options.map((option) => /* @__PURE__ */ React18.createElement(Listbox.Option, { + key: option.key, + value: option, + className: ({ active }) => cn4(option.key === selected.key ? "" : "", active ? "text-primary-500 bg-primary-50 dark:bg-primary-500 dark:bg-opacity-10" : "text-gray-800 dark:text-gray-100", "cursor-default select-none relative py-1.5 pl-3 pr-9 whitespace-nowrap") +- }, option.name, option.key === selected.key ? /* @__PURE__ */ React11.createElement("span", { ++ }, option.name, option.key === selected.key ? /* @__PURE__ */ React18.createElement("span", { + className: cn4("absolute inset-y-0 right-0 flex items-center pr-3") +- }, /* @__PURE__ */ React11.createElement(Check, null)) : null)))))); +-} +- +-// src/icons/globe.tsx +-import React12 from "react"; +-function Globe() { +- return /* @__PURE__ */ React12.createElement("svg", { +- viewBox: "0 0 20 20", +- width: "1em", +- height: "1em", +- fill: "currentColor" +- }, /* @__PURE__ */ React12.createElement("path", { +- fillRule: "evenodd", +- d: "M4.083 9h1.946c.089-1.546.383-2.97.837-4.118A6.004 6.004 0 004.083 9zM10 2a8 8 0 100 16 8 8 0 000-16zm0 2c-.076 0-.232.032-.465.262-.238.234-.497.623-.737 1.182-.389.907-.673 2.142-.766 3.556h3.936c-.093-1.414-.377-2.649-.766-3.556-.24-.56-.5-.948-.737-1.182C10.232 4.032 10.076 4 10 4zm3.971 5c-.089-1.546-.383-2.97-.837-4.118A6.004 6.004 0 0115.917 9h-1.946zm-2.003 2H8.032c.093 1.414.377 2.649.766 3.556.24.56.5.948.737 1.182.233.23.389.262.465.262.076 0 .232-.032.465-.262.238-.234.498-.623.737-1.182.389-.907.673-2.142.766-3.556zm1.166 4.118c.454-1.147.748-2.572.837-4.118h1.946a6.004 6.004 0 01-2.783 4.118zm-6.268 0C6.412 13.97 6.118 12.546 6.03 11H4.083a6.004 6.004 0 002.783 4.118z", +- clipRule: "evenodd" +- })); ++ }, /* @__PURE__ */ React18.createElement(CheckIcon, null)) : null)))))); + } + + // src/locale-switch.tsx +@@ -852,7 +951,7 @@ function LocaleSwitch({ options }) { + const router = useRouter4(); + const { locale, asPath } = router; + const selected = options.find((l) => locale === l.locale); +- return /* @__PURE__ */ React13.createElement(Menu, { ++ return /* @__PURE__ */ React19.createElement(Menu, { + onChange: (option) => { + const date = new Date(Date.now() + 365 * 24 * 60 * 60 * 1e3); + document.cookie = `NEXT_LOCALE=${option.key}; expires=${date.toUTCString()}; path=/`; +@@ -860,9 +959,9 @@ function LocaleSwitch({ options }) { + }, + selected: { + key: selected.locale, +- name: /* @__PURE__ */ React13.createElement("div", { ++ name: /* @__PURE__ */ React19.createElement("div", { + className: "flex items-center gap-2" +- }, /* @__PURE__ */ React13.createElement(Globe, null), /* @__PURE__ */ React13.createElement("span", null, selected.text)) ++ }, /* @__PURE__ */ React19.createElement(GlobeIcon, null), /* @__PURE__ */ React19.createElement("span", null, selected.text)) + }, + options: options.map((l) => ({ + key: l.locale, +@@ -872,100 +971,36 @@ function LocaleSwitch({ options }) { + } + + // src/theme-switch.tsx +-import React16, { memo as memo2 } from "react"; ++import React20, { memo as memo2 } from "react"; + import { useTheme as useTheme2 } from "next-themes"; +- +-// src/icons/sun.tsx +-import React14 from "react"; +-function Moon() { +- return /* @__PURE__ */ React14.createElement("svg", { +- viewBox: "0 0 20 20", +- width: "1em", +- height: "1em", +- fill: "currentColor" +- }, /* @__PURE__ */ React14.createElement("path", { +- fillRule: "evenodd", +- d: "M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z", +- clipRule: "evenodd" +- })); +-} +- +-// src/icons/moon.tsx +-import React15 from "react"; +-function Sun() { +- return /* @__PURE__ */ React15.createElement("svg", { +- viewBox: "0 0 20 20", +- width: "1em", +- height: "1em", +- fill: "currentColor" +- }, /* @__PURE__ */ React15.createElement("path", { +- d: "M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" +- })); +-} +- +-// src/theme-switch.tsx + function ThemeSwitch({ lite = true }) { + const { theme, setTheme, systemTheme } = useTheme2(); + const renderedTheme = theme === "system" ? systemTheme : theme; +- const [mounted, setMounted] = React16.useState(false); +- React16.useEffect(() => setMounted(true), []); +- return /* @__PURE__ */ React16.createElement(Menu, { ++ const mounted = useMounted(); ++ return /* @__PURE__ */ React20.createElement(Menu, { + onChange: (option) => { + setTheme(option.key); + }, + selected: { + key: theme || "", +- name: /* @__PURE__ */ React16.createElement("div", { ++ name: /* @__PURE__ */ React20.createElement("div", { + className: "flex items-center gap-2 capitalize" +- }, mounted && renderedTheme === "dark" ? /* @__PURE__ */ React16.createElement(Sun, null) : /* @__PURE__ */ React16.createElement(Moon, null), lite ? "" : /* @__PURE__ */ React16.createElement("span", null, mounted ? theme : "light")) ++ }, mounted && renderedTheme === "dark" ? /* @__PURE__ */ React20.createElement(MoonIcon, { ++ className: "[&>path]:fill-current h-4 w-4" ++ }) : /* @__PURE__ */ React20.createElement(SunIcon, { ++ className: "[&>path]:fill-current h-4 w-4" ++ }), lite ? "" : /* @__PURE__ */ React20.createElement("span", null, mounted ? theme : "light")) + }, + options: [ +- { +- key: "light", +- name: "Light" +- }, +- { +- key: "dark", +- name: "Dark" +- }, +- { +- key: "system", +- name: "System" +- } ++ { key: "light", name: "Light" }, ++ { key: "dark", name: "Dark" }, ++ { key: "system", name: "System" } + ] + }); + } + var theme_switch_default = memo2(ThemeSwitch); + + // src/footer.tsx +-var NextLink = ({ route, title, isRTL }) => { +- return /* @__PURE__ */ React17.createElement(Link4, { +- href: route +- }, /* @__PURE__ */ React17.createElement("a", { +- className: cn5("text-base md:text-lg font-medium p-4 -m-4 no-underline transition-colors text-gray-600 dark:text-gray-300 dark:hover:text-primary-500 hover:text-primary-500 inline-flex items-center justify-end rounded", { "ml-2": !isRTL, "mr-2": isRTL }), +- title +- }, title, /* @__PURE__ */ React17.createElement(arrow_right_default, { +- height: 20, +- className: cn5("transform inline flex-shrink-0", { +- "rotate-180 mr-1": isRTL, +- "ml-1": !isRTL +- }) +- }))); +-}; +-var PrevLink = ({ route, title, isRTL }) => { +- return /* @__PURE__ */ React17.createElement(Link4, { +- href: route +- }, /* @__PURE__ */ React17.createElement("a", { +- className: cn5("text-base md:text-lg font-medium p-4 -m-4 no-underline transition-colors text-gray-600 dark:text-gray-300 dark:hover:text-primary-500 hover:text-primary-500 flex items-center rounded", { "mr-2": !isRTL, "ml-2": isRTL }), +- title +- }, /* @__PURE__ */ React17.createElement(arrow_right_default, { +- height: 20, +- className: cn5("transform inline flex-shrink-0", { +- "rotate-180 mr-1": !isRTL, +- "ml-1": isRTL +- }) +- }), title)); +-}; + var NavLinks = ({ + flatDirectories, + currentIndex, +@@ -976,74 +1011,79 @@ var NavLinks = ({ + const next = config.nextLinks ? flatDirectories[currentIndex + 1] : null; + if (!prev && !next) + return null; +- return /* @__PURE__ */ React17.createElement("div", { ++ return /* @__PURE__ */ React21.createElement("div", { + className: "nextra-navigation-links pt-8 mb-8 border-t dark:border-neutral-800 flex flex-row items-center justify-between" +- }, /* @__PURE__ */ React17.createElement("div", { ++ }, /* @__PURE__ */ React21.createElement("div", { + className: "flex-1 min-w-0 flex justify-start" +- }, prev ? /* @__PURE__ */ React17.createElement(PrevLink, { +- route: prev.route, +- title: prev.title, +- isRTL +- }) : null), /* @__PURE__ */ React17.createElement("div", { ++ }, prev && /* @__PURE__ */ React21.createElement(Anchor, { ++ href: prev.route, ++ className: cn5("text-base md:text-lg font-medium p-4 -m-4 no-underline transition-colors text-gray-600 dark:text-gray-300 dark:hover:text-primary-500 hover:text-primary-500 flex items-center rounded", isRTL ? "ml-2" : "mr-2"), ++ title: prev.title ++ }, /* @__PURE__ */ React21.createElement(ArrowRightIcon, { ++ height: 20, ++ className: cn5("transform inline flex-shrink-0", isRTL ? "ml-1" : "rotate-180 mr-1") ++ }), prev.title)), /* @__PURE__ */ React21.createElement("div", { + className: "flex-1 min-w-0 flex justify-end" +- }, next ? /* @__PURE__ */ React17.createElement(NextLink, { +- route: next.route, +- title: next.title, +- isRTL +- }) : null)); ++ }, next && /* @__PURE__ */ React21.createElement(Anchor, { ++ href: next.route, ++ className: cn5("text-base md:text-lg font-medium p-4 -m-4 no-underline transition-colors text-gray-600 dark:text-gray-300 dark:hover:text-primary-500 hover:text-primary-500 inline-flex items-center justify-end rounded", isRTL ? "mr-2" : "ml-2"), ++ title: next.title ++ }, next.title, /* @__PURE__ */ React21.createElement(ArrowRightIcon, { ++ height: 20, ++ className: cn5("transform inline flex-shrink-0", isRTL ? "rotate-180 mr-1" : "ml-1") ++ })))); + }; + var Footer = ({ menu }) => { + const { locale } = useRouter5(); + const config = useConfig(); +- return /* @__PURE__ */ React17.createElement("footer", { ++ return /* @__PURE__ */ React21.createElement("footer", { + className: "bg-gray-100 dark:bg-neutral-900 pb-[env(safe-area-inset-bottom)]" +- }, /* @__PURE__ */ React17.createElement("div", { +- className: cn5("py-2 border-b dark:border-neutral-800 hidden md:block", menu ? "" : "md:hidden") +- }, /* @__PURE__ */ React17.createElement("div", { ++ }, /* @__PURE__ */ React21.createElement("div", { ++ className: cn5("py-2 border-b dark:border-neutral-800 hidden md:block", !menu && "md:hidden") ++ }, /* @__PURE__ */ React21.createElement("div", { + className: "max-w-[90rem] mx-auto" +- }, /* @__PURE__ */ React17.createElement("div", { ++ }, /* @__PURE__ */ React21.createElement("div", { + className: "inline-flex px-4" +- }, config.i18n ? /* @__PURE__ */ React17.createElement("div", { ++ }, config.i18n ? /* @__PURE__ */ React21.createElement("div", { + className: "flex-1 relative" +- }, /* @__PURE__ */ React17.createElement(LocaleSwitch, { ++ }, /* @__PURE__ */ React21.createElement(LocaleSwitch, { + options: config.i18n +- })) : null, config.darkMode ? /* @__PURE__ */ React17.createElement("div", { ++ })) : null, config.darkMode ? /* @__PURE__ */ React21.createElement("div", { + className: "grow-0 relative" +- }, /* @__PURE__ */ React17.createElement(theme_switch_default, { ++ }, /* @__PURE__ */ React21.createElement(theme_switch_default, { + lite: false +- })) : null))), /* @__PURE__ */ React17.createElement("div", { ++ })) : null))), /* @__PURE__ */ React21.createElement("div", { + className: "max-w-[90rem] mx-auto pl-[max(env(safe-area-inset-left),1.5rem)] pr-[max(env(safe-area-inset-right),1.5rem)] py-12" +- }, /* @__PURE__ */ React17.createElement("div", { ++ }, /* @__PURE__ */ React21.createElement("div", { + className: "flex justify-between flex-col-reverse md:flex-row items-center md:items-end" +- }, /* @__PURE__ */ React17.createElement("span", { ++ }, /* @__PURE__ */ React21.createElement("span", { + className: "text-gray-600 dark:text-gray-400" +- }, render_component_default(config.footerText, { locale })), /* @__PURE__ */ React17.createElement("div", { ++ }, render_component_default(config.footerText, { locale })), /* @__PURE__ */ React21.createElement("div", { + className: "mt-6" + })))); + }; + var footer_default = Footer; + + // src/misc/theme.tsx +-import Link5 from "next/link"; +-import React23, { +- useEffect as useEffect4, ++import React27, { ++ useEffect as useEffect5, + useRef as useRef4, +- useState as useState4, ++ useState as useState5, + useContext as useContext3 + } from "react"; + import "intersection-observer"; + + // src/misc/active-anchor.tsx +-import React18, { createContext as createContext2, useContext as useContext2, useState as useState3 } from "react"; ++import React22, { createContext as createContext2, useContext as useContext2, useState as useState4 } from "react"; + var ActiveAnchorContext = createContext2({}); + var ActiveAnchorSetterContext = createContext2((s) => s); + var useActiveAnchor = () => useContext2(ActiveAnchorContext); + var useActiveAnchorSet = () => useContext2(ActiveAnchorSetterContext); + var ActiveAnchor = ({ children }) => { +- const state = useState3({}); +- return /* @__PURE__ */ React18.createElement(ActiveAnchorContext.Provider, { ++ const state = useState4({}); ++ return /* @__PURE__ */ React22.createElement(ActiveAnchorContext.Provider, { + value: state[0] +- }, /* @__PURE__ */ React18.createElement(ActiveAnchorSetterContext.Provider, { ++ }, /* @__PURE__ */ React22.createElement(ActiveAnchorSetterContext.Provider, { + value: state[1] + }, children)); + }; +@@ -1052,7 +1092,7 @@ var ActiveAnchor = ({ children }) => { + import { MDXProvider } from "@mdx-js/react"; + + // src/components/collapse.tsx +-import React19, { useRef as useRef3, useEffect as useEffect3 } from "react"; ++import React23, { useRef as useRef3, useEffect as useEffect4 } from "react"; + function Collapse({ + children, + open +@@ -1062,7 +1102,7 @@ function Collapse({ + const animationRef = useRef3(); + const initialRender = useRef3(true); + const initialState = useRef3(open); +- useEffect3(() => { ++ useEffect4(() => { + if (initialRender.current) + return; + if (animationRef.current) { +@@ -1102,16 +1142,16 @@ function Collapse({ + } + } + }, [open]); +- useEffect3(() => { ++ useEffect4(() => { + initialRender.current = false; + }, []); +- return /* @__PURE__ */ React19.createElement("div", { ++ return /* @__PURE__ */ React23.createElement("div", { + ref: containerRef, + className: "transition-all ease-in-out duration-300 overflow-hidden transform-gpu motion-reduce:transition-none", + style: { + maxHeight: initialState.current ? void 0 : 0 + } +- }, /* @__PURE__ */ React19.createElement("div", { ++ }, /* @__PURE__ */ React23.createElement("div", { + ref: innerRef, + className: "nextra-collapse-content transition-opacity ease-in-out duration-500 overflow-hidden transform-gpu motion-reduce:transition-none", + style: { +@@ -1121,7 +1161,7 @@ function Collapse({ + } + + // src/components/tabs.tsx +-import React20 from "react"; ++import React24 from "react"; + import cn6 from "classnames"; + import { Tab as HeadlessTab } from "@headlessui/react"; + function Tabs({ +@@ -1131,44 +1171,44 @@ function Tabs({ + onChange, + children + }) { +- return /* @__PURE__ */ React20.createElement(HeadlessTab.Group, { ++ return /* @__PURE__ */ React24.createElement(HeadlessTab.Group, { + selectedIndex, + defaultIndex, + onChange +- }, /* @__PURE__ */ React20.createElement("div", { ++ }, /* @__PURE__ */ React24.createElement("div", { + className: "p-2 -m-2 overscroll-x-contain overflow-x-auto overflow-y-hidden no-scrollbar" +- }, /* @__PURE__ */ React20.createElement(HeadlessTab.List, { ++ }, /* @__PURE__ */ React24.createElement(HeadlessTab.List, { + className: "flex mt-4 pb-[1px] border-b border-gray-200 dark:border-neutral-800 w-max min-w-full" + }, items.map((item, index) => { + const disabled = !!(item && typeof item === "object" && "disabled" in item && item.disabled); +- return /* @__PURE__ */ React20.createElement(HeadlessTab, { ++ return /* @__PURE__ */ React24.createElement(HeadlessTab, { + key: index, + disabled, + className: ({ selected }) => cn6("p-2 mr-2 leading-5 font-medium text-md transition-colors", "select-none border-b-2 mb-[-2px] focus:outline-none focus-visible:ring ring-offset-2 rounded-[1px]", selected ? "text-primary-500 border-primary-500" : "text-gray-600 dark:text-gray-200 hover:border-gray-200 dark:hover:border-neutral-800 border-transparent hover:text-black dark:hover:text-white", disabled ? "pointer-events-none text-gray-400 dark:text-neutral-600" : "") + }, item && typeof item === "object" && "label" in item ? item.label : item); +- }))), /* @__PURE__ */ React20.createElement(HeadlessTab.Panels, null, children)); ++ }))), /* @__PURE__ */ React24.createElement(HeadlessTab.Panels, null, children)); + } + function Tab({ children }) { +- return /* @__PURE__ */ React20.createElement(HeadlessTab.Panel, { ++ return /* @__PURE__ */ React24.createElement(HeadlessTab.Panel, { + className: "focus:outline-none focus-visible:ring" + }, children); + } + + // src/bleed.tsx +-import React21 from "react"; ++import React25 from "react"; + import cn7 from "classnames"; + var Bleed = ({ + full, + children + }) => { +- return /* @__PURE__ */ React21.createElement("div", { ++ return /* @__PURE__ */ React25.createElement("div", { + className: cn7("bleed relative mt-6 -mx-6 md:-mx-8 2xl:-mx-24", { full }) + }, children); + }; + var bleed_default = Bleed; + + // src/callout.tsx +-import React22 from "react"; ++import React26 from "react"; + var themes = { + default: "bg-orange-50 border border-orange-100 text-orange-800 dark:text-orange-300 dark:bg-orange-400 dark:border-orange-400 dark:bg-opacity-20 dark:border-opacity-30", + error: "bg-red-100 border border-red-200 text-red-900 dark:text-red-200 dark:bg-red-900 dark:bg-opacity-30 dark:border-opacity-30", +@@ -1180,14 +1220,14 @@ var Callout = ({ + type = "default", + emoji = "\u{1F4A1}" + }) => { +- return /* @__PURE__ */ React22.createElement("div", { ++ return /* @__PURE__ */ React26.createElement("div", { + className: `${themes[type]} flex rounded-lg nextra-callout mt-6` +- }, /* @__PURE__ */ React22.createElement("div", { ++ }, /* @__PURE__ */ React26.createElement("div", { + className: "pl-3 pr-2 py-2 select-none text-xl", + style: { + fontFamily: '"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"' + } +- }, emoji), /* @__PURE__ */ React22.createElement("div", { ++ }, emoji), /* @__PURE__ */ React26.createElement("div", { + className: "pr-4 py-2" + }, children)); + }; +@@ -1200,9 +1240,8 @@ var slugs = /* @__PURE__ */ new WeakMap(); + if (typeof window !== "undefined") { + observer = observer || new IntersectionObserver((entries) => { + const headers = []; +- for (let i = 0; i < entries.length; i++) { +- const entry = entries[i]; +- if (entry && entry.rootBounds && slugs.has(entry.target)) { ++ for (const entry of entries) { ++ if ((entry == null ? void 0 : entry.rootBounds) && slugs.has(entry.target)) { + const [slug, index] = slugs.get(entry.target); + const aboveHalfViewport = entry.boundingClientRect.y + entry.boundingClientRect.height <= entry.rootBounds.y + entry.rootBounds.height; + const insideHalfViewport = entry.intersectionRatio > 0; +@@ -1241,34 +1280,21 @@ if (typeof window !== "undefined") { + threshold: [0, 1] + }); + } +-var HeaderLink = (_a) => { ++var createHeaderLink = (Tag) => function HeaderLink(_a) { + var _b = _a, { +- tag: Tag, + children, +- id, +- context, +- withObserver = true ++ id: slug + } = _b, props = __objRest(_b, [ +- "tag", + "children", +- "id", +- "context", +- "withObserver" ++ "id" + ]); + setActiveAnchor = useActiveAnchorSet(); + const obRef = useRef4(null); +- const slug = id; +- const anchor = /* @__PURE__ */ React23.createElement("span", { +- className: "subheading-anchor", +- id: slug, +- ref: obRef +- }); +- const index = context.index++; +- useEffect4(() => { ++ useEffect5(() => { + const ref = obRef; + if (!ref.current) + return; +- slugs.set(ref.current, [slug, index]); ++ slugs.set(ref.current, [slug, Number(Tag[1]) - 1]); + if (ref.current) + observer.observe(ref.current); + return () => { +@@ -1281,92 +1307,44 @@ var HeaderLink = (_a) => { + }); + }; + }, []); +- return /* @__PURE__ */ React23.createElement(Tag, __spreadValues({}, props), anchor, /* @__PURE__ */ React23.createElement("a", { ++ return /* @__PURE__ */ React27.createElement(Tag, __spreadValues({}, props), /* @__PURE__ */ React27.createElement("span", { ++ className: "subheading-anchor", ++ id: slug, ++ ref: obRef ++ }), /* @__PURE__ */ React27.createElement("a", { + href: "#" + slug, + className: "anchor text-current no-underline no-outline" +- }, children, /* @__PURE__ */ React23.createElement("span", { ++ }, children, /* @__PURE__ */ React27.createElement("span", { + className: "anchor-icon", + "aria-hidden": true + }, "#"))); + }; +-var H2 = (context) => (_a) => { +- var _b = _a, { children } = _b, props = __objRest(_b, ["children"]); +- return /* @__PURE__ */ React23.createElement(HeaderLink, __spreadValues({ +- tag: "h2", +- context +- }, props), children); +-}; +-var H3 = (context) => (_a) => { +- var _b = _a, { children } = _b, props = __objRest(_b, ["children"]); +- return /* @__PURE__ */ React23.createElement(HeaderLink, __spreadValues({ +- tag: "h3", +- context +- }, props), children); +-}; +-var H4 = (context) => (_a) => { +- var _b = _a, { children } = _b, props = __objRest(_b, ["children"]); +- return /* @__PURE__ */ React23.createElement(HeaderLink, __spreadValues({ +- tag: "h4", +- context +- }, props), children); +-}; +-var H5 = (context) => (_a) => { +- var _b = _a, { children } = _b, props = __objRest(_b, ["children"]); +- return /* @__PURE__ */ React23.createElement(HeaderLink, __spreadValues({ +- tag: "h5", +- context +- }, props), children); +-}; +-var H6 = (context) => (_a) => { +- var _b = _a, { children } = _b, props = __objRest(_b, ["children"]); +- return /* @__PURE__ */ React23.createElement(HeaderLink, __spreadValues({ +- tag: "h6", +- context +- }, props), children); +-}; +-var A = (_a) => { +- var _b = _a, { +- children +- } = _b, props = __objRest(_b, [ +- "children" +- ]); +- const isExternal = props.href && props.href.startsWith("https://"); +- if (isExternal) { +- return /* @__PURE__ */ React23.createElement("a", __spreadValues({ +- target: "_blank", +- rel: "noreferrer" +- }, props), children); +- } +- return props.href ? /* @__PURE__ */ React23.createElement(Link5, { +- href: props.href +- }, /* @__PURE__ */ React23.createElement("a", __spreadValues({}, props), children)) : /* @__PURE__ */ React23.createElement(React23.Fragment, null); +-}; + var Table = ({ children }) => { +- return /* @__PURE__ */ React23.createElement("div", { ++ return /* @__PURE__ */ React27.createElement("div", { + className: "table-container" +- }, /* @__PURE__ */ React23.createElement("table", null, children)); ++ }, /* @__PURE__ */ React27.createElement("table", null, children)); + }; +-var DetailsContext = React23.createContext(() => { ++var DetailsContext = React27.createContext(() => { + }); + var findSummary = (children) => { + let summary = null; + let restChildren = []; +- React23.Children.forEach(children, (child, index) => { ++ React27.Children.forEach(children, (child, index) => { + var _a; + if (child && child.type === Summary) { + summary = summary || child; +- } else { +- let c = child; +- if (!summary && typeof child === "object" && child && child.type !== Details && "props" in child && child.props) { +- const result = findSummary(child.props.children); +- summary = summary || result[0]; +- c = React23.cloneElement(child, __spreadProps(__spreadValues({}, child.props), { +- children: ((_a = result[1]) == null ? void 0 : _a.length) ? result[1] : void 0, +- key: index +- })); +- } +- restChildren.push(c); ++ return; + } ++ let c = child; ++ if (!summary && typeof child === "object" && child && child.type !== Details && "props" in child && child.props) { ++ const result = findSummary(child.props.children); ++ summary = summary || result[0]; ++ c = React27.cloneElement(child, __spreadProps(__spreadValues({}, child.props), { ++ children: ((_a = result[1]) == null ? void 0 : _a.length) ? result[1] : void 0, ++ key: index ++ })); ++ } ++ restChildren.push(c); + }); + return [summary, restChildren]; + }; +@@ -1378,35 +1356,39 @@ var Details = (_a) => { + "children", + "open" + ]); +- const [openState, setOpen] = useState4(!!open); ++ const [openState, setOpen] = useState5(!!open); + const ref = useRef4(null); + const [summary, restChildren] = findSummary(children); +- return /* @__PURE__ */ React23.createElement("details", __spreadValues(__spreadProps(__spreadValues({}, props), { ++ return /* @__PURE__ */ React27.createElement("details", __spreadValues(__spreadProps(__spreadValues({}, props), { + ref, + open: true +- }), openState ? { "data-open": "" } : null), /* @__PURE__ */ React23.createElement(DetailsContext.Provider, { ++ }), openState && { "data-open": "" }), /* @__PURE__ */ React27.createElement(DetailsContext.Provider, { + value: setOpen +- }, summary), /* @__PURE__ */ React23.createElement(Collapse, { ++ }, summary), /* @__PURE__ */ React27.createElement(Collapse, { + open: openState + }, restChildren)); + }; + var Summary = (_a) => { +- var _b = _a, { children } = _b, props = __objRest(_b, ["children"]); ++ var _b = _a, { ++ children ++ } = _b, props = __objRest(_b, [ ++ "children" ++ ]); + const setOpen = useContext3(DetailsContext); +- return /* @__PURE__ */ React23.createElement("summary", __spreadProps(__spreadValues({}, props), { ++ return /* @__PURE__ */ React27.createElement("summary", __spreadProps(__spreadValues({}, props), { + onClick: (e) => { + e.preventDefault(); + setOpen((v) => !v); + } + }), children); + }; +-var getComponents = (context) => ({ +- h2: H2(context), +- h3: H3(context), +- h4: H4(context), +- h5: H5(context), +- h6: H6(context), +- a: A, ++var components = { ++ h2: createHeaderLink("h2"), ++ h3: createHeaderLink("h3"), ++ h4: createHeaderLink("h4"), ++ h5: createHeaderLink("h5"), ++ h6: createHeaderLink("h6"), ++ a: Anchor, + table: Table, + details: Details, + summary: Summary, +@@ -1416,19 +1398,20 @@ var getComponents = (context) => ({ + Tabs, + Tab + } +-}); +-var MDXTheme = ({ children }) => { +- return /* @__PURE__ */ React23.createElement(MDXProvider, { +- components: getComponents({ index: 0 }) ++}; ++var MDXTheme = ({ ++ children ++}) => { ++ return /* @__PURE__ */ React27.createElement(MDXProvider, { ++ components + }, children); + }; + + // src/sidebar.tsx +-import React24, { useState as useState5, useEffect as useEffect5, useMemo as useMemo2 } from "react"; ++import React28, { useState as useState6, useEffect as useEffect6, useMemo as useMemo2 } from "react"; + import cn8 from "classnames"; + import Slugger from "github-slugger"; + import { useRouter as useRouter6 } from "next/router"; +-import Link6 from "next/link"; + import scrollIntoView from "scroll-into-view-if-needed"; + + // src/utils/get-heading-text.ts +@@ -1438,7 +1421,7 @@ function getHeadingText(heading) { + + // src/sidebar.tsx + var TreeState = {}; +-var Folder = React24.memo(FolderImpl); ++var Folder = React28.memo(FolderImpl); + function FolderImpl({ item, anchors }) { + const { asPath, locale } = useRouter6(); + const routeOriginal = getFSRoute(asPath, locale); +@@ -1447,14 +1430,15 @@ function FolderImpl({ item, anchors }) { + const activeRouteInside = active || route.startsWith(item.route + "/"); + const { defaultMenuCollapsed } = useMenuContext(); + const open = typeof TreeState[item.route] !== "undefined" ? TreeState[item.route] : active || activeRouteInside || !defaultMenuCollapsed; +- const rerender = useState5({})[1]; ++ const rerender = useState6({})[1]; + const { setMenu } = useMenuContext(); +- useEffect5(() => { ++ useEffect6(() => { + if (activeRouteInside) { + TreeState[item.route] = true; + } + }, [activeRouteInside]); +- const link = /* @__PURE__ */ React24.createElement("a", { ++ const link = /* @__PURE__ */ React28.createElement(Anchor, { ++ href: item.withIndexPage ? item.route : "", + className: "cursor-pointer", + onClick: (e) => { + const clickedToggleIcon = ["svg", "path"].includes(e.target.tagName.toLowerCase()); +@@ -1476,22 +1460,17 @@ function FolderImpl({ item, anchors }) { + TreeState[item.route] = !open; + rerender({}); + } +- }, /* @__PURE__ */ React24.createElement("span", { ++ }, /* @__PURE__ */ React28.createElement("span", { + className: "flex items-center justify-between" +- }, item.title, /* @__PURE__ */ React24.createElement(arrow_right_default, { ++ }, item.title, /* @__PURE__ */ React28.createElement(ArrowRightIcon, { + height: "1em", +- className: "ml-2 p-[2px] rounded-sm min-w-[18px] h-[18px] dark:hover:bg-gray-100 hover:bg-gray-800 hover:bg-opacity-5 dark:hover:bg-opacity-5", +- childProps: { +- className: cn8("transition-transform origin-center", open ? "rotate-90" : "") +- } ++ className: cn8("ml-2 p-0.5 rounded-sm min-w-[18px] h-[18px] dark:hover:bg-gray-100 hover:bg-gray-800 hover:bg-opacity-5 dark:hover:bg-opacity-5", "[&>path]:transition-transform [&>path]:origin-center", open && "[&>path]:rotate-90") + }))); +- return /* @__PURE__ */ React24.createElement("li", { ++ return /* @__PURE__ */ React28.createElement("li", { + className: cn8({ open, active }) +- }, item.withIndexPage ? /* @__PURE__ */ React24.createElement(Link6, { +- href: item.route +- }, link) : link, /* @__PURE__ */ React24.createElement(Collapse, { ++ }, link, /* @__PURE__ */ React28.createElement(Collapse, { + open +- }, Array.isArray(item.children) && /* @__PURE__ */ React24.createElement(Menu2, { ++ }, Array.isArray(item.children) && /* @__PURE__ */ React28.createElement(Menu2, { + submenu: true, + directories: item.children, + base: item.route, +@@ -1499,92 +1478,97 @@ function FolderImpl({ item, anchors }) { + }))); + } + function Separator({ title, topLevel }) { +- const hasTitle = typeof title !== "undefined"; ++ const hasTitle = title !== void 0; + const { sidebarSubtitle } = useConfig(); +- return /* @__PURE__ */ React24.createElement("li", { ++ return /* @__PURE__ */ React28.createElement("li", { + className: cn8(topLevel ? "first:mt-1" : "first:mt-2", hasTitle ? "mt-5 mb-2" : "my-4") +- }, hasTitle ? /* @__PURE__ */ React24.createElement("div", { ++ }, hasTitle ? /* @__PURE__ */ React28.createElement("div", { + className: "text-sm mx-2 py-1.5 font-semibold no-underline text-gray-900 dark:text-gray-100" +- }, sidebarSubtitle ? render_component_default(sidebarSubtitle, { title }) : title) : /* @__PURE__ */ React24.createElement("hr", { ++ }, sidebarSubtitle ? render_component_default(sidebarSubtitle, { title }) : title) : /* @__PURE__ */ React28.createElement("hr", { + className: "mx-2 border-t border-gray-200 dark:border-primary-100 dark:border-opacity-10" + })); + } + function File({ item, anchors, topLevel }) { + const { asPath, locale } = useRouter6(); + const route = getFSRoute(asPath, locale); +- const active = route === item.route + "/" || route + "/" === item.route + "/"; ++ const active = [route, route + "/"].includes(item.route + "/"); + const slugger = new Slugger(); + const activeAnchor = useActiveAnchor(); + const { setMenu } = useMenuContext(); +- const title = item.title; + if (item.type === "separator") { +- return /* @__PURE__ */ React24.createElement(Separator, { +- title, ++ return /* @__PURE__ */ React28.createElement(Separator, { ++ title: item.title, + topLevel + }); + } +- if (anchors && anchors.length) { ++ if (anchors == null ? void 0 : anchors.length) { + if (active) { + let activeIndex = 0; +- const anchorInfo = anchors.map((anchor, i) => { +- const text = anchor; ++ const anchorInfo = anchors.map((text, i) => { ++ var _a; + const slug = slugger.slug(text); +- if (activeAnchor[slug] && activeAnchor[slug].isActive) { ++ if ((_a = activeAnchor[slug]) == null ? void 0 : _a.isActive) { + activeIndex = i; + } + return { text, slug }; + }); +- return /* @__PURE__ */ React24.createElement("li", { ++ return /* @__PURE__ */ React28.createElement("li", { + className: active ? "active" : "" +- }, /* @__PURE__ */ React24.createElement(Link6, { ++ }, /* @__PURE__ */ React28.createElement(Anchor, __spreadProps(__spreadValues({ + href: item.href || item.route +- }, /* @__PURE__ */ React24.createElement("a", __spreadProps(__spreadValues({}, item.newWindow ? { target: "_blank", rel: "noopener noreferrer" } : {}), { ++ }, item.newWindow && { ++ target: "_blank", ++ rel: "noopener noreferrer" ++ }), { + onClick: () => { + setMenu(false); + } +- }), title)), /* @__PURE__ */ React24.createElement("ul", null, anchors.map((_, i) => { ++ }), item.title), /* @__PURE__ */ React28.createElement("ul", null, anchors.map((_, i) => { + const { slug, text } = anchorInfo[i]; + const isActive = i === activeIndex; +- return /* @__PURE__ */ React24.createElement("li", { ++ return /* @__PURE__ */ React28.createElement("li", { + key: `a-${slug}` +- }, /* @__PURE__ */ React24.createElement("a", { ++ }, /* @__PURE__ */ React28.createElement("a", { + href: "#" + slug, + className: isActive ? "active-anchor" : "", + onClick: () => { + setMenu(false); + } +- }, /* @__PURE__ */ React24.createElement("span", { ++ }, /* @__PURE__ */ React28.createElement("span", { + className: "flex text-sm" +- }, /* @__PURE__ */ React24.createElement("span", { ++ }, /* @__PURE__ */ React28.createElement("span", { + className: "opacity-25" +- }, "#"), /* @__PURE__ */ React24.createElement("span", { ++ }, "#"), /* @__PURE__ */ React28.createElement("span", { + className: "mr-2" +- }), /* @__PURE__ */ React24.createElement("span", { ++ }), /* @__PURE__ */ React28.createElement("span", { + className: "inline-block" + }, text)))); + }))); + } + } +- return /* @__PURE__ */ React24.createElement("li", { ++ return /* @__PURE__ */ React28.createElement("li", { + className: active ? "active" : "" +- }, /* @__PURE__ */ React24.createElement(Link6, { ++ }, /* @__PURE__ */ React28.createElement(Anchor, __spreadProps(__spreadValues({ + href: item.href || item.route +- }, /* @__PURE__ */ React24.createElement("a", __spreadProps(__spreadValues({}, item.newWindow ? { target: "_blank", rel: "noopener noreferrer" } : {}), { ++ }, item.newWindow && { ++ target: "_blank", ++ rel: "noopener noreferrer" ++ }), { + onClick: () => { + setMenu(false); + } +- }), title))); ++ }), item.title)); + } + function Menu2({ directories, anchors, submenu }) { +- return /* @__PURE__ */ React24.createElement("ul", null, directories.map((item) => { ++ return /* @__PURE__ */ React28.createElement("ul", null, directories.map((item) => { + if (item.children && (item.children.length || !item.withIndexPage)) { +- return /* @__PURE__ */ React24.createElement(Folder, { ++ return /* @__PURE__ */ React28.createElement(Folder, { + key: item.name, + item, + anchors + }); + } +- return /* @__PURE__ */ React24.createElement(File, { ++ return /* @__PURE__ */ React28.createElement(File, { + key: item.name, + item, + anchors, +@@ -1604,14 +1588,14 @@ function Sidebar({ + const config = useConfig(); + const anchors = useMemo2(() => headings.filter((v) => v.children && v.depth === 2 && v.type === "heading").map((v) => getHeadingText(v)).filter(Boolean), [headings]); + const { menu } = useMenuContext(); +- useEffect5(() => { ++ useEffect6(() => { + if (menu) { + document.body.classList.add("overflow-hidden", "md:overflow-auto"); + } else { + document.body.classList.remove("overflow-hidden", "md:overflow-auto"); + } + }, [menu]); +- useEffect5(() => { ++ useEffect6(() => { + const activeElement = document.querySelector(".nextra-sidebar li.active"); + if (activeElement) { + scrollIntoView(activeElement, { +@@ -1623,72 +1607,59 @@ function Sidebar({ + } + }, []); + const hasMenu = !!(config.i18n || config.darkMode); +- return /* @__PURE__ */ React24.createElement(React24.Fragment, null, includePlaceholder && asPopover ? /* @__PURE__ */ React24.createElement("div", { ++ return /* @__PURE__ */ React28.createElement(React28.Fragment, null, includePlaceholder && asPopover ? /* @__PURE__ */ React28.createElement("div", { + className: "hidden xl:block w-64 h-0 flex-shrink-0" +- }) : null, /* @__PURE__ */ React24.createElement("aside", { +- className: cn8("nextra-sidebar-container nextra-scrollbar fixed flex-shrink-0 w-full md:w-64 md:sticky z-[15] top-16 self-start overflow-y-auto transform-none h-[calc(100vh-4rem)]", asPopover ? "md:hidden" : "md:block", hasMenu ? "with-menu" : "", { open: menu }) +- }, /* @__PURE__ */ React24.createElement("div", { ++ }) : null, /* @__PURE__ */ React28.createElement("aside", { ++ className: cn8("nextra-sidebar-container nextra-scrollbar fixed flex-shrink-0 w-full md:w-64 md:sticky z-[15] top-16 self-start overflow-y-auto h-[calc(100vh-4rem)]", asPopover ? "md:hidden" : "md:block", hasMenu && "with-menu", { open: menu }) ++ }, /* @__PURE__ */ React28.createElement("div", { + className: "nextra-sidebar select-none w-full h-full md:h-auto pl-[calc(env(safe-area-inset-left)-1.5rem)]" +- }, /* @__PURE__ */ React24.createElement("div", { ++ }, /* @__PURE__ */ React28.createElement("div", { + className: "p-4 min-h-[calc(100vh-4rem-61px)]" +- }, /* @__PURE__ */ React24.createElement("div", { ++ }, /* @__PURE__ */ React28.createElement("div", { + className: "nextra-sidebar-search mb-4 block md:hidden" +- }, config.customSearch || (config.search ? config.unstable_flexsearch ? /* @__PURE__ */ React24.createElement(Search2, null) : /* @__PURE__ */ React24.createElement(search_default, { ++ }, config.customSearch || (config.search ? config.unstable_flexsearch ? /* @__PURE__ */ React28.createElement(Search2, null) : /* @__PURE__ */ React28.createElement(search_default, { + directories: flatDirectories +- }) : null)), /* @__PURE__ */ React24.createElement("div", { ++ }) : null)), /* @__PURE__ */ React28.createElement("div", { + className: "hidden md:block" +- }, /* @__PURE__ */ React24.createElement(Menu2, { ++ }, /* @__PURE__ */ React28.createElement(Menu2, { + directories, + anchors: config.floatTOC ? [] : anchors +- })), /* @__PURE__ */ React24.createElement("div", { ++ })), /* @__PURE__ */ React28.createElement("div", { + className: "md:hidden" +- }, /* @__PURE__ */ React24.createElement(Menu2, { ++ }, /* @__PURE__ */ React28.createElement(Menu2, { + directories: fullDirectories, + anchors +- }))), !hasMenu ? null : /* @__PURE__ */ React24.createElement("div", { ++ }))), !hasMenu ? null : /* @__PURE__ */ React28.createElement("div", { + className: "nextra-sidebar-menu mx-4 border-t dark:border-neutral-800 shadow-[0_-12px_16px_white] dark:shadow-[0_-12px_16px_#111]" +- }, /* @__PURE__ */ React24.createElement("div", { ++ }, /* @__PURE__ */ React28.createElement("div", { + className: "bg-white dark:bg-dark py-4 flex gap-1 pb-4" +- }, config.i18n ? /* @__PURE__ */ React24.createElement("div", { ++ }, config.i18n ? /* @__PURE__ */ React28.createElement("div", { + className: "flex-1 relative" +- }, /* @__PURE__ */ React24.createElement(LocaleSwitch, { ++ }, /* @__PURE__ */ React28.createElement(LocaleSwitch, { + options: config.i18n +- })) : null, config.darkMode ? /* @__PURE__ */ React24.createElement(React24.Fragment, null, /* @__PURE__ */ React24.createElement("div", { ++ })) : null, config.darkMode ? /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement("div", { + className: cn8("relative md:hidden", { + locale: config.i18n, + "flex-1": !config.i18n + }) +- }, /* @__PURE__ */ React24.createElement(theme_switch_default, { ++ }, /* @__PURE__ */ React28.createElement(theme_switch_default, { + lite: false +- })), /* @__PURE__ */ React24.createElement("div", { ++ })), /* @__PURE__ */ React28.createElement("div", { + className: cn8("relative hidden md:block", { + locale: config.i18n + }, config.i18n ? "grow-0" : "flex-1") +- }, /* @__PURE__ */ React24.createElement(theme_switch_default, { ++ }, /* @__PURE__ */ React28.createElement(theme_switch_default, { + lite: !!config.i18n + }))) : null))))); + } + + // src/toc.tsx +-import React25 from "react"; ++import React29 from "react"; + import cn9 from "classnames"; + import Slugger2 from "github-slugger"; + import parseGitUrl from "parse-git-url"; + import { useRouter as useRouter7 } from "next/router"; + import scrollIntoView2 from "scroll-into-view-if-needed"; +- +-// src/utils/use-mounted.ts +-import { useEffect as useEffect6, useState as useState6 } from "react"; +-var useMounted = () => { +- const [mounted, setMounted] = useState6(false); +- useEffect6(() => { +- setMounted(true); +- }, []); +- return mounted; +-}; +-var use_mounted_default = useMounted; +- +-// src/toc.tsx + var createEditUrl = (repository, filepath) => { + const repo = parseGitUrl(repository || ""); + if (!repo) +@@ -1702,7 +1673,7 @@ var createEditUrl = (repository, filepath) => { + return "#"; + }; + var useCreateFeedbackUrl = (repository, filepath, labels) => { +- const mounted = use_mounted_default(); ++ const mounted = useMounted(); + if (!mounted) + return "#"; + const repo = parseGitUrl(repository || ""); +@@ -1724,7 +1695,7 @@ var EditPageLink = ({ + }) => { + const url = createEditUrl(repository, filepath); + const { locale } = useRouter7(); +- return /* @__PURE__ */ React25.createElement("a", { ++ return /* @__PURE__ */ React29.createElement("a", { + className: "text-xs font-medium no-underline block text-gray-500 mb-2 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100", + href: url, + target: "_blank", +@@ -1741,7 +1712,7 @@ var FeedbackLink = ({ + }) => { + const url = useCreateFeedbackUrl(repository, filepath, labels); + const { locale } = useRouter7(); +- return /* @__PURE__ */ React25.createElement("a", { ++ return /* @__PURE__ */ React29.createElement("a", { + className: "text-xs font-medium no-underline block text-gray-500 mb-2 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100", + href: url, + target: "_blank", +@@ -1771,8 +1742,8 @@ function Item3({ + }) { + const text = getHeadingText(heading); + const state = activeAnchor[slug]; +- const ref = React25.useRef(null); +- React25.useEffect(() => { ++ const ref = React29.useRef(null); ++ React29.useEffect(() => { + const el = ref.current; + const toc = document.getElementsByClassName("nextra-toc")[0]; + if ((state == null ? void 0 : state.isActive) && el && toc) { +@@ -1785,11 +1756,11 @@ function Item3({ + }); + } + }, [state == null ? void 0 : state.isActive]); +- return /* @__PURE__ */ React25.createElement("li", { ++ return /* @__PURE__ */ React29.createElement("li", { + className: "scroll-py-6 scroll-my-6", + style: indent(heading.depth), + ref +- }, /* @__PURE__ */ React25.createElement("a", { ++ }, /* @__PURE__ */ React29.createElement("a", { + href: `#${slug}`, + className: cn9("no-underline inline-block", heading.depth === 2 ? "font-semibold" : "", (state == null ? void 0 : state.isActive) ? "text-primary-500 subpixel-antialiased" : "text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-300"), + "aria-selected": state == null ? void 0 : state.isActive +@@ -1806,39 +1777,39 @@ function ToC({ + headings = headings ? headings.filter((heading) => heading.type === "heading" && heading.depth > 1) : headings; + const hasHeadings = headings && headings.length > 0; + const hasMetaInfo = config.feedbackLink || config.footerEditLink || config.tocExtraContent; +- return /* @__PURE__ */ React25.createElement("div", { ++ return /* @__PURE__ */ React29.createElement("div", { + className: "nextra-toc w-64 hidden xl:block text-sm px-4 order-last flex-shrink-0" +- }, /* @__PURE__ */ React25.createElement("div", { ++ }, /* @__PURE__ */ React29.createElement("div", { + className: "nextra-toc-content overflow-y-auto pr-4 -mr-4 sticky max-h-[calc(100vh-4rem-env(safe-area-inset-bottom))] top-16 pt-8" +- }, hasHeadings && headings ? /* @__PURE__ */ React25.createElement("ul", null, /* @__PURE__ */ React25.createElement("p", { ++ }, hasHeadings && headings ? /* @__PURE__ */ React29.createElement("ul", null, /* @__PURE__ */ React29.createElement("p", { + className: "font-semibold tracking-tight mb-4" + }, "On This Page"), headings.map((heading) => { + const text = getHeadingText(heading); + const slug = slugger.slug(text); +- return /* @__PURE__ */ React25.createElement(Item3, { ++ return /* @__PURE__ */ React29.createElement(Item3, { + heading, + activeAnchor, + slug, + key: slug + }); +- })) : null, hasMetaInfo ? /* @__PURE__ */ React25.createElement("div", { ++ })) : null, hasMetaInfo ? /* @__PURE__ */ React29.createElement("div", { + className: cn9("nextra-toc-meta", hasHeadings ? "border-t mt-8 pt-8 shadow-[0_-12px_16px_white] dark:shadow-[0_-12px_16px_#111] bg-white dark:bg-dark" : "", "sticky pb-8 bottom-0 dark:border-neutral-800") +- }, config.feedbackLink ? /* @__PURE__ */ React25.createElement(FeedbackLink, { ++ }, config.feedbackLink ? /* @__PURE__ */ React29.createElement(FeedbackLink, { + filepath: filepathWithName, + repository: config.docsRepositoryBase, + labels: config.feedbackLabels, + text: config.feedbackLink +- }) : null, config.footerEditLink ? /* @__PURE__ */ React25.createElement(EditPageLink, { ++ }) : null, config.footerEditLink ? /* @__PURE__ */ React29.createElement(EditPageLink, { + filepath: filepathWithName, + repository: config.docsRepositoryBase, + text: config.footerEditLink +- }) : null, config.tocExtraContent ? /* @__PURE__ */ React25.createElement("div", { ++ }) : null, config.tocExtraContent ? /* @__PURE__ */ React29.createElement("div", { + className: "pt-4 leading-4" + }, render_component_default(config.tocExtraContent, { locale })) : null) : null)); + } + + // src/misc/default.config.tsx +-import React26 from "react"; ++import React30 from "react"; + var defaultTheme = { + projectLink: "https://github.com/shuding/nextra", + docsRepositoryBase: "https://github.com/shuding/nextra", +@@ -1857,33 +1828,33 @@ var defaultTheme = { + footerText: `MIT ${new Date().getFullYear()} \xA9 Nextra.`, + footerEditLink: "Edit this page", + gitTimestamp: "Last updated on", +- logo: /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement("span", { ++ logo: /* @__PURE__ */ React30.createElement(React30.Fragment, null, /* @__PURE__ */ React30.createElement("span", { + className: "mr-2 font-extrabold hidden md:inline" +- }, "Nextra"), /* @__PURE__ */ React26.createElement("span", { ++ }, "Nextra"), /* @__PURE__ */ React30.createElement("span", { + className: "text-gray-600 font-normal hidden md:inline" + }, "The Next Docs Builder")), +- head: /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement("meta", { ++ head: /* @__PURE__ */ React30.createElement(React30.Fragment, null, /* @__PURE__ */ React30.createElement("meta", { + name: "msapplication-TileColor", + content: "#ffffff" +- }), /* @__PURE__ */ React26.createElement("meta", { ++ }), /* @__PURE__ */ React30.createElement("meta", { + httpEquiv: "Content-Language", + content: "en" +- }), /* @__PURE__ */ React26.createElement("meta", { ++ }), /* @__PURE__ */ React30.createElement("meta", { + name: "description", + content: "Nextra: the next docs builder" +- }), /* @__PURE__ */ React26.createElement("meta", { ++ }), /* @__PURE__ */ React30.createElement("meta", { + name: "twitter:card", + content: "summary_large_image" +- }), /* @__PURE__ */ React26.createElement("meta", { ++ }), /* @__PURE__ */ React30.createElement("meta", { + name: "twitter:site", + content: "@shuding_" +- }), /* @__PURE__ */ React26.createElement("meta", { ++ }), /* @__PURE__ */ React30.createElement("meta", { + property: "og:title", + content: "Nextra: the next docs builder" +- }), /* @__PURE__ */ React26.createElement("meta", { ++ }), /* @__PURE__ */ React30.createElement("meta", { + property: "og:description", + content: "Nextra: the next docs builder" +- }), /* @__PURE__ */ React26.createElement("meta", { ++ }), /* @__PURE__ */ React30.createElement("meta", { + name: "apple-mobile-web-app-title", + content: "Nextra" + })), +@@ -1892,7 +1863,7 @@ var defaultTheme = { + return "\u641C\u7D22\u6587\u6863..."; + return "Search documentation..."; + }, +- unstable_searchResultEmpty: () => /* @__PURE__ */ React26.createElement("span", { ++ unstable_searchResultEmpty: () => /* @__PURE__ */ React30.createElement("span", { + className: "block p-8 text-center text-gray-400 text-sm select-none" + }, "No results found.") + }; +@@ -1901,7 +1872,7 @@ var default_config_default = defaultTheme; + // src/utils/normalize-pages.tsx + import getTitle from "title"; + +-// src/misc/theme-context.tsx ++// src/misc/theme-context.ts + var theme_context_default = { + navbar: true, + sidebar: true, +@@ -2163,31 +2134,29 @@ if (typeof window !== "undefined") { + } + + // src/breadcrumb.tsx +-import React27 from "react"; +-import Link7 from "next/link"; ++import React31 from "react"; + import cn10 from "classnames"; + function Breadcrumb({ activePath }) { +- return /* @__PURE__ */ React27.createElement("div", { ++ return /* @__PURE__ */ React31.createElement("div", { + className: "nextra-breadcrumb text-sm font-normal flex mt-2.5 text-gray-500 transition-colors cursor-default overflow-hidden" + }, activePath.map((item, index) => { + const isLink = !item.children || item.withIndexPage; + const isActive = index === activePath.length - 1; +- return /* @__PURE__ */ React27.createElement(React27.Fragment, { +- key: item.route +- }, index ? /* @__PURE__ */ React27.createElement(arrow_right_default, { ++ return /* @__PURE__ */ React31.createElement(React31.Fragment, { ++ key: item.route + item.name ++ }, index > 0 && /* @__PURE__ */ React31.createElement(ArrowRightIcon, { + width: 14, + className: "mx-1 select-none" +- }) : null, /* @__PURE__ */ React27.createElement("div", { ++ }), /* @__PURE__ */ React31.createElement("div", { + key: item.route, + className: cn10("transition-colors hover:text-gray-900 dark:hover:text-gray-200", { + "text-gray-600 dark:text-gray-400 active": isActive, + "text-ellipsis whitespace-nowrap overflow-hidden min-w-[24px]": !isActive + }) +- }, isLink && !isActive ? /* @__PURE__ */ React27.createElement(Link7, { +- href: item.route +- }, /* @__PURE__ */ React27.createElement("a", { ++ }, isLink && !isActive ? /* @__PURE__ */ React31.createElement(Anchor, { ++ href: item.route, + className: "text-current no-underline" +- }, item.title)) : item.title)); ++ }, item.title) : item.title)); + })); + } + +@@ -2215,9 +2184,9 @@ var Body = ({ + const config = useConfig(); + const { locale } = useRouter8(); + const date = timestamp ? new Date(timestamp) : null; +- return /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(SkipNavContent, null), themeContext.layout === "full" ? /* @__PURE__ */ React28.createElement("article", { ++ return /* @__PURE__ */ React32.createElement(React32.Fragment, null, /* @__PURE__ */ React32.createElement(SkipNavContent, null), themeContext.layout === "full" ? /* @__PURE__ */ React32.createElement("article", { + className: "nextra-body full relative justify-center overflow-x-hidden pl-[max(env(safe-area-inset-left),1.5rem)] pr-[max(env(safe-area-inset-right),1.5rem)]" +- }, /* @__PURE__ */ React28.createElement(MDXTheme, null, children), date && config.gitTimestamp ? /* @__PURE__ */ React28.createElement("div", { ++ }, /* @__PURE__ */ React32.createElement(MDXTheme, null, children), date && config.gitTimestamp ? /* @__PURE__ */ React32.createElement("div", { + className: "text-xs text-right block text-gray-500 mt-12 mb-8 dark:text-gray-400 pointer-default" + }, typeof config.gitTimestamp === "string" ? config.gitTimestamp + " " + date.toLocaleDateString(locale, { + year: "numeric", +@@ -2226,15 +2195,15 @@ var Body = ({ + }) : render_component_default(config.gitTimestamp, { + timestamp: date, + locale +- })) : /* @__PURE__ */ React28.createElement("div", { ++ })) : /* @__PURE__ */ React32.createElement("div", { + className: "mt-16" +- }), navLinks) : themeContext.layout === "raw" ? /* @__PURE__ */ React28.createElement("div", { ++ }), navLinks) : themeContext.layout === "raw" ? /* @__PURE__ */ React32.createElement("div", { + className: "nextra-body full relative overflow-x-hidden expand" +- }, children) : /* @__PURE__ */ React28.createElement("article", { ++ }, children) : /* @__PURE__ */ React32.createElement("article", { + className: cn11("nextra-body relative pb-8 w-full justify-center max-w-full flex min-w-0 pr-[calc(env(safe-area-inset-right)-1.5rem)]", themeContext.typesetting ? "nextra-body-typesetting-" + themeContext.typesetting : "") +- }, /* @__PURE__ */ React28.createElement("main", { ++ }, /* @__PURE__ */ React32.createElement("main", { + className: "max-w-4xl px-6 md:px-8 pt-4 z-10 min-w-0 w-full" +- }, breadcrumb, /* @__PURE__ */ React28.createElement(MDXTheme, null, children), date && config.gitTimestamp ? /* @__PURE__ */ React28.createElement("div", { ++ }, breadcrumb, /* @__PURE__ */ React32.createElement(MDXTheme, null, children), date && config.gitTimestamp ? /* @__PURE__ */ React32.createElement("div", { + className: "text-xs text-right block text-gray-500 mt-12 mb-8 dark:text-gray-400 pointer-default" + }, typeof config.gitTimestamp === "string" ? config.gitTimestamp + " " + date.toLocaleDateString(locale, { + year: "numeric", +@@ -2243,7 +2212,7 @@ var Body = ({ + }) : render_component_default(config.gitTimestamp, { + timestamp: date, + locale +- })) : /* @__PURE__ */ React28.createElement("div", { ++ })) : /* @__PURE__ */ React32.createElement("div", { + className: "mt-16" + }), navLinks))); + }; +@@ -2283,30 +2252,30 @@ var Content = ({ + const hideSidebar = !themeContext.sidebar || themeContext.layout === "raw"; + const hideToc = !themeContext.toc || themeContext.layout === "raw"; + const headingArr = headings != null ? headings : []; +- return /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(Head, { ++ return /* @__PURE__ */ React32.createElement(React32.Fragment, null, /* @__PURE__ */ React32.createElement(Head, { + title, + locale, + meta +- }), /* @__PURE__ */ React28.createElement(MenuContext.Provider, { ++ }), /* @__PURE__ */ React32.createElement(MenuContext.Provider, { + value: { + menu, + setMenu, + defaultMenuCollapsed: !!config.defaultMenuCollapsed + } +- }, /* @__PURE__ */ React28.createElement("div", { ++ }, /* @__PURE__ */ React32.createElement("div", { + className: cn11("nextra-container main-container flex flex-col", { + rtl: isRTL, + "menu-active": menu + }) +- }, themeContext.navbar ? /* @__PURE__ */ React28.createElement(Navbar, { ++ }, themeContext.navbar ? /* @__PURE__ */ React32.createElement(Navbar, { + isRTL, + flatDirectories, + items: topLevelPageItems +- }) : null, /* @__PURE__ */ React28.createElement(ActiveAnchor, null, /* @__PURE__ */ React28.createElement("div", { ++ }) : null, /* @__PURE__ */ React32.createElement(ActiveAnchor, null, /* @__PURE__ */ React32.createElement("div", { + className: "max-w-[90rem] w-full mx-auto flex flex-1 items-stretch" +- }, /* @__PURE__ */ React28.createElement("div", { ++ }, /* @__PURE__ */ React32.createElement("div", { + className: "flex flex-1 w-full" +- }, /* @__PURE__ */ React28.createElement(Sidebar, { ++ }, /* @__PURE__ */ React32.createElement(Sidebar, { + directories: docsDirectories, + flatDirectories, + fullDirectories: directories, +@@ -2314,23 +2283,23 @@ var Content = ({ + isRTL, + asPopover: activeType === "page" || hideSidebar, + includePlaceholder: themeContext.layout === "default" +- }), activeType === "page" || hideToc || themeContext.layout !== "default" ? themeContext.layout === "full" || themeContext.layout === "raw" ? null : /* @__PURE__ */ React28.createElement("div", { ++ }), console.log("(activeType === 'page'", activeType === "page", "hideSidebar", hideSidebar), activeType === "page" || hideToc || themeContext.layout !== "default" ? themeContext.layout === "full" || themeContext.layout === "raw" ? null : /* @__PURE__ */ React32.createElement("div", { + className: "nextra-toc w-64 hidden xl:block text-sm px-4 order-last flex-shrink-0" +- }) : /* @__PURE__ */ React28.createElement(ToC, { ++ }) : /* @__PURE__ */ React32.createElement(ToC, { + headings: config.floatTOC ? headingArr : null, + filepathWithName +- }), /* @__PURE__ */ React28.createElement(Body, { ++ }), /* @__PURE__ */ React32.createElement(Body, { + themeContext, +- breadcrumb: activeType === "page" ? null : themeContext.breadcrumb ? /* @__PURE__ */ React28.createElement(Breadcrumb, { ++ breadcrumb: activeType === "page" ? null : themeContext.breadcrumb ? /* @__PURE__ */ React32.createElement(Breadcrumb, { + activePath + }) : null, +- navLinks: activeType === "page" ? null : themeContext.pagination ? /* @__PURE__ */ React28.createElement(NavLinks, { ++ navLinks: activeType === "page" ? null : themeContext.pagination ? /* @__PURE__ */ React32.createElement(NavLinks, { + flatDirectories: flatDocsDirectories, + currentIndex: activeIndex, + isRTL + }) : null, + timestamp +- }, children)))), themeContext.footer && config.footer ? /* @__PURE__ */ React28.createElement(footer_default, { ++ }, children)))), themeContext.footer && config.footer ? /* @__PURE__ */ React32.createElement(footer_default, { + menu: activeType === "page" || hideSidebar + }) : null))); + }; +@@ -2345,16 +2314,16 @@ var createLayout = (opts, _config) => { + }; + Page.getLayout = (page) => { + layoutUsed = true; +- return /* @__PURE__ */ React28.createElement(ThemeConfigContext.Provider, { ++ return /* @__PURE__ */ React32.createElement(ThemeConfigContext.Provider, { + value: extendedConfig +- }, /* @__PURE__ */ React28.createElement(ThemeProvider, __spreadValues({ ++ }, /* @__PURE__ */ React32.createElement(ThemeProvider, __spreadValues({ + attribute: "class", + disableTransitionOnChange: true + }, { + defaultTheme: extendedConfig.nextThemes.defaultTheme, + storageKey: extendedConfig.nextThemes.storageKey, + forcedTheme: extendedConfig.nextThemes.forcedTheme +- }), /* @__PURE__ */ React28.createElement(Content, __spreadValues({}, opts), page))); ++ }), /* @__PURE__ */ React32.createElement(Content, __spreadValues({}, opts), page))); + }; + return Page; + }; +diff --git a/node_modules/nextra-theme-docs/dist/misc/theme.js b/node_modules/nextra-theme-docs/dist/misc/theme.js +new file mode 100644 +index 0000000..f4fe595 +--- /dev/null ++++ b/node_modules/nextra-theme-docs/dist/misc/theme.js +@@ -0,0 +1,412 @@ ++var __defProp = Object.defineProperty; ++var __defProps = Object.defineProperties; ++var __getOwnPropDescs = Object.getOwnPropertyDescriptors; ++var __getOwnPropSymbols = Object.getOwnPropertySymbols; ++var __hasOwnProp = Object.prototype.hasOwnProperty; ++var __propIsEnum = Object.prototype.propertyIsEnumerable; ++var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; ++var __spreadValues = (a, b) => { ++ for (var prop in b || (b = {})) ++ if (__hasOwnProp.call(b, prop)) ++ __defNormalProp(a, prop, b[prop]); ++ if (__getOwnPropSymbols) ++ for (var prop of __getOwnPropSymbols(b)) { ++ if (__propIsEnum.call(b, prop)) ++ __defNormalProp(a, prop, b[prop]); ++ } ++ return a; ++}; ++var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); ++var __objRest = (source, exclude) => { ++ var target = {}; ++ for (var prop in source) ++ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0) ++ target[prop] = source[prop]; ++ if (source != null && __getOwnPropSymbols) ++ for (var prop of __getOwnPropSymbols(source)) { ++ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop)) ++ target[prop] = source[prop]; ++ } ++ return target; ++}; ++ ++// src/misc/theme.tsx ++import React8, { ++ useEffect as useEffect2, ++ useRef as useRef2, ++ useState as useState2, ++ useContext as useContext2 ++} from "react"; ++import "intersection-observer"; ++ ++// src/misc/active-anchor.tsx ++import React, { createContext, useContext, useState } from "react"; ++var ActiveAnchorContext = createContext({}); ++var ActiveAnchorSetterContext = createContext((s) => s); ++var useActiveAnchorSet = () => useContext(ActiveAnchorSetterContext); ++ ++// src/misc/theme.tsx ++import { MDXProvider } from "@mdx-js/react"; ++ ++// src/components/collapse.tsx ++import React2, { useRef, useEffect } from "react"; ++function Collapse({ ++ children, ++ open ++}) { ++ const containerRef = useRef(null); ++ const innerRef = useRef(null); ++ const animationRef = useRef(); ++ const initialRender = useRef(true); ++ const initialState = useRef(open); ++ useEffect(() => { ++ if (initialRender.current) ++ return; ++ if (animationRef.current) { ++ clearTimeout(animationRef.current); ++ } ++ if (open) { ++ const container = containerRef.current; ++ const inner = innerRef.current; ++ if (container && inner) { ++ const contentHeight = innerRef.current.clientHeight; ++ container.style.maxHeight = contentHeight + "px"; ++ container.classList.remove("duration-500"); ++ container.classList.add("duration-300"); ++ inner.style.opacity = "1"; ++ animationRef.current = setTimeout(() => { ++ const container2 = containerRef.current; ++ if (container2) { ++ container2.style.removeProperty("max-height"); ++ } ++ }, 300); ++ } ++ } else { ++ const container = containerRef.current; ++ const inner = innerRef.current; ++ if (container && inner) { ++ const contentHeight = innerRef.current.clientHeight; ++ container.style.maxHeight = contentHeight + "px"; ++ container.classList.remove("duration-300"); ++ container.classList.add("duration-500"); ++ inner.style.opacity = "0"; ++ setTimeout(() => { ++ const container2 = containerRef.current; ++ if (container2) { ++ container2.style.maxHeight = "0px"; ++ } ++ }); ++ } ++ } ++ }, [open]); ++ useEffect(() => { ++ initialRender.current = false; ++ }, []); ++ return /* @__PURE__ */ React2.createElement("div", { ++ ref: containerRef, ++ className: "transition-all ease-in-out duration-300 overflow-hidden transform-gpu motion-reduce:transition-none", ++ style: { ++ maxHeight: initialState.current ? void 0 : 0 ++ } ++ }, /* @__PURE__ */ React2.createElement("div", { ++ ref: innerRef, ++ className: "nextra-collapse-content transition-opacity ease-in-out duration-500 overflow-hidden transform-gpu motion-reduce:transition-none", ++ style: { ++ opacity: initialState.current ? 1 : 0 ++ } ++ }, children)); ++} ++ ++// src/components/tabs.tsx ++import React3 from "react"; ++import cn from "classnames"; ++import { Tab as HeadlessTab } from "@headlessui/react"; ++function Tabs({ ++ items, ++ selectedIndex, ++ defaultIndex, ++ onChange, ++ children ++}) { ++ return /* @__PURE__ */ React3.createElement(HeadlessTab.Group, { ++ selectedIndex, ++ defaultIndex, ++ onChange ++ }, /* @__PURE__ */ React3.createElement("div", { ++ className: "p-2 -m-2 overscroll-x-contain overflow-x-auto overflow-y-hidden no-scrollbar" ++ }, /* @__PURE__ */ React3.createElement(HeadlessTab.List, { ++ className: "flex mt-4 pb-[1px] border-b border-gray-200 dark:border-neutral-800 w-max min-w-full" ++ }, items.map((item, index) => { ++ const disabled = !!(item && typeof item === "object" && "disabled" in item && item.disabled); ++ return /* @__PURE__ */ React3.createElement(HeadlessTab, { ++ key: index, ++ disabled, ++ className: ({ selected }) => cn("p-2 mr-2 leading-5 font-medium text-md transition-colors", "select-none border-b-2 mb-[-2px] focus:outline-none focus-visible:ring ring-offset-2 rounded-[1px]", selected ? "text-primary-500 border-primary-500" : "text-gray-600 dark:text-gray-200 hover:border-gray-200 dark:hover:border-neutral-800 border-transparent hover:text-black dark:hover:text-white", disabled ? "pointer-events-none text-gray-400 dark:text-neutral-600" : "") ++ }, item && typeof item === "object" && "label" in item ? item.label : item); ++ }))), /* @__PURE__ */ React3.createElement(HeadlessTab.Panels, null, children)); ++} ++function Tab({ children }) { ++ return /* @__PURE__ */ React3.createElement(HeadlessTab.Panel, { ++ className: "focus:outline-none focus-visible:ring" ++ }, children); ++} ++ ++// src/bleed.tsx ++import React4 from "react"; ++import cn2 from "classnames"; ++var Bleed = ({ ++ full, ++ children ++}) => { ++ return /* @__PURE__ */ React4.createElement("div", { ++ className: cn2("bleed relative mt-6 -mx-6 md:-mx-8 2xl:-mx-24", { full }) ++ }, children); ++}; ++var bleed_default = Bleed; ++ ++// src/callout.tsx ++import React5 from "react"; ++var themes = { ++ default: "bg-orange-50 border border-orange-100 text-orange-800 dark:text-orange-300 dark:bg-orange-400 dark:border-orange-400 dark:bg-opacity-20 dark:border-opacity-30", ++ error: "bg-red-100 border border-red-200 text-red-900 dark:text-red-200 dark:bg-red-900 dark:bg-opacity-30 dark:border-opacity-30", ++ info: "bg-blue-100 border border-blue-200 text-blue-900 dark:text-blue-200 dark:bg-blue-900 dark:bg-opacity-30 dark:border-opacity-30", ++ warning: "bg-yellow-50 border border-yellow-100 text-yellow-900 dark:text-yellow-200 dark:bg-yellow-700 dark:bg-opacity-30" ++}; ++var Callout = ({ ++ children, ++ type = "default", ++ emoji = "\u{1F4A1}" ++}) => { ++ return /* @__PURE__ */ React5.createElement("div", { ++ className: `${themes[type]} flex rounded-lg nextra-callout mt-6` ++ }, /* @__PURE__ */ React5.createElement("div", { ++ className: "pl-3 pr-2 py-2 select-none text-xl", ++ style: { ++ fontFamily: '"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"' ++ } ++ }, emoji), /* @__PURE__ */ React5.createElement("div", { ++ className: "pr-4 py-2" ++ }, children)); ++}; ++var callout_default = Callout; ++ ++// src/anchor.tsx ++import React7 from "react"; ++import NextLink from "next/link"; ++ ++// src/config.ts ++import React6 from "react"; ++var ThemeConfigContext = React6.createContext({ ++ newNextLinkBehavior: false ++}); ++var useConfig = () => React6.useContext(ThemeConfigContext); ++ ++// src/anchor.tsx ++function Anchor(_a) { ++ var _b = _a, { ++ href = "", ++ children ++ } = _b, props = __objRest(_b, [ ++ "href", ++ "children" ++ ]); ++ const config = useConfig(); ++ if (!href) { ++ return /* @__PURE__ */ React7.createElement("a", __spreadValues({}, props), children); ++ } ++ const isExternal = href.startsWith("https://"); ++ if (isExternal) { ++ return /* @__PURE__ */ React7.createElement("a", __spreadValues({ ++ target: "_blank", ++ rel: "noreferrer", ++ href ++ }, props), children); ++ } ++ if (config.newNextLinkBehavior) { ++ return /* @__PURE__ */ React7.createElement(NextLink, __spreadValues({ ++ href ++ }, props), children); ++ } ++ return /* @__PURE__ */ React7.createElement(NextLink, { ++ href, ++ passHref: true ++ }, /* @__PURE__ */ React7.createElement("a", __spreadValues({}, props), children)); ++} ++ ++// src/misc/theme.tsx ++var observer; ++var setActiveAnchor; ++var slugs = /* @__PURE__ */ new WeakMap(); ++if (typeof window !== "undefined") { ++ observer = observer || new IntersectionObserver((entries) => { ++ const headers = []; ++ for (const entry of entries) { ++ if ((entry == null ? void 0 : entry.rootBounds) && slugs.has(entry.target)) { ++ const [slug, index] = slugs.get(entry.target); ++ const aboveHalfViewport = entry.boundingClientRect.y + entry.boundingClientRect.height <= entry.rootBounds.y + entry.rootBounds.height; ++ const insideHalfViewport = entry.intersectionRatio > 0; ++ headers.push([slug, index, aboveHalfViewport, insideHalfViewport]); ++ } ++ } ++ setActiveAnchor((f) => { ++ const ret = __spreadValues({}, f); ++ for (const header of headers) { ++ ret[header[0]] = { ++ index: header[1], ++ aboveHalfViewport: header[2], ++ insideHalfViewport: header[3] ++ }; ++ } ++ let activeSlug = ""; ++ let smallestIndexInViewport = Infinity; ++ let largestIndexAboveViewport = -1; ++ for (let s in ret) { ++ ret[s].isActive = false; ++ if (ret[s].insideHalfViewport && ret[s].index < smallestIndexInViewport) { ++ smallestIndexInViewport = ret[s].index; ++ activeSlug = s; ++ } ++ if (smallestIndexInViewport === Infinity && ret[s].aboveHalfViewport && ret[s].index > largestIndexAboveViewport) { ++ largestIndexAboveViewport = ret[s].index; ++ activeSlug = s; ++ } ++ } ++ if (ret[activeSlug]) ++ ret[activeSlug].isActive = true; ++ return ret; ++ }); ++ }, { ++ rootMargin: "0px 0px -50%", ++ threshold: [0, 1] ++ }); ++} ++var createHeaderLink = (Tag) => function HeaderLink(_a) { ++ var _b = _a, { ++ children, ++ id: slug ++ } = _b, props = __objRest(_b, [ ++ "children", ++ "id" ++ ]); ++ setActiveAnchor = useActiveAnchorSet(); ++ const obRef = useRef2(null); ++ useEffect2(() => { ++ const ref = obRef; ++ if (!ref.current) ++ return; ++ slugs.set(ref.current, [slug, Number(Tag[1]) - 1]); ++ if (ref.current) ++ observer.observe(ref.current); ++ return () => { ++ observer.disconnect(); ++ slugs.delete(ref.current); ++ setActiveAnchor((f) => { ++ const ret = __spreadValues({}, f); ++ delete ret[slug]; ++ return ret; ++ }); ++ }; ++ }, []); ++ return /* @__PURE__ */ React8.createElement(Tag, __spreadValues({}, props), /* @__PURE__ */ React8.createElement("span", { ++ className: "subheading-anchor", ++ id: slug, ++ ref: obRef ++ }), /* @__PURE__ */ React8.createElement("a", { ++ href: "#" + slug, ++ className: "anchor text-current no-underline no-outline" ++ }, children, /* @__PURE__ */ React8.createElement("span", { ++ className: "anchor-icon", ++ "aria-hidden": true ++ }, "#"))); ++}; ++var Table = ({ children }) => { ++ return /* @__PURE__ */ React8.createElement("div", { ++ className: "table-container" ++ }, /* @__PURE__ */ React8.createElement("table", null, children)); ++}; ++var DetailsContext = React8.createContext(() => { ++}); ++var findSummary = (children) => { ++ let summary = null; ++ let restChildren = []; ++ React8.Children.forEach(children, (child, index) => { ++ var _a; ++ if (child && child.type === Summary) { ++ summary = summary || child; ++ return; ++ } ++ let c = child; ++ if (!summary && typeof child === "object" && child && child.type !== Details && "props" in child && child.props) { ++ const result = findSummary(child.props.children); ++ summary = summary || result[0]; ++ c = React8.cloneElement(child, __spreadProps(__spreadValues({}, child.props), { ++ children: ((_a = result[1]) == null ? void 0 : _a.length) ? result[1] : void 0, ++ key: index ++ })); ++ } ++ restChildren.push(c); ++ }); ++ return [summary, restChildren]; ++}; ++var Details = (_a) => { ++ var _b = _a, { ++ children, ++ open ++ } = _b, props = __objRest(_b, [ ++ "children", ++ "open" ++ ]); ++ const [openState, setOpen] = useState2(!!open); ++ const ref = useRef2(null); ++ const [summary, restChildren] = findSummary(children); ++ return /* @__PURE__ */ React8.createElement("details", __spreadValues(__spreadProps(__spreadValues({}, props), { ++ ref, ++ open: true ++ }), openState && { "data-open": "" }), /* @__PURE__ */ React8.createElement(DetailsContext.Provider, { ++ value: setOpen ++ }, summary), /* @__PURE__ */ React8.createElement(Collapse, { ++ open: openState ++ }, restChildren)); ++}; ++var Summary = (_a) => { ++ var _b = _a, { ++ children ++ } = _b, props = __objRest(_b, [ ++ "children" ++ ]); ++ const setOpen = useContext2(DetailsContext); ++ return /* @__PURE__ */ React8.createElement("summary", __spreadProps(__spreadValues({}, props), { ++ onClick: (e) => { ++ e.preventDefault(); ++ setOpen((v) => !v); ++ } ++ }), children); ++}; ++var components = { ++ h2: createHeaderLink("h2"), ++ h3: createHeaderLink("h3"), ++ h4: createHeaderLink("h4"), ++ h5: createHeaderLink("h5"), ++ h6: createHeaderLink("h6"), ++ a: Anchor, ++ table: Table, ++ details: Details, ++ summary: Summary, ++ Nextra: { ++ Bleed: bleed_default, ++ Callout: callout_default, ++ Tabs, ++ Tab ++ } ++}; ++var MDXTheme = ({ ++ children ++}) => { ++ return /* @__PURE__ */ React8.createElement(MDXProvider, { ++ components ++ }, children); ++}; ++export { ++ MDXTheme, ++ components ++}; +diff --git a/node_modules/nextra-theme-docs/dist/types.d.ts b/node_modules/nextra-theme-docs/dist/types.d.ts +new file mode 100755 +index 0000000..b7660ac +--- /dev/null ++++ b/node_modules/nextra-theme-docs/dist/types.d.ts +@@ -0,0 +1,77 @@ ++/// ++export interface DocsThemeConfig { ++ docsRepositoryBase?: string; ++ titleSuffix?: string | React.FC<{ ++ locale: string; ++ config: DocsThemeConfig; ++ title: string; ++ meta: Record; ++ }>; ++ nextLinks?: boolean; ++ prevLinks?: boolean; ++ search?: boolean; ++ darkMode?: boolean; ++ /** ++ * A subset of configurations for https://github.com/pacocoursey/next-themes#themeprovider ++ * - defaultTheme ++ * - storageKey ++ * - forcedTheme ++ */ ++ nextThemes?: object; ++ defaultMenuCollapsed?: boolean; ++ font?: boolean; ++ footer?: boolean; ++ footerText?: string; ++ footerEditLink?: string; ++ feedbackLink?: string; ++ feedbackLabels?: string; ++ head?: React.ReactNode | React.FC<{ ++ locale: string; ++ config: DocsThemeConfig; ++ title: string; ++ meta: Record; ++ }>; ++ logo?: React.ReactNode; ++ direction?: string; ++ i18n?: { ++ locale: string; ++ text: string; ++ direction: string; ++ }[]; ++ customSearch?: boolean; ++ searchPlaceholder?: string | ((props: { ++ locale?: string; ++ }) => string); ++ projectLink?: string; ++ github?: string; ++ projectLinkIcon?: React.FC<{ ++ locale: string; ++ }>; ++ projectChatLink?: string; ++ projectChatLinkIcon?: React.FC<{ ++ locale: string; ++ }>; ++ sidebarSubtitle?: React.FC<{ ++ title: string; ++ }>; ++ floatTOC?: boolean; ++ banner?: React.FC<{ ++ locale: string; ++ }>; ++ bannerKey?: string; ++ gitTimestamp?: string | React.FC<{ ++ locale: string; ++ timestamp: Date; ++ }>; ++ tocExtraContent?: React.FC<{ ++ locale: string; ++ }>; ++ unstable_faviconGlyph?: string; ++ unstable_flexsearch?: boolean; ++ unstable_searchResultEmpty?: React.ReactNode | React.FC<{ ++ locale: string; ++ config: DocsThemeConfig; ++ title: string; ++ meta: Record; ++ }>; ++} +diff --git a/node_modules/nextra-theme-docs/package.json b/node_modules/nextra-theme-docs/package.json +index 98b2f56..b475ee3 100644 +--- a/node_modules/nextra-theme-docs/package.json ++++ b/node_modules/nextra-theme-docs/package.json +@@ -25,6 +25,9 @@ + }, + "./tabs": { + "import": "./dist/components/tabs.js" ++ }, ++ "./theme": { ++ "import": "./dist/misc/theme.js" + } + }, + "scripts": { +@@ -33,7 +36,7 @@ + "build:layout": "node scripts/build.js", + "build:tailwind": "cross-env NODE_ENV=production pnpm postcss src/styles.css -o style.css --verbose", + "types": "tsc -p tsconfig.types.json", +- "dev:layout": "node scripts/dev.js", ++ "dev:layout": "node scripts/build.js --dev", + "dev:tailwind": "cross-env TAILWIND_MODE=watch pnpm postcss src/styles.css -o style.css --watch", + "prepublishOnly": "rm -rf dist && pnpm build", + "test": "vitest --run" +@@ -48,7 +51,7 @@ + "github-slugger": "^1.4.0", + "intersection-observer": "^0.12.0", + "match-sorter": "^4.2.0", +- "next-themes": "^0.2.0-beta.2", ++ "next-themes": "^0.2.0", + "parse-git-url": "^1.0.1", + "scroll-into-view-if-needed": "^2.2.29", + "title": "^3.4.2" +diff --git a/node_modules/nextra-theme-docs/style.css b/node_modules/nextra-theme-docs/style.css +old mode 100644 +new mode 100755 +index 9ccd243..1ed4b49 +--- a/node_modules/nextra-theme-docs/style.css ++++ b/node_modules/nextra-theme-docs/style.css +@@ -1 +1 @@ +-/*! tailwindcss v3.0.23 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder, textarea::-moz-placeholder{opacity:1;color:#9ca3af}input:-ms-input-placeholder, textarea:-ms-input-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:after,:before{--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,0.5);--tw-ring-offset-shadow:0 0 transparent;--tw-ring-shadow:0 0 transparent;--tw-shadow:0 0 transparent;--tw-shadow-colored:0 0 transparent;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }html{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:16px;font-feature-settings:"rlig" 1,"calt" 1,"ss01" 1,"ss06" 1;-webkit-tap-highlight-color:transparent}body{width:100%;--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.dark body{--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity));color:rgb(243 244 246/var(--tw-text-opacity))}.dark body,a{--tw-text-opacity:1}a{color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity));-webkit-text-decoration-line:underline;text-decoration-line:underline;text-underline-position:under;text-decoration-thickness:from-font}p{line-height:1.75rem}.table-container:not(:first-child),blockquote:not(:first-child),p:not(:first-child){margin-top:1.5rem}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:-webkit-sticky;position:sticky}.inset-y-0{top:0;bottom:0}.right-0{right:0}.top-full{top:100%}.top-0{top:0}.left-0{left:0}.bottom-\[130\%\]{bottom:130%}.top-16{top:4rem}.top-10{top:2.5rem}.bottom-0{bottom:0}.z-10{z-index:10}.z-20{z-index:20}.z-\[15\]{z-index:15}.z-\[1\]{z-index:1}.order-last{order:9999}.m-0{margin:0}.-m-4{margin:-1rem}.-m-2{margin:-.5rem}.-mx-6{margin-left:-1.5rem;margin-right:-1.5rem}.mx-1{margin-left:.25rem;margin-right:.25rem}.mx-2\.5{margin-left:.625rem;margin-right:.625rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-auto{margin-left:auto;margin-right:auto}.my-4{margin-top:1rem;margin-bottom:1rem}.mx-4{margin-left:1rem;margin-right:1rem}.mt-6{margin-top:1.5rem}.mt-2\.5{margin-top:.625rem}.mt-2{margin-top:.5rem}.mb-2{margin-bottom:.5rem}.mt-1{margin-top:.25rem}.-ml-1{margin-left:-.25rem}.mr-2{margin-right:.5rem}.ml-2{margin-left:.5rem}.mr-1{margin-right:.25rem}.ml-1{margin-left:.25rem}.mb-8{margin-bottom:2rem}.mt-12{margin-top:3rem}.mt-16{margin-top:4rem}.-ml-2{margin-left:-.5rem}.mt-5{margin-top:1.25rem}.mb-4{margin-bottom:1rem}.ml-6{margin-left:1.5rem}.mr-5{margin-right:1.25rem}.ml-0{margin-left:0}.-mr-4{margin-right:-1rem}.mt-8{margin-top:2rem}.mt-4{margin-top:1rem}.mb-\[-2px\]{margin-bottom:-2px}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.hidden{display:none}.h-5{height:1.25rem}.h-10{height:2.5rem}.h-4{height:1rem}.h-full{height:100%}.h-16{height:4rem}.h-7{height:1.75rem}.h-\[18px\]{height:18px}.h-0{height:0}.h-\[calc\(100vh-4rem\)\]{height:calc(100vh - 4rem)}.max-h-64{max-height:16rem}.max-h-\[calc\(100vh-4rem-env\(safe-area-inset-bottom\)\)\]{max-height:calc(100vh - 4rem - env(safe-area-inset-bottom))}.min-h-\[calc\(100vh-4rem-61px\)\]{min-height:calc(100vh - 4rem - 61px)}.w-full{width:100%}.w-5{width:1.25rem}.w-64{width:16rem}.w-8{width:2rem}.w-4{width:1rem}.w-max{width:-webkit-max-content;width:-moz-max-content;width:max-content}.min-w-\[24px\]{min-width:24px}.min-w-0{min-width:0}.min-w-full{min-width:100%}.min-w-\[18px\]{min-width:18px}.max-w-\[90rem\]{max-width:90rem}.max-w-full{max-width:100%}.max-w-4xl{max-width:56rem}.flex-1{flex:1 1 0%}.flex-auto{flex:1 1 auto}.flex-shrink-0{flex-shrink:0}.grow-0{flex-grow:0}.origin-center{transform-origin:center}.rotate-180{--tw-rotate:180deg}.rotate-90,.rotate-180{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-90{--tw-rotate:90deg}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform-gpu{transform:translate3d(var(--tw-translate-x),var(--tw-translate-y),0) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform-none{transform:none}@-webkit-keyframes spin{to{transform:rotate(1turn)}}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{-webkit-animation:spin 1s linear infinite;animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.resize{resize:both}.scroll-my-6{scroll-margin-top:1.5rem;scroll-margin-bottom:1.5rem}.scroll-py-6{scroll-padding-top:1.5rem;scroll-padding-bottom:1.5rem}.list-none{list-style-type:none}.list-disc{list-style-type:disc}.list-decimal{list-style-type:decimal}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-1{gap:.25rem}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.self-start{align-self:flex-start}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-hidden{overflow-y:hidden}.overscroll-contain{-ms-scroll-chaining:none;overscroll-behavior:contain}.overscroll-x-contain{overscroll-behavior-x:contain}.truncate{overflow:hidden;white-space:nowrap}.text-ellipsis,.truncate{text-overflow:ellipsis}.whitespace-nowrap{white-space:nowrap}.break-words{overflow-wrap:break-word}.rounded-lg{border-radius:.5rem}.rounded{border-radius:.25rem}.rounded-xl{border-radius:.75rem}.rounded-md{border-radius:.375rem}.rounded-sm{border-radius:.125rem}.rounded-none{border-radius:0}.rounded-\[1px\]{border-radius:1px}.border{border-width:1px}.border-t{border-top-width:1px}.border-b{border-bottom-width:1px}.border-l-2{border-left-width:2px}.border-r-2{border-right-width:2px}.border-b-2{border-bottom-width:2px}.border-none{border-style:none}.border-orange-100{--tw-border-opacity:1;border-color:rgb(255 237 213/var(--tw-border-opacity))}.border-red-200{--tw-border-opacity:1;border-color:rgb(254 202 202/var(--tw-border-opacity))}.border-blue-200{--tw-border-opacity:1;border-color:rgb(191 219 254/var(--tw-border-opacity))}.border-yellow-100{--tw-border-opacity:1;border-color:rgb(254 249 195/var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.border-primary-500{--tw-border-opacity:1;border-color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-border-opacity))}.border-primary-900{--tw-border-opacity:1;border-color:hsl(var(--nextra-primary-hue) 100% 24%/var(--tw-border-opacity))}.border-current{border-color:currentColor}.border-gray-900{--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}.border-gray-600{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}.border-transparent{border-color:transparent}.border-primary-100{--tw-border-opacity:1;border-color:hsl(var(--nextra-primary-hue) 100% 94%/var(--tw-border-opacity))}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-black{--tw-border-opacity:1;border-color:rgb(0 0 0/var(--tw-border-opacity))}.border-white{--tw-border-opacity:1;border-color:rgb(255 255 255/var(--tw-border-opacity))}.border-neutral-800{--tw-border-opacity:1;border-color:rgb(38 38 38/var(--tw-border-opacity))}.border-opacity-20{--tw-border-opacity:0.2}.border-opacity-5{--tw-border-opacity:0.05}.bg-orange-50{--tw-bg-opacity:1;background-color:rgb(255 247 237/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity))}.bg-blue-100{--tw-bg-opacity:1;background-color:rgb(219 234 254/var(--tw-bg-opacity))}.bg-yellow-50{--tw-bg-opacity:1;background-color:rgb(254 252 232/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-neutral-900{--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity))}.bg-transparent{background-color:transparent}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-primary-50{--tw-bg-opacity:1;background-color:hsl(var(--nextra-primary-hue) 100% 97%/var(--tw-bg-opacity))}.bg-dark{--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity))}.bg-gray-400{--tw-bg-opacity:1;background-color:rgb(156 163 175/var(--tw-bg-opacity))}.bg-primary-750{--tw-bg-opacity:1;background-color:hsl(var(--nextra-primary-hue) 100% 35%/var(--tw-bg-opacity))}.bg-primary-800{--tw-bg-opacity:1;background-color:hsl(var(--nextra-primary-hue) 100% 32%/var(--tw-bg-opacity))}.bg-primary-700{--tw-bg-opacity:1;background-color:hsl(var(--nextra-primary-hue) 100% 39%/var(--tw-bg-opacity))}.bg-primary-400{--tw-bg-opacity:1;background-color:hsl(var(--nextra-primary-hue) 100% 66%/var(--tw-bg-opacity))}.bg-primary-500{--tw-bg-opacity:1;background-color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-bg-opacity))}.bg-opacity-\[\.03\]{--tw-bg-opacity:.03}.bg-opacity-\[\.85\]{--tw-bg-opacity:.85}.bg-opacity-5{--tw-bg-opacity:0.05}.bg-opacity-10{--tw-bg-opacity:0.1}.p-8{padding:2rem}.p-4{padding:1rem}.p-2{padding:.5rem}.p-0{padding:0}.p-\[2px\]{padding:2px}.p-1{padding:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-0{padding-left:0;padding-right:0}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.px-4{padding-left:1rem;padding-right:1rem}.py-12{padding-top:3rem;padding-bottom:3rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pl-3{padding-left:.75rem}.pr-2{padding-right:.5rem}.pr-4{padding-right:1rem}.pb-1\.5{padding-bottom:.375rem}.pb-1{padding-bottom:.25rem}.pr-1\.5{padding-right:.375rem}.pr-1{padding-right:.25rem}.pt-8{padding-top:2rem}.pb-\[env\(safe-area-inset-bottom\)\]{padding-bottom:env(safe-area-inset-bottom)}.pl-\[max\(env\(safe-area-inset-left\)\2c 1\.5rem\)\]{padding-left:max(env(safe-area-inset-left),1.5rem)}.pr-\[max\(env\(safe-area-inset-right\)\2c 1\.5rem\)\]{padding-right:max(env(safe-area-inset-right),1.5rem)}.pb-8{padding-bottom:2rem}.pr-\[calc\(env\(safe-area-inset-right\)-1\.5rem\)\]{padding-right:calc(env(safe-area-inset-right) - 1.5rem)}.pt-4{padding-top:1rem}.pl-10{padding-left:2.5rem}.pr-9{padding-right:2.25rem}.pr-3{padding-right:.75rem}.pl-\[calc\(env\(safe-area-inset-left\)-1\.5rem\)\]{padding-left:calc(env(safe-area-inset-left) - 1.5rem)}.pb-4{padding-bottom:1rem}.pt-16{padding-top:4rem}.pl-6{padding-left:1.5rem}.pl-2{padding-left:.5rem}.pr-6{padding-right:1.5rem}.pl-0{padding-left:0}.pb-\[1px\]{padding-bottom:1px}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-sm{font-size:.875rem}.text-xl{font-size:1.25rem}.text-xs{font-size:.75rem}.text-base{font-size:1rem}.text-4xl{font-size:2.25rem}.text-3xl{font-size:1.875rem}.text-2xl{font-size:1.5rem}.text-lg{font-size:1.125rem}.font-normal{font-weight:400}.font-semibold{font-weight:600}.font-medium{font-weight:500}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.leading-5{line-height:1.25rem}.leading-\[1\.35rem\]{line-height:1.35rem}.leading-tight{line-height:1.25}.leading-4{line-height:1rem}.tracking-tight{letter-spacing:-.015em}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.text-current{color:currentColor}.text-orange-800{--tw-text-opacity:1;color:rgb(154 52 18/var(--tw-text-opacity))}.text-red-900{--tw-text-opacity:1;color:rgb(127 29 29/var(--tw-text-opacity))}.text-blue-900{--tw-text-opacity:1;color:rgb(30 58 138/var(--tw-text-opacity))}.text-yellow-900{--tw-text-opacity:1;color:rgb(113 63 18/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-slate-50{--tw-text-opacity:1;color:rgb(248 250 252/var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.text-primary-500{--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity))}.text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.text-gray-50{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.\!text-gray-600{--tw-text-opacity:1!important;color:rgb(75 85 99/var(--tw-text-opacity))!important}.text-primary-1000{--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 12%/var(--tw-text-opacity))}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.text-gray-100{--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.underline{-webkit-text-decoration-line:underline;text-decoration-line:underline}.no-underline{-webkit-text-decoration-line:none;text-decoration-line:none}.decoration-primary-400{-webkit-text-decoration-color:hsl(var(--nextra-primary-hue) 100% 66%);text-decoration-color:hsl(var(--nextra-primary-hue) 100% 66%)}.subpixel-antialiased{-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}.opacity-100{opacity:1}.opacity-0{opacity:0}.opacity-25{opacity:.25}.opacity-75{opacity:.75}.opacity-80{opacity:.8}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,0.1),0 8px 10px -6px rgba(0,0,0,0.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color)}.shadow-md,.shadow-xl{box-shadow:var(--tw-ring-offset-shadow,0 0 transparent),var(--tw-ring-shadow,0 0 transparent),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,0.1),0 2px 4px -2px rgba(0,0,0,0.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,0.1),0 4px 6px -4px rgba(0,0,0,0.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-\[0_-12px_16px_white\],.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 transparent),var(--tw-ring-shadow,0 0 transparent),var(--tw-shadow)}.shadow-\[0_-12px_16px_white\]{--tw-shadow:0 -12px 16px #fff;--tw-shadow-colored:0 -12px 16px var(--tw-shadow-color)}.shadow-\[0_0_0_3px_rgba\(0\2c 0\2c 0\2c 0\.3\)\]{--tw-shadow:0 0 0 3px rgba(0,0,0,0.3);--tw-shadow-colored:0 0 0 3px var(--tw-shadow-color)}.shadow-\[0_0_0_3px_rgba\(0\2c 0\2c 0\2c 0\.3\)\],.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 transparent),var(--tw-ring-shadow,0 0 transparent),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,0.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.shadow-primary-800\/10{--tw-shadow-color:hsl(var(--nextra-primary-hue) 100% 32%/0.1);--tw-shadow:var(--tw-shadow-colored)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring,.ring-1{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 transparent)}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring-black{--tw-ring-opacity:1;--tw-ring-color:rgb(0 0 0/var(--tw-ring-opacity))}.ring-primary-200{--tw-ring-opacity:1;--tw-ring-color:hsl(var(--nextra-primary-hue) 100% 86%/var(--tw-ring-opacity))}.ring-primary-500{--tw-ring-opacity:1;--tw-ring-color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-ring-opacity))}.ring-white{--tw-ring-opacity:1;--tw-ring-color:rgb(255 255 255/var(--tw-ring-opacity))}.ring-opacity-5{--tw-ring-opacity:0.05}.ring-offset-2{--tw-ring-offset-width:2px}.blur{--tw-blur:blur(8px)}.blur,.contrast-150{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.contrast-150{--tw-contrast:contrast(1.5)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition-colors{transition-property:color,background-color,border-color,fill,stroke,-webkit-text-decoration-color;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,-webkit-text-decoration-color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition{transition-property:color,background-color,border-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-text-decoration-color,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-text-decoration-color,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-100{transition-duration:.1s}.duration-500{transition-duration:.5s}.duration-300{transition-duration:.3s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.main-container{min-height:100vh}.nextra-container .nextra-nav-container a:focus,.nextra-container .nextra-nav-container summary:focus{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;outline:2px solid transparent;outline-offset:2px}.nextra-container .nextra-nav-container a:focus-visible,.nextra-container .nextra-nav-container summary:focus-visible{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 transparent);--tw-ring-opacity:1;--tw-ring-color:hsl(var(--nextra-primary-hue) 100% 86%/var(--tw-ring-opacity))}.nextra-container .nextra-nav-container .nextra-nav-container-blur{z-index:-1;box-shadow:0 2px 4px rgba(0,0,0,.02),inset 0 -1px 0 rgba(0,0,0,.06)}.dark .nextra-container .nextra-nav-container .nextra-nav-container-blur{box-shadow:inset 0 -1px 0 hsla(0,0%,100%,.1)}@media (prefers-contrast:more){.nextra-container .nextra-nav-container .nextra-nav-container-blur{box-shadow:0 0 0 1px #000}.dark .nextra-container .nextra-nav-container .nextra-nav-container-blur{box-shadow:0 0 0 1px #fff}}@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))){.nextra-container .nextra-nav-container .nextra-nav-container-blur{-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);--tw-bg-opacity:.85}.dark .nextra-container .nextra-nav-container .nextra-nav-container-blur{--tw-bg-opacity:0.8}}.nextra-container .nextra-nav-container .nextra-nav-link{font-size:.875rem}.nextra-container .nextra-nav-container .nextra-menu-icon{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border-radius:.25rem;outline:2px solid transparent;outline-offset:2px}.nextra-container .nextra-nav-container .nextra-menu-icon:active{background-color:rgb(156 163 175/var(--tw-bg-opacity));--tw-bg-opacity:0.2}.nextra-container .nextra-nav-container .nextra-menu-icon svg g{transform-origin:center}.nextra-container .nextra-nav-container .nextra-menu-icon svg path{opacity:1;transition:transform .2s cubic-bezier(.25,1,.5,1) .2s,opacity .2s ease .2s}.nextra-container .nextra-nav-container .nextra-menu-icon svg g{transition:transform .2s cubic-bezier(.25,1,.5,1)}.nextra-container .nextra-nav-container .nextra-menu-icon svg.open path{transition:transform .2s cubic-bezier(.25,1,.5,1),opacity 0s ease .2s}.nextra-container .nextra-nav-container .nextra-menu-icon svg.open g{transition:transform .2s cubic-bezier(.25,1,.5,1) .2s}.nextra-container .nextra-nav-container .nextra-menu-icon svg.open>path{opacity:0}.nextra-container .nextra-nav-container .nextra-menu-icon svg.open>g:first-of-type{transform:rotate(45deg)}.nextra-container .nextra-nav-container .nextra-menu-icon svg.open>g:first-of-type path{transform:translate3d(0,6px,0)}.nextra-container .nextra-nav-container .nextra-menu-icon svg.open>g:nth-of-type(2){transform:rotate(-45deg)}.nextra-container .nextra-nav-container .nextra-menu-icon svg.open>g:nth-of-type(2) path{transform:translate3d(0,-6px,0)}.nextra-container .nextra-sidebar-container{-webkit-mask-image:linear-gradient(180deg,transparent,#000 20px),linear-gradient(270deg,#000 10px,transparent 0);mask-image:linear-gradient(180deg,transparent,#000 20px),linear-gradient(270deg,#000 10px,transparent 0)}.nextra-container .nextra-sidebar-container.with-menu.nextra-scrollbar::-webkit-scrollbar-track{margin-bottom:76px}.nextra-container .nextra-sidebar{-webkit-touch-callout:none}.nextra-container .nextra-sidebar ul a:focus-visible,.nextra-container .nextra-sidebar ul button:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 transparent);--tw-ring-opacity:1;--tw-ring-color:hsl(var(--nextra-primary-hue) 100% 86%/var(--tw-ring-opacity))}.nextra-container .nextra-sidebar ul .active-anchor{font-weight:600;--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.dark .nextra-container .nextra-sidebar ul .active-anchor{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.nextra-container .nextra-sidebar ul li.active>a,.nextra-container .nextra-sidebar ul li.active>a:hover{--tw-bg-opacity:1;background-color:hsl(var(--nextra-primary-hue) 100% 97%/var(--tw-bg-opacity));font-weight:700;--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity))}.dark .nextra-container .nextra-sidebar ul li.active>a,.dark .nextra-container .nextra-sidebar ul li.active>a:hover{background-color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-bg-opacity));--tw-bg-opacity:0.1;--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity))}@media (prefers-contrast:more){.nextra-container .nextra-sidebar ul li.active>a{border-width:1px}.dark .nextra-container .nextra-sidebar ul li.active>a,.nextra-container .nextra-sidebar ul li.active>a{--tw-border-opacity:1;border-color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-border-opacity))}}.nextra-container .nextra-sidebar ul button,.nextra-container .nextra-sidebar ul li a,.nextra-container .nextra-sidebar ul summary{margin-top:.25rem;display:block;width:100%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border-radius:.25rem;padding:.375rem .5rem;text-align:left;font-size:.875rem;--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity));-webkit-text-decoration-line:none;text-decoration-line:none;outline:2px solid transparent;outline-offset:2px;transition-property:background-color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.dark .nextra-container .nextra-sidebar ul button,.dark .nextra-container .nextra-sidebar ul li a,.dark .nextra-container .nextra-sidebar ul summary{--tw-text-opacity:1;color:rgb(115 115 115/var(--tw-text-opacity))}.nextra-container .nextra-sidebar ul button,.nextra-container .nextra-sidebar ul li a,.nextra-container .nextra-sidebar ul summary{-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none}.nextra-container .nextra-sidebar ul button:hover,.nextra-container .nextra-sidebar ul li a:hover,.nextra-container .nextra-sidebar ul summary:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.dark .nextra-container .nextra-sidebar ul button:hover,.dark .nextra-container .nextra-sidebar ul li a:hover,.dark .nextra-container .nextra-sidebar ul summary:hover{background-color:hsl(var(--nextra-primary-hue) 100% 94%/var(--tw-bg-opacity));--tw-bg-opacity:0.05;--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}@media (prefers-contrast:more){.nextra-container .nextra-sidebar ul button,.nextra-container .nextra-sidebar ul li a,.nextra-container .nextra-sidebar ul summary{border-width:1px;border-color:transparent;--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.nextra-container .nextra-sidebar ul button:hover,.nextra-container .nextra-sidebar ul li a:hover,.nextra-container .nextra-sidebar ul summary:hover{--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}.dark .nextra-container .nextra-sidebar ul button,.dark .nextra-container .nextra-sidebar ul li a,.dark .nextra-container .nextra-sidebar ul summary{border-width:1px;border-color:transparent;--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.dark .nextra-container .nextra-sidebar ul button:hover,.dark .nextra-container .nextra-sidebar ul li a:hover,.dark .nextra-container .nextra-sidebar ul summary:hover{--tw-border-opacity:1;border-color:rgb(249 250 251/var(--tw-border-opacity))}}.nextra-container .nextra-sidebar ul ul{position:relative;padding-left:.75rem;margin-left:.75rem;background-image:linear-gradient(90deg,#e5e7eb 1px,transparent 0)}.dark .nextra-container .nextra-sidebar ul ul{background-image:linear-gradient(90deg,rgba(224,243,255,.1) 1px,transparent 0)}.nextra-container .nextra-sidebar ul ul{background-size:1px calc(100% - 12px);background-position:0 6px;background-repeat:no-repeat}.nextra-container .nextra-sidebar .locale .menu{right:0}.nextra-container .nextra-sidebar .nextra-sidebar-search{position:-webkit-sticky;position:sticky;top:0;margin-top:-1rem;--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding-top:1rem}.dark .nextra-container .nextra-sidebar .nextra-sidebar-search{--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity))}.nextra-container .nextra-sidebar .nextra-sidebar-search{box-shadow:0 2px 14px 6px #fff;z-index:1}.dark .nextra-container .nextra-sidebar .nextra-sidebar-search{box-shadow:0 2px 14px 6px #111}.nextra-container .nextra-sidebar .nextra-sidebar-menu{position:-webkit-sticky;position:sticky;bottom:0}@media (prefers-contrast:more){.nextra-container .nextra-sidebar .nextra-sidebar-menu{box-shadow:none;border-top:1px solid #999}}.nextra-container .nextra-scrollbar{scrollbar-gutter:stable}.nextra-container .nextra-scrollbar::-webkit-scrollbar{width:6px}.nextra-container .nextra-scrollbar::-webkit-scrollbar-track{margin-top:20px;margin-bottom:16px;background-color:transparent}.nextra-container .nextra-scrollbar::-webkit-scrollbar-thumb{box-shadow:inset 0 0 0 5px hsla(0,0%,50.2%,0);border-radius:20px}.nextra-container .nextra-scrollbar:hover::-webkit-scrollbar-thumb{box-shadow:inset 0 0 0 5px hsla(0,0%,50.2%,.2)}.nextra-container .nextra-scrollbar:hover::-webkit-scrollbar-thumb:hover{box-shadow:inset 0 0 0 5px hsla(0,0%,50.2%,.4)}@media (max-width:767px){article:before{content:"";position:fixed;top:0;left:0;right:0;bottom:-200px;pointer-events:none;transition:opacity 1.5s ease;opacity:0;z-index:14;background-color:#000}.nextra-container.menu-active article:before{opacity:.8}.nextra-sidebar-container{top:0;-ms-scroll-chaining:none;overscroll-behavior:contain;--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding-top:4rem}.dark .nextra-sidebar-container{--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity))}.nextra-sidebar-container{height:100vh;height:-webkit-fill-available;opacity:0;transform:translate3d(0,-110%,0);transition:transform .8s cubic-bezier(.52,.16,.04,1),opacity 0s linear 1s;will-change:transform,opacity;contain:layout style;-webkit-backface-visibility:hidden;backface-visibility:hidden}.nextra-sidebar-container.open{opacity:1;transform:translateZ(0);transition:transform .8s cubic-bezier(.52,.16,.04,1)}body.resizing .nextra-sidebar-container{transition:none}.nextra-banner-container~div .nextra-sidebar-container{padding-top:6.5rem}.nextra-banner-container~div.nextra-nav-container{top:2.5rem}@media (min-width:768px){.nextra-banner-container~div.nextra-nav-container{top:0}}.nextra-banner-hidden .nextra-banner-container~div .nextra-sidebar-container{padding-top:4rem}.nextra-banner-hidden div.nextra-nav-container{top:0}.nextra-container .nextra-scrollbar{scrollbar-gutter:auto}}@media (prefers-reduced-motion:reduce) and (max-width:767px){.nextra-sidebar-container,.nextra-sidebar-container.open,article:before{transition:none}}@media (prefers-contrast:more){.nextra-toc-meta{box-shadow:none;border-top:1px solid #999!important}.nextra-toc-meta a{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.dark .nextra-toc-meta a{--tw-text-opacity:1!important;color:rgb(249 250 251/var(--tw-text-opacity))!important}article h2{border-color:#999!important}.nextra-nav-container nav .nextra-nav-link{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.dark .nextra-nav-container nav .nextra-nav-link{--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.nextra-nav-container nav .nextra-nav-link.active{font-weight:700}article pre{border-width:1px;--tw-border-opacity:1;border-color:hsl(var(--nextra-primary-hue) 100% 24%/var(--tw-border-opacity));--tw-border-opacity:0.2;--tw-contrast:contrast(1.5);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.dark article pre{--tw-border-opacity:1;border-color:hsl(var(--nextra-primary-hue) 100% 94%/var(--tw-border-opacity));--tw-border-opacity:0.4}.nextra-callout{border-color:currentColor}.dark .nextra-callout{border-color:currentColor!important}.nextra-search input{box-shadow:0 0 0 1px!important}.nextra-search input::-moz-placeholder{--tw-text-opacity:1!important;color:rgb(75 85 99/var(--tw-text-opacity))!important}.nextra-search input:-ms-input-placeholder{--tw-text-opacity:1!important;color:rgb(75 85 99/var(--tw-text-opacity))!important}.nextra-search input::placeholder{--tw-text-opacity:1!important;color:rgb(75 85 99/var(--tw-text-opacity))!important}.dark .nextra-search input::-moz-placeholder{--tw-text-opacity:1!important;color:rgb(156 163 175/var(--tw-text-opacity))!important}.dark .nextra-search input:-ms-input-placeholder{--tw-text-opacity:1!important;color:rgb(156 163 175/var(--tw-text-opacity))!important}.dark .nextra-search input::placeholder{--tw-text-opacity:1!important;color:rgb(156 163 175/var(--tw-text-opacity))!important}.nextra-search kbd{--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity));--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.dark .nextra-search kbd{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity));--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.nextra-search ul{border-width:1px;--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}.dark .nextra-search ul{--tw-border-opacity:1;border-color:rgb(249 250 251/var(--tw-border-opacity))}.nextra-search ul div.nextra-search-section{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity));--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.dark .nextra-search ul div.nextra-search-section{--tw-border-opacity:1;border-color:rgb(249 250 251/var(--tw-border-opacity));--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.nextra-search ul li{border-width:1px;border-color:transparent}.dark .nextra-search ul li .excerpt{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.nextra-search ul li.active{border-width:1px;--tw-border-opacity:1;border-color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-border-opacity))}.nextra-navigation-links{border-color:#999!important}.nextra-breadcrumb{color:currentColor}.nextra-breadcrumb .active{font-weight:700;color:currentColor!important}.nextra-toc ul li a{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity));-webkit-text-decoration-line:underline;text-decoration-line:underline}.dark .nextra-toc ul li a{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.nextra-toc ul li a[aria-selected=true]{--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity))}}.nextra-body.full{width:100%}.nextra-body.full.expand{width:100vw;margin:0 calc(50% - 50vw)}article{min-height:calc(100vh - 64px)}article h1{margin-top:.5rem;font-size:2.25rem;font-weight:700;letter-spacing:-.015em}article h2{margin-top:2.5rem;font-size:1.875rem;font-weight:600;letter-spacing:-.015em;border-bottom-width:1px;padding-bottom:.25rem}.dark article h2{border-color:hsl(var(--nextra-primary-hue) 100% 94%/var(--tw-border-opacity));--tw-border-opacity:0.1}article h3{font-size:1.5rem}article h3,article h4{margin-top:2rem;font-weight:600;letter-spacing:-.015em}article h4{font-size:1.25rem}article h5{font-size:1.125rem}article h5,article h6{margin-top:2rem;font-weight:600;letter-spacing:-.015em}article h6{font-size:1rem}article ul{margin-left:1.5rem;margin-top:1.5rem;list-style-type:disc}article ul:first-child{margin-top:0}article li{margin-top:.5rem;margin-bottom:.5rem}article ol{margin-left:1.5rem;margin-top:1.5rem;list-style-type:decimal}article blockquote{border-left-width:2px;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity));padding-left:1.5rem;font-style:italic;--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.dark article blockquote{--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity));--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}article h2 a{-webkit-text-decoration-line:none;text-decoration-line:none}article code{overflow-wrap:break-word;border-radius:.375rem;border-width:1px;border-color:rgb(0 0 0/var(--tw-border-opacity));--tw-border-opacity:0.05;background-color:rgb(0 0 0/var(--tw-bg-opacity));--tw-bg-opacity:0.05;font-size:.9em;padding:2px .25em;-webkit-box-decoration-break:clone;box-decoration-break:clone;font-feature-settings:"rlig" 1,"calt" 1,"ss01" 1}.dark article code{border-color:rgb(255 255 255/var(--tw-border-opacity));--tw-border-opacity:0.1;background-color:rgb(255 255 255/var(--tw-bg-opacity));--tw-bg-opacity:0.1}article pre{contain:paint;margin-top:1.5rem;margin-bottom:1rem;overflow-x:auto;border-radius:.75rem;background-color:hsl(var(--nextra-primary-hue) 100% 35%/var(--tw-bg-opacity));--tw-bg-opacity:0.05;padding:1rem;font-weight:500;-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}.dark article pre{background-color:hsl(var(--nextra-primary-hue) 100% 77%/var(--tw-bg-opacity));--tw-bg-opacity:0.1}article pre code{line-height:1.25rem;position:relative;display:inline-block;min-width:100%;border-radius:0;border-style:none;padding:0;font-size:.875rem;color:currentColor}.dark article pre code,article pre code{background-color:transparent}article pre code .line.highlighted:before{pointer-events:none;position:absolute;left:-1rem;right:-1rem;display:block;height:1.25rem;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:hsl(var(--nextra-primary-hue) 100% 45%/var(--tw-bg-opacity));content:var(--tw-content);--tw-bg-opacity:0.1}article pre code .line.highlighted span{position:relative}article pre code .line .highlighted{background-color:hsl(var(--nextra-primary-hue) 100% 32%/var(--tw-bg-opacity));--tw-bg-opacity:0.1}.dark article pre code .line .highlighted{background-color:hsl(var(--nextra-primary-hue) 100% 77%/var(--tw-bg-opacity));--tw-bg-opacity:0.1}article pre code .line .highlighted{border-radius:.125rem;--tw-shadow:0 0 0 3px rgba(0,0,0,0.3);--tw-shadow-colored:0 0 0 3px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 transparent),var(--tw-ring-shadow,0 0 transparent),var(--tw-shadow);--tw-shadow-color:hsl(var(--nextra-primary-hue) 100% 32%/0.1);--tw-shadow:var(--tw-shadow-colored)}.dark article pre code .line .highlighted{--tw-shadow-color:hsl(var(--nextra-primary-hue) 100% 77%/0.1);--tw-shadow:var(--tw-shadow-colored)}article a{--tw-ring-color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-ring-opacity));--tw-ring-opacity:0.3}article a:focus{outline:2px solid transparent;outline-offset:2px}article a:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 transparent)}article a code{color:currentColor;-webkit-text-decoration-line:none;text-decoration-line:none}article [data-nextra-code][data-filename]{position:relative;display:block}article [data-nextra-code][data-filename]:before{content:attr(data-filename);position:absolute;top:0;z-index:1;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-top-left-radius:.75rem;border-top-right-radius:.75rem;background-color:hsl(var(--nextra-primary-hue) 100% 39%/var(--tw-bg-opacity));--tw-bg-opacity:0.05;padding:.5rem 1rem;font-size:.75rem;--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 12%/var(--tw-text-opacity))}.dark article [data-nextra-code][data-filename]:before{background-color:hsl(var(--nextra-primary-hue) 100% 77%/var(--tw-bg-opacity));--tw-bg-opacity:0.1;--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}article [data-nextra-code][data-filename] pre{padding-top:3rem}article hr{margin-top:2rem;margin-bottom:2rem}.dark article hr{--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}article details{margin-top:1rem;margin-bottom:1rem;border-radius:.25rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding:.5rem;--tw-shadow:0 1px 2px 0 rgba(0,0,0,0.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 transparent),var(--tw-ring-shadow,0 0 transparent),var(--tw-shadow)}.dark article details{--tw-border-opacity:1;border-color:rgb(38 38 38/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity))}article details:first-child{margin-top:0}article details:last-child{margin-bottom:0}article details .nextra-collapse-content{padding:.5rem}article summary{cursor:pointer;border-radius:.25rem;padding:.25rem;outline:2px solid transparent;outline-offset:2px;transition-property:color,background-color,border-color,fill,stroke,-webkit-text-decoration-color;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,-webkit-text-decoration-color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}article summary:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.dark article summary:hover{--tw-bg-opacity:1;background-color:rgb(38 38 38/var(--tw-bg-opacity))}article summary::-webkit-details-marker{display:none}article details>summary{list-style-type:none}article details>summary:before{content:"";background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' class='h-5 w-5' viewBox='0 0 20 20' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z' clip-rule='evenodd'/%3E%3C/svg%3E");height:1.2em;width:1.2em;margin-right:.125em;vertical-align:-4px;display:inline-block;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.dark article details>summary:before{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' class='h-5 w-5' viewBox='0 0 20 20' fill='%23fff'%3E%3Cpath fill-rule='evenodd' d='M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z' clip-rule='evenodd'/%3E%3C/svg%3E")}article details[data-open]>summary{list-style-type:none}article details[data-open]>summary:before{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}article .subheading-anchor{margin-top:-84px;display:inline-block;position:absolute;width:1px}article .subheading-anchor+a:hover .anchor-icon{opacity:1}article .subheading-anchor:target+a .anchor-icon{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity));opacity:1}.dark article .subheading-anchor:target+a .anchor-icon{--tw-text-opacity:1;color:rgb(115 115 115/var(--tw-text-opacity))}article .anchor-icon{position:absolute;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding-left:.5rem;--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity));opacity:0;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.dark article .anchor-icon{--tw-text-opacity:1;color:rgb(64 64 64/var(--tw-text-opacity))}article.nextra-body-typesetting-article{font-size:17px;font-feature-settings:"rlig" 1,"calt" 1}article.nextra-body-typesetting-article h1{margin-top:1.5rem;margin-bottom:1rem;text-align:center;font-size:2.5rem}article.nextra-body-typesetting-article h2{border-style:none}article.nextra-body-typesetting-article a:not(.anchor){-webkit-text-decoration-line:none;text-decoration-line:none}article.nextra-body-typesetting-article a:not(.anchor):hover{-webkit-text-decoration-line:underline;text-decoration-line:underline}article.nextra-body-typesetting-article p{line-height:2rem}article.nextra-body-typesetting-article code{border-style:none}.dark article.nextra-body-typesetting-article code{--tw-bg-opacity:1;background-color:rgb(64 64 64/var(--tw-bg-opacity))}.dark article.nextra-body-typesetting-article pre code{background-color:transparent}article.nextra-body-typesetting-article .anchor-icon{display:none}.nextra-toc .nextra-toc-content{-webkit-mask-image:linear-gradient(180deg,transparent,#000 20px),linear-gradient(270deg,#000 10px,transparent 0);mask-image:linear-gradient(180deg,transparent,#000 20px),linear-gradient(270deg,#000 10px,transparent 0)}.nextra-toc ul{margin:0;list-style-type:none;overflow-wrap:break-word;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto}.nextra-toc ul:first-child{margin-top:0}.nextra-toc li{margin-top:.5rem;margin-bottom:.5rem}.nextra-search input{background-color:rgb(0 0 0/var(--tw-bg-opacity));--tw-bg-opacity:.03;font-size:.875rem;--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.dark .nextra-search input{background-color:rgb(249 250 251/var(--tw-bg-opacity));--tw-bg-opacity:0.1;--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity));--tw-border-opacity:1;border-color:rgb(31 41 55/var(--tw-border-opacity))}.nextra-search input::-moz-placeholder{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.nextra-search input:-ms-input-placeholder{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.nextra-search input::placeholder{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.dark .nextra-search input::-moz-placeholder{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.dark .nextra-search input:-ms-input-placeholder{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.dark .nextra-search input::placeholder{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.nextra-search.nextra-flexsearch ul{left:0;overflow:auto}@media (min-width:768px){.nextra-search.nextra-flexsearch ul{left:-20rem;right:0}}.nextra-search.nextra-flexsearch ul{min-height:100px;max-height:min(calc(100vh - 5rem - env(safe-area-inset-bottom)),400px);max-width:min(calc(100vw - 2rem),calc(100% + 20rem));transition:max-height .2s ease;width:100vw}.nextra-search ul a{scroll-margin:50px}.nextra-search ul{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity));--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 transparent);--tw-ring-color:rgb(0 0 0/var(--tw-ring-opacity));--tw-ring-opacity:0.05}.nextra-search ul li{margin-left:.625rem;margin-right:.625rem;overflow-wrap:break-word;border-radius:.375rem;padding:.5rem .625rem;--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.nextra-search ul li .highlight{--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity));-webkit-text-decoration-line:underline;text-decoration-line:underline;-webkit-text-decoration-color:hsl(var(--nextra-primary-hue) 100% 66%);text-decoration-color:hsl(var(--nextra-primary-hue) 100% 66%)}.nextra-search ul a:focus li,.nextra-search ul li.active{background-color:hsl(var(--nextra-primary-hue) 100% 66%/var(--tw-bg-opacity));--tw-bg-opacity:.1;--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity))}.nextra-search ul .nextra-search-section{border-bottom-width:1px;border-color:rgb(0 0 0/var(--tw-border-opacity));--tw-border-opacity:0.1}.dark .nextra-search ul .nextra-search-section{border-bottom-width:1px;border-color:rgb(255 255 255/var(--tw-border-opacity));--tw-border-opacity:0.2}.dark .nextra-search ul{--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity));--tw-ring-color:rgb(255 255 255/var(--tw-ring-opacity));--tw-ring-opacity:0.1}.dark .nextra-search ul li{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.dark .nextra-search ul li .highlight{--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity));-webkit-text-decoration-line:underline;text-decoration-line:underline;-webkit-text-decoration-color:hsl(var(--nextra-primary-hue) 100% 66%);text-decoration-color:hsl(var(--nextra-primary-hue) 100% 66%)}.dark .nextra-search ul a:focus li,.dark .nextra-search ul li.active{background-color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-bg-opacity));--tw-bg-opacity:.1;--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity))}@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))){.nextra-search ul{-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);--tw-bg-opacity:.7}.dark .nextra-search ul{--tw-bg-opacity:.8}}@media screen and (max-width:767px){.nextra-search .excerpt{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:1;line-clamp:1;-webkit-box-orient:vertical}.nextra-search.nextra-flexsearch ul{max-height:min(calc(50vh - 11rem - env(safe-area-inset-bottom)),400px)}}.search-overlay{position:fixed;top:0;bottom:0;left:0;right:0}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration,input[type=search]::-webkit-search-results-button,input[type=search]::-webkit-search-results-decoration{-webkit-appearance:none}.locale-switch summary::-webkit-details-marker{content:"";display:none}.locale-switch summary::marker{content:"";display:none}.locale-switch[open] summary:before{content:" ";position:fixed;top:0;right:0;bottom:0;left:0;z-index:10;display:block;cursor:default;background:transparent}.locale-switch .locale-dropdown{position:absolute;z-index:11}table{margin-top:.5rem;padding:0}table:first-child{margin-top:0}table tr{margin:0;border-top-width:1px;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity));padding:0}.dark table tr{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}table tr:nth-child(2n){--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.dark table tr:nth-child(2n){background-color:rgb(75 85 99/var(--tw-bg-opacity));--tw-bg-opacity:0.2}table tr th{font-weight:600}table tr td[align=center],table tr th[align=center]{text-align:center}table tr td[align=right],table tr th[align=right]{text-align:right}table tr td,table tr th{text-align:left;margin:0;border-width:1px;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity));padding:.5rem 1rem}.dark table tr td,.dark table tr th{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}.table-container{overflow:auto}.contains-task-list{margin-left:0;list-style-type:none}.contains-task-list input[type=checkbox]{margin-right:.25rem}.nextra-container.rtl{direction:rtl}.nextra-container.rtl .nextra-sidebar ul ul{margin-right:1.25rem;margin-left:0}.nextra-container.rtl .nextra-sidebar a,.nextra-container.rtl .nextra-sidebar button{text-align:right}.nextra-container.rtl article blockquote{border-right-width:2px;border-left-width:0;padding-right:1.5rem;padding-left:0}@media (min-width:768px){.nextra-container:not(.page) article .bleed.full{margin-left:calc(-50vw + 50% + 8rem);margin-right:calc(-50vw + 50% + 8rem)}.nextra-container.page article .bleed.full{margin-left:calc(-50vw + 50%);margin-right:calc(-50vw + 50%)}}@media (min-width:1280px){.nextra-container:not(.rtl):not(.page) article .bleed.full{margin-left:calc(50% - 50vw + 16rem);margin-right:calc(50% - 50vw)}.nextra-container.rtl:not(.page) article .bleed.full{margin-left:calc(50% - 50vw);margin-right:calc(50% - 50vw + 16rem)}.nextra-container.page article .bleed.full{margin-left:calc(50% - 50vw);margin-right:calc(50% - 50vw)}}.nextra-container.rtl code{direction:ltr}.nextra-container.rtl .anchor-icon{margin-left:0;margin-right:.5rem;display:inline-block}.nextra-container.rtl article ol,.nextra-container.rtl article ul{margin-left:0;margin-right:1.5rem}@media (min-width:768px){.nextra-container.rtl .nextra-sidebar{border-left-width:1px}}.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}.nextra-banner-hidden .nextra-banner-container{display:none}:root{--shiki-color-text:#414141;--shiki-color-background:transparent;--shiki-token-constant:#1976d2;--shiki-token-string:#22863a;--shiki-token-comment:#aaa;--shiki-token-keyword:#d32f2f;--shiki-token-parameter:#ff9800;--shiki-token-function:#6f42c1;--shiki-token-string-expression:#22863a;--shiki-token-punctuation:#212121;--shiki-token-link:#22863a;--nextra-shiki-deleted:red;--nextra-shiki-inserted:red;--nextra-primary-hue:212deg}.dark{--shiki-color-text:#d1d1d1;--shiki-token-constant:#79b8ff;--shiki-token-string:#ffab70;--shiki-token-comment:#6b737c;--shiki-token-keyword:#f97583;--shiki-token-parameter:#ff9800;--shiki-token-function:#b392f0;--shiki-token-string-expression:#4bb74a;--shiki-token-punctuation:#bbb;--shiki-token-link:#ffab70;--nextra-primary-hue:204deg}.before\:pointer-events-none:before{content:var(--tw-content);pointer-events:none}.before\:absolute:before{content:var(--tw-content);position:absolute}.before\:-inset-x-4:before{content:var(--tw-content);left:-1rem;right:-1rem}.before\:block:before{content:var(--tw-content);display:block}.before\:h-5:before{content:var(--tw-content);height:1.25rem}.before\:bg-primary-600:before{content:var(--tw-content);--tw-bg-opacity:1;background-color:hsl(var(--nextra-primary-hue) 100% 45%/var(--tw-bg-opacity))}.before\:bg-opacity-10:before{content:var(--tw-content);--tw-bg-opacity:0.1}.first\:mt-0:first-child{margin-top:0}.first\:mt-1:first-child{margin-top:.25rem}.first\:mt-2:first-child{margin-top:.5rem}.hover\:border-gray-200:hover{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.hover\:bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.hover\:bg-gray-800:hover{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.hover\:bg-opacity-5:hover{--tw-bg-opacity:0.05}.hover\:text-gray-900:hover{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.hover\:text-primary-500:hover{--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity))}.hover\:text-gray-800:hover{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.hover\:text-black:hover{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.hover\:opacity-100:hover{opacity:1}.hover\:opacity-75:hover{opacity:.75}.focus\:bg-white:focus{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-1:focus,.focus\:ring:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 transparent)}.focus\:ring:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-gray-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(229 231 235/var(--tw-ring-opacity))}.focus-visible\:ring:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 transparent)}@media (prefers-reduced-motion:reduce){.motion-reduce\:transition-none{transition-property:none}}.dark .dark\:border-orange-400{--tw-border-opacity:1;border-color:rgb(251 146 60/var(--tw-border-opacity))}.dark .dark\:border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity))}.dark .dark\:border-neutral-800{--tw-border-opacity:1;border-color:rgb(38 38 38/var(--tw-border-opacity))}.dark .dark\:border-gray-400{--tw-border-opacity:1;border-color:rgb(156 163 175/var(--tw-border-opacity))}.dark .dark\:border-primary-100{--tw-border-opacity:1;border-color:hsl(var(--nextra-primary-hue) 100% 94%/var(--tw-border-opacity))}.dark .dark\:border-gray-50{--tw-border-opacity:1;border-color:rgb(249 250 251/var(--tw-border-opacity))}.dark .dark\:border-gray-700{--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity))}.dark .dark\:border-opacity-30{--tw-border-opacity:0.3}.dark .dark\:border-opacity-20{--tw-border-opacity:0.2}.dark .dark\:border-opacity-10{--tw-border-opacity:0.1}.dark .dark\:bg-orange-400{--tw-bg-opacity:1;background-color:rgb(251 146 60/var(--tw-bg-opacity))}.dark .dark\:bg-red-900{--tw-bg-opacity:1;background-color:rgb(127 29 29/var(--tw-bg-opacity))}.dark .dark\:bg-blue-900{--tw-bg-opacity:1;background-color:rgb(30 58 138/var(--tw-bg-opacity))}.dark .dark\:bg-yellow-700{--tw-bg-opacity:1;background-color:rgb(161 98 7/var(--tw-bg-opacity))}.dark .dark\:bg-dark{--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity))}.dark .dark\:bg-neutral-900{--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity))}.dark .dark\:bg-primary-100{--tw-bg-opacity:1;background-color:hsl(var(--nextra-primary-hue) 100% 94%/var(--tw-bg-opacity))}.dark .dark\:bg-neutral-800{--tw-bg-opacity:1;background-color:rgb(38 38 38/var(--tw-bg-opacity))}.dark .dark\:bg-primary-500{--tw-bg-opacity:1;background-color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-bg-opacity))}.dark .dark\:bg-primary-300{--tw-bg-opacity:1;background-color:hsl(var(--nextra-primary-hue) 100% 77%/var(--tw-bg-opacity))}.dark .dark\:bg-transparent{background-color:transparent}.dark .dark\:bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.dark .dark\:bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}.dark .dark\:bg-opacity-20{--tw-bg-opacity:0.2}.dark .dark\:bg-opacity-30{--tw-bg-opacity:0.3}.dark .dark\:bg-opacity-50{--tw-bg-opacity:0.5}.dark .dark\:bg-opacity-10{--tw-bg-opacity:0.1}.dark .dark\:bg-\[linear-gradient\(1deg\2c \#383838\2c \#212121\)\]{background-image:linear-gradient(1deg,#383838,#212121)}.dark .dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.dark .dark\:text-orange-300{--tw-text-opacity:1;color:rgb(253 186 116/var(--tw-text-opacity))}.dark .dark\:text-red-200{--tw-text-opacity:1;color:rgb(254 202 202/var(--tw-text-opacity))}.dark .dark\:text-blue-200{--tw-text-opacity:1;color:rgb(191 219 254/var(--tw-text-opacity))}.dark .dark\:text-yellow-200{--tw-text-opacity:1;color:rgb(254 240 138/var(--tw-text-opacity))}.dark .dark\:text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.dark .dark\:text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.dark .dark\:text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.dark .dark\:text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.dark .dark\:text-gray-50{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.dark .dark\:text-gray-100{--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.dark .dark\:text-primary-500{--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity))}.dark .dark\:text-gray-200{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}.dark .dark\:text-neutral-700{--tw-text-opacity:1;color:rgb(64 64 64/var(--tw-text-opacity))}.dark .dark\:text-neutral-600{--tw-text-opacity:1;color:rgb(82 82 82/var(--tw-text-opacity))}.dark .dark\:shadow-\[0_-12px_16px_\#111\]{--tw-shadow:0 -12px 16px #111;--tw-shadow-colored:0 -12px 16px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 transparent),var(--tw-ring-shadow,0 0 transparent),var(--tw-shadow)}.dark .dark\:shadow-primary-300\/10{--tw-shadow-color:hsl(var(--nextra-primary-hue) 100% 77%/0.1);--tw-shadow:var(--tw-shadow-colored)}.dark .dark\:ring-white{--tw-ring-opacity:1;--tw-ring-color:rgb(255 255 255/var(--tw-ring-opacity))}.dark .dark\:ring-opacity-20{--tw-ring-opacity:0.2}.dark .dark\:hover\:border-neutral-800:hover{--tw-border-opacity:1;border-color:rgb(38 38 38/var(--tw-border-opacity))}.dark .dark\:hover\:bg-primary-100:hover{--tw-bg-opacity:1;background-color:hsl(var(--nextra-primary-hue) 100% 94%/var(--tw-bg-opacity))}.dark .dark\:hover\:bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.dark .dark\:hover\:bg-opacity-5:hover{--tw-bg-opacity:0.05}.dark .dark\:hover\:text-gray-200:hover{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}.dark .dark\:hover\:text-primary-500:hover{--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity))}.dark .dark\:hover\:text-gray-50:hover{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.dark .dark\:hover\:text-gray-100:hover{--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.dark .dark\:hover\:text-gray-300:hover{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.dark .dark\:hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.dark .dark\:focus\:bg-dark:focus{--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity))}.dark .dark\:focus\:ring-gray-100:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(243 244 246/var(--tw-ring-opacity))}.dark .dark\:focus\:ring-opacity-20:focus{--tw-ring-opacity:0.2}@media (min-width:640px){.sm\:flex{display:flex}}@media (min-width:768px){.md\:relative{position:relative}.md\:sticky{position:-webkit-sticky;position:sticky}.md\:right-0{right:0}.md\:-left-80{left:-20rem}.md\:-mx-8{margin-left:-2rem;margin-right:-2rem}.md\:block{display:block}.md\:inline-block{display:inline-block}.md\:inline{display:inline}.md\:hidden{display:none}.md\:h-auto{height:auto}.md\:w-64{width:16rem}.md\:w-auto{width:auto}.md\:flex-row{flex-direction:row}.md\:items-end{align-items:flex-end}.md\:overflow-auto{overflow:auto}.md\:px-8{padding-left:2rem;padding-right:2rem}.md\:text-lg{font-size:1.125rem}}@media (min-width:1280px){.xl\:block{display:block}}@media (min-width:1536px){.\32xl\:-mx-24{margin-left:-6rem;margin-right:-6rem}} +\ No newline at end of file ++/*! tailwindcss v3.1.5 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder, textarea::-moz-placeholder{opacity:1;color:#9ca3af}input:-ms-input-placeholder, textarea:-ms-input-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,0.5);--tw-ring-offset-shadow:0 0 transparent;--tw-ring-shadow:0 0 transparent;--tw-shadow:0 0 transparent;--tw-shadow-colored:0 0 transparent;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::-webkit-backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,0.5);--tw-ring-offset-shadow:0 0 transparent;--tw-ring-shadow:0 0 transparent;--tw-shadow:0 0 transparent;--tw-shadow-colored:0 0 transparent;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,0.5);--tw-ring-offset-shadow:0 0 transparent;--tw-ring-shadow:0 0 transparent;--tw-shadow:0 0 transparent;--tw-shadow-colored:0 0 transparent;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }html{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:16px;font-feature-settings:"rlig" 1,"calt" 1,"ss01" 1,"ss06" 1;-webkit-tap-highlight-color:transparent}body{width:100%;--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.dark body{--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity));color:rgb(243 244 246/var(--tw-text-opacity))}.dark body,a{--tw-text-opacity:1}a{color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity));-webkit-text-decoration-line:underline;text-decoration-line:underline;text-underline-position:under;text-decoration-thickness:from-font}p{line-height:1.75rem}.table-container:not(:first-child),blockquote:not(:first-child),p:not(:first-child){margin-top:1.5rem}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:-webkit-sticky;position:sticky}.inset-y-0{top:0;bottom:0}.right-0{right:0}.top-full{top:100%}.top-0{top:0}.left-0{left:0}.bottom-\[130\%\]{bottom:130%}.top-16{top:4rem}.bottom-0{bottom:0}.z-10{z-index:10}.z-20{z-index:20}.z-\[15\]{z-index:15}.order-last{order:9999}.m-0{margin:0}.-m-4{margin:-1rem}.-m-2{margin:-.5rem}.-mx-6{margin-left:-1.5rem;margin-right:-1.5rem}.mx-1{margin-left:.25rem;margin-right:.25rem}.mx-2\.5{margin-left:.625rem;margin-right:.625rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-auto{margin-left:auto;margin-right:auto}.my-4{margin-top:1rem;margin-bottom:1rem}.mx-4{margin-left:1rem;margin-right:1rem}.mt-6{margin-top:1.5rem}.mt-2\.5{margin-top:.625rem}.mt-2{margin-top:.5rem}.mb-2{margin-bottom:.5rem}.mt-1{margin-top:.25rem}.-ml-1{margin-left:-.25rem}.mr-2{margin-right:.5rem}.mb-8{margin-bottom:2rem}.ml-2{margin-left:.5rem}.ml-1{margin-left:.25rem}.mr-1{margin-right:.25rem}.mt-12{margin-top:3rem}.mt-16{margin-top:4rem}.-ml-2{margin-left:-.5rem}.mt-5{margin-top:1.25rem}.mb-4{margin-bottom:1rem}.-mr-4{margin-right:-1rem}.mt-8{margin-top:2rem}.mt-4{margin-top:1rem}.mb-\[-2px\]{margin-bottom:-2px}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.hidden{display:none}.h-5{height:1.25rem}.h-10{height:2.5rem}.h-full{height:100%}.h-16{height:4rem}.h-7{height:1.75rem}.h-\[18px\]{height:18px}.h-0{height:0}.h-\[calc\(100vh-4rem\)\]{height:calc(100vh - 4rem)}.h-4{height:1rem}.max-h-64{max-height:16rem}.max-h-\[calc\(100vh-4rem-env\(safe-area-inset-bottom\)\)\]{max-height:calc(100vh - 4rem - env(safe-area-inset-bottom))}.min-h-\[calc\(100vh-4rem-61px\)\]{min-height:calc(100vh - 4rem - 61px)}.w-full{width:100%}.w-5{width:1.25rem}.w-64{width:16rem}.w-8{width:2rem}.w-4{width:1rem}.w-max{width:-webkit-max-content;width:-moz-max-content;width:max-content}.min-w-\[24px\]{min-width:24px}.min-w-0{min-width:0}.min-w-full{min-width:100%}.min-w-\[18px\]{min-width:18px}.max-w-\[90rem\]{max-width:90rem}.max-w-full{max-width:100%}.max-w-4xl{max-width:56rem}.flex-1{flex:1 1 0%}.flex-auto{flex:1 1 auto}.flex-shrink-0{flex-shrink:0}.grow-0{flex-grow:0}.rotate-180{--tw-rotate:180deg}.rotate-180,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform-gpu{transform:translate3d(var(--tw-translate-x),var(--tw-translate-y),0) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@-webkit-keyframes spin{to{transform:rotate(1turn)}}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{-webkit-animation:spin 1s linear infinite;animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.resize{resize:both}.scroll-my-6{scroll-margin-top:1.5rem;scroll-margin-bottom:1.5rem}.scroll-py-6{scroll-padding-top:1.5rem;scroll-padding-bottom:1.5rem}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-1{gap:.25rem}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.self-start{align-self:flex-start}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-hidden{overflow-y:hidden}.overscroll-contain{-ms-scroll-chaining:none;overscroll-behavior:contain}.overscroll-x-contain{overscroll-behavior-x:contain}.truncate{overflow:hidden;white-space:nowrap}.text-ellipsis,.truncate{text-overflow:ellipsis}.whitespace-nowrap{white-space:nowrap}.rounded-lg{border-radius:.5rem}.rounded{border-radius:.25rem}.rounded-xl{border-radius:.75rem}.rounded-md{border-radius:.375rem}.rounded-sm{border-radius:.125rem}.rounded-\[1px\]{border-radius:1px}.border{border-width:1px}.border-t{border-top-width:1px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-orange-100{--tw-border-opacity:1;border-color:rgb(255 237 213/var(--tw-border-opacity))}.border-red-200{--tw-border-opacity:1;border-color:rgb(254 202 202/var(--tw-border-opacity))}.border-blue-200{--tw-border-opacity:1;border-color:rgb(191 219 254/var(--tw-border-opacity))}.border-yellow-100{--tw-border-opacity:1;border-color:rgb(254 249 195/var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.border-primary-500{--tw-border-opacity:1;border-color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-border-opacity))}.border-transparent{border-color:transparent}.bg-orange-50{--tw-bg-opacity:1;background-color:rgb(255 247 237/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity))}.bg-blue-100{--tw-bg-opacity:1;background-color:rgb(219 234 254/var(--tw-bg-opacity))}.bg-yellow-50{--tw-bg-opacity:1;background-color:rgb(254 252 232/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-neutral-900{--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity))}.bg-transparent{background-color:transparent}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-primary-50{--tw-bg-opacity:1;background-color:hsl(var(--nextra-primary-hue) 100% 97%/var(--tw-bg-opacity))}.bg-opacity-\[\.03\]{--tw-bg-opacity:.03}.p-8{padding:2rem}.p-4{padding:1rem}.p-2{padding:.5rem}.p-0{padding:0}.p-0\.5{padding:.125rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-0{padding-left:0;padding-right:0}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.px-4{padding-left:1rem;padding-right:1rem}.py-12{padding-top:3rem;padding-bottom:3rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pl-3{padding-left:.75rem}.pr-2{padding-right:.5rem}.pr-4{padding-right:1rem}.pb-1\.5{padding-bottom:.375rem}.pb-1{padding-bottom:.25rem}.pr-1\.5{padding-right:.375rem}.pr-1{padding-right:.25rem}.pt-8{padding-top:2rem}.pb-\[env\(safe-area-inset-bottom\)\]{padding-bottom:env(safe-area-inset-bottom)}.pl-\[max\(env\(safe-area-inset-left\)\2c 1\.5rem\)\]{padding-left:max(env(safe-area-inset-left),1.5rem)}.pr-\[max\(env\(safe-area-inset-right\)\2c 1\.5rem\)\]{padding-right:max(env(safe-area-inset-right),1.5rem)}.pb-8{padding-bottom:2rem}.pr-\[calc\(env\(safe-area-inset-right\)-1\.5rem\)\]{padding-right:calc(env(safe-area-inset-right) - 1.5rem)}.pt-4{padding-top:1rem}.pl-10{padding-left:2.5rem}.pr-9{padding-right:2.25rem}.pr-3{padding-right:.75rem}.pl-\[calc\(env\(safe-area-inset-left\)-1\.5rem\)\]{padding-left:calc(env(safe-area-inset-left) - 1.5rem)}.pb-4{padding-bottom:1rem}.pb-\[1px\]{padding-bottom:1px}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-sm{font-size:.875rem}.text-xl{font-size:1.25rem}.text-xs{font-size:.75rem}.text-base{font-size:1rem}.font-normal{font-weight:400}.font-semibold{font-weight:600}.font-medium{font-weight:500}.font-extrabold{font-weight:800}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.leading-5{line-height:1.25rem}.leading-\[1\.35rem\]{line-height:1.35rem}.leading-tight{line-height:1.25}.leading-4{line-height:1rem}.tracking-tight{letter-spacing:-.015em}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.text-current{color:currentColor}.text-orange-800{--tw-text-opacity:1;color:rgb(154 52 18/var(--tw-text-opacity))}.text-red-900{--tw-text-opacity:1;color:rgb(127 29 29/var(--tw-text-opacity))}.text-blue-900{--tw-text-opacity:1;color:rgb(30 58 138/var(--tw-text-opacity))}.text-yellow-900{--tw-text-opacity:1;color:rgb(113 63 18/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-slate-50{--tw-text-opacity:1;color:rgb(248 250 252/var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.text-primary-500{--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity))}.text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.no-underline{-webkit-text-decoration-line:none;text-decoration-line:none}.subpixel-antialiased{-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}.opacity-100{opacity:1}.opacity-0{opacity:0}.opacity-80{opacity:.8}.opacity-25{opacity:.25}.opacity-75{opacity:.75}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,0.1),0 8px 10px -6px rgba(0,0,0,0.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color)}.shadow-md,.shadow-xl{box-shadow:var(--tw-ring-offset-shadow,0 0 transparent),var(--tw-ring-shadow,0 0 transparent),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,0.1),0 2px 4px -2px rgba(0,0,0,0.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,0.1),0 4px 6px -4px rgba(0,0,0,0.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-\[0_-12px_16px_white\],.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 transparent),var(--tw-ring-shadow,0 0 transparent),var(--tw-shadow)}.shadow-\[0_-12px_16px_white\]{--tw-shadow:0 -12px 16px #fff;--tw-shadow-colored:0 -12px 16px var(--tw-shadow-color)}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 transparent)}.ring-black{--tw-ring-opacity:1;--tw-ring-color:rgb(0 0 0/var(--tw-ring-opacity))}.ring-opacity-5{--tw-ring-opacity:0.05}.ring-offset-2{--tw-ring-offset-width:2px}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-colors{transition-property:color,background-color,border-color,fill,stroke,-webkit-text-decoration-color;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,-webkit-text-decoration-color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition{transition-property:color,background-color,border-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-text-decoration-color,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-text-decoration-color,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-100{transition-duration:.1s}.duration-500{transition-duration:.5s}.duration-300{transition-duration:.3s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.main-container{min-height:100vh}.nextra-container .nextra-nav-container a:focus,.nextra-container .nextra-nav-container summary:focus{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;outline:2px solid transparent;outline-offset:2px}.nextra-container .nextra-nav-container a:focus-visible,.nextra-container .nextra-nav-container summary:focus-visible{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 transparent);--tw-ring-opacity:1;--tw-ring-color:hsl(var(--nextra-primary-hue) 100% 86%/var(--tw-ring-opacity))}.nextra-container .nextra-nav-container .nextra-nav-container-blur{z-index:-1;box-shadow:0 2px 4px rgba(0,0,0,.02),inset 0 -1px 0 rgba(0,0,0,.06)}.dark .nextra-container .nextra-nav-container .nextra-nav-container-blur{box-shadow:inset 0 -1px 0 hsla(0,0%,100%,.1)}@media (prefers-contrast:more){.nextra-container .nextra-nav-container .nextra-nav-container-blur{box-shadow:0 0 0 1px #000}.dark .nextra-container .nextra-nav-container .nextra-nav-container-blur{box-shadow:0 0 0 1px #fff}}@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))){.nextra-container .nextra-nav-container .nextra-nav-container-blur{--tw-bg-opacity:.85;--tw-backdrop-blur:blur(12px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.dark .nextra-container .nextra-nav-container .nextra-nav-container-blur{--tw-bg-opacity:0.8}}.nextra-container .nextra-nav-container .nextra-nav-link{font-size:.875rem}.nextra-container .nextra-nav-container .nextra-menu-icon{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border-radius:.25rem;outline:2px solid transparent;outline-offset:2px}.nextra-container .nextra-nav-container .nextra-menu-icon:active{background-color:rgba(156,163,175,.2)}.nextra-container .nextra-nav-container .nextra-menu-icon svg g{transform-origin:center;transition:transform .2s cubic-bezier(.25,1,.5,1)}.nextra-container .nextra-nav-container .nextra-menu-icon svg path{opacity:1;transition:transform .2s cubic-bezier(.25,1,.5,1) .2s,opacity .2s ease .2s}.nextra-container .nextra-nav-container .nextra-menu-icon svg.open path{transition:transform .2s cubic-bezier(.25,1,.5,1),opacity 0s ease .2s}.nextra-container .nextra-nav-container .nextra-menu-icon svg.open g{transition:transform .2s cubic-bezier(.25,1,.5,1) .2s}.nextra-container .nextra-nav-container .nextra-menu-icon svg.open>path{opacity:0}.nextra-container .nextra-nav-container .nextra-menu-icon svg.open>g:first-of-type{--tw-rotate:45deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.nextra-container .nextra-nav-container .nextra-menu-icon svg.open>g:first-of-type path{transform:translate3d(0,6px,0)}.nextra-container .nextra-nav-container .nextra-menu-icon svg.open>g:nth-of-type(2){--tw-rotate:-45deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.nextra-container .nextra-nav-container .nextra-menu-icon svg.open>g:nth-of-type(2) path{transform:translate3d(0,-6px,0)}.nextra-container .nextra-sidebar-container{-webkit-mask-image:linear-gradient(180deg,transparent,#000 20px),linear-gradient(270deg,#000 10px,transparent 0);mask-image:linear-gradient(180deg,transparent,#000 20px),linear-gradient(270deg,#000 10px,transparent 0)}.nextra-container .nextra-sidebar-container.with-menu.nextra-scrollbar::-webkit-scrollbar-track{margin-bottom:76px}.nextra-container .nextra-sidebar{-webkit-touch-callout:none}.nextra-container .nextra-sidebar ul a:focus-visible,.nextra-container .nextra-sidebar ul button:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 transparent);--tw-ring-opacity:1;--tw-ring-color:hsl(var(--nextra-primary-hue) 100% 86%/var(--tw-ring-opacity))}.nextra-container .nextra-sidebar ul .active-anchor{font-weight:600;--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.dark .nextra-container .nextra-sidebar ul .active-anchor{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.nextra-container .nextra-sidebar ul li.active>a,.nextra-container .nextra-sidebar ul li.active>a:hover{--tw-bg-opacity:1;background-color:hsl(var(--nextra-primary-hue) 100% 97%/var(--tw-bg-opacity));font-weight:700;--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity))}.dark .nextra-container .nextra-sidebar ul li.active>a,.dark .nextra-container .nextra-sidebar ul li.active>a:hover{background-color:hsl(var(--nextra-primary-hue) 100% 50%/.1);--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity))}@media (prefers-contrast:more){.nextra-container .nextra-sidebar ul li.active>a{border-width:1px}.dark .nextra-container .nextra-sidebar ul li.active>a,.nextra-container .nextra-sidebar ul li.active>a{--tw-border-opacity:1;border-color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-border-opacity))}}.nextra-container .nextra-sidebar ul button,.nextra-container .nextra-sidebar ul li a,.nextra-container .nextra-sidebar ul summary{margin-top:.25rem;display:block;width:100%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border-radius:.25rem;padding:.375rem .5rem;text-align:left;font-size:.875rem;--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity));-webkit-text-decoration-line:none;text-decoration-line:none;outline:2px solid transparent;outline-offset:2px;transition-property:background-color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.dark .nextra-container .nextra-sidebar ul button,.dark .nextra-container .nextra-sidebar ul li a,.dark .nextra-container .nextra-sidebar ul summary{--tw-text-opacity:1;color:rgb(115 115 115/var(--tw-text-opacity))}.nextra-container .nextra-sidebar ul button,.nextra-container .nextra-sidebar ul li a,.nextra-container .nextra-sidebar ul summary{-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none}.nextra-container .nextra-sidebar ul button:hover,.nextra-container .nextra-sidebar ul li a:hover,.nextra-container .nextra-sidebar ul summary:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.dark .nextra-container .nextra-sidebar ul button:hover,.dark .nextra-container .nextra-sidebar ul li a:hover,.dark .nextra-container .nextra-sidebar ul summary:hover{background-color:hsl(var(--nextra-primary-hue) 100% 94%/.05);--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}@media (prefers-contrast:more){.nextra-container .nextra-sidebar ul button,.nextra-container .nextra-sidebar ul li a,.nextra-container .nextra-sidebar ul summary{border-width:1px;border-color:transparent;--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.dark .nextra-container .nextra-sidebar ul button,.dark .nextra-container .nextra-sidebar ul li a,.dark .nextra-container .nextra-sidebar ul summary{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.nextra-container .nextra-sidebar ul button:hover,.nextra-container .nextra-sidebar ul li a:hover,.nextra-container .nextra-sidebar ul summary:hover{--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}.dark .nextra-container .nextra-sidebar ul button:hover,.dark .nextra-container .nextra-sidebar ul li a:hover,.dark .nextra-container .nextra-sidebar ul summary:hover{--tw-border-opacity:1;border-color:rgb(249 250 251/var(--tw-border-opacity))}}.nextra-container .nextra-sidebar ul ul{position:relative;margin-left:.75rem;background-repeat:no-repeat;padding-left:.75rem;background-image:linear-gradient(90deg,#e5e7eb 1px,transparent 0)}.dark .nextra-container .nextra-sidebar ul ul{background-image:linear-gradient(90deg,rgba(224,243,255,.1) 1px,transparent 0)}.nextra-container .nextra-sidebar ul ul{background-size:1px calc(100% - 12px);background-position:0 6px}.nextra-container .nextra-sidebar .locale .menu{right:0}.nextra-container .nextra-sidebar .nextra-sidebar-search{position:-webkit-sticky;position:sticky;top:0;z-index:1;margin-top:-1rem;--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding-top:1rem}.dark .nextra-container .nextra-sidebar .nextra-sidebar-search{--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity))}.nextra-container .nextra-sidebar .nextra-sidebar-search{box-shadow:0 2px 14px 6px #fff}.dark .nextra-container .nextra-sidebar .nextra-sidebar-search{box-shadow:0 2px 14px 6px #111}.nextra-container .nextra-sidebar .nextra-sidebar-menu{position:-webkit-sticky;position:sticky;bottom:0}@media (prefers-contrast:more){.nextra-container .nextra-sidebar .nextra-sidebar-menu{box-shadow:none;border-top:1px solid #999}}.nextra-container .nextra-scrollbar{scrollbar-gutter:stable}.nextra-container .nextra-scrollbar::-webkit-scrollbar{width:.375rem}.nextra-container .nextra-scrollbar::-webkit-scrollbar-track{margin-top:1.25rem;margin-bottom:1rem;background-color:transparent}.nextra-container .nextra-scrollbar::-webkit-scrollbar-thumb{box-shadow:inset 0 0 0 5px hsla(0,0%,50.2%,0);border-radius:20px}.nextra-container .nextra-scrollbar:hover::-webkit-scrollbar-thumb{box-shadow:inset 0 0 0 5px hsla(0,0%,50.2%,.2)}.nextra-container .nextra-scrollbar:hover::-webkit-scrollbar-thumb:hover{box-shadow:inset 0 0 0 5px hsla(0,0%,50.2%,.4)}@media (max-width:767px){article:before{pointer-events:none;position:fixed;top:0;left:0;right:0;bottom:-200px;z-index:14;opacity:0;--tw-content:"";content:var(--tw-content);transition:opacity 1.5s ease;background-color:#000}.nextra-container.menu-active article:before{opacity:.8}.nextra-sidebar-container{top:0;height:100vh;-ms-scroll-chaining:none;overscroll-behavior:contain;--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding-top:4rem;opacity:0}.dark .nextra-sidebar-container{--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity))}.nextra-sidebar-container{height:-webkit-fill-available;transform:translate3d(0,-110%,0);transition:transform .8s cubic-bezier(.52,.16,.04,1),opacity 0s linear 1s;will-change:transform,opacity;contain:layout style;-webkit-backface-visibility:hidden;backface-visibility:hidden}.nextra-sidebar-container.open{opacity:1;transform:translateZ(0);transition:transform .8s cubic-bezier(.52,.16,.04,1)}body.resizing .nextra-sidebar-container{transition:none}.nextra-banner-container~div .nextra-sidebar-container{padding-top:6.5rem}.nextra-banner-container~div.nextra-nav-container{top:2.5rem}@media (min-width:768px){.nextra-banner-container~div.nextra-nav-container{top:0}}.nextra-banner-hidden .nextra-banner-container~div .nextra-sidebar-container{padding-top:4rem}.nextra-banner-hidden div.nextra-nav-container{top:0}.nextra-container .nextra-scrollbar{scrollbar-gutter:auto}}@media (prefers-reduced-motion:reduce) and (max-width:767px){.nextra-sidebar-container,.nextra-sidebar-container.open,article:before{transition:none}}@media (prefers-contrast:more){.nextra-toc-meta{box-shadow:none;border-top:1px solid #999!important}.nextra-toc-meta a{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.dark .nextra-toc-meta a{--tw-text-opacity:1!important;color:rgb(249 250 251/var(--tw-text-opacity))!important}article h2{border-color:#999!important}.nextra-nav-container nav .nextra-nav-link{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.dark .nextra-nav-container nav .nextra-nav-link{--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.nextra-nav-container nav .nextra-nav-link.active{font-weight:700}article pre{border-width:1px;border-color:hsl(var(--nextra-primary-hue) 100% 24%/.2);--tw-contrast:contrast(1.5);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.dark article pre{border-color:hsl(var(--nextra-primary-hue) 100% 94%/.4)}.nextra-callout{border-color:currentColor}.dark .nextra-callout{border-color:currentColor!important}.nextra-search input{box-shadow:0 0 0 1px!important}.nextra-search input::-moz-placeholder{--tw-text-opacity:1!important;color:rgb(75 85 99/var(--tw-text-opacity))!important}.nextra-search input:-ms-input-placeholder{--tw-text-opacity:1!important;color:rgb(75 85 99/var(--tw-text-opacity))!important}.nextra-search input::placeholder{--tw-text-opacity:1!important;color:rgb(75 85 99/var(--tw-text-opacity))!important}.dark .nextra-search input::-moz-placeholder{--tw-text-opacity:1!important;color:rgb(156 163 175/var(--tw-text-opacity))!important}.dark .nextra-search input:-ms-input-placeholder{--tw-text-opacity:1!important;color:rgb(156 163 175/var(--tw-text-opacity))!important}.dark .nextra-search input::placeholder{--tw-text-opacity:1!important;color:rgb(156 163 175/var(--tw-text-opacity))!important}.nextra-search kbd{border-color:rgb(17 24 39/var(--tw-border-opacity));color:rgb(17 24 39/var(--tw-text-opacity))}.dark .nextra-search kbd,.nextra-search kbd{--tw-border-opacity:1;--tw-text-opacity:1}.dark .nextra-search kbd{border-color:rgb(243 244 246/var(--tw-border-opacity));color:rgb(243 244 246/var(--tw-text-opacity))}.nextra-search ul{border-width:1px;--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}.dark .nextra-search ul{--tw-border-opacity:1;border-color:rgb(249 250 251/var(--tw-border-opacity))}.nextra-search ul div.nextra-search-section{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity));--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.dark .nextra-search ul div.nextra-search-section{--tw-border-opacity:1;border-color:rgb(249 250 251/var(--tw-border-opacity));--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.nextra-search ul li{border-width:1px;border-color:transparent}.dark .nextra-search ul li .excerpt{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.nextra-search ul li.active{border-width:1px;--tw-border-opacity:1;border-color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-border-opacity))}.nextra-navigation-links{border-color:#999!important}.nextra-breadcrumb{color:currentColor}.nextra-breadcrumb .active{font-weight:700;color:currentColor!important}.nextra-toc ul li a{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity));-webkit-text-decoration-line:underline;text-decoration-line:underline}.dark .nextra-toc ul li a{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.nextra-toc ul li a[aria-selected=true]{--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity))}}.nextra-body.full{width:100%}.nextra-body.full.expand{width:100vw;margin:0 calc(50% - 50vw)}article{min-height:calc(100vh - 64px)}article h1{margin-top:.5rem;font-size:2.25rem;font-weight:700;letter-spacing:-.015em}article h2{margin-top:2.5rem;font-size:1.875rem;font-weight:600;letter-spacing:-.015em;border-bottom-width:1px;padding-bottom:.25rem}.dark article h2{border-color:hsl(var(--nextra-primary-hue) 100% 94%/.1)}article h3{font-size:1.5rem}article h3,article h4{margin-top:2rem;font-weight:600;letter-spacing:-.015em}article h4{font-size:1.25rem}article h5{font-size:1.125rem}article h5,article h6{margin-top:2rem;font-weight:600;letter-spacing:-.015em}article h6{font-size:1rem}article ul{margin-left:1.5rem;margin-top:1.5rem;list-style-type:disc}article ul:first-child{margin-top:0}article li{margin-top:.5rem;margin-bottom:.5rem}article ol{margin-left:1.5rem;margin-top:1.5rem;list-style-type:decimal}article blockquote{border-left-width:2px;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity));padding-left:1.5rem;font-style:italic;--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.dark article blockquote{--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity));--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}article h2 a{-webkit-text-decoration-line:none;text-decoration-line:none}article code{overflow-wrap:break-word;border-radius:.375rem;border-width:1px;border-color:rgba(0,0,0,.05);background-color:rgba(0,0,0,.05);padding:.125rem .25rem;font-size:.9em;-webkit-box-decoration-break:clone;box-decoration-break:clone;font-feature-settings:"rlig" 1,"calt" 1,"ss01" 1}.dark article code{border-color:hsla(0,0%,100%,.1);background-color:hsla(0,0%,100%,.1)}article pre{contain:paint;margin-top:1.5rem;margin-bottom:1rem;overflow-x:auto;border-radius:.75rem;background-color:hsl(var(--nextra-primary-hue) 100% 35%/.05);padding-top:1rem;padding-bottom:1rem;font-weight:500;-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}.dark article pre{background-color:hsl(var(--nextra-primary-hue) 100% 77%/.1)}article pre code[data-line-numbers]{counter-reset:line}article pre code[data-line-numbers]>.line:before{counter-increment:line;content:counter(line);margin-right:2rem;display:inline-block;width:1rem;text-align:right;--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity))}article pre code{display:grid;min-width:100%;border-radius:0;border-style:none;background-color:transparent;padding:0;font-size:.875rem;line-height:1.25rem;color:currentColor}.dark article pre code{background-color:transparent}article pre code .line{border-left-width:2px;border-color:transparent}article pre code .line,article pre code:not([data-language]){padding-left:1rem;padding-right:1rem}article pre code .line.highlighted{border-color:hsl(var(--nextra-primary-hue) 100% 45%/.6);background-color:hsl(var(--nextra-primary-hue) 100% 45%/.1)}article pre code .line.highlighted span{position:relative}article pre code .line .highlighted{background-color:hsl(var(--nextra-primary-hue) 100% 32%/.1)}.dark article pre code .line .highlighted{background-color:hsl(var(--nextra-primary-hue) 100% 77%/.1)}article pre code .line .highlighted{border-radius:.125rem;--tw-shadow:0 0 0 3px rgba(0,0,0,0.3);--tw-shadow-colored:0 0 0 3px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 transparent),var(--tw-ring-shadow,0 0 transparent),var(--tw-shadow);--tw-shadow-color:hsl(var(--nextra-primary-hue) 100% 32%/0.1);--tw-shadow:var(--tw-shadow-colored)}.dark article pre code .line .highlighted{--tw-shadow-color:hsl(var(--nextra-primary-hue) 100% 77%/0.1);--tw-shadow:var(--tw-shadow-colored)}article a{--tw-ring-color:hsl(var(--nextra-primary-hue) 100% 50%/0.3)}article a:focus{outline:2px solid transparent;outline-offset:2px}article a:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 transparent)}article a code{color:currentColor;-webkit-text-decoration-line:none;text-decoration-line:none}article [data-nextra-code][data-filename]{position:relative;display:block}article [data-nextra-code][data-filename]:before{content:attr(data-filename);position:absolute;top:0;z-index:1;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-top-left-radius:.75rem;border-top-right-radius:.75rem;background-color:hsl(var(--nextra-primary-hue) 100% 39%/.05);padding:.5rem 1rem;font-size:.75rem;--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 12%/var(--tw-text-opacity))}.dark article [data-nextra-code][data-filename]:before{background-color:hsl(var(--nextra-primary-hue) 100% 77%/.1);--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}article [data-nextra-code][data-filename] pre{padding-top:3rem}article hr{margin-top:2rem;margin-bottom:2rem}.dark article hr{--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}article details{margin-top:1rem;margin-bottom:1rem;border-radius:.25rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));padding:.5rem;--tw-shadow:0 1px 2px 0 rgba(0,0,0,0.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 transparent),var(--tw-ring-shadow,0 0 transparent),var(--tw-shadow)}.dark article details{--tw-border-opacity:1;border-color:rgb(38 38 38/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity))}article details:first-child{margin-top:0}article details:last-child{margin-bottom:0}article details .nextra-collapse-content{padding:.5rem}article summary{cursor:pointer;border-radius:.25rem;padding:.25rem;outline:2px solid transparent;outline-offset:2px;transition-property:color,background-color,border-color,fill,stroke,-webkit-text-decoration-color;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,-webkit-text-decoration-color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}article summary:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.dark article summary:hover{--tw-bg-opacity:1;background-color:rgb(38 38 38/var(--tw-bg-opacity))}article summary::-webkit-details-marker{display:none}article details>summary{list-style-type:none}article details>summary:before{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' class='h-5 w-5' viewBox='0 0 20 20' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z' clip-rule='evenodd'/%3E%3C/svg%3E");height:1.2em;width:1.2em;vertical-align:-4px;margin-right:.125rem;display:inline-block;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s;--tw-content:"";content:var(--tw-content)}.dark article details>summary:before{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' class='h-5 w-5' viewBox='0 0 20 20' fill='%23fff'%3E%3Cpath fill-rule='evenodd' d='M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z' clip-rule='evenodd'/%3E%3C/svg%3E")}article details[data-open]>summary{list-style-type:none}article details[data-open]>summary:before{content:var(--tw-content);--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}article .subheading-anchor{margin-top:-84px;position:absolute;display:inline-block;width:1px}article .subheading-anchor+a:hover .anchor-icon{opacity:1}article .subheading-anchor:target+a .anchor-icon{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity));opacity:1}.dark article .subheading-anchor:target+a .anchor-icon{--tw-text-opacity:1;color:rgb(115 115 115/var(--tw-text-opacity))}article .anchor-icon{position:absolute;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding-left:.5rem;--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity));opacity:0;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.dark article .anchor-icon{--tw-text-opacity:1;color:rgb(64 64 64/var(--tw-text-opacity))}article.nextra-body-typesetting-article{font-size:17px;font-feature-settings:"rlig" 1,"calt" 1}article.nextra-body-typesetting-article h1{margin-top:1.5rem;margin-bottom:1rem;text-align:center;font-size:2.5rem}article.nextra-body-typesetting-article h2{border-style:none}article.nextra-body-typesetting-article a:not(.anchor){-webkit-text-decoration-line:none;text-decoration-line:none}article.nextra-body-typesetting-article a:not(.anchor):hover{-webkit-text-decoration-line:underline;text-decoration-line:underline}article.nextra-body-typesetting-article p{line-height:2rem}article.nextra-body-typesetting-article code{border-style:none}.dark article.nextra-body-typesetting-article code{--tw-bg-opacity:1;background-color:rgb(64 64 64/var(--tw-bg-opacity))}.dark article.nextra-body-typesetting-article pre code{background-color:transparent}article.nextra-body-typesetting-article .anchor-icon{display:none}.nextra-toc .nextra-toc-content{-webkit-mask-image:linear-gradient(180deg,transparent,#000 20px),linear-gradient(270deg,#000 10px,transparent 0);mask-image:linear-gradient(180deg,transparent,#000 20px),linear-gradient(270deg,#000 10px,transparent 0)}.nextra-toc ul{margin:0;list-style-type:none;overflow-wrap:break-word;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto}.nextra-toc ul:first-child{margin-top:0}.nextra-toc li{margin-top:.5rem;margin-bottom:.5rem}.nextra-search input{background-color:rgb(0 0 0/var(--tw-bg-opacity));--tw-bg-opacity:.03;font-size:.875rem;--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.dark .nextra-search input{background-color:rgba(249,250,251,.1);--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity));--tw-border-opacity:1;border-color:rgb(31 41 55/var(--tw-border-opacity))}.nextra-search input::-moz-placeholder{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.nextra-search input:-ms-input-placeholder{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.nextra-search input::placeholder{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.dark .nextra-search input::-moz-placeholder{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.dark .nextra-search input:-ms-input-placeholder{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.dark .nextra-search input::placeholder{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.nextra-search.nextra-flexsearch ul{left:0;min-height:100px;width:100vw;overflow:auto}@media (min-width:768px){.nextra-search.nextra-flexsearch ul{left:-20rem;right:0}}.nextra-search.nextra-flexsearch ul{max-height:min(calc(100vh - 5rem - env(safe-area-inset-bottom)),400px);max-width:min(calc(100vw - 2rem),calc(100% + 20rem));transition:max-height .2s ease}.nextra-search ul a{scroll-margin:50px}.nextra-search ul{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity));--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 transparent);--tw-ring-color:rgba(0,0,0,0.05)}.dark .nextra-search ul{--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity));--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity));--tw-ring-color:hsla(0,0%,100%,0.1)}.nextra-search ul li{margin-left:.625rem;margin-right:.625rem;overflow-wrap:break-word;border-radius:.375rem;padding:.5rem .625rem;--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.dark .nextra-search ul li{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.nextra-search ul li .highlight{--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity));-webkit-text-decoration-line:underline;text-decoration-line:underline;-webkit-text-decoration-color:hsl(var(--nextra-primary-hue) 100% 66%);text-decoration-color:hsl(var(--nextra-primary-hue) 100% 66%)}.nextra-search ul a:focus li,.nextra-search ul li.active{background-color:hsl(var(--nextra-primary-hue) 100% 66%/.1);--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity))}.dark .nextra-search ul a:focus li,.dark .nextra-search ul li.active{--tw-bg-opacity:1;background-color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-bg-opacity))}.nextra-search ul .nextra-search-section{border-bottom-width:1px;border-color:rgba(0,0,0,.1)}.dark .nextra-search ul .nextra-search-section{border-color:hsla(0,0%,100%,.2)}@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))){.nextra-search ul{--tw-bg-opacity:.7;--tw-backdrop-blur:blur(16px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.dark .nextra-search ul{--tw-bg-opacity:.8}}@media screen and (max-width:767px){.nextra-search .excerpt{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:1;line-clamp:1;-webkit-box-orient:vertical}.nextra-search.nextra-flexsearch ul{max-height:min(calc(50vh - 11rem - env(safe-area-inset-bottom)),400px)}}.search-overlay{position:fixed;top:0;right:0;bottom:0;left:0}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration,input[type=search]::-webkit-search-results-button,input[type=search]::-webkit-search-results-decoration{-webkit-appearance:none}.locale-switch summary::-webkit-details-marker,.locale-switch summary::marker{display:none;--tw-content:"";content:var(--tw-content)}.locale-switch[open] summary:before{position:fixed;top:0;right:0;bottom:0;left:0;z-index:10;display:block;cursor:default;background-color:transparent;content:" "}.locale-switch .locale-dropdown{position:absolute;z-index:11}table{margin-top:.5rem;padding:0}table:first-child{margin-top:0}table tr{margin:0;border-top-width:1px;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity));padding:0}.dark table tr{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}table tr:nth-child(2n){--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.dark table tr:nth-child(2n){background-color:rgba(75,85,99,.2)}table tr th{font-weight:600}table tr td[align=center],table tr th[align=center]{text-align:center}table tr td[align=right],table tr th[align=right]{text-align:right}table tr td,table tr th{text-align:left;margin:0;border-width:1px;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity));padding:.5rem 1rem}.dark table tr td,.dark table tr th{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}.table-container{overflow:auto}.contains-task-list{margin-left:0;list-style-type:none}.contains-task-list input[type=checkbox]{margin-right:.25rem}.nextra-container.rtl{direction:rtl}.nextra-container.rtl .nextra-sidebar ul ul{margin-right:1.25rem;margin-left:0}.nextra-container.rtl .nextra-sidebar a,.nextra-container.rtl .nextra-sidebar button{text-align:right}.nextra-container.rtl article blockquote{border-right-width:2px;border-left-width:0;padding-right:1.5rem;padding-left:0}@media (min-width:768px){.nextra-container:not(.page) article .bleed.full{margin-left:calc(-50vw + 50% + 8rem);margin-right:calc(-50vw + 50% + 8rem)}.nextra-container.page article .bleed.full{margin-left:calc(-50vw + 50%);margin-right:calc(-50vw + 50%)}}@media (min-width:1280px){.nextra-container:not(.rtl):not(.page) article .bleed.full{margin-left:calc(50% - 50vw + 16rem);margin-right:calc(50% - 50vw)}.nextra-container.rtl:not(.page) article .bleed.full{margin-left:calc(50% - 50vw);margin-right:calc(50% - 50vw + 16rem)}.nextra-container.page article .bleed.full{margin-left:calc(50% - 50vw);margin-right:calc(50% - 50vw)}}.nextra-container.rtl code{direction:ltr}.nextra-container.rtl .anchor-icon{margin-left:0;margin-right:.5rem;display:inline-block}.nextra-container.rtl article ol,.nextra-container.rtl article ul{margin-left:0;margin-right:1.5rem}@media (min-width:768px){.nextra-container.rtl .nextra-sidebar{border-left-width:1px}}.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}.nextra-banner-hidden .nextra-banner-container{display:none}:root{--shiki-color-text:#414141;--shiki-color-background:transparent;--shiki-token-constant:#1976d2;--shiki-token-string:#22863a;--shiki-token-comment:#aaa;--shiki-token-keyword:#d32f2f;--shiki-token-parameter:#ff9800;--shiki-token-function:#6f42c1;--shiki-token-string-expression:#22863a;--shiki-token-punctuation:#212121;--shiki-token-link:#22863a;--nextra-shiki-deleted:red;--nextra-shiki-inserted:red;--nextra-primary-hue:212deg}.dark{--shiki-color-text:#d1d1d1;--shiki-token-constant:#79b8ff;--shiki-token-string:#ffab70;--shiki-token-comment:#6b737c;--shiki-token-keyword:#f97583;--shiki-token-parameter:#ff9800;--shiki-token-function:#b392f0;--shiki-token-string-expression:#4bb74a;--shiki-token-punctuation:#bbb;--shiki-token-link:#ffab70;--nextra-primary-hue:204deg}.first\:mt-0:first-child{margin-top:0}.first\:mt-1:first-child{margin-top:.25rem}.first\:mt-2:first-child{margin-top:.5rem}.hover\:border-gray-200:hover{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.hover\:bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.hover\:bg-gray-800:hover{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.hover\:bg-opacity-5:hover{--tw-bg-opacity:0.05}.hover\:text-gray-900:hover{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.hover\:text-primary-500:hover{--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity))}.hover\:text-gray-800:hover{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.hover\:text-black:hover{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.hover\:opacity-100:hover{opacity:1}.hover\:opacity-75:hover{opacity:.75}.focus\:bg-white:focus{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-1:focus,.focus\:ring:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 transparent)}.focus\:ring:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-gray-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(229 231 235/var(--tw-ring-opacity))}.focus-visible\:ring:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 transparent)}@media (prefers-reduced-motion:reduce){.motion-reduce\:transition-none{transition-property:none}}.dark .dark\:border-orange-400{--tw-border-opacity:1;border-color:rgb(251 146 60/var(--tw-border-opacity))}.dark .dark\:border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity))}.dark .dark\:border-neutral-800{--tw-border-opacity:1;border-color:rgb(38 38 38/var(--tw-border-opacity))}.dark .dark\:border-gray-400{--tw-border-opacity:1;border-color:rgb(156 163 175/var(--tw-border-opacity))}.dark .dark\:border-primary-100{--tw-border-opacity:1;border-color:hsl(var(--nextra-primary-hue) 100% 94%/var(--tw-border-opacity))}.dark .dark\:border-opacity-30{--tw-border-opacity:0.3}.dark .dark\:border-opacity-20{--tw-border-opacity:0.2}.dark .dark\:border-opacity-10{--tw-border-opacity:0.1}.dark .dark\:bg-orange-400{--tw-bg-opacity:1;background-color:rgb(251 146 60/var(--tw-bg-opacity))}.dark .dark\:bg-red-900{--tw-bg-opacity:1;background-color:rgb(127 29 29/var(--tw-bg-opacity))}.dark .dark\:bg-blue-900{--tw-bg-opacity:1;background-color:rgb(30 58 138/var(--tw-bg-opacity))}.dark .dark\:bg-yellow-700{--tw-bg-opacity:1;background-color:rgb(161 98 7/var(--tw-bg-opacity))}.dark .dark\:bg-dark{--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity))}.dark .dark\:bg-neutral-900{--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity))}.dark .dark\:bg-primary-100{--tw-bg-opacity:1;background-color:hsl(var(--nextra-primary-hue) 100% 94%/var(--tw-bg-opacity))}.dark .dark\:bg-neutral-800{--tw-bg-opacity:1;background-color:rgb(38 38 38/var(--tw-bg-opacity))}.dark .dark\:bg-primary-500{--tw-bg-opacity:1;background-color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-bg-opacity))}.dark .dark\:bg-opacity-20{--tw-bg-opacity:0.2}.dark .dark\:bg-opacity-30{--tw-bg-opacity:0.3}.dark .dark\:bg-opacity-50{--tw-bg-opacity:0.5}.dark .dark\:bg-opacity-10{--tw-bg-opacity:0.1}.dark .dark\:bg-\[linear-gradient\(1deg\2c \#383838\2c \#212121\)\]{background-image:linear-gradient(1deg,#383838,#212121)}.dark .dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.dark .dark\:text-orange-300{--tw-text-opacity:1;color:rgb(253 186 116/var(--tw-text-opacity))}.dark .dark\:text-red-200{--tw-text-opacity:1;color:rgb(254 202 202/var(--tw-text-opacity))}.dark .dark\:text-blue-200{--tw-text-opacity:1;color:rgb(191 219 254/var(--tw-text-opacity))}.dark .dark\:text-yellow-200{--tw-text-opacity:1;color:rgb(254 240 138/var(--tw-text-opacity))}.dark .dark\:text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.dark .dark\:text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.dark .dark\:text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.dark .dark\:text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.dark .dark\:text-gray-50{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.dark .dark\:text-gray-100{--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.dark .dark\:text-gray-200{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}.dark .dark\:text-neutral-600{--tw-text-opacity:1;color:rgb(82 82 82/var(--tw-text-opacity))}.dark .dark\:shadow-\[0_-12px_16px_\#111\]{--tw-shadow:0 -12px 16px #111;--tw-shadow-colored:0 -12px 16px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 transparent),var(--tw-ring-shadow,0 0 transparent),var(--tw-shadow)}.dark .dark\:ring-white{--tw-ring-opacity:1;--tw-ring-color:rgb(255 255 255/var(--tw-ring-opacity))}.dark .dark\:ring-opacity-20{--tw-ring-opacity:0.2}.dark .dark\:hover\:border-neutral-800:hover{--tw-border-opacity:1;border-color:rgb(38 38 38/var(--tw-border-opacity))}.dark .dark\:hover\:bg-primary-100:hover{--tw-bg-opacity:1;background-color:hsl(var(--nextra-primary-hue) 100% 94%/var(--tw-bg-opacity))}.dark .dark\:hover\:bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.dark .dark\:hover\:bg-opacity-5:hover{--tw-bg-opacity:0.05}.dark .dark\:hover\:text-gray-200:hover{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}.dark .dark\:hover\:text-primary-500:hover{--tw-text-opacity:1;color:hsl(var(--nextra-primary-hue) 100% 50%/var(--tw-text-opacity))}.dark .dark\:hover\:text-gray-50:hover{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}.dark .dark\:hover\:text-gray-100:hover{--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.dark .dark\:hover\:text-gray-300:hover{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}.dark .dark\:hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.dark .dark\:focus\:bg-dark:focus{--tw-bg-opacity:1;background-color:rgb(17 17 17/var(--tw-bg-opacity))}.dark .dark\:focus\:ring-gray-100:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(243 244 246/var(--tw-ring-opacity))}.dark .dark\:focus\:ring-opacity-20:focus{--tw-ring-opacity:0.2}@media (min-width:640px){.sm\:flex{display:flex}}@media (min-width:768px){.md\:relative{position:relative}.md\:sticky{position:-webkit-sticky;position:sticky}.md\:right-0{right:0}.md\:-mx-8{margin-left:-2rem;margin-right:-2rem}.md\:block{display:block}.md\:inline-block{display:inline-block}.md\:inline{display:inline}.md\:hidden{display:none}.md\:h-auto{height:auto}.md\:w-64{width:16rem}.md\:w-auto{width:auto}.md\:flex-row{flex-direction:row}.md\:items-end{align-items:flex-end}.md\:overflow-auto{overflow:auto}.md\:px-8{padding-left:2rem;padding-right:2rem}.md\:text-lg{font-size:1.125rem}}@media (min-width:1280px){.xl\:block{display:block}}@media (min-width:1536px){.\32xl\:-mx-24{margin-left:-6rem;margin-right:-6rem}}.\[\&\>path\]\:origin-center>path{transform-origin:center}.\[\&\>path\]\:rotate-90>path{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.\[\&\>path\]\:fill-current>path{fill:currentColor}.\[\&\>path\]\:transition-transform>path{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s} +\ No newline at end of file diff --git a/prettier.config.cjs b/prettier.config.cjs index cd056fbdf20..f7673363809 100644 --- a/prettier.config.cjs +++ b/prettier.config.cjs @@ -6,5 +6,8 @@ module.exports = { ...plugins, // `prettier-plugin-svelte` and `svelte` packages used for formatting ```svelte code blocks in md/mdx files 'prettier-plugin-svelte', + // Sort classes in website + 'prettier-plugin-tailwindcss', ], + tailwindConfig: './website/tailwind.config.cjs', }; diff --git a/website/.babelrc.js b/website/.babelrc.js deleted file mode 100644 index b88126e4470..00000000000 --- a/website/.babelrc.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - presets: [ - [ - 'next/babel', - { - 'preset-react': { - runtime: 'automatic', - importSource: '@emotion/react', - }, - }, - ], - ], - plugins: ['@emotion/babel-plugin', 'babel-plugin-macros'], -}; diff --git a/website/.eslintrc.js b/website/.eslintrc.js index 08471cc08f7..567ae9fbab6 100644 --- a/website/.eslintrc.js +++ b/website/.eslintrc.js @@ -13,15 +13,4 @@ module.exports = { 'react/jsx-curly-brace-presence': ['error', 'never'], 'react/jsx-filename-extension': ['error', { extensions: ['.tsx'] }], }, - overrides: [ - { - files: ['.babelrc.js', '.eslintrc.js', 'next-i18next.config.js', 'next.config.js'], - env: { - node: true, - }, - rules: { - '@typescript-eslint/no-var-requires': 'off', - }, - }, - ], }; diff --git a/website/docs-templates/client-note.md b/website/docs-templates/client-note.md deleted file mode 100644 index 5a7088afd70..00000000000 --- a/website/docs-templates/client-note.md +++ /dev/null @@ -1,5 +0,0 @@ - -In order to use this GraphQL Codegen plugin, please make sure that you have GraphQL operations (`query` / `mutation` / `subscription` and `fragment`) set as `documents: ...` in your `codegen.yml`. - -Without loading your GraphQL operations (`query`, `mutation`, `subscription` and `fragment`), you won't see any change in the generated output. - diff --git a/website/docs-templates/flow-operations.md b/website/docs-templates/flow-operations.md deleted file mode 100644 index 7f53056e1dd..00000000000 --- a/website/docs-templates/flow-operations.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -id: flow-operations ---- - -{@operationsNote} - -{@apiDocs} diff --git a/website/docs-templates/import-types-preset.md b/website/docs-templates/import-types-preset.md deleted file mode 100644 index bef2a14dcd1..00000000000 --- a/website/docs-templates/import-types-preset.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -id: import-types ---- - -This preset generates a file per each operation file, and allow to import types from another file. - -{@apiDocs} diff --git a/website/docs-templates/introspection.md b/website/docs-templates/introspection.md deleted file mode 100644 index 3ea7da20b81..00000000000 --- a/website/docs-templates/introspection.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -id: introspection ---- - -{@apiDocs} diff --git a/website/docs-templates/java-resolvers.md b/website/docs-templates/java-resolvers.md deleted file mode 100644 index f03403fd2f5..00000000000 --- a/website/docs-templates/java-resolvers.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -id: java-resolvers ---- - -The `java-resolvers` plugin creates Java `interface`s for the resolvers' signature. - -It works with `graphql-java` library, and it uses it's `DataFetcher` API. - -You can use this plugin to generate interfaces and later implement them, this way you can always tell if one of the fields is missing a resolvers: - -```java -import com.my.app.generated.Resolvers; -import com.my.app.models.User; -import graphql.schema.DataFetcher; - -export class QueryResolvers implements Resolvers.Query { - public DataFetcher id() { - return environment -> environment.getSource().getId(); - } -} -``` - -## Prepare your environment - -{@javaInstallation} - -{@apiDocs} diff --git a/website/docs-templates/java.md b/website/docs-templates/java.md deleted file mode 100644 index d040e44324a..00000000000 --- a/website/docs-templates/java.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -id: java ---- - -## Prepare your environment - -{@javaInstallation} - -{@apiDocs} - -## How to use - -You can use it directly to transform your `input` in your resolvers: - -```graphql -type Query { - user(id: ID!): User! -} - -type User { - id: ID -} -``` - -Then, in your resolver: - -```java -import com.my.app.generated.Types; -import com.my.app.models.User; -import graphql.schema.DataFetcher; - -export class QueryResolvers { - public DataFetcher user() { - return env -> { - Types.QueryUserArgs args = new Types.QueryUserArgs(env.getArguments()); - String userId = args.getId(); - - // rest of the code - }; - } -} -``` diff --git a/website/docs-templates/jsdoc.md b/website/docs-templates/jsdoc.md deleted file mode 100644 index 96ac121a3a9..00000000000 --- a/website/docs-templates/jsdoc.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -id: jsdoc ---- - -> developed by [`CarloPalinckx`](https://github.com/CarloPalinckx) - -This plugin generates types in the form of JSDoc comments based on your GraphQLSchema. diff --git a/website/docs-templates/schema-ast.md b/website/docs-templates/schema-ast.md deleted file mode 100644 index 0b78517e690..00000000000 --- a/website/docs-templates/schema-ast.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -id: schema-ast ---- - -{@apiDocs} - -## Examples - -```yaml -# ... -schema: - - 'http://localhost:3000/graphql' - - './src/**/*.graphql' - - 'scalar MyCustomScalar' -generates: - path/to/file.graphql: - plugins: - - schema-ast -``` diff --git a/website/docs-templates/time.md b/website/docs-templates/time.md deleted file mode 100644 index 0e5947ceed6..00000000000 --- a/website/docs-templates/time.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -id: time ---- - -{@apiDocs} diff --git a/website/docs-templates/typescript-generic-sdk.md b/website/docs-templates/typescript-generic-sdk.md deleted file mode 100644 index b07b7f891ab..00000000000 --- a/website/docs-templates/typescript-generic-sdk.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -id: typescript-generic-sdk ---- - -{@operationsNote} - -> Make sure you have `typescript` plugin and `typescript-operations` as well in your configuration: - -{@apiDocs} - -## Usage - -You can find a usage [example for Apollo-Client here](https://gist.github.com/akozhemiakin/731b0c1e99eb89b01f80f08f9146b6b6). diff --git a/website/docs-templates/typescript-operations.md b/website/docs-templates/typescript-operations.md deleted file mode 100644 index 6b1f0c754c1..00000000000 --- a/website/docs-templates/typescript-operations.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -id: typescript-operations ---- - -{@operationsNote} - -{@apiDocs} diff --git a/website/docs-templates/typescript.md b/website/docs-templates/typescript.md deleted file mode 100644 index 1a7a54f5918..00000000000 --- a/website/docs-templates/typescript.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -id: typescript ---- - -{@apiDocs} diff --git a/website/docs-templates/urql-introspection.md b/website/docs-templates/urql-introspection.md deleted file mode 100644 index db365bac994..00000000000 --- a/website/docs-templates/urql-introspection.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -id: urql-introspection ---- - -{@apiDocs} - -## How to use? - -```ts -// generated by the plugin -import schema from './generated-introspection.json' -const cache = cacheExchange({ schema }) -``` - -> [Read more about Schema Awareness](https://formidable.com/open-source/urql/docs/graphcache/schema-awareness) diff --git a/website/docs/integrations/gatsby.mdx b/website/docs/integrations/gatsby.mdx deleted file mode 100644 index 45a64e3b4e3..00000000000 --- a/website/docs/integrations/gatsby.mdx +++ /dev/null @@ -1,14 +0,0 @@ ---- -id: gatsby -title: Gatsby ---- - -If you build apps using [Gatsby](https://gatsbyjs.com), you can use its built-in feature called [GraphQL Typegen](https://www.gatsbyjs.com/docs/how-to/local-development/graphql-typegen/). Under the hood it uses the GraphQL Code Generator to generate TypeScript types but you don't need to set anything up other than enabling an option. - -It also sets up everything needed for [GraphQL Config](https://www.graphql-config.com/). - -## Community Plugins - -Gatsby's GraphQL Typegen feature is solving most common use cases. If you find yourself limited by its features you should open a feature request or trying using one of these community plugins: - -- [gatsby-plugin-typegen](https://github.com/cometkim/gatsby-plugin-typegen) diff --git a/website/next-i18next.config.js b/website/next-i18next.config.js deleted file mode 100644 index fe5519f5669..00000000000 --- a/website/next-i18next.config.js +++ /dev/null @@ -1,4 +0,0 @@ -exports.i18n = { - defaultLocale: 'en', - locales: ['en'], -}; diff --git a/website/next.config.mjs b/website/next.config.mjs index 0dcc79bce3c..210f85a6c2c 100644 --- a/website/next.config.mjs +++ b/website/next.config.mjs @@ -1,17 +1,20 @@ -import { createRequire } from 'module'; -import { withGuildDocs } from '@guild-docs/server'; -import { register } from 'esbuild-register/dist/node.js'; -import { i18n } from './next-i18next.config.js'; +import nextra from 'nextra'; +import { CategoryToPackages } from './src/category-to-packages.mjs'; -const require = createRequire(import.meta.url); - -register({ extensions: ['.ts', '.tsx'] }); +const withNextra = nextra({ + theme: 'nextra-theme-docs', + themeConfig: './theme.config.tsx', + unstable_staticImage: true, +}); -const { getRoutes } = require('./routes.ts'); +const PLUGINS_REDIRECTS = Object.entries(CategoryToPackages).flatMap(([category, packageNames]) => + packageNames.map(packageName => ({ + source: `/plugins/${packageName}`, + destination: `/plugins/${category}/${packageName}`, + })) +); -export default withGuildDocs({ - i18n, - getRoutes, +export default withNextra({ eslint: { ignoreDuringBuilds: true, }, @@ -19,74 +22,64 @@ export default withGuildDocs({ // Todo: remove it before merge to master ignoreBuildErrors: true, }, + swcMinify: true, + reactStrictMode: true, webpack(config) { config.resolve.fallback = { ...config.resolve.fallback, - module: false, // Fix error - Module not found: Can't resolve 'module' - fs: false, - repl: false, - console: false, + module: false, }; return config; }, - swcMinify: false, - async redirects() { - return [ + redirects: () => + [ { source: '/docs/presets/:presetName', destination: '/plugins/:presetName-preset', - permanent: true, }, { source: '/docs/plugins/:pluginName', destination: '/plugins/:pluginName', - permanent: true, }, { source: '/docs/getting-started/config-reference/codegen-config', destination: '/docs/config-reference/codegen-config', - permanent: true, }, { source: '/docs/getting-started/codegen-config', destination: '/docs/config-reference/codegen-config', - permanent: true, }, { source: '/docs/getting-started/documents-field', destination: '/docs/config-reference/documents-field', - permanent: true, }, { source: '/docs/getting-started/schema-field', destination: '/docs/config-reference/schema-field', - permanent: true, }, { source: '/docs/getting-started/config-field', destination: '/docs/config-reference/config-field', - permanent: true, }, { source: '/docs/getting-started/lifecycle-hooks', destination: '/docs/config-reference/lifecycle-hooks', - permanent: true, }, { source: '/docs/getting-started/require-field', destination: '/docs/config-reference/require-field', - permanent: true, }, { source: '/docs/getting-started/naming-convention', destination: '/docs/config-reference/naming-convention', - permanent: true, }, { source: '/docs/getting-started/how-does-it-work', destination: '/docs/advanced/how-does-it-work', - permanent: true, }, - ]; - }, + ...PLUGINS_REDIRECTS, + ].map(redirect => ({ + ...redirect, + permanent: true, + })), }); diff --git a/website/package.json b/website/package.json index d46c5c017b2..1a902c3ffc0 100644 --- a/website/package.json +++ b/website/package.json @@ -6,25 +6,25 @@ "algolia-sync": "node scripts/algolia-ci.mjs", "start": "yarn generate-json-config && next start", "build": "yarn generate-json-config && next build", - "dev": "concurrently -r 'next-remote-watch ./docs ./src/pages/_app.tsx' 'wait-on -s 1 http://localhost:3000'", + "dev": "next dev", "lint": "eslint --ignore-path .gitignore --ext js,jsx,cjs,mjs,ts,tsx,cts,mts .", "next": "next", "generate-json-config": "ts-node generate-config-json-schema.ts" }, "devDependencies": { - "@guild-docs/algolia": "0.0.6", + "@guild-docs/algolia": "0.1.0-alpha-4da5dd0.0", "@types/classnames": "2.3.1", "@types/dedent": "0.7.0", "@types/jsonpath": "0.2.0", "@types/node": "16.11.43", "@types/react": "18.0.15", - "@types/react-dom": "18.0.6", - "concurrently": "7.2.2", - "esbuild-register": "3.3.3", + "autoprefixer": "10.4.7", + "cssnano": "5.1.12", "eslint-config-next": "12.2.2", "jsonpath": "1.1.1", - "typescript": "4.7.4", - "wait-on": "6.0.1" + "postcss": "8.4.14", + "prettier-plugin-tailwindcss": "0.1.11", + "tailwindcss": "3.1.4" }, "dependencies": { "@chakra-ui/icons": "1.1.7", @@ -72,11 +72,10 @@ "@graphql-codegen/typescript-vue-apollo": "3.3.1", "@graphql-codegen/typescript-vue-apollo-smart-ops": "2.3.1", "@graphql-codegen/typescript-vue-urql": "2.3.1", - "@guild-docs/client": "3.1.0", + "@guild-docs/client": "4.0.0-alpha-977f9d3.0", "@guild-docs/server": "4.0.0", - "@mdx-js/react": "2.1.2", "@monaco-editor/react": "4.4.5", - "@theguild/components": "1.11.8", + "@theguild/components": "2.0.0-alpha-8c5e72a.0", "classnames": "2.3.1", "date-fns": "2.28.0", "dedent": "0.7.0", @@ -85,24 +84,18 @@ "js-yaml": "4.1.0", "next": "12.2.2", "next-i18next": "11.0.0", - "next-remote-watch": "1.0.0", + "next-mdx-remote": "4.0.3", "next-seo": "5.4.0", - "node-polyfill-webpack-plugin": "2.0.0", + "nextra": "2.0.0-alpha.56", + "nextra-theme-docs": "2.0.0-alpha.59", "react": "17.0.2", "react-dom": "17.0.2", - "react-markdown": "8.0.3", - "react-select": "5.4.0", "react-icons": "4.4.0", + "react-select": "5.4.0", "react-use": "17.4.0", - "remark-admonitions": "1.2.1", - "shiki": "0.10.1", + "rehype-mdx-title": "^1.0.0", "typescript-json-schema": "0.54.0" }, - "babelMacros": { - "twin": { - "preset": "emotion" - } - }, "browserslist": { "production": [ ">0.2%", diff --git a/website/postcss.config.js b/website/postcss.config.js new file mode 100644 index 00000000000..5825d8b7d83 --- /dev/null +++ b/website/postcss.config.js @@ -0,0 +1,7 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + ...(process.env.NODE_ENV === 'production' && { cssnano: {} }), + }, +}; diff --git a/website/public/config.schema.json b/website/public/config.schema.json index d05315f1049..9a68862c569 100644 --- a/website/public/config.schema.json +++ b/website/public/config.schema.json @@ -415,6 +415,10 @@ "description": "Generates enum as TypeScript `const assertions` instead of `enum`. This can even be used to enable enum-like patterns in plain JavaScript code if you choose not to use TypeScript’s enum construct.\nDefault value: \"false\"", "type": "boolean" }, + "onlyEnums": { + "description": "This will cause the generator to emit types for enums only.\nDefault value: \"false\"", + "type": "boolean" + }, "onlyOperationTypes": { "description": "This will cause the generator to emit types for operations only (basically only enums and scalars).\nInteracts well with `preResolveTypes: true`\nDefault value: \"false\"", "type": "boolean" @@ -596,6 +600,10 @@ "description": "If set to true, it will enable support for parsing variables on fragments.\nDefault value: \"false\"", "type": "boolean" }, + "mergeFragmentTypes": { + "description": "If set to true, merge equal fragment interfaces.\nDefault value: \"false\"", + "type": "boolean" + }, "addUnderscoreToArgsType": { "description": "Adds `_` to generated `Args` types in order to avoid duplicate identifiers.", "type": "boolean" @@ -623,6 +631,10 @@ "description": "Set to `true` in order to wrap field definitions with `FieldWrapper`.\nThis is useful to allow return types such as Promises and functions.\nDefault value: \"false\"", "type": "boolean" }, + "onlyEnums": { + "description": "This will cause the generator to emit types for enums only\nDefault value: \"false\"", + "type": "boolean" + }, "onlyOperationTypes": { "description": "This will cause the generator to emit types for operations only (basically only enums and scalars)\nDefault value: \"false\"", "type": "boolean" @@ -951,6 +963,10 @@ "description": "Generates enum as TypeScript `const assertions` instead of `enum`. This can even be used to enable enum-like patterns in plain JavaScript code if you choose not to use TypeScript’s enum construct.\nDefault value: \"false\"", "type": "boolean" }, + "onlyEnums": { + "description": "This will cause the generator to emit types for enums only.\nDefault value: \"false\"", + "type": "boolean" + }, "onlyOperationTypes": { "description": "This will cause the generator to emit types for operations only (basically only enums and scalars).\nInteracts well with `preResolveTypes: true`\nDefault value: \"false\"", "type": "boolean" @@ -2765,6 +2781,10 @@ "description": "Set to `true` in order to wrap field definitions with `FieldWrapper`.\nThis is useful to allow return types such as Promises and functions.\nDefault value: \"false\"", "type": "boolean" }, + "onlyEnums": { + "description": "This will cause the generator to emit types for enums only\nDefault value: \"false\"", + "type": "boolean" + }, "onlyOperationTypes": { "description": "This will cause the generator to emit types for operations only (basically only enums and scalars)\nDefault value: \"false\"", "type": "boolean" @@ -3003,6 +3023,10 @@ "description": "If set to true, it will enable support for parsing variables on fragments.\nDefault value: \"false\"", "type": "boolean" }, + "mergeFragmentTypes": { + "description": "If set to true, merge equal fragment interfaces.\nDefault value: \"false\"", + "type": "boolean" + }, "addUnderscoreToArgsType": { "description": "Adds `_` to generated `Args` types in order to avoid duplicate identifiers.", "type": "boolean" @@ -3030,6 +3054,10 @@ "description": "Set to `true` in order to wrap field definitions with `FieldWrapper`.\nThis is useful to allow return types such as Promises and functions.\nDefault value: \"false\"", "type": "boolean" }, + "onlyEnums": { + "description": "This will cause the generator to emit types for enums only\nDefault value: \"false\"", + "type": "boolean" + }, "onlyOperationTypes": { "description": "This will cause the generator to emit types for operations only (basically only enums and scalars)\nDefault value: \"false\"", "type": "boolean" @@ -3122,7 +3150,7 @@ } }, "FragmentMatcherConfig": { - "description": "This plugin generates an introspection file but only with Interfaces and Unions, based on your GraphQLSchema.\n\nIf you are using `apollo-client` and your schema contains `interface` or `union` declaration, it's recommended to use Apollo's Fragment Matcher and the result generated by the plugin.\n\nYou can read more about it in `apollo-client` documentation: https://www.apollographql.com/docs/react/data/fragments/#fragments-on-unions-and-interfaces.\n\nFragment Matcher plugin accepts a TypeScript / JavaScript or a JSON file as an output _(`.ts, .tsx, .js, .jsx, .json`)_.\n\nBoth in TypeScript and JavaScript a default export is being used.\n\n> The output is based on the output you choose for the output file name.", + "description": "This plugin generates an introspection file but only with Interfaces and Unions, based on your GraphQLSchema.\n\nIf you are using `apollo-client` and your schema contains `interface` or `union` declaration, it's recommended to use Apollo's Fragment Matcher and the result generated by the plugin.\n\nYou can read more about it in [`apollo-client` documentation](https://apollographql.com/docs/react/data/fragments/#fragments-on-unions-and-interfaces).\n\nFragment Matcher plugin accepts a TypeScript / JavaScript or a JSON file as an output _(`.ts, .tsx, .js, .jsx, .json`)_.\n\nBoth in TypeScript and JavaScript a default export is being used.\n\n> The output is based on the output you choose for the output file name.", "type": "object", "properties": { "module": { @@ -4349,11 +4377,11 @@ }, { "const": "fragment-matcher", - "description": "This plugin generates an introspection file but only with Interfaces and Unions, based on your GraphQLSchema.\n\nIf you are using `apollo-client` and your schema contains `interface` or `union` declaration, it's recommended to use Apollo's Fragment Matcher and the result generated by the plugin.\n\nYou can read more about it in `apollo-client` documentation: https://www.apollographql.com/docs/react/data/fragments/#fragments-on-unions-and-interfaces.\n\nFragment Matcher plugin accepts a TypeScript / JavaScript or a JSON file as an output _(`.ts, .tsx, .js, .jsx, .json`)_.\n\nBoth in TypeScript and JavaScript a default export is being used.\n\n> The output is based on the output you choose for the output file name.\n\nFor more details and documentation: https://graphql-code-generator.com/docs/plugins/fragment-matcher\n\n=> Make sure to include \"@graphql-codegen/fragment-matcher\" in your package.json file and install your dependencies.\n\n" + "description": "This plugin generates an introspection file but only with Interfaces and Unions, based on your GraphQLSchema.\n\nIf you are using `apollo-client` and your schema contains `interface` or `union` declaration, it's recommended to use Apollo's Fragment Matcher and the result generated by the plugin.\n\nYou can read more about it in [`apollo-client` documentation](https://apollographql.com/docs/react/data/fragments/#fragments-on-unions-and-interfaces).\n\nFragment Matcher plugin accepts a TypeScript / JavaScript or a JSON file as an output _(`.ts, .tsx, .js, .jsx, .json`)_.\n\nBoth in TypeScript and JavaScript a default export is being used.\n\n> The output is based on the output you choose for the output file name.\n\nFor more details and documentation: https://graphql-code-generator.com/docs/plugins/fragment-matcher\n\n=> Make sure to include \"@graphql-codegen/fragment-matcher\" in your package.json file and install your dependencies.\n\n" }, { "const": "@graphql-codegen/fragment-matcher", - "description": "This plugin generates an introspection file but only with Interfaces and Unions, based on your GraphQLSchema.\n\nIf you are using `apollo-client` and your schema contains `interface` or `union` declaration, it's recommended to use Apollo's Fragment Matcher and the result generated by the plugin.\n\nYou can read more about it in `apollo-client` documentation: https://www.apollographql.com/docs/react/data/fragments/#fragments-on-unions-and-interfaces.\n\nFragment Matcher plugin accepts a TypeScript / JavaScript or a JSON file as an output _(`.ts, .tsx, .js, .jsx, .json`)_.\n\nBoth in TypeScript and JavaScript a default export is being used.\n\n> The output is based on the output you choose for the output file name.\n\nFor more details and documentation: https://graphql-code-generator.com/docs/plugins/fragment-matcher\n\n=> Make sure to include \"@graphql-codegen/fragment-matcher\" in your package.json file and install your dependencies.\n\n" + "description": "This plugin generates an introspection file but only with Interfaces and Unions, based on your GraphQLSchema.\n\nIf you are using `apollo-client` and your schema contains `interface` or `union` declaration, it's recommended to use Apollo's Fragment Matcher and the result generated by the plugin.\n\nYou can read more about it in [`apollo-client` documentation](https://apollographql.com/docs/react/data/fragments/#fragments-on-unions-and-interfaces).\n\nFragment Matcher plugin accepts a TypeScript / JavaScript or a JSON file as an output _(`.ts, .tsx, .js, .jsx, .json`)_.\n\nBoth in TypeScript and JavaScript a default export is being used.\n\n> The output is based on the output you choose for the output file name.\n\nFor more details and documentation: https://graphql-code-generator.com/docs/plugins/fragment-matcher\n\n=> Make sure to include \"@graphql-codegen/fragment-matcher\" in your package.json file and install your dependencies.\n\n" }, { "const": "urql-introspection", diff --git a/website/public/locales/en/common.json b/website/public/locales/en/common.json deleted file mode 100644 index 1dd64c715b3..00000000000 --- a/website/public/locales/en/common.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "greeting": "Hello!" -} diff --git a/website/public/style.css b/website/public/style.css index 677c6c186ec..fbd82dceb3c 100644 --- a/website/public/style.css +++ b/website/public/style.css @@ -1,58 +1,7 @@ -code[class*='language-'], -pre[class*='language-'] { - white-space: pre-wrap !important; - word-break: break-word !important; -} - -code, -code * { - font-family: 'SF Mono', 'Source Code Pro', Menlo, monospace !important; - - margin-top: 0.2em; - margin-bottom: 0.2em; -} - -article { - width: 100%; - overflow-x: auto; -} - -#__next { - font-family: TGCFont, sans-serif; -} - -.admonition-heading .chakra-heading { - padding-top: 0; -} - -.collapse-title { - font-weight: bold; - margin-bottom: 0.5rem; - cursor: pointer; - font-family: 'SF Mono', 'Source Code Pro', Menlo, monospace !important; -} - -.collapse-title > p { - display: inline-block; -} - -details > *:last-child { - padding-bottom: 2rem; -} - -.admonition { - margin-top: 10px; -} - -.admonition-heading h5 { - text-transform: none; -} - -.chakra-link { - color: #0070f3; - text-decoration: none; -} +@tailwind components; +@tailwind utilities; -.chakra-collapse a { - border-left-width: 0 !important; +/* quick fix for menu on mobile */ +.nextra-sidebar-search { + display: none; } diff --git a/website/routes.ts b/website/routes.ts index b80b1460935..e69de29bb2d 100644 --- a/website/routes.ts +++ b/website/routes.ts @@ -1,87 +0,0 @@ -import type { IRoutes } from '@guild-docs/server'; -import { GenerateRoutes } from '@guild-docs/server'; - -export function getRoutes(): IRoutes { - const Routes: IRoutes = { - _: { - 'docs/getting-started': { - $name: 'Getting Started', - $routes: [ - ['index', 'Introduction'], - ['installation', 'Installation'], - ['development-workflow', 'Development workflow'], - ], - }, - 'docs/guides': { - $name: 'Guides', - $routes: [ - ['react', 'React'], - ['vue', 'Vue.js'], - ['angular', 'Angular'], - ['svelte', 'Svelte / Kit'], - ['front-end-typescript-only', 'TypeScript only (front-end)'], - ['graphql-server-apollo-yoga', 'Apollo Server / GraphQL Yoga'], - ['graphql-modules', 'GraphQL Modules'], - ['further-reading', 'Further Reading'], - ], - }, - 'docs/config-reference': { - $name: 'Config Reference', - $routes: [ - ['codegen-config', 'codegen.yml'], - ['schema-field', 'schema field'], - ['documents-field', 'documents field'], - ['config-field', 'plugin config'], - ['require-field', 'require field'], - ['naming-convention', 'Naming Convention'], - ['lifecycle-hooks', 'Lifecycle Hooks'], - ['multiproject-config', 'Multi Project'], - ], - }, - 'docs/advanced': { - $name: 'Advanced Usage', - $routes: [ - ['generated-files-colocation', 'Generated files colocation'], - ['programmatic-usage', 'Programmatic Usage'], - ['how-does-it-work', 'How does it work?'], - ['profiler', 'Profiler'], - ], - }, - 'docs/integrations': { - $name: 'Integrations', - $routes: [ - ['vscode', 'VSCode Extension'], - ['prettier', 'Prettier'], - ['federation', 'Apollo Federation'], - ['apollo-local-state', 'apollo-local-state'], - ['create-react-app', 'create-react-app'], - ['gatsby', 'Gatsby'], - ], - }, - 'docs/custom-codegen': { - $name: 'Writing Plugins', - $routes: [ - ['index', 'What are Plugins?'], - ['plugin-structure', 'Plugin structure'], - ['validate-configuration', 'Validate Configuration'], - ['extend-schema', 'Extend Schema'], - ['using-visitor', 'Using Visitor Pattern'], - ['contributing', 'Contributing'], - ], - }, - 'docs/migration': { - $name: 'Migration Guides', - $routes: [ - ['from-0-18', 'v0.18 -> v1.0'], - ['from-0-13', 'v0.13 -> v0.17'], - ], - }, - }, - }; - - GenerateRoutes({ - Routes, - }); - - return Routes; -} diff --git a/website/scripts/algolia-ci.mjs b/website/scripts/algolia-ci.mjs index e33ab8538b4..5c0da76c716 100644 --- a/website/scripts/algolia-ci.mjs +++ b/website/scripts/algolia-ci.mjs @@ -1,25 +1,22 @@ -import { createRequire } from 'node:module'; import { resolve, dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; import { indexToAlgolia } from '@guild-docs/algolia'; -import { register } from 'esbuild-register/dist/node.js'; -import { getPackagesData } from '@guild-docs/server/npm'; -register({ extensions: ['.ts', '.tsx'] }); - -const require = createRequire(import.meta.url); const __dirname = dirname(fileURLToPath(import.meta.url)); -const { getRoutes } = require('../routes.ts'); -const { packageList } = require('../src/lib/plugins.ts'); - -getPackagesData({ packageList }).then(plugins => { - indexToAlgolia({ - routes: [getRoutes()], - plugins: plugins, - source: 'Code Generator', - dryMode: process.env.ALGOLIA_DRY_RUN === 'true', - domain: process.env.SITE_URL, - lockfilePath: resolve(__dirname, '../algolia-lockfile.json'), - }); +indexToAlgolia({ + nextra: { + docsBaseDir: resolve(__dirname, '../src/pages/'), + }, + source: 'Code Generator', + dryMode: process.env.ALGOLIA_DRY_RUN === 'true', + domain: process.env.SITE_URL, + postProcessor: objects => + objects.map(o => { + if (o.url.includes('plugins/')) { + o.type = 'Plugin'; + } + return o; + }), + lockfilePath: resolve(__dirname, '../algolia-lockfile.json'), }); diff --git a/website/src/category-to-packages.mjs b/website/src/category-to-packages.mjs new file mode 100644 index 00000000000..e85ac1351b9 --- /dev/null +++ b/website/src/category-to-packages.mjs @@ -0,0 +1,49 @@ +/* + Used to determine right category folder in plugins and for redirect legacy links in next.config#redirects + */ +export const CategoryToPackages = { + 'c-sharp': ['c-sharp-operations'], + flow: ['flow-operations', 'flow-resolvers'], + java: ['java', 'java-apollo-android', 'java-resolvers', 'kotlin'], + other: [ + 'urql-introspection', + 'time', + 'schema-ast', + 'reason-client', + 'jsdoc', + 'introspection', + 'hasura-allow-list', + 'fragment-matcher', + 'add', + ], + presets: ['near-operation-file-preset', 'import-types-preset', 'graphql-modules-preset', 'gql-tag-operations-preset'], + typescript: [ + 'named-operations-object', + 'relay-operation-optimizer', + 'typed-document-node', + 'typescript', + 'typescript-apollo-angular', + 'typescript-apollo-client-helpers', + 'typescript-apollo-next', + 'typescript-document-nodes', + 'typescript-generic-sdk', + 'typescript-graphql-files-modules', + 'typescript-graphql-request', + 'typescript-mongodb', + 'typescript-msw', + 'typescript-oclif', + 'typescript-operations', + 'typescript-react-apollo', + 'typescript-react-query', + 'typescript-resolvers', + 'typescript-rtk-query', + 'typescript-stencil-apollo', + 'typescript-svelte-apollo', + 'typescript-type-graphql', + 'typescript-urql', + 'typescript-validation-schema', + 'typescript-vue-apollo', + 'typescript-vue-apollo-smart-ops', + 'typescript-vue-urql', + ], +}; diff --git a/website/src/components/MDXTabs/MDXTab.tsx b/website/src/components/MDXTabs/MDXTab.tsx deleted file mode 100644 index ea727c2d66f..00000000000 --- a/website/src/components/MDXTabs/MDXTab.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React, { ReactNode, useContext, useEffect } from 'react'; -import { MDXTabCurrentTabsContext } from './MDXTabs'; - -const MDXTab = ({ children, label }: { label: string; children?: ReactNode }) => { - const { addTab } = useContext(MDXTabCurrentTabsContext); - - // register the tab in the tabs parent - useEffect(() => { - addTab(label); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return <>{children}; -}; - -export default MDXTab; diff --git a/website/src/components/MDXTabs/MDXTabs.tsx b/website/src/components/MDXTabs/MDXTabs.tsx deleted file mode 100644 index a7c38254b73..00000000000 --- a/website/src/components/MDXTabs/MDXTabs.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import { Tab, TabList, TabPanel, TabPanels, Tabs } from '@chakra-ui/tabs'; -import { MDXTabsCurrentTabContext } from 'components/MDXTabsCurrentTabContext'; -import React, { Children, createContext, ReactNode, useCallback, useContext, useState } from 'react'; - -// fetch active tabIndex across all instances of sharing the same namespace -const useCurrentTab = (namespace: string): [number, (i: number) => void] => { - const { value, update } = useContext(MDXTabsCurrentTabContext); - - const setTab = useCallback( - (i: number) => { - update(namespace, i); - }, - [namespace, update] - ); - - return [value[namespace], setTab]; -}; - -interface MDXTabCurrentTabsContext { - value: string[]; - addTab: (value: string) => void; -} - -export const MDXTabCurrentTabsContext = createContext({ - value: [], - // eslint-disable-next-line @typescript-eslint/no-empty-function - addTab: () => {}, -}); -const MDXTabsCurrentTabsContextProvider: React.FunctionComponent = ({ children }) => { - const [value, updateValue] = useState([]); - - const addTab = useCallback( - (tab: string) => { - updateValue(prev => [...prev, tab]); - }, - [updateValue] - ); - - return {children}; -}; - -const MDXTabsRenderer = ({ children, namespace }: { namespace: string; children: ReactNode }) => { - const [index, setTabIndex] = useCurrentTab(namespace); - const { value: tabs } = useContext(MDXTabCurrentTabsContext); - - return ( - - - {tabs.map(tab => ( - {tab} - ))} - - - {Children.toArray(children).map((c, k) => ( - {c} - ))} - - {/* */} - - ); -}; -/** - * Tab component that can contain MDX markup (ex: code snippet) - * - * @component - * @example - * - * - * - * - * Apollo code example here - * - * - * - * - * - * - * Yoga code example here - * - * - * - * - * ) - */ -const MDXTabs = ({ children, namespace }: { namespace: string; children: ReactNode }) => ( - - {children} - -); - -export default MDXTabs; diff --git a/website/src/components/MDXTabsCurrentTabContext.tsx b/website/src/components/MDXTabsCurrentTabContext.tsx deleted file mode 100644 index 215e373928f..00000000000 --- a/website/src/components/MDXTabsCurrentTabContext.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { createContext, useCallback, useState } from 'react'; - -interface Context { - value: { [k: string]: number }; - update: (ns: string, value: number) => void; -} - -export const MDXTabsCurrentTabContext = createContext({ - value: {}, - // eslint-disable-next-line @typescript-eslint/no-empty-function - update: () => {}, -}); - -export const Provider: React.FunctionComponent = ({ children }) => { - const [value, updateValue] = useState<{ [k: string]: number }>({}); - - const update = useCallback( - (ns: string, val: number) => { - updateValue({ - ...value, - [ns]: val, - }); - }, - [updateValue, value] - ); - - return {children}; -}; diff --git a/website/src/components/MDXWarning.tsx b/website/src/components/MDXWarning.tsx deleted file mode 100644 index 69071a96b15..00000000000 --- a/website/src/components/MDXWarning.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import type { FC } from 'react'; -import { Flex, Alert, AlertIcon, AlertTitle, AlertDescription } from '@chakra-ui/react'; - -export const MDXWarning: FC<{ - title: string; -}> = props => { - return ( - - - - {props.title} - - {props.children} - - ); -}; diff --git a/website/src/components/index.ts b/website/src/components/index.ts new file mode 100644 index 00000000000..1a902c11384 --- /dev/null +++ b/website/src/components/index.ts @@ -0,0 +1,2 @@ +export { PackageCmd } from './package-cmd'; +export { PackageApiDocs, PackageHeader } from './package-api-docs'; diff --git a/website/src/components/live-demo/CodegenOutput.tsx b/website/src/components/live-demo/CodegenOutput.tsx index b71a068d330..33431aa194c 100644 --- a/website/src/components/live-demo/CodegenOutput.tsx +++ b/website/src/components/live-demo/CodegenOutput.tsx @@ -1,13 +1,13 @@ -import { FC, useEffect, useState } from 'react'; +import { ReactElement, useEffect, useState } from 'react'; import Editor from './Editor'; import { basename } from 'path'; import classes from './styles.module.css'; import classnames from 'classnames'; -const CodegenOutput: FC = ({ outputArray, editorProps, error }) => { +const CodegenOutput = ({ outputArray, editorProps, error }): ReactElement => { const [index, setIndex] = useState(0); - const editorContent = error ? error : outputArray && outputArray[index] ? outputArray[index].content : ''; + const editorContent = error || outputArray?.[index].content || ''; useEffect(() => { setIndex(0); diff --git a/website/src/components/live-demo/Editor.tsx b/website/src/components/live-demo/Editor.tsx index aa8327ad4bc..7d77411d37d 100644 --- a/website/src/components/live-demo/Editor.tsx +++ b/website/src/components/live-demo/Editor.tsx @@ -1,16 +1,20 @@ -import { FC } from 'react'; -import { useThemeContext } from '@theguild/components'; +import { ReactElement } from 'react'; +import { useTheme } from 'next-themes'; import MonacoEditor from '@monaco-editor/react'; -import { canUseDOM } from '../../utils'; +import { canUseDOM } from '@/utils'; -const Editor: FC<{ lang: string; value: string; readOnly?: boolean; onEdit: (value?: string) => void }> = ({ +const Editor = ({ value, lang, readOnly, onEdit, -}) => { - const { isDarkTheme } = useThemeContext(); - +}: { + lang: string; + value: string; + readOnly?: boolean; + onEdit: (value?: string) => void; +}): ReactElement | null => { + const { theme } = useTheme(); if (!canUseDOM) { return null; } @@ -19,7 +23,7 @@ const Editor: FC<{ lang: string; value: string; readOnly?: boolean; onEdit: (val onEdit(newValue)} + onChange={onEdit} /> ); }; diff --git a/website/src/components/live-demo/LiveDemo.tsx b/website/src/components/live-demo/LiveDemo.tsx index 9e3e4250ccf..f00d3e3f516 100644 --- a/website/src/components/live-demo/LiveDemo.tsx +++ b/website/src/components/live-demo/LiveDemo.tsx @@ -1,16 +1,14 @@ -import { useState, useEffect, Suspense, Fragment } from 'react'; +import { useState, useEffect, Suspense, ReactElement } from 'react'; import { load } from 'js-yaml'; import dynamic from 'next/dynamic'; import Image from 'next/image'; +import { useTheme } from '@theguild/components'; import Select from 'react-select'; -// import ReactMarkdown from 'react-markdown'; -import { useThemeContext } from '@theguild/components'; import { EXAMPLES, EXAMPLES_ICONS } from './examples'; import { getMode } from './formatter'; import { generate } from './generate'; import { Loading } from '../ui/Loading'; import LiveDemoEditors from './LiveDemoEditors'; -import classes from './styles.module.css'; const ErrorBoundary = dynamic(import('./ErrorBoundary'), { ssr: false }); @@ -49,8 +47,9 @@ const DEFAULT_EXAMPLE = { index: 0, } as const; -export const LiveDemo = () => { - const { isDarkTheme } = useThemeContext(); +export const LiveDemo = (): ReactElement => { + const { theme } = useTheme(); + const isDarkTheme = theme === 'dark'; const [template, setTemplate] = useState(`${DEFAULT_EXAMPLE.catName}__${DEFAULT_EXAMPLE.index}`); const [schema, setSchema] = useState(EXAMPLES[DEFAULT_EXAMPLE.catName][DEFAULT_EXAMPLE.index].schema); const [documents, setDocuments] = useState(EXAMPLES[DEFAULT_EXAMPLE.catName][DEFAULT_EXAMPLE.index].documents); @@ -82,65 +81,48 @@ export const LiveDemo = () => { // } return ( - <> -
-

Choose Live Example:

-
- ({ + ...styles, + fontSize: 13, + ...(isFocused && isDarkTheme && { backgroundColor: 'gray' }), + }), + }} + isMulti={false} + isClearable={false} + onChange={e => changeTemplate(e.selectId)} + getOptionValue={o => o.selectId} + getOptionLabel={o => ( +
+ {o.name} + {o.tags?.map((t, index) => { + const icon = EXAMPLES_ICONS[t]; + const key = `${o.name}_${index}`; + return icon ? ( + {icon.alt} + ) : ( + + {t} + + ); + })} +
+ )} + defaultValue={groupedExamples[0].options[0]} + options={groupedExamples} + />
-
+
}> {
- +
); }; diff --git a/website/src/components/live-demo/examples.ts b/website/src/components/live-demo/examples.ts index 9e35b16b8d3..bc9fc31e8d2 100644 --- a/website/src/components/live-demo/examples.ts +++ b/website/src/components/live-demo/examples.ts @@ -31,7 +31,7 @@ export const EXAMPLES_ICONS = { src: '/assets/img/icons/mongodb.png', }, nodejs: { - alt: 'NodeJS', + alt: 'Node.js', src: '/assets/img/icons/nodejs.svg', }, react: { @@ -181,7 +181,8 @@ export const EXAMPLES = { }, { name: 'TypedDocumentNode', - description: `This plugin generates a per-compiled version of \`DocumentNode\`, with the result and variables types bundled into the object, using this library: https://github.com/dotansimha/graphql-typed-document-node`, + description: + 'This plugin generates a per-compiled version of `DocumentNode`, with the result and variables types bundled into the object, using this library: https://github.com/dotansimha/graphql-typed-document-node', tags: ['typescript', 'frontend'], config: `generates: operations-types.ts: @@ -204,7 +205,8 @@ export const EXAMPLES = { }, { name: 'React-Query Hooks', - description: `This example uses types generated by \`typescript\` and \`typescript-operations\`, and creates a fully type-safe React Hooks, based on your GraphQL operations, that wraps "react-query" hooks.`, + description: + 'This example uses types generated by `typescript` and `typescript-operations`, and creates a fully type-safe React Hooks, based on your GraphQL operations, that wraps "react-query" hooks.', tags: ['typescript', 'react', 'react-query', 'frontend'], config: `generates: types-and-hooks.tsx: diff --git a/website/src/components/live-demo/generate.ts b/website/src/components/live-demo/generate.ts index 56da5cbbf23..27b53444188 100644 --- a/website/src/components/live-demo/generate.ts +++ b/website/src/components/live-demo/generate.ts @@ -3,7 +3,7 @@ import { codegen } from '@graphql-codegen/core'; import { parse } from 'graphql'; import { pluginLoaderMap, presetLoaderMap } from './plugins'; import { normalizeConfig } from './utils'; -import { canUseDOM } from '../../utils'; +import { canUseDOM } from '@/utils'; if (canUseDOM) { process.hrtime = () => [0, 0]; // Fix error - TypeError: process.hrtime is not a function @@ -18,14 +18,14 @@ export async function generate(config: string, schema: string, documents?: strin const runConfigurations = []; for (const [filename, outputOptions] of Object.entries(generates)) { - const hasPreset = !!outputOptions.preset; + const hasPreset = Boolean(outputOptions.preset); const plugins = normalizeConfig(outputOptions.plugins || outputOptions); const outputConfig = outputOptions.config; const pluginMap = {}; await Promise.all( plugins.map(async pluginElement => { - const pluginName = Object.keys(pluginElement)[0]; + const [pluginName] = Object.keys(pluginElement); try { pluginMap[pluginName] = await pluginLoaderMap[pluginName](); } catch (e) { diff --git a/website/src/components/live-demo/styles.module.css b/website/src/components/live-demo/styles.module.css index 7245ae76a61..4bb62a5ede4 100644 --- a/website/src/components/live-demo/styles.module.css +++ b/website/src/components/live-demo/styles.module.css @@ -1,53 +1,10 @@ @import url('https://fonts.googleapis.com/css2?family=Inconsolata&display=swap'); -.picker { - padding-left: 30px; - padding-right: 30px; - padding-bottom: 5px; - margin: 30px auto 0 auto; - text-align: center; - width: 50%; -} - -.exampleDesc { - font-size: 0.9em; - border-left: 10px #f1f1f1 solid; - padding-left: 10px; - margin-top: 10px; - text-align: left; -} - .react-monaco-editor-container, .monaco-editor { height: 400px; } -.exampleTag { - background-color: gainsboro; - border-radius: 10px; - font-size: 11px; - padding: 3px 5px 3px 5px; - color: black !important; - margin-right: 3px; - margin-left: 3px; -} - -.exampleTags { - padding-right: 20px; - float: right; - display: flex; -} - -.container { - display: flex; - align-items: flex-start; - justify-content: stretch; - border-top: 1px solid #e5e5e5; - border-bottom: 1px solid #e5e5e5; - margin-top: 3px; - font-size: 12px; -} - .column { align-self: stretch; flex-flow: column; diff --git a/website/src/components/package-api-docs.tsx b/website/src/components/package-api-docs.tsx new file mode 100644 index 00000000000..55775e40361 --- /dev/null +++ b/website/src/components/package-api-docs.tsx @@ -0,0 +1,89 @@ +import { ReactElement } from 'react'; +import { useSSG } from 'nextra/ssg'; +import { components } from 'nextra-theme-docs/theme'; +import Callout from 'nextra-theme-docs/callout'; +import { MDXRemote } from 'next-mdx-remote'; +import { PackageCmd } from './package-cmd'; +import { format } from 'date-fns'; + +export const PackageApiDocs = (): ReactElement => { + // Get the data from SSG, and render it as a component. + const { pluginData } = useSSG(); + + return ; +}; + +export const PackageHeader = ({ + isDev = true, + hasOperationsNote = false, +}: { + isDev?: boolean; + hasOperationsNote?: boolean; +}): ReactElement => { + // Get the data from SSG, and render it as a component. + const { pluginData } = useSSG(); + + return ( + <> +

{pluginData.title}

+

Package Details

+ {/* Unfortunately Nextra doesn't support import `.mdx` files in `.mdx`, so I copied generated code + * and exported as React component + */} +
+ + + + + + + + + + + + + + + + + + + + + + + +
Package + + {pluginData.npmPackage} + +
Weekly Downloads + downloads +
Version + license +
License + license +
Updated{format(new Date(pluginData.stats.modifiedDate), 'MMM do, yyyy')}
+

Installation

+ + {hasOperationsNote && ( + +

+ Usage Requirements +

+

+ In order to use this GraphQL Codegen plugin, please make sure that you have GraphQL operations ( + query / mutation / subscription and fragment) set as{' '} + documents: … in your codegen.yml. +

+

+ Without loading your GraphQL operations (query, mutation,{' '} + subscription and fragment), you won't see any change in the generated output. +

+
+ )} +
+ + ); +}; diff --git a/website/src/components/package-cmd.tsx b/website/src/components/package-cmd.tsx new file mode 100644 index 00000000000..140a71b29b7 --- /dev/null +++ b/website/src/components/package-cmd.tsx @@ -0,0 +1,87 @@ +import { ReactElement, ReactNode } from 'react'; +import { Tabs, Tab } from 'nextra-theme-docs/tabs'; + +const CodeTab = ({ children }: { children: ReactNode }): ReactElement => { + return ( + + {/* Unfortunately Nextra doesn't support import `.mdx` files in `.mdx`, so I copied generated code + * and exported as React component + */} +
+        
+          
+            {children}
+          
+        
+      
+
+ ); +}; + +const PACKAGE_MANAGERS = ['yarn', 'npm', 'pnpm'] as const; + +type PackageMap = Record; + +const Add: PackageMap = { + yarn: 'yarn add', + npm: 'npm install', + pnpm: 'pnpm add', +}; + +const Run: PackageMap = { + yarn: 'yarn', + npm: 'npm run', + pnpm: 'pnpm', +}; + +const Install: PackageMap = { + yarn: 'yarn', + npm: 'npm install', + pnpm: 'pnpm install', +}; + +const Init: PackageMap = { + yarn: 'yarn init --yes', + npm: 'npm init --yes', + pnpm: 'pnpm init', +}; + +type Command = { + name: string; + cmd: 'add' | 'run' | 'install' | 'init'; + isNpx?: boolean; +}; + +export const PackageCmd = ({ packages }: { packages: (string | Command)[] }) => { + const pkgs = packages.map(pkg => + typeof pkg === 'string' + ? ({ + name: pkg, + cmd: 'add', + } as Command) + : pkg + ); + + return ( + + {PACKAGE_MANAGERS.map(pkgManager => ( + + {pkgs + .map(pkg => { + switch (pkg.cmd) { + case 'run': + return `${pkgManager === 'npm' && pkg.isNpx ? 'npx' : Run[pkgManager]} ${pkg.name}`; + case 'install': + return `${Install[pkgManager]}${pkg.name ? ` ${pkg.name}` : ''}`; + case 'init': + return Init[pkgManager]; + default: + return `${Add[pkgManager]} ${pkg.name}`; + } + }) + .join('\n')} + + ))} + + ); +}; diff --git a/website/src/components/plugins.tsx b/website/src/components/plugins.tsx new file mode 100644 index 00000000000..17ad5a4fb94 --- /dev/null +++ b/website/src/components/plugins.tsx @@ -0,0 +1,97 @@ +import { ReactElement, useMemo } from 'react'; +import { useSSG } from 'nextra/ssg'; +import { compareDesc } from 'date-fns'; +import { handlePushRoute } from '@guild-docs/client'; +import { CompiledMDX } from '@guild-docs/server'; +import { PackageWithStats } from '@guild-docs/server/npm'; +import { MarketplaceSearch } from '@theguild/components'; +import { IMarketplaceItemProps } from '@theguild/components/dist/types/components'; +import Markdown from '@/components/ui/Markdown'; +import { ALL_TAGS } from '@/lib/plugins'; +import { CategoryToPackages } from '@/category-to-packages.mjs'; + +type MarketplaceProps = { + data: (PackageWithStats & { + description: CompiledMDX; + content: CompiledMDX; + })[]; +}; + +const categoryEntries = Object.entries(CategoryToPackages); + +export const Plugins = (): ReactElement => { + const { data } = useSSG() as MarketplaceProps; + + const marketplaceItems: (IMarketplaceItemProps & { raw: PackageWithStats })[] = useMemo( + () => + data.map(plugin => { + const [category] = categoryEntries.find(([, packageNames]) => packageNames.includes(plugin.identifier)) || []; + const linkHref = `/plugins/${category}/${plugin.identifier}`; + return { + raw: plugin, + tags: plugin.tags, + title: plugin.title, + link: { + href: linkHref, + title: `${plugin.title} plugin details`, + onClick: ev => handlePushRoute(linkHref, ev), + }, + description: , + update: plugin.stats?.modifiedDate || new Date().toISOString(), + image: plugin.iconUrl + ? { + height: 60, + width: 60, + src: plugin.iconUrl, + alt: plugin.title, + } + : undefined, + }; + }), + [data] + ); + + const recentlyUpdatedItems = useMemo( + () => [...marketplaceItems].sort((a, b) => compareDesc(new Date(a.update), new Date(b.update))), + [marketplaceItems] + ); + + const trendingItems = useMemo( + () => + marketplaceItems + .filter(i => i.raw.stats?.weeklyNPMDownloads) + .sort((a, b) => { + const aMonthlyDownloads = a.raw.stats?.weeklyNPMDownloads || 0; + const bMonthlyDownloads = b.raw.stats?.weeklyNPMDownloads || 0; + + return bMonthlyDownloads - aMonthlyDownloads; + }), + [marketplaceItems] + ); + + return ( + + ); +}; diff --git a/website/src/components/ui/Markdown.tsx b/website/src/components/ui/Markdown.tsx index 45762ea9b62..416bde9d7d1 100644 --- a/website/src/components/ui/Markdown.tsx +++ b/website/src/components/ui/Markdown.tsx @@ -1,6 +1,5 @@ import type { CompiledMDX } from '@guild-docs/server'; -import type { ComponentProps } from 'react'; -import { FC } from 'react'; +import type { ComponentProps, ReactElement } from 'react'; import { Link } from '@chakra-ui/react'; import { MDX } from '@guild-docs/client'; @@ -20,7 +19,7 @@ const extraComponents = { }, }; -const Markdown: FC<{ content: CompiledMDX }> = ({ content }) => { +const Markdown = ({ content }: { content: CompiledMDX }): ReactElement => { return ; }; diff --git a/website/src/lib/docs-generator.ts b/website/src/lib/docs-generator.ts index 4528651e272..86cfc02f517 100644 --- a/website/src/lib/docs-generator.ts +++ b/website/src/lib/docs-generator.ts @@ -14,7 +14,6 @@ export function generateDocs(schema: TJS.Definition, types: (PluginConfig | Pres content += `${subSchema.description}\n\n`; } - content += ``; if (apiDocs) { content += `### Config API Reference\n\n${apiDocs}`; } @@ -31,7 +30,7 @@ function generateContentForSchema(schema: TJS.Definition): string { const prop = schema.properties![propName] as TJS.Definition; return `
- + ${propName} diff --git a/website/src/lib/get-npm-info.tsx b/website/src/lib/get-npm-info.tsx new file mode 100644 index 00000000000..589237f67e9 --- /dev/null +++ b/website/src/lib/get-npm-info.tsx @@ -0,0 +1,39 @@ +import { getPackagesData } from '@guild-docs/server/npm'; +import { PACKAGES } from './plugins'; +import { transformDocs } from './transform'; +import { compileMdx } from 'nextra/compile'; + +export const getNpmInfo = (packageName: string) => + // Passing packageName for `getStaticProps` of mdx files in plugins directory + async function getStaticProps() { + const [pluginData] = await getPackagesData({ + idSpecific: packageName, + packageList: PACKAGES, + }); + const generatedDocs = transformDocs(); + + const source = + generatedDocs.docs[packageName] || + pluginData.stats?.readme?.replace('ERROR: No README data found!', '').replaceAll('```yml', '```yaml') || + ''; + + const mdx = await compileMdx(source, { + outputFormat: 'function-body', + jsx: false, + }); + + return { + props: { + // We add an `ssg` field to the page props, + // which will be provided to the Nextra `useSSG` hook. + ssg: { + pluginData: { + ...pluginData, + compiledSource: mdx.result, + }, + }, + }, + // The page will be considered as stale and regenerated every 24 hours. + revalidate: 60 * 60 * 24, + }; + }; diff --git a/website/src/lib/plugins.ts b/website/src/lib/plugins.ts index 2e7cfa349d4..2684e2b2b27 100644 --- a/website/src/lib/plugins.ts +++ b/website/src/lib/plugins.ts @@ -1,7 +1,4 @@ import type { Package } from '@guild-docs/server/npm'; -import { existsSync, readFileSync } from 'fs'; -import { transformDocs } from './transform'; -import { canUseDOM } from '../utils'; export const ALL_TAGS = [ 'typescript', @@ -33,51 +30,63 @@ export const ALL_TAGS = [ export type Tags = typeof ALL_TAGS[number]; -let generatedDocs: ReturnType | null = null; -let staticMapping: Record | null = null; - -function loadGeneratedReadme(options: { templateFile: string; pluginIdentifier: string }): string { - if (!generatedDocs) { - generatedDocs = transformDocs(); - } - - if (!staticMapping) { - staticMapping = { - '{@operationsNote}': readFileSync(`docs-templates/client-note.md`, 'utf-8'), - '{@javaInstallation}': readFileSync(`docs-templates/java-installation.md`, 'utf-8'), - }; - } - - let templateBase = '{@apiDocs}'; - - if (existsSync(options.templateFile)) { - templateBase = readFileSync(options.templateFile, 'utf-8'); - } - - let out = templateBase.replace('{@apiDocs}', generatedDocs.docs[options.pluginIdentifier] || ''); - - Object.keys(staticMapping).forEach(key => { - out = out.replace(key, staticMapping![key]); - }); - - return out; -} - -const PACKAGES: Package[] = [ +export const PACKAGES: Package[] = [ { - identifier: 'near-operation-file-preset', - title: 'near-operation-file-preset', - npmPackage: '@graphql-codegen/near-operation-file-preset', + identifier: 'add', + title: 'Add', + npmPackage: '@graphql-codegen/add', + iconUrl: '/assets/img/icons/graphql.svg', + tags: ['plugin'], + }, + { + identifier: 'c-sharp-operations', + title: 'C# Operations', + npmPackage: '@graphql-codegen/c-sharp-operations', + iconUrl: '/assets/img/icons/csharp.svg', + tags: ['plugin', 'csharp'], + }, + { + identifier: 'flow-operations', + title: 'Flow Operations', + npmPackage: '@graphql-codegen/flow-operations', + iconUrl: '/assets/img/icons/flow.svg', + tags: ['plugin', 'flow'], + }, + { + identifier: 'flow-resolvers', + title: 'Flow Resolvers', + npmPackage: '@graphql-codegen/flow-resolvers', + iconUrl: '/assets/img/icons/flow.svg', + tags: ['plugin', 'flow'], + }, + { + identifier: 'fragment-matcher', + title: 'Fragment Matcher', + npmPackage: '@graphql-codegen/fragment-matcher', + iconUrl: '/assets/img/icons/graphql.svg', + tags: ['plugin', 'apollo'], + }, + { + identifier: 'gql-tag-operations-preset', + title: 'gql-tag-operations-preset', + npmPackage: '@graphql-codegen/gql-tag-operations-preset', iconUrl: '/assets/img/icons/codegen.svg', - tags: ['preset', 'utilities'], + tags: ['preset', 'utilities', 'typescript'], }, { identifier: 'graphql-modules-preset', title: 'graphql-modules-preset', npmPackage: '@graphql-codegen/graphql-modules-preset', - iconUrl: 'https://www.graphql-modules.com/img/just-logo.svg', + iconUrl: 'https://graphql-modules.com/img/just-logo.svg', tags: ['preset', 'utilities', 'resolvers'], }, + { + identifier: 'hasura-allow-list', + title: 'Hasura Allow List', + npmPackage: '@graphql-codegen/hasura-allow-list', + iconUrl: '/assets/img/icons/hasura.svg', + tags: ['plugin', 'utilities', 'hasura'], + }, { identifier: 'import-types-preset', title: 'import-types-preset', @@ -86,11 +95,46 @@ const PACKAGES: Package[] = [ tags: ['preset', 'utilities'], }, { - identifier: 'gql-tag-operations-preset', - title: 'gql-tag-operations-preset', - npmPackage: '@graphql-codegen/gql-tag-operations-preset', - iconUrl: '/assets/img/icons/codegen.svg', - tags: ['preset', 'utilities', 'typescript'], + identifier: 'introspection', + title: 'Introspection', + npmPackage: '@graphql-codegen/introspection', + iconUrl: '/assets/img/icons/graphql.svg', + tags: ['plugin', 'utilities'], + }, + { + identifier: 'java', + title: 'Java', + npmPackage: '@graphql-codegen/java', + iconUrl: '/assets/img/icons/java.svg', + tags: ['plugin', 'java'], + }, + { + identifier: 'java-apollo-android', + title: 'Java Apollo Android', + npmPackage: '@graphql-codegen/java-apollo-android', + iconUrl: '/assets/img/icons/java.svg', + tags: ['plugin', 'java', 'apollo', 'android'], + }, + { + identifier: 'java-resolvers', + title: 'Java Resolvers', + npmPackage: '@graphql-codegen/java-resolvers', + iconUrl: '/assets/img/icons/java.svg', + tags: ['plugin', 'java'], + }, + { + identifier: 'jsdoc', + title: 'JSDoc', + npmPackage: '@graphql-codegen/jsdoc', + iconUrl: '/assets/img/icons/graphql.svg', + tags: ['plugin', 'jsdoc'], + }, + { + identifier: 'kotlin', + title: 'Kotlin', + npmPackage: '@graphql-codegen/kotlin', + iconUrl: '/assets/img/icons/java.svg', + tags: ['plugin', 'java', 'kotlin'], }, { identifier: 'named-operations-object', @@ -99,6 +143,41 @@ const PACKAGES: Package[] = [ iconUrl: '/assets/img/icons/typescript.svg', tags: ['plugin', 'typescript'], }, + { + identifier: 'near-operation-file-preset', + title: 'near-operation-file-preset', + npmPackage: '@graphql-codegen/near-operation-file-preset', + iconUrl: '/assets/img/icons/codegen.svg', + tags: ['preset', 'utilities'], + }, + { + identifier: 'reason-client', + title: 'Reason Client', + npmPackage: 'graphql-codegen-reason-client', + iconUrl: 'https://pbs.twimg.com/profile_images/1004185780313395200/ImZxrDWf_400x400.jpg', + tags: ['plugin', 'reason'], + }, + { + identifier: 'relay-operation-optimizer', + title: 'Relay Operation Optimizer', + npmPackage: '@graphql-codegen/relay-operation-optimizer', + iconUrl: '/assets/img/icons/graphql.svg', + tags: ['plugin', 'relay'], + }, + { + identifier: 'schema-ast', + title: 'Schema AST', + npmPackage: '@graphql-codegen/schema-ast', + iconUrl: '/assets/img/icons/graphql.svg', + tags: ['plugin', 'utilities'], + }, + { + identifier: 'time', + title: 'Time', + npmPackage: '@graphql-codegen/time', + iconUrl: '/assets/img/icons/graphql.svg', + tags: ['plugin', 'utilities'], + }, { identifier: 'typed-document-node', title: 'TypedDocumentNode', @@ -106,6 +185,13 @@ const PACKAGES: Package[] = [ iconUrl: '/assets/img/icons/typescript.svg', tags: ['plugin', 'typescript'], }, + { + identifier: 'typescript', + title: 'TypeScript', + npmPackage: '@graphql-codegen/typescript', + iconUrl: '/assets/img/icons/typescript.svg', + tags: ['plugin', 'typescript'], + }, { identifier: 'typescript-apollo-angular', title: 'TypeScript Apollo Angular', @@ -113,13 +199,6 @@ const PACKAGES: Package[] = [ iconUrl: '/assets/img/icons/angular.svg', tags: ['plugin', 'typescript', 'apollo', 'angular'], }, - { - identifier: 'typescript-msw', - title: 'typescript-msw', - npmPackage: '@graphql-codegen/typescript-msw', - iconUrl: 'https://raw.githubusercontent.com/mswjs/msw/HEAD/media/msw-logo.svg', - tags: ['plugin', 'typescript', 'utilities'], - }, { identifier: 'typescript-apollo-client-helpers', title: 'Apollo-Client Helpers', @@ -169,6 +248,13 @@ const PACKAGES: Package[] = [ iconUrl: '/assets/img/icons/mongodb.png', tags: ['plugin', 'typescript', 'mongodb'], }, + { + identifier: 'typescript-msw', + title: 'typescript-msw', + npmPackage: '@graphql-codegen/typescript-msw', + iconUrl: 'https://raw.githubusercontent.com/mswjs/msw/HEAD/media/msw-logo.svg', + tags: ['plugin', 'typescript', 'utilities'], + }, { identifier: 'typescript-oclif', title: 'TypeScript oclif', @@ -183,13 +269,6 @@ const PACKAGES: Package[] = [ iconUrl: '/assets/img/icons/typescript.svg', tags: ['plugin', 'typescript'], }, - { - identifier: 'typescript', - title: 'TypeScript', - npmPackage: '@graphql-codegen/typescript', - iconUrl: '/assets/img/icons/typescript.svg', - tags: ['plugin', 'typescript'], - }, { identifier: 'typescript-react-apollo', title: 'TypeScript React Apollo', @@ -246,6 +325,13 @@ const PACKAGES: Package[] = [ iconUrl: '/assets/img/icons/typescript.svg', tags: ['plugin', 'typescript', 'urql', 'react'], }, + { + identifier: 'typescript-validation-schema', + title: 'TypeScript Validation Schema', + npmPackage: 'graphql-codegen-typescript-validation-schema', + iconUrl: '/assets/img/icons/graphql.svg', + tags: ['plugin', 'validation', 'yup', 'zod', 'typescript'], + }, { identifier: 'typescript-vue-apollo', title: 'TypeScript Vue Apollo Composition API', @@ -267,111 +353,6 @@ const PACKAGES: Package[] = [ iconUrl: '/assets/img/icons/vue.svg', tags: ['plugin', 'typescript', 'vue', 'urql'], }, - { - identifier: 'c-sharp-operations', - title: 'C# Operations', - npmPackage: '@graphql-codegen/c-sharp-operations', - iconUrl: '/assets/img/icons/csharp.svg', - tags: ['plugin', 'csharp'], - }, - { - identifier: 'flow-operations', - title: 'Flow Operations', - npmPackage: '@graphql-codegen/flow-operations', - iconUrl: '/assets/img/icons/flow.svg', - tags: ['plugin', 'flow'], - }, - { - identifier: 'flow-resolvers', - title: 'Flow Resolvers', - npmPackage: '@graphql-codegen/flow-resolvers', - iconUrl: '/assets/img/icons/flow.svg', - tags: ['plugin', 'flow'], - }, - { - identifier: 'java', - title: 'Java', - npmPackage: '@graphql-codegen/java', - iconUrl: '/assets/img/icons/java.svg', - tags: ['plugin', 'java'], - }, - { - identifier: 'java-apollo-android', - title: 'Java Apollo Android', - npmPackage: '@graphql-codegen/java-apollo-android', - iconUrl: '/assets/img/icons/java.svg', - tags: ['plugin', 'java', 'apollo', 'android'], - }, - { - identifier: 'java-resolvers', - title: 'Java Resolvers', - npmPackage: '@graphql-codegen/java-resolvers', - iconUrl: '/assets/img/icons/java.svg', - tags: ['plugin', 'java'], - }, - { - identifier: 'kotlin', - title: 'Kotlin', - npmPackage: '@graphql-codegen/kotlin', - iconUrl: '/assets/img/icons/java.svg', - tags: ['plugin', 'java', 'kotlin'], - }, - { - identifier: 'reason-client', - title: 'Reason Client', - npmPackage: 'graphql-codegen-reason-client', - iconUrl: 'https://pbs.twimg.com/profile_images/1004185780313395200/ImZxrDWf_400x400.jpg', - tags: ['plugin', 'reason'], - }, - { - identifier: 'add', - title: 'Add', - npmPackage: '@graphql-codegen/add', - iconUrl: '/assets/img/icons/graphql.svg', - tags: ['plugin'], - }, - { - identifier: 'fragment-matcher', - title: 'Fragment Matcher', - npmPackage: '@graphql-codegen/fragment-matcher', - iconUrl: '/assets/img/icons/graphql.svg', - tags: ['plugin', 'apollo'], - }, - { - identifier: 'introspection', - title: 'Introspection', - npmPackage: '@graphql-codegen/introspection', - iconUrl: '/assets/img/icons/graphql.svg', - tags: ['plugin', 'utilities'], - }, - { - identifier: 'jsdoc', - title: 'JSDoc', - npmPackage: '@graphql-codegen/jsdoc', - iconUrl: '/assets/img/icons/graphql.svg', - tags: ['plugin', 'jsdoc'], - }, - { - identifier: 'relay-operation-optimizer', - title: 'Relay Operation Optimizer', - npmPackage: '@graphql-codegen/relay-operation-optimizer', - iconUrl: '/assets/img/icons/graphql.svg', - tags: ['plugin', 'relay'], - }, - { - identifier: 'schema-ast', - title: 'Schema AST', - npmPackage: '@graphql-codegen/schema-ast', - iconUrl: '/assets/img/icons/graphql.svg', - tags: ['plugin', 'utilities'], - }, - { - identifier: 'time', - title: 'Time', - npmPackage: '@graphql-codegen/time', - iconUrl: '/assets/img/icons/graphql.svg', - tags: ['plugin', 'utilities'], - }, { identifier: 'urql-introspection', title: 'Urql Introspection for Schema Awareness', @@ -379,28 +360,4 @@ const PACKAGES: Package[] = [ iconUrl: '/assets/img/icons/graphql.svg', tags: ['plugin', 'urql', 'typescript'], }, - { - identifier: 'typescript-validation-schema', - title: 'TypeScript Validation Schema', - npmPackage: 'graphql-codegen-typescript-validation-schema', - iconUrl: '/assets/img/icons/graphql.svg', - tags: ['plugin', 'validation', 'yup', 'zod', 'typescript'], - }, - { - identifier: 'hasura-allow-list', - title: 'Hasura Allow List', - npmPackage: '@graphql-codegen/hasura-allow-list', - iconUrl: '/assets/img/icons/hasura.svg', - tags: ['plugin', 'utilities', 'hasura'], - }, ]; - -export const packageList = PACKAGES.map(p => ({ - ...p, - readme: canUseDOM - ? '' - : loadGeneratedReadme({ - pluginIdentifier: p.identifier, - templateFile: `docs-templates/${p.identifier}.md`, - }), -})); diff --git a/website/src/lib/transform.ts b/website/src/lib/transform.ts index 4e9d2d412b5..f28045befd9 100644 --- a/website/src/lib/transform.ts +++ b/website/src/lib/transform.ts @@ -43,7 +43,7 @@ export function transformDocs() { ); if (!schema.definitions) { - throw new Error(`Config-transform: "schema.definitions" is not defined`); + throw new Error('Config-transform: "schema.definitions" is not defined'); } // This will make sure to add a nice auto complete for all built-in plugins and their configuration mapped diff --git a/website/src/pages/_app.tsx b/website/src/pages/_app.tsx index f8eec953f0b..e9ea5b7b9ac 100644 --- a/website/src/pages/_app.tsx +++ b/website/src/pages/_app.tsx @@ -1,187 +1,29 @@ -import type { FC } from 'react'; -import type { AppProps } from 'next/app'; -import dynamic from 'next/dynamic'; - -import { appWithTranslation } from 'next-i18next'; -import { extendTheme, theme as chakraTheme } from '@chakra-ui/react'; -import { mode } from '@chakra-ui/theme-tools'; -import { - ExtendComponents, - handlePushRoute, - CombinedThemeProvider, - DocsPage, - AppSeoProps, - useGoogleAnalytics, -} from '@guild-docs/client'; -import { Header, Subheader, FooterExtended } from '@theguild/components'; -import 'remark-admonitions/styles/classic.css'; -import '../../public/style.css'; +import { ReactElement } from 'react'; import Script from 'next/script'; -import React from 'react'; -import { Provider as MDXTabsCurrentTabContextProvider } from 'components/MDXTabsCurrentTabContext'; -import { MDXWarning } from 'components/MDXWarning'; +import { AppProps } from 'next/app'; +import { useGoogleAnalytics } from '@guild-docs/client'; +import { Header, ThemeProvider, FooterExtended } from '@theguild/components'; +import 'nextra-theme-docs/style.css'; +import '../../public/style.css'; import '@algolia/autocomplete-theme-classic'; import '@theguild/components/dist/static/css/SearchBarV2.css'; -const MDXTabs = dynamic(() => import('components/MDXTabs/MDXTabs')); -const MDXTab = dynamic(() => import('components/MDXTabs/MDXTab')); - -ExtendComponents({ - HelloWorld() { - return

Hello World!

; - }, - MDXTabs, - MDXTab, - MDXWarning, -}); - -const styles: typeof chakraTheme['styles'] = { - global: props => ({ - body: { - bg: mode('white', 'gray.850')(props), - }, - }), -}; - const accentColor = '#0070f3'; -const theme = extendTheme({ - colors: { - gray: { - 50: '#fafafa', - 100: '#f5f5f5', - 200: '#e5e5e5', - 300: '#5c3a3a', - 400: '#a3a3a3', - 500: '#737373', - 600: '#525252', - 700: '#404040', - 800: '#262626', - 850: '#1b1b1b', - 900: '#171717', - }, - }, - accentColor, - fonts: { - heading: 'TGCFont, sans-serif', - body: 'TGCFont, sans-serif', - }, - config: { - initialColorMode: 'light', - useSystemColorMode: false, - }, - styles, -}); - -const serializedMdx = process.env.SERIALIZED_MDX_ROUTES; -const mdxRoutes = { data: serializedMdx && JSON.parse(serializedMdx) }; - -function AppContent(appProps: AppProps) { - const { Component, pageProps, router } = appProps; - const isDocs = router.asPath.startsWith('/docs'); +export default function App({ Component, pageProps, router }: AppProps): ReactElement { const analytics = useGoogleAnalytics({ router, trackingId: 'G-0SE4YQR4K3' }); + const { getLayout } = Component; + const childComponent = ; return ( - <> + ``` + - - - - + ```tsx const GET_POSTS = gql` query Posts { @@ -213,9 +193,7 @@ interface Post { } } -@Component({ - /* ... */ -}) +@Component({ /* … */ }) class PostsComponent implements OnInit, OnDestroy { posts: Post[] @@ -223,9 +201,7 @@ class PostsComponent implements OnInit, OnDestroy { ngOnInit() { this.querySubscription = this.apollo - .watchQuery({ - query: GET_POSTS - }) + .watchQuery({ query: GET_POSTS }) .valueChanges.subscribe(({ data }) => { this.posts = data.posts as Post[] }) @@ -235,11 +211,9 @@ class PostsComponent implements OnInit, OnDestroy { } } ``` + - - - - + ```svelte
    - +
``` - -
- - + + Manually maintaining the GraphQL operation types or the complete absence of types can lead to many issues: @@ -287,10 +259,8 @@ experience and stability of your stack. After [installing](/docs/getting-started/installation) and [configuring](/docs/config-reference/codegen-config) GraphQL Code Generator, our front-end code will be fully-typed and up-to-date as follows: - - - - + + ```tsx import { useQuery } from 'urql' import { postsQueryDocument } from './graphql/generated' @@ -299,14 +269,12 @@ const Posts = () => { const [result] = useQuery({ query: postsQueryDocument }) // `result` is fully typed! - // ... + // … } ``` + - - - - + ```tsx import { usePosts } from '../graphql/generated' @@ -314,18 +282,16 @@ const Posts = () => { const { data } = usePosts() // `data` is typed! - // ... + // … } ``` + - - - - + ```vue @@ -335,9 +301,7 @@ import { usePostQuery } from '../generated/graphql' export default { apollo: usePostQuery({ // `variables` is properly typed! - variables: { - id: 1 - } + variables: { id: 1 } }), data() { return { @@ -347,20 +311,16 @@ export default { } ``` + - - - - + ```tsx import { PostsGQL, PostsQuery } from './graphql' -//BE SURE TO USE Observable from `rxjs` and not from `@apollo/client/core` when using map +// BE SURE TO USE Observable from `rxjs` and not from `@apollo/client/core` when using map import { Observable } from 'rxjs' import { map } from 'rxjs/operators' -@Component({ - /* ... */ -}) +@Component({ /* … */ }) export class PostsComponent { posts: Observable @@ -369,11 +329,9 @@ export class PostsComponent { } } ``` + - - - - + ```svelte
    - +
``` - -
- -
+ + Now, with simple configuration and an npm/yarn script, a front-end developers benefits from: @@ -399,17 +355,11 @@ Now, with simple configuration and an npm/yarn script, a front-end developers be - **less boilerplate** (thanks to full code generation such as React hooks generation) -
- -> **How does GraphQL Code Generator work?** -> -> More details on the inner working of GraphQL Code Generator are available on [this page](/docs/advanced/how-does-it-work). - -

 

- ---- + +**How does GraphQL Code Generator work?** -

 

+More details on the inner working of GraphQL Code Generator are available on [this page](/docs/advanced/how-does-it-work). +
### To the back-end @@ -419,20 +369,15 @@ Most GraphQL API resolvers remain untyped or wrongly typed which, leads to multi - typos in the resolvers' function type signature -
- For this reason, GraphQL Code Generator provides multiple plugins that help you automate the generation of resolvers' typings. Here are an example of a GraphQL API leveraging GraphQL Code Generator resolvers typings (based on the `schema.graphql` above): - - - - + + ```ts +import { readFileSync } from 'node:fs' import { ApolloServer } from 'apollo-server' -import { readFileSync } from 'fs' - import { Resolvers } from './resolvers-types' const typeDefs = readFileSync('./schema.graphql', 'utf8') @@ -445,20 +390,17 @@ const resolvers: Resolvers = { const server = new ApolloServer({ typeDefs, resolvers }) -// The `listen` method launches a web server. +// The `listen` method launches a web server server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`) }) ``` + - - - - + ```ts +import { readFileSync } from 'node:fs' import { createServer } from '@graphql-yoga/node' -import { readFileSync } from 'fs' - import { Resolvers } from './resolvers-types' const typeDefs = readFileSync('./schema.graphql', 'utf8') @@ -469,18 +411,13 @@ const resolvers: Resolvers = { } } -const server = createServer({ - typeDefs, - resolvers -}) +const server = createServer({ typeDefs, resolvers }) server.start() ``` + - - - - + Given the following structure: ``` @@ -498,20 +435,15 @@ Given the following structure: The User module resolvers would be: -```tsx -// src/modules/user/resolvers.ts +```tsx filename="src/modules/user/resolvers.ts" import { UsersModule } from './generated-types/module-types' export const resolvers: UsersModule.Resolvers = { // Here, you can implement only the types and fields defined in your module! } ``` - - - - - -

 

+ + ## What's next? diff --git a/website/docs/getting-started/installation.mdx b/website/src/pages/docs/getting-started/installation.mdx similarity index 61% rename from website/docs/getting-started/installation.mdx rename to website/src/pages/docs/getting-started/installation.mdx index 27914f18c23..f4a76ea0cbb 100644 --- a/website/docs/getting-started/installation.mdx +++ b/website/src/pages/docs/getting-started/installation.mdx @@ -1,36 +1,31 @@ ---- -id: installation -title: Installation ---- +import Callout from 'nextra-theme-docs/callout' +import { PackageCmd } from '@/components' -## Installing Codegen +# Installation Make sure that you add both the `graphql` and `@graphql-codegen/cli` packages in your project's dependencies: - + - - Please avoid installing `graphql`, `@graphql-codegen/cli`, and its plugins as global dependencies. This will cause - issues because of duplications of the `graphql` package. Install it only locally in your project. - +## Global Installation - -If you are using Monorepo setup (Lerna/Yarn Workspaces/anything else), please note that GraphQL Codegen is using `require` to load plugins and files. This might break and fail in case of hoisting. + +Please avoid installing `graphql`, `@graphql-codegen/cli`, and its plugins as global dependencies. This will cause issues because of duplications of the `graphql` package. Install it only locally in your project. -If you are having issues with loading GraphQL-Codegen plugins, make sure it's installed correctly, at the same level of `node_modules`, and make sure it's accessible and available for the Codegen CLI. + - +## Monorepo Project -GraphQL Code Generator comes with dozen plugins, from front-end to back-end, from web apps to mobile apps. -If you are not sure which plugins might be helpful for your GraphQL stack, give a try at the [_Initialization Wizard_](#initialization-wizard). + +If you are using Monorepo setup (Lerna/Yarn Workspaces/anything else), please note that GraphQL Codegen is using `require` to load plugins and files. This might break and fail in case of hoisting. -Otherwise, you can start exploring the [plugins](/plugins) and [setting up them manually](#manual-setup). +If you are having issues with loading GraphQL-Codegen plugins, make sure it's installed correctly, at the same level of `node_modules`, and make sure it's accessible and available for the Codegen CLI. -

 

+
---- +GraphQL Code Generator comes with dozen plugins, from front-end to back-end, from web apps to mobile apps. If you are not sure which plugins might be helpful for your GraphQL stack, give a try at the [_Initialization Wizard_](#initialization-wizard). -

 

+Otherwise, you can start exploring the [plugins](/plugins) and [setting up them manually](#manual-setup). ## Setup @@ -38,23 +33,21 @@ Otherwise, you can start exploring the [plugins](/plugins) and [setting up them Once installed, GraphQL Code Generator CLI can help you configure your project based on some popular flows: - + Question by question, it will guide you through the whole process of setting up a schema, selecting and installing plugins, picking a destination to where your files are generated, and a lot more. -> **npx** -> -> The init process above can also be run through `npx`. - ### Manual Setup Once GraphQL Code Generator is installed and added to your project's development workflow (scripts), you can start installing plugins and configuring them. If you are looking for the **best way to leverage GraphQL Code Generator on your stack**, you should read one of our _Guides_. -On top of each plugin documentation, we provide one Guide for the most famous framework such as [React](/docs/guides/react) or [Apollo Server](/docs/guides/graphql-server-apollo-yoga). -Each guide exposes the best plugins and configurations available for each framework and stack (React with Apollo / URQL / React Query, Angular with Apollo, ...). - -
+On top of each plugin documentation, we provide one Guide for the most famous framework such as [React](/docs/guides/react) or [Apollo Server](/docs/guides/graphql-server-apollo-yoga). Each guide exposes the best plugins and configurations available for each framework and stack (React with Apollo / URQL / React Query, Angular with Apollo, …). Otherwise, if you **prefer exploring plugins and skipping the high-level explanations**, the go-to resource will be the [plugins documentation](/plugins) and the [`codegen.yaml` API reference documentation](/docs/config-reference/codegen-config). diff --git a/website/src/pages/docs/getting-started/meta.json b/website/src/pages/docs/getting-started/meta.json new file mode 100644 index 00000000000..38219be95e3 --- /dev/null +++ b/website/src/pages/docs/getting-started/meta.json @@ -0,0 +1,5 @@ +{ + "index": "Introduction", + "installation": "Installation", + "development-workflow": "Development workflow" +} diff --git a/website/docs/guides/angular.mdx b/website/src/pages/docs/guides/angular.mdx similarity index 77% rename from website/docs/guides/angular.mdx rename to website/src/pages/docs/guides/angular.mdx index 23775311248..5568ce29f84 100644 --- a/website/docs/guides/angular.mdx +++ b/website/src/pages/docs/guides/angular.mdx @@ -1,16 +1,13 @@ ---- -id: angular -title: 'Guide: Angular' -type: Guide ---- +import Callout from 'nextra-theme-docs/callout' +import { PackageCmd } from '@/components' + +# Guide: Angular GraphQL Code Generator provides the `@graphql-codegen/typescript-apollo-angular` plugin that generates full-typed Apollo GraphQL services. Taking the following schema: -```graphql -# schema.graphql - +```graphql filename="schema.graphql" type Author { id: Int! firstName: String! @@ -57,7 +54,7 @@ interface Post { } @Component({ - /* ... */ + /* … */ }) class PostsComponent implements OnInit, OnDestroy { posts: Post[] @@ -89,23 +86,17 @@ Not typing or manually maintaining the data-types can lead to many issues: For this reason, GraphQL Code Generator provides a `@graphql-codegen/typescript-apollo-angular` plugin that generates typed Apollo services for each GraphQL operation. -
- Just a few configuration steps are required to get those Apollo services: -**1. Install the `@graphql-codegen/typescript-apollo-angular` plugin** +### Install - -
- -**2. Configure the plugin** +### Configure the plugin Create or update your `codegen.yaml` file as follows: @@ -120,19 +111,20 @@ generates: - typescript-apollo-angular ``` -> **`schema` and `documents` values** -> -> `schema` needs to be your target GraphQL API URL (`"/graphql"` included). -> -> `documents` is a glob expression to your `.graphql` or `.ts` files. + +**`schema` and `documents` values** + +`schema` needs to be your target GraphQL API URL (`"/graphql"` included). -
+`documents` is a glob expression to your `.graphql` or `.ts` files. -**3. Run the codegen and update your code** +
+ +### Run the codegen and update your code Assuming that, as recommended, your `package.json` has the following script: -```json +```json filename="package.json" { "scripts": { "generate": "graphql-codegen" @@ -140,24 +132,20 @@ Assuming that, as recommended, your `package.json` has the following script: } ``` -
- Running the following generates the `graphql/generated.ts` file. - - -
+ We can now update our code as follows: ```ts import { PostsGQL, PostsQuery } from './graphql' -//BE SURE TO USE Observable from `rxjs` and not from `@apollo/client/core` when using map +// BE SURE TO USE Observable from `rxjs` and not from `@apollo/client/core` when using map import { Observable } from 'rxjs' import { map } from 'rxjs/operators' @Component({ - /* ... */ + /* … */ }) export class PostsComponent { posts: Observable @@ -168,10 +156,6 @@ export class PostsComponent { } ``` -

 

- For more advanced configuration, please refer to the [plugin documentation](/plugins/typescript-apollo-angular). For a different organization of the generated files, please refer to the ["Generated files colocation"](/docs/advanced/generated-files-colocation) page. - -

 

diff --git a/website/docs/guides/front-end-typescript-only.mdx b/website/src/pages/docs/guides/front-end-typescript-only.mdx similarity index 71% rename from website/docs/guides/front-end-typescript-only.mdx rename to website/src/pages/docs/guides/front-end-typescript-only.mdx index 2a27c5d1ce5..a14f0c75cb5 100644 --- a/website/docs/guides/front-end-typescript-only.mdx +++ b/website/src/pages/docs/guides/front-end-typescript-only.mdx @@ -1,8 +1,7 @@ ---- -id: front-end-typescript-only -title: 'Guide: TypeScript-only for front-end' -type: Guide ---- +import Callout from 'nextra-theme-docs/callout' +import { PackageCmd } from '@/components' + +# Guide: TypeScript-only for front-end Even while using another GraphQL Client (not listed in our guides) or willing only to use generated TypeScript types, GraphQL Code Generator still got you covered! @@ -36,13 +35,11 @@ Using `@graphql-codegen/typescript-operations` would generate the TypeScript typ Just a few configuration steps are required to get those TypeScript types generated: -**1. Install the `@graphql-codegen/typescript-operations` plugin** - - +### Install -
+ -**2. Configure the plugin** +### Configure the plugin Create or update your `codegen.yaml` file as follows: @@ -56,19 +53,20 @@ generates: - typescript-operations ``` -> **`schema` and `documents` values** -> -> `schema` needs to be your target GraphQL API URL (`"/graphql"` included). -> -> `documents` is a glob expression to your `.graphql`, `.ts` or `.tsx` files. + +**`schema` and `documents` values** + +`schema` needs to be your target GraphQL API URL (`"/graphql"` included). + +`documents` is a glob expression to your `.graphql`, `.ts` or `.tsx` files. -
+
-**3. Run the codegen and update your code** +### Run the codegen and update your code Assuming that, as recommended, your `package.json` has the following script: -```json +```json filename="package.json" { "scripts": { "generate": "graphql-codegen" @@ -76,13 +74,9 @@ Assuming that, as recommended, your `package.json` has the following script: } ``` -
- Running the following generates the `graphql/generated.tsx` file. - - -
+ We can now use the generated types as follows: @@ -111,6 +105,4 @@ const Posts = () => { } ``` -

 

- -For more information on the `@graphql-codegen/typescript-operations` plugin configuration , please refer to its [documentation](/plugins/typescript-operations). +For more information on the `@graphql-codegen/typescript-operations` plugin configuration, please refer to its [documentation](/plugins/typescript-operations). diff --git a/website/docs/guides/further-reading.mdx b/website/src/pages/docs/guides/further-reading.mdx similarity index 74% rename from website/docs/guides/further-reading.mdx rename to website/src/pages/docs/guides/further-reading.mdx index 54d503355dd..cf83831904a 100644 --- a/website/docs/guides/further-reading.mdx +++ b/website/src/pages/docs/guides/further-reading.mdx @@ -1,31 +1,25 @@ ---- -id: further-reading -title: Further Reading -type: Guide ---- +# Further Reading GraphQL Code Generator's community has written many articles over the years 🚀. The following articles are also excellent guides covering famous or lesser-known capabilities of GraphQL Code Generator. -
+## TypeScript -### TypeScript - -- [graphql.wtf](https://graphql.wtf/) by [Jamie Barton](https://twitter.com/notrab) is a set of video tutorials around GraphQL. -- [GraphQL Codegen For Effortless GraphQL and Typescript](https://www.youtube.com/watch?v=CtcjrPCwojQ) by [LevelUpTuts](https://leveluptutorials.com/) -- [GraphQL with TypeScript done right](https://the-guild.dev/blog/graphql-with-typescript-done-right) by [Charly Poly](https://charlypoly.com/) +- [graphql.wtf](https://graphql.wtf) by [Jamie Barton](https://twitter.com/notrab) is a set of video tutorials around GraphQL +- [GraphQL Codegen For Effortless GraphQL and Typescript](https://youtube.com/watch?v=CtcjrPCwojQ) by [LevelUpTuts](https://leveluptutorials.com) +- [GraphQL with TypeScript done right](https://the-guild.dev/blog/graphql-with-typescript-done-right) by [Charly Poly](https://charlypoly.com) - [Best Practices for integrating GraphQL Code Generator in your frontend applications](https://the-guild.dev/blog/graphql-codegen-best-practices) - [Better Type Safety for your GraphQL resolvers with GraphQL Codegen](https://the-guild.dev/blog/better-type-safety-for-resolvers-with-graphql-codegen) -- [Game Of Types: A Song Of GraphQL And TypeScript](https://formidable.com/blog/2019/strong-typing) - by Formidable. +- [Game Of Types: A Song Of GraphQL And TypeScript](https://formidable.com/blog/2019/strong-typing) - by Formidable -### Integrations +## Integrations - [Setup Hasura with GraphQL Code Generator](https://codedaily.io/tutorials/Setup-Hasura-with-GraphQL-Code-Generator) by [Jason Brown](https://twitter.com/browniefed) - [Working with GraphQL Code Generator and GraphCMS](https://graphcms.com/blog/working-with-graphql-code-generator-and-graphcms) by Jamie Barton -- [GraphQL-Modules integration with GraphQL Code Generator](https://www.graphql-modules.com/docs/legacy/recipes/graphql-code-generator/) +- [GraphQL-Modules integration with GraphQL Code Generator](https://graphql-modules.com/docs/legacy/recipes/graphql-code-generator) - [GraphQL Code Generator for WPGraphQL](https://developers.wpengine.com/blog/graphql-code-generator-for-wpgraphql) by Kellen Mace -- [GraphQL Queries in Apollo React](https://dgraph.io/learn/courses/messageboardapp/react/develop/react/graphql-queries/) by DGraph +- [GraphQL Queries in Apollo React](https://dgraph.io/learn/courses/messageboardapp/react/develop/react/graphql-queries) by DGraph - [Using Apollo GraphQL with Angular in an Nx Workspace](https://blog.nrwl.io/using-apollo-graphql-with-angular-in-an-nx-workspace-9ad0155c1914?gi=603641d4b51a) by [Philip Fulcher](https://medium.com/@philipjfulcher?source=post_page-----9ad0155c1914-----------------------------------) -- [Simplify GraphQL requests with React Query, GraphQL Code Generator, and TypeScript](https://blog.logrocket.com/making-graphql-requests-easy-with-react-typescript-and-react-query/) by [Iva Kop](https://blog.logrocket.com/author/ivakop/) +- [Simplify GraphQL requests with React Query, GraphQL Code Generator, and TypeScript](https://blog.logrocket.com/making-graphql-requests-easy-with-react-typescript-and-react-query) by [Iva Kop](https://blog.logrocket.com/author/ivakop) - [Gatsby and GraphQL Code Generator - A Perfect Match](https://talohana.com/blog/gatsby-graphql-code-generator) by [Tal Ohana](https://talohana.com) diff --git a/website/docs/guides/graphql-modules.mdx b/website/src/pages/docs/guides/graphql-modules.mdx similarity index 73% rename from website/docs/guides/graphql-modules.mdx rename to website/src/pages/docs/guides/graphql-modules.mdx index 0b79d5fa038..a479433e950 100644 --- a/website/docs/guides/graphql-modules.mdx +++ b/website/src/pages/docs/guides/graphql-modules.mdx @@ -1,8 +1,6 @@ ---- -id: graphql-modules -title: 'Guide: GraphQL Modules' -type: Guide ---- +import { PackageCmd } from '@/components' + +# Guide: GraphQL Modules GraphQL Code Generator's `@graphql-codegen/graphql-modules-preset` plugin helps to generate resolvers type for each module of a GraphQL Modules GraphQL API. @@ -24,19 +22,15 @@ Given the following GraphQL API structure using GraphQL Modules: Just a few configuration steps are required to get the resolvers types generated: -**1. Install the `@graphql-codegen/graphql-modules-preset` plugin** +### Install - -
- -**2. Configure the plugin** +### Configure the plugin Create or update your `codegen.yaml` file as follows: @@ -55,13 +49,11 @@ generates: - typescript-resolvers ``` -
- -**3. Run the codegen and update your code** +### Run the codegen and update your code Assuming that, as recommended, your `package.json` has the following script: -```json +```json filename="package.json" { "scripts": { "generate": "graphql-codegen" @@ -69,18 +61,13 @@ Assuming that, as recommended, your `package.json` has the following script: } ``` -
- Running the following generates the `graphql/generated.tsx` file. - - -
+ The User module resolvers would be: -```tsx -// src/modules/user/resolvers.ts +```tsx filename="src/modules/user/resolvers.ts" import { UsersModule } from './generated-types/module-types' export const resolvers: UsersModule.Resolvers = { @@ -88,12 +75,6 @@ export const resolvers: UsersModule.Resolvers = { } ``` -

 

- ---- - -

 

- -A complete article, written by Arda Tanrikulu from The Guild, is available on our blog: [Writing a GraphQL TypeScript project w/ GraphQL-Modules and GraphQL-Code-Generator](https://www.the-guild.dev/blog/graphql-typescript-modules-codegen). +A complete article, written by Arda Tanrikulu from The Guild, is available on our blog: [Writing a GraphQL TypeScript project w/ GraphQL-Modules and GraphQL-Code-Generator](https://the-guild.dev/blog/graphql-typescript-modules-codegen). For more advanced configuration (models or context typing), please refer to the [plugin documentation](/plugins/graphql-modules-preset). diff --git a/website/docs/guides/graphql-server-apollo-yoga.mdx b/website/src/pages/docs/guides/graphql-server-apollo-yoga.mdx similarity index 70% rename from website/docs/guides/graphql-server-apollo-yoga.mdx rename to website/src/pages/docs/guides/graphql-server-apollo-yoga.mdx index 9df8e172db7..5a32f6fd855 100644 --- a/website/docs/guides/graphql-server-apollo-yoga.mdx +++ b/website/src/pages/docs/guides/graphql-server-apollo-yoga.mdx @@ -1,38 +1,27 @@ ---- -id: graphql-server-apollo-yoga -title: 'Guide: GraphQL Yoga, Apollo Server' -type: Guide ---- +import Callout from 'nextra-theme-docs/callout' +import { Tabs, Tab } from 'nextra-theme-docs/tabs' +import { PackageCmd } from '@/components' -GraphQL Code Generator's `@graphql-codegen/typescript-resolvers` plugin generates TypeScript types for your GraphQL API's resolvers. - -

 

+# Guide: GraphQL Yoga, Apollo Server' ---- - -

 

+GraphQL Code Generator's `@graphql-codegen/typescript-resolvers` plugin generates TypeScript types for your GraphQL API's resolvers. ## Video tutorial [Episode #26 of `graphql.wtf`](https://graphql.wtf/episodes/26-type-safe-resolvers-with-graphql-code-generator) is a great introduction to `@graphql-codegen/typescript-resolvers`: +/> -> [More weekly episodes are available in `graphql.wtf`](https://graphql.wtf/) by [Jamie Barton](https://twitter.com/notrab). - -

 

- ---- - -

 

+ + [More weekly episodes are available in `graphql.wtf`](https://graphql.wtf) by [Jamie + Barton](https://twitter.com/notrab). + ## Guide @@ -44,19 +33,13 @@ Most GraphQL API resolvers remain untyped or wrongly typed, which leads to multi - typos in the resolvers' function type signature -
- For this reason, GraphQL Code Generator provides `@graphql-codegen/typescript-resolvers` that help automate the generation of resolvers' typings. -
- Just a few configuration steps are required to get the resolvers types generated: **1. Move your GraphQL Schema declaration in dedicated `.graphql` files** -```graphql -#schema.graphql - +```graphql filename="schema.graphql" type Author { id: Int! firstName: String! @@ -77,18 +60,14 @@ type Query { **2. Install the `@graphql-codegen/typescript-resolvers` plugin** - - -
+ **3. Configure the plugin** Create or update your `codegen.yaml` file as follows: - - - - + + ```yaml schema: schema.graphql generates: @@ -99,11 +78,9 @@ generates: - typescript - typescript-resolvers ``` + - - - - + ```yaml schema: schema.graphql generates: @@ -112,18 +89,14 @@ generates: - typescript - typescript-resolvers ``` - - - - - -
+ + **4. Run the codegen and update your code** Assuming that, as recommended, your `package.json` has the following script: -```json +```json filename="package.json" { "scripts": { "generate": "graphql-codegen" @@ -131,24 +104,17 @@ Assuming that, as recommended, your `package.json` has the following script: } ``` -
- Running the following generates the `graphql/generated.tsx` file. - - -
+ We can now write/migrate our GraphQL API implementation as follows: - - - - + + ```ts +import { readFileSync } from 'node:fs' import { ApolloServer } from 'apollo-server' -import { readFileSync } from 'fs' - import { Resolvers } from './resolvers-types' const typeDefs = readFileSync('./schema.graphql', 'utf8') @@ -166,15 +132,12 @@ server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`) }) ``` + - - - - + ```ts +import { readFileSync } from 'node:fs' import { createServer } from '@graphql-yoga/node' -import { readFileSync } from 'fs' - import { Resolvers } from './resolvers-types' const typeDefs = readFileSync('./schema.graphql', 'utf8') @@ -185,24 +148,13 @@ const resolvers: Resolvers = { } } -const server = createServer({ - typeDefs, - resolvers -}) +const server = createServer({ typeDefs, resolvers }) server.start() ``` + + - - - - -

 

- ---- - -

 

- -A complete tutorial, written by The Guild's CTO, Dotan Simha, is available on our blog: [Better Type Safety for your GraphQL resolvers with GraphQL Codegen](https://www.the-guild.dev/blog/better-type-safety-for-resolvers-with-graphql-codegen). +A complete tutorial, written by The Guild's CTO, Dotan Simha, is available on our blog: [Better Type Safety for your GraphQL resolvers with GraphQL Codegen](https://the-guild.dev/blog/better-type-safety-for-resolvers-with-graphql-codegen). For more advanced configuration (models or context typing), please refer to the [plugin documentation](/plugins/typescript-resolvers). diff --git a/website/src/pages/docs/guides/meta.json b/website/src/pages/docs/guides/meta.json new file mode 100644 index 00000000000..1cd4ed1c12e --- /dev/null +++ b/website/src/pages/docs/guides/meta.json @@ -0,0 +1,10 @@ +{ + "react": "React", + "vue": "Vue.js", + "angular": "Angular", + "svelte": "Svelte / Kit", + "front-end-typescript-only": "TypeScript only (front-end)", + "graphql-server-apollo-yoga": "Apollo Server / GraphQL Yoga", + "graphql-modules": "GraphQL Modules", + "further-reading": "Further Reading" +} diff --git a/website/docs/guides/react.mdx b/website/src/pages/docs/guides/react.mdx similarity index 78% rename from website/docs/guides/react.mdx rename to website/src/pages/docs/guides/react.mdx index b6ed370339b..eb12848ee18 100644 --- a/website/docs/guides/react.mdx +++ b/website/src/pages/docs/guides/react.mdx @@ -1,25 +1,19 @@ ---- -id: react -title: 'Guide: React and GraphQL' -type: Guide ---- +import { Tabs, Tab } from 'nextra-theme-docs/tabs' +import Callout from 'nextra-theme-docs/callout' +import { PackageCmd } from '@/components' + +# Guide: React and GraphQL GraphQL Code Generator provides typed code generation for React Query, URQL React, React Apollo Client, and other clients. The plugins and available options vary depending on the target client; for this reason, you find guides for each of them below: -
- - [React Query](#react-query) - [Apollo and URQL](#apollo-and-urql) -

 

- All the following guides query the schema below: -```graphql -# schema.graphql - +```graphql filename="schema.graphql" type Author { id: Int! firstName: String! @@ -38,12 +32,6 @@ type Query { } ``` -

 

- ---- - -

 

- ## React Query Most React Query usage with GraphQL and TypeScript will look as follows: @@ -84,7 +72,7 @@ const Posts = () => { return posts }) - // ... + // … } ``` @@ -98,22 +86,16 @@ Not typing or manually maintaining the data-types can lead to many issues: For this reason, GraphQL Code Generator provides a `@graphql-codegen/typescript-react-query` plugin that generates a typed hook for each GraphQL operation. -
- Just a few configuration steps are required to get those typed hooks generated: **1. Install the `@graphql-codegen/typescript-react-query` plugin** - -
- **2. Configure the plugin** Create or update your `codegen.yaml` file as follows: @@ -131,19 +113,20 @@ generates: fetcher: fetch ``` -> **`schema` and `documents` values** -> -> `schema` needs to be your target GraphQL API URL (`"/graphql"` included). -> -> `documents` is a glob expression to your `.graphql`, `.ts` or `.tsx` files. + +**`schema` and `documents` values** -
+`schema` needs to be your target GraphQL API URL (`"/graphql"` included). + +`documents` is a glob expression to your `.graphql`, `.ts` or `.tsx` files. + +
**3. Run the codegen and update your code** Assuming that, as recommended, your `package.json` has the following script: -```json +```json filename="package.json" { "scripts": { "generate": "graphql-codegen" @@ -151,13 +134,9 @@ Assuming that, as recommended, your `package.json` has the following script: } ``` -
- Running the following will generate the `graphql/generated.tsx` file. - - -
+ We can now update our code as follows: @@ -184,23 +163,14 @@ const Posts = () => { const { data } = usePosts() // `data` is typed! - - // ... + // … } ``` -

 

- For more advanced configuration (custom fetcher, infinite queries), please refer to the [plugin documentation](/plugins/typescript-react-query#using-graphql-request). For a different organization of the generated files, please refer to the ["Generated files colocation"](/docs/advanced/generated-files-colocation) page. -

 

- ---- - -

 

- ## Apollo and URQL ### Optimal configuration for Apollo and URQL @@ -215,10 +185,8 @@ While Apollo and URQL have their GraphQL Code Generator plugins that generate fu Given the following code example: - - - - + + ```tsx import { gql, useQuery } from '@apollo/client' @@ -251,14 +219,12 @@ const postsQueryDocument = gql` const Posts = () => { const { data } = useQuery(postsQueryDocument) - // ... + // … } ``` + - - - - + ```tsx import { useQuery } from 'urql' @@ -291,20 +257,16 @@ const postsQueryDocument = ` const Posts = () => { const [result] = useQuery({ query: postsQueryDocument }) - // ... + // … } ``` - - - - + + installing and configuring the `@graphql-codegen/typed-document-node` plugin would allow the following refactoring: - - - - + + ```tsx import { useQuery } from '@apollo/client' import { postsQueryDocument } from './graphql/generated' @@ -313,14 +275,12 @@ const Posts = () => { const { data } = useQuery(postsQueryDocument) // `result` is fully typed! - // ... + // … } ``` + - - - - + ```tsx import { useQuery } from 'urql' import { postsQueryDocument } from './graphql/generated' @@ -329,13 +289,11 @@ const Posts = () => { const [result] = useQuery({ query: postsQueryDocument }) // `result` is fully typed! - // ... + // … } ``` - - - - + + Just a few configuration steps are required to get those typed document nodes generated: @@ -345,9 +303,7 @@ To have `@graphql-codegen/typed-document-node` working and avoid code duplicatio we highly recommend moving all `gql` document declarations outside of `.tsx`/`.ts` files. For this, create a colocated `.graphql` file for each GraphQL document, as follows: -```graphql -# postsQuery.graphql - +```graphql filename="postsQuery.graphql" # 'Document' will be appended to the name of the query in the generated output query postsQuery { posts { @@ -364,16 +320,10 @@ query postsQuery { **2. Install the `@graphql-codegen/typed-document-node` plugin** - -
- **3. Configure the plugin** Create or update your `codegen.yaml` file as follows: @@ -389,18 +339,19 @@ generates: - typed-document-node ``` -> **`schema` and `documents` values** -> -> `schema` needs to be your target GraphQL API URL (`"/graphql"` included). -> `documents` is a glob expression to your `.graphql` files. + +**`schema` and `documents` values** -
+`schema` needs to be your target GraphQL API URL (`"/graphql"` included). + +`documents` is a glob expression to your `.graphql` files. +
**4. Run the codegen and update your code** Assuming that, as recommended, your `package.json` has the following script: -```json +```json filename="package.json" { "scripts": { "generate": "graphql-codegen" @@ -408,20 +359,14 @@ Assuming that, as recommended, your `package.json` has the following script: } ``` -
- Running the following generates the `graphql/generated.tsx` file. - - -
+ We can now update our code as follows: - - - - + + ```tsx import { useQuery } from '@apollo/client' import { postsQueryDocument } from './graphql/generated' @@ -430,14 +375,12 @@ const Posts = () => { const { data } = useQuery(postsQueryDocument) // `result` is fully typed! - // ... + // … } ``` + - - - - + ```tsx import { useQuery } from 'urql' import { postsQueryDocument } from './graphql/generated' @@ -446,23 +389,15 @@ const Posts = () => { const [result] = useQuery({ query: postsQueryDocument }) // `result` is fully typed! - // ... + // … } ``` - - - - - -

 

+ + For more advanced configuration, please refer to the [plugin documentation](/plugins/typed-document-node). -If you are curious about `@graphql-codegen/typed-document-node` inner workings, feel free to read the following The Guild's CTO blog post: [TypedDocumentNode: the next generation of GraphQL and TypeScript](https://www.the-guild.dev/blog/typed-document-node). - -

 

- -

 

+If you are curious about `@graphql-codegen/typed-document-node` inner workings, feel free to read the following The Guild's CTO blog post: [TypedDocumentNode: the next generation of GraphQL and TypeScript](https://the-guild.dev/blog/typed-document-node). ### Typed hooks for Apollo and URQL @@ -470,10 +405,8 @@ GraphQL Code Generator also proposes two plugins (one for Apollo one for URQL) t Given the following code example: - - - - + + ```tsx import { gql, useQuery } from '@apollo/client' @@ -506,14 +439,12 @@ const postsQueryDocument = gql` const Posts = () => { const { data } = useQuery(postsQueryDocument) - // ... + // … } ``` + - - - - + ```tsx import { useQuery } from 'urql' @@ -529,16 +460,16 @@ interface PostQuery { }[] } -const postsQueryDocument = ` +const postsQueryDocument = /* GraphQL */` query Posts { posts { + id + title + author { id - title - author { - id - firstName - lastName - } + firstName + lastName + } } } ` @@ -546,20 +477,16 @@ const postsQueryDocument = ` const Posts = () => { const [result] = useQuery({ query: postsQueryDocument }) - // ... + // … } ``` - - - - + + installing and configuring the `@graphql-codegen/typescript-react-apollo` or `@graphql-codegen/typescript-urql` plugin would allow the following refactoring: - - - - + + ```tsx import { usePostsQuery } from './graphql/generated' @@ -567,14 +494,12 @@ const Posts = () => { const { data } = usePostsQuery() // `result` is fully typed! - // ... + // … } ``` + - - - - + ```tsx import { usePostsQuery } from './graphql/generated' @@ -582,13 +507,11 @@ const Posts = () => { const [result] = usePostsQuery() // `result` is fully typed! - // ... + // … } ``` - - - - + + Some might prefer this approach to `@graphql-codegen/typed-document-node` since its results in a total abstraction of the query logic and fewer imports. @@ -603,34 +526,22 @@ Just a few configuration steps are required to get those typed hooks generated: For React Apollo: - For URQL React: - -
- **2. Configure the plugin** Create or update your `codegen.yaml` file as follows: - - - - + + ```yaml schema: http://my-graphql-api.com/graphql documents: './src/**/*.tsx' @@ -643,11 +554,9 @@ generates: config: withHooks: true ``` + - - - - + ```yaml schema: http://my-graphql-api.com/graphql documents: './src/**/*.tsx' @@ -660,24 +569,23 @@ generates: config: withHooks: true ``` + + - + +**`schema` and `documents` values** - +`schema` needs to be your target GraphQL API URL (`"/graphql"` included). -> **`schema` and `documents` values** -> -> `schema` needs to be your target GraphQL API URL (`"/graphql"` included). -> -> `documents` is a glob expression to your `.graphql`, `.ts` or `.tsx` files. +`documents` is a glob expression to your `.graphql`, `.ts` or `.tsx` files. -
+ **3. Run the codegen and update your code** Assuming that, as recommended, your `package.json` has the following script: -```json +```json filename="package.json" { "scripts": { "generate": "graphql-codegen" @@ -685,20 +593,14 @@ Assuming that, as recommended, your `package.json` has the following script: } ``` -
- Running the following generates the `graphql/generated.tsx` file. - - -
+ We can now update our code as follows: - - - - + + ```tsx import { usePostsQuery } from './graphql/generated' @@ -706,14 +608,12 @@ const Posts = () => { const { data } = usePostsQuery() // `result` is fully typed! - // ... + // … } ``` + - - - - + ```tsx import { usePostsQuery } from './graphql/generated' @@ -721,21 +621,15 @@ const Posts = () => { const [result] = usePostsQuery() // `result` is fully typed! - // ... + // … } ``` - - - - - -

 

+ + For more advanced configuration, please refer to the plugin documentation: - [`@graphql-codegen/typescript-react-apollo` documentation](/plugins/typescript-react-apollo) - [`@graphql-codegen/typescript-urql` documentation](/plugins/typescript-urql) -
- For a different organization of the generated files, please refer to the ["Generated files colocation"](/docs/advanced/generated-files-colocation) page. diff --git a/website/docs/guides/svelte.mdx b/website/src/pages/docs/guides/svelte.mdx similarity index 83% rename from website/docs/guides/svelte.mdx rename to website/src/pages/docs/guides/svelte.mdx index d97cc07fac4..bc2e04d031f 100644 --- a/website/docs/guides/svelte.mdx +++ b/website/src/pages/docs/guides/svelte.mdx @@ -1,25 +1,18 @@ ---- -id: svelte -title: 'Guide: Svelte / Kit' -type: Guide ---- +import Callout from 'nextra-theme-docs/callout' +import { PackageCmd } from '@/components' + +# Guide: Svelte / Kit GraphQL Code Generator and the community provide typed code generation for Apollo, SvelteKit _native_, and other clients. Plugins and available options vary depending on the selected codegen; for this reason, you will find guides for each of them below: -
- - [Svelte Apollo](#svelte-apollo) - [SvelteKit Native](#sveltekit-native) -

 

- All the following guides query the schema below: -```graphql -# schema.graphql - +```graphql filename="schema.graphql" type Author { id: Int! firstName: String! @@ -38,12 +31,6 @@ type Query { } ``` -

 

- ---- - -

 

- ## Svelte Apollo Thank to the [community-built plugin](https://github.com/ticruz38/graphql-codegen-svelte-apollo#readme) `graphql-codegen-svelte-apollo`, GraphQL Code Generator generates full-typed Apollo GraphQL services for Svelte. @@ -71,7 +58,7 @@ and the following reference script: const posts = query(postsQueryDocument) - + {posts.data} ``` @@ -79,12 +66,10 @@ Just a few configuration steps are required to get observable Apollo queries wit **1. Install the `graphql-codegen-svelte-apollo` plugin** - -
- **2. Configure the plugin** Create or update your `codegen.yaml` file as follows: @@ -100,22 +85,23 @@ generates: - graphql-codegen-svelte-apollo ``` -> **`schema` and `documents` values** -> -> `schema` can be: -> -> - your target GraphQL API URL (`"/graphql"` included) -> - your SDL file. (eg: `./src/schema.graphql`) -> -> `documents` is a glob expression to your `.graphql`, `.gql` files. + +**`schema` and `documents` values** + +`schema` can be: -
+- your target GraphQL API URL (`"/graphql"` included) +- your SDL file. (eg: `./src/schema.graphql`) + +`documents` is a glob expression to your `.graphql`, `.gql` files. + +
**3. Run the codegen and update your code** Assuming that, as recommended, your `package.json` has the following script: -```json +```json filename="package.json" { "scripts": { "generate": "graphql-codegen" @@ -123,13 +109,9 @@ Assuming that, as recommended, your `package.json` has the following script: } ``` -
- Running the following generates the `graphql/generated.ts` file. - - -
+ We can now update our code as follows: @@ -141,22 +123,14 @@ We can now update our code as follows: // `posts` is fully typed! - + {$posts.data} ``` -

 

- For more advanced configuration (ex: async queries), please refer to the [plugin documentation](/plugins/typescript-svelte-apollo) and the [GitHub repository README](https://github.com/ticruz38/graphql-codegen-svelte-apollo). For a different organization of the generated files, please refer to the ["Generated files colocation"](/docs/advanced/generated-files-colocation) page. -

 

- ---- - -

 

- ## SvelteKit Native ![logoKitQL](https://raw.githubusercontent.com/jycouet/kitql/main/logo.svg) @@ -167,9 +141,7 @@ Just a few configuration steps are required to get SvelteKit stores fully typed **1. Install the plugin** - - -
+ **2. Configure the plugin** @@ -187,13 +159,11 @@ generates: - '@kitql/graphql-codegen' ``` -
- **3. Run the codegen and update your code** Assuming that, as recommended, your `package.json` has the following script: -```json +```json filename="package.json" { "scripts": { "generate": "graphql-codegen" @@ -201,13 +171,9 @@ Assuming that, as recommended, your `package.json` has the following script: } ``` -
- Running the following generates the `graphql/generated.ts` file. - - -
+ We can now update our code as follows: @@ -222,14 +188,10 @@ We can now update our code as follows: } - + {$PostsQueryStore.data} ``` -

 

- For more advanced configuration, please refer to the [KitQL documentation](https://github.com/jycouet/kitql/tree/main/packages/graphql-codegen). For a different organization of the generated files, please refer to the ["Generated files colocation"](/docs/advanced/generated-files-colocation) page. - -

 

diff --git a/website/docs/guides/vue.mdx b/website/src/pages/docs/guides/vue.mdx similarity index 82% rename from website/docs/guides/vue.mdx rename to website/src/pages/docs/guides/vue.mdx index 8553aa62a2a..299e59c1c48 100644 --- a/website/docs/guides/vue.mdx +++ b/website/src/pages/docs/guides/vue.mdx @@ -1,25 +1,18 @@ ---- -id: vue -title: 'Guide: Vue.js' -type: Guide ---- +import Callout from 'nextra-theme-docs/callout' +import { PackageCmd } from '@/components' + +# Guide: Vue.js GraphQL Code Generator provides typed code generation for URQL Vue.js and Apollo Vue.js. The plugins and available options vary depending on the target client; for this reason, you will find guides for each of them below: -
- - [URQL Vue.js](#vuejs-urql) - [Apollo Vue.js](#vuejs-apollo) -

 

- All the following guides query the schema below: -```graphql -# schema.graphql - +```graphql filename="schema.graphql" type Author { id: Int! firstName: String! @@ -38,12 +31,6 @@ type Query { } ``` -

 

- ---- - -

 

- ## Vue.js URQL Most Vue.js URQL usage with TypeScript will look as follows: @@ -51,7 +38,7 @@ Most Vue.js URQL usage with TypeScript will look as follows: ```vue @@ -107,16 +94,12 @@ For this reason, GraphQL Code Generator is providing a `@graphql-codegen/typescr **1. Install the `@graphql-codegen/typescript-vue-urql` plugin** - -
- **2. Configure the plugin** Create or update your `codegen.yaml` file as follows: @@ -132,19 +115,20 @@ generates: - typescript-vue-urql ``` -> **`schema` and `documents` values** -> -> `schema` needs to be your target GraphQL API URL (`"/graphql"` included). -> -> `documents` is a glob expression to your `.graphql`, `.ts` or `.tsx` files. + +**`schema` and `documents` values** + +`schema` needs to be your target GraphQL API URL (`"/graphql"` included). -
+`documents` is a glob expression to your `.graphql`, `.ts` or `.tsx` files. + +
**3. Run the codegen and update your code** Assuming that, as recommended, your `package.json` has the following script: -```json +```json filename="package.json" { "scripts": { "generate": "graphql-codegen" @@ -152,20 +136,16 @@ Assuming that, as recommended, your `package.json` has the following script: } ``` -
- Running the following generates the `graphql/generated.tsx` file. - - -
+ We can now update our code as follows: ```vue @@ -188,18 +168,10 @@ export default { ``` -

 

- For more advanced configuration, please refer to the [plugin documentation](/plugins/typescript-vue-urql). For a different organization of the generated files, please refer to the ["Generated files colocation"](/docs/advanced/generated-files-colocation) page. -

 

- ---- - -

 

- ## Vue.js Apollo Most Vue.js Apollo usage with TypeScript will look as follows: @@ -207,7 +179,7 @@ Most Vue.js Apollo usage with TypeScript will look as follows: ```vue @@ -262,16 +234,12 @@ For this reason, GraphQL Code Generator is providing a `@graphql-codegen/typescr **1. Install the `@graphql-codegen/typescript-vue-apollo-smart-ops` plugin** - -
- **2. Configure the plugin** Create or update your `codegen.yaml` file as follows: @@ -287,19 +255,20 @@ generates: - typescript-vue-apollo-smart-ops ``` -> **`schema` and `documents` values** -> -> `schema` needs to be your target GraphQL API URL (`"/graphql"` included). -> -> `documents` is a glob expression to your `.graphql`, `.ts` or `.tsx` files. + +**`schema` and `documents` values** -
+`schema` needs to be your target GraphQL API URL (`"/graphql"` included). + +`documents` is a glob expression to your `.graphql`, `.ts` or `.tsx` files. + +
**3. Run the codegen and update your code** Assuming that, as recommended, your `package.json` has the following script: -```json +```json filename="package.json" { "scripts": { "generate": "graphql-codegen" @@ -307,20 +276,16 @@ Assuming that, as recommended, your `package.json` has the following script: } ``` -
- Running the following generates the `graphql/generated.tsx` file. - - -
+ We can now update our code as follows: ```vue @@ -343,8 +308,6 @@ export default { ``` -

 

- For more advanced configuration, please refer to the [plugin documentation](/plugins/typescript-vue-apollo-smart-ops). For a different organization of the generated files, please refer to the ["Generated files colocation"](/docs/advanced/generated-files-colocation) page. diff --git a/website/docs/integrations/apollo-local-state.mdx b/website/src/pages/docs/integrations/apollo-local-state.mdx similarity index 95% rename from website/docs/integrations/apollo-local-state.mdx rename to website/src/pages/docs/integrations/apollo-local-state.mdx index 37e5b846c48..4404e2fba60 100644 --- a/website/docs/integrations/apollo-local-state.mdx +++ b/website/src/pages/docs/integrations/apollo-local-state.mdx @@ -1,7 +1,4 @@ ---- -id: apollo-local-state -title: Apollo Local State ---- +# Apollo Local State Suppose you are using [apollo-client](https://apollographql.com/docs/react/v2/data/local-state) >2.5 (or older, with [apollo-link-state](https://apollographql.com/docs/link/links/state.html)) to manage your app state with GraphQL. In that case, you're probably using a client-side only GraphQL schema and client-side directives such as `@client`. @@ -23,7 +20,7 @@ query myQuery { If you wish to get better integration and fully type-safe types for your client-side schema as well, you can create a `.graphql` file for your local schema, for example: -```gql +```graphql type Todo { selected: Boolean! } diff --git a/website/docs/integrations/create-react-app.mdx b/website/src/pages/docs/integrations/create-react-app.mdx similarity index 87% rename from website/docs/integrations/create-react-app.mdx rename to website/src/pages/docs/integrations/create-react-app.mdx index a600cc068f1..737af671d49 100644 --- a/website/docs/integrations/create-react-app.mdx +++ b/website/src/pages/docs/integrations/create-react-app.mdx @@ -1,7 +1,4 @@ ---- -id: create-react-app -title: Create-React-App ---- +# Create-React-App Since v2 of [Create-React-App](https://github.com/facebook/create-react-app), you can use TypeScript without the need to eject from the basic scripts packages. diff --git a/website/docs/integrations/federation.mdx b/website/src/pages/docs/integrations/federation.mdx similarity index 78% rename from website/docs/integrations/federation.mdx rename to website/src/pages/docs/integrations/federation.mdx index 7ae222bc463..75e40d18ada 100644 --- a/website/docs/integrations/federation.mdx +++ b/website/src/pages/docs/integrations/federation.mdx @@ -1,13 +1,10 @@ ---- -id: federation -title: Apollo Federation ---- +# Apollo Federation The `typescript-resolvers` plugin also supports [Apollo Federation](https://apollographql.com/docs/apollo-server/federation/introduction). -To use it, add `federation: true` to your configuration: +To use it, add `federation: true{:yaml}` to your configuration: -```yaml +```yaml {6-7} generates: ./src/types.ts: plugins: diff --git a/website/src/pages/docs/integrations/gatsby.mdx b/website/src/pages/docs/integrations/gatsby.mdx new file mode 100644 index 00000000000..1705eccd912 --- /dev/null +++ b/website/src/pages/docs/integrations/gatsby.mdx @@ -0,0 +1,11 @@ +# Gatsby + +If you build apps using [Gatsby](https://gatsbyjs.com), you can use its built-in feature called [GraphQL Typegen](https://gatsbyjs.com/docs/how-to/local-development/graphql-typegen). Under the hood it uses the GraphQL Code Generator to generate TypeScript types, but you don't need to set anything up other than enabling an option. + +It also sets up everything needed for [GraphQL Config](https://graphql-config.com). + +## Community Plugins + +Gatsby's GraphQL Typegen feature is solving most common use cases. If you find yourself limited by its features you should open a feature request or trying using one of these community plugins: + +- [gatsby-plugin-typegen](https://github.com/cometkim/gatsby-plugin-typegen) diff --git a/website/src/pages/docs/integrations/meta.json b/website/src/pages/docs/integrations/meta.json new file mode 100644 index 00000000000..e7fbbbe8aa5 --- /dev/null +++ b/website/src/pages/docs/integrations/meta.json @@ -0,0 +1,8 @@ +{ + "vscode": "VSCode Extension", + "prettier": "Prettier & Linters", + "federation": "Apollo Federation", + "apollo-local-state": "apollo-local-state", + "create-react-app": "create-react-app", + "gatsby": "Gatsby" +} diff --git a/website/docs/integrations/prettier.mdx b/website/src/pages/docs/integrations/prettier.mdx similarity index 96% rename from website/docs/integrations/prettier.mdx rename to website/src/pages/docs/integrations/prettier.mdx index 19c0d3d7cb1..bd9d5a623e4 100644 --- a/website/docs/integrations/prettier.mdx +++ b/website/src/pages/docs/integrations/prettier.mdx @@ -1,7 +1,4 @@ ---- -id: prettier -title: Prettier & Linters ---- +# Prettier & Linters The codegen supports lifecycle hooks, and you can use those for integration with Prettier or other linters, to apply your custom code style and formatting rules. diff --git a/website/docs/integrations/vscode.mdx b/website/src/pages/docs/integrations/vscode.mdx similarity index 92% rename from website/docs/integrations/vscode.mdx rename to website/src/pages/docs/integrations/vscode.mdx index 41a60a458dd..47de00c06fc 100644 --- a/website/docs/integrations/vscode.mdx +++ b/website/src/pages/docs/integrations/vscode.mdx @@ -1,7 +1,4 @@ ---- -id: vscode -title: VSCode ---- +# VSCode In VSCode, you can install a lightweight extension to get your codegen on every save effortlessly. diff --git a/website/src/pages/docs/meta.json b/website/src/pages/docs/meta.json new file mode 100644 index 00000000000..35c1ed7de7c --- /dev/null +++ b/website/src/pages/docs/meta.json @@ -0,0 +1,9 @@ +{ + "getting-started": "Getting Started", + "guides": "Guides", + "config-reference": "Config Reference", + "advanced": "Advanced Usage", + "integrations": "Integrations", + "custom-codegen": "Writing Plugins", + "migration": "Migration Guides" +} diff --git a/website/docs/migration/from-0-13.mdx b/website/src/pages/docs/migration/from-0-13.mdx similarity index 57% rename from website/docs/migration/from-0-13.mdx rename to website/src/pages/docs/migration/from-0-13.mdx index 2e2dea9b07f..8725874e305 100644 --- a/website/docs/migration/from-0-13.mdx +++ b/website/src/pages/docs/migration/from-0-13.mdx @@ -1,33 +1,30 @@ ---- -id: from-0-13 -title: Migration from 0.13 to 0.18 ---- +import Callout from 'nextra-theme-docs/callout' -_March 1st, 2019_ +# Migration from 0.13 to 0.18 ## What has changed? In >= 0.14 we changed the way you pass configuration to GraphQL Code Generator. -In the previous versions of the code-generator, the configuration was confusing and passed through 3 ways: CLI flags, config file (`gql-gen.json` and environment variables. +In the previous versions of the code-generator, the configuration was confusing and passed through 3 ways: CLI flags, config file `gql-gen.json` and environment variables. -It became very confusing and difficult to use, so we decided to merge all existing configurations into a single .yml file - `codegen.yml`. +It became very confusing and difficult to use, so we decided to merge all existing configurations into a single `.yml` file – `codegen.yml`. ## How to migrate? To migrate from GraphQL Code Generator v0.13 API to >=0.14, just start by installing the latest version of `graphql-code-generator` from NPM. -Then, run your existing `gql-gen ...` command as is. You'll see a warning about your current usage. +Then, run your existing `gql-gen …` command as is. You'll see a warning about your current usage. -The new CLI makes it much easier - it will show you how your `codegen.yml` file should look according to your usage with the old API: +The new CLI makes it much easier – it will show you how your `codegen.yml` file should look according to your usage with the old API: -![CLI Migration](/img/v13-migration-cli.gif) +![CLI Migration](/assets/img/v13-migration-cli.gif) Now, create a file called `codegen.yml` with the content that the codegen suggests for you. Next, update your NPM scripts to run `graphql-codegen` only, without any cli-flags: -```json +```json filename="package.json" { "name": "my-project", "scripts": { @@ -40,4 +37,8 @@ Now, replace your deprecated `templates` packages with the new `plugins` package For example, if you were using `graphql-codegen-typescript-template`, you should replace it with: `graphql-codegen-typescript`, and `graphql-codegen-typescript-operations`. -Note sure which new packages you need to use now? [You can take a look here](https://github.com/dotansimha/graphql-code-generator/tree/master/packages/old-templates). Under each directory you'll find a `package.json` pointing to the new packages names. + + Note sure which new packages you need to use now? [You can take a look + here](https://github.com/dotansimha/graphql-code-generator/tree/master/packages/old-templates). Under each directory + you'll find a `package.json` pointing to the new packages names. + diff --git a/website/docs/migration/from-0-18.mdx b/website/src/pages/docs/migration/from-0-18.mdx similarity index 73% rename from website/docs/migration/from-0-18.mdx rename to website/src/pages/docs/migration/from-0-18.mdx index 2e50ca05870..62b1b8f480e 100644 --- a/website/docs/migration/from-0-18.mdx +++ b/website/src/pages/docs/migration/from-0-18.mdx @@ -1,25 +1,24 @@ ---- -id: from-0-18 -title: Migration to 1.0.0 ---- +import Callout from 'nextra-theme-docs/callout' +import { Tabs, Tab } from 'nextra-theme-docs/tabs' +import { PackageCmd } from '@/components' -_March 20th, 2019_ +# Migration to 1.0.0 ## What has changed? Our goals (and achievements) for 1.0.0 release was: -- Rename all package from `graphql-codegen-...` to scoped packages `@graphql-codegen/...`. -- Stabilize the core package and the YML configuration file. -- Remove the old, deprecated code from this repository (everything related to `flattenDocuments` and `buildSchemaContext`). -- Separate the CLI package from the core package, and create an easy-to-use and easy-to-consume core package. -- Add better support for running the codegen in non-node environments, by clearing unused dependencies and add support for tree shaking. -- Remove the dependency for Handlebars from this repository. -- Introduce a new, easy-to-use common base for plugins, based on `Visitor` pattern, that uses `visit` from `graphql` package. -- Better unit tests for all plugins packages, by use TypeScript compiler to compile each test result- makes it much easier to detect mismatches and invalid output. -- Refactor the entire TypeScript plugin, and create better and optimized output. -- Fix most of the GitHub issues. -- Update website and documentation for all plugins. +- Rename all package from `graphql-codegen-…` to scoped packages `@graphql-codegen/…` +- Stabilize the core package and the YML configuration file +- Remove the old, deprecated code from this repository (everything related to `flattenDocuments` and `buildSchemaContext`) +- Separate the CLI package from the core package, and create an easy-to-use and easy-to-consume core package +- Add better support for running the codegen in non-node environments, by clearing unused dependencies and add support for tree shaking +- Remove the dependency for Handlebars from this repository +- Introduce a new, easy-to-use common base for plugins, based on `Visitor` pattern, that uses `visit` from `graphql` package +- Better unit tests for all plugins packages, by use TypeScript compiler to compile each test result- makes it much easier to detect mismatches and invalid output +- Refactor the entire TypeScript plugin, and create better and optimized output +- Fix most of the GitHub issues +- Update website and documentation for all plugins ### New TypeScript Libraries @@ -35,13 +34,13 @@ The reason for this change is the fact that now `typescript-operations` uses `Pi First, the new packages have a different name, that means that you need to manually update those packages names, and not just it's version. -The `graphql-code-generator` package is now `@graphql-codegen/cli` and all other packages has been changes from `graphql-codegen-...` to `@graphql-codegen/...`. +The `graphql-code-generator` package is now `@graphql-codegen/cli` and all other packages has been changes from `graphql-codegen-…` to `@graphql-codegen/…`. So start by updating your `package.json`: -**Before:** - -```json + + +```json filename="package.json" { "devDependencies": { "graphql-code-generator": "0.18.0", @@ -51,10 +50,10 @@ So start by updating your `package.json`: } } ``` + -**After:** - -```json + +```json filename="package.json" { "devDependencies": { "@graphql-codegen/cli": "^1.0.0", @@ -63,11 +62,13 @@ So start by updating your `package.json`: } } ``` + + Also, make sure to update your YML config file: -**Before**: - + + ```yaml ./my-file.ts: schema: schema.json @@ -75,20 +76,22 @@ Also, make sure to update your YML config file: - typescript-common - typescript-server ``` + -**After:** - + ```yaml ./my-file.ts: schema: schema.json plugins: - typescript ``` + + And for client-side: -**Before**: - + + ```yaml ./my-file.ts: schema: schema.json @@ -96,9 +99,9 @@ And for client-side: - typescript-common - typescript-client ``` + -**After:** - + ```yaml ./my-file.ts: schema: schema.json @@ -106,6 +109,8 @@ And for client-side: - typescript - typescript-operations ``` + + ## Breaking Changes & Semver @@ -113,16 +118,14 @@ We tried to avoid breaking changes, but it's not always possible. We had a lot o It was very hard for us to track breaking changes in the past, but it it's easier for us, and we promise to be semver-compatible. -You can find a list of all breaking changes in [GitHub Releases page](https://github.com/dotansimha/graphql-code-generator/releases/). +You can find a list of all breaking changes in [GitHub Releases page](https://github.com/dotansimha/graphql-code-generator/releases). We also created a new plugin, called `typescript-compatibility` that generates backward compatibility for the `typescript-operations` and `typescript-react-apollo` plugins. It will generates for you types that are pointing to the new form of types. It supports _most_ of the use-cases. To use it, start by installing from NPM: -```sh -yarn add -D @graphql-codegen/typescript-compatibility -``` + Then, add it to your codegen configuration: @@ -135,4 +138,7 @@ Then, add it to your codegen configuration: - typescript-compatibility ``` -> Note: If `typescript-react-apollo` plugin also specified in your config file, it will generate backward-compatibility for it. + + If `typescript-react-apollo` plugin also specified in your config file, it will generate backward-compatibility for + it. + diff --git a/website/src/pages/docs/migration/meta.json b/website/src/pages/docs/migration/meta.json new file mode 100644 index 00000000000..c2dcc27deca --- /dev/null +++ b/website/src/pages/docs/migration/meta.json @@ -0,0 +1,4 @@ +{ + "from-0-18": "v0.18 -> v1.0", + "from-0-13": "v0.13 -> v0.17" +} diff --git a/website/src/pages/index.mdx b/website/src/pages/index.mdx new file mode 100644 index 00000000000..4c115bb1dab --- /dev/null +++ b/website/src/pages/index.mdx @@ -0,0 +1,46 @@ +--- +title: Home +--- + +import { HeroGradient, HeroIllustration } from '@theguild/components' +import { NPMBadge } from '@guild-docs/client' +import dynamic from 'next/dynamic' + +export const LiveDemo = dynamic(() => import('@/components/live-demo/LiveDemo')) + +} + colors={['#1dbbff', '#ee1cd9']} + image={{ + src: '/assets/illustrations/gql-codegen-cover.svg', + alt: 'Illustration' + }} +/> + + + + + + diff --git a/website/src/pages/index.tsx b/website/src/pages/index.tsx deleted file mode 100644 index 6a6c4e3abb8..00000000000 --- a/website/src/pages/index.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { FC } from 'react'; -import dynamic from 'next/dynamic'; -import { FeatureList, HeroGradient, HeroIllustration } from '@theguild/components'; -import { handlePushRoute, NPMBadge } from '@guild-docs/client'; -import tw from 'twin.macro'; - -const LiveDemo = dynamic(() => import('../components/live-demo/LiveDemo'), { ssr: false }); - -const IndexPage: FC = () => { - return ( - <> - handlePushRoute('/docs/getting-started', e), - }} - version={} - colors={['#1dbbff', '#ee1cd9']} - image={{ - className: 'no-right', - src: '/assets/illustrations/gql-codegen-cover.svg', - alt: 'Illustration', - }} - wrapperProps={{ - style: { marginTop: 12 }, - }} - /> - -
- -
- - - - - - ); -}; - -export default IndexPage; diff --git a/website/src/pages/meta.json b/website/src/pages/meta.json new file mode 100644 index 00000000000..e59cb4e3b52 --- /dev/null +++ b/website/src/pages/meta.json @@ -0,0 +1,29 @@ +{ + "index": { + "title": "Home", + "type": "page", + "theme": { + "layout": "raw" + } + }, + "docs": { + "title": "Docs", + "type": "page", + "theme": { + "toc": true + } + }, + "plugins": { + "title": "Plugins", + "type": "page", + "theme": { + "toc": false + } + }, + "contact-us-link": { + "title": "Contact Us", + "href": "https://the-guild.dev/contact", + "type": "page", + "newWindow": true + } +} diff --git a/website/src/pages/plugins/[name].tsx b/website/src/pages/plugins/[name].tsx deleted file mode 100644 index bd0761e4a95..00000000000 --- a/website/src/pages/plugins/[name].tsx +++ /dev/null @@ -1,200 +0,0 @@ -import { FC } from 'react'; -import { GetStaticPaths, GetStaticProps } from 'next'; -import Head from 'next/head'; -import { format } from 'date-fns'; -import tw, { styled } from 'twin.macro'; -import { Box, Center, Code, Container, Grid, SimpleGrid } from '@chakra-ui/react'; -import { PackageInstall, RemoteGHMarkdown, EditOnGitHubButton } from '@guild-docs/client'; -import { buildMDX, CompiledMDX } from '@guild-docs/server'; -import { getPackagesData, PackageInfo, PackageWithStats } from '@guild-docs/server/npm'; -import { packageList } from '../../lib/plugins'; - -export const SubTitle = styled.h2(() => [tw`mt-0 mb-4 font-bold text-lg md:text-xl`]); -export const Title = styled.h2(() => [tw`mt-0 mb-4 font-bold text-xl md:text-2xl`]); - -const StyledLink = styled.a(() => [tw`cursor-pointer`]); -const CodeLink = styled(Code)(() => [tw`hover:font-bold`]); - -interface PluginPageProps { - data: (PackageWithStats & { mdx: CompiledMDX })[]; -} - -type PluginPageParams = { - name: string; -}; - -export const getStaticProps: GetStaticProps = async ctx => { - const pluginName = ctx.params?.name; - - const pluginsData = - typeof pluginName === 'string' - ? await getPackagesData({ - idSpecific: pluginName, - packageList, - }) - : []; - - const data = await Promise.all( - pluginsData.map(async plugin => { - return { - ...plugin, - mdx: await buildMDX(plugin.readme || plugin.stats?.readme || ''), - }; - }) - ); - - return { - props: { - data, - }, - // Revalidate at most once every 1 hour - revalidate: 60 * 60, - }; -}; - -export const getStaticPaths: GetStaticPaths = async () => { - const plugins = await getPackagesData({ packageList }); - - return { - fallback: 'blocking', - paths: plugins.map(({ identifier }) => { - return { - params: { - name: identifier, - }, - }; - }), - }; -}; - -const PluginPageContent: FC = ({ data }) => { - if (!data.length) { - return ( -
- 404 -
Plugin not found.
-
- ); - } - - const pluginData = data[0]; - - const description = pluginData.stats?.description ? pluginData.stats.description : null; - const title = `${pluginData.title} | GraphQL Codegen Plugin Hub`; - const repoInfo = extractRepositoryInformation(pluginData.stats); - - return ( - <> - - {title} - - - {description && ( - <> - - - - - )} - - - {pluginData.title} - - - - - - - Package Details - -
Package
-
- - {pluginData.npmPackage} - -
- {pluginData.stats?.license ? ( - <> -
License
-
- {pluginData.stats.license} -
- - ) : null} - {pluginData.stats?.version ? ( - <> -
Version
-
- {pluginData.stats.version} -
- - ) : null} - {pluginData.stats?.modifiedDate ? ( - <> -
Updated
-
- {format(new Date(pluginData.stats.modifiedDate), 'MMM do, yyyy')} -
- - ) : null} - {pluginData.stats?.weeklyNPMDownloads ? ( - <> -
Weekly Downloads
-
- {pluginData.stats?.weeklyNPMDownloads} -
- - ) : null} - {repoInfo ? ( - - ) : null} -
-
-
-
- - ); -}; - -/** - * TODO: document how people can configure their yoga plugin package.json so it properly processed. - */ -function extractRepositoryInformation(stats: PackageInfo | null | undefined) { - if ( - stats?.repository == null || - typeof stats.repository !== 'object' || - !stats.repository.directory || - !stats.repository.url - ) { - return null; - } - - const parseRepoURLRegex = /git\+https:\/\/github\.com\/([A-Za-z0-9-]+\/[A-Za-z0-9-]+)\.git/; - const result = stats.repository.url.match(parseRepoURLRegex); - - if (result === null) { - return null; - } - - const [, repo] = result; - - return { - repo, - baseDir: stats.repository.directory, - /** TODO: this should probably be more flexible. */ - sourceFilePath: '', - /** TODO: this should probably be more flexible. */ - branch: 'master', - }; -} - -export default PluginPageContent; diff --git a/website/src/pages/plugins/[name].tsx.old b/website/src/pages/plugins/[name].tsx.old new file mode 100644 index 00000000000..abbab4709ed --- /dev/null +++ b/website/src/pages/plugins/[name].tsx.old @@ -0,0 +1,225 @@ +import { ReactElement } from 'react'; +import { GetStaticPaths, GetStaticProps } from 'next'; +import Head from 'next/head'; +import { getPackagesData, PackageInfo, PackageWithStats } from '@guild-docs/server/npm'; +import { compileMdx } from 'nextra/compile'; +import { MDXRemote } from 'next-mdx-remote'; +import { components } from 'nextra-theme-docs/theme'; +import createLayout from 'nextra-theme-docs'; +import themeConfig from '../../../theme.config'; +import { PACKAGES } from '@/lib/plugins'; +import { PackageCmd } from '@/components'; + +interface PluginPageProps { + data: (PackageWithStats & { compiledSource: string })[]; +} + +type PluginPageParams = { + name: string; +}; + +export const getStaticProps: GetStaticProps = async ctx => { + const pluginName = ctx.params?.name; + + const pluginsData = + typeof pluginName === 'string' + ? await getPackagesData({ + idSpecific: pluginName, + packageList: PACKAGES, + }) + .catch(err => { + console.log(err) + throw err + }) + : []; + + const data = await Promise.all( + pluginsData.map(async plugin => { + const source = plugin.readme || plugin.stats?.readme || ''; + const mdx = await compileMdx(source, { + outputFormat: 'function-body', + jsx: false, + }); + + const compiledSource = mdx.result; + + return { + ...plugin, + compiledSource, + }; + }) + ); + + return { + props: { + data, + }, + // Revalidate at most once every 1 hour + revalidate: 60 * 60, + }; +}; + +export const getStaticPaths: GetStaticPaths = async () => { + const plugins = await getPackagesData({ packageList: PACKAGES }); + + return { + fallback: 'blocking', + paths: plugins.map(({ identifier }) => ({ + params: { + name: identifier, + }, + })), + }; +}; + +const NextraLayout = createLayout( + { + filename: '[name].tsx', + route: '/plugins/[name]', + meta: {}, + pageMap: [ + { + name: 'plugins', + children: PACKAGES.map(pkg => ({ + name: pkg.identifier, + route: `/plugins/${pkg.identifier}`, + })), + // [ + // { + // name: '[name]', + // route: '/plugins/[name]' + // } + // ], + }, + ], + titleText: undefined, + headings: [], + hasH1: false, + timestamp: null, + }, + themeConfig +); + +const PluginPage = ({ data }: PluginPageProps): ReactElement => { + const pluginData = data[0]; + + if (!pluginData) { + return ( +
+

404

+
Plugin not found.
+
+ ); + } + + const description = pluginData.stats?.description ? pluginData.stats.description : null; + const title = `${pluginData.title} | GraphQL Codegen Plugin Hub`; + const repoInfo = extractRepositoryInformation(pluginData.stats); + + return ( + + + {title} + + + {description && ( + <> + + + + + )} + +
+

{pluginData.title}

+

Install

+ + +
+ {/*
*/} + {/*

Package Details

*/} + {/*
*/} + {/*
Package
*/} + {/* */} + {/* {pluginData.stats?.license ? (*/} + {/* <>*/} + {/*
License
*/} + {/*
*/} + {/* {pluginData.stats.license}*/} + {/*
*/} + {/* */} + {/* ) : null}*/} + {/* {pluginData.stats?.version ? (*/} + {/* <>*/} + {/*
Version
*/} + {/*
*/} + {/* {pluginData.stats.version}*/} + {/*
*/} + {/* */} + {/* ) : null}*/} + {/* {pluginData.stats?.modifiedDate ? (*/} + {/* <>*/} + {/*
Updated
*/} + {/*
*/} + {/* {format(new Date(pluginData.stats.modifiedDate), 'MMM do, yyyy')}*/} + {/*
*/} + {/* */} + {/* ) : null}*/} + {/* {pluginData.stats?.weeklyNPMDownloads ? (*/} + {/* <>*/} + {/*
Weekly Downloads
*/} + {/*
*/} + {/* {pluginData.stats?.weeklyNPMDownloads}*/} + {/*
*/} + {/* */} + {/* ) : null}*/} + {/* {repoInfo ? (*/} + {/* */} + {/* ) : null}*/} + {/*
*/} + + ); +}; + +/** + * TODO: document how people can configure their yoga plugin package.json so it properly processed. + */ +function extractRepositoryInformation(stats?: PackageInfo | null) { + if ( + stats?.repository == null || + typeof stats.repository !== 'object' || + !stats.repository.directory || + !stats.repository.url + ) { + return null; + } + + const parseRepoURLRegex = /git\+https:\/\/github\.com\/([A-Za-z0-9-]+\/[A-Za-z0-9-]+)\.git/; + const result = stats.repository.url.match(parseRepoURLRegex); + + if (result === null) { + return null; + } + + return { + repo: result[1], + baseDir: stats.repository.directory, + /** TODO: this should probably be more flexible. */ + sourceFilePath: '', + /** TODO: this should probably be more flexible. */ + branch: 'master', + }; +} + +PluginPage.getLayout = NextraLayout.getLayout; + +export default PluginPage; diff --git a/website/docs-templates/c-sharp-operations.md b/website/src/pages/plugins/c-sharp/c-sharp-operations.mdx similarity index 66% rename from website/docs-templates/c-sharp-operations.md rename to website/src/pages/plugins/c-sharp/c-sharp-operations.mdx index ee1d165061c..6fd81ad77e2 100644 --- a/website/docs-templates/c-sharp-operations.md +++ b/website/src/pages/plugins/c-sharp/c-sharp-operations.mdx @@ -1,7 +1,14 @@ --- -id: c-sharp-operations +title: c-sharp-operations --- +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('c-sharp-operations') + + + The `c-sharp-operations` plugin generates C# methods for the resolvers' signature. It works with [GraphQL.Client](https://nuget.org/packages/GraphQL.Client) library and methods can be invoked through the `GraphQLHttpClient`. @@ -17,6 +24,4 @@ using GraphQL.Client.Serializer.Newtonsoft; var response = await client.SendQueryAsync(UsersGQL.Request()); ``` -{@operationsNote} - -{@apiDocs} + diff --git a/website/src/pages/plugins/c-sharp/meta.json b/website/src/pages/plugins/c-sharp/meta.json new file mode 100644 index 00000000000..307d49c50f3 --- /dev/null +++ b/website/src/pages/plugins/c-sharp/meta.json @@ -0,0 +1,3 @@ +{ + "c-sharp-operations": "operations" +} diff --git a/website/src/pages/plugins/flow/flow-operations.mdx b/website/src/pages/plugins/flow/flow-operations.mdx new file mode 100644 index 00000000000..6fb0ca7bed5 --- /dev/null +++ b/website/src/pages/plugins/flow/flow-operations.mdx @@ -0,0 +1,11 @@ +--- +title: flow-operations +--- + +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('flow-operations') + + + diff --git a/website/docs-templates/flow-resolvers.md b/website/src/pages/plugins/flow/flow-resolvers.mdx similarity index 71% rename from website/docs-templates/flow-resolvers.md rename to website/src/pages/plugins/flow/flow-resolvers.mdx index e22eb987147..18c01afdc2f 100644 --- a/website/docs-templates/flow-resolvers.md +++ b/website/src/pages/plugins/flow/flow-resolvers.mdx @@ -1,14 +1,23 @@ --- -id: flow-resolvers +title: flow-resolvers --- -{@apiDocs} +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('flow-resolvers') + + ## Usage Example -> **Quick Start with `flow-resolvers`** -> -> You can find [a blog post we wrote about using and customizing this plugin here](https://the-guild.dev/blog/better-type-safety-for-resolvers-with-graphql-codegen), it refers to `typescript-resolvers` but everything there is relevant to `flow-resolvers` as well. + +**Quick Start with `flow-resolvers`** + +You can find [a blog post we wrote about using and customizing this plugin here](https://the-guild.dev/blog/better-type-safety-for-resolvers-with-graphql-codegen), it refers to `typescript-resolvers` but everything there is relevant to `flow-resolvers` as well. + + ## Enum Resolvers @@ -45,14 +54,14 @@ generates: - flow-resolvers ``` -```ts -// in your enums.js +```ts filename="enums.ts" export enum ColorsCode { MY_RED = '#FF0000', MY_BLUE = '#0000FF' } +``` -// in your resolvers.js +```ts filename="resolvers.ts" import type { Resolvers } from './resolvers-types' import { ColorsCode } from './enums' @@ -69,7 +78,7 @@ const resolvers: Resolvers = { You can also define the same with explicit enum values: -```yaml +```yaml {7-8} schema: schema.graphql generates: ./resolvers-types.js: @@ -85,7 +94,7 @@ generates: Or, with `mappers`: -```yaml +```yaml {5-6} schema: schema.graphql generates: ./resolvers-types.js: @@ -96,3 +105,5 @@ generates: - flow - flow-resolvers ``` + + diff --git a/website/src/pages/plugins/flow/meta.json b/website/src/pages/plugins/flow/meta.json new file mode 100644 index 00000000000..ff57065f4f2 --- /dev/null +++ b/website/src/pages/plugins/flow/meta.json @@ -0,0 +1,4 @@ +{ + "flow-operations": "operations", + "flow-resolvers": "resolvers" +} diff --git a/website/src/pages/plugins/index.mdx b/website/src/pages/plugins/index.mdx new file mode 100644 index 00000000000..693b694b147 --- /dev/null +++ b/website/src/pages/plugins/index.mdx @@ -0,0 +1,39 @@ +--- +title: Plugins +--- + +import { buildMultipleMDX } from '@guild-docs/server'; +import { getPackagesData } from '@guild-docs/server/npm'; +import { Plugins } from '@/components/plugins'; +import { PACKAGES } from '@/lib/plugins'; + +export const getStaticProps = async () => { + const pluginsData = await getPackagesData({ packageList: PACKAGES }); + + const data = await Promise.all( + pluginsData.map(async plugin => { + const [description, content] = await buildMultipleMDX([ + `${plugin.stats?.version || ''}\n\n${plugin.stats?.description || ''}`, + plugin.readme || plugin.stats?.readme || '', + ]); + + return { + ...plugin, + description, + content, + }; + }) + ); + + return { + props: { + // We add an `ssg` field to the page props, + // which will be provided to the Nextra's `useSSG` hook. + ssg: { data }, + }, + // Revalidate at most once every 1 hour + revalidate: 60 * 60, + }; +}; + + diff --git a/website/src/pages/plugins/index.tsx b/website/src/pages/plugins/index.tsx deleted file mode 100644 index e5919857e51..00000000000 --- a/website/src/pages/plugins/index.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import { FC, useMemo } from 'react'; -import type { GetStaticProps } from 'next'; -import Head from 'next/head'; -import { compareDesc } from 'date-fns'; -import { handlePushRoute } from '@guild-docs/client'; -import { buildMultipleMDX, CompiledMDX } from '@guild-docs/server'; -import { getPackagesData, PackageWithStats } from '@guild-docs/server/npm'; -import { MarketplaceSearch } from '@theguild/components'; -import { IMarketplaceItemProps } from '@theguild/components/dist/types/components'; - -import Markdown from '../../components/ui/Markdown'; -import { ALL_TAGS, packageList } from '../../lib/plugins'; - -type MarketplaceProps = { - data: (PackageWithStats & { - description: CompiledMDX; - content: CompiledMDX; - })[]; -}; - -export const getStaticProps: GetStaticProps = async () => { - const pluginsData = await getPackagesData({ packageList }); - - const data = await Promise.all( - pluginsData.map(async plugin => { - const [description, content] = await buildMultipleMDX([ - `${plugin.stats?.version || ''}\n\n${plugin.stats?.description || ''}`, - plugin.readme || plugin.stats?.readme || '', - ]); - - return { - ...plugin, - description, - content, - }; - }) - ); - - return { - props: { - data, - }, - // Revalidate at most once every 1 hour - revalidate: 60 * 60, - }; -}; - -const Marketplace: FC = ({ data }) => { - const marketplaceItems: (IMarketplaceItemProps & { raw: PackageWithStats })[] = useMemo( - () => - data.map(rawPlugin => { - const linkHref = `/plugins/${rawPlugin.identifier}`; - return { - raw: rawPlugin, - tags: rawPlugin.tags, - title: rawPlugin.title, - link: { - href: linkHref, - title: `${rawPlugin.title} plugin details`, - onClick: ev => handlePushRoute(linkHref, ev), - }, - description: , - update: rawPlugin.stats?.modifiedDate || new Date().toISOString(), - image: rawPlugin.iconUrl - ? { - height: 60, - width: 60, - src: rawPlugin.iconUrl, - alt: rawPlugin.title, - } - : undefined, - }; - }), - [data] - ); - - const recentlyUpdatedItems = useMemo( - () => [...marketplaceItems].sort((a, b) => compareDesc(new Date(a.update), new Date(b.update))), - [marketplaceItems] - ); - - const trendingItems = useMemo( - () => - marketplaceItems - .filter(i => i.raw.stats?.weeklyNPMDownloads) - .sort((a, b) => { - const aMonthlyDownloads = a.raw.stats?.weeklyNPMDownloads || 0; - const bMonthlyDownloads = b.raw.stats?.weeklyNPMDownloads || 0; - - return bMonthlyDownloads - aMonthlyDownloads; - }), - [marketplaceItems] - ); - - return ( - <> - - Plugin Hub - - - - ); -}; - -export default Marketplace; diff --git a/website/docs-templates/java-apollo-android.md b/website/src/pages/plugins/java/java-apollo-android.mdx similarity index 59% rename from website/docs-templates/java-apollo-android.md rename to website/src/pages/plugins/java/java-apollo-android.mdx index 9d728fff2b9..05604dd916e 100644 --- a/website/docs-templates/java-apollo-android.md +++ b/website/src/pages/plugins/java/java-apollo-android.mdx @@ -1,22 +1,25 @@ --- -id: java-apollo-android +title: java-apollo-android --- -{@apiDocs} +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader, PackageCmd } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('java-apollo-android') + + ## Prepare your env To get started with these plugins and preset, make sure you have the following installed: -- NodeJS (10 or later) +- Node.js (10 or later) - NPM or Yarn Run the following in your Android project: -```sh -yarn init --yes -yarn add @graphql-codegen/cli graphql @graphql-codegen/java-apollo-android -``` + Then, create `codegen.yml` with the following configuration: @@ -34,14 +37,14 @@ generates: - java-apollo-android ``` -> Also, make sure to add `node_modules` to your `.gitignore` file. +Also, make sure to add `node_modules` to your `.gitignore` file. To integrate with your Gradle build, you can add the following to your app Gradle file: ``` preBuild.doFirst { - def proc = "yarn graphql-codegen".execute() - proc.waitForProcessOutput(System.out, System.err) + def proc = "yarn graphql-codegen".execute() + proc.waitForProcessOutput(System.out, System.err) } build.dependsOn preBuild @@ -51,4 +54,6 @@ This will make sure to run and generate output before each time you build your p ## Usage -You can find a [repository with a working example using AppSync](https://github.com/dotansimha/graphql-codegen-appsync-android-example) +You can find a [repository with a working example using AppSync](https://github.com/dotansimha/graphql-codegen-appsync-android-example). + + diff --git a/website/src/pages/plugins/java/java-resolvers.mdx b/website/src/pages/plugins/java/java-resolvers.mdx new file mode 100644 index 00000000000..097d4d51cc6 --- /dev/null +++ b/website/src/pages/plugins/java/java-resolvers.mdx @@ -0,0 +1,87 @@ +--- +title: java-resolvers +--- + +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('java-resolvers') + + + +The `java-resolvers` plugin creates Java `interface`s for the resolvers' signature. + +It works with `graphql-java` library, and it uses it's `DataFetcher` API. + +You can use this plugin to generate interfaces and later implement them, this way you can always tell if one of the fields is missing a resolvers: + +```java +import com.my.app.generated.Resolvers; +import com.my.app.models.User; +import graphql.schema.DataFetcher; + +export class QueryResolvers implements Resolvers.Query { + public DataFetcher id() { + return environment -> environment.getSource().getId(); + } +} +``` + +## Prepare your environment + +To use the GraphQL Code Generator with Java, start by adding the [com.moowork.node](https://plugins.gradle.org/plugin/com.moowork.node) Gradle plugin to your `build.gradle`: + +``` +plugins { + id "com.moowork.node" version "1.3.1" +} +``` + +Then, add the following in order to make sure you are running the code-generator on each build: + +``` +build.dependsOn yarn +``` + +Then, create a `package.json` file in your project root, with the following content: + +```json +{ + "name": "java-app", + "scripts": { + "postinstall": "graphql-codegen" + }, + "dependencies": { + "graphql": "14.5.8", + "@graphql-codegen/cli": "1.7.0", + "@graphql-codegen/RELEVANT_PLUGIN": "1.7.0" + } +} +``` + + + Make sure to use the latest version of codegen and the plugins, and replace `RELEVANT_PLUGIN` with your plugin name. + + +Then, create `codegen.yml` file in your root directory, pointing to your schema, and add the plugins you need. For example: + +```yaml +schema: src/main/resources/schema.graphqls +generates: + src/main/java/com/my-name/my-app/generated/File.java: + - RELEVANT_PLUGIN # Replace with your plugin name +``` + +Also, make sure you add the following to your `.gitignore` file: + +```text +yarn.lock +node_modules +``` + +Now, run `gradle yarn` to install the dependencies for the first time. + +Next time, the codegen will run automatically each time you run your Gradle build script. + + diff --git a/website/docs-templates/java-installation.md b/website/src/pages/plugins/java/java.mdx similarity index 55% rename from website/docs-templates/java-installation.md rename to website/src/pages/plugins/java/java.mdx index 2d40eb5f659..1fe0dad54f0 100644 --- a/website/docs-templates/java-installation.md +++ b/website/src/pages/plugins/java/java.mdx @@ -1,3 +1,17 @@ +--- +title: java +--- + +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('java') + + + +## Prepare your environment + To use the GraphQL Code Generator with Java, start by adding the [com.moowork.node](https://plugins.gradle.org/plugin/com.moowork.node) Gradle plugin to your `build.gradle`: ``` @@ -28,7 +42,9 @@ Then, create a `package.json` file in your project root, with the following cont } ``` -> Make sure to use the latest version of codegen and the plugins, and replace `RELEVANT_PLUGIN` with your plugin name. + + Make sure to use the latest version of codegen and the plugins, and replace `RELEVANT_PLUGIN` with your plugin name. + Then, create `codegen.yml` file in your root directory, pointing to your schema, and add the plugins you need. For example: @@ -36,14 +52,12 @@ Then, create `codegen.yml` file in your root directory, pointing to your schema, schema: src/main/resources/schema.graphqls generates: src/main/java/com/my-name/my-app/generated/File.java: - - RELEVANT_PLUGIN + - RELEVANT_PLUGIN # Replace with your plugin name ``` -> Replace `RELEVANT_PLUGIN` with your plugin name. - Also, make sure you add the following to your `.gitignore` file: -```gitignore +```text yarn.lock node_modules ``` @@ -51,3 +65,38 @@ node_modules Now, run `gradle yarn` to install the dependencies for the first time. Next time, the codegen will run automatically each time you run your Gradle build script. + +## How to use + +You can use it directly to transform your `input` in your resolvers: + +```graphql +type Query { + user(id: ID!): User! +} + +type User { + id: ID +} +``` + +Then, in your resolver: + +```java +import com.my.app.generated.Types; +import com.my.app.models.User; +import graphql.schema.DataFetcher; + +export class QueryResolvers { + public DataFetcher user() { + return env -> { + Types.QueryUserArgs args = new Types.QueryUserArgs(env.getArguments()); + String userId = args.getId(); + + // rest of the code + }; + } +} +``` + + diff --git a/website/docs-templates/kotlin.md b/website/src/pages/plugins/java/kotlin.mdx similarity index 56% rename from website/docs-templates/kotlin.md rename to website/src/pages/plugins/java/kotlin.mdx index 92824b20aeb..ac91341540f 100644 --- a/website/docs-templates/kotlin.md +++ b/website/src/pages/plugins/java/kotlin.mdx @@ -1,7 +1,15 @@ --- -id: kotlin +title: kotlin --- +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader, PackageCmd } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('kotlin') + + + The `kotlin` plugin generates Kotlin `classes` for Enums and Input types. You can use this plugin to generate Java enums based on your GraphQL schema, and it also generates a type-safe Kotlin transformer for GraphQL `input` types. @@ -10,15 +18,12 @@ You can use this plugin to generate Java enums based on your GraphQL schema, and To get started with these plugins and preset, make sure you have the following installed: -- NodeJS (10 or later) +- Node.js (10 or later) - NPM or Yarn Run the following in your Android project: -```sh -yarn init --yes -yarn add @graphql-codegen/cli graphql @graphql-codegen/kotlin -``` + Then, create `codegen.yml` with the following configuration: @@ -31,6 +36,6 @@ generates: - kotlin ``` -> Also, make sure to add `node_modules` to your `.gitignore` file. +Also, make sure to add `node_modules` to your `.gitignore` file. -{@apiDocs} + diff --git a/website/src/pages/plugins/java/meta.json b/website/src/pages/plugins/java/meta.json new file mode 100644 index 00000000000..f1de40805d5 --- /dev/null +++ b/website/src/pages/plugins/java/meta.json @@ -0,0 +1,6 @@ +{ + "java": "java", + "java-apollo-android": "java-apollo-android", + "java-resolvers": "java-resolvers", + "kotlin": "kotlin" +} diff --git a/website/src/pages/plugins/meta.json b/website/src/pages/plugins/meta.json new file mode 100644 index 00000000000..e1bdb4c20d4 --- /dev/null +++ b/website/src/pages/plugins/meta.json @@ -0,0 +1,13 @@ +{ + "index": { + "title": "Plugins", + "theme": { + "layout": "raw" + } + }, + "typescript": "TypeScript", + "presets": "Presets", + "java": "Java", + "c-sharp": "C-Sharp", + "flow": "Flow" +} diff --git a/website/docs-templates/add.md b/website/src/pages/plugins/other/add.mdx similarity index 66% rename from website/docs-templates/add.md rename to website/src/pages/plugins/other/add.mdx index 2e0cbadc7a1..b053e46908f 100644 --- a/website/docs-templates/add.md +++ b/website/src/pages/plugins/other/add.mdx @@ -1,17 +1,22 @@ --- -id: add +title: add --- +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('add') + + + `add` plugin adds custom text to your output file. You can use this plugin to add custom code, imports, comments and more to your output file. -{@apiDocs} - ## Examples -```yaml -# ... +```yaml {5-6} +# … generates: path/to/file.ts: plugins: @@ -20,8 +25,8 @@ generates: - typescript ``` -```yaml -# ... +```yaml {5-10} +# … generates: path/to/file.ts: plugins: @@ -33,3 +38,5 @@ generates: content: '}' - typescript ``` + + diff --git a/website/docs-templates/fragment-matcher.md b/website/src/pages/plugins/other/fragment-matcher.mdx similarity index 54% rename from website/docs-templates/fragment-matcher.md rename to website/src/pages/plugins/other/fragment-matcher.mdx index b3c57d72e8e..653776daad7 100644 --- a/website/docs-templates/fragment-matcher.md +++ b/website/src/pages/plugins/other/fragment-matcher.mdx @@ -1,13 +1,20 @@ --- -id: fragment-matcher +title: fragment-matcher --- -{@apiDocs} +import Callout from 'nextra-theme-docs/callout' +import { Tabs, Tab } from 'nextra-theme-docs/tabs' +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' -## How to use? +export const getStaticProps = getNpmInfo('fragment-matcher') + + -## Usage with Apollo Client 3 +## How to use? + + If you are using Apollo Client 3, update your codegen config accordingly, and then use it in your Apollo cache instance: ```ts @@ -19,11 +26,13 @@ import generatedIntrospection from '../introspection-result' const cache = new InMemoryCache({ possibleTypes: generatedIntrospection.possibleTypes }) ``` -> [Read more about fragment matcher and its usage on Apollo Client](https://apollographql.com/docs/react/data/fragments/#defining-possibletypes-manually) + +[Read more about fragment matcher and its usage on Apollo Client](https://apollographql.com/docs/react/data/fragments/#defining-possibletypes-manually). + + -## Usage with Apollo Client 2 - -If you are using version 2 of Apollo-Client, you need to specify the `apolloClientVersion: 2` configuration, and then use it like that: + +If you are using version 2 of Apollo-Client, you need to specify the `apolloClientVersion: 2{:yaml}` configuration, and then use it like that: ```ts import { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory' @@ -37,3 +46,8 @@ const fragmentMatcher = new IntrospectionFragmentMatcher({ const cache = new InMemoryCache({ fragmentMatcher }) ``` + + + + + diff --git a/website/docs-templates/hasura-allow-list.md b/website/src/pages/plugins/other/hasura-allow-list.mdx similarity index 51% rename from website/docs-templates/hasura-allow-list.md rename to website/src/pages/plugins/other/hasura-allow-list.mdx index 3124cd454a7..903461bbbbe 100644 --- a/website/docs-templates/hasura-allow-list.md +++ b/website/src/pages/plugins/other/hasura-allow-list.mdx @@ -1,21 +1,28 @@ --- -id: hasura-allow-list +title: hasura-allow-list --- +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('hasura-allow-list') + + + Generate hasura allow list metadata from graphql files -You can use this plugin to generate an [allow list](https://hasura.io/docs/latest/graphql/cloud/security/allow-lists.html) for your [hasura](https://hasura.io/) project. +You can use this plugin to generate an [allow list](https://hasura.io/docs/latest/graphql/cloud/security/allow-lists.html) for your [hasura](https://hasura.io) project. This can be useful to keep your allow list and front end code in sync. -{@apiDocs} - ## Examples -```yaml -# ... +```yaml {5} +# … generates: path/to/metadata/allow_list.yaml: plugins: - - hasura-allow-list: + - hasura-allow-list ``` + + diff --git a/website/src/pages/plugins/other/introspection.mdx b/website/src/pages/plugins/other/introspection.mdx new file mode 100644 index 00000000000..505b55d988b --- /dev/null +++ b/website/src/pages/plugins/other/introspection.mdx @@ -0,0 +1,11 @@ +--- +title: introspection +--- + +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('introspection') + + + diff --git a/website/src/pages/plugins/other/jsdoc.mdx b/website/src/pages/plugins/other/jsdoc.mdx new file mode 100644 index 00000000000..226a226bcad --- /dev/null +++ b/website/src/pages/plugins/other/jsdoc.mdx @@ -0,0 +1,14 @@ +--- +title: jsdoc +--- + +import { PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('jsdoc') + + + +_developed by [`CarloPalinckx`](https://github.com/CarloPalinckx)_ + +This plugin generates types in the form of JSDoc comments based on your GraphQLSchema. diff --git a/website/src/pages/plugins/other/meta.json b/website/src/pages/plugins/other/meta.json new file mode 100644 index 00000000000..95408d650d3 --- /dev/null +++ b/website/src/pages/plugins/other/meta.json @@ -0,0 +1,11 @@ +{ + "add": "add", + "fragment-matcher": "fragment-matcher", + "hasura-allow-list": "hasura-allow-list", + "introspection": "introspection", + "jsdoc": "jsdoc", + "reason-client": "reason-client", + "schema-ast": "schema-ast", + "time": "time", + "urql-introspection": "urql-introspection" +} diff --git a/website/docs-templates/reason-client.md b/website/src/pages/plugins/other/reason-client.mdx similarity index 62% rename from website/docs-templates/reason-client.md rename to website/src/pages/plugins/other/reason-client.mdx index cbd2524d9f3..75fe80bfd54 100644 --- a/website/docs-templates/reason-client.md +++ b/website/src/pages/plugins/other/reason-client.mdx @@ -1,14 +1,21 @@ --- -id: reason-client +title: reason-client --- -_Built and maintained by [kgoggin](https://github.com/kgoggin)_ +import { PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('reason-client') + + + +_Built and maintained by [kgoggin](https://github.com/kgoggin)_. A plugin for GraphQL Codegen to generate ReasonML types based on your GraphQL schema for use in a client application. ## Examples -Set up your project per the GraphQL Codegen Docs, and specify this plugin in your codegen.yml: +Set up your project per the GraphQL Codegen Docs, and specify this plugin in your `codegen.yml`: ```yaml schema: http://path.to.your.app diff --git a/website/src/pages/plugins/other/schema-ast.mdx b/website/src/pages/plugins/other/schema-ast.mdx new file mode 100644 index 00000000000..3d01d9d3c27 --- /dev/null +++ b/website/src/pages/plugins/other/schema-ast.mdx @@ -0,0 +1,26 @@ +--- +title: schema-ast +--- + +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('schema-ast') + + + +## Examples + +```yaml {9} +# … +schema: + - 'http://localhost:3000/graphql' + - './src/**/*.graphql' + - 'scalar MyCustomScalar' +generates: + path/to/file.graphql: + plugins: + - schema-ast +``` + + diff --git a/website/src/pages/plugins/other/time.mdx b/website/src/pages/plugins/other/time.mdx new file mode 100644 index 00000000000..935c29ae3b8 --- /dev/null +++ b/website/src/pages/plugins/other/time.mdx @@ -0,0 +1,11 @@ +--- +title: time +--- + +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('time') + + + diff --git a/website/src/pages/plugins/other/urql-introspection.mdx b/website/src/pages/plugins/other/urql-introspection.mdx new file mode 100644 index 00000000000..0f2820d6fa7 --- /dev/null +++ b/website/src/pages/plugins/other/urql-introspection.mdx @@ -0,0 +1,25 @@ +--- +title: urql-introspection +--- + +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('urql-introspection') + + + +## How to use? + +```ts +// generated by the plugin +import schema from './generated-introspection.json' +const cache = cacheExchange({ schema }) +``` + + + [Read more about Schema Awareness](https://formidable.com/open-source/urql/docs/graphcache/schema-awareness) + + + diff --git a/website/docs-templates/gql-tag-operations-preset.md b/website/src/pages/plugins/presets/gql-tag-operations-preset.mdx similarity index 85% rename from website/docs-templates/gql-tag-operations-preset.md rename to website/src/pages/plugins/presets/gql-tag-operations-preset.mdx index 343e744a75a..9a5d6c720e9 100644 --- a/website/docs-templates/gql-tag-operations-preset.md +++ b/website/src/pages/plugins/presets/gql-tag-operations-preset.mdx @@ -1,7 +1,15 @@ --- -id: gql-tag-operations +title: gql-tag-operations-preset --- +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('gql-tag-operations-preset') + + + This preset generates typings for your inline `gql` function usages, without having to manually specify import statements for the documents. All you need to do is import your `gql` function and run codegen in watch mode. Huge thanks to [Maël Nison](https://github.com/arcanis), who conceptualized the foundation for this preset [over here](https://github.com/arcanis/graphql-typescript-integration). @@ -43,7 +51,7 @@ generates: It is also recommended, that you link `./src/gql` to `@app/gql`, so you can import your gql function easily from anywhere within your app. -```bash +```sh yarn add -D @app/gql@link:./src/gql ``` @@ -64,7 +72,7 @@ const TweetsQuery = gql(/* GraphQL */ ` `) ``` -Next we can simply add our GraphQL client of choice and use the typed document! Let's try urql! +Next we can simply add our GraphQL client of choice and use the typed document! Let's try `urql`! ```tsx import { gql } from '@app/gql' @@ -84,8 +92,8 @@ const Tweets = () => { const [result] = useQuery({ query: TweetsQuery }) const { data, fetching, error } = result - if (fetching) return

Loading...

- if (error) return

Oh no... {error.message}

+ if (fetching) return

Loading…

+ if (error) return

Oh no… {error.message}

return (
    @@ -111,7 +119,7 @@ const TweetFragment = gql(/* GraphQL */ ` `) const Tweet = (props: { - /** tweet property has the correct type 🎉 */ + /* tweet property has the correct type 🎉 */ tweet: DocumentType }) => { return
  • {props.tweet.body}
  • @@ -130,8 +138,8 @@ const Tweets = () => { const [result] = useQuery({ query: TweetsQuery }) const { data, fetching, error } = result - if (fetching) return

    Loading...

    - if (error) return

    Oh no... {error.message}

    + if (fetching) return

    Loading…

    + if (error) return

    Oh no… {error.message}

    return (
      @@ -202,15 +210,13 @@ This will result in much smaller bundles when you code-split parts of your code. Applying the babel plugin is straight-forward: -**.babelrc.mjs** - -```ts +```ts filename=".babelrc.mjs" import { babelPlugin } from '@graphql-codegen/gql-tag-operations-preset' export default { plugins: [ // your other plugins such as typescript syntax stripping etc. - // make sure the artifactDirectory is the same as your generates path within the codegen.yml + // make sure the artifactDirectory is the same as your generates path within the `codegen.yml` [babelPlugin, { artifactDirectory: './src/gql' }] ] } @@ -224,9 +230,7 @@ Sometimes the library you are using, let's use `urql` for this example, already This can be easily achieved by running the `gql-tag-operations` plugin in module augmentation mode! -**codegen.yml** - -```yaml +```yaml filename="codegen.yml" schema: src/path/to/your/schema.graphql documents: - 'src/**/*.ts' @@ -267,7 +271,12 @@ const FooQuery = gql(/* GraphQL */ ` `) ``` -**NOTE**: In case you are using fragments you **MUST** use the gql-tag-operations babel plugin as otherwise the `gql` calls that reference global fragments will cause runtime errors, as the `gql` operation cannot find the global fragment. Unfortunately, it is also **NOT** possible to embed fragments with template string interpolation, as it breaks TypeScript type-inference. + + In case you are using fragments you **MUST** use the gql-tag-operations babel plugin as otherwise the `gql` calls that + reference global fragments will cause runtime errors, as the `gql` operation cannot find the global fragment. + Unfortunately, it is also **NOT** possible to embed fragments with template string interpolation, as it breaks + TypeScript type-inference. + ```ts import { gql } from 'urql' @@ -290,9 +299,7 @@ Fragment masking is a powerful tool that allows building scalable UI components, Fragment masking is enabled via the `fragmentMasking` config option. -**codegen.yml** - -```yaml +```yaml filename="codegen.yml" schema: src/path/to/your/schema.graphql documents: - 'src/**/*.ts' @@ -318,7 +325,7 @@ const TweetFragment = gql(/* GraphQL */ ` `) const Tweet = (props: { - /** tweet property has the correct type 🎉 */ + /* tweet property has the correct type 🎉 */ tweet: FragmentType }) => { // we unmask our fragment to the actual type @@ -339,8 +346,8 @@ const Tweets = () => { const [result] = useQuery({ query: TweetsQuery }) const { data, fetching, error } = result - if (fetching) return

      Loading...

      - if (error) return

      Oh no... {error.message}

      + if (fetching) return

      Loading…

      + if (error) return

      Oh no… {error.message}

      return (
        @@ -354,15 +361,18 @@ const Tweets = () => { } ``` -**Note**: The default `useFragment` implementation does only data masking on a TypeScript type level. If you log the object, you can all properties, including the masked ones, are available on the object. For true runtime data masking, the GraphQL client must implement it. Currently, there is no client that does this (aside from relay which should best be used with relay-compiler). + + The default `useFragment` implementation does only data masking on a TypeScript type level. If you log the object, you + can all properties, including the masked ones, are available on the object. For true runtime data masking, the GraphQL + client must implement it. Currently, there is no client that does this (aside from relay which should best be used + with relay-compiler). + ### Fragment Masking with custom unmask name By default, the data unmask function name is `useFragment`, which follows the React hook naming convention. For React users we recommend keeping that name. If you need to customize the name of the function you can provide the `fragmentMasking.unmaskFunctionName` option. -**codegen.yml** - -```yaml +```yaml filename="codegen.yml" schema: src/path/to/your/schema.graphql documents: - 'src/**/*.ts' @@ -380,9 +390,7 @@ generates: Similar to the `gql` module augmentation configuration it is also possible to generate type definitions for the unmask function. The `fragmentMasking.unmaskFunctionName` will be used when doing so. -**codegen.yml** - -```yaml +```yaml filename="codegen.yml" schema: src/path/to/your/schema.graphql documents: - 'src/**/*.ts' @@ -395,4 +403,4 @@ generates: augmentedModuleName: '@something/fragment' ``` -{@apiDocs} + diff --git a/website/docs-templates/graphql-modules-preset.md b/website/src/pages/plugins/presets/graphql-modules-preset.mdx similarity index 72% rename from website/docs-templates/graphql-modules-preset.md rename to website/src/pages/plugins/presets/graphql-modules-preset.mdx index b0edb66da09..ed9d4b1a5c0 100644 --- a/website/docs-templates/graphql-modules-preset.md +++ b/website/src/pages/plugins/presets/graphql-modules-preset.mdx @@ -1,20 +1,27 @@ --- -id: graphql-modules +title: graphql-modules-preset --- +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('graphql-modules-preset') + + + The `@graphql-codegen/graphql-modules-preset` generates `.ts` file with TypeScript types, per each directory that contains GraphQL SDL definitions. The generates files will be generated based on each module definition, and based on the GraphQL schema defined in that specific module, allowing you to write type-safe resolvers, while keeping modules types boundaries. - -This preset generates code for `graphql-modules` @ `v1` / `v2` (previous versions are not supported) by default. + +**Usage Requirements** -If you are not using `graphql-modules`, you can set `useGraphQLModules: false` to disable this behaviour. - +This preset generates code for `graphql-modules` @ `v1` / `v2` (previous versions are not supported) by default. -## Configuration +If you are not using `graphql-modules`, you can set `useGraphQLModules: false{:yaml}` to disable this behaviour. -{@apiDocs} + ## Usage Example @@ -54,8 +61,7 @@ This will generate a file called `module-types.ts` under each module you have. To use the generates resolvers, you can use `Resolvers` signature and apply it to your resolvers object within the module: -```ts -// src/modules/user/resolvers.ts +```ts filename="src/modules/user/resolvers.ts" import { MyModule } from './generated-types/module-types' export const resolvers: MyModule.Resolvers = { @@ -63,8 +69,13 @@ export const resolvers: MyModule.Resolvers = { } ``` -> You can find [an example project here](https://github.com/dotansimha/graphql-code-generator/tree/master/dev-test/modules). + + You can find [an example project + here](https://github.com/dotansimha/graphql-code-generator/tree/master/dev-test/modules). + ## Using without GraphQL-Modules -By default, this preset it generating code for `graphql-modules`, but if you are not using it, you can set `useGraphQLModules: false` in your preset configuration to generate fully agnostic types that are based on folder structure only. +By default, this preset it generating code for `graphql-modules`, but if you are not using it, you can set `useGraphQLModules: false{:yaml}` in your preset configuration to generate fully agnostic types that are based on folder structure only. + + diff --git a/website/src/pages/plugins/presets/import-types-preset.mdx b/website/src/pages/plugins/presets/import-types-preset.mdx new file mode 100644 index 00000000000..d10d3278af7 --- /dev/null +++ b/website/src/pages/plugins/presets/import-types-preset.mdx @@ -0,0 +1,14 @@ +--- +title: import-types-preset +--- + +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('import-types-preset') + + + +This preset generates a file per each operation file, and allow to import types from another file. + + diff --git a/website/src/pages/plugins/presets/meta.json b/website/src/pages/plugins/presets/meta.json new file mode 100644 index 00000000000..658264d526d --- /dev/null +++ b/website/src/pages/plugins/presets/meta.json @@ -0,0 +1,6 @@ +{ + "gql-tag-operations-preset": "gql-tag-operations", + "graphql-modules-preset": "graphql-modules", + "import-types-preset": "import-types", + "near-operation-file-preset": "near-operation-file" +} diff --git a/website/docs-templates/near-operation-file-preset.md b/website/src/pages/plugins/presets/near-operation-file-preset.mdx similarity index 69% rename from website/docs-templates/near-operation-file-preset.md rename to website/src/pages/plugins/presets/near-operation-file-preset.mdx index 3bab4c39199..7d2a165e920 100644 --- a/website/docs-templates/near-operation-file-preset.md +++ b/website/src/pages/plugins/presets/near-operation-file-preset.mdx @@ -1,10 +1,16 @@ --- -id: near-operation-file +title: near-operation-file-preset --- -This preset generates a file per each operation file. +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('near-operation-file-preset') -{@apiDocs} + + +This preset generates a file per each operation file. ## Example @@ -39,4 +45,8 @@ The second output refers to the base directory of the project (`./src/`) and it The `presetConfig` section contains a key for setting the output files extension (in our case, `.generated.tsx` because of `react-apollo`), and the location of the base schema types file we created in the first section of this file (it will look for it in the base directory). -> Note: If you're loading your `documents` from files with the same extension as the generated files, make sure the glob you use excludes the generated files. For example, if your original glob was `src/**/*.{ts,tsx}`, use `src/**/!(*.generated).{ts,tsx}` instead. + +Note: If you're loading your `documents` from files with the same extension as the generated files, make sure the glob you use excludes the generated files. For example, if your original glob was `src/**/*.{ts,tsx}`, use `src/**/!(*.generated).{ts,tsx}` instead. + + + diff --git a/website/src/pages/plugins/typescript/meta.json b/website/src/pages/plugins/typescript/meta.json new file mode 100644 index 00000000000..9271cb1f2f3 --- /dev/null +++ b/website/src/pages/plugins/typescript/meta.json @@ -0,0 +1,29 @@ +{ + "named-operations-object": "named-operations-object", + "relay-operation-optimizer": "relay-operation-optimizer", + "typed-document-node": "typed-document-node", + "typescript": "typescript", + "typescript-apollo-angular": "apollo-angular", + "typescript-apollo-client-helpers": "apollo-client-helpers", + "typescript-apollo-next": "apollo-next", + "typescript-document-nodes": "document-nodes", + "typescript-generic-sdk": "generic-sdk", + "typescript-graphql-files-modules": "graphql-files-modules", + "typescript-graphql-request": "graphql-request", + "typescript-mongodb": "mongodb", + "typescript-msw": "msw", + "typescript-oclif": "oclif", + "typescript-operations": "operations", + "typescript-react-apollo": "react-apollo", + "typescript-react-query": "react-query", + "typescript-resolvers": "resolvers", + "typescript-rtk-query": "rtk-query", + "typescript-stencil-apollo": "stencil-apollo", + "typescript-svelte-apollo": "svelte-apollo", + "typescript-type-graphql": "type-graphql", + "typescript-urql": "urql", + "typescript-validation-schema": "validation-schema", + "typescript-vue-apollo": "vue-apollo", + "typescript-vue-apollo-smart-ops": "vue-apollo-smart-ops", + "typescript-vue-urql": "vue-urql" +} diff --git a/website/docs-templates/named-operations-object.md b/website/src/pages/plugins/typescript/named-operations-object.mdx similarity index 85% rename from website/docs-templates/named-operations-object.md rename to website/src/pages/plugins/typescript/named-operations-object.mdx index c4bbdd95cb4..bc43535446b 100644 --- a/website/docs-templates/named-operations-object.md +++ b/website/src/pages/plugins/typescript/named-operations-object.mdx @@ -1,7 +1,14 @@ --- -id: named-operations-object +title: named-operations-object --- +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('named-operations-object') + + + This plugin generates an object containing a list of all your GraphQL operations and fragments. This is useful if you are using Apollo-Client and wish to have type validation when you are using `refetchQueries`. All operations and fragments are being exported by their name (so unnamed operations are being ignored), in the following structure: @@ -15,11 +22,11 @@ export const namedOperations = { } ``` -{@apiDocs} + ## How to use? -Include the plugin within your output (into an existing JS/TS file, or a new file), for example: +Include the plugin within your output (into an existing `.js`/`.ts` file, or a new file), for example: ```yaml schema: YOUR_SCHEMA diff --git a/website/docs-templates/relay-operation-optimizer.md b/website/src/pages/plugins/typescript/relay-operation-optimizer.mdx similarity index 67% rename from website/docs-templates/relay-operation-optimizer.md rename to website/src/pages/plugins/typescript/relay-operation-optimizer.mdx index 016179d6ed4..dd20284c7dc 100644 --- a/website/docs-templates/relay-operation-optimizer.md +++ b/website/src/pages/plugins/typescript/relay-operation-optimizer.mdx @@ -1,10 +1,18 @@ --- -id: relay-operation-optimizer +title: relay-operation-optimizer --- -_Built and maintained by [n1ru4l](https://github.com/n1ru4l)_ +import Callout from 'nextra-theme-docs/callout' +import { PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' -A GraphQL Codegen feature for bringing the benefits of Relay Compiler to any GraphQL Client using [Relay Operation Optimizer](https://graphql-tools.com/docs/relay-operation-optimizer) +export const getStaticProps = getNpmInfo('relay-operation-optimizer') + + + +_Built and maintained by [n1ru4l](https://github.com/n1ru4l)_. + +A GraphQL Codegen feature for bringing the benefits of Relay Compiler to any GraphQL Client using [Relay Operation Optimizer](https://graphql-tools.com/docs/relay-operation-optimizer). You can test how relay-compiler affects your queries over on the [Relay Compiler REPL](https://relay-compiler-repl.netlify.com). @@ -20,9 +28,9 @@ You can test how relay-compiler affects your queries over on the [Relay Compiler ## Usage -Set up your project per the GraphQL Codegen Docs, and add `flattenGeneratedTypes: true` in your codegen.yml: +Set up your project per the GraphQL Codegen Docs, and add `flattenGeneratedTypes: true{:yaml}` in your `codegen.yml`: -```yaml +```yaml {8} overwrite: true schema: schema.graphql generates: @@ -39,4 +47,7 @@ generates: Please notice that you have to skip the document validation - but no worries, relay-compiler will validate your documents instead! -> [See Laurin Quast's blog post to learn how to use those directives in your operations](https://the-guild.dev/blog/graphql-codegen-relay-compiler) + + [See Laurin Quast's blog post to learn how to use those directives in your + operations](https://the-guild.dev/blog/graphql-codegen-relay-compiler) + diff --git a/website/docs-templates/typed-document-node.md b/website/src/pages/plugins/typescript/typed-document-node.mdx similarity index 75% rename from website/docs-templates/typed-document-node.md rename to website/src/pages/plugins/typescript/typed-document-node.mdx index 55cec9db2b2..de6f0af2791 100644 --- a/website/docs-templates/typed-document-node.md +++ b/website/src/pages/plugins/typescript/typed-document-node.mdx @@ -1,8 +1,14 @@ --- -id: typed-document-node +title: typed-document-node --- -{@operationsNote} +import Callout from 'nextra-theme-docs/callout' +import { PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('typed-document-node') + + These plugins generate a ready-to-use `TypedDocumentNode` (a combination of pre-compiled `DocumentNode` and the TypeScript signature it represents). @@ -10,17 +16,18 @@ With the `typed-document-node` plugin you no longer need to reconfigure, and ins This plugin also generates less boilerplate code for your GraphQL operations. -> Watch [Episode #41 of `graphql.wtf`](https://graphql.wtf/episodes/41-typed-document-node) for a quick introduction to using this plugin with GraphQL Code Generator: + + Watch [Episode #41 of `graphql.wtf`](https://graphql.wtf/episodes/41-typed-document-node) for a quick introduction to + using this plugin with GraphQL Code Generator: + +/> ### Usage example @@ -67,6 +74,6 @@ export const ratesQuery: TypedDocumentNode = { } ``` -> This plugin also requires `typescript` and `typescript-operations`. +This plugin also requires `typescript` and `typescript-operations`. For information about the setup and usage of `TypedDocumentNode`, [please refer to the library's documentation](https://github.com/dotansimha/graphql-typed-document-node). diff --git a/website/docs-templates/typescript-apollo-angular.md b/website/src/pages/plugins/typescript/typescript-apollo-angular.mdx similarity index 62% rename from website/docs-templates/typescript-apollo-angular.md rename to website/src/pages/plugins/typescript/typescript-apollo-angular.mdx index 9b9840355c9..bba558425d6 100644 --- a/website/docs-templates/typescript-apollo-angular.md +++ b/website/src/pages/plugins/typescript/typescript-apollo-angular.mdx @@ -1,10 +1,15 @@ --- -id: typescript-apollo-angular +title: typescript-apollo-angular --- -{@operationsNote} +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' -{@apiDocs} +export const getStaticProps = getNpmInfo('typescript-apollo-angular') + + + ## How to use? @@ -22,7 +27,7 @@ query MyFeed { Using `graphql-codegen` you can generate a file with Angular services that you can use when coding an Angular component: ```yaml -# ... +# … generates: path/to/output.ts: plugins: @@ -35,7 +40,7 @@ Then, use it: ```ts import { MyFeedGQL, MyFeedQuery } from './graphql' -//BE SURE TO USE Observable from rxjs and not from @apollo/client/core when using map +// BE SURE TO USE Observable from rxjs and not from @apollo/client/core when using map import { Observable } from 'rxjs' import { map } from 'rxjs/operators' @@ -59,9 +64,9 @@ export class FeedComponent { #### `@NgModule` directive -All generated services are defined with `@Injectable({ providedIn: 'root' })` and in most cases you don't need to overwrite it, because providing a service to the root injector is highly recommended. To customize that behavior you can use `@NgModule` directive, anywhere in an operation, to let the codegen know which injector should it use to create a service. +All generated services are defined with `@Injectable({ providedIn: 'root' }){:ts}` and in most cases you don't need to overwrite it, because providing a service to the root injector is highly recommended. To customize that behavior you can use `@NgModule` directive, anywhere in an operation, to let the codegen know which injector should it use to create a service. -> You can't use multiple `@NgModule` directives in the same operation +You can't use multiple `@NgModule` directives in the same operation ```graphql query feed { @@ -76,7 +81,7 @@ query feed { Sometimes you end up with multiple Apollo clients, which means part of operations can't use the defaults. In order to customize that behavior you simply attach the `@namedClient` directive and the `typescript-apollo-angular` plugin takes care of the rest. -> You can't use multiple `@namedClient` directives in the same operation +You can't use multiple `@namedClient` directives in the same operation ```graphql query feed { diff --git a/website/docs-templates/typescript-apollo-client-helpers.md b/website/src/pages/plugins/typescript/typescript-apollo-client-helpers.mdx similarity index 62% rename from website/docs-templates/typescript-apollo-client-helpers.md rename to website/src/pages/plugins/typescript/typescript-apollo-client-helpers.mdx index eb656bac110..49c15000fbb 100644 --- a/website/docs-templates/typescript-apollo-client-helpers.md +++ b/website/src/pages/plugins/typescript/typescript-apollo-client-helpers.mdx @@ -1,20 +1,31 @@ --- -id: typescript-apollo-client-helpers +title: typescript-apollo-client-helpers --- +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('typescript-apollo-client-helpers') + + + This plugin generates helpers for improving the integration of TypeScript and Apollo-Client, based on your schema. -> Note: this plugin generates code that intended for `apollo-client` @ `> v3` only. +Note: this plugin generates code that intended for `apollo-client` @ `> v3` only. This plugin generates fully-typed `keyFields` and Type-Policies for Apollo-Client. -> [You can read more about type-policies in Apollo Cache here](https://apollographql.com/docs/react/caching/cache-configuration/#typepolicy-fields) + + [You can read more about type-policies in Apollo Cache + here](https://apollographql.com/docs/react/caching/cache-configuration/#typepolicy-fields) + ### How to use? Start by adding this plugin to your configuration: -```yaml +```yaml {5} schema: my-schema.graphql generates: apollo-helpers.ts: @@ -24,7 +35,7 @@ generates: Then, use the generated TypeScript `type` as your signature for `typePolicies`: -```ts +```ts /StrictTypedTypePolicies/2 import { StrictTypedTypePolicies } from './apollo-helpers' const typePolicies: StrictTypedTypePolicies = { @@ -48,4 +59,4 @@ const typePolicies: StrictTypedTypePolicies = { const cache = new InMemoryCache({ typePolicies }) ``` -{@apiDocs} + diff --git a/website/docs-templates/typescript-apollo-next.md b/website/src/pages/plugins/typescript/typescript-apollo-next.mdx similarity index 90% rename from website/docs-templates/typescript-apollo-next.md rename to website/src/pages/plugins/typescript/typescript-apollo-next.mdx index 035c2e26cd4..d3faad6504a 100644 --- a/website/docs-templates/typescript-apollo-next.md +++ b/website/src/pages/plugins/typescript/typescript-apollo-next.mdx @@ -1,8 +1,13 @@ --- -id: typescript-apollo-next +title: typescript-apollo-next --- -{@operationsNote} +import { PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('typescript-apollo-next') + + This plugin generates: @@ -14,7 +19,7 @@ It extends the basic TypeScript plugins: `@graphql-codegen/typescript`, `@graphq ## Motivations -Nextjs recently introduced `getServerSideProps` and `getStaticProps` which doesn't allow to use the HOC pattern adopted by the official apollo graphql plugin (based on `getInitialProps`). At the same time the SSR method offered by apollo client (`getDataFromTree`) enforces the React app to render multiple times in order to collect and fetch all the relevant queries. +Next.js recently introduced `getServerSideProps` and `getStaticProps` which doesn't allow to use the HOC pattern adopted by the official apollo graphql plugin (based on `getInitialProps`). At the same time the SSR method offered by apollo client (`getDataFromTree`) enforces the React app to render multiple times in order to collect and fetch all the relevant queries. By declaring a top level query we can save rendering time and provide a simpler pattern which works with `getServerSideProps`. Note that this pattern requires each SSR query to run at top level. [Example](https://github.com/correttojs/graphql-codegen-apollo-next-ssr/tree/master/example) ## API Reference @@ -56,7 +61,7 @@ Sets the version of react-apollo. #### Usage Examples -```yaml +```yaml {8} generates: path/to/file.ts: plugins: @@ -76,7 +81,7 @@ Customized the output by enabling/disabling the HOC. #### Usage Examples -```yaml +```yaml {8} generates: path/to/file.ts: plugins: @@ -96,7 +101,7 @@ Customized the output by enabling/disabling the generated React Hooks. #### Usage Examples -```yaml +```yaml {8} generates: path/to/file.ts: plugins: @@ -154,14 +159,14 @@ This is useful if you want to use modules other than `graphql-tag`, e.g. `graphq ##### graphql.macro -```yaml +```yaml {2} config: gqlImport: graphql.macro#gql ``` ##### Gatsby -```yaml +```yaml {2} config: gqlImport: gatsby#graphql ``` @@ -254,13 +259,13 @@ This config should be used if `documentMode` is `external`. This has 2 usage: #### Usage Examples -```yaml +```yaml {3} config: documentMode: external importDocumentNodeExternallyFrom: path/to/document-node-file ``` -```yaml +```yaml {3} config: documentMode: external importDocumentNodeExternallyFrom: near-operation-file @@ -274,7 +279,7 @@ Extends or overrides the built-in scalars and custom GraphQL scalars to a custom #### Usage Examples -```yaml +```yaml {2-4} config: scalars: DateTime: Date @@ -298,14 +303,14 @@ which is to preserve underscores. ##### Override All Names -```yaml +```yaml {2} config: namingConvention: change-case-all#lowerCase ``` ##### Upper-case enum values -```yaml +```yaml {4} config: namingConvention: typeNames: change-case-all#pascalCase @@ -314,14 +319,14 @@ config: ##### Keep names as is -```yaml +```yaml {2} config: namingConvention: keep ``` ##### Remove Underscores -```yaml +```yaml {4} config: namingConvention: typeNames: change-case-all#pascalCase @@ -337,7 +342,7 @@ Prefixes all the generated types. #### Usage Examples -```yaml +```yaml {2} config: typesPrefix: I ``` @@ -351,7 +356,7 @@ Does not add `__typename` to the generated types, unless it was specified in the #### Usage Examples -```yaml +```yaml {2} config: skipTypename: true ``` @@ -362,11 +367,11 @@ type: `boolean` default: `false` Automatically adds `__typename` field to the generated types, even when they are not specified -in the selection set, and makes it non-optional +in the selection set, and makes it non-optional. #### Usage Examples -```yaml +```yaml {2} config: nonOptionalTypename: true ``` diff --git a/website/docs-templates/typescript-document-nodes.md b/website/src/pages/plugins/typescript/typescript-document-nodes.mdx similarity index 62% rename from website/docs-templates/typescript-document-nodes.md rename to website/src/pages/plugins/typescript/typescript-document-nodes.mdx index 3369f030d60..68d0ab716c6 100644 --- a/website/docs-templates/typescript-document-nodes.md +++ b/website/src/pages/plugins/typescript/typescript-document-nodes.mdx @@ -1,8 +1,14 @@ --- -id: typescript-document-nodes +title: typescript-document-nodes --- -{@apiDocs} +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('typescript-document-nodes') + + + ## Usage diff --git a/website/src/pages/plugins/typescript/typescript-generic-sdk.mdx b/website/src/pages/plugins/typescript/typescript-generic-sdk.mdx new file mode 100644 index 00000000000..921c72b37c2 --- /dev/null +++ b/website/src/pages/plugins/typescript/typescript-generic-sdk.mdx @@ -0,0 +1,19 @@ +--- +title: typescript-generic-sdk +--- + +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('typescript-generic-sdk') + + + +Make sure you have `typescript` plugin and `typescript-operations` as well in your configuration: + + + +## Usage + +You can find a usage [example for Apollo-Client here](https://gist.github.com/akozhemiakin/731b0c1e99eb89b01f80f08f9146b6b6). diff --git a/website/docs-templates/typescript-graphql-files-modules.md b/website/src/pages/plugins/typescript/typescript-graphql-files-modules.mdx similarity index 71% rename from website/docs-templates/typescript-graphql-files-modules.md rename to website/src/pages/plugins/typescript/typescript-graphql-files-modules.mdx index 88dae102dce..ff5386571a3 100644 --- a/website/docs-templates/typescript-graphql-files-modules.md +++ b/website/src/pages/plugins/typescript/typescript-graphql-files-modules.mdx @@ -1,16 +1,27 @@ --- -id: typescript-graphql-files-modules +title: typescript-graphql-files-modules --- -:::note Webpack Integration +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('typescript-graphql-files-modules') + + + + +**Webpack Integration** + If you wish to have a simpler integration in a Webpack project, use [`graphql-let`](https://github.com/piglovesyou/graphql-let), it uses this plugin behind the scenes, and provides simpler developer experience. -::: + + ## Pre-Requirements To use this template, make sure you are using [`graphql-tag/loader`](https://github.com/apollographql/graphql-tag#webpack-preprocessing-with-graphql-tagloader) with Webpack. -{@apiDocs} + ## Example diff --git a/website/docs-templates/typescript-graphql-request.md b/website/src/pages/plugins/typescript/typescript-graphql-request.mdx similarity index 85% rename from website/docs-templates/typescript-graphql-request.md rename to website/src/pages/plugins/typescript/typescript-graphql-request.mdx index ca760f776c0..32694bfbcb4 100644 --- a/website/docs-templates/typescript-graphql-request.md +++ b/website/src/pages/plugins/typescript/typescript-graphql-request.mdx @@ -1,12 +1,18 @@ --- -id: typescript-graphql-request +title: typescript-graphql-request --- -{@operationsNote} +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' -> Make sure you have `typescript` plugin and `typescript-operations` as well in your configuration: +export const getStaticProps = getNpmInfo('typescript-graphql-request') -{@apiDocs} + + +Make sure you have `typescript` plugin and `typescript-operations` as well in your configuration: + + ## Usage Example diff --git a/website/docs-templates/typescript-mongodb.md b/website/src/pages/plugins/typescript/typescript-mongodb.mdx similarity index 91% rename from website/docs-templates/typescript-mongodb.md rename to website/src/pages/plugins/typescript/typescript-mongodb.mdx index 3541c9a4a15..9910755c908 100644 --- a/website/docs-templates/typescript-mongodb.md +++ b/website/src/pages/plugins/typescript/typescript-mongodb.mdx @@ -1,7 +1,19 @@ --- -id: typescript-mongodb +title: typescript-mongodb --- +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('typescript-mongodb') + + + + + Don't install this plugin as `devDependency`, because you need to import the directives from it. + + This plugin generates TypeScript types for MongoDB models, which makes it relevant for server-side development only. It uses GraphQL directives to declare the types you want to generate and use in your MongoDB backend. ### What this plugin does? @@ -30,15 +42,13 @@ export interface UserDbObject { This interface can be used for db read/write purposes, thus making communication with the db much more consistent. -> Don't install this plugin as devDependency, because you need to import the directives from it. - -{@apiDocs} + ## Usage Example Once installed, add the directives declaration to your GraphQL Schema definition: -```typescript +```ts import { makeExecutableSchema } from '@graphql-tools/schema' import { DIRECTIVES } from '@graphql-codegen/typescript-mongodb' @@ -94,7 +104,9 @@ Use this directive to declare a specific GraphQL field as part of your generated - `overrideType: String` - use this to override the type of the field; for example, if you store dates as `Date` but expose them as `String`. -> ⚠ If target property is an embedded entity, you should use `@embedded` instead. + + If target property is an embedded entity, you should use `@embedded` instead. + #### `@id` (on `FIELD_DEFINITION`) @@ -154,7 +166,7 @@ type TextNotification implements BaseNotification @entity { This way, you will get: -```typescript +```ts export interface BaseNotificationDbInterface { notificationType: string _id: ObjectId diff --git a/website/docs-templates/typescript-msw.md b/website/src/pages/plugins/typescript/typescript-msw.mdx similarity index 52% rename from website/docs-templates/typescript-msw.md rename to website/src/pages/plugins/typescript/typescript-msw.mdx index 00ca30bbd85..7039828e399 100644 --- a/website/docs-templates/typescript-msw.md +++ b/website/src/pages/plugins/typescript/typescript-msw.mdx @@ -1,12 +1,18 @@ --- -id: typescript-msw +title: typescript-msw --- -{@operationsNote} +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' -> Make sure you have `typescript` plugin and `typescript-operations` as well in your configuration: +export const getStaticProps = getNpmInfo('typescript-msw') -{@apiDocs} + + +Make sure you have `typescript` plugin and `typescript-operations` as well in your configuration: + + ### Usage @@ -32,7 +38,7 @@ const worker = setupWorker( return res( ctx.data({ - getUser: { name: 'John Doe', id: id } + getUser: { name: 'John Doe', id } }) ) }) diff --git a/website/docs-templates/typescript-oclif.md b/website/src/pages/plugins/typescript/typescript-oclif.mdx similarity index 94% rename from website/docs-templates/typescript-oclif.md rename to website/src/pages/plugins/typescript/typescript-oclif.mdx index 4cfd6fb73f2..71b1dd9726b 100644 --- a/website/docs-templates/typescript-oclif.md +++ b/website/src/pages/plugins/typescript/typescript-oclif.mdx @@ -1,12 +1,18 @@ --- -id: typescript-oclif +title: typescript-oclif --- -This plugin generates [`oclif`](https://npmjs.com/package/oclif) CLI commands. +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('typescript-oclif') + + + -{@operationsNote} +This plugin generates [`oclif`](https://npmjs.com/package/oclif) CLI commands. -The, make sure you have `typescript` plugin as well in your configuration: +Then, make sure you have `typescript` plugin as well in your configuration: ```yaml schema: http://localhost:4000 @@ -81,9 +87,7 @@ by the codegen. To get started quickly and easily, consider using the simple `graphql-request` as your handler: -```ts -// handler.ts - +```ts filename="handler.ts" import { GraphQLClient } from 'graphql-request' import { Command } from '@oclif/command' @@ -149,7 +153,7 @@ necessary `oclif` command files. With that complete, follow the directions in th You can add descriptions and examples for your commands via `typescript-oclif` with the `@oclif` client-side directive, like so: -```gql +```graphql mutation CreateAuthor($name: String!) @oclif( description: "Create a new author" diff --git a/website/src/pages/plugins/typescript/typescript-operations.mdx b/website/src/pages/plugins/typescript/typescript-operations.mdx new file mode 100644 index 00000000000..5e729f9ec13 --- /dev/null +++ b/website/src/pages/plugins/typescript/typescript-operations.mdx @@ -0,0 +1,11 @@ +--- +title: typescript-operations +--- + +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' + +export const getStaticProps = getNpmInfo('typescript-operations') + + + diff --git a/website/docs-templates/typescript-react-apollo.md b/website/src/pages/plugins/typescript/typescript-react-apollo.mdx similarity index 68% rename from website/docs-templates/typescript-react-apollo.md rename to website/src/pages/plugins/typescript/typescript-react-apollo.mdx index 1bdd7d25780..b914141d6af 100644 --- a/website/docs-templates/typescript-react-apollo.md +++ b/website/src/pages/plugins/typescript/typescript-react-apollo.mdx @@ -1,10 +1,15 @@ --- -id: typescript-react-apollo +title: typescript-react-apollo --- -{@operationsNote} +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' -{@apiDocs} +export const getStaticProps = getNpmInfo('typescript-react-apollo') + + + ## Usage Example @@ -51,7 +56,7 @@ import { useTest } from './generated-types' export const MyComponent: React.FC = () => { const { data, error, loading } = useTest() - return
        ...
        + return
        } ``` @@ -73,14 +78,15 @@ config: withHOC: true ``` -> Watch [Episode #29 of `graphql.wtf`](https://graphql.wtf/episodes/29-apollo-client-3-with-graphql-code-generator) for a quick introduction to using this plugin with GraphQL Code Generator: + + Watch [Episode #29 of `graphql.wtf`](https://graphql.wtf/episodes/29-apollo-client-3-with-graphql-code-generator) for + a quick introduction to using this plugin with GraphQL Code Generator: + +/> diff --git a/website/docs-templates/typescript-react-query.md b/website/src/pages/plugins/typescript/typescript-react-query.mdx similarity index 88% rename from website/docs-templates/typescript-react-query.md rename to website/src/pages/plugins/typescript/typescript-react-query.mdx index 32f83201e15..e2ab6d502da 100644 --- a/website/docs-templates/typescript-react-query.md +++ b/website/src/pages/plugins/typescript/typescript-react-query.mdx @@ -1,14 +1,22 @@ --- -id: typescript-react-query +title: typescript-react-query --- -{@operationsNote} +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' -{@apiDocs} +export const getStaticProps = getNpmInfo('typescript-react-query') + + + ## Usage Examples -> Note: all generated hooks are just wrappers around `react-query` original functions. This codegen plugin just burns the generated TypeScript types into the operation, and provides flexibility to choose your `fetcher`. + + Note: all generated hooks are just wrappers around `react-query` original functions. This codegen plugin just burns + the generated TypeScript types into the operation, and provides flexibility to choose your `fetcher`. + ### Using default `fetch` @@ -160,7 +168,7 @@ generates: As a shortcut, the `fetcher` property may also directly contain the function as a mapper string: ```yaml -#... +# … config: fetcher: './my-file#myFetcher' # isReactHook is false here (the default version) ``` @@ -199,7 +207,7 @@ export const fetchData = ( method: 'POST', headers: { 'Content-Type': 'application/json', - ...(options ?? {}) + ...options }, body: JSON.stringify({ query, @@ -210,8 +218,8 @@ export const fetchData = ( const json = await res.json() if (json.errors) { - const { message } = json.errors[0] || 'Error..' - throw new Error(message) + const { message } = json.errors[0] || {} + throw new Error(message || 'Error…') } return json.data @@ -235,7 +243,7 @@ export const useFetchData = ( headers: { 'Content-Type': 'application/json', ...headers, - ...(options ?? {}) + ...options }, body: JSON.stringify({ query, @@ -246,8 +254,8 @@ export const useFetchData = ( const json = await res.json() if (json.errors) { - const { message } = json.errors[0] || 'Error..' - throw new Error(message) + const { message } = json.errors[0] || {} + throw new Error(message || 'Error…') } return json.data @@ -255,7 +263,9 @@ export const useFetchData = ( } ``` -> Note: The return value is an async function, with no params, that returns a `Promise` with the actual data. + + Note: The return value is an async function, with no params, that returns a `Promise` with the actual data. + ### Using Infinite Query @@ -265,15 +275,15 @@ To use this you need to return an object of new queries, and it blends them in t #### Usage example (`addInfiniteQuery: true`) -with the following query +with the following query: ```graphql query AnimalsQuery($catsRange: Int, $catsStarting: Int, $dogsRange: Int, $dogsStarting: Int) { cats(range: $catsRange, starting: $catsStarting) { - # ... + # … } dogs(range: $dogsRange, starting: $dogsStarting) { - # ... + # … } } ``` diff --git a/website/docs-templates/typescript-resolvers.md b/website/src/pages/plugins/typescript/typescript-resolvers.mdx similarity index 76% rename from website/docs-templates/typescript-resolvers.md rename to website/src/pages/plugins/typescript/typescript-resolvers.mdx index 03531bcdc12..513a11f4d49 100644 --- a/website/docs-templates/typescript-resolvers.md +++ b/website/src/pages/plugins/typescript/typescript-resolvers.mdx @@ -1,20 +1,43 @@ --- -id: typescript-resolvers +title: typescript-resolvers --- -> Watch [Episode #26 of `graphql.wtf`](https://graphql.wtf/episodes/26-type-safe-resolvers-with-graphql-code-generator) for a quick introduction to this plugin and its features: +import Callout from 'nextra-theme-docs/callout' +import { PackageApiDocs, PackageHeader } from '@/components' +import { getNpmInfo } from '@/lib/get-npm-info' - +export const getStaticProps = getNpmInfo('typescript-resolvers') -> [More weekly episodes are available in `graphql.wtf`](https://graphql.wtf/) by [Jamie Barton](https://twitter.com/notrab). + -{@apiDocs} + + Watch [Episode #26 of `graphql.wtf`](https://graphql.wtf/episodes/26-type-safe-resolvers-with-graphql-code-generator) + for a quick introduction to this plugin and its features: + + +