feat(lite/stories): needed components for incoming Component Stories (#6611)

This commit is contained in:
Thierry Goettelmann
2023-02-17 10:42:35 +01:00
committed by GitHub
parent b42127f083
commit bc0afb589e
18 changed files with 571 additions and 135 deletions

View File

@@ -24,12 +24,14 @@
"d3-time-format": "^4.1.0",
"decorator-synchronized": "^0.6.0",
"echarts": "^5.3.3",
"highlight.js": "^11.6.0",
"human-format": "^1.0.0",
"json-rpc-2.0": "^1.3.0",
"json5": "^2.2.1",
"limit-concurrency-decorator": "^0.5.0",
"lodash-es": "^4.17.21",
"make-error": "^1.3.6",
"markdown-it": "^13.0.1",
"pinia": "^2.0.14",
"placement.js": "^1.0.0-beta.5",
"vue": "^3.2.37",

View File

@@ -16,8 +16,8 @@ a {
color: var(--color-extra-blue-base);
}
code {
font-family: monospace;
code, code * {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
.card-view {

View File

@@ -0,0 +1,114 @@
<template>
<div ref="rootElement" class="app-markdown" v-html="html" />
</template>
<script lang="ts" setup>
import { type Ref, computed, ref } from "vue";
import { useEventListener } from "@vueuse/core";
import "highlight.js/styles/github-dark.css";
import { markdown } from "@/libs/markdown";
const rootElement = ref() as Ref<HTMLElement>;
const props = defineProps<{
content: string;
}>();
const html = computed(() => markdown.render(props.content ?? ""));
useEventListener(
rootElement,
"click",
(event: MouseEvent) => {
const target = event.target as HTMLElement;
if (!target.classList.contains("copy-button")) {
return;
}
const copyable =
target.parentElement!.querySelector<HTMLElement>(".copyable");
if (copyable !== null) {
navigator.clipboard.writeText(copyable.innerText);
}
},
{ capture: true }
);
</script>
<style lang="postcss" scoped>
.app-markdown {
font-size: 1.6rem;
:deep() {
p,
h1,
h2,
h3,
h4,
h5,
h6,
pre {
margin: 1rem 0;
}
pre {
width: 100%;
padding: 0.8rem 1.4rem;
border-radius: 1rem;
}
code:not(.hljs-code) {
background-color: var(--background-color-extra-blue);
padding: 0.3rem 0.6rem;
border-radius: 0.6rem;
}
ul,
ol {
margin: revert;
padding-left: 2rem;
list-style-type: revert;
}
table {
border-spacing: 0;
th,
td {
padding: 0.5rem 1rem;
}
thead th {
border-bottom: 2px solid var(--color-blue-scale-400);
background-color: var(--background-color-secondary);
}
tbody td {
border-bottom: 1px solid var(--color-blue-scale-400);
}
}
.copy-button {
font-size: 1.6rem;
font-weight: 400;
position: absolute;
z-index: 1;
right: 1rem;
cursor: pointer;
color: white;
border: none;
background-color: transparent;
&:hover {
color: var(--color-extra-blue-base);
}
&:active {
color: var(--color-extra-blue-d20);
}
}
}
}
</style>

View File

@@ -0,0 +1,41 @@
<template>
<pre class="code-highlight hljs"><code v-html="codeAsHtml"></code></pre>
</template>
<script lang="ts" setup>
import HLJS from "highlight.js";
import { computed } from "vue";
import "highlight.js/styles/github-dark.css";
const props = withDefaults(
defineProps<{
code?: any;
lang?: string;
}>(),
{ lang: "typescript" }
);
const codeAsText = computed(() => {
switch (typeof props.code) {
case "string":
return props.code;
case "function":
return String(props.code);
default:
return JSON.stringify(props.code, undefined, 2);
}
});
const codeAsHtml = computed(
() => HLJS.highlight(codeAsText.value, { language: props.lang }).value
);
</script>
<style lang="postcss" scoped>
.code-highlight {
display: inline-block;
padding: 0.3rem 0.6rem;
text-align: left;
border-radius: 0.6rem;
}
</style>

View File

@@ -0,0 +1,29 @@
<template>
<RouterLink
v-slot="{ isActive, href }"
:to="disabled || isTabBarDisabled ? '' : to"
custom
>
<UiTab :active="isActive" :disabled="disabled" :href="href" tag="a">
<slot />
</UiTab>
</RouterLink>
</template>
<script lang="ts" setup>
import { type ComputedRef, computed, inject } from "vue";
import type { RouteLocationRaw } from "vue-router";
import UiTab from "@/components/ui/UiTab.vue";
const props = defineProps<{
to: RouteLocationRaw;
disabled?: boolean;
}>();
const isTabBarDisabled = inject<ComputedRef<boolean>>(
"isTabBarDisabled",
computed(() => false)
);
</script>
<style lang="postcss" scoped></style>

View File

@@ -1,54 +0,0 @@
<template>
<span v-if="disabled" class="tab-bar-item disabled">
<slot />
</span>
<RouterLink v-else class="tab-bar-item" v-bind="$props">
<slot />
</RouterLink>
</template>
<script lang="ts" setup>
import type { RouterLinkProps } from "vue-router";
// https://vuejs.org/api/sfc-script-setup.html#type-only-props-emit-declarations
interface Props extends RouterLinkProps {
disabled?: boolean;
}
defineProps<Props>();
</script>
<style lang="postcss" scoped>
.tab-bar-item {
font-size: 1.8rem;
font-weight: 600;
display: flex;
align-items: center;
padding: 0 1.2em;
text-decoration: none;
text-transform: uppercase;
color: var(--color-blue-scale-100);
border-bottom: 2px solid transparent;
&:hover:not(.disabled) {
border-bottom-color: var(--color-extra-blue-base);
background-color: var(--background-color-secondary);
}
&:active:not(.disabled) {
color: var(--color-extra-blue-base);
border-bottom-color: var(--color-extra-blue-base);
background-color: var(--background-color-secondary);
}
&.router-link-active {
color: var(--color-extra-blue-base);
border-bottom-color: var(--color-extra-blue-base);
background-color: var(--background-color-primary);
}
&.disabled {
color: var(--color-blue-scale-400);
}
}
</style>

View File

@@ -6,6 +6,7 @@
>
<input
v-model="value"
:class="{ indeterminate: type === 'checkbox' && value === undefined }"
:disabled="isLabelDisabled || disabled"
:type="type === 'radio' ? 'radio' : 'checkbox'"
class="input"
@@ -32,7 +33,7 @@ import {
inject,
ref,
} from "vue";
import { faCheck, faCircle } from "@fortawesome/free-solid-svg-icons";
import { faCheck, faCircle, faMinus } from "@fortawesome/free-solid-svg-icons";
import { useVModel } from "@vueuse/core";
import UiIcon from "@/components/ui/UiIcon.vue";
@@ -53,7 +54,17 @@ const value = useVModel(props, "modelValue", emit);
const type = inject<"checkbox" | "radio" | "toggle">("inputType", "checkbox");
const hasLabel = inject("hasLabel", false);
const isLabelDisabled = inject("isLabelDisabled", ref(false));
const icon = computed(() => (type === "checkbox" ? faCheck : faCircle));
const icon = computed(() => {
if (type !== "checkbox") {
return faCircle;
}
if (value.value === undefined) {
return faMinus;
}
return faCheck;
});
</script>
<style lang="postcss" scoped>
@@ -74,6 +85,11 @@ const icon = computed(() => (type === "checkbox" ? faCheck : faCircle));
.form-checkbox {
--checkbox-border-radius: 0.25em;
--checkbox-icon-size: 1em;
.input.indeterminate + .fake-checkbox > .icon {
opacity: 1;
color: var(--color-blue-scale-300);
}
}
.form-checkbox,
@@ -109,8 +125,8 @@ const icon = computed(() => (type === "checkbox" ? faCheck : faCircle));
}
.icon {
transform: translateX(-0.7em);
transition: transform 0.125s ease-in-out;
transform: translateX(-0.7em);
}
.input:checked + .fake-checkbox > .icon {
@@ -140,12 +156,12 @@ const icon = computed(() => (type === "checkbox" ? faCheck : faCircle));
align-items: center;
justify-content: center;
height: 1.25em;
transition: background-color 0.125s ease-in-out,
border-color 0.125s ease-in-out;
border: var(--checkbox-border-width) solid var(--border-color);
border-radius: var(--checkbox-border-radius);
background-color: var(--background-color);
box-shadow: var(--shadow-100);
transition: background-color 0.125s ease-in-out,
border-color 0.125s ease-in-out;
--border-color: var(--color-blue-scale-400);
}

View File

@@ -1,15 +1,6 @@
<template>
<span :class="wrapperClass" v-bind="wrapperAttrs">
<input
v-if="!isSelect"
v-model="value"
:class="inputClass"
:disabled="disabled || isLabelDisabled"
class="input"
ref="inputElement"
v-bind="$attrs"
/>
<template v-else>
<template v-if="inputType === 'select'">
<select
v-model="value"
:class="inputClass"
@@ -24,6 +15,24 @@
<UiIcon :fixed-width="false" :icon="faAngleDown" />
</span>
</template>
<textarea
v-else-if="inputType === 'textarea'"
ref="textarea"
v-model="value"
:class="inputClass"
:disabled="disabled || isLabelDisabled"
class="textarea"
v-bind="$attrs"
/>
<input
v-else
v-model="value"
:class="inputClass"
:disabled="disabled || isLabelDisabled"
class="input"
ref="inputElement"
v-bind="$attrs"
/>
<span v-if="before !== undefined" class="before">
<template v-if="typeof before === 'string'">{{ before }}</template>
<UiIcon v-else :icon="before" class="before" />
@@ -43,18 +52,19 @@ export default {
</script>
<script lang="ts" setup>
import { isEmpty } from "lodash-es";
import {
type HTMLAttributes,
type InputHTMLAttributes,
computed,
inject,
nextTick,
ref,
watch,
} from "vue";
import type { Color } from "@/types";
import type { IconDefinition } from "@fortawesome/fontawesome-common-types";
import { faAngleDown } from "@fortawesome/free-solid-svg-icons";
import { useVModel } from "@vueuse/core";
import { useTextareaAutosize, useVModel } from "@vueuse/core";
import UiIcon from "@/components/ui/UiIcon.vue";
// Temporary workaround for https://github.com/vuejs/core/issues/4294
@@ -79,8 +89,10 @@ const emit = defineEmits<{
}>();
const value = useVModel(props, "modelValue", emit);
const empty = computed(() => isEmpty(props.modelValue));
const isSelect = inject("isSelect", false);
const isEmpty = computed(
() => props.modelValue == null || String(props.modelValue).trim() === ""
);
const inputType = inject("inputType", "input");
const isLabelDisabled = inject("isLabelDisabled", ref(false));
const color = inject(
"color",
@@ -88,10 +100,10 @@ const color = inject(
);
const wrapperClass = computed(() => [
isSelect ? "form-select" : "form-input",
`form-${inputType}`,
{
disabled: props.disabled || isLabelDisabled.value,
empty: empty.value,
empty: isEmpty.value,
},
]);
@@ -104,6 +116,12 @@ const inputClass = computed(() => [
},
]);
const { textarea, triggerResize } = useTextareaAutosize();
watch(value, () => nextTick(() => triggerResize()), {
immediate: true,
});
const focus = () => inputElement.value.focus();
defineExpose({
@@ -113,12 +131,13 @@ defineExpose({
<style lang="postcss" scoped>
.form-input,
.form-select {
.form-select,
.form-textarea {
display: inline-grid;
align-items: stretch;
--before-width: v-bind('beforeWidth ?? "1.75em"');
--after-width: v-bind('afterWidth ?? "1.625em"');
--before-width: v-bind('beforeWidth || "1.75em"');
--after-width: v-bind('afterWidth || "1.625em"');
--caret-width: 1.5em;
--text-color: var(--color-blue-scale-100);
@@ -132,7 +151,8 @@ defineExpose({
}
}
.form-input {
.form-input,
.form-textarea {
grid-template-columns: var(--before-width) auto var(--after-width);
}
@@ -145,8 +165,10 @@ defineExpose({
}
.input,
.textarea,
.select {
font-size: 1em;
width: 100%;
height: 2em;
margin: 0;
color: var(--text-color);
@@ -235,8 +257,19 @@ defineExpose({
}
}
.textarea {
height: auto;
min-height: 2em;
}
.input {
padding: 0 0.625em 0 0.625em;
padding: 0;
}
.input,
.textarea {
padding-right: 0.625em;
padding-left: 0.625em;
&.has-before {
padding-left: calc(var(--before-width) + 0.25em);

View File

@@ -0,0 +1,93 @@
<template>
<UiModal
@submit.prevent="saveJson"
:color="isJsonValid ? 'success' : 'error'"
v-if="isCodeModalOpen"
:icon="faCode"
@close="closeCodeModal"
>
<FormTextarea class="modal-textarea" v-model="editedJson" />
<template #buttons>
<UiButton transparent @click="formatJson">{{ $t("reformat") }}</UiButton>
<UiButton outlined @click="closeCodeModal">{{ $t("cancel") }}</UiButton>
<UiButton :disabled="!isJsonValid" type="submit"
>{{ $t("save") }}
</UiButton>
</template>
</UiModal>
<FormInput
@click="openCodeModal"
:model-value="jsonValue"
:before="faCode"
readonly
/>
</template>
<script lang="ts" setup>
import FormInput from "@/components/form/FormInput.vue";
import FormTextarea from "@/components/form/FormTextarea.vue";
import UiButton from "@/components/ui/UiButton.vue";
import UiModal from "@/components/ui/UiModal.vue";
import useModal from "@/composables/modal.composable";
import { faCode } from "@fortawesome/free-solid-svg-icons";
import { useVModel, whenever } from "@vueuse/core";
import { computed, ref } from "vue";
const props = defineProps<{
modelValue: any;
}>();
const emit = defineEmits<{
(event: "update:modelValue", value: any): void;
}>();
const model = useVModel(props, "modelValue", emit);
const {
open: openCodeModal,
close: closeCodeModal,
isOpen: isCodeModalOpen,
} = useModal();
const jsonValue = computed(() => JSON.stringify(model.value, undefined, 2));
const isJsonValid = computed(() => {
try {
JSON.parse(editedJson.value);
return true;
} catch {
return false;
}
});
const formatJson = () => {
if (!isJsonValid.value) {
return;
}
editedJson.value = JSON.stringify(JSON.parse(editedJson.value), undefined, 2);
};
const saveJson = () => {
if (!isJsonValid.value) {
return;
}
formatJson();
model.value = JSON.parse(editedJson.value);
closeCodeModal();
};
whenever(isCodeModalOpen, () => (editedJson.value = jsonValue.value));
const editedJson = ref();
</script>
<style lang="postcss" scoped>
:deep(.modal-textarea) {
min-width: 50rem;
min-height: 20rem;
}
</style>

View File

@@ -8,7 +8,7 @@
import { provide } from "vue";
import FormInput from "@/components/form/FormInput.vue";
provide("isSelect", true);
provide("inputType", "select");
</script>
<style lang="postcss" scoped></style>

View File

@@ -0,0 +1,12 @@
<template>
<FormInput />
</template>
<script lang="ts" setup>
import { provide } from "vue";
import FormInput from "@/components/form/FormInput.vue";
provide("inputType", "textarea");
</script>
<style lang="postcss" scoped></style>

View File

@@ -1,67 +1,40 @@
<template>
<TabBar>
<TabBarItem
:disabled="!isReady"
:to="{ name: 'pool.dashboard', params: { uuid: poolUuid } }"
>
<UiTabBar :disabled="!isReady">
<RouterTab :to="{ name: 'pool.dashboard', params: { uuid: poolUuid } }">
{{ $t("dashboard") }}
</TabBarItem>
<TabBarItem
:disabled="!isReady"
:to="{ name: 'pool.alarms', params: { uuid: poolUuid } }"
>
</RouterTab>
<RouterTab :to="{ name: 'pool.alarms', params: { uuid: poolUuid } }">
{{ $t("alarms") }}
</TabBarItem>
<TabBarItem
:disabled="!isReady"
:to="{ name: 'pool.stats', params: { uuid: poolUuid } }"
>
</RouterTab>
<RouterTab :to="{ name: 'pool.stats', params: { uuid: poolUuid } }">
{{ $t("stats") }}
</TabBarItem>
<TabBarItem
:disabled="!isReady"
:to="{ name: 'pool.system', params: { uuid: poolUuid } }"
>
</RouterTab>
<RouterTab :to="{ name: 'pool.system', params: { uuid: poolUuid } }">
{{ $t("system") }}
</TabBarItem>
<TabBarItem
:disabled="!isReady"
:to="{ name: 'pool.network', params: { uuid: poolUuid } }"
>
</RouterTab>
<RouterTab :to="{ name: 'pool.network', params: { uuid: poolUuid } }">
{{ $t("network") }}
</TabBarItem>
<TabBarItem
:disabled="!isReady"
:to="{ name: 'pool.storage', params: { uuid: poolUuid } }"
>
</RouterTab>
<RouterTab :to="{ name: 'pool.storage', params: { uuid: poolUuid } }">
{{ $t("storage") }}
</TabBarItem>
<TabBarItem
:disabled="!isReady"
:to="{ name: 'pool.tasks', params: { uuid: poolUuid } }"
>
</RouterTab>
<RouterTab :to="{ name: 'pool.tasks', params: { uuid: poolUuid } }">
{{ $t("tasks") }}
</TabBarItem>
<TabBarItem
:disabled="!isReady"
:to="{ name: 'pool.hosts', params: { uuid: poolUuid } }"
>
</RouterTab>
<RouterTab :to="{ name: 'pool.hosts', params: { uuid: poolUuid } }">
{{ $t("hosts") }}
</TabBarItem>
<TabBarItem
:disabled="!isReady"
:to="{ name: 'pool.vms', params: { uuid: poolUuid } }"
>
</RouterTab>
<RouterTab :to="{ name: 'pool.vms', params: { uuid: poolUuid } }">
{{ $t("vms") }}
</TabBarItem>
</TabBar>
</RouterTab>
</UiTabBar>
</template>
<script lang="ts" setup>
import { storeToRefs } from "pinia";
import { computed } from "vue";
import TabBar from "@/components/TabBar.vue";
import TabBarItem from "@/components/TabBarItem.vue";
import RouterTab from "@/components/RouterTab.vue";
import UiTabBar from "@/components/ui/UiTabBar.vue";
import { usePoolStore } from "@/stores/pool.store";
const poolStore = usePoolStore();

View File

@@ -0,0 +1,68 @@
<template>
<component
:is="tag"
:class="{ active, disabled: disabled || isTabBarDisabled }"
class="ui-tab"
>
<slot />
</component>
</template>
<script lang="ts" setup>
import { type ComputedRef, computed, inject } from "vue";
withDefaults(
defineProps<{
disabled?: boolean;
active?: boolean;
tag?: string;
}>(),
{ tag: "span" }
);
const isTabBarDisabled = inject<ComputedRef<boolean>>(
"isTabBarDisabled",
computed(() => false)
);
</script>
<style lang="postcss" scoped>
.ui-tab {
font-size: 1.8rem;
font-weight: 600;
display: flex;
align-items: center;
padding: 0 1.2em;
text-decoration: none;
text-transform: uppercase;
color: var(--color-blue-scale-100);
border-bottom: 2px solid transparent;
&.disabled {
pointer-events: none;
color: var(--color-blue-scale-400);
}
&:not(.disabled) {
cursor: pointer;
&:hover {
cursor: pointer;
border-bottom-color: var(--color-extra-blue-base);
background-color: var(--background-color-secondary);
}
&:active {
color: var(--color-extra-blue-base);
border-bottom-color: var(--color-extra-blue-base);
background-color: var(--background-color-secondary);
}
&.active {
color: var(--color-extra-blue-base);
border-bottom-color: var(--color-extra-blue-base);
background-color: var(--background-color-primary);
}
}
}
</style>

View File

@@ -1,16 +1,29 @@
<template>
<div class="tab-bar">
<div class="ui-tab-bar">
<slot />
</div>
</template>
<script lang="ts" setup>
import { computed, provide } from "vue";
const props = defineProps<{
disabled?: boolean;
}>();
provide(
"isTabBarDisabled",
computed(() => props.disabled)
);
</script>
<style lang="postcss" scoped>
.tab-bar {
.ui-tab-bar {
display: flex;
align-items: stretch;
height: 6.5rem;
background-color: var(--background-color-primary);
border-bottom: 1px solid var(--color-blue-scale-400);
background-color: var(--background-color-primary);
max-width: 100%;
overflow: auto;
}

View File

@@ -0,0 +1,64 @@
import HLJS from "highlight.js";
import MarkdownIt from "markdown-it";
export const markdown = new MarkdownIt();
markdown.set({
highlight: (str: string, lang: string) => {
const code = highlight(str, lang);
return `<pre class="hljs"><button class="copy-button" type="button">Copy</button><code class="hljs-code">${code}</code></pre>`;
},
});
function highlight(str: string, lang: string) {
switch (lang) {
case "vue-template": {
const indented = str
.trim()
.split("\n")
.map((s) => ` ${s}`)
.join("\n");
return wrap(indented, "template");
}
case "vue-script":
return wrap(str.trim(), "script");
case "vue-style":
return wrap(str.trim(), "style");
default: {
if (HLJS.getLanguage(lang) !== undefined) {
return copyable(HLJS.highlight(str, { language: lang }).value);
}
return copyable(markdown.utils.escapeHtml(str));
}
}
}
function wrap(str: string, tag: "template" | "script" | "style") {
let openTag;
let code;
switch (tag) {
case "template":
openTag = "<template>";
code = HLJS.highlight(str, { language: "xml" }).value;
break;
case "script":
openTag = '<script lang="ts" setup>';
code = HLJS.highlight(str, { language: "typescript" }).value;
break;
case "style":
openTag = '<style lang="postcss" scoped>';
code = HLJS.highlight(str, { language: "scss" }).value;
break;
}
const openTagHtml = HLJS.highlight(openTag, { language: "xml" }).value;
const closeTagHtml = HLJS.highlight(`</${tag}>`, { language: "xml" }).value;
return `${openTagHtml}${copyable(code)}${closeTagHtml}`;
}
function copyable(code: string) {
return `<div class="copyable">${code}</div>`;
}

View File

@@ -55,6 +55,7 @@
"property": "Property",
"ram-usage": "RAM usage",
"reboot": "Reboot",
"reformat": "Reformat",
"relative-time": {
"day": "1 day | {n} days",
"future": "In {str}",
@@ -67,6 +68,7 @@
"year": "1 year | {n} years"
},
"resume": "Resume",
"save": "Save",
"send-us-feedback": "Send us feedback",
"settings": "Settings",
"shutdown": "Shutdown",

View File

@@ -55,6 +55,7 @@
"property": "Propriété",
"ram-usage": "Utilisation de la RAM",
"reboot": "Redémarrer",
"reformat": "Reformater",
"relative-time": {
"day": "1 jour | {n} jours",
"future": "Dans {str}",
@@ -67,6 +68,7 @@
"year": "1 an | {n} ans"
},
"resume": "Reprendre",
"save": "Enregistrer",
"send-us-feedback": "Envoyez-nous vos commentaires",
"settings": "Paramètres",
"shutdown": "Arrêter",

View File

@@ -7926,6 +7926,11 @@ entities@~1.1.1:
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
entities@~3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4"
integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==
envify@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/envify/-/envify-4.1.0.tgz#f39ad3db9d6801b4e6b478b61028d3f0b6819f7e"
@@ -10507,6 +10512,11 @@ highland@^2.11.1:
dependencies:
util-deprecate "^1.0.2"
highlight.js@^11.6.0:
version "11.6.0"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.6.0.tgz#a50e9da05763f1bb0c1322c8f4f755242cff3f5a"
integrity sha512-ig1eqDzJaB0pqEvlPVIpSSyMaO92bH1N2rJpLMN/nX396wTpDA4Eq0uK+7I/2XG17pFaaKE0kjV/XPeGt7Evjw==
highlight.js@^9.7.0:
version "9.18.5"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.5.tgz#d18a359867f378c138d6819edfc2a8acd5f29825"
@@ -12857,6 +12867,13 @@ linkify-it@^2.0.0:
dependencies:
uc.micro "^1.0.1"
linkify-it@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-4.0.1.tgz#01f1d5e508190d06669982ba31a7d9f56a5751ec"
integrity sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==
dependencies:
uc.micro "^1.0.1"
lint-staged@^13.0.3:
version "13.1.0"
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.1.0.tgz#d4c61aec939e789e489fa51987ec5207b50fd37e"
@@ -13388,6 +13405,17 @@ markdown-it-table-of-contents@^0.4.0:
resolved "https://registry.yarnpkg.com/markdown-it-table-of-contents/-/markdown-it-table-of-contents-0.4.4.tgz#3dc7ce8b8fc17e5981c77cc398d1782319f37fbc"
integrity sha512-TAIHTHPwa9+ltKvKPWulm/beozQU41Ab+FIefRaQV1NRnpzwcV9QOe6wXQS5WLivm5Q/nlo0rl6laGkMDZE7Gw==
markdown-it@^13.0.1:
version "13.0.1"
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-13.0.1.tgz#c6ecc431cacf1a5da531423fc6a42807814af430"
integrity sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==
dependencies:
argparse "^2.0.1"
entities "~3.0.1"
linkify-it "^4.0.1"
mdurl "^1.0.1"
uc.micro "^1.0.5"
markdown-it@^8.4.1:
version "8.4.2"
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54"