Add project-mode tooling: characters, outline, diff and revision status
Rounds out project mode, where the workspace is the project root and one subfolder holds the manuscript proper: - Characters and Outline windows, backed by new `characters` and `outline` modules that read the cast from character sheets and measure how much of the snowflake outline is actually written. - Edit ▸ Changes… diffs the open file against its last committed version. - Revision status, per-file and project word counts, an archive action and hidden folders in the file panel. - Chapter-file export alongside the ODT master, richer header parsing, and a project word list for names and invented terms. - The export path now follows the workspace: opening a project points it at that project root, keeping a file name you chose yourself and re-deriving one that merely echoed the folder it sat in. - Clicking an issue in the grammar/spelling panel takes the editor to it, selecting the words and centring them; applying a suggestion jumps to the rewritten text as well. README covers the new windows and workflows. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017bSn3Xijp8GofZVUnRX4oq
This commit is contained in:
@@ -145,6 +145,50 @@ A single number (`## Word Count Target: 1800`) sets a point goal; ranges accept
|
||||
`-`, `–`, `to`, and grouped digits (`1,500`). Like the other header lines, the
|
||||
target is stripped from the exported document.
|
||||
|
||||
## Project mode
|
||||
|
||||
Open a **project root** — a folder holding the manuscript alongside the
|
||||
characters, outline, premise and the rest — and the app recognises the layout
|
||||
instead of treating every file in it as a chapter.
|
||||
|
||||
The trigger is simple: if the folder you open contains a subfolder named like
|
||||
the **manuscript folder** (`06-First Draft` by default), it is a project. A
|
||||
plain folder of chapters has no such subfolder, so it behaves exactly as before
|
||||
— everything in it is the manuscript.
|
||||
|
||||
In a project:
|
||||
|
||||
* **Files under the manuscript folder are the book.** They are ordered,
|
||||
numbered, and they are what **Export ODT** concatenates. Chapter numbering
|
||||
counts only them, so a defaulted title is `3.` because it is the third
|
||||
*chapter*, not the third file in the project.
|
||||
* **Everything else is reference** — character sheets, the outline, the scratch
|
||||
pad — and is **not listed in the file panel**, which stays about the book.
|
||||
Reference material is reached through the windows that understand it
|
||||
([Characters](#characters-tools--characters), [Outline](#outline-tools--outline)),
|
||||
and it stays out of the order and out of the export.
|
||||
|
||||
Turn on **View ▸ Show reference files** to list it in the tree anyway, dimmed,
|
||||
with the manuscript folder tagged **· manuscript**.
|
||||
* `order.json`, `titles.json` and `wordlist.json` live at the **project root**,
|
||||
so one word list covers the whole project rather than one folder of it.
|
||||
* **File ▸ New project…** opens the project root, not the drafting folder.
|
||||
|
||||
Set which folder is the manuscript under **Settings ▸ New project… ▸ Manuscript
|
||||
folder**. The number is optional — `First Draft` matches `06-First Draft` — and
|
||||
the setting is global, so every project on this machine uses the same layout.
|
||||
If your writing actually lives in `05-Plot`, point it there.
|
||||
|
||||
### Hidden folders
|
||||
|
||||
An archive of superseded drafts can hold hundreds of files that would swamp the
|
||||
tree, so folders named like **`Archive`** are skipped by the scan entirely — the
|
||||
same treatment `target/` and `node_modules/` already get. The match ignores a
|
||||
leading number, so `10-Archive` is covered.
|
||||
|
||||
Change the list with `hidden_folders` in
|
||||
`~/.config/md-manuscript/config.json`; set it to `[]` to see everything.
|
||||
|
||||
## Organising with folders
|
||||
|
||||
The file list is a tree. Any `*.md` file at or below the workspace is part of the
|
||||
@@ -182,6 +226,101 @@ bottom**, so the order you see down the left is the order the chapters are
|
||||
concatenated in, folders and all. Chapter numbering follows the same sequence,
|
||||
so a defaulted title in `part-2/` continues counting from `part-1/`.
|
||||
|
||||
## Working on the novel's other parts
|
||||
|
||||
A manuscript project is more than its chapters. These read the rest of it.
|
||||
|
||||
### Hiding the header while you write
|
||||
|
||||
A scene card's fields sit at the top of the same file as its prose, and once
|
||||
drafting is under way they are mostly in the way. **View ▸ Hide header in
|
||||
editor** folds away everything above the draft marker, leaving the prose alone
|
||||
in the editor. A single line above the editor says so — `▸ header hidden (8
|
||||
fields)` — and clicking it flips back.
|
||||
|
||||
While the header is hidden it is genuinely **not in the editor's text**: the
|
||||
file is put back together on save, so what lands on disk is unchanged. Doing it
|
||||
that way rather than merely scrolling past the header means search, replace,
|
||||
spelling underlines and the caret all address exactly what you can see, with no
|
||||
offsets to go wrong. Everything that wants the whole file — the chapter title
|
||||
hint, the word-count target, the file-list tooltip — still reads it whole.
|
||||
|
||||
Files with no draft marker have nothing to fold, so the line does not appear.
|
||||
|
||||
### Characters (Tools ▸ Characters…)
|
||||
|
||||
Reads the project's character sheets — a file whose level-1 heading is the name,
|
||||
as either `# Bixby Reynolds` or `# Name: Jonathan Bronski`. For each character
|
||||
it shows:
|
||||
|
||||
* their descriptor, from a `Slug:` field or the heading beneath the name;
|
||||
* **which scenes they appear in**, by matching the `Characters:` line of every
|
||||
manuscript file. A first name matches a full name, so `Characters: Bixby, Mom`
|
||||
finds *Bixby Reynolds*. Click a scene to open it;
|
||||
* **▦ Rebuild grid**, which regenerates the project's `character_grid.md` from
|
||||
the sheets as a markdown table. A hand-kept grid drifts the moment a sheet
|
||||
changes; this one cannot. Long values are trimmed, since a grid is a
|
||||
quick-look summary.
|
||||
|
||||
### Outline (Tools ▸ Outline…)
|
||||
|
||||
The snowflake outline files are scaffolds of HTML comments, one per beat
|
||||
(`<!-- Midpoint: A major turning point. -->`). The app strips comments, so
|
||||
these files otherwise render and export as *blank* — there is no way to see how
|
||||
much of the outline exists.
|
||||
|
||||
This window reads the scaffold back: every beat it names, and whether prose has
|
||||
been written under it, with a progress bar over the whole outline. A beat counts
|
||||
as written when there is ordinary text between its prompt and the next one.
|
||||
|
||||
Beats generated by [the Mistral tool](#plot-beats-mistral) can be appended
|
||||
straight into the matching act file with **📝 Append to act_0N.md**, which
|
||||
appears when a run filled exactly one act. It appends under a dated comment
|
||||
rather than replacing, because the prompts are the reason the file is worth
|
||||
keeping.
|
||||
|
||||
### Revision status
|
||||
|
||||
Give a file a `Status:` header line and the file panel shows a compact badge for
|
||||
it (initials, so `Structural Edit` becomes `SE`) and offers a **Status** filter
|
||||
above the list. The filter narrows the tree to one stage — every file you have
|
||||
still to proofread, say.
|
||||
|
||||
### Archive
|
||||
|
||||
**🗄 Archive** moves the selected file into the project's archive folder,
|
||||
keeping its place inside it (`Act 1/scene.md` → `10-Archive/Act 1/scene.md`).
|
||||
It leaves the manuscript order and, since archive folders are
|
||||
[hidden](#hidden-folders), the file panel — but stays on disk. Deleting is for
|
||||
things you want gone; this is for things you have moved past.
|
||||
|
||||
### Changes since the last commit (Edit ▸ Changes…)
|
||||
|
||||
Diffs the open file against its committed version, coloured the way git colours
|
||||
a diff. Revising is comparing, and the repository already holds the answer.
|
||||
|
||||
### Word counts
|
||||
|
||||
The status bar carries the open file's word count, its change this session, and
|
||||
the **whole manuscript's total**. Reference files are not counted.
|
||||
|
||||
### Manuscript details (Settings ▸ Manuscript details…)
|
||||
|
||||
Title and author, written into exported `.odt` files as their document
|
||||
properties — what a word processor shows under File ▸ Properties. A blank title
|
||||
uses the project folder's name. Exports previously carried no metadata at all.
|
||||
|
||||
### Exporting chapter files (File ▸ Export chapters + master)
|
||||
|
||||
Writes one `.odt` per chapter into a `chapters/` folder, plus an `.odm` master
|
||||
document that links them — the shape the template's `Full Text.odm` implies.
|
||||
|
||||
**The per-chapter files are the reliable part**: they are ordinary documents and
|
||||
open anywhere. The master is a shell with a title page and one linked section
|
||||
per chapter; LibreOffice does not follow those links when it opens the file, so
|
||||
treat it as a starting point to relink rather than as the assembled book. For a
|
||||
single finished document, use **Export ODT**.
|
||||
|
||||
## New projects from a cookiecutter template
|
||||
|
||||
**File ▸ ✨ New project…** scaffolds a whole manuscript project from a
|
||||
@@ -300,6 +439,37 @@ results take over the underlines until you next edit the text — at which point
|
||||
the live offline checker resumes. In other words, LanguageTool is used when it's
|
||||
available and current; the offline checker is the always-on default.
|
||||
|
||||
### The word list (names and invented terms)
|
||||
|
||||
No Hunspell dictionary knows your characters, so without somewhere to record
|
||||
them a novel's cast is underlined on every line of every scene. **Settings ▸
|
||||
Word list…** is that place.
|
||||
|
||||
* **Right-click an underlined word** in the editor and choose
|
||||
**📗 Add “…” to the word list**. The underline goes immediately — there is no
|
||||
wait for the next check.
|
||||
* **👤 Add character names** reads the project's character sheets and lists
|
||||
every name in them at once. It looks for a `Characters` folder (a numeric
|
||||
prefix like `03-Characters` is fine) beside the workspace and up to three
|
||||
levels above it, so it still finds them while you are editing in
|
||||
`06-First Draft`. Both `# Bixby Reynolds` and `# Name: Jonathan Bronski`
|
||||
headings are understood, and an unfilled template sheet (`# Name`,
|
||||
`# Protagonist`) contributes nothing. Each part of a name is listed
|
||||
separately, since prose says *Bixby* far more often than *Bixby Reynolds*.
|
||||
* Words can also be **typed in** directly, and taken back out with **✖**.
|
||||
|
||||
Matching is case-insensitive, and a listed name covers its **possessive and
|
||||
plural** — `Bixby` accepts `Bixby's`, `Bixbys` and `Bixbys'` — because the
|
||||
tokenizer hands the checker `Bixby's` as a single word.
|
||||
|
||||
The list is saved as **`wordlist.json`** in the workspace, beside `order.json`
|
||||
and `titles.json`, so it is committed to git and travels with the manuscript. It
|
||||
is a plain sorted JSON array, and a corrupt or hand-mangled file is treated as
|
||||
empty rather than stopping the checker.
|
||||
|
||||
Note that the list belongs to the *workspace*, not the whole project — open a
|
||||
different folder of the same project and it has its own list.
|
||||
|
||||
The bundled dictionaries live under `dictionaries/` and are derived from
|
||||
[SCOWL](http://wordlist.sourceforge.net/) under a permissive license (kept
|
||||
alongside them in each `license` file).
|
||||
@@ -467,8 +637,12 @@ only triggers in the header region, never in the prose below the marker.
|
||||
| `<workspace>/**/*.md` | your manuscript files, in folders if you like |
|
||||
| `<workspace>/order.json` | the manual ordering, as paths (committed to git) |
|
||||
| `<workspace>/titles.json` | chapter-title overrides, keyed by path (committed to git) |
|
||||
| `<workspace>/wordlist.json` | names the spell checker accepts (committed to git) |
|
||||
| `~/.config/md-manuscript/config.json` | last workspace, export path, prefs, new-file template, project/Gitea settings |
|
||||
|
||||
In [project mode](#project-mode) the workspace is the project root, so those
|
||||
three bookkeeping files sit there and cover the whole project.
|
||||
|
||||
## Markdown supported in ODT export
|
||||
|
||||
Headings, paragraphs, **bold**, *italic*, ***both***, `inline code`, fenced/indented
|
||||
|
||||
Reference in New Issue
Block a user