├── LICENSE
├── code
├── boton
│ └── main.py
├── dht11
│ └── main.py
├── ldr
│ └── main.py
├── led
│ └── main.py
├── modulo_actualizaIP
│ ├── main.py
│ └── u_ip.py
├── mqtt-publicacion
│ └── main.py
├── mqtt-suscripcion
│ └── main.py
├── peticiones
│ └── main.py
├── pwm
│ └── main.py
├── servidorI
│ └── main.py
├── servidorII
│ └── main.py
├── webREPL
│ └── boot.py
└── wifi
│ └── boot.py
├── css
├── reveal.css
└── theme
│ ├── README.md
│ └── serif.css
├── guion.md
├── img
├── configure_webrepl.png
├── devkit.png
├── download_micropython.png
├── esp8266_block_diagram.png
├── flashing_esp8266.png
├── installing_esptool.png
├── led_builtin.jpg
├── modules.png
├── mqtt-diagram.png
├── new_wifi.jpg
├── questions.jpg
├── toi.jpg
└── webrepl.png
├── index.html
├── js
├── highlight.js
├── markdown.js
├── marked.js
├── math.js
├── notes.js
├── print-pdf.js
├── reveal.js
├── search.js
└── zoom.js
├── lib
├── css
│ └── zenburn.css
├── font
│ ├── league-gothic
│ │ ├── LICENSE
│ │ ├── league-gothic.css
│ │ ├── league-gothic.eot
│ │ ├── league-gothic.ttf
│ │ └── league-gothic.woff
│ └── source-sans-pro
│ │ ├── LICENSE
│ │ ├── source-sans-pro-italic.eot
│ │ ├── source-sans-pro-italic.ttf
│ │ ├── source-sans-pro-italic.woff
│ │ ├── source-sans-pro-regular.eot
│ │ ├── source-sans-pro-regular.ttf
│ │ ├── source-sans-pro-regular.woff
│ │ ├── source-sans-pro-semibold.eot
│ │ ├── source-sans-pro-semibold.ttf
│ │ ├── source-sans-pro-semibold.woff
│ │ ├── source-sans-pro-semibolditalic.eot
│ │ ├── source-sans-pro-semibolditalic.ttf
│ │ ├── source-sans-pro-semibolditalic.woff
│ │ └── source-sans-pro.css
└── js
│ ├── classList.js
│ ├── head.min.js
│ └── html5shiv.js
├── print
├── paper.css
└── pdf.css
├── readme.md
└── slides.md
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/code/boton/main.py:
--------------------------------------------------------------------------------
1 | import machine
2 | boton = machine.Pin(4, machine.Pin.IN)
3 | boton.value()
4 | def boton_irq(p):
5 | print("El botón ha sido pulsado")
6 | boton.irq(trigger=machine.Pin.IRQ_RISING, handler=boton_irq)
7 | #boton.irq(trigger=machine.Pin.IRQ_FALLING, handler=boton_irq)
--------------------------------------------------------------------------------
/code/dht11/main.py:
--------------------------------------------------------------------------------
1 | import machine
2 | import dht
3 | d = dht.DHT11(machine.Pin(5))
4 | d.measure()
5 | d.temperature()
6 | d.humidity()
--------------------------------------------------------------------------------
/code/ldr/main.py:
--------------------------------------------------------------------------------
1 | import machine
2 | lum = machine.ADC(0)
3 | lum.read()
--------------------------------------------------------------------------------
/code/led/main.py:
--------------------------------------------------------------------------------
1 | import machine
2 | led = machine.Pin(2, machine.Pin.OUT)
3 | led.value()
4 | led.off() # led.value(0)
5 | led.on() # led.value(1)
--------------------------------------------------------------------------------
/code/modulo_actualizaIP/main.py:
--------------------------------------------------------------------------------
1 | import machine
2 | import ntptime
3 | import u_ip
4 | ntptime.settime() #actualiza hora
5 | tim = machine.Timer(-1)
6 | u_ip.actualiza_ip(0) #actualiza ip al iniciar
7 | tim.init(period=120000, mode=machine.Timer.PERIODIC, callback=u_ip.actualiza_ip) #actualiza ip cada 2 minutos
--------------------------------------------------------------------------------
/code/modulo_actualizaIP/u_ip.py:
--------------------------------------------------------------------------------
1 | try:
2 | import time as utime
3 | except:
4 | import utime
5 | try:
6 | import urequests as requests
7 | except:
8 | import requests
9 |
10 | def actualiza_ip(t):
11 | try:
12 | fip = open("ip","r")
13 | ip_old = fip.read()
14 | fip.close()
15 | domain = "esp8266.kcobos.es"
16 | res_ip = requests.get("http://ip.42.pl/raw")
17 | ip = res_ip.text
18 | ip = "1.1.1.2"
19 | if ip != ip_old:
20 | user = "usuario"
21 | password = "secreto"
22 | dir = "https://www.ovh.com/nic/update?system=dyndns&hostname="+domain+"&myip="+ip
23 | response = requests.get(dir, headers={'Authorization':""})
24 | fip = open("ip", "w")
25 | fip.write(ip)
26 | fip.close()
27 | except Exception as e:
28 | f = open("log", "a")
29 | f.write(str(utime.localtime()))
30 | f.write(" ERROR ACTUALIZA IP ")
31 | f.write(str(e))
32 | f.write("\n")
33 | f.close()
34 |
35 |
--------------------------------------------------------------------------------
/code/mqtt-publicacion/main.py:
--------------------------------------------------------------------------------
1 | import time
2 | from umqtt.simple import MQTTClient
3 |
4 | c = MQTTClient("ESP8266", "cubie.kcobos.es")
5 | if not c.connect():
6 | print("Conectando")
7 |
8 | i=0
9 | while True:
10 | c.publish("prueba", "contando "+str(i))
11 | time.sleep(1)
12 | i+=1
13 |
14 | c.disconnect()
--------------------------------------------------------------------------------
/code/mqtt-suscripcion/main.py:
--------------------------------------------------------------------------------
1 | from umqtt.simple import MQTTClient
2 |
3 | def sub_cb(topic, msg):
4 | print((topic, msg))
5 |
6 | c = MQTTClient("ESP8266", "cubie.kcobos.es")
7 | c.set_callback(sub_cb)
8 | c.connect()
9 | print("Conectando")
10 | c.subscribe(b"prueba")
11 | print("Suscrito a prueba")
12 |
13 | while True:
14 | c.wait_msg()
15 |
16 | c.disconnect()
--------------------------------------------------------------------------------
/code/peticiones/main.py:
--------------------------------------------------------------------------------
1 | import urequests
2 | respuesta = urequests.get('https://httpbin.org/get')
3 | print(respuesta.text)
4 | print(respuesta.json())
5 | print(respuesta.status_code)
6 | print(respuesta.reason)
7 | respuesta = urequests.post('https://httpbin.org/post', data="micropython")
8 | print(respuesta.text)
9 | respuesta = urequests.delete('https://httpbin.org/delete', data="compilar para probar")
10 | print(respuesta.text)
11 | respuesta = urequests.put('https://httpbin.org/put', data="IoT fácil")
12 | print(respuesta.text)
--------------------------------------------------------------------------------
/code/pwm/main.py:
--------------------------------------------------------------------------------
1 | from machine import Pin, PWM
2 | pwm0 = PWM(Pin(2))
3 | pwm0.freq() # 0 - 1000
4 | pwm0.freq(1000)
5 | pwm0.duty() # 0 - 1023
6 | pwm0.duty(200)
7 | pwm0.deinit()
8 | pwm1 = PWM(Pin(2), freq=500, duty=512)
--------------------------------------------------------------------------------
/code/servidorI/main.py:
--------------------------------------------------------------------------------
1 | import socket
2 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
3 | s.bind(('', 80))
4 | s.listen(0)
5 | while True:
6 | conn, addr = s.accept()
7 | print("Conexión desde: %s" % str(addr))
8 | request = conn.recv(512)
9 | print("Contenido recivido: %s" % str(request))
10 | conn.send("
Servidor ESP8266 Hola desde mi IoT ")
11 | conn.close()
--------------------------------------------------------------------------------
/code/servidorII/main.py:
--------------------------------------------------------------------------------
1 | import machine
2 | led = machine.Pin(2, machine.Pin.OUT)
3 | import socket
4 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
5 | s.bind(('', 80))
6 | s.listen(0)
7 | while True:
8 | conn, addr = s.accept()
9 | print("Conexión desde: %s" % str(addr))
10 | request = conn.recv(512)
11 | request = str(request).split(" ")
12 | if request[1] == "/?LED=ON":
13 | led.on()
14 | if request[1] == "/?LED=OFF":
15 | led.off()
16 | print("Contenido recivido: %s" % str(request))
17 | conn.send("Servidor ESP8266 Hola desde mi IoT %s "%led.value())
18 | conn.close()
--------------------------------------------------------------------------------
/code/webREPL/boot.py:
--------------------------------------------------------------------------------
1 | import webrepl
2 | webrepl.start()
--------------------------------------------------------------------------------
/code/wifi/boot.py:
--------------------------------------------------------------------------------
1 | import webrepl
2 | webrepl.start()
3 |
4 | import network
5 |
6 | wlan = network.WLAN(network.STA_IF)
7 | wlan.active(True)
8 | wlan.isconnected()
9 | wlan.connect('essid', 'password')
10 | wlan.ifconfig()
11 |
12 | # ap = network.WLAN(network.AP_IF)
13 | # ap.active(True)
14 | # ap.config(essid='ESP-AP', password='miESPap123')
15 | # ap.ifconfig(('192.168.4.1', '255.255.255.0', '192.168.4.1', '8.8.8.8'))
--------------------------------------------------------------------------------
/css/reveal.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * reveal.js
3 | * http://revealjs.com
4 | * MIT licensed
5 | *
6 | * Copyright (C) 2018 Hakim El Hattab, http://hakim.se
7 | */
8 | /*********************************************
9 | * RESET STYLES
10 | *********************************************/
11 | html, body, .reveal div, .reveal span, .reveal applet, .reveal object, .reveal iframe,
12 | .reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6, .reveal p, .reveal blockquote, .reveal pre,
13 | .reveal a, .reveal abbr, .reveal acronym, .reveal address, .reveal big, .reveal cite, .reveal code,
14 | .reveal del, .reveal dfn, .reveal em, .reveal img, .reveal ins, .reveal kbd, .reveal q, .reveal s, .reveal samp,
15 | .reveal small, .reveal strike, .reveal strong, .reveal sub, .reveal sup, .reveal tt, .reveal var,
16 | .reveal b, .reveal u, .reveal center,
17 | .reveal dl, .reveal dt, .reveal dd, .reveal ol, .reveal ul, .reveal li,
18 | .reveal fieldset, .reveal form, .reveal label, .reveal legend,
19 | .reveal table, .reveal caption, .reveal tbody, .reveal tfoot, .reveal thead, .reveal tr, .reveal th, .reveal td,
20 | .reveal article, .reveal aside, .reveal canvas, .reveal details, .reveal embed,
21 | .reveal figure, .reveal figcaption, .reveal footer, .reveal header, .reveal hgroup,
22 | .reveal menu, .reveal nav, .reveal output, .reveal ruby, .reveal section, .reveal summary,
23 | .reveal time, .reveal mark, .reveal audio, .reveal video {
24 | margin: 0;
25 | padding: 0;
26 | border: 0;
27 | font-size: 100%;
28 | font: inherit;
29 | vertical-align: baseline; }
30 |
31 | .reveal article, .reveal aside, .reveal details, .reveal figcaption, .reveal figure,
32 | .reveal footer, .reveal header, .reveal hgroup, .reveal menu, .reveal nav, .reveal section {
33 | display: block; }
34 |
35 | /*********************************************
36 | * GLOBAL STYLES
37 | *********************************************/
38 | html,
39 | body {
40 | width: 100%;
41 | height: 100%;
42 | overflow: hidden; }
43 |
44 | body {
45 | position: relative;
46 | line-height: 1;
47 | background-color: #fff;
48 | color: #000; }
49 |
50 | /*********************************************
51 | * VIEW FRAGMENTS
52 | *********************************************/
53 | .reveal .slides section .fragment {
54 | opacity: 0;
55 | visibility: hidden;
56 | transition: all .2s ease; }
57 | .reveal .slides section .fragment.visible {
58 | opacity: 1;
59 | visibility: inherit; }
60 |
61 | .reveal .slides section .fragment.grow {
62 | opacity: 1;
63 | visibility: inherit; }
64 | .reveal .slides section .fragment.grow.visible {
65 | -webkit-transform: scale(1.3);
66 | transform: scale(1.3); }
67 |
68 | .reveal .slides section .fragment.shrink {
69 | opacity: 1;
70 | visibility: inherit; }
71 | .reveal .slides section .fragment.shrink.visible {
72 | -webkit-transform: scale(0.7);
73 | transform: scale(0.7); }
74 |
75 | .reveal .slides section .fragment.zoom-in {
76 | -webkit-transform: scale(0.1);
77 | transform: scale(0.1); }
78 | .reveal .slides section .fragment.zoom-in.visible {
79 | -webkit-transform: none;
80 | transform: none; }
81 |
82 | .reveal .slides section .fragment.fade-out {
83 | opacity: 1;
84 | visibility: inherit; }
85 | .reveal .slides section .fragment.fade-out.visible {
86 | opacity: 0;
87 | visibility: hidden; }
88 |
89 | .reveal .slides section .fragment.semi-fade-out {
90 | opacity: 1;
91 | visibility: inherit; }
92 | .reveal .slides section .fragment.semi-fade-out.visible {
93 | opacity: 0.5;
94 | visibility: inherit; }
95 |
96 | .reveal .slides section .fragment.strike {
97 | opacity: 1;
98 | visibility: inherit; }
99 | .reveal .slides section .fragment.strike.visible {
100 | text-decoration: line-through; }
101 |
102 | .reveal .slides section .fragment.fade-up {
103 | -webkit-transform: translate(0, 20%);
104 | transform: translate(0, 20%); }
105 | .reveal .slides section .fragment.fade-up.visible {
106 | -webkit-transform: translate(0, 0);
107 | transform: translate(0, 0); }
108 |
109 | .reveal .slides section .fragment.fade-down {
110 | -webkit-transform: translate(0, -20%);
111 | transform: translate(0, -20%); }
112 | .reveal .slides section .fragment.fade-down.visible {
113 | -webkit-transform: translate(0, 0);
114 | transform: translate(0, 0); }
115 |
116 | .reveal .slides section .fragment.fade-right {
117 | -webkit-transform: translate(-20%, 0);
118 | transform: translate(-20%, 0); }
119 | .reveal .slides section .fragment.fade-right.visible {
120 | -webkit-transform: translate(0, 0);
121 | transform: translate(0, 0); }
122 |
123 | .reveal .slides section .fragment.fade-left {
124 | -webkit-transform: translate(20%, 0);
125 | transform: translate(20%, 0); }
126 | .reveal .slides section .fragment.fade-left.visible {
127 | -webkit-transform: translate(0, 0);
128 | transform: translate(0, 0); }
129 |
130 | .reveal .slides section .fragment.fade-in-then-out,
131 | .reveal .slides section .fragment.current-visible {
132 | opacity: 0;
133 | visibility: hidden; }
134 | .reveal .slides section .fragment.fade-in-then-out.current-fragment,
135 | .reveal .slides section .fragment.current-visible.current-fragment {
136 | opacity: 1;
137 | visibility: inherit; }
138 |
139 | .reveal .slides section .fragment.fade-in-then-semi-out {
140 | opacity: 0;
141 | visibility: hidden; }
142 | .reveal .slides section .fragment.fade-in-then-semi-out.visible {
143 | opacity: 0.5;
144 | visibility: inherit; }
145 | .reveal .slides section .fragment.fade-in-then-semi-out.current-fragment {
146 | opacity: 1;
147 | visibility: inherit; }
148 |
149 | .reveal .slides section .fragment.highlight-red,
150 | .reveal .slides section .fragment.highlight-current-red,
151 | .reveal .slides section .fragment.highlight-green,
152 | .reveal .slides section .fragment.highlight-current-green,
153 | .reveal .slides section .fragment.highlight-blue,
154 | .reveal .slides section .fragment.highlight-current-blue {
155 | opacity: 1;
156 | visibility: inherit; }
157 |
158 | .reveal .slides section .fragment.highlight-red.visible {
159 | color: #ff2c2d; }
160 |
161 | .reveal .slides section .fragment.highlight-green.visible {
162 | color: #17ff2e; }
163 |
164 | .reveal .slides section .fragment.highlight-blue.visible {
165 | color: #1b91ff; }
166 |
167 | .reveal .slides section .fragment.highlight-current-red.current-fragment {
168 | color: #ff2c2d; }
169 |
170 | .reveal .slides section .fragment.highlight-current-green.current-fragment {
171 | color: #17ff2e; }
172 |
173 | .reveal .slides section .fragment.highlight-current-blue.current-fragment {
174 | color: #1b91ff; }
175 |
176 | /*********************************************
177 | * DEFAULT ELEMENT STYLES
178 | *********************************************/
179 | /* Fixes issue in Chrome where italic fonts did not appear when printing to PDF */
180 | .reveal:after {
181 | content: '';
182 | font-style: italic; }
183 |
184 | .reveal iframe {
185 | z-index: 1; }
186 |
187 | /** Prevents layering issues in certain browser/transition combinations */
188 | .reveal a {
189 | position: relative; }
190 |
191 | .reveal .stretch {
192 | max-width: none;
193 | max-height: none; }
194 |
195 | .reveal pre.stretch code {
196 | height: 100%;
197 | max-height: 100%;
198 | box-sizing: border-box; }
199 |
200 | /*********************************************
201 | * CONTROLS
202 | *********************************************/
203 | @-webkit-keyframes bounce-right {
204 | 0%, 10%, 25%, 40%, 50% {
205 | -webkit-transform: translateX(0);
206 | transform: translateX(0); }
207 | 20% {
208 | -webkit-transform: translateX(10px);
209 | transform: translateX(10px); }
210 | 30% {
211 | -webkit-transform: translateX(-5px);
212 | transform: translateX(-5px); } }
213 | @keyframes bounce-right {
214 | 0%, 10%, 25%, 40%, 50% {
215 | -webkit-transform: translateX(0);
216 | transform: translateX(0); }
217 | 20% {
218 | -webkit-transform: translateX(10px);
219 | transform: translateX(10px); }
220 | 30% {
221 | -webkit-transform: translateX(-5px);
222 | transform: translateX(-5px); } }
223 |
224 | @-webkit-keyframes bounce-down {
225 | 0%, 10%, 25%, 40%, 50% {
226 | -webkit-transform: translateY(0);
227 | transform: translateY(0); }
228 | 20% {
229 | -webkit-transform: translateY(10px);
230 | transform: translateY(10px); }
231 | 30% {
232 | -webkit-transform: translateY(-5px);
233 | transform: translateY(-5px); } }
234 |
235 | @keyframes bounce-down {
236 | 0%, 10%, 25%, 40%, 50% {
237 | -webkit-transform: translateY(0);
238 | transform: translateY(0); }
239 | 20% {
240 | -webkit-transform: translateY(10px);
241 | transform: translateY(10px); }
242 | 30% {
243 | -webkit-transform: translateY(-5px);
244 | transform: translateY(-5px); } }
245 |
246 | .reveal .controls {
247 | display: none;
248 | position: absolute;
249 | top: auto;
250 | bottom: 12px;
251 | right: 12px;
252 | left: auto;
253 | z-index: 1;
254 | color: #000;
255 | pointer-events: none;
256 | font-size: 10px; }
257 | .reveal .controls button {
258 | position: absolute;
259 | padding: 0;
260 | background-color: transparent;
261 | border: 0;
262 | outline: 0;
263 | cursor: pointer;
264 | color: currentColor;
265 | -webkit-transform: scale(0.9999);
266 | transform: scale(0.9999);
267 | transition: color 0.2s ease, opacity 0.2s ease, -webkit-transform 0.2s ease;
268 | transition: color 0.2s ease, opacity 0.2s ease, transform 0.2s ease;
269 | z-index: 2;
270 | pointer-events: auto;
271 | font-size: inherit;
272 | visibility: hidden;
273 | opacity: 0;
274 | -webkit-appearance: none;
275 | -webkit-tap-highlight-color: transparent; }
276 | .reveal .controls .controls-arrow:before,
277 | .reveal .controls .controls-arrow:after {
278 | content: '';
279 | position: absolute;
280 | top: 0;
281 | left: 0;
282 | width: 2.6em;
283 | height: 0.5em;
284 | border-radius: 0.25em;
285 | background-color: currentColor;
286 | transition: all 0.15s ease, background-color 0.8s ease;
287 | -webkit-transform-origin: 0.2em 50%;
288 | transform-origin: 0.2em 50%;
289 | will-change: transform; }
290 | .reveal .controls .controls-arrow {
291 | position: relative;
292 | width: 3.6em;
293 | height: 3.6em; }
294 | .reveal .controls .controls-arrow:before {
295 | -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(45deg);
296 | transform: translateX(0.5em) translateY(1.55em) rotate(45deg); }
297 | .reveal .controls .controls-arrow:after {
298 | -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-45deg);
299 | transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); }
300 | .reveal .controls .controls-arrow:hover:before {
301 | -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(40deg);
302 | transform: translateX(0.5em) translateY(1.55em) rotate(40deg); }
303 | .reveal .controls .controls-arrow:hover:after {
304 | -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-40deg);
305 | transform: translateX(0.5em) translateY(1.55em) rotate(-40deg); }
306 | .reveal .controls .controls-arrow:active:before {
307 | -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(36deg);
308 | transform: translateX(0.5em) translateY(1.55em) rotate(36deg); }
309 | .reveal .controls .controls-arrow:active:after {
310 | -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-36deg);
311 | transform: translateX(0.5em) translateY(1.55em) rotate(-36deg); }
312 | .reveal .controls .navigate-left {
313 | right: 6.4em;
314 | bottom: 3.2em;
315 | -webkit-transform: translateX(-10px);
316 | transform: translateX(-10px); }
317 | .reveal .controls .navigate-right {
318 | right: 0;
319 | bottom: 3.2em;
320 | -webkit-transform: translateX(10px);
321 | transform: translateX(10px); }
322 | .reveal .controls .navigate-right .controls-arrow {
323 | -webkit-transform: rotate(180deg);
324 | transform: rotate(180deg); }
325 | .reveal .controls .navigate-right.highlight {
326 | -webkit-animation: bounce-right 2s 50 both ease-out;
327 | animation: bounce-right 2s 50 both ease-out; }
328 | .reveal .controls .navigate-up {
329 | right: 3.2em;
330 | bottom: 6.4em;
331 | -webkit-transform: translateY(-10px);
332 | transform: translateY(-10px); }
333 | .reveal .controls .navigate-up .controls-arrow {
334 | -webkit-transform: rotate(90deg);
335 | transform: rotate(90deg); }
336 | .reveal .controls .navigate-down {
337 | right: 3.2em;
338 | bottom: 0;
339 | -webkit-transform: translateY(10px);
340 | transform: translateY(10px); }
341 | .reveal .controls .navigate-down .controls-arrow {
342 | -webkit-transform: rotate(-90deg);
343 | transform: rotate(-90deg); }
344 | .reveal .controls .navigate-down.highlight {
345 | -webkit-animation: bounce-down 2s 50 both ease-out;
346 | animation: bounce-down 2s 50 both ease-out; }
347 | .reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled,
348 | .reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled {
349 | opacity: 0.3; }
350 | .reveal .controls[data-controls-back-arrows="faded"] .navigate-left.enabled:hover,
351 | .reveal .controls[data-controls-back-arrows="faded"] .navigate-up.enabled:hover {
352 | opacity: 1; }
353 | .reveal .controls[data-controls-back-arrows="hidden"] .navigate-left.enabled,
354 | .reveal .controls[data-controls-back-arrows="hidden"] .navigate-up.enabled {
355 | opacity: 0;
356 | visibility: hidden; }
357 | .reveal .controls .enabled {
358 | visibility: visible;
359 | opacity: 0.9;
360 | cursor: pointer;
361 | -webkit-transform: none;
362 | transform: none; }
363 | .reveal .controls .enabled.fragmented {
364 | opacity: 0.5; }
365 | .reveal .controls .enabled:hover,
366 | .reveal .controls .enabled.fragmented:hover {
367 | opacity: 1; }
368 |
369 | .reveal:not(.has-vertical-slides) .controls .navigate-left {
370 | bottom: 1.4em;
371 | right: 5.5em; }
372 |
373 | .reveal:not(.has-vertical-slides) .controls .navigate-right {
374 | bottom: 1.4em;
375 | right: 0.5em; }
376 |
377 | .reveal:not(.has-horizontal-slides) .controls .navigate-up {
378 | right: 1.4em;
379 | bottom: 5em; }
380 |
381 | .reveal:not(.has-horizontal-slides) .controls .navigate-down {
382 | right: 1.4em;
383 | bottom: 0.5em; }
384 |
385 | .reveal.has-dark-background .controls {
386 | color: #fff; }
387 |
388 | .reveal.has-light-background .controls {
389 | color: #000; }
390 |
391 | .reveal.no-hover .controls .controls-arrow:hover:before,
392 | .reveal.no-hover .controls .controls-arrow:active:before {
393 | -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(45deg);
394 | transform: translateX(0.5em) translateY(1.55em) rotate(45deg); }
395 |
396 | .reveal.no-hover .controls .controls-arrow:hover:after,
397 | .reveal.no-hover .controls .controls-arrow:active:after {
398 | -webkit-transform: translateX(0.5em) translateY(1.55em) rotate(-45deg);
399 | transform: translateX(0.5em) translateY(1.55em) rotate(-45deg); }
400 |
401 | @media screen and (min-width: 500px) {
402 | .reveal .controls[data-controls-layout="edges"] {
403 | top: 0;
404 | right: 0;
405 | bottom: 0;
406 | left: 0; }
407 | .reveal .controls[data-controls-layout="edges"] .navigate-left,
408 | .reveal .controls[data-controls-layout="edges"] .navigate-right,
409 | .reveal .controls[data-controls-layout="edges"] .navigate-up,
410 | .reveal .controls[data-controls-layout="edges"] .navigate-down {
411 | bottom: auto;
412 | right: auto; }
413 | .reveal .controls[data-controls-layout="edges"] .navigate-left {
414 | top: 50%;
415 | left: 8px;
416 | margin-top: -1.8em; }
417 | .reveal .controls[data-controls-layout="edges"] .navigate-right {
418 | top: 50%;
419 | right: 8px;
420 | margin-top: -1.8em; }
421 | .reveal .controls[data-controls-layout="edges"] .navigate-up {
422 | top: 8px;
423 | left: 50%;
424 | margin-left: -1.8em; }
425 | .reveal .controls[data-controls-layout="edges"] .navigate-down {
426 | bottom: 8px;
427 | left: 50%;
428 | margin-left: -1.8em; } }
429 |
430 | /*********************************************
431 | * PROGRESS BAR
432 | *********************************************/
433 | .reveal .progress {
434 | position: absolute;
435 | display: none;
436 | height: 3px;
437 | width: 100%;
438 | bottom: 0;
439 | left: 0;
440 | z-index: 10;
441 | background-color: rgba(0, 0, 0, 0.2);
442 | color: #fff; }
443 |
444 | .reveal .progress:after {
445 | content: '';
446 | display: block;
447 | position: absolute;
448 | height: 10px;
449 | width: 100%;
450 | top: -10px; }
451 |
452 | .reveal .progress span {
453 | display: block;
454 | height: 100%;
455 | width: 0px;
456 | background-color: currentColor;
457 | transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
458 |
459 | /*********************************************
460 | * SLIDE NUMBER
461 | *********************************************/
462 | .reveal .slide-number {
463 | position: absolute;
464 | display: block;
465 | right: 8px;
466 | bottom: 8px;
467 | z-index: 31;
468 | font-family: Helvetica, sans-serif;
469 | font-size: 12px;
470 | line-height: 1;
471 | color: #fff;
472 | background-color: rgba(0, 0, 0, 0.4);
473 | padding: 5px; }
474 |
475 | .reveal .slide-number a {
476 | color: currentColor; }
477 |
478 | .reveal .slide-number-delimiter {
479 | margin: 0 3px; }
480 |
481 | /*********************************************
482 | * SLIDES
483 | *********************************************/
484 | .reveal {
485 | position: relative;
486 | width: 100%;
487 | height: 100%;
488 | overflow: hidden;
489 | -ms-touch-action: none;
490 | touch-action: none; }
491 |
492 | @media only screen and (orientation: landscape) {
493 | .reveal.ua-iphone {
494 | position: fixed; } }
495 |
496 | .reveal .slides {
497 | position: absolute;
498 | width: 100%;
499 | height: 100%;
500 | top: 0;
501 | right: 0;
502 | bottom: 0;
503 | left: 0;
504 | margin: auto;
505 | pointer-events: none;
506 | overflow: visible;
507 | z-index: 1;
508 | text-align: center;
509 | -webkit-perspective: 600px;
510 | perspective: 600px;
511 | -webkit-perspective-origin: 50% 40%;
512 | perspective-origin: 50% 40%; }
513 |
514 | .reveal .slides > section {
515 | -ms-perspective: 600px; }
516 |
517 | .reveal .slides > section,
518 | .reveal .slides > section > section {
519 | display: none;
520 | position: absolute;
521 | width: 100%;
522 | padding: 20px 0px;
523 | pointer-events: auto;
524 | z-index: 10;
525 | -webkit-transform-style: flat;
526 | transform-style: flat;
527 | transition: -webkit-transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), -webkit-transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
528 | transition: transform-origin 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), transform 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), visibility 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985), opacity 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
529 |
530 | /* Global transition speed settings */
531 | .reveal[data-transition-speed="fast"] .slides section {
532 | transition-duration: 400ms; }
533 |
534 | .reveal[data-transition-speed="slow"] .slides section {
535 | transition-duration: 1200ms; }
536 |
537 | /* Slide-specific transition speed overrides */
538 | .reveal .slides section[data-transition-speed="fast"] {
539 | transition-duration: 400ms; }
540 |
541 | .reveal .slides section[data-transition-speed="slow"] {
542 | transition-duration: 1200ms; }
543 |
544 | .reveal .slides > section.stack {
545 | padding-top: 0;
546 | padding-bottom: 0;
547 | pointer-events: none; }
548 |
549 | .reveal .slides > section.present,
550 | .reveal .slides > section > section.present {
551 | display: block;
552 | z-index: 11;
553 | opacity: 1; }
554 |
555 | .reveal .slides > section:empty,
556 | .reveal .slides > section > section:empty,
557 | .reveal .slides > section[data-background-interactive],
558 | .reveal .slides > section > section[data-background-interactive] {
559 | pointer-events: none; }
560 |
561 | .reveal.center,
562 | .reveal.center .slides,
563 | .reveal.center .slides section {
564 | min-height: 0 !important; }
565 |
566 | /* Don't allow interaction with invisible slides */
567 | .reveal .slides > section.future,
568 | .reveal .slides > section > section.future,
569 | .reveal .slides > section.past,
570 | .reveal .slides > section > section.past {
571 | pointer-events: none; }
572 |
573 | .reveal.overview .slides > section,
574 | .reveal.overview .slides > section > section {
575 | pointer-events: auto; }
576 |
577 | .reveal .slides > section.past,
578 | .reveal .slides > section.future,
579 | .reveal .slides > section > section.past,
580 | .reveal .slides > section > section.future {
581 | opacity: 0; }
582 |
583 | /*********************************************
584 | * Mixins for readability of transitions
585 | *********************************************/
586 | /*********************************************
587 | * SLIDE TRANSITION
588 | * Aliased 'linear' for backwards compatibility
589 | *********************************************/
590 | .reveal.slide section {
591 | -webkit-backface-visibility: hidden;
592 | backface-visibility: hidden; }
593 |
594 | .reveal .slides > section[data-transition=slide].past,
595 | .reveal .slides > section[data-transition~=slide-out].past,
596 | .reveal.slide .slides > section:not([data-transition]).past {
597 | -webkit-transform: translate(-150%, 0);
598 | transform: translate(-150%, 0); }
599 |
600 | .reveal .slides > section[data-transition=slide].future,
601 | .reveal .slides > section[data-transition~=slide-in].future,
602 | .reveal.slide .slides > section:not([data-transition]).future {
603 | -webkit-transform: translate(150%, 0);
604 | transform: translate(150%, 0); }
605 |
606 | .reveal .slides > section > section[data-transition=slide].past,
607 | .reveal .slides > section > section[data-transition~=slide-out].past,
608 | .reveal.slide .slides > section > section:not([data-transition]).past {
609 | -webkit-transform: translate(0, -150%);
610 | transform: translate(0, -150%); }
611 |
612 | .reveal .slides > section > section[data-transition=slide].future,
613 | .reveal .slides > section > section[data-transition~=slide-in].future,
614 | .reveal.slide .slides > section > section:not([data-transition]).future {
615 | -webkit-transform: translate(0, 150%);
616 | transform: translate(0, 150%); }
617 |
618 | .reveal.linear section {
619 | -webkit-backface-visibility: hidden;
620 | backface-visibility: hidden; }
621 |
622 | .reveal .slides > section[data-transition=linear].past,
623 | .reveal .slides > section[data-transition~=linear-out].past,
624 | .reveal.linear .slides > section:not([data-transition]).past {
625 | -webkit-transform: translate(-150%, 0);
626 | transform: translate(-150%, 0); }
627 |
628 | .reveal .slides > section[data-transition=linear].future,
629 | .reveal .slides > section[data-transition~=linear-in].future,
630 | .reveal.linear .slides > section:not([data-transition]).future {
631 | -webkit-transform: translate(150%, 0);
632 | transform: translate(150%, 0); }
633 |
634 | .reveal .slides > section > section[data-transition=linear].past,
635 | .reveal .slides > section > section[data-transition~=linear-out].past,
636 | .reveal.linear .slides > section > section:not([data-transition]).past {
637 | -webkit-transform: translate(0, -150%);
638 | transform: translate(0, -150%); }
639 |
640 | .reveal .slides > section > section[data-transition=linear].future,
641 | .reveal .slides > section > section[data-transition~=linear-in].future,
642 | .reveal.linear .slides > section > section:not([data-transition]).future {
643 | -webkit-transform: translate(0, 150%);
644 | transform: translate(0, 150%); }
645 |
646 | /*********************************************
647 | * CONVEX TRANSITION
648 | * Aliased 'default' for backwards compatibility
649 | *********************************************/
650 | .reveal .slides section[data-transition=default].stack,
651 | .reveal.default .slides section.stack {
652 | -webkit-transform-style: preserve-3d;
653 | transform-style: preserve-3d; }
654 |
655 | .reveal .slides > section[data-transition=default].past,
656 | .reveal .slides > section[data-transition~=default-out].past,
657 | .reveal.default .slides > section:not([data-transition]).past {
658 | -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0);
659 | transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); }
660 |
661 | .reveal .slides > section[data-transition=default].future,
662 | .reveal .slides > section[data-transition~=default-in].future,
663 | .reveal.default .slides > section:not([data-transition]).future {
664 | -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0);
665 | transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); }
666 |
667 | .reveal .slides > section > section[data-transition=default].past,
668 | .reveal .slides > section > section[data-transition~=default-out].past,
669 | .reveal.default .slides > section > section:not([data-transition]).past {
670 | -webkit-transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0);
671 | transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); }
672 |
673 | .reveal .slides > section > section[data-transition=default].future,
674 | .reveal .slides > section > section[data-transition~=default-in].future,
675 | .reveal.default .slides > section > section:not([data-transition]).future {
676 | -webkit-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0);
677 | transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); }
678 |
679 | .reveal .slides section[data-transition=convex].stack,
680 | .reveal.convex .slides section.stack {
681 | -webkit-transform-style: preserve-3d;
682 | transform-style: preserve-3d; }
683 |
684 | .reveal .slides > section[data-transition=convex].past,
685 | .reveal .slides > section[data-transition~=convex-out].past,
686 | .reveal.convex .slides > section:not([data-transition]).past {
687 | -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0);
688 | transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); }
689 |
690 | .reveal .slides > section[data-transition=convex].future,
691 | .reveal .slides > section[data-transition~=convex-in].future,
692 | .reveal.convex .slides > section:not([data-transition]).future {
693 | -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0);
694 | transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); }
695 |
696 | .reveal .slides > section > section[data-transition=convex].past,
697 | .reveal .slides > section > section[data-transition~=convex-out].past,
698 | .reveal.convex .slides > section > section:not([data-transition]).past {
699 | -webkit-transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0);
700 | transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); }
701 |
702 | .reveal .slides > section > section[data-transition=convex].future,
703 | .reveal .slides > section > section[data-transition~=convex-in].future,
704 | .reveal.convex .slides > section > section:not([data-transition]).future {
705 | -webkit-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0);
706 | transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); }
707 |
708 | /*********************************************
709 | * CONCAVE TRANSITION
710 | *********************************************/
711 | .reveal .slides section[data-transition=concave].stack,
712 | .reveal.concave .slides section.stack {
713 | -webkit-transform-style: preserve-3d;
714 | transform-style: preserve-3d; }
715 |
716 | .reveal .slides > section[data-transition=concave].past,
717 | .reveal .slides > section[data-transition~=concave-out].past,
718 | .reveal.concave .slides > section:not([data-transition]).past {
719 | -webkit-transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0);
720 | transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); }
721 |
722 | .reveal .slides > section[data-transition=concave].future,
723 | .reveal .slides > section[data-transition~=concave-in].future,
724 | .reveal.concave .slides > section:not([data-transition]).future {
725 | -webkit-transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0);
726 | transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); }
727 |
728 | .reveal .slides > section > section[data-transition=concave].past,
729 | .reveal .slides > section > section[data-transition~=concave-out].past,
730 | .reveal.concave .slides > section > section:not([data-transition]).past {
731 | -webkit-transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0);
732 | transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0); }
733 |
734 | .reveal .slides > section > section[data-transition=concave].future,
735 | .reveal .slides > section > section[data-transition~=concave-in].future,
736 | .reveal.concave .slides > section > section:not([data-transition]).future {
737 | -webkit-transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0);
738 | transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0); }
739 |
740 | /*********************************************
741 | * ZOOM TRANSITION
742 | *********************************************/
743 | .reveal .slides section[data-transition=zoom],
744 | .reveal.zoom .slides section:not([data-transition]) {
745 | transition-timing-function: ease; }
746 |
747 | .reveal .slides > section[data-transition=zoom].past,
748 | .reveal .slides > section[data-transition~=zoom-out].past,
749 | .reveal.zoom .slides > section:not([data-transition]).past {
750 | visibility: hidden;
751 | -webkit-transform: scale(16);
752 | transform: scale(16); }
753 |
754 | .reveal .slides > section[data-transition=zoom].future,
755 | .reveal .slides > section[data-transition~=zoom-in].future,
756 | .reveal.zoom .slides > section:not([data-transition]).future {
757 | visibility: hidden;
758 | -webkit-transform: scale(0.2);
759 | transform: scale(0.2); }
760 |
761 | .reveal .slides > section > section[data-transition=zoom].past,
762 | .reveal .slides > section > section[data-transition~=zoom-out].past,
763 | .reveal.zoom .slides > section > section:not([data-transition]).past {
764 | -webkit-transform: translate(0, -150%);
765 | transform: translate(0, -150%); }
766 |
767 | .reveal .slides > section > section[data-transition=zoom].future,
768 | .reveal .slides > section > section[data-transition~=zoom-in].future,
769 | .reveal.zoom .slides > section > section:not([data-transition]).future {
770 | -webkit-transform: translate(0, 150%);
771 | transform: translate(0, 150%); }
772 |
773 | /*********************************************
774 | * CUBE TRANSITION
775 | *
776 | * WARNING:
777 | * this is deprecated and will be removed in a
778 | * future version.
779 | *********************************************/
780 | .reveal.cube .slides {
781 | -webkit-perspective: 1300px;
782 | perspective: 1300px; }
783 |
784 | .reveal.cube .slides section {
785 | padding: 30px;
786 | min-height: 700px;
787 | -webkit-backface-visibility: hidden;
788 | backface-visibility: hidden;
789 | box-sizing: border-box;
790 | -webkit-transform-style: preserve-3d;
791 | transform-style: preserve-3d; }
792 |
793 | .reveal.center.cube .slides section {
794 | min-height: 0; }
795 |
796 | .reveal.cube .slides section:not(.stack):before {
797 | content: '';
798 | position: absolute;
799 | display: block;
800 | width: 100%;
801 | height: 100%;
802 | left: 0;
803 | top: 0;
804 | background: rgba(0, 0, 0, 0.1);
805 | border-radius: 4px;
806 | -webkit-transform: translateZ(-20px);
807 | transform: translateZ(-20px); }
808 |
809 | .reveal.cube .slides section:not(.stack):after {
810 | content: '';
811 | position: absolute;
812 | display: block;
813 | width: 90%;
814 | height: 30px;
815 | left: 5%;
816 | bottom: 0;
817 | background: none;
818 | z-index: 1;
819 | border-radius: 4px;
820 | box-shadow: 0px 95px 25px rgba(0, 0, 0, 0.2);
821 | -webkit-transform: translateZ(-90px) rotateX(65deg);
822 | transform: translateZ(-90px) rotateX(65deg); }
823 |
824 | .reveal.cube .slides > section.stack {
825 | padding: 0;
826 | background: none; }
827 |
828 | .reveal.cube .slides > section.past {
829 | -webkit-transform-origin: 100% 0%;
830 | transform-origin: 100% 0%;
831 | -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg);
832 | transform: translate3d(-100%, 0, 0) rotateY(-90deg); }
833 |
834 | .reveal.cube .slides > section.future {
835 | -webkit-transform-origin: 0% 0%;
836 | transform-origin: 0% 0%;
837 | -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg);
838 | transform: translate3d(100%, 0, 0) rotateY(90deg); }
839 |
840 | .reveal.cube .slides > section > section.past {
841 | -webkit-transform-origin: 0% 100%;
842 | transform-origin: 0% 100%;
843 | -webkit-transform: translate3d(0, -100%, 0) rotateX(90deg);
844 | transform: translate3d(0, -100%, 0) rotateX(90deg); }
845 |
846 | .reveal.cube .slides > section > section.future {
847 | -webkit-transform-origin: 0% 0%;
848 | transform-origin: 0% 0%;
849 | -webkit-transform: translate3d(0, 100%, 0) rotateX(-90deg);
850 | transform: translate3d(0, 100%, 0) rotateX(-90deg); }
851 |
852 | /*********************************************
853 | * PAGE TRANSITION
854 | *
855 | * WARNING:
856 | * this is deprecated and will be removed in a
857 | * future version.
858 | *********************************************/
859 | .reveal.page .slides {
860 | -webkit-perspective-origin: 0% 50%;
861 | perspective-origin: 0% 50%;
862 | -webkit-perspective: 3000px;
863 | perspective: 3000px; }
864 |
865 | .reveal.page .slides section {
866 | padding: 30px;
867 | min-height: 700px;
868 | box-sizing: border-box;
869 | -webkit-transform-style: preserve-3d;
870 | transform-style: preserve-3d; }
871 |
872 | .reveal.page .slides section.past {
873 | z-index: 12; }
874 |
875 | .reveal.page .slides section:not(.stack):before {
876 | content: '';
877 | position: absolute;
878 | display: block;
879 | width: 100%;
880 | height: 100%;
881 | left: 0;
882 | top: 0;
883 | background: rgba(0, 0, 0, 0.1);
884 | -webkit-transform: translateZ(-20px);
885 | transform: translateZ(-20px); }
886 |
887 | .reveal.page .slides section:not(.stack):after {
888 | content: '';
889 | position: absolute;
890 | display: block;
891 | width: 90%;
892 | height: 30px;
893 | left: 5%;
894 | bottom: 0;
895 | background: none;
896 | z-index: 1;
897 | border-radius: 4px;
898 | box-shadow: 0px 95px 25px rgba(0, 0, 0, 0.2);
899 | -webkit-transform: translateZ(-90px) rotateX(65deg); }
900 |
901 | .reveal.page .slides > section.stack {
902 | padding: 0;
903 | background: none; }
904 |
905 | .reveal.page .slides > section.past {
906 | -webkit-transform-origin: 0% 0%;
907 | transform-origin: 0% 0%;
908 | -webkit-transform: translate3d(-40%, 0, 0) rotateY(-80deg);
909 | transform: translate3d(-40%, 0, 0) rotateY(-80deg); }
910 |
911 | .reveal.page .slides > section.future {
912 | -webkit-transform-origin: 100% 0%;
913 | transform-origin: 100% 0%;
914 | -webkit-transform: translate3d(0, 0, 0);
915 | transform: translate3d(0, 0, 0); }
916 |
917 | .reveal.page .slides > section > section.past {
918 | -webkit-transform-origin: 0% 0%;
919 | transform-origin: 0% 0%;
920 | -webkit-transform: translate3d(0, -40%, 0) rotateX(80deg);
921 | transform: translate3d(0, -40%, 0) rotateX(80deg); }
922 |
923 | .reveal.page .slides > section > section.future {
924 | -webkit-transform-origin: 0% 100%;
925 | transform-origin: 0% 100%;
926 | -webkit-transform: translate3d(0, 0, 0);
927 | transform: translate3d(0, 0, 0); }
928 |
929 | /*********************************************
930 | * FADE TRANSITION
931 | *********************************************/
932 | .reveal .slides section[data-transition=fade],
933 | .reveal.fade .slides section:not([data-transition]),
934 | .reveal.fade .slides > section > section:not([data-transition]) {
935 | -webkit-transform: none;
936 | transform: none;
937 | transition: opacity 0.5s; }
938 |
939 | .reveal.fade.overview .slides section,
940 | .reveal.fade.overview .slides > section > section {
941 | transition: none; }
942 |
943 | /*********************************************
944 | * NO TRANSITION
945 | *********************************************/
946 | .reveal .slides section[data-transition=none],
947 | .reveal.none .slides section:not([data-transition]) {
948 | -webkit-transform: none;
949 | transform: none;
950 | transition: none; }
951 |
952 | /*********************************************
953 | * PAUSED MODE
954 | *********************************************/
955 | .reveal .pause-overlay {
956 | position: absolute;
957 | top: 0;
958 | left: 0;
959 | width: 100%;
960 | height: 100%;
961 | background: black;
962 | visibility: hidden;
963 | opacity: 0;
964 | z-index: 100;
965 | transition: all 1s ease; }
966 |
967 | .reveal .pause-overlay .resume-button {
968 | position: absolute;
969 | bottom: 20px;
970 | right: 20px;
971 | color: #ccc;
972 | border-radius: 2px;
973 | padding: 6px 14px;
974 | border: 2px solid #ccc;
975 | font-size: 16px;
976 | background: transparent;
977 | cursor: pointer; }
978 | .reveal .pause-overlay .resume-button:hover {
979 | color: #fff;
980 | border-color: #fff; }
981 |
982 | .reveal.paused .pause-overlay {
983 | visibility: visible;
984 | opacity: 1; }
985 |
986 | /*********************************************
987 | * FALLBACK
988 | *********************************************/
989 | .no-transforms {
990 | overflow-y: auto; }
991 |
992 | .no-transforms .reveal .slides {
993 | position: relative;
994 | width: 80%;
995 | height: auto !important;
996 | top: 0;
997 | left: 50%;
998 | margin: 0;
999 | text-align: center; }
1000 |
1001 | .no-transforms .reveal .controls,
1002 | .no-transforms .reveal .progress {
1003 | display: none !important; }
1004 |
1005 | .no-transforms .reveal .slides section {
1006 | display: block !important;
1007 | opacity: 1 !important;
1008 | position: relative !important;
1009 | height: auto;
1010 | min-height: 0;
1011 | top: 0;
1012 | left: -50%;
1013 | margin: 70px 0;
1014 | -webkit-transform: none;
1015 | transform: none; }
1016 |
1017 | .no-transforms .reveal .slides section section {
1018 | left: 0; }
1019 |
1020 | .reveal .no-transition,
1021 | .reveal .no-transition * {
1022 | transition: none !important; }
1023 |
1024 | /*********************************************
1025 | * PER-SLIDE BACKGROUNDS
1026 | *********************************************/
1027 | .reveal .backgrounds {
1028 | position: absolute;
1029 | width: 100%;
1030 | height: 100%;
1031 | top: 0;
1032 | left: 0;
1033 | -webkit-perspective: 600px;
1034 | perspective: 600px; }
1035 |
1036 | .reveal .slide-background {
1037 | display: none;
1038 | position: absolute;
1039 | width: 100%;
1040 | height: 100%;
1041 | opacity: 0;
1042 | visibility: hidden;
1043 | overflow: hidden;
1044 | background-color: transparent;
1045 | transition: all 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
1046 |
1047 | .reveal .slide-background-content {
1048 | position: absolute;
1049 | width: 100%;
1050 | height: 100%;
1051 | background-position: 50% 50%;
1052 | background-repeat: no-repeat;
1053 | background-size: cover; }
1054 |
1055 | .reveal .slide-background.stack {
1056 | display: block; }
1057 |
1058 | .reveal .slide-background.present {
1059 | opacity: 1;
1060 | visibility: visible;
1061 | z-index: 2; }
1062 |
1063 | .print-pdf .reveal .slide-background {
1064 | opacity: 1 !important;
1065 | visibility: visible !important; }
1066 |
1067 | /* Video backgrounds */
1068 | .reveal .slide-background video {
1069 | position: absolute;
1070 | width: 100%;
1071 | height: 100%;
1072 | max-width: none;
1073 | max-height: none;
1074 | top: 0;
1075 | left: 0;
1076 | -o-object-fit: cover;
1077 | object-fit: cover; }
1078 |
1079 | .reveal .slide-background[data-background-size="contain"] video {
1080 | -o-object-fit: contain;
1081 | object-fit: contain; }
1082 |
1083 | /* Immediate transition style */
1084 | .reveal[data-background-transition=none] > .backgrounds .slide-background,
1085 | .reveal > .backgrounds .slide-background[data-background-transition=none] {
1086 | transition: none; }
1087 |
1088 | /* Slide */
1089 | .reveal[data-background-transition=slide] > .backgrounds .slide-background,
1090 | .reveal > .backgrounds .slide-background[data-background-transition=slide] {
1091 | opacity: 1;
1092 | -webkit-backface-visibility: hidden;
1093 | backface-visibility: hidden; }
1094 |
1095 | .reveal[data-background-transition=slide] > .backgrounds .slide-background.past,
1096 | .reveal > .backgrounds .slide-background.past[data-background-transition=slide] {
1097 | -webkit-transform: translate(-100%, 0);
1098 | transform: translate(-100%, 0); }
1099 |
1100 | .reveal[data-background-transition=slide] > .backgrounds .slide-background.future,
1101 | .reveal > .backgrounds .slide-background.future[data-background-transition=slide] {
1102 | -webkit-transform: translate(100%, 0);
1103 | transform: translate(100%, 0); }
1104 |
1105 | .reveal[data-background-transition=slide] > .backgrounds .slide-background > .slide-background.past,
1106 | .reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=slide] {
1107 | -webkit-transform: translate(0, -100%);
1108 | transform: translate(0, -100%); }
1109 |
1110 | .reveal[data-background-transition=slide] > .backgrounds .slide-background > .slide-background.future,
1111 | .reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=slide] {
1112 | -webkit-transform: translate(0, 100%);
1113 | transform: translate(0, 100%); }
1114 |
1115 | /* Convex */
1116 | .reveal[data-background-transition=convex] > .backgrounds .slide-background.past,
1117 | .reveal > .backgrounds .slide-background.past[data-background-transition=convex] {
1118 | opacity: 0;
1119 | -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0);
1120 | transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); }
1121 |
1122 | .reveal[data-background-transition=convex] > .backgrounds .slide-background.future,
1123 | .reveal > .backgrounds .slide-background.future[data-background-transition=convex] {
1124 | opacity: 0;
1125 | -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0);
1126 | transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); }
1127 |
1128 | .reveal[data-background-transition=convex] > .backgrounds .slide-background > .slide-background.past,
1129 | .reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=convex] {
1130 | opacity: 0;
1131 | -webkit-transform: translate3d(0, -100%, 0) rotateX(90deg) translate3d(0, -100%, 0);
1132 | transform: translate3d(0, -100%, 0) rotateX(90deg) translate3d(0, -100%, 0); }
1133 |
1134 | .reveal[data-background-transition=convex] > .backgrounds .slide-background > .slide-background.future,
1135 | .reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=convex] {
1136 | opacity: 0;
1137 | -webkit-transform: translate3d(0, 100%, 0) rotateX(-90deg) translate3d(0, 100%, 0);
1138 | transform: translate3d(0, 100%, 0) rotateX(-90deg) translate3d(0, 100%, 0); }
1139 |
1140 | /* Concave */
1141 | .reveal[data-background-transition=concave] > .backgrounds .slide-background.past,
1142 | .reveal > .backgrounds .slide-background.past[data-background-transition=concave] {
1143 | opacity: 0;
1144 | -webkit-transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0);
1145 | transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); }
1146 |
1147 | .reveal[data-background-transition=concave] > .backgrounds .slide-background.future,
1148 | .reveal > .backgrounds .slide-background.future[data-background-transition=concave] {
1149 | opacity: 0;
1150 | -webkit-transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0);
1151 | transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); }
1152 |
1153 | .reveal[data-background-transition=concave] > .backgrounds .slide-background > .slide-background.past,
1154 | .reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=concave] {
1155 | opacity: 0;
1156 | -webkit-transform: translate3d(0, -100%, 0) rotateX(-90deg) translate3d(0, -100%, 0);
1157 | transform: translate3d(0, -100%, 0) rotateX(-90deg) translate3d(0, -100%, 0); }
1158 |
1159 | .reveal[data-background-transition=concave] > .backgrounds .slide-background > .slide-background.future,
1160 | .reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=concave] {
1161 | opacity: 0;
1162 | -webkit-transform: translate3d(0, 100%, 0) rotateX(90deg) translate3d(0, 100%, 0);
1163 | transform: translate3d(0, 100%, 0) rotateX(90deg) translate3d(0, 100%, 0); }
1164 |
1165 | /* Zoom */
1166 | .reveal[data-background-transition=zoom] > .backgrounds .slide-background,
1167 | .reveal > .backgrounds .slide-background[data-background-transition=zoom] {
1168 | transition-timing-function: ease; }
1169 |
1170 | .reveal[data-background-transition=zoom] > .backgrounds .slide-background.past,
1171 | .reveal > .backgrounds .slide-background.past[data-background-transition=zoom] {
1172 | opacity: 0;
1173 | visibility: hidden;
1174 | -webkit-transform: scale(16);
1175 | transform: scale(16); }
1176 |
1177 | .reveal[data-background-transition=zoom] > .backgrounds .slide-background.future,
1178 | .reveal > .backgrounds .slide-background.future[data-background-transition=zoom] {
1179 | opacity: 0;
1180 | visibility: hidden;
1181 | -webkit-transform: scale(0.2);
1182 | transform: scale(0.2); }
1183 |
1184 | .reveal[data-background-transition=zoom] > .backgrounds .slide-background > .slide-background.past,
1185 | .reveal > .backgrounds .slide-background > .slide-background.past[data-background-transition=zoom] {
1186 | opacity: 0;
1187 | visibility: hidden;
1188 | -webkit-transform: scale(16);
1189 | transform: scale(16); }
1190 |
1191 | .reveal[data-background-transition=zoom] > .backgrounds .slide-background > .slide-background.future,
1192 | .reveal > .backgrounds .slide-background > .slide-background.future[data-background-transition=zoom] {
1193 | opacity: 0;
1194 | visibility: hidden;
1195 | -webkit-transform: scale(0.2);
1196 | transform: scale(0.2); }
1197 |
1198 | /* Global transition speed settings */
1199 | .reveal[data-transition-speed="fast"] > .backgrounds .slide-background {
1200 | transition-duration: 400ms; }
1201 |
1202 | .reveal[data-transition-speed="slow"] > .backgrounds .slide-background {
1203 | transition-duration: 1200ms; }
1204 |
1205 | /*********************************************
1206 | * OVERVIEW
1207 | *********************************************/
1208 | .reveal.overview {
1209 | -webkit-perspective-origin: 50% 50%;
1210 | perspective-origin: 50% 50%;
1211 | -webkit-perspective: 700px;
1212 | perspective: 700px; }
1213 | .reveal.overview .slides {
1214 | -moz-transform-style: preserve-3d; }
1215 | .reveal.overview .slides section {
1216 | height: 100%;
1217 | top: 0 !important;
1218 | opacity: 1 !important;
1219 | overflow: hidden;
1220 | visibility: visible !important;
1221 | cursor: pointer;
1222 | box-sizing: border-box; }
1223 | .reveal.overview .slides section:hover,
1224 | .reveal.overview .slides section.present {
1225 | outline: 10px solid rgba(150, 150, 150, 0.4);
1226 | outline-offset: 10px; }
1227 | .reveal.overview .slides section .fragment {
1228 | opacity: 1;
1229 | transition: none; }
1230 | .reveal.overview .slides section:after,
1231 | .reveal.overview .slides section:before {
1232 | display: none !important; }
1233 | .reveal.overview .slides > section.stack {
1234 | padding: 0;
1235 | top: 0 !important;
1236 | background: none;
1237 | outline: none;
1238 | overflow: visible; }
1239 | .reveal.overview .backgrounds {
1240 | -webkit-perspective: inherit;
1241 | perspective: inherit;
1242 | -moz-transform-style: preserve-3d; }
1243 | .reveal.overview .backgrounds .slide-background {
1244 | opacity: 1;
1245 | visibility: visible;
1246 | outline: 10px solid rgba(150, 150, 150, 0.1);
1247 | outline-offset: 10px; }
1248 | .reveal.overview .backgrounds .slide-background.stack {
1249 | overflow: visible; }
1250 |
1251 | .reveal.overview .slides section,
1252 | .reveal.overview-deactivating .slides section {
1253 | transition: none; }
1254 |
1255 | .reveal.overview .backgrounds .slide-background,
1256 | .reveal.overview-deactivating .backgrounds .slide-background {
1257 | transition: none; }
1258 |
1259 | /*********************************************
1260 | * RTL SUPPORT
1261 | *********************************************/
1262 | .reveal.rtl .slides,
1263 | .reveal.rtl .slides h1,
1264 | .reveal.rtl .slides h2,
1265 | .reveal.rtl .slides h3,
1266 | .reveal.rtl .slides h4,
1267 | .reveal.rtl .slides h5,
1268 | .reveal.rtl .slides h6 {
1269 | direction: rtl;
1270 | font-family: sans-serif; }
1271 |
1272 | .reveal.rtl pre,
1273 | .reveal.rtl code {
1274 | direction: ltr; }
1275 |
1276 | .reveal.rtl ol,
1277 | .reveal.rtl ul {
1278 | text-align: right; }
1279 |
1280 | .reveal.rtl .progress span {
1281 | float: right; }
1282 |
1283 | /*********************************************
1284 | * PARALLAX BACKGROUND
1285 | *********************************************/
1286 | .reveal.has-parallax-background .backgrounds {
1287 | transition: all 0.8s ease; }
1288 |
1289 | /* Global transition speed settings */
1290 | .reveal.has-parallax-background[data-transition-speed="fast"] .backgrounds {
1291 | transition-duration: 400ms; }
1292 |
1293 | .reveal.has-parallax-background[data-transition-speed="slow"] .backgrounds {
1294 | transition-duration: 1200ms; }
1295 |
1296 | /*********************************************
1297 | * LINK PREVIEW OVERLAY
1298 | *********************************************/
1299 | .reveal .overlay {
1300 | position: absolute;
1301 | top: 0;
1302 | left: 0;
1303 | width: 100%;
1304 | height: 100%;
1305 | z-index: 1000;
1306 | background: rgba(0, 0, 0, 0.9);
1307 | opacity: 0;
1308 | visibility: hidden;
1309 | transition: all 0.3s ease; }
1310 |
1311 | .reveal .overlay.visible {
1312 | opacity: 1;
1313 | visibility: visible; }
1314 |
1315 | .reveal .overlay .spinner {
1316 | position: absolute;
1317 | display: block;
1318 | top: 50%;
1319 | left: 50%;
1320 | width: 32px;
1321 | height: 32px;
1322 | margin: -16px 0 0 -16px;
1323 | z-index: 10;
1324 | background-image: url(data:image/gif;base64,R0lGODlhIAAgAPMAAJmZmf%2F%2F%2F6%2Bvr8nJybW1tcDAwOjo6Nvb26ioqKOjo7Ozs%2FLy8vz8%2FAAAAAAAAAAAACH%2FC05FVFNDQVBFMi4wAwEAAAAh%2FhpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh%2BQQJCgAAACwAAAAAIAAgAAAE5xDISWlhperN52JLhSSdRgwVo1ICQZRUsiwHpTJT4iowNS8vyW2icCF6k8HMMBkCEDskxTBDAZwuAkkqIfxIQyhBQBFvAQSDITM5VDW6XNE4KagNh6Bgwe60smQUB3d4Rz1ZBApnFASDd0hihh12BkE9kjAJVlycXIg7CQIFA6SlnJ87paqbSKiKoqusnbMdmDC2tXQlkUhziYtyWTxIfy6BE8WJt5YJvpJivxNaGmLHT0VnOgSYf0dZXS7APdpB309RnHOG5gDqXGLDaC457D1zZ%2FV%2FnmOM82XiHRLYKhKP1oZmADdEAAAh%2BQQJCgAAACwAAAAAIAAgAAAE6hDISWlZpOrNp1lGNRSdRpDUolIGw5RUYhhHukqFu8DsrEyqnWThGvAmhVlteBvojpTDDBUEIFwMFBRAmBkSgOrBFZogCASwBDEY%2FCZSg7GSE0gSCjQBMVG023xWBhklAnoEdhQEfyNqMIcKjhRsjEdnezB%2BA4k8gTwJhFuiW4dokXiloUepBAp5qaKpp6%2BHo7aWW54wl7obvEe0kRuoplCGepwSx2jJvqHEmGt6whJpGpfJCHmOoNHKaHx61WiSR92E4lbFoq%2BB6QDtuetcaBPnW6%2BO7wDHpIiK9SaVK5GgV543tzjgGcghAgAh%2BQQJCgAAACwAAAAAIAAgAAAE7hDISSkxpOrN5zFHNWRdhSiVoVLHspRUMoyUakyEe8PTPCATW9A14E0UvuAKMNAZKYUZCiBMuBakSQKG8G2FzUWox2AUtAQFcBKlVQoLgQReZhQlCIJesQXI5B0CBnUMOxMCenoCfTCEWBsJColTMANldx15BGs8B5wlCZ9Po6OJkwmRpnqkqnuSrayqfKmqpLajoiW5HJq7FL1Gr2mMMcKUMIiJgIemy7xZtJsTmsM4xHiKv5KMCXqfyUCJEonXPN2rAOIAmsfB3uPoAK%2B%2BG%2Bw48edZPK%2BM6hLJpQg484enXIdQFSS1u6UhksENEQAAIfkECQoAAAAsAAAAACAAIAAABOcQyEmpGKLqzWcZRVUQnZYg1aBSh2GUVEIQ2aQOE%2BG%2BcD4ntpWkZQj1JIiZIogDFFyHI0UxQwFugMSOFIPJftfVAEoZLBbcLEFhlQiqGp1Vd140AUklUN3eCA51C1EWMzMCezCBBmkxVIVHBWd3HHl9JQOIJSdSnJ0TDKChCwUJjoWMPaGqDKannasMo6WnM562R5YluZRwur0wpgqZE7NKUm%2BFNRPIhjBJxKZteWuIBMN4zRMIVIhffcgojwCF117i4nlLnY5ztRLsnOk%2BaV%2BoJY7V7m76PdkS4trKcdg0Zc0tTcKkRAAAIfkECQoAAAAsAAAAACAAIAAABO4QyEkpKqjqzScpRaVkXZWQEximw1BSCUEIlDohrft6cpKCk5xid5MNJTaAIkekKGQkWyKHkvhKsR7ARmitkAYDYRIbUQRQjWBwJRzChi9CRlBcY1UN4g0%2FVNB0AlcvcAYHRyZPdEQFYV8ccwR5HWxEJ02YmRMLnJ1xCYp0Y5idpQuhopmmC2KgojKasUQDk5BNAwwMOh2RtRq5uQuPZKGIJQIGwAwGf6I0JXMpC8C7kXWDBINFMxS4DKMAWVWAGYsAdNqW5uaRxkSKJOZKaU3tPOBZ4DuK2LATgJhkPJMgTwKCdFjyPHEnKxFCDhEAACH5BAkKAAAALAAAAAAgACAAAATzEMhJaVKp6s2nIkolIJ2WkBShpkVRWqqQrhLSEu9MZJKK9y1ZrqYK9WiClmvoUaF8gIQSNeF1Er4MNFn4SRSDARWroAIETg1iVwuHjYB1kYc1mwruwXKC9gmsJXliGxc%2BXiUCby9ydh1sOSdMkpMTBpaXBzsfhoc5l58Gm5yToAaZhaOUqjkDgCWNHAULCwOLaTmzswadEqggQwgHuQsHIoZCHQMMQgQGubVEcxOPFAcMDAYUA85eWARmfSRQCdcMe0zeP1AAygwLlJtPNAAL19DARdPzBOWSm1brJBi45soRAWQAAkrQIykShQ9wVhHCwCQCACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiRMDjI0Fd30%2FiI2UA5GSS5UDj2l6NoqgOgN4gksEBgYFf0FDqKgHnyZ9OX8HrgYHdHpcHQULXAS2qKpENRg7eAMLC7kTBaixUYFkKAzWAAnLC7FLVxLWDBLKCwaKTULgEwbLA4hJtOkSBNqITT3xEgfLpBtzE%2FjiuL04RGEBgwWhShRgQExHBAAh%2BQQJCgAAACwAAAAAIAAgAAAE7xDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfZiCqGk5dTESJeaOAlClzsJsqwiJwiqnFrb2nS9kmIcgEsjQydLiIlHehhpejaIjzh9eomSjZR%2BipslWIRLAgMDOR2DOqKogTB9pCUJBagDBXR6XB0EBkIIsaRsGGMMAxoDBgYHTKJiUYEGDAzHC9EACcUGkIgFzgwZ0QsSBcXHiQvOwgDdEwfFs0sDzt4S6BK4xYjkDOzn0unFeBzOBijIm1Dgmg5YFQwsCMjp1oJ8LyIAACH5BAkKAAAALAAAAAAgACAAAATwEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GGl6NoiPOH16iZKNlH6KmyWFOggHhEEvAwwMA0N9GBsEC6amhnVcEwavDAazGwIDaH1ipaYLBUTCGgQDA8NdHz0FpqgTBwsLqAbWAAnIA4FWKdMLGdYGEgraigbT0OITBcg5QwPT4xLrROZL6AuQAPUS7bxLpoWidY0JtxLHKhwwMJBTHgPKdEQAACH5BAkKAAAALAAAAAAgACAAAATrEMhJaVKp6s2nIkqFZF2VIBWhUsJaTokqUCoBq%2BE71SRQeyqUToLA7VxF0JDyIQh%2FMVVPMt1ECZlfcjZJ9mIKoaTl1MRIl5o4CUKXOwmyrCInCKqcWtvadL2SYhyASyNDJ0uIiUd6GAULDJCRiXo1CpGXDJOUjY%2BYip9DhToJA4RBLwMLCwVDfRgbBAaqqoZ1XBMHswsHtxtFaH1iqaoGNgAIxRpbFAgfPQSqpbgGBqUD1wBXeCYp1AYZ19JJOYgH1KwA4UBvQwXUBxPqVD9L3sbp2BNk2xvvFPJd%2BMFCN6HAAIKgNggY0KtEBAAh%2BQQJCgAAACwAAAAAIAAgAAAE6BDISWlSqerNpyJKhWRdlSAVoVLCWk6JKlAqAavhO9UkUHsqlE6CwO1cRdCQ8iEIfzFVTzLdRAmZX3I2SfYIDMaAFdTESJeaEDAIMxYFqrOUaNW4E4ObYcCXaiBVEgULe0NJaxxtYksjh2NLkZISgDgJhHthkpU4mW6blRiYmZOlh4JWkDqILwUGBnE6TYEbCgevr0N1gH4At7gHiRpFaLNrrq8HNgAJA70AWxQIH1%2BvsYMDAzZQPC9VCNkDWUhGkuE5PxJNwiUK4UfLzOlD4WvzAHaoG9nxPi5d%2BjYUqfAhhykOFwJWiAAAIfkECQoAAAAsAAAAACAAIAAABPAQyElpUqnqzaciSoVkXVUMFaFSwlpOCcMYlErAavhOMnNLNo8KsZsMZItJEIDIFSkLGQoQTNhIsFehRww2CQLKF0tYGKYSg%2BygsZIuNqJksKgbfgIGepNo2cIUB3V1B3IvNiBYNQaDSTtfhhx0CwVPI0UJe0%2Bbm4g5VgcGoqOcnjmjqDSdnhgEoamcsZuXO1aWQy8KAwOAuTYYGwi7w5h%2BKr0SJ8MFihpNbx%2B4Erq7BYBuzsdiH1jCAzoSfl0rVirNbRXlBBlLX%2BBP0XJLAPGzTkAuAOqb0WT5AH7OcdCm5B8TgRwSRKIHQtaLCwg1RAAAOwAAAAAAAAAAAA%3D%3D);
1325 | visibility: visible;
1326 | opacity: 0.6;
1327 | transition: all 0.3s ease; }
1328 |
1329 | .reveal .overlay header {
1330 | position: absolute;
1331 | left: 0;
1332 | top: 0;
1333 | width: 100%;
1334 | height: 40px;
1335 | z-index: 2;
1336 | border-bottom: 1px solid #222; }
1337 |
1338 | .reveal .overlay header a {
1339 | display: inline-block;
1340 | width: 40px;
1341 | height: 40px;
1342 | line-height: 36px;
1343 | padding: 0 10px;
1344 | float: right;
1345 | opacity: 0.6;
1346 | box-sizing: border-box; }
1347 |
1348 | .reveal .overlay header a:hover {
1349 | opacity: 1; }
1350 |
1351 | .reveal .overlay header a .icon {
1352 | display: inline-block;
1353 | width: 20px;
1354 | height: 20px;
1355 | background-position: 50% 50%;
1356 | background-size: 100%;
1357 | background-repeat: no-repeat; }
1358 |
1359 | .reveal .overlay header a.close .icon {
1360 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABkklEQVRYR8WX4VHDMAxG6wnoJrABZQPYBCaBTWAD2g1gE5gg6OOsXuxIlr40d81dfrSJ9V4c2VLK7spHuTJ/5wpM07QXuXc5X0opX2tEJcadjHuV80li/FgxTIEK/5QBCICBD6xEhSMGHgQPgBgLiYVAB1dpSqKDawxTohFw4JSEA3clzgIBPCURwE2JucBR7rhPJJv5OpJwDX+SfDjgx1wACQeJG1aChP9K/IMmdZ8DtESV1WyP3Bt4MwM6sj4NMxMYiqUWHQu4KYA/SYkIjOsm3BXYWMKFDwU2khjCQ4ELJUJ4SmClRArOCmSXGuKma0fYD5CbzHxFpCSGAhfAVSSUGDUk2BWZaff2g6GE15BsBQ9nwmpIGDiyHQddwNTMKkbZaf9fajXQca1EX44puJZUsnY0ObGmITE3GVLCbEhQUjGVt146j6oasWN+49Vph2w1pZ5EansNZqKBm1txbU57iRRcZ86RWMDdWtBJUHBHwoQPi1GV+JCbntmvok7iTX4/Up9mgyTc/FJYDTcndgH/AA5A/CHsyEkVAAAAAElFTkSuQmCC); }
1361 |
1362 | .reveal .overlay header a.external .icon {
1363 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAcElEQVRYR+2WSQoAIQwEzf8f7XiOMkUQxUPlGkM3hVmiQfQR9GYnH1SsAQlI4DiBqkCMoNb9y2e90IAEJPAcgdznU9+engMaeJ7Azh5Y1U67gAho4DqBqmB1buAf0MB1AlVBek83ZPkmJMGc1wAR+AAqod/B97TRpQAAAABJRU5ErkJggg==); }
1364 |
1365 | .reveal .overlay .viewport {
1366 | position: absolute;
1367 | display: -webkit-box;
1368 | display: -ms-flexbox;
1369 | display: flex;
1370 | top: 40px;
1371 | right: 0;
1372 | bottom: 0;
1373 | left: 0; }
1374 |
1375 | .reveal .overlay.overlay-preview .viewport iframe {
1376 | width: 100%;
1377 | height: 100%;
1378 | max-width: 100%;
1379 | max-height: 100%;
1380 | border: 0;
1381 | opacity: 0;
1382 | visibility: hidden;
1383 | transition: all 0.3s ease; }
1384 |
1385 | .reveal .overlay.overlay-preview.loaded .viewport iframe {
1386 | opacity: 1;
1387 | visibility: visible; }
1388 |
1389 | .reveal .overlay.overlay-preview.loaded .viewport-inner {
1390 | position: absolute;
1391 | z-index: -1;
1392 | left: 0;
1393 | top: 45%;
1394 | width: 100%;
1395 | text-align: center;
1396 | letter-spacing: normal; }
1397 |
1398 | .reveal .overlay.overlay-preview .x-frame-error {
1399 | opacity: 0;
1400 | transition: opacity 0.3s ease 0.3s; }
1401 |
1402 | .reveal .overlay.overlay-preview.loaded .x-frame-error {
1403 | opacity: 1; }
1404 |
1405 | .reveal .overlay.overlay-preview.loaded .spinner {
1406 | opacity: 0;
1407 | visibility: hidden;
1408 | -webkit-transform: scale(0.2);
1409 | transform: scale(0.2); }
1410 |
1411 | .reveal .overlay.overlay-help .viewport {
1412 | overflow: auto;
1413 | color: #fff; }
1414 |
1415 | .reveal .overlay.overlay-help .viewport .viewport-inner {
1416 | width: 600px;
1417 | margin: auto;
1418 | padding: 20px 20px 80px 20px;
1419 | text-align: center;
1420 | letter-spacing: normal; }
1421 |
1422 | .reveal .overlay.overlay-help .viewport .viewport-inner .title {
1423 | font-size: 20px; }
1424 |
1425 | .reveal .overlay.overlay-help .viewport .viewport-inner table {
1426 | border: 1px solid #fff;
1427 | border-collapse: collapse;
1428 | font-size: 16px; }
1429 |
1430 | .reveal .overlay.overlay-help .viewport .viewport-inner table th,
1431 | .reveal .overlay.overlay-help .viewport .viewport-inner table td {
1432 | width: 200px;
1433 | padding: 14px;
1434 | border: 1px solid #fff;
1435 | vertical-align: middle; }
1436 |
1437 | .reveal .overlay.overlay-help .viewport .viewport-inner table th {
1438 | padding-top: 20px;
1439 | padding-bottom: 20px; }
1440 |
1441 | /*********************************************
1442 | * PLAYBACK COMPONENT
1443 | *********************************************/
1444 | .reveal .playback {
1445 | position: absolute;
1446 | left: 15px;
1447 | bottom: 20px;
1448 | z-index: 30;
1449 | cursor: pointer;
1450 | transition: all 400ms ease;
1451 | -webkit-tap-highlight-color: transparent; }
1452 |
1453 | .reveal.overview .playback {
1454 | opacity: 0;
1455 | visibility: hidden; }
1456 |
1457 | /*********************************************
1458 | * ROLLING LINKS
1459 | *********************************************/
1460 | .reveal .roll {
1461 | display: inline-block;
1462 | line-height: 1.2;
1463 | overflow: hidden;
1464 | vertical-align: top;
1465 | -webkit-perspective: 400px;
1466 | perspective: 400px;
1467 | -webkit-perspective-origin: 50% 50%;
1468 | perspective-origin: 50% 50%; }
1469 |
1470 | .reveal .roll:hover {
1471 | background: none;
1472 | text-shadow: none; }
1473 |
1474 | .reveal .roll span {
1475 | display: block;
1476 | position: relative;
1477 | padding: 0 2px;
1478 | pointer-events: none;
1479 | transition: all 400ms ease;
1480 | -webkit-transform-origin: 50% 0%;
1481 | transform-origin: 50% 0%;
1482 | -webkit-transform-style: preserve-3d;
1483 | transform-style: preserve-3d;
1484 | -webkit-backface-visibility: hidden;
1485 | backface-visibility: hidden; }
1486 |
1487 | .reveal .roll:hover span {
1488 | background: rgba(0, 0, 0, 0.5);
1489 | -webkit-transform: translate3d(0px, 0px, -45px) rotateX(90deg);
1490 | transform: translate3d(0px, 0px, -45px) rotateX(90deg); }
1491 |
1492 | .reveal .roll span:after {
1493 | content: attr(data-title);
1494 | display: block;
1495 | position: absolute;
1496 | left: 0;
1497 | top: 0;
1498 | padding: 0 2px;
1499 | -webkit-backface-visibility: hidden;
1500 | backface-visibility: hidden;
1501 | -webkit-transform-origin: 50% 0%;
1502 | transform-origin: 50% 0%;
1503 | -webkit-transform: translate3d(0px, 110%, 0px) rotateX(-90deg);
1504 | transform: translate3d(0px, 110%, 0px) rotateX(-90deg); }
1505 |
1506 | /*********************************************
1507 | * SPEAKER NOTES
1508 | *********************************************/
1509 | .reveal aside.notes {
1510 | display: none; }
1511 |
1512 | .reveal .speaker-notes {
1513 | display: none;
1514 | position: absolute;
1515 | width: 25vw;
1516 | height: 100%;
1517 | top: 0;
1518 | left: 100%;
1519 | padding: 14px 18px 14px 18px;
1520 | z-index: 1;
1521 | font-size: 18px;
1522 | line-height: 1.4;
1523 | border: 1px solid rgba(0, 0, 0, 0.05);
1524 | color: #222;
1525 | background-color: #f5f5f5;
1526 | overflow: auto;
1527 | box-sizing: border-box;
1528 | text-align: left;
1529 | font-family: Helvetica, sans-serif;
1530 | -webkit-overflow-scrolling: touch; }
1531 | .reveal .speaker-notes .notes-placeholder {
1532 | color: #ccc;
1533 | font-style: italic; }
1534 | .reveal .speaker-notes:focus {
1535 | outline: none; }
1536 | .reveal .speaker-notes:before {
1537 | content: 'Speaker notes';
1538 | display: block;
1539 | margin-bottom: 10px;
1540 | opacity: 0.5; }
1541 |
1542 | .reveal.show-notes {
1543 | max-width: 75vw;
1544 | overflow: visible; }
1545 |
1546 | .reveal.show-notes .speaker-notes {
1547 | display: block; }
1548 |
1549 | @media screen and (min-width: 1600px) {
1550 | .reveal .speaker-notes {
1551 | font-size: 20px; } }
1552 |
1553 | @media screen and (max-width: 1024px) {
1554 | .reveal.show-notes {
1555 | border-left: 0;
1556 | max-width: none;
1557 | max-height: 70%;
1558 | overflow: visible; }
1559 | .reveal.show-notes .speaker-notes {
1560 | top: 100%;
1561 | left: 0;
1562 | width: 100%;
1563 | height: 42.8571428571%; } }
1564 |
1565 | @media screen and (max-width: 600px) {
1566 | .reveal.show-notes {
1567 | max-height: 60%; }
1568 | .reveal.show-notes .speaker-notes {
1569 | top: 100%;
1570 | height: 66.6666666667%; }
1571 | .reveal .speaker-notes {
1572 | font-size: 14px; } }
1573 |
1574 | /*********************************************
1575 | * ZOOM PLUGIN
1576 | *********************************************/
1577 | .zoomed .reveal *,
1578 | .zoomed .reveal *:before,
1579 | .zoomed .reveal *:after {
1580 | -webkit-backface-visibility: visible !important;
1581 | backface-visibility: visible !important; }
1582 |
1583 | .zoomed .reveal .progress,
1584 | .zoomed .reveal .controls {
1585 | opacity: 0; }
1586 |
1587 | .zoomed .reveal .roll span {
1588 | background: none; }
1589 |
1590 | .zoomed .reveal .roll span:after {
1591 | visibility: hidden; }
1592 |
--------------------------------------------------------------------------------
/css/theme/README.md:
--------------------------------------------------------------------------------
1 | ## Dependencies
2 |
3 | Themes are written using Sass to keep things modular and reduce the need for repeated selectors across files. Make sure that you have the reveal.js development environment including the Grunt dependencies installed before proceeding: https://github.com/hakimel/reveal.js#full-setup
4 |
5 | ## Creating a Theme
6 |
7 | To create your own theme, start by duplicating a ```.scss``` file in [/css/theme/source](https://github.com/hakimel/reveal.js/blob/master/css/theme/source). It will be automatically compiled by Grunt from Sass to CSS (see the [Gruntfile](https://github.com/hakimel/reveal.js/blob/master/Gruntfile.js)) when you run `npm run build -- css-themes`.
8 |
9 | Each theme file does four things in the following order:
10 |
11 | 1. **Include [/css/theme/template/mixins.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/mixins.scss)**
12 | Shared utility functions.
13 |
14 | 2. **Include [/css/theme/template/settings.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/settings.scss)**
15 | Declares a set of custom variables that the template file (step 4) expects. Can be overridden in step 3.
16 |
17 | 3. **Override**
18 | This is where you override the default theme. Either by specifying variables (see [settings.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/settings.scss) for reference) or by adding any selectors and styles you please.
19 |
20 | 4. **Include [/css/theme/template/theme.scss](https://github.com/hakimel/reveal.js/blob/master/css/theme/template/theme.scss)**
21 | The template theme file which will generate final CSS output based on the currently defined variables.
22 |
--------------------------------------------------------------------------------
/css/theme/serif.css:
--------------------------------------------------------------------------------
1 | /**
2 | * A simple theme for reveal.js presentations, similar
3 | * to the default theme. The accent color is brown.
4 | *
5 | * This theme is Copyright (C) 2012-2013 Owen Versteeg, http://owenversteeg.com - it is MIT licensed.
6 | */
7 | .reveal a {
8 | line-height: 1.3em; }
9 |
10 | /*********************************************
11 | * GLOBAL STYLES
12 | *********************************************/
13 | body {
14 | background: #F0F1EB;
15 | background-color: #F0F1EB; }
16 |
17 | .reveal {
18 | font-family: "Palatino Linotype", "Book Antiqua", Palatino, FreeSerif, serif;
19 | font-size: 40px;
20 | font-weight: normal;
21 | color: #000; }
22 |
23 | ::selection {
24 | color: #fff;
25 | background: #26351C;
26 | text-shadow: none; }
27 |
28 | ::-moz-selection {
29 | color: #fff;
30 | background: #26351C;
31 | text-shadow: none; }
32 |
33 | .reveal .slides section,
34 | .reveal .slides section > section {
35 | line-height: 1.3;
36 | font-weight: inherit; }
37 |
38 | /*********************************************
39 | * HEADERS
40 | *********************************************/
41 | .reveal h1,
42 | .reveal h2,
43 | .reveal h3,
44 | .reveal h4,
45 | .reveal h5,
46 | .reveal h6 {
47 | margin: 0 0 20px 0;
48 | color: #383D3D;
49 | font-family: "Palatino Linotype", "Book Antiqua", Palatino, FreeSerif, serif;
50 | font-weight: normal;
51 | line-height: 1.2;
52 | letter-spacing: normal;
53 | text-transform: none;
54 | text-shadow: none;
55 | word-wrap: break-word; }
56 |
57 | .reveal h1 {
58 | font-size: 3.77em; }
59 |
60 | .reveal h2 {
61 | font-size: 2.11em; }
62 |
63 | .reveal h3 {
64 | font-size: 1.55em; }
65 |
66 | .reveal h4 {
67 | font-size: 1em; }
68 |
69 | .reveal h1 {
70 | text-shadow: none; }
71 |
72 | /*********************************************
73 | * OTHER
74 | *********************************************/
75 | .reveal p {
76 | margin: 20px 0;
77 | line-height: 1.3; }
78 |
79 | /* Ensure certain elements are never larger than the slide itself */
80 | .reveal img,
81 | .reveal video,
82 | .reveal iframe {
83 | max-width: 95%;
84 | max-height: 95%; }
85 |
86 | .reveal strong,
87 | .reveal b {
88 | font-weight: bold; }
89 |
90 | .reveal em {
91 | font-style: italic; }
92 |
93 | .reveal ol,
94 | .reveal dl,
95 | .reveal ul {
96 | display: inline-block;
97 | text-align: left;
98 | margin: 0 0 0 1em; }
99 |
100 | .reveal ol {
101 | list-style-type: decimal; }
102 |
103 | .reveal ul {
104 | list-style-type: disc; }
105 |
106 | .reveal ul ul {
107 | list-style-type: square; }
108 |
109 | .reveal ul ul ul {
110 | list-style-type: circle; }
111 |
112 | .reveal ul ul,
113 | .reveal ul ol,
114 | .reveal ol ol,
115 | .reveal ol ul {
116 | display: block;
117 | margin-left: 40px; }
118 |
119 | .reveal dt {
120 | font-weight: bold; }
121 |
122 | .reveal dd {
123 | margin-left: 40px; }
124 |
125 | .reveal blockquote {
126 | display: block;
127 | position: relative;
128 | width: 70%;
129 | margin: 20px auto;
130 | padding: 5px;
131 | font-style: italic;
132 | background: rgba(255, 255, 255, 0.05);
133 | box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); }
134 |
135 | .reveal blockquote p:first-child,
136 | .reveal blockquote p:last-child {
137 | display: inline-block; }
138 |
139 | .reveal q {
140 | font-style: italic; }
141 |
142 | .reveal pre {
143 | display: block;
144 | position: relative;
145 | width: 90%;
146 | margin: 20px auto;
147 | text-align: left;
148 | font-size: 0.55em;
149 | font-family: monospace;
150 | line-height: 1.2em;
151 | word-wrap: break-word;
152 | box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); }
153 |
154 | .reveal code {
155 | font-family: monospace;
156 | text-transform: none; }
157 |
158 | .reveal pre code {
159 | display: block;
160 | padding: 5px;
161 | overflow: auto;
162 | max-height: 400px;
163 | word-wrap: normal; }
164 |
165 | .reveal table {
166 | margin: auto;
167 | border-collapse: collapse;
168 | border-spacing: 0; }
169 |
170 | .reveal table th {
171 | font-weight: bold; }
172 |
173 | .reveal table th,
174 | .reveal table td {
175 | text-align: left;
176 | padding: 0.2em 0.5em 0.2em 0.5em;
177 | border-bottom: 1px solid; }
178 |
179 | .reveal table th[align="center"],
180 | .reveal table td[align="center"] {
181 | text-align: center; }
182 |
183 | .reveal table th[align="right"],
184 | .reveal table td[align="right"] {
185 | text-align: right; }
186 |
187 | .reveal table tbody tr:last-child th,
188 | .reveal table tbody tr:last-child td {
189 | border-bottom: none; }
190 |
191 | .reveal sup {
192 | vertical-align: super;
193 | font-size: smaller; }
194 |
195 | .reveal sub {
196 | vertical-align: sub;
197 | font-size: smaller; }
198 |
199 | .reveal small {
200 | display: inline-block;
201 | font-size: 0.6em;
202 | line-height: 1.2em;
203 | vertical-align: top; }
204 |
205 | .reveal small * {
206 | vertical-align: top; }
207 |
208 | /*********************************************
209 | * LINKS
210 | *********************************************/
211 | .reveal a {
212 | color: #51483D;
213 | text-decoration: none;
214 | -webkit-transition: color .15s ease;
215 | -moz-transition: color .15s ease;
216 | transition: color .15s ease; }
217 |
218 | .reveal a:hover {
219 | color: #8b7c69;
220 | text-shadow: none;
221 | border: none; }
222 |
223 | .reveal .roll span:after {
224 | color: #fff;
225 | background: #25211c; }
226 |
227 | /*********************************************
228 | * IMAGES
229 | *********************************************/
230 | .reveal section img {
231 | margin: 15px 0px;
232 | background: rgba(255, 255, 255, 0.12);
233 | border: 4px solid #000;
234 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); }
235 |
236 | .reveal section img.plain {
237 | border: 0;
238 | box-shadow: none; }
239 |
240 | .reveal a img {
241 | -webkit-transition: all .15s linear;
242 | -moz-transition: all .15s linear;
243 | transition: all .15s linear; }
244 |
245 | .reveal a:hover img {
246 | background: rgba(255, 255, 255, 0.2);
247 | border-color: #51483D;
248 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); }
249 |
250 | /*********************************************
251 | * NAVIGATION CONTROLS
252 | *********************************************/
253 | .reveal .controls {
254 | color: #51483D; }
255 |
256 | /*********************************************
257 | * PROGRESS BAR
258 | *********************************************/
259 | .reveal .progress {
260 | background: rgba(0, 0, 0, 0.2);
261 | color: #51483D; }
262 |
263 | .reveal .progress span {
264 | -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
265 | -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
266 | transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
267 |
268 | /*********************************************
269 | * PRINT BACKGROUND
270 | *********************************************/
271 | @media print {
272 | .backgrounds {
273 | background-color: #F0F1EB; } }
274 |
--------------------------------------------------------------------------------
/guion.md:
--------------------------------------------------------------------------------
1 | * ¿Qué es micropython?
2 | * Diferencias entre micropython y arduino
3 | * ¿Qué me hace falta?
4 | * Instalando micropython
5 | * Primeros pasos
6 | * Conexión serie
7 | * Conexión por wifi: WebREPL
8 | * Sistema de archivos
9 | * boot.py
10 | * main.py
11 | * Conexión a un AP *
12 | * Configuración como AP
13 | * Servicio web
14 | * Sockets
15 | * Salida digital
16 | * Lectura digital
17 | * Lectura de sensor
18 | * Lectura de potenciómetro
19 | * Pulse width modulation (PWM)
20 |
21 | Plataformas: fiware, thingspeak, openhab, home assistant
22 |
23 | La idea sería hacer un pequeño IoT para el hogar el cual nos dé medidas, podamos realizar acciones a través de él y haga acciones automáticas.
24 | * Lectura de un pulsador -> encendido de un led
25 | * Temperatura / humedad
26 | * LDR para el control automático de un led
27 | * Control mediante web
--------------------------------------------------------------------------------
/img/configure_webrepl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/img/configure_webrepl.png
--------------------------------------------------------------------------------
/img/devkit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/img/devkit.png
--------------------------------------------------------------------------------
/img/download_micropython.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/img/download_micropython.png
--------------------------------------------------------------------------------
/img/esp8266_block_diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/img/esp8266_block_diagram.png
--------------------------------------------------------------------------------
/img/flashing_esp8266.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/img/flashing_esp8266.png
--------------------------------------------------------------------------------
/img/installing_esptool.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/img/installing_esptool.png
--------------------------------------------------------------------------------
/img/led_builtin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/img/led_builtin.jpg
--------------------------------------------------------------------------------
/img/modules.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/img/modules.png
--------------------------------------------------------------------------------
/img/mqtt-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/img/mqtt-diagram.png
--------------------------------------------------------------------------------
/img/new_wifi.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/img/new_wifi.jpg
--------------------------------------------------------------------------------
/img/questions.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/img/questions.jpg
--------------------------------------------------------------------------------
/img/toi.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/img/toi.jpg
--------------------------------------------------------------------------------
/img/webrepl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/img/webrepl.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | MicroPython
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/js/markdown.js:
--------------------------------------------------------------------------------
1 | /**
2 | * The reveal.js markdown plugin. Handles parsing of
3 | * markdown inside of presentations as well as loading
4 | * of external markdown documents.
5 | */
6 | (function( root, factory ) {
7 | if (typeof define === 'function' && define.amd) {
8 | root.marked = require( './marked' );
9 | root.RevealMarkdown = factory( root.marked );
10 | root.RevealMarkdown.initialize();
11 | } else if( typeof exports === 'object' ) {
12 | module.exports = factory( require( './marked' ) );
13 | } else {
14 | // Browser globals (root is window)
15 | root.RevealMarkdown = factory( root.marked );
16 | root.RevealMarkdown.initialize();
17 | }
18 | }( this, function( marked ) {
19 |
20 | var DEFAULT_SLIDE_SEPARATOR = '^\r?\n---\r?\n$',
21 | DEFAULT_NOTES_SEPARATOR = 'notes?:',
22 | DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR = '\\\.element\\\s*?(.+?)$',
23 | DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR = '\\\.slide:\\\s*?(\\\S.+?)$';
24 |
25 | var SCRIPT_END_PLACEHOLDER = '__SCRIPT_END__';
26 |
27 |
28 | /**
29 | * Retrieves the markdown contents of a slide section
30 | * element. Normalizes leading tabs/whitespace.
31 | */
32 | function getMarkdownFromSlide( section ) {
33 |
34 | // look for a ' );
42 |
43 | var leadingWs = text.match( /^\n?(\s*)/ )[1].length,
44 | leadingTabs = text.match( /^\n?(\t*)/ )[1].length;
45 |
46 | if( leadingTabs > 0 ) {
47 | text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' );
48 | }
49 | else if( leadingWs > 1 ) {
50 | text = text.replace( new RegExp('\\n? {' + leadingWs + '}', 'g'), '\n' );
51 | }
52 |
53 | return text;
54 |
55 | }
56 |
57 | /**
58 | * Given a markdown slide section element, this will
59 | * return all arguments that aren't related to markdown
60 | * parsing. Used to forward any other user-defined arguments
61 | * to the output markdown slide.
62 | */
63 | function getForwardedAttributes( section ) {
64 |
65 | var attributes = section.attributes;
66 | var result = [];
67 |
68 | for( var i = 0, len = attributes.length; i < len; i++ ) {
69 | var name = attributes[i].name,
70 | value = attributes[i].value;
71 |
72 | // disregard attributes that are used for markdown loading/parsing
73 | if( /data\-(markdown|separator|vertical|notes)/gi.test( name ) ) continue;
74 |
75 | if( value ) {
76 | result.push( name + '="' + value + '"' );
77 | }
78 | else {
79 | result.push( name );
80 | }
81 | }
82 |
83 | return result.join( ' ' );
84 |
85 | }
86 |
87 | /**
88 | * Inspects the given options and fills out default
89 | * values for what's not defined.
90 | */
91 | function getSlidifyOptions( options ) {
92 |
93 | options = options || {};
94 | options.separator = options.separator || DEFAULT_SLIDE_SEPARATOR;
95 | options.notesSeparator = options.notesSeparator || DEFAULT_NOTES_SEPARATOR;
96 | options.attributes = options.attributes || '';
97 |
98 | return options;
99 |
100 | }
101 |
102 | /**
103 | * Helper function for constructing a markdown slide.
104 | */
105 | function createMarkdownSlide( content, options ) {
106 |
107 | options = getSlidifyOptions( options );
108 |
109 | var notesMatch = content.split( new RegExp( options.notesSeparator, 'mgi' ) );
110 |
111 | if( notesMatch.length === 2 ) {
112 | content = notesMatch[0] + '' + marked(notesMatch[1].trim()) + ' ';
113 | }
114 |
115 | // prevent script end tags in the content from interfering
116 | // with parsing
117 | content = content.replace( /<\/script>/g, SCRIPT_END_PLACEHOLDER );
118 |
119 | return '';
120 |
121 | }
122 |
123 | /**
124 | * Parses a data string into multiple slides based
125 | * on the passed in separator arguments.
126 | */
127 | function slidify( markdown, options ) {
128 |
129 | options = getSlidifyOptions( options );
130 |
131 | var separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ),
132 | horizontalSeparatorRegex = new RegExp( options.separator );
133 |
134 | var matches,
135 | lastIndex = 0,
136 | isHorizontal,
137 | wasHorizontal = true,
138 | content,
139 | sectionStack = [];
140 |
141 | // iterate until all blocks between separators are stacked up
142 | while( matches = separatorRegex.exec( markdown ) ) {
143 | notes = null;
144 |
145 | // determine direction (horizontal by default)
146 | isHorizontal = horizontalSeparatorRegex.test( matches[0] );
147 |
148 | if( !isHorizontal && wasHorizontal ) {
149 | // create vertical stack
150 | sectionStack.push( [] );
151 | }
152 |
153 | // pluck slide content from markdown input
154 | content = markdown.substring( lastIndex, matches.index );
155 |
156 | if( isHorizontal && wasHorizontal ) {
157 | // add to horizontal stack
158 | sectionStack.push( content );
159 | }
160 | else {
161 | // add to vertical stack
162 | sectionStack[sectionStack.length-1].push( content );
163 | }
164 |
165 | lastIndex = separatorRegex.lastIndex;
166 | wasHorizontal = isHorizontal;
167 | }
168 |
169 | // add the remaining slide
170 | ( wasHorizontal ? sectionStack : sectionStack[sectionStack.length-1] ).push( markdown.substring( lastIndex ) );
171 |
172 | var markdownSections = '';
173 |
174 | // flatten the hierarchical stack, and insert tags
175 | for( var i = 0, len = sectionStack.length; i < len; i++ ) {
176 | // vertical
177 | if( sectionStack[i] instanceof Array ) {
178 | markdownSections += '';
179 |
180 | sectionStack[i].forEach( function( child ) {
181 | markdownSections += '' + createMarkdownSlide( child, options ) + ' ';
182 | } );
183 |
184 | markdownSections += ' ';
185 | }
186 | else {
187 | markdownSections += '' + createMarkdownSlide( sectionStack[i], options ) + ' ';
188 | }
189 | }
190 |
191 | return markdownSections;
192 |
193 | }
194 |
195 | /**
196 | * Parses any current data-markdown slides, splits
197 | * multi-slide markdown into separate sections and
198 | * handles loading of external markdown.
199 | */
200 | function processSlides() {
201 |
202 | var sections = document.querySelectorAll( '[data-markdown]'),
203 | section;
204 |
205 | for( var i = 0, len = sections.length; i < len; i++ ) {
206 |
207 | section = sections[i];
208 |
209 | if( section.getAttribute( 'data-markdown' ).length ) {
210 |
211 | var xhr = new XMLHttpRequest(),
212 | url = section.getAttribute( 'data-markdown' );
213 |
214 | datacharset = section.getAttribute( 'data-charset' );
215 |
216 | // see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes
217 | if( datacharset != null && datacharset != '' ) {
218 | xhr.overrideMimeType( 'text/html; charset=' + datacharset );
219 | }
220 |
221 | xhr.onreadystatechange = function() {
222 | if( xhr.readyState === 4 ) {
223 | // file protocol yields status code 0 (useful for local debug, mobile applications etc.)
224 | if ( ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status === 0 ) {
225 |
226 | section.outerHTML = slidify( xhr.responseText, {
227 | separator: section.getAttribute( 'data-separator' ),
228 | verticalSeparator: section.getAttribute( 'data-separator-vertical' ),
229 | notesSeparator: section.getAttribute( 'data-separator-notes' ),
230 | attributes: getForwardedAttributes( section )
231 | });
232 |
233 | }
234 | else {
235 |
236 | section.outerHTML = '' +
237 | 'ERROR: The attempt to fetch ' + url + ' failed with HTTP status ' + xhr.status + '.' +
238 | 'Check your browser\'s JavaScript console for more details.' +
239 | 'Remember that you need to serve the presentation HTML from a HTTP server.
' +
240 | ' ';
241 |
242 | }
243 | }
244 | };
245 |
246 | xhr.open( 'GET', url, false );
247 |
248 | try {
249 | xhr.send();
250 | }
251 | catch ( e ) {
252 | alert( 'Failed to get the Markdown file ' + url + '. Make sure that the presentation and the file are served by a HTTP server and the file can be found there. ' + e );
253 | }
254 |
255 | }
256 | else if( section.getAttribute( 'data-separator' ) || section.getAttribute( 'data-separator-vertical' ) || section.getAttribute( 'data-separator-notes' ) ) {
257 |
258 | section.outerHTML = slidify( getMarkdownFromSlide( section ), {
259 | separator: section.getAttribute( 'data-separator' ),
260 | verticalSeparator: section.getAttribute( 'data-separator-vertical' ),
261 | notesSeparator: section.getAttribute( 'data-separator-notes' ),
262 | attributes: getForwardedAttributes( section )
263 | });
264 |
265 | }
266 | else {
267 | section.innerHTML = createMarkdownSlide( getMarkdownFromSlide( section ) );
268 | }
269 | }
270 |
271 | }
272 |
273 | /**
274 | * Check if a node value has the attributes pattern.
275 | * If yes, extract it and add that value as one or several attributes
276 | * the the terget element.
277 | *
278 | * You need Cache Killer on Chrome to see the effect on any FOM transformation
279 | * directly on refresh (F5)
280 | * http://stackoverflow.com/questions/5690269/disabling-chrome-cache-for-website-development/7000899#answer-11786277
281 | */
282 | function addAttributeInElement( node, elementTarget, separator ) {
283 |
284 | var mardownClassesInElementsRegex = new RegExp( separator, 'mg' );
285 | var mardownClassRegex = new RegExp( "([^\"= ]+?)=\"([^\"=]+?)\"", 'mg' );
286 | var nodeValue = node.nodeValue;
287 | if( matches = mardownClassesInElementsRegex.exec( nodeValue ) ) {
288 |
289 | var classes = matches[1];
290 | nodeValue = nodeValue.substring( 0, matches.index ) + nodeValue.substring( mardownClassesInElementsRegex.lastIndex );
291 | node.nodeValue = nodeValue;
292 | while( matchesClass = mardownClassRegex.exec( classes ) ) {
293 | elementTarget.setAttribute( matchesClass[1], matchesClass[2] );
294 | }
295 | return true;
296 | }
297 | return false;
298 | }
299 |
300 | /**
301 | * Add attributes to the parent element of a text node,
302 | * or the element of an attribute node.
303 | */
304 | function addAttributes( section, element, previousElement, separatorElementAttributes, separatorSectionAttributes ) {
305 |
306 | if ( element != null && element.childNodes != undefined && element.childNodes.length > 0 ) {
307 | previousParentElement = element;
308 | for( var i = 0; i < element.childNodes.length; i++ ) {
309 | childElement = element.childNodes[i];
310 | if ( i > 0 ) {
311 | j = i - 1;
312 | while ( j >= 0 ) {
313 | aPreviousChildElement = element.childNodes[j];
314 | if ( typeof aPreviousChildElement.setAttribute == 'function' && aPreviousChildElement.tagName != "BR" ) {
315 | previousParentElement = aPreviousChildElement;
316 | break;
317 | }
318 | j = j - 1;
319 | }
320 | }
321 | parentSection = section;
322 | if( childElement.nodeName == "section" ) {
323 | parentSection = childElement ;
324 | previousParentElement = childElement ;
325 | }
326 | if ( typeof childElement.setAttribute == 'function' || childElement.nodeType == Node.COMMENT_NODE ) {
327 | addAttributes( parentSection, childElement, previousParentElement, separatorElementAttributes, separatorSectionAttributes );
328 | }
329 | }
330 | }
331 |
332 | if ( element.nodeType == Node.COMMENT_NODE ) {
333 | if ( addAttributeInElement( element, previousElement, separatorElementAttributes ) == false ) {
334 | addAttributeInElement( element, section, separatorSectionAttributes );
335 | }
336 | }
337 | }
338 |
339 | /**
340 | * Converts any current data-markdown slides in the
341 | * DOM to HTML.
342 | */
343 | function convertSlides() {
344 |
345 | var sections = document.querySelectorAll( '[data-markdown]');
346 |
347 | for( var i = 0, len = sections.length; i < len; i++ ) {
348 |
349 | var section = sections[i];
350 |
351 | // Only parse the same slide once
352 | if( !section.getAttribute( 'data-markdown-parsed' ) ) {
353 |
354 | section.setAttribute( 'data-markdown-parsed', true )
355 |
356 | var notes = section.querySelector( 'aside.notes' );
357 | var markdown = getMarkdownFromSlide( section );
358 |
359 | section.innerHTML = marked( markdown );
360 | addAttributes( section, section, null, section.getAttribute( 'data-element-attributes' ) ||
361 | section.parentNode.getAttribute( 'data-element-attributes' ) ||
362 | DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR,
363 | section.getAttribute( 'data-attributes' ) ||
364 | section.parentNode.getAttribute( 'data-attributes' ) ||
365 | DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR);
366 |
367 | // If there were notes, we need to re-add them after
368 | // having overwritten the section's HTML
369 | if( notes ) {
370 | section.appendChild( notes );
371 | }
372 |
373 | }
374 |
375 | }
376 |
377 | }
378 |
379 | // API
380 | return {
381 |
382 | initialize: function() {
383 | if( typeof marked === 'undefined' ) {
384 | throw 'The reveal.js Markdown plugin requires marked to be loaded';
385 | }
386 |
387 | if( typeof hljs !== 'undefined' ) {
388 | marked.setOptions({
389 | highlight: function( code, lang ) {
390 | return hljs.highlightAuto( code, [lang] ).value;
391 | }
392 | });
393 | }
394 |
395 | var options = Reveal.getConfig().markdown;
396 |
397 | if ( options ) {
398 | marked.setOptions( options );
399 | }
400 |
401 | processSlides();
402 | convertSlides();
403 | },
404 |
405 | // TODO: Do these belong in the API?
406 | processSlides: processSlides,
407 | convertSlides: convertSlides,
408 | slidify: slidify
409 |
410 | };
411 |
412 | }));
413 |
--------------------------------------------------------------------------------
/js/marked.js:
--------------------------------------------------------------------------------
1 | /**
2 | * marked - a markdown parser
3 | * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
4 | * https://github.com/chjj/marked
5 | */
6 | (function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+block.def.source+")")();block.blockquote=replace(block.blockquote)("def",block.def)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";block.html=replace(block.html)("comment",//)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1","\\2")+"|"+block.list.source.replace("\\1","\\3")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm){if(this.options.tables){this.rules=block.tables}else{this.rules=block.gfm}}}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)};Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top,bq){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1){this.tokens.push({type:"space"})}}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm,"");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]||""});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i ?/gm,"");this.token(cap,top,true);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i1&&b.length>1)){src=cap.slice(i+1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item.charAt(item.length-1)==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false,bq);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:!this.options.sanitizer&&(cap[1]==="pre"||cap[1]==="script"||cap[1]==="style"),text:cap[0]});continue}if(!bq&&top&&(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal;this.renderer=this.options.renderer||new Renderer;this.renderer.options=this.options;if(!this.links){throw new Error("Tokens array requires a `links` property.")}if(this.options.gfm){if(this.options.breaks){this.rules=inline.breaks}else{this.rules=inline.gfm}}else if(this.options.pedantic){this.rules=inline.pedantic}}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length);out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1].charAt(6)===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=this.renderer.link(href,null,text);continue}if(!this.inLink&&(cap=this.rules.url.exec(src))){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=this.renderer.link(href,null,text);continue}if(cap=this.rules.tag.exec(src)){if(!this.inLink&&/^/i.test(cap[0])){this.inLink=false}src=src.substring(cap[0].length);out+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(cap[0]):escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);this.inLink=true;out+=this.outputLink(cap,{href:cap[2],title:cap[3]});this.inLink=false;continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0].charAt(0);src=cap[0].substring(1)+src;continue}this.inLink=true;out+=this.outputLink(cap,link);this.inLink=false;continue}if(cap=this.rules.strong.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.strong(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.em(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.codespan(escape(cap[2],true));continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.br();continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.del(this.output(cap[1]));continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.text(escape(this.smartypants(cap[0])));continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return out};InlineLexer.prototype.outputLink=function(cap,link){var href=escape(link.href),title=link.title?escape(link.title):null;return cap[0].charAt(0)!=="!"?this.renderer.link(href,title,this.output(cap[1])):this.renderer.image(href,title,escape(cap[1]))};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…")};InlineLexer.prototype.mangle=function(text){if(!this.options.mangle)return text;var out="",l=text.length,i=0,ch;for(;i.5){ch="x"+ch.toString(16)}out+=""+ch+";"}return out};function Renderer(options){this.options=options||{}}Renderer.prototype.code=function(code,lang,escaped){if(this.options.highlight){var out=this.options.highlight(code,lang);if(out!=null&&out!==code){escaped=true;code=out}}if(!lang){return""+(escaped?code:escape(code,true))+"\n
"}return''+(escaped?code:escape(code,true))+"\n
\n"};Renderer.prototype.blockquote=function(quote){return"\n"+quote+" \n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"\n"};Renderer.prototype.hr=function(){return this.options.xhtml?" \n":" \n"};Renderer.prototype.list=function(body,ordered){var type=ordered?"ol":"ul";return"<"+type+">\n"+body+""+type+">\n"};Renderer.prototype.listitem=function(text){return""+text+" \n"};Renderer.prototype.paragraph=function(text){return""+text+"
\n"};Renderer.prototype.table=function(header,body){return"\n"+"\n"+header+" \n"+"\n"+body+" \n"+"
\n"};Renderer.prototype.tablerow=function(content){return"\n"+content+" \n"};Renderer.prototype.tablecell=function(content,flags){var type=flags.header?"th":"td";var tag=flags.align?"<"+type+' style="text-align:'+flags.align+'">':"<"+type+">";return tag+content+""+type+">\n"};Renderer.prototype.strong=function(text){return""+text+" "};Renderer.prototype.em=function(text){return""+text+" "};Renderer.prototype.codespan=function(text){return""+text+"
"};Renderer.prototype.br=function(){return this.options.xhtml?" ":" "};Renderer.prototype.del=function(text){return""+text+""};Renderer.prototype.link=function(href,title,text){if(this.options.sanitize){try{var prot=decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return""}if(prot.indexOf("javascript:")===0||prot.indexOf("vbscript:")===0){return""}}var out='"+text+" ";return out};Renderer.prototype.image=function(href,title,text){var out=' ":">";return out};Renderer.prototype.text=function(text){return text};function Parser(options){this.tokens=[];this.token=null;this.options=options||marked.defaults;this.options.renderer=this.options.renderer||new Renderer;this.renderer=this.options.renderer;this.renderer.options=this.options}Parser.parse=function(src,options,renderer){var parser=new Parser(options,renderer);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options,this.renderer);this.tokens=src.reverse();var out="";while(this.next()){out+=this.tok()}return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text;while(this.peek().type==="text"){body+="\n"+this.next().text}return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case"space":{return""}case"hr":{return this.renderer.hr()}case"heading":{return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text)}case"code":{return this.renderer.code(this.token.text,this.token.lang,this.token.escaped)}case"table":{var header="",body="",i,row,cell,flags,j;cell="";for(i=0;i /g,">").replace(/"/g,""").replace(/'/g,"'")}function unescape(html){return html.replace(/&([#\w]+);/g,function(_,n){n=n.toLowerCase();if(n==="colon")return":";if(n.charAt(0)==="#"){return n.charAt(1)==="x"?String.fromCharCode(parseInt(n.substring(2),16)):String.fromCharCode(+n.substring(1))}return""})}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i=1,target,key;for(;iAn error occured:"+escape(e.message+"",true)+" "}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,sanitizer:null,mangle:true,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};marked.Parser=Parser;marked.parser=Parser.parse;marked.Renderer=Renderer;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;marked.parse=marked;if(typeof module!=="undefined"&&typeof exports==="object"){module.exports=marked}else if(typeof define==="function"&&define.amd){define(function(){return marked})}else{this.marked=marked}}).call(function(){return this||(typeof window!=="undefined"?window:global)}());
--------------------------------------------------------------------------------
/js/math.js:
--------------------------------------------------------------------------------
1 | /**
2 | * A plugin which enables rendering of math equations inside
3 | * of reveal.js slides. Essentially a thin wrapper for MathJax.
4 | *
5 | * @author Hakim El Hattab
6 | */
7 | var RevealMath = window.RevealMath || (function(){
8 |
9 | var options = Reveal.getConfig().math || {};
10 | options.mathjax = options.mathjax || 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js';
11 | options.config = options.config || 'TeX-AMS_HTML-full';
12 | options.tex2jax = options.tex2jax || {
13 | inlineMath: [['$','$'],['\\(','\\)']] ,
14 | skipTags: ['script','noscript','style','textarea','pre'] };
15 |
16 | loadScript( options.mathjax + '?config=' + options.config, function() {
17 |
18 | MathJax.Hub.Config({
19 | messageStyle: 'none',
20 | tex2jax: options.tex2jax,
21 | skipStartupTypeset: true
22 | });
23 |
24 | // Typeset followed by an immediate reveal.js layout since
25 | // the typesetting process could affect slide height
26 | MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub ] );
27 | MathJax.Hub.Queue( Reveal.layout );
28 |
29 | // Reprocess equations in slides when they turn visible
30 | Reveal.addEventListener( 'slidechanged', function( event ) {
31 |
32 | MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, event.currentSlide ] );
33 |
34 | } );
35 |
36 | } );
37 |
38 | function loadScript( url, callback ) {
39 |
40 | var head = document.querySelector( 'head' );
41 | var script = document.createElement( 'script' );
42 | script.type = 'text/javascript';
43 | script.src = url;
44 |
45 | // Wrapper for callback to make sure it only fires once
46 | var finish = function() {
47 | if( typeof callback === 'function' ) {
48 | callback.call();
49 | callback = null;
50 | }
51 | }
52 |
53 | script.onload = finish;
54 |
55 | // IE
56 | script.onreadystatechange = function() {
57 | if ( this.readyState === 'loaded' ) {
58 | finish();
59 | }
60 | }
61 |
62 | // Normal browsers
63 | head.appendChild( script );
64 |
65 | }
66 |
67 | })();
68 |
--------------------------------------------------------------------------------
/js/notes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Handles opening of and synchronization with the reveal.js
3 | * notes window.
4 | *
5 | * Handshake process:
6 | * 1. This window posts 'connect' to notes window
7 | * - Includes URL of presentation to show
8 | * 2. Notes window responds with 'connected' when it is available
9 | * 3. This window proceeds to send the current presentation state
10 | * to the notes window
11 | */
12 | var RevealNotes = (function() {
13 |
14 | function openNotes( notesFilePath ) {
15 |
16 | if( !notesFilePath ) {
17 | var jsFileLocation = document.querySelector('script[src$="notes.js"]').src; // this js file path
18 | jsFileLocation = jsFileLocation.replace(/notes\.js(\?.*)?$/, ''); // the js folder path
19 | notesFilePath = jsFileLocation + 'notes.html';
20 | }
21 |
22 | var notesPopup = window.open( notesFilePath, 'reveal.js - Notes', 'width=1100,height=700' );
23 |
24 | if( !notesPopup ) {
25 | alert( 'Speaker view popup failed to open. Please make sure popups are allowed and reopen the speaker view.' );
26 | return;
27 | }
28 |
29 | // Allow popup window access to Reveal API
30 | notesPopup.Reveal = window.Reveal;
31 |
32 | /**
33 | * Connect to the notes window through a postmessage handshake.
34 | * Using postmessage enables us to work in situations where the
35 | * origins differ, such as a presentation being opened from the
36 | * file system.
37 | */
38 | function connect() {
39 | // Keep trying to connect until we get a 'connected' message back
40 | var connectInterval = setInterval( function() {
41 | notesPopup.postMessage( JSON.stringify( {
42 | namespace: 'reveal-notes',
43 | type: 'connect',
44 | url: window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search,
45 | state: Reveal.getState()
46 | } ), '*' );
47 | }, 500 );
48 |
49 | window.addEventListener( 'message', function( event ) {
50 | var data = JSON.parse( event.data );
51 | if( data && data.namespace === 'reveal-notes' && data.type === 'connected' ) {
52 | clearInterval( connectInterval );
53 | onConnected();
54 | }
55 | } );
56 | }
57 |
58 | /**
59 | * Posts the current slide data to the notes window
60 | */
61 | function post( event ) {
62 |
63 | var slideElement = Reveal.getCurrentSlide(),
64 | notesElement = slideElement.querySelector( 'aside.notes' ),
65 | fragmentElement = slideElement.querySelector( '.current-fragment' );
66 |
67 | var messageData = {
68 | namespace: 'reveal-notes',
69 | type: 'state',
70 | notes: '',
71 | markdown: false,
72 | whitespace: 'normal',
73 | state: Reveal.getState()
74 | };
75 |
76 | // Look for notes defined in a slide attribute
77 | if( slideElement.hasAttribute( 'data-notes' ) ) {
78 | messageData.notes = slideElement.getAttribute( 'data-notes' );
79 | messageData.whitespace = 'pre-wrap';
80 | }
81 |
82 | // Look for notes defined in a fragment
83 | if( fragmentElement ) {
84 | var fragmentNotes = fragmentElement.querySelector( 'aside.notes' );
85 | if( fragmentNotes ) {
86 | notesElement = fragmentNotes;
87 | }
88 | else if( fragmentElement.hasAttribute( 'data-notes' ) ) {
89 | messageData.notes = fragmentElement.getAttribute( 'data-notes' );
90 | messageData.whitespace = 'pre-wrap';
91 |
92 | // In case there are slide notes
93 | notesElement = null;
94 | }
95 | }
96 |
97 | // Look for notes defined in an aside element
98 | if( notesElement ) {
99 | messageData.notes = notesElement.innerHTML;
100 | messageData.markdown = typeof notesElement.getAttribute( 'data-markdown' ) === 'string';
101 | }
102 |
103 | notesPopup.postMessage( JSON.stringify( messageData ), '*' );
104 |
105 | }
106 |
107 | /**
108 | * Called once we have established a connection to the notes
109 | * window.
110 | */
111 | function onConnected() {
112 |
113 | // Monitor events that trigger a change in state
114 | Reveal.addEventListener( 'slidechanged', post );
115 | Reveal.addEventListener( 'fragmentshown', post );
116 | Reveal.addEventListener( 'fragmenthidden', post );
117 | Reveal.addEventListener( 'overviewhidden', post );
118 | Reveal.addEventListener( 'overviewshown', post );
119 | Reveal.addEventListener( 'paused', post );
120 | Reveal.addEventListener( 'resumed', post );
121 |
122 | // Post the initial state
123 | post();
124 |
125 | }
126 |
127 | connect();
128 |
129 | }
130 |
131 | if( !/receiver/i.test( window.location.search ) ) {
132 |
133 | // If the there's a 'notes' query set, open directly
134 | if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) {
135 | openNotes();
136 | }
137 |
138 | // Open the notes when the 's' key is hit
139 | Reveal.addKeyBinding({keyCode: 83, key: 'S', description: 'Speaker notes view'}, function() {
140 | openNotes();
141 | } );
142 |
143 | }
144 |
145 | return { open: openNotes };
146 |
147 | })();
148 |
--------------------------------------------------------------------------------
/js/print-pdf.js:
--------------------------------------------------------------------------------
1 | /**
2 | * phantomjs script for printing presentations to PDF.
3 | *
4 | * Example:
5 | * phantomjs print-pdf.js "http://revealjs.com?print-pdf" reveal-demo.pdf
6 | *
7 | * @author Manuel Bieh (https://github.com/manuelbieh)
8 | * @author Hakim El Hattab (https://github.com/hakimel)
9 | * @author Manuel Riezebosch (https://github.com/riezebosch)
10 | */
11 |
12 | // html2pdf.js
13 | var system = require( 'system' );
14 |
15 | var probePage = new WebPage();
16 | var printPage = new WebPage();
17 |
18 | var inputFile = system.args[1] || 'index.html?print-pdf';
19 | var outputFile = system.args[2] || 'slides.pdf';
20 |
21 | if( outputFile.match( /\.pdf$/gi ) === null ) {
22 | outputFile += '.pdf';
23 | }
24 |
25 | console.log( 'Export PDF: Reading reveal.js config [1/4]' );
26 |
27 | probePage.open( inputFile, function( status ) {
28 |
29 | console.log( 'Export PDF: Preparing print layout [2/4]' );
30 |
31 | var config = probePage.evaluate( function() {
32 | return Reveal.getConfig();
33 | } );
34 |
35 | if( config ) {
36 |
37 | printPage.paperSize = {
38 | width: Math.floor( config.width * ( 1 + config.margin ) ),
39 | height: Math.floor( config.height * ( 1 + config.margin ) ),
40 | border: 0
41 | };
42 |
43 | printPage.open( inputFile, function( status ) {
44 | console.log( 'Export PDF: Preparing pdf [3/4]')
45 | printPage.evaluate( function() {
46 | Reveal.isReady() ? window.callPhantom() : Reveal.addEventListener( 'pdf-ready', window.callPhantom );
47 | } );
48 | } );
49 |
50 | printPage.onCallback = function( data ) {
51 | // For some reason we need to "jump the queue" for syntax highlighting to work.
52 | // See: http://stackoverflow.com/a/3580132/129269
53 | setTimeout( function() {
54 | console.log( 'Export PDF: Writing file [4/4]' );
55 | printPage.render( outputFile );
56 | console.log( 'Export PDF: Finished successfully!' );
57 | phantom.exit();
58 | }, 0 );
59 | };
60 | }
61 | else {
62 |
63 | console.log( 'Export PDF: Unable to read reveal.js config. Make sure the input address points to a reveal.js page.' );
64 | phantom.exit( 1 );
65 |
66 | }
67 | } );
68 |
--------------------------------------------------------------------------------
/js/search.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Handles finding a text string anywhere in the slides and showing the next occurrence to the user
3 | * by navigatating to that slide and highlighting it.
4 | *
5 | * By Jon Snyder , February 2013
6 | */
7 |
8 | var RevealSearch = (function() {
9 |
10 | var matchedSlides;
11 | var currentMatchedIndex;
12 | var searchboxDirty;
13 | var myHilitor;
14 |
15 | // Original JavaScript code by Chirp Internet: www.chirp.com.au
16 | // Please acknowledge use of this code by including this header.
17 | // 2/2013 jon: modified regex to display any match, not restricted to word boundaries.
18 |
19 | function Hilitor(id, tag)
20 | {
21 |
22 | var targetNode = document.getElementById(id) || document.body;
23 | var hiliteTag = tag || "EM";
24 | var skipTags = new RegExp("^(?:" + hiliteTag + "|SCRIPT|FORM)$");
25 | var colors = ["#ff6", "#a0ffff", "#9f9", "#f99", "#f6f"];
26 | var wordColor = [];
27 | var colorIdx = 0;
28 | var matchRegex = "";
29 | var matchingSlides = [];
30 |
31 | this.setRegex = function(input)
32 | {
33 | input = input.replace(/^[^\w]+|[^\w]+$/g, "").replace(/[^\w'-]+/g, "|");
34 | matchRegex = new RegExp("(" + input + ")","i");
35 | }
36 |
37 | this.getRegex = function()
38 | {
39 | return matchRegex.toString().replace(/^\/\\b\(|\)\\b\/i$/g, "").replace(/\|/g, " ");
40 | }
41 |
42 | // recursively apply word highlighting
43 | this.hiliteWords = function(node)
44 | {
45 | if(node == undefined || !node) return;
46 | if(!matchRegex) return;
47 | if(skipTags.test(node.nodeName)) return;
48 |
49 | if(node.hasChildNodes()) {
50 | for(var i=0; i < node.childNodes.length; i++)
51 | this.hiliteWords(node.childNodes[i]);
52 | }
53 | if(node.nodeType == 3) { // NODE_TEXT
54 | if((nv = node.nodeValue) && (regs = matchRegex.exec(nv))) {
55 | //find the slide's section element and save it in our list of matching slides
56 | var secnode = node;
57 | while (secnode != null && secnode.nodeName != 'SECTION') {
58 | secnode = secnode.parentNode;
59 | }
60 |
61 | var slideIndex = Reveal.getIndices(secnode);
62 | var slidelen = matchingSlides.length;
63 | var alreadyAdded = false;
64 | for (var i=0; i < slidelen; i++) {
65 | if ( (matchingSlides[i].h === slideIndex.h) && (matchingSlides[i].v === slideIndex.v) ) {
66 | alreadyAdded = true;
67 | }
68 | }
69 | if (! alreadyAdded) {
70 | matchingSlides.push(slideIndex);
71 | }
72 |
73 | if(!wordColor[regs[0].toLowerCase()]) {
74 | wordColor[regs[0].toLowerCase()] = colors[colorIdx++ % colors.length];
75 | }
76 |
77 | var match = document.createElement(hiliteTag);
78 | match.appendChild(document.createTextNode(regs[0]));
79 | match.style.backgroundColor = wordColor[regs[0].toLowerCase()];
80 | match.style.fontStyle = "inherit";
81 | match.style.color = "#000";
82 |
83 | var after = node.splitText(regs.index);
84 | after.nodeValue = after.nodeValue.substring(regs[0].length);
85 | node.parentNode.insertBefore(match, after);
86 | }
87 | }
88 | };
89 |
90 | // remove highlighting
91 | this.remove = function()
92 | {
93 | var arr = document.getElementsByTagName(hiliteTag);
94 | while(arr.length && (el = arr[0])) {
95 | el.parentNode.replaceChild(el.firstChild, el);
96 | }
97 | };
98 |
99 | // start highlighting at target node
100 | this.apply = function(input)
101 | {
102 | if(input == undefined || !input) return;
103 | this.remove();
104 | this.setRegex(input);
105 | this.hiliteWords(targetNode);
106 | return matchingSlides;
107 | };
108 |
109 | }
110 |
111 | function openSearch() {
112 | //ensure the search term input dialog is visible and has focus:
113 | var inputboxdiv = document.getElementById("searchinputdiv");
114 | var inputbox = document.getElementById("searchinput");
115 | inputboxdiv.style.display = "inline";
116 | inputbox.focus();
117 | inputbox.select();
118 | }
119 |
120 | function closeSearch() {
121 | var inputboxdiv = document.getElementById("searchinputdiv");
122 | inputboxdiv.style.display = "none";
123 | if(myHilitor) myHilitor.remove();
124 | }
125 |
126 | function toggleSearch() {
127 | var inputboxdiv = document.getElementById("searchinputdiv");
128 | if (inputboxdiv.style.display !== "inline") {
129 | openSearch();
130 | }
131 | else {
132 | closeSearch();
133 | }
134 | }
135 |
136 | function doSearch() {
137 | //if there's been a change in the search term, perform a new search:
138 | if (searchboxDirty) {
139 | var searchstring = document.getElementById("searchinput").value;
140 |
141 | if (searchstring === '') {
142 | if(myHilitor) myHilitor.remove();
143 | matchedSlides = null;
144 | }
145 | else {
146 | //find the keyword amongst the slides
147 | myHilitor = new Hilitor("slidecontent");
148 | matchedSlides = myHilitor.apply(searchstring);
149 | currentMatchedIndex = 0;
150 | }
151 | }
152 |
153 | if (matchedSlides) {
154 | //navigate to the next slide that has the keyword, wrapping to the first if necessary
155 | if (matchedSlides.length && (matchedSlides.length <= currentMatchedIndex)) {
156 | currentMatchedIndex = 0;
157 | }
158 | if (matchedSlides.length > currentMatchedIndex) {
159 | Reveal.slide(matchedSlides[currentMatchedIndex].h, matchedSlides[currentMatchedIndex].v);
160 | currentMatchedIndex++;
161 | }
162 | }
163 | }
164 |
165 | var dom = {};
166 | dom.wrapper = document.querySelector( '.reveal' );
167 |
168 | if( !dom.wrapper.querySelector( '.searchbox' ) ) {
169 | var searchElement = document.createElement( 'div' );
170 | searchElement.id = "searchinputdiv";
171 | searchElement.classList.add( 'searchdiv' );
172 | searchElement.style.position = 'absolute';
173 | searchElement.style.top = '10px';
174 | searchElement.style.right = '10px';
175 | searchElement.style.zIndex = 10;
176 | //embedded base64 search icon Designed by Sketchdock - http://www.sketchdock.com/:
177 | searchElement.innerHTML = ' ';
178 | dom.wrapper.appendChild( searchElement );
179 | }
180 |
181 | document.getElementById( 'searchbutton' ).addEventListener( 'click', function(event) {
182 | doSearch();
183 | }, false );
184 |
185 | document.getElementById( 'searchinput' ).addEventListener( 'keyup', function( event ) {
186 | switch (event.keyCode) {
187 | case 13:
188 | event.preventDefault();
189 | doSearch();
190 | searchboxDirty = false;
191 | break;
192 | default:
193 | searchboxDirty = true;
194 | }
195 | }, false );
196 |
197 | document.addEventListener( 'keydown', function( event ) {
198 | if( event.key == "F" && (event.ctrlKey || event.metaKey) ) { //Control+Shift+f
199 | event.preventDefault();
200 | toggleSearch();
201 | }
202 | }, false );
203 | if( window.Reveal ) Reveal.registerKeyboardShortcut( 'Ctrl-Shift-F', 'Search' );
204 | closeSearch();
205 | return { open: openSearch };
206 | })();
207 |
--------------------------------------------------------------------------------
/js/zoom.js:
--------------------------------------------------------------------------------
1 | // Custom reveal.js integration
2 | (function(){
3 | var revealElement = document.querySelector( '.reveal' );
4 | if( revealElement ) {
5 |
6 | revealElement.addEventListener( 'mousedown', function( event ) {
7 | var defaultModifier = /Linux/.test( window.navigator.platform ) ? 'ctrl' : 'alt';
8 |
9 | var modifier = ( Reveal.getConfig().zoomKey ? Reveal.getConfig().zoomKey : defaultModifier ) + 'Key';
10 | var zoomLevel = ( Reveal.getConfig().zoomLevel ? Reveal.getConfig().zoomLevel : 2 );
11 |
12 | if( event[ modifier ] && !Reveal.isOverview() ) {
13 | event.preventDefault();
14 |
15 | zoom.to({
16 | x: event.clientX,
17 | y: event.clientY,
18 | scale: zoomLevel,
19 | pan: false
20 | });
21 | }
22 | } );
23 |
24 | }
25 | })();
26 |
27 | /*!
28 | * zoom.js 0.3 (modified for use with reveal.js)
29 | * http://lab.hakim.se/zoom-js
30 | * MIT licensed
31 | *
32 | * Copyright (C) 2011-2014 Hakim El Hattab, http://hakim.se
33 | */
34 | var zoom = (function(){
35 |
36 | // The current zoom level (scale)
37 | var level = 1;
38 |
39 | // The current mouse position, used for panning
40 | var mouseX = 0,
41 | mouseY = 0;
42 |
43 | // Timeout before pan is activated
44 | var panEngageTimeout = -1,
45 | panUpdateInterval = -1;
46 |
47 | // Check for transform support so that we can fallback otherwise
48 | var supportsTransforms = 'WebkitTransform' in document.body.style ||
49 | 'MozTransform' in document.body.style ||
50 | 'msTransform' in document.body.style ||
51 | 'OTransform' in document.body.style ||
52 | 'transform' in document.body.style;
53 |
54 | if( supportsTransforms ) {
55 | // The easing that will be applied when we zoom in/out
56 | document.body.style.transition = 'transform 0.8s ease';
57 | document.body.style.OTransition = '-o-transform 0.8s ease';
58 | document.body.style.msTransition = '-ms-transform 0.8s ease';
59 | document.body.style.MozTransition = '-moz-transform 0.8s ease';
60 | document.body.style.WebkitTransition = '-webkit-transform 0.8s ease';
61 | }
62 |
63 | // Zoom out if the user hits escape
64 | document.addEventListener( 'keyup', function( event ) {
65 | if( level !== 1 && event.keyCode === 27 ) {
66 | zoom.out();
67 | }
68 | } );
69 |
70 | // Monitor mouse movement for panning
71 | document.addEventListener( 'mousemove', function( event ) {
72 | if( level !== 1 ) {
73 | mouseX = event.clientX;
74 | mouseY = event.clientY;
75 | }
76 | } );
77 |
78 | /**
79 | * Applies the CSS required to zoom in, prefers the use of CSS3
80 | * transforms but falls back on zoom for IE.
81 | *
82 | * @param {Object} rect
83 | * @param {Number} scale
84 | */
85 | function magnify( rect, scale ) {
86 |
87 | var scrollOffset = getScrollOffset();
88 |
89 | // Ensure a width/height is set
90 | rect.width = rect.width || 1;
91 | rect.height = rect.height || 1;
92 |
93 | // Center the rect within the zoomed viewport
94 | rect.x -= ( window.innerWidth - ( rect.width * scale ) ) / 2;
95 | rect.y -= ( window.innerHeight - ( rect.height * scale ) ) / 2;
96 |
97 | if( supportsTransforms ) {
98 | // Reset
99 | if( scale === 1 ) {
100 | document.body.style.transform = '';
101 | document.body.style.OTransform = '';
102 | document.body.style.msTransform = '';
103 | document.body.style.MozTransform = '';
104 | document.body.style.WebkitTransform = '';
105 | }
106 | // Scale
107 | else {
108 | var origin = scrollOffset.x +'px '+ scrollOffset.y +'px',
109 | transform = 'translate('+ -rect.x +'px,'+ -rect.y +'px) scale('+ scale +')';
110 |
111 | document.body.style.transformOrigin = origin;
112 | document.body.style.OTransformOrigin = origin;
113 | document.body.style.msTransformOrigin = origin;
114 | document.body.style.MozTransformOrigin = origin;
115 | document.body.style.WebkitTransformOrigin = origin;
116 |
117 | document.body.style.transform = transform;
118 | document.body.style.OTransform = transform;
119 | document.body.style.msTransform = transform;
120 | document.body.style.MozTransform = transform;
121 | document.body.style.WebkitTransform = transform;
122 | }
123 | }
124 | else {
125 | // Reset
126 | if( scale === 1 ) {
127 | document.body.style.position = '';
128 | document.body.style.left = '';
129 | document.body.style.top = '';
130 | document.body.style.width = '';
131 | document.body.style.height = '';
132 | document.body.style.zoom = '';
133 | }
134 | // Scale
135 | else {
136 | document.body.style.position = 'relative';
137 | document.body.style.left = ( - ( scrollOffset.x + rect.x ) / scale ) + 'px';
138 | document.body.style.top = ( - ( scrollOffset.y + rect.y ) / scale ) + 'px';
139 | document.body.style.width = ( scale * 100 ) + '%';
140 | document.body.style.height = ( scale * 100 ) + '%';
141 | document.body.style.zoom = scale;
142 | }
143 | }
144 |
145 | level = scale;
146 |
147 | if( document.documentElement.classList ) {
148 | if( level !== 1 ) {
149 | document.documentElement.classList.add( 'zoomed' );
150 | }
151 | else {
152 | document.documentElement.classList.remove( 'zoomed' );
153 | }
154 | }
155 | }
156 |
157 | /**
158 | * Pan the document when the mosue cursor approaches the edges
159 | * of the window.
160 | */
161 | function pan() {
162 | var range = 0.12,
163 | rangeX = window.innerWidth * range,
164 | rangeY = window.innerHeight * range,
165 | scrollOffset = getScrollOffset();
166 |
167 | // Up
168 | if( mouseY < rangeY ) {
169 | window.scroll( scrollOffset.x, scrollOffset.y - ( 1 - ( mouseY / rangeY ) ) * ( 14 / level ) );
170 | }
171 | // Down
172 | else if( mouseY > window.innerHeight - rangeY ) {
173 | window.scroll( scrollOffset.x, scrollOffset.y + ( 1 - ( window.innerHeight - mouseY ) / rangeY ) * ( 14 / level ) );
174 | }
175 |
176 | // Left
177 | if( mouseX < rangeX ) {
178 | window.scroll( scrollOffset.x - ( 1 - ( mouseX / rangeX ) ) * ( 14 / level ), scrollOffset.y );
179 | }
180 | // Right
181 | else if( mouseX > window.innerWidth - rangeX ) {
182 | window.scroll( scrollOffset.x + ( 1 - ( window.innerWidth - mouseX ) / rangeX ) * ( 14 / level ), scrollOffset.y );
183 | }
184 | }
185 |
186 | function getScrollOffset() {
187 | return {
188 | x: window.scrollX !== undefined ? window.scrollX : window.pageXOffset,
189 | y: window.scrollY !== undefined ? window.scrollY : window.pageYOffset
190 | }
191 | }
192 |
193 | return {
194 | /**
195 | * Zooms in on either a rectangle or HTML element.
196 | *
197 | * @param {Object} options
198 | * - element: HTML element to zoom in on
199 | * OR
200 | * - x/y: coordinates in non-transformed space to zoom in on
201 | * - width/height: the portion of the screen to zoom in on
202 | * - scale: can be used instead of width/height to explicitly set scale
203 | */
204 | to: function( options ) {
205 |
206 | // Due to an implementation limitation we can't zoom in
207 | // to another element without zooming out first
208 | if( level !== 1 ) {
209 | zoom.out();
210 | }
211 | else {
212 | options.x = options.x || 0;
213 | options.y = options.y || 0;
214 |
215 | // If an element is set, that takes precedence
216 | if( !!options.element ) {
217 | // Space around the zoomed in element to leave on screen
218 | var padding = 20;
219 | var bounds = options.element.getBoundingClientRect();
220 |
221 | options.x = bounds.left - padding;
222 | options.y = bounds.top - padding;
223 | options.width = bounds.width + ( padding * 2 );
224 | options.height = bounds.height + ( padding * 2 );
225 | }
226 |
227 | // If width/height values are set, calculate scale from those values
228 | if( options.width !== undefined && options.height !== undefined ) {
229 | options.scale = Math.max( Math.min( window.innerWidth / options.width, window.innerHeight / options.height ), 1 );
230 | }
231 |
232 | if( options.scale > 1 ) {
233 | options.x *= options.scale;
234 | options.y *= options.scale;
235 |
236 | magnify( options, options.scale );
237 |
238 | if( options.pan !== false ) {
239 |
240 | // Wait with engaging panning as it may conflict with the
241 | // zoom transition
242 | panEngageTimeout = setTimeout( function() {
243 | panUpdateInterval = setInterval( pan, 1000 / 60 );
244 | }, 800 );
245 |
246 | }
247 | }
248 | }
249 | },
250 |
251 | /**
252 | * Resets the document zoom state to its default.
253 | */
254 | out: function() {
255 | clearTimeout( panEngageTimeout );
256 | clearInterval( panUpdateInterval );
257 |
258 | magnify( { x: 0, y: 0 }, 1 );
259 |
260 | level = 1;
261 | },
262 |
263 | // Alias
264 | magnify: function( options ) { this.to( options ) },
265 | reset: function() { this.out() },
266 |
267 | zoomLevel: function() {
268 | return level;
269 | }
270 | }
271 |
272 | })();
273 |
--------------------------------------------------------------------------------
/lib/css/zenburn.css:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Zenburn style from voldmar.ru (c) Vladimir Epifanov
4 | based on dark.css by Ivan Sagalaev
5 |
6 | */
7 |
8 | .hljs {
9 | display: block;
10 | overflow-x: auto;
11 | padding: 0.5em;
12 | background: #3f3f3f;
13 | color: #dcdcdc;
14 | }
15 |
16 | .hljs-keyword,
17 | .hljs-selector-tag,
18 | .hljs-tag {
19 | color: #e3ceab;
20 | }
21 |
22 | .hljs-template-tag {
23 | color: #dcdcdc;
24 | }
25 |
26 | .hljs-number {
27 | color: #8cd0d3;
28 | }
29 |
30 | .hljs-variable,
31 | .hljs-template-variable,
32 | .hljs-attribute {
33 | color: #efdcbc;
34 | }
35 |
36 | .hljs-literal {
37 | color: #efefaf;
38 | }
39 |
40 | .hljs-subst {
41 | color: #8f8f8f;
42 | }
43 |
44 | .hljs-title,
45 | .hljs-name,
46 | .hljs-selector-id,
47 | .hljs-selector-class,
48 | .hljs-section,
49 | .hljs-type {
50 | color: #efef8f;
51 | }
52 |
53 | .hljs-symbol,
54 | .hljs-bullet,
55 | .hljs-link {
56 | color: #dca3a3;
57 | }
58 |
59 | .hljs-deletion,
60 | .hljs-string,
61 | .hljs-built_in,
62 | .hljs-builtin-name {
63 | color: #cc9393;
64 | }
65 |
66 | .hljs-addition,
67 | .hljs-comment,
68 | .hljs-quote,
69 | .hljs-meta {
70 | color: #7f9f7f;
71 | }
72 |
73 |
74 | .hljs-emphasis {
75 | font-style: italic;
76 | }
77 |
78 | .hljs-strong {
79 | font-weight: bold;
80 | }
81 |
--------------------------------------------------------------------------------
/lib/font/league-gothic/LICENSE:
--------------------------------------------------------------------------------
1 | SIL Open Font License (OFL)
2 | http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL
3 |
--------------------------------------------------------------------------------
/lib/font/league-gothic/league-gothic.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'League Gothic';
3 | src: url('league-gothic.eot');
4 | src: url('league-gothic.eot?#iefix') format('embedded-opentype'),
5 | url('league-gothic.woff') format('woff'),
6 | url('league-gothic.ttf') format('truetype');
7 |
8 | font-weight: normal;
9 | font-style: normal;
10 | }
--------------------------------------------------------------------------------
/lib/font/league-gothic/league-gothic.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/lib/font/league-gothic/league-gothic.eot
--------------------------------------------------------------------------------
/lib/font/league-gothic/league-gothic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/lib/font/league-gothic/league-gothic.ttf
--------------------------------------------------------------------------------
/lib/font/league-gothic/league-gothic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/lib/font/league-gothic/league-gothic.woff
--------------------------------------------------------------------------------
/lib/font/source-sans-pro/LICENSE:
--------------------------------------------------------------------------------
1 | SIL Open Font License
2 |
3 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name ‘Source’. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
4 |
5 | This Font Software is licensed under the SIL Open Font License, Version 1.1.
6 | This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
7 |
8 | —————————————————————————————-
9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10 | —————————————————————————————-
11 |
12 | PREAMBLE
13 | The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others.
14 |
15 | The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives.
16 |
17 | DEFINITIONS
18 | “Font Software” refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation.
19 |
20 | “Reserved Font Name” refers to any names specified as such after the copyright statement(s).
21 |
22 | “Original Version” refers to the collection of Font Software components as distributed by the Copyright Holder(s).
23 |
24 | “Modified Version” refers to any derivative made by adding to, deleting, or substituting—in part or in whole—any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment.
25 |
26 | “Author” refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.
27 |
28 | PERMISSION & CONDITIONS
29 | Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions:
30 |
31 | 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself.
32 |
33 | 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.
34 |
35 | 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users.
36 |
37 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission.
38 |
39 | 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software.
40 |
41 | TERMINATION
42 | This license becomes null and void if any of the above conditions are not met.
43 |
44 | DISCLAIMER
45 | THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
--------------------------------------------------------------------------------
/lib/font/source-sans-pro/source-sans-pro-italic.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/lib/font/source-sans-pro/source-sans-pro-italic.eot
--------------------------------------------------------------------------------
/lib/font/source-sans-pro/source-sans-pro-italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/lib/font/source-sans-pro/source-sans-pro-italic.ttf
--------------------------------------------------------------------------------
/lib/font/source-sans-pro/source-sans-pro-italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/lib/font/source-sans-pro/source-sans-pro-italic.woff
--------------------------------------------------------------------------------
/lib/font/source-sans-pro/source-sans-pro-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/lib/font/source-sans-pro/source-sans-pro-regular.eot
--------------------------------------------------------------------------------
/lib/font/source-sans-pro/source-sans-pro-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/lib/font/source-sans-pro/source-sans-pro-regular.ttf
--------------------------------------------------------------------------------
/lib/font/source-sans-pro/source-sans-pro-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/lib/font/source-sans-pro/source-sans-pro-regular.woff
--------------------------------------------------------------------------------
/lib/font/source-sans-pro/source-sans-pro-semibold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/lib/font/source-sans-pro/source-sans-pro-semibold.eot
--------------------------------------------------------------------------------
/lib/font/source-sans-pro/source-sans-pro-semibold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/lib/font/source-sans-pro/source-sans-pro-semibold.ttf
--------------------------------------------------------------------------------
/lib/font/source-sans-pro/source-sans-pro-semibold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/lib/font/source-sans-pro/source-sans-pro-semibold.woff
--------------------------------------------------------------------------------
/lib/font/source-sans-pro/source-sans-pro-semibolditalic.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/lib/font/source-sans-pro/source-sans-pro-semibolditalic.eot
--------------------------------------------------------------------------------
/lib/font/source-sans-pro/source-sans-pro-semibolditalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/lib/font/source-sans-pro/source-sans-pro-semibolditalic.ttf
--------------------------------------------------------------------------------
/lib/font/source-sans-pro/source-sans-pro-semibolditalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kcobos/intro-micropython/43d766e9c81a53c176741826574fc7d5edf866e2/lib/font/source-sans-pro/source-sans-pro-semibolditalic.woff
--------------------------------------------------------------------------------
/lib/font/source-sans-pro/source-sans-pro.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Source Sans Pro';
3 | src: url('source-sans-pro-regular.eot');
4 | src: url('source-sans-pro-regular.eot?#iefix') format('embedded-opentype'),
5 | url('source-sans-pro-regular.woff') format('woff'),
6 | url('source-sans-pro-regular.ttf') format('truetype');
7 | font-weight: normal;
8 | font-style: normal;
9 | }
10 |
11 | @font-face {
12 | font-family: 'Source Sans Pro';
13 | src: url('source-sans-pro-italic.eot');
14 | src: url('source-sans-pro-italic.eot?#iefix') format('embedded-opentype'),
15 | url('source-sans-pro-italic.woff') format('woff'),
16 | url('source-sans-pro-italic.ttf') format('truetype');
17 | font-weight: normal;
18 | font-style: italic;
19 | }
20 |
21 | @font-face {
22 | font-family: 'Source Sans Pro';
23 | src: url('source-sans-pro-semibold.eot');
24 | src: url('source-sans-pro-semibold.eot?#iefix') format('embedded-opentype'),
25 | url('source-sans-pro-semibold.woff') format('woff'),
26 | url('source-sans-pro-semibold.ttf') format('truetype');
27 | font-weight: 600;
28 | font-style: normal;
29 | }
30 |
31 | @font-face {
32 | font-family: 'Source Sans Pro';
33 | src: url('source-sans-pro-semibolditalic.eot');
34 | src: url('source-sans-pro-semibolditalic.eot?#iefix') format('embedded-opentype'),
35 | url('source-sans-pro-semibolditalic.woff') format('woff'),
36 | url('source-sans-pro-semibolditalic.ttf') format('truetype');
37 | font-weight: 600;
38 | font-style: italic;
39 | }
--------------------------------------------------------------------------------
/lib/js/classList.js:
--------------------------------------------------------------------------------
1 | /*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js*/
2 | if(typeof document!=="undefined"&&!("classList" in document.createElement("a"))){(function(j){var a="classList",f="prototype",m=(j.HTMLElement||j.Element)[f],b=Object,k=String[f].trim||function(){return this.replace(/^\s+|\s+$/g,"")},c=Array[f].indexOf||function(q){var p=0,o=this.length;for(;pn?(i.screensCss.gt&&r("gt-"+n),i.screensCss.gte&&r("gte-"+n)):tt);u.feature("landscape",fe?(i.browserCss.gt&&r("gt-"+f+e),i.browserCss.gte&&r("gte-"+f+e)):h2&&this[u+1]!==t)u&&r(this.slice(u,u+1).join("-").toLowerCase()+i.section);else{var f=n||"index",e=f.indexOf(".");e>0&&(f=f.substring(0,e));c.id=f.toLowerCase()+i.page;u||r("root"+i.section)}});u.screen={height:n.screen.height,width:n.screen.width};tt();b=0;n.addEventListener?n.addEventListener("resize",it,!1):n.attachEvent("onresize",it)})(window);
3 | /*! head.css3 - v1.0.0 */
4 | (function(n,t){"use strict";function a(n){for(var r in n)if(i[n[r]]!==t)return!0;return!1}function r(n){var t=n.charAt(0).toUpperCase()+n.substr(1),i=(n+" "+c.join(t+" ")+t).split(" ");return!!a(i)}var h=n.document,o=h.createElement("i"),i=o.style,s=" -o- -moz- -ms- -webkit- -khtml- ".split(" "),c="Webkit Moz O ms Khtml".split(" "),l=n.head_conf&&n.head_conf.head||"head",u=n[l],f={gradient:function(){var n="background-image:";return i.cssText=(n+s.join("gradient(linear,left top,right bottom,from(#9f9),to(#fff));"+n)+s.join("linear-gradient(left top,#eee,#fff);"+n)).slice(0,-n.length),!!i.backgroundImage},rgba:function(){return i.cssText="background-color:rgba(0,0,0,0.5)",!!i.backgroundColor},opacity:function(){return o.style.opacity===""},textshadow:function(){return i.textShadow===""},multiplebgs:function(){i.cssText="background:url(https://),url(https://),red url(https://)";var n=(i.background||"").match(/url/g);return Object.prototype.toString.call(n)==="[object Array]"&&n.length===3},boxshadow:function(){return r("boxShadow")},borderimage:function(){return r("borderImage")},borderradius:function(){return r("borderRadius")},cssreflections:function(){return r("boxReflect")},csstransforms:function(){return r("transform")},csstransitions:function(){return r("transition")},touch:function(){return"ontouchstart"in n},retina:function(){return n.devicePixelRatio>1},fontface:function(){var t=u.browser.name,n=u.browser.version;switch(t){case"ie":return n>=9;case"chrome":return n>=13;case"ff":return n>=6;case"ios":return n>=5;case"android":return!1;case"webkit":return n>=5.1;case"opera":return n>=10;default:return!1}}};for(var e in f)f[e]&&u.feature(e,f[e].call(),!0);u.feature()})(window);
5 | /*! head.load - v1.0.3 */
6 | (function(n,t){"use strict";function w(){}function u(n,t){if(n){typeof n=="object"&&(n=[].slice.call(n));for(var i=0,r=n.length;i
2 |
3 |
4 |
5 | ## ¿Qué es?
6 | Una implementación de Python3 para microcontroladores
7 |
8 | ### ¿Qué es un microcontrolador?
9 | 
10 | 
11 | [Datasheet ESP8266](https://www.espressif.com/sites/default/files/documentation/0a-esp8266ex_datasheet_en.pdf)
12 |
13 |
14 |
15 |
16 | ## ¿Por qué µPython?
17 | * Interpretado. Menos velocidad pero portable.
18 | * Interactivo. ¡¡Tenemos consola!!
19 | * Tenemos muchos [módulos](https://docs.micropython.org/en/latest/library/index.html#python-standard-libraries-and-micro-libraries) a nuestra disposición.
20 | * Extensible. Podemos crear los módulos que necesitemos. Python a alto nivel y CPython a bajo nivel.
21 | ### Más alto nivel.
22 |
23 |
24 | ## Cambios de firmware al instante
25 |
26 |
27 |
28 | ## Empecemos...
29 |
30 |
31 | ### ¿Qué necesitamos?
32 | 1. µcontrolador compatible: Pyboard, WiPy, ESP8266, ESP32...
33 | 2. Ordenador con Python3 (solo al principio)
34 | 3. Firmware (intérprete de µPython)
35 | 4. 5 minutos
36 |
37 |
38 | ### Descargar intérprete de la web [http://micropython.org/](http://micropython.org/)
39 |
40 |
41 |
42 | ### Instalar esptool
43 |
44 | `pip3 install esptool`
45 |
46 |
47 | ### Flashear el µcontrolador
48 |
49 | `esptool.py --port /dev/ttyUSB0 erase_flash`
50 |
51 | `esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect 0 esp8266-20170108-v1.8.7.bin`
52 |
53 | [Docu](http://docs.micropython.org/en/latest/esp8266/tutorial/intro.html#deploying-the-firmware)
54 |
55 |
56 | ## Algo nuevo se huele en el ambiente
57 |
58 | ### ¡¡Y listo para su uso y disfrute!!
59 |
60 |
61 |
62 | ## ¿Nos conectamos al aparato?
63 | * Conexión serie (115200 br):
64 | * screen, picocom...
65 | * PuTTY...
66 | * WiFi: WebREPL (Read Evaluate Print Loop)
67 |
68 |
69 | ## Hacer pruebas con un µcontrolador por WiFi...
70 | # mola
71 |
72 |
73 | ## Vamos a configurarlo
74 |
75 | `import webrepl_setup`
76 |
77 | boot.py
78 | ```python
79 | import webrepl
80 | webrepl.start()
81 | ```
82 |
83 | Y lo subimos al µcontrolador:
84 |
85 | `pip3 install adafruit-ampy`
86 |
87 | `ampy -p /dev/ttyUSB0 put boot.py`
88 |
89 |
90 | ### Incluso lo podemos reiniciar con AMPY
91 | `ampy -p /dev/ttyUSB0 reset`
92 |
93 |
94 |
95 | ## WebREPL
96 |
97 | [Repo](https://github.com/micropython/webrepl)
98 |
99 |
100 |
101 | ## ¿Encendemos un LED?
102 |
103 | ```python
104 | import machine
105 | led = machine.Pin(2, machine.Pin.OUT)
106 | led.value()
107 | led.off() # led.value(0)
108 | led.on() # led.value(1)
109 | ```
110 |
111 |
112 |
113 | # ¿Dudas hasta ahora?
114 |
115 |
116 |
117 |
118 | ## ¿Y ese `boot.py`?
119 | µPython es más que un intérprete.
120 |
121 | ### Tiene un sistema de archivos interno.
122 | Tipo EEPROM (Arduino) pero mejor.
123 |
124 |
125 | ## Dos archivos especiales
126 | * `boot.py`: se ejecuta primero, si existe.
127 | * `main.py`: se ejecuta.
128 |
129 | En boot.py se suele configurar el µcontrolador: WiFi, pines...
130 |
131 | En main.py irá la programación del µ.
132 |
133 | ### ¡Ojo con el while True!
134 |
135 |
136 | ## Jugando con el sistema de archivos
137 | ```python
138 | f = open('archivo.txt', 'w')
139 | f.write("hola!! estoy en un archivo") # Devuelve la longitud
140 | f.close()
141 | ```
142 |
143 | ```python
144 | f = open('archivo.txt')
145 | f.read()
146 | f.close()
147 | ```
148 |
149 |
150 |
151 | # ¡Eso se puede hacer con EEPROM!
152 | ## No es nuevo
153 |
154 |
155 | ## ¿Listar archivos?
156 | ```python
157 | import os
158 | os.listdir()
159 | ```
160 |
161 |
162 | ## ¿Crear carpetas en un µcontrolador?
163 | ```python
164 | import os
165 | os.mkdir('carpeta')
166 | ```
167 | ## ¿Y eliminarlas?
168 | ```python
169 | import os
170 | os.rmdir('carpeta')
171 | ```
172 |
173 |
174 |
175 | ## ¿Renombrar ficheros?
176 | ```python
177 | import os
178 | os.rename('archivo.txt', 'archivo_antiguo.txt')
179 | ```
180 | ## ¿Eliminar archivos?
181 | ```python
182 | import os
183 | os.remove('archivo.txt')
184 | ```
185 |
186 |
187 |
188 | # Pequeño "OS"
189 | ```python
190 | import os
191 | os.uname()
192 | ```
193 |
194 | ¿µPython os ha sorprendido?
195 |
196 |
197 |
198 | ## Módulos disponibles
199 |
200 | ```python
201 | help('modules')
202 | ```
203 |
204 |
205 | ## Módulos estándar
206 | * array
207 | * math
208 | * collections / ucollections
209 | * hashlib / uhashlib
210 | * json / ujson
211 | * random / urandom
212 | * time
213 | * re / ure
214 | * zlib / uzlib
215 | * ucryptolib
216 | * uheapq
217 |
218 |
219 | ## Módulos específicos
220 | * btree
221 | * esp
222 | * gc
223 | * io / uio
224 | * machine: I2C, IRQ, Pin, PWM, RTC, SPI, UART...
225 | * micropython
226 | * network: http_client(_ssl), http_server(_ssl)
227 | * ntptime
228 | * os / uos
229 | * sys
230 | * upip
231 |
232 |
233 | ## Módulos complementarios
234 | * dht
235 | * ds18x20
236 | * lwip
237 | * neopixel
238 | * ssd1306
239 | * onewire
240 | * umqtt(simple/robust)
241 |
242 |
243 | ## Hebras y tareas
244 | * _thread
245 | * uasyncio
246 |
247 |
248 |
249 | # ¿IoT?
250 |
251 | ## WiFi
252 |
253 |
254 | ## Configuración básica
255 | ```python
256 | import network
257 |
258 | wlan = network.WLAN(network.STA_IF)
259 | wlan.active(True)
260 | wlan.isconnected()
261 | wlan.connect('essid', 'password')
262 | wlan.ifconfig()
263 | wlan.ifconfig(('192.168.1.44', '255.255.255.0', '192.168.1.1', '8.8.8.8'))
264 |
265 | ap = network.WLAN(network.AP_IF)
266 | ap.active(True)
267 | ap.config(essid='ESP-AP', password='miESPap123')
268 | ap.ifconfig(('192.168.4.1', '255.255.255.0', '192.168.4.1', '8.8.8.8'))
269 | ```
270 | [Docu](https://docs.micropython.org/en/latest/library/network.WLAN.html)
271 |
272 |
273 | ## Peticiones
274 | ```python
275 | import urequests
276 | respuesta = urequests.get('https://httpbin.org/get')
277 | print(respuesta.text)
278 | ```
279 | ```python
280 | print(respuesta.json())
281 | ```
282 |
283 | ```python
284 | print(respuesta.status_code)
285 | print(respuesta.reason)
286 | ```
287 |
288 | ```python
289 | urequests.post('https://httpbin.org/post', data="micropython")
290 | urequests.delete('https://httpbin.org/delete', data="compilar para probar")
291 | urequests.put('https://httpbin.org/put', data="IoT fácil")
292 | ```
293 |
294 |
295 |
296 | ## Servidor
297 | ```python
298 | import socket
299 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
300 | s.bind(('', 80))
301 | s.listen(0)
302 | while True:
303 | conn, addr = s.accept()
304 | print("Conexión desde: %s" % str(addr))
305 | request = conn.recv(512)
306 | print("Contenido recivido: %s" % str(request))
307 | conn.send("Servidor ESP8266 Hola desde mi IoT ")
308 | conn.close()
309 | ```
310 |
311 |
312 | ## Servidor II
313 | ```python
314 | import machine
315 | led = machine.Pin(2, machine.Pin.OUT)
316 | import socket
317 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
318 | s.bind(('', 80))
319 | s.listen(0)
320 | while True:
321 | conn, addr = s.accept()
322 | print("Conexión desde: %s" % str(addr))
323 | request = conn.recv(512)
324 | request = str(request).split(" ")
325 | if request[1] == "/?LED=ON":
326 | led.on()
327 | if request[1] == "/?LED=OFF":
328 | led.off()
329 | print("Contenido recivido: %s" % str(request))
330 | conn.send("Servidor ESP8266 Hola desde mi IoT %s "%led.value())
331 | conn.close()
332 | ```
333 |
334 |
335 |
336 | # MQTT
337 |
338 | [Cliente](https://mqttfx.jensd.de/index.php/download)
339 |
340 |
341 | ## Librerías incluidas
342 | * umqtt.simple
343 | * umqtt.robust
344 |
345 |
346 | ## Suscripción
347 | ```python
348 | from umqtt.simple import MQTTClient
349 |
350 | def sub_cb(topic, msg):
351 | print((topic, msg))
352 |
353 | c = MQTTClient("ESP8266", "cubie.kcobos.es") # user="usuario", password="secreto"
354 | c.set_callback(sub_cb)
355 | c.connect()
356 | print("Conectando")
357 | c.subscribe(b"prueba")
358 | print("Suscrito a prueba")
359 |
360 | while True:
361 | c.wait_msg()
362 |
363 | c.disconnect()
364 | ```
365 |
366 |
367 | ## Publicación
368 | ```python
369 | import time
370 | from umqtt.simple import MQTTClient
371 |
372 | c = MQTTClient("ESP8266", "cubie.kcobos.es")
373 | if not c.connect():
374 | print("Conectando")
375 |
376 | i=0
377 | while True:
378 | c.publish("prueba", "contando "+str(i))
379 | time.sleep(1)
380 | i+=1
381 |
382 | c.disconnect()
383 | ```
384 |
385 |
386 |
387 | # ¿Hacemos cosas con el µ?
388 |
389 |
390 |
391 | ## Salida digital
392 | ```python
393 | import machine
394 | led = machine.Pin(2, machine.Pin.OUT)
395 | led.value()
396 | led.off() # led.value(0)
397 | led.on() # led.value(1)
398 | ```
399 |
400 |
401 | ## Lectura digital
402 | ```python
403 | import machine
404 | boton = machine.Pin(4, machine.Pin.IN)
405 | boton.value()
406 | ```
407 | ```python
408 | def boton_irq(p):
409 | print("El botón ha sido pulsado")
410 | boton.irq(trigger=machine.Pin.IRQ_RISING, handler=boton_irq)
411 | #boton.irq(trigger=machine.Pin.IRQ_FALLING, handler=boton_irq)
412 | ```
413 |
414 |
415 |
416 | ## Lectura sensor
417 | DHT11
418 | ```python
419 | import machine
420 | import dht
421 | d = dht.DHT11(machine.Pin(5))
422 | d.measure()
423 | d.temperature()
424 | d.humidity()
425 | ```
426 |
427 |
428 | ## Lectura analógica
429 | ```python
430 | import machine
431 | lum = machine.ADC(0)
432 | lum.read()
433 | ```
434 |
435 |
436 | ## PWM (Pulse Width Modulation)
437 |
438 | ```python
439 | from machine import Pin, PWM
440 | pwm0 = PWM(Pin(2))
441 | pwm0.freq() # 0 - 1000
442 | pwm0.freq(1000)
443 | pwm0.duty() # 0 - 1023
444 | pwm0.duty(200)
445 | pwm0.deinit()
446 | ```
447 |
448 | ```python
449 | pwm1 = PWM(Pin(2), freq=500, duty=512)
450 | ```
451 |
452 |
453 |
454 | ## Y un largo etcétera
455 |
456 |
457 |
458 | ## ¿Cacharreamos?
459 |
460 |
461 | ## Placa de desarrollo
462 | ESP8266 NodeMCU WiFi Devkit
463 |
464 | [Datasheet](https://www.handsontec.com/pdf_learn/esp8266-V10.pdf)
465 |
466 |
467 |
468 |
469 |
470 | ## ¿Qué podemos hacer?
471 | * Controlar una el encendido y apagado de luz, electrodoméstico o calefacción desde nuestro móvil.
472 | * Controlar una el encendido y apagado de luz, electrodoméstico o calefacción por tiempo.
473 | * Controlar una el encendido y apagado de luz por luminosidad.
474 | * Controlar una el encendido y apagado de calefacción por temperatura.
475 | * Abrir una puerta con tarjeta RFID.
476 | * Telémetro con ultrasonidos.
477 |
--------------------------------------------------------------------------------