Documentation
¶
Overview ¶
CORE-09 (03-07): auto-fit + shrink MARKER emission -- a marker/attribute-materialization battery, NOT a rendering battery. This file emits two stable, sanitize-survivable markers:
- A fitting header ("# <!--fit-->") gets its marker comment stripped and a `data-auto-scaling="fit"` attribute added directly to the <hN> element.
- A fenced-code block or a "$$...$$" math-shaped paragraph gets wrapped in a `<div class="marp-fit-shrink">...</div>`.
`@auto-scaling` (the theme front-matter directive) is NOT handled here at all -- it is already parsed into theme metadata by chase/theme/meta.go (THEME-02) and lives entirely in theme CSS. This file never emits runtime JavaScript and never implements a layout pass; it only materializes the two markers. Originally these fed a now-removed viewer-side JS helper (Objective 8, 08-06 dropped it -- auto-fit is Flutter-only, 08-07); the markers themselves are UNCHANGED and stay emitted, now serving as the Flutter binding's fit signal instead (inert on the plain-HTML web path). The exact marker shape is a documented BASELINE -- Objective 8 owns any hardening.
Package press is Eden Press's public API (API-03): the ONE package a consumer imports to render a complete Marp-compatible deck from Markdown -- HTML + packed CSS + the JSON-serializable document model -- with no JavaScript runtime, no Node, and no browser (OBJECTIVE.md success criterion 4).
press.Render (defined in wave 3, TRD 03-09) is a SIBLING composition to chase.Render, not a wrapper: it drives its OWN battery-laden goldmark engine -- emoji (CORE-06), syntax highlighting via chroma (CORE-04/05), LaTeX-to-MathML (CORE-07/08), and an always-on bluemonday sanitize pass (CORE-05) -- through the SAME two-phase, one-parse flow chase already uses, via the additive chase/markdown.ParseWithEngine seam this objective introduces (TRD 03-01). It never touches chase.Render or chase/chase.go; every existing chase caller stays byte-for-byte unaffected.
This file (doc.go) carries only the package documentation. The public surface itself lives in options.go: the Options input struct and the Output result struct -- the frozen API-03 contract every wave-2 battery TRD and the wave-3 compose TRD (03-09) consume, and the shape Objective 7's Dart binding serializes over. Those types are defined once, here in press/, so the downstream binding never has to chase per-battery API churn.
Invariant: press/ never imports a headless-browser driver. `go list -deps ./press/...` must never contain chromedp -- Eden Press renders HTML and structured data without ever launching a browser, and that promise is enforced from the very first file in this package.
CORE-06: native emoji, no JavaScript. This file wires the SHORTCODE half (":smile:") entirely by REUSING github.com/yuin/goldmark-emoji v1.0.6 -- its emoji.New(...) is a goldmark.Extender that already registers an InlineParser (triggers on ':', shortcode table from definition.Github()) and a NodeRenderer (emoji.WithRenderingMethod(emoji.Twemoji) renders a static <img> tag). Nothing here hand-rolls a shortcode table or a ':' parser -- research's Don't-Hand-Roll row 1.
The OTHER half of CORE-06 -- literal unicode emoji typed directly in prose -- is emoji_unicode.go's bespoke InlineParser. Task 2 folds its unicodeEmojiExtender into emojiOptionWithTwemoji below, bundling both halves into the ONE goldmark.Option press.Render (03-09) will fold into its engine. goldmark-emoji's own parser only triggers on ':'; it never looks for raw unicode runes, so that gap is the entire bespoke surface this TRD adds (research Don't-Hand-Roll row 2).
CORE-06's bespoke half: literal unicode emoji typed directly in prose (as opposed to ":shortcode:", which emoji.go's reused goldmark-emoji parser already handles). goldmark-emoji's InlineParser triggers ONLY on ':' -- it never scans for raw unicode emoji runes -- so this file supplies ONLY the missing trigger + lookup. It deliberately emits the SAME east.Emoji AST node goldmark-emoji's own emojiHTMLRenderer already renders (registered by emoji.New's Extend, see emoji.go); no second NodeRenderer is registered here, and no <img> string is ever built by hand in this file.
definition.Github() (goldmark-emoji's own shortcode table) exposes no enumeration method -- only Get(shortName) -- so a full reverse-index walk of its ~1870 entries is not possible through the public API. Instead, unicodeEmojiShortnames below is a SEED list of canonical Github shortnames covering the common, mostly-single-rune emoji this baseline targets (error_recovery: ZWJ sequences / skin-tone modifiers are a documented long tail, not a blocker). Each seed name's *definition.Emoji is fetched via Get -- never hand-transcribed -- so its Name/Unicode/ShortNames fields are guaranteed byte-identical to what the shortcode parser itself resolves.
CORE-03's one genuinely new piece: goldmark GFM's extension.Strikethrough renders "~~x~~" as "<del>x</del>" (extension/strikethrough.go, registered at renderer priority 500), but Marp Core renders GFM strikethrough as "<s>x</s>". strikethrough.go closes that gap with a self-contained goldmark.Option a caller folds into chase/markdown.NewEngine's extra-opts hook -- it never re-implements or touches GFM tables, hard breaks, or heading-ID slugs, all three of which are already baked into NewEngine (extension.GFM, ghtml.WithHardWraps, parser.WithAutoHeadingID) and are verified, not re-wired, by gfm_verify_test.go.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Options ¶
type Options struct {
// Theme selects the named theme. "" resolves the deck's own front-matter
// `theme:` directive, and absent that, Marp Core's built-in "default"
// theme. A non-empty value overrides the front matter.
Theme string
// Profile selects the chase/profile.Profile that supplies the unit element
// and scaffold CSS. "" resolves profile.Default() (today: "slides", the
// only registered profile).
Profile string
// InlineSVG selects the inline-<svg><foreignObject> container mode. The
// 03-09 baseline turns this on to match Marp Core; the flag's own zero
// value is false and is documented here without any speculative inversion.
InlineSVG bool
// MathMode selects the math rendering backend. "" resolves to "mathml"
// (the CORE-07/08 baseline); "off" disables math rendering. Objective 8
// hardens the fallback rules on top of this baseline.
MathMode string
// NoHighlight disables syntax highlighting when true. It is INVERTED on
// purpose: the zero value (false) leaves highlighting ON, matching Marp
// Core's default, so an Options{} caller keeps chroma highlighting without
// having to opt in.
NoHighlight bool
// HighlightStyle names the chroma style used when highlighting is on. ""
// resolves the default style pre-verified against the .hljs class remap
// (CORE-04/05, TRD 03-05).
HighlightStyle string
// Sanitize is the HTML sanitization policy applied to the composed output.
// nil (the zero value) does NOT disable sanitization -- it selects the
// built-in always-on policy. CORE-05 sanitization is not optional; a
// caller may supply a stricter/looser *bluemonday.Policy, but never turn
// it off by leaving this nil.
Sanitize *bluemonday.Policy
// ThemeCSS is raw custom-theme CSS TEXT, additive to press.Render (TRD
// 04-01): each entry is a self-contained theme stylesheet that names
// itself via its own leading `/* @theme <name> */` comment (the same
// requirement chase/theme.Load enforces for the 3 bundled themes). The
// caller (e.g. the CLI's `--theme-set`) reads any theme file(s) from
// disk; press/ NEVER touches the filesystem itself -- Render stays a
// pure function of (md, opts). A nil/empty slice (the zero value) is a
// no-op: no custom themes are registered, and press.Render(md,
// Options{}) behaves exactly as it did before this field existed.
//
// Each entry is registered via the SAME chase/theme.Load +
// ThemeSet.Add path the 3 embedded themes (default/gaia/uncover) use,
// so a custom theme becomes selectable by name through the normal
// opts.Theme / front-matter `theme:` resolution chain -- it is not a
// separate lookup mechanism.
ThemeCSS []string
}
Options configures press.Render (defined in TRD 03-09). This is the frozen API-03 input surface: it is defined once, here, and every wave-2 battery TRD and Objective 7's Dart binding builds against it, so it must stay stable -- add a field only when a named consumer needs it, never speculatively.
Its ZERO VALUE (press.Options{}) is a valid, Marp-Core-matching configuration: every field's zero value MEANS "do what Marp Core does by default", so press.Render(md, press.Options{}) just works. Two fields are deliberately shaped so their zero value is the SAFE default rather than an off/empty one -- NoHighlight is inverted (zero => highlighting ON) and Sanitize is nil-defaulted (zero => the built-in always-on policy applies).
type Output ¶
type Output struct {
// HTML is the battery-composed, post-sanitize rendered deck HTML.
HTML string
// CSS is the packed theme CSS (chase/theme ThemeSet.Pack output).
CSS string
// Model is the JSON-serializable document model, exactly as
// chase/model.Build produces it -- unchanged by the press batteries.
Model *model.Document
// Meta is a convenience alias for Model.Meta (deck-level front-matter
// metadata), surfaced top-level so a caller wanting only metadata need not
// reach through Model.
Meta model.Meta
// Comments is the deck's speaker notes flattened into document order: the
// aggregation of every model.Section.Notes entry across Model.Sections.
// It is []string (never a nested shape) -- the exact contract the Dart
// binding serializes. It is NOT a fresh AST walk; model.Section.Notes is
// already populated by chase/model.Build.
Comments []string
// Profile is the ID of the chase/profile.Profile that produced this
// Output ("slides", "paged"). Recorded so a downstream exporter can
// resolve the SAME size table this render used, instead of guessing.
//
// Before this field existed, convert/pdf hardcoded profiles/slides' table
// (so an A4 paged document exported at 1280x720) and convert/png called
// profile.Default(), whose "first registered wins" rule depends on the
// final binary's import graph rather than on anything the caller decided --
// the hazard press.Render itself was fixed to avoid (see
// defaultProfileName's comment in press.go).
//
// Render records the RESOLVED profile's own ID, never opts.Profile: an
// empty opts.Profile resolves to "slides" by name, and recording "" would
// leave the exporters guessing again for every default render.
//
// This is a press.Output field, NOT a model.Document field: it carries no
// JSON schema contract and so needs no model.SchemaVersion bump.
Profile string
}
Output is press.Render's result -- the frozen API-03 output contract, the stable shape Objective 7's Dart binding serializes to JSON. It mirrors chase.Output (HTML/CSS/Model/Meta) and adds Comments, the flattened speaker notes already carried by the model.
func Render ¶
Render is the PUBLIC one-parse-two-sinks composition (API-01): it wires every press battery (03-03 strikethrough, 03-04 emoji, 03-05 highlight, 03-06 math, 03-07 autofit) into a SINGLE battery-laden goldmark engine, runs the seam's ONE parse over md, and forks that single finalized *ast.Document to two independent sinks -- the HTML renderer (sink 1) and chase/model.Build (sink 2) -- then sanitizes the composed HTML LAST, packs the theme CSS from the embedded ThemeSet, and aggregates speaker notes into Comments.
It is a SIBLING to chase.Render, never a wrapper: it builds its own engine via markdown.NewEngine(pressExtraOpts...) and drives markdown.ParseWithEngine directly, so chase/chase.go is neither called nor modified (03-09 anti_patterns) and the one-parse invariant is preserved -- building on top of chase.Render would re-parse.
CRITICAL: exactly ONE markdown.ParseWithEngine call happens in this function. Every render-affecting Option is honored; press.Render(md, Options{}) works at the zero value (Marp-Core-matching defaults).
type TwemojiOptions ¶
type TwemojiOptions struct {
// Base is the CDN or local base path emoji <img src> values are resolved
// against, e.g. "https://cdn.jsdelivr.net/gh/twitter/twemoji@latest/assets/72x72/".
Base string
// Ext is the image file extension, including the leading dot, e.g.
// ".png" or ".svg".
Ext string
}
TwemojiOptions configures the twemoji CDN/base + file extension used when rendering emoji as <img> tags -- the base/ext half of Marp's emoji contract (FEATURES.md). Base must end in "/"; Ext must include the leading dot (e.g. ".png" or ".svg").
func DefaultTwemojiOptions ¶
func DefaultTwemojiOptions() TwemojiOptions
DefaultTwemojiOptions returns the sensible default: jsDelivr's public twemoji CDN serving 72x72 PNG assets -- byte-identical to goldmark-emoji's own emoji.DefaultTwemojiTemplate, just expressed as overridable base/ext fields instead of a single opaque template string.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package math is CORE-08's BASELINE math battery: a self-contained goldmark.Option that renders Pandoc/Marp-style `$…$` (inline) and `$$…$$` (block) LaTeX. Common math becomes native MathML via the vendored latex2mathml; heavy constructs the construct-detection predicate flags (detect.go) degrade to a PNG-only raster <img> via go-latex/latex.
|
Package math is CORE-08's BASELINE math battery: a self-contained goldmark.Option that renders Pandoc/Marp-style `$…$` (inline) and `$$…$$` (block) LaTeX. Common math becomes native MathML via the vendored latex2mathml; heavy constructs the construct-detection predicate flags (detect.go) degrade to a PNG-only raster <img> via go-latex/latex. |
|
Package sanitize authors CORE-05's always-on HTML allow-list sanitization policy: a bluemonday policy that behaviorally matches Marp's current (v4-era) `xss` allow-list, co-designed against every wave-2 battery's documented output shape so legitimate deck markup survives while XSS vectors are neutralized.
|
Package sanitize authors CORE-05's always-on HTML allow-list sanitization policy: a bluemonday policy that behaviorally matches Marp's current (v4-era) `xss` allow-list, co-designed against every wave-2 battery's documented output shape so legitimate deck markup survives while XSS vectors are neutralized. |
|
Package themes builds a name-keyed *chase/theme.ThemeSet from the three official Marp themes bundled verbatim via go:embed (CORE-01).
|
Package themes builds a name-keyed *chase/theme.ThemeSet from the three official Marp themes bundled verbatim via go:embed (CORE-01). |