nav tabs on admin dashboard

This commit is contained in:
2019-03-07 00:20:34 -06:00
parent f73d6ae228
commit e4f473f376
11661 changed files with 216240 additions and 1544253 deletions

View File

@@ -1,7 +1,7 @@
## PostCSS Architecture
General overview of PostCSS architecture.
It can be useful for everyone who wish to contribute to core or develop better understanding of the tool.
General overview of the PostCSS architecture.
It can be useful for everyone who wishes to contribute to the core or develop a better understanding of the tool.
**Table of Contents**
@@ -18,34 +18,34 @@ It can be useful for everyone who wish to contribute to core or develop better u
> This section describes ideas lying behind PostCSS
Before diving deeper into development of PostCSS let's briefly describe what is PostCSS and what is not.
Before diving deeper into the development of PostCSS let's briefly describe what is PostCSS and what is not.
**PostCSS**
- *is **NOT** a style preprocessor like `Sass` or `Less`.*
It does not define custom syntax and semantic, it's not actually a language.
PostCSS works with CSS and can be easily integrated with tools described above. That being said any valid CSS can be processed by PostCSS.
It does not define a custom syntax and semantics, it's not actually a language.
PostCSS works with CSS and can be easily integrated with the tools described above. That being said any valid CSS can be processed by PostCSS.
- *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 PostCSS is not strictly about CSS spec but about syntax definition manner of CSS. In such way you can define custom syntax constructs like at-rule, that could be very helpful for tools build around PostCSS. PostCSS plays a role of framework for building outstanding tools for CSS manipulations.
It allows you to define custom CSS like syntax that could be understandable and transformed by plugins. That being said PostCSS 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 PostCSS. PostCSS plays the role of a framework for building outstanding tools for CSS manipulations.
- *is a big player in CSS ecosystem*
Large amount of lovely tools like `Autoprefixer`, `Stylelint`, `CSSnano` were built on PostCSS ecosystem. There is big chance that you already use it implicitly, just check your `node_modules` :smiley:
A Large amount of lovely tools like `Autoprefixer`, `Stylelint`, `CSSnano` were built on PostCSS ecosystem. There is a big chance that you already use it implicitly, just check your `node_modules` :smiley:
### Workflow
This is high level overview of whole PostCSS workflow
This is a high-level overview of the whole PostCSS workflow
<img width="300" src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/PostCSS_scheme.svg/512px-PostCSS_scheme.svg.png" alt="workflow">
As you can see from diagram above, PostCSS architecture is pretty straightforward but some parts of it could be misunderstood.
As you can see from the diagram above, PostCSS architecture is pretty straightforward but some parts of it could be misunderstood.
From diagram above you can see part called *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 object representation of it.
You can see a part called *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 parser
That being said, there are few ways to write a parser.
- *Write a single file with string to AST transformation*
@@ -54,18 +54,18 @@ That being said, there are few ways to write parser
- *Split it into lexical analysis/parsing steps (source string → tokens → AST)*
This is the way of how we do it in PostCSS and also the most popular one.
A lot of parsers like [`Babylon` (parser behind Babel)](https://github.com/babel/babel/tree/master/packages/babylon), [`CSSTree`](https://github.com/csstree/csstree) were written in such way.
A lot of parsers like [`@babel/parser` (parser behind Babel)](https://github.com/babel/babel/tree/master/packages/babel-parser), [`CSSTree`](https://github.com/csstree/csstree) were written in such way.
The main reasons to separate tokenization from parsing steps are performance and abstracting complexity.
Let think about why second way is better for our needs.
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.
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 in two steps improve performance and code readability.
Summing it up splitting into two steps improve performance and code readability.
So now lets look more closely on structures that play main role in PostCSS workflow.
So now let's look more closely on structures that play the main role in PostCSS workflow.
### Core Structures
@@ -73,17 +73,17 @@ So now lets look more closely on structures that play main role in PostCSS workf
Tokenizer (aka Lexer) plays important role in syntax analysis.
It accepts CSS string and returns list of tokens.
It accepts CSS string and returns a list of tokens.
Token is a simple structure that describes some part of syntax like `at-rule`, `comment` or `word`. It can also contain positional information for more descriptive errors.
For example if we consider following css
For example, if we consider following CSS
```css
.className { color: #FFF; }
```
corresponding tokens representation from PostCSS will be
corresponding tokens from PostCSS will be
```js
[
["word", ".className", 1, 1, 1, 10]
@@ -100,9 +100,9 @@ So now lets look more closely on structures that play main role in PostCSS workf
]
```
As you can see from the example above single token represented as a list and also `space` token doesn't have positional information.
As you can see from the example above a single token represented as a list and also `space` token doesn't have positional information.
Lets look more closely on single token like `word`. As it was said each token represented as a list and follow such pattern.
Let's look more closely on single token like `word`. As it was said each token represented as a list and follow such pattern.
```js
const token = [
@@ -113,7 +113,7 @@ So now lets look more closely on structures that play main role in PostCSS workf
'.className',
// This two numbers represent start position of token.
// It's optional value as we saw in example above,
// It is optional value as we saw in the example above,
// tokens like `space` don't have such information.
// Here the first number is line number and the second one is corresponding column.
@@ -121,31 +121,31 @@ So now lets look more closely on structures that play main role in PostCSS workf
// 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
];
]
```
There are many patterns how tokenization could be done, PostCSS motto is performance and simplicity. Tokenization is complex computing operation and take large amount of syntax analysis time ( ~90% ), that why PostCSS' Tokenizer looks dirty but it was optimized for speed. Any high-level constructs like classes could dramatically slow down tokenizer.
There are many patterns how tokenization could be done, PostCSS motto is performance and simplicity. Tokenization is a complex computing operation and takes a large amount of syntax analysis time ( ~90% ), that why PostCSS' Tokenizer looks dirty but it was optimized for speed. Any high-level constructs like classes could dramatically slow down tokenizer.
PostCSS' Tokenizer use some sort of streaming/chaining API where you exposes [`nextToken()`](https://github.com/postcss/postcss/blob/master/lib/tokenize.es6#L48-L308) method to Parser. In this manner we provide clean interface for Parser and reduce memory usage by storing only few tokens and not whole list of tokens.
PostCSS' Tokenizer uses some sort of streaming/chaining API where you expose [`nextToken()`](https://github.com/postcss/postcss/blob/master/lib/tokenize.es6#L48-L308) 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.
- #### Parser ( [lib/parse.es6](https://github.com/postcss/postcss/blob/master/lib/parse.es6), [lib/parser.es6](https://github.com/postcss/postcss/blob/master/lib/parser.es6) )
Parser is main structure that responsible for [syntax analysis](https://en.wikipedia.org/wiki/Parsing) of incoming CSS. Parser produces structure called [Abstract Syntax Tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree) that could then be transformed by plugins later on.
Parser is the main structure responsible for [syntax analysis](https://en.wikipedia.org/wiki/Parsing) of incoming CSS. Parser produces a structure called [Abstract Syntax Tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree) 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 very inefficient operation.
Parser works in common with Tokenizer and operates over tokens, not source string, as it would be a very inefficient operation.
It use mostly `nextToken` and `back` methods provided by Tokenizer for obtaining single or multiple tokens and than construct part of AST called `Node`
It uses mostly `nextToken` and `back` methods provided by Tokenizer for obtaining single or multiple tokens and then construct part of AST called `Node`.
There are multiple Node types that PostCSS could produce but all of them inherit from base Node [class](https://github.com/postcss/postcss/blob/master/lib/node.es6#L34).
- #### Processor ( [lib/processor.es6](https://github.com/postcss/postcss/blob/master/lib/processor.es6) )
Processor is a very plain structure that initializes plugins and run syntax transformations. Plugin is just a function registered with [postcss.plugin](https://github.com/postcss/postcss/blob/master/lib/postcss.es6#L109) call.
Processor is a very plain structure that initializes plugins and runs syntax transformations. Plugin is just a function registered with [postcss.plugin](https://github.com/postcss/postcss/blob/master/lib/postcss.es6#L109) call.
It exposes quite few public API methods. Description of them could be found on [api.postcss.org/Processor](http://api.postcss.org/Processor.html)
It exposes only a few public API methods. Description of them could be found on [api.postcss.org/Processor](http://api.postcss.org/Processor.html)
- #### Stringifier ( [lib/stringify.es6](https://github.com/postcss/postcss/blob/master/lib/stringify.es6), [lib/stringifier.es6](https://github.com/postcss/postcss/blob/master/lib/stringifier.es6) )
Stringifier is a base class that translates modified AST to pure CSS string. Stringifier traverse AST starting from provided Node and generate raw string representation of it calling corresponding methods.
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 [`Stringifier.stringify`](https://github.com/postcss/postcss/blob/master/lib/stringifier.es6#L25-L27)
that accepts initial Node and semicolon indicator.

View File

@@ -22,34 +22,34 @@ 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, [cssnext] and [Autoprefixer].
PostCSS — for example, [RTLCSS] and [Autoprefixer].
[Autoprefixer]: https://github.com/postcss/autoprefixer
[cssnext]: http://cssnext.io/
[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, [cssnext] contains many small plugins,
one for each W3C specification. And [cssnano] contains a separate plugin
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.
[cssnext]: http://cssnext.io/
[cssnano]: https://github.com/ben-eb/cssnano
[`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].
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
[`postcss-mixins`]: https://github.com/postcss/postcss-mixins
### 1.4. Create plugin by `postcss.plugin`
@@ -57,11 +57,11 @@ By wrapping your function in this method,
you are hooking into a common plugin API:
```js
module.exports = postcss.plugin('plugin-name', function (opts) {
return function (root, result) {
// Plugin code
};
});
module.exports = postcss.plugin('plugin-name', opts => {
return (root, result) => {
// Plugin code
}
})
```
## 2. Processing
@@ -78,19 +78,19 @@ different environments. You should test in (at least) Node.js [active LTS](https
For example, use `fs.writeFile` instead of `fs.writeFileSync`:
```js
postcss.plugin('plugin-sprite', function (opts) {
return function (root, result) {
postcss.plugin('plugin-sprite', opts => {
return (root, result) => {
return new Promise(function (resolve, reject) {
var sprite = makeSprite();
fs.writeFile(opts.file, function (err) {
if ( err ) return reject(err);
resolve();
})
});
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
@@ -98,22 +98,22 @@ postcss.plugin('plugin-sprite', function (opts) {
Every node must have a relevant `source` so PostCSS can generate
an accurate source map.
So if you add new declaration based on some existing declaration, you should
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 });
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' ) {
var keyframe = createAnimationByName(decl.value);
keyframes.source = decl.source;
decl.root().append(keyframes);
if (decl.prop === 'animation') {
const keyframe = createAnimationByName(decl.value)
keyframes.source = decl.source
decl.root().append(keyframes)
}
```
@@ -134,8 +134,8 @@ 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' });
if (typeof mixins[name] === 'undefined') {
throw decl.error('Unknown mixin ' + name, { plugin: 'postcss-mixins' })
}
```
@@ -145,8 +145,8 @@ 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 (outdated(decl.prop)) {
result.warn(decl.prop + ' is outdated', { node: decl })
}
```
@@ -156,7 +156,7 @@ If CSS input is a source of the warning, the plugin must set the `node` option.
### 4.1. Document your plugin in English
PostCSS plugins must have their `README.md` written in English. Do not be afraid
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;

View File

@@ -23,12 +23,12 @@ it can support plugins which accept a function, such as [`postcss-assets`]:
```js
module.exports = [
require('postcss-assets')({
cachebuster: function (file) {
return fs.statSync(file).mtime.getTime().toString(16);
}
})
];
require('postcss-assets')({
cachebuster: function (file) {
return fs.statSync(file).mtime.getTime().toString(16)
}
})
]
```
[`postcss-assets`]: https://github.com/borodean/postcss-assets
@@ -43,7 +43,7 @@ writing to disk (for example, a gulp transform), you should set both options
to point to the same file:
```js
processor.process({ from: file.path, to: file.path });
processor.process({ from: file.path, to: file.path })
```
### 2.2. Use only the asynchronous API
@@ -53,8 +53,8 @@ The synchronous API is provided only for debugging, is slower,
and cant work with asynchronous plugins.
```js
processor.process(opts).then(function (result) {
// processing is finished
processor.process(opts).then(result => {
// processing is finished
});
```
@@ -75,13 +75,13 @@ as the runner can be used by developers who are not familiar with JavaScript.
Instead, handle such errors gracefully:
```js
processor.process(opts).catch(function (error) {
if ( error.name === 'CssSyntaxError' ) {
process.stderr.write(error.message + error.showSourceCode());
} else {
throw error;
}
});
processor.process(opts).catch(error => {
if (error.name === 'CssSyntaxError') {
process.stderr.write(error.message + error.showSourceCode())
} else {
throw error
}
})
```
### 3.2. Display `result.warnings()`
@@ -89,9 +89,9 @@ processor.process(opts).catch(function (error) {
PostCSS runners must output warnings from `result.warnings()`:
```js
result.warnings().forEach(function (warn) {
process.stderr.write(warn.toString());
});
result.warnings().forEach(warn => {
process.stderr.write(warn.toString())
})
```
See also [postcss-log-warnings] and [postcss-messages] plugins.
@@ -106,8 +106,8 @@ PostCSS runners must provide an option to save the source map in a different
file:
```js
if ( result.map ) {
fs.writeFile(opts.to + '.map', result.map.toString());
if (result.map) {
fs.writeFile(opts.to + '.map', result.map.toString())
}
```
@@ -115,7 +115,7 @@ if ( result.map ) {
### 4.1. Document your runner in English
PostCSS runners must have their `README.md` written in English. Do not be afraid
PostCSS runners 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;
@@ -127,7 +127,7 @@ PostCSS runners must describe changes of all releases in a separate file,
such as `ChangeLog.md`, `History.md`, or with [GitHub Releases].
Visit [Keep A Changelog] for more information on how to write one of these.
Of course you should use [SemVer].
Of course, you should use [SemVer].
[Keep A Changelog]: http://keepachangelog.com/
[GitHub Releases]: https://help.github.com/articles/creating-releases/

View File

@@ -13,17 +13,17 @@ If you dont want the map inlined, you can set `map.inline: false`.
```js
processor
.process(css, {
from: 'app.sass.css',
to: 'app.css',
map: { inline: false },
})
.then(function (result) {
result.map //=> '{ "version":3,
// "file":"app.css",
// "sources":["app.sass"],
// "mappings":"AAAA,KAAI" }'
});
.process(css, {
from: 'app.sass.css',
to: 'app.css',
map: { inline: false }
})
.then(result => {
result.map //=> '{ "version":3,
// "file":"app.css",
// "sources":["app.sass"],
// "mappings":"AAAA,KAAI" }'
})
```
If PostCSS finds source maps from a previous transformation,

46
node_modules/postcss/docs/syntax.md generated vendored
View File

@@ -24,9 +24,9 @@ functions:
```js
module.exports = {
parse: require('./parse'),
stringify: require('./stringify')
};
parse: require('./parse'),
stringify: require('./stringify')
}
```
[SCSS]: https://github.com/postcss/postcss-scss
@@ -41,13 +41,13 @@ The parser API is a function which receives a string & returns a [`Root`] node.
The second argument is a function which receives an object with PostCSS options.
```js
var postcss = require('postcss');
const postcss = require('postcss')
module.exports = function (css, opts) {
var root = postcss.root();
// Add other nodes to root
return root;
};
module.exports = function parse (css, opts) {
const root = postcss.root()
// Add other nodes to root
return root
}
```
[Safe Parser]: https://github.com/postcss/postcss-safe-parser
@@ -88,11 +88,11 @@ Second optimization is using character codes instead of strings.
```js
// Slow
string[i] === '{';
string[i] === '{'
// Fast
const OPEN_CURLY = 123; // `{'
string.charCodeAt(i) === OPEN_CURLY;
const OPEN_CURLY = 123 // `{'
string.charCodeAt(i) === OPEN_CURLY
```
Third optimization is “fast jumps”. If you find open quotes, you can find
@@ -100,12 +100,12 @@ next closing quote much faster by `indexOf`:
```js
// Simple jump
next = string.indexOf('"', currentPosition + 1);
next = string.indexOf('"', currentPosition + 1)
// Jump by RegExp
regexp.lastIndex = currentPosion + 1;
regexp.test(string);
next = regexp.lastIndex;
regexp.lastIndex = currentPosion + 1
regexp.test(string)
next = regexp.lastIndex
```
The parser can be a well written class. There is no need in copy-paste and
@@ -166,11 +166,11 @@ A Stringifier is a function which receives [`Root`] node and builder callback.
Then it calls builder with every nodes string and node instance.
```js
module.exports = function (root, builder) {
// Some magic
var string = decl.prop + ':' + decl.value + ';';
builder(string, decl);
// Some science
module.exports = function stringify (root, builder) {
// Some magic
const string = decl.prop + ':' + decl.value + ';'
builder(string, decl)
// Some science
};
```
@@ -201,9 +201,9 @@ For these cases, you should pass a third argument to builder function:
`'start'` or `'end'` string:
```js
this.builder(rule.selector + '{', rule, 'start');
this.builder(rule.selector + '{', rule, 'start')
// Stringify declarations inside
this.builder('}', rule, 'end');
this.builder('}', rule, 'end')
```
### Raw Values