Skip to content

Instantly share code, notes, and snippets.

@pavanpodila
Created October 7, 2019 05:11
Show Gist options
  • Save pavanpodila/5694287573e16684fdeec7cd5cfd5c91 to your computer and use it in GitHub Desktop.
Save pavanpodila/5694287573e16684fdeec7cd5cfd5c91 to your computer and use it in GitHub Desktop.
Metadata Loader files
const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const generator = require('@babel/generator').default;
module.exports = function(source) {
// Parse to get the AST
const ast = parser.parse(source, {
sourceType: 'module',
plugins: [
'jsx',
[
'decorators',
{
decoratorsBeforeExport: false,
},
],
],
});
// The current context is the loader and contains methods to emitError, emitFile etc.
const loader = this;
// Visit the AST, specifically the ClassDeclaration, which has the decorator
traverse(ast, {
ClassDeclaration: ({ node }) => {
const name = node.id.name;
const result = getMetadata(node.decorators || []);
if (!result) return;
const { decorator, args } = result;
// Strip out the decorator from the AST
node.decorators = node.decorators.filter(x => x !== decorator);
if (node.decorators.length === 0) {
delete node.decorators;
}
const options = {
name,
...args,
env: {
context: loader.context,
},
};
// Validate that the options are correctly specified, such the name, description, thumbnail.
// Also checks that the thumbnail file actually exists
if (!validateOptions(options, name, loader)) return;
loader.emitFile(
`${options.name}.component.json`,
JSON.stringify(options, null, 4),
);
},
});
const { code } = generator(ast);
return code;
};
import React from 'react';
@Metadata({
name: 'Sample',
thumbnail: './sample.png',
description: 'A Sample Component',
properties: [
{ name: 'title', label: 'Title', type: 'string' },
{ name: 'message', label: 'Message', type: 'string' },
],
})
class SampleComponent extends React.Component {}
const path = require('path');
module.exports = {
entry: './sample/index.js',
output: {
path: path.resolve('./build'),
filename: 'sample.js',
},
module: {
rules: [
{
test: /\.js$/,
use: [
/* used last */ 'babel-loader',
/* used first in chain*/ path.resolve('./lib/index.js'),
],
},
],
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment