/**
* @module plugin
*/
const fs = require('fs')
const path = require('path')
const utils = require('./utils.js')
/* this allows this module to be tested outside of the jsdoc context */
let logger
try {
logger = require('jsdoc/util/logger')
} catch (e) {
logger = { info: function () {} } // console.log
}
// The directory from which following examples will be taken
let _examplesDir = ''
// Holds contents of examples file (JSON) for each class or module
let _examples = {}
// used to avoid double file loads -- jsdoc seems to duplicate tags
let previousValue = null
let previousFilename = null
/**
* Adds example text to '@examples'-tagged doclets.
* If examples already exist, they are appended to.
* @param {Object} doclet - the current JSDoc doclet
*/
function newDoclet ({ doclet }) {
// console.log(JSON.stringify(doclet, null, 2))
const name = doclet.name
let examples = (Array.isArray(_examples)) ? _examples : _examples[name]
examples = examples || _readExamples(name)
if (!examples) return
doclet.examples = doclet.examples || [] // ensure doclet has examples list
// add each example to the doclet's list
for (const example of examples) {
const lines = utils.bodyString(example.code)
if ('expect' in example) { // add the result at the end, if needed
lines.push('// <= ' + JSON.stringify(example.expect))
}
if (lines[0].startsWith('// caption:')) {
const str = lines[0].replace('// caption:', '').trim()
lines[0] = '<caption>' + str + '</caption>'
}
doclet.examples.push(lines.join('\n'))
}
if (Array.isArray(_examples)) _examples = false
}
/**
* Defines the '@examples' tag, and the action to be taken
* when the tag is encountered
* @param {*} dictionary
*/
function defineTags (dictionary) {
dictionary.defineTag('examples', {
mustHaveValue: true,
onTagged: function (doclet, tag) {
const filename = doclet.meta.filename
if (filename !== previousFilename) _examplesDir = ''
previousFilename = filename
const value = tag.value
if (value === previousValue) return // avoid double-processing
previousValue = value
if (fs.existsSync(value) && fs.lstatSync(value).isDirectory()) {
logger.info('examples directory:', value)
_examplesDir = value
_examples = {} // null
} else { // read example file
_readExamples(doclet.name, value)
}
}
})
}
function _readExamples (name, fn) {
const expath = path.resolve(_examplesDir, fn || name + '.js')
if (fs.existsSync(expath)) {
logger.info('Reading @examples: ', expath)
_examples = utils.examples(expath)
if (_examples.examples) {
if (_examples.setup) {
_examples.examples[name] = [{ code: _examples.setup }]
}
_examples = _examples.examples
}
}
return (Array.isArray(_examples)) ? _examples : _examples[name]
}
module.exports = {
handlers: { newDoclet: newDoclet },
defineTags: defineTags
}