diff --git a/asset/js/setup.js b/asset/js/setup.js index c6b54ef24f..85c4ac4bb6 100644 --- a/asset/js/setup.js +++ b/asset/js/setup.js @@ -40,6 +40,12 @@ function setupAnchors() { top: calc(-${headerHeight}px - ${bufferHeight}rem) }`, ); + insertCss(`span.card-container::before { + display: block; + content: ''; + margin-top: calc(-${headerHeight}px - ${bufferHeight}rem); + height: calc(${headerHeight}px + ${bufferHeight}rem); + }`); } jQuery('h1, h2, h3, h4, h5, h6, .header-wrapper').each((index, heading) => { if (heading.id) { @@ -48,13 +54,6 @@ function setupAnchors() { jQuery(heading).on('mouseleave', () => jQuery(heading).find('.fa.fa-anchor').css('visibility', 'hidden')); if (isFixed) { - /** - * Fixing the top navbar would break anchor navigation, - * by creating empty spans above the tag we can prevent - * the headings from being covered by the navbar. - */ - const spanId = heading.id; - heading.insertAdjacentHTML('beforebegin', ``); jQuery(heading).removeAttr('id'); // to avoid duplicated id problem } } diff --git a/src/Page.js b/src/Page.js index 9b007a1602..34af722c83 100644 --- a/src/Page.js +++ b/src/Page.js @@ -1172,9 +1172,35 @@ class Page { this.pluginsContext[pluginName] || {}, this.frontMatter, this.getPluginConfig()); } }); + // After rendering everything, add dummy spans to headings if a fixed header is present. + postRenderedContent = Page._postRenderForFixedHeader(postRenderedContent); return postRenderedContent; } + /** + * Generate dummy spans if fixed header is used. + * @param content HTML content to be rendered. + * @return {string} Rendered HTML content. + * @private + */ + static _postRenderForFixedHeader(content) { + const $ = cheerio.load(content, { xmlMode: false }); + const hasHeader = $('header')[0] !== undefined; + if (hasHeader) { + // Check if the first header has a class named 'header-fixed' + const isFixed = $('header')[0].attribs === undefined + ? false : $('header')[0].attribs.class === 'header-fixed'; + if (isFixed) { + $('h1, h2, h3, h4, h5, h6, .header-wrapper').each((index, heading) => { + const spanId = heading.attribs.id; + $(heading).prepend(``); + }); + } + return $.html(); + } + return content; + } + /** * Collect page content inserted by plugins */ diff --git a/test/functional/test_site/expected/markbind/js/setup.js b/test/functional/test_site/expected/markbind/js/setup.js index c6b54ef24f..85c4ac4bb6 100644 --- a/test/functional/test_site/expected/markbind/js/setup.js +++ b/test/functional/test_site/expected/markbind/js/setup.js @@ -40,6 +40,12 @@ function setupAnchors() { top: calc(-${headerHeight}px - ${bufferHeight}rem) }`, ); + insertCss(`span.card-container::before { + display: block; + content: ''; + margin-top: calc(-${headerHeight}px - ${bufferHeight}rem); + height: calc(${headerHeight}px + ${bufferHeight}rem); + }`); } jQuery('h1, h2, h3, h4, h5, h6, .header-wrapper').each((index, heading) => { if (heading.id) { @@ -48,13 +54,6 @@ function setupAnchors() { jQuery(heading).on('mouseleave', () => jQuery(heading).find('.fa.fa-anchor').css('visibility', 'hidden')); if (isFixed) { - /** - * Fixing the top navbar would break anchor navigation, - * by creating empty spans above the tag we can prevent - * the headings from being covered by the navbar. - */ - const spanId = heading.id; - heading.insertAdjacentHTML('beforebegin', ``); jQuery(heading).removeAttr('id'); // to avoid duplicated id problem } } diff --git a/test/functional/test_site_algolia_plugin/expected/markbind/js/setup.js b/test/functional/test_site_algolia_plugin/expected/markbind/js/setup.js index c6b54ef24f..85c4ac4bb6 100644 --- a/test/functional/test_site_algolia_plugin/expected/markbind/js/setup.js +++ b/test/functional/test_site_algolia_plugin/expected/markbind/js/setup.js @@ -40,6 +40,12 @@ function setupAnchors() { top: calc(-${headerHeight}px - ${bufferHeight}rem) }`, ); + insertCss(`span.card-container::before { + display: block; + content: ''; + margin-top: calc(-${headerHeight}px - ${bufferHeight}rem); + height: calc(${headerHeight}px + ${bufferHeight}rem); + }`); } jQuery('h1, h2, h3, h4, h5, h6, .header-wrapper').each((index, heading) => { if (heading.id) { @@ -48,13 +54,6 @@ function setupAnchors() { jQuery(heading).on('mouseleave', () => jQuery(heading).find('.fa.fa-anchor').css('visibility', 'hidden')); if (isFixed) { - /** - * Fixing the top navbar would break anchor navigation, - * by creating empty spans above the tag we can prevent - * the headings from being covered by the navbar. - */ - const spanId = heading.id; - heading.insertAdjacentHTML('beforebegin', ``); jQuery(heading).removeAttr('id'); // to avoid duplicated id problem } } diff --git a/test/functional/test_site_convert/expected/markbind/js/setup.js b/test/functional/test_site_convert/expected/markbind/js/setup.js index c6b54ef24f..85c4ac4bb6 100644 --- a/test/functional/test_site_convert/expected/markbind/js/setup.js +++ b/test/functional/test_site_convert/expected/markbind/js/setup.js @@ -40,6 +40,12 @@ function setupAnchors() { top: calc(-${headerHeight}px - ${bufferHeight}rem) }`, ); + insertCss(`span.card-container::before { + display: block; + content: ''; + margin-top: calc(-${headerHeight}px - ${bufferHeight}rem); + height: calc(${headerHeight}px + ${bufferHeight}rem); + }`); } jQuery('h1, h2, h3, h4, h5, h6, .header-wrapper').each((index, heading) => { if (heading.id) { @@ -48,13 +54,6 @@ function setupAnchors() { jQuery(heading).on('mouseleave', () => jQuery(heading).find('.fa.fa-anchor').css('visibility', 'hidden')); if (isFixed) { - /** - * Fixing the top navbar would break anchor navigation, - * by creating empty spans above the tag we can prevent - * the headings from being covered by the navbar. - */ - const spanId = heading.id; - heading.insertAdjacentHTML('beforebegin', ``); jQuery(heading).removeAttr('id'); // to avoid duplicated id problem } } diff --git a/test/functional/test_site_expressive_layout/expected/markbind/js/setup.js b/test/functional/test_site_expressive_layout/expected/markbind/js/setup.js index c6b54ef24f..85c4ac4bb6 100644 --- a/test/functional/test_site_expressive_layout/expected/markbind/js/setup.js +++ b/test/functional/test_site_expressive_layout/expected/markbind/js/setup.js @@ -40,6 +40,12 @@ function setupAnchors() { top: calc(-${headerHeight}px - ${bufferHeight}rem) }`, ); + insertCss(`span.card-container::before { + display: block; + content: ''; + margin-top: calc(-${headerHeight}px - ${bufferHeight}rem); + height: calc(${headerHeight}px + ${bufferHeight}rem); + }`); } jQuery('h1, h2, h3, h4, h5, h6, .header-wrapper').each((index, heading) => { if (heading.id) { @@ -48,13 +54,6 @@ function setupAnchors() { jQuery(heading).on('mouseleave', () => jQuery(heading).find('.fa.fa-anchor').css('visibility', 'hidden')); if (isFixed) { - /** - * Fixing the top navbar would break anchor navigation, - * by creating empty spans above the tag we can prevent - * the headings from being covered by the navbar. - */ - const spanId = heading.id; - heading.insertAdjacentHTML('beforebegin', ``); jQuery(heading).removeAttr('id'); // to avoid duplicated id problem } } diff --git a/test/functional/test_site_special_tags/expected/markbind/js/setup.js b/test/functional/test_site_special_tags/expected/markbind/js/setup.js index c6b54ef24f..85c4ac4bb6 100644 --- a/test/functional/test_site_special_tags/expected/markbind/js/setup.js +++ b/test/functional/test_site_special_tags/expected/markbind/js/setup.js @@ -40,6 +40,12 @@ function setupAnchors() { top: calc(-${headerHeight}px - ${bufferHeight}rem) }`, ); + insertCss(`span.card-container::before { + display: block; + content: ''; + margin-top: calc(-${headerHeight}px - ${bufferHeight}rem); + height: calc(${headerHeight}px + ${bufferHeight}rem); + }`); } jQuery('h1, h2, h3, h4, h5, h6, .header-wrapper').each((index, heading) => { if (heading.id) { @@ -48,13 +54,6 @@ function setupAnchors() { jQuery(heading).on('mouseleave', () => jQuery(heading).find('.fa.fa-anchor').css('visibility', 'hidden')); if (isFixed) { - /** - * Fixing the top navbar would break anchor navigation, - * by creating empty spans above the tag we can prevent - * the headings from being covered by the navbar. - */ - const spanId = heading.id; - heading.insertAdjacentHTML('beforebegin', ``); jQuery(heading).removeAttr('id'); // to avoid duplicated id problem } } diff --git a/test/functional/test_site_templates/test_default/expected/markbind/js/setup.js b/test/functional/test_site_templates/test_default/expected/markbind/js/setup.js index c6b54ef24f..85c4ac4bb6 100644 --- a/test/functional/test_site_templates/test_default/expected/markbind/js/setup.js +++ b/test/functional/test_site_templates/test_default/expected/markbind/js/setup.js @@ -40,6 +40,12 @@ function setupAnchors() { top: calc(-${headerHeight}px - ${bufferHeight}rem) }`, ); + insertCss(`span.card-container::before { + display: block; + content: ''; + margin-top: calc(-${headerHeight}px - ${bufferHeight}rem); + height: calc(${headerHeight}px + ${bufferHeight}rem); + }`); } jQuery('h1, h2, h3, h4, h5, h6, .header-wrapper').each((index, heading) => { if (heading.id) { @@ -48,13 +54,6 @@ function setupAnchors() { jQuery(heading).on('mouseleave', () => jQuery(heading).find('.fa.fa-anchor').css('visibility', 'hidden')); if (isFixed) { - /** - * Fixing the top navbar would break anchor navigation, - * by creating empty spans above the tag we can prevent - * the headings from being covered by the navbar. - */ - const spanId = heading.id; - heading.insertAdjacentHTML('beforebegin', ``); jQuery(heading).removeAttr('id'); // to avoid duplicated id problem } } diff --git a/test/functional/test_site_templates/test_minimal/expected/markbind/js/setup.js b/test/functional/test_site_templates/test_minimal/expected/markbind/js/setup.js index c6b54ef24f..85c4ac4bb6 100644 --- a/test/functional/test_site_templates/test_minimal/expected/markbind/js/setup.js +++ b/test/functional/test_site_templates/test_minimal/expected/markbind/js/setup.js @@ -40,6 +40,12 @@ function setupAnchors() { top: calc(-${headerHeight}px - ${bufferHeight}rem) }`, ); + insertCss(`span.card-container::before { + display: block; + content: ''; + margin-top: calc(-${headerHeight}px - ${bufferHeight}rem); + height: calc(${headerHeight}px + ${bufferHeight}rem); + }`); } jQuery('h1, h2, h3, h4, h5, h6, .header-wrapper').each((index, heading) => { if (heading.id) { @@ -48,13 +54,6 @@ function setupAnchors() { jQuery(heading).on('mouseleave', () => jQuery(heading).find('.fa.fa-anchor').css('visibility', 'hidden')); if (isFixed) { - /** - * Fixing the top navbar would break anchor navigation, - * by creating empty spans above the tag we can prevent - * the headings from being covered by the navbar. - */ - const spanId = heading.id; - heading.insertAdjacentHTML('beforebegin', ``); jQuery(heading).removeAttr('id'); // to avoid duplicated id problem } }