1
1
mirror of https://github.com/primer/css.git synced 2024-12-15 07:23:54 +03:00
css/modules/generator-primer-module/app/index.js
2017-09-06 12:50:12 -07:00

232 lines
5.5 KiB
JavaScript

const chalk = require("chalk")
const fse = require("fs-extra")
const path = require("path")
const Generator = require("yeoman-generator")
const capitalize = require("./lib/capitalize")
const stripPrimerPrefix = str => str.replace(/^primer-/, "")
module.exports = class PrimerModule extends Generator {
constructor(args, opts) {
super(args, opts)
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",
})
}
initializing() {
this.log("It looks like you are adding a new Primer module!")
}
prompting() {
if (this.options.module) {
this.log("Great, let's get you started with %s...", this.options.module)
}
const prompts = [
{
name: "module",
message: "What should the module name be (on npm)?",
type: "input",
required: true,
},
{
name: "title",
message: "What should the title be (for humans)?",
type: "input",
default: ({module}) => {
return capitalize(
stripPrimerPrefix(module || this.options.module)
)
},
},
{
name: "description",
message: [
"Describe your module in a single sentence.",
chalk.yellow("(This will go into the package.json and README.md.)"),
].join("\n"),
type: "input",
default: "TODO: fill in this description later",
},
{
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",
],
},
{
name: "dependents",
message: "Which meta-package(s) should we add this to?",
when: ({category}) => category !== "meta",
type: "checkbox",
choices: [
"primer-css",
"primer-core",
"primer-product",
"primer-marketing",
],
default: ["primer-css"],
},
{
type: "input",
message: [
"Where can we find the docs?",
chalk.yellow("(We'll read this file from the path you provide.)"),
].join("\n"),
name: "docs",
validate: (filePath) => {
if (!filePath) {
return true
}
return fse.exists(filePath)
.then(exists => {
return exits ||
`No such file: "${filePath}" in ${process.cwd()}`
})
},
},
]
// remove prompts for which arguments were already provided
return this.prompt(prompts.filter(prompt => {
return !(prompt.name in this.options)
}))
.then(answers => {
Object.assign(this.options, answers)
})
}
configuring() {
this.options.dependencies = this._getDependencies()
if (this.options.docs) {
return fse.readFile(this.options.docs, "utf8")
.then(docs => this.options.docs = docs)
}
}
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
)
// 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)
}
install() {
const pkg = this.fs.readJSON(
path.join(this.basePath, "package.json")
)
// this.log("package:", pkg.name, "@", pkg.version)
if (this.options.test !== true) {
this.options.dependents.forEach(dependent => {
this._addAsDependencyTo(pkg, dependent)
})
}
}
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:")
)
if (this.options.test !== true) {
this.spawnCommandSync("ack", ["TODO", this.basePath], {
stdio: "inherit",
})
}
}
_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,
},
})
}
}