Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 10 additions & 87 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,91 +1,14 @@
# Table tool
# Table tool with paste ability

The Table Block for the [Editor.js](https://editorjs.io). Finally improved.
Fork From https://github.com/editor-js/table

![](https://capella.pics/41294cec-a2b3-4157-8399-ffefed3d8ffd.jpg)
paste in editor.js will lost tr/td data of table node,so need modify

## Installation
editor.js\src\components\modules\paste.ts

Get the package

```shell
npm i --save @editorjs/table
```
or

```shell
yarn add @editorjs/table
```

## Usage

Add a new Tool to the `tools` property of the Editor.js initial config.

```javascript
import Table from '@editorjs/table';

var editor = EditorJS({
tools: {
table: Table,
}
});
```

Or init the Table tool with additional settings

```javascript
var editor = EditorJS({
tools: {
table: {
class: Table,
inlineToolbar: true,
config: {
rows: 2,
cols: 3,
},
},
},
});
```

## Config Params

| Field | Type | Description |
| ------------------ | -------- | ---------------------------------------- |
| `rows` | `number` | initial number of rows. `2` by default |
| `cols` | `number` | initial number of columns. `2` by default |

## Output data

This Tool returns `data` in the following format

| Field | Type | Description |
| -------------- | ------------ | ----------------------------------------- |
| `withHeadings` | `boolean` | Uses the first line as headings |
| `content` | `string[][]` | two-dimensional array with table contents |

```json
{
"type" : "table",
"data" : {
"withHeadings": true,
"content" : [ [ "Kine", "Pigs", "Chicken" ], [ "1 pcs", "3 pcs", "12 pcs" ], [ "100$", "200$", "150$" ] ]
}
}
```

# Support maintenance 🎖

If you're using this tool and editor.js in your business, please consider supporting their maintenance and evolution.

[http://opencollective.com/editorjs](http://opencollective.com/editorjs)

# About CodeX

<img align="right" width="120" height="120" src="https://codex.so/public/app/img/codex-logo.svg" hspace="50">

CodeX is a team of digital specialists around the world interested in building high-quality open source products on a global market. We are [open](https://codex.so/join) for young people who want to constantly improve their skills and grow professionally with experiments in leading technologies.

| 🌐 | Join 👋 | Twitter | Instagram |
| -- | -- | -- | -- |
| [codex.so](https://codex.so) | [codex.so/join](https://codex.so/join) |[@codex_team](http://twitter.com/codex_team) | [@codex_team](http://instagram.com/codex_team) |
555 content.innerHTML = clean(content.innerHTML, customConfig);
to
555 if(!(/<tbody>/i.test(content.innerHTML)))
556 content.innerHTML = clean(content.innerHTML, customConfig);


107 changes: 107 additions & 0 deletions src/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,113 @@ export default class TableBlock {

return wrapper;
}

/**
* Table Tool on paste configuration
*
* @public
*/
static get pasteConfig() {
return {
tags: ["table", "tr", "td", "th"]
};
}

/**
* On paste callback that is fired from Editor
* ready for word table or html table
*
* @param {PasteEvent} event - event with pasted data
*/
onPaste(event) {
if (event.tag = "table") {
//get table body
let tbody = event.detail.data.outerHTML;
//get trs
const trregexp = /<tr[^>]*?>(.*?)<\/tr>/gism;
let tr = [...tbody.matchAll(trregexp)];
//if first item is th,set withHeadings true
if (tr.length > 0 && /<th[^>]*?>.*?<\/th>/gism.test(tr[0]))
this.data.withHeadings = true;
//ups is rowspan place holder
let ups = [];
//each tr line
for (let i = 0; i < tr.length; i++) {
let trmatch = tr[i];
let subdata = [];
//get tds
const tdregexp = /<(t[hd])([^>]*?)>(.*?)<\/\1>/gism;
let td = [...trmatch[1].matchAll(tdregexp)];
for (let j = 0; j < td.length; j++) {
let tdmatch = td[j];
//get colspan,rowspan of td
let colspan = 0;
let rowspan = 0;
let colmatch = tdmatch[2].match(/colspan[^\d]*(\d+)/i);
if (colmatch)
colspan = parseInt(colmatch[1]);
let rowmatch = tdmatch[2].match(/rowspan[^\d]*(\d+)/i);
if (rowmatch)
rowspan = parseInt(rowmatch[1]);
subdata.push((tdmatch[3]).trim());
//cursor of col
let offset = 0;
ups.forEach(function (up) {
if (up[0] == i && up[1] <= j) {
offset++;
}
});
//mark rowspan place holder
while (rowspan > 1) {
ups.push([i + rowspan - 1, j + offset]);
let tmpcol = colspan;
while (tmpcol > 1) {
ups.push([i + rowspan - 1, j + offset + tmpcol - 1]);
tmpcol--;
}
rowspan--;
}
//push "<" to colspan place
while (colspan > 1) {
subdata.push("<");
colspan--;
}
}
//push "^" to each rowspan place
ups.forEach(function (up) {
if (up[0] == i) {
subdata.splice(up[1], 0, "^");
}
});
this.data.content.push(subdata);
}
//some data need standardization, such as "half select tabe" from html
//get max col of content data
let maxcol = 0;
this.data.content.forEach(function (row) {
if (row.length > maxcol)
maxcol = row.length;
});
//add missing data,first line to left,other line to right
for(let k=0;k<this.data.content.length;k++){
while(this.data.content[k].length<maxcol){
if(k==0)
{
this.data.content[k].splice(0,0," ");
}
else
{
this.data.content[k].push("");
}
}
}
//render table
const oldView = this.table.wrapper;
if (oldView) {
oldView.parentNode.replaceChild(this.render(), oldView);
}
}
}

/**
* Extract table data from the view
Expand Down