Comparing version 0.7.0 to 0.7.1
@@ -0,1 +1,8 @@ | ||
0.7.1 / 2015-04-03 | ||
================== | ||
Context parsing has been re-factored into an array of functions that are iterated over until a match is found. This array is exposed as `dox.contextPatternMatchers`, allowing for extension with new contexts without needing to edit the dox source. | ||
* Fix: ES6 classes extended from sub-properties (such as Backbone.View) are now properly matched | ||
0.7.0 / 2015-03-24 | ||
@@ -2,0 +9,0 @@ ================== |
364
lib/dox.js
@@ -484,150 +484,226 @@ /*! | ||
// class, possibly exported by name or as a default | ||
if (/^\s*(export(\s+default)?\s+)?class\s+([\w$]+)(\s+extends\s+([\w$]+))?\s*{/.exec(str)) { | ||
return { | ||
type: 'class' | ||
, constructor: RegExp.$3 | ||
, cons: RegExp.$3 | ||
, name: RegExp.$3 | ||
, extends: RegExp.$5 | ||
, string: 'new ' + RegExp.$3 + '()' | ||
}; | ||
// class constructor | ||
} else if (/^\s*constructor\s*\(/.exec(str)) { | ||
return { | ||
type: 'constructor' | ||
, constructor: parentContext.name | ||
, cons: parentContext.name | ||
, name: 'constructor' | ||
, string: (parentContext && parentContext.name && parentContext.name + '.prototype.' || '') + 'constructor()' | ||
}; | ||
// class method | ||
} else if (/^\s*([\w$]+)\s*\(/.exec(str)) { | ||
return { | ||
type: 'method' | ||
, constructor: parentContext.name | ||
, cons: parentContext.name | ||
, name: RegExp.$1 | ||
, string: (parentContext && parentContext.name && parentContext.name + '.prototype.' || '') + RegExp.$1 + '()' | ||
}; | ||
// named function statement, possibly exported by name or as a default | ||
} else if (/^\s*(export(\s+default)?\s+)?function\s+([\w$]+)\s*\(/.exec(str)) { | ||
return { | ||
type: 'function' | ||
, name: RegExp.$3 | ||
, string: RegExp.$3 + '()' | ||
}; | ||
// anonymous function expression exported as a default | ||
} else if (/^\s*export\s+default\s+function\s*\(/.exec(str)) { | ||
return { | ||
type: 'function' | ||
, name: RegExp.$1 // undefined | ||
, string: RegExp.$1 + '()' | ||
}; | ||
// function expression | ||
} else if (/^return\s+function(?:\s+([\w$]+))?\s*\(/.exec(str)) { | ||
return { | ||
type: 'function' | ||
, name: RegExp.$1 | ||
, string: RegExp.$1 + '()' | ||
}; | ||
// function expression | ||
} else if (/^\s*(?:const|let|var)\s+([\w$]+)\s*=\s*function/.exec(str)) { | ||
return { | ||
type: 'function' | ||
, name: RegExp.$1 | ||
, string: RegExp.$1 + '()' | ||
}; | ||
// prototype method | ||
} else if (/^\s*([\w$.]+)\s*\.\s*prototype\s*\.\s*([\w$]+)\s*=\s*function/.exec(str)) { | ||
return { | ||
var ctx; | ||
// loop through all context matchers, returning the first successful match | ||
return exports.contextPatternMatchers.some(function (matcher) { | ||
return ctx = matcher(str, parentContext); | ||
}) && ctx; | ||
}; | ||
exports.contextPatternMatchers = [ | ||
function (str) { | ||
// class, possibly exported by name or as a default | ||
if (/^\s*(export(\s+default)?\s+)?class\s+([\w$]+)(\s+extends\s+([\w$.]+))?\s*{/.exec(str)) { | ||
return { | ||
type: 'class' | ||
, constructor: RegExp.$3 | ||
, cons: RegExp.$3 | ||
, name: RegExp.$3 | ||
, extends: RegExp.$5 | ||
, string: 'new ' + RegExp.$3 + '()' | ||
}; | ||
} | ||
}, | ||
function (str, parentContext) { | ||
// class constructor | ||
if (/^\s*constructor\s*\(/.exec(str)) { | ||
return { | ||
type: 'constructor' | ||
, constructor: parentContext.name | ||
, cons: parentContext.name | ||
, name: 'constructor' | ||
, string: (parentContext && parentContext.name && parentContext.name + '.prototype.' || '') + 'constructor()' | ||
}; | ||
// class method | ||
} | ||
}, | ||
function (str, parentContext) { | ||
if (/^\s*([\w$]+)\s*\(/.exec(str)) { | ||
return { | ||
type: 'method' | ||
, constructor: RegExp.$1 | ||
, cons: RegExp.$1 | ||
, name: RegExp.$2 | ||
, string: RegExp.$1 + '.prototype.' + RegExp.$2 + '()' | ||
}; | ||
// prototype property | ||
} else if (/^\s*([\w$.]+)\s*\.\s*prototype\s*\.\s*([\w$]+)\s*=\s*([^\n;]+)/.exec(str)) { | ||
return { | ||
, constructor: parentContext.name | ||
, cons: parentContext.name | ||
, name: RegExp.$1 | ||
, string: (parentContext && parentContext.name && parentContext.name + '.prototype.' || '') + RegExp.$1 + '()' | ||
}; | ||
// named function statement, possibly exported by name or as a default | ||
} | ||
}, | ||
function (str) { | ||
if (/^\s*(export(\s+default)?\s+)?function\s+([\w$]+)\s*\(/.exec(str)) { | ||
return { | ||
type: 'function' | ||
, name: RegExp.$3 | ||
, string: RegExp.$3 + '()' | ||
}; | ||
} | ||
}, | ||
function (str) { | ||
// anonymous function expression exported as a default | ||
if (/^\s*export\s+default\s+function\s*\(/.exec(str)) { | ||
return { | ||
type: 'function' | ||
, name: RegExp.$1 // undefined | ||
, string: RegExp.$1 + '()' | ||
}; | ||
} | ||
}, | ||
function (str) { | ||
// function expression | ||
if (/^return\s+function(?:\s+([\w$]+))?\s*\(/.exec(str)) { | ||
return { | ||
type: 'function' | ||
, name: RegExp.$1 | ||
, string: RegExp.$1 + '()' | ||
}; | ||
} | ||
}, | ||
function (str) { | ||
// function expression | ||
if (/^\s*(?:const|let|var)\s+([\w$]+)\s*=\s*function/.exec(str)) { | ||
return { | ||
type: 'function' | ||
, name: RegExp.$1 | ||
, string: RegExp.$1 + '()' | ||
}; | ||
} | ||
}, | ||
function (str, parentContext) { | ||
// prototype method | ||
if (/^\s*([\w$.]+)\s*\.\s*prototype\s*\.\s*([\w$]+)\s*=\s*function/.exec(str)) { | ||
return { | ||
type: 'method' | ||
, constructor: RegExp.$1 | ||
, cons: RegExp.$1 | ||
, name: RegExp.$2 | ||
, string: RegExp.$1 + '.prototype.' + RegExp.$2 + '()' | ||
}; | ||
} | ||
}, | ||
function (str) { | ||
// prototype property | ||
if (/^\s*([\w$.]+)\s*\.\s*prototype\s*\.\s*([\w$]+)\s*=\s*([^\n;]+)/.exec(str)) { | ||
return { | ||
type: 'property' | ||
, constructor: RegExp.$1 | ||
, cons: RegExp.$1 | ||
, name: RegExp.$2 | ||
, value: RegExp.$3.trim() | ||
, string: RegExp.$1 + '.prototype.' + RegExp.$2 | ||
}; | ||
} | ||
}, | ||
function (str) { | ||
// prototype property without assignment | ||
if (/^\s*([\w$]+)\s*\.\s*prototype\s*\.\s*([\w$]+)\s*/.exec(str)) { | ||
return { | ||
type: 'property' | ||
, constructor: RegExp.$1 | ||
, cons: RegExp.$1 | ||
, name: RegExp.$2 | ||
, string: RegExp.$1 + '.prototype.' + RegExp.$2 | ||
}; | ||
} | ||
}, | ||
function (str) { | ||
// inline prototype | ||
if (/^\s*([\w$.]+)\s*\.\s*prototype\s*=\s*{/.exec(str)) { | ||
return { | ||
type: 'prototype' | ||
, constructor: RegExp.$1 | ||
, cons: RegExp.$1 | ||
, name: RegExp.$1 | ||
, string: RegExp.$1 + '.prototype' | ||
}; | ||
} | ||
}, | ||
function (str, parentContext) { | ||
// inline method | ||
if (/^\s*([\w$.]+)\s*:\s*function/.exec(str)) { | ||
return { | ||
type: 'method' | ||
, constructor: parentContext.name | ||
, cons: parentContext.name | ||
, name: RegExp.$1 | ||
, string: (parentContext && parentContext.name && parentContext.name + '.prototype.' || '') + RegExp.$1 + '()' | ||
}; | ||
} | ||
}, | ||
function (str, parentContext) { | ||
// inline property | ||
if (/^\s*([\w$.]+)\s*:\s*([^\n;]+)/.exec(str)) { | ||
return { | ||
type: 'property' | ||
, constructor: RegExp.$1 | ||
, cons: RegExp.$1 | ||
, name: RegExp.$2 | ||
, value: RegExp.$3.trim() | ||
, string: RegExp.$1 + '.prototype.' + RegExp.$2 | ||
}; | ||
// prototype property without assignment | ||
} else if (/^\s*([\w$]+)\s*\.\s*prototype\s*\.\s*([\w$]+)\s*/.exec(str)) { | ||
return { | ||
, constructor: parentContext.name | ||
, cons: parentContext.name | ||
, name: RegExp.$1 | ||
, value: RegExp.$2.trim() | ||
, string: (parentContext && parentContext.name && parentContext.name + '.' || '') + RegExp.$1 | ||
}; | ||
} | ||
}, | ||
function (str, parentContext) { | ||
// inline getter/setter | ||
if (/^\s*(get|set)\s*([\w$.]+)\s*\(/.exec(str)) { | ||
return { | ||
type: 'property' | ||
, constructor: RegExp.$1 | ||
, cons: RegExp.$1 | ||
, name: RegExp.$2 | ||
, string: RegExp.$1 + '.prototype.' + RegExp.$2 | ||
}; | ||
// inline prototype | ||
} else if (/^\s*([\w$.]+)\s*\.\s*prototype\s*=\s*{/.exec(str)) { | ||
return { | ||
type: 'prototype' | ||
, constructor: RegExp.$1 | ||
, cons: RegExp.$1 | ||
, name: RegExp.$1 | ||
, string: RegExp.$1 + '.prototype' | ||
}; | ||
// inline method | ||
} else if (/^\s*([\w$.]+)\s*:\s*function/.exec(str)) { | ||
return { | ||
type: 'method' | ||
, constructor: parentContext.name | ||
, cons: parentContext.name | ||
, name: RegExp.$1 | ||
, string: (parentContext && parentContext.name && parentContext.name + '.prototype.' || '') + RegExp.$1 + '()' | ||
}; | ||
// inline property | ||
} else if (/^\s*([\w$.]+)\s*:\s*([^\n;]+)/.exec(str)) { | ||
return { | ||
type: 'property' | ||
, constructor: parentContext.name | ||
, cons: parentContext.name | ||
, name: RegExp.$1 | ||
, value: RegExp.$2.trim() | ||
, string: (parentContext && parentContext.name && parentContext.name + '.' || '') + RegExp.$1 | ||
}; | ||
// inline getter/setter | ||
} else if (/^\s*(get|set)\s*([\w$.]+)\s*\(/.exec(str)) { | ||
return { | ||
type: 'property' | ||
, constructor: parentContext.name | ||
, cons: parentContext.name | ||
, name: RegExp.$2 | ||
, string: (parentContext && parentContext.name && parentContext.name + '.prototype.' || '') + RegExp.$2 | ||
}; | ||
// method | ||
} else if (/^\s*([\w$.]+)\s*\.\s*([\w$]+)\s*=\s*function/.exec(str)) { | ||
return { | ||
type: 'method' | ||
, receiver: RegExp.$1 | ||
, name: RegExp.$2 | ||
, string: RegExp.$1 + '.' + RegExp.$2 + '()' | ||
}; | ||
// property | ||
} else if (/^\s*([\w$.]+)\s*\.\s*([\w$]+)\s*=\s*([^\n;]+)/.exec(str)) { | ||
return { | ||
type: 'property' | ||
, receiver: RegExp.$1 | ||
, name: RegExp.$2 | ||
, value: RegExp.$3.trim() | ||
, string: RegExp.$1 + '.' + RegExp.$2 | ||
}; | ||
// declaration | ||
} else if (/^\s*(?:const|let|var)\s+([\w$]+)\s*=\s*([^\n;]+)/.exec(str)) { | ||
return { | ||
type: 'declaration' | ||
, name: RegExp.$1 | ||
, value: RegExp.$2.trim() | ||
, string: RegExp.$1 | ||
}; | ||
, constructor: parentContext.name | ||
, cons: parentContext.name | ||
, name: RegExp.$2 | ||
, string: (parentContext && parentContext.name && parentContext.name + '.prototype.' || '') + RegExp.$2 | ||
}; | ||
} | ||
}, | ||
function (str) { | ||
// method | ||
if (/^\s*([\w$.]+)\s*\.\s*([\w$]+)\s*=\s*function/.exec(str)) { | ||
return { | ||
type: 'method' | ||
, receiver: RegExp.$1 | ||
, name: RegExp.$2 | ||
, string: RegExp.$1 + '.' + RegExp.$2 + '()' | ||
}; | ||
} | ||
}, | ||
function (str) { | ||
// property | ||
if (/^\s*([\w$.]+)\s*\.\s*([\w$]+)\s*=\s*([^\n;]+)/.exec(str)) { | ||
return { | ||
type: 'property' | ||
, receiver: RegExp.$1 | ||
, name: RegExp.$2 | ||
, value: RegExp.$3.trim() | ||
, string: RegExp.$1 + '.' + RegExp.$2 | ||
}; | ||
} | ||
}, | ||
function (str) { | ||
// declaration | ||
if (/^\s*(?:const|let|var)\s+([\w$]+)\s*=\s*([^\n;]+)/.exec(str)) { | ||
return { | ||
type: 'declaration' | ||
, name: RegExp.$1 | ||
, value: RegExp.$2.trim() | ||
, string: RegExp.$1 | ||
}; | ||
} | ||
} | ||
}; | ||
]; | ||
@@ -634,0 +710,0 @@ exports.setMarkedOptions = function(opts) { |
{ | ||
"name": "dox", | ||
"description": "Markdown / JSdoc documentation generator", | ||
"version": "0.7.0", | ||
"version": "0.7.1", | ||
"author": "TJ Holowaychuk <tj@vision-media.ca>", | ||
@@ -6,0 +6,0 @@ "contributors": [ |
@@ -408,2 +408,20 @@ # Dox | ||
### Extending Context Matching | ||
Context matching in dox is done by performing pattern matching against the code following a | ||
comment block. `dox.contextPatternMatchers` is an array of all pattern matching functions, | ||
which dox will iterate over until one of them returns a result. If none return a result, | ||
then the comment block does not receive a `ctx` value. | ||
This array is exposed to allow for extension of unsupported context patterns by adding more | ||
functions. Each function is passed the code following the comment block and (if detected) | ||
the parent context if the block. | ||
```js | ||
dox.contextPatternMatchers.push(function (str, parentContext) { | ||
// return a context object if found | ||
// return false otherwise | ||
}); | ||
``` | ||
### Ignore | ||
@@ -410,0 +428,0 @@ |
Sorry, the diff of this file is not supported yet
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
43990
714
477
0