-
Notifications
You must be signed in to change notification settings - Fork 49
/
Copy pathindex.js
150 lines (129 loc) · 5.14 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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
const path = require('path')
const fs = require('fs')
const Cache = require('cache-point')
const DmdOptions = require('./lib/dmd-options')
const FileSet = require('file-set')
const os = require('os')
const partialCache = require('./partials/partial-cache.js')
const arrayify = require('array-back')
const walkBack = require('walk-back')
const HandlebarsTemplate = require('./lib/handlebars-template.js')
const pkg = JSON.parse(fs.readFileSync(path.resolve(__dirname, './package.json'), 'utf8'))
const dmdVersion = pkg.version
/**
* @module dmd
*/
/**
* Transforms jsdoc-parse data into markdown documentation.
* @param {object[]}
* @param [options] {module:dmd-options} - The render options
* @return {Promise<string>}
* @alias module:dmd
*/
async function dmd (templateData = [], options) {
options = new DmdOptions(options)
if (skipCache(options)) {
return generate(templateData, options)
} else {
try {
const result = await dmd.cache.read([templateData, options, dmdVersion])
return result
} catch (err) {
/* cache miss */
return generate(templateData, options)
}
}
}
/* Expose cache so `jsdoc2md --clear` command can access it */
dmd.cache = new Cache({ dir: path.join(os.tmpdir(), 'dmd') })
async function loadPartialFiles (paths) {
const fileSet = new FileSet()
await fileSet.add(paths)
return fileSet.files.map(file => {
return [
path.basename(file, '.hbs'),
fs.readFileSync(file, 'utf8') || ''
]
})
}
async function loadHelperFiles (helpers) {
const fileSet = new FileSet()
await fileSet.add(helpers)
return fileSet.files.map(file => {
return require(path.resolve(process.cwd(), file))
})
}
function validateIncomingTemplateData (templateData) {
const moduleTagRequired = templateData.filter(d => d.id === 'module.exports' && d.memberof === 'module')
if (moduleTagRequired.length) {
for (const doclet of moduleTagRequired) {
console.warn(`Module tag required in this file: ${doclet.meta.path}${path.sep}${doclet.meta.filename}`)
console.warn('See the wiki for an explanation: https://github.com/jsdoc2md/jsdoc-to-markdown/wiki/How-to-document-an-ES2015-module-(single-default-export)')
}
}
}
async function generate (templateData, options) {
validateIncomingTemplateData(templateData)
const handlebarsTemplate = new HandlebarsTemplate()
/* Copy input data */
const inputData = templateData.map(row => Object.assign({}, row))
const inputOptions = Object.assign({}, options)
/* used by helpers.headingDepth */
options._depth = 0
/* used by helpers.indexDepth */
options._indexDepth = 0
/* This gives all helper code access to the dmd options */
templateData.options = options
/* state module, for sharing data between the helpers - functions as a global object */
const state = require('./lib/state')
state.templateData = templateData
state.options = options
/* if plugins were specified, register the helpers/partials from them too */
if (options.plugin) {
for (let i = 0; i < options.plugin.length; i++) {
const plugin = options.plugin[i]
let modulePath = ''
/* user supplied an existing path */
if (fs.existsSync(path.resolve(plugin))) {
modulePath = path.resolve(plugin)
/* else user supplied a module name, search npm installed modules */
} else {
modulePath = walkBack(process.cwd(), path.join('node_modules', plugin))
}
if (modulePath) {
/* load the plugin options */
const pluginOptions = require(modulePath)(options)
options.partial = options.partial.concat(pluginOptions.partial)
options.helper = options.helper.concat(pluginOptions.helper)
} else {
throw new Error('Cannot find plugin: ' + plugin)
}
}
}
/* register all internal and external dmd partials. */
const internalPartials = Array.from(partialCache)
const externalPartials = await loadPartialFiles(options.partial)
for (const [name, content] of [...internalPartials, ...externalPartials]) {
handlebarsTemplate.handlebars.registerPartial(name, content)
}
/* Register internal helpers first so they can be overriden by user-defined helpers */
const internalHelpers = [require('./helpers/helpers.js'), require('./helpers/ddata.js'), require('./helpers/selectors.js')]
const externalHelpers = await loadHelperFiles(options.helper)
for (const helper of [...internalHelpers, ...externalHelpers]) {
handlebarsTemplate.handlebars.registerHelper(helper)
}
let output = handlebarsTemplate.generate(options.template, templateData)
if (options.EOL) {
output = output.replace(/\r?\n/gm, options.EOL === 'posix' ? '\n' : '\r\n')
/* Additional check for naked \r characters created by jsdoc */
/* See: https://github.com/jsdoc2md/dmd/issues/102 */
output = output.replace(/\r(?!\n)/g, options.EOL === 'posix' ? '\n' : '\r\n')
}
dmd.cache.writeSync([inputData, inputOptions, dmdVersion], output)
return output
}
/* always skip the cache when custom plugins, partials or helpers are used */
function skipCache (options) {
return options.noCache || options.plugin.length || options.partial.length || options.helper.length
}
module.exports = dmd