├── .npmignore ├── bin ├── build-dependency-less.sh ├── build-dependency-css.sh ├── build.sh ├── build-dependency-js.sh └── airpub-bootstrap.less ├── .gitignore ├── src ├── controllers │ ├── global.js │ ├── meta.js │ ├── archive.js │ ├── base.js │ ├── single.js │ └── admin.js ├── services │ └── share.js ├── filters │ └── marked.js ├── addons │ └── meta.js └── airpub.js ├── configs-sample.js ├── LICENSE ├── index.html ├── bower.json ├── package.json ├── dev.html ├── README.md ├── libs ├── ui-bootstrap-custom-0.12.0.min.js └── ui-bootstrap-custom-tpls-0.12.0.min.js └── dist ├── airpub.min.js ├── airpub.min.js.map └── airpub-dependencies.min.css /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_* 2 | thumb 3 | node_modules 4 | *.sublime* 5 | *.log 6 | bower_* 7 | configs.js 8 | editor 9 | csrf* -------------------------------------------------------------------------------- /bin/build-dependency-less.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | node_modules/.bin/lessc -x \ 4 | bin/airpub-bootstrap.less \ 5 | dist/airpub-bootstrap.min.css 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_* 2 | thumb 3 | node_modules 4 | *.sublime* 5 | *.log 6 | bower_* 7 | configs.js 8 | editor 9 | csrf* 10 | dist/*-bootstrap.min.css -------------------------------------------------------------------------------- /bin/build-dependency-css.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | node_modules/.bin/cleancss \ 4 | dist/airpub-bootstrap.min.css \ 5 | bower_components/nprogress/nprogress.css \ 6 | bower_components/highlightjs/styles/github.css \ 7 | -o dist/airpub-dependencies.min.css \ 8 | --s0 \ 9 | --debug -------------------------------------------------------------------------------- /src/controllers/global.js: -------------------------------------------------------------------------------- 1 | ;(function(angular, debug) { 2 | 'use strict'; 3 | 4 | angular 5 | .module('airpub') 6 | .controller('global', ['$scope', globalCtrler]); 7 | 8 | function globalCtrler($scope) { 9 | if (!airpubConfigs) 10 | return console.error(new Error('airpub 缺少必要的配置文件!')); 11 | 12 | $scope.configs = airpubConfigs; 13 | } 14 | })(window.angular, window.debug); 15 | -------------------------------------------------------------------------------- /bin/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | node_modules/.bin/uglifyjs \ 4 | src/airpub.js \ 5 | src/filters/marked.js \ 6 | src/services/share.js \ 7 | src/controllers/global.js \ 8 | src/controllers/meta.js \ 9 | src/controllers/base.js \ 10 | src/controllers/archive.js \ 11 | src/controllers/single.js \ 12 | src/controllers/admin.js \ 13 | src/addons/meta.js \ 14 | --mangle \ 15 | --compress \ 16 | -o dist/airpub.min.js \ 17 | --source-map dist/airpub.min.js.map \ 18 | --source-map-url airpub.min.js.map -------------------------------------------------------------------------------- /bin/build-dependency-js.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | node_modules/.bin/uglifyjs \ 4 | bower_components/angular/angular.min.js \ 5 | bower_components/angular-sanitize/angular-sanitize.min.js \ 6 | libs/ui-bootstrap-custom-0.12.0.min.js \ 7 | libs/ui-bootstrap-custom-tpls-0.12.0.min.js \ 8 | bower_components/angular-ui-router/release/angular-ui-router.min.js \ 9 | bower_components/oclazyload/dist/ocLazyLoad.min.js \ 10 | bower_components/nprogress/nprogress.js \ 11 | bower_components/duoshuo/dist/duoshuo.min.js \ 12 | bower_components/upyun/dist/upyun.min.js \ 13 | --mangle \ 14 | --compress \ 15 | -o dist/airpub-dependencies.min.js \ 16 | --source-map dist/airpub-dependencies.min.js.map \ 17 | --source-map-url airpub-dependencies.min.js.map -------------------------------------------------------------------------------- /configs-sample.js: -------------------------------------------------------------------------------- 1 | var airpubConfigs = {}; 2 | 3 | // 博客名称 4 | airpubConfigs.name = 'Airpub'; 5 | 6 | // 简单介绍 7 | airpubConfigs.description = '轻如蝉翼的写作工具'; 8 | 9 | // 博客首页的固定链接 10 | airpubConfigs.url = 'http://yourUri.com'; 11 | 12 | // 又拍云上传配置 13 | // 推荐使用 upyun-sign 生成短期签名的方式,不暴露 key 实现上传 14 | // 具体可以参考 https://github.com/turingou/upyun-sign 15 | airpubConfigs.upyun = { 16 | sign: '', // upyun-sign 生成的签名 17 | policy: '', // upyun-sign 生成的 policy 18 | // bucket: 'mybucket', 19 | // form_api_secret: 'xxxxxx', // 可选参数 20 | // uri: 'http://{{bucketName}}.b0.upaiyun.com', // 可选参数 21 | // endpoint: 'http://v0.api.upyun.com/{{bucketName}}', // 可选参数 22 | }; 23 | 24 | // 多说配置 25 | var duoshuoQuery = { 26 | short_name: '{{your_duoshuo_short_name}}' 27 | }; -------------------------------------------------------------------------------- /src/services/share.js: -------------------------------------------------------------------------------- 1 | ;(function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('airpub') 6 | .service('share', [shareService]); 7 | 8 | function shareService() { 9 | var defaults = { 10 | title: 'Airpub', 11 | link: 'http://airpub.io', 12 | desc: '基于 Angular.js 搭建,多说数据驱动的纯前端写作工具。' 13 | }; 14 | 15 | this.wechat = wechatShare; 16 | 17 | function wechatShare(article) { 18 | if (!window.wechat) 19 | return; 20 | 21 | var wechat = window.wechat; 22 | var data = {}; 23 | 24 | angular.forEach([ 25 | 'title', 26 | 'link', 27 | 'desc' 28 | ], function(item){ 29 | data[item] = article[item] || defaults[item]; 30 | }); 31 | 32 | wechat('friend', data); 33 | wechat('timeline', data); 34 | wechat('weibo', data); 35 | } 36 | } 37 | })(); 38 | -------------------------------------------------------------------------------- /src/controllers/meta.js: -------------------------------------------------------------------------------- 1 | ;(function(angular, debug) { 2 | 'use strict'; 3 | 4 | angular 5 | .module('airpub') 6 | .controller('meta', [ 7 | '$scope', 8 | '$rootScope', 9 | 'share', 10 | metaCtrler 11 | ]); 12 | 13 | function metaCtrler($scope, $rootScope, share) { 14 | $scope.title = $scope.configs.name || 'Airpub'; 15 | $scope.description = $scope.configs.description || 'just another Airpub blog'; 16 | 17 | // Init service share 18 | share.wechat({ 19 | title: $scope.configs.name, 20 | link: $scope.configs.url, 21 | desc: $scope.configs.description 22 | }); 23 | 24 | $rootScope.$on('updateMeta', function(eve, data){ 25 | if (typeof(data) === 'string') 26 | return $scope.title = data; 27 | angular.forEach(data, function(v, k){ 28 | $scope[k] = v; 29 | }); 30 | }); 31 | } 32 | })(window.angular, window.debug); 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Guo Yu <o.u.turing@gmail.com> 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "airpub", 3 | "version": "0.4.0", 4 | "homepage": "https://github.com/duoshuo/airpub", 5 | "authors": [ 6 | "Guo Yu " 7 | ], 8 | "description": "a pure front-end blog engine powered by duoshuo API", 9 | "main": "index.html", 10 | "keywords": [ 11 | "blog", 12 | "cms", 13 | "angular", 14 | "airpub", 15 | "airpress", 16 | "wordpress", 17 | "blog engine", 18 | "blog platform", 19 | "article" 20 | ], 21 | "license": "MIT", 22 | "ignore": [ 23 | "**/.*", 24 | "node_modules", 25 | "bower_components", 26 | "test", 27 | "tests", 28 | "editor", 29 | "thumb" 30 | ], 31 | "dependencies": { 32 | "angular": "1.3.8", 33 | "angular-sanitize": "~1.3.8", 34 | "angular-ui-router": "0.2.13", 35 | "bootstrap": "3.3.1", 36 | "nprogress": "~0.1.6", 37 | "node-uuid": "~1.4.1", 38 | "upyun": "0.4.0", 39 | "duoshuo": "0.5.2", 40 | "marked": "~0.3.2", 41 | "highlightjs": "~8.0.0", 42 | "chill": "0.3.0", 43 | "ninja": "0.1.1", 44 | "oclazyload": "~0.5.2" 45 | }, 46 | "devDependencies": { 47 | "debug": "git@github.com:visionmedia/debug.git" 48 | }, 49 | "resolutions": { 50 | "angular": "1.3.8" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "airpub", 3 | "version": "0.4.0", 4 | "description": "a pure front-end blog engine powered by duoshuo API", 5 | "main": "index.html", 6 | "author": "turing ", 7 | "license": "MIT", 8 | "scripts": { 9 | "build": "bin/build.sh", 10 | "build-deps": "npm run build-deps-js && npm run build-deps-css", 11 | "build-deps-js": "bin/build-dependency-js.sh", 12 | "build-deps-css": "bin/build-dependency-css.sh", 13 | "build-deps-less": "bin/build-dependency-less.sh", 14 | "serve": "node_modules/.bin/serve --no-less .", 15 | "watch": "node_modules/.bin/rewatch src/*.js src/**/*.js -c 'npm run build'", 16 | "dev": "npm run serve & npm run watch", 17 | "start": "npm run dev" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/duoshuo/airpub.git" 22 | }, 23 | "bugs": { 24 | "url": "https://github.com/duoshuo/airpub/issues" 25 | }, 26 | "keywords": [ 27 | "air", 28 | "publish", 29 | "press", 30 | "airpub", 31 | "cms", 32 | "blog", 33 | "blog platform", 34 | "angular" 35 | ], 36 | "devDependencies": { 37 | "clean-css": "^2.2.13", 38 | "less": "^2.1.2", 39 | "rewatch": "~0.2.2", 40 | "serve": "~1.4.0", 41 | "uglify-js": "^2.4.15" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /bin/airpub-bootstrap.less: -------------------------------------------------------------------------------- 1 | // Core variables and mixins 2 | @import "bower_components/bootstrap/less/variables.less"; 3 | @import "bower_components/bootstrap/less/mixins.less"; 4 | 5 | // Reset and dependencies 6 | @import "bower_components/bootstrap/less/normalize.less"; 7 | @import "bower_components/bootstrap/less/print.less"; 8 | 9 | // Core CSS 10 | @import "bower_components/bootstrap/less/scaffolding.less"; 11 | @import "bower_components/bootstrap/less/type.less"; 12 | @import "bower_components/bootstrap/less/code.less"; 13 | @import "bower_components/bootstrap/less/grid.less"; 14 | @import "bower_components/bootstrap/less/tables.less"; 15 | @import "bower_components/bootstrap/less/forms.less"; 16 | @import "bower_components/bootstrap/less/buttons.less"; 17 | 18 | // Components 19 | @import "bower_components/bootstrap/less/component-animations.less"; 20 | @import "bower_components/bootstrap/less/thumbnails.less";; 21 | @import "bower_components/bootstrap/less/alerts.less";; 22 | @import "bower_components/bootstrap/less/pagination.less";; 23 | @import "bower_components/bootstrap/less/pager.less";; 24 | 25 | // Components w/ JavaScript 26 | @import "bower_components/bootstrap/less/tooltip.less";; 27 | 28 | // Utility classes 29 | @import "bower_components/bootstrap/less/utilities.less"; 30 | @import "bower_components/bootstrap/less/responsive-utilities.less"; -------------------------------------------------------------------------------- /src/controllers/archive.js: -------------------------------------------------------------------------------- 1 | ;(function(angular, debug) { 2 | 'use strict'; 3 | 4 | angular 5 | .module('airpub') 6 | .controller('archive', [ 7 | '$scope', 8 | '$state', 9 | 'duoshuo', 10 | '$rootScope', 11 | archiveCtrler 12 | ]); 13 | 14 | function archiveCtrler($scope, $state, duoshuo, $rootScope) { 15 | $scope.itemsPerPage = 10; 16 | $scope.currentPage = parseNumber($state.params.page) || 1; 17 | 18 | // Update document title 19 | $rootScope.$emit('updateMeta', $scope.configs.name); 20 | 21 | // Read articles from cache 22 | if ($scope.articles && $scope.articles.length > 0) 23 | return; 24 | 25 | // TODO: remove this ugly hack 26 | if ($state.params.page) { 27 | var lock = true; 28 | var currentPage = $scope.currentPage; 29 | } 30 | 31 | // Read data from fresh 32 | fetchFreshArticles(); 33 | 34 | // When page changed, go => /#/page/currentPage 35 | // Why the fucking event was trigged twice and return `1` the second time ?! 36 | $scope.pageChanged = pageChanged; 37 | 38 | function fetchFreshArticles() { 39 | var query = {}; 40 | query.page = $scope.currentPage; 41 | query.limit = $scope.itemsPerPage; 42 | query.with_content = 1; 43 | 44 | // Open a request 45 | duoshuo.get('threads/list', query, onSuccess, onError); 46 | 47 | function onSuccess(err, result, res) { 48 | if ($state.params.page) 49 | lock = false; 50 | if (err) 51 | return $scope.addAlert('获取信息失败,请重试', 'danger'); 52 | if (result.length === 0) 53 | return $state.go('layout.404'); 54 | 55 | // Exporse locals to templates 56 | $scope.articles = result || []; 57 | $scope.totalItems = res.cursor.total; 58 | 59 | if ($state.params.page) 60 | $scope.currentPage = currentPage; 61 | 62 | return; 63 | } 64 | 65 | function onError(err) { 66 | return $state.go('layout.404'); 67 | } 68 | } 69 | 70 | function pageChanged() { 71 | if (lock) 72 | return; 73 | 74 | $state.go('layout.pager', { 75 | page: $scope.currentPage 76 | }); 77 | } 78 | 79 | function parseNumber(str) { 80 | if (str && !isNaN(parseInt(str))) 81 | return parseInt(str); 82 | 83 | return false; 84 | } 85 | } 86 | })(window.angular, window.debug); 87 | -------------------------------------------------------------------------------- /src/controllers/base.js: -------------------------------------------------------------------------------- 1 | ;(function(angular, debug) { 2 | 'use strict'; 3 | 4 | angular 5 | .module('airpub') 6 | .controller('layout', ['$scope', layoutCtrler]) 7 | .controller('base', [ 8 | '$scope', 9 | '$state', 10 | '$timeout', 11 | '$location', 12 | 'duoshuo', 13 | baseCtrler 14 | ]); 15 | 16 | function baseCtrler($scope, $state, $timeout, $location, duoshuo) { 17 | // Exporse locals to template 18 | $scope.location = $location; 19 | $scope.state = $state; 20 | 21 | // Signin section 22 | $scope.hiddenSigninSection = true; 23 | $scope.toggleSigninSection = toggleSigninSection; 24 | 25 | // Alerts module 26 | $scope.alerts = []; 27 | $scope.addAlert = addAlert; 28 | $scope.closeAlert = closeAlert; 29 | 30 | // Update header backgroud 31 | $scope.updateBackground = updateBackground; 32 | 33 | // Expose copyright year 34 | $scope.copyrightYear = (new Date()).getFullYear(); 35 | 36 | // Init account infomation 37 | duoshuo.on('ready', initAccount); 38 | 39 | function initAccount(err, data) { 40 | var isVisitor = (data.user_id === 0); 41 | 42 | if (err || isVisitor) { 43 | $scope.isVisitor = true; 44 | return; 45 | } 46 | 47 | // Expose user data 48 | $scope.user = data; 49 | } 50 | 51 | function toggleSigninSection() { 52 | $scope.hiddenSigninSection = !$scope.hiddenSigninSection; 53 | } 54 | 55 | function addAlert(msg, type, dismiss) { 56 | $scope.alerts.push({ 57 | msg: msg, 58 | type: type || 'success' 59 | }); 60 | var alertIndex = $scope.alerts.length - 1; 61 | $timeout(function() { 62 | $scope.closeAlert(alertIndex); 63 | }, dismiss ? (dismiss * 1000) : 3000); 64 | return alertIndex; 65 | } 66 | 67 | function closeAlert(index) { 68 | $scope.alerts.splice(index, 1); 69 | } 70 | 71 | function updateBackground(uri, dom) { 72 | if (!uri) 73 | return; 74 | if (uri.indexOf('http') !== 0 && uri.indexOf('https') !== 0) 75 | return; 76 | 77 | var hd = dom || document.getElementsByTagName('header')[0]; 78 | 79 | if (!hd) 80 | return; 81 | 82 | angular.element(hd).css({ 83 | 'background-image': 'url(' + uri + ')' 84 | }); 85 | } 86 | } 87 | 88 | function layoutCtrler() {} 89 | 90 | })(window.angular, window.debug); 91 | -------------------------------------------------------------------------------- /src/controllers/single.js: -------------------------------------------------------------------------------- 1 | ; 2 | (function(angular, debug) { 3 | 'use strict'; 4 | 5 | angular 6 | .module('airpub') 7 | .controller('single', [ 8 | '$scope', 9 | '$state', 10 | 'duoshuo', 11 | '$rootScope', 12 | singleArticleCtrler 13 | ]); 14 | 15 | function singleArticleCtrler($scope, $state, duoshuo, $rootScope) { 16 | if (!$state.params.uri) 17 | return $state.go('layout.404'); 18 | 19 | // Expose locals to templates 20 | $scope.threadId = $state.params.uri; 21 | 22 | // Read from cache 23 | if ($scope.article) 24 | return; 25 | 26 | // Fetch article details 27 | fetchFreshDetail($state.params.uri); 28 | 29 | function fetchFreshDetail(thread_id) { 30 | var query = {}; 31 | query.thread_id = thread_id; 32 | 33 | // Open a request 34 | duoshuo.get( 35 | 'threads/details', 36 | query, 37 | onSuccess, 38 | onError 39 | ); 40 | 41 | function onSuccess(err, result) { 42 | if (err) 43 | return $scope.addAlert('文章内容获取失败,请稍后再试...', 'danger'); 44 | 45 | // Expose locals to templates 46 | $scope.article = result; 47 | 48 | // Update title and desciption 49 | $rootScope.$emit('updateMeta', { 50 | title: result.title, 51 | description: fetchDesciption(result.content) 52 | }); 53 | 54 | // Update background if required. 55 | if (result.meta && result.meta.background) 56 | $scope.updateBackground(result.meta.background); 57 | 58 | // Init wechat share 59 | // if ($scope.article) 60 | // initWeixinShare($scope.article) 61 | 62 | // Fetch authors' profile 63 | if (!result.author_id) 64 | return; 65 | 66 | fetchUserProfile(result); 67 | } 68 | 69 | function onError(err) { 70 | return $state.go('layout.404'); 71 | } 72 | 73 | function fetchDesciption(text) { 74 | var maxLength = 80; 75 | if (!text) 76 | return ''; 77 | 78 | if (text.length <= maxLength) 79 | return text; 80 | 81 | return text.substr(0, maxLength) + '...'; 82 | } 83 | } 84 | 85 | function fetchUserProfile(result) { 86 | var query = {}; 87 | query.user_id = result.author_id; 88 | 89 | // Open a request 90 | duoshuo.get('users/profile', query, onSuccess); 91 | 92 | function onSuccess(err, result) { 93 | // Ignore null profile 94 | if (err) return; 95 | 96 | $scope.author = result; 97 | $scope.author.description = result.connected_services.weibo ? 98 | result.connected_services.weibo.description : 99 | null; 100 | } 101 | } 102 | } 103 | 104 | function initWeixinShare(article) { 105 | if (!window.wechat) 106 | return; 107 | 108 | var limit = 42; 109 | var data = {}; 110 | 111 | data.link = article.url; 112 | data.title = article.title; 113 | data.desc = article.content.substr(0, limit) + (article.content.length > limit ? '...' : ''); 114 | 115 | if (article.meta && article.meta.background) 116 | data.img = article.meta.background; 117 | 118 | // TODO: Remove hardcode here, replace key `wechatSharePic` with a anchor 119 | if (article.meta && article.meta.wechatSharePic) 120 | data.img = article.meta.wechatSharePic; 121 | 122 | if (airpubConfigs.wechat && airpubConfigs.wechat.appId) 123 | data.app = airpubConfigs.wechat.appId; 124 | 125 | window.wechat('friend', data); 126 | window.wechat('timeline', data); 127 | window.wechat('weibo', data); 128 | } 129 | })(window.angular, window.debug); 130 | -------------------------------------------------------------------------------- /src/filters/marked.js: -------------------------------------------------------------------------------- 1 | ;(function(angular, debug) { 2 | 'use strict'; 3 | 4 | angular 5 | .module('airpub') 6 | .filter('marked', ['$sce', '$sanitize', markedFilter]); 7 | 8 | function markedFilter($sce, $sanitize) { 9 | return function(raw) { 10 | if (!raw) 11 | return ''; 12 | if (!marked) 13 | throw new Error('Marked.js is required!'); 14 | 15 | var wrappers; 16 | 17 | // Check if additional filter params is provided. 18 | if (arguments.length > 1) 19 | wrappers = parseWrapperString(Array.prototype.slice.call(arguments, 1)); 20 | 21 | var markedOptions = {}; 22 | 23 | // Make a custom Renderer for marked 24 | var render = new marked.Renderer(); 25 | 26 | // Extends from code prototye but let user to choose 27 | // Use unescape html or not. 28 | render.code = function(code, lang, escaped) { 29 | var html = marked.Renderer.prototype.code.call( 30 | this, 31 | (lang === 'unsafe-html') ? $sanitize(code) : code, 32 | lang, 33 | escaped 34 | ); 35 | 36 | if (wrappers && wrappers.code) 37 | return injectTo(wrappers.code, html) 38 | 39 | return html; 40 | }; 41 | 42 | // Extends from other prototypes 43 | angular.forEach([ 44 | 'blockquote', 45 | 'html', 46 | 'heading', 47 | 'list', 48 | 'listitem', 49 | 'paragraph', 50 | 'table', 51 | 'tablerow', 52 | 'tablecell', 53 | 'image' 54 | ], function(type){ 55 | render[type] = function() { 56 | var html = marked.Renderer.prototype[type].apply(this, arguments); 57 | 58 | if (wrappers && wrappers[type]) 59 | return injectTo(wrappers[type], html) 60 | 61 | if (wrappers && wrappers.all) 62 | return injectTo(wrappers.all, html) 63 | 64 | return html; 65 | } 66 | }) 67 | 68 | markedOptions.renderer = render; 69 | 70 | // Setting: highlight 71 | if (window.hljs) 72 | markedOptions.highlight = highlightCode; 73 | 74 | marked.setOptions(markedOptions); 75 | 76 | function highlightCode(code) { 77 | return window.hljs.highlightAuto(code).value; 78 | } 79 | 80 | function parseWrapperString(wrappers) { 81 | var parsed = {}; 82 | 83 | wrappers.forEach(function(str) { 84 | var key = str.indexOf(':') === -1 ? 85 | 'all' : str.split(':')[0]; 86 | 87 | parsed[key] = str.split(':')[1]; 88 | }); 89 | 90 | return parsed; 91 | } 92 | 93 | function injectTo(str, entryHtml) { 94 | function parseName(str) { 95 | var arr = str.split(' ') 96 | if (arr.length === 1) 97 | return str.substr(1); 98 | 99 | var ret = ''; 100 | angular.forEach(arr, function(token) { 101 | ret += token.substr(1) + ' '; 102 | }); 103 | return ret; 104 | } 105 | 106 | var domNotes = str.split('>'); 107 | 108 | if (!domNotes.length) 109 | return entryHtml; 110 | 111 | var wraps = ''; 112 | 113 | angular.forEach(domNotes, function(item) { 114 | var attrName = item.charAt(0) === '.' ? 115 | 'class' : 'id'; 116 | wraps += '
'; 117 | }); 118 | 119 | wraps += entryHtml; 120 | 121 | angular.forEach(domNotes, function() { 122 | wraps += '
'; 123 | }); 124 | 125 | return wraps; 126 | } 127 | 128 | return $sce.trustAsHtml(marked(raw)); 129 | } 130 | } 131 | })(window.angular, window.debug); 132 | -------------------------------------------------------------------------------- /src/addons/meta.js: -------------------------------------------------------------------------------- 1 | ;(function() { 2 | 'use strict'; 3 | 4 | // Meta directive 5 | // todo: parse configs obejct to deps 6 | angular 7 | .module('airpub') 8 | .directive('metaBackground', ['upyun', metaBackgroundDirective]) 9 | .directive('metaShare', ['duoshuo', metaShareDirective]); 10 | 11 | function metaBackgroundDirective(upyun) { 12 | var directive = { 13 | restrict: 'AE', 14 | require: 'ngModel', 15 | replace: true, 16 | link: link, 17 | template: [ 18 | '
', 19 | '
', 20 | '', 21 | '', 22 | '上传背景图片', 23 | '', 24 | '
', 25 | '
' 26 | ].join('\n') 27 | }; 28 | return directive; 29 | 30 | function link(scope, element, attrs, ctrl) { 31 | var $ = angular.element; 32 | var uploading = false; 33 | 34 | var inputButton = document.getElementById('uploadBackgroundBtn'); 35 | $(inputButton).on('change', bindUpload); 36 | 37 | // model => view 38 | ctrl.$render = function() { 39 | fillBackgroundImage(ctrl.$viewValue); 40 | }; 41 | 42 | // upload images and fill uri 43 | function bindUpload(eve) { 44 | // begin upload 45 | if (uploading) return; 46 | uploading = true; 47 | upyun.upload('metaBackgroundForm', function(err, response, image) { 48 | uploading = false; 49 | if (err) { 50 | console.error(err); 51 | return alert('上传失败,请稍后再试...'); 52 | } 53 | var uploadOk = image.code === 200 && image.message === 'ok'; 54 | if (!uploadOk) return; 55 | // fill image 56 | fillBackgroundImage(image.absUrl); 57 | // view => model 58 | ctrl.$setViewValue(image.absUrl); 59 | }); 60 | } 61 | 62 | function fillBackgroundImage(uri) { 63 | if (!uri) return; 64 | if (uri.indexOf('http') !== 0) return; 65 | var hd = document.getElementsByTagName('header')[0]; 66 | var self = document.getElementById('metaBackground'); 67 | if (!hd) return; 68 | var style = {}; 69 | style['background-image'] = 'url(' + uri + ')'; 70 | $(hd).css(style); 71 | $(self).css(style); 72 | } 73 | } 74 | } 75 | 76 | function metaShareDirective(duoshuo) { 77 | var directive = { 78 | restrict: 'AE', 79 | require: 'ngModel', 80 | replace: true, 81 | link: link, 82 | template: [ 83 | '
', 84 | '', 85 | '', 86 | '
' 87 | ].join('\n') 88 | }; 89 | return directive; 90 | 91 | function link(scope, element, attrs, ctrl) { 92 | scope.checkToShare = false; 93 | scope.updateCheckStatus = updateCheckingStatus; 94 | 95 | // bind events 96 | scope.on('afterCreate', shareArticle()); 97 | scope.on('afterUpdate', shareArticle()); 98 | 99 | // view => model 100 | function updateCheckingStatus() { 101 | ctrl.$setViewValue(scope.checkToShare); 102 | } 103 | 104 | // share article 105 | function shareArticle(type) { 106 | return function(article) { 107 | return; // disable for temp 108 | if (!scope.checkToShare) return; 109 | var query = article; 110 | query.sync_to = type || 'weibo'; 111 | query.short_name = duoshuoQuery.short_name; 112 | if (query.meta) delete query.meta; 113 | // todo: update this API 114 | return duoshuo.post('threads/sync', query, function(){}); 115 | }; 116 | } 117 | } 118 | } 119 | })(); 120 | -------------------------------------------------------------------------------- /dev.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Airpub logo](http://ww1.sinaimg.cn/large/61ff0de3gw1ejdogm8gyxj20pt0hamyc.jpg)](http://airpub.io) 2 | 3 | ## Airpub ![NPM version](https://img.shields.io/npm/v/airpub.svg?style=flat) 4 | 5 | [Airpub](http://airpub.io) 是基于 Angular.js 搭建,[多说](http://duoshuo.com) 数据驱动的纯前端写作工具。 6 | 7 | 基于多说现有社交网络账户体系与健壮 API,Airpub 能够托管在任何静态资源服务器上,例如 GitHub Pages、又拍云储存、七牛云储存或使用自定义的 FTP 工具上传到任何 VPS 或虚拟主机中使用,为最终用户提供便捷流畅,优质轻量的博客写作与阅读体验。访问[官方网站](http://airpub.io) 8 | 9 | ### 快速开始 10 | 11 | - [如何安装](#%E5%A6%82%E4%BD%95%E5%AE%89%E8%A3%85) 12 | - [配置指南](#%E9%85%8D%E7%BD%AE%E6%8C%87%E5%8D%97) 13 | - [开发指南](#%E5%BC%80%E5%8F%91%E6%8C%87%E5%8D%97) 14 | - [贡献代码](#%E8%B4%A1%E7%8C%AE%E4%BB%A3%E7%A0%81) 15 | 16 | ### Airpub 功能特色 17 | --- 18 | 19 | 已实现的功能特色: 20 | 21 | - [x] 支持 Markdown 写作 22 | - [x] 支持图片上传,目前支持上传到 又拍云 23 | - [x] 支持插入代码以及代码高亮 24 | - [x] 支持基于多说的社交网络账户登录 25 | - [x] 基于 Angular Directive 规范的 add-on 系统 26 | - [x] 基于 bower 管理的主题系统 27 | - [x] 符合规范的,更好的 Angular SEO 实现 28 | - [x] 更好的移动端登录体验,去掉多说登录中间页面,跳转到相应社交网站登录页面 29 | - [x] 拆分后台文件与逻辑到独立页面,缩减普通用户请求资源大小 30 | - [x] 支持友好地分享到微信信息流、朋友圈 31 | 32 | Todo List: 33 | 34 | - [x] 精细化压缩 `bootstrap.css`,实现更小的页面资源加载。 35 | - [x] 解决前端鉴权产生的冗余依赖问题,消除对 `angular-md5`,`angular-base64` 等库的依赖。 36 | - [ ] 实现单一文章多账户编辑的逻辑与界面,设计基本的 ACL 机制。 37 | 38 | ### 如何安装 39 | --- 40 | 41 | #### 自动安装 42 | 43 | 使用 [Airpub CLI Installer](https://github.com/airpub/installer) 来安装 Airpub 的稳定版本: 44 | ``` 45 | $ [sudo] npm install -g airpub-installer 46 | ``` 47 | 新建站点目录: 48 | ``` 49 | $ mkdir my-airpub-blog && cd my-airpub-blog 50 | ``` 51 | 然后执行操作将相关的依赖全部安装完毕: 52 | ``` 53 | $ airpub install 54 | ``` 55 | airpub installer 将自动新建配置,仅需[简单编辑](#%E9%85%8D%E7%BD%AE%E6%8C%87%E5%8D%97): 56 | ``` 57 | $ vi configs.js 58 | ``` 59 | 大功告成!即可访问你的站点,开始 Airpub 简洁流畅的书写体验。 60 | 61 | #### 手动安装 62 | 63 | 手动安装 Airpub 也**异常简单**,仅需使用 Git 拉取主干代码,即可直接部署在静态资源服务器上: 64 | ``` 65 | // 拉取代码 66 | $ git clone https://github.com/turingou/airpub.git 67 | 68 | // 手动新建配置文件 69 | $ cd airpub 70 | $ cp configs-sample.js configs.js 71 | 72 | // 根据提示编辑配置文件,填入多说配置与站点信息 73 | $ vi configs.js 74 | ``` 75 | 配置填写完毕后,我们需要安装 Airpub 依赖的前端资源文件,执行: 76 | 77 | ``` 78 | $ bower install 79 | ``` 80 | 依赖安装完成后,即可访问你的站点,开始 Airpub 简洁流畅的书写体验。 81 | 82 | ### 配置指南 83 | --- 84 | 85 | Airpub 仅需简单配置,即可达成不错的写作与阅读效果。在 `configs.js` 中,你应该会注意到存在两种配置项: 86 | 87 | - `airpubConfig`: Airpub 博客系统本身的配置,包括站点名称,描述,以及其他元数据。 88 | * `name`: 站点名称 89 | * `description`: 站点描述 90 | * `url`: 线上访问地址,必须是绝对地址,用于分享 91 | * `upyun` 又拍云配置(用于上传图片) 92 | - `bucket`: 又拍云 bucket **名称**,在提供 `policy` 与 `signature` 时不需要提供 93 | - `policy`: 又拍云 policy,可通过 upyun-sign 命令行工具生成 94 | - `signature`: 又拍云 signature,可通过 upyun-sign 命令行工具生成 95 | - `form_api_secret`: 又拍云 `form_api_secret`,不推荐直接暴露在前端 96 | - `host`: 返回的图片的默认主机地址(可选) 97 | - `endpoint`: 默认 API 地址(可选) 98 | 99 | - `duoshuoQuery`: 你的多说站点信息,目前仅需要提供 `short_name` 100 | 101 | Airpub 鉴权基于多说用户系统,这意味着你不需要对 管理员 身份进行任何配置,仅需使用生成该 `short_name` 相应的多说用户登录即可进行文章的新建与管理操作。 102 | 103 | **重要提示**: 如你的多说 `short_name` 之前有在任何服务中使用过,请申请全新的多说站点以获得不同的 `short_name`,我们推荐你采用这样的方式来管理自己不同的多说站点之间的关系,例如 `myname-wordpress` 和 `myname-airpub`。 104 | 105 | **重要提示**: 建议你在多说管理后台(站点管理 => 设置 => 文章信息来源)开启 `只接受来自服务器的文章信息请求` 选项,防止非 API 请求造成的非法数据写入。 106 | 107 | **提示**: 由于表单上传会暴露您的 `form_api_secret`,建议开启防盗链模式,并经常性更换 `form_api_secret`。如果你选择这种方式在前端进行摘要计算,记得在自己的页面上额外引入 `js-base64` 与 `js-md5` 的代码库。 108 | 109 | ### 开发指南 110 | --- 111 | 112 | Airpub 的前端依赖基于 bower 构建,工作流基于 NPM 构建。在进行 Airpub 二次开发之前,确保你有安装 Node.js、NPM 以及 bower,然后执行以下步骤: 113 | 114 | ``` 115 | $ cd airpub 116 | $ bower install 117 | $ npm install 118 | $ npm run dev 119 | ``` 120 | 121 | 命令 `$ npm run dev` 将再 `localhost:3000` 运行一个静态资源服务器,并实时压缩 dist 文件。需要确保这个端口没有被占用后再执行此操作。 122 | 123 | ### 贡献代码 124 | --- 125 | 126 | 欢迎为 Airpub 贡献代码。如果你有兴趣为 Airpub 贡献代码,请先查阅本项目中的相关代码,fork 项目后,再提交 pull request。 127 | 如果你对 Airpub 计划中的主题系统或 add-on 系统感兴趣,欢迎在 [issue](https://github.com/duoshuo/airpub/issues) 区提交新话题。 128 | 129 | ### MIT license 130 | Copyright (c) 2014 Guo Yu <o.u.turing@gmail.com> 131 | 132 | Permission is hereby granted, free of charge, to any person obtaining a copy 133 | of this software and associated documentation files (the "Software"), to deal 134 | in the Software without restriction, including without limitation the rights 135 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 136 | copies of the Software, and to permit persons to whom the Software is 137 | furnished to do so, subject to the following conditions: 138 | 139 | The above copyright notice and this permission notice shall be included in 140 | all copies or substantial portions of the Software. 141 | 142 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 143 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 144 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 145 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 146 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 147 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 148 | THE SOFTWARE. 149 | 150 | --- 151 | ![docor](https://cdn1.iconfinder.com/data/icons/windows8_icons_iconpharm/26/doctor.png) 152 | generated using [docor](https://github.com/turingou/docor.git) @ 0.1.0. brought to you by [turingou](https://github.com/turingou) -------------------------------------------------------------------------------- /src/airpub.js: -------------------------------------------------------------------------------- 1 | ;(function(angular, debug) { 2 | 'use strict'; 3 | 4 | angular 5 | .module('airpub', [ 6 | 'upyun', 7 | 'duoshuo', 8 | 'ui.router', 9 | 'ui.bootstrap', 10 | 'oc.lazyLoad', 11 | 'ngSanitize' 12 | ]).config([ 13 | '$stateProvider', 14 | '$urlRouterProvider', 15 | '$locationProvider', 16 | '$ocLazyLoadProvider', 17 | 'upyunProvider', 18 | initAirpub 19 | ]); 20 | 21 | function initAirpub($stateProvider, $urlRouterProvider, $locationProvider, $ocLazyLoadProvider, upyunProvider) { 22 | // Theme configs 23 | var theme = airpubConfigs.theme || 'chill'; 24 | var themePath = (airpubConfigs.themePath || 'bower_components') + '/' + theme; 25 | var staticPath = airpubConfigs.staticPath || ''; 26 | 27 | // Init Router objects 28 | var routers = defineRoutes(['archive', 'single', 'admin', '404', 'layout']); 29 | 30 | // Routes configs 31 | $urlRouterProvider.otherwise("/404"); 32 | // Signup routes uri 33 | $stateProvider 34 | .state('layout', routerMaker('', routers.layout)) 35 | .state('layout.home', routerMaker('/', routers.layout)) // alias router for layout 36 | .state('layout.pager', routerMaker('/page/:page', routers.archive)) 37 | .state('layout.single', routerMaker('/article/:uri', routers.single)) 38 | .state('layout.create', routerMaker('/create', routers.admin, appendTitleToRouter('写新文章'))) 39 | .state('layout.update', routerMaker('/article/:uri/update', routers.admin, appendTitleToRouter('更新文章'))) 40 | .state('layout.404', routerMaker('/404', routers['404'])); 41 | 42 | // Rredefine async loaded scripts 43 | $ocLazyLoadProvider.config({ 44 | modules: [{ 45 | name: 'EditorNinja', 46 | files: [ 47 | staticPath + 'bower_components/ninja/dist/ninja.min.js', 48 | staticPath + 'bower_components/ninja/dist/ninja.min.css' 49 | ] 50 | },{ 51 | name: 'EditorNinja.upload', 52 | files: [ 53 | staticPath + 'bower_components/ninja/dist/ninja.min.js' 54 | ] 55 | }] 56 | }); 57 | 58 | // Hashtag config 59 | $locationProvider 60 | .hashPrefix(airpubConfigs.hashPrefix || '!'); 61 | 62 | // Html5 mode should also be supported by server side, check this out: 63 | // http://stackoverflow.com/questions/18452832/angular-route-with-html5mode-giving-not-found-page-after-reload 64 | if (airpubConfigs.html5Mode) 65 | $locationProvider.html5Mode(true); 66 | 67 | if (airpubConfigs.upyun) 68 | upyunProvider.config(airpubConfigs.upyun); 69 | 70 | initWeixinShare(); 71 | 72 | function defineRoutes(routes) { 73 | var routers = {}; 74 | 75 | angular.forEach(routes, function(route) { 76 | routers[route] = {}; 77 | routers[route].templateUrl = themePath + '/' + route + '.html'; 78 | if (route !== '404') 79 | routers[route].controller = route; 80 | // Define the LAYOUT router 81 | if (route === 'layout') { 82 | // Define default sub-views of layout 83 | routers[route].views = { 84 | 'layout': routers.layout, 85 | '@layout': routers.archive, 86 | '@layout.home': routers.archive 87 | } 88 | } 89 | 90 | if (['admin', 'single'].indexOf(route) > -1) 91 | routers[route].resolve = lazyloadResources(route); 92 | }); 93 | 94 | return routers; 95 | } 96 | 97 | function lazyloadResources(route) { 98 | var map = { 99 | admin: loadEditor, 100 | single: loadSingle 101 | }; 102 | 103 | return { 104 | lazyload: ['$ocLazyLoad', map[route]] 105 | } 106 | } 107 | 108 | // Load EditorNinja async 109 | function loadEditor($ocLazyLoad) { 110 | return $ocLazyLoad.load('EditorNinja').then(function(){ 111 | // Load ninja addons 112 | $ocLazyLoad.load('EditorNinja.upload'); 113 | // Load other deps in `admin.html` 114 | $ocLazyLoad.load({ 115 | files: [ 116 | staticPath + 'bower_components/node-uuid/uuid.js' 117 | ] 118 | }); 119 | }); 120 | } 121 | 122 | function loadSingle($ocLazyLoad) { 123 | return $ocLazyLoad.load({ 124 | files: [ 125 | staticPath + 'bower_components/marked/lib/marked.js', 126 | staticPath + 'bower_components/highlightjs/highlight.pack.js', 127 | ] 128 | }); 129 | } 130 | 131 | function routerMaker(url, router, data) { 132 | var obj = angular.copy(router); 133 | obj.url = url; 134 | if (data && typeof(data) === 'object') 135 | obj = angular.extend(obj, data); 136 | return obj; 137 | } 138 | 139 | function appendTitleToRouter(title) { 140 | return { 141 | data: { 142 | title: title 143 | } 144 | } 145 | } 146 | 147 | function initWeixinShare() { 148 | if (!window.wechat) 149 | return; 150 | 151 | var data = {}; 152 | 153 | if (airpubConfigs.url) 154 | data.link = airpubConfigs.url; 155 | if (airpubConfigs.description) 156 | data.desc = airpubConfigs.description; 157 | if (airpubConfigs.name) 158 | data.title = airpubConfigs.name; 159 | 160 | window.wechat('friend', data); 161 | window.wechat('timeline', data); 162 | window.wechat('weibo', data); 163 | } 164 | } 165 | })(window.angular, window.debug); 166 | -------------------------------------------------------------------------------- /src/controllers/admin.js: -------------------------------------------------------------------------------- 1 | ;(function(angular, debug) { 2 | 'use strict'; 3 | 4 | angular 5 | .module('airpub') 6 | .controller('admin', [ 7 | '$scope', 8 | '$state', 9 | 'duoshuo', 10 | '$location', 11 | '$rootScope', 12 | adminCtrler 13 | ]); 14 | 15 | function adminCtrler($scope, $state, duoshuo, $location, $rootScope) { 16 | // Reset isAdmin status 17 | $scope.isAdmin = false; 18 | 19 | var baseUri = $scope.configs.url || $location.host(); 20 | var hashPrefix = $scope.configs.hashPrefix || '!'; 21 | var hashTag = '/#' + hashPrefix; 22 | 23 | initAdmin(); 24 | 25 | // Expose functions to templates 26 | $scope.createArticle = createArticle; 27 | $scope.updateArticle = updateArticle; 28 | $scope.removeArticle = removeArticle; 29 | $scope.on = eventBinder; 30 | 31 | // Init admin page 32 | function initAdmin() { 33 | $rootScope.$emit('updateMeta', $state.current.data.title); 34 | 35 | // Open a request 36 | duoshuo.get('sites/membership', {}, onSuccess, onError); 37 | 38 | function onSuccess(err, result) { 39 | if (err || result.role !== 'administrator') 40 | return $state.go('layout.home'); 41 | 42 | var isUpdatePage = $state.current.name === 'layout.update' && $state.params.uri; 43 | 44 | // If status is `update`, fetch data 45 | if (!isUpdatePage) { 46 | $scope.isAdmin = true; 47 | return; 48 | } 49 | 50 | var query = {}; 51 | query.thread_id = $state.params.uri; 52 | 53 | // Fetch article details in edit mode. 54 | duoshuo.get('threads/details', query, response, fail); 55 | 56 | function response(err, result) { 57 | // Now show the page 58 | $scope.isAdmin = true; 59 | 60 | if (err) 61 | return fail(err); 62 | 63 | // Expose article locals to template 64 | $scope.article = result; 65 | } 66 | 67 | function fail(err) { 68 | return $scope.addAlert('文章内容获取失败,请稍后再试...', 'danger'); 69 | } 70 | } 71 | 72 | // Error callback 73 | function onError(err) { 74 | $scope.addAlert(err.errorMessage, 'danger'); 75 | $state.go('layout.home'); 76 | } 77 | } 78 | 79 | // Create a new article 80 | function createArticle() { 81 | if (!$scope.isAdmin) 82 | return false; 83 | if (!$scope.article.title) 84 | return $scope.addAlert('至少写个标题咯...', 'danger'); 85 | if (!$scope.article.content) 86 | return $scope.addAlert('至少写点内容咯...', 'danger'); 87 | 88 | var baby = {}; 89 | baby.format = 'markdown'; 90 | baby.title = $scope.article.title; 91 | baby.content = $scope.article.content; 92 | baby.thread_key = uuid.v1(); 93 | baby = insertMeta(baby); 94 | 95 | // Trigger events 96 | eventTrigger('beforeCreate', baby); 97 | 98 | // Open a request 99 | duoshuo.post('threads/create', baby, onSuccess, onError); 100 | 101 | function onSuccess(err, result) { 102 | if (err) 103 | return $scope.addAlert('发布失败...', 'danger'); 104 | 105 | $scope.addAlert('发布成功'); 106 | 107 | // Update article URI 108 | // TODO: Merge this two request in one. 109 | var query = {}; 110 | query.thread_id = result.thread_id; 111 | query.url = baseUri + hashTag + '/article/' + result.thread_id; 112 | 113 | // Open a request 114 | duoshuo.post('threads/update', query, response); 115 | 116 | // Trigger events 117 | eventTrigger('afterCreate', result); 118 | 119 | function response(err, res) { 120 | if (err) 121 | console.log(err); 122 | 123 | $state.go('layout.single', { 124 | uri: result.thread_id 125 | }); 126 | } 127 | } 128 | 129 | function onError(err) { 130 | return $scope.addAlert('发布失败...', 'danger'); 131 | } 132 | }; 133 | 134 | // Update a exist article 135 | function updateArticle(id) { 136 | if (!id) 137 | return $scope.createArticle(); 138 | if (!$scope.isAdmin) 139 | return false; 140 | 141 | var baby = {}; 142 | baby.thread_id = id; 143 | baby.title = $scope.article.title; 144 | baby.content = $scope.article.content; 145 | baby.url = baseUri + hashTag + '/article/' + id; 146 | baby = insertMeta(baby); 147 | 148 | // Trigger events 149 | eventTrigger('beforeUpdate', baby); 150 | 151 | // Open a request 152 | duoshuo.post('threads/update', baby, onSuccess, onError); 153 | 154 | function onSuccess(err, result) { 155 | if (err) 156 | return $scope.addAlert('更新失败,请稍后再试...', 'danger'); 157 | 158 | $scope.addAlert('更新成功!'); 159 | 160 | // Trigger events 161 | eventTrigger('afterUpdate', result); 162 | 163 | // Goto article details page 164 | $state.go('layout.single', { 165 | uri: id 166 | }); 167 | } 168 | 169 | function onError(err) { 170 | return $scope.addAlert('更新失败,请稍后再试...', 'danger'); 171 | } 172 | }; 173 | 174 | // Remove a exist article 175 | function removeArticle(id) { 176 | if (!id) 177 | return false; 178 | if (!$scope.isAdmin) 179 | return false; 180 | 181 | // Trigger events 182 | eventTrigger('beforeRemove', id); 183 | 184 | // TODO: Confirm delete action 185 | var query = {}; 186 | query.thread_id = id; 187 | 188 | // Open a request 189 | duoshuo.post('threads/remove', query, onSuccess, onError); 190 | 191 | function onSuccess(err, result) { 192 | if (err) 193 | return $scope.addAlert('删除失败,请稍后再试...', 'danger'); 194 | 195 | // Trigger events 196 | eventTrigger('afterRemove', id); 197 | 198 | $scope.addAlert('删除成功!'); 199 | $state.go('layout.home'); 200 | } 201 | 202 | function onError(err) { 203 | return $scope.addAlert('删除失败,请稍后再试...', 'danger'); 204 | } 205 | }; 206 | 207 | // Insert meta to plain text query string. 208 | function insertMeta(qs) { 209 | if (!$scope.article.meta) 210 | return qs; 211 | 212 | angular.forEach($scope.article.meta, function(v, k) { 213 | qs['meta[' + k + ']'] = v; 214 | }); 215 | 216 | return qs; 217 | } 218 | 219 | // Bind events 220 | function eventBinder(eventName, func) { 221 | if (!eventName || !func || typeof(func) !== 'function') 222 | return false; 223 | 224 | if (!$scope.bindedEvents) 225 | $scope.bindedEvents = {}; 226 | 227 | $scope.bindedEvents[eventName] = func; 228 | 229 | return $scope.bindedEvents; 230 | } 231 | 232 | // Events trigger 233 | function eventTrigger(eventName, data) { 234 | if (!$scope.bindedEvents || !$scope.bindedEvents[eventName]) 235 | return; 236 | return $scope.bindedEvents[eventName](data || $scope.article, eventName); 237 | } 238 | } 239 | })(window.angular, window.debug); 240 | -------------------------------------------------------------------------------- /libs/ui-bootstrap-custom-0.12.0.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * angular-ui-bootstrap 3 | * http://angular-ui.github.io/bootstrap/ 4 | 5 | * Version: 0.12.0 - 2014-11-16 6 | * License: MIT 7 | */ 8 | angular.module("ui.bootstrap",["ui.bootstrap.transition","ui.bootstrap.alert","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.position","ui.bootstrap.bindHtml","ui.bootstrap.collapse"]),angular.module("ui.bootstrap.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(t,n,e){function i(t){for(var n in t)if(void 0!==a.style[n])return t[n]}var o=function(i,a,r){r=r||{};var l=t.defer(),s=o[r.animation?"animationEndEventName":"transitionEndEventName"],u=function(){e.$apply(function(){i.unbind(s,u),l.resolve(i)})};return s&&i.bind(s,u),n(function(){angular.isString(a)?i.addClass(a):angular.isFunction(a)?a(i):angular.isObject(a)&&i.css(a),s||l.resolve(i)}),l.promise.cancel=function(){s&&i.unbind(s,u),l.reject("Transition cancelled")},l.promise},a=document.createElement("trans"),r={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},l={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return o.transitionEndEventName=i(r),o.animationEndEventName=i(l),o}]),angular.module("ui.bootstrap.alert",[]).controller("AlertController",["$scope","$attrs",function(t,n){t.closeable="close"in n,this.close=t.close}]).directive("alert",function(){return{restrict:"EA",controller:"AlertController",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"@",close:"&"}}}).directive("dismissOnTimeout",["$timeout",function(t){return{require:"alert",link:function(n,e,i,o){t(function(){o.close()},parseInt(i.dismissOnTimeout,10))}}}]),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$attrs","$parse",function(t,n,e){var i=this,o={$setViewValue:angular.noop},a=n.numPages?e(n.numPages).assign:angular.noop;this.init=function(a,r){o=a,this.config=r,o.$render=function(){i.render()},n.itemsPerPage?t.$parent.$watch(e(n.itemsPerPage),function(n){i.itemsPerPage=parseInt(n,10),t.totalPages=i.calculateTotalPages()}):this.itemsPerPage=r.itemsPerPage},this.calculateTotalPages=function(){var n=this.itemsPerPage<1?1:Math.ceil(t.totalItems/this.itemsPerPage);return Math.max(n||0,1)},this.render=function(){t.page=parseInt(o.$viewValue,10)||1},t.selectPage=function(n){t.page!==n&&n>0&&n<=t.totalPages&&(o.$setViewValue(n),o.$render())},t.getText=function(n){return t[n+"Text"]||i.config[n+"Text"]},t.noPrevious=function(){return 1===t.page},t.noNext=function(){return t.page===t.totalPages},t.$watch("totalItems",function(){t.totalPages=i.calculateTotalPages()}),t.$watch("totalPages",function(n){a(t.$parent,n),t.page>n?t.selectPage(n):o.$render()})}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["$parse","paginationConfig",function(t,n){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@"},require:["pagination","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(e,i,o,a){function r(t,n,e){return{number:t,text:n,active:e}}function l(t,n){var e=[],i=1,o=n,a=angular.isDefined(c)&&n>c;a&&(p?(i=Math.max(t-Math.floor(c/2),1),o=i+c-1,o>n&&(o=n,i=o-c+1)):(i=(Math.ceil(t/c)-1)*c+1,o=Math.min(i+c-1,n)));for(var l=i;o>=l;l++){var s=r(l,l,l===t);e.push(s)}if(a&&!p){if(i>1){var u=r(i-1,"...",!1);e.unshift(u)}if(n>o){var f=r(o+1,"...",!1);e.push(f)}}return e}var s=a[0],u=a[1];if(u){var c=angular.isDefined(o.maxSize)?e.$parent.$eval(o.maxSize):n.maxSize,p=angular.isDefined(o.rotate)?e.$parent.$eval(o.rotate):n.rotate;e.boundaryLinks=angular.isDefined(o.boundaryLinks)?e.$parent.$eval(o.boundaryLinks):n.boundaryLinks,e.directionLinks=angular.isDefined(o.directionLinks)?e.$parent.$eval(o.directionLinks):n.directionLinks,s.init(u,n),o.maxSize&&e.$parent.$watch(t(o.maxSize),function(t){c=parseInt(t,10),s.render()});var f=s.render;s.render=function(){f(),e.page>0&&e.page<=e.totalPages&&(e.pages=l(e.page,e.totalPages))}}}}}]).constant("pagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("pager",["pagerConfig",function(t){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@"},require:["pager","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(n,e,i,o){var a=o[0],r=o[1];r&&(n.align=angular.isDefined(i.align)?n.$parent.$eval(i.align):t.align,a.init(r,t))}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).provider("$tooltip",function(){function t(t){var n=/[A-Z]/g,e="-";return t.replace(n,function(t,n){return(n?e:"")+t.toLowerCase()})}var n={placement:"top",animation:!0,popupDelay:0},e={mouseenter:"mouseleave",click:"click",focus:"blur"},i={};this.options=function(t){angular.extend(i,t)},this.setTriggers=function(t){angular.extend(e,t)},this.$get=["$window","$compile","$timeout","$document","$position","$interpolate",function(o,a,r,l,s,u){return function(o,c,p){function f(t){var n=t||d.trigger||p,i=e[n]||n;return{show:n,hide:i}}var d=angular.extend({},n,i),g=t(o),m=u.startSymbol(),h=u.endSymbol(),v="
';return{restrict:"EA",compile:function(){var t=a(v);return function(n,e,i){function a(){O.isOpen?p():u()}function u(){(!D||n.$eval(i[c+"Enable"]))&&($(),O.popupDelay?C||(C=r(g,O.popupDelay,!1),C.then(function(t){t()})):g()())}function p(){n.$apply(function(){m()})}function g(){return C=null,w&&(r.cancel(w),w=null),O.content?(h(),x.css({top:0,left:0,display:"block"}),E?l.find("body").append(x):e.after(x),L(),O.isOpen=!0,O.$digest(),L):angular.noop}function m(){O.isOpen=!1,r.cancel(C),C=null,O.animation?w||(w=r(v,500)):v()}function h(){x&&v(),y=O.$new(),x=t(y,angular.noop)}function v(){w=null,x&&(x.remove(),x=null),y&&(y.$destroy(),y=null)}function $(){b(),P()}function b(){var t=i[c+"Placement"];O.placement=angular.isDefined(t)?t:d.placement}function P(){var t=i[c+"PopupDelay"],n=parseInt(t,10);O.popupDelay=isNaN(n)?d.popupDelay:n}function T(){var t=i[c+"Trigger"];H(),k=f(t),k.show===k.hide?e.bind(k.show,a):(e.bind(k.show,u),e.bind(k.hide,p))}var x,y,w,C,E=angular.isDefined(d.appendToBody)?d.appendToBody:!1,k=f(void 0),D=angular.isDefined(i[c+"Enable"]),O=n.$new(!0),L=function(){var t=s.positionElements(e,x,O.placement,E);t.top+="px",t.left+="px",x.css(t)};O.isOpen=!1,i.$observe(o,function(t){O.content=t,!t&&O.isOpen&&m()}),i.$observe(c+"Title",function(t){O.title=t});var H=function(){e.unbind(k.show,u),e.unbind(k.hide,p)};T();var S=n.$eval(i[c+"Animation"]);O.animation=angular.isDefined(S)?!!S:d.animation;var A=n.$eval(i[c+"AppendToBody"]);E=angular.isDefined(A)?A:E,E&&n.$on("$locationChangeSuccess",function(){O.isOpen&&m()}),n.$on("$destroy",function(){r.cancel(w),r.cancel(C),H(),v(),O=null})}}}}}]}).directive("tooltipPopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(t){return t("tooltip","tooltip","mouseenter")}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).directive("tooltipHtmlUnsafe",["$tooltip",function(t){return t("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(t,n){function e(t,e){return t.currentStyle?t.currentStyle[e]:n.getComputedStyle?n.getComputedStyle(t)[e]:t.style[e]}function i(t){return"static"===(e(t,"position")||"static")}var o=function(n){for(var e=t[0],o=n.offsetParent||e;o&&o!==e&&i(o);)o=o.offsetParent;return o||e};return{position:function(n){var e=this.offset(n),i={top:0,left:0},a=o(n[0]);a!=t[0]&&(i=this.offset(angular.element(a)),i.top+=a.clientTop-a.scrollTop,i.left+=a.clientLeft-a.scrollLeft);var r=n[0].getBoundingClientRect();return{width:r.width||n.prop("offsetWidth"),height:r.height||n.prop("offsetHeight"),top:e.top-i.top,left:e.left-i.left}},offset:function(e){var i=e[0].getBoundingClientRect();return{width:i.width||e.prop("offsetWidth"),height:i.height||e.prop("offsetHeight"),top:i.top+(n.pageYOffset||t[0].documentElement.scrollTop),left:i.left+(n.pageXOffset||t[0].documentElement.scrollLeft)}},positionElements:function(t,n,e,i){var o,a,r,l,s=e.split("-"),u=s[0],c=s[1]||"center";o=i?this.offset(t):this.position(t),a=n.prop("offsetWidth"),r=n.prop("offsetHeight");var p={center:function(){return o.left+o.width/2-a/2},left:function(){return o.left},right:function(){return o.left+o.width}},f={center:function(){return o.top+o.height/2-r/2},top:function(){return o.top},bottom:function(){return o.top+o.height}};switch(u){case"right":l={top:f[c](),left:p[u]()};break;case"left":l={top:f[c](),left:o.left-a};break;case"bottom":l={top:f[u](),left:p[c]()};break;default:l={top:o.top-r,left:p[c]()}}return l}}}]),angular.module("ui.bootstrap.bindHtml",[]).directive("bindHtmlUnsafe",function(){return function(t,n,e){n.addClass("ng-binding").data("$binding",e.bindHtmlUnsafe),t.$watch(e.bindHtmlUnsafe,function(t){n.html(t||"")})}}),angular.module("ui.bootstrap.collapse",["ui.bootstrap.transition"]).directive("collapse",["$transition",function(t){return{link:function(n,e,i){function o(n){function i(){u===o&&(u=void 0)}var o=t(e,n);return u&&u.cancel(),u=o,o.then(i,i),o}function a(){c?(c=!1,r()):(e.removeClass("collapse").addClass("collapsing"),o({height:e[0].scrollHeight+"px"}).then(r))}function r(){e.removeClass("collapsing"),e.addClass("collapse in"),e.css({height:"auto"})}function l(){if(c)c=!1,s(),e.css({height:0});else{e.css({height:e[0].scrollHeight+"px"});{e[0].offsetWidth}e.removeClass("collapse in").addClass("collapsing"),o({height:0}).then(s)}}function s(){e.removeClass("collapsing"),e.addClass("collapse")}var u,c=!0;n.$watch(i.collapse,function(t){t?l():a()})}}}]); -------------------------------------------------------------------------------- /dist/airpub.min.js: -------------------------------------------------------------------------------- 1 | !function(e){"use strict";function t(t,n,r,i,a){function o(t){var n={};return e.forEach(t,function(e){n[e]={},n[e].templateUrl=p+"/"+e+".html","404"!==e&&(n[e].controller=e),"layout"===e&&(n[e].views={layout:n.layout,"@layout":n.archive,"@layout.home":n.archive}),["admin","single"].indexOf(e)>-1&&(n[e].resolve=u(e))}),n}function u(e){var t={admin:c,single:d};return{lazyload:["$ocLazyLoad",t[e]]}}function c(e){return e.load("EditorNinja").then(function(){e.load("EditorNinja.upload"),e.load({files:[m+"bower_components/node-uuid/uuid.js"]})})}function d(e){return e.load({files:[m+"bower_components/marked/lib/marked.js",m+"bower_components/highlightjs/highlight.pack.js"]})}function l(t,n,r){var i=e.copy(n);return i.url=t,r&&"object"==typeof r&&(i=e.extend(i,r)),i}function s(e){return{data:{title:e}}}function f(){if(window.wechat){var e={};airpubConfigs.url&&(e.link=airpubConfigs.url),airpubConfigs.description&&(e.desc=airpubConfigs.description),airpubConfigs.name&&(e.title=airpubConfigs.name),window.wechat("friend",e),window.wechat("timeline",e),window.wechat("weibo",e)}}var g=airpubConfigs.theme||"chill",p=(airpubConfigs.themePath||"bower_components")+"/"+g,m=airpubConfigs.staticPath||"",h=o(["archive","single","admin","404","layout"]);n.otherwise("/404"),t.state("layout",l("",h.layout)).state("layout.home",l("/",h.layout)).state("layout.pager",l("/page/:page",h.archive)).state("layout.single",l("/article/:uri",h.single)).state("layout.create",l("/create",h.admin,s("写新文章"))).state("layout.update",l("/article/:uri/update",h.admin,s("更新文章"))).state("layout.404",l("/404",h[404])),i.config({modules:[{name:"EditorNinja",files:[m+"bower_components/ninja/dist/ninja.min.js",m+"bower_components/ninja/dist/ninja.min.css"]},{name:"EditorNinja.upload",files:[m+"bower_components/ninja/dist/ninja.min.js"]}]}),r.hashPrefix(airpubConfigs.hashPrefix||"!"),airpubConfigs.html5Mode&&r.html5Mode(!0),airpubConfigs.upyun&&a.config(airpubConfigs.upyun),f()}e.module("airpub",["upyun","duoshuo","ui.router","ui.bootstrap","oc.lazyLoad","ngSanitize"]).config(["$stateProvider","$urlRouterProvider","$locationProvider","$ocLazyLoadProvider","upyunProvider",t])}(window.angular,window.debug),function(e){"use strict";function t(t,n){return function(r){function i(e){return window.hljs.highlightAuto(e).value}function a(e){var t={};return e.forEach(function(e){var n=-1===e.indexOf(":")?"all":e.split(":")[0];t[n]=e.split(":")[1]}),t}function o(t,n){function r(t){var n=t.split(" ");if(1===n.length)return t.substr(1);var r="";return e.forEach(n,function(e){r+=e.substr(1)+" "}),r}var i=t.split(">");if(!i.length)return n;var a="";return e.forEach(i,function(e){var t="."===e.charAt(0)?"class":"id";a+="
'}),a+=n,e.forEach(i,function(){a+="
"}),a}if(!r)return"";if(!marked)throw new Error("Marked.js is required!");var u;arguments.length>1&&(u=a(Array.prototype.slice.call(arguments,1)));var c={},d=new marked.Renderer;return d.code=function(e,t,r){var i=marked.Renderer.prototype.code.call(this,"unsafe-html"===t?n(e):e,t,r);return u&&u.code?o(u.code,i):i},e.forEach(["blockquote","html","heading","list","listitem","paragraph","table","tablerow","tablecell","image"],function(e){d[e]=function(){var t=marked.Renderer.prototype[e].apply(this,arguments);return u&&u[e]?o(u[e],t):u&&u.all?o(u.all,t):t}}),c.renderer=d,window.hljs&&(c.highlight=i),marked.setOptions(c),t.trustAsHtml(marked(r))}}e.module("airpub").filter("marked",["$sce","$sanitize",t])}(window.angular,window.debug),function(){"use strict";function e(){function e(e){if(window.wechat){var n=window.wechat,r={};angular.forEach(["title","link","desc"],function(n){r[n]=e[n]||t[n]}),n("friend",r),n("timeline",r),n("weibo",r)}}var t={title:"Airpub",link:"http://airpub.io",desc:"基于 Angular.js 搭建,多说数据驱动的纯前端写作工具。"};this.wechat=e}angular.module("airpub").service("share",[e])}(),function(e){"use strict";function t(e){return airpubConfigs?void(e.configs=airpubConfigs):console.error(new Error("airpub 缺少必要的配置文件!"))}e.module("airpub").controller("global",["$scope",t])}(window.angular,window.debug),function(e){"use strict";function t(t,n,r){t.title=t.configs.name||"Airpub",t.description=t.configs.description||"just another Airpub blog",r.wechat({title:t.configs.name,link:t.configs.url,desc:t.configs.description}),n.$on("updateMeta",function(n,r){return"string"==typeof r?t.title=r:void e.forEach(r,function(e,n){t[n]=e})})}e.module("airpub").controller("meta",["$scope","$rootScope","share",t])}(window.angular,window.debug),function(e){"use strict";function t(t,n,r,i,a){function o(e,n){var r=0===n.user_id;return e||r?void(t.isVisitor=!0):void(t.user=n)}function u(){t.hiddenSigninSection=!t.hiddenSigninSection}function c(e,n,i){t.alerts.push({msg:e,type:n||"success"});var a=t.alerts.length-1;return r(function(){t.closeAlert(a)},i?1e3*i:3e3),a}function d(e){t.alerts.splice(e,1)}function l(t,n){if(t&&(0===t.indexOf("http")||0===t.indexOf("https"))){var r=n||document.getElementsByTagName("header")[0];r&&e.element(r).css({"background-image":"url("+t+")"})}}t.location=i,t.state=n,t.hiddenSigninSection=!0,t.toggleSigninSection=u,t.alerts=[],t.addAlert=c,t.closeAlert=d,t.updateBackground=l,t.copyrightYear=(new Date).getFullYear(),a.on("ready",o)}function n(){}e.module("airpub").controller("layout",["$scope",n]).controller("base",["$scope","$state","$timeout","$location","duoshuo",t])}(window.angular,window.debug),function(e){"use strict";function t(e,t,n,r){function i(){function r(n,r,i){return t.params.page&&(u=!1),n?e.addAlert("获取信息失败,请重试","danger"):0===r.length?t.go("layout.404"):(e.articles=r||[],e.totalItems=i.cursor.total,void(t.params.page&&(e.currentPage=c)))}function i(){return t.go("layout.404")}var a={};a.page=e.currentPage,a.limit=e.itemsPerPage,a.with_content=1,n.get("threads/list",a,r,i)}function a(){u||t.go("layout.pager",{page:e.currentPage})}function o(e){return e&&!isNaN(parseInt(e))?parseInt(e):!1}if(e.itemsPerPage=10,e.currentPage=o(t.params.page)||1,r.$emit("updateMeta",e.configs.name),!(e.articles&&e.articles.length>0)){if(t.params.page)var u=!0,c=e.currentPage;i(),e.pageChanged=a}}e.module("airpub").controller("archive",["$scope","$state","duoshuo","$rootScope",t])}(window.angular,window.debug),function(e){"use strict";function t(e,t,n,r){function i(i){function o(t,n){return t?e.addAlert("文章内容获取失败,请稍后再试...","danger"):(e.article=n,r.$emit("updateMeta",{title:n.title,description:c(n.content)}),n.meta&&n.meta.background&&e.updateBackground(n.meta.background),void(n.author_id&&a(n)))}function u(){return t.go("layout.404")}function c(e){var t=80;return e?e.length<=t?e:e.substr(0,t)+"...":""}var d={};d.thread_id=i,n.get("threads/details",d,o,u)}function a(t){function r(t,n){t||(e.author=n,e.author.description=n.connected_services.weibo?n.connected_services.weibo.description:null)}var i={};i.user_id=t.author_id,n.get("users/profile",i,r)}return t.params.uri?(e.threadId=t.params.uri,void(e.article||i(t.params.uri))):t.go("layout.404")}e.module("airpub").controller("single",["$scope","$state","duoshuo","$rootScope",t])}(window.angular,window.debug),function(e){"use strict";function t(t,n,r,i,a){function o(){function e(e,i){function a(e,n){return t.isAdmin=!0,e?o(e):void(t.article=n)}function o(){return t.addAlert("文章内容获取失败,请稍后再试...","danger")}if(e||"administrator"!==i.role)return n.go("layout.home");var u="layout.update"===n.current.name&&n.params.uri;if(!u)return void(t.isAdmin=!0);var c={};c.thread_id=n.params.uri,r.get("threads/details",c,a,o)}function i(e){t.addAlert(e.errorMessage,"danger"),n.go("layout.home")}a.$emit("updateMeta",n.current.data.title),r.get("sites/membership",{},e,i)}function u(){function e(e,i){function a(e){e&&console.log(e),n.go("layout.single",{uri:i.thread_id})}if(e)return t.addAlert("发布失败...","danger");t.addAlert("发布成功");var o={};o.thread_id=i.thread_id,o.url=g+m+"/article/"+i.thread_id,r.post("threads/update",o,a),f("afterCreate",i)}function i(){return t.addAlert("发布失败...","danger")}if(!t.isAdmin)return!1;if(!t.article.title)return t.addAlert("至少写个标题咯...","danger");if(!t.article.content)return t.addAlert("至少写点内容咯...","danger");var a={};a.format="markdown",a.title=t.article.title,a.content=t.article.content,a.thread_key=uuid.v1(),a=l(a),f("beforeCreate",a),r.post("threads/create",a,e,i)}function c(e){function i(r,i){return r?t.addAlert("更新失败,请稍后再试...","danger"):(t.addAlert("更新成功!"),f("afterUpdate",i),void n.go("layout.single",{uri:e}))}function a(){return t.addAlert("更新失败,请稍后再试...","danger")}if(!e)return t.createArticle();if(!t.isAdmin)return!1;var o={};o.thread_id=e,o.title=t.article.title,o.content=t.article.content,o.url=g+m+"/article/"+e,o=l(o),f("beforeUpdate",o),r.post("threads/update",o,i,a)}function d(e){function i(r){return r?t.addAlert("删除失败,请稍后再试...","danger"):(f("afterRemove",e),t.addAlert("删除成功!"),void n.go("layout.home"))}function a(){return t.addAlert("删除失败,请稍后再试...","danger")}if(!e)return!1;if(!t.isAdmin)return!1;f("beforeRemove",e);var o={};o.thread_id=e,r.post("threads/remove",o,i,a)}function l(n){return t.article.meta?(e.forEach(t.article.meta,function(e,t){n["meta["+t+"]"]=e}),n):n}function s(e,n){return e&&n&&"function"==typeof n?(t.bindedEvents||(t.bindedEvents={}),t.bindedEvents[e]=n,t.bindedEvents):!1}function f(e,n){return t.bindedEvents&&t.bindedEvents[e]?t.bindedEvents[e](n||t.article,e):void 0}t.isAdmin=!1;var g=t.configs.url||i.host(),p=t.configs.hashPrefix||"!",m="/#"+p;o(),t.createArticle=u,t.updateArticle=c,t.removeArticle=d,t.on=s}e.module("airpub").controller("admin",["$scope","$state","duoshuo","$location","$rootScope",t])}(window.angular,window.debug),function(){"use strict";function e(e){function t(t,n,r,i){function a(){c||(c=!0,e.upload("metaBackgroundForm",function(e,t,n){if(c=!1,e)return console.error(e),alert("上传失败,请稍后再试...");var r=200===n.code&&"ok"===n.message;r&&(o(n.absUrl),i.$setViewValue(n.absUrl))}))}function o(e){if(e&&0===e.indexOf("http")){var t=document.getElementsByTagName("header")[0],n=document.getElementById("metaBackground");if(t){var r={};r["background-image"]="url("+e+")",u(t).css(r),u(n).css(r)}}}var u=angular.element,c=!1,d=document.getElementById("uploadBackgroundBtn");u(d).on("change",a),i.$render=function(){o(i.$viewValue)}}var n={restrict:"AE",require:"ngModel",replace:!0,link:t,template:['
','
','','',"上传背景图片","","
","
"].join("\n")};return n}function t(e){function t(e,t,n,r){function i(){r.$setViewValue(e.checkToShare)}function a(e){return function(e){return}}e.checkToShare=!1,e.updateCheckStatus=i,e.on("afterCreate",a()),e.on("afterUpdate",a())}var n={restrict:"AE",require:"ngModel",replace:!0,link:t,template:['
','','',"
"].join("\n")};return n}angular.module("airpub").directive("metaBackground",["upyun",e]).directive("metaShare",["duoshuo",t])}(); 2 | //# sourceMappingURL=airpub.min.js.map -------------------------------------------------------------------------------- /libs/ui-bootstrap-custom-tpls-0.12.0.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * angular-ui-bootstrap 3 | * http://angular-ui.github.io/bootstrap/ 4 | 5 | * Version: 0.12.0 - 2014-11-16 6 | * License: MIT 7 | */ 8 | angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.transition","ui.bootstrap.alert","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.position","ui.bootstrap.bindHtml","ui.bootstrap.collapse"]),angular.module("ui.bootstrap.tpls",["template/alert/alert.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html"]),angular.module("ui.bootstrap.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(t,e,n){function i(t){for(var e in t)if(void 0!==a.style[e])return t[e]}var o=function(i,a,r){r=r||{};var l=t.defer(),s=o[r.animation?"animationEndEventName":"transitionEndEventName"],u=function(){n.$apply(function(){i.unbind(s,u),l.resolve(i)})};return s&&i.bind(s,u),e(function(){angular.isString(a)?i.addClass(a):angular.isFunction(a)?a(i):angular.isObject(a)&&i.css(a),s||l.resolve(i)}),l.promise.cancel=function(){s&&i.unbind(s,u),l.reject("Transition cancelled")},l.promise},a=document.createElement("trans"),r={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},l={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return o.transitionEndEventName=i(r),o.animationEndEventName=i(l),o}]),angular.module("ui.bootstrap.alert",[]).controller("AlertController",["$scope","$attrs",function(t,e){t.closeable="close"in e,this.close=t.close}]).directive("alert",function(){return{restrict:"EA",controller:"AlertController",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"@",close:"&"}}}).directive("dismissOnTimeout",["$timeout",function(t){return{require:"alert",link:function(e,n,i,o){t(function(){o.close()},parseInt(i.dismissOnTimeout,10))}}}]),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$attrs","$parse",function(t,e,n){var i=this,o={$setViewValue:angular.noop},a=e.numPages?n(e.numPages).assign:angular.noop;this.init=function(a,r){o=a,this.config=r,o.$render=function(){i.render()},e.itemsPerPage?t.$parent.$watch(n(e.itemsPerPage),function(e){i.itemsPerPage=parseInt(e,10),t.totalPages=i.calculateTotalPages()}):this.itemsPerPage=r.itemsPerPage},this.calculateTotalPages=function(){var e=this.itemsPerPage<1?1:Math.ceil(t.totalItems/this.itemsPerPage);return Math.max(e||0,1)},this.render=function(){t.page=parseInt(o.$viewValue,10)||1},t.selectPage=function(e){t.page!==e&&e>0&&e<=t.totalPages&&(o.$setViewValue(e),o.$render())},t.getText=function(e){return t[e+"Text"]||i.config[e+"Text"]},t.noPrevious=function(){return 1===t.page},t.noNext=function(){return t.page===t.totalPages},t.$watch("totalItems",function(){t.totalPages=i.calculateTotalPages()}),t.$watch("totalPages",function(e){a(t.$parent,e),t.page>e?t.selectPage(e):o.$render()})}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["$parse","paginationConfig",function(t,e){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@"},require:["pagination","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(n,i,o,a){function r(t,e,n){return{number:t,text:e,active:n}}function l(t,e){var n=[],i=1,o=e,a=angular.isDefined(p)&&e>p;a&&(c?(i=Math.max(t-Math.floor(p/2),1),o=i+p-1,o>e&&(o=e,i=o-p+1)):(i=(Math.ceil(t/p)-1)*p+1,o=Math.min(i+p-1,e)));for(var l=i;o>=l;l++){var s=r(l,l,l===t);n.push(s)}if(a&&!c){if(i>1){var u=r(i-1,"...",!1);n.unshift(u)}if(e>o){var f=r(o+1,"...",!1);n.push(f)}}return n}var s=a[0],u=a[1];if(u){var p=angular.isDefined(o.maxSize)?n.$parent.$eval(o.maxSize):e.maxSize,c=angular.isDefined(o.rotate)?n.$parent.$eval(o.rotate):e.rotate;n.boundaryLinks=angular.isDefined(o.boundaryLinks)?n.$parent.$eval(o.boundaryLinks):e.boundaryLinks,n.directionLinks=angular.isDefined(o.directionLinks)?n.$parent.$eval(o.directionLinks):e.directionLinks,s.init(u,e),o.maxSize&&n.$parent.$watch(t(o.maxSize),function(t){p=parseInt(t,10),s.render()});var f=s.render;s.render=function(){f(),n.page>0&&n.page<=n.totalPages&&(n.pages=l(n.page,n.totalPages))}}}}}]).constant("pagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("pager",["pagerConfig",function(t){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@"},require:["pager","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(e,n,i,o){var a=o[0],r=o[1];r&&(e.align=angular.isDefined(i.align)?e.$parent.$eval(i.align):t.align,a.init(r,t))}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).provider("$tooltip",function(){function t(t){var e=/[A-Z]/g,n="-";return t.replace(e,function(t,e){return(e?n:"")+t.toLowerCase()})}var e={placement:"top",animation:!0,popupDelay:0},n={mouseenter:"mouseleave",click:"click",focus:"blur"},i={};this.options=function(t){angular.extend(i,t)},this.setTriggers=function(t){angular.extend(n,t)},this.$get=["$window","$compile","$timeout","$document","$position","$interpolate",function(o,a,r,l,s,u){return function(o,p,c){function f(t){var e=t||g.trigger||c,i=n[e]||e;return{show:e,hide:i}}var g=angular.extend({},e,i),d=t(o),m=u.startSymbol(),h=u.endSymbol(),v="
';return{restrict:"EA",compile:function(){var t=a(v);return function(e,n,i){function a(){O.isOpen?c():u()}function u(){(!D||e.$eval(i[p+"Enable"]))&&(b(),O.popupDelay?k||(k=r(d,O.popupDelay,!1),k.then(function(t){t()})):d()())}function c(){e.$apply(function(){m()})}function d(){return k=null,w&&(r.cancel(w),w=null),O.content?(h(),T.css({top:0,left:0,display:"block"}),C?l.find("body").append(T):n.after(T),L(),O.isOpen=!0,O.$digest(),L):angular.noop}function m(){O.isOpen=!1,r.cancel(k),k=null,O.animation?w||(w=r(v,500)):v()}function h(){T&&v(),y=O.$new(),T=t(y,angular.noop)}function v(){w=null,T&&(T.remove(),T=null),y&&(y.$destroy(),y=null)}function b(){$(),P()}function $(){var t=i[p+"Placement"];O.placement=angular.isDefined(t)?t:g.placement}function P(){var t=i[p+"PopupDelay"],e=parseInt(t,10);O.popupDelay=isNaN(e)?g.popupDelay:e}function x(){var t=i[p+"Trigger"];H(),E=f(t),E.show===E.hide?n.bind(E.show,a):(n.bind(E.show,u),n.bind(E.hide,c))}var T,y,w,k,C=angular.isDefined(g.appendToBody)?g.appendToBody:!1,E=f(void 0),D=angular.isDefined(i[p+"Enable"]),O=e.$new(!0),L=function(){var t=s.positionElements(n,T,O.placement,C);t.top+="px",t.left+="px",T.css(t)};O.isOpen=!1,i.$observe(o,function(t){O.content=t,!t&&O.isOpen&&m()}),i.$observe(p+"Title",function(t){O.title=t});var H=function(){n.unbind(E.show,u),n.unbind(E.hide,c)};x();var S=e.$eval(i[p+"Animation"]);O.animation=angular.isDefined(S)?!!S:g.animation;var A=e.$eval(i[p+"AppendToBody"]);C=angular.isDefined(A)?A:C,C&&e.$on("$locationChangeSuccess",function(){O.isOpen&&m()}),e.$on("$destroy",function(){r.cancel(w),r.cancel(k),H(),v(),O=null})}}}}}]}).directive("tooltipPopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(t){return t("tooltip","tooltip","mouseenter")}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).directive("tooltipHtmlUnsafe",["$tooltip",function(t){return t("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(t,e){function n(t,n){return t.currentStyle?t.currentStyle[n]:e.getComputedStyle?e.getComputedStyle(t)[n]:t.style[n]}function i(t){return"static"===(n(t,"position")||"static")}var o=function(e){for(var n=t[0],o=e.offsetParent||n;o&&o!==n&&i(o);)o=o.offsetParent;return o||n};return{position:function(e){var n=this.offset(e),i={top:0,left:0},a=o(e[0]);a!=t[0]&&(i=this.offset(angular.element(a)),i.top+=a.clientTop-a.scrollTop,i.left+=a.clientLeft-a.scrollLeft);var r=e[0].getBoundingClientRect();return{width:r.width||e.prop("offsetWidth"),height:r.height||e.prop("offsetHeight"),top:n.top-i.top,left:n.left-i.left}},offset:function(n){var i=n[0].getBoundingClientRect();return{width:i.width||n.prop("offsetWidth"),height:i.height||n.prop("offsetHeight"),top:i.top+(e.pageYOffset||t[0].documentElement.scrollTop),left:i.left+(e.pageXOffset||t[0].documentElement.scrollLeft)}},positionElements:function(t,e,n,i){var o,a,r,l,s=n.split("-"),u=s[0],p=s[1]||"center";o=i?this.offset(t):this.position(t),a=e.prop("offsetWidth"),r=e.prop("offsetHeight");var c={center:function(){return o.left+o.width/2-a/2},left:function(){return o.left},right:function(){return o.left+o.width}},f={center:function(){return o.top+o.height/2-r/2},top:function(){return o.top},bottom:function(){return o.top+o.height}};switch(u){case"right":l={top:f[p](),left:c[u]()};break;case"left":l={top:f[p](),left:o.left-a};break;case"bottom":l={top:f[u](),left:c[p]()};break;default:l={top:o.top-r,left:c[p]()}}return l}}}]),angular.module("ui.bootstrap.bindHtml",[]).directive("bindHtmlUnsafe",function(){return function(t,e,n){e.addClass("ng-binding").data("$binding",n.bindHtmlUnsafe),t.$watch(n.bindHtmlUnsafe,function(t){e.html(t||"")})}}),angular.module("ui.bootstrap.collapse",["ui.bootstrap.transition"]).directive("collapse",["$transition",function(t){return{link:function(e,n,i){function o(e){function i(){u===o&&(u=void 0)}var o=t(n,e);return u&&u.cancel(),u=o,o.then(i,i),o}function a(){p?(p=!1,r()):(n.removeClass("collapse").addClass("collapsing"),o({height:n[0].scrollHeight+"px"}).then(r))}function r(){n.removeClass("collapsing"),n.addClass("collapse in"),n.css({height:"auto"})}function l(){if(p)p=!1,s(),n.css({height:0});else{n.css({height:n[0].scrollHeight+"px"});{n[0].offsetWidth}n.removeClass("collapse in").addClass("collapsing"),o({height:0}).then(s)}}function s(){n.removeClass("collapsing"),n.addClass("collapse")}var u,p=!0;e.$watch(i.collapse,function(t){t?l():a()})}}}]),angular.module("template/alert/alert.html",[]).run(["$templateCache",function(t){t.put("template/alert/alert.html",'\n')}]),angular.module("template/pagination/pager.html",[]).run(["$templateCache",function(t){t.put("template/pagination/pager.html",'')}]),angular.module("template/pagination/pagination.html",[]).run(["$templateCache",function(t){t.put("template/pagination/pagination.html",'')}]),angular.module("template/tooltip/tooltip-html-unsafe-popup.html",[]).run(["$templateCache",function(t){t.put("template/tooltip/tooltip-html-unsafe-popup.html",'
\n
\n
\n
\n')}]),angular.module("template/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(t){t.put("template/tooltip/tooltip-popup.html",'
\n
\n
\n
\n')}]); -------------------------------------------------------------------------------- /dist/airpub.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"dist/airpub.min.js","sources":["src/airpub.js","src/filters/marked.js","src/services/share.js","src/controllers/global.js","src/controllers/meta.js","src/controllers/base.js","src/controllers/archive.js","src/controllers/single.js","src/controllers/admin.js","src/addons/meta.js"],"names":["angular","initAirpub","$stateProvider","$urlRouterProvider","$locationProvider","$ocLazyLoadProvider","upyunProvider","defineRoutes","routes","routers","forEach","route","templateUrl","themePath","controller","views","layout","@layout","archive","@layout.home","indexOf","resolve","lazyloadResources","map","admin","loadEditor","single","loadSingle","lazyload","$ocLazyLoad","load","then","files","staticPath","routerMaker","url","router","data","obj","copy","extend","appendTitleToRouter","title","initWeixinShare","window","wechat","airpubConfigs","link","description","desc","name","theme","otherwise","state","config","modules","hashPrefix","html5Mode","upyun","module","debug","markedFilter","$sce","$sanitize","raw","highlightCode","code","hljs","highlightAuto","value","parseWrapperString","wrappers","parsed","str","key","split","injectTo","entryHtml","parseName","arr","length","substr","ret","token","domNotes","wraps","item","attrName","charAt","marked","Error","arguments","Array","prototype","slice","call","markedOptions","render","Renderer","lang","escaped","html","this","type","apply","all","renderer","highlight","setOptions","trustAsHtml","filter","shareService","wechatShare","article","defaults","service","globalCtrler","$scope","configs","console","error","metaCtrler","$rootScope","share","$on","eve","v","k","baseCtrler","$state","$timeout","$location","duoshuo","initAccount","err","isVisitor","user_id","user","toggleSigninSection","hiddenSigninSection","addAlert","msg","dismiss","alerts","push","alertIndex","closeAlert","index","splice","updateBackground","uri","dom","hd","document","getElementsByTagName","element","css","background-image","location","copyrightYear","Date","getFullYear","on","layoutCtrler","archiveCtrler","fetchFreshArticles","onSuccess","result","res","params","page","lock","go","articles","totalItems","cursor","total","currentPage","onError","query","limit","itemsPerPage","with_content","get","pageChanged","parseNumber","isNaN","parseInt","$emit","singleArticleCtrler","fetchFreshDetail","thread_id","fetchDesciption","content","meta","background","author_id","fetchUserProfile","text","maxLength","author","connected_services","weibo","threadId","adminCtrler","initAdmin","response","isAdmin","fail","role","isUpdatePage","current","errorMessage","createArticle","log","baseUri","hashTag","post","eventTrigger","baby","format","thread_key","uuid","v1","insertMeta","updateArticle","id","removeArticle","qs","eventBinder","eventName","func","bindedEvents","host","metaBackgroundDirective","scope","attrs","ctrl","bindUpload","uploading","upload","image","alert","uploadOk","message","fillBackgroundImage","absUrl","$setViewValue","self","getElementById","style","$","inputButton","$render","$viewValue","directive","restrict","require","replace","template","join","metaShareDirective","updateCheckingStatus","checkToShare","shareArticle","updateCheckStatus"],"mappings":"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"} -------------------------------------------------------------------------------- /dist/airpub-dependencies.min.css: -------------------------------------------------------------------------------- 1 | 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}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0}mark{background:#ff0;color:#000}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}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{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[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-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*,:after,:before{background:0 0!important;color:#000!important;box-shadow:none!important;text-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}*,:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:transparent}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:dotted thin;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container,.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.row{margin-left:-15px;margin-right:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered,.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;float:none;display:table-column}table td[class*=col-],table th[class*=col-]{position:static;float:none;display:table-cell}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:dotted thin;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date],input[type=datetime-local],input[type=month],input[type=time]{line-height:34px}input[type=date].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm,input[type=time].input-sm{line-height:30px}input[type=date].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg,input[type=time].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:400;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}.checkbox-inline.disabled,.checkbox.disabled label,.radio-inline.disabled,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio label,fieldset[disabled] .radio-inline,fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.form-group-sm .form-control,.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.form-group-sm .form-control,select.input-sm{height:30px;line-height:30px}select[multiple].form-group-sm .form-control,select[multiple].input-sm,textarea.form-group-sm .form-control,textarea.input-sm{height:auto}.form-group-lg .form-control,.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.form-group-lg .form-control,select.input-lg{height:46px;line-height:46px}select[multiple].form-group-lg .form-control,select[multiple].input-lg,textarea.form-group-lg .form-control,textarea.input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:7px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.3px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px}}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:dotted thin;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.active,.btn-default.focus,.btn-default:active,.btn-default:focus,.btn-default:hover,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.active,.btn-primary.focus,.btn-primary:active,.btn-primary:focus,.btn-primary:hover,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.active,.btn-success.focus,.btn-success:active,.btn-success:focus,.btn-success:hover,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.active,.btn-info.focus,.btn-info:active,.btn-info:focus,.btn-info:hover,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.active,.btn-warning.focus,.btn-warning:active,.btn-warning:focus,.btn-warning:hover,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.active,.btn-danger.focus,.btn-danger:active,.btn-danger:focus,.btn-danger:hover,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#337ab7;font-weight:400;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none;visibility:hidden}.collapse.in{display:block;visibility:visible}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height,visibility;transition-property:height,visibility;-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;transition-timing-function:ease}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-left:auto;margin-right:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.42857143;text-decoration:none;color:#337ab7;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7;cursor:default}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;background-color:#fff;cursor:not-allowed}.tooltip{position:absolute;z-index:1070;display:block;visibility:visible;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-weight:400;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;right:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.pager:after,.pager:before,.row:after,.row:before{content:" ";display:table}.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.pager:after,.row:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-print,.visible-print-block,.visible-print-inline,.visible-print-inline-block,.visible-sm,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}@media print{.visible-print-block{display:block!important}}@media print{.visible-print-inline{display:inline!important}}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;-webkit-transform:rotate(3deg) translate(0px,-4px);-ms-transform:rotate(3deg) translate(0px,-4px);transform:rotate(3deg) translate(0px,-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner 400ms linear infinite;animation:nprogress-spinner 400ms linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.hljs{display:block;padding:.5em;color:#333;background:#f8f8f8}.diff .hljs-header,.hljs-comment,.hljs-javadoc,.hljs-template_comment{color:#998;font-style:italic}.css .rule .hljs-keyword,.hljs-keyword,.hljs-request,.hljs-status,.hljs-subst,.hljs-winutils,.javascript .hljs-title,.nginx .hljs-title{color:#333;font-weight:700}.hljs-hexcolor,.hljs-number,.ruby .hljs-constant{color:#099}.hljs-phpdoc,.hljs-string,.hljs-tag .hljs-value,.tex .hljs-formula{color:#d14}.coffeescript .hljs-params,.hljs-id,.hljs-title,.scss .hljs-preprocessor{color:#900;font-weight:700}.clojure .hljs-title,.hljs-subst,.javascript .hljs-title,.lisp .hljs-title{font-weight:400}.haskell .hljs-type,.hljs-class .hljs-title,.tex .hljs-command,.vhdl .hljs-literal{color:#458;font-weight:700}.django .hljs-tag .hljs-keyword,.hljs-rules .hljs-property,.hljs-tag,.hljs-tag .hljs-title{color:navy;font-weight:400}.hljs-attribute,.hljs-variable,.lisp .hljs-body{color:teal}.hljs-regexp{color:#009926}.hljs-prompt,.hljs-symbol,.lisp .hljs-keyword,.ruby .hljs-symbol .hljs-string,.tex .hljs-special{color:#990073}.clojure .hljs-built_in,.hljs-built_in,.lisp .hljs-title{color:#0086b3}.hljs-cdata,.hljs-doctype,.hljs-pi,.hljs-pragma,.hljs-preprocessor,.hljs-shebang{color:#999;font-weight:700}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.diff .hljs-change{background:#0086b3}.hljs-chunk{color:#aaa} --------------------------------------------------------------------------------