markdown

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 5, 2026 License: MIT Imports: 6 Imported by: 0

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

Constants

This section is empty.

Variables

View Source
var DefaultOptions = Options{}

DefaultOptions is conversion as the CLI runs it with no flags.

Functions

func InlineText

func InlineText(s string) string

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

func LinkLabel(s string) string

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

func OutlineString(o *doc.Outline, opt Options) string

OutlineString renders an outline to a string, for tests and in-process consumers.

func String

func String(d *doc.Document, opt Options) 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

func Write(w io.Writer, d *doc.Document, opt Options) error

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

func WriteBlocks(w io.Writer, blocks []doc.Block, opt Options) error

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

func WriteOutline(w io.Writer, o *doc.Outline, opt Options) error

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

func WritePage(w io.Writer, meta doc.Metadata, p doc.Page, total int, opt Options) error

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

func YAMLString(s string) string

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL