Skip to content

Commit

Permalink
chore: use custom rule
Browse files Browse the repository at this point in the history
  • Loading branch information
iamsivin committed Aug 30, 2024
1 parent 60ec1e4 commit fbda0fd
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 55 deletions.
119 changes: 72 additions & 47 deletions src/rules/tables.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,75 @@
import { InputRule } from "prosemirror-inputrules";
import { NodeType, Schema } from "prosemirror-model";
import { EditorState, TextSelection, Transaction } from "prosemirror-state";

function createTable(schema, rowsCount, colsCount) {
const {
table,
table_row: tableRow,
table_cell: tableCell,
table_header: tableHeader,
paragraph,
} = schema.nodes;

const cells = [];
for (let i = 0; i < colsCount; i++) {
cells.push(
tableHeader.createAndFill() || tableCell.createAndFill()
);
}

const rows = [];
for (let i = 0; i < rowsCount; i++) {
rows.push(tableRow.createChecked(null, cells));
}

return table.createChecked(null, rows);
}

export function tableInputRule(schema) {
return new InputRule(
/^\|\s+([\s\S]*)\s+\|\s*$/,
(state, match, start, end) => {
const [okay, columns] = match;
if (okay) {
const parts = columns.split("|").map((s) => s.trim());
const table = createTable(schema, 1, parts.length);

const tr = state.tr.replaceRangeWith(start, end, table);
const selection = TextSelection.create(
tr.doc,
start + 1
);
return tr.setSelection(selection);
import Token from "markdown-it/lib/token";

const BREAK_REGEX = /(?:^|[^\\])\\n/;

export default function markdownTables(md) {
// insert a new rule after the "inline" rules are parsed
md.core.ruler.after("inline", "tables-pm", (state) => {
const tokens = state.tokens;
let inside = false;

for (let i = tokens.length - 1; i > 0; i--) {
if (inside) {
tokens[i].level--;
}

// convert unescaped \n in the text into real br tag
if (tokens[i].type === "inline" && tokens[i].content.match(BREAK_REGEX)) {
const existing = tokens[i].children || [];
tokens[i].children = [];

existing.forEach((child) => {
const breakParts = child.content.split(BREAK_REGEX);

// a schema agnostic way to know if a node is inline code would be
// great, for now we are stuck checking the node type.
if (breakParts.length > 1 && child.type !== "code_inline") {
breakParts.forEach((part, index) => {
const token = new Token("text", "", 1);
token.content = part.trim();
if (tokens[i].children) tokens[i].children.push(token);

if (index < breakParts.length - 1) {
const brToken = new Token("br", "br", 1);
if (tokens[i].children) tokens[i].children.push(brToken);
}
});
} else if (tokens[i].children) {
tokens[i].children.push(child);
}
});
}

// filter out incompatible tokens from markdown-it that we don't need
// in prosemirror. thead/tbody do nothing.
if (
["thead_open", "thead_close", "tbody_open", "tbody_close"].includes(
tokens[i].type
)
) {
inside = !inside;
tokens.splice(i, 1);
}

if (["th_open", "td_open"].includes(tokens[i].type)) {
// markdown-it table parser does not return paragraphs inside the cells
// but prosemirror requires them, so we add 'em in here.
tokens.splice(i + 1, 0, new Token("paragraph_open", "p", 1));

// markdown-it table parser stores alignment as html styles, convert
// to a simple string here
const tokenAttrs = tokens[i].attrs;
if (tokenAttrs) {
const style = tokenAttrs[0][1];
tokens[i].info = style.split(":")[1];
}
}

if (["th_close", "td_close"].includes(tokens[i].type)) {
tokens.splice(i, 0, new Token("paragraph_close", "p", -1));
}
return null;
}
);
}

export default tableInputRule;
return false;
});
}
10 changes: 2 additions & 8 deletions src/schema/markdown/articleParser.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import MarkdownIt from 'markdown-it';
import MarkdownItSup from 'markdown-it-sup';
import { MarkdownParser } from 'prosemirror-markdown';
import MarkdownItMultimdTable from 'markdown-it-multimd-table';
import markdownItTable from '../../rules/tables';

import {
baseSchemaToMdMapping,
Expand Down Expand Up @@ -65,13 +65,7 @@ const md = MarkdownIt('commonmark', {
html: false,
linkify: true,
breaks: true,
}).use(MarkdownItSup).use(MarkdownItMultimdTable, {
multiline: false,
rowspan: false,
headerless: false,
multibody: false,
autolabel: false,
});
}).use(MarkdownItSup).use(markdownItTable);

md.enable([
// Process html entity - &#123;, &#xAF;, &quot;, ...
Expand Down

0 comments on commit fbda0fd

Please sign in to comment.