tangled
alpha
login
or
join now
ericwood.org
/
photos-site
1
fork
atom
A little app to serve my photography from my personal website
1
fork
atom
overview
issues
pulls
pipelines
make posts page layout generic
ericwood.org
2 months ago
9ee4fd09
714a3ac8
+236
-226
9 changed files
expand all
collapse all
unified
split
src
styles
app.css
posts.css
views
blog
index
style.css
template.jinja
shared.css
show
style.css
template.jinja
templates
layout.jinja
posts.jinja
+98
src/styles/app.css
···
1
1
+
:root {
2
2
+
--foreground: black;
3
3
+
--background: white;
4
4
+
--half: color-mix(in srgb, var(--foreground) 50%, transparent);
5
5
+
--light: color-mix(in srgb, var(--foreground) 10%, transparent);
6
6
+
}
7
7
+
8
8
+
* {
9
9
+
box-sizing: border-box;
10
10
+
}
11
11
+
12
12
+
html, body {
13
13
+
height: 100%;
14
14
+
min-height: 100%;
15
15
+
margin: 0;
16
16
+
padding: 0;
17
17
+
color: var(--foreground);
18
18
+
background-color: var(--background);
19
19
+
}
20
20
+
21
21
+
body {
22
22
+
display: flex;
23
23
+
flex-direction: column;
24
24
+
align-items: center;
25
25
+
height: 100%;
26
26
+
}
27
27
+
28
28
+
.container {
29
29
+
width: 100%;
30
30
+
height: 100%;
31
31
+
max-width: 3000px;
32
32
+
overflow: auto;
33
33
+
display: flex;
34
34
+
flex-direction: column;
35
35
+
justify-content: space-between;
36
36
+
}
37
37
+
38
38
+
header {
39
39
+
display: flex;
40
40
+
font-size: 16pt;
41
41
+
width: 100%;
42
42
+
border-bottom: solid var(--foreground) 3px;
43
43
+
}
44
44
+
45
45
+
header h1 {
46
46
+
color: var(--foreground);
47
47
+
text-transform: uppercase;
48
48
+
font-weight: 900;
49
49
+
margin: 0;
50
50
+
letter-spacing: 3px;
51
51
+
padding: 10px 30px;
52
52
+
border-right: solid var(--foreground) 3px;
53
53
+
}
54
54
+
55
55
+
header nav ul {
56
56
+
display: flex;
57
57
+
height: 100%;
58
58
+
list-style-type: none;
59
59
+
margin: 0;
60
60
+
padding: 0;
61
61
+
}
62
62
+
63
63
+
header nav ul a {
64
64
+
display: flex;
65
65
+
align-items: center;
66
66
+
height: 100%;
67
67
+
text-decoration: none;
68
68
+
color: var(--foreground);
69
69
+
padding: 0 30px;
70
70
+
}
71
71
+
72
72
+
header nav ul a.active, header nav ul a:hover {
73
73
+
background-color: var(--foreground);
74
74
+
color: var(--background);
75
75
+
}
76
76
+
77
77
+
@media (max-width: 850px) {
78
78
+
header {
79
79
+
flex-direction: column;
80
80
+
}
81
81
+
82
82
+
header nav ul {
83
83
+
flex-direction: column;
84
84
+
}
85
85
+
}
86
86
+
87
87
+
.layout {
88
88
+
width: fit-content;
89
89
+
margin: 0 auto;
90
90
+
max-width: 900px;
91
91
+
width: 100%;
92
92
+
}
93
93
+
94
94
+
footer {
95
95
+
margin-top: 30px;
96
96
+
padding: 30px;
97
97
+
color: var(--half);
98
98
+
}
+78
src/styles/posts.css
···
1
1
+
.posts__title {
2
2
+
font-size: 26pt;
3
3
+
margin: 30px 0;
4
4
+
}
5
5
+
6
6
+
.posts__tags {
7
7
+
display: flex;
8
8
+
align-items: center;
9
9
+
gap: 10px;
10
10
+
padding: 10px 0;
11
11
+
border-bottom: solid var(--foreground) 2px;
12
12
+
}
13
13
+
14
14
+
.posts__tags-title {
15
15
+
font-size: 10pt;
16
16
+
text-transform: uppercase;
17
17
+
font-weight: 600;
18
18
+
}
19
19
+
20
20
+
.posts__tag-list {
21
21
+
display: flex;
22
22
+
gap: 5px;
23
23
+
margin: 0;
24
24
+
padding: 0;
25
25
+
list-style-type: none;
26
26
+
}
27
27
+
28
28
+
.posts__entries {
29
29
+
display: flex;
30
30
+
flex-direction: column;
31
31
+
gap: 10px;
32
32
+
padding: 0;
33
33
+
list-style-type: none;
34
34
+
}
35
35
+
36
36
+
.posts__entries li {
37
37
+
display: flex;
38
38
+
justify-content: space-between;
39
39
+
border-bottom: solid var(--light) 1px;
40
40
+
padding-bottom: 10px;
41
41
+
}
42
42
+
43
43
+
.posts__entries li > a {
44
44
+
color: var(--foreground);
45
45
+
font-size: 12pt;
46
46
+
text-decoration: none;
47
47
+
}
48
48
+
49
49
+
.posts__entries li > a:hover {
50
50
+
text-decoration: underline;
51
51
+
}
52
52
+
53
53
+
.posts__entries li time {
54
54
+
font-family: monospace;
55
55
+
margin-left: 10px;
56
56
+
}
57
57
+
58
58
+
.tag {
59
59
+
border-radius: 5px;
60
60
+
padding: 3px 7px;
61
61
+
background-color: var(--light);
62
62
+
color: var(--foreground);
63
63
+
text-decoration: none;
64
64
+
display: inline-flex;
65
65
+
align-items: center;
66
66
+
gap: 5px;
67
67
+
}
68
68
+
69
69
+
.tag svg {
70
70
+
width: 12px;
71
71
+
height: 12px;
72
72
+
}
73
73
+
74
74
+
.tag.active {
75
75
+
padding: 1px 5px;
76
76
+
border: solid var(--foreground) 2px;
77
77
+
background-color: var(--background);
78
78
+
}
-56
src/views/blog/index/style.css
···
1
1
-
.blog__title {
2
2
-
font-size: 26pt;
3
3
-
margin: 30px 0;
4
4
-
}
5
5
-
6
6
-
.blog__tags {
7
7
-
display: flex;
8
8
-
align-items: center;
9
9
-
gap: 10px;
10
10
-
padding: 10px 0;
11
11
-
border-bottom: solid var(--foreground) 2px;
12
12
-
}
13
13
-
14
14
-
.blog__tags-title {
15
15
-
font-size: 10pt;
16
16
-
text-transform: uppercase;
17
17
-
font-weight: 600;
18
18
-
}
19
19
-
20
20
-
.blog__tag-list {
21
21
-
display: flex;
22
22
-
gap: 5px;
23
23
-
margin: 0;
24
24
-
padding: 0;
25
25
-
list-style-type: none;
26
26
-
}
27
27
-
28
28
-
.blog__entries {
29
29
-
display: flex;
30
30
-
flex-direction: column;
31
31
-
gap: 10px;
32
32
-
padding: 0;
33
33
-
list-style-type: none;
34
34
-
}
35
35
-
36
36
-
.blog__entries li {
37
37
-
display: flex;
38
38
-
justify-content: space-between;
39
39
-
border-bottom: solid var(--light) 1px;
40
40
-
padding-bottom: 10px;
41
41
-
}
42
42
-
43
43
-
.blog__entries li > a {
44
44
-
color: var(--foreground);
45
45
-
font-size: 12pt;
46
46
-
text-decoration: none;
47
47
-
}
48
48
-
49
49
-
.blog__entries li > a:hover {
50
50
-
text-decoration: underline;
51
51
-
}
52
52
-
53
53
-
.blog__entries li time {
54
54
-
font-family: monospace;
55
55
-
margin-left: 10px;
56
56
-
}
+5
-43
src/views/blog/index/template.jinja
···
2
2
{% set active_page = 'blog' %}
3
3
{% block title %}Blog{% endblock %}
4
4
{% block head %}
5
5
-
{{ inline_style("src/views/blog/shared.css") }}
6
5
{{ inline_style("src/views/blog/index/style.css") }}
6
6
+
{{ inline_style("src/styles/posts.css") }}
7
7
{% endblock %}
8
8
+
{% import "posts" as posts_macro %}
8
9
9
10
{% block body %}
10
10
-
<div class="blog__layout">
11
11
-
<h2 class="blog__title">
12
12
-
→ Blog
13
13
-
{% if tag %}
14
14
-
/ {{ tag }}
15
15
-
{% endif %}
16
16
-
</h2>
17
17
-
<div class="blog__tags">
18
18
-
<span class="blog__tags-title">Categories</span>
19
19
-
<ul class="blog__tag-list">
20
20
-
{% if tag %}
21
21
-
<li>
22
22
-
<a href="/blog" class="tag active">
23
23
-
{{ tag }}
24
24
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
25
25
-
<use xlink:href="#close-icon" />
26
26
-
</svg>
27
27
-
</a>
28
28
-
</li>
29
29
-
{% endif %}
30
30
-
{% for t in tags %}
31
31
-
{% if t[0] != tag %}
32
32
-
<li>
33
33
-
<a class="tag" href="/blog?tag={{ url_escape(t[0]) }}">{{ t[0] }}</a>
34
34
-
</li>
35
35
-
{% endif %}
36
36
-
{% endfor %}
37
37
-
</ul>
38
38
-
</div>
39
39
-
<ul class="blog__entries">
40
40
-
{% for post in posts %}
41
41
-
<li>
42
42
-
<a href="/blog/{{ post.slug }}">{{ post.title }}</a>
43
43
-
<span>
44
44
-
{% for t in post.tags %}
45
45
-
<a class="tag" href="/blog?tag={{ url_escape(t) }}">{{ t }}</a>
46
46
-
{% endfor %}
47
47
-
<time datetime="{{ post.published_at }}" data-short="true">{{ post.published_at }}</time>
48
48
-
</span>
49
49
-
</li>
50
50
-
{% endfor %}
51
51
-
</ul>
11
11
+
<div class="layout">
12
12
+
{{ posts_macro.header("Blog", tag=tag) }}
13
13
+
{{ posts_macro.table(posts, root_path="/blog", tag=tag) }}
52
14
</div>
53
15
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" style="display: none">
54
16
<defs>
-34
src/views/blog/shared.css
···
1
1
-
.blog__layout {
2
2
-
width: fit-content;
3
3
-
margin: 0 auto;
4
4
-
max-width: 900px;
5
5
-
width: 100%;
6
6
-
}
7
7
-
8
8
-
.blog__container {
9
9
-
display: flex;
10
10
-
gap: 60px;
11
11
-
position: relative;
12
12
-
}
13
13
-
14
14
-
.tag {
15
15
-
border-radius: 5px;
16
16
-
padding: 3px 7px;
17
17
-
background-color: var(--light);
18
18
-
color: var(--foreground);
19
19
-
text-decoration: none;
20
20
-
display: inline-flex;
21
21
-
align-items: center;
22
22
-
gap: 5px;
23
23
-
}
24
24
-
25
25
-
.tag svg {
26
26
-
width: 12px;
27
27
-
height: 12px;
28
28
-
}
29
29
-
30
30
-
.tag.active {
31
31
-
padding: 1px 5px;
32
32
-
border: solid var(--foreground) 2px;
33
33
-
background-color: var(--background);
34
34
-
}
+6
src/views/blog/show/style.css
···
1
1
+
.blog__container {
2
2
+
display: flex;
3
3
+
gap: 60px;
4
4
+
position: relative;
5
5
+
}
6
6
+
1
7
.blog__header {
2
8
border-bottom: solid var(--foreground) 2px;
3
9
}
-1
src/views/blog/show/template.jinja
···
2
2
{% set active_page = 'blog' %}
3
3
{% block title %}Blog{% endblock %}
4
4
{% block head %}
5
5
-
{{ inline_style("src/views/blog/shared.css") }}
6
5
{{ inline_style("src/views/blog/show/style.css") }}
7
6
{% if has_code %}
8
7
{{ inline_style("src/views/blog/show/syntax.css") }}
+1
-92
templates/layout.jinja
···
22
22
:root { font-family: 'InterVariable', serif; }
23
23
}
24
24
</style>
25
25
-
<style type="text/css">
26
26
-
:root {
27
27
-
--foreground: black;
28
28
-
--background: white;
29
29
-
--half: color-mix(in srgb, var(--foreground) 50%, transparent);
30
30
-
--light: color-mix(in srgb, var(--foreground) 10%, transparent);
31
31
-
}
32
25
33
33
-
* {
34
34
-
box-sizing: border-box;
35
35
-
}
36
36
-
37
37
-
html, body {
38
38
-
height: 100%;
39
39
-
min-height: 100%;
40
40
-
margin: 0;
41
41
-
padding: 0;
42
42
-
color: var(--foreground);
43
43
-
background-color: var(--background);
44
44
-
}
45
45
-
46
46
-
body {
47
47
-
display: flex;
48
48
-
flex-direction: column;
49
49
-
align-items: center;
50
50
-
height: 100%;
51
51
-
}
52
52
-
53
53
-
.container {
54
54
-
width: 100%;
55
55
-
height: 100%;
56
56
-
max-width: 3000px;
57
57
-
overflow: auto;
58
58
-
display: flex;
59
59
-
flex-direction: column;
60
60
-
justify-content: space-between;
61
61
-
}
62
62
-
63
63
-
header {
64
64
-
display: flex;
65
65
-
font-size: 16pt;
66
66
-
width: 100%;
67
67
-
border-bottom: solid var(--foreground) 3px;
68
68
-
}
69
69
-
70
70
-
header h1 {
71
71
-
color: var(--foreground);
72
72
-
text-transform: uppercase;
73
73
-
font-weight: 900;
74
74
-
margin: 0;
75
75
-
letter-spacing: 3px;
76
76
-
padding: 10px 30px;
77
77
-
border-right: solid var(--foreground) 3px;
78
78
-
}
79
79
-
80
80
-
header nav ul {
81
81
-
display: flex;
82
82
-
height: 100%;
83
83
-
list-style-type: none;
84
84
-
margin: 0;
85
85
-
padding: 0;
86
86
-
}
87
87
-
88
88
-
header nav ul a {
89
89
-
display: flex;
90
90
-
align-items: center;
91
91
-
height: 100%;
92
92
-
text-decoration: none;
93
93
-
color: var(--foreground);
94
94
-
padding: 0 30px;
95
95
-
}
96
96
-
97
97
-
header nav ul a.active, header nav ul a:hover {
98
98
-
background-color: var(--foreground);
99
99
-
color: var(--background);
100
100
-
}
101
101
-
102
102
-
@media (max-width: 850px) {
103
103
-
header {
104
104
-
flex-direction: column;
105
105
-
}
106
106
-
107
107
-
header nav ul {
108
108
-
flex-direction: column;
109
109
-
}
110
110
-
}
111
111
-
112
112
-
footer {
113
113
-
margin-top: 30px;
114
114
-
padding: 30px;
115
115
-
color: var(--half);
116
116
-
}
117
117
-
</style>
26
26
+
{{ inline_style("src/styles/app.css") }}
118
27
<title>{% block title %}{% endblock %}</title>
119
28
{% block head %}{% endblock %}
120
29
</head>
+48
templates/posts.jinja
···
1
1
+
{% macro header(title, tag=None) %}
2
2
+
<h2 class="posts__title">
3
3
+
→ {{ title }}
4
4
+
{% if tag %}
5
5
+
/ {{ tag }}
6
6
+
{% endif %}
7
7
+
</h2>
8
8
+
{% endmacro %}
9
9
+
10
10
+
{% macro table(posts, show_tags=true, root_path="", tag=None) %}
11
11
+
{% if show_tags %}
12
12
+
<div class="posts__tags">
13
13
+
<span class="posts__tags-title">Categories</span>
14
14
+
<ul class="posts__tag-list">
15
15
+
{% if tag %}
16
16
+
<li>
17
17
+
<a href="{{ root_path }}" class="tag active">
18
18
+
{{ tag }}
19
19
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
20
20
+
<use xlink:href="#close-icon" />
21
21
+
</svg>
22
22
+
</a>
23
23
+
</li>
24
24
+
{% endif %}
25
25
+
{% for t in tags %}
26
26
+
{% if t[0] != tag %}
27
27
+
<li>
28
28
+
<a class="tag" href="{{ root_path }}?tag={{ url_escape(t[0]) }}">{{ t[0] }}</a>
29
29
+
</li>
30
30
+
{% endif %}
31
31
+
{% endfor %}
32
32
+
</ul>
33
33
+
</div>
34
34
+
{% endif %}
35
35
+
<ul class="posts__entries">
36
36
+
{% for post in posts %}
37
37
+
<li>
38
38
+
<a href="{{ root_path }}/{{ post.slug }}">{{ post.title }}</a>
39
39
+
<span>
40
40
+
{% for t in post.tags %}
41
41
+
<a class="tag" href="{{ root_path }}?tag={{ url_escape(t) }}">{{ t }}</a>
42
42
+
{% endfor %}
43
43
+
<time datetime="{{ post.published_at }}" data-short="true">{{ post.published_at }}</time>
44
44
+
</span>
45
45
+
</li>
46
46
+
{% endfor %}
47
47
+
</ul>
48
48
+
{% endmacro %}