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

Add some kind of "non-rendering render hook" #26

Closed
bep opened this issue Nov 7, 2019 · 5 comments
Closed

Add some kind of "non-rendering render hook" #26

bep opened this issue Nov 7, 2019 · 5 comments

Comments

@bep
Copy link

@bep bep commented Nov 7, 2019

In working on adding this to Hugo, I wanted to implement ToC in a general way that we could possibly also use for other things; e.g. a "content map" with byte slice pointers (start/stop) into the rendered content.

I experimented by creating an extension:

https://github.com/bep/hugo/blob/goldmark2/markup/goldmark/contentmap.go#L35

But that doesn't work, as I notice that you pick up the first renderer for a given node kind.

Note that for the ToC thing (which is what Hugo has today), I can traverse the AST and build the ToC from that, but it would be really useful if could somehow register the rendered start/stop position for the different blocks; so people could do things like:

  • Split content over multiple pages
  • Insert ads/bylines etc.
  • ...

Again, thanks for this library, it's really easy to use.

@yuin

This comment has been minimized.

Copy link
Owner

@yuin yuin commented Nov 7, 2019

What you want is probably an ASTTransformer. You can add your ASTTransformer by WithASTTransformers.

The footnote extension is implemented using an ASTTransformer(see here)

In case of ToC extension, you can use the ast.Walk function inside an ASTTransformer to traverse heading nodes,

If I implement a ToC Extension:

  1. Define an ast.TableOfContents block node
  2. Define parser.BlockParser to parse my ToC expression
  3. Define an parser.ASTTransformer
    1. Allocate some collection(slice, map, or structs) to store "ToC" data.
    2. Call ast.Walk
      1. If find a heading node, add it to the collection.
      2. if find an ast.TableOfContents node, assign it to some variable.
  4. Update an ast.TableOfContents node that was found at above by the collection.
  5. Define a parser.NodeRenderer that renders ast.TableOfContents node
  6. Wrap these up as an Extender .
@bep

This comment has been minimized.

Copy link
Author

@bep bep commented Nov 7, 2019

Adding the ToC to this discussion was a mistake.

What I want/need (which I also would consider to be generally very useful) is a way to map the rendered output, i.e.record the start/stop indices of selected blocks in the render buffer, so I could do:

buf := &bytes.Buffer{}
md.Convert(ctx.Src, buf)
b := buf.Bytes()

firstHeader := b[12:32]
@bep

This comment has been minimized.

Copy link
Author

@bep bep commented Nov 7, 2019

But note that this isn't something I need right now, but it would be really cool...

@yuin

This comment has been minimized.

Copy link
Owner

@yuin yuin commented Nov 8, 2019

I see. But I have never seen such functionalities in other libraries, so I can not imagine what is good APIs. Do you have any libraries in your mind that implement this functionality?

@stale

This comment has been minimized.

Copy link

@stale stale bot commented Dec 29, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Dec 29, 2019
@stale stale bot closed this Jan 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.