Last active
August 30, 2021 12:20
-
-
Save anvilation/a192dd91ba36e972487503ede3344461 to your computer and use it in GitHub Desktop.
Smart UI CI / CD - Re-written Yeoman Widget Generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const chalk = require('chalk'); | |
const esprima = require('esprima'); | |
const escodegen = require('escodegen'); | |
const superb = require('superb'); | |
const yosay = require('yosay'); | |
const _ = require('../shared/lodash-complete'); | |
const Generator = require('yeoman-generator'); | |
-_.extend(Generator.prototype, require('yeoman-generator/lib/actions/install')); | |
const promptDefaults = { | |
"widgetDirectory": "hello", | |
"widgetClassPrefix": "Hello", | |
"widgetCssClass": "-hello", | |
"widgetTitle": "Hello", | |
"widgetDescription": "Simple Widget for the widgets", | |
"widgetBundle": "drive-all" | |
} | |
module.exports = class extends Generator { | |
constructor(args, opts) { | |
// Calling the super constructor is important so our generator is correctly set up | |
super(args, opts); | |
this.properties = {}; | |
this.option('secret-sauce', { | |
'default': false | |
}); | |
// Next, add your custom code | |
this.option('skip-install', { | |
desc: 'Skips the "npm install" command after generating the project.', | |
type: Boolean, | |
'default': false | |
}); | |
} | |
async prompting() { | |
this.log(yosay(`Let us add a ${superb.random()} ${chalk.red('CS UI Widget')}`)); | |
let modulePrefix = this.config.get('modulePrefix'); | |
let widgetName; | |
if (this.options['secret-sauce']) { | |
this.properties = promptDefaults | |
} else { | |
this.properties = await this.prompt([ | |
{ | |
type: "input", | |
name: "projectName", | |
message: 'CS module name:', | |
default: 'greetings', | |
filter: function (value) { | |
projectName = value; | |
return _.computerize(value); | |
} | |
}, | |
{ | |
type: 'input', | |
name: 'projectDescription', | |
message: 'CS module description:', | |
default: 'CS UI greetings extension module' | |
}, | |
{ | |
type: 'input', | |
name: 'modulePrefix', | |
message: 'RequireJS module prefix:', | |
default: () => { | |
return _.computerize(projectName).substring(0, 5); | |
}, | |
filter: (value) => { | |
return _.computerize(value); | |
} | |
} | |
]); | |
} | |
this.properties = await this.prompt([ | |
{ | |
type: 'input', | |
name: 'widgetDirectory', | |
message: 'Widget directory name:', | |
default: 'hello', | |
filter: function (value) { | |
widgetName = _.dottify(value); | |
return widgetName; | |
} | |
}, | |
{ | |
type: 'input', | |
name: 'widgetClassPrefix', | |
message: 'Widget class name prefix:', | |
default: function () { | |
return _.classify(widgetName); | |
}, | |
filter: function (value) { | |
return _.classify(value); | |
} | |
}, | |
{ | |
type: 'input', | |
name: 'widgetCssClass', | |
message: 'Widget CSS class name:', | |
default: function () { | |
return _.dasherize(_.classify(widgetName)).replace(/^-/, ''); | |
}, | |
filter: function (value) { | |
return _.dasherize(_.classify(value)); | |
} | |
}, | |
{ | |
type: 'input', | |
name: 'widgetTitle', | |
message: 'Widget manifest title:', | |
default: 'Hello' | |
}, | |
{ | |
type: 'input', | |
name: 'widgetDescription', | |
message: 'Widget manifest descriotion:', | |
default: 'Welcomes the current user.' | |
}, | |
{ | |
type: 'input', | |
name: 'widgetBundle', | |
message: 'Widget target bundle:', | |
default: function () { | |
return modulePrefix + '-all'; | |
} | |
} | |
]); | |
this.properties.modulePrefix = modulePrefix; | |
} | |
writing() { | |
// Widget Files | |
let name = this.properties.widgetDirectory; | |
let directory = `src/widgets/${name}`; | |
this.log(`Writing the widget to "${directory}"`); | |
this.fs.copy(this.templatePath('src/widgets/widget/widget.manifest.json'), this.destinationPath(`src/widgets/${name}/${name}.manifest.json`)); | |
this.fs.copy(this.templatePath('src/widgets/widget/widget.md'), this.destinationPath(`src/widgets/${name}/${name}.md`)); | |
this.fs.copy(this.templatePath('src/widgets/widget/widget.view.js'), this.destinationPath(`src/widgets/${name}/${name}.view.js`)); | |
this.fs.copy(this.templatePath('src/widgets/widget/impl/widget.css'), this.destinationPath(`src/widgets/${name}/impl/${name}.css`)); | |
this.fs.copy(this.templatePath('src/widgets/widget/impl/widget.hbs'), this.destinationPath(`src/widgets/${name}/impl/${name}.hbs`)); | |
this.fs.copy(this.templatePath('src/widgets/widget/impl/widget.model.factory.js'), this.destinationPath(`src/widgets/${name}/impl/${name}.model.factory.js`)); | |
this.fs.copy(this.templatePath('src/widgets/widget/impl/widget.model.js'), this.destinationPath(`src/widgets/${name}/impl/${name}.model.js`)); | |
this.fs.copy(this.templatePath('src/widgets/widget/impl/nls'), this.destinationPath(`src/widgets/${name}/impl/nls`)); | |
this.fs.copy(this.templatePath('src/widgets/widget/test/widget.mock.js'), this.destinationPath(`src/widgets/${name}/test/${name}.mock.js`)); | |
this.fs.copy(this.templatePath('src/widgets/widget/test/widget.spec.js'), this.destinationPath(`src/widgets/${name}/test/${name}.spec.js`)); | |
this.fs.copy(this.templatePath('src/widgets/widget/test/index.html'), this.destinationPath(`src/widgets/${name}/test/index.html`)); | |
this.log('Widget Files Copied...') | |
this.log(this.properties) | |
// extensionsJson | |
const prefix = this.properties.modulePrefix; | |
const widgetName = this.properties.widgetDirectory; | |
const extensionJson = this.destinationPath(`src/${prefix}-extensions.json`); | |
const content = this.fs.read(extensionJson); | |
const extensions = JSON.parse(content); | |
let extension = extensions['csui/models/widget/widget.collection']; | |
if (!extension) { | |
extension = extensions['csui/models/widget/widget.collection'] = {}; | |
} | |
let widgets = extension.widgets; | |
if (!widgets) { | |
widgets = extension.widgets = {}; | |
} | |
let moduleWidgets = widgets[prefix]; | |
if (!moduleWidgets) { | |
moduleWidgets = widgets[prefix] = [] | |
} | |
const widgetPath = prefix + '/widgets/' + widgetName | |
let widget = moduleWidgets.some(function (name) { | |
return widgetPath === name; | |
}); | |
if (!widget) { | |
moduleWidgets.push(widgetPath); | |
moduleWidgets = moduleWidgets.sort(); | |
} | |
const extensionsOutput = JSON.stringify(extensions, undefined, 2); | |
this.fs.write(extensionJson, extensionsOutput); | |
// bundleIndex | |
const viewPath = `${widgetPath}/${widgetName}.view`; | |
const manifestPath = `json!${widgetPath}/${widgetName}.manifest.json`; | |
const fileName = this.destinationPath(`src/bundles/${this.properties.widgetBundle}.js`); | |
const bundeIndexContent = this.fs.read(fileName); | |
var code = esprima.parse(bundeIndexContent, { | |
tokens: true, | |
range: true, | |
comment: true | |
}); | |
code = escodegen.attachComments(code, code.comments, code.tokens); | |
traverseCode(code, function (node) { | |
if (node && node.type === 'CallExpression') { | |
var callee = node.callee; | |
if (callee && callee.type === 'Identifier' && callee.name === 'define') { | |
var parameters = node.arguments; | |
if (parameters && Array.isArray(parameters) && parameters.length > 0) { | |
var parameter = parameters[0]; | |
if (parameter && parameter.type === 'ArrayExpression') { | |
var elements = parameter.elements; | |
if (!elements) { | |
elements = parameters.elements = []; | |
} | |
if (!elements.some(function (child) { | |
return child && child.type === 'Literal' && child.value === viewPath; | |
})) { | |
elements.push({ | |
type: 'Literal', | |
value: viewPath, | |
raw: viewPath | |
}); | |
} | |
if (!elements.some(function (child) { | |
return child && child.type === 'Literal' && child.value === manifestPath; | |
})) { | |
elements.push({ | |
type: 'Literal', | |
value: manifestPath, | |
raw: manifestPath | |
}); | |
} | |
} | |
} | |
} | |
} | |
}); | |
const output = escodegen.generate(code, { | |
comment: true, | |
format: { | |
indent: { style: ' ' }, | |
preserveBlankLines: true | |
}, | |
sourceCode: bundeIndexContent | |
}); | |
this.fs.write(fileName, output); | |
} | |
install() { | |
if (!this.options['skip-install']) { | |
return; | |
} | |
this.installDependencies({ | |
bower: false, | |
npm: true | |
}) | |
} | |
} | |
function traverseCode(object, visitor) { | |
if (!object) { | |
return; | |
} | |
if (visitor.call(null, object) === false) { | |
return false; | |
} | |
for (var i = 0, keys = Object.keys(object), count = keys.length; i < count; ++i) { | |
var child = object[keys[i]]; | |
if (typeof child === 'object' && child !== null) { | |
if (traverseCode(child, visitor) === false) { | |
return false; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment