create-postcss-plugin
Advanced tools
Comparing version 1.0.0 to 2.0.0
161
index.js
#!/usr/bin/env node | ||
// tooling | ||
const args = require('./lib/args'); | ||
const child = require('./lib/child_process'); | ||
const fs = require('./lib/fs'); | ||
const gitinfo = require('./lib/gitinfo'); | ||
const path = require('path'); | ||
const question = require('./lib/question'); | ||
const copydir = require('./lib/copy-dir'); | ||
const exec = require('./lib/exec'); | ||
// caching | ||
const answers = {}; | ||
// capturing | ||
const keys = /\$\{([^\}]+)\}/g; | ||
// directory names | ||
const tpl = 'template'; | ||
// directory paths | ||
const __tpl = path.join(__dirname, tpl); | ||
const __out = process.cwd(); | ||
// capture answers | ||
(questions => Object.keys(questions).reduce( | ||
(resolver, key) => resolver.then( | ||
() => questions[key]() | ||
).then( | ||
answer => answers[key] = answer | ||
), | ||
Promise.resolve() | ||
).then( | ||
() => answers | ||
))({ | ||
// --date, or formatted date | ||
date: () => args('date').catch( | ||
() => new Date(Date.now()).toLocaleDateString('en-US', { | ||
weekday: 'narrow', | ||
year: 'numeric', | ||
month: 'long', | ||
day: 'numeric' | ||
}).slice(3) | ||
), | ||
// --title, prompt, or Example | ||
title: () => args('title').catch( | ||
() => question('Plugin Name') | ||
).catch( | ||
() => 'Example' | ||
).then( | ||
title => title | ||
.trim() | ||
.replace(/^(postcss\s+)?/i, 'PostCSS ') | ||
), | ||
// --id, or formatted title | ||
id: () => args('id').catch( | ||
() => answers.title | ||
).then( | ||
answer => answer | ||
.trim() | ||
.replace(/[^\w]+/g, '-') | ||
.replace(/^-+|-+$/g, '') | ||
.toLowerCase() | ||
), | ||
// --id-camel, or formatted title | ||
idCamelCase: () => args('id-camel').catch( | ||
() => answers.title | ||
).then( | ||
answer => `postcss${ | ||
answer | ||
.trim() | ||
.replace(/^postcss\s+/i, '') | ||
.replace(/[^\w\s]+/g, '-') | ||
.replace(/(^|\s+)-+/g, '$1') | ||
.replace(/-+(\s+|$)/g, '$1') | ||
.replace(/\s+./g, match => match.trim().toUpperCase()) | ||
.replace(/^[A-z]/, match => match.toUpperCase()) | ||
}` | ||
), | ||
// --author, gitinfo name, prompt, or PostCSS Community | ||
author: () => args('author').catch( | ||
() => gitinfo('name') | ||
).catch( | ||
() => question('GitHub author') | ||
).catch( | ||
() => 'PostCSS Community' | ||
), | ||
// --email, gitinfo email, prompt, or postcss@postcss.org | ||
email: () => args('email').catch( | ||
() => gitinfo('email') | ||
).catch( | ||
() => question('GitHub email') | ||
).catch( | ||
() => 'postcss@postcss.org' | ||
), | ||
// --email, gitinfo user, prompt, or postcss | ||
user: () => args('user').catch( | ||
() => gitinfo('user') | ||
).catch( | ||
() => question('GitHub user') | ||
).catch( | ||
() => 'postcss' | ||
), | ||
// --keywords, or prompt, and then formatted | ||
keywords: () => args('keywords').catch( | ||
() => question('Keywords') | ||
).catch( | ||
() => '' | ||
).then( | ||
keywords => ['postcss', 'css', 'postcss-plugin'].concat( | ||
keywords | ||
.trim() | ||
.split(/\s*,\s*/) | ||
).join('",\n "') | ||
) | ||
}).then( | ||
// read template files, update their contents with answers, and write them to the destination | ||
answers => Promise.all([ | ||
copydir(__tpl, __out, answers) | ||
]).then( | ||
() => Promise.all([ | ||
fs.rmdir(path.resolve(__out, '.git')).catch(() => {}).then( | ||
() => child( | ||
'git init', | ||
{ | ||
cwd: __out | ||
} | ||
) | ||
).then( | ||
() => child( | ||
`git remote add origin git@github.com:${answers.user}/${answers.id}.git`, | ||
{ | ||
cwd: __out | ||
} | ||
) | ||
).then( | ||
() => exec( | ||
'npm install', | ||
{ | ||
cwd: __out | ||
} | ||
) | ||
), | ||
fs.rmdir(path.resolve(__out, 'lib')).catch(() => {}), | ||
fs.rmdir(path.resolve(__tpl)).catch(() => {}), | ||
fs.touchFile(path.resolve(__out, 'test/basic.css')), | ||
fs.touchFile(path.resolve(__out, 'test/basic.expect.css')) | ||
]) | ||
) | ||
).then( | ||
() => process.exit(0), | ||
error => console.warn(error) && process.exit(1) | ||
); | ||
function _interopDefault(e){return e&&"object"==typeof e&&"default"in e?e.default:e}var path=_interopDefault(require("path")),fs=_interopDefault(require("fs")),child_process=require("child_process"),https=_interopDefault(require("https")),os=_interopDefault(require("os")),readline=_interopDefault(require("readline"));function asyncGeneratorStep(e,t,r,s,a,i,n){try{var o=e[i](n),c=o.value}catch(e){return void r(e)}o.done?t(c):Promise.resolve(c).then(s,a)}function _asyncToGenerator(e){return function(){var t=this,r=arguments;return new Promise(function(s,a){var i=e.apply(t,r);function n(e){asyncGeneratorStep(i,s,a,n,o,"next",e)}function o(e){asyncGeneratorStep(i,s,a,n,o,"throw",e)}n(void 0)})}}const dash=/^--([^\s]+)$/;var args=process.argv.slice(2).reduce((e,t,r,s)=>(dash.test(t)?e[t.replace(dash,"$1")]=!(r+1 in s)||s[r+1]:dash.test(s[r-1])||e.to||(e.to=t),e),{});const colors={reset:"[0m",bold:"[1m",dim:"[2m",underline:"[4m",blink:"[5m",reverse:"[7m",hidden:"[8m",black:"[30m",red:"[31m",green:"[32m",yellow:"[33m",blue:"[34m",magenta:"[35m",cyan:"[36m",white:"[37m",bgBlack:"[40m",bgRed:"[41m",bgGreen:"[42m",bgYellow:"[43m",bgBlue:"[44m",bgMagenta:"[45m",bgCyan:"[46m",bgWhite:"[47m"},reset=colors.reset;var color=Object.keys(colors).reduce((e,t)=>{const r=colors[t];return e[t]=(e=>r+e.replace(reset,reset+r)+reset),e},{});const fse={};function copyTemplateDir(e,t,r){return fse.readdir(e).then(s=>Promise.all(s.map(s=>fse.lstat(path.resolve(e,s)).then(a=>a.isFile()?fse.readFile(path.join(e,s),"utf8").then(e=>e.replace(keys,(e,t)=>t in r?r[t]:e).replace(patchPkg,"")).then(e=>fse.writeFile(path.join(t,s),e)):fse.mkdir(path.resolve(t,s)).then(()=>copyTemplateDir(path.resolve(e,s),path.resolve(t,s),r))))))}["access","appendFile","chmod","chown","close","exists","fchmod","fchown","fdatasync","fstat","fsync","ftruncate","futimes","lchmod","lchown","link","lstat","mkdtemp","open","read","readdir","readFile","readlink","realpath","rename","rmdir","stat","symlink","truncate","unlink","utimes","write","write"].forEach(e=>(fse[e]=((t,...r)=>new Promise((s,a)=>fs[e](t,...r,(e,...t)=>{e?a(e):s(...t)}))),fse)),["mkdir","writeFile"].forEach(e=>{fse[e]=((t,...r)=>new Promise((s,a)=>{fs[e](t,...r,i=>{i&&"ENOENT"===i.code?fse.mkdir(path.dirname(t)).then(()=>fse[e](t,...r)).then(s):i&&"EEXIST"!==i.code?a(i):s()})}))}),["mkdirSync","writeFileSync"].forEach(e=>{fse[e]=((e,...t)=>{try{fs[key](e,...t)}catch(r){if(r&&"ENOENT"===r.code)fse.mkdirSync(path.dirname(e)),fse[key](e,...t);else if(r&&"EEXIST"!==r.code)throw r}})}),fse.copydir=((e,t)=>fse.mkdir(t).then(()=>fse.readdir(e)).then(r=>Promise.all(r.map(r=>{const s=path.resolve(e,r),a=path.resolve(t,r);return fse.lstat(s).then(e=>e.isDirectory()?fse.copydir(s,a):fse.copyFile(s,a))})).then(()=>Promise.resolve()))),fse.copydirSync=((e,t)=>{fse.mkdirSync(t),fse.readdirSync(e).forEach(r=>{const s=path.resolve(e,r),a=path.resolve(t,r);fse.lstatSync(s).isDirectory()?fse.copydirSync(s,a):fse.copyFileSync(s,a)})}),fse.copyFile=((e,t)=>fse.touchFile(t).then(()=>new Promise((r,s)=>{const a=fse.createReadStream(path.resolve(e)),i=fse.createWriteStream(path.resolve(t));function n(e){a.destroy(),i.end(),s(e)}a.on("error",n),i.on("error",n),i.on("finish",r),a.pipe(i)}))),fse.copyFileSync=((e,t)=>{fse.mkdirSync(path.dirname(t));const r=Buffer.alloc(65536);let s=1,a=0;const i=fs.openSync(e,"r"),n=fs.openSync(t,"w");for(;s>0;)s=fs.readSync(i,r,0,65536,a),fs.writeSync(n,r,0,s),a+=s;fs.closeSync(i),fs.closeSync(n)}),fse.readJson=(e=>fse.readFile(e,"utf8").then(JSON.parse)),fse.readJsonSync=(e=>JSON.parse(fse.readFileSync(e,"utf8"))),fse.rmdir=(e=>new Promise((t,r)=>{fs.rmdir(e,s=>{s&&"ENOTEMPTY"===s.code?t(fse.readdir(e).then(t=>Promise.all(t.map(t=>{const r=path.resolve(e,t);return fse.lstat(r).then(e=>e.isDirectory()?fse.rmdir(r):fse.unlink(r))}))).then(()=>fse.rmdir(e))):s?r(s):t()})})),fse.rmdirSync=(e=>{try{fs.rmdirSync(e)}catch(t){if(!t||"ENOTEMPTY"!==t.code)throw t;fse.readdirSync(e).forEach(t=>{const r=path.resolve(e,t);fse.lstatSync(r).isDirectory()?fse.rmdirSync(r):fse.unlinkSync(r)}),fse.rmdirSync(e)}}),fse.touchFile=(e=>new Promise((t,r)=>{fs.open(e,"wx",s=>{s&&"ENOENT"===s.code?fse.mkdir(path.dirname(e)).then(()=>fse.touchFile(e)).then(t):s&&"EEXIST"!==s.code?r(s):t()})})),fse.touchFileSync=(e=>{try{fs.openSync(e,"wx")}catch(t){if(t&&"ENOENT"===t.code)fse.mkdirSync(path.dirname(e)),fse.touchFileSync(e);else if(t&&"EEXIST"!==t.code)throw t}});const keys=/\$\{([^\}]+)\}/g,patchPkg=',\n ".*",\n "*"';function exec(e,t){return new Promise((r,s)=>{child_process.exec(e,Object(t),(e,t,a)=>{e?s(a):r(t)})})}function pipeExec(e,t){return new Promise((r,s)=>{try{const a=Object.assign({stdio:["pipe","pipe",process.stderr]},t);r(child_process.execSync(e,a))}catch(e){s(e)}})}var githubUser=e=>new Promise((t,r)=>{https.get({hostname:"api.github.com",path:`/search/users?q=${e}+in:email`,headers:{Accept:"application/vnd.github.v3+json","user-agent":"https://github.com/sindresorhus/gh-got"}},e=>{let s="";200!==e.statusCode&&r(e.statusCode),e.on("data",e=>s+=e),e.on("end",()=>{const e=JSON.parse(s);e.items&&e.items.length?t(e.items[0].login):r("No User Found")})})});const iniLine=/\s*\n+\s*/,iniHeading=/^\[\s*(.*)\s*\]$/,iniValue=/^\s*([^\s]*)\s*=\s*(.*)\s*$/,iniObject={};let iniCurrent=iniObject;var gitConfig=fse.readFile(path.resolve(os.homedir(),".gitconfig"),"utf8").then(e=>e.split(iniLine).map(e=>{iniHeading.test(e)?iniCurrent=iniObject[e.replace(iniHeading,"$1")]={}:iniCurrent[e.replace(iniValue,"$1")]=e.replace(iniValue,"$2")})).then(()=>{if("user"in iniObject)return iniObject.user;throw"No user object in .gitconfig"});let gituser;var gitInfo=e=>gitConfig.then(function(){var t=_asyncToGenerator(function*(t){if(e in t)return t[e];if("user"===e)return gituser=yield gituser||githubUser(t.email);throw`No ${e} in .gitconfig`});return function(e){return t.apply(this,arguments)}}()),question=e=>new Promise((t,r)=>{const s=readline.createInterface({input:process.stdin,output:process.stdout});s.question(color.dim(`${e}: `),e=>{s.close(),e?t(e):r()})});function main(){return _main.apply(this,arguments)}function _main(){return(_main=_asyncToGenerator(function*(){yield updateArgs(),yield createTemplate()})).apply(this,arguments)}function updateArgs(){return _updateArgs.apply(this,arguments)}function _updateArgs(){return(_updateArgs=_asyncToGenerator(function*(){if(args.to||(args.to="./"),args.date||(args.date=new Date(Date.now()).toLocaleDateString("en-US",{weekday:"narrow",year:"numeric",month:"long",day:"numeric"}).slice(3)),!args.title)try{args.title=yield question(titlePrompt)}catch(e){args.title=titleFallback}if(args.title=formatTitle(args.title),args.id=formatId(args.id||args.title),args.idCamelCase=formatCamelCase(args["camel-case-id"]||args.id),args.desc||(args.desc=formatDesc(args.description||descFallback)),args.pkgdesc=formatPkgDesc(args["package-description"]||args.desc),!args.author)try{args.author=yield gitInfo("name")}catch(e){try{args.author=yield question(authorPrompt)}catch(e){args.author=authorFallback}}if(!args.email)try{args.email=yield gitInfo("email")}catch(e){try{args.email=yield question(emailPrompt)}catch(e){args.email=emailFallback}}if(!args.user)try{args.user=yield gitInfo("user")}catch(e){try{args.user=yield question(userPrompt)}catch(e){args.user=userFallback}}if(!args.keywords)try{args.keywords=yield question(keywordPrompt)}catch(e){args.keywords=keywordFallback}args.keywords=formatKeywords(args.keywords),console.log("")})).apply(this,arguments)}function createTemplate(){return _createTemplate.apply(this,arguments)}function _createTemplate(){return(_createTemplate=_asyncToGenerator(function*(){const e=path.join(__dirname,"template"),t=path.resolve(process.cwd(),args.to),r={cwd:t};try{yield copyTemplateDir(e,t,args);try{yield exec("git init",r),yield exec(`git remote add origin git@github.com:${args.user}/${args.id}.git`,r)}catch(e){}args["no-install"]||(yield pipeExec("npm install",r)),console.log(getSuccessMessage(args)),process.exit(0)}catch(e){console.error(e),process.exit(1)}})).apply(this,arguments)}function getSuccessMessage(){return`Success! Created ${color.bold(args.title)} at ${color.bold(args.to)}\n\nWe suggest that you begin by typing:\n cd ${path.relative(process.cwd(),args.to)}\n npm test\n\nHappy PostCSS-ing!\n`}const authorFallback="PostCSS Community",authorPrompt="Author Name",descFallback="...",emailFallback="postcss@postcss.org",emailPrompt="GitHub Email",keywordFallback="",keywordPrompt="Keywords",titleFallback="Example",titlePrompt="Plugin Name",userFallback="postcss",userPrompt="GitHub User",formatTitle=e=>e.trim().replace(/^(postcss\s+)?/i,"PostCSS "),formatDesc=e=>e.trim(),formatPkgDesc=e=>e.replace(/^[a-z]/,e=>e.toUpperCase()),formatId=e=>e.trim().replace(/[^\w]+/g,"-").replace(/^-+|-+$/g,"").toLowerCase(),formatCamelCase=e=>e.replace(/-[a-z]/g,e=>e.slice(1).toUpperCase()),formatKeywords=e=>["postcss","css","postcss-plugin"].concat(e.trim().split(/\s*,\s*/)).join('",\n "');main(); |
{ | ||
"name": "create-postcss-plugin", | ||
"version": "1.0.0", | ||
"bin": { | ||
"create-postcss-plugin": "./index.js" | ||
}, | ||
"version": "2.0.0", | ||
"description": "Quickly create new PostCSS plugins", | ||
@@ -13,10 +10,41 @@ "author": "Jonathan Neal <jonathantneal@hotmail.com>", | ||
"bugs": "https://github.com/csstools/create-postcss-plugin/issues", | ||
"engines": { | ||
"node": ">=6.5.0" | ||
"main": "index.js", | ||
"bin": { | ||
"create-postcss-plugin": "./index.js" | ||
}, | ||
"files": [ | ||
"index.js", | ||
"lib/**/*", | ||
"template/**/*" | ||
"template" | ||
], | ||
"scripts": { | ||
"lint": "eslint src/**.js --cache --ignore-path .gitignore --quiet", | ||
"build": "rollup --config --silent", | ||
"prepublishOnly": "npm test && npm run build", | ||
"test": "npm run lint" | ||
}, | ||
"engines": { | ||
"node": ">=6.0.0" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.2.2", | ||
"@babel/plugin-syntax-dynamic-import": "^7.2.0", | ||
"@babel/preset-env": "^7.3.1", | ||
"babel-eslint": "^10.0.1", | ||
"eslint": "^5.12.1", | ||
"eslint-config-dev": "^2.0.0", | ||
"postcss-tape": "^4.0.0", | ||
"pre-commit": "^1.2.2", | ||
"rollup": "^1.1.2", | ||
"rollup-plugin-babel": "^4.3.2", | ||
"rollup-plugin-terser": "^4.0.3" | ||
}, | ||
"eslintConfig": { | ||
"extends": "dev", | ||
"parser": "babel-eslint", | ||
"rules": { | ||
"complexity": [ | ||
0 | ||
] | ||
} | ||
}, | ||
"keywords": [ | ||
@@ -23,0 +51,0 @@ "postcss", |
@@ -7,9 +7,103 @@ # create-postcss-plugin [<img src="https://postcss.github.io/postcss/logo.svg" alt="PostCSS" width="90" height="90" align="right">][PostCSS] | ||
```sh | ||
npm init postcss-plugin | ||
npm init postcss-plugin YOUR_DESTINATION | ||
``` | ||
```sh | ||
npx create-postcss-plugin YOUR_DESTINATION | ||
``` | ||
After completing the instructions, write your plugin to `src/index.js` and | ||
update `README.md` to replace `...` with the gist of your plugin. | ||
update `README.md` with further details outlining your plugin functionality. | ||
## Options | ||
You can pass options into postcss-plugin to automate plugin creation. | ||
### to | ||
The `to` argument defines the destination of the new project. The first | ||
undefined argument will also determine this value. | ||
```sh | ||
npm init postcss-plugin --to path/to/plugin | ||
``` | ||
### title | ||
The `title` argument defines the formal name of the project. | ||
```sh | ||
npm init postcss-plugin --title Super | ||
``` | ||
```sh | ||
npm init postcss-plugin --title "Awesome Blossom" | ||
``` | ||
### id | ||
The `id` argument defines the id used by the project package.json and | ||
repository. | ||
```sh | ||
npm init postcss-plugin --id awes-blos | ||
``` | ||
### desc | ||
The `desc` or `description` argument defines the description used by the | ||
project README.md and package.json. | ||
```sh | ||
# becomes "Use exciting new functions" and "Awesome Blossom lets you create new functions in CSS." | ||
npm init postcss-plugin --desc "use exciting new functions" | ||
``` | ||
```sh | ||
# becomes "Use exciting new functions" and "Awesome Blossom lets you create new functions in CSS." | ||
npm init postcss-plugin --description "use exciting new functions" | ||
``` | ||
### author | ||
The `author` argument defines the author used by the project package.json. | ||
```sh | ||
npm init postcss-plugin --author "Joe Bloggs" | ||
``` | ||
The `email` argument defines the email used by the project package.json. | ||
```sh | ||
npm init postcss-plugin --email "postcss@postcss.org" | ||
``` | ||
### user | ||
The `user` argument defines the repository user or group hosting the project. | ||
```sh | ||
npm init postcss-plugin --user "postcss" | ||
``` | ||
### keywords | ||
The `keywords` argument defines the keywords used by the project package.json. | ||
```sh | ||
npm init postcss-plugin --keywords "awesome,blossom" | ||
``` | ||
### no-install | ||
The `no-install` argument instructs the project to not automatically install | ||
dependencies. | ||
```sh | ||
npm init postcss-plugin --no-install | ||
``` | ||
[Create PostCSS Plugin]: https://github.com/csstools/create-postcss-plugin | ||
[PostCSS]: https://github.com/postcss/postcss |
{ | ||
"name": "${id}", | ||
"version": "1.0.0", | ||
"description": "Use ... in CSS", | ||
"description": "${pkgdesc} in CSS", | ||
"author": "${author} <${email}>", | ||
@@ -31,14 +31,14 @@ "license": "CC0-1.0", | ||
"dependencies": { | ||
"postcss": "^7.0.7" | ||
"postcss": "^7.0.14" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.2.2", | ||
"@babel/preset-env": "^7.2.3", | ||
"@babel/preset-env": "^7.3.1", | ||
"babel-eslint": "^10.0.1", | ||
"eslint": "^5.10.0", | ||
"eslint": "^5.12.1", | ||
"eslint-config-dev": "^2.0.0", | ||
"postcss-tape": "^4.0.0", | ||
"pre-commit": "^1.2.2", | ||
"rollup": "^0.68.1", | ||
"rollup-plugin-babel": "^4.1.0" | ||
"rollup": "^1.1.2", | ||
"rollup-plugin-babel": "^4.3.2" | ||
}, | ||
@@ -45,0 +45,0 @@ "eslintConfig": { |
@@ -7,3 +7,3 @@ # ${title} [<img src="https://postcss.github.io/postcss/logo.svg" alt="PostCSS" width="90" height="90" align="right">][postcss] | ||
[${title}] lets you use ... in CSS. | ||
[${title}] lets you ${desc} in CSS. | ||
@@ -10,0 +10,0 @@ ```pcss |
import postcss from 'postcss'; | ||
export default postcss.plugin('${id}', opts => { | ||
console.log('opts', opts); | ||
console.log({ opts }); | ||
return (root, result) => { | ||
console.log('root, result', root, result); | ||
console.log({ root, result }); | ||
}; | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
109
28771
11
17
63
1