Skip to content

Commit

Permalink
feat(checkbox): add support for inline markup in checkbox label (#194)
Browse files Browse the repository at this point in the history
  • Loading branch information
d3m1d0v authored Nov 8, 2022
1 parent 3b63dcb commit 7582017
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 17 deletions.
28 changes: 15 additions & 13 deletions src/transform/plugins/checkbox/checkbox.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import MarkdownIt from 'markdown-it';
import StateCore from 'markdown-it/lib/rules_core/state_core';
import Token from 'markdown-it/lib/token';
import type MarkdownIt from 'markdown-it';
import type StateCore from 'markdown-it/lib/rules_core/state_core';
import type Token from 'markdown-it/lib/token';

// eslint-disable-next-line no-useless-escape
const pattern = /^\[(X|\s|\_|\-)\]\s(.*)/i;
Expand All @@ -26,14 +26,14 @@ export const checkboxReplace = function (_md: MarkdownIt, opts: CheckboxOptions)
};
const options = Object.assign(defaults, opts);

const createTokens = function (checked: boolean, label: string) {
const createTokens = function (state: StateCore, checked: boolean, label: string) {
let token;
const nodes = [];

/**
* <div class="checkbox">
*/
token = new Token('checkbox_open', 'div', 1);
token = new state.Token('checkbox_open', 'div', 1);
token.block = true;
token.attrs = [['class', options.divClass]];
nodes.push(token);
Expand All @@ -43,7 +43,7 @@ export const checkboxReplace = function (_md: MarkdownIt, opts: CheckboxOptions)
*/
const id = options.idPrefix + lastId;
lastId += 1;
token = new Token('checkbox_input', 'input', 0);
token = new state.Token('checkbox_input', 'input', 0);
token.block = true;
token.attrs = [
['type', 'checkbox'],
Expand All @@ -58,36 +58,38 @@ export const checkboxReplace = function (_md: MarkdownIt, opts: CheckboxOptions)
/**
* <label for="checkbox{n}">
*/
token = new Token('checkbox_label_open', 'label', 1);
token = new state.Token('checkbox_label_open', 'label', 1);
token.attrs = [['for', id]];
nodes.push(token);

/**
* content of label tag
*/
token = new Token('text', '', 0);
token = new state.Token('inline', '', 0);
token.children = [];
token.content = label;
state.md.inline.parse(token.content, state.md, state.env, token.children);
nodes.push(token);

/**
* closing tags
*/
token = new Token('checkbox_label_close', 'label', -1);
token = new state.Token('checkbox_label_close', 'label', -1);
token.block = true;
nodes.push(token);
token = new Token('checkbox_close', 'div', -1);
token = new state.Token('checkbox_close', 'div', -1);
token.block = true;
nodes.push(token);
return nodes;
};
const splitTextToken = function (matches: RegExpMatchArray) {
const splitTextToken = function (state: StateCore, matches: RegExpMatchArray) {
let checked = false;
const value = matches[1];
const label = matches[2];
if (value === 'X' || value === 'x') {
checked = true;
}
return createTokens(checked, label);
return createTokens(state, checked, label);
};
return function (state: StateCore) {
const blockTokens = state.tokens;
Expand All @@ -97,7 +99,7 @@ export const checkboxReplace = function (_md: MarkdownIt, opts: CheckboxOptions)
continue;
}

blockTokens.splice(i, 3, ...splitTextToken(match));
blockTokens.splice(i, 3, ...splitTextToken(state, match));
}
};
};
30 changes: 26 additions & 4 deletions test/checkbox.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
'use strict';

import path from 'path';
import transform from '../src/transform';
import plugin from '../src/transform/plugins/checkbox';
import MarkdownIt from 'markdown-it';

const generate = require('markdown-it-testgen');
const assert = require('assert');

const transformYfm = (text: string) => {
const {
result: {html},
} = transform(text, {
plugins: [plugin],
});
return html;
};

describe('markdown-it-checkbox', function () {
describe('markdown-it-checkbox()', function () {
const md = new MarkdownIt({});
Expand All @@ -20,8 +30,9 @@ describe('markdown-it-checkbox', function () {
assert.equal(res, '<h1>test</h1>\n');
});
});
return describe('markdown-it-checkbox(options)', function () {
it('should should optionally wrap arround a div layer', function () {

describe('markdown-it-checkbox(options)', function () {
it('should optionally wrap arround a div layer', function () {
const md = new MarkdownIt({});

md.use(plugin);
Expand All @@ -34,7 +45,8 @@ describe('markdown-it-checkbox', function () {
'</div>\n',
);
});
it('should should optionally change class of div layer', function () {

it('should optionally change class of div layer', function () {
const md = new MarkdownIt({});

md.use(plugin, {
Expand All @@ -49,7 +61,8 @@ describe('markdown-it-checkbox', function () {
'</div>\n',
);
});
return it('should should optionally change the id', function () {

it('should optionally change the id', function () {
const md = new MarkdownIt({});

md.use(plugin, {
Expand All @@ -65,4 +78,13 @@ describe('markdown-it-checkbox', function () {
);
});
});

it('should parse inline markup in label', () => {
expect(transformYfm('[X] text *italic* **bold** label')).toBe(
'<div class="checkbox">\n' +
'<input type="checkbox" id="checkbox0" disabled="" checked="true">\n' +
'<label for="checkbox0">text <em>italic</em> <strong>bold</strong> label</label>\n' +
'</div>\n',
);
});
});

0 comments on commit 7582017

Please sign in to comment.