UNPKG

@bitrix/cli

Version:
412 lines (395 loc) 14 kB
'use strict'; 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;