2017-09-01 08:23:17 +03:00
|
|
|
const chalk = require("chalk")
|
2017-09-01 21:57:00 +03:00
|
|
|
const fse = require("fs-extra")
|
2017-09-01 08:23:17 +03:00
|
|
|
const path = require("path")
|
|
|
|
const Generator = require("yeoman-generator")
|
|
|
|
const capitalize = require("./lib/capitalize")
|
|
|
|
|
2017-09-01 21:57:00 +03:00
|
|
|
const stripPrimerPrefix = str => str.replace(/^primer-/, "")
|
2017-09-01 08:23:17 +03:00
|
|
|
|
|
|
|
module.exports = class PrimerModule extends Generator {
|
|
|
|
|
2017-09-06 22:42:22 +03:00
|
|
|
constructor(args, opts) {
|
|
|
|
super(args, opts)
|
2017-09-01 08:23:17 +03:00
|
|
|
|
|
|
|
this.argument("module", {
|
|
|
|
desc: "The name of your module (on npm)",
|
|
|
|
type: String,
|
|
|
|
required: false,
|
|
|
|
})
|
|
|
|
|
|
|
|
// assign defaults
|
|
|
|
Object.assign(this.options, {
|
|
|
|
type: "css",
|
|
|
|
status: "Experimental",
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-09-06 22:42:22 +03:00
|
|
|
initializing() {
|
|
|
|
this.log("It looks like you are adding a new Primer module!")
|
|
|
|
}
|
|
|
|
|
2017-09-01 08:23:17 +03:00
|
|
|
prompting() {
|
|
|
|
if (this.options.module) {
|
|
|
|
this.log("Great, let's get you started with %s...", this.options.module)
|
|
|
|
}
|
|
|
|
|
2017-09-06 22:50:12 +03:00
|
|
|
const prompts = [
|
2017-09-01 08:23:17 +03:00
|
|
|
{
|
|
|
|
name: "module",
|
|
|
|
message: "What should the module name be (on npm)?",
|
|
|
|
type: "input",
|
2017-09-06 22:50:12 +03:00
|
|
|
required: true,
|
2017-09-01 08:23:17 +03:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "title",
|
|
|
|
message: "What should the title be (for humans)?",
|
|
|
|
type: "input",
|
2017-09-06 22:50:12 +03:00
|
|
|
default: ({module}) => {
|
2017-09-01 08:23:17 +03:00
|
|
|
return capitalize(
|
2017-09-06 22:50:12 +03:00
|
|
|
stripPrimerPrefix(module || this.options.module)
|
2017-09-01 08:23:17 +03:00
|
|
|
)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "description",
|
2017-09-06 22:50:12 +03:00
|
|
|
message: [
|
|
|
|
"Describe your module in a single sentence.",
|
|
|
|
chalk.yellow("(This will go into the package.json and README.md.)"),
|
|
|
|
].join("\n"),
|
2017-09-01 08:23:17 +03:00
|
|
|
type: "input",
|
|
|
|
default: "TODO: fill in this description later",
|
|
|
|
},
|
2017-09-06 22:50:12 +03:00
|
|
|
{
|
|
|
|
name: "category",
|
|
|
|
message: "Which meta-package does this belong to?",
|
|
|
|
type: "list",
|
|
|
|
choices: [
|
|
|
|
"core",
|
|
|
|
"product",
|
|
|
|
"marketing",
|
|
|
|
{
|
|
|
|
value: "meta",
|
|
|
|
message: "meta (this is a new meta-package)",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: undefined,
|
|
|
|
message: "none (I'll figure this out later)",
|
|
|
|
}
|
|
|
|
],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "module_type",
|
|
|
|
message: "What type of module is this?",
|
|
|
|
type: "option",
|
|
|
|
choices: [
|
|
|
|
"utilities",
|
|
|
|
"objects",
|
|
|
|
"components",
|
|
|
|
"meta",
|
|
|
|
],
|
|
|
|
},
|
2017-09-01 08:23:17 +03:00
|
|
|
{
|
|
|
|
name: "dependents",
|
|
|
|
message: "Which meta-package(s) should we add this to?",
|
2017-09-06 22:50:12 +03:00
|
|
|
when: ({category}) => category !== "meta",
|
2017-09-01 08:23:17 +03:00
|
|
|
type: "checkbox",
|
|
|
|
choices: [
|
|
|
|
"primer-css",
|
|
|
|
"primer-core",
|
|
|
|
"primer-product",
|
|
|
|
"primer-marketing",
|
|
|
|
],
|
|
|
|
default: ["primer-css"],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: "input",
|
2017-09-06 22:50:12 +03:00
|
|
|
message: [
|
|
|
|
"Where can we find the docs?",
|
|
|
|
chalk.yellow("(We'll read this file from the path you provide.)"),
|
|
|
|
].join("\n"),
|
2017-09-01 08:23:17 +03:00
|
|
|
name: "docs",
|
|
|
|
validate: (filePath) => {
|
|
|
|
if (!filePath) {
|
|
|
|
return true
|
|
|
|
}
|
2017-09-01 21:57:00 +03:00
|
|
|
return fse.exists(filePath)
|
|
|
|
.then(exists => {
|
|
|
|
return exits ||
|
|
|
|
`No such file: "${filePath}" in ${process.cwd()}`
|
|
|
|
})
|
2017-09-01 08:23:17 +03:00
|
|
|
},
|
|
|
|
},
|
|
|
|
]
|
|
|
|
|
|
|
|
// remove prompts for which arguments were already provided
|
2017-09-06 22:50:12 +03:00
|
|
|
return this.prompt(prompts.filter(prompt => {
|
|
|
|
return !(prompt.name in this.options)
|
|
|
|
}))
|
2017-09-01 08:23:17 +03:00
|
|
|
.then(answers => {
|
|
|
|
Object.assign(this.options, answers)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
configuring() {
|
|
|
|
this.options.dependencies = this._getDependencies()
|
2017-09-01 21:57:00 +03:00
|
|
|
if (this.options.docs) {
|
|
|
|
return fse.readFile(this.options.docs, "utf8")
|
|
|
|
.then(docs => this.options.docs = docs)
|
|
|
|
}
|
2017-09-01 08:23:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
paths() {
|
|
|
|
this.basePath = this.destinationPath(this.options.module)
|
|
|
|
}
|
|
|
|
|
|
|
|
writing() {
|
|
|
|
this.log("creating: %s", chalk.green(this.basePath))
|
|
|
|
|
|
|
|
const data = [
|
|
|
|
"module",
|
|
|
|
"dependencies",
|
|
|
|
"description",
|
|
|
|
"docs",
|
|
|
|
"status",
|
|
|
|
"title",
|
|
|
|
"type",
|
|
|
|
].reduce((acc, key) => {
|
|
|
|
acc[key] = this.options[key]
|
|
|
|
return acc
|
|
|
|
}, {})
|
|
|
|
|
|
|
|
// this.log("data:", JSON.stringify(data, null, " "))
|
|
|
|
|
|
|
|
// copy the whole directory with each file treated as
|
|
|
|
// an EJS template
|
|
|
|
this.fs.copyTpl(
|
|
|
|
this.templatePath(),
|
|
|
|
this.basePath,
|
|
|
|
data
|
|
|
|
)
|
2017-09-01 21:57:00 +03:00
|
|
|
|
|
|
|
// rename lib/module.scss to lib/{name}.scss, where
|
|
|
|
// {name} is the module name without the "primer-" prefix
|
|
|
|
const name = stripPrimerPrefix(this.options.module)
|
|
|
|
const src = path.join(this.basePath, "lib/module.scss")
|
|
|
|
const dest = src.replace("module.scss", `${name}.scss`)
|
|
|
|
this.fs.move(src, dest)
|
2017-09-01 08:23:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
install() {
|
|
|
|
const pkg = this.fs.readJSON(
|
|
|
|
path.join(this.basePath, "package.json")
|
|
|
|
)
|
|
|
|
// this.log("package:", pkg.name, "@", pkg.version)
|
|
|
|
|
2017-09-01 21:58:19 +03:00
|
|
|
if (this.options.test !== true) {
|
|
|
|
this.options.dependents.forEach(dependent => {
|
|
|
|
this._addAsDependencyTo(pkg, dependent)
|
|
|
|
})
|
|
|
|
}
|
2017-09-01 08:23:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
end() {
|
|
|
|
this.log(
|
|
|
|
"\n%s\n\n%s",
|
|
|
|
chalk.green("Ready to roll!"),
|
|
|
|
chalk.yellow("Remember to fill in real stuff if you have any TODOs listed below:")
|
|
|
|
)
|
2017-09-01 21:58:19 +03:00
|
|
|
if (this.options.test !== true) {
|
|
|
|
this.spawnCommandSync("ack", ["TODO", this.basePath], {
|
|
|
|
stdio: "inherit",
|
|
|
|
})
|
|
|
|
}
|
2017-09-01 08:23:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
_getDependencies() {
|
|
|
|
return [
|
|
|
|
"primer-support",
|
|
|
|
].reduce((deps, module) => {
|
|
|
|
deps[module] = require(`${module}/package.json`)
|
|
|
|
return deps
|
|
|
|
}, {})
|
|
|
|
}
|
|
|
|
|
|
|
|
_addAsDependencyTo(pkg, dest) {
|
|
|
|
this.log(
|
|
|
|
"adding %s@%s as a dependency to %s...",
|
|
|
|
pkg.name, pkg.version, dest,
|
|
|
|
pkg
|
|
|
|
)
|
|
|
|
|
|
|
|
const destPath = require.resolve(
|
|
|
|
path.join(dest, "package.json")
|
|
|
|
)
|
|
|
|
|
|
|
|
this.fs.extendJSON(destPath, {
|
|
|
|
dependencies: {
|
|
|
|
[pkg.name]: pkg.version,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|