Opened 9 years ago

Last modified 4 weeks ago

#3558 new enhancement

BlogList macro: Allow the base heading level to be specified

Reported by: James Teh Owned by: Odd Simon Simonsen
Priority: normal Component: FullBlogPlugin
Severity: normal Keywords:
Cc: Mitar Trac Release: 0.11


When using the BlogList macro with the full or float formats, blog posts are rendered with their heading inside an h1 tag. Structurally, this infers a top level heading and associated section. This breaks the structure of a document when the BlogList macro is used to render posts beneath the top level. For example, on the front page of, I use heading level 1 for the page title and heading level 2 for the main section headings. "News" is a main section heading (level 2), so the blog post titles should be at heading level 3.

Attachments (1)

tracfullblog_heading-level.patch (3.8 KB) - added by James Teh 6 years ago.
Patch updated for latest code

Download all attachments as: .zip

Change History (8)

comment:1 Changed 9 years ago by James Teh

This patch uses a stream filter to "rebase" the heading levels. I don't think there is a nice way to do this from within the templates. py:replace or py:match might be used to achieve this, but it would be a bit ugly at best. Nevertheless, a better implementation is welcome.

Note that the web site given as an example above ( has this patch applied. The blog posts appear at heading level 3 instead of heading level 1. Heading level 1 is of course still the default.

comment:2 Changed 8 years ago by Mitar

Cc: Mitar added; anonymous removed

Why was this patch not integrated? I would also like this feature. Even more, I would like to be able to specify base heading level of posts also when listed or displayed standalone (through some configuration option). I would like to do something like for lists:

<h1>Listing description</h1> ... <h2>Post title</h2> ... <h3>First heading level, for example = ... = in post content<h3>

and when displayed standalone:

<h1>Post title</h1> ... <h2>First heading level, for example = ... = in post content<h2>

This would make blog pages semantically valid XML/HTML.

I have tried to do this with site.html template (using #6023):

<py:match path="div[@class='blog-main-list']//h6"><h6>${select('*|text()')}</h6></py:match>
<py:match path="div[@class='blog-main-list']//h5"><h6>${select('*|text()')}</h6></py:match>
<py:match path="div[@class='blog-main-list']//h4"><h5>${select('*|text()')}</h5></py:match>
<py:match path="div[@class='blog-main-list']//h3"><h4>${select('*|text()')}</h4></py:match>
<py:match path="div[@class='blog-main-list']//h2"><h3>${select('*|text()')}</h3></py:match>
<py:match path="div[@class='blog-main-list']//h1"><h2>${select('*|text()')}</h2></py:match>
<py:match path="div[@class='blog-main-list']//div[@class='blog-body']//h6"><h6>${select('*|text()')}</h6></py:match>
<py:match path="div[@class='blog-main-list']//div[@class='blog-body']//h5"><h6>${select('*|text()')}</h6></py:match>
<py:match path="div[@class='blog-main-list']//div[@class='blog-body']//h4"><h6>${select('*|text()')}</h6></py:match>
<py:match path="div[@class='blog-main-list']//div[@class='blog-body']//h3"><h5>${select('*|text()')}</h5></py:match>
<py:match path="div[@class='blog-main-list']//div[@class='blog-body']//h2"><h4>${select('*|text()')}</h4></py:match>
<py:match path="div[@class='blog-main-list']//div[@class='blog-body']//h1"><h3>${select('*|text()')}</h3></py:match>

but it does not work because of the #8770. So the other way I see this to make work is to do it in plugins code. With for example two configuration options which would output from wiki_to_html in post render pipe through header rebaser.

comment:3 Changed 8 years ago by Odd Simon Simonsen

Priority: normalhighest

I've somehow overlooked this ticket and patch. It is useful, and a nice implementation. Thanks jteh!

I'll look to get it integrated as a macro-only thing, and don't think I want to redo the regular blog listings.

comment:4 Changed 8 years ago by Mitar

I doubt it has to be much reworked. Would not it be enough to change line to:

${wiki_to_html(context(post.resource), do_shorten and post.body[:blog_max_size] + ' ... ' or post.body) | HeadingRebaser(list_heading_level_from_config if list_mode else alone_heading_level_from_config)}

with HeadingRebaser from above patch?

comment:5 in reply to:  3 Changed 6 years ago by James Teh

Replying to osimons:

I'll look to get it integrated as a macro-only thing

Is there something that needs to be fixed/changed before this can be committed? I'm happy to try to do the required work if any.

Changed 6 years ago by James Teh

Patch updated for latest code

comment:6 Changed 14 months ago by anonymous

Has any changes with this problem?

comment:7 Changed 4 weeks ago by Ryan J Ollos

Priority: highestnormal

Modify Ticket

Change Properties
Set your email in Preferences
as new The owner will remain Odd Simon Simonsen.

Add Comment

E-mail address and name can be saved in the Preferences.

Note: See TracTickets for help on using tickets.