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.
115 lines
3.0 KiB
Go
115 lines
3.0 KiB
Go
package domutils
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/JohannesKaufmann/dom"
|
|
"golang.org/x/net/html"
|
|
)
|
|
|
|
// TODO: make this configurable via the options???
|
|
func getMarkdownStructure(name string) string {
|
|
switch name {
|
|
case "#document", "html", "head", "body",
|
|
"blockquote", "ul", "ol", "li":
|
|
// A container block can also contain other blocks.
|
|
return "container_block"
|
|
|
|
// Note: "p" would also be part of "leaf_block"
|
|
case "hr", "pre",
|
|
"h1", "h2", "h3", "h4", "h5", "h6":
|
|
// Leaf blocks can contain inline content
|
|
// but NOT other blocks.
|
|
return "leaf_block"
|
|
|
|
case "#text", "span", "code",
|
|
"b", "strong", "i", "em",
|
|
"a", "img", "br":
|
|
return "inline"
|
|
|
|
case "div", "p":
|
|
// Since these are just placing newlines,
|
|
// we dont categorize them.
|
|
return ""
|
|
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
func headingAlternative(ctx context.Context, node *html.Node) {
|
|
node.Data = "strong"
|
|
|
|
newChild := &html.Node{
|
|
Type: html.ElementNode,
|
|
Data: "br",
|
|
}
|
|
node.Parent.InsertBefore(newChild, node.NextSibling)
|
|
}
|
|
func blockquoteAlternative(ctx context.Context, node *html.Node) {
|
|
newBefore := &html.Node{Type: html.TextNode, Data: ` "`}
|
|
node.Parent.InsertBefore(newBefore, node)
|
|
|
|
node.Data = "span"
|
|
|
|
newAfter := &html.Node{Type: html.TextNode, Data: `" `}
|
|
node.Parent.InsertBefore(newAfter, node.NextSibling)
|
|
}
|
|
func preAlternative(ctx context.Context, node *html.Node) {
|
|
node.Data = "code"
|
|
}
|
|
func hrAlternative(ctx context.Context, node *html.Node) {
|
|
dom.RemoveNode(node)
|
|
}
|
|
|
|
// TODO: make this configurable via the options?
|
|
var alternatives = map[string]func(ctx context.Context, node *html.Node){
|
|
"h1": headingAlternative,
|
|
"h2": headingAlternative,
|
|
"h3": headingAlternative,
|
|
"h4": headingAlternative,
|
|
"h5": headingAlternative,
|
|
"h6": headingAlternative,
|
|
"blockquote": blockquoteAlternative,
|
|
"pre": preAlternative,
|
|
"hr": hrAlternative,
|
|
}
|
|
|
|
func LeafBlockAlternatives(ctx context.Context, doc *html.Node) {
|
|
var finder func(node *html.Node, isInsideLeafBlock bool, isInsideInline bool)
|
|
finder = func(node *html.Node, isInsideLeafBlock bool, isInsideInline bool) {
|
|
name := dom.NodeName(node)
|
|
|
|
structure := getMarkdownStructure(name)
|
|
if (structure == "container_block" || structure == "leaf_block") && (isInsideLeafBlock || isInsideInline) {
|
|
// A block inside an inline OR a block inside a leaf-block
|
|
// is not valid markdown so cannot be rendered.
|
|
//
|
|
// For example, you cannot place a blockquote inside a heading.
|
|
//
|
|
// Instead of this weird output (## Heading > My Quote)
|
|
// we try to find alternatives (## Heading "My Quote")
|
|
fn, ok := alternatives[name]
|
|
if ok {
|
|
fn(ctx, node)
|
|
} else {
|
|
node.Data = "span"
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - //
|
|
|
|
if structure == "leaf_block" {
|
|
isInsideLeafBlock = true
|
|
}
|
|
if structure == "inline" {
|
|
isInsideInline = true
|
|
}
|
|
|
|
for child := node.FirstChild; child != nil; child = child.NextSibling {
|
|
defer finder(child, isInsideLeafBlock, isInsideInline)
|
|
}
|
|
}
|
|
finder(doc, false, false)
|
|
}
|