diff options
| -rw-r--r-- | README.md | 71 | ||||
| -rw-r--r-- | main.py | 53 | ||||
| -rw-r--r-- | static/favicon.png | bin | 0 -> 706 bytes | |||
| -rw-r--r-- | static/logo.png | bin | 0 -> 28922 bytes | |||
| -rw-r--r-- | static/normalize.css | 427 | ||||
| -rw-r--r-- | static/raleway.woff2 | bin | 0 -> 20332 bytes | |||
| -rw-r--r-- | static/skeleton.css | 418 | ||||
| -rw-r--r-- | static/style.css | 48 | ||||
| -rw-r--r-- | templates/base.html | 42 | ||||
| -rw-r--r-- | templates/download.html | 37 | ||||
| -rw-r--r-- | templates/index.html | 36 |
11 files changed, 1084 insertions, 48 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..79b9069 --- /dev/null +++ b/README.md | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | ``` | ||
| 2 | _ ___ _ | ||
| 3 | | | |__ \ | | | ||
| 4 | _ __ ___ __ _| |_ ) |_______ _____| |__ Trashing your meta, | ||
| 5 | | '_ ` _ \ / _` | __| / /______\ \ /\ / / _ \ '_ \ keeping your data, | ||
| 6 | | | | | | | (_| | |_ / /_ \ V V / __/ |_) | within your browser. | ||
| 7 | |_| |_| |_|\__,_|\__|____| \_/\_/ \___|_.__/ | ||
| 8 | ``` | ||
| 9 | |||
| 10 | This is an online version of [mat2](https://0xacab.org/jvoisin/mat2). | ||
| 11 | Keep in mind that this is a beta version, don't rely on it for anything | ||
| 12 | serious, yet. | ||
| 13 | |||
| 14 | # How to deploy it? | ||
| 15 | |||
| 16 | Since mat2 isn't available in debian stable yet, you might want to add this to | ||
| 17 | /etc/apt/preferences.d/ to be able to install `mat2` via apt. | ||
| 18 | |||
| 19 | ``` | ||
| 20 | Package: * | ||
| 21 | Pin: release o=Debian,a=unstable | ||
| 22 | Pin-Priority: 10 | ||
| 23 | ``` | ||
| 24 | |||
| 25 | Then: | ||
| 26 | |||
| 27 | ``` | ||
| 28 | # apt install git nginx-light uwsgi uwsgi-plugin-python3 mat2 --no-install-recommends | ||
| 29 | # cd /var/www/ | ||
| 30 | # git clone https://0xacab.org/jvoisin/mat2-web.git | ||
| 31 | # mkdir ./mat2-web/uploads/ | ||
| 32 | # chown -R www-data:www-data ./mat2-web | ||
| 33 | # service uwsgi start | ||
| 34 | # service nginx start | ||
| 35 | ``` | ||
| 36 | |||
| 37 | Since uwsgi isn't fun to configure, feel free to slap this into your | ||
| 38 | `/etc/uwsgi/apps-enabled/mat2-web.ini`: | ||
| 39 | |||
| 40 | ``` | ||
| 41 | [uwsgi] | ||
| 42 | module=main | ||
| 43 | chdir = /var/www/mat2-web/ | ||
| 44 | callable = app | ||
| 45 | wsgi-file = main.py | ||
| 46 | master = true | ||
| 47 | workers = 1 | ||
| 48 | |||
| 49 | uid = www-data | ||
| 50 | gid = www-data | ||
| 51 | |||
| 52 | # kill stalled processes | ||
| 53 | harakiri = 30 | ||
| 54 | die-on-term = true | ||
| 55 | |||
| 56 | socket = mat2-web.sock | ||
| 57 | chmod-socket = 774 | ||
| 58 | plugins = python3 | ||
| 59 | ``` | ||
| 60 | |||
| 61 | and this into your `/etc/nginx/site-enabled/mat2-web`: | ||
| 62 | |||
| 63 | ``` | ||
| 64 | location / { try_files $uri @yourapplication; } | ||
| 65 | location @yourapplication { | ||
| 66 | include uwsgi_params; | ||
| 67 | uwsgi_pass unix:/var/www/mat2-web/mat2-web.sock; | ||
| 68 | } | ||
| 69 | ``` | ||
| 70 | |||
| 71 | It should now be working. | ||
| @@ -8,14 +8,36 @@ from flask import send_from_directory, after_this_request | |||
| 8 | 8 | ||
| 9 | from werkzeug.utils import secure_filename | 9 | from werkzeug.utils import secure_filename |
| 10 | 10 | ||
| 11 | UPLOAD_FOLDER = './' | ||
| 12 | ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif']) | ||
| 13 | 11 | ||
| 14 | app = Flask(__name__) | 12 | app = Flask(__name__) |
| 15 | app.config['SECRET_KEY'] = '1337' | 13 | app.config['SECRET_KEY'] = os.urandom(32) |
| 16 | app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER | 14 | app.config['UPLOAD_FOLDER'] = './uploads/' |
| 17 | app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB | 15 | app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB |
| 18 | 16 | ||
| 17 | mimetypes = 'image/jpeg, image/png' | ||
| 18 | |||
| 19 | |||
| 20 | @app.route('/download/<string:filename>') | ||
| 21 | def download_file(filename:str): | ||
| 22 | if filename != secure_filename(filename): | ||
| 23 | flash('naughty naughty') | ||
| 24 | return redirect(url_for('upload_file')) | ||
| 25 | |||
| 26 | filepath = secure_filename(filename) | ||
| 27 | |||
| 28 | complete_path = os.path.join(app.config['UPLOAD_FOLDER'], filepath) | ||
| 29 | if not os.path.exists(complete_path): | ||
| 30 | return redirect(url_for('upload_file')) | ||
| 31 | |||
| 32 | @after_this_request | ||
| 33 | def remove_file(response): | ||
| 34 | os.remove(complete_path) | ||
| 35 | return response | ||
| 36 | return send_from_directory(app.config['UPLOAD_FOLDER'], filepath) | ||
| 37 | |||
| 38 | @app.route('/about') | ||
| 39 | def about(): | ||
| 40 | return render_template('about.html', mimetypes=mimetypes) | ||
| 19 | 41 | ||
| 20 | @app.route('/', methods=['GET', 'POST']) | 42 | @app.route('/', methods=['GET', 'POST']) |
| 21 | def upload_file(): | 43 | def upload_file(): |
| @@ -24,7 +46,7 @@ def upload_file(): | |||
| 24 | flash('No file part') | 46 | flash('No file part') |
| 25 | return redirect(request.url) | 47 | return redirect(request.url) |
| 26 | uploaded_file = request.files['file'] | 48 | uploaded_file = request.files['file'] |
| 27 | if uploaded_file.filename == '': | 49 | if not uploaded_file.filename: |
| 28 | flash('No selected file') | 50 | flash('No selected file') |
| 29 | return redirect(request.url) | 51 | return redirect(request.url) |
| 30 | filename = secure_filename(uploaded_file.filename) | 52 | filename = secure_filename(uploaded_file.filename) |
| @@ -35,20 +57,23 @@ def upload_file(): | |||
| 35 | if parser is None: | 57 | if parser is None: |
| 36 | flash('The type %s is not supported' % mime) | 58 | flash('The type %s is not supported' % mime) |
| 37 | return redirect(url_for('upload_file')) | 59 | return redirect(url_for('upload_file')) |
| 38 | elif parser.remove_all() is not True: | 60 | |
| 61 | meta = parser.get_meta() | ||
| 62 | |||
| 63 | if parser.remove_all() is not True: | ||
| 39 | flash('Unable to clean ' % mime) | 64 | flash('Unable to clean ' % mime) |
| 40 | return redirect(url_for('upload_file')) | 65 | return redirect(url_for('upload_file')) |
| 41 | os.remove(filename) | 66 | output_filename = os.path.basename(parser.output_filename) |
| 42 | 67 | ||
| 43 | @after_this_request | 68 | # Get metadata after cleanup |
| 44 | def remove_file(response): | 69 | parser, _ = parser_factory.get_parser(parser.output_filename) |
| 45 | os.remove(parser.output_filename) | 70 | meta_after = parser.get_meta() |
| 46 | return response | 71 | os.remove(filepath) |
| 47 | 72 | ||
| 48 | return send_from_directory(app.config['UPLOAD_FOLDER'], parser.output_filename) | 73 | return render_template('download.html', mimetypes=mimetypes, meta=meta, filename=output_filename, meta_after=meta_after) |
| 49 | 74 | ||
| 50 | mimetypes = 'image/jpeg, image/png' | ||
| 51 | return render_template('index.html', mimetypes=mimetypes) | 75 | return render_template('index.html', mimetypes=mimetypes) |
| 52 | 76 | ||
| 53 | 77 | ||
| 54 | app.run() | 78 | if __name__ == '__main__': |
| 79 | app.run() | ||
diff --git a/static/favicon.png b/static/favicon.png new file mode 100644 index 0000000..2b98f40 --- /dev/null +++ b/static/favicon.png | |||
| Binary files differ | |||
diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000..712cccf --- /dev/null +++ b/static/logo.png | |||
| Binary files differ | |||
diff --git a/static/normalize.css b/static/normalize.css new file mode 100644 index 0000000..81c6f31 --- /dev/null +++ b/static/normalize.css | |||
| @@ -0,0 +1,427 @@ | |||
| 1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */ | ||
| 2 | |||
| 3 | /** | ||
| 4 | * 1. Set default font family to sans-serif. | ||
| 5 | * 2. Prevent iOS text size adjust after orientation change, without disabling | ||
| 6 | * user zoom. | ||
| 7 | */ | ||
| 8 | |||
| 9 | html { | ||
| 10 | font-family: sans-serif; /* 1 */ | ||
| 11 | -ms-text-size-adjust: 100%; /* 2 */ | ||
| 12 | -webkit-text-size-adjust: 100%; /* 2 */ | ||
| 13 | } | ||
| 14 | |||
| 15 | /** | ||
| 16 | * Remove default margin. | ||
| 17 | */ | ||
| 18 | |||
| 19 | body { | ||
| 20 | margin: 0; | ||
| 21 | } | ||
| 22 | |||
| 23 | /* HTML5 display definitions | ||
| 24 | ========================================================================== */ | ||
| 25 | |||
| 26 | /** | ||
| 27 | * Correct `block` display not defined for any HTML5 element in IE 8/9. | ||
| 28 | * Correct `block` display not defined for `details` or `summary` in IE 10/11 | ||
| 29 | * and Firefox. | ||
| 30 | * Correct `block` display not defined for `main` in IE 11. | ||
| 31 | */ | ||
| 32 | |||
| 33 | article, | ||
| 34 | aside, | ||
| 35 | details, | ||
| 36 | figcaption, | ||
| 37 | figure, | ||
| 38 | footer, | ||
| 39 | header, | ||
| 40 | hgroup, | ||
| 41 | main, | ||
| 42 | menu, | ||
| 43 | nav, | ||
| 44 | section, | ||
| 45 | summary { | ||
| 46 | display: block; | ||
| 47 | } | ||
| 48 | |||
| 49 | /** | ||
| 50 | * 1. Correct `inline-block` display not defined in IE 8/9. | ||
| 51 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. | ||
| 52 | */ | ||
| 53 | |||
| 54 | audio, | ||
| 55 | canvas, | ||
| 56 | progress, | ||
| 57 | video { | ||
| 58 | display: inline-block; /* 1 */ | ||
| 59 | vertical-align: baseline; /* 2 */ | ||
| 60 | } | ||
| 61 | |||
| 62 | /** | ||
| 63 | * Prevent modern browsers from displaying `audio` without controls. | ||
| 64 | * Remove excess height in iOS 5 devices. | ||
| 65 | */ | ||
| 66 | |||
| 67 | audio:not([controls]) { | ||
| 68 | display: none; | ||
| 69 | height: 0; | ||
| 70 | } | ||
| 71 | |||
| 72 | /** | ||
| 73 | * Address `[hidden]` styling not present in IE 8/9/10. | ||
| 74 | * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. | ||
| 75 | */ | ||
| 76 | |||
| 77 | [hidden], | ||
| 78 | template { | ||
| 79 | display: none; | ||
| 80 | } | ||
| 81 | |||
| 82 | /* Links | ||
| 83 | ========================================================================== */ | ||
| 84 | |||
| 85 | /** | ||
| 86 | * Remove the gray background color from active links in IE 10. | ||
| 87 | */ | ||
| 88 | |||
| 89 | a { | ||
| 90 | background-color: transparent; | ||
| 91 | } | ||
| 92 | |||
| 93 | /** | ||
| 94 | * Improve readability when focused and also mouse hovered in all browsers. | ||
| 95 | */ | ||
| 96 | |||
| 97 | a:active, | ||
| 98 | a:hover { | ||
| 99 | outline: 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | /* Text-level semantics | ||
| 103 | ========================================================================== */ | ||
| 104 | |||
| 105 | /** | ||
| 106 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome. | ||
| 107 | */ | ||
| 108 | |||
| 109 | abbr[title] { | ||
| 110 | border-bottom: 1px dotted; | ||
| 111 | } | ||
| 112 | |||
| 113 | /** | ||
| 114 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. | ||
| 115 | */ | ||
| 116 | |||
| 117 | b, | ||
| 118 | strong { | ||
| 119 | font-weight: bold; | ||
| 120 | } | ||
| 121 | |||
| 122 | /** | ||
| 123 | * Address styling not present in Safari and Chrome. | ||
| 124 | */ | ||
| 125 | |||
| 126 | dfn { | ||
| 127 | font-style: italic; | ||
| 128 | } | ||
| 129 | |||
| 130 | /** | ||
| 131 | * Address variable `h1` font-size and margin within `section` and `article` | ||
| 132 | * contexts in Firefox 4+, Safari, and Chrome. | ||
| 133 | */ | ||
| 134 | |||
| 135 | h1 { | ||
| 136 | font-size: 2em; | ||
| 137 | margin: 0.67em 0; | ||
| 138 | } | ||
| 139 | |||
| 140 | /** | ||
| 141 | * Address styling not present in IE 8/9. | ||
| 142 | */ | ||
| 143 | |||
| 144 | mark { | ||
| 145 | background: #ff0; | ||
| 146 | color: #000; | ||
| 147 | } | ||
| 148 | |||
| 149 | /** | ||
| 150 | * Address inconsistent and variable font size in all browsers. | ||
| 151 | */ | ||
| 152 | |||
| 153 | small { | ||
| 154 | font-size: 80%; | ||
| 155 | } | ||
| 156 | |||
| 157 | /** | ||
| 158 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. | ||
| 159 | */ | ||
| 160 | |||
| 161 | sub, | ||
| 162 | sup { | ||
| 163 | font-size: 75%; | ||
| 164 | line-height: 0; | ||
| 165 | position: relative; | ||
| 166 | vertical-align: baseline; | ||
| 167 | } | ||
| 168 | |||
| 169 | sup { | ||
| 170 | top: -0.5em; | ||
| 171 | } | ||
| 172 | |||
| 173 | sub { | ||
| 174 | bottom: -0.25em; | ||
| 175 | } | ||
| 176 | |||
| 177 | /* Embedded content | ||
| 178 | ========================================================================== */ | ||
| 179 | |||
| 180 | /** | ||
| 181 | * Remove border when inside `a` element in IE 8/9/10. | ||
| 182 | */ | ||
| 183 | |||
| 184 | img { | ||
| 185 | border: 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | /** | ||
| 189 | * Correct overflow not hidden in IE 9/10/11. | ||
| 190 | */ | ||
| 191 | |||
| 192 | svg:not(:root) { | ||
| 193 | overflow: hidden; | ||
| 194 | } | ||
| 195 | |||
| 196 | /* Grouping content | ||
| 197 | ========================================================================== */ | ||
| 198 | |||
| 199 | /** | ||
| 200 | * Address margin not present in IE 8/9 and Safari. | ||
| 201 | */ | ||
| 202 | |||
| 203 | figure { | ||
| 204 | margin: 1em 40px; | ||
| 205 | } | ||
| 206 | |||
| 207 | /** | ||
| 208 | * Address differences between Firefox and other browsers. | ||
| 209 | */ | ||
| 210 | |||
| 211 | hr { | ||
| 212 | -moz-box-sizing: content-box; | ||
| 213 | box-sizing: content-box; | ||
| 214 | height: 0; | ||
| 215 | } | ||
| 216 | |||
| 217 | /** | ||
| 218 | * Contain overflow in all browsers. | ||
| 219 | */ | ||
| 220 | |||
| 221 | pre { | ||
| 222 | overflow: auto; | ||
| 223 | } | ||
| 224 | |||
| 225 | /** | ||
| 226 | * Address odd `em`-unit font size rendering in all browsers. | ||
| 227 | */ | ||
| 228 | |||
| 229 | code, | ||
| 230 | kbd, | ||
| 231 | pre, | ||
| 232 | samp { | ||
| 233 | font-family: monospace, monospace; | ||
| 234 | font-size: 1em; | ||
| 235 | } | ||
| 236 | |||
| 237 | /* Forms | ||
| 238 | ========================================================================== */ | ||
| 239 | |||
| 240 | /** | ||
| 241 | * Known limitation: by default, Chrome and Safari on OS X allow very limited | ||
| 242 | * styling of `select`, unless a `border` property is set. | ||
| 243 | */ | ||
| 244 | |||
| 245 | /** | ||
| 246 | * 1. Correct color not being inherited. | ||
| 247 | * Known issue: affects color of disabled elements. | ||
| 248 | * 2. Correct font properties not being inherited. | ||
| 249 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. | ||
| 250 | */ | ||
| 251 | |||
| 252 | button, | ||
| 253 | input, | ||
| 254 | optgroup, | ||
| 255 | select, | ||
| 256 | textarea { | ||
| 257 | color: inherit; /* 1 */ | ||
| 258 | font: inherit; /* 2 */ | ||
| 259 | margin: 0; /* 3 */ | ||
| 260 | } | ||
| 261 | |||
| 262 | /** | ||
| 263 | * Address `overflow` set to `hidden` in IE 8/9/10/11. | ||
| 264 | */ | ||
| 265 | |||
| 266 | button { | ||
| 267 | overflow: visible; | ||
| 268 | } | ||
| 269 | |||
| 270 | /** | ||
| 271 | * Address inconsistent `text-transform` inheritance for `button` and `select`. | ||
| 272 | * All other form control elements do not inherit `text-transform` values. | ||
| 273 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. | ||
| 274 | * Correct `select` style inheritance in Firefox. | ||
| 275 | */ | ||
| 276 | |||
| 277 | button, | ||
| 278 | select { | ||
| 279 | text-transform: none; | ||
| 280 | } | ||
| 281 | |||
| 282 | /** | ||
| 283 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` | ||
| 284 | * and `video` controls. | ||
| 285 | * 2. Correct inability to style clickable `input` types in iOS. | ||
| 286 | * 3. Improve usability and consistency of cursor style between image-type | ||
| 287 | * `input` and others. | ||
| 288 | */ | ||
| 289 | |||
| 290 | button, | ||
| 291 | html input[type="button"], /* 1 */ | ||
| 292 | input[type="reset"], | ||
| 293 | input[type="submit"] { | ||
| 294 | -webkit-appearance: button; /* 2 */ | ||
| 295 | cursor: pointer; /* 3 */ | ||
| 296 | } | ||
| 297 | |||
| 298 | /** | ||
| 299 | * Re-set default cursor for disabled elements. | ||
| 300 | */ | ||
| 301 | |||
| 302 | button[disabled], | ||
| 303 | html input[disabled] { | ||
| 304 | cursor: default; | ||
| 305 | } | ||
| 306 | |||
| 307 | /** | ||
| 308 | * Remove inner padding and border in Firefox 4+. | ||
| 309 | */ | ||
| 310 | |||
| 311 | button::-moz-focus-inner, | ||
| 312 | input::-moz-focus-inner { | ||
| 313 | border: 0; | ||
| 314 | padding: 0; | ||
| 315 | } | ||
| 316 | |||
| 317 | /** | ||
| 318 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in | ||
| 319 | * the UA stylesheet. | ||
| 320 | */ | ||
| 321 | |||
| 322 | input { | ||
| 323 | line-height: normal; | ||
| 324 | } | ||
| 325 | |||
| 326 | /** | ||
| 327 | * It's recommended that you don't attempt to style these elements. | ||
| 328 | * Firefox's implementation doesn't respect box-sizing, padding, or width. | ||
| 329 | * | ||
| 330 | * 1. Address box sizing set to `content-box` in IE 8/9/10. | ||
| 331 | * 2. Remove excess padding in IE 8/9/10. | ||
| 332 | */ | ||
| 333 | |||
| 334 | input[type="checkbox"], | ||
| 335 | input[type="radio"] { | ||
| 336 | box-sizing: border-box; /* 1 */ | ||
| 337 | padding: 0; /* 2 */ | ||
| 338 | } | ||
| 339 | |||
| 340 | /** | ||
| 341 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain | ||
| 342 | * `font-size` values of the `input`, it causes the cursor style of the | ||
| 343 | * decrement button to change from `default` to `text`. | ||
| 344 | */ | ||
| 345 | |||
| 346 | input[type="number"]::-webkit-inner-spin-button, | ||
| 347 | input[type="number"]::-webkit-outer-spin-button { | ||
| 348 | height: auto; | ||
| 349 | } | ||
| 350 | |||
| 351 | /** | ||
| 352 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome. | ||
| 353 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome | ||
| 354 | * (include `-moz` to future-proof). | ||
| 355 | */ | ||
| 356 | |||
| 357 | input[type="search"] { | ||
| 358 | -webkit-appearance: textfield; /* 1 */ | ||
| 359 | -moz-box-sizing: content-box; | ||
| 360 | -webkit-box-sizing: content-box; /* 2 */ | ||
| 361 | box-sizing: content-box; | ||
| 362 | } | ||
| 363 | |||
| 364 | /** | ||
| 365 | * Remove inner padding and search cancel button in Safari and Chrome on OS X. | ||
| 366 | * Safari (but not Chrome) clips the cancel button when the search input has | ||
| 367 | * padding (and `textfield` appearance). | ||
| 368 | */ | ||
| 369 | |||
| 370 | input[type="search"]::-webkit-search-cancel-button, | ||
| 371 | input[type="search"]::-webkit-search-decoration { | ||
| 372 | -webkit-appearance: none; | ||
| 373 | } | ||
| 374 | |||
| 375 | /** | ||
| 376 | * Define consistent border, margin, and padding. | ||
| 377 | */ | ||
| 378 | |||
| 379 | fieldset { | ||
| 380 | border: 1px solid #c0c0c0; | ||
| 381 | margin: 0 2px; | ||
| 382 | padding: 0.35em 0.625em 0.75em; | ||
| 383 | } | ||
| 384 | |||
| 385 | /** | ||
| 386 | * 1. Correct `color` not being inherited in IE 8/9/10/11. | ||
| 387 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. | ||
| 388 | */ | ||
| 389 | |||
| 390 | legend { | ||
| 391 | border: 0; /* 1 */ | ||
| 392 | padding: 0; /* 2 */ | ||
| 393 | } | ||
| 394 | |||
| 395 | /** | ||
| 396 | * Remove default vertical scrollbar in IE 8/9/10/11. | ||
| 397 | */ | ||
| 398 | |||
| 399 | textarea { | ||
| 400 | overflow: auto; | ||
| 401 | } | ||
| 402 | |||
| 403 | /** | ||
| 404 | * Don't inherit the `font-weight` (applied by a rule above). | ||
| 405 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. | ||
| 406 | */ | ||
| 407 | |||
| 408 | optgroup { | ||
| 409 | font-weight: bold; | ||
| 410 | } | ||
| 411 | |||
| 412 | /* Tables | ||
| 413 | ========================================================================== */ | ||
| 414 | |||
| 415 | /** | ||
| 416 | * Remove most spacing between table cells. | ||
| 417 | */ | ||
| 418 | |||
| 419 | table { | ||
| 420 | border-collapse: collapse; | ||
| 421 | border-spacing: 0; | ||
| 422 | } | ||
| 423 | |||
| 424 | td, | ||
| 425 | th { | ||
| 426 | padding: 0; | ||
| 427 | } \ No newline at end of file | ||
diff --git a/static/raleway.woff2 b/static/raleway.woff2 new file mode 100644 index 0000000..7cb7031 --- /dev/null +++ b/static/raleway.woff2 | |||
| Binary files differ | |||
diff --git a/static/skeleton.css b/static/skeleton.css new file mode 100644 index 0000000..f28bf6c --- /dev/null +++ b/static/skeleton.css | |||
| @@ -0,0 +1,418 @@ | |||
| 1 | /* | ||
| 2 | * Skeleton V2.0.4 | ||
| 3 | * Copyright 2014, Dave Gamache | ||
| 4 | * www.getskeleton.com | ||
| 5 | * Free to use under the MIT license. | ||
| 6 | * http://www.opensource.org/licenses/mit-license.php | ||
| 7 | * 12/29/2014 | ||
| 8 | */ | ||
| 9 | |||
| 10 | |||
| 11 | /* Table of contents | ||
| 12 | –––––––––––––––––––––––––––––––––––––––––––––––––– | ||
| 13 | - Grid | ||
| 14 | - Base Styles | ||
| 15 | - Typography | ||
| 16 | - Links | ||
| 17 | - Buttons | ||
| 18 | - Forms | ||
| 19 | - Lists | ||
| 20 | - Code | ||
| 21 | - Tables | ||
| 22 | - Spacing | ||
| 23 | - Utilities | ||
| 24 | - Clearing | ||
| 25 | - Media Queries | ||
| 26 | */ | ||
| 27 | |||
| 28 | |||
| 29 | /* Grid | ||
| 30 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ | ||
| 31 | .container { | ||
| 32 | position: relative; | ||
| 33 | width: 100%; | ||
| 34 | max-width: 960px; | ||
| 35 | margin: 0 auto; | ||
| 36 | padding: 0 20px; | ||
| 37 | box-sizing: border-box; } | ||
| 38 | .column, | ||
| 39 | .columns { | ||
| 40 | width: 100%; | ||
| 41 | float: left; | ||
| 42 | box-sizing: border-box; } | ||
| 43 | |||
| 44 | /* For devices larger than 400px */ | ||
| 45 | @media (min-width: 400px) { | ||
| 46 | .container { | ||
| 47 | width: 85%; | ||
| 48 | padding: 0; } | ||
| 49 | } | ||
| 50 | |||
| 51 | /* For devices larger than 550px */ | ||
| 52 | @media (min-width: 550px) { | ||
| 53 | .container { | ||
| 54 | width: 80%; } | ||
| 55 | .column, | ||
| 56 | .columns { | ||
| 57 | margin-left: 4%; } | ||
| 58 | .column:first-child, | ||
| 59 | .columns:first-child { | ||
| 60 | margin-left: 0; } | ||
| 61 | |||
| 62 | .one.column, | ||
| 63 | .one.columns { width: 4.66666666667%; } | ||
| 64 | .two.columns { width: 13.3333333333%; } | ||
| 65 | .three.columns { width: 22%; } | ||
| 66 | .four.columns { width: 30.6666666667%; } | ||
| 67 | .five.columns { width: 39.3333333333%; } | ||
| 68 | .six.columns { width: 48%; } | ||
| 69 | .seven.columns { width: 56.6666666667%; } | ||
| 70 | .eight.columns { width: 65.3333333333%; } | ||
| 71 | .nine.columns { width: 74.0%; } | ||
| 72 | .ten.columns { width: 82.6666666667%; } | ||
| 73 | .eleven.columns { width: 91.3333333333%; } | ||
| 74 | .twelve.columns { width: 100%; margin-left: 0; } | ||
| 75 | |||
| 76 | .one-third.column { width: 30.6666666667%; } | ||
| 77 | .two-thirds.column { width: 65.3333333333%; } | ||
| 78 | |||
| 79 | .one-half.column { width: 48%; } | ||
| 80 | |||
| 81 | /* Offsets */ | ||
| 82 | .offset-by-one.column, | ||
| 83 | .offset-by-one.columns { margin-left: 8.66666666667%; } | ||
| 84 | .offset-by-two.column, | ||
| 85 | .offset-by-two.columns { margin-left: 17.3333333333%; } | ||
| 86 | .offset-by-three.column, | ||
| 87 | .offset-by-three.columns { margin-left: 26%; } | ||
| 88 | .offset-by-four.column, | ||
| 89 | .offset-by-four.columns { margin-left: 34.6666666667%; } | ||
| 90 | .offset-by-five.column, | ||
| 91 | .offset-by-five.columns { margin-left: 43.3333333333%; } | ||
| 92 | .offset-by-six.column, | ||
| 93 | .offset-by-six.columns { margin-left: 52%; } | ||
| 94 | .offset-by-seven.column, | ||
| 95 | .offset-by-seven.columns { margin-left: 60.6666666667%; } | ||
| 96 | .offset-by-eight.column, | ||
| 97 | .offset-by-eight.columns { margin-left: 69.3333333333%; } | ||
| 98 | .offset-by-nine.column, | ||
| 99 | .offset-by-nine.columns { margin-left: 78.0%; } | ||
| 100 | .offset-by-ten.column, | ||
| 101 | .offset-by-ten.columns { margin-left: 86.6666666667%; } | ||
| 102 | .offset-by-eleven.column, | ||
| 103 | .offset-by-eleven.columns { margin-left: 95.3333333333%; } | ||
| 104 | |||
| 105 | .offset-by-one-third.column, | ||
| 106 | .offset-by-one-third.columns { margin-left: 34.6666666667%; } | ||
| 107 | .offset-by-two-thirds.column, | ||
| 108 | .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } | ||
| 109 | |||
| 110 | .offset-by-one-half.column, | ||
| 111 | .offset-by-one-half.columns { margin-left: 52%; } | ||
| 112 | |||
| 113 | } | ||
| 114 | |||
| 115 | |||
| 116 | /* Base Styles | ||
| 117 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ | ||
| 118 | /* NOTE | ||
| 119 | html is set to 62.5% so that all the REM measurements throughout Skeleton | ||
| 120 | are based on 10px sizing. So basically 1.5rem = 15px :) */ | ||
| 121 | html { | ||
| 122 | font-size: 62.5%; } | ||
| 123 | body { | ||
| 124 | font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ | ||
| 125 | line-height: 1.6; | ||
| 126 | font-weight: 400; | ||
| 127 | font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; | ||
| 128 | color: #222; } | ||
| 129 | |||
| 130 | |||
| 131 | /* Typography | ||
| 132 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ | ||
| 133 | h1, h2, h3, h4, h5, h6 { | ||
| 134 | margin-top: 0; | ||
| 135 | margin-bottom: 2rem; | ||
| 136 | font-weight: 300; } | ||
| 137 | h1 { font-size: 4.0rem; line-height: 1.2; letter-spacing: -.1rem;} | ||
| 138 | h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; } | ||
| 139 | h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; } | ||
| 140 | h4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; } | ||
| 141 | h5 { font-size: 1.8rem; line-height: 1.5; letter-spacing: -.05rem; } | ||
| 142 | h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; } | ||
| 143 | |||
| 144 | /* Larger than phablet */ | ||
| 145 | @media (min-width: 550px) { | ||
| 146 | h1 { font-size: 5.0rem; } | ||
| 147 | h2 { font-size: 4.2rem; } | ||
| 148 | h3 { font-size: 3.6rem; } | ||
| 149 | h4 { font-size: 3.0rem; } | ||
| 150 | h5 { font-size: 2.4rem; } | ||
| 151 | h6 { font-size: 1.5rem; } | ||
| 152 | } | ||
| 153 | |||
| 154 | p { | ||
| 155 | margin-top: 0; } | ||
| 156 | |||
| 157 | |||
| 158 | /* Links | ||
| 159 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ | ||
| 160 | a { | ||
| 161 | color: #1EAEDB; } | ||
| 162 | a:hover { | ||
| 163 | color: #0FA0CE; } | ||
| 164 | |||
| 165 | |||
| 166 | /* Buttons | ||
| 167 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ | ||
| 168 | .button, | ||
| 169 | button, | ||
| 170 | input[type="submit"], | ||
| 171 | input[type="reset"], | ||
| 172 | input[type="button"] { | ||
| 173 | display: inline-block; | ||
| 174 | height: 38px; | ||
| 175 | padding: 0 30px; | ||
| 176 | color: #555; | ||
| 177 | text-align: center; | ||
| 178 | font-size: 11px; | ||
| 179 | font-weight: 600; | ||
| 180 | line-height: 38px; | ||
| 181 | letter-spacing: .1rem; | ||
| 182 | text-transform: uppercase; | ||
| 183 | text-decoration: none; | ||
| 184 | white-space: nowrap; | ||
| 185 | background-color: transparent; | ||
| 186 | border-radius: 4px; | ||
| 187 | border: 1px solid #bbb; | ||
| 188 | cursor: pointer; | ||
| 189 | box-sizing: border-box; } | ||
| 190 | .button:hover, | ||
| 191 | button:hover, | ||
| 192 | input[type="submit"]:hover, | ||
| 193 | input[type="reset"]:hover, | ||
| 194 | input[type="button"]:hover, | ||
| 195 | .button:focus, | ||
| 196 | button:focus, | ||
| 197 | input[type="submit"]:focus, | ||
| 198 | input[type="reset"]:focus, | ||
| 199 | input[type="button"]:focus { | ||
| 200 | color: #333; | ||
| 201 | border-color: #888; | ||
| 202 | outline: 0; } | ||
| 203 | .button.button-primary, | ||
| 204 | button.button-primary, | ||
| 205 | input[type="submit"].button-primary, | ||
| 206 | input[type="reset"].button-primary, | ||
| 207 | input[type="button"].button-primary { | ||
| 208 | color: #FFF; | ||
| 209 | background-color: #33C3F0; | ||
| 210 | border-color: #33C3F0; } | ||
| 211 | .button.button-primary:hover, | ||
| 212 | button.button-primary:hover, | ||
| 213 | input[type="submit"].button-primary:hover, | ||
| 214 | input[type="reset"].button-primary:hover, | ||
| 215 | input[type="button"].button-primary:hover, | ||
| 216 | .button.button-primary:focus, | ||
| 217 | button.button-primary:focus, | ||
| 218 | input[type="submit"].button-primary:focus, | ||
| 219 | input[type="reset"].button-primary:focus, | ||
| 220 | input[type="button"].button-primary:focus { | ||
| 221 | color: #FFF; | ||
| 222 | background-color: #1EAEDB; | ||
| 223 | border-color: #1EAEDB; } | ||
| 224 | |||
| 225 | |||
| 226 | /* Forms | ||
| 227 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ | ||
| 228 | input[type="email"], | ||
| 229 | input[type="number"], | ||
| 230 | input[type="search"], | ||
| 231 | input[type="text"], | ||
| 232 | input[type="tel"], | ||
| 233 | input[type="url"], | ||
| 234 | input[type="password"], | ||
| 235 | textarea, | ||
| 236 | select { | ||
| 237 | height: 38px; | ||
| 238 | padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ | ||
| 239 | background-color: #fff; | ||
| 240 | border: 1px solid #D1D1D1; | ||
| 241 | border-radius: 4px; | ||
| 242 | box-shadow: none; | ||
| 243 | box-sizing: border-box; } | ||
| 244 | /* Removes awkward default styles on some inputs for iOS */ | ||
| 245 | input[type="email"], | ||
| 246 | input[type="number"], | ||
| 247 | input[type="search"], | ||
| 248 | input[type="text"], | ||
| 249 | input[type="tel"], | ||
| 250 | input[type="url"], | ||
| 251 | input[type="password"], | ||
| 252 | textarea { | ||
| 253 | -webkit-appearance: none; | ||
| 254 | -moz-appearance: none; | ||
| 255 | appearance: none; } | ||
| 256 | textarea { | ||
| 257 | min-height: 65px; | ||
| 258 | padding-top: 6px; | ||
| 259 | padding-bottom: 6px; } | ||
| 260 | input[type="email"]:focus, | ||
| 261 | input[type="number"]:focus, | ||
| 262 | input[type="search"]:focus, | ||
| 263 | input[type="text"]:focus, | ||
| 264 | input[type="tel"]:focus, | ||
| 265 | input[type="url"]:focus, | ||
| 266 | input[type="password"]:focus, | ||
| 267 | textarea:focus, | ||
| 268 | select:focus { | ||
| 269 | border: 1px solid #33C3F0; | ||
| 270 | outline: 0; } | ||
| 271 | label, | ||
| 272 | legend { | ||
| 273 | display: block; | ||
| 274 | margin-bottom: .5rem; | ||
| 275 | font-weight: 600; } | ||
| 276 | fieldset { | ||
| 277 | padding: 0; | ||
| 278 | border-width: 0; } | ||
| 279 | input[type="checkbox"], | ||
| 280 | input[type="radio"] { | ||
| 281 | display: inline; } | ||
| 282 | label > .label-body { | ||
| 283 | display: inline-block; | ||
| 284 | margin-left: .5rem; | ||
| 285 | font-weight: normal; } | ||
| 286 | |||
| 287 | |||
| 288 | /* Lists | ||
| 289 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ | ||
| 290 | ul { | ||
| 291 | list-style: circle inside; } | ||
| 292 | ol { | ||
| 293 | list-style: decimal inside; } | ||
| 294 | ol, ul { | ||
| 295 | padding-left: 0; | ||
| 296 | margin-top: 0; } | ||
| 297 | ul ul, | ||
| 298 | ul ol, | ||
| 299 | ol ol, | ||
| 300 | ol ul { | ||
| 301 | margin: 1.5rem 0 1.5rem 3rem; | ||
| 302 | font-size: 90%; } | ||
| 303 | li { | ||
| 304 | margin-bottom: 1rem; } | ||
| 305 | |||
| 306 | |||
| 307 | /* Code | ||
| 308 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ | ||
| 309 | code { | ||
| 310 | padding: .2rem .5rem; | ||
| 311 | margin: 0 .2rem; | ||
| 312 | font-size: 90%; | ||
| 313 | white-space: nowrap; | ||
| 314 | background: #F1F1F1; | ||
| 315 | border: 1px solid #E1E1E1; | ||
| 316 | border-radius: 4px; } | ||
| 317 | pre > code { | ||
| 318 | display: block; | ||
| 319 | padding: 1rem 1.5rem; | ||
| 320 | white-space: pre; } | ||
| 321 | |||
| 322 | |||
| 323 | /* Tables | ||
| 324 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ | ||
| 325 | th, | ||
| 326 | td { | ||
| 327 | padding: 12px 15px; | ||
| 328 | text-align: left; | ||
| 329 | border-bottom: 1px solid #E1E1E1; } | ||
| 330 | th:first-child, | ||
| 331 | td:first-child { | ||
| 332 | padding-left: 0; } | ||
| 333 | th:last-child, | ||
| 334 | td:last-child { | ||
| 335 | padding-right: 0; } | ||
| 336 | |||
| 337 | |||
| 338 | /* Spacing | ||
| 339 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ | ||
| 340 | button, | ||
| 341 | .button { | ||
| 342 | margin-bottom: 1rem; } | ||
| 343 | input, | ||
| 344 | textarea, | ||
| 345 | select, | ||
| 346 | fieldset { | ||
| 347 | margin-bottom: 1.5rem; } | ||
| 348 | pre, | ||
| 349 | blockquote, | ||
| 350 | dl, | ||
| 351 | figure, | ||
| 352 | table, | ||
| 353 | p, | ||
| 354 | ul, | ||
| 355 | ol, | ||
| 356 | form { | ||
| 357 | margin-bottom: 2.5rem; } | ||
| 358 | |||
| 359 | |||
| 360 | /* Utilities | ||
| 361 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ | ||
| 362 | .u-full-width { | ||
| 363 | width: 100%; | ||
| 364 | box-sizing: border-box; } | ||
| 365 | .u-max-full-width { | ||
| 366 | max-width: 100%; | ||
| 367 | box-sizing: border-box; } | ||
| 368 | .u-pull-right { | ||
| 369 | float: right; } | ||
| 370 | .u-pull-left { | ||
| 371 | float: left; } | ||
| 372 | |||
| 373 | |||
| 374 | /* Misc | ||
| 375 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ | ||
| 376 | hr { | ||
| 377 | margin-top: 3rem; | ||
| 378 | margin-bottom: 3.5rem; | ||
| 379 | border-width: 0; | ||
| 380 | border-top: 1px solid #E1E1E1; } | ||
| 381 | |||
| 382 | |||
| 383 | /* Clearing | ||
| 384 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ | ||
| 385 | |||
| 386 | /* Self Clearing Goodness */ | ||
| 387 | .container:after, | ||
| 388 | .row:after, | ||
| 389 | .u-cf { | ||
| 390 | content: ""; | ||
| 391 | display: table; | ||
| 392 | clear: both; } | ||
| 393 | |||
| 394 | |||
| 395 | /* Media Queries | ||
| 396 | –––––––––––––––––––––––––––––––––––––––––––––––––– */ | ||
| 397 | /* | ||
| 398 | Note: The best way to structure the use of media queries is to create the queries | ||
| 399 | near the relevant code. For example, if you wanted to change the styles for buttons | ||
| 400 | on small devices, paste the mobile query code up in the buttons section and style it | ||
| 401 | there. | ||
| 402 | */ | ||
| 403 | |||
| 404 | |||
| 405 | /* Larger than mobile */ | ||
| 406 | @media (min-width: 400px) {} | ||
| 407 | |||
| 408 | /* Larger than phablet (also point when grid becomes active) */ | ||
| 409 | @media (min-width: 550px) {} | ||
| 410 | |||
| 411 | /* Larger than tablet */ | ||
| 412 | @media (min-width: 750px) {} | ||
| 413 | |||
| 414 | /* Larger than desktop */ | ||
| 415 | @media (min-width: 1000px) {} | ||
| 416 | |||
| 417 | /* Larger than Desktop HD */ | ||
| 418 | @media (min-width: 1200px) {} | ||
diff --git a/static/style.css b/static/style.css index ed92664..5f854a4 100644 --- a/static/style.css +++ b/static/style.css | |||
| @@ -1,21 +1,41 @@ | |||
| 1 | header { | 1 | @font-face { |
| 2 | border-bottom: 1px solid black; | 2 | font-family: 'Raleway'; |
| 3 | width: 100%; | 3 | font-style: normal; |
| 4 | font-weight: 400; | ||
| 5 | src: local('Raleway'), local('Raleway-Regular'), url(raleway-ext.woff2) format('woff2'); | ||
| 6 | unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; | ||
| 7 | } | ||
| 8 | |||
| 9 | @font-face { | ||
| 10 | font-family: 'Raleway'; | ||
| 11 | font-style: normal; | ||
| 12 | font-weight: 400; | ||
| 13 | src: local('Raleway'), local('Raleway-Regular'), url(raleway.woff2) format('woff2'); | ||
| 14 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; | ||
| 15 | } | ||
| 16 | |||
| 17 | |||
| 18 | .container { | ||
| 19 | margin-top: 18rem; | ||
| 4 | } | 20 | } |
| 5 | 21 | ||
| 6 | header h1 { | 22 | .flashes { |
| 7 | text-align: center; | 23 | text-align: center; |
| 24 | border: 1px solid #1EAEDB; | ||
| 8 | } | 25 | } |
| 9 | header a { | 26 | |
| 10 | text-align:right; | 27 | footer { |
| 28 | width: 100%; | ||
| 29 | position: absolute; | ||
| 30 | bottom: 0; | ||
| 31 | height: 1%; | ||
| 32 | text-align: center; | ||
| 33 | } | ||
| 34 | |||
| 35 | a { | ||
| 36 | text-decoration: none; | ||
| 11 | } | 37 | } |
| 12 | 38 | ||
| 13 | section { | 39 | a:hover { |
| 14 | border-radius: 1em; | 40 | text-decoration: underline; |
| 15 | padding: 1em; | ||
| 16 | position: absolute; | ||
| 17 | top: 50%; | ||
| 18 | left: 50%; | ||
| 19 | margin-right: -50%; | ||
| 20 | transform: translate(-50%, -50%); | ||
| 21 | } | 41 | } |
diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..3f6e97b --- /dev/null +++ b/templates/base.html | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | <!doctype html> | ||
| 2 | <html> | ||
| 3 | <head> | ||
| 4 | <title>mat2 - web edition</title> | ||
| 5 | <link href="{{url_for('static', filename='raleway.woff2') }}" as="font" type="font/woff2" rel="preload"> | ||
| 6 | <link rel="stylesheet" href="{{ url_for('static', filename='normalize.css') }}" type="text/css" /> | ||
| 7 | <link rel="stylesheet" href="{{ url_for('static', filename='skeleton.css') }}" type="text/css" /> | ||
| 8 | <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" type="text/css" /> | ||
| 9 | <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.png') }}"> | ||
| 10 | </head> | ||
| 11 | <body> | ||
| 12 | <div class="container"> | ||
| 13 | <div class="row"> | ||
| 14 | {% with messages = get_flashed_messages() %} | ||
| 15 | {% if messages %} | ||
| 16 | <ul class=flashes> | ||
| 17 | {% for message in messages %} | ||
| 18 | <li>{{ message }}</li> | ||
| 19 | {% endfor %} | ||
| 20 | </ul> | ||
| 21 | {% endif %} | ||
| 22 | {% endwith %} | ||
| 23 | </div> | ||
| 24 | |||
| 25 | <section> | ||
| 26 | <div class="row"> | ||
| 27 | <div class="four columns"> | ||
| 28 | <a href='.'> | ||
| 29 | <img class='u-max-full-width' src="{{ url_for('static', filename='logo.png') }}" alt="mat2 logo"/> | ||
| 30 | </a> | ||
| 31 | </div> | ||
| 32 | <div class="eight columns"> | ||
| 33 | {% block content %}{% endblock %} | ||
| 34 | </div> | ||
| 35 | </section> | ||
| 36 | |||
| 37 | <footer> | ||
| 38 | © <a href='https://dustri.org'>jvoisin</a> - | ||
| 39 | <a href='https://0xacab.org/jvoisin/mat2-web'>source</a> - | ||
| 40 | ♥ | ||
| 41 | </footer> | ||
| 42 | </body> | ||
diff --git a/templates/download.html b/templates/download.html new file mode 100644 index 0000000..c2b2a42 --- /dev/null +++ b/templates/download.html | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | {% extends "base.html" %} | ||
| 2 | |||
| 3 | {% block content %} | ||
| 4 | <h2>» Metadata removed</h2> | ||
| 5 | <p> | ||
| 6 | {% if not meta_after %} | ||
| 7 | mat2 managed to remove <b>all metadata</b> from your file. | ||
| 8 | {% else %} | ||
| 9 | mat2 <b>could not</b> remove all the metadata from your file, those are the remaining ones: | ||
| 10 | <ul> | ||
| 11 | {% for key, value in meta_after.items() %} | ||
| 12 | <li> <b>{{ key }}</b>: {{ value }}</li> | ||
| 13 | {% endfor %} | ||
| 14 | </ul> | ||
| 15 | {%endif %} | ||
| 16 | </p> | ||
| 17 | <a class="button button-primary" href='{{ url_for('download_file', filename=filename) }}'>⇩ Download cleaned file</a> | ||
| 18 | |||
| 19 | <hr/> | ||
| 20 | |||
| 21 | {% if meta %} | ||
| 22 | <p>Just for fun, those are the metadata that mat2 detected in your file, before cleanup.</p> | ||
| 23 | <div class='b'> | ||
| 24 | <ul> | ||
| 25 | {% for key, value in meta.items() %} | ||
| 26 | <li>{{ key }}: <i>{{ value }}</i></li> | ||
| 27 | {% endfor %} | ||
| 28 | </ul> | ||
| 29 | </div> | ||
| 30 | {% else %} | ||
| 31 | meh | ||
| 32 | {% endif %} | ||
| 33 | |||
| 34 | <hr/> | ||
| 35 | |||
| 36 | {% endblock %} | ||
| 37 | |||
diff --git a/templates/index.html b/templates/index.html index 0496c2d..1e05c82 100644 --- a/templates/index.html +++ b/templates/index.html | |||
| @@ -1,20 +1,16 @@ | |||
| 1 | <!doctype html> | 1 | {% extends "base.html" %} |
| 2 | <html> | 2 | {% block content %} |
| 3 | <head> | 3 | |
| 4 | <title>mat2 - online edition</title> | 4 | <h2>» Remove metadata</h2> |
| 5 | <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" type="text/css" /> | 5 | <p> |
| 6 | </head> | 6 | Upload your image, get a <em>cleaned</em> one in response.<br> |
| 7 | <body> | 7 | <br> |
| 8 | <header> | 8 | Please note that while we do not keep a copy of your image,<br> |
| 9 | <h1>mat2 - online edition</h1> | 9 | there is no way that you could be certain about this: act accordingly. |
| 10 | </header> | 10 | </p> |
| 11 | <section> | 11 | <br> |
| 12 | <h1>Remove metadata from your images</h1> | 12 | <form class='b' method=post enctype=multipart/form-data> |
| 13 | <p>Drag and drop anywhere you want and get your files cleaned</p> | 13 | <input type=file name=file id="upload_file" accept="{{ mimetypes }}"> |
| 14 | <br> | 14 | <input type=submit value=Upload> |
| 15 | <form method=post enctype=multipart/form-data> | 15 | </form> |
| 16 | <input type=file name=file id="upload_file" accept="{{ mimetypes }}"> | 16 | {% endblock %} |
| 17 | <input type=submit value=Upload> | ||
| 18 | </form> | ||
| 19 | </section> | ||
| 20 | </body> | ||
