File size: 3,617 Bytes
9d8008e
 
 
 
 
 
 
 
0760113
9d8008e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0760113
 
 
 
9d8008e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
073cfb5
 
 
 
 
 
9d8008e
 
 
 
 
 
 
 
 
 
 
 
 
0760113
9d8008e
 
 
 
 
 
 
 
 
 
 
0760113
9d8008e
0760113
 
 
 
 
 
 
 
9d8008e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import inspect
import re
from dataclasses import dataclass
from functools import cached_property
from pathlib import Path
from types import ModuleType

import fasthtml.common as fh
from fasthtml.common import H1, H3, A, Code, Div, Hgroup, P, Pre

from tutorial import utils


@dataclass
class Example:
    module: ModuleType
    name: str

    @cached_property
    def title(self):
        return self.name.replace("_", " ").title()

    @cached_property
    def desc(self):
        return self.module.DESC

    @cached_property
    def doc(self):
        return self.module.DOC

    @cached_property
    def height(self):
        return getattr(self.module, "HEIGHT", "500px")

    @cached_property
    def slug(self):
        return self.name.replace("_", "-")

    @cached_property
    def htmx_url(self):
        return getattr(self.module, "HTMX_URL", f"https://htmx.org/examples/{self.slug}/")

    @cached_property
    def start_url(self):
        module, slug = self.module, self.slug
        url = getattr(module, "START_URL", module.app.routes[1].path)
        return f"/{slug}{url}"

    def create_routes(self, main_app: fh.FastHTML):
        sub_app, slug = self.module.app, self.slug
        sub_app.htmlkw = main_app.htmlkw
        sub_app.hdrs += (
            utils.alpine(),
            fh.Script(src="/script.js"),
            fh.Script(f"init_sub_page('{slug}')"),
            utils.piwik(),
        )
        main_app.mount(f"/{slug}", sub_app)
        main_app.get(f"/{slug}")(self.main_page)

    def main_page(self, tab: str = "explain"):
        module = self.module
        if tab == "code":
            code = Path(module.__file__).read_text().split("DESC = ")[0]
            code = code.strip().replace("# fmt: on\n", "").replace("# fmt: off\n", "")
            content = Pre(Code(code))
        else:
            doc = _replace_code_blocks(module, self.doc)
            content = Div(doc, cls="marked")

        return fh.Main(cls="container", x_cloak=True)(
            Hgroup(H1(self.title), P(self.desc)),
            Div(
                *utils.concat(
                    A("HOME", href="/"),
                    A("Explain", href=f"/{self.slug}?tab=explain"),
                    A("Code", href=f"/{self.slug}?tab=code"),
                    A("Htmx Docs", href=self.htmx_url),
                    A("Full screen", href=self.start_url),
                )
            ),
            Div(cls="grid")(
                Div(content, style="max-height:80vh;overflow:scroll"),
                Div(
                    Div(cls="grid")(
                        fh.Label(fh.Input(type="checkbox", role="switch", x_model="showRequests"), "Show requests"),
                    ),
                    Div(fh.Iframe(src=self.start_url, height=self.height, width="100%")),
                ),
                Div(**{"x-show": "showRequests"})(
                    H3("Server Calls"),
                    Div(Div(id="request-list"), style="height:80vh;overflow:scroll"),
                ),
            ),
        )


def _replace_code_blocks(module, doc):
    """Replace placeholders by real implementations"""
    return re.sub("::([a-zA-Z_0-9\s]+)::", lambda x: _code_block(module, x.group(1).strip().split()), doc)


def _code_block(module, function_names):
    code = ""
    for o in function_names:
        func = getattr(module, o)
        if callable(func):
            func = getattr(func, "__wrapped__", func)
            code += inspect.getsource(func)
        else:
            code += str(func).strip()
        code += "\n"
    code = code.strip()
    return f"```\n{code.strip()}\n```"