Commit Graph
651 Commits
Author SHA1 Message Date
Steffen Becker 48f44f3dcd feat: named list styles — assignment UI and manager tab
setListStyle assigns on the outermost list, clearing the subtree's direct
marker attrs (applying a Listenformatvorlage replaces direct numbering).
Both chromes' bullet/numbering dropdowns grow a "List styles" section split
by the style's level-1 kind, plus a manage entry; the style manager gets a
fourth, flat tab with a per-level editor and a three-level preview. The
decoration now also sets data-bullet — editor.css keys the var()-reading
marker rule on it, so a style's bullet paints (verified live, headless).
2026-08-26 00:38:44 +00:00
Steffen Becker b0de0311a8 feat: named list styles — DOCX round-trip
One shared abstract per style (each list its own w:num instance, so numbering
restarts); a post-pack pass injects w:styleLink and the numbering style's real
numId, which the docx library cannot express. Import follows w:styleLink and
w:numStyleLink — a linked abstract used to resolve to {} and silently import
as a bullet list — maps the style onto listStyleName + sheet.list, and derives
no per-level attrs. Probed: LO ignores DOCX numbering styles both ways (mints
WWNum# on import, flattens to the look on export); ODF carries the identity.
2026-08-25 22:19:14 +00:00
Steffen Becker e2525237de feat: named list styles — model, editor resolution, ODF round-trip
Fourth style family (LibreOffice's Listenformatvorlagen): per-level model in
styles/listStyles.ts, five probed LO built-ins, listStyleName on the outermost
list, one effective-level resolver shared by the decoration walk and the export.
ODF writes the full named text:list-style into styles.xml and repoints
unoverridden lists at it (overrides keep the resolved automatic clone);
import maps named list styles back to the attr + registry, attr-free.
Probed: LO keeps the named reference and display-name across a re-save.
2026-08-25 20:38:15 +00:00
Steffen Becker 7dd997cbfa feat: four draft templates, shelved out of the gallery
Cover letter, CV, invoice and meeting minutes as builder modules on a shared
builders.ts (JSON helpers + the 45mm window-envelope arithmetic), localized
en/de. They sit in the registry's SHELVED list: compiled and schema-checked
per locale by tests/unit/templates.test.ts, but not offered in the gallery
until their content is settled. Gallery gains per-template thumbnails.
2026-08-25 16:03:56 +00:00
Steffen Becker f60a07580c fix: PDF/print export with a placeholder field selected
The selected-node highlight is color-mix(), whose computed value
serializes as a color() function html2canvas cannot parse — the whole
capture aborted. The export clone now strips selection highlights
(which should not print anyway). Reproduced and verified headlessly.
2026-08-25 15:12:05 +00:00
Steffen Becker 162552cdbf feat: add the notation zone to the Form B letter
Two lines above the address (DIN's Zusatz- und Vermerkzone, filled
bottom-up) share their rows with the top of the info block, which now
starts at the norm's 50mm; the lower line carries a notation
placeholder (e.g. registered mail). Measured headlessly: info block
at 50.0mm, notation 54.8mm, address zone from 59.7mm ending 79mm —
inside the window.
2026-08-25 15:12:03 +00:00
Steffen Becker 46c59ffb11 feat: add a personal-letter template
Same window-envelope geometry as the Form B letter (45mm address
field, fold marks), but no info block: a three-line sender block on
top and a right-aligned place/date line instead. The gallery thumb
swaps the info column for a date line on this card. Positions
verified headlessly: return address 44.8mm, recipient 49.8mm, date
flush with the right margin.
2026-08-24 19:51:51 +00:00
Steffen Becker 70888409da feat: draw the fold marks on the right edge too
Both edges help fold the sheet; the punch mark stays left, where the
pages are filed. The exports mirror them as EdenFoldMark<N>R lines
(page width from the ODF page layout / the DOCX page size), the
importers already match on the shared name prefix. Verified headlessly:
5mm from either edge at 87/192mm.
2026-08-24 17:47:01 +00:00
Steffen Becker d2e7ccb48c fix: pin the letter template's mm geometry, measured headlessly
The return-address paragraph gets fontSize 8pt so its line box is 8pt
tall (a 12pt paragraph mark pushed the address zone 1.6mm low), and an
info line with no address half indents 10cm instead of leading with a
tab (a leading tab stays on the default grid). Measured in Chromium:
return address 44.97mm, address zone 49.98mm, info column 124.98mm,
fold marks 87/148.5/192mm.
2026-08-24 17:00:42 +00:00
Steffen Becker 0f8bca31cd feat: built-in template gallery with a DIN 5008 letter
lib/templates/: registry + one module per template, localized via t()
at build time. applyTemplate (App.svelte) reuses the extracted
resetDocumentState() from handleNew, then assigns the template's
margins, styles and fold marks; no file handle, so Save asks where.
Gallery dialog reachable from the ribbon File menu and the modern
chrome; first template is a DIN 5008 Form B business letter built from
placeholder fields, with the address field at 45mm and a 10cm info tab.
2026-08-24 16:54:03 +00:00
Steffen Becker a5c072db23 feat: fold and punch marks (Falzmarken, DIN 5008)
edentext-fold-marks flag: FoldMarkLayer draws the 87/192mm folds and the
148.5mm punch mark per page inside .paper, so print and PDF include them.
Toggled in the Layout tab. Exported as named EdenFoldMark* lines in the
master page's header (ODF page-relative draw:line, DOCX VML v:line);
both importers read the names back into the flag. Roundtrip Leg 32.
2026-08-24 16:27:27 +00:00
Steffen Becker 0753caa5a9 feat: placeholder fields (inline atom + ODF/DOCX round trip)
An inline atom drawn gray as ‹label›: a click selects the whole field,
typing replaces it, Tab/Shift-Tab jump between fields. Exports to ODF
<text:placeholder> (PLH sentinel U+E022) and a DOCX w:sdt content
control tagged edentext-placeholder; both importers read it back, the
export-minted gray stripped. Covered in roundtrip Leg 31 + fuzzDoc.
2026-08-24 16:16:24 +00:00
Steffen Becker ca29ff780b fix: make the recent-files list only offer files it can reopen
A file opened without a File System Access handle (no API — Firefox,
Safari, Brave — or a template) is no longer recorded: nothing could
ever reopen it, so every click failed and dropped the entry. A startup
prune clears such stale entries. Reopening now asks for 'read' instead
of 'readwrite' (Save re-prompts on its own), and a declined permission
prompt keeps the entry — only a moved or deleted file drops it.
2026-08-23 18:54:52 +00:00
Steffen Becker 91a1ecb26d style: brand the link-preview image with the logo header
Icon + wordmark above the screenshot on the light chrome color,
same 1200x630 frame.
2026-08-22 12:10:04 +00:00
Steffen Becker dca155ddd6 chore: add a single-entry sitemap.xml 2026-08-22 11:45:37 +00:00
Steffen Becker 236aad826d chore: add robots.txt (allow all, point at the sitemap) 2026-08-22 11:45:29 +00:00
Steffen Becker 8ba1fefb62 feat: serve a static intro paragraph to crawlers and noscript browsers
The block lives inside #app and is removed right before mount,
since Svelte's mount() appends rather than replaces.
2026-08-22 11:45:09 +00:00
Steffen Becker 0c420b8765 feat: add Open Graph tags, a canonical URL and a 1200x630 preview image
Shared links now render a preview card; the image is the README
screenshot center-cropped to the standard card ratio.
2026-08-22 11:44:05 +00:00
Steffen Becker 742cf97571 chore: add the Google Search Console site-verification file 2026-08-22 11:03:37 +00:00
Steffen Becker 4a87d5eb23 feat: add a meta description for search results and crawlers
The README's opening pitch, trimmed to Google's ~160-character
snippet length.
2026-08-22 10:35:06 +00:00
Steffen Becker 96e5b2fc87 fix: the PWA install icon uses the current logo
The icon PNGs still carried the old two-leaf motif; only favicon.svg was
updated in the redesign, and Chrome takes the PNGs for the install icon.
Re-rendered both from the current logo, added a padded maskable variant
so Android's mask no longer clips the leaves, bumped the service-worker
cache so existing installs drop the stale icons, and removed the
unreferenced old favicon and wordmark files.
2026-08-21 15:39:19 +02:00
Steffen Becker 5034ac7d6f docs: add an editor screenshot to the README
docs/screenshot.png sits right before the Features section, linked to
the app. Plain Markdown image syntax, so the VS Code preview renders
it too; the title bar's file name is painted out.
2026-08-20 18:59:53 +02:00
Steffen Becker 05b3f4a28b fix: first-run spell-check language follows the browser locale
loadDocumentLanguage falls back to resolveBrowserLocale() instead of a
hardcoded 'en', so a de-* browser starts with the German dictionary. A
saved choice and the document's own fo:language still win.
2026-08-20 15:19:23 +02:00
Steffen Becker c336127006 fix: ship every bundled MIT notice and link licenses.txt in About
collect-licenses falls back to the README's License section (only when it
carries a copyright line) for packages without a LICENSE file; hash.js and
isarray now ship their full notice. The About dialog links /licenses.txt,
which was previously reachable only by knowing the URL.
2026-08-20 15:15:52 +02:00
Steffen Becker 6bbf4286c3 style: the floating-island chrome is dev-only in the menu
The appearance menu's "Modern (beta)" entry sits behind
import.meta.env.DEV, so a production build offers no way into the
island chrome until it catches up with the ribbon. The chrome itself
and a stored 'modern' pref keep working.
2026-08-20 14:56:48 +02:00
Steffen Becker a7522547b7 fix: the table dialog flips below a table it would cover
The formula/sort/split popover hangs above the table's top-left corner;
with the table at the top of the page the keep-in-view clamp slid it
down over the table itself. With no room above, the dialog now opens
below the table when that fits the viewport, and only a table filling
the whole window keeps the old clamp.
2026-08-20 14:37:18 +02:00
Steffen Becker de7f63f269 fix: Enter frees the caret from a leading table
At the very first position of a table with no block before it, Enter
inserts a paragraph above the table and moves the caret there, as both
word processors do — previously the caret could never get before such
a table. Generic first-child check, so it also covers a table leading
a cell, text box or columns section.
2026-08-20 14:26:57 +02:00
Steffen Becker 8537fd0106 fix: zooming the page grid keeps the view anchored
The grid snapped the scroll to the top of the first row on every zoom,
losing the reader's place whenever it sat mid-row and ignoring the
pointer anchor of a trackpad zoom. It now uses the same anchor logic as
a single pane, measured against the grid canvas: the pointer for a
wheel zoom, else the viewport top; firstRow is re-read after the write
so the page cells re-aim immediately. Measured drift < 1px across a
92% -> 194% wheel burst.
2026-08-20 12:26:03 +02:00
Steffen Becker fb59a30b63 fix: defer the toolbar tick past Svelte's flush
Tearing down the focused pane's DOM on a layout switch fires blur
synchronously inside Svelte's commit; TipTap answers with a focus-meta
transaction, and onTransaction's tick write threw state_unsafe_mutation
there — aborting the handler before the other panes got the new state.
The tick now bumps in a microtask, after the flush, before paint.
2026-08-20 12:25:27 +02:00
Steffen Becker c6aae13a9e fix: the page count survives switching the pane layout
The pm-pagecount listener sat on the hosts[0] element, which Svelte
replaces when the pane layout changes (multi-page grid, split view).
The editor view moves to the new host, the listener died with the old
one — numPages froze, so no new page ever appeared in the grid.
Listen on the view's own DOM instead, which is only ever re-parented.
2026-08-20 11:57:20 +02:00
Steffen Becker ab79740787 style: the inline-wrap icon shows the object in the line
Three bare lines said nothing and read the same at any size. It now draws
the box on the text baseline like the floating toolbar's glyph, with the
outlined object the other three wrap icons use.
2026-08-20 00:24:04 +02:00
Steffen Becker 2436deb3bf style: Shape Format follows the caret, and carries vertical text
The tab only showed while the box was node-selected, so it vanished the
moment you clicked in to type — the floating toolbar stayed. It now reads
findTextBox(), the same box that toolbar reads; an image selected inside a
box still shows Picture Format alone. Vertical text was the one control the
tab was missing, now a Text group of its own.
2026-08-20 00:23:46 +02:00
Steffen Becker 7b3348ca6e docs: add contributer list 2026-08-19 18:56:17 +02:00
Steffen Becker a87e7a4ada fix: a heading's style name never lands on a plain paragraph
styleName was kept on split, so Enter at the end of a heading left a paragraph
carrying it: drawn like a heading, absent from the navigator's outline, exported
as text:p. It is no longer kept there. setParagraphStyle also missed the name
whenever it switched the node type — a following updateAttributes looks for the
new type in the pre-chain state — so it now rides along with setNode. Levels 2–6
never reached that command at all: the digit class built from MAX_HEADING_LEVEL
(10) read as [0-1], so Heading's own Mod-Alt-N took the key and set a level with
no style; that keymap is dropped, running ahead of every plugin binding.
2026-08-19 18:41:21 +02:00
Steffen Becker 78b732ac44 update link to custom domain 2026-08-19 09:03:21 +02:00
Steffen Becker fda166103f ci: 20-minute job timeouts
A hung apt mirror on the runner otherwise holds a job until the
6-hour default limit; every job normally finishes in minutes.
2026-08-18 22:30:37 +02:00
Steffen Becker fc20e0a89c fix: improve saving where the File System Access API is unavailable
The fallback download shows a one-time hint about the browser's
ask-where-to-save setting, keeps its anchor in the DOM and the blob
URL alive past the click (Gecko). Failed saves and exports now report
the underlying error, with a clear message when a script blocker
prevented a lazy chunk from loading. A full or blocked localStorage
no longer fails the save when recording the recent-files entry.
2026-08-18 19:56:32 +02:00
Steffen Becker f1b63c722c feat: the build ships its dependency licenses and its commit
The minifier strips every legal comment, so the bundle reached users without
the notice MIT and Apache-2.0 require to travel with a copy. collect-licenses
quotes all 97 bundled packages into public/licenses.txt, which deploys like the
font and dictionary licenses do. The About dialog's version now carries the
short commit, so a user of the hosted app can identify the source it was built
from - what AGPL 13 asks for and a fixed 0.1.0 could not answer.
2026-08-18 16:44:42 +02:00
Steffen Becker 946b7e44be chore: package.json names the real repo, homepage and contact
author, homepage and repository.url were still the scaffolding placeholders.
2026-08-18 10:33:16 +02:00
Steffen Becker 7e0f9ca617 docs: the font licenses ship with the fonts, the notices name them all
public/ is copied verbatim into the build, src/assets/ is not - so the fonts
were deployed without the license texts that OFL-1.1 and Bitstream Vera require
to travel with them. Moving the texts to public/font-licenses/ fixes that with
no build step. The notices covered only Liberation and missed five bundled
dependencies; the commercial license now states what it cannot relicense, the
copyleft German dictionary and thesaurus above all.
2026-08-18 10:33:10 +02:00
Steffen Becker 2f9dd3cdf7 docs: the CLA asks for the phrase its bot actually accepts
The signing instructions named a phrase the workflow ignores, and told
contributors to put it in the PR description rather than a comment - following
them left a PR blocked forever. Both files now quote the action's own phrase.
Drops the note that CLA Assistant still had to be set up; it is running.
2026-08-18 10:33:03 +02:00
Steffen Becker 36ffd6e768 docs: CONTRIBUTING lists the test commands instead of denying a suite
The setup section still claimed no test suite existed. It now names check,
test, test:lo and test:smoke, and what CI runs of them; the linter note stays,
since none is configured.
2026-08-18 09:21:16 +02:00
Steffen Becker 1f039990d1 docs: the changelog names both chromes, the ribbon as default 2026-08-17 23:12:20 +02:00
Steffen Becker 810846b00c test: the smoke test exports its PDF through the ribbon's File menu
The save chevron it clicked lives in the modern island, which a fresh
profile no longer mounts since the ribbon became the default.
2026-08-17 23:10:08 +02:00
Steffen Becker 10b650c64c refactor: the floating island's mode id is 'modern', matching its label
The id said 'classic' while the UI called the ribbon Classic and the
island Modern (beta). Type, i18n keys, comments and docs now agree;
a stored legacy 'classic' still selects the island.
2026-08-17 20:05:15 +02:00
Steffen Becker 501bfe501f fix: a first visit opens the ribbon, not the floating island
The tabbed chrome is the layout users know; the stored choice still wins.
2026-08-17 20:03:06 +02:00
Steffen Becker 95530c6f07 docs: README pitch sharpened, beta status called out
Beta badge and note: actively developed, occasional bugs expected,
keep backups.
2026-08-17 19:43:12 +02:00
Steffen Becker 6bec446dfe ci: deploy to GitHub Pages on push to main 2026-08-17 18:59:48 +02:00
Steffen Becker 3ae8d27b26 fix: the build runs under a subpath, not only at the domain root
base './' emits relative asset URLs; the manifest, the service-worker
registration and sw.js's precache resolve against their own location;
the four hardcoded /image literals turn relative. Verified headless
under a simulated /edentext/ subpath: boots, types, SW scope correct.
2026-08-17 18:59:48 +02:00
Steffen Becker b37261375a docs: 0.1.0 release date moves to the Pages launch day 2026-08-17 18:59:48 +02:00