rollup-plugin-drupal-sdc-generator
Version:
This is a [Rollup](https://rollupjs.org) plugin that creates [single directory components](https://www.drupal.org/docs/develop/theming-drupal/using-single-directory-components) for embedding your app in a [Drupal](https://www.drupal.org) module or theme.
129 lines (108 loc) • 4.44 kB
JavaScript
;
var promises = require('node:fs/promises');
var node_path = require('node:path');
var node_url = require('node:url');
var yaml = require('yaml');
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
const FILE_PATH = node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
const DIRECTORY_NAME = node_path.dirname(FILE_PATH);
function drupalSdcGenerator({
directory: _directory,
group,
label: _label = 'My Component',
} = {}) {
const directory = _directory || node_path.join(DIRECTORY_NAME, '../templates');
const label = _label || 'My Component';
return {
name: 'rollup-plugin-drupal-sdc-generator',
async generateBundle(options, bundle) {
for (const bundleId in bundle) {
const { isEntry, name, fileName, type } = bundle[bundleId];
this.debug(
`Working on ${bundleId} isEntry=${isEntry}, name=${name}, fileName=${fileName}, type=${type}`,
);
if (Object.hasOwn(bundle, 'style.css')) {
const bundleId = 'style.css';
const cssFileName = node_path.basename(options.dir);
this.debug({
message: `Renaming ${bundleId} to ${cssFileName}.css`,
});
bundle[bundleId].fileName = `${cssFileName}.css`;
}
if (type !== 'chunk' || !isEntry) {
this.debug({ message: `Skipping ${bundleId}` });
continue;
}
const templateDirectory =
typeof directory === 'object' ? directory[name] : directory;
const files = await promises.readdir(templateDirectory);
const templateLabel = typeof label === 'object' ? label[name] : label;
const templateGroup = typeof group === 'object' ? group[name] : group;
await Promise.all(
files.map(async (file) => {
const source = await promises.readFile(
node_path.join(templateDirectory, file),
'utf8',
);
const emittedFileName = file.replace('[name]', name);
this.debug(`emitted filename is ${emittedFileName}`);
const vars = { name, label: templateLabel };
const reducer = (acc, key) => {
return acc
.replaceAll(
new RegExp(`(?<!\\[)\\[${key}](?!])`, 'g'),
vars[key],
)
.replaceAll(new RegExp(`\\[\\[${key}\\]]`, 'g'), `[${key}]`);
};
const sourceDoc = yaml.parseDocument(source);
if (
templateGroup &&
sourceDoc.contents &&
sourceDoc.contents.items
) {
sourceDoc.add(sourceDoc.createPair('group', templateGroup));
}
const applyVars = (str) => Object.keys(vars).reduce(reducer, str);
const processComments = (node) => {
if (!node) return;
if (node.commentBefore != null) {
node.commentBefore = applyVars(node.commentBefore);
}
if (node.comment != null) {
node.comment = applyVars(node.comment);
}
};
yaml.visit(sourceDoc, {
Pair(_, pair) {
if (pair.key) {
processComments(pair.key);
if (typeof pair.key.value === 'string') {
pair.key.value = applyVars(pair.key.value);
}
}
if (pair.value) {
processComments(pair.value);
if (typeof pair.value.value === 'string') {
pair.value.value = applyVars(pair.value.value);
}
}
},
});
const emittedSource = yaml.stringify(sourceDoc);
const emittedFile = {
type: 'asset',
fileName: emittedFileName,
source: emittedSource,
};
this.debug({
message: `Emitting ${bundleId} => ${emittedFile.fileName}`,
});
this.emitFile(emittedFile);
}),
);
}
},
};
}
module.exports = drupalSdcGenerator;