General overview of the Post\+CSS architecture. It can be useful for everyone who wishes to contribute to the core or develop a better understanding of the tool.

{\bfseries{Table of Contents}}


\begin{DoxyItemize}
\item \href{\#overview}{\texttt{ Overview}}
\item \href{\#workflow}{\texttt{ Workflow}}
\item \href{\#core-structures}{\texttt{ Core Structures}}
\begin{DoxyItemize}
\item \href{\#tokenizer--libtokenizees6-}{\texttt{ Tokenizer}}
\item \href{\#parser--libparsees6-libparseres6-}{\texttt{ Parser}}
\item \href{\#processor--libprocessores6-}{\texttt{ Processor}}
\item \href{\#stringifier--libstringifyes6-libstringifieres6-}{\texttt{ Stringifier}}
\end{DoxyItemize}
\item \href{\#api-reference}{\texttt{ API}}
\end{DoxyItemize}\hypertarget{md_sfcode_node_modules_postcss_docs_architecture_autotoc_md20681}{}\doxysubsection{Overview}\label{md_sfcode_node_modules_postcss_docs_architecture_autotoc_md20681}
\begin{quote}
This section describes ideas lying behind Post\+CSS \end{quote}
Before diving deeper into the development of Post\+CSS let\textquotesingle{}s briefly describe what is Post\+CSS and what is not.

{\bfseries{Post\+CSS}}


\begin{DoxyItemize}
\item {\itshape is {\bfseries{NOT}} a style preprocessor like {\ttfamily Sass} or {\ttfamily Less}.}

It does not define a custom syntax and semantics, it\textquotesingle{}s not actually a language. Post\+CSS works with CSS and can be easily integrated with the tools described above. That being said any valid CSS can be processed by Post\+CSS.
\item {\itshape is a tool for CSS syntax transformations}

It allows you to define custom CSS like syntax that could be understandable and transformed by plugins. That being said Post\+CSS is not strictly about CSS spec but about syntax definition manner of CSS. In such a way you can define custom syntax constructs like at-\/rule, that could be very helpful for tools build around Post\+CSS. Post\+CSS plays the role of a framework for building outstanding tools for CSS manipulations.
\item {\itshape is a big player in CSS ecosystem}

A Large amount of lovely tools like {\ttfamily Autoprefixer}, {\ttfamily Stylelint}, {\ttfamily CSSnano} were built on Post\+CSS ecosystem. There is a big chance that you already use it implicitly, just check your {\ttfamily node\+\_\+modules} \+:smiley\+:
\end{DoxyItemize}\hypertarget{md_sfcode_node_modules_postcss_docs_architecture_autotoc_md20682}{}\doxysubsection{Workflow}\label{md_sfcode_node_modules_postcss_docs_architecture_autotoc_md20682}
This is a high-\/level overview of the whole Post\+CSS workflow



As you can see from the diagram above, Post\+CSS architecture is pretty straightforward but some parts of it could be misunderstood.

You can see a part called {\itshape Parser}, this construct will be described in details later on, just for now think about it as a structure that can understand your CSS like syntax and create an object representation of it.

That being said, there are few ways to write a parser.


\begin{DoxyItemize}
\item {\itshape Write a single file with string to AST transformation}

This method is quite popular, for example, the \href{https://github.com/reworkcss/css/blob/master/lib/parse/index.js}{\texttt{ Rework analyzer}} was written in this style. But with a large code base, the code becomes hard to read and pretty slow.
\item {\itshape Split it into lexical analysis/parsing steps (source string → tokens → AST)}

This is the way of how we do it in Post\+CSS and also the most popular one. A lot of parsers like \href{https://github.com/babel/babel/tree/master/packages/babel-parser}{\texttt{ {\ttfamily @babel/parser} (parser behind Babel)}}, \href{https://github.com/csstree/csstree}{\texttt{ {\ttfamily CSSTree}}} were written in such way. The main reasons to separate tokenization from parsing steps are performance and abstracting complexity.
\end{DoxyItemize}

Let think about why the second way is better for our needs.

First of all, because string to tokens step takes more time than parsing step. We operate on large source string and process it char by char, this is why it is very inefficient operation in terms of performance and we should perform it only once.

But from other side tokens to AST transformation is logically more complex so with such separation we could write very fast tokenizer (but from this comes sometimes hard to read code) and easy to read (but slow) parser.

Summing it up splitting into two steps improve performance and code readability.

So now let\textquotesingle{}s look more closely on structures that play the main role in Post\+CSS workflow.\hypertarget{md_sfcode_node_modules_postcss_docs_architecture_autotoc_md20683}{}\doxysubsection{Core Structures}\label{md_sfcode_node_modules_postcss_docs_architecture_autotoc_md20683}

\begin{DoxyItemize}
\item \#\#\#\# Tokenizer ( \href{https://github.com/postcss/postcss/blob/master/lib/tokenize.es6}{\texttt{ lib/tokenize.\+es6}} )

Tokenizer (aka Lexer) plays important role in syntax analysis.

It accepts CSS string and returns a list of tokens.

Token is a simple structure that describes some part of syntax like {\ttfamily at-\/rule}, {\ttfamily comment} or {\ttfamily word}. It can also contain positional information for more descriptive errors.

For example, if we consider following CSS

\`{}\`{}\`{}css .class\+Name \{ color\+: \#\+FFF; \} \`{}\`{}\`{}

corresponding tokens from Post\+CSS will be \`{}\`{}\`{}js \mbox{[} \mbox{[}\char`\"{}word\char`\"{}, \char`\"{}.\+class\+Name\char`\"{}, 1, 1, 1, 10\mbox{]} \mbox{[}\char`\"{}space\char`\"{}, \char`\"{} \char`\"{}\mbox{]} \mbox{[}\char`\"{}\{\char`\"{}, \char`\"{}\{\char`\"{}, 1, 12\mbox{]} \mbox{[}\char`\"{}space\char`\"{}, \char`\"{} \char`\"{}\mbox{]} \mbox{[}\char`\"{}word\char`\"{}, \char`\"{}color\char`\"{}, 1, 14, 1, 18\mbox{]} \mbox{[}\char`\"{}\+:\char`\"{}, \char`\"{}\+:\char`\"{}, 1, 19\mbox{]} \mbox{[}\char`\"{}space\char`\"{}, \char`\"{} \char`\"{}\mbox{]} \mbox{[}\char`\"{}word\char`\"{}, \char`\"{}\#\+FFF\char`\"{} , 1, 21, 1, 23\mbox{]} \mbox{[}\char`\"{};\char`\"{}, \char`\"{};\char`\"{}, 1, 24\mbox{]} \mbox{[}\char`\"{}space\char`\"{}, \char`\"{} \char`\"{}\mbox{]} \mbox{[}\char`\"{}\}\char`\"{}, \char`\"{}\}\char`\"{}, 1, 26\mbox{]} \mbox{]} \`{}\`{}\`{}

As you can see from the example above a single token represented as a list and also {\ttfamily space} token doesn\textquotesingle{}t have positional information.

Let\textquotesingle{}s look more closely on single token like {\ttfamily word}. As it was said each token represented as a list and follow such pattern.

\`{}\`{}\`{}js const token = \mbox{[} // represents token type \textquotesingle{}word\textquotesingle{},

// represents matched word \textquotesingle{}.class\+Name\textquotesingle{},

// This two numbers represent start position of token. // It is optional value as we saw in the example above, // tokens like {\ttfamily space} don\textquotesingle{}t have such information.

// Here the first number is line number and the second one is corresponding column. 1, 1,

// Next two numbers also optional and represent end position for multichar tokens like this one. Numbers follow same rule as was described above 1, 10 \mbox{]} \`{}\`{}` There are many patterns how tokenization could be done, Post\+CSS motto is performance and simplicity. Tokenization is a complex computing operation and takes a large amount of syntax analysis time ( $\sim$90\% ), that why Post\+CSS' Tokenizer looks dirty but it was optimized for speed. Any high-\/level constructs like classes could dramatically slow down tokenizer.

Post\+CSS\textquotesingle{} Tokenizer uses some sort of streaming/chaining API where you expose \href{https://github.com/postcss/postcss/blob/master/lib/tokenize.es6\#L48-L308}{\texttt{ {\ttfamily next\+Token()}}} method to Parser. In this manner, we provide a clean interface for Parser and reduce memory usage by storing only a few tokens and not the whole list of tokens.
\end{DoxyItemize}

\#\#\#\# Parser ( \href{https://github.com/postcss/postcss/blob/master/lib/parse.es6}{\texttt{ lib/parse.\+es6}}, \href{https://github.com/postcss/postcss/blob/master/lib/parser.es6}{\texttt{ lib/parser.\+es6}} )

Parser is the main structure responsible for \href{https://en.wikipedia.org/wiki/Parsing}{\texttt{ syntax analysis}} of incoming CSS. Parser produces a structure called \href{https://en.wikipedia.org/wiki/Abstract_syntax_tree}{\texttt{ Abstract Syntax Tree (AST)}} that could then be transformed by plugins later on.

Parser works in common with Tokenizer and operates over tokens, not source string, as it would be a very inefficient operation.

It uses mostly {\ttfamily next\+Token} and {\ttfamily back} methods provided by Tokenizer for obtaining single or multiple tokens and then construct part of AST called {\ttfamily Node}.

There are multiple Node types that Post\+CSS could produce but all of them inherit from base Node \href{https://github.com/postcss/postcss/blob/master/lib/node.es6\#L34}{\texttt{ class}}.


\begin{DoxyItemize}
\item \#\#\#\# Processor ( \href{https://github.com/postcss/postcss/blob/master/lib/processor.es6}{\texttt{ lib/processor.\+es6}} )

Processor is a very plain structure that initializes plugins and runs syntax transformations. Plugin is just a function registered with \href{https://github.com/postcss/postcss/blob/master/lib/postcss.es6\#L109}{\texttt{ postcss.\+plugin}} call.

It exposes only a few public API methods. Description of them could be found on \href{http://api.postcss.org/Processor.html}{\texttt{ api.\+postcss.\+org/\+Processor}}
\item \#\#\#\# Stringifier ( \href{https://github.com/postcss/postcss/blob/master/lib/stringify.es6}{\texttt{ lib/stringify.\+es6}}, \href{https://github.com/postcss/postcss/blob/master/lib/stringifier.es6}{\texttt{ lib/stringifier.\+es6}} )

Stringifier is a base class that translates modified AST to pure CSS string. Stringifier traverses AST starting from provided Node and generates a raw string representation of it calling corresponding methods.

The most essential method is \href{https://github.com/postcss/postcss/blob/master/lib/stringifier.es6\#L25-L27}{\texttt{ {\ttfamily Stringifier.\+stringify}}} that accepts initial Node and semicolon indicator. You can learn more by checking \href{https://github.com/postcss/postcss/blob/master/lib/stringifier.es6}{\texttt{ stringifier.\+es6}}
\end{DoxyItemize}\hypertarget{md_sfcode_node_modules_postcss_docs_architecture_autotoc_md20684}{}\doxysubsection{API Reference}\label{md_sfcode_node_modules_postcss_docs_architecture_autotoc_md20684}
More descriptive API documentation could be found \href{http://api.postcss.org/}{\texttt{ here}} 