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

Leading content replaced by TOC if I don't have a heading before it #40

Closed
4 tasks done
dereckmezquita opened this issue Sep 3, 2023 · 5 comments
Closed
4 tasks done
Labels
👯 no/duplicate Déjà vu 👎 phase/no Post cannot or will not be acted on

Comments

@dereckmezquita
Copy link

Initial checklist

Affected packages and versions

^10.1.0

Link to runnable example

No response

Steps to reproduce

If I have my markdown with a TOC insertion point and content directly below it without a header then any content until the next header is removed and replaced with the TOC:

---
title: "Hierarchy in art"
published: true
---

## Table of contents

Here is some content that will get removed.

## test

Some more content.

However, if I do this then my content doesn't get removed:

---
title: "Hierarchy in art"
published: true
---

## Table of contents

## some header any header here even an empty one protects content

Here is some content that will get removed.

## test

Some more content.

Is there a way I can avoid losing that content there? I have my h1 generated from the yaml in my markdown and only want to insert the TOC for any lower level headers h2 etc.

I don't necessarily need my leading content to have a header as this is my de facto introduction etc.

You can consult my source code here; note this is a work in progress: https://github.com/dereckmezquita/derecksnotes.com/tree/v3-nextjs-refactor/client-next

Expected behavior

If I place a TOC header and no following headers then the content should not be removed instead a TOC should be inserted.

Actual behavior

If there is not header after a TOC insertion point and there is content directly after, then any content before the next header gets removed.

Runtime

Node v16

Package manager

npm 8

OS

macOS

Build and bundle tools

Next.js

@github-actions github-actions bot added 👋 phase/new Post is being triaged automatically 🤞 phase/open Post is being triaged manually and removed 👋 phase/new Post is being triaged automatically labels Sep 3, 2023
@ChristianMurphy
Copy link
Member

Duplicate of #18

@ChristianMurphy ChristianMurphy marked this as a duplicate of #18 Sep 3, 2023
@ChristianMurphy ChristianMurphy closed this as not planned Won't fix, can't repro, duplicate, stale Sep 3, 2023
@github-actions

This comment has been minimized.

@github-actions
Copy link

github-actions bot commented Sep 3, 2023

Hi! Thanks for taking the time to contribute!

Because we treat issues as our backlog, we close duplicates to focus our work and not have to touch the same chunk of code for the same reason multiple times. This is also why we may mark something as duplicate that isn’t an exact duplicate but is closely related.

Thanks,
— bb

@github-actions github-actions bot added 👎 phase/no Post cannot or will not be acted on and removed 🤞 phase/open Post is being triaged manually labels Sep 3, 2023
@dereckmezquita
Copy link
Author

dereckmezquita commented Sep 15, 2023

I posted this a while ago because I was not happy with remarkToc; I was not happy with the rigidity - unfortunately, we can't have more options.

I created my own remark plugin using the underlying dependency mdast-util-toc; sharing for others to use:

import { toc, Options as TocOptions } from 'mdast-util-toc';
import { Root } from 'mdast';
import { Node } from 'mdast-util-toc/lib'
import { Plugin } from 'unified';

interface RemarkTocCollapseOptions extends TocOptions {
    heading?: string;
}

/**
 * Plugin to generate a Table of Contents (TOC); does not remove leading paragraphs without headers.
 */
const remarkToc: Plugin<[(RemarkTocOptions | undefined)?], Root> = (options = {}) => {
    return (node: Node) => {
        const result = toc(
            node as Root,
            Object.assign({}, options, {
                heading: options.heading || 'toc|table[ -]of[ -]contents?',
                tight: true,
                maxDepth: 10
            })
        );

        if (
            result.endIndex === null ||
            result.index === null ||
            result.index === -1 ||
            !result.map
        ) {
            return;
        }

        // I don't want remarkToc to remove leading paragraphs with no headers
        if ('children' in node) {
            node.children = [
                ...node.children.slice(0, result.index),
 
                result.map,
               
                ...node.children.slice(result.index)
            ];
        }
    };
};

export default remarkToc;

@wooorm
Copy link
Member

wooorm commented Sep 16, 2023

That algorithm unfortunately doesn’t support repeated calls: it would keep on adding tables of contents repeatedly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
👯 no/duplicate Déjà vu 👎 phase/no Post cannot or will not be acted on
Development

No branches or pull requests

3 participants