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
)
postAceInit
builds 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_createTableViaAttributes
calculates 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
aceAttribsToClasses
converts 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.js
decodes the class and restores the attribute. -
DOM rendering inside the editor
acePostWriteDomLineHTML
runs 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
startColumnResize
overlays 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.css
draws borders, equalises row height, hides author-colour spans, and styles resize handles.
•caret.css
keeps the caret visible in otherwise empty cells.
•table-menu.css
skins 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.