Documentation
¶
Overview ¶
Package extensions hosts the AST transformer that adds shithub- specific inline patterns (`@user`, `#N`, `owner/repo#N`, commit SHAs, emoji shortcodes) to Goldmark's parsed text without ever touching the contents of code blocks or inline code.
Approach: a single `parser.ASTTransformer` walks the document after parsing, visiting only `*ast.Text` nodes whose ancestors are NOT code/codespan/autolink/link nodes. Each visited text node is run through one combined regex; matches are replaced with `*ast.Link` (mention/ref/commit) or `*ast.String` (emoji) nodes, with the surrounding text preserved as `*ast.String` segments.
Why an ASTTransformer instead of inline parsers: inline parsers run during the main parse pass and need a `Trigger()` byte set plus careful interaction with Goldmark's existing inline disambiguation. The transformer approach is simpler, well-trodden in other Go markdown stacks, and produces equivalent output for every input we care about.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Extension ¶
type Extension struct{ Opts *Options }
Extension is a goldmark.Extender that registers the AST transformer.
type Options ¶
type Options struct {
Ctx context.Context
RepoOwner string
RepoName string
ViewerUserID int64
Resolvers Resolvers
// Refs and Mentions accumulate resolved references for the caller.
// Pointers so the transformer can append.
Refs *[]Ref
Mentions *[]Mention
}
Options is the per-render config consumed by the transformer.
type Resolvers ¶
type Resolvers struct {
User func(ctx context.Context, username string) (href string, ok bool)
// Issue covers both same-repo (#N when ownerHint == "") and
// cross-repo (owner/repo#N).
Issue func(ctx context.Context, ownerHint, repoHint string, number int64, viewerUserID int64) (href string, ok bool)
// Commit is invoked only when RepoOwner+RepoName are both set
// (a same-repo render) and the matched token is a 7-40 char
// lowercase hex string at a word boundary.
Commit func(ctx context.Context, repoOwner, repoName, shaPrefix string) (href, fullSHA string, ok bool)
// Team resolves an `@org/team` mention to the team page link.
// Visibility-aware: a secret team the viewer can't see should
// return `ok=false` so the renderer falls back to plain text
// (no existence leak).
Team func(ctx context.Context, orgSlug, teamSlug string, viewerUserID int64) (href string, ok bool)
}
Resolvers wires the transformer against the runtime. The fields are independent so the parent package can decide which flavors to enable. nil-resolver means "render this kind as plain text" (no link, no error).
All resolvers MUST be visibility-aware. The transformer does not re-check visibility — it trusts the resolver's `ok` to gate existence.