Post\+CSS can transform styles in any syntax, and is not limited to just CSS. By writing a custom syntax, you can transform styles in any desired format.

Writing a custom syntax is much harder than writing a Post\+CSS plugin, but it is an awesome adventure.

There are 3 types of Post\+CSS syntax packages\+:


\begin{DoxyItemize}
\item {\bfseries{Parser}} to parse input string to node’s tree.
\item {\bfseries{Stringifier}} to generate output string by node’s tree.
\item {\bfseries{Syntax}} contains both parser and stringifier.
\end{DoxyItemize}\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24680}{}\doxysection{Syntax}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24680}
A good example of a custom syntax is \href{https://github.com/postcss/postcss-scss}{\texttt{ SCSS}}. Some users may want to transform SCSS sources with Post\+CSS plugins, for example if they need to add vendor prefixes or change the property order. So this syntax should output SCSS from an SCSS input.

The syntax API is a very simple plain object, with {\ttfamily parse} \& {\ttfamily stringify} functions\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{module.exports = \{}
\DoxyCodeLine{  parse:     require('./parse'),}
\DoxyCodeLine{  stringify: require('./stringify')}
\DoxyCodeLine{\} }

\end{DoxyCode}
\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24681}{}\doxysection{Parser}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24681}
A good example of a parser is \href{https://github.com/postcss/postcss-safe-parser}{\texttt{ Safe Parser}}, which parses malformed/broken CSS. Because there is no point to generate broken output, this package only provides a parser.

The parser API is a function which receives a string \& returns a \href{http://api.postcss.org/Root.html}{\texttt{ {\ttfamily Root}}} node. The second argument is a function which receives an object with Post\+CSS options.


\begin{DoxyCode}{0}
\DoxyCodeLine{const postcss = require('postcss')}
\DoxyCodeLine{}
\DoxyCodeLine{module.exports = function parse (css, opts) \{}
\DoxyCodeLine{  const root = postcss.root()}
\DoxyCodeLine{  // Add other nodes to root}
\DoxyCodeLine{  return root}
\DoxyCodeLine{\} }

\end{DoxyCode}
\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24682}{}\doxysubsection{Main Theory}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24682}
There are many books about parsers; but do not worry because CSS syntax is very easy, and so the parser will be much simpler than a programming language parser.

The default Post\+CSS parser contains two steps\+:


\begin{DoxyEnumerate}
\item \href{https://github.com/postcss/postcss/blob/master/lib/tokenize.es6}{\texttt{ Tokenizer}} which reads input string character by character and builds a tokens array. For example, it joins space symbols to a `\mbox{[}\textquotesingle{}space', \textquotesingle{}~\newline
 \textquotesingle{}\mbox{]}{\ttfamily  token, and detects strings to a}\mbox{[}\textquotesingle{}string\textquotesingle{}, \textquotesingle{}\char`\"{}\textbackslash{}\char`\"{}\{\char`\"{}\textquotesingle{}\mbox{]}\`{} token. 2. $<$a href=\char`\"{}\href{https://github.com/postcss/postcss/blob/master/lib/parser.es6}{\texttt{ https\+://github.\+com/postcss/postcss/blob/master/lib/parser.\+es6}}"{}$>$Parser which reads the tokens array, creates node instances and builds a tree.
\end{DoxyEnumerate}\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24683}{}\doxysubsection{Performance}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24683}
Parsing input is often the most time consuming task in CSS processors. So it is very important to have a fast parser.

The main rule of optimization is that there is no performance without a benchmark. You can look at \href{https://github.com/postcss/benchmark}{\texttt{ Post\+CSS benchmarks}} to build your own.

Of parsing tasks, the tokenize step will often take the most time, so its performance should be prioritized. Unfortunately, classes, functions and high level structures can slow down your tokenizer. Be ready to write dirty code with repeated statements. This is why it is difficult to extend the default \href{https://github.com/postcss/postcss/blob/master/lib/tokenize.es6}{\texttt{ Post\+CSS tokenizer}}; copy \& paste will be a necessary evil.

Second optimization is using character codes instead of strings.


\begin{DoxyCode}{0}
\DoxyCodeLine{// Slow}
\DoxyCodeLine{string[i] === '\{'}
\DoxyCodeLine{}
\DoxyCodeLine{// Fast}
\DoxyCodeLine{const OPEN\_CURLY = 123 // `\{'}
\DoxyCodeLine{string.charCodeAt(i) === OPEN\_CURLY }

\end{DoxyCode}


Third optimization is “fast jumps”. If you find open quotes, you can find next closing quote much faster by {\ttfamily index\+Of}\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{// Simple jump}
\DoxyCodeLine{next = string.indexOf('"{}', currentPosition + 1)}
\DoxyCodeLine{}
\DoxyCodeLine{// Jump by RegExp}
\DoxyCodeLine{regexp.lastIndex = currentPosion + 1}
\DoxyCodeLine{regexp.test(string)}
\DoxyCodeLine{next = regexp.lastIndex }

\end{DoxyCode}


The parser can be a well written class. There is no need in copy-\/paste and hardcore optimization there. You can extend the default \href{https://github.com/postcss/postcss/blob/master/lib/parser.es6}{\texttt{ Post\+CSS parser}}.\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24684}{}\doxysubsection{Node Source}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24684}
Every node should have {\ttfamily source} property to generate correct source map. This property contains {\ttfamily start} and {\ttfamily end} properties with {\ttfamily \{ line, column \}}, and {\ttfamily input} property with an \href{https://github.com/postcss/postcss/blob/master/lib/input.es6}{\texttt{ {\ttfamily Input}}} instance.

Your tokenizer should save the original position so that you can propagate the values to the parser, to ensure that the source map is correctly updated.\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24685}{}\doxysubsection{Raw Values}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24685}
A good Post\+CSS parser should provide all information (including spaces symbols) to generate byte-\/to-\/byte equal output. It is not so difficult, but respectful for user input and allow integration smoke tests.

A parser should save all additional symbols to {\ttfamily node.\+raws} object. It is an open structure for you, you can add additional keys. For example, \href{https://github.com/postcss/postcss-scss}{\texttt{ SCSS parser}} saves comment types ({\ttfamily /$\ast$ $\ast$/} or {\ttfamily //}) in {\ttfamily node.\+raws.\+inline}.

The default parser cleans CSS values from comments and spaces. It saves the original value with comments to {\ttfamily node.\+raws.\+value.\+raw} and uses it, if the node value was not changed.\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24686}{}\doxysubsection{Tests}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24686}
Of course, all parsers in the Post\+CSS ecosystem must have tests.

If your parser just extends CSS syntax (like \href{https://github.com/postcss/postcss-scss}{\texttt{ SCSS}} or \href{https://github.com/postcss/postcss-safe-parser}{\texttt{ Safe Parser}}), you can use the \href{https://github.com/postcss/postcss-parser-tests}{\texttt{ Post\+CSS Parser Tests}}. It contains unit \& integration tests.\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24687}{}\doxysection{Stringifier}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24687}
A style guide generator is a good example of a stringifier. It generates output HTML which contains CSS components. For this use case, a parser isn\textquotesingle{}t necessary, so the package should just contain a stringifier.

The Stringifier API is little bit more complicated, than the parser API. Post\+CSS generates a source map, so a stringifier can’t just return a string. It must link every substring with its source node.

A Stringifier is a function which receives \href{http://api.postcss.org/Root.html}{\texttt{ {\ttfamily Root}}} node and builder callback. Then it calls builder with every node’s string and node instance.


\begin{DoxyCode}{0}
\DoxyCodeLine{module.exports = function stringify (root, builder) \{}
\DoxyCodeLine{  // Some magic}
\DoxyCodeLine{  const string = decl.prop + ':' + decl.value + ';'}
\DoxyCodeLine{  builder(string, decl)}
\DoxyCodeLine{  // Some science}
\DoxyCodeLine{\}; }

\end{DoxyCode}
\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24688}{}\doxysubsection{Main Theory}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24688}
Post\+CSS \href{https://github.com/postcss/postcss/blob/master/lib/stringifier.es6}{\texttt{ default stringifier}} is just a class with a method for each node type and many methods to detect raw properties.

In most cases it will be enough just to extend this class, like in \href{https://github.com/postcss/postcss-scss/blob/master/lib/scss-stringifier.es6}{\texttt{ SCSS stringifier}}.\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24689}{}\doxysubsection{Builder Function}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24689}
A builder function will be passed to {\ttfamily stringify} function as second argument. For example, the default Post\+CSS stringifier class saves it to {\ttfamily this.\+builder} property.

Builder receives output substring and source node to append this substring to the final output.

Some nodes contain other nodes in the middle. For example, a rule has a {\ttfamily \{} at the beginning, many declarations inside and a closing {\ttfamily \}}.

For these cases, you should pass a third argument to builder function\+: `\textquotesingle{}start'{\ttfamily or}\textquotesingle{}end\textquotesingle{}\`{} string\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{this.builder(rule.selector + '\{', rule, 'start')}
\DoxyCodeLine{// Stringify declarations inside}
\DoxyCodeLine{this.builder('\}', rule, 'end') }

\end{DoxyCode}
\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24690}{}\doxysubsection{Raw Values}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24690}
A good Post\+CSS custom syntax saves all symbols and provide byte-\/to-\/byte equal output if there were no changes.

This is why every node has {\ttfamily node.\+raws} object to store space symbol, etc.

Be careful, because sometimes these raw properties will not be present; some nodes may be built manually, or may lose their indentation when they are moved to another parent node.

This is why the default stringifier has a {\ttfamily raw()} method to autodetect raw properties by other nodes. For example, it will look at other nodes to detect indent size and them multiply it with the current node depth.\hypertarget{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24691}{}\doxysubsection{Tests}\label{md_sfcode_node_modules_resolve_url_loader_node_modules_postcss_docs_syntax_autotoc_md24691}
A stringifier must have tests too.

You can use unit and integration test cases from \href{https://github.com/postcss/postcss-parser-tests}{\texttt{ Post\+CSS Parser Tests}}. Just compare input CSS with CSS after your parser and stringifier. 