Skip to content

Commit

Permalink
Add styles based on the documentation tool (#473)
Browse files Browse the repository at this point in the history
Use our heuristic to detect the documentation tool/theme and add
specific `--readthedocs-*` CSS variables based on that for known
tools/themes.

Reference:
readthedocs/readthedocs.org#11849 (comment)

---------

Co-authored-by: Anthony <[email protected]>
  • Loading branch information
humitos and agjohnson committed Jan 22, 2025
1 parent f8c7c30 commit 928ecdc
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 14 deletions.
7 changes: 7 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,11 @@ export const ASCIIDOCTOR = "asciidoctor";
export const JEKYLL = "jekyll";
export const DOCSIFY = "docsify";
export const ANTORA = "antora";
export const MDBOOK = "mdbook";
export const FALLBACK_DOCTOOL = "fallback";

// Known documentation tools themes
export const SPHINX_ALABASTER = "alabaster";
export const SPHINX_FURO = "furo";
export const SPHINX_READTHEDOCS = "readthedocs";
export const SPHINX_IMMATERIAL = "immaterial";
33 changes: 33 additions & 0 deletions src/doctools.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Specific styles based on documentation tools and themes
*
* Usage of `@layer` at-rule pushes this rules down a step in
* precedence/priority. This allows a user `:root` rule to override these
* values.
**/
@layer defaults {
:root[data-readthedocs-tool="mkdocs-material"] {
--readthedocs-font-size: 0.58rem;
--readthedocs-flyout-font-size: 0.58rem;
}

:root[data-readthedocs-tool="antora"] {
--readthedocs-font-size: 0.7rem;
--readthedocs-flyout-font-size: 0.7rem;
}

:root[data-readthedocs-tool="mdbook"] {
--readthedocs-font-size: 1.3rem;
--readthedocs-flyout-font-size: 1.3rem;
}

:root[data-readthedocs-tool="sphinx"][data-readthedocs-tool-theme="furo"] {
--readthedocs-font-size: 0.725rem;
--readthedocs-flyout-font-size: 0.725rem;
}

:root[data-readthedocs-tool="sphinx"][data-readthedocs-tool-theme="immaterial"] {
--readthedocs-font-size: 0.58rem;
--readthedocs-flyout-font-size: 0.58rem;
}
}
20 changes: 12 additions & 8 deletions src/flyout.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
/* New */
/* Flyout styles */

:host {
/* These variables are used more than once, use a local variable so we can set
* a default in this addon */
--addons-flyout-font-size: var(
--readthedocs-flyout-font-size,
var(--readthedocs-font-size, 0.8rem)
);
--addons-flyout-line-height: var(--readthedocs-flyout-line-height, 1.25em);
}

.container {
position: fixed;
Expand All @@ -7,6 +17,7 @@
height: auto;
max-height: calc(100% - 100px);
overflow-y: auto;
line-height: var(--addons-flyout-line-height);
}

.container.bottom-right {
Expand All @@ -29,13 +40,6 @@
top: 50px;
}

:host {
--addons-flyout-font-size: var(
--readthedocs-flyout-font-size,
var(--readthedocs-font-size, 0.8rem)
);
}

:host > div {
font-family: var(
--readthedocs-flyout-font-family,
Expand Down
8 changes: 4 additions & 4 deletions src/flyout.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { default as objectPath } from "object-path";

import styleSheet from "./flyout.css";
import { AddonBase, addUtmParameters, getLinkWithFilename } from "./utils";
import { SPHINX, MKDOCS_MATERIAL } from "./constants";
import {
EVENT_READTHEDOCS_SEARCH_SHOW,
EVENT_READTHEDOCS_FLYOUT_HIDE,
Expand All @@ -38,6 +39,8 @@ export class FlyoutElement extends LitElement {
this.opened = false;
this.floating = true;
this.position = "bottom-right";
this.classes = { floating: this.floating, container: true };
this.classes[this.position] = true;
this.readthedocsLogo = READTHEDOCS_LOGO;
}

Expand Down Expand Up @@ -319,11 +322,8 @@ export class FlyoutElement extends LitElement {
return nothing;
}

const classes = { floating: this.floating, container: true };
classes[this.position] = true;

return html`
<div class=${classMap(classes)}>
<div class=${classMap(this.classes)}>
${this.renderHeader()}
<main class=${classMap({ closed: !this.opened })}>
${this.renderLanguages()} ${this.renderVersions()}
Expand Down
31 changes: 31 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { CSSResult } from "lit";

import { getReadTheDocsConfig } from "./readthedocs-config";
import * as notification from "./notification";
import * as analytics from "./analytics";
Expand All @@ -11,13 +13,16 @@ import * as filetreediff from "./filetreediff";
import * as customscript from "./customscript";
import { default as objectPath } from "object-path";
import {
docTool,
domReady,
isEmbedded,
IS_PRODUCTION,
setupLogging,
getMetadataValue,
} from "./utils";

import doctoolsStyleSheet from "./doctools.css";

export function setup() {
const addons = [
flyout.FlyoutAddon,
Expand Down Expand Up @@ -50,6 +55,32 @@ export function setup() {
}
}

// Apply fixes to variables for individual documentation tools
const elementHtml = document.querySelector("html");
if (elementHtml) {
// Inject styles at the parent DOM to set variables at :root
let styleSheet = doctoolsStyleSheet;
if (doctoolsStyleSheet instanceof CSSResult) {
styleSheet = doctoolsStyleSheet.styleSheet;
}
document.adoptedStyleSheets = [styleSheet];

// If we detect a documentation tool, set attributes on :root to allow
// for CSS selectors to utilize these values.
if (docTool.documentationTool) {
elementHtml.setAttribute(
"data-readthedocs-tool",
docTool.documentationTool,
);
}
if (docTool.documentationTheme) {
elementHtml.setAttribute(
"data-readthedocs-tool-theme",
docTool.documentationTheme,
);
}
}

return getReadTheDocsConfig(sendUrlParam);
})
.then((config) => {
Expand Down
76 changes: 74 additions & 2 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import { ajv } from "./data-validation";
import { default as objectPath } from "object-path";
import {
SPHINX,
SPHINX_FURO,
SPHINX_ALABASTER,
SPHINX_READTHEDOCS,
SPHINX_IMMATERIAL,
MDBOOK,
MKDOCS,
MKDOCS_MATERIAL,
DOCUSAURUS,
Expand Down Expand Up @@ -297,6 +302,7 @@ export class DocumentationTool {

constructor() {
this.documentationTool = this.getDocumentationTool();
this.documentationTheme = this.getDocumentationTheme();
console.debug(`Documentation tool detected: ${this.documentationTool}`);
}

Expand Down Expand Up @@ -411,10 +417,63 @@ export class DocumentationTool {
return DOCSIFY;
}

if (this.isMdBook()) {
return MDBOOK;
}

if (this.isAntora()) {
return ANTORA;
}

console.debug("We were not able to detect the documentation tool.");
return null;
}

getDocumentationTheme() {
const documentationTool =
this.documentationTool || this.getDocumentationTool();

if (documentationTool === SPHINX) {
if (this.isSphinxAlabasterLikeTheme()) {
return SPHINX_ALABASTER;
} else if (this.isSphinxReadTheDocsLikeTheme()) {
return SPHINX_READTHEDOCS;
} else if (this.isSphinxFuroLikeTheme()) {
return SPHINX_FURO;
} else if (this.isSphinxImmaterialLikeTheme()) {
return SPHINX_IMMATERIAL;
}
}

// TODO: add the other known themes
return null;
}

isAntora() {
if (
document.querySelectorAll('meta[name="generator"][content^="Antora"]')
.length
) {
return true;
}
return false;
}

isMdBook() {
// <head>
// <!-- Book generated using mdBook -->
// <meta charset="UTF-8">
// ...
if (
document?.head?.firstChild?.nextSibling?.textContent.includes(
"Book generated using mdBook",
)
) {
return true;
}
return false;
}

isDocsify() {
if (document.querySelectorAll("head > link[href*=docsify]").length) {
return true;
Expand All @@ -427,7 +486,8 @@ export class DocumentationTool {
this.isSphinxAlabasterLikeTheme() ||
this.isSphinxReadTheDocsLikeTheme() ||
this.isSphinxFuroLikeTheme() ||
this.isSphinxBookThemeLikeTheme()
this.isSphinxBookThemeLikeTheme() ||
this.isSphinxImmaterialLikeTheme()
);
}

Expand Down Expand Up @@ -476,7 +536,7 @@ export class DocumentationTool {
// MkDocs version : 1.4.2
// Build Date UTC : 2023-07-11 16:08:07.379780+00:00
// -->
if (document.lastChild.textContent.includes("MkDocs version :")) {
if (document?.lastChild?.textContent.includes("MkDocs version :")) {
return true;
}
return false;
Expand Down Expand Up @@ -531,6 +591,18 @@ export class DocumentationTool {
return false;
}

isSphinxImmaterialLikeTheme() {
if (
document.querySelectorAll(
'link[href^="_static/sphinx_immaterial_theme"]',
'a[href="https://github.com/jbms/sphinx-immaterial/"][rel="noopener"]',
).length
) {
return true;
}
return false;
}

isMaterialMkDocsTheme() {
if (
document.querySelectorAll(
Expand Down

0 comments on commit 928ecdc

Please sign in to comment.