Add presentation and insomnia workspace

This commit is contained in:
Andrey Mayorov 2018-07-31 12:28:15 +03:00
parent f0d69cbdae
commit 23a68a3c8e
9 changed files with 1340 additions and 0 deletions

189
01-networks.md Normal file
View File

@ -0,0 +1,189 @@
title: Networks
class: animation-fade
layout: true
---
class: impact
# Компьютерные сети
## и их протоколы
---
# Зачем?
--
## Совместное пользование ресурсами
--
* информационными
--
* вычислительными
---
# Что это?
--
.col-4[
* _Сеть_ (network)
]
.col-8[
Множество _узлов_, обменивающихся анными_ согласно общеизвестным _протоколам_
]
--
.col-4[
* _Узел_ (node)
]
.col-8[
Любое устройство, производящее, перенаправляющее или принимающее _данные_
]
--
.col-4[
* _Хост_ (host)
]
.col-8[
Узел, предоставляющий _ресурсы_ и _сервисы_, и обладающий определённым _адресом_
]
--
.col-4[
* ротокол_ (protocol)
]
.col-8[
Набор _правил_, которые требуют исполнения _узлами_ для проведения обмена _данными_
]
---
# Протокол
> Protocols are to communication what programming languages are to computations.
--
* задача
--
* медиум
--
* роли участников
--
* формат данных
--
* набор сообщений
--
* порядок обмена сообщениями
---
# Интернет
> The Internet is a network of networks.
>
> <cite>[RFC1122: Requirements for Internet Hosts Communication Layers](https://tools.ietf.org/html/rfc1122)</cite>
## Многоуровневый набор протоколов
--
.col-6[
* Прикладной уровень (application layer)
]
.col-6[
_HTTP_ / _SSH_ / _IMAP_ / _WebDAV_ / ...
]
--
.col-6[
* Транспортный уровень (transport layer)
]
.col-6[
_TCP_ / _UDP_ / _SCTP_
]
--
.col-6[
* Межсетевой уровень (internet layer)
]
.col-6[
_IP_ / _IPv6_ / _ICMP_ / _IPoAC_ / ...
]
--
.col-6[
* Канальный уровень (link layer)
]
.col-6[
_Ethernet_ / _802.11_ / ...
]
---
# IP over Avian Carriers <small>RFC 1149</small>
> IPoAC has been successfully implemented, but for only nine packets of data, with a packet loss ratio of 55% (due to operator error), and a response time ranging from 3000 seconds (≈54 minutes) to over 6000 seconds (≈1.77 hours).
>
> <cite>[The informal report from the RFC 1149 event](https://www.blug.linux.no/rfc1149/writeup/)</cite>
--
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Pigeon_krakow.jpg/1024px-Pigeon_krakow.jpg" style="width:50%; margin: 0 25%;"/>
---
# Модель OSI
--
### 7. Прикладной уровень
### 6. Уровень представления данных
### 5. Сессионный уровень
### 4. Транспортный уровень
### 3. Сетевой уровень
### 2. Канальный уровень
### 1. Физический уровень
---
class: impact
# Пока всё
## Спасибо за внимание

85
01-tasks.md Normal file
View File

@ -0,0 +1,85 @@
title: Networks
class: animation-fade
layout: true
---
# Подготовка
* [Wireshark](https://www.wireshark.org/), инструмент для перехвата и анализа сетевого трафика
```
brew cask install wireshark
```
* [Netcat](http://netcat.sourceforge.net/), инструмент для управления и обмена сообщениями по протоколам транспортного уровня
```
brew install netcat
```
---
# Задача 1
Проанализировать трафик по протоколу DHCP в момент подсоединения к WLAN-сети и сделать вывод о том:
* какие задачи решаются в процессе,
* кто участники,
* какими сообщениями они обмениваются.
--
Capture filter:
```
udp
```
Display filter:
```
udp.port == 67 or udp.port == 68
```
---
# Задача 2
Проанализировать трафик по протоколу DNS в процессе соединения с github.com.
Вопросы к аналитике такие же, как и в предыдущих задачах.
--
Capture filter:
```
udp port 53
```
---
# Задача 3
Проанализировать трафик по протоколу TCP. Один из вас выступает в роли _слушателя_, двое других в роли _клиентов_.
Вопросы к аналитике такие же, как и в предыдущих задачах.
--
```
netcat --verbose -l -p 8888
```
```
netcat --verbose -c ${ADDRESS} 8888
```
--
Capture filter:
```
tcp port 8888
```

391
02-http-rest.md Normal file
View File

@ -0,0 +1,391 @@
title: Networks
class: animation-fade
layout: true
---
class: impact
# HTTP
## и сын его REST
---
# Зачем HTTP?
--
* Чтобы <big><strong>Г̹̲͇̾̚И̩̙͔̼̻̠̊͛П̫ͦ̐Е̣̊͛̌̏ͨР̮͎̱̦̗ͨ̿̐̉М͎̮̀͒̔ͫ̍Е͈̼̳̬ͨ͊ͩ̎̎̆Д̼͖͖̲̗̒И͌̐ͧА̾̈</strong></big>
--
* _Очень много крайне различной_ информации
--
* _Много_ разных агентов c _различными_ задачами
--
* _Малый_ порог входа и участия
---
# Что такое HTTP?
По крайней мере HTTP/1.1. 😓
## Задачи
--
* Организовать обмен <big>**ГИПЕРМЕДИА**</big>
--
* Обеспечить равноправие различных агентов
--
* Дать возможность плавной эволюции протокола и систем
--
* Минимизировать порог входа
---
# Что такое HTTP?
## Участники
--
* пользователькие агенты
--
* веб-сервисы
--
* посредники
- прокси
- кэширующие сервера
- файрволлы
---
# Что такое HTTP?
## Сообщения и формат данных
--
```http
GET /user HTTP/1.1
Host: api.github.com
User-Agent: insomnia/5.16.6
Accept: application/vnd.github.v3+json
Authorization: token 17561dd75d2d4ca18162aa0ee6689ad352f7c716
```
---
# Что такое HTTP?
## Сообщения и формат данных
```http
HTTP/1.1 200 OK
Server: GitHub.com
Date: Mon, 30 Jul 2018 19:07:46 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 1173
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4999
X-RateLimit-Reset: 1532981266
Cache-Control: private, max-age=60, s-maxage=60
Vary: Accept, Authorization, Cookie, X-GitHub-OTP
ETag: "43e7e661929a522cbf07d1254805b17e"
Last-Modified: Wed, 11 Jul 2018 15:47:47 GMT
... куча байтов тела ответа ...
```
---
# Зачем REST?
--
* _Очень много_ участников
--
* _Очень часто_ появляются новые
--
* _Очень много_ способов решить задачу
--
* _Крайне мало_ средств общаться на "одном языке"
---
# Что такое REST?
--
* Клиент-серверная архитектура систем
--
* Коммуникация посредством явной передачи состояния
--
* Средства для явного, предсказуемого и безопасного кэширования
--
* Многоуровневая архитектура с разделением задач между уровнями
--
* **Унифицированный интерфейс**
---
## Унифицированный интерфейс
--
* Ресурсы и их расположения в сети
--
* Представления ресурсов
--
* Явные и понятные учатникам без предварительного знания сообщения
--
* <big><strong>Ḥ̹̮͖ͬͧ̆ͧA̦͍͕̮͊́ͦ̆ͯT̹̘̭̱̪ͫE̲͎̖͇̦͋̇̓O̬̻͕̩̣̗ͨ͑̃ͤÂ͐S̯̘̘̟̪͔̀͊́ͤ</strong></big>
---
### Ресурсы и их расположения
#### URL
```
URI = scheme:[//authority]path[?query][#fragment]
```
```
authority = [userinfo@]host[:port]
```
--
#### Примеры
* Github Repository Issues
```
https://github.com/stevemao/left-pad/issues
```
--
* Github Logged-in User Settings
```
https://github.com/settings/profile
```
---
### Представления ресурсов
```http
GET /v0/item/17621448.json?print=pretty HTTP/1.1
Host: hacker-news.firebaseio.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,ru-RU;q=0.8,ru;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
```
```http
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 697
{
"by" : "captain_perl",
"id" : 17621448,
"kids" : [ 17621675, 17621623 ],
"parent" : 17620543,
"text" : "Just for the record, I surveyed a dozen Hipchat users who used it all day in late 2016 for software development. They had zero complaints about using Hipchat.<p>My opinion of the Hipchat web client at the time was that it worked fine (no complaints from me.)<p>I believe we were on the free tier, so that was a great deal.<p>A new Eng. VP wanted to seem hip, so he switched us to Slack &quot;to ensure we were using the best tools possible.&quot;<p>Nobody said that Slack was better or added any features that were worth mentioning.",
"time" : 1532640989,
"type" : "comment"
}
```
---
### Понятные сообщения
#### Методы
--
* **GET**
Получить _представление_ ресурса, расположенного по URL.
--
В ответе присутствует ело_ с представлением ресурса.
--
езопасный_ метод.
--
_Идемпотентный_ метод.
--
Позволено _кэшировать_.
--
* **HEAD**
Получить етаданные_ ресурса, расположенного по URL.
--
В ответе отсутствует ело_ с представлением ресурса.
--
езопасный_ метод.
--
_Идемпотентный_ метод.
--
Позволено _кэшировать_.
--
* **POST**
Создать _подресурс_ в рамках расположенного по URL ресурса согласно переданному представлению.
--
В ответе присутствует ело_ с представлением созданного ресурса.
--
_Небезопасный_ метод.
--
_Неидемпотентный_ метод.
--
Позволено _кэшировать_.
---
### Понятные сообщения
#### Методы
* **PUT**
Задать _состояние_ расположенного по URL ресурса согласно переданному представлению.
--
В ответе присутствует ело_ с представлением созданного или изменённого ресурса.
--
_Небезопасный_ метод.
--
_Идемпотентный_ метод.
--
Недопустимо _кэшировать_.
--
* **PATCH**
Внести астичные изменения_ в состояние расположенного по URL ресурса согласно переданному представлению.
--
В ответе присутствует ело_ с представлением созданного или изменённого ресурса.
--
_Небезопасный_ метод.
--
_Неидемпотентный_ метод.
--
Недопустимо _кэшировать_.
--
* **DELETE**
Удалить расположенный по URL ресурс.
--
В ответе присутствует ело_ с представлением созданного или изменённого ресурса.
--
_Небезопасный_ метод.
--
_Идемпотентный_ метод.
--
Недопустимо _кэшировать_.
---
### Понятные сообщения
#### Классы ответов
* **1XX Success**
_Информация для ознакомления_. Обычно используется для согласования обновления прикладных протоколов.
--
* **2XX Success**
_Успех_. Запрошенное агентом действие было корректно сформулировано, получено и успешно обработано.
--
* **3XX Redirection**
_Необходимы дополнительные действия_, чаще всего используется для перенаправления агента для совершения действия над ругим_ ресурсом.
---
### Понятные сообщения
#### Классы ошибок
* **4XX Client Error**
_Агент допустил ошибку_ в процессе формирования запроса, его отправки или в результате попытки проведения действия, неприменимого к текущему состоянию ресурса. Чтобы добиться успеха, агент имеет возможность _скорректировать_ свой запрос.
--
* **5XX Server Error**
_Сервер не в состоянии обработать запрос_ в результате какой-либо ошибки. Ошибочное состояние может быть _постоянным_ или ременным_ (_транзиентная_ ошибка). Обычно агент не имеет возможности в итоге добиться успеха.
---
## HATEOAS
**H**ypermedia **a**s **t**he **e**ngine **o**f **a**pplication **s**tate
> When I say hypertext, I mean the simultaneous presentation of information and controls such that the information becomes the affordance through which the user (or automaton) obtains choices and selects actions.
>
> <cite>Roy Fielding в своём [блоге](http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven#comment-718)</cite>
--
### [https://apidocs.goabout.com](https://apidocs.goabout.com)
---
class: impact
# Ну и хватит
## всё равно в REST никто нормально не может

32
02-tasks.md Normal file
View File

@ -0,0 +1,32 @@
title: Networks
class: animation-fade
layout: true
---
# Подготовка
* [Insomnia](https://insomnia.rest/), инструмент для организации полуавтоматизированного взаимодействия с REST API вебсервиса
```
brew cask install insomnia
```
---
# Задача 1
Собрать Insomnia workspace, работающий с Github API, чтобы решить следующие задачи:
* Добавить своего коллегу как оллаборатора_ в репозиторий.
* Отправить комментарий в _проблему_ в репозитории.
* Добавить етку_ в репозиторий.
* Добавить эту етку_ к _проблеме_.
* Залочить _проблему_ с какой-либо причиной.
* Закрыть _проблему_.
...Ну или рассказать, почему что-то из этого не удалось выполнить.
Репозиторий: `rbkmoney/camp-net-rest-bite`
Не забудьте выписать себе _Authorization Token_ и указать его в workspace environment.

View File

@ -0,0 +1,318 @@
{
"_type": "export",
"__export_format": 3,
"__export_date": "2018-07-30T19:02:43.978Z",
"__export_source": "insomnia.desktop.app:v5.16.6",
"resources": [
{
"_id": "wrk_d31222b058e2482abb1837ed4b7ccf84",
"created": 1532971917206,
"description": "",
"modified": 1532971917206,
"name": "Insomnia",
"parentId": null,
"_type": "workspace"
},
{
"_id": "env_0224eda7455f4b4d939064dda03891d3",
"color": null,
"created": 1532971917243,
"data": {
"repo": "swagger-codegen",
"token": "???"
},
"isPrivate": false,
"modified": 1532976731466,
"name": "New Environment",
"parentId": "wrk_d31222b058e2482abb1837ed4b7ccf84",
"_type": "environment"
},
{
"_id": "jar_258273397de14f1cbf79377393f8d2ee",
"cookies": [],
"created": 1532971917318,
"modified": 1532977295262,
"name": "Default Jar",
"parentId": "wrk_d31222b058e2482abb1837ed4b7ccf84",
"_type": "cookie_jar"
},
{
"_id": "req_b9c04ee7d6274bf59e9db33a8f745c4d",
"authentication": {
"prefix": "token",
"token": "{{ token }}",
"type": "bearer"
},
"body": {},
"created": 1532974495022,
"description": "",
"headers": [
{
"disabled": false,
"id": "pair_cd4708187e3649c588f60ff9bc40c109",
"name": "Accept",
"value": "application/vnd.github.v3+json"
}
],
"isPrivate": false,
"metaSortKey": -1532972198284,
"method": "GET",
"modified": 1532976083225,
"name": "me",
"parameters": [],
"parentId": "wrk_d31222b058e2482abb1837ed4b7ccf84",
"settingDisableRenderRequestBody": false,
"settingEncodeUrl": true,
"settingRebuildPath": true,
"settingSendCookies": true,
"settingStoreCookies": true,
"url": "https://api.github.com/user",
"_type": "request"
},
{
"_id": "req_e46a7dfa071140b0a15ef3e09315eccd",
"authentication": {},
"body": {},
"created": 1532975103084,
"description": "",
"headers": [
{
"disabled": true,
"id": "pair_0786a6abdb7748b1ab15a14d334560e1",
"name": "If-Modified-Since",
"value": "{% response 'header', 'req_e46a7dfa071140b0a15ef3e09315eccd', 'Last-Modified' %}"
}
],
"isPrivate": false,
"metaSortKey": -1532972198234,
"method": "GET",
"modified": 1532976080313,
"name": "my avatar",
"parameters": [],
"parentId": "wrk_d31222b058e2482abb1837ed4b7ccf84",
"settingDisableRenderRequestBody": false,
"settingEncodeUrl": true,
"settingRebuildPath": true,
"settingSendCookies": true,
"settingStoreCookies": true,
"url": "{% response 'body', 'req_b9c04ee7d6274bf59e9db33a8f745c4d', '$.avatar_url' %}",
"_type": "request"
},
{
"_id": "req_aad4a5acaeb74a19bfa23bfe2e6a8de4",
"authentication": {
"prefix": "token",
"token": "{{ token }}",
"type": "bearer"
},
"body": {},
"created": 1532975483506,
"description": "",
"headers": [
{
"disabled": false,
"id": "pair_cd4708187e3649c588f60ff9bc40c109",
"name": "Accept",
"value": "application/vnd.github.v3+json"
}
],
"isPrivate": false,
"metaSortKey": -1532972198184,
"method": "GET",
"modified": 1532976076745,
"name": "my precious repo",
"parameters": [],
"parentId": "wrk_d31222b058e2482abb1837ed4b7ccf84",
"settingDisableRenderRequestBody": false,
"settingEncodeUrl": true,
"settingRebuildPath": true,
"settingSendCookies": true,
"settingStoreCookies": true,
"url": "https://api.github.com/repos/keynslug/{{ repo }}",
"_type": "request"
},
{
"_id": "req_c85cec8b3ddd43839fdc934d3d308da0",
"authentication": {
"prefix": "token",
"token": "{{ token }}",
"type": "bearer"
},
"body": {},
"created": 1532975797167,
"description": "",
"headers": [
{
"disabled": false,
"id": "pair_cd4708187e3649c588f60ff9bc40c109",
"name": "Accept",
"value": "application/vnd.github.v3+json"
}
],
"isPrivate": false,
"metaSortKey": -1532972198134,
"method": "GET",
"modified": 1532976074410,
"name": "its source repo",
"parameters": [],
"parentId": "wrk_d31222b058e2482abb1837ed4b7ccf84",
"settingDisableRenderRequestBody": false,
"settingEncodeUrl": true,
"settingRebuildPath": true,
"settingSendCookies": true,
"settingStoreCookies": true,
"url": "{% response 'body', 'req_aad4a5acaeb74a19bfa23bfe2e6a8de4', '$.source.url' %}",
"_type": "request"
},
{
"_id": "req_c8a2b47040244f8082b304e7701ce1bc",
"authentication": {},
"body": {},
"created": 1532975897460,
"description": "",
"headers": [
{
"id": "pair_3439f16e83e745d0856996f5cffd5df1",
"name": "Accept",
"value": "text/plain"
}
],
"isPrivate": false,
"metaSortKey": -1532972198084,
"method": "GET",
"modified": 1532976070946,
"name": "its plain text representation",
"parameters": [],
"parentId": "wrk_d31222b058e2482abb1837ed4b7ccf84",
"settingDisableRenderRequestBody": false,
"settingEncodeUrl": true,
"settingRebuildPath": true,
"settingSendCookies": true,
"settingStoreCookies": true,
"url": "{% response 'body', 'req_c85cec8b3ddd43839fdc934d3d308da0', '$.html_url' %}",
"_type": "request"
},
{
"_id": "req_742362ec71204cba9d62cba750e7ed74",
"authentication": {
"prefix": "token",
"token": "{{ token }}",
"type": "bearer"
},
"body": {},
"created": 1532976133888,
"description": "",
"headers": [
{
"disabled": false,
"id": "pair_cd4708187e3649c588f60ff9bc40c109",
"name": "Accept",
"value": "application/vnd.github.v3+json"
}
],
"isPrivate": false,
"metaSortKey": -1532972198034,
"method": "GET",
"modified": 1532976539625,
"name": "its commits",
"parameters": [],
"parentId": "wrk_d31222b058e2482abb1837ed4b7ccf84",
"settingDisableRenderRequestBody": false,
"settingEncodeUrl": true,
"settingRebuildPath": true,
"settingSendCookies": true,
"settingStoreCookies": true,
"url": "{% response 'body', 'req_c85cec8b3ddd43839fdc934d3d308da0', '$.url' %}/commits",
"_type": "request"
},
{
"_id": "req_12c354a5f16246e1bb6aac71ee417a6d",
"authentication": {
"prefix": "token",
"token": "{{ token }}",
"type": "bearer"
},
"body": {},
"created": 1532976545159,
"description": "",
"headers": [
{
"disabled": false,
"id": "pair_cd4708187e3649c588f60ff9bc40c109",
"name": "Accept",
"value": "application/vnd.github.v3+json"
},
{
"disabled": true,
"id": "pair_0922850b221c4918b779656da7df6906",
"name": "Accept",
"value": "application/vnd.github.v3.patch"
}
],
"isPrivate": false,
"metaSortKey": -1532972197984,
"method": "GET",
"modified": 1532976845289,
"name": "its latest commit as patch",
"parameters": [],
"parentId": "wrk_d31222b058e2482abb1837ed4b7ccf84",
"settingDisableRenderRequestBody": false,
"settingEncodeUrl": true,
"settingRebuildPath": true,
"settingSendCookies": true,
"settingStoreCookies": true,
"url": "{% response 'body', 'req_742362ec71204cba9d62cba750e7ed74', '$[0].url' %}",
"_type": "request"
},
{
"_id": "req_80a3eb59120140ec985840c24a3639fc",
"authentication": {
"prefix": "token",
"token": "{{ token }}",
"type": "bearer"
},
"body": {},
"created": 1532976988716,
"description": "",
"headers": [
{
"disabled": false,
"id": "pair_cd4708187e3649c588f60ff9bc40c109",
"name": "Accept",
"value": "application/vnd.github.v3+json"
},
{
"disabled": true,
"id": "pair_e5e12ae5820749d59f4ff4d8b6034ee8",
"name": "Accept",
"value": "application/vnd.github.v3.html+json"
}
],
"isPrivate": false,
"metaSortKey": -1532972197934,
"method": "GET",
"modified": 1532977198553,
"name": "its issues",
"parameters": [
{
"id": "pair_92fb1475a0274533ba274d458cece597",
"name": "state",
"value": "open"
},
{
"id": "pair_3e87b89093ec4344beccb7f546ceb32d",
"name": "labels",
"value": "Client: Erlang"
}
],
"parentId": "wrk_d31222b058e2482abb1837ed4b7ccf84",
"settingDisableRenderRequestBody": false,
"settingEncodeUrl": true,
"settingRebuildPath": true,
"settingSendCookies": true,
"settingStoreCookies": true,
"url": "{% response 'body', 'req_c85cec8b3ddd43839fdc934d3d308da0', '$.url' %}/issues",
"_type": "request"
}
]
}

63
outline.md Normal file
View File

@ -0,0 +1,63 @@
# План лекций
## Лекция 1
### Теория
> ≈ 60 минут / вышло даже немного меньше
О чём: сети, протоколы, интернет, кратко об OSI.
* Зачем нужны _сети_?
* Что такое _сеть_?
* Что такое _протокол_?
* _Интернет_ куча протоколов, спроектированных согласно общим принципам
- Четыре уровня IPS
- Кроссуровневые протоколы
+ DNS
+ ARP
- Инкапсуляция
+ OpenVPN
- Шутка про IPoAC
- Сопоставление с OSI
### Практика
> ≈ 60 минут / вышло около 90 на удивление
В основном на работу с Wireshark и анализ трафика.
1. Анализ трафика DHCP в процессе подключения к точке доступа WLAN.
2. Анализ трафика DNS в процессе визита браузера на github.com.
3. Анализ трафика TCP в процессе клиент-серверного взаимодествия с помощью netcat.
## Лекция 2
### Теория
> ≈ 50 минут
О чём: гипермедиа, задачи, участники, протокол, почему REST и его задачи.
* Зачем нам _HTTP_?
- академический уклон
- гипермедиа
- проблемы
- user agents
- intermediaries
- многозадачность
- стабильная эволюция
- всё пошло не совсем так
* Зачем нам _REST_?
- _архитектурный стиль_
- проблемы
- набор _ограничений_
- унифицированный интерфейс
- ресурсы и модели
- их представления
- глаголы, безопасность и идемпотентность
- классы ошибок, общие и частные
### Практика
В основном на работу с Insomnia и анализ REST-практик в интерфейсах.

22
template/index.html Normal file
View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{{title}}</title>
{{{style}}}
<script src="remark.min.js"></script>
<script>
function create() {
return remark.create({
{{{source}}},
ratio: '16:9',
highlightLines: true,
countIncrementalSlides: false,
highlightStyle: 'monokai'
});
}
</script>
</head>
<body onload="slideshow = create()">
</body>
</html>

18
template/remark.min.js vendored Normal file

File diff suppressed because one or more lines are too long

222
template/style.scss Normal file
View File

@ -0,0 +1,222 @@
// Theme
// ---------------------------------------------------------------------------
$primary : #3F51B5;
$secondary : #009688;
$tertiary : #757575;
$light : #FFF;
$dark : #333;
$text-dark : #212121;
$text-light : $light;
$code-background : #F8F8F8;
$overlay : transparentize(#000, .5);
$font-size : 24px;
$font-size-impact : 128px;
$font : Arial, Helvetica, sans-serif;
$font-title : Arial, Helvetica, sans-serif;
$font-fixed : 'Lucida Console', Monaco, monospace;
$margin : 20px;
$iframe-scale : 1.5;
// CSS Base
// ---------------------------------------------------------------------------
* { box-sizing: border-box; }
body { font-family: $font; }
h1, h2, h3, h4, h5, h6 {
margin: 0 0 $margin 0;
font-family: $font-title;
& > small { font-size: 0.5em; }
}
h1 { color: $primary; }
h2 { color: $secondary; }
h3 { color: $tertiary; }
li { margin-bottom: .25em; };
pre, code {
text-align: left;
font-family: $font-fixed;
color: $secondary;
background: $code-background;
}
a, a:visited, a:hover, a:active { color: $text-dark; }
img { vertical-align: inherit; }
blockquote {
border-left: 8px solid;
padding-left: .5em;
color: $tertiary;
text-align: left;
margin: 1em 0;
& > p { margin: 0; }
& cite {
display: block;
font-size: 0.8em;
margin: 1em 0 0;
}
}
// Remark base
// ---------------------------------------------------------------------------
.remark-code { font-size: .9em; }
.remark-container { background: $dark; }
.remark-slide-scaler { box-shadow: none; }
.remark-notes { font-size: 1.5em; }
.remark-slide-content {
font-size: $font-size;
padding: 1em 2em;
color: $text-dark;
background-size: cover;
}
.remark-slide-number {
color: $text-light;
right: 1em;
opacity: .6;
font-size: 0.8em;
z-index: 2;
.no-counter & { display: none; }
}
// Additions
.impact {
background-color: $primary;
vertical-align: middle;
text-align: center;
&, h1, h2 { color: $text-light; }
h1 { font-size: $font-size-impact; }
}
.full {
&, h1, h2 { color: $text-light; }
&iframe {
height: calc(#{100%/$iframe-scale} - 1.2em);
width: 100%/$iframe-scale;
transform: scale($iframe-scale);
transform-origin: 0 0;
border: 0;
}
}
.bottom-bar {
background-color: $primary;
color: $text-light;
position: absolute;
bottom: 0;
left: 0;
right: 0;
font-size: 20px;
padding: .8em;
text-align: left;
z-index: 1;
p { margin: 0;}
.impact &, .full & { display: none; }
}
// Utilities
// ---------------------------------------------------------------------------
// Positioning
.side-layer {
position: absolute;
left: 0;
width: 100%;
padding: 0 2em;
}
.middle { &, & img, & span { vertical-align: middle; } };
.top { vertical-align: top; };
.bottom { vertical-align: bottom; };
.inline-block {
p, ul, ol, blockquote {
display: inline-block;
text-align: left;
}
}
.no-margin { &, & > p, & > pre, & > ul, & > ol { margin: 0; } }
.no-padding { padding: 0; }
.space-left { padding-left: 1em; }
.space-right { padding-right: 1em; }
// Images
.responsive > img { width: 100%; height: auto; };
.contain { background-size: contain; };
.overlay { box-shadow: inset 0 0 0 9999px $overlay; }
// Text
.left { text-align: left; }
.right { text-align: right; }
.center { text-align: center; }
.justify { text-align: justify; }
.primary { color: $primary; }
.alt { color: $secondary; };
.em { color: $tertiary; };
.thin { font-weight: 200; }
.huge { font-size: 2em; }
.big { font-size: 1.5em; }
.small { font-size: .8em; }
.dark-bg { background-color: $dark; }
.alt-bg { background-color: $secondary; };
// Simple 12-columns grid system
.row {
width: 100%;
&::after {
content: '';
display: table;
clear: both;
}
&.table { display: table; };
&.table [class^="col-"] {
float: none;
display: table-cell;
vertical-align: inherit;
}
}
[class^="col-"] {
float: left;
&.inline-block {
float: none;
display: inline-block;
}
}
@for $i from 1 through 12 {
.col-#{$i} {width: 100% / 12 * $i; }
}
// Animations
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.animation-fade {
animation-duration: 300ms;
animation-fill-mode: both;
animation-timing-function: ease-out;
.remark-visible & { animation-name: fadeIn; }
}
// Fix PDF print with chrome
// ---------------------------------------------------------------------------
@page {
// 908px 681px for 4/3 slides
size: 1210px 681px;
margin: 0;
}
@media print {
.remark-slide-scaler {
width: 100% !important;
height: 100% !important;
transform: scale(1) !important;
top: 0 !important;
left: 0 !important;
}
}