@jsdoc/core
Advanced tools
Comparing version 0.4.0 to 0.4.1
@@ -11,4 +11,4 @@ /** | ||
module.exports = { | ||
config, | ||
name | ||
config, | ||
name, | ||
}; |
@@ -14,123 +14,117 @@ /** | ||
const defaults = exports.defaults = { | ||
// TODO(hegemonic): Integrate CLI options with other options. | ||
opts: { | ||
destination: './out', | ||
encoding: 'utf8' | ||
}, | ||
const defaults = (exports.defaults = { | ||
// TODO(hegemonic): Integrate CLI options with other options. | ||
opts: { | ||
destination: './out', | ||
encoding: 'utf8', | ||
}, | ||
/** | ||
* The JSDoc plugins to load. | ||
*/ | ||
plugins: [], | ||
// TODO(hegemonic): Move to `source` or remove. | ||
recurseDepth: 10, | ||
/** | ||
* Settings for loading and parsing source files. | ||
*/ | ||
source: { | ||
/** | ||
* The JSDoc plugins to load. | ||
* A regular expression that matches source files to exclude from processing. | ||
* | ||
* To exclude files if any portion of their path begins with an underscore, use the value | ||
* `(^|\\/|\\\\)_`. | ||
*/ | ||
plugins: [], | ||
// TODO(hegemonic): Move to `source` or remove. | ||
recurseDepth: 10, | ||
excludePattern: '', | ||
/** | ||
* Settings for loading and parsing source files. | ||
* A regular expression that matches source files that JSDoc should process. | ||
* | ||
* By default, all source files with the extensions `.js`, `.jsdoc`, and `.jsx` are | ||
* processed. | ||
*/ | ||
source: { | ||
/** | ||
* A regular expression that matches source files to exclude from processing. | ||
* | ||
* To exclude files if any portion of their path begins with an underscore, use the value | ||
* `(^|\\/|\\\\)_`. | ||
*/ | ||
excludePattern: '', | ||
/** | ||
* A regular expression that matches source files that JSDoc should process. | ||
* | ||
* By default, all source files with the extensions `.js`, `.jsdoc`, and `.jsx` are | ||
* processed. | ||
*/ | ||
includePattern: '.+\\.js(doc|x)?$', | ||
/** | ||
* The type of source file. In general, you should use the value `module`. If none of your | ||
* source files use ECMAScript >=2015 syntax, you can use the value `script`. | ||
*/ | ||
type: 'module' | ||
}, | ||
includePattern: '.+\\.js(doc|x)?$', | ||
/** | ||
* Settings for interpreting JSDoc tags. | ||
* The type of source file. In general, you should use the value `module`. If none of your | ||
* source files use ECMAScript >=2015 syntax, you can use the value `script`. | ||
*/ | ||
tags: { | ||
/** | ||
* Set to `true` to allow tags that JSDoc does not recognize. | ||
*/ | ||
allowUnknownTags: true, | ||
// TODO(hegemonic): Use module paths, not magic strings. | ||
/** | ||
* The JSDoc tag dictionaries to load. | ||
* | ||
* If you specify two or more tag dictionaries, and a tag is defined in multiple | ||
* dictionaries, JSDoc uses the definition from the first dictionary that includes that tag. | ||
*/ | ||
dictionaries: [ | ||
'jsdoc', | ||
'closure' | ||
] | ||
}, | ||
type: 'module', | ||
}, | ||
/** | ||
* Settings for interpreting JSDoc tags. | ||
*/ | ||
tags: { | ||
/** | ||
* Settings for generating output with JSDoc templates. Some JSDoc templates might ignore these | ||
* settings. | ||
* Set to `true` to allow tags that JSDoc does not recognize. | ||
*/ | ||
templates: { | ||
/** | ||
* Set to `true` to use a monospaced font for links to other code symbols, but not links to | ||
* websites. | ||
*/ | ||
cleverLinks: false, | ||
/** | ||
* Set to `true` to use a monospaced font for all links. | ||
*/ | ||
monospaceLinks: false | ||
} | ||
}; | ||
allowUnknownTags: true, | ||
// TODO(hegemonic): Use module paths, not magic strings. | ||
/** | ||
* The JSDoc tag dictionaries to load. | ||
* | ||
* If you specify two or more tag dictionaries, and a tag is defined in multiple | ||
* dictionaries, JSDoc uses the definition from the first dictionary that includes that tag. | ||
*/ | ||
dictionaries: ['jsdoc', 'closure'], | ||
}, | ||
/** | ||
* Settings for generating output with JSDoc templates. Some JSDoc templates might ignore these | ||
* settings. | ||
*/ | ||
templates: { | ||
/** | ||
* Set to `true` to use a monospaced font for links to other code symbols, but not links to | ||
* websites. | ||
*/ | ||
cleverLinks: false, | ||
/** | ||
* Set to `true` to use a monospaced font for all links. | ||
*/ | ||
monospaceLinks: false, | ||
}, | ||
}); | ||
// TODO: Consider exporting this class. | ||
class Config { | ||
constructor(filepath, config) { | ||
this.config = config; | ||
this.filepath = filepath; | ||
} | ||
constructor(filepath, config) { | ||
this.config = config; | ||
this.filepath = filepath; | ||
} | ||
} | ||
function loadJson(filepath, content) { | ||
return defaultLoaders['.json'](filepath, stripBom(stripJsonComments(content))); | ||
return defaultLoaders['.json'](filepath, stripBom(stripJsonComments(content))); | ||
} | ||
function loadYaml(filepath, content) { | ||
return defaultLoaders['.yaml'](filepath, stripBom(content)); | ||
return defaultLoaders['.yaml'](filepath, stripBom(content)); | ||
} | ||
const explorerSync = cosmiconfigSync(MODULE_NAME, { | ||
cache: false, | ||
loaders: { | ||
'.json': loadJson, | ||
'.yaml': loadYaml, | ||
'.yml': loadYaml, | ||
noExt: loadYaml | ||
}, | ||
searchPlaces: [ | ||
'package.json', | ||
`.${MODULE_NAME}rc`, | ||
`.${MODULE_NAME}rc.json`, | ||
`.${MODULE_NAME}rc.yaml`, | ||
`.${MODULE_NAME}rc.yml`, | ||
`.${MODULE_NAME}rc.js`, | ||
`${MODULE_NAME}.config.js` | ||
] | ||
cache: false, | ||
loaders: { | ||
'.json': loadJson, | ||
'.yaml': loadYaml, | ||
'.yml': loadYaml, | ||
noExt: loadYaml, | ||
}, | ||
searchPlaces: [ | ||
'package.json', | ||
`.${MODULE_NAME}rc`, | ||
`.${MODULE_NAME}rc.json`, | ||
`.${MODULE_NAME}rc.yaml`, | ||
`.${MODULE_NAME}rc.yml`, | ||
`.${MODULE_NAME}rc.js`, | ||
`${MODULE_NAME}.config.js`, | ||
], | ||
}); | ||
exports.loadSync = (filepath) => { | ||
let loaded; | ||
let loaded; | ||
if (filepath) { | ||
loaded = explorerSync.load(filepath); | ||
} else { | ||
loaded = explorerSync.search() || {}; | ||
} | ||
if (filepath) { | ||
loaded = explorerSync.load(filepath); | ||
} else { | ||
loaded = explorerSync.search() || {}; | ||
} | ||
return new Config( | ||
loaded.filepath, | ||
_.defaultsDeep({}, loaded.config, defaults) | ||
); | ||
return new Config(loaded.filepath, _.defaultsDeep({}, loaded.config, defaults)); | ||
}; |
455
lib/name.js
@@ -19,6 +19,6 @@ /** | ||
exports.LONGNAMES = { | ||
/** Longname used for doclets that do not have a longname, such as anonymous functions. */ | ||
ANONYMOUS: '<anonymous>', | ||
/** Longname that represents global scope. */ | ||
GLOBAL: '<global>' | ||
/** Longname used for doclets that do not have a longname, such as anonymous functions. */ | ||
ANONYMOUS: '<anonymous>', | ||
/** Longname that represents global scope. */ | ||
GLOBAL: '<global>', | ||
}; | ||
@@ -36,22 +36,22 @@ | ||
*/ | ||
const SCOPE = exports.SCOPE = { | ||
NAMES: { | ||
GLOBAL: 'global', | ||
INNER: 'inner', | ||
INSTANCE: 'instance', | ||
STATIC: 'static' | ||
}, | ||
PUNC: { | ||
INNER: '~', | ||
INSTANCE: '#', | ||
STATIC: '.' | ||
} | ||
}; | ||
const SCOPE = (exports.SCOPE = { | ||
NAMES: { | ||
GLOBAL: 'global', | ||
INNER: 'inner', | ||
INSTANCE: 'instance', | ||
STATIC: 'static', | ||
}, | ||
PUNC: { | ||
INNER: '~', | ||
INSTANCE: '#', | ||
STATIC: '.', | ||
}, | ||
}); | ||
// Keys must be lowercase. | ||
const SCOPE_TO_PUNC = exports.SCOPE_TO_PUNC = { | ||
inner: SCOPE.PUNC.INNER, | ||
instance: SCOPE.PUNC.INSTANCE, | ||
static: SCOPE.PUNC.STATIC | ||
}; | ||
const SCOPE_TO_PUNC = (exports.SCOPE_TO_PUNC = { | ||
inner: SCOPE.PUNC.INNER, | ||
instance: SCOPE.PUNC.INSTANCE, | ||
static: SCOPE.PUNC.STATIC, | ||
}); | ||
@@ -83,5 +83,5 @@ exports.PUNC_TO_SCOPE = _.invert(SCOPE_TO_PUNC); | ||
exports.nameIsLongname = (name, memberof) => { | ||
const regexp = new RegExp(`^${escape(memberof)}${SCOPE_PUNC_STRING}`); | ||
const regexp = new RegExp(`^${escape(memberof)}${SCOPE_PUNC_STRING}`); | ||
return regexp.test(name); | ||
return regexp.test(name); | ||
}; | ||
@@ -97,10 +97,10 @@ | ||
*/ | ||
const prototypeToPunc = exports.prototypeToPunc = name => { | ||
// Don't mangle symbols named `prototype`. | ||
if (name === 'prototype') { | ||
return name; | ||
} | ||
const prototypeToPunc = (exports.prototypeToPunc = (name) => { | ||
// Don't mangle symbols named `prototype`. | ||
if (name === 'prototype') { | ||
return name; | ||
} | ||
return name.replace(/(?:^|\.)prototype\.?/g, SCOPE.PUNC.INSTANCE); | ||
}; | ||
return name.replace(/(?:^|\.)prototype\.?/g, SCOPE.PUNC.INSTANCE); | ||
}); | ||
@@ -113,3 +113,3 @@ /** | ||
*/ | ||
exports.hasLeadingScope = name => REGEXP_LEADING_SCOPE.test(name); | ||
exports.hasLeadingScope = (name) => REGEXP_LEADING_SCOPE.test(name); | ||
@@ -122,3 +122,3 @@ /** | ||
*/ | ||
exports.hasTrailingScope = name => REGEXP_TRAILING_SCOPE.test(name); | ||
exports.hasTrailingScope = (name) => REGEXP_TRAILING_SCOPE.test(name); | ||
@@ -137,90 +137,88 @@ /** | ||
*/ | ||
exports.getBasename = name => { | ||
if (!name) { | ||
return null; | ||
} | ||
exports.getBasename = (name) => { | ||
if (!name) { | ||
return null; | ||
} | ||
return name.replace(/^([$a-z_][$a-z_0-9]*).*?$/i, '$1'); | ||
return name.replace(/^([$a-z_][$a-z_0-9]*).*?$/i, '$1'); | ||
}; | ||
// TODO: docs | ||
exports.stripNamespace = longname => longname.replace(/^[a-zA-Z]+:/, ''); | ||
exports.stripNamespace = (longname) => longname.replace(/^[a-zA-Z]+:/, ''); | ||
// TODO: docs | ||
function slice(longname, sliceChars, forcedMemberof) { | ||
let i; | ||
let memberof = ''; | ||
let name = ''; | ||
let parts; | ||
let partsRegExp; | ||
let scopePunc = ''; | ||
let token; | ||
const tokens = []; | ||
let variation; | ||
let i; | ||
let memberof = ''; | ||
let name = ''; | ||
let parts; | ||
let partsRegExp; | ||
let scopePunc = ''; | ||
let token; | ||
const tokens = []; | ||
let variation; | ||
sliceChars = sliceChars || SCOPE_PUNC; | ||
sliceChars = sliceChars || SCOPE_PUNC; | ||
// Quoted strings in a longname are atomic, so we convert them to tokens: | ||
// foo["bar"] => foo.@{1}@ | ||
// Foo.prototype["bar"] => Foo#@{1} | ||
longname = longname.replace(/(prototype|#)?(\[?["'].+?["']\]?)/g, ($, p1, p2) => { | ||
let punc = ''; | ||
// Quoted strings in a longname are atomic, so we convert them to tokens: | ||
// foo["bar"] => foo.@{1}@ | ||
// Foo.prototype["bar"] => Foo#@{1} | ||
longname = longname.replace(/(prototype|#)?(\[?["'].+?["']\]?)/g, ($, p1, p2) => { | ||
let punc = ''; | ||
// Is there a leading bracket? | ||
if ( /^\[/.test(p2) ) { | ||
// Is it a static or instance member? | ||
punc = p1 ? SCOPE.PUNC.INSTANCE : SCOPE.PUNC.STATIC; | ||
p2 = p2.replace(/^\[/g, '') | ||
.replace(/\]$/g, ''); | ||
} | ||
// Is there a leading bracket? | ||
if (/^\[/.test(p2)) { | ||
// Is it a static or instance member? | ||
punc = p1 ? SCOPE.PUNC.INSTANCE : SCOPE.PUNC.STATIC; | ||
p2 = p2.replace(/^\[/g, '').replace(/\]$/g, ''); | ||
} | ||
token = `@{${tokens.length}}@`; | ||
tokens.push(p2); | ||
token = `@{${tokens.length}}@`; | ||
tokens.push(p2); | ||
return punc + token; | ||
}); | ||
return punc + token; | ||
}); | ||
longname = prototypeToPunc(longname); | ||
longname = prototypeToPunc(longname); | ||
if (typeof forcedMemberof !== 'undefined') { | ||
partsRegExp = new RegExp(`^(.*?)([${sliceChars.join()}]?)$`); | ||
name = longname.substr(forcedMemberof.length); | ||
parts = forcedMemberof.match(partsRegExp); | ||
if (typeof forcedMemberof !== 'undefined') { | ||
partsRegExp = new RegExp(`^(.*?)([${sliceChars.join()}]?)$`); | ||
name = longname.substr(forcedMemberof.length); | ||
parts = forcedMemberof.match(partsRegExp); | ||
if (parts[1]) { | ||
memberof = parts[1] || forcedMemberof; | ||
} | ||
if (parts[2]) { | ||
scopePunc = parts[2]; | ||
} | ||
if (parts[1]) { | ||
memberof = parts[1] || forcedMemberof; | ||
} | ||
else if (longname) { | ||
parts = longname.match(new RegExp(`^(:?(.+)([${sliceChars.join()}]))?(.+?)$`)) || []; | ||
name = parts.pop() || ''; | ||
scopePunc = parts.pop() || ''; | ||
memberof = parts.pop() || ''; | ||
if (parts[2]) { | ||
scopePunc = parts[2]; | ||
} | ||
} else if (longname) { | ||
parts = longname.match(new RegExp(`^(:?(.+)([${sliceChars.join()}]))?(.+?)$`)) || []; | ||
name = parts.pop() || ''; | ||
scopePunc = parts.pop() || ''; | ||
memberof = parts.pop() || ''; | ||
} | ||
// Like `@name foo.bar(2)`. | ||
if (/(.+)\(([^)]+)\)$/.test(name)) { | ||
name = RegExp.$1; | ||
variation = RegExp.$2; | ||
} | ||
// Like `@name foo.bar(2)`. | ||
if (/(.+)\(([^)]+)\)$/.test(name)) { | ||
name = RegExp.$1; | ||
variation = RegExp.$2; | ||
} | ||
// Restore quoted strings. | ||
i = tokens.length; | ||
while (i--) { | ||
longname = longname.replace(`@{${i}}@`, tokens[i]); | ||
memberof = memberof.replace(`@{${i}}@`, tokens[i]); | ||
scopePunc = scopePunc.replace(`@{${i}}@`, tokens[i]); | ||
name = name.replace(`@{${i}}@`, tokens[i]); | ||
} | ||
// Restore quoted strings. | ||
i = tokens.length; | ||
while (i--) { | ||
longname = longname.replace(`@{${i}}@`, tokens[i]); | ||
memberof = memberof.replace(`@{${i}}@`, tokens[i]); | ||
scopePunc = scopePunc.replace(`@{${i}}@`, tokens[i]); | ||
name = name.replace(`@{${i}}@`, tokens[i]); | ||
} | ||
return { | ||
longname: longname, | ||
memberof: memberof, | ||
scope: scopePunc, | ||
name: name, | ||
variation: variation | ||
}; | ||
return { | ||
longname: longname, | ||
memberof: memberof, | ||
scope: scopePunc, | ||
name: name, | ||
variation: variation, | ||
}; | ||
} | ||
@@ -241,5 +239,3 @@ | ||
*/ | ||
exports.toParts = (longname, forcedMemberof) => slice( | ||
longname, null, forcedMemberof | ||
); | ||
exports.toParts = (longname, forcedMemberof) => slice(longname, null, forcedMemberof); | ||
@@ -253,12 +249,12 @@ // TODO: docs | ||
exports.applyNamespace = (longname, ns) => { | ||
const nameParts = slice(longname); | ||
const name = nameParts.name; | ||
const nameParts = slice(longname); | ||
const name = nameParts.name; | ||
longname = nameParts.longname; | ||
longname = nameParts.longname; | ||
if (!/^[a-zA-Z]+?:.+$/i.test(name)) { | ||
longname = longname.replace(new RegExp(`${escape(name)}$`), `${ns}:${name}`); | ||
} | ||
if (!/^[a-zA-Z]+?:.+$/i.test(name)) { | ||
longname = longname.replace(new RegExp(`${escape(name)}$`), `${ns}:${name}`); | ||
} | ||
return longname; | ||
return longname; | ||
}; | ||
@@ -274,66 +270,62 @@ | ||
exports.hasAncestor = (parent, child) => { | ||
let hasAncestor = false; | ||
let memberof = child; | ||
let hasAncestor = false; | ||
let memberof = child; | ||
if (!parent || !child) { | ||
return hasAncestor; | ||
} | ||
if (!parent || !child) { | ||
return hasAncestor; | ||
} | ||
// Fast path for obvious non-ancestors. | ||
if (child.indexOf(parent) !== 0) { | ||
return hasAncestor; | ||
} | ||
// Fast path for obvious non-ancestors. | ||
if (child.indexOf(parent) !== 0) { | ||
return hasAncestor; | ||
} | ||
do { | ||
memberof = slice(memberof).memberof; | ||
do { | ||
memberof = slice(memberof).memberof; | ||
if (memberof === parent) { | ||
hasAncestor = true; | ||
} | ||
} while (!hasAncestor && memberof); | ||
if (memberof === parent) { | ||
hasAncestor = true; | ||
} | ||
} while (!hasAncestor && memberof); | ||
return hasAncestor; | ||
return hasAncestor; | ||
}; | ||
// TODO: docs | ||
const fromParts = exports.fromParts = ({memberof, scope, name, variation}) => [ | ||
(memberof || ''), | ||
(scope || ''), | ||
(name || ''), | ||
(variation ? `(${variation})` : '') | ||
].join(''); | ||
const fromParts = (exports.fromParts = ({ memberof, scope, name, variation }) => | ||
[memberof || '', scope || '', name || '', variation ? `(${variation})` : ''].join('')); | ||
// TODO: docs | ||
exports.stripVariation = name => { | ||
const parts = slice(name); | ||
exports.stripVariation = (name) => { | ||
const parts = slice(name); | ||
parts.variation = ''; | ||
parts.variation = ''; | ||
return fromParts(parts); | ||
return fromParts(parts); | ||
}; | ||
function splitLongname(longname, options) { | ||
const chunks = []; | ||
let currentNameInfo; | ||
const nameInfo = {}; | ||
let previousName = longname; | ||
const splitters = SCOPE_PUNC.concat('/'); | ||
const chunks = []; | ||
let currentNameInfo; | ||
const nameInfo = {}; | ||
let previousName = longname; | ||
const splitters = SCOPE_PUNC.concat('/'); | ||
options = _.defaults(options || {}, { | ||
includeVariation: true | ||
}); | ||
options = _.defaults(options || {}, { | ||
includeVariation: true, | ||
}); | ||
do { | ||
if (!options.includeVariation) { | ||
previousName = exports.stripVariation(previousName); | ||
} | ||
currentNameInfo = nameInfo[previousName] = slice(previousName, splitters); | ||
previousName = currentNameInfo.memberof; | ||
chunks.push(currentNameInfo.scope + currentNameInfo.name); | ||
} while (previousName); | ||
do { | ||
if (!options.includeVariation) { | ||
previousName = exports.stripVariation(previousName); | ||
} | ||
currentNameInfo = nameInfo[previousName] = slice(previousName, splitters); | ||
previousName = currentNameInfo.memberof; | ||
chunks.push(currentNameInfo.scope + currentNameInfo.name); | ||
} while (previousName); | ||
return { | ||
chunks: chunks.reverse(), | ||
nameInfo: nameInfo | ||
}; | ||
return { | ||
chunks: chunks.reverse(), | ||
nameInfo: nameInfo, | ||
}; | ||
} | ||
@@ -424,39 +416,39 @@ | ||
exports.longnamesToTree = (longnames, doclets) => { | ||
const splitOptions = { includeVariation: false }; | ||
const tree = {}; | ||
const splitOptions = { includeVariation: false }; | ||
const tree = {}; | ||
longnames.forEach(longname => { | ||
let currentLongname = ''; | ||
let currentParent = tree; | ||
let nameInfo; | ||
let processed; | ||
longnames.forEach((longname) => { | ||
let currentLongname = ''; | ||
let currentParent = tree; | ||
let nameInfo; | ||
let processed; | ||
// Don't try to add empty longnames to the tree. | ||
if (!longname) { | ||
return; | ||
} | ||
// Don't try to add empty longnames to the tree. | ||
if (!longname) { | ||
return; | ||
} | ||
processed = splitLongname(longname, splitOptions); | ||
nameInfo = processed.nameInfo; | ||
processed = splitLongname(longname, splitOptions); | ||
nameInfo = processed.nameInfo; | ||
processed.chunks.forEach(chunk => { | ||
currentLongname += chunk; | ||
processed.chunks.forEach((chunk) => { | ||
currentLongname += chunk; | ||
if (currentParent !== tree) { | ||
currentParent.children = currentParent.children || {}; | ||
currentParent = currentParent.children; | ||
} | ||
if (currentParent !== tree) { | ||
currentParent.children = currentParent.children || {}; | ||
currentParent = currentParent.children; | ||
} | ||
if (!hasOwnProp.call(currentParent, chunk)) { | ||
currentParent[chunk] = nameInfo[currentLongname]; | ||
} | ||
if (!hasOwnProp.call(currentParent, chunk)) { | ||
currentParent[chunk] = nameInfo[currentLongname]; | ||
} | ||
if (currentParent[chunk]) { | ||
currentParent[chunk].doclet = doclets ? doclets[currentLongname] : null; | ||
currentParent = currentParent[chunk]; | ||
} | ||
}); | ||
if (currentParent[chunk]) { | ||
currentParent[chunk].doclet = doclets ? doclets[currentLongname] : null; | ||
currentParent = currentParent[chunk]; | ||
} | ||
}); | ||
}); | ||
return tree; | ||
return tree; | ||
}; | ||
@@ -473,41 +465,40 @@ | ||
function splitNameMatchingBrackets(nameDesc) { | ||
const buffer = []; | ||
let c; | ||
let stack = 0; | ||
let stringEnd = null; | ||
const buffer = []; | ||
let c; | ||
let stack = 0; | ||
let stringEnd = null; | ||
for (var i = 0; i < nameDesc.length; ++i) { | ||
c = nameDesc[i]; | ||
buffer.push(c); | ||
for (var i = 0; i < nameDesc.length; ++i) { | ||
c = nameDesc[i]; | ||
buffer.push(c); | ||
if (stringEnd) { | ||
if (c === '\\' && i + 1 < nameDesc.length) { | ||
buffer.push(nameDesc[++i]); | ||
} else if (c === stringEnd) { | ||
stringEnd = null; | ||
} | ||
} else if (c === '"' || c === "'") { | ||
stringEnd = c; | ||
} else if (c === '[') { | ||
++stack; | ||
} else if (c === ']') { | ||
if (--stack === 0) { | ||
break; | ||
} | ||
} | ||
if (stringEnd) { | ||
if (c === '\\' && i + 1 < nameDesc.length) { | ||
buffer.push(nameDesc[++i]); | ||
} else if (c === stringEnd) { | ||
stringEnd = null; | ||
} | ||
} else if (c === '"' || c === "'") { | ||
stringEnd = c; | ||
} else if (c === '[') { | ||
++stack; | ||
} else if (c === ']') { | ||
if (--stack === 0) { | ||
break; | ||
} | ||
} | ||
} | ||
if (stack || stringEnd) { | ||
return null; | ||
} | ||
if (stack || stringEnd) { | ||
return null; | ||
} | ||
nameDesc.substr(i).match(REGEXP_DESCRIPTION); | ||
nameDesc.substr(i).match(REGEXP_DESCRIPTION); | ||
return { | ||
name: buffer.join(''), | ||
description: RegExp.$1 | ||
}; | ||
return { | ||
name: buffer.join(''), | ||
description: RegExp.$1, | ||
}; | ||
} | ||
/** | ||
@@ -518,23 +509,23 @@ * Split a string that starts with a name and ends with a description into separate parts. | ||
*/ | ||
exports.splitNameAndDescription = str => { | ||
// Like: `name`, `[name]`, `name text`, `[name] text`, `name - text`, or `[name] - text`. | ||
// To ensure that we don't get confused by leading dashes in Markdown list items, the hyphen | ||
// must be on the same line as the name. | ||
exports.splitNameAndDescription = (str) => { | ||
// Like: `name`, `[name]`, `name text`, `[name] text`, `name - text`, or `[name] - text`. | ||
// To ensure that we don't get confused by leading dashes in Markdown list items, the hyphen | ||
// must be on the same line as the name. | ||
// Optional values get special treatment, | ||
let result = null; | ||
// Optional values get special treatment, | ||
let result = null; | ||
if (str[0] === '[') { | ||
result = splitNameMatchingBrackets(str); | ||
if (result !== null) { | ||
return result; | ||
} | ||
if (str[0] === '[') { | ||
result = splitNameMatchingBrackets(str); | ||
if (result !== null) { | ||
return result; | ||
} | ||
} | ||
str.match(REGEXP_NAME_DESCRIPTION); | ||
str.match(REGEXP_NAME_DESCRIPTION); | ||
return { | ||
name: RegExp.$1, | ||
description: RegExp.$2 | ||
}; | ||
return { | ||
name: RegExp.$1, | ||
description: RegExp.$2, | ||
}; | ||
}; |
{ | ||
"name": "@jsdoc/core", | ||
"version": "0.4.0", | ||
"version": "0.4.1", | ||
"description": "Core functionality for JSDoc.", | ||
@@ -25,5 +25,5 @@ "keywords": [ | ||
"dependencies": { | ||
"cosmiconfig": "^7.0.0", | ||
"cosmiconfig": "^7.0.1", | ||
"escape-string-regexp": "^4.0.0", | ||
"lodash": "^4.17.20", | ||
"lodash": "^4.17.21", | ||
"strip-bom": "^4.0.0", | ||
@@ -33,5 +33,5 @@ "strip-json-comments": "^3.1.1" | ||
"engines": { | ||
"node": ">=10.18.0" | ||
"node": ">=v14.17.6" | ||
}, | ||
"gitHead": "ed08da57c652b103ac69ddc5a727abb6074ebe46" | ||
"gitHead": "81fdd2bc4224cadd96f569a796a3e8afabc6f468" | ||
} |
29620
580
Updatedcosmiconfig@^7.0.1
Updatedlodash@^4.17.21