-
-
Notifications
You must be signed in to change notification settings - Fork 393
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 plugin capability #380
Comments
I'm not quite sure wether this comment is best placed here or under #381, but I tend to here, so I'll place it here. I agree that a plugin feature is really missing from shiki, but the current plugin proposal doesn't fit all usecases that I have for plugins. My Usecases1. Embedding into SSGsI want to use shiki in a SSG where I add it as a wrapped plugin that is configured once to my likings and then called many times (once for each codeblock) and I want to keep config between calls. 2. Wrapping OutputI want to add additional custom html around what shiki renders to e.g. add a header that shows the language and file name. This might be based on content of the lang and code. 3. Modify input code as textMy usecase uses something similar to the #5 decoration API where I add markers for enhancement or file name to the first line of a code block like this:
This currently breaks tokenization, because function greet(name) {
- console.log(`Hello ${name}`);
+ console.log(`Hello ${name || "World"}`);
} to show diffs or for line numbers this: 15 function greet(name) {
16 console.log(`Hello ${name || "World"}`);
...
25 } In both cases a plugin would need to modify the code before it is passed into tokenization. 4. Change tokenized dataI currently use inline comments to add modifiers to lines (similar to how [torchlight.dev] does this): function greet(name) {
console.log(`Hello ${name || "World"}`); // [sh! highlight]
} This would be rendered like the following with the second line highlighted via a class: function greet(name) {
console.log(`Hello ${name || "World"}`);
} This requires that a plugin is able to alter the tokenized code (so comments are correctly detected and can be analyzed). 5. Remove classes / attributesI came across the issue where the name of my theme was already used in my CSS, so I didn't want the theme name to appear as a class. Requirements from these usecasesAt least three hooks are needed for plugins:
Also unlike in the current proposal plugins shouldn't be cleared between each render call. I think in those cases a second instance of For usecase number 5, the current proposal has a search and replace based solution, but I think that one is really not good, especially when you keep potential bugs with replacements in mind like this plugin: module.exports = config => {
return {
name: 'pluginHookAfter',
hooks: {
after: context => {
return context.elementType === 'pre'
? { html: context.html.replace(/class="shiki/, 'class="highlighter') }
: { html: context.html }
}
}
}
} would make this:
into this:
This could be fixed, if the tags are functions instead of objects, which can modify the tag. But I don't know if that's the best option. As you can see, I have some thoughts and I hope the final solution can match my usecases. |
Shiki would benefit from providing a pluggable plugin architecture.
Why?
renderHTML
directly and provides their element definition.How?
Good question. I started to design an (opinionated) approach, you can look at it in #381
The text was updated successfully, but these errors were encountered: