mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
feat: support markdown table (#294)
* feat: support markdown table * chore: update table style * test: for markdown table parse
This commit is contained in:
@ -3,6 +3,38 @@ import { unescape } from "lodash-es";
|
|||||||
import { marked } from ".";
|
import { marked } from ".";
|
||||||
|
|
||||||
describe("test marked parser", () => {
|
describe("test marked parser", () => {
|
||||||
|
test("test markdown table", () => {
|
||||||
|
const tests = [
|
||||||
|
{
|
||||||
|
markdown: `| a | b | c |
|
||||||
|
|---|---|---|
|
||||||
|
| 1 | 2 | 3 |
|
||||||
|
| 4 | 5 | 6 |`,
|
||||||
|
want: `<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>a</th><th>b</th><th>c</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>1</td><td>2</td><td>3</td></tr><tr><td>4</td><td>5</td><td>6</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
markdown: `| a | b | c |
|
||||||
|
| 1 | 2 | 3 |
|
||||||
|
| 4 | 5 | 6 |`,
|
||||||
|
want: `<p>| a | b | c |</p>
|
||||||
|
<p>| 1 | 2 | 3 |</p>
|
||||||
|
<p>| 4 | 5 | 6 |</p>`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
for (const t of tests) {
|
||||||
|
expect(unescape(marked(t.markdown))).toBe(t.want);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test("parse code block", () => {
|
test("parse code block", () => {
|
||||||
const tests = [
|
const tests = [
|
||||||
{
|
{
|
||||||
|
45
web/src/labs/marked/parser/Table.ts
Normal file
45
web/src/labs/marked/parser/Table.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* Match markdown table
|
||||||
|
* example:
|
||||||
|
* | a | b | c |
|
||||||
|
* |---|---|---|
|
||||||
|
* | 1 | 2 | 3 |
|
||||||
|
* | 4 | 5 | 6 |
|
||||||
|
*/
|
||||||
|
export const TABLE_REG = /^(\|.*\|)(?:(?:\n(?:\|-*)+\|))((?:\n\|.*\|)+)/;
|
||||||
|
|
||||||
|
const renderer = (rawStr: string): string => {
|
||||||
|
const matchResult = rawStr.match(TABLE_REG);
|
||||||
|
if (!matchResult) {
|
||||||
|
return rawStr;
|
||||||
|
}
|
||||||
|
const tableHeader = matchResult[1]
|
||||||
|
.split("|")
|
||||||
|
.filter((str) => str !== "")
|
||||||
|
.map((str) => str.trim());
|
||||||
|
const tableBody = matchResult[2]
|
||||||
|
.trim()
|
||||||
|
.split("\n")
|
||||||
|
.map((str) =>
|
||||||
|
str
|
||||||
|
.split("|")
|
||||||
|
.filter((str) => str !== "")
|
||||||
|
.map((str) => str.trim())
|
||||||
|
);
|
||||||
|
return `<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
${tableHeader.map((str) => `<th>${str}</th>`).join("")}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
${tableBody.map((row) => `<tr>${row.map((str) => `<td>${str}</td>`).join("")}</tr>`).join("")}
|
||||||
|
</tbody>
|
||||||
|
</table>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "table",
|
||||||
|
regex: TABLE_REG,
|
||||||
|
renderer,
|
||||||
|
};
|
@ -13,6 +13,7 @@ import Emphasis from "./Emphasis";
|
|||||||
import PlainLink from "./PlainLink";
|
import PlainLink from "./PlainLink";
|
||||||
import InlineCode from "./InlineCode";
|
import InlineCode from "./InlineCode";
|
||||||
import PlainText from "./PlainText";
|
import PlainText from "./PlainText";
|
||||||
|
import Table from "./Table";
|
||||||
|
|
||||||
export { CODE_BLOCK_REG } from "./CodeBlock";
|
export { CODE_BLOCK_REG } from "./CodeBlock";
|
||||||
export { TODO_LIST_REG } from "./TodoList";
|
export { TODO_LIST_REG } from "./TodoList";
|
||||||
@ -21,8 +22,9 @@ export { TAG_REG } from "./Tag";
|
|||||||
export { IMAGE_REG } from "./Image";
|
export { IMAGE_REG } from "./Image";
|
||||||
export { LINK_REG } from "./Link";
|
export { LINK_REG } from "./Link";
|
||||||
export { MARK_REG } from "./Mark";
|
export { MARK_REG } from "./Mark";
|
||||||
|
export { TABLE_REG } from "./Table";
|
||||||
|
|
||||||
// The order determines the order of execution.
|
// The order determines the order of execution.
|
||||||
export const blockElementParserList = [CodeBlock, TodoList, DoneList, OrderedList, UnorderedList, Paragraph];
|
export const blockElementParserList = [Table, CodeBlock, TodoList, DoneList, OrderedList, UnorderedList, Paragraph];
|
||||||
export const inlineElementParserList = [Image, Mark, Bold, Emphasis, Link, InlineCode, PlainLink, Tag, PlainText];
|
export const inlineElementParserList = [Image, Mark, Bold, Emphasis, Link, InlineCode, PlainLink, Tag, PlainText];
|
||||||
export const parserList = [...blockElementParserList, ...inlineElementParserList];
|
export const parserList = [...blockElementParserList, ...inlineElementParserList];
|
||||||
|
@ -58,6 +58,18 @@
|
|||||||
code {
|
code {
|
||||||
@apply bg-gray-100 px-1 rounded text-sm font-mono leading-6 inline-block;
|
@apply bg-gray-100 px-1 rounded text-sm font-mono leading-6 inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
@apply my-1 table-auto border-collapse border border-gray-300;
|
||||||
|
|
||||||
|
th {
|
||||||
|
@apply px-4 py-1 text-center border border-gray-300;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
@apply px-4 py-1 text-center border border-gray-300;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .expand-btn-container {
|
> .expand-btn-container {
|
||||||
|
Reference in New Issue
Block a user