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

Feature: Option for list item indentation #484

Open
zirkelc opened this issue Sep 26, 2024 · 3 comments
Open

Feature: Option for list item indentation #484

zirkelc opened this issue Sep 26, 2024 · 3 comments

Comments

@zirkelc
Copy link

zirkelc commented Sep 26, 2024

The current implementation uses 3 spaces for <li> indentation. In order to change it, we have to add a custom rule.
Would it be possible to add an option to configure this setting, for example as bulletListIndentation?

rules.listItem = {
filter: 'li',
replacement: function (content, node, options) {
content = content
.replace(/^\n+/, '') // remove leading newlines
.replace(/\n+$/, '\n') // replace trailing newlines with just a single one
.replace(/\n/gm, '\n ') // indent
var prefix = options.bulletListMarker + ' '
var parent = node.parentNode
if (parent.nodeName === 'OL') {
var start = parent.getAttribute('start')

If accepted I'd be willing to submit a PR

@martincizek
Copy link
Collaborator

martincizek commented Sep 26, 2024

Hi @zirkelc, actually this was requested a few times. As this neither adds unjustified complexity, nor introduces use case specific behaviour, I think we can add it.

Actually we have implemented it on our project too - as a side effect of different handling of ordered lists that have more than single-digit items.

The constant 3 would be just replaced with a config setting. Maybe listIndentSize (similarly to the "tabsize" option in text editors or listIndentSpaces to emphasize the setting is numeric and not a string with the actual spaces.

function listIndent(content, indentLength) {
  const indent = strings.repeat(' ', indentLength);
  return content
    .replace(/^\n+/, '') // remove leading newlines
    .replace(/\n+$/, '\n') // replace trailing newlines with just a single one
    .replace(/\n/gm, `\n${indent}`); // indent
}

rules.set('listItem', {
  filter: 'li',
  replacement(content, node, options) {
    const parent = node.parentNode;
    let marker = options.bulletListMarker;
    if (parent.nodeName === 'OL') {
      const start = parent.getAttribute('start');
      const index = Array.prototype.indexOf.call(parent.children, node);
      marker = `${start ? Number(start) + index : index + 1}.`;
    }
    const space = repeat(' ', 1 + Math.max(0, 3 - marker.length));
    const prefix = `${marker}${space}`;
    const liContent = listIndent(content, prefix.length);
    const trailNl = node.nextSibling && !/\n$/.test(liContent) ? '\n' : '';
    return `${prefix}${liContent}${trailNl}`;
  },
});

For ordered lists, it works like this:

<it should="respect multi-digit ordered list items">
<turndown>
  <ol start="9">
    <li>a</li>
    <li>b</li>
  </ol>
</turndown>
<produces>
9.  a
10. b
</produces>
</it>

You can try if it does the job for you (e.g. using this as a custom rule) and I'd then implement it.

@zirkelc
Copy link
Author

zirkelc commented Oct 7, 2024

Hi @martincizek

that looks good! I think both listIndentSize and listIndentSpaces are good names.

@zirkelc
Copy link
Author

zirkelc commented Nov 28, 2024

@martincizek do you consider adding this feature? If you're busy, I can draft a PR for 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