+5
-4
gleam.toml
+5
-4
gleam.toml
···
1
1
name = "website"
2
+
target = "javascript"
2
3
version = "1.0.0"
3
4
4
5
[dependencies]
5
6
gleam_stdlib = ">= 0.34.0 and < 2.0.0"
6
7
lustre = ">= 4.2.0 and < 5.0.0"
7
-
birl = ">= 1.6.1 and < 2.0.0"
8
-
sketch = ">= 2.1.0 and < 3.0.0"
8
+
modem = ">= 1.1.0 and < 2.0.0"
9
+
lustre_ui = ">= 0.6.0 and < 1.0.0"
10
+
birl = ">= 1.7.0 and < 2.0.0"
9
11
10
12
[dev-dependencies]
11
13
gleeunit = ">= 1.0.0 and < 2.0.0"
12
-
lustre_dev_tools = ">= 1.2.2 and < 2.0.0"
13
-
lustre_ssg = ">= 0.6.1 and < 1.0.0"
14
+
lustre_dev_tools = ">= 1.3.2 and < 2.0.0"
+15
index.html
+15
index.html
···
1
+
<!doctype html>
2
+
<html lang="en">
3
+
<head>
4
+
<meta charset="UTF-8" />
5
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+
7
+
<title>🚧 website</title>
8
+
9
+
<script type="module" src="/priv/static/website.mjs"></script>
10
+
</head>
11
+
12
+
<body>
13
+
<div id="app"></div>
14
+
</body>
15
+
</html>
+13
-13
manifest.toml
+13
-13
manifest.toml
···
3
3
4
4
packages = [
5
5
{ name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" },
6
-
{ name = "birl", version = "1.6.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "ranger"], otp_app = "birl", source = "hex", outer_checksum = "976CFF85D34D50F7775896615A71745FBE0C325E50399787088F941B539A0497" },
6
+
{ name = "birl", version = "1.7.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "ranger"], otp_app = "birl", source = "hex", outer_checksum = "B1FA529E7BE3FF12CADF32814AB8EC7294E74CEDEE8CC734505707B929A98985" },
7
7
{ name = "exception", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "F5580D584F16A20B7FCDCABF9E9BE9A2C1F6AC4F9176FA6DD0B63E3B20D450AA" },
8
8
{ name = "filepath", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "EFB6FF65C98B2A16378ABC3EE2B14124168C0CE5201553DE652E2644DCFDB594" },
9
9
{ name = "fs", version = "8.6.1", build_tools = ["rebar3"], requirements = [], otp_app = "fs", source = "hex", outer_checksum = "61EA2BDAEDAE4E2024D0D25C63E44DCCF65622D4402DB4A2DF12868D1546503F" },
···
12
12
{ name = "gleam_crypto", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "ADD058DEDE8F0341F1ADE3AAC492A224F15700829D9A3A3F9ADF370F875C51B7" },
13
13
{ name = "gleam_erlang", version = "0.25.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "054D571A7092D2A9727B3E5D183B7507DAB0DA41556EC9133606F09C15497373" },
14
14
{ name = "gleam_http", version = "3.6.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "8C07DF9DF8CC7F054C650839A51C30A7D3C26482AC241C899C1CEA86B22DBE51" },
15
-
{ name = "gleam_javascript", version = "0.8.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_javascript", source = "hex", outer_checksum = "14D5B7E1A70681E0776BF0A0357F575B822167960C844D3D3FA114D3A75F05A8" },
15
+
{ name = "gleam_httpc", version = "2.2.0", build_tools = ["gleam"], requirements = ["gleam_http", "gleam_stdlib"], otp_app = "gleam_httpc", source = "hex", outer_checksum = "CF76C71002DEECF6DC5D9CA83D962728FAE166B57926BE442D827004D3C7DF1B" },
16
16
{ name = "gleam_json", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "thoas"], otp_app = "gleam_json", source = "hex", outer_checksum = "9063D14D25406326C0255BDA0021541E797D8A7A12573D849462CAFED459F6EB" },
17
17
{ name = "gleam_otp", version = "0.10.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "0B04FE915ACECE539B317F9652CAADBBC0F000184D586AAAF2D94C100945D72B" },
18
18
{ name = "gleam_package_interface", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], otp_app = "gleam_package_interface", source = "hex", outer_checksum = "52A721BCA972C8099BB881195D821AAA64B9F2655BECC102165D5A1097731F01" },
19
19
{ name = "gleam_stdlib", version = "0.37.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "5398BD6C2ABA17338F676F42F404B9B7BABE1C8DC7380031ACB05BBE1BCF3742" },
20
-
{ name = "glearray", version = "0.2.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glearray", source = "hex", outer_checksum = "908154F695D330E06A37FAB2C04119E8F315D643206F8F32B6A6C14A8709FFF4" },
20
+
{ name = "glearray", version = "0.2.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glearray", source = "hex", outer_checksum = "9C207E05F38D724F464FA921378DB3ABC2B0A2F5821116D8BC8B2CACC68930D5" },
21
21
{ name = "gleeunit", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "72CDC3D3F719478F26C4E2C5FED3E657AC81EC14A47D2D2DEBB8693CA3220C3B" },
22
22
{ name = "glint", version = "0.18.1", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_community_colour", "gleam_stdlib", "snag"], otp_app = "glint", source = "hex", outer_checksum = "5FB54D7732B4105E4AF4D89A7EE6D5E8CF33DA13A3575D0C6ECE470B97958454" },
23
23
{ name = "glisten", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib"], otp_app = "glisten", source = "hex", outer_checksum = "CF3A9383E9BA4A8CBAF2F7B799716290D02F2AC34E7A77556B49376B662B9314" },
24
+
{ name = "gramps", version = "2.0.1", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gramps", source = "hex", outer_checksum = "FBB7EA641C8A1EF02C0E938B6045A1360B925E5E65BAD0E228C4AEF6C6933722" },
24
25
{ name = "hpack_erl", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "hpack", source = "hex", outer_checksum = "D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0" },
25
-
{ name = "jot", version = "0.4.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "jot", source = "hex", outer_checksum = "B20A745707EE60B857249D4533656A52964EA024E844005C4AD8135ED432D66C" },
26
26
{ name = "logging", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "A996064F04EF6E67F0668FD0ACFB309830B05D0EE3A0C11BBBD2D4464334F792" },
27
27
{ name = "lustre", version = "4.2.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_json", "gleam_otp", "gleam_stdlib"], otp_app = "lustre", source = "hex", outer_checksum = "258F876CD7AB12C2C773F1A30F76DFC0A0ED989B720070DF32FC0717A6A0E60C" },
28
-
{ name = "lustre_dev_tools", version = "1.2.2", build_tools = ["gleam"], requirements = ["argv", "filepath", "fs", "gleam_community_ansi", "gleam_erlang", "gleam_http", "gleam_json", "gleam_otp", "gleam_package_interface", "gleam_stdlib", "glint", "glisten", "mist", "simplifile", "spinner", "tom", "wisp"], otp_app = "lustre_dev_tools", source = "hex", outer_checksum = "6F8A671F6021640F2F8F68C227375C601D3D12D0139EDDBCD1980B3560E99C18" },
29
-
{ name = "lustre_ssg", version = "0.6.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "jot", "lustre", "simplifile", "tom"], otp_app = "lustre_ssg", source = "hex", outer_checksum = "2C55F49F597DF8FC3FDD651349026FADFD2394763C34BB88BB8A57549E30ECFA" },
28
+
{ name = "lustre_dev_tools", version = "1.3.2", build_tools = ["gleam"], requirements = ["argv", "filepath", "fs", "gleam_community_ansi", "gleam_erlang", "gleam_http", "gleam_httpc", "gleam_json", "gleam_otp", "gleam_package_interface", "gleam_stdlib", "glint", "glisten", "mist", "simplifile", "spinner", "term_size", "tom", "wisp"], otp_app = "lustre_dev_tools", source = "hex", outer_checksum = "CC8F46BCE51C1349862C5F6BA0075B0C68096B866ED1C520B60358FAAB398B60" },
29
+
{ name = "lustre_ui", version = "0.6.0", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_json", "gleam_stdlib", "lustre"], otp_app = "lustre_ui", source = "hex", outer_checksum = "FA1F9E89D89CDD5DF376ED86ABA8A38441CB2E664CD4D402F22A49DA4D7BB56D" },
30
30
{ name = "marceau", version = "1.1.0", build_tools = ["gleam"], requirements = [], otp_app = "marceau", source = "hex", outer_checksum = "1AAD727A30BE0F95562C3403BB9B27C823797AD90037714255EEBF617B1CDA81" },
31
-
{ name = "mist", version = "1.0.0", build_tools = ["gleam"], requirements = ["birl", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "glisten", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "7765E53DCC9ACCACF217B8E0CA3DE7E848C783BFAE5118B75011E81C2C80385C" },
32
-
{ name = "plinth", version = "0.2.0", build_tools = ["gleam"], requirements = ["gleam_javascript", "gleam_json", "gleam_stdlib"], otp_app = "plinth", source = "hex", outer_checksum = "83211E672D83F3CE14681D0ECD3AD883EE7588E423E7C9DDDB460014AD60AC24" },
31
+
{ name = "mist", version = "1.2.0", build_tools = ["gleam"], requirements = ["birl", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "glisten", "gramps", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "109B4D64E68C104CC23BB3CC5441ECD479DD7444889DA01113B75C6AF0F0E17B" },
32
+
{ name = "modem", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "lustre"], otp_app = "modem", source = "hex", outer_checksum = "4C6E448089B09A57C179455D44526A717E4E217D4000B91201617FD2D9F18E68" },
33
33
{ name = "ranger", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "ranger", source = "hex", outer_checksum = "1566C272B1D141B3BBA38B25CB761EF56E312E79EC0E2DFD4D3C19FB0CC1F98C" },
34
34
{ name = "repeatedly", version = "2.1.1", build_tools = ["gleam"], requirements = [], otp_app = "repeatedly", source = "hex", outer_checksum = "38808C3EC382B0CD981336D5879C24ECB37FCB9C1D1BD128F7A80B0F74404D79" },
35
35
{ name = "simplifile", version = "1.7.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "1D5DFA3A2F9319EC85825F6ED88B8E449F381B0D55A62F5E61424E748E7DDEB0" },
36
-
{ name = "sketch", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib", "lustre", "plinth"], otp_app = "sketch", source = "hex", outer_checksum = "47175BD019A00CFEAAF2851830825544E24ABA58168083A1D219FA8E06EF6713" },
37
36
{ name = "snag", version = "0.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "snag", source = "hex", outer_checksum = "54D32E16E33655346AA3E66CBA7E191DE0A8793D2C05284E3EFB90AD2CE92BCC" },
38
37
{ name = "spinner", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_erlang", "gleam_stdlib", "glearray", "repeatedly"], otp_app = "spinner", source = "hex", outer_checksum = "200BA3D4A04D468898E63C0D316E23F526E02514BC46454091975CB5BAE41E8F" },
38
+
{ name = "term_size", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "term_size", source = "hex", outer_checksum = "D00BD2BC8FB3EBB7E6AE076F3F1FF2AC9D5ED1805F004D0896C784D06C6645F1" },
39
39
{ name = "thoas", version = "1.2.0", build_tools = ["rebar3"], requirements = [], otp_app = "thoas", source = "hex", outer_checksum = "540C8CB7D9257F2AD0A14145DC23560F91ACDCA995F0CCBA779EB33AF5D859D1" },
40
40
{ name = "tom", version = "0.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "tom", source = "hex", outer_checksum = "0831C73E45405A2153091226BF98FB485ED16376988602CC01A5FD086B82D577" },
41
41
{ name = "wisp", version = "0.14.0", build_tools = ["gleam"], requirements = ["exception", "gleam_crypto", "gleam_erlang", "gleam_http", "gleam_json", "gleam_stdlib", "logging", "marceau", "mist", "simplifile"], otp_app = "wisp", source = "hex", outer_checksum = "9F5453AF1F9275E6F8707BC815D6A6A9DF41551921B16FBDBA52883773BAE684" },
42
42
]
43
43
44
44
[requirements]
45
-
birl = { version = ">= 1.6.1 and < 2.0.0" }
45
+
birl = { version = ">= 1.7.0 and < 2.0.0"}
46
46
gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" }
47
47
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
48
48
lustre = { version = ">= 4.2.0 and < 5.0.0" }
49
-
lustre_dev_tools = { version = ">= 1.2.2 and < 2.0.0" }
50
-
lustre_ssg = { version = ">= 0.6.1 and < 1.0.0" }
51
-
sketch = { version = ">= 2.1.0 and < 3.0.0"}
49
+
lustre_dev_tools = { version = ">= 1.3.2 and < 2.0.0" }
50
+
lustre_ui = { version = ">= 0.6.0 and < 1.0.0" }
51
+
modem = { version = ">= 1.1.0 and < 2.0.0" }
-50
src/build.gleam
-50
src/build.gleam
···
1
-
import gleam/dict
2
-
import gleam/io
3
-
import gleam/list
4
-
import lustre/ssg
5
-
import sketch
6
-
import sketch/lustre as sklustre
7
-
import sketch/options as skoptions
8
-
import website/data/posts
9
-
import website/data/projects
10
-
import website/page/blog
11
-
import website/page/index
12
-
import website/page/post
13
-
import website/page/project
14
-
15
-
pub fn main() {
16
-
let assert Ok(cache) =
17
-
skoptions.node()
18
-
|> sklustre.setup()
19
-
20
-
sketch.prepare(cache)
21
-
22
-
let posts =
23
-
dict.from_list({
24
-
use post <- list.map(posts.all())
25
-
#(post.id, post)
26
-
})
27
-
28
-
let projects =
29
-
dict.from_list({
30
-
use project <- list.map(projects.all())
31
-
#(project.id, project)
32
-
})
33
-
34
-
let build =
35
-
ssg.new("./out")
36
-
|> ssg.add_static_route("/", index.view(cache))
37
-
|> ssg.add_static_route("/blog", blog.view(posts.all()))
38
-
|> ssg.add_dynamic_route("/blog", posts, post.view)
39
-
|> ssg.add_static_route("/projects", projects.view(projects.all(), cache))
40
-
|> ssg.add_dynamic_route("/projects", projects, project.view)
41
-
|> ssg.build
42
-
43
-
case build {
44
-
Ok(_) -> io.println("Build successful!")
45
-
Error(e) -> {
46
-
io.debug(e)
47
-
io.println("Build failed!")
48
-
}
49
-
}
50
-
}
+152
src/website.gleam
+152
src/website.gleam
···
1
+
import gleam/list
2
+
import gleam/string
3
+
import gleam/uri.{type Uri}
4
+
import lustre
5
+
import lustre/attribute
6
+
import lustre/effect.{type Effect}
7
+
import lustre/element.{type Element}
8
+
import lustre/element/html
9
+
import lustre/ui
10
+
import lustre/ui/layout/cluster
11
+
import modem
12
+
import website/posts
13
+
import website/projects
14
+
import website/common
15
+
16
+
// Main
17
+
18
+
pub fn main() {
19
+
let app = lustre.application(init, update, view)
20
+
let assert Ok(dispatch) = lustre.start(app, "#app", Nil)
21
+
22
+
dispatch
23
+
}
24
+
25
+
// Model
26
+
27
+
type Model {
28
+
Model(
29
+
current_route: Route,
30
+
posts: List(posts.Post),
31
+
projects: List(projects.Project),
32
+
)
33
+
}
34
+
35
+
type Route {
36
+
Home
37
+
Posts
38
+
Post(id: String)
39
+
Projects
40
+
Project(id: String)
41
+
}
42
+
43
+
@external(javascript, "./ffi.mjs", "get_route")
44
+
fn do_get_route() -> String
45
+
46
+
fn get_route() -> Route {
47
+
case do_get_route() |> string.split("/") {
48
+
["", "projects", id] | ["", "project", id] -> Project(id)
49
+
["", "projects"] -> Projects
50
+
["", "posts", id] | ["", "post", id] -> Post(id)
51
+
["", "posts"] -> Posts
52
+
_ -> Home
53
+
}
54
+
}
55
+
56
+
fn init(_flags) -> #(Model, Effect(Msg)) {
57
+
#(
58
+
Model(current_route: get_route(), projects: projects.all(), posts: []),
59
+
modem.init(on_route_change),
60
+
)
61
+
}
62
+
63
+
fn on_route_change(uri: Uri) -> Msg {
64
+
case uri.path_segments(uri.path) {
65
+
["projects", id] | ["project", id] -> OnRouteChange(Project(id))
66
+
["projects"] -> OnRouteChange(Projects)
67
+
["posts", id] | ["post", id] -> OnRouteChange(Post(id))
68
+
["posts"] -> OnRouteChange(Posts)
69
+
_ -> OnRouteChange(Home)
70
+
}
71
+
}
72
+
73
+
// Update
74
+
75
+
pub opaque type Msg {
76
+
OnRouteChange(Route)
77
+
}
78
+
79
+
fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
80
+
case msg {
81
+
OnRouteChange(route) -> #(
82
+
Model(..model, current_route: route),
83
+
effect.none(),
84
+
)
85
+
}
86
+
}
87
+
88
+
// View
89
+
90
+
fn view(model: Model) -> Element(Msg) {
91
+
let styles = [#("margin-left", "15vh"), #("margin-top", "5vh")]
92
+
93
+
let page = case model.current_route {
94
+
Home -> view_home(model)
95
+
Projects -> view_projects(model)
96
+
Project(id) -> view_project(model, id)
97
+
Posts -> view_posts(model)
98
+
_ -> view_home(model)
99
+
}
100
+
101
+
ui.stack([attribute.style(styles)], [view_navbar(model), page])
102
+
}
103
+
104
+
fn view_navbar(_) -> Element(Msg) {
105
+
let item_styles = [#("text-decoration", "underline")]
106
+
107
+
let view_nav_item = fn(path, text) {
108
+
html.a([attribute.href("/" <> path), attribute.style(item_styles)], [
109
+
element.text(text),
110
+
])
111
+
}
112
+
113
+
cluster.of(html.nav, [], [
114
+
view_nav_item("", "Home"),
115
+
view_nav_item("projects", "Projects"),
116
+
view_nav_item("posts", "Posts"),
117
+
])
118
+
}
119
+
120
+
fn view_home(model: Model) -> Element(Msg) {
121
+
html.h1([], [element.text("Homepage")])
122
+
}
123
+
124
+
fn icon_style() -> List(#(String, String)) {
125
+
[
126
+
#("max-width", "4em"),
127
+
#("max-height", "4em"),
128
+
#("border-radius", "1em"),
129
+
]
130
+
}
131
+
132
+
fn view_projects(model: Model) -> Element(Msg) {
133
+
let projects =
134
+
model.projects
135
+
|> list.map(fn(project: projects.Project) {
136
+
html.div([], [
137
+
html.span([], [
138
+
html.img([attribute.src(project.img), attribute.style(icon_style())]),
139
+
html.h1([], [common.link(project.title, "projects/" <> project.id)])
140
+
])
141
+
])
142
+
})
143
+
html.div([], projects)
144
+
}
145
+
146
+
fn view_project(model: Model, id: String) -> Element(Msg) {
147
+
html.h1([], [element.text("Project: " <> id)])
148
+
}
149
+
150
+
fn view_posts(model: Model) -> Element(Msg) {
151
+
html.h1([], [element.text("Posts")])
152
+
}
+7
src/website/common.gleam
+7
src/website/common.gleam
+5
-5
src/website/data/posts.gleam
src/website/posts.gleam
+5
-5
src/website/data/posts.gleam
src/website/posts.gleam
···
2
2
import lustre/attribute
3
3
import lustre/element
4
4
import lustre/element/html
5
-
import website/page/index.{link}
5
+
import website/common.{link}
6
6
7
7
pub type Post {
8
8
Post(
···
13
13
summary: element.Element(String),
14
14
content: element.Element(String),
15
15
)
16
+
}
17
+
18
+
pub fn all() -> List(Post) {
19
+
[release_mystcraft_ages(), mystcraft_ages_alpha_2()]
16
20
}
17
21
18
22
fn mystcraft_short_descriptor() -> element.Element(String) {
···
166
170
]),
167
171
)
168
172
}
169
-
170
-
pub fn all() -> List(Post) {
171
-
[release_mystcraft_ages(), mystcraft_ages_alpha_2()]
172
-
}
+1
-74
src/website/data/projects.gleam
src/website/projects.gleam
+1
-74
src/website/data/projects.gleam
src/website/projects.gleam
···
1
-
import gleam/list
2
-
import lustre/attribute
3
1
import lustre/element
4
2
import lustre/element/html
5
-
import sketch
6
-
import sketch/lustre.{ssr}
7
-
import sketch/size.{em, em_}
8
-
import website/page/index.{link}
3
+
import website/common.{link}
9
4
10
5
pub type Link {
11
6
Link(title: String, url: String, img: String)
···
21
16
archived: Bool,
22
17
summary: element.Element(String),
23
18
)
24
-
}
25
-
26
-
fn project_class(archived: Bool) -> attribute.Attribute(a) {
27
-
let #(bg, bg_hov) = case archived {
28
-
True -> #("#d36473", "#c55d6b")
29
-
False -> #("#cae4e7", "#b8cfd2")
30
-
}
31
-
sketch.class([
32
-
sketch.background(bg),
33
-
sketch.padding(em(1)),
34
-
sketch.hover([sketch.background(bg_hov)]),
35
-
sketch.margin_bottom(em_(0.5)),
36
-
sketch.border_radius(em_(0.75)),
37
-
])
38
-
|> sketch.to_lustre
39
-
}
40
-
41
-
fn icon_class() -> attribute.Attribute(a) {
42
-
sketch.class([
43
-
sketch.max_width(em_(3.5)),
44
-
sketch.max_height(em_(3.5)),
45
-
sketch.border_radius(em_(0.75)),
46
-
])
47
-
|> sketch.to_lustre
48
-
}
49
-
50
-
fn project_bar_class() -> attribute.Attribute(a) {
51
-
sketch.class([
52
-
sketch.display("flex"),
53
-
sketch.flex_direction("horizontal"),
54
-
sketch.align_items("center"),
55
-
sketch.gap(em(1)),
56
-
])
57
-
|> sketch.to_lustre
58
-
}
59
-
60
-
pub fn view(
61
-
projects: List(Project),
62
-
cache: sketch.Cache,
63
-
) -> element.Element(String) {
64
-
projects
65
-
|> list.map(fn(project) {
66
-
let links =
67
-
project.links
68
-
|> list.map(fn(link) {
69
-
html.a([attribute.href(link.url)], [
70
-
html.img([
71
-
attribute.alt(link.title),
72
-
attribute.src(link.img),
73
-
icon_class(),
74
-
]),
75
-
])
76
-
})
77
-
|> html.span([], _)
78
-
|> ssr(cache)
79
-
sketch.prepare(cache)
80
-
html.div([project_class(project.archived)], [
81
-
html.span([project_bar_class()], [
82
-
html.img([attribute.src(project.img), icon_class()]),
83
-
html.h2([], [element.text(project.title)]),
84
-
links,
85
-
]),
86
-
project.summary,
87
-
])
88
-
|> ssr(cache)
89
-
})
90
-
|> html.div([], _)
91
-
|> index.wrapper(cache)
92
19
}
93
20
94
21
pub fn all() -> List(Project) {
-40
src/website/page/blog.gleam
-40
src/website/page/blog.gleam
···
1
-
import birl
2
-
import gleam/int
3
-
import gleam/list
4
-
import lustre/attribute
5
-
import lustre/element
6
-
import lustre/element/html
7
-
import website/data/posts.{type Post}
8
-
9
-
pub fn view(posts: List(Post)) -> element.Element(String) {
10
-
posts
11
-
|> list.reverse
12
-
|> list.map(fn(post: Post) {
13
-
html.a([attribute.href("./blog/" <> post.id <> ".html")], [
14
-
html.div([], [
15
-
html.h1([], [element.text(post.title)]),
16
-
html.p([], [
17
-
element.text(
18
-
"Date posted: "
19
-
<> post.date_posted
20
-
|> day_to_string,
21
-
),
22
-
element.text("Author: " <> post.author),
23
-
]),
24
-
// html.p([], [element.text(post.summary.children)]),
25
-
]),
26
-
])
27
-
})
28
-
|> html.div([], _)
29
-
}
30
-
31
-
fn day_to_string(day: birl.Day) -> String {
32
-
day.date
33
-
|> int.to_string
34
-
<> "-"
35
-
<> day.month
36
-
|> int.to_string
37
-
<> "-"
38
-
<> day.year
39
-
|> int.to_string
40
-
}
-49
src/website/page/index.gleam
-49
src/website/page/index.gleam
···
1
-
import lustre/attribute
2
-
import lustre/element
3
-
import lustre/element/html
4
-
import sketch
5
-
import sketch/lustre.{ssr}
6
-
import sketch/size.{em}
7
-
8
-
pub fn link(text: String, url: String) -> element.Element(a) {
9
-
html.a([attribute.href(url)], [element.text(text)])
10
-
}
11
-
12
-
fn body_class() -> attribute.Attribute(a) {
13
-
sketch.class([
14
-
sketch.margin_left(em(15)),
15
-
sketch.margin_right(em(15)),
16
-
sketch.font_family("\"Inter\", sans-serif"),
17
-
sketch.font_weight("400"),
18
-
sketch.font_style("normal"),
19
-
])
20
-
|> sketch.to_lustre
21
-
}
22
-
23
-
pub fn wrapper(inner: element.Element(a), cache) -> element.Element(a) {
24
-
html.html([], [
25
-
html.head([], [
26
-
html.link([
27
-
attribute.rel("preconnect"),
28
-
attribute.href("https://fonts.googleapis.com"),
29
-
]),
30
-
html.link([
31
-
attribute.rel("preconnect"),
32
-
attribute.href("https://fonts.gstatic.com"),
33
-
]),
34
-
html.link([
35
-
attribute.href(
36
-
"https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap",
37
-
),
38
-
attribute.rel("stylesheet"),
39
-
]),
40
-
]),
41
-
html.body([body_class()], [inner]),
42
-
])
43
-
|> ssr(cache)
44
-
}
45
-
46
-
pub fn view(cache: sketch.Cache) -> element.Element(a) {
47
-
html.h1([], [element.text("Index")])
48
-
|> wrapper(cache)
49
-
}
-11
src/website/page/post.gleam
-11
src/website/page/post.gleam
···
1
-
import lustre/element
2
-
import lustre/element/html
3
-
import website/data/posts.{type Post}
4
-
5
-
pub fn view(post: Post) -> element.Element(String) {
6
-
html.div([], [
7
-
html.h1([], [element.text(post.title)]),
8
-
html.p([], [post.summary]),
9
-
html.p([], [post.content]),
10
-
])
11
-
}
-10
src/website/page/project.gleam
-10
src/website/page/project.gleam