spec conversion - #81
Open
aaronmbauman wants to merge 46 commits into
Open
Conversation
The specification is an ISO Publicly Available Specification, and the rules for transposing one decide several things that would otherwise be guessed at: whether Directives conformance is mandatory, whether change bars are needed, and when the next review falls. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Establishes the master document and the ISO metadata the build needs. Front matter is kept in its own file from the start. The OGF edition differs from the ISO one only there, so nothing added to the body later can become specific to one edition. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
The specification ships in two editions. Both use ISO formatting, and the OGF one carries OGF front matter and copyright, so section and page numbers stay identical between them (OpenGridForum#76). JTC 1 SD-9 (6th ed. 2021) §7.3.1 states the same intention from the other side, that ISO avoids divergence between a transposed PAS and the version published by the originator [1]. [1]: https://jtc1info.org/wp-content/uploads/2022/01/SD-9-Guide-to-the-Transposition-of-PAS-2021.pdf Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Pin metanorma-cli so local and CI builds render identically. Output is keyed by edition. The OGF and ISO editions render identically-named artifacts, so they need separate directories from the start rather than a rename once the second edition exists. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
ruff and black run on the host rather than in the Metanorma container, which carries neither. check runs the validators in tools/ over the build. Both targets tolerate an empty tools/. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Rendering happens inside the pinned Metanorma image, so the runner installs nothing. The uploaded artifacts are how a reviewer reads the rendered spec without a local toolchain. Both editions are built, because a change can break one and not the other. There is no push or pull_request trigger. This repository has never run CI, and whether it should, and on what, is a working group decision; the workflow is here to be run from the Actions tab until that is settled. Read-only permissions and no secrets, so it behaves identically for pull requests from a fork. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Separate from the build job so a lint failure and a rendering failure are distinguishable at a glance. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Converting the whole document in one pass produces a diff nobody can review, so the tool addresses one top-level clause at a time. Word owns the heading numbering and switches it off for the front matter, so the specification's own clause keys are reconstructed rather than read out of the text. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Word splits a logical listing across consecutive paragraphs, so a run of them collapses into one source block. Schema fragments left in body text are listings too: read as prose their quotes curl and their tags are taken for markup. Prose passes through AsciiDoc's inline markup and then Metanorma's smart formatting, and both claim sequences that are normative here. 0x55, #,##,##0, <= and ' are wrapped per sequence, so ordinary emphasis still works around them. Editors' notes live in Word's hidden text and are kept as AsciiDoc comments, where the next editor has them and no reader does. Listings the source neither numbers nor names are marked unnumbered, so they do not take figure numbers from the diagrams that carry one. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Ids come from heading and caption text rather than Word's internal bookmark names, so a cross-reference reads as something in the specification and survives reconversion. Because the document is converted a clause at a time, a reference can point outside the text being emitted; those keep Word's cached result so the sentence still reads. Word writes a reference as a pair of fields, one resolving to the target's number and one to its title. Only the number is Metanorma's to regenerate, so the pair becomes one reference followed by the title. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Word tolerates rows whose cells do not add up to the table grid and AsciiDoc drops the surplus silently, so every row is fitted to the grid first. Word places a caption after the object it describes; AsciiDoc wants the title in front and Metanorma numbers tables itself. Some captions are laid out as a row of the table, where a title left in place is read as cell markup and takes the cell down with it. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Metanorma resolves image macros against the source tree, so the media parts of the package are written out beside the AsciiDoc. Where a drawing carries both an SVG and a raster fallback the SVG is taken, as it stays sharp in the rendered PDF and HTML. An image is rewritten only when its bytes differ, so re-running the conversion leaves the working tree alone. A footnote is a macro, so brackets in its text have to be escaped; those belonging to the passthroughs that carry technical sequences are left alone, since escaping them would undo the protection. A footnote on a heading is not carried into the rendered title, so it moves to the text the heading introduces. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Word and Metanorma disagree on escaping and whitespace even where the conversion is faithful, so the two can only be compared through a normalised form. Every character folded away is one no comparison can see differ, so the default folds only what the formats must disagree about and typography folding is opt-in. Clause numbers are reconstructed from structure because neither format stores them as text, and the unnumbered front-matter regions are numbered too, so a difference there can be located. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Counting occurrences of normative phrases passes while an entire property table is dropped, so the check is a differential over the whole of both documents. It compares strictly by default: fold quotes, dashes and symbols away and a target that turned every 0x55 in an encoding table into 0x55 with a multiplication sign compares identical to its source. Tokens rather than words carry the verdict, since punctuation is what means something in a regex or a number pattern. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
The conversion lands one clause at a time, so a run over the whole document calls lost what has simply not been written yet. The built output is the authority on what has been converted. A clause the build carries is compared whether or not it has a body, and a clause the build carries that answers to no source clause is content nobody can trace back. Both fail the run. Clauses pair by title because the ISO edition renumbers them, and repeated titles pair in document order: 25 to 28 are four siblings all titled "Removed". Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
The cover page is the publisher's imprint rather than specification text: the title, the document status, the copyright line and the abstract are metadata each edition states in its own form, and ISO generates all of it from the document attributes in the master file. The abstract is the one part both editions print as prose, so it is carried here, in the source's own words. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Verbatim output of tools/docx2adoc.py at ed1aa48. The preamble carries the source's own statement of the two-edition requirement — that section and page numbers stay identical between the OGF and ISO editions, and that sections before the Introduction are unnumbered. It is retained rather than treated as editorial scaffolding; whether the MS-Word cross-referencing instructions belong in the specification is the working group's decision, not the conversion's. The intellectual property statement, the disclaimer and the full copyright notice are the specification's own text, headed and numbered as it heads and numbers them, and both editions carry them as converted clauses rather than as wording chosen here. Everything before the Introduction is preface in both editions, so that the numbered clauses start at the same number in each. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Verbatim output of tools/docx2adoc.py at ed1aa48. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Metanorma reads a clause titled "Introduction" as ISO prefatory matter and leaves it unnumbered, which shifts every following clause number away from the one the specification uses for itself and cites in its own cross-references. The conversion lands one clause at a time, and a cross-reference can only be made against a target the build already carries; until then the converter leaves the text Word cached for the field. These clauses now have each other to point at. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Verbatim output of tools/docx2adoc.py at ed1aa48. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Clauses 1 to 5 introduce the annotation syntax and the property scoping rules by name; the sentences that do so are references now that what they name is in the build. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Verbatim output of tools/docx2adoc.py at ed1aa48. The converted Clause 11 supersedes the stub that hosted a cross-reference target. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
The data syntax grammar and the element defaults are cited from the syntax clauses and from the overview of the representation properties, and the processing clauses cite the annotation elements back. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Verbatim output of tools/docx2adoc.py at ed1aa48. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
The framing properties are where alignment, delimiters and length are defined, and the clauses converted before them point at all three. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Verbatim output of tools/docx2adoc.py at ed1aa48. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Framing cites the simple types for the binary number representations it aligns and measures, and the simple types cite framing back for the lengths they are read with. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Verbatim output of tools/docx2adoc.py at ed1aa48. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
The model group and array properties are what the parser clause names when it resolves points of uncertainty, and what the overview lists as the shape of the property set. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Verbatim output of tools/docx2adoc.py at ed1aa48. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Every property that takes an expression or a pattern points at the two languages that define them. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Verbatim output of tools/docx2adoc.py at ed1aa48. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Clause 29 is the reference list, so the bracketed labels the rest of the specification cites become citations of the bibliography entries they name rather than the text Word cached for them. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Verbatim output of tools/docx2adoc.py at ed1aa48. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
The glossary and the escape-scheme, string-literal and encoding appendices are cited throughout the clauses, and cite the clauses back. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
The front-matter index was maintained by hand in Word, and has fallen badly behind the specification: it lists seven of the properties the property tables define. Deriving the index from the built document keeps it complete without asking an author to remember a second edit, and comparing it against the converted one tells the working group exactly which properties a reader cannot currently look up. Its output stays outside the converted source. That source is held to a character-for-character comparison against the Word original, so the front matter has to keep saying what Word said until the working group decides to adopt the derived index in its place. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
A cross-reference whose target does not exist does not stop the build. Metanorma prints the anchor name where the clause number belongs and carries on, so the damage reaches the rendered specification and is found, if at all, by a reader who follows the link. The conversion from MS-Word produced these anchors in bulk, which is exactly the situation in which one of them goes astray unnoticed. Citations of the bibliography fail the same way, and an anchor declared in two places is as unusable as one declared nowhere, so both are checked here too. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
The check job already runs every executable validator against the built semantic XML, so marking the checker as one is enough to turn it from something a maintainer may remember to run into a condition every branch and pull request has to satisfy. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
The editions share their normative text and differ only in front matter, so a single invocation guarantees both were rendered from the same source state; issuing two separate commands leaves a stale variant indistinguishable from a current one. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
The working group has always distributed rendered deliverables from the repository itself, so that a reader needs no build toolchain. Committing every working build would instead drop a regenerated PDF into the history of every source change, so only published versions are kept, and each is rendered from scratch so that what is committed matches the source it claims to come from. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
A contributor arriving at the AsciiDoc source has to discover the container, the two editions and the release flow by reading the Makefile, and meets the rough edges by hitting them: font fallback that looks like an error, and revision-mark syntax that renders as plain text without complaint. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
The specification points at these clauses in prose that Word left as prose: it never bookmarked them, so the conversion had nothing to convert. An anchor on each is what a reference to it can be made against. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
The specification names these clauses in prose and Word left the number it typed to go stale. Each is a reference now, and Metanorma writes the number, so the sentence says what it says today and keeps saying it. Word's own text is untouched: only the number becomes the reference, so "Section 13.7 Properties Specific to Number with Binary Representation" still reads that way. Where the number could not be replaced without changing the sentence - the change history recording the numbers of past edits, a reference to a section of another document, and a clause Metanorma labels "Clause" where the specification says "Section" - it stays as prose. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Text can be intact while the document is wrong: prose naming the wrong figure, a caption that never attached to its table, markup leaking into the text, or editor-facing notes the source hides being published. Checks run against the rendered page, which carries the resolved labels and is what a reader sees. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
Comparing the build against the Word source proves the conversion, and fails on any deliberate change to the specification: an erratum is meant to differ from GFD.240. Leaving it in the default checks would make the first correction look like a defect, and the obvious fix would be to teach the check to ignore differences, which is worse than not running it at all. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
The source is a directory of clause files with generated numbering, so where to make a change and what the tooling will object to are not evident from the tree. Covers the conventions an editor has to know rather than guess: how clauses are named and added, how cross-references are anchored, why an untitled listing must be marked unnumbered, and which sequences need protecting from AsciiDoc and Metanorma rewriting. Signed-off-by: Aaron Bauman <bauman.aaron@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Convert spec from MS-Word to AsciiDoc
The specification builds to an ISO-formatted PDF, HTML and semantic XML for both
the OGF and ISO editions, from one body, on one command, in a pinned container.
Why AsciiDoc when the issue asks for XML
The XML is here. It is produced and schema-validated on every build, and it is
what the property index and the cross-reference checker read: both were built by
querying it, not by parsing prose. What differs from a literal reading of #68 is
that editors write AsciiDoc rather than angle brackets.
A 12,000-line hand-edited XML document raises the barrier to contributing,
makes merge conflicts worse, and adds a failure mode AsciiDoc does not have: a
document that is no longer well-formed. Machines still get the XML.
DFDL's own concepts are expressible too. A property written as a typed
requirement block emits name, value type, default, valid values, owning
annotation and normative constraints as separate elements. That is demonstrated
but deliberately not adopted here; see what is deferred, below.
Why the conversion reproduces the source's mistakes
The conversion is faithful, including defects.
pattern.atstays misspelled, anem dash Word autocorrected into an XML comment stays an em dash, a missing full
stop stays missing.
A conversion that improves its source cannot be verified against it. Every
difference then has to be argued about individually, and nobody can say which
were intended. Holding the line makes the whole document checkable by machine,
which is what lets the claim "nothing was lost or altered" mean anything.
Seven classes of defect the conversion surfaced are recorded rather than fixed,
including a Property Index listing 7 of the specification's 106 properties, and
six
dfdl:names in prose that match no property. Those are the working group'sto decide on.
Why there are three validators
Text can be provably intact while the document is wrong, so
make checkasksthree different questions.
A comparison that normalises typography away on both sides will report a
conversion clean while every
0x55in an encoding table has become0×55, anormative regex has lost a parenthesis, and
<=has turned into an arrow innormative grammar. Those substitutions live in exactly the characters such a
check is taught to ignore. So the fidelity check is strict by default and counts
punctuation, not only words.
Resolving is a separate question from surviving, so the link checker proves every
cross-reference and citation lands on exactly one target.
Neither of those can see a document that is internally incoherent. The structural
checker reads the rendered page and asserts it says what it means: no sentence
naming the wrong figure, no caption stranded as a body paragraph, no markup
leaking into text, nothing published that Word hides.
The link and structure checks stay useful for as long as the document is edited,
so they are what
make checkruns.spec/EDITING.mdcovers the conventions aneditor needs: how clauses are named and added, how cross-references are
anchored, why an untitled listing has to be marked unnumbered.
Coverage is 81,709 of 81,884 source words; the shortfall is the cover page, which
becomes document metadata. A clause that pairs but is not compared is an error
rather than a note, because a gate that silently compares nothing still reports
PASS.
Why the two editions share one body
The source states the requirement in its own preamble: section and page numbers
must not change between the OGF and ISO editions. JTC 1 SD-9 §7.3.1 says the same
from the other side, that ISO intends no divergence between a transposed PAS and
the originator's version 1.
One body with two front matters makes that mechanical rather than a discipline
somebody has to maintain.
spec/frontmatter/is the only thing that differs.What is deferred, and why
The DFDL property model, expressing property tables as typed requirement
blocks, is a second pull request. It re-shapes 15 tables, which is a different
review question from "is this the same specification", and mixing the two makes
both unanswerable.
Publication is untouched. Nothing here changes GitHub Pages, the README's
htmlpreviewlink, or which document is authoritative. The series is purelyadditive: it adds
spec/,tools/and aMakefile, and changes nothing thatexists, so merging it cannot break anything in use today.
Errata and ISO Directives edits change the specification's text. Neither is
conversion work.
Notes
Comparing the build against the Word source is not part of
make check. Itproves the conversion, and fails on any deliberate change to the specification,
so leaving it in the default checks would make the first erratum look like a
defect. It runs on its own as
make check-conversion.Six plain-text references were left unlinked because linking them would change
what the sentence says: Metanorma labels a top-level clause "Clause 11" where the
specification writes "Section 11".
The workflow has no push or pull request trigger, so opening this will show no
check. Whether this repository runs CI automatically, and on what, is a working
group decision rather than something a conversion should assume; the triggers to
add are commented at the top of
.github/workflows/spec.yml. Until then it runsfrom the Actions tab, and
make checkruns the same validators locally.Closes: #68
Closes: #78
Closes: #79