├── .gitignore
├── LICENSE.md
├── Procfile
├── README
├── import_slides.sh
├── index.html
├── instructors
├── index.html
└── slides
│ ├── slides.md
│ └── static
│ ├── css
│ ├── print
│ │ └── paper.css
│ ├── reveal.css
│ └── theme
│ │ ├── black.css
│ │ └── simple.css
│ ├── js
│ ├── jquery-2.1.3.min.js
│ └── reveal.js
│ ├── lib
│ ├── css
│ │ └── zenburn.css
│ ├── font
│ │ └── source-sans-pro
│ │ │ ├── source-sans-pro-italic.woff
│ │ │ ├── source-sans-pro-regular.woff
│ │ │ ├── source-sans-pro-semibold.woff
│ │ │ └── source-sans-pro.css
│ └── js
│ │ └── head.min.js
│ ├── plugin
│ ├── markdown
│ │ ├── markdown.js
│ │ └── marked.js
│ ├── notes
│ │ ├── notes.html
│ │ └── notes.js
│ └── zoom-js
│ │ └── zoom.js
│ └── slides.html
├── requirements.txt
├── schedule
├── .gitignore
└── index.html
├── static
├── bootstrap-4.1.3-dist
│ ├── css
│ │ ├── .DS_Store
│ │ ├── bootstrap-grid.css
│ │ ├── bootstrap-grid.css.map
│ │ ├── bootstrap-grid.min.css
│ │ ├── bootstrap-grid.min.css.map
│ │ ├── bootstrap-reboot.css
│ │ ├── bootstrap-reboot.css.map
│ │ ├── bootstrap-reboot.min.css
│ │ ├── bootstrap-reboot.min.css.map
│ │ ├── bootstrap.css
│ │ ├── bootstrap.css.map
│ │ ├── bootstrap.min.css
│ │ └── bootstrap.min.css.map
│ └── js
│ │ ├── bootstrap.bundle.js
│ │ ├── bootstrap.bundle.js.map
│ │ ├── bootstrap.bundle.min.js
│ │ ├── bootstrap.bundle.min.js.map
│ │ ├── bootstrap.js
│ │ ├── bootstrap.js.map
│ │ ├── bootstrap.min.js
│ │ └── bootstrap.min.js.map
├── images
│ └── IMG_9232.jpg
├── jquery-2.1.3.js
└── pets.css
└── student-handout
├── slides.md
└── static
├── css
├── print
│ └── paper.css
├── reveal.css
└── theme
│ ├── black.css
│ └── simple.css
├── js
├── jquery-2.1.3.min.js
└── reveal.js
├── lib
├── css
│ └── zenburn.css
├── font
│ └── source-sans-pro
│ │ ├── source-sans-pro-italic.woff
│ │ ├── source-sans-pro-regular.woff
│ │ ├── source-sans-pro-semibold.woff
│ │ └── source-sans-pro.css
└── js
│ └── head.min.js
├── plugin
├── markdown
│ ├── markdown.js
│ └── marked.js
├── notes
│ ├── notes.html
│ └── notes.js
└── zoom-js
│ └── zoom.js
└── slides.html
/.gitignore:
--------------------------------------------------------------------------------
1 | *#
2 | .idea
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: python -m http.server $PORT
2 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | This repository contains the lab material for the tutorial Web Application Security with Django.
2 |
3 | This tutorial was presented at PyCon 2015 and 2019, and DjangoCon 2018 and 2019.
4 |
5 | The PyCon versions were recorded and the videos can be found here:
6 |
7 | PyCon 2019 with Jacinda Shelly: https://www.youtube.com/watch?v=8W4MGggwgfM
8 |
9 | PyCon 2015 with Asheesh Laroia, Jacky Chang, and Nicole Zuckerman: https://www.youtube.com/watch?v=f9XVNIeRxUo
10 |
--------------------------------------------------------------------------------
/import_slides.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Like 'use strict'; but for bash!
4 | set -euo pipefail
5 |
6 | # This script will import slides from the Hacker Slides instance that
7 | # Asheesh has been using into a directory structure that can live in
8 | # this repo.
9 |
10 | mkdir -p student-handout
11 | pushd student-handout
12 |
13 | # First, nab the slides.
14 | wget --header "Cookie: $2" "https://$1/slides.md"
15 |
16 | # Then, nab the static directory, and all that it references.
17 | mkdir -p static
18 | pushd static
19 | wget -nH --cut-dirs=1 --mirror --no-parent --header "Cookie: $2" "https://$1/static/slides.html" || true # OK if this fails.
20 |
21 | # Grab these extra dependencies.
22 | for thing in "plugin/markdown/markdown.js" "plugin/markdown/marked.js" "css/print/paper.css" "plugin/zoom-js/zoom.js" "plugin/notes/notes.js" "plugin/notes/notes.html"
23 | do
24 | wget -nH --cut-dirs=1 --mirror --no-parent --header "Cookie: $2" "https://$1/static/$thing" || true # OK if this fails.
25 | done
26 |
27 | # Prepare this for git commit, but let the user be the one to actually
28 | # commit it.
29 | popd; popd
30 | git add .
31 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
Welcome to pettwitter
12 |
13 |
14 |
About this site
15 |
16 |
This is a site to help you prepare for a DjangoCon 2019 tutorial called
17 | Web Application Security with Django .
18 |
19 |
20 |
27 |
28 |
29 |
30 |
31 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/instructors/index.html:
--------------------------------------------------------------------------------
1 |
2 | There's a
3 |
4 | secret slides link
5 |
6 | just for instructors.
7 |
8 |
--------------------------------------------------------------------------------
/instructors/slides/static/css/print/paper.css:
--------------------------------------------------------------------------------
1 | /* Default Print Stylesheet Template
2 | by Rob Glazebrook of CSSnewbie.com
3 | Last Updated: June 4, 2008
4 |
5 | Feel free (nay, compelled) to edit, append, and
6 | manipulate this file as you see fit. */
7 |
8 |
9 | @media print {
10 |
11 | /* SECTION 1: Set default width, margin, float, and
12 | background. This prevents elements from extending
13 | beyond the edge of the printed page, and prevents
14 | unnecessary background images from printing */
15 | html {
16 | background: #fff;
17 | width: auto;
18 | height: auto;
19 | overflow: visible;
20 | }
21 | body {
22 | background: #fff;
23 | font-size: 20pt;
24 | width: auto;
25 | height: auto;
26 | border: 0;
27 | margin: 0 5%;
28 | padding: 0;
29 | overflow: visible;
30 | float: none !important;
31 | }
32 |
33 | /* SECTION 2: Remove any elements not needed in print.
34 | This would include navigation, ads, sidebars, etc. */
35 | .nestedarrow,
36 | .controls,
37 | .fork-reveal,
38 | .share-reveal,
39 | .state-background,
40 | .reveal .progress,
41 | .reveal .backgrounds {
42 | display: none !important;
43 | }
44 |
45 | /* SECTION 3: Set body font face, size, and color.
46 | Consider using a serif font for readability. */
47 | body, p, td, li, div {
48 | font-size: 20pt!important;
49 | font-family: Georgia, "Times New Roman", Times, serif !important;
50 | color: #000;
51 | }
52 |
53 | /* SECTION 4: Set heading font face, sizes, and color.
54 | Differentiate your headings from your body text.
55 | Perhaps use a large sans-serif for distinction. */
56 | h1,h2,h3,h4,h5,h6 {
57 | color: #000!important;
58 | height: auto;
59 | line-height: normal;
60 | font-family: Georgia, "Times New Roman", Times, serif !important;
61 | text-shadow: 0 0 0 #000 !important;
62 | text-align: left;
63 | letter-spacing: normal;
64 | }
65 | /* Need to reduce the size of the fonts for printing */
66 | h1 { font-size: 28pt !important; }
67 | h2 { font-size: 24pt !important; }
68 | h3 { font-size: 22pt !important; }
69 | h4 { font-size: 22pt !important; font-variant: small-caps; }
70 | h5 { font-size: 21pt !important; }
71 | h6 { font-size: 20pt !important; font-style: italic; }
72 |
73 | /* SECTION 5: Make hyperlinks more usable.
74 | Ensure links are underlined, and consider appending
75 | the URL to the end of the link for usability. */
76 | a:link,
77 | a:visited {
78 | color: #000 !important;
79 | font-weight: bold;
80 | text-decoration: underline;
81 | }
82 | /*
83 | .reveal a:link:after,
84 | .reveal a:visited:after {
85 | content: " (" attr(href) ") ";
86 | color: #222 !important;
87 | font-size: 90%;
88 | }
89 | */
90 |
91 |
92 | /* SECTION 6: more reveal.js specific additions by @skypanther */
93 | ul, ol, div, p {
94 | visibility: visible;
95 | position: static;
96 | width: auto;
97 | height: auto;
98 | display: block;
99 | overflow: visible;
100 | margin: 0;
101 | text-align: left !important;
102 | }
103 | .reveal pre,
104 | .reveal table {
105 | margin-left: 0;
106 | margin-right: 0;
107 | }
108 | .reveal pre code {
109 | padding: 20px;
110 | border: 1px solid #ddd;
111 | }
112 | .reveal blockquote {
113 | margin: 20px 0;
114 | }
115 | .reveal .slides {
116 | position: static !important;
117 | width: auto !important;
118 | height: auto !important;
119 |
120 | left: 0 !important;
121 | top: 0 !important;
122 | margin-left: 0 !important;
123 | margin-top: 0 !important;
124 | padding: 0 !important;
125 | zoom: 1 !important;
126 |
127 | overflow: visible !important;
128 | display: block !important;
129 |
130 | text-align: left !important;
131 | -webkit-perspective: none;
132 | -moz-perspective: none;
133 | -ms-perspective: none;
134 | perspective: none;
135 |
136 | -webkit-perspective-origin: 50% 50%;
137 | -moz-perspective-origin: 50% 50%;
138 | -ms-perspective-origin: 50% 50%;
139 | perspective-origin: 50% 50%;
140 | }
141 | .reveal .slides section {
142 | visibility: visible !important;
143 | position: static !important;
144 | width: 100% !important;
145 | height: auto !important;
146 | display: block !important;
147 | overflow: visible !important;
148 |
149 | left: 0 !important;
150 | top: 0 !important;
151 | margin-left: 0 !important;
152 | margin-top: 0 !important;
153 | padding: 60px 20px !important;
154 | z-index: auto !important;
155 |
156 | opacity: 1 !important;
157 |
158 | page-break-after: always !important;
159 |
160 | -webkit-transform-style: flat !important;
161 | -moz-transform-style: flat !important;
162 | -ms-transform-style: flat !important;
163 | transform-style: flat !important;
164 |
165 | -webkit-transform: none !important;
166 | -moz-transform: none !important;
167 | -ms-transform: none !important;
168 | transform: none !important;
169 |
170 | -webkit-transition: none !important;
171 | -moz-transition: none !important;
172 | -ms-transition: none !important;
173 | transition: none !important;
174 | }
175 | .reveal .slides section.stack {
176 | padding: 0 !important;
177 | }
178 | .reveal section:last-of-type {
179 | page-break-after: avoid !important;
180 | }
181 | .reveal section .fragment {
182 | opacity: 1 !important;
183 | visibility: visible !important;
184 |
185 | -webkit-transform: none !important;
186 | -moz-transform: none !important;
187 | -ms-transform: none !important;
188 | transform: none !important;
189 | }
190 | .reveal section img {
191 | display: block;
192 | margin: 15px 0px;
193 | background: rgba(255,255,255,1);
194 | border: 1px solid #666;
195 | box-shadow: none;
196 | }
197 |
198 | .reveal section small {
199 | font-size: 0.8em;
200 | }
201 |
202 | }
--------------------------------------------------------------------------------
/instructors/slides/static/css/theme/black.css:
--------------------------------------------------------------------------------
1 | @import url(../../lib/font/source-sans-pro/source-sans-pro.css);
2 | /**
3 | * Black theme for reveal.js. This is the opposite of the 'white' theme.
4 | *
5 | * Copyright (C) 2015 Hakim El Hattab, http://hakim.se
6 | */
7 | section.has-light-background, section.has-light-background h1, section.has-light-background h2, section.has-light-background h3, section.has-light-background h4, section.has-light-background h5, section.has-light-background h6 {
8 | color: #222; }
9 |
10 | /*********************************************
11 | * GLOBAL STYLES
12 | *********************************************/
13 | body {
14 | background: #222;
15 | background-color: #222; }
16 |
17 | .reveal {
18 | font-family: 'Source Sans Pro', Helvetica, sans-serif;
19 | font-size: 38px;
20 | font-weight: normal;
21 | color: #fff; }
22 |
23 | ::selection {
24 | color: #fff;
25 | background: #bee4fd;
26 | text-shadow: none; }
27 |
28 | .reveal .slides > section, .reveal .slides > section > section {
29 | line-height: 1.3;
30 | font-weight: inherit; }
31 |
32 | /*********************************************
33 | * HEADERS
34 | *********************************************/
35 | .reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 {
36 | margin: 0 0 20px 0;
37 | color: #fff;
38 | font-family: 'Source Sans Pro', Helvetica, sans-serif;
39 | font-weight: 600;
40 | line-height: 1.2;
41 | letter-spacing: normal;
42 | text-transform: uppercase;
43 | text-shadow: none;
44 | word-wrap: break-word; }
45 |
46 | .reveal h1 {
47 | font-size: 2.5em; }
48 |
49 | .reveal h2 {
50 | font-size: 1.6em; }
51 |
52 | .reveal h3 {
53 | font-size: 1.3em; }
54 |
55 | .reveal h4 {
56 | font-size: 1em; }
57 |
58 | .reveal h1 {
59 | text-shadow: none; }
60 |
61 | /*********************************************
62 | * OTHER
63 | *********************************************/
64 | .reveal p {
65 | margin: 20px 0;
66 | line-height: 1.3; }
67 |
68 | /* Ensure certain elements are never larger than the slide itself */
69 | .reveal img, .reveal video, .reveal iframe {
70 | max-width: 95%;
71 | max-height: 95%; }
72 |
73 | .reveal strong, .reveal b {
74 | font-weight: bold; }
75 |
76 | .reveal em {
77 | font-style: italic; }
78 |
79 | .reveal ol, .reveal dl, .reveal ul {
80 | display: inline-block;
81 | text-align: left;
82 | margin: 0 0 0 1em; }
83 |
84 | .reveal ol {
85 | list-style-type: decimal; }
86 |
87 | .reveal ul {
88 | list-style-type: disc; }
89 |
90 | .reveal ul ul {
91 | list-style-type: square; }
92 |
93 | .reveal ul ul ul {
94 | list-style-type: circle; }
95 |
96 | .reveal ul ul, .reveal ul ol, .reveal ol ol, .reveal ol ul {
97 | display: block;
98 | margin-left: 40px; }
99 |
100 | .reveal dt {
101 | font-weight: bold; }
102 |
103 | .reveal dd {
104 | margin-left: 40px; }
105 |
106 | .reveal q, .reveal blockquote {
107 | quotes: none; }
108 |
109 | .reveal blockquote {
110 | display: block;
111 | position: relative;
112 | width: 70%;
113 | margin: 20px auto;
114 | padding: 5px;
115 | font-style: italic;
116 | background: rgba(255, 255, 255, 0.05);
117 | box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); }
118 |
119 | .reveal blockquote p:first-child, .reveal blockquote p:last-child {
120 | display: inline-block; }
121 |
122 | .reveal q {
123 | font-style: italic; }
124 |
125 | .reveal pre {
126 | display: block;
127 | position: relative;
128 | width: 90%;
129 | margin: 20px auto;
130 | text-align: left;
131 | font-size: 0.55em;
132 | font-family: monospace;
133 | line-height: 1.2em;
134 | word-wrap: break-word;
135 | box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); }
136 |
137 | .reveal code {
138 | font-family: monospace; }
139 |
140 | .reveal pre code {
141 | display: block;
142 | padding: 5px;
143 | overflow: auto;
144 | max-height: 400px;
145 | word-wrap: normal;
146 | background: #3F3F3F;
147 | color: #DCDCDC; }
148 |
149 | .reveal table {
150 | margin: auto;
151 | border-collapse: collapse;
152 | border-spacing: 0; }
153 |
154 | .reveal table th {
155 | font-weight: bold; }
156 |
157 | .reveal table th, .reveal table td {
158 | text-align: left;
159 | padding: 0.2em 0.5em 0.2em 0.5em;
160 | border-bottom: 1px solid; }
161 |
162 | .reveal table tr:last-child td {
163 | border-bottom: none; }
164 |
165 | .reveal sup {
166 | vertical-align: super; }
167 |
168 | .reveal sub {
169 | vertical-align: sub; }
170 |
171 | .reveal small {
172 | display: inline-block;
173 | font-size: 0.6em;
174 | line-height: 1.2em;
175 | vertical-align: top; }
176 |
177 | .reveal small * {
178 | vertical-align: top; }
179 |
180 | /*********************************************
181 | * LINKS
182 | *********************************************/
183 | .reveal a {
184 | color: #42affa;
185 | text-decoration: none;
186 | -webkit-transition: color 0.15s ease;
187 | -moz-transition: color 0.15s ease;
188 | transition: color 0.15s ease; }
189 |
190 | .reveal a:hover {
191 | color: #8dcffc;
192 | text-shadow: none;
193 | border: none; }
194 |
195 | .reveal .roll span:after {
196 | color: #fff;
197 | background: #068ee9; }
198 |
199 | /*********************************************
200 | * IMAGES
201 | *********************************************/
202 | .reveal section img {
203 | margin: 15px 0px;
204 | background: rgba(255, 255, 255, 0.12);
205 | border: 4px solid #fff;
206 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); }
207 |
208 | .reveal a img {
209 | -webkit-transition: all 0.15s linear;
210 | -moz-transition: all 0.15s linear;
211 | transition: all 0.15s linear; }
212 |
213 | .reveal a:hover img {
214 | background: rgba(255, 255, 255, 0.2);
215 | border-color: #42affa;
216 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); }
217 |
218 | /*********************************************
219 | * NAVIGATION CONTROLS
220 | *********************************************/
221 | .reveal .controls div.navigate-left, .reveal .controls div.navigate-left.enabled {
222 | border-right-color: #42affa; }
223 |
224 | .reveal .controls div.navigate-right, .reveal .controls div.navigate-right.enabled {
225 | border-left-color: #42affa; }
226 |
227 | .reveal .controls div.navigate-up, .reveal .controls div.navigate-up.enabled {
228 | border-bottom-color: #42affa; }
229 |
230 | .reveal .controls div.navigate-down, .reveal .controls div.navigate-down.enabled {
231 | border-top-color: #42affa; }
232 |
233 | .reveal .controls div.navigate-left.enabled:hover {
234 | border-right-color: #8dcffc; }
235 |
236 | .reveal .controls div.navigate-right.enabled:hover {
237 | border-left-color: #8dcffc; }
238 |
239 | .reveal .controls div.navigate-up.enabled:hover {
240 | border-bottom-color: #8dcffc; }
241 |
242 | .reveal .controls div.navigate-down.enabled:hover {
243 | border-top-color: #8dcffc; }
244 |
245 | /*********************************************
246 | * PROGRESS BAR
247 | *********************************************/
248 | .reveal .progress {
249 | background: rgba(0, 0, 0, 0.2); }
250 |
251 | .reveal .progress span {
252 | background: #42affa;
253 | -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
254 | -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
255 | transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
256 |
257 | /*********************************************
258 | * SLIDE NUMBER
259 | *********************************************/
260 | .reveal .slide-number {
261 | color: #42affa; }
262 |
--------------------------------------------------------------------------------
/instructors/slides/static/css/theme/simple.css:
--------------------------------------------------------------------------------
1 | @import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700);
2 | @import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
3 | /**
4 | * A simple theme for reveal.js presentations, similar
5 | * to the default theme. The accent color is darkblue.
6 | *
7 | * This theme is Copyright (C) 2012 Owen Versteeg, https://github.com/StereotypicalApps. It is MIT licensed.
8 | * reveal.js is Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
9 | */
10 | /*********************************************
11 | * GLOBAL STYLES
12 | *********************************************/
13 | body {
14 | background: #fff;
15 | background-color: #fff; }
16 |
17 | .reveal {
18 | font-family: 'Lato', sans-serif;
19 | font-size: 36px;
20 | font-weight: normal;
21 | color: #000; }
22 |
23 | ::selection {
24 | color: #fff;
25 | background: rgba(0, 0, 0, 0.99);
26 | text-shadow: none; }
27 |
28 | .reveal .slides > section, .reveal .slides > section > section {
29 | line-height: 1.3;
30 | font-weight: inherit; }
31 |
32 | /*********************************************
33 | * HEADERS
34 | *********************************************/
35 | .reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 {
36 | margin: 0 0 20px 0;
37 | color: #000;
38 | font-family: 'News Cycle', Impact, sans-serif;
39 | font-weight: normal;
40 | line-height: 1.2;
41 | letter-spacing: normal;
42 | text-transform: none;
43 | text-shadow: none;
44 | word-wrap: break-word; }
45 |
46 | .reveal h1 {
47 | font-size: 3.77em; }
48 |
49 | .reveal h2 {
50 | font-size: 2em; }
51 |
52 | .reveal h3 {
53 | font-size: 1.55em; }
54 |
55 | .reveal h4 {
56 | font-size: 1em; }
57 |
58 | .reveal h1 {
59 | text-shadow: none; }
60 |
61 | /*********************************************
62 | * OTHER
63 | *********************************************/
64 | .reveal p {
65 | margin: 20px 0;
66 | line-height: 1.3; }
67 |
68 | /* Ensure certain elements are never larger than the slide itself */
69 | .reveal img, .reveal video, .reveal iframe {
70 | max-width: 95%;
71 | max-height: 95%; }
72 |
73 | .reveal strong, .reveal b {
74 | font-weight: bold; }
75 |
76 | .reveal em {
77 | font-style: italic; }
78 |
79 | .reveal ol, .reveal dl, .reveal ul {
80 | display: inline-block;
81 | text-align: left;
82 | margin: 0 0 0 1em; }
83 |
84 | .reveal ol {
85 | list-style-type: decimal; }
86 |
87 | .reveal ul {
88 | list-style-type: disc; }
89 |
90 | .reveal ul ul {
91 | list-style-type: square; }
92 |
93 | .reveal ul ul ul {
94 | list-style-type: circle; }
95 |
96 | .reveal ul ul, .reveal ul ol, .reveal ol ol, .reveal ol ul {
97 | display: block;
98 | margin-left: 40px; }
99 |
100 | .reveal dt {
101 | font-weight: bold; }
102 |
103 | .reveal dd {
104 | margin-left: 40px; }
105 |
106 | .reveal q, .reveal blockquote {
107 | quotes: none; }
108 |
109 | .reveal blockquote {
110 | display: block;
111 | position: relative;
112 | width: 70%;
113 | margin: 20px auto;
114 | padding: 5px;
115 | font-style: italic;
116 | background: rgba(255, 255, 255, 0.05);
117 | box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); }
118 |
119 | .reveal blockquote p:first-child, .reveal blockquote p:last-child {
120 | display: inline-block; }
121 |
122 | .reveal q {
123 | font-style: italic; }
124 |
125 | .reveal pre {
126 | display: block;
127 | position: relative;
128 | width: 90%;
129 | margin: 20px auto;
130 | text-align: left;
131 | font-size: 0.55em;
132 | font-family: monospace;
133 | line-height: 1.2em;
134 | word-wrap: break-word;
135 | box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); }
136 |
137 | .reveal code {
138 | font-family: monospace; }
139 |
140 | .reveal pre code {
141 | display: block;
142 | padding: 5px;
143 | overflow: auto;
144 | max-height: 400px;
145 | word-wrap: normal;
146 | background: #3F3F3F;
147 | color: #DCDCDC; }
148 |
149 | .reveal table {
150 | margin: auto;
151 | border-collapse: collapse;
152 | border-spacing: 0; }
153 |
154 | .reveal table th {
155 | font-weight: bold; }
156 |
157 | .reveal table th, .reveal table td {
158 | text-align: left;
159 | padding: 0.2em 0.5em 0.2em 0.5em;
160 | border-bottom: 1px solid; }
161 |
162 | .reveal table tr:last-child td {
163 | border-bottom: none; }
164 |
165 | .reveal sup {
166 | vertical-align: super; }
167 |
168 | .reveal sub {
169 | vertical-align: sub; }
170 |
171 | .reveal small {
172 | display: inline-block;
173 | font-size: 0.6em;
174 | line-height: 1.2em;
175 | vertical-align: top; }
176 |
177 | .reveal small * {
178 | vertical-align: top; }
179 |
180 | /*********************************************
181 | * LINKS
182 | *********************************************/
183 | .reveal a {
184 | color: #00008B;
185 | text-decoration: none;
186 | -webkit-transition: color 0.15s ease;
187 | -moz-transition: color 0.15s ease;
188 | transition: color 0.15s ease; }
189 |
190 | .reveal a:hover {
191 | color: #0000f1;
192 | text-shadow: none;
193 | border: none; }
194 |
195 | .reveal .roll span:after {
196 | color: #fff;
197 | background: #00003f; }
198 |
199 | /*********************************************
200 | * IMAGES
201 | *********************************************/
202 | .reveal section img {
203 | margin: 15px 0px;
204 | background: rgba(255, 255, 255, 0.12);
205 | border: 4px solid #000;
206 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); }
207 |
208 | .reveal a img {
209 | -webkit-transition: all 0.15s linear;
210 | -moz-transition: all 0.15s linear;
211 | transition: all 0.15s linear; }
212 |
213 | .reveal a:hover img {
214 | background: rgba(255, 255, 255, 0.2);
215 | border-color: #00008B;
216 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); }
217 |
218 | /*********************************************
219 | * NAVIGATION CONTROLS
220 | *********************************************/
221 | .reveal .controls div.navigate-left, .reveal .controls div.navigate-left.enabled {
222 | border-right-color: #00008B; }
223 |
224 | .reveal .controls div.navigate-right, .reveal .controls div.navigate-right.enabled {
225 | border-left-color: #00008B; }
226 |
227 | .reveal .controls div.navigate-up, .reveal .controls div.navigate-up.enabled {
228 | border-bottom-color: #00008B; }
229 |
230 | .reveal .controls div.navigate-down, .reveal .controls div.navigate-down.enabled {
231 | border-top-color: #00008B; }
232 |
233 | .reveal .controls div.navigate-left.enabled:hover {
234 | border-right-color: #0000f1; }
235 |
236 | .reveal .controls div.navigate-right.enabled:hover {
237 | border-left-color: #0000f1; }
238 |
239 | .reveal .controls div.navigate-up.enabled:hover {
240 | border-bottom-color: #0000f1; }
241 |
242 | .reveal .controls div.navigate-down.enabled:hover {
243 | border-top-color: #0000f1; }
244 |
245 | /*********************************************
246 | * PROGRESS BAR
247 | *********************************************/
248 | .reveal .progress {
249 | background: rgba(0, 0, 0, 0.2); }
250 |
251 | .reveal .progress span {
252 | background: #00008B;
253 | -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
254 | -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
255 | transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
256 |
257 | /*********************************************
258 | * SLIDE NUMBER
259 | *********************************************/
260 | .reveal .slide-number {
261 | color: #00008B; }
262 |
--------------------------------------------------------------------------------
/instructors/slides/static/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; padding: 0.5em;
10 | background: #3F3F3F;
11 | color: #DCDCDC;
12 | }
13 |
14 | .hljs-keyword,
15 | .hljs-tag,
16 | .css .hljs-class,
17 | .css .hljs-id,
18 | .lisp .hljs-title,
19 | .nginx .hljs-title,
20 | .hljs-request,
21 | .hljs-status,
22 | .clojure .hljs-attribute {
23 | color: #E3CEAB;
24 | }
25 |
26 | .django .hljs-template_tag,
27 | .django .hljs-variable,
28 | .django .hljs-filter .hljs-argument {
29 | color: #DCDCDC;
30 | }
31 |
32 | .hljs-number,
33 | .hljs-date {
34 | color: #8CD0D3;
35 | }
36 |
37 | .dos .hljs-envvar,
38 | .dos .hljs-stream,
39 | .hljs-variable,
40 | .apache .hljs-sqbracket {
41 | color: #EFDCBC;
42 | }
43 |
44 | .dos .hljs-flow,
45 | .diff .hljs-change,
46 | .python .exception,
47 | .python .hljs-built_in,
48 | .hljs-literal,
49 | .tex .hljs-special {
50 | color: #EFEFAF;
51 | }
52 |
53 | .diff .hljs-chunk,
54 | .hljs-subst {
55 | color: #8F8F8F;
56 | }
57 |
58 | .dos .hljs-keyword,
59 | .python .hljs-decorator,
60 | .hljs-title,
61 | .haskell .hljs-type,
62 | .diff .hljs-header,
63 | .ruby .hljs-class .hljs-parent,
64 | .apache .hljs-tag,
65 | .nginx .hljs-built_in,
66 | .tex .hljs-command,
67 | .hljs-prompt {
68 | color: #efef8f;
69 | }
70 |
71 | .dos .hljs-winutils,
72 | .ruby .hljs-symbol,
73 | .ruby .hljs-symbol .hljs-string,
74 | .ruby .hljs-string {
75 | color: #DCA3A3;
76 | }
77 |
78 | .diff .hljs-deletion,
79 | .hljs-string,
80 | .hljs-tag .hljs-value,
81 | .hljs-preprocessor,
82 | .hljs-pragma,
83 | .hljs-built_in,
84 | .sql .hljs-aggregate,
85 | .hljs-javadoc,
86 | .smalltalk .hljs-class,
87 | .smalltalk .hljs-localvars,
88 | .smalltalk .hljs-array,
89 | .css .hljs-rules .hljs-value,
90 | .hljs-attr_selector,
91 | .hljs-pseudo,
92 | .apache .hljs-cbracket,
93 | .tex .hljs-formula,
94 | .coffeescript .hljs-attribute {
95 | color: #CC9393;
96 | }
97 |
98 | .hljs-shebang,
99 | .diff .hljs-addition,
100 | .hljs-comment,
101 | .java .hljs-annotation,
102 | .hljs-template_comment,
103 | .hljs-pi,
104 | .hljs-doctype {
105 | color: #7F9F7F;
106 | }
107 |
108 | .coffeescript .javascript,
109 | .javascript .xml,
110 | .tex .hljs-formula,
111 | .xml .javascript,
112 | .xml .vbscript,
113 | .xml .css,
114 | .xml .hljs-cdata {
115 | opacity: 0.5;
116 | }
117 |
118 |
--------------------------------------------------------------------------------
/instructors/slides/static/lib/font/source-sans-pro/source-sans-pro-italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/django-security-tutorials/hands-on-web-security-slides/471b4c53d7e1b64a0ebc5f7af1dc054a665c4bdc/instructors/slides/static/lib/font/source-sans-pro/source-sans-pro-italic.woff
--------------------------------------------------------------------------------
/instructors/slides/static/lib/font/source-sans-pro/source-sans-pro-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/django-security-tutorials/hands-on-web-security-slides/471b4c53d7e1b64a0ebc5f7af1dc054a665c4bdc/instructors/slides/static/lib/font/source-sans-pro/source-sans-pro-regular.woff
--------------------------------------------------------------------------------
/instructors/slides/static/lib/font/source-sans-pro/source-sans-pro-semibold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/django-security-tutorials/hands-on-web-security-slides/471b4c53d7e1b64a0ebc5f7af1dc054a665c4bdc/instructors/slides/static/lib/font/source-sans-pro/source-sans-pro-semibold.woff
--------------------------------------------------------------------------------
/instructors/slides/static/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 | }
--------------------------------------------------------------------------------
/instructors/slides/static/lib/js/head.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | Head JS The only script in your
3 | Copyright Tero Piirainen (tipiirai)
4 | License MIT / http://bit.ly/mit-license
5 | Version 0.96
6 |
7 | http://headjs.com
8 | */(function(a){function z(){d||(d=!0,s(e,function(a){p(a)}))}function y(c,d){var e=a.createElement("script");e.type="text/"+(c.type||"javascript"),e.src=c.src||c,e.async=!1,e.onreadystatechange=e.onload=function(){var a=e.readyState;!d.done&&(!a||/loaded|complete/.test(a))&&(d.done=!0,d())},(a.body||b).appendChild(e)}function x(a,b){if(a.state==o)return b&&b();if(a.state==n)return k.ready(a.name,b);if(a.state==m)return a.onpreload.push(function(){x(a,b)});a.state=n,y(a.url,function(){a.state=o,b&&b(),s(g[a.name],function(a){p(a)}),u()&&d&&s(g.ALL,function(a){p(a)})})}function w(a,b){a.state===undefined&&(a.state=m,a.onpreload=[],y({src:a.url,type:"cache"},function(){v(a)}))}function v(a){a.state=l,s(a.onpreload,function(a){a.call()})}function u(a){a=a||h;var b;for(var c in a){if(a.hasOwnProperty(c)&&a[c].state!=o)return!1;b=!0}return b}function t(a){return Object.prototype.toString.call(a)=="[object Function]"}function s(a,b){if(!!a){typeof a=="object"&&(a=[].slice.call(a));for(var c=0;c 0 ) {
50 | text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' );
51 | }
52 | else if( leadingWs > 1 ) {
53 | text = text.replace( new RegExp('\\n? {' + leadingWs + '}'), '\n' );
54 | }
55 |
56 | return text;
57 |
58 | }
59 |
60 | /**
61 | * Given a markdown slide section element, this will
62 | * return all arguments that aren't related to markdown
63 | * parsing. Used to forward any other user-defined arguments
64 | * to the output markdown slide.
65 | */
66 | function getForwardedAttributes( section ) {
67 |
68 | var attributes = section.attributes;
69 | var result = [];
70 |
71 | for( var i = 0, len = attributes.length; i < len; i++ ) {
72 | var name = attributes[i].name,
73 | value = attributes[i].value;
74 |
75 | // disregard attributes that are used for markdown loading/parsing
76 | if( /data\-(markdown|separator|vertical|notes)/gi.test( name ) ) continue;
77 |
78 | if( value ) {
79 | result.push( name + '=' + value );
80 | }
81 | else {
82 | result.push( name );
83 | }
84 | }
85 |
86 | return result.join( ' ' );
87 |
88 | }
89 |
90 | /**
91 | * Inspects the given options and fills out default
92 | * values for what's not defined.
93 | */
94 | function getSlidifyOptions( options ) {
95 |
96 | options = options || {};
97 | options.separator = options.separator || DEFAULT_SLIDE_SEPARATOR;
98 | options.notesSeparator = options.notesSeparator || DEFAULT_NOTES_SEPARATOR;
99 | options.attributes = options.attributes || '';
100 |
101 | return options;
102 |
103 | }
104 |
105 | /**
106 | * Helper function for constructing a markdown slide.
107 | */
108 | function createMarkdownSlide( content, options ) {
109 |
110 | options = getSlidifyOptions( options );
111 |
112 | var notesMatch = content.split( new RegExp( options.notesSeparator, 'mgi' ) );
113 |
114 | if( notesMatch.length === 2 ) {
115 | content = notesMatch[0] + '' + notesMatch[1].trim() + ' ';
116 | }
117 |
118 | return '';
119 |
120 | }
121 |
122 | /**
123 | * Parses a data string into multiple slides based
124 | * on the passed in separator arguments.
125 | */
126 | function slidify( markdown, options ) {
127 |
128 | options = getSlidifyOptions( options );
129 |
130 | var separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ),
131 | horizontalSeparatorRegex = new RegExp( options.separator );
132 |
133 | var matches,
134 | lastIndex = 0,
135 | isHorizontal,
136 | wasHorizontal = true,
137 | content,
138 | sectionStack = [];
139 |
140 | // iterate until all blocks between separators are stacked up
141 | while( matches = separatorRegex.exec( markdown ) ) {
142 | notes = null;
143 |
144 | // determine direction (horizontal by default)
145 | isHorizontal = horizontalSeparatorRegex.test( matches[0] );
146 |
147 | if( !isHorizontal && wasHorizontal ) {
148 | // create vertical stack
149 | sectionStack.push( [] );
150 | }
151 |
152 | // pluck slide content from markdown input
153 | content = markdown.substring( lastIndex, matches.index );
154 |
155 | if( isHorizontal && wasHorizontal ) {
156 | // add to horizontal stack
157 | sectionStack.push( content );
158 | }
159 | else {
160 | // add to vertical stack
161 | sectionStack[sectionStack.length-1].push( content );
162 | }
163 |
164 | lastIndex = separatorRegex.lastIndex;
165 | wasHorizontal = isHorizontal;
166 | }
167 |
168 | // add the remaining slide
169 | ( wasHorizontal ? sectionStack : sectionStack[sectionStack.length-1] ).push( markdown.substring( lastIndex ) );
170 |
171 | var markdownSections = '';
172 |
173 | // flatten the hierarchical stack, and insert tags
174 | for( var i = 0, len = sectionStack.length; i < len; i++ ) {
175 | // vertical
176 | if( sectionStack[i] instanceof Array ) {
177 | markdownSections += '';
178 |
179 | sectionStack[i].forEach( function( child ) {
180 | markdownSections += '' + createMarkdownSlide( child, options ) + ' ';
181 | } );
182 |
183 | markdownSections += ' ';
184 | }
185 | else {
186 | markdownSections += '' + createMarkdownSlide( sectionStack[i], options ) + ' ';
187 | }
188 | }
189 |
190 | return markdownSections;
191 |
192 | }
193 |
194 | /**
195 | * Parses any current data-markdown slides, splits
196 | * multi-slide markdown into separate sections and
197 | * handles loading of external markdown.
198 | */
199 | function processSlides() {
200 |
201 | var sections = document.querySelectorAll( '[data-markdown]'),
202 | section;
203 |
204 | for( var i = 0, len = sections.length; i < len; i++ ) {
205 |
206 | section = sections[i];
207 |
208 | if( section.getAttribute( 'data-markdown' ).length ) {
209 |
210 | var xhr = new XMLHttpRequest(),
211 | url = section.getAttribute( 'data-markdown' );
212 |
213 | datacharset = section.getAttribute( 'data-charset' );
214 |
215 | // see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes
216 | if( datacharset != null && datacharset != '' ) {
217 | xhr.overrideMimeType( 'text/html; charset=' + datacharset );
218 | }
219 |
220 | xhr.onreadystatechange = function() {
221 | if( xhr.readyState === 4 ) {
222 | // file protocol yields status code 0 (useful for local debug, mobile applications etc.)
223 | if ( ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status === 0 ) {
224 |
225 | section.outerHTML = slidify( xhr.responseText, {
226 | separator: section.getAttribute( 'data-separator' ),
227 | verticalSeparator: section.getAttribute( 'data-separator-vertical' ),
228 | notesSeparator: section.getAttribute( 'data-separator-notes' ),
229 | attributes: getForwardedAttributes( section )
230 | });
231 |
232 | }
233 | else {
234 |
235 | section.outerHTML = '' +
236 | 'ERROR: The attempt to fetch ' + url + ' failed with HTTP status ' + xhr.status + '.' +
237 | 'Check your browser\'s JavaScript console for more details.' +
238 | 'Remember that you need to serve the presentation HTML from a HTTP server.
' +
239 | ' ';
240 |
241 | }
242 | }
243 | };
244 |
245 | xhr.open( 'GET', url, false );
246 |
247 | try {
248 | xhr.send();
249 | }
250 | catch ( e ) {
251 | 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 );
252 | }
253 |
254 | }
255 | else if( section.getAttribute( 'data-separator' ) || section.getAttribute( 'data-separator-vertical' ) || section.getAttribute( 'data-separator-notes' ) ) {
256 |
257 | section.outerHTML = slidify( getMarkdownFromSlide( section ), {
258 | separator: section.getAttribute( 'data-separator' ),
259 | verticalSeparator: section.getAttribute( 'data-separator-vertical' ),
260 | notesSeparator: section.getAttribute( 'data-separator-notes' ),
261 | attributes: getForwardedAttributes( section )
262 | });
263 |
264 | }
265 | else {
266 | section.innerHTML = createMarkdownSlide( getMarkdownFromSlide( section ) );
267 | }
268 | }
269 |
270 | }
271 |
272 | /**
273 | * Check if a node value has the attributes pattern.
274 | * If yes, extract it and add that value as one or several attributes
275 | * the the terget element.
276 | *
277 | * You need Cache Killer on Chrome to see the effect on any FOM transformation
278 | * directly on refresh (F5)
279 | * http://stackoverflow.com/questions/5690269/disabling-chrome-cache-for-website-development/7000899#answer-11786277
280 | */
281 | function addAttributeInElement( node, elementTarget, separator ) {
282 |
283 | var mardownClassesInElementsRegex = new RegExp( separator, 'mg' );
284 | var mardownClassRegex = new RegExp( "([^\"= ]+?)=\"([^\"=]+?)\"", 'mg' );
285 | var nodeValue = node.nodeValue;
286 | if( matches = mardownClassesInElementsRegex.exec( nodeValue ) ) {
287 |
288 | var classes = matches[1];
289 | nodeValue = nodeValue.substring( 0, matches.index ) + nodeValue.substring( mardownClassesInElementsRegex.lastIndex );
290 | node.nodeValue = nodeValue;
291 | while( matchesClass = mardownClassRegex.exec( classes ) ) {
292 | elementTarget.setAttribute( matchesClass[1], matchesClass[2] );
293 | }
294 | return true;
295 | }
296 | return false;
297 | }
298 |
299 | /**
300 | * Add attributes to the parent element of a text node,
301 | * or the element of an attribute node.
302 | */
303 | function addAttributes( section, element, previousElement, separatorElementAttributes, separatorSectionAttributes ) {
304 |
305 | if ( element != null && element.childNodes != undefined && element.childNodes.length > 0 ) {
306 | previousParentElement = element;
307 | for( var i = 0; i < element.childNodes.length; i++ ) {
308 | childElement = element.childNodes[i];
309 | if ( i > 0 ) {
310 | j = i - 1;
311 | while ( j >= 0 ) {
312 | aPreviousChildElement = element.childNodes[j];
313 | if ( typeof aPreviousChildElement.setAttribute == 'function' && aPreviousChildElement.tagName != "BR" ) {
314 | previousParentElement = aPreviousChildElement;
315 | break;
316 | }
317 | j = j - 1;
318 | }
319 | }
320 | parentSection = section;
321 | if( childElement.nodeName == "section" ) {
322 | parentSection = childElement ;
323 | previousParentElement = childElement ;
324 | }
325 | if ( typeof childElement.setAttribute == 'function' || childElement.nodeType == Node.COMMENT_NODE ) {
326 | addAttributes( parentSection, childElement, previousParentElement, separatorElementAttributes, separatorSectionAttributes );
327 | }
328 | }
329 | }
330 |
331 | if ( element.nodeType == Node.COMMENT_NODE ) {
332 | if ( addAttributeInElement( element, previousElement, separatorElementAttributes ) == false ) {
333 | addAttributeInElement( element, section, separatorSectionAttributes );
334 | }
335 | }
336 | }
337 |
338 | /**
339 | * Converts any current data-markdown slides in the
340 | * DOM to HTML.
341 | */
342 | function convertSlides() {
343 |
344 | var sections = document.querySelectorAll( '[data-markdown]');
345 |
346 | for( var i = 0, len = sections.length; i < len; i++ ) {
347 |
348 | var section = sections[i];
349 |
350 | // Only parse the same slide once
351 | if( !section.getAttribute( 'data-markdown-parsed' ) ) {
352 |
353 | section.setAttribute( 'data-markdown-parsed', true )
354 |
355 | var notes = section.querySelector( 'aside.notes' );
356 | var markdown = getMarkdownFromSlide( section );
357 |
358 | section.innerHTML = marked( markdown );
359 | addAttributes( section, section, null, section.getAttribute( 'data-element-attributes' ) ||
360 | section.parentNode.getAttribute( 'data-element-attributes' ) ||
361 | DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR,
362 | section.getAttribute( 'data-attributes' ) ||
363 | section.parentNode.getAttribute( 'data-attributes' ) ||
364 | DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR);
365 |
366 | // If there were notes, we need to re-add them after
367 | // having overwritten the section's HTML
368 | if( notes ) {
369 | section.appendChild( notes );
370 | }
371 |
372 | }
373 |
374 | }
375 |
376 | }
377 |
378 | // API
379 | return {
380 |
381 | initialize: function() {
382 | processSlides();
383 | convertSlides();
384 | },
385 |
386 | // TODO: Do these belong in the API?
387 | processSlides: processSlides,
388 | convertSlides: convertSlides,
389 | slidify: slidify
390 |
391 | };
392 |
393 | }));
394 |
--------------------------------------------------------------------------------
/instructors/slides/static/plugin/markdown/marked.js:
--------------------------------------------------------------------------------
1 | /**
2 | * marked - a markdown parser
3 | * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)
4 | * https://github.com/chjj/marked
5 | */
6 |
7 | (function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){3,} *\n*/,blockquote:/^( *>[^\n]+(\n[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,def:/^ *\[([^\]]+)\]: *([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
8 | 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+(?=(?: *[-*_]){3,} *(?:\n+|$))/)();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+(?!:/|@)\\b";block.html=replace(block.html)("comment",/\x3c!--[\s\S]*?--\x3e/)("closed",
9 | /<(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:/^/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1",
10 | "\\2")+"|")();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)};
11 | 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){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,
12 | "");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,
13 | "").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i ?/gm,"");this.token(cap,top);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);
15 | 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+
16 | 1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item[item.length-1]==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false);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:cap[1]==="pre"||cap[1]==="script",text:cap[0]});continue}if(top&&
17 | (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:/^\x3c!--[\s\S]*?--\x3e|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
20 | 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)\*\*(?!\*)/,
21 | 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;
22 | 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);
23 | out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1][6]===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=''+text+" ";continue}if(cap=this.rules.url.exec(src)){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=''+text+" ";continue}if(cap=this.rules.tag.exec(src)){src=src.substring(cap[0].length);
24 | out+=this.options.sanitize?escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);out+=this.outputLink(cap,{href:cap[2],title:cap[3]});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][0];src=cap[0].substring(1)+src;continue}out+=this.outputLink(cap,link);continue}if(cap=this.rules.strong.exec(src)){src=
25 | src.substring(cap[0].length);out+=""+this.output(cap[2]||cap[1])+" ";continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=""+this.output(cap[2]||cap[1])+" ";continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=""+escape(cap[2],true)+"
";continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+=" ";continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=""+
26 | this.output(cap[1])+"";continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=escape(cap[0]);continue}if(src)throw new Error("Infinite loop on byte: "+src.charCodeAt(0));}return out};InlineLexer.prototype.outputLink=function(cap,link){if(cap[0][0]!=="!")return'"+this.output(cap[1])+" ";else return' "};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/--/g,"\u2014").replace(/'([^']*)'/g,"\u2018$1\u2019").replace(/"([^"]*)"/g,"\u201c$1\u201d").replace(/\.{3}/g,"\u2026")};InlineLexer.prototype.mangle=function(text){var out="",l=text.length,i=0,ch;for(;i0.5)ch="x"+ch.toString(16);out+=""+ch+";"}return out};function Parser(options){this.tokens=[];this.token=null;
28 | this.options=options||marked.defaults}Parser.parse=function(src,options){var parser=new Parser(options);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options);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;
29 | 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" \n";case "heading":return""+this.inline.output(this.token.text)+" \n";case "code":if(this.options.highlight){var code=this.options.highlight(this.token.text,this.token.lang);if(code!=null&&code!==this.token.text){this.token.escaped=true;this.token.text=code}}if(!this.token.escaped)this.token.text=
30 | escape(this.token.text,true);return""+this.token.text+"
\n";case "table":var body="",heading,i,row,cell,j;body+="\n\n";for(i=0;i'+heading+"\n":""+heading+" \n"}body+=" \n \n";body+="\n";for(i=0;i\n";for(j=0;j'+cell+"\n":""+cell+" \n"}body+="\n"}body+=" \n";return"\n";case "blockquote_start":var body="";while(this.next().type!=="blockquote_end")body+=this.tok();return"\n"+body+" \n";case "list_start":var type=this.token.ordered?"ol":"ul",body="";while(this.next().type!=="list_end")body+=
32 | this.tok();return"<"+type+">\n"+body+""+type+">\n";case "list_item_start":var body="";while(this.next().type!=="list_item_end")body+=this.token.type==="text"?this.parseText():this.tok();return""+body+" \n";case "loose_item_start":var body="";while(this.next().type!=="list_item_end")body+=this.tok();return""+body+" \n";case "html":return!this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;case "paragraph":return""+this.inline.output(this.token.text)+
33 | "
\n";case "text":return""+this.parseText()+"
\n"}};function escape(html,encode){return html.replace(!encode?/&(?!#?\w+;)/g:/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}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=
34 | 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,smartLists:false,silent:false,highlight:null,langPrefix:""};marked.Parser=Parser;marked.parser=Parser.parse;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;
37 | marked.parse=marked;if(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)}());
38 |
--------------------------------------------------------------------------------
/instructors/slides/static/plugin/notes/notes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | reveal.js - Slide Notes
7 |
8 |
151 |
152 |
153 |
154 |
155 |
156 | UPCOMING:
157 |
158 |
159 |
Time Click to Reset
160 |
161 | 0:00 AM
162 |
163 |
164 | 00 :00 :00
165 |
166 |
167 |
168 |
169 |
173 |
174 |
175 |
176 |
405 |
406 |
407 |
--------------------------------------------------------------------------------
/instructors/slides/static/plugin/notes/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() {
15 | var jsFileLocation = document.querySelector('script[src$="notes.js"]').src; // this js file path
16 | jsFileLocation = jsFileLocation.replace(/notes\.js(\?.*)?$/, ''); // the js folder path
17 | var notesPopup = window.open( jsFileLocation + 'notes.html', 'reveal.js - Notes', 'width=1100,height=700' );
18 |
19 | /**
20 | * Connect to the notes window through a postmessage handshake.
21 | * Using postmessage enables us to work in situations where the
22 | * origins differ, such as a presentation being opened from the
23 | * file system.
24 | */
25 | function connect() {
26 | // Keep trying to connect until we get a 'connected' message back
27 | var connectInterval = setInterval( function() {
28 | notesPopup.postMessage( JSON.stringify( {
29 | namespace: 'reveal-notes',
30 | type: 'connect',
31 | url: window.location.protocol + '//' + window.location.host + window.location.pathname,
32 | state: Reveal.getState()
33 | } ), '*' );
34 | }, 500 );
35 |
36 | window.addEventListener( 'message', function( event ) {
37 | var data = JSON.parse( event.data );
38 | if( data && data.namespace === 'reveal-notes' && data.type === 'connected' ) {
39 | clearInterval( connectInterval );
40 | onConnected();
41 | }
42 | } );
43 | }
44 |
45 | /**
46 | * Posts the current slide data to the notes window
47 | */
48 | function post() {
49 |
50 | var slideElement = Reveal.getCurrentSlide(),
51 | notesElement = slideElement.querySelector( 'aside.notes' );
52 |
53 | var messageData = {
54 | namespace: 'reveal-notes',
55 | type: 'state',
56 | notes: '',
57 | markdown: false,
58 | state: Reveal.getState()
59 | };
60 |
61 | // Look for notes defined in a slide attribute
62 | if( slideElement.hasAttribute( 'data-notes' ) ) {
63 | messageData.notes = slideElement.getAttribute( 'data-notes' );
64 | }
65 |
66 | // Look for notes defined in an aside element
67 | if( notesElement ) {
68 | messageData.notes = notesElement.innerHTML;
69 | messageData.markdown = typeof notesElement.getAttribute( 'data-markdown' ) === 'string';
70 | }
71 |
72 | notesPopup.postMessage( JSON.stringify( messageData ), '*' );
73 |
74 | }
75 |
76 | /**
77 | * Called once we have established a connection to the notes
78 | * window.
79 | */
80 | function onConnected() {
81 |
82 | // Monitor events that trigger a change in state
83 | Reveal.addEventListener( 'slidechanged', post );
84 | Reveal.addEventListener( 'fragmentshown', post );
85 | Reveal.addEventListener( 'fragmenthidden', post );
86 | Reveal.addEventListener( 'overviewhidden', post );
87 | Reveal.addEventListener( 'overviewshown', post );
88 | Reveal.addEventListener( 'paused', post );
89 | Reveal.addEventListener( 'resumed', post );
90 |
91 | // Post the initial state
92 | post();
93 |
94 | }
95 |
96 | connect();
97 | }
98 |
99 | if( !/receiver/i.test( window.location.search ) ) {
100 |
101 | // If the there's a 'notes' query set, open directly
102 | if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) {
103 | openNotes();
104 | }
105 |
106 | // Open the notes when the 's' key is hit
107 | document.addEventListener( 'keydown', function( event ) {
108 | // Disregard the event if the target is editable or a
109 | // modifier is present
110 | if ( document.querySelector( ':focus' ) !== null || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ) return;
111 |
112 | if( event.keyCode === 83 ) {
113 | event.preventDefault();
114 | openNotes();
115 | }
116 | }, false );
117 |
118 | }
119 |
120 | return { open: openNotes };
121 |
122 | })();
123 |
--------------------------------------------------------------------------------
/instructors/slides/static/plugin/zoom-js/zoom.js:
--------------------------------------------------------------------------------
1 | // Custom reveal.js integration
2 | (function(){
3 | var isEnabled = true;
4 |
5 | document.querySelector( '.reveal' ).addEventListener( 'mousedown', function( event ) {
6 | var modifier = ( Reveal.getConfig().zoomKey ? Reveal.getConfig().zoomKey : 'alt' ) + 'Key';
7 |
8 | var zoomPadding = 20;
9 | var revealScale = Reveal.getScale();
10 |
11 | if( event[ modifier ] && isEnabled ) {
12 | event.preventDefault();
13 |
14 | var bounds = event.target.getBoundingClientRect();
15 |
16 | zoom.to({
17 | x: ( bounds.left * revealScale ) - zoomPadding,
18 | y: ( bounds.top * revealScale ) - zoomPadding,
19 | width: ( bounds.width * revealScale ) + ( zoomPadding * 2 ),
20 | height: ( bounds.height * revealScale ) + ( zoomPadding * 2 ),
21 | pan: false
22 | });
23 | }
24 | } );
25 |
26 | Reveal.addEventListener( 'overviewshown', function() { isEnabled = false; } );
27 | Reveal.addEventListener( 'overviewhidden', function() { isEnabled = true; } );
28 | })();
29 |
30 | /*!
31 | * zoom.js 0.3 (modified for use with reveal.js)
32 | * http://lab.hakim.se/zoom-js
33 | * MIT licensed
34 | *
35 | * Copyright (C) 2011-2014 Hakim El Hattab, http://hakim.se
36 | */
37 | var zoom = (function(){
38 |
39 | // The current zoom level (scale)
40 | var level = 1;
41 |
42 | // The current mouse position, used for panning
43 | var mouseX = 0,
44 | mouseY = 0;
45 |
46 | // Timeout before pan is activated
47 | var panEngageTimeout = -1,
48 | panUpdateInterval = -1;
49 |
50 | // Check for transform support so that we can fallback otherwise
51 | var supportsTransforms = 'WebkitTransform' in document.body.style ||
52 | 'MozTransform' in document.body.style ||
53 | 'msTransform' in document.body.style ||
54 | 'OTransform' in document.body.style ||
55 | 'transform' in document.body.style;
56 |
57 | if( supportsTransforms ) {
58 | // The easing that will be applied when we zoom in/out
59 | document.body.style.transition = 'transform 0.8s ease';
60 | document.body.style.OTransition = '-o-transform 0.8s ease';
61 | document.body.style.msTransition = '-ms-transform 0.8s ease';
62 | document.body.style.MozTransition = '-moz-transform 0.8s ease';
63 | document.body.style.WebkitTransition = '-webkit-transform 0.8s ease';
64 | }
65 |
66 | // Zoom out if the user hits escape
67 | document.addEventListener( 'keyup', function( event ) {
68 | if( level !== 1 && event.keyCode === 27 ) {
69 | zoom.out();
70 | }
71 | } );
72 |
73 | // Monitor mouse movement for panning
74 | document.addEventListener( 'mousemove', function( event ) {
75 | if( level !== 1 ) {
76 | mouseX = event.clientX;
77 | mouseY = event.clientY;
78 | }
79 | } );
80 |
81 | /**
82 | * Applies the CSS required to zoom in, prefers the use of CSS3
83 | * transforms but falls back on zoom for IE.
84 | *
85 | * @param {Object} rect
86 | * @param {Number} scale
87 | */
88 | function magnify( rect, scale ) {
89 |
90 | var scrollOffset = getScrollOffset();
91 |
92 | // Ensure a width/height is set
93 | rect.width = rect.width || 1;
94 | rect.height = rect.height || 1;
95 |
96 | // Center the rect within the zoomed viewport
97 | rect.x -= ( window.innerWidth - ( rect.width * scale ) ) / 2;
98 | rect.y -= ( window.innerHeight - ( rect.height * scale ) ) / 2;
99 |
100 | if( supportsTransforms ) {
101 | // Reset
102 | if( scale === 1 ) {
103 | document.body.style.transform = '';
104 | document.body.style.OTransform = '';
105 | document.body.style.msTransform = '';
106 | document.body.style.MozTransform = '';
107 | document.body.style.WebkitTransform = '';
108 | }
109 | // Scale
110 | else {
111 | var origin = scrollOffset.x +'px '+ scrollOffset.y +'px',
112 | transform = 'translate('+ -rect.x +'px,'+ -rect.y +'px) scale('+ scale +')';
113 |
114 | document.body.style.transformOrigin = origin;
115 | document.body.style.OTransformOrigin = origin;
116 | document.body.style.msTransformOrigin = origin;
117 | document.body.style.MozTransformOrigin = origin;
118 | document.body.style.WebkitTransformOrigin = origin;
119 |
120 | document.body.style.transform = transform;
121 | document.body.style.OTransform = transform;
122 | document.body.style.msTransform = transform;
123 | document.body.style.MozTransform = transform;
124 | document.body.style.WebkitTransform = transform;
125 | }
126 | }
127 | else {
128 | // Reset
129 | if( scale === 1 ) {
130 | document.body.style.position = '';
131 | document.body.style.left = '';
132 | document.body.style.top = '';
133 | document.body.style.width = '';
134 | document.body.style.height = '';
135 | document.body.style.zoom = '';
136 | }
137 | // Scale
138 | else {
139 | document.body.style.position = 'relative';
140 | document.body.style.left = ( - ( scrollOffset.x + rect.x ) / scale ) + 'px';
141 | document.body.style.top = ( - ( scrollOffset.y + rect.y ) / scale ) + 'px';
142 | document.body.style.width = ( scale * 100 ) + '%';
143 | document.body.style.height = ( scale * 100 ) + '%';
144 | document.body.style.zoom = scale;
145 | }
146 | }
147 |
148 | level = scale;
149 |
150 | if( document.documentElement.classList ) {
151 | if( level !== 1 ) {
152 | document.documentElement.classList.add( 'zoomed' );
153 | }
154 | else {
155 | document.documentElement.classList.remove( 'zoomed' );
156 | }
157 | }
158 | }
159 |
160 | /**
161 | * Pan the document when the mosue cursor approaches the edges
162 | * of the window.
163 | */
164 | function pan() {
165 | var range = 0.12,
166 | rangeX = window.innerWidth * range,
167 | rangeY = window.innerHeight * range,
168 | scrollOffset = getScrollOffset();
169 |
170 | // Up
171 | if( mouseY < rangeY ) {
172 | window.scroll( scrollOffset.x, scrollOffset.y - ( 1 - ( mouseY / rangeY ) ) * ( 14 / level ) );
173 | }
174 | // Down
175 | else if( mouseY > window.innerHeight - rangeY ) {
176 | window.scroll( scrollOffset.x, scrollOffset.y + ( 1 - ( window.innerHeight - mouseY ) / rangeY ) * ( 14 / level ) );
177 | }
178 |
179 | // Left
180 | if( mouseX < rangeX ) {
181 | window.scroll( scrollOffset.x - ( 1 - ( mouseX / rangeX ) ) * ( 14 / level ), scrollOffset.y );
182 | }
183 | // Right
184 | else if( mouseX > window.innerWidth - rangeX ) {
185 | window.scroll( scrollOffset.x + ( 1 - ( window.innerWidth - mouseX ) / rangeX ) * ( 14 / level ), scrollOffset.y );
186 | }
187 | }
188 |
189 | function getScrollOffset() {
190 | return {
191 | x: window.scrollX !== undefined ? window.scrollX : window.pageXOffset,
192 | y: window.scrollY !== undefined ? window.scrollY : window.pageYOffset
193 | }
194 | }
195 |
196 | return {
197 | /**
198 | * Zooms in on either a rectangle or HTML element.
199 | *
200 | * @param {Object} options
201 | * - element: HTML element to zoom in on
202 | * OR
203 | * - x/y: coordinates in non-transformed space to zoom in on
204 | * - width/height: the portion of the screen to zoom in on
205 | * - scale: can be used instead of width/height to explicitly set scale
206 | */
207 | to: function( options ) {
208 |
209 | // Due to an implementation limitation we can't zoom in
210 | // to another element without zooming out first
211 | if( level !== 1 ) {
212 | zoom.out();
213 | }
214 | else {
215 | options.x = options.x || 0;
216 | options.y = options.y || 0;
217 |
218 | // If an element is set, that takes precedence
219 | if( !!options.element ) {
220 | // Space around the zoomed in element to leave on screen
221 | var padding = 20;
222 | var bounds = options.element.getBoundingClientRect();
223 |
224 | options.x = bounds.left - padding;
225 | options.y = bounds.top - padding;
226 | options.width = bounds.width + ( padding * 2 );
227 | options.height = bounds.height + ( padding * 2 );
228 | }
229 |
230 | // If width/height values are set, calculate scale from those values
231 | if( options.width !== undefined && options.height !== undefined ) {
232 | options.scale = Math.max( Math.min( window.innerWidth / options.width, window.innerHeight / options.height ), 1 );
233 | }
234 |
235 | if( options.scale > 1 ) {
236 | options.x *= options.scale;
237 | options.y *= options.scale;
238 |
239 | magnify( options, options.scale );
240 |
241 | if( options.pan !== false ) {
242 |
243 | // Wait with engaging panning as it may conflict with the
244 | // zoom transition
245 | panEngageTimeout = setTimeout( function() {
246 | panUpdateInterval = setInterval( pan, 1000 / 60 );
247 | }, 800 );
248 |
249 | }
250 | }
251 | }
252 | },
253 |
254 | /**
255 | * Resets the document zoom state to its default.
256 | */
257 | out: function() {
258 | clearTimeout( panEngageTimeout );
259 | clearInterval( panUpdateInterval );
260 |
261 | magnify( { x: 0, y: 0 }, 1 );
262 |
263 | level = 1;
264 | },
265 |
266 | // Alias
267 | magnify: function( options ) { this.to( options ) },
268 | reset: function() { this.out() },
269 |
270 | zoomLevel: function() {
271 | return level;
272 | }
273 | }
274 |
275 | })();
276 |
277 |
278 |
279 |
--------------------------------------------------------------------------------
/instructors/slides/static/slides.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | reveal.js - The HTML Presentation Framework
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
31 |
32 |
35 |
36 |
37 |
38 |
39 |
42 |
43 |
44 |
45 |
46 |
47 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | argparse
2 |
--------------------------------------------------------------------------------
/schedule/.gitignore:
--------------------------------------------------------------------------------
1 | # Emacs backup files
2 | *~
3 |
--------------------------------------------------------------------------------
/schedule/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
Schedule for tutorial
12 |
13 |
14 |
15 | 30 min: Lecture: A tour of attacks
16 | 15 min: Small group exercise, Google Dorking
17 | 15 min: Small group discussion, What's at risk?
18 | 30 min: Lab time, part 1
19 | 20 min: Break
20 | 60 min: Lab time, part 2
21 | 30 min: Lecture: Best practices & wrap-up
22 |
23 |
24 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/static/bootstrap-4.1.3-dist/css/.DS_Store:
--------------------------------------------------------------------------------
1 | Bud1 % @ � @ � @ � @ E % DSDB ` � @ � @ � @
--------------------------------------------------------------------------------
/static/bootstrap-4.1.3-dist/css/bootstrap-reboot.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Reboot v4.1.3 (https://getbootstrap.com/)
3 | * Copyright 2011-2018 The Bootstrap Authors
4 | * Copyright 2011-2018 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
7 | */
8 | *,
9 | *::before,
10 | *::after {
11 | box-sizing: border-box;
12 | }
13 |
14 | html {
15 | font-family: sans-serif;
16 | line-height: 1.15;
17 | -webkit-text-size-adjust: 100%;
18 | -ms-text-size-adjust: 100%;
19 | -ms-overflow-style: scrollbar;
20 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
21 | }
22 |
23 | @-ms-viewport {
24 | width: device-width;
25 | }
26 |
27 | article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
28 | display: block;
29 | }
30 |
31 | body {
32 | margin: 0;
33 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
34 | font-size: 1rem;
35 | font-weight: 400;
36 | line-height: 1.5;
37 | color: #212529;
38 | text-align: left;
39 | background-color: #fff;
40 | }
41 |
42 | [tabindex="-1"]:focus {
43 | outline: 0 !important;
44 | }
45 |
46 | hr {
47 | box-sizing: content-box;
48 | height: 0;
49 | overflow: visible;
50 | }
51 |
52 | h1, h2, h3, h4, h5, h6 {
53 | margin-top: 0;
54 | margin-bottom: 0.5rem;
55 | }
56 |
57 | p {
58 | margin-top: 0;
59 | margin-bottom: 1rem;
60 | }
61 |
62 | abbr[title],
63 | abbr[data-original-title] {
64 | text-decoration: underline;
65 | -webkit-text-decoration: underline dotted;
66 | text-decoration: underline dotted;
67 | cursor: help;
68 | border-bottom: 0;
69 | }
70 |
71 | address {
72 | margin-bottom: 1rem;
73 | font-style: normal;
74 | line-height: inherit;
75 | }
76 |
77 | ol,
78 | ul,
79 | dl {
80 | margin-top: 0;
81 | margin-bottom: 1rem;
82 | }
83 |
84 | ol ol,
85 | ul ul,
86 | ol ul,
87 | ul ol {
88 | margin-bottom: 0;
89 | }
90 |
91 | dt {
92 | font-weight: 700;
93 | }
94 |
95 | dd {
96 | margin-bottom: .5rem;
97 | margin-left: 0;
98 | }
99 |
100 | blockquote {
101 | margin: 0 0 1rem;
102 | }
103 |
104 | dfn {
105 | font-style: italic;
106 | }
107 |
108 | b,
109 | strong {
110 | font-weight: bolder;
111 | }
112 |
113 | small {
114 | font-size: 80%;
115 | }
116 |
117 | sub,
118 | sup {
119 | position: relative;
120 | font-size: 75%;
121 | line-height: 0;
122 | vertical-align: baseline;
123 | }
124 |
125 | sub {
126 | bottom: -.25em;
127 | }
128 |
129 | sup {
130 | top: -.5em;
131 | }
132 |
133 | a {
134 | color: #007bff;
135 | text-decoration: none;
136 | background-color: transparent;
137 | -webkit-text-decoration-skip: objects;
138 | }
139 |
140 | a:hover {
141 | color: #0056b3;
142 | text-decoration: underline;
143 | }
144 |
145 | a:not([href]):not([tabindex]) {
146 | color: inherit;
147 | text-decoration: none;
148 | }
149 |
150 | a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {
151 | color: inherit;
152 | text-decoration: none;
153 | }
154 |
155 | a:not([href]):not([tabindex]):focus {
156 | outline: 0;
157 | }
158 |
159 | pre,
160 | code,
161 | kbd,
162 | samp {
163 | font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
164 | font-size: 1em;
165 | }
166 |
167 | pre {
168 | margin-top: 0;
169 | margin-bottom: 1rem;
170 | overflow: auto;
171 | -ms-overflow-style: scrollbar;
172 | }
173 |
174 | figure {
175 | margin: 0 0 1rem;
176 | }
177 |
178 | img {
179 | vertical-align: middle;
180 | border-style: none;
181 | }
182 |
183 | svg {
184 | overflow: hidden;
185 | vertical-align: middle;
186 | }
187 |
188 | table {
189 | border-collapse: collapse;
190 | }
191 |
192 | caption {
193 | padding-top: 0.75rem;
194 | padding-bottom: 0.75rem;
195 | color: #6c757d;
196 | text-align: left;
197 | caption-side: bottom;
198 | }
199 |
200 | th {
201 | text-align: inherit;
202 | }
203 |
204 | label {
205 | display: inline-block;
206 | margin-bottom: 0.5rem;
207 | }
208 |
209 | button {
210 | border-radius: 0;
211 | }
212 |
213 | button:focus {
214 | outline: 1px dotted;
215 | outline: 5px auto -webkit-focus-ring-color;
216 | }
217 |
218 | input,
219 | button,
220 | select,
221 | optgroup,
222 | textarea {
223 | margin: 0;
224 | font-family: inherit;
225 | font-size: inherit;
226 | line-height: inherit;
227 | }
228 |
229 | button,
230 | input {
231 | overflow: visible;
232 | }
233 |
234 | button,
235 | select {
236 | text-transform: none;
237 | }
238 |
239 | button,
240 | html [type="button"],
241 | [type="reset"],
242 | [type="submit"] {
243 | -webkit-appearance: button;
244 | }
245 |
246 | button::-moz-focus-inner,
247 | [type="button"]::-moz-focus-inner,
248 | [type="reset"]::-moz-focus-inner,
249 | [type="submit"]::-moz-focus-inner {
250 | padding: 0;
251 | border-style: none;
252 | }
253 |
254 | input[type="radio"],
255 | input[type="checkbox"] {
256 | box-sizing: border-box;
257 | padding: 0;
258 | }
259 |
260 | input[type="date"],
261 | input[type="time"],
262 | input[type="datetime-local"],
263 | input[type="month"] {
264 | -webkit-appearance: listbox;
265 | }
266 |
267 | textarea {
268 | overflow: auto;
269 | resize: vertical;
270 | }
271 |
272 | fieldset {
273 | min-width: 0;
274 | padding: 0;
275 | margin: 0;
276 | border: 0;
277 | }
278 |
279 | legend {
280 | display: block;
281 | width: 100%;
282 | max-width: 100%;
283 | padding: 0;
284 | margin-bottom: .5rem;
285 | font-size: 1.5rem;
286 | line-height: inherit;
287 | color: inherit;
288 | white-space: normal;
289 | }
290 |
291 | progress {
292 | vertical-align: baseline;
293 | }
294 |
295 | [type="number"]::-webkit-inner-spin-button,
296 | [type="number"]::-webkit-outer-spin-button {
297 | height: auto;
298 | }
299 |
300 | [type="search"] {
301 | outline-offset: -2px;
302 | -webkit-appearance: none;
303 | }
304 |
305 | [type="search"]::-webkit-search-cancel-button,
306 | [type="search"]::-webkit-search-decoration {
307 | -webkit-appearance: none;
308 | }
309 |
310 | ::-webkit-file-upload-button {
311 | font: inherit;
312 | -webkit-appearance: button;
313 | }
314 |
315 | output {
316 | display: inline-block;
317 | }
318 |
319 | summary {
320 | display: list-item;
321 | cursor: pointer;
322 | }
323 |
324 | template {
325 | display: none;
326 | }
327 |
328 | [hidden] {
329 | display: none !important;
330 | }
331 | /*# sourceMappingURL=bootstrap-reboot.css.map */
--------------------------------------------------------------------------------
/static/bootstrap-4.1.3-dist/css/bootstrap-reboot.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Reboot v4.1.3 (https://getbootstrap.com/)
3 | * Copyright 2011-2018 The Bootstrap Authors
4 | * Copyright 2011-2018 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
7 | */*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}@-ms-viewport{width:device-width}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
8 | /*# sourceMappingURL=bootstrap-reboot.min.css.map */
--------------------------------------------------------------------------------
/static/images/IMG_9232.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/django-security-tutorials/hands-on-web-security-slides/471b4c53d7e1b64a0ebc5f7af1dc054a665c4bdc/static/images/IMG_9232.jpg
--------------------------------------------------------------------------------
/static/pets.css:
--------------------------------------------------------------------------------
1 | body {
2 | background: #ffe9dc;
3 | }
4 |
5 | h1 {
6 | text-transform: lowercase;
7 | font-weight: 100;
8 | font-size: 48px;
9 | }
--------------------------------------------------------------------------------
/student-handout/static/css/print/paper.css:
--------------------------------------------------------------------------------
1 | /* Default Print Stylesheet Template
2 | by Rob Glazebrook of CSSnewbie.com
3 | Last Updated: June 4, 2008
4 |
5 | Feel free (nay, compelled) to edit, append, and
6 | manipulate this file as you see fit. */
7 |
8 |
9 | @media print {
10 |
11 | /* SECTION 1: Set default width, margin, float, and
12 | background. This prevents elements from extending
13 | beyond the edge of the printed page, and prevents
14 | unnecessary background images from printing */
15 | html {
16 | background: #fff;
17 | width: auto;
18 | height: auto;
19 | overflow: visible;
20 | }
21 | body {
22 | background: #fff;
23 | font-size: 20pt;
24 | width: auto;
25 | height: auto;
26 | border: 0;
27 | margin: 0 5%;
28 | padding: 0;
29 | overflow: visible;
30 | float: none !important;
31 | }
32 |
33 | /* SECTION 2: Remove any elements not needed in print.
34 | This would include navigation, ads, sidebars, etc. */
35 | .nestedarrow,
36 | .controls,
37 | .fork-reveal,
38 | .share-reveal,
39 | .state-background,
40 | .reveal .progress,
41 | .reveal .backgrounds {
42 | display: none !important;
43 | }
44 |
45 | /* SECTION 3: Set body font face, size, and color.
46 | Consider using a serif font for readability. */
47 | body, p, td, li, div {
48 | font-size: 20pt!important;
49 | font-family: Georgia, "Times New Roman", Times, serif !important;
50 | color: #000;
51 | }
52 |
53 | /* SECTION 4: Set heading font face, sizes, and color.
54 | Differentiate your headings from your body text.
55 | Perhaps use a large sans-serif for distinction. */
56 | h1,h2,h3,h4,h5,h6 {
57 | color: #000!important;
58 | height: auto;
59 | line-height: normal;
60 | font-family: Georgia, "Times New Roman", Times, serif !important;
61 | text-shadow: 0 0 0 #000 !important;
62 | text-align: left;
63 | letter-spacing: normal;
64 | }
65 | /* Need to reduce the size of the fonts for printing */
66 | h1 { font-size: 28pt !important; }
67 | h2 { font-size: 24pt !important; }
68 | h3 { font-size: 22pt !important; }
69 | h4 { font-size: 22pt !important; font-variant: small-caps; }
70 | h5 { font-size: 21pt !important; }
71 | h6 { font-size: 20pt !important; font-style: italic; }
72 |
73 | /* SECTION 5: Make hyperlinks more usable.
74 | Ensure links are underlined, and consider appending
75 | the URL to the end of the link for usability. */
76 | a:link,
77 | a:visited {
78 | color: #000 !important;
79 | font-weight: bold;
80 | text-decoration: underline;
81 | }
82 | /*
83 | .reveal a:link:after,
84 | .reveal a:visited:after {
85 | content: " (" attr(href) ") ";
86 | color: #222 !important;
87 | font-size: 90%;
88 | }
89 | */
90 |
91 |
92 | /* SECTION 6: more reveal.js specific additions by @skypanther */
93 | ul, ol, div, p {
94 | visibility: visible;
95 | position: static;
96 | width: auto;
97 | height: auto;
98 | display: block;
99 | overflow: visible;
100 | margin: 0;
101 | text-align: left !important;
102 | }
103 | .reveal pre,
104 | .reveal table {
105 | margin-left: 0;
106 | margin-right: 0;
107 | }
108 | .reveal pre code {
109 | padding: 20px;
110 | border: 1px solid #ddd;
111 | }
112 | .reveal blockquote {
113 | margin: 20px 0;
114 | }
115 | .reveal .slides {
116 | position: static !important;
117 | width: auto !important;
118 | height: auto !important;
119 |
120 | left: 0 !important;
121 | top: 0 !important;
122 | margin-left: 0 !important;
123 | margin-top: 0 !important;
124 | padding: 0 !important;
125 | zoom: 1 !important;
126 |
127 | overflow: visible !important;
128 | display: block !important;
129 |
130 | text-align: left !important;
131 | -webkit-perspective: none;
132 | -moz-perspective: none;
133 | -ms-perspective: none;
134 | perspective: none;
135 |
136 | -webkit-perspective-origin: 50% 50%;
137 | -moz-perspective-origin: 50% 50%;
138 | -ms-perspective-origin: 50% 50%;
139 | perspective-origin: 50% 50%;
140 | }
141 | .reveal .slides section {
142 | visibility: visible !important;
143 | position: static !important;
144 | width: 100% !important;
145 | height: auto !important;
146 | display: block !important;
147 | overflow: visible !important;
148 |
149 | left: 0 !important;
150 | top: 0 !important;
151 | margin-left: 0 !important;
152 | margin-top: 0 !important;
153 | padding: 60px 20px !important;
154 | z-index: auto !important;
155 |
156 | opacity: 1 !important;
157 |
158 | page-break-after: always !important;
159 |
160 | -webkit-transform-style: flat !important;
161 | -moz-transform-style: flat !important;
162 | -ms-transform-style: flat !important;
163 | transform-style: flat !important;
164 |
165 | -webkit-transform: none !important;
166 | -moz-transform: none !important;
167 | -ms-transform: none !important;
168 | transform: none !important;
169 |
170 | -webkit-transition: none !important;
171 | -moz-transition: none !important;
172 | -ms-transition: none !important;
173 | transition: none !important;
174 | }
175 | .reveal .slides section.stack {
176 | padding: 0 !important;
177 | }
178 | .reveal section:last-of-type {
179 | page-break-after: avoid !important;
180 | }
181 | .reveal section .fragment {
182 | opacity: 1 !important;
183 | visibility: visible !important;
184 |
185 | -webkit-transform: none !important;
186 | -moz-transform: none !important;
187 | -ms-transform: none !important;
188 | transform: none !important;
189 | }
190 | .reveal section img {
191 | display: block;
192 | margin: 15px 0px;
193 | background: rgba(255,255,255,1);
194 | border: 1px solid #666;
195 | box-shadow: none;
196 | }
197 |
198 | .reveal section small {
199 | font-size: 0.8em;
200 | }
201 |
202 | }
--------------------------------------------------------------------------------
/student-handout/static/css/theme/black.css:
--------------------------------------------------------------------------------
1 | @import url(../../lib/font/source-sans-pro/source-sans-pro.css);
2 | /**
3 | * Black theme for reveal.js. This is the opposite of the 'white' theme.
4 | *
5 | * Copyright (C) 2015 Hakim El Hattab, http://hakim.se
6 | */
7 | section.has-light-background, section.has-light-background h1, section.has-light-background h2, section.has-light-background h3, section.has-light-background h4, section.has-light-background h5, section.has-light-background h6 {
8 | color: #222; }
9 |
10 | /*********************************************
11 | * GLOBAL STYLES
12 | *********************************************/
13 | body {
14 | background: #222;
15 | background-color: #222; }
16 |
17 | .reveal {
18 | font-family: 'Source Sans Pro', Helvetica, sans-serif;
19 | font-size: 38px;
20 | font-weight: normal;
21 | color: #fff; }
22 |
23 | ::selection {
24 | color: #fff;
25 | background: #bee4fd;
26 | text-shadow: none; }
27 |
28 | .reveal .slides > section, .reveal .slides > section > section {
29 | line-height: 1.3;
30 | font-weight: inherit; }
31 |
32 | /*********************************************
33 | * HEADERS
34 | *********************************************/
35 | .reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 {
36 | margin: 0 0 20px 0;
37 | color: #fff;
38 | font-family: 'Source Sans Pro', Helvetica, sans-serif;
39 | font-weight: 600;
40 | line-height: 1.2;
41 | letter-spacing: normal;
42 | text-transform: uppercase;
43 | text-shadow: none;
44 | word-wrap: break-word; }
45 |
46 | .reveal h1 {
47 | font-size: 2.5em; }
48 |
49 | .reveal h2 {
50 | font-size: 1.6em; }
51 |
52 | .reveal h3 {
53 | font-size: 1.3em; }
54 |
55 | .reveal h4 {
56 | font-size: 1em; }
57 |
58 | .reveal h1 {
59 | text-shadow: none; }
60 |
61 | /*********************************************
62 | * OTHER
63 | *********************************************/
64 | .reveal p {
65 | margin: 20px 0;
66 | line-height: 1.3; }
67 |
68 | /* Ensure certain elements are never larger than the slide itself */
69 | .reveal img, .reveal video, .reveal iframe {
70 | max-width: 95%;
71 | max-height: 95%; }
72 |
73 | .reveal strong, .reveal b {
74 | font-weight: bold; }
75 |
76 | .reveal em {
77 | font-style: italic; }
78 |
79 | .reveal ol, .reveal dl, .reveal ul {
80 | display: inline-block;
81 | text-align: left;
82 | margin: 0 0 0 1em; }
83 |
84 | .reveal ol {
85 | list-style-type: decimal; }
86 |
87 | .reveal ul {
88 | list-style-type: disc; }
89 |
90 | .reveal ul ul {
91 | list-style-type: square; }
92 |
93 | .reveal ul ul ul {
94 | list-style-type: circle; }
95 |
96 | .reveal ul ul, .reveal ul ol, .reveal ol ol, .reveal ol ul {
97 | display: block;
98 | margin-left: 40px; }
99 |
100 | .reveal dt {
101 | font-weight: bold; }
102 |
103 | .reveal dd {
104 | margin-left: 40px; }
105 |
106 | .reveal q, .reveal blockquote {
107 | quotes: none; }
108 |
109 | .reveal blockquote {
110 | display: block;
111 | position: relative;
112 | width: 70%;
113 | margin: 20px auto;
114 | padding: 5px;
115 | font-style: italic;
116 | background: rgba(255, 255, 255, 0.05);
117 | box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); }
118 |
119 | .reveal blockquote p:first-child, .reveal blockquote p:last-child {
120 | display: inline-block; }
121 |
122 | .reveal q {
123 | font-style: italic; }
124 |
125 | .reveal pre {
126 | display: block;
127 | position: relative;
128 | width: 90%;
129 | margin: 20px auto;
130 | text-align: left;
131 | font-size: 0.55em;
132 | font-family: monospace;
133 | line-height: 1.2em;
134 | word-wrap: break-word;
135 | box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); }
136 |
137 | .reveal code {
138 | font-family: monospace; }
139 |
140 | .reveal pre code {
141 | display: block;
142 | padding: 5px;
143 | overflow: auto;
144 | max-height: 400px;
145 | word-wrap: normal;
146 | background: #3F3F3F;
147 | color: #DCDCDC; }
148 |
149 | .reveal table {
150 | margin: auto;
151 | border-collapse: collapse;
152 | border-spacing: 0; }
153 |
154 | .reveal table th {
155 | font-weight: bold; }
156 |
157 | .reveal table th, .reveal table td {
158 | text-align: left;
159 | padding: 0.2em 0.5em 0.2em 0.5em;
160 | border-bottom: 1px solid; }
161 |
162 | .reveal table tr:last-child td {
163 | border-bottom: none; }
164 |
165 | .reveal sup {
166 | vertical-align: super; }
167 |
168 | .reveal sub {
169 | vertical-align: sub; }
170 |
171 | .reveal small {
172 | display: inline-block;
173 | font-size: 0.6em;
174 | line-height: 1.2em;
175 | vertical-align: top; }
176 |
177 | .reveal small * {
178 | vertical-align: top; }
179 |
180 | /*********************************************
181 | * LINKS
182 | *********************************************/
183 | .reveal a {
184 | color: #42affa;
185 | text-decoration: none;
186 | -webkit-transition: color 0.15s ease;
187 | -moz-transition: color 0.15s ease;
188 | transition: color 0.15s ease; }
189 |
190 | .reveal a:hover {
191 | color: #8dcffc;
192 | text-shadow: none;
193 | border: none; }
194 |
195 | .reveal .roll span:after {
196 | color: #fff;
197 | background: #068ee9; }
198 |
199 | /*********************************************
200 | * IMAGES
201 | *********************************************/
202 | .reveal section img {
203 | margin: 15px 0px;
204 | background: rgba(255, 255, 255, 0.12);
205 | border: 4px solid #fff;
206 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); }
207 |
208 | .reveal a img {
209 | -webkit-transition: all 0.15s linear;
210 | -moz-transition: all 0.15s linear;
211 | transition: all 0.15s linear; }
212 |
213 | .reveal a:hover img {
214 | background: rgba(255, 255, 255, 0.2);
215 | border-color: #42affa;
216 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); }
217 |
218 | /*********************************************
219 | * NAVIGATION CONTROLS
220 | *********************************************/
221 | .reveal .controls div.navigate-left, .reveal .controls div.navigate-left.enabled {
222 | border-right-color: #42affa; }
223 |
224 | .reveal .controls div.navigate-right, .reveal .controls div.navigate-right.enabled {
225 | border-left-color: #42affa; }
226 |
227 | .reveal .controls div.navigate-up, .reveal .controls div.navigate-up.enabled {
228 | border-bottom-color: #42affa; }
229 |
230 | .reveal .controls div.navigate-down, .reveal .controls div.navigate-down.enabled {
231 | border-top-color: #42affa; }
232 |
233 | .reveal .controls div.navigate-left.enabled:hover {
234 | border-right-color: #8dcffc; }
235 |
236 | .reveal .controls div.navigate-right.enabled:hover {
237 | border-left-color: #8dcffc; }
238 |
239 | .reveal .controls div.navigate-up.enabled:hover {
240 | border-bottom-color: #8dcffc; }
241 |
242 | .reveal .controls div.navigate-down.enabled:hover {
243 | border-top-color: #8dcffc; }
244 |
245 | /*********************************************
246 | * PROGRESS BAR
247 | *********************************************/
248 | .reveal .progress {
249 | background: rgba(0, 0, 0, 0.2); }
250 |
251 | .reveal .progress span {
252 | background: #42affa;
253 | -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
254 | -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
255 | transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
256 |
257 | /*********************************************
258 | * SLIDE NUMBER
259 | *********************************************/
260 | .reveal .slide-number {
261 | color: #42affa; }
262 |
--------------------------------------------------------------------------------
/student-handout/static/css/theme/simple.css:
--------------------------------------------------------------------------------
1 | @import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700);
2 | @import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
3 | /**
4 | * A simple theme for reveal.js presentations, similar
5 | * to the default theme. The accent color is darkblue.
6 | *
7 | * This theme is Copyright (C) 2012 Owen Versteeg, https://github.com/StereotypicalApps. It is MIT licensed.
8 | * reveal.js is Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
9 | */
10 | /*********************************************
11 | * GLOBAL STYLES
12 | *********************************************/
13 | body {
14 | background: #fff;
15 | background-color: #fff; }
16 |
17 | .reveal {
18 | font-family: 'Lato', sans-serif;
19 | font-size: 36px;
20 | font-weight: normal;
21 | color: #000; }
22 |
23 | ::selection {
24 | color: #fff;
25 | background: rgba(0, 0, 0, 0.99);
26 | text-shadow: none; }
27 |
28 | .reveal .slides > section, .reveal .slides > section > section {
29 | line-height: 1.3;
30 | font-weight: inherit; }
31 |
32 | /*********************************************
33 | * HEADERS
34 | *********************************************/
35 | .reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 {
36 | margin: 0 0 20px 0;
37 | color: #000;
38 | font-family: 'News Cycle', Impact, sans-serif;
39 | font-weight: normal;
40 | line-height: 1.2;
41 | letter-spacing: normal;
42 | text-transform: none;
43 | text-shadow: none;
44 | word-wrap: break-word; }
45 |
46 | .reveal h1 {
47 | font-size: 3.77em; }
48 |
49 | .reveal h2 {
50 | font-size: 2em; }
51 |
52 | .reveal h3 {
53 | font-size: 1.55em; }
54 |
55 | .reveal h4 {
56 | font-size: 1em; }
57 |
58 | .reveal h1 {
59 | text-shadow: none; }
60 |
61 | /*********************************************
62 | * OTHER
63 | *********************************************/
64 | .reveal p {
65 | margin: 20px 0;
66 | line-height: 1.3; }
67 |
68 | /* Ensure certain elements are never larger than the slide itself */
69 | .reveal img, .reveal video, .reveal iframe {
70 | max-width: 95%;
71 | max-height: 95%; }
72 |
73 | .reveal strong, .reveal b {
74 | font-weight: bold; }
75 |
76 | .reveal em {
77 | font-style: italic; }
78 |
79 | .reveal ol, .reveal dl, .reveal ul {
80 | display: inline-block;
81 | text-align: left;
82 | margin: 0 0 0 1em; }
83 |
84 | .reveal ol {
85 | list-style-type: decimal; }
86 |
87 | .reveal ul {
88 | list-style-type: disc; }
89 |
90 | .reveal ul ul {
91 | list-style-type: square; }
92 |
93 | .reveal ul ul ul {
94 | list-style-type: circle; }
95 |
96 | .reveal ul ul, .reveal ul ol, .reveal ol ol, .reveal ol ul {
97 | display: block;
98 | margin-left: 40px; }
99 |
100 | .reveal dt {
101 | font-weight: bold; }
102 |
103 | .reveal dd {
104 | margin-left: 40px; }
105 |
106 | .reveal q, .reveal blockquote {
107 | quotes: none; }
108 |
109 | .reveal blockquote {
110 | display: block;
111 | position: relative;
112 | width: 70%;
113 | margin: 20px auto;
114 | padding: 5px;
115 | font-style: italic;
116 | background: rgba(255, 255, 255, 0.05);
117 | box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2); }
118 |
119 | .reveal blockquote p:first-child, .reveal blockquote p:last-child {
120 | display: inline-block; }
121 |
122 | .reveal q {
123 | font-style: italic; }
124 |
125 | .reveal pre {
126 | display: block;
127 | position: relative;
128 | width: 90%;
129 | margin: 20px auto;
130 | text-align: left;
131 | font-size: 0.55em;
132 | font-family: monospace;
133 | line-height: 1.2em;
134 | word-wrap: break-word;
135 | box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); }
136 |
137 | .reveal code {
138 | font-family: monospace; }
139 |
140 | .reveal pre code {
141 | display: block;
142 | padding: 5px;
143 | overflow: auto;
144 | max-height: 400px;
145 | word-wrap: normal;
146 | background: #3F3F3F;
147 | color: #DCDCDC; }
148 |
149 | .reveal table {
150 | margin: auto;
151 | border-collapse: collapse;
152 | border-spacing: 0; }
153 |
154 | .reveal table th {
155 | font-weight: bold; }
156 |
157 | .reveal table th, .reveal table td {
158 | text-align: left;
159 | padding: 0.2em 0.5em 0.2em 0.5em;
160 | border-bottom: 1px solid; }
161 |
162 | .reveal table tr:last-child td {
163 | border-bottom: none; }
164 |
165 | .reveal sup {
166 | vertical-align: super; }
167 |
168 | .reveal sub {
169 | vertical-align: sub; }
170 |
171 | .reveal small {
172 | display: inline-block;
173 | font-size: 0.6em;
174 | line-height: 1.2em;
175 | vertical-align: top; }
176 |
177 | .reveal small * {
178 | vertical-align: top; }
179 |
180 | /*********************************************
181 | * LINKS
182 | *********************************************/
183 | .reveal a {
184 | color: #00008B;
185 | text-decoration: none;
186 | -webkit-transition: color 0.15s ease;
187 | -moz-transition: color 0.15s ease;
188 | transition: color 0.15s ease; }
189 |
190 | .reveal a:hover {
191 | color: #0000f1;
192 | text-shadow: none;
193 | border: none; }
194 |
195 | .reveal .roll span:after {
196 | color: #fff;
197 | background: #00003f; }
198 |
199 | /*********************************************
200 | * IMAGES
201 | *********************************************/
202 | .reveal section img {
203 | margin: 15px 0px;
204 | background: rgba(255, 255, 255, 0.12);
205 | border: 4px solid #000;
206 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); }
207 |
208 | .reveal a img {
209 | -webkit-transition: all 0.15s linear;
210 | -moz-transition: all 0.15s linear;
211 | transition: all 0.15s linear; }
212 |
213 | .reveal a:hover img {
214 | background: rgba(255, 255, 255, 0.2);
215 | border-color: #00008B;
216 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); }
217 |
218 | /*********************************************
219 | * NAVIGATION CONTROLS
220 | *********************************************/
221 | .reveal .controls div.navigate-left, .reveal .controls div.navigate-left.enabled {
222 | border-right-color: #00008B; }
223 |
224 | .reveal .controls div.navigate-right, .reveal .controls div.navigate-right.enabled {
225 | border-left-color: #00008B; }
226 |
227 | .reveal .controls div.navigate-up, .reveal .controls div.navigate-up.enabled {
228 | border-bottom-color: #00008B; }
229 |
230 | .reveal .controls div.navigate-down, .reveal .controls div.navigate-down.enabled {
231 | border-top-color: #00008B; }
232 |
233 | .reveal .controls div.navigate-left.enabled:hover {
234 | border-right-color: #0000f1; }
235 |
236 | .reveal .controls div.navigate-right.enabled:hover {
237 | border-left-color: #0000f1; }
238 |
239 | .reveal .controls div.navigate-up.enabled:hover {
240 | border-bottom-color: #0000f1; }
241 |
242 | .reveal .controls div.navigate-down.enabled:hover {
243 | border-top-color: #0000f1; }
244 |
245 | /*********************************************
246 | * PROGRESS BAR
247 | *********************************************/
248 | .reveal .progress {
249 | background: rgba(0, 0, 0, 0.2); }
250 |
251 | .reveal .progress span {
252 | background: #00008B;
253 | -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
254 | -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
255 | transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
256 |
257 | /*********************************************
258 | * SLIDE NUMBER
259 | *********************************************/
260 | .reveal .slide-number {
261 | color: #00008B; }
262 |
--------------------------------------------------------------------------------
/student-handout/static/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; padding: 0.5em;
10 | background: #3F3F3F;
11 | color: #DCDCDC;
12 | }
13 |
14 | .hljs-keyword,
15 | .hljs-tag,
16 | .css .hljs-class,
17 | .css .hljs-id,
18 | .lisp .hljs-title,
19 | .nginx .hljs-title,
20 | .hljs-request,
21 | .hljs-status,
22 | .clojure .hljs-attribute {
23 | color: #E3CEAB;
24 | }
25 |
26 | .django .hljs-template_tag,
27 | .django .hljs-variable,
28 | .django .hljs-filter .hljs-argument {
29 | color: #DCDCDC;
30 | }
31 |
32 | .hljs-number,
33 | .hljs-date {
34 | color: #8CD0D3;
35 | }
36 |
37 | .dos .hljs-envvar,
38 | .dos .hljs-stream,
39 | .hljs-variable,
40 | .apache .hljs-sqbracket {
41 | color: #EFDCBC;
42 | }
43 |
44 | .dos .hljs-flow,
45 | .diff .hljs-change,
46 | .python .exception,
47 | .python .hljs-built_in,
48 | .hljs-literal,
49 | .tex .hljs-special {
50 | color: #EFEFAF;
51 | }
52 |
53 | .diff .hljs-chunk,
54 | .hljs-subst {
55 | color: #8F8F8F;
56 | }
57 |
58 | .dos .hljs-keyword,
59 | .python .hljs-decorator,
60 | .hljs-title,
61 | .haskell .hljs-type,
62 | .diff .hljs-header,
63 | .ruby .hljs-class .hljs-parent,
64 | .apache .hljs-tag,
65 | .nginx .hljs-built_in,
66 | .tex .hljs-command,
67 | .hljs-prompt {
68 | color: #efef8f;
69 | }
70 |
71 | .dos .hljs-winutils,
72 | .ruby .hljs-symbol,
73 | .ruby .hljs-symbol .hljs-string,
74 | .ruby .hljs-string {
75 | color: #DCA3A3;
76 | }
77 |
78 | .diff .hljs-deletion,
79 | .hljs-string,
80 | .hljs-tag .hljs-value,
81 | .hljs-preprocessor,
82 | .hljs-pragma,
83 | .hljs-built_in,
84 | .sql .hljs-aggregate,
85 | .hljs-javadoc,
86 | .smalltalk .hljs-class,
87 | .smalltalk .hljs-localvars,
88 | .smalltalk .hljs-array,
89 | .css .hljs-rules .hljs-value,
90 | .hljs-attr_selector,
91 | .hljs-pseudo,
92 | .apache .hljs-cbracket,
93 | .tex .hljs-formula,
94 | .coffeescript .hljs-attribute {
95 | color: #CC9393;
96 | }
97 |
98 | .hljs-shebang,
99 | .diff .hljs-addition,
100 | .hljs-comment,
101 | .java .hljs-annotation,
102 | .hljs-template_comment,
103 | .hljs-pi,
104 | .hljs-doctype {
105 | color: #7F9F7F;
106 | }
107 |
108 | .coffeescript .javascript,
109 | .javascript .xml,
110 | .tex .hljs-formula,
111 | .xml .javascript,
112 | .xml .vbscript,
113 | .xml .css,
114 | .xml .hljs-cdata {
115 | opacity: 0.5;
116 | }
117 |
118 |
--------------------------------------------------------------------------------
/student-handout/static/lib/font/source-sans-pro/source-sans-pro-italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/django-security-tutorials/hands-on-web-security-slides/471b4c53d7e1b64a0ebc5f7af1dc054a665c4bdc/student-handout/static/lib/font/source-sans-pro/source-sans-pro-italic.woff
--------------------------------------------------------------------------------
/student-handout/static/lib/font/source-sans-pro/source-sans-pro-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/django-security-tutorials/hands-on-web-security-slides/471b4c53d7e1b64a0ebc5f7af1dc054a665c4bdc/student-handout/static/lib/font/source-sans-pro/source-sans-pro-regular.woff
--------------------------------------------------------------------------------
/student-handout/static/lib/font/source-sans-pro/source-sans-pro-semibold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/django-security-tutorials/hands-on-web-security-slides/471b4c53d7e1b64a0ebc5f7af1dc054a665c4bdc/student-handout/static/lib/font/source-sans-pro/source-sans-pro-semibold.woff
--------------------------------------------------------------------------------
/student-handout/static/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 | }
--------------------------------------------------------------------------------
/student-handout/static/lib/js/head.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | Head JS The only script in your
3 | Copyright Tero Piirainen (tipiirai)
4 | License MIT / http://bit.ly/mit-license
5 | Version 0.96
6 |
7 | http://headjs.com
8 | */(function(a){function z(){d||(d=!0,s(e,function(a){p(a)}))}function y(c,d){var e=a.createElement("script");e.type="text/"+(c.type||"javascript"),e.src=c.src||c,e.async=!1,e.onreadystatechange=e.onload=function(){var a=e.readyState;!d.done&&(!a||/loaded|complete/.test(a))&&(d.done=!0,d())},(a.body||b).appendChild(e)}function x(a,b){if(a.state==o)return b&&b();if(a.state==n)return k.ready(a.name,b);if(a.state==m)return a.onpreload.push(function(){x(a,b)});a.state=n,y(a.url,function(){a.state=o,b&&b(),s(g[a.name],function(a){p(a)}),u()&&d&&s(g.ALL,function(a){p(a)})})}function w(a,b){a.state===undefined&&(a.state=m,a.onpreload=[],y({src:a.url,type:"cache"},function(){v(a)}))}function v(a){a.state=l,s(a.onpreload,function(a){a.call()})}function u(a){a=a||h;var b;for(var c in a){if(a.hasOwnProperty(c)&&a[c].state!=o)return!1;b=!0}return b}function t(a){return Object.prototype.toString.call(a)=="[object Function]"}function s(a,b){if(!!a){typeof a=="object"&&(a=[].slice.call(a));for(var c=0;c 0 ) {
50 | text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' );
51 | }
52 | else if( leadingWs > 1 ) {
53 | text = text.replace( new RegExp('\\n? {' + leadingWs + '}'), '\n' );
54 | }
55 |
56 | return text;
57 |
58 | }
59 |
60 | /**
61 | * Given a markdown slide section element, this will
62 | * return all arguments that aren't related to markdown
63 | * parsing. Used to forward any other user-defined arguments
64 | * to the output markdown slide.
65 | */
66 | function getForwardedAttributes( section ) {
67 |
68 | var attributes = section.attributes;
69 | var result = [];
70 |
71 | for( var i = 0, len = attributes.length; i < len; i++ ) {
72 | var name = attributes[i].name,
73 | value = attributes[i].value;
74 |
75 | // disregard attributes that are used for markdown loading/parsing
76 | if( /data\-(markdown|separator|vertical|notes)/gi.test( name ) ) continue;
77 |
78 | if( value ) {
79 | result.push( name + '=' + value );
80 | }
81 | else {
82 | result.push( name );
83 | }
84 | }
85 |
86 | return result.join( ' ' );
87 |
88 | }
89 |
90 | /**
91 | * Inspects the given options and fills out default
92 | * values for what's not defined.
93 | */
94 | function getSlidifyOptions( options ) {
95 |
96 | options = options || {};
97 | options.separator = options.separator || DEFAULT_SLIDE_SEPARATOR;
98 | options.notesSeparator = options.notesSeparator || DEFAULT_NOTES_SEPARATOR;
99 | options.attributes = options.attributes || '';
100 |
101 | return options;
102 |
103 | }
104 |
105 | /**
106 | * Helper function for constructing a markdown slide.
107 | */
108 | function createMarkdownSlide( content, options ) {
109 |
110 | options = getSlidifyOptions( options );
111 |
112 | var notesMatch = content.split( new RegExp( options.notesSeparator, 'mgi' ) );
113 |
114 | if( notesMatch.length === 2 ) {
115 | content = notesMatch[0] + '' + notesMatch[1].trim() + ' ';
116 | }
117 |
118 | return '';
119 |
120 | }
121 |
122 | /**
123 | * Parses a data string into multiple slides based
124 | * on the passed in separator arguments.
125 | */
126 | function slidify( markdown, options ) {
127 |
128 | options = getSlidifyOptions( options );
129 |
130 | var separatorRegex = new RegExp( options.separator + ( options.verticalSeparator ? '|' + options.verticalSeparator : '' ), 'mg' ),
131 | horizontalSeparatorRegex = new RegExp( options.separator );
132 |
133 | var matches,
134 | lastIndex = 0,
135 | isHorizontal,
136 | wasHorizontal = true,
137 | content,
138 | sectionStack = [];
139 |
140 | // iterate until all blocks between separators are stacked up
141 | while( matches = separatorRegex.exec( markdown ) ) {
142 | notes = null;
143 |
144 | // determine direction (horizontal by default)
145 | isHorizontal = horizontalSeparatorRegex.test( matches[0] );
146 |
147 | if( !isHorizontal && wasHorizontal ) {
148 | // create vertical stack
149 | sectionStack.push( [] );
150 | }
151 |
152 | // pluck slide content from markdown input
153 | content = markdown.substring( lastIndex, matches.index );
154 |
155 | if( isHorizontal && wasHorizontal ) {
156 | // add to horizontal stack
157 | sectionStack.push( content );
158 | }
159 | else {
160 | // add to vertical stack
161 | sectionStack[sectionStack.length-1].push( content );
162 | }
163 |
164 | lastIndex = separatorRegex.lastIndex;
165 | wasHorizontal = isHorizontal;
166 | }
167 |
168 | // add the remaining slide
169 | ( wasHorizontal ? sectionStack : sectionStack[sectionStack.length-1] ).push( markdown.substring( lastIndex ) );
170 |
171 | var markdownSections = '';
172 |
173 | // flatten the hierarchical stack, and insert tags
174 | for( var i = 0, len = sectionStack.length; i < len; i++ ) {
175 | // vertical
176 | if( sectionStack[i] instanceof Array ) {
177 | markdownSections += '';
178 |
179 | sectionStack[i].forEach( function( child ) {
180 | markdownSections += '' + createMarkdownSlide( child, options ) + ' ';
181 | } );
182 |
183 | markdownSections += ' ';
184 | }
185 | else {
186 | markdownSections += '' + createMarkdownSlide( sectionStack[i], options ) + ' ';
187 | }
188 | }
189 |
190 | return markdownSections;
191 |
192 | }
193 |
194 | /**
195 | * Parses any current data-markdown slides, splits
196 | * multi-slide markdown into separate sections and
197 | * handles loading of external markdown.
198 | */
199 | function processSlides() {
200 |
201 | var sections = document.querySelectorAll( '[data-markdown]'),
202 | section;
203 |
204 | for( var i = 0, len = sections.length; i < len; i++ ) {
205 |
206 | section = sections[i];
207 |
208 | if( section.getAttribute( 'data-markdown' ).length ) {
209 |
210 | var xhr = new XMLHttpRequest(),
211 | url = section.getAttribute( 'data-markdown' );
212 |
213 | datacharset = section.getAttribute( 'data-charset' );
214 |
215 | // see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes
216 | if( datacharset != null && datacharset != '' ) {
217 | xhr.overrideMimeType( 'text/html; charset=' + datacharset );
218 | }
219 |
220 | xhr.onreadystatechange = function() {
221 | if( xhr.readyState === 4 ) {
222 | // file protocol yields status code 0 (useful for local debug, mobile applications etc.)
223 | if ( ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status === 0 ) {
224 |
225 | section.outerHTML = slidify( xhr.responseText, {
226 | separator: section.getAttribute( 'data-separator' ),
227 | verticalSeparator: section.getAttribute( 'data-separator-vertical' ),
228 | notesSeparator: section.getAttribute( 'data-separator-notes' ),
229 | attributes: getForwardedAttributes( section )
230 | });
231 |
232 | }
233 | else {
234 |
235 | section.outerHTML = '' +
236 | 'ERROR: The attempt to fetch ' + url + ' failed with HTTP status ' + xhr.status + '.' +
237 | 'Check your browser\'s JavaScript console for more details.' +
238 | 'Remember that you need to serve the presentation HTML from a HTTP server.
' +
239 | ' ';
240 |
241 | }
242 | }
243 | };
244 |
245 | xhr.open( 'GET', url, false );
246 |
247 | try {
248 | xhr.send();
249 | }
250 | catch ( e ) {
251 | 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 );
252 | }
253 |
254 | }
255 | else if( section.getAttribute( 'data-separator' ) || section.getAttribute( 'data-separator-vertical' ) || section.getAttribute( 'data-separator-notes' ) ) {
256 |
257 | section.outerHTML = slidify( getMarkdownFromSlide( section ), {
258 | separator: section.getAttribute( 'data-separator' ),
259 | verticalSeparator: section.getAttribute( 'data-separator-vertical' ),
260 | notesSeparator: section.getAttribute( 'data-separator-notes' ),
261 | attributes: getForwardedAttributes( section )
262 | });
263 |
264 | }
265 | else {
266 | section.innerHTML = createMarkdownSlide( getMarkdownFromSlide( section ) );
267 | }
268 | }
269 |
270 | }
271 |
272 | /**
273 | * Check if a node value has the attributes pattern.
274 | * If yes, extract it and add that value as one or several attributes
275 | * the the terget element.
276 | *
277 | * You need Cache Killer on Chrome to see the effect on any FOM transformation
278 | * directly on refresh (F5)
279 | * http://stackoverflow.com/questions/5690269/disabling-chrome-cache-for-website-development/7000899#answer-11786277
280 | */
281 | function addAttributeInElement( node, elementTarget, separator ) {
282 |
283 | var mardownClassesInElementsRegex = new RegExp( separator, 'mg' );
284 | var mardownClassRegex = new RegExp( "([^\"= ]+?)=\"([^\"=]+?)\"", 'mg' );
285 | var nodeValue = node.nodeValue;
286 | if( matches = mardownClassesInElementsRegex.exec( nodeValue ) ) {
287 |
288 | var classes = matches[1];
289 | nodeValue = nodeValue.substring( 0, matches.index ) + nodeValue.substring( mardownClassesInElementsRegex.lastIndex );
290 | node.nodeValue = nodeValue;
291 | while( matchesClass = mardownClassRegex.exec( classes ) ) {
292 | elementTarget.setAttribute( matchesClass[1], matchesClass[2] );
293 | }
294 | return true;
295 | }
296 | return false;
297 | }
298 |
299 | /**
300 | * Add attributes to the parent element of a text node,
301 | * or the element of an attribute node.
302 | */
303 | function addAttributes( section, element, previousElement, separatorElementAttributes, separatorSectionAttributes ) {
304 |
305 | if ( element != null && element.childNodes != undefined && element.childNodes.length > 0 ) {
306 | previousParentElement = element;
307 | for( var i = 0; i < element.childNodes.length; i++ ) {
308 | childElement = element.childNodes[i];
309 | if ( i > 0 ) {
310 | j = i - 1;
311 | while ( j >= 0 ) {
312 | aPreviousChildElement = element.childNodes[j];
313 | if ( typeof aPreviousChildElement.setAttribute == 'function' && aPreviousChildElement.tagName != "BR" ) {
314 | previousParentElement = aPreviousChildElement;
315 | break;
316 | }
317 | j = j - 1;
318 | }
319 | }
320 | parentSection = section;
321 | if( childElement.nodeName == "section" ) {
322 | parentSection = childElement ;
323 | previousParentElement = childElement ;
324 | }
325 | if ( typeof childElement.setAttribute == 'function' || childElement.nodeType == Node.COMMENT_NODE ) {
326 | addAttributes( parentSection, childElement, previousParentElement, separatorElementAttributes, separatorSectionAttributes );
327 | }
328 | }
329 | }
330 |
331 | if ( element.nodeType == Node.COMMENT_NODE ) {
332 | if ( addAttributeInElement( element, previousElement, separatorElementAttributes ) == false ) {
333 | addAttributeInElement( element, section, separatorSectionAttributes );
334 | }
335 | }
336 | }
337 |
338 | /**
339 | * Converts any current data-markdown slides in the
340 | * DOM to HTML.
341 | */
342 | function convertSlides() {
343 |
344 | var sections = document.querySelectorAll( '[data-markdown]');
345 |
346 | for( var i = 0, len = sections.length; i < len; i++ ) {
347 |
348 | var section = sections[i];
349 |
350 | // Only parse the same slide once
351 | if( !section.getAttribute( 'data-markdown-parsed' ) ) {
352 |
353 | section.setAttribute( 'data-markdown-parsed', true )
354 |
355 | var notes = section.querySelector( 'aside.notes' );
356 | var markdown = getMarkdownFromSlide( section );
357 |
358 | section.innerHTML = marked( markdown );
359 | addAttributes( section, section, null, section.getAttribute( 'data-element-attributes' ) ||
360 | section.parentNode.getAttribute( 'data-element-attributes' ) ||
361 | DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR,
362 | section.getAttribute( 'data-attributes' ) ||
363 | section.parentNode.getAttribute( 'data-attributes' ) ||
364 | DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR);
365 |
366 | // If there were notes, we need to re-add them after
367 | // having overwritten the section's HTML
368 | if( notes ) {
369 | section.appendChild( notes );
370 | }
371 |
372 | }
373 |
374 | }
375 |
376 | }
377 |
378 | // API
379 | return {
380 |
381 | initialize: function() {
382 | processSlides();
383 | convertSlides();
384 | },
385 |
386 | // TODO: Do these belong in the API?
387 | processSlides: processSlides,
388 | convertSlides: convertSlides,
389 | slidify: slidify
390 |
391 | };
392 |
393 | }));
394 |
--------------------------------------------------------------------------------
/student-handout/static/plugin/markdown/marked.js:
--------------------------------------------------------------------------------
1 | /**
2 | * marked - a markdown parser
3 | * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)
4 | * https://github.com/chjj/marked
5 | */
6 |
7 | (function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){3,} *\n*/,blockquote:/^( *>[^\n]+(\n[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,def:/^ *\[([^\]]+)\]: *([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
8 | 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+(?=(?: *[-*_]){3,} *(?:\n+|$))/)();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+(?!:/|@)\\b";block.html=replace(block.html)("comment",/\x3c!--[\s\S]*?--\x3e/)("closed",
9 | /<(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:/^/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1",
10 | "\\2")+"|")();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)};
11 | 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){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,
12 | "");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,
13 | "").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i ?/gm,"");this.token(cap,top);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);
15 | 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+
16 | 1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item[item.length-1]==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false);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:cap[1]==="pre"||cap[1]==="script",text:cap[0]});continue}if(top&&
17 | (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:/^\x3c!--[\s\S]*?--\x3e|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
20 | 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)\*\*(?!\*)/,
21 | 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;
22 | 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);
23 | out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1][6]===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=''+text+" ";continue}if(cap=this.rules.url.exec(src)){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=''+text+" ";continue}if(cap=this.rules.tag.exec(src)){src=src.substring(cap[0].length);
24 | out+=this.options.sanitize?escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);out+=this.outputLink(cap,{href:cap[2],title:cap[3]});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][0];src=cap[0].substring(1)+src;continue}out+=this.outputLink(cap,link);continue}if(cap=this.rules.strong.exec(src)){src=
25 | src.substring(cap[0].length);out+=""+this.output(cap[2]||cap[1])+" ";continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=""+this.output(cap[2]||cap[1])+" ";continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=""+escape(cap[2],true)+"
";continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+=" ";continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=""+
26 | this.output(cap[1])+"";continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=escape(cap[0]);continue}if(src)throw new Error("Infinite loop on byte: "+src.charCodeAt(0));}return out};InlineLexer.prototype.outputLink=function(cap,link){if(cap[0][0]!=="!")return'"+this.output(cap[1])+" ";else return' "};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/--/g,"\u2014").replace(/'([^']*)'/g,"\u2018$1\u2019").replace(/"([^"]*)"/g,"\u201c$1\u201d").replace(/\.{3}/g,"\u2026")};InlineLexer.prototype.mangle=function(text){var out="",l=text.length,i=0,ch;for(;i0.5)ch="x"+ch.toString(16);out+=""+ch+";"}return out};function Parser(options){this.tokens=[];this.token=null;
28 | this.options=options||marked.defaults}Parser.parse=function(src,options){var parser=new Parser(options);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options);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;
29 | 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" \n";case "heading":return""+this.inline.output(this.token.text)+" \n";case "code":if(this.options.highlight){var code=this.options.highlight(this.token.text,this.token.lang);if(code!=null&&code!==this.token.text){this.token.escaped=true;this.token.text=code}}if(!this.token.escaped)this.token.text=
30 | escape(this.token.text,true);return""+this.token.text+"
\n";case "table":var body="",heading,i,row,cell,j;body+="\n\n";for(i=0;i'+heading+"\n":""+heading+" \n"}body+=" \n \n";body+="\n";for(i=0;i\n";for(j=0;j'+cell+"\n":""+cell+" \n"}body+="\n"}body+=" \n";return"\n";case "blockquote_start":var body="";while(this.next().type!=="blockquote_end")body+=this.tok();return"\n"+body+" \n";case "list_start":var type=this.token.ordered?"ol":"ul",body="";while(this.next().type!=="list_end")body+=
32 | this.tok();return"<"+type+">\n"+body+""+type+">\n";case "list_item_start":var body="";while(this.next().type!=="list_item_end")body+=this.token.type==="text"?this.parseText():this.tok();return""+body+" \n";case "loose_item_start":var body="";while(this.next().type!=="list_item_end")body+=this.tok();return""+body+" \n";case "html":return!this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;case "paragraph":return""+this.inline.output(this.token.text)+
33 | "
\n";case "text":return""+this.parseText()+"
\n"}};function escape(html,encode){return html.replace(!encode?/&(?!#?\w+;)/g:/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}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=
34 | 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,smartLists:false,silent:false,highlight:null,langPrefix:""};marked.Parser=Parser;marked.parser=Parser.parse;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;
37 | marked.parse=marked;if(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)}());
38 |
--------------------------------------------------------------------------------
/student-handout/static/plugin/notes/notes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | reveal.js - Slide Notes
7 |
8 |
151 |
152 |
153 |
154 |
155 |
156 | UPCOMING:
157 |
158 |
159 |
Time Click to Reset
160 |
161 | 0:00 AM
162 |
163 |
164 | 00 :00 :00
165 |
166 |
167 |
168 |
169 |
173 |
174 |
175 |
176 |
405 |
406 |
407 |
--------------------------------------------------------------------------------
/student-handout/static/plugin/notes/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() {
15 | var jsFileLocation = document.querySelector('script[src$="notes.js"]').src; // this js file path
16 | jsFileLocation = jsFileLocation.replace(/notes\.js(\?.*)?$/, ''); // the js folder path
17 | var notesPopup = window.open( jsFileLocation + 'notes.html', 'reveal.js - Notes', 'width=1100,height=700' );
18 |
19 | /**
20 | * Connect to the notes window through a postmessage handshake.
21 | * Using postmessage enables us to work in situations where the
22 | * origins differ, such as a presentation being opened from the
23 | * file system.
24 | */
25 | function connect() {
26 | // Keep trying to connect until we get a 'connected' message back
27 | var connectInterval = setInterval( function() {
28 | notesPopup.postMessage( JSON.stringify( {
29 | namespace: 'reveal-notes',
30 | type: 'connect',
31 | url: window.location.protocol + '//' + window.location.host + window.location.pathname,
32 | state: Reveal.getState()
33 | } ), '*' );
34 | }, 500 );
35 |
36 | window.addEventListener( 'message', function( event ) {
37 | var data = JSON.parse( event.data );
38 | if( data && data.namespace === 'reveal-notes' && data.type === 'connected' ) {
39 | clearInterval( connectInterval );
40 | onConnected();
41 | }
42 | } );
43 | }
44 |
45 | /**
46 | * Posts the current slide data to the notes window
47 | */
48 | function post() {
49 |
50 | var slideElement = Reveal.getCurrentSlide(),
51 | notesElement = slideElement.querySelector( 'aside.notes' );
52 |
53 | var messageData = {
54 | namespace: 'reveal-notes',
55 | type: 'state',
56 | notes: '',
57 | markdown: false,
58 | state: Reveal.getState()
59 | };
60 |
61 | // Look for notes defined in a slide attribute
62 | if( slideElement.hasAttribute( 'data-notes' ) ) {
63 | messageData.notes = slideElement.getAttribute( 'data-notes' );
64 | }
65 |
66 | // Look for notes defined in an aside element
67 | if( notesElement ) {
68 | messageData.notes = notesElement.innerHTML;
69 | messageData.markdown = typeof notesElement.getAttribute( 'data-markdown' ) === 'string';
70 | }
71 |
72 | notesPopup.postMessage( JSON.stringify( messageData ), '*' );
73 |
74 | }
75 |
76 | /**
77 | * Called once we have established a connection to the notes
78 | * window.
79 | */
80 | function onConnected() {
81 |
82 | // Monitor events that trigger a change in state
83 | Reveal.addEventListener( 'slidechanged', post );
84 | Reveal.addEventListener( 'fragmentshown', post );
85 | Reveal.addEventListener( 'fragmenthidden', post );
86 | Reveal.addEventListener( 'overviewhidden', post );
87 | Reveal.addEventListener( 'overviewshown', post );
88 | Reveal.addEventListener( 'paused', post );
89 | Reveal.addEventListener( 'resumed', post );
90 |
91 | // Post the initial state
92 | post();
93 |
94 | }
95 |
96 | connect();
97 | }
98 |
99 | if( !/receiver/i.test( window.location.search ) ) {
100 |
101 | // If the there's a 'notes' query set, open directly
102 | if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) {
103 | openNotes();
104 | }
105 |
106 | // Open the notes when the 's' key is hit
107 | document.addEventListener( 'keydown', function( event ) {
108 | // Disregard the event if the target is editable or a
109 | // modifier is present
110 | if ( document.querySelector( ':focus' ) !== null || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ) return;
111 |
112 | if( event.keyCode === 83 ) {
113 | event.preventDefault();
114 | openNotes();
115 | }
116 | }, false );
117 |
118 | }
119 |
120 | return { open: openNotes };
121 |
122 | })();
123 |
--------------------------------------------------------------------------------
/student-handout/static/plugin/zoom-js/zoom.js:
--------------------------------------------------------------------------------
1 | // Custom reveal.js integration
2 | (function(){
3 | var isEnabled = true;
4 |
5 | document.querySelector( '.reveal' ).addEventListener( 'mousedown', function( event ) {
6 | var modifier = ( Reveal.getConfig().zoomKey ? Reveal.getConfig().zoomKey : 'alt' ) + 'Key';
7 |
8 | var zoomPadding = 20;
9 | var revealScale = Reveal.getScale();
10 |
11 | if( event[ modifier ] && isEnabled ) {
12 | event.preventDefault();
13 |
14 | var bounds = event.target.getBoundingClientRect();
15 |
16 | zoom.to({
17 | x: ( bounds.left * revealScale ) - zoomPadding,
18 | y: ( bounds.top * revealScale ) - zoomPadding,
19 | width: ( bounds.width * revealScale ) + ( zoomPadding * 2 ),
20 | height: ( bounds.height * revealScale ) + ( zoomPadding * 2 ),
21 | pan: false
22 | });
23 | }
24 | } );
25 |
26 | Reveal.addEventListener( 'overviewshown', function() { isEnabled = false; } );
27 | Reveal.addEventListener( 'overviewhidden', function() { isEnabled = true; } );
28 | })();
29 |
30 | /*!
31 | * zoom.js 0.3 (modified for use with reveal.js)
32 | * http://lab.hakim.se/zoom-js
33 | * MIT licensed
34 | *
35 | * Copyright (C) 2011-2014 Hakim El Hattab, http://hakim.se
36 | */
37 | var zoom = (function(){
38 |
39 | // The current zoom level (scale)
40 | var level = 1;
41 |
42 | // The current mouse position, used for panning
43 | var mouseX = 0,
44 | mouseY = 0;
45 |
46 | // Timeout before pan is activated
47 | var panEngageTimeout = -1,
48 | panUpdateInterval = -1;
49 |
50 | // Check for transform support so that we can fallback otherwise
51 | var supportsTransforms = 'WebkitTransform' in document.body.style ||
52 | 'MozTransform' in document.body.style ||
53 | 'msTransform' in document.body.style ||
54 | 'OTransform' in document.body.style ||
55 | 'transform' in document.body.style;
56 |
57 | if( supportsTransforms ) {
58 | // The easing that will be applied when we zoom in/out
59 | document.body.style.transition = 'transform 0.8s ease';
60 | document.body.style.OTransition = '-o-transform 0.8s ease';
61 | document.body.style.msTransition = '-ms-transform 0.8s ease';
62 | document.body.style.MozTransition = '-moz-transform 0.8s ease';
63 | document.body.style.WebkitTransition = '-webkit-transform 0.8s ease';
64 | }
65 |
66 | // Zoom out if the user hits escape
67 | document.addEventListener( 'keyup', function( event ) {
68 | if( level !== 1 && event.keyCode === 27 ) {
69 | zoom.out();
70 | }
71 | } );
72 |
73 | // Monitor mouse movement for panning
74 | document.addEventListener( 'mousemove', function( event ) {
75 | if( level !== 1 ) {
76 | mouseX = event.clientX;
77 | mouseY = event.clientY;
78 | }
79 | } );
80 |
81 | /**
82 | * Applies the CSS required to zoom in, prefers the use of CSS3
83 | * transforms but falls back on zoom for IE.
84 | *
85 | * @param {Object} rect
86 | * @param {Number} scale
87 | */
88 | function magnify( rect, scale ) {
89 |
90 | var scrollOffset = getScrollOffset();
91 |
92 | // Ensure a width/height is set
93 | rect.width = rect.width || 1;
94 | rect.height = rect.height || 1;
95 |
96 | // Center the rect within the zoomed viewport
97 | rect.x -= ( window.innerWidth - ( rect.width * scale ) ) / 2;
98 | rect.y -= ( window.innerHeight - ( rect.height * scale ) ) / 2;
99 |
100 | if( supportsTransforms ) {
101 | // Reset
102 | if( scale === 1 ) {
103 | document.body.style.transform = '';
104 | document.body.style.OTransform = '';
105 | document.body.style.msTransform = '';
106 | document.body.style.MozTransform = '';
107 | document.body.style.WebkitTransform = '';
108 | }
109 | // Scale
110 | else {
111 | var origin = scrollOffset.x +'px '+ scrollOffset.y +'px',
112 | transform = 'translate('+ -rect.x +'px,'+ -rect.y +'px) scale('+ scale +')';
113 |
114 | document.body.style.transformOrigin = origin;
115 | document.body.style.OTransformOrigin = origin;
116 | document.body.style.msTransformOrigin = origin;
117 | document.body.style.MozTransformOrigin = origin;
118 | document.body.style.WebkitTransformOrigin = origin;
119 |
120 | document.body.style.transform = transform;
121 | document.body.style.OTransform = transform;
122 | document.body.style.msTransform = transform;
123 | document.body.style.MozTransform = transform;
124 | document.body.style.WebkitTransform = transform;
125 | }
126 | }
127 | else {
128 | // Reset
129 | if( scale === 1 ) {
130 | document.body.style.position = '';
131 | document.body.style.left = '';
132 | document.body.style.top = '';
133 | document.body.style.width = '';
134 | document.body.style.height = '';
135 | document.body.style.zoom = '';
136 | }
137 | // Scale
138 | else {
139 | document.body.style.position = 'relative';
140 | document.body.style.left = ( - ( scrollOffset.x + rect.x ) / scale ) + 'px';
141 | document.body.style.top = ( - ( scrollOffset.y + rect.y ) / scale ) + 'px';
142 | document.body.style.width = ( scale * 100 ) + '%';
143 | document.body.style.height = ( scale * 100 ) + '%';
144 | document.body.style.zoom = scale;
145 | }
146 | }
147 |
148 | level = scale;
149 |
150 | if( document.documentElement.classList ) {
151 | if( level !== 1 ) {
152 | document.documentElement.classList.add( 'zoomed' );
153 | }
154 | else {
155 | document.documentElement.classList.remove( 'zoomed' );
156 | }
157 | }
158 | }
159 |
160 | /**
161 | * Pan the document when the mosue cursor approaches the edges
162 | * of the window.
163 | */
164 | function pan() {
165 | var range = 0.12,
166 | rangeX = window.innerWidth * range,
167 | rangeY = window.innerHeight * range,
168 | scrollOffset = getScrollOffset();
169 |
170 | // Up
171 | if( mouseY < rangeY ) {
172 | window.scroll( scrollOffset.x, scrollOffset.y - ( 1 - ( mouseY / rangeY ) ) * ( 14 / level ) );
173 | }
174 | // Down
175 | else if( mouseY > window.innerHeight - rangeY ) {
176 | window.scroll( scrollOffset.x, scrollOffset.y + ( 1 - ( window.innerHeight - mouseY ) / rangeY ) * ( 14 / level ) );
177 | }
178 |
179 | // Left
180 | if( mouseX < rangeX ) {
181 | window.scroll( scrollOffset.x - ( 1 - ( mouseX / rangeX ) ) * ( 14 / level ), scrollOffset.y );
182 | }
183 | // Right
184 | else if( mouseX > window.innerWidth - rangeX ) {
185 | window.scroll( scrollOffset.x + ( 1 - ( window.innerWidth - mouseX ) / rangeX ) * ( 14 / level ), scrollOffset.y );
186 | }
187 | }
188 |
189 | function getScrollOffset() {
190 | return {
191 | x: window.scrollX !== undefined ? window.scrollX : window.pageXOffset,
192 | y: window.scrollY !== undefined ? window.scrollY : window.pageYOffset
193 | }
194 | }
195 |
196 | return {
197 | /**
198 | * Zooms in on either a rectangle or HTML element.
199 | *
200 | * @param {Object} options
201 | * - element: HTML element to zoom in on
202 | * OR
203 | * - x/y: coordinates in non-transformed space to zoom in on
204 | * - width/height: the portion of the screen to zoom in on
205 | * - scale: can be used instead of width/height to explicitly set scale
206 | */
207 | to: function( options ) {
208 |
209 | // Due to an implementation limitation we can't zoom in
210 | // to another element without zooming out first
211 | if( level !== 1 ) {
212 | zoom.out();
213 | }
214 | else {
215 | options.x = options.x || 0;
216 | options.y = options.y || 0;
217 |
218 | // If an element is set, that takes precedence
219 | if( !!options.element ) {
220 | // Space around the zoomed in element to leave on screen
221 | var padding = 20;
222 | var bounds = options.element.getBoundingClientRect();
223 |
224 | options.x = bounds.left - padding;
225 | options.y = bounds.top - padding;
226 | options.width = bounds.width + ( padding * 2 );
227 | options.height = bounds.height + ( padding * 2 );
228 | }
229 |
230 | // If width/height values are set, calculate scale from those values
231 | if( options.width !== undefined && options.height !== undefined ) {
232 | options.scale = Math.max( Math.min( window.innerWidth / options.width, window.innerHeight / options.height ), 1 );
233 | }
234 |
235 | if( options.scale > 1 ) {
236 | options.x *= options.scale;
237 | options.y *= options.scale;
238 |
239 | magnify( options, options.scale );
240 |
241 | if( options.pan !== false ) {
242 |
243 | // Wait with engaging panning as it may conflict with the
244 | // zoom transition
245 | panEngageTimeout = setTimeout( function() {
246 | panUpdateInterval = setInterval( pan, 1000 / 60 );
247 | }, 800 );
248 |
249 | }
250 | }
251 | }
252 | },
253 |
254 | /**
255 | * Resets the document zoom state to its default.
256 | */
257 | out: function() {
258 | clearTimeout( panEngageTimeout );
259 | clearInterval( panUpdateInterval );
260 |
261 | magnify( { x: 0, y: 0 }, 1 );
262 |
263 | level = 1;
264 | },
265 |
266 | // Alias
267 | magnify: function( options ) { this.to( options ) },
268 | reset: function() { this.out() },
269 |
270 | zoomLevel: function() {
271 | return level;
272 | }
273 | }
274 |
275 | })();
276 |
277 |
278 |
279 |
--------------------------------------------------------------------------------
/student-handout/static/slides.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | reveal.js - The HTML Presentation Framework
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
31 |
32 |
35 |
36 |
37 |
38 |
39 |
42 |
43 |
44 |
45 |
46 |
47 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------