generator-begcode
Version:
Spring Boot + Angular/React/Vue in one handy generator
128 lines (127 loc) • 5.86 kB
JavaScript
import assert from 'assert';
import { escapeRegExp, kebabCase } from 'lodash-es';
import { joinCallbacks } from './write-files.js';
export const convertToPrettierExpressions = (str) => str.replace(/\s+/g, '([\\s\n]*)').replace(/>+/g, '(\n?[\\s]*)>');
export const checkContentIn = (contentToCheck, content, ignoreWhitespaces = true) => {
assert(content, 'content is required');
assert(contentToCheck, 'contentToCheck is required');
let re;
if (typeof contentToCheck === 'string') {
const pattern = ignoreWhitespaces
? convertToPrettierExpressions(escapeRegExp(contentToCheck))
: contentToCheck
.split('\n')
.map(line => `\\s*${escapeRegExp(line)}`)
.join('\n');
re = new RegExp(pattern);
}
else {
re = contentToCheck;
}
return re.test(content);
};
export const insertContentBeforeNeedle = ({ content, contentToAdd, needle, autoIndent = true }) => {
assert(needle, 'needle is required');
assert(content, 'content is required');
assert(contentToAdd, 'contentToAdd is required');
needle = needle.includes('jhipster-needle-') ? needle : `jhipster-needle-${needle}`;
let regexp = new RegExp(`(?://|<!--|/*|#) ${needle}(?:$|\n| )`, 'g');
let firstMatch = regexp.exec(content);
if (!firstMatch) {
regexp = new RegExp(`"${needle}": `, 'g');
firstMatch = regexp.exec(content);
if (!firstMatch) {
return null;
}
}
if (typeof contentToAdd !== 'function' && regexp.exec(content)) {
throw new Error(`Multiple needles found for ${needle}`);
}
const needleIndex = firstMatch.index;
const needleLineIndex = content.lastIndexOf('\n', needleIndex);
const beforeContent = content.substring(0, needleLineIndex + 1);
const afterContent = content.substring(needleLineIndex + 1);
const needleLine = afterContent.split('\n', 2)[0];
const needleIndent = needleLine.length - needleLine.trimStart().length;
if (typeof contentToAdd === 'function') {
return contentToAdd(content, { needleIndent, indentPrefix: ' '.repeat(needleIndent) });
}
contentToAdd = Array.isArray(contentToAdd) ? contentToAdd : [contentToAdd];
if (autoIndent) {
contentToAdd = contentToAdd.map(eachContentToAdd => eachContentToAdd.split('\n')).flat();
}
const firstContent = contentToAdd.find(line => line.trim());
if (!firstContent) {
return null;
}
const contentIndent = firstContent.length - firstContent.trimStart().length;
if (needleIndent > contentIndent) {
const identToApply = ' '.repeat(needleIndent - contentIndent);
contentToAdd = contentToAdd.map(line => (line ? identToApply + line : line));
}
else if (needleIndent < contentIndent) {
let identToRemove = contentIndent - needleIndent;
contentToAdd
.filter(line => line.trimStart())
.forEach(line => {
const trimmedLine = line.trimStart();
const lineIndent = line.length - trimmedLine.length;
if (lineIndent < identToRemove) {
identToRemove = lineIndent;
}
});
contentToAdd = contentToAdd.map(line => (line.length > identToRemove ? line.substring(identToRemove) : ''));
}
return `${beforeContent}${contentToAdd.join('\n')}\n${afterContent}`;
};
export const createNeedleCallback = ({ needle, contentToAdd, contentToCheck, optional = false, ignoreWhitespaces = true, autoIndent, }) => {
assert(needle, 'needle is required');
assert(contentToAdd, 'contentToAdd is required');
return function (content, filePath) {
if (contentToCheck && checkContentIn(contentToCheck, content, ignoreWhitespaces)) {
return content;
}
if (typeof contentToAdd !== 'function') {
if (typeof contentToAdd === 'string' && contentToAdd.startsWith('\n')) {
contentToAdd = contentToAdd.slice(1);
}
contentToAdd = (Array.isArray(contentToAdd) ? contentToAdd : [contentToAdd]).filter(eachContent => !checkContentIn(eachContent, content, ignoreWhitespaces));
if (contentToAdd.length === 0) {
return content;
}
}
const newContent = insertContentBeforeNeedle({
needle,
content,
contentToAdd,
autoIndent,
});
if (newContent) {
return newContent;
}
const message = `Missing ${optional ? 'optional' : 'required'} jhipster-needle ${needle} not found at '${filePath}'`;
if (optional && this) {
this.log.warn(message);
return content;
}
throw new Error(message);
};
};
export function createBaseNeedle(options, needles) {
const actualNeedles = needles === undefined ? options : needles;
const actualOptions = needles === undefined ? {} : options;
assert(actualNeedles, 'needles is required');
const { needlesPrefix, filePath, ...needleOptions } = actualOptions;
needleOptions.optional = needleOptions.optional ?? false;
needleOptions.ignoreWhitespaces = needleOptions.ignoreWhitespaces ?? true;
const callbacks = Object.entries(actualNeedles)
.filter(([_key, contentToAdd]) => contentToAdd)
.map(([key, contentToAdd]) => createNeedleCallback({ ...needleOptions, needle: `${needlesPrefix ? `${needlesPrefix}-` : ''}${kebabCase(key)}`, contentToAdd }));
assert(callbacks.length > 0, 'At least 1 needle is required');
const callback = callbacks.length === 1 ? callbacks[0] : joinCallbacks(...callbacks);
if (filePath) {
assert(this?.editFile, 'when passing filePath, the generator is required');
return this.editFile(filePath, callback);
}
return callback;
}