Skip to content

Commit 2c14e3f

Browse files
author
JelteMX
committed
Generator can now be used on existing widgets
1 parent 29cab7e commit 2c14e3f

File tree

3 files changed

+168
-86
lines changed

3 files changed

+168
-86
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ npm install -g yo generator-mendix grunt-cli
1818

1919
### Usage
2020

21-
##### 1.) Start the generator:
21+
##### 1.) Start the generator in the folder you want to create a widget:
2222

2323
```bash
2424
yo mendix

generators/app/index.js

Lines changed: 166 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
/*jshint -W108*/
1+
/*jshint -W108,-W069*/
22
'use strict';
33

44
var pkg = require(__dirname + '/../../package.json');
55
var semver = require('semver');
6-
var fs = require('extfs');
6+
var fs = require('fs');
7+
var extfs = require('extfs');
8+
var xml2js = require("xml2js");
9+
var parser = new xml2js.Parser();
710
var yeoman = require('yeoman-generator');
811
var chalk = require('chalk');
912

1013
var boilerPlatePath = '/AppStoreWidgetBoilerplate/';
11-
1214
var banner = [
1315
'',
1416
chalk.bold.cyan(' __ ____ __') + ' _ _ _ ',
@@ -27,10 +29,41 @@ var banner = [
2729
module.exports = yeoman.generators.Base.extend({
2830
constructor: function () {
2931
yeoman.generators.Base.apply(this, arguments);
30-
if (!fs.isEmptySync(this.destinationRoot())) {
31-
this.log(banner);
32-
this.log(chalk.red('Error: Current folder does not seem to be empty, the generator needs to be run in an empty folder. Please create an empty folder first.\n'));
33-
process.exit(0);
32+
var done = this.async();
33+
this.isNew = true;
34+
35+
this.folders = extfs.getDirsSync(this.destinationRoot());
36+
this.current = {};
37+
this.current.version = '1.0.0';
38+
this.current.name = 'CurrentWidget';
39+
40+
if (this.folders.indexOf('src') !== -1) {
41+
var srcFolderContent = extfs.getDirsSync(this.destinationPath('src'));
42+
if (srcFolderContent.length === 1) {
43+
this.current.name = srcFolderContent[0];
44+
}
45+
if (!extfs.isEmptySync(this.destinationPath('src/package.xml'))) {
46+
var pkgXml = fs.readFileSync(this.destinationPath('src/package.xml')).toString();
47+
parser.parseString(pkgXml, function (err, result) {
48+
this.isNew = false;
49+
if (err) {
50+
this.log('Error: ' + err);
51+
process.exit(0);
52+
}
53+
if (result.package.clientModule[0]["$"]["version"]) {
54+
this.current.version = result.package.clientModule[0]["$"]["version"];
55+
}
56+
done();
57+
}.bind(this));
58+
} else {
59+
this.isNew = false;
60+
done();
61+
}
62+
} else if (!extfs.isEmptySync(this.destinationRoot())) {
63+
this.isNew = false;
64+
done();
65+
} else {
66+
done();
3467
}
3568
},
3669
prompting: function () {
@@ -39,7 +72,7 @@ module.exports = yeoman.generators.Base.extend({
3972
// Have Yeoman greet the user.
4073
this.log(banner);
4174

42-
var prompts = [
75+
var promptsNew = [
4376
{
4477
type: 'input',
4578
name: 'widgetName',
@@ -92,12 +125,58 @@ module.exports = yeoman.generators.Base.extend({
92125
}
93126
];
94127

95-
this.prompt(prompts, function (props) {
96-
this.props = props;
97-
// To access props later use this.props.someOption;
128+
var promptsUpgrade = [
129+
{
130+
type: 'confirm',
131+
name: 'upgrade',
132+
message: 'Are you upgrading a custom widget? (Need \'src\' folder to work)',
133+
default: false
134+
},{
135+
type: 'input',
136+
name: 'widgetName',
137+
validate: function (input) {
138+
if (/^([a-zA-Z]*)$/.test(input)) { return true; }
139+
return 'Your widget can only contain letters (a-z & A-Z). Please provide a valid name';
140+
},
141+
message: 'What is name of your widget? (Please make it the same as your current MPK file, e.g. "CustomWidget.mpk", name is "CustomWidget")',
142+
default: this.current.name,
143+
when: function (props) {
144+
return props.upgrade;
145+
}
146+
},{
147+
type: 'input',
148+
name: 'version',
149+
validate: function (input) {
150+
if (semver.valid(input) && semver.satisfies(input, '>=1.0.0')) {
151+
return true;
152+
}
153+
return 'Your version needs to be formatted as x.x.x and starts at 1.0.0. Using 1.0.0';
154+
},
155+
message: 'Enter your current version (package.xml) or the default version',
156+
default: this.current.version,
157+
when: function (props) {
158+
return props.upgrade;
159+
}
160+
}
161+
];
98162

99-
done();
100-
}.bind(this));
163+
if (this.isNew) {
164+
this.prompt(promptsNew, function (props) {
165+
this.props = props;
166+
// To access props later use this.props.someOption;
167+
done();
168+
}.bind(this));
169+
} else {
170+
this.log(chalk.bold.red(' The directory is not empty. If you are creating a new widget, please open the generator in an empty folder (Press Ctrl+C to abort)\n\n'));
171+
this.prompt(promptsUpgrade, function (props) {
172+
this.props = props;
173+
if (!props.upgrade) {
174+
process.exit(0);
175+
} else {
176+
done();
177+
}
178+
}.bind(this));
179+
}
101180

102181
},
103182

@@ -119,83 +198,85 @@ module.exports = yeoman.generators.Base.extend({
119198
// Using grunt (future version will include Gulp)
120199
this.widget.builder = 'grunt';
121200

122-
// Copy generic files
123-
this.fs.copy(this.templatePath(boilerPlatePath + '.jshintrc'), this.destinationPath('.jshintrc'));
124-
this.fs.copy(this.templatePath('_gitignore'), this.destinationPath('.gitignore'));
125-
this.fs.copy(this.templatePath('icon.png'), this.destinationPath('icon.png'));
126-
this.fs.copy(this.templatePath(boilerPlatePath + 'assets/app_store_banner.png'), this.destinationPath('assets/app_store_banner.png'));
127-
this.fs.copy(this.templatePath(boilerPlatePath + 'assets/app_store_icon.png'), this.destinationPath('assets/app_store_icon.png'));
128-
this.fs.copy(this.templatePath(boilerPlatePath + 'LICENSE'), this.destinationPath('LICENSE'));
129-
this.fs.copy(this.templatePath(boilerPlatePath + 'README.md'), this.destinationPath('README.md'));
130-
this.fs.copy(this.templatePath(boilerPlatePath + 'test/Test.mpr'), this.destinationPath('test/Test.mpr'));
131-
this.fs.copy(this.templatePath(boilerPlatePath + 'xsd/widget.xsd'), this.destinationPath('xsd/widget.xsd'));
132-
133-
// Copy files based on WidgetName
134-
this.fs.copy(
135-
this.templatePath(boilerPlatePath + 'src/WidgetName/lib/jquery-1.11.2.js'),
136-
this.destinationPath('src/' + this.widget.widgetName + '/lib/jquery-1.11.2.js')
137-
);
201+
if (this.isNew) {
202+
// Copy generic files
203+
this.fs.copy(this.templatePath(boilerPlatePath + '.jshintrc'), this.destinationPath('.jshintrc'));
204+
this.fs.copy(this.templatePath('_gitignore'), this.destinationPath('.gitignore'));
205+
this.fs.copy(this.templatePath('icon.png'), this.destinationPath('icon.png'));
206+
this.fs.copy(this.templatePath(boilerPlatePath + 'assets/app_store_banner.png'), this.destinationPath('assets/app_store_banner.png'));
207+
this.fs.copy(this.templatePath(boilerPlatePath + 'assets/app_store_icon.png'), this.destinationPath('assets/app_store_icon.png'));
208+
this.fs.copy(this.templatePath(boilerPlatePath + 'LICENSE'), this.destinationPath('LICENSE'));
209+
this.fs.copy(this.templatePath(boilerPlatePath + 'README.md'), this.destinationPath('README.md'));
210+
this.fs.copy(this.templatePath(boilerPlatePath + 'test/Test.mpr'), this.destinationPath('test/Test.mpr'));
211+
this.fs.copy(this.templatePath(boilerPlatePath + 'xsd/widget.xsd'), this.destinationPath('xsd/widget.xsd'));
138212

139-
this.fs.copy(
140-
this.templatePath(boilerPlatePath + 'src/WidgetName/widget/template/WidgetName.html'),
141-
this.destinationPath('src/' + this.widget.widgetName + '/widget/template/' + this.widget.widgetName + '.html')
142-
);
213+
// Copy files based on WidgetName
214+
this.fs.copy(
215+
this.templatePath(boilerPlatePath + 'src/WidgetName/lib/jquery-1.11.2.js'),
216+
this.destinationPath('src/' + this.widget.widgetName + '/lib/jquery-1.11.2.js')
217+
);
143218

144-
this.fs.copy(
145-
this.templatePath(boilerPlatePath + 'src/WidgetName/widget/ui/WidgetName.css'),
146-
this.destinationPath('src/' + this.widget.widgetName + '/widget/ui/' + this.widget.widgetName + '.css')
147-
);
219+
this.fs.copy(
220+
this.templatePath(boilerPlatePath + 'src/WidgetName/widget/template/WidgetName.html'),
221+
this.destinationPath('src/' + this.widget.widgetName + '/widget/template/' + this.widget.widgetName + '.html')
222+
);
148223

149-
// Rename references in widget main JS
150-
this.fs.copy(
151-
this.templatePath(boilerPlatePath + 'src/WidgetName/widget/WidgetName.js'),
152-
this.destinationPath('src/' + this.widget.widgetName + '/widget/' + this.widget.widgetName + '.js'),
153-
{
154-
process: function (file) {
155-
var fileText = file.toString();
156-
fileText = fileText
157-
.replace(/WidgetName\.widget\.WidgetName/g, this.widget.packageName + '.widget.' + this.widget.widgetName)
158-
.replace(/WidgetName\/widget\/WidgetName/g, this.widget.packageName + '/widget/' + this.widget.widgetName)
159-
.replace(/WidgetName/g, this.widget.widgetName)
160-
.replace(/\{\{version\}\}/g, this.widget.version)
161-
.replace(/\{\{date\}\}/g, this.widget.date)
162-
.replace(/\{\{copyright\}\}/g, this.widget.copyright)
163-
.replace(/\{\{license\}\}/g, this.widget.license)
164-
.replace(/\{\{author\}\}/g, this.widget.author);
165-
return fileText;
166-
}.bind(this)
167-
}
168-
);
224+
this.fs.copy(
225+
this.templatePath(boilerPlatePath + 'src/WidgetName/widget/ui/WidgetName.css'),
226+
this.destinationPath('src/' + this.widget.widgetName + '/widget/ui/' + this.widget.widgetName + '.css')
227+
);
169228

170-
// Rename references package.xml
171-
this.fs.copy(
172-
this.templatePath(boilerPlatePath + 'src/package.xml'),
173-
this.destinationPath('src/package.xml'),
174-
{
175-
process: function (file) {
176-
var fileText = file.toString();
177-
fileText = fileText
178-
.replace(/WidgetName/g, this.widget.widgetName)
179-
.replace(/\{\{version\}\}/g, this.widget.version);
180-
return fileText;
181-
}.bind(this)
182-
}
183-
);
229+
// Rename references in widget main JS
230+
this.fs.copy(
231+
this.templatePath(boilerPlatePath + 'src/WidgetName/widget/WidgetName.js'),
232+
this.destinationPath('src/' + this.widget.widgetName + '/widget/' + this.widget.widgetName + '.js'),
233+
{
234+
process: function (file) {
235+
var fileText = file.toString();
236+
fileText = fileText
237+
.replace(/WidgetName\.widget\.WidgetName/g, this.widget.packageName + '.widget.' + this.widget.widgetName)
238+
.replace(/WidgetName\/widget\/WidgetName/g, this.widget.packageName + '/widget/' + this.widget.widgetName)
239+
.replace(/WidgetName/g, this.widget.widgetName)
240+
.replace(/\{\{version\}\}/g, this.widget.version)
241+
.replace(/\{\{date\}\}/g, this.widget.date)
242+
.replace(/\{\{copyright\}\}/g, this.widget.copyright)
243+
.replace(/\{\{license\}\}/g, this.widget.license)
244+
.replace(/\{\{author\}\}/g, this.widget.author);
245+
return fileText;
246+
}.bind(this)
247+
}
248+
);
184249

185-
// Rename references WidgetName
186-
this.fs.copy(
187-
this.templatePath(boilerPlatePath + 'src/WidgetName/WidgetName.xml'),
188-
this.destinationPath('src/' + this.widget.widgetName + '/' + this.widget.widgetName + '.xml'),
189-
{
190-
process: function (file) {
191-
var fileText = file.toString();
192-
fileText = fileText
193-
.replace(/WidgetName\.widget\.WidgetName/g, this.widget.packageName + '.widget.' + this.widget.widgetName)
194-
.replace(/WidgetName/g, this.widget.widgetName);
195-
return fileText;
196-
}.bind(this)
197-
}
198-
);
250+
// Rename references package.xml
251+
this.fs.copy(
252+
this.templatePath(boilerPlatePath + 'src/package.xml'),
253+
this.destinationPath('src/package.xml'),
254+
{
255+
process: function (file) {
256+
var fileText = file.toString();
257+
fileText = fileText
258+
.replace(/WidgetName/g, this.widget.widgetName)
259+
.replace(/\{\{version\}\}/g, this.widget.version);
260+
return fileText;
261+
}.bind(this)
262+
}
263+
);
264+
265+
// Rename references WidgetName
266+
this.fs.copy(
267+
this.templatePath(boilerPlatePath + 'src/WidgetName/WidgetName.xml'),
268+
this.destinationPath('src/' + this.widget.widgetName + '/' + this.widget.widgetName + '.xml'),
269+
{
270+
process: function (file) {
271+
var fileText = file.toString();
272+
fileText = fileText
273+
.replace(/WidgetName\.widget\.WidgetName/g, this.widget.packageName + '.widget.' + this.widget.widgetName)
274+
.replace(/WidgetName/g, this.widget.widgetName);
275+
return fileText;
276+
}.bind(this)
277+
}
278+
);
279+
}
199280

200281
// Package.JSON
201282
this.template('_package.json', 'package.json', this.widget, {});

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"chalk": "^1.0.0",
3434
"extfs": "0.0.7",
3535
"semver": "^5.1.0",
36+
"xml2js": "^0.4.15",
3637
"yeoman-generator": "^0.19.0"
3738
},
3839
"devDependencies": {

0 commit comments

Comments
 (0)