├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── cli.js ├── package.json ├── src ├── generate.ts ├── index.ts ├── svelte.d.ts ├── tests │ ├── index.ts │ ├── to-svelte.test.ts │ └── utils.test.ts ├── to-svelte.ts └── utils.ts ├── tsconfig.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /icons 2 | /dist 3 | /node_modules 4 | /lib 5 | .DS_Store 6 | yarn-debug.log* 7 | yarn-error.log* -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 12 3 | cache: yarn 4 | script: 5 | - yarn test 6 | - yarn prepack 7 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## Unreleased 9 | 10 | - generate documentation 11 | - custom svg element properties (filter, add) 12 | - inject script/styles 13 | - allow direction for adding a prop (i.e. before/after `$$restProps`) 14 | 15 | ## [2.2.1](https://github.com/metonym/svg-to-svelte/releases/tag/v2.2.1) - 2021-07-24 16 | 17 | - include missing `cli.js` in source control 18 | - ignore `a11y-mouse-events-have-key-events` warning 19 | 20 | ## [2.2.0](https://github.com/metonym/svg-to-svelte/releases/tag/v2.2.0) - 2021-02-03 21 | 22 | - add CLI wrapper for generate 23 | 24 | ## [2.1.1](https://github.com/metonym/svg-to-svelte/releases/tag/v2.1.1) - 2021-02-03 25 | 26 | - remove sample code 27 | 28 | ## [2.1.0](https://github.com/metonym/svg-to-svelte/releases/tag/v2.1.0) - 2021-02-03 29 | 30 | - add `generate` method 31 | 32 | ## [2.0.0](https://github.com/metonym/svg-to-svelte/releases/tag/v2.0.0) - 2020-08-25 33 | 34 | - use sync behavior 35 | - breaking change: by default, `generateFromFolder` will clean the output directory 36 | 37 | ## [1.1.2](https://github.com/metonym/svg-to-svelte/releases/tag/v1.1.2) - 2020-08-25 38 | 39 | - fix async behavior 40 | 41 | ## [1.1.1](https://github.com/metonym/svg-to-svelte/releases/tag/v1.1.1) - 2020-08-25 42 | 43 | - do not add component to exports if failed to generate 44 | 45 | ## [1.1.0](https://github.com/metonym/svg-to-svelte/releases/tag/v1.1.0) - 2020-08-25 46 | 47 | - add `generateIndex` to generate icon index in Markdown format 48 | 49 | ## [1.0.1](https://github.com/metonym/svg-to-svelte/releases/tag/v1.0.1) - 2020-08-22 50 | 51 | - fix `generateFromFolder` to handle duplicate module names 52 | 53 | ## [1.0.0](https://github.com/metonym/svg-to-svelte/releases/tag/v1.0.0) - 2020-08-04 54 | 55 | - replace svg-parser with svelte compiler to componentize svg (Breaking change: `toSvelte` method no longer accepts a second parameter for options) 56 | 57 | ## [0.3.8](https://github.com/metonym/svg-to-svelte/releases/tag/v0.3.8) - 2020-05-10 58 | 59 | - Hot fix: append class after `$$restProps` 60 | 61 | ## [0.3.7](https://github.com/metonym/svg-to-svelte/releases/tag/v0.3.7) - 2020-05-10 62 | 63 | - Support optional `slot` for `toSvelte` 64 | 65 | ## [0.3.6](https://github.com/metonym/svg-to-svelte/releases/tag/v0.3.6) - 2020-05-10 66 | 67 | - `$$restProps` should override default SVG attributes 68 | 69 | ## [0.3.5](https://github.com/metonym/svg-to-svelte/releases/tag/v0.3.5) - 2020-05-04 70 | 71 | - Prefix first word with underscore that starts with a number 72 | 73 | ## [0.3.4](https://github.com/metonym/svg-to-svelte/releases/tag/v0.3.4) - 2020-05-03 74 | 75 | - Move writeFile order 76 | 77 | ## [0.3.3](https://github.com/metonym/svg-to-svelte/releases/tag/v0.3.3) - 2020-05-03 78 | 79 | - Push to moduleName, imports arrays before writing 80 | 81 | ## [0.3.2](https://github.com/metonym/svg-to-svelte/releases/tag/v0.3.2) - 2020-05-03 82 | 83 | - Fix to ensure output directory is created 84 | 85 | ## [0.3.1](https://github.com/metonym/svg-to-svelte/releases/tag/v0.3.1) - 2020-05-03 86 | 87 | - Promisify `fs` methods 88 | 89 | ## [0.3.0](https://github.com/metonym/svg-to-svelte/releases/tag/v0.3.0) - 2020-04-24 90 | 91 | - Remove `generate` method 92 | 93 | - Remove `svelte`, `prettier` from dependencies 94 | 95 | ## [0.2.1](https://github.com/metonym/svg-to-svelte/releases/tag/v0.2.1) - 2020-04-24 96 | 97 | - Support clean option in `generateFromFolder` 98 | 99 | ## [0.2.0](https://github.com/metonym/svg-to-svelte/releases/tag/v0.2.0) - 2020-04-24 100 | 101 | - Support optional `onModuleName` hook (`(moduleName: string) => moduleName`) 102 | 103 | ## [0.1.1](https://github.com/metonym/svg-to-svelte/releases/tag/v0.1.1) - 2020-04-24 104 | 105 | - Drop Svelte formatting 106 | 107 | ## [0.1.0](https://github.com/metonym/svg-to-svelte/releases/tag/v0.1.0) - 2020-04-24 108 | 109 | - Initial release 110 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020-present Eric Liu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # svg-to-svelte 2 | 3 | [![NPM][npm]][npm-url] 4 | [![Build][build]][build-badge] 5 | 6 | > Convert SVG files to Svelte components. 7 | 8 | ## Background 9 | 10 | Today, a comprehensive UI design system typically ships with icons that underline its brand. Usually, icon components are generated from a folder containing raw SVG files. The reason for "componentizing" SVG files is to make it easier to consume in a library or framework like React, Vue, or Angular. 11 | 12 | Svelte is a relatively new language; there are not many existing design systems that implement SVG icons as Svelte components. 13 | 14 | This library uses the Svelte compiler to convert SVG icon libraries into Svelte components. 15 | 16 | This is accomplished by the following: 17 | 18 | - forward `$$restProps` to the SVG element 19 | - forward common events: `click`, `mouseover`, `mouseenter`, `mouseleave`, `keydown` 20 | - enable the default `slot` 21 | 22 | ```diff 23 | - 24 | + 25 | ``` 26 | 27 | More generally, this utility experiments with augmenting plain HTML into Svelte. 28 | 29 | Icon libraries generated using `svg-to-svelte`: 30 | 31 | - **[svelte-atlaskit-icons](https://github.com/metonym/svelte-atlaskit-icons)** (Atlassian Atlaskit) 32 | - **[svelte-baseui-icons](https://github.com/metonym/svelte-baseui-icons)**: (Uber Base Web) 33 | - **[svelte-bootstrap-icons](https://github.com/metonym/svelte-bootstrap-icons)** (Bootstrap) 34 | - **[svelte-eui-icons](https://github.com/metonym/svelte-eui-icons)** (Elastic EUI) 35 | - **[svelte-gestalt-icons](https://github.com/metonym/svelte-gestalt-icons)** (Pinterest Gestalt) 36 | - **[svelte-leafygreen-icons](https://github.com/metonym/svelte-leafygreen-icons)**: (MongoDB Leafygreen) 37 | - **[svelte-polaris-icons](https://github.com/metonym/svelte-polaris-icons)** (Shopify Polaris) 38 | - **[svelte-spectrum-icons](https://github.com/metonym/svelte-spectrum-icons)** (Adobe Spectrum) 39 | - **[svelte-super-tiny-icons](https://github.com/metonym/svelte-super-tiny-icons)** (Super Tiny Icons) 40 | 41 | ## Install 42 | 43 | **Note: this module requires Node.js version 12 or greater.** 44 | 45 | ```bash 46 | yarn add -D svg-to-svelte 47 | ``` 48 | 49 | ## Usage 50 | 51 | ### `generateFromFolder` 52 | 53 | The fastest way is to specify the path to a folder that contains SVG elements. 54 | 55 | The second parameter is the output directory. By default, it is "lib." 56 | 57 | ```js 58 | const { generateFromFolder } = require("svg-to-svelte"); 59 | 60 | (async () => { 61 | await generateFromFolder("node_modules/gestalt/src/icons", "lib", { 62 | clean: true, 63 | }); 64 | // reads all SVG files from the path "node_modules/gestalt/src/icons" 65 | // generates a Svelte component per SVG file in the "lib" output folder 66 | })(); 67 | ``` 68 | 69 | ### `generateIndex` 70 | 71 | The `generateIndex` method generates static documentation listing the module names for the library in Markdown format. 72 | 73 | ```ts 74 | interface GenerateIndexOptions { 75 | title?: string; // title of the generated markdown file 76 | pkgName: string; // name of the Svelte package name 77 | pkgVersion: string; // version of the Svelte icon library 78 | moduleNames: ModuleNames; // module names returned by `generateFromFolder` 79 | outputFile?: string; // name of the markdown output file 80 | libraryFolder?: string; // name of the folder containing generated Svelte components 81 | } 82 | ``` 83 | 84 | ```js 85 | const { generateIndex } = require("svg-to-svelte"); 86 | const { name, devDependencies } = require("./package.json"); 87 | 88 | (async () => { 89 | const libraryFolder = "lib"; 90 | 91 | const { moduleNames } = await generateFromFolder( 92 | "node_modules/gestalt/src/icons", 93 | libraryFolder 94 | ); 95 | 96 | // generates components from `gestalt` into the "lib" folder 97 | 98 | await generateIndex({ 99 | moduleNames, 100 | pkgName: name, 101 | pkgVersion: devDependencies["gestalt"], 102 | outputFile: "ICON_INDEX.md", 103 | libraryFolder, 104 | }); 105 | 106 | // writes the file to "ICON_INDEX.md" 107 | })(); 108 | ``` 109 | 110 | ### `generate` 111 | 112 | The `generate` method executes both the `generateFromFolder` and `generateIndex` functions. 113 | 114 | The only parameter it accepts is the path to the source folder. 115 | 116 | ```js 117 | require("svg-to-svelte").generate("node_modules/gestalt/src/icons"); 118 | ``` 119 | 120 | #### CLI usage 121 | 122 | ```sh 123 | svg-to-svelte --input=node_modules/gestalt/src/icons 124 | # OR 125 | s2s --input=node_modules/gestalt/src/icons 126 | ``` 127 | 128 | #### Options 129 | 130 | An optional third argument passed to `generateFromFolder` include: 131 | 132 | ```ts 133 | interface GenerateFromFolderOptions { 134 | clean: boolean; // remove and create output directory (default is `true`) 135 | onModuleName: (moduleName: string) => string; // called when the `moduleName` is created 136 | } 137 | ``` 138 | 139 | ### `toSvelte` 140 | 141 | The `toSvelte` method converts an SVG string to Svelte. 142 | 143 | ```js 144 | const { toSvelte } = require("svg-to-svelte"); 145 | 146 | const result = toSvelte(``); 147 | /** 148 | * `result.template`: Svelte file as a string 149 | */ 150 | ``` 151 | 152 | ### `toModuleName` 153 | 154 | The `toModuleName` converts a file name to an exportable module name. 155 | 156 | - `add-file.svg` --> `AddFile` 157 | - `123--alt.svg` --> `_123Alt` 158 | 159 | ```ts 160 | const { toModuleName } = require("svg-to-svelte"); 161 | 162 | toModuleName("add-file.svg"); // AddFile 163 | ``` 164 | 165 | ### `cleanDir` 166 | 167 | The `cleanDir` method is an asynchronous method that removes and creates a directory. 168 | 169 | ```ts 170 | const { cleanDir } = require("svg-to-svelte"); 171 | 172 | cleanDir("lib"); 173 | ``` 174 | 175 | ## [Changelog](CHANGELOG.md) 176 | 177 | ## License 178 | 179 | [MIT](LICENSE) 180 | 181 | [npm]: https://img.shields.io/npm/v/svg-to-svelte.svg?color=blue 182 | [npm-url]: https://npmjs.com/package/svg-to-svelte 183 | [build]: https://travis-ci.com/metonym/svg-to-svelte.svg?branch=master 184 | [build-badge]: https://travis-ci.com/metonym/svg-to-svelte 185 | -------------------------------------------------------------------------------- /cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const input = process.argv.slice(2).map((flag) => { 4 | const [key, value] = flag.split("="); 5 | if (key === "--input") return value; 6 | })[0]; 7 | 8 | require("./dist").generate(input); 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svg-to-svelte", 3 | "version": "2.2.1", 4 | "license": "MIT", 5 | "description": "Convert SVG files to Svelte components", 6 | "author": "Eric Liu (https://github.com/metonym)", 7 | "main": "./dist/index.js", 8 | "types": "./dist/index.d.ts", 9 | "engines": { 10 | "node": ">=12" 11 | }, 12 | "scripts": { 13 | "develop": "tsnd --respawn --transpile-only src", 14 | "test": "tsnd --transpile-only src/tests", 15 | "test:tdd": "tsnd --respawn --transpile-only src/tests", 16 | "prepack": "tsc" 17 | }, 18 | "dependencies": { 19 | "svelte": "^3.32.1" 20 | }, 21 | "devDependencies": { 22 | "@types/node": "^14.14.23", 23 | "ts-node-dev": "1.1.1", 24 | "typescript": "4.1.3" 25 | }, 26 | "repository": { 27 | "type": "git", 28 | "url": "https://github.com/metonym/svg-to-svelte.git" 29 | }, 30 | "homepage": "https://github.com/metonym/svg-to-svelte", 31 | "bugs": "https://github.com/metonym/svg-to-svelte/issues", 32 | "keywords": [ 33 | "svelte", 34 | "svelte component", 35 | "svg", 36 | "icon", 37 | "library" 38 | ], 39 | "files": [ 40 | "dist", 41 | "cli.js" 42 | ], 43 | "bin": { 44 | "svg-to-svelte": "./cli.js", 45 | "s2s": "./cli.js" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/generate.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import * as path from "path"; 3 | import { toModuleName } from "./utils"; 4 | import { toSvelte } from "./to-svelte"; 5 | import { performance } from "perf_hooks"; 6 | import { promisify } from "util"; 7 | 8 | const readdir = promisify(fs.readdir); 9 | const rmdir = promisify(fs.rmdir); 10 | const mkdir = promisify(fs.mkdir); 11 | const readFile = promisify(fs.readFile); 12 | const writeFile = promisify(fs.writeFile); 13 | 14 | export async function cleanDir(folder: string) { 15 | const dir = path.join(process.cwd(), folder); 16 | await rmdir(dir, { recursive: true }); 17 | await mkdir(dir); 18 | } 19 | 20 | type ModuleNames = string[]; 21 | 22 | export async function generateFromFolder( 23 | source_folder: string, 24 | folder: string = "lib", 25 | options: { 26 | clean?: boolean; 27 | onModuleName?: (moduleName: string) => string; 28 | } = {} 29 | ) { 30 | if (options.clean !== false) { 31 | await cleanDir(folder); 32 | } 33 | 34 | const start = performance.now(); 35 | const moduleNames: string[] = []; 36 | const imports: string[] = []; 37 | const files = await readdir(path.join(process.cwd(), source_folder)); 38 | const generatedFiles = new Set(); 39 | 40 | files 41 | .filter((file) => file.endsWith(".svg")) 42 | .forEach(async (file) => { 43 | const filePath = path.join(process.cwd(), source_folder, file); 44 | 45 | let moduleName = toModuleName(path.basename(filePath)); 46 | 47 | if (generatedFiles.has(moduleName)) { 48 | process.stdout.write(`"${moduleName}" already exists.\n`); 49 | return; 50 | } 51 | 52 | try { 53 | const source = fs.readFileSync(filePath, "utf-8"); 54 | const template = toSvelte(source).template; 55 | 56 | generatedFiles.add(moduleName); 57 | 58 | if (options.onModuleName) { 59 | moduleName = options.onModuleName(moduleName); 60 | } 61 | 62 | moduleNames.push(moduleName); 63 | imports.push(`export { ${moduleName} } from "./${moduleName}";`); 64 | 65 | const moduleFolder = path.join(process.cwd(), folder, moduleName); 66 | 67 | fs.mkdirSync(moduleFolder); 68 | fs.writeFileSync( 69 | path.join(moduleFolder, "index.js"), 70 | `import ${moduleName} from "./${moduleName}.svelte";\nexport { ${moduleName} };\nexport default ${moduleName};` 71 | ); 72 | fs.writeFileSync( 73 | path.join(moduleFolder, `${moduleName}.svelte`), 74 | template 75 | ); 76 | } catch (e) { 77 | process.stdout.write( 78 | `Failed to generate "${moduleName}." Omitting...\n` 79 | ); 80 | } 81 | }); 82 | 83 | await writeFile( 84 | path.join(process.cwd(), folder, "index.js"), 85 | imports.join("\n") 86 | ); 87 | 88 | process.stdout.write( 89 | `⚡ Converted ${imports.length} SVG files in ${( 90 | (performance.now() - start) / 91 | 1000 92 | ).toFixed(2)}s.` + "\n" 93 | ); 94 | 95 | return { moduleNames }; 96 | } 97 | 98 | export async function generateIndex(opts: { 99 | title?: string; 100 | pkgName: string; 101 | pkgVersion: string; 102 | moduleNames: ModuleNames; 103 | outputFile?: string; 104 | libraryFolder?: string; 105 | }) { 106 | const moduleNames = opts.moduleNames || []; 107 | const index = `# ${opts.title || "Icon Index"}\n 108 | > ${moduleNames.length} icons from ${opts.pkgName}@${opts.pkgVersion}.\n 109 | ## Usage\n 110 | \`\`\`html 111 | 116 | 117 | 118 | \`\`\`\n 119 | ## Icons by \`ModuleName\`\n 120 | ${moduleNames.map((name) => `- ${name}`).join("\n")}\n`; 121 | 122 | if (opts.outputFile !== undefined) { 123 | await writeFile(opts.outputFile, index); 124 | } 125 | 126 | return { index }; 127 | } 128 | 129 | export async function generate(source_folder: string) { 130 | const { moduleNames } = await generateFromFolder(source_folder); 131 | 132 | console.log(`[generate] Created ${moduleNames.length} components from "${source_folder}".`); 133 | 134 | const pkg_json = path.join(process.cwd(), 'package.json'); 135 | 136 | if (fs.existsSync(pkg_json)) { 137 | const pkg = JSON.parse(fs.readFileSync(pkg_json, 'utf-8')); 138 | const pkgName = pkg.name; 139 | const pkgVersion = pkg.version; 140 | 141 | console.log(`[generate] Creating icon index for ${pkgName}@${pkgVersion}`); 142 | 143 | await generateIndex({ 144 | moduleNames, 145 | pkgName, 146 | pkgVersion, 147 | outputFile: "ICON_INDEX.md", 148 | }); 149 | } else { 150 | console.log('[generate] Could not locate `package.json`') 151 | } 152 | } -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { cleanDir, generateFromFolder, generateIndex, generate } from "./generate"; 2 | export { toSvelte } from "./to-svelte"; 3 | export { toModuleName } from "./utils"; 4 | -------------------------------------------------------------------------------- /src/svelte.d.ts: -------------------------------------------------------------------------------- 1 | declare module "svelte/compiler" { 2 | export const walk: any; 3 | export const parse: any; 4 | } 5 | -------------------------------------------------------------------------------- /src/tests/index.ts: -------------------------------------------------------------------------------- 1 | import "./to-svelte.test"; 2 | import "./utils.test"; 3 | -------------------------------------------------------------------------------- /src/tests/to-svelte.test.ts: -------------------------------------------------------------------------------- 1 | import { toSvelte } from "../to-svelte"; 2 | import { strict } from "assert"; 3 | 4 | const result = toSvelte(` 5 | 6 | 7 | 8 | 9 | 10 | 11 | `); 12 | 13 | strict.equal( 14 | result.template, 15 | ` 16 | 17 | 18 | 19 | 20 | 21 | ` 22 | ); 23 | -------------------------------------------------------------------------------- /src/tests/utils.test.ts: -------------------------------------------------------------------------------- 1 | import * as utils from "../utils"; 2 | import { strict } from "assert"; 3 | 4 | strict.equal(utils.toModuleName("one two three.svg"), "OneTwoThree"); 5 | strict.equal(utils.toModuleName("one--two-three.svg"), "OneTwoThree"); 6 | strict.equal(utils.toModuleName("1--two__three.svg"), "_1TwoThree"); 7 | strict.equal(utils.toModuleName("arrow-90deg-up.svg"), "Arrow90degUp"); 8 | -------------------------------------------------------------------------------- /src/to-svelte.ts: -------------------------------------------------------------------------------- 1 | import { walk, parse } from "svelte/compiler"; 2 | 3 | export function toSvelte(svg: string) { 4 | let svg_attributes = ""; 5 | let svg_children = ""; 6 | 7 | walk(parse(svg), { 8 | enter(node: any) { 9 | if (node.type === "Element" && node.name === "svg") { 10 | node.children.forEach((child: any) => { 11 | const { start, end } = child; 12 | svg_children += svg.slice(start, end); 13 | }); 14 | 15 | node.attributes.forEach((attr: any) => { 16 | const { name, value } = attr; 17 | if (name === "class") { 18 | value[0].raw.split(" ").forEach((name: any) => { 19 | svg_attributes += ` class:${name}={true}`; 20 | }); 21 | } else { 22 | svg_attributes += ` ${name}="${value[0].raw}"`; 23 | } 24 | }); 25 | } 26 | }, 27 | }); 28 | 29 | return { 30 | template: `${svg_children}`, 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | export function toModuleName(name: string) { 2 | return name 3 | .replace(/\_+|-+/g, " ") 4 | .replace(/\.svg/g, "") 5 | .split(" ") 6 | .map((_, i) => { 7 | let first_char = _.slice(0, 1); 8 | 9 | if (i === 0 && first_char.match(/[0-9]/)) { 10 | first_char = "_" + first_char; 11 | } 12 | 13 | return first_char.toUpperCase() + _.slice(1); 14 | }) 15 | .join(""); 16 | } 17 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "lib": ["esnext", "DOM"], 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "skipLibCheck": true, 8 | "outDir": "dist", 9 | "strict": false, 10 | "target": "es5" 11 | }, 12 | "include": ["src"], 13 | "exclude": ["src/tests"] 14 | } 15 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@types/node@^14.14.23": 6 | version "14.14.23" 7 | resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.23.tgz#2dfa2c74cfddbaf9649b407190a2ed1a1433c60d" 8 | integrity sha512-pkKXgf96TELUhrc8C01J0e+If5qb0WqF+WF09FbCINywIk+iUEQgMlA8IxgdZ79qQ88Bljw+9NcqwvWGXknWDw== 9 | 10 | "@types/strip-bom@^3.0.0": 11 | version "3.0.0" 12 | resolved "https://registry.yarnpkg.com/@types/strip-bom/-/strip-bom-3.0.0.tgz#14a8ec3956c2e81edb7520790aecf21c290aebd2" 13 | integrity sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I= 14 | 15 | "@types/strip-json-comments@0.0.30": 16 | version "0.0.30" 17 | resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1" 18 | integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ== 19 | 20 | anymatch@~3.1.1: 21 | version "3.1.1" 22 | resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" 23 | integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== 24 | dependencies: 25 | normalize-path "^3.0.0" 26 | picomatch "^2.0.4" 27 | 28 | arg@^4.1.0: 29 | version "4.1.3" 30 | resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" 31 | integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== 32 | 33 | array-find-index@^1.0.1: 34 | version "1.0.2" 35 | resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" 36 | integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= 37 | 38 | balanced-match@^1.0.0: 39 | version "1.0.0" 40 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 41 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 42 | 43 | binary-extensions@^2.0.0: 44 | version "2.1.0" 45 | resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" 46 | integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== 47 | 48 | brace-expansion@^1.1.7: 49 | version "1.1.11" 50 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 51 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 52 | dependencies: 53 | balanced-match "^1.0.0" 54 | concat-map "0.0.1" 55 | 56 | braces@~3.0.2: 57 | version "3.0.2" 58 | resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 59 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 60 | dependencies: 61 | fill-range "^7.0.1" 62 | 63 | buffer-from@^1.0.0: 64 | version "1.1.1" 65 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" 66 | integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== 67 | 68 | camelcase-keys@^2.0.0: 69 | version "2.1.0" 70 | resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" 71 | integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc= 72 | dependencies: 73 | camelcase "^2.0.0" 74 | map-obj "^1.0.0" 75 | 76 | camelcase@^2.0.0: 77 | version "2.1.1" 78 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" 79 | integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= 80 | 81 | chokidar@^3.4.0: 82 | version "3.4.2" 83 | resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz#38dc8e658dec3809741eb3ef7bb0a47fe424232d" 84 | integrity sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A== 85 | dependencies: 86 | anymatch "~3.1.1" 87 | braces "~3.0.2" 88 | glob-parent "~5.1.0" 89 | is-binary-path "~2.1.0" 90 | is-glob "~4.0.1" 91 | normalize-path "~3.0.0" 92 | readdirp "~3.4.0" 93 | optionalDependencies: 94 | fsevents "~2.1.2" 95 | 96 | concat-map@0.0.1: 97 | version "0.0.1" 98 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 99 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 100 | 101 | currently-unhandled@^0.4.1: 102 | version "0.4.1" 103 | resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" 104 | integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= 105 | dependencies: 106 | array-find-index "^1.0.1" 107 | 108 | dateformat@~1.0.4-1.2.3: 109 | version "1.0.12" 110 | resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" 111 | integrity sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk= 112 | dependencies: 113 | get-stdin "^4.0.1" 114 | meow "^3.3.0" 115 | 116 | decamelize@^1.1.2: 117 | version "1.2.0" 118 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" 119 | integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= 120 | 121 | diff@^4.0.1: 122 | version "4.0.2" 123 | resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" 124 | integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== 125 | 126 | dynamic-dedupe@^0.3.0: 127 | version "0.3.0" 128 | resolved "https://registry.yarnpkg.com/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz#06e44c223f5e4e94d78ef9db23a6515ce2f962a1" 129 | integrity sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE= 130 | dependencies: 131 | xtend "^4.0.0" 132 | 133 | error-ex@^1.2.0: 134 | version "1.3.2" 135 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" 136 | integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== 137 | dependencies: 138 | is-arrayish "^0.2.1" 139 | 140 | fill-range@^7.0.1: 141 | version "7.0.1" 142 | resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 143 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 144 | dependencies: 145 | to-regex-range "^5.0.1" 146 | 147 | find-up@^1.0.0: 148 | version "1.1.2" 149 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" 150 | integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= 151 | dependencies: 152 | path-exists "^2.0.0" 153 | pinkie-promise "^2.0.0" 154 | 155 | fs.realpath@^1.0.0: 156 | version "1.0.0" 157 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 158 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 159 | 160 | fsevents@~2.1.2: 161 | version "2.1.3" 162 | resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" 163 | integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== 164 | 165 | get-stdin@^4.0.1: 166 | version "4.0.1" 167 | resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" 168 | integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= 169 | 170 | glob-parent@~5.1.0: 171 | version "5.1.1" 172 | resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" 173 | integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== 174 | dependencies: 175 | is-glob "^4.0.1" 176 | 177 | glob@^7.1.3: 178 | version "7.1.6" 179 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" 180 | integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== 181 | dependencies: 182 | fs.realpath "^1.0.0" 183 | inflight "^1.0.4" 184 | inherits "2" 185 | minimatch "^3.0.4" 186 | once "^1.3.0" 187 | path-is-absolute "^1.0.0" 188 | 189 | graceful-fs@^4.1.2: 190 | version "4.2.3" 191 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" 192 | integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== 193 | 194 | hosted-git-info@^2.1.4: 195 | version "2.8.8" 196 | resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" 197 | integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== 198 | 199 | indent-string@^2.1.0: 200 | version "2.1.0" 201 | resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" 202 | integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= 203 | dependencies: 204 | repeating "^2.0.0" 205 | 206 | inflight@^1.0.4: 207 | version "1.0.6" 208 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 209 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 210 | dependencies: 211 | once "^1.3.0" 212 | wrappy "1" 213 | 214 | inherits@2: 215 | version "2.0.4" 216 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 217 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 218 | 219 | is-arrayish@^0.2.1: 220 | version "0.2.1" 221 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 222 | integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= 223 | 224 | is-binary-path@~2.1.0: 225 | version "2.1.0" 226 | resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" 227 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== 228 | dependencies: 229 | binary-extensions "^2.0.0" 230 | 231 | is-extglob@^2.1.1: 232 | version "2.1.1" 233 | resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 234 | integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= 235 | 236 | is-finite@^1.0.0: 237 | version "1.1.0" 238 | resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" 239 | integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== 240 | 241 | is-glob@^4.0.1, is-glob@~4.0.1: 242 | version "4.0.1" 243 | resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" 244 | integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== 245 | dependencies: 246 | is-extglob "^2.1.1" 247 | 248 | is-number@^7.0.0: 249 | version "7.0.0" 250 | resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 251 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 252 | 253 | is-utf8@^0.2.0: 254 | version "0.2.1" 255 | resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" 256 | integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= 257 | 258 | load-json-file@^1.0.0: 259 | version "1.1.0" 260 | resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" 261 | integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= 262 | dependencies: 263 | graceful-fs "^4.1.2" 264 | parse-json "^2.2.0" 265 | pify "^2.0.0" 266 | pinkie-promise "^2.0.0" 267 | strip-bom "^2.0.0" 268 | 269 | loud-rejection@^1.0.0: 270 | version "1.6.0" 271 | resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" 272 | integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= 273 | dependencies: 274 | currently-unhandled "^0.4.1" 275 | signal-exit "^3.0.0" 276 | 277 | make-error@^1.1.1: 278 | version "1.3.6" 279 | resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" 280 | integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== 281 | 282 | map-obj@^1.0.0, map-obj@^1.0.1: 283 | version "1.0.1" 284 | resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" 285 | integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= 286 | 287 | meow@^3.3.0: 288 | version "3.7.0" 289 | resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" 290 | integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= 291 | dependencies: 292 | camelcase-keys "^2.0.0" 293 | decamelize "^1.1.2" 294 | loud-rejection "^1.0.0" 295 | map-obj "^1.0.1" 296 | minimist "^1.1.3" 297 | normalize-package-data "^2.3.4" 298 | object-assign "^4.0.1" 299 | read-pkg-up "^1.0.1" 300 | redent "^1.0.0" 301 | trim-newlines "^1.0.0" 302 | 303 | minimatch@^3.0.4: 304 | version "3.0.4" 305 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 306 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 307 | dependencies: 308 | brace-expansion "^1.1.7" 309 | 310 | minimist@^1.1.3, minimist@^1.2.5: 311 | version "1.2.5" 312 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" 313 | integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== 314 | 315 | mkdirp@^1.0.4: 316 | version "1.0.4" 317 | resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" 318 | integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== 319 | 320 | normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: 321 | version "2.5.0" 322 | resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" 323 | integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== 324 | dependencies: 325 | hosted-git-info "^2.1.4" 326 | resolve "^1.10.0" 327 | semver "2 || 3 || 4 || 5" 328 | validate-npm-package-license "^3.0.1" 329 | 330 | normalize-path@^3.0.0, normalize-path@~3.0.0: 331 | version "3.0.0" 332 | resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" 333 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== 334 | 335 | object-assign@^4.0.1: 336 | version "4.1.1" 337 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 338 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 339 | 340 | once@^1.3.0: 341 | version "1.4.0" 342 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 343 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 344 | dependencies: 345 | wrappy "1" 346 | 347 | parse-json@^2.2.0: 348 | version "2.2.0" 349 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" 350 | integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= 351 | dependencies: 352 | error-ex "^1.2.0" 353 | 354 | path-exists@^2.0.0: 355 | version "2.1.0" 356 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" 357 | integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= 358 | dependencies: 359 | pinkie-promise "^2.0.0" 360 | 361 | path-is-absolute@^1.0.0: 362 | version "1.0.1" 363 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 364 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 365 | 366 | path-parse@^1.0.6: 367 | version "1.0.6" 368 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" 369 | integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== 370 | 371 | path-type@^1.0.0: 372 | version "1.1.0" 373 | resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" 374 | integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= 375 | dependencies: 376 | graceful-fs "^4.1.2" 377 | pify "^2.0.0" 378 | pinkie-promise "^2.0.0" 379 | 380 | picomatch@^2.0.4, picomatch@^2.2.1: 381 | version "2.2.2" 382 | resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" 383 | integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== 384 | 385 | pify@^2.0.0: 386 | version "2.3.0" 387 | resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" 388 | integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= 389 | 390 | pinkie-promise@^2.0.0: 391 | version "2.0.1" 392 | resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" 393 | integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= 394 | dependencies: 395 | pinkie "^2.0.0" 396 | 397 | pinkie@^2.0.0: 398 | version "2.0.4" 399 | resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" 400 | integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= 401 | 402 | read-pkg-up@^1.0.1: 403 | version "1.0.1" 404 | resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" 405 | integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= 406 | dependencies: 407 | find-up "^1.0.0" 408 | read-pkg "^1.0.0" 409 | 410 | read-pkg@^1.0.0: 411 | version "1.1.0" 412 | resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" 413 | integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= 414 | dependencies: 415 | load-json-file "^1.0.0" 416 | normalize-package-data "^2.3.2" 417 | path-type "^1.0.0" 418 | 419 | readdirp@~3.4.0: 420 | version "3.4.0" 421 | resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada" 422 | integrity sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ== 423 | dependencies: 424 | picomatch "^2.2.1" 425 | 426 | redent@^1.0.0: 427 | version "1.0.0" 428 | resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" 429 | integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94= 430 | dependencies: 431 | indent-string "^2.1.0" 432 | strip-indent "^1.0.1" 433 | 434 | repeating@^2.0.0: 435 | version "2.0.1" 436 | resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" 437 | integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= 438 | dependencies: 439 | is-finite "^1.0.0" 440 | 441 | resolve@^1.0.0, resolve@^1.10.0: 442 | version "1.15.1" 443 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" 444 | integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== 445 | dependencies: 446 | path-parse "^1.0.6" 447 | 448 | rimraf@^2.6.1: 449 | version "2.7.1" 450 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" 451 | integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== 452 | dependencies: 453 | glob "^7.1.3" 454 | 455 | "semver@2 || 3 || 4 || 5": 456 | version "5.7.1" 457 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" 458 | integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== 459 | 460 | signal-exit@^3.0.0: 461 | version "3.0.2" 462 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" 463 | integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= 464 | 465 | source-map-support@^0.5.12: 466 | version "0.5.16" 467 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" 468 | integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== 469 | dependencies: 470 | buffer-from "^1.0.0" 471 | source-map "^0.6.0" 472 | 473 | source-map-support@^0.5.17: 474 | version "0.5.19" 475 | resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" 476 | integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== 477 | dependencies: 478 | buffer-from "^1.0.0" 479 | source-map "^0.6.0" 480 | 481 | source-map@^0.6.0: 482 | version "0.6.1" 483 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 484 | integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== 485 | 486 | spdx-correct@^3.0.0: 487 | version "3.1.0" 488 | resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" 489 | integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== 490 | dependencies: 491 | spdx-expression-parse "^3.0.0" 492 | spdx-license-ids "^3.0.0" 493 | 494 | spdx-exceptions@^2.1.0: 495 | version "2.2.0" 496 | resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" 497 | integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== 498 | 499 | spdx-expression-parse@^3.0.0: 500 | version "3.0.0" 501 | resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" 502 | integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== 503 | dependencies: 504 | spdx-exceptions "^2.1.0" 505 | spdx-license-ids "^3.0.0" 506 | 507 | spdx-license-ids@^3.0.0: 508 | version "3.0.5" 509 | resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" 510 | integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== 511 | 512 | strip-bom@^2.0.0: 513 | version "2.0.0" 514 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" 515 | integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= 516 | dependencies: 517 | is-utf8 "^0.2.0" 518 | 519 | strip-bom@^3.0.0: 520 | version "3.0.0" 521 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" 522 | integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= 523 | 524 | strip-indent@^1.0.1: 525 | version "1.0.1" 526 | resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" 527 | integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= 528 | dependencies: 529 | get-stdin "^4.0.1" 530 | 531 | strip-json-comments@^2.0.0: 532 | version "2.0.1" 533 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" 534 | integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= 535 | 536 | svelte@^3.32.1: 537 | version "3.32.1" 538 | resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.32.1.tgz#c4b6e35517d0ed77e652cc8964ef660afa2f70f3" 539 | integrity sha512-j1KmD2ZOU0RGq1/STDXjwfh0/eJ/Deh2NXyuz1bpR9eOcz9yImn4CGxXdbSAN7cMTm9a7IyPUIbuBCzu/pXK0g== 540 | 541 | to-regex-range@^5.0.1: 542 | version "5.0.1" 543 | resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 544 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 545 | dependencies: 546 | is-number "^7.0.0" 547 | 548 | tree-kill@^1.2.2: 549 | version "1.2.2" 550 | resolved "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" 551 | integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== 552 | 553 | trim-newlines@^1.0.0: 554 | version "1.0.0" 555 | resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" 556 | integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= 557 | 558 | ts-node-dev@1.1.1: 559 | version "1.1.1" 560 | resolved "https://registry.yarnpkg.com/ts-node-dev/-/ts-node-dev-1.1.1.tgz#b7602929395b1616b4aa99a3be0a4e121742283d" 561 | integrity sha512-kAO8LUZgXZSY0+PucMPsQ0Bbdv0x+lgbN7j8gcD4PuTI4uKC6YchekaspmYTBNilkiu+rQYkWJA7cK+Q8/B0tQ== 562 | dependencies: 563 | chokidar "^3.4.0" 564 | dateformat "~1.0.4-1.2.3" 565 | dynamic-dedupe "^0.3.0" 566 | minimist "^1.2.5" 567 | mkdirp "^1.0.4" 568 | resolve "^1.0.0" 569 | rimraf "^2.6.1" 570 | source-map-support "^0.5.12" 571 | tree-kill "^1.2.2" 572 | ts-node "^9.0.0" 573 | tsconfig "^7.0.0" 574 | 575 | ts-node@^9.0.0: 576 | version "9.0.0" 577 | resolved "https://registry.npmjs.org/ts-node/-/ts-node-9.0.0.tgz#e7699d2a110cc8c0d3b831715e417688683460b3" 578 | integrity sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg== 579 | dependencies: 580 | arg "^4.1.0" 581 | diff "^4.0.1" 582 | make-error "^1.1.1" 583 | source-map-support "^0.5.17" 584 | yn "3.1.1" 585 | 586 | tsconfig@^7.0.0: 587 | version "7.0.0" 588 | resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-7.0.0.tgz#84538875a4dc216e5c4a5432b3a4dec3d54e91b7" 589 | integrity sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw== 590 | dependencies: 591 | "@types/strip-bom" "^3.0.0" 592 | "@types/strip-json-comments" "0.0.30" 593 | strip-bom "^3.0.0" 594 | strip-json-comments "^2.0.0" 595 | 596 | typescript@4.1.3: 597 | version "4.1.3" 598 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7" 599 | integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== 600 | 601 | validate-npm-package-license@^3.0.1: 602 | version "3.0.4" 603 | resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" 604 | integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== 605 | dependencies: 606 | spdx-correct "^3.0.0" 607 | spdx-expression-parse "^3.0.0" 608 | 609 | wrappy@1: 610 | version "1.0.2" 611 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 612 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 613 | 614 | xtend@^4.0.0: 615 | version "4.0.2" 616 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" 617 | integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== 618 | 619 | yn@3.1.1: 620 | version "3.1.1" 621 | resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" 622 | integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== 623 | --------------------------------------------------------------------------------