Update extra.js (#17040)
Signed-off-by: UltralyticsAssistant <web@ultralytics.com> Co-authored-by: UltralyticsAssistant <web@ultralytics.com>
This commit is contained in:
parent
e38228774f
commit
2c8f31c9c0
7 changed files with 175 additions and 126 deletions
6
.github/workflows/docs.yml
vendored
6
.github/workflows/docs.yml
vendored
|
|
@ -22,8 +22,8 @@ on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
publish_docs:
|
publish_docs:
|
||||||
description: 'Publish live to https://docs.ultralytics.com'
|
description: "Publish live to https://docs.ultralytics.com"
|
||||||
default: 'true'
|
default: "true"
|
||||||
type: boolean
|
type: boolean
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
@ -48,7 +48,7 @@ jobs:
|
||||||
python-version: "3.x"
|
python-version: "3.x"
|
||||||
cache: "pip" # caching pip dependencies
|
cache: "pip" # caching pip dependencies
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: pip install ruff black tqdm mkdocs-material "mkdocstrings[python]" mkdocs-jupyter mkdocs-redirects mkdocs-ultralytics-plugin mkdocs-macros-plugin
|
run: pip install ruff black tqdm minify-html mkdocs-material "mkdocstrings[python]" mkdocs-jupyter mkdocs-redirects mkdocs-ultralytics-plugin mkdocs-macros-plugin
|
||||||
- name: Ruff fixes
|
- name: Ruff fixes
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: ruff check --fix --unsafe-fixes --select D --ignore=D100,D104,D203,D205,D212,D213,D401,D406,D407,D413 .
|
run: ruff check --fix --unsafe-fixes --select D --ignore=D100,D104,D203,D205,D212,D213,D401,D406,D407,D413 .
|
||||||
|
|
|
||||||
|
|
@ -238,8 +238,36 @@ def remove_macros():
|
||||||
print(f"Removed {len(macros_indices)} URLs containing '/macros/' from {sitemap}")
|
print(f"Removed {len(macros_indices)} URLs containing '/macros/' from {sitemap}")
|
||||||
|
|
||||||
|
|
||||||
|
def minify_html_files():
|
||||||
|
"""Minifies all HTML files in the site directory and prints reduction stats."""
|
||||||
|
try:
|
||||||
|
from minify_html import minify # pip install minify-html
|
||||||
|
except ImportError:
|
||||||
|
return
|
||||||
|
|
||||||
|
total_original_size = 0
|
||||||
|
total_minified_size = 0
|
||||||
|
for html_file in tqdm(SITE.rglob("*.html"), desc="Minifying HTML files"):
|
||||||
|
with open(html_file, encoding="utf-8") as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
original_size = len(content)
|
||||||
|
minified_content = minify(content)
|
||||||
|
minified_size = len(minified_content)
|
||||||
|
|
||||||
|
total_original_size += original_size
|
||||||
|
total_minified_size += minified_size
|
||||||
|
|
||||||
|
with open(html_file, "w", encoding="utf-8") as f:
|
||||||
|
f.write(minified_content)
|
||||||
|
|
||||||
|
total_reduction = total_original_size - total_minified_size
|
||||||
|
total_percent_reduction = (total_reduction / total_original_size) * 100
|
||||||
|
print(f"Minify HTML reduction: {total_percent_reduction:.2f}% " f"({total_reduction / 1024:.2f} KB saved)")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Builds docs, updates titles and edit links, and prints local server command."""
|
"""Builds docs, updates titles and edit links, minifies HTML, and prints local server command."""
|
||||||
prepare_docs_markdown()
|
prepare_docs_markdown()
|
||||||
|
|
||||||
# Build the main documentation
|
# Build the main documentation
|
||||||
|
|
@ -251,6 +279,9 @@ def main():
|
||||||
# Update docs HTML pages
|
# Update docs HTML pages
|
||||||
update_docs_html()
|
update_docs_html()
|
||||||
|
|
||||||
|
# Minify HTML files
|
||||||
|
minify_html_files()
|
||||||
|
|
||||||
# Show command to serve built website
|
# Show command to serve built website
|
||||||
print('Docs built correctly ✅\nServe site at http://localhost:8000 with "python -m http.server --directory site"')
|
print('Docs built correctly ✅\nServe site at http://localhost:8000 with "python -m http.server --directory site"')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,71 +1,68 @@
|
||||||
// Function that applies light/dark theme based on the user's preference
|
// Apply theme based on user preference
|
||||||
const applyAutoTheme = () => {
|
const applyTheme = (isDark) => {
|
||||||
// Determine the user's preferred color scheme
|
document.body.setAttribute(
|
||||||
const prefersLight = window.matchMedia("(prefers-color-scheme: light)").matches;
|
"data-md-color-scheme",
|
||||||
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
isDark ? "slate" : "default",
|
||||||
|
);
|
||||||
|
document.body.setAttribute(
|
||||||
|
"data-md-color-primary",
|
||||||
|
isDark ? "black" : "indigo",
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
// Apply the appropriate attributes based on the user's preference
|
// Check and apply auto theme
|
||||||
if (prefersLight) {
|
const checkAutoTheme = () => {
|
||||||
document.body.setAttribute("data-md-color-scheme", "default");
|
const supportedLangCodes = [
|
||||||
document.body.setAttribute("data-md-color-primary", "indigo");
|
"en",
|
||||||
} else if (prefersDark) {
|
"zh",
|
||||||
document.body.setAttribute("data-md-color-scheme", "slate");
|
"ko",
|
||||||
document.body.setAttribute("data-md-color-primary", "black");
|
"ja",
|
||||||
|
"ru",
|
||||||
|
"de",
|
||||||
|
"fr",
|
||||||
|
"es",
|
||||||
|
"pt",
|
||||||
|
"it",
|
||||||
|
"tr",
|
||||||
|
"vi",
|
||||||
|
"ar",
|
||||||
|
];
|
||||||
|
const langCode = window.location.pathname.split("/")[1];
|
||||||
|
const localStorageKey = `${supportedLangCodes.includes(langCode) ? `/${langCode}` : ""}/.__palette`;
|
||||||
|
const palette = JSON.parse(localStorage.getItem(localStorageKey) || "{}");
|
||||||
|
|
||||||
|
if (palette.index === 0) {
|
||||||
|
applyTheme(window.matchMedia("(prefers-color-scheme: dark)").matches);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function that checks and applies light/dark theme based on the user's preference (if auto theme is enabled)
|
// Event listeners for theme changes
|
||||||
function checkAutoTheme() {
|
const mediaQueryList = window.matchMedia("(prefers-color-scheme: dark)");
|
||||||
// Array of supported language codes -> each language has its own palette (stored in local storage)
|
mediaQueryList.addListener(checkAutoTheme);
|
||||||
const supportedLangCodes = ["en", "zh", "ko", "ja", "ru", "de", "fr", "es", "pt", "it", "tr", "vi", "nl"];
|
|
||||||
// Get the URL path
|
|
||||||
const path = window.location.pathname;
|
|
||||||
// Extract the language code from the URL (assuming it's in the format /xx/...)
|
|
||||||
const langCode = path.split("/")[1];
|
|
||||||
// Check if the extracted language code is in the supported languages
|
|
||||||
const isValidLangCode = supportedLangCodes.includes(langCode);
|
|
||||||
// Construct the local storage key based on the language code if valid, otherwise default to the root key
|
|
||||||
const localStorageKey = isValidLangCode ? `/${langCode}/.__palette` : "/.__palette";
|
|
||||||
// Retrieve the palette from local storage using the constructed key
|
|
||||||
const palette = localStorage.getItem(localStorageKey);
|
|
||||||
if (palette) {
|
|
||||||
// Check if the palette's index is 0 (auto theme)
|
|
||||||
const paletteObj = JSON.parse(palette);
|
|
||||||
if (paletteObj && paletteObj.index === 0) {
|
|
||||||
applyAutoTheme();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run function when the script loads
|
// Initial theme check
|
||||||
checkAutoTheme();
|
checkAutoTheme();
|
||||||
|
|
||||||
// Re-run the function when the user's preference changes (when the user changes their system theme)
|
// Auto theme input listener
|
||||||
window.matchMedia("(prefers-color-scheme: light)").addEventListener("change", checkAutoTheme);
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", checkAutoTheme);
|
const autoThemeInput = document.getElementById("__palette_1");
|
||||||
|
autoThemeInput?.addEventListener("click", () => {
|
||||||
// Re-run the function when the palette changes (e.g. user switched from dark theme to auto theme)
|
if (autoThemeInput.checked) setTimeout(checkAutoTheme);
|
||||||
// ! We can't use window.addEventListener("storage", checkAutoTheme) because it will NOT be triggered on the current tab
|
|
||||||
// ! So we have to use the following workaround:
|
|
||||||
// Get the palette input for auto theme
|
|
||||||
var autoThemeInput = document.getElementById("__palette_1");
|
|
||||||
if (autoThemeInput) {
|
|
||||||
// Add a click event listener to the input
|
|
||||||
autoThemeInput.addEventListener("click", function () {
|
|
||||||
// Check if the auto theme is selected
|
|
||||||
if (autoThemeInput.checked) {
|
|
||||||
// Re-run the function after a short delay (to ensure that the palette has been updated)
|
|
||||||
setTimeout(applyAutoTheme);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
|
||||||
// Add iframe navigation
|
// Iframe navigation
|
||||||
window.onhashchange = function() {
|
window.onhashchange = () => {
|
||||||
window.parent.postMessage({
|
window.parent.postMessage(
|
||||||
type: 'navigation',
|
{
|
||||||
hash: window.location.pathname + window.location.search + window.location.hash
|
type: "navigation",
|
||||||
}, '*');
|
hash:
|
||||||
|
window.location.pathname +
|
||||||
|
window.location.search +
|
||||||
|
window.location.hash,
|
||||||
|
},
|
||||||
|
"*",
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add Inkeep button
|
// Add Inkeep button
|
||||||
|
|
@ -112,35 +109,35 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||||
},
|
},
|
||||||
aiChatSettings: {
|
aiChatSettings: {
|
||||||
chatSubjectName: "Ultralytics",
|
chatSubjectName: "Ultralytics",
|
||||||
botAvatarSrcUrl: "https://storage.googleapis.com/organization-image-assets/ultralytics-botAvatarSrcUrl-1727908259285.png",
|
botAvatarSrcUrl:
|
||||||
botAvatarDarkSrcUrl: "https://storage.googleapis.com/organization-image-assets/ultralytics-botAvatarDarkSrcUrl-1727908258478.png",
|
"https://storage.googleapis.com/organization-image-assets/ultralytics-botAvatarSrcUrl-1729379860806.svg",
|
||||||
quickQuestions: [
|
quickQuestions: [
|
||||||
"What's new in Ultralytics YOLO11?",
|
"What's new in Ultralytics YOLO11?",
|
||||||
"How can I get started with Ultralytics HUB?",
|
"How can I get started with Ultralytics HUB?",
|
||||||
"How does Ultralytics Enterprise Licensing work?"
|
"How does Ultralytics Enterprise Licensing work?",
|
||||||
],
|
],
|
||||||
getHelpCallToActions: [
|
getHelpCallToActions: [
|
||||||
{
|
{
|
||||||
name: "Ask on Ultralytics GitHub",
|
name: "Ask on Ultralytics GitHub",
|
||||||
url: "https://github.com/ultralytics/ultralytics",
|
url: "https://github.com/ultralytics/ultralytics",
|
||||||
icon: {
|
icon: {
|
||||||
builtIn: "FaGithub"
|
builtIn: "FaGithub",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Ask on Ultralytics Discourse",
|
name: "Ask on Ultralytics Discourse",
|
||||||
url: "https://community.ultralytics.com/",
|
url: "https://community.ultralytics.com/",
|
||||||
icon: {
|
icon: {
|
||||||
builtIn: "FaDiscourse"
|
builtIn: "FaDiscourse",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Ask on Ultralytics Discord",
|
name: "Ask on Ultralytics Discord",
|
||||||
url: "https://discord.com/invite/ultralytics",
|
url: "https://discord.com/invite/ultralytics",
|
||||||
icon: {
|
icon: {
|
||||||
builtIn: "FaDiscord"
|
builtIn: "FaDiscord",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
63
docs/overrides/javascript/giscus.js
Normal file
63
docs/overrides/javascript/giscus.js
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
// Giscus functionality
|
||||||
|
function loadGiscus() {
|
||||||
|
const script = document.createElement("script");
|
||||||
|
script.src = "https://giscus.app/client.js";
|
||||||
|
script.setAttribute("data-repo", "ultralytics/ultralytics");
|
||||||
|
script.setAttribute("data-repo-id", "R_kgDOH-jzvQ");
|
||||||
|
script.setAttribute("data-category", "Docs");
|
||||||
|
script.setAttribute("data-category-id", "DIC_kwDOH-jzvc4CWLkL");
|
||||||
|
script.setAttribute("data-mapping", "pathname");
|
||||||
|
script.setAttribute("data-strict", "1");
|
||||||
|
script.setAttribute("data-reactions-enabled", "1");
|
||||||
|
script.setAttribute("data-emit-metadata", "0");
|
||||||
|
script.setAttribute("data-input-position", "top");
|
||||||
|
script.setAttribute("data-theme", "preferred_color_scheme");
|
||||||
|
script.setAttribute("data-lang", "en");
|
||||||
|
script.setAttribute("data-loading", "lazy");
|
||||||
|
script.setAttribute("crossorigin", "anonymous");
|
||||||
|
script.setAttribute("async", "");
|
||||||
|
|
||||||
|
const giscusContainer = document.getElementById("giscus-container");
|
||||||
|
if (giscusContainer) {
|
||||||
|
giscusContainer.appendChild(script);
|
||||||
|
|
||||||
|
// Synchronize Giscus theme with palette
|
||||||
|
var palette = __md_get("__palette");
|
||||||
|
if (palette && typeof palette.color === "object") {
|
||||||
|
var theme = palette.color.scheme === "slate" ? "dark" : "light";
|
||||||
|
script.setAttribute("data-theme", theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register event handlers for theme changes
|
||||||
|
var ref = document.querySelector("[data-md-component=palette]");
|
||||||
|
if (ref) {
|
||||||
|
ref.addEventListener("change", function () {
|
||||||
|
var palette = __md_get("__palette");
|
||||||
|
if (palette && typeof palette.color === "object") {
|
||||||
|
var theme = palette.color.scheme === "slate" ? "dark" : "light";
|
||||||
|
|
||||||
|
// Instruct Giscus to change theme
|
||||||
|
var frame = document.querySelector(".giscus-frame");
|
||||||
|
if (frame) {
|
||||||
|
frame.contentWindow.postMessage(
|
||||||
|
{ giscus: { setConfig: { theme } } },
|
||||||
|
"https://giscus.app",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MkDocs specific: Load Giscus when the page content is fully loaded
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
var observer = new MutationObserver(function (mutations) {
|
||||||
|
if (document.getElementById("giscus-container")) {
|
||||||
|
loadGiscus();
|
||||||
|
observer.disconnect();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(document.body, { childList: true, subtree: true });
|
||||||
|
});
|
||||||
|
|
@ -1,51 +1,7 @@
|
||||||
{% if page.meta.comments %}
|
{% if page.meta.comments %}
|
||||||
<h2 id="__comments">{{ lang.t("meta.comments") }}</h2>
|
<h2 id="__comments">{{ lang.t("meta.comments") }}</h2>
|
||||||
|
|
||||||
<!-- Insert Giscus code snippet from https://giscus.app/ here -->
|
<!-- Giscus container -->
|
||||||
<script async
|
<div id="giscus-container"></div>
|
||||||
crossorigin="anonymous"
|
|
||||||
data-category="Docs"
|
|
||||||
data-category-id="DIC_kwDOH-jzvc4CWLkL"
|
|
||||||
data-emit-metadata="0"
|
|
||||||
data-input-position="top"
|
|
||||||
data-lang="en"
|
|
||||||
data-loading="lazy"
|
|
||||||
data-mapping="pathname"
|
|
||||||
data-reactions-enabled="1"
|
|
||||||
data-repo="ultralytics/ultralytics"
|
|
||||||
data-repo-id="R_kgDOH-jzvQ"
|
|
||||||
data-strict="1"
|
|
||||||
data-theme="preferred_color_scheme"
|
|
||||||
src="https://giscus.app/client.js">
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Synchronize Giscus theme with palette -->
|
|
||||||
<script>
|
|
||||||
var giscus = document.querySelector("script[src*=giscus]")
|
|
||||||
|
|
||||||
/* Set palette on initial load */
|
|
||||||
var palette = __md_get("__palette")
|
|
||||||
if (palette && typeof palette.color === "object") {
|
|
||||||
var theme = palette.color.scheme === "slate" ? "dark" : "light"
|
|
||||||
giscus.setAttribute("data-theme", theme)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register event handlers after documented loaded */
|
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
|
||||||
var ref = document.querySelector("[data-md-component=palette]")
|
|
||||||
ref.addEventListener("change", function() {
|
|
||||||
var palette = __md_get("__palette")
|
|
||||||
if (palette && typeof palette.color === "object") {
|
|
||||||
var theme = palette.color.scheme === "slate" ? "dark" : "light"
|
|
||||||
|
|
||||||
/* Instruct Giscus to change theme */
|
|
||||||
var frame = document.querySelector(".giscus-frame")
|
|
||||||
frame.contentWindow.postMessage(
|
|
||||||
{ giscus: { setConfig: { theme } } },
|
|
||||||
"https://giscus.app"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,6 @@ div.highlight {
|
||||||
.banner-wrapper {
|
.banner-wrapper {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
|
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -121,7 +120,6 @@ div.highlight {
|
||||||
.banner-wrapper > .banner-button-wrapper,
|
.banner-wrapper > .banner-button-wrapper,
|
||||||
.banner-wrapper > .banner-button-wrapper > .banner-button-wrapper {
|
.banner-wrapper > .banner-button-wrapper > .banner-button-wrapper {
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
|
|
||||||
background-color: rgba(222, 255, 56, 0.2);
|
background-color: rgba(222, 255, 56, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,13 +129,10 @@ div.highlight {
|
||||||
|
|
||||||
.banner-wrapper > .banner-button-wrapper > .banner-button-wrapper > button {
|
.banner-wrapper > .banner-button-wrapper > .banner-button-wrapper > button {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
min-width: 132px;
|
min-width: 132px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #111f68;
|
color: #111f68;
|
||||||
|
|
||||||
background-color: rgb(222, 255, 56);
|
background-color: rgb(222, 255, 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -156,13 +151,11 @@ div.highlight {
|
||||||
|
|
||||||
.banner-wrapper {
|
.banner-wrapper {
|
||||||
gap: 32px;
|
gap: 32px;
|
||||||
|
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.banner-wrapper > .banner-content-wrapper {
|
.banner-wrapper > .banner-content-wrapper {
|
||||||
gap: 24px;
|
gap: 24px;
|
||||||
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -217,6 +210,13 @@ div.highlight {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
margin-right: 3px;
|
margin-right: 3px;
|
||||||
|
background-color: #f0f0f0; /* Placeholder color */
|
||||||
|
opacity: 0; /* Start fully transparent */
|
||||||
|
transition: opacity 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.author-link .hover-item[src] {
|
||||||
|
opacity: 1; /* Fade in when src is set (image loaded) */
|
||||||
}
|
}
|
||||||
|
|
||||||
.hover-item:hover {
|
.hover-item:hover {
|
||||||
|
|
|
||||||
|
|
@ -96,8 +96,10 @@ extra: # version:
|
||||||
|
|
||||||
extra_css:
|
extra_css:
|
||||||
- stylesheets/style.css
|
- stylesheets/style.css
|
||||||
|
|
||||||
extra_javascript:
|
extra_javascript:
|
||||||
- javascript/extra.js
|
- javascript/extra.js
|
||||||
|
- javascript/giscus.js
|
||||||
|
|
||||||
markdown_extensions:
|
markdown_extensions:
|
||||||
- admonition
|
- admonition
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue