Skip to content

Commit 588e842

Browse files
committed
08: Content pages.
1 parent 1ef899d commit 588e842

File tree

17 files changed

+220
-46
lines changed

17 files changed

+220
-46
lines changed

docs/building/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,5 @@ first_pyscript
3333
bulma
3434
examples_template
3535
resource_listing
36+
pages
3637
```

docs/building/pages.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Content Pages
2+
3+
We have a home page, but we'll need some other content pages, such as "About".
4+
Add a "Page" resource, with Markdown+frontmatter-driven content under `/pages`.
5+
6+
7+
## Pages In `/pages`
8+
9+
- All pages will be Markdown-driven, e.g. `src/psc/pages/about.md` and `/pages/about.html`
10+
- Install `python-frontmatter` as regular dependency
11+
- Write tests for a new `Page` resource type and views
12+
- Implement them
13+
- Home page stays as a Jinja2 template, as it is heavily-Bulma (not a good candidate for Markdown)
14+
15+
## Navbar
16+
17+
- Wire `About` into the navbar
18+
19+
## Home Page
20+
21+
- Better formatting
22+
- Content for: homepage, about, contributing, vision, homepage hero
23+
24+
## Future
25+
26+
- Images
27+
- Static content
28+
- Contributors
29+
- Build command

src/psc/app.py

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ async def homepage(request: Request) -> _TemplateResponse:
3434
index_file = HERE / "index.html"
3535

3636
return templates.TemplateResponse(
37-
"page.jinja2",
37+
"homepage.jinja2",
3838
dict(
3939
title="Home Page",
4040
main=index_file.read_text(),
@@ -43,14 +43,14 @@ async def homepage(request: Request) -> _TemplateResponse:
4343
)
4444

4545

46-
async def examples(request: Request) -> _TemplateResponse:
47-
"""Handle the examples listing page."""
46+
async def gallery(request: Request) -> _TemplateResponse:
47+
"""Handle the gallery listing page."""
4848
these_examples: Iterator[Example] = request.app.state.resources.examples.values()
4949

5050
return templates.TemplateResponse(
51-
"examples.jinja2",
51+
"gallery.jinja2",
5252
dict(
53-
title="Examples",
53+
title="Gallery",
5454
examples=these_examples,
5555
request=request,
5656
),
@@ -76,15 +76,32 @@ async def example(request: Request) -> _TemplateResponse:
7676
)
7777

7878

79+
async def content_page(request: Request) -> _TemplateResponse:
80+
"""Handle a content page."""
81+
page_path = PurePath(request.path_params["page_name"])
82+
resources: Resources = request.app.state.resources
83+
this_page = resources.pages[page_path]
84+
85+
return templates.TemplateResponse(
86+
"page.jinja2",
87+
dict(
88+
title=this_page.title,
89+
main=this_page.body,
90+
request=request,
91+
),
92+
)
93+
94+
7995
routes = [
8096
Route("/", homepage),
8197
Route("/index.html", homepage),
8298
Route("/favicon.png", favicon),
83-
Route("/examples/index.html", examples),
84-
Route("/examples", examples),
85-
Route("/examples/{example_name}/index.html", example),
86-
Route("/examples/{example_name}/", example),
87-
Mount("/examples", StaticFiles(directory=HERE / "examples")),
99+
Route("/gallery/index.html", gallery),
100+
Route("/gallery", gallery),
101+
Route("/gallery/{example_name}/index.html", example),
102+
Route("/gallery/{example_name}/", example),
103+
Route("/pages/{page_name}", content_page),
104+
Mount("/gallery", StaticFiles(directory=HERE / "examples")),
88105
Mount("/static", StaticFiles(directory=HERE / "static")),
89106
Mount("/pyscript", StaticFiles(directory=PYSCRIPT)),
90107
Mount("/pyodide", StaticFiles(directory=PYODIDE)),

src/psc/pages/about.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
title: About PyScript Collective
3+
---
4+
5+
Stuff *is here*.

src/psc/resources.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from pathlib import PurePath
99
from typing import cast
1010

11+
import frontmatter
1112
from bs4 import BeautifulSoup
1213
from bs4 import Tag
1314
from markdown_it import MarkdownIt
@@ -130,11 +131,29 @@ def __post_init__(self) -> None:
130131
self.extra_pyscript = get_pyscript_nodes(soup)
131132

132133

134+
@dataclass
135+
class Page(Resource):
136+
"""A Markdown+frontmatter driven content page."""
137+
138+
body: str = ""
139+
140+
def __post_init__(self) -> None:
141+
"""Extract content from Markdown file."""
142+
md_file = HERE / "pages" / f"{self.path}.md"
143+
if not md_file.exists():
144+
raise ValueError(f"No page at {self.path}")
145+
md_fm = frontmatter.load(md_file)
146+
self.title = md_fm["title"]
147+
md = MarkdownIt()
148+
self.body = str(md.render(md_fm.content))
149+
150+
133151
@dataclass
134152
class Resources:
135153
"""Container for all resources in site."""
136154

137155
examples: dict[PurePath, Example] = field(default_factory=dict)
156+
pages: dict[PurePath, Page] = field(default_factory=dict)
138157

139158

140159
def get_resources() -> Resources:
@@ -148,4 +167,13 @@ def get_resources() -> Resources:
148167
this_path = PurePath(example.name)
149168
this_example = Example(path=this_path)
150169
resources.examples[this_path] = this_example
170+
171+
# Load the Pages
172+
pages_dir = HERE / "pages"
173+
pages = [e for e in pages_dir.iterdir()]
174+
for page in pages:
175+
this_path = PurePath(page.stem)
176+
this_page = Page(path=this_path)
177+
resources.pages[this_path] = this_page
178+
151179
return resources

src/psc/static/psc.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ body {
33
font-size: x-large;
44
}
55

6+
#navbar {
7+
margin-left: 2rem;
8+
}
9+
610
#main_container {
711
margin-top: 3rem;
812
margin-bottom: 3rem;

src/psc/templates/example.jinja2

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{% extends "layout.jinja2" %}
22
{% block extra_head %}
3-
<meta name="subtitle" content="{{ subtitle }}" >
3+
<meta name="subtitle" content="{{ subtitle }}">
44
<script defer src="/pyscript/pyscript.js"></script>
55
{{ extra_head | safe }}{% endblock %}
66
{% block extra_body %}
@@ -14,5 +14,7 @@
1414
{{ extra_pyscript | safe }}
1515
{% endblock %}
1616
{% block main %}
17-
{{ main | safe }}
17+
<main id="main_container" class="container">
18+
{{ main | safe }}
19+
</main>
1820
{% endblock %}

src/psc/templates/examples.jinja2

Lines changed: 0 additions & 16 deletions
This file was deleted.

src/psc/templates/gallery.jinja2

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{% extends "layout.jinja2" %}
2+
{% block main %}
3+
<main id="main_container" class="container">
4+
<div class="tile is-ancestor">
5+
{% for example in examples %}
6+
<div class="tile is-parent is-4">
7+
<article class="tile is-child box">
8+
<p class="title"><a href="/gallery/{{ example.path.name }}/">{{ example.title }}</a></p>
9+
<p class="subtitle">{{ example.subtitle }}</p>
10+
<div class="content">
11+
{{ example.description | safe }}
12+
</div>
13+
</article>
14+
</div>
15+
{% endfor %}
16+
</div>
17+
</main>
18+
{% endblock %}

src/psc/templates/homepage.jinja2

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{% extends "layout.jinja2" %}
2+
{% block main %}
3+
<section class="hero is-medium is-warning">
4+
<div class="hero-body">
5+
<p class="title">
6+
Medium hero
7+
</p>
8+
<p class="subtitle">
9+
Medium subtitle
10+
</p>
11+
</div>
12+
</section>
13+
<section class="section has-background-info-light">
14+
<h1 class="title">Section</h1>
15+
<h2 class="subtitle">
16+
A simple container to divide your page into <strong>sections</strong>, like the one you're currently
17+
reading.
18+
</h2>
19+
<div class="tile is-ancestor">
20+
<div class="tile is-parent">
21+
<article class="tile is-child box">
22+
<p class="title">Hello World</p>
23+
<p class="subtitle">What is up?</p>
24+
</article>
25+
</div>
26+
<div class="tile is-parent">
27+
<article class="tile is-child box">
28+
<p class="title">Foo</p>
29+
<p class="subtitle">Bar</p>
30+
</article>
31+
</div>
32+
<div class="tile is-parent">
33+
<article class="tile is-child box">
34+
<p class="title">Third column</p>
35+
<p class="subtitle">With some content</p>
36+
<div class="content">
37+
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ornare magna eros, eu
38+
pellentesque tortor vestibulum ut. Maecenas non massa sem. Etiam finibus odio quis feugiat
39+
facilisis.</p>
40+
</div>
41+
</article>
42+
</div>
43+
</div>
44+
</section>
45+
{% endblock %}

0 commit comments

Comments
 (0)