Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow including parent headers in child header link ("#parent-header--child-header") #195

Open
marcospgp opened this issue Nov 2, 2023 · 1 comment

Comments

@marcospgp
Copy link

marcospgp commented Nov 2, 2023

I have a notes page on my website which changes often.

When I add new headers, there's a potential for overriding existing ones.

Being able to include the parent headers in a child header's link would prevent, for example, adding a new <h3> earlier in the page than a pre-existing <h3> with the same text from overriding the latter's link.

For now I used this as a workaround on my Jekyll website:

{% if site.enable_anchorjs %}<!-- AnchorJS -->

<script src="https://cdnjs.cloudflare.com/ajax/libs/anchor-js/5.0.0/anchor.min.js"></script>
<script>
    // Set our own IDs for AnchorJS to use when linking to headers.
    //
    // We include parent headers in children header IDs, except for "<h1>"s.
    // This prevents issues such as adding an <h3> to an existing page
    // where an equal <h3> was already present later in the page overriding
    // the latter's link.
    //
    // This was introduced for the Notes page, which changes often.
    const headers = document.querySelectorAll('h2, h3, h4, h5, h6');
    const lastHeaders = {};

    headers.forEach(header => {
        let uniqueId = header.textContent.trim().replace(/\s+/g, '-').toLowerCase();

        const hLevel = parseInt(header.tagName[1]) - 1

        for (let i = hLevel; i >= 2; i--) {
            const lastHeader = lastHeaders['h' + i];
            if (lastHeader) {
                uniqueId = lastHeader.id + '--' + uniqueId;
                break;
            }
        }

        header.id = uniqueId;
        lastHeaders[header.tagName.toLowerCase()] = header;
    });

    anchors.options.visible = 'always';
    anchors.add('article h2, article h3, article h4, article h5, article h6');
</script>

{% endif %}
@bryanbraun
Copy link
Owner

Thanks for sharing your solution.

I want to keep anchor-js as general of a tool as possible, so I'd rather not include a feature for this specific edge-case at the moment. I'm not sure how common it would be it is to have exact name collisions like the ones you're describing.

I like your workaround—let's leave this issue open for a while, so anybody with a similar problem can find it. I may reconsider adding a feature for this if it turns out there's a lot of demand for something like this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants