markdown-it-table-of-contents icon indicating copy to clipboard operation
markdown-it-table-of-contents copied to clipboard

Add attributes to the TOC list

Open nicofranzp opened this issue 3 years ago • 6 comments

Hi I was wondering if it is possible to add an option to add attributes to the list in the TOC i.e. add a default listAttrs: '' --- around line 28 ---, and replace current line 181 for return '<' + options.listType + ' ' + options.listAttrs +'>' + tocItem.children.map(childItem => { or something similar

nicofranzp avatar Nov 13 '21 04:11 nicofranzp

@nicofranzp Could you clarify which attributes you'd want to set to a list besides the class attribute?

cmaas avatar Nov 16 '21 13:11 cmaas

I thought it might be useful to have access to style and id

nicofranzp avatar Nov 16 '21 17:11 nicofranzp

🤔 hmm not sure about that. Lists are created recursively and listAttrs with an id would be applied to all lists, which doesn't make sense. Same with inline styles. They would be assigned to each list. Would this really be necessary or is it better to have a custom transform function for the container class and then target the rest via CSS selectors? This way, the API is way cleaner and can be understood better.

I think listClass and itemClass as options make sense, but more than that, I can't really see it. Would you actually need this in one of your projects and if so, why is there no other way to access or style lists in the TOC?

cmaas avatar Nov 17 '21 13:11 cmaas

What I ended up using is the following:

function tocItemToHtml(tocItem, options, md, counter = 0) {
  let extraAttributes = ''
  if (counter == 0){
    if (options.listAttrs !== '') { extraAttributes = ' ' + options.listAttrs }
  }
  return '<' + options.listType + extraAttributes + '>' + tocItem.children.map(childItem => {
    let li = '<li>';
    let anchor = childItem.anchor;
    if (options && options.transformLink) {
      anchor = options.transformLink(anchor);
    }

    let text = childItem.text ? options.format(childItem.text, md, anchor) : null;

    li += anchor ? `<a href="#${anchor}">${text}</a>` : (text || '');

    return li + (childItem.children.length > 0 ? tocItemToHtml(childItem, options, md, counter + 1) : '') + '</li>';
  }).join('') + '</' + options.listType + '>';
}

Which avoids adding the same attributes into sub-lists (and the unnecessary white space). Maybe this could be generalized to sublists, but there I understand the concern that the id would not be a goo idea

I had to get rid of the container since the people which I send the final HTML set that constraint. I don't know if that's to specific to be honest, haha

nicofranzp avatar Nov 18 '21 00:11 nicofranzp

That'd work, but before we talk about the actual implementation, please share more details about the scenario you wanna achieve.

What is the exact HTML output you desire? That would be your test case to test against.

Also, do you use markdown-it-table-of-contents in a dynamic context (JS on a website) or in a static context (JS used in a static site generator such as 11ty via node, which is my personal use case)?

cmaas avatar Nov 18 '21 07:11 cmaas

I use it in a static context (I use gulp to combine everything). The built HTML has to have a table of contents without container (which I ditch using md.renderer.rules.toc_open and close) and and set of classes and styles in the <ul> in particular:

<ul id="TOC" class="some clases" style="some styles">
    <li><a href="#S1">Section 1</a></li>
    <li><a href="#S2">Section 2</a></li>
   ...
</ul>

nicofranzp avatar Nov 19 '21 14:11 nicofranzp