diff options
author | Sheogorath | 2019-12-03 14:40:00 +0100 |
---|---|---|
committer | GitHub | 2019-12-03 14:40:00 +0100 |
commit | 33150b79c7a4c3ba456afdadb31c709b3be18980 (patch) | |
tree | e8f4be1a385a70336830e1851ab86d7d9fb686a5 /public | |
parent | 2ddec15af8e77fcad85e62ee8c0b6eccefc52405 (diff) | |
parent | ad1a2fb19c842ea5e4cb46a24989ce95b2041902 (diff) |
Merge pull request #218 from hoijui/linkifyHeaderStyle
Linkify header style
Diffstat (limited to 'public')
-rw-r--r-- | public/js/extra.js | 85 | ||||
-rw-r--r-- | public/js/lib/common/constant.ejs | 2 |
2 files changed, 67 insertions, 20 deletions
diff --git a/public/js/extra.js b/public/js/extra.js index d381576f..6cda6171 100644 --- a/public/js/extra.js +++ b/public/js/extra.js @@ -825,6 +825,36 @@ 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 idBase = slug.toLowerCase() + id = idBase + if (headerIds !== null) { + // ... making sure the id is unique + let i = 1 + while (headerIds.has(id)) { + id = idBase + '-' + 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 +862,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 +888,43 @@ 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 + const 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) + } } } } diff --git a/public/js/lib/common/constant.ejs b/public/js/lib/common/constant.ejs index bbcb8c7a..114a9077 100644 --- a/public/js/lib/common/constant.ejs +++ b/public/js/lib/common/constant.ejs @@ -5,6 +5,6 @@ window.version = '<%- version %>' window.allowedUploadMimeTypes = <%- JSON.stringify(allowedUploadMimeTypes) %> -window.linkifyHeaderStyle = <%- JSON.stringify(linkifyHeaderStyle) %> +window.linkifyHeaderStyle = '<%- linkifyHeaderStyle %>' window.DROPBOX_APP_KEY = '<%- DROPBOX_APP_KEY %>' |