├── .gitignore
├── favicon.png
├── img
├── icon.png
├── logo.png
├── logo-white.svg
└── logo.svg
├── css
├── fonts
│ ├── roboto-light.eot
│ ├── roboto-light.ttf
│ ├── roboto-light.woff
│ ├── roboto-regular.eot
│ ├── roboto-regular.ttf
│ ├── roboto-regular.woff
│ ├── fontawesome-webfont.eot
│ ├── fontawesome-webfont.ttf
│ ├── fontawesome-webfont.woff
│ └── fontawesome-webfont.woff2
├── grids-responsive-min.css
├── simplemde.min.css
├── pure-min.css
├── blog.css
└── font-awesome.min.css
├── config-example.json
├── manifest.json
├── LICENSE
├── README.md
├── js
├── dropdown.js
└── moment.min.js
├── index.html
└── app
├── solid.js
└── app.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | config.json
3 | posts/
4 |
--------------------------------------------------------------------------------
/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deiu/solid-plume/gh-pages/favicon.png
--------------------------------------------------------------------------------
/img/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deiu/solid-plume/gh-pages/img/icon.png
--------------------------------------------------------------------------------
/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deiu/solid-plume/gh-pages/img/logo.png
--------------------------------------------------------------------------------
/css/fonts/roboto-light.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deiu/solid-plume/gh-pages/css/fonts/roboto-light.eot
--------------------------------------------------------------------------------
/css/fonts/roboto-light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deiu/solid-plume/gh-pages/css/fonts/roboto-light.ttf
--------------------------------------------------------------------------------
/css/fonts/roboto-light.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deiu/solid-plume/gh-pages/css/fonts/roboto-light.woff
--------------------------------------------------------------------------------
/css/fonts/roboto-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deiu/solid-plume/gh-pages/css/fonts/roboto-regular.eot
--------------------------------------------------------------------------------
/css/fonts/roboto-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deiu/solid-plume/gh-pages/css/fonts/roboto-regular.ttf
--------------------------------------------------------------------------------
/css/fonts/roboto-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deiu/solid-plume/gh-pages/css/fonts/roboto-regular.woff
--------------------------------------------------------------------------------
/css/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deiu/solid-plume/gh-pages/css/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/css/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deiu/solid-plume/gh-pages/css/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/css/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deiu/solid-plume/gh-pages/css/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/css/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deiu/solid-plume/gh-pages/css/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/config-example.json:
--------------------------------------------------------------------------------
1 | {
2 | "owners": [""],
3 | "title": "Plume",
4 | "tagline": "Light as a feather",
5 | "picture": "img/logo.svg",
6 | "fadeText": true,
7 | "showSources": true,
8 | "cacheUnit": "days",
9 | "defaultPath": "posts",
10 | "postsURL": ""
11 | }
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Plume",
3 | "icons": [
4 | {
5 | "src": "img/favicon.png",
6 | "sizes": "256x256",
7 | "type": "image/icon.png",
8 | "density": "4.0"
9 | }
10 | ],
11 | "start_url": "index.html",
12 | "display": "standalone",
13 | "orientation": "portrait"
14 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Andrei
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/img/logo-white.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
8 |
9 |
10 |
19 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/img/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
8 |
9 |
10 |
20 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Plume
2 |
3 |
4 |
5 | *Plume* is a 100% client-side blogging platform, built using [Solid standards](https://github.com/solid/), in which data is decoupled from the application itself. This means that you can host the application on any Web server, without having to install anything -- no database, no messing around with Node.js, it has 0 dependencies! It also means that other similar applications will be able to reuse the data resulting from your posts, without having to go through a complicated API.
6 |
7 | Plume uses [Markdown](https://en.wikipedia.org/wiki/Markdown) to provide you with the easiest and fastest experience for writing beautiful articles.
8 |
9 | It currently does not support dynamic configuration of data spaces, which means you will have to either run it on your own Web server, or manually upload it to your account -- you can use [https://databox.me]( https://databox.me) as storage. The next version will allow you to run it from Github, like all the other [Solid apps](https://github.com/solid/solid-apps) we currently offer.
10 |
11 | ## Configuration
12 |
13 | Before being able to use Plume, you will have to manually set some config values. First you need to copy/rename the `config-example.json` file to `config.json`. Then you need to set the `postsURL` value to have it point to an **existing** container on a [Solid-friendly server](https://github.com/solid/solid-platform) that holds your blog posts. Finally, you should also set the `owners` variable by adding your own WebID, in order to be able to access the editor UI and to create new posts.
14 |
15 | Here is an example of the configuration file:
16 |
17 | ```
18 | {
19 | "owners": ["https://example.org/profile#me"],
20 | "title": "Plume",
21 | "tagline": "Light as a feather",
22 | "picture": "img/logo.svg",
23 | "fadeText": true,
24 | "showSources": true,
25 | "cacheUnit": "days",
26 | "defaultPath": "posts",
27 | "postsURL": "https://account.databox.me/Public/blog/posts/"
28 | }
29 | ```
30 |
31 | Here is what each config parameter means:
32 |
33 | * `owner`: a list of URLs (WebIDs) of the people who can post on the blog
34 | * `title`: the title of the blog
35 | * `tagline`: tagline/subtitle
36 | * `picture`: the picture to display on the blog's header
37 | * `fadeText`: true/false - shortens the posts length when viewing the full blog
38 | * `showSources`: true/false - it will add a button/link that points to the source of the blog post (the actual resource)
39 | * `cacheUnit`: minutes/hours/days/ - validity of certain cached data (you shouldn't really need to change it)
40 | * `defaultPath`: this value will be suggested to the user if the blog needs to be initialized
41 | * `postsURL`: the URL of the folder (container) holding the posts for the blog
42 |
--------------------------------------------------------------------------------
/js/dropdown.js:
--------------------------------------------------------------------------------
1 | (function (window, document) {
2 | 'use strict';
3 |
4 | // Enable drop-down menus in Pure
5 | // Inspired by YUI3 gallery-simple-menu by Julien LeComte
6 | // [https://github.com/yui/yui3-gallery/blob/master/src/gallery-simple-menu/js/simple-menu.js]
7 |
8 | function PureDropdown(dropdownParent) {
9 |
10 | var PREFIX = 'pure-',
11 | ACTIVE_CLASS_NAME = PREFIX + 'menu-active',
12 | ARIA_ROLE = 'role',
13 | ARIA_HIDDEN = 'aria-hidden',
14 | MENU_OPEN = 0,
15 | MENU_CLOSED = 1,
16 | MENU_PARENT_CLASS_NAME = 'pure-menu-has-children',
17 | MENU_ACTIVE_SELECTOR = '.pure-menu-active',
18 | MENU_LINK_SELECTOR = '.pure-menu-link',
19 | MENU_SELECTOR = '.pure-menu-children',
20 | DISMISS_EVENT = (window.hasOwnProperty &&
21 | window.hasOwnProperty('ontouchstart')) ?
22 | 'touchstart' : 'mousedown',
23 |
24 | ARROW_KEYS_ENABLED = true,
25 |
26 | ddm = this; // drop down menu
27 |
28 | this._state = MENU_CLOSED;
29 |
30 | this.show = function () {
31 | if (this._state !== MENU_OPEN) {
32 | this._dropdownParent.classList.add(ACTIVE_CLASS_NAME);
33 | this._menu.setAttribute(ARIA_HIDDEN, false);
34 | this._state = MENU_OPEN;
35 | }
36 | };
37 |
38 | this.hide = function () {
39 | if (this._state !== MENU_CLOSED) {
40 | this._dropdownParent.classList.remove(ACTIVE_CLASS_NAME);
41 | this._menu.setAttribute(ARIA_HIDDEN, true);
42 | this._link.focus();
43 | this._state = MENU_CLOSED;
44 | }
45 | };
46 |
47 | this.toggle = function () {
48 | this[this._state === MENU_CLOSED ? 'show' : 'hide']();
49 | };
50 |
51 | this.halt = function (e) {
52 | e.stopPropagation();
53 | e.preventDefault();
54 | };
55 |
56 | this._dropdownParent = dropdownParent;
57 | this._link = this._dropdownParent.querySelector(MENU_LINK_SELECTOR);
58 | this._menu = this._dropdownParent.querySelector(MENU_SELECTOR);
59 | this._firstMenuLink = this._menu.querySelector(MENU_LINK_SELECTOR);
60 |
61 | // Set ARIA attributes
62 | this._link.setAttribute('aria-haspopup', 'true');
63 | this._menu.setAttribute(ARIA_ROLE, 'menu');
64 | this._menu.setAttribute('aria-labelledby', this._link.getAttribute('id'));
65 | this._menu.setAttribute('aria-hidden', 'true');
66 | [].forEach.call(
67 | this._menu.querySelectorAll('li'),
68 | function(el){
69 | el.setAttribute(ARIA_ROLE, 'presentation');
70 | }
71 | );
72 | [].forEach.call(
73 | this._menu.querySelectorAll('a'),
74 | function(el){
75 | el.setAttribute(ARIA_ROLE, 'menuitem');
76 | }
77 | );
78 |
79 | // Toggle on click
80 | this._link.addEventListener('click', function (e) {
81 | e.stopPropagation();
82 | e.preventDefault();
83 | ddm.toggle();
84 | });
85 |
86 | // Keyboard navigation
87 | document.addEventListener('keydown', function (e) {
88 | var currentLink,
89 | previousSibling,
90 | nextSibling,
91 | previousLink,
92 | nextLink;
93 |
94 | // if the menu isn't active, ignore
95 | if (ddm._state !== MENU_OPEN) {
96 | return;
97 | }
98 |
99 | // if the menu is the parent of an open, active submenu, ignore
100 | if (ddm._menu.querySelector(MENU_ACTIVE_SELECTOR)) {
101 | return;
102 | }
103 |
104 | currentLink = ddm._menu.querySelector(':focus');
105 |
106 | // Dismiss an open menu on ESC
107 | if (e.keyCode === 27) {
108 | /* Esc */
109 | ddm.halt(e);
110 | ddm.hide();
111 | }
112 | // Go to the next link on down arrow
113 | else if (ARROW_KEYS_ENABLED && e.keyCode === 40) {
114 | /* Down arrow */
115 | ddm.halt(e);
116 | // get the nextSibling (an LI) of the current link's LI
117 | nextSibling = (currentLink) ? currentLink.parentNode.nextSibling : null;
118 | // if the nextSibling is a text node (not an element), go to the next one
119 | while (nextSibling && nextSibling.nodeType !== 1) {
120 | nextSibling = nextSibling.nextSibling;
121 | }
122 | nextLink = (nextSibling) ? nextSibling.querySelector('.pure-menu-link') : null;
123 | // if there is no currently focused link, focus the first one
124 | if (!currentLink) {
125 | ddm._menu.querySelector('.pure-menu-link').focus();
126 | }
127 | else if (nextLink) {
128 | nextLink.focus();
129 | }
130 | }
131 | // Go to the previous link on up arrow
132 | else if (ARROW_KEYS_ENABLED && e.keyCode === 38) {
133 | /* Up arrow */
134 | ddm.halt(e);
135 | // get the currently focused link
136 | previousSibling = (currentLink) ? currentLink.parentNode.previousSibling : null;
137 | while (previousSibling && previousSibling.nodeType !== 1) {
138 | previousSibling = previousSibling.previousSibling;
139 | }
140 | previousLink = (previousSibling) ? previousSibling.querySelector('.pure-menu-link') : null;
141 | // if there is no currently focused link, focus the last link
142 | if (!currentLink) {
143 | ddm._menu.querySelector('.pure-menu-item:last-child .pure-menu-link').focus();
144 | }
145 | // else if there is a previous item, go to the previous item
146 | else if (previousLink) {
147 | previousLink.focus();
148 | }
149 | }
150 | });
151 |
152 | // Dismiss an open menu on outside event
153 | document.addEventListener(DISMISS_EVENT, function (e) {
154 | var target = e.target;
155 | if (target !== ddm._link && !ddm._menu.contains(target)) {
156 | ddm.hide();
157 | ddm._link.blur();
158 | }
159 | });
160 |
161 | }
162 |
163 | function initDropdowns() {
164 | var dropdownParents = document.querySelectorAll('.pure-menu-has-children');
165 | for (var i = 0; i < dropdownParents.length; i++) {
166 | var ddm = new PureDropdown(dropdownParents[i]);
167 | }
168 | }
169 |
170 | initDropdowns();
171 |
172 | }(this, this.document));
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Plume
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
28 |
29 |
34 |
35 |
36 |
37 |
45 |
46 |
47 |
48 |
Loading post(s)...
49 |
50 |
51 |
52 |
72 |
75 |
76 | Publish
77 | View
78 | Cancel
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
You haven't published anything yet.
91 |
92 |
93 |
94 |
95 |
96 |
Could not find a blog URL.
97 |
If you would like, Plume can attempt to find your blog, or help you create one.
98 |
Do you use WebID? [ ]
99 |
Yes, I use WebID
100 |
No, I need a WebID
101 |
102 |
103 |
104 |
105 |
Could not find blog URL
106 |
107 |
108 | ≪ Back to blog
109 | Request access
110 |
111 |
112 |
113 |
114 |
121 |
122 |
123 |
124 |
125 |
126 |
What is a WebID?
127 |
128 | A WebID is a URL for you. It allows you to set up a reusable identity
129 | and a profile, with friends, pictures and all kinds of things.
130 |
131 |
132 | Unlike social networks, with WebID you reuse your identity and personal
133 | data in a decentralized, privacy-friendly way, across multiple applications
134 | and services on the Web. It works like having an account on a social
135 | networking site, but it isn't restricted to just that site. It is very
136 | open because the information can connect to other people, apps, projects
137 | and so on, without everyone having to join the same social networking site.
138 | (more information )
139 |
140 |
141 | When you create a WebID account, you may also get storage space on the
142 | selected server. The amount of available space can vary from server to
143 | server. Additionally, a common list of workspaces (i.e. dedicated folders)
144 | maye be created by default, such as Public , Private ,
145 | Family , Work , etc.
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
--------------------------------------------------------------------------------
/css/grids-responsive-min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | Pure v0.6.0
3 | Copyright 2014 Yahoo! Inc. All rights reserved.
4 | Licensed under the BSD License.
5 | https://github.com/yahoo/pure/blob/master/LICENSE.md
6 | */
7 | @media screen and (min-width:35.5em){.pure-u-sm-1,.pure-u-sm-1-1,.pure-u-sm-1-2,.pure-u-sm-1-3,.pure-u-sm-2-3,.pure-u-sm-1-4,.pure-u-sm-3-4,.pure-u-sm-1-5,.pure-u-sm-2-5,.pure-u-sm-3-5,.pure-u-sm-4-5,.pure-u-sm-5-5,.pure-u-sm-1-6,.pure-u-sm-5-6,.pure-u-sm-1-8,.pure-u-sm-3-8,.pure-u-sm-5-8,.pure-u-sm-7-8,.pure-u-sm-1-12,.pure-u-sm-5-12,.pure-u-sm-7-12,.pure-u-sm-11-12,.pure-u-sm-1-24,.pure-u-sm-2-24,.pure-u-sm-3-24,.pure-u-sm-4-24,.pure-u-sm-5-24,.pure-u-sm-6-24,.pure-u-sm-7-24,.pure-u-sm-8-24,.pure-u-sm-9-24,.pure-u-sm-10-24,.pure-u-sm-11-24,.pure-u-sm-12-24,.pure-u-sm-13-24,.pure-u-sm-14-24,.pure-u-sm-15-24,.pure-u-sm-16-24,.pure-u-sm-17-24,.pure-u-sm-18-24,.pure-u-sm-19-24,.pure-u-sm-20-24,.pure-u-sm-21-24,.pure-u-sm-22-24,.pure-u-sm-23-24,.pure-u-sm-24-24{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-sm-1-24{width:4.1667%;*width:4.1357%}.pure-u-sm-1-12,.pure-u-sm-2-24{width:8.3333%;*width:8.3023%}.pure-u-sm-1-8,.pure-u-sm-3-24{width:12.5%;*width:12.469%}.pure-u-sm-1-6,.pure-u-sm-4-24{width:16.6667%;*width:16.6357%}.pure-u-sm-1-5{width:20%;*width:19.969%}.pure-u-sm-5-24{width:20.8333%;*width:20.8023%}.pure-u-sm-1-4,.pure-u-sm-6-24{width:25%;*width:24.969%}.pure-u-sm-7-24{width:29.1667%;*width:29.1357%}.pure-u-sm-1-3,.pure-u-sm-8-24{width:33.3333%;*width:33.3023%}.pure-u-sm-3-8,.pure-u-sm-9-24{width:37.5%;*width:37.469%}.pure-u-sm-2-5{width:40%;*width:39.969%}.pure-u-sm-5-12,.pure-u-sm-10-24{width:41.6667%;*width:41.6357%}.pure-u-sm-11-24{width:45.8333%;*width:45.8023%}.pure-u-sm-1-2,.pure-u-sm-12-24{width:50%;*width:49.969%}.pure-u-sm-13-24{width:54.1667%;*width:54.1357%}.pure-u-sm-7-12,.pure-u-sm-14-24{width:58.3333%;*width:58.3023%}.pure-u-sm-3-5{width:60%;*width:59.969%}.pure-u-sm-5-8,.pure-u-sm-15-24{width:62.5%;*width:62.469%}.pure-u-sm-2-3,.pure-u-sm-16-24{width:66.6667%;*width:66.6357%}.pure-u-sm-17-24{width:70.8333%;*width:70.8023%}.pure-u-sm-3-4,.pure-u-sm-18-24{width:75%;*width:74.969%}.pure-u-sm-19-24{width:79.1667%;*width:79.1357%}.pure-u-sm-4-5{width:80%;*width:79.969%}.pure-u-sm-5-6,.pure-u-sm-20-24{width:83.3333%;*width:83.3023%}.pure-u-sm-7-8,.pure-u-sm-21-24{width:87.5%;*width:87.469%}.pure-u-sm-11-12,.pure-u-sm-22-24{width:91.6667%;*width:91.6357%}.pure-u-sm-23-24{width:95.8333%;*width:95.8023%}.pure-u-sm-1,.pure-u-sm-1-1,.pure-u-sm-5-5,.pure-u-sm-24-24{width:100%}}@media screen and (min-width:48em){.pure-u-md-1,.pure-u-md-1-1,.pure-u-md-1-2,.pure-u-md-1-3,.pure-u-md-2-3,.pure-u-md-1-4,.pure-u-md-3-4,.pure-u-md-1-5,.pure-u-md-2-5,.pure-u-md-3-5,.pure-u-md-4-5,.pure-u-md-5-5,.pure-u-md-1-6,.pure-u-md-5-6,.pure-u-md-1-8,.pure-u-md-3-8,.pure-u-md-5-8,.pure-u-md-7-8,.pure-u-md-1-12,.pure-u-md-5-12,.pure-u-md-7-12,.pure-u-md-11-12,.pure-u-md-1-24,.pure-u-md-2-24,.pure-u-md-3-24,.pure-u-md-4-24,.pure-u-md-5-24,.pure-u-md-6-24,.pure-u-md-7-24,.pure-u-md-8-24,.pure-u-md-9-24,.pure-u-md-10-24,.pure-u-md-11-24,.pure-u-md-12-24,.pure-u-md-13-24,.pure-u-md-14-24,.pure-u-md-15-24,.pure-u-md-16-24,.pure-u-md-17-24,.pure-u-md-18-24,.pure-u-md-19-24,.pure-u-md-20-24,.pure-u-md-21-24,.pure-u-md-22-24,.pure-u-md-23-24,.pure-u-md-24-24{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-md-1-24{width:4.1667%;*width:4.1357%}.pure-u-md-1-12,.pure-u-md-2-24{width:8.3333%;*width:8.3023%}.pure-u-md-1-8,.pure-u-md-3-24{width:12.5%;*width:12.469%}.pure-u-md-1-6,.pure-u-md-4-24{width:16.6667%;*width:16.6357%}.pure-u-md-1-5{width:20%;*width:19.969%}.pure-u-md-5-24{width:20.8333%;*width:20.8023%}.pure-u-md-1-4,.pure-u-md-6-24{width:25%;*width:24.969%}.pure-u-md-7-24{width:29.1667%;*width:29.1357%}.pure-u-md-1-3,.pure-u-md-8-24{width:33.3333%;*width:33.3023%}.pure-u-md-3-8,.pure-u-md-9-24{width:37.5%;*width:37.469%}.pure-u-md-2-5{width:40%;*width:39.969%}.pure-u-md-5-12,.pure-u-md-10-24{width:41.6667%;*width:41.6357%}.pure-u-md-11-24{width:45.8333%;*width:45.8023%}.pure-u-md-1-2,.pure-u-md-12-24{width:50%;*width:49.969%}.pure-u-md-13-24{width:54.1667%;*width:54.1357%}.pure-u-md-7-12,.pure-u-md-14-24{width:58.3333%;*width:58.3023%}.pure-u-md-3-5{width:60%;*width:59.969%}.pure-u-md-5-8,.pure-u-md-15-24{width:62.5%;*width:62.469%}.pure-u-md-2-3,.pure-u-md-16-24{width:66.6667%;*width:66.6357%}.pure-u-md-17-24{width:70.8333%;*width:70.8023%}.pure-u-md-3-4,.pure-u-md-18-24{width:75%;*width:74.969%}.pure-u-md-19-24{width:79.1667%;*width:79.1357%}.pure-u-md-4-5{width:80%;*width:79.969%}.pure-u-md-5-6,.pure-u-md-20-24{width:83.3333%;*width:83.3023%}.pure-u-md-7-8,.pure-u-md-21-24{width:87.5%;*width:87.469%}.pure-u-md-11-12,.pure-u-md-22-24{width:91.6667%;*width:91.6357%}.pure-u-md-23-24{width:95.8333%;*width:95.8023%}.pure-u-md-1,.pure-u-md-1-1,.pure-u-md-5-5,.pure-u-md-24-24{width:100%}}@media screen and (min-width:64em){.pure-u-lg-1,.pure-u-lg-1-1,.pure-u-lg-1-2,.pure-u-lg-1-3,.pure-u-lg-2-3,.pure-u-lg-1-4,.pure-u-lg-3-4,.pure-u-lg-1-5,.pure-u-lg-2-5,.pure-u-lg-3-5,.pure-u-lg-4-5,.pure-u-lg-5-5,.pure-u-lg-1-6,.pure-u-lg-5-6,.pure-u-lg-1-8,.pure-u-lg-3-8,.pure-u-lg-5-8,.pure-u-lg-7-8,.pure-u-lg-1-12,.pure-u-lg-5-12,.pure-u-lg-7-12,.pure-u-lg-11-12,.pure-u-lg-1-24,.pure-u-lg-2-24,.pure-u-lg-3-24,.pure-u-lg-4-24,.pure-u-lg-5-24,.pure-u-lg-6-24,.pure-u-lg-7-24,.pure-u-lg-8-24,.pure-u-lg-9-24,.pure-u-lg-10-24,.pure-u-lg-11-24,.pure-u-lg-12-24,.pure-u-lg-13-24,.pure-u-lg-14-24,.pure-u-lg-15-24,.pure-u-lg-16-24,.pure-u-lg-17-24,.pure-u-lg-18-24,.pure-u-lg-19-24,.pure-u-lg-20-24,.pure-u-lg-21-24,.pure-u-lg-22-24,.pure-u-lg-23-24,.pure-u-lg-24-24{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-lg-1-24{width:4.1667%;*width:4.1357%}.pure-u-lg-1-12,.pure-u-lg-2-24{width:8.3333%;*width:8.3023%}.pure-u-lg-1-8,.pure-u-lg-3-24{width:12.5%;*width:12.469%}.pure-u-lg-1-6,.pure-u-lg-4-24{width:16.6667%;*width:16.6357%}.pure-u-lg-1-5{width:20%;*width:19.969%}.pure-u-lg-5-24{width:20.8333%;*width:20.8023%}.pure-u-lg-1-4,.pure-u-lg-6-24{width:25%;*width:24.969%}.pure-u-lg-7-24{width:29.1667%;*width:29.1357%}.pure-u-lg-1-3,.pure-u-lg-8-24{width:33.3333%;*width:33.3023%}.pure-u-lg-3-8,.pure-u-lg-9-24{width:37.5%;*width:37.469%}.pure-u-lg-2-5{width:40%;*width:39.969%}.pure-u-lg-5-12,.pure-u-lg-10-24{width:41.6667%;*width:41.6357%}.pure-u-lg-11-24{width:45.8333%;*width:45.8023%}.pure-u-lg-1-2,.pure-u-lg-12-24{width:50%;*width:49.969%}.pure-u-lg-13-24{width:54.1667%;*width:54.1357%}.pure-u-lg-7-12,.pure-u-lg-14-24{width:58.3333%;*width:58.3023%}.pure-u-lg-3-5{width:60%;*width:59.969%}.pure-u-lg-5-8,.pure-u-lg-15-24{width:62.5%;*width:62.469%}.pure-u-lg-2-3,.pure-u-lg-16-24{width:66.6667%;*width:66.6357%}.pure-u-lg-17-24{width:70.8333%;*width:70.8023%}.pure-u-lg-3-4,.pure-u-lg-18-24{width:75%;*width:74.969%}.pure-u-lg-19-24{width:79.1667%;*width:79.1357%}.pure-u-lg-4-5{width:80%;*width:79.969%}.pure-u-lg-5-6,.pure-u-lg-20-24{width:83.3333%;*width:83.3023%}.pure-u-lg-7-8,.pure-u-lg-21-24{width:87.5%;*width:87.469%}.pure-u-lg-11-12,.pure-u-lg-22-24{width:91.6667%;*width:91.6357%}.pure-u-lg-23-24{width:95.8333%;*width:95.8023%}.pure-u-lg-1,.pure-u-lg-1-1,.pure-u-lg-5-5,.pure-u-lg-24-24{width:100%}}@media screen and (min-width:80em){.pure-u-xl-1,.pure-u-xl-1-1,.pure-u-xl-1-2,.pure-u-xl-1-3,.pure-u-xl-2-3,.pure-u-xl-1-4,.pure-u-xl-3-4,.pure-u-xl-1-5,.pure-u-xl-2-5,.pure-u-xl-3-5,.pure-u-xl-4-5,.pure-u-xl-5-5,.pure-u-xl-1-6,.pure-u-xl-5-6,.pure-u-xl-1-8,.pure-u-xl-3-8,.pure-u-xl-5-8,.pure-u-xl-7-8,.pure-u-xl-1-12,.pure-u-xl-5-12,.pure-u-xl-7-12,.pure-u-xl-11-12,.pure-u-xl-1-24,.pure-u-xl-2-24,.pure-u-xl-3-24,.pure-u-xl-4-24,.pure-u-xl-5-24,.pure-u-xl-6-24,.pure-u-xl-7-24,.pure-u-xl-8-24,.pure-u-xl-9-24,.pure-u-xl-10-24,.pure-u-xl-11-24,.pure-u-xl-12-24,.pure-u-xl-13-24,.pure-u-xl-14-24,.pure-u-xl-15-24,.pure-u-xl-16-24,.pure-u-xl-17-24,.pure-u-xl-18-24,.pure-u-xl-19-24,.pure-u-xl-20-24,.pure-u-xl-21-24,.pure-u-xl-22-24,.pure-u-xl-23-24,.pure-u-xl-24-24{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-xl-1-24{width:4.1667%;*width:4.1357%}.pure-u-xl-1-12,.pure-u-xl-2-24{width:8.3333%;*width:8.3023%}.pure-u-xl-1-8,.pure-u-xl-3-24{width:12.5%;*width:12.469%}.pure-u-xl-1-6,.pure-u-xl-4-24{width:16.6667%;*width:16.6357%}.pure-u-xl-1-5{width:20%;*width:19.969%}.pure-u-xl-5-24{width:20.8333%;*width:20.8023%}.pure-u-xl-1-4,.pure-u-xl-6-24{width:25%;*width:24.969%}.pure-u-xl-7-24{width:29.1667%;*width:29.1357%}.pure-u-xl-1-3,.pure-u-xl-8-24{width:33.3333%;*width:33.3023%}.pure-u-xl-3-8,.pure-u-xl-9-24{width:37.5%;*width:37.469%}.pure-u-xl-2-5{width:40%;*width:39.969%}.pure-u-xl-5-12,.pure-u-xl-10-24{width:41.6667%;*width:41.6357%}.pure-u-xl-11-24{width:45.8333%;*width:45.8023%}.pure-u-xl-1-2,.pure-u-xl-12-24{width:50%;*width:49.969%}.pure-u-xl-13-24{width:54.1667%;*width:54.1357%}.pure-u-xl-7-12,.pure-u-xl-14-24{width:58.3333%;*width:58.3023%}.pure-u-xl-3-5{width:60%;*width:59.969%}.pure-u-xl-5-8,.pure-u-xl-15-24{width:62.5%;*width:62.469%}.pure-u-xl-2-3,.pure-u-xl-16-24{width:66.6667%;*width:66.6357%}.pure-u-xl-17-24{width:70.8333%;*width:70.8023%}.pure-u-xl-3-4,.pure-u-xl-18-24{width:75%;*width:74.969%}.pure-u-xl-19-24{width:79.1667%;*width:79.1357%}.pure-u-xl-4-5{width:80%;*width:79.969%}.pure-u-xl-5-6,.pure-u-xl-20-24{width:83.3333%;*width:83.3023%}.pure-u-xl-7-8,.pure-u-xl-21-24{width:87.5%;*width:87.469%}.pure-u-xl-11-12,.pure-u-xl-22-24{width:91.6667%;*width:91.6357%}.pure-u-xl-23-24{width:95.8333%;*width:95.8023%}.pure-u-xl-1,.pure-u-xl-1-1,.pure-u-xl-5-5,.pure-u-xl-24-24{width:100%}}
--------------------------------------------------------------------------------
/css/simplemde.min.css:
--------------------------------------------------------------------------------
1 | /**
2 | * simplemde v1.8.1
3 | * Copyright Next Step Webs, Inc.
4 | * @link https://github.com/NextStepWebs/simplemde-markdown-editor
5 | * @license MIT
6 | */
7 | .CodeMirror{color:#000}.CodeMirror-lines{padding:4px 0}.CodeMirror pre{padding:0 4px}.CodeMirror-gutter-filler,.CodeMirror-scrollbar-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid #000;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-animate-fat-cursor{width:auto;border:0;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite;background-color:#7e7}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-ruler{border-left:1px solid #ccc;position:absolute}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta,.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-invalidchar,.cm-s-default .cm-error{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0f0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#f22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:#fff}.CodeMirror-scroll{overflow:scroll!important;margin-bottom:-30px;margin-right:-30px;padding-bottom:30px;height:100%;outline:0;position:relative}.CodeMirror-sizer{position:relative;border-right:30px solid transparent}.CodeMirror-gutter-filler,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-vscrollbar{position:absolute;z-index:6;display:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;margin-bottom:-30px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:0 0!important;border:none!important;-webkit-user-select:none;-moz-user-select:none;user-select:none}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror,.CodeMirror-scroll{min-height:300px}.CodeMirror pre{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:0 0;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent}.CodeMirror-wrap pre{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;overflow:auto}.CodeMirror-code{outline:0}.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber,.CodeMirror-scroll,.CodeMirror-sizer{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.CodeMirror-focused div.CodeMirror-cursors,div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected,.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background:#ffa;background:rgba(255,255,0,.4)}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:''}span.CodeMirror-selectedtext{background:0 0}.CodeMirror{height:auto;border:1px solid #ddd;border-bottom-left-radius:4px;border-bottom-right-radius:4px;padding:10px;font:inherit;z-index:1}.CodeMirror-fullscreen{background:#fff;position:fixed!important;top:50px;left:0;right:0;bottom:0;height:auto;z-index:9}.CodeMirror-sided{width:50%!important}.editor-toolbar{position:relative;opacity:.6;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;padding:0 10px;border-top:1px solid #bbb;border-left:1px solid #bbb;border-right:1px solid #bbb;border-top-left-radius:4px;border-top-right-radius:4px}.editor-toolbar:after,.editor-toolbar:before{display:block;content:' ';height:1px}.editor-toolbar:before{margin-bottom:8px}.editor-toolbar:after{margin-top:8px}.editor-toolbar:hover,.editor-wrapper input.title:focus,.editor-wrapper input.title:hover{opacity:.8}.editor-toolbar.fullscreen{width:100%;height:50px;overflow-x:auto;overflow-y:hidden;white-space:nowrap;padding-top:10px;padding-bottom:10px;box-sizing:border-box;background:#fff;border:0;position:fixed;top:0;left:0;opacity:1;z-index:9}.editor-toolbar.fullscreen::before{width:20px;height:50px;background:-moz-linear-gradient(left,rgba(255,255,255,1) 0,rgba(255,255,255,0) 100%);background:-webkit-gradient(linear,left top,right top,color-stop(0,rgba(255,255,255,1)),color-stop(100%,rgba(255,255,255,0)));background:-webkit-linear-gradient(left,rgba(255,255,255,1) 0,rgba(255,255,255,0) 100%);background:-o-linear-gradient(left,rgba(255,255,255,1) 0,rgba(255,255,255,0) 100%);background:-ms-linear-gradient(left,rgba(255,255,255,1) 0,rgba(255,255,255,0) 100%);background:linear-gradient(to right,rgba(255,255,255,1) 0,rgba(255,255,255,0) 100%);position:fixed;top:0;left:0;margin:0;padding:0}.editor-toolbar.fullscreen::after{width:20px;height:50px;background:-moz-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,1) 100%);background:-webkit-gradient(linear,left top,right top,color-stop(0,rgba(255,255,255,0)),color-stop(100%,rgba(255,255,255,1)));background:-webkit-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,1) 100%);background:-o-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,1) 100%);background:-ms-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,1) 100%);background:linear-gradient(to right,rgba(255,255,255,0) 0,rgba(255,255,255,1) 100%);position:fixed;top:0;right:0;margin:0;padding:0}.editor-toolbar a{display:inline-block;text-align:center;text-decoration:none!important;color:#2c3e50!important;width:30px;height:30px;margin:0;border:1px solid transparent;border-radius:3px;cursor:pointer}.editor-toolbar a.active,.editor-toolbar a:hover{background:#fcfcfc;border-color:#95a5a6}.editor-toolbar a:before{line-height:30px}.editor-toolbar i.separator{display:inline-block;width:0;border-left:1px solid #d9d9d9;border-right:1px solid #fff;color:transparent;text-indent:-10px;margin:0 6px}.editor-toolbar a.fa-header-x:after{font-family:Arial,"Helvetica Neue",Helvetica,sans-serif;font-size:65%;vertical-align:text-bottom;position:relative;top:2px}.editor-toolbar a.fa-header-1:after{content:"1"}.editor-toolbar a.fa-header-2:after{content:"2"}.editor-toolbar a.fa-header-3:after{content:"3"}.editor-toolbar a.fa-header-bigger:after{content:"▲"}.editor-toolbar a.fa-header-smaller:after{content:"▼"}.editor-toolbar.disabled-for-preview a:not(.no-disable){pointer-events:none;background:#fff;border-color:transparent;text-shadow:inherit}@media only screen and (max-width:700px){.editor-toolbar a.no-mobile{display:none}}.editor-statusbar{padding:8px 10px;font-size:12px;color:#959694;text-align:right}.editor-statusbar span{display:inline-block;min-width:4em;margin-left:1em}.editor-preview,.editor-preview-side{padding:10px;background:#fafafa;overflow:auto;display:none;box-sizing:border-box}.editor-statusbar .lines:before{content:'lines: '}.editor-statusbar .words:before{content:'words: '}.editor-preview{position:absolute;width:100%;height:100%;top:0;left:0;z-index:2}.editor-preview-side{position:fixed;bottom:0;width:50%;top:50px;right:0;z-index:9999;border:1px solid #ddd}.editor-preview-active,.editor-preview-active-side{display:block}.editor-preview-side>p,.editor-preview>p{margin-top:0}.editor-preview pre,.editor-preview-side pre{background:#eee;margin-bottom:10px}.editor-preview table td,.editor-preview table th,.editor-preview-side table td,.editor-preview-side table th{border:1px solid #ddd;padding:5px}.CodeMirror .CodeMirror-code .cm-tag{color:#63a35c}.CodeMirror .CodeMirror-code .cm-attribute{color:#795da3}.CodeMirror .CodeMirror-code .cm-string{color:#183691}.CodeMirror .CodeMirror-selected{background:#d9d9d9}.CodeMirror .CodeMirror-code .cm-header-1{font-size:200%;line-height:200%}.CodeMirror .CodeMirror-code .cm-header-2{font-size:160%;line-height:160%}.CodeMirror .CodeMirror-code .cm-header-3{font-size:125%;line-height:125%}.CodeMirror .CodeMirror-code .cm-header-4{font-size:110%;line-height:110%}.CodeMirror .CodeMirror-code .cm-comment{background:rgba(0,0,0,.05);border-radius:2px}.CodeMirror .CodeMirror-code .cm-link{color:#7f8c8d}.CodeMirror .CodeMirror-code .cm-url{color:#aab2b3}.CodeMirror .CodeMirror-code .cm-strikethrough{text-decoration:line-through}.CodeMirror .cm-spell-error:not(.cm-url):not(.cm-comment):not(.cm-tag):not(.cm-word){background:rgba(255,0,0,.15)}
--------------------------------------------------------------------------------
/css/pure-min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | Pure v0.6.0
3 | Copyright 2014 Yahoo! Inc. All rights reserved.
4 | Licensed under the BSD License.
5 | https://github.com/yahoo/pure/blob/master/LICENSE.md
6 | */
7 | /*!
8 | normalize.css v^3.0 | MIT License | git.io/normalize
9 | Copyright (c) Nicolas Gallagher and Jonathan Neal
10 | */
11 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}.hidden,[hidden]{display:none!important}.pure-img{max-width:100%;height:auto;display:block}.pure-g{letter-spacing:-.31em;*letter-spacing:normal;*word-spacing:-.43em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:-webkit-flex;-webkit-flex-flow:row wrap;display:-ms-flexbox;-ms-flex-flow:row wrap;-ms-align-content:flex-start;-webkit-align-content:flex-start;align-content:flex-start}.opera-only :-o-prefocus,.pure-g{word-spacing:-.43em}.pure-u{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-g [class *="pure-u"]{font-family:sans-serif}.pure-u-1,.pure-u-1-1,.pure-u-1-2,.pure-u-1-3,.pure-u-2-3,.pure-u-1-4,.pure-u-3-4,.pure-u-1-5,.pure-u-2-5,.pure-u-3-5,.pure-u-4-5,.pure-u-5-5,.pure-u-1-6,.pure-u-5-6,.pure-u-1-8,.pure-u-3-8,.pure-u-5-8,.pure-u-7-8,.pure-u-1-12,.pure-u-5-12,.pure-u-7-12,.pure-u-11-12,.pure-u-1-24,.pure-u-2-24,.pure-u-3-24,.pure-u-4-24,.pure-u-5-24,.pure-u-6-24,.pure-u-7-24,.pure-u-8-24,.pure-u-9-24,.pure-u-10-24,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24{display:inline-block;*display:inline;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-u-1-24{width:4.1667%;*width:4.1357%}.pure-u-1-12,.pure-u-2-24{width:8.3333%;*width:8.3023%}.pure-u-1-8,.pure-u-3-24{width:12.5%;*width:12.469%}.pure-u-1-6,.pure-u-4-24{width:16.6667%;*width:16.6357%}.pure-u-1-5{width:20%;*width:19.969%}.pure-u-5-24{width:20.8333%;*width:20.8023%}.pure-u-1-4,.pure-u-6-24{width:25%;*width:24.969%}.pure-u-7-24{width:29.1667%;*width:29.1357%}.pure-u-1-3,.pure-u-8-24{width:33.3333%;*width:33.3023%}.pure-u-3-8,.pure-u-9-24{width:37.5%;*width:37.469%}.pure-u-2-5{width:40%;*width:39.969%}.pure-u-5-12,.pure-u-10-24{width:41.6667%;*width:41.6357%}.pure-u-11-24{width:45.8333%;*width:45.8023%}.pure-u-1-2,.pure-u-12-24{width:50%;*width:49.969%}.pure-u-13-24{width:54.1667%;*width:54.1357%}.pure-u-7-12,.pure-u-14-24{width:58.3333%;*width:58.3023%}.pure-u-3-5{width:60%;*width:59.969%}.pure-u-5-8,.pure-u-15-24{width:62.5%;*width:62.469%}.pure-u-2-3,.pure-u-16-24{width:66.6667%;*width:66.6357%}.pure-u-17-24{width:70.8333%;*width:70.8023%}.pure-u-3-4,.pure-u-18-24{width:75%;*width:74.969%}.pure-u-19-24{width:79.1667%;*width:79.1357%}.pure-u-4-5{width:80%;*width:79.969%}.pure-u-5-6,.pure-u-20-24{width:83.3333%;*width:83.3023%}.pure-u-7-8,.pure-u-21-24{width:87.5%;*width:87.469%}.pure-u-11-12,.pure-u-22-24{width:91.6667%;*width:91.6357%}.pure-u-23-24{width:95.8333%;*width:95.8023%}.pure-u-1,.pure-u-1-1,.pure-u-5-5,.pure-u-24-24{width:100%}.pure-button{display:inline-block;zoom:1;line-height:normal;white-space:nowrap;vertical-align:middle;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button{font-family:inherit;font-size:100%;padding:.5em 1em;color:#444;color:rgba(0,0,0,.8);border:1px solid #999;border:0 rgba(0,0,0,0);background-color:#E6E6E6;text-decoration:none;border-radius:2px}.pure-button-hover,.pure-button:hover,.pure-button:focus{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#1a000000', GradientType=0);background-image:-webkit-gradient(linear,0 0,0 100%,from(transparent),color-stop(40%,rgba(0,0,0,.05)),to(rgba(0,0,0,.1)));background-image:-webkit-linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1));background-image:-moz-linear-gradient(top,rgba(0,0,0,.05) 0,rgba(0,0,0,.1));background-image:-o-linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1));background-image:linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1))}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;border-color:#000\9}.pure-button[disabled],.pure-button-disabled,.pure-button-disabled:hover,.pure-button-disabled:focus,.pure-button-disabled:active{border:0;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);filter:alpha(opacity=40);-khtml-opacity:.4;-moz-opacity:.4;opacity:.4;cursor:not-allowed;box-shadow:none}.pure-button-hidden{display:none}.pure-button::-moz-focus-inner{padding:0;border:0}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{background-color:#0078e7;color:#fff}.pure-form input[type=text],.pure-form input[type=password],.pure-form input[type=email],.pure-form input[type=url],.pure-form input[type=date],.pure-form input[type=month],.pure-form input[type=time],.pure-form input[type=datetime],.pure-form input[type=datetime-local],.pure-form input[type=week],.pure-form input[type=number],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=color],.pure-form select,.pure-form textarea{padding:.5em .6em;display:inline-block;border:1px solid #ccc;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;vertical-align:middle;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.pure-form input:not([type]){padding:.5em .6em;display:inline-block;border:1px solid #ccc;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.pure-form input[type=color]{padding:.2em .5em}.pure-form input[type=text]:focus,.pure-form input[type=password]:focus,.pure-form input[type=email]:focus,.pure-form input[type=url]:focus,.pure-form input[type=date]:focus,.pure-form input[type=month]:focus,.pure-form input[type=time]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=week]:focus,.pure-form input[type=number]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=color]:focus,.pure-form select:focus,.pure-form textarea:focus{outline:0;border-color:#129FEA}.pure-form input:not([type]):focus{outline:0;border-color:#129FEA}.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus,.pure-form input[type=checkbox]:focus{outline:thin solid #129FEA;outline:1px auto #129FEA}.pure-form .pure-checkbox,.pure-form .pure-radio{margin:.5em 0;display:block}.pure-form input[type=text][disabled],.pure-form input[type=password][disabled],.pure-form input[type=email][disabled],.pure-form input[type=url][disabled],.pure-form input[type=date][disabled],.pure-form input[type=month][disabled],.pure-form input[type=time][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=week][disabled],.pure-form input[type=number][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=color][disabled],.pure-form select[disabled],.pure-form textarea[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input:not([type])[disabled]{cursor:not-allowed;background-color:#eaeded;color:#cad2d3}.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{background-color:#eee;color:#777;border-color:#ccc}.pure-form input:focus:invalid,.pure-form textarea:focus:invalid,.pure-form select:focus:invalid{color:#b94a48;border-color:#e9322d}.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus,.pure-form input[type=checkbox]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{height:2.25em;border:1px solid #ccc;background-color:#fff}.pure-form select[multiple]{height:auto}.pure-form label{margin:.5em 0 .2em}.pure-form fieldset{margin:0;padding:.35em 0 .75em;border:0}.pure-form legend{display:block;width:100%;padding:.3em 0;margin-bottom:.3em;color:#333;border-bottom:1px solid #e5e5e5}.pure-form-stacked input[type=text],.pure-form-stacked input[type=password],.pure-form-stacked input[type=email],.pure-form-stacked input[type=url],.pure-form-stacked input[type=date],.pure-form-stacked input[type=month],.pure-form-stacked input[type=time],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=week],.pure-form-stacked input[type=number],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=color],.pure-form-stacked input[type=file],.pure-form-stacked select,.pure-form-stacked label,.pure-form-stacked textarea{display:block;margin:.25em 0}.pure-form-stacked input:not([type]){display:block;margin:.25em 0}.pure-form-aligned input,.pure-form-aligned textarea,.pure-form-aligned select,.pure-form-aligned .pure-help-inline,.pure-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.pure-form-aligned textarea{vertical-align:top}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;display:inline-block;vertical-align:middle;width:10em;margin:0 1em 0 0}.pure-form-aligned .pure-controls{margin:1.5em 0 0 11em}.pure-form input.pure-input-rounded,.pure-form .pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input,.pure-form .pure-group textarea{display:block;padding:10px;margin:0 0 -1px;border-radius:0;position:relative;top:-1px}.pure-form .pure-group input:focus,.pure-form .pure-group textarea:focus{z-index:3}.pure-form .pure-group input:first-child,.pure-form .pure-group textarea:first-child{top:1px;border-radius:4px 4px 0 0;margin:0}.pure-form .pure-group input:first-child:last-child,.pure-form .pure-group textarea:first-child:last-child{top:1px;border-radius:4px;margin:0}.pure-form .pure-group input:last-child,.pure-form .pure-group textarea:last-child{top:-2px;border-radius:0 0 4px 4px;margin:0}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-1{width:100%}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-2{width:50%}.pure-form .pure-input-1-3{width:33%}.pure-form .pure-input-1-4{width:25%}.pure-form .pure-help-inline,.pure-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:.875em}.pure-form-message{display:block;color:#666;font-size:.875em}@media only screen and (max-width :480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input:not([type]),.pure-form input[type=text],.pure-form input[type=password],.pure-form input[type=email],.pure-form input[type=url],.pure-form input[type=date],.pure-form input[type=month],.pure-form input[type=time],.pure-form input[type=datetime],.pure-form input[type=datetime-local],.pure-form input[type=week],.pure-form input[type=number],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=color],.pure-form label{margin-bottom:.3em;display:block}.pure-group input:not([type]),.pure-group input[type=text],.pure-group input[type=password],.pure-group input[type=email],.pure-group input[type=url],.pure-group input[type=date],.pure-group input[type=month],.pure-group input[type=time],.pure-group input[type=datetime],.pure-group input[type=datetime-local],.pure-group input[type=week],.pure-group input[type=number],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=color]{margin-bottom:0}.pure-form-aligned .pure-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.pure-form-aligned .pure-controls{margin:1.5em 0 0}.pure-form .pure-help-inline,.pure-form-message-inline,.pure-form-message{display:block;font-size:.75em;padding:.2em 0 .8em}}.pure-menu{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.pure-menu-fixed{position:fixed;left:0;top:0;z-index:3}.pure-menu-list,.pure-menu-item{position:relative}.pure-menu-list{list-style:none;margin:0;padding:0}.pure-menu-item{padding:0;margin:0;height:100%}.pure-menu-link,.pure-menu-heading{display:block;text-decoration:none;white-space:nowrap}.pure-menu-horizontal{width:100%;white-space:nowrap}.pure-menu-horizontal .pure-menu-list{display:inline-block}.pure-menu-horizontal .pure-menu-item,.pure-menu-horizontal .pure-menu-heading,.pure-menu-horizontal .pure-menu-separator{display:inline-block;*display:inline;zoom:1;vertical-align:middle}.pure-menu-item .pure-menu-item{display:block}.pure-menu-children{display:none;position:absolute;left:100%;top:0;margin:0;padding:0;z-index:3}.pure-menu-horizontal .pure-menu-children{left:0;top:auto;width:inherit}.pure-menu-allow-hover:hover>.pure-menu-children,.pure-menu-active>.pure-menu-children{display:block;position:absolute}.pure-menu-has-children>.pure-menu-link:after{padding-left:.5em;content:"\25B8";font-size:small}.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after{content:"\25BE"}.pure-menu-scrollable{overflow-y:scroll;overflow-x:hidden}.pure-menu-scrollable .pure-menu-list{display:block}.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list{display:inline-block}.pure-menu-horizontal.pure-menu-scrollable{white-space:nowrap;overflow-y:hidden;overflow-x:auto;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;padding:.5em 0}.pure-menu-horizontal.pure-menu-scrollable::-webkit-scrollbar{display:none}.pure-menu-separator{background-color:#ccc;height:1px;margin:.3em 0}.pure-menu-horizontal .pure-menu-separator{width:1px;height:1.3em;margin:0 .3em}.pure-menu-heading{text-transform:uppercase;color:#565d64}.pure-menu-link{color:#777}.pure-menu-children{background-color:#fff}.pure-menu-link,.pure-menu-disabled,.pure-menu-heading{padding:.5em 1em}.pure-menu-disabled{opacity:.5}.pure-menu-disabled .pure-menu-link:hover{background-color:transparent}.pure-menu-active>.pure-menu-link,.pure-menu-link:hover,.pure-menu-link:focus{background-color:#eee}.pure-menu-selected .pure-menu-link,.pure-menu-selected .pure-menu-link:visited{color:#000}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.pure-table td,.pure-table th{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:.5em 1em}.pure-table td:first-child,.pure-table th:first-child{border-left-width:0}.pure-table thead{background-color:#e0e0e0;color:#000;text-align:left;vertical-align:bottom}.pure-table td{background-color:transparent}.pure-table-odd td{background-color:#f2f2f2}.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-bordered tbody>tr:last-child>td{border-bottom-width:0}.pure-table-horizontal td,.pure-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #cbcbcb}.pure-table-horizontal tbody>tr:last-child>td{border-bottom-width:0}
--------------------------------------------------------------------------------
/css/blog.css:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 | /* CSS Document */
3 |
4 | @font-face {
5 | font-family: 'Roboto';
6 | font-style: normal;
7 | font-weight: 300;
8 | src: url('fonts/roboto-light.eot') format('embedded-opentype'),url('fonts/roboto-light.woff') format('woff'), url('fonts/roboto-light.ttf') format('truetype');
9 | }
10 | @font-face {
11 | font-family: 'Roboto';
12 | font-style: normal;
13 | font-weight: 400;
14 | src: url('fonts/roboto-regular.eot') format('embedded-opentype'),url('fonts/roboto-regular.woff') format('woff'), url('fonts/roboto-regular.ttf') format('truetype');
15 | }
16 |
17 | html {
18 | font-family: 'Roboto', sans-serif;
19 | }
20 |
21 | * {
22 | -webkit-box-sizing: border-box;
23 | -moz-box-sizing: border-box;
24 | box-sizing: border-box;
25 | }
26 |
27 | a {
28 | text-decoration: none;
29 | color: #3D92C9;
30 | }
31 | a:hover,
32 | a:focus {
33 | text-decoration: underline;
34 | }
35 |
36 | h3 {
37 | font-weight: 100;
38 | }
39 |
40 | .separator {
41 | position: relative;
42 | margin: 35px 0;
43 | height: 1px;
44 | background: #ccc;
45 | background: -webkit-gradient(linear, 0 0, 100% 0, from(#fff), to(#fff), color-stop(50%, #ccc));
46 | }
47 |
48 | .link {
49 | color: inherit;
50 | }
51 |
52 | /* NOTIFICATIONS */
53 | .note {
54 | position: fixed;
55 | z-index: 101;
56 | top: 0;
57 | left: 0;
58 | right: 0;
59 | background: #eee;
60 | color: #fff;
61 | text-align: center;
62 | font-size: 1.5em;
63 | font-weight: 200;
64 | line-height: 2em;
65 | overflow-y: hidden;
66 | -webkit-box-shadow: 0 0 5px black;
67 | -moz-box-shadow: 0 0 5px black;
68 | box-shadow: 0 0 5px black;
69 | transition: opacity 2s linear;
70 | }
71 |
72 | /* LAYOUT CSS */
73 | .pure-img-responsive {
74 | max-width: 100%;
75 | height: auto;
76 | }
77 |
78 | #layout {
79 | padding: 0;
80 | display: flex;
81 | justify-content: center;
82 | }
83 |
84 | .sidebar {
85 | background: #333;
86 | color: #fff;
87 | }
88 |
89 | .plume-logo {
90 | height: 1em;
91 | }
92 |
93 | .blog-info {
94 | margin-top: 2em;
95 | }
96 |
97 | .blog-title,
98 | .blog-tagline,
99 | .blog-picture {
100 | margin: 0;
101 | }
102 | /*.blog-title {
103 | color: #333;
104 | font-weight: 300;
105 | padding: 0.2em;
106 | }
107 |
108 | .blog-tagline {
109 | font-weight: 300;
110 | color: #777;
111 | }*/
112 | .blog-picture {
113 | height: 100px;
114 | width: auto;
115 | }
116 |
117 | /* LOADING */
118 | .loading {
119 | position: relative;
120 | padding: 50px;
121 | }
122 | .loading>p {
123 | position: relative;
124 | top: 50px;
125 | color: #777;
126 | }
127 | .loadingbox {
128 | width: 50px;
129 | height: 50px;
130 | margin: auto;
131 | position: absolute;
132 | left: 0;
133 | right: 0;
134 | top: 0;
135 | bottom: 0;
136 | }
137 | .loadingbox:before {
138 | content: '';
139 | width: 50px;
140 | height: 5px;
141 | background: #000;
142 | opacity: 0.1;
143 | position: absolute;
144 | top: 59px;
145 | left: 0;
146 | border-radius: 50%;
147 | animation: shadow .5s linear infinite;
148 | }
149 | .loadingbox:after {
150 | content: '';
151 | width: 50px;
152 | height: 50px;
153 | background: #B0CADB;
154 | animation: animate .5s linear infinite;
155 | position: absolute;
156 | top: 0;
157 | left: 0;
158 | border-radius: 3px;
159 | }
160 | @keyframes animate {
161 | 17% {
162 | border-bottom-right-radius: 3px;
163 | }
164 | 25% {
165 | transform: translateY(9px) rotate(22.5deg);
166 | }
167 | 50% {
168 | transform: translateY(18px) scale(1, 0.9) rotate(45deg);
169 | border-bottom-right-radius: 40px;
170 | }
171 | 75% {
172 | transform: translateY(9px) rotate(67.5deg);
173 | }
174 | 100% {
175 | transform: translateY(0) rotate(90deg);
176 | }
177 | }
178 | @keyframes shadow {
179 | 0%,
180 | 100% {
181 | transform: scale(1, 1);
182 | }
183 | 50% {
184 | transform: scale(1.2, 1);
185 | }
186 | }
187 |
188 | /* EDITOR */
189 | .CodeMirror, .CodeMirror-scroll {
190 | min-height: 200px;
191 | }
192 | .editor {
193 | padding-top: 1em;
194 | color: #444;
195 | }
196 | .editor-title {
197 | font-size: 2em;
198 | min-width: 100%;
199 | max-width: 100%;
200 | padding: 0.5em 0;
201 | border-radius: 3px;
202 | outline: none;
203 | border: 0;
204 | border-bottom: 1px dotted #ccc;
205 | }
206 | .editor-title:focus {
207 | background: #ffc;
208 | padding-left: 10px;
209 | }
210 | .editor-meta {
211 | padding-top: 5px;
212 | }
213 | .editor-tags a {
214 | margin-left: 5px;
215 | color: #ccc;
216 | cursor: pointer;
217 | }
218 | .editor-add-tag {
219 | width: 70px;
220 | border: 0;
221 | border-bottom: 1px dotted #777;
222 | }
223 | span.editor-title:empty::before {
224 | content: 'Title';
225 | color: #ccc;
226 | }
227 | span.editor-title:empty:focus::before {
228 | content: 'Title';
229 | color: #777;
230 | }
231 | a.editor-author, a.editor-author:visited {
232 | color: #3D92C9;
233 | }
234 | .editor header {
235 | margin-bottom: 10px;
236 | }
237 | .editor footer {
238 | margin-top: 10px;
239 | }
240 |
241 | .editor-body {
242 | margin-bottom: 1em;
243 | border-radius: 3px;
244 | outline: none;
245 | border: 1px solid #E6E6E6;
246 | font-size: 1em;
247 | min-height: 100px;
248 | color: #777;
249 | }
250 |
251 | .small {
252 | font-size: 50%;
253 | }
254 |
255 | .button-xsmall {
256 | font-size: 50%;
257 | }
258 | .button {
259 | display: inline-block;
260 | padding: 20px 10px;
261 | margin-right: 5px;
262 | background: #fff;
263 | border-radius: 4px;
264 | font-weight: normal;
265 | font-size: 14px;
266 | color: #777;
267 | letter-spacing: 1px;
268 | line-height: 1px;
269 | text-transform: uppercase;
270 | border: 1px solid #777;
271 | }
272 | .success {
273 | background: #1CB841!important;
274 | color: #fff;
275 | border: 1px solid #1CB841;
276 | }
277 | .danger {
278 | background: #CA3C3C!important;
279 | color: #fff;
280 | border: 0;
281 | }
282 | .danger-text {
283 | color: #CA3C3C!important;
284 | }
285 |
286 | .clickable {
287 | cursor: pointer;
288 | }
289 |
290 | /* DROPDOWN */
291 | .pure-menu-children {
292 | list-style: none;
293 | position: absolute!important;
294 | left: initial;
295 | top: initial;
296 | margin: 0;
297 | padding: 0;
298 | width: 70px;
299 | z-index: 3;
300 | }
301 | .pure-menu-has-children>.pure-menu-link:after {
302 | content: "\25BE";
303 | font-size: 80%;
304 | padding-left: 0.5em;
305 | }
306 |
307 | /* COLOR PICKER */
308 | .color-0 { background: #999!important; }
309 | .color-1 { background: #ffbf00!important; }
310 | .color-2 { background: #df2d4f!important; }
311 | .color-3 { background: #4d85d1!important; }
312 | .color-4 { background: #5aba59!important; }
313 | .color-5 { background: #8156a7!important; }
314 |
315 | /* ACTION BUTTONS */
316 |
317 | .action-button {
318 | background-color: #fff;
319 | color: #777;
320 | letter-spacing: 0.05em;
321 | text-transform: uppercase;
322 | font-size: 60%;
323 | padding: 1em 1.5em;
324 | text-decoration: none;
325 | border: 1px solid #777;
326 | border-radius: 2px;
327 | margin-right: 5px;
328 | cursor: pointer;
329 | }
330 | .action-button:hover {
331 | text-decoration: none;
332 | }
333 | .action-button img {
334 | position: relative;
335 | height: 20px;
336 | top: 7px;
337 | }
338 |
339 | .dialog {
340 | width: 300px;
341 | position: fixed;
342 | padding: 2em;
343 | text-align: center;
344 | font-weight: 200;
345 | background: #fff;
346 | z-index: 10;
347 | top: 50%;
348 | left: 50%;
349 | border: 1px solid #ccc;
350 | box-shadow: 0 0 4px #eee;
351 | border-radius: 5px;
352 | -webkit-transform: translateX(-50%) translateY(-50%);
353 | -moz-transform: translateX(-50%) translateY(-50%);
354 | -ms-transform: translateX(-50%) translateY(-50%);
355 | transform: translateX(-50%) translateY(-50%);
356 | }
357 | .dialog p {
358 | width: 100%;
359 | }
360 | .dialog footer {
361 | position: relative;
362 | margin-top: 30px;
363 | }
364 |
365 | .post-edit {
366 | background: #129FEA;
367 | height: 25px;
368 | width: 25px;
369 | -webkit-mask: url(../img/logo.svg) no-repeat 50% 50%;
370 | mask: url(../img/logo.svg) no-repeat 50% 50%;
371 | }
372 | .post-title {
373 | font-size: 1.7em!important;
374 | font-weight: bold;
375 | color: #333;
376 | margin-top: 1.5em;
377 | }
378 |
379 | .post-title>a,.post-title>a:hover,.post-title>a:visited {
380 | color: #333;
381 | text-decoration: none;
382 | }
383 | .post-title>a:hover {
384 | box-shadow: inset 0 0px 0 white, inset 0 -1px 0 #333;
385 | }
386 | .post-author {
387 | /*font-size: 1.2em;*/
388 | }
389 | .post-author:hover, .post-author:visited {
390 | color: rgb(61, 146, 201);
391 | }
392 | .post-avatar {
393 | border-radius: 50px;
394 | float: left;
395 | height: 40px;
396 | width: 40px;
397 | margin-right: 1em;
398 | }
399 | .post-date {
400 | font-weight: 200;
401 | }
402 | .post-body {
403 | color: #444;
404 | line-height: 1.6em;
405 | font-weight: 200;
406 | }
407 | .post-body>a,.post-body>a:hover,.post-body>a:visited {
408 | color: #3D92C9;
409 | text-decoration: none;
410 | }
411 | .post-body img {
412 | max-width: 100%;
413 | max-height: 100%;
414 | }
415 | .post-meta {
416 | color: #999;
417 | font-size: 0.8em;
418 | line-height: 1.3em;
419 | margin: 0;
420 | }
421 |
422 | .post-category {
423 | margin: 0 0.1em;
424 | padding: 0.3em 1em;
425 | color: #fff!important;
426 | background: #999;
427 | font-size: 80%;
428 | cursor: pointer;
429 | }
430 |
431 | .post-images {
432 | margin: 1em 0;
433 | }
434 | .post-image-meta {
435 | margin-top: -3.5em;
436 | margin-left: 1em;
437 | color: #fff;
438 | text-shadow: 0 1px 1px #333;
439 | }
440 |
441 | .fade-out {
442 | background-color: rgba(238,212,119,0.25);
443 | transition: background-color 1.5s linear;
444 | -moz-transition: background-color 1.5s linear;
445 | -webkit-transition: background-color 1.5s linear;
446 | -ms-transition: background-color 1.5s linear;
447 | }
448 |
449 | .fade-bottom {
450 | position: relative;
451 | bottom: 4em;
452 | height: 4em;
453 | margin-bottom: -2em;
454 | padding-top: 4em;
455 | color: #777;
456 | background: -webkit-linear-gradient(
457 | rgba(255, 255, 255, 0) 0%,
458 | rgba(255, 255, 255, 1) 100%
459 | );
460 | background-image: -moz-linear-gradient(
461 | rgba(255, 255, 255, 0) 0%,
462 | rgba(255, 255, 255, 1) 100%
463 | );
464 | background-image: -o-linear-gradient(
465 | rgba(255, 255, 255, 0) 0%,
466 | rgba(255, 255, 255, 1) 100%
467 | );
468 | background-image: linear-gradient(
469 | rgba(255, 255, 255, 0) 0%,
470 | rgba(255, 255, 255, 1) 100%
471 | );
472 | background-image: -ms-linear-gradient(
473 | rgba(255, 255, 255, 0) 0%,
474 | rgba(255, 255, 255, 1) 100%
475 | );
476 | }
477 |
478 | .less {
479 | overflow: hidden;
480 | text-overflow: ellipsis;
481 | height: 300px!important;
482 | }
483 |
484 | pre {
485 | background: #F9F9F9;
486 | font-size: 1rem;
487 | padding: 0.5rem;
488 | }
489 |
490 | .footer {
491 | text-align: center;
492 | padding: 1em 0;
493 | }
494 | .footer ul {
495 | -webkit-padding-start: 0px;
496 | }
497 | .footer a {
498 | color: #777;
499 | font-size: 80%;
500 | }
501 | .footer .pure-menu a:hover,
502 | .footer .pure-menu a:focus {
503 | background: none;
504 | }
505 |
506 | .dark {
507 | color: #333!important;
508 | }
509 | .grey {
510 | color: #999;
511 | }
512 |
513 | .hidden {
514 | display: none;
515 | }
516 |
517 | .inline-block {
518 | display: inline-block;
519 | }
520 |
521 | .fixed-nav {
522 | margin: 0;
523 | position: fixed;
524 | top: 0;
525 | left: 0;
526 | width: 100%;
527 | -webkit-transform: translateY(0);
528 | -ms-transform: translateY(0);
529 | transform: translateY(0);
530 | }
531 |
532 | .spacer {
533 | height: 1em;
534 | }
535 |
536 | .float-right {
537 | float: right;
538 | }
539 |
540 | .float-left {
541 | float: left;
542 | }
543 |
544 | .center-text {
545 | text-align: center;
546 | }
547 |
548 | .center {
549 | position: relative;
550 | top: 50%;
551 | transform: translateY(-50%);
552 | }
553 |
554 | .underline:hover {
555 | text-decoration: underline;
556 | }
557 |
558 | .no-decoration, .no-decoration:hover, .no-decoration:visited {
559 | text-decoration: none;
560 | }
561 |
562 | .pure-img-responsive {
563 | max-width: 100%;
564 | height: auto;
565 | }
566 |
567 | .overlay {
568 | visibility: hidden;
569 | position: absolute;
570 | left: 0px;
571 | top: 0px;
572 | width:100%;
573 | height:100%;
574 | font-weight: 200;
575 | background: rgba(0, 0, 0, 0.6);
576 | z-index: 1000;
577 | }
578 |
579 | .overlay-text {
580 | min-width:300px;
581 | margin: 10% 5% auto;
582 | background-color: #fff;
583 | border:1px solid #ccc;
584 | padding:15px 15px 40px 15px;
585 | }
586 |
587 | .content {
588 | margin: 0 auto;
589 | padding: 0 1em;
590 | line-height: 1.6em;
591 | position: relative;
592 | top: 0;
593 | right: 0;
594 | -moz-transition: all 300ms;
595 | -o-transition: all 300ms;
596 | -webkit-transition: all 300ms;
597 | transition: all 300ms;
598 | }
599 | .content h1 {
600 | line-height: 1em;
601 | font-size: 1.3em;
602 | }
603 |
604 | .content h2 {
605 | line-height: 1em;
606 | font-size: 1.1em;
607 | }
608 |
609 | .header {
610 | margin: 0;
611 | color: #333;
612 | text-align: center;
613 | padding: 2em 2em 0 2em;
614 | top: auto;
615 | }
616 | .header h1 {
617 | margin: 0.2em 0;
618 | font-size: 2.5em;
619 | font-weight: 300;
620 | line-height: 0.8em;
621 | }
622 | .header h2 {
623 | font-weight: 300;
624 | color: #999;
625 | padding: 0;
626 | margin-top: 0;
627 | }
628 |
629 | /* NEW LAYOUT FOR MENU */
630 | nav#global-nav {
631 | background-color: #333;
632 | bottom: 0;
633 | max-width: 220px;
634 | overflow: auto;
635 | position: fixed;
636 | top: 0;
637 | left: -220px;
638 | width: 100%;
639 | z-index: 9;
640 | -moz-transition: all 300ms;
641 | -o-transition: all 300ms;
642 | -webkit-transition: all 300ms;
643 | transition: all 300ms;
644 | }
645 | body.active nav#global-nav {
646 | -moz-transform: translateX(220px);
647 | -ms-transform: translateX(220px);
648 | -webkit-transform: translateX(220px);
649 | transform: translateX(220px);
650 | }
651 | nav#global-nav ul {
652 | margin: 0;
653 | padding: 0;
654 | }
655 | nav#global-nav ul li {
656 | border-bottom: 1px solid #474747;
657 | padding: 0;
658 | margin: 0;
659 | width: 100%;
660 | }
661 | nav#global-nav ul li a {
662 | display: block;
663 | background-color: #474747;
664 | color: #fff;
665 | text-decoration: none;
666 | font-size: 1.2em;
667 | font-weight: 200;
668 | letter-spacing: 1px;
669 | border: 0;
670 | margin-right: 0;
671 | padding: 1em;
672 | }
673 | nav#global-nav ul li a:hover, nav#global-nav ul li a:focus {
674 | background-color: #474747;
675 | }
676 | nav#global-nav ul li a:active {
677 | color: #3D92C9;
678 | }
679 | nav#global-nav img {
680 | position: relative;
681 | color: #fff;
682 | height: 30px;
683 | top: 7px;
684 | }
685 |
686 | /* Menu button */
687 |
688 | #menu-button {
689 | background-color: rgba(0, 0, 0, 0.1);
690 | border: 0;
691 | color: #333;
692 | cursor: pointer;
693 | display: block;
694 | line-height: 1;
695 | width: 4em;
696 | height: 4em;
697 | left: 0.5em;
698 | top: 0.5em;
699 | padding: 0;
700 | position: relative;
701 | text-align: center;
702 | z-index: 8;
703 | -moz-transition: all 300ms;
704 | -o-transition: all 300ms;
705 | -webkit-transition: all 300ms;
706 | transition: all 300ms;
707 | }
708 | #menu-button:hover, #menu-button:active {
709 | background: #777;
710 |
711 | }
712 | #menu-button span.menu-icon {
713 | display: block;
714 | pointer-events: none;
715 | font-size: 3em;
716 | text-shadow: 2px 2px 2px #333;
717 | }
718 | #menu-button span.menu-icon svg rect {
719 | fill: #333;
720 | }
721 | #menu-button:hover span.menu-icon svg rect {
722 | fill: #fff;
723 | }
724 | #menu-button span.menu-text {
725 | display: block;
726 | font-size: 0.8em;
727 | margin-top: 0.2em;
728 | }
729 |
730 | /* Utilities */
731 | .visuallyhidden {
732 | border: 0;
733 | clip: rect(0 0 0 0);
734 | height: 1px;
735 | margin: -1px;
736 | overflow: hidden;
737 | padding: 0;
738 | position: absolute;
739 | width: 1px;
740 | }
741 |
742 |
743 | @media (min-width: 48em) {
744 | .header,
745 | .content {
746 | padding-left: 2em;
747 | padding-right: 2em;
748 | }
749 |
750 | .blog-picture {
751 | display: inline;
752 | }
753 |
754 | .sidebar {
755 | position: fixed;
756 | top: 0;
757 | bottom: 0;
758 | }
759 |
760 |
761 | .menu-link {
762 | position: fixed;
763 | }
764 | #layout.active .menu-link {
765 | left: 150px;
766 | }
767 |
768 | .post-body {
769 | font-size: 125%;
770 | }
771 |
772 | }
773 |
774 | @media (max-width: 48em) {
775 | .header h1 {
776 | font-size: 1.7em;
777 | }
778 | .header h2 {
779 | font-size: 1.3em;
780 | }
781 |
782 | #menu-button {
783 | width: 3em;
784 | height: 3em;
785 | }
786 |
787 | article>footer {
788 | text-align: center;
789 | }
790 | }
791 |
--------------------------------------------------------------------------------
/app/solid.js:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | The MIT License (MIT)
4 |
5 | Copyright (c) 2015 Solid
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 |
25 | Solid.js is a Javascript library for Solid applications. This library currently
26 | depends on rdflib.js. Please make sure to load the rdflib.js script before
27 | loading solid.js.
28 |
29 | If you would like to know more about the solid Solid project, please see
30 | https://github.com/solid/
31 |
32 | */
33 |
34 | // WebID authentication and signup
35 | var Solid = Solid || {};
36 | Solid.auth = (function(window) {
37 | 'use strict';
38 |
39 | // default (preferred) authentication endpoint
40 | var authEndpoint = 'https://databox.me/';
41 | var signupEndpoint = 'https://solid.github.io/solid-idps/';
42 |
43 | // attempt to find the current user's WebID from the User header if authenticated
44 | // resolve(webid) - string
45 | var login = function(url) {
46 | url = url || window.location.origin+window.location.pathname;
47 | var promise = new Promise(function(resolve, reject) {
48 | var http = new XMLHttpRequest();
49 | http.open('HEAD', url);
50 | http.withCredentials = true;
51 | http.onreadystatechange = function() {
52 | if (this.readyState == this.DONE) {
53 | if (this.status === 200) {
54 | var user = this.getResponseHeader('User');
55 | if (user && user.length > 0 && user.slice(0, 4) == 'http') {
56 | return resolve(user);
57 | }
58 | }
59 | // authenticate to a known endpoint
60 | var http = new XMLHttpRequest();
61 | http.open('HEAD', authEndpoint);
62 | http.withCredentials = true;
63 | http.onreadystatechange = function() {
64 | if (this.readyState == this.DONE) {
65 | if (this.status === 200) {
66 | var user = this.getResponseHeader('User');
67 | if (user && user.length > 0 && user.slice(0, 4) == 'http') {
68 | return resolve(user);
69 | }
70 | }
71 | return reject({status: this.status, xhr: this});
72 | }
73 | };
74 | http.send();
75 | }
76 | };
77 | http.send();
78 | });
79 |
80 | return promise;
81 | };
82 |
83 | // Open signup window
84 | var signup = function(url) {
85 | url = url || signupEndpoint;
86 | var leftPosition, topPosition;
87 | var width = 1024;
88 | var height = 600;
89 | // set borders
90 | leftPosition = (window.screen.width / 2) - ((width / 2) + 10);
91 | // set title and status bars
92 | topPosition = (window.screen.height / 2) - ((height / 2) + 50);
93 | window.open(url+"?origin="+encodeURIComponent(window.location.origin), "Solid signup", "resizable,scrollbars,status,width="+width+",height="+height+",left="+ leftPosition + ",top=" + topPosition);
94 |
95 | var promise = new Promise(function(resolve, reject) {
96 | console.log("Starting listener");
97 | listen().then(function(webid) {
98 | return resolve(webid);
99 | }).catch(function(err){
100 | return reject(err);
101 | });
102 | });
103 |
104 | return promise;
105 | };
106 |
107 | // Listen to login messages from child window/iframe
108 | var listen = function() {
109 | var promise = new Promise(function(resolve, reject){
110 | console.log("In listen()");
111 | var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
112 | var eventListener = window[eventMethod];
113 | var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
114 | eventListener(messageEvent,function(e) {
115 | var u = e.data;
116 | if (u.slice(0,5) == 'User:') {
117 | var user = u.slice(5, u.length);
118 | if (user && user.length > 0 && user.slice(0,4) == 'http') {
119 | return resolve(user);
120 | } else {
121 | return reject(user);
122 | }
123 | }
124 | },true);
125 | });
126 |
127 | return promise;
128 | };
129 |
130 | // return public methods
131 | return {
132 | login: login,
133 | signup: signup,
134 | listen: listen,
135 | };
136 | }(this));
137 | // Identity / WebID
138 | var Solid = Solid || {};
139 | Solid.identity = (function(window) {
140 | 'use strict';
141 |
142 | // common vocabs
143 | var RDF = $rdf.Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#");
144 | var OWL = $rdf.Namespace("http://www.w3.org/2002/07/owl#");
145 | var PIM = $rdf.Namespace("http://www.w3.org/ns/pim/space#");
146 | var FOAF = $rdf.Namespace("http://xmlns.com/foaf/0.1/");
147 | var DCT = $rdf.Namespace("http://purl.org/dc/terms/");
148 |
149 | // fetch user profile (follow sameAs links) and return promise with a graph
150 | // resolve(graph)
151 | var getProfile = function(url) {
152 | var promise = new Promise(function(resolve, reject) {
153 | // Load main profile
154 | Solid.web.get(url).then(
155 | function(graph) {
156 | // set WebID
157 | var webid = graph.any($rdf.sym(url), FOAF('primaryTopic'));
158 | // find additional resources to load
159 | var sameAs = graph.statementsMatching(webid, OWL('sameAs'), undefined);
160 | var seeAlso = graph.statementsMatching(webid, OWL('seeAlso'), undefined);
161 | var prefs = graph.statementsMatching(webid, PIM('preferencesFile'), undefined);
162 | var toLoad = sameAs.length + seeAlso.length + prefs.length;
163 |
164 | // sync promises externally instead of using Promise.all() which fails if one GET fails
165 | var syncAll = function() {
166 | if (toLoad === 0) {
167 | return resolve(graph);
168 | }
169 | }
170 | // Load sameAs files
171 | if (sameAs.length > 0) {
172 | sameAs.forEach(function(same){
173 | Solid.web.get(same.object.value, same.object.value).then(
174 | function(g) {
175 | Solid.utils.appendGraph(graph, g);
176 | toLoad--;
177 | syncAll();
178 | }
179 | ).catch(
180 | function(err){
181 | toLoad--;
182 | syncAll();
183 | });
184 | });
185 | }
186 | // Load seeAlso files
187 | if (seeAlso.length > 0) {
188 | seeAlso.forEach(function(see){
189 | Solid.web.get(see.object.value).then(
190 | function(g) {
191 | Solid.utils.appendGraph(graph, g, see.object.value);
192 | toLoad--;
193 | syncAll();
194 | }
195 | ).catch(
196 | function(err){
197 | toLoad--;
198 | syncAll();
199 | });
200 | });
201 | }
202 | // Load preferences files
203 | if (prefs.length > 0) {
204 | prefs.forEach(function(pref){
205 | Solid.web.get(pref.object.value).then(
206 | function(g) {
207 | Solid.utils.appendGraph(graph, g, pref.object.value);
208 | toLoad--;
209 | syncAll();
210 | }
211 | ).catch(
212 | function(err){
213 | toLoad--;
214 | syncAll();
215 | });
216 | });
217 | }
218 | }
219 | )
220 | .catch(
221 | function(err) {
222 | reject(err);
223 | }
224 | );
225 | });
226 |
227 | return promise;
228 | };
229 |
230 | // Find the user's workspaces
231 | // Return an object with the list of objects (workspaces)
232 | var getWorkspaces = function(webid, graph) {
233 | var promise = new Promise(function(resolve, reject){
234 | if (!graph) {
235 | // fetch profile and call function again
236 | getProfile(webid).then(function(g) {
237 | getWorkspaces(webid, g).then(function(ws) {
238 | return resolve(ws);
239 | }).catch(function(err) {
240 | return reject(err);
241 | });
242 | }).catch(function(err){
243 | return reject(err);
244 | });
245 | } else {
246 | // find workspaces
247 | var workspaces = [];
248 | var ws = graph.statementsMatching($rdf.sym(webid), PIM('workspace'), undefined);
249 | if (ws.length === 0) {
250 | return resolve(workspaces);
251 | }
252 | ws.forEach(function(w){
253 | // try to get some additional info - i.e. desc/title
254 | var workspace = {};
255 | var title = graph.any(w.object, DCT('title'));
256 | if (title && title.value) {
257 | workspace.title = title.value;
258 | }
259 | workspace.url = w.object.uri;
260 | workspace.statements = graph.statementsMatching(w.object, undefined, undefined);
261 | workspaces.push(workspace);
262 | });
263 | return resolve(workspaces);
264 | }
265 | });
266 |
267 | return promise;
268 | };
269 |
270 | // return public methods
271 | return {
272 | getProfile: getProfile,
273 | getWorkspaces: getWorkspaces
274 | };
275 | }(this));
276 | // Events
277 | Solid = Solid || {};
278 | Solid.status = (function(window) {
279 | 'use strict';
280 |
281 | // Get current online status
282 | var isOnline = function() {
283 | return window.navigator.onLine;
284 | };
285 |
286 | // Is offline
287 | var onOffline = function(callback) {
288 | window.addEventListener("offline", callback, false);
289 | };
290 | // Is online
291 | var onOnline = function(callback) {
292 | window.addEventListener("online", callback, false);
293 | };
294 |
295 | // return public methods
296 | return {
297 | isOnline: isOnline,
298 | onOffline: onOffline,
299 | onOnline: onOnline,
300 | };
301 | }(this));
302 | // Helper functions
303 | var Solid = Solid || {};
304 | Solid.utils = (function(window) {
305 | 'use strict';
306 |
307 | // parse a Link header
308 | var parseLinkHeader = function(link) {
309 | var linkexp = /<[^>]*>\s*(\s*;\s*[^\(\)<>@,;:"\/\[\]\?={} \t]+=(([^\(\)<>@,;:"\/\[\]\?={} \t]+)|("[^"]*")))*(,|$)/g;
310 | var paramexp = /[^\(\)<>@,;:"\/\[\]\?={} \t]+=(([^\(\)<>@,;:"\/\[\]\?={} \t]+)|("[^"]*"))/g;
311 |
312 | var matches = link.match(linkexp);
313 | var rels = {};
314 | for (var i = 0; i < matches.length; i++) {
315 | var split = matches[i].split('>');
316 | var href = split[0].substring(1);
317 | var ps = split[1];
318 | var s = ps.match(paramexp);
319 | for (var j = 0; j < s.length; j++) {
320 | var p = s[j];
321 | var paramsplit = p.split('=');
322 | var name = paramsplit[0];
323 | var rel = paramsplit[1].replace(/["']/g, '');
324 | rels[rel] = href;
325 | }
326 | }
327 | return rels;
328 | };
329 |
330 | // append statements from one graph object to another
331 | var appendGraph = function(toGraph, fromGraph, docURI) {
332 | var why = (docURI)?$rdf.sym(docURI):undefined;
333 | fromGraph.statementsMatching(undefined, undefined, undefined, why).forEach(function(st) {
334 | toGraph.add(st.subject, st.predicate, st.object, st.why);
335 | });
336 | };
337 |
338 | return {
339 | parseLinkHeader: parseLinkHeader,
340 | appendGraph: appendGraph,
341 | };
342 | }(this));
343 | // LDP operations
344 | var Solid = Solid || {};
345 | Solid.web = (function(window) {
346 | 'use strict';
347 |
348 | // Init some defaults;
349 | var PROXY = "https://databox.me/,proxy?uri={uri}";
350 | var TIMEOUT = 5000;
351 |
352 | $rdf.Fetcher.crossSiteProxyTemplate = PROXY;
353 | // common vocabs
354 | var LDP = $rdf.Namespace("http://www.w3.org/ns/ldp#");
355 |
356 | // return metadata for a given request
357 | var parseResponseMeta = function(resp) {
358 | var h = Solid.utils.parseLinkHeader(resp.getResponseHeader('Link'));
359 | var meta = {};
360 | meta.url = (resp.getResponseHeader('Location'))?resp.getResponseHeader('Location'):resp.responseURL;
361 | meta.acl = h['acl'];
362 | meta.meta = (h['meta'])?h['meta']:h['describedBy'];
363 | meta.user = (resp.getResponseHeader('User'))?resp.getResponseHeader('User'):'';
364 | meta.websocket = (resp.getResponseHeader('Updates-Via'))?resp.getResponseHeader('Updates-Via'):'';
365 | meta.exists = false;
366 | meta.exists = (resp.status === 200)?true:false;
367 | meta.xhr = resp;
368 | return meta;
369 | };
370 |
371 | // check if a resource exists and return useful Solid info (acl, meta, type, etc)
372 | // resolve(metaObj)
373 | var head = function(url) {
374 | var promise = new Promise(function(resolve) {
375 | var http = new XMLHttpRequest();
376 | http.open('HEAD', url);
377 | http.onreadystatechange = function() {
378 | if (this.readyState == this.DONE) {
379 | resolve(parseResponseMeta(this));
380 | }
381 | };
382 | http.send();
383 | });
384 |
385 | return promise;
386 | };
387 |
388 | // fetch an RDF resource
389 | // resolve(graph) | reject(this)
390 | var get = function(url) {
391 | var promise = new Promise(function(resolve, reject) {
392 | var g = new $rdf.graph();
393 | var f = new $rdf.fetcher(g, TIMEOUT);
394 |
395 | var docURI = (url.indexOf('#') >= 0)?url.slice(0, url.indexOf('#')):url;
396 | f.nowOrWhenFetched(docURI,undefined,function(ok, body, xhr) {
397 | if (!ok) {
398 | reject({status: xhr.status, xhr: xhr});
399 | } else {
400 | resolve(g);
401 | }
402 | });
403 | });
404 |
405 | return promise;
406 | };
407 |
408 | // create new resource
409 | // resolve(metaObj) | reject
410 | var post = function(url, slug, data, isContainer) {
411 | var resType = (isContainer)?LDP('BasicContainer').uri:LDP('Resource').uri;
412 | var promise = new Promise(function(resolve, reject) {
413 | var http = new XMLHttpRequest();
414 | http.open('POST', url);
415 | http.setRequestHeader('Content-Type', 'text/turtle');
416 | http.setRequestHeader('Link', '<'+resType+'>; rel="type"');
417 | if (slug && slug.length > 0) {
418 | http.setRequestHeader('Slug', slug);
419 | }
420 | http.withCredentials = true;
421 | http.onreadystatechange = function() {
422 | if (this.readyState == this.DONE) {
423 | if (this.status === 200 || this.status === 201) {
424 | resolve(parseResponseMeta(this));
425 | } else {
426 | reject({status: this.status, xhr: this});
427 | }
428 | }
429 | };
430 | if (data && data.length > 0) {
431 | http.send(data);
432 | } else {
433 | http.send();
434 | }
435 | });
436 |
437 | return promise;
438 | };
439 |
440 | // update/create resource using HTTP PUT
441 | // resolve(metaObj) | reject
442 | var put = function(url, data) {
443 | var promise = new Promise(function(resolve, reject) {
444 | var http = new XMLHttpRequest();
445 | http.open('PUT', url);
446 | http.setRequestHeader('Content-Type', 'text/turtle');
447 | http.withCredentials = true;
448 | http.onreadystatechange = function() {
449 | if (this.readyState == this.DONE) {
450 | if (this.status === 200 || this.status === 201) {
451 | return resolve(parseResponseMeta(this));
452 | } else {
453 | reject({status: this.status, xhr: this});
454 | }
455 | }
456 | };
457 | if (data) {
458 | http.send(data);
459 | } else {
460 | http.send();
461 | }
462 | });
463 |
464 | return promise;
465 | };
466 |
467 | // delete a resource
468 | // resolve(true) | reject
469 | var del = function(url) {
470 | var promise = new Promise(function(resolve, reject) {
471 | var http = new XMLHttpRequest();
472 | http.open('DELETE', url);
473 | http.withCredentials = true;
474 | http.onreadystatechange = function() {
475 | if (this.readyState == this.DONE) {
476 | if (this.status === 200) {
477 | return resolve(true);
478 | } else {
479 | reject({status: this.status, xhr: this});
480 | }
481 | }
482 | };
483 | http.send();
484 | });
485 |
486 | return promise;
487 | }
488 |
489 | // return public methods
490 | return {
491 | head: head,
492 | get: get,
493 | post: post,
494 | put: put,
495 | del: del,
496 | };
497 | }(this));
498 |
--------------------------------------------------------------------------------
/css/font-awesome.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome 4.5.0 by @davegandy - http://fontawesome.io - @fontawesome
3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
4 | */
5 | @font-face{font-family:'FontAwesome';src:url('fonts/fontawesome-webfont.eot');src:url('fonts/fontawesome-webfont.eot') format('embedded-opentype'),url('fonts/fontawesome-webfont.woff') format('woff'),url('fonts/fontawesome-webfont.ttf') format('truetype'),url('fonts/fontawesome-webfont.svg#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}
6 |
--------------------------------------------------------------------------------
/js/moment.min.js:
--------------------------------------------------------------------------------
1 | //! moment.js
2 | //! version : 2.10.6
3 | //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
4 | //! license : MIT
5 | //! momentjs.com
6 | !function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return Hc.apply(null,arguments)}function b(a){Hc=a}function c(a){return"[object Array]"===Object.prototype.toString.call(a)}function d(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function e(a,b){var c,d=[];for(c=0;c0)for(c in Jc)d=Jc[c],e=b[d],"undefined"!=typeof e&&(a[d]=e);return a}function n(b){m(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),Kc===!1&&(Kc=!0,a.updateOffset(this),Kc=!1)}function o(a){return a instanceof n||null!=a&&null!=a._isAMomentObject}function p(a){return 0>a?Math.ceil(a):Math.floor(a)}function q(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=p(b)),c}function r(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&q(a[d])!==q(b[d]))&&g++;return g+f}function s(){}function t(a){return a?a.toLowerCase().replace("_","-"):a}function u(a){for(var b,c,d,e,f=0;f0;){if(d=v(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&r(e,c,!0)>=b-1)break;b--}f++}return null}function v(a){var b=null;if(!Lc[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=Ic._abbr,require("./locale/"+a),w(b)}catch(c){}return Lc[a]}function w(a,b){var c;return a&&(c="undefined"==typeof b?y(a):x(a,b),c&&(Ic=c)),Ic._abbr}function x(a,b){return null!==b?(b.abbr=a,Lc[a]=Lc[a]||new s,Lc[a].set(b),w(a),Lc[a]):(delete Lc[a],null)}function y(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return Ic;if(!c(a)){if(b=v(a))return b;a=[a]}return u(a)}function z(a,b){var c=a.toLowerCase();Mc[c]=Mc[c+"s"]=Mc[b]=a}function A(a){return"string"==typeof a?Mc[a]||Mc[a.toLowerCase()]:void 0}function B(a){var b,c,d={};for(c in a)f(a,c)&&(b=A(c),b&&(d[b]=a[c]));return d}function C(b,c){return function(d){return null!=d?(E(this,b,d),a.updateOffset(this,c),this):D(this,b)}}function D(a,b){return a._d["get"+(a._isUTC?"UTC":"")+b]()}function E(a,b,c){return a._d["set"+(a._isUTC?"UTC":"")+b](c)}function F(a,b){var c;if("object"==typeof a)for(c in a)this.set(c,a[c]);else if(a=A(a),"function"==typeof this[a])return this[a](b);return this}function G(a,b,c){var d=""+Math.abs(a),e=b-d.length,f=a>=0;return(f?c?"+":"":"-")+Math.pow(10,Math.max(0,e)).toString().substr(1)+d}function H(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(Qc[a]=e),b&&(Qc[b[0]]=function(){return G(e.apply(this,arguments),b[1],b[2])}),c&&(Qc[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function I(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function J(a){var b,c,d=a.match(Nc);for(b=0,c=d.length;c>b;b++)Qc[d[b]]?d[b]=Qc[d[b]]:d[b]=I(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function K(a,b){return a.isValid()?(b=L(b,a.localeData()),Pc[b]=Pc[b]||J(b),Pc[b](a)):a.localeData().invalidDate()}function L(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Oc.lastIndex=0;d>=0&&Oc.test(a);)a=a.replace(Oc,c),Oc.lastIndex=0,d-=1;return a}function M(a){return"function"==typeof a&&"[object Function]"===Object.prototype.toString.call(a)}function N(a,b,c){dd[a]=M(b)?b:function(a){return a&&c?c:b}}function O(a,b){return f(dd,a)?dd[a](b._strict,b._locale):new RegExp(P(a))}function P(a){return a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}).replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function Q(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=q(a)}),c=0;cd;d++){if(e=h([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}function X(a,b){var c;return"string"==typeof b&&(b=a.localeData().monthsParse(b),"number"!=typeof b)?a:(c=Math.min(a.date(),T(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a)}function Y(b){return null!=b?(X(this,b),a.updateOffset(this,!0),this):D(this,"Month")}function Z(){return T(this.year(),this.month())}function $(a){var b,c=a._a;return c&&-2===j(a).overflow&&(b=c[gd]<0||c[gd]>11?gd:c[hd]<1||c[hd]>T(c[fd],c[gd])?hd:c[id]<0||c[id]>24||24===c[id]&&(0!==c[jd]||0!==c[kd]||0!==c[ld])?id:c[jd]<0||c[jd]>59?jd:c[kd]<0||c[kd]>59?kd:c[ld]<0||c[ld]>999?ld:-1,j(a)._overflowDayOfYear&&(fd>b||b>hd)&&(b=hd),j(a).overflow=b),a}function _(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function aa(a,b){var c=!0;return g(function(){return c&&(_(a+"\n"+(new Error).stack),c=!1),b.apply(this,arguments)},b)}function ba(a,b){od[a]||(_(b),od[a]=!0)}function ca(a){var b,c,d=a._i,e=pd.exec(d);if(e){for(j(a).iso=!0,b=0,c=qd.length;c>b;b++)if(qd[b][1].exec(d)){a._f=qd[b][0];break}for(b=0,c=rd.length;c>b;b++)if(rd[b][1].exec(d)){a._f+=(e[6]||" ")+rd[b][0];break}d.match(ad)&&(a._f+="Z"),va(a)}else a._isValid=!1}function da(b){var c=sd.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(ca(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}function ea(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function fa(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function ga(a){return ha(a)?366:365}function ha(a){return a%4===0&&a%100!==0||a%400===0}function ia(){return ha(this.year())}function ja(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=Da(a).add(f,"d"),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function ka(a){return ja(a,this._week.dow,this._week.doy).week}function la(){return this._week.dow}function ma(){return this._week.doy}function na(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function oa(a){var b=ja(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}function pa(a,b,c,d,e){var f,g=6+e-d,h=fa(a,0,1+g),i=h.getUTCDay();return e>i&&(i+=7),c=null!=c?1*c:e,f=1+g+7*(b-1)-i+c,{year:f>0?a:a-1,dayOfYear:f>0?f:ga(a-1)+f}}function qa(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function ra(a,b,c){return null!=a?a:null!=b?b:c}function sa(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function ta(a){var b,c,d,e,f=[];if(!a._d){for(d=sa(a),a._w&&null==a._a[hd]&&null==a._a[gd]&&ua(a),a._dayOfYear&&(e=ra(a._a[fd],d[fd]),a._dayOfYear>ga(e)&&(j(a)._overflowDayOfYear=!0),c=fa(e,0,a._dayOfYear),a._a[gd]=c.getUTCMonth(),a._a[hd]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=f[b]=d[b];for(;7>b;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];24===a._a[id]&&0===a._a[jd]&&0===a._a[kd]&&0===a._a[ld]&&(a._nextDay=!0,a._a[id]=0),a._d=(a._useUTC?fa:ea).apply(null,f),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[id]=24)}}function ua(a){var b,c,d,e,f,g,h;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,c=ra(b.GG,a._a[fd],ja(Da(),1,4).year),d=ra(b.W,1),e=ra(b.E,1)):(f=a._locale._week.dow,g=a._locale._week.doy,c=ra(b.gg,a._a[fd],ja(Da(),f,g).year),d=ra(b.w,1),null!=b.d?(e=b.d,f>e&&++d):e=null!=b.e?b.e+f:f),h=pa(c,d,e,g,f),a._a[fd]=h.year,a._dayOfYear=h.dayOfYear}function va(b){if(b._f===a.ISO_8601)return void ca(b);b._a=[],j(b).empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,k=0;for(e=L(b._f,b._locale).match(Nc)||[],c=0;c0&&j(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),k+=d.length),Qc[f]?(d?j(b).empty=!1:j(b).unusedTokens.push(f),S(f,d,b)):b._strict&&!d&&j(b).unusedTokens.push(f);j(b).charsLeftOver=i-k,h.length>0&&j(b).unusedInput.push(h),j(b).bigHour===!0&&b._a[id]<=12&&b._a[id]>0&&(j(b).bigHour=void 0),b._a[id]=wa(b._locale,b._a[id],b._meridiem),ta(b),$(b)}function wa(a,b,c){var d;return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b}function xa(a){var b,c,d,e,f;if(0===a._f.length)return j(a).invalidFormat=!0,void(a._d=new Date(NaN));for(e=0;ef)&&(d=f,c=b));g(a,c||b)}function ya(a){if(!a._d){var b=B(a._i);a._a=[b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],ta(a)}}function za(a){var b=new n($(Aa(a)));return b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b}function Aa(a){var b=a._i,e=a._f;return a._locale=a._locale||y(a._l),null===b||void 0===e&&""===b?l({nullInput:!0}):("string"==typeof b&&(a._i=b=a._locale.preparse(b)),o(b)?new n($(b)):(c(e)?xa(a):e?va(a):d(b)?a._d=b:Ba(a),a))}function Ba(b){var f=b._i;void 0===f?b._d=new Date:d(f)?b._d=new Date(+f):"string"==typeof f?da(b):c(f)?(b._a=e(f.slice(0),function(a){return parseInt(a,10)}),ta(b)):"object"==typeof f?ya(b):"number"==typeof f?b._d=new Date(f):a.createFromInputFallback(b)}function Ca(a,b,c,d,e){var f={};return"boolean"==typeof c&&(d=c,c=void 0),f._isAMomentObject=!0,f._useUTC=f._isUTC=e,f._l=c,f._i=a,f._f=b,f._strict=d,za(f)}function Da(a,b,c,d){return Ca(a,b,c,d,!1)}function Ea(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return Da();for(d=b[0],e=1;ea&&(a=-a,c="-"),c+G(~~(a/60),2)+b+G(~~a%60,2)})}function Ka(a){var b=(a||"").match(ad)||[],c=b[b.length-1]||[],d=(c+"").match(xd)||["-",0,0],e=+(60*d[1])+q(d[2]);return"+"===d[0]?e:-e}function La(b,c){var e,f;return c._isUTC?(e=c.clone(),f=(o(b)||d(b)?+b:+Da(b))-+e,e._d.setTime(+e._d+f),a.updateOffset(e,!1),e):Da(b).local()}function Ma(a){return 15*-Math.round(a._d.getTimezoneOffset()/15)}function Na(b,c){var d,e=this._offset||0;return null!=b?("string"==typeof b&&(b=Ka(b)),Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Ma(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?bb(this,Ya(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Ma(this)}function Oa(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Pa(a){return this.utcOffset(0,a)}function Qa(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Ma(this),"m")),this}function Ra(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Ka(this._i)),this}function Sa(a){return a=a?Da(a).utcOffset():0,(this.utcOffset()-a)%60===0}function Ta(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Ua(){if("undefined"!=typeof this._isDSTShifted)return this._isDSTShifted;var a={};if(m(a,this),a=Aa(a),a._a){var b=a._isUTC?h(a._a):Da(a._a);this._isDSTShifted=this.isValid()&&r(a._a,b.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function Va(){return!this._isUTC}function Wa(){return this._isUTC}function Xa(){return this._isUTC&&0===this._offset}function Ya(a,b){var c,d,e,g=a,h=null;return Ia(a)?g={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(g={},b?g[b]=a:g.milliseconds=a):(h=yd.exec(a))?(c="-"===h[1]?-1:1,g={y:0,d:q(h[hd])*c,h:q(h[id])*c,m:q(h[jd])*c,s:q(h[kd])*c,ms:q(h[ld])*c}):(h=zd.exec(a))?(c="-"===h[1]?-1:1,g={y:Za(h[2],c),M:Za(h[3],c),d:Za(h[4],c),h:Za(h[5],c),m:Za(h[6],c),s:Za(h[7],c),w:Za(h[8],c)}):null==g?g={}:"object"==typeof g&&("from"in g||"to"in g)&&(e=_a(Da(g.from),Da(g.to)),g={},g.ms=e.milliseconds,g.M=e.months),d=new Ha(g),Ia(a)&&f(a,"_locale")&&(d._locale=a._locale),d}function Za(a,b){var c=a&&parseFloat(a.replace(",","."));return(isNaN(c)?0:c)*b}function $a(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function _a(a,b){var c;return b=La(b,a),a.isBefore(b)?c=$a(a,b):(c=$a(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c}function ab(a,b){return function(c,d){var e,f;return null===d||isNaN(+d)||(ba(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period)."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=Ya(c,d),bb(this,e,a),this}}function bb(b,c,d,e){var f=c._milliseconds,g=c._days,h=c._months;e=null==e?!0:e,f&&b._d.setTime(+b._d+f*d),g&&E(b,"Date",D(b,"Date")+g*d),h&&X(b,D(b,"Month")+h*d),e&&a.updateOffset(b,g||h)}function cb(a,b){var c=a||Da(),d=La(c,this).startOf("day"),e=this.diff(d,"days",!0),f=-6>e?"sameElse":-1>e?"lastWeek":0>e?"lastDay":1>e?"sameDay":2>e?"nextDay":7>e?"nextWeek":"sameElse";return this.format(b&&b[f]||this.localeData().calendar(f,this,Da(c)))}function db(){return new n(this)}function eb(a,b){var c;return b=A("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=o(a)?a:Da(a),+this>+a):(c=o(a)?+a:+Da(a),c<+this.clone().startOf(b))}function fb(a,b){var c;return b=A("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=o(a)?a:Da(a),+a>+this):(c=o(a)?+a:+Da(a),+this.clone().endOf(b)b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)}function kb(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function lb(){var a=this.clone().utc();return 0b;b++)if(this._weekdaysParse[b]||(c=Da([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b}function Pb(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=Kb(a,this.localeData()),this.add(a-b,"d")):b}function Qb(a){var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function Rb(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)}function Sb(a,b){H(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}function Tb(a,b){return b._meridiemParse}function Ub(a){return"p"===(a+"").toLowerCase().charAt(0)}function Vb(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function Wb(a,b){b[ld]=q(1e3*("0."+a))}function Xb(){return this._isUTC?"UTC":""}function Yb(){return this._isUTC?"Coordinated Universal Time":""}function Zb(a){return Da(1e3*a)}function $b(){return Da.apply(null,arguments).parseZone()}function _b(a,b,c){var d=this._calendar[a];return"function"==typeof d?d.call(b,c):d}function ac(a){var b=this._longDateFormat[a],c=this._longDateFormat[a.toUpperCase()];return b||!c?b:(this._longDateFormat[a]=c.replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a])}function bc(){return this._invalidDate}function cc(a){return this._ordinal.replace("%d",a)}function dc(a){return a}function ec(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)}function fc(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)}function gc(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b;this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function hc(a,b,c,d){var e=y(),f=h().set(d,b);return e[c](f,a)}function ic(a,b,c,d,e){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return hc(a,b,c,e);var f,g=[];for(f=0;d>f;f++)g[f]=hc(a,f,c,e);return g}function jc(a,b){return ic(a,b,"months",12,"month")}function kc(a,b){return ic(a,b,"monthsShort",12,"month")}function lc(a,b){return ic(a,b,"weekdays",7,"day")}function mc(a,b){return ic(a,b,"weekdaysShort",7,"day")}function nc(a,b){return ic(a,b,"weekdaysMin",7,"day")}function oc(){var a=this._data;return this._milliseconds=Wd(this._milliseconds),this._days=Wd(this._days),this._months=Wd(this._months),a.milliseconds=Wd(a.milliseconds),a.seconds=Wd(a.seconds),a.minutes=Wd(a.minutes),a.hours=Wd(a.hours),a.months=Wd(a.months),a.years=Wd(a.years),this}function pc(a,b,c,d){var e=Ya(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}function qc(a,b){return pc(this,a,b,1)}function rc(a,b){return pc(this,a,b,-1)}function sc(a){return 0>a?Math.floor(a):Math.ceil(a)}function tc(){var a,b,c,d,e,f=this._milliseconds,g=this._days,h=this._months,i=this._data;return f>=0&&g>=0&&h>=0||0>=f&&0>=g&&0>=h||(f+=864e5*sc(vc(h)+g),g=0,h=0),i.milliseconds=f%1e3,a=p(f/1e3),i.seconds=a%60,b=p(a/60),i.minutes=b%60,c=p(b/60),i.hours=c%24,g+=p(c/24),e=p(uc(g)),h+=e,g-=sc(vc(e)),d=p(h/12),h%=12,i.days=g,i.months=h,i.years=d,this}function uc(a){return 4800*a/146097}function vc(a){return 146097*a/4800}function wc(a){var b,c,d=this._milliseconds;if(a=A(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+uc(b),"month"===a?c:c/12;switch(b=this._days+Math.round(vc(this._months)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3;case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}}function xc(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*q(this._months/12)}function yc(a){return function(){return this.as(a)}}function zc(a){return a=A(a),this[a+"s"]()}function Ac(a){return function(){return this._data[a]}}function Bc(){return p(this.days()/7)}function Cc(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function Dc(a,b,c){var d=Ya(a).abs(),e=ke(d.as("s")),f=ke(d.as("m")),g=ke(d.as("h")),h=ke(d.as("d")),i=ke(d.as("M")),j=ke(d.as("y")),k=e0,k[4]=c,Cc.apply(null,k)}function Ec(a,b){return void 0===le[a]?!1:void 0===b?le[a]:(le[a]=b,!0)}function Fc(a){var b=this.localeData(),c=Dc(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function Gc(){var a,b,c,d=me(this._milliseconds)/1e3,e=me(this._days),f=me(this._months);a=p(d/60),b=p(a/60),d%=60,a%=60,c=p(f/12),f%=12;var g=c,h=f,i=e,j=b,k=a,l=d,m=this.asSeconds();return m?(0>m?"-":"")+"P"+(g?g+"Y":"")+(h?h+"M":"")+(i?i+"D":"")+(j||k||l?"T":"")+(j?j+"H":"")+(k?k+"M":"")+(l?l+"S":""):"P0D"}var Hc,Ic,Jc=a.momentProperties=[],Kc=!1,Lc={},Mc={},Nc=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,Oc=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Pc={},Qc={},Rc=/\d/,Sc=/\d\d/,Tc=/\d{3}/,Uc=/\d{4}/,Vc=/[+-]?\d{6}/,Wc=/\d\d?/,Xc=/\d{1,3}/,Yc=/\d{1,4}/,Zc=/[+-]?\d{1,6}/,$c=/\d+/,_c=/[+-]?\d+/,ad=/Z|[+-]\d\d:?\d\d/gi,bd=/[+-]?\d+(\.\d{1,3})?/,cd=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,dd={},ed={},fd=0,gd=1,hd=2,id=3,jd=4,kd=5,ld=6;H("M",["MM",2],"Mo",function(){return this.month()+1}),H("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),H("MMMM",0,0,function(a){return this.localeData().months(this,a)}),z("month","M"),N("M",Wc),N("MM",Wc,Sc),N("MMM",cd),N("MMMM",cd),Q(["M","MM"],function(a,b){b[gd]=q(a)-1}),Q(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[gd]=e:j(c).invalidMonth=a});var md="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),nd="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),od={};a.suppressDeprecationWarnings=!1;var pd=/^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,qd=[["YYYYYY-MM-DD",/[+-]\d{6}-\d{2}-\d{2}/],["YYYY-MM-DD",/\d{4}-\d{2}-\d{2}/],["GGGG-[W]WW-E",/\d{4}-W\d{2}-\d/],["GGGG-[W]WW",/\d{4}-W\d{2}/],["YYYY-DDD",/\d{4}-\d{3}/]],rd=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],sd=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=aa("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),H(0,["YY",2],0,function(){return this.year()%100}),H(0,["YYYY",4],0,"year"),H(0,["YYYYY",5],0,"year"),H(0,["YYYYYY",6,!0],0,"year"),z("year","y"),N("Y",_c),N("YY",Wc,Sc),N("YYYY",Yc,Uc),N("YYYYY",Zc,Vc),N("YYYYYY",Zc,Vc),Q(["YYYYY","YYYYYY"],fd),Q("YYYY",function(b,c){c[fd]=2===b.length?a.parseTwoDigitYear(b):q(b)}),Q("YY",function(b,c){c[fd]=a.parseTwoDigitYear(b)}),a.parseTwoDigitYear=function(a){return q(a)+(q(a)>68?1900:2e3)};var td=C("FullYear",!1);H("w",["ww",2],"wo","week"),H("W",["WW",2],"Wo","isoWeek"),z("week","w"),z("isoWeek","W"),N("w",Wc),N("ww",Wc,Sc),N("W",Wc),N("WW",Wc,Sc),R(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=q(a)});var ud={dow:0,doy:6};H("DDD",["DDDD",3],"DDDo","dayOfYear"),z("dayOfYear","DDD"),N("DDD",Xc),N("DDDD",Tc),Q(["DDD","DDDD"],function(a,b,c){c._dayOfYear=q(a)}),a.ISO_8601=function(){};var vd=aa("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(){var a=Da.apply(null,arguments);return this>a?this:a}),wd=aa("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(){var a=Da.apply(null,arguments);return a>this?this:a});Ja("Z",":"),Ja("ZZ",""),N("Z",ad),N("ZZ",ad),Q(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=Ka(a)});var xd=/([\+\-]|\d\d)/gi;a.updateOffset=function(){};var yd=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,zd=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/;Ya.fn=Ha.prototype;var Ad=ab(1,"add"),Bd=ab(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ";var Cd=aa("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});H(0,["gg",2],0,function(){return this.weekYear()%100}),H(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Db("gggg","weekYear"),Db("ggggg","weekYear"),Db("GGGG","isoWeekYear"),Db("GGGGG","isoWeekYear"),z("weekYear","gg"),z("isoWeekYear","GG"),N("G",_c),N("g",_c),N("GG",Wc,Sc),N("gg",Wc,Sc),N("GGGG",Yc,Uc),N("gggg",Yc,Uc),N("GGGGG",Zc,Vc),N("ggggg",Zc,Vc),R(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=q(a)}),R(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),H("Q",0,0,"quarter"),z("quarter","Q"),N("Q",Rc),Q("Q",function(a,b){b[gd]=3*(q(a)-1)}),H("D",["DD",2],"Do","date"),z("date","D"),N("D",Wc),N("DD",Wc,Sc),N("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),Q(["D","DD"],hd),Q("Do",function(a,b){b[hd]=q(a.match(Wc)[0],10)});var Dd=C("Date",!0);H("d",0,"do","day"),H("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),H("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),H("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),H("e",0,0,"weekday"),H("E",0,0,"isoWeekday"),z("day","d"),z("weekday","e"),z("isoWeekday","E"),N("d",Wc),N("e",Wc),N("E",Wc),N("dd",cd),N("ddd",cd),N("dddd",cd),R(["dd","ddd","dddd"],function(a,b,c){var d=c._locale.weekdaysParse(a);null!=d?b.d=d:j(c).invalidWeekday=a}),R(["d","e","E"],function(a,b,c,d){b[d]=q(a)});var Ed="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Fd="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Gd="Su_Mo_Tu_We_Th_Fr_Sa".split("_");H("H",["HH",2],0,"hour"),H("h",["hh",2],0,function(){return this.hours()%12||12}),Sb("a",!0),Sb("A",!1),z("hour","h"),N("a",Tb),N("A",Tb),N("H",Wc),N("h",Wc),N("HH",Wc,Sc),N("hh",Wc,Sc),Q(["H","HH"],id),Q(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),Q(["h","hh"],function(a,b,c){b[id]=q(a),j(c).bigHour=!0});var Hd=/[ap]\.?m?\.?/i,Id=C("Hours",!0);H("m",["mm",2],0,"minute"),z("minute","m"),N("m",Wc),N("mm",Wc,Sc),Q(["m","mm"],jd);var Jd=C("Minutes",!1);H("s",["ss",2],0,"second"),z("second","s"),N("s",Wc),N("ss",Wc,Sc),Q(["s","ss"],kd);var Kd=C("Seconds",!1);H("S",0,0,function(){return~~(this.millisecond()/100)}),H(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),H(0,["SSS",3],0,"millisecond"),H(0,["SSSS",4],0,function(){return 10*this.millisecond()}),H(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),H(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),H(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),H(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),H(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),z("millisecond","ms"),N("S",Xc,Rc),N("SS",Xc,Sc),N("SSS",Xc,Tc);var Ld;for(Ld="SSSS";Ld.length<=9;Ld+="S")N(Ld,$c);for(Ld="S";Ld.length<=9;Ld+="S")Q(Ld,Wb);var Md=C("Milliseconds",!1);H("z",0,0,"zoneAbbr"),H("zz",0,0,"zoneName");var Nd=n.prototype;Nd.add=Ad,Nd.calendar=cb,Nd.clone=db,Nd.diff=ib,Nd.endOf=ub,Nd.format=mb,Nd.from=nb,Nd.fromNow=ob,Nd.to=pb,Nd.toNow=qb,Nd.get=F,Nd.invalidAt=Cb,Nd.isAfter=eb,Nd.isBefore=fb,Nd.isBetween=gb,Nd.isSame=hb,Nd.isValid=Ab,Nd.lang=Cd,Nd.locale=rb,Nd.localeData=sb,Nd.max=wd,Nd.min=vd,Nd.parsingFlags=Bb,Nd.set=F,Nd.startOf=tb,Nd.subtract=Bd,Nd.toArray=yb,Nd.toObject=zb,Nd.toDate=xb,Nd.toISOString=lb,Nd.toJSON=lb,Nd.toString=kb,Nd.unix=wb,Nd.valueOf=vb,Nd.year=td,Nd.isLeapYear=ia,Nd.weekYear=Fb,Nd.isoWeekYear=Gb,Nd.quarter=Nd.quarters=Jb,Nd.month=Y,Nd.daysInMonth=Z,Nd.week=Nd.weeks=na,Nd.isoWeek=Nd.isoWeeks=oa,Nd.weeksInYear=Ib,Nd.isoWeeksInYear=Hb,Nd.date=Dd,Nd.day=Nd.days=Pb,Nd.weekday=Qb,Nd.isoWeekday=Rb,Nd.dayOfYear=qa,Nd.hour=Nd.hours=Id,Nd.minute=Nd.minutes=Jd,Nd.second=Nd.seconds=Kd,
7 | Nd.millisecond=Nd.milliseconds=Md,Nd.utcOffset=Na,Nd.utc=Pa,Nd.local=Qa,Nd.parseZone=Ra,Nd.hasAlignedHourOffset=Sa,Nd.isDST=Ta,Nd.isDSTShifted=Ua,Nd.isLocal=Va,Nd.isUtcOffset=Wa,Nd.isUtc=Xa,Nd.isUTC=Xa,Nd.zoneAbbr=Xb,Nd.zoneName=Yb,Nd.dates=aa("dates accessor is deprecated. Use date instead.",Dd),Nd.months=aa("months accessor is deprecated. Use month instead",Y),Nd.years=aa("years accessor is deprecated. Use year instead",td),Nd.zone=aa("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",Oa);var Od=Nd,Pd={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Qd={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},Rd="Invalid date",Sd="%d",Td=/\d{1,2}/,Ud={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Vd=s.prototype;Vd._calendar=Pd,Vd.calendar=_b,Vd._longDateFormat=Qd,Vd.longDateFormat=ac,Vd._invalidDate=Rd,Vd.invalidDate=bc,Vd._ordinal=Sd,Vd.ordinal=cc,Vd._ordinalParse=Td,Vd.preparse=dc,Vd.postformat=dc,Vd._relativeTime=Ud,Vd.relativeTime=ec,Vd.pastFuture=fc,Vd.set=gc,Vd.months=U,Vd._months=md,Vd.monthsShort=V,Vd._monthsShort=nd,Vd.monthsParse=W,Vd.week=ka,Vd._week=ud,Vd.firstDayOfYear=ma,Vd.firstDayOfWeek=la,Vd.weekdays=Lb,Vd._weekdays=Ed,Vd.weekdaysMin=Nb,Vd._weekdaysMin=Gd,Vd.weekdaysShort=Mb,Vd._weekdaysShort=Fd,Vd.weekdaysParse=Ob,Vd.isPM=Ub,Vd._meridiemParse=Hd,Vd.meridiem=Vb,w("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===q(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),a.lang=aa("moment.lang is deprecated. Use moment.locale instead.",w),a.langData=aa("moment.langData is deprecated. Use moment.localeData instead.",y);var Wd=Math.abs,Xd=yc("ms"),Yd=yc("s"),Zd=yc("m"),$d=yc("h"),_d=yc("d"),ae=yc("w"),be=yc("M"),ce=yc("y"),de=Ac("milliseconds"),ee=Ac("seconds"),fe=Ac("minutes"),ge=Ac("hours"),he=Ac("days"),ie=Ac("months"),je=Ac("years"),ke=Math.round,le={s:45,m:45,h:22,d:26,M:11},me=Math.abs,ne=Ha.prototype;ne.abs=oc,ne.add=qc,ne.subtract=rc,ne.as=wc,ne.asMilliseconds=Xd,ne.asSeconds=Yd,ne.asMinutes=Zd,ne.asHours=$d,ne.asDays=_d,ne.asWeeks=ae,ne.asMonths=be,ne.asYears=ce,ne.valueOf=xc,ne._bubble=tc,ne.get=zc,ne.milliseconds=de,ne.seconds=ee,ne.minutes=fe,ne.hours=ge,ne.days=he,ne.weeks=Bc,ne.months=ie,ne.years=je,ne.humanize=Fc,ne.toISOString=Gc,ne.toString=Gc,ne.toJSON=Gc,ne.locale=rb,ne.localeData=sb,ne.toIsoString=aa("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",Gc),ne.lang=Cd,H("X",0,0,"unix"),H("x",0,0,"valueOf"),N("x",_c),N("X",bd),Q("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),Q("x",function(a,b,c){c._d=new Date(q(a))}),a.version="2.10.6",b(Da),a.fn=Od,a.min=Fa,a.max=Ga,a.utc=h,a.unix=Zb,a.months=jc,a.isDate=d,a.locale=w,a.invalid=l,a.duration=Ya,a.isMoment=o,a.weekdays=lc,a.parseZone=$b,a.localeData=y,a.isDuration=Ia,a.monthsShort=kc,a.weekdaysMin=nc,a.defineLocale=x,a.weekdaysShort=mc,a.normalizeUnits=A,a.relativeTimeThreshold=Ec;var oe=a;return oe});
--------------------------------------------------------------------------------
/app/app.js:
--------------------------------------------------------------------------------
1 | /* ---- DON'T EDIT BELOW ---- */
2 |
3 | var Plume = Plume || {};
4 |
5 | Plume = (function () {
6 | 'use strict';
7 |
8 | var config = Plume.config || {};
9 | var appURL = window.location.origin+window.location.pathname;
10 |
11 | // RDF
12 | var PROXY = "https://databox.me/,proxy?uri={uri}";
13 | var TIMEOUT = 5000;
14 |
15 | $rdf.Fetcher.crossSiteProxyTemplate = PROXY;
16 | // common vocabs
17 | var RDF = $rdf.Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#");
18 | var FOAF = $rdf.Namespace("http://xmlns.com/foaf/0.1/");
19 | var DCT = $rdf.Namespace("http://purl.org/dc/terms/");
20 | var LDP = $rdf.Namespace("http://www.w3.org/ns/ldp#");
21 | var SIOC = $rdf.Namespace("http://rdfs.org/sioc/ns#");
22 | var SIOC = $rdf.Namespace("http://rdfs.org/sioc/ns#");
23 | var SOLID = $rdf.Namespace("http://www.w3.org/ns/solid/terms#");
24 |
25 | // init markdown editor
26 | var editor = new SimpleMDE({
27 | status: false,
28 | spellChecker: false
29 | });
30 | editor.codemirror.on("change", function(){
31 | savePendingPost(editor.value());
32 | });
33 |
34 | // sanitize value to/from markdown editor
35 | var getBodyValue = function() {
36 | var val = editor.codemirror.getValue();
37 | return val.replace('"', '\"');
38 | };
39 | var setBodyValue = function(val) {
40 | editor.value(val);
41 | }
42 |
43 | // set up markdown parser
44 | var parseMD = function(data) {
45 | if (data) {
46 | return editor.markdown(data);
47 | }
48 | return '';
49 | };
50 |
51 | // Get params from the URL
52 | var queryVals = (function(a) {
53 | if (a == "") return {};
54 | var b = {};
55 | for (var i = 0; i < a.length; ++i)
56 | {
57 | var p=a[i].split('=', 2);
58 | if (p.length == 1)
59 | b[p[0]] = "";
60 | else
61 | b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
62 | }
63 | return b;
64 | })(window.location.search.substr(1).split('&'));
65 |
66 | var defaultUser = {
67 | name: "John Doe",
68 | webid: "https://example.org/user#me",
69 | picture: "img/icon-blue.svg",
70 | authenticated: false
71 | };
72 |
73 | var user = {};
74 | var posts = {};
75 | var authors = {};
76 | var webSockets = {};
77 |
78 | // Initializer
79 | var init = function(configData) {
80 | // set config params
81 | applyConfig(configData);
82 |
83 | // try to load authors
84 | loadLocalAuthors();
85 |
86 | // Add online/offline events
87 | Solid.status.onOffline(function(){
88 | notify('info', "You are no longer connected to the internet.", 3000);
89 | });
90 | Solid.status.onOnline(function(){
91 | notify('info', "And we're back!");
92 | });
93 | // Init growl-like notifications
94 | window.addEventListener('load', function () {
95 | Notification.requestPermission(function (status) {
96 | // This allows to use Notification.permission with Chrome/Safari
97 | if (Notification.permission !== status) {
98 | Notification.permission = status;
99 | }
100 | });
101 | });
102 |
103 | // basic app routes
104 | if (queryVals['post'] && queryVals['post'].length > 0) {
105 | var url = decodeURIComponent(queryVals['post']);
106 | showViewer(url);
107 | return;
108 | } else if (queryVals['view'] && queryVals['view'].length > 0) {
109 | // legacy [to be deprecated]
110 | var url = decodeURIComponent(queryVals['view']);
111 | showViewer(url);
112 | return;
113 | } else if (queryVals['edit'] && queryVals['edit'].length > 0) {
114 | var url = decodeURIComponent(queryVals['edit']);
115 | showEditor(url);
116 | return;
117 | } else if (queryVals['new'] !== undefined) {
118 | clearPendingPost();
119 | showEditor();
120 | return;
121 | } else if (queryVals['blog'] && queryVals['blog'].length > 0) {
122 | config.loadInBg = false;
123 | showBlog(queryVals['blog']);
124 | return;
125 | } else {
126 | // Load posts or initialize post container
127 | config.loadInBg = false;
128 | if (config.postsURL && config.postsURL.length > 0) {
129 | showBlog(config.postsURL);
130 | } else {
131 | showInitDialog();
132 | }
133 | }
134 | };
135 |
136 | // Set default config values
137 | var applyConfig = function(configData) {
138 | // loaded config from file
139 | config.defaultPath = 'posts';
140 | if (configData) {
141 | config = configData;
142 | // append trailing slash to data path if missing
143 | if (config.defaultPath.lastIndexOf('/') < 0) {
144 | config.defaultPath += '/';
145 | }
146 | config.saveDate = Date.now();
147 | saveLocalStorage();
148 | } else {
149 | // try to load config from localStorage
150 | console.log("Loading config from localStorage");
151 | loadLocalStorage();
152 | }
153 |
154 | document.querySelector('.blog-picture').src = config.picture;
155 | document.querySelector('.blog-title').innerHTML = config.title;
156 | document.querySelector('title').innerHTML = config.title;
157 | document.querySelector('.blog-tagline').innerHTML = config.tagline;
158 | // set default parent element for posts
159 | config.postsElement = '.posts';
160 |
161 | if (user.authenticated) {
162 | hideLogin();
163 | }
164 |
165 | // append trailing slash to data path if missing
166 | if (config.defaultPath.lastIndexOf('/') < 0) {
167 | config.defaultPath += '/';
168 | }
169 | if (!config.postsURL || config.postsURL.length === 0) {
170 | config.postsURL = appURL + config.defaultPath;
171 | }
172 |
173 | config.loadInBg = true;
174 | };
175 |
176 | // show a particular blog
177 | var showBlog = function(url) {
178 | // show loading
179 | if (!config.loadInBg) {
180 | showLoading();
181 | }
182 | fetchPosts(url);
183 | };
184 |
185 | // Init data container
186 | var initContainer = function(url) {
187 | Solid.web.head(url).then(
188 | function(container) {
189 | // create data container for posts if it doesn't exist
190 | if (!container.exists && container.xhr.status < 500) {
191 | Solid.web.post(appURL, config.defaultPath, null, true).then(
192 | function(res) {
193 | if (res.url && res.url.length > 0) {
194 | config.postsURL = res.url;
195 | }
196 | // add dummy post
197 | var acme = {
198 | title: "Welcome to Plume, a Solid blogging platform",
199 | author: user.webid,
200 | date: "3 Dec 2015",
201 | body: "```\nHellowWorld();\n```\n\n**Note!** This is a demo post created under your name. Feel free to remove it whenever you wish.\n\n*Plume* is a 100% client-side application built using [Solid standards](https://github.com/solid/), in which data is decoupled from the application itself. This means that you can host the application on any Web server, without having to install anything -- no database, no messing around with Node.js, it has 0 dependencies! It also means that other similar applications will be able to reuse the data resulting from your posts, without having to go through a complicated API.\n\nPlume uses [Markdown](https://en.wikipedia.org/wiki/Markdown) to provide you with the easiest and fastest experience for writing beautiful articles. Click the *Edit* button below to see this article.\n\nGive it a try, write your first post!",
202 | tags: [
203 | { color: "#df2d4f", name: "Decentralization" },
204 | { color: "#4d85d1", name: "Solid" }
205 | ]
206 | };
207 | savePost(acme);
208 | }
209 | )
210 | .catch(
211 | function(err) {
212 | console.log("Could not create data container for posts.");
213 | console.log(err);
214 | notify('error', 'Could not create data container');
215 | }
216 | );
217 | } else if (container.exists) {
218 | config.postsURL = appURL+config.defaultPath;
219 | fetchPosts(url);
220 | }
221 | }
222 | );
223 | }
224 |
225 | // Log user in
226 | var login = function() {
227 | // Get the current user
228 | Solid.auth.login().then(function(webid){
229 | gotWebID(webid);
230 | }).catch(function(err) {
231 | console.log(err);
232 | notify('error', "Authentication failed");
233 | showError(err);
234 | });
235 | };
236 | // Signup for a WebID and space
237 | var signup = function() {
238 | Solid.auth.signup().then(function(webid) {
239 | gotWebID(webid);
240 | }).catch(function(err) {
241 | console.log("Err", err);
242 | notify('error', "Authentication failed");
243 | showError(err);
244 | });
245 | };
246 | // Log user out
247 | var logout = function() {
248 | user = defaultUser;
249 | clearLocalStorage();
250 | showLogin();
251 | window.location.reload();
252 | };
253 |
254 | // set the logged in user
255 | var gotWebID = function(webid) {
256 | // set WebID
257 | user.webid = webid;
258 | user.authenticated = true;
259 | hideLogin();
260 | // fetch and set user profile
261 | Solid.identity.getProfile(webid).then(function(g) {
262 | var profile = getUserProfile(webid, g);
263 | user.name = profile.name;
264 | user.picture = profile.picture;
265 | user.date = Date.now();
266 | // add self to authors list
267 | authors[webid] = user;
268 | saveLocalAuthors();
269 | // add workspaces
270 | Solid.identity.getWorkspaces(webid, g).then(function(ws){
271 | user.workspaces = ws;
272 | // save to local storage and refresh page
273 | saveLocalStorage();
274 | window.location.reload();
275 | }).catch(function(err) {
276 | showError(err);
277 | // save to local storage and refresh page
278 | saveLocalStorage();
279 | window.location.reload();
280 | });
281 | });
282 | };
283 |
284 | // get profile data for a given user
285 | // Returns
286 | // webid: "https://example.org/user#me"
287 | // name: "John Doe",
288 | // picture: "https://example.org/profile.png"
289 | var getUserProfile = function(webid, g) {
290 | var profile = {};
291 |
292 | if (!g) {
293 | return profile;
294 | }
295 |
296 | var webidRes = $rdf.sym(webid);
297 |
298 | // set webid
299 | profile.webid = webid;
300 |
301 | // set name
302 | var name = g.any(webidRes, FOAF('name'));
303 | if (name && name.value.length > 0) {
304 | profile.name = name.value;
305 | } else {
306 | profile.name = '';
307 | // use familyName and givenName instead of full name
308 | var givenName = g.any(webidRes, FOAF('familyName'));
309 | if (givenName) {
310 | profile.name += givenName.value;
311 | }
312 | var familyName = g.any(webidRes, FOAF('familyName'));
313 | if (familyName) {
314 | profile.name += (givenName)?' '+familyName.value:familyName.value;
315 | }
316 | // use nick
317 | if (!givenName && !familyName) {
318 | var nick = g.any(webidRes, FOAF('nick'));
319 | if (nick) {
320 | profile.name = nick.value;
321 | }
322 | }
323 | }
324 |
325 | // set picture
326 | var pic, img = g.any(webidRes, FOAF('img'));
327 | if (img) {
328 | pic = img;
329 | } else {
330 | // check if profile uses depic instead
331 | var depic = g.any(webidRes, FOAF('depiction'));
332 | if (depic) {
333 | pic = depic;
334 | }
335 | }
336 | if (pic && pic.uri.length > 0) {
337 | profile.picture = pic.uri;
338 | }
339 |
340 | return profile;
341 | };
342 |
343 | var confirmDelete = function(url) {
344 | var postTitle = (posts[url].title)?''+posts[url].title+'
':'this post';
345 | var div = document.createElement('div');
346 | div.id = 'delete';
347 | div.classList.add('dialog');
348 | var section = document.createElement('section');
349 | section.innerHTML = "You are about to delete "+postTitle;
350 | div.appendChild(section);
351 |
352 | var footer = document.createElement('footer');
353 |
354 | var del = document.createElement('button');
355 | del.classList.add("button");
356 | del.classList.add('danger');
357 | del.classList.add('float-left');
358 | del.setAttribute('onclick', 'Plume.deletePost(\''+url+'\')');
359 | del.innerHTML = 'Delete';
360 | footer.appendChild(del);
361 | // delete button
362 | var cancel = document.createElement('button');
363 | cancel.classList.add('button');
364 | cancel.classList.add('float-right');
365 | cancel.setAttribute('onclick', 'Plume.cancelDelete()');
366 | cancel.innerHTML = 'Cancel';
367 | footer.appendChild(cancel);
368 | div.appendChild(footer);
369 |
370 | // append to body
371 | document.querySelector('body').appendChild(div);
372 | };
373 |
374 | var cancelDelete = function() {
375 | document.getElementById('delete').remove();
376 | };
377 |
378 | var deletePost = function(url) {
379 | if (url) {
380 | Solid.web.del(url).then(
381 | function(done) {
382 | if (done) {
383 | delete posts[url];
384 | document.getElementById(url).remove();
385 | document.getElementById('delete').remove();
386 | notify('success', 'Successfully deleted post');
387 | resetAll(true);
388 | }
389 | }
390 | )
391 | .catch(
392 | function(err) {
393 | notify('error', 'Could not delete post');
394 | resetAll();
395 | }
396 | );
397 | }
398 | };
399 |
400 | var showError = function(err) {
401 | if (!err || !err.xhr) {
402 | return;
403 | }
404 | hideLoading();
405 | var url = err.xhr.requestedURI;
406 | var errorText = '';
407 | if (err.status > 400 && err.status < 500) {
408 | errorText = "Could not fetch URL";
409 | }
410 | document.querySelector('.error-title').innerHTML = errorText + ' - ' + err.status;
411 | document.querySelector('.error-url').innerHTML = document.querySelector('.error-url').href = url;
412 | document.querySelector('.error').classList.remove('hidden');
413 | };
414 |
415 | var showViewer = function(url) {
416 | window.history.pushState("", document.querySelector('title').value, window.location.pathname+"?post="+encodeURIComponent(url));
417 | // hide main page
418 | document.querySelector(config.postsElement).classList.add('hidden');
419 | var viewer = document.querySelector('.viewer');
420 | viewer.classList.remove('hidden');
421 |
422 | var article = postToHTML(posts[url]);
423 | if (!article) {
424 | showLoading();
425 | fetchPost(url).then(
426 | function(post) {
427 | // convert post to HTML
428 | posts[url] = post;
429 | hideLoading();
430 | showViewer(url);
431 | }
432 | ).catch(
433 | function(err) {
434 | showError(err);
435 | }
436 | );
437 | return;
438 | }
439 |
440 | // Update document title
441 | if (posts[url] && posts[url].title) {
442 | document.querySelector('title').innerHTML += ' - ' + posts[url].title;
443 | }
444 |
445 | // add last modified date
446 | if (posts[url].modified && posts[url].modified != posts[url].created) {
447 | var modDate = document.createElement('p');
448 | modDate.innerHTML += ' '+"Last updated "+formatDate(posts[url].modified, 'LLL')+' ';
449 | article.querySelector('section').appendChild(modDate);
450 | }
451 |
452 | // append article
453 | viewer.appendChild(article);
454 | var footer = document.createElement('footer');
455 | viewer.appendChild(footer);
456 | // add separator
457 | var sep = document.createElement('h1');
458 | sep.classList.add('content-subhead');
459 | footer.appendChild(sep);
460 | // create button list
461 | var buttonList = document.createElement('div');
462 | // add back button
463 | var back = document.createElement('a');
464 | back.classList.add("action-button");
465 | back.href = window.location.pathname;
466 | back.innerHTML = '≪ Back to blog';
467 | buttonList.appendChild(back);
468 | // add view source
469 | if (config.showSources) {
470 | var src = document.createElement('a');
471 | src.classList.add("action-button");
472 | src.href = url;
473 | src.target = '_blank';
474 | src.innerHTML = 'View data';
475 | buttonList.appendChild(src);
476 | }
477 | // append button list to viewer
478 | footer.appendChild(buttonList);
479 | }
480 |
481 | var showEditor = function(url) {
482 | if (!user.authenticated) {
483 | notify('all', "You must log in before creating or editing posts.");
484 | return;
485 | }
486 |
487 | // make sure we're entering in edit mode
488 | if (editor.isPreviewActive()) {
489 | togglePreview();
490 | }
491 | // hide nav button
492 | document.getElementById('menu-button').classList.add('hidden');
493 | // handle tags
494 | var tags = document.querySelector('.editor-tags');
495 | var appendTag = function(name, color) {
496 | var tagDiv = document.createElement('div');
497 | tagDiv.classList.add('post-category');
498 | tagDiv.classList.add('inline-block');
499 | if (color) {
500 | tagDiv.setAttribute('style', 'background:'+color+';');
501 | }
502 | var span = document.createElement('span');
503 | span.innerHTML = name;
504 | tagDiv.appendChild(span);
505 | var tagLink = document.createElement('a');
506 | tagLink.setAttribute('onclick', 'this.parentElement.remove()');
507 | tagLink.innerHTML = 'x';
508 | tagDiv.appendChild(tagLink);
509 | tags.appendChild(tagDiv);
510 | // clear input
511 | document.querySelector('.editor-add-tag').value = '';
512 | };
513 |
514 | var loadPost = function(url) {
515 | var post = posts[url];
516 | if (post.title) {
517 | document.querySelector('.editor-title').value = post.title;
518 | // Also update document title
519 | document.querySelector('title').innerHTML += ' - Editing - ' + posts[url].title;
520 | }
521 | if (post.author) {
522 | var author = getAuthorByWebID(post.author);
523 | document.querySelector('.editor-author').innerHTML = author.name;
524 | }
525 | if (post.created) {
526 | document.querySelector('.editor-date').innerHTML = formatDate(post.created);
527 | }
528 |
529 | // add tags
530 | if (post.tags && post.tags.length > 0) {
531 | var tagInput = document.createElement('input');
532 | for (var i in post.tags) {
533 | var tag = post.tags[i];
534 | if (tag.name && tag.name.length > 0) {
535 | appendTag(tag.name, tag.color);
536 | }
537 | }
538 |
539 | }
540 | if (post.body) {
541 | setBodyValue(decodeHTML(post.body));
542 | }
543 |
544 | document.querySelector('.publish').innerHTML = "Update";
545 | document.querySelector('.publish').setAttribute('onclick', 'Plume.publishPost(\''+url+'\')');
546 | window.history.pushState("", document.querySelector('title').value, window.location.pathname+"?edit="+encodeURIComponent(url));
547 | };
548 |
549 | document.querySelector('.posts').classList.add('hidden');
550 | document.querySelector('.viewer').classList.add('hidden');
551 | document.querySelector('.start').classList.add('hidden');
552 | document.querySelector('.editor').classList.remove('hidden');
553 | document.querySelector('.editor-title').focus();
554 | document.querySelector('.editor-author').innerHTML = user.name;
555 | document.querySelector('.editor-date').innerHTML = formatDate();
556 | document.querySelector('.editor-tags').innerHTML = '';
557 |
558 | // add event listener and set up tags
559 | // document.querySelector('.editor-add-tag').value = '';
560 | // document.querySelector('.editor-add-tag').onkeypress = function(e){
561 | // if (!e) e = window.event;
562 | // var keyCode = e.keyCode || e.which;
563 | // if (keyCode == '13'){
564 | // appendTag(document.querySelector('.editor-add-tag').value, document.querySelector('.color-picker').style.background);
565 | // }
566 | // }
567 |
568 | // preload data if updating
569 | if (url && url.length > 0) {
570 | if (posts[url]) {
571 | loadPost(url);
572 | } else {
573 | fetchPost(url).then(
574 | function(post) {
575 | loadPost(url);
576 | }
577 | );
578 | }
579 | } else {
580 | // resume post if we have data
581 | var post = loadPendingPost();
582 | if (post) {
583 | setBodyValue(post.body);
584 | document.querySelector('.editor-title').value = post.title;
585 | }
586 | document.querySelector('.publish').innerHTML = "Publish";
587 | document.querySelector('.publish').setAttribute('onclick', 'Plume.publishPost()');
588 | }
589 | };
590 |
591 | var publishPost = function(url) {
592 | var post = (url)?posts[url]:{};
593 | post.title = trim(document.querySelector('.editor-title').value);
594 | post.body = getBodyValue();
595 | post.tags = [];
596 | var allTags = document.querySelectorAll('.editor-tags .post-category');
597 | for (var i in allTags) {
598 | if (allTags[i].style) {
599 | var tag = {};
600 | tag.name = allTags[i].querySelector('span').innerHTML;
601 | tag.color = rgbToHex(allTags[i].style.background);
602 | post.tags.push(tag);
603 | }
604 | }
605 |
606 | post.modified = moment().utcOffset('00:00').format("YYYY-MM-DDTHH:mm:ssZ");
607 |
608 | if (!url) {
609 | post.author = user.webid;
610 | post.created = post.modified;
611 | }
612 |
613 | savePost(post, url);
614 | };
615 |
616 | // save post data to server
617 | var savePost = function(post, url) {
618 | //TODO also write tags - use sioc:topic -> uri
619 | var g = new $rdf.graph();
620 | g.add($rdf.sym(''), RDF('type'), SIOC('Post'));
621 | g.add($rdf.sym(''), DCT('title'), $rdf.lit(post.title));
622 | g.add($rdf.sym(''), SIOC('has_creator'), $rdf.sym('#author'));
623 | g.add($rdf.sym(''), DCT('created'), $rdf.lit(post.created, '', $rdf.Symbol.prototype.XSDdateTime));
624 | g.add($rdf.sym(''), DCT('modified'), $rdf.lit(post.modified, '', $rdf.Symbol.prototype.XSDdateTime));
625 | g.add($rdf.sym(''), SIOC('content'), $rdf.lit(encodeHTML(post.body)));
626 |
627 | g.add($rdf.sym('#author'), RDF('type'), SIOC('UserAccount'));
628 | g.add($rdf.sym('#author'), SIOC('account_of'), $rdf.sym(post.author));
629 | g.add($rdf.sym('#author'), FOAF('name'), $rdf.lit(authors[post.author].name));
630 | g.add($rdf.sym('#author'), SIOC('avatar'), $rdf.sym(authors[post.author].picture));
631 |
632 | var triples = new $rdf.Serializer(g).toN3(g);
633 |
634 | if (url) {
635 | var writer = Solid.web.put(url, triples);
636 | } else {
637 | var slug = makeSlug(post.title);
638 | var writer = Solid.web.post(config.postsURL, slug, triples);
639 | }
640 | writer.then(
641 | function(res) {
642 | // all done, clean up and go to initial state
643 | if (res.url.slice(0,4) !== 'http') {
644 | res.url = config.postsURL.slice(0, config.postsURL.lastIndexOf('/') + 1)+slug;
645 | }
646 | cancelPost('?post='+encodeURIComponent(res.url));
647 | }
648 | )
649 | .catch(
650 | function(err) {
651 | console.log("Could not create post!");
652 | console.log(err);
653 | notify('error', 'Could not create post');
654 | resetAll();
655 | }
656 | );
657 | };
658 |
659 | var fetchPosts = function(url, showGrowl) {
660 | // select element holding all the posts
661 | var postsdiv = document.querySelector(config.postsElement);
662 | // clear previous posts
663 | postsdiv.innerHTML = '';
664 | // ask only for sioc:Post resources
665 | Solid.web.get(url).then(
666 | function(g) {
667 | var _posts = [];
668 | var st = g.statementsMatching(undefined, RDF('type'), SIOC('Post'));
669 | // fallback to containment triples
670 | if (st.length === 0) {
671 | st = g.statementsMatching($rdf.sym(url), LDP('contains'), undefined);
672 | st.forEach(function(s) {
673 | _posts.push(s.object.uri);
674 | })
675 | } else {
676 | st.forEach(function(s) {
677 | _posts.push(s.subject.uri);
678 | });
679 | }
680 |
681 | if (_posts.length === 0) {
682 | resetAll();
683 | hideLoading();
684 | if (user.authenticated) {
685 | document.querySelector('.start').classList.remove('hidden');
686 | } else {
687 | document.querySelector('.init').classList.remove('hidden');
688 | }
689 | }
690 |
691 | var toLoad = _posts.length;
692 | var isDone = function() {
693 | if (toLoad <= 0) {
694 | hideLoading();
695 | if (showGrowl) {
696 | growl("Updating...", "Finished updating your blog");
697 | }
698 | }
699 | }
700 |
701 | var sortedPosts = [];
702 | _posts.forEach(function(url){
703 | fetchPost(url).then(
704 | function(post) {
705 | if (len(post) === 0) {
706 | toLoad--;
707 | isDone();
708 | } else {
709 | // convert post to HTML
710 | var article = postToHTML(post, true);
711 |
712 | // sort array and add to dom
713 | // TODO improve it later
714 | sortedPosts.push({date: post.created, url: post.url});
715 | sortedPosts.sort(function(a,b) {
716 | var c = new Date(a.date);
717 | var d = new Date(b.date);
718 | return d-c;
719 | });
720 | for(var i=0; i 0) {
754 | socketSubscribe(meta.websocket, url);
755 | }
756 | }).catch(
757 | function(err) {
758 | showError(err);
759 | }
760 | );
761 | }
762 | )
763 | .catch(
764 | function(err) {
765 | showError(err);
766 | }
767 | );
768 | };
769 |
770 | var fetchPost = function(url) {
771 | var promise = new Promise(function(resolve, reject){
772 | Solid.web.get(url).then(
773 | function(g) {
774 | var subject = g.any(undefined, RDF('type'), SIOC('Post'));
775 |
776 | if (!subject) {
777 | subject = g.any(undefined, RDF('type'), SOLID('Notification'));
778 | }
779 |
780 | if (subject) {
781 | var post = { url: subject.uri };
782 |
783 | // add title
784 | var title = g.any(subject, DCT('title'));
785 | if (title && title.value) {
786 | post.title = encodeHTML(title.value);
787 | }
788 |
789 | // add author
790 | var author = {};
791 | var creator = g.any(subject, SIOC('has_creator'));
792 | if (creator) {
793 | var accountOf = g.any(creator, SIOC('account_of'));
794 | if (accountOf) {
795 | post.author = encodeHTML(accountOf.uri);
796 | author.webid = post.author;
797 | }
798 | var name = g.any(creator, FOAF('name'));
799 | if (name && name.value && name.value.length > 0) {
800 | author.name = encodeHTML(name.value);
801 | }
802 | var picture = g.any(creator, SIOC('avatar'));
803 | if (picture) {
804 | author.picture = encodeHTML(picture.uri);
805 | }
806 | } else {
807 | creator = g.any(subject, DCT('creator'));
808 | if (creator) {
809 | post.author = encodeHTML(creator.uri);
810 | }
811 | }
812 | // add to list of authors if not self
813 | if (post.author && post.author != user.webid && !authors[post.author]) {
814 | authors[post.author] = author;
815 | // save list to localStorage
816 | saveLocalAuthors();
817 | }
818 | // update author info with fresh data
819 | if (post.author && post.author.length >0) {
820 | updateAuthorInfo(post.author, url);
821 | }
822 |
823 | // add created date
824 | var created = g.any(subject, DCT('created'));
825 | if (created) {
826 | post.created = created.value;
827 | }
828 |
829 | // add modified date
830 | var modified = g.any(subject, DCT('modified'));
831 | if (modified) {
832 | post.modified = modified.value;
833 | } else {
834 | post.modified = post.created;
835 | }
836 |
837 | // add body
838 | var body = g.any(subject, SIOC('content'));
839 | if (body) {
840 | post.body = body.value;
841 | }
842 |
843 | // add post to local list
844 | posts[post.url] = post;
845 | resolve(post);
846 | } else {
847 | resolve({});
848 | }
849 | }
850 | )
851 | .catch(
852 | function(err) {
853 | reject(err);
854 | }
855 | );
856 | });
857 |
858 | return promise;
859 | };
860 |
861 | // update author details with more recent data
862 | // TODO add date of last update to avoid repeated fetches
863 | var updateAuthorInfo = function(webid, url) {
864 | // check if it really needs updating first
865 | if (webid == user.webid || authors[webid].updated || authors[webid].lock) {
866 | return;
867 | }
868 | authors[webid].lock = true;
869 | Solid.identity.getProfile(webid).
870 | then(function(g) {
871 | var profile = getUserProfile(webid, g);
872 | if (len(profile) > 0) {
873 | authors[webid].updated = true;
874 | authors[webid].name = profile.name;
875 | authors[webid].picture = profile.picture;
876 | // save to localStorage
877 | saveLocalAuthors();
878 | // release lock
879 | authors[webid].lock = false;
880 | if (url && posts[url]) {
881 | var postId = document.getElementById(url);
882 | if (profile.name && postId) {
883 | postId.querySelector('.post-author').innerHTML = profile.name;
884 | postId.querySelector('.post-avatar').title = profile.name+"'s picture";
885 | postId.querySelector('.post-avatar').alt = profile.name+"'s picture";
886 | }
887 | if (profile.picture && postId) {
888 | postId.querySelector('.post-avatar').src = profile.picture;
889 | }
890 | }
891 | }
892 | }).
893 | catch(function(err) {
894 | console.log(err);
895 | });
896 | };
897 |
898 | var getAuthorByWebID = function(webid) {
899 | var name = 'Unknown';
900 | var picture = 'img/icon-blue.svg';
901 | if (webid && webid.length > 0) {
902 | var author = authors[webid];
903 | if (author && author.name) {
904 | name = author.name;
905 | }
906 | if (author && author.picture) {
907 | picture = author.picture;
908 | }
909 | }
910 | return {name: name, picture: picture};
911 | };
912 |
913 | var postToHTML = function(post, makeLink) {
914 | // change separator: Recent Posts
915 | if (!post) {
916 | return;
917 | }
918 | var author = getAuthorByWebID(post.author);
919 | var name = author.name;
920 | var picture = author.picture;
921 |
922 | // create main post element
923 | var article = document.createElement('article');
924 | article.classList.add('post');
925 | article.id = post.url;
926 |
927 | // create header
928 | var header = document.createElement('header');
929 | header.classList.add('post-header');
930 | // append header to article
931 | article.appendChild(header);
932 |
933 | // set avatar
934 | var avatar = document.createElement('img');
935 | avatar.classList.add('post-avatar');
936 | avatar.src = picture;
937 | avatar.alt = avatar.title = name+"'s picture";
938 | // append picture to header
939 | var avatarLink = document.createElement('a');
940 | avatarLink.href = post.author;
941 | avatarLink.setAttribute('target', '_blank');
942 | avatarLink.appendChild(avatar);
943 | header.appendChild(avatarLink);
944 |
945 | // add meta data
946 | var meta = document.createElement('div');
947 | meta.classList.add('post-meta');
948 | // append meta to header
949 | header.appendChild(meta);
950 |
951 | // create meta author
952 | var metaAuthor = document.createElement('a');
953 | metaAuthor.classList.add('post-author');
954 | metaAuthor.href = post.author;
955 | metaAuthor.setAttribute('target', '_blank');
956 | metaAuthor.innerHTML = name;
957 | // append meta author to meta
958 | meta.appendChild(metaAuthor);
959 |
960 | // add br
961 | meta.appendChild(document.createElement('br'));
962 |
963 | // create meta date
964 | var metaDate = document.createElement('span');
965 | metaDate.classList.add('post-date');
966 | metaDate.innerHTML = formatDate(post.created);
967 | // append meta date to meta
968 | meta.appendChild(metaDate);
969 |
970 | // create meta tags
971 | if (post.tags && post.tags.length > 0) {
972 | var metaTags = document.createElement('span');
973 | metaTags.classList.add('post-tags');
974 | metaTags.innerHTML = " under ";
975 | for (var i in post.tags) {
976 | var tag = post.tags[i];
977 | if (tag.name && tag.name.length > 0) {
978 | var tagLink = document.createElement('a');
979 | tagLink.classList.add('post-category');
980 | if (tag.color) {
981 | tagLink.setAttribute('style', 'background:'+tag.color+';');
982 | }
983 | tagLink.innerHTML = tag.name;
984 | tagLink.href = "#";
985 | tagLink.setAttribute('onclick', 'Plume.sortTag("'+tag.name+'")');
986 | metaTags.appendChild(tagLink);
987 | }
988 | }
989 |
990 | // append meta tag
991 | meta.appendChild(metaTags);
992 | }
993 |
994 | // create title
995 | var title = document.createElement('h1');
996 | title.classList.add('post-title');
997 | title.innerHTML = (post.title)?''+post.title+' ':'';
998 | // append title to body
999 | header.appendChild(title);
1000 |
1001 | // create body
1002 | var section = document.createElement('section');
1003 | section.classList.add('post-body');
1004 | article.appendChild(section);
1005 |
1006 | var bodyText = parseMD(decodeHTML(post.body));
1007 |
1008 | // add post body
1009 | if (makeLink) {
1010 | section.classList.add('clickable');
1011 | section.addEventListener('click', function (event) { window.location.replace('?post='+encodeURIComponent(post.url))});
1012 | }
1013 | section.innerHTML += bodyText;
1014 |
1015 | // add footer with action links
1016 | var footer = document.createElement('footer');
1017 |
1018 | if (user.webid == post.author) {
1019 | // edit button
1020 | var edit = document.createElement('a');
1021 | edit.classList.add("action-button");
1022 | edit.href = '?edit='+encodeURIComponent(post.url);
1023 | edit.setAttribute('title', 'Edit post');
1024 | edit.innerHTML = ' Edit';
1025 | footer.appendChild(edit);
1026 | // delete button
1027 | var del = document.createElement('a');
1028 | del.classList.add('action-button');
1029 | del.classList.add('danger-text');
1030 | del.setAttribute('onclick', 'Plume.confirmDelete(\''+post.url+'\')');
1031 | del.innerHTML = 'Delete';
1032 | footer.appendChild(del);
1033 | }
1034 |
1035 | // append footer to post
1036 | article.appendChild(footer);
1037 |
1038 | var sep = document.createElement('div');
1039 | sep.classList.add('separator');
1040 | article.appendChild(sep);
1041 |
1042 | // append article to list of posts
1043 | return article;
1044 | };
1045 |
1046 | // fade long text in articles
1047 | // TODO fix fade after updating post
1048 | var addTextFade = function(url) {
1049 | // get element current height
1050 | var article = document.getElementById(url);
1051 | if (url && article) {
1052 | var section = article.querySelector('section');
1053 | var height = section.offsetHeight;
1054 | // fade post contents if post is too long
1055 | if (height > 400) {
1056 | section.classList.add('less');
1057 | var fade = document.createElement('div');
1058 | fade.classList.add('fade-bottom');
1059 | fade.classList.add('center-text');
1060 | fade.innerHTML = '— '+"more — ";
1061 | article.insertBefore(fade, article.querySelector('footer'));
1062 | }
1063 | }
1064 | };
1065 |
1066 | // Websocket
1067 | var connectToSocket = function(wss, uri) {
1068 | if (!webSockets[wss]) {
1069 | var socket = new WebSocket(wss);
1070 | socket.onopen = function(){
1071 | this.send('sub ' + uri);
1072 | console.log("Connected to WebSocket at", wss);
1073 | }
1074 | socket.onmessage = function(msg){
1075 | if (msg.data && msg.data.slice(0, 3) === 'pub') {
1076 | // resource updated
1077 | var res = trim(msg.data.slice(3, msg.data.length));
1078 | console.log("Got new message: pub", res);
1079 | fetchPosts(res, true); //refetch posts and notify
1080 | }
1081 | }
1082 | socket.onclose = function() {
1083 | console.log("Websocket connection closed. Restarting...");
1084 | connectToSocket(wss, uri);
1085 | }
1086 | webSockets[wss] = socket;
1087 | }
1088 | };
1089 |
1090 | // Subscribe to changes to a URL
1091 | var socketSubscribe = function(wss, url) {
1092 | if (webSockets[wss]) {
1093 | webSockets[wss].send('sub '+url);
1094 | } else {
1095 | connectToSocket(wss, url);
1096 | }
1097 | };
1098 |
1099 | // Misc/helper functions
1100 | var sortTag = function(name) {
1101 | console.log(name);
1102 | };
1103 |
1104 | var notify = function(ntype, text, timeout) {
1105 | timeout = timeout || 1500;
1106 | var note = document.createElement('div');
1107 | note.classList.add('note');
1108 | note.innerHTML = text;
1109 | note.addEventListener('click', note.remove, false);
1110 |
1111 | switch (ntype) {
1112 | case 'success':
1113 | note.classList.add('success');
1114 | break;
1115 | case 'error':
1116 | timeout = 3000;
1117 | note.classList.add('danger');
1118 | var tip = document.createElement('small');
1119 | tip.classList.add('small');
1120 | tip.innerHTML = ' Tip: check console for debug information.';
1121 | note.appendChild(tip);
1122 | break;
1123 | case 'sticky':
1124 | timeout = 0;
1125 | note.classList.add('dark');
1126 | note.innerHTML += ' [dismiss] '
1127 | break;
1128 | default:
1129 | note.classList.add('dark');
1130 | }
1131 | document.querySelector('body').appendChild(note);
1132 | if (timeout > 0) {
1133 | setTimeout(function() {
1134 | note.remove();
1135 | }, timeout);
1136 | }
1137 | };
1138 |
1139 | // Send a browser notification
1140 | var growl = function(type, body, timeout) {
1141 | var icon = 'favicon.png';
1142 | if (!timeout) {
1143 | var timeout = 2000;
1144 | }
1145 |
1146 | // Let's check if the browser supports notifications
1147 | if (!("Notification" in window)) {
1148 | console.log("This browser does not support desktop notification");
1149 | }
1150 |
1151 | // At last, if the user already denied any notification, and you
1152 | // want to be respectful there is no need to bother him any more.
1153 | // Let's check if the user is okay to get some notification
1154 | if (Notification.permission === "granted") {
1155 | // If it's okay let's create a notification
1156 | var notification = new Notification(type, {
1157 | dir: "auto",
1158 | lang: "",
1159 | icon: icon,
1160 | body: body,
1161 | tag: "notif"
1162 | });
1163 | setTimeout(function() { notification.close(); }, timeout);
1164 | }
1165 | };
1166 | // Authorize browser notifications
1167 | function authorizeNotifications() {
1168 | var status = getNotifStatus();
1169 | // Let's check if the browser supports notifications
1170 | if (!("Notification" in window)) {
1171 | console.log("This browser does not support desktop notification");
1172 | }
1173 |
1174 | if (status !== 'granted') {
1175 | Notification.requestPermission(function (permission) {
1176 | // Whatever the user answers, we make sure we store the information
1177 | Notification.permission = permission;
1178 | });
1179 | } else if (status === 'granted') {
1180 | Notification.permission = 'denied';
1181 | }
1182 | };
1183 | // Browser notifications status
1184 | function getNotifStatus() {
1185 | // Let's check if the browser supports notifications
1186 | if (!("Notification" in window)) {
1187 | console.log("This browser does not support desktop notification");
1188 | return undefined
1189 | } else {
1190 | return Notification.permission;
1191 | }
1192 | };
1193 |
1194 | // Overlay
1195 | var toggleOverlay = function(elem) {
1196 | var overlay = document.querySelector(elem);
1197 | overlay.addEventListener('click', toggleOverlay);
1198 | overlay.style.visibility = (overlay.style.visibility == "visible") ? "hidden" : "visible";
1199 | };
1200 |
1201 | // Convert rgb() to #hex
1202 | var rgbToHex = function (color) {
1203 | color = color.replace(/\s/g,"");
1204 | var aRGB = color.match(/^rgb\((\d{1,3}[%]?),(\d{1,3}[%]?),(\d{1,3}[%]?)\)$/i);
1205 | if(aRGB)
1206 | {
1207 | color = '';
1208 | for (var i=1; i<=3; i++) color += Math.round((aRGB[i][aRGB[i].length-1]=="%"?2.55:1)*parseInt(aRGB[i])).toString(16).replace(/^(.)$/,'0$1');
1209 | }
1210 | else color = color.replace(/^#?([\da-f])([\da-f])([\da-f])$/i, '$1$1$2$2$3$3');
1211 | return '#'+color;
1212 | };
1213 |
1214 | var togglePreview = function() {
1215 | editor.togglePreview();
1216 | var text = document.querySelector('.preview');
1217 | text.innerHTML = (text.innerHTML=="View")?"Edit":"View";
1218 | };
1219 |
1220 | // check if user is among the owners list
1221 | var isOwner = function() {
1222 | if (config.owners && config.owners.indexOf(user.webid) >= 0) {
1223 | return true;
1224 | }
1225 | return false;
1226 | };
1227 |
1228 | // formatDate
1229 | var formatDate = function(date, style) {
1230 | style = style || 'LL';
1231 | if (moment().diff(moment(date), 'days') > 1) {
1232 | return moment(date).format(style);
1233 | } else {
1234 | return moment(date).fromNow();
1235 | }
1236 | };
1237 |
1238 | // sanitize strings
1239 | var trim = function (str) {
1240 | return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
1241 | }
1242 | var makeSlug = function (str) {
1243 | // replace white spaces and multiple dashes
1244 | str = str.replace(/\s+/g, '-').
1245 | replace(/-+/g, '-').
1246 | replace(/^-+/, '').
1247 | replace(/-*$/, '').
1248 | replace(/[^A-Za-z0-9-]/g, '').
1249 | toLowerCase();
1250 | str += '.ttl';
1251 | return str;
1252 | };
1253 |
1254 | // escape HTML code
1255 | var encodeHTML = function (html) {
1256 | return html
1257 | .replace(/&/g, "&")
1258 | .replace(//g, ">")
1260 | .replace(/"/g, """)
1261 | .replace(/'/g, "'");
1262 | };
1263 |
1264 | var decodeHTML = function (html) {
1265 | return html
1266 | .replace(/&/g, "&")
1267 | .replace(/</g, "<")
1268 | .replace(/>/g, ">")
1269 | .replace(/"/g, "\"")
1270 | .replace(/'/g, "'");
1271 | };
1272 | // compute length of objects based on its keys
1273 | var len = function(obj) {
1274 | return Object.keys(obj).length;
1275 | };
1276 |
1277 |
1278 | var setColor = function(color) {
1279 | document.querySelector('.color-picker').style.background = window.getComputedStyle(document.querySelector('.'+color), null).backgroundColor;
1280 | document.querySelector('.pure-menu-active').classList.remove('pure-menu-active');
1281 | document.querySelector('.editor-add-tag').focus();
1282 | };
1283 |
1284 | var cancelPost = function(url) {
1285 | clearPendingPost();
1286 | url = (url)?url:window.location.pathname;
1287 | window.location.replace(url);
1288 | };
1289 |
1290 | // reset to initial view
1291 | var resetAll = function(refresh) {
1292 | document.getElementById('menu-button').classList.remove('hidden');
1293 | if (isOwner()) {
1294 | showNewPostButton();
1295 | }
1296 | hideLoading();
1297 | document.querySelector('.init').classList.add('hidden');
1298 | document.querySelector('.editor').classList.add('hidden');
1299 | document.querySelector('.viewer').classList.add('hidden');
1300 | document.querySelector('.viewer').innerHTML = '';
1301 | document.querySelector('.posts').classList.remove('hidden');
1302 | // document.querySelector('.editor-add-tag').value = '';
1303 | if (posts && len(posts) === 0) {
1304 | if (user.authenticated) {
1305 | document.querySelector('.start').classList.remove('hidden');
1306 | } else {
1307 | document.querySelector('.init').classList.remove('hidden');
1308 | }
1309 | }
1310 | if (refresh) {
1311 | showBlog(config.postsURL);
1312 | } else {
1313 | window.history.pushState("", document.querySelector('title').value, window.location.pathname);
1314 | }
1315 | };
1316 |
1317 | // login / logout buttons + new post
1318 | var showLogin = function() {
1319 | document.getElementsByClassName('login')[0].classList.remove('hidden');
1320 | document.getElementsByClassName('logout')[0].classList.add('hidden');
1321 | hideNewPostButton();
1322 | };
1323 | var hideLogin = function() {
1324 | document.getElementsByClassName('login')[0].classList.add('hidden');
1325 | document.getElementsByClassName('logout')[0].classList.remove('hidden');
1326 | };
1327 | // loading animation
1328 | var hideLoading = function() {
1329 | document.querySelector('.loading').classList.add('hidden');
1330 | }
1331 | var showLoading = function() {
1332 | document.querySelector('.loading').classList.remove('hidden');
1333 | }
1334 | // new post button
1335 | var hideNewPostButton = function() {
1336 | document.querySelector('.new').classList.add('hidden');
1337 | };
1338 | var showNewPostButton = function() {
1339 | document.querySelector('.new').classList.remove('hidden');
1340 | };
1341 |
1342 | // save pending post text to localStorage
1343 | var savePendingPost = function(text) {
1344 | var post = {};
1345 | post.title = trim(document.querySelector('.editor-title').value);
1346 | post.body = text;
1347 | try {
1348 | localStorage.setItem(appURL+'pendingPost', JSON.stringify(post));
1349 | } catch(err) {
1350 | console.log(err);
1351 | }
1352 |
1353 | };
1354 | // load pending post text from localStorage
1355 | var loadPendingPost = function() {
1356 | try {
1357 | return JSON.parse(localStorage.getItem(appURL+'pendingPost'));
1358 | } catch(err) {
1359 | console.log(err);
1360 | }
1361 | };
1362 | var clearPendingPost = function() {
1363 | setBodyValue('');
1364 | try {
1365 | localStorage.removeItem(appURL+'pendingPost');
1366 | } catch(err) {
1367 | console.log(err);
1368 | }
1369 | }
1370 |
1371 | // save authors to localStorage
1372 | var saveLocalAuthors = function() {
1373 | try {
1374 | localStorage.setItem(appURL+'authors', JSON.stringify(authors));
1375 | } catch(err) {
1376 | console.log(err);
1377 | }
1378 | };
1379 | // clear localstorage authors data
1380 | var clearLocalAuthors = function() {
1381 | try {
1382 | localStorage.removeItem(appURL+'authors');
1383 | } catch(err) {
1384 | console.log(err);
1385 | }
1386 | };
1387 | // clear localstorage config data
1388 | var loadLocalAuthors = function() {
1389 | try {
1390 | var data = JSON.parse(localStorage.getItem(appURL+'authors'));
1391 | if (data) {
1392 | authors = data;
1393 | }
1394 | } catch(err) {
1395 | console.log(err);
1396 | }
1397 | };
1398 |
1399 | // save config data to localStorage
1400 | var saveLocalStorage = function() {
1401 | var data = {
1402 | user: user,
1403 | config: config
1404 | };
1405 | try {
1406 | localStorage.setItem(appURL, JSON.stringify(data));
1407 | } catch(err) {
1408 | console.log(err);
1409 | }
1410 | };
1411 | // clear localstorage config data
1412 | var clearLocalStorage = function() {
1413 | try {
1414 | localStorage.removeItem(appURL);
1415 | } catch(err) {
1416 | console.log(err);
1417 | }
1418 | };
1419 | var loadLocalStorage = function() {
1420 | try {
1421 | var data = JSON.parse(localStorage.getItem(appURL));
1422 | if (data) {
1423 | // don't let session data become stale (24h validity)
1424 | var dateValid = data.config.saveDate + 1000 * 60 * 60 * 24;
1425 | if (Date.now() < dateValid) {
1426 | config = data.config;
1427 | user = data.user;
1428 | if (user.authenticated) {
1429 | hideLogin();
1430 | }
1431 | if (isOwner()) {
1432 | showNewPostButton();
1433 | }
1434 | } else {
1435 | console.log("Deleting localStorage data because it expired");
1436 | localStorage.removeItem(appURL);
1437 | }
1438 | } else {
1439 | // clear sessionStorage in case there was a change to the data structure
1440 | localStorage.removeItem(appURL);
1441 | }
1442 | } catch(err) {
1443 | notify('sticky', 'Persistence functionality is disabled while cookies are disabled.');
1444 | console.log(err);
1445 | }
1446 | };
1447 |
1448 |
1449 |
1450 | // ----- INIT -----
1451 | // start app by loading the config file
1452 | applyConfig();
1453 | var http = new XMLHttpRequest();
1454 | http.open('get', 'config.json');
1455 | http.onreadystatechange = function() {
1456 | if (this.readyState == this.DONE) {
1457 | init(JSON.parse(this.response));
1458 | }
1459 | };
1460 | http.send();
1461 |
1462 |
1463 |
1464 | // return public functions
1465 | return {
1466 | notify: notify,
1467 | user: user,
1468 | posts: posts,
1469 | login: login,
1470 | logout: logout,
1471 | signup: signup,
1472 | resetAll: resetAll,
1473 | cancelPost: cancelPost,
1474 | showEditor: showEditor,
1475 | showViewer: showViewer,
1476 | setColor: setColor,
1477 | publishPost: publishPost,
1478 | confirmDelete: confirmDelete,
1479 | cancelDelete: cancelDelete,
1480 | deletePost: deletePost,
1481 | togglePreview: togglePreview,
1482 | toggleOverlay: toggleOverlay,
1483 | growl: growl
1484 | };
1485 | }(this));
1486 |
1487 |
1488 | Plume.menu = (function() {
1489 | var ESCAPE_CODE = 27;
1490 |
1491 | var navButton = document.getElementById('menu-button'),
1492 | navMenu = document.getElementById('global-nav'),
1493 | mainDiv = document.getElementById('main');
1494 |
1495 | var navLinks = navMenu.getElementsByTagName('a');
1496 |
1497 | function handleKeydown(event) {
1498 | event.preventDefault();
1499 | if (event.keyCode === ESCAPE_CODE) {
1500 | document.body.classList.toggle('active');
1501 | disableNavLinks();
1502 | navButton.focus();
1503 | }
1504 | };
1505 | function handleClick(event) {
1506 | event.preventDefault();
1507 | if (document.body.classList.contains('active')) {
1508 | document.body.classList.remove('active');
1509 | disableNavLinks();
1510 | }
1511 | else {
1512 | document.body.classList.add('active');
1513 | enableNavLinks();
1514 | navLinks[0].focus();
1515 | }
1516 | };
1517 | function forceClose(event) {
1518 | if (document.body.classList.contains('active')) {
1519 | document.body.classList.remove('active');
1520 | disableNavLinks();
1521 | }
1522 | };
1523 | function enableNavLinks() {
1524 | navButton.removeAttribute('aria-label', 'Menu expanded');
1525 | navMenu.removeAttribute('aria-hidden');
1526 | for (var i=0; i