The plugin is designed to support resilient and feature rich editing within data tables, while being transparent to other styles that might share the line. So, you can/should be able to insert any character based styles such as hyperlinks, font color/size/superscript/subscript, images (from ep_images_extended), etc into cells and they will display as usual. It also supports authorship coloring. Some block styles work but YMMV, ep_align is fully compatible.
Additionally, some other features are supported like real time column resizing and interactions via the tables toolbar.
It is based on ep_tables5 but takes the design in a different direction - ep_tables5 and preceding tables plugins stored the table JSON as text within the pad, this keeps the structure outside of the pad
Does not currently support the timeslider. Actually, I have no idea how to make it support the timeslider. Doesn't support HTML export. Some copy/paste actions can affect the table structure (I am dealing with this in another plugin ep_docx_html_customizer right now, but that is also WIP). Note this plugin is based on/branching from ep_tables5, more attribution will be added soon.
There are probably 1000's of unnecessary lines of code in the plugin, I am planning to clean it up soon, but I have not had time yet. The code was mainly generated by LLMs as I have been brute forcing the features I want for an etherpad based project. o3 summary below:
-
EEJS injection (server,
static/js/index.js)
On pad load the server injects a small toolbar button, inline CSS and a<script>tag that registers the client hooks. -
UI bootstrap (client,
static/js/initialisation.js)
postAceInitbuilds a context menu and a grid picker (like Google Docs) for selecting the initial table size.
Menu actions call the two ACE helpers that the plugin exposes:
•ace_createTableViaAttributes(rows, cols)
•ace_doDatatableOptions(action)(row/column add-delete, etc.) -
Table creation (
static/js/client_hooks.js)
ace_createTableViaAttributescalculates a table id, creates the requested number of Etherpad lines and, for each line, applies an attribute of the form
tbljson::<base64(JSON)>
The JSON contains{ tblId, row, cols, columnWidths, … }. -
Attribute ↔ class round-trip
aceAttribsToClassesconverts the attribute into a DOM class (tbljson-<base64>) so the value survives copy-paste and import.
On the way back in (export, import, or timeslider replay) the server hookcollectContentPre.jsdecodes the class and restores the attribute. -
DOM rendering inside the editor
acePostWriteDomLineHTMLruns every time Etherpad flushes a line to the iframe.
If it sees our attribute it replaces the plain<span>with:<table class="dataTable" …><tr><td>…</td>…</tr></table>
Resize handles are injected into the first row, navigation helpers capture Tab/Arrow keys, etc.
-
Live editing helpers
Navigation helpers (navigateToNextCell,navigateToCellBelow, …) translate cursor moves into line + offset updates so Etherpad OT remains sane.
Structural changes (addTableRowBelowWithText,deleteTableColumnWithText, …) map UI actions to document operations by:
• locating the affected lines viagetTableLineMetadata
• cloning / deleting lines
• updating the JSON attribute. -
Column resizing
startColumnResizeoverlays a transparent drag handle.
On mouse-up the new percentage widths are written back into each row's JSON and pushed throughdocumentAttributeManager. -
Styling (
static/css)
•datatables-editor.cssdraws borders, equalises row height, hides author-colour spans, and styles resize handles.
•caret.csskeeps the caret visible in otherwise empty cells.
•table-menu.cssskins the context menu.
| File / directory | Role |
|---|---|
ep.json |
Hook registration |
static/js/index.js |
Server-side EEJS bridge |
static/js/initialisation.js |
Toolbar + menu wiring |
static/js/client_hooks.js |
All editor logic (attributes, rendering, nav, resize) |
collectContentPre.js |
Server-side attribute reconstruction |
static/js/datatables-renderer.js |
Export & timeslider renderer |
static/css/ |
Editor / UI styles |
templates/*.ejs |
Snippets injected into Etherpad shells |
- Merged cells and table copy-paste are not handled yet.
- Heavy DOM rewrites mean very large tables may impact performance.
- Codebase is still verbose and log-heavy for debugging; expect refactors.

