$def with (project, repo, readme, package_releases, pyproject, api_python, test_results, test_coverage, mentions, issues)
$var breadcrumbs = ("projects", "Projects")
$ title = project
$var title_classes = ["p-name"]
$var article_classes = ["h-ragt-ag-project"]
<style>
/* h2 {
display: none; } */
#files {
background-color: #073642;
font-family: UbuntuMonoPowerline;
padding: .5em; }
#files ul, .commits, .releases {
list-style: none;
padding-left: 0; }
#files ul {
margin: 0; }
#files p {
font-size: .8em;
margin-bottom: 0; }
.testindicator {
border-radius: 50%;
display: inline-block;
height: .9em;
width: .9em; }
aside small strong {
text-transform: small-caps; }
</style>
$ likes = 0
$for mention in mentions:
$if mention["data"]["comment_type"][0] == "like":
$ likes += 1
$elif mention["data"]["comment_type"][0] == "like":
$ likes += 1
<p><a href=/projects/$project/issues>Issues</a>
$if issues:
<sub><small>$issues</small></sub>
</p>
</p>
$if likes:
<p>$emoji.emojize(":red_heart:") <sub>$likes</sub></p>
$# <div>
$# $ data = mention["data"]
$# $if name := data.get("name", None):
$# <h3>$name</h3>
$# $if data:
$# $ a = data["author"]
$# $ comment_type = data["comment_type"][0]
$# $if comment_type == "like":
$# $emoji.emojize(":red_heart:")
$# $if content := data.get("content"):
$# <div>$:content</div>
$# $ published = data["published"][0]
$# <small>Opened <a href=$data["url"]><time class=dt-published
$# datetime="$published.isoformat()">$published.diff_for_humans()</time></a>
$# $if data:
$# by <a href=$a["url"]>$a.get("name", a["url"])</a>,
$# $if comment := data.get("comment"):
$# $ comment_count = len(comment)
$# $if comment_count:
$# 💬 $comment_count comment$("s" if comment_count > 1 else "")
$# </small>
$# </div>
$if repo.exists():
$ commits = list(repo.log().values())
$if commits:
$ commit = commits[0]
$ author_url = commit["author_email"]
$if "@" in author_url:
$ author_url = f"mailto:{author_url}"
$else:
$ author_url = f"https://{author_url}"
<div class=h-entry>
$# <a class=u-author href="$author_url">$commit["author_name"]</a>
<span class=p-name>$:str(mkdn(commit["message"]))[3:-4]</span>
$if "errors" in test_results:
$if test_results["errors"]:
$ test_color = "red"
$ test_indicator = "■"
$ plural = ""
$if test_results["errors"] > 1:
$ plural = "s"
$ test_msg = f"{test_results['errors']} test{plural} of {test_results['tests']} failing"
$else:
$ test_color = "green"
$ test_indicator = "●"
$ plural = ""
$if test_results["tests"] > 1:
$ plural = "s"
$ test_msg = f"{test_results['tests']} test{plural} passing"
<span style=color:$test_color>$:test_indicator</span>
$test_msg in $test_results["time"]<small>s</small>
<small><small>
<a class=u-url href=/projects/$project/commits/$commit["hash"]>\
<code>$commit["hash"][:7].upper()</code> <time class=dt-published \
datetime=$commit["timestamp"].isoformat()>\
$:commit["timestamp"].diff_for_humans().replace(" ", " ")</time></a>
</small></small>
<a href=/projects/$project/commits><strong>$len(repo.log())</strong> commits</a>
</div>
$ files = sorted(repo.files)
$if files:
<div id=files>
$ ignorable_files = (
$ ".github",
$ ".gitignore",
$ "README",
$ "README.md",
$ "pyproject.toml",
$ "pyrightconfig.json",
$ "package.json",
$ "tsconfig.json",
$ "webpack.config.js",
$ "eslintrc.js",
$ "eslintrc.json",
$ "eslintrc.yml",
$ )
$ prev_file = None
<ul>
$ unique_files = [f for f in files if str(f).partition("/")[0] not in ignorable_files]
$for file in unique_files:
$ file, is_dir, _ = str(file).partition("/")
$if file == prev_file:
$continue
<li><a href=/projects/$project/files/$file>$file</a>\
$if is_dir:
/
</li>
$ prev_file = file
</ul>
$ prev_file = None
$ known_files = [f for f in files if str(f).partition("/")[0] in ignorable_files]
<p style=color:#586e75>\
$for file in known_files:
$ file, is_dir, _ = str(file).partition("/")
$if file == prev_file:
$continue
<a href=/projects/$project/files/$file>$file</a>\
$if is_dir:
/\
$ prev_file = file
$if not loop.last:
,
</p>
</div>
$# $ git_url = f"{tx.origin}/code/projects/{project}.git"
$# <pre style=text-align:right><small>$git_url <a href=""
$# onclick="navigator.clipboard.writeText('$git_url'); return false">📋</a></small></pre>
$if readme:
<link rel=stylesheet href=$tx.origin/static/solarized.css media=screen>
<div>$:mkdn(readme)</div>
$if api_members := api_python.get("members"):
$if readme:
<hr>
$ _imports, _globals, _exceptions, _functions, _classes = api_members
<img style=float:right;width:12em src=/projects/$project/api/$(api_python["name"]).svg>
<h3><a href=/projects/$project/api/$api_python["name"]>$api_python["name"]</a></h3>
$if mod_doc := api_python["mod"].get("doc"):
$:mkdn(mod_doc.partition("\n\n")[0])
<small>
$for module in set(dict(_imports).keys()).difference(stdlib_module_names).difference(set(api_python["descendants"].keys())):
$module\
$if not loop.last:
,
</small></p>
$ metrics = api_python["mod"]["metrics"]
<p><code>$metrics["lines"][1]</code> <abbr title="Logical Lines Of Code">LLOC</abbr>,
<abbr title=$round(metrics["maintainability"])>
$if metrics["maintainability"] >= 19:
highly maintainable
$elif metrics["maintainability"] >= 9:
moderately maintainable
$else:
difficult to maintain
</abbr>
</p>
$for func_name, func_details in _functions:
$if func_name not in api_python["mod"]["all"]:
$continue
<h4 style="margin-bottom:0;padding:0 2em;text-indent:-2em"><a
href=/projects/$project/api/$api_python["name"]#$func_name>$func_name</a>\
<em style=font-weight:normal>$func_details["sig"]</em></h4>
<div style=font-size:.8em>
$if func_doc := func_details.get("doc"):
$:mkdn(func_doc.partition("\n\n")[0])
</div>
<ul>
$for descendant, desc_details in api_python["descendants"].items():
$if descendant == "__main__":
$continue
<li>
<h5><a href=/projects/$project/api/$api_python["name"]/$descendant>$descendant</a></h5>
$if desc_doc := desc_details["mod"].get("doc"):
$:mkdn(desc_doc.partition("\n\n")[0])
$ metrics = desc_details["mod"]["metrics"]
<p><code>$metrics["lines"][1]</code> <abbr title="Logical Lines Of Code">LLOC</abbr>,
<abbr title=$round(metrics["maintainability"])>
$if metrics["maintainability"] >= 19:
highly maintainable
$elif metrics["maintainability"] >= 9:
moderately maintainable
$else:
difficult to maintain
</abbr>
<br>
<small><code>
$for obj_name, obj_complexity in metrics["complexity"].items():
$obj_name $obj_complexity
</code></small>
</p>
</li>
</ul>
$var title = title
$def aside():
$if pyproject:
$ py_project = pyproject["tool"]["poetry"]
$ py_project_name = py_project.pop("name")
$# title += f" <code style=font-size:.5em>{py_project.pop('version')}</code>"
<p><big>$py_project.pop("description")</big><br>
$if keywords := py_project.pop("keywords", None):
<small>
$for keyword in keywords:
$keyword\
$if not loop.last:
,
</small>
</p>
<p><small><strong>Package</strong><br>
<small><code>$py_project_name</code>
$for source in py_project.pop("source", []):
$if source["name"] == "main":
<code>@<a href="$source['url']">$source["url"].removeprefix("https://")</a></code>
</small></small></p>
$if py_deps := py_project.pop("dependencies", None):
<p><small><strong>Requires</strong><br>
<small><code>python $py_deps.pop("python")</code><br>
<small>
$for dep, version in sorted(py_deps.items()):
$ dep_nobreak = dep.replace("-", "‍-‍")
<code><a href=https://pypi.org/project/$dep>$:dep_nobreak</a></code>\
$if not loop.last:
,
</small></small></small></p>
$ plugins = py_project.pop("plugins", None)
$ scripts = py_project.pop("scripts", None)
$if plugins or scripts:
<p><small><strong>Provides</strong><br>
<small>
$if plugins:
$if webapps := plugins.pop("webapps", None):
webapps (\
$for webapp, webapp_callable in webapps.items():
$ webapp_path = webapp_callable.replace(".", "/").replace(":", "#")
<a href="/projects/$project/api/$webapp_path">$webapp</a>\
$if not loop.last:
, \
)
$if websites := plugins.pop("websites", None):
websites (\
$for website, website_callable in websites.items():
$ website_path = website_callable.replace(".", "/").replace(":", "#")
<a href="/projects/$project/api/$website_path">$website</a>\
$if not loop.last:
, \
)
$if scripts:
scripts (\
$for script, script_callable in scripts.items():
$ script_path = script_callable.replace(".", "/").replace(":", "#")
<a href="/projects/$project/api/$script_path">$script</a>\
$if not loop.last:
, \
)
$if plugins or scripts:
</small></small></p>
$ license = py_project.pop("license")
$ licenses = {"0BSD": '<abbr title="Berkeley Software Distribution">BSD</abbr> Zero Clause License',
$ "BSD-2-Clause": '<abbr title="Berkeley Software Distribution">BSD</abbr> 2-Clause "Simplified" License',
$ "BSD-3-Clause": '<abbr title="Berkeley Software Distribution">BSD</abbr> 3-Clause "Modified" License',
$ "AGPL-3.0-or-later": 'GNU <abbr title="Affero General Public License">AGPL</abbr> v3.0 or later'}
<p><small><strong>License</strong><br>
<small><a href=https://spdx.org/licenses/$(license).html>\
<code>$:licenses[license]</code></a></small></small></p>
$if package_releases:
$ release, entry = package_releases[0]
<p class=h-entry><small><strong>Releases <code>(<a
href=/projects/$project/releases>$len(package_releases)</a>)</code></strong><br>
<span class=p-name>v$release</span>
<a class=u-url href=/projects/$project/releases/$release><time
class=dt-published datetime=$entry["published"][0].isoformat()>\
$:entry["published"][0].diff_for_humans().replace(" ", " ")</time></a>
</small>
</p>
$if not (pyproject or package_releases):
<div></div>
$var aside = aside()