fix: separate the Database and Picker modules
This commit is contained in:
parent
0c60360a6b
commit
8c7305a2e1
187
README.md
187
README.md
|
@ -1,43 +1,186 @@
|
|||
lite-emoji-picker
|
||||
====
|
||||
|
||||
A small, performant, accessible emoji picker and lookup library, distributed as a web component.
|
||||
A small, performant, accessible emoji picker, distributed as a web component.
|
||||
|
||||
Built on top of IndexedDB so it consumes far less memory then other emoji pickers. Suitable for mobile web apps or other resource-constrained environments.
|
||||
It's built on top of IndexedDB, so it consumes far less memory than other emoji pickers. It also uses [Svelte](https://svelte.dev), so it has a minimal runtime footprint.
|
||||
|
||||
Design goals:
|
||||
|
||||
- Store emoji in IndexedDB, not memory
|
||||
- Use IndexedDB for querying
|
||||
- Render native emoji
|
||||
- Store emoji data in IndexedDB, not memory
|
||||
- Render native emoji, no spritesheets
|
||||
- Accessible by default
|
||||
- Drop-in as a vanilla web component
|
||||
|
||||
## Install
|
||||
|
||||
npm install lite-emoji-picker
|
||||
|
||||
```js
|
||||
import { Picker } from 'lite-emoji-picker'
|
||||
customElements.define('emoji-picker', Picker)
|
||||
document.body.appendChild(new Picker())
|
||||
## Usage
|
||||
|
||||
```html
|
||||
<lite-emoji-picker></lite-emoji-picker>
|
||||
```
|
||||
|
||||
```js
|
||||
import 'lite-emoji-picker';
|
||||
```
|
||||
|
||||
`lite-emoji-picker` will expand to fit whatever container you give it. Here is a good default:
|
||||
|
||||
```css
|
||||
.lite-emoji-picker {
|
||||
width: 400px;
|
||||
height: 300px;
|
||||
}
|
||||
```
|
||||
|
||||
`lite-emoji-picker` uses Shadow DOM, so its inner styling is not accessible except via the API.
|
||||
|
||||
## API
|
||||
|
||||
### Picker
|
||||
|
||||
```js
|
||||
import { Picker } from 'lite-emoji-picker';
|
||||
const picker = new Picker();
|
||||
document.body.appendChild(picker);
|
||||
```
|
||||
|
||||
`new Picker(options)` supports a few different options:
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
| ------ | ---- | ------- | ----------- |
|
||||
| `locale` | String | `"en"` | Locale, should map to the locales supported by `emojibase-data` |
|
||||
| `dataSource` | String | `"https://cdn.jsdelivr.net/npm/emojibase-data@5/en/data.json"` | Where to fetch the emoji data from. Note that `lite-emoji-picker` requires the full `data.json`, not `compact.json`. |
|
||||
| `i18n` | Object | See below | Strings to use for i18n in the Picker itself, i.e. the text and `aria-label`s.
|
||||
| `locale` | String | `"en"` | Locale, should map to the locales supported by `emojibase-data` |
|
||||
| `i18n` | Object | See below | Strings to use for internationalization of the Picker itself, i.e. the text and `aria-label`s. Note that `lite-emoji-picker` only ships with English by default. |
|
||||
| `numColumns` | number | `8` | Number of emoji to show per row. |
|
||||
| `darkMode` | boolean/String | `"auto"` | Dark mode. Either `false`, `true`, or `"auto"`. `"auto"` chooses based on [`prefers-color-scheme`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme).
|
||||
| `darkMode` | boolean/String | `"auto"` | Dark mode. Either `false`, `true`, or `"auto"`. The `"auto"` option chooses based on [`prefers-color-scheme`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme).
|
||||
|
||||
These values can also be set at runtime, e.g.:
|
||||
|
||||
```js
|
||||
const picker = new Picker();
|
||||
picker.numColumns = 6;
|
||||
```
|
||||
|
||||
#### i18n structure
|
||||
|
||||
Note that some of these values are only visible to users of screen readers (but you should still support them if you internationalize your app!).
|
||||
|
||||
```json
|
||||
{
|
||||
"loading": "Loading…",
|
||||
"regionLabel": "Emoji picker",
|
||||
"search": "Search",
|
||||
"categoriesLabel": "Categories",
|
||||
"categories": {
|
||||
"smileys-emotion": "Smileys and emoticons",
|
||||
"people-body": "People and body",
|
||||
"animals-nature": "Animals and nature",
|
||||
"food-drink": "Food and drink",
|
||||
"travel-places": "Travel and places",
|
||||
"activities": "Activities",
|
||||
"objects": "Objects",
|
||||
"symbols": "Symbols",
|
||||
"flags": "Flags"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Database
|
||||
|
||||
You can work with the database API separately:
|
||||
|
||||
```js
|
||||
import { Database } from 'lite-emoji-picker';
|
||||
|
||||
const database = new Database();
|
||||
await database.getEmojiBySearchPrefix('elephant'); // [{unicode: "🐘", ...}]
|
||||
```
|
||||
|
||||
`new Database()` takes similar options as the picker:
|
||||
|
||||
```js
|
||||
const database = new Database({
|
||||
locale: 'en',
|
||||
dataSource: 'https://cdn.jsdelivr.net/npm/emojibase-data@5/en/data.json'
|
||||
});
|
||||
```
|
||||
|
||||
In general, it's not a problem to create multiple `Database` objects with the same arguments. Under the hood, they will share the same IndexedDB connection.
|
||||
|
||||
<!-- TODO: Database API here -->
|
||||
|
||||
### Tree-shaking
|
||||
|
||||
If you want to import the `Database` without the `Picker`, or you want to import them separately, then do:
|
||||
|
||||
```js
|
||||
import Picker from 'lite-emoji-picker/dist/es/Picker.js';
|
||||
import Database from 'lite-emoji-picker/dist/es/Database.js';
|
||||
```
|
||||
|
||||
The reason for this is that `Picker` automatically registers itself as a custom element, following [web component best practices](https://justinfagnani.com/2019/11/01/how-to-publish-web-components-to-npm/). But this adds side effects, so bundlers do not tree-shake as well unless the modules are imported from completely separate files.
|
||||
|
||||
## Focus outline
|
||||
|
||||
By default, `lite-emoji-picker` displays a prominent focus ring for accessibility reasons. If you want to hide the focus ring for non-keyboard users (e.g. mouse and touch only), then use the [focus-visible](https://github.com/WICG/focus-visible) polyfill, e.g.:
|
||||
|
||||
```css
|
||||
.js-focus-visible :focus:not(.focus-visible) {
|
||||
outline: none;
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
import { applyFocusVisiblePolyfill } from 'focus-visible';
|
||||
|
||||
const picker = new Picker();
|
||||
applyFocusVisiblePolyfill(picker.shadowRoot);
|
||||
```
|
||||
|
||||
`lite-emoji-picker` already ships with the proper CSS for both the `:focus_visible` standard and the polyfill.
|
||||
|
||||
## Data and offline
|
||||
|
||||
### Data source and JSON format
|
||||
|
||||
You can fetch the emoji JSON file from wherever you want. However, it's recommended that your server expose an `ETag` header. If so, `lite-emoji-picker` can avoid re-downloading the entire JSON file over and over again. Instead, it will fire off a `HEAD` request and just check the `ETag`.
|
||||
|
||||
If your server is cross-origin, then it will also need to expose `Access-Control-Allow-Origin: *` and `Access-Control-Allow-Headers: *`. (Note that `jsdelivr` already does this, which is why it is the default.)
|
||||
|
||||
`lite-emoji-picker` requires the _full_ [emojibase-data](https://github.com/milesj/emojibase) JSON file, not the "compact" one. If you would like to trim the JSON file down even further, then modify the file to only contain these keys:
|
||||
|
||||
```json
|
||||
[
|
||||
"annotation", "emoji", "emoticon", "group",
|
||||
"order", "shortcodes", "tags", "version"
|
||||
]
|
||||
```
|
||||
|
||||
### Offline-first
|
||||
|
||||
By default, `lite-emoji-picker` will use the "stale while revalidate" strategy the second time it loads. In other words, it will use any existing data it finds in IndexedDB, and lazily update via the `dataSource` in case data has changed. This means it will work offline-first the second time it runs.
|
||||
|
||||
If you would like to manage the database yourself (e.g. to ensure that it's correctly populated before displaying the `Picker`), then create a new `Database` instance and wait for its `ready()` promise to resolve:
|
||||
|
||||
```js
|
||||
const database = new Database()
|
||||
try {
|
||||
await database.ready()
|
||||
} catch (err) {
|
||||
// Deal with any errors (e.g. offline)
|
||||
}
|
||||
```
|
||||
|
||||
If `lite-emoji-picker` fails to fetch the JSON data the first time it loads, then it will display no emoji.
|
||||
|
||||
## Design decisions
|
||||
|
||||
### IndexedDB
|
||||
|
||||
The [`emojibase-data`](https://github.com/milesj/emojibase) English JSON file is [854kB](https://unpkg.com/browse/emojibase-data@5.0.1/en/). The "compact" version is still 543kB. That's a lot of data to keep in memory just for an emoji picker. And it's not like that number is ever going down; the Unicode Consortium keeps adding more emoji every year.
|
||||
The [`emojibase-data`](https://github.com/milesj/emojibase) English JSON file is [854kB](https://unpkg.com/browse/emojibase-data@5.0.1/en/), and the "compact" version is still 543kB. That's a lot of data to keep in memory just for an emoji picker. And it's not like that number is ever going down; the Unicode Consortium keeps adding more emoji every year.
|
||||
|
||||
Using IndexedDB has a few advantages:
|
||||
|
||||
|
@ -46,6 +189,20 @@ Using IndexedDB has a few advantages:
|
|||
|
||||
### Native emoji
|
||||
|
||||
To avoid downloading a large sprite sheet (or deal with potential IP issues), `lite-emoji-picker` only renders native emoji. This means it is limited to the emoji actually installed on the user's device.
|
||||
To avoid downloading a large sprite sheet (which may be copyrighted, or may look out-of-place on different platforms), `lite-emoji-picker` only renders native emoji. This means it is limited to the emoji actually installed on the user's device.
|
||||
|
||||
To avoid rendering ugly unsupported or half-supported emoji, `lite-emoji-picker` will detect emoji support and only render the supported characters. (So no empty boxes or double-width characters.)
|
||||
To avoid rendering ugly unsupported or half-supported emoji, `lite-emoji-picker` will automatically detect emoji support and only render the supported characters. (So no empty boxes or awkward double emoji.)
|
||||
|
||||
### Browser support
|
||||
|
||||
Only the latest versions of Chrome, Firefox, and Safari (and browsers using equivalent rendering engines) are supported.
|
||||
|
||||
## Contributing
|
||||
|
||||
Install
|
||||
|
||||
yarn
|
||||
|
||||
Run the tests:
|
||||
|
||||
yarn test
|
11
package.json
11
package.json
|
@ -7,10 +7,14 @@
|
|||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"sideEffects": false,
|
||||
"scripts": {
|
||||
"build": "NODE_ENV=production rollup -c",
|
||||
"dev": "NODE_ENV=development rollup -c -w",
|
||||
"build:clean": "rm -fr dist && mkdir -p dist/cjs dist/es",
|
||||
"build:copy": "cp src/index.cjs.js dist/cjs/index.js && cp src/index.es.js dist/es/index.js",
|
||||
"build:static": "run-s build:clean build:copy",
|
||||
"build:rollup": "NODE_ENV=production rollup -c",
|
||||
"dev:rollup": "NODE_ENV=development rollup -c -w",
|
||||
"build": "run-s build:static build:rollup",
|
||||
"dev": "run-s build:static dev:rollup",
|
||||
"lint": "standard",
|
||||
"lint:fix": "standard --fix",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
|
@ -43,6 +47,7 @@
|
|||
"if-emoji": "^0.1.0",
|
||||
"lint-staged": "^10.2.7",
|
||||
"lodash-es": "^4.17.15",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"rollup": "^2.8.2",
|
||||
"rollup-plugin-svelte": "^5.2.1",
|
||||
"rollup-plugin-svelte-hot": "^0.7.0",
|
||||
|
|
|
@ -10,30 +10,41 @@ import { versionsAndTestEmoji } from './bin/versionsAndTestEmoji'
|
|||
const dev = process.env.NODE_ENV !== 'production'
|
||||
const svelte = dev ? hotSvelte : mainSvelte
|
||||
|
||||
// Build Database.js and Picker.js as separate modules at build times so that they are properly tree-shakeable.
|
||||
// Most of this has to happen because customElements.define() has side effects
|
||||
const baseConfig = {
|
||||
plugins: [
|
||||
resolve(),
|
||||
cjs({
|
||||
exclude: ['node_modules/lodash-es/**']
|
||||
}),
|
||||
cjs(),
|
||||
json(),
|
||||
replace({
|
||||
'process.env.VERSIONS_AND_TEST_EMOJI': JSON.stringify(versionsAndTestEmoji)
|
||||
}),
|
||||
replace({
|
||||
'../../../database/Database.js': './Database.js',
|
||||
delimiters: ['', '']
|
||||
}),
|
||||
svelte({
|
||||
css: true,
|
||||
customElement: true,
|
||||
dev,
|
||||
preprocess: autoPreprocess()
|
||||
})
|
||||
],
|
||||
external: [
|
||||
'../../../database/Database.js'
|
||||
]
|
||||
}
|
||||
|
||||
const formats = ['es', 'cjs']
|
||||
const entryPoints = [
|
||||
{
|
||||
input: './src/index.js',
|
||||
output: 'index.js'
|
||||
input: './src/svelte/components/Picker/Picker.svelte',
|
||||
output: 'Picker.js'
|
||||
},
|
||||
{
|
||||
input: './src/database/Database.js',
|
||||
output: 'Database.js'
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
@ -5,10 +5,10 @@ import { assertEmojiBaseData } from './utils/assertEmojiBaseData'
|
|||
import { assertNumber } from './utils/assertNumber'
|
||||
import { DEFAULT_DATA_SOURCE, DEFAULT_LOCALE } from './constants'
|
||||
import { uniqEmoji } from './utils/uniqEmoji'
|
||||
import { jsonChecksum } from '../svelte/utils/jsonChecksum'
|
||||
import { jsonChecksum } from './utils/jsonChecksum'
|
||||
import { warnOffline } from './utils/warnOffline'
|
||||
|
||||
export class Database {
|
||||
export default class Database {
|
||||
constructor ({ dataSource = DEFAULT_DATA_SOURCE, locale = DEFAULT_LOCALE } = {}) {
|
||||
this._dataSource = dataSource
|
||||
this._locale = locale
|
||||
|
@ -65,6 +65,10 @@ export class Database {
|
|||
await this._idbEngine.loadData(emojiBaseData, url, eTag)
|
||||
}
|
||||
|
||||
async ready () {
|
||||
return this._readyPromise
|
||||
}
|
||||
|
||||
async getEmojiByGroup (group) {
|
||||
assertNumber(group)
|
||||
await this._readyPromise
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
const requiredKeys = [
|
||||
'annotation', 'emoji', 'emoticon', 'group',
|
||||
'order', 'shortcodes', 'tags', 'version'
|
||||
]
|
||||
|
||||
export function assertEmojiBaseData (emojiBaseData) {
|
||||
if (!emojiBaseData || !Array.isArray(emojiBaseData) ||
|
||||
!emojiBaseData.length || !emojiBaseData[0].emoji || !emojiBaseData[0].version) {
|
||||
if (!emojiBaseData ||
|
||||
!Array.isArray(emojiBaseData) ||
|
||||
!emojiBaseData.length ||
|
||||
requiredKeys.some(key => (!(key in emojiBaseData[0])))) {
|
||||
throw new Error('Expected emojibase full (not compact) data, but data is in wrong format')
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
// Directly copied into dist/cjs/index.js
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true })
|
||||
|
||||
exports.Picker = require('./Picker.js')
|
||||
exports.Database = require('./Database.js')
|
|
@ -0,0 +1,5 @@
|
|||
// Directly copied into dist/es/index.js
|
||||
|
||||
import Picker from './Picker.js'
|
||||
import Database from './Database.js'
|
||||
export { Picker, Database }
|
|
@ -1,4 +1,4 @@
|
|||
<svelte:options tag={null} />
|
||||
<svelte:options tag="lite-emoji-picker" />
|
||||
<section
|
||||
class="lep-picker {resolvedDarkMode ? 'lep-dark' : 'lep-light'}"
|
||||
aria-label={i18n.regionLabel}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
/* global supportedZwjEmojis, emojiSupportLevel */
|
||||
/* eslint-disable prefer-const,no-labels */
|
||||
|
||||
import Database from '../../../database/Database.js'
|
||||
import i18n from '../../i18n/en.json'
|
||||
import { categories } from '../../categories'
|
||||
import { DEFAULT_LOCALE, DEFAULT_DATA_SOURCE } from '../../../database/constants'
|
||||
import { Database } from '../../../database/Database'
|
||||
import { MIN_SEARCH_TEXT_LENGTH, DEFAULT_NUM_COLUMNS } from '../../constants'
|
||||
import { requestIdleCallback } from '../../utils/requestIdleCallback'
|
||||
import { calculateTextWidth } from '../../utils/calculateTextWidth'
|
||||
import { hasZwj } from '../../utils/hasZwj'
|
||||
import { thunk } from '../../utils/thunk'
|
||||
import { emojiSupportLevel, supportedZwjEmojis } from '../../utils/emojiSupport'
|
||||
|
||||
let database
|
||||
let numColumns = DEFAULT_NUM_COLUMNS
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
<template src="./Picker.html"></template>
|
||||
<style src="./Picker.scss" lang="scss"></style>
|
||||
<script context="module" src="./Picker.module.js"></script>
|
||||
<script src="./Picker.js"></script>
|
|
@ -1,4 +1,4 @@
|
|||
import { determineEmojiSupportLevel } from '../../utils/determineEmojiSupportLevel'
|
||||
import { determineEmojiSupportLevel } from './determineEmojiSupportLevel'
|
||||
// Check which emojis we know for sure aren't supported, based on Unicode version level
|
||||
export const emojiSupportLevel = determineEmojiSupportLevel()
|
||||
// determine which emojis containing ZWJ (zero width joiner) characters
|
|
@ -7,23 +7,16 @@
|
|||
.container {
|
||||
height: 300px;
|
||||
width: 400px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Ad-hoc test</h1>
|
||||
<div class="container"></div>
|
||||
<div class="container">
|
||||
<lite-emoji-picker></lite-emoji-picker>
|
||||
</div>
|
||||
<script type="module">
|
||||
import * as liteEmojiPicker from '../dist/es/index.js'
|
||||
|
||||
(async () => {
|
||||
window.liteEmojiPicker = liteEmojiPicker
|
||||
|
||||
customElements.define('lite-emoji-picker', liteEmojiPicker.Picker)
|
||||
const picker = document.createElement('lite-emoji-picker')
|
||||
document.querySelector('.container').appendChild(picker)
|
||||
})()
|
||||
import '../dist/es/index.js'
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
71
yarn.lock
71
yarn.lock
|
@ -404,7 +404,7 @@ callsites@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
||||
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
|
||||
|
||||
chalk@^2.0.0, chalk@^2.1.0:
|
||||
chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.1:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||
|
@ -1950,6 +1950,16 @@ load-json-file@^2.0.0:
|
|||
pify "^2.0.0"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
load-json-file@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
|
||||
integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs=
|
||||
dependencies:
|
||||
graceful-fs "^4.1.2"
|
||||
parse-json "^4.0.0"
|
||||
pify "^3.0.0"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
load-json-file@^5.2.0:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-5.3.0.tgz#4d3c1e01fa1c03ea78a60ac7af932c9ce53403f3"
|
||||
|
@ -2049,6 +2059,11 @@ media-typer@0.3.0:
|
|||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
|
||||
|
||||
memorystream@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2"
|
||||
integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI=
|
||||
|
||||
merge-descriptors@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
|
||||
|
@ -2241,6 +2256,21 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||
|
||||
npm-run-all@^4.1.5:
|
||||
version "4.1.5"
|
||||
resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba"
|
||||
integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==
|
||||
dependencies:
|
||||
ansi-styles "^3.2.1"
|
||||
chalk "^2.4.1"
|
||||
cross-spawn "^6.0.5"
|
||||
memorystream "^0.3.1"
|
||||
minimatch "^3.0.4"
|
||||
pidtree "^0.3.0"
|
||||
read-pkg "^3.0.0"
|
||||
shell-quote "^1.6.1"
|
||||
string.prototype.padend "^3.0.0"
|
||||
|
||||
npm-run-path@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
|
||||
|
@ -2517,6 +2547,13 @@ path-type@^2.0.0:
|
|||
dependencies:
|
||||
pify "^2.0.0"
|
||||
|
||||
path-type@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
|
||||
integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==
|
||||
dependencies:
|
||||
pify "^3.0.0"
|
||||
|
||||
path-type@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
|
||||
|
@ -2527,11 +2564,21 @@ picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1, picomatch@^2.2.2:
|
|||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
|
||||
integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
|
||||
|
||||
pidtree@^0.3.0:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a"
|
||||
integrity sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==
|
||||
|
||||
pify@^2.0.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
|
||||
integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
|
||||
|
||||
pify@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
|
||||
integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
|
||||
|
||||
pify@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
|
||||
|
@ -2677,6 +2724,15 @@ read-pkg@^2.0.0:
|
|||
normalize-package-data "^2.3.2"
|
||||
path-type "^2.0.0"
|
||||
|
||||
read-pkg@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
|
||||
integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=
|
||||
dependencies:
|
||||
load-json-file "^4.0.0"
|
||||
normalize-package-data "^2.3.2"
|
||||
path-type "^3.0.0"
|
||||
|
||||
readable-stream@^2.0.2:
|
||||
version "2.3.7"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
||||
|
@ -2956,6 +3012,11 @@ shebang-regex@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
|
||||
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
|
||||
|
||||
shell-quote@^1.6.1:
|
||||
version "1.7.2"
|
||||
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2"
|
||||
integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==
|
||||
|
||||
signal-exit@^3.0.2:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
|
||||
|
@ -3148,6 +3209,14 @@ string-width@^4.1.0, string-width@^4.2.0:
|
|||
is-fullwidth-code-point "^3.0.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
string.prototype.padend@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz#dc08f57a8010dc5c153550318f67e13adbb72ac3"
|
||||
integrity sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA==
|
||||
dependencies:
|
||||
define-properties "^1.1.3"
|
||||
es-abstract "^1.17.0-next.1"
|
||||
|
||||
string.prototype.trimend@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913"
|
||||
|
|
Loading…
Reference in New Issue