Skip to content

Commit

Permalink
Merge pull request #3 from yaycmyk/chore/remark-migration
Browse files Browse the repository at this point in the history
mdast 2.x -> remark 3.x, prep for 1.2.0
  • Loading branch information
Evan Jacobs committed Jan 5, 2016
2 parents 79958b2 + 02c2439 commit 6f5b447
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 43 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# markdown-to-jsx
## Changelog

### 1.2.0 (January 4, 2016)

- Upgrade mdast 2.x to remark 3.x (same project, rewritten internals + changed name)
- Re-enable some tests now that a few bugs in remark/mdast were fixed

### 1.1.0 (December 8, 2015)

- Implement GFM table per-column alignment (d2ab598eaa7b2effc21befc93024ae4eecd1b3d9)
Expand Down
18 changes: 4 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Enables the safe parsing of markdown into proper React JSX objects, so you don't

The only exception is arbitrary HTML in the markdown (kind of an antipattern), which will still use the unsafe method.

Uses [mdast](https://github.com/wooorm/mdast) under the hood to parse markdown into a consistent AST format.
Uses [remark](https://github.com/wooorm/remark) under the hood to parse markdown into a consistent AST format.

Requires React >= 0.14.

Expand All @@ -20,25 +20,15 @@ import {render} from 'react-dom';
render(converter('# Hello world!'), document.body);
```

[mdast options](https://github.com/wooorm/mdast#mdastprocessvalue-options-done) can be passed as the second argument:
[remark options](https://github.com/wooorm/remark#remarkprocessvalue-options-done) can be passed as the second argument:

```js
converter('# Hello world[^2]!\n\n[^2]: A beautiful place.', {footnotes: true});
```


## Development Checklist

- [x] Base library
- [x] Unit testing
- [x] Ship 1.0.0 to npm
- [ ] _stretch goal_ - don't use `dangerouslySetInnerHTML` for arbitrary HTML in the markdown

## Known Issues

- mdast's handling of lists will sometimes add a child paragraph tag inside the
`<li>` where it shouldn't exist - [Bug Ticket](https://github.com/wooorm/mdast/issues/104)

- mdast incorrectly parses footnote definitions with only one word - [Bug Ticket](https://github.com/wooorm/mdast/issues/106)
- remark's handling of lists will sometimes add a child paragraph tag inside the
`<li>` where it shouldn't exist - [Bug Ticket](https://github.com/wooorm/remark/issues/104)

MIT
133 changes: 111 additions & 22 deletions __tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,19 +175,27 @@ describe('markdown-to-jsx', () => {
});

it('should handle an image reference', () => {
const element = render(converter('![][1]\n[1]: /xyz.png'));
const element = render(converter([
'![][1]',
'[1]: /xyz.png',
].join('\n')));

const elementNode = ReactDOM.findDOMNode(element);
const image = elementNode.querySelector('img');

expect(image).not.toBe(null);
/* bug in mdast: https://github.com/wooorm/mdast/issues/103 */
// expect(image.getAttribute('alt')).toBe(null);
expect(image.getAttribute('alt')).toBe(null);
expect(image.getAttribute('title')).toBe(null);
expect(image.src).toBe('/xyz.png');
});

it('should handle an image reference with alt text', () => {
const element = render(converter('![test][1]\n[1]: /xyz.png'));
const element = render(converter([
'![test][1]',
'[1]: /xyz.png',
].join('\n')));

const elementNode = ReactDOM.findDOMNode(element);
const image = elementNode.querySelector('img');

Expand All @@ -198,7 +206,11 @@ describe('markdown-to-jsx', () => {
});

it('should handle an image reference with title', () => {
const element = render(converter('![test][1]\n[1]: /xyz.png "foo"'));
const element = render(converter([
'![test][1]',
'[1]: /xyz.png "foo"',
].join('\n')));

const elementNode = ReactDOM.findDOMNode(element);
const image = elementNode.querySelector('img');

Expand Down Expand Up @@ -233,7 +245,11 @@ describe('markdown-to-jsx', () => {
});

it('should handle a link reference', () => {
const element = render(converter('[foo][1]\n[1]: /xyz.png'));
const element = render(converter([
'[foo][1]',
'[1]: /xyz.png',
].join('\n')));

const elementNode = ReactDOM.findDOMNode(element);
const link = elementNode.querySelector('a');

Expand All @@ -244,7 +260,11 @@ describe('markdown-to-jsx', () => {
});

it('should handle a link reference with title', () => {
const element = render(converter('[foo][1]\n[1]: /xyz.png "bar"'));
const element = render(converter([
'[foo][1]',
'[1]: /xyz.png "bar"',
].join('\n')));

const elementNode = ReactDOM.findDOMNode(element);
const link = elementNode.querySelector('a');

Expand All @@ -258,7 +278,12 @@ describe('markdown-to-jsx', () => {
describe('lists', () => {
/* disabled pending a fix from mdast: https://github.com/wooorm/mdast/issues/104 */
xit('should handle a tight list', () => {
const element = render(converter('- xyz\n- abc\n- foo'));
const element = render(converter([
'- xyz',
'- abc',
'- foo',
].join('\n')));

const elementNode = ReactDOM.findDOMNode(element);
const list = elementNode.querySelector('ul');

Expand All @@ -275,7 +300,14 @@ describe('markdown-to-jsx', () => {
});

it('should handle a loose list', () => {
const element = render(converter('- xyz\n\n- abc\n\n- foo'));
const element = render(converter([
'- xyz',
'',
'- abc',
'',
'- foo',
].join('\n')));

const elementNode = ReactDOM.findDOMNode(element);
const list = elementNode.querySelector('ul');

Expand All @@ -290,7 +322,12 @@ describe('markdown-to-jsx', () => {
});

it('should handle an ordered list', () => {
const element = render(converter('1. xyz\n1. abc\n1. foo'));
const element = render(converter([
'1. xyz',
'1. abc',
'1. foo',
].join('\n')));

const elementNode = ReactDOM.findDOMNode(element);
const list = elementNode.querySelector('ol');

Expand All @@ -302,7 +339,12 @@ describe('markdown-to-jsx', () => {
});

it('should handle an ordered list with a specific start index', () => {
const element = render(converter('2. xyz\n3. abc\n4. foo'));
const element = render(converter([
'2. xyz',
'3. abc',
'4. foo',
].join('\n')));

const elementNode = ReactDOM.findDOMNode(element);
const list = elementNode.querySelector('ol');

Expand All @@ -311,7 +353,12 @@ describe('markdown-to-jsx', () => {
});

it('should handle a nested list', () => {
const element = render(converter('- xyz\n - abc\n- foo'));
const element = render(converter([
'- xyz',
' - abc',
'- foo',
].join('\n')));

const elementNode = ReactDOM.findDOMNode(element);
const list = elementNode.querySelector('ul');

Expand Down Expand Up @@ -357,7 +404,13 @@ describe('markdown-to-jsx', () => {

describe('GFM tables', () => {
it('should handle a basic table', () => {
const element = render(converter('foo|bar\n-|-\n1|2'));
const element = render(converter([
'foo|bar',
'---|---',
'1 |2',
'',
].join('\n')));

const elementNode = ReactDOM.findDOMNode(element);
const table = elementNode.querySelector('table');
const thead = table.querySelector('thead tr');
Expand All @@ -373,7 +426,13 @@ describe('markdown-to-jsx', () => {
});

it('should handle a table with aligned columns', () => {
const element = render(converter('foo|bar\n-:|-\n1|2'));
const element = render(converter([
'foo|bar',
'--:|---',
'1 |2',
'',
].join('\n')));

const elementNode = ReactDOM.findDOMNode(element);
const table = elementNode.querySelector('table');
const thead = table.querySelector('thead tr');
Expand Down Expand Up @@ -412,8 +471,12 @@ describe('markdown-to-jsx', () => {
});

describe('line breaks', () => {
it('should be handled', () => {
const element = render(converter('hello \nthere'));
it('should be added for 2-space sequences', () => {
const element = render(converter([
'hello ',
'there',
].join('\n')));

const elementNode = ReactDOM.findDOMNode(element);
const lineBreak = elementNode.querySelector('br');

Expand All @@ -423,7 +486,12 @@ describe('markdown-to-jsx', () => {

describe('fenced code blocks', () => {
it('should be handled', () => {
const element = render(converter('```js\nfoo\n```'));
const element = render(converter([
'```js',
'foo',
'```',
].join('\n')));

const elementNode = ReactDOM.findDOMNode(element);
const pre = elementNode.querySelector('pre');

Expand All @@ -448,9 +516,11 @@ describe('markdown-to-jsx', () => {

describe('footnotes', () => {
it('should handle conversion of references into links', () => {
const element = render(
converter('foo[^abc] bar\n\n[^abc]: Baz baz', {footnotes: true})
);
const element = render(converter([
'foo[^abc] bar',
'',
'[^abc]: Baz baz',
].join('\n'), {footnotes: true}));

const elementNode = ReactDOM.findDOMNode(element);

Expand All @@ -472,9 +542,11 @@ describe('markdown-to-jsx', () => {
});

it('should inject the definitions in a footer at the end of the root', () => {
const element = render(
converter('foo[^abc] bar\n\n[^abc]: Baz baz', {footnotes: true})
);
const element = render(converter([
'foo[^abc] bar',
'',
'[^abc]: Baz baz',
].join('\n'), {footnotes: true}));

const elementNode = ReactDOM.findDOMNode(element);
const definitions = elementNode.children[1];
Expand All @@ -485,5 +557,22 @@ describe('markdown-to-jsx', () => {
expect(definitions.children[0].id).toBe('abc');
expect(definitions.children[0].textContent).toBe('[abc]: Baz baz');
});

it('should handle single word footnote definitions', () => {
const element = render(converter([
'foo[^abc] bar',
'',
'[^abc]: Baz',
].join('\n'), {footnotes: true}));

const elementNode = ReactDOM.findDOMNode(element);
const definitions = elementNode.children[1];

expect(definitions).not.toBe(null);
expect(definitions.tagName).toBe('FOOTER');
expect(definitions.children[0].tagName).toBe('DIV');
expect(definitions.children[0].id).toBe('abc');
expect(definitions.children[0].textContent).toBe('[abc]: Baz');
});
});
});
10 changes: 6 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import {parse} from 'mdast';
import {parse} from 'remark';

const textTypes = ['text', 'textNode', 'escape'];
const textTypes = ['text', 'textNode'];

let definitions;
let footnotes;
Expand Down Expand Up @@ -290,11 +290,13 @@ function extractDefinitionsFromASTTree(ast) {
});
}

export default function markdownToJSX(markdown, mdastOptions = {}) {
export default function markdownToJSX(markdown, remarkOptions = {}) {
let ast;

remarkOptions.position = remarkOptions.position || false;

try {
ast = parse(markdown, mdastOptions);
ast = parse(markdown, remarkOptions);
} catch (error) {
return error;
}
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
"name": "markdown-to-jsx",
"description": "Interprets markdown text and outputs a JSX equivalent.",
"license": "MIT",
"version": "1.1.0",
"version": "1.2.0",
"keywords": [
"markdown",
"react",
"jsx"
"jsx",
"remark"
],
"author": "Evan Jacobs <evan@yaycmyk.com> (http://yaycmyk.com)",
"repository": "yaycmyk/markdown-to-jsx",
Expand All @@ -23,7 +24,7 @@
"react-dom": "^0.14.0"
},
"dependencies": {
"mdast": "^2.3.0"
"remark": "^3.0.0"
},
"peerDependencies": {
"react": "^0.14.0"
Expand Down

0 comments on commit 6f5b447

Please sign in to comment.