Use markdown block renderer for post content
This commit is contained in:
parent
2177fb4948
commit
f975167ea7
4 changed files with 41 additions and 8 deletions
|
@ -91,13 +91,20 @@ function getContent(): string {
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(p),
|
||||||
|
:deep(pre) {
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
:deep(a) {
|
:deep(a) {
|
||||||
@include block-link;
|
@include block-link;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(pre),
|
:deep(pre),
|
||||||
:deep(code) {
|
:deep(code) {
|
||||||
overflow-x: scroll;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(ul),
|
:deep(ul),
|
||||||
|
|
|
@ -10,7 +10,15 @@ const markdown = new MarkdownIt({ linkify: true, breaks: true })
|
||||||
|
|
||||||
// Minimal renderer
|
// Minimal renderer
|
||||||
const markdownLite = new MarkdownIt({ linkify: true, breaks: true })
|
const markdownLite = new MarkdownIt({ linkify: true, breaks: true })
|
||||||
.disable(["strikethrough", "image"])
|
.disable([
|
||||||
|
"blockquote",
|
||||||
|
"list",
|
||||||
|
"heading",
|
||||||
|
"lheading",
|
||||||
|
"hr",
|
||||||
|
"strikethrough",
|
||||||
|
"image",
|
||||||
|
])
|
||||||
.use(
|
.use(
|
||||||
MarkdownItLinkAttrs,
|
MarkdownItLinkAttrs,
|
||||||
{ attrs: { target: "_blank", rel: "noopener" } },
|
{ attrs: { target: "_blank", rel: "noopener" } },
|
||||||
|
@ -19,11 +27,20 @@ const markdownLite = new MarkdownIt({ linkify: true, breaks: true })
|
||||||
// Remove \n from output
|
// Remove \n from output
|
||||||
markdownLite.renderer.rules.hardbreak = () => "<br>"
|
markdownLite.renderer.rules.hardbreak = () => "<br>"
|
||||||
markdownLite.renderer.rules.softbreak = () => "<br>"
|
markdownLite.renderer.rules.softbreak = () => "<br>"
|
||||||
|
markdownLite.renderer.rules.paragraph_close = () => "</p>"
|
||||||
|
const default_fence_rule = markdownLite.renderer.rules.fence
|
||||||
|
markdownLite.renderer.rules.fence = (...args: any[]) => {
|
||||||
|
return default_fence_rule(...args).trim()
|
||||||
|
}
|
||||||
|
|
||||||
export function renderMarkdown(text: string): string {
|
export function renderMarkdown(text: string): string {
|
||||||
return markdown.render(text)
|
return markdown.render(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderMarkdownLite(text: string): string {
|
export function renderMarkdownLite(text: string): string {
|
||||||
|
return markdownLite.render(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderMarkdownLiteInline(text: string): string {
|
||||||
return markdownLite.renderInline(text)
|
return markdownLite.renderInline(text)
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ import ProfileCard from "@/components/ProfileCard.vue"
|
||||||
import SidebarLayout from "@/components/SidebarLayout.vue"
|
import SidebarLayout from "@/components/SidebarLayout.vue"
|
||||||
import { useCurrentUser } from "@/store/user"
|
import { useCurrentUser } from "@/store/user"
|
||||||
import { setupAutoResize } from "@/utils/autoresize"
|
import { setupAutoResize } from "@/utils/autoresize"
|
||||||
import { renderMarkdownLite } from "@/utils/markdown"
|
import { renderMarkdownLiteInline } from "@/utils/markdown"
|
||||||
import { fileToDataUrl, dataUrlToBase64 } from "@/utils/upload"
|
import { fileToDataUrl, dataUrlToBase64 } from "@/utils/upload"
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
@ -152,7 +152,7 @@ const profilePreview = $computed<Profile>(() => {
|
||||||
|
|
||||||
function onBioUpdate(event: Event) {
|
function onBioUpdate(event: Event) {
|
||||||
form.note_source = (event.target as HTMLTextAreaElement).value
|
form.note_source = (event.target as HTMLTextAreaElement).value
|
||||||
form.note = renderMarkdownLite(form.note_source)
|
form.note = renderMarkdownLiteInline(form.note_source)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onFilePicked(fieldName: "avatar" | "header", event: Event) {
|
async function onFilePicked(fieldName: "avatar" | "header", event: Event) {
|
||||||
|
@ -167,7 +167,7 @@ async function onFilePicked(fieldName: "avatar" | "header", event: Event) {
|
||||||
|
|
||||||
function onExtraFieldUpdate(field: ProfileFieldAttrs, event: Event) {
|
function onExtraFieldUpdate(field: ProfileFieldAttrs, event: Event) {
|
||||||
field.value_source = (event.target as HTMLInputElement).value
|
field.value_source = (event.target as HTMLInputElement).value
|
||||||
field.value = renderMarkdownLite(field.value_source)
|
field.value = renderMarkdownLiteInline(field.value_source)
|
||||||
}
|
}
|
||||||
|
|
||||||
function isValidExtraField(index: number): boolean {
|
function isValidExtraField(index: number): boolean {
|
||||||
|
|
|
@ -1,10 +1,19 @@
|
||||||
import { expect } from "chai"
|
import { expect } from "chai"
|
||||||
import { renderMarkdownLite } from "@/utils/markdown"
|
import {
|
||||||
|
renderMarkdownLite,
|
||||||
|
renderMarkdownLiteInline,
|
||||||
|
} from "@/utils/markdown"
|
||||||
|
|
||||||
describe("Render markdown", () => {
|
describe("Render markdown", () => {
|
||||||
|
const text = "# heading\n\ntest **bold** test *italic* test ~~strike~~ with `code`, <span>html</span> and https://example.com\nnew line\n\ntwo new lines and a list:\n- item 1\n- item 2\n\ncode block:\n```\nlet test\ntest = 1\n```"
|
||||||
|
|
||||||
it("Render markdown lite", () => {
|
it("Render markdown lite", () => {
|
||||||
const text = "test **bold** test *italic* test ~~strike~~ with `code`, <span>html</span> and https://example.com\nnew line\n\ntwo new lines and a list:\n- item 1\n- item 2\n\ncode block:\n```\nlet test\ntest = 1\n```"
|
|
||||||
const html = renderMarkdownLite(text)
|
const html = renderMarkdownLite(text)
|
||||||
expect(html).to.equal('test <strong>bold</strong> test <em>italic</em> test ~~strike~~ with <code>code</code>, <span>html</span> and <a href="https://example.com" target="_blank" rel="noopener">https://example.com</a><br>new line<br><br>two new lines and a list:<br>- item 1<br>- item 2<br><br>code block:<br><code>let test test = 1</code>')
|
expect(html).to.equal('<p># heading</p><p>test <strong>bold</strong> test <em>italic</em> test ~~strike~~ with <code>code</code>, <span>html</span> and <a href="https://example.com" target="_blank" rel="noopener">https://example.com</a><br>new line</p><p>two new lines and a list:<br>- item 1<br>- item 2</p><p>code block:</p><pre><code>let test\ntest = 1\n</code></pre>')
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Render markdown lite inline", () => {
|
||||||
|
const html = renderMarkdownLiteInline(text)
|
||||||
|
expect(html).to.equal('# heading<br><br>test <strong>bold</strong> test <em>italic</em> test ~~strike~~ with <code>code</code>, <span>html</span> and <a href="https://example.com" target="_blank" rel="noopener">https://example.com</a><br>new line<br><br>two new lines and a list:<br>- item 1<br>- item 2<br><br>code block:<br><code>let test test = 1</code>')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue