How to load external javascript in sphinx-doc - jinja2

I'm extending the basic theme from sphinx-doc and I notice the following code chunk inside basic theme layout.html script macro
{%- for scriptfile in script_files %}
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
{%- endfor %}
Does that mean I can add a html_theme_options like the following inside my theme.conf:
[options]
script_files =
and inside my conf.py, I add:
html_theme_options = {'script_files': '_static'}
However, with this set, the build is totally messed up and produced junk pages like:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>...</head>
<body>
-->
<!-- my js code but is automatically commented out-->
</body>
</html>
Which part goes wrong? What should I do in order to load my own customized javascript? Thanks much!

script_files is a template-internal variable. You cannot set it via html_theme_options (all theme variables have theme_as a prefix, see below).
The Sphinx docs explain here how to add additional scripts directly in the template files, via the script_files variable.
In case you regard it as important to define the additional scripts in your conf.py, proceed as follows:
Add the following line to your template's layout.html, for example below the endblock of the DOCTYPE definition:
{% set script_files = script_files + theme_extra_scripts %}
Define the theme variable extra_scripts and its default value in theme.conf:
extra_scripts = []
Override the variable in conf.py:
html_theme_options = {
'extra_scripts': ['_static/test.js']
}

Related

Trouble with custom footer in sphinx-rtd-theme

I'm having some issues adding a custom footer to my Sphinx .html files. I'm using the sphinx_rtd_theme. I've checked this post and tried it (and some of the suggestions in the comments) but to no avail. I'm not sure what I'm missing. Apologies if I haven't posted enough here to actually indicate what is causing the problem. Any help or suggestions is appreciated!
My css theme file has been (poorly) modified by myself (I'm not an HTML/CSS person!) but I don't think that should matter? The only other thing I can think of is maybe I have to do something special when I re-compile the output files. I just use:
make clean html && make html
My conf.py is located at: root/source/conf.py. Here's some excerpts from my conf.py file:
import sphinx_rtd_theme
project = 'Project Name'
copyright = '2021, My Company'
author = 'My Name, Coworker Name'
master_doc = 'Home'
extensions = ["sphinx_rtd_theme", "sphinx.ext.todo"]
todo_include_todos = True
templates_path = ['_templates']
source_suffix = ['.rst']
html4_writer = True
html_theme = 'sphinx_rtd_theme'
# html_theme_path = ['_static']
html_static_path = ['_static']
# html_extra_path = []
html_show_sphinx = True
html_show_copyright = True
html_style = 'css/my_theme.css'
Here's my layout.html file that I have overridden. It's located in the path shown in the comment.
<!-- layout.html
* Place this file in root/source/_templates
* -->
{% extends "!layout.html" %}
{% block extrahead %}
{{super}}
<link href="{{ pathto("_static/my_theme.css", True) }}" rel="stylesheet" type="text/css">
{% endblock %}
{% block extrafooter %}
{{super}}
<div class="footer">
My custom footer just needs to add a single sentance to the existing footer.
</div>
{% endblock %}
Do you want to add a custom footer or replace the default one? in my case, I only need to override the footer.html file instead of layout.html.
Here's what I do that 100% worked for my Sphinx documentation:
create a footer.html in the _template folder of your Sphinx project.
then add this:
{% extends "!footer.html" %}
{%- block contentinfo %}
{{ super }}
<!-- your custom footer here-->
{% endblock %}
be mindful in which block your footer is actually contained within. In my case it's inside contentinfo
So I found a workaround.
1. Copy existing RTD html files
I copied the existing RTD .html files from my virtual environment folder. On my system it was located at the usual place:
.../Miniconda3/envs/my_env_name/Lib/site-packages/sphinx_rtd_theme/
I found the following files:
breadcrumbs.html
footer.html
Layout.html
search.html
searchbox.html
theme.conf
versions.html
I copied those to my working directory for my project:
.../Documentation-repo/Sphinx/root/source/_templates/
2. Edit conf.py file in working directory
I opened my conf.py file and changed the following:
# Add any paths that contain templates here, relative to this directory.
# Uncomment the line below to enable customized template #
#
# templates_path = ['_templates']
to this:
# Add any paths that contain templates here, relative to this directory.
# Uncomment the line below to enable customized template #
#
templates_path = ['_templates']
3. Add new content to footer.html file
I opened footer.html and edited it to add the content I wanted at the bottom. In my case it was as simple as adding my single sentence of changes below the {%- block extrafooter %} {% endblock %} line. Easy. Might not be the perfect solution but it works for what I need.

How to include ClojureScript into HTML page?

I am following guestbook example from the book Web Development With Clojure 3rd edition. I am struggling with including ClojureScript namespace into HTML document. Everything is working fine with example where I have one core.cljs. With that file, only I have to do is to include this piece of code into home.html document:
{% extends "base.html" %}
{% block content %}
<input id="token" type="hidden" value="{{csrf-token}}">
<div id="content"></div>
{% endblock %}
{% block page-scripts %}
{% script "/js/app.js" %}
{% endblock %}
As I mentioned, everything is ok in this situation. But when I created additional ClojureScript file and name it test.cljs and included that in the same way in the new HTML document named test.html I see errors in the console such as "Target container is not a DOM element.". I think that something is wrong with this part:
{% block page-scripts %}
{% script "/js/app.js" %}
{% endblock %}
But I can't figure out how to solve this. Actually, my question maybe should be: How to include ClojureScript into HTML file?. Is the only way this piece of code?
{% block page-scripts %}
{% script "/js/app.js" %}
{% endblock %}
Or, maybe I should change {% script "/js/app.js" %} part of this snippet?
Or even better, when I create simple HTML file without extending any base.html file, how to add clojurescript namespace, how to reference it? You know, like javascript helloworld example
<script src="myscripts.js"></script>
How to do this in ClojureScript? I am using Luminus framework.
In general, a Luminus project with ClojureScript support will compile all ClojureScript code into a single app.js file, as in this block of the project.clj file (from a project I just created with lein new luminus guestbook +h2 +immutant +cljs, where the +cljs is the important bit):
:cljsbuild{:builds
{:app
{:source-paths ["src/cljs" "src/cljc" "env/dev/cljs"]
:figwheel {:on-jsload "guestbook.core/mount-components"}
:compiler
{:main "guestbook.app"
:asset-path "/js/out"
:output-to "target/cljsbuild/public/js/app.js" ;; <= THIS
:output-dir "target/cljsbuild/public/js/out"
:source-map true
:optimizations :none
:pretty-print true}}}}
That's a very convenient default for single page apps (a la Angular or React), but I think you are thinking of a website with different HTML pages, each one including a different JavaScript file (in this case, everything is compiled to a single JavaScript file).
If you want to call different functions (eg. from different namespaces), you'll need to export them (to make them easily available from JavaScript) and then call each function in their respective HTML file, a bit like the following:
...
<!-- in test.html -->
{% script "/js/app.js" %}
<script>
guestbook.test.init();
</script>
...
in src/cljs/guestbook/test.cljs
(ns guestbook.test)
(defn mount-components []
(let [content (js/document.getElementById "app")]
(while (.hasChildNodes content)
(.removeChild content (.-lastChild content)))
(.appendChild content (js/document.createTextNode "Welcome to the test page"))))
(defn ^:export init []
(mount-components))
Also, remember to rebuild your ClojureScript files. You can leave another terminal running the following command to recompile any ClojureScript files when they change: lein cljsbuild auto

{% load static %} Shown as a text line in html opened on browser

Im trying to use templatetags, but when i write {% load static %} on top of html document and run, it takes this as a text, and does not load the static.
I set the static config in settings.py but stills not working
{% load static%}
<!DOCTYPE html>
<html>
...
</html>
when i open the file on browser or when i send the template via email, as expected in the proyect, the css works, but the images doesnt. I realized i'd use the static dir, but the line: {% load static %} is shown in the browser as text.
Follow the steps below,
In "settings.py" set STATIC_URL = '/static/'
In your template ensure you type {% load static %}, do note that there should be a space between the percentage symbol "%" and the word "static". From your code snippet above this seems to be the source of the problem.
Ensure all your static files are stored in a folder named static as such "/static//example.jpg." then in the html file image tag should be "/example.jpg" %}" alt="My image">.
Do note that the method stated above is only suitable during the development stage. You can read the docs here for more information

Add javascript library to Octopress posts?

For different posts (generated through rake new_post[my_post]), I want to add a javascript function that is to be only included in that post, and nowhere else on the blog.
I can do this by hand-editing the public/my_post/index.html file but then every time I do a rake generate, I will have to do this again.
Is there a built in way to make this happen in Octopress?
Cheers
In 2.1 you will be able to inject per page/post JavaScript or CSS assets into the header by setting some vars in the yaml front matter.
Currently you can simply insert a link or script tag inside of the post or page itself and it will be loaded in place. Example:
<script type="text/javascript" src="/path/to/file.js"></script>
<link rel="stylesheet" type="text/css" href="/path/to/file.css">
Supposing you needed this.js and that.js in a post save them under the newly created /javascripts/custom/ directory.
Than in your default layout add, inside the <head> tag, something like:
{% if page.custom_javascript %}
{% for js in page.custom_javascript %}
<script type="text/javascript" src="/javascripts/custom/{{ js }}"></script>
{% endfor%}
{% endif %}
Finally you can inject per-post javascript simply adding to the post YAML front-matter the field custom_javascript:
---
layout: post
title: "Insert javascript inside head with Octopress"
custom_javascript: [this.js, that.js]
---
Of course you can use a similar approach for others things you need to inject into the <head>.

Custom Variables in Jekyll Front Matter

New to Jekyll and wondering if it's possible to include custom variables in Jekyll Front Matter. It would be useful for nested layouts, for example something like:
layouts/artist.html
----
layout: default
title: {{ page.artist }} (Artist)
----
I get an error trying that.
At the moment, Jekyll do not support Liquid variables in the front matter, and the only way to do that would be through a plugin, such as jekyll-conrefifier.
Alternatively, what you can do, though, is create variables that you re-use on the same file:
{% assign new_title = page.title | append: " (Artist)" %}
<h1>{{ new_title }}</h1>
and you can also pass variables to files that get included. For example, including a file from _includes\display-post.html passing the modified title as an argument:
{% assign new_title = page.title | append: " (Artist)" %}
{% include display-post.html post_title=new_title %}
And then getting the value of the value passed in (example content of _includes\display-post.html):
{% assign title_received = include.post_title %}
<h1>Title that as passed in: {{ title_received }}</h1>
I'm not sure if there is a way to do this properly (i.e. server side), but a stop-gap measure could be to have a small snippet of Javascript that sets the correct title in the users browser. e.g.
---
title: Default title blah blah
---
[... content ...]
<span id="pagetitle" style="display: none">{{ page.artist | escape }} (Artist)</span>
<script type="text/javascript">
var pagetitle = document.getElementById("pagetitle");
if (pagetitle) {
document.title = pagetitle.textContent;
}
</script>
Notes:
The substitution of page.artist is performed in HTML rather than in the Javascript because it is easier to quote any HTML special characters (via escape) rather than the Javascript special characters ' or " or \ (there isn't a built-in filter to do this).
One could also move the pagetitle span to the top of the page so that it is near the other YAML front matter.
Unfortunately, this is a very poor way of achieving this, but it looks like it might be the only way other than writing a plugin.