@@ -75,7 +75,7 @@ def get_body_content(s: BeautifulSoup, test_path: Path = PYODIDE) -> str:
7575class Resource :
7676 """Base dataclass used for all resources."""
7777
78- path : PurePath
78+ name : str
7979 title : str = ""
8080 body : str = ""
8181 extra_head : str = ""
@@ -91,41 +91,55 @@ class Example(Resource):
9191 Meaning, HERE / "examples" / name / "index.html".
9292 """
9393
94- description : str = ""
9594 subtitle : str = ""
95+ description : str = ""
96+ author : str | None = None
9697
9798 def __post_init__ (self ) -> None :
9899 """Extract most of the data from the HTML file."""
99- # Title, subtitle, description come from the example's MD file.
100- index_md_file = HERE / "gallery/examples" / self .path / "index.md"
100+ # Title, subtitle, body come from the example's MD file.
101+ index_md_file = HERE / "gallery/examples" / self .name / "index.md"
101102 md_fm = frontmatter .load (index_md_file )
102103 self .title = md_fm .get ("title" , "" )
104+ self .author = md_fm .get ("author" , "" )
103105 self .subtitle = md_fm .get ("subtitle" , "" )
104106 md = MarkdownIt ()
105107 self .description = str (md .render (md_fm .content ))
106108
107109 # Main, extra head example's HTML file.
108- index_html_file = HERE / "gallery/examples" / self .path / "index.html"
110+ index_html_file = HERE / "gallery/examples" / self .name / "index.html"
109111 if not index_html_file .exists (): # pragma: nocover
110- raise ValueError (f"No example at { self .path } " )
112+ raise ValueError (f"No example at { self .name } " )
111113 soup = BeautifulSoup (index_html_file .read_text (), "html5lib" )
112114 self .extra_head = get_head_nodes (soup )
113115 self .body = get_body_content (soup )
114116
115117
118+ @dataclass
119+ class Author (Resource ):
120+ """Information about an author, from Markdown."""
121+
122+ def __post_init__ (self ) -> None :
123+ """Initialize the rest of the fields from the Markdown."""
124+ md_file = HERE / "gallery/authors" / f"{ self .name } .md"
125+ md_fm = frontmatter .load (md_file )
126+ self .title = md_fm .get ("title" , "" )
127+ md = MarkdownIt ()
128+ self .body = str (md .render (md_fm .content ))
129+
130+
116131@dataclass
117132class Page (Resource ):
118133 """A Markdown+frontmatter driven content page."""
119134
120135 subtitle : str = ""
121- body : str = ""
122136
123137 def __post_init__ (self ) -> None :
124138 """Extract content from either Markdown or HTML file."""
125- md_file = HERE / "pages" / f"{ self .path } .md"
126- html_file = HERE / "pages" / f"{ self .path } .html"
139+ md_file = HERE / "pages" / f"{ self .name } .md"
140+ html_file = HERE / "pages" / f"{ self .name } .html"
127141
128- # If this self.path resolves to a Markdown file, use it first
142+ # If this self.name resolves to a Markdown file, use it first
129143 if md_file .exists ():
130144 md_fm = frontmatter .load (md_file )
131145 self .title = md_fm .get ("title" , "" )
@@ -146,40 +160,49 @@ def __post_init__(self) -> None:
146160 if body_node and isinstance (body_node , Tag ):
147161 self .body = body_node .prettify ()
148162 else : # pragma: no cover
149- raise ValueError (f"No page at { self .path } " )
163+ raise ValueError (f"No page at { self .name } " )
150164
151165
152166@dataclass
153167class Resources :
154168 """Container for all resources in site."""
155169
156- examples : dict [PurePath , Example ] = field (default_factory = dict )
157- pages : dict [PurePath , Page ] = field (default_factory = dict )
170+ authors : dict [str , Author ] = field (default_factory = dict )
171+ examples : dict [str , Example ] = field (default_factory = dict )
172+ pages : dict [str , Page ] = field (default_factory = dict )
158173
159174
160- def get_sorted_examples ( ) -> list [PurePath ]:
175+ def get_sorted_paths ( target_dir : Path , only_dirs : bool = True ) -> list [PurePath ]:
161176 """Return an alphabetized listing of the examples."""
162- examples_dir = HERE / "gallery/examples"
163- examples = [e for e in examples_dir .iterdir () if e .is_dir ()]
164- return sorted (examples , key = attrgetter ("name" ))
177+ if only_dirs :
178+ paths = [e for e in target_dir .iterdir () if e .is_dir ()]
179+ else :
180+ paths = [e for e in target_dir .iterdir ()]
181+
182+ return sorted (paths , key = attrgetter ("name" ))
165183
166184
167185def get_resources () -> Resources :
168186 """Factory to construct all the resources in the site."""
169187 resources = Resources ()
170188
189+ # Load the authors
190+ authors = HERE / "gallery/authors"
191+ for author in get_sorted_paths (authors , only_dirs = False ):
192+ this_author = Author (name = author .stem )
193+ resources .authors [author .stem ] = this_author
194+
171195 # Load the examples
172- for example in get_sorted_examples ():
173- this_path = PurePath ( example . name )
174- this_example = Example (path = this_path )
175- resources .examples [this_path ] = this_example
196+ examples = HERE / "gallery/examples"
197+ for example in get_sorted_paths ( examples ):
198+ this_example = Example (example . stem )
199+ resources .examples [example . stem ] = this_example
176200
177201 # Load the Pages
178202 pages_dir = HERE / "pages"
179203 pages = [e for e in pages_dir .iterdir ()]
180204 for page in pages :
181- this_path = PurePath (page .stem )
182- this_page = Page (path = this_path )
183- resources .pages [this_path ] = this_page
205+ this_page = Page (name = page .stem )
206+ resources .pages [page .stem ] = this_page
184207
185208 return resources
0 commit comments