feat: rendering for image descriptions
Text inside an image's alt-text section `` will be treated as markdown and rendered as HTML inside `<small>` tags (all still inside the image-container div).
This commit is contained in:
parent
ce706e4ff9
commit
525cbcd980
1 changed files with 48 additions and 3 deletions
|
@ -53,12 +53,21 @@ func processLink(p string) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderImage(w io.Writer, node *ast.Image, entering bool) {
|
// renderImage outputs an ast Image node as HTML string.
|
||||||
|
func renderImage(w io.Writer, node *ast.Image, entering bool, next *ast.Text) {
|
||||||
// we add image-container div tag
|
// we add image-container div tag
|
||||||
// here before the opening img tag
|
// here before the opening img tag
|
||||||
if entering {
|
if entering {
|
||||||
fmt.Fprintf(w, "<div class=\"image-container\">\n")
|
fmt.Fprintf(w, "<div class=\"image-container\">\n")
|
||||||
fmt.Fprintf(w, `<img src="%s" title="%s">`, node.Destination, node.Title)
|
fmt.Fprintf(w, `<img src="%s" title="%s">`, node.Destination, node.Title)
|
||||||
|
if next != nil && len(next.Literal) > 0 {
|
||||||
|
// handle rendering Literal as markdown here
|
||||||
|
md := []byte(next.Literal)
|
||||||
|
html := convertEmbedded(md)
|
||||||
|
// TODO: render inside a special div?
|
||||||
|
// is this necessary since this is all inside image-container anyways?
|
||||||
|
fmt.Fprintf(w, `<small>%s</small>`, html)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// if it's the closing img tag
|
// if it's the closing img tag
|
||||||
// we close the div tag *after*
|
// we close the div tag *after*
|
||||||
|
@ -80,19 +89,55 @@ func renderLink(w io.Writer, l *ast.Link, entering bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func htmlRenderHookNoImage(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) {
|
||||||
|
if link, ok := node.(*ast.Link); ok {
|
||||||
|
renderLink(w, link, entering)
|
||||||
|
return ast.GoToNext, true
|
||||||
|
} else if _, ok := node.(*ast.Image); ok {
|
||||||
|
// we do not render images
|
||||||
|
return ast.GoToNext, true
|
||||||
|
}
|
||||||
|
return ast.GoToNext, false
|
||||||
|
}
|
||||||
|
|
||||||
// htmlRenderHook hooks the HTML renderer and overrides the rendering of certain nodes.
|
// htmlRenderHook hooks the HTML renderer and overrides the rendering of certain nodes.
|
||||||
func htmlRenderHook(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) {
|
func htmlRenderHook(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) {
|
||||||
if link, ok := node.(*ast.Link); ok {
|
if link, ok := node.(*ast.Link); ok {
|
||||||
renderLink(w, link, entering)
|
renderLink(w, link, entering)
|
||||||
return ast.GoToNext, true
|
return ast.GoToNext, true
|
||||||
} else if image, ok := node.(*ast.Image); ok {
|
} else if image, ok := node.(*ast.Image); ok {
|
||||||
// TODO: should do something more interesting with the alt text -- like put it in a <small> tag?
|
var nextNode *ast.Text
|
||||||
renderImage(w, image, entering)
|
if entering {
|
||||||
|
nextNodes := node.GetChildren()
|
||||||
|
fmt.Println("img next node len:", len(nextNodes))
|
||||||
|
if len(nextNodes) == 1 {
|
||||||
|
if textNode, ok := nextNodes[0].(*ast.Text); ok {
|
||||||
|
nextNode = textNode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
renderImage(w, image, entering, nextNode)
|
||||||
|
// Skip rendering of `nextNode` explicitly
|
||||||
|
if nextNode != nil {
|
||||||
|
return ast.SkipChildren, true
|
||||||
|
}
|
||||||
return ast.GoToNext, true
|
return ast.GoToNext, true
|
||||||
}
|
}
|
||||||
return ast.GoToNext, false
|
return ast.GoToNext, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convertEmbedded renders markdown as HTML
|
||||||
|
// but does NOT render images
|
||||||
|
func convertEmbedded(md []byte) []byte {
|
||||||
|
p := parser.NewWithExtensions(parser.CommonExtensions)
|
||||||
|
htmlFlags := html.CommonFlags | html.HrefTargetBlank
|
||||||
|
opts := html.RendererOptions{Flags: htmlFlags}
|
||||||
|
opts.RenderNodeHook = htmlRenderHookNoImage
|
||||||
|
r := html.NewRenderer(opts)
|
||||||
|
htmlText := markdown.ToHTML(md, p, r)
|
||||||
|
return htmlText
|
||||||
|
}
|
||||||
|
|
||||||
func newZonaRenderer(opts html.RendererOptions) *html.Renderer {
|
func newZonaRenderer(opts html.RendererOptions) *html.Renderer {
|
||||||
opts.RenderNodeHook = htmlRenderHook
|
opts.RenderNodeHook = htmlRenderHook
|
||||||
return html.NewRenderer(opts)
|
return html.NewRenderer(opts)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue