reflex icon indicating copy to clipboard operation
reflex copied to clipboard

[ENG-3848][ENG-3861]Shiki Code block Experimental

Open ElijahAhianyo opened this issue 1 year ago β€’ 2 comments

High-level API

rx._x.code_block(
        """
     console.log('hewwo') 
     console.log('hello')
     console.log('goodbye') 
  """,
       language="typescript",
       theme="github-dark",
)
Screenshot 2024-10-01 at 4 09 03 PM (2)

With copy button

rx._x.code_block(
        """
     console.log('hewwo') 
     console.log('hello')
     console.log('goodbye') 
  """,
       language="typescript",
       theme="github-dark",
       can_copy=True
 )
Screenshot 2024-10-01 at 4 12 17 PM (2)

Using transformers

rx._x.code_block(
        """
    console.log('hewwo') // [!code --]
     console.log('hello') // [!code ++]
     console.log('goodbye') // [!code highlight]
  """,
       language="typescript",
       use_transformers=True,
       theme="github-dark",
 )
Screenshot 2024-10-01 at 4 17 21 PM (2)

Low-level API

Shikijs transformer

The shiki transformer is provided via code_block.transformers API.

rx._x.code_block.root(
        """
    console.log('hewwo') // [!code --]
    console.log('hello') // [!code ++]
    console.log('goodbye') // [!code highlight]
  """,
       language="typescript",
       transformers=[rx._x.code_block.transformers.shikijs(fns=["transformerNotationDiff", "transformerNotationHighlight"])],
       theme="github-dark",
 )
Screenshot 2024-10-01 at 4 17 21 PM (2)

Custom transformer

In using custom transformers from third-party libs, we provide a code_block.create_transformer API that allows you to specify the library and functions to call from the lib.

rx._x.code_block.root(
        """
    console.log('hewwo') // [!code --]
    console.log('hello') // [!code ++]
    console.log('goodbye') // [!code highlight]
  """,
       language="typescript",
       transformers=[
                rx._x.code_block.create_transformer( # using a transformer from a third party library
                          library="shiki-transformer-color-highlight",
                          fns=["transformerColorHighlight"], 
                          style={...}
                  ),
                 {
                      code(node) { # lifted this off https://shiki.matsu.io/guide/transformers#transformers
                        this.addClassToHast(node, 'language-js')
                      },
                      line(node, line) {
                        node.properties['data-line'] = line
                        if ([1, 3, 4].includes(line))
                          this.addClassToHast(node, 'highlight')
                      },
                      span(node, line, col) {
                        node.properties['data-token'] = `token:${line}:${col}`
                      },
                },
         ],
         theme="github-dark",
 )

Some Notes:

  • The styling for provided transformer(code_block.transformers.shikijs ) needs to be improved. The bg colors for the diffs overflow out of the div as well as the line numbers.
  • Styles for other transformer fns in the provided transformer need to be provided (eg, for highlighting, etc)
  • copy button needs to be improved

ElijahAhianyo avatar Sep 30 '24 15:09 ElijahAhianyo

Could we just include transformers internally in the component so they dont have to define this. Just have all the transformers in there

That way we can avoid this line. transformers=[rx._x.code_block.transformers.shikijs(fns=["transformerNotationDiff", "transformerNotationHighlight"])],

Or have transformers be a boolean where it's disabled by default but they can enable it with some default styles. Then have a separate prop called custom_transformer where they can add customized ones. I think the current code is a a bit too low level for an end user

Alek99 avatar Oct 01 '24 17:10 Alek99

cant tell why the tests are failing after merge just by looking at the CI errors. @adhami3310 any ideas?

ElijahAhianyo avatar Oct 22 '24 15:10 ElijahAhianyo