Skip to content

Commit 318b83c

Browse files
committed
Update tocify code
1 parent 518c35d commit 318b83c

File tree

7 files changed

+144
-109
lines changed

7 files changed

+144
-109
lines changed

bin/bookdown

Lines changed: 2 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,4 @@
11
#!/usr/bin/env node
2-
const Metalsmith = require('metalsmith')
3-
const each = require('lodash/collection/each')
4-
const marked = require('marked')
5-
2+
var bookdown = require('../lib')
63
var app = bookdown(process.cwd())
7-
app.build((err) => {
8-
if (err) throw err
9-
})
10-
11-
function bookdown (cwd) {
12-
return Metalsmith(cwd)
13-
.source('.')
14-
.destination('_bookdown')
15-
.ignore('**/*.!(md)') // ignore non-md files
16-
.ignore('.*') // ignore dot directories
17-
.ignore('node_modules')
18-
.ignore('_bookdown') // ignore output
19-
.ignore('_book')
20-
.use(bookdownParse)
21-
}
22-
23-
function bookdownParse (files, ms, done) {
24-
var sources = Object.keys(files)
25-
console.log(sources)
26-
27-
// 1: find or infer the TOC.
28-
// - strip out docs/ prefix
29-
// - turn the first page in the toc to `index.html`
30-
// - turn README to index
31-
// - flatten it as `pages`
32-
var toc = {
33-
sections: {
34-
'index.html': {
35-
source: 'README.md'
36-
},
37-
'docs.html': {
38-
source: 'docs/docs.md',
39-
sections: {
40-
'rails.html': {
41-
source: 'docs/rails.md'
42-
}
43-
}
44-
},
45-
}
46-
}
47-
48-
files['toc.json'] = {
49-
contents: JSON.stringify(toc) + '\n'
50-
}
51-
52-
// 2: flatten TOC to pages.
53-
var pages = {
54-
'index.html': { source: 'README.md' },
55-
'rails.html': { source: 'docs/rails.md' }
56-
}
57-
58-
files['pages.json'] = {
59-
contents: JSON.stringify(pages) + '\n'
60-
}
61-
62-
63-
// 3: render each page
64-
each(pages, (opts, fname) => {
65-
const file = files[opts.source]
66-
file.markdown = file.contents
67-
file.contents = marked(file.contents.toString(), { gfm: true, tables: true })
68-
files[fname] = file
69-
})
70-
71-
// 4: add assets
72-
73-
// delete sources
74-
sources.forEach((fname) => {
75-
delete files[fname]
76-
})
77-
78-
done()
79-
}
4+
app.build((err) => { if (err) throw err })

lib/index.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
'use strict'
2+
3+
const Metalsmith = require('metalsmith')
4+
const each = require('lodash/collection/each')
5+
const marked = require('marked')
6+
7+
const tocify = require('./tocify')
8+
9+
function bookdown (cwd) {
10+
return Metalsmith(cwd)
11+
.source('.')
12+
.destination('_bookdown')
13+
.ignore('**/*.!(md)') // ignore non-md files
14+
.ignore('.*') // ignore dot directories
15+
.ignore('node_modules')
16+
.ignore('_bookdown') // ignore output
17+
.ignore('_book')
18+
.use(tocifyMd)
19+
.use(bookdownParse)
20+
}
21+
22+
function tocifyMd (files, ms, done) {
23+
if (!files['docs/README.md']) {
24+
var err = new Error('No table of contents found')
25+
return done(err)
26+
}
27+
28+
var toc = tocify(files['docs/README.md'].contents.toString())
29+
30+
// 1: find or infer the TOC.
31+
// - strip out docs/ prefix
32+
// - turn the first page in the toc to `index.html`
33+
// - turn README to index
34+
// - flatten it as `pages`
35+
files['toc.json'] = {
36+
contents: JSON.stringify(toc, null, 2) + '\n'
37+
}
38+
39+
done()
40+
}
41+
42+
function bookdownParse (files, ms, done) {
43+
var sources = Object.keys(files)
44+
console.log(sources)
45+
46+
// 2: flatten TOC to pages.
47+
var pages = {
48+
'index.html': { source: 'README.md' },
49+
'rails.html': { source: 'docs/rails.md' }
50+
}
51+
52+
files['pages.json'] = {
53+
contents: JSON.stringify(pages) + '\n'
54+
}
55+
56+
// 3: render each page
57+
each(pages, (opts, fname) => {
58+
const file = files[opts.source]
59+
file.markdown = file.contents
60+
file.contents = marked(file.contents.toString(), { gfm: true, tables: true })
61+
files[fname] = file
62+
})
63+
64+
// 4: add assets
65+
66+
// delete sources
67+
sources.forEach((fname) => {
68+
if (fname !== 'toc.json') {
69+
delete files[fname]
70+
}
71+
})
72+
73+
done()
74+
}
75+
76+
module.exports = bookdown

lib/tocify.js

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
'use strict'
2+
13
var marked = require('marked')
2-
var slugify = require('slugify')
34

45
module.exports = function tocify (md) {
56
var tokens = marked.lexer(md)
@@ -12,18 +13,30 @@ module.exports = function tocify (md) {
1213
tokens.forEach((token) => {
1314
switch (token.type) {
1415
case 'list_start':
15-
scope = current.sections = {}
16+
scope = current.sections = []
1617
crumbs.push(scope)
1718
break
1819

1920
case 'text':
2021
const m = token.text.match(/^\[([^\]]*)\]\((.*)\)$/)
2122
const title = m ? m[1] : token.text
2223
const source = m ? m[2] : null
23-
const key = slugify(title).toLowerCase()
24+
let url
25+
26+
if (source && source.substr(0, 1) !== '/') {
27+
throw new Error('source not valid: ' + url)
28+
}
29+
30+
if (source) {
31+
url = source.replace(/\.md$/, '.html')
32+
url = url.replace(/README\.html$/, 'index.html')
33+
// url = url.replace(/\/docs\//, '/')
34+
}
2435

25-
current = scope[key] = { title: title }
36+
current = { title }
2637
if (source) current.source = source
38+
if (url) current.url = url
39+
scope.push(current)
2740
break
2841

2942
case 'list_end':

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
},
2020
"devDependencies": {
2121
"expect": "1.11.1",
22-
"mocha": "2.3.3"
22+
"mocha": "2.3.3",
23+
"mocha-standard": "1.0.0",
24+
"standard": "5.3.1"
2325
}
2426
}

test/standard_test.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
var standard = require('mocha-standard')
2+
3+
describe('coding style', function () {
4+
this.timeout(5000)
5+
6+
it('lib conforms to standard', standard.files([
7+
'*.js',
8+
'lib/**/*.js'
9+
]))
10+
11+
it('tests conform to standard', standard.files([
12+
'test/**/*.js'
13+
], {
14+
global: [
15+
'describe', 'it', 'xdescribe', 'xit',
16+
'before', 'beforeEach', 'after', 'afterEach',
17+
'expect'
18+
]
19+
}))
20+
})

test/tocify_test.js

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,35 @@
11
const tocify = require('../lib/tocify')
22

33
describe('tocify', function () {
4-
var toc = [
5-
'# toc',
6-
'',
7-
'* [readme](/README.md)',
8-
].join('\n')
9-
104
var output
115

126
it('works', function () {
137
output = tocify([
14-
'* [Readme](/README.md)',
8+
'* [Readme](/README.md)'
159
].join('\n'))
1610

1711
expect(output).toEqual({
18-
sections: {
19-
readme: {
12+
sections: [
13+
{
2014
title: 'Readme',
15+
url: '/index.html',
2116
source: '/README.md'
2217
}
23-
}
18+
]
2419
})
2520
})
2621

2722
it('handles non-links', function () {
2823
output = tocify([
29-
'* Readme',
24+
'* Readme'
3025
].join('\n'))
3126

3227
expect(output).toEqual({
33-
sections: {
34-
readme: {
28+
sections: [
29+
{
3530
title: 'Readme'
3631
}
37-
}
32+
]
3833
})
3934
})
4035

@@ -47,26 +42,28 @@ describe('tocify', function () {
4742
].join('\n'))
4843

4944
expect(output).toEqual({
50-
sections: {
51-
readme: {
45+
sections: [
46+
{
5247
title: 'Readme',
53-
source: '/README.md',
48+
url: '/index.html',
49+
source: '/README.md'
5450
},
55-
'getting-started': {
51+
{
5652
title: 'Getting Started',
57-
sections: {
58-
'install': {
53+
sections: [
54+
{
5955
title: 'Install',
60-
source: '/docs/install.md',
56+
url: '/docs/install.html',
57+
source: '/docs/install.md'
6158
},
62-
'usage': {
59+
{
6360
title: 'Usage',
64-
source: '/docs/usage.md',
61+
url: '/docs/usage.html',
62+
source: '/docs/usage.md'
6563
}
66-
}
64+
]
6765
}
68-
}
66+
]
6967
})
7068
})
71-
7269
})

test/todo_test.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
describe('to do', function () {
2-
it('parsing toc')
2+
it('parsing toc', done)
3+
it('validating toc')
34
it('flattening toc to pages')
45
it('rendering pages')
56
})
67

8+
function done () {}

0 commit comments

Comments
 (0)