markdown

package
v0.11.0 Latest Latest
Warning

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

Go to latest
Published: Aug 17, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var KindSpoiler = ast.NewNodeKind("Spoiler")

KindSpoiler is the kind of SpoilerNode

Functions

func BalanceOpenMarkers added in v0.9.0

func BalanceOpenMarkers(s string) string

BalanceOpenMarkers appends the minimum suffix needed to close any open Markdown markers in `s`, so that mid-stream content can be safely fed to ToHTML without producing dangling/unrendered markup.

Handled markers (these cover ~99% of LLM chat output):

  • Triple-backtick fenced code blocks (```)
  • Inline code (`)
  • Bold (**)

Intentionally NOT handled — they're rare in chat and the heuristics would do more harm than good (snake_case identifiers, mathematical asterisks, etc.):

  • Single-asterisk italic (*)
  • Underscore italic (_) and underscore bold (__)
  • Strikethrough (~~)

The function is purely additive: it never modifies or removes characters from the input. If a marker can't be cleanly closed (e.g. an opening fence with no language line yet) the function still appends a closer so goldmark sees a well-formed buffer.

func HardSplitUTF16 added in v0.10.1

func HardSplitUTF16(s string, limit int) []string

HardSplitUTF16 splits s into pieces of at most limit UTF-16 code units, cutting on rune boundaries and preferring a whitespace boundary near the cut. Last-resort plain-text splitter for content that cannot be delivered formatted within the budget.

func NewSpoilerExtension

func NewSpoilerExtension() goldmark.Extender

NewSpoilerExtension creates a new SpoilerExtension

func NewSpoilerHTMLRenderer

func NewSpoilerHTMLRenderer(opts ...html.Option) renderer.NodeRenderer

NewSpoilerHTMLRenderer creates a new SpoilerHTMLRenderer

func NewTelegramHTMLRenderer

func NewTelegramHTMLRenderer(opts ...ghtml.Option) renderer.NodeRenderer

NewTelegramHTMLRenderer creates a new TelegramHTMLRenderer

func SafeLegacyPlainText added in v0.11.0

func SafeLegacyPlainText(text string) string

SafeLegacyPlainText escapes a last-resort plain-text chunk and applies the same mention neutralization as ToSafeLegacyHTML.

func ToHTML

func ToHTML(markdown string) (string, error)

ToHTML converts Markdown to Telegram-compatible HTML

func ToSafeLegacyHTML added in v0.11.0

func ToSafeLegacyHTML(markdown string) (string, error)

ToSafeLegacyHTML renders the policy-equivalent legacy representation used only as a preflighted fallback for Rich Messages. It preserves image alt text, removes unsafe/model-authored mention links and neutralizes bare @mentions so legacy entity auto-detection cannot bypass the rich skip_entity_detection boundary.

func UTF16Length

func UTF16Length(s string) int

UTF16Length calculates the length of a string in UTF-16 code units This is how Telegram counts message length

Types

type RichDocument added in v0.11.0

type RichDocument struct {
	LegacySource string
	HTML         string
	Stats        RichStats
	Fragments    []RichFragment
}

RichDocument is the immutable result of one canonical Markdown parse. HTML and Stats are exact aggregates of Fragments in order. LegacySource is kept byte-identical even when the rich parser applies its narrow list-boundary normalization internally.

func ParseRichFragments added in v0.11.0

func ParseRichFragments(input string) (RichDocument, error)

ParseRichFragments parses canonical Markdown once and renders every top-level block as an independently packable Rich HTML fragment. Every returned fragment is atomic: callers may combine adjacent fragments into a Telegram message, but must not split a fragment internally. This keeps lists, tables, quotes, code and display math structurally valid.

type RichFragment added in v0.11.0

type RichFragment struct {
	Kind         RichFragmentKind
	Atomic       bool
	SourceStart  int
	SourceEnd    int
	LegacySource string
	HTML         string
	Stats        RichStats
	// BoundaryTextRanges are exact source ranges of direct Text children of a
	// top-level paragraph. Application protocol markers may only be recognized
	// inside these ranges; syntax owned by any inline container is excluded.
	BoundaryTextRanges []RichSourceRange
}

RichFragment is one complete top-level Markdown block rendered through the Rich HTML allowlist. Atomic is deliberately explicit: a delivery packer may group adjacent fragments, but must not split an atomic fragment's HTML or LegacySource. SourceStart and SourceEnd are byte offsets into the exact input passed to ParseRichFragments, and LegacySource is that byte-identical slice. Blank lines between blocks belong to the preceding fragment so the ordered LegacySource values concatenate back to the input without normalization.

type RichFragmentKind added in v0.11.0

type RichFragmentKind string

RichFragmentKind identifies the top-level structural unit represented by a RichFragment. A fragment kind describes the rendered structure rather than the Markdown spelling (for example, both fenced and indented code are code fragments).

const (
	RichFragmentParagraph  RichFragmentKind = "paragraph"
	RichFragmentHeading    RichFragmentKind = "heading"
	RichFragmentList       RichFragmentKind = "list"
	RichFragmentTable      RichFragmentKind = "table"
	RichFragmentCode       RichFragmentKind = "code"
	RichFragmentMath       RichFragmentKind = "math"
	RichFragmentBlockquote RichFragmentKind = "blockquote"
	RichFragmentDivider    RichFragmentKind = "divider"
	RichFragmentRaw        RichFragmentKind = "raw"
	RichFragmentOther      RichFragmentKind = "other"
)

type RichSourceRange added in v0.11.0

type RichSourceRange struct {
	Start int
	End   int
}

RichSourceRange is a half-open byte range in the exact canonical input passed to ParseRichFragments.

type RichStats added in v0.11.0

type RichStats struct {
	Characters      int
	Blocks          int
	MaxDepth        int
	MaxTableColumns int
}

RichStats describes the Telegram rich-message limits represented by a rendered payload. Characters counts visible Unicode code points (including formula source); Blocks counts emitted structural blocks and nested list items/table rows; MaxDepth counts nested emitted tags; MaxTableColumns is the widest GFM table. The renderer reports these values but deliberately does not enforce Telegram's transport limits or split messages.

func ToRichHTML added in v0.11.0

func ToRichHTML(input string) (string, RichStats, error)

ToRichHTML renders canonical Markdown as a safe Telegram Rich HTML payload. It emits only an allowlisted textual/structural tag set. Raw HTML is ignored, Markdown images retain only their alt text, and unsafe links retain only their visible label, so model-controlled input cannot create rich media.

func ToRichHTMLPreview added in v0.11.0

func ToRichHTMLPreview(input string) (string, RichStats, error)

ToRichHTMLPreview renders a safe Telegram Rich HTML payload for a streaming draft. It shares ToRichHTML's parser and allowlist, but emits no active link or anchor elements: link labels remain visible as inert text. Telegram's skip_entity_detection transport option must also be enabled so visible bare URLs are not made clickable by a client during the preview.

type SpoilerExtension

type SpoilerExtension struct{}

SpoilerExtension is a goldmark extension for spoilers

func (*SpoilerExtension) Extend

func (e *SpoilerExtension) Extend(m goldmark.Markdown)

Extend implements goldmark.Extender

type SpoilerHTMLRenderer

type SpoilerHTMLRenderer struct {
	html.Config
}

SpoilerHTMLRenderer renders spoiler nodes to HTML

func (*SpoilerHTMLRenderer) RegisterFuncs

RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs

type SpoilerNode

type SpoilerNode struct {
	ast.BaseInline
}

SpoilerNode represents a spoiler node in the AST

func NewSpoilerNode

func NewSpoilerNode() *SpoilerNode

NewSpoilerNode creates a new SpoilerNode

func (*SpoilerNode) Dump

func (n *SpoilerNode) Dump(source []byte, level int)

Dump implements ast.Node.Dump

func (*SpoilerNode) Kind

func (n *SpoilerNode) Kind() ast.NodeKind

Kind implements ast.Node.Kind

type TelegramHTMLRenderer

type TelegramHTMLRenderer struct {
	ghtml.Config
	// contains filtered or unexported fields
}

TelegramHTMLRenderer is a custom renderer for Telegram HTML format

func (*TelegramHTMLRenderer) RegisterFuncs

RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs

Jump to

Keyboard shortcuts

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