···
"github.com/microcosm-cc/bluemonday"
"github.com/yuin/goldmark"
···
"github.com/yuin/goldmark/renderer/html"
"github.com/yuin/goldmark/text"
"github.com/yuin/goldmark/util"
20
+
htmlparse "golang.org/x/net/html"
"tangled.sh/tangled.sh/core/appview/pages/repoinfo"
···
if err := md.Convert([]byte(source), &buf); err != nil {
69
+
var processed strings.Builder
70
+
if err := postProcess(rctx, strings.NewReader(buf.String()), &processed); err != nil {
74
+
return processed.String()
77
+
func postProcess(ctx *RenderContext, input io.Reader, output io.Writer) error {
78
+
node, err := htmlparse.Parse(io.MultiReader(
79
+
strings.NewReader("<html><body>"),
81
+
strings.NewReader("</body></html>"),
84
+
return fmt.Errorf("failed to parse html: %w", err)
87
+
if node.Type == htmlparse.DocumentNode {
88
+
node = node.FirstChild
91
+
visitNode(ctx, node)
93
+
newNodes := make([]*htmlparse.Node, 0, 5)
95
+
if node.Data == "html" {
96
+
node = node.FirstChild
97
+
for node != nil && node.Data != "body" {
98
+
node = node.NextSibling
102
+
if node.Data == "body" {
103
+
child := node.FirstChild
105
+
newNodes = append(newNodes, child)
106
+
child = child.NextSibling
109
+
newNodes = append(newNodes, node)
113
+
for _, node := range newNodes {
114
+
if err := htmlparse.Render(output, node); err != nil {
115
+
return fmt.Errorf("failed to render processed html: %w", err)
122
+
func visitNode(ctx *RenderContext, node *htmlparse.Node) {
124
+
case htmlparse.ElementNode:
125
+
if node.Data == "img" {
126
+
for i, attr := range node.Attr {
127
+
if attr.Key != "src" {
130
+
attr.Val = ctx.imageFromKnotTransformer(attr.Val)
131
+
attr.Val = ctx.camoImageLinkTransformer(attr.Val)
132
+
node.Attr[i] = attr
136
+
for n := node.FirstChild; n != nil; n = n.NextSibling {
func (rctx *RenderContext) Sanitize(html string) string {
···
a.rctx.relativeLinkTransformer(n)
104
-
a.rctx.imageFromKnotTransformer(n)
105
-
a.rctx.camoImageLinkTransformer(n)
180
+
a.rctx.imageFromKnotAstTransformer(n)
181
+
a.rctx.camoImageLinkAstTransformer(n)
case RendererTypeDefault:
110
-
a.rctx.imageFromKnotTransformer(n)
111
-
a.rctx.camoImageLinkTransformer(n)
186
+
a.rctx.imageFromKnotAstTransformer(n)
187
+
a.rctx.camoImageLinkAstTransformer(n)
···
link.Destination = []byte(newPath)
133
-
func (rctx *RenderContext) imageFromKnotTransformer(img *ast.Image) {
134
-
dst := string(img.Destination)
209
+
func (rctx *RenderContext) imageFromKnotTransformer(dst string) string {
···
newPath := parsedURL.String()
158
-
img.Destination = []byte(newPath)
235
+
func (rctx *RenderContext) imageFromKnotAstTransformer(img *ast.Image) {
236
+
dst := string(img.Destination)
237
+
img.Destination = []byte(rctx.imageFromKnotTransformer(dst))
// actualPath decides when to join the file path with the