Skip to content

Commit

Permalink
Merge branch 'main' into fix/add-default-title
Browse files Browse the repository at this point in the history
  • Loading branch information
jph00 authored Dec 22, 2024
2 parents f5e2375 + e0ef241 commit 2af4272
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 38 deletions.
1 change: 0 additions & 1 deletion fasthtml/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ def show(ft,*rest):
"hx_disabled_elt": Literal["this", "next", "previous"] | str,
"hx_history": Literal["false"] | str,
"hx_params": Literal["*", "none"] | str,
"hx_replace_url": Literal["true", "false"] | str,
"hx_validate": Literal["true", "false"],
}
hx_attrs_annotations |= {o: str for o in set(hx_attrs) - set(hx_attrs_annotations.keys())}
Expand Down
25 changes: 13 additions & 12 deletions fasthtml/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,20 +435,20 @@ async def _wrap_call(f, req, params):

# %% ../nbs/api/00_core.ipynb
htmx_exts = {
"head-support": "https://unpkg.com/htmx-ext-head-support@2.0.1/head-support.js",
"preload": "https://unpkg.com/htmx-ext-preload@2.0.1/preload.js",
"class-tools": "https://unpkg.com/htmx-ext-class-tools@2.0.1/class-tools.js",
"loading-states": "https://unpkg.com/htmx-ext-loading-states@2.0.0/loading-states.js",
"multi-swap": "https://unpkg.com/htmx-ext-multi-swap@2.0.0/multi-swap.js",
"path-deps": "https://unpkg.com/htmx-ext-path-deps@2.0.0/path-deps.js",
"head-support": "https://unpkg.com/htmx-ext-head-support@2.0.3/head-support.js",
"preload": "https://unpkg.com/htmx-ext-preload@2.1.0/preload.js",
"class-tools": "https://unpkg.com/htmx-ext-class-tools@2.0.1/class-tools.js",
"loading-states": "https://unpkg.com/htmx-ext-loading-states@2.0.0/loading-states.js",
"multi-swap": "https://unpkg.com/htmx-ext-multi-swap@2.0.0/multi-swap.js",
"path-deps": "https://unpkg.com/htmx-ext-path-deps@2.0.0/path-deps.js",
"remove-me": "https://unpkg.com/htmx-ext-remove-me@2.0.0/remove-me.js",
"ws": "https://unpkg.com/htmx-ext-ws@2.0.1/ws.js",
"ws": "https://unpkg.com/htmx-ext-ws@2.0.2/ws.js",
"chunked-transfer": "https://unpkg.com/htmx-ext-transfer-encoding-chunked@0.4.0/transfer-encoding-chunked.js"
}

# %% ../nbs/api/00_core.ipynb
htmxsrc = Script(src="https://unpkg.com/htmx.org@2.0.3/dist/htmx.min.js")
fhjsscr = Script(src="https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.4/fasthtml.js")
htmxsrc = Script(src="https://unpkg.com/htmx.org@2.0.4/dist/htmx.min.js")
fhjsscr = Script(src="https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js")
surrsrc = Script(src="https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js")
scopesrc = Script(src="https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js")
viewport = Meta(name="viewport", content="width=device-width, initial-scale=1, viewport-fit=cover")
Expand Down Expand Up @@ -668,10 +668,11 @@ def __dir__(self): return list(self._funcs.keys())
# %% ../nbs/api/00_core.ipynb
class APIRouter:
"Add routes to an app"
def __init__(self, prefix:str|None=None):
def __init__(self, prefix:str|None=None, body_wrap=noop_body):
self.routes,self.wss = [],[]
self.rt_funcs = RouteFuncs() # Store wrapped route function for discoverability
self.prefix = prefix if prefix else ""
self.body_wrap = body_wrap

def _wrap_func(self, func, path=None):
name = func.__name__
Expand All @@ -681,12 +682,12 @@ def _wrap_func(self, func, path=None):
if name not in all_meths: setattr(self.rt_funcs, name, wrapped)
return wrapped

def __call__(self, path:str=None, methods=None, name=None, include_in_schema=True, body_wrap=noop_body):
def __call__(self, path:str=None, methods=None, name=None, include_in_schema=True, body_wrap=None):
"Add a route at `path`"
def f(func):
p = self.prefix + ("/" + ('' if path.__name__=='index' else func.__name__) if callable(path) else path)
wrapped = self._wrap_func(func, p)
self.routes.append((func, p, methods, name, include_in_schema, body_wrap))
self.routes.append((func, p, methods, name, include_in_schema, body_wrap or self.body_wrap))
return wrapped
return f(path) if callable(path) else f

Expand Down
4 changes: 2 additions & 2 deletions fasthtml/js.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def light_media(
def dark_media(
css: str # CSS to be included in the dark media query
):
"Render dark media for nught mode views"
"Render dark media for night mode views"
return Style('@media (prefers-color-scheme: dark) {%s}' %css)

# %% ../nbs/api/03_js.ipynb
Expand Down Expand Up @@ -56,7 +56,7 @@ def KatexMarkdownJS(

# %% ../nbs/api/03_js.ipynb
def HighlightJS(
sel='pre code', # CSS selector for code elements. Default is industry standard, be careful before adjusting it
sel='pre code:not([data-highlighted="yes"])', # CSS selector for code elements. Default is industry standard, be careful before adjusting it
langs:str|list|tuple='python', # Language(s) to highlight
light='atom-one-light', # Light theme
dark='atom-one-dark' # Dark theme
Expand Down
33 changes: 17 additions & 16 deletions nbs/api/00_core.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@
{
"data": {
"text/plain": [
"datetime.datetime(2024, 12, 14, 14, 0)"
"datetime.datetime(2024, 12, 20, 14, 0)"
]
},
"execution_count": null,
Expand Down Expand Up @@ -1176,14 +1176,14 @@
"source": [
"#| export\n",
"htmx_exts = {\n",
" \"head-support\": \"https://unpkg.com/htmx-ext-head-support@2.0.1/head-support.js\", \n",
" \"preload\": \"https://unpkg.com/htmx-ext-preload@2.0.1/preload.js\", \n",
" \"class-tools\": \"https://unpkg.com/htmx-ext-class-tools@2.0.1/class-tools.js\", \n",
" \"loading-states\": \"https://unpkg.com/htmx-ext-loading-states@2.0.0/loading-states.js\", \n",
" \"multi-swap\": \"https://unpkg.com/htmx-ext-multi-swap@2.0.0/multi-swap.js\", \n",
" \"path-deps\": \"https://unpkg.com/htmx-ext-path-deps@2.0.0/path-deps.js\", \n",
" \"head-support\": \"https://unpkg.com/htmx-ext-head-support@2.0.3/head-support.js\",\n",
" \"preload\": \"https://unpkg.com/htmx-ext-preload@2.1.0/preload.js\",\n",
" \"class-tools\": \"https://unpkg.com/htmx-ext-class-tools@2.0.1/class-tools.js\",\n",
" \"loading-states\": \"https://unpkg.com/htmx-ext-loading-states@2.0.0/loading-states.js\",\n",
" \"multi-swap\": \"https://unpkg.com/htmx-ext-multi-swap@2.0.0/multi-swap.js\",\n",
" \"path-deps\": \"https://unpkg.com/htmx-ext-path-deps@2.0.0/path-deps.js\",\n",
" \"remove-me\": \"https://unpkg.com/htmx-ext-remove-me@2.0.0/remove-me.js\",\n",
" \"ws\": \"https://unpkg.com/htmx-ext-ws@2.0.1/ws.js\",\n",
" \"ws\": \"https://unpkg.com/htmx-ext-ws@2.0.2/ws.js\",\n",
" \"chunked-transfer\": \"https://unpkg.com/htmx-ext-transfer-encoding-chunked@0.4.0/transfer-encoding-chunked.js\"\n",
"}"
]
Expand All @@ -1196,8 +1196,8 @@
"outputs": [],
"source": [
"#| export\n",
"htmxsrc = Script(src=\"https://unpkg.com/htmx.org@2.0.3/dist/htmx.min.js\")\n",
"fhjsscr = Script(src=\"https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.4/fasthtml.js\")\n",
"htmxsrc = Script(src=\"https://unpkg.com/htmx.org@2.0.4/dist/htmx.min.js\")\n",
"fhjsscr = Script(src=\"https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js\")\n",
"surrsrc = Script(src=\"https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js\")\n",
"scopesrc = Script(src=\"https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js\")\n",
"viewport = Meta(name=\"viewport\", content=\"width=device-width, initial-scale=1, viewport-fit=cover\")\n",
Expand Down Expand Up @@ -2478,13 +2478,13 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Set to 2024-12-14 12:38:57.886589\n"
"Set to 2024-12-20 19:21:33.748637\n"
]
},
{
"data": {
"text/plain": [
"'Session time: 2024-12-14 12:38:57.886589'"
"'Session time: 2024-12-20 19:21:33.748637'"
]
},
"execution_count": null,
Expand Down Expand Up @@ -2691,10 +2691,11 @@
"#| export\n",
"class APIRouter:\n",
" \"Add routes to an app\"\n",
" def __init__(self, prefix:str|None=None): \n",
" def __init__(self, prefix:str|None=None, body_wrap=noop_body): \n",
" self.routes,self.wss = [],[]\n",
" self.rt_funcs = RouteFuncs() # Store wrapped route function for discoverability\n",
" self.prefix = prefix if prefix else \"\"\n",
" self.body_wrap = body_wrap\n",
"\n",
" def _wrap_func(self, func, path=None):\n",
" name = func.__name__\n",
Expand All @@ -2704,12 +2705,12 @@
" if name not in all_meths: setattr(self.rt_funcs, name, wrapped)\n",
" return wrapped\n",
"\n",
" def __call__(self, path:str=None, methods=None, name=None, include_in_schema=True, body_wrap=noop_body):\n",
" def __call__(self, path:str=None, methods=None, name=None, include_in_schema=True, body_wrap=None):\n",
" \"Add a route at `path`\"\n",
" def f(func):\n",
" p = self.prefix + (\"/\" + ('' if path.__name__=='index' else func.__name__) if callable(path) else path)\n",
" wrapped = self._wrap_func(func, p)\n",
" self.routes.append((func, p, methods, name, include_in_schema, body_wrap))\n",
" self.routes.append((func, p, methods, name, include_in_schema, body_wrap or self.body_wrap))\n",
" return wrapped\n",
" return f(path) if callable(path) else f\n",
" \n",
Expand Down Expand Up @@ -3004,7 +3005,7 @@
{
"data": {
"text/plain": [
"'Cookie was set at time 12:38:58.050326'"
"'Cookie was set at time 19:21:34.644743'"
]
},
"execution_count": null,
Expand Down
1 change: 0 additions & 1 deletion nbs/api/01_components.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@
" \"hx_disabled_elt\": Literal[\"this\", \"next\", \"previous\"] | str, \n",
" \"hx_history\": Literal[\"false\"] | str,\n",
" \"hx_params\": Literal[\"*\", \"none\"] | str,\n",
" \"hx_replace_url\": Literal[\"true\", \"false\"] | str, \n",
" \"hx_validate\": Literal[\"true\", \"false\"],\n",
"}\n",
"hx_attrs_annotations |= {o: str for o in set(hx_attrs) - set(hx_attrs_annotations.keys())}\n",
Expand Down
4 changes: 2 additions & 2 deletions nbs/api/03_js.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
"def dark_media(\n",
" css: str # CSS to be included in the dark media query\n",
" ):\n",
" \"Render dark media for nught mode views\"\n",
" \"Render dark media for night mode views\"\n",
" return Style('@media (prefers-color-scheme: dark) {%s}' %css)"
]
},
Expand Down Expand Up @@ -228,7 +228,7 @@
"source": [
"#| export\n",
"def HighlightJS(\n",
" sel='pre code', # CSS selector for code elements. Default is industry standard, be careful before adjusting it\n",
" sel='pre code:not([data-highlighted=\"yes\"])', # CSS selector for code elements. Default is industry standard, be careful before adjusting it\n",
" langs:str|list|tuple='python', # Language(s) to highlight\n",
" light='atom-one-light', # Light theme\n",
" dark='atom-one-dark' # Dark theme\n",
Expand Down
12 changes: 8 additions & 4 deletions nbs/tutorials/by_example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,9 @@
"metadata": {},
"outputs": [],
"source": [
"from fasthtml.common import *\n",
"from starlette.testclient import TestClient\n",
"\n",
"app = FastHTML()\n",
"cli = TestClient(app)"
]
Expand Down Expand Up @@ -1093,7 +1096,7 @@
"source": [
"reg_re_param(\"imgext\", \"ico|gif|jpg|jpeg|webm\")\n",
"\n",
"@app.get(r'/static/{path:path}{fn}.{ext:imgext}')\n",
"@app.get(r'/static/{path:path}/{fn}.{ext:imgext}')\n",
"def get_img(fn:str, path:str, ext:str): return f\"Getting {fn}.{ext} from /{path}\"\n",
"\n",
"cli.get('/static/foo/jph.ico').text"
Expand Down Expand Up @@ -1179,7 +1182,7 @@
"fake_db = [{\"name\": \"Foo\"}, {\"name\": \"Bar\"}]\n",
"\n",
"@app.get(\"/items/\")\n",
"def read_item(idx:int|None = 0): return fake_db[idx]\n",
"def read_item(idx: int = 0): return fake_db[idx]\n",
"\n",
"print(cli.get('/items/?idx=1').text)"
]
Expand All @@ -1198,6 +1201,7 @@
}
],
"source": [
"# Equivalent to `/items/?idx=0`.\n",
"print(cli.get('/items/').text)"
]
},
Expand Down Expand Up @@ -1905,7 +1909,7 @@
"}\n",
"```\n",
"\n",
"The [AI Pictionary example](https://github.com/AnswerDotAI/fasthtml-example/tree/main/ai_pictionary) uses a larger chunk of custom JavaScript to handle the drawing canvas. It's a good example of the type of application where running code on the client side makes the most sense, but still shows how you can integrate it with FastHTML on the server side to add functionality (like the AI responses) easily.\n",
"The [AI Pictionary example](https://github.com/AnswerDotAI/fasthtml-example/tree/main/03_pictionary) uses a larger chunk of custom JavaScript to handle the drawing canvas. It's a good example of the type of application where running code on the client side makes the most sense, but still shows how you can integrate it with FastHTML on the server side to add functionality (like the AI responses) easily.\n",
"\n",
"Adding styling with custom CSS and libraries such as tailwind is done the same way we add custom JavaScript. The [doodle example](https://github.com/AnswerDotAI/fasthtml-example/tree/main/doodle) uses [Doodle.CSS](https://github.com/chr15m/DoodleCSS) to style the page in a quirky way."
]
Expand Down Expand Up @@ -1944,7 +1948,7 @@
"6. Fetches and displays the URL of our app.\n",
"7. By default, mounts a `/app/data` folder on the cloud to our app's root folder. The app is run in `/app` by default, so from our app anything we store in `/data` will persist across restarts.\n",
"\n",
"A final note about Railway: We can add secrets like API keys that can be accessed as environment variables from our apps via ['Variables'](https://docs.railway.app/guides/variables). For example, for the image app (TODO link), we can add a `REPLICATE_API_KEY` variable, and then in `main.py` we can access it as `os.environ['REPLICATE_API_KEY']`.\n",
"A final note about Railway: We can add secrets like API keys that can be accessed as environment variables from our apps via ['Variables'](https://docs.railway.app/guides/variables). For example, for the [image generation app](https://github.com/AnswerDotAI/fasthtml-example/tree/main/image_app_simple), we can add a `REPLICATE_API_KEY` variable, and then in `main.py` we can access it as `os.environ['REPLICATE_API_KEY']`.\n",
"\n",
"\n",
"\n",
Expand Down

0 comments on commit 2af4272

Please sign in to comment.