Skip to content

Added ability to manipulate HTML-attributes with AST - #483

Open
temapavloff wants to merge 5 commits into
russross:v2from
temapavloff:v2
Open

Added ability to manipulate HTML-attributes with AST#483
temapavloff wants to merge 5 commits into
russross:v2from
temapavloff:v2

Conversation

@temapavloff

Copy link
Copy Markdown

Purpose: make possible to change output HTML attributes without re-implementing whole renderer.

For example, I want to add extra class to paragraphs which contains images. Now I can do it simply analyzing and changing AST before rendering content:

func TestASTModification(t *testing.T) {
	input := "\nPicture signature\n![alt text](/p.jpg)\n"
	expected := "<p class=\"img\">Picture signature\n<img src=\"/p.jpg\" alt=\"alt text\" /></p>\n"

	r := NewHTMLRenderer(HTMLRendererParameters{
		Flags: CommonHTMLFlags,
	})
	var buf bytes.Buffer
	optList := []Option{
		WithRenderer(r),
		WithExtensions(CommonExtensions)}
	parser := New(optList...)
	ast := parser.Parse([]byte(input))
	r.RenderHeader(&buf, ast)
	ast.Walk(func(node *Node, entering bool) WalkStatus {
                // Where the magic happens
		if node.Type == Image && entering && node.Parent.Type == Paragraph {
			node.Parent.Attributes.Add("class", "img")
		}
		return GoToNext
	})
	ast.Walk(func(node *Node, entering bool) WalkStatus {
		return r.RenderNode(&buf, node, entering)
	})
	r.RenderFooter(&buf, ast)
	actual := buf.String()

	if actual != expected {
		t.Errorf("Expected: %s\nActual: %s\n", expected, actual)
	}
}

@rtfb

rtfb commented Sep 4, 2018

Copy link
Copy Markdown
Collaborator

I love the idea! Let me sit on it for a few days to let the API design to sink in...

Thanks!

@bep

bep commented Sep 14, 2018

Copy link
Copy Markdown
Contributor

While it would be cool to do something like the above, I don't think changing the AST is a good idea.

What I want to do with Blackfriday in Hugo is to parse once, render many. Adding HTML specific AST mods will break that. I think your approach could work if you somehow managed to create a copy of the node you want to "override".

Also, note that you don't have implement a full renderer to manipulate single nodes, as shown in my quick test repo below:

that https://github.com/bep/blackfriday-v2-test

You will end up with byte manipulation, which is less clean, but certainly possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants