Skip to content

Releases: jonmichaels/ctrl-kd

v4.10.1

Choose a tag to compare

@jonmichaels jonmichaels released this 26 Oct 14:30

Fixed

  • -t markdown --pictures embed now exports and links the pictures, as
    -t md always did.
    The command line checked the format name as typed, so
    the long name skipped the picture export and the degradation note that the
    short one gave. It now checks the format itself, whichever name was typed.

  • A Printed document with footnotes, endnotes or annotations now lays out
    exactly like one without, apart from the note area itself.
    The two had
    separate paginators, and the one for notes had drifted: it ignored .psb/
    .psa, the .pm first-line indent and the per-line .sr roll, dropped a
    print control's declared width when a heading restyled it, kept columns
    only until the first wrap, never resolved the even/odd page offset
    (.poe/.poo), stamped no per-page margin, length or orientation, and
    gave every page the document's last running head instead of the one in
    force on it. There is one paginator now; the note area (growth, the
    three-line floor, continuation, endnotes at the end) is a feature it runs
    when the document has notes. A note-bearing document's layout JSON now
    carries each page's own running head and foot, and its trailing blank lines
    are stripped like any other page's. A block that opens on a blank line
    enters its first text line at the style's own leading, notes or not
    (measured against real WordStar 7 on LYING.WS).

v4.10.0

Choose a tag to compare

@jonmichaels jonmichaels released this 17 Sep 16:48

Added

  • A page can declare its own sheet. .pr or= (landscape/portrait)
    measured against real WordStar 7: set at the top of a page it applies to
    that page immediately; set in the middle of a page it waits for the next
    page boundary, exactly as WS7 does. The Printed PDF now draws each page on
    its own sheet size instead of one page size for the whole document, and
    the running head/foot and automatic page number follow that page's own
    height (a landscape page's number no longer resolves off the top of a
    portrait document). layout JSON version 13 publishes a page's own size
    (width/height/orientation) only where it differs from the document's — the
    same "omit unless it differs" rule every other per-page field here already
    follows; a page that never changes size emits nothing new. Modern is
    unchanged by design — it composes on one reflowed sheet regardless of what
    the source document's pages asked for.

  • The layout JSON says when a running head, foot or page number is off the
    paper
    (version 12). WordStar commands such a row anyway and lets the printer
    clip it — real WordStar 7 prints put the automatic number 14.4pt below the
    bottom edge of a Letter sheet when .mb is smaller than .fm — so the PDF is
    unchanged and still draws it there, with the page as its clip. A program
    drawing pages from this JSON has no paper to clip with, so such a row now
    carries off_sheet: true and must not be drawn. The key is absent, not false,
    on every row that is on the sheet.

Fixed

  • Page furniture is set in the document's own face, not in Times. Running
    heads, running feet, the automatic page number and footnote/endnote text were
    written in a hardcoded face and size in the RTF exports and in the Modern PDF
    — Times New Roman 11 on a Printed page whose body is Courier 12, on every page
    of a running-head document. They resolve through the same font chain body text
    does now: a .h#/.f# that opens a font block prints in THAT face and size
    (22 documents in the public test corpus, which the Printed PDF has always
    honoured and the other three surfaces threw away); a head that declares
    nothing takes the mode's body face — Courier in Printed, the reading face in
    Modern, Courier in a document that declares itself non-proportional. Sizes
    follow the same rule: Printed furniture is the body's size, Modern furniture
    is the body size less 2pt (12pt against Modern's 14pt body, where the RTF and
    the Modern PDF both used 11). Printed PDF is unchanged — it was already right.

  • Modern: a list bullet and its text no longer read as one crowded word.
    The square bullet was drawn on the same fixed-pitch cell Printed uses, but
    the space after it was measured in the reading face — 3.5pt against the
    cell's 7.2 — so the item's first word sat about half as far from the bullet
    as it does in the Printed and Native views. It is now one cell, as it is
    there: the first word starts two cells past the bullet in all three views.
    Also fixed in the Modern RTF's hanging indent, which had computed a third
    number again. Only bullets whose marker is a cp437 block glyph are
    affected; a * or - marker is a real letter in the reading face and
    keeps the spacing it had.

  • Markdown: text that used to vanish now survives. A document that
    literally says <SP>, <Enter> or <B> had that read as an HTML tag by
    every Markdown renderer, which showed NOTHING — the word disappeared.
    (<B> was worse: a real tag, switching bold on with nothing to switch it
    off.) < and & are escaped now. Affects Sawyer's macro and patch
    documentation heavily; none of the shipped samples.

  • Markdown: strikeout no longer breaks where a bold or italic word sits
    inside it.
    The emitter closed the strikeout and reopened it with nothing
    in between (~~alpha~~~~**beta**~~~~gamma~~); four tildes are not
    strikethrough in any flavour, so the strike was lost AND the tildes showed
    up as text. The run is merged now.

  • Markdown: a verse or stanza containing a blank line no longer emits a
    line of invisible whitespace.
    The two-trailing-spaces hard break turned
    such a blank into a line holding just two spaces, which CommonMark reads as
    a blank line — so the paragraph split anyway, into pieces whose raw text
    claimed otherwise. A blank line ends the unit now, which is what it always
    rendered as. The dangling trailing spaces at a unit's end go too.

    All three are Modern-mode Markdown only. A Printed-mode body, and any
    print-stream or ruler-driven document in either mode, is a fenced code
    block whose content is literal and is untouched.

  • ctrl-kd --version no longer prints a Python SyntaxWarning ahead of its
    own output. A docstring cited RTF's \margr control word inside a plain
    (non-raw) string, so Python read \m as an escape sequence it did not
    recognise and warned about it. Nothing was broken, but the warning named a
    file inside the package and was the first thing a new Homebrew or PyPI user
    saw, which reads like a crash. It appeared only on a COLD bytecode cache —
    the first run after an install — which is why no development machine ever
    showed it. Every module is now compiled with warnings as errors by both the
    test suite and tools/run-full-suite.sh, so it cannot come back.

  • Printed RTF's text column is the document's own ruler width, not a
    fixed arithmetic off the page margins.
    The column had been computed as
    paper width minus twice the left margin, which has nothing to do with what
    the author actually typed the page to hold; at the ordinary default it came
    out one character narrower than a common 69-character line, so thousands of
    facsimile lines across the public corpus arrived re-wrapped by the reader —
    the one thing Printed mode exists to prevent. The column now follows the
    widest ruler in the document (or the longest printed line itself, when box
    art or a print stream runs past its own ruler), and the page grows to fit
    it, up to Word's own maximum page size. A document whose lines are wider
    than even that still re-wraps in the reader — there is no page any reader
    accepts that would hold them, and that group shrank from 132 documents to
    32 in a full sweep.

  • A reverse-video banner ("white on black") is visible in RTF and HTML,
    not white text on a white page.
    Both exporters kept WordStar's white
    colour but never painted the black ground behind it, so the words were
    simply not there — three documents in the public corpus lost a banner this
    way, one of which says outright in its own text that it should read white
    on black. The ground is drawn now; turning off inline styling removes it
    along with the colour, same as it always has for every other colour.

  • A Printed HTML page is no longer twice as tall as the document. The
    facsimile block already breaks a line on its own newline; the emitter was
    also writing a <br> at the end of every line, so each line was followed
    by a blank one. A 57-page document rendered at double height with its line
    grid gone. The extra break is removed.

  • Newspaper-style columns (.co) render as one column block per section,
    in both Printed and Modern HTML
    , not one box per paragraph. Modern had
    been opening a fresh pair of columns for every paragraph in a columnar
    region, which balances each paragraph on its own and leaves ragged,
    half-empty columns underneath; Printed dropped the columns entirely. Both
    now open a single container for the whole section, closing it only where
    the document itself ends the columns.

  • A Modern HTML page no longer scrolls sideways on a phone. The Modern
    stylesheet had no line-length limit at all — a wide window gave a line
    roughly twice a comfortable reading length, and at phone width a long path,
    a run of control words, or a wide row of block graphics pushed the whole
    page off the edge of the screen. Modern HTML now keeps a reading-width
    column and lets only the one unbreakable row (an embedded picture) scroll
    inside itself, the way the Printed facsimile already does. Printed HTML is
    untouched — it was already narrow enough.

Changed

  • Every quirk was renamed, and the names that shipped in 4.9.0 still work.
    A quirk's name is text a reader reads and types — --list-quirks prints it,
    --quirk/--no-quirk take it, the layout format publishes it — so the six
    now say what they do in plain words instead of naming the printer driver or
    the code behind them:

    4.9.0 now
    driver-euro-sign euro-swap
    lj6dtp-typography smart-punctuation
    lj6dtp-box-corners box-corners
    lj6dtp-colour-as-gray colors-as-gray
    lj6dtp-fill-patterns fill-patterns
    stray-style-strikeout sawyer-strikeout

    The old names are still ACCEPTED wherever one can be typed or stored, so
    nothing anyone has scripted or saved stops working. They are never PRINTED:
    --list-quirks, quirks_applicable/quirks_applied and every report say the
    new name only, so one output can never show both spellings for one quirk.

  • Descriptions and the quirk window's own row titles use US spelling: "Screen
    colors as gray", "Colors 9–14 as hatch patterns".

  • --headers and --page-numbers now say outright, in their own --help
    text, that they apply to PDF and RTF only. Text, Markdown and HTML are
    unpaged by design and never carried running heads, feet or page numbers;
    the flags are still accepted (and ignored, with no error) on those three
    formats — nothing about how they convert has changed.

3,325 answer-key cells were re-recorded across this release's commits (a cell
can move more than once as later commits build on earlier ones): 796 for the
per-page-sheet schema bump (792 layout cells at the version number alone,
one document's pdf.printed/rtf.printed pair for its actual landscape
page, and that same d...

Read more

v4.9.0

Choose a tag to compare

@jonmichaels jonmichaels released this 17 Sep 00:55

A minor release: one new feature, three fixes.

Quirks mode. Some WordStar documents were printed through a printer
driver that was itself patched to depart from the file's literal bytes —
printing a euro sign where the byte says peseta, for instance, or drawing
card suits as box corners. ctrl-kd already reproduced these; now they're
named, and you can see and control them. --list-quirks lists every known
quirk; --list-quirks FILE says which apply to a given file and why;
--quirk NAME / --no-quirk NAME turn one on or off; --quirks off|auto|all sets the baseline. Six ship with this release — five on by
default (the file's own printer header is the evidence for them), one off
by default (ignoring a strikethrough set only by a paragraph style, never
by the writer). The layout output format now reports which quirks apply
to a document and which fired.

Fixes. A paragraph-style selection written at the very end of a line
was lost whenever the next line was a formatting command — a manuscript's
book list could print in the wrong typeface and spill onto an extra page,
with the rest of the document coming out right-aligned. Both fixed, and a
document's own explicit line-height setting now correctly overrides a
style's, matching WordStar. Strikethrough is now drawn as one continuous
line across each struck run of text, spaces included, rather than one
short stroke per word.

824 answer-key cells were re-recorded for this release: 792 for a
purely additive layout schema change (nothing else moved), and 32 for
the two layout/print fixes above.

Full changelog: v4.8.1...v4.9.0

v4.8.1

Choose a tag to compare

@jonmichaels jonmichaels released this 16 Sep 12:08

A patch release fixing two things.

A style whose typeface was an ordinary face — Courier, for one — but whose
character-set bits said "math" printed its whole text in the Symbol font:
Greek letters instead of words, in every export. A resolved typeface now
wins; the character-set bits only decide when the typeface itself is
unknown.

Strikethrough declared by a paragraph style now stays on until a later
style turns it off, which is what WordStar 7 prints — it previously ended
with the styled paragraph. Documents whose style sheet sets strikethrough
and never clears it now print struck through to the end, as on paper. An
opt-in "quirks" mode to read such documents cleanly is planned for the next
release.

40 answer-key cells in 5 reference documents were re-recorded for these two
fixes.

Full changelog: v4.8.0...v4.8.1

v4.8.0

Choose a tag to compare

@jonmichaels jonmichaels released this 16 Sep 05:03

Modern view, Modern PDF and Modern RTF now keep the page the document itself declares: landscape sheets, newspaper columns, and short sheets for envelopes, labels and Rolodex cards — which used to come out blank. Modern's right margin mirrors its left, instead of being forced to a flat inch.

Modern shows WordStar's automatic page number again, wherever the Printed view does, and running heads and footers land where the document aligns them: right, centre, or two on one row at opposite edges.

The automatic page number is now placed from the print offset in force on the page being numbered, so it sits in the right column on landscape templates and on documents that move the offset part-way through. Its row — and a footer's own text row — are counted in WordStar page lines, so numbers no longer vanish from documents set at more than 12pt leading.

A plain paragraph that happens to open "Note: " is no longer turned into a hanging definition-list entry; a definition list now needs at least two entries with different terms.

Documents that turn page breaks off with .pl 0 are written to RTF on a Letter page instead of a zero-height one that some word processors refuse to open.

Turning running heads off (--headers off) now applies to Modern PDF as well as Printed; the automatic page number stays governed by --page-numbers alone.

Full list in CHANGELOG.md.

v4.7.1

Choose a tag to compare

@jonmichaels jonmichaels released this 15 Sep 11:34

A patch release fixing one thing. A document that used footnotes and also
asked for no page numbers got a page number printed at the foot of every page
anyway — real WordStar 7 prints none on such a document.

The fix reaches the PDF, RTF and HTML exports and the page-layout views
alike. Nothing else changed since 4.7.0.

Full changelog: v4.7.0...v4.7.1

v4.7.0

Choose a tag to compare

@jonmichaels jonmichaels released this 15 Sep 02:26

This release finishes what 4.6.0 started: RTF and HTML now carry the
same page-level behaviour PDF got last time (page numbers, facing
headers/footers, columns, keep-with-next, matching tabs/indents, Modern
spacing) — checked against a real word processor and a real browser, not
just our own PDF. Plus another round of printed-page fixes measured
against real WordStar 7 (auto-leading, print-time reflow, header/footer
timing, comment lines, form-feed formatting loss, the driver's character
substitutions including the euro), and a new MailMerge data-file reader.
Full itemized list in the CHANGELOG.

Measured against real WordStar 7: named divergences against real WS7
LaserJet printouts down from 10,576 to 3,682; 132 of 194 test documents
now print byte-identical to the original.

Known limit carried forward: RTF columns/keep-with-next/sections are
Printed-view only — Modern has no column model, by design.

Full changelog: v4.6.0...v4.7.0

v4.6.0

Choose a tag to compare

@jonmichaels jonmichaels released this 12 Sep 00:16

ctrl-kd is the Python reference engine that reads WordStar 4–7 documents and
converts them to text, Markdown, HTML, RTF and PDF. This release is a large
accuracy pass on printed-page layout, measured page by page against real
WordStar 7 output, plus a set of Modern-view layout rules brought across from
the Soft Return app so that the app and the engines lay out the same lines.

Note before you upgrade: the RTF and HTML emitters do not yet carry the
new page-level behaviour described below. They are correct as text; the page
model is PDF and the on-screen views for now. That work is scheduled next.

Modern layout — the app's rules are now the engine's rules

The Soft Return app's "Modern" reading view had a number of typographic
refinements the engines did not share, so the same document could break lines
differently on screen and in an exported PDF. Those rules now live in the
engine:

  • Verse and centred lines tighten up. Poetry, song lyrics and centred
    display lines now use the same reduced line height the app uses, with the
    matching bit of extra air above the first tightened line, instead of full
    body leading on every line.
  • Definition lists hang properly. A definition-style row now hangs its
    label at the left margin with the body text and every continuation line
    aligned under the start of the body, across the full measure. Bulleted rows
    hang on the bullet's own cell.
  • A one-sided left-margin change is no longer treated as a block indent.
    A .lm with no matching .rm used to push a paragraph a further inch and a
    half into the page in Modern; it now sits at the margin, the way the printed
    page shows it.
  • The page baseline model matches the app. The first line of every Modern
    page now starts flush at the top margin rather than a full line below it, and
    a page fits while the line's box is inside the margin. On documents that mix
    type sizes this was worth a whole line per page.
  • Line height is measured from the font's real design metrics — corrected
    natural line height for the body face, real vertical metrics from the font
    tables, and a blank line following a tightened line keeps body leading
    instead of inheriting the tightened value.
  • Centring that a document implies rather than declares is now detected and
    centred.
  • Rows that must not wrap no longer wrap — legend rows, chart rows and
    similar fixed-shape lines are kept on one line, and a colon inside such a row
    is no longer taken as a break opportunity.
  • Line width is computed the same way the reference implementation computes
    it
    , so a line that fits in one engine fits in the other.
  • Box and rule characters advance by the document's own fixed-pitch cell,
    not by the size of the face they happen to be drawn in — rules built from
    box-drawing characters now end flush at the margin instead of running off the
    page.
  • Runs no font block covers keep the reader's face, and honour
    "proportional spacing off".
  • Endnotes start a new page when the last page of the body already carries
    footnotes.
  • Greek, mathematical and dingbat characters no longer fall back to a
    question mark in Modern PDF, and box characters inside a symbol-mapped run
    draw as real shapes.

The euro, and the peseta

Code 158 in the DOS character set is the peseta sign. Some WordStar 7 printer
definitions were patched in the late 1990s to print a euro there instead — a
well-known trick, documented in WordStar's own release notes. ctrl-kd now
models it the way WordStar did: if the document's last-used printer is one of
the three patched LaserJet definitions, code 158 prints as €; otherwise it
prints as the peseta ₧
— drawn as a real glyph where the base font set has no
slot for it. This replaces a blanket "always euro" fallback that turned genuine
peseta amounts in older documents into euros. The rule applies to body text and
to running heads and feet alike.

Printed-page layout, measured against real WordStar 7 printouts

  • Newspaper columns (.co) are implemented in printed PDF layout: columns
    as wide as the block's right margin, filled down and then across, no
    balancing, and leaving a column region breaks the page — WordStar's own
    behaviour, verified against captures.
  • Full justification (.oj on) is implemented, with the extra space split
    between gaps the way WordStar splits it.
  • Even/odd page handling. .h1e/.h1o/.f1e/.f1o conditional headers
    and footers were never recognised at all (the pattern matched two of three
    letters); they now work, and the even/odd page offset .poe/.poo reaches
    the running head and foot, not just the body.
  • Line numbering (.l#) is positional — a document can turn numbering on
    and off down the page and the gutter numbers follow — instead of one flat
    setting for the whole file.
  • Landscape pages. A page length that does not match a named paper size no
    longer produces a square, clipped page; the document's own width is honoured.
  • Leading. A paragraph style's own line height now outranks a stale
    document-wide setting; automatic leading inside a font block has a ceiling and
    never governs its own line; page capacity prices each line at its real height
    rather than the document default.
  • Indents. A typed run of leading spaces indents by the natural width of a
    space when no paragraph-margin rate is in force, and by the paragraph margin
    when one is; a style-driven first-line indent no longer double-counts a typed
    one.
  • Tabs. A literal tab byte round-trips and expands to the next column stop
    at layout time; a run of spaces before a tab shifts that stop correctly; a
    ruler line (.rr) resets left, paragraph and right margins, not only the tab
    stops, and consumes its own ruler-image line.
  • Headers and footers honour an embedded paragraph-style selection for
    alignment, font and attributes, re-apply bullet substitution on the fast path,
    and track a page offset only when it is a real page-geometry change.
  • Conditional text. .if/.el/.ei are evaluated for constant
    conditions, and a dot command immediately after a form feed is recognised.
  • Page breaks. .cb/.cc/.cp are honoured in the footnote-aware
    paginator; a trailing .pa opens a new page only when real content follows;
    .fi prints nothing when its target cannot be resolved.
  • Superscripts and subscripts in proportional text keep the surrounding
    block's pitch and change only the drawn size, matching WordStar.
  • Pictures are included by default and sit at the right vertical offset,
    with the descent gap before the image WordStar leaves.

Reading printer output

The tooling that decodes captured printer streams now tracks symbol-set
selection, so curly quotes, the copyright sign and Symbol-font runs decode
correctly; it implements transparent print data; it unwraps a vertical-position
overflow WordStar itself emits; and page-size and paper-source commands eject a
page. Four more WordStar typeface identifiers are mapped.

Test corpus and manifests

  • Test material that was never meant to ship no longer appears anywhere in the
    public test suite or tooling, and the public manifest no longer records stray
    files found in a corpus tree.
  • Documents that cannot meaningfully be compared against a printout are now
    excluded by name and by class rather than silently failing: mail-merge data
    and format files, PostScript-driver documents, documents with form feeds
    turned off, duplicate copies of the same document, and one degenerate file
    that declares a zero-length page.
  • Coverage of the printed-output comparison expanded to a much larger capture
    round, and the shared cross-engine answer key now covers the full corpus
    rather than a hand-picked subset.
  • Tier-1 tests run on every push and pull request.

Other

  • Plugin loading works again on Python 3.9.
  • One environment variable per corpus, one shape each.

Known issues

  • RTF and HTML exports do not yet carry the new page-layout rules. They are
    correct as text, but the page-level behaviour added in this release — default
    page numbers, even/odd page headers, page capacity, newspaper columns, tabbed
    tables and the Modern verse tightening — is not reflected in those two formats
    yet. PDF and the layout model are unaffected. Scheduled for the next release.
  • The printed-output comparison set grew faster than it has been triaged.
    This release expanded the set of real WordStar 7 printouts we compare against
    from a few dozen pages to a few hundred. On a substantial number of the newly
    added documents the printed PDF still differs from the original printout, and
    those differences have not yet been sorted into "a substituted font is a
    different width" versus "we place something wrongly". They are measured and
    reported by name in the test output rather than hidden; classifying them is
    the next round of this work. The two engines agree with each other on
    every one of those documents.
  • Documents that declare printer fonts we substitute — the LaserJet's
    scalable faces — can break lines slightly differently from the original
    printout, because the substituted face's character widths are not identical.
    Laying the page out with WordStar's own printer width tables is a planned
    improvement.
  • On one page of one archived Sawyer test document, eight words sit about a
    third of a point to the left of where the original printer placed them. It is
    far below anything the eye resolves and is recorded rather than chased.

v4.5.1

Choose a tag to compare

@jonmichaels jonmichaels released this 07 Sep 02:59

Compatibility

  • Fixed a crash on Python 3.9: load_plugins() called importlib.metadata.entry_points()
    with a group= keyword that Python 3.9 doesn't support there. ctrl-kd now works on
    Python 3.9 again, not just 3.10+.

Printed-mode fidelity

This release is measured against real, factory-default WordStar 7 output (not just our
own previous exports), and fixes a batch of small placement bugs found that way:

  • Superscript and subscript now use the correct size and horizontal spacing for each font
    family, instead of one fixed value.
  • Header and footer lines can now contain inline style toggles (bold/italic/underline
    partway through the line) without corrupting the text.
  • Running heads now honor a page's own left/right offset instead of always using page 1's.
  • Right-aligned tabs in headers and footers now recompute their padding on every page
    (previously only correct on the page it was first calculated for).
  • Footnote reference markers now join correctly to their note text.
  • Page numbers are now on by default, matching stock WordStar 7 (previously off unless
    requested).
  • Automatic single-line spacing is now 1.0x, matching WordStar 7's own default (previously
    1.2x, borrowed from a customized install).
  • Top margin now uses the document's .mt setting alone, instead of double-counting it
    with the header margin.
  • The footnote area reserves the same vertical space stock WordStar 7 does.
  • Running head lines now use the page's default margins correctly.
  • Fixed an off-by-one in right-tab column placement.
  • A typed paragraph indent combined with a style-driven .pm indent is no longer
    double-counted.
  • HTML output: fixed a rendering glitch where a tab-and-leader run in a centered row
    (e.g. a symmetric table-of-contents line) produced an oversized gap instead of a
    single space.

Testing infrastructure

  • New coordinate-level test tier that checks PDF output against real WordStar 7 printer
    output, page by page.
  • New tooling to track and record page-by-page visual review against real printed pages
    (paper scans), so a reviewed page is a recorded fact instead of tribal knowledge.
  • CI now runs the test suite on every push, not just manually.

Known state at release

  • Reduced (public) test suite: 846/846 passing.
  • Coordinate-level fidelity tier: 14 of 18 captured documents match real WordStar 7
    output exactly. 4 have named, unresolved residuals:
    • LJ6DTP — parked by design; its own printing-hack features are out of scope for
      this tier.
    • LYING and WARPRAYR — small residual font-metric drift from a substituted font
      (ctrl-kd never embeds fonts; the base-14 substitute doesn't have identical metrics
      to the original).
    • -SCREEN — a test-harness limitation matching short Greek/math symbol fragments
      across a font switch, not a rendering bug.
  • Paper-scan visual review: 69 pages catalogued, all recorded as unreviewed pending
    human review — tracked and testable, not silently skipped.

v4.5.0

Choose a tag to compare

@jonmichaels jonmichaels released this 28 Aug 19:37

First official release from the fresh public history. WordStar for DOS (v4–v7) to modern formats: Modern RTF/HTML/Markdown/text and Printed PDF facsimile. New since 4.x: sentence-spacing control (--sentence-spacing), bundled sample documents (--samples DIR), the public three-tier test suite with the committed Sawyer-archive manifest, and the documented era model (ERAS.md).