Introduction
My requirement is to implement an online paper typesetting editor and export the pdf generated by LaTeX.
-- Updated --
https://github.com/facebook/draft-js/pull/2590
-- Orignial --
Project link:Eorg
Relative projects are Overleaf and Resumake.
I prefer to React.js, so I chose Draft.js, a rich text editor that was also developed for Facebook. Paper writing can't hide from table insertion, but Draft.js does not have a ready-made table plug-in. There are also a few tools for generating tables. Totally unnecessary to write another table support by my own, but it is convenient for users, and the table does not need to be too complicated. You can export a booktabs
-like table, so I plan to try to implement table support by myself
Content
Idea:
A robust table is to use new ContentBlock
to write metadata into block
,which is an approach closed to Draft.js !
Relatively speaking, my implementation is more trick, which borrow from offical TeX example ,using AtomicBlockUtils.insertAtomicBlock(newEditorState, entityKey, ' ')
API to add metadata to React.js props:
- rows and columns
const contentStateWithEntity = contentState.createEntity(
'TABLE',
'IMMUTABLE',
{
row, column, caption, // data
},
)
// ...
const { row, column, caption } = props // Table Component
- table cell
// createTable.js
/**
* cell = {
* 0: ["cell-0,0", "cell-0,1", ..., "cell-0,m"],
* 1: ["cell-1,0", "cell-1,1", ..., "cell-1,m"],
* ...,
* n: ["cell-n,0", "cell-n,1", ..., "cell-n,m"],
* }
*/
const cell = Object.fromEntries(Array.from(
{ length: row },
(_, i) => [
i,
Array.from({ length: column }, (_, j) => `cell-${i},${j}`)
])
)
const contentStateWithEntity = contentState.createEntity(
'TABLE',
'IMMUTABLE',
{
..., cell, // data
},
)
// ...
const { ..., cell } = props // Table Component
and initialize a table:
// TableBlock.js
// tbody -- version 1
const coordinate = []
if (row > 1) {
for (let i = 1; i < row; i += 1) {
const cols = []
for (let j = 0; j < column; j += 1) {
cols.push(
<td key={i + j} >
{cell[i][j]}
</td>,
)
}
rows.push(<tr key={i}>{cols}</tr>)
}
}
store
row
,column
,caption
,cell
to React.jsprops
- obtain cell coordinate:
The first idea is to calculate the Dom Node location,which means find the index of <tr>
at closest('td')
at closest('table')
Later, more better approach is retrive the key
value in <tr>
and <td>
, and its coordinate is (x1, y1):
// TableBlock.js
// tbody -- version 2
const coordinate = []
if (row > 1) { // thead need to calculate separately
for (let i = 1; i < row; i += 1) {
const cols = []
for (let j = 0; j < column; j += 1) {
cols.push(
<td
key={i + j} // TODO key-1
onDoubleClick={() => coordinate.push([i, j])}
>
{cell[i][j]}
</td>,
)
}
rows.push(<tr key={i}>{cols}</tr>)
}
}
Above key-1 is not stable,we can work with nanoid library:
key = {`i+j+${nanoid()}`}
Now it's stable and we can store cell values:
// find the coordinate of the node clicked
const x1 = coordinate[coordinate.length - 1][0]
const y1 = coordinate[coordinate.length - 1][1]
// update cell[i][j]
cell[x1][y1] = evt.target.innerHTML
cell-2,1 can be stored to props
Summary
The table is not yet complete, for example:
- how to process cursor
- it's mutable
Next
To support adding and deleting cell.
Top comments (0)