/
var
/
www
/
greso.tech
/
server
/
nsm
/
node_modules
/
catharsis
/
lib
/
/var/www/greso.tech/server/nsm/node_modules/catharsis/lib
mkdir
upload
Name
Size
Mode
Actions
describe.js
16495
0644
edit
dl
rm
parser.js
262802
0644
edit
dl
rm
schema.js
1476
0644
edit
dl
rm
stringify.js
6656
0644
edit
dl
rm
types.js
654
0644
edit
dl
rm
Edit:
/var/www/greso.tech/server/nsm/node_modules/catharsis/lib/describe.js
(16495B)
const _ = require('lodash'); const fs = require('fs'); const path = require('path'); const stringify = require('./stringify'); const Types = require('./types'); const DEFAULT_OPTIONS = { language: 'en', resources: { en: JSON.parse(fs.readFileSync(path.join(__dirname, '../res/en.json'), 'utf8')) } }; // order matters for these! const FUNCTION_DETAILS = ['new', 'this']; const FUNCTION_DETAILS_VARIABLES = ['functionNew', 'functionThis']; const MODIFIERS = ['optional', 'nullable', 'repeatable']; const TEMPLATE_VARIABLES = [ 'application', 'codeTagClose', 'codeTagOpen', 'element', 'field', 'functionNew', 'functionParams', 'functionReturns', 'functionThis', 'keyApplication', 'name', 'nullable', 'optional', 'param', 'prefix', 'repeatable', 'suffix', 'type' ]; const FORMATS = { EXTENDED: 'extended', SIMPLE: 'simple' }; function makeTagOpen(codeTag, codeClass) { let tagOpen = ''; const tags = codeTag ? codeTag.split(' ') : []; tags.forEach(tag => { const tagClass = codeClass ? ` class="${codeClass}"` : ''; tagOpen += `<${tag}${tagClass}>`; }); return tagOpen; } function makeTagClose(codeTag) { let tagClose = ''; const tags = codeTag ? codeTag.split(' ') : []; tags.reverse(); tags.forEach(tag => { tagClose += `</${tag}>`; }); return tagClose; } function reduceMultiple(context, keyName, contextName, translate, previous, current, index, items) { let key; switch (index) { case 0: key = '.first.many'; break; case (items.length - 1): key = '.last.many'; break; default: key = '.middle.many'; } key = keyName + key; context[contextName] = items[index]; return previous + translate(key, context); } function modifierKind(useLongFormat) { return useLongFormat ? FORMATS.EXTENDED : FORMATS.SIMPLE; } function buildModifierStrings(describer, modifiers, type, useLongFormat) { const result = {}; modifiers.forEach(modifier => { const key = modifierKind(useLongFormat); const modifierStrings = describer[modifier](type[modifier]); result[modifier] = modifierStrings[key]; }); return result; } function addModifiers(describer, context, result, type, useLongFormat) { const keyPrefix = `modifiers.${modifierKind(useLongFormat)}`; const modifiers = buildModifierStrings(describer, MODIFIERS, type, useLongFormat); MODIFIERS.forEach(modifier => { const modifierText = modifiers[modifier] || ''; result.modifiers[modifier] = modifierText; if (!useLongFormat) { context[modifier] = modifierText; } }); context.prefix = describer._translate(`${keyPrefix}.prefix`, context); context.suffix = describer._translate(`${keyPrefix}.suffix`, context); } function addFunctionModifiers(describer, context, {modifiers}, type, useLongFormat) { const functionDetails = buildModifierStrings(describer, FUNCTION_DETAILS, type, useLongFormat); FUNCTION_DETAILS.forEach((functionDetail, i) => { const functionExtraInfo = functionDetails[functionDetail] || ''; const functionDetailsVariable = FUNCTION_DETAILS_VARIABLES[i]; modifiers[functionDetailsVariable] = functionExtraInfo; if (!useLongFormat) { context[functionDetailsVariable] += functionExtraInfo; } }); } // Replace 2+ whitespace characters with a single whitespace character. function collapseSpaces(string) { return string.replace(/(\s)+/g, '$1'); } function getApplicationKey({expression}, applications) { if (applications.length === 1) { if (/[Aa]rray/.test(expression.name)) { return 'array'; } else { return 'other'; } } else if (/[Ss]tring/.test(applications[0].name)) { // object with string keys return 'object'; } else { // object with non-string keys return 'objectNonString'; } } class Result { constructor() { this.description = ''; this.modifiers = { functionNew: '', functionThis: '', optional: '', nullable: '', repeatable: '' }; this.returns = ''; } } class Context { constructor(props) { props = props || {}; TEMPLATE_VARIABLES.forEach(variable => { this[variable] = props[variable] || ''; }); } } class Describer { constructor(opts) { let options; this._useLongFormat = true; options = this._options = _.defaults(opts || {}, DEFAULT_OPTIONS); this._stringifyOptions = _.defaults(options, { _ignoreModifiers: true }); // use a dictionary, not a Context object, so we can more easily merge this into Context objects this._i18nContext = { codeTagClose: makeTagClose(options.codeTag), codeTagOpen: makeTagOpen(options.codeTag, options.codeClass) }; // templates start out as strings; we lazily replace them with template functions this._templates = options.resources[options.language]; if (!this._templates) { throw new Error(`I18N resources are not available for the language ${options.language}`); } } _stringify(type, typeString, useLongFormat) { const context = new Context({ type: typeString || stringify(type, this._stringifyOptions) }); const result = new Result(); addModifiers(this, context, result, type, useLongFormat); result.description = this._translate('type', context).trim(); return result; } _translate(key, context) { let result; let templateFunction = _.get(this._templates, key); context = context || new Context(); if (templateFunction === undefined) { throw new Error(`The template ${key} does not exist for the ` + `language ${this._options.language}`); } // compile and cache the template function if necessary if (typeof templateFunction === 'string') { // force the templates to use the `context` object templateFunction = templateFunction.replace(/<%= /g, '<%= context.'); templateFunction = _.template(templateFunction, {variable: 'context'}); _.set(this._templates, key, templateFunction); } result = (templateFunction(_.extend(context, this._i18nContext)) || '') // strip leading spaces .replace(/^\s+/, ''); result = collapseSpaces(result); return result; } _modifierHelper(key, modifierPrefix = '', context) { return { extended: key ? this._translate(`${modifierPrefix}.${FORMATS.EXTENDED}.${key}`, context) : '', simple: key ? this._translate(`${modifierPrefix}.${FORMATS.SIMPLE}.${key}`, context) : '' }; } _translateModifier(key, context) { return this._modifierHelper(key, 'modifiers', context); } _translateFunctionModifier(key, context) { return this._modifierHelper(key, 'function', context); } application(type, useLongFormat) { const applications = type.applications.slice(0); const context = new Context(); const key = `application.${getApplicationKey(type, applications)}`; const result = new Result(); addModifiers(this, context, result, type, useLongFormat); context.type = this.type(type.expression).description; context.application = this.type(applications.pop()).description; context.keyApplication = applications.length ? this.type(applications.pop()).description : ''; result.description = this._translate(key, context).trim(); return result; } elements(type, useLongFormat) { const context = new Context(); const items = type.elements.slice(0); const result = new Result(); addModifiers(this, context, result, type, useLongFormat); result.description = this._combineMultiple(items, context, 'union', 'element'); return result; } new(funcNew) { const context = new Context({'functionNew': this.type(funcNew).description}); const key = funcNew ? 'new' : ''; return this._translateFunctionModifier(key, context); } nullable(nullable) { let key; switch (nullable) { case true: key = 'nullable'; break; case false: key = 'nonNullable'; break; default: key = ''; } return this._translateModifier(key); } optional(optional) { const key = (optional === true) ? 'optional' : ''; return this._translateModifier(key); } repeatable(repeatable) { const key = (repeatable === true) ? 'repeatable' : ''; return this._translateModifier(key); } _combineMultiple(items, context, keyName, contextName) { const result = new Result(); const self = this; let strings; strings = typeof items[0] === 'string' ? items.slice(0) : items.map(item => self.type(item).description); switch (strings.length) { case 0: // falls through case 1: context[contextName] = strings[0] || ''; result.description = this._translate(`${keyName}.first.one`, context); break; case 2: strings.forEach((item, idx) => { const key = `${keyName + (idx === 0 ? '.first' : '.last' )}.two`; context[contextName] = item; result.description += self._translate(key, context); }); break; default: result.description = strings.reduce(reduceMultiple.bind(null, context, keyName, contextName, this._translate.bind(this)), ''); } return result.description.trim(); } /* eslint-enable no-unused-vars */ params(params, functionContext) { const context = new Context(); const result = new Result(); const self = this; let strings; // TODO: this hardcodes the order and placement of functionNew and functionThis; need to move // this to the template (and also track whether to put a comma after the last modifier) functionContext = functionContext || {}; params = params || []; strings = params.map(param => self.type(param).description); if (functionContext.functionThis) { strings.unshift(functionContext.functionThis); } if (functionContext.functionNew) { strings.unshift(functionContext.functionNew); } result.description = this._combineMultiple(strings, context, 'params', 'param'); return result; } this(funcThis) { const context = new Context({'functionThis': this.type(funcThis).description}); const key = funcThis ? 'this' : ''; return this._translateFunctionModifier(key, context); } type(type, useLongFormat) { let result = new Result(); if (useLongFormat === undefined) { useLongFormat = this._useLongFormat; } // ensure we don't use the long format for inner types this._useLongFormat = false; if (!type) { return result; } switch (type.type) { case Types.AllLiteral: result = this._stringify(type, this._translate('all'), useLongFormat); break; case Types.FunctionType: result = this._signature(type, useLongFormat); break; case Types.NameExpression: result = this._stringify(type, null, useLongFormat); break; case Types.NullLiteral: result = this._stringify(type, this._translate('null'), useLongFormat); break; case Types.RecordType: result = this._record(type, useLongFormat); break; case Types.TypeApplication: result = this.application(type, useLongFormat); break; case Types.TypeUnion: result = this.elements(type, useLongFormat); break; case Types.UndefinedLiteral: result = this._stringify(type, this._translate('undefined'), useLongFormat); break; case Types.UnknownLiteral: result = this._stringify(type, this._translate('unknown'), useLongFormat); break; default: throw new Error(`Unknown type: ${JSON.stringify(type)}`); } return result; } _record(type, useLongFormat) { const context = new Context(); let items; const result = new Result(); items = this._recordFields(type.fields); addModifiers(this, context, result, type, useLongFormat); result.description = this._combineMultiple(items, context, 'record', 'field'); return result; } _recordFields(fields) { const context = new Context(); let result = []; const self = this; if (!fields.length) { return result; } result = fields.map(field => { const key = `field.${field.value ? 'typed' : 'untyped'}`; context.name = self.type(field.key).description; if (field.value) { context.type = self.type(field.value).description; } return self._translate(key, context); }); return result; } _getHrefForString(nameString) { let href = ''; const links = this._options.links; if (!links) { return href; } // accept a map or an object if (links instanceof Map) { href = links.get(nameString); } else if ({}.hasOwnProperty.call(links, nameString)) { href = links[nameString]; } return href; } _addLinks(nameString) { const href = this._getHrefForString(nameString); let link = nameString; let linkClass = this._options.linkClass || ''; if (href) { if (linkClass) { linkClass = ` class="${linkClass}"`; } link = `<a href="${href}"${linkClass}>${nameString}</a>`; } return link; } result(type, useLongFormat) { const context = new Context(); const key = `function.${modifierKind(useLongFormat)}.returns`; const result = new Result(); context.type = this.type(type).description; addModifiers(this, context, result, type, useLongFormat); result.description = this._translate(key, context); return result; } _signature(type, useLongFormat) { const context = new Context(); const kind = modifierKind(useLongFormat); const result = new Result(); let returns; addModifiers(this, context, result, type, useLongFormat); addFunctionModifiers(this, context, result, type, useLongFormat); context.functionParams = this.params(type.params || [], context).description; if (type.result) { returns = this.result(type.result, useLongFormat); if (useLongFormat) { result.returns = returns.description; } else { context.functionReturns = returns.description; } } result.description += this._translate(`function.${kind}.signature`, context).trim(); return result; } } module.exports = (type, options) => { const simple = new Describer(options).type(type, false); const extended = new Describer(options).type(type); [simple, extended].forEach(result => { result.description = collapseSpaces(result.description.trim()); }); return { simple: simple.description, extended }; };
Save
cmd:
run