Skip to content

Commit 2085310

Browse files
committed
Add icons
1 parent d8c8276 commit 2085310

7 files changed

Lines changed: 45 additions & 18 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
<div style="text-align: center;">
2+
<img src="https://github.com/apiad/violetear/blob/main/logo.png?raw=true" height="200px" style="border-radius:5px;">
3+
</div>
4+
15
# 🐦 violetear
26

37
**The Full-Stack Web Framework for Pythonistas.**

logo.png

408 KB
Loading

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,6 @@ dev = [
3131
"pytest>=9.0.2",
3232
"pytest-cov>=7.0.0",
3333
]
34+
35+
[tool.setuptools.package-data]
36+
violetear = ["*.png"]

violetear/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@
1111
from .selector import Selector
1212
from .units import Unit
1313
from .color import Color
14+
from .markup import Document, Element, Component
1415

1516
# New Framework export (lazy import to avoid hard dependency errors if possible,
1617
# though our App class handles the check internally)
17-
from .app import App
18+
try:
19+
from .app import App
20+
except ImportError:
21+
pass
1822

1923
__version__ = "1.2.0"

violetear/app.py

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,22 @@
44
from textwrap import dedent
55
from typing import Any, Callable, Dict, List, Union
66

7-
from pydantic import create_model
8-
97

108
# --- Optional Server Dependencies ---
119
try:
10+
from pydantic import create_model
1211
from fastapi import FastAPI, APIRouter, Request, Response
13-
from fastapi.responses import HTMLResponse
12+
from fastapi.responses import HTMLResponse, FileResponse
1413
from fastapi.staticfiles import StaticFiles
1514
import uvicorn
1615

1716
HAS_SERVER = True
17+
1818
except ImportError:
19-
HAS_SERVER = False
20-
# Dummy classes for type hinting
21-
FastAPI = object # type: ignore
22-
APIRouter = object # type: ignore
23-
Request = object # type: ignore
24-
Response = object # type: ignore
19+
raise ImportError(
20+
"Violetear Server dependencies are missing. "
21+
"Please install them with: uv add --extra server 'fastapi[standard]'"
22+
)
2523

2624

2725
from .stylesheet import StyleSheet
@@ -34,16 +32,20 @@ class App:
3432
Wraps FastAPI to provide a full-stack Python web framework experience.
3533
"""
3634

37-
def __init__(self, title: str = "Violetear App"):
38-
if not HAS_SERVER:
39-
raise ImportError(
40-
"Violetear Server dependencies are missing. "
41-
"Please install them with: uv add --extra server 'fastapi[standard]'"
42-
)
43-
35+
def __init__(self, title: str = "Violetear App", favicon: str | None = None):
4436
self.title = title
4537
self.api = FastAPI(title=title)
4638

39+
if favicon is None:
40+
favicon = str(Path(__file__).parent / "icon.png")
41+
42+
self.favicon = favicon
43+
44+
# Standard path for browser favicon requests
45+
@self.api.get("/favicon.ico", include_in_schema=False)
46+
async def favicon():
47+
return FileResponse(self.favicon)
48+
4749
# Registry of served styles to prevent duplicate route registration
4850
self.served_styles: Dict[str, StyleSheet] = {}
4951

violetear/icon.png

861 KB
Loading

violetear/markup.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,9 +335,15 @@ def _render(self, fp, indent: int):
335335

336336

337337
class Head(Markup):
338-
def __init__(self, charset: str = "UTF-8", title: str = "") -> None:
338+
def __init__(
339+
self,
340+
charset: str = "UTF-8",
341+
title: str = "",
342+
favicon: str = "/favicon.ico"
343+
) -> None:
339344
self.charset = charset
340345
self.title = title
346+
self.favicon = favicon
341347
self.styles: list[StyleResource] = []
342348
self.scripts: list[ScriptResource] = []
343349

@@ -354,6 +360,14 @@ def _render(self, fp, indent: int):
354360
)
355361
self._write_line(fp, f"<title>{self.title}</title>", indent + 1)
356362

363+
# Render Favicon
364+
if self.favicon:
365+
self._write_line(
366+
fp,
367+
f'<link rel="icon" href="{self.favicon}">',
368+
indent + 1
369+
)
370+
357371
for style in self.styles:
358372
if style.inline and style.sheet:
359373
# Render Inline

0 commit comments

Comments
 (0)