Documentation
¶
Index ¶
- Variables
- func BalanceOpenMarkers(s string) string
- func HardSplitUTF16(s string, limit int) []string
- func NewSpoilerExtension() goldmark.Extender
- func NewSpoilerHTMLRenderer(opts ...html.Option) renderer.NodeRenderer
- func NewTelegramHTMLRenderer(opts ...ghtml.Option) renderer.NodeRenderer
- func SafeLegacyPlainText(text string) string
- func ToHTML(markdown string) (string, error)
- func ToSafeLegacyHTML(markdown string) (string, error)
- func UTF16Length(s string) int
- type RichDocument
- type RichFragment
- type RichFragmentKind
- type RichSourceRange
- type RichStats
- type SpoilerExtension
- type SpoilerHTMLRenderer
- type SpoilerNode
- type TelegramHTMLRenderer
Constants ¶
This section is empty.
Variables ¶
var KindSpoiler = ast.NewNodeKind("Spoiler")
KindSpoiler is the kind of SpoilerNode
Functions ¶
func BalanceOpenMarkers ¶ added in v0.9.0
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
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 ¶
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
SafeLegacyPlainText escapes a last-resort plain-text chunk and applies the same mention neutralization as ToSafeLegacyHTML.
func ToSafeLegacyHTML ¶ added in v0.11.0
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 ¶
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
RichSourceRange is a half-open byte range in the exact canonical input passed to ParseRichFragments.
type RichStats ¶ added in v0.11.0
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
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
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 ¶
SpoilerHTMLRenderer renders spoiler nodes to HTML
func (*SpoilerHTMLRenderer) RegisterFuncs ¶
func (r *SpoilerHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer)
RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs
type SpoilerNode ¶
type SpoilerNode struct {
ast.BaseInline
}
SpoilerNode represents a spoiler node in the AST
func (*SpoilerNode) Dump ¶
func (n *SpoilerNode) Dump(source []byte, level int)
Dump implements ast.Node.Dump
type TelegramHTMLRenderer ¶
TelegramHTMLRenderer is a custom renderer for Telegram HTML format
func (*TelegramHTMLRenderer) RegisterFuncs ¶
func (r *TelegramHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer)
RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs