-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Deployed 3f968c3 with MkDocs version: 1.6.1
- Loading branch information
Unknown
committed
Oct 17, 2024
0 parents
commit 7e73695
Showing
1,428 changed files
with
25,188 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
Large diffs are not rendered by default.
Oops, something went wrong.
Binary file not shown.
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 |
---|---|---|
@@ -0,0 +1,148 @@ | ||
import json | ||
from pathlib import Path | ||
from typing import TYPE_CHECKING | ||
|
||
import mkdocs_gen_files | ||
import natsort | ||
import numpy as np | ||
|
||
if TYPE_CHECKING: | ||
from cmap import _catalog | ||
from cmap import Colormap | ||
from cmap._util import report | ||
|
||
# TODO: convert to jinja | ||
TEMPLATE = """# {name} | ||
{aliases} | ||
{info} | ||
| category | license | authors | source | | ||
| --- | --- | --- | --- | | ||
| {category} | {license} | {authors} | {source} | | ||
```python | ||
from cmap import Colormap | ||
cm = Colormap('{name}') # case insensitive | ||
``` | ||
{{{{ cmap: {name} 40 }}}} | ||
{{{{ cmap_gray: {name} 30 }}}} | ||
{{{{ cmap_sineramp: {name} }}}} | ||
## Perceptual Lightness | ||
<canvas class="linearity-chart cmap-chart" data-cmap-name="{name}" width="800" height="350"></canvas> | ||
<p style="text-align: center;"> | ||
<em style="font-size: small; color: gray;"> | ||
L* measured in | ||
<a href="https://onlinelibrary.wiley.com/doi/10.1002/col.20227">CAM02 Uniform Color Space (CAM02-UCS)</a> | ||
</em> | ||
</p> | ||
## RGB components | ||
<canvas class="rgb-chart cmap-chart" data-cmap-name="{name}" width="800" height="350"></canvas> | ||
## Hue & Saturation | ||
<canvas class="hsl-chart cmap-chart" data-cmap-name="{name}" width="800" height="350"></canvas> | ||
<script> | ||
window.cmap_data = {data}; | ||
<!-- Note: this is here because of `navigation.instant` in the mkdocs settings --> | ||
typeof(initCharts) !== 'undefined' && initCharts(); | ||
</script> | ||
""" | ||
|
||
DOCS = Path(__file__).parent | ||
LICENSE_URL = { | ||
"CC0": "https://creativecommons.org/publicdomain/zero/1.0/", | ||
"CC-BY-4.0": "https://creativecommons.org/licenses/by/4.0/", | ||
"Apache-2.0": "https://www.apache.org/licenses/LICENSE-2.0", | ||
"MIT": "https://opensource.org/licenses/MIT", | ||
"BSD-3-Clause": "https://opensource.org/licenses/BSD-3-Clause", | ||
"BSD-2-Clause": "https://opensource.org/licenses/BSD-2-Clause", | ||
"PSF": "https://opensource.org/licenses/Python-2.0", | ||
} | ||
|
||
|
||
INCLUDE_DATA = ( | ||
"x", | ||
"color", | ||
"R", | ||
"G", | ||
"B", | ||
"J", | ||
"lightness_derivs", | ||
"hue", | ||
"saturation", | ||
"chroma", | ||
) | ||
|
||
|
||
def build_catalog(catalog: "_catalog.Catalog") -> None: | ||
nav = mkdocs_gen_files.Nav() | ||
for name in natsort.natsorted(catalog, alg=natsort.ns.IGNORECASE): | ||
if ":" not in name: | ||
continue | ||
try: | ||
info = catalog[name] | ||
category = info.category | ||
license_: str = info.license | ||
except KeyError as e: | ||
raise KeyError(f"Missing info for {name}: {e}") from e | ||
|
||
if info.qualified_name.lower() != name.lower(): | ||
# skip aliases | ||
continue | ||
|
||
source = info.source | ||
source = f"[{source}]({source})" if source.startswith("http") else f"`{source}`" | ||
authors = ", ".join(info.authors) | ||
if license_ in LICENSE_URL: | ||
license_ = f"[{license_}]({LICENSE_URL[license_]})" | ||
|
||
# write data used for charts | ||
cm = Colormap(name) | ||
cmap_data = { | ||
k: np.around(v, 4).tolist() if isinstance(v, np.ndarray) else v | ||
for k, v in report(cm).items() | ||
if k in INCLUDE_DATA | ||
} | ||
|
||
_aliases = [x for x in info.aliases if x != info.name] | ||
aliases = _make_aliases_md(_aliases) if _aliases else "" | ||
|
||
# write the actual markdown file | ||
doc_path = f"{category}/{name.lower()}.md" | ||
nav[(category.title(), name)] = doc_path | ||
with mkdocs_gen_files.open(f"catalog/{doc_path}", "w") as f: | ||
f.write( | ||
TEMPLATE.format( | ||
name=name, | ||
category=category.title(), | ||
license=license_, | ||
authors=authors, | ||
source=source, | ||
aliases=aliases, | ||
info=info.info, | ||
data=json.dumps({name: cmap_data}, separators=(",", ":")), | ||
) | ||
) | ||
|
||
# sort categories alphabetically | ||
nav._data = dict(sorted(nav._data.items(), key=lambda x: x[0][0])) | ||
with mkdocs_gen_files.open("catalog/SUMMARY.md", "w") as nav_file: | ||
nav_file.writelines(["# SUMMARY { data-search-exclude }\n"]) | ||
nav_file.writelines(nav.build_literate_nav()) | ||
|
||
|
||
def _make_aliases_md(aliases: list[str]) -> str: | ||
return "**Aliases**: " + ", ".join(f"`{a}`" for a in aliases) | ||
|
||
|
||
build_catalog(Colormap.catalog()) |
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 |
---|---|---|
@@ -0,0 +1,208 @@ | ||
import base64 | ||
import re | ||
import sys | ||
from functools import partial | ||
from pathlib import Path | ||
from typing import TYPE_CHECKING, Any, Sequence, cast | ||
|
||
import natsort | ||
import numpy as np | ||
|
||
from cmap import Colormap, _util | ||
|
||
if TYPE_CHECKING: | ||
from cmap._catalog import CatalogDict | ||
from cmap._color import NAME_TO_RGB | ||
|
||
CATALOG = cast("CatalogDict", Colormap.catalog()._data) # type: ignore | ||
|
||
# the template for a single colormap | ||
CMAP_DIV = """ | ||
<div class="cmap {class_list}" id="cmap-{name}"> | ||
<div class="cmap-name">{name}</div> | ||
{img} | ||
</div> | ||
""" | ||
CMAP_LINK = '<a href="{url}">' + CMAP_DIV + "</a>" | ||
DEV_MODE = "serve" in sys.argv | ||
SINERAMP = _util.sineramp((96, 826))[:, ::-1] | ||
|
||
|
||
def _to_img_tag( | ||
cm: Colormap, | ||
height: str = "32px", | ||
width: str = "100%", | ||
img: np.ndarray | None = None, | ||
) -> str: | ||
"""Return a base64-encoded <img> tag for the given colormap.""" | ||
_img = cm._repr_png_(width=826, height=1, img=img) | ||
data = base64.b64encode(_img).decode("ascii") | ||
return ( | ||
f'<img style="height: {height}" width="{width}" src="data:image/png;base64,' | ||
f'{data}" alt="{cm.name} colormap" />' | ||
) | ||
|
||
|
||
def _cm_url(cm: Colormap) -> str: | ||
name = cm.name.lower() | ||
if name.endswith("_r"): | ||
name = name[:-2] | ||
return f"/catalog/{cm.category}/{name}/" | ||
|
||
|
||
def _cmap_div(match: re.Match | str, class_list: Sequence[str] = ()) -> str: | ||
"""Convert a `cmap` tag to a div with the colormap. | ||
{{ cmap: name }} -> <div class="cmap"> | ||
""" | ||
map_name = match if isinstance(match, str) else match[1].strip() | ||
cm = Colormap(map_name) | ||
height = (match[2] if isinstance(match, re.Match) else None) or 32 | ||
img = _to_img_tag(cm, height=f"{height}px") | ||
return CMAP_LINK.format( | ||
name=map_name, img=img, class_list=" ".join(class_list), url=_cm_url(cm) | ||
) | ||
|
||
|
||
def _cmap_expr(match: re.Match) -> str: | ||
"""Convert a `cmap_expr` tag to a div with the colormap. | ||
{{ cmap_expr: {0: 'blue', 0.5: 'yellow', 1: 'red'} }} -> <div class="cmap">... | ||
""" | ||
cm = Colormap(eval(match[1].strip())) # noqa: S307 | ||
return CMAP_DIV.format(name="", img=_to_img_tag(cm), class_list="cmap-expr") | ||
|
||
|
||
def _cmap_sineramp(match: re.Match) -> str: | ||
"""Convert a `cmap_sineramp` tag to an img element with sineramp applied. | ||
{{ cmap_sineramp: viridis }} -> <img class="cmap">... | ||
""" | ||
# if DEV_MODE: | ||
# return "[sineramp slow -- disabled in `mkdocs serve`]" | ||
|
||
map_name = match[1].strip() | ||
return _to_img_tag(Colormap(map_name), f"{SINERAMP.shape[0]}px", img=SINERAMP) | ||
|
||
|
||
def _cmap_catalog() -> str: | ||
"""Return the HTML for the colormap catalog page. | ||
this works in conjunction with the `javascripts/extra.js` script. | ||
""" | ||
categories = set() | ||
lines = [] | ||
for cmap_name, details in natsort.natsorted( | ||
CATALOG.items(), key=lambda x: x[0].lower() | ||
): | ||
if "alias" in details: | ||
continue | ||
category = details.get("category") or "Uncategorized" | ||
categories.add(category) | ||
classes = ["filterDiv", category.lower()] | ||
lines.append(_cmap_div(cmap_name, classes)) | ||
|
||
btns = [ | ||
'<div id="cmapFilterButtons">', | ||
"""<button class="btn active" onclick="filterSelection('all')">All</button>""", | ||
] | ||
btns.extend( | ||
f'<button class="btn" onclick="filterSelection({c.lower()!r})">{c}</button>' | ||
for c in sorted(categories) | ||
) | ||
btns.append("</div>") | ||
lines = btns + lines | ||
|
||
return "\n".join(lines) | ||
|
||
|
||
COLORBOX = """<div class="colorbox" style="background-color: {hex}; color: {text_color}"> | ||
<strong class="colornamespan">{name}</strong><br /> | ||
<span class="colorhexspan">{hex}</span><br /> | ||
<span class="colortuple">{rgb}</span><br /> | ||
</div> | ||
""" | ||
|
||
|
||
def _color_list() -> str: | ||
"""Return the HTML for the color list page.""" | ||
colors = [] | ||
for name, c in NAME_TO_RGB.items(): | ||
if (hsl := c.to_hsl()).l == 0.5: | ||
text_color = "#000" if hsl.h <= 0.5 else "#FFF" | ||
else: | ||
text_color = "#000" if hsl.l > 0.50 or not c.a else "#FFF" | ||
cbox = COLORBOX.format( | ||
name=name, | ||
hex=c.to_hex(), | ||
text_color=text_color, | ||
rgb=c.rgba_string(), | ||
) | ||
colors.append(cbox) | ||
return '<div class="colorlist">{}</div>'.format("\n".join(colors)) | ||
|
||
|
||
# ----------------------------------------------------------------------------- | ||
# mkdocs hooks | ||
# ----------------------------------------------------------------------------- | ||
|
||
# markdown tag for a single colormap: {{ cmap: name }} | ||
CSS_CMAP = re.compile(r"{{\s?cmap:\s?([^}^\s]+)\s?(\d+)?\s?}}") | ||
CSS_CMAP_GRAY = re.compile(r"{{\s?cmap_gray:\s?([^}^\s]+)\s?(\d+)?\s?}}") | ||
CMAP_SINERAMP = re.compile(r"{{\s?cmap_sineramp:\s?([^}]+)\s?}}") | ||
CMAP_EXPR = re.compile(r"{{\s?cmap_expr:\s(.+)\s}}") | ||
CMAP_CATALOG = r"{{ CMAP_CATALOG }}" | ||
COLOR_LIST = r"{{ COLOR_LIST }}" | ||
|
||
|
||
def on_page_content(html: str, **kwargs: Any) -> str: | ||
html = CSS_CMAP.sub(_cmap_div, html) | ||
html = CSS_CMAP_GRAY.sub(partial(_cmap_div, class_list=["grayscale"]), html) | ||
html = CMAP_EXPR.sub(_cmap_expr, html) | ||
html = CMAP_SINERAMP.sub(_cmap_sineramp, html) | ||
if CMAP_CATALOG in html: | ||
html = html.replace(CMAP_CATALOG, _cmap_catalog()) | ||
if COLOR_LIST in html: | ||
html = html.replace(COLOR_LIST, _color_list()) | ||
return html | ||
|
||
|
||
REDIRECT_TEMPLATE = """<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Redirecting...</title> | ||
<link rel="canonical" href="{url}"> | ||
<meta name="robots" content="noindex"> | ||
<script> | ||
var anchor=window.location.hash.substr(1);location.href="{url}"+(anchor?"#"+anchor:"") | ||
</script> | ||
<meta http-equiv="refresh" content="0; url={url}"> | ||
</head> | ||
<body> | ||
Redirecting... | ||
</body> | ||
</html> | ||
""" | ||
|
||
|
||
def _write_cmap_redirects(site_dir: str) -> None: | ||
sd = Path(site_dir) | ||
for cmap_name, details in natsort.natsorted( | ||
CATALOG.items(), key=lambda x: x[0].lower() | ||
): | ||
if "alias" in details: | ||
cmap_name = cmap_name.replace(":", "-") | ||
real = Colormap(details["alias"]) # type: ignore | ||
old_path_abs = ( | ||
sd / "catalog" / str(real.category) / cmap_name / "index.html" | ||
) | ||
old_path_abs.parent.mkdir(parents=True, exist_ok=True) | ||
content = REDIRECT_TEMPLATE.format(url=_cm_url(real)) | ||
with open(old_path_abs, "w", encoding="utf-8") as f: | ||
f.write(content) | ||
|
||
|
||
def on_post_build(config: dict, **kwargs: Any) -> None: | ||
"""Copy the extra javascripts to the output directory.""" | ||
_write_cmap_redirects(config["site_dir"]) |
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Oops, something went wrong.