The final slice: land the format-neutral document model with REAL consumers
and unify the Markdown parser — no duplication, byte-identical output.
Neutral model (pkg/docforge/model.go): Document / Block / InlineSpan.
BlockKind values are the stylemap keys. A hyperlink is a span with Link set
+ Children (the label's spans), preserving link boundaries so adjacent
same-URL links stay distinct — byte-exact with the pre-model walker.
Markdown importer (pkg/docforge/markdown): Import(md) → Document. The SINGLE
Markdown parser for docforge — block split, marker detection, inline
bold/italic/link tokenisation, {{placeholder}} pass-through (the b78a984
fix). Relocated out of the docx walker.
docx renderer (pkg/docforge/docx/markdown.go): now RENDERS a Document →
OOXML (RenderDocumentToOOXML); RenderMarkdownToOOXML[WithStyles] = render(
markdown.Import(md)). The shipped submission walker routes through the model,
so there is one parser, not two. The comprehensive byte-exact render tests
(RenderMarkdownToOOXML_*) all PASS unchanged = output identical.
Exporter interface (pkg/docforge/exporter.go, PRD §4 B4): Exporter{Format,
MIMEType, RenderBody(Document)} with the .docx impl (pkg/docforge/docx/
exporter.go). The seam a future PDF/HTML exporter slots into.
Tests: parser tests relocated to the markdown pkg (parseSpans/detectBlockMarker)
+ new importer Document tests + exporter conformance test.
Verification: go build/vet clean; gofmt clean; full NO-DB test suite GREEN
(authoritative — proves no regression); docforge byte-exact render oracle
PASS; composer live test renders through the rewired walker (PASS); bun build
+ bun test 274/274. The shared-DB live run fails ~85 tests across unrelated
services from a harness pq-42P08 $1-type seeding quirk + a stale
deadline_rules test — systemic/environmental (the no-DB run is clean), not
this change.
docforge train complete: 8 slices, the engine extracted + cleaned + a working
author→generate→export loop on uploaded templates, plus the neutral model +
importer + exporter seam for future formats/consumers.
m/paliad#157
40 lines
1.5 KiB
Go
40 lines
1.5 KiB
Go
package docx
|
|
|
|
import "mgit.msbls.de/m/paliad/pkg/docforge"
|
|
|
|
// Exporter is the .docx implementation of docforge.Exporter — it renders a
|
|
// neutral Document to OOXML body markup (t-paliad-349 slice 8). The
|
|
// stylemap (block kind → Word paragraph style) and the optional hyperlink
|
|
// allocator are baked in at construction, so RenderBody matches the
|
|
// interface's format-neutral signature.
|
|
//
|
|
// This is the seam a future PDF/HTML exporter slots into: implement
|
|
// docforge.Exporter, no engine change. The submission composer can render
|
|
// section content through this exporter instead of calling
|
|
// RenderDocumentToOOXML directly once a second format exists.
|
|
type Exporter struct {
|
|
Stylemap map[string]string
|
|
Links HyperlinkAllocator
|
|
}
|
|
|
|
// compile-time conformance.
|
|
var _ docforge.Exporter = Exporter{}
|
|
|
|
// NewExporter builds a .docx exporter with the given stylemap + allocator.
|
|
func NewExporter(stylemap map[string]string, links HyperlinkAllocator) Exporter {
|
|
return Exporter{Stylemap: stylemap, Links: links}
|
|
}
|
|
|
|
// Format returns the format id.
|
|
func (Exporter) Format() string { return "docx" }
|
|
|
|
// MIMEType returns the .docx container MIME type.
|
|
func (Exporter) MIMEType() string {
|
|
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
}
|
|
|
|
// RenderBody renders the Document to OOXML paragraph markup.
|
|
func (e Exporter) RenderBody(doc docforge.Document) ([]byte, error) {
|
|
return []byte(RenderDocumentToOOXML(doc, e.Stylemap, e.Links)), nil
|
|
}
|