mirror of
				https://github.com/NginxProxyManager/nginx-proxy-manager.git
				synced 2025-10-31 07:43:33 +00:00 
			
		
		
		
	Tidy up
- Add help docs for most sections - Add translations documentation - Fix up todos - Remove german translation
This commit is contained in:
		| @@ -8,14 +8,11 @@ | ||||
|  | ||||
| const allLocales = [ | ||||
| 	["en", "en-US"], | ||||
| 	["de", "de-DE"], | ||||
| 	["fa", "fa-IR"], | ||||
| ]; | ||||
|  | ||||
| const ignoreUnused = [ | ||||
| 	/^capability\..*$/, | ||||
| 	/^status\..*$/, | ||||
| 	/^type\..*$/, | ||||
| 	/^.*$/, | ||||
| ]; | ||||
|  | ||||
| const { spawnSync } = require("child_process"); | ||||
| @@ -119,20 +116,10 @@ const compareLocale = (locale) => { | ||||
| const checkForMissing = (locale) => { | ||||
| 	allKeys.forEach((key) => { | ||||
| 		if (typeof locale.data[key] === "undefined") { | ||||
| 			let ignored = false; | ||||
| 			ignoreMissing.map((regex) => { | ||||
| 				if (key.match(regex)) { | ||||
| 					ignored = true; | ||||
| 				} | ||||
| 				return null; | ||||
| 			}); | ||||
|  | ||||
| 			if (!ignored) { | ||||
| 			allWarnings.push( | ||||
| 				"WARN: `" + locale[0] + "` does not contain item: `" + key + "`", | ||||
| 			); | ||||
| 		} | ||||
| 		} | ||||
| 		return null; | ||||
| 	}); | ||||
| }; | ||||
|   | ||||
| @@ -33,6 +33,7 @@ | ||||
| 		"react-bootstrap": "^2.10.10", | ||||
| 		"react-dom": "^19.2.0", | ||||
| 		"react-intl": "^7.1.14", | ||||
| 		"react-markdown": "^10.1.0", | ||||
| 		"react-router-dom": "^7.9.4", | ||||
| 		"react-select": "^5.10.2", | ||||
| 		"react-toastify": "^11.0.5", | ||||
|   | ||||
| @@ -4,7 +4,6 @@ import type { AccessList } from "./models"; | ||||
| export async function createAccessList(item: AccessList): Promise<AccessList> { | ||||
| 	return await api.post({ | ||||
| 		url: "/nginx/access-lists", | ||||
| 		// todo: only use whitelist of fields for this data | ||||
| 		data: item, | ||||
| 	}); | ||||
| } | ||||
|   | ||||
| @@ -4,7 +4,6 @@ import type { DeadHost } from "./models"; | ||||
| export async function createDeadHost(item: DeadHost): Promise<DeadHost> { | ||||
| 	return await api.post({ | ||||
| 		url: "/nginx/dead-hosts", | ||||
| 		// todo: only use whitelist of fields for this data | ||||
| 		data: item, | ||||
| 	}); | ||||
| } | ||||
|   | ||||
| @@ -4,7 +4,6 @@ import type { ProxyHost } from "./models"; | ||||
| export async function createProxyHost(item: ProxyHost): Promise<ProxyHost> { | ||||
| 	return await api.post({ | ||||
| 		url: "/nginx/proxy-hosts", | ||||
| 		// todo: only use whitelist of fields for this data | ||||
| 		data: item, | ||||
| 	}); | ||||
| } | ||||
|   | ||||
| @@ -4,7 +4,6 @@ import type { RedirectionHost } from "./models"; | ||||
| export async function createRedirectionHost(item: RedirectionHost): Promise<RedirectionHost> { | ||||
| 	return await api.post({ | ||||
| 		url: "/nginx/redirection-hosts", | ||||
| 		// todo: only use whitelist of fields for this data | ||||
| 		data: item, | ||||
| 	}); | ||||
| } | ||||
|   | ||||
| @@ -4,7 +4,6 @@ import type { Stream } from "./models"; | ||||
| export async function createStream(item: Stream): Promise<Stream> { | ||||
| 	return await api.post({ | ||||
| 		url: "/nginx/streams", | ||||
| 		// todo: only use whitelist of fields for this data | ||||
| 		data: item, | ||||
| 	}); | ||||
| } | ||||
|   | ||||
| @@ -18,7 +18,6 @@ export interface NewUser { | ||||
| export async function createUser(item: NewUser, noAuth?: boolean): Promise<User> { | ||||
| 	return await api.post({ | ||||
| 		url: "/users", | ||||
| 		// todo: only use whitelist of fields for this data | ||||
| 		data: item, | ||||
| 		noAuth, | ||||
| 	}); | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| import { createIntl, createIntlCache } from "react-intl"; | ||||
| import langDe from "./lang/de.json"; | ||||
| import langEn from "./lang/en.json"; | ||||
| import langFa from "./lang/fa.json"; | ||||
| import langList from "./lang/lang-list.json"; | ||||
| @@ -9,15 +8,12 @@ import langList from "./lang/lang-list.json"; | ||||
| // Remember when adding to this list, also update check-locales.js script | ||||
| const localeOptions = [ | ||||
| 	["en", "en-US"], | ||||
| 	["de", "de-DE"], | ||||
| 	["fa", "fa-IR"], | ||||
| ]; | ||||
|  | ||||
| const loadMessages = (locale?: string): typeof langList & typeof langEn => { | ||||
| 	const thisLocale = locale || "en"; | ||||
| 	switch (thisLocale.slice(0, 2)) { | ||||
| 		case "de": | ||||
| 			return Object.assign({}, langList, langEn, langDe); | ||||
| 		case "fa": | ||||
| 			return Object.assign({}, langList, langEn, langFa); | ||||
| 		default: | ||||
| @@ -27,9 +23,6 @@ const loadMessages = (locale?: string): typeof langList & typeof langEn => { | ||||
|  | ||||
| const getFlagCodeForLocale = (locale?: string) => { | ||||
| 	switch (locale) { | ||||
| 		case "de-DE": | ||||
| 		case "de": | ||||
| 			return "DE"; | ||||
| 		case "fa-IR": | ||||
| 		case "fa": | ||||
| 			return "IR"; | ||||
|   | ||||
| @@ -1,23 +1,48 @@ | ||||
| # Internationalisation support | ||||
|  | ||||
| ## Before you start | ||||
|  | ||||
| It's highly recommended that you spin up a development instance of this project | ||||
| on your docker capable server. It's pretty easy: | ||||
|  | ||||
| ```bash | ||||
| git clone https://github.com/NginxProxyManager/nginx-proxy-manager.git | ||||
| cd nginx-proxy-manager | ||||
| ./scripts/start-dev -f | ||||
| ``` | ||||
|  | ||||
| Then after a while, you can access http://yourserverip:3081 | ||||
|  | ||||
| This stack will watch the file system for changes, especially to language files, | ||||
| and reload the site you have open in the browser. | ||||
|  | ||||
|  | ||||
| ## Adding new translations | ||||
|  | ||||
| Modify the files in the `src` folder. Follow the conventions already there. | ||||
|  | ||||
| When the development stack is running, it will sort the locale lang files | ||||
| for you when you save. | ||||
|  | ||||
|  | ||||
| ## After making changes | ||||
|  | ||||
| You will need to run `yarn locale-compile` in this frontend folder for | ||||
| If you're NOT running the development stack, you will need to run | ||||
| `yarn locale-compile` in the `frontend` folder for | ||||
| the new translations to be compiled into the `lang` folder. | ||||
|  | ||||
| When running in dev mode, this should automatically happen within Vite. | ||||
|  | ||||
| ## Adding a whole new language | ||||
|  | ||||
| There's a fair bit you'll need to touch. Here's a list that may | ||||
| not be complete by the time you're reading this: | ||||
|  | ||||
| - frontend/src/locale/src/[yourlang].json | ||||
| - frontend/src/locale/src/lang-list.json | ||||
| - frontend/src/locale/src/HelpDoc/* | ||||
| - frontend/src/locale/IntlProvider.tsx | ||||
|  | ||||
|  | ||||
| ## Checking for missing translations in other languages | ||||
| ## Checking for missing translations in languages | ||||
|  | ||||
| Run `node check-locales.cjs` in this frontend folder. | ||||
|  | ||||
|  | ||||
| ## Adding new languages | ||||
|  | ||||
| todo | ||||
|   | ||||
| @@ -1,3 +0,0 @@ | ||||
| { | ||||
|   "dashboard": "Armaturenbrett" | ||||
| } | ||||
| @@ -100,7 +100,11 @@ | ||||
|   "error.invalid-auth": "Invalid email or password", | ||||
|   "error.invalid-domain": "Invalid domain: {domain}", | ||||
|   "error.invalid-email": "Invalid email address", | ||||
|   "error.max-character-length": "Maximum length is {max} character{max, plural, one {} other {s}}", | ||||
|   "error.max-domains": "Too many domains, max is {max}", | ||||
|   "error.maximum": "Maximum is {max}", | ||||
|   "error.min-character-length": "Minimum length is {min} character{min, plural, one {} other {s}}", | ||||
|   "error.minimum": "Minimum is {min}", | ||||
|   "error.passwords-must-match": "Passwords must match", | ||||
|   "error.required": "This is required", | ||||
|   "expires.on": "Expires: {date}", | ||||
|   | ||||
							
								
								
									
										7
									
								
								frontend/src/locale/src/HelpDoc/en/AccessLists.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								frontend/src/locale/src/HelpDoc/en/AccessLists.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| ## What is an Access List? | ||||
|  | ||||
| Access Lists provide a blacklist or whitelist of specific client IP addresses along with authentication for the Proxy Hosts via Basic HTTP Authentication. | ||||
|  | ||||
| You can configure multiple client rules, usernames and passwords for a single Access List and then apply that to one or more _Proxy Hosts_. | ||||
|  | ||||
| This is most useful for forwarded web services that do not have authentication mechanisms built in or when you want to protect from unknown clients. | ||||
							
								
								
									
										32
									
								
								frontend/src/locale/src/HelpDoc/en/Certificates.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								frontend/src/locale/src/HelpDoc/en/Certificates.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| ## Certificates Help | ||||
|  | ||||
| ### HTTP Certificate | ||||
|  | ||||
| A HTTP validated certificate means Let's Encrypt servers will | ||||
| attempt to reach your domains over HTTP (not HTTPS!) and if successful, they | ||||
| will issue your certificate. | ||||
|  | ||||
| For this method, you will have to have a _Proxy Host_ created for your domains(s) that | ||||
| is accessible with HTTP and pointing to this Nginx installation. After a certificate | ||||
| has been given, you can modify the _Proxy Host_ to also use this certificate for HTTPS | ||||
| connections. However, the _Proxy Host_ will still need to be configured for HTTP access | ||||
| in order for the certificate to renew. | ||||
|  | ||||
| This process _does not_ support wildcard domains. | ||||
|  | ||||
| ### DNS Certificate | ||||
|  | ||||
| A DNS validated certificate requires you to use a DNS Provider plugin. This DNS | ||||
| Provider will be used to create temporary records on your domain and then Let's | ||||
| Encrypt will query those records to be sure you're the owner and if successful, they | ||||
| will issue your certificate. | ||||
|  | ||||
| You do not need a _Proxy Host_ to be created prior to requesting this type of | ||||
| certificate. Nor do you need to have your _Proxy Host_ configured for HTTP access. | ||||
|  | ||||
| This process _does_ support wildcard domains. | ||||
|  | ||||
| ### Custom Certificate | ||||
|  | ||||
| Use this option to upload your own SSL Certificate, as provided by your own | ||||
| Certificate Authority. | ||||
							
								
								
									
										10
									
								
								frontend/src/locale/src/HelpDoc/en/DeadHosts.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								frontend/src/locale/src/HelpDoc/en/DeadHosts.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| ## What is a 404 Host? | ||||
|  | ||||
| A 404 Host is simply a host setup that shows a 404 page. | ||||
|  | ||||
| This can be useful when your domain is listed in search engines and you want | ||||
| to provide a nicer error page or specifically to tell the search indexers that | ||||
| the domain pages no longer exist. | ||||
|  | ||||
| Another benefit of having this host is to track the logs for hits to it and | ||||
| view the referrers. | ||||
							
								
								
									
										7
									
								
								frontend/src/locale/src/HelpDoc/en/ProxyHosts.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								frontend/src/locale/src/HelpDoc/en/ProxyHosts.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| ## What is a Proxy Host? | ||||
|  | ||||
| A Proxy Host is the incoming endpoint for a web service that you want to forward. | ||||
|  | ||||
| It provides optional SSL termination for your service that might not have SSL support built in. | ||||
|  | ||||
| Proxy Hosts are the most common use for the Nginx Proxy Manager. | ||||
							
								
								
									
										7
									
								
								frontend/src/locale/src/HelpDoc/en/RedirectionHosts.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								frontend/src/locale/src/HelpDoc/en/RedirectionHosts.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| ## What is a Redirection Host? | ||||
|  | ||||
| A Redirection Host will redirect requests from the incoming domain and push the | ||||
| viewer to another domain. | ||||
|  | ||||
| The most common reason to use this type of host is when your website changes | ||||
| domains but you still have search engine or referrer links pointing to the old domain. | ||||
							
								
								
									
										6
									
								
								frontend/src/locale/src/HelpDoc/en/Streams.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								frontend/src/locale/src/HelpDoc/en/Streams.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| ## What is a Stream? | ||||
|  | ||||
| A relatively new feature for Nginx, a Stream will serve to forward TCP/UDP | ||||
| traffic directly to another computer on the network. | ||||
|  | ||||
| If you're running game servers, FTP or SSH servers this can come in handy. | ||||
							
								
								
									
										6
									
								
								frontend/src/locale/src/HelpDoc/en/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								frontend/src/locale/src/HelpDoc/en/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| export * as AccessLists from "./AccessLists.md"; | ||||
| export * as Certificates from "./Certificates.md"; | ||||
| export * as DeadHosts from "./DeadHosts.md"; | ||||
| export * as ProxyHosts from "./ProxyHosts.md"; | ||||
| export * as RedirectionHosts from "./RedirectionHosts.md"; | ||||
| export * as Streams from "./Streams.md"; | ||||
							
								
								
									
										20
									
								
								frontend/src/locale/src/HelpDoc/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								frontend/src/locale/src/HelpDoc/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| // import * as de from "./de/index"; | ||||
| // import * as fa from "./fa/index"; | ||||
| import * as en from "./en/index"; | ||||
|  | ||||
| const items: any = { en }; | ||||
|  | ||||
| const fallbackLang = "en"; | ||||
|  | ||||
| export const getHelpFile = (lang: string, section: string): string => { | ||||
| 	if (typeof items[lang] !== "undefined" && typeof items[lang][section] !== "undefined") { | ||||
| 		return items[lang][section].default; | ||||
| 	} | ||||
| 	// Fallback to English | ||||
| 	if (typeof items[fallbackLang] !== "undefined" && typeof items[fallbackLang][section] !== "undefined") { | ||||
| 		return items[fallbackLang][section].default; | ||||
| 	} | ||||
| 	throw new Error(`Cannot load help doc for ${lang}-${section}`); | ||||
| }; | ||||
|  | ||||
| export default items; | ||||
| @@ -1,5 +0,0 @@ | ||||
| { | ||||
| 	"dashboard": { | ||||
| 		"defaultMessage": "Armaturenbrett" | ||||
| 	} | ||||
| } | ||||
| @@ -302,9 +302,21 @@ | ||||
| 	"error.invalid-email": { | ||||
| 		"defaultMessage": "Invalid email address" | ||||
| 	}, | ||||
| 	"error.max-character-length": { | ||||
| 		"defaultMessage": "Maximum length is {max} character{max, plural, one {} other {s}}" | ||||
| 	}, | ||||
| 	"error.max-domains": { | ||||
| 		"defaultMessage": "Too many domains, max is {max}" | ||||
| 	}, | ||||
| 	"error.maximum": { | ||||
| 		"defaultMessage": "Maximum is {max}" | ||||
| 	}, | ||||
| 	"error.min-character-length": { | ||||
| 		"defaultMessage": "Minimum length is {min} character{min, plural, one {} other {s}}" | ||||
| 	}, | ||||
| 	"error.minimum": { | ||||
| 		"defaultMessage": "Minimum is {min}" | ||||
| 	}, | ||||
| 	"error.passwords-must-match": { | ||||
| 		"defaultMessage": "Passwords must match" | ||||
| 	}, | ||||
|   | ||||
| @@ -52,7 +52,27 @@ const DeleteConfirmModal = EasyModal.create( | ||||
| 					<Alert variant="danger" show={!!error} onClose={() => setError(null)} dismissible> | ||||
| 						{error} | ||||
| 					</Alert> | ||||
| 					{children} | ||||
| 					<div className="text-center mb-3"> | ||||
| 						<svg | ||||
| 							role="img" | ||||
| 							aria-label="warning icon" | ||||
| 							xmlns="http://www.w3.org/2000/svg" | ||||
| 							className="icon mb-2 text-danger icon-lg" | ||||
| 							width="24" | ||||
| 							height="24" | ||||
| 							viewBox="0 0 24 24" | ||||
| 							stroke-width="2" | ||||
| 							stroke="currentColor" | ||||
| 							fill="none" | ||||
| 							stroke-linecap="round" | ||||
| 							stroke-linejoin="round" | ||||
| 						> | ||||
| 							<path stroke="none" d="M0 0h24v24H0z" fill="none" /> | ||||
| 							<path d="M12 9v2m0 4v.01" /> | ||||
| 							<path d="M5 19h14a2 2 0 0 0 1.84 -2.75l-7.1 -12.25a2 2 0 0 0 -3.5 0l-7.1 12.25a2 2 0 0 0 1.75 2.75" /> | ||||
| 						</svg> | ||||
| 					</div> | ||||
| 					<div className="text-center mb-3">{children}</div> | ||||
| 				</Modal.Body> | ||||
| 				<Modal.Footer> | ||||
| 					<Button data-bs-dismiss="modal" onClick={remove} disabled={isSubmitting}> | ||||
|   | ||||
							
								
								
									
										54
									
								
								frontend/src/modals/HelpModal.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								frontend/src/modals/HelpModal.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| import cn from "classnames"; | ||||
| import EasyModal, { type InnerModalProps } from "ez-modal-react"; | ||||
| import { useEffect, useState } from "react"; | ||||
| import Modal from "react-bootstrap/Modal"; | ||||
| import ReactMarkdown from "react-markdown"; | ||||
| import { Button } from "src/components"; | ||||
| import { getLocale, T } from "src/locale"; | ||||
| import { getHelpFile } from "src/locale/src/HelpDoc"; | ||||
|  | ||||
| interface Props extends InnerModalProps { | ||||
| 	section: string; | ||||
| 	color?: string; | ||||
| } | ||||
|  | ||||
| const showHelpModal = (section: string, color?: string) => { | ||||
| 	EasyModal.show(HelpModal, { section, color }); | ||||
| }; | ||||
|  | ||||
| const HelpModal = EasyModal.create(({ section, color, visible, remove }: Props) => { | ||||
| 	const [markdownText, setMarkdownText] = useState(""); | ||||
| 	const lang = getLocale(true); | ||||
|  | ||||
| 	useEffect(() => { | ||||
| 		try { | ||||
| 			const docFile = getHelpFile(lang, section) as any; | ||||
| 			fetch(docFile) | ||||
| 				.then((response) => response.text()) | ||||
| 				.then(setMarkdownText); | ||||
| 		} catch (ex: any) { | ||||
| 			setMarkdownText(`**ERROR:** ${ex.message}`); | ||||
| 		} | ||||
| 	}, [lang, section]); | ||||
|  | ||||
| 	return ( | ||||
| 		<Modal show={visible} onHide={remove}> | ||||
| 			<Modal.Body> | ||||
| 				<ReactMarkdown>{markdownText}</ReactMarkdown> | ||||
| 			</Modal.Body> | ||||
| 			<Modal.Footer> | ||||
| 				<Button | ||||
| 					type="button" | ||||
| 					actionType="primary" | ||||
| 					className={cn("ms-auto", color ? `btn-${color}` : null)} | ||||
| 					data-bs-dismiss="modal" | ||||
| 					onClick={remove} | ||||
| 				> | ||||
| 					<T id="action.close" /> | ||||
| 				</Button> | ||||
| 			</Modal.Footer> | ||||
| 		</Modal> | ||||
| 	); | ||||
| }); | ||||
|  | ||||
| export { showHelpModal }; | ||||
| @@ -5,6 +5,7 @@ export * from "./DeadHostModal"; | ||||
| export * from "./DeleteConfirmModal"; | ||||
| export * from "./DNSCertificateModal"; | ||||
| export * from "./EventDetailsModal"; | ||||
| export * from "./HelpModal"; | ||||
| export * from "./HTTPCertificateModal"; | ||||
| export * from "./PermissionsModal"; | ||||
| export * from "./ProxyHostModal"; | ||||
|   | ||||
| @@ -11,12 +11,10 @@ const validateString = (minLength = 0, maxLength = 0) => { | ||||
| 			return intl.formatMessage({ id: "error.required" }); | ||||
| 		} | ||||
| 		if (minLength && value.length < minLength) { | ||||
| 			// TODO: i18n | ||||
| 			return `Minimum length is ${minLength} character${minLength === 1 ? "" : "s"}`; | ||||
| 			return intl.formatMessage({ id: "error.min-character-length" }, { min: minLength }); | ||||
| 		} | ||||
| 		if (maxLength && (typeof value === "undefined" || value.length > maxLength)) { | ||||
| 			// TODO: i18n | ||||
| 			return `Maximum length is ${maxLength} character${maxLength === 1 ? "" : "s"}`; | ||||
| 			return intl.formatMessage({ id: "error.max-character-length" }, { max: maxLength }); | ||||
| 		} | ||||
| 	}; | ||||
| }; | ||||
| @@ -33,12 +31,10 @@ const validateNumber = (min = -1, max = -1) => { | ||||
| 			return intl.formatMessage({ id: "error.required" }); | ||||
| 		} | ||||
| 		if (min > -1 && int < min) { | ||||
| 			// TODO: i18n | ||||
| 			return `Minimum is ${min}`; | ||||
| 			return intl.formatMessage({ id: "error.minimum" }, { min }); | ||||
| 		} | ||||
| 		if (max > -1 && int > max) { | ||||
| 			// TODO: i18n | ||||
| 			return `Maximum is ${max}`; | ||||
| 			return intl.formatMessage({ id: "error.maximum" }, { max }); | ||||
| 		} | ||||
| 	}; | ||||
| }; | ||||
|   | ||||
| @@ -53,7 +53,7 @@ export default function Table({ data, isFetching, isFiltered, onEdit, onDelete, | ||||
| 				cell: (info: any) => <T id="proxy-hosts.count" data={{ count: info.getValue() }} />, | ||||
| 			}), | ||||
| 			columnHelper.display({ | ||||
| 				id: "id", // todo: not needed for a display? | ||||
| 				id: "id", | ||||
| 				cell: (info: any) => { | ||||
| 					return ( | ||||
| 						<span className="dropdown"> | ||||
|   | ||||
| @@ -1,11 +1,11 @@ | ||||
| import { IconSearch } from "@tabler/icons-react"; | ||||
| import { IconHelp, IconSearch } from "@tabler/icons-react"; | ||||
| import { useState } from "react"; | ||||
| import Alert from "react-bootstrap/Alert"; | ||||
| import { deleteAccessList } from "src/api/backend"; | ||||
| import { Button, LoadingPage } from "src/components"; | ||||
| import { useAccessLists } from "src/hooks"; | ||||
| import { T } from "src/locale"; | ||||
| import { showAccessListModal, showDeleteConfirmModal } from "src/modals"; | ||||
| import { showAccessListModal, showDeleteConfirmModal, showHelpModal } from "src/modals"; | ||||
| import { showObjectSuccess } from "src/notifications"; | ||||
| import Table from "./Table"; | ||||
|  | ||||
| @@ -47,9 +47,10 @@ export default function TableWrapper() { | ||||
| 								<T id="access-lists" /> | ||||
| 							</h2> | ||||
| 						</div> | ||||
| 						{data?.length ? ( | ||||
|  | ||||
| 						<div className="col-md-auto col-sm-12"> | ||||
| 							<div className="ms-auto d-flex flex-wrap btn-list"> | ||||
| 								{data?.length ? ( | ||||
| 									<div className="input-group input-group-flat w-auto"> | ||||
| 										<span className="input-group-text input-group-text-sm"> | ||||
| 											<IconSearch size={16} /> | ||||
| @@ -62,14 +63,19 @@ export default function TableWrapper() { | ||||
| 											onChange={(e: any) => setSearch(e.target.value.toLowerCase().trim())} | ||||
| 										/> | ||||
| 									</div> | ||||
| 								) : null} | ||||
| 								<Button size="sm" onClick={() => showHelpModal("AccessLists", "cyan")}> | ||||
| 									<IconHelp size={20} /> | ||||
| 								</Button> | ||||
| 								{data?.length ? ( | ||||
| 									<Button size="sm" className="btn-cyan" onClick={() => showAccessListModal("new")}> | ||||
| 										<T id="object.add" tData={{ object: "access-list" }} /> | ||||
| 									</Button> | ||||
| 								</div> | ||||
| 							</div> | ||||
| 								) : null} | ||||
| 							</div> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 				<Table | ||||
| 					data={filtered ?? data ?? []} | ||||
| 					isFetching={isFetching} | ||||
| @@ -77,7 +83,7 @@ export default function TableWrapper() { | ||||
| 					onEdit={(id: number) => showAccessListModal(id)} | ||||
| 					onDelete={(id: number) => | ||||
| 						showDeleteConfirmModal({ | ||||
| 							title: "access.delete.title", | ||||
| 							title: <T id="object.delete" tData={{ object: "access-list" }} />, | ||||
| 							onConfirm: () => handleDelete(id), | ||||
| 							invalidations: [["access-lists"], ["access-list", id]], | ||||
| 							children: <T id="object.delete.content" tData={{ object: "access-list" }} />, | ||||
|   | ||||
| @@ -1,14 +1,15 @@ | ||||
| import { IconSearch } from "@tabler/icons-react"; | ||||
| import { IconHelp, IconSearch } from "@tabler/icons-react"; | ||||
| import { useState } from "react"; | ||||
| import Alert from "react-bootstrap/Alert"; | ||||
| import { deleteCertificate, downloadCertificate } from "src/api/backend"; | ||||
| import { LoadingPage } from "src/components"; | ||||
| import { Button, LoadingPage } from "src/components"; | ||||
| import { useCertificates } from "src/hooks"; | ||||
| import { T } from "src/locale"; | ||||
| import { | ||||
| 	showCustomCertificateModal, | ||||
| 	showDeleteConfirmModal, | ||||
| 	showDNSCertificateModal, | ||||
| 	showHelpModal, | ||||
| 	showHTTPCertificateModal, | ||||
| 	showRenewCertificateModal, | ||||
| } from "src/modals"; | ||||
| @@ -69,9 +70,10 @@ export default function TableWrapper() { | ||||
| 								<T id="certificates" /> | ||||
| 							</h2> | ||||
| 						</div> | ||||
| 						{data?.length ? ( | ||||
|  | ||||
| 						<div className="col-md-auto col-sm-12"> | ||||
| 							<div className="ms-auto d-flex flex-wrap btn-list"> | ||||
| 								{data?.length ? ( | ||||
| 									<div className="input-group input-group-flat w-auto"> | ||||
| 										<span className="input-group-text input-group-text-sm"> | ||||
| 											<IconSearch size={16} /> | ||||
| @@ -84,6 +86,11 @@ export default function TableWrapper() { | ||||
| 											onChange={(e: any) => setSearch(e.target.value.toLowerCase().trim())} | ||||
| 										/> | ||||
| 									</div> | ||||
| 								) : null} | ||||
| 								<Button size="sm" onClick={() => showHelpModal("Certificates", "pink")}> | ||||
| 									<IconHelp size={20} /> | ||||
| 								</Button> | ||||
| 								{data?.length ? ( | ||||
| 									<div className="dropdown"> | ||||
| 										<button | ||||
| 											type="button" | ||||
| @@ -126,11 +133,11 @@ export default function TableWrapper() { | ||||
| 											</a> | ||||
| 										</div> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 							</div> | ||||
| 								) : null} | ||||
| 							</div> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 				<Table | ||||
| 					data={filtered ?? data ?? []} | ||||
| 					isFiltered={!!search} | ||||
|   | ||||
| @@ -116,12 +116,7 @@ const Dashboard = () => { | ||||
| 				<code>{`Todo: | ||||
|  | ||||
| - check mobile | ||||
| - use statuses for table formatters where applicable: https://docs.tabler.io/ui/components/statuses | ||||
| - add help docs for host types | ||||
| - REDO SCREENSHOTS in docs folder | ||||
| - search codebase for "TODO" | ||||
| - update documentation to add development notes for translations | ||||
| - double check output of access field selection on proxy host dialog, after access lists are completed | ||||
| - check permissions in all places | ||||
|  | ||||
| More for api, then implement here: | ||||
|   | ||||
| @@ -58,7 +58,7 @@ export default function Table({ data, isFetching, onEdit, onDelete, onDisableTog | ||||
| 				}, | ||||
| 			}), | ||||
| 			columnHelper.display({ | ||||
| 				id: "id", // todo: not needed for a display? | ||||
| 				id: "id", | ||||
| 				cell: (info: any) => { | ||||
| 					return ( | ||||
| 						<span className="dropdown"> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { IconSearch } from "@tabler/icons-react"; | ||||
| import { IconHelp, IconSearch } from "@tabler/icons-react"; | ||||
| import { useQueryClient } from "@tanstack/react-query"; | ||||
| import { useState } from "react"; | ||||
| import Alert from "react-bootstrap/Alert"; | ||||
| @@ -6,7 +6,7 @@ import { deleteDeadHost, toggleDeadHost } from "src/api/backend"; | ||||
| import { Button, LoadingPage } from "src/components"; | ||||
| import { useDeadHosts } from "src/hooks"; | ||||
| import { T } from "src/locale"; | ||||
| import { showDeadHostModal, showDeleteConfirmModal } from "src/modals"; | ||||
| import { showDeadHostModal, showDeleteConfirmModal, showHelpModal } from "src/modals"; | ||||
| import { showObjectSuccess } from "src/notifications"; | ||||
| import Table from "./Table"; | ||||
|  | ||||
| @@ -56,9 +56,10 @@ export default function TableWrapper() { | ||||
| 								<T id="dead-hosts" /> | ||||
| 							</h2> | ||||
| 						</div> | ||||
| 						{data?.length ? ( | ||||
|  | ||||
| 						<div className="col-md-auto col-sm-12"> | ||||
| 							<div className="ms-auto d-flex flex-wrap btn-list"> | ||||
| 								{data?.length ? ( | ||||
| 									<div className="input-group input-group-flat w-auto"> | ||||
| 										<span className="input-group-text input-group-text-sm"> | ||||
| 											<IconSearch size={16} /> | ||||
| @@ -71,14 +72,19 @@ export default function TableWrapper() { | ||||
| 											onChange={(e: any) => setSearch(e.target.value.toLowerCase().trim())} | ||||
| 										/> | ||||
| 									</div> | ||||
| 								) : null} | ||||
| 								<Button size="sm" onClick={() => showHelpModal("DeadHosts", "red")}> | ||||
| 									<IconHelp size={20} /> | ||||
| 								</Button> | ||||
| 								{data?.length ? ( | ||||
| 									<Button size="sm" className="btn-red" onClick={() => showDeadHostModal("new")}> | ||||
| 										<T id="object.add" tData={{ object: "dead-host" }} /> | ||||
| 									</Button> | ||||
| 								</div> | ||||
| 							</div> | ||||
| 								) : null} | ||||
| 							</div> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 				<Table | ||||
| 					data={filtered ?? data ?? []} | ||||
| 					isFiltered={!!search} | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { IconSearch } from "@tabler/icons-react"; | ||||
| import { IconHelp, IconSearch } from "@tabler/icons-react"; | ||||
| import { useQueryClient } from "@tanstack/react-query"; | ||||
| import { useState } from "react"; | ||||
| import Alert from "react-bootstrap/Alert"; | ||||
| @@ -6,7 +6,7 @@ import { deleteProxyHost, toggleProxyHost } from "src/api/backend"; | ||||
| import { Button, LoadingPage } from "src/components"; | ||||
| import { useProxyHosts } from "src/hooks"; | ||||
| import { T } from "src/locale"; | ||||
| import { showDeleteConfirmModal, showProxyHostModal } from "src/modals"; | ||||
| import { showDeleteConfirmModal, showHelpModal, showProxyHostModal } from "src/modals"; | ||||
| import { showObjectSuccess } from "src/notifications"; | ||||
| import Table from "./Table"; | ||||
|  | ||||
| @@ -59,9 +59,10 @@ export default function TableWrapper() { | ||||
| 								<T id="proxy-hosts" /> | ||||
| 							</h2> | ||||
| 						</div> | ||||
| 						{data?.length ? ( | ||||
|  | ||||
| 						<div className="col-md-auto col-sm-12"> | ||||
| 							<div className="ms-auto d-flex flex-wrap btn-list"> | ||||
| 								{data?.length ? ( | ||||
| 									<div className="input-group input-group-flat w-auto"> | ||||
| 										<span className="input-group-text input-group-text-sm"> | ||||
| 											<IconSearch size={16} /> | ||||
| @@ -74,14 +75,19 @@ export default function TableWrapper() { | ||||
| 											onChange={(e: any) => setSearch(e.target.value.toLowerCase().trim())} | ||||
| 										/> | ||||
| 									</div> | ||||
| 								) : null} | ||||
| 								<Button size="sm" onClick={() => showHelpModal("ProxyHosts", "lime")}> | ||||
| 									<IconHelp size={20} /> | ||||
| 								</Button> | ||||
| 								{data?.length ? ( | ||||
| 									<Button size="sm" className="btn-lime" onClick={() => showProxyHostModal("new")}> | ||||
| 										<T id="object.add" tData={{ object: "proxy-host" }} /> | ||||
| 									</Button> | ||||
| 								</div> | ||||
| 							</div> | ||||
| 								) : null} | ||||
| 							</div> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 				<Table | ||||
| 					data={filtered ?? data ?? []} | ||||
| 					isFiltered={!!search} | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { IconSearch } from "@tabler/icons-react"; | ||||
| import { IconHelp, IconSearch } from "@tabler/icons-react"; | ||||
| import { useQueryClient } from "@tanstack/react-query"; | ||||
| import { useState } from "react"; | ||||
| import Alert from "react-bootstrap/Alert"; | ||||
| @@ -6,7 +6,7 @@ import { deleteRedirectionHost, toggleRedirectionHost } from "src/api/backend"; | ||||
| import { Button, LoadingPage } from "src/components"; | ||||
| import { useRedirectionHosts } from "src/hooks"; | ||||
| import { T } from "src/locale"; | ||||
| import { showDeleteConfirmModal, showRedirectionHostModal } from "src/modals"; | ||||
| import { showDeleteConfirmModal, showHelpModal, showRedirectionHostModal } from "src/modals"; | ||||
| import { showObjectSuccess } from "src/notifications"; | ||||
| import Table from "./Table"; | ||||
|  | ||||
| @@ -59,9 +59,10 @@ export default function TableWrapper() { | ||||
| 								<T id="redirection-hosts" /> | ||||
| 							</h2> | ||||
| 						</div> | ||||
| 						{data?.length ? ( | ||||
|  | ||||
| 						<div className="col-md-auto col-sm-12"> | ||||
| 							<div className="ms-auto d-flex flex-wrap btn-list"> | ||||
| 								{data?.length ? ( | ||||
| 									<div className="input-group input-group-flat w-auto"> | ||||
| 										<span className="input-group-text input-group-text-sm"> | ||||
| 											<IconSearch size={16} /> | ||||
| @@ -74,6 +75,11 @@ export default function TableWrapper() { | ||||
| 											onChange={(e: any) => setSearch(e.target.value.toLowerCase().trim())} | ||||
| 										/> | ||||
| 									</div> | ||||
| 								) : null} | ||||
| 								<Button size="sm" onClick={() => showHelpModal("RedirectionHosts", "yellow")}> | ||||
| 									<IconHelp size={20} /> | ||||
| 								</Button> | ||||
| 								{data?.length ? ( | ||||
| 									<Button | ||||
| 										size="sm" | ||||
| 										className="btn-yellow" | ||||
| @@ -81,11 +87,11 @@ export default function TableWrapper() { | ||||
| 									> | ||||
| 										<T id="object.add" tData={{ object: "redirection-host" }} /> | ||||
| 									</Button> | ||||
| 								</div> | ||||
| 							</div> | ||||
| 								) : null} | ||||
| 							</div> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 				<Table | ||||
| 					data={filtered ?? data ?? []} | ||||
| 					isFiltered={!!search} | ||||
|   | ||||
| @@ -87,7 +87,7 @@ export default function Table({ data, isFetching, isFiltered, onEdit, onDelete, | ||||
| 				}, | ||||
| 			}), | ||||
| 			columnHelper.display({ | ||||
| 				id: "id", // todo: not needed for a display? | ||||
| 				id: "id", | ||||
| 				cell: (info: any) => { | ||||
| 					return ( | ||||
| 						<span className="dropdown"> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { IconSearch } from "@tabler/icons-react"; | ||||
| import { IconHelp, IconSearch } from "@tabler/icons-react"; | ||||
| import { useQueryClient } from "@tanstack/react-query"; | ||||
| import { useState } from "react"; | ||||
| import Alert from "react-bootstrap/Alert"; | ||||
| @@ -6,7 +6,7 @@ import { deleteStream, toggleStream } from "src/api/backend"; | ||||
| import { Button, LoadingPage } from "src/components"; | ||||
| import { useStreams } from "src/hooks"; | ||||
| import { T } from "src/locale"; | ||||
| import { showDeleteConfirmModal, showStreamModal } from "src/modals"; | ||||
| import { showDeleteConfirmModal, showHelpModal, showStreamModal } from "src/modals"; | ||||
| import { showObjectSuccess } from "src/notifications"; | ||||
| import Table from "./Table"; | ||||
|  | ||||
| @@ -61,9 +61,10 @@ export default function TableWrapper() { | ||||
| 								<T id="streams" /> | ||||
| 							</h2> | ||||
| 						</div> | ||||
| 						{data?.length ? ( | ||||
|  | ||||
| 						<div className="col-md-auto col-sm-12"> | ||||
| 							<div className="ms-auto d-flex flex-wrap btn-list"> | ||||
| 								{data?.length ? ( | ||||
| 									<div className="input-group input-group-flat w-auto"> | ||||
| 										<span className="input-group-text input-group-text-sm"> | ||||
| 											<IconSearch size={16} /> | ||||
| @@ -76,14 +77,19 @@ export default function TableWrapper() { | ||||
| 											onChange={(e: any) => setSearch(e.target.value.toLowerCase().trim())} | ||||
| 										/> | ||||
| 									</div> | ||||
| 								) : null} | ||||
| 								<Button size="sm" onClick={() => showHelpModal("Streams", "blue")}> | ||||
| 									<IconHelp size={20} /> | ||||
| 								</Button> | ||||
| 								{data?.length ? ( | ||||
| 									<Button size="sm" className="btn-blue" onClick={() => showStreamModal("new")}> | ||||
| 										<T id="object.add" tData={{ object: "stream" }} /> | ||||
| 									</Button> | ||||
| 								</div> | ||||
| 							</div> | ||||
| 								) : null} | ||||
| 							</div> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 				<Table | ||||
| 					data={filtered ?? data ?? []} | ||||
| 					isFetching={isFetching} | ||||
|   | ||||
| @@ -47,4 +47,5 @@ export default defineConfig({ | ||||
| 		environment: "happy-dom", | ||||
| 		setupFiles: ["./vitest-setup.js"], | ||||
| 	}, | ||||
| 	assetsInclude: ["**/*.md", "**/*.png", "**/*.svg"], | ||||
| }); | ||||
|   | ||||
| @@ -977,12 +977,26 @@ | ||||
|   resolved "https://registry.yarnpkg.com/@types/country-flag-icons/-/country-flag-icons-1.2.2.tgz#8f51089cab857f0f700feabd38b3960d006d64f2" | ||||
|   integrity sha512-CefEn/J336TBDp7NX8JqzlDtCBOsm8M3r1Li0gEOt0HOMHF1XemNyrx9lSHjsafcb1yYWybU0N8ZAXuyCaND0w== | ||||
|  | ||||
| "@types/debug@^4.0.0": | ||||
|   version "4.1.12" | ||||
|   resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" | ||||
|   integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ== | ||||
|   dependencies: | ||||
|     "@types/ms" "*" | ||||
|  | ||||
| "@types/deep-eql@*": | ||||
|   version "4.0.2" | ||||
|   resolved "https://registry.yarnpkg.com/@types/deep-eql/-/deep-eql-4.0.2.tgz#334311971d3a07121e7eb91b684a605e7eea9cbd" | ||||
|   integrity sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw== | ||||
|  | ||||
| "@types/estree@1.0.8", "@types/estree@^1.0.0": | ||||
| "@types/estree-jsx@^1.0.0": | ||||
|   version "1.0.5" | ||||
|   resolved "https://registry.yarnpkg.com/@types/estree-jsx/-/estree-jsx-1.0.5.tgz#858a88ea20f34fe65111f005a689fa1ebf70dc18" | ||||
|   integrity sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg== | ||||
|   dependencies: | ||||
|     "@types/estree" "*" | ||||
|  | ||||
| "@types/estree@*", "@types/estree@1.0.8", "@types/estree@^1.0.0": | ||||
|   version "1.0.8" | ||||
|   resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" | ||||
|   integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== | ||||
| @@ -1020,6 +1034,11 @@ | ||||
|   dependencies: | ||||
|     "@types/unist" "*" | ||||
|  | ||||
| "@types/ms@*": | ||||
|   version "2.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/@types/ms/-/ms-2.1.0.tgz#052aa67a48eccc4309d7f0191b7e41434b90bb78" | ||||
|   integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== | ||||
|  | ||||
| "@types/node@^20.0.0": | ||||
|   version "20.19.11" | ||||
|   resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.11.tgz#728cab53092bd5f143beed7fbba7ba99de3c16c4" | ||||
| @@ -1356,6 +1375,13 @@ date-fns@^4.1.0: | ||||
|   resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-4.1.0.tgz#64b3d83fff5aa80438f5b1a633c2e83b8a1c2d14" | ||||
|   integrity sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg== | ||||
|  | ||||
| debug@^4.0.0, debug@^4.4.3: | ||||
|   version "4.4.3" | ||||
|   resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" | ||||
|   integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== | ||||
|   dependencies: | ||||
|     ms "^2.1.3" | ||||
|  | ||||
| debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: | ||||
|   version "4.4.1" | ||||
|   resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" | ||||
| @@ -1363,13 +1389,6 @@ debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: | ||||
|   dependencies: | ||||
|     ms "^2.1.3" | ||||
|  | ||||
| debug@^4.4.3: | ||||
|   version "4.4.3" | ||||
|   resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" | ||||
|   integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== | ||||
|   dependencies: | ||||
|     ms "^2.1.3" | ||||
|  | ||||
| decimal.js@^10.4.3: | ||||
|   version "10.6.0" | ||||
|   resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.6.0.tgz#e649a43e3ab953a72192ff5983865e509f37ed9a" | ||||
| @@ -1491,6 +1510,11 @@ escape-string-regexp@^4.0.0: | ||||
|   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" | ||||
|   integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== | ||||
|  | ||||
| estree-util-is-identifier-name@^3.0.0: | ||||
|   version "3.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz#0b5ef4c4ff13508b34dcd01ecfa945f61fce5dbd" | ||||
|   integrity sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg== | ||||
|  | ||||
| estree-walker@^3.0.3: | ||||
|   version "3.0.3" | ||||
|   resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" | ||||
| @@ -1655,6 +1679,27 @@ hast-util-to-html@^9.0.0: | ||||
|     stringify-entities "^4.0.0" | ||||
|     zwitch "^2.0.4" | ||||
|  | ||||
| hast-util-to-jsx-runtime@^2.0.0: | ||||
|   version "2.3.6" | ||||
|   resolved "https://registry.yarnpkg.com/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz#ff31897aae59f62232e21594eac7ef6b63333e98" | ||||
|   integrity sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg== | ||||
|   dependencies: | ||||
|     "@types/estree" "^1.0.0" | ||||
|     "@types/hast" "^3.0.0" | ||||
|     "@types/unist" "^3.0.0" | ||||
|     comma-separated-tokens "^2.0.0" | ||||
|     devlop "^1.0.0" | ||||
|     estree-util-is-identifier-name "^3.0.0" | ||||
|     hast-util-whitespace "^3.0.0" | ||||
|     mdast-util-mdx-expression "^2.0.0" | ||||
|     mdast-util-mdx-jsx "^3.0.0" | ||||
|     mdast-util-mdxjs-esm "^2.0.0" | ||||
|     property-information "^7.0.0" | ||||
|     space-separated-tokens "^2.0.0" | ||||
|     style-to-js "^1.0.0" | ||||
|     unist-util-position "^5.0.0" | ||||
|     vfile-message "^4.0.0" | ||||
|  | ||||
| hast-util-to-string@^3.0.0: | ||||
|   version "3.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz#a4f15e682849326dd211c97129c94b0c3e76527c" | ||||
| @@ -1698,6 +1743,11 @@ hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react- | ||||
|   dependencies: | ||||
|     react-is "^16.7.0" | ||||
|  | ||||
| html-url-attributes@^3.0.0: | ||||
|   version "3.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/html-url-attributes/-/html-url-attributes-3.0.1.tgz#83b052cd5e437071b756cd74ae70f708870c2d87" | ||||
|   integrity sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ== | ||||
|  | ||||
| html-void-elements@^3.0.0: | ||||
|   version "3.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-3.0.0.tgz#fc9dbd84af9e747249034d4d62602def6517f1d7" | ||||
| @@ -1731,6 +1781,11 @@ indent-string@^4.0.0: | ||||
|   resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" | ||||
|   integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== | ||||
|  | ||||
| inline-style-parser@0.2.4: | ||||
|   version "0.2.4" | ||||
|   resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.2.4.tgz#f4af5fe72e612839fcd453d989a586566d695f22" | ||||
|   integrity sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q== | ||||
|  | ||||
| intl-messageformat@10.7.18: | ||||
|   version "10.7.18" | ||||
|   resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.7.18.tgz#51a6f387afbca9b0f881b2ec081566db8c540b0d" | ||||
| @@ -1845,6 +1900,11 @@ lodash@^4.17.21: | ||||
|   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" | ||||
|   integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== | ||||
|  | ||||
| longest-streak@^3.0.0: | ||||
|   version "3.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.1.0.tgz#62fa67cd958742a1574af9f39866364102d90cd4" | ||||
|   integrity sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g== | ||||
|  | ||||
| loose-envify@^1.0.0, loose-envify@^1.4.0: | ||||
|   version "1.4.0" | ||||
|   resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" | ||||
| @@ -1871,6 +1931,74 @@ magic-string@^0.30.19: | ||||
|   dependencies: | ||||
|     "@jridgewell/sourcemap-codec" "^1.5.5" | ||||
|  | ||||
| mdast-util-from-markdown@^2.0.0: | ||||
|   version "2.0.2" | ||||
|   resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz#4850390ca7cf17413a9b9a0fbefcd1bc0eb4160a" | ||||
|   integrity sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA== | ||||
|   dependencies: | ||||
|     "@types/mdast" "^4.0.0" | ||||
|     "@types/unist" "^3.0.0" | ||||
|     decode-named-character-reference "^1.0.0" | ||||
|     devlop "^1.0.0" | ||||
|     mdast-util-to-string "^4.0.0" | ||||
|     micromark "^4.0.0" | ||||
|     micromark-util-decode-numeric-character-reference "^2.0.0" | ||||
|     micromark-util-decode-string "^2.0.0" | ||||
|     micromark-util-normalize-identifier "^2.0.0" | ||||
|     micromark-util-symbol "^2.0.0" | ||||
|     micromark-util-types "^2.0.0" | ||||
|     unist-util-stringify-position "^4.0.0" | ||||
|  | ||||
| mdast-util-mdx-expression@^2.0.0: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz#43f0abac9adc756e2086f63822a38c8d3c3a5096" | ||||
|   integrity sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ== | ||||
|   dependencies: | ||||
|     "@types/estree-jsx" "^1.0.0" | ||||
|     "@types/hast" "^3.0.0" | ||||
|     "@types/mdast" "^4.0.0" | ||||
|     devlop "^1.0.0" | ||||
|     mdast-util-from-markdown "^2.0.0" | ||||
|     mdast-util-to-markdown "^2.0.0" | ||||
|  | ||||
| mdast-util-mdx-jsx@^3.0.0: | ||||
|   version "3.2.0" | ||||
|   resolved "https://registry.yarnpkg.com/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz#fd04c67a2a7499efb905a8a5c578dddc9fdada0d" | ||||
|   integrity sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q== | ||||
|   dependencies: | ||||
|     "@types/estree-jsx" "^1.0.0" | ||||
|     "@types/hast" "^3.0.0" | ||||
|     "@types/mdast" "^4.0.0" | ||||
|     "@types/unist" "^3.0.0" | ||||
|     ccount "^2.0.0" | ||||
|     devlop "^1.1.0" | ||||
|     mdast-util-from-markdown "^2.0.0" | ||||
|     mdast-util-to-markdown "^2.0.0" | ||||
|     parse-entities "^4.0.0" | ||||
|     stringify-entities "^4.0.0" | ||||
|     unist-util-stringify-position "^4.0.0" | ||||
|     vfile-message "^4.0.0" | ||||
|  | ||||
| mdast-util-mdxjs-esm@^2.0.0: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz#019cfbe757ad62dd557db35a695e7314bcc9fa97" | ||||
|   integrity sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg== | ||||
|   dependencies: | ||||
|     "@types/estree-jsx" "^1.0.0" | ||||
|     "@types/hast" "^3.0.0" | ||||
|     "@types/mdast" "^4.0.0" | ||||
|     devlop "^1.0.0" | ||||
|     mdast-util-from-markdown "^2.0.0" | ||||
|     mdast-util-to-markdown "^2.0.0" | ||||
|  | ||||
| mdast-util-phrasing@^4.0.0: | ||||
|   version "4.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz#7cc0a8dec30eaf04b7b1a9661a92adb3382aa6e3" | ||||
|   integrity sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w== | ||||
|   dependencies: | ||||
|     "@types/mdast" "^4.0.0" | ||||
|     unist-util-is "^6.0.0" | ||||
|  | ||||
| mdast-util-to-hast@^13.0.0: | ||||
|   version "13.2.0" | ||||
|   resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz#5ca58e5b921cc0a3ded1bc02eed79a4fe4fe41f4" | ||||
| @@ -1886,11 +2014,102 @@ mdast-util-to-hast@^13.0.0: | ||||
|     unist-util-visit "^5.0.0" | ||||
|     vfile "^6.0.0" | ||||
|  | ||||
| mdast-util-to-markdown@^2.0.0: | ||||
|   version "2.1.2" | ||||
|   resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz#f910ffe60897f04bb4b7e7ee434486f76288361b" | ||||
|   integrity sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA== | ||||
|   dependencies: | ||||
|     "@types/mdast" "^4.0.0" | ||||
|     "@types/unist" "^3.0.0" | ||||
|     longest-streak "^3.0.0" | ||||
|     mdast-util-phrasing "^4.0.0" | ||||
|     mdast-util-to-string "^4.0.0" | ||||
|     micromark-util-classify-character "^2.0.0" | ||||
|     micromark-util-decode-string "^2.0.0" | ||||
|     unist-util-visit "^5.0.0" | ||||
|     zwitch "^2.0.0" | ||||
|  | ||||
| mdast-util-to-string@^4.0.0: | ||||
|   version "4.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz#7a5121475556a04e7eddeb67b264aae79d312814" | ||||
|   integrity sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg== | ||||
|   dependencies: | ||||
|     "@types/mdast" "^4.0.0" | ||||
|  | ||||
| memoize-one@^6.0.0: | ||||
|   version "6.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045" | ||||
|   integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw== | ||||
|  | ||||
| micromark-core-commonmark@^2.0.0: | ||||
|   version "2.0.3" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz#c691630e485021a68cf28dbc2b2ca27ebf678cd4" | ||||
|   integrity sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg== | ||||
|   dependencies: | ||||
|     decode-named-character-reference "^1.0.0" | ||||
|     devlop "^1.0.0" | ||||
|     micromark-factory-destination "^2.0.0" | ||||
|     micromark-factory-label "^2.0.0" | ||||
|     micromark-factory-space "^2.0.0" | ||||
|     micromark-factory-title "^2.0.0" | ||||
|     micromark-factory-whitespace "^2.0.0" | ||||
|     micromark-util-character "^2.0.0" | ||||
|     micromark-util-chunked "^2.0.0" | ||||
|     micromark-util-classify-character "^2.0.0" | ||||
|     micromark-util-html-tag-name "^2.0.0" | ||||
|     micromark-util-normalize-identifier "^2.0.0" | ||||
|     micromark-util-resolve-all "^2.0.0" | ||||
|     micromark-util-subtokenize "^2.0.0" | ||||
|     micromark-util-symbol "^2.0.0" | ||||
|     micromark-util-types "^2.0.0" | ||||
|  | ||||
| micromark-factory-destination@^2.0.0: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz#8fef8e0f7081f0474fbdd92deb50c990a0264639" | ||||
|   integrity sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA== | ||||
|   dependencies: | ||||
|     micromark-util-character "^2.0.0" | ||||
|     micromark-util-symbol "^2.0.0" | ||||
|     micromark-util-types "^2.0.0" | ||||
|  | ||||
| micromark-factory-label@^2.0.0: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz#5267efa97f1e5254efc7f20b459a38cb21058ba1" | ||||
|   integrity sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg== | ||||
|   dependencies: | ||||
|     devlop "^1.0.0" | ||||
|     micromark-util-character "^2.0.0" | ||||
|     micromark-util-symbol "^2.0.0" | ||||
|     micromark-util-types "^2.0.0" | ||||
|  | ||||
| micromark-factory-space@^2.0.0: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz#36d0212e962b2b3121f8525fc7a3c7c029f334fc" | ||||
|   integrity sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg== | ||||
|   dependencies: | ||||
|     micromark-util-character "^2.0.0" | ||||
|     micromark-util-types "^2.0.0" | ||||
|  | ||||
| micromark-factory-title@^2.0.0: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz#237e4aa5d58a95863f01032d9ee9b090f1de6e94" | ||||
|   integrity sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw== | ||||
|   dependencies: | ||||
|     micromark-factory-space "^2.0.0" | ||||
|     micromark-util-character "^2.0.0" | ||||
|     micromark-util-symbol "^2.0.0" | ||||
|     micromark-util-types "^2.0.0" | ||||
|  | ||||
| micromark-factory-whitespace@^2.0.0: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz#06b26b2983c4d27bfcc657b33e25134d4868b0b1" | ||||
|   integrity sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ== | ||||
|   dependencies: | ||||
|     micromark-factory-space "^2.0.0" | ||||
|     micromark-util-character "^2.0.0" | ||||
|     micromark-util-symbol "^2.0.0" | ||||
|     micromark-util-types "^2.0.0" | ||||
|  | ||||
| micromark-util-character@^2.0.0: | ||||
|   version "2.1.1" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-2.1.1.tgz#2f987831a40d4c510ac261e89852c4e9703ccda6" | ||||
| @@ -1899,11 +2118,71 @@ micromark-util-character@^2.0.0: | ||||
|     micromark-util-symbol "^2.0.0" | ||||
|     micromark-util-types "^2.0.0" | ||||
|  | ||||
| micromark-util-chunked@^2.0.0: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz#47fbcd93471a3fccab86cff03847fc3552db1051" | ||||
|   integrity sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA== | ||||
|   dependencies: | ||||
|     micromark-util-symbol "^2.0.0" | ||||
|  | ||||
| micromark-util-classify-character@^2.0.0: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz#d399faf9c45ca14c8b4be98b1ea481bced87b629" | ||||
|   integrity sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q== | ||||
|   dependencies: | ||||
|     micromark-util-character "^2.0.0" | ||||
|     micromark-util-symbol "^2.0.0" | ||||
|     micromark-util-types "^2.0.0" | ||||
|  | ||||
| micromark-util-combine-extensions@^2.0.0: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz#2a0f490ab08bff5cc2fd5eec6dd0ca04f89b30a9" | ||||
|   integrity sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg== | ||||
|   dependencies: | ||||
|     micromark-util-chunked "^2.0.0" | ||||
|     micromark-util-types "^2.0.0" | ||||
|  | ||||
| micromark-util-decode-numeric-character-reference@^2.0.0: | ||||
|   version "2.0.2" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz#fcf15b660979388e6f118cdb6bf7d79d73d26fe5" | ||||
|   integrity sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw== | ||||
|   dependencies: | ||||
|     micromark-util-symbol "^2.0.0" | ||||
|  | ||||
| micromark-util-decode-string@^2.0.0: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz#6cb99582e5d271e84efca8e61a807994d7161eb2" | ||||
|   integrity sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ== | ||||
|   dependencies: | ||||
|     decode-named-character-reference "^1.0.0" | ||||
|     micromark-util-character "^2.0.0" | ||||
|     micromark-util-decode-numeric-character-reference "^2.0.0" | ||||
|     micromark-util-symbol "^2.0.0" | ||||
|  | ||||
| micromark-util-encode@^2.0.0: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz#0d51d1c095551cfaac368326963cf55f15f540b8" | ||||
|   integrity sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw== | ||||
|  | ||||
| micromark-util-html-tag-name@^2.0.0: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz#e40403096481986b41c106627f98f72d4d10b825" | ||||
|   integrity sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA== | ||||
|  | ||||
| micromark-util-normalize-identifier@^2.0.0: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz#c30d77b2e832acf6526f8bf1aa47bc9c9438c16d" | ||||
|   integrity sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q== | ||||
|   dependencies: | ||||
|     micromark-util-symbol "^2.0.0" | ||||
|  | ||||
| micromark-util-resolve-all@^2.0.0: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz#e1a2d62cdd237230a2ae11839027b19381e31e8b" | ||||
|   integrity sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg== | ||||
|   dependencies: | ||||
|     micromark-util-types "^2.0.0" | ||||
|  | ||||
| micromark-util-sanitize-uri@^2.0.0: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz#ab89789b818a58752b73d6b55238621b7faa8fd7" | ||||
| @@ -1913,6 +2192,16 @@ micromark-util-sanitize-uri@^2.0.0: | ||||
|     micromark-util-encode "^2.0.0" | ||||
|     micromark-util-symbol "^2.0.0" | ||||
|  | ||||
| micromark-util-subtokenize@^2.0.0: | ||||
|   version "2.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz#d8ade5ba0f3197a1cf6a2999fbbfe6357a1a19ee" | ||||
|   integrity sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA== | ||||
|   dependencies: | ||||
|     devlop "^1.0.0" | ||||
|     micromark-util-chunked "^2.0.0" | ||||
|     micromark-util-symbol "^2.0.0" | ||||
|     micromark-util-types "^2.0.0" | ||||
|  | ||||
| micromark-util-symbol@^2.0.0: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz#e5da494e8eb2b071a0d08fb34f6cefec6c0a19b8" | ||||
| @@ -1923,6 +2212,29 @@ micromark-util-types@^2.0.0: | ||||
|   resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-2.0.2.tgz#f00225f5f5a0ebc3254f96c36b6605c4b393908e" | ||||
|   integrity sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA== | ||||
|  | ||||
| micromark@^4.0.0: | ||||
|   version "4.0.2" | ||||
|   resolved "https://registry.yarnpkg.com/micromark/-/micromark-4.0.2.tgz#91395a3e1884a198e62116e33c9c568e39936fdb" | ||||
|   integrity sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA== | ||||
|   dependencies: | ||||
|     "@types/debug" "^4.0.0" | ||||
|     debug "^4.0.0" | ||||
|     decode-named-character-reference "^1.0.0" | ||||
|     devlop "^1.0.0" | ||||
|     micromark-core-commonmark "^2.0.0" | ||||
|     micromark-factory-space "^2.0.0" | ||||
|     micromark-util-character "^2.0.0" | ||||
|     micromark-util-chunked "^2.0.0" | ||||
|     micromark-util-combine-extensions "^2.0.0" | ||||
|     micromark-util-decode-numeric-character-reference "^2.0.0" | ||||
|     micromark-util-encode "^2.0.0" | ||||
|     micromark-util-normalize-identifier "^2.0.0" | ||||
|     micromark-util-resolve-all "^2.0.0" | ||||
|     micromark-util-sanitize-uri "^2.0.0" | ||||
|     micromark-util-subtokenize "^2.0.0" | ||||
|     micromark-util-symbol "^2.0.0" | ||||
|     micromark-util-types "^2.0.0" | ||||
|  | ||||
| micromatch@^4.0.5: | ||||
|   version "4.0.8" | ||||
|   resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" | ||||
| @@ -2184,6 +2496,23 @@ react-lifecycles-compat@^3.0.4: | ||||
|   resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" | ||||
|   integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== | ||||
|  | ||||
| react-markdown@^10.1.0: | ||||
|   version "10.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-10.1.0.tgz#e22bc20faddbc07605c15284255653c0f3bad5ca" | ||||
|   integrity sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ== | ||||
|   dependencies: | ||||
|     "@types/hast" "^3.0.0" | ||||
|     "@types/mdast" "^4.0.0" | ||||
|     devlop "^1.0.0" | ||||
|     hast-util-to-jsx-runtime "^2.0.0" | ||||
|     html-url-attributes "^3.0.0" | ||||
|     mdast-util-to-hast "^13.0.0" | ||||
|     remark-parse "^11.0.0" | ||||
|     remark-rehype "^11.0.0" | ||||
|     unified "^11.0.0" | ||||
|     unist-util-visit "^5.0.0" | ||||
|     vfile "^6.0.0" | ||||
|  | ||||
| react-refresh@^0.18.0: | ||||
|   version "0.18.0" | ||||
|   resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.18.0.tgz#2dce97f4fe932a4d8142fa1630e475c1729c8062" | ||||
| @@ -2304,6 +2633,27 @@ rehype@~13.0.0: | ||||
|     rehype-stringify "^10.0.0" | ||||
|     unified "^11.0.0" | ||||
|  | ||||
| remark-parse@^11.0.0: | ||||
|   version "11.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-11.0.0.tgz#aa60743fcb37ebf6b069204eb4da304e40db45a1" | ||||
|   integrity sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA== | ||||
|   dependencies: | ||||
|     "@types/mdast" "^4.0.0" | ||||
|     mdast-util-from-markdown "^2.0.0" | ||||
|     micromark-util-types "^2.0.0" | ||||
|     unified "^11.0.0" | ||||
|  | ||||
| remark-rehype@^11.0.0: | ||||
|   version "11.1.2" | ||||
|   resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-11.1.2.tgz#2addaadda80ca9bd9aa0da763e74d16327683b37" | ||||
|   integrity sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw== | ||||
|   dependencies: | ||||
|     "@types/hast" "^3.0.0" | ||||
|     "@types/mdast" "^4.0.0" | ||||
|     mdast-util-to-hast "^13.0.0" | ||||
|     unified "^11.0.0" | ||||
|     vfile "^6.0.0" | ||||
|  | ||||
| resolve-from@^4.0.0: | ||||
|   version "4.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" | ||||
| @@ -2439,6 +2789,20 @@ strip-indent@^3.0.0: | ||||
|   dependencies: | ||||
|     min-indent "^1.0.0" | ||||
|  | ||||
| style-to-js@^1.0.0: | ||||
|   version "1.1.18" | ||||
|   resolved "https://registry.yarnpkg.com/style-to-js/-/style-to-js-1.1.18.tgz#3e6c13bd4c4db079bd2c2c94571cce5c758bc2ff" | ||||
|   integrity sha512-JFPn62D4kJaPTnhFUI244MThx+FEGbi+9dw1b9yBBQ+1CZpV7QAT8kUtJ7b7EUNdHajjF/0x8fT+16oLJoojLg== | ||||
|   dependencies: | ||||
|     style-to-object "1.0.11" | ||||
|  | ||||
| style-to-object@1.0.11: | ||||
|   version "1.0.11" | ||||
|   resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-1.0.11.tgz#cf252c4051758b7acb18a5efb296f91fb79bb9c4" | ||||
|   integrity sha512-5A560JmXr7wDyGLK12Nq/EYS38VkGlglVzkis1JEdbGWSnbQIEhZzTJhzURXN5/8WwwFCs/f/VVcmkTppbXLow== | ||||
|   dependencies: | ||||
|     inline-style-parser "0.2.4" | ||||
|  | ||||
| stylis@4.2.0: | ||||
|   version "4.2.0" | ||||
|   resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" | ||||
| @@ -2757,7 +3121,7 @@ yaml@^1.10.0: | ||||
|   resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" | ||||
|   integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== | ||||
|  | ||||
| zwitch@^2.0.4: | ||||
| zwitch@^2.0.0, zwitch@^2.0.4: | ||||
|   version "2.0.4" | ||||
|   resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7" | ||||
|   integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A== | ||||
|   | ||||
		Reference in New Issue
	
	Block a user