From 76a4fa629c495056de9c6d4be8186a1d1dd75465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vandr=C3=A9=20Leal?= Date: Wed, 28 Jun 2023 14:38:40 -0300 Subject: [PATCH] chore: add prettier and husky for formatting --- .husky/pre-commit | 4 + .prettierignore | 5 + .prettierrc | 9 + README.md | 40 +-- admonition-icons.js | 19 +- babel.config.js | 4 +- constants.js | 82 +++--- docusaurus.config.js | 268 ++++++++--------- package.json | 12 +- replace-algolia-objects.js | 52 ++-- shared/_example-shared-content.md | 2 +- src/api.js | 54 ++-- src/build-algolia-objects.js | 316 ++++++++++----------- src/components/FeedbackForm/index.js | 47 +-- src/components/FeedbackFormButton/index.js | 18 +- src/components/ImageShowcase/index.js | 26 +- src/components/InputField/index.js | 17 +- src/components/LoadingSpinner/index.js | 19 +- src/contexts/AuthContext.js | 87 +++--- src/contexts/BreadcrumbsContext.js | 61 ++-- src/contexts/DocusaurusContext.js | 39 +-- src/define-env-vars-plugin.js | 42 +-- src/environment.js | 2 +- src/hooks/useAuthContext.js | 9 +- src/hooks/useBreadcrumbsContext.js | 9 +- src/hooks/useFeedbackForm.js | 56 ++-- src/hooks/useFeedbackFormData.js | 71 ++--- src/hooks/useToast.js | 14 +- src/pages/index.js | 46 +-- src/product-variables.js | 36 +-- src/symlink-docusaurus/index.js | 22 +- src/theme/DocItem/index.js | 8 +- src/theme/DocPaginator/index.js | 10 +- src/theme/DocSidebar/index.js | 38 +-- src/theme/Heading/index.js | 55 ++-- src/theme/Layout/index.js | 32 ++- src/theme/Navbar/index.js | 68 ++--- src/theme/NavbarItem/index.js | 96 +++---- src/theme/Root/index.js | 10 +- src/theme/SearchBar/DocSearchModal.js | 181 ++++++------ src/theme/SearchBar/Footer.js | 6 +- src/theme/SearchBar/Hits.js | 72 +++-- src/theme/SearchBar/SearchBox.js | 16 +- src/theme/SearchBar/Snippet.js | 12 +- src/theme/SearchBar/getItemUrl.js | 16 +- src/theme/SearchBar/icons/GoToExternal.js | 4 +- src/theme/SearchBar/icons/LoadingIcon.js | 4 +- src/theme/SearchBar/icons/SearchIcon.js | 4 +- src/theme/SearchBar/icons/SourceIcon.js | 18 +- src/theme/SearchBar/index.js | 71 +++-- src/theme/SearchBar/useTouchEvents.js | 18 +- src/theme/SearchBar/useTrapFocus.js | 32 +-- src/theme/prism-include-languages.js | 36 +-- urls.js | 18 +- yarn.lock | 210 +++++++++++++- 55 files changed, 1387 insertions(+), 1136 deletions(-) create mode 100644 .husky/pre-commit create mode 100644 .prettierignore create mode 100644 .prettierrc diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..d2041c1 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +yarn pretty-quick --staged \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..b20ffc5 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +dist +node_modules +build +coverage +.docusaurus \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..a751884 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,9 @@ +{ + "arrowParens": "avoid", + "semi": false, + "importOrder": ["^react$", "", "^@(.*)$", "^[./]"], + "importOrderCaseInsensitive": true, + "importOrderParserPlugins": ["jsx", "typescript"], + "importOrderSeparation": true, + "importOrderSortSpecifiers": true +} diff --git a/README.md b/README.md index b958c52..216fa21 100644 --- a/README.md +++ b/README.md @@ -82,23 +82,23 @@ For example for React Native, there is a file at `/docusaurus/reactnative-docusa module.exports = { plugins: [ [ - '@docusaurus/plugin-content-docs', + "@docusaurus/plugin-content-docs", { - lastVersion: '3.x.x', + lastVersion: "3.x.x", versions: { current: { - label: '4.0.0', - banner: 'unreleased', - path: '4.0.0', + label: "4.0.0", + banner: "unreleased", + path: "4.0.0", }, - '3.x.x': { - label: '3.x.x', + "3.x.x": { + label: "3.x.x", }, }, }, ], ], -}; +} ``` ## Sidebars @@ -117,7 +117,7 @@ To share content between multiple SDKs, put markdown files in the `shared` direc Then, import and render the shared content using mdx: ```mdx -import SharedContent from '../../../shared/_example-shared-content.md'; +import SharedContent from "../../../shared/_example-shared-content.md" ``` @@ -171,13 +171,13 @@ To make use of the `` component, remember to add the correct im Example of how to use it: ```jsx -import ImageShowcase from '@site/src/components/ImageShowcase'; +import ImageShowcase from "@site/src/components/ImageShowcase" -import channelList from '../assets/channel_list.png'; -import messageInput from '../assets/message_input.png'; -import messageList from '../assets/message_list.png'; +import channelList from "../assets/channel_list.png" +import messageInput from "../assets/message_input.png" +import messageList from "../assets/message_list.png" -ChannelList can be used with no props ), - alt: 'Example of how to use channelList component', + alt: "Example of how to use channelList component", }, - { image: messageInput, caption: 'Message input design' }, - { image: messageList, caption: 'Message list sample' }, + { image: messageInput, caption: "Message input design" }, + { image: messageList, caption: "Message list sample" }, ]} -/>; +/> ``` ![Example ImageShowcase desktop](./assets/images/Example_showcase.png) @@ -205,12 +205,12 @@ You can also add border to the images using the boolean prop `border` like the f { image: image1, caption: Images with border 🙂, - alt: 'Example of custom message', + alt: "Example of custom message", }, { image: image2, caption: Another one!, - alt: 'Example of custom message part 2', + alt: "Example of custom message part 2", }, ]} /> diff --git a/admonition-icons.js b/admonition-icons.js index 4330a6f..79a8094 100644 --- a/admonition-icons.js +++ b/admonition-icons.js @@ -1,17 +1,22 @@ -const note = ''; +const note = + '' -const tip = ''; +const tip = + '' -const info = ''; +const info = + '' -const caution = ''; +const caution = + '' -const danger = ''; +const danger = + '' module.exports = { note, tip, info, caution, - danger -}; + danger, +} diff --git a/babel.config.js b/babel.config.js index af33a6d..c7f2312 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,4 +1,4 @@ /* eslint-disable no-undef */ module.exports = { - presets: [require.resolve('@docusaurus/core/lib/babel/preset')], -}; + presets: [require.resolve("@docusaurus/core/lib/babel/preset")], +} diff --git a/constants.js b/constants.js index 4bf228c..31e9379 100644 --- a/constants.js +++ b/constants.js @@ -1,54 +1,54 @@ const folderMapping = { - android: 'Android', - flutter: 'Flutter', - ios: 'iOS', - react: 'React', - reactnative: 'React Native', - angular: 'Angular', - api: 'API', -}; + android: "Android", + flutter: "Flutter", + ios: "iOS", + react: "React", + reactnative: "React Native", + angular: "Angular", + api: "API", +} const platformMapping = { - android: 'android', - flutter: 'flutter-dart', - ios: 'ios-swift', - react: 'react', - reactnative: 'react-native', - angular: 'angular', - api: 'api', -}; + android: "android", + flutter: "flutter-dart", + ios: "ios-swift", + react: "react", + reactnative: "react-native", + angular: "angular", + api: "api", +} const languageMapping = { - android: 'kotlin', - flutter: 'dart', - ios: 'swift', - react: 'javascript', - reactnative: 'javascript', - angular: 'javascript', - api: 'javascript', -}; + android: "kotlin", + flutter: "dart", + ios: "swift", + react: "javascript", + reactnative: "javascript", + angular: "javascript", + api: "javascript", +} -const PRODUCT = process.env.PRODUCT; +const PRODUCT = process.env.PRODUCT let DOCUSAURUS_INDEX = - process.env.DEPLOYMENT_ENV === 'production' - ? `DOCUSAURUS${PRODUCT === 'video' ? '_VIDEO' : ''}` - : `DOCUSAURUS${PRODUCT === 'video' ? '_VIDEO' : ''}_STG`; -const CMS_INDEX = 'DOCS'; + process.env.DEPLOYMENT_ENV === "production" + ? `DOCUSAURUS${PRODUCT === "video" ? "_VIDEO" : ""}` + : `DOCUSAURUS${PRODUCT === "video" ? "_VIDEO" : ""}_STG` +const CMS_INDEX = "DOCS" -const IGNORED_DIRECTORIES = ['common-content']; +const IGNORED_DIRECTORIES = ["common-content"] const SDK_ORDER = [ - 'react', - 'ios', - 'android', - 'reactnative', - 'flutter', - 'angular', - 'api', -]; + "react", + "ios", + "android", + "reactnative", + "flutter", + "angular", + "api", +] -const ignoredVideoSDKsStaging = ['angular']; -const ignoredVideoSDKsProduction = ['angular', 'reactnative']; +const ignoredVideoSDKsStaging = ["angular"] +const ignoredVideoSDKsProduction = ["angular", "reactnative"] module.exports = { IGNORED_DIRECTORIES, @@ -60,4 +60,4 @@ module.exports = { SDK_ORDER, ignoredVideoSDKsStaging, ignoredVideoSDKsProduction, -}; +} diff --git a/docusaurus.config.js b/docusaurus.config.js index f8f017a..2d183fb 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -1,19 +1,19 @@ /* eslint-disable no-undef */ /** @type {import('@docusaurus/types').DocusaurusConfig} */ -const fs = require('node:fs'); -const path = require('node:path'); +const fs = require("node:fs") +const path = require("node:path") const STREAM_SDK_DOCUSAURUS_PATH = path.join( process.env.CURRENT_WORKING_PATH, - 'docusaurus' -); + "docusaurus" +) -require('dotenv').config({ - path: path.join(STREAM_SDK_DOCUSAURUS_PATH, '.env'), -}); +require("dotenv").config({ + path: path.join(STREAM_SDK_DOCUSAURUS_PATH, ".env"), +}) if (!process.env.PRODUCT) { - process.env.PRODUCT = 'chat'; + process.env.PRODUCT = "chat" } const { @@ -22,58 +22,58 @@ const { SDK_ORDER, ignoredVideoSDKsStaging, ignoredVideoSDKsProduction, -} = require('./constants'); -const URLS = require('./urls'); -const productVariables = require('./src/product-variables'); -const Icons = require('./admonition-icons'); +} = require("./constants") +const URLS = require("./urls") +const productVariables = require("./src/product-variables") +const Icons = require("./admonition-icons") -const getCustomPluginRegExp = (prefix = '') => - new RegExp(`^${prefix}docusaurus.*\.plugin.js$`); +const getCustomPluginRegExp = (prefix = "") => + new RegExp(`^${prefix}docusaurus.*\.plugin.js$`) -const DOCUSAURUS_DIR_CONTENTS = fs.readdirSync(STREAM_SDK_DOCUSAURUS_PATH); -const DOCS_DIR = fs.readdirSync(`${STREAM_SDK_DOCUSAURUS_PATH}/docs`); +const DOCUSAURUS_DIR_CONTENTS = fs.readdirSync(STREAM_SDK_DOCUSAURUS_PATH) +const DOCS_DIR = fs.readdirSync(`${STREAM_SDK_DOCUSAURUS_PATH}/docs`) -const PRODUCT = process.env.PRODUCT; -const label = PRODUCT === 'video' ? 'Video docs' : 'SDK'; +const PRODUCT = process.env.PRODUCT +const label = PRODUCT === "video" ? "Video docs" : "SDK" const { productTitle, docusaurus: { title: navbarTitle }, -} = productVariables[PRODUCT]; +} = productVariables[PRODUCT] -let SDK_FOLDERS = DOCS_DIR.filter((file) => { - if (PRODUCT === 'video') { +let SDK_FOLDERS = DOCS_DIR.filter(file => { + if (PRODUCT === "video") { if ( - process.env.DEPLOYMENT_ENV === 'production' && + process.env.DEPLOYMENT_ENV === "production" && ignoredVideoSDKsProduction.includes(file) ) { - return false; + return false } else if ( - process.env.DEPLOYMENT_ENV === 'staging' && + process.env.DEPLOYMENT_ENV === "staging" && ignoredVideoSDKsStaging.includes(file) ) { - return false; + return false } } return fs .lstatSync(`${STREAM_SDK_DOCUSAURUS_PATH}/docs/${file}`) - .isDirectory(); -}); + .isDirectory() +}) SDK_FOLDERS = SDK_FOLDERS.sort((a, b) => { - const aIndex = SDK_ORDER.indexOf(a.toLowerCase()) ?? 1000; - const bIndex = SDK_ORDER.indexOf(b.toLowerCase()) ?? 1000; - return aIndex - bIndex; -}); + const aIndex = SDK_ORDER.indexOf(a.toLowerCase()) ?? 1000 + const bIndex = SDK_ORDER.indexOf(b.toLowerCase()) ?? 1000 + return aIndex - bIndex +}) -const CUSTOM_PLUGIN_FILES = DOCUSAURUS_DIR_CONTENTS.filter((file) => +const CUSTOM_PLUGIN_FILES = DOCUSAURUS_DIR_CONTENTS.filter(file => getCustomPluginRegExp().test(file) -); +) -const CUSTOM_PLUGINS = CUSTOM_PLUGIN_FILES.map((file) => { - const sdkConfig = require(path.join(STREAM_SDK_DOCUSAURUS_PATH, file)); - return sdkConfig.plugins; -}).flat(); +const CUSTOM_PLUGINS = CUSTOM_PLUGIN_FILES.map(file => { + const sdkConfig = require(path.join(STREAM_SDK_DOCUSAURUS_PATH, file)) + return sdkConfig.plugins +}).flat() /** * Named to indicate that this is used with any plugin file @@ -87,59 +87,59 @@ const CUSTOM_PLUGINS = CUSTOM_PLUGIN_FILES.map((file) => { * `(${Object.keys(foldermapping).join('|')})-` * ``` * */ -const SDK_CUSTOM_PLUGINS = DOCUSAURUS_DIR_CONTENTS.filter((file) => - getCustomPluginRegExp('.*-').test(file) +const SDK_CUSTOM_PLUGINS = DOCUSAURUS_DIR_CONTENTS.filter(file => + getCustomPluginRegExp(".*-").test(file) ).reduce((files, file) => { - const pluginModule = require(path.join(STREAM_SDK_DOCUSAURUS_PATH, file)); - return { ...files, [file]: pluginModule.plugins }; -}, {}); + const pluginModule = require(path.join(STREAM_SDK_DOCUSAURUS_PATH, file)) + return { ...files, [file]: pluginModule.plugins } +}, {}) -const getCustomPluginFilesForSDK = (sdk) => +const getCustomPluginFilesForSDK = sdk => Object.keys(SDK_CUSTOM_PLUGINS) - .filter((file) => getCustomPluginRegExp(`${sdk}-`).test(file)) - .map((file) => SDK_CUSTOM_PLUGINS[file]); + .filter(file => getCustomPluginRegExp(`${sdk}-`).test(file)) + .map(file => SDK_CUSTOM_PLUGINS[file]) -const CUSTOM_CSS_PATH = path.join(__dirname, 'src/css/components'); +const CUSTOM_CSS_PATH = path.join(__dirname, "src/css/components") const CUSTOM_CSS_FILES = fs .readdirSync(CUSTOM_CSS_PATH) - .map((file) => `${CUSTOM_CSS_PATH}/${file}`); + .map(file => `${CUSTOM_CSS_PATH}/${file}`) -const pluginWithId = (pluginId) => (plugin) => plugin[0] === pluginId; -const fileWithPluginId = (pluginId) => (files) => - Array.from(files).find(pluginWithId(pluginId)); +const pluginWithId = pluginId => plugin => plugin[0] === pluginId +const fileWithPluginId = pluginId => files => + Array.from(files).find(pluginWithId(pluginId)) const getPluginFileForSDK = (sdk, pluginId) => - getCustomPluginFilesForSDK(sdk).find(fileWithPluginId(pluginId)) ?? []; + getCustomPluginFilesForSDK(sdk).find(fileWithPluginId(pluginId)) ?? [] const getCustomPluginForSDK = (sdk, pluginId) => - getPluginFileForSDK(sdk, pluginId).find(pluginWithId(pluginId)); + getPluginFileForSDK(sdk, pluginId).find(pluginWithId(pluginId)) -const defaultPlugins = SDK_FOLDERS.map((SDK) => { - const strippedSDK = SDK.toLowerCase().replace(' ', ''); +const defaultPlugins = SDK_FOLDERS.map(SDK => { + const strippedSDK = SDK.toLowerCase().replace(" ", "") const sidebarPathWithoutExtension = `${STREAM_SDK_DOCUSAURUS_PATH}/sidebars-${folderMapping[ strippedSDK ] .toLowerCase() - .replace(' ', '-')}`; + .replace(" ", "-")}` - const jsSidebarPath = `${sidebarPathWithoutExtension}.js`; - const jsonSidebarPath = `${sidebarPathWithoutExtension}.json`; + const jsSidebarPath = `${sidebarPathWithoutExtension}.js` + const jsonSidebarPath = `${sidebarPathWithoutExtension}.json` const sidebarPath = fs.existsSync(jsSidebarPath) ? jsSidebarPath - : jsonSidebarPath; + : jsonSidebarPath - const pluginId = '@docusaurus/plugin-content-docs'; + const pluginId = "@docusaurus/plugin-content-docs" const defaultConfiguration = { sidebarItemsGenerator: async function ({ defaultSidebarItemsGenerator, ...args }) { - const sidebarItems = await defaultSidebarItemsGenerator(args); - return sidebarItems.filter((item) => { - return !IGNORED_DIRECTORIES.includes(item.label); - }); + const sidebarItems = await defaultSidebarItemsGenerator(args) + return sidebarItems.filter(item => { + return !IGNORED_DIRECTORIES.includes(item.label) + }) }, id: strippedSDK, path: `${STREAM_SDK_DOCUSAURUS_PATH}/docs/${SDK}`, @@ -153,28 +153,28 @@ const defaultPlugins = SDK_FOLDERS.map((SDK) => { infima: true, customTypes: { note: { - ifmClass: 'note', + ifmClass: "note", svg: Icons.note, }, tip: { - ifmClass: 'tip', + ifmClass: "tip", svg: Icons.tip, }, info: { - ifmClass: 'info', + ifmClass: "info", svg: Icons.info, }, caution: { - ifmClass: 'warning', + ifmClass: "warning", svg: Icons.caution, }, danger: { - ifmClass: 'danger', + ifmClass: "danger", svg: Icons.danger, }, }, }, - }; + } /** * Merge configuration from a custom plugin file if one exists @@ -187,83 +187,83 @@ const defaultPlugins = SDK_FOLDERS.map((SDK) => { * and since docusaurus validates the plugins during a build, * we don't do any extra validation here for this. * */ - const customPlugin = getCustomPluginForSDK(strippedSDK, pluginId); - const customConfiguration = customPlugin ? customPlugin[1] : {}; + const customPlugin = getCustomPluginForSDK(strippedSDK, pluginId) + const customConfiguration = customPlugin ? customPlugin[1] : {} - return [pluginId, { ...defaultConfiguration, ...customConfiguration }]; -}); + return [pluginId, { ...defaultConfiguration, ...customConfiguration }] +}) -const navbarSDKItems = SDK_FOLDERS.map((SDK) => { - const strippedSDK = SDK.toLowerCase().replace(' ', ''); - const readableSDK = folderMapping[strippedSDK] || SDK; +const navbarSDKItems = SDK_FOLDERS.map(SDK => { + const strippedSDK = SDK.toLowerCase().replace(" ", "") + const readableSDK = folderMapping[strippedSDK] || SDK return { label: readableSDK, id: strippedSDK, docsPluginId: strippedSDK, - docId: 'none', + docId: "none", to: `${strippedSDK}/`, - type: 'doc', - }; -}); + type: "doc", + } +}) // We have one section in the dropdown, which says 'SDK'. -if (process.env.PRODUCT === 'video') { +if (process.env.PRODUCT === "video") { navbarSDKItems.splice(0, 0, { - label: 'SDKs', - className: 'navbar__break', - href: '#', - }); + label: "SDKs", + className: "navbar__break", + href: "#", + }) } -const navbarVersionItems = SDK_FOLDERS.map((SDK) => ({ - docsPluginId: SDK.toLowerCase().replace(' ', ''), - type: 'docsVersionDropdown', - className: 'navbar__link__custom-dropdown--version', -})); +const navbarVersionItems = SDK_FOLDERS.map(SDK => ({ + docsPluginId: SDK.toLowerCase().replace(" ", ""), + type: "docsVersionDropdown", + className: "navbar__link__custom-dropdown--version", +})) const navbarGithubItem = { - label: 'github', + label: "github", href: URLS.github_root, - position: 'left', - className: 'navbar__link__github', - 'aria-label': 'Github repository', + position: "left", + className: "navbar__link__github", + "aria-label": "Github repository", mobile: false, -}; +} const navbarItems = [ { - type: 'search', - position: 'right', + type: "search", + position: "right", }, { href: URLS.website.signup, - label: 'Sign Up', - position: 'right', - className: 'navbar__link__sign-up', + label: "Sign Up", + position: "right", + className: "navbar__link__sign-up", mobile: false, }, ...navbarVersionItems, navbarGithubItem, -]; +] if (navbarSDKItems.length > 1) { navbarItems.unshift({ items: navbarSDKItems, label, - className: 'navbar__link__custom-dropdown--sdks', - position: 'right', - }); + className: "navbar__link__custom-dropdown--sdks", + position: "right", + }) } -const plugins = [...defaultPlugins, ...CUSTOM_PLUGINS]; +const plugins = [...defaultPlugins, ...CUSTOM_PLUGINS] -if (process.env.DEPLOYMENT_ENV === 'production') { +if (process.env.DEPLOYMENT_ENV === "production") { plugins.push([ - '@docusaurus/plugin-google-gtag', + "@docusaurus/plugin-google-gtag", { - trackingID: process.env.GOOGLE_TAG_TRACKING_ID || 'DEFAULT', + trackingID: process.env.GOOGLE_TAG_TRACKING_ID || "DEFAULT", }, - ]); + ]) } /** @@ -271,29 +271,29 @@ if (process.env.DEPLOYMENT_ENV === 'production') { */ if (process.env.SOURCE_HOMEPAGE) { plugins.push([ - '@docusaurus/plugin-content-pages', + "@docusaurus/plugin-content-pages", { - path: path.join(STREAM_SDK_DOCUSAURUS_PATH, 'pages'), + path: path.join(STREAM_SDK_DOCUSAURUS_PATH, "pages"), }, - ]); + ]) } else { - plugins.push('@docusaurus/plugin-content-pages'); + plugins.push("@docusaurus/plugin-content-pages") } plugins.push( - 'docusaurus-plugin-sass', - path.resolve(__dirname, 'src/symlink-docusaurus'), - path.resolve(__dirname, 'src/define-env-vars-plugin'), - path.resolve(__dirname, 'src/build-algolia-objects') -); + "docusaurus-plugin-sass", + path.resolve(__dirname, "src/symlink-docusaurus"), + path.resolve(__dirname, "src/define-env-vars-plugin"), + path.resolve(__dirname, "src/build-algolia-objects") +) module.exports = { baseUrl: URLS.docs.root, trailingSlash: true, - favicon: 'https://getstream.imgix.net/images/favicons/favicon-96x96.png', - onBrokenLinks: 'warn', - onBrokenMarkdownLinks: 'warn', - organizationName: 'GetStream', + favicon: "https://getstream.imgix.net/images/favicons/favicon-96x96.png", + onBrokenLinks: "warn", + onBrokenMarkdownLinks: "warn", + organizationName: "GetStream", plugins, projectName: `stream-${PRODUCT}`, tagline: `Stream ${productTitle} Component SDKs`, @@ -301,40 +301,40 @@ module.exports = { // Docusaurus forces us to pass these values even if they are not internally used. // Theyre only used to show/hide the search bar in our case. algolia: { - appId: 'MOCK', - apiKey: 'MOCK', - indexName: 'MOCK', + appId: "MOCK", + apiKey: "MOCK", + indexName: "MOCK", }, colorMode: { disableSwitch: true, }, liveCodeBlock: { - playgroundPosition: 'bottom', + playgroundPosition: "bottom", }, navbar: { items: navbarItems, logo: { - alt: 'Stream docs logo', - src: 'img/logo.svg', + alt: "Stream docs logo", + src: "img/logo.svg", }, title: navbarTitle, }, - metadata: [{ name: 'twitter:card', content: 'summary_large_image' }], + metadata: [{ name: "twitter:card", content: "summary_large_image" }], hideableSidebar: true, }, themes: [ [ - '@docusaurus/theme-classic', + "@docusaurus/theme-classic", { customCss: [ - require.resolve('./src/css/custom.scss'), + require.resolve("./src/css/custom.scss"), ...CUSTOM_CSS_FILES, ], }, ], - '@docusaurus/theme-live-codeblock', - '@docusaurus/theme-search-algolia', + "@docusaurus/theme-live-codeblock", + "@docusaurus/theme-search-algolia", ], title: `Stream ${productTitle} - Component SDK Docs`, url: URLS.website.root, -}; +} diff --git a/package.json b/package.json index a61fe71..847e034 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,11 @@ "start": "docusaurus start --poll --host 0.0.0.0", "swizzle": "docusaurus swizzle", "write-translations": "docusaurus write-translations", - "write-heading-ids": "docusaurus write-heading-ids" + "write-heading-ids": "docusaurus write-heading-ids", + "prettier": "prettier --config .prettierrc --write \"**/*.{js,ts}\"", + "prettier:diff": "prettier --config .prettierrc --list-different \"**/*.{js,ts}\"", + "prettier-docs": "prettier --config .prettierrc --write \"**/*.md\"", + "postinstall": "husky install" }, "dependencies": { "@docusaurus/core": "^2.0.0-beta.14", @@ -57,8 +61,12 @@ "viz.js": "1.8.0" }, "devDependencies": { + "@trivago/prettier-plugin-sort-imports": "^4.1.1", "cheerio": "1.0.0-rc.9", - "node-fetch": "2.6.1" + "husky": "^8.0.3", + "node-fetch": "2.6.1", + "prettier": "^2.8.8", + "pretty-quick": "^3.1.3" }, "browserslist": { "production": [ diff --git a/replace-algolia-objects.js b/replace-algolia-objects.js index 7180b97..750d8c1 100644 --- a/replace-algolia-objects.js +++ b/replace-algolia-objects.js @@ -1,44 +1,44 @@ -const dotenv = require('dotenv'); -const path = require('path'); -const fs = require('fs'); -const algoliasearch = require('algoliasearch/lite'); +const dotenv = require("dotenv") +const path = require("path") +const fs = require("fs") +const algoliasearch = require("algoliasearch/lite") const json = require(path.join( process.env.CURRENT_WORKING_PATH, - 'algolia-objects.json' -)); + "algolia-objects.json" +)) -require('dotenv').config({ - path: path.join(process.env.CURRENT_WORKING_PATH, 'docusaurus', '.env'), -}); +require("dotenv").config({ + path: path.join(process.env.CURRENT_WORKING_PATH, "docusaurus", ".env"), +}) if (!process.env.PRODUCT) { - process.env.PRODUCT = 'chat'; + process.env.PRODUCT = "chat" } const DOCUSAURUS_INDEX = - process.env.PRODUCT === 'chat' - ? process.env.DEPLOYMENT_ENV === 'production' - ? 'DOCUSAURUS' - : 'DOCUSAURUS_STG' - : process.env.PRODUCT === 'video' - ? process.env.DEPLOYMENT_ENV === 'production' - ? 'DOCUSAURUS_VIDEO' - : 'DOCUSAURUS_VIDEO_STG' - : 'NEVER'; + process.env.PRODUCT === "chat" + ? process.env.DEPLOYMENT_ENV === "production" + ? "DOCUSAURUS" + : "DOCUSAURUS_STG" + : process.env.PRODUCT === "video" + ? process.env.DEPLOYMENT_ENV === "production" + ? "DOCUSAURUS_VIDEO" + : "DOCUSAURUS_VIDEO_STG" + : "NEVER" const client = algoliasearch( process.env.ALGOLIA_APP_ID, process.env.ALGOLIA_API_WRITE_KEY -); +) -const index = client.initIndex(DOCUSAURUS_INDEX); +const index = client.initIndex(DOCUSAURUS_INDEX) index .replaceAllObjects(json) .then(({ objectIDs }) => { - console.log(`Updated ${DOCUSAURUS_INDEX} Algolia index for: `, objectIDs); + console.log(`Updated ${DOCUSAURUS_INDEX} Algolia index for: `, objectIDs) + }) + .catch(error => { + console.error(`Error while replacing object with Algolia: ${error}`) + process.exit(1) }) - .catch((error) => { - console.error(`Error while replacing object with Algolia: ${error}`); - process.exit(1); - }); diff --git a/shared/_example-shared-content.md b/shared/_example-shared-content.md index 575f850..c6154b7 100644 --- a/shared/_example-shared-content.md +++ b/shared/_example-shared-content.md @@ -5,7 +5,7 @@ some content here. To embed this content in your SDK docs, use this syntax: ```mdx -import SharedContent from '../../../shared/_example-shared-content.md'; +import SharedContent from "../../../shared/_example-shared-content.md" ``` diff --git a/src/api.js b/src/api.js index a9ac4d5..f642732 100644 --- a/src/api.js +++ b/src/api.js @@ -1,52 +1,52 @@ -import { WEBSITE_BASE_URL } from './environment'; +import { WEBSITE_BASE_URL } from "./environment" function getCSRFToken() { - const matches = document.cookie.match(new RegExp('csrftoken=([^;]+)', 'i')); - return matches ? matches[1] : ''; + const matches = document.cookie.match(new RegExp("csrftoken=([^;]+)", "i")) + return matches ? matches[1] : "" } const fetchApi = async (method, path, body) => { const response = await fetch(`${WEBSITE_BASE_URL}/${path}/`, { method, body, - credentials: 'include', - headers: { 'x-csrftoken': getCSRFToken() }, - }); + credentials: "include", + headers: { "x-csrftoken": getCSRFToken() }, + }) - let data; + let data if (response.status !== 204) { try { - data = await response.json(); + data = await response.json() } catch (err) { - console.error(response, err); + console.error(response, err) } } - if (response.ok) return data; + if (response.ok) return data const err = new Error( `Request failed with status ${response.status}: ${response.statusText}` - ); - err.data = data; - err.status = response.status; - err.response = response; - throw err; -}; - -export const getAPIErrorMsg = (error) => { + ) + err.data = data + err.status = response.status + err.response = response + throw err +} + +export const getAPIErrorMsg = error => { if (error && error.data) { - return error.data; + return error.data } return { - detail: 'Something went wrong. Please try again or contact support!', - }; -}; + detail: "Something went wrong. Please try again or contact support!", + } +} -export const apiDocFeedback = (data) => { - return fetchApi('POST', 'api/docs_cms/feedback', data); -}; +export const apiDocFeedback = data => { + return fetchApi("POST", "api/docs_cms/feedback", data) +} -export const apiGetUser = () => fetchApi('GET', 'api/accounts/user'); +export const apiGetUser = () => fetchApi("GET", "api/accounts/user") export const apiGetPublicUserToken = () => - fetchApi('GET', 'api/core/chat_docs_credentials'); // activity feeds credentials ??? + fetchApi("GET", "api/core/chat_docs_credentials") // activity feeds credentials ??? diff --git a/src/build-algolia-objects.js b/src/build-algolia-objects.js index 6f00375..c735078 100644 --- a/src/build-algolia-objects.js +++ b/src/build-algolia-objects.js @@ -1,14 +1,14 @@ -const fs = require('fs'); -const mdx = require('@mdx-js/mdx'); -const admonitions = require('remark-admonitions'); +const fs = require("fs") +const mdx = require("@mdx-js/mdx") +const admonitions = require("remark-admonitions") const { parseFrontMatter, parseMarkdownContentTitle, parseMarkdownHeadingId, -} = require('@docusaurus/utils'); -const slugs = require('github-slugger')(); -const { platformMapping, IGNORED_DIRECTORIES } = require('../constants'); -const productVariables = require('./product-variables'); +} = require("@docusaurus/utils") +const slugs = require("github-slugger")() +const { platformMapping, IGNORED_DIRECTORIES } = require("../constants") +const productVariables = require("./product-variables") const { algolia: { @@ -18,54 +18,54 @@ const { id: parent_section_id, }, }, -} = productVariables[process.env.PRODUCT]; +} = productVariables[process.env.PRODUCT] -const extractSyntaxTree = (path) => { +const extractSyntaxTree = path => { // This function takes care of transforming the .md/.mdx file into an // array of nodes which contains the type and data about that node // in the markdown file. Also, it categorizes everything so we can // later remove the js/react code used on .mdx files // Note: It wont remove code samples, only actual code used to // render react components inside the markdown - return new Promise((res) => { - var doc = fs.readFileSync(path, 'utf8'); + return new Promise(res => { + var doc = fs.readFileSync(path, "utf8") - const { content: contentWithTitle, frontMatter } = parseFrontMatter(doc); + const { content: contentWithTitle, frontMatter } = parseFrontMatter(doc) if (frontMatter.hide_from_search) { - return res(null); + return res(null) } - const { content } = parseMarkdownContentTitle(contentWithTitle); + const { content } = parseMarkdownContentTitle(contentWithTitle) mdx.sync(content, { skipExport: true, remarkPlugins: [ admonitions, - () => (ast) => { - res(ast); - return ast; + () => ast => { + res(ast) + return ast }, ], - }); - }); -}; + }) + }) +} const mergeChildTree = (curr, childrenItem) => { - Object.values(childrenItem).forEach((childrenData) => { + Object.values(childrenItem).forEach(childrenData => { if (!curr[childrenData.headerId]) { curr[childrenData.headerId] = { headerId: childrenData.headerId, text: [], code: [], - }; + } } - curr[childrenData.headerId].text.push(childrenData.text.join(' ')); - curr[childrenData.headerId].code.push(...childrenData.code); - }); + curr[childrenData.headerId].text.push(childrenData.text.join(" ")) + curr[childrenData.headerId].code.push(...childrenData.code) + }) - return curr; -}; + return curr +} const parseMdxData = ( path, @@ -74,19 +74,19 @@ const parseMdxData = ( lastHeaderIdParam, mdxImportedComponentsParam ) => { - let lastHeaderId = undefined; - let mdxImportedComponents = mdxImportedComponentsParam || {}; - const initialReduceValue = {}; + let lastHeaderId = undefined + let mdxImportedComponents = mdxImportedComponentsParam || {} + const initialReduceValue = {} // When calling this function recursively we will receive the // "lastHeaderIdParam" param and it means we need to // pre-initialize things if (lastHeaderIdParam) { - lastHeaderId = lastHeaderIdParam; + lastHeaderId = lastHeaderIdParam initialReduceValue[lastHeaderId] = { headerId: lastHeaderId, text: [], code: [], - }; + } } // This reduce functions basically iterate through the markdown @@ -94,46 +94,46 @@ const parseMdxData = ( // by header id. This will allow us to later have search results // that leads us to specific page headers in the docs return syntaxTree.children.reduce(async (currP, item) => { - let curr = await currP; + let curr = await currP // If import, we get every mdx imported component and save it on a map - if (item.type === 'import') { - const imports = item.value.split('\n').filter((item) => { - const extension = item.split('.').pop(); - return extension.includes('mdx'); - }); + if (item.type === "import") { + const imports = item.value.split("\n").filter(item => { + const extension = item.split(".").pop() + return extension.includes("mdx") + }) // [import Component from path] should become {[Component]: path} // This is safe because mdx imports have to use default - imports.forEach((item) => { - const [, importComponent, _, path] = item.split(' '); + imports.forEach(item => { + const [, importComponent, _, path] = item.split(" ") mdxImportedComponents = { ...mdxImportedComponents, - [importComponent]: path.replace(/('|;|")/gi, ''), - }; - }); + [importComponent]: path.replace(/('|;|")/gi, ""), + } + }) - return curr; + return curr } // If heading, we initialize the heading object and set it // as lastHeaderId so next items in the tree can use it as // key - if (item.type === 'heading') { + if (item.type === "heading") { if ( curr[lastHeaderId] && curr[lastHeaderId].text.length === 0 && curr[lastHeaderId].code.length === 0 ) { // cleanup empty items from last iteration - delete curr[lastHeaderId]; + delete curr[lastHeaderId] } // Support explicit heading IDs - const heading = toString(item); - const parsedHeading = parseMarkdownHeadingId(heading); + const heading = toString(item) + const parsedHeading = parseMarkdownHeadingId(heading) - lastHeaderId = parsedHeading.id || slugs.slug(heading); - curr[lastHeaderId] = { headerId: lastHeaderId, text: [], code: [] }; + lastHeaderId = parsedHeading.id || slugs.slug(heading) + curr[lastHeaderId] = { headerId: lastHeaderId, text: [], code: [] } } // If there is no heading id yet, it means that this page has some description @@ -144,21 +144,21 @@ const parseMdxData = ( path, toString, { children: [item] }, - 'page', + "page", mdxImportedComponents - ); + ) if (!curr.page) { curr.page = { text: [], code: [], - }; + } } - curr.page.text.push(...pageItem.page.text); - curr.page.code.push(...pageItem.page.code); + curr.page.text.push(...pageItem.page.text) + curr.page.code.push(...pageItem.page.code) - return curr; + return curr } // Nodes with children should run recursively because if we just call @@ -171,32 +171,32 @@ const parseMdxData = ( item, lastHeaderId, mdxImportedComponents - ); + ) - return mergeChildTree(curr, childrenItem); + return mergeChildTree(curr, childrenItem) } // If type is jsx, it can two things: It is some component being used // or some html tags wrapping text. If its a component, we check if its // a mdx component and if so, we extract its syntax tree recursively. // Any other kind of jsx tag is removed, only leaving its content as text - if (item.type === 'jsx') { + if (item.type === "jsx") { const usedImportedComponents = Object.keys(mdxImportedComponents).filter( - (component) => new RegExp(`(<${component}([^>]+)>)`).test(item.value) - ); + component => new RegExp(`(<${component}([^>]+)>)`).test(item.value) + ) if (usedImportedComponents.length > 0) { // If this node is using an imported mdx component, then we go through all used // components and parse it as mdx in order to extract its data for the search await Promise.all( - usedImportedComponents.map(async (usedImportedComponent) => { - const pathWithoutFileName = path.includes('.md') - ? path.substring(0, path.lastIndexOf('/')) - : path; - const componentPath = `${pathWithoutFileName}/${mdxImportedComponents[usedImportedComponent]}`; + usedImportedComponents.map(async usedImportedComponent => { + const pathWithoutFileName = path.includes(".md") + ? path.substring(0, path.lastIndexOf("/")) + : path + const componentPath = `${pathWithoutFileName}/${mdxImportedComponents[usedImportedComponent]}` const importedComponentSyntaxTree = await extractSyntaxTree( componentPath - ); + ) if (importedComponentSyntaxTree) { const importedComponentData = await parseMdxData( componentPath, @@ -204,119 +204,119 @@ const parseMdxData = ( importedComponentSyntaxTree, lastHeaderId, mdxImportedComponents - ); - curr = mergeChildTree(curr, importedComponentData); + ) + curr = mergeChildTree(curr, importedComponentData) } }) - ); + ) - return curr; + return curr } // Any other kind of jsx tag is removed, only leaving its content as text - const jsxString = toString(item).replace(/(<([^>]+)>)/gi, ''); + const jsxString = toString(item).replace(/(<([^>]+)>)/gi, "") // Cleanup empty strings and solo line breaks after tags removal - if (jsxString !== '\n' && jsxString !== '') { - curr[lastHeaderId].text.push(jsxString); + if (jsxString !== "\n" && jsxString !== "") { + curr[lastHeaderId].text.push(jsxString) } - return curr; + return curr } // If code, we just push its content - if (item.type === 'code') { - curr[lastHeaderId].code.push(toString(item)); - return curr; + if (item.type === "code") { + curr[lastHeaderId].code.push(toString(item)) + return curr } // These tags tags should be ignored if ( - item.type === 'import' && - item.type === 'image' && - item.type === 'comment' && - item.type === 'thematicBreak' + item.type === "import" && + item.type === "image" && + item.type === "comment" && + item.type === "thematicBreak" ) { - return curr; + return curr } // Any other tag should be parsed to string - curr[lastHeaderId].text.push(toString(item)); + curr[lastHeaderId].text.push(toString(item)) - return curr; - }, Promise.resolve(initialReduceValue)); -}; + return curr + }, Promise.resolve(initialReduceValue)) +} -const extractMdxData = async (path) => { +const extractMdxData = async path => { return (async () => { - const { toString } = await import('mdast-util-to-string'); - const syntaxTree = await extractSyntaxTree(path); + const { toString } = await import("mdast-util-to-string") + const syntaxTree = await extractSyntaxTree(path) if (syntaxTree) { - const splitDirPath = path.split('/'); + const splitDirPath = path.split("/") // pops filename from path - splitDirPath.pop(); + splitDirPath.pop() let { page, ...headers } = await parseMdxData( - splitDirPath.join('/'), + splitDirPath.join("/"), toString, syntaxTree - ); + ) - const headersArr = Object.values(headers); + const headersArr = Object.values(headers) // If there is no page, it means that the mdx file has a custom h1 header // which should represent the page info and it will be used as page. if (!page) { - page = headersArr.shift(); + page = headersArr.shift() } - return { page, headers: headersArr }; + return { page, headers: headersArr } } - })(); -}; + })() +} -const capitalizeFirstLetter = (string) => { - return string.charAt(0).toUpperCase() + string.slice(1); -}; +const capitalizeFirstLetter = string => { + return string.charAt(0).toUpperCase() + string.slice(1) +} -const extractDocsData = async (docsContent) => { - const sdksContent = Object.entries(docsContent); +const extractDocsData = async docsContent => { + const sdksContent = Object.entries(docsContent) // Basically we navigate through the content object utill we get to the // doc objects which contain the information about a doc page const docs = sdksContent.map(([sdkKey, sdkContent], platformIndex) => { return sdkContent.loadedVersions.map((sdkContentVersion, versionIndex) => { return sdkContentVersion.docs - .filter((sdkDocVersion) => { + .filter(sdkDocVersion => { // Filters ignored directories - return !IGNORED_DIRECTORIES.find((ignoredDir) => + return !IGNORED_DIRECTORIES.find(ignoredDir => sdkDocVersion.sourceDirName.includes(ignoredDir) - ); + ) }) .map(async (sdkDocVersion, pageIndex) => { const [_, ...reversedSections] = sdkDocVersion.unversionedId - .split('/') - .reverse(); - const sections = reversedSections.reverse(); - const sectionsSlug = sections.join('/'); + .split("/") + .reverse() + const sections = reversedSections.reverse() + const sectionsSlug = sections.join("/") // Once we dont have the header data/page content on the object generated by // docusaurus, we need to extract it manually from the md/mdx file const pageMdxData = await extractMdxData( - sdkDocVersion.source.replace('@site/', '') - ); + sdkDocVersion.source.replace("@site/", "") + ) // Pages without mdx data (most likely pages with hidden: true) should be ignored. if (!pageMdxData) { - return null; + return null } - const { page: pageData, headers: pageHeadersData } = pageMdxData; + const { page: pageData, headers: pageHeadersData } = pageMdxData - const version = sdkDocVersion.version; + const version = sdkDocVersion.version const page_id = parseInt( `${platformIndex}${versionIndex}${pageIndex}` - ); - const name = sdkDocVersion.title; + ) + const name = sdkDocVersion.title // Last version urls actually have no versions // We use the label here instead of the name because the // url is based on the lab ex: current version has the next label @@ -325,21 +325,21 @@ const extractDocsData = async (docsContent) => { ? sdkDocVersion.slug.substring(1) : `${sdkContentVersion.versionLabel.toLowerCase()}/${sdkDocVersion.slug.substring( 1 - )}`; + )}` const section_name = sections - .map((section_slug) => capitalizeFirstLetter(section_slug)) - .join(' > '); - const section_slug = sectionsSlug; - const section_id = sectionsSlug; - const platform = platformMapping[sdkKey]; - const content_serialized_text = pageData && pageData.text.join('\n'); - const code_sample = pageData && pageData.code.join('\n'); - const pageObjectID = `${platformMapping[sdkKey]}-${sdkDocVersion.version}-${pageIndex}-`; + .map(section_slug => capitalizeFirstLetter(section_slug)) + .join(" > ") + const section_slug = sectionsSlug + const section_id = sectionsSlug + const platform = platformMapping[sdkKey] + const content_serialized_text = pageData && pageData.text.join("\n") + const code_sample = pageData && pageData.code.join("\n") + const pageObjectID = `${platformMapping[sdkKey]}-${sdkDocVersion.version}-${pageIndex}-` const pageObject = { version, page_id, - header_id: '', + header_id: "", name, slug, section_name, @@ -352,10 +352,10 @@ const extractDocsData = async (docsContent) => { content_serialized_text, code_sample, objectID: pageObjectID, - }; + } return [ pageObject, - ...pageHeadersData.map((headerData) => { + ...pageHeadersData.map(headerData => { return { version, page_id, @@ -369,55 +369,55 @@ const extractDocsData = async (docsContent) => { parent_section_slug, parent_section_id, platform, - content_serialized_text: headerData.text.join('\n'), - code_sample: headerData.code.join('\n'), + content_serialized_text: headerData.text.join("\n"), + code_sample: headerData.code.join("\n"), objectID: `${pageObjectID}${headerData.headerId}`, - }; + } }), - ]; - }); - }); - }); + ] + }) + }) + }) - const resolvedDocs = await Promise.all(docs.flat(Infinity)); + const resolvedDocs = await Promise.all(docs.flat(Infinity)) // Filtering pages without mdx data - return resolvedDocs.flat(Infinity).filter((item) => !!item); -}; + return resolvedDocs.flat(Infinity).filter(item => !!item) +} module.exports = () => { - let allContent = null; + let allContent = null return { - name: 'algolia-index', + name: "algolia-index", async contentLoaded({ allContent: loadedContent }) { // This is only available on contentLoad event but // this event its called multiple times during the build // phase, so we store the value in this variable and use it // in the post build script which is called only once - if (process.env.NODE_ENV === 'production') { - allContent = loadedContent; + if (process.env.NODE_ENV === "production") { + allContent = loadedContent } }, async postBuild() { - if (process.env.NODE_ENV === 'production') { - const docsContent = allContent['docusaurus-plugin-content-docs']; - const docsData = await extractDocsData(docsContent); + if (process.env.NODE_ENV === "production") { + const docsContent = allContent["docusaurus-plugin-content-docs"] + const docsData = await extractDocsData(docsContent) return new Promise((res, rej) => { fs.writeFile( - './algolia-objects.json', + "./algolia-objects.json", JSON.stringify(docsData), - (err) => { + err => { if (err) { - throw rej(err); + throw rej(err) } console.log( - 'algolia json data generated for: ', - docsData.map((doc) => doc.objectID) - ); - res(); + "algolia json data generated for: ", + docsData.map(doc => doc.objectID) + ) + res() } - ); - }); + ) + }) } }, - }; -}; + } +} diff --git a/src/components/FeedbackForm/index.js b/src/components/FeedbackForm/index.js index d494a9e..103adeb 100644 --- a/src/components/FeedbackForm/index.js +++ b/src/components/FeedbackForm/index.js @@ -1,33 +1,32 @@ -import React, { useMemo } from 'react'; +import React, { useMemo } from "react" -import { LoadingSpinner } from '../LoadingSpinner'; -import { InputField } from '../InputField'; -import { useFeedbackForm } from '../../hooks/useFeedbackForm'; -import { useFeedbackFormData } from '../../hooks/useFeedbackFormData'; -import { useToast } from '../../hooks/useToast'; - -import './styles.scss'; +import { useFeedbackForm } from "../../hooks/useFeedbackForm" +import { useFeedbackFormData } from "../../hooks/useFeedbackFormData" +import { useToast } from "../../hooks/useToast" +import { InputField } from "../InputField" +import { LoadingSpinner } from "../LoadingSpinner" +import "./styles.scss" export const FeedbackForm = () => { - const { header, setHeader, headers } = useFeedbackFormData(); + const { header, setHeader, headers } = useFeedbackFormData() const sections = useMemo(() => { return headers.map(({ value }) => ({ label: value, value, - })); - }, [headers]); + })) + }, [headers]) const { submitHandler, loading, success, error, data, fieldChangeHandler } = useFeedbackForm( - { email: '', feedback: '' }, - header.isPageHeader && header.value.replace(/\s+/g, '-').toLowerCase() - ); + { email: "", feedback: "" }, + header.isPageHeader && header.value.replace(/\s+/g, "-").toLowerCase() + ) useToast( error && error.detail, - success ? 'Thanks for helping us to get better!' : '', - 'feedback-form' - ); + success ? "Thanks for helping us to get better!" : "", + "feedback-form" + ) return (
@@ -47,10 +46,12 @@ export const FeedbackForm = () => { className="input" name="sections" value={header.value} - onChange={(a) => setHeader(a.target.value)} + onChange={a => setHeader(a.target.value)} > - - {sections.map((sectionItem) => ( + + {sections.map(sectionItem => ( @@ -66,9 +67,9 @@ export const FeedbackForm = () => { required />
- ); -}; + ) +} diff --git a/src/components/FeedbackFormButton/index.js b/src/components/FeedbackFormButton/index.js index 7effd10..3456b9d 100644 --- a/src/components/FeedbackFormButton/index.js +++ b/src/components/FeedbackFormButton/index.js @@ -1,16 +1,14 @@ -import React from 'react'; +import React from "react" -import { useFeedbackFormData } from '../../hooks/useFeedbackFormData'; - -import ConfusedIcon from './confused-icon.svg'; - -import './styles.scss'; +import { useFeedbackFormData } from "../../hooks/useFeedbackFormData" +import ConfusedIcon from "./confused-icon.svg" +import "./styles.scss" export const FeedbackFormButton = ({ lastHeaderTitle }) => { - const { goToFeedbackForm } = useFeedbackFormData(lastHeaderTitle); + const { goToFeedbackForm } = useFeedbackFormData(lastHeaderTitle) return ( -
+
- ); -}; + ) +} diff --git a/src/components/ImageShowcase/index.js b/src/components/ImageShowcase/index.js index ab90371..1fa46e9 100644 --- a/src/components/ImageShowcase/index.js +++ b/src/components/ImageShowcase/index.js @@ -1,6 +1,8 @@ -import React from 'react'; -import clsx from 'clsx'; -import styles from './styles.scss'; +import React from "react" + +import clsx from "clsx" + +import styles from "./styles.scss" /** * Component for showing more than one image in a responsive flex container (with optional captions) @@ -11,17 +13,21 @@ import styles from './styles.scss'; * @param {boolean} border */ const ImageShowcase = ({ items, border }) => ( -
-
+
+
{items.map(({ image, alt, caption }, key) => (
- {alt} - { caption && (
{caption}
) } + {alt} + {caption &&
{caption}
}
))}
-); - -export default ImageShowcase; +) +export default ImageShowcase diff --git a/src/components/InputField/index.js b/src/components/InputField/index.js index b33131e..9217b43 100644 --- a/src/components/InputField/index.js +++ b/src/components/InputField/index.js @@ -1,13 +1,14 @@ -import React, { forwardRef } from 'react'; -import clsx from 'clsx'; +import React, { forwardRef } from "react" -import './styles.scss'; +import clsx from "clsx" + +import "./styles.scss" const InputFieldComponent = ( { id, name, - type = 'text', + type = "text", value, placeholder, label, @@ -29,7 +30,7 @@ const InputFieldComponent = ( placeholder={placeholder} type={type} required={required} - className={clsx('input', error && 'inputField-error')} + className={clsx("input", error && "inputField-error")} onChange={onChange} ref={ref} autoFocus={autoFocus} @@ -44,7 +45,7 @@ const InputFieldComponent = ( {error && {error}} {help && !error && {help}}
- ); -}; + ) +} -export const InputField = forwardRef(InputFieldComponent); +export const InputField = forwardRef(InputFieldComponent) diff --git a/src/components/LoadingSpinner/index.js b/src/components/LoadingSpinner/index.js index bf6f287..58af68e 100644 --- a/src/components/LoadingSpinner/index.js +++ b/src/components/LoadingSpinner/index.js @@ -1,11 +1,12 @@ -import React from 'react'; -import PropTypes from 'prop-types'; +import React from "react" -import './styles.scss'; +import PropTypes from "prop-types" + +import "./styles.scss" export const LoadingSpinner = ({ - className = '', - color = 'white', + className = "", + color = "white", size = 36, }) => { return ( @@ -13,11 +14,11 @@ export const LoadingSpinner = ({ className={`spinner ${color} ${className}`} style={{ width: size, height: size }} /> - ); -}; + ) +} LoadingSpinner.propTypes = { className: PropTypes.string, size: PropTypes.number, - color: PropTypes.oneOf(['white', 'blue']), -}; + color: PropTypes.oneOf(["white", "blue"]), +} diff --git a/src/contexts/AuthContext.js b/src/contexts/AuthContext.js index 733c83e..4b00ecb 100644 --- a/src/contexts/AuthContext.js +++ b/src/contexts/AuthContext.js @@ -1,80 +1,81 @@ -import React, { useState, useEffect, useCallback, useMemo } from 'react'; -import { apiGetUser, apiGetPublicUserToken } from '../api'; +import React, { useCallback, useEffect, useMemo, useState } from "react" -const isBrowser = typeof window !== `undefined`; +import { apiGetPublicUserToken, apiGetUser } from "../api" + +const isBrowser = typeof window !== `undefined` export const setUser = (user = {}) => { - if (!isBrowser) return; - window.localStorage.setItem('stream_user', JSON.stringify(user)); -}; + if (!isBrowser) return + window.localStorage.setItem("stream_user", JSON.stringify(user)) +} const getUser = () => { - if (!isBrowser) return {}; - return JSON.parse(window.localStorage.getItem('stream_user') || '{}'); -}; + if (!isBrowser) return {} + return JSON.parse(window.localStorage.getItem("stream_user") || "{}") +} -export const AuthContext = React.createContext({ email: '', username: '' }); +export const AuthContext = React.createContext({ email: "", username: "" }) // TODO: rename this to User Context export const AuthContextProvider = ({ children }) => { - const [state, setState] = useState(getUser()); - const [publicAppToken, setPublicAppToken] = useState(); + const [state, setState] = useState(getUser()) + const [publicAppToken, setPublicAppToken] = useState() - const isLoggedIn = !!state.email; + const isLoggedIn = !!state.email const setLogin = useCallback((user = {}) => { - setUser({ ...user, organizations: undefined }); - setState((prevState) => ({ ...prevState, ...user })); - }, []); + setUser({ ...user, organizations: undefined }) + setState(prevState => ({ ...prevState, ...user })) + }, []) const getUserData = useCallback(async () => { - const user = await apiGetUser(); - setLogin(user); - return user; - }, [setLogin]); + const user = await apiGetUser() + setLogin(user) + return user + }, [setLogin]) useEffect(() => { - if (typeof window === 'undefined') return; // Skip async for SSR + if (typeof window === "undefined") return // Skip async for SSR if (isLoggedIn) { - getUserData(); + getUserData() } apiGetPublicUserToken() - .then((data) => { + .then(data => { if (data) { setPublicAppToken({ ...data, - user_name: data && data.user_id.split('-')[0], - }); + user_name: data && data.user_id.split("-")[0], + }) } }) - .catch((e) => { - throw e; - }); - }, [isLoggedIn]); // eslint-disable-line react-hooks/exhaustive-deps + .catch(e => { + throw e + }) + }, [isLoggedIn]) // eslint-disable-line react-hooks/exhaustive-deps const getSelectedOrg = useCallback( (firstOrg = false) => { - if (!isLoggedIn) return null; - const orgs = state.organizations || []; - if (firstOrg) return orgs[orgs.length - 1]; // last org in the array is the first create org - return orgs.find((o) => o.is_selected) || orgs[0]; + if (!isLoggedIn) return null + const orgs = state.organizations || [] + if (firstOrg) return orgs[orgs.length - 1] // last org in the array is the first create org + return orgs.find(o => o.is_selected) || orgs[0] }, [isLoggedIn, state] - ); + ) const getSelectedApp = useCallback( (firstApp = false) => { - const selectedOrg = getSelectedOrg(firstApp); - if (!isLoggedIn || !selectedOrg) return null; - const { apps } = selectedOrg; + const selectedOrg = getSelectedOrg(firstApp) + if (!isLoggedIn || !selectedOrg) return null + const { apps } = selectedOrg - if (firstApp) return apps[apps.length - 1]; // last app in the array is the first create app - return apps.find((o) => o.isSelected) || apps[0]; + if (firstApp) return apps[apps.length - 1] // last app in the array is the first create app + return apps.find(o => o.isSelected) || apps[0] }, [isLoggedIn, getSelectedOrg] - ); + ) const value = useMemo( () => ({ @@ -95,7 +96,7 @@ export const AuthContextProvider = ({ children }) => { getSelectedApp, getUserData, ] - ); + ) - return {children}; -}; + return {children} +} diff --git a/src/contexts/BreadcrumbsContext.js b/src/contexts/BreadcrumbsContext.js index 7ae8236..fdd6216 100644 --- a/src/contexts/BreadcrumbsContext.js +++ b/src/contexts/BreadcrumbsContext.js @@ -1,55 +1,56 @@ -import React, { useState, useCallback, useMemo, useEffect } from 'react'; -import { useLocation } from '@docusaurus/router'; +import React, { useCallback, useEffect, useMemo, useState } from "react" -export const BreadcrumbsContext = React.createContext(); +import { useLocation } from "@docusaurus/router" -const removeTrailingSlash = (string) => { - return string && string[string.length - 1] === '/' +export const BreadcrumbsContext = React.createContext() + +const removeTrailingSlash = string => { + return string && string[string.length - 1] === "/" ? string.substring(0, string.length - 1) - : string; -}; + : string +} const extractPathObjects = (sidebar, pathname) => { - const path = []; + const path = [] const recursiveDeepFind = (sidebar, pathAcc) => { - return sidebar.find((sidebarItem) => { - let item; + return sidebar.find(sidebarItem => { + let item if (sidebarItem.items) { - item = recursiveDeepFind(sidebarItem.items, pathAcc); + item = recursiveDeepFind(sidebarItem.items, pathAcc) } else { if ( removeTrailingSlash(sidebarItem.href) === removeTrailingSlash(pathname) ) { - item = sidebarItem; + item = sidebarItem } } if (item) { - pathAcc.unshift(sidebarItem); + pathAcc.unshift(sidebarItem) } - return item; - }); - }; - recursiveDeepFind(sidebar, path); - return path; -}; + return item + }) + } + recursiveDeepFind(sidebar, path) + return path +} export const BreadcrumbsContextProvider = ({ children }) => { - const [breadcrumbs, setBreadcrumbs] = useState([]); - const [sidebar, setSidebar] = useState([]); - const { pathname } = useLocation(); + const [breadcrumbs, setBreadcrumbs] = useState([]) + const [sidebar, setSidebar] = useState([]) + const { pathname } = useLocation() const extarctBreadcrumbs = useCallback((localSidebar, localPathname) => { - const pathObjects = extractPathObjects(localSidebar, localPathname); - return setBreadcrumbs(pathObjects); - }, []); + const pathObjects = extractPathObjects(localSidebar, localPathname) + return setBreadcrumbs(pathObjects) + }, []) useEffect(() => { - extarctBreadcrumbs(sidebar, pathname); - }, [sidebar, pathname]); + extarctBreadcrumbs(sidebar, pathname) + }, [sidebar, pathname]) const value = useMemo( () => ({ @@ -57,11 +58,11 @@ export const BreadcrumbsContextProvider = ({ children }) => { setSidebar, }), [breadcrumbs, setSidebar] - ); + ) return ( {children} - ); -}; + ) +} diff --git a/src/contexts/DocusaurusContext.js b/src/contexts/DocusaurusContext.js index b03f1fa..e4d5313 100644 --- a/src/contexts/DocusaurusContext.js +++ b/src/contexts/DocusaurusContext.js @@ -4,35 +4,36 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -import React, { useMemo } from 'react'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import { Context as DocusaurusContext } from '@docusaurus/docusaurusContext'; -import { useLocation } from '@docusaurus/router'; +import React, { useMemo } from "react" -import { folderMapping } from '../../constants'; -import URLS from '../../urls'; -import productVariables from '../product-variables'; +import { Context as DocusaurusContext } from "@docusaurus/docusaurusContext" +import { useLocation } from "@docusaurus/router" +import useDocusaurusContext from "@docusaurus/useDocusaurusContext" -const { productTitle } = productVariables[process.env.PRODUCT]; +import { folderMapping } from "../../constants" +import URLS from "../../urls" +import productVariables from "../product-variables" + +const { productTitle } = productVariables[process.env.PRODUCT] // Dynamically overrides docusaurus context // Used to have unique SEO tags for SDK. export const DocusaurusContextProvider = ({ children }) => { - const contextValue = useDocusaurusContext(); - const { siteConfig } = contextValue; + const contextValue = useDocusaurusContext() + const { siteConfig } = contextValue - const location = useLocation(); + const location = useLocation() const locationPlatform = useMemo(() => { const [urlPlatform] = location.pathname - .replace(URLS.docs.root, '') - .split('/'); - return urlPlatform; - }, [location.pathname]); + .replace(URLS.docs.root, "") + .split("/") + return urlPlatform + }, [location.pathname]) - const platform = folderMapping[locationPlatform]; + const platform = folderMapping[locationPlatform] const metaTitle = platform ? `Stream ${productTitle} - ${platform} SDK Docs` - : siteConfig.title; + : siteConfig.title return ( { > {children} - ); -}; + ) +} diff --git a/src/define-env-vars-plugin.js b/src/define-env-vars-plugin.js index c9df40d..75cfd10 100644 --- a/src/define-env-vars-plugin.js +++ b/src/define-env-vars-plugin.js @@ -1,42 +1,42 @@ -const webpack = require('webpack'); -const environment = require('./environment'); +const webpack = require("webpack") +const environment = require("./environment") // This plugin defines which env vars will be exposed to the webpack build // We are limiting ourselves to the ones declared in the environment.js file const OPTIONAL_VARIABLES = [ - 'ALGOLIA_APP_ID', - 'ALGOLIA_API_KEY', - 'WEBSITE_BASE_URL', - 'DEPLOYMENT_ENV', - 'PRODUCT', -]; + "ALGOLIA_APP_ID", + "ALGOLIA_API_KEY", + "WEBSITE_BASE_URL", + "DEPLOYMENT_ENV", + "PRODUCT", +] const filteredVariables = Object.keys(environment).reduce((acc, item) => { - if (OPTIONAL_VARIABLES.includes(item)) return acc; - acc[item] = process.env[item]; - return acc; -}, {}); + if (OPTIONAL_VARIABLES.includes(item)) return acc + acc[item] = process.env[item] + return acc +}, {}) module.exports = function () { return { - name: 'define-env-vars-plugin', + name: "define-env-vars-plugin", configureWebpack() { return { plugins: [ new webpack.EnvironmentPlugin({ - ALGOLIA_APP_ID: 'DEFAULT', - ALGOLIA_API_KEY: 'DEFAULT', - WEBSITE_BASE_URL: 'DEFAULT', - DEPLOYMENT_ENV: 'staging', - PRODUCT: 'chat', // either "chat" or "activity-feeds" + ALGOLIA_APP_ID: "DEFAULT", + ALGOLIA_API_KEY: "DEFAULT", + WEBSITE_BASE_URL: "DEFAULT", + DEPLOYMENT_ENV: "staging", + PRODUCT: "chat", // either "chat" or "activity-feeds" ...filteredVariables, }), ], module: { rules: [], }, - }; + } }, - }; -}; + } +} diff --git a/src/environment.js b/src/environment.js index 2ccdb4f..9a94488 100644 --- a/src/environment.js +++ b/src/environment.js @@ -6,4 +6,4 @@ module.exports = { ALGOLIA_API_KEY: process.env.ALGOLIA_API_KEY, WEBSITE_BASE_URL: process.env.WEBSITE_BASE_URL, PRODUCT: process.env.PRODUCT, -}; +} diff --git a/src/hooks/useAuthContext.js b/src/hooks/useAuthContext.js index 924070f..2b746f7 100644 --- a/src/hooks/useAuthContext.js +++ b/src/hooks/useAuthContext.js @@ -1,6 +1,7 @@ -import { useContext } from 'react'; -import { AuthContext } from '../contexts/AuthContext'; +import { useContext } from "react" + +import { AuthContext } from "../contexts/AuthContext" export const useAuthContext = () => { - return useContext(AuthContext); -}; + return useContext(AuthContext) +} diff --git a/src/hooks/useBreadcrumbsContext.js b/src/hooks/useBreadcrumbsContext.js index 79cbf07..dffabd7 100644 --- a/src/hooks/useBreadcrumbsContext.js +++ b/src/hooks/useBreadcrumbsContext.js @@ -1,6 +1,7 @@ -import { useContext } from 'react'; -import { BreadcrumbsContext } from '../contexts/BreadcrumbsContext'; +import { useContext } from "react" + +import { BreadcrumbsContext } from "../contexts/BreadcrumbsContext" export const useBreadcrumbsContext = () => { - return useContext(BreadcrumbsContext); -}; + return useContext(BreadcrumbsContext) +} diff --git a/src/hooks/useFeedbackForm.js b/src/hooks/useFeedbackForm.js index 5bdf5d3..de5a728 100644 --- a/src/hooks/useFeedbackForm.js +++ b/src/hooks/useFeedbackForm.js @@ -1,52 +1,52 @@ -import { useState, useCallback } from 'react'; +import { useCallback, useState } from "react" -import { apiDocFeedback, getAPIErrorMsg } from '../api'; +import { apiDocFeedback, getAPIErrorMsg } from "../api" export const useFeedbackForm = (initialState, section) => { - const [loading, setLoading] = useState(false); - const [success, setSuccess] = useState(false); - const [error, setError] = useState(undefined); - const [data, setData] = useState(initialState); + const [loading, setLoading] = useState(false) + const [success, setSuccess] = useState(false) + const [error, setError] = useState(undefined) + const [data, setData] = useState(initialState) const fieldChangeHandler = useCallback( - (e) => setData((d) => ({ ...d, [e.target.name]: e.target.value })), + e => setData(d => ({ ...d, [e.target.name]: e.target.value })), [] - ); + ) const submitHandler = useCallback( - async (e) => { - e.preventDefault(); - if (success) return; - if (error) setError(undefined); + async e => { + e.preventDefault() + if (success) return + if (error) setError(undefined) - const formData = new FormData(); + const formData = new FormData() for (let key in data) { - formData.append(key, data[key]); + formData.append(key, data[key]) } - const sectionHash = section ? `#${section}` : ''; + const sectionHash = section ? `#${section}` : "" - formData.append('page_url', `${window.location.href}${sectionHash}`); + formData.append("page_url", `${window.location.href}${sectionHash}`) - setLoading(true); + setLoading(true) try { - await apiDocFeedback(formData); + await apiDocFeedback(formData) - setSuccess(true); - resetForm(e.target); + setSuccess(true) + resetForm(e.target) setTimeout(() => { - setSuccess(false); - setData(initialState); - }, 3000); + setSuccess(false) + setData(initialState) + }, 3000) } catch (err) { - setError(getAPIErrorMsg(err)); + setError(getAPIErrorMsg(err)) } - setLoading(false); + setLoading(false) }, [data, success, error] - ); + ) - return { submitHandler, fieldChangeHandler, loading, success, error, data }; -}; + return { submitHandler, fieldChangeHandler, loading, success, error, data } +} diff --git a/src/hooks/useFeedbackFormData.js b/src/hooks/useFeedbackFormData.js index e2e0da6..55233bb 100644 --- a/src/hooks/useFeedbackFormData.js +++ b/src/hooks/useFeedbackFormData.js @@ -1,16 +1,17 @@ import React, { useCallback, useContext, - useState, - useMemo, useEffect, -} from 'react'; -import { useHistory } from '@docusaurus/router'; + useMemo, + useState, +} from "react" + +import { useHistory } from "@docusaurus/router" -const FeedbackFormContext = React.createContext(); +const FeedbackFormContext = React.createContext() export const FeedbackFormProvider = ({ children, title }) => { - const [clickedButtonHeader, setClickedButtonHeader] = useState(title); + const [clickedButtonHeader, setClickedButtonHeader] = useState(title) // We need to keep the clickedButtonHeader in the context provider because // once user clicks on the feedback button it will lose reference to the // current page header @@ -21,76 +22,76 @@ export const FeedbackFormProvider = ({ children, title }) => { setClickedButtonHeader, }), [clickedButtonHeader] - ); + ) return ( {children} - ); -}; + ) +} -const extractTitle = (element) => - element && element.innerText.replace('#', '').replace('\n', ''); +const extractTitle = element => + element && element.innerText.replace("#", "").replace("\n", "") -export const useFeedbackFormData = (lastHeaderTitle) => { - const history = useHistory(); +export const useFeedbackFormData = lastHeaderTitle => { + const history = useHistory() const { clickedButtonHeader, setClickedButtonHeader } = - useContext(FeedbackFormContext); + useContext(FeedbackFormContext) const [headers, setHeaders] = useState([ { value: clickedButtonHeader, isPageHeader: true, }, - ]); + ]) const [currentHeader, setCurrentHeader] = useState({ value: clickedButtonHeader, isPageHeader: true, - }); + }) useEffect(() => { - const pageHeader = document.querySelector('h1'); - const headersAnchors = Array.from(document.querySelectorAll('h2.heading')); - const headers = headersAnchors.map((item) => ({ + const pageHeader = document.querySelector("h1") + const headersAnchors = Array.from(document.querySelectorAll("h2.heading")) + const headers = headersAnchors.map(item => ({ value: extractTitle(item), isPageHeader: false, - })); + })) if (pageHeader) { headers.unshift({ value: extractTitle(pageHeader), isPageHeader: true, - }); + }) } - const lastHeaderTitleString = extractTitle(lastHeaderTitle); + const lastHeaderTitleString = extractTitle(lastHeaderTitle) const headerIndex = headers.findIndex( - (item) => item.value === lastHeaderTitleString - ); + item => item.value === lastHeaderTitleString + ) const prevHeader = lastHeaderTitle ? headers[headerIndex - 1] - : headers[headers.length - 1]; + : headers[headers.length - 1] - setHeaders(headers); - setCurrentHeader(prevHeader); - }, []); + setHeaders(headers) + setCurrentHeader(prevHeader) + }, []) const header = useMemo(() => { - return headers.find((item) => item.value === clickedButtonHeader); - }, [headers, clickedButtonHeader]); + return headers.find(item => item.value === clickedButtonHeader) + }, [headers, clickedButtonHeader]) const goToFeedbackForm = useCallback(() => { history.push( `${history.location.pathname}${history.location.search}#feedback-form` - ); - setClickedButtonHeader(currentHeader.value); - }, [currentHeader]); + ) + setClickedButtonHeader(currentHeader.value) + }, [currentHeader]) return { header, setHeader: setClickedButtonHeader, headers, goToFeedbackForm, - }; -}; + } +} diff --git a/src/hooks/useToast.js b/src/hooks/useToast.js index 6217d3c..90b66a2 100644 --- a/src/hooks/useToast.js +++ b/src/hooks/useToast.js @@ -1,15 +1,15 @@ -import { useEffect } from 'react'; +import { useEffect } from "react" -import { toast } from 'react-toastify'; -import 'react-toastify/dist/ReactToastify.css'; +import { toast } from "react-toastify" +import "react-toastify/dist/ReactToastify.css" export const useToast = (error, success, id) => { useEffect(() => { if (error) { - toast(error, { type: toast.TYPE.ERROR, toastId: id }); + toast(error, { type: toast.TYPE.ERROR, toastId: id }) } if (success) { - toast(success, { type: toast.TYPE.SUCCESS, toastId: id }); + toast(success, { type: toast.TYPE.SUCCESS, toastId: id }) } - }, [success, error, id]); -}; + }, [success, error, id]) +} diff --git a/src/pages/index.js b/src/pages/index.js index e53c154..c14891e 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -1,22 +1,24 @@ -import React from 'react'; -import clsx from 'clsx'; -import Layout from '@theme/Layout'; -import Link from '@docusaurus/Link'; -import useBaseUrl from '@docusaurus/useBaseUrl'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import useGlobalData from '@docusaurus/useGlobalData'; -import styles from './styles.module.css'; +import React from "react" -import { folderMapping } from '../../constants'; +import clsx from "clsx" + +import Link from "@docusaurus/Link" +import useBaseUrl from "@docusaurus/useBaseUrl" +import useDocusaurusContext from "@docusaurus/useDocusaurusContext" +import useGlobalData from "@docusaurus/useGlobalData" +import Layout from "@theme/Layout" + +import { folderMapping } from "../../constants" +import styles from "./styles.module.css" const Feature = ({ title }) => { - const platform = `${title.toLowerCase().replace(' ', '')}`; + const platform = `${title.toLowerCase().replace(" ", "")}` return ( -
+
{
- ); -}; + ) +} export const Home = () => { - const { siteConfig = {} } = useDocusaurusContext(); - const globalData = useGlobalData(); + const { siteConfig = {} } = useDocusaurusContext() + const globalData = useGlobalData() const SDK_FOLDERS = Object.values( - globalData['docusaurus-plugin-content-docs'] || {} - ).map(({ path }) => folderMapping[path.substring(path.lastIndexOf('/') + 1)]); + globalData["docusaurus-plugin-content-docs"] || {} + ).map(({ path }) => folderMapping[path.substring(path.lastIndexOf("/") + 1)]) return ( -
+

{siteConfig.title}

{siteConfig.tagline}

@@ -61,7 +63,7 @@ export const Home = () => { )} - ); -}; + ) +} -export default Home; +export default Home diff --git a/src/product-variables.js b/src/product-variables.js index 315ff8f..b9710c9 100644 --- a/src/product-variables.js +++ b/src/product-variables.js @@ -1,14 +1,14 @@ -const GITHUB_ROOT = 'https://github.com/GetStream'; +const GITHUB_ROOT = "https://github.com/GetStream" module.exports = { - 'activity-feeds': { - productTitle: 'Activity Feeds', + "activity-feeds": { + productTitle: "Activity Feeds", // Algolia stuff algolia: { parentSection: { - name: 'Activity Feeds API Docs', - slug: 'activity_feeds_docs', - id: 'activity_feeds_docs', + name: "Activity Feeds API Docs", + slug: "activity_feeds_docs", + id: "activity_feeds_docs", }, }, // GitHub stuff @@ -21,16 +21,16 @@ module.exports = { }, // Docusaurus (config) stuff docusaurus: { - title: 'Activity Feeds', + title: "Activity Feeds", }, }, chat: { - productTitle: 'Chat', + productTitle: "Chat", algolia: { parentSection: { - name: 'Chat API Docs', - slug: 'chat_docs', - id: 'chat_docs', + name: "Chat API Docs", + slug: "chat_docs", + id: "chat_docs", }, }, github: { @@ -42,16 +42,16 @@ module.exports = { angular: `${GITHUB_ROOT}/stream-chat-angular/`, }, docusaurus: { - title: 'Chat Messaging', + title: "Chat Messaging", }, }, video: { - productTitle: 'Video', + productTitle: "Video", algolia: { parentSection: { - name: 'Video API Docs', - slug: 'video_docs', - id: 'video_docs', + name: "Video API Docs", + slug: "video_docs", + id: "video_docs", }, }, github: { @@ -63,7 +63,7 @@ module.exports = { // angular: `${GITHUB_ROOT}/stream-video-js/`, }, docusaurus: { - title: 'Video', + title: "Video", }, }, -}; +} diff --git a/src/symlink-docusaurus/index.js b/src/symlink-docusaurus/index.js index 1a5abbb..69c06b9 100644 --- a/src/symlink-docusaurus/index.js +++ b/src/symlink-docusaurus/index.js @@ -1,12 +1,12 @@ -module.exports = function(context, options) { - return { - name: 'symlink-docusaurus', - configureWebpack(config, isServer, utils) { - return { - resolve: { - symlinks: false - } - }; +module.exports = function (context, options) { + return { + name: "symlink-docusaurus", + configureWebpack(config, isServer, utils) { + return { + resolve: { + symlinks: false, + }, } - }; - }; \ No newline at end of file + }, + } +} diff --git a/src/theme/DocItem/index.js b/src/theme/DocItem/index.js index fca916c..dbe6956 100644 --- a/src/theme/DocItem/index.js +++ b/src/theme/DocItem/index.js @@ -1,13 +1,13 @@ -import React from 'react'; +import React from "react" -import OriginalDocItem from '@theme-original/DocItem'; +import OriginalDocItem from "@theme-original/DocItem" -import { FeedbackFormProvider } from '../../hooks/useFeedbackFormData'; +import { FeedbackFormProvider } from "../../hooks/useFeedbackFormData" export default function DocItem(props) { return ( - ); + ) } diff --git a/src/theme/DocPaginator/index.js b/src/theme/DocPaginator/index.js index 8fa13a8..28e3364 100644 --- a/src/theme/DocPaginator/index.js +++ b/src/theme/DocPaginator/index.js @@ -1,9 +1,9 @@ -import React from 'react'; +import React from "react" -import OriginalDocPaginator from '@theme-original/DocPaginator'; +import OriginalDocPaginator from "@theme-original/DocPaginator" -import { FeedbackForm } from '../../components/FeedbackForm'; -import { FeedbackFormButton } from '../../components/FeedbackFormButton'; +import { FeedbackForm } from "../../components/FeedbackForm" +import { FeedbackFormButton } from "../../components/FeedbackFormButton" export default function DocPaginator(props) { return ( @@ -12,5 +12,5 @@ export default function DocPaginator(props) { - ); + ) } diff --git a/src/theme/DocSidebar/index.js b/src/theme/DocSidebar/index.js index d49331d..457a3ab 100644 --- a/src/theme/DocSidebar/index.js +++ b/src/theme/DocSidebar/index.js @@ -1,46 +1,48 @@ -import React, { useEffect, useMemo } from 'react'; -import OriginalDocSidebar from '@theme-original/DocSidebar'; -import { useBreadcrumbsContext } from '../../hooks/useBreadcrumbsContext'; +import React, { useEffect, useMemo } from "react" + +import OriginalDocSidebar from "@theme-original/DocSidebar" + +import { useBreadcrumbsContext } from "../../hooks/useBreadcrumbsContext" const WEB_LINKS = [ - ['Contact Support', 'https://getstream.io/contact/support/'], - ['Maker Account', 'https://getstream.io/maker-account/'], - ['Mobile Chat Kit', 'https://getstream.io/chat/ux-kit/'], // activity feeds ux kit ??? + ["Contact Support", "https://getstream.io/contact/support/"], + ["Maker Account", "https://getstream.io/maker-account/"], + ["Mobile Chat Kit", "https://getstream.io/chat/ux-kit/"], // activity feeds ux kit ??? [ <> © Stream.IO, Inc.
All Rights Reserved. , - '/', + "/", ], -]; +] -const addTitle = (sidebarItems) => { +const addTitle = sidebarItems => { return sidebarItems.map(({ label, items, ...props }) => ({ ...props, ...(items && { items: addTitle(items) }), label: {label}, - })); -}; + })) +} export default function DocSidebar({ sidebar, ...props }) { - const { setSidebar } = useBreadcrumbsContext(); + const { setSidebar } = useBreadcrumbsContext() useEffect(() => { - setSidebar(sidebar); - }, [sidebar]); + setSidebar(sidebar) + }, [sidebar]) const sidebarItems = useMemo( () => addTitle([ - ...sidebar.map((category) => ({ ...category, collapsed: false })), + ...sidebar.map(category => ({ ...category, collapsed: false })), ...WEB_LINKS.map(([label, href]) => ({ - type: 'link', + type: "link", label, href, })), ]), [sidebar] - ); + ) - return ; + return } diff --git a/src/theme/Heading/index.js b/src/theme/Heading/index.js index f45b054..b5952de 100644 --- a/src/theme/Heading/index.js +++ b/src/theme/Heading/index.js @@ -6,14 +6,15 @@ */ /* eslint-disable jsx-a11y/anchor-has-content, jsx-a11y/anchor-is-valid */ -import React, { useEffect, useState, useRef } from 'react'; -import clsx from 'clsx'; -import { translate } from '@docusaurus/Translate'; -import { useThemeConfig } from '@docusaurus/theme-common'; +import React, { useEffect, useRef, useState } from "react" -import { FeedbackFormButton } from '../../components/FeedbackFormButton'; +import clsx from "clsx" -import './styles.scss'; +import { useThemeConfig } from "@docusaurus/theme-common" +import { translate } from "@docusaurus/Translate" + +import { FeedbackFormButton } from "../../components/FeedbackFormButton" +import "./styles.scss" export const MainHeading = function MainHeading({ ...props }) { return ( @@ -25,42 +26,42 @@ export const MainHeading = function MainHeading({ ...props }) { {props.children}
- ); -}; + ) +} -export const Heading = (Tag) => +export const Heading = Tag => function TargetComponent({ id, ...props }) { - const copyLink = (e) => { - navigator?.clipboard?.writeText(e.target.href); - }; + const copyLink = e => { + navigator?.clipboard?.writeText(e.target.href) + } - const [title, setTitle] = useState(); - const headingRef = useRef(null); + const [title, setTitle] = useState() + const headingRef = useRef(null) useEffect(() => { - if (Tag === 'h2') { - setTitle(headingRef.current); + if (Tag === "h2") { + setTitle(headingRef.current) } - }, []); + }, []) const { navbar: { hideOnScroll }, - } = useThemeConfig(); + } = useThemeConfig() if (!id) { - return ; + return } return ( <> - {Tag === 'h2' && title && ( + {Tag === "h2" && title && ( )} - ); - }; + ) + } -export default Heading; +export default Heading diff --git a/src/theme/Layout/index.js b/src/theme/Layout/index.js index 5ca31fa..2fdc672 100644 --- a/src/theme/Layout/index.js +++ b/src/theme/Layout/index.js @@ -1,31 +1,33 @@ -import React, { useEffect, useState } from 'react'; -import OriginalLayout from '@theme-original/Layout'; -import { ToastContainer } from 'react-toastify'; +import React, { useEffect, useState } from "react" -import URLS from '../../../urls'; -import { AuthContextProvider } from '../../contexts/AuthContext'; +import { ToastContainer } from "react-toastify" -const isBrowser = typeof window !== `undefined`; -const isProd = process.env.DEPLOYMENT_ENV === 'production'; +import OriginalLayout from "@theme-original/Layout" + +import URLS from "../../../urls" +import { AuthContextProvider } from "../../contexts/AuthContext" + +const isBrowser = typeof window !== `undefined` +const isProd = process.env.DEPLOYMENT_ENV === "production" export default function Layout(props) { - const isRootPath = isBrowser && window.location.pathname === URLS.docs.root; + const isRootPath = isBrowser && window.location.pathname === URLS.docs.root const shouldRedirect = - isBrowser && window.location.pathname !== '/video/docs/'; - const [canRender, setCanRender] = useState(!isProd || !isRootPath); + isBrowser && window.location.pathname !== "/video/docs/" + const [canRender, setCanRender] = useState(!isProd || !isRootPath) // whick redirect for home page. this should happen here in order to avoid // rendering the layout when redirecting. useEffect(() => { if (isProd && isRootPath && shouldRedirect) { - window.location.replace(URLS.website.cms_docs); + window.location.replace(URLS.website.cms_docs) } else if (!canRender) { - setCanRender(true); + setCanRender(true) } - }, []); + }, []) if (!canRender) { - return null; + return null } return ( @@ -33,5 +35,5 @@ export default function Layout(props) { - ); + ) } diff --git a/src/theme/Navbar/index.js b/src/theme/Navbar/index.js index 2816205..c781f70 100644 --- a/src/theme/Navbar/index.js +++ b/src/theme/Navbar/index.js @@ -1,19 +1,19 @@ -import React, { useMemo } from 'react'; -import clsx from 'clsx'; -import OriginalNavbar from '@theme-original/Navbar'; -import { useLocation, Link } from '@docusaurus/router'; +import React, { useMemo } from "react" -import { useBreadcrumbsContext } from '../../hooks/useBreadcrumbsContext'; -import { folderMapping } from '../../../constants'; -import { docs, website } from '../../../urls'; +import clsx from "clsx" -import URLS from '../../../urls'; -import productVariables from '../../product-variables'; +import { Link, useLocation } from "@docusaurus/router" +import OriginalNavbar from "@theme-original/Navbar" -import './styles.scss'; +import { folderMapping } from "../../../constants" +import { docs, website } from "../../../urls" +import URLS from "../../../urls" +import { useBreadcrumbsContext } from "../../hooks/useBreadcrumbsContext" +import productVariables from "../../product-variables" +import "./styles.scss" -const PRODUCT = process.env.PRODUCT; -const { productTitle } = productVariables[PRODUCT]; +const PRODUCT = process.env.PRODUCT +const { productTitle } = productVariables[PRODUCT] export default function Navbar(props) { return ( @@ -21,53 +21,53 @@ export default function Navbar(props) { - ); + ) } const SiteNavbar = () => { - const { breadcrumbs } = useBreadcrumbsContext(); + const { breadcrumbs } = useBreadcrumbsContext() - const location = useLocation(); + const location = useLocation() const locationPlatform = useMemo(() => { const [urlPlatform] = location.pathname - .replace(URLS.docs.root, '') - .split('/'); - return urlPlatform; - }, [location.pathname]); + .replace(URLS.docs.root, "") + .split("/") + return urlPlatform + }, [location.pathname]) - const platform = folderMapping[locationPlatform]; + const platform = folderMapping[locationPlatform] const breadcrumbsWithSeparators = useMemo( () => breadcrumbs.flatMap((value, index, array) => - array.length - 1 !== index && value.type !== 'category' - ? [value, { type: 'separator' }] + array.length - 1 !== index && value.type !== "category" + ? [value, { type: "separator" }] : value ), [breadcrumbs] - ); + ) const breadcrumbItems = useMemo( () => breadcrumbsWithSeparators.map((item, i) => { - if (item.type === 'separator') { + if (item.type === "separator") { return (
  • »
  • - ); - } else if (item.type === 'category') { + ) + } else if (item.type === "category") { return (
  • {item.label}:
  • - ); + ) } - return
  • {item.label}
  • ; + return
  • {item.label}
  • }), [breadcrumbsWithSeparators] - ); + ) return (
    - ); -}; + ) +} diff --git a/src/theme/NavbarItem/index.js b/src/theme/NavbarItem/index.js index 934e36c..df75bc5 100644 --- a/src/theme/NavbarItem/index.js +++ b/src/theme/NavbarItem/index.js @@ -1,17 +1,17 @@ -import React, { useMemo } from 'react'; -import { useLocation } from '@docusaurus/router'; -import useGlobalData from '@docusaurus/useGlobalData'; -import OriginalNavbarItem from '@theme-original/NavbarItem'; -import { useActiveVersion } from '@theme/hooks/useDocs'; +import React, { useMemo } from "react" -import { useAuthContext } from '../../hooks/useAuthContext'; -import URLS from '../../../urls'; +import { useLocation } from "@docusaurus/router" +import useGlobalData from "@docusaurus/useGlobalData" +import OriginalNavbarItem from "@theme-original/NavbarItem" +import { useActiveVersion } from "@theme/hooks/useDocs" -import './styles.scss'; +import URLS from "../../../urls" +import { useAuthContext } from "../../hooks/useAuthContext" +import "./styles.scss" function GithubReleaseLink({ activeVersion, href }) { return ( - activeVersion.name !== 'current' && ( + activeVersion.name !== "current" && ( ) - ); + ) } function CustomNavbarItem(props) { - const { docsPluginId, label, type, items } = props; - const { location, locationPlatform, activeVersion, ...itemProps } = props; - const { pathname } = location; + const { docsPluginId, label, type, items } = props + const { location, locationPlatform, activeVersion, ...itemProps } = props + const { pathname } = location - const { isLoggedIn } = useAuthContext(); + const { isLoggedIn } = useAuthContext() const selectedSDK = useMemo(() => { - if (label === 'SDK' && items.length) { - return items.find((item) => + if (label === "SDK" && items.length) { + return items.find(item => pathname.includes(`${URLS.docs.root}${item.id}/`) - ); + ) } - }, [items, label, pathname]); + }, [items, label, pathname]) if (selectedSDK) { return ( - ); + ) } if ( - type === 'docsVersionDropdown' && + type === "docsVersionDropdown" && pathname - .replace(' ', '') - .search(new RegExp(`${URLS.docs.root}${docsPluginId}/.*`, 'g')) === -1 + .replace(" ", "") + .search(new RegExp(`${URLS.docs.root}${docsPluginId}/.*`, "g")) === -1 ) { - return null; + return null } - if (label === 'github') { + if (label === "github") { return ( activeVersion && (
    @@ -66,12 +66,12 @@ function CustomNavbarItem(props) {
    ) - ); + ) } - if (label === 'Sign Up') { + if (label === "Sign Up") { if (isLoggedIn) { - return null; + return null } } @@ -80,16 +80,16 @@ function CustomNavbarItem(props) { {...itemProps} docId={activeVersion && activeVersion.mainDocId} /> - ); + ) } const PlatformNavbarItem = ({ items, ...props }) => { const sdks = useMemo( - () => items.map((sdk) => ({ ...sdk, label: PlatformLabel(sdk) })), + () => items.map(sdk => ({ ...sdk, label: PlatformLabel(sdk) })), [items] - ); - return ; -}; + ) + return +} const PlatformLabel = ({ id, label }) => ( @@ -100,27 +100,27 @@ const PlatformLabel = ({ id, label }) => ( /> {label} -); +) function NavbarItemWithActiveVersion(props) { - const { docsPluginId, locationPlatform } = props; - const activeVersion = useActiveVersion(docsPluginId || locationPlatform); + const { docsPluginId, locationPlatform } = props + const activeVersion = useActiveVersion(docsPluginId || locationPlatform) - return ; + return } export default function NavbarItem(props) { - const { docsPluginId, label, type, items } = props; - const location = useLocation(); + const { docsPluginId, label, type, items } = props + const location = useLocation() const locationPlatform = useMemo(() => { const [urlPlatform] = location.pathname - .replace(URLS.docs.root, '') - .split('/'); - return urlPlatform; - }, [location.pathname]); + .replace(URLS.docs.root, "") + .split("/") + return urlPlatform + }, [location.pathname]) - const globalData = useGlobalData(); - const SDKS = globalData['docusaurus-plugin-content-docs']; + const globalData = useGlobalData() + const SDKS = globalData["docusaurus-plugin-content-docs"] if (docsPluginId === locationPlatform && SDKS[locationPlatform]) { return ( @@ -129,12 +129,12 @@ export default function NavbarItem(props) { location={location} locationPlatform={locationPlatform} /> - ); + ) } const lastVersion = SDKS[docsPluginId] - ? SDKS[docsPluginId].versions.find((v) => v.isLast) - : null; + ? SDKS[docsPluginId].versions.find(v => v.isLast) + : null return ( - ); + ) } diff --git a/src/theme/Root/index.js b/src/theme/Root/index.js index ca49ebe..9a83ee0 100644 --- a/src/theme/Root/index.js +++ b/src/theme/Root/index.js @@ -1,9 +1,9 @@ -import React from 'react'; +import React from "react" -import OriginalRoot from '@theme-original/Root'; +import OriginalRoot from "@theme-original/Root" -import { DocusaurusContextProvider } from '../../contexts/DocusaurusContext'; -import { BreadcrumbsContextProvider } from '../../contexts/BreadcrumbsContext'; +import { BreadcrumbsContextProvider } from "../../contexts/BreadcrumbsContext" +import { DocusaurusContextProvider } from "../../contexts/DocusaurusContext" export default function DocItem(props) { return ( @@ -12,5 +12,5 @@ export default function DocItem(props) { - ); + ) } diff --git a/src/theme/SearchBar/DocSearchModal.js b/src/theme/SearchBar/DocSearchModal.js index 7fc6951..c807635 100644 --- a/src/theme/SearchBar/DocSearchModal.js +++ b/src/theme/SearchBar/DocSearchModal.js @@ -1,131 +1,132 @@ -import React, { useMemo } from 'react'; -import algoliasearch from 'algoliasearch/lite'; -import { createAutocomplete } from '@algolia/autocomplete-core'; -import url from 'url'; -import { useLocation } from '@docusaurus/router'; -import { useActivePlugin, useActiveVersion } from '@theme/hooks/useDocs'; -import { Footer } from './Footer'; -import { SearchBox } from './SearchBox'; -import { Hits } from './Hits'; +import React, { useMemo } from "react" -import { useTouchEvents } from './useTouchEvents'; -import { useTrapFocus } from './useTrapFocus'; -import { getItemUrl } from './getItemUrl'; +import algoliasearch from "algoliasearch/lite" +import url from "url" + +import { createAutocomplete } from "@algolia/autocomplete-core" +import { useLocation } from "@docusaurus/router" +import { useActivePlugin, useActiveVersion } from "@theme/hooks/useDocs" import { - platformMapping, - folderMapping, - DOCUSAURUS_INDEX, CMS_INDEX, -} from '../../../constants'; -import environment from '../../environment'; -import productVariables from '../../product-variables'; + DOCUSAURUS_INDEX, + folderMapping, + platformMapping, +} from "../../../constants" +import environment from "../../environment" +import productVariables from "../../product-variables" +import { Footer } from "./Footer" +import { getItemUrl } from "./getItemUrl" +import { Hits } from "./Hits" +import { SearchBox } from "./SearchBox" +import { useTouchEvents } from "./useTouchEvents" +import { useTrapFocus } from "./useTrapFocus" const { algolia: { parentSection: { slug: parentSectionSlug }, }, -} = productVariables[process.env.PRODUCT]; +} = productVariables[process.env.PRODUCT] const algoliaClient = algoliasearch( environment.ALGOLIA_APP_ID, environment.ALGOLIA_API_KEY -); +) -const mergeResults = (results) => { - const docussaurusHits = results[0].hits.map((item) => ({ +const mergeResults = results => { + const docussaurusHits = results[0].hits.map(item => ({ ...item, index: DOCUSAURUS_INDEX, - })); - const docsHits = results[1].hits.map((item) => ({ + })) + const docsHits = results[1].hits.map(item => ({ ...item, index: CMS_INDEX, - })); - return [...docussaurusHits, ...docsHits]; -}; + })) + return [...docussaurusHits, ...docsHits] +} export function DocSearchModal({ onClose = () => null, initialScrollY = 0, locationPlatform, }) { - const containerRef = React.useRef(null); - const formElementRef = React.useRef(null); - const dropdownRef = React.useRef(null); - const inputRef = React.useRef(null); - const modalRef = React.useRef(null); - const snippetLength = React.useRef(10); - const location = useLocation(); + const containerRef = React.useRef(null) + const formElementRef = React.useRef(null) + const dropdownRef = React.useRef(null) + const inputRef = React.useRef(null) + const modalRef = React.useRef(null) + const snippetLength = React.useRef(10) + const location = useLocation() const locationQuery = useMemo(() => { - const { query } = url.parse(location.search || '', { + const { query } = url.parse(location.search || "", { parseQueryString: true, - }); - return query; - }, [location.search]); + }) + return query + }, [location.search]) const [state, setState] = React.useState({ - query: locationQuery.query || '', - }); - const { pluginId } = useActivePlugin({ failfast: true }); + query: locationQuery.query || "", + }) + const { pluginId } = useActivePlugin({ failfast: true }) - const activeVersion = useActiveVersion(pluginId); + const activeVersion = useActiveVersion(pluginId) React.useEffect(() => { - document.body.classList.add('DocSearch--active'); + document.body.classList.add("DocSearch--active") return () => { - document.body.classList.remove('DocSearch--active'); + document.body.classList.remove("DocSearch--active") // IE11 doesn't support `scrollTo` so we check that the method exists // first. - window.scrollTo?.(0, initialScrollY); - }; + window.scrollTo?.(0, initialScrollY) + } // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + }, []) React.useEffect(() => { - const isMobileMediaQuery = window.matchMedia('(max-width: 750px)'); + const isMobileMediaQuery = window.matchMedia("(max-width: 750px)") if (isMobileMediaQuery.matches) { - snippetLength.current = 5; + snippetLength.current = 5 } - }, []); + }, []) React.useEffect(() => { function setFullViewportHeight() { if (modalRef.current) { - const vh = window.innerHeight * 0.01; - modalRef.current.style.setProperty('--docsearch-vh', `${vh}px`); + const vh = window.innerHeight * 0.01 + modalRef.current.style.setProperty("--docsearch-vh", `${vh}px`) } } - setFullViewportHeight(); + setFullViewportHeight() - window.addEventListener('resize', setFullViewportHeight); + window.addEventListener("resize", setFullViewportHeight) return () => { - window.removeEventListener('resize', setFullViewportHeight); - }; - }, []); + window.removeEventListener("resize", setFullViewportHeight) + } + }, []) const autocomplete = React.useMemo( () => createAutocomplete({ - id: 'search', + id: "search", defaultActiveItemId: 0, - placeholder: 'Search', + placeholder: "Search", onStateChange({ state, setCollections }) { if (!state.query && state.collections.length > 0) { - return setCollections([]); + return setCollections([]) } - setState(state); + setState(state) }, getSources({ query }) { return algoliaClient .multipleQueries([ { indexName: DOCUSAURUS_INDEX, - type: 'default', + type: "default", query, params: { filters: `parent_section_slug:${parentSectionSlug} AND platform:${platformMapping[locationPlatform]} AND version:${activeVersion.name}`, @@ -133,7 +134,7 @@ export function DocSearchModal({ }, { indexName: CMS_INDEX, - type: 'default', + type: "default", query, params: { filters: `parent_section_slug:${parentSectionSlug} AND platforms:${platformMapping[locationPlatform]}`, @@ -141,41 +142,41 @@ export function DocSearchModal({ }, ]) .then(({ results }) => { - const hits = mergeResults(results); + const hits = mergeResults(results) const grouped = hits.reduce((acc, hit) => { // If section slug doesnt exist, initialize - if (!acc[hit.section_slug]) acc[hit.section_slug] = {}; + if (!acc[hit.section_slug]) acc[hit.section_slug] = {} // If slug doesnt exist, initialize it with the hit. // Needed in order to categorize the response by page. // index: "DOCS" is used later in order to redirect to // old cms website if (!acc[hit.section_slug][hit.slug]) - acc[hit.section_slug][hit.slug] = [hit]; + acc[hit.section_slug][hit.slug] = [hit] else { if (!hit.header_id) { // If no header_id is present, it means that the result is linked // to the page itself and not a header inside the page. // Docusaurus and our design always shows the page first, then a list of headers - acc[hit.section_slug][hit.slug].unshift(hit); + acc[hit.section_slug][hit.slug].unshift(hit) } else { - acc[hit.section_slug][hit.slug].push(hit); + acc[hit.section_slug][hit.slug].push(hit) } } - return acc; - }, {}); + return acc + }, {}) return Object.entries(grouped).map(([key, group]) => ({ sourceId: key, getItems() { return Object.values(group) .flat() - .map((item) => ({ + .map(item => ({ ...item, // Needed in order to know if it should show the tree icon in search results includes_slug_parent: !group[item.slug][0].header_id, - })); + })) }, getItemUrl({ item }) { return getItemUrl({ @@ -183,49 +184,49 @@ export function DocSearchModal({ platform: locationPlatform, cmsPlatform: platformMapping[locationPlatform], locationQuery, - }); + }) }, - })); - }); + })) + }) }, }), [locationPlatform, activeVersion] - ); + ) - const { getEnvironmentProps, getRootProps } = autocomplete; + const { getEnvironmentProps, getRootProps } = autocomplete React.useEffect(() => { if (dropdownRef.current) { - dropdownRef.current.scrollTop = 0; + dropdownRef.current.scrollTop = 0 } - }, [state.query]); + }, [state.query]) useTouchEvents({ getEnvironmentProps, panelElement: dropdownRef.current, formElement: formElementRef.current, inputElement: inputRef.current, - }); + }) - useTrapFocus({ container: containerRef.current }); + useTrapFocus({ container: containerRef.current }) return (
    { + .join(" ")} + onMouseDown={event => { if (event.target === event.currentTarget) { - onClose(); + onClose() } }} > @@ -256,5 +257,5 @@ export function DocSearchModal({
    - ); + ) } diff --git a/src/theme/SearchBar/Footer.js b/src/theme/SearchBar/Footer.js index 6a2b963..bd16318 100644 --- a/src/theme/SearchBar/Footer.js +++ b/src/theme/SearchBar/Footer.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React from "react" export function Footer() { return ( @@ -35,7 +35,7 @@ export function Footer() { - ); + ) } function CommandIcon(props) { @@ -51,5 +51,5 @@ function CommandIcon(props) { {props.children} - ); + ) } diff --git a/src/theme/SearchBar/Hits.js b/src/theme/SearchBar/Hits.js index fb6e6a1..0af97f4 100644 --- a/src/theme/SearchBar/Hits.js +++ b/src/theme/SearchBar/Hits.js @@ -1,26 +1,24 @@ -import React from 'react'; +import React from "react" -import Link from '@docusaurus/Link'; +import Link from "@docusaurus/Link" -import { Snippet } from './Snippet'; -import { SourceIcon } from './icons/SourceIcon'; -import { GoToExternal } from './icons/GoToExternal'; -import { getItemUrl } from './getItemUrl'; - -import { CMS_INDEX, languageMapping } from '../../../constants'; - -import './hits.scss'; +import { CMS_INDEX, languageMapping } from "../../../constants" +import { getItemUrl } from "./getItemUrl" +import "./hits.scss" +import { GoToExternal } from "./icons/GoToExternal" +import { SourceIcon } from "./icons/SourceIcon" +import { Snippet } from "./Snippet" export function Hits(props) { if (!props.collections) { - return null; + return null } - return props.collections.map((collection) => ( + return props.collections.map(collection => (
    - {collection.items[0].section_name}{' '} - {collection.items[0].index === CMS_INDEX && '(old website)'} + {collection.items[0].section_name}{" "} + {collection.items[0].index === CMS_INDEX && "(old website)"}
      @@ -37,11 +35,11 @@ export function Hits(props) { getItemProps={props.getItemProps} closeSearchModal={props.closeSearchModal} /> - ); + ) })}
    - )); + )) } export function Hit({ @@ -52,24 +50,24 @@ export function Hit({ closeSearchModal, children, }) { - const url = getItemUrl({ item: hit, platform, cmsPlatform, locationQuery }); + const url = getItemUrl({ item: hit, platform, cmsPlatform, locationQuery }) if (hit.index === CMS_INDEX) { return ( - + {children} - ); + ) } return ( {children} - ); + ) } function Result({ @@ -82,30 +80,30 @@ function Result({ locationQuery, closeSearchModal, }) { - const action = React.useRef(null); - const title = item._highlightResult.name; - const snippetResult = item._snippetResult; - const path = snippetResult && snippetResult.content_serialized_text; + const action = React.useRef(null) + const title = item._highlightResult.name + const snippetResult = item._snippetResult + const path = snippetResult && snippetResult.content_serialized_text const codeSnippet = snippetResult && (snippetResult[`code_sample_${languageMapping[platform]}`] || - snippetResult.code_sample); + snippetResult.code_sample) - const istLastItemOnSlug = item.slug !== collection.items[index + 1]?.slug; + const istLastItemOnSlug = item.slug !== collection.items[index + 1]?.slug - const shouldHavePath = item.includes_slug_parent && !!item.header_id; + const shouldHavePath = item.includes_slug_parent && !!item.header_id return (
  • { if (action.current) { - action.current(); + action.current() } }} {...getItemProps({ @@ -143,11 +141,11 @@ function Result({
    - +
    @@ -161,7 +159,7 @@ function Result({ hit={path} attribute="value" /> - {codeSnippet && codeSnippet.matchLevel !== 'none' && ( + {codeSnippet && codeSnippet.matchLevel !== "none" && (
  • - ); + ) } diff --git a/src/theme/SearchBar/SearchBox.js b/src/theme/SearchBar/SearchBox.js index f5bc6d1..23fd708 100644 --- a/src/theme/SearchBar/SearchBox.js +++ b/src/theme/SearchBar/SearchBox.js @@ -1,18 +1,18 @@ -import React from 'react'; +import React from "react" -import { SearchIcon } from './icons/SearchIcon'; -import { LoadingIcon } from './icons/LoadingIcon'; +import { LoadingIcon } from "./icons/LoadingIcon" +import { SearchIcon } from "./icons/SearchIcon" function SearchBoxComponent(props) { const { onReset } = props.getFormProps({ inputElement: props.inputRef.current, - }); + }) return ( <>
    { - event.preventDefault(); + onSubmit={event => { + event.preventDefault() }} onReset={onReset} > @@ -42,7 +42,7 @@ function SearchBoxComponent(props) { Cancel - ); + ) } -export const SearchBox = SearchBoxComponent; +export const SearchBox = SearchBoxComponent diff --git a/src/theme/SearchBar/Snippet.js b/src/theme/SearchBar/Snippet.js index 7ee51a6..bee1011 100644 --- a/src/theme/SearchBar/Snippet.js +++ b/src/theme/SearchBar/Snippet.js @@ -1,13 +1,13 @@ -import { createElement } from 'react'; +import { createElement } from "react" function getPropertyByPath(object, path) { - if (!path) return object; - const parts = path.split('.'); + if (!path) return object + const parts = path.split(".") - return parts.reduce((current, key) => current && current[key], object); + return parts.reduce((current, key) => current && current[key], object) } -export function Snippet({ hit, attribute, tagName = 'span', ...rest }) { +export function Snippet({ hit, attribute, tagName = "span", ...rest }) { return createElement(tagName, { ...rest, dangerouslySetInnerHTML: { @@ -15,5 +15,5 @@ export function Snippet({ hit, attribute, tagName = 'span', ...rest }) { getPropertyByPath(hit, `_snippetResult.${attribute}.value`) || getPropertyByPath(hit, attribute), }, - }); + }) } diff --git a/src/theme/SearchBar/getItemUrl.js b/src/theme/SearchBar/getItemUrl.js index 853095d..6e353e2 100644 --- a/src/theme/SearchBar/getItemUrl.js +++ b/src/theme/SearchBar/getItemUrl.js @@ -1,19 +1,19 @@ -import url from 'url'; +import url from "url" -import { website, docs } from '../../../urls'; -import { CMS_INDEX } from '../../../constants'; +import { CMS_INDEX } from "../../../constants" +import { docs, website } from "../../../urls" export const getItemUrl = ({ item, platform, cmsPlatform, locationQuery }) => { - const headerId = item.header_id.replace('_', '-'); + const headerId = item.header_id.replace("_", "-") if (item.index === CMS_INDEX) { return `${website.cms_docs}${url.format({ pathname: `${cmsPlatform}/${item.slug}/`, query: locationQuery, - })}${!!headerId ? `#${headerId}` : ''}`; + })}${!!headerId ? `#${headerId}` : ""}` } return `${docs.root}${url.format({ - pathname: item.slug === '' ? `${platform}/` : `${platform}/${item.slug}/`, + pathname: item.slug === "" ? `${platform}/` : `${platform}/${item.slug}/`, query: locationQuery, - })}${!!headerId ? `#${headerId}` : ''}`; -}; + })}${!!headerId ? `#${headerId}` : ""}` +} diff --git a/src/theme/SearchBar/icons/GoToExternal.js b/src/theme/SearchBar/icons/GoToExternal.js index d8aafa7..fd9992e 100644 --- a/src/theme/SearchBar/icons/GoToExternal.js +++ b/src/theme/SearchBar/icons/GoToExternal.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React from "react" export function GoToExternal() { return ( @@ -24,5 +24,5 @@ export function GoToExternal() { strokeLinejoin="round" /> - ); + ) } diff --git a/src/theme/SearchBar/icons/LoadingIcon.js b/src/theme/SearchBar/icons/LoadingIcon.js index 6963ca4..6e4fe45 100644 --- a/src/theme/SearchBar/icons/LoadingIcon.js +++ b/src/theme/SearchBar/icons/LoadingIcon.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React from "react" export function LoadingIcon() { return ( @@ -19,5 +19,5 @@ export function LoadingIcon() { - ); + ) } diff --git a/src/theme/SearchBar/icons/SearchIcon.js b/src/theme/SearchBar/icons/SearchIcon.js index bb4e830..91a81b1 100644 --- a/src/theme/SearchBar/icons/SearchIcon.js +++ b/src/theme/SearchBar/icons/SearchIcon.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React from "react" export function SearchIcon() { return ( @@ -16,5 +16,5 @@ export function SearchIcon() { fill="#005FFF" /> - ); + ) } diff --git a/src/theme/SearchBar/icons/SourceIcon.js b/src/theme/SearchBar/icons/SourceIcon.js index 8249f26..10e97bb 100644 --- a/src/theme/SearchBar/icons/SourceIcon.js +++ b/src/theme/SearchBar/icons/SourceIcon.js @@ -1,13 +1,13 @@ -import React from 'react'; +import React from "react" export function SourceIcon(props) { switch (props.type) { - case 'section': - return ; - case 'content': - return ; + case "section": + return + case "content": + return default: - return ; + return } } @@ -22,7 +22,7 @@ function SectionIcon() { strokeLinejoin="round" /> - ); + ) } function AnchorIcon() { @@ -37,7 +37,7 @@ function AnchorIcon() { strokeLinejoin="round" /> - ); + ) } function ContentIcon() { @@ -51,5 +51,5 @@ function ContentIcon() { strokeLinejoin="round" /> - ); + ) } diff --git a/src/theme/SearchBar/index.js b/src/theme/SearchBar/index.js index cdad4f6..efbeb77 100644 --- a/src/theme/SearchBar/index.js +++ b/src/theme/SearchBar/index.js @@ -4,43 +4,42 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ +import React, { useCallback, useMemo, useRef, useState } from "react" -import React, { useState, useRef, useCallback, useMemo } from 'react'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import useGlobalData from '@docusaurus/useGlobalData'; -import Head from '@docusaurus/Head'; -import { DocSearchButton, useDocSearchKeyboardEvents } from '@docsearch/react'; -import { translate } from '@docusaurus/Translate'; -import { useLocation } from '@docusaurus/router'; +import { DocSearchButton, useDocSearchKeyboardEvents } from "@docsearch/react" +import Head from "@docusaurus/Head" +import { useLocation } from "@docusaurus/router" +import { translate } from "@docusaurus/Translate" +import useDocusaurusContext from "@docusaurus/useDocusaurusContext" +import useGlobalData from "@docusaurus/useGlobalData" -import { DocSearchModal } from './DocSearchModal'; +import URLS from "../../../urls" +import { DocSearchModal } from "./DocSearchModal" -import('@docsearch/react/style'); -import('./styles.css'); - -import URLS from '../../../urls'; +import("@docsearch/react/style") +import("./styles.css") function DocSearch({ contextualSearch, ...props }) { - const searchButtonRef = useRef(null); - const [isOpen, setIsOpen] = useState(false); + const searchButtonRef = useRef(null) + const [isOpen, setIsOpen] = useState(false) - const location = useLocation(); + const location = useLocation() const locationPlatform = useMemo(() => { const [urlPlatform] = location.pathname - .replace(URLS.docs.root, '') - .split('/'); - return urlPlatform; - }, [location.pathname]); + .replace(URLS.docs.root, "") + .split("/") + return urlPlatform + }, [location.pathname]) const onOpen = useCallback(() => { - setIsOpen(true); - }, [setIsOpen]); + setIsOpen(true) + }, [setIsOpen]) const onClose = useCallback(() => { - setIsOpen(false); - }, [setIsOpen]); + setIsOpen(false) + }, [setIsOpen]) - const onInput = useCallback(() => {}, []); + const onInput = useCallback(() => {}, []) useDocSearchKeyboardEvents({ isOpen, @@ -48,18 +47,18 @@ function DocSearch({ contextualSearch, ...props }) { onClose, onInput, searchButtonRef, - }); + }) - const globalData = useGlobalData(); - const SDKS = globalData['docusaurus-plugin-content-docs']; + const globalData = useGlobalData() + const SDKS = globalData["docusaurus-plugin-content-docs"] - if (!SDKS[locationPlatform]) return null; + if (!SDKS[locationPlatform]) return null const translatedSearchLabel = translate({ - id: 'theme.SearchBar.label', - message: 'Search', - description: 'The ARIA label and placeholder for search button', - }); + id: "theme.SearchBar.label", + message: "Search", + description: "The ARIA label and placeholder for search button", + }) return ( <> @@ -89,12 +88,12 @@ function DocSearch({ contextualSearch, ...props }) { )} - ); + ) } function SearchBar() { - const { siteConfig } = useDocusaurusContext(); - return ; + const { siteConfig } = useDocusaurusContext() + return } -export default SearchBar; +export default SearchBar diff --git a/src/theme/SearchBar/useTouchEvents.js b/src/theme/SearchBar/useTouchEvents.js index e1fdd74..456e416 100644 --- a/src/theme/SearchBar/useTouchEvents.js +++ b/src/theme/SearchBar/useTouchEvents.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React from "react" export function useTouchEvents({ getEnvironmentProps, @@ -8,21 +8,21 @@ export function useTouchEvents({ }) { React.useEffect(() => { if (!(panelElement && formElement && inputElement)) { - return undefined; + return undefined } const { onTouchStart, onTouchMove } = getEnvironmentProps({ panelElement, formElement, inputElement, - }); + }) - window.addEventListener('touchstart', onTouchStart); - window.addEventListener('touchmove', onTouchMove); + window.addEventListener("touchstart", onTouchStart) + window.addEventListener("touchmove", onTouchMove) return () => { - window.removeEventListener('touchstart', onTouchStart); - window.removeEventListener('touchmove', onTouchMove); - }; - }, [getEnvironmentProps, panelElement, formElement, inputElement]); + window.removeEventListener("touchstart", onTouchStart) + window.removeEventListener("touchmove", onTouchMove) + } + }, [getEnvironmentProps, panelElement, formElement, inputElement]) } diff --git a/src/theme/SearchBar/useTrapFocus.js b/src/theme/SearchBar/useTrapFocus.js index 16c2b25..5df25cf 100644 --- a/src/theme/SearchBar/useTrapFocus.js +++ b/src/theme/SearchBar/useTrapFocus.js @@ -1,37 +1,37 @@ -import React from 'react'; +import React from "react" export function useTrapFocus({ container }) { React.useEffect(() => { if (!container) { - return undefined; + return undefined } const focusableElements = container.querySelectorAll( - 'a[href]:not([disabled]), button:not([disabled]), input:not([disabled])' - ); - const firstElement = focusableElements[0]; - const lastElement = focusableElements[focusableElements.length - 1]; + "a[href]:not([disabled]), button:not([disabled]), input:not([disabled])" + ) + const firstElement = focusableElements[0] + const lastElement = focusableElements[focusableElements.length - 1] function trapFocus(event) { - if (event.key !== 'Tab') { - return; + if (event.key !== "Tab") { + return } if (event.shiftKey) { if (document.activeElement === firstElement) { - event.preventDefault(); - lastElement.focus(); + event.preventDefault() + lastElement.focus() } } else if (document.activeElement === lastElement) { - event.preventDefault(); - firstElement.focus(); + event.preventDefault() + firstElement.focus() } } - container.addEventListener('keydown', trapFocus); + container.addEventListener("keydown", trapFocus) return () => { - container.removeEventListener('keydown', trapFocus); - }; - }, [container]); + container.removeEventListener("keydown", trapFocus) + } + }, [container]) } diff --git a/src/theme/prism-include-languages.js b/src/theme/prism-include-languages.js index d7532ac..2ba1a18 100644 --- a/src/theme/prism-include-languages.js +++ b/src/theme/prism-include-languages.js @@ -4,27 +4,27 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; -import siteConfig from '@generated/docusaurus.config'; +import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment" +import siteConfig from "@generated/docusaurus.config" -const prismIncludeLanguages = (PrismObject) => { +const prismIncludeLanguages = PrismObject => { if (ExecutionEnvironment.canUseDOM) { const { themeConfig: { prism: { additionalLanguages = [] } = {} }, - } = siteConfig; - window.Prism = PrismObject; - additionalLanguages.forEach((lang) => { - require(`prismjs/components/prism-${lang}`); // eslint-disable-line - }); - require('prismjs/components/prism-kotlin'); - require('prismjs/components/prism-swift'); - require('prismjs/components/prism-java'); - require('prismjs/components/prism-dart'); - require('prismjs/components/prism-groovy'); - require('prismjs/components/prism-ruby'); - require('prismjs/components/prism-go'); - delete window.Prism; + } = siteConfig + window.Prism = PrismObject + additionalLanguages.forEach(lang => { + require(`prismjs/components/prism-${lang}`) // eslint-disable-line + }) + require("prismjs/components/prism-kotlin") + require("prismjs/components/prism-swift") + require("prismjs/components/prism-java") + require("prismjs/components/prism-dart") + require("prismjs/components/prism-groovy") + require("prismjs/components/prism-ruby") + require("prismjs/components/prism-go") + delete window.Prism } -}; +} -export default prismIncludeLanguages; +export default prismIncludeLanguages diff --git a/urls.js b/urls.js index dec90aa..2db559c 100644 --- a/urls.js +++ b/urls.js @@ -1,14 +1,14 @@ -const ROOT = 'https://getstream.io'; -const GITHUB_ROOT = 'https://github.com/GetStream'; +const ROOT = "https://getstream.io" +const GITHUB_ROOT = "https://github.com/GetStream" -const productVariables = require('./src/product-variables'); +const productVariables = require("./src/product-variables") -const PRODUCT = process.env.PRODUCT; -const { github } = productVariables[PRODUCT]; +const PRODUCT = process.env.PRODUCT +const { github } = productVariables[PRODUCT] module.exports = { docs: { - root: PRODUCT === 'video' ? '/video/docs/' : `/${PRODUCT}/docs/sdk/`, + root: PRODUCT === "video" ? "/video/docs/" : `/${PRODUCT}/docs/sdk/`, }, website: { root: `${ROOT}`, @@ -107,16 +107,16 @@ module.exports = { secondary: [ { contact: true, - label: 'Contact Sales', + label: "Contact Sales", href: `${ROOT}/contact/`, }, { contact: true, - label: 'Contact Support', + label: "Contact Support", href: `${ROOT}/contact/support/`, }, ], }, github_root: GITHUB_ROOT, github, -}; +} diff --git a/yarn.lock b/yarn.lock index 01146fd..a5b290d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -296,6 +296,15 @@ semver "^6.3.0" source-map "^0.5.0" +"@babel/generator@7.17.7": + version "7.17.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.7.tgz#8da2599beb4a86194a3b24df6c085931d9ee45ad" + integrity sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w== + dependencies: + "@babel/types" "^7.17.0" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/generator@^7.12.5", "@babel/generator@^7.15.0": version "7.15.0" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.0.tgz#a7d0c172e0d814974bad5aa77ace543b97917f15" @@ -323,6 +332,16 @@ jsesc "^2.5.1" source-map "^0.5.0" +"@babel/generator@^7.17.3": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.5.tgz#1e7bf768688acfb05cf30b2369ef855e82d984f7" + integrity sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA== + dependencies: + "@babel/types" "^7.22.5" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz#7bf478ec3b71726d56a8ca5775b046fc29879e61" @@ -802,6 +821,11 @@ dependencies: "@babel/types" "^7.16.7" +"@babel/helper-string-parser@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" + integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== + "@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.9": version "7.14.9" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48" @@ -817,6 +841,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== +"@babel/helper-validator-identifier@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" + integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== + "@babel/helper-validator-option@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" @@ -908,6 +937,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.7.tgz#d372dda9c89fcec340a82630a9f533f2fe15877e" integrity sha512-sR4eaSrnM7BV7QPzGfEX5paG/6wrZM3I0HDzfIAK06ESvo9oy3xBuVBxE3MbQaKNhvg8g/ixjMWo2CGpzpHsDA== +"@babel/parser@^7.17.3", "@babel/parser@^7.20.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.5.tgz#721fd042f3ce1896238cf1b341c77eb7dee7dbea" + integrity sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q== + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz#4eda6d6c2a0aa79c70fa7b6da67763dfe2141050" @@ -2134,6 +2168,22 @@ "@babel/parser" "^7.16.7" "@babel/types" "^7.16.7" +"@babel/traverse@7.17.3": + version "7.17.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57" + integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.3" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/parser" "^7.17.3" + "@babel/types" "^7.17.0" + debug "^4.1.0" + globals "^11.1.0" + "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.14.5", "@babel/traverse@^7.15.0": version "7.15.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.0.tgz#4cca838fd1b2a03283c1f38e141f639d60b3fc98" @@ -2180,6 +2230,14 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/types@7.17.0": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" + integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + to-fast-properties "^2.0.0" + "@babel/types@^7.12.7", "@babel/types@^7.14.5", "@babel/types@^7.14.8", "@babel/types@^7.15.0", "@babel/types@^7.4.4": version "7.15.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.0.tgz#61af11f2286c4e9c69ca8deb5f4375a73c72dcbd" @@ -2204,6 +2262,15 @@ "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" +"@babel/types@^7.17.0", "@babel/types@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe" + integrity sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA== + dependencies: + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.5" + to-fast-properties "^2.0.0" + "@docsearch/css@3.0.0-alpha.40": version "3.0.0-alpha.40" resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.0.0-alpha.40.tgz#c37bd7b03f4c30a6ea7a19b87fe71880d2e8b22a" @@ -2553,6 +2620,43 @@ dependencies: "@hapi/hoek" "^9.0.0" +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@1.4.14": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.18" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" + integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + "@mdx-js/mdx@1.6.22", "@mdx-js/mdx@^1.6.21", "@mdx-js/mdx@^1.6.22": version "1.6.22" resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-1.6.22.tgz#8a723157bf90e78f17dc0f27995398e6c731f1ba" @@ -2782,6 +2886,18 @@ dependencies: defer-to-connect "^1.0.1" +"@trivago/prettier-plugin-sort-imports@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.1.1.tgz#71c3c1ae770c3738b6fc85710714844477574ffd" + integrity sha512-dQ2r2uzNr1x6pJsuh/8x0IRA3CBUB+pWEW3J/7N98axqt7SQSm+2fy0FLNXvXGg77xEDC7KHxJlHfLYyi7PDcw== + dependencies: + "@babel/generator" "7.17.7" + "@babel/parser" "^7.20.5" + "@babel/traverse" "7.17.3" + "@babel/types" "7.17.0" + javascript-natural-sort "0.7.1" + lodash "^4.17.21" + "@trysound/sax@0.1.1": version "0.1.1" resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.1.1.tgz#3348564048e7a2d7398c935d466c0414ebb6a669" @@ -2898,6 +3014,11 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== +"@types/minimatch@^3.0.3": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" + integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== + "@types/node@*": version "16.7.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-16.7.1.tgz#c6b9198178da504dfca1fd0be9b2e1002f1586f0" @@ -3332,6 +3453,11 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +array-differ@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" + integrity sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg== + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -3347,6 +3473,11 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +arrify@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" + integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== + async@^2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" @@ -3730,6 +3861,14 @@ chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -4126,7 +4265,7 @@ cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: path-type "^4.0.0" yaml "^1.10.0" -cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -4774,6 +4913,21 @@ events@^3.2.0: resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== +execa@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -5062,7 +5216,7 @@ get-stream@^4.1.0: dependencies: pump "^3.0.0" -get-stream@^5.1.0: +get-stream@^5.0.0, get-stream@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== @@ -5527,11 +5681,21 @@ http-proxy@^1.18.1: follow-redirects "^1.0.0" requires-port "^1.0.0" +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +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" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -5871,6 +6035,11 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= +javascript-natural-sort@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59" + integrity sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw== + jest-worker@^27.0.2: version "27.0.6" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.0.6.tgz#a5fdb1e14ad34eb228cfe162d9f729cdbfa28aed" @@ -6387,6 +6556,11 @@ mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +mri@^1.1.5: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" + integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -6420,6 +6594,17 @@ multicast-dns@^6.0.1: dns-packet "^1.3.1" thunky "^1.0.2" +multimatch@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-4.0.0.tgz#8c3c0f6e3e8449ada0af3dd29efb491a375191b3" + integrity sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ== + dependencies: + "@types/minimatch" "^3.0.3" + array-differ "^3.0.0" + array-union "^2.1.0" + arrify "^2.0.1" + minimatch "^3.0.4" + nanoid@^3.1.23: version "3.1.25" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.25.tgz#09ca32747c0e543f0e1814b7d3793477f9c8e152" @@ -6495,7 +6680,7 @@ normalize-url@^6.0.1: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== -npm-run-path@^4.0.1: +npm-run-path@^4.0.0, npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== @@ -6573,7 +6758,7 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^5.1.2: +onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -7159,6 +7344,11 @@ prepend-http@^2.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= +prettier@^2.8.8: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== + pretty-error@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-3.0.4.tgz#94b1d54f76c1ed95b9c604b9de2194838e5b574e" @@ -7167,6 +7357,18 @@ pretty-error@^3.0.4: lodash "^4.17.20" renderkid "^2.0.6" +pretty-quick@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/pretty-quick/-/pretty-quick-3.1.3.tgz#15281108c0ddf446675157ca40240099157b638e" + integrity sha512-kOCi2FJabvuh1as9enxYmrnBC6tVMoVOenMaBqRfsvBHB0cbpYHjdQEpSglpASDFEXVwplpcGR4CLEaisYAFcA== + dependencies: + chalk "^3.0.0" + execa "^4.0.0" + find-up "^4.1.0" + ignore "^5.1.4" + mri "^1.1.5" + multimatch "^4.0.0" + pretty-time@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e"