diff --git a/.github/ISSUE_TEMPLATE/adding-your-tooling.yml b/.github/ISSUE_TEMPLATE/adding-your-tooling.yml new file mode 100644 index 000000000..ae5312003 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/adding-your-tooling.yml @@ -0,0 +1,175 @@ +name: Add or Modify JSON Schema Tool +description: Submit your tool to be added or updated in the JSON Schema ecosystem. +title: "Add or Modify [Tool Name] in JSON Schema Ecosystem" +labels: ["Status: Triage"] +body: + - type: input + id: name + attributes: + label: "Tool Name" + description: "Please provide the name of your tool." + placeholder: "Enter the tool name" + validations: + required: true + + - type: textarea + id: description + attributes: + label: "Tool Description" + description: "Provide a brief description of your tool." + placeholder: "Enter a brief description of the tool" + validations: + required: true + + - type: checkboxes + id: actionType + attributes: + label: "Action Type" + description: "Select whether you want to add a new tool or modify an existing one." + options: + - label: "Add Tool" + - label: "Modify Tool" + validations: + required: true + + - type: checkboxes + id: toolingTypes + attributes: + label: "Tooling Types" + description: "Select the categories of tooling that best describe your project." + options: + - label: "validator" + - label: "hyper-schema" + - label: "benchmarks" + - label: "documentation" + - label: "LDO-utility" + - label: "code-to-schema" + - label: "data-to-schema" + - label: "model-to-schema" + - label: "schema-to-types" + - label: "schema-to-code" + - label: "schema-to-web-UI" + - label: "schema-to-data" + - label: "util-general-processing" + - label: "util-schema-to-schema" + - label: "util-draft-migration" + - label: "util-format-conversion" + - label: "util-testing" + - label: "editor" + - label: "editor-plugins" + - label: "schema-repository" + - label: "linter" + - label: "linter-plugins" + validations: + required: true + + - type: textarea + id: languages + attributes: + label: "Languages" + description: "List the languages your tool is built in or supports." + placeholder: "Enter the languages" + + - type: textarea + id: environments + attributes: + label: "Environments" + description: "List the platforms or environments in which your tool operates." + placeholder: "Enter the environments" + + - type: textarea + id: dependsOnValidators + attributes: + label: "Dependencies on Validators" + description: "If your tool depends on other validators, please provide their URLs." + placeholder: "Enter URLs of dependent validators" + + - type: textarea + id: creators + attributes: + label: "Creators" + description: "Provide information about the creators or authors of the project." + placeholder: "Provide information about the creators or authors of the project. Include their username and platform." + + - type: textarea + id: maintainers + attributes: + label: "Maintainers" + description: "Provide information about the maintainers or authors of the project." + placeholder: "Provide information about the maintainers or authors of the project. Include their username and platform." + + - type: input + id: license + attributes: + label: "License" + description: "Specify the license under which your project is distributed." + placeholder: "Enter the license" + validations: + required: true + + - type: input + id: source + attributes: + label: "Source Repository URL" + description: "Provide the URL of your project's repository." + placeholder: "Enter the source URL" + validations: + required: true + + - type: input + id: homepage + attributes: + label: "Homepage URL" + description: "Provide the URL of your project's homepage." + placeholder: "Enter the homepage URL" + + - type: checkboxes + id: supportedDialects + attributes: + label: "Supported Dialects" + description: "List the supported JSON Schema dialects. Use the draft version identifiers from the list below." + options: + - label: "1" + - label: "2" + - label: "3" + - label: "4" + - label: "5" + - label: "6" + - label: "7" + - label: "2019-09" + - label: "2020-12" + + - type: textarea + id: additionalDialects + attributes: + label: "Additional Dialects" + description: "If there are additional dialects supported, provide their name and source URL." + placeholder: "Enter the additional dialects." + + - type: input + id: bowtieIdentifier + attributes: + label: "Bowtie Compliance Testing" + description: "If your tool is tested by Bowtie, provide the Bowtie identifier." + placeholder: "Enter the Bowtie identifier" + + - type: textarea + id: toolingListingNotes + attributes: + label: "Tooling Listing Notes" + description: "Add any notes about the tooling which will appear in the tooling listing on the website." + placeholder: "Enter the tooling listing notes." + + - type: textarea + id: compliance + attributes: + label: "Compliance" + description: "Provide details on what must be done to make the implementation the most compliant that it can be." + placeholder: "Enter the compliance details." + + - type: textarea + id: landscape + attributes: + label: "Landscape Information" + description: "Provide additional information for the JSON Schema landscape diagram, such as your logo or a link to your logo. Indicate if you want to opt-out of the landscape." + placeholder: "Enter the landscape information and preferences." diff --git a/.github/workflows/new-implementation.yml b/.github/workflows/new-implementation.yml index a4dbe4303..67c817028 100644 --- a/.github/workflows/new-implementation.yml +++ b/.github/workflows/new-implementation.yml @@ -10,8 +10,7 @@ on: branches: - main paths: - - data/*.yml - - pages/implementations/main.md + - data/tooling-data.yaml jobs: comment: diff --git a/.github/workflows/trigger-update-landscape-tooling.yml b/.github/workflows/trigger-update-landscape-tooling.yml new file mode 100644 index 000000000..5b67adfec --- /dev/null +++ b/.github/workflows/trigger-update-landscape-tooling.yml @@ -0,0 +1,33 @@ +name: Trigger Update Landscape Tooling Workflow + +on: + push: + paths: + - data/tooling-data.yaml + branches: + - main + workflow_dispatch: + + +jobs: + trigger-workflow: + runs-on: ubuntu-latest + + steps: + - name: Create workflow token + id: app-token + uses: actions/create-github-app-token@v1 + with: + app-id: ${{ vars.APP_ID }} + private-key: ${{ secrets.PRIVATE_KEY }} + + - name: Trigger update landscape repository workflow + env: + AUTH_TOKEN: ${{ steps.app-token.output.token }} + run: | + curl -L \ + -X POST \ + -H "Accept: application/vnd.github.v3+json" \ + -H "Authorization: Bearer $AUTH_TOKEN" \ + https://api.github.com/repos/json-schema-org/landscape/actions/workflows/update-landscape-tooling.yml/dispatches \ + -d '{"ref":"main"}' diff --git a/.github/workflows/validate-tooling-data.yml b/.github/workflows/validate-tooling-data.yml new file mode 100644 index 000000000..5ec227928 --- /dev/null +++ b/.github/workflows/validate-tooling-data.yml @@ -0,0 +1,61 @@ +name: Validate Tooling Data + +on: + push: + paths: + - data/tooling-data.yaml + branches: + - main + pull_request: + paths: + - data/tooling-data.yaml + workflow_dispatch: + +jobs: + validate-tooling-data: + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Corepack enable + run: corepack enable + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install dependencies + run: yarn add ajv ajv-formats js-yaml + + - name: Validate tooling-data.yaml + run: | + node -e " + const Ajv = require('ajv/dist/2020'); + const addFormats = require('ajv-formats'); + const path = require('path'); + const fs = require('fs'); + const yaml = require('js-yaml'); + const dataDir = path.join(process.env.GITHUB_WORKSPACE, 'data'); + const schemaPath = path.join(dataDir, 'tooling-data.schema.json'); + const dataPath = path.join(dataDir, 'tooling-data.yaml'); + + try { + const schema = JSON.parse(fs.readFileSync(schemaPath, 'utf-8')); + const data = yaml.load(fs.readFileSync(dataPath, 'utf-8')); + const ajv = new Ajv({ allErrors: true }); + addFormats(ajv); + const validate = ajv.compile(schema); + const valid = validate(data); + if (!valid) { + console.error('Validation failed:', validate.errors); + process.exit(1); + } else { + console.log('tooling-data.yaml is valid.'); + } + } catch (error) { + console.error('Error validating tooling-data.yaml:', error); + process.exit(1); + }" diff --git a/components/Layout.tsx b/components/Layout.tsx index 6581ccca5..079e703a3 100644 --- a/components/Layout.tsx +++ b/components/Layout.tsx @@ -205,7 +205,7 @@ const MainNavigation = () => { @@ -294,11 +294,7 @@ const MobileNav = () => { isActive={section === 'docs'} /> - + + rule.test?.test?.('.svg'), + ); + + config.module.rules.push( + { + ...fileLoaderRule, + test: /\.svg$/i, + resourceQuery: /url/, // *.svg?url + }, + + { + test: /\.svg$/i, + issuer: fileLoaderRule.issuer, + resourceQuery: { not: [...fileLoaderRule.resourceQuery.not, /url/] }, + use: ['@svgr/webpack'], + }, + ); + + fileLoaderRule.exclude = /\.svg$/i; return config; }, }; -module.exports = nextConfig; \ No newline at end of file +module.exports = nextConfig; + diff --git a/package.json b/package.json index d610a9607..017f20d94 100644 --- a/package.json +++ b/package.json @@ -27,13 +27,16 @@ }, "dependencies": { "@docsearch/react": "3.6.1", + "@types/jsonpath": "^0.2.4", "axios": "1.7.4", "babel-loader": "^9.1.3", "classnames": "^2.5.1", "feed": "^4.2.2", "file-saver": "^2.0.5", + "fuse.js": "^7.0.0", "gray-matter": "^4.0.3", "js-yaml": "^4.1.0", + "jsonpath": "^1.1.1", "jszip": "^3.10.1", "markdown-to-jsx": "^7.4.7", "moment": "2.29.4", @@ -58,6 +61,7 @@ "@babel/preset-env": "^7.25.3", "@cypress/code-coverage": "^3.12.46", "@next/eslint-plugin-next": "^14.0.1", + "@svgr/webpack": "^8.1.0", "@types/babel__core": "^7", "@types/babel__preset-env": "^7", "@types/file-saver": "^2.0.7", @@ -80,7 +84,7 @@ "eslint-plugin-n": "^16.6.2", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^5.2.1", - "eslint-plugin-promise": "^7.1.0", + "eslint-plugin-promise": "^6.0.0", "eslint-plugin-react": "^7.35.0", "eslint-plugin-react-hooks": "^4.4.0", "husky": "^9.1.3", diff --git a/pages/blog/posts/and-then-there-were-three.md b/pages/blog/posts/and-then-there-were-three.md index 13d49236b..ffd1573d5 100644 --- a/pages/blog/posts/and-then-there-were-three.md +++ b/pages/blog/posts/and-then-there-were-three.md @@ -64,7 +64,7 @@ And now, I'm extremely excited to announce that I'm joining Postman Open Technol To start with the specification, the output format will continue to be a primary focus for me. Earlier this year, I opened a [discussion](https://github.com/orgs/json-schema-org/discussions/63) on potential improvements. I think that we're in a good place, and I need to start creating PRs that move the current language in the specification to the new design. -I'm not sure yet what implementor support will look like, but based on our [implementations page](https://json-schema.org/implementations.html), it seems that many of them haven't updated to supporting 2020-12 yet. Outreach is probably the best place to start here. We need to find out the status of each of these projects. Are they still maintained? Do they _intend_ to stay up-to-date with the specification? Do they need help? Answering these questions will be the first step. +I'm not sure yet what implementor support will look like, but based on our [implementations page](https://json-schema.org/tools), it seems that many of them haven't updated to supporting 2020-12 yet. Outreach is probably the best place to start here. We need to find out the status of each of these projects. Are they still maintained? Do they _intend_ to stay up-to-date with the specification? Do they need help? Answering these questions will be the first step. And finally adjacent tooling. I'm really excited about this part because it will highlight for me how JSON Schema is being used in the real world, thereby _validating_ (ha!) its usefulness. diff --git a/pages/blog/posts/applicability-json-schema-fundamentals-part-1.md b/pages/blog/posts/applicability-json-schema-fundamentals-part-1.md index ae67a586b..729ac9c2e 100644 --- a/pages/blog/posts/applicability-json-schema-fundamentals-part-1.md +++ b/pages/blog/posts/applicability-json-schema-fundamentals-part-1.md @@ -424,7 +424,7 @@ All feedback is welcome. If you have questions or comments, you can find me on t - [Weekly Office Hours (Tuesday, 15:00 UTC)](https://github.com/json-schema-org/community/discussions/34) - [Open Community Slack Server](/slack) - [Community GitHub Discussions](https://github.com/json-schema-org/community/discussions) -- [List of implementations](/implementations) +- [List of implementations](/tools) - [Human-friendly documentation for understanding JSON Schema](/understanding-json-schema) - [JSON Schema live playground (ajv) for draft-07 with shareable links](https://jsonschema.dev) - [JSON Schema live playground (hyperjump validator) for all drafts (from draft-04)](https://json-schema.hyperjump.io) diff --git a/pages/blog/posts/bowtie-intro.md b/pages/blog/posts/bowtie-intro.md index 00891023c..2455c727d 100644 --- a/pages/blog/posts/bowtie-intro.md +++ b/pages/blog/posts/bowtie-intro.md @@ -43,7 +43,7 @@ There's prior art in doing this sort of thing. The [JSONPath Comparison project](https://cburgmer.github.io/json-path-comparison/) does this extremely well for [JSONPath](https://github.com/ietf-wg-jsonpath/draft-ietf-jsonpath-base), and [Nicolas Seriot's "Parsing JSON is a Minefield"](https://seriot.ch/projects/parsing_json.html) is a fantastic example for JSON itself. Bowtie attempts to bring these ideas to JSON Schema. -From the existing [list of JSON Schema implementations](https://json-schema.org/implementations.html#validators), Bowtie already [supports](https://github.com/orgs/bowtie-json-schema/packages) *12* implementations across *9* programming languages, allowing anyone to run any of these implementations and see what they have to say about schemas and instances. +From the existing [list of JSON Schema implementations](https://json-schema.org/tools#validators), Bowtie already [supports](https://github.com/orgs/bowtie-json-schema/packages) *12* implementations across *9* programming languages, allowing anyone to run any of these implementations and see what they have to say about schemas and instances. It ships with a [command line program](https://docs.bowtie.report/en/stable/cli/) but perhaps more excitingly, ongoing automated runs of this CLI have been set up, such that Bowtie emits a [report across all of its supported implementations](https://bowtie.report). @@ -136,7 +136,7 @@ If you don't see activity on one, feel free to leave a comment if you begin to w #### I Want to Learn About a New Implementation or Programming Language This is possibly the most "fun" thing to work on, or at least I quite enjoyed doing it. -Pick an implementation Bowtie doesn't already support from the [list of implementations](https://json-schema.org/implementations.html#validators) and follow the [tutorial for writing a harness](https://bowtie-json-schema.readthedocs.io/en/latest/implementers/) which will guide you through what Bowtie expects from a harness. +Pick an implementation Bowtie doesn't already support from the [list of implementations](https://json-schema.org/tools#validators) and follow the [tutorial for writing a harness](https://bowtie-json-schema.readthedocs.io/en/latest/implementers/) which will guide you through what Bowtie expects from a harness. If there are gaps in the tutorial, do raise them or ping me! But this can be a nice way to play with a simple program in a language you haven't used before, as well as a way to learn a JSON Schema implementation which may have made different choices than one you're already familiar with. diff --git a/pages/blog/posts/get-started-with-json-schema-in-node-js.md b/pages/blog/posts/get-started-with-json-schema-in-node-js.md index f37f90cfa..1cc0cef11 100644 --- a/pages/blog/posts/get-started-with-json-schema-in-node-js.md +++ b/pages/blog/posts/get-started-with-json-schema-in-node-js.md @@ -167,7 +167,7 @@ We can use Ajv as a standalone library or we can integrate it with the framework When we combine JSON Schema and Ajv, we have a flexible solution for implementing validation in our Node.js applications: -- **Learn once, use everywhere.** The JSON Schema specification is cross-platform, and there are [validation libraries](/implementations) available for every popular programming language. We're not locked into a library, framework or language. Once we've learnt the fundamentals of JSON Schema, we can use it everywhere. +- **Learn once, use everywhere.** The JSON Schema specification is cross-platform, and there are [validation libraries](/tools) available for every popular programming language. We're not locked into a library, framework or language. Once we've learnt the fundamentals of JSON Schema, we can use it everywhere. - **Portability.** Because JSON Schema is cross-platform, even if we decide to rewrite our applications in another framework or language, we can take our schemas with us. - **Speed**. Under the hood, Ajv compiles our JSON schemas into JavaScript code. This improves the performance of repeated validation of data against a schema. For example, schemas can be compiled by Ajv when our Node.js application starts. HTTP request data which the application receives can then be validated against the pre-compiled schemas. - **Active and supportive community**. There's an active community of folks on Slack who are happy to help out (the [JSON Schema website](https://json-schema.org/) has a link you can use to join). diff --git a/pages/blog/posts/json-schema-in-5-minutes.md b/pages/blog/posts/json-schema-in-5-minutes.md index 28fe6fca3..1ce09f7fd 100644 --- a/pages/blog/posts/json-schema-in-5-minutes.md +++ b/pages/blog/posts/json-schema-in-5-minutes.md @@ -231,7 +231,7 @@ Here are some places you may find helpful moving forward: - [Weekly Office Hours (Tuesday, 15:00 UTC)](https://github.com/json-schema-org/community/discussions/34) - [Open Community Slack Server](/slack) - [Community GitHub Discussions](https://github.com/json-schema-org/community/discussions) -- [List of implementations](/implementations) +- [List of implementations](/tools) - [Human-friendly documentation for understanding JSON Schema](/understanding-json-schema) - [JSON Schema live playground (ajv) for draft-07 with shareable links](https://jsonschema.dev) - [JSON Schema live playground (hyperjump validator) for all drafts (from draft-04)](https://json-schema.hyperjump.io) diff --git a/pages/implementations/index.page.tsx b/pages/implementations/index.page.tsx deleted file mode 100644 index a89490fc4..000000000 --- a/pages/implementations/index.page.tsx +++ /dev/null @@ -1,228 +0,0 @@ -import React from 'react'; -import { getLayout } from '~/components/SiteLayout'; -import fs from 'fs'; -import matter from 'gray-matter'; -import StyledMarkdown from '~/components/StyledMarkdown'; -import yaml from 'js-yaml'; -import { Headline1, Headline2, Headline3 } from 'components/Headlines'; -import slugify from 'slugify'; -import { useRouter } from 'next/router'; -import classnames from 'classnames'; -import { SectionContext } from '~/context'; -import { DRAFT_ORDER } from '~/lib/config'; - -// @ts-ignore -import zeroFill from 'zero-fill'; - -export async function getStaticProps() { - const validators = yaml.load( - fs.readFileSync('data/validator-libraries-modern.yml', 'utf-8'), - ); - const hyperLibaries = yaml.load( - fs.readFileSync('data/hyper-libraries-modern.yml', 'utf-8'), - ); - - const intro = fs.readFileSync('pages/implementations/intro.md', 'utf-8'); - const main = fs.readFileSync('pages/implementations/main.md', 'utf-8'); - const { content: introContent } = matter(intro); - const { content: mainContent } = matter(main); - return { - props: { - blocks: { - intro: introContent, - main: mainContent, - }, - validators, - hyperLibaries, - }, - }; -} - -type ImplementationByLanguage = { name: string }; - -export default function ImplementationsPages({ - blocks, - validators, - hyperLibaries, -}: { - blocks: any; - validators: ImplementationByLanguage[]; - hyperLibaries: ImplementationByLanguage[]; -}) { - return ( - -
- Tools - - Validators - - - -
-
- ); -} -ImplementationsPages.getLayout = getLayout; - -function ImplementationTable({ - implementationsByLanguage, - prefix, -}: { - implementationsByLanguage: any; - prefix: string; -}) { - const router = useRouter(); - return ( - <> -
- {implementationsByLanguage.map( - (implementationByLanguage: any, index: number) => { - const slug = - prefix + - slugify(implementationByLanguage.name, { - lower: true, - trim: true, - }); - const isActive = router.query.language === slug; - return ( - - {implementationByLanguage.name} - - ); - }, - )} -
-
- - - - - - - - - - {implementationsByLanguage.map( - (implementationByLanguage: any, index: number) => { - const slug = - prefix + - slugify(implementationByLanguage.name, { - lower: true, - trim: true, - }); - const isActive = router.query.language === slug; - if (router.query.language && !isActive) return null; - - return ( - - - - - {implementationByLanguage.implementations.map( - (implementation: any, index: number) => { - let mixedNotes = ''; - if (implementation.notes) { - mixedNotes = implementation.notes; - } - if (implementation.compliance) { - if (implementation.notes) { - mixedNotes += '
Compliance:'; - } else { - mixedNotes = 'Compliance:'; - } - if (implementation.compliance.config.docs) { - mixedNotes += - ' This implementation documents that you must '; - } - if (implementation.compliance.config.instructions) { - mixedNotes += - '' + - implementation.compliance.config.instructions + - ' to produce specification-compliant behavior.'; - } - } - const allDrafts = [ - ...(implementation['date-draft'] || []), - ...(implementation['draft'] || []), - ]; - return ( - - - - - - - ); - }, - )} - - ); - }, - )} - -
- - About - - Drafts - - License -
- - {implementationByLanguage.name} - -
- - {implementation.name} - - - - - {allDrafts - ?.sort((a, b) => - DRAFT_ORDER.indexOf(a) < - DRAFT_ORDER.indexOf(b) - ? -1 - : 1, - ) - ?.map((draft: string | number) => ( - - {typeof draft === 'number' - ? zeroFill(2, draft) - : draft} - - ))} - - {implementation.license} -
-
- - ); -} diff --git a/pages/implementations/intro.md b/pages/implementations/intro.md deleted file mode 100644 index cbcb79c4c..000000000 --- a/pages/implementations/intro.md +++ /dev/null @@ -1,11 +0,0 @@ -_**NOTE:** This page lists implementations with (or actively working towards) support for draft-06 or later._ - -_For implementations supporting only draft-04 or older, or that are no longer in development, see the [Obsolete Implementations](obsolete-implementations) page._ - -Implementations below are written in different languages, and support part, or all, of at least one recent version of the specification. - -Implementations are classified based on their functionality. When known, the license of the project is also mentioned. - -If you have updates to this list, make a pull request on the [GitHub repo](https://github.com/json-schema-org/website). - -Listing does not signify a recommendation or endorsement of any kind. diff --git a/pages/implementations/main.md b/pages/implementations/main.md deleted file mode 100644 index 142aed4b5..000000000 --- a/pages/implementations/main.md +++ /dev/null @@ -1,266 +0,0 @@ - -### Benchmarks - -Benchmarks that compare at least two implementations supporting draft-06+ may be listed here. - -- JavaScript - - [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) - an independent benchmark for Node.js JSON-schema validators based on JSON-Schema Test Suite (MIT) - -- PHP - - [php-json-schema-bench](https://github.com/swaggest/php-json-schema-bench) - comparative benchmark for JSON-schema PHP validators using JSON-Schema Test Suite and z-schema/JSCK (MIT) - -- JVM (Java, Kotlin, Scala) - - [json-schema-validation-comparison](https://www.creekservice.org/json-schema-validation-comparison/) - an independent functional and performance comparison of JVM-based validator implementations using JSON-Schema Test Suite and more (MIT) - -### API documentation - -- JavaScript - - [@cloudflare/doca](https://github.com/cloudflare/json-schema-tools/tree/master/workspaces/doca) ([JSON Schema Tools](https://github.com/cloudflare/json-schema-tools)), _draft-04, -06, -07, and Doca extensions_ (UI forthcoming) - - [@adobe/jsonschema2md](https://github.com/adobe/jsonschema2md) makes it easier by providing a number of scripts that can turn JSON Schema files into readable Markdown documentation that is ready for consumption on GitHub or processed using Jekyll or other static site generators. _JSON Schema 2019-09_ ([partial](https://github.com/adobe/jsonschema2md/blob/master/schemasupport.md)) - -- Python - - [FastAPI](https://github.com/tiangolo/fastapi) (MIT) is an API framework based on Python 3.6+ types that generates [OpenAPI 3](https://www.openapis.org) schemas, including **JSON Schemas** for all the models declared. - -### Link Description Object utilities - -- JavaScript - - [@cloudflare/json-hyper-schema](https://github.com/cloudflare/json-schema-tools/tree/master/workspaces/json-hyper-schema) _draft-07, -06, -04_ (BSD-3-Clause) - - -## Schema generators - -Schema generators need not support generating every schema keyword. -For schema generators, compatibility with a draft means that either: - -* Schemas produced explicitly set the draft with `$schema` -* Schemas produced lack `$schema` but are valid against the appropriate meta-schema - -For example, the only incompatibilities between draft-04 and draft-06 involve `exclusiveMinimum`, `exclusiveMaximum`, and `id` vs `$id`. If a generator does not set `$schema` and does not ever emit those keywords, then it is compatible with draft-06 even if it was written with draft-04 in mind. - -### From code - -- .NET - - [Json.NET](https://www.newtonsoft.com/jsonschema) (AGPL-3.0) - generates schemas from .NET types - - [NJsonSchema](https://github.com/RSuter/NJsonSchema/) - (Ms-PL) - generates schemas from .NET types, see issue [574](https://github.com/RSuter/NJsonSchema/issues/574) for draft-06+ support progress - - [JsonSchema.Net.Generation](https://github.com/gregsdennis/json-everything) (MIT) - generates schemas from .NET types - - [LateApexEarlySpeed.Json.Schema](https://github.com/lateapexearlyspeed/Lateapexearlyspeed.JsonSchema) (BSD-3-Clause) - generates schemas (draft 2020.12) from fluent builders & .NET types -- Go - - [jsonschema](https://github.com/invopop/jsonschema) - (MIT) - generate schemas from Go structs. Supports Draft 2020-12. -- PHP - - [Liform](https://github.com/Limenius/liform) (MIT) - generates schemas from Symfony forms -- TypeScript - - [typescript-json-schema](https://github.com/YousefED/typescript-json-schema) -- Python - - [Pydantic](https://pydantic-docs.helpmanual.io/) (MIT) - generates schemas from Python models based on Python 3.6+ type hints. - - [msgspec](https://jcristharif.com/msgspec/) (BSD-3-Clause) - generates schemas from Python type annotations. - - [mashumaro](https://github.com/Fatal1ty/mashumaro) (Apache 2.0) - generates schemas from Python type annotations - - [drf-jsonschema-serializer](https://github.com/maykinmedia/drf-jsonschema-serializer) (BSD-3-Clause) - generates schemas from Django Rest Framework serializers -- Java - - [jsonschema-generator](https://github.com/victools/jsonschema-generator) (Apache 2.0) - generates schemas from Java types *supports Drafts 6, 7, 2019-09 and 2020-12* -- Scala - - [scala-jsonschema](https://github.com/andyglow/scala-jsonschema) (Apache 2.0) - generates schemad out of Scala case classes -- Ruby - - [Shale](https://github.com/kgiszczak/shale) (MIT) - generates schema from Ruby models *supports Draft 2020-12* -- Rust - - [Schemars](https://github.com/GREsau/schemars) (MIT) - generates schema from Rust code *supports Draft 7* - -### From data - -- Java - - [saasquatch/json-schema-inferrer](https://github.com/saasquatch/json-schema-inferrer) _2020-12, 2019-09, draft-07, draft-06, draft-04_ (Apache 2.0) - Java library for inferring JSON Schemas from one or multiple JSON samples. -- Scala - - [Schema Guru](https://github.com/snowplow/schema-guru) (Apache 2.0) - CLI util, Spark Job and Web UI for deriving JSON Schemas out of corpus of JSON instances; see issue [178](https://github.com/snowplow/schema-guru/issues/178) for progress towards draft-06+ support - - [JSONoid](https://github.com/michaelmior/jsonoid-discovery/) (MIT) - command line tool and Spark application for inferring schemas from JSON documents, supports draft 2020-12 -- Clojure - - [luposlip/json-schema](https://github.com/luposlip/json-schema) (Apache 2.0) - infer JSON Schema from Clojure data -- Online (web tool) - - [jsonschema.net](https://www.jsonschema.net/) - generates schemas from example data - - [Liquid Online Tools](https://www.liquid-technologies.com/online-json-to-schema-converter) - infer JSON Schema from sample JSON data - - [quicktype.io](https://app.quicktype.io/#l=schema) - infer JSON Schema from samples, and generate TypeScript, C++, go, Java, C#, Swift, etc. types from JSON Schema -- Helm - - [dadav/helm-schema](https://github.com/dadav/helm-schema) (MIT) - generate _values.schema.json_ from Helm _values.yaml_; compatible with [helm-docs](https://github.com/norwoodj/helm-docs) comments - -### From model - -- [Dataspecer](https://dataspecer.com) - Generates JSON Schema (and JSON-LD context) from conceptual model *supports Draft 2020-12* - -## Generators from schemas - -Tools that generate artifacts from schemas need not support every keyword, -as not all keywords work well for generative use cases. - -Generators are considered compatible with a draft if they support (or benignly -ignore) the appropriate `$schema` value, and interpret the keywords that they -do support according to that draft. - -For example, if a generator that was originally written for draft-04 does not -support `id`, `exclusiveMinimum`, or `exclusiveMaximum`, then as long as it does -not require a draft-04 `$schema`, it is compatible with draft-06 since those -are the only keywords that changed. - -### Type generation - -- TypeScript - - [json-schema-to-ts](https://github.com/ThomasAribart/json-schema-to-ts) (MIT) - generates TypeScript types from JSON schemas - - [json-schema-to-typescript](https://github.com/bcherny/json-schema-to-typescript) (MIT) - JSON Schema to TypeScript type generator used by Amazon, Microsoft, Mozilla, Webpack, and others - -### Code generation - -- Dotnet - - [Corvus.JsonSchema](https://www.nuget.org/packages/Corvus.Json.JsonSchema.TypeGeneratorTool/) - generates an idiomatic dotnet type model from JSON Schema files, supporting all JSON Schema features, including property accessors, enumeration, common string `format`, and JSON document building/modification; over low-level `System.Text.Json` types. *supports Draft 6, Draft 7, Draft 2019-09 and Draft 2020-12*. -- Elm - - [json-schema-to-elm](https://github.com/dragonwasrobot/json-schema-to-elm) - generates Elm types, JSON decoders+encoders, and fuzz tests from one or more JSON Schema files, using [dragonwasrobot/json_schema](https://github.com/dragonwasrobot/json_schema) *supports Draft 7* -- Go - - [go-jsonschema](https://git.sr.ht/~emersion/go-jsonschema) - generates Go types and helpers from JSON schema files *supports Draft 2020-12* - - [protoc-gen-jsonschema](https://github.com/chrusty/protoc-gen-jsonschema) - Generates JSON schemas from protobuf proto v2 and v3 files. -- Java - - [jsonCodeGen](https://github.com/schlothauer-wauer/jsoncodegen) (MIT) - Groovy based generation tasks from JSON schema. Already includes templates/generators for Java Beans, Swagger specification files and PlantUML diagrams. - - [jsonschema2pojo](https://github.com/joelittlejohn/jsonschema2pojo) (Apache 2.0) - generates Java types from JSON Schema (or example JSON) and can annotate those types for data-binding with Jackson 2.x or Gson. *draft-07* - - [jsonschematypes](https://github.com/jimblackler/jsonschematypes) (Apache 2.0) - Java library to generate Java or TypeScript classes from standard JSON Schemas. *JSON Schema 2019-09, draft-07, -06, -04, -03* - - [jsongenerator](https://github.com/jimblackler/jsonschematypes/tree/master/codegen) *JSON Schema 2019-09, draft-07, -06, -04, -03* (Apache-2.0) - - [OpenAPI JSON Schema Generator](https://github.com/openapi-json-schema-tools/openapi-json-schema-generator) (Apache-2.0) - Allows auto-generation of API client libraries (SDK generation) given an [OpenAPI](https://www.openapis.org) document. This project focuses on making the output 100% compliant with openapi + JSON schema specs. JSON Schema 2020-12, draft-05 -- Kotlin - - [json-kotlin-schema-codegen](https://github.com/pwall567/json-kotlin-schema-codegen) (MIT) - Generates Kotlin data classes, Java classes or TypeScript interfaces from JSON Schema. - - [OpenAPI JSON Schema Generator](https://github.com/openapi-json-schema-tools/openapi-json-schema-generator) (Apache-2.0) - Allows auto-generation of API client libraries (SDK generation) given an [OpenAPI](https://www.openapis.org) document. This project focuses on making the output 100% compliant with openapi + JSON schema specs. JSON Schema 2020-12, draft-05 -- Online (web tool) - - [quicktype.io](https://app.quicktype.io/#l=schema) - infer JSON Schema from samples, and generate TypeScript, C++, go, Java, C#, Swift, etc. types from JSON Schema -- PHP - - [php-code-builder](https://github.com/swaggest/php-code-builder)(MIT) - generates PHP mapping structures defined by JSON schema using [swaggest/json-schema](https://github.com/swaggest/php-json-schema) *supports Draft 7* -- Python - - [yacg](https://github.com/OkieOth/yacg) (MIT) - parse JSON Schema and [OpenAPI](https://www.openapis.org) files to build a meta model from them. This meta model can be used in Mako templates to generate source code, other schemas or plantUml. - - [statham](https://github.com/jacksmith15/statham-schema) (MIT) - generate type-annotated models from JSON Schema documents. - - [OpenAPI JSON Schema Generator](https://github.com/openapi-json-schema-tools/openapi-json-schema-generator) (Apache-2.0) - Allows auto-generation of API client libraries (SDK generation) given an [OpenAPI](https://www.openapis.org) document. This project focuses on making the output 100% compliant with openapi + JSON schema specs. JSON Schema 2020-12, draft-05 -- Rust - - [schemafy](https://github.com/Marwes/schemafy/) - generates Rust types and serialization code from a JSON schema. *supports Draft 4* -- Scala - - [json-schema-to-case-class](https://github.com/cchandurkar/json-schema-to-case-class) (MIT) - NPM Package, [Web UI](https://cchandurkar.github.io/json-schema-to-case-class) and a CLI to generate Scala case classes from JSON Schema. *Supports JSON Schema 2019-09, draft-07, -06, -04, -03* -- TypeScript - - [jsongenerator](https://github.com/jimblackler/jsonschematypes/tree/master/codegen) *JSON Schema 2019-09, draft-07, -06, -04, -03* (Apache-2.0) - - [Shale](https://github.com/kgiszczak/shale) (MIT) - generates Ruby models from a JSON schema *supports Draft 2020-12* - -### Web UI generation - -_TODO: Sort by draft support._ - -Various levels of support for UI generation primarily from the validation vocabulary or combined with UI specific definition. - -- JavaScript - - [Alpaca Forms](http://www.alpacajs.org/) (ASL 2.0) - - [Angular Schema Form](https://github.com/json-schema-form/angular-schema-form) (MIT) - - [Angular2 Schema Form](https://github.com/makinacorpus/angular2-schema-form) *unrelated to Angular Schema Form* (MIT) - - [Angular6-json-schema-form](https://github.com/hamzahamidi/Angular6-json-schema-form) (MIT) - - [Dashjoin JSON Schema Form](https://github.com/dashjoin/json-schema-form) (Apache 2) *draft-06 (minus oneOf, anyOf, allOf, not)* - - [JSON Editor](https://github.com/json-editor/json-editor) (MIT) - - [JSON Form (joshfire)](https://github.com/joshfire/jsonform) (joshfire) (MIT) - - [Json Forms (brutusin)](https://github.com/brutusin/json-forms) (brutusin) (MIT) - - [json-schema-form (Remote.com)](https://github.com/remoteoss/json-schema-form) (Remote.com) (MIT) - - [JSON Schema Form Element](https://jsfe.js.org) (ISC) - - [JSONForms (jsonforms.io)](https://jsonforms.io/) (EclipseSource) (MIT) - - [Liform-react](https://github.com/Limenius/liform-react) (MIT) - - [React JSON Schema Form (mozilla)](https://github.com/mozilla-services/react-jsonschema-form) (Apache 2) - - [React Json Schema Form (Mui)](https://github.com/vip-git/react-jsonschema-form-material-ui) (MIT) - - [React Schema Form (networknt)](https://github.com/networknt/react-schema-form) (MIT) - - [Restspace Schema Form](https://github.com/restspace/schema-form) (MIT) - - [uniforms (Vazco)](https://github.com/vazco/uniforms) (MIT) - - [UI Schema for React](https://github.com/ui-schema/ui-schema) (MIT) *2019-09 / draft-08, -07, -06, -04 (incompatible `type=integer`)* - -### Data from schemas - -- .Net - - [JsonSchema.Net.DataGeneration](https://github.com/gregsdennis/json-everything) (MIT) Data generation from JSON schemas, powered by the Bogus testing data generation library. -- Python - - [hypothesis-jsonschema](https://github.com/Zac-HD/hypothesis-jsonschema) (MPL) *draft-07, -06, -04*; takes any schema, even with complex and interacting constraints, and returns a [Hypothesis](https://hypothesis.works/) strategy which can generate valid documents for testing. -- Java - - [jsongenerator](https://github.com/jimblackler/jsongenerator) *JSON Schema 2019-09, draft-07, -06, -04, -03* (Apache-2.0) - -## Utilities - -Draft compatibility for utilities is generally specific to the purpose of -the utility, and decided on a case-by-case basis. - -### General processing - -- JavaScript - - [json-schema-ref-parser](https://github.com/BigstickCarpet/json-schema-ref-parser) (MIT) Tools for dereferencing non-cyclic schemas, bundling referenced schemas into a single file, and other `$ref` processing. - - [json-schema-library](https://github.com/sagold/json-schema-library) (MIT) - Exposes tools to work with json-schema, including: data creation from json-schema, `$ref` processing, walk through schemas, etc. - - [@cloudflare/json-schema-walker](https://github.com/cloudflare/json-schema-tools/tree/master/workspaces/json-schema-walker) ([JSON Schema Tools](https://github.com/cloudflare/json-schema-tools)), _draft-07, -06, -04, and Cloudflare's Doca extensions_ Walks schemas and runs pre- and post-walk callbacks. Can modify schemas in place. (BSD-3-Clause) - - [@hyperjump/json-schema-core](https://github.com/jdesrosiers/json-schema-core) - (MIT) Tools for working with schemas that handle identifiers and - references. Build vocabularies and other JSON Schema based tools. - -### Schema to Schema - -- JavaScript - - [@cloudflare/json-schema-transform](https://github.com/cloudflare/json-schema-tools/tree/master/workspaces/json-schema-transform) ([JSON Schema Tools](https://github.com/cloudflare/json-schema-tools)), (BSD-3-Clause) Utilities using @cloudflare/json-schema-walker for transformations including `allOf` merging and example roll-up. - - [mokkabanna/json-schema-merge-allof](https://github.com/mokkabonna/json-schema-merge-allof) (MIT) - - [mokkabanna/json-schema-compare](https://github.com/mokkabonna/json-schema-compare) (MIT) - - [loganvolkers/json-schema-resolve-allof](https://www.npmjs.com/package/json-schema-resolve-allof) (_license not stated_) - - [JSON-Schema-Instantiator](https://github.com/tomarad/JSON-Schema-Instantiator) (MIT) - -### Schema draft migration - -- JavaScript - - [AlterSchema](https://github.com/sourcemeta/alterschema) _JSON Schema 2020-12, 2019-09, draft-07, -06, -04_ - -### Format converters - -- [OpenAPI](https://www.openapis.org) - - [JSON Schema to OpenAPI Schema](https://github.com/wework/json-schema-to-openapi-schema) _draft-04_ Draft-06 and -07 planned per README (MIT) - - [OpenAPI specification to JSON Schema](https://github.com/instrumenta/openapi2jsonschema) Draft-07 (MIT) -- Orderly - - [Orderly](https://github.com/lloyd/orderly) (BSD-3-Clause) -- RAML - - [ramldt2jsonschema](https://github.com/raml-org/ramldt2jsonschema) _draft-06, 04_ (Apache-2.0) -- Webpack - - [@cloudflare/json-schema-ref-loader](https://github.com/cloudflare/json-schema-tools/tree/master/workspaces/json-schema-ref-loader) ([JSON Schema Tools](https://github.com/cloudflare/json-schema-tools)), (BSD-3-Clause) Webpack loader for dereference-able schemas in JSON, JSON5, YAML, or JavaScript - - [@cloudflare/json-schema-apidoc-loader](https://github.com/cloudflare/json-schema-tools/tree/master/workspaces/json-schema-apidoc-loader) ([JSON Schema Tools](https://github.com/cloudflare/json-schema-tools)), Back-end for [@cloudflare/doca](https://github.com/cloudflare/json-schema-tools/tree/master/workspaces/doca), _draft-04, -06, -07, and Doca extensions_ -- XSD - - [Oxygen XSD to JSON Schema](https://www.oxygenxml.com/json_converter.html#xsd-to-json-schema) - Generate from an XSD file a similar JSON Schema structure. - - [XSD to JSON Schema IntellJ plugin](https://plugins.jetbrains.com/plugin/19024-xsd-to-json-schema) - Plugin for converting an XML Schema (XSD) file to a JSON Schema file. - -### Testing - -- Python - - [hypothesis-jsonschema](https://github.com/Zac-HD/hypothesis-jsonschema) (MPL) *draft-07, -06, -04*; takes any schema, even with complex and interacting constraints, and returns a [Hypothesis](https://hypothesis.works/) strategy which can generate valid documents for testing. - -### Editors - -- [Altova XMLSpy 2019r3](https://www.altova.com/xmlspy-xml-editor#json_schema) - *Graphical JSON Schema editor for draft-06 and draft-7, as well as validation of JSON files based on JSON Schema* -- [Dashjoin JSON Schema editor](https://dashjoin.github.io/#/schema) - *Graphical online JSON Schema editor for draft-06 (minus oneOf, anyOf, allOf, not). The generated schema can be tested immediately via a form that is driven by it.* -- [Hackolade Studio](https://hackolade.com/help/JSONSchemaEditor.html) - *Visual JSON Schema editor for draft-04, draft-06, draft-07, 2019-09, 2020-12, as well as data modeling tool for NoSQL databases, storage formats, REST APIs, and JSON in RDBMS. Also converts to and from: different draft specifications, DDL, XSD, Swagger, OpenAPI, YAML, Avro, Parquet, Protobuf, and most of the NoSQL script syntaxes. Includes a GUI for Entity-Relationship Diagrams and a Command-Line Interface.* -- [JSONBuddy](https://www.json-buddy.com/) - *Text and grid-style JSON editor and validator. Complete JSON Schema development environment with JSON Schema analyzer, context sensitive entry-helpers, sample data generation based on JSON Schema and JSON Schema validation debugger: Step through the validation process and set breakpoints. JSON Schema testing tool including schema coverage. Support for draft-4, draft-6, draft-7, 2019-09 and 2020-12.* -- [JSONEditor Online](https://jsoneditoronline.org/) - *View, edit, format, and validate JSON online* Support draft-4, draft-6, and draft-7. -- [Liquid JSON Schema Editor](https://www.liquid-technologies.com/json-schema-editor) - *Graphical JSON Schema editor for draft-04, draft-06, draft-07 and 2019-09, with split source code and grphical editing. Includes validation of JSON files based on JSON Schema, JSON Sample Generator and JSON Schema Documentation Generator.* -- [Oxygen JSON Schema Editor](https://www.oxygenxml.com/xml_developer/json_schema_editor.html) - *JSON Schema editor with a variety of editing features and helper views (Design/Text/Author). Support for validation and editing JSON Schema draft-4, draft-6, and draft-7, 2019-09 (partial), 2020-12 (partial). Validation and editing of JSON files based on JSON Schema.* -- [Perseid Modeler](https://www.datensen.com/data-modeling/perseid-modeler-for-json-schema.html) - *a modeling tool for JSON Schema and [OpenAPI](https://www.openapis.org). Key features include: visual JSON schema creation using tree and ERD-like diagrams, support for JSON schema structures including operators and conditions, import of existing schemas from files, creation of detailed HTML reports, export to PDF, script generation, and more. Supported versions: draft 4, 6, 7, 2019-09 and 2020-12* -- [Stoplight Studio](https://stoplight.io/) - *JSON Schema IDE (text-based and GUI) with support for JSON/YAML linting, which can also be based on JSON Schema rules via Spectral. Support for draft-4, draft-6 and draft-7.* -- [Visual Studio Code](https://code.visualstudio.com/) - *Schema driven code completion, hovers and validation for editing JSON files (including schemas)* -- [WebStorm](https://www.jetbrains.com/webstorm/), [IntelliJ IDEA](https://www.jetbrains.com/idea/), and other [JetBrains IDEs](https://www.jetbrains.com/products.html?fromMenu#type=ide) - *Code completion, documentation, and validation for JSON and YAML files using JSON Schema. Support for draft-4, draft-6, and draft-7.* -- [Eclipse IDE](https://www.eclipse.org/downloads/eclipse-packages) - *Rich JSON edition supporting schema for instantaneous validation and error reporting, completion, documentation.* - -### Documentation generators - -- [docusaurus-json-schema-plugin](https://github.com/jy95/docusaurus-json-schema-plugin) - Schema viewer. Runs within a [Docusaurus](https://docusaurus.io/) web app. Supports draft-7, 2019-09, Draft 2020-12 -- [json-schema-static-docs](https://tomcollins.github.io/json-schema-static-docs/) - Generates human friendly markdown documentation from JSON Schema. Includes links between pages based on $ref values. Supports draft-7. -- [jsonschematic](https://github.com/yanick/jsonschematic/) - Svelte-based schema viewer. Runs as a local web app. Supports draft-7. -- [docson](https://github.com/lbovet/docson) - Javascript-based schema viewer. Runs as a local web app. Supports draft-4. -- [json-schema-for-humans](https://pypi.org/project/json-schema-for-humans/) - Generate HTML representation of a schema. Python-based. Supports draft-7. -- [oXygen JSON Schema Documentation](https://www.oxygenxml.com/json_converter.html#generate-json-schema-documentation) - Generate JSON Schema documentation in HTML format including diagrams. -- [wetzel](https://github.com/CesiumGS/wetzel) - Generates Markdown and AsciiDoc. With some limitations, supports draft-3, draft-4, draft-7, and 2020-12. -- [jsonschema-markdown](https://github.com/elisiariocouto/jsonschema-markdown) - Generate Markdown documentation of a schema. Can be used as a CLI or as a Python library. - -## Schema Repositories - -- [SchemaStore.org](https://schemastore.org/json/) - validate against common JSON Schemas - -## Schema Linter - -- [json-schema-linter](https://www.json-schema-linter.com/) - Lint/validate/parse json-schema itself, and find typos, missing properties, missing required keys, etc. Supports draft 4, 6, and 7. -- [Stoplight Spectral](https://stoplight.io/open-source/spectral) - A flexible JSON/YAML linter for creating automated style guides, with baked in support for [OpenAPI v2/v3 ](https://www.openapis.org)and JSON Schema. Supports draft 4, 6, and 7. - -## Linter plugins - -- [remark-lint-frontmatter-schema](https://github.com/JulianCataldo/remark-lint-frontmatter-schema) - Validate **Markdown** frontmatter **YAML** against an associated **JSON schema** with this **remark-lint** rule plugin. -- [eslint-plugin-json-schema-validator](https://github.com/ota-meshi/eslint-plugin-json-schema-validator) - ESLint plugin that validates code using JSON schema and reports violations. - -## Hyper-Schema diff --git a/pages/implementers/interfaces.md b/pages/implementers/interfaces.md index fa4d94fb8..c0a54629b 100644 --- a/pages/implementers/interfaces.md +++ b/pages/implementers/interfaces.md @@ -4,7 +4,7 @@ section: implementers --- JSON Schema is extremely widely used and nearly equally widely implemented. -There are implementations of JSON Schema validation for [over 20 languages](https://json-schema.org/implementations.html) or environments. +There are implementations of JSON Schema validation for [over 20 languages](https://json-schema.org/tools) or environments. This prevalence is fantastic for user choice -- as someone wishing to use JSON Schema you can be almost certain you'll find an implementation suitable for your target environment. But when it comes to community support, it can be challenging to know how to perform various JSON Schema operations in a particular library or implementation, as each may have slightly differing (or more than slightly differing) APIs. @@ -75,7 +75,7 @@ Consider a division function on floats, represented as `x / y`. We will write the type of this function as `Float → Float → Float DivideByZeroError`, where the interpretation of this signature is that the function takes 2 floats and returns a float, but the `` signals it may also propagate a `DivideByZeroError` (in this case when the function is asked to divide by zero). The specific manifestation of `DivideByZeroError` will depend on the programming language. -In a language with exceptions, this function may raise a `DivideByZeroError`-equivalent as an exception, which must or may be handled by the caller. +In a language with exceptions, this function may raise a `DivideByZeroError`-equivalent as an exception, which must or may be handled by the caller. In a language with option types, the "correct" type signature may really be wrapped in an `Option` type which represents the division by zero case (so the "true" signature in such a language would be `Option[Float → Float → Float]`). In a language with wrapper return types, the true type signature may be `Result` where the returned value must be inspected to ensure it contains a successful result, and where the divide by zero error is instead a possible error value. In a language with a convention to return "junk" values, the true type may be precisely `Float → Float → Float` where some arbitrary float value is diff --git a/pages/index.page.tsx b/pages/index.page.tsx index a74b734ef..e30c419e1 100644 --- a/pages/index.page.tsx +++ b/pages/index.page.tsx @@ -395,7 +395,7 @@ const Home = (props: any) => { amazing Community.

diff --git a/pages/learn/getting-started-step-by-step/getting-started-step-by-step.md b/pages/learn/getting-started-step-by-step/getting-started-step-by-step.md index 30731701e..7a3cbf79a 100644 --- a/pages/learn/getting-started-step-by-step/getting-started-step-by-step.md +++ b/pages/learn/getting-started-step-by-step/getting-started-step-by-step.md @@ -5,15 +5,15 @@ section: docs JSON Schema is a vocabulary that you can use to annotate and validate JSON documents. This tutorial guides you through the process of creating a JSON Schema. -After creating your JSON Schema, you can then validate example data against your schema by using a validator in a language of your choice. Please, visit [Tools](https://json-schema.org/implementations#validators) and select the validator that better suit your needs. +After creating your JSON Schema, you can then validate example data against your schema by using a validator in a language of your choice. Please, visit [Tools](https://json-schema.org/tools#validators) and select the validator that better suit your needs. -If you already know how to create JSON Schemas and you are looking for different JSON Schema use cases like schema generation, code generation, documentation, UI generation or JSON Schema processing or conversion, please visit [Tools](https://json-schema.org/implementations) and explore the amazing tooling available in the JSON Schema Ecosystem. +If you already know how to create JSON Schemas and you are looking for different JSON Schema use cases like schema generation, code generation, documentation, UI generation or JSON Schema processing or conversion, please visit [Tools](https://json-schema.org/tools) and explore the amazing tooling available in the JSON Schema Ecosystem. -## Overview +## Overview The example we use in this guide is a product catalog that stores its data using JSON objects, like the following: @@ -388,7 +388,7 @@ To create a nested data structure: ``` 4. To make each of these properties required, add a `required` validation keyword inside the `dimensions` object: - + ```jsonc ... "dimensions": { @@ -575,11 +575,10 @@ With the external schema reference, the overall schema looks like this: ## Validate JSON data against the schema -Now that you have your JSON Schema is time to validate [JSON data](https://json-schema.org/learn/glossary#instance) against it using a [JSON Schema Validator](https://json-schema.org/implementations#validators). +Now that you have your JSON Schema is time to validate [JSON data](https://json-schema.org/learn/glossary#instance) against it using a [JSON Schema Validator](https://json-schema.org/tools#validators). A Validator is a tool that implements the JSON Schema specification. All validators works in a similar way: they take a JSON Schema and a JSON Instance as input and they returns the validation result as output. ![How JSON Schema works](https://json-schema.org/img/json_schema.svg) -To try it yourself, please visit [Tools](https://json-schema.org/implementations#validators) and select the validator that better suit your needs, our use the editors available below to explore the different Schemas and Instances and see the different validation results. - +To try it yourself, please visit [Tools](https://json-schema.org/tools#validators) and select the validator that better suit your needs, our use the editors available below to explore the different Schemas and Instances and see the different validation results. diff --git a/pages/learn/getting-started-step-by-step/next-steps.md b/pages/learn/getting-started-step-by-step/next-steps.md index a986de19d..1b02232ec 100644 --- a/pages/learn/getting-started-step-by-step/next-steps.md +++ b/pages/learn/getting-started-step-by-step/next-steps.md @@ -9,4 +9,4 @@ Now that you know how to create a JSON Schema and use it to validate JSON data, * Learn more about JSON Schema by visiting the [reference documentation](../understanding-json-schema). * Explore the details of the current version of the Spec [2020-12](https://json-schema.org/specification). -If you already know how to create JSON Schemas and you are looking for different JSON Schema use cases like schema generation, code generation, documentation, UI generation or JSON Schema processing or conversion, please visit [Tools](https://json-schema.org/implementations) and explore the amazing tooling available in the JSON Schema Ecosystem. \ No newline at end of file +If you already know how to create JSON Schemas and you are looking for different JSON Schema use cases like schema generation, code generation, documentation, UI generation or JSON Schema processing or conversion, please visit [Tools](https://json-schema.org/tools) and explore the amazing tooling available in the JSON Schema Ecosystem. diff --git a/pages/overview/what-is-jsonschema.md b/pages/overview/what-is-jsonschema.md index f599848bc..8228375a2 100644 --- a/pages/overview/what-is-jsonschema.md +++ b/pages/overview/what-is-jsonschema.md @@ -10,7 +10,7 @@ title: What is JSON Schema? When it comes to data exchange, JSON Schema stands out as a powerful standard for defining the structure and rules of JSON data. It uses a set of [keywords](https://json-schema.org/learn/glossary#keyword) to define the properties of your data. -While JSON Schema provides the language, validating a JSON [instance](https://json-schema.org/learn/glossary#instance) against a [schema](https://json-schema.org/learn/glossary#schema) requires a JSON Schema [validator](https://json-schema.org/implementations#validators). The JSON validator checks if the JSON documents conform to the schema. +While JSON Schema provides the language, validating a JSON [instance](https://json-schema.org/learn/glossary#instance) against a [schema](https://json-schema.org/learn/glossary#schema) requires a JSON Schema [validator](https://json-schema.org/tools#validators). The JSON validator checks if the JSON documents conform to the schema. JSON Schema Validators are tools that implement the JSON Schema specification. Such tooling enables easy integration of JSON Schema into projects of any size. diff --git a/pages/tools/JSONSchemaTool.ts b/pages/tools/JSONSchemaTool.ts new file mode 100644 index 000000000..89c957253 --- /dev/null +++ b/pages/tools/JSONSchemaTool.ts @@ -0,0 +1,59 @@ +export interface JSONSchemaTool { + name: string; + description?: string; + toolingTypes: string[]; + languages?: string[]; + environments?: string[]; + dependsOnValidators?: string[]; + creators?: Person[]; + maintainers?: Person[]; + license?: string; + source?: string; + homepage?: string; + documentation?: object; + supportedDialects?: { + draft?: (number | string)[]; + additional?: { + name: string; + homepage?: string; + source: string; + }[]; + }; + bowtie?: { + identifier: string; + }; + toolingListingNotes?: string; + compliance?: { + config?: { + docs?: string; + instructions?: string; + }; + }; + landscape?: { + logo?: string; + optOut?: boolean; + }; + lastUpdated?: string; +} + +export interface Person { + name?: string; + email?: string; + username?: string; + platform?: 'github' | 'gitlab' | 'bitbucket' | string; +} + +export interface BowtieEntry { + id: string; + dialects: Array; + badges_urls: { + supported_versions: string; + compliance: { + [dialectURI: string]: string; + }; + }; +} + +export interface BowtieReport { + [source: string]: BowtieEntry; +} diff --git a/pages/tools/components/GroupByMenu.tsx b/pages/tools/components/GroupByMenu.tsx new file mode 100644 index 000000000..b46c11622 --- /dev/null +++ b/pages/tools/components/GroupByMenu.tsx @@ -0,0 +1,56 @@ +import React, { Dispatch, SetStateAction } from 'react'; +import { Transform } from '../hooks/useToolsTransform'; + +interface GroupByMenuProps { + transform: Transform; + setTransform: Dispatch>; +} + +const GroupByMenu = ({ transform, setTransform }: GroupByMenuProps) => { + const groupedBy = transform.groupBy; + + const groupBy = [ + { + label: 'None', + accessorKey: 'none', + }, + { + label: 'Tooling Types', + accessorKey: 'toolingTypes', + }, + { + label: 'Languages', + accessorKey: 'languages', + }, + ]; + + const setGroupBy = (event: React.MouseEvent) => { + setTransform((prev) => ({ + ...prev, + groupBy: (event.target as HTMLButtonElement) + .value as Transform['groupBy'], + sortBy: 'name', + sortOrder: 'ascending', + })); + }; + + return ( +
+ GROUP BY: + {groupBy.map((group) => { + return ( + + ); + })} +
+ ); +}; + +export default GroupByMenu; diff --git a/pages/tools/components/SearchBar.tsx b/pages/tools/components/SearchBar.tsx new file mode 100644 index 000000000..f4fd2bd65 --- /dev/null +++ b/pages/tools/components/SearchBar.tsx @@ -0,0 +1,31 @@ +import React, { useEffect, useState } from 'react'; +import type { Transform } from '../hooks/useToolsTransform'; + +const SearchBar = ({ transform }: { transform: Transform }) => { + const [query, setQuery] = useState(transform.query); + + const changeHandler = (e: React.ChangeEvent) => { + setQuery(e.target.value); + }; + + useEffect(() => { + setQuery(transform.query); + }, [transform.query]); + + return ( +
+
+ +
+
+ ); +}; + +export default SearchBar; diff --git a/pages/tools/components/Sidebar.tsx b/pages/tools/components/Sidebar.tsx new file mode 100644 index 000000000..8e7f29b15 --- /dev/null +++ b/pages/tools/components/Sidebar.tsx @@ -0,0 +1,113 @@ +import React, { Dispatch, SetStateAction, useRef } from 'react'; +import FilterIcon from '~/public/icons/filter.svg'; +import DropdownMenu from './ui/DropdownMenu'; +import Checkbox from './ui/Checkbox'; +import SearchBar from './SearchBar'; +import toTitleCase from '../lib/toTitleCase'; +import type { Transform } from '../hooks/useToolsTransform'; +import type { FilterCriteriaFields } from '../index.page'; +import { postAnalytics } from '../lib/postAnalytics'; + +interface SidebarProps { + filterCriteria: Record; + transform: Transform; + setTransform: Dispatch>; + resetTransform: () => void; + setIsSidebarOpen: Dispatch>; +} + +export default function Sidebar({ + filterCriteria, + transform, + setTransform, + resetTransform, + setIsSidebarOpen, +}: SidebarProps) { + const filterFormRef = useRef(null); + + const filters = [ + { label: 'Languages', accessorKey: 'languages' }, + { label: 'Drafts', accessorKey: 'drafts' }, + { label: 'Tooling Types', accessorKey: 'toolingTypes' }, + { label: 'License', accessorKey: 'licenses' }, + ]; + + const applyFilters = (e: React.FormEvent) => { + e.preventDefault(); + if (!filterFormRef.current) return; + const formData = new FormData(filterFormRef.current); + setTransform((prev) => { + const newTransform = { + query: (formData.get('query') as Transform['query']) || '', + sortBy: prev.sortBy || 'name', + sortOrder: prev.sortOrder || 'ascending', + groupBy: prev.groupBy || 'toolingTypes', + languages: formData.getAll('languages').map((value) => value as string), + licenses: formData.getAll('licenses').map((value) => value as string), + drafts: formData + .getAll('drafts') + .map((value) => value) as Transform['drafts'], + toolingTypes: formData + .getAll('toolingTypes') + .map((value) => value as string), + }; + postAnalytics({ eventType: 'query', eventPayload: newTransform }); + return newTransform; + }); + setIsSidebarOpen((prev) => !prev); + }; + + const clearFilters = () => { + if (filterFormRef.current) { + filterFormRef.current.reset(); + } + resetTransform(); + setIsSidebarOpen((prev) => !prev); + }; + + return ( +
+
+ + {filters.map(({ label, accessorKey }) => { + const checkedValues = transform[accessorKey as keyof Transform] || []; + return ( + }> + {filterCriteria[accessorKey as FilterCriteriaFields] + ?.map(String) + .map((filterOption) => ( + + ))} + + ); + })} + +
+ + +
+ +
+ ); +} diff --git a/pages/tools/components/ToolingDetailModal.tsx b/pages/tools/components/ToolingDetailModal.tsx new file mode 100644 index 000000000..887e3c79d --- /dev/null +++ b/pages/tools/components/ToolingDetailModal.tsx @@ -0,0 +1,385 @@ +import React, { useEffect, useState } from 'react'; + +import CancelIcon from '~/public/icons/cancel.svg'; + +import Badge from './ui/Badge'; +import type { + BowtieEntry, + BowtieReport, + JSONSchemaTool, +} from '../JSONSchemaTool'; +import toTitleCase from '../lib/toTitleCase'; + +export default function ToolingDetailModal({ + tool, + onClose, +}: { + tool: JSONSchemaTool; + onClose: () => void; +}) { + const [bowtieEntry, setBowtieEntry] = useState< + BowtieEntry | 'loading' | null + >('loading'); + + useEffect(() => { + document.body.classList.add('no-scroll'); + return () => { + document.body.classList.remove('no-scroll'); + }; + }, []); + + useEffect(() => { + if (tool.source) { + const fetchBowtieReport = async () => { + try { + const res = await fetch( + 'https://bowtie.report/api/v1/json-schema-org/implementations', + ); + const bowtieReport: BowtieReport = await res.json(); + + setBowtieEntry(bowtieReport[tool.source!] || null); + } catch (error) { + console.error('Error fetching Bowtie report:', error); + setBowtieEntry(null); + } + }; + + fetchBowtieReport(); + } else { + setBowtieEntry(null); + } + }, [tool.source]); + + return ( +
+
+
+
+ +
+
+ {tool.landscape?.logo && ( +
+ +
+ )} +
+

{tool.name}

+ {tool.description && ( +

+ {tool.description} +

+ )} +
+
+
+
+ {tool.source && ( +
+

Source

+ + {tool.source} + +
+ )} + + {tool.homepage && ( +
+

Homepage

+ + {tool.homepage} + +
+ )} + + {tool.license && ( +
+

License

+

{tool.license}

+
+ )} + + {tool.compliance && ( +
+

Compliance

+ {tool.compliance.config && ( +
+ {tool.compliance.config.docs && ( + + )} + {tool.compliance.config.instructions && ( +
+

Instructions:

+

{tool.compliance.config.instructions}

+
+ )} +
+ )} +
+ )} + + {tool.toolingListingNotes && ( +
+

Tooling Listing Notes

+

{tool.toolingListingNotes}

+
+ )} + + {tool.creators && ( +
+

Creators

+
    + {tool.creators.map((creator, index) => ( +
  • + {creator.name ? creator.name : 'N.A.'} + + ( + {creator.username && creator.platform && ( + + @{creator.username} + + )} + ) + +
  • + ))} +
+
+ )} + + {tool.maintainers && ( +
+

Maintainers

+
    + {tool.maintainers.map((maintainer, index) => ( +
  • + {maintainer.name ? maintainer.name : 'N.A.'} + + ( + {maintainer.username && maintainer.platform && ( + + @{maintainer.username} + + )} + ) + +
  • + ))} +
+
+ )} + + {tool.supportedDialects && ( +
+

Supported Dialects

+ {tool.supportedDialects.draft && ( +
+

Draft:

+
    + {tool.supportedDialects.draft.map((draft) => ( + {draft} + ))} +
+
+ )} + {tool.supportedDialects.additional && ( +
+

Additional:

+
    + {tool.supportedDialects.additional.map( + (additional, index) => ( +
  • + {additional.name} ( + + Source + + ) +
  • + ), + )} +
+
+ )} +
+ )} + + {bowtieEntry === 'loading' ? ( +
+

+ Crunching the latest Bowtie report for you... +

+
+ ) : ( + bowtieEntry && ( +
+

Bowtie Report

+ {bowtieEntry.badges_urls.supported_versions && ( +
+

+ Supported Versions: +

+ +
+ )} + {bowtieEntry.badges_urls.compliance && ( +
+

Compliance:

+ {Object.values(bowtieEntry.badges_urls.compliance).map( + (badgeURI) => ( + + ), + )} +
+ )} +
+ ) + )} + + {tool.toolingTypes && ( +
+

Tooling Types

+
    + {tool.toolingTypes.map((type) => ( + {toTitleCase(type, '-')} + ))} +
+
+ )} + + {tool.languages && ( +
+

Languages

+
    + {tool.languages.map((language) => ( + {language} + ))} +
+
+ )} + + {tool.environments && ( +
+

Environments

+
    + {tool.environments.map((environment) => ( + {environment} + ))} +
+
+ )} + + {tool.bowtie && ( +
+

Bowtie Identifier

+

{tool.bowtie.identifier}

+
+ )} + + {tool.dependsOnValidators && ( +
+

Depends On Validators

+
    + {tool.dependsOnValidators.map((validator, index) => ( +
  • + + {validator} + +
  • + ))} +
+
+ )} + + {tool.landscape?.optOut && ( +
+

Landscape

+ {tool.landscape.optOut !== undefined && ( +
+

Opt-Out:

+

{tool.landscape.optOut ? 'Yes' : 'No'}

+
+ )} +
+ )} +
+
+
+
+ ); +} + +const BowtieReportBadge = ({ uri }: { uri: string }) => { + const [loading, setLoading] = useState(true); + const [error, setError] = useState(false); + + return ( +
+ {loading && !error && ( +
+ )} + setLoading(false)} + onError={() => { + setLoading(false); + setError(true); + }} + style={{ display: loading ? 'none' : 'block' }} + alt='Bowtie Badge' + className='my-1' + /> + {error && ( +
Failed to load badge
+ )} +
+ ); +}; diff --git a/pages/tools/components/ToolingTable.tsx b/pages/tools/components/ToolingTable.tsx new file mode 100644 index 000000000..b233ef360 --- /dev/null +++ b/pages/tools/components/ToolingTable.tsx @@ -0,0 +1,326 @@ +import React, { + Dispatch, + ReactNode, + SetStateAction, + useEffect, + useState, +} from 'react'; + +import { Headline2 } from '~/components/Headlines'; +import CancelIcon from '~/public/icons/cancel.svg'; +import OutLinkIcon from '~/public/icons/outlink.svg'; + +import toTitleCase from '../lib/toTitleCase'; +import type { GroupedTools, Transform } from '../hooks/useToolsTransform'; +import type { JSONSchemaTool } from '../JSONSchemaTool'; +import Badge from './ui/Badge'; + +import ToolingDetailModal from './ToolingDetailModal'; +import classnames from 'classnames'; +import { postAnalytics } from '../lib/postAnalytics'; + +interface ToolingTableProps { + toolsByGroup: GroupedTools; + transform: Transform; + setTransform: Dispatch>; +} + +const ToolingTable = ({ + toolsByGroup, + transform, + setTransform, +}: ToolingTableProps) => { + const [selectedTool, setSelectedTool] = useState(null); + + const groups = Object.keys(toolsByGroup); + + const openModal = (tool: JSONSchemaTool) => { + setSelectedTool(tool); + postAnalytics({ + eventType: 'about', + eventPayload: { + name: tool.name, + toolingTypes: tool.toolingTypes, + languages: tool.languages, + environments: tool.environments, + license: tool.license, + supportedDialects: tool.supportedDialects, + }, + }); + }; + + const closeModal = () => { + setSelectedTool(null); + }; + + return ( + <> + {groups.map((group) => ( +
+ {group !== 'none' && ( +
+ {toTitleCase(group, '-')} +
+ )} +
+ + + + + Name + + {transform.groupBy !== 'toolingTypes' && ( + + Tooling Type + + )} + {transform.groupBy !== 'languages' && ( + + Languages + + )} + + Drafts + + + License + + + Bowtie + + + + + {toolsByGroup[group].map((tool: JSONSchemaTool, index) => ( + openModal(tool)} + > + segment.length > 25) ? 'break-all' : ''}`, + style: { + flexBasis: '240px', + flexShrink: 0, + flexGrow: 0, + }, + title: 'See details', + }} + > + {tool.name} + + {transform.groupBy !== 'toolingTypes' && ( + + {tool.toolingTypes + ?.map((type) => toTitleCase(type, '-')) + .join(', ')} + + )} + {transform.groupBy !== 'languages' && ( + + {tool.languages?.join(', ')} + + )} + + {tool.supportedDialects?.draft?.map((draft) => { + return {draft}; + })} + + + {tool.license} + + +
+ {tool.bowtie?.identifier ? ( + event.stopPropagation()} + title='See at Bowtie' + > + + + ) : ( + + )} +
+
+ + ))} + +
+
+
+ ))} + {selectedTool && ( + + )} + + ); +}; + +const TableColumnHeader = ({ + children, + attributes: propAttributes, +}: { + children: ReactNode | ReactNode[]; + attributes?: Record; +}) => { + return ( + + {children} + + ); +}; + +const TableSortableColumnHeader = ({ + sortBy, + transform, + setTransform, + children, + attributes: propAttributes, +}: { + sortBy: Transform['sortBy']; + transform: Transform; + setTransform: Dispatch>; + children: ReactNode; + attributes?: Record; +}) => { + const [isSortedBy, setIsSortedBy] = useState(transform.sortBy === sortBy); + + useEffect(() => { + setIsSortedBy(transform.sortBy === sortBy); + }, [transform.sortBy]); + + const sortByColumn = (e: React.MouseEvent) => { + e.preventDefault(); + setTransform((prevTransform) => { + const newSortOrder = + prevTransform.sortBy === sortBy + ? prevTransform.sortOrder === 'descending' + ? 'ascending' + : 'descending' + : 'ascending'; + return { + ...prevTransform, + sortBy, + sortOrder: newSortOrder, + }; + }); + + setIsSortedBy(true); + }; + + const rotateClass = transform.sortOrder === 'ascending' ? 'rotate-180' : ''; + + return ( + + + + ); +}; + +const TableCell = ({ + children, + attributes: propAttributes, +}: { + children: ReactNode | ReactNode[]; + attributes?: Record; +}) => { + return ( + + {children} + + ); +}; + +export default ToolingTable; diff --git a/pages/tools/components/ui/Badge.tsx b/pages/tools/components/ui/Badge.tsx new file mode 100644 index 000000000..2085773c3 --- /dev/null +++ b/pages/tools/components/ui/Badge.tsx @@ -0,0 +1,11 @@ +import React, { ReactNode } from 'react'; + +const Badge = ({ children }: { children: ReactNode }) => { + return ( +
+ {children} +
+ ); +}; + +export default Badge; diff --git a/pages/tools/components/ui/Checkbox.tsx b/pages/tools/components/ui/Checkbox.tsx new file mode 100644 index 000000000..4f7daaed6 --- /dev/null +++ b/pages/tools/components/ui/Checkbox.tsx @@ -0,0 +1,38 @@ +import React, { useEffect, useState } from 'react'; + +export default function Checkbox({ + label, + value, + name, + checked, +}: { + label: string; + value: string; + name: string; + checked?: boolean; +}) { + const [isChecked, setIsChecked] = useState(checked); + + useEffect(() => { + setIsChecked(checked); + }, [checked]); + + const handleChange = () => { + setIsChecked((prevChecked) => !prevChecked); + }; + + return ( + + ); +} diff --git a/pages/tools/components/ui/DropdownMenu.tsx b/pages/tools/components/ui/DropdownMenu.tsx new file mode 100644 index 000000000..2ceaa0483 --- /dev/null +++ b/pages/tools/components/ui/DropdownMenu.tsx @@ -0,0 +1,75 @@ +import classnames from 'classnames'; +import { useRouter } from 'next/router'; +import React, { + type ReactElement, + type ReactNode, + useEffect, + useState, +} from 'react'; + +interface DropdownMenuProps { + children: ReactNode; + label: string; + icon: ReactElement; +} + +export default function DropdownMenu({ + children, + label, + icon, +}: DropdownMenuProps) { + const [isDropdownOpen, setIsDropdownOpen] = useState(false); + const router = useRouter(); + + useEffect(() => { + setIsDropdownOpen(false); + }, [router]); + + return ( +
+
{ + setIsDropdownOpen((prev) => !prev); + }} + > + {React.cloneElement(icon, { + className: 'mr-2', + })} +
+ {label} +
+ + + +
+ +
+ {children} +
+
+ ); +} diff --git a/pages/tools/components/ui/Radio.tsx b/pages/tools/components/ui/Radio.tsx new file mode 100644 index 000000000..911500ff7 --- /dev/null +++ b/pages/tools/components/ui/Radio.tsx @@ -0,0 +1,32 @@ +import React, { ChangeEventHandler } from 'react'; + +export default function Radio({ + label, + value, + selectedValue, + onChange, +}: { + label: string; + value: string; + selectedValue: string; + onChange: ChangeEventHandler; +}) { + return ( + + ); +} diff --git a/pages/tools/hooks/useToolsTransform.tsx b/pages/tools/hooks/useToolsTransform.tsx new file mode 100644 index 000000000..b5c494079 --- /dev/null +++ b/pages/tools/hooks/useToolsTransform.tsx @@ -0,0 +1,335 @@ +import { useEffect, useMemo, useState } from 'react'; +import { useRouter } from 'next/router'; +import Fuse from 'fuse.js'; + +import { DRAFT_ORDER } from '~/lib/config'; +import type { JSONSchemaTool } from '../JSONSchemaTool'; + +export interface Transform { + query: string; + sortBy: 'name' | 'license' | 'bowtie'; + sortOrder: 'ascending' | 'descending'; + groupBy: 'none' | 'toolingTypes' | 'languages'; + licenses: string[]; + languages: string[]; + drafts: `${(typeof DRAFT_ORDER)[number]}`[]; + toolingTypes: string[]; +} + +export type TransformUpdate = + | Partial + | ((prevTransform: Transform) => Partial); + +export interface GroupedTools { + [group: string]: JSONSchemaTool[]; +} + +const buildQueryString = (transform: Transform) => { + return new URLSearchParams({ + query: transform.query, + sortBy: transform.sortBy, + sortOrder: transform.sortOrder, + groupBy: transform.groupBy, + licenses: transform.licenses.join(','), + languages: transform.languages.join(','), + drafts: transform.drafts.join(','), + toolingTypes: transform.toolingTypes.join(','), + }).toString(); +}; + +export default function useToolsTransform(tools: JSONSchemaTool[]) { + const router = useRouter(); + const { query } = router; + + const [transform, setTransform] = useState({ + query: '', + sortBy: 'name', + sortOrder: 'ascending', + groupBy: 'toolingTypes', + languages: [], + licenses: [], + drafts: [], + toolingTypes: [], + }); + + useEffect(() => { + if (!router.isReady) return; + + const parseArrayParam = ( + param: string | string[] | undefined, + ): string[] => { + if (Array.isArray(param)) { + return param; + } + if (typeof param === 'string') { + return param.split(',').filter(Boolean); + } + return []; + }; + + const updatedTransform = { + query: (query.query as Transform['query']) || '', + sortBy: (query.sortBy as Transform['sortBy']) || 'name', + sortOrder: (query.sortOrder as Transform['sortOrder']) || 'ascending', + groupBy: (query.groupBy as Transform['groupBy']) || 'toolingTypes', + languages: parseArrayParam(query.languages) as Transform['languages'], + licenses: parseArrayParam(query.licenses) as Transform['licenses'], + drafts: parseArrayParam(query.drafts) as Transform['drafts'], + toolingTypes: parseArrayParam( + query.toolingTypes, + ) as Transform['toolingTypes'], + }; + + const queryString = buildQueryString(updatedTransform); + const hash = window.location.hash; + + router.replace(`/tools?${queryString}${hash}`, undefined, { + shallow: true, + }); + + setTransform(updatedTransform); + }, [router.isReady]); + + useEffect(() => { + if (!router.isReady) return; + const { query } = router; + + if (Object.keys(query).length === 0) { + resetTransform(); + } + }, [router]); + + const updateTransform = (update: TransformUpdate) => { + setTransform((prevTransform) => { + const newTransform = + typeof update === 'function' + ? { ...prevTransform, ...update(prevTransform) } + : { ...prevTransform, ...update }; + + const queryString = buildQueryString(newTransform); + + router.push(`/tools?${queryString}`, undefined, { shallow: true }); + + return newTransform; + }); + }; + + const resetTransform = () => { + const initialTransform: Transform = { + query: '', + sortBy: 'name', + sortOrder: 'ascending', + groupBy: 'toolingTypes', + languages: [], + licenses: [], + drafts: [], + toolingTypes: [], + }; + + const queryString = buildQueryString(initialTransform); + + router.push(`/tools?${queryString}`, undefined, { shallow: true }); + + updateTransform(initialTransform); + window.scrollTo(0, 0); + }; + + const fuse = useMemo( + () => + new Fuse(tools, { keys: ['name'], includeScore: true, threshold: 0.3 }), + [tools], + ); + + const hits = useMemo( + () => + transform.query.trim() === '' + ? tools + : fuse.search(transform.query).map((result) => result.item), + [fuse, transform.query, tools], + ); + + const filteredHits = useMemo( + () => filterTools(hits, transform), + [hits, transform], + ); + + const sortedHits = useMemo( + () => sortTools(filteredHits, transform), + [filteredHits, transform.sortBy, transform.sortOrder], + ); + + const { numberOfTools, toolsByGroup } = useMemo( + () => groupTools(sortedHits, transform), + [sortedHits, transform.groupBy], + ); + + return { + numberOfTools, + tools: sortedHits, + toolsByGroup, + transform, + setTransform: updateTransform, + resetTransform, + }; +} + +const lowerCaseArray = (arr: string[]) => arr.map((item) => item.toLowerCase()); + +const filterTools = ( + tools: JSONSchemaTool[], + transform: Transform, +): JSONSchemaTool[] => { + const lowerCaseTransform = { + languages: lowerCaseArray(transform.languages), + licenses: lowerCaseArray(transform.licenses), + toolingTypes: lowerCaseArray(transform.toolingTypes), + drafts: transform.drafts.map(String), + }; + + return tools.filter((tool) => { + const matchesLanguage = + !lowerCaseTransform.languages.length || + (tool.languages || []).some((lang) => + lowerCaseTransform.languages.includes(lang.toLowerCase()), + ); + + const matchesLicense = + !lowerCaseTransform.licenses.length || + (tool.license && + lowerCaseTransform.licenses.includes(tool.license.toLowerCase())); + + const matchesToolingType = + !lowerCaseTransform.toolingTypes.length || + (tool.toolingTypes || []).some((type) => + lowerCaseTransform.toolingTypes.includes(type.toLowerCase()), + ); + + const matchesDraft = + !lowerCaseTransform.drafts.length || + (tool.supportedDialects?.draft || []).some((draft) => + lowerCaseTransform.drafts.includes(String(draft)), + ); + + return ( + matchesLanguage && matchesLicense && matchesToolingType && matchesDraft + ); + }); +}; + +const sortTools = ( + tools: JSONSchemaTool[], + transform: Transform, +): JSONSchemaTool[] => { + return tools.slice().sort((a, b) => { + let aValue: string | undefined; + let bValue: string | undefined; + + if (transform.sortBy === 'name') { + aValue = a.name.toLowerCase(); + bValue = b.name.toLowerCase(); + } else if (transform.sortBy === 'license') { + aValue = (a.license || '').toLowerCase(); + bValue = (b.license || '').toLowerCase(); + } else if (transform.sortBy === 'bowtie') { + const aHasIdentifier = Boolean(a.bowtie?.identifier); + const bHasIdentifier = Boolean(b.bowtie?.identifier); + + if (transform.sortOrder === 'ascending') { + if (aHasIdentifier && !bHasIdentifier) return -1; + if (!aHasIdentifier && bHasIdentifier) return 1; + } else { + if (aHasIdentifier && !bHasIdentifier) return 1; + if (!aHasIdentifier && bHasIdentifier) return -1; + } + + aValue = (a.bowtie?.identifier || '').toLowerCase(); + bValue = (b.bowtie?.identifier || '').toLowerCase(); + } + + if (aValue === undefined || bValue === undefined) { + return 0; + } + + return transform.sortOrder === 'ascending' + ? aValue.localeCompare(bValue) + : bValue.localeCompare(aValue); + }); +}; + +const groupTools = ( + tools: JSONSchemaTool[], + transform: Transform, +): { + numberOfTools: number; + toolsByGroup: GroupedTools; +} => { + const toolingTypesOrder = [ + 'validator', + 'hyper-schema', + 'benchmarks', + 'documentation', + 'LDO-utility', + 'code-to-schema', + 'data-to-schema', + 'model-to-schema', + 'schema-to-types', + 'schema-to-code', + 'schema-to-web-UI', + 'schema-to-data', + 'util-general-processing', + 'util-schema-to-schema', + 'util-draft-migration', + 'util-format-conversion', + 'util-testing', + 'editor', + 'editor-plugins', + 'schema-repository', + 'linter', + 'linter-plugins', + ]; + + let numberOfTools = 0; + const groupedTools: GroupedTools = {}; + const groupBy = transform.groupBy; + + if (groupBy === 'languages' || groupBy === 'toolingTypes') { + tools.forEach((tool) => { + const groups = tool[groupBy] || []; + if (groups.length > 0) { + groups.forEach((group) => { + if (!groupedTools[group]) groupedTools[group] = []; + groupedTools[group].push(tool); + }); + numberOfTools++; + } + }); + } else { + groupedTools['none'] = tools; + return { + numberOfTools: tools.length, + toolsByGroup: groupedTools, + }; + } + + const sortedGroupedTools = Object.keys(groupedTools) + .sort((a, b) => { + if (groupBy === 'toolingTypes') { + const indexA = toolingTypesOrder.indexOf(a); + const indexB = toolingTypesOrder.indexOf(b); + if (indexA === -1 || indexB === -1) { + return a.toLowerCase().localeCompare(b.toLowerCase()); + } + return indexA - indexB; + } + return a.toLowerCase().localeCompare(b.toLowerCase()); + }) + .reduce((acc, key) => { + acc[key] = groupedTools[key]; + return acc; + }, {} as GroupedTools); + + return { + numberOfTools, + toolsByGroup: sortedGroupedTools, + }; +}; diff --git a/pages/tools/index.page.tsx b/pages/tools/index.page.tsx new file mode 100644 index 000000000..ab35b6ff1 --- /dev/null +++ b/pages/tools/index.page.tsx @@ -0,0 +1,214 @@ +import React, { useState } from 'react'; +import fs from 'fs'; +import Link from 'next/link'; +import Head from 'next/head'; +import yaml from 'js-yaml'; + +import { SectionContext } from '~/context'; +import { Headline1 } from '~/components/Headlines'; +import { getLayout } from '~/components/SiteLayout'; +import { DRAFT_ORDER } from '~/lib/config'; + +import GroupByMenu from './components/GroupByMenu'; +import Sidebar from './components/Sidebar'; +import ToolingTable from './components/ToolingTable'; +import useToolsTransform from './hooks/useToolsTransform'; +import getDistinctEntries from './lib/getDistinctEntries'; +import type { JSONSchemaTool } from './JSONSchemaTool'; + +export type FilterCriteriaFields = + | 'languages' + | 'drafts' + | 'toolingTypes' + | 'licenses'; + +export async function getStaticProps() { + const toolingData = yaml.load( + fs.readFileSync('data/tooling-data.yaml', 'utf-8'), + ) as JSONSchemaTool[]; + + toolingData.forEach((tool) => { + tool.supportedDialects?.draft?.sort((a, b) => { + const aIndex = DRAFT_ORDER.map(String).indexOf(a.toString()); + const bIndex = DRAFT_ORDER.map(String).indexOf(b.toString()); + + if (aIndex === -1 && bIndex === -1) { + return 0; + } else if (aIndex === -1) { + return 1; + } else if (bIndex === -1) { + return -1; + } + + return bIndex - aIndex; + }); + }); + + const filterCriteria = { + languages: getDistinctEntries(toolingData, '$..languages[*]'), + drafts: getDistinctEntries( + toolingData, + '$..supportedDialects.draft[*]', + [1, 2, 3], + ), + toolingTypes: getDistinctEntries(toolingData, '$..toolingTypes[*]'), + licenses: getDistinctEntries(toolingData, '$..license'), + }; + + filterCriteria.drafts?.sort((a, b) => { + const aIndex = DRAFT_ORDER.map(String).indexOf(a.toString()); + const bIndex = DRAFT_ORDER.map(String).indexOf(b.toString()); + + if (aIndex === -1 && bIndex === -1) { + return 0; + } else if (aIndex === -1) { + return 1; + } else if (bIndex === -1) { + return -1; + } + + return aIndex - bIndex; + }); + + return { + props: { + toolingData, + filterCriteria, + }, + }; +} + +interface ToolingPageProps { + toolingData: JSONSchemaTool[]; + filterCriteria: Record; +} + +export default function ToolingPage({ + toolingData, + filterCriteria, +}: ToolingPageProps) { + const [isSidebarOpen, setIsSidebarOpen] = useState(false); + + const { + numberOfTools, + toolsByGroup, + transform, + setTransform, + resetTransform, + } = useToolsTransform(toolingData); + + return ( + + + JSON Schema - Tools + +
+
{ + setIsSidebarOpen((prev) => !prev); + }} + > +

{numberOfTools} Tools

+ + + + +
+ +
+
+
+

+ {numberOfTools} +

+
+ Tools +
+
+ +
+ +
+ JSON Schema Tooling +

+ Toolings below are written in different languages, and support + part, or all, of at least one recent version of the specification. +

+

+ Listing does not signify a recommendation or endorsement of any + kind. +

+
+
+ + + +

+ Raise an issue to get your tool added or updated in the + tooling table. +

+
+ +
+ + + +

+ Bowtie is a meta-validator for JSON Schema implementations and + it provides compliance reports. +

+
+
+ + +
+
+
+
+ ); +} + +ToolingPage.getLayout = getLayout; diff --git a/pages/tools/lib/analytics.schema.json b/pages/tools/lib/analytics.schema.json new file mode 100644 index 000000000..14062aff8 --- /dev/null +++ b/pages/tools/lib/analytics.schema.json @@ -0,0 +1,152 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "JSON Schema Tooling Analytics", + "description": "Schema for JSON Schema Tooling analytics events.", + "type": "object", + "properties": { + "event": { + "description": "The type of event.", + "type": "string", + "enum": ["query", "about"] + }, + "deviceType": { + "description": "The type of device from which the event is being sent.", + "type": "string", + "enum": ["Desktop", "Mobile"] + }, + "payload": { + "description": "The data specific to the event type.", + "type": "object", + "oneOf": [ + { + "description": "Payload for 'query' event.", + "properties": { + "query": { + "description": "The search query string.", + "type": "string" + }, + "groupBy": { + "description": "The field by which the results are grouped.", + "type": "string", + "enum": ["none", "toolingTypes", "languages"] + }, + "sortBy": { + "description": "The field by which the results are sorted.", + "type": "string", + "enum": ["name", "license", "bowtie"] + }, + "sortOrder": { + "description": "The order in which results are sorted.", + "type": "string", + "enum": ["ascending", "descending"] + }, + "languages": { + "description": "The languages selected for filtering.", + "type": "array", + "items": { + "type": "string" + } + }, + "licenses": { + "description": "The licenses selected for filtering.", + "type": "array", + "items": { + "type": "string" + } + }, + "drafts": { + "description": "The drafts selected for filtering.", + "type": "array", + "items": { + "type": "string" + } + }, + "toolingTypes": { + "description": "The tooling types selected for filtering.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + { + "description": "Payload for 'about' event.", + "properties": { + "name": { + "description": "The name of the project.", + "type": "string" + }, + "toolingTypes": { + "description": "The categories of tooling for the project.", + "type": "array", + "items": { + "type": "string" + } + }, + "languages": { + "description": "The language or languages a tool is built in. In the case of a validator, this will likely be the language it is written in. In the case of a conversion or transformation tool, these are the languages that are supported in some capacity.", + "type": "array", + "items": { + "type": "string" + } + }, + "environments": { + "description": "The platforms or environments in which the tool or library is designed to operate. This field is optional and should be included when the tool or library is specific to a certain platform or environment.", + "type": "array", + "items": { + "type": "string" + } + }, + "license": { + "description": "The license under which the project is distributed. SPDX expressions only.", + "type": "array", + "items": { + "type": "string" + } + }, + "supportedDialects": { + "description": "The declared supported dialects of JSON Schema. This includes draft version identifiers.", + "type": "object", + "properties": { + "draft": { + "description": "An array of dialects of JSON Schema.", + "type": "array", + "items": { + "enum": [1, 2, 3, 4, 5, 6, 7, "2019-09", "2020-12"] + } + }, + "additional": { + "description": "Additional Dialects that are supported beyond the ones defined by the JSON Schema project, such as the OpenAPI Dialect.", + "type": "array", + "items": { + "description": "Individual JSON Schema Dialect items", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "homepage": { + "type": "string", + "format": "uri" + }, + "source": { + "type": "string", + "format": "uri" + } + }, + "required": ["name", "source"], + "additionalProperties": false + } + } + }, + "additionalProperties": false + } + } + } + ] + } + }, + "required": ["event", "deviceType", "payload"], + "additionalProperties": false +} diff --git a/pages/tools/lib/getDistinctEntries.ts b/pages/tools/lib/getDistinctEntries.ts new file mode 100644 index 000000000..8e234fab1 --- /dev/null +++ b/pages/tools/lib/getDistinctEntries.ts @@ -0,0 +1,20 @@ +import jsonpath from 'jsonpath'; + +const getDistinctEntries = ( + data: T, + path: string, + exclude: Array = [], +): Array => { + if (!data || typeof data !== 'object') { + throw new Error('Invalid data input. Expected an object or an array.'); + } + if (typeof path !== 'string') { + throw new Error('Invalid path input. Expected a string.'); + } + + const values = Array.from(new Set(jsonpath.query(data, path))); + + return values.filter((value) => !exclude.includes(value)); +}; + +export default getDistinctEntries; diff --git a/pages/tools/lib/postAnalytics.ts b/pages/tools/lib/postAnalytics.ts new file mode 100644 index 000000000..70fc43423 --- /dev/null +++ b/pages/tools/lib/postAnalytics.ts @@ -0,0 +1,56 @@ +import type { JSONSchemaTool } from '../JSONSchemaTool'; +import type { Transform } from '../hooks/useToolsTransform'; + +interface AnalyticsQueryParams { + eventType: 'query'; + eventPayload: Transform; +} + +interface AnalyticsAboutParams { + eventType: 'about'; + eventPayload: AnalyticsAboutPayload; +} + +interface AnalyticsAboutPayload { + name: JSONSchemaTool['name']; + toolingTypes: JSONSchemaTool['toolingTypes']; + languages: JSONSchemaTool['languages']; + environments: JSONSchemaTool['environments']; + license: JSONSchemaTool['license']; + supportedDialects: JSONSchemaTool['supportedDialects']; +} + +type AnalyticsParams = AnalyticsQueryParams | AnalyticsAboutParams; + +export async function postAnalytics({ + eventType, + eventPayload, +}: AnalyticsParams) { + try { + const deviceType = /Mobi/.test(navigator.userAgent) ? 'Mobile' : 'Desktop'; + + const response = await fetch( + 'https://script.google.com/macros/s/AKfycbyKimeFeIfrY8OH2waWajATg-21cdC6PlzZ4iJTsETNQA6854jkQSAyMVv6lDKzCUSs/exec', + { + redirect: 'follow', + method: 'POST', + headers: { + 'Content-Type': 'text/plain;charset=utf-8', + }, + body: JSON.stringify({ + deviceType, + event: eventType, + payload: eventPayload, + }), + }, + ); + + if (!response.ok) { + console.error('Error posting analytics event:', response.statusText); + } else { + console.log('Event posted successfully'); + } + } catch (error) { + console.error('Error posting event:', error); + } +} diff --git a/pages/tools/lib/toTitleCase.ts b/pages/tools/lib/toTitleCase.ts new file mode 100644 index 000000000..364d10fc1 --- /dev/null +++ b/pages/tools/lib/toTitleCase.ts @@ -0,0 +1,12 @@ +export default function toTitleCase( + text: string, + delimiter: string = ' ', + separator: string = ' ', +) { + return text + .split(delimiter) + .map(function (word: string) { + return word.charAt(0).toUpperCase() + word.slice(1); + }) + .join(separator); +} diff --git a/pages/understanding-json-schema/_index.md b/pages/understanding-json-schema/_index.md index 83e5cf183..e5ac9fef9 100644 --- a/pages/understanding-json-schema/_index.md +++ b/pages/understanding-json-schema/_index.md @@ -35,7 +35,7 @@ in the text. - [json-schema.org](http://json-schema.org) has a number of resources, including the official specification and tools for working with JSON Schema from various programming languages. -- There are a number of [online JSON Schema tools](https://json-schema.org/implementations.html#validator-web%20(online)) +- There are a number of [online JSON Schema tools](https://json-schema.org/tools#validator) that allow you to run your own JSON schemas against example documents. These can be very handy if you want to try things out without installing any software. diff --git a/public/_redirects b/public/_redirects index 6282f8c5a..2476aa9c2 100644 --- a/public/_redirects +++ b/public/_redirects @@ -19,7 +19,7 @@ /latest/json-schema-validation /draft/2020-12/json-schema-validation 301 /latest/relative-json-pointer /draft/2020-12/relative-json-pointer.html 301 /latest/release-notes /draft/2020-12/release-notes -/tools /implementations 301 +/implementations /tools 301 /slack https://join.slack.com/t/json-schema/shared_invite/zt-2n5bzzgx3-ro3V0mnnzUoaguILLosT2A 301 /slack-redirect https://join.slack.com/t/json-schema/shared_invite/zt-2n5bzzgx3-ro3V0mnnzUoaguILLosT2A 301 /ambassadors https://github.com/json-schema-org/community/tree/main/programs/ambassadors 301 diff --git a/public/icons/filter.svg b/public/icons/filter.svg index 1d92e8eb2..67bfd3419 100644 --- a/public/icons/filter.svg +++ b/public/icons/filter.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/public/icons/outlink.svg b/public/icons/outlink.svg new file mode 100644 index 000000000..fd931774c --- /dev/null +++ b/public/icons/outlink.svg @@ -0,0 +1,9 @@ + + + + diff --git a/public/img/tools/adding_your_tool.png b/public/img/tools/adding_your_tool.png new file mode 100644 index 000000000..fd1bd6857 Binary files /dev/null and b/public/img/tools/adding_your_tool.png differ diff --git a/public/img/tools/logos/json-everything.svg b/public/img/tools/logos/json-everything.svg new file mode 100644 index 000000000..3113bb3d4 --- /dev/null +++ b/public/img/tools/logos/json-everything.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/img/tools/try_bowtie.png b/public/img/tools/try_bowtie.png new file mode 100644 index 000000000..371cb88a5 Binary files /dev/null and b/public/img/tools/try_bowtie.png differ diff --git a/styles/globals.css b/styles/globals.css index b028c23c3..463c04848 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -270,3 +270,22 @@ border-radius: 4px; */ @apply dark:bg-slate-800 bg-white; } } + +.no-scroll { + overflow: hidden; +} + +.tools-dropdown-menu::-webkit-scrollbar { + width: 0.5rem; + height: 5px; +} + +.tools-dropdown-menu::-webkit-scrollbar-track { + background: white; + border-radius: 8px; +} + +.tools-dropdown-menu::-webkit-scrollbar-thumb { + background: grey; + border-radius: 8px; +} diff --git a/svgr.d.ts b/svgr.d.ts new file mode 100644 index 000000000..eac810e99 --- /dev/null +++ b/svgr.d.ts @@ -0,0 +1,10 @@ +declare module '*.svg' { + import { FC, SVGProps } from 'react'; + const content: FC>; + export default content; +} + +declare module '*.svg?url' { + const content: any; + export default content; +} diff --git a/tsconfig.json b/tsconfig.json index 3e3772e64..746d414d5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,6 +21,6 @@ "@public/*": ["./public/*"] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "include": ["next-env.d.ts", "svgr.d.ts", "**/*.ts", "**/*.tsx"], "exclude": ["node_modules"] } diff --git a/yarn.lock b/yarn.lock index 84bb19d8b..c346321be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -204,7 +204,7 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.24.7": +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.24.7": version: 7.24.7 resolution: "@babel/code-frame@npm:7.24.7" dependencies: @@ -228,6 +228,29 @@ __metadata: languageName: node linkType: hard +"@babel/core@npm:^7.21.3, @babel/core@npm:^7.25.2": + version: 7.25.2 + resolution: "@babel/core@npm:7.25.2" + dependencies: + "@ampproject/remapping": "npm:^2.2.0" + "@babel/code-frame": "npm:^7.24.7" + "@babel/generator": "npm:^7.25.0" + "@babel/helper-compilation-targets": "npm:^7.25.2" + "@babel/helper-module-transforms": "npm:^7.25.2" + "@babel/helpers": "npm:^7.25.0" + "@babel/parser": "npm:^7.25.0" + "@babel/template": "npm:^7.25.0" + "@babel/traverse": "npm:^7.25.2" + "@babel/types": "npm:^7.25.2" + convert-source-map: "npm:^2.0.0" + debug: "npm:^4.1.0" + gensync: "npm:^1.0.0-beta.2" + json5: "npm:^2.2.3" + semver: "npm:^6.3.1" + checksum: 10c0/a425fa40e73cb72b6464063a57c478bc2de9dbcc19c280f1b55a3d88b35d572e87e8594e7d7b4880331addb6faef641bbeb701b91b41b8806cd4deae5d74f401 + languageName: node + linkType: hard + "@babel/core@npm:^7.23.9, @babel/core@npm:^7.7.5": version: 7.24.9 resolution: "@babel/core@npm:7.24.9" @@ -251,29 +274,6 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.25.2": - version: 7.25.2 - resolution: "@babel/core@npm:7.25.2" - dependencies: - "@ampproject/remapping": "npm:^2.2.0" - "@babel/code-frame": "npm:^7.24.7" - "@babel/generator": "npm:^7.25.0" - "@babel/helper-compilation-targets": "npm:^7.25.2" - "@babel/helper-module-transforms": "npm:^7.25.2" - "@babel/helpers": "npm:^7.25.0" - "@babel/parser": "npm:^7.25.0" - "@babel/template": "npm:^7.25.0" - "@babel/traverse": "npm:^7.25.2" - "@babel/types": "npm:^7.25.2" - convert-source-map: "npm:^2.0.0" - debug: "npm:^4.1.0" - gensync: "npm:^1.0.0-beta.2" - json5: "npm:^2.2.3" - semver: "npm:^6.3.1" - checksum: 10c0/a425fa40e73cb72b6464063a57c478bc2de9dbcc19c280f1b55a3d88b35d572e87e8594e7d7b4880331addb6faef641bbeb701b91b41b8806cd4deae5d74f401 - languageName: node - linkType: hard - "@babel/generator@npm:^7.24.9, @babel/generator@npm:^7.25.0": version: 7.25.0 resolution: "@babel/generator@npm:7.25.0" @@ -331,7 +331,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.24.7": +"@babel/helper-create-class-features-plugin@npm:^7.24.7, @babel/helper-create-class-features-plugin@npm:^7.25.0": version: 7.25.0 resolution: "@babel/helper-create-class-features-plugin@npm:7.25.0" dependencies: @@ -500,7 +500,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-option@npm:^7.24.8": +"@babel/helper-validator-option@npm:^7.24.7, @babel/helper-validator-option@npm:^7.24.8": version: 7.24.8 resolution: "@babel/helper-validator-option@npm:7.24.8" checksum: 10c0/73db93a34ae89201351288bee7623eed81a54000779462a986105b54ffe82069e764afd15171a428b82e7c7a9b5fec10b5d5603b216317a414062edf5c67a21f @@ -727,6 +727,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-jsx@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-syntax-jsx@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.24.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/f44d927a9ae8d5ef016ff5b450e1671e56629ddc12e56b938e41fd46e141170d9dfc9a53d6cb2b9a20a7dd266a938885e6a3981c60c052a2e1daed602ac80e51 + languageName: node + linkType: hard + "@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4": version: 7.10.4 resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" @@ -815,6 +826,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-typescript@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-syntax-typescript@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.24.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/cdabd2e8010fb0ad15b49c2c270efc97c4bfe109ead36c7bbcf22da7a74bc3e49702fc4f22f12d2d6049e8e22a5769258df1fd05f0420ae45e11bdd5bc07805a + languageName: node + linkType: hard + "@babel/plugin-syntax-unicode-sets-regex@npm:^7.18.6": version: 7.18.6 resolution: "@babel/plugin-syntax-unicode-sets-regex@npm:7.18.6" @@ -1105,7 +1127,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-modules-commonjs@npm:^7.24.8": +"@babel/plugin-transform-modules-commonjs@npm:^7.24.7, @babel/plugin-transform-modules-commonjs@npm:^7.24.8": version: 7.24.8 resolution: "@babel/plugin-transform-modules-commonjs@npm:7.24.8" dependencies: @@ -1290,6 +1312,66 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-react-constant-elements@npm:^7.21.3": + version: 7.25.1 + resolution: "@babel/plugin-transform-react-constant-elements@npm:7.25.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.24.8" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/8e9a61e8d74804ad3e4c8051463b2d8c42be5aa1f381f7b0db3ac8696a5cb5faead54036b1e4bcd53f6ab74c0bb3e45e4d9a1a2f50b9a575a8d7965b77d89c28 + languageName: node + linkType: hard + +"@babel/plugin-transform-react-display-name@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-react-display-name@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.24.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/c14a07a9e75723c96f1a0a306b8a8e899ff1c6a0cc3d62bcda79bb1b54e4319127b258651c513a1a47da152cdc22e16525525a30ae5933a2980c7036fd0b4d24 + languageName: node + linkType: hard + +"@babel/plugin-transform-react-jsx-development@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-react-jsx-development@npm:7.24.7" + dependencies: + "@babel/plugin-transform-react-jsx": "npm:^7.24.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/fce647db50f90a5291681f0f97865d9dc76981262dff71d6d0332e724b85343de5860c26f9e9a79e448d61e1d70916b07ce91e8c7f2b80dceb4b16aee41794d8 + languageName: node + linkType: hard + +"@babel/plugin-transform-react-jsx@npm:^7.24.7": + version: 7.25.2 + resolution: "@babel/plugin-transform-react-jsx@npm:7.25.2" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.24.7" + "@babel/helper-module-imports": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/plugin-syntax-jsx": "npm:^7.24.7" + "@babel/types": "npm:^7.25.2" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/8c5b515f38118471197605e02bea54a8a4283010e3c55bad8cfb78de59ad63612b14d40baca63689afdc9d57b147aac4c7794fe5f7736c9e1ed6dd38784be624 + languageName: node + linkType: hard + +"@babel/plugin-transform-react-pure-annotations@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.24.7" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/fae517d293d9c93b7b920458c3e4b91cb0400513889af41ba184a5f3acc8bfef27242cc262741bb8f87870df376f1733a0d0f52b966d342e2aaaf5607af8f73d + languageName: node + linkType: hard + "@babel/plugin-transform-regenerator@npm:^7.24.7": version: 7.24.7 resolution: "@babel/plugin-transform-regenerator@npm:7.24.7" @@ -1369,6 +1451,21 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-typescript@npm:^7.24.7": + version: 7.25.2 + resolution: "@babel/plugin-transform-typescript@npm:7.25.2" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.24.7" + "@babel/helper-create-class-features-plugin": "npm:^7.25.0" + "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.24.7" + "@babel/plugin-syntax-typescript": "npm:^7.24.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/b3c941da39ee7ecf72df1b78a01d4108160438245f2ab61befe182f51d17fd0034733c6d079b7efad81e03a66438aa3881a671cd68c5eb0fc775df86b88df996 + languageName: node + linkType: hard + "@babel/plugin-transform-unicode-escapes@npm:^7.24.7": version: 7.24.7 resolution: "@babel/plugin-transform-unicode-escapes@npm:7.24.7" @@ -1416,7 +1513,7 @@ __metadata: languageName: node linkType: hard -"@babel/preset-env@npm:^7.25.3": +"@babel/preset-env@npm:^7.20.2, @babel/preset-env@npm:^7.25.3": version: 7.25.3 resolution: "@babel/preset-env@npm:7.25.3" dependencies: @@ -1522,6 +1619,37 @@ __metadata: languageName: node linkType: hard +"@babel/preset-react@npm:^7.18.6": + version: 7.24.7 + resolution: "@babel/preset-react@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-validator-option": "npm:^7.24.7" + "@babel/plugin-transform-react-display-name": "npm:^7.24.7" + "@babel/plugin-transform-react-jsx": "npm:^7.24.7" + "@babel/plugin-transform-react-jsx-development": "npm:^7.24.7" + "@babel/plugin-transform-react-pure-annotations": "npm:^7.24.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/9658b685b25cedaadd0b65c4e663fbc7f57394b5036ddb4c99b1a75b0711fb83292c1c625d605c05b73413fc7a6dc20e532627f6a39b6dc8d4e00415479b054c + languageName: node + linkType: hard + +"@babel/preset-typescript@npm:^7.21.0": + version: 7.24.7 + resolution: "@babel/preset-typescript@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-validator-option": "npm:^7.24.7" + "@babel/plugin-syntax-jsx": "npm:^7.24.7" + "@babel/plugin-transform-modules-commonjs": "npm:^7.24.7" + "@babel/plugin-transform-typescript": "npm:^7.24.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/986bc0978eedb4da33aba8e1e13a3426dd1829515313b7e8f4ba5d8c18aff1663b468939d471814e7acf4045d326ae6cff37239878d169ac3fe53a8fde71f8ee + languageName: node + linkType: hard + "@babel/regjsgen@npm:^0.8.0": version: 0.8.0 resolution: "@babel/regjsgen@npm:0.8.0" @@ -1588,7 +1716,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.24.8, @babel/types@npm:^7.25.2, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.3, @babel/types@npm:^7.24.8, @babel/types@npm:^7.25.2, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": version: 7.25.2 resolution: "@babel/types@npm:7.25.2" dependencies: @@ -2076,6 +2204,162 @@ __metadata: languageName: node linkType: hard +"@svgr/babel-plugin-add-jsx-attribute@npm:8.0.0": + version: 8.0.0 + resolution: "@svgr/babel-plugin-add-jsx-attribute@npm:8.0.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/a50bd0baa34faf16bcba712091f94c7f0e230431fe99a9dfc3401fa92823ad3f68495b86ab9bf9044b53839e8c416cfbb37eb3f246ff33f261e0fa9ee1779c5b + languageName: node + linkType: hard + +"@svgr/babel-plugin-remove-jsx-attribute@npm:8.0.0": + version: 8.0.0 + resolution: "@svgr/babel-plugin-remove-jsx-attribute@npm:8.0.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/8a98e59bd9971e066815b4129409932f7a4db4866834fe75677ea6d517972fb40b380a69a4413189f20e7947411f9ab1b0f029dd5e8068686a5a0188d3ccd4c7 + languageName: node + linkType: hard + +"@svgr/babel-plugin-remove-jsx-empty-expression@npm:8.0.0": + version: 8.0.0 + resolution: "@svgr/babel-plugin-remove-jsx-empty-expression@npm:8.0.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/517dcca75223bd05d3f056a8514dbba3031278bea4eadf0842c576d84f4651e7a4e0e7082d3ee4ef42456de0f9c4531d8a1917c04876ca64b014b859ca8f1bde + languageName: node + linkType: hard + +"@svgr/babel-plugin-replace-jsx-attribute-value@npm:8.0.0": + version: 8.0.0 + resolution: "@svgr/babel-plugin-replace-jsx-attribute-value@npm:8.0.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/004bd1892053b7e9c1b0bb14acc44e77634ec393722b87b1e4fae53e2c35122a2dd0d5c15e9070dbeec274e22e7693a2b8b48506733a8009ee92b12946fcb10a + languageName: node + linkType: hard + +"@svgr/babel-plugin-svg-dynamic-title@npm:8.0.0": + version: 8.0.0 + resolution: "@svgr/babel-plugin-svg-dynamic-title@npm:8.0.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/80e0a7fcf902f984c705051ca5c82ea6050ccbb70b651a8fea6d0eb5809e4dac274b49ea6be2d87f1eb9dfc0e2d6cdfffe1669ec2117f44b67a60a07d4c0b8b8 + languageName: node + linkType: hard + +"@svgr/babel-plugin-svg-em-dimensions@npm:8.0.0": + version: 8.0.0 + resolution: "@svgr/babel-plugin-svg-em-dimensions@npm:8.0.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/73e92c8277a89279745c0c500f59f083279a8dc30cd552b22981fade2a77628fb2bd2819ee505725fcd2e93f923e3790b52efcff409a159e657b46604a0b9a21 + languageName: node + linkType: hard + +"@svgr/babel-plugin-transform-react-native-svg@npm:8.1.0": + version: 8.1.0 + resolution: "@svgr/babel-plugin-transform-react-native-svg@npm:8.1.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/655ed6bc7a208ceaa4ecff0a54ccc36008c3cb31efa90d11e171cab325ebbb21aa78f09c7b65f9b3ddeda3a85f348c0c862902c48be13c14b4de165c847974e3 + languageName: node + linkType: hard + +"@svgr/babel-plugin-transform-svg-component@npm:8.0.0": + version: 8.0.0 + resolution: "@svgr/babel-plugin-transform-svg-component@npm:8.0.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/4ac00bb99a3db4ef05e4362f116a3c608ee365a2d26cf7318d8d41a4a5b30a02c80455cce0e62c65b60ed815b5d632bedabac2ccd4b56f998fadef5286e3ded4 + languageName: node + linkType: hard + +"@svgr/babel-preset@npm:8.1.0": + version: 8.1.0 + resolution: "@svgr/babel-preset@npm:8.1.0" + dependencies: + "@svgr/babel-plugin-add-jsx-attribute": "npm:8.0.0" + "@svgr/babel-plugin-remove-jsx-attribute": "npm:8.0.0" + "@svgr/babel-plugin-remove-jsx-empty-expression": "npm:8.0.0" + "@svgr/babel-plugin-replace-jsx-attribute-value": "npm:8.0.0" + "@svgr/babel-plugin-svg-dynamic-title": "npm:8.0.0" + "@svgr/babel-plugin-svg-em-dimensions": "npm:8.0.0" + "@svgr/babel-plugin-transform-react-native-svg": "npm:8.1.0" + "@svgr/babel-plugin-transform-svg-component": "npm:8.0.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/49367d3ad0831f79b1056871b91766246f449d4d1168623af5e283fbaefce4a01d77ab00de6b045b55e956f9aae27895823198493cd232d88d3435ea4517ffc5 + languageName: node + linkType: hard + +"@svgr/core@npm:8.1.0": + version: 8.1.0 + resolution: "@svgr/core@npm:8.1.0" + dependencies: + "@babel/core": "npm:^7.21.3" + "@svgr/babel-preset": "npm:8.1.0" + camelcase: "npm:^6.2.0" + cosmiconfig: "npm:^8.1.3" + snake-case: "npm:^3.0.4" + checksum: 10c0/6a2f6b1bc79bce39f66f088d468985d518005fc5147ebf4f108570a933818b5951c2cb7da230ddff4b7c8028b5a672b2d33aa2acce012b8b9770073aa5a2d041 + languageName: node + linkType: hard + +"@svgr/hast-util-to-babel-ast@npm:8.0.0": + version: 8.0.0 + resolution: "@svgr/hast-util-to-babel-ast@npm:8.0.0" + dependencies: + "@babel/types": "npm:^7.21.3" + entities: "npm:^4.4.0" + checksum: 10c0/f4165b583ba9eaf6719e598977a7b3ed182f177983e55f9eb55a6a73982d81277510e9eb7ab41f255151fb9ed4edd11ac4bef95dd872f04ed64966d8c85e0f79 + languageName: node + linkType: hard + +"@svgr/plugin-jsx@npm:8.1.0": + version: 8.1.0 + resolution: "@svgr/plugin-jsx@npm:8.1.0" + dependencies: + "@babel/core": "npm:^7.21.3" + "@svgr/babel-preset": "npm:8.1.0" + "@svgr/hast-util-to-babel-ast": "npm:8.0.0" + svg-parser: "npm:^2.0.4" + peerDependencies: + "@svgr/core": "*" + checksum: 10c0/07b4d9e00de795540bf70556fa2cc258774d01e97a12a26234c6fdf42b309beb7c10f31ee24d1a71137239347b1547b8bb5587d3a6de10669f95dcfe99cddc56 + languageName: node + linkType: hard + +"@svgr/plugin-svgo@npm:8.1.0": + version: 8.1.0 + resolution: "@svgr/plugin-svgo@npm:8.1.0" + dependencies: + cosmiconfig: "npm:^8.1.3" + deepmerge: "npm:^4.3.1" + svgo: "npm:^3.0.2" + peerDependencies: + "@svgr/core": "*" + checksum: 10c0/bfd25460f23f1548bfb8f6f3bedd6d6972c1a4f8881bd35a4f8c115218da6e999e8f9ac0ef0ed88c4e0b93fcec37f382b94c0322f4ec2b26752a89e5cc8b9d7a + languageName: node + linkType: hard + +"@svgr/webpack@npm:^8.1.0": + version: 8.1.0 + resolution: "@svgr/webpack@npm:8.1.0" + dependencies: + "@babel/core": "npm:^7.21.3" + "@babel/plugin-transform-react-constant-elements": "npm:^7.21.3" + "@babel/preset-env": "npm:^7.20.2" + "@babel/preset-react": "npm:^7.18.6" + "@babel/preset-typescript": "npm:^7.21.0" + "@svgr/core": "npm:8.1.0" + "@svgr/plugin-jsx": "npm:8.1.0" + "@svgr/plugin-svgo": "npm:8.1.0" + checksum: 10c0/4c1cac45bd5890de8643e5a7bfb71f3bcd8b85ae5bbacf10b8ad9f939b7a98e8d601c3ada204ffb95223abf4a24beeac5a2a0d6928a52a1ab72a29da3c015c22 + languageName: node + linkType: hard + "@swc/counter@npm:^0.1.3": version: 0.1.3 resolution: "@swc/counter@npm:0.1.3" @@ -2093,6 +2377,13 @@ __metadata: languageName: node linkType: hard +"@trysound/sax@npm:0.2.0": + version: 0.2.0 + resolution: "@trysound/sax@npm:0.2.0" + checksum: 10c0/44907308549ce775a41c38a815f747009ac45929a45d642b836aa6b0a536e4978d30b8d7d680bbd116e9dd73b7dbe2ef0d1369dcfc2d09e83ba381e485ecbe12 + languageName: node + linkType: hard + "@types/babel__core@npm:^7": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" @@ -2205,6 +2496,13 @@ __metadata: languageName: node linkType: hard +"@types/jsonpath@npm:^0.2.4": + version: 0.2.4 + resolution: "@types/jsonpath@npm:0.2.4" + checksum: 10c0/3fdf725e5db61a0abb0afa95667e561a0e5f3604f30b609497af135606f4721449d7235ca8304da4984fb2ac4f6d290ad49de5ad6878740555542ddd28ee0b69 + languageName: node + linkType: hard + "@types/node@npm:*": version: 20.14.12 resolution: "@types/node@npm:20.14.12" @@ -3310,6 +3608,13 @@ __metadata: languageName: node linkType: hard +"boolbase@npm:^1.0.0": + version: 1.0.0 + resolution: "boolbase@npm:1.0.0" + checksum: 10c0/e4b53deb4f2b85c52be0e21a273f2045c7b6a6ea002b0e139c744cb6f95e9ec044439a52883b0d74dedd1ff3da55ed140cfdddfed7fb0cccbed373de5dce1bcf + languageName: node + linkType: hard + "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -3513,6 +3818,13 @@ __metadata: languageName: node linkType: hard +"camelcase@npm:^6.2.0": + version: 6.3.0 + resolution: "camelcase@npm:6.3.0" + checksum: 10c0/0d701658219bd3116d12da3eab31acddb3f9440790c0792e0d398f0a520a6a4058018e546862b6fba89d7ae990efaeb97da71e1913e9ebf5a8b5621a3d55c710 + languageName: node + linkType: hard + "caniuse-lite@npm:^1.0.30001541, caniuse-lite@npm:^1.0.30001579": version: 1.0.30001627 resolution: "caniuse-lite@npm:1.0.30001627" @@ -3770,6 +4082,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:^7.2.0": + version: 7.2.0 + resolution: "commander@npm:7.2.0" + checksum: 10c0/8d690ff13b0356df7e0ebbe6c59b4712f754f4b724d4f473d3cc5b3fdcf978e3a5dc3078717858a2ceb50b0f84d0660a7f22a96cdc50fb877d0c9bb31593d23a + languageName: node + linkType: hard + "common-path-prefix@npm:^3.0.0": version: 3.0.0 resolution: "common-path-prefix@npm:3.0.0" @@ -3842,6 +4161,23 @@ __metadata: languageName: node linkType: hard +"cosmiconfig@npm:^8.1.3": + version: 8.3.6 + resolution: "cosmiconfig@npm:8.3.6" + dependencies: + import-fresh: "npm:^3.3.0" + js-yaml: "npm:^4.1.0" + parse-json: "npm:^5.2.0" + path-type: "npm:^4.0.0" + peerDependencies: + typescript: ">=4.9.5" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/0382a9ed13208f8bfc22ca2f62b364855207dffdb73dc26e150ade78c3093f1cf56172df2dd460c8caf2afa91c0ed4ec8a88c62f8f9cd1cf423d26506aa8797a + languageName: node + linkType: hard + "cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" @@ -3853,6 +4189,46 @@ __metadata: languageName: node linkType: hard +"css-select@npm:^5.1.0": + version: 5.1.0 + resolution: "css-select@npm:5.1.0" + dependencies: + boolbase: "npm:^1.0.0" + css-what: "npm:^6.1.0" + domhandler: "npm:^5.0.2" + domutils: "npm:^3.0.1" + nth-check: "npm:^2.0.1" + checksum: 10c0/551c60dba5b54054741032c1793b5734f6ba45e23ae9e82761a3c0ed1acbb8cfedfa443aaba3a3c1a54cac12b456d2012a09d2cd5f0e82e430454c1b9d84d500 + languageName: node + linkType: hard + +"css-tree@npm:^2.3.1": + version: 2.3.1 + resolution: "css-tree@npm:2.3.1" + dependencies: + mdn-data: "npm:2.0.30" + source-map-js: "npm:^1.0.1" + checksum: 10c0/6f8c1a11d5e9b14bf02d10717fc0351b66ba12594166f65abfbd8eb8b5b490dd367f5c7721db241a3c792d935fc6751fbc09f7e1598d421477ad9fadc30f4f24 + languageName: node + linkType: hard + +"css-tree@npm:~2.2.0": + version: 2.2.1 + resolution: "css-tree@npm:2.2.1" + dependencies: + mdn-data: "npm:2.0.28" + source-map-js: "npm:^1.0.1" + checksum: 10c0/47e87b0f02f8ac22f57eceb65c58011dd142d2158128882a0bf963cf2eabb81a4ebbc2e3790c8289be7919fa8b83750c7b69272bd66772c708143b772ba3c186 + languageName: node + linkType: hard + +"css-what@npm:^6.1.0": + version: 6.1.0 + resolution: "css-what@npm:6.1.0" + checksum: 10c0/a09f5a6b14ba8dcf57ae9a59474722e80f20406c53a61e9aedb0eedc693b135113ffe2983f4efc4b5065ae639442e9ae88df24941ef159c218b231011d733746 + languageName: node + linkType: hard + "cssesc@npm:^3.0.0": version: 3.0.0 resolution: "cssesc@npm:3.0.0" @@ -3862,6 +4238,15 @@ __metadata: languageName: node linkType: hard +"csso@npm:^5.0.5": + version: 5.0.5 + resolution: "csso@npm:5.0.5" + dependencies: + css-tree: "npm:~2.2.0" + checksum: 10c0/ab4beb1e97dd7e207c10e9925405b45f15a6cd1b4880a8686ad573aa6d476aed28b4121a666cffd26c37a26179f7b54741f7c257543003bfb244d06a62ad569b + languageName: node + linkType: hard + "csstype@npm:^3.0.2": version: 3.1.2 resolution: "csstype@npm:3.1.2" @@ -4029,13 +4414,20 @@ __metadata: languageName: node linkType: hard -"deep-is@npm:^0.1.3": +"deep-is@npm:^0.1.3, deep-is@npm:~0.1.3": version: 0.1.4 resolution: "deep-is@npm:0.1.4" checksum: 10c0/7f0ee496e0dff14a573dc6127f14c95061b448b87b995fc96c017ce0a1e66af1675e73f1d6064407975bc4ea6ab679497a29fff7b5b9c4e99cb10797c1ad0b4c languageName: node linkType: hard +"deepmerge@npm:^4.3.1": + version: 4.3.1 + resolution: "deepmerge@npm:4.3.1" + checksum: 10c0/e53481aaf1aa2c4082b5342be6b6d8ad9dfe387bc92ce197a66dea08bd4265904a087e75e464f14d1347cf2ac8afe1e4c16b266e0561cc5df29382d3c5f80044 + languageName: node + linkType: hard + "default-require-extensions@npm:^3.0.0": version: 3.0.1 resolution: "default-require-extensions@npm:3.0.1" @@ -4142,6 +4534,54 @@ __metadata: languageName: node linkType: hard +"dom-serializer@npm:^2.0.0": + version: 2.0.0 + resolution: "dom-serializer@npm:2.0.0" + dependencies: + domelementtype: "npm:^2.3.0" + domhandler: "npm:^5.0.2" + entities: "npm:^4.2.0" + checksum: 10c0/d5ae2b7110ca3746b3643d3ef60ef823f5f078667baf530cec096433f1627ec4b6fa8c072f09d079d7cda915fd2c7bc1b7b935681e9b09e591e1e15f4040b8e2 + languageName: node + linkType: hard + +"domelementtype@npm:^2.3.0": + version: 2.3.0 + resolution: "domelementtype@npm:2.3.0" + checksum: 10c0/686f5a9ef0fff078c1412c05db73a0dce096190036f33e400a07e2a4518e9f56b1e324f5c576a0a747ef0e75b5d985c040b0d51945ce780c0dd3c625a18cd8c9 + languageName: node + linkType: hard + +"domhandler@npm:^5.0.2, domhandler@npm:^5.0.3": + version: 5.0.3 + resolution: "domhandler@npm:5.0.3" + dependencies: + domelementtype: "npm:^2.3.0" + checksum: 10c0/bba1e5932b3e196ad6862286d76adc89a0dbf0c773e5ced1eb01f9af930c50093a084eff14b8de5ea60b895c56a04d5de8bbc4930c5543d029091916770b2d2a + languageName: node + linkType: hard + +"domutils@npm:^3.0.1": + version: 3.1.0 + resolution: "domutils@npm:3.1.0" + dependencies: + dom-serializer: "npm:^2.0.0" + domelementtype: "npm:^2.3.0" + domhandler: "npm:^5.0.3" + checksum: 10c0/342d64cf4d07b8a0573fb51e0a6312a88fb520c7fefd751870bf72fa5fc0f2e0cb9a3958a573610b1d608c6e2a69b8e9b4b40f0bfb8f87a71bce4f180cca1887 + languageName: node + linkType: hard + +"dot-case@npm:^3.0.4": + version: 3.0.4 + resolution: "dot-case@npm:3.0.4" + dependencies: + no-case: "npm:^3.0.4" + tslib: "npm:^2.0.3" + checksum: 10c0/5b859ea65097a7ea870e2c91b5768b72ddf7fa947223fd29e167bcdff58fe731d941c48e47a38ec8aa8e43044c8fbd15cd8fa21689a526bc34b6548197cd5b05 + languageName: node + linkType: hard + "eastasianwidth@npm:^0.2.0": version: 0.2.0 resolution: "eastasianwidth@npm:0.2.0" @@ -4242,6 +4682,13 @@ __metadata: languageName: node linkType: hard +"entities@npm:^4.2.0, entities@npm:^4.4.0": + version: 4.5.0 + resolution: "entities@npm:4.5.0" + checksum: 10c0/5b039739f7621f5d1ad996715e53d964035f75ad3b9a4d38c6b3804bb226e282ffeae2443624d8fdd9c47d8e926ae9ac009c54671243f0c3294c26af7cc85250 + languageName: node + linkType: hard + "env-paths@npm:^2.2.0": version: 2.2.1 resolution: "env-paths@npm:2.2.1" @@ -4256,6 +4703,15 @@ __metadata: languageName: node linkType: hard +"error-ex@npm:^1.3.1": + version: 1.3.2 + resolution: "error-ex@npm:1.3.2" + dependencies: + is-arrayish: "npm:^0.2.1" + checksum: 10c0/ba827f89369b4c93382cfca5a264d059dfefdaa56ecc5e338ffa58a6471f5ed93b71a20add1d52290a4873d92381174382658c885ac1a2305f7baca363ce9cce + languageName: node + linkType: hard + "es-abstract@npm:^1.17.5, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3": version: 1.23.3 resolution: "es-abstract@npm:1.23.3" @@ -4488,6 +4944,25 @@ __metadata: languageName: node linkType: hard +"escodegen@npm:^1.8.1": + version: 1.14.3 + resolution: "escodegen@npm:1.14.3" + dependencies: + esprima: "npm:^4.0.1" + estraverse: "npm:^4.2.0" + esutils: "npm:^2.0.2" + optionator: "npm:^0.8.1" + source-map: "npm:~0.6.1" + dependenciesMeta: + source-map: + optional: true + bin: + escodegen: bin/escodegen.js + esgenerate: bin/esgenerate.js + checksum: 10c0/30d337803e8f44308c90267bf6192399e4b44792497c77a7506b68ab802ba6a48ebbe1ce77b219aba13dfd2de5f5e1c267e35be1ed87b2a9c3315e8b283e302a + languageName: node + linkType: hard + "eslint-compat-utils@npm:^0.5.1": version: 0.5.1 resolution: "eslint-compat-utils@npm:0.5.1" @@ -4732,12 +5207,12 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-promise@npm:^7.1.0": - version: 7.1.0 - resolution: "eslint-plugin-promise@npm:7.1.0" +"eslint-plugin-promise@npm:^6.0.0": + version: 6.6.0 + resolution: "eslint-plugin-promise@npm:6.6.0" peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 - checksum: 10c0/bbc3406139715dfa5f48d04f6d5b5e82f68929d954b0fa3821eb8cd6dc381b210512cedd2d874e5de5381005d316566f4ae046a4750ce3f5f5cbf28a14cc0ab2 + checksum: 10c0/93a667dbc9ff15c4d586b0d40a31c7828314cbbb31b2b9a75802aa4ef536e9457bb3e1a89b384b07aa336dd61b315ae8b0aadc0870210378023dd018819b59b3 languageName: node linkType: hard @@ -4880,7 +5355,17 @@ __metadata: languageName: node linkType: hard -"esprima@npm:^4.0.0": +"esprima@npm:1.2.2": + version: 1.2.2 + resolution: "esprima@npm:1.2.2" + bin: + esparse: ./bin/esparse.js + esvalidate: ./bin/esvalidate.js + checksum: 10c0/a5a8fd359651dd8228736d7352eb7636c7765e1ec6ff8fff3f6641622039a9f51fa501969a1a4777ba4187cf9942a8d7e0367dccaff768b782bdb1a71d046abf + languageName: node + linkType: hard + +"esprima@npm:^4.0.0, esprima@npm:^4.0.1": version: 4.0.1 resolution: "esprima@npm:4.0.1" bin: @@ -4908,7 +5393,7 @@ __metadata: languageName: node linkType: hard -"estraverse@npm:^4.1.1": +"estraverse@npm:^4.1.1, estraverse@npm:^4.2.0": version: 4.3.0 resolution: "estraverse@npm:4.3.0" checksum: 10c0/9cb46463ef8a8a4905d3708a652d60122a0c20bb58dec7e0e12ab0e7235123d74214fc0141d743c381813e1b992767e2708194f6f6e0f9fd00c1b4e0887b8b6d @@ -5057,7 +5542,7 @@ __metadata: languageName: node linkType: hard -"fast-levenshtein@npm:^2.0.6": +"fast-levenshtein@npm:^2.0.6, fast-levenshtein@npm:~2.0.6": version: 2.0.6 resolution: "fast-levenshtein@npm:2.0.6" checksum: 10c0/111972b37338bcb88f7d9e2c5907862c280ebf4234433b95bc611e518d192ccb2d38119c4ac86e26b668d75f7f3894f4ff5c4982899afced7ca78633b08287c4 @@ -5381,6 +5866,13 @@ __metadata: languageName: node linkType: hard +"fuse.js@npm:^7.0.0": + version: 7.0.0 + resolution: "fuse.js@npm:7.0.0" + checksum: 10c0/3574b7fc2e0ccb047e05dbe5f8f04e8f0754f62fa209669ef426ea1354a32ae7355620788af8f1d29f94e1fdecd513f1f3787f012848a31ec90bb4e0e6092504 + languageName: node + linkType: hard + "gensync@npm:^1.0.0-beta.2": version: 1.0.0-beta.2 resolution: "gensync@npm:1.0.0-beta.2" @@ -5873,7 +6365,7 @@ __metadata: languageName: node linkType: hard -"import-fresh@npm:^3.2.1": +"import-fresh@npm:^3.2.1, import-fresh@npm:^3.3.0": version: 3.3.0 resolution: "import-fresh@npm:3.3.0" dependencies: @@ -5991,6 +6483,13 @@ __metadata: languageName: node linkType: hard +"is-arrayish@npm:^0.2.1": + version: 0.2.1 + resolution: "is-arrayish@npm:0.2.1" + checksum: 10c0/e7fb686a739068bb70f860b39b67afc62acc62e36bb61c5f965768abce1873b379c563e61dd2adad96ebb7edf6651111b385e490cf508378959b0ed4cac4e729 + languageName: node + linkType: hard + "is-async-function@npm:^2.0.0": version: 2.0.0 resolution: "is-async-function@npm:2.0.0" @@ -6594,7 +7093,7 @@ __metadata: languageName: node linkType: hard -"json-parse-even-better-errors@npm:^2.3.1": +"json-parse-even-better-errors@npm:^2.3.0, json-parse-even-better-errors@npm:^2.3.1": version: 2.3.1 resolution: "json-parse-even-better-errors@npm:2.3.1" checksum: 10c0/140932564c8f0b88455432e0f33c4cb4086b8868e37524e07e723f4eaedb9425bdc2bafd71bd1d9765bd15fd1e2d126972bc83990f55c467168c228c24d665f3 @@ -6631,10 +7130,12 @@ __metadata: "@cypress/code-coverage": "npm:^3.12.46" "@docsearch/react": "npm:3.6.1" "@next/eslint-plugin-next": "npm:^14.0.1" + "@svgr/webpack": "npm:^8.1.0" "@types/babel__core": "npm:^7" "@types/babel__preset-env": "npm:^7" "@types/file-saver": "npm:^2.0.7" "@types/js-yaml": "npm:^4.0.5" + "@types/jsonpath": "npm:^0.2.4" "@types/node": "npm:^22.4.2" "@types/react": "npm:18.3.5" "@types/react-syntax-highlighter": "npm:^15.5.13" @@ -6656,14 +7157,16 @@ __metadata: eslint-plugin-n: "npm:^16.6.2" eslint-plugin-node: "npm:^11.1.0" eslint-plugin-prettier: "npm:^5.2.1" - eslint-plugin-promise: "npm:^7.1.0" + eslint-plugin-promise: "npm:^6.0.0" eslint-plugin-react: "npm:^7.35.0" eslint-plugin-react-hooks: "npm:^4.4.0" feed: "npm:^4.2.2" file-saver: "npm:^2.0.5" + fuse.js: "npm:^7.0.0" gray-matter: "npm:^4.0.3" husky: "npm:^9.1.3" js-yaml: "npm:^4.1.0" + jsonpath: "npm:^1.1.1" jszip: "npm:^3.10.1" markdown-to-jsx: "npm:^7.4.7" moment: "npm:2.29.4" @@ -6738,6 +7241,17 @@ __metadata: languageName: node linkType: hard +"jsonpath@npm:^1.1.1": + version: 1.1.1 + resolution: "jsonpath@npm:1.1.1" + dependencies: + esprima: "npm:1.2.2" + static-eval: "npm:2.0.2" + underscore: "npm:1.12.1" + checksum: 10c0/4fea3f83bcb4df08c32090ba8a0d1a6d26244f6d19c4296f9b58caa01eeb7de0f8347eba40077ceee2f95acc69d032b0b48226d350339063ba580e87983f6dec + languageName: node + linkType: hard + "jsprim@npm:^2.0.2": version: 2.0.2 resolution: "jsprim@npm:2.0.2" @@ -6823,6 +7337,16 @@ __metadata: languageName: node linkType: hard +"levn@npm:~0.3.0": + version: 0.3.0 + resolution: "levn@npm:0.3.0" + dependencies: + prelude-ls: "npm:~1.1.2" + type-check: "npm:~0.3.2" + checksum: 10c0/e440df9de4233da0b389cd55bd61f0f6aaff766400bebbccd1231b81801f6dbc1d816c676ebe8d70566394b749fa624b1ed1c68070e9c94999f0bdecc64cb676 + languageName: node + linkType: hard + "lie@npm:~3.3.0": version: 3.3.0 resolution: "lie@npm:3.3.0" @@ -6976,6 +7500,15 @@ __metadata: languageName: node linkType: hard +"lower-case@npm:^2.0.2": + version: 2.0.2 + resolution: "lower-case@npm:2.0.2" + dependencies: + tslib: "npm:^2.0.3" + checksum: 10c0/3d925e090315cf7dc1caa358e0477e186ffa23947740e4314a7429b6e62d72742e0bbe7536a5ae56d19d7618ce998aba05caca53c2902bd5742fdca5fc57fd7b + languageName: node + linkType: hard + "lowlight@npm:^1.17.0": version: 1.20.0 resolution: "lowlight@npm:1.20.0" @@ -7065,6 +7598,20 @@ __metadata: languageName: node linkType: hard +"mdn-data@npm:2.0.28": + version: 2.0.28 + resolution: "mdn-data@npm:2.0.28" + checksum: 10c0/20000932bc4cd1cde9cba4e23f08cc4f816398af4c15ec81040ed25421d6bf07b5cf6b17095972577fb498988f40f4cb589e3169b9357bb436a12d8e07e5ea7b + languageName: node + linkType: hard + +"mdn-data@npm:2.0.30": + version: 2.0.30 + resolution: "mdn-data@npm:2.0.30" + checksum: 10c0/a2c472ea16cee3911ae742593715aa4c634eb3d4b9f1e6ada0902aa90df13dcbb7285d19435f3ff213ebaa3b2e0c0265c1eb0e3fb278fda7f8919f046a410cd9 + languageName: node + linkType: hard + "merge-stream@npm:^2.0.0": version: 2.0.0 resolution: "merge-stream@npm:2.0.0" @@ -7404,6 +7951,16 @@ __metadata: languageName: node linkType: hard +"no-case@npm:^3.0.4": + version: 3.0.4 + resolution: "no-case@npm:3.0.4" + dependencies: + lower-case: "npm:^2.0.2" + tslib: "npm:^2.0.3" + checksum: 10c0/8ef545f0b3f8677c848f86ecbd42ca0ff3cd9dd71c158527b344c69ba14710d816d8489c746b6ca225e7b615108938a0bda0a54706f8c255933703ac1cf8e703 + languageName: node + linkType: hard + "node-gyp@npm:latest": version: 10.2.0 resolution: "node-gyp@npm:10.2.0" @@ -7493,6 +8050,15 @@ __metadata: languageName: node linkType: hard +"nth-check@npm:^2.0.1": + version: 2.1.1 + resolution: "nth-check@npm:2.1.1" + dependencies: + boolbase: "npm:^1.0.0" + checksum: 10c0/5fee7ff309727763689cfad844d979aedd2204a817fbaaf0e1603794a7c20db28548d7b024692f953557df6ce4a0ee4ae46cd8ebd9b36cfb300b9226b567c479 + languageName: node + linkType: hard + "nyc@npm:15.1.0": version: 15.1.0 resolution: "nyc@npm:15.1.0" @@ -7671,6 +8237,20 @@ __metadata: languageName: node linkType: hard +"optionator@npm:^0.8.1": + version: 0.8.3 + resolution: "optionator@npm:0.8.3" + dependencies: + deep-is: "npm:~0.1.3" + fast-levenshtein: "npm:~2.0.6" + levn: "npm:~0.3.0" + prelude-ls: "npm:~1.1.2" + type-check: "npm:~0.3.2" + word-wrap: "npm:~1.2.3" + checksum: 10c0/ad7000ea661792b3ec5f8f86aac28895850988926f483b5f308f59f4607dfbe24c05df2d049532ee227c040081f39401a268cf7bbf3301512f74c4d760dc6dd8 + languageName: node + linkType: hard + "optionator@npm:^0.9.3": version: 0.9.3 resolution: "optionator@npm:0.9.3" @@ -7820,6 +8400,18 @@ __metadata: languageName: node linkType: hard +"parse-json@npm:^5.2.0": + version: 5.2.0 + resolution: "parse-json@npm:5.2.0" + dependencies: + "@babel/code-frame": "npm:^7.0.0" + error-ex: "npm:^1.3.1" + json-parse-even-better-errors: "npm:^2.3.0" + lines-and-columns: "npm:^1.1.6" + checksum: 10c0/77947f2253005be7a12d858aedbafa09c9ae39eb4863adf330f7b416ca4f4a08132e453e08de2db46459256fb66afaac5ee758b44fe6541b7cdaf9d252e59585 + languageName: node + linkType: hard + "path-exists@npm:^4.0.0": version: 4.0.0 resolution: "path-exists@npm:4.0.0" @@ -8045,6 +8637,13 @@ __metadata: languageName: node linkType: hard +"prelude-ls@npm:~1.1.2": + version: 1.1.2 + resolution: "prelude-ls@npm:1.1.2" + checksum: 10c0/7284270064f74e0bb7f04eb9bff7be677e4146417e599ccc9c1200f0f640f8b11e592d94eb1b18f7aa9518031913bb42bea9c86af07ba69902864e61005d6f18 + languageName: node + linkType: hard + "prettier-linter-helpers@npm:^1.0.0": version: 1.0.0 resolution: "prettier-linter-helpers@npm:1.0.0" @@ -8961,6 +9560,16 @@ __metadata: languageName: node linkType: hard +"snake-case@npm:^3.0.4": + version: 3.0.4 + resolution: "snake-case@npm:3.0.4" + dependencies: + dot-case: "npm:^3.0.4" + tslib: "npm:^2.0.3" + checksum: 10c0/ab19a913969f58f4474fe9f6e8a026c8a2142a01f40b52b79368068343177f818cdfef0b0c6b9558f298782441d5ca8ed5932eb57822439fad791d866e62cecd + languageName: node + linkType: hard + "socks-proxy-agent@npm:^8.0.3": version: 8.0.4 resolution: "socks-proxy-agent@npm:8.0.4" @@ -8982,6 +9591,13 @@ __metadata: languageName: node linkType: hard +"source-map-js@npm:^1.0.1, source-map-js@npm:^1.2.0": + version: 1.2.0 + resolution: "source-map-js@npm:1.2.0" + checksum: 10c0/7e5f896ac10a3a50fe2898e5009c58ff0dc102dcb056ed27a354623a0ece8954d4b2649e1a1b2b52ef2e161d26f8859c7710350930751640e71e374fe2d321a4 + languageName: node + linkType: hard + "source-map-js@npm:^1.0.2": version: 1.0.2 resolution: "source-map-js@npm:1.0.2" @@ -8989,13 +9605,6 @@ __metadata: languageName: node linkType: hard -"source-map-js@npm:^1.2.0": - version: 1.2.0 - resolution: "source-map-js@npm:1.2.0" - checksum: 10c0/7e5f896ac10a3a50fe2898e5009c58ff0dc102dcb056ed27a354623a0ece8954d4b2649e1a1b2b52ef2e161d26f8859c7710350930751640e71e374fe2d321a4 - languageName: node - linkType: hard - "source-map-support@npm:~0.5.20": version: 0.5.21 resolution: "source-map-support@npm:0.5.21" @@ -9006,7 +9615,7 @@ __metadata: languageName: node linkType: hard -"source-map@npm:^0.6.0, source-map@npm:^0.6.1": +"source-map@npm:^0.6.0, source-map@npm:^0.6.1, source-map@npm:~0.6.1": version: 0.6.1 resolution: "source-map@npm:0.6.1" checksum: 10c0/ab55398007c5e5532957cb0beee2368529618ac0ab372d789806f5718123cc4367d57de3904b4e6a4170eb5a0b0f41373066d02ca0735a0c4d75c7d328d3e011 @@ -9078,6 +9687,15 @@ __metadata: languageName: node linkType: hard +"static-eval@npm:2.0.2": + version: 2.0.2 + resolution: "static-eval@npm:2.0.2" + dependencies: + escodegen: "npm:^1.8.1" + checksum: 10c0/9bc1114ea5ba2a6978664907c4dd3fde6f58767274f6cb4fbfb11ba3a73cb6e74dc11e89ec4a7bf1472a587c1f976fcd4ab8fe9aae1651f5e576f097745d48ff + languageName: node + linkType: hard + "streamsearch@npm:^1.1.0": version: 1.1.0 resolution: "streamsearch@npm:1.1.0" @@ -9323,6 +9941,30 @@ __metadata: languageName: node linkType: hard +"svg-parser@npm:^2.0.4": + version: 2.0.4 + resolution: "svg-parser@npm:2.0.4" + checksum: 10c0/02f6cb155dd7b63ebc2f44f36365bc294543bebb81b614b7628f1af3c54ab64f7e1cec20f06e252bf95bdde78441ae295a412c68ad1678f16a6907d924512b7a + languageName: node + linkType: hard + +"svgo@npm:^3.0.2": + version: 3.3.2 + resolution: "svgo@npm:3.3.2" + dependencies: + "@trysound/sax": "npm:0.2.0" + commander: "npm:^7.2.0" + css-select: "npm:^5.1.0" + css-tree: "npm:^2.3.1" + css-what: "npm:^6.1.0" + csso: "npm:^5.0.5" + picocolors: "npm:^1.0.0" + bin: + svgo: ./bin/svgo + checksum: 10c0/a6badbd3d1d6dbb177f872787699ab34320b990d12e20798ecae915f0008796a0f3c69164f1485c9def399e0ce0a5683eb4a8045e51a5e1c364bb13a0d9f79e1 + languageName: node + linkType: hard + "synckit@npm:^0.9.1": version: 0.9.1 resolution: "synckit@npm:0.9.1" @@ -9550,7 +10192,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.1.0": +"tslib@npm:^2.0.3, tslib@npm:^2.1.0": version: 2.6.3 resolution: "tslib@npm:2.6.3" checksum: 10c0/2598aef53d9dbe711af75522464b2104724d6467b26a60f2bdac8297d2b5f1f6b86a71f61717384aa8fd897240467aaa7bcc36a0700a0faf751293d1331db39a @@ -9589,6 +10231,15 @@ __metadata: languageName: node linkType: hard +"type-check@npm:~0.3.2": + version: 0.3.2 + resolution: "type-check@npm:0.3.2" + dependencies: + prelude-ls: "npm:~1.1.2" + checksum: 10c0/776217116b2b4e50e368c7ee0c22c0a85e982881c16965b90d52f216bc296d6a52ef74f9202d22158caacc092a7645b0b8d5fe529a96e3fe35d0fb393966c875 + languageName: node + linkType: hard + "type-fest@npm:^0.20.2": version: 0.20.2 resolution: "type-fest@npm:0.20.2" @@ -9750,6 +10401,13 @@ __metadata: languageName: node linkType: hard +"underscore@npm:1.12.1": + version: 1.12.1 + resolution: "underscore@npm:1.12.1" + checksum: 10c0/00f392357e363353ac485e7c156b749505087e31ff4fdad22e04ebd2f94a56fbc554cd41a6722e3895a818466cf298b1cae93ff6211d102d373a9b50db63bfd0 + languageName: node + linkType: hard + "undici-types@npm:~5.26.4": version: 5.26.5 resolution: "undici-types@npm:5.26.5" @@ -10080,6 +10738,13 @@ __metadata: languageName: node linkType: hard +"word-wrap@npm:~1.2.3": + version: 1.2.5 + resolution: "word-wrap@npm:1.2.5" + checksum: 10c0/e0e4a1ca27599c92a6ca4c32260e8a92e8a44f4ef6ef93f803f8ed823f486e0889fc0b93be4db59c8d51b3064951d25e43d434e95dc8c960cc3a63d65d00ba20 + languageName: node + linkType: hard + "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": version: 7.0.0 resolution: "wrap-ansi@npm:7.0.0"