Monorepo for Tangled tangled.org

appview: pages/markup: rewrite links links to camo url

anirudh.fi 6b54d85a 3867a5ac

verified
Changed files
+57 -16
appview
+2
appview/config.go
··· 13 13 Dev bool `env:"TANGLED_DEV, default=false"` 14 14 JetstreamEndpoint string `env:"TANGLED_JETSTREAM_ENDPOINT, default=wss://jetstream1.us-east.bsky.network/subscribe"` 15 15 ResendApiKey string `env:"TANGLED_RESEND_API_KEY"` 16 + CamoHost string `env:"TANGLED_CAMO_HOST, default=https://camo.tangled.sh"` 17 + CamoSharedSecret string `env:"TANGLED_CAMO_SHARED_SECRET"` 16 18 } 17 19 18 20 func LoadConfig(ctx context.Context) (*Config, error) {
+1 -1
appview/pages/funcmap.go
··· 143 143 return v.Slice(start, end).Interface() 144 144 }, 145 145 "markdown": func(text string) template.HTML { 146 - rctx := &markup.RenderContext{} 146 + rctx := &markup.RenderContext{RendererType: markup.RendererTypeDefault} 147 147 return template.HTML(rctx.RenderMarkdown(text)) 148 148 }, 149 149 "isNil": func(t any) bool {
+31
appview/pages/markup/camo.go
··· 1 + package markup 2 + 3 + import ( 4 + "crypto/hmac" 5 + "crypto/sha256" 6 + "encoding/hex" 7 + "fmt" 8 + 9 + "github.com/yuin/goldmark/ast" 10 + ) 11 + 12 + func generateCamoURL(baseURL, secret, imageURL string) string { 13 + h := hmac.New(sha256.New, []byte(secret)) 14 + h.Write([]byte(imageURL)) 15 + signature := hex.EncodeToString(h.Sum(nil)) 16 + hexURL := hex.EncodeToString([]byte(imageURL)) 17 + return fmt.Sprintf("%s/%s/%s", baseURL, signature, hexURL) 18 + } 19 + 20 + func (rctx *RenderContext) camoImageLinkTransformer(img *ast.Image) { 21 + // don't camo on dev 22 + if rctx.IsDev { 23 + return 24 + } 25 + 26 + dst := string(img.Destination) 27 + 28 + if rctx.CamoUrl != "" && rctx.CamoSecret != "" { 29 + img.Destination = []byte(generateCamoURL(rctx.CamoUrl, rctx.CamoSecret, dst)) 30 + } 31 + }
+12 -1
appview/pages/markup/markdown.go
··· 21 21 const ( 22 22 // RendererTypeRepoMarkdown is for repository documentation markdown files 23 23 RendererTypeRepoMarkdown RendererType = iota 24 + // RendererTypeDefault is non-repo markdown, like issues/pulls/comments. 25 + RendererTypeDefault 24 26 ) 25 27 26 28 // RenderContext holds the contextual data for rendering markdown. 27 29 // It can be initialized empty, and that'll skip any transformations. 28 30 type RenderContext struct { 31 + CamoUrl string 32 + CamoSecret string 29 33 repoinfo.RepoInfo 30 34 IsDev bool 31 35 RendererType RendererType ··· 73 77 a.rctx.relativeLinkTransformer(n.(*ast.Link)) 74 78 case *ast.Image: 75 79 a.rctx.imageFromKnotTransformer(n.(*ast.Image)) 80 + a.rctx.camoImageLinkTransformer(n.(*ast.Image)) 76 81 } 77 - // more types here like RendererTypeIssue/Pull etc. 82 + 83 + case RendererTypeDefault: 84 + switch n.(type) { 85 + case *ast.Image: 86 + a.rctx.imageFromKnotTransformer(n.(*ast.Image)) 87 + a.rctx.camoImageLinkTransformer(n.(*ast.Image)) 88 + } 78 89 } 79 90 80 91 return ast.WalkContinue, nil
+10 -13
appview/pages/pages.go
··· 15 15 "path/filepath" 16 16 "strings" 17 17 18 + "tangled.sh/tangled.sh/core/appview" 18 19 "tangled.sh/tangled.sh/core/appview/auth" 19 20 "tangled.sh/tangled.sh/core/appview/db" 20 21 "tangled.sh/tangled.sh/core/appview/pages/markup" ··· 43 44 rctx *markup.RenderContext 44 45 } 45 46 46 - func NewPages(dev bool) *Pages { 47 + func NewPages(config *appview.Config) *Pages { 47 48 // initialized with safe defaults, can be overriden per use 48 49 rctx := &markup.RenderContext{ 49 - IsDev: dev, 50 + IsDev: config.Dev, 51 + CamoUrl: config.CamoHost, 52 + CamoSecret: config.CamoSharedSecret, 50 53 } 51 54 52 55 p := &Pages{ 53 56 t: make(map[string]*template.Template), 54 - dev: dev, 57 + dev: config.Dev, 55 58 embedFS: Files, 56 59 rctx: rctx, 57 60 templateDir: "appview/pages", ··· 379 382 return p.executeRepo("repo/empty", w, params) 380 383 } 381 384 382 - p.rctx = &markup.RenderContext{ 383 - RepoInfo: params.RepoInfo, 384 - IsDev: p.dev, 385 - RendererType: markup.RendererTypeRepoMarkdown, 386 - } 385 + p.rctx.RepoInfo = params.RepoInfo 386 + p.rctx.RendererType = markup.RendererTypeRepoMarkdown 387 387 388 388 if params.ReadmeFileName != "" { 389 389 var htmlString string ··· 508 508 if params.ShowRendered { 509 509 switch markup.GetFormat(params.Path) { 510 510 case markup.FormatMarkdown: 511 - p.rctx = &markup.RenderContext{ 512 - RepoInfo: params.RepoInfo, 513 - IsDev: p.dev, 514 - RendererType: markup.RendererTypeRepoMarkdown, 515 - } 511 + p.rctx.RepoInfo = params.RepoInfo 512 + p.rctx.RendererType = markup.RendererTypeRepoMarkdown 516 513 params.RenderedContents = template.HTML(p.rctx.RenderMarkdown(params.Contents)) 517 514 } 518 515 }
+1 -1
appview/state/state.go
··· 55 55 56 56 clock := syntax.NewTIDClock(0) 57 57 58 - pgs := pages.NewPages(config.Dev) 58 + pgs := pages.NewPages(config) 59 59 60 60 resolver := appview.NewResolver() 61 61