-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow specifying input / output directories when building website (#667)
### Summary Beforehand, these were hard-coded. Now you can install the `ecosystem` package from this repo, then run: ```sh ecosystem build --resources ecosystem/resources --output website ``` --------- Co-authored-by: Eric Arellano <[email protected]>
- Loading branch information
1 parent
310a08f
commit 20e9a85
Showing
7 changed files
with
138 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,15 @@ | ||
"""Ecosystem main module.""" | ||
import fire | ||
|
||
from ecosystem.cli import CliMembers, CliCI, build_website | ||
|
||
|
||
def main(): | ||
# pylint: disable=missing-function-docstring | ||
fire.Fire( | ||
{ | ||
"members": CliMembers, | ||
"build": build_website, | ||
"ci": CliCI, | ||
} | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
"""CLI.""" | ||
from .members import CliMembers | ||
from .website import CliWebsite | ||
from .website import build_website | ||
from .ci import CliCI |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,114 +1,132 @@ | ||
"""CliWebsite class for controlling all CLI functions.""" | ||
from __future__ import annotations | ||
|
||
|
||
from pathlib import Path | ||
from typing import Optional | ||
from typing import Any | ||
import json | ||
import os | ||
import toml | ||
|
||
from jinja2 import Environment, FileSystemLoader | ||
from jinja2 import Environment, PackageLoader, Template | ||
|
||
from ecosystem.daos import DAO | ||
from ecosystem.models.repository import Repository | ||
|
||
|
||
class CliWebsite: | ||
"""CliMembers class. | ||
Entrypoint for all CLI website commands. | ||
def build_website(resources: str, output: str) -> None: | ||
""" | ||
Generates the ecosystem web page from data in `resources` dir, writing to `output` dir. | ||
""" | ||
resources_dir = Path(resources) | ||
html = _build_html(*_load_from_file(resources_dir)) | ||
Path(output, "index.html").write_text(html) | ||
|
||
Each public method of this class is CLI command | ||
and arguments for method are options/flags for this command. | ||
|
||
Ex: `python manager.py website build_website` | ||
def _load_from_file( | ||
resources_dir: Path, | ||
) -> tuple[list[Repository], dict[str, Any], dict[str, str], dict[str, Template]]: | ||
""" | ||
Loads website data from file. | ||
Returns: | ||
* Projects: List of Repository objects from `members` folder. | ||
* Web data: Strings (title / descriptions etc.) from `website.toml`. | ||
* Label descriptions: from `labels.json`. | ||
* Jinja templates: from `html_templates` folder. | ||
""" | ||
# Projects list | ||
dao = DAO(path=resources_dir) | ||
projects = sorted( | ||
dao.get_all(), | ||
key=lambda item: ( | ||
-(item.stars or 0), | ||
item.name, | ||
), | ||
) | ||
|
||
def __init__(self, root_path: Optional[str] = None): | ||
"""CliWebsite class.""" | ||
self.current_dir = root_path or os.path.abspath(os.getcwd()) | ||
resources_dir = Path(self.current_dir, "ecosystem/resources") | ||
self.dao = DAO(path=resources_dir) | ||
self.label_descriptions = { | ||
item["name"]: item["description"] | ||
for item in json.loads(Path(resources_dir, "labels.json").read_text()) | ||
} | ||
self.web_data = toml.loads((resources_dir / "website.toml").read_text()) | ||
|
||
def build_website(self): | ||
"""Generates the ecosystem web page reading the TOML files.""" | ||
# pylint: disable=too-many-locals | ||
environment = Environment(loader=FileSystemLoader("ecosystem/html_templates/")) | ||
projects = self.dao.storage.read() | ||
projects_sorted = sorted( | ||
projects.items(), | ||
key=lambda item: ( | ||
-item[1].stars if item[1].stars is not None else 0, | ||
item[1].name, | ||
), | ||
) | ||
templates = { | ||
"website": environment.get_template("webpage.html.jinja"), | ||
"card": environment.get_template("card.html.jinja"), | ||
"tag": environment.get_template("tag.html.jinja"), | ||
"link": environment.get_template("link.html.jinja"), | ||
} | ||
sections = {group["id"]: group for group in self.web_data["groups"]} | ||
for section in sections.values(): | ||
section.setdefault("html", "") | ||
|
||
max_chars_description_visible = 400 | ||
min_chars_description_hidden = 100 | ||
count_read_more = 1 | ||
for _, repo in projects_sorted: | ||
# Card tags | ||
tags = "" | ||
for index, label in enumerate(repo.labels): | ||
tags += templates["tag"].render( | ||
color="purple", | ||
text=label, | ||
tooltip=self.label_descriptions[label], | ||
# Sometimes tooltips are clipped by the browser window. | ||
# While not perfect, the following line solves 95% of cases | ||
alignment="bottom" if (index % 3) == 2 else "bottom-left", | ||
) | ||
|
||
# Card links | ||
links = "" | ||
for url, link_text in ( | ||
(repo.url, "repository"), | ||
(repo.website, "website"), | ||
(repo.reference_paper, "paper"), | ||
(repo.documentation, "documentation"), | ||
): | ||
if url: | ||
links += templates["link"].render(url=url, place=link_text) | ||
|
||
# Card description | ||
if ( | ||
len(repo.description) - max_chars_description_visible | ||
>= min_chars_description_hidden | ||
): | ||
description = [ | ||
repo.description[:max_chars_description_visible], | ||
repo.description[max_chars_description_visible:], | ||
] | ||
id_read_more = str(count_read_more) | ||
count_read_more += 1 | ||
else: | ||
description = [repo.description, ""] | ||
id_read_more = "None" | ||
|
||
# Create the card | ||
card = templates["card"].render( | ||
title=repo.name, | ||
tags=tags, | ||
description_visible=description[0], | ||
description_hidden=description[1], | ||
id_read_more=id_read_more, | ||
links=links, | ||
# Label descriptions | ||
label_descriptions = { | ||
item["name"]: item["description"] | ||
for item in json.loads(Path(resources_dir, "labels.json").read_text()) | ||
} | ||
|
||
# Website strings | ||
web_data = toml.loads((resources_dir / "website.toml").read_text()) | ||
|
||
# Jinja templates | ||
environment = Environment(loader=PackageLoader("ecosystem", "html_templates/")) | ||
templates = { | ||
"website": environment.get_template("webpage.html.jinja"), | ||
"card": environment.get_template("card.html.jinja"), | ||
"tag": environment.get_template("tag.html.jinja"), | ||
"link": environment.get_template("link.html.jinja"), | ||
} | ||
return projects, web_data, label_descriptions, templates | ||
|
||
|
||
def _build_html(projects, web_data, label_descriptions, templates) -> str: | ||
""" | ||
Take all data needed to build the website and produce a HTML string. | ||
""" | ||
sections = {group["id"]: group for group in web_data["groups"]} | ||
for section in sections.values(): | ||
section.setdefault("html", "") | ||
|
||
max_chars_description_visible = 400 | ||
min_chars_description_hidden = 100 | ||
count_read_more = 1 | ||
for repo in projects: | ||
# Card tags | ||
tags = "" | ||
for index, label in enumerate(repo.labels): | ||
tags += templates["tag"].render( | ||
color="purple", | ||
text=label, | ||
tooltip=label_descriptions[label], | ||
# Sometimes tooltips are clipped by the browser window. | ||
# While not perfect, the following line solves 95% of cases | ||
alignment="bottom" if (index % 3) == 2 else "bottom-left", | ||
) | ||
|
||
# Adding the card to a section | ||
sections[repo.group]["html"] += card | ||
# Card links | ||
links = "" | ||
for url, link_text in ( | ||
(repo.url, "repository"), | ||
(repo.website, "website"), | ||
(repo.reference_paper, "paper"), | ||
(repo.documentation, "documentation"), | ||
): | ||
if url: | ||
links += templates["link"].render(url=url, place=link_text) | ||
|
||
# Card description | ||
if ( | ||
len(repo.description) - max_chars_description_visible | ||
>= min_chars_description_hidden | ||
): | ||
description = [ | ||
repo.description[:max_chars_description_visible], | ||
repo.description[max_chars_description_visible:], | ||
] | ||
id_read_more = str(count_read_more) | ||
count_read_more += 1 | ||
else: | ||
description = [repo.description, ""] | ||
id_read_more = "None" | ||
|
||
return templates["website"].render( | ||
header=self.web_data["header"], | ||
sections=sections.values(), | ||
# Create the card | ||
card = templates["card"].render( | ||
title=repo.name, | ||
tags=tags, | ||
description_visible=description[0], | ||
description_hidden=description[1], | ||
id_read_more=id_read_more, | ||
links=links, | ||
) | ||
|
||
# Adding the card to a section | ||
sections[repo.group]["html"] += card | ||
|
||
return templates["website"].render( | ||
header=web_data["header"], | ||
sections=sections.values(), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters