minecraft-utils-shared
Version:
Shared utils for Minecraft Bedrock / Forge development related utilities.
195 lines (187 loc) • 8.01 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _chalk = _interopRequireDefault(require("chalk"));
var _fsExtra = _interopRequireDefault(require("fs-extra"));
var _path = _interopRequireDefault(require("path"));
var _template_file = _interopRequireDefault(require("../formats/template_file.cjs"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* @file Minecraft Utils Shared - Template
* @license Apache-2.0
* @author Markus@Bordihn.de (Markus Bordihn)
*/
/**
* @returns {string}
*/
const getTemplatePath = () => {
if (process.env) {
if ((process.env.npm_lifecycle_script || '').includes('minecraft-bedrock-utils') || (process.env.npm_package_name || '').includes('minecraft-bedrock-utils')) {
return '.minecraft-bedrock-utils-templates';
} else if ((process.env.npm_lifecycle_script || '').includes('minecraft-forge-utils') || (process.env.npm_package_name || '').includes('minecraft-forge-utils')) {
return '.minecraft-forge-utils-templates';
}
}
return '.minecraft-utils-shared-templates';
};
// eslint-disable-next-line prefer-const
let templatePath = _path.default.join(process.cwd(), getTemplatePath());
/**
* Template Processing engine
*
* The target path could be a simple string for easier operations or
* and object for more advanced requirements like Forge Mods.
* We expect the targetPath Object in the following format:
* {
* assetsPath: '',
* classPath: '',
* dataPath: '',
* }
*
* @param {string} template
* @param {object} placeholder
* @param {string|object} targetPath
*/
const processTemplateFile = (template, placeholder, targetPath = '') => {
if (!_fsExtra.default.existsSync(template)) {
console.error('Unable to find template:', template);
return;
}
if (targetPath && typeof targetPath == 'object') {
console.log(_chalk.default.green('🏷️ Processing multi template', template, 'with', placeholder, 'and', targetPath));
} else {
if (targetPath && !_fsExtra.default.existsSync(targetPath)) {
console.error('Unable to access target path:', targetPath);
return;
}
console.log(_chalk.default.green('🏷️ Processing template', template, 'with', placeholder));
}
const templateDefinition = _template_file.default.parse(template, placeholder);
templateDefinition.forEach(definition => {
const fileName = definition.fileName;
let filePath = definition.filePath;
// Automatically detect correct target path based on file type.
if (targetPath && typeof targetPath == 'object') {
switch (definition.fileType) {
case _template_file.default.fileType.JAVA:
filePath = _path.default.join(targetPath.classPath, definition.filePath);
break;
case _template_file.default.fileType.RESOURCE:
filePath = _path.default.join(targetPath.assetsPath, definition.filePath);
break;
case _template_file.default.fileType.DATA:
filePath = _path.default.join(targetPath.dataPath, definition.filePath);
break;
case _template_file.default.fileType.DATA_MINECRAFT:
filePath = _path.default.join(targetPath.dataPath, '..', definition.filePath);
break;
}
} else if (targetPath) {
filePath = _path.default.join(targetPath, definition.filePath);
}
let content = '';
// Handle different kind of operation based on the patch definition.
if (definition.copy) {
// Copy src file to dst file, if not already exists
if (_fsExtra.default.existsSync(filePath)) {
console.info(_chalk.default.red('[Skipping Copy]'), fileName, 'already exists.');
} else {
console.info(_chalk.default.green('[Copy]'), fileName);
_fsExtra.default.ensureDirSync(_path.default.dirname(filePath));
_fsExtra.default.copyFileSync(definition.copy, filePath);
}
} else if (definition.create) {
// Create new file
if (_fsExtra.default.existsSync(filePath)) {
console.info(_chalk.default.red('[Skipping Create]'), fileName, 'already exists.');
} else {
console.info(_chalk.default.green('[Create]'), fileName);
content = definition.code;
}
} else if (definition.before || definition.after) {
// Patch existing files according the "after" or "before" placeholder.
// We will only processing the file if the code is not already included!
if (filePath && _fsExtra.default.existsSync(filePath)) {
content = _fsExtra.default.readFileSync(filePath, 'utf-8');
if (!content) {
console.error(_chalk.default.red('[Skipping after/before]'), fileName, 'file is empty.');
} else if (content.includes(definition.code)) {
console.info(_chalk.default.yellow('[Skipping after/before]'), fileName, 'code is already injected.');
content = '';
} else if (definition.after) {
const insertPositionRegExp = new RegExp(`${escapeRegExp(definition.after)}[ \t]*(\r\n|\n|\r)?`);
const insertPosition = content.search(insertPositionRegExp);
if (insertPosition != -1) {
const insertPositionLength = content.match(insertPositionRegExp)[0].length;
console.info(_chalk.default.green('[After]'), 'Inject code into', fileName);
content = content.slice(0, insertPosition + insertPositionLength) + definition.code + content.slice(insertPosition + insertPositionLength);
} else {
console.warn(_chalk.default.yellow('[After]'), 'Unable to find entry point', definition.after, 'in', fileName);
}
} else if (definition.before) {
const insertPosition = content.search(new RegExp(`[ \t]*${escapeRegExp(definition.before)}`));
if (insertPosition != -1) {
console.info(_chalk.default.green('[Before]'), 'Inject code into', fileName);
content = content.slice(0, insertPosition) + definition.code + content.slice(insertPosition);
} else {
console.warn(_chalk.default.yellow('[Before]'), 'Unable to find entry point', definition.before, 'in', fileName);
}
}
} else {
// Show an error, if the file doesn't exists under the location!
console.error(_chalk.default.red('[Skipping after/before]'), fileName, 'file does not exists at', filePath);
}
} else {
// Show an general error for any unknown template option.
console.warn(_chalk.default.yellow('[?] Unsupported template option, skipping', fileName, '!'));
}
if (content) {
_fsExtra.default.outputFileSync(filePath, content);
}
});
};
/**
* @param {string} content
* @param {object} placeholder
* @returns {string}
*/
const replacePlaceholder = (content, placeholder = {}) => {
const newContent = content.replace(/\[\[ --([A-Za-z0-9_. ]+)-- \]\]/g, matchString => {
const placeholderString = matchString.replace('[[ --', '').replace('-- ]]', '').trim();
return placeholder[placeholderString] || placeholderString;
});
return newContent;
};
/**
* @param {string} text
* @returns {string}
*/
const escapeRegExp = text => {
return text.replace(/[\\(){}[\]^$+*?.]/g, '\\$&');
};
const hasCustomTemplateFiles = () => {
return !_fsExtra.default.existsSync(templatePath) ? false : !_fsExtra.default.emptyDirSync(templatePath);
};
const getCustomTemplateFiles = () => {
if (!_fsExtra.default.existsSync(templatePath)) {
return null;
}
const result = [];
_fsExtra.default.readdirSync(templatePath).forEach(file => {
const filePath = _path.default.resolve(templatePath, file);
if (_fsExtra.default.lstatSync(filePath).isFile()) {
result.push(filePath);
}
});
return result;
};
var _default = {
getCustomTemplateFiles,
hasCustomTemplateFiles,
processTemplateFile,
replacePlaceholder,
templatePath
};
exports.default = _default;