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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 6 additions & 0 deletions .github/workflows/flutter-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,12 @@ jobs:
BUSYMARK_TYPST_PATH: ${{ github.workspace }}/build/linux/x64/release/bundle/libexec/busymark/typst
run: flutter test

- name: Exercise demand-driven native visualization lifecycle
run: |
xvfb-run -a -s '-screen 0 1280x1024x24' \
env GDK_BACKEND=x11 LIBGL_ALWAYS_SOFTWARE=1 NO_AT_BRIDGE=1 \
bash tools/test_web_render_host.sh

- name: Run real WebKit, PlantUML, Mermaid, OpenAPI, and D2 smoke tests
run: |
xvfb-run -a -s '-screen 0 1280x1024x24' \
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ migrate_working_dir/
/delivery/
/test-results/
/evidence/
/docs/development/evidence/
/docs/development/element-properties*-acceptance.md
/docs/development/nextcloud-notes-milestone-*.md
.widget_preview/
**/node_modules/
linux/flutter/ephemeral/
Expand Down
26 changes: 21 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ Markdown, Writerside, and Nextcloud Notes editor for Linux.

[![busymark](https://snapcraft.io/busymark/badge.svg)](https://snapcraft.io/busymark)

[![Get it from the Snap Store](https://snapcraft.io/en/dark/install.svg)](https://snapcraft.io/busymark)

<a href="https://snapcraft.io/busymark">
<img
src="https://snapcraft.io/en/dark/install.svg"
alt="Get it from the Snap Store"
width="182"
/>
</a>
<p align="center">
<img src="docs/screenshots/busymark-split-view.png" alt="BusyMark split source and reading view" width="900">
</p>
Expand All @@ -15,6 +20,7 @@ Markdown, Writerside, and Nextcloud Notes editor for Linux.
* **Markdown editing** — Source, Editor, Reading, and Split views with formatting tools, syntax highlighting, code folding, tables, images, links, code blocks, callouts, collapsible content, and document diagnostics.
* **Writerside projects** — Open and create Writerside-compatible projects; edit Markdown and XML topics; manage instances, tables of contents, reusable TOC libraries, and project structure.
* **Nextcloud Notes** — Connect to a Nextcloud server, create and edit notes offline, synchronize changes, search and filter notes, manage categories and favorites, and work with attachments.
* **References and links** — Incoming/outgoing references, document/topic/heading target chooser, reviewed local Markdown rename/move, and portable Nextcloud note URLs. See [reference workflows](docs/references.md).
* **Navigation and search** — Files, Topics, and Outline views, tabbed documents, command palette, keyboard shortcuts, document search and replace, reviewed replacement across local workspaces, and Markdown TOC generation.
* **Technical documentation** — Local rendering of Mermaid, PlantUML, D2, fenced OpenAPI specifications, and MathJax mathematical expressions.
* **PDF and HTML publishing** — Export Markdown documents and Writerside instances to configurable PDF or portable offline HTML, with controls for layout, typography, tables of contents, heading numbering, and HTML styling.
Expand Down Expand Up @@ -97,6 +103,7 @@ the current `snap/snapcraft.yaml` in a clean Ubuntu 24.04 amd64 Snapcraft build
environment. The authoritative build sequence is:

```bash
export SNAPCRAFT_BUILD_INFO=1
snapcraft --version
snapcraft expand-extensions
snapcraft clean
Expand All @@ -108,6 +115,7 @@ Inspect and test the exact file emitted by the final `snapcraft` command. A
failed build must not fall back to an older `.snap`. The `snap` job in
[the Linux workflow](.github/workflows/flutter-linux.yml) follows this route,
installs that selected artifact, and runs the strict-confinement smoke checks.
Build information embeds the original recipe for the workflow's identity check.

`tools/build_install_snap_local.sh` is intentionally different: it replaces
the Flutter payload in an installed Snap scaffold for quick development and
Expand Down Expand Up @@ -203,11 +211,15 @@ Once connected, select **Nextcloud Notes** on the welcome screen to reopen the w
### Work with notes

* **Create and edit:** Create notes from the Notes sidebar and edit them using the normal Markdown editor. Use each note’s menu to change its title, category, or favorite status, save a separate local copy, or delete the note.
* **Find and organize:** Search notes by title, content, or category; filter by favorites or category; and see synchronization status in the note list and editor.
* **Work offline:** Edits and new notes are saved to local storage before they are synchronized. Pending changes can survive an application restart. Synchronization runs when a connection is available; the sidebar’s **Refresh** control requests another pass.
* **Find and organize:** Use All notes, Favorites, Uncategorized, Recovery, or a category and its descendants. Sort by activity or title. Ctrl-click toggles selection, Shift-click selects a range, and Ctrl+A selects the current list; the selected-notes action reviews batch favorite/category changes and reports partial outcomes.
* **Quick Open and search:** Ctrl+P finds titles/categories, including unopened cached notes; Ctrl+Shift+P opens the command palette. Notes search combines terms with AND and supports quoted phrases, `title:` / `category:` restrictions, whole words, snippets, and navigation to the match. Unsaved open text is included without forcing a save.
* **Work offline:** Edits and new notes are saved locally before synchronization and survive restart. **Make available offline** retains a note or category/subtree's supported managed media. Its status lists available/missing bytes and offers deliberate retry/cancellation. Offline availability, freshness, and acknowledged synchronization are separate states; external dependencies remain identified.
* **Review conflicts:** If a note changes on the server while you have local edits, BusyMark preserves the competing versions for review instead of silently overwriting one. The comparison workflow supports choosing a version, merging changes, or recovering content as a separate note. Ambiguous note-creation results also require explicit review.
* **Use attachments:** Add files to notes, view supported images and media, and include managed resources when exporting Markdown or HTML. PDF export includes supported images but does not embed arbitrary file attachments. New uploads are limited to **100 MiB per file**.
* **Export or recover:** Export individual notes to PDF or offline HTML, use **Save As** to create an independent local Markdown copy, and restore earlier content through Local History.
* **Export and import:** Keep per-note **Save local copy**, PDF, and offline HTML exports, or export a category/subtree or account as ordinary Markdown with companion media and a versioned metadata manifest. Dirty buffers must save first; missing media is listed explicitly. Import Markdown files/folders or these snapshots through a review of categories, media, and collisions. Imports create distinct notes and resume successful local items after interruption.
* **Recover:** Recovery lists retained deleted notes and available Local History revisions, previews their content/media availability, and recovers as a new note. It uses local retention settings; Nextcloud server trash/history is unavailable.

See the [Notes workspace guide](docs/development/nextcloud-notes.md#everyday-notes-workspace) for search syntax, offline requirements, recovery, and the portable snapshot format.

### Requirements and limitations

Expand Down Expand Up @@ -263,6 +275,10 @@ Issues and focused pull requests are welcome.

Changes should remain consistent with BusyMark's scope as a Linux desktop editor for Markdown, Writerside documentation, and Nextcloud Notes.

Keep temporary execution reports, test-run screenshots, agent session notes, and
acceptance diaries outside the repository; keep reusable tests, fixtures, tools,
and maintained documentation in it.

## License

BusyMark is licensed under the Apache License 2.0. See [LICENSE](LICENSE).
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ are intentionally independent so they can be referenced directly.

- [Supported content and limitations](writerside-support.md)
- [Instances and TOC libraries](writerside-instances.md)
- [Element Properties](element-properties.md): contextual Writerside properties, defaults, drafts, Source integration and navigation.
- [Admonitions](admonitions.md)
- [Collapsible elements](collapsible-elements.md)
- [Videos](videos.md)
Expand Down
8 changes: 5 additions & 3 deletions docs/collapsible-elements.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@ independent disclosure item:
</deflist>
```

Collapsible content is closed initially unless its element has
`default-state="expanded"`. BusyMark preserves the original source and passes
the same documented syntax to Writerside's official build pipeline.
Published state follows authored values, module defaults and the pinned builder's
element-specific rules. Inspect **Element Properties** to see authored overrides
and effective defaults; local editor expansion is separate and source-neutral.
See [Element Properties](element-properties.md) for state-only forms, explicit
false and definition-item inheritance verified against builder `2026.08.0328`.

The syntax follows JetBrains' [Writerside collapsible-elements documentation](https://www.jetbrains.com/help/writerside/collapsible-elements.html).
40 changes: 40 additions & 0 deletions docs/development/nextcloud-notes-api-coverage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Notes API coverage

Contract: Notes API **1.4**, verified Notes **6.0.2** and **6.1.0**. Direct Notes
API integration, one account, schema **6**, existing outbox/coordinator retained.

| Operation | Coverage | State boundary |
| --- | --- | --- |
| GET full `/api/v1/notes` | Chunk cursors, pruneBefore, collection If-None-Match, final ID-only entries | Only a completed authoritative collection advances checkpoints or infers deletion |
| GET `/api/v1/notes/{id}` | Complete 200 and conditional 304; quoted ETag; unconditional retry path when cache is absent | 304 reuses the captured server base, never acknowledges local edits/conflicts |
| GET filtered/reduced collection | Optional exact category and exclude parameters retained on every chunk; omitted fields represented by presence | Query-scoped projections, no full-account checkpoint/validator/deletion inference |
| GET reduced single note | Server-supported exclude projection; identity checked when included | Projection object, no fabricated NoteState defaults |
| POST/PUT/DELETE note | Existing durable outbox, optimistic conflict handling, uncertainty/retry evidence | Existing accepted synchronization strategy |
| GET/PUT settings | Existing conditional/concurrent settings handling and suffix normalization | Existing settings boundary |
| GET/POST attachment | Existing authenticated API 1.4 retrieval/upload and safe managed-reference publication | Existing ownership, generation and uncertainty protections |
| DELETE attachment | Notes 6.1.0 application capability gate retained | Existing unsupported-version explanation |
| Browser `/note/{id}` | Ordinary HTTPS web navigation, installation prefix, real server ID; public routing observation selects the configured pretty/front-controller form | Existing connected-account opening; cached offline or authenticated repository retrieval |

A category filter is exact on the supported servers; it is not a descendant
category synchronization strategy. Exclude can omit ID; ID-only entries repeated
by the final server chunk are continuation evidence, not complete projected
notes. Optional reads do not feed the full-account synchronization checkpoint.
The tagged helper always adds ETag and some internal server fields; projections
retain present fields rather than promising that every excluded server field
will disappear.

The public installation login page's explicit `modRewriteWorking` configuration
selects the web URL form. This anonymous, bounded request never sends account
credentials or follows redirects. A successful HTTP response from the other
form does not prove navigation: on a pretty-URL installation the Notes SPA can
open its most recent note instead. Browser acceptance verifies the intended
note ID and unique content. The optional cached route observation is stored in
the existing account JSON; schema 6 and synchronization checkpoints are unchanged.
BusyMark recognizes both pasted forms internally. Portable heading insertion
is disabled because the verified browser view does not expose BusyMark's heading IDs.

Deterministic retrieval tests are in
`test/src/nextcloud_notes/notes_retrieval_test.dart`; authenticated fixture checks
are in `tools/nextcloud_notes_live_acceptance.dart`. See the
[verification instructions](nextcloud-notes.md#verification) for running them
against isolated HTTPS fixtures.
Loading
Loading