mirror of
https://github.com/usememos/memos.git
synced 2025-02-01 01:58:14 +08:00
chore: show inline image in daily review dialog (#135)
This commit is contained in:
parent
9994b1fabc
commit
df7b4d54c6
7 changed files with 51 additions and 31 deletions
|
@ -2,10 +2,10 @@ import { IMAGE_URL_REG } from "../helpers/consts";
|
||||||
import * as utils from "../helpers/utils";
|
import * as utils from "../helpers/utils";
|
||||||
import useToggle from "../hooks/useToggle";
|
import useToggle from "../hooks/useToggle";
|
||||||
import { memoService } from "../services";
|
import { memoService } from "../services";
|
||||||
|
import { formatMemoContent } from "../helpers/marked";
|
||||||
import Only from "./common/OnlyWhen";
|
import Only from "./common/OnlyWhen";
|
||||||
import Image from "./Image";
|
import Image from "./Image";
|
||||||
import toastHelper from "./Toast";
|
import toastHelper from "./Toast";
|
||||||
import { formatMemoContent } from "./Memo";
|
|
||||||
import "../less/memo.less";
|
import "../less/memo.less";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import { IMAGE_URL_REG } from "../helpers/consts";
|
|
||||||
import * as utils from "../helpers/utils";
|
import * as utils from "../helpers/utils";
|
||||||
import Only from "./common/OnlyWhen";
|
import { formatMemoContent } from "../helpers/marked";
|
||||||
import { formatMemoContent } from "./Memo";
|
|
||||||
import "../less/daily-memo.less";
|
import "../less/daily-memo.less";
|
||||||
|
|
||||||
interface DailyMemo extends Memo {
|
interface DailyMemo extends Memo {
|
||||||
|
@ -20,7 +18,6 @@ const DailyMemo: React.FC<Props> = (props: Props) => {
|
||||||
createdAtStr: utils.getDateTimeString(propsMemo.createdTs),
|
createdAtStr: utils.getDateTimeString(propsMemo.createdTs),
|
||||||
timeStr: utils.getTimeString(propsMemo.createdTs),
|
timeStr: utils.getTimeString(propsMemo.createdTs),
|
||||||
};
|
};
|
||||||
const imageUrls = Array.from(memo.content.match(IMAGE_URL_REG) ?? []).map((s) => s.replace(IMAGE_URL_REG, "$1"));
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="daily-memo-wrapper">
|
<div className="daily-memo-wrapper">
|
||||||
|
@ -28,14 +25,14 @@ const DailyMemo: React.FC<Props> = (props: Props) => {
|
||||||
<span className="normal-text">{memo.timeStr}</span>
|
<span className="normal-text">{memo.timeStr}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="memo-content-container">
|
<div className="memo-content-container">
|
||||||
<div className="memo-content-text" dangerouslySetInnerHTML={{ __html: formatMemoContent(memo.content) }}></div>
|
<div
|
||||||
<Only when={imageUrls.length > 0}>
|
className="memo-content-text"
|
||||||
<div className="images-container">
|
dangerouslySetInnerHTML={{
|
||||||
{imageUrls.map((imgUrl, idx) => (
|
__html: formatMemoContent(memo.content, {
|
||||||
<img key={idx} src={imgUrl} decoding="async" />
|
inlineImage: true,
|
||||||
))}
|
}),
|
||||||
</div>
|
}}
|
||||||
</Only>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<div className="split-line"></div>
|
<div className="split-line"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { memo, useEffect, useRef, useState } from "react";
|
import { memo, useEffect, useRef, useState } from "react";
|
||||||
import { escape, indexOf } from "lodash-es";
|
import { indexOf } from "lodash-es";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import relativeTime from "dayjs/plugin/relativeTime";
|
import relativeTime from "dayjs/plugin/relativeTime";
|
||||||
import { IMAGE_URL_REG, LINK_URL_REG, MEMO_LINK_REG, TAG_REG, UNKNOWN_ID } from "../helpers/consts";
|
import { IMAGE_URL_REG, UNKNOWN_ID } from "../helpers/consts";
|
||||||
import { DONE_BLOCK_REG, parseMarkedToHtml, TODO_BLOCK_REG } from "../helpers/marked";
|
import { DONE_BLOCK_REG, formatMemoContent, TODO_BLOCK_REG } from "../helpers/marked";
|
||||||
import { editorStateService, locationService, memoService, userService } from "../services";
|
import { editorStateService, locationService, memoService, userService } from "../services";
|
||||||
import Only from "./common/OnlyWhen";
|
import Only from "./common/OnlyWhen";
|
||||||
import toastHelper from "./Toast";
|
import toastHelper from "./Toast";
|
||||||
|
@ -234,15 +234,4 @@ const Memo: React.FC<Props> = (props: Props) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function formatMemoContent(content: string) {
|
|
||||||
const tempElement = document.createElement("div");
|
|
||||||
tempElement.innerHTML = parseMarkedToHtml(escape(content));
|
|
||||||
|
|
||||||
return tempElement.innerHTML
|
|
||||||
.replace(IMAGE_URL_REG, "")
|
|
||||||
.replace(MEMO_LINK_REG, "<span class='memo-link-text' data-value='$2'>$1</span>")
|
|
||||||
.replace(LINK_URL_REG, "<a class='link' target='_blank' rel='noreferrer' href='$2'>$1</a>")
|
|
||||||
.replace(TAG_REG, "<span class='tag-span'>#$1</span> ");
|
|
||||||
}
|
|
||||||
|
|
||||||
export default memo(Memo);
|
export default memo(Memo);
|
||||||
|
|
|
@ -2,12 +2,11 @@ import { useState, useEffect, useCallback } from "react";
|
||||||
import { editorStateService, memoService, userService } from "../services";
|
import { editorStateService, memoService, userService } from "../services";
|
||||||
import { IMAGE_URL_REG, MEMO_LINK_REG, UNKNOWN_ID } from "../helpers/consts";
|
import { IMAGE_URL_REG, MEMO_LINK_REG, UNKNOWN_ID } from "../helpers/consts";
|
||||||
import * as utils from "../helpers/utils";
|
import * as utils from "../helpers/utils";
|
||||||
import { parseHtmlToRawText } from "../helpers/marked";
|
import { formatMemoContent, parseHtmlToRawText } from "../helpers/marked";
|
||||||
import Only from "./common/OnlyWhen";
|
import Only from "./common/OnlyWhen";
|
||||||
import toastHelper from "./Toast";
|
import toastHelper from "./Toast";
|
||||||
import { generateDialog } from "./Dialog";
|
import { generateDialog } from "./Dialog";
|
||||||
import Image from "./Image";
|
import Image from "./Image";
|
||||||
import { formatMemoContent } from "./Memo";
|
|
||||||
import "../less/memo-card-dialog.less";
|
import "../less/memo-card-dialog.less";
|
||||||
import Selector from "./common/Selector";
|
import Selector from "./common/Selector";
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,10 @@ import { userService } from "../services";
|
||||||
import toImage from "../labs/html2image";
|
import toImage from "../labs/html2image";
|
||||||
import { ANIMATION_DURATION, IMAGE_URL_REG } from "../helpers/consts";
|
import { ANIMATION_DURATION, IMAGE_URL_REG } from "../helpers/consts";
|
||||||
import * as utils from "../helpers/utils";
|
import * as utils from "../helpers/utils";
|
||||||
|
import { formatMemoContent } from "../helpers/marked";
|
||||||
import { generateDialog } from "./Dialog";
|
import { generateDialog } from "./Dialog";
|
||||||
import Only from "./common/OnlyWhen";
|
import Only from "./common/OnlyWhen";
|
||||||
import toastHelper from "./Toast";
|
import toastHelper from "./Toast";
|
||||||
import { formatMemoContent } from "./Memo";
|
|
||||||
import "../less/share-memo-image-dialog.less";
|
import "../less/share-memo-image-dialog.less";
|
||||||
|
|
||||||
interface Props extends DialogProps {
|
interface Props extends DialogProps {
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
import { escape } from "lodash-es";
|
||||||
|
import { IMAGE_URL_REG, LINK_URL_REG, MEMO_LINK_REG, TAG_REG } from "./consts";
|
||||||
|
|
||||||
const CODE_BLOCK_REG = /```([\s\S]*?)```/g;
|
const CODE_BLOCK_REG = /```([\s\S]*?)```/g;
|
||||||
const BOLD_TEXT_REG = /\*\*(.+?)\*\*/g;
|
const BOLD_TEXT_REG = /\*\*(.+?)\*\*/g;
|
||||||
const EM_TEXT_REG = /\*(.+?)\*/g;
|
const EM_TEXT_REG = /\*(.+?)\*/g;
|
||||||
|
@ -28,4 +31,32 @@ const parseHtmlToRawText = (htmlStr: string): string => {
|
||||||
return text;
|
return text;
|
||||||
};
|
};
|
||||||
|
|
||||||
export { parseMarkedToHtml, parseHtmlToRawText };
|
interface FormatterConfig {
|
||||||
|
inlineImage: boolean;
|
||||||
|
}
|
||||||
|
const defaultFormatterConfig: FormatterConfig = {
|
||||||
|
inlineImage: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatMemoContent = (content: string, addtionConfig?: Partial<FormatterConfig>) => {
|
||||||
|
const config = {
|
||||||
|
...defaultFormatterConfig,
|
||||||
|
...addtionConfig,
|
||||||
|
};
|
||||||
|
const tempElement = document.createElement("div");
|
||||||
|
tempElement.innerHTML = parseMarkedToHtml(escape(content));
|
||||||
|
|
||||||
|
let outputString = tempElement.innerHTML;
|
||||||
|
if (config.inlineImage) {
|
||||||
|
outputString = outputString.replace(IMAGE_URL_REG, "<img class='img' src='$1' />");
|
||||||
|
} else {
|
||||||
|
outputString = outputString.replace(IMAGE_URL_REG, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputString
|
||||||
|
.replace(MEMO_LINK_REG, "<span class='memo-link-text' data-value='$2'>$1</span>")
|
||||||
|
.replace(LINK_URL_REG, "<a class='link' target='_blank' rel='noreferrer' href='$2'>$1</a>")
|
||||||
|
.replace(TAG_REG, "<span class='tag-span'>#$1</span> ");
|
||||||
|
};
|
||||||
|
|
||||||
|
export { formatMemoContent, parseHtmlToRawText };
|
||||||
|
|
|
@ -7,6 +7,10 @@
|
||||||
@apply inline-block w-full h-auto mb-1 last:mb-0 text-base leading-7 whitespace-pre-wrap break-all;
|
@apply inline-block w-full h-auto mb-1 last:mb-0 text-base leading-7 whitespace-pre-wrap break-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.img {
|
||||||
|
@apply float-left max-w-full w-full;
|
||||||
|
}
|
||||||
|
|
||||||
.tag-span {
|
.tag-span {
|
||||||
@apply inline-block w-auto font-mono text-blue-600;
|
@apply inline-block w-auto font-mono text-blue-600;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue