-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
104 lines (89 loc) · 3.07 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
const Styledown = require('@peopledoc/styledown')
const Plugin = require('broccoli-plugin')
const walkSync = require('walk-sync')
const FSTree = require('fs-tree-diff')
const FS_OPTIONS = { encoding: 'utf8' }
const EXTENSIONS = ['less', 'css', 'sass', 'scss', 'styl']
const WHITELIST_GLOB_REGEXP = `**/*.{${EXTENSIONS.join(',')}}`
class StyledownCompiler extends Plugin {
constructor(inputNode, options) {
options = options || {}
options.persistentOutput = true
options.needsCache = true
options.name = options.displayName ? `StyledownCompiler - ${options.displayName}` : 'StyledownCompiler'
super(inputNode, options)
this.configMd = options.configMd || 'config.md'
this.destFile = options.destFile || 'index.html'
this.styledownOpts = options.styledown || {}
if (options.onBuildError) {
if (typeof options.onBuildError !== "function") {
throw new TypeError('Option onBuildError should be a function')
}
this.onBuildError = options.onBuildError
}
this._cached = []
}
_hasChanged() {
let changed = false
for (let inputPath of this.inputPaths) {
const current = FSTree.fromEntries(walkSync.entries(inputPath))
const patch = current.calculatePatch(this._cached[inputPath] || [])
this._cached[inputPath] = current
if (patch.length) {
changed = true
}
}
return changed
}
async build() {
if (!this._hasChanged()) { // do this for each transformations
return
}
let sourceFileData = this.getSourceFileData()
let sourceData = sourceFileData.reduce((result, data) => result.concat(data), [])
try {
let html = Styledown.parse(sourceData, this.styledownOpts)
return this.output.writeFileSync(this.destFile, html, FS_OPTIONS)
} catch (error) {
if (this.onBuildError) {
this.onBuildError(
error, {
destFile: this.destFile,
inputPaths: sourceFileData.map(({ name }) => name)
})
}
throw error
}
}
/**
* Get all data for files in srcPath.
*
* @return {Promise} Array of all files [{ name: 'fileName', data: String }]
*/
getSourceFileData() {
let filePaths = this.input.entries('', { globs: [WHITELIST_GLOB_REGEXP]})
.map((file) => file.relativePath)
// Todo: Use sort
let filePathsMd = this.input.entries('', { globs: ["**/*.md"]})
.filter(({ relativePath }) => (relativePath !== this.configMd))
.map((file) => file.relativePath)
// For some reason, Styledown chokes if the md files comes before any
// of the CSS files
filePaths = filePaths.concat(filePathsMd)
// If available, add configMd at the end of the list
if (this.input.existsSync(this.configMd)) {
filePaths = filePaths.concat(this.configMd)
}
try {
return filePaths.map((filePath) => ({
data: this.input.readFileSync(filePath, FS_OPTIONS),
name: filePath
}))
} catch(err) {
console.log('Error reading source file data')
console.error(err)
throw(err)
}
}
}
module.exports = StyledownCompiler