From dd26dd044b9d85c7a3e6a6395954a8040c3d4f96 Mon Sep 17 00:00:00 2001 From: Nikhil Rao Date: Tue, 6 Dec 2022 01:22:57 -0800 Subject: [PATCH] Add style for code blocks. (#32) * Rename github actions file * Update custom code * Add theme for code blocks --- .../{python-checks.yml => build.yml} | 2 +- README.md | 2 +- pynecone/.templates/web/styles/code/prism.js | 992 ++++++++++++++++++ pynecone/compiler/compiler.py | 2 +- pynecone/compiler/utils.py | 4 +- pynecone/components/base/__init__.py | 2 +- pynecone/components/base/meta.py | 3 +- pynecone/components/component.py | 22 +- pynecone/components/datadisplay/code.py | 25 +- pynecone/components/datadisplay/datatable.py | 10 +- pynecone/components/graphing/plotly.py | 5 +- pynecone/components/layout/box.py | 3 +- pynecone/components/typography/markdown.py | 4 +- pynecone/utils.py | 1 - tests/components/test_component.py | 18 +- 15 files changed, 1059 insertions(+), 36 deletions(-) rename .github/workflows/{python-checks.yml => build.yml} (98%) create mode 100644 pynecone/.templates/web/styles/code/prism.js diff --git a/.github/workflows/python-checks.yml b/.github/workflows/build.yml similarity index 98% rename from .github/workflows/python-checks.yml rename to .github/workflows/build.yml index 26255ff6f..cf9c45909 100644 --- a/.github/workflows/python-checks.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: Python application +name: build on: push: diff --git a/README.md b/README.md index e413490f9..f2603a984 100644 --- a/README.md +++ b/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) diff --git a/pynecone/.templates/web/styles/code/prism.js b/pynecone/.templates/web/styles/code/prism.js new file mode 100644 index 000000000..20853361d --- /dev/null +++ b/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%)" + } +} diff --git a/pynecone/compiler/compiler.py b/pynecone/compiler/compiler.py index 74021edc4..1f9635f07 100644 --- a/pynecone/compiler/compiler.py +++ b/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), diff --git a/pynecone/compiler/utils.py b/pynecone/compiler/utils.py index b8498ffad..7fa8bd9d0 100644 --- a/pynecone/compiler/utils.py +++ b/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 diff --git a/pynecone/components/base/__init__.py b/pynecone/components/base/__init__.py index 3f5be972a..c34499a48 100644 --- a/pynecone/components/base/__init__.py +++ b/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 diff --git a/pynecone/components/base/meta.py b/pynecone/components/base/meta.py index 4c9864064..f01612408 100644 --- a/pynecone/components/base/meta.py +++ b/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): diff --git a/pynecone/components/component.py b/pynecone/components/component.py index f670fac6a..8fa917466 100644 --- a/pynecone/components/component.py +++ b/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: diff --git a/pynecone/components/datadisplay/code.py b/pynecone/components/datadisplay/code.py index fa6c2f888..e9d02a0dc 100644 --- a/pynecone/components/datadisplay/code.py +++ b/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.""" diff --git a/pynecone/components/datadisplay/datatable.py b/pynecone/components/datadisplay/datatable.py index 5b40654d0..b609ee42c 100644 --- a/pynecone/components/datadisplay/datatable.py +++ b/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)): diff --git a/pynecone/components/graphing/plotly.py b/pynecone/components/graphing/plotly.py index 7251e3a37..ab16c4a3c 100644 --- a/pynecone/components/graphing/plotly.py +++ b/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: diff --git a/pynecone/components/layout/box.py b/pynecone/components/layout/box.py index 13c809257..e5a2b17ad 100644 --- a/pynecone/components/layout/box.py +++ b/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): diff --git a/pynecone/components/typography/markdown.py b/pynecone/components/typography/markdown.py index 7df251533..8ba34130c 100644 --- a/pynecone/components/typography/markdown.py +++ b/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): diff --git a/pynecone/utils.py b/pynecone/utils.py index 6efd8c66b..aa23726a3 100644 --- a/pynecone/utils.py +++ b/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 diff --git a/tests/components/test_component.py b/tests/components/test_component.py index 8e1f81d01..86d5e580f 100644 --- a/tests/components/test_component.py +++ b/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')", + }