Skip to content

Commit 3b99cc7

Browse files
darmadocursoragent
andcommitted
site: polish logo, search dropdown, syntax highlight, meta column
Unconstrained hero logo with sr-only title fallback; local logo.svg/png support; GitHub icon header; search results dropdown; Pygments for shell/YAML; metadata sticky right column; decluttered procedure sidebar list. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 5807826 commit 3b99cc7

9 files changed

Lines changed: 410 additions & 135 deletions

File tree

‎docs/Design/website_docs_pipeline.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ python3 site/build/build_site.py
5454
cd site/public && python3 -m http.server 8765
5555
```
5656

57+
**Site logo:** drop `logo.svg`, `logo.png`, or `logo.webp` into `site/build/static/` (copied to `site/public/assets/` on build). That file overrides the remote `SITE_LOGO_URL` fallback.
58+
5759
CI uses a fresh Ubuntu runner with `pip install -r site/build/requirements.txt`; your local Python policy does not affect Pages deploy.
5860

5961
## Adding or updating content

‎site/build/build_site.py‎

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,49 @@
6464
MARKDOWN_EXT = ".md"
6565
HTML_EXT = ".html"
6666

67-
SITE_LOGO_URL = os.environ.get(
67+
SITE_LOGO_REMOTE = os.environ.get(
6868
"SITE_LOGO_URL",
6969
"https://github.com/user-attachments/assets/03a5c7dc-9dd6-49f9-a58b-2fdcdb6596f6",
7070
)
71+
SITE_LOGO_FILES = ("logo.svg", "logo.png", "logo.webp")
72+
73+
def resolve_site_logo_url() -> str:
74+
"""Prefer site/build/static/logo.{svg,png,webp} over remote SITE_LOGO_URL."""
75+
for name in SITE_LOGO_FILES:
76+
if (STATIC / name).is_file():
77+
return _site_url(SITE_ASSETS_SEGMENT, name)
78+
return SITE_LOGO_REMOTE
79+
80+
81+
def build_search_index(procedures: list[dict]) -> list[dict]:
82+
return [
83+
{
84+
"name": p["procedure_name"],
85+
"href": p["page_href"],
86+
"tactic": p.get("tactic", ""),
87+
"ttp": p.get("ttp_id", ""),
88+
"intent": p.get("intent", ""),
89+
"author": p.get("author", ""),
90+
}
91+
for p in procedures
92+
]
93+
94+
95+
def highlight_code(text: str, lang: str) -> Markup:
96+
if not text:
97+
return Markup("")
98+
try:
99+
from pygments import highlight
100+
from pygments.formatters import HtmlFormatter
101+
from pygments.lexers import BashLexer, YamlLexer
102+
103+
lexer = BashLexer() if lang == "bash" else YamlLexer()
104+
formatter = HtmlFormatter(linenos=False, cssclass="code-highlight")
105+
return Markup(highlight(text, lexer, formatter))
106+
except (ImportError, ValueError):
107+
escaped = text.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
108+
return Markup(f'<pre class="code-raw-fallback"><code>{escaped}</code></pre>')
109+
71110

72111
INTENT_SHORT_LIMIT = 56
73112

@@ -276,6 +315,10 @@ def copy_static() -> None:
276315
dest.mkdir(parents=True, exist_ok=True)
277316
shutil.copy2(STATIC / "app.css", dest / "app.css")
278317
shutil.copy2(STATIC / "app.js", dest / "app.js")
318+
for name in SITE_LOGO_FILES:
319+
src = STATIC / name
320+
if src.is_file():
321+
shutil.copy2(src, dest / name)
279322

280323

281324
def main() -> int:
@@ -290,6 +333,8 @@ def main() -> int:
290333
procedures = load_procedures()
291334
tactics = sorted({p["tactic"] for p in procedures if p.get("tactic")})
292335
doc_nav = build_doc_nav()
336+
site_logo_url = resolve_site_logo_url()
337+
search_index = build_search_index(procedures)
293338
write_procedures_json(procedures)
294339
copy_static()
295340

@@ -306,7 +351,8 @@ def render(name: str, out_rel: str, **ctx) -> None:
306351
tactics=tactics,
307352
doc_nav=doc_nav,
308353
github_repo=GITHUB_REPO,
309-
site_logo_url=SITE_LOGO_URL,
354+
site_logo_url=site_logo_url,
355+
search_index=search_index,
310356
**ctx,
311357
)
312358
out_path = OUT / out_rel
@@ -336,10 +382,11 @@ def render(name: str, out_rel: str, **ctx) -> None:
336382
tactics=tactics,
337383
doc_nav=doc_nav,
338384
github_repo=GITHUB_REPO,
339-
site_logo_url=SITE_LOGO_URL,
385+
site_logo_url=site_logo_url,
386+
search_index=search_index,
340387
proc=proc,
341-
yaml_raw=yaml_raw,
342-
script_raw=script_raw,
388+
yaml_html=highlight_code(yaml_raw, "yaml"),
389+
script_html=highlight_code(script_raw, "bash") if has_script else Markup(""),
343390
has_script=has_script,
344391
default_view=default_view,
345392
body_html=Markup(body_html) if body_html else None,
@@ -364,7 +411,8 @@ def render(name: str, out_rel: str, **ctx) -> None:
364411
tactics=tactics,
365412
doc_nav=doc_nav,
366413
github_repo=GITHUB_REPO,
367-
site_logo_url=SITE_LOGO_URL,
414+
site_logo_url=site_logo_url,
415+
search_index=search_index,
368416
doc_title=item["title"],
369417
body_html=body,
370418
current_href=item["href"],

‎site/build/requirements.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
Jinja2>=3.1,<4
22
Markdown>=3.5,<4
33
PyYAML>=6,<7
4+
Pygments>=2.17,<3

0 commit comments

Comments
 (0)