feat(v2): @docusaurus/init package (#1655)

* feat(v2): separate v2 docusaurus/init package

* nits

* docs

* rm unwanted

* readme
This commit is contained in:
Endi 2019-07-14 01:06:23 +07:00 committed by GitHub
parent 22ce04d3fb
commit d61cc01217
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 217 additions and 7957 deletions

View file

@ -12,4 +12,5 @@ packages/docusaurus-1.x/lib/core/MetadataBlog.js
packages/docusaurus-1.x/lib/core/__tests__/split-tab.test.js
packages/docusaurus-utils/lib/
packages/docusaurus/lib/
packages/docusaurus-init/lib/

1
.gitignore vendored
View file

@ -14,5 +14,6 @@ build
types
packages/docusaurus-utils/lib/
packages/docusaurus/lib/
packages/docusaurus-init/lib/

View file

@ -4,3 +4,4 @@ build
.docusaurus
packages/docusaurus-utils/lib/
packages/docusaurus/lib/
packages/docusaurus-init/lib/

View file

@ -4,7 +4,7 @@
"packages/*",
"website",
"website-1.x",
"packages/docusaurus/templates/*"
"packages/docusaurus-init/templates/*"
],
"scripts": {
"start": "yarn tsc && yarn start:v2",
@ -27,11 +27,14 @@
"@types/escape-string-regexp": "^1.0.0",
"@types/express": "^4.16.1",
"@types/fs-extra": "7.0.0",
"@types/inquirer": "^6.0.3",
"@types/jest": "^24.0.13",
"@types/lodash": "^4.14.129",
"@types/lodash.kebabcase": "^4.1.6",
"@types/node": "^12.0.2",
"@types/react": "^16.8.18",
"@types/react-dev-utils": "^9.0.1",
"@types/semver": "^6.0.1",
"@types/shelljs": "^0.8.5",
"@types/webpack": "^4.4.31",
"@types/webpack-dev-server": "^3.1.5",
@ -58,7 +61,7 @@
"react": "^16.8.4",
"react-dom": "^16.8.4",
"rimraf": "^2.6.3",
"typescript": "^3.5.2"
"typescript": "^3.5.3"
},
"lint-staged": {
"linters": {

View file

@ -0,0 +1,58 @@
#!/usr/bin/env node
/**
* Copyright (c) 2017-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const chalk = require('chalk');
const semver = require('semver');
const path = require('path');
const program = require('commander');
const {init} = require('../lib');
const requiredVersion = require('../package.json').engines.node;
if (!semver.satisfies(process.version, requiredVersion)) {
console.log(
chalk.red(`\nMinimum node version not met :)`) +
chalk.yellow(
`\nYou are using Node ${
process.version
}, Requirement: Node ${requiredVersion}.\n`,
),
);
process.exit(1);
}
function wrapCommand(fn) {
return (...args) =>
fn(...args).catch(err => {
console.error(chalk.red(err.stack));
process.exitCode = 1;
});
}
program
.version(require('../package.json').version)
.usage('<command> [options]');
program
.command('init [siteName] [template] [rootDir]')
.description('Initialize website')
.action((siteName, template, rootDir = '.') => {
wrapCommand(init)(path.resolve(rootDir), siteName, template);
});
program.arguments('<command>').action(cmd => {
program.outputHelp();
console.log(` ${chalk.red(`\n Unknown command ${chalk.yellow(cmd)}.`)}`);
console.log();
});
program.parse(process.argv);
if (!process.argv.slice(2).length) {
program.outputHelp();
}

View file

@ -0,0 +1,34 @@
{
"name": "@docusaurus/init",
"version": "2.0.0-alpha.19",
"description": "Create Docusaurus app easily",
"repository": {
"type": "git",
"url": "https://github.com/facebook/docusaurus.git"
},
"bugs": {
"url": "https://github.com/facebook/docusaurus/issues"
},
"scripts": {
"tsc": "tsc"
},
"bin": {
"docusaurus-init": "bin/index.js"
},
"publishConfig": {
"access": "public"
},
"license": "MIT",
"dependencies": {
"chalk": "^2.4.2",
"commander": "^2.20.0",
"fs-extra": "^8.1.0",
"inquirer": "^6.5.0",
"lodash.kebabcase": "^4.1.1",
"semver": "^6.1.1",
"shelljs": "^0.8.3"
},
"engines": {
"node": ">= 8.9.0"
}
}

View file

@ -6,12 +6,12 @@
*/
import chalk from 'chalk';
import {execSync} from 'child_process';
import fs from 'fs-extra';
import {execSync} from 'child_process';
import inquirer from 'inquirer';
import _ from 'lodash';
import path from 'path';
import shell from 'shelljs';
import kebabCase from 'lodash.kebabcase';
function hasYarn(): boolean {
try {
@ -22,11 +22,11 @@ function hasYarn(): boolean {
}
}
function isValidGitRepoUrl(gitRepoUrl): boolean {
function isValidGitRepoUrl(gitRepoUrl: string): boolean {
return ['https://', 'git@'].some(item => gitRepoUrl.startsWith(item));
}
async function updatePkg(pkgPath: string, obj): Promise<void> {
async function updatePkg(pkgPath: string, obj: any): Promise<void> {
const content = await fs.readFile(pkgPath, 'utf-8');
const pkg = JSON.parse(content);
const newPkg = Object.assign(pkg, obj);
@ -40,7 +40,7 @@ export async function init(
reqTemplate?: string,
): Promise<void> {
const useYarn = hasYarn();
const templatesDir = path.resolve(__dirname, '../../templates');
const templatesDir = path.resolve(__dirname, '../templates');
const templates = fs
.readdirSync(templatesDir)
.filter(d => !d.startsWith('.') && !d.startsWith('README'));
@ -52,13 +52,13 @@ export async function init(
// Prompt if siteName is not passed from CLI
if (!name) {
const answers = await inquirer.prompt({
const {name: promptedName} = await inquirer.prompt({
type: 'input',
name: 'name',
message: 'What should we name this site?',
default: 'website',
});
name = answers.name;
name = promptedName;
}
if (!name) {
@ -73,13 +73,13 @@ export async function init(
let template = reqTemplate;
// Prompt if template is not provided from CLI
if (!template) {
const answers = await inquirer.prompt({
const {template: promptedTemplate} = await inquirer.prompt({
type: 'list',
name: 'template',
message: 'Select a template below...',
choices: templateChoices,
});
template = answers.template;
template = promptedTemplate;
}
// If user choose Git repository, we'll prompt for the url
@ -128,7 +128,7 @@ export async function init(
// Update package.json info
try {
await updatePkg(path.join(dest, 'package.json'), {
name: _.kebabCase(name),
name: kebabCase(name),
version: '0.0.0',
private: true,
});
@ -152,9 +152,8 @@ export async function init(
console.log(`Installing dependencies with: ${chalk.cyan(pkgManager)}`);
// we use execSync instead of shell.exec to hide installation output
try {
execSync(`cd "${name}" && ${useYarn ? 'yarn' : 'npm install'}`);
shell.exec(`cd "${name}" && ${useYarn ? 'yarn' : 'npm install'}`);
} catch (err) {
console.log(chalk.red('Installation failed'));
throw err;

View file

@ -1,6 +1,6 @@
# Templates
Official templates provided by Docusaurus. They are designed to be selected when using the `docusaurus init` CLI command.
Official templates provided by Docusaurus. They are designed to be selected when using the `npx @docusaurus/init@next init [name] [template]` CLI command.
## Guide to Test Templates for Developer

View file

Before

Width:  |  Height:  |  Size: 766 B

After

Width:  |  Height:  |  Size: 766 B

View file

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View file

@ -0,0 +1,9 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"incremental": true,
"tsBuildInfoFile": "./lib/.tsbuildinfo",
"rootDir": "src",
"outDir": "lib",
}
}

View file

@ -33,7 +33,7 @@ function Layout(props) {
permalink,
} = props;
const metaTitle = title || `${defaultTitle} · ${tagline}`;
const metaImage = `${siteUrl}${withBaseUrl(image || defaultImage)}`;
const metaImage = image || defaultImage;
return (
<React.Fragment>
<Head>
@ -50,8 +50,18 @@ function Layout(props) {
{keywords && keywords.length && (
<meta property="keywords" content={keywords} />
)}
{metaImage && <meta property="og:image" content={metaImage} />}
{metaImage && <meta property="twitter:image" content={metaImage} />}
{metaImage && (
<meta
property="og:image"
content={siteUrl + withBaseUrl(metaImage)}
/>
)}
{metaImage && (
<meta
property="twitter:image"
content={siteUrl + withBaseUrl(metaImage)}
/>
)}
{metaImage && (
<meta name="twitter:image:alt" content={`Image for ${metaTitle}`} />
)}

View file

@ -8,11 +8,10 @@
*/
const chalk = require('chalk');
const envinfo = require('envinfo');
const semver = require('semver');
const path = require('path');
const program = require('commander');
const {build, swizzle, init, deploy, start} = require('../lib');
const {build, swizzle, deploy, start} = require('../lib');
const requiredVersion = require('../package.json').engines.node;
if (!semver.satisfies(process.version, requiredVersion)) {
@ -61,13 +60,6 @@ program
wrapCommand(swizzle)(path.resolve(siteDir), themeName, componentName);
});
program
.command('init [siteName] [template] [rootDir]')
.description('Initialize website')
.action((siteName, template, rootDir = '.') => {
wrapCommand(init)(path.resolve(rootDir), siteName, template);
});
program
.command('deploy [siteDir]')
.description('Deploy website to GitHub pages')
@ -94,22 +86,6 @@ program
});
});
program
.command('info')
.description('Shows debugging information about the local environment')
.action(() => {
console.log(chalk.bold('\nEnvironment Info:'));
envinfo
.run({
System: ['OS', 'CPU'],
Binaries: ['Node', 'Yarn', 'npm'],
Browsers: ['Chrome', 'Edge', 'Firefox', 'Safari'],
npmPackages: '?(@)docusaurus{*,*/**}',
npmGlobalPackages: '?(@)docusaurus{*,*/**}',
})
.then(console.log);
});
program.arguments('<command>').action(cmd => {
program.outputHelp();
console.log(` ${chalk.red(`\n Unknown command ${chalk.yellow(cmd)}.`)}`);

View file

@ -45,14 +45,12 @@
"copy-webpack-plugin": "^5.0.3",
"css-loader": "^2.1.1",
"ejs": "^2.6.1",
"envinfo": "^7.2.0",
"express": "^4.17.1",
"fs-extra": "^7.0.0",
"globby": "^9.2.0",
"html-webpack-plugin": "^4.0.0-beta.5",
"import-fresh": "^3.0.0",
"inquirer": "^6.3.1",
"lodash": "^4.17.11",
"lodash": "^4.17.14",
"mini-css-extract-plugin": "^0.7.0",
"nprogress": "^0.2.0",
"null-loader": "^3.0.0",

View file

@ -6,7 +6,6 @@
*/
export {build} from './commands/build';
export {init} from './commands/init';
export {start} from './commands/start';
export {swizzle} from './commands/swizzle';
export {deploy} from './commands/deploy';

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,7 @@ title: Installation
The easiest way to install Docusaurus is to use the command line tool that helps you scaffold a Docusaurus site skeleton. You can run this command anywhere in a new empty repository or within an existing repository, it will create a new directory containing the scaffolded files.
```bash
npx @docusaurus/core@next init [name] [template]
npx @docusaurus/init@next init [name] [template]
```
If you do not specify `name` or `template`, it will prompt you for the missing inputs. We recommend the `classic` template so that you can get started quickly. The `classic` template comes with standard documentation, blog and custom pages features.

View file

@ -1973,6 +1973,14 @@
dependencies:
"@types/node" "*"
"@types/inquirer@^6.0.3":
version "6.0.3"
resolved "https://registry.yarnpkg.com/@types/inquirer/-/inquirer-6.0.3.tgz#597b3c1aa4a575899841ab99bb4f1774d0b8c090"
integrity sha512-lBsdZScFMaFYYIE3Y6CWX22B9VeY2NerT1kyU2heTc3u/W6a+Om6Au2q0rMzBrzynN0l4QoABhI0cbNdyz6fDg==
dependencies:
"@types/through" "*"
rxjs "^6.4.0"
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
@ -2010,6 +2018,18 @@
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636"
integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==
"@types/lodash.kebabcase@^4.1.6":
version "4.1.6"
resolved "https://registry.yarnpkg.com/@types/lodash.kebabcase/-/lodash.kebabcase-4.1.6.tgz#07b07aeca6c0647836de46f87a3cdfff72166c8e"
integrity sha512-+RAD9pCAa8kuVyCYTeDNiwBXwD/0u0p+hos3NSqD+tXTjJextbfF3farfYB+ssAKgEssoewXEtBsfwBpsI7gsA==
dependencies:
"@types/lodash" "*"
"@types/lodash@*":
version "4.14.136"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.136.tgz#413e85089046b865d960c9ff1d400e04c31ab60f"
integrity sha512-0GJhzBdvsW2RUccNHOBkabI8HZVdOXmXbXhuKlDEd5Vv12P7oAVGfomGp3Ne21o5D/qu1WmthlNKFaoZJJeErA==
"@types/lodash@^4.14.129":
version "4.14.130"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.130.tgz#04b3a690d5f4fc34579963c99adae067b8c8eb5a"
@ -2069,6 +2089,11 @@
resolved "https://registry.yarnpkg.com/@types/relateurl/-/relateurl-0.2.28.tgz#6bda7db8653fa62643f5ee69e9f69c11a392e3a6"
integrity sha1-a9p9uGU/piZD9e5p6facEaOS46Y=
"@types/semver@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.0.1.tgz#a984b405c702fa5a7ec6abc56b37f2ba35ef5af6"
integrity sha512-ffCdcrEE5h8DqVxinQjo+2d1q+FV5z7iNtPofw3JsrltSoSVlOGaW0rY8XxtO9XukdTn8TaCGWmk2VFGhI70mg==
"@types/serve-static@*":
version "1.13.2"
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.2.tgz#f5ac4d7a6420a99a6a45af4719f4dcd8cd907a48"
@ -2095,6 +2120,13 @@
resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.4.tgz#b4ffc7dc97b498c969b360a41eee247f82616370"
integrity sha512-78AdXtlhpCHT0K3EytMpn4JNxaf5tbqbLcbIRoQIHzpTIyjpxLQKRoxU55ujBXAtg3Nl2h/XWvfDa9dsMOd0pQ==
"@types/through@*":
version "0.0.29"
resolved "https://registry.yarnpkg.com/@types/through/-/through-0.0.29.tgz#72943aac922e179339c651fa34a4428a4d722f93"
integrity sha512-9a7C5VHh+1BKblaYiq+7Tfc+EOmjMdZaD1MYtkQjSoxgB69tBjW98ry6SKsi4zEIWztLOMRuL87A3bdT/Fc/4w==
dependencies:
"@types/node" "*"
"@types/uglify-js@*":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.0.4.tgz#96beae23df6f561862a830b4288a49e86baac082"
@ -5274,11 +5306,6 @@ envify@^4.0.0:
esprima "^4.0.0"
through "~2.3.4"
envinfo@^7.2.0:
version "7.3.1"
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.3.1.tgz#892e42f7bf858b3446d9414ad240dbaf8da52f09"
integrity sha512-GvXiDTqLYrORVSCuJCsWHPXF5BFvoWMQA9xX4YVjPT1jyS3aZEHUBwjzxU/6LTPF9ReHgVEbX7IEN5UvSXHw/A==
enzyme-adapter-react-16@^1.12.1:
version "1.13.1"
resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.13.1.tgz#2e8ee300e38674b9914ae52b04af9493050355e2"
@ -6335,6 +6362,15 @@ fs-extra@^8.0.1:
jsonfile "^4.0.0"
universalify "^0.1.0"
fs-extra@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
dependencies:
graceful-fs "^4.2.0"
jsonfile "^4.0.0"
universalify "^0.1.0"
fs-minipass@^1.2.5:
version "1.2.6"
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07"
@ -6763,6 +6799,11 @@ graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
graceful-fs@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b"
integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==
"graceful-readlink@>= 1.0.0":
version "1.0.1"
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
@ -7520,7 +7561,7 @@ inquirer@6.2.2:
strip-ansi "^5.0.0"
through "^2.3.6"
inquirer@^6.2.0, inquirer@^6.3.1:
inquirer@^6.2.0:
version "6.3.1"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.3.1.tgz#7a413b5e7950811013a3db491c61d1f3b776e8e7"
integrity sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA==
@ -7539,6 +7580,25 @@ inquirer@^6.2.0, inquirer@^6.3.1:
strip-ansi "^5.1.0"
through "^2.3.6"
inquirer@^6.5.0:
version "6.5.0"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.0.tgz#2303317efc9a4ea7ec2e2df6f86569b734accf42"
integrity sha512-scfHejeG/lVZSpvCXpsB4j/wQNPM5JC8kiElOI0OUTwmc1RTpXr4H32/HOlQHcZiYl2z2VElwuCVDRG8vFmbnA==
dependencies:
ansi-escapes "^3.2.0"
chalk "^2.4.2"
cli-cursor "^2.1.0"
cli-width "^2.0.0"
external-editor "^3.0.3"
figures "^2.0.0"
lodash "^4.17.12"
mute-stream "0.0.7"
run-async "^2.2.0"
rxjs "^6.4.0"
string-width "^2.1.0"
strip-ansi "^5.1.0"
through "^2.3.6"
internal-ip@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907"
@ -9029,6 +9089,11 @@ lodash.ismatch@^4.4.0:
resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37"
integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=
lodash.kebabcase@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36"
integrity sha1-hImxyw0p/4gZXM7KRI/21swpXDY=
lodash.map@^4.4.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3"
@ -9104,6 +9169,11 @@ lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.17.5
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
lodash@^4.17.12, lodash@^4.17.14:
version "4.17.14"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba"
integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==
log-symbols@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
@ -13933,10 +14003,10 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
typescript@^3.5.2:
version "3.5.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.2.tgz#a09e1dc69bc9551cadf17dba10ee42cf55e5d56c"
integrity sha512-7KxJovlYhTX5RaRbUdkAXN1KUZ8PwWlTzQdHV6xNqvuFOs7+WBo10TQUqT19Q/Jz2hk5v9TQDIhyLhhJY4p5AA==
typescript@^3.5.3:
version "3.5.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977"
integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==
ua-parser-js@^0.7.18:
version "0.7.19"