commit af3c83b
Artur Manuel
·
2026-07-30 18:49:01 +0000 UTC
parent 1a7fa44
gtm: add a bunch of things :3
9 files changed,
+127,
-66
+1,
-0
1@@ -0,0 +1 @@
2+
+4,
-7
1@@ -1,13 +1,10 @@
2 {
3- "title": "My cool capsule",
4- "description": "Made with paws :3",
5+ "default_title": "My cool capsule",
6+ "default_description": "Made with paws :3",
7 "content_dir": "./content",
8 "templates_dir": "./templates",
9- "page_settings": {
10- "ascii_fop": {
11- "template": "none"
12- }
13- },
14+ "assets_dir": "./assets",
15+ "output_dir": "./output",
16 "extra": {
17 "fav_frb_creators": [
18 "PowerPoint Rap Battles",
+17,
-0
1@@ -0,0 +1,17 @@
2+# BEHOLD, foppy
3+
4+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⠀⠀⠀
5+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⡴⠻⣀⠀⠀
6+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡴⡆⠀⠀⣦⡀⠀⠀⠀⠀⠉⠓⢄⣠⠼⠛⠂
7+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡞⠀⣇⠀⠀⡇⢳⡀⠀⠀⠀⠀⠀⣼⠁⠀⠀⠀
8+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠇⠀⠈⠉⠉⠁⠀⡇⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀
9+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢺⡀⠀⡇⠀⡇⠀⠀⢧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
10+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠓⢢⠀⠀⠀⢠⠶⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
11+⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠗⠒⣆⠀⠀⠀⠀⡼⠀⠀⠀⠀⢧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
12+⠀⠀⠀⣿⠀⠀⠀⠀⠀⠀⢀⡴⠃⠀⠀⣸⠀⠀⠀⠀⡇⠀⠀⠀⠀⠈⢧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀
13+⠀⠀⣴⠿⢄⡀⠀⠀⠀⣰⠃⠀⠀⠀⢠⠇⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠳⣀⠀⠀⠀⠀⠀⠀⠀⠀
14+⣀⣔⠋⠀⢀⡨⠗⠂⠀⡇⠀⠀⠀⠀⠸⡀⠀⠀⠀⠀⡇⠀⣇⡧⠼⠤⠤⢄⡸⡁⠀⠀⠀⠀⠀⠀⠀
15+⠀⠀⠉⣧⠋⠀⠀⠀⠀⢱⡀⠀⠀⠀⠀⠙⠒⠦⠤⠤⠖⠋⠁⠀⠀⠀⠀⠀⠘⡇⠀⠀⠀⠀⠀⠀⠀
16+⠀⠀⠀⠛⠀⠀⠀⠀⠀⠀⠙⠢⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠞⠁⠀⠀⠀⠀⠀⠀⠀
17+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠑⠒⠦⢄⣀⡀⠀⠀⠀⠀⣀⠔⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀
18+⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+1,
-0
1@@ -0,0 +1 @@
2+# hai :3
+7,
-0
1@@ -0,0 +1,7 @@
2+I'm a red foppy :3
3+
4+## Here are my favourite rap battle creators!
5+
6+{%- for frb_creator in extra.fav_frb_creators %}
7+- {{ frb_creator }}
8+{%- endfor %}
+1,
-41
1@@ -1,44 +1,4 @@
2-import sys
3-from pathlib import Path
4-
5-import click
6-
7-
8-EXAMPLE_GTM_CONFIG: str = """
9-{
10- "title": "Example capsule",
11- "description": "I would put more information about my capsule here",
12- "content_dir": "./content",
13- "templates_dir": "./templates",
14- "assets_dir": "./assets",
15- "page_settings": {},
16- "extra": {}
17-}
18-"""
19-
20-
21-@click.group()
22-def run():
23- pass
24-
25-
26-@run.command()
27-@click.option('--path', type=click.Path(exists=True, file_okay=False, writable=True, path_type=Path, executable=True), default=".")
28-def build(path: str):
29- """Build the Gemini capsules into your output directory"""
30- sys.stderr.write("Hello, currently I have nothing written for here. Sorry for the inconvenience :(\n")
31-
32-@run.command()
33-@click.option('--path', type=click.Path(exists=False), default=".")
34-def init(path: str):
35- """Initialise a gtm project"""
36- output_path = Path(path)
37- output_path.mkdir(0o755, parents=True)
38- output_config_file = output_path / "gtm.json"
39- output_config_file.write_text(EXAMPLE_GTM_CONFIG)
40- for dir in ["assets", "content", "templates"]:
41- (output_path / dir).mkdir(0o755)
42-
43+from gtm.commands import run
44
45 if __name__ == "__main__":
46 run()
+58,
-0
1@@ -0,0 +1,58 @@
2+import shutil
3+import os
4+from gtm.config import Config
5+from pathlib import Path
6+
7+import click
8+
9+
10+EXAMPLE_GTM_CONFIG: str = """
11+{
12+ "title": "Example capsule",
13+ "description": "I would put more information about my capsule here",
14+ "content_dir": "./content",
15+ "templates_dir": "./templates",
16+ "assets_dir": "./assets",
17+ "page_settings": {},
18+ "extra": {}
19+}
20+"""
21+
22+
23+@click.group()
24+def run():
25+ pass
26+
27+
28+@run.command()
29+@click.option(
30+ "--config-path",
31+ type=click.Path(path_type=Path, exists=True),
32+ default="./gtm.json",
33+)
34+def build(config_path: Path):
35+ """Build the Gemini capsules into your output directory"""
36+ config = Config.loads(config_path.read_text())
37+ if not os.path.exists(config.output_dir):
38+ Path(config.output_dir).mkdir(0o755, parents=True)
39+ for dirpath, _, filenames in os.walk(config.content_dir):
40+ for filename in filenames:
41+ output_path = Path(config.output_dir, filename)
42+ if output_path.stem.startswith(".") or output_path.suffix != "gmi":
43+ continue
44+ output_path.parent.mkdir(0o755, parents=True, exist_ok=True)
45+ output_path.touch(0o644)
46+ content = Path(dirpath, filename).read_text()
47+ output_path.write_text(content)
48+
49+
50+@run.command()
51+@click.option("--path", type=click.Path(exists=False, path_type=Path), default=".")
52+def init(path: Path):
53+ """Initialise a gtm project"""
54+ path.mkdir(0o755, parents=True)
55+ config_file = path / "gtm.json"
56+ config_file.touch(0o644)
57+ config_file.write_text(EXAMPLE_GTM_CONFIG)
58+ for dir in ["assets", "content", "templates"]:
59+ (path / dir).mkdir(0o755)
+9,
-12
1@@ -3,26 +3,23 @@ import json
2 from typing import Any, Self
3 from os import PathLike
4
5-from gtm.page import Page
6-
7-
8 class Config:
9 def __init__(
10 self,
11 content_dir: str | PathLike = "./content",
12 templates_dir: str | PathLike = "./templates",
13 assets_dir: str | PathLike = "./assets",
14+ output_dir: str | PathLike = "./output",
15 default_title: str | None = None,
16 default_description: str | None = None,
17- page_settings: dict[str, Page] = {},
18 extra: dict[str, Any] = {},
19 ):
20 self.content_dir = content_dir
21 self.templates_dir = templates_dir
22 self.assets_dir = assets_dir
23+ self.output_dir = output_dir
24 self.default_title = default_title
25 self.default_description = default_description
26- self.page_settings = page_settings
27 self.extra = extra
28 pass
29
30@@ -32,13 +29,13 @@ class Config:
31 doc = json.loads(text)
32 if not isinstance(doc, dict):
33 raise ValueError("Expected JSON config to be a set")
34- config.assets_dir = doc["assets_dir"]
35- config.templates_dir = doc["templates_dir"]
36- config.content_dir = doc["content_dir"]
37- config.default_title = doc["default_title"]
38- config.default_description = doc["default_description"]
39- config.page_settings = doc["page_settings"]
40- config.extra = doc["extra"]
41+ config.assets_dir = doc.get("assets_dir") or config.assets_dir
42+ config.templates_dir = doc.get("templates_dir") or config.templates_dir
43+ config.content_dir = doc.get("content_dir") or config.content_dir
44+ config.output_dir = doc.get("output_dir") or config.output_dir
45+ config.default_title = doc.get("default_title") or config.default_title
46+ config.default_description = doc.get("default_description") or config.default_description
47+ config.extra = doc.get("extra")
48 return config
49
50 @classmethod
+29,
-6
1@@ -2,8 +2,12 @@ from gtm.config import Config
2
3 config_text = '''
4 {
5- "title": "My cool capsule",
6- "description": "Made with paws :3",
7+ "default_title": "My cool capsule",
8+ "default_description": "Made with paws :3",
9+ "content_dir": "./content",
10+ "templates_dir": "./templates",
11+ "assets_dir": "./assets",
12+ "output_dir": "./output",
13 "extra": {
14 "fav_frb_creators": [
15 "PowerPoint Rap Battles",
16@@ -23,8 +27,27 @@ config_text = '''
17
18 def test_load_config_from_text():
19 config = Config.loads(config_text)
20+ assert isinstance(config, Config)
21 assert config.default_title == "My cool capsule"
22- creators = config.extra.get("fav_frb_creators")
23- assert creators and isinstance(creators, list)
24- for creator in creators:
25- assert creator in ["PowerPoint Rap Battles", "AdamDRB", "worms_of_cans", "Indie Game Rap Battles", "Eddiefrb"]
26+ assert config.default_description == "Made with paws :3"
27+ assert config.content_dir == "./content"
28+ assert config.assets_dir == "./assets"
29+ assert config.templates_dir == "./templates"
30+ assert config.output_dir == "./output"
31+ assert config.extra.get("fav_frb_creators")
32+ fav_frb_creators = config.extra.get("fav_frb_creators")
33+ assert isinstance(fav_frb_creators, list)
34+ assert fav_frb_creators == [
35+ "PowerPoint Rap Battles",
36+ "AdamDRB",
37+ "worms_of_cans",
38+ "Indie Game Rap Battles",
39+ "Eddiefrb",
40+ ]
41+ nav_links = config.extra.get("nav_links")
42+ assert isinstance(nav_links, list)
43+ assert nav_links == [
44+ "index",
45+ "ascii_fop",
46+ "hello",
47+ ]