A Post\+CSS plugin is a function that receives and, usually, transforms a CSS AST from the Post\+CSS parser.

The rules below are {\itshape mandatory} for all Post\+CSS plugins.

See also \href{http://blog.clojurewerkz.org/blog/2013/04/20/how-to-make-your-open-source-project-really-awesome/}{\texttt{ Clojure\+Werkz’s recommendations}} for open source projects.\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24644}{}\doxysection{1. API}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24644}
\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24645}{}\doxysubsection{1.\+1 Clear name with $<$tt$>$postcss-\/$<$/tt$>$ prefix}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24645}
The plugin’s purpose should be clear just by reading its name. If you wrote a transpiler for CSS 4 Custom Media, {\ttfamily postcss-\/custom-\/media} would be a good name. If you wrote a plugin to support mixins, {\ttfamily postcss-\/mixins} would be a good name.

The prefix {\ttfamily postcss-\/} shows that the plugin is part of the Post\+CSS ecosystem.

This rule is not mandatory for plugins that can run as independent tools, without the user necessarily knowing that it is powered by Post\+CSS — for example, \href{https://rtlcss.com/}{\texttt{ RTLCSS}} and \href{https://github.com/postcss/autoprefixer}{\texttt{ Autoprefixer}}.\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24646}{}\doxysubsection{1.\+2. Do one thing, and do it well}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24646}
Do not create multitool plugins. Several small, one-\/purpose plugins bundled into a plugin pack is usually a better solution.

For example, \href{https://preset-env.cssdb.org/}{\texttt{ {\ttfamily postcss-\/preset-\/env}}} contains many small plugins, one for each W3C specification. And \href{https://github.com/ben-eb/cssnano}{\texttt{ {\ttfamily cssnano}}} contains a separate plugin for each of its optimization.\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24647}{}\doxysubsection{1.\+3. Do not use mixins}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24647}
Preprocessors libraries like Compass provide an API with mixins.

Post\+CSS plugins are different. A plugin cannot be just a set of mixins for \href{https://github.com/postcss/postcss-mixins}{\texttt{ {\ttfamily postcss-\/mixins}}}.

To achieve your goal, consider transforming valid CSS or using custom at-\/rules and custom properties.\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24648}{}\doxysubsection{1.\+4. Create plugin by $<$tt$>$postcss.\+plugin$<$/tt$>$}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24648}
By wrapping your function in this method, you are hooking into a common plugin API\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{module.exports = postcss.plugin('plugin-\/name', opts => \{}
\DoxyCodeLine{  return (root, result) => \{}
\DoxyCodeLine{    // Plugin code}
\DoxyCodeLine{  \}}
\DoxyCodeLine{\}) }

\end{DoxyCode}
\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24649}{}\doxysection{2. Processing}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24649}
\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24650}{}\doxysubsection{2.\+1. Plugin must be tested}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24650}
A CI service like \href{https://travis-ci.org/}{\texttt{ Travis}} is also recommended for testing code in different environments. You should test in (at least) Node.\+js \href{https://github.com/nodejs/LTS}{\texttt{ active LTS}} and current stable version.\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24651}{}\doxysubsection{2.\+2. Use asynchronous methods whenever possible}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24651}
For example, use {\ttfamily fs.\+write\+File} instead of {\ttfamily fs.\+write\+File\+Sync}\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{postcss.plugin('plugin-\/sprite', opts => \{}
\DoxyCodeLine{  return (root, result) => \{}
\DoxyCodeLine{}
\DoxyCodeLine{    return new Promise((resolve, reject) => \{}
\DoxyCodeLine{      const sprite = makeSprite()}
\DoxyCodeLine{      fs.writeFile(opts.file, sprite, err => \{}
\DoxyCodeLine{        if (err) return reject(err)}
\DoxyCodeLine{        resolve()}
\DoxyCodeLine{      \})}
\DoxyCodeLine{    \})}
\DoxyCodeLine{}
\DoxyCodeLine{  \}}
\DoxyCodeLine{\}) }

\end{DoxyCode}
\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24652}{}\doxysubsection{2.\+3. Set $<$tt$>$node.\+source$<$/tt$>$ for new nodes}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24652}
Every node must have a relevant {\ttfamily source} so Post\+CSS 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 {\ttfamily source}.


\begin{DoxyCode}{0}
\DoxyCodeLine{if (needPrefix(decl.prop)) \{}
\DoxyCodeLine{  decl.cloneBefore(\{ prop: '-\/webkit-\/' + decl.prop \})}
\DoxyCodeLine{\} }

\end{DoxyCode}


You can also set {\ttfamily source} directly, copying from some existing node\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{if (decl.prop === 'animation') \{}
\DoxyCodeLine{  const keyframe = createAnimationByName(decl.value)}
\DoxyCodeLine{  keyframes.source = decl.source}
\DoxyCodeLine{  decl.root().append(keyframes)}
\DoxyCodeLine{\} }

\end{DoxyCode}
\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24653}{}\doxysubsection{2.\+4. Use only the public Post\+CSS API}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24653}
Post\+CSS 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 \href{http://api.postcss.org/}{\texttt{ API docs}}.\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24654}{}\doxysection{3. Errors}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24654}
\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24655}{}\doxysubsection{3.\+1. Use $<$tt$>$node.\+error$<$/tt$>$ on CSS relevant errors}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24655}
If you have an error because of input CSS (like an unknown name in a mixin plugin) you should use {\ttfamily node.\+error} to create an error that includes source position\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{if (typeof mixins[name] === 'undefined') \{}
\DoxyCodeLine{  throw decl.error('Unknown mixin ' + name, \{ plugin: 'postcss-\/mixins' \})}
\DoxyCodeLine{\} }

\end{DoxyCode}
\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24656}{}\doxysubsection{3.\+2. Use $<$tt$>$result.\+warn$<$/tt$>$ for warnings}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24656}
Do not print warnings with {\ttfamily console.\+log} or {\ttfamily console.\+warn}, because some Post\+CSS runner may not allow console output.


\begin{DoxyCode}{0}
\DoxyCodeLine{if (outdated(decl.prop)) \{}
\DoxyCodeLine{  result.warn(decl.prop + ' is outdated', \{ node: decl \})}
\DoxyCodeLine{\} }

\end{DoxyCode}


If CSS input is a source of the warning, the plugin must set the {\ttfamily node} option.\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24657}{}\doxysection{4. Documentation}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24657}
\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24658}{}\doxysubsection{4.\+1. Document your plugin in English}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24658}
Post\+CSS plugins must have their {\ttfamily 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.~{\ttfamily README.\+ja.\+md}).\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24659}{}\doxysubsection{4.\+2. Include input and output examples}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24659}
The plugin\textquotesingle{}s {\ttfamily 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 {\ttfamily README.\+md} is a good place to put examples. See \href{https://github.com/iamvdo/postcss-opacity}{\texttt{ postcss-\/opacity}} for an example.

Of course, this guideline does not apply if your plugin does not transform the CSS.\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24660}{}\doxysubsection{4.\+3. Maintain a changelog}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24660}
Post\+CSS plugins must describe the changes of all their releases in a separate file, such as {\ttfamily CHANGELOG.\+md}, {\ttfamily History.\+md}, or~\href{https://help.github.com/articles/creating-releases/}{\texttt{ Git\+Hub Releases}}. Visit \href{http://keepachangelog.com/}{\texttt{ Keep A Changelog}} for more information about how to write one of these.

Of course, you should be using \href{http://semver.org/}{\texttt{ Sem\+Ver}}.\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24661}{}\doxysubsection{4.\+4. Include $<$tt$>$postcss-\/plugin$<$/tt$>$ keyword in $<$tt$>$package.\+json$<$/tt$>$}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_guidelines_plugin_autotoc_md24661}
Post\+CSS plugins written for npm must have the {\ttfamily postcss-\/plugin} keyword in their {\ttfamily package.\+json}. This special keyword will~be useful for feedback about the Post\+CSS ecosystem.

For packages not published to npm, this is not mandatory, but is recommended if the package format can contain keywords. 