diff --git a/.docs/images/navigation.png b/.docs/images/navigation.png new file mode 100644 index 0000000..f70f3ec Binary files /dev/null and b/.docs/images/navigation.png differ diff --git a/.docs/images/plugin-config.png b/.docs/images/plugin-config.png new file mode 100644 index 0000000..0facdbd Binary files /dev/null and b/.docs/images/plugin-config.png differ diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..27dd8af --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "endOfLine": "lf", + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "all" +} diff --git a/Readme.md b/Readme.md index 1ff1d8b..71ec493 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,19 @@ [[_TOC_]] -# Plain JS Plugin +# Singleton types + +## Usage + +Select content types that should only contain one record. + +![](.docs/images/plugin-config.png) + +Now when you click on the types selected in the plugin configuration you will be taken directly to the edit or add page +of Content object + +![](.docs/images/navigation.png) + +> **Warning**: Using the plugin does not change the way the API manages objects ## Quick start @@ -26,7 +39,9 @@ The plugins are built into a single `dist/index.js` file. The manifest is copied ## Loading the plugin -**Warning:** While developing, you can use `https://localhost:3053/plugin-manifest.json` address to load the plugin manifest. Make sure your browser trusts the local certificate on the latter, to be able to use it e.g. with `https://editor.flotiq.com` +**Warning:** While developing, you can use `https://localhost:3053/plugin-manifest.json` address to load the plugin +manifest. Make sure your browser trusts the local certificate on the latter, to be able to use it e.g. +with `https://editor.flotiq.com` ### URL @@ -44,7 +59,7 @@ The plugins are built into a single `dist/index.js` file. The manifest is copied 1. Open Flotiq editor 2. Open Chrome Dev console -3. Paste the content of `dist/index.js` +3. Paste the content of `dist/index.js` 4. Navigate to the view that is modified by the plugin ### Deployment diff --git a/common/api-helpers.js b/common/api-helpers.js deleted file mode 100644 index 06f87cd..0000000 --- a/common/api-helpers.js +++ /dev/null @@ -1,17 +0,0 @@ -const cachedRelationData = {}; - -const getRelationData = (client, dataUrl) => { - if (!dataUrl) return null; - if (cachedRelationData[dataUrl]) return cachedRelationData[dataUrl]; - const { contentTypeName, id } = dataUrl.match( - /(?[^/]+)\/(?[^/]+)$/, - ).groups; - - cachedRelationData[dataUrl] = client[contentTypeName] - .get(id) - .then(({ body }) => body); - - return cachedRelationData[dataUrl]; -}; - -export { getRelationData }; diff --git a/common/plugin-element-cache.js b/common/plugin-element-cache.js index eb43a2c..ff7b3bd 100644 --- a/common/plugin-element-cache.js +++ b/common/plugin-element-cache.js @@ -6,13 +6,26 @@ export const addElementToCache = (element, key, data = {}) => { data, }; + let detachTimeoutId; + + element.addEventListener('flotiq.attached', () => { + if (detachTimeoutId) { + clearTimeout(detachTimeoutId); + detachTimeoutId = null; + } + }); + element.addEventListener('flotiq.detached', () => { - setTimeout(() => { - return delete appRoots[key]; + detachTimeoutId = setTimeout(() => { + delete appRoots[key]; }, 50); }); }; +export const addObjectToCache = (key, data = {}) => { + appRoots[key] = data; +}; + export const getCachedElement = (key) => { return appRoots[key]; }; diff --git a/i18n.js b/i18n.js new file mode 100644 index 0000000..7302917 --- /dev/null +++ b/i18n.js @@ -0,0 +1,24 @@ +import i18n from 'i18next'; + +i18n.init({ + fallbackLng: 'en', + supportedLngs: ['en', 'pl'], + resources: { + en: { + translation: { + SingletonTypes: 'Singleton Types', + SingletonTypesDescription: + 'List of content types that should only contain one record', + }, + }, + pl: { + translation: { + SingletonTypes: 'Typy singletonowe', + SingletonTypesDescription: + 'Lista typów treści, które powinny zawierać tylko jeden rekord.', + }, + }, + }, +}); + +export default i18n; diff --git a/package.json b/package.json index 9556ae4..28d0179 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,8 @@ }, "dependencies": { "chalk": "^5.3.0", - "esbuild-plugin-copy": "^2.1.1" + "esbuild-plugin-copy": "^2.1.1", + "i18n": "^0.15.1", + "i18next": "^24.2.0" } } diff --git a/plugin-manifest.json b/plugin-manifest.json index 35f614d..50d796e 100644 --- a/plugin-manifest.json +++ b/plugin-manifest.json @@ -1,15 +1,9 @@ { - "id": "flotiq.plain-js-template", - "name": "Plain JS Plugin Template", - "description": "A plain js example of Flotiq plugin. This plugin changes the rendering of some data in the grid. It renders colorful text properties, bold numbers, and relations as text.", - "version": "0.1.2", - "repository": "https://github.com/flotiq/flotiq-ui-plugin-templates-plain-js", + "id": "flotiq.singleton-types", + "name": "Flotiq singleton types plugin", + "description": "The plugin allows setting selected content types as singletons, redirecting object views to creation or editing skipping the content objects grid", + "version": "0.1.3", + "repository": "https://github.com/flotiq/flotiq-ui-plugin-singleton-types", "url": "https://localhost:3053/index.js", - "permissions": [ - { - "ctdName": "*", - "canRead": true, - "type": "CO" - } - ] + "permissions": [] } diff --git a/plugins/grid-renderers/index.js b/plugins/grid-renderers/index.js deleted file mode 100644 index 42990c3..0000000 --- a/plugins/grid-renderers/index.js +++ /dev/null @@ -1,62 +0,0 @@ -import { getRelationData } from "../../common/api-helpers"; -import { - addElementToCache, - getCachedElement, -} from "../../common/plugin-element-cache"; - -const textColors = [ - "rgb(239 68 68)", - "rgb(249 115 22)", - "rgb(234 179 8)", - "rgb(132 204 22)", - "rgb(34 197 94)", - "rgb(20 184 166)", - "rgb(59 130 246)", - "rgb(139 92 246)", - "rgb(168 85 247)", - "rgb(217 70 239)", -]; - -export function handleGridPlugin( - { accessor, contentObject, inputType, data }, - client, - pluginInfo, -) { - if (!["text", "number", "datasource"].includes(inputType)) return; - - const cacheKey = `${pluginInfo.id}-${contentObject.id}-${accessor}`; - - let element = getCachedElement(cacheKey)?.element; - if (!element) { - element = document.createElement("div"); - element.classList.add("plugin-name-cell-renderer"); - if (inputType === "text") { - const textColor = textColors[Math.floor(Math.random() * 10)]; - element.style.color = textColor; - element.textContent = data; - } else if (inputType === "number") { - element.style.fontWeight = 900; - element.textContent = data; - } else { - if (data) - Promise.all( - data.map((relation) => - getRelationData(client, relation.dataUrl).then( - (data) => - data.internal?.objectTitle || - data.title || - data.name || - data.id, - ), - ), - ).then((resultArray) => { - const joinedData = (resultArray || []).filter((r) => !!r).join(", "); - element.textContent = joinedData; - }); - } - } - - addElementToCache(element, cacheKey); - - return element; -} diff --git a/plugins/index.js b/plugins/index.js index 8882312..414ff02 100644 --- a/plugins/index.js +++ b/plugins/index.js @@ -1,20 +1,40 @@ -import { registerFn } from "../common/plugin-element-cache"; -import pluginInfo from "../plugin-manifest.json"; -import cssString from "inline:./styles/style.css"; -import { handleGridPlugin } from "./grid-renderers"; +import { registerFn } from '../common/plugin-element-cache'; +import pluginInfo from '../plugin-manifest.json'; +import cssString from 'inline:./styles/style.css'; +import { pluginsManageFormSchemaHandler } from './mange/index.js'; +import gridRenderHandler from './navigate/index.js'; +import i18n from '../i18n.js'; -registerFn(pluginInfo, (handler, client) => { - /** - * Add plugin styles to the head of the document - */ - if (!document.getElementById(`${pluginInfo.id}-styles`)) { - const style = document.createElement("style"); - style.id = `${pluginInfo.id}-styles`; - style.textContent = cssString; - document.head.appendChild(style); - } +registerFn( + pluginInfo, + (handler, _, { getPluginSettings, getLanguage, navigate }) => { + /** + * Add plugin styles to the head of the document + */ + if (!document.getElementById(`${pluginInfo.id}-styles`)) { + const style = document.createElement('style'); + style.id = `${pluginInfo.id}-styles`; + style.textContent = cssString; + document.head.appendChild(style); + } - handler.on("flotiq.grid.cell::render", (data) => - handleGridPlugin(data, client, pluginInfo), - ); -}); + const language = getLanguage(); + if (language !== i18n.language) { + i18n.changeLanguage(language); + } + + handler.on('flotiq.grid::render', (event) => { + return gridRenderHandler(event, getPluginSettings, navigate); + }); + + handler.on('flotiq.plugins.manage::form-schema', ({ contentTypes }) => { + return pluginsManageFormSchemaHandler(contentTypes); + }); + + handler.on('flotiq.language::changed', ({ language }) => { + if (language !== i18n.language) { + i18n.changeLanguage(language); + } + }); + }, +); diff --git a/plugins/mange/index.js b/plugins/mange/index.js new file mode 100644 index 0000000..f7870b2 --- /dev/null +++ b/plugins/mange/index.js @@ -0,0 +1,52 @@ +import pluginInfo from '../../plugin-manifest.json'; +import i18n from 'i18next'; + +const getFields = (contentTypes) => { + return { + metaDefinition: { + order: ['singleton_types'], + propertiesConfig: { + singleton_types: { + label: i18n.t('SingletonTypes'), + helpText: i18n.t('SingletonTypesDescription'), + unique: false, + inputType: 'select', + optionsWithLabels: contentTypes, + useOptionsWithLabels: true, + isMultiple: true, + }, + }, + }, + schemaDefinition: { + additionalProperties: false, + required: [], + type: 'object', + allOf: [ + { + $ref: '#/components/schemas/AbstractContentTypeSchemaDefinition', + }, + { + type: 'object', + properties: { + singleton_types: { + type: 'array', + }, + }, + }, + ], + }, + }; +}; + +export const pluginsManageFormSchemaHandler = (contentTypes) => { + const ctds = contentTypes + ?.filter(({ internal }) => !internal) + ?.map(({ name, label }) => ({ value: name, label })); + + return { + schema: { + ...getFields(ctds), + id: pluginInfo.id, + }, + }; +}; diff --git a/plugins/navigate/index.js b/plugins/navigate/index.js new file mode 100644 index 0000000..e0a976e --- /dev/null +++ b/plugins/navigate/index.js @@ -0,0 +1,47 @@ +import { + addElementToCache, + getCachedElement, +} from '../../common/plugin-element-cache.js'; + +const generateLoader = (pluginId) => { + let loader = getCachedElement( + `${pluginId}-flotiq-singleton-plugin-loader`, + )?.element; + + if (!loader) { + loader = document.createElement('div'); + loader.classList.add('flotiq-singleton-plugin-loader-container'); + loader.innerHTML = '
'; + + addElementToCache(loader, `${pluginId}-flotiq-singleton-plugin-loader`); + } + + return loader; +}; + +export default function gridRenderHandler( + { contentType, contentObjects, isFetching, isLoading }, + getPluginSettings, + navigate, +) { + if (isLoading || isFetching) return generateLoader(); + const settings = JSON.parse(getPluginSettings()); + + if (!settings.singleton_types.includes(contentType?.name)) return; + + const url = new URL(window.location.href); + + if (!contentObjects[0]) { + url.pathname = url.pathname.replace( + '/' + contentType.name, + `/add/${contentType.name}`, + ); + } else { + url.pathname = url.pathname.replace( + '/' + contentType.name, + `/edit/${contentType.name}/${contentObjects[0].id}`, + ); + } + + navigate(url.pathname); +} diff --git a/plugins/styles/RobotoMono-Medium.ttf b/plugins/styles/RobotoMono-Medium.ttf deleted file mode 100644 index f6c149a..0000000 Binary files a/plugins/styles/RobotoMono-Medium.ttf and /dev/null differ diff --git a/plugins/styles/style.css b/plugins/styles/style.css index fdcc8ad..08d7e67 100644 --- a/plugins/styles/style.css +++ b/plugins/styles/style.css @@ -1,8 +1,16 @@ -@font-face { - font-family: "Roboto Mono"; - src: url(./RobotoMono-Medium.ttf) format("truetype"); +.flotiq-singleton-plugin-loader-container{ + width: 100%; + height: 100vh; + display: flex; + justify-content: center; + align-items: center; } -.plugin-name-cell-renderer { - font-family: "Roboto Mono", monospace; +.flotiq-singleton-plugin-loader{ + width: 50px; + height: 50px; + border: 5px solid #ccc; + border-top: 5px solid #0083FC; + border-radius: 50%; + animation: spin 1s linear infinite; } diff --git a/yarn.lock b/yarn.lock index 042cc78..642189a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16,6 +16,13 @@ eslint-visitor-keys "^2.1.0" semver "^6.3.1" +"@babel/runtime@^7.23.2": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1" + integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== + dependencies: + regenerator-runtime "^0.14.0" + "@esbuild/aix-ppc64@0.20.2": version "0.20.2" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz#a70f4ac11c6a1dfc18b8bbb13284155d933b9537" @@ -182,6 +189,42 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== +"@messageformat/core@^3.0.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@messageformat/core/-/core-3.4.0.tgz#2814c23383dec7bddf535d54f2a03e410165ca9f" + integrity sha512-NgCFubFFIdMWJGN5WuQhHCNmzk7QgiVfrViFxcS99j7F5dDS5EP6raR54I+2ydhe4+5/XTn/YIEppFaqqVWHsw== + dependencies: + "@messageformat/date-skeleton" "^1.0.0" + "@messageformat/number-skeleton" "^1.0.0" + "@messageformat/parser" "^5.1.0" + "@messageformat/runtime" "^3.0.1" + make-plural "^7.0.0" + safe-identifier "^0.4.1" + +"@messageformat/date-skeleton@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@messageformat/date-skeleton/-/date-skeleton-1.1.0.tgz#3bad068cbf5873d14592cfc7a73dd4d8615e2739" + integrity sha512-rmGAfB1tIPER+gh3p/RgA+PVeRE/gxuQ2w4snFWPF5xtb5mbWR7Cbw7wCOftcUypbD6HVoxrVdyyghPm3WzP5A== + +"@messageformat/number-skeleton@^1.0.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@messageformat/number-skeleton/-/number-skeleton-1.2.0.tgz#e7c245c41a1b2722bc59dad68f4d454f761bc9b4" + integrity sha512-xsgwcL7J7WhlHJ3RNbaVgssaIwcEyFkBqxHdcdaiJzwTZAWEOD8BuUFxnxV9k5S0qHN3v/KzUpq0IUpjH1seRg== + +"@messageformat/parser@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@messageformat/parser/-/parser-5.1.0.tgz#05e4851c782d633ad735791dd0a68ee65d2a7201" + integrity sha512-jKlkls3Gewgw6qMjKZ9SFfHUpdzEVdovKFtW1qRhJ3WI4FW5R/NnGDqr8SDGz+krWDO3ki94boMmQvGke1HwUQ== + dependencies: + moo "^0.5.1" + +"@messageformat/runtime@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@messageformat/runtime/-/runtime-3.0.1.tgz#94d1f6c43265c28ef7aed98ecfcc0968c6c849ac" + integrity sha512-6RU5ol2lDtO8bD9Yxe6CZkl0DArdv0qkuoZC+ZwowU+cdRlVE1157wjCmlA5Rsf1Xc/brACnsZa5PZpEDfTFFg== + dependencies: + make-plural "^7.0.0" + "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": version "5.1.1-v1" resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" @@ -361,6 +404,13 @@ debug@^4.3.1, debug@^4.3.2: dependencies: ms "2.1.2" +debug@^4.3.3: + version "4.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -573,6 +623,11 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-printf@^1.6.9: + version "1.6.10" + resolved "https://registry.yarnpkg.com/fast-printf/-/fast-printf-1.6.10.tgz#c44ad871726152159d7a903a5af0d65cf3d75875" + integrity sha512-GwTgG9O4FVIdShhbVF3JxOgSBY2+ePGsu2V/UONgoCPzF9VY6ZdBMKsHKCYQHZwNk3qNouUolRDsgVxcVA5G1w== + fastq@^1.6.0: version "1.17.1" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" @@ -695,6 +750,25 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +i18n@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/i18n/-/i18n-0.15.1.tgz#68fb8993c461cc440bc2485d82f72019f2b92de8" + integrity sha512-yue187t8MqUPMHdKjiZGrX+L+xcUsDClGO0Cz4loaKUOK9WrGw5pgan4bv130utOwX7fHE9w2iUeHFalVQWkXA== + dependencies: + "@messageformat/core" "^3.0.0" + debug "^4.3.3" + fast-printf "^1.6.9" + make-plural "^7.0.0" + math-interval-parser "^2.0.1" + mustache "^4.2.0" + +i18next@^24.2.0: + version "24.2.0" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-24.2.0.tgz#344c15a6f3b43d02aed78e2b08532e5b170951b4" + integrity sha512-ArJJTS1lV6lgKH7yEf4EpgNZ7+THl7bsGxxougPYiXRTJ/Fe1j08/TBpV9QsXCIYVfdE/HWG/xLezJ5DOlfBOA== + dependencies: + "@babel/runtime" "^7.23.2" + ignore@^5.2.0: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" @@ -825,6 +899,16 @@ make-dir@~3.1.0: dependencies: semver "^6.0.0" +make-plural@^7.0.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/make-plural/-/make-plural-7.4.0.tgz#fa6990dd550dea4de6b20163f74e5ed83d8a8d6d" + integrity sha512-4/gC9KVNTV6pvYg2gFeQYTW3mWaoJt7WZE5vrp1KnQDgW92JtYZnzmZT81oj/dUTqAIu0ufI2x3dkgu3bB1tYg== + +math-interval-parser@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/math-interval-parser/-/math-interval-parser-2.0.1.tgz#e22cd6d15a0a7f4c03aec560db76513da615bed4" + integrity sha512-VmlAmb0UJwlvMyx8iPhXUDnVW1F9IrGEd9CIOmv+XL8AErCUUuozoDMrgImvnYt2A+53qVX/tPW6YJurMKYsvA== + merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" @@ -857,11 +941,26 @@ minimatch@~3.0.4: dependencies: brace-expansion "^1.1.7" +moo@^0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.2.tgz#f9fe82473bc7c184b0d32e2215d3f6e67278733c" + integrity sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +mustache@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64" + integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== + nanoid@^3.3.7: version "3.3.7" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" @@ -993,6 +1092,11 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -1017,6 +1121,11 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +safe-identifier@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/safe-identifier/-/safe-identifier-0.4.2.tgz#cf6bfca31c2897c588092d1750d30ef501d59fcb" + integrity sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w== + semver@^6.0.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"