extensions

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: May 10, 2026 License: AGPL-3.0 Imports: 9 Imported by: 0

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

func New

func New(opts *Options) goldmark.Extender

New constructs the extender with the given options.

Types

type Extension

type Extension struct{ Opts *Options }

Extension is a goldmark.Extender that registers the AST transformer.

func (*Extension) Extend

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

Extend implements goldmark.Extender.

type Mention

type Mention struct {
	Username string
	Href     string
}

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 Ref

type Ref struct {
	Kind    string
	Owner   string
	Repo    string
	Number  int64
	FullSHA string
	Href    string
}

Ref / Mention mirror the parent-package types; we redeclare to avoid an import cycle.

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.

Jump to

Keyboard shortcuts

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