Inconsistent Heading Levels in XWiki Standard

Hi devs,

Hello, I’m just discovering today the proposal at Accessibility proposal: removing extra H1s from the page and it’s a pity I missed it since I’d have been quite strongly against it.

Thus I’m opening this new proposal based on the fact that we’re now having inconsistent heading levels in an XWiki instance (i.e. user pages don’t have the same headings than default pages), and that XWiki is now pushing users to use level 2+ headings when XWiki is not designed for this at all.

For me the fact that our XS default pages now start at heading level 2 (i.e. using ==) is a plain bug. See below for more.

Some of the problems have already been mentioned in some posts (for ex Accessibility proposal: removing extra H1s from the page - #9 by pbodnar) but let me list the issues I see:

  1. The proposal is inconsistent: what is done with standard default pages is different from what users write.

  2. No user base will ever understand nor consistently follow a best practice with a tool that is pushing them to do otherwise. In XWiki when you writing a heading, the first level you’re proposed is a Level 1 (not a Level 2).This forces admins to go through very unnatural hoops, such as Accessibility proposal: removing extra H1s from the page - #10 by Simpel

BTW I’m mentioning users here but it’s same for extension developers. If there are extensions with content you’ll see that they won’t use level 2 headings by default and you’ll need to correct them one by one (it’s normal, it’s completely unnatural to start at level 2). As an example, if you check the Help app (bundled in XS) you’ll find it’s using level 1 headings: http://localhost:8080/xwiki/bin/view/Help/

  1. The whole rendering is made to start at Level 1 and not Level 2. See for example the usage of the TOC macro on a page:

  1. The home page of XWiki is now promoting a bad example usage of XWiki whereas it’s supposed to be a good example (it’s supposed to be demo content that the user edits). It’s promoting using level 2 headings+ and not level 1 which is incomprehensible by users since it’s anti-XWiki (which again is not made for this).

The only valid solution for me is:

At the rendering level map Level 1 to H2, and Level 5 to H6. And for Level 6, also map it to H6 (unless it’s possible to have a H7), but with some CSS to display it as a level 7 visually.

It’s much less a problem since it’s more rare to use a level 6 than a level 1 heading… It would solve all points listed above, while adding a small structural problem for pages using Level 6 headings today (visually it would be fine, the HTML export would still work I think, but the issue would be with Readers which would read them as level 6 and not level 7). For the rare cases where this is a problem, we could even have a configuration option that would keep mapping headings 1 to 6 to H1-H6, to cope with existing XWiki instances using Level 6 headings. And start deprecating level 6 headings (which should have been the case from the beginning if we wanted to only support 5 levels for user-content).

WDYT?

Thx

2 Likes

+1 In fact, this is the approach that Notion has taken as well.

Page Name => H1
Heading 1 => H2
Heading 2 => H3
Heading 3 => H4

They only support user heading up to lvl 3 btw.

1 Like

Seems like a very good idea to me.

One point of discussion is what to do with Markdown content. Do we let users keep <h1> headings if they use a single # for title? Do we show a warning?

There shouldn’t be any problem with any markup syntax since the syntax parsers will transform the markup for heading 1 into a HeadingBlock of level 1 (which will be mapped to H2 in the HTML renderer).

The only little issue (which is not a problem IMO) is for markup syntaxes allowing HTML (i.e. in MD you could use <h1> directly) or when using the {{raw}} macro with HTML. But then it becomes the user’s responsibility and no longer XWiki’s.

Thx

1 Like

I’m not so sure about that, many people follow the standards and use ## for all top-level headings in their document, expecting an <h2> where we would see an <h3> here.

Also, converting ## to a <h3> would be a violation of Markdown’s own spec which specifically indicates how headings should be translated to HTML.

In XWiki, also with Markdown syntax, the document title is metadata that is separate of the content, so having a single # for the document title will duplicate the title which means that this isn’t a use case in XWiki.

I think the best would be to do the transformation only if the document contains at least one h1. The problem with that is that XWiki uses a streaming renderer so we can’t really scan for that. What we could do as an approximation is that we enable the heading layer shifting after the first h1 that is encountered. So if you don’t use h1, heading levels will stay the same, but if you use a h1, it will be transformed into a h2 and everything after that will be shifted by one level, too. The only fear I have is that this could be too magic.

Another problem that hasn’t been mentioned yet is WYSIWYG editing: When we shift heading levels by one level, in the WYSIWYG editor, we have two options:

  1. We don’t shift heading levels when rendering for the editor. This creates accessibility problems (as we will have several h1 again) and style problems (we would need specific styles to shift the heading levels in CSS).
  2. We shift heading levels also for WYSIWYG editing. Then, the user will only see h2 and lower levels in the existing content but could still introduce new h1, creating a huge mess that will be basically impossible to parse back into XWiki syntax correctly. The only option to prevent this would be to prevent using h1 in the WYSIWYG editor.

I like the idea but in particular for WYSIWYG editing, I think there are problems we need to solve.

The spec says that headings start at level 1, see CommonMark Spec

Starting at level 2 is a bug from any user not starting at level 1 (since all docs need to start at H1).

Note that we don’t use Daring Fireball: Markdown Syntax Documentation but CommonMark.

What I find important is that a doc content starts heading with = (ie Heading Level 1). I don’t really see the difference between MD or XWiki Syntax.

I don’t understand this. All docs in XWiki have a title so you always have a H1.

When you choose Level 1 in the WYSIWYG editor, it’ll be displayed as H2 (same as when you view the page). So no, you cannot choose to add a H1. You can only add H2 and below, by choosing heading level 1+.

I don’t see the problem.

Thanks

1 Like

I meant the rendered content that doesn’t include the title.

So basically you suggest re-configuring the WYSIWYG editor to forbid inserting H1/to re-map H1 to H2 etc.?

And then we also modify HTML parsing to parse H2 as H1? If yes, how should HTML parsing treat an actual H1 element, which could, e.g., happen during office import (which converts office documents to HTML and then the HTML to wiki syntax)?

Yes. Basically reconfigure the Style toolbar item (Heading 1 → H2, etc):

Screenshot 2025-07-03 at 14.37.23

Indeed, hadn’t thought of parsing. But yes, it’s logical: if the HTML Renderer renders a HeadingBlock of level 1 to H2, then the HTML parser also needs to do the same and parse a H2 as HeadingBlock of level 1.

Good question re office import and general HTML importing when there’s a H1. I’d need to check how we do it currently but I’d assume that if we find a H1 we should use the heading content as the doc title (and put the section in content, without a heading).

If we find more than one H1 we need to decide what we want to do. The logical thing to do would be to “fix” the headings. The same type of question arise if we have a doc with bad headings such as, for example:

<h3>
....
<h1>
...

Generally speaking we need to shift all HTML headings by 1 when importing HTML content (be it through office import of HTML paste in the wysiwyg editor).

This is starting to be complex :slight_smile: However, we were able to get away from this issue so far at the expense of having several H1s.

So the real question is: Do we really want only a single H1 in HTML-rendered xwiki pages or is acceptable to have several H1? When we did the WCAG/DWG analysis several years ago we said it was acceptable, see https://dev.xwiki.org/xwiki/bin/view/Community/Testing/WCAGTesting/Dutch%20Web%20Guidelines%20WCAG%20testing/#HOtherExceptions where we said:

  • We are using the H1 element several times on pages, once for the page title and once for the header level 1 from the page’s content. We consider that this doesn’t violate the rule “Do not skip any heading elements in the document hierarchy.” since we’re not skipping any level.

If the answer is yes (knowing the consequences), then we currently have a problem with HTML import, independently of this proposal. And we’ll need to work on it.

Thx

When we made our bitv (german wcag) we were urged to use only a single H1. That’s why we did some counter measures. Users can’t choose “Heading 1” anymore in our wysiwyg editor.

CKEDITOR.config.format_tags = 'p;h2;h3;h4;h5;h6;pre';

We removed it from the quick actions too.

config.removeQuickActions = ['h1'];

And we explained the users why they can’t see a heading 1.

CKE_Headlines

We adapted the TOC macro too. By default, the TOC always starts with header 1. The parameter start=“2” can be passed to the TOC, but it cannot be set as the default. This would mean that the list would always have a meaningless leading dot for the empty H1 of the article. However, this dot should disappear.

Yes I’ve followed your other post at Accessibility proposal: removing extra H1s from the page - #10 by Simpel, but XWiki is not made for this ATM and you’ll find problems. This is exactly why, when I realized that we implemented Accessibility proposal: removing extra H1s from the page I thought I had to open this proposal/brainstorming since I don’t believe that 1) we’re offering a real solution so far and 2) what we implemented is inconsistent.

Thx for your feedback