diff --git a/.gitignore b/.gitignore index c46c5ca..773204a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ logs npm-debug.log* yarn-debug.log* yarn-error.log* -yarn.lock +.DS_Store # Runtime data pids diff --git a/CHANGELOG.md b/CHANGELOG.md index 4169b48..2bbc7bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,27 @@ + +## [0.0.5](https://github.com/abdullahceylan/vscode-react-component-generator/compare/0.0.4...0.0.5) (2024-10-11) + +### Updates +* Updated TypeScript Remix Route component extension + + +## [0.0.4](https://github.com/abdullahceylan/vscode-react-component-generator/compare/0.0.3...0.0.4) (2024-10-11) + +### Updates +* Updated the classic React component templates +* Removed container component templates +* Added TypeScript component creation +* Added TypeScript Remix component creation +* Added TypeScript Remix route component creation +* Added CSS Module prefix support for the stylesheet extension option. + + +## [0.0.3](https://github.com/abdullahceylan/vscode-react-component-generator/compare/0.0.2...0.0.3) (2018-12-30) + +### Updates +* Added .scss CSS file extension support for the stylesheet extension option. (Thanks to Mark Casias) +* Fixed some typos. (Thanks to Mark Casias) + ## [0.0.2](https://github.com/abdullahceylan/vscode-react-component-generator/compare/0.0.1...0.0.2) (2018-12-09) @@ -10,7 +34,7 @@ ### New Features * Added **lifecycle** type option. Now you can choose whether to create a component with legacy lifecycle or React v16 lifecycles -* Added **SASS** and **LESS** css extension option. +* Added **SASS** and **LESS** stylesheet extension option. ## [0.0.1](#) (2018-12-02) diff --git a/README.md b/README.md index edc3e97..09a7715 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,25 @@ -# React Component Generation Extension for VSCode -(**vscode-react-component-generator**) +# React Component Generator Extension for VSCode -[![Version](https://vsmarketplacebadge.apphb.com/version/abdullahceylan.vscode-react-component-generator.svg)](https://marketplace.visualstudio.com/items?itemName=abdullahceylan.vscode-react-component-generator) -[![Installs](https://vsmarketplacebadge.apphb.com/installs/abdullahceylan.vscode-react-component-generator.svg)](https://marketplace.visualstudio.com/items?itemName=abdullahceylan.vscode-react-component-generator) +The extension helps you to create a React component with one-click. There are also options to create Remix and TypeScript React components. + +[![Version](https://vsmarketplacebadges.dev/version/abdullahceylan.vscode-react-component-generator.png)](https://marketplace.visualstudio.com/items?itemName=abdullahceylan.vscode-react-component-generator) +[![Installs](https://vsmarketplacebadges.dev/installs-short/abdullahceylan.vscode-react-component-generator.png)](https://marketplace.visualstudio.com/items?itemName=abdullahceylan.vscode-react-component-generator) +[![Installs](https://vsmarketplacebadges.dev/rating-star/abdullahceylan.vscode-react-component-generator.png)](https://marketplace.visualstudio.com/items?itemName=abdullahceylan.vscode-react-component-generator) [![The MIT License](https://flat.badgen.net/badge/license/MIT/orange)](http://opensource.org/licenses/MIT) -[![GitHub](https://flat.badgen.net/github/release/abdullahceylan/vscode-react-component-generator)](https://github.com/abdullahceylan/vscode-react-component-generator/releases) + +## Other Versions +[Please click here for React Native version](https://marketplace.visualstudio.com/items?itemName=abdullahceylan.vscode-react-native-component-generator) ## Description + The extension automatically creates folder for react component containing : -- `index.js` -- `ComponentName.jsx` -- `ComponentName.styles.js` (for `styled`-component or `emotion` option) + +- `index.(js|ts)` +- `ComponentName.(jsx|tsx)` +- `ComponentName.styles.(js|ts)` (for `styled`-component or `emotion` option) - `ComponentName.css` (for `standard` style option) -- `ComponentName.sass` (for `sass` style option) +- `ComponentName.module.css` (you'll need to set prefix from the extension settings) +- `ComponentName.scss` (for `sass` style option) - `ComponentName.less` (for `less` style option) ## Installation @@ -23,7 +30,7 @@ Install through VS Code extensions. Search for `VSCode React Component Generator Can also be installed in VS Code: Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter. -``` +```bash ext install abdullahceylan.vscode-react-component-generator ``` @@ -31,69 +38,93 @@ ext install abdullahceylan.vscode-react-component-generator - Right click on the file or folder in the file explorer - Select one of following options: - - "New React Container Component" - - "New React Stateless Component" - - "New React Container Component with Redux" - - "New React Stateless Component with Redux" + - "New React Stateless Component" + - "New React Stateless Component with Redux" + - "New React TypeScript Component" + - "New React TypeScript Remix Component" + - "New React TypeScript Remix Route Component" + - Enter a component name in the pop up in camelCase or PascalCase. If you enter the component name as in camelCase, then extension will convert it PascalCase automatically. -![Container component](assets/images/vscode-1.gif) +- For Remix Route component, enter the route file name and the file will be created with `app.` prefix. i.e.: + - demoRoute -> app.demo.route.ts + - demoRouteChild -> app.demo.route.child.ts -![Basic component](assets/images/vscode-2.gif) +### Creating a React Component + +![Classic React Component](assets/images/ac-vscode-classic-component.gif) + +### Creating a TypeScript React Component, Remix TypeScript Component and React TypeScript Route Component + +![TypeScript and Remix Component](assets/images/ac-vscode-typescript-remix.gif) -![Container component with redux](assets/images/vscode-3.gif) ![Extension settings](assets/images/vscode-settings.png) ## Configuration + You can access to the extension's settings through VSCode settings. You can customize: +### `ACReactComponentGenerator.global.generateFolder` (default: `true`) -#### `ACReactComponentGenerator.global.generateFolder` (default: `true`) Generate or not separate folder for newly created component -#### `ACReactComponentGenerator.global.quotes` (default: `single`) +### `ACReactComponentGenerator.global.quotes` (default: `single`) + Controls the quotes for the imports in the files. Valid options: - - "single" - e.g.: import React from `'`react`'` - - "double" - e.g.: import React from `"`react`"` - -#### `ACReactComponentGenerator.global.lifecycleType` (default: `legacy`) + +- "single" - e.g.: import React from `'`react`'` +- "double" - e.g.: import React from `"`react`"` + +### `ACReactComponentGenerator.global.lifecycleType` (default: `legacy`) + The lifecycle type of generated component. Valid options: - - "legacy" - Contains `componentWillReceiveProps`, `componentWillMount` - - "reactv16" - Contains `getSnapshotBeforeUpdate`, `getDerivedStateFromProps`, `getDerivedStateFromError`, `componentDidCatch` and removes `componentWillReceiveProps` and `componentWillMount` -#### `ACReactComponentGenerator.indexFile.create` (default: `true`) -Weather to generate component's index file or not. +- "legacy" - Contains `componentWillReceiveProps`, `componentWillMount` +- "reactv16" - Contains `getSnapshotBeforeUpdate`, `getDerivedStateFromProps`, `getDerivedStateFromError`, `componentDidCatch` and removes `componentWillReceiveProps` and `componentWillMount` + +### `ACReactComponentGenerator.indexFile.create` (default: `true`) + +Whether to generate component's index file or not. + +### `ACReactComponentGenerator.indexFile.extension` (default: `ts`) -#### `ACReactComponentGenerator.indexFile.extension` (default: `js`) The extension of generated component index file. e.g.: index.(`extension`) -#### `ACReactComponentGenerator.mainFile.create` (default: `true`) -Weather to generate component's main file or not. +### `ACReactComponentGenerator.mainFile.create` (default: `true`) + +Whether to generate component's main file or not. + +### `ACReactComponentGenerator.mainFile.extension` (default: `tsx`) -#### `ACReactComponentGenerator.mainFile.extension` (default: `jsx`) The extension of generated component file. e.g.: ComponentName.(`extension`) -#### `ACReactComponentGenerator.styleFile.create` (default: `true`) -Weather to generate component's stylesheet file or not. +### `ACReactComponentGenerator.styleFile.create` (default: `true`) + +Whether to generate component's stylesheet file or not. + +### `ACReactComponentGenerator.styleFile.extension` (default: `css`) -#### `ACReactComponentGenerator.styleFile.extension` (default: `jsx`) The extension of generated stylesheet file. e.g.: ComponentName.styles.(`extension`) -#### `ACReactComponentGenerator.styleFile.suffix` (default: `.styles`) -The suffix to add to the end of the stylesheet filename. Default: ComponentName`.styles`.(extension) +### `ACReactComponentGenerator.styleFile.suffix` (default: `none`) + +The suffix to add to the end of the stylesheet filename. Default: None +You have option to select `CSS modules` and `Styled Component` + +### `ACReactComponentGenerator.styleFile.type` (default: `styled-components`) -#### `ACReactComponentGenerator.styleFile.type` (default: `styled-components`) The type of stylesheet file to create. Valid options: -- "styled-components (.js)" - ComponentName.styles.`js` -- "emotion (.js)" - ComponentName.styles.`js` + +- "standard (.css)" - ComponentName.`css` (You can use this for CSS modules as well) +- "styled-components/emotion (.js)" - ComponentName.styles.`js` - "standard (.css)" - ComponentName.styles.`css` -- "sass (.sass)" - ComponentName.styles.`sass` +- "sass (.scss)" - ComponentName.styles.`sass` - "less (.less)" - ComponentName.styles.`less` -### Changelog +## Changelog -#### [Click here](CHANGELOG.md) +### [Click here](CHANGELOG.md) ## Bugs diff --git a/assets/images/ac-vscode-classic-component.gif b/assets/images/ac-vscode-classic-component.gif new file mode 100644 index 0000000..c21f5d0 Binary files /dev/null and b/assets/images/ac-vscode-classic-component.gif differ diff --git a/assets/images/ac-vscode-typescript-remix.gif b/assets/images/ac-vscode-typescript-remix.gif new file mode 100644 index 0000000..96d1ba0 Binary files /dev/null and b/assets/images/ac-vscode-typescript-remix.gif differ diff --git a/assets/images/vscode-settings.png b/assets/images/vscode-settings.png index f6328ee..92f9347 100644 Binary files a/assets/images/vscode-settings.png and b/assets/images/vscode-settings.png differ diff --git a/assets/templates/component-container.template b/assets/templates/component-container.template deleted file mode 100644 index 61e6053..0000000 --- a/assets/templates/component-container.template +++ /dev/null @@ -1,75 +0,0 @@ -import React, { PureComponent } from {quotes}react{quotes}; -import PropTypes from {quotes}prop-types{quotes}; -//import { Test } from {quotes}./{componentName}.styles{quotes}; - -class {componentName} extends PureComponent { - constructor(props) { - super(props); - - this.state = { - hasError: false, - }; - } - - componentWillMount = () => { - console.log('{componentName} will mount'); - } - - componentDidMount = () => { - console.log('{componentName} mounted'); - } - - componentWillReceiveProps = (nextProps) => { - console.log('{componentName} will receive props', nextProps); - } - - componentWillUpdate = (nextProps, nextState) => { - console.log('{componentName} will update', nextProps, nextState); - } - - static getDerivedStateFromError(error) { - // getDerivedStateFromError -> Update state so the next render will show the fallback UI. - return { hasError: true }; - } - - componentDidCatch(error, info) { - // You can also log the error to an error reporting service - } - - getDerivedStateFromProps = (nextProps, prevState) => { - console.log('{componentName} getDerivedStateFromProps', nextProps, prevState); - } - - getSnapshotBeforeUpdate = (prevProps, prevState) => { - console.log('{componentName} getSnapshotBeforeUpdate', prevProps, prevState); - } - - componentDidUpdate = () => { - console.log('{componentName} did update'); - } - - componentWillUnmount = () => { - console.log('{componentName} will unmount'); - } - - render () { - if (this.state.hasError) { - return

Something went wrong.

; - } - return ( -
- Test content -
- ); - } -} - -{componentName}.propTypes = { - // bla: PropTypes.string, -}; - -{componentName}.defaultProps = { - // bla: 'test', -}; - -export default {componentName}; diff --git a/assets/templates/component-hook-state.template b/assets/templates/component-hook-state.template new file mode 100644 index 0000000..4d99bad --- /dev/null +++ b/assets/templates/component-hook-state.template @@ -0,0 +1,44 @@ +import { useState, useEffect } from {quotes}react{quotes}; +import PropTypes from {quotes}prop-types{quotes}; +//import { Test } from {quotes}./{componentName}.styles{quotes}; + +const {componentName} = props => { + const [state, setState] = useState(null); + const [hasError, setHasError] = useState(false); + + // on mount + useEffect(() => { + console.log('component has mounted') + + // component will unmount + return () => { + // your code to be run after unmount + } + }, []); + + // on hasError state update + useEffect(() => { + if (hasError) { + console.log('An error occured'); + } + }, [hasError]) + + if (hasError) { + return

Something went wrong.

; + } + return ( +
+ Test content +
+ ); +} + +{componentName}.propTypes = { + // bla: PropTypes.string, +}; + +{componentName}.defaultProps = { + // bla: 'test', +}; + +export default {componentName}; diff --git a/assets/templates/component-reduxContainer.template b/assets/templates/component-reduxContainer.template deleted file mode 100644 index b392fb9..0000000 --- a/assets/templates/component-reduxContainer.template +++ /dev/null @@ -1,84 +0,0 @@ -import React, { PureComponent } from {quotes}react{quotes}; -import { connect } from {quotes}react-redux{quotes}; -import PropTypes from {quotes}prop-types{quotes}; -//import { Test } from {quotes}./{componentName}.styles{quotes}; - -class {componentName} extends PureComponent { - constructor(props) { - super(props); - - this.state = { - hasError: false, - }; - } - - componentWillMount = () => { - console.log('{componentName} will mount'); - } - - componentDidMount = () => { - console.log('{componentName} mounted'); - } - - componentWillReceiveProps = (nextProps) => { - console.log('{componentName} will receive props', nextProps); - } - - componentWillUpdate = (nextProps, nextState) => { - console.log('{componentName} will update', nextProps, nextState); - } - - - static getDerivedStateFromError(error) { - // getDerivedStateFromError -> Update state so the next render will show the fallback UI. - return { hasError: true }; - } - - componentDidCatch(error, info) { - // You can also log the error to an error reporting service - } - - getSnapshotBeforeUpdate = (prevProps, prevState) => { - console.log('{componentName} getSnapshotBeforeUpdate', prevProps, prevState); - } - - componentDidUpdate = () => { - console.log('{componentName} did update'); - } - - componentWillUnmount = () => { - console.log('{componentName} will unmount'); - } - - render () { - if (this.state.hasError) { - return

Something went wrong.

; - } - return ( -
- Test content -
- ); - } -} - -{componentName}.propTypes = { - // bla: PropTypes.string, -}; - -{componentName}.defaultProps = { - // bla: 'test', -}; - -const mapStateToProps = state => ({ - // blabla: state.blabla, -}); - -const mapDispatchToProps = dispatch => ({ - // fnBlaBla: () => dispatch(action.name()), -}); - -export default connect( - mapStateToProps, - mapDispatchToProps, -)({componentName}); diff --git a/assets/templates/component-reduxStateless.template b/assets/templates/component-reduxStateless.template index c6cdbc6..8867253 100644 --- a/assets/templates/component-reduxStateless.template +++ b/assets/templates/component-reduxStateless.template @@ -1,13 +1,16 @@ -import React from {quotes}react{quotes}; import PropTypes from {quotes}prop-types{quotes}; -import { connect } from {quotes}react-redux{quotes}; +import { useDispatch } from {quotes}react-redux{quotes}; //import { Test } from './{componentName}.styles'; -const {componentName} = (props) => ( -
- Test content -
-); +const {componentName} = (props) => { + const dispatch = useDispatch() + + return ( +
+ Test content +
+ ) +} {componentName}.propTypes = { // bla: PropTypes.string, @@ -17,15 +20,4 @@ const {componentName} = (props) => ( // bla: 'test', }; -const mapStateToProps = state => ({ - // blabla: state.blabla, -}); - -const mapDispatchToProps = dispatch => ({ - // fnBlaBla: () => dispatch(action.name()), -}); - -export default connect( - mapStateToProps, - mapDispatchToProps, -)({componentName}); +export default {componentName} \ No newline at end of file diff --git a/assets/templates/component-stateless.template b/assets/templates/component-stateless.template index 269021f..2a0bdc5 100644 --- a/assets/templates/component-stateless.template +++ b/assets/templates/component-stateless.template @@ -1,12 +1,18 @@ -import React from {quotes}react{quotes}; +import { useEffect } from 'react'; import PropTypes from {quotes}prop-types{quotes}; -//import { Test } from './{componentName}.styles'; -const {componentName} = (props) => ( -
- Test content -
-); +const {componentName} = () => { + + useEffect(() => { + console.log(`{componentName} mounted`) + }, []) + + return ( +
+ Test content +
+ ) +} {componentName}.propTypes = { // bla: PropTypes.string, diff --git a/assets/templates/component-typescript-remix.template b/assets/templates/component-typescript-remix.template new file mode 100644 index 0000000..7df2ec5 --- /dev/null +++ b/assets/templates/component-typescript-remix.template @@ -0,0 +1,27 @@ +import { json } from '@remix-run/node'; +import type { LoaderFunctionArgs, ActionFunctionArgs } from '@remix-run/node'; +import { useLoaderData } from '@remix-run/react'; + +export async function loader({ request }: LoaderFunctionArgs) { + return { dummyProp: 'test' } +}; + +export async function action({ request }: ActionFunctionArgs) { + return json({ status: 200 }) +}; + +interface I{componentName} { + test: string +} + +const {componentName} = ({ test }: I{componentName}) => { + const { dummyProp } = useLoaderData(); + + return ( +
+ Test content +
+ ); +} + +export default {componentName}; diff --git a/assets/templates/component-typescript.template b/assets/templates/component-typescript.template new file mode 100644 index 0000000..b881cfa --- /dev/null +++ b/assets/templates/component-typescript.template @@ -0,0 +1,20 @@ +import { useEffect } from 'react'; + +interface I{componentName} { + test: string +} + +const {componentName} = ({ test }: I{componentName}) => { + + useEffect(() => { + console.log(`{componentName} mounted`) + }, []) + + return ( +
+ Test content +
+ ) +} + +export default {componentName}; diff --git a/assets/templates/css-emotion.template b/assets/templates/css-emotion.template index 0e83752..325f764 100644 --- a/assets/templates/css-emotion.template +++ b/assets/templates/css-emotion.template @@ -2,5 +2,4 @@ // export const Test = styled.div` // display: flex; -// `; -// \ No newline at end of file +// `; \ No newline at end of file diff --git a/assets/templates/css-module.template b/assets/templates/css-module.template new file mode 100644 index 0000000..6a12d3e --- /dev/null +++ b/assets/templates/css-module.template @@ -0,0 +1,3 @@ +.{componentName}-component { + display: flex; +} \ No newline at end of file diff --git a/assets/templates/css.template b/assets/templates/css.template index b606079..6a12d3e 100644 --- a/assets/templates/css.template +++ b/assets/templates/css.template @@ -1 +1,3 @@ -/* your css code */ \ No newline at end of file +.{componentName}-component { + display: flex; +} \ No newline at end of file diff --git a/package.json b/package.json index c18a365..698215c 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-react-component-generator", "displayName": "VSCode React Component Generator", "description": "Generates React component files automatically", - "version": "0.0.2", + "version": "0.0.5", "publisher": "abdullahceylan", "author": { "name": "Abdullah Ceylan", @@ -10,8 +10,8 @@ }, "homepage": "https://github.com/abdullahceylan/vscode-react-component-generator", "galleryBanner": { - "color": "#0273D4", - "theme": "dark" + "color": "#0273D4", + "theme": "dark" }, "repository": { "type": "git", @@ -40,10 +40,11 @@ "typescript" ], "activationEvents": [ - "onCommand:extension.genReactContainerComponentFiles", "onCommand:extension.genReactStatelessComponentFiles", - "onCommand:extension.genReactReduxContainerComponentFiles", - "onCommand:extension.genReactReduxStatelessComponentFiles" + "onCommand:extension.genReactReduxStatelessComponentFiles", + "onCommand:extension.genReactTypeScriptComponentFiles", + "onCommand:extension.genReactTypeScriptRemixComponentFiles", + "onCommand:extension.genReactTypeScriptRemixRouteComponentFiles" ], "main": "./out/src/extension", "icon": "assets/images/icon.png", @@ -68,92 +69,112 @@ }, "ACReactComponentGenerator.global.lifecycleType": { "type": "string", - "default": "legacy", + "default": "reactv16", "enum": [ "legacy", "reactv16" ], - "description": "The lifecycle type of generated component. `legacy` is contains componentWillReceiveProps, componentWillMount etc." + "description": "The lifecycle type of generated component. `legacy` contains componentWillReceiveProps, componentWillMount etc." }, "ACReactComponentGenerator.mainFile.create": { "type": "boolean", "default": true, - "description": "Weather to generate component's main file or not. e.g.: ComponentName.(extension)" + "description": "Whether to generate component's main file or not. e.g.: ComponentName.(extension)" }, "ACReactComponentGenerator.mainFile.extension": { "type": "string", - "default": "jsx", + "enum": [ + "TypeScript (.tsx)", + "JSX (.jsx)" + ], + "default": "TypeScript (.tsx)", "description": "The extension of generated component file" }, "ACReactComponentGenerator.styleFile.create": { "type": "boolean", "default": true, - "description": "Weather to generate component's style file or not. e.g.: ComponentName.(extension)" + "description": "Whether to generate component's style file or not. e.g.: ComponentName.(extension)" }, "ACReactComponentGenerator.styleFile.type": { "type": "string", "enum": [ - "styled-components (.js)", - "emotion (.js)", "standard (.css)", + "styled-components/emotion (.js)", "sass (.sass)", + "sass (.scss)", "less (.less)" ], - "default": "styled-components (.js)", + "default": "standard (.css)", "description": "The type of stylesheet file to create" }, - "ACReactComponentGenerator.styleFile.suffix": { "type": "string", - "default": ".styles", - "description": "The suffix to add to the end of the stylesheet filename. Default: ComponentName.styles.(extension)" + "enum": [ + "none", + ".module", + ".styles" + ], + "default": "none", + "description": "The suffix to add to the end of the stylesheet filename. Default: ComponentName.modules.(extension)" }, "ACReactComponentGenerator.indexFile.create": { "type": "boolean", "default": true, - "description": "Weather to generate component's index file or not. e.g.: index.(extension)" + "description": "Whether to generate component's index file or not. e.g.: index.(extension)" }, "ACReactComponentGenerator.indexFile.extension": { "type": "string", - "default": "js", + "enum": [ + "Vanilla (.js)", + "TypeScript (.ts)" + ], + "default": "ts", "description": "The extension of generated component index file" } } }, "commands": [ - { - "command": "extension.genReactContainerComponentFiles", - "title": "New React Container Component" - }, { "command": "extension.genReactStatelessComponentFiles", "title": "New React Stateless Component" }, - { - "command": "extension.genReactReduxContainerComponentFiles", - "title": "New React Container Component with Redux" - }, { "command": "extension.genReactReduxStatelessComponentFiles", "title": "New React Stateless Component with Redux" + }, + { + "command": "extension.genReactTypeScriptComponentFiles", + "title": "New React TypeScript Component" + }, + { + "command": "extension.genReactTypeScriptRemixComponentFiles", + "title": "New React TypeScript Remix Component" + }, + { + "command": "extension.genReactTypeScriptRemixRouteComponentFiles", + "title": "New React TypeScript Remix Route Component" } ], "menus": { "explorer/context": [ { - "command": "extension.genReactContainerComponentFiles", + "command": "extension.genReactStatelessComponentFiles", "group": "navigation" }, { - "command": "extension.genReactStatelessComponentFiles", + "command": "extension.genReactReduxStatelessComponentFiles", "group": "navigation" }, { - "command": "extension.genReactReduxContainerComponentFiles", + "command": "extension.genReactTypeScriptComponentFiles", "group": "navigation" }, { - "command": "extension.genReactReduxStatelessComponentFiles", + "command": "extension.genReactTypeScriptRemixComponentFiles", + "group": "navigation" + }, + { + "command": "extension.genReactTypeScriptRemixRouteComponentFiles", "group": "navigation" } ] @@ -165,19 +186,18 @@ "postinstall": "node ./node_modules/vscode/bin/install" }, "devDependencies": { + "@types/mocha": "^2.2.42", + "@types/node": "^22.7.5", + "eslint": "^9.12.0", "mocha": "^2.3.3", - "typescript": "^2.6.1", - "vscode": "^1.1.21", - "eslint": "^4.11.0", - "@types/node": "^8.10.25", - "@types/mocha": "^2.2.42" - + "typescript": "^5.6.3", + "vscode": "^1.1.37" }, "dependencies": { "change-case": "^3.0.2", "fs": "^0.0.1-security", - "fs-extra": "^0.30.0", - "rxjs": "^5.0.0-rc.1", - "lodash": "^4.17.11" + "fs-extra": "^11.2.0", + "lodash": "^4.17.11", + "rxjs": "^5.0.0-rc.1" } } diff --git a/src/extension.ts b/src/extension.ts index 9e1b772..8111a0b 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,85 +1,118 @@ -'use strict'; +// @ts-nocheck +"use strict"; // The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below -import { ExtensionContext, workspace, window, commands } from 'vscode'; -import { paramCase } from 'change-case'; -import { Observable } from 'rxjs'; +import { ExtensionContext, workspace, window, commands } from "vscode"; +import { paramCase } from "change-case"; +import { Observable } from "rxjs"; -import { FileHelper, logger } from './helpers'; -import { Config as ConfigInterface } from './config.interface'; +import { FileHelper, logger } from "./helpers"; +import { Config as ConfigInterface } from "./config.interface"; -const TEMPLATE_SUFFIX_SEPERATOR = '-'; +const TEMPLATE_SUFFIX_SEPERATOR = "-"; // this method is called when your extension is activated // your extension is activated the very first time the command is executed export function activate(context: ExtensionContext) { + const createComponent = (uri, suffix: string = "") => { + // Display a dialog to the user + let enterComponentNameDialog$ = Observable.from( + window.showInputBox({ + prompt: + "Please enter component name in camelCase then I can convert it to PascalCase for you.", + }) + ); - const createComponent = (uri, suffix: string = '') => { - // Display a dialog to the user - let enterComponentNameDialog$ = Observable.from( - window.showInputBox( - {prompt: 'Please enter component name in camelCase then I can convert it to PascalCase for you.'} - )); + enterComponentNameDialog$ + .concatMap((val) => { + if (val.length === 0) { + logger("error", "Component name can not be empty!"); + throw new Error("Component name can not be empty!"); + } - enterComponentNameDialog$ - .concatMap( val => { - if (val.length === 0) { - logger('error', 'Component name can not be empty!'); - throw new Error('Component name can not be empty!'); - } - let componentName = paramCase(val); - let componentDir = FileHelper.createComponentDir(uri, componentName); + const isRemixRouteFile = ["-typescript-remix-route"].includes(suffix); - return Observable.forkJoin( - FileHelper.createComponent(componentDir, componentName, suffix), - FileHelper.createIndexFile(componentDir, componentName), - FileHelper.createCSS(componentDir, componentName), - ); - }) - .concatMap(result => Observable.from(result)) - .filter(path => path.length > 0) - .first() - .concatMap(filename => Observable.from(workspace.openTextDocument(filename))) - .concatMap(textDocument => { - if (!textDocument) { - logger('error', 'Could not open file!'); - throw new Error('Could not open file!'); - }; - return Observable.from(window.showTextDocument(textDocument)) - }) - .do(editor => { - if (!editor) { - logger('error', 'Could not open file!'); - throw new Error('Could not open file!') - }; - }) - .subscribe( - (c) => logger('success', 'React component successfully created!'), - err => logger('error', err.message) - ); - }; + const componentName = paramCase(val); + const componentDir = FileHelper.createComponentDir( + uri, + componentName, + isRemixRouteFile + ); - const componentArray = [ - { type: "container", commandId: 'extension.genReactContainerComponentFiles' }, - { type: "stateless", commandId: 'extension.genReactStatelessComponentFiles' }, - { type: "reduxContainer", commandId: 'extension.genReactReduxContainerComponentFiles' }, - { type: "reduxStateless", commandId: 'extension.genReactReduxStatelessComponentFiles' }, - ]; + if (isRemixRouteFile) { + return Observable.forkJoin( + FileHelper.createRemixRouteFile(uri, componentName) + ); + } - // The command has been defined in the package.json file - // Now provide the implementation of the command with registerCommand - // The commandId parameter must match the command field in package.json - componentArray.forEach(c => { - const suffix = `${TEMPLATE_SUFFIX_SEPERATOR}${c.type}`; - const disposable = commands.registerCommand( - c.commandId, (uri) => createComponent(uri, suffix)); - - // Add to a list of disposables which are disposed when this extension is deactivated. - context.subscriptions.push(disposable); - }); + return Observable.forkJoin( + FileHelper.createComponent(componentDir, componentName, suffix), + FileHelper.createIndexFile(componentDir, componentName), + FileHelper.createCSS(componentDir, componentName) + ); + }) + .concatMap((result) => Observable.from(result)) + .filter((path) => path.length > 0) + .first() + .concatMap((filename) => + Observable.from(workspace.openTextDocument(filename)) + ) + .concatMap((textDocument) => { + if (!textDocument) { + logger("error", "Could not open file!"); + throw new Error("Could not open file!"); + } + return Observable.from(window.showTextDocument(textDocument)); + }) + .do((editor) => { + if (!editor) { + logger("error", "Could not open file!"); + throw new Error("Could not open file!"); + } + }) + .subscribe( + (c) => logger("success", "React component successfully created!"), + (err) => logger("error", err.message) + ); + }; + + const componentArray = [ + { + type: "stateless", + commandId: "extension.genReactStatelessComponentFiles", + }, + { + type: "reduxStateless", + commandId: "extension.genReactReduxStatelessComponentFiles", + }, + { + type: "typescript", + commandId: "extension.genReactTypeScriptComponentFiles", + }, + { + type: "typescript-remix", + commandId: "extension.genReactTypeScriptRemixComponentFiles", + }, + { + type: "typescript-remix-route", + commandId: "extension.genReactTypeScriptRemixRouteComponentFiles", + }, + ]; + + // The command has been defined in the package.json file + // Now provide the implementation of the command with registerCommand + // The commandId parameter must match the command field in package.json + componentArray.forEach((c) => { + const suffix = `${TEMPLATE_SUFFIX_SEPERATOR}${c.type}`; + const disposable = commands.registerCommand(c.commandId, (uri) => + createComponent(uri, suffix) + ); + // Add to a list of disposables which are disposed when this extension is deactivated. + context.subscriptions.push(disposable); + }); } // this method is called when your extension is deactivated export function deactivate() { - // code whe + // deactivate } diff --git a/src/helpers.ts b/src/helpers.ts index 86f3c00..b70adc5 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -1,177 +1,260 @@ -import { workspace, Uri, window } from 'vscode'; -import * as fse from 'fs-extra'; -import * as fs from 'fs'; -import * as path from 'path'; -import { pascalCase } from 'change-case'; -import { Observable } from 'rxjs'; +// @ts-nocheck +import { workspace, Uri, window } from "vscode"; +import * as fse from "fs-extra"; +import * as fs from "fs"; +import * as path from "path"; +import { pascalCase, dotCase } from "change-case"; +import { Observable } from "rxjs"; import { IndexInterface, CSSInterface, ComponentInterface, -} from './interfaces/types'; -import GlobalInterface from './interfaces/global.interface'; +} from "./interfaces/types"; +import GlobalInterface from "./interfaces/global.interface"; +export class FileHelper { + private static assetRootDir: string = path.join(__dirname, "../../assets"); -// import { Config as ConfigInterface } from './config.interface'; + private static createFile = <(file: string, data: string) => Observable<{}>>( + Observable.bindNodeCallback(fse.outputFile) + ); -export class FileHelper { - private static assetRootDir: string = path.join(__dirname, '../../assets'); + public static createComponentDir( + uri: any, + componentName: string, + isRemixRouteFile?: boolean + ): string { + let contextMenuSourcePath; + const globalConfig: GlobalInterface = getConfig().get("global"); - private static createFile = <(file: string, data: string) => Observable<{}>>Observable.bindNodeCallback(fse.outputFile); + if (uri && fs.lstatSync(uri.fsPath).isDirectory()) { + contextMenuSourcePath = uri.fsPath; + } else if (uri) { + contextMenuSourcePath = path.dirname(uri.fsPath); + } else { + contextMenuSourcePath = workspace.rootPath; + } - public static createComponentDir(uri: any, componentName: string): string { - let contextMenuSourcePath; - const globalConfig: GlobalInterface = getConfig().get('global'); + let componentDir = `${contextMenuSourcePath}`; + if (globalConfig.generateFolder) { + componentDir = `${contextMenuSourcePath}/${this.setName(componentName)}`; + if (!isRemixRouteFile) fse.mkdirsSync(componentDir); + } - if (uri && fs.lstatSync(uri.fsPath).isDirectory()) { - contextMenuSourcePath = uri.fsPath; - } else if (uri) { - contextMenuSourcePath = path.dirname(uri.fsPath); - } else { - contextMenuSourcePath = workspace.rootPath; - } + return componentDir; + } - let componentDir = `${contextMenuSourcePath}`; - if(globalConfig.generateFolder) { - componentDir = `${contextMenuSourcePath}/${this.setName(componentName)}`; - fse.mkdirsSync(componentDir); - } + public static getExtension = (ext: string) => { + switch (ext) { + case "TypeScript (.tsx)": + return "tsx"; + case "JSX (.jsx)": + return "jsx"; + case "Vanilla (.js)": + return "js"; + case "TypeScript (.ts)": + return "ts"; + default: + return ext; + } + }; - return componentDir; + public static createComponent( + componentDir: string, + componentName: string, + suffix: string = "-container" + ): Observable { + const globalConfig: GlobalInterface = getConfig().get("global"); + const componentConfig: ComponentInterface = getConfig().get("mainFile"); + let templateFileName = + this.assetRootDir + `/templates/component${suffix}.template`; + if (componentConfig.template) { + templateFileName = this.resolveWorkspaceRoot(componentConfig.template); } - public static createComponent(componentDir: string, componentName: string, suffix: string = '-container'): Observable { - const globalConfig: GlobalInterface = getConfig().get('global'); - const componentConfig: ComponentInterface = getConfig().get('mainFile'); - let templateFileName = this.assetRootDir + `/templates/component${suffix}.template`; - if (componentConfig.template) { - templateFileName = this.resolveWorkspaceRoot(componentConfig.template); - } - - const compName = this.setName(componentName); - const removeLifecycleType = globalConfig.lifecycleType == 'legacy' ? 'reactv16' : 'legacy'; - console.log('removeLifecycleType', removeLifecycleType); - - let componentContent = fs.readFileSync( templateFileName ).toString() - .replace(/{componentName}/g, compName) - .replace(/{quotes}/g, this.getQuotes(globalConfig)) - - // console.log('content', componentContent); - - componentContent = removeBetweenTags(globalConfig.lifecycleType, removeLifecycleType, componentContent); - - let filename = `${componentDir}/${compName}.${componentConfig.extension}`; - - if (componentConfig.create) { - return this.createFile(filename, componentContent) - .map(result => filename); - } - else { - return Observable.of(''); - } - }; - - public static createIndexFile(componentDir: string, componentName: string): Observable { - const globalConfig: GlobalInterface = getConfig().get('global'); - const indexConfig: IndexInterface = getConfig().get('indexFile'); - - let templateFileName = this.assetRootDir + '/templates/index.template'; - if (indexConfig.template) { - templateFileName = this.resolveWorkspaceRoot(indexConfig.template); - } - - const compName = this.setName(componentName); - let indexContent = fs.readFileSync( templateFileName ).toString() - .replace(/{componentName}/g, compName) - .replace(/{quotes}/g, this.getQuotes(globalConfig)); - - let filename = `${componentDir}/index.${indexConfig.extension}`; - if (indexConfig.create) { - return this.createFile(filename, indexContent) - .map(result => filename); - } - else { - return Observable.of(''); - } - }; - - public static createCSS(componentDir: string, componentName: string): Observable { - const globalConfig: GlobalInterface = getConfig().get('global'); - const styleConfig: CSSInterface = getConfig().get('styleFile'); - const styleTemplate = getStyleSheetExtTemplate(); - let templateFileName = `${this.assetRootDir}/templates/${styleTemplate.template}`; - // if (styleConfig.template) { - // templateFileName = this.resolveWorkspaceRoot(styleConfig.template); - // } - - const compName = this.setName(componentName); - let cssContent = fs.readFileSync( templateFileName ).toString() - .replace(/{componentName}/g, compName) - .replace(/{quotes}/g, this.getQuotes(globalConfig)); - - let filename = `${componentDir}/${compName}${styleConfig.suffix}.${styleTemplate.ext}`; - if (styleConfig.create) { - return this.createFile(filename, cssContent) - .map(result => filename); - } - else { - return Observable.of(''); - } - }; - - public static resolveWorkspaceRoot = (path: string): string => path.replace('${workspaceFolder}', workspace.rootPath) - - private static getQuotes = (config: GlobalInterface) => config.quotes === "double" ? '"' : '\'' - - public static setName = (name: string) => pascalCase(name) -} + const compName = this.setName(componentName); + const removeLifecycleType = + globalConfig.lifecycleType == "legacy" ? "reactv16" : "legacy"; + console.log("removeLifecycleType", removeLifecycleType); + + let componentContent = fs + .readFileSync(templateFileName) + .toString() + .replace(/{componentName}/g, compName) + .replace(/{quotes}/g, this.getQuotes(globalConfig)); + + componentContent = removeBetweenTags( + globalConfig.lifecycleType, + removeLifecycleType, + componentContent + ); -export function logger(type: 'success'|'warning'|'error', msg: string = '') { - switch (type) { - case 'success': - return window.setStatusBarMessage(`Success: ${msg}`, 5000); - // return window.showInformationMessage(`Success: ${msg}`); - case 'warning': - return window.showWarningMessage(`Warning: ${msg}`); - case 'error': - return window.showErrorMessage(`Failed: ${msg}`); + let filename = `${componentDir}/${compName}.${this.getExtension( + componentConfig.extension + )}`; + + if (componentConfig.create) { + return this.createFile(filename, componentContent).map( + (result) => filename + ); + } else { + return Observable.of(""); } } + public static createIndexFile( + componentDir: string, + componentName: string + ): Observable { + const globalConfig: GlobalInterface = getConfig().get("global"); + const indexConfig: IndexInterface = getConfig().get("indexFile"); + + let templateFileName = this.assetRootDir + "/templates/index.template"; + if (indexConfig.template) { + templateFileName = this.resolveWorkspaceRoot(indexConfig.template); + } + const compName = this.setName(componentName); + let indexContent = fs + .readFileSync(templateFileName) + .toString() + .replace(/{componentName}/g, compName) + .replace(/{quotes}/g, this.getQuotes(globalConfig)); + + let filename = `${componentDir}/index.${this.getExtension( + indexConfig.extension + )}`; + if (indexConfig.create) { + return this.createFile(filename, indexContent).map((result) => filename); + } else { + return Observable.of(""); + } + } + + public static createRemixRouteFile( + componentDir: string, + componentName: string + ): Observable { + const globalConfig: GlobalInterface = getConfig().get("global"); + const indexConfig: IndexInterface = getConfig().get("indexFile"); + const componentConfig: ComponentInterface = getConfig().get("mainFile"); + + let templateFileName = + this.assetRootDir + "/templates/component-typescript-remix.template"; + if (indexConfig.template) { + templateFileName = this.resolveWorkspaceRoot(indexConfig.template); + } + + const compName = this.setName(componentName); + const templateContent = fs + .readFileSync(templateFileName) + .toString() + .replace(/{componentName}/g, compName) + .replace(/{quotes}/g, this.getQuotes(globalConfig)); + + const filename = `${componentDir.path}/app.${dotCase( + compName + )}.${this.getExtension(componentConfig.extension)}`; + if (indexConfig.create) { + return this.createFile(filename, templateContent).map( + (result) => filename + ); + } else { + return Observable.of(""); + } + } + + public static createCSS( + componentDir: string, + componentName: string + ): Observable { + const globalConfig: GlobalInterface = getConfig().get("global"); + const styleConfig: CSSInterface = getConfig().get("styleFile"); + const styleTemplate = getStyleSheetExtTemplate(); + let templateFileName = `${this.assetRootDir}/templates/${styleTemplate.template}`; + + const compName = this.setName(componentName); + let cssContent = fs + .readFileSync(templateFileName) + .toString() + .replace(/{componentName}/g, compName) + .replace(/{quotes}/g, this.getQuotes(globalConfig)); + + let filename = `${componentDir}/${compName}${styleConfig.suffix.replace( + "none", + "" + )}.${styleTemplate.ext}`; + if (styleConfig.create) { + return this.createFile(filename, cssContent).map((result) => filename); + } else { + return Observable.of(""); + } + } + + public static resolveWorkspaceRoot = (path: string): string => + path.replace("${workspaceFolder}", workspace.rootPath); + + private static getQuotes = (config: GlobalInterface) => + config.quotes === "double" ? '"' : "'"; + + public static setName = (name: string) => pascalCase(name); +} + +export function logger( + type: "success" | "warning" | "error", + msg: string = "" +) { + switch (type) { + case "success": + return window.setStatusBarMessage(`Success: ${msg}`, 5000); + // return window.showInformationMessage(`Success: ${msg}`); + case "warning": + return window.showWarningMessage(`Warning: ${msg}`); + case "error": + return window.showErrorMessage(`Failed: ${msg}`); + } +} export default function getConfig(uri?: Uri) { - return workspace.getConfiguration('ACReactComponentGenerator', uri) as any; + return workspace.getConfiguration("ACReactComponentGenerator", uri) as any; } export function getStyleSheetExtTemplate() { - const configuredView = getConfig().get('styleFile.type'); + const configuredView = getConfig().get("styleFile.type"); let styleTemplate = { - ext: 'css', - template: 'css.template', + ext: "css", + template: "css.template", }; - switch (configuredView) { - case 'styled-components (.js)': - styleTemplate = { ext: 'js', template: 'css-styled.template' }; + switch (configuredView) { + case "styled-components/emotion (.js)": + styleTemplate = { ext: "js", template: "css-styled.template" }; break; - case 'emotion (.js)': - styleTemplate = { ext: 'js', template: 'css-emotion.template' }; + case "sass (.sass)": + styleTemplate.ext = "sass"; break; - case 'sass (.sass)': - styleTemplate.ext = 'sass'; + case "sass (.scss)": + styleTemplate.ext = "scss"; break; - case 'less (.less)': - styleTemplate.ext = 'less'; + case "less (.less)": + styleTemplate.ext = "less"; break; } - + return styleTemplate; } export function removeBetweenTags(remainTag, removedtag, content) { - const escapeRegExp = s => s.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&"); - const regexPattern = RegExp(`${escapeRegExp(`<${removedtag}>`)}([\\S\\s]+?)${escapeRegExp(``)}`, "gi"); - const removeOnlyTagsPattern = new RegExp(`<(${escapeRegExp(remainTag)}|/${escapeRegExp(remainTag)})[^>]{0,}>`, "gi"); + const escapeRegExp = (s) => s.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&"); + const regexPattern = RegExp( + `${escapeRegExp(`<${removedtag}>`)}([\\S\\s]+?)${escapeRegExp( + `` + )}`, + "gi" + ); + const removeOnlyTagsPattern = new RegExp( + `<(${escapeRegExp(remainTag)}|/${escapeRegExp(remainTag)})[^>]{0,}>`, + "gi" + ); - return content.replace(regexPattern, '').replace(removeOnlyTagsPattern, ''); -} \ No newline at end of file + return content.replace(regexPattern, "").replace(removeOnlyTagsPattern, ""); +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..d87dfd5 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,1133 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.11.0": + version "4.11.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.1.tgz#a547badfc719eb3e5f4b556325e542fbe9d7a18f" + integrity sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q== + +"@eslint/config-array@^0.18.0": + version "0.18.0" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.18.0.tgz#37d8fe656e0d5e3dbaea7758ea56540867fd074d" + integrity sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw== + dependencies: + "@eslint/object-schema" "^2.1.4" + debug "^4.3.1" + minimatch "^3.1.2" + +"@eslint/core@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.6.0.tgz#9930b5ba24c406d67a1760e94cdbac616a6eb674" + integrity sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg== + +"@eslint/eslintrc@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.1.0.tgz#dbd3482bfd91efa663cbe7aa1f506839868207b6" + integrity sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^10.0.1" + globals "^14.0.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@9.12.0": + version "9.12.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.12.0.tgz#69ca3ca9fab9a808ec6d67b8f6edb156cbac91e1" + integrity sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA== + +"@eslint/object-schema@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.4.tgz#9e69f8bb4031e11df79e03db09f9dbbae1740843" + integrity sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ== + +"@eslint/plugin-kit@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz#8712dccae365d24e9eeecb7b346f85e750ba343d" + integrity sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig== + dependencies: + levn "^0.4.1" + +"@humanfs/core@^0.19.0": + version "0.19.0" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.0.tgz#08db7a8c73bb07673d9ebd925f2dad746411fcec" + integrity sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw== + +"@humanfs/node@^0.16.5": + version "0.16.5" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.5.tgz#a9febb7e7ad2aff65890fdc630938f8d20aa84ba" + integrity sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg== + dependencies: + "@humanfs/core" "^0.19.0" + "@humanwhocodes/retry" "^0.3.0" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/retry@^0.3.0", "@humanwhocodes/retry@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" + integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== + +"@tootallnate/once@1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" + integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== + +"@types/estree@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" + integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== + +"@types/json-schema@^7.0.15": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/mocha@^2.2.42": + version "2.2.48" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.48.tgz#3523b126a0b049482e1c3c11877460f76622ffab" + integrity sha512-nlK/iyETgafGli8Zh9zJVCTicvU3iajSkRwOh3Hhiva598CMqNJ4NcVCGMTGKpGpTYj/9R8RLzS9NAykSSCqGw== + +"@types/node@^22.7.5": + version "22.7.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b" + integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ== + dependencies: + undici-types "~6.19.2" + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.12.0: + version "8.12.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== + +agent-base@4, agent-base@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" + integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== + dependencies: + es6-promisify "^5.0.0" + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camel-case@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" + integrity sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w== + dependencies: + no-case "^2.2.0" + upper-case "^1.1.1" + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +change-case@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/change-case/-/change-case-3.1.0.tgz#0e611b7edc9952df2e8513b27b42de72647dd17e" + integrity sha512-2AZp7uJZbYEzRPsFoa+ijKdvp9zsrnnt6+yFokfwEpeJm0xuJDVoxiRCAaTzyJND8GJkofo2IcKWaUZ/OECVzw== + dependencies: + camel-case "^3.0.0" + constant-case "^2.0.0" + dot-case "^2.1.0" + header-case "^1.0.0" + is-lower-case "^1.1.0" + is-upper-case "^1.1.0" + lower-case "^1.1.1" + lower-case-first "^1.0.0" + no-case "^2.3.2" + param-case "^2.1.0" + pascal-case "^2.0.0" + path-case "^2.1.0" + sentence-case "^2.1.0" + snake-case "^2.1.0" + swap-case "^1.1.0" + title-case "^2.1.0" + upper-case "^1.1.1" + upper-case-first "^1.1.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +commander@0.6.1: + version "0.6.1" + resolved "http://registry.npmjs.org/commander/-/commander-0.6.1.tgz#fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06" + +commander@2.15.1: + version "2.15.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== + +commander@2.3.0: + version "2.3.0" + resolved "http://registry.npmjs.org/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +constant-case@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/constant-case/-/constant-case-2.0.0.tgz#4175764d389d3fa9c8ecd29186ed6005243b6a46" + integrity sha512-eS0N9WwmjTqrOmR3o83F5vW8Z+9R1HnVz3xmzT2PMFug9ly+Au/fxRWlEBSb6LcZwspSsEn9Xs1uw9YgzAg1EQ== + dependencies: + snake-case "^2.1.0" + upper-case "^1.1.1" + +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" + integrity sha512-X0rGvJcskG1c3TgSCPqHJ0XJgwlcvOC7elJ5Y0hYuKBZoVqWpAMfLOeIh2UI/DCQ5ruodIjvsugZtjUYUw2pUw== + dependencies: + ms "0.7.1" + +debug@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + +debug@4, debug@^4.3.1, debug@^4.3.2: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + +debug@^3.1.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + dependencies: + ms "^2.1.1" + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +diff@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" + +diff@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + +dot-case@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-2.1.1.tgz#34dcf37f50a8e93c2b3bca8bb7fb9155c7da3bee" + integrity sha512-HnM6ZlFqcajLsyudHq7LeeLDr2rFAVYtDv/hV5qchQEidSck8j9OPUsXY9KwJv/lHMtYlX4DjRQqwFYa+0r8Ug== + dependencies: + no-case "^2.2.0" + +es6-promise@^4.0.3: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ== + dependencies: + es6-promise "^4.0.3" + +escape-string-regexp@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" + +escape-string-regexp@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-scope@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.1.0.tgz#70214a174d4cbffbc3e8a26911d8bf51b9ae9d30" + integrity sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint-visitor-keys@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz#1f785cc5e81eb7534523d85922248232077d2f8c" + integrity sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg== + +eslint@^9.12.0: + version "9.12.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.12.0.tgz#54fcba2876c90528396da0fa44b6446329031e86" + integrity sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.11.0" + "@eslint/config-array" "^0.18.0" + "@eslint/core" "^0.6.0" + "@eslint/eslintrc" "^3.1.0" + "@eslint/js" "9.12.0" + "@eslint/plugin-kit" "^0.2.0" + "@humanfs/node" "^0.16.5" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.3.1" + "@types/estree" "^1.0.6" + "@types/json-schema" "^7.0.15" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + escape-string-regexp "^4.0.0" + eslint-scope "^8.1.0" + eslint-visitor-keys "^4.1.0" + espree "^10.2.0" + esquery "^1.5.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^8.0.0" + find-up "^5.0.0" + glob-parent "^6.0.2" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + json-stable-stringify-without-jsonify "^1.0.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + text-table "^0.2.0" + +espree@^10.0.1, espree@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.2.0.tgz#f4bcead9e05b0615c968e85f83816bc386a45df6" + integrity sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g== + dependencies: + acorn "^8.12.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.1.0" + +esquery@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== + dependencies: + flat-cache "^4.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.4" + +flatted@^3.2.9: + version "3.3.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" + integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== + +fs-extra@^11.2.0: + version "11.2.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" + integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +fs@^0.0.1-security: + version "0.0.1-security" + resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.1-security.tgz#8a7bd37186b6dddf3813f23858b57ecaaf5e41d4" + integrity sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w== + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@3.2.11: + version "3.2.11" + resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" + integrity sha512-hVb0zwEZwC1FXSKRPFTeOtN7AArJcJlI6ULGLtrstaswKNlrTJqAA+1lYlSUop4vjA423xlBzqfVS3iWGlqJ+g== + dependencies: + inherits "2" + minimatch "0.3" + +glob@7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.2: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== + +graceful-fs@^4.1.6: + version "4.1.15" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" + +graceful-fs@^4.2.0: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + +growl@1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" + integrity sha512-RTBwDHhNuOx4F0hqzItc/siXCasGfC4DeWcBamclWd+6jWtBaeB/SGbMkGf0eiQoW7ib8JpvOgnUsmgMHI3Mfw== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +he@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + integrity sha512-z/GDPjlRMNOa2XJiB4em8wJpuuBfrFOlYKTZxtpkdr1uPdibHI8rYA3MY0KDObpVyaes0e/aunid/t88ZI2EKA== + +header-case@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/header-case/-/header-case-1.0.1.tgz#9535973197c144b09613cd65d317ef19963bd02d" + integrity sha512-i0q9mkOeSuhXw6bGgiQCCBgY/jlZuV/7dZXyZ9c6LcBrqwvT8eT719E9uxE5LiZftdl+z81Ugbg/VvXV4OJOeQ== + dependencies: + no-case "^2.2.0" + upper-case "^1.1.3" + +http-proxy-agent@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" + integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg== + dependencies: + agent-base "4" + debug "3.1.0" + +http-proxy-agent@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" + integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== + dependencies: + "@tootallnate/once" "1" + agent-base "6" + debug "4" + +https-proxy-agent@^2.2.1: + version "2.2.4" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" + integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== + dependencies: + agent-base "^4.3.0" + debug "^3.1.0" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +ignore@^5.2.0: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-glob@^4.0.0, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-lower-case@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/is-lower-case/-/is-lower-case-1.1.3.tgz#7e147be4768dc466db3bfb21cc60b31e6ad69393" + integrity sha512-+5A1e/WJpLLXZEDlgz4G//WYSHyQBD32qa4Jd3Lw06qQlv3fJHnp3YIHjTQSGzHMgzmVKz2ZP3rBxTHkPw/lxA== + dependencies: + lower-case "^1.1.0" + +is-upper-case@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-upper-case/-/is-upper-case-1.1.2.tgz#8d0b1fa7e7933a1e58483600ec7d9661cbaf756f" + integrity sha512-GQYSJMgfeAmVwh9ixyk888l7OIhNAGKtY6QA+IrWlu9MDTCaXmeozOZ2S9Knj7bQwBO/H6J2kb+pbyTUiMNbsw== + dependencies: + upper-case "^1.1.0" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + +jade@0.26.3: + version "0.26.3" + resolved "https://registry.yarnpkg.com/jade/-/jade-0.26.3.tgz#8f10d7977d8d79f2f6ff862a81b0513ccb25686c" + dependencies: + commander "0.6.1" + mkdirp "0.3.0" + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +keyv@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash@^4.17.11: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +lower-case-first@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/lower-case-first/-/lower-case-first-1.0.2.tgz#e5da7c26f29a7073be02d52bac9980e5922adfa1" + integrity sha512-UuxaYakO7XeONbKrZf5FEgkantPf5DUqDayzP5VXZrtRPdH86s4kN47I8B3TW10S4QKiE3ziHNf3kRN//okHjA== + dependencies: + lower-case "^1.1.2" + +lower-case@^1.1.0, lower-case@^1.1.1, lower-case@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" + integrity sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA== + +lru-cache@2: + version "2.7.3" + resolved "http://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" + +minimatch@0.3: + version "0.3.0" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" + integrity sha512-WFX1jI1AaxNTZVOHLBVazwTWKaQjoykSzCBNXB72vDTCzopQGtyP91tKdFK5cv1+qMwPyiTu1HqUriqplI8pcA== + dependencies: + lru-cache "2" + sigmund "~1.0.0" + +minimatch@3.0.4, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +mkdirp@0.3.0: + version "0.3.0" + resolved "http://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" + +mkdirp@0.5.1: + version "0.5.1" + resolved "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +mocha@^2.3.3: + version "2.5.3" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-2.5.3.tgz#161be5bdeb496771eb9b35745050b622b5aefc58" + integrity sha512-jNt2iEk9FPmZLzL+sm4FNyOIDYXf2wUU6L4Cc8OIKK/kzgMHKPi4YhTZqG4bW4kQVdIv6wutDybRhXfdnujA1Q== + dependencies: + commander "2.3.0" + debug "2.2.0" + diff "1.4.0" + escape-string-regexp "1.0.2" + glob "3.2.11" + growl "1.9.2" + jade "0.26.3" + mkdirp "0.5.1" + supports-color "1.2.0" + to-iso-string "0.0.2" + +mocha@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" + integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== + dependencies: + browser-stdout "1.3.1" + commander "2.15.1" + debug "3.1.0" + diff "3.5.0" + escape-string-regexp "1.0.5" + glob "7.1.2" + growl "1.10.5" + he "1.1.1" + minimatch "3.0.4" + mkdirp "0.5.1" + supports-color "5.4.0" + +ms@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" + integrity sha512-lRLiIR9fSNpnP6TC4v8+4OU7oStC01esuNowdQ34L+Gk8e5Puoc88IqJ+XAY/B3Mn2ZKis8l8HX90oU8ivzUHg== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + +no-case@^2.2.0, no-case@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" + integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== + dependencies: + lower-case "^1.1.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.5" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +param-case@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" + integrity sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w== + dependencies: + no-case "^2.2.0" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +pascal-case@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-2.0.1.tgz#2d578d3455f660da65eca18ef95b4e0de912761e" + integrity sha512-qjS4s8rBOJa2Xm0jmxXiyh1+OFf6ekCWOvUaRgAQSktzlTbMotS0nmG9gyYAybCWBcuP4fsBeRCKNwGBnMe2OQ== + dependencies: + camel-case "^3.0.0" + upper-case-first "^1.1.0" + +path-case@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/path-case/-/path-case-2.1.1.tgz#94b8037c372d3fe2906e465bb45e25d226e8eea5" + integrity sha512-Ou0N05MioItesaLr9q8TtHVWmJ6fxWdqKB2RohFmNWVyJ+2zeKIeDNWAN6B/Pe7wpzWChhZX6nONYmOnMeJQ/Q== + dependencies: + no-case "^2.2.0" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +rxjs@^5.0.0-rc.1: + version "5.5.12" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.12.tgz#6fa61b8a77c3d793dbaf270bee2f43f652d741cc" + integrity sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw== + dependencies: + symbol-observable "1.0.1" + +semver@^5.4.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +sentence-case@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-2.1.1.tgz#1f6e2dda39c168bf92d13f86d4a918933f667ed4" + integrity sha512-ENl7cYHaK/Ktwk5OTD+aDbQ3uC8IByu/6Bkg+HDv8Mm+XnBnppVNalcfJTNsp1ibstKh030/JKQQWglDvtKwEQ== + dependencies: + no-case "^2.2.0" + upper-case-first "^1.1.2" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +sigmund@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + +snake-case@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-2.1.0.tgz#41bdb1b73f30ec66a04d4e2cad1b76387d4d6d9f" + integrity sha512-FMR5YoPFwOLuh4rRz92dywJjyKYZNLpMn1R5ujVpIYkbA9p01fq8RMg0FkO4M+Yobt4MjHeLTJVm5xFFBHSV2Q== + dependencies: + no-case "^2.2.0" + +source-map-support@^0.5.0: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.2.0.tgz#ff1ed1e61169d06b3cf2d588e188b18d8847e17e" + +supports-color@5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +swap-case@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/swap-case/-/swap-case-1.1.2.tgz#c39203a4587385fad3c850a0bd1bcafa081974e3" + integrity sha512-BAmWG6/bx8syfc6qXPprof3Mn5vQgf5dwdUNJhsNqU9WdPt5P+ES/wQ5bxfijy8zwZgZZHslC3iAsxsuQMCzJQ== + dependencies: + lower-case "^1.1.1" + upper-case "^1.1.1" + +symbol-observable@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" + integrity sha512-Kb3PrPYz4HanVF1LVGuAdW6LoVgIwjUYJGzFe7NDrBLCN4lsV/5J0MFurV+ygS4bRVwrCEt2c7MQ1R2a72oJDw== + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +title-case@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/title-case/-/title-case-2.1.1.tgz#3e127216da58d2bc5becf137ab91dae3a7cd8faa" + integrity sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q== + dependencies: + no-case "^2.2.0" + upper-case "^1.0.3" + +to-iso-string@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1" + integrity sha512-oeHLgfWA7d0CPQa6h0+i5DAJZISz5un0d5SHPkw+Untclcvzv9T+AC3CvGXlZJdOlIbxbTfyyzlqCXc5hjpXYg== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +typescript@^5.6.3: + version "5.6.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b" + integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw== + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + +upper-case-first@^1.1.0, upper-case-first@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-1.1.2.tgz#5d79bedcff14419518fd2edb0a0507c9b6859115" + integrity sha512-wINKYvI3Db8dtjikdAqoBbZoP6Q+PZUyfMR7pmwHzjC2quzSkUq5DmPrTtPEqHaz8AGtmsB4TqwapMTM1QAQOQ== + dependencies: + upper-case "^1.1.1" + +upper-case@^1.0.3, upper-case@^1.1.0, upper-case@^1.1.1, upper-case@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" + integrity sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA== + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +vscode-test@^0.4.1: + version "0.4.3" + resolved "https://registry.yarnpkg.com/vscode-test/-/vscode-test-0.4.3.tgz#461ebf25fc4bc93d77d982aed556658a2e2b90b8" + integrity sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w== + dependencies: + http-proxy-agent "^2.1.0" + https-proxy-agent "^2.2.1" + +vscode@^1.1.37: + version "1.1.37" + resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.37.tgz#c2a770bee4bb3fff765e2b72c7bcc813b8a6bb0a" + integrity sha512-vJNj6IlN7IJPdMavlQa1KoFB3Ihn06q1AiN3ZFI/HfzPNzbKZWPPuiU+XkpNOfGU5k15m4r80nxNPlM7wcc0wg== + dependencies: + glob "^7.1.2" + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + mocha "^5.2.0" + semver "^5.4.1" + source-map-support "^0.5.0" + vscode-test "^0.4.1" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==