minimalist-notation
Version:
Minimalist Notation
1,338 lines (1,057 loc) • 43 kB
Markdown
[English](https://github.com/mr-amirka/minimalist-notation/blob/master/docs.md)
# Minimalist Notation Docs
* [About](#about)
* [Example for class name](#example-for-class-name)
* [Example for attr](#example-for-attr)
* [Notation](#notation)
* [Имя эссенции](#Имя-эссенции)
* [Контекст эссенции](#Контекст-эссенции)
* [Медиа-запросы в нотации](#Медиа-запросы-в-нотации)
* [Grouping](#grouping)
* [Media-queries generation](#media-queries-generation)
* [Escaping](#escaping)
* [Essences of styles](#essences-of-styles)
* [Dynamic essences](#dynamic-essences)
* [Generating the essences of styles](#generating-the-essences-of-styles)
* [States](#states)
* [Auto prefixes](#auto-prefixes)
* [Parent/child selectors](#parent/child-selectors)
* [Depth](#depth)
* [Complex selectors](#complex-selectors)
* [Essences assignment (Example with container)](#essences-assignment)
* [Priority multiplier](#priority-multiplier)
* [Getting started](https://github.com/mr-amirka/minimalist-notation/blob/master/README-ru.md)
* [Предустановленные опции](https://github.com/mr-amirka/minimalist-notation/presets/blob/master/README.md)
* [От автора](https://github.com/mr-amirka/minimalist-notation/blob/master/from-author-ru.md)
Try this tests:
* https://jsfiddle.net/Amirka/dkozgauy/
* https://jsfiddle.net/Amirka/0475wbq2/
Home page: https://minimalist-notation.org
Буду благодарен за Ваши отзывы и замечания. Пишите мне в [telegram](https://t.me/mr_amirka) .
С любовью, Ваш mr.Amirka :)
Вы заинтересованы в развитии проекта? Внесите свою [лепту](https://yasobe.ru/na/notation).
## About
Minimalist Notation (MN) (минималистическая нотация) - это технология генерации стилей, основанная на парсинге разметки. Генерация осуществляется непосредственно в СSS. Технология колоссально ускоряет процесс верстки и может использоваться дополнительно с традиционными технологиями, либо заменять их полностью.
Преимущество перед традиционными технологиями CSS-препроцессинга в том, что разработчик избавляется от необходимости писать CSS. CSS генерируется автоматически на основании нотации и заданных разработчиком правил генерации стилей. Разработчику больше не нужно контролировать, какие стили используются в его разметке, а какие - нет, ибо отныне стили генерируются только для того, что присутствует в разметке.
PS:
Технология ориентирована на методологию Functional/Atomic CSS.
Если Вы верстаете по методологии Functional/Atomic CSS, то:
* со временем Вы с первого взгляда понимаете смысл каждого имени в разметке;
* имеете возможность легко стандартизировать правила нотации и именования;
* разметку легко переиспользовать в новом проекте, если он предусматривает тот же базовый набор функциональных стилей в CSS.
* в случае внесения правок в дизайн, Вы будете менять только HTML-разметку.
* у Вас прямые руки - Вы не натыкаетесь на грабли с перекрытиями стилей;
* имеете возможность настроить Вашу систему сборки под автоматическую генерацию CSS из атрибутов в разметке;
* не задаете громоздкие атрибуты длинным селекторам в каждом месте, где хотите, например, просто добавить плавность трансформации. В функциональном подходе это делается один раз, как в CSS-коде ниже:
```css
.dn250 {
-khtml-transition-duration: 250ms;
-ms-transition-duration: 250ms;
-o-transition-duration: 250ms;
-moz-transition-duration: 250ms;
-webkit-transition-duration: 250ms;
transition-duration: 250ms;
}
```
Благодаря MN:
* **ноль CSS-кода и CSS-файлов** в проекте. Абсолютно нет необходимости писать CSS-код.
* СSS генерируется автоматически из значений атрибутов в разметке, и мы экономим время, избавив себя от написания "сатаниского" CSS-кода;
* нет мертвого CSS-кода, ибо CSS генерируется только для той разметки, которая имеется.
* в runtime версии мы имеем возможность не обращаться на сервер за "тяжелыми" СSS-файлами.
* при внесении правок в дизайн мы меняем только разметку HTML, не трогая СSS.
Технология "Minimalist Notation" поддерживает:
* параметризуемую нотацию имен
* параметризуемые состояния;
* контексты родительских/дочерних селекторов;
* контексты комплексных селекторов;
* управление глубиной в dom-дереве через нотацию;
* управление приоритетом стилей через нотацию;
* контексты медиа-запросов;
* группировки подстрок в нотации;
* синонимы состояний и медиа-запросов;
* наследование от эссенций стилей (расширение; аналог ``` @extend ``` в SASS) ;
* примеси эссенций (аналог ``` @include ``` в SASS);
* ассоциацию селекторов с эссенциями стилей;
* манипуляция глобальными стилями CSS в рантайме.
Для целей кастомизации стилей разметки под определенную тему в MN предусмотрена возможность манипуляции глобальными CSS правилами в рантайме, например, так для эссенций:
```js
mn('bgTheme', {
style: {
backgroundColor: '#EEE',
borderColor: '#CCC',
},
});
```
или путем расширения эссенции за счет других эссенций:
```js
mn('bgTheme', {
exts: 'bgE cC',
});
// shorter way
mn('bgTheme', 'bgE cC');
```
или так только для конкретных селекторов без интеграции в нотацию:
```js
mn.css('.bgTheme', {
backgroundColor: '#EEE',
borderColor: '#CCC',
});
```
или путем ассоциации селекторов с эссенциями стилей:
```js
mn.assign({
'.bgTheme': 'bgE cC',
});
```
PS: Если необходимо задать несколько альтернативных значений для одного атрибута по аналогии с оным в CSS:
```css
.bgTheme {
background-color: #CCC;
background-color: rgba(0,0,0,0.2);
}
```
Вы можете сделать так:
```js
mn.css('.bgTheme', {
backgroundColor: ['#CCC', 'rgba(0,0,0,0.2)']
});
```
### Example for class name
Input:
```html
<div class="f12 p10 mb10 f14:h cF00<.parent c0F0@mediaName sq40 bg0F0">...</div>
```
Output:
```css
@media mediaName{
.c0F0\@mediaName{color:rgb(0,255,0)}
}
.f12{font-size:12px}
.f14\:h:hover{font-size:14px}
.parent .cF00\<\.parent{color:rgb(255,0,0)}
.bg0F0{background:rgb(0,255,0)}
.sq40{width:40px;height:40px}
.p10{padding:10px}
.mb10{margin-bottom:10px}
```
### Example for attr "m"
Input:
```html
<div m-n="f12 p10 mb10 f14:h cF00<.parent c0F0@mediaName sq40 bg0F0">...</div>
```
Output:
```css
@media mediaName{
[m-n~='c0F0@mediaName']{color:rgb(0,255,0)}
}
[m-n~='f12']{font-size:12px}
[m-n~='f14:h']:hover{font-size:14px}
.parent [m-n~='cF00<.parent']{color:rgb(255,0,0)}
[m-n~='bg0F0']{background:rgb(0,255,0)}
[m-n~='sq40']{width:40px;height:40px}
[m-n~='p10']{padding:10px}
[m-n~='mb10']{margin-bottom:10px}
```
## Notation
Base format:
```
{property}{value}@{mediaName}[...(>{depth}{childSelectors}|<{depth}{parentSelectors})@{mediaName}]*{priority}
```
Запись нотации MN делится на 2 части:
* имя эссенции;
* контекст эссенции (комбинированный селектор и медиа-запрос).
За имя эссенции отвечает подстрока от начала имени до первого служебного символа (``` <>.[]:+@ ```).
Остальная часть нотации, включая первый служебный символ относится к контексту эссенции, в пределах которого стили эссенции применяются (селекторы и медиа-запросы). Например:
Example 1:
``` ph10>1 ``` ->
имя эссенции: ``` ph10 ```; контекст эссенции: ``` >1 ```
Example 2:
``` bgF00<.theme-1 ``` ->
имя эссенции: ``` bgF00 ``` ; контекст эссенции: ``` <.theme-1 ```
Example 3:
``` cF:h ``` ->
имя эссенции: ``` cF ```; контекст эссенции: ``` :h ```
Example 4:
``` mh-10@m>1 ``` ->
имя эссенции: ``` mh-10 ```; контекст эссенции: ``` @m>1 ```
### Имя эссенции
Часть имени, которая отвечает за эссенцию, парсится для генерации стилей и также делится на 2 части:
* префикс эссенции (статичная часть, собственно само имя эссенции);
* суффикс эссенции (параметризуемая часть, значение эссенции).
Префиксом имени эссенции является первая часть имени эссенции, состоящая из латинских букв в нижнем регистре. Оно может являться аббревиатурой. Соответственно, остальная часть имени эссенции является префиксом - параметризуемой частью. Например:
Example 1:
``` ph10 ``` ->
префикс эссенции: ``` ph ```; суффикс эссенции: ```10 ```
Example 2:
``` bgF00 ``` ->
префикс эссенции: ``` bg ```; суффикс эссенции: ``` F00 ```
Example 3:
``` cF ``` ->
префикс эссенции: ``` c ```; суффикс эссенции: ``` F ```
### Контекст эссенции
Часть нотации, отвечающая за контекст эссенции может разделяться символом ``` > ``` на несколько частей, представляющие собой последовательность дочерних элементов до целевого элемента, на который распространяется влияние эссенции. Например:
``` essenceValue>.child1>.child2>.targetChild ```
Затем полученные части могут разделяться символом ``` < ``` на несколько частей представляющие собой последовательность родительских элементов, при наличии которых стили эссенции вступают в силу. Например:
``` essenceValue<.parent1<.parent2 ```
### Медиа-запросы в нотации
Каждая полученная выше часть может разделяться символом ``` @ ```, отвечающий за имя медиа-запроса, при наличии которого стили эссенции вступают в силу. Например:
``` essenceValue@mediaName ```
``` essenceValue@mediaName<.parent ```
``` essenceValue<.parent@mediaName ```
``` essenceValue@mediaName>.targetChild ```
``` essenceValue<.parent1@mediaName<.parent2 ```
``` essenceValue@mediaName<.parent1<.parent2>.child1>.targetChild ```
Допустимо указывать имена нескольких медиа-запросов, например так:
``` essenceValue@mediaName1<parent@mediaName2 ```
Однако в подобных случаях задействуется только первое найденное имя медиа-запроса. В данном случае, это ``` mediaName1 ```
Таким образом сделано для удобства использования нотации, например в случаях, когда мы задаем общий медиа-запрос для нескольких атрибутов дочернего элемента, но для некоторых атрибутов этот медиа-запрос должен отличаться:
```html
<div m-n="(sq200|f20|f14@m)>.child1@d">
<div class="child1">
текст
</div>
</div>
```
Нотация ``` (sq200|f20|f14@m)>.child1@d ``` распарсится как несколько таких строк:
1. ``` sq200>.child1@d ```
2. ``` f20>.child1@d ```
3. ``` f14@m>.child1@d ```
В строке *3* мы получим несколько имен медиа-запросов, но в силу вступит только первое имя медиа-запроса в этой последовательности.
### Grouping
Группировка помогает сократить запись.
Несколько параметров можно сгруппировать вместе с помощью разделителя ``` | ``` между альтернативными подстроками внутри скобок.
Example:
Вместо этого
```html
<div m-n="bc00F>input:h bc00F>input:a bg0>input:h bg0>input:a"></div>
```
Вы можете сделать так:
```html
<div m-n="(bc00F|bg0)>input:(h|a)"></div>
```
Т.е., эти записи эквивалентны:
Example 1:
``` (bc00F|bg0)>input ``` -> ``` bc00F>input bg0>input ```
Example 2:
``` input:(h|a) ``` -> ``` input:h input:a ```
Example 3:
``` (bc00F|bg0)>input:(h|a) ``` -> ``` bc00F>input:h bc00F>input:a bg0>input:h bg0>input:a ```
### Escaping
В процессе применения MN могут возникать ситуации, когда Вам нужно экранировать служебные символы, например в таком случае:
```html
<div m-n="pt33.3%"></div>
```
Мы получим не то, чего ожидаем, так как точка является служебным символом
``` pt33.3% ``` ->
```css
[m-n~='pt33.3%'].3%{padding-top:33px}
```
Если мы хотим, чтобы точка попала в параметры эссенции, то мы должны экранировать её так:
```html
<div m-n="pt33\.3%"></div>
```
Таким образом, получим желаемое:
``` pt33\.3% ``` ->
```css
[m-n~='pt33\\.3%']{padding-top:33.3%}
```
### Media-queries generation
По умолчанию имя медиа-запроса генерируется в CSS как есть, например:
INPUT:
```html
<div m-n="f20@m f10@print">текст</div>
```
OUTPUT:
```css
@media m {
[m-n~='f20@m'] {
font-size: 20px;
}
}
@media print {
[m-n~='f10@print'] {
font-size: 10px;
}
}
```
Именам медиа-запросов в нотации можно установить синонимы.
Пример:
INPUT:
```js
mn.media.m = {
query: '(max-width: 991px)',
priority: 0
};
mn.media.m2 = {
query: '(max-width: 767px)',
priority: 1
};
```
```html
<div m-n="f18@m f16@m2">текст</div>
```
OUTPUT:
```css
@media (max-width: 991px) {
[m-n~='f18@m'] {
font-size: 18px;
}
}
@media (max-width: 767px) {
[m-n~='f16@m2'] {
font-size: 16px;
}
}
```
Если в имени медиа-запроса будет распознана сокращенная запись подпадающая под шаблон:
```
{min-width?:number}-{max-width?:number}x{min-height?:number}-{max-height?:number}^{media-priority?:number}
```
Тогда будут сгенерированы соответствующие медиа-запросы, например:
INPUT:
```html
<div m-n="f20@768-992x300-600^2">текст</div>
```
OUTPUT:
```css
@media (min-width: 768px) and (max-width: 992px) and (min-height: 300px) and (max-height: 600px) {
[m-n~='f20@768-992x300-600^2'] {
font-size: 20px;
}
}
```
Параметры шаблона сокращенной записи медиа-запроса в нотации не являются обязательными и некоторые из них можно опустить, например:
INPUT:
```html
<div m-n="f20@768 f30@992- f40@x600 f50@1000-1200 f3@x10-60">текст</div>
```
OUTPUT:
```css
@media (min-width: 1000px) and (max-width: 1200px) {
[m-n~='f50@1000-1200'] {
font-size: 50px;
}
}
@media (max-width: 768px) {
[m-n~='f20@768'] {
font-size: 20px;
}
}
@media (min-height: 10px) and (max-height: 60px) {
[m-n~='f3@x10-60'] {
font-size: 3px;
}
}
@media (min-width: 992px) {
[m-n~='f30@992-'] {
font-size: 30px;
}
}
@media (max-height: 600px) {
[m-n~='f40@x600'] {
font-size: 40px;
}
}
```
### Essences of styles
В MN эссенция стиля - это именованная атомарная абстракция с набором опций, на основе которых генерируются стили.
Эти опции включают:
* атрибуты стилей;
* приоритет в ранжировании;
* массив cелекторов, которые будут конкатенироваться к целевым селекторам;
* массив имен примешиваемых эссенций;
* массив имен эссенций, от которых наследуется текущая эссенция;
* ассоциативный массив дочерних эссенций;
* ассоциативный массив эссенций для конкретных медиа-запросов.
Эссенции могут быть двух типов:
* статические;
* динамические.
Статические эссенции задаются путем установки опций эссенции напрямую.
Динамические эссенции задаются путем установки функции генерирующей опции эссенции.
Как создаются эссенции стилей:
```js
// Статическая эссенция
mn('btnTheme', {
//priority: 10, - можно задать приоритет эссенции
//exts: [ 'dn250' /*, ... */ ], - так можно наследовать свойства других эссенций, аналогично @extend в SASS
//include: [ 'dn250' /*, ... */ ], - так можно примешивать свойства других эссенций, аналогично @include в SASS
style: { //здесь указываем стили эссенции
fontSize: '16px',
display: 'inline-block',
borderRadius: '3px',
overflow: 'hidden',
position: 'relative',
cursor: 'pointer'
},
childs: { //здесь мы можем добавлять определения для дочерних/вложенных элементов эссенции
inner: { // inner - это просто именованное значение дочернего элемента для навигации по вложенным элементам
selectors: [ ' .btn-inner' ], // здесь можно задать селекторы дочернего элемента
//priority: 10, - приоритет можно задать дочерним элементам эссенции
style: { //здесь указываем стили дочернего элемента эссенции
width: '200px',
maxWidth: '100%',
color: '#FFF',
padding: '0px 15px',
position: 'relative',
height: '45px',
borderColor,
borderStyle: 'solid',
borderWidth: '0px',
borderBottomWidth: '3px'
}
//,childs: { ... } - вложенностей может быть сколько угодно
}
//,other: { ... } - другой дочерний элемент
},
media: {
print: {
style: {
display: none;
}
},
//sm ...
}
});
```
Есть возможность устанавливать/менять атрибуты дочерних элементов эссенции, например, таким образом:
```js
mn('btnTheme.inner', {
style: {
width: '250px'
}
});
```
Пример того, каким образом может быть задекларирована эссенция ``` tbl ``` :
```js
mn('tbl', {
style: {display: 'table'},
childs: {
cell: {
selectors: [ '>*' ],
style: {
display: 'table-cell',
verticalAlign: 'middle'
}
}
}
});
```
или так:
```js
mn('tbl', {
style: {display: 'table'}
});
mn('tbl.cell', {
selectors: [ '>*' ],
style: {
display: 'table-cell',
verticalAlign: 'middle'
}
});
```
Работает это следующим образом:
Example 1.
Вы просто пишите в разметку:
```html
<div m-n="tbl">
<div>текст</div>
</div>
```
CSS для этой разметки генерируется автоматически:
```css
[m-n~='tbl']>*{display:table-cell;vertical-align:middle}
[m-n~='tbl']{display:table}
```
Example 2.
Как это работает с контекстами эссенций:
```html
<div m-n="tbl>.example2__item">
<div class="example2__item">
<div>текст</div>
</div>
<div class="example2__item">
<div>текст</div>
</div>
</div>
```
Сгенерированный CSS:
```css
[m-n~='tbl>.example2__item'] .example2__item>*{display:table-cell;vertical-align:middle}
[m-n~='tbl>.example2__item'] .example2__item{display:table}
```
Example 3.
Практический пример:
```html
<div m-n="mb10 lh">
<a class="example__button" m-n="tbl w200 h50 tc cF bg0">
<div>центрированный текст</div>
</a>
</div>
```
Сгенерированный CSS:
```css
[m-n~='lh']{line-height:1}
[m-n~='bg0']{background:rgba(0,0,0,1)}
[m-n~='cF']{color:rgba(255,255,255,1)}
[m-n~='tc']{text-align:center}
[m-n~='tbl']>*{display:table-cell;vertical-align:middle}
[m-n~='tbl']{display:table}
[m-n~='h50']{height:50px}
[m-n~='w200']{width:200px}
[m-n~='mb10']{margin-bottom:10px}
```
### Dynamic essences
(Обработчики, генерирующие стили)
На вход функций, которые Вы задаете для генерации эссенций стилей, подставляются параметры извлеченные при предварительном парсинге строки эссенции в результате сопоставления строки с последовательностью шаблонов:
1. ``` ^([a-z]+):name(.*?):suffix$ ```
2. ``` ^(.*?):suffix(-i):ni$ ```
3. ``` ^(([A-Z][a-z]+):camel|((\\-):negative?[0-9]+):num):value([a-z%]+):unit?(.*?):other?$ ```
```js
params.ni || (params.ni = '');
params.i = params.ni ? '' : '!important';
```
PS: см. функцию **mn-utils/routeParseProvider**
#### Generating the essences of styles
Example 1:
INPUT:
```html
<div m-n="p20 mb20 dt5 br2">...</div>
```
```js
mn('p', p => {
return {
style: {
padding: (p.num || '0') + (p.unit || 'px') + p.i
}
};
});
mn('mb', p => {
return {
style: {
marginBottom: (p.num || '0') + (p.unit || 'px') + p.i
}
};
});
mn('dt', p => {
return {
style: {
top: (p.num || '0') + (p.unit || 'px') + p.i
}
};
});
mn('br', p => {
return {
style: {
borderRightWidth: (p.num || '0') + (p.unit || 'px') + p.i
}
};
});
```
OUTPUT:
```css
[m-n~='p10']{padding:10px}
[m-n~='mb20']{margin-bottom:20px}
[m-n~='dt5']{top:5px}
[m-n~='br2']{border-right-width:2px}
```
Example 2:
Обработчик:
```js
mn('x', p => {
return {
style: {
transform: 'translate(' + ((p.x || '0') + (p.xu || 'px')) + ',' +
((p.y || '0') + (p.yu || 'px')) + ')' +
(p.s ? (' scale(' + (0.01 * p.s) + ')') : '') + p.i
}
};
}, '^(-?[0-9]+):x?(%):xu?([yY](-?[0-9]+):y(%):yu?)?([sS]([0-9]+):s)?$');
```
```html
<div m-n="x10y5">...</div>
```
```css
[m-n~='x10y5']{
-khtml-transform:translate(10px,5px);
-ms-transform:translate(10px,5px);
-o-transform:translate(10px,5px);
-moz-transform:translate(10px,5px);
-webkit-transform:translate(10px,5px);
transform:translate(10px,5px)
}
```
```html
<div m-n="x12">...</div>
```
```css
[m-n~='x12']{
-khtml-transform:translate(12px,0px);
-ms-transform:translate(12px,0px);
-o-transform:translate(12px,0px);
-moz-transform:translate(12px,0px);
-webkit-transform:translate(12px,0px);
transform:translate(12px,0px)
}
```
```html
<div m-n="x0y20%">...</div>
```
```css
[m-n~='x0y20%']{
-khtml-transform:translate(0px,20%);
-ms-transform:translate(0px,20%);
-o-transform:translate(0px,20%);
-moz-transform:translate(0px,20%);
-webkit-transform:translate(0px,20%);
transform:translate(0px,20%)
}
```
```html
<div m-n="x0y20">...</div>
```
```css
[m-n~='x0y20']{
-khtml-transform:translate(0px,20px);
-ms-transform:translate(0px,20px);
-o-transform:translate(0px,20px);
-moz-transform:translate(0px,20px);
-webkit-transform:translate(0px,20px);
transform:translate(0px,20px)
}
```
```html
<div m-n="x7%y20%">...</div>
```
```css
[m-n~='x7%y20%']{
-khtml-transform:translate(7%,20%);
-ms-transform:translate(7%,20%);
-o-transform:translate(7%,20%);
-moz-transform:translate(7%,20%);
-webkit-transform:translate(7%,20%);
transform:translate(7%,20%)
}
```
```html
<div m-n="x0y20s90">...</div>
```
```css
[m-n~='x0y20s90']{
-webkit-transform:translate(0px,20px) scale(0.9);
-moz-transform:translate(0px,20px) scale(0.9);
-o-transform:translate(0px,20px) scale(0.9);
-ms-transform:translate(0px,20px) scale(0.9);
-khtml-transform:translate(0px,20px) scale(0.9);
transform:translate(0px,20px) scale(0.9)
}
```
### Auto prefixes
Вы можете настроить авто-подстановку префиксов для кроссбраузерности верстки, добавив имена свойств стилей в карту префиксов таким образом:
```js
mn.propertiesStringify.prefixedAttrs.transform = true;
mn.propertiesStringify.prefixedAttrs.transitionDuration = true;
mn.propertiesStringify.prefixedAttrs.pointerEvents = true;
mn.propertiesStringify.prefixedAttrs.userSelect = true;
mn.propertiesStringify.prefixedAttrs.filter = true;
mn.propertiesStringify.prefixedAttrs.boxSizing = true;
```
либо так:
```js
mn.utils.extend(mn.propertiesStringify.prefixedAttrs, {
transform: true,
transitionDuration: true,
pointerEvents: true,
userSelect: true,
filter: true,
boxSizing: true
});
```
, но лучше так:
```js
mn.utils.flags([
'transform', 'transitionDuration', 'pointerEvents', 'userSelect', 'filter', 'boxSizing'
], mn.propertiesStringify.prefixedAttrs);
```
Указать какие именно префиксы должны подставляться Вы можете так:
```js
mn.utils.flags(['-webkit-', '-moz-', '-o-', '-ms-', '-khtml-' ], mn.propertiesStringify.prefixes);
```
### States
Состояние - в MN это часть записи нотации после двоеточия(``` : ```), которой может соответствовать аналогичные псевдоселекторы в терминах CSS.
В MN мы стараемся использовать сокращенные записи. Так для одного имени состояния в MN можно указать несколько произвольных селекторов.
Input:
```html
<i
class="ion-chevron-right"
m-n="x10:h cF00:a f16:(h|a)"
></i>
```
```js
mn.utils.extend(mn.states, {
h: [ ':hover' ],
a: [ ':active', '.active' ]
});
```
Output:
```css
[m-n~='x10:h']:hover{
-khtml-transform:translate(10px,0px);
-ms-transform:translate(10px,0px);
-o-transform:translate(10px,0px);
-moz-transform:translate(10px,0px);
-webkit-transform:translate(10px,0px);
transform:translate(10px,0px)
}
[m-n~='cF00:a']:active,
[m-n~='cF00:a'].active{
color:rgba(255,0,0,1)
}
[m-n~='f16:(h|a)']:hover,
[m-n~='f16:(h|a)']:active,
[m-n~='f16:(h|a)'].active{
font-size: 16px;
}
```
Если Вы укажете какое-либо иное незадекларированное состояние, то оно выводится как есть:
```css
f16:hz ->
[m-n~='f16:hz']:hz{font-size: 16px;}
f16:hover ->
[m-n~='f16:hover']:hover{font-size: 16px;}
```
*Вы можете параметризовать состояния через квадратные скобки:*
```js
mn.states.n = [ ':nth-child' ];
```
```css
f16:n[3n+2] ->
[m-n~='f16:n[3n+2]']:nth-child(3n+2){font-size: 16px;}
```
PS: В связи с тем, что круглые скобки являются служебными символами MN, необходимыми для группировки подстрок, то вместо них применяются квадратные скобки.
Вы можете без проблем в нотации записать псевдокласс отрицания:
```css
f16:not[.active] ->
[m-n~='f16:not[.active]']:not(.active){font-size: 16px;}
f16:not[[type=number]] ->
[m-n~='f16:not[[type=number]]']:not([type=number]){font-size: 16px;}
```
Вы можете указать в нотации несколько состояний:
```css
f16:(hover|active) ->
[m-n~='f16:(hover|active)']:hover, [m-n~='f16:(hover|active)']:active{font-size: 16px;}
```
В состояниях предусмотрена возможность использования нестандартных псевдоклассов в качестве синонимов:
Input:
```js
mn.states.i = [
'::-webkit-input-placeholder',
'::-moz-placeholder',
':-ms-input-placeholder',
'::placeholder'
];
```
```html
<input m-n="cA:i" placeholder="имя"/>
```
Output:
```css
[m-n~='cA:i']::-webkit-input-placeholder{color:rgb(170,170,170)}
[m-n~='cA:i']::-moz-placeholder{color:rgb(170,170,170)}
[m-n~='cA:i']:-ms-input-placeholder{color:rgb(170,170,170)}
[m-n~='cA:i']::placeholder{color:rgb(170,170,170)}
```
PS: селекторы с нестандартными псевдоклассами и браузерными префиксами для валидности автоматически разбивается на отдельные каскадные блоки.
### Parent/child selectors
Разделитель родительских селекторов: ``` < ```
Например, для записи ``` bgF00<.active ``` генерируется следующий селектор:
```css
.active [m-n~='bgF00<.active'] { /* ... */ }
```
Так мы можем указать для текущего элемента при наличии какого родительского элемента будет отображаться стиль эссенции ``` bgF00 ```.
Разделитель дочерних селекторов: ``` > ```
С дочерними селекторами всё точно также как и с родительскими, только наоборот.
Например, для записи ``` bgF00>.active ``` генерируется следующий селектор:
```css
[m-n~='bgF00>.active'] .active { /* ... */ }
```
### Depth
Для задания определенной глубины вложенности мы можем подставить число перед селектором, например:
```css
/* bgF00<1.active -> */
.active>[m-n~='bgF00<1.active'] { /* ... */ }
/* bgF00<2.active -> */
.active>*>[m-n~='bgF00<2.active'] { /* ... */ }
/* bgF00<3.active -> */
.active>*>*>[m-n~='bgF00<3.active'] { /* ... */ }
```
Если нужно чтобы стили эссенции были активны при наличии какого-либо селектора(в частности класс ``` active ```) на текущем элементе:
```css
/* bgF00<0.active -> */
.active[m-n~='bgF00<0.active'] { /* ... */ }
```
Если есть отрицательный знак, то мы получим распространение стиля эссенции на дочернии элементы:
```css
/* bgF00<-1.active -> */
[m-n~='bgF00<-1.active']>.active { /* ... */ }
/* bgF00<-2.active -> */
[m-n~='bgF00<-2.active']>*>.active { /* ... */ }
```
Вы можете игнорировать разделитель.
Если нужно чтобы стили эссенции были активны при наличии какого-либо селектора на текущем элементе (в частности класс active), то Вы можете писать более лаконично и получать на выходе желаемое:
```css
/* bgF00.active -> */
[m-n~='bgF00.active'].active { /* ... */ }
```
### Complex selectors
Всё вышеперечисленное аналогично можем применять и для других селекторов с атрибутами:
```css
/* bgF00>[type=text] -> */
[m-n~='bgF00>[type=text]'] [type=text] { /* ... */ }
/* bgF00[type=text] -> */
[m-n~='bgF00[type=text]'][type=text] { /* ... */ }
```
Пример более сложного селектора:
```css
/* bgF00.theme1.active -> */
[m-n~='bgF00.theme1.active'].theme1.active { /* ... */ }
```
Разделители подразумевают, что Вы можете совместно указать сколько угодно родительских и дочерних элементов и состояний в контексте эссенции:
```css
/* bgF00.active<.md>.anyChild -> */
.md [m-n~='bgF00.active<.md>.anyChild'].active .anyChild { /* ... */ }
```
Example 1:
Input:
```html
<a href="#">
<i
class="ion-chevron-right"
m-n="x10<a:h cF00:a"
></i>
</a>
<div m-n="c0F0:a<.parent1">...</div>
<div m-n="bg02<.parent1<.parent2">...</div>
<div m-n="c065:a<0.parent1">...</div>
<div m-n="bgD852<3.parent1<.parent2:h">...</div>
```
Output:
```css
[m-n~='cF00:a'].active,
[m-n~='cF00:a']:active{
color:rgba(255,0,0,1)
}
a:hover [m-n~='x10<a:h']{
-khtml-transform:translate(10px,0px);
-ms-transform:translate(10px,0px);
-o-transform:translate(10px,0px);
-moz-transform:translate(10px,0px);
-webkit-transform:translate(10px,0px);
transform:translate(10px,0px)
}
.parent1 [m-n~='c0F0:a<.parent1']:active,
.parent1 [m-n~='c0F0:a<.parent1'].active{
color:rgba(0,255,0,1)
}
.parent1[m-n~='c065:a<0.parent1']:active,
.parent1[m-n~='c065:a<0.parent1'].active{
color:rgba(0,102,85,1)
}
.parent2 .parent1 [m-n~='bg02<.parent1<.parent2']{
background-color:rgba(0,0,0,0.13333333333333333)
}
.parent2:hover .parent1>*>*>[m-n~='bgD852<3.parent1<.parent2:h']{
background-color:rgba(221,136,85,0.13333333333333333)
}
```
Example 2:
Input:
```html
<div m-n="(sq50|bg0)<2.anyClass"></div>
<div m-n="(w50|h5|bg00F8)>5.innerItem"></div>
```
Output:
```css
.anyClass>*>[m-n~='(sq50|bg0)<2.anyClass']{
background:rgba(0,0,0,1)
}
.anyClass>*>[m-n~='(sq50|bg0)<2.anyClass']{
width:50px;
height:50px
}
[m-n~='(w50|h5|bg00F8)>5.innerItem']>*>*>*>*>.innerItem{
background:rgba(0,0,255,0.5333333333333333)
}
[m-n~='(w50|h5|bg00F8)>5.innerItem']>*>*>*>*>.innerItem{
height:5px
}
[m-n~='(w50|h5|bg00F8)>5.innerItem']>*>*>*>*>.innerItem{
width:50px
}
```
### Essences assignment
(Example with container)
Связывание селекторов с эссенциями стилей
Для наглядности рассмотрим приближенный синтетический пример имплементации контейнера из Twitter Bootstrap 3.
Так это делается вручную с помощью CSS:
```css
.container {
margin-right: auto;
margin-left: auto;
padding-left: 15px;
padding-right: 15px
}
@media (min-width: 768px) {
.container {
width: 750px
}
}
@media (min-width: 992px) {
.container {
width: 970px
}
}
@media (min-width: 1200px) {
.container {
width: 1170px
}
}
```
Для того, чтобы сделать тоже самое с MN можно пойти разными путями в зависимости от Ваших нужд.
Несколько лаконичных способов:
Example 1.
```js
mn.assign('.container', '(mhAuto|ph15|w750@m2-|w970@d|w1170@d2)');
```
Example 2. Без использования предустановленных синонимов по умолчанию для медиа-запросов:
```js
mn.assign('.container', '(mhAuto|ph15|w750@768-|w970@992-|w1170@1200-)');
```
Example 3. Если мы хотим иметь возможность переиспользовать стили контейнера в других селекторах,
то мы можем декларировать контейнер как эссенцию:
```js
mn('container', '(mhAuto|ph15|w750@m2-|w970@d|w1170@d2)');
```
Таким образом будет задействована вся мощь минималистической нотации, для которой селекторы генерируются автоматически:
Input:
```html
<div class="container">...</div>
<div class="container>.child">
<div class="child"></div>
<div class="child"></div>
</div>
<div class="parent">
<div class="container<.parent">...</div>
</div>
```
Output:
```css
.container, .container\>\.child .child, .parent .container\<\.parent {
margin-right: auto;
margin-left: auto;
}
.container, .container\>\.child .child, .parent .container\<\.parent {
padding-left: 15px;
padding-right: 15px
}
@media (min-width: 768px) {
.container, .container\>\.child .child, .parent .container\<\.parent {
width: 750px
}
}
@media (min-width: 992px) {
.container, .container\>\.child .child, .parent .container\<\.parent {
width: 970px
}
}
@media (min-width: 1200px) {
.container, .container\>\.child .child, .parent .container\<\.parent {
width: 1170px
}
}
```
Этот приведенный пример
```js
mn('container', '(mhAuto|ph15|w750@m2-|w970@d|w1170@d2)');
```
является сокращенным способом такой декларации:
```js
mn('container', {
exts: '(mhAuto|ph15|w750@m2-|w970@d|w1170@d2)'
});
```
В приведенных выше примерах декларация эссенции осуществляется на основе других более атомарных эссенций.
Таким образом мы можем многократно переиспользовать однажды созданные эссенции стилей в новых эссенциях.
Вместо этого мы также могли декларировать эссенцию тем же способом, что и более атомарные эссенции, на которых мы основывались до этого.
Допустим, у нас пока нет тех атомарных эссенций, которые мы использовали в прошлых примерах, и нам было лень их писать до этого момента,
либо мы руководствуемся какими то другими причинами. Тогда мы можем декларировать эссенцию контейнера таким способом:
```js
mn('container', {
style: {
marginRight: 'auto',
marginLeft: 'auto',
paddingLeft: '15px',
paddingRight: '15px'
},
media: {
/*
'(min-width: 768px)': {
style: {
width: '750px'
}
},
*/
// with synonyms:
'm2-': {
style: {
width: '750px'
}
},
d: {
style: {
width: '970px'
}
},
d2: {
style: {
width: '1170px'
}
}
}
});
```
### Priority multiplier
В MN есть возможность манипуляции приоритетом стилей, которая позволяет лаконично перекрывать влияние некоторых других CSS правил.
Format:
```
{notation}*{multiplier:([0-9]+)}
```
Example 1:
```html
<div m-n="h40*3"></div>
```
Output:
```css
[m='h40*3'][m='h40*3'][m='h40*3'] {
height: 40px;
}
```
Example 2:
```html
<div m-n="h40.isActive*2"></div>
```
Output:
```css
[m='h40.isActive*2'][m='h40.isActive*2'].isActive {
height: 40px;
}
```
Example 3:
```html
<div m-n="h40>.child1>.child2*3"></div>
```
Output:
```css
[m='h40>.child1>.child2*3'][m='h40>.child1>.child2*3'][m='h40>.child1>.child2*3'] .child1 .child2 {
height: 40px;
}
```