Use this page to choose the shortest path to the task you have. If this is your first time using Marksplice, start with Getting Started.
| Goal | Start here | Runnable example |
|---|---|---|
| Load a Markdown file and inspect its structure | Inspect a document | go run ./examples/inspect |
| Rename, replace, check, remove, insert, move, or combine edits | Edit an existing document | go run ./examples/edit |
| Create Markdown from structured Go values | Create a document | go run ./examples/build |
| Export one deterministic normalized Markdown representation | Render canonical Markdown | go run ./examples/render --markdown |
| Render deterministic HTML or correlate Markdown ranges with emitted HTML | Render HTML | go run ./examples/render / go run ./examples/render --map |
| Work with list hierarchies, sections, or GFM tables | Lists, sections, and tables | go run ./examples/query |
| Discover/follow Markdown files, resolve fragments, build backlinks, or validate a document set | Links and workspaces | go run ./examples/workspace |
| Observe application-specific syntax without changing core GFM | Read-only extensions | go run ./examples/extensions |
| Check whether a feature is supported | Capability matrix | — |
| Find an exact function or method signature | API Reference | — |
Marksplice deliberately separates two jobs.
A parsed Document is immutable and owns an exact source snapshot. Existing-document operations prepare narrow ChangeSet values against that snapshot. Applying a change to different bytes fails with ErrSourceConflict.
This is the path to use when author formatting matters.
A DocumentBuilder represents construction intent. It writes deterministic canonical GFM because there is no existing author source to preserve.
Do not use the builder to round-trip an existing document when your goal is a small edit.
The public API exposes several levels of detail:
Nodes()gives source-ordered promoted structural summaries.- Typed accessors such as
Heading,Task,TableCell,FencedCode,InlineLink, andReferenceDefinitionexpose operation-specific detail;Heading.Text()provides parser-derived semantic heading text whileHeading.Range()retains exact authored source ownership. - Higher-level views such as
Sections,FencedBlocks,Alerts,MathExpressions,FootnoteDefinitions, andFrontMatterexpose reviewed semantics that do not always imply mutation authority. QueryNodesandQuerySectionsprovide bounded structural selection.HeadingAnchors,ResolveFragment, andLinkRelationshipsprovide navigation and relationship intelligence;LocalFragmentContinuityvalidates how already-resolved local-fragment relationships behave across one preparedChangeSetwithout comparing snapshot-scoped node IDs.
A public Range always means exactly what the accessor documents. Marksplice intentionally does not define one universal "full node range" for every construct.
Most mutation APIs are named Prepare.... Typical families include:
- paragraph, heading, task, fenced-code/info, inline, direct-link/image/autolink, reference-definition, front-matter, HTML, footnote, math, and table-cell replacements;
- source-proven blockquote content replacement and GitHub alert kind/body mutation for uniform marker/EOL forms;
- section replacement/removal/insertion/movement/child append;
- list-item content/subtree replacement, removal, sibling insertion/movement, and child append;
- table row, alignment, and complete-column operations;
- thematic-break and complete-blockquote removal;
- managed TOC synchronization, including
ComposeChangesAndSyncTOCwhen heading/section changes and the derived TOC must agree in one final atomic result; ComposeChangesfor independent operations prepared from the same snapshot.
The exact supported shapes are deliberately conservative. If Marksplice cannot prove the source ownership or surviving structure required by an operation, it returns an error instead of rewriting a wider region.
See Edit an existing document.
DocumentBuilder supports reviewed GFM construction for common document families, including:
- headings and paragraphs;
- typed inline text, code, emphasis, strong, strikethrough, links, images, autolinks, references, footnote references, and reviewed math forms;
- ordered/unordered lists and task lists, including reviewed homogeneous nesting;
- tables and alignments;
- fenced code;
- blockquotes and GitHub alerts;
- reference definitions plus immediate/deferred single-line and reviewed canonical multiline footnote definitions;
- YAML/TOML front-matter envelopes;
- thematic breaks and mathematical blocks.
Generated content is reparsed and checked against construction expectations before Markdown() returns it.
See Create a document.
Canonical Markdown is an explicit export path, not an implementation detail of source-preserving editing. Document.RenderCanonicalMarkdown streams one deterministic Markdown representation to an io.Writer; Document.CanonicalMarkdown returns caller-owned bytes when buffering the complete result is useful.
The writer consumes the same Native semantic walk used by the HTML renderer and does not parse Markdown syntax a second time or retain a rendering AST in Document. It intentionally exposes no style configuration: formatting normalization is the purpose of this export, and one stable Marksplice profile keeps semantic round-trip and byte-idempotence testable.
The parsed source snapshot remains untouched. Use ordinary Prepare... operations and ChangeSet.Apply when the goal is a narrow edit that preserves unrelated author bytes. Use canonical rendering only when the caller explicitly wants normalized Markdown output.
See Render canonical Markdown or run go run ./examples/render --markdown.
HTML rendering is an explicit export path, not an implementation detail of editing. Document.RenderHTML streams a deterministic fragment to an io.Writer; Document.HTML returns caller-owned bytes when buffering the whole result is useful.
The renderer consumes the same Native semantic walk used by the other rendering paths and does not parse Markdown syntax a second time. HTMLRenderOptions makes three policy boundaries explicit: raw HTML preservation versus escaping, dangerous-URL suppression versus allowance, and the published GFM tag filter. The zero value preserves parser-proven raw HTML, enables the GFM tag filter, and suppresses dangerous URL schemes.
Preserved raw HTML is not a sanitizer. Use HTMLRawEscape or an application-appropriate downstream sanitization boundary for untrusted input. Rendering does not fetch URLs or images, run templates, highlight code, execute fenced content, or invoke a mathematical rendering engine.
Standalone RenderHTMLDocument/HTMLDocument wrap the same body renderer in deterministic doctype/html/head/charset/body markup. HTMLDocumentOptions reuses HTMLRenderOptions for the body and maps only exact lower-case title, description, author, and safe lang values from already source-proven simple top-level front matter. Complex, duplicate, nested, invalid-UTF-8, or escape-dependent values are omitted rather than interpreted by a YAML/TOML parser. HTMLMetadataOmit disables that mapping.
For preview/editor integration, the ...WithSourceMap variants return caller-owned HTMLSourceMapEntry values that correlate snapshot-local Markdown byte ranges with byte ranges in the exact emitted HTML. The map is semantic-event granular rather than complete byte coverage: nested ranges may overlap, synthetic HTML can be unmapped, and standalone offsets are absolute from the beginning of the complete HTML document. Mapping is opt-in; ordinary rendering retains no result map.
See Render HTML, run go run ./examples/render for HTML, or go run ./examples/render --map to inspect source/output correlations.
Marksplice can understand document relationships without hidden filesystem or URL authority. Root graph APIs remain in-memory; workspacefs is a separate read-only adapter that operates only on a caller-supplied fs.FS under explicit finite limits.
For one document:
- derive GitHub-compatible heading anchors;
- resolve local fragments;
- generate and conservatively synchronize managed TOCs;
- enumerate semantic link/image/autolink relationships.
For filesystem-backed documentation:
workspacefs.Scandiscovers.md/.markdownfiles under one explicitfs.FSroot and assigns deterministic slash-relative keys;workspacefs.Followstarts from explicit entries and follows reviewed local Markdown URI paths, normalizing relative dot segments against each source document, percent-decoding path components once, ignoring query text for file lookup, preserving target fragments, and visiting cycles once;- absolute/scheme/protocol-relative paths, backslashes, encoded traversal or separators, directory targets, and extensionless targets are not followed. Case and symlink behavior comes from the
fs.FSsupplied by your application; - both operations enforce caller-supplied document, byte, depth, and relationship limits and perform no writes, network access, or command execution.
For several documents that your application already loaded, or for the documents returned by workspacefs:
BuildDocumentGraphcreates an immutable graph over explicit caller keys;- a caller resolver decides which non-local relationships map to which already-supplied documents;
- graph queries expose outgoing edges, backlinks, reachability, and related documents;
ValidateWorkspaceadds deterministic link/fragment/reference/orphan/managed-TOC diagnostics and conservative repair planning;BuildKnowledgeIndexadds caller-declared aliases, tags, and logical references without inventing Markdown syntax.
See Links and workspaces.
ParseWithOptions can attach namespaced read-only observations produced by caller-linked recognizers. Extension nodes cannot replace core GFM nodes or gain generic editing, construction, graph, filesystem, network, or command authority.
Use this for product-specific syntax such as a private [[wikilink]] convention when observation is enough. See Read-only extensions.
Use errors.Is with public sentinel families rather than comparing messages:
ErrNodeNotFoundErrInvalidReplacementErrInvalidTargetKindErrSourceConflictErrInvalidConstructionErrInvalidQueryErrInvalidGraphErrInvalidWorkspaceErrInvalidKnowledgeErrInvalidExtensionErrInvalidRender
The separate workspacefs package classifies malformed filesystem-workspace input with workspacefs.ErrInvalidInput and exhausted load/traversal limits with workspacefs.ErrBudgetExceeded.
Diagnostic strings are not compatibility contracts.
Successfully built immutable Document, DocumentGraph, KnowledgeIndex, WorkspaceReport, workspacefs.Workspace, and prepared ChangeSet values may be read concurrently.
DocumentBuilder is mutable and requires caller synchronization for concurrent use. Resolver and extension callbacks are invoked synchronously and are not retained after the build/parse call returns.
Public variable-length results are caller-owned unless an API explicitly states otherwise.
The root document/graph APIs perform no implicit filesystem, network, or command I/O. workspacefs adds only explicit read-only filesystem access through the caller's fs.FS; it does not write files, fetch URLs, or execute commands. Marksplice emits canonical Markdown or HTML only when explicitly requested; it does not render PDF, execute fenced languages, serialize arbitrary YAML/TOML, run templates, run a LaTeX/math engine, fetch assets, or normalize an existing document as a side effect of a structural edit.
Those boundaries are summarized in Capabilities. Architecture and conformance rationale live in the maintainer documentation.