rollup-plugin-stimulus
Version:
Rollup.js plugin for rolling Stimulus.js applications
186 lines (153 loc) • 4.76 kB
JavaScript
;
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var util = require('util');
var fs = _interopDefault(require('fs'));
function processBasePath(moduleConfig, rollupOptions) {
if (moduleConfig.rawBasePath) {
return moduleConfig.rawBasePath;
}
let basePath = moduleConfig.basePath;
if (!basePath) {
basePath = rollupOptions.input.replace(/\/+$/, '');
const baseNamePosition = basePath.lastIndexOf('/');
if (baseNamePosition !== -1) {
basePath = basePath.substring(0, baseNamePosition) + '/controllers';
}
}
if (!basePath.startsWith('/') && !basePath.startsWith('./')) {
basePath = `./${basePath.replace(/\/+$/, '')}`;
}
return basePath;
}
class Config
{
constructor() {
this.importName = '\0stimulus-controllers';
this.basePath = null;
}
configure(moduleConfig, rollupOptions) {
if (!moduleConfig) {
moduleConfig = {};
} else if (typeof moduleConfig === 'string') {
moduleConfig = {
basePath: moduleConfig
};
}
this.basePath = processBasePath(moduleConfig, rollupOptions);
if (moduleConfig.importName) {
this.importName = `\0${moduleConfig.importName}`;
}
if (!moduleConfig.showWarnings) {
const originalWarnHandler = rollupOptions.onwarn;
rollupOptions.onwarn = function(warning, warn) {
if (warning.code === 'THIS_IS_UNDEFINED'
&& warning.loc.file.includes('/@stimulus/')
) {
return;
}
if (originalWarnHandler) {
originalWarnHandler(warning, warn);
} else {
warn(warning);
}
};
}
}
}
/**
* @param {string} basePath: the path to search for controllers in
* @param {string} path: the path relative to the basePath to search
*/
function * iterateControllerFilesRecursive(basePath, path) {
const dir = path ? `${basePath}/${path}` : basePath;
if (!fs.existsSync(dir) || !fs.lstatSync(dir).isDirectory()) {
return;
}
const files = fs.readdirSync(dir, {withFileTypes: true});
for (let file of files) {
const relativePath = path ? `${path}/${file.name}` : file.name;
if (file.isDirectory()) {
yield * iterateControllerFilesRecursive(basePath, relativePath);
continue;
}
if (!file.isFile()) {
continue;
}
const logicalName = (relativePath.match(/^(?:\.\/)?(.+)(?:[_-]controller\..+?)$/) || [])[1];
if (logicalName) {
const identifier = logicalName.replace(/_/g, '-').replace(/\//g, '--');
yield new Controller(identifier, `${basePath}/${relativePath}`);
}
}}
class Controller
{
/**
* @param {string} basePath: the path to search for controllers in
* @returns Controller
*/
static * findAllInDirectory(basePath) {
yield * iterateControllerFilesRecursive(basePath, '');
}
constructor(identifier, path) {
/**
* The controller identifier to be used in the data-controller attribute,
* generated using Stimulus' conventions
*
* @type {string}
*/
this.identifier = identifier;
/**
* The path to the file containing the Controller's source, which should
* export the Stimulus Controller as its default: `export default class`
*
* @type {string}
*/
this.path = path;
/**
* The controller identifier converted to a format that is safe to use as a
* JavaScript variable in the `import` statement.
*
* @type {string}
*/
this.importIdentifier = 'import_' + this.identifier.replace(/-/g, '_');
}
}
function generateImport({importIdentifier: ctrl, path}) {
return util.format('import %s from %j;\n', ctrl, path);
}
function generateExport({identifier: id, importIdentifier: ctrl}) {
return util.format(' {identifier: %j, controllerConstructor: %s},\n', id, ctrl);
}
function generateControllersImport(config) {
const controllers = Controller.findAllInDirectory(config.basePath);
let imports = '';
let exports = '\nexport default [\n';
for (const controller of controllers) {
imports += generateImport(controller);
exports += generateExport(controller);
}
exports += '];\n';
return imports + exports;
}
function rollupPluginStimulus(moduleConfig) {
let config = new Config();
return {
name: "rollup-plugin-stimulus",
options(options) {
config.configure(moduleConfig, options);
},
resolveId(id) {
if (`\0${id}` === config.importName) {
return config.importName;
}
return null;
},
load(id) {
if (id !== config.importName) {
return;
}
return generateControllersImport(config);
}
};
}
module.exports = rollupPluginStimulus;