antfu / shikiji

A syntax highlighter based on TextMate grammars. ESM rewrite of shiki, with more features and capabilities.
https://shikiji.netlify.app/
MIT License
1.47k stars 38 forks source link

feat(transformers): two new transformers for word highlighting #92

Closed fuma-nama closed 8 months ago

fuma-nama commented 8 months ago

Description

Add functionality for highlighting a specific word/token, for example, a variable name. It adds a highlighted-word class to the matching element.

transformerNotationWordHighlight

Use [!code word:xxx] to highlight a word (adding highlighted-word class).

export function foo() {
  // [!code word:a]
  const a = 'Hello World'
}

Notice that you cannot place anything before the comment in the same line of code.

transformerMetaWordHighlight

Highlight words based on the meta string provided on the code snippet. Requires integrations supports.

```js /a/
const a = 'Hello World'
console.log(a)

- Updated docs
- Updated tests

### Linked Issues

fix #95

### Additional context

The current implementation does a bit more than line highlighting because a token can contain whitespaces, like ` a` for example. We will separate the matched string and its whitespaces:

Before:
```html
<span style="x"> a</span>

After:

<span style="x"> </span><span style="x" class="highlighted-word">a</span>

All properties from the original node will be kept.

netlify[bot] commented 8 months ago

Deploy Preview for shikiji ready!

Name Link
Latest commit a48b3cbc2683ba5b1c9873cb3fe9df44cbdd7ee2
Latest deploy log https://app.netlify.com/sites/shikiji/deploys/65a7f75a3bb11000083fb63f
Deploy Preview https://deploy-preview-92--shikiji.netlify.app
Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

fuma-nama commented 8 months ago

I noticed markdown-it-shikiji also uses similar transformers for highlighting. If you like, I can merge them into the shared folder so that we can reduce deduplicated code.

antfu commented 8 months ago

That's a nice idea! But instead of overloading the code block meta, I feel it might be better to use a control comment, like // [!code word:foo] and // [!code word:/hellos?/] (for regex). And we could have it in https://shikiji.netlify.app/packages/transformers so that can work for any integrations

fuma-nama commented 8 months ago

That is plausible, I'd agree using notation transformers for highlight features. But I think the current curly braces approach might be inconsistent if we prefer transformers over meta strings when highlighting lines.

Perhaps removing support for curly braces in a major release? So that we can solve many compatibility issues with meta string.

antfu commented 8 months ago

Yeah it makes sense to disable the meta-based highlight in a major in favor of the transformer we already have. And then we could remove it the next-next major.

I am planning to start the next major in beta, around now.

Edit: Done that in 21e9955408ec834c3fed388209e83df4c900258a and fe0e4cb298bc2391383376d39b340e8856db690f

fuma-nama commented 8 months ago

I have just added transformerNotationWordHighlight to support word highlighting:

```js
export function transformerNotationFocus(
  options = {}, // [!code highlight[options]:4]
) {
  const options = "Hello World"
  console.log(options)
}
dbzx10299 commented 8 months ago

I am also in favor of this syntax

```js /foo/
const foo = 'bar'
```

This is also a cool feature to be able to highlight only the first two instances of x. Rehype pretty code does all this but I think it would be cool to have something like this with just shikiji.

```js /x/1-2
let x = 1
x++
...
x++
```

or give the highlighted token an id

```js /x/#highlighted_token
const x = 1
```
fuma-nama commented 8 months ago

Probably can be an additional feature to the meta highlight transformer as @antfu suggested.

This can solve compatibility issues, especially if you are working with other rehype plugins.

antfu commented 8 months ago

I think we could have two transformers with different syntax (where shared the internal logic), like the current line highlight

fuma-nama commented 8 months ago

Just implemented a meta transformer similar to line highlighting.

This is also a cool feature to be able to highlight only the first two instances of x

About highlighting a word in a specific range, I would recommend using the notation transformer instead. You can easily specify a range right under the comment, so you don't have to waste time counting the line number of code.

codecov[bot] commented 8 months ago

Codecov Report

All modified and coverable lines are covered by tests :white_check_mark:

Comparison is base (ac6298b) 96.77% compared to head (e7f3216) 96.88%.

:exclamation: Current head e7f3216 differs from pull request most recent head a48b3cb. Consider uploading reports for the commit a48b3cb to get more accurate results

Additional details and impacted files ```diff @@ Coverage Diff @@ ## main #92 +/- ## ========================================== + Coverage 96.77% 96.88% +0.10% ========================================== Files 51 54 +3 Lines 4495 4648 +153 Branches 572 595 +23 ========================================== + Hits 4350 4503 +153 Misses 142 142 Partials 3 3 ```

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

dbzx10299 commented 8 months ago

This is an awesome feature to have! I love using this library so much more than shikijs and having a highlight word basically removes the need to use rehype pretty code. Is there a way with this transformer to make a specific class for the highlighted words?

For example this way two words could be targeted, and a different color could be applied to each one

const foo = ref() //add 'highlighted-word' class to foo + '#foo' id for example
const bar = ref() // in addition to 'highlighted-word', '#bar'
antfu commented 8 months ago

You can always wrote your custom https://shikiji.netlify.app/guide/transformers to do the customization you want

fuma-nama commented 8 months ago

It's not hard to add this as a new feature though, welcome for contributions!