Skip to content

Commit 42e4a09

Browse files
committedNov 10, 2017
Add gfm plugins
1 parent 216791b commit 42e4a09

16 files changed

+180747
-0
lines changed
 

‎README.md

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# turndown-plugin-gfm
2+
3+
A [Turndown](https://github.com/domchristie/turndown) plugin which adds GitHub Flavored Markdown extensions.
4+
5+
## Installation
6+
7+
npm:
8+
9+
```
10+
npm install turndown-plugin-gfm
11+
```
12+
13+
Browser:
14+
15+
```html
16+
<script src="https://unpkg.com/turndown/dist/turndown.js"></script>
17+
<script src="https://unpkg.com/turndown/dist/turndown-plugin-gfm.js"></script>
18+
```
19+
20+
## Usage
21+
22+
```js
23+
// For Node.js
24+
var TurndownService = require('turndown')
25+
var turndownPluginGfm = require('turndown-plugin-gfm')
26+
27+
var gfm = turndownPluginGfm.gfm
28+
var turndownService = new TurndownService()
29+
turndownService.use(gfm)
30+
var markdown = turndownService.turndown('<strike>Hello world!</strike>')
31+
```
32+
33+
turndown-plugin-gfm is a suite of plugins which can be applied individually. The available plugins are as follows:
34+
35+
- `strikethrough` (for converting `<strike>`, `<s>`, and `<del>` elements)
36+
- `tables`
37+
- `taskListItems`
38+
- `gfm` (which applies all of the above)
39+
40+
So for example, if you only wish to convert tables:
41+
42+
```js
43+
var tables = require('turndown-plugin-gfm').tables
44+
var turndownService = new TurndownService()
45+
turndownService.use(tables)
46+
```
47+
48+
## License
49+
50+
turndown-plugin-gfm is copyright © 2017+ Dom Christie and released under the MIT license.

‎config/rollup.config.browser.cjs.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import config from './rollup.config'
2+
3+
export default config({
4+
output: {
5+
format: 'cjs',
6+
file: 'lib/turndown-plugin-gfm.browser.cjs.js'
7+
}
8+
})

‎config/rollup.config.browser.es.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import config from './rollup.config'
2+
3+
export default config({
4+
output: {
5+
format: 'es',
6+
file: 'lib/turndown-plugin-gfm.browser.es.js'
7+
}
8+
})

‎config/rollup.config.cjs.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import config from './rollup.config'
2+
3+
export default config({
4+
output: {
5+
format: 'cjs',
6+
file: 'lib/turndown-plugin-gfm.cjs.js'
7+
}
8+
})

‎config/rollup.config.es.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import config from './rollup.config'
2+
3+
export default config({
4+
output: {
5+
format: 'es',
6+
file: 'lib/turndown-plugin-gfm.es.js'
7+
}
8+
})

‎config/rollup.config.iife.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import config from './rollup.config'
2+
3+
export default config({
4+
output: {
5+
format: 'iife',
6+
file: 'dist/turndown-plugin-gfm.js'
7+
}
8+
})

‎config/rollup.config.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default function (config) {
2+
return {
3+
name: 'turndownPluginGfm',
4+
input: 'src/gfm.js',
5+
output: config.output
6+
}
7+
}

‎package-lock.json

+3,576
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"name": "turndown-plugin-gfm",
3+
"description": "Turndown plugin to add GitHub Flavored Markdown extensions.",
4+
"version": "0.0.1",
5+
"author": "Dom Christie",
6+
"devDependencies": {
7+
"browserify": "^14.5.0",
8+
"rollup": "^0.50.0",
9+
"standard": "^10.0.3",
10+
"turndown": "0.0.8",
11+
"turndown-attendant": "0.0.2"
12+
},
13+
"files": [
14+
"lib",
15+
"dist"
16+
],
17+
"jsnext:main": "lib/turndown-plugin-gfm.es.js",
18+
"keywords": [
19+
"turndown",
20+
"turndown-plugin",
21+
"html-to-markdown",
22+
"html",
23+
"markdown",
24+
"github-flavored-markdown",
25+
"gfm"
26+
],
27+
"license": "MIT",
28+
"main": "lib/turndown-plugin-gfm.cjs.js",
29+
"module": "lib/turndown-plugin-gfm.es.js",
30+
"scripts": {
31+
"build": "npm run build-cjs && npm run build-es && npm run build-iife",
32+
"build-cjs": "rollup -c config/rollup.config.cjs.js && rollup -c config/rollup.config.browser.cjs.js",
33+
"build-es": "rollup -c config/rollup.config.es.js && rollup -c config/rollup.config.browser.es.js",
34+
"build-iife": "rollup -c config/rollup.config.iife.js",
35+
"build-test": "browserify test/turndown-plugin-gfm-test.js --outfile test/turndown-plugin-gfm-test.browser.js",
36+
"prepublish": "npm run build",
37+
"test": "npm run build && standard ./src/**/*.js && node test/turndown-plugin-gfm-test.js"
38+
}
39+
}

‎src/gfm.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import strikethrough from './strikethrough'
2+
import tables from './tables'
3+
import taskListItems from './task-list-items'
4+
5+
function gfm (turndownService) {
6+
turndownService.use([strikethrough, tables, taskListItems])
7+
}
8+
9+
export { gfm, strikethrough, tables, taskListItems }

‎src/strikethrough.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export default function strikethrough (turndownService) {
2+
turndownService.addRule('strikethrough', {
3+
filter: ['del', 's', 'strike'],
4+
replacement: function (content) {
5+
return '~' + content + '~'
6+
}
7+
})
8+
}

‎src/tables.js

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
var rules = {}
2+
3+
rules.tableCell = {
4+
filter: ['th', 'td'],
5+
replacement: function (content, node) {
6+
return cell(content, node)
7+
}
8+
}
9+
10+
rules.tableRow = {
11+
filter: 'tr',
12+
replacement: function (content, node) {
13+
var borderCells = ''
14+
var alignMap = { left: ':--', right: '--:', center: ':-:' }
15+
16+
if (node.parentNode.nodeName === 'THEAD') {
17+
for (var i = 0; i < node.childNodes.length; i++) {
18+
var align = node.childNodes[i].attributes.align
19+
var border = '---'
20+
21+
if (align) border = alignMap[align.value] || border
22+
23+
borderCells += cell(border, node.childNodes[i])
24+
}
25+
}
26+
return '\n' + content + (borderCells ? '\n' + borderCells : '')
27+
}
28+
}
29+
30+
rules.table = {
31+
filter: 'table',
32+
replacement: function (content) {
33+
// Ensure there are no blank lines
34+
content = content.replace('\n\n', '\n')
35+
return '\n\n' + content + '\n\n'
36+
}
37+
}
38+
39+
rules.tableSection = {
40+
filter: ['thead', 'tbody', 'tfoot'],
41+
replacement: function (content) {
42+
return content
43+
}
44+
}
45+
46+
function cell (content, node) {
47+
var index = Array.prototype.indexOf.call(node.parentNode.childNodes, node)
48+
var prefix = ' '
49+
if (index === 0) prefix = '| '
50+
return prefix + content + ' |'
51+
}
52+
53+
export default function tables (turndownService) {
54+
for (var key in rules) turndownService.addRule(key, rules[key])
55+
}

‎src/task-list-items.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export default function taskListItems (turndownService) {
2+
turndownService.addRule('taskListItems', {
3+
filter: function (node) {
4+
return node.type === 'checkbox' && node.parentNode.nodeName === 'LI'
5+
},
6+
replacement: function (content, node) {
7+
return (node.checked ? '[x]' : '[ ]') + ' '
8+
}
9+
})
10+
}

‎test/index.html

+178
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<title>turndown test runner</title>
6+
<link rel="stylesheet" href="../node_modules/turndown-attendant/dist/styles.css">
7+
</head>
8+
<body>
9+
10+
<!-- TEST CASES -->
11+
12+
<div class="case" data-name="strike">
13+
<div class="input"><strike>Lorem ipsum</strike></div>
14+
<pre class="expected">~Lorem ipsum~</pre>
15+
</div>
16+
17+
<div class="case" data-name="s">
18+
<div class="input"><s>Lorem ipsum</s></div>
19+
<pre class="expected">~Lorem ipsum~</pre>
20+
</div>
21+
22+
<div class="case" data-name="del">
23+
<div class="input"><del>Lorem ipsum</del></div>
24+
<pre class="expected">~Lorem ipsum~</pre>
25+
</div>
26+
27+
<div class="case" data-name="unchecked inputs">
28+
<div class="input"><ul><li><input type=checkbox>Check Me!</li></ul></div>
29+
<pre class="expected">* [ ] Check Me!</pre>
30+
</div>
31+
32+
<div class="case" data-name="checked inputs">
33+
<div class="input"><ul><li><input type=checkbox checked>Checked!</li></ul></div>
34+
<pre class="expected">* [x] Checked!</pre>
35+
</div>
36+
37+
<div class="case" data-name="basic table">
38+
<div class="input">
39+
<table>
40+
<thead>
41+
<tr>
42+
<th>Column 1</th>
43+
<th>Column 2</th>
44+
</tr>
45+
</thead>
46+
<tbody>
47+
<tr>
48+
<td>Row 1, Column 1</td>
49+
<td>Row 1, Column 2</td>
50+
</tr>
51+
<tr>
52+
<td>Row 2, Column 1</td>
53+
<td>Row 2, Column 2</td>
54+
</tr>
55+
</tbody>
56+
</table>
57+
</div>
58+
<pre class="expected">| Column 1 | Column 2 |
59+
| --- | --- |
60+
| Row 1, Column 1 | Row 1, Column 2 |
61+
| Row 2, Column 1 | Row 2, Column 2 |</pre>
62+
</div>
63+
64+
<div class="case" data-name="cell alignment">
65+
<div class="input">
66+
<table>
67+
<thead>
68+
<tr>
69+
<th align="left">Column 1</th>
70+
<th align="center">Column 2</th>
71+
<th align="right">Column 3</th>
72+
<th align="foo">Column 4</th>
73+
</tr>
74+
</thead>
75+
<tbody>
76+
<tr>
77+
<td>Row 1, Column 1</td>
78+
<td>Row 1, Column 2</td>
79+
<td>Row 1, Column 3</td>
80+
<td>Row 1, Column 4</td>
81+
</tr>
82+
<tr>
83+
<td>Row 2, Column 1</td>
84+
<td>Row 2, Column 2</td>
85+
<td>Row 2, Column 3</td>
86+
<td>Row 2, Column 4</td>
87+
</tr>
88+
</tbody>
89+
</table>
90+
</div>
91+
<pre class="expected">| Column 1 | Column 2 | Column 3 | Column 4 |
92+
| :-- | :-: | --: | --- |
93+
| Row 1, Column 1 | Row 1, Column 2 | Row 1, Column 3 | Row 1, Column 4 |
94+
| Row 2, Column 1 | Row 2, Column 2 | Row 2, Column 3 | Row 2, Column 4 |</pre>
95+
</div>
96+
97+
<div class="case" data-name="empty cells">
98+
<div class="input">
99+
<table>
100+
<thead>
101+
<tr>
102+
<th align="left">Column 1</th>
103+
<th align="center">Column 2</th>
104+
<th align="right">Column 3</th>
105+
<th align="foo">Column 4</th>
106+
</tr>
107+
</thead>
108+
<tbody>
109+
<tr>
110+
<td></td>
111+
<td>Row 1, Column 2</td>
112+
<td>Row 1, Column 3</td>
113+
<td>Row 1, Column 4</td>
114+
</tr>
115+
<tr>
116+
<td>Row 2, Column 1</td>
117+
<td></td>
118+
<td>Row 2, Column 3</td>
119+
<td>Row 2, Column 4</td>
120+
</tr>
121+
<tr>
122+
<td>Row 3, Column 1</td>
123+
<td>Row 3, Column 2</td>
124+
<td></td>
125+
<td>Row 3, Column 4</td>
126+
</tr>
127+
<tr>
128+
<td>Row 4, Column 1</td>
129+
<td>Row 4, Column 2</td>
130+
<td>Row 4, Column 3</td>
131+
<td></td>
132+
</tr>
133+
<tr>
134+
<td></td>
135+
<td></td>
136+
<td></td>
137+
<td>Row 5, Column 4</td>
138+
</tr>
139+
</tbody>
140+
</table>
141+
</div>
142+
<pre class="expected">| Column 1 | Column 2 | Column 3 | Column 4 |
143+
| :-- | :-: | --: | --- |
144+
| | Row 1, Column 2 | Row 1, Column 3 | Row 1, Column 4 |
145+
| Row 2, Column 1 | | Row 2, Column 3 | Row 2, Column 4 |
146+
| Row 3, Column 1 | Row 3, Column 2 | | Row 3, Column 4 |
147+
| Row 4, Column 1 | Row 4, Column 2 | Row 4, Column 3 | |
148+
| | | | Row 5, Column 4 |</pre>
149+
</div>
150+
151+
<div class="case" data-name="empty rows">
152+
<div class="input">
153+
<table>
154+
<tbody>
155+
<tr>
156+
<td>Row 1</td>
157+
<td>Row 1</td>
158+
</tr>
159+
<tr>
160+
<td></td>
161+
<td></td>
162+
</tr>
163+
<tr>
164+
<td>Row 3</td>
165+
<td>Row 3</td>
166+
</tr>
167+
</tbody>
168+
</table>
169+
</div>
170+
<pre class="expected">| Row 1 | Row 1 |
171+
| Row 3 | Row 3 |</pre>
172+
</div>
173+
174+
<!-- /TEST CASES -->
175+
176+
<script src="turndown-plugin-gfm-test.browser.js"></script>
177+
</body>
178+
</html>

‎test/turndown-plugin-gfm-test.browser.js

+176,762
Large diffs are not rendered by default.

‎test/turndown-plugin-gfm-test.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
var Attendant = require('turndown-attendant')
2+
var TurndownService = require('../../to-markdown/lib/turndown.cjs')
3+
var gfm = require('../lib/turndown-plugin-gfm.cjs').gfm
4+
5+
var attendant = new Attendant({
6+
file: __dirname + '/index.html',
7+
TurndownService: TurndownService,
8+
beforeEach: function (turndownService) {
9+
turndownService.use(gfm)
10+
}
11+
})
12+
13+
attendant.run()

0 commit comments

Comments
 (0)
Please sign in to comment.