Forráskód Böngészése

Reduce Syntax highlighter footprint (#2037)

Elijah Ahianyo 1 éve
szülő
commit
ea22452b27

+ 20 - 3
reflex/.templates/jinja/web/pages/custom_component.js.jinja2

@@ -3,8 +3,25 @@
 {% block export %}
 {% for component in components %}
 
-export const {{component.name}} = memo(({ {{-component.props|join(", ")-}} }) => (
-  {{utils.render(component.render)}}
-))
+export const {{component.name}} = memo(({ {{-component.props|join(", ")-}} }) => {
+{% if component.name == "CodeBlock" and "language" in component.props %}
+    if (language) {
+      (async () => {
+        try {
+          const module = await import(`react-syntax-highlighter/dist/cjs/languages/prism/${language}`);
+          SyntaxHighlighter.registerLanguage(language, module.default);
+        } catch (error) {
+          console.error(`Error importing language module for ${language}:`, error);
+        }
+      })();
+
+
+    }
+{% endif %}
+    return(
+        {{utils.render(component.render)}}
+      )
+
+})
 {% endfor %}
 {% endblock %}

+ 0 - 1015
reflex/.templates/web/styles/code/prism.js

@@ -1,1015 +0,0 @@
-export const light = {
-  'code[class*="language-"]': {
-    background: "hsl(230, 1%, 98%)",
-    color: "hsl(230, 8%, 24%)",
-    fontFamily:
-      '"Fira Code", "Fira Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace',
-    direction: "ltr",
-    textAlign: "left",
-    whiteSpace: "pre",
-    wordSpacing: "normal",
-    wordBreak: "normal",
-    lineHeight: "1.5",
-    MozTabSize: "2",
-    OTabSize: "2",
-    tabSize: "2",
-    WebkitHyphens: "none",
-    MozHyphens: "none",
-    msHyphens: "none",
-    hyphens: "none",
-  },
-  'pre[class*="language-"]': {
-    background: "hsl(230, 1%, 98%)",
-    color: "hsl(230, 8%, 24%)",
-    fontFamily:
-      '"Fira Code", "Fira Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace',
-    direction: "ltr",
-    textAlign: "left",
-    whiteSpace: "pre",
-    wordSpacing: "normal",
-    wordBreak: "normal",
-    lineHeight: "1.5",
-    MozTabSize: "2",
-    OTabSize: "2",
-    tabSize: "2",
-    WebkitHyphens: "none",
-    MozHyphens: "none",
-    msHyphens: "none",
-    hyphens: "none",
-    padding: "1em",
-    margin: "0.5em 0",
-    overflow: "auto",
-    borderRadius: "0.3em",
-  },
-  'code[class*="language-"]::-moz-selection': {
-    background: "hsl(230, 1%, 90%)",
-    color: "inherit",
-  },
-  'code[class*="language-"] *::-moz-selection': {
-    background: "hsl(230, 1%, 90%)",
-    color: "inherit",
-  },
-  'pre[class*="language-"] *::-moz-selection': {
-    background: "hsl(230, 1%, 90%)",
-    color: "inherit",
-  },
-  'code[class*="language-"]::selection': {
-    background: "hsl(230, 1%, 90%)",
-    color: "inherit",
-  },
-  'code[class*="language-"] *::selection': {
-    background: "hsl(230, 1%, 90%)",
-    color: "inherit",
-  },
-  'pre[class*="language-"] *::selection': {
-    background: "hsl(230, 1%, 90%)",
-    color: "inherit",
-  },
-  ':not(pre) > code[class*="language-"]': {
-    padding: "0.2em 0.3em",
-    borderRadius: "0.3em",
-    whiteSpace: "normal",
-  },
-  comment: {
-    color: "hsl(230, 4%, 64%)",
-    fontStyle: "italic",
-  },
-  prolog: {
-    color: "hsl(230, 4%, 64%)",
-  },
-  cdata: {
-    color: "hsl(230, 4%, 64%)",
-  },
-  doctype: {
-    color: "hsl(230, 8%, 24%)",
-  },
-  punctuation: {
-    color: "hsl(230, 8%, 24%)",
-  },
-  entity: {
-    color: "hsl(230, 8%, 24%)",
-    cursor: "help",
-  },
-  "attr-name": {
-    color: "hsl(35, 99%, 36%)",
-  },
-  "class-name": {
-    color: "hsl(35, 99%, 36%)",
-  },
-  boolean: {
-    color: "hsl(35, 99%, 36%)",
-  },
-  constant: {
-    color: "hsl(35, 99%, 36%)",
-  },
-  number: {
-    color: "hsl(35, 99%, 36%)",
-  },
-  atrule: {
-    color: "hsl(35, 99%, 36%)",
-  },
-  keyword: {
-    color: "hsl(301, 63%, 40%)",
-  },
-  property: {
-    color: "hsl(5, 74%, 59%)",
-  },
-  tag: {
-    color: "hsl(5, 74%, 59%)",
-  },
-  symbol: {
-    color: "hsl(5, 74%, 59%)",
-  },
-  deleted: {
-    color: "hsl(5, 74%, 59%)",
-  },
-  important: {
-    color: "hsl(5, 74%, 59%)",
-  },
-  selector: {
-    color: "hsl(119, 34%, 47%)",
-  },
-  string: {
-    color: "hsl(119, 34%, 47%)",
-  },
-  char: {
-    color: "hsl(119, 34%, 47%)",
-  },
-  builtin: {
-    color: "hsl(119, 34%, 47%)",
-  },
-  inserted: {
-    color: "hsl(119, 34%, 47%)",
-  },
-  regex: {
-    color: "hsl(119, 34%, 47%)",
-  },
-  "attr-value": {
-    color: "hsl(119, 34%, 47%)",
-  },
-  "attr-value > .token.punctuation": {
-    color: "hsl(119, 34%, 47%)",
-  },
-  variable: {
-    color: "hsl(221, 87%, 60%)",
-  },
-  operator: {
-    color: "hsl(221, 87%, 60%)",
-  },
-  function: {
-    color: "hsl(221, 87%, 60%)",
-  },
-  url: {
-    color: "hsl(198, 99%, 37%)",
-  },
-  "attr-value > .token.punctuation.attr-equals": {
-    color: "hsl(230, 8%, 24%)",
-  },
-  "special-attr > .token.attr-value > .token.value.css": {
-    color: "hsl(230, 8%, 24%)",
-  },
-  ".language-css .token.selector": {
-    color: "hsl(5, 74%, 59%)",
-  },
-  ".language-css .token.property": {
-    color: "hsl(230, 8%, 24%)",
-  },
-  ".language-css .token.function": {
-    color: "hsl(198, 99%, 37%)",
-  },
-  ".language-css .token.url > .token.function": {
-    color: "hsl(198, 99%, 37%)",
-  },
-  ".language-css .token.url > .token.string.url": {
-    color: "hsl(119, 34%, 47%)",
-  },
-  ".language-css .token.important": {
-    color: "hsl(301, 63%, 40%)",
-  },
-  ".language-css .token.atrule .token.rule": {
-    color: "hsl(301, 63%, 40%)",
-  },
-  ".language-javascript .token.operator": {
-    color: "hsl(301, 63%, 40%)",
-  },
-  ".language-javascript .token.template-string > .token.interpolation > .token.interpolation-punctuation.punctuation":
-    {
-      color: "hsl(344, 84%, 43%)",
-    },
-  ".language-json .token.operator": {
-    color: "hsl(230, 8%, 24%)",
-  },
-  ".language-json .token.null.keyword": {
-    color: "hsl(35, 99%, 36%)",
-  },
-  ".language-markdown .token.url": {
-    color: "hsl(230, 8%, 24%)",
-  },
-  ".language-markdown .token.url > .token.operator": {
-    color: "hsl(230, 8%, 24%)",
-  },
-  ".language-markdown .token.url-reference.url > .token.string": {
-    color: "hsl(230, 8%, 24%)",
-  },
-  ".language-markdown .token.url > .token.content": {
-    color: "hsl(221, 87%, 60%)",
-  },
-  ".language-markdown .token.url > .token.url": {
-    color: "hsl(198, 99%, 37%)",
-  },
-  ".language-markdown .token.url-reference.url": {
-    color: "hsl(198, 99%, 37%)",
-  },
-  ".language-markdown .token.blockquote.punctuation": {
-    color: "hsl(230, 4%, 64%)",
-    fontStyle: "italic",
-  },
-  ".language-markdown .token.hr.punctuation": {
-    color: "hsl(230, 4%, 64%)",
-    fontStyle: "italic",
-  },
-  ".language-markdown .token.code-snippet": {
-    color: "hsl(119, 34%, 47%)",
-  },
-  ".language-markdown .token.bold .token.content": {
-    color: "hsl(35, 99%, 36%)",
-  },
-  ".language-markdown .token.italic .token.content": {
-    color: "hsl(301, 63%, 40%)",
-  },
-  ".language-markdown .token.strike .token.content": {
-    color: "hsl(5, 74%, 59%)",
-  },
-  ".language-markdown .token.strike .token.punctuation": {
-    color: "hsl(5, 74%, 59%)",
-  },
-  ".language-markdown .token.list.punctuation": {
-    color: "hsl(5, 74%, 59%)",
-  },
-  ".language-markdown .token.title.important > .token.punctuation": {
-    color: "hsl(5, 74%, 59%)",
-  },
-  bold: {
-    fontWeight: "bold",
-  },
-  italic: {
-    fontStyle: "italic",
-  },
-  namespace: {
-    Opacity: "0.8",
-  },
-  "token.tab:not(:empty):before": {
-    color: "hsla(230, 8%, 24%, 0.2)",
-  },
-  "token.cr:before": {
-    color: "hsla(230, 8%, 24%, 0.2)",
-  },
-  "token.lf:before": {
-    color: "hsla(230, 8%, 24%, 0.2)",
-  },
-  "token.space:before": {
-    color: "hsla(230, 8%, 24%, 0.2)",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item": {
-    marginRight: "0.4em",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item > button": {
-    background: "hsl(230, 1%, 90%)",
-    color: "hsl(230, 6%, 44%)",
-    padding: "0.1em 0.4em",
-    borderRadius: "0.3em",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item > a": {
-    background: "hsl(230, 1%, 90%)",
-    color: "hsl(230, 6%, 44%)",
-    padding: "0.1em 0.4em",
-    borderRadius: "0.3em",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item > span": {
-    background: "hsl(230, 1%, 90%)",
-    color: "hsl(230, 6%, 44%)",
-    padding: "0.1em 0.4em",
-    borderRadius: "0.3em",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:hover": {
-    background: "hsl(230, 1%, 78%)",
-    color: "hsl(230, 8%, 24%)",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:focus": {
-    background: "hsl(230, 1%, 78%)",
-    color: "hsl(230, 8%, 24%)",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:hover": {
-    background: "hsl(230, 1%, 78%)",
-    color: "hsl(230, 8%, 24%)",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:focus": {
-    background: "hsl(230, 1%, 78%)",
-    color: "hsl(230, 8%, 24%)",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:hover": {
-    background: "hsl(230, 1%, 78%)",
-    color: "hsl(230, 8%, 24%)",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:focus": {
-    background: "hsl(230, 1%, 78%)",
-    color: "hsl(230, 8%, 24%)",
-  },
-  ".line-highlight.line-highlight": {
-    background: "hsla(230, 8%, 24%, 0.05)",
-  },
-  ".line-highlight.line-highlight:before": {
-    background: "hsl(230, 1%, 90%)",
-    color: "hsl(230, 8%, 24%)",
-    padding: "0.1em 0.6em",
-    borderRadius: "0.3em",
-    boxShadow: "0 2px 0 0 rgba(0, 0, 0, 0.2)",
-  },
-  ".line-highlight.line-highlight[data-end]:after": {
-    background: "hsl(230, 1%, 90%)",
-    color: "hsl(230, 8%, 24%)",
-    padding: "0.1em 0.6em",
-    borderRadius: "0.3em",
-    boxShadow: "0 2px 0 0 rgba(0, 0, 0, 0.2)",
-  },
-  "pre[id].linkable-line-numbers.linkable-line-numbers span.line-numbers-rows > span:hover:before":
-    {
-      backgroundColor: "hsla(230, 8%, 24%, 0.05)",
-    },
-  ".line-numbers.line-numbers .line-numbers-rows": {
-    borderRightColor: "hsla(230, 8%, 24%, 0.2)",
-  },
-  ".command-line .command-line-prompt": {
-    borderRightColor: "hsla(230, 8%, 24%, 0.2)",
-  },
-  ".line-numbers .line-numbers-rows > span:before": {
-    color: "hsl(230, 1%, 62%)",
-  },
-  ".command-line .command-line-prompt > span:before": {
-    color: "hsl(230, 1%, 62%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-1": {
-    color: "hsl(5, 74%, 59%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-5": {
-    color: "hsl(5, 74%, 59%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-9": {
-    color: "hsl(5, 74%, 59%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-2": {
-    color: "hsl(119, 34%, 47%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-6": {
-    color: "hsl(119, 34%, 47%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-10": {
-    color: "hsl(119, 34%, 47%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-3": {
-    color: "hsl(221, 87%, 60%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-7": {
-    color: "hsl(221, 87%, 60%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-11": {
-    color: "hsl(221, 87%, 60%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-4": {
-    color: "hsl(301, 63%, 40%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-8": {
-    color: "hsl(301, 63%, 40%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-12": {
-    color: "hsl(301, 63%, 40%)",
-  },
-  "pre.diff-highlight > code .token.token.deleted:not(.prefix)": {
-    backgroundColor: "hsla(353, 100%, 66%, 0.15)",
-  },
-  "pre > code.diff-highlight .token.token.deleted:not(.prefix)": {
-    backgroundColor: "hsla(353, 100%, 66%, 0.15)",
-  },
-  "pre.diff-highlight > code .token.token.deleted:not(.prefix)::-moz-selection":
-    {
-      backgroundColor: "hsla(353, 95%, 66%, 0.25)",
-    },
-  "pre.diff-highlight > code .token.token.deleted:not(.prefix) *::-moz-selection":
-    {
-      backgroundColor: "hsla(353, 95%, 66%, 0.25)",
-    },
-  "pre > code.diff-highlight .token.token.deleted:not(.prefix)::-moz-selection":
-    {
-      backgroundColor: "hsla(353, 95%, 66%, 0.25)",
-    },
-  "pre > code.diff-highlight .token.token.deleted:not(.prefix) *::-moz-selection":
-    {
-      backgroundColor: "hsla(353, 95%, 66%, 0.25)",
-    },
-  "pre.diff-highlight > code .token.token.deleted:not(.prefix)::selection": {
-    backgroundColor: "hsla(353, 95%, 66%, 0.25)",
-  },
-  "pre.diff-highlight > code .token.token.deleted:not(.prefix) *::selection": {
-    backgroundColor: "hsla(353, 95%, 66%, 0.25)",
-  },
-  "pre > code.diff-highlight .token.token.deleted:not(.prefix)::selection": {
-    backgroundColor: "hsla(353, 95%, 66%, 0.25)",
-  },
-  "pre > code.diff-highlight .token.token.deleted:not(.prefix) *::selection": {
-    backgroundColor: "hsla(353, 95%, 66%, 0.25)",
-  },
-  "pre.diff-highlight > code .token.token.inserted:not(.prefix)": {
-    backgroundColor: "hsla(137, 100%, 55%, 0.15)",
-  },
-  "pre > code.diff-highlight .token.token.inserted:not(.prefix)": {
-    backgroundColor: "hsla(137, 100%, 55%, 0.15)",
-  },
-  "pre.diff-highlight > code .token.token.inserted:not(.prefix)::-moz-selection":
-    {
-      backgroundColor: "hsla(135, 73%, 55%, 0.25)",
-    },
-  "pre.diff-highlight > code .token.token.inserted:not(.prefix) *::-moz-selection":
-    {
-      backgroundColor: "hsla(135, 73%, 55%, 0.25)",
-    },
-  "pre > code.diff-highlight .token.token.inserted:not(.prefix)::-moz-selection":
-    {
-      backgroundColor: "hsla(135, 73%, 55%, 0.25)",
-    },
-  "pre > code.diff-highlight .token.token.inserted:not(.prefix) *::-moz-selection":
-    {
-      backgroundColor: "hsla(135, 73%, 55%, 0.25)",
-    },
-  "pre.diff-highlight > code .token.token.inserted:not(.prefix)::selection": {
-    backgroundColor: "hsla(135, 73%, 55%, 0.25)",
-  },
-  "pre.diff-highlight > code .token.token.inserted:not(.prefix) *::selection": {
-    backgroundColor: "hsla(135, 73%, 55%, 0.25)",
-  },
-  "pre > code.diff-highlight .token.token.inserted:not(.prefix)::selection": {
-    backgroundColor: "hsla(135, 73%, 55%, 0.25)",
-  },
-  "pre > code.diff-highlight .token.token.inserted:not(.prefix) *::selection": {
-    backgroundColor: "hsla(135, 73%, 55%, 0.25)",
-  },
-  ".prism-previewer.prism-previewer:before": {
-    borderColor: "hsl(0, 0, 95%)",
-  },
-  ".prism-previewer-gradient.prism-previewer-gradient div": {
-    borderColor: "hsl(0, 0, 95%)",
-    borderRadius: "0.3em",
-  },
-  ".prism-previewer-color.prism-previewer-color:before": {
-    borderRadius: "0.3em",
-  },
-  ".prism-previewer-easing.prism-previewer-easing:before": {
-    borderRadius: "0.3em",
-  },
-  ".prism-previewer.prism-previewer:after": {
-    borderTopColor: "hsl(0, 0, 95%)",
-  },
-  ".prism-previewer-flipped.prism-previewer-flipped.after": {
-    borderBottomColor: "hsl(0, 0, 95%)",
-  },
-  ".prism-previewer-angle.prism-previewer-angle:before": {
-    background: "hsl(0, 0%, 100%)",
-  },
-  ".prism-previewer-time.prism-previewer-time:before": {
-    background: "hsl(0, 0%, 100%)",
-  },
-  ".prism-previewer-easing.prism-previewer-easing": {
-    background: "hsl(0, 0%, 100%)",
-  },
-  ".prism-previewer-angle.prism-previewer-angle circle": {
-    stroke: "hsl(230, 8%, 24%)",
-    strokeOpacity: "1",
-  },
-  ".prism-previewer-time.prism-previewer-time circle": {
-    stroke: "hsl(230, 8%, 24%)",
-    strokeOpacity: "1",
-  },
-  ".prism-previewer-easing.prism-previewer-easing circle": {
-    stroke: "hsl(230, 8%, 24%)",
-    fill: "transparent",
-  },
-  ".prism-previewer-easing.prism-previewer-easing path": {
-    stroke: "hsl(230, 8%, 24%)",
-  },
-  ".prism-previewer-easing.prism-previewer-easing line": {
-    stroke: "hsl(230, 8%, 24%)",
-  },
-};
-
-export const dark = {
-  'code[class*="language-"]': {
-    background: "hsl(220, 13%, 18%)",
-    color: "hsl(220, 14%, 71%)",
-    textShadow: "0 1px rgba(0, 0, 0, 0.3)",
-    fontFamily:
-      '"Fira Code", "Fira Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace',
-    direction: "ltr",
-    textAlign: "left",
-    whiteSpace: "pre",
-    wordSpacing: "normal",
-    wordBreak: "normal",
-    lineHeight: "1.5",
-    MozTabSize: "2",
-    OTabSize: "2",
-    tabSize: "2",
-    WebkitHyphens: "none",
-    MozHyphens: "none",
-    msHyphens: "none",
-    hyphens: "none",
-  },
-  'pre[class*="language-"]': {
-    background: "hsl(220, 13%, 18%)",
-    color: "hsl(220, 14%, 71%)",
-    textShadow: "0 1px rgba(0, 0, 0, 0.3)",
-    fontFamily:
-      '"Fira Code", "Fira Mono", Menlo, Consolas, "DejaVu Sans Mono", monospace',
-    direction: "ltr",
-    textAlign: "left",
-    whiteSpace: "pre",
-    wordSpacing: "normal",
-    wordBreak: "normal",
-    lineHeight: "1.5",
-    MozTabSize: "2",
-    OTabSize: "2",
-    tabSize: "2",
-    WebkitHyphens: "none",
-    MozHyphens: "none",
-    msHyphens: "none",
-    hyphens: "none",
-    padding: "1em",
-    margin: "0.5em 0",
-    overflow: "auto",
-    borderRadius: "0.3em",
-  },
-  'code[class*="language-"]::-moz-selection': {
-    background: "hsl(220, 13%, 28%)",
-    color: "inherit",
-    textShadow: "none",
-  },
-  'code[class*="language-"] *::-moz-selection': {
-    background: "hsl(220, 13%, 28%)",
-    color: "inherit",
-    textShadow: "none",
-  },
-  'pre[class*="language-"] *::-moz-selection': {
-    background: "hsl(220, 13%, 28%)",
-    color: "inherit",
-    textShadow: "none",
-  },
-  'code[class*="language-"]::selection': {
-    background: "hsl(220, 13%, 28%)",
-    color: "inherit",
-    textShadow: "none",
-  },
-  'code[class*="language-"] *::selection': {
-    background: "hsl(220, 13%, 28%)",
-    color: "inherit",
-    textShadow: "none",
-  },
-  'pre[class*="language-"] *::selection': {
-    background: "hsl(220, 13%, 28%)",
-    color: "inherit",
-    textShadow: "none",
-  },
-  ':not(pre) > code[class*="language-"]': {
-    padding: "0.2em 0.3em",
-    borderRadius: "0.3em",
-    whiteSpace: "normal",
-  },
-  comment: {
-    color: "hsl(220, 10%, 40%)",
-    fontStyle: "italic",
-  },
-  prolog: {
-    color: "hsl(220, 10%, 40%)",
-  },
-  cdata: {
-    color: "hsl(220, 10%, 40%)",
-  },
-  doctype: {
-    color: "hsl(220, 14%, 71%)",
-  },
-  punctuation: {
-    color: "hsl(220, 14%, 71%)",
-  },
-  entity: {
-    color: "hsl(220, 14%, 71%)",
-    cursor: "help",
-  },
-  "attr-name": {
-    color: "hsl(29, 54%, 61%)",
-  },
-  "class-name": {
-    color: "hsl(29, 54%, 61%)",
-  },
-  boolean: {
-    color: "hsl(29, 54%, 61%)",
-  },
-  constant: {
-    color: "hsl(29, 54%, 61%)",
-  },
-  number: {
-    color: "hsl(29, 54%, 61%)",
-  },
-  atrule: {
-    color: "hsl(29, 54%, 61%)",
-  },
-  keyword: {
-    color: "hsl(286, 60%, 67%)",
-  },
-  property: {
-    color: "hsl(355, 65%, 65%)",
-  },
-  tag: {
-    color: "hsl(355, 65%, 65%)",
-  },
-  symbol: {
-    color: "hsl(355, 65%, 65%)",
-  },
-  deleted: {
-    color: "hsl(355, 65%, 65%)",
-  },
-  important: {
-    color: "hsl(355, 65%, 65%)",
-  },
-  selector: {
-    color: "hsl(95, 38%, 62%)",
-  },
-  string: {
-    color: "hsl(95, 38%, 62%)",
-  },
-  char: {
-    color: "hsl(95, 38%, 62%)",
-  },
-  builtin: {
-    color: "hsl(95, 38%, 62%)",
-  },
-  inserted: {
-    color: "hsl(95, 38%, 62%)",
-  },
-  regex: {
-    color: "hsl(95, 38%, 62%)",
-  },
-  "attr-value": {
-    color: "hsl(95, 38%, 62%)",
-  },
-  "attr-value > .token.punctuation": {
-    color: "hsl(95, 38%, 62%)",
-  },
-  variable: {
-    color: "hsl(207, 82%, 66%)",
-  },
-  operator: {
-    color: "hsl(207, 82%, 66%)",
-  },
-  function: {
-    color: "hsl(207, 82%, 66%)",
-  },
-  url: {
-    color: "hsl(187, 47%, 55%)",
-  },
-  "attr-value > .token.punctuation.attr-equals": {
-    color: "hsl(220, 14%, 71%)",
-  },
-  "special-attr > .token.attr-value > .token.value.css": {
-    color: "hsl(220, 14%, 71%)",
-  },
-  ".language-css .token.selector": {
-    color: "hsl(355, 65%, 65%)",
-  },
-  ".language-css .token.property": {
-    color: "hsl(220, 14%, 71%)",
-  },
-  ".language-css .token.function": {
-    color: "hsl(187, 47%, 55%)",
-  },
-  ".language-css .token.url > .token.function": {
-    color: "hsl(187, 47%, 55%)",
-  },
-  ".language-css .token.url > .token.string.url": {
-    color: "hsl(95, 38%, 62%)",
-  },
-  ".language-css .token.important": {
-    color: "hsl(286, 60%, 67%)",
-  },
-  ".language-css .token.atrule .token.rule": {
-    color: "hsl(286, 60%, 67%)",
-  },
-  ".language-javascript .token.operator": {
-    color: "hsl(286, 60%, 67%)",
-  },
-  ".language-javascript .token.template-string > .token.interpolation > .token.interpolation-punctuation.punctuation":
-    {
-      color: "hsl(5, 48%, 51%)",
-    },
-  ".language-json .token.operator": {
-    color: "hsl(220, 14%, 71%)",
-  },
-  ".language-json .token.null.keyword": {
-    color: "hsl(29, 54%, 61%)",
-  },
-  ".language-markdown .token.url": {
-    color: "hsl(220, 14%, 71%)",
-  },
-  ".language-markdown .token.url > .token.operator": {
-    color: "hsl(220, 14%, 71%)",
-  },
-  ".language-markdown .token.url-reference.url > .token.string": {
-    color: "hsl(220, 14%, 71%)",
-  },
-  ".language-markdown .token.url > .token.content": {
-    color: "hsl(207, 82%, 66%)",
-  },
-  ".language-markdown .token.url > .token.url": {
-    color: "hsl(187, 47%, 55%)",
-  },
-  ".language-markdown .token.url-reference.url": {
-    color: "hsl(187, 47%, 55%)",
-  },
-  ".language-markdown .token.blockquote.punctuation": {
-    color: "hsl(220, 10%, 40%)",
-    fontStyle: "italic",
-  },
-  ".language-markdown .token.hr.punctuation": {
-    color: "hsl(220, 10%, 40%)",
-    fontStyle: "italic",
-  },
-  ".language-markdown .token.code-snippet": {
-    color: "hsl(95, 38%, 62%)",
-  },
-  ".language-markdown .token.bold .token.content": {
-    color: "hsl(29, 54%, 61%)",
-  },
-  ".language-markdown .token.italic .token.content": {
-    color: "hsl(286, 60%, 67%)",
-  },
-  ".language-markdown .token.strike .token.content": {
-    color: "hsl(355, 65%, 65%)",
-  },
-  ".language-markdown .token.strike .token.punctuation": {
-    color: "hsl(355, 65%, 65%)",
-  },
-  ".language-markdown .token.list.punctuation": {
-    color: "hsl(355, 65%, 65%)",
-  },
-  ".language-markdown .token.title.important > .token.punctuation": {
-    color: "hsl(355, 65%, 65%)",
-  },
-  bold: {
-    fontWeight: "bold",
-  },
-  italic: {
-    fontStyle: "italic",
-  },
-  namespace: {
-    Opacity: "0.8",
-  },
-  "token.tab:not(:empty):before": {
-    color: "hsla(220, 14%, 71%, 0.15)",
-    textShadow: "none",
-  },
-  "token.cr:before": {
-    color: "hsla(220, 14%, 71%, 0.15)",
-    textShadow: "none",
-  },
-  "token.lf:before": {
-    color: "hsla(220, 14%, 71%, 0.15)",
-    textShadow: "none",
-  },
-  "token.space:before": {
-    color: "hsla(220, 14%, 71%, 0.15)",
-    textShadow: "none",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item": {
-    marginRight: "0.4em",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item > button": {
-    background: "hsl(220, 13%, 26%)",
-    color: "hsl(220, 9%, 55%)",
-    padding: "0.1em 0.4em",
-    borderRadius: "0.3em",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item > a": {
-    background: "hsl(220, 13%, 26%)",
-    color: "hsl(220, 9%, 55%)",
-    padding: "0.1em 0.4em",
-    borderRadius: "0.3em",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item > span": {
-    background: "hsl(220, 13%, 26%)",
-    color: "hsl(220, 9%, 55%)",
-    padding: "0.1em 0.4em",
-    borderRadius: "0.3em",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:hover": {
-    background: "hsl(220, 13%, 28%)",
-    color: "hsl(220, 14%, 71%)",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:focus": {
-    background: "hsl(220, 13%, 28%)",
-    color: "hsl(220, 14%, 71%)",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:hover": {
-    background: "hsl(220, 13%, 28%)",
-    color: "hsl(220, 14%, 71%)",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:focus": {
-    background: "hsl(220, 13%, 28%)",
-    color: "hsl(220, 14%, 71%)",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:hover": {
-    background: "hsl(220, 13%, 28%)",
-    color: "hsl(220, 14%, 71%)",
-  },
-  "div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:focus": {
-    background: "hsl(220, 13%, 28%)",
-    color: "hsl(220, 14%, 71%)",
-  },
-  ".line-highlight.line-highlight": {
-    background: "hsla(220, 100%, 80%, 0.04)",
-  },
-  ".line-highlight.line-highlight:before": {
-    background: "hsl(220, 13%, 26%)",
-    color: "hsl(220, 14%, 71%)",
-    padding: "0.1em 0.6em",
-    borderRadius: "0.3em",
-    boxShadow: "0 2px 0 0 rgba(0, 0, 0, 0.2)",
-  },
-  ".line-highlight.line-highlight[data-end]:after": {
-    background: "hsl(220, 13%, 26%)",
-    color: "hsl(220, 14%, 71%)",
-    padding: "0.1em 0.6em",
-    borderRadius: "0.3em",
-    boxShadow: "0 2px 0 0 rgba(0, 0, 0, 0.2)",
-  },
-  "pre[id].linkable-line-numbers.linkable-line-numbers span.line-numbers-rows > span:hover:before":
-    {
-      backgroundColor: "hsla(220, 100%, 80%, 0.04)",
-    },
-  ".line-numbers.line-numbers .line-numbers-rows": {
-    borderRightColor: "hsla(220, 14%, 71%, 0.15)",
-  },
-  ".command-line .command-line-prompt": {
-    borderRightColor: "hsla(220, 14%, 71%, 0.15)",
-  },
-  ".line-numbers .line-numbers-rows > span:before": {
-    color: "hsl(220, 14%, 45%)",
-  },
-  ".command-line .command-line-prompt > span:before": {
-    color: "hsl(220, 14%, 45%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-1": {
-    color: "hsl(355, 65%, 65%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-5": {
-    color: "hsl(355, 65%, 65%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-9": {
-    color: "hsl(355, 65%, 65%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-2": {
-    color: "hsl(95, 38%, 62%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-6": {
-    color: "hsl(95, 38%, 62%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-10": {
-    color: "hsl(95, 38%, 62%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-3": {
-    color: "hsl(207, 82%, 66%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-7": {
-    color: "hsl(207, 82%, 66%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-11": {
-    color: "hsl(207, 82%, 66%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-4": {
-    color: "hsl(286, 60%, 67%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-8": {
-    color: "hsl(286, 60%, 67%)",
-  },
-  ".rainbow-braces .token.token.punctuation.brace-level-12": {
-    color: "hsl(286, 60%, 67%)",
-  },
-  "pre.diff-highlight > code .token.token.deleted:not(.prefix)": {
-    backgroundColor: "hsla(353, 100%, 66%, 0.15)",
-  },
-  "pre > code.diff-highlight .token.token.deleted:not(.prefix)": {
-    backgroundColor: "hsla(353, 100%, 66%, 0.15)",
-  },
-  "pre.diff-highlight > code .token.token.deleted:not(.prefix)::-moz-selection":
-    {
-      backgroundColor: "hsla(353, 95%, 66%, 0.25)",
-    },
-  "pre.diff-highlight > code .token.token.deleted:not(.prefix) *::-moz-selection":
-    {
-      backgroundColor: "hsla(353, 95%, 66%, 0.25)",
-    },
-  "pre > code.diff-highlight .token.token.deleted:not(.prefix)::-moz-selection":
-    {
-      backgroundColor: "hsla(353, 95%, 66%, 0.25)",
-    },
-  "pre > code.diff-highlight .token.token.deleted:not(.prefix) *::-moz-selection":
-    {
-      backgroundColor: "hsla(353, 95%, 66%, 0.25)",
-    },
-  "pre.diff-highlight > code .token.token.deleted:not(.prefix)::selection": {
-    backgroundColor: "hsla(353, 95%, 66%, 0.25)",
-  },
-  "pre.diff-highlight > code .token.token.deleted:not(.prefix) *::selection": {
-    backgroundColor: "hsla(353, 95%, 66%, 0.25)",
-  },
-  "pre > code.diff-highlight .token.token.deleted:not(.prefix)::selection": {
-    backgroundColor: "hsla(353, 95%, 66%, 0.25)",
-  },
-  "pre > code.diff-highlight .token.token.deleted:not(.prefix) *::selection": {
-    backgroundColor: "hsla(353, 95%, 66%, 0.25)",
-  },
-  "pre.diff-highlight > code .token.token.inserted:not(.prefix)": {
-    backgroundColor: "hsla(137, 100%, 55%, 0.15)",
-  },
-  "pre > code.diff-highlight .token.token.inserted:not(.prefix)": {
-    backgroundColor: "hsla(137, 100%, 55%, 0.15)",
-  },
-  "pre.diff-highlight > code .token.token.inserted:not(.prefix)::-moz-selection":
-    {
-      backgroundColor: "hsla(135, 73%, 55%, 0.25)",
-    },
-  "pre.diff-highlight > code .token.token.inserted:not(.prefix) *::-moz-selection":
-    {
-      backgroundColor: "hsla(135, 73%, 55%, 0.25)",
-    },
-  "pre > code.diff-highlight .token.token.inserted:not(.prefix)::-moz-selection":
-    {
-      backgroundColor: "hsla(135, 73%, 55%, 0.25)",
-    },
-  "pre > code.diff-highlight .token.token.inserted:not(.prefix) *::-moz-selection":
-    {
-      backgroundColor: "hsla(135, 73%, 55%, 0.25)",
-    },
-  "pre.diff-highlight > code .token.token.inserted:not(.prefix)::selection": {
-    backgroundColor: "hsla(135, 73%, 55%, 0.25)",
-  },
-  "pre.diff-highlight > code .token.token.inserted:not(.prefix) *::selection": {
-    backgroundColor: "hsla(135, 73%, 55%, 0.25)",
-  },
-  "pre > code.diff-highlight .token.token.inserted:not(.prefix)::selection": {
-    backgroundColor: "hsla(135, 73%, 55%, 0.25)",
-  },
-  "pre > code.diff-highlight .token.token.inserted:not(.prefix) *::selection": {
-    backgroundColor: "hsla(135, 73%, 55%, 0.25)",
-  },
-  ".prism-previewer.prism-previewer:before": {
-    borderColor: "hsl(224, 13%, 17%)",
-  },
-  ".prism-previewer-gradient.prism-previewer-gradient div": {
-    borderColor: "hsl(224, 13%, 17%)",
-    borderRadius: "0.3em",
-  },
-  ".prism-previewer-color.prism-previewer-color:before": {
-    borderRadius: "0.3em",
-  },
-  ".prism-previewer-easing.prism-previewer-easing:before": {
-    borderRadius: "0.3em",
-  },
-  ".prism-previewer.prism-previewer:after": {
-    borderTopColor: "hsl(224, 13%, 17%)",
-  },
-  ".prism-previewer-flipped.prism-previewer-flipped.after": {
-    borderBottomColor: "hsl(224, 13%, 17%)",
-  },
-  ".prism-previewer-angle.prism-previewer-angle:before": {
-    background: "hsl(219, 13%, 22%)",
-  },
-  ".prism-previewer-time.prism-previewer-time:before": {
-    background: "hsl(219, 13%, 22%)",
-  },
-  ".prism-previewer-easing.prism-previewer-easing": {
-    background: "hsl(219, 13%, 22%)",
-  },
-  ".prism-previewer-angle.prism-previewer-angle circle": {
-    stroke: "hsl(220, 14%, 71%)",
-    strokeOpacity: "1",
-  },
-  ".prism-previewer-time.prism-previewer-time circle": {
-    stroke: "hsl(220, 14%, 71%)",
-    strokeOpacity: "1",
-  },
-  ".prism-previewer-easing.prism-previewer-easing circle": {
-    stroke: "hsl(220, 14%, 71%)",
-    fill: "transparent",
-  },
-  ".prism-previewer-easing.prism-previewer-easing path": {
-    stroke: "hsl(220, 14%, 71%)",
-  },
-  ".prism-previewer-easing.prism-previewer-easing line": {
-    stroke: "hsl(220, 14%, 71%)",
-  },
-};

+ 2 - 0
reflex/components/datadisplay/__init__.py

@@ -2,6 +2,8 @@
 
 from .badge import Badge
 from .code import Code, CodeBlock
+from .code import LiteralCodeBlockTheme as LiteralCodeBlockTheme
+from .code import LiteralCodeLanguage as LiteralCodeLanguage
 from .dataeditor import DataEditor, DataEditorTheme
 from .datatable import DataTable
 from .divider import Divider

+ 388 - 14
reflex/components/datadisplay/code.py

@@ -1,19 +1,349 @@
 """A code component."""
 
-from typing import Dict, Optional, Union
+from typing import Dict, Literal, Optional, Union
 
 from reflex.components.component import Component
 from reflex.components.forms import Button
 from reflex.components.layout import Box
-from reflex.components.libs.chakra import ChakraComponent, LiteralTheme
+from reflex.components.libs.chakra import (
+    ChakraComponent,
+)
 from reflex.components.media import Icon
 from reflex.event import set_clipboard
 from reflex.style import Style
-from reflex.utils import imports
+from reflex.utils import format, imports
 from reflex.vars import ImportVar, Var
 
-# Path to the prism styles.
-PRISM_STYLES_PATH: str = "/styles/code/prism"
+LiteralCodeBlockTheme = Literal[
+    "a11y-dark",
+    "atom-dark",
+    "cb",
+    "coldark-cold",
+    "coldark-dark",
+    "coy",
+    "coy-without-shadows",
+    "darcula",
+    "dark",
+    "dracula",
+    "duotone-dark",
+    "duotone-earth",
+    "duotone-forest",
+    "duotone-light",
+    "duotone-sea",
+    "duotone-space",
+    "funky",
+    "ghcolors",
+    "gruvbox-dark",
+    "gruvbox-light",
+    "holi-theme",
+    "hopscotch",
+    "light",  # not present in react-syntax-highlighter styles
+    "lucario",
+    "material-dark",
+    "material-light",
+    "material-oceanic",
+    "night-owl",
+    "nord",
+    "okaidia",
+    "one-dark",
+    "one-light",
+    "pojoaque",
+    "prism",
+    "shades-of-purple",
+    "solarized-dark-atom",
+    "solarizedlight",
+    "synthwave84",
+    "tomorrow",
+    "twilight",
+    "vs",
+    "vs-dark",
+    "vsc-dark-plus",
+    "xonokai",
+    "z-touch",
+]
+
+
+LiteralCodeLanguage = Literal[
+    "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 CodeBlock(Component):
@@ -21,13 +351,15 @@ class CodeBlock(Component):
 
     library = "react-syntax-highlighter@15.5.0"
 
-    tag = "Prism"
+    tag = "PrismAsyncLight"
+
+    alias = "SyntaxHighlighter"
 
     # The theme to use ("light" or "dark").
-    theme: Var[LiteralTheme]
+    theme: Var[LiteralCodeBlockTheme] = "one-light"  # type: ignore
 
     # The language to use.
-    language: Var[str]
+    language: Var[LiteralCodeLanguage] = "python"  # type: ignore
 
     # If this is enabled line numbers will be shown next to the code block.
     show_line_numbers: Var[bool]
@@ -46,13 +378,43 @@ class CodeBlock(Component):
 
     def _get_imports(self) -> imports.ImportDict:
         merged_imports = super()._get_imports()
-        if self.theme is not None:
+        merged_imports = imports.merge_imports(
+            merged_imports,
+            {
+                f"react-syntax-highlighter/dist/cjs/styles/prism/{self.theme._var_name}": {
+                    ImportVar(
+                        tag=format.to_camel_case(self.theme._var_name),
+                        is_default=True,
+                        install=False,
+                    )
+                }
+            },
+        )
+        if (
+            self.language is not None
+            and self.language._var_name in LiteralCodeLanguage.__args__  # type: ignore
+        ):
             merged_imports = imports.merge_imports(
                 merged_imports,
-                {PRISM_STYLES_PATH: {ImportVar(tag=self.theme._var_name)}},
+                {
+                    f"react-syntax-highlighter/dist/cjs/languages/prism/{self.language._var_name}": {
+                        ImportVar(
+                            tag=format.to_camel_case(self.language._var_name),
+                            is_default=True,
+                            install=False,
+                        )
+                    }
+                },
             )
         return merged_imports
 
+    def _get_custom_code(self) -> Optional[str]:
+        if (
+            self.language is not None
+            and self.language._var_name in LiteralCodeLanguage.__args__  # type: ignore
+        ):
+            return f"{self.alias}.registerLanguage('{self.language._var_name}', {format.to_camel_case(self.language._var_name)})"
+
     @classmethod
     def create(
         cls,
@@ -75,6 +437,17 @@ class CodeBlock(Component):
         # This component handles style in a special prop.
         custom_style = props.pop("custom_style", {})
 
+        # react-syntax-highlighter doesnt have an explicit "light" or "dark" theme so we use one-light and one-dark
+        # themes respectively to ensure code compatibility.
+        if "theme" in props:
+            props["theme"] = (
+                "one-light"
+                if props["theme"] == "light"
+                else "one-dark"
+                if props["theme"] == "dark"
+                else props["theme"]
+            )
+
         if can_copy:
             code = children[0]
             copy_button = (  # type: ignore
@@ -112,10 +485,11 @@ class CodeBlock(Component):
 
     def _render(self):
         out = super()._render()
-        if self.theme is not None:
-            out.add_props(
-                style=Var.create(self.theme._var_name, _var_is_local=False)
-            ).remove_props("theme")
+        out.add_props(
+            style=Var.create(
+                format.to_camel_case(self.theme._var_name), _var_is_local=False
+            )
+        ).remove_props("theme")
         return out
 
 

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1076 - 7
reflex/components/datadisplay/code.pyi


+ 2 - 0
reflex/components/libs/chakra.py

@@ -122,6 +122,8 @@ LiteralColorScheme = Literal[
 LiteralVariant = Literal["solid", "subtle", "outline"]
 LiteralDividerVariant = Literal["solid", "dashed"]
 LiteralTheme = Literal["light", "dark"]
+
+
 LiteralTagColorScheme = Literal[
     "gray",
     "red",

+ 323 - 24
reflex/components/libs/chakra.pyi

@@ -1,14 +1,330 @@
-"""Stub file for chakra.py"""
+"""Stub file for reflex/components/libs/chakra.py"""
 # ------------------- DO NOT EDIT ----------------------
 # This file was generated by `scripts/pyi_generator.py`!
 # ------------------------------------------------------
 
-from typing import Literal, Optional, Union, overload
-from reflex.components.component import Component
+from typing import Optional, Literal, Any, overload, List, Union, Dict
 from reflex.vars import Var, BaseVar, ComputedVar
-from reflex.event import EventHandler, EventChain, EventSpec
+from reflex.event import EventChain, EventHandler, EventSpec
+from reflex.style import Style
+from typing import List, Literal
+from reflex.components.component import Component
+from reflex.utils import imports
+from reflex.vars import ImportVar, Var
+
+class ChakraComponent(Component):
+    ...
+
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, str]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "ChakraComponent":
+        """Create the component.
+
+        Args:
+            *children: The children of the component.
+            style: The style of the component.
+            key: A unique key for the component.
+            id: The id for the component.
+            class_name: The class name for the component.
+            autofocus: Whether the component should take the focus once the page is loaded
+            custom_attrs: custom attribute
+            **props: The props of the component.
+
+        Returns:
+            The component.
+
+        Raises:
+            TypeError: If an invalid child is passed.
+        """
+        ...
+
+class Global(Component):
+    ...
+
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        styles: Optional[Union[Var[str], str]] = None,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, str]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "Global":
+        """Create the component.
+
+        Args:
+            *children: The children of the component.
+            style: The style of the component.
+            key: A unique key for the component.
+            id: The id for the component.
+            class_name: The class name for the component.
+            autofocus: Whether the component should take the focus once the page is loaded
+            custom_attrs: custom attribute
+            **props: The props of the component.
+
+        Returns:
+            The component.
+
+        Raises:
+            TypeError: If an invalid child is passed.
+        """
+        ...
+
+class ChakraProvider(ChakraComponent):
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        theme: Optional[Union[Var[str], str]] = None,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, str]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "ChakraProvider":
+        """Create a new ChakraProvider component.
+
+        Returns:
+            A new ChakraProvider component.
+        """
+        ...
+
+class ChakraColorModeProvider(Component):
+    ...
+
+    @overload
+    @classmethod
+    def create(  # type: ignore
+        cls,
+        *children,
+        style: Optional[Style] = None,
+        key: Optional[Any] = None,
+        id: Optional[Any] = None,
+        class_name: Optional[Any] = None,
+        autofocus: Optional[bool] = None,
+        custom_attrs: Optional[Dict[str, str]] = None,
+        on_blur: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_click: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_context_menu: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_double_click: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_focus: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mount: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_down: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_enter: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_leave: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_move: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_out: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_over: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_mouse_up: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_scroll: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        on_unmount: Optional[
+            Union[EventHandler, EventSpec, List, function, BaseVar]
+        ] = None,
+        **props
+    ) -> "ChakraColorModeProvider":
+        """Create the component.
+
+        Args:
+            *children: The children of the component.
+            style: The style of the component.
+            key: A unique key for the component.
+            id: The id for the component.
+            class_name: The class name for the component.
+            autofocus: Whether the component should take the focus once the page is loaded
+            custom_attrs: custom attribute
+            **props: The props of the component.
+
+        Returns:
+            The component.
+
+        Raises:
+            TypeError: If an invalid child is passed.
+        """
+        ...
 
 LiteralColorScheme = Literal[
+    "none",
     "gray",
     "red",
     "orange",
@@ -32,6 +348,7 @@ LiteralColorScheme = Literal[
 LiteralVariant = Literal["solid", "subtle", "outline"]
 LiteralDividerVariant = Literal["solid", "dashed"]
 LiteralTheme = Literal["light", "dark"]
+
 LiteralTagColorScheme = Literal[
     "gray",
     "red",
@@ -94,8 +411,8 @@ LiteralCardVariant = Literal["outline", "filled", "elevated", "unstyled"]
 LiteralStackDirection = Literal["row", "column"]
 LiteralImageLoading = Literal["eager", "lazy"]
 LiteralTagSize = Literal["sm", "md", "lg"]
-LiteralSpinnerSize = Literal[Literal[LiteralTagSize], "xs"]
-LiteralAvatarSize = Literal[Literal[LiteralTagSize], "xs", "2xl", "full", "2xs"]
+LiteralSpinnerSize = Literal[Literal[LiteralTagSize], "xs", "xl"]
+LiteralAvatarSize = Literal[Literal[LiteralTagSize], "xl", "xs", "2xl", "full", "2xs"]
 LiteralButtonSize = Literal["sm", "md", "lg", "xs"]
 # Applies to AlertDialog and Modal
 LiteralAlertDialogSize = Literal[
@@ -108,21 +425,3 @@ LiteralMenuOption = Literal["checkbox", "radio"]
 LiteralPopOverTrigger = Literal["click", "hover"]
 
 LiteralHeadingSize = Literal["lg", "md", "sm", "xs", "xl", "2xl", "3xl", "4xl"]
-
-class ChakraComponent(Component):
-    @overload
-    @classmethod
-    def create(cls, *children, on_blur: Optional[Union[EventHandler, EventSpec, List, function, BaseVar]] = None, on_click: Optional[Union[EventHandler, EventSpec, List, function, BaseVar]] = None, on_context_menu: Optional[Union[EventHandler, EventSpec, List, function, BaseVar]] = None, on_double_click: Optional[Union[EventHandler, EventSpec, List, function, BaseVar]] = None, on_focus: Optional[Union[EventHandler, EventSpec, List, function, BaseVar]] = None, on_mount: Optional[Union[EventHandler, EventSpec, List, function, BaseVar]] = None, on_mouse_down: Optional[Union[EventHandler, EventSpec, List, function, BaseVar]] = None, on_mouse_enter: Optional[Union[EventHandler, EventSpec, List, function, BaseVar]] = None, on_mouse_leave: Optional[Union[EventHandler, EventSpec, List, function, BaseVar]] = None, on_mouse_move: Optional[Union[EventHandler, EventSpec, List, function, BaseVar]] = None, on_mouse_out: Optional[Union[EventHandler, EventSpec, List, function, BaseVar]] = None, on_mouse_over: Optional[Union[EventHandler, EventSpec, List, function, BaseVar]] = None, on_mouse_up: Optional[Union[EventHandler, EventSpec, List, function, BaseVar]] = None, on_scroll: Optional[Union[EventHandler, EventSpec, List, function, BaseVar]] = None, on_unmount: Optional[Union[EventHandler, EventSpec, List, function, BaseVar]] = None, **props) -> "ChakraComponent":  # type: ignore
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            **props: The props of the component.
-
-        Returns:
-            The component.
-
-        Raises:
-            TypeError: If an invalid child is passed.
-        """
-        ...

+ 10 - 0
reflex/components/typography/markdown.py

@@ -240,6 +240,16 @@ class Markdown(Component):
         ] = f"""{{({{inline, className, {_CHILDREN._var_name}, {_PROPS._var_name}}}) => {{
     const match = (className || '').match(/language-(?<lang>.*)/);
     const language = match ? match[1] : '';
+    if (language) {{
+    (async () => {{
+      try {{
+        const module = await import(`react-syntax-highlighter/dist/cjs/languages/prism/${{language}}`);
+        SyntaxHighlighter.registerLanguage(language, module.default);
+      }} catch (error) {{
+        console.error(`Error importing language module for ${{language}}:`, error);
+      }}
+    }})();
+  }}
     return inline ? (
         {self.format_component("code")}
     ) : (

+ 3 - 8
reflex/utils/format.py

@@ -137,14 +137,9 @@ def to_camel_case(text: str) -> str:
     Returns:
         The camel case string.
     """
-    if "_" not in text:
-        return text
-    camel = "".join(
-        word.capitalize() if i > 0 else word.lower()
-        for i, word in enumerate(text.lstrip("_").split("_"))
-    )
-    prefix = "_" if text.startswith("_") else ""
-    return prefix + camel
+    words = re.split("[_-]", text)
+    # Capitalize the first letter of each word except the first one
+    return words[0] + "".join(x.capitalize() for x in words[1:])
 
 
 def to_title_case(text: str) -> str:

+ 31 - 0
tests/components/datadisplay/test_code.py

@@ -0,0 +1,31 @@
+import pytest
+
+from reflex.components.datadisplay.code import CodeBlock
+
+
+@pytest.mark.parametrize(
+    "theme, expected", [("light", "one-light"), ("dark", "one-dark")]
+)
+def test_code_light_dark_theme(theme, expected):
+    code_block = CodeBlock.create(theme=theme)
+
+    assert code_block.theme._var_name == expected  # type: ignore
+
+
+def generate_custom_code(language, expected_case):
+    return f"SyntaxHighlighter.registerLanguage('{language}', {expected_case})"
+
+
+@pytest.mark.parametrize(
+    "language, expected_case",
+    [
+        ("python", "python"),
+        ("firestore-security-rules", "firestoreSecurityRules"),
+        ("typescript", "typescript"),
+    ],
+)
+def test_get_custom_code(language, expected_case):
+    code_block = CodeBlock.create(language=language)
+    assert code_block._get_custom_code() == generate_custom_code(
+        language, expected_case
+    )

+ 3 - 0
tests/utils/test_format.py

@@ -139,6 +139,9 @@ def test_to_snake_case(input: str, output: str):
         ("Hello", "Hello"),
         ("snake_case", "snakeCase"),
         ("snake_case_two", "snakeCaseTwo"),
+        ("kebab-case", "kebabCase"),
+        ("kebab-case-two", "kebabCaseTwo"),
+        ("snake_kebab-case", "snakeKebabCase"),
     ],
 )
 def test_to_camel_case(input: str, output: str):

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott