Skip to content

Commit d8fa8b0

Browse files
committed
Document the refactoring
1 parent 3ed22eb commit d8fa8b0

File tree

3 files changed

+121
-60
lines changed

3 files changed

+121
-60
lines changed

lib/fix_html.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'use strict'
22

3-
const cheerio = require('cheerio')
43
const slugify = require('slugify')
54
const resolve = require('path').resolve
65
const dirname = require('path').dirname
@@ -10,11 +9,9 @@ const relative = require('path').relative
109
* Performs syntax highlighting and stuff.
1110
*/
1211

13-
module.exports = function fixHtml (html, fname, sources, files) {
14-
const $ = cheerio.load(html)
12+
module.exports = function fixHtml ($, fname, sources, files) {
1513
idify($)
1614
fixReferences($, fname, sources, files)
17-
return $.html()
1815
}
1916

2017
/**

lib/index.js

Lines changed: 114 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const ware = require('ware')
44
const each = require('lodash/collection/each')
55
const markdownIt = require('markdown-it')
6+
const cheerio = require('cheerio')
67

78
const tocify = require('./tocify')
89
const indexify = require('./indexify')
@@ -11,50 +12,112 @@ const syntaxHighlight = require('./syntax_highlight')
1112

1213
const assign = Object.assign
1314

14-
module.exports = function (options) {
15-
var app = ware()
16-
.use(buildIndex)
17-
.use(renderMarkdown)
18-
.use(cleanFiles)
19-
20-
return function (files, ms, done) {
21-
app.run(files, ms, done)
22-
}
23-
}
24-
2515
/**
26-
* Builds docpress.json (`files['docpress.json']`). It is as JSON file, which
27-
* has the following metadata:
16+
* Metalsmith Middleware that takes a source tree and generates a site from it.
17+
* It turns markdown into HTML files, but these files are bare and don't have
18+
* anything other than rendered markup.
19+
*
20+
* It also builds docpress.json which has reusable
21+
* metadata for subsequent tools (like `docpress-base`).
2822
*
29-
* - `index` — pages index.
30-
* - `toc` — table of contents (as a tree).
31-
* — `sources` — a mapping of source to destination filenames.
23+
* ### docpress.json
24+
* `docpress.json` is a JSON file with the following metadata:
25+
*
26+
* - `index` (Object) — pages index.
27+
* - `toc` (Object) — table of contents (as a tree).
28+
* — `sources` (Object) — a mapping of source to destination filenames.
3229
*
3330
* These datas can be obtained via `files['docpress.json'].index` (ie, as
3431
* Metalsmith file metadata) or by parsing docpress.json.
3532
*
36-
* ### Table of contents
37-
* Each toc item has:
38-
*
39-
* - `sections` (key/value of sections)
40-
* - `source` (path to source)
41-
* - `title` (title)
42-
* - `slug` (slug for the item)
43-
* - `url` (URL, if applicable)
44-
* - `headings` (array of `{ title, depth, id }`)
33+
* files['docpress.json'].index
34+
* files['docpress.json'].sources
35+
* files['docpress.json'].toc
4536
*
4637
* ### Index
47-
* Each index item has:
38+
* Each `index` item has:
4839
*
4940
* - `source` — path to source
5041
* - `title` — the page title according to TOC
5142
* - `slug` — slug for the page
5243
* - `headings` — an array of headings
5344
*
54-
* ### Files
55-
* It will modify files with new metadata:
45+
* index = files['docpress.json'].index
46+
* index['index.html']
47+
* => {
48+
* source: 'README.md',
49+
* title: 'My project',
50+
* slug: 'index',
51+
* headings: [
52+
* { title: 'Overview', depth: 2, id: 'overview' },
53+
* { title: 'Usage', depth: 2, id: 'usage', headings: [
54+
* { title: 'via npm', depth: 3, id: 'via-npm' },
55+
* ]},
56+
* ]
57+
* }
58+
*
59+
* ### Sources
60+
* `sources` is a key-value pairing of source files to built files.
61+
*
62+
* files['docpress.json'].sources
63+
* => {
64+
* "README.md": "index.html",
65+
* "docs/usage.md": "usage.html",
66+
* "docs/install/windows.md": "install/windows.html"
67+
* }
68+
*
69+
* ### Table of contents
70+
* Each `toc` item has:
71+
*
72+
* - `sections` — array of sections
73+
* - `source` — path to source
74+
* - `title` — title
75+
* - `slug` — slug for the item
76+
* - `url` — URL, if applicable
77+
* - `headings` — array of `{ title, depth, id }`
78+
*
79+
* toc = files['docpress.json'].toc
80+
* toc = {
81+
* sections: [
82+
* {
83+
* title: 'My project',
84+
* source: 'README.md',
85+
* url: 'index.html',
86+
* slug: 'index',
87+
* headings: [ ... ]
88+
* }, ...
89+
* ]
90+
* }
5691
*
57-
* - `newName` — the build output filename
92+
* ### Each file
93+
* Each HTML file will have these metadata available:
94+
*
95+
* file = files['index.html']
96+
* file._processed //=> true
97+
* file.title //=> "My project"
98+
* file.slug //=> "index" (perfect for HTML IDs)
99+
* file.source //=> "README.md" (where it was rendered from)
100+
* file.filename //=> "index.html" (new filename)
101+
* file.$ // Cheerio instance
102+
* file.markdown // Markdown source
103+
* file.html // Rendered HTML
104+
* file.contents // Same as `.html`
105+
*/
106+
107+
module.exports = function core (options) {
108+
var app = ware()
109+
.use(buildIndex)
110+
.use(renderMarkdown)
111+
.use(cleanFiles)
112+
113+
return function (files, ms, done) {
114+
app.run(files, ms, done)
115+
}
116+
}
117+
118+
/**
119+
* Builds `docpress.json`. See `core()` for a description on what it is.
120+
* It will also modify files with the `.filenmae` attribute.
58121
*/
59122

60123
function buildIndex (files, ms, done) {
@@ -66,23 +129,28 @@ function buildIndex (files, ms, done) {
66129
return done(err)
67130
}
68131

132+
// Build `toc`
69133
var toc = tocify(files[`${docs}/README.md`].contents.toString(), files, { docs })
134+
135+
// Build `index` and `sources`
70136
var indexes = indexify(toc, { docs })
71137

138+
// Generate source mappings for things outside the TOC
72139
Object.keys(files).forEach((fname) => {
73140
const file = files[fname]
74141
if (!indexes.sources[fname]) {
75142
// rename images
76-
const newName = fname.replace(docsExpr, '')
77-
if (newName !== fname && !fname.match(/\.md$/)) {
78-
file.newName = newName
79-
indexes.sources[fname] = newName
143+
const filename = fname.replace(docsExpr, '')
144+
if (filename !== fname && !fname.match(/\.md$/)) {
145+
file.filename = filename
146+
indexes.sources[fname] = filename
80147
}
81148
} else {
82-
file.newName = indexes.sources[fname]
149+
file.filename = indexes.sources[fname]
83150
}
84151
})
85152

153+
// Ensure every link in the TOC works
86154
verifyIndex(indexes.index, files)
87155

88156
var data = {
@@ -91,23 +159,17 @@ function buildIndex (files, ms, done) {
91159
sources: indexes.sources
92160
}
93161

94-
files['docpress.json'] = assign({}, data, { contents: JSON.stringify(data, null, 2) + '\n' })
162+
// Save
163+
files['docpress.json'] = assign({}, data, {
164+
contents: JSON.stringify(data, null, 2) + '\n'
165+
})
95166

96167
done()
97168
}
98169

99170
/**
100171
* Private: Converts .md to .html.
101-
*
102-
* At the end of this, you get a site with `.html` files (bare, no layout)
103-
* and a `toc.json` and `index.json`.
104-
*
105-
* Each html also has:
106-
*
107-
* - `title` (title according to TOC)
108-
* - `source` (path of source)
109-
* - `markdown` (raw Markdown source)
110-
* - `html` (rendered HTML)
172+
* At the end of this, you get a site with `.html` files (bare, no layout).
111173
*/
112174

113175
function renderMarkdown (files, ms, done) {
@@ -122,10 +184,13 @@ function renderMarkdown (files, ms, done) {
122184
highlight: syntaxHighlight,
123185
html: true
124186
}).render(file.contents.toString())
187+
const $ = cheerio.load(html)
125188

189+
fixHtml($, fname, sources, files)
190+
file.$ = $
126191
file._processed = true
127192
file.markdown = file.contents
128-
file.html = fixHtml(html, fname, sources, files)
193+
file.html = $.html()
129194
file.title = page.title
130195
file.source = page.source
131196
file.slug = page.slug
@@ -154,9 +219,9 @@ function cleanFiles (files, ms, done) {
154219
}
155220

156221
// rename docs/images/pic.png => images/pic.png
157-
// (`newName` is left by an earlier step)
158-
if (file.newName) {
159-
files[file.newName] = files[fname]
222+
// (`filename` is left by an earlier step)
223+
if (file.filename) {
224+
files[file.filename] = files[fname]
160225
delete files[fname]
161226
}
162227
})
@@ -176,4 +241,3 @@ function verifyIndex (index, files) {
176241
}
177242
})
178243
}
179-

lib/tocify.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,17 @@ function itemify (text, docs, files) {
7676
current.title = title
7777
if (source) current.source = source
7878

79-
// Add headings
80-
if (source && files && files[source]) {
81-
const headings = tocifyPage(files[source].contents)
82-
if (headings) current.headings = headings
83-
}
84-
8579
// Add slug
8680
if (url) {
8781
current.url = url
8882
current.slug = slugify(url) || 'index'
8983
}
9084

85+
// Add headings
86+
if (source && files && files[source]) {
87+
const headings = tocifyPage(files[source].contents)
88+
if (headings) current.headings = headings
89+
}
90+
9191
return current
9292
}

0 commit comments

Comments
 (0)