mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-25 03:06:31 -05:00
fix gfm header link generation with respect to deduplicatedHeaderId
Signed-off-by: hoijui <hoijui.quaero@gmail.com>
This commit is contained in:
parent
cfa2ec38c5
commit
3be40b23d1
1 changed files with 69 additions and 19 deletions
|
@ -825,6 +825,37 @@ const anchorForId = id => {
|
||||||
return anchor
|
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 linkifyAnchors = (level, containingElement) => {
|
||||||
const headers = containingElement.getElementsByTagName(`h${level}`)
|
const headers = containingElement.getElementsByTagName(`h${level}`)
|
||||||
|
|
||||||
|
@ -832,13 +863,7 @@ const linkifyAnchors = (level, containingElement) => {
|
||||||
let header = headers[i]
|
let header = headers[i]
|
||||||
if (header.getElementsByClassName('anchor').length === 0) {
|
if (header.getElementsByClassName('anchor').length === 0) {
|
||||||
if (typeof header.id === 'undefined' || header.id === '') {
|
if (typeof header.id === 'undefined' || header.id === '') {
|
||||||
// to escape characters not allow in css and humanize
|
header.id = createHeaderId(getHeaderContent(header))
|
||||||
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
|
|
||||||
}
|
}
|
||||||
if (!(typeof header.id === 'undefined' || header.id === '')) {
|
if (!(typeof header.id === 'undefined' || header.id === '')) {
|
||||||
header.insertBefore(anchorForId(header.id), header.firstChild)
|
header.insertBefore(anchorForId(header.id), header.firstChild)
|
||||||
|
@ -864,20 +889,45 @@ function getHeaderContent (header) {
|
||||||
return headerHTML[0].innerHTML
|
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) {
|
export function deduplicatedHeaderId (view) {
|
||||||
|
|
||||||
|
// headers contained in the last change
|
||||||
const headers = view.find(':header.raw').removeClass('raw').toArray()
|
const headers = view.find(':header.raw').removeClass('raw').toArray()
|
||||||
for (let i = 0; i < headers.length; i++) {
|
if (headers.length == 0) {
|
||||||
const id = $(headers[i]).attr('id')
|
return;
|
||||||
if (!id) continue
|
}
|
||||||
const duplicatedHeaders = view.find(`:header[id="${id}"]`).toArray()
|
if (window.linkifyHeaderStyle === 'gfm') {
|
||||||
for (let j = 0; j < duplicatedHeaders.length; j++) {
|
// consistent with GitHub, GitLab, Pandoc & co.
|
||||||
if (duplicatedHeaders[j] !== headers[i]) {
|
// all headers contained in the document, in order of appearance
|
||||||
const newId = id + j
|
const allHeaders = view.find(`:header`).toArray()
|
||||||
const $duplicatedHeader = $(duplicatedHeaders[j])
|
// list of finaly assigned header IDs
|
||||||
$duplicatedHeader.attr('id', newId)
|
let headerIds = new Set()
|
||||||
const $headerLink = $duplicatedHeader.find(`> a.anchor[href="#${id}"]`)
|
for (let j = 0; j < allHeaders.length; j++) {
|
||||||
$headerLink.attr('href', `#${newId}`)
|
const $header = $(allHeaders[j])
|
||||||
$headerLink.attr('title', newId)
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue