Skip to content

Commit 9ab2aeb

Browse files
Merge pull request #1 from dreamsicle-io/develop
release/0.0.1
2 parents d1c2398 + f1c93cd commit 9ab2aeb

File tree

4 files changed

+1617
-39
lines changed

4 files changed

+1617
-39
lines changed

.gitignore

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
# Dependencies
2-
/node_modules
1+
# dependencies
2+
/node_modules
3+
4+
# tmp
5+
/tmp

index.js

Lines changed: 279 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,309 @@
1-
#!/usr/bin/env node
1+
#!/usr/bin/env node --harmony
22
'use-strict';
33

4+
const path = require('path');
5+
const fs = require('fs');
46
const program = require('commander');
7+
const co = require('co');
8+
const prompt = require('co-prompt');
9+
const nodegit = require('nodegit');
10+
const del = require('del');
11+
const ncp = require('ncp').ncp;
12+
const fetch = require('node-fetch');
13+
const pkg = require('./package.json');
514

615
const defaultArgs = {
7-
themename: 'WP Theme',
8-
themeuri: 'https://github.com/dreamsicle-io/create-wp-theme',
9-
themeversion: '0.0.1',
10-
themedescription: 'This theme was generated using "create-wp-theme".',
11-
author: 'Dreamsicle',
12-
authoruri: 'https://www.dreamsicle.io',
13-
license: 'GPL-3.0',
14-
textdomain: 'wp-theme',
15-
tags: 'accessibility-ready, translation-ready',
16+
themeName: 'WP Theme',
17+
themeTextDomain: 'wp-theme',
18+
themeVersion: '0.0.1',
19+
themeTemplate: '',
20+
themeURI: 'https://github.com/dreamsicle-io/create-wp-theme',
21+
themeBugsURI: 'https://github.com/dreamsicle-io/create-wp-theme/issues',
22+
themeRepoURI: 'https://github.com/dreamsicle-io/create-wp-theme.git',
23+
themeRepoType: 'git',
24+
themeDescription: 'This theme was generated using create-wp-theme.',
25+
themeAuthor: 'Dreamsicle',
26+
themeAuthorEmail: 'hello@dreamsicle.io',
27+
themeAuthorURI: 'https://www.dreamsicle.io',
28+
themeLicense: 'GPL-3.0',
29+
themeTags: 'accessibility-ready, translation-ready',
30+
wpVersionRequired: '4.9.8',
31+
wpVersionTested: '4.9.8',
32+
};
33+
34+
const argTypes = {
35+
themeName: 'name',
36+
themeTextDomain: 'textdomain',
37+
themeVersion: 'version',
38+
themeTemplate: 'theme',
39+
themeURI: 'uri',
40+
themeBugsURI: 'uri',
41+
themeRepoURI: 'uri',
42+
themeRepoType: 'type',
43+
themeDescription: 'description',
44+
themeAuthor: 'name',
45+
themeAuthorEmail: 'email',
46+
themeAuthorURI: 'uri',
47+
themeLicense: 'spdx',
48+
themeTags: 'tags',
49+
wpVersionRequired: 'version',
50+
wpVersionTested: 'version',
51+
};
52+
53+
const argTitles = {
54+
themeName: 'Theme Name',
55+
themeTextDomain: 'Text Domain',
56+
themeVersion: 'Version',
57+
themeTemplate: 'Template',
58+
themeURI: 'Theme URI',
59+
themeBugsURI: 'Theme Bugs URI',
60+
themeRepoURI: 'Theme Repository URI',
61+
themeRepoType: 'Theme Repository Type',
62+
themeDescription: 'Description',
63+
themeAuthor: 'Author',
64+
themeAuthorEmail: 'Author Email',
65+
themeAuthorURI: 'Author URI',
66+
themeLicense: 'License',
67+
themeTags: 'Tags',
68+
wpVersionRequired: 'WP Version Required',
69+
wpVersionTested: 'WP Version Tested',
1670
};
1771

1872
const argDescriptions = {
19-
themename: 'The theme name.',
20-
themeuri: 'The theme URI.',
21-
themeversion: 'The theme version.',
22-
themedescription: 'The theme description',
23-
author: 'The theme author.',
24-
authoruri: 'The theme author URI.',
25-
license: 'The theme license as a valid SPDX expression.',
26-
textdomain: 'The theme text domain.',
27-
tags: 'A comma separated list of valid WordPress theme repository tags.',
73+
themeName: 'The theme name',
74+
themeTextDomain: 'The theme text domain',
75+
themeVersion: 'The theme version',
76+
themeTemplate: 'The parent theme if this is a child theme',
77+
themeURI: 'The theme URI',
78+
themeBugsURI: 'The theme bugs URI',
79+
themeRepoURI: 'The theme repository URI',
80+
themeRepoType: 'The theme repository type',
81+
themeDescription: 'The theme description',
82+
themeAuthor: 'The theme author',
83+
themeAuthorEmail: 'The theme author email',
84+
themeAuthorURI: 'The theme author URI',
85+
themeLicense: 'The theme license as a valid SPDX expression',
86+
themeTags: 'A CSV of WordPress theme tags',
87+
wpVersionRequired: 'The version of WordPress the theme requires',
88+
wpVersionTested: 'The version of WordPress the theme has been tested up to',
2889
};
2990

3091
const argAliases = {
31-
themename: 'tn',
32-
themeuri: 'tu',
33-
themeversion: 'tv',
34-
themedescription: 'td',
35-
author: 'a',
36-
authoruri: 'au',
37-
license: 'l',
38-
textdomain: 'td',
39-
tags: 't',
92+
themeName: 'N',
93+
themeTextDomain: 'D',
94+
themeVersion: 'X',
95+
themeTemplate: 'T',
96+
themeURI: 'U',
97+
themeBugsURI: 'B',
98+
themeRepoURI: 'R',
99+
themeRepoType: 'r',
100+
themeDescription: 'd',
101+
themeAuthor: 'A',
102+
themeAuthorEmail: 'E',
103+
themeAuthorURI: 'u',
104+
themeLicense: 'L',
105+
themeTags: 't',
106+
wpVersionRequired: 'W',
107+
wpVersionTested: 'w',
40108
};
41109

42110
const requiredArgs = [
43-
'themename',
44-
'textdomain',
111+
'themeName',
112+
'themeTextDomain',
45113
];
46114

115+
program.name(getCommandName());
116+
program.version(pkg.version);
47117
program.arguments('<file>');
48118

49119
for (var key in defaultArgs) {
50120
const defaultValue = defaultArgs[key];
51121
const alias = argAliases[key];
52122
const description = argDescriptions[key];
53123
const isRequired = (requiredArgs.indexOf(key) !== -1);
54-
program.option('-' + alias + ', --' + key + ' <' + key + '>', description);
124+
const argType = argTypes[key];
125+
const type = isRequired ? '<' + argType + '>' : '[' + argType + ']';
126+
program.option('-' + alias + ', --' + key + ' ' + type, description, defaultValue);
55127
}
56128

57129
program.parse(process.argv);
58130

59-
const args = defaultArgs;
60-
for (var key in defaultArgs) {
61-
if (program[key]) {
62-
args[key] = program[key];
131+
const repoPath = 'https://github.com/dreamsicle-io/wp-theme-assets.git';
132+
const tmpPath = path.join(__dirname, 'tmp');
133+
const tmpThemePath = path.join(tmpPath, 'package');
134+
const tmpThemePkgPath = path.join(tmpThemePath, 'package.json');
135+
const tmpThemePkgLockPath = path.join(tmpThemePath, 'package-lock.json');
136+
const tmpThemeLicPath = path.join(tmpThemePath, 'LICENSE');
137+
const themeDirName = program.args[0];
138+
const themePath = path.join(process.cwd(), themeDirName);
139+
const cloneOptions = {
140+
fetchOpts: {
141+
callbacks: {
142+
// This is a required callback for OS X machines. There is a known issue
143+
// with libgit2 being able to verify certificates from GitHub.
144+
certificateCheck: function() { return 1; }
145+
}
146+
}
147+
};
148+
149+
function pathExists(path = '') {
150+
var exists = true;
151+
try {
152+
fs.statSync(path);
153+
} catch(error) {
154+
exists = false;
155+
}
156+
return exists;
157+
}
158+
159+
function getCommandName() {
160+
var cmd = pkg.name;
161+
if (pkg.bin) {
162+
for (var key in pkg.bin) {
163+
cmd = key;
164+
break;
165+
}
63166
}
167+
return cmd;
64168
}
65169

66-
console.log(args);
170+
function putPackage(args = null) {
171+
ncp(tmpThemePath, themePath, function(error) {
172+
if (error) {
173+
console.error(error);
174+
process.exit();
175+
} else {
176+
console.info('Theme copied: ' + themePath);
177+
del([tmpPath], { force: true })
178+
.then(function(paths) {
179+
if (paths.length > 0) {
180+
console.info('Repo cleaned: ' + paths.join(', '));
181+
}
182+
console.info('\nTheme created: ' + args.themeName + ' in ' + themePath);
183+
process.exit();
184+
}).catch(function(error) {
185+
console.error(error);
186+
process.exit();
187+
});
188+
}
189+
});
190+
}
191+
192+
function writeLicense(args = null) {
193+
fetch('https://api.github.com/licenses/' + encodeURIComponent(args.themeLicense.toLowerCase()))
194+
.then(function(response) {
195+
if (response.status === 200) {
196+
return response.json();
197+
} else {
198+
throw new Error('License not found: ' + args.themeLicense);
199+
}
200+
}).then(function(data) {
201+
console.info('License fetched: ' + data.name);
202+
fs.writeFile(tmpThemeLicPath, data.body, function(error) {
203+
if (error) {
204+
console.error(error);
205+
process.exit();
206+
} else {
207+
console.info('License written: ' + tmpThemeLicPath);
208+
putPackage(args);
209+
}
210+
});
211+
}).catch(function(error) {
212+
console.info(error.message);
213+
putPackage(args);
214+
});
215+
}
216+
217+
function writePackage(args = null) {
218+
del([tmpThemePkgLockPath], { force: true })
219+
.then(function(paths) {
220+
if (paths.length > 0) {
221+
console.info('package-lock.json cleaned: ' + paths.join(', '));
222+
}
223+
fs.readFile(tmpThemePkgPath, function(error, data) {
224+
if (error) {
225+
console.error(error);
226+
process.exit();
227+
} else {
228+
themePkg = JSON.parse(data);
229+
themePkg.name = themeDirName;
230+
themePkg.version = args.themeVersion;
231+
themePkg.description = args.themeDescription;
232+
themePkg.keywords = args.themeTags ? args.themeTags.split(',').map(function(tag) { return tag.trim(); }) : [];
233+
themePkg.author = {
234+
name: args.themeAuthor,
235+
email: args.themeAuthorEmail,
236+
url: args.themeAuthorURI,
237+
};
238+
themePkg.license = args.themeLicense;
239+
themePkg.wordpress = {
240+
versionRequired: args.wpVersionRequired,
241+
versionTested: args.wpVersionTested,
242+
};
243+
themePkg.bugs = {
244+
url: args.themeBugsURI,
245+
};
246+
themePkg.homepage = args.themeURI;
247+
themePkg.repository = {
248+
type: args.themeRepoType,
249+
url: args.themeRepoURI,
250+
};
251+
fs.writeFile(tmpThemePkgPath, JSON.stringify(themePkg, null, '\t'), function(error) {
252+
if (error) {
253+
console.error(error);
254+
process.exit();
255+
} else {
256+
console.info('package.json written: ' + tmpThemePkgPath);
257+
writeLicense(args);
258+
}
259+
});
260+
}
261+
});
262+
}).catch(function(error) {
263+
console.error(error);
264+
process.exit();
265+
});
266+
}
267+
268+
function clonePackage(args = null) {
269+
del([tmpPath], { force: true })
270+
.then(function(paths) {
271+
if (paths.length > 0) {
272+
console.info('Repo cleaned: ' + paths.join(', '));
273+
}
274+
nodegit.Clone(repoPath, tmpPath, cloneOptions)
275+
.then(function(repo) {
276+
console.info('Repo cloned: ' + repoPath + ' --> ' + tmpPath);
277+
writePackage(args);
278+
}).catch(function(error) {
279+
console.error(error);
280+
process.exit();
281+
});
282+
})
283+
.catch(function(error) {
284+
console.error(error);
285+
process.exit();
286+
});
287+
}
288+
289+
co(function *() {
290+
if (pathExists(themePath)) {
291+
console.log('\nPath already exists: ' + themePath);
292+
process.exit();
293+
}
294+
console.info('\nThe following tool will help you configure your new theme.\nFor each setting, set a value and hit "Enter" to continue.\n');
295+
var values = defaultArgs;
296+
for (var key in defaultArgs) {
297+
const promptValue = yield prompt(argTitles[key] + ': (' + program[key] + ') ');
298+
if (promptValue || program[key]) {
299+
values[key] = promptValue || program[key];
300+
}
301+
}
302+
return values;
303+
}).then(function(args) {
304+
console.info('\nCreating theme: ' + args.themeName + ' in ' + themePath + '\n');
305+
clonePackage(args);
306+
}, function(error) {
307+
console.error(error);
308+
process.exit();
309+
});

0 commit comments

Comments
 (0)