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

What is the "right" way to add links around an inline token? #834

Closed
AramZS opened this issue Dec 23, 2021 · 4 comments
Closed

What is the "right" way to add links around an inline token? #834

AramZS opened this issue Dec 23, 2021 · 4 comments

Comments

@AramZS
Copy link
Contributor

AramZS commented Dec 23, 2021

So I've checked the docs and a number of plugins and seen a variety of way different folks add links to content. I'm not sure which is the best way or why. I have a plugin that processes inline commit messages I write into my blog posts, searches the GitHub API and gets back links to the actual commits. Most of that is pretty irrelevant to my question, but you can see the whole plugin here.

The relevant part is that I am looking for inline type tokens, finding ones with content matching my pattern, assuming that (because this is my writing pattern) it always has code_inline type children and adding a link around the code_inline token as follows:

const { link_open, link_close } = createLinkTokens(
	state.Token,
	linkToRepo
);
tokens[i].children.unshift(link_open);
tokens[i].children.push(link_close);

All this works fine, but I'm also trying to be as correct in my use of Markdown-It as possible so I have a question that doesn't seem to have a clear answer:

When creating the link should I be using html_inline or link_open and link_close?

For now, I'm using html_inline as follows:

const createLinkTokens = (TokenConstructor, commitLink) => {
	const link_open = new TokenConstructor("html_inline", "", 0);
	link_open.content = `<a target="_blank" href="${commitLink}" class="git-commit-link">`;
	// Why doesn't this work?
	// setAttr(link_open, "target", "_blank");
	// setAttr(link_open, "href", commitLink);
	// setAttr(link_open, "class", "git-commit-link");
	/**
	 * Ah, `html_inline` is not a "real" token type as per https://github.com/markdown-it/markdown-it/issues/320. 
	 * It can't have any further processing.
	 *
	 * Arguably I should use `link_open` here? 
	 * But [it](https://github.com/markdown-it/markdown-it/blob/df4607f1d4d4be7fdc32e71c04109aea8cc373fa/lib/rules_inline/link.js) 
	 * seems to be reserved for specific functionality within the plugin? So perhaps not.
	 */
	const link_close = new TokenConstructor("html_inline", "", 0);
	link_close.content = "</a>";
	return { link_open, link_close };
};

But I could also use link_open and then I would have access to the attrPush on the token and could use the setAttr functions commented out above, which looks like this:

function setAttr(token, name, value) {
	const index = token.attrIndex(name);
	const attr = [name, value];

	if (index < 0) {
		token.attrPush(attr);
	} else {
		token.attrs[index] = attr;
	}
}

But I'm not sure that's the right way to go? I don't seem to have any ability to tell which token types are already available at the point I initiate my plugin md.core.ruler.after("inline" or if a type like link_open is reserved for special behavior that might make it harder for my plugin to work properly?

This isn't some super urgent question, so please feel free to take your time to respond, but I would really like to know what the best practice is here. Thanks!

@puzrin
Copy link
Member

puzrin commented Dec 23, 2021

When creating the link should I be using html_inline or link_open and link_close?

html_inline is raw html injection, ignoring all abstraction layers. I would not recommend to use it.

Injecting link_open/close tokens is more appropriate. I would place it on the end of core chain (when all parser job done, but before renderer).

PS. It would be more easy to understand, if you could provide minimal "real world example" of input text and ouput text. Probably i missed something.

@AramZS
Copy link
Contributor Author

AramZS commented Dec 25, 2021

Ah, sorry, forgot that! The input markdown text would look like:

Some text etc...

`git commit -am "Touch up day 34 stuff"`

Some more text.

And I'm trying to capture the code_inline string git commit -am "Make a commit" to apply a link around it. So the target resulting HTML would look like:

<p>Some text etc...</p>
<p><a href="https://github.com/AramZS/devblog/commit/a901930b83fe4006c4f5759b0041f9192312585d" class="git-commit-link" target="_blank"><code>git commit -am "Touch up day 34 stuff"</code></a></p>
<p>Some more text.</p>

Right now my function is called as follows: md.core.ruler.after('inline', 'git_commit', state => {

But when you say "I would place it on the end of core chain", I'm not sure what the best way to do that is?

Would this make sense as the new way to call the rule function?

md.core.ruler.after(md.core.ruler.__rules__[md.core.ruler.__rules__.length-1].name, 'git_commit', state => {

@puzrin
Copy link
Member

puzrin commented Dec 25, 2021

Just use md.core.ruler.push()

https://github.com/markdown-it/markdown-it/blob/master/lib/ruler.js#L233

@AramZS
Copy link
Contributor Author

AramZS commented Dec 25, 2021

Ah, I hadn't seen that function. Thanks @puzrin ! This was very useful! I'm made the change and it looks like it is working: AramZS/devblog@af17fab

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

No branches or pull requests

2 participants