mirror of
				https://github.com/fooflington/selfdefined.git
				synced 2025-10-31 14:18:32 +00:00 
			
		
		
		
	
		
			
	
	
		
			196 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			196 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
|   | # PostCSS Plugin Guidelines
 | |||
|  | 
 | |||
|  | A PostCSS plugin is a function that receives and, usually, | |||
|  | transforms a CSS AST from the PostCSS parser. | |||
|  | 
 | |||
|  | The rules below are *mandatory* for all PostCSS plugins. | |||
|  | 
 | |||
|  | See also [ClojureWerkz’s recommendations] for open source projects. | |||
|  | 
 | |||
|  | [ClojureWerkz’s recommendations]:  http://blog.clojurewerkz.org/blog/2013/04/20/how-to-make-your-open-source-project-really-awesome/ | |||
|  | 
 | |||
|  | ## 1. API
 | |||
|  | 
 | |||
|  | ### 1.1 Clear name with `postcss-` prefix
 | |||
|  | 
 | |||
|  | The plugin’s purpose should be clear just by reading its name. | |||
|  | If you wrote a transpiler for CSS 4 Custom Media, `postcss-custom-media` | |||
|  | would be a good name. If you wrote a plugin to support mixins, | |||
|  | `postcss-mixins` would be a good name. | |||
|  | 
 | |||
|  | The prefix `postcss-` shows that the plugin is part of the PostCSS ecosystem. | |||
|  | 
 | |||
|  | This rule is not mandatory for plugins that can run as independent tools, | |||
|  | without the user necessarily knowing that it is powered by | |||
|  | PostCSS — for example, [RTLCSS] and [Autoprefixer]. | |||
|  | 
 | |||
|  | [Autoprefixer]: https://github.com/postcss/autoprefixer | |||
|  | [RTLCSS]:       https://rtlcss.com/ | |||
|  | 
 | |||
|  | ### 1.2. Do one thing, and do it well
 | |||
|  | 
 | |||
|  | Do not create multitool plugins. Several small, one-purpose plugins bundled into | |||
|  | a plugin pack is usually a better solution. | |||
|  | 
 | |||
|  | For example, [`postcss-preset-env`] contains many small plugins, | |||
|  | one for each W3C specification. And [`cssnano`] contains a separate plugin | |||
|  | for each of its optimization. | |||
|  | 
 | |||
|  | [`postcss-preset-env`]: https://preset-env.cssdb.org/ | |||
|  | [`cssnano`]:            https://github.com/ben-eb/cssnano | |||
|  | 
 | |||
|  | ### 1.3. Do not use mixins
 | |||
|  | 
 | |||
|  | Preprocessors libraries like Compass provide an API with mixins. | |||
|  | 
 | |||
|  | PostCSS plugins are different. | |||
|  | A plugin cannot be just a set of mixins for [`postcss-mixins`]. | |||
|  | 
 | |||
|  | To achieve your goal, consider transforming valid CSS | |||
|  | or using custom at-rules and custom properties. | |||
|  | 
 | |||
|  | [`postcss-mixins`]: https://github.com/postcss/postcss-mixins | |||
|  | 
 | |||
|  | ### 1.4. Create plugin by `postcss.plugin`
 | |||
|  | 
 | |||
|  | By wrapping your function in this method, | |||
|  | you are hooking into a common plugin API: | |||
|  | 
 | |||
|  | ```js | |||
|  | module.exports = postcss.plugin('plugin-name', opts => { | |||
|  |   return (root, result) => { | |||
|  |     // Plugin code | |||
|  |   } | |||
|  | }) | |||
|  | ``` | |||
|  | 
 | |||
|  | ## 2. Processing
 | |||
|  | 
 | |||
|  | ### 2.1. Plugin must be tested
 | |||
|  | 
 | |||
|  | A CI service like [Travis] is also recommended for testing code in | |||
|  | different environments. You should test in (at least) Node.js [active LTS](https://github.com/nodejs/LTS) and current stable version. | |||
|  | 
 | |||
|  | [Travis]: https://travis-ci.org/ | |||
|  | 
 | |||
|  | ### 2.2. Use asynchronous methods whenever possible
 | |||
|  | 
 | |||
|  | For example, use `fs.writeFile` instead of `fs.writeFileSync`: | |||
|  | 
 | |||
|  | ```js | |||
|  | postcss.plugin('plugin-sprite', opts => { | |||
|  |   return (root, result) => { | |||
|  | 
 | |||
|  |     return new Promise((resolve, reject) => { | |||
|  |       const sprite = makeSprite() | |||
|  |       fs.writeFile(opts.file, sprite, err => { | |||
|  |         if (err) return reject(err) | |||
|  |         resolve() | |||
|  |       }) | |||
|  |     }) | |||
|  | 
 | |||
|  |   } | |||
|  | }) | |||
|  | ``` | |||
|  | 
 | |||
|  | ### 2.3. Set `node.source` for new nodes
 | |||
|  | 
 | |||
|  | Every node must have a relevant `source` so PostCSS can generate | |||
|  | an accurate source map. | |||
|  | 
 | |||
|  | So if you add a new declaration based on some existing declaration, you should | |||
|  | clone the existing declaration in order to save that original `source`. | |||
|  | 
 | |||
|  | ```js | |||
|  | if (needPrefix(decl.prop)) { | |||
|  |   decl.cloneBefore({ prop: '-webkit-' + decl.prop }) | |||
|  | } | |||
|  | ``` | |||
|  | 
 | |||
|  | You can also set `source` directly, copying from some existing node: | |||
|  | 
 | |||
|  | ```js | |||
|  | if (decl.prop === 'animation') { | |||
|  |   const keyframe = createAnimationByName(decl.value) | |||
|  |   keyframes.source = decl.source | |||
|  |   decl.root().append(keyframes) | |||
|  | } | |||
|  | ``` | |||
|  | 
 | |||
|  | ### 2.4. Use only the public PostCSS API
 | |||
|  | 
 | |||
|  | PostCSS plugins must not rely on undocumented properties or methods, | |||
|  | which may be subject to change in any minor release. The public API | |||
|  | is described in [API docs]. | |||
|  | 
 | |||
|  | [API docs]: http://api.postcss.org/ | |||
|  | 
 | |||
|  | ## 3. Errors
 | |||
|  | 
 | |||
|  | ### 3.1. Use `node.error` on CSS relevant errors
 | |||
|  | 
 | |||
|  | If you have an error because of input CSS (like an unknown name | |||
|  | in a mixin plugin) you should use `node.error` to create an error | |||
|  | that includes source position: | |||
|  | 
 | |||
|  | ```js | |||
|  | if (typeof mixins[name] === 'undefined') { | |||
|  |   throw decl.error('Unknown mixin ' + name, { plugin: 'postcss-mixins' }) | |||
|  | } | |||
|  | ``` | |||
|  | 
 | |||
|  | ### 3.2. Use `result.warn` for warnings
 | |||
|  | 
 | |||
|  | Do not print warnings with `console.log` or `console.warn`, | |||
|  | because some PostCSS runner may not allow console output. | |||
|  | 
 | |||
|  | ```js | |||
|  | if (outdated(decl.prop)) { | |||
|  |   result.warn(decl.prop + ' is outdated', { node: decl }) | |||
|  | } | |||
|  | ``` | |||
|  | 
 | |||
|  | If CSS input is a source of the warning, the plugin must set the `node` option. | |||
|  | 
 | |||
|  | ## 4. Documentation
 | |||
|  | 
 | |||
|  | ### 4.1. Document your plugin in English
 | |||
|  | 
 | |||
|  | PostCSS plugins must have their `README.md` wrote in English. Do not be afraid | |||
|  | of your English skills, as the open source community will fix your errors. | |||
|  | 
 | |||
|  | Of course, you are welcome to write documentation in other languages; | |||
|  | just name them appropriately (e.g. `README.ja.md`). | |||
|  | 
 | |||
|  | ### 4.2. Include input and output examples
 | |||
|  | 
 | |||
|  | The plugin's `README.md` must contain example input and output CSS. | |||
|  | A clear example is the best way to describe how your plugin works. | |||
|  | 
 | |||
|  | The first section of the `README.md` is a good place to put examples. | |||
|  | See [postcss-opacity](https://github.com/iamvdo/postcss-opacity) for an example. | |||
|  | 
 | |||
|  | Of course, this guideline does not apply if your plugin does not | |||
|  | transform the CSS. | |||
|  | 
 | |||
|  | ### 4.3. Maintain a changelog
 | |||
|  | 
 | |||
|  | PostCSS plugins must describe the changes of all their releases | |||
|  | in a separate file, such as `CHANGELOG.md`, `History.md`, or [GitHub Releases]. | |||
|  | Visit [Keep A Changelog] for more information about how to write one of these. | |||
|  | 
 | |||
|  | Of course, you should be using [SemVer]. | |||
|  | 
 | |||
|  | [Keep A Changelog]: http://keepachangelog.com/ | |||
|  | [GitHub Releases]:  https://help.github.com/articles/creating-releases/ | |||
|  | [SemVer]:           http://semver.org/ | |||
|  | 
 | |||
|  | ### 4.4. Include `postcss-plugin` keyword in `package.json`
 | |||
|  | 
 | |||
|  | PostCSS plugins written for npm must have the `postcss-plugin` keyword | |||
|  | in their `package.json`. This special keyword will be useful for feedback about | |||
|  | the PostCSS ecosystem. | |||
|  | 
 | |||
|  | For packages not published to npm, this is not mandatory, but is recommended | |||
|  | if the package format can contain keywords. |