Sphinx change table of contents HTML - python

I'm working on theming my documentation, and I'm trying to get sphinx to add a class to the <ul> elements of the Table of Contents. Unfortunately, it looks like the HTML is generated just the same as any other list.
Is there a way to add a class to the TOC?
The class that I want to add (fyi) is nav nav-tabs nav-stacked; I'm using a bootstrap theme.
Update: my current hack is to override localtoc.html template to have
{{ toc|replace("<ul>", "<ul class='nav nav-tabs nav-stacked'>") }}
but it feels ugly...

The TOCs are converted to HTML separately and then inserted into the document, without letting you control it. Checkout the render_partial method of sphinx.builds.html.StandaloneHTMLBuilder.
Your hack is the easiest method, the other option is to subclass StandaloneHTMLBuilder and override render_partial to control the docutils' HTMLWriter.

Related

Get list of variables from Jinja2 template (parent and child)

I'm trying to get a list of variables from a Jinja2 template.
test1.j2:
some-non-relevant-content
{{var1}}
{% include 'test2.j2' %}
test2.j2:
another-text
{{var2}}
I can get variables from test1 easily:
env = Environment(loader=FileSystemLoader(searchpath='./Templates'))
src_t = env.loader.get_source(env, 'test1.j2')[0]
parsed_t = env.parse(source=src_t)
t_vars = meta.find_undeclared_variables(ast=parsed_t)
Problem is, I can only get variables from the parent template with get_source.
Obviously, I can not feed class template object to parse method as well.
Is there any way to build the full list? {'var1', 'var2'} in my case.
Ideally by using Jinja2 API. Minimum custom code.
Found a way to code that without a big pain.
meta.find_referenced_templates helps to load all child templates when applied recursively. When done, it's trivial to get variables from all templates in a single list.

Can you have multiple generic subviews of a content element in Kotti?

You can add a 'view' for a content type in kotti by doing something along these lines:
from kotti_mysite.views import poll_view
config.add_view(
poll_view,
context=Poll,
name='view',
permission='view',
renderer='kotti_mysite:templates/poll.pt',
)
(more details: http://kotti.readthedocs.org/en/latest/first_steps/tut-2.html)
You can also have multiple views, and use the 'set default view', but sometimes it's convenient to have several similar views with very similar urls.
For example, in plone, its trivial to have a url structure like this:
/blah/item/ <--- Normal view
/blah/item/json <--- Json version of item
/blah/item/pdf <--- PDF download of item
You can... sort of, do a similar thing in kotti by screwing with the view you create and rendering different content based on get/post params, but it's messy, and frankly, rather rubbish.
The only solution I've found is to have a custom content type 'JsonView' that has a json renderer, and add it as a child of the parent object, and it's renderer looks for the parent content, and renders that.
However, doing this requires you to manually create a 'JsonView' child for every instance of the type you want, which is also rather cumbersome.
Is there a better way of doing this?
--
Nb. Specifically note that having a custom view /blah/item/json isn't any use at all; any type of item, in any parent folder should be able to render in the way described above; using a single static route isn't the right solution.
You can register a json view for all your content like this:
from kotti.interfaces import IContent
config.add_view(
my_json_view,
context=IContent,
name='json',
permission='view',
renderer='json',
)
This way, when you open /blah/json, where /blah points to some content, it will call your my_json_view view.
SQLAlchemy's new class object inspection system might help you write a useful generic json view that works for more than one content type. Alternatively, you can register your view for specific content types only (by use of a more specific context argument in config.add_view).
Using renderer='json' you tell Pyramid that you want to use its json renderer.

Injecting values from a child template into a parent template in Jinja2

I have created a Jinja2 template called lesson.html that defines the basic structure of a lesson. From that, I derive one child template for each actual lesson (since the content of each lesson is different). For example, intro.html, variables.html, lists.html, and functions.html all derive from lesson.html.
Along with slides, exercises, and what-not, each actual lesson has a YouTube video. I want to put the ID of the video in the child template file, but then put the HTML that actually references videos in the parent template (i.e., lesson.html) to ensure that every video is referenced and formatted the same way. For example, I would like lesson.html to look like:
<div class="youtube"><br/>
<iframe title="{{TITLE}}" time="{{TIME}}" src="http://www.youtube.com/embed/{{ID}}"></iframe>
<br/>
</div>
and then have TITLE, TIME, and ID all defined in the child template file itself (since that's the most logical place to store them). My current hack is to create a function that takes these values as arguments and returns a blob of HTML to be inserted in the right place:
{{youtube("Title of this Lecture", "abcde01234", "05:10")|safe}}
but (a) I'd rather use straight template expansion than function calls, and (b) the title, YouTube ID, and time aren't explicitly identified in the lesson template file (which makes them harder to extract for use elsewhere: I can do it with regular expressions, but I'd really rather not).
Is there a clean way to define values in a child template for use in a parent template?
You can use set, DOC are as follows:
Inside code blocks, you can also assign values to variables. Assignments at top level (outside of blocks, macros or loops) are exported from the template like top level macros and can be imported by other templates.
Same question can be found here.

Jinja2: Looking for a View-Helper

I'am new to the Jinja2 template engine. Is there something like the view-helpers from Zend Framework? Can i create simple functions and reuse them all over all my template-files?
Something like this?
#somewhere in my python code:
def nice_demo_function(message):
""""return a simple message"""
return message
So i can to use that:
<!-- now in my template-file -->
{% nice_demo_function('yes, this works great!') %}
There are a number of ways you can expose helper functions to your templates. You could define them using macros, and then import them into templates that use them. You could add functions to the globals attribute of your Template objects, or pass them to the render() method. You could subclass Template to do the same without having to repeat yourself each time. If you want to get really fancy, you could look into writing extensions as well (but you probably don't need to go that deep).
At some point you will have created a Jinja2 environment. The environment has an attribute on it called filters which is a dict that maps names to functions. So what you want to do is:
def my_helper(value):
return "-~*#--- %s ---#*~-" % value
env = Jinja2.Environment(...)
env.filters['my_helper'] = my_helper
Now in your template you can do:
<p>The winner is {{ winner | my_helper }}</p>
And your function will be called with the value of the variable, in this case winner. If you are using Pylons, this all happens in config/environment.py.

concat multiple block in jinja2?

I use jinja2 for my template engine in python.
i would like to join content of multiple block and would like to render it at the end of the template, just before tag. { they are various JavaScript snippets throughout the code in multiple template which i would like to move to the end of the file, how do i do it ? }
edit :
I would like to move all my inline javascript that are created in child jinja templates. I would like to move them to bottom of the page. so I have created a block in the parent template at the end of the page and using it in child template to write javascript. but , there may be multiple child, and so multiple javascript block, and as multiple block does not supported in jinja2 , what is the other solution do i have ? -------- one alternate i think is to create javascript itself in such a way that it does not need to be inline.
I assume that by multiple children, you mean that there are templates inheriting from templates inheriting from templates ... inheriting from the base template. If that's the case, you need to define the same javascript block in each template and call super() in all of the children, in addition to adding more JavaScript. Calling super() prints the output of the parent's javascript block, and so on up the chain of inheritance. Along the way, each block may add code of its own.
So you could have something like this in each template:
{% block javascript %}
{{ super() }}
function foo(x, y) {
return x + y;
}
{% endblock %}

Categories