Skip to content

Commit 29e6aea

Browse files
committed
try adding branding to jupyterlite
1 parent bff838b commit 29e6aea

4 files changed

Lines changed: 86 additions & 0 deletions

File tree

.github/workflows/build-and-deploy.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ jobs:
105105
run: |
106106
pip install -r requirements-jupyterlite.txt
107107
jupyter lite build --contents jupyterlite --output-dir _build/jupyterlite
108+
python jupyterlite/inject_branding.py _build/jupyterlite
108109
109110
- name: Upload artifact
110111
uses: actions/upload-pages-artifact@v3.0.1

jupyter-lite.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"jupyter-lite-schema-version": 0,
3+
"jupyter-config-data": {
4+
"appName": "PySDR",
5+
"faviconUrl": "/_static/myicon.png"
6+
}
7+
}

jupyterlite/inject_branding.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env python3
2+
"""Inject PySDR branding into a built JupyterLite site.
3+
4+
Run AFTER `jupyter lite build`. JupyterLab 4 / Notebook 7 render the top-left
5+
logo from JavaScript and offer no user-CSS hook, so we inline a small stylesheet
6+
(pysdr-brand.css) into every generated app page. It hides the built-in Jupyter
7+
mark (#jp-NotebookLogo for the Notebook apps, #jp-MainLogo for Lab) and paints
8+
the PySDR logo from /_static/logo.svg instead.
9+
10+
Usage: python jupyterlite/inject_branding.py [output_dir]
11+
(output_dir defaults to _build/jupyterlite)
12+
13+
Exits non-zero if it patches nothing, so CI fails loudly if a JupyterLite
14+
upgrade changes the build layout out from under us.
15+
"""
16+
from __future__ import annotations
17+
18+
import sys
19+
from pathlib import Path
20+
21+
HERE = Path(__file__).resolve().parent
22+
MARKER = "pysdr-branding"
23+
24+
25+
def main() -> int:
26+
out = Path(sys.argv[1] if len(sys.argv) > 1 else "_build/jupyterlite")
27+
if not out.is_dir():
28+
print(f"[inject_branding] output dir not found: {out}", file=sys.stderr)
29+
return 1
30+
31+
css = (HERE / "pysdr-brand.css").read_text(encoding="utf-8")
32+
block = f'<style data-{MARKER}="1">\n{css}\n</style>'
33+
34+
patched = 0
35+
for html in out.rglob("*.html"):
36+
text = html.read_text(encoding="utf-8")
37+
if MARKER in text or "</head>" not in text:
38+
continue
39+
html.write_text(text.replace("</head>", block + "\n</head>", 1), encoding="utf-8")
40+
patched += 1
41+
42+
print(f"[inject_branding] patched {patched} page(s) under {out}")
43+
return 0 if patched else 1
44+
45+
46+
if __name__ == "__main__":
47+
raise SystemExit(main())

jupyterlite/pysdr-brand.css

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* PySDR branding for the self-hosted JupyterLite deployment.
2+
*
3+
* JupyterLab 4 / Notebook 7 build the top-left logo in JavaScript and expose no
4+
* user-CSS hook, so inject_branding.py inlines this file into every generated
5+
* app page after `jupyter lite build`. We hide the built-in Jupyter mark and
6+
* paint the PySDR logo (served at /_static/logo.svg on the deployed site)
7+
* instead. logo.svg is ~1983x1192 (=1.66:1); at 28px tall that is ~47px wide. */
8+
9+
/* Notebook 7 apps: notebooks/, tree/, edit/, consoles/ (this is what opens) */
10+
#jp-NotebookLogo {
11+
background-image: url(/_static/logo.svg);
12+
background-repeat: no-repeat;
13+
background-position: left center;
14+
background-size: contain;
15+
width: 48px;
16+
}
17+
#jp-NotebookLogo svg {
18+
visibility: hidden;
19+
}
20+
21+
/* JupyterLab app: lab/ */
22+
#jp-MainLogo {
23+
background-image: url(/_static/logo.svg);
24+
background-repeat: no-repeat;
25+
background-position: center;
26+
background-size: contain;
27+
width: 48px;
28+
}
29+
#jp-MainLogo svg {
30+
visibility: hidden;
31+
}

0 commit comments

Comments
 (0)