@jaames/cod
Advanced tools
Comparing version 1.2.1 to 1.2.3
498
dist/cod.js
@@ -1,245 +0,259 @@ | ||
const REGEX_NEWLINE = /\r?\n/; | ||
function extractDocCommentsBetween(src, beginDoc, endDoc) { | ||
let blocks = []; | ||
let inside = false; | ||
let currDepth = 0; | ||
let currSubDepth = 0; | ||
let currBlockText = []; | ||
let currStartLine = 0; | ||
const srcLines = src.split(REGEX_NEWLINE); | ||
for (let i = 0; i < srcLines.length; i++) { | ||
const lineNum = i + 1; | ||
const line = srcLines[i]; | ||
// outside a block | ||
if (!inside) { | ||
currDepth = line.indexOf(beginDoc); | ||
// block start | ||
if (currDepth >= 0) { | ||
inside = true; | ||
currBlockText = []; | ||
currStartLine = lineNum; | ||
} | ||
} | ||
// inside block | ||
else { | ||
const idx = line.indexOf(endDoc); | ||
// block end | ||
if (idx >= 0) { | ||
inside = false; | ||
blocks.push({ | ||
body: currBlockText, | ||
lineBefore: currStartLine - 1, | ||
lineAfter: lineNum + 1 | ||
}); | ||
currBlockText = []; | ||
currStartLine = 0; | ||
} | ||
else { | ||
let substr = line.substring(currDepth); | ||
const search = substr.search(/[^ ]/); | ||
if (search >= 0) | ||
currSubDepth = search; | ||
else if (substr.length < currSubDepth) | ||
substr = ' '.repeat(currSubDepth + 1); | ||
currBlockText.push(substr); | ||
} | ||
} | ||
} | ||
return blocks; | ||
} | ||
function extractDocCommentsWithPrefix(src, docLinePrefix) { | ||
let blocks = []; | ||
let inside = false; | ||
let currDepth = 0; | ||
let currSubDepth = 0; | ||
let currBlockText = []; | ||
let currStartLine = 0; | ||
const prefixRegex = new RegExp(`^(${docLinePrefix})`); | ||
const srcLines = src.split(REGEX_NEWLINE); | ||
for (let i = 0; i < srcLines.length; i++) { | ||
const lineNum = i + 1; | ||
const line = srcLines[i]; | ||
// outside a block | ||
if (!inside) { | ||
// currDepth = line.indexOf(docLinePrefix); | ||
// block start | ||
if (line.startsWith(docLinePrefix)) { | ||
currDepth = 0; | ||
inside = true; | ||
currBlockText = []; | ||
currStartLine = lineNum; | ||
} | ||
} | ||
// inside block | ||
if (inside) { | ||
const idx = line.indexOf(docLinePrefix); | ||
// block end | ||
if (idx == -1) { | ||
inside = false; | ||
blocks.push({ | ||
body: currBlockText, | ||
lineBefore: currStartLine - 1, | ||
lineAfter: lineNum | ||
}); | ||
currBlockText = []; | ||
currStartLine = 0; | ||
} | ||
else { | ||
let substr = line.replace(prefixRegex, '').substring(currDepth); | ||
const search = substr.search(/[^ ]/); | ||
if (search >= 0) | ||
currSubDepth = search; | ||
else if (substr.length < currSubDepth) | ||
substr = ' '.repeat(currSubDepth + 1); | ||
currBlockText.push(substr); | ||
} | ||
} | ||
} | ||
return blocks; | ||
} | ||
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
typeof define === 'function' && define.amd ? define(['exports'], factory) : | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.cod = {})); | ||
})(this, (function (exports) { 'use strict'; | ||
var ParsedLineType; | ||
(function (ParsedLineType) { | ||
ParsedLineType[ParsedLineType["Text"] = 0] = "Text"; | ||
ParsedLineType[ParsedLineType["NumberTag"] = 1] = "NumberTag"; | ||
ParsedLineType[ParsedLineType["StringTag"] = 2] = "StringTag"; | ||
ParsedLineType[ParsedLineType["BooleanTag"] = 3] = "BooleanTag"; | ||
ParsedLineType[ParsedLineType["PlainTag"] = 4] = "PlainTag"; | ||
})(ParsedLineType || (ParsedLineType = {})); | ||
// parses a line to extract the tag + value, or the text. assumes indentation has already been stripped. | ||
const parseTag = (line) => { | ||
// match float or int value | ||
const numMatch = line.match(/^(@\S+)\s+(([+-]?\d+(\.\d+)?))/i); | ||
if (numMatch) | ||
return { type: ParsedLineType.NumberTag, key: numMatch[1], value: parseFloat(numMatch[2]) }; | ||
// match string or explicit boolean value | ||
const stringMatch = line.match(/^(@\S+)\s+(.+)/i); | ||
if (stringMatch) { | ||
const val = stringMatch[2]; | ||
if (val === 'true' || val === 'false') | ||
return { type: ParsedLineType.BooleanTag, key: stringMatch[1], value: Boolean(val) }; | ||
return { type: ParsedLineType.StringTag, key: stringMatch[1], value: val }; | ||
} | ||
// match tag identifier | ||
const tagMatch = line.match(/^(@\S+)/i); | ||
if (tagMatch) | ||
return { type: ParsedLineType.PlainTag, key: tagMatch[1] }; | ||
return { type: ParsedLineType.Text, value: line }; | ||
}; | ||
// parse a line to figure out its indent level, and extract any tags | ||
const parseLine = (line) => { | ||
const indent = line.length - line.trimStart().length; | ||
return { | ||
line, | ||
indent, | ||
parsed: parseTag(line.substring(indent)), | ||
children: [], | ||
}; | ||
}; | ||
// sorts lines into a tree structure by their indent level | ||
const buildIndentTree = (lines) => { | ||
if (lines.length >= 2) { | ||
let firstLine = lines.shift(); | ||
let nextLine = lines[0]; | ||
const children = []; | ||
while (firstLine.indent < nextLine.indent) { | ||
children.push(lines.shift()); | ||
if (lines.length === 0) | ||
break; | ||
nextLine = lines[0]; | ||
} | ||
firstLine.children = buildIndentTree(children); | ||
if (lines.length > 0) | ||
return [firstLine].concat(buildIndentTree(lines)); | ||
else | ||
return [firstLine]; | ||
} | ||
else if (lines.length === 1) { | ||
lines[0].children = []; | ||
return lines; | ||
} | ||
else | ||
return []; | ||
}; | ||
// transform an indent tree into our nicely formatted doc structure | ||
const transformTree = (output, node) => { | ||
const parsed = node.parsed; | ||
const type = parsed.type; | ||
// add a key to the output doc node | ||
const addValue = (key, value) => { | ||
// if a key has been seen twice, merge both values into an array | ||
if (output.hasOwnProperty(key)) { | ||
const mapVal = output[key]; | ||
if (Array.isArray(mapVal)) { | ||
mapVal.push(value); | ||
output[key] = mapVal; | ||
} | ||
else | ||
output[key] = [mapVal, value]; | ||
} | ||
else | ||
output[key] = value; | ||
}; | ||
// standard tags | ||
if (type !== ParsedLineType.Text && node.children.length === 0) { | ||
// no value and no children, assume true boolean | ||
if (type === ParsedLineType.PlainTag) | ||
addValue(parsed.key, true); | ||
// explicit boolean value | ||
else if (type === ParsedLineType.BooleanTag) | ||
addValue(parsed.key, parsed.value); | ||
// string value | ||
else if (type === ParsedLineType.StringTag) | ||
addValue(parsed.key, parsed.value); | ||
// int or float value | ||
else if (type === ParsedLineType.NumberTag) | ||
addValue(parsed.key, parsed.value); | ||
} | ||
// text | ||
else if (type === ParsedLineType.Text) { | ||
const text = []; | ||
// if text is indented the parser considers it a child node (bleh), but a workaround is just collecting children and ignoring lower indents | ||
const condenseText = (node, indentLevel) => { | ||
text.push(node.line.substring(indentLevel)); | ||
node.children.forEach((subNode) => condenseText(subNode, indentLevel)); | ||
}; | ||
condenseText(node, node.indent); | ||
if (output.text) | ||
output.text += '\n' + text.join('\n'); | ||
else | ||
output.text = text.join('\n'); | ||
} | ||
// nested values | ||
else { | ||
const childMap = {}; | ||
node.children.forEach((subNode) => transformTree(childMap, subNode)); | ||
addValue(parsed.key, childMap); | ||
} | ||
return output; | ||
}; | ||
// takes an extracted doc comment block and parses it into our doc object | ||
const parseCommentBlock = ({ body, lineBefore, lineAfter }) => { | ||
const block = { lineBefore, lineAfter }; | ||
const lines = body.map(parseLine); | ||
const tree = buildIndentTree(lines); | ||
tree.forEach((item) => transformTree(block, item)); | ||
return block; | ||
}; | ||
var REGEX_NEWLINE = /\r?\n/; | ||
function extractDocCommentsBetween(src, beginDoc, endDoc) { | ||
var blocks = []; | ||
var inside = false; | ||
var currDepth = 0; | ||
var currSubDepth = 0; | ||
var currBlockText = []; | ||
var currStartLine = 0; | ||
var srcLines = src.split(REGEX_NEWLINE); | ||
for (var i = 0; i < srcLines.length; i++) { | ||
var lineNum = i + 1; | ||
var line = srcLines[i]; | ||
// outside a block | ||
if (!inside) { | ||
currDepth = line.indexOf(beginDoc); | ||
// block start | ||
if (currDepth >= 0) { | ||
inside = true; | ||
currBlockText = []; | ||
currStartLine = lineNum; | ||
} | ||
} | ||
// inside block | ||
else { | ||
var idx = line.indexOf(endDoc); | ||
// block end | ||
if (idx >= 0) { | ||
inside = false; | ||
blocks.push({ | ||
body: currBlockText, | ||
lineBefore: currStartLine - 1, | ||
lineAfter: lineNum + 1 | ||
}); | ||
currBlockText = []; | ||
currStartLine = 0; | ||
} | ||
else { | ||
var substr = line.substring(currDepth); | ||
var search = substr.search(/[^ ]/); | ||
if (search >= 0) | ||
currSubDepth = search; | ||
else if (substr.length < currSubDepth) | ||
substr = ' '.repeat(currSubDepth + 1); | ||
currBlockText.push(substr); | ||
} | ||
} | ||
} | ||
return blocks; | ||
} | ||
function extractDocCommentsWithPrefix(src, docLinePrefix) { | ||
var blocks = []; | ||
var inside = false; | ||
var currDepth = 0; | ||
var currSubDepth = 0; | ||
var currBlockText = []; | ||
var currStartLine = 0; | ||
var prefixRegex = new RegExp("^(".concat(docLinePrefix, ")")); | ||
var srcLines = src.split(REGEX_NEWLINE); | ||
for (var i = 0; i < srcLines.length; i++) { | ||
var lineNum = i + 1; | ||
var line = srcLines[i]; | ||
// outside a block | ||
if (!inside) { | ||
// currDepth = line.indexOf(docLinePrefix); | ||
// block start | ||
if (line.startsWith(docLinePrefix)) { | ||
currDepth = 0; | ||
inside = true; | ||
currBlockText = []; | ||
currStartLine = lineNum; | ||
} | ||
} | ||
// inside block | ||
if (inside) { | ||
var idx = line.indexOf(docLinePrefix); | ||
// block end | ||
if (idx == -1) { | ||
inside = false; | ||
blocks.push({ | ||
body: currBlockText, | ||
lineBefore: currStartLine - 1, | ||
lineAfter: lineNum | ||
}); | ||
currBlockText = []; | ||
currStartLine = 0; | ||
} | ||
else { | ||
var substr = line.replace(prefixRegex, '').substring(currDepth); | ||
var search = substr.search(/[^ ]/); | ||
if (search >= 0) | ||
currSubDepth = search; | ||
else if (substr.length < currSubDepth) | ||
substr = ' '.repeat(currSubDepth + 1); | ||
currBlockText.push(substr); | ||
} | ||
} | ||
} | ||
return blocks; | ||
} | ||
function cod(text, config) { | ||
const opts = Object.assign({ | ||
docBegin: '/**', | ||
docEnd: 's*/', | ||
docLinePrefix: '' | ||
}, config); | ||
if (opts.docLinePrefix) { | ||
const blocks = extractDocCommentsWithPrefix(text, opts.docLinePrefix); | ||
return blocks.map(parseCommentBlock); | ||
} | ||
else { | ||
const blocks = extractDocCommentsBetween(text, opts.docBegin, opts.docEnd); | ||
return blocks.map(parseCommentBlock); | ||
} | ||
} | ||
exports.ParsedLineType = void 0; | ||
(function (ParsedLineType) { | ||
ParsedLineType[ParsedLineType["Text"] = 0] = "Text"; | ||
ParsedLineType[ParsedLineType["NumberTag"] = 1] = "NumberTag"; | ||
ParsedLineType[ParsedLineType["StringTag"] = 2] = "StringTag"; | ||
ParsedLineType[ParsedLineType["BooleanTag"] = 3] = "BooleanTag"; | ||
ParsedLineType[ParsedLineType["PlainTag"] = 4] = "PlainTag"; | ||
})(exports.ParsedLineType || (exports.ParsedLineType = {})); | ||
// parses a line to extract the tag + value, or the text. assumes indentation has already been stripped. | ||
var parseTag = function (line) { | ||
// match float or int value | ||
var numMatch = line.match(/^(@\S+)\s+(([+-]?\d+(\.\d+)?))/i); | ||
if (numMatch) | ||
return { type: exports.ParsedLineType.NumberTag, key: numMatch[1], value: parseFloat(numMatch[2]) }; | ||
// match string or explicit boolean value | ||
var stringMatch = line.match(/^(@\S+)\s+(.+)/i); | ||
if (stringMatch) { | ||
var val = stringMatch[2]; | ||
if (val === 'true' || val === 'false') | ||
return { type: exports.ParsedLineType.BooleanTag, key: stringMatch[1], value: Boolean(val) }; | ||
return { type: exports.ParsedLineType.StringTag, key: stringMatch[1], value: val }; | ||
} | ||
// match tag identifier | ||
var tagMatch = line.match(/^(@\S+)/i); | ||
if (tagMatch) | ||
return { type: exports.ParsedLineType.PlainTag, key: tagMatch[1] }; | ||
return { type: exports.ParsedLineType.Text, value: line }; | ||
}; | ||
// parse a line to figure out its indent level, and extract any tags | ||
var parseLine = function (line) { | ||
var indent = line.length - line.trimStart().length; | ||
return { | ||
line: line, | ||
indent: indent, | ||
parsed: parseTag(line.substring(indent)), | ||
children: [], | ||
}; | ||
}; | ||
// sorts lines into a tree structure by their indent level | ||
var buildIndentTree = function (lines) { | ||
if (lines.length >= 2) { | ||
var firstLine = lines.shift(); | ||
var nextLine = lines[0]; | ||
var children = []; | ||
while (firstLine.indent < nextLine.indent) { | ||
children.push(lines.shift()); | ||
if (lines.length === 0) | ||
break; | ||
nextLine = lines[0]; | ||
} | ||
firstLine.children = buildIndentTree(children); | ||
if (lines.length > 0) | ||
return [firstLine].concat(buildIndentTree(lines)); | ||
else | ||
return [firstLine]; | ||
} | ||
else if (lines.length === 1) { | ||
lines[0].children = []; | ||
return lines; | ||
} | ||
else | ||
return []; | ||
}; | ||
// transform an indent tree into our nicely formatted doc structure | ||
var transformTree = function (output, node) { | ||
var parsed = node.parsed; | ||
var type = parsed.type; | ||
// add a key to the output doc node | ||
var addValue = function (key, value) { | ||
// if a key has been seen twice, merge both values into an array | ||
if (output.hasOwnProperty(key)) { | ||
var mapVal = output[key]; | ||
if (Array.isArray(mapVal)) { | ||
mapVal.push(value); | ||
output[key] = mapVal; | ||
} | ||
else | ||
output[key] = [mapVal, value]; | ||
} | ||
else | ||
output[key] = value; | ||
}; | ||
// standard tags | ||
if (type !== exports.ParsedLineType.Text && node.children.length === 0) { | ||
// no value and no children, assume true boolean | ||
if (type === exports.ParsedLineType.PlainTag) | ||
addValue(parsed.key, true); | ||
// explicit boolean value | ||
else if (type === exports.ParsedLineType.BooleanTag) | ||
addValue(parsed.key, parsed.value); | ||
// string value | ||
else if (type === exports.ParsedLineType.StringTag) | ||
addValue(parsed.key, parsed.value); | ||
// int or float value | ||
else if (type === exports.ParsedLineType.NumberTag) | ||
addValue(parsed.key, parsed.value); | ||
} | ||
// text | ||
else if (type === exports.ParsedLineType.Text) { | ||
var text_1 = []; | ||
// if text is indented the parser considers it a child node (bleh), but a workaround is just collecting children and ignoring lower indents | ||
var condenseText_1 = function (node, indentLevel) { | ||
text_1.push(node.line.substring(indentLevel)); | ||
node.children.forEach(function (subNode) { return condenseText_1(subNode, indentLevel); }); | ||
}; | ||
condenseText_1(node, node.indent); | ||
if (output.text) | ||
output.text += '\n' + text_1.join('\n'); | ||
else | ||
output.text = text_1.join('\n'); | ||
} | ||
// nested values | ||
else { | ||
var childMap_1 = {}; | ||
node.children.forEach(function (subNode) { return transformTree(childMap_1, subNode); }); | ||
addValue(parsed.key, childMap_1); | ||
} | ||
return output; | ||
}; | ||
// takes an extracted doc comment block and parses it into our doc object | ||
var parseCommentBlock = function (_a) { | ||
var body = _a.body, lineBefore = _a.lineBefore, lineAfter = _a.lineAfter; | ||
var block = { lineBefore: lineBefore, lineAfter: lineAfter }; | ||
var lines = body.map(parseLine); | ||
var tree = buildIndentTree(lines); | ||
tree.forEach(function (item) { return transformTree(block, item); }); | ||
return block; | ||
}; | ||
export { ParsedLineType, cod, extractDocCommentsBetween, extractDocCommentsWithPrefix, parseCommentBlock }; | ||
function cod(text, config) { | ||
var opts = Object.assign({ | ||
docBegin: '/**', | ||
docEnd: 's*/', | ||
docLinePrefix: '' | ||
}, config); | ||
if (opts.docLinePrefix) { | ||
var blocks = extractDocCommentsWithPrefix(text, opts.docLinePrefix); | ||
return blocks.map(parseCommentBlock); | ||
} | ||
else { | ||
var blocks = extractDocCommentsBetween(text, opts.docBegin, opts.docEnd); | ||
return blocks.map(parseCommentBlock); | ||
} | ||
} | ||
exports.cod = cod; | ||
exports.extractDocCommentsBetween = extractDocCommentsBetween; | ||
exports.extractDocCommentsWithPrefix = extractDocCommentsWithPrefix; | ||
exports.parseCommentBlock = parseCommentBlock; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
})); |
{ | ||
"name": "@jaames/cod", | ||
"version": "1.2.1", | ||
"version": "1.2.3", | ||
"description": "An unopinionated documentation generator.", | ||
"main": "dist/cod.js", | ||
"module": "dist/cod.js", | ||
"files": [ | ||
"dist/*.js" | ||
], | ||
"main": "dist/cod.js", | ||
"module": "dist/cod.es.js", | ||
"bin": { | ||
"cod": "dist/cli.js" | ||
}, | ||
"types": "dist/index.d.ts", | ||
"scripts": { | ||
@@ -11,0 +15,0 @@ "build": "rollup -c --environment BUILD:production", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
132519
6
3529