Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configurably vendor all external JS/CSS #166

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ celerybeat-schedule
.venv
venv/
ENV/
envs/

# Spyder project settings
.spyderproject
Expand All @@ -103,3 +104,6 @@ ENV/

node_modules/
.vscode

# vendored js/css
vendor/
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@
"webpack-watch-files-plugin": "^1.0.3"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^5.13.0",
"@openfonts/lato_latin-ext": "^1.44.1",
"@openfonts/open-sans_all": "^1.44.1",
"bootstrap": "^4.4.1",
"optimize-css-assets-webpack-plugin": "^5.0.3"
"jquery": "^3.5.0",
"mathjax": "2.7.5",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"popper.js": "^1.16.0"
}
}
81 changes: 79 additions & 2 deletions pydata_sphinx_theme/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,24 @@
"""
import os

import docutils

import sphinx
import sphinx.util.logging
from sphinx.errors import ExtensionError

from .bootstrap_html_translator import BootstrapHTML5Translator
import docutils

__version__ = "0.2.2dev0"

NAME = "pydata_sphinx_theme"

at_least_sphinx_three = sphinx.__version__ >= "3.0.0"

logger = sphinx.util.logging.getLogger(__name__)

warned = {}


def add_toctree_functions(app, pagename, templatename, context, doctree):
"""Add functions so Jinja templates can add toctree objects.
Expand Down Expand Up @@ -167,6 +178,66 @@ def get_edit_url():
# -----------------------------------------------------------------------------


def setup_cdn(app, pagename, templatename, context, doctree):
"""hoist the `use_public_cdns` config value to the template context
"""

use_public_cdns = app.config.use_public_cdns

context["use_public_cdns"] = use_public_cdns

if not has_default_mathjax_path(app):
return

if at_least_sphinx_three or use_public_cdns:
return

mathjax_path = app.config.mathjax_path

if not warned.get("mathjax_path"):
logger.warning(
"`use_public_cdns` is %s, but `mathjax_path` is configured,"
" probably by default, as:\n\n"
" %s\n\n"
"> upgrade to `sphinx >=3`, which supports event `priority`...\n"
"> or configure `mathjax_path` in `conf.py`, e.g.:\n\n"
" import %s\n"
" def setup(app):\n"
" app.config.use_public_cdns = False\n"
" app.config.mathjax_path = %s.get_mathjax_path()\n",
use_public_cdns,
mathjax_path,
NAME,
NAME,
type="configuration",
location=pagename,
)
warned["mathjax_path"] = True
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bollwyvl can you explain the mathjax situation a bit more?

So sphinx has an option to set the mathjax path (https://www.sphinx-doc.org/en/master/usage/extensions/math.html#confval-mathjax_path). But if we use our vendored assets (which included mathjax), we override what a user might have configured for mathjax?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, it's all rather mysterious to me as well!

The math extension adds this configurable and then at env-updated, it adds the mathjax link. I don't know how to intercept it doing that, hence this whole rube goldberg setup.

In sphinx <3 (which i assume needs to be supported) the only way to control the order is the actual extensions order in setup.py, but themes are "special" and don't go there. So it checks whether mathjax_path is set to the default cloudflare value (which is luckily kept around), and will replace only that.

As a user, one can set it to whatever is wanted (e.g. for SVG output) in conf.py and it would still be respected. But vendoring all of MathJax is 75mb, so i just tried to bring in everything that was related to the default output, so if one did want SVG, they'd have to bring all the assets into their _static. This would probably need documentation.



# -----------------------------------------------------------------------------


def configure_mathjax(app, env):
if not app.config.use_public_cdns and has_default_mathjax_path(app):
app.config.mathjax_path = get_mathjax_path()


# -----------------------------------------------------------------------------


def has_default_mathjax_path(app):
if "mathjax_path" not in app.config:
return False

return app.config.mathjax_path == app.config.values["mathjax_path"][0]


def get_mathjax_path():
"""Return the locally-vendored MathJax path"""
return "vendor/mathjax/latest.js?config=TeX-AMS-MML_HTMLorMML"


def get_html_theme_path():
"""Return list of HTML theme paths."""
theme_path = os.path.abspath(os.path.dirname(__file__))
Expand All @@ -175,7 +246,7 @@ def get_html_theme_path():

def setup(app):
theme_path = get_html_theme_path()[0]
app.add_html_theme("pydata_sphinx_theme", theme_path)
app.add_html_theme(NAME, theme_path)
app.set_translator("html", BootstrapHTML5Translator)

# Read the Docs uses ``readthedocs`` as the name of the build, and also
Expand All @@ -185,5 +256,11 @@ def setup(app):
app.set_translator("readthedocsdirhtml", BootstrapHTML5Translator, override=True)
app.connect("html-page-context", setup_edit_url)
app.connect("html-page-context", add_toctree_functions)
app.connect("html-page-context", setup_cdn)

app.add_config_value("use_public_cdns", True, "html")

if at_least_sphinx_three:
app.connect("env-updated", configure_mathjax, priority=-1)

return {"parallel_read_safe": True, "parallel_write_safe": True}
18 changes: 14 additions & 4 deletions pydata_sphinx_theme/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,28 @@
{% endmacro %}

{%- block css %}
{% if use_public_cdns %}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css" integrity="sha384-KA6wR/X5RY4zFAHpv/CnoG2UW1uogYfdnP67Uv7eULvTveboZJg0qUpmJZb5VqzN" crossorigin="anonymous">
<link href="{{ pathto('_static/css/index.css', 1) }}" rel="stylesheet">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:400|Lato:400">
{% else %}
<link rel="stylesheet" href="{{ pathto('_static/vendor/fontawesome/css/all.min.css', 1) }}">
<link rel="stylesheet" href="{{ pathto('_static/vendor/open-sans_all/index.css', 1) }}">
<link rel="stylesheet" href="{{ pathto('_static/vendor/lato_latin-ext/index.css', 1) }}">
{% endif %}
<link rel="stylesheet" href="{{ pathto('_static/css/index.css', 1) }}">
{{- css() }}
{%- endblock %}

{%- block extrahead %}

<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="docsearch:language" content="en">

{% if use_public_cdns %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
{% else %}
<script src="{{ pathto('_static/vendor/bootstrap/bootstrap.bundle.min.js', 1) }}"></script>
{% endif %}
{%- endblock %}

{# Silence the sidebar's, relbar's #}
Expand Down Expand Up @@ -93,4 +103,4 @@

{%- block footer %}
{%- include "footer.html" %}
{%- endblock %}
{%- endblock %}
2 changes: 1 addition & 1 deletion pydata_sphinx_theme/static/css/index.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 2 additions & 5 deletions src/scss/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ $container-max-widths: (
// Include core Bootstrap
@import '../../node_modules/bootstrap/scss/bootstrap';

// Import custom fonts
@import url('https://fonts.googleapis.com/css?family=Open+Sans:400|Lato:400');

@import './base';
@import './navbar';

Expand Down Expand Up @@ -83,8 +80,8 @@ table.field-list {
}
}

/**
* Styling for autosummary tables
/**
* Styling for autosummary tables
*/

// The first column (with the signature) should not wrap
Expand Down
98 changes: 95 additions & 3 deletions webpack.common.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
const path = require('path');
const { resolve } = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');

const staticPath = resolve(__dirname, 'pydata_sphinx_theme/static');
const vendor = resolve(staticPath, 'vendor');

module.exports = {
entry: {
index: ['./src/js/index.js', './src/scss/index.scss'],
},
output: {
filename: 'js/[name].js?[hash]',
path: path.resolve(__dirname, 'pydata_sphinx_theme/static'),
path: staticPath,
},
module: {
rules: [
Expand Down Expand Up @@ -40,5 +44,93 @@ module.exports = {
},
],
},
plugins: [new CleanWebpackPlugin()],
plugins: [
new CleanWebpackPlugin(),
new CopyPlugin([
// bootstrap
{
// includes popper.js
context: './node_modules/bootstrap/dist/js/',
from: 'bootstrap.bundle.min.*',
to: resolve(vendor, 'bootstrap')
},
{
context: './node_modules/bootstrap/',
from: 'LICENSE',
to: resolve(vendor, 'bootstrap')
},
// fonts
{
context: './node_modules/@fortawesome/fontawesome-free/css',
from: 'all.min.css',
to: resolve(vendor, 'fontawesome', 'css')
},
{
context: './node_modules/@fortawesome/fontawesome-free',
from: 'webfonts',
to: resolve(vendor, 'fontawesome', 'webfonts')
},
{
context: './node_modules/@fortawesome/fontawesome-free',
from: 'LICENSE.txt',
to: resolve(vendor, 'fontawesome')
},
{
context: './node_modules/@openfonts/open-sans_all',
from: 'files/*-400*',
to: resolve(vendor, 'open-sans_all')
},
{
context: './node_modules/@openfonts/open-sans_all',
from: 'index.css',
to: resolve(vendor, 'open-sans_all')
},
{
context: './node_modules/@openfonts/open-sans_all',
from: 'LICENSE.md',
to: resolve(vendor, 'open-sans_all')
},
{
context: './node_modules/@openfonts/lato_latin-ext',
from: 'files/*-400*',
to: resolve(vendor, 'lato_latin-ext')
},
{
context: './node_modules/@openfonts/lato_latin-ext',
from: 'index.css',
to: resolve(vendor, 'lato_latin-ext')
},
{
context: './node_modules/@openfonts/lato_latin-ext',
from: 'LICENSE.md',
to: resolve(vendor, 'lato_latin-ext')
},
// mathjax
{
context: './node_modules/mathjax',
from: '*.js',
to: resolve(vendor, 'mathjax')
},
{
context: './node_modules/mathjax',
from: 'jax/output/HTML-CSS',
to: resolve(vendor, 'mathjax/jax/output/HTML-CSS')
},
{
context: './node_modules/mathjax',
from: 'fonts/HTML-CSS/TeX',
to: resolve(vendor, 'mathjax/fonts/HTML-CSS/TeX')
},
{
context: './node_modules/mathjax',
from: 'config/TeX-AMS-MML_HTMLorMML.js',
to: resolve(vendor, 'mathjax/config')
},
{
context: './node_modules/mathjax',
from: 'LICENSE',
to: resolve(vendor, 'mathjax')
},
])
],
};
30 changes: 30 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@
# yarn lockfile v1


"@fortawesome/fontawesome-free@^5.13.0":
version "5.13.0"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.13.0.tgz#fcb113d1aca4b471b709e8c9c168674fbd6e06d9"
integrity sha512-xKOeQEl5O47GPZYIMToj6uuA2syyFlq9EMSl2ui0uytjY9xbe8XS0pexNWmxrdcCyNGyDmLyYw5FtKsalBUeOg==

"@openfonts/lato_latin-ext@^1.44.1":
version "1.44.1"
resolved "https://registry.yarnpkg.com/@openfonts/lato_latin-ext/-/lato_latin-ext-1.44.1.tgz#b36a9c5905e0143f5f72e25cf635625f645603dd"
integrity sha512-uEhdHlTQtLumrWuKHV3JpzH7H1/gGnwXrNC8PAK6StF/Tq1AQPfdjokqgwrHPVQPooj/LAwujhvBwPDdW4/5eQ==

"@openfonts/open-sans_all@^1.44.1":
version "1.44.1"
resolved "https://registry.yarnpkg.com/@openfonts/open-sans_all/-/open-sans_all-1.44.1.tgz#4a05c454a89d0a70eb2f17bfa2ea3f21e3aae091"
integrity sha512-/3uxdiRxH1Sk+llrw4o7lunFhM5IwU/LBo2PU6EYw+iMRNuoUqKU7eyeGtFdAbvErjsU9Xvbe75zkqmsBcXGaw==

"@types/anymatch@*":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a"
Expand Down Expand Up @@ -2895,6 +2910,11 @@ isstream@~0.1.2:
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=

jquery@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.0.tgz#9980b97d9e4194611c36530e7dc46a58d7340fc9"
integrity sha512-Xb7SVYMvygPxbFMpTFQiHh1J7HClEaThguL15N/Gg37Lri/qKyhRGZYzHRyLH8Stq3Aow0LsHO2O2ci86fCrNQ==

js-base64@^2.1.8:
version "2.5.2"
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.2.tgz#313b6274dda718f714d00b3330bbae6e38e90209"
Expand Down Expand Up @@ -3119,6 +3139,11 @@ map-visit@^1.0.0:
dependencies:
object-visit "^1.0.0"

[email protected]:
version "2.7.5"
resolved "https://registry.yarnpkg.com/mathjax/-/mathjax-2.7.5.tgz#c9c5947f86f9be31651f5f3667d3c9a8bb01efe4"
integrity sha512-OzsJNitEHAJB3y4IIlPCAvS0yoXwYjlo2Y4kmm9KQzyIBZt2d8yKRalby3uTRNN4fZQiGL2iMXjpdP1u2Rq2DQ==

md5.js@^1.3.4:
version "1.3.5"
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
Expand Down Expand Up @@ -3919,6 +3944,11 @@ pkg-dir@^3.0.0:
dependencies:
find-up "^3.0.0"

popper.js@^1.16.0:
version "1.16.1"
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b"
integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==

portfinder@^1.0.25:
version "1.0.25"
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca"
Expand Down