Skip to content
Merged
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
27 changes: 27 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,33 @@ Key facts:
- Template snapshots reuse the document snapshot dialogs
(`CreateSnapshotDialog` accepts no `MAT_DIALOG_DATA`).

### Editor Schema & Tables

The ProseMirror `Schema` is built in
`frontend/src/app/components/element-ref/extended-schema.ts` from ngx-editor's
base specs + `prosemirror-tables`' `tableNodes()` + Inkweld's own extensions.

**Never construct the `Schema` inside `packages/inkweld-prosemirror`** — the
shared package returns specs only. Building it there pulls a second copy of
`prosemirror-model` into the bundle, which breaks class-identity checks in
y-prosemirror and `EditorView`; typing into the editor then silently produces
no output (see PR #1068). For the same reason `prosemirror-tables` is pinned
in `frontend/package.json`'s `resolutions` block.

Table support deliberately lives in Inkweld rather than in the
`@bobbyquantum/ngx-editor` fork: Inkweld replaced ngx-editor's menu with its
own Material toolbar, so the upstream table PR's menu components would be dead
weight. Only the schema and plugins are used.

**When touching tables, all of these need to stay in step**:

- `extended-schema.ts` — node specs (`cellContent: 'paragraph+'`, `align` attr)
- `document.service.ts` — `columnResizing` (must precede) + `tableEditing` + Tab keymap
- `packages/inkweld-prosemirror/src/xml/tags.ts` — table names in `BLOCK_NODE_NAMES`,
so empty cells don't collapse to self-closing tags and drop columns
- `markdown-to-xml.ts` / `xml-to-markdown.ts` — GFM table parsing and emission
- `markdown-`, `html-`, `epub-`, `pdf-generator.service.ts` — publish output

### File Structure

- Projects contain documents and elements
Expand Down
5 changes: 3 additions & 2 deletions backend/src/mcp/tools/mutation.tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1374,9 +1374,10 @@ registerTool({
title: 'Update Document Content',
description: `Replace the prose content of a document element. Supports two input formats:

- "prosemirror_xml" (default): Inkweld's canonical XML format. Use tags like <paragraph>, <heading level="1">, <blockquote>, <bullet_list><list_item>...</list_item></bullet_list>, etc.
- "prosemirror_xml" (default): Inkweld's canonical XML format. Use tags like <paragraph>, <heading level="1">, <blockquote>, <bullet_list><list_item>...</list_item></bullet_list>, <table><table_row><table_header>...</table_header></table_row></table>, etc.
Example: <paragraph>Hello <bold>world</bold></paragraph>
- "markdown": Standard CommonMark-style Markdown. Lossy formatting (comments, text colors) can be expressed via inline <span data-mark="..."> elements. Element references use <code>[label](inkweld://username/slug/element/{id})</code> links.
Table cells hold block content, so each one wraps its text in a <paragraph>; an optional align="left|center|right" attribute on a cell sets column alignment.
- "markdown": Standard CommonMark-style Markdown, plus GFM tables (including :--- / :---: / ---: column alignment). Lossy formatting (comments, text colors) can be expressed via inline <span data-mark="..."> elements. Element references use <code>[label](inkweld://username/slug/element/{id})</code> links.

The content replaces the entire document. Use get_document_content first to read the current content if you need to make partial edits.`,
inputSchema: {
Expand Down
7 changes: 7 additions & 0 deletions docs/site/docs-user-guide/publishing/formats.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ Each export includes:
- **Document content** — The documents you added to the plan
- **Metadata** — Title, author, language, description

### Tables

Tables export to every format. Merged cells are the one thing that does not
survive everywhere: PDF keeps them, while Markdown, HTML, and EPUB flatten a
merge into the cell plus empty columns so the grid keeps its shape. Column
alignment is preserved in all four.

## Client-Side Generation

Exports are generated entirely in your browser:
Expand Down
1 change: 1 addition & 0 deletions docs/site/docs-user-guide/writing/editor.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ Click the paragraph style dropdown to choose:
| Button | Effect |
|--------|--------|
| Link | Insert or edit a hyperlink |
| Table | Insert a table, or edit the rows and columns of the one you are in |
| Horizontal rule | Insert a scene break line |
| Clear formatting | Remove all formatting from selection |
| Undo | Undo last action (`Ctrl/Cmd + Z`) |
Expand Down
54 changes: 54 additions & 0 deletions docs/site/docs-user-guide/writing/formatting.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,60 @@ Insert a horizontal rule for:

Create with the horizontal rule button in the toolbar.

## Tables

Tables are useful for reference material that sits alongside your prose — magic
system rules, character stat blocks, timelines of regnal years, translation
glossaries.

### Inserting a Table

1. Place the cursor where you want the table
2. Click the **Table** button in the toolbar
3. Choose **Insert table**

A new table starts as three columns by three rows. The first row is a **header
row**, styled differently from the body and preserved when you export.

### Editing a Table

Click into any cell and type. Cells hold ordinary paragraphs, so all the
character formatting above works inside them.

| Action | How |
|--------|-----|
| Move to the next cell | `Tab` |
| Move to the previous cell | `Shift + Tab` |
| Insert a row or column | Table menu → *Insert row/column* |
| Delete a row or column | Table menu → *Delete row/column* |
| Merge selected cells | Table menu → *Merge cells* |
| Split a merged cell | Table menu → *Split cell* |
| Resize a column | Drag the divider between two column headers |
| Remove the whole table | Table menu → *Delete table* |

Select several cells by clicking one and dragging across the others — merge and
alignment actions apply to the whole selection.

:::tip
`Tab` in the last cell does **not** create a new row. Use *Insert row below*
from the table menu when you need more space.
:::

### Tables and Export

Tables export to Markdown, HTML, EPUB, and PDF.

Markdown and EPUB have no way to express merged cells. When you export a table
containing merged cells, the merge is flattened: the cell's text stays in place
and the columns it spanned become empty, so the grid keeps its shape. PDF output
preserves merges.

:::warning
A table always exports with its first row as the header. If you turn the header
row off in the editor, Markdown export will still treat row one as the header —
that is a limitation of the Markdown table format, not of Inkweld.
:::

## Links

### Inserting Links
Expand Down
12 changes: 12 additions & 0 deletions docs/site/docs-user-guide/writing/keyboard-shortcuts.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ When inside a list item:
| Outdent list item | `Ctrl + [` | `Cmd + [` |
| Line break (no new item) | `Shift + Enter` | `Shift + Enter` |

## Table Editing

When the cursor is inside a table cell:

| Action | Windows/Linux | macOS |
|--------|---------------|-------|
| Next cell | `Tab` | `Tab` |
| Previous cell | `Shift + Tab` | `Shift + Tab` |

`Tab` in the last cell does not add a row — use *Insert row below* from the
toolbar's table menu.

## Navigation

| Action | Windows/Linux | macOS |
Expand Down
42 changes: 42 additions & 0 deletions docs/site/docs/developer/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,48 @@ export class MyComponent {
- **WorldbuildingService** - Template/schema system
- **AuthService** - Authentication and session management

### Editor Schema

The ProseMirror schema is assembled in
`frontend/src/app/components/element-ref/extended-schema.ts`. It composes
three sources:

1. ngx-editor's base nodes and marks (`@bobbyquantum/ngx-editor/schema`)
2. `prosemirror-tables`' `tableNodes()` output
3. Inkweld's own extensions from `@inkweld/prosemirror/schema` — the
`elementRef` node plus the `comment`, `autoReview`, and secure `link` marks

`new Schema(...)` is constructed **in the frontend**, never inside the shared
package. The shared package returns specs only; building the `Schema` there
would pull a second copy of `prosemirror-model` into the bundle and break the
class-identity checks in y-prosemirror and `EditorView` — typing would
silently stop working. `prosemirror-tables` is pinned in `resolutions`
alongside the other ProseMirror packages for the same reason.

#### Tables

Table support is layered on `prosemirror-tables` rather than on ngx-editor's
menu, because Inkweld replaced that menu with its own Material toolbar
(`editor-toolbar.component.ts`). Only the schema and the editing plugins come
from the library:

- **Schema** — `tableNodes()` with `cellContent: 'paragraph+'`. Cells are
restricted to paragraphs deliberately: allowing arbitrary blocks would
permit nested tables and headings that no export format renders sensibly.
An extra `align` cell attribute carries GFM column alignment.
- **Plugins** — `columnResizing`, `tableEditing`, and a `Tab` / `Shift-Tab`
keymap, appended to the editor's plugin list in `document.service.ts`.
`columnResizing` must be registered before `tableEditing`.
- **Wire format** — table node names are block-level in
`packages/inkweld-prosemirror/src/xml/tags.ts`, so an empty cell serializes
as `<table_cell></table_cell>` rather than collapsing to a self-closing tag
and desynchronising the row.
- **Markdown** — `markdownToXml` parses GFM tables and `xmlToMarkdown` emits
them, so tables round-trip through the MCP tools and markdown export.
- **Publish** — the HTML, EPUB, and Typst/PDF generators each render tables.
Tables are not yet part of the user-configurable publish-styles system and
currently get fixed built-in styling.

## Backend (Bun + Hono)

### Technology Stack
Expand Down
4 changes: 4 additions & 0 deletions frontend/bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading