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