@bitrix/cli
Version:
Bitrix CLI tools
412 lines (395 loc) • 14 kB
JavaScript
;
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var postcss = _interopDefault(require('rollup-plugin-postcss-independed'));
var autoprefixer = _interopDefault(require('autoprefixer'));
var json = _interopDefault(require('rollup-plugin-json'));
var babel = _interopDefault(require('rollup-plugin-simple-babel'));
var resolve = _interopDefault(require('rollup-plugin-node-resolve'));
var commonjs = _interopDefault(require('rollup-plugin-commonjs'));
var postcssSvgo = _interopDefault(require('postcss-svgo'));
var rollupPluginTerser = require('rollup-plugin-terser');
var os = _interopDefault(require('os'));
var postcss$1 = _interopDefault(require('postcss'));
var declProcessor = require('postcss-url/src/lib/decl-processor');
var rollupUrl = _interopDefault(require('rollup-plugin-url'));
var slash = _interopDefault(require('slash'));
var path = _interopDefault(require('path'));
var fs = require('fs');
var fs__default = _interopDefault(fs);
const appRoot = path.resolve(__dirname, '../');
const lockFile = path.resolve(os.homedir(), '.bitrix.lock');
function resolvePackageModule(moduleName) {
return path.resolve(appRoot, 'node_modules', moduleName);
}
/**
* Parses component template path
* @example
* /bitrix/modules/main/install/components/bitrix/news.list/templates/.default/script.js
* /local/modules/main/install/components/bitrix/news.list/templates/.default/script.js
* /.../modules/main/install/components/bitrix/news.list/templates/.default/script.js
*
* /.../modules/main/install/templates/.../components/bitrix/news.list/templates/.default/script.js
*
* /bitrix/components/bitrix/news.list/templates/.default/script.js
* /local/components/bitrix/news.list/templates/.default/script.js
*
* /bitrix/templates/.../components/bitrix/news.list/templates/.default/script.js
* /local/templates/.../components/bitrix/news.list/templates/.default/script.js
*/
function parseComponentTemplatePath(sourcePath = '') {
const preparedPath = slash(sourcePath);
const installComponentsExp = new RegExp('/(.[a-z0-9_-]+)/modules/.[a-z0-9_-]+/install/components/(.[a-z0-9_-]+)/(.[.a-z0-9_-]+)/templates/(.[.a-z0-9_-]+)/');
const productComponentsExp = new RegExp('/(bitrix|local)/components/(.[a-z0-9_-]+)/(.[.a-z0-9_-]+)/templates/(.[.a-z0-9_-]+)/');
const moduleTemplateComponentsExp = new RegExp('/(.[a-z0-9_-]+)/modules/.[a-z0-9_-]+/install/templates/.[a-z0-9_-]+/components/(.[a-z0-9_-]+)/(.[.a-z0-9_-]+)/templates/(.[.a-z0-9_-]+)/');
const productTemplateComponentsExp = new RegExp('/(bitrix|local)/templates/.[a-z0-9_-]+/components/(.[a-z0-9_-]+)/(.[.a-z0-9_-]+)/templates/(.[.a-z0-9_-]+)/');
const componentsResult = preparedPath.match(installComponentsExp) || preparedPath.match(productComponentsExp) || preparedPath.match(moduleTemplateComponentsExp) || preparedPath.match(productTemplateComponentsExp);
if (!!componentsResult && !!componentsResult[1] && !!componentsResult[2] && !!componentsResult[3] && !!componentsResult[4]) {
const [templatePath,, namespace, component, template] = componentsResult;
const [, filePath] = preparedPath.split(path.join(templatePath));
const root = (() => {
const [, rootDirname] = componentsResult;
return ['bitrix', 'local'].includes(rootDirname) ? rootDirname : 'bitrix';
})();
return {
root,
namespace,
component,
template,
filePath
};
}
return null;
}
function isComponentPath(filePath) {
const parsed = parseComponentTemplatePath(filePath);
return !!parsed;
}
/**
* Parses site template path
* @example
* /.../modules/install/templates/.../
* /.../templates/.../
*/
function parseSiteTemplatePath(sourcePath = '') {
const preparedPath = slash(sourcePath);
const installTemplatesExp = new RegExp('/(.[a-z0-9_-]+)/modules/.[a-z0-9_-]+/install/templates/(.[a-z0-9_-]+)/');
const productTemplatesExp = new RegExp('/(local|bitrix)/templates/((.[a-z0-9-_]+))/');
const templateResult = preparedPath.match(installTemplatesExp) || preparedPath.match(productTemplatesExp);
if (!!templateResult && !!templateResult[1] && !!templateResult[2]) {
const [templatePath, rootDirname, template] = templateResult;
const root = ['bitrix', 'local'].includes(rootDirname) ? rootDirname : 'bitrix';
const [, filePath] = preparedPath.split(path.join(templatePath));
return {
root,
template,
filePath
};
}
return null;
}
function isTemplatePath(filePath) {
const parsed = parseSiteTemplatePath(filePath);
return !!parsed;
}
function getDestDir({
destDir,
output,
context
}) {
if (typeof destDir === 'string') {
return `${destDir.replace(/(^\.\/|^\/)(\/$)/g, '')}/`;
}
const outputDirname = path.dirname(output);
const preparedContext = path.join(context, '/');
if (isComponentPath(preparedContext) || isTemplatePath(preparedContext)) {
const relativeOutputPath = path.relative(preparedContext, outputDirname);
return path.join(relativeOutputPath, 'dist');
}
return path.relative(preparedContext, outputDirname);
}
const postcssBackgroundUrl = postcss$1.plugin('postcss-background-url', (options, sourceTo, context) => {
const preparedOptions = Array.isArray(options) ? options : [options];
const multipleOptions = preparedOptions.map(entry => {
const {
type: url = 'inline',
output,
...restOptions
} = entry || {};
const assetsPath = getDestDir({
destDir: output,
output: sourceTo,
context
});
if (typeof output === 'string') {
restOptions.assetsPath = path.resolve(context, assetsPath);
} else {
restOptions.assetsPath = path.resolve(context, assetsPath, 'images');
}
return {
maxSize: 14,
fallback: 'copy',
...restOptions,
url
};
});
return (styles, result) => {
const {
from: sourceFrom
} = result.opts || {};
const from = sourceFrom ? path.dirname(sourceFrom) : '.';
const to = sourceTo ? path.dirname(sourceTo) : from;
styles.walkDecls(decl => declProcessor.declProcessor(from, to, multipleOptions, result, decl));
};
});
const maxDepth = 10;
function findExtensionContext(sourcePath, depth = 0) {
const configPath = path.join(sourcePath, 'bundle.config.js');
if (fs__default.existsSync(configPath)) {
return sourcePath;
}
if (sourcePath.length > 1 && depth < maxDepth) {
const nextDepth = depth + 1;
const dirname = path.dirname(sourcePath);
return findExtensionContext(dirname, nextDepth);
}
return null;
}
/**
* Parses any extensions paths
* @example
* /../local/js/main/core/core.js
* /../bitrix/js/main/core/core.js
* /../bitrix/modules/main/install/js/main/core/core.js
* /../local/modules/main/install/js/main/core/core.js
* /../modules/main/install/js/main/core/core.js
*/
function parseExtensionPath(sourcePath = '') {
const preparedPath = slash(sourcePath);
const installJsExp = new RegExp('/(.[a-z0-9-_]+)/modules/(.[a-z0-9-_]+)/install/js/(.[a-z0-9-_]+)/');
const productJsExp = new RegExp('/(.[a-z0-9-_]+)/js/((.[a-z0-9-_]+))/');
const moduleResult = preparedPath.match(installJsExp) || preparedPath.match(productJsExp);
if (!!moduleResult && !!moduleResult[1] && !!moduleResult[2] && !!moduleResult[3]) {
const context = findExtensionContext(preparedPath);
if (context) {
const [jsPath, rootDirname, module, jsDir] = moduleResult;
const root = ['bitrix', 'local'].includes(rootDirname) ? rootDirname : 'bitrix';
const [, filePath] = preparedPath.split(path.join(context, '/'));
const extension = (() => {
const [, extPath = ''] = context.split(jsPath);
return extPath.split('/');
})();
return {
root,
module,
jsDir,
extension,
filePath
};
}
}
return null;
}
function resolveToProductPath(sourcePath) {
const parsedExtensionPath = parseExtensionPath(sourcePath);
if (parsedExtensionPath) {
const {
root,
jsDir,
extension,
filePath
} = parsedExtensionPath;
return `/${root}/js/${jsDir}/${extension.join('/')}${filePath ? `/${filePath}` : ''}`;
}
const parsedComponentPath = parseComponentTemplatePath(sourcePath);
if (parsedComponentPath) {
const {
root,
namespace,
component,
template,
filePath
} = parsedComponentPath;
return `/${root}/components/${namespace}/${component}/templates/${template}${filePath ? `/${filePath}` : ''}`;
}
const parsedSiteTemplatePath = parseSiteTemplatePath(sourcePath);
if (parsedSiteTemplatePath) {
const {
root,
template,
filePath
} = parsedSiteTemplatePath;
return `/${root}/templates/${template}${filePath ? `/${filePath}` : ''}`;
}
return null;
}
function rollupFiles(options) {
const productContext = resolveToProductPath(path.join(options.context, '/'));
if (productContext) {
const destDir = getDestDir({
destDir: options.resolveFilesImport.output,
output: options.output,
context: options.context
});
const rollupUrlOptions = {
fileName: '[dirname][name][extname]',
publicPath: slash(path.join(productContext, destDir, '/')),
destDir: slash(path.join(options.context, destDir)),
sourceDir: slash(path.dirname(options.input)),
include: options.resolveFilesImport.include,
exclude: options.resolveFilesImport.exclude,
limit: 0
};
return rollupUrl(rollupUrlOptions);
}
return undefined;
}
function rollupConfig({
input,
output,
context,
plugins = {},
cssImages = {},
resolveFilesImport = {},
targets,
transformClasses,
minification,
sourceMaps
}) {
const enabledPlugins = [];
const isLoaded = id => !!enabledPlugins.find(item => {
return item.name === id;
});
const compatMode = targets.some(rule => {
const parsed = String(rule).toLowerCase().split(' ');
return !parsed.includes('not') && (parsed.includes('ie') || parsed.includes('ie_mob'));
});
if (Array.isArray(plugins.custom)) {
plugins.custom.forEach(item => {
enabledPlugins.push(item);
});
}
if (plugins.resolve && !isLoaded('node-resolve')) {
enabledPlugins.push(resolve({
browser: true
}));
}
if (!isLoaded('json')) {
enabledPlugins.push(json());
}
if (!isLoaded('postcss')) {
enabledPlugins.push(postcss({
extract: output.css || true,
sourceMap: false,
plugins: [postcssBackgroundUrl(cssImages, output.css, context), (() => {
if (cssImages.svgo !== false) {
return postcssSvgo({
encode: true
});
}
return undefined;
})(), autoprefixer({
overrideBrowserslist: targets
})]
}));
}
if (plugins.babel !== false) {
enabledPlugins.push(babel(plugins.babel || {
sourceMaps,
presets: [[resolvePackageModule('@babel/preset-env'), {
targets,
bugfixes: !compatMode,
loose: !compatMode && !transformClasses
}]],
plugins: [resolvePackageModule('@babel/plugin-external-helpers'), resolvePackageModule('@babel/plugin-transform-flow-strip-types'), ...(() => {
const babelPlugins = [];
if (compatMode) {
Object.assign(babelPlugins, [resolvePackageModule('@babel/plugin-proposal-object-rest-spread')]);
}
if (compatMode || transformClasses) {
Object.assign(babelPlugins, [resolvePackageModule('@babel/plugin-proposal-class-properties'), resolvePackageModule('@babel/plugin-proposal-private-methods'), resolvePackageModule('@babel/plugin-transform-classes')]);
}
return babelPlugins;
})()]
}));
}
if (plugins.resolve && !isLoaded('commonjs')) {
enabledPlugins.push(commonjs({
sourceMap: false
}));
}
if (minification) {
const terserPlugin = (() => {
if (typeof minification === 'object') {
return rollupPluginTerser.terser(minification);
}
return rollupPluginTerser.terser();
})();
enabledPlugins.push(terserPlugin);
}
return {
input: {
input: input.input,
external: ['BX'],
treeshake: input.treeshake !== false,
plugins: [{
name: 'resolve-index',
resolveId: (importPath, modulePath) => {
if (!importPath || path.isAbsolute(importPath)) {
return null;
}
if (!modulePath) {
return null;
}
const moduleDir = path.dirname(modulePath);
const pathsToTry = ['.js', '.css', '.jsx', '.vue'].map(ext => {
return path.join(moduleDir, importPath, `index${ext}`);
});
const paths = pathsToTry.map(pathToTry => {
let stats;
let result = null;
try {
stats = fs.statSync(pathToTry);
if (stats.isFile()) {
result = pathToTry;
}
} catch (err) {
result = null;
}
return result;
});
const filteredPaths = paths.filter(Boolean);
if (filteredPaths.length > 1) {
throw new Error(` Found multiple matching paths! \n${filteredPaths.join('\n')}`.red);
}
return filteredPaths.at(0);
}
}, (() => {
if (!isLoaded('url') && resolveFilesImport !== false) {
return rollupFiles({
resolveFilesImport,
context,
input: input.input,
output: output.js
});
}
return undefined;
})(), ...enabledPlugins],
onwarn: () => {}
},
output: {
file: output.js,
name: output.name || 'window',
format: 'iife',
sourcemap: sourceMaps,
extend: true,
exports: 'named',
banner: '/* eslint-disable */',
globals: {
BX: 'BX',
window: 'window',
...output.globals
}
}
};
}
module.exports = rollupConfig;