feat: markdown support (#165)

* initial markdown support via markdown-it

* sanitize markup

* remove pre-padding

* fix linter errors
This commit is contained in:
Hayden 2022-12-02 16:12:32 -09:00 committed by GitHub
parent d2aa022347
commit 974d6914a2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 1396 additions and 1049 deletions

View file

@ -17,6 +17,11 @@
</a>
</div>
</template>
<template v-else-if="detail.type === 'markdown'">
<ClientOnly>
<Markdown :source="detail.text" />
</ClientOnly>
</template>
<template v-else>
{{ detail.text }}
</template>
@ -28,11 +33,11 @@
</template>
<script setup lang="ts">
import type { CustomDetail, Detail } from "./types";
import type { AnyDetail, Detail } from "./types";
defineProps({
details: {
type: Object as () => (Detail | CustomDetail)[],
type: Object as () => (Detail | AnyDetail)[],
required: true,
},
});

View file

@ -21,11 +21,16 @@ type LinkDetail = BaseDetail & {
href: string;
};
export type CustomDetail = DateDetail | CurrencyDetail | LinkDetail;
type MarkdownDetail = BaseDetail & {
type: "markdown";
text: string;
};
export type Detail = BaseDetail & {
text: StringLike;
type?: "text";
};
export type Details = Array<Detail | CustomDetail>;
export type AnyDetail = DateDetail | CurrencyDetail | LinkDetail | MarkdownDetail | Detail;
export type Details = Array<Detail | AnyDetail>;

View file

@ -0,0 +1,80 @@
<script setup lang="ts">
import MarkdownIt from "markdown-it";
import DOMPurify from "dompurify";
type Props = {
source: string;
};
const props = withDefaults(defineProps<Props>(), {});
const md = new MarkdownIt({
html: true,
linkify: true,
typographer: true,
});
const raw = computed(() => {
const html = md.render(props.source);
return DOMPurify.sanitize(html);
});
</script>
<template>
<div class="markdown" v-html="raw"></div>
</template>
<style scoped>
* {
--y-gap: 0.65rem;
}
.markdown > :first-child {
margin-top: 0px !important;
}
.markdown :where(p, ul, ol, dl, blockquote, h1, h2, h3, h4, h5, h6) {
margin-top: var(--y-gap);
margin-bottom: var(--y-gap);
}
.markdown :where(ul) {
list-style: disc;
margin-left: 2rem;
}
.markdown :where(ol) {
list-style: decimal;
margin-left: 2rem;
}
/* Heading Styles */
.markdown :where(h1) {
font-size: 2rem;
font-weight: 700;
}
.markdown :where(h2) {
font-size: 1.5rem;
font-weight: 700;
}
.markdown :where(h3) {
font-size: 1.25rem;
font-weight: 700;
}
.markdown :where(h4) {
font-size: 1rem;
font-weight: 700;
}
.markdown :where(h5) {
font-size: 0.875rem;
font-weight: 700;
}
.markdown :where(h6) {
font-size: 0.75rem;
font-weight: 700;
}
</style>