diff options
-rw-r--r-- | FrontEnd/package.json | 3 | ||||
-rw-r--r-- | FrontEnd/src/services/TimelinePostBuilder.ts | 36 | ||||
-rw-r--r-- | FrontEnd/src/views/timeline/TimelinePostContentView.tsx | 15 |
3 files changed, 26 insertions, 28 deletions
diff --git a/FrontEnd/package.json b/FrontEnd/package.json index 415363f7..930eaa63 100644 --- a/FrontEnd/package.json +++ b/FrontEnd/package.json @@ -50,6 +50,7 @@ "devDependencies": {
"@types/color": "^3.0.3",
"@types/lodash": "^4.14.181",
+ "@types/marked": "^4.0.3",
"@types/node": "^17.0.23",
"@types/react": "^17.0.0",
"@types/react-color": "^3.0.6",
@@ -69,4 +70,4 @@ "vite": "^2.9.1",
"vite-plugin-pwa": "^0.11.3"
}
-}
\ No newline at end of file +}
diff --git a/FrontEnd/src/services/TimelinePostBuilder.ts b/FrontEnd/src/services/TimelinePostBuilder.ts index 40279eca..0c21b353 100644 --- a/FrontEnd/src/services/TimelinePostBuilder.ts +++ b/FrontEnd/src/services/TimelinePostBuilder.ts @@ -1,29 +1,37 @@ -import { Remarkable } from "remarkable"; +import { marked } from "marked"; import { UiLogicError } from "@/common"; import { base64 } from "@/http/common"; import { HttpTimelinePostPostRequest } from "@/http/timeline"; +class TimelinePostMarkedRenderer extends marked.Renderer { + constructor(private _images: { file: File; url: string }[]) { + super(); + } + + image(href: string | null, title: string | null, text: string): string { + if (href != null) { + const i = parseInt(href); + if (!isNaN(i) && i > 0 && i <= this._images.length) { + href = this._images[i - 1].url; + } + } + return this.image(href, title, text); + } +} + export default class TimelinePostBuilder { private _onChange: () => void; private _text = ""; private _images: { file: File; url: string }[] = []; - private _md: Remarkable = new Remarkable(); + private _markedOptions: marked.MarkedOptions; constructor(onChange: () => void) { this._onChange = onChange; - const oldImageRenderer = this._md.renderer.rules.image; - this._md.renderer.rules.image = (( - _t: TimelinePostBuilder - ): Remarkable.Rule<Remarkable.ImageToken, string> => - function (tokens, idx, options /*, env */) { - const i = parseInt(tokens[idx].src); - if (!isNaN(i) && i > 0 && i <= _t._images.length) { - tokens[idx].src = _t._images[i - 1].url; - } - return oldImageRenderer(tokens, idx, options); - })(this); + this._markedOptions = { + renderer: new TimelinePostMarkedRenderer(this._images), + }; } setMarkdownText(text: string): void { @@ -87,7 +95,7 @@ export default class TimelinePostBuilder { } renderHtml(): string { - return this._md.render(this._text); + return marked.parse(this._text); } dispose(): void { diff --git a/FrontEnd/src/views/timeline/TimelinePostContentView.tsx b/FrontEnd/src/views/timeline/TimelinePostContentView.tsx index 88cd756a..9e50e5cb 100644 --- a/FrontEnd/src/views/timeline/TimelinePostContentView.tsx +++ b/FrontEnd/src/views/timeline/TimelinePostContentView.tsx @@ -1,6 +1,6 @@ import React from "react"; import classnames from "classnames"; -import { Remarkable } from "remarkable"; +import { marked } from "marked"; import { UiLogicError } from "@/common"; @@ -88,17 +88,6 @@ const ImageView: React.FC<TimelinePostContentViewProps> = (props) => { const MarkdownView: React.FC<TimelinePostContentViewProps> = (props) => { const { post, className, style } = props; - const _remarkable = React.useRef<Remarkable>(); - - const getRemarkable = (): Remarkable => { - if (_remarkable.current) { - return _remarkable.current; - } else { - _remarkable.current = new Remarkable(); - return _remarkable.current; - } - }; - const [markdown, setMarkdown] = React.useState<string | null>(null); const [error, setError] = React.useState<"offline" | "error" | null>(null); @@ -134,7 +123,7 @@ const MarkdownView: React.FC<TimelinePostContentViewProps> = (props) => { const markdownHtml = React.useMemo<string | null>(() => { if (markdown == null) return null; - return getRemarkable().render(markdown); + return marked.parse(markdown); }, [markdown]); if (error != null) { |