UNPKG

@enterthenamehere/esdoc

Version:

Good Documentation Generator For JavaScript, updated for new decade

170 lines (152 loc) 5.28 kB
/** * Param Type Parser class. */ export default class ParamParser { /** * parse param value. * @param {string} value - param value. * @param {boolean} [type=true] if true, contain param type. * @param {boolean} [name=true] if true, contain param name. * @param {boolean} [desc=true] if true, contain param description. * @return {{typeText: string, paramName: string, paramDesc: string}} parsed value. * * @example * let value = '{number} param - this is number param'; * let {typeText, paramName, paramDesc} = ParamParser.parseParamValue(value); * * let value = '{number} this is number return value'; * let {typeText, paramDesc} = ParamParser.parseParamValue(value, true, false, true); * * let value = '{number}'; * let {typeText} = ParamParser.parseParamValue(value, true, false, false); */ static parseParamValue(value, type = true, name = true, desc = true) { value = value.trim(); let match = []; let typeText = null; let paramName = null; let paramDesc = null; // e.g {number} if (type) { const reg = /^\{([^@]*?)\}(\s+|$)/u; // ``@`` is special char in ``{@link foo}`` match = value.match(reg); if (match) { typeText = match[1]; value = value.replace(reg, ''); } else { typeText = '*'; } } // e.g. [p1=123] if (name) { if (value.charAt(0) === '[') { paramName = ''; let counter = 0; for (const c of value) { paramName += c; if (c === '[') counter++; if (c === ']') counter--; if (counter === 0) break; } if (paramName) { value = value.substr(paramName.length).trim(); } } else { match = value.match(/^(\S+)/u); if (match) { paramName = match[1]; value = value.replace(/^\S+\s*/u, ''); } } } // e.g. this is p1 desc. if (desc) { paramDesc = ( value.startsWith('-') ? value.substring(1).trimStart() : value ); } if( !(typeText || paramName || paramDesc ) ) { console.error(`ParamParser::parseParamValue() - Param is invalid. param = "${value}"`); throw new Error(`ParamParser::parseParamValue() - Param is invalid. param = "${value}"`); } return {typeText, paramName, paramDesc}; } /** * parse param text and build formatted result. * @param {string} typeText - param type text. * @param {string} [paramName] - param name. * @param {string} [paramDesc] - param description. * @returns {ParsedParam} formatted result. * * @example * let value = '{number} param - this is number param'; * let {typeText, paramName, paramDesc} = ParamParser.parseParamValue(value); * let result = ParamParser.parseParam(typeText, paramName, paramDesc); */ static parseParam(typeText = null, paramName = null, paramDesc = null) { const result = {}; if (typeText) { // check nullable if (typeText[0] === '?') { result.nullable = true; } else if (typeText[0] === '!') { result.nullable = false; } else { result.nullable = null; } typeText = typeText.replace(/^[?!]/u, ''); // check record and union if (typeText[0] === '{') { result.types = [typeText]; } else if (typeText[0] === '(') { typeText = typeText.replace(/^[(]/u, '').replace(/[)]$/u, ''); result.types = typeText.split('|'); } else if (typeText.includes('|')) { if (typeText.match(/<.*?\|.*?>/u)) { // union in generics. e.g. `Array<string|number>` // hack: in this case, process this type in DocBuilder#_buildTypeDocLinkHTML result.types = [typeText]; } else if (typeText.match(/^\.\.\.\(.*?\)/u)) { // union with spread. e.g. `...(string|number)` // hack: in this case, process this type in DocBuilder#_buildTypeDocLinkHTML result.types = [typeText]; } else { result.types = typeText.split('|'); } } else { result.types = [typeText]; } if (typeText.indexOf('...') === 0) { result.spread = true; } else { result.spread = false; } } else { result.types = ['']; } if (result.types.some((t) => { return !t; })) { throw new Error(`Empty Type found name=${paramName} desc=${paramDesc}`); } if (paramName) { // check optional if (paramName[0] === '[') { result.optional = true; paramName = paramName.replace(/^[[]/u, '').replace(/[\]]$/u, ''); } else { result.optional = false; } // check default value const pair = paramName.split('='); if (pair.length === 2) { result.defaultValue = pair[1]; try { const raw = JSON.parse(pair[1]); result.defaultRaw = raw; } catch (e) { result.defaultRaw = pair[1]; } } result.name = pair[0].trim(); } result.description = paramDesc; return result; } }