summaryrefslogtreecommitdiff
path: root/public
diff options
context:
space:
mode:
authorhoijui2019-10-29 09:58:59 +0100
committerhoijui2019-10-30 17:46:24 +0100
commit3be40b23d11ddded3f5bf8430dc2084e46563f11 (patch)
tree5a00b7a80ebceaf02b72f523facf3a2b00ce3080 /public
parentcfa2ec38c52a2e74112262ebdae9b55c740421d2 (diff)
fix gfm header link generation with respect to `deduplicatedHeaderId`
Signed-off-by: hoijui <hoijui.quaero@gmail.com>
Diffstat (limited to 'public')
-rw-r--r--public/js/extra.js88
1 files changed, 69 insertions, 19 deletions
diff --git a/public/js/extra.js b/public/js/extra.js
index d381576f..810d6146 100644
--- a/public/js/extra.js
+++ b/public/js/extra.js
@@ -825,6 +825,37 @@ const anchorForId = id => {
return anchor
}
+const createHeaderId = (headerContent, headerIds = null) => {
+
+ // to escape characters not allow in css and humanize
+ const slug = slugifyWithUTF8(headerContent)
+ let id
+ if (window.linkifyHeaderStyle === 'keep-case') {
+ id = slug
+ } else if (window.linkifyHeaderStyle === 'lower-case') {
+ // to make compatible with GitHub, GitLab, Pandoc and many more
+ id = slug.toLowerCase()
+ } else if (window.linkifyHeaderStyle === 'gfm') {
+ // see GitHub implementation reference:
+ // https://gist.github.com/asabaylus/3071099#gistcomment-1593627
+ // it works like 'lower-case', but ...
+ const id_base = slug.toLowerCase()
+ id = id_base
+ if (headerIds !== null) {
+ // ... making sure the id is unique
+ let i = 1
+ while (headerIds.has(id)) {
+ id = id_base + '-' + i
+ i++
+ }
+ headerIds.add(id)
+ }
+ } else {
+ throw new Error('Unknown linkifyHeaderStyle value "' + window.linkifyHeaderStyle + '"')
+ }
+ return id
+}
+
const linkifyAnchors = (level, containingElement) => {
const headers = containingElement.getElementsByTagName(`h${level}`)
@@ -832,13 +863,7 @@ const linkifyAnchors = (level, containingElement) => {
let header = headers[i]
if (header.getElementsByClassName('anchor').length === 0) {
if (typeof header.id === 'undefined' || header.id === '') {
- // to escape characters not allow in css and humanize
- let id = slugifyWithUTF8(getHeaderContent(header))
- // to make compatible with GitHub, GitLab, Pandoc and many more
- if (window.linkifyHeaderStyle !== 'keep-case') {
- id = id.toLowerCase()
- }
- header.id = id
+ header.id = createHeaderId(getHeaderContent(header))
}
if (!(typeof header.id === 'undefined' || header.id === '')) {
header.insertBefore(anchorForId(header.id), header.firstChild)
@@ -864,20 +889,45 @@ function getHeaderContent (header) {
return headerHTML[0].innerHTML
}
+function changeHeaderId ($header, id, newId) {
+
+ $header.attr('id', newId)
+ const $headerLink = $header.find(`> a.anchor[href="#${id}"]`)
+ $headerLink.attr('href', `#${newId}`)
+ $headerLink.attr('title', newId)
+}
+
export function deduplicatedHeaderId (view) {
+
+ // headers contained in the last change
const headers = view.find(':header.raw').removeClass('raw').toArray()
- for (let i = 0; i < headers.length; i++) {
- const id = $(headers[i]).attr('id')
- if (!id) continue
- const duplicatedHeaders = view.find(`:header[id="${id}"]`).toArray()
- for (let j = 0; j < duplicatedHeaders.length; j++) {
- if (duplicatedHeaders[j] !== headers[i]) {
- const newId = id + j
- const $duplicatedHeader = $(duplicatedHeaders[j])
- $duplicatedHeader.attr('id', newId)
- const $headerLink = $duplicatedHeader.find(`> a.anchor[href="#${id}"]`)
- $headerLink.attr('href', `#${newId}`)
- $headerLink.attr('title', newId)
+ if (headers.length == 0) {
+ return;
+ }
+ if (window.linkifyHeaderStyle === 'gfm') {
+ // consistent with GitHub, GitLab, Pandoc & co.
+ // all headers contained in the document, in order of appearance
+ const allHeaders = view.find(`:header`).toArray()
+ // list of finaly assigned header IDs
+ let headerIds = new Set()
+ for (let j = 0; j < allHeaders.length; j++) {
+ const $header = $(allHeaders[j])
+ const id = $header.attr('id')
+ const newId = createHeaderId(getHeaderContent($header), headerIds)
+ changeHeaderId($header, id, newId)
+ }
+ } else {
+ // the legacy way
+ for (let i = 0; i < headers.length; i++) {
+ const id = $(headers[i]).attr('id')
+ if (!id) continue
+ const duplicatedHeaders = view.find(`:header[id="${id}"]`).toArray()
+ for (let j = 0; j < duplicatedHeaders.length; j++) {
+ if (duplicatedHeaders[j] !== headers[i]) {
+ const newId = id + j
+ const $header = $(duplicatedHeaders[j])
+ changeHeaderId($header, id, newId)
+ }
}
}
}