Files
sift/vendor/github.com/JohannesKaufmann/html-to-markdown/v2/converter/ctx.go
T
kyle 9444a35322 p1: /v2/scrape, /v1/fetch, auth, CLI, contract tests
Single Fetcher.Fetch on the Guard that holds DenyPrefixes. skipTlsVerification
is ignored. No 502. keys add writes the secret only to --out. Release binary
has no -test-allow-prefix.
2026-09-22 21:54:01 -07:00

191 lines
4.8 KiB
Go

package converter
import (
"context"
"fmt"
"github.com/JohannesKaufmann/dom"
"golang.org/x/net/html"
)
// func GetValue[K string, V any](ctx context.Context, key K) V {
// val, _ := ctx.Value(key).(V)
// return val
// }
// func SetValue[K string, V any](ctx context.Context, key K, val V) context.Context {
// return context.WithValue(ctx, key, val)
// }
type ctxKey string
const (
ctxKeyAssembleAbsoluteURL ctxKey = "AssembleAbsoluteURL"
ctxKeyDomain ctxKey = "Domain"
ctxKeySetState ctxKey = "SetState"
ctxKeyUpdateState ctxKey = "UpdateState"
ctxKeyGetState ctxKey = "GetState"
)
func provideDomain(ctx context.Context, domain string) context.Context {
return context.WithValue(ctx, ctxKeyDomain, domain)
}
func GetDomain(ctx context.Context) string {
domain, ok := ctx.Value(ctxKeyDomain).(string)
if !ok {
fmt.Println("[warning] value ctxKeyDomain is different")
return ""
}
return domain
}
// - - - - - - - - - - - - - - - - - - - - - //
type AssembleAbsoluteURLFunc func(tagName string, rawURL string, domain string) string
func assembleAbsoluteURL(ctx context.Context, tagName string, rawURL string) string {
domain := GetDomain(ctx)
// TODO: since this gets passed down from the converter, it doesn't have to provided from the ctx anymore
fn, ok := ctx.Value(ctxKeyAssembleAbsoluteURL).(AssembleAbsoluteURLFunc)
if !ok {
fmt.Println("[warning] func ctxKeyAssembleAbsoluteURL is different")
return ""
}
return fn(tagName, rawURL, domain)
}
func provideAssembleAbsoluteURL(ctx context.Context, fn AssembleAbsoluteURLFunc) context.Context {
return context.WithValue(ctx, ctxKeyAssembleAbsoluteURL, fn)
}
// - - - - - - - - - - - - - - - - - - - - - //
type SetStateFunc func(key string, val any)
type UpdateStateFunc func(key string, fn func(any) any)
type GetStateFunc func(key string) any
type globalState struct {
data map[string]any
}
func newGlobalState() *globalState {
return &globalState{
data: make(map[string]any),
}
}
func (s *globalState) setState(key string, val any) {
s.data[key] = val
}
func (s *globalState) updateState(key string, fn func(any) any) {
s.data[key] = fn(s.data[key])
}
func (s *globalState) getState(key string) any {
return s.data[key]
}
func (s *globalState) provideGlobalState(ctx context.Context) context.Context {
var setState SetStateFunc = s.setState
var updateState UpdateStateFunc = s.updateState
var getState GetStateFunc = s.getState
ctx = context.WithValue(ctx, ctxKeySetState, setState)
ctx = context.WithValue(ctx, ctxKeyUpdateState, updateState)
ctx = context.WithValue(ctx, ctxKeyGetState, getState)
return ctx
}
func GetState[V any](ctx context.Context, key string) V {
fn := ctx.Value(ctxKeyGetState).(GetStateFunc)
val, _ := fn(key).(V)
return val
}
func SetState[V any](ctx context.Context, key string, val V) {
fn := ctx.Value(ctxKeySetState).(SetStateFunc)
fn(key, val)
}
func UpdateState[V any](ctx context.Context, key string, fn func(V) V) {
updater := ctx.Value(ctxKeyUpdateState).(UpdateStateFunc)
updater(key, func(val any) any {
value, ok := val.(V)
if !ok && val != nil {
// TODO: slog?
fmt.Println("[warning] val is different than V in UpdateState")
}
return fn(value)
})
}
// - - - - - - //
// Context extends the normal context.Context with some additional
// methods useful for the process of converting.
type Context interface {
context.Context
AssembleAbsoluteURL(ctx Context, tagName string, rawURL string) string
GetTagType(tagName string) (tagType, bool)
RenderNodes(ctx Context, w Writer, nodes ...*html.Node)
RenderChildNodes(ctx Context, w Writer, n *html.Node)
EscapeContent(content []byte) []byte
UnEscapeContent(content []byte) []byte
WithValue(key any, val any) Context
}
type converterContext struct {
context.Context
conv *Converter
}
func newConverterContext(ctx context.Context, conv *Converter) Context {
return &converterContext{
Context: ctx,
conv: conv,
}
}
func (c *converterContext) AssembleAbsoluteURL(ctx Context, tagName string, rawURL string) string {
return assembleAbsoluteURL(ctx, tagName, rawURL)
}
func (c *converterContext) RenderNodes(ctx Context, w Writer, nodes ...*html.Node) {
c.conv.handleRenderNodes(ctx, w, nodes...)
}
func (c *converterContext) RenderChildNodes(ctx Context, w Writer, n *html.Node) {
c.conv.handleRenderNodes(ctx, w, dom.AllChildNodes(n)...)
}
func (c *converterContext) GetTagType(tagName string) (tagType, bool) {
return c.conv.getTagType(tagName)
}
func (c *converterContext) EscapeContent(content []byte) []byte {
return c.conv.escapeContent(content)
}
func (c *converterContext) UnEscapeContent(content []byte) []byte {
return c.conv.unEscapeContent(content)
}
func (c *converterContext) WithValue(key any, val any) Context {
return &converterContext{
Context: context.WithValue(c.Context, key, val),
conv: c.conv,
}
}