feat(lite/stories): needed components for incoming Component Stories (#6611)
This commit is contained in:
committed by
GitHub
parent
b42127f083
commit
bc0afb589e
@@ -24,12 +24,14 @@
|
|||||||
"d3-time-format": "^4.1.0",
|
"d3-time-format": "^4.1.0",
|
||||||
"decorator-synchronized": "^0.6.0",
|
"decorator-synchronized": "^0.6.0",
|
||||||
"echarts": "^5.3.3",
|
"echarts": "^5.3.3",
|
||||||
|
"highlight.js": "^11.6.0",
|
||||||
"human-format": "^1.0.0",
|
"human-format": "^1.0.0",
|
||||||
"json-rpc-2.0": "^1.3.0",
|
"json-rpc-2.0": "^1.3.0",
|
||||||
"json5": "^2.2.1",
|
"json5": "^2.2.1",
|
||||||
"limit-concurrency-decorator": "^0.5.0",
|
"limit-concurrency-decorator": "^0.5.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"make-error": "^1.3.6",
|
"make-error": "^1.3.6",
|
||||||
|
"markdown-it": "^13.0.1",
|
||||||
"pinia": "^2.0.14",
|
"pinia": "^2.0.14",
|
||||||
"placement.js": "^1.0.0-beta.5",
|
"placement.js": "^1.0.0-beta.5",
|
||||||
"vue": "^3.2.37",
|
"vue": "^3.2.37",
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ a {
|
|||||||
color: var(--color-extra-blue-base);
|
color: var(--color-extra-blue-base);
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code, code * {
|
||||||
font-family: monospace;
|
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-view {
|
.card-view {
|
||||||
|
|||||||
114
@xen-orchestra/lite/src/components/AppMarkdown.vue
Normal file
114
@xen-orchestra/lite/src/components/AppMarkdown.vue
Normal 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>
|
||||||
41
@xen-orchestra/lite/src/components/CodeHighlight.vue
Normal file
41
@xen-orchestra/lite/src/components/CodeHighlight.vue
Normal 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>
|
||||||
29
@xen-orchestra/lite/src/components/RouterTab.vue
Normal file
29
@xen-orchestra/lite/src/components/RouterTab.vue
Normal 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>
|
||||||
@@ -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>
|
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
v-model="value"
|
v-model="value"
|
||||||
|
:class="{ indeterminate: type === 'checkbox' && value === undefined }"
|
||||||
:disabled="isLabelDisabled || disabled"
|
:disabled="isLabelDisabled || disabled"
|
||||||
:type="type === 'radio' ? 'radio' : 'checkbox'"
|
:type="type === 'radio' ? 'radio' : 'checkbox'"
|
||||||
class="input"
|
class="input"
|
||||||
@@ -32,7 +33,7 @@ import {
|
|||||||
inject,
|
inject,
|
||||||
ref,
|
ref,
|
||||||
} from "vue";
|
} 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 { useVModel } from "@vueuse/core";
|
||||||
import UiIcon from "@/components/ui/UiIcon.vue";
|
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 type = inject<"checkbox" | "radio" | "toggle">("inputType", "checkbox");
|
||||||
const hasLabel = inject("hasLabel", false);
|
const hasLabel = inject("hasLabel", false);
|
||||||
const isLabelDisabled = inject("isLabelDisabled", ref(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>
|
</script>
|
||||||
|
|
||||||
<style lang="postcss" scoped>
|
<style lang="postcss" scoped>
|
||||||
@@ -74,6 +85,11 @@ const icon = computed(() => (type === "checkbox" ? faCheck : faCircle));
|
|||||||
.form-checkbox {
|
.form-checkbox {
|
||||||
--checkbox-border-radius: 0.25em;
|
--checkbox-border-radius: 0.25em;
|
||||||
--checkbox-icon-size: 1em;
|
--checkbox-icon-size: 1em;
|
||||||
|
|
||||||
|
.input.indeterminate + .fake-checkbox > .icon {
|
||||||
|
opacity: 1;
|
||||||
|
color: var(--color-blue-scale-300);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-checkbox,
|
.form-checkbox,
|
||||||
@@ -109,8 +125,8 @@ const icon = computed(() => (type === "checkbox" ? faCheck : faCircle));
|
|||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
transform: translateX(-0.7em);
|
|
||||||
transition: transform 0.125s ease-in-out;
|
transition: transform 0.125s ease-in-out;
|
||||||
|
transform: translateX(-0.7em);
|
||||||
}
|
}
|
||||||
|
|
||||||
.input:checked + .fake-checkbox > .icon {
|
.input:checked + .fake-checkbox > .icon {
|
||||||
@@ -140,12 +156,12 @@ const icon = computed(() => (type === "checkbox" ? faCheck : faCircle));
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: 1.25em;
|
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: var(--checkbox-border-width) solid var(--border-color);
|
||||||
border-radius: var(--checkbox-border-radius);
|
border-radius: var(--checkbox-border-radius);
|
||||||
background-color: var(--background-color);
|
background-color: var(--background-color);
|
||||||
box-shadow: var(--shadow-100);
|
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);
|
--border-color: var(--color-blue-scale-400);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<span :class="wrapperClass" v-bind="wrapperAttrs">
|
<span :class="wrapperClass" v-bind="wrapperAttrs">
|
||||||
<input
|
<template v-if="inputType === 'select'">
|
||||||
v-if="!isSelect"
|
|
||||||
v-model="value"
|
|
||||||
:class="inputClass"
|
|
||||||
:disabled="disabled || isLabelDisabled"
|
|
||||||
class="input"
|
|
||||||
ref="inputElement"
|
|
||||||
v-bind="$attrs"
|
|
||||||
/>
|
|
||||||
<template v-else>
|
|
||||||
<select
|
<select
|
||||||
v-model="value"
|
v-model="value"
|
||||||
:class="inputClass"
|
:class="inputClass"
|
||||||
@@ -24,6 +15,24 @@
|
|||||||
<UiIcon :fixed-width="false" :icon="faAngleDown" />
|
<UiIcon :fixed-width="false" :icon="faAngleDown" />
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</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">
|
<span v-if="before !== undefined" class="before">
|
||||||
<template v-if="typeof before === 'string'">{{ before }}</template>
|
<template v-if="typeof before === 'string'">{{ before }}</template>
|
||||||
<UiIcon v-else :icon="before" class="before" />
|
<UiIcon v-else :icon="before" class="before" />
|
||||||
@@ -43,18 +52,19 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { isEmpty } from "lodash-es";
|
|
||||||
import {
|
import {
|
||||||
type HTMLAttributes,
|
type HTMLAttributes,
|
||||||
type InputHTMLAttributes,
|
type InputHTMLAttributes,
|
||||||
computed,
|
computed,
|
||||||
inject,
|
inject,
|
||||||
|
nextTick,
|
||||||
ref,
|
ref,
|
||||||
|
watch,
|
||||||
} from "vue";
|
} from "vue";
|
||||||
import type { Color } from "@/types";
|
import type { Color } from "@/types";
|
||||||
import type { IconDefinition } from "@fortawesome/fontawesome-common-types";
|
import type { IconDefinition } from "@fortawesome/fontawesome-common-types";
|
||||||
import { faAngleDown } from "@fortawesome/free-solid-svg-icons";
|
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";
|
import UiIcon from "@/components/ui/UiIcon.vue";
|
||||||
|
|
||||||
// Temporary workaround for https://github.com/vuejs/core/issues/4294
|
// Temporary workaround for https://github.com/vuejs/core/issues/4294
|
||||||
@@ -79,8 +89,10 @@ const emit = defineEmits<{
|
|||||||
}>();
|
}>();
|
||||||
|
|
||||||
const value = useVModel(props, "modelValue", emit);
|
const value = useVModel(props, "modelValue", emit);
|
||||||
const empty = computed(() => isEmpty(props.modelValue));
|
const isEmpty = computed(
|
||||||
const isSelect = inject("isSelect", false);
|
() => props.modelValue == null || String(props.modelValue).trim() === ""
|
||||||
|
);
|
||||||
|
const inputType = inject("inputType", "input");
|
||||||
const isLabelDisabled = inject("isLabelDisabled", ref(false));
|
const isLabelDisabled = inject("isLabelDisabled", ref(false));
|
||||||
const color = inject(
|
const color = inject(
|
||||||
"color",
|
"color",
|
||||||
@@ -88,10 +100,10 @@ const color = inject(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const wrapperClass = computed(() => [
|
const wrapperClass = computed(() => [
|
||||||
isSelect ? "form-select" : "form-input",
|
`form-${inputType}`,
|
||||||
{
|
{
|
||||||
disabled: props.disabled || isLabelDisabled.value,
|
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();
|
const focus = () => inputElement.value.focus();
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
@@ -113,12 +131,13 @@ defineExpose({
|
|||||||
|
|
||||||
<style lang="postcss" scoped>
|
<style lang="postcss" scoped>
|
||||||
.form-input,
|
.form-input,
|
||||||
.form-select {
|
.form-select,
|
||||||
|
.form-textarea {
|
||||||
display: inline-grid;
|
display: inline-grid;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
|
|
||||||
--before-width: v-bind('beforeWidth ?? "1.75em"');
|
--before-width: v-bind('beforeWidth || "1.75em"');
|
||||||
--after-width: v-bind('afterWidth ?? "1.625em"');
|
--after-width: v-bind('afterWidth || "1.625em"');
|
||||||
--caret-width: 1.5em;
|
--caret-width: 1.5em;
|
||||||
|
|
||||||
--text-color: var(--color-blue-scale-100);
|
--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);
|
grid-template-columns: var(--before-width) auto var(--after-width);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,8 +165,10 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
|
|
||||||
.input,
|
.input,
|
||||||
|
.textarea,
|
||||||
.select {
|
.select {
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
|
width: 100%;
|
||||||
height: 2em;
|
height: 2em;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
@@ -235,8 +257,19 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.textarea {
|
||||||
|
height: auto;
|
||||||
|
min-height: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
.input {
|
.input {
|
||||||
padding: 0 0.625em 0 0.625em;
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input,
|
||||||
|
.textarea {
|
||||||
|
padding-right: 0.625em;
|
||||||
|
padding-left: 0.625em;
|
||||||
|
|
||||||
&.has-before {
|
&.has-before {
|
||||||
padding-left: calc(var(--before-width) + 0.25em);
|
padding-left: calc(var(--before-width) + 0.25em);
|
||||||
|
|||||||
93
@xen-orchestra/lite/src/components/form/FormJson.vue
Normal file
93
@xen-orchestra/lite/src/components/form/FormJson.vue
Normal 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>
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
import { provide } from "vue";
|
import { provide } from "vue";
|
||||||
import FormInput from "@/components/form/FormInput.vue";
|
import FormInput from "@/components/form/FormInput.vue";
|
||||||
|
|
||||||
provide("isSelect", true);
|
provide("inputType", "select");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="postcss" scoped></style>
|
<style lang="postcss" scoped></style>
|
||||||
|
|||||||
12
@xen-orchestra/lite/src/components/form/FormTextarea.vue
Normal file
12
@xen-orchestra/lite/src/components/form/FormTextarea.vue
Normal 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>
|
||||||
@@ -1,67 +1,40 @@
|
|||||||
<template>
|
<template>
|
||||||
<TabBar>
|
<UiTabBar :disabled="!isReady">
|
||||||
<TabBarItem
|
<RouterTab :to="{ name: 'pool.dashboard', params: { uuid: poolUuid } }">
|
||||||
:disabled="!isReady"
|
|
||||||
:to="{ name: 'pool.dashboard', params: { uuid: poolUuid } }"
|
|
||||||
>
|
|
||||||
{{ $t("dashboard") }}
|
{{ $t("dashboard") }}
|
||||||
</TabBarItem>
|
</RouterTab>
|
||||||
<TabBarItem
|
<RouterTab :to="{ name: 'pool.alarms', params: { uuid: poolUuid } }">
|
||||||
:disabled="!isReady"
|
|
||||||
:to="{ name: 'pool.alarms', params: { uuid: poolUuid } }"
|
|
||||||
>
|
|
||||||
{{ $t("alarms") }}
|
{{ $t("alarms") }}
|
||||||
</TabBarItem>
|
</RouterTab>
|
||||||
<TabBarItem
|
<RouterTab :to="{ name: 'pool.stats', params: { uuid: poolUuid } }">
|
||||||
:disabled="!isReady"
|
|
||||||
:to="{ name: 'pool.stats', params: { uuid: poolUuid } }"
|
|
||||||
>
|
|
||||||
{{ $t("stats") }}
|
{{ $t("stats") }}
|
||||||
</TabBarItem>
|
</RouterTab>
|
||||||
<TabBarItem
|
<RouterTab :to="{ name: 'pool.system', params: { uuid: poolUuid } }">
|
||||||
:disabled="!isReady"
|
|
||||||
:to="{ name: 'pool.system', params: { uuid: poolUuid } }"
|
|
||||||
>
|
|
||||||
{{ $t("system") }}
|
{{ $t("system") }}
|
||||||
</TabBarItem>
|
</RouterTab>
|
||||||
<TabBarItem
|
<RouterTab :to="{ name: 'pool.network', params: { uuid: poolUuid } }">
|
||||||
:disabled="!isReady"
|
|
||||||
:to="{ name: 'pool.network', params: { uuid: poolUuid } }"
|
|
||||||
>
|
|
||||||
{{ $t("network") }}
|
{{ $t("network") }}
|
||||||
</TabBarItem>
|
</RouterTab>
|
||||||
<TabBarItem
|
<RouterTab :to="{ name: 'pool.storage', params: { uuid: poolUuid } }">
|
||||||
:disabled="!isReady"
|
|
||||||
:to="{ name: 'pool.storage', params: { uuid: poolUuid } }"
|
|
||||||
>
|
|
||||||
{{ $t("storage") }}
|
{{ $t("storage") }}
|
||||||
</TabBarItem>
|
</RouterTab>
|
||||||
<TabBarItem
|
<RouterTab :to="{ name: 'pool.tasks', params: { uuid: poolUuid } }">
|
||||||
:disabled="!isReady"
|
|
||||||
:to="{ name: 'pool.tasks', params: { uuid: poolUuid } }"
|
|
||||||
>
|
|
||||||
{{ $t("tasks") }}
|
{{ $t("tasks") }}
|
||||||
</TabBarItem>
|
</RouterTab>
|
||||||
<TabBarItem
|
<RouterTab :to="{ name: 'pool.hosts', params: { uuid: poolUuid } }">
|
||||||
:disabled="!isReady"
|
|
||||||
:to="{ name: 'pool.hosts', params: { uuid: poolUuid } }"
|
|
||||||
>
|
|
||||||
{{ $t("hosts") }}
|
{{ $t("hosts") }}
|
||||||
</TabBarItem>
|
</RouterTab>
|
||||||
<TabBarItem
|
<RouterTab :to="{ name: 'pool.vms', params: { uuid: poolUuid } }">
|
||||||
:disabled="!isReady"
|
|
||||||
:to="{ name: 'pool.vms', params: { uuid: poolUuid } }"
|
|
||||||
>
|
|
||||||
{{ $t("vms") }}
|
{{ $t("vms") }}
|
||||||
</TabBarItem>
|
</RouterTab>
|
||||||
</TabBar>
|
</UiTabBar>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
import TabBar from "@/components/TabBar.vue";
|
import RouterTab from "@/components/RouterTab.vue";
|
||||||
import TabBarItem from "@/components/TabBarItem.vue";
|
import UiTabBar from "@/components/ui/UiTabBar.vue";
|
||||||
import { usePoolStore } from "@/stores/pool.store";
|
import { usePoolStore } from "@/stores/pool.store";
|
||||||
|
|
||||||
const poolStore = usePoolStore();
|
const poolStore = usePoolStore();
|
||||||
|
|||||||
68
@xen-orchestra/lite/src/components/ui/UiTab.vue
Normal file
68
@xen-orchestra/lite/src/components/ui/UiTab.vue
Normal 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>
|
||||||
@@ -1,16 +1,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="tab-bar">
|
<div class="ui-tab-bar">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</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>
|
<style lang="postcss" scoped>
|
||||||
.tab-bar {
|
.ui-tab-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
height: 6.5rem;
|
height: 6.5rem;
|
||||||
background-color: var(--background-color-primary);
|
|
||||||
border-bottom: 1px solid var(--color-blue-scale-400);
|
border-bottom: 1px solid var(--color-blue-scale-400);
|
||||||
|
background-color: var(--background-color-primary);
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
64
@xen-orchestra/lite/src/libs/markdown.ts
Normal file
64
@xen-orchestra/lite/src/libs/markdown.ts
Normal 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>`;
|
||||||
|
}
|
||||||
@@ -55,6 +55,7 @@
|
|||||||
"property": "Property",
|
"property": "Property",
|
||||||
"ram-usage": "RAM usage",
|
"ram-usage": "RAM usage",
|
||||||
"reboot": "Reboot",
|
"reboot": "Reboot",
|
||||||
|
"reformat": "Reformat",
|
||||||
"relative-time": {
|
"relative-time": {
|
||||||
"day": "1 day | {n} days",
|
"day": "1 day | {n} days",
|
||||||
"future": "In {str}",
|
"future": "In {str}",
|
||||||
@@ -67,6 +68,7 @@
|
|||||||
"year": "1 year | {n} years"
|
"year": "1 year | {n} years"
|
||||||
},
|
},
|
||||||
"resume": "Resume",
|
"resume": "Resume",
|
||||||
|
"save": "Save",
|
||||||
"send-us-feedback": "Send us feedback",
|
"send-us-feedback": "Send us feedback",
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
"shutdown": "Shutdown",
|
"shutdown": "Shutdown",
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
"property": "Propriété",
|
"property": "Propriété",
|
||||||
"ram-usage": "Utilisation de la RAM",
|
"ram-usage": "Utilisation de la RAM",
|
||||||
"reboot": "Redémarrer",
|
"reboot": "Redémarrer",
|
||||||
|
"reformat": "Reformater",
|
||||||
"relative-time": {
|
"relative-time": {
|
||||||
"day": "1 jour | {n} jours",
|
"day": "1 jour | {n} jours",
|
||||||
"future": "Dans {str}",
|
"future": "Dans {str}",
|
||||||
@@ -67,6 +68,7 @@
|
|||||||
"year": "1 an | {n} ans"
|
"year": "1 an | {n} ans"
|
||||||
},
|
},
|
||||||
"resume": "Reprendre",
|
"resume": "Reprendre",
|
||||||
|
"save": "Enregistrer",
|
||||||
"send-us-feedback": "Envoyez-nous vos commentaires",
|
"send-us-feedback": "Envoyez-nous vos commentaires",
|
||||||
"settings": "Paramètres",
|
"settings": "Paramètres",
|
||||||
"shutdown": "Arrêter",
|
"shutdown": "Arrêter",
|
||||||
|
|||||||
28
yarn.lock
28
yarn.lock
@@ -7926,6 +7926,11 @@ entities@~1.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
|
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
|
||||||
integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
|
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:
|
envify@^4.0.0:
|
||||||
version "4.1.0"
|
version "4.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/envify/-/envify-4.1.0.tgz#f39ad3db9d6801b4e6b478b61028d3f0b6819f7e"
|
resolved "https://registry.yarnpkg.com/envify/-/envify-4.1.0.tgz#f39ad3db9d6801b4e6b478b61028d3f0b6819f7e"
|
||||||
@@ -10507,6 +10512,11 @@ highland@^2.11.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
util-deprecate "^1.0.2"
|
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:
|
highlight.js@^9.7.0:
|
||||||
version "9.18.5"
|
version "9.18.5"
|
||||||
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.5.tgz#d18a359867f378c138d6819edfc2a8acd5f29825"
|
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.5.tgz#d18a359867f378c138d6819edfc2a8acd5f29825"
|
||||||
@@ -12857,6 +12867,13 @@ linkify-it@^2.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
uc.micro "^1.0.1"
|
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:
|
lint-staged@^13.0.3:
|
||||||
version "13.1.0"
|
version "13.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.1.0.tgz#d4c61aec939e789e489fa51987ec5207b50fd37e"
|
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"
|
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==
|
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:
|
markdown-it@^8.4.1:
|
||||||
version "8.4.2"
|
version "8.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54"
|
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54"
|
||||||
|
|||||||
Reference in New Issue
Block a user