Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ability to manipulate HTML-attributes with AST #483

Open
wants to merge 5 commits into
base: v2
Choose a base branch
from

Conversation

temapavloff
Copy link

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
Copy link
Collaborator

rtfb commented Sep 4, 2018

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

Thanks!

@bep
Copy link
Contributor

bep commented Sep 14, 2018

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