Documentation
¶
Overview ¶
Package markdown writes a doc.Document as Markdown.
This is a sink: it consumes doc and knows nothing about PDFs, fonts, or glyph positions. That separation is what lets a page recovered by OCR and a page recovered from a content stream produce identical output — by the time either reaches this package the difference is gone.
It writes to an io.Writer and never touches the filesystem. Per-page splitting is a naming decision — where files go, what they are called, whether a directory is created — and that belongs to the command, which is also the only layer that can ask the user about it. Keeping it out means every function here is testable against a bytes.Buffer.
The work that is actually difficult is escaping. Extracted text is prose that happens to contain every character Markdown reserves: a PDF specification is full of `<</Type /Page>>`, `*` footnote markers, and `snake_case` identifiers. Emitting it raw produces a document that renders wrong, and escaping it indiscriminately produces one that reads as backslashes. See escapeInto.
Index ¶
- Variables
- func InlineText(s string) string
- func LinkLabel(s string) string
- func OutlineString(o *doc.Outline, opt Options) string
- func String(d *doc.Document, opt Options) string
- func Write(w io.Writer, d *doc.Document, opt Options) error
- func WriteBlocks(w io.Writer, blocks []doc.Block, opt Options) error
- func WriteOutline(w io.Writer, o *doc.Outline, opt Options) error
- func WritePage(w io.Writer, meta doc.Metadata, p doc.Page, total int, opt Options) error
- func YAMLString(s string) string
- type Options
Constants ¶
This section is empty.
Variables ¶
var DefaultOptions = Options{}
DefaultOptions is conversion as the CLI runs it with no flags.
Functions ¶
func InlineText ¶
InlineText escapes a plain string as Markdown inline content — a heading a sink composed itself, a value that was a struct field rather than a span.
Not treated as beginning a block, because the callers all prefix something: "# " before a heading, "* " before a list item. A "-" that follows either of those is a hyphen, and escaping it there would put a backslash in the middle of a rendered line.
func LinkLabel ¶
LinkLabel escapes a plain string for use between the brackets of a Markdown link.
Both brackets are escaped unconditionally here, where escapeInto escapes "[" only when it could open a link and "]" never — correct for prose, wrong inside a label, where the first unescaped "]" ends the label and turns the rest of the title into text followed by a bare URL. ISO 32000-2 has clause titles containing brackets, so this is a real case and not a defensive one.
func OutlineString ¶
OutlineString renders an outline to a string, for tests and in-process consumers.
func String ¶
String renders the document to a string, for callers that want the text rather than a stream — tests, and any future in-process consumer.
func Write ¶
Write emits the whole document, pages separated by a blank line.
No page markers and no horizontal rules between pages. A paragraph continuing across a page break is one paragraph, and a document that announces every page boundary cannot be read as prose. Recovering the continuation is sectionize's job; asserting a boundary here would make that harder rather than easier.
func WriteBlocks ¶
WriteBlocks emits a run of blocks and nothing else: no frontmatter, no page structure, no headings the caller did not put in the slice.
It exists for sink/okf, which writes one file per clause and needs the body of that clause rendered with the same escaping policy as everything else. The alternative was a second implementation of escapeInto in that package, and two escaping policies diverge — the first document containing "<</Type /Page>>" would be escaped one way in the Markdown output and another in the bundle, from the same extraction.
func WriteOutline ¶
WriteOutline emits a reconstructed outline: the preamble, then every section as a heading followed by its own content, depth first.
This is the same sink as Write with one thing added — the headings. Write emits page after page because that is all a doc.Document knows; a doc.Outline knows which text is a clause title and at what rank, so the output gains a document outline and loses the page boundaries, which were never meaningful in prose. A paragraph continuing across a page break is one paragraph.
Section titles are emitted as they were resolved, clause number included. Splitting "7.5.8" back off into a separate construct would be a numbering scheme this package invented; the number is already in doc.Section.Number for a consumer that wants it structurally, and a reader wants to see it in the heading.
func WritePage ¶
WritePage emits one page, for --split.
The metadata comes in separately because a page does not carry it and a split page still needs it: a directory of pages with no record of which document they came from cannot be checked against the original.
func YAMLString ¶
YAMLString quotes a value for use as a YAML scalar, quoting only when the value needs it. Exported for sink/okf, whose frontmatter is nested where this package's is flat — so it cannot reuse the writer, but must not reimplement the quoting rule. See yamlString for what the rule is and why it is conservative.
Types ¶
type Options ¶
type Options struct {
// Frontmatter emits a YAML frontmatter block. Off by default, per
// docs/DESIGN.md §2: frontmatter is what a knowledge bundle needs and what a
// plain conversion does not, and a document that starts with a metadata block
// is not what someone converting one file to read it asked for.
Frontmatter bool
// Artifacts emits blocks with doc.RoleArtifact — running headers, folios,
// watermarks. Off by default, matching extract.Options.KeepArtifacts, so that
// asking extract to keep them and asking this package to emit them are the same
// decision made once. Without it the extractor's flag would silently do nothing.
Artifacts bool
}
Options configures output.