Jelajahi Sumber

Support Tailwind out of the box (#1155)

Kabir Goel 1 tahun lalu
induk
melakukan
1de48ee17a

+ 17 - 0
pynecone/.templates/jinja/web/tailwind.config.js.jinja2

@@ -0,0 +1,17 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+	content: {{content|json_dumps}},
+	theme: {{theme|json_dumps}},
+	plugins: [
+	{% for plugin in plugins %}
+		require({{plugin|json_dumps}}),
+	{% endfor %}
+	],
+	{% if presets is defined %}
+	presets: [
+	{% for preset in presets %}
+		require({{preset|json_dumps}})
+	{% endfor %}
+	]
+	{% endif %}
+};

TEMPAT SAMPAH
pynecone/.templates/web/bun.lockb


+ 5 - 0
pynecone/.templates/web/package.json

@@ -34,5 +34,10 @@
     "remark-math": "^5.1.1",
     "socket.io-client": "^4.6.1",
     "victory": "^36.6.8"
+  },
+  "devDependencies": {
+    "autoprefixer": "^10.4.14",
+    "postcss": "^8.4.24",
+    "tailwindcss": "^3.3.2"
   }
 }

+ 2 - 0
pynecone/.templates/web/pages/_app.js

@@ -2,6 +2,8 @@ import { ChakraProvider, extendTheme } from "@chakra-ui/react";
 import { Global, css } from "@emotion/react";
 import theme from "/utils/theme";
 
+import '../styles/tailwind.css'
+
 const GlobalStyles = css`
   /* Hide the blue border around Chakra components. */
   .js-focus-visible :focus:not([data-focus-visible-added]) {

+ 6 - 0
pynecone/.templates/web/postcss.config.js

@@ -0,0 +1,6 @@
+module.exports = {
+  plugins: {
+    tailwindcss: {},
+    autoprefixer: {},
+  },
+}

+ 3 - 0
pynecone/.templates/web/styles/tailwind.css

@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;

+ 7 - 0
pynecone/app.py

@@ -453,6 +453,13 @@ class App(Base):
         # Compile the theme.
         compiler.compile_theme(self.style)
 
+        # Compile the Tailwind config.
+        compiler.compile_tailwind(
+            dict(**config.tailwind, content=constants.TAILWIND_CONTENT)
+            if config.tailwind is not None
+            else {}
+        )
+
         # Compile the pages.
         custom_components = set()
         thread_pool = ThreadPool()

+ 36 - 0
pynecone/compiler/compiler.py

@@ -125,6 +125,22 @@ def _compile_components(components: Set[CustomComponent]) -> str:
     )
 
 
+def _compile_tailwind(
+    config: dict,
+) -> str:
+    """Compile the Tailwind config.
+
+    Args:
+        config: The Tailwind config.
+
+    Returns:
+        The compiled Tailwind config.
+    """
+    return templates.TAILWIND_CONFIG.render(
+        **config,
+    )
+
+
 def write_output(fn: Callable[..., Tuple[str, str]]):
     """Write the output of the function to a file.
 
@@ -239,6 +255,26 @@ def compile_components(components: Set[CustomComponent]):
     return output_path, code
 
 
+@write_output
+def compile_tailwind(
+    config: dict,
+):
+    """Compile the Tailwind config.
+
+    Args:
+        config: The Tailwind config.
+
+    Returns:
+        The compiled Tailwind config.
+    """
+    # Get the path for the output file.
+    output_path = constants.TAILWIND_CONFIG
+
+    # Compile the config.
+    code = _compile_tailwind(config)
+    return output_path, code
+
+
 def purge_web_pages_dir():
     """Empty out .web directory."""
     template_files = ["_app.js", "404.js"]

+ 3 - 0
pynecone/compiler/templates.py

@@ -65,6 +65,9 @@ DOCUMENT_ROOT = get_template("web/pages/_document.js.jinja2")
 # Template for the theme file.
 THEME = get_template("web/utils/theme.js.jinja2")
 
+# Template for Tailwind config.
+TAILWIND_CONFIG = get_template("web/tailwind.config.js.jinja2")
+
 # Code to render a single NextJS page.
 PAGE = get_template("web/pages/index.js.jinja2")
 

+ 4 - 1
pynecone/config.py

@@ -6,7 +6,7 @@ import importlib
 import os
 import sys
 import urllib.parse
-from typing import List, Optional
+from typing import Any, Dict, List, Optional
 
 from dotenv import load_dotenv
 
@@ -197,6 +197,9 @@ class Config(Base):
     # Whether to override OS environment variables.
     override_os_envs: Optional[bool] = True
 
+    # Tailwind config.
+    tailwind: Optional[Dict[str, Any]] = None
+
     # Timeout when launching the gunicorn server.
     timeout: int = constants.TIMEOUT
 

+ 4 - 0
pynecone/constants.py

@@ -77,6 +77,10 @@ WEB_STATIC_DIR = os.path.join(WEB_DIR, "_static")
 WEB_UTILS_DIR = os.path.join(WEB_DIR, UTILS_DIR)
 # The directory where the assets are located.
 WEB_ASSETS_DIR = os.path.join(WEB_DIR, "public")
+# The Tailwind config.
+TAILWIND_CONFIG = os.path.join(WEB_DIR, "tailwind.config.js")
+# Default Tailwind content paths
+TAILWIND_CONTENT = ["./pages/**/*.{js,ts,jsx,tsx}"]
 # The sitemap config file.
 SITEMAP_CONFIG_FILE = os.path.join(WEB_DIR, "next-sitemap.config.js")
 # The node modules directory.