Shiki Code block Experimental
This commit is contained in:
parent
9719f5d57e
commit
8725ae5619
23
reflex/.templates/web/components/shiki/code.js
Normal file
23
reflex/.templates/web/components/shiki/code.js
Normal file
@ -0,0 +1,23 @@
|
||||
import { useEffect, useState } from "react"
|
||||
import { codeToHtml} from "shiki"
|
||||
|
||||
export function Code ({code, theme, language, themes, transformers}) {
|
||||
const [codeResult, setCodeResult] = useState("")
|
||||
useEffect(() => {
|
||||
async function fetchCode() {
|
||||
const result = await codeToHtml(code, {
|
||||
lang: language || "plaintext",
|
||||
theme: theme || "nord",
|
||||
transformers: transformers || []
|
||||
});
|
||||
setCodeResult(result);
|
||||
}
|
||||
fetchCode();
|
||||
}, [code, language, theme, themes, transformers]
|
||||
|
||||
)
|
||||
|
||||
return (
|
||||
<div dangerouslySetInnerHTML={{__html: codeResult}}></div>
|
||||
)
|
||||
}
|
@ -18,6 +18,7 @@ from reflex.utils.imports import ImportDict, ImportVar
|
||||
from reflex.vars.base import LiteralVar, Var, VarData
|
||||
|
||||
LiteralCodeLanguage = Literal[
|
||||
"ts",
|
||||
"abap",
|
||||
"abnf",
|
||||
"actionscript",
|
||||
|
381
reflex/components/datadisplay/shiki_code_block.py
Normal file
381
reflex/components/datadisplay/shiki_code_block.py
Normal file
@ -0,0 +1,381 @@
|
||||
from collections import defaultdict
|
||||
from typing import Any, Literal, Optional, Union
|
||||
|
||||
from reflex.components.component import Component
|
||||
from reflex.components.lucide.icon import Icon
|
||||
from reflex.components.radix.themes.components.button import Button
|
||||
from reflex.components.radix.themes.layout.box import Box
|
||||
from reflex.event import set_clipboard
|
||||
from reflex.style import Style
|
||||
from reflex.utils.imports import ImportDict, ImportVar
|
||||
from reflex.vars.base import Var
|
||||
from reflex.vars.function import FunctionStringVar
|
||||
|
||||
COMMON_TRANSFORMERS = {
|
||||
"transformerNotationDiff",
|
||||
"transformerNotationHighlight",
|
||||
"transformerNotationWordHighlight",
|
||||
"transformerNotationFocus",
|
||||
"transformerNotationErrorLevel",
|
||||
"transformerRenderWhitespace",
|
||||
"transformerMetaHighlight",
|
||||
"transformerMetaWordHighlight",
|
||||
"transformerCompactLineOptions",
|
||||
"transformerRemoveLineBreak",
|
||||
"transformerRemoveNotationEscape",
|
||||
}
|
||||
LiteralCodeLanguage = Literal[
|
||||
"ts",
|
||||
"abap",
|
||||
"abnf",
|
||||
"actionscript",
|
||||
"ada",
|
||||
"agda",
|
||||
"al",
|
||||
"antlr4",
|
||||
"apacheconf",
|
||||
"apex",
|
||||
"apl",
|
||||
"applescript",
|
||||
"aql",
|
||||
"arduino",
|
||||
"arff",
|
||||
"asciidoc",
|
||||
"asm6502",
|
||||
"asmatmel",
|
||||
"aspnet",
|
||||
"autohotkey",
|
||||
"autoit",
|
||||
"avisynth",
|
||||
"avro-idl",
|
||||
"bash",
|
||||
"basic",
|
||||
"batch",
|
||||
"bbcode",
|
||||
"bicep",
|
||||
"birb",
|
||||
"bison",
|
||||
"bnf",
|
||||
"brainfuck",
|
||||
"brightscript",
|
||||
"bro",
|
||||
"bsl",
|
||||
"c",
|
||||
"cfscript",
|
||||
"chaiscript",
|
||||
"cil",
|
||||
"clike",
|
||||
"clojure",
|
||||
"cmake",
|
||||
"cobol",
|
||||
"coffeescript",
|
||||
"concurnas",
|
||||
"coq",
|
||||
"core",
|
||||
"cpp",
|
||||
"crystal",
|
||||
"csharp",
|
||||
"cshtml",
|
||||
"csp",
|
||||
"css",
|
||||
"css-extras",
|
||||
"csv",
|
||||
"cypher",
|
||||
"d",
|
||||
"dart",
|
||||
"dataweave",
|
||||
"dax",
|
||||
"dhall",
|
||||
"diff",
|
||||
"django",
|
||||
"dns-zone-file",
|
||||
"docker",
|
||||
"dot",
|
||||
"ebnf",
|
||||
"editorconfig",
|
||||
"eiffel",
|
||||
"ejs",
|
||||
"elixir",
|
||||
"elm",
|
||||
"erb",
|
||||
"erlang",
|
||||
"etlua",
|
||||
"excel-formula",
|
||||
"factor",
|
||||
"false",
|
||||
"firestore-security-rules",
|
||||
"flow",
|
||||
"fortran",
|
||||
"fsharp",
|
||||
"ftl",
|
||||
"gap",
|
||||
"gcode",
|
||||
"gdscript",
|
||||
"gedcom",
|
||||
"gherkin",
|
||||
"git",
|
||||
"glsl",
|
||||
"gml",
|
||||
"gn",
|
||||
"go",
|
||||
"go-module",
|
||||
"graphql",
|
||||
"groovy",
|
||||
"haml",
|
||||
"handlebars",
|
||||
"haskell",
|
||||
"haxe",
|
||||
"hcl",
|
||||
"hlsl",
|
||||
"hoon",
|
||||
"hpkp",
|
||||
"hsts",
|
||||
"http",
|
||||
"ichigojam",
|
||||
"icon",
|
||||
"icu-message-format",
|
||||
"idris",
|
||||
"iecst",
|
||||
"ignore",
|
||||
"index",
|
||||
"inform7",
|
||||
"ini",
|
||||
"io",
|
||||
"j",
|
||||
"java",
|
||||
"javadoc",
|
||||
"javadoclike",
|
||||
"javascript",
|
||||
"javastacktrace",
|
||||
"jexl",
|
||||
"jolie",
|
||||
"jq",
|
||||
"js-extras",
|
||||
"js-templates",
|
||||
"jsdoc",
|
||||
"json",
|
||||
"json5",
|
||||
"jsonp",
|
||||
"jsstacktrace",
|
||||
"jsx",
|
||||
"julia",
|
||||
"keepalived",
|
||||
"keyman",
|
||||
"kotlin",
|
||||
"kumir",
|
||||
"kusto",
|
||||
"latex",
|
||||
"latte",
|
||||
"less",
|
||||
"lilypond",
|
||||
"liquid",
|
||||
"lisp",
|
||||
"livescript",
|
||||
"llvm",
|
||||
"log",
|
||||
"lolcode",
|
||||
"lua",
|
||||
"magma",
|
||||
"makefile",
|
||||
"markdown",
|
||||
"markup",
|
||||
"markup-templating",
|
||||
"matlab",
|
||||
"maxscript",
|
||||
"mel",
|
||||
"mermaid",
|
||||
"mizar",
|
||||
"mongodb",
|
||||
"monkey",
|
||||
"moonscript",
|
||||
"n1ql",
|
||||
"n4js",
|
||||
"nand2tetris-hdl",
|
||||
"naniscript",
|
||||
"nasm",
|
||||
"neon",
|
||||
"nevod",
|
||||
"nginx",
|
||||
"nim",
|
||||
"nix",
|
||||
"nsis",
|
||||
"objectivec",
|
||||
"ocaml",
|
||||
"opencl",
|
||||
"openqasm",
|
||||
"oz",
|
||||
"parigp",
|
||||
"parser",
|
||||
"pascal",
|
||||
"pascaligo",
|
||||
"pcaxis",
|
||||
"peoplecode",
|
||||
"perl",
|
||||
"php",
|
||||
"php-extras",
|
||||
"phpdoc",
|
||||
"plsql",
|
||||
"powerquery",
|
||||
"powershell",
|
||||
"processing",
|
||||
"prolog",
|
||||
"promql",
|
||||
"properties",
|
||||
"protobuf",
|
||||
"psl",
|
||||
"pug",
|
||||
"puppet",
|
||||
"pure",
|
||||
"purebasic",
|
||||
"purescript",
|
||||
"python",
|
||||
"q",
|
||||
"qml",
|
||||
"qore",
|
||||
"qsharp",
|
||||
"r",
|
||||
"racket",
|
||||
"reason",
|
||||
"regex",
|
||||
"rego",
|
||||
"renpy",
|
||||
"rest",
|
||||
"rip",
|
||||
"roboconf",
|
||||
"robotframework",
|
||||
"ruby",
|
||||
"rust",
|
||||
"sas",
|
||||
"sass",
|
||||
"scala",
|
||||
"scheme",
|
||||
"scss",
|
||||
"shell-session",
|
||||
"smali",
|
||||
"smalltalk",
|
||||
"smarty",
|
||||
"sml",
|
||||
"solidity",
|
||||
"solution-file",
|
||||
"soy",
|
||||
"sparql",
|
||||
"splunk-spl",
|
||||
"sqf",
|
||||
"sql",
|
||||
"squirrel",
|
||||
"stan",
|
||||
"stylus",
|
||||
"swift",
|
||||
"systemd",
|
||||
"t4-cs",
|
||||
"t4-templating",
|
||||
"t4-vb",
|
||||
"tap",
|
||||
"tcl",
|
||||
"textile",
|
||||
"toml",
|
||||
"tremor",
|
||||
"tsx",
|
||||
"tt2",
|
||||
"turtle",
|
||||
"twig",
|
||||
"typescript",
|
||||
"typoscript",
|
||||
"unrealscript",
|
||||
"uorazor",
|
||||
"uri",
|
||||
"v",
|
||||
"vala",
|
||||
"vbnet",
|
||||
"velocity",
|
||||
"verilog",
|
||||
"vhdl",
|
||||
"vim",
|
||||
"visual-basic",
|
||||
"warpscript",
|
||||
"wasm",
|
||||
"web-idl",
|
||||
"wiki",
|
||||
"wolfram",
|
||||
"wren",
|
||||
"xeora",
|
||||
"xml-doc",
|
||||
"xojo",
|
||||
"xquery",
|
||||
"yaml",
|
||||
"yang",
|
||||
"zig",
|
||||
]
|
||||
|
||||
|
||||
class ShikiCodeBlock(Component):
|
||||
library = "/utils/code"
|
||||
tag = "Code"
|
||||
alias = "ShikiCode"
|
||||
language: Var[LiteralCodeLanguage] = "python"
|
||||
theme: Var[str] = "min-dark"
|
||||
themes: Var[list[dict[str, Any]] | dict[str, str]]
|
||||
code: Var[str]
|
||||
transformers: Var[list] = []
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
*children,
|
||||
can_copy: Optional[bool] = False,
|
||||
copy_button: Optional[Union[bool, Component]] = None,
|
||||
**props,
|
||||
) -> Component:
|
||||
props["code"] = children[0]
|
||||
|
||||
if can_copy:
|
||||
code = children[0]
|
||||
copy_button = ( # type: ignore
|
||||
copy_button
|
||||
if copy_button is not None
|
||||
else Button.create(
|
||||
Icon.create(tag="copy"),
|
||||
on_click=set_clipboard(code),
|
||||
style=Style({"position": "absolute", "top": "0.5em", "right": "0"}),
|
||||
)
|
||||
)
|
||||
else:
|
||||
copy_button = None
|
||||
|
||||
transformers = props.pop("transformers", [])
|
||||
trans_final = []
|
||||
for transformer in transformers:
|
||||
if transformer in COMMON_TRANSFORMERS:
|
||||
trans_final.append(FunctionStringVar(f"{transformer}()"))
|
||||
else:
|
||||
trans_final.append(transformer)
|
||||
|
||||
if trans_final:
|
||||
props["transformers"] = trans_final
|
||||
|
||||
code_block = super().create(**props)
|
||||
|
||||
if copy_button:
|
||||
return Box.create(code_block, copy_button, position="relative")
|
||||
else:
|
||||
return code_block
|
||||
|
||||
def add_imports(self) -> ImportDict | list[ImportDict]:
|
||||
imports = defaultdict(list)
|
||||
for transformer in self.transformers._var_value:
|
||||
if (
|
||||
isinstance(transformer, FunctionStringVar)
|
||||
and (transformer_import_str := str(transformer).strip("()"))
|
||||
in COMMON_TRANSFORMERS
|
||||
):
|
||||
imports["@shikijs/transformers"].append(
|
||||
ImportVar(tag=transformer_import_str)
|
||||
)
|
||||
self.lib_dependencies.append(
|
||||
"@shikijs/transformers"
|
||||
) if "@shikijs/transformers" not in self.lib_dependencies else None
|
||||
|
||||
return imports
|
||||
|
||||
|
||||
code_block = ShikiCodeBlock.create
|
@ -2,6 +2,7 @@
|
||||
|
||||
from types import SimpleNamespace
|
||||
|
||||
from reflex.components.datadisplay.shiki_code_block import code_block as code_block
|
||||
from reflex.components.props import PropsBase
|
||||
from reflex.components.radix.themes.components.progress import progress as progress
|
||||
from reflex.components.sonner.toast import toast as toast
|
||||
@ -67,4 +68,5 @@ _x = ExperimentalNamespace(
|
||||
layout=layout,
|
||||
PropsBase=PropsBase,
|
||||
run_in_thread=run_in_thread,
|
||||
code_block=code_block,
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user