- Add MANIFEST.in to include utils/ and setup/ in source distributions - Add utils/build_all.py - unified multi-platform build orchestrator (Linux amd64/arm64, macOS amd64/arm64, Windows amd64/arm64) - Add BUILD_LINUX.md - Linux build guide with .deb and AppImage options - Add RELEASE.md - complete release process with versioning (YYYY/MM.####), platform support matrix, and release workflow - Fix .gitignore to exclude UmbraEdit_Projects/, Inner_Demon_1.2a.docm, UmbraEdit_deb_Build_Script.txt, requirements.txt, .DS_Store - All source distributions now include build scripts for Linux packages
214 lines
9.8 KiB
Markdown
214 lines
9.8 KiB
Markdown
# UmbraEdit — Project Scan & Structure
|
|
|
|
Copyright (C) 2026 B.D. Murphy and novelWriter contributors.
|
|
Documentation for the UmbraEdit project (renamed from novelWriter).
|
|
|
|
This document is a structural scan of the **UmbraEdit** codebase. It is intended for developers who want to modify or extend the project.
|
|
|
|
> UmbraEdit was created by cloning **novelWriter** (vkbo/saga-soft) into this folder and renaming the project to `UmbraEdit`. The full upstream git history is preserved (see §6).
|
|
|
|
---
|
|
|
|
## 1. Overview
|
|
|
|
| Property | Value |
|
|
|---|---|
|
|
| **Project name** | UmbraEdit |
|
|
| **Origin** | Renamed/rebased from [novelWriter](https://github.com/vkbo/novelWriter) (vkbo / saga-soft) |
|
|
| **Inherited version** | 26.3b1 (novelWriter v26 series; see `umbraedit/__init__.py`) |
|
|
| **Base version** | Based on novelWrite 2026.02 by Veronica Berglyd Olsen (novelWriter.io), GPL v3.0 |
|
|
| **Language** | Python 3.11+ |
|
|
| **UI framework** | Qt6 via PyQt6 |
|
|
| **Platforms** | Linux, Windows, macOS |
|
|
| **Storage model** | Plain-text project files (one document per scene + a project XML), well suited to Git and file-sync tools |
|
|
| **Formatting** | Minimal Markdown-like syntax plus a metadata syntax for comments, synopsis, and cross-references |
|
|
| **License** | `GPL-3.0-or-later AND Apache-2.0 AND ISC AND MIT` (see `pyproject.toml`, `LICENSE.md`) |
|
|
| **Entry point** | `UmbraEdit.py` → `umbraedit:main()` |
|
|
|
|
**Core idea:** a novel is built from many small plain-text documents organised in a binder/tree, with a composing editor and a compile/export step (DOCX, EPUB, HTML, ODT, Markdown, raw text, QDoc).
|
|
|
|
---
|
|
|
|
## 2. Repository layout (top level)
|
|
|
|
```
|
|
UmbraEdit/ <- this folder (was novelWriter2)
|
|
├── UmbraEdit.py <- application start script (imports umbraedit, calls main)
|
|
├── pyproject.toml <- project metadata, dependencies, ruff/pytest config
|
|
├── uv.lock <- dependency lockfile (regenerate if deps change)
|
|
├── run_tests.py <- pytest runner wrapper
|
|
├── pkgutils.py <- packaging / i18n utility script
|
|
├── README.md <- user-facing project page (mechanically renamed to UmbraEdit)
|
|
├── LICENSE.md
|
|
├── CHANGELOG.md <- historical novelWriter changelog (retains original attribution)
|
|
├── CONTRIBUTING.md
|
|
├── CREDITS.md
|
|
├── AI_POLICY.md
|
|
├── .gitignore
|
|
├── .env.example
|
|
├── docs/ <- Sphinx documentation source
|
|
├── i18n/ <- Qt translation sources (ue_XX.ts) — compiled .qm are gitignored
|
|
├── sample/ <- sample novel project (.nwx + content)
|
|
├── setup/ <- packaging: deb, windows, flatpak, macOS, appimage, icons
|
|
├── tests/ <- pytest suite (core, editor, gui, manuscript, models, story, text, tools, …)
|
|
├── umbraedit/ <- main Python package (was novelwriter/)
|
|
└── utils/ <- build scripts (appimage, debian, flatpak, pypi, windows, assets, docs)
|
|
```
|
|
|
|
**Note:** `AGENTS.md` is gitignored by this project (`.gitignore` line 68). This scan lives in `UMBRAEDIT.md` instead.
|
|
|
|
---
|
|
|
|
## 3. Package layout — `umbraedit/`
|
|
|
|
| Module / package | Responsibility |
|
|
|---|---|
|
|
| `__init__.py` | Application bootstrap, `__version__`, `main()` entry |
|
|
| `config.py` | Runtime configuration, paths, locale/i18n loading (`_ueLangPath`) |
|
|
| `constants.py` | Application-wide constants |
|
|
| `shared.py` | Shared data / singleton state |
|
|
| `enum.py`, `types.py`, `error.py` | Enums, shared types, error handling |
|
|
| `splash.py` | Splash screen |
|
|
| `guimain.py` | Main window / GUI assembly |
|
|
| `core/` | Project model: project, projectdata, projectxml, tree, item, document, storage, sessions, index, indexdata, projectsearch, spellcheck, status, options, coretools |
|
|
| `editor/` | The composing editor: editor, editordocument, highlighter, history, hovercard, header/footer, toolbars, viewer, search, completion, vim mode |
|
|
| `gui/` | Widgets/views: main menu, novel tree, project tree, sidebar, status bar, item details, search, theme |
|
|
| `manuscript/` | Compile/export: manuscript build, document build, settings |
|
|
| `models/` | Qt item models: item, novel, outline, search |
|
|
| `story/` | Outline/story view, story settings |
|
|
| `text/` | Text processing: counting, patterns, formats, autoreplace |
|
|
| `tools/` | Dictionaries, lorem ipsum, welcome, writing stats |
|
|
| `formats/` | Import/export filters: to/from DOCX, EPUB, HTML, ODT, Markdown, QDoc, raw text, TOML, QDoc |
|
|
| `dialogs/` | Preferences, project settings, about, split/merge, labels, links, quotes, word list |
|
|
| `extensions/` | Custom widgets: tab widget, switch, progress bars, event filters, etc. |
|
|
| `assets/` | Icons, images, themes (`.toml`), i18n project JSON, manual, credits |
|
|
|
|
---
|
|
|
|
## 4. How to build and run
|
|
|
|
### Requirements
|
|
- Python ≥ 3.11 (system Python 3.9.6 is **too old** — `match`/`case` syntax requires 3.10+)
|
|
- `pyqt6>=6.4`, `pyenchant>=3.3.0`
|
|
- macOS only: `pyobjc-framework-Cocoa`
|
|
|
|
### Run the application
|
|
```bash
|
|
cd /Volumes/1TB_APL_Storage/UmbraEdit
|
|
python3 UmbraEdit.py
|
|
# or, with the package on PYTHONPATH:
|
|
python3 -c "import umbraedit; umbraedit.main()"
|
|
```
|
|
|
|
### Syntax check (Python 3.11+)
|
|
```bash
|
|
/Volumes/Dock/worstauthor/.local/bin/python3.11 -m py_compile umbraedit/*.py umbraedit/**/*.py
|
|
```
|
|
|
|
### Tests
|
|
```bash
|
|
python3 run_tests.py # full pytest suite
|
|
python3 run_tests.py -m core # run a test marker group
|
|
```
|
|
Test configuration lives in `pyproject.toml` (`[tool.pytest.ini_options]`, testpaths=`tests`).
|
|
|
|
### Linting
|
|
The project uses **ruff** (see `[tool.ruff]` in `pyproject.toml`) and **pyright**.
|
|
|
|
### Packaging
|
|
See `setup/` and `utils/`:
|
|
- `utils/build_debian.py`, `build_windows.py`, `build_flatpak.py`, `build_appimage.py`, `build_pypi.py`
|
|
- `setup/windows/`, `setup/macos/`, `setup/debian/`, `setup/flatpak/`
|
|
|
|
---
|
|
|
|
## 5. i18n (translations)
|
|
|
|
- Translation sources: `i18n/ue_XX.ts` (renamed from `nw_XX.ts`)
|
|
- Compiled `.qm` files are **gitignored** (`i18n/*.qm`, `/umbraedit/assets/i18n/*.qm`) and generated at build time
|
|
- `umbraedit/config.py` loads `ue_<locale>.qm` from `_ueLangPath` (`umbraedit/assets/i18n`)
|
|
- Add a new language: create `i18n/ue_XX.ts` and regenerate the `.qm` with Qt Linguist / `lrelease`
|
|
|
|
---
|
|
|
|
## 6. Git system & Gitea publishing
|
|
|
|
### Current remote state
|
|
```
|
|
upstream https://github.com/vkbo/novelWriter.git (original novelWriter, preserved as reference)
|
|
```
|
|
There is **no `origin`** yet.
|
|
|
|
### What was done in this session
|
|
1. Cloned `https://github.com/vkbo/novelWriter.git` into this folder (`novelWriter2`).
|
|
2. Renamed the project `novelWriter` → `UmbraEdit` (package `novelwriter` → `umbraedit`, entry `novelWriter.py` → `UmbraEdit.py`, i18n `nw_*.ts` → `ue_*.ts`, packaging files, all imports/docs/tests/workflows).
|
|
3. Committed the rename:
|
|
- `70d74e675 chore: rename project from novelWriter to UmbraEdit` (474 files, all renames detected by git)
|
|
4. Archived the previous UmbraEdit (Rust/Tauri, pre-implementation spec project) preserving its git history:
|
|
- `/Volumes/1TB_APL_Storage/Archive/UmbraEdit_archived_20261105/`
|
|
5. Working tree is clean; branch is `main`.
|
|
|
|
### To publish as UmbraEdit on your Gitea server
|
|
A Gitea credential is **not** configured in this environment, and the Gitea server URL is not known yet, so `origin` was intentionally left unset. When ready:
|
|
|
|
```bash
|
|
# 1. Create the "UmbraEdit" repository on your Gitea server first
|
|
# 2. Add it as origin
|
|
git remote add origin <GITEA_URL>/UmbraEdit.git
|
|
|
|
# 3. Push
|
|
git push -u origin main
|
|
|
|
# 4. (Optional) keep pulling upstream novelWriter improvements
|
|
git fetch upstream
|
|
git merge upstream/main # or cherry-pick as desired
|
|
```
|
|
|
|
### Project URLs to update
|
|
`README.md` and `pyproject.toml` currently carry mechanically-renamed GitHub URLs
|
|
(`https://github.com/saga-soft/UmbraEdit`, etc.). Before publishing, replace these
|
|
with your Gitee instance URLs, e.g.:
|
|
- Repository → `https://<gitea>/<owner>/UmbraEdit`
|
|
- Issues → `https://<gitea>/<owner>/UmbraEdit/issues`
|
|
- Homepage / Documentation → your UmbraEdit docs site
|
|
|
|
---
|
|
|
|
## 7. Extension guidance (adding features)
|
|
|
|
The codebase is organised by concern, which makes it straightforward to extend:
|
|
|
|
| To add… | Touch… |
|
|
|---|---|
|
|
| New editor feature / syntax highlighting | `umbraedit/editor/` (editor, highlighter, history) |
|
|
| New project-tree / binder operation | `umbraedit/core/` (tree, project, projectdata, projectxml) |
|
|
| New import/export format | `umbraedit/formats/` (add a `toXxx` / `fromXxx` module) |
|
|
| New settings / preferences UI | `umbraedit/dialogs/preferences.py`, `umbraedit/config.py` |
|
|
| New view / dock panel | `umbraedit/gui/`, `umbraedit/guimain.py` |
|
|
| New data model / Qt model | `umbraedit/models/`, `umbraedit/core/item.py` |
|
|
| New compile/export target | `umbraedit/manuscript/` + a format module |
|
|
| New theme | `umbraedit/assets/themes/*.toml` |
|
|
| New translation | `i18n/ue_XX.ts` (§5) |
|
|
|
|
### Recommended workflow for new features
|
|
1. Create a feature branch off `main`: `git checkout -b feature/<name>`
|
|
2. Implement + add tests under `tests/` mirroring the source layout
|
|
3. Run `python3 run_tests.py` and `ruff` lint
|
|
4. Commit on the feature branch, then merge to `main`
|
|
5. Never let a week of work sit uncommitted (per project convention)
|
|
|
|
---
|
|
|
|
## 8. Files intentionally left as-is
|
|
|
|
| File | Reason |
|
|
|---|---|
|
|
| `uv.lock` | Dependency lockfile; still references `novelwriter` — regenerate (`uv lock`) if dependencies change |
|
|
| `setup/windows/novelWriter.exe` | Binary executable |
|
|
| `umbraedit/assets/images/welcome.webp` | Binary image (may still render "novelWriter" text) |
|
|
| `CHANGELOG.md`, `CREDITS.md` | Historical records retaining original novelWriter attribution |
|
|
|
|
---
|
|
|
|
*Generated as part of the UmbraEdit project setup. Scan date: 2026-11-05.*
|