Skip to content

Commit

Permalink
Merge pull request #82 from yaycmyk/pull-prop-overrides
Browse files Browse the repository at this point in the history
Allow component/prop overrides for special rendering cases
  • Loading branch information
Evan Jacobs authored Sep 26, 2016
2 parents d2ebb69 + 25f70a6 commit 7fb7beb
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 16 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ Depending on the type of element, there are some props that must be preserved to
- `a`: `title`, `href`
- `img`: `title`, `alt`, `src`
- `input[type="checkbox"]`: `checked`, `readonly` (specifically, the one rendered by a GFM task list)
- `ol`: `start`
- `td`: `style`
- `th`: `style`
Expand Down
48 changes: 34 additions & 14 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -412,12 +412,22 @@ export default function markdownToJSX(markdown, {overrides = {}} = {}) {
const key = index || '0';

if (ast.type === 'code' && ast.value) {
return (
<pre key={key}>
<code className={`lang-${ast.lang}`}>
{ast.value}
</code>
</pre>
const preProps = get(overrides, 'pre.props', {});
const codeProps = get(overrides, 'code.props', {});

preProps.key = key;
codeProps.className = codeProps.className
? `${codeProps.className} lang-${ast.lang}`
: `lang-${ast.lang}`;

return React.createElement(
get(overrides, 'pre.component', 'pre'),
preProps,
React.createElement(
get(overrides, 'code.component', 'code'),
codeProps,
ast.value
),
);
} /* Refers to fenced blocks, need to create a pre:code nested structure */

Expand All @@ -436,14 +446,24 @@ export default function markdownToJSX(markdown, {overrides = {}} = {}) {

if (ast.type === 'listItem') {
if (ast.checked === true || ast.checked === false) {
return (
<li key={key}>
<input key='checkbox'
type="checkbox"
checked={ast.checked}
disabled />
{ast.children.map(astToJSX)}
</li>
const liProps = get(overrides, 'li.props', {});

liProps.key = key;

const inputProps = get(overrides, 'input.props', {});

inputProps.key = 'checkbox';
inputProps.type = 'checkbox';
inputProps.checked = ast.checked;
inputProps.readOnly = true;

return React.createElement(
get(overrides, 'li.component', 'li'),
liProps,
[
React.createElement(get(overrides, 'input.component', 'input'), inputProps),
ast.children.map(astToJSX),
],
);
} /* gfm task list, need to add a checkbox */
}
Expand Down
108 changes: 106 additions & 2 deletions index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -403,13 +403,13 @@ describe('markdown-to-jsx', () => {
expect(checkbox.parentNode.textContent).toBe('foo');
});

it('should disable the checkboxes', () => {
it('should mark the checkboxes as readonly', () => {
const element = render(converter('- [x] foo'));
const $element = dom(element);
const checkbox = $element.querySelector('ul li input');

expect(checkbox).not.toBe(null);
expect(checkbox.disabled).toBe(true);
expect(checkbox.readOnly).toBe(true);
});
});

Expand Down Expand Up @@ -695,5 +695,109 @@ describe('markdown-to-jsx', () => {
expect($element.className).toBe('abc');
expect($element.textContent).toBe('Hello.');
});

it('should add props to pre & code tags if supplied', () => {
const element = render(
converter(`
\`\`\`
foo
\`\`\`
`, {
overrides: {
code: {
props: {
'data-foo': 'bar',
},
},

pre: {
props: {
className: 'abc',
},
},
},
})
);

const $element = dom(element);

expect($element.tagName).toBe('PRE');
expect($element.className).toBe('abc');
expect($element.textContent).toContain('foo');
expect($element.children[0].tagName).toBe('CODE');
expect($element.children[0].getAttribute('data-foo')).toBe('bar');
});

it('should substitute pre & code tags if supplied with an override component', () => {
class OverridenPre extends React.Component {
render() {
const {children, ...props} = this.props;

return (
<pre {...props} data-bar='baz'>{children}</pre>
);
}
}

class OverridenCode extends React.Component {
render() {
const {children, ...props} = this.props;

return (
<code {...props} data-baz='fizz'>{children}</code>
);
}
}

const element = render(
converter(`
\`\`\`
foo
\`\`\`
`, {
overrides: {
code: {
component: OverridenCode,
props: {
'data-foo': 'bar',
},
},

pre: {
component: OverridenPre,
props: {
className: 'abc',
},
},
},
})
);

const $element = dom(element);

expect($element.tagName).toBe('PRE');
expect($element.className).toBe('abc');
expect($element.getAttribute('data-bar')).toBe('baz');
expect($element.textContent).toContain('foo');
expect($element.children[0].tagName).toBe('CODE');
expect($element.children[0].getAttribute('data-foo')).toBe('bar');
expect($element.children[0].getAttribute('data-baz')).toBe('fizz');
});

it('should be able to override gfm task list items', () => {
const element = render(converter('- [ ] foo', {overrides: {li: {props: {className: 'foo'}}}}));
const $element = dom(element).querySelector('li');

expect($element).not.toBe(null);
expect($element.className).toContain('foo');
});

it('should be able to override gfm task list item checkboxes', () => {
const element = render(converter('- [ ] foo', {overrides: {input: {props: {className: 'foo'}}}}));
const $element = dom(element).querySelector('input');

expect($element).not.toBe(null);
expect($element.className).toContain('foo');
});
});
});

0 comments on commit 7fb7beb

Please sign in to comment.