docs: glossary infra (#34231)
* feat: glossary infra * fix static analysis error * fix ruff linter error. * updates docs.yaml to use ubuntu-24.04 * code review fixespull/34235/head
parent
8743bc4fe2
commit
93a8d87b34
5 changed files with 117 additions and 1 deletions
@ -0,0 +1,44 @@ |
|||||||
|
[data-tooltip] { |
||||||
|
position: relative; |
||||||
|
display: inline-block; |
||||||
|
border-bottom: 1px dotted black; |
||||||
|
} |
||||||
|
|
||||||
|
[data-tooltip] .tooltip-content { |
||||||
|
width: max-content; |
||||||
|
max-width: 25em; |
||||||
|
position: absolute; |
||||||
|
top: 100%; |
||||||
|
left: 50%; |
||||||
|
transform: translateX(-50%); |
||||||
|
background-color: white; |
||||||
|
color: #404040; |
||||||
|
box-shadow: 0 4px 14px 0 rgba(0,0,0,.2), 0 0 0 1px rgba(0,0,0,.05); |
||||||
|
padding: 10px; |
||||||
|
font: 14px/1.5 Lato, proxima-nova, Helvetica Neue, Arial, sans-serif; |
||||||
|
text-decoration: none; |
||||||
|
opacity: 0; |
||||||
|
visibility: hidden; |
||||||
|
transition: opacity 0.1s, visibility 0s; |
||||||
|
z-index: 1000; |
||||||
|
pointer-events: none; /* Prevent accidental interaction */ |
||||||
|
} |
||||||
|
|
||||||
|
[data-tooltip]:hover .tooltip-content { |
||||||
|
opacity: 1; |
||||||
|
visibility: visible; |
||||||
|
pointer-events: auto; /* Allow interaction when visible */ |
||||||
|
} |
||||||
|
|
||||||
|
.tooltip-content .tooltip-glossary-link { |
||||||
|
display: inline-block; |
||||||
|
margin-top: 8px; |
||||||
|
font-size: 12px; |
||||||
|
color: #007bff; |
||||||
|
text-decoration: none; |
||||||
|
} |
||||||
|
|
||||||
|
.tooltip-content .tooltip-glossary-link:hover { |
||||||
|
color: #0056b3; |
||||||
|
text-decoration: underline; |
||||||
|
} |
@ -0,0 +1,68 @@ |
|||||||
|
import re |
||||||
|
import tomllib |
||||||
|
|
||||||
|
def load_glossary(file_path="docs/glossary.toml"): |
||||||
|
with open(file_path, "rb") as f: |
||||||
|
glossary_data = tomllib.load(f) |
||||||
|
return glossary_data.get("glossary", {}) |
||||||
|
|
||||||
|
def generate_anchor_id(name): |
||||||
|
return name.replace(" ", "-").replace("_", "-").lower() |
||||||
|
|
||||||
|
def format_markdown_term(name, definition): |
||||||
|
anchor_id = generate_anchor_id(name) |
||||||
|
markdown = f"* [**{name.replace('_', ' ').title()}**](#{anchor_id})" |
||||||
|
if definition.get("abbreviation"): |
||||||
|
markdown += f" *({definition['abbreviation']})*" |
||||||
|
if definition.get("description"): |
||||||
|
markdown += f": {definition['description']}\n" |
||||||
|
return markdown |
||||||
|
|
||||||
|
def glossary_markdown(vocabulary): |
||||||
|
markdown = "" |
||||||
|
for category, terms in vocabulary.items(): |
||||||
|
markdown += f"## {category.replace('_', ' ').title()}\n\n" |
||||||
|
for name, definition in terms.items(): |
||||||
|
markdown += format_markdown_term(name, definition) |
||||||
|
return markdown |
||||||
|
|
||||||
|
def format_tooltip_html(term_key, definition, html): |
||||||
|
display_term = term_key.replace("_", " ").title() |
||||||
|
clean_description = re.sub(r"\[(.+)]\(.+\)", r"\1", definition["description"]) |
||||||
|
glossary_link = ( |
||||||
|
f"<a href='/concepts/glossary#{term_key}' class='tooltip-glossary-link' title='View in glossary'>Glossary🔗</a>" |
||||||
|
) |
||||||
|
return re.sub( |
||||||
|
re.escape(display_term), |
||||||
|
lambda |
||||||
|
match: f"<span data-tooltip>{match.group(0)}<span class='tooltip-content'>{clean_description} {glossary_link}</span></span>", |
||||||
|
html, |
||||||
|
flags=re.IGNORECASE, |
||||||
|
) |
||||||
|
|
||||||
|
def apply_tooltip(_term_key, _definition, pattern, html): |
||||||
|
return re.sub( |
||||||
|
pattern, |
||||||
|
lambda match: format_tooltip_html(_term_key, _definition, match.group(0)), |
||||||
|
html, |
||||||
|
flags=re.IGNORECASE, |
||||||
|
) |
||||||
|
|
||||||
|
def tooltip_html(vocabulary, html): |
||||||
|
for _category, terms in vocabulary.items(): |
||||||
|
for term_key, definition in terms.items(): |
||||||
|
if definition.get("description"): |
||||||
|
pattern = rf"(?<!\w){re.escape(term_key.replace('_', ' ').title())}(?![^<]*<\/a>)(?!\([^)]*\))" |
||||||
|
html = apply_tooltip(term_key, definition, pattern, html) |
||||||
|
return html |
||||||
|
|
||||||
|
# Page Hooks |
||||||
|
def on_page_markdown(markdown, **kwargs): |
||||||
|
glossary = load_glossary() |
||||||
|
return markdown.replace("{{GLOSSARY_DEFINITIONS}}", glossary_markdown(glossary)) |
||||||
|
|
||||||
|
def on_page_content(html, **kwargs): |
||||||
|
if kwargs.get("page").title == "Glossary": |
||||||
|
return html |
||||||
|
glossary = load_glossary() |
||||||
|
return tooltip_html(glossary, html) |
Loading…
Reference in new issue