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

Labels #1486

Open
anoblet opened this issue May 9, 2019 · 9 comments
Open

Labels #1486

anoblet opened this issue May 9, 2019 · 9 comments

Comments

@anoblet
Copy link

anoblet commented May 9, 2019

Describe the feature
Task lists should generate a label for their input element

<label>
  <input type="checkbox">Receive promotional offers?</input>
</label>

currently it only generates:

  <input type="checkbox"/> Receive promotional offers?

Why is this feature necessary?
Accessibility is a a rule on performance tests. Checkboxes without labels bring down the score.

Describe alternatives you've considered
NA

Is this already available, or a known issue?

@UziTech
Copy link
Member

UziTech commented May 9, 2019

I agree, accessibility should be important.

Unfortunately that would go against the gfm spec. Since we are focused on following the spec, this might be a better argument for changing the spec.

I'm not even sure where you would go to request such a change.

@anoblet
Copy link
Author

anoblet commented May 9, 2019

I hear you. I'm going to try and see if I can't find someone from Github to comment on the issue.

@UziTech
Copy link
Member

UziTech commented May 9, 2019

The easiest way to do that currently would be to extend the renderer and add the <label>

var marked = require('marked');

var renderer = new marked.Renderer();
var renderListitem = renderer.listitem.bind(renderer);

renderer.listitem = function(text, task) {
  var html = renderListitem(text, task);

  if (task) {
    html = '<li><label>' + html.replace(/^<li>([\s\S]*)<\/li>\n$/, '$1') + '</label></li>\n';
  }

  return html;
};

console.log(marked('- [ ] task', { renderer: renderer }));
// <ul>
// <li><label><input disabled="" type="checkbox"> task</label></li>
// </ul>

I could see there being an issue with this format when you have nested lists. You could have labels inside labels.

The correct way to do this would require parsing the list item and only wrapping the inline text after the checkbox with a <label>

@anoblet
Copy link
Author

anoblet commented May 9, 2019

I don't see that being an issue just yet, but thank you for the snippet. I'm going to try it out now. I also reached out to Github on Twitter and on their forum to see if they have an opinion on whether or not a renderer would be going against spec by implementing this without it being defined. Thanks for all of the help!

@kungpaogao
Copy link

Is there a convenient way to just get the inline text after the checkbox? I'm trying to make checkboxes more accessible with labels, and the solution @UziTech mentioned is pretty good unless there are nested items.

@UziTech
Copy link
Member

UziTech commented Oct 13, 2022

@kungpaogao you can change the regular expression however you want to wrap the label. The best way to do it will depend on your use case. If you want to allow any markdown you could use another tool to create the dom after marked converts it to html and add the label that way.

@kungpaogao
Copy link

kungpaogao commented Oct 16, 2022

@UziTech sorry for the late reply - I'm trying to do something like the following:

- [x] todo item 1 with `inline code` block
- [ ] todo item 2
   - [ ] nested item
       some text underneath that's technically another paragraph

should become something like

<ul>
  <li>
    <label><input type="checkbox" ...>todo item 1 with <code>inline code</code> block</label>
  </li>
  <li>
    <label><input type="checkbox" ...>todo item 2</label>
    <ul>
       <!-- following line could also be wrapped in paragraph tabs (i think that's current behavior) -->
       <label><input type="checkbox" ...>nested item</label>
       <p>some text underneath that's technically another paragraph</p>
    </ul>
  </li>
</ul>

I tried for a while, but I'm stumped on how to only have the <label> wrap the text afterwards + any inline blocks, but not any children/nested list items or block items. Do you have any pointers, or is this use case out of the scope of just extending marked?

@UziTech
Copy link
Member

UziTech commented Oct 16, 2022

Your best bet is to use a different tool. You can still extend marked the way I show above but using regex to add the label in every situation would be difficult.

Ideally you would do something like:

import { marked } from 'marked';

const renderer = new marked.Renderer();
const renderListitem = renderer.listitem.bind(renderer);

renderer.listitem = function(text, task) {
  let html = renderListitem(text, task);

  if (task) {
    // use different tool to parse html and add label
  }

  return html;
};

marked.use({ renderer });

console.log(marked('- [ ] task'));
// <ul>
// <li><label><input disabled="" type="checkbox"> task</label></li>
// </ul>

@kungpaogao
Copy link

kungpaogao commented Oct 25, 2022

thanks for the suggestion! I was able to solve this for my use case by first parsing the list item to

- [x] <label>some todo item</label>

and then using simple string manipulation to move the label tag around

    if (task && text.includes("<label>")) {
      return (
        "<li class='todo-item'><label>" + text.replace("<label>", "") + "</li>"
      );
    }

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

No branches or pull requests

3 participants