浏览代码

Add style for code blocks. (#32)

* Rename github actions file
* Update custom code
* Add theme for code blocks
Nikhil Rao 2 年之前
父节点
当前提交
dd26dd044b

+ 1 - 1
.github/workflows/python-checks.yml → .github/workflows/build.yml

@@ -1,4 +1,4 @@
-name: Python application
+name: build
 
 on:
   push:

+ 1 - 1
README.md

@@ -5,7 +5,7 @@
 **Build performant, customizable web apps in minutes just using Python.**
 
 [![PyPI version](https://badge.fury.io/py/pynecone-io.svg)](https://badge.fury.io/py/pynecone-io)
-![tests](https://github.com/pynecone-io/pynecone/actions/workflows/python-checks.yml/badge.svg)
+![tests](https://github.com/pynecone-io/pynecone/actions/workflows/build.yml/badge.svg)
 ![versions](https://img.shields.io/pypi/pyversions/pynecone-io.svg)
 [![License](https://img.shields.io/badge/License-Apache_2.0-yellowgreen.svg)](https://opensource.org/licenses/Apache-2.0)  
 

+ 992 - 0
pynecone/.templates/web/styles/code/prism.js

@@ -0,0 +1,992 @@
+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%)"
+    }
+}

+ 1 - 1
pynecone/compiler/compiler.py

@@ -60,7 +60,7 @@ def compile_component(component: Component, state: Type[State]) -> str:
     # Compile the code to render the component.
     return templates.COMPONENT(
         imports=utils.compile_imports(imports),
-        custom_code=component.get_custom_code(),
+        custom_code=templates.join(component.get_custom_code()),
         constants=utils.compile_constants(),
         state=utils.compile_state(state),
         events=utils.compile_events(state),

+ 2 - 2
pynecone/compiler/utils.py

@@ -9,15 +9,15 @@ from pynecone import constants, utils
 from pynecone.compiler import templates
 from pynecone.components.base import (
     Body,
+    Description,
     DocumentHead,
     Head,
     Html,
+    Image,
     Link,
     Main,
     Script,
     Title,
-    Description,
-    Image,
 )
 from pynecone.components.component import ImportDict
 from pynecone.state import State

+ 1 - 1
pynecone/components/base/__init__.py

@@ -4,4 +4,4 @@ from .body import Body
 from .document import DocumentHead, Html, Main, Script
 from .head import Head
 from .link import Link
-from .meta import Title, Description, Image
+from .meta import Description, Image, Title

+ 2 - 1
pynecone/components/base/meta.py

@@ -1,9 +1,10 @@
 """Display the title of the current page."""
 
+from typing import Optional
+
 from pynecone.components.base.bare import Bare
 from pynecone.components.component import Component
 from pynecone.components.tags import Tag
-from typing import Optional
 
 
 class Title(Component):

+ 15 - 7
pynecone/components/component.py

@@ -321,25 +321,33 @@ class Component(Base, ABC):
             )
         )
 
-    def _get_custom_code(self) -> str:
+    def _get_custom_code(self) -> Optional[str]:
         """Get custom code for the component.
 
         Returns:
             The custom code.
         """
-        return ""
+        return None
 
-    def get_custom_code(self) -> str:
+    def get_custom_code(self) -> Set[str]:
         """Get custom code for the component and its children.
 
         Returns:
             The custom code.
         """
-        code = self._get_custom_code()
+        # Store the code in a set to avoid duplicates.
+        code = set()
+
+        # Add the custom code for this component.
+        custom_code = self._get_custom_code()
+        if custom_code is not None:
+            code.add(custom_code)
+
+        # Add the custom code for the children.
         for child in self.children:
-            child_code = child.get_custom_code()
-            if child_code != "" and child_code not in code:
-                code += "\n" + child_code
+            code |= child.get_custom_code()
+
+        # Return the code.
         return code
 
     def _get_imports(self) -> ImportDict:

+ 24 - 1
pynecone/components/datadisplay/code.py

@@ -2,10 +2,14 @@
 
 from typing import Dict
 
-from pynecone.components.component import Component
+from pynecone import utils
+from pynecone.components.component import Component, ImportDict
 from pynecone.components.libs.chakra import ChakraComponent
 from pynecone.var import Var
 
+# Path to the prism styles.
+PRISM_STYLES_PATH = "/styles/code/prism"
+
 
 class CodeBlock(Component):
     """A code block."""
@@ -14,6 +18,9 @@ class CodeBlock(Component):
 
     tag = "Prism"
 
+    # The theme to use.
+    theme: Var[str]
+
     # The language to use.
     language: Var[str]
 
@@ -32,6 +39,14 @@ class CodeBlock(Component):
     # Props passed down to the code tag.
     code_tag_props: Var[Dict[str, str]]
 
+    def _get_imports(self) -> ImportDict:
+        imports = super()._get_imports()
+        if self.theme is not None:
+            imports = utils.merge_imports(
+                imports, {PRISM_STYLES_PATH: {self.theme.name}}
+            )
+        return imports
+
     @classmethod
     def create(cls, *children, **props):
         """Create a text component.
@@ -61,6 +76,14 @@ class CodeBlock(Component):
         self.custom_style = self.custom_style or {}
         self.custom_style.update(style)  # type: ignore
 
+    def _render(self):
+        out = super()._render()
+        if self.theme is not None:
+            out.add_props(
+                style=Var.create(self.theme.name, is_local=False)
+            ).remove_props("theme")
+        return out
+
 
 class Code(ChakraComponent):
     """Used to display inline code."""

+ 5 - 5
pynecone/components/datadisplay/datatable.py

@@ -3,7 +3,7 @@
 from typing import Any, List
 
 from pynecone import utils
-from pynecone.components.component import Component
+from pynecone.components.component import Component, ImportDict
 from pynecone.components.tags import Tag
 from pynecone.var import Var
 
@@ -39,10 +39,10 @@ class DataTable(Gridjs):
     # Enable pagination.
     pagination: Var[bool]
 
-    def _get_custom_code(self) -> str:
-        return """
-import "gridjs/dist/theme/mermaid.css";
-"""
+    def _get_imports(self) -> ImportDict:
+        return utils.merge_imports(
+            super()._get_imports(), {"": {"gridjs/dist/theme/mermaid.css"}}
+        )
 
     def _render(self) -> Tag:
         if utils.is_dataframe(type(self.data)):

+ 2 - 3
pynecone/components/graphing/plotly.py

@@ -37,9 +37,8 @@ class Plotly(PlotlyLib):
         return {}
 
     def _get_custom_code(self) -> str:
-        return """
-import dynamic from 'next/dynamic'
-const Plot = dynamic(() => import('react-plotly.js'), { ssr: false }); 
+        return """import dynamic from 'next/dynamic'
+const Plot = dynamic(() => import('react-plotly.js'), { ssr: false });
 """
 
     def _render(self) -> Tag:

+ 2 - 1
pynecone/components/layout/box.py

@@ -1,9 +1,10 @@
 """A box component that can contain other components."""
 
+from typing import Optional
+
 from pynecone.components.libs.chakra import ChakraComponent
 from pynecone.components.tags import Tag
 from pynecone.var import Var
-from typing import Optional
 
 
 class Box(ChakraComponent):

+ 1 - 3
pynecone/components/typography/markdown.py

@@ -16,9 +16,6 @@ class Markdown(Component):
 
     src: Var[str]
 
-    def _get_custom_code(self) -> str:
-        return "import 'katex/dist/katex.min.css'"
-
     def _get_imports(self):
         imports = super()._get_imports()
         imports["@chakra-ui/react"] = {"Heading", "Code", "Text", "Link"}
@@ -26,6 +23,7 @@ class Markdown(Component):
         imports["remark-math"] = {"remarkMath"}
         imports["remark-gfm"] = {"remarkGfm"}
         imports["rehype-katex"] = {"rehypeKatex"}
+        imports[""] = {"katex/dist/katex.min.css"}
         return imports
 
     def _render(self):

+ 0 - 1
pynecone/utils.py

@@ -34,7 +34,6 @@ from rich.console import Console
 from pynecone import constants
 from pynecone.base import Base
 
-
 if TYPE_CHECKING:
     from pynecone.components.component import ImportDict
     from pynecone.config import Config

+ 10 - 8
tests/components/test_component.py

@@ -136,17 +136,19 @@ def test_get_custom_code(component1: Type[Component], component2: Type[Component
     # Check that the code gets compiled correctly.
     c1 = component1.create()
     c2 = component2.create()
-    assert c1.get_custom_code() == "console.log('component1')"
-    assert c2.get_custom_code() == "console.log('component2')"
+    assert c1.get_custom_code() == {"console.log('component1')"}
+    assert c2.get_custom_code() == {"console.log('component2')"}
 
     # Check that nesting components compiles both codes.
     c1 = component1.create(c2)
-    assert (
-        c1.get_custom_code() == "console.log('component1')\nconsole.log('component2')"
-    )
+    assert c1.get_custom_code() == {
+        "console.log('component1')",
+        "console.log('component2')",
+    }
 
     # Check that code is not duplicated.
     c1 = component1.create(c2, c2, c1, c1)
-    assert (
-        c1.get_custom_code() == "console.log('component1')\nconsole.log('component2')"
-    )
+    assert c1.get_custom_code() == {
+        "console.log('component1')",
+        "console.log('component2')",
+    }