Pagedown: [html_paged] Using period (.) in a section title crashes Paged.js

Created on 11 Mar 2019  路  10Comments  路  Source: rstudio/pagedown

Thanks for the pagedown package which is simply amazing. I am using the package for writing a little doc using html_paged, and I really appreciate it. I don't know if it is worth to mention, but I noticed a section should not have a dot "." at its end, otherwise it can lead to losing the "page format". Here is a minimal example:

````

title: "A Multi-page HTML Document"
author: "Yves"
date: "r Sys.Date()"
output:
pagedown::html_paged:
toc: true

self_contained: false

Introduction

This is an example of a multi-page HTML document.
See https://pagedown.rbind.io for the full documentation.

Good Morning. The Great world.

````

bug

Most helpful comment

Sorry, I've underestimated the difficulty of this issue.
For now, this issue is not fixed and I reopen it.

Description of the issue

pagedown::html_paged() uses the same Pandoc's extensions as rmarkdown::html_document(), in particular the ascii_identifiers extension to produce automatic identifiers from titles.
With this extension, if a title contains a period (.), the auto identifier will contain a period too.
For instance, if the title is # Good Morning. The Great world, the identifier will be good-morning.-the-great-world.

A period is a valid character for HTML identifiers. But using a period in an HTML identifier is a very bad idea.

Why?
In many circumstances, some JavaScript libraries retrieve a reference to an element. This reference is of the form "#anyidentifier". That value may be used as the argument of a querySelector() method, e.g. document.querySelector("#anyidentifier").
If the identifier contains a period (for instance any.identifier), the call is document.querySelector("#any.identifier").
The meaning of this last CSS selector is from far different: we're looking for element whose identifier is any and of class identifier. So, using a period in an identifier leads to a total mess.

Solutions

JavaScript escaping

There's the CSS.escape() method from the CSSOM Working Draft. That's what I tried to use in https://github.com/rstudio/pagedown/commit/530f01f708dbb6cfee5d511d887be9e0e677b404 without success.

Avoid using any period in identifier

_I recommend this option mostly because the previous one assumes that tier JavaScript libraries escape DOMString._

With Pandoc < 2.5

AFAIK, the only mean is to use a custom identifier, e.g.

# Good Morning. The Great world {#good-morning}
With Pandoc >= 2.5

Since Pandoc 2.5, the gfm_auto_identifiers extension can be used with all formats.

@AKYves I recommend one of these solutions:

  • keep Pandoc < 2.5 and use a custom identifier when there is a period in a title
  • upgrade to Pandoc >= 2.5 and use the gfm_auto_identifiers extension:
    yaml --- title: "A Multi-page HTML Document" author: "Yves" date: "`r Sys.Date()`" output: pagedown::html_paged: toc: true self_contained: false md_extensions: "+gfm_auto_identifiers" ---

All 10 comments

Thanks! I've isolated the problem: this is a bug in one of our JS scripts.

The problem is here: https://github.com/rstudio/pagedown/blob/1ede0069a4050e8672c168375abf7c7bc0e0b1c7/inst/resources/js/config.js#L33

Chrome console log:

DOMException: Failed to execute 'querySelector' on 'Document': '#good-morning.-the-great-world.' is not a valid selector.

@AKYves Could you install the development version and tell me if this is OK for you? It works for me with Chrome 72.0.3626.121 (windows).

Thanks much @RLesur . It works now. I am using the same web browser on linux. :+1:

Please @RLesur and sorry to come back again, I just want to mention that I noticed in #35 there were an issue with page references in table of contents. But now, every section is linking to page 0. I really don't know if it is the same issue or if it is related to this upgrade. Thanks.

@AKYves I didn't notice that... thanks!

Sorry, I've underestimated the difficulty of this issue.
For now, this issue is not fixed and I reopen it.

Description of the issue

pagedown::html_paged() uses the same Pandoc's extensions as rmarkdown::html_document(), in particular the ascii_identifiers extension to produce automatic identifiers from titles.
With this extension, if a title contains a period (.), the auto identifier will contain a period too.
For instance, if the title is # Good Morning. The Great world, the identifier will be good-morning.-the-great-world.

A period is a valid character for HTML identifiers. But using a period in an HTML identifier is a very bad idea.

Why?
In many circumstances, some JavaScript libraries retrieve a reference to an element. This reference is of the form "#anyidentifier". That value may be used as the argument of a querySelector() method, e.g. document.querySelector("#anyidentifier").
If the identifier contains a period (for instance any.identifier), the call is document.querySelector("#any.identifier").
The meaning of this last CSS selector is from far different: we're looking for element whose identifier is any and of class identifier. So, using a period in an identifier leads to a total mess.

Solutions

JavaScript escaping

There's the CSS.escape() method from the CSSOM Working Draft. That's what I tried to use in https://github.com/rstudio/pagedown/commit/530f01f708dbb6cfee5d511d887be9e0e677b404 without success.

Avoid using any period in identifier

_I recommend this option mostly because the previous one assumes that tier JavaScript libraries escape DOMString._

With Pandoc < 2.5

AFAIK, the only mean is to use a custom identifier, e.g.

# Good Morning. The Great world {#good-morning}
With Pandoc >= 2.5

Since Pandoc 2.5, the gfm_auto_identifiers extension can be used with all formats.

@AKYves I recommend one of these solutions:

  • keep Pandoc < 2.5 and use a custom identifier when there is a period in a title
  • upgrade to Pandoc >= 2.5 and use the gfm_auto_identifiers extension:
    yaml --- title: "A Multi-page HTML Document" author: "Yves" date: "`r Sys.Date()`" output: pagedown::html_paged: toc: true self_contained: false md_extensions: "+gfm_auto_identifiers" ---

Waouh... Cool... Thanks much @RLesur ! I will stick to the first option, and create a custom identifier.

fixed by #202

Was this page helpful?
0 / 5 - 0 ratings