Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(shiki-highlighter): improve performance & auto load new languages #1775

Merged
merged 2 commits into from
Jan 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 9 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@
"destr": "^1.2.2",
"detab": "^3.0.2",
"html-tags": "^3.2.0",
"json5": "^2.2.1",
"json5": "^2.2.3",
"knitwork": "^1.0.0",
"listhen": "^1.0.1",
"mdast-util-to-hast": "^12.2.4",
"mdast-util-to-hast": "^12.2.5",
"mdurl": "^1.0.1",
"ohash": "^1.0.0",
"pathe": "^1.0.0",
Expand All @@ -68,7 +68,7 @@
"remark-rehype": "^10.1.0",
"remark-squeeze-paragraphs": "^5.0.1",
"scule": "^1.0.0",
"shiki-es": "^0.1.2",
"shiki-es": "^0.2.0",
"slugify": "^1.6.5",
"socket.io-client": "^4.5.4",
"ufo": "^1.0.1",
Expand All @@ -77,26 +77,26 @@
"unist-util-position": "^4.0.3",
"unist-util-visit": "^4.1.1",
"unstorage": "^1.0.1",
"ws": "^8.11.0"
"ws": "^8.12.0"
},
"devDependencies": {
"@nuxt/module-builder": "^0.2.1",
"@nuxt/schema": "v3.0.0",
"@nuxt/test-utils": "v3.0.0",
"@nuxthq/admin": "npm:@nuxthq/admin-edge@latest",
"@nuxtjs/eslint-config-typescript": "latest",
"@types/ws": "^8.5.3",
"@types/ws": "^8.5.4",
"c8": "^7.12.0",
"csvtojson": "^2.0.10",
"eslint": "^8.29.0",
"eslint": "^8.31.0",
"globby": "^13.1.3",
"husky": "^8.0.2",
"jiti": "^1.16.0",
"husky": "^8.0.3",
"jiti": "^1.16.2",
"lint-staged": "^13.1.0",
"nuxt": "v3.0.0",
"rehype-figure": "^1.0.1",
"remark-oembed": "^1.2.2",
"vitest": "^0.25.8",
"vitest": "^0.27.0",
"vue-docgen-web-types": "^0.1.8"
}
}
45 changes: 25 additions & 20 deletions src/runtime/transformers/shiki/highlighter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ const logger = consola.withScope('@nuxt/content')
*
* Used to resolve lang from both languages id's and aliases.
*/
const resolveLang = (lang: string): Lang =>
(BUNDLED_LANGUAGES.find(l => l.id === lang || l.aliases?.includes(lang))?.id || lang) as Lang
const resolveLang = (lang: string) =>
(BUNDLED_LANGUAGES.find(l => l.id === lang || l.aliases?.includes(lang)))

/**
* Resolve Shiki compatible theme from string.
Expand Down Expand Up @@ -65,6 +65,16 @@ export const useShikiHighlighter = createSingleton((opts?: Exclude<ModuleOptions
grammar: mdcTMLanguage
}
] as any[]
}).then((highlighter) => {
// Load all themes on-demand
const themes = Object.values(typeof theme === 'string' ? { default: theme } : (theme || {}))

if (themes.length) {
return Promise
.all(themes.map(theme => highlighter.loadTheme(theme)))
.then(() => highlighter)
}
return highlighter
})
}
return promise
Expand All @@ -75,7 +85,7 @@ export const useShikiHighlighter = createSingleton((opts?: Exclude<ModuleOptions
// Remove trailing carriage returns
code = code.replace(/\n+$/, '')
// Resolve lang & theme (i.e check if shiki supports them)
lang = resolveLang(lang || '')
lang = (resolveLang(lang || '')?.id || lang) as Lang
theme = resolveTheme(theme || '') || { default: highlighter.getTheme() as any as ShikiTheme }

// Skip highlight if lang is not supported
Expand All @@ -85,30 +95,25 @@ export const useShikiHighlighter = createSingleton((opts?: Exclude<ModuleOptions

// Load supported language on-demand
if (!highlighter.getLoadedLanguages().includes(lang)) {
let message = 'Content Highlighter Error\n\n'
message = message + `Language "${lang}" is not loaded Shiki. Falling back to plain code.\n\n`
message = message + `Please make sure you add "${lang}" to the 'preload' list in your Nuxt config.\n\n`
message = message + 'See: https://content.nuxtjs.org/api/configuration#highlight'
logger.warn(message)
const languageRegistration = resolveLang(lang)

// TODO: Enable autoloading of language when upstream Shiki supports it\
// See: https://github.com/nuxt/content/issues/1225#issuecomment-1148786924
// await highlighter.loadLanguage(lang)
return [[{ content: code }]]
if (languageRegistration) {
await highlighter.loadLanguage(languageRegistration)
} else {
logger.warn(`Language '${lang}' is not supported by shiki. Skipping highlight.`)
return [[{ content: code }]]
}
}

// Load supported theme on-demand
await Promise.all(
Object.values(theme).map(async (theme) => {
if (!highlighter.getLoadedThemes().includes(theme)) {
await highlighter.loadTheme(theme)
}
})
)
const newThemes = Object.values(theme).filter(t => !highlighter.getLoadedThemes().includes(t))
if (newThemes.length) {
await Promise.all(newThemes.map(highlighter.loadTheme))
}

// Highlight code
const coloredTokens = Object.entries(theme).map(([key, theme]) => {
const tokens = highlighter.codeToThemedTokens(code, lang, theme)
const tokens = highlighter.codeToThemedTokens(code, lang, theme, { includeExplanation: false })
return {
key,
theme,
Expand Down
120 changes: 86 additions & 34 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -399,25 +399,25 @@
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.16.6.tgz#26094ac38600cdac049cb320018bc34da9af22c2"
integrity sha512-BlXuMzOWhAcdLRzE/PQLAAyhItzvL1fRMvbmHV6k09Xiq8rZzFJB/CrfX3ZQI0nKBlfxO4sLN9H9WwK2nLo7Pg==

"@eslint/eslintrc@^1.3.3":
version "1.3.3"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.3.tgz#2b044ab39fdfa75b4688184f9e573ce3c5b0ff95"
integrity sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==
"@eslint/eslintrc@^1.4.1":
version "1.4.1"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e"
integrity sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==
dependencies:
ajv "^6.12.4"
debug "^4.3.2"
espree "^9.4.0"
globals "^13.15.0"
globals "^13.19.0"
ignore "^5.2.0"
import-fresh "^3.2.1"
js-yaml "^4.1.0"
minimatch "^3.1.2"
strip-json-comments "^3.1.1"

"@humanwhocodes/config-array@^0.11.6":
version "0.11.7"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.7.tgz#38aec044c6c828f6ed51d5d7ae3d9b9faf6dbb0f"
integrity sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw==
"@humanwhocodes/config-array@^0.11.8":
version "0.11.8"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9"
integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==
dependencies:
"@humanwhocodes/object-schema" "^1.2.1"
debug "^4.1.1"
Expand Down Expand Up @@ -941,10 +941,10 @@
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d"
integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==

"@types/ws@^8.5.3":
version "8.5.3"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d"
integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==
"@types/ws@^8.5.4":
version "8.5.4"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.4.tgz#bb10e36116d6e570dd943735f86c933c1587b8a5"
integrity sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==
dependencies:
"@types/node" "*"

Expand Down Expand Up @@ -1638,6 +1638,11 @@ c8@^7.12.0:
yargs "^16.2.0"
yargs-parser "^20.2.9"

cac@^6.7.14:
version "6.7.14"
resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959"
integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==

cacheable-lookup@^5.0.3:
version "5.0.4"
resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005"
Expand Down Expand Up @@ -2882,13 +2887,13 @@ eslint-visitor-keys@^3.3.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==

eslint@^8.29.0:
version "8.29.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.29.0.tgz#d74a88a20fb44d59c51851625bc4ee8d0ec43f87"
integrity sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg==
eslint@^8.31.0:
version "8.31.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.31.0.tgz#75028e77cbcff102a9feae1d718135931532d524"
integrity sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA==
dependencies:
"@eslint/eslintrc" "^1.3.3"
"@humanwhocodes/config-array" "^0.11.6"
"@eslint/eslintrc" "^1.4.1"
"@humanwhocodes/config-array" "^0.11.8"
"@humanwhocodes/module-importer" "^1.0.1"
"@nodelib/fs.walk" "^1.2.8"
ajv "^6.10.0"
Expand All @@ -2907,7 +2912,7 @@ eslint@^8.29.0:
file-entry-cache "^6.0.1"
find-up "^5.0.0"
glob-parent "^6.0.2"
globals "^13.15.0"
globals "^13.19.0"
grapheme-splitter "^1.0.4"
ignore "^5.2.0"
import-fresh "^3.0.0"
Expand Down Expand Up @@ -3383,7 +3388,7 @@ globals@^11.1.0:
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==

globals@^13.15.0:
globals@^13.19.0:
version "13.19.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-13.19.0.tgz#7a42de8e6ad4f7242fbcca27ea5b23aca367b5c8"
integrity sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==
Expand Down Expand Up @@ -3799,10 +3804,10 @@ human-signals@^3.0.1:
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-3.0.1.tgz#c740920859dafa50e5a3222da9d3bf4bb0e5eef5"
integrity sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==

husky@^8.0.2:
version "8.0.2"
resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.2.tgz#5816a60db02650f1f22c8b69b928fd6bcd77a236"
integrity sha512-Tkv80jtvbnkK3mYWxPZePGFpQ/tT3HNSs/sasF9P2YfkMezDl3ON37YN6jUUI4eTg5LcyVynlb6r4eyvOmspvg==
husky@^8.0.3:
version "8.0.3"
resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184"
integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==

iconv-lite@^0.4.24:
version "0.4.24"
Expand Down Expand Up @@ -4218,6 +4223,11 @@ jiti@^1.16.0:
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.16.0.tgz#f72065954446ad1866fa8d6bcc3bed3cc1cebdaa"
integrity sha512-L3BJStEf5NAqNuzrpfbN71dp43mYIcBUlCRea/vdyv5dW/AYa1d4bpelko4SHdY3I6eN9Wzyasxirj1/vv5kmg==

jiti@^1.16.2:
version "1.16.2"
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.16.2.tgz#75f7a0a8fde4a0e57e576f7d329491d588db89cf"
integrity sha512-OKBOVWmU3FxDt/UH4zSwiKPuc1nihFZiOD722FuJlngvLz2glX1v2/TJIgoA4+mrpnXxHV6dSAoCvPcYQtoG5A==

js-sdsl@^4.1.4:
version "4.2.0"
resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.2.0.tgz#278e98b7bea589b8baaf048c20aeb19eb7ad09d0"
Expand Down Expand Up @@ -4277,6 +4287,11 @@ json5@^2.2.1:
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==

json5@^2.2.3:
version "2.2.3"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==

jsonc-parser@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76"
Expand Down Expand Up @@ -4697,7 +4712,7 @@ mdast-util-gfm@^2.0.0:
mdast-util-gfm-task-list-item "^1.0.0"
mdast-util-to-markdown "^1.0.0"

mdast-util-to-hast@^12.1.0, mdast-util-to-hast@^12.2.4:
mdast-util-to-hast@^12.1.0:
version "12.2.4"
resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-12.2.4.tgz#34c1ef2b6cf01c27b3e3504e2c977c76f722e7e1"
integrity sha512-a21xoxSef1l8VhHxS1Dnyioz6grrJkoaCUgGzMD/7dWHvboYX3VW53esRUfB5tgTyz4Yos1n25SPcj35dJqmAg==
Expand All @@ -4712,6 +4727,21 @@ mdast-util-to-hast@^12.1.0, mdast-util-to-hast@^12.2.4:
unist-util-position "^4.0.0"
unist-util-visit "^4.0.0"

mdast-util-to-hast@^12.2.5:
version "12.2.5"
resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-12.2.5.tgz#91532ebd929a7def21585034f7901eb367d2d272"
integrity sha512-EFNhT35ZR/VZ85/EedDdCNTq0oFM+NM/+qBomVGQ0+Lcg0nhI8xIwmdCzNMlVlCJNXRprpobtKP/IUh8cfz6zQ==
dependencies:
"@types/hast" "^2.0.0"
"@types/mdast" "^3.0.0"
mdast-util-definitions "^5.0.0"
micromark-util-sanitize-uri "^1.1.0"
trim-lines "^3.0.0"
unist-builder "^3.0.0"
unist-util-generated "^2.0.0"
unist-util-position "^4.0.0"
unist-util-visit "^4.0.0"

mdast-util-to-markdown@^1.0.0, mdast-util-to-markdown@^1.3.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-1.4.0.tgz#bb0153a865dbc022975f403a156fb6399c494ddf"
Expand Down Expand Up @@ -6766,10 +6796,10 @@ shebang-regex@^3.0.0:
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==

shiki-es@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/shiki-es/-/shiki-es-0.1.2.tgz#37176c6ff8d734f95e27560b62e1230c9a90c0cb"
integrity sha512-eqtfk8idlYlSLAn0gp0Ly2+FbKc2d78IddigHSS4iHAnpXoY2kdRzyFGZOdi6TvemYMnRhZBi1HsSqZc5eNKqg==
shiki-es@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/shiki-es/-/shiki-es-0.2.0.tgz#ae5bced62dca0ba46ee81149e68d428565a3e6fb"
integrity sha512-RbRMD+IuJJseSZljDdne9ThrUYrwBwJR04FvN4VXpfsU3MNID5VJGHLAD5je/HGThCyEKNgH+nEkSFEWKD7C3Q==

side-channel@^1.0.4:
version "1.0.4"
Expand Down Expand Up @@ -7667,6 +7697,20 @@ vfile@^5.0.0:
unist-util-stringify-position "^3.0.0"
vfile-message "^3.0.0"

vite-node@0.27.0:
version "0.27.0"
resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-0.27.0.tgz#26ec5895565fce43b501ea53ba905bb5b62318e1"
integrity sha512-O1o9joT0qCGx5Om6W0VNLr7M00ttrnFlfZX2d+oxt2T9oZ9DvYSv8kDRhNJDVhAgNgUm3Tc0h/+jppNf3mVKbA==
dependencies:
cac "^6.7.14"
debug "^4.3.4"
mlly "^1.0.0"
pathe "^0.2.0"
picocolors "^1.0.0"
source-map "^0.6.1"
source-map-support "^0.5.21"
vite "^3.0.0 || ^4.0.0"

vite-node@^0.25.2:
version "0.25.8"
resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-0.25.8.tgz#b1477e9d84b9e86dddc559542179ae3d34a264e9"
Expand Down Expand Up @@ -7724,25 +7768,28 @@ vite@~3.2.4:
optionalDependencies:
fsevents "~2.3.2"

vitest@^0.25.8:
version "0.25.8"
resolved "https://registry.yarnpkg.com/vitest/-/vitest-0.25.8.tgz#9b57e0b41cd6f2d2d92aa94a39b35c36f715f8cc"
integrity sha512-X75TApG2wZTJn299E/TIYevr4E9/nBo1sUtZzn0Ci5oK8qnpZAZyhwg0qCeMSakGIWtc6oRwcQFyFfW14aOFWg==
vitest@^0.27.0:
version "0.27.0"
resolved "https://registry.yarnpkg.com/vitest/-/vitest-0.27.0.tgz#6f76e76f0f8dd5d41cb30c75623b2d43a41101fb"
integrity sha512-BnOa7T6CnXVC6UgcAsvFOZ2Dtvqkt+/Nl6CRgh4qVT70vElf65XwEL6zMRyTF+h2QXJziEkxYdrLo5WCxckMLQ==
dependencies:
"@types/chai" "^4.3.4"
"@types/chai-subset" "^1.3.3"
"@types/node" "*"
acorn "^8.8.1"
acorn-walk "^8.2.0"
cac "^6.7.14"
chai "^4.3.7"
debug "^4.3.4"
local-pkg "^0.4.2"
picocolors "^1.0.0"
source-map "^0.6.1"
strip-literal "^1.0.0"
tinybench "^2.3.1"
tinypool "^0.3.0"
tinyspy "^1.0.2"
vite "^3.0.0 || ^4.0.0"
vite-node "0.27.0"

void-elements@^3.1.0:
version "3.1.0"
Expand Down Expand Up @@ -7986,6 +8033,11 @@ ws@^8.11.0, ws@^8.6.0:
resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143"
integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==

ws@^8.12.0:
version "8.12.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8"
integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==

ws@~8.2.3:
version "8.2.3"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba"
Expand Down