├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── main.py ├── pyprint ├── __init__.py ├── background │ ├── static │ │ ├── css │ │ │ ├── bootstrap-theme.css.map │ │ │ ├── bootstrap-theme.min.css │ │ │ ├── bootstrap.css.map │ │ │ ├── bootstrap.min.css │ │ │ ├── foundation-icons.css │ │ │ ├── foundation-icons.eot │ │ │ ├── foundation-icons.ttf │ │ │ ├── foundation-icons.woff │ │ │ └── style.css │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ └── glyphicons-halflings-regular.woff │ │ └── js │ │ │ ├── bootstrap.min.js │ │ │ └── jquery.js │ └── templates │ │ ├── add_post.html │ │ ├── layout.html │ │ ├── links.html │ │ ├── login.html │ │ └── posts.html ├── constants.py ├── database.py ├── handler.py ├── localsettings.example.py ├── models.py ├── settings.py ├── themes │ ├── __init__.py │ ├── clean │ │ ├── __init__.py │ │ ├── config.py │ │ ├── static │ │ │ └── css │ │ │ │ ├── style.css │ │ │ │ └── yue.css │ │ └── templates │ │ │ ├── diaries.html │ │ │ ├── feed.xml │ │ │ ├── index.html │ │ │ ├── layout.html │ │ │ ├── links.html │ │ │ ├── not_found.html │ │ │ └── post.html │ ├── default │ │ ├── static │ │ │ ├── css │ │ │ │ ├── akarin.css │ │ │ │ ├── archives.css │ │ │ │ ├── foundation-icons.css │ │ │ │ ├── foundation-icons.eot │ │ │ │ ├── foundation-icons.ttf │ │ │ │ ├── foundation-icons.woff │ │ │ │ ├── layout.css │ │ │ │ ├── links.css │ │ │ │ ├── nprogress.css │ │ │ │ ├── post.css │ │ │ │ └── yue.css │ │ │ ├── imgs │ │ │ │ ├── avatar.jpg │ │ │ │ ├── banner.jpg │ │ │ │ └── not_found.jpg │ │ │ └── js │ │ │ │ ├── jquery.lazyload.js │ │ │ │ ├── jquery.min.js │ │ │ │ ├── jquery.pjax.js │ │ │ │ └── nprogress.js │ │ └── templates │ │ │ ├── archives.html │ │ │ ├── diaries.html │ │ │ ├── feed.xml │ │ │ ├── index.html │ │ │ ├── layout.html │ │ │ ├── links.html │ │ │ ├── not_found.html │ │ │ ├── pjax_layout.html │ │ │ └── post.html │ ├── mdl │ │ ├── static │ │ │ ├── css │ │ │ │ ├── font.css │ │ │ │ ├── material-scrolltop.css │ │ │ │ ├── material.min.css │ │ │ │ ├── style.css │ │ │ │ └── yue.css │ │ │ ├── imgs │ │ │ │ ├── avatar.jpg │ │ │ │ ├── not_found.gif │ │ │ │ └── top-arrow.svg │ │ │ └── js │ │ │ │ ├── jquery.min.js │ │ │ │ ├── jquery.pjax.js │ │ │ │ ├── material-progress.js │ │ │ │ ├── material-scrolltop.js │ │ │ │ ├── material.min.js │ │ │ │ └── material.min.js.map │ │ └── templates │ │ │ ├── archives.html │ │ │ ├── diaries.html │ │ │ ├── feed.xml │ │ │ ├── index.html │ │ │ ├── layout.html │ │ │ ├── links.html │ │ │ ├── not_found.html │ │ │ ├── pjax_layout.html │ │ │ └── post.html │ └── none │ │ └── templates │ │ ├── diaries.html │ │ ├── feed.xml │ │ ├── index.html │ │ ├── layout.html │ │ ├── links.html │ │ ├── not_found.html │ │ └── post.html ├── utils.py └── views │ ├── __init__.py │ ├── background.py │ ├── diaries.py │ ├── links.py │ ├── others.py │ └── posts.py └── requirement.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.db3 3 | .idea 4 | *.db 5 | pyprint/localsettings.py 6 | pyprint/themes/default/static/postimg/* 7 | *.log 8 | .python-version 9 | .DS_Store 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Ricter Zheng 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | pyprint 2 | ======= 3 | 4 | Blog system just for me 5 | 6 | ### Usage 7 | 8 | git clone https://github.com/RicterZ/pyprint 9 | cd pyprint 10 | python pyprint/models.py 11 | python main.py --port=8888 --address=0.0.0.0 12 | 13 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import tornado.ioloop 2 | import tornado.httpserver 3 | import tornado.options 4 | from tornado.options import options, define 5 | 6 | from pyprint import Application 7 | 8 | define('port', default=8888, help='listen on the port', type=int) 9 | define('address', default='0.0.0.0', help='binding at given address', type=str) 10 | 11 | if __name__ == '__main__': 12 | tornado.options.parse_command_line() 13 | http_server = tornado.httpserver.HTTPServer(Application()) 14 | http_server.listen(options.port, address=options.address) 15 | print '[+] PyPrint listening on {address}:{port}'.format(address=options.address, 16 | port=options.port) 17 | tornado.ioloop.IOLoop.instance().start() 18 | 19 | -------------------------------------------------------------------------------- /pyprint/__init__.py: -------------------------------------------------------------------------------- 1 | import os.path 2 | from hashlib import md5 3 | 4 | # third-part 5 | import tornado.web 6 | 7 | # custom 8 | import views 9 | from settings import * 10 | from models import engine 11 | 12 | 13 | theme_path = os.path.join(os.path.dirname(__file__), 'themes/{theme_name}'.format(theme_name=theme)) 14 | background_path = os.path.join(os.path.dirname(__file__), 'background') 15 | 16 | class Application(tornado.web.Application): 17 | def __init__(self): 18 | handlers = views.handlers 19 | handlers.insert(0, (r'/kamisama/static/(.*)', tornado.web.StaticFileHandler, 20 | {'path': os.path.join(background_path, 'static')})) 21 | 22 | settings = dict( 23 | background_template_path=os.path.join(background_path, 'templates'), 24 | 25 | static_path=os.path.join(theme_path, 'static'), 26 | template_path=os.path.join(theme_path, 'templates'), 27 | login_url='/login', 28 | cookie_secret=cookie_secret, 29 | 30 | post_of_page=post_of_page, 31 | 32 | username=username, 33 | email=email, 34 | email_md5=md5(email.lower()).hexdigest(), 35 | motto=motto, 36 | title=title, 37 | disqus_shortname=disqus_shortname, 38 | analytics_code=analytics_code, 39 | 40 | debug=debug, 41 | ) 42 | 43 | tornado.web.Application.__init__(self, handlers=handlers, **settings) 44 | 45 | -------------------------------------------------------------------------------- /pyprint/background/static/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.1.1 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | 7 | .btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn:active,.btn.active{background-image:none}.btn-default{background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;text-shadow:0 1px 0 #fff;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-primary{background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#2b669a}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-color:#357ebd}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:linear-gradient(to bottom,#222 0,#282828 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0)}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0)}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0)}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0)}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0)}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0)}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} -------------------------------------------------------------------------------- /pyprint/background/static/css/foundation-icons.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Foundation Icons v 3.0 3 | * Made by ZURB 2013 http://zurb.com/playground/foundation-icon-fonts-3 4 | * MIT License 5 | */ 6 | 7 | @font-face { 8 | font-family: "foundation-icons"; 9 | src: url("foundation-icons.eot"); 10 | src: url("foundation-icons.eot?#iefix") format("embedded-opentype"), 11 | url("foundation-icons.woff") format("woff"), 12 | url("foundation-icons.ttf") format("truetype"), 13 | url("foundation-icons.svg#fontcustom") format("svg"); 14 | font-weight: normal; 15 | font-style: normal; 16 | } 17 | 18 | .fi-address-book:before, 19 | .fi-alert:before, 20 | .fi-align-center:before, 21 | .fi-align-justify:before, 22 | .fi-align-left:before, 23 | .fi-align-right:before, 24 | .fi-anchor:before, 25 | .fi-annotate:before, 26 | .fi-archive:before, 27 | .fi-arrow-down:before, 28 | .fi-arrow-left:before, 29 | .fi-arrow-right:before, 30 | .fi-arrow-up:before, 31 | .fi-arrows-compress:before, 32 | .fi-arrows-expand:before, 33 | .fi-arrows-in:before, 34 | .fi-arrows-out:before, 35 | .fi-asl:before, 36 | .fi-asterisk:before, 37 | .fi-at-sign:before, 38 | .fi-background-color:before, 39 | .fi-battery-empty:before, 40 | .fi-battery-full:before, 41 | .fi-battery-half:before, 42 | .fi-bitcoin-circle:before, 43 | .fi-bitcoin:before, 44 | .fi-blind:before, 45 | .fi-bluetooth:before, 46 | .fi-bold:before, 47 | .fi-book-bookmark:before, 48 | .fi-book:before, 49 | .fi-bookmark:before, 50 | .fi-braille:before, 51 | .fi-burst-new:before, 52 | .fi-burst-sale:before, 53 | .fi-burst:before, 54 | .fi-calendar:before, 55 | .fi-camera:before, 56 | .fi-check:before, 57 | .fi-checkbox:before, 58 | .fi-clipboard-notes:before, 59 | .fi-clipboard-pencil:before, 60 | .fi-clipboard:before, 61 | .fi-clock:before, 62 | .fi-closed-caption:before, 63 | .fi-cloud:before, 64 | .fi-comment-minus:before, 65 | .fi-comment-quotes:before, 66 | .fi-comment-video:before, 67 | .fi-comment:before, 68 | .fi-comments:before, 69 | .fi-compass:before, 70 | .fi-contrast:before, 71 | .fi-credit-card:before, 72 | .fi-crop:before, 73 | .fi-crown:before, 74 | .fi-css3:before, 75 | .fi-database:before, 76 | .fi-die-five:before, 77 | .fi-die-four:before, 78 | .fi-die-one:before, 79 | .fi-die-six:before, 80 | .fi-die-three:before, 81 | .fi-die-two:before, 82 | .fi-dislike:before, 83 | .fi-dollar-bill:before, 84 | .fi-dollar:before, 85 | .fi-download:before, 86 | .fi-eject:before, 87 | .fi-elevator:before, 88 | .fi-euro:before, 89 | .fi-eye:before, 90 | .fi-fast-forward:before, 91 | .fi-female-symbol:before, 92 | .fi-female:before, 93 | .fi-filter:before, 94 | .fi-first-aid:before, 95 | .fi-flag:before, 96 | .fi-folder-add:before, 97 | .fi-folder-lock:before, 98 | .fi-folder:before, 99 | .fi-foot:before, 100 | .fi-foundation:before, 101 | .fi-graph-bar:before, 102 | .fi-graph-horizontal:before, 103 | .fi-graph-pie:before, 104 | .fi-graph-trend:before, 105 | .fi-guide-dog:before, 106 | .fi-hearing-aid:before, 107 | .fi-heart:before, 108 | .fi-home:before, 109 | .fi-html5:before, 110 | .fi-indent-less:before, 111 | .fi-indent-more:before, 112 | .fi-info:before, 113 | .fi-italic:before, 114 | .fi-key:before, 115 | .fi-laptop:before, 116 | .fi-layout:before, 117 | .fi-lightbulb:before, 118 | .fi-like:before, 119 | .fi-link:before, 120 | .fi-list-bullet:before, 121 | .fi-list-number:before, 122 | .fi-list-thumbnails:before, 123 | .fi-list:before, 124 | .fi-lock:before, 125 | .fi-loop:before, 126 | .fi-magnifying-glass:before, 127 | .fi-mail:before, 128 | .fi-male-female:before, 129 | .fi-male-symbol:before, 130 | .fi-male:before, 131 | .fi-map:before, 132 | .fi-marker:before, 133 | .fi-megaphone:before, 134 | .fi-microphone:before, 135 | .fi-minus-circle:before, 136 | .fi-minus:before, 137 | .fi-mobile-signal:before, 138 | .fi-mobile:before, 139 | .fi-monitor:before, 140 | .fi-mountains:before, 141 | .fi-music:before, 142 | .fi-next:before, 143 | .fi-no-dogs:before, 144 | .fi-no-smoking:before, 145 | .fi-page-add:before, 146 | .fi-page-copy:before, 147 | .fi-page-csv:before, 148 | .fi-page-delete:before, 149 | .fi-page-doc:before, 150 | .fi-page-edit:before, 151 | .fi-page-export-csv:before, 152 | .fi-page-export-doc:before, 153 | .fi-page-export-pdf:before, 154 | .fi-page-export:before, 155 | .fi-page-filled:before, 156 | .fi-page-multiple:before, 157 | .fi-page-pdf:before, 158 | .fi-page-remove:before, 159 | .fi-page-search:before, 160 | .fi-page:before, 161 | .fi-paint-bucket:before, 162 | .fi-paperclip:before, 163 | .fi-pause:before, 164 | .fi-paw:before, 165 | .fi-paypal:before, 166 | .fi-pencil:before, 167 | .fi-photo:before, 168 | .fi-play-circle:before, 169 | .fi-play-video:before, 170 | .fi-play:before, 171 | .fi-plus:before, 172 | .fi-pound:before, 173 | .fi-power:before, 174 | .fi-previous:before, 175 | .fi-price-tag:before, 176 | .fi-pricetag-multiple:before, 177 | .fi-print:before, 178 | .fi-prohibited:before, 179 | .fi-projection-screen:before, 180 | .fi-puzzle:before, 181 | .fi-quote:before, 182 | .fi-record:before, 183 | .fi-refresh:before, 184 | .fi-results-demographics:before, 185 | .fi-results:before, 186 | .fi-rewind-ten:before, 187 | .fi-rewind:before, 188 | .fi-rss:before, 189 | .fi-safety-cone:before, 190 | .fi-save:before, 191 | .fi-share:before, 192 | .fi-sheriff-badge:before, 193 | .fi-shield:before, 194 | .fi-shopping-bag:before, 195 | .fi-shopping-cart:before, 196 | .fi-shuffle:before, 197 | .fi-skull:before, 198 | .fi-social-500px:before, 199 | .fi-social-adobe:before, 200 | .fi-social-amazon:before, 201 | .fi-social-android:before, 202 | .fi-social-apple:before, 203 | .fi-social-behance:before, 204 | .fi-social-bing:before, 205 | .fi-social-blogger:before, 206 | .fi-social-delicious:before, 207 | .fi-social-designer-news:before, 208 | .fi-social-deviant-art:before, 209 | .fi-social-digg:before, 210 | .fi-social-dribbble:before, 211 | .fi-social-drive:before, 212 | .fi-social-dropbox:before, 213 | .fi-social-evernote:before, 214 | .fi-social-facebook:before, 215 | .fi-social-flickr:before, 216 | .fi-social-forrst:before, 217 | .fi-social-foursquare:before, 218 | .fi-social-game-center:before, 219 | .fi-social-github:before, 220 | .fi-social-google-plus:before, 221 | .fi-social-hacker-news:before, 222 | .fi-social-hi5:before, 223 | .fi-social-instagram:before, 224 | .fi-social-joomla:before, 225 | .fi-social-lastfm:before, 226 | .fi-social-linkedin:before, 227 | .fi-social-medium:before, 228 | .fi-social-myspace:before, 229 | .fi-social-orkut:before, 230 | .fi-social-path:before, 231 | .fi-social-picasa:before, 232 | .fi-social-pinterest:before, 233 | .fi-social-rdio:before, 234 | .fi-social-reddit:before, 235 | .fi-social-skillshare:before, 236 | .fi-social-skype:before, 237 | .fi-social-smashing-mag:before, 238 | .fi-social-snapchat:before, 239 | .fi-social-spotify:before, 240 | .fi-social-squidoo:before, 241 | .fi-social-stack-overflow:before, 242 | .fi-social-steam:before, 243 | .fi-social-stumbleupon:before, 244 | .fi-social-treehouse:before, 245 | .fi-social-tumblr:before, 246 | .fi-social-twitter:before, 247 | .fi-social-vimeo:before, 248 | .fi-social-windows:before, 249 | .fi-social-xbox:before, 250 | .fi-social-yahoo:before, 251 | .fi-social-yelp:before, 252 | .fi-social-youtube:before, 253 | .fi-social-zerply:before, 254 | .fi-social-zurb:before, 255 | .fi-sound:before, 256 | .fi-star:before, 257 | .fi-stop:before, 258 | .fi-strikethrough:before, 259 | .fi-subscript:before, 260 | .fi-superscript:before, 261 | .fi-tablet-landscape:before, 262 | .fi-tablet-portrait:before, 263 | .fi-target-two:before, 264 | .fi-target:before, 265 | .fi-telephone-accessible:before, 266 | .fi-telephone:before, 267 | .fi-text-color:before, 268 | .fi-thumbnails:before, 269 | .fi-ticket:before, 270 | .fi-torso-business:before, 271 | .fi-torso-female:before, 272 | .fi-torso:before, 273 | .fi-torsos-all-female:before, 274 | .fi-torsos-all:before, 275 | .fi-torsos-female-male:before, 276 | .fi-torsos-male-female:before, 277 | .fi-torsos:before, 278 | .fi-trash:before, 279 | .fi-trees:before, 280 | .fi-trophy:before, 281 | .fi-underline:before, 282 | .fi-universal-access:before, 283 | .fi-unlink:before, 284 | .fi-unlock:before, 285 | .fi-upload-cloud:before, 286 | .fi-upload:before, 287 | .fi-usb:before, 288 | .fi-video:before, 289 | .fi-volume-none:before, 290 | .fi-volume-strike:before, 291 | .fi-volume:before, 292 | .fi-web:before, 293 | .fi-wheelchair:before, 294 | .fi-widget:before, 295 | .fi-wrench:before, 296 | .fi-x-circle:before, 297 | .fi-x:before, 298 | .fi-yen:before, 299 | .fi-zoom-in:before, 300 | .fi-zoom-out:before { 301 | font-family: "foundation-icons"; 302 | font-style: normal; 303 | font-weight: normal; 304 | font-variant: normal; 305 | text-transform: none; 306 | line-height: 1; 307 | -webkit-font-smoothing: antialiased; 308 | display: inline-block; 309 | text-decoration: inherit; 310 | } 311 | 312 | .fi-address-book:before { content: "\f100"; } 313 | .fi-alert:before { content: "\f101"; } 314 | .fi-align-center:before { content: "\f102"; } 315 | .fi-align-justify:before { content: "\f103"; } 316 | .fi-align-left:before { content: "\f104"; } 317 | .fi-align-right:before { content: "\f105"; } 318 | .fi-anchor:before { content: "\f106"; } 319 | .fi-annotate:before { content: "\f107"; } 320 | .fi-archive:before { content: "\f108"; } 321 | .fi-arrow-down:before { content: "\f109"; } 322 | .fi-arrow-left:before { content: "\f10a"; } 323 | .fi-arrow-right:before { content: "\f10b"; } 324 | .fi-arrow-up:before { content: "\f10c"; } 325 | .fi-arrows-compress:before { content: "\f10d"; } 326 | .fi-arrows-expand:before { content: "\f10e"; } 327 | .fi-arrows-in:before { content: "\f10f"; } 328 | .fi-arrows-out:before { content: "\f110"; } 329 | .fi-asl:before { content: "\f111"; } 330 | .fi-asterisk:before { content: "\f112"; } 331 | .fi-at-sign:before { content: "\f113"; } 332 | .fi-background-color:before { content: "\f114"; } 333 | .fi-battery-empty:before { content: "\f115"; } 334 | .fi-battery-full:before { content: "\f116"; } 335 | .fi-battery-half:before { content: "\f117"; } 336 | .fi-bitcoin-circle:before { content: "\f118"; } 337 | .fi-bitcoin:before { content: "\f119"; } 338 | .fi-blind:before { content: "\f11a"; } 339 | .fi-bluetooth:before { content: "\f11b"; } 340 | .fi-bold:before { content: "\f11c"; } 341 | .fi-book-bookmark:before { content: "\f11d"; } 342 | .fi-book:before { content: "\f11e"; } 343 | .fi-bookmark:before { content: "\f11f"; } 344 | .fi-braille:before { content: "\f120"; } 345 | .fi-burst-new:before { content: "\f121"; } 346 | .fi-burst-sale:before { content: "\f122"; } 347 | .fi-burst:before { content: "\f123"; } 348 | .fi-calendar:before { content: "\f124"; } 349 | .fi-camera:before { content: "\f125"; } 350 | .fi-check:before { content: "\f126"; } 351 | .fi-checkbox:before { content: "\f127"; } 352 | .fi-clipboard-notes:before { content: "\f128"; } 353 | .fi-clipboard-pencil:before { content: "\f129"; } 354 | .fi-clipboard:before { content: "\f12a"; } 355 | .fi-clock:before { content: "\f12b"; } 356 | .fi-closed-caption:before { content: "\f12c"; } 357 | .fi-cloud:before { content: "\f12d"; } 358 | .fi-comment-minus:before { content: "\f12e"; } 359 | .fi-comment-quotes:before { content: "\f12f"; } 360 | .fi-comment-video:before { content: "\f130"; } 361 | .fi-comment:before { content: "\f131"; } 362 | .fi-comments:before { content: "\f132"; } 363 | .fi-compass:before { content: "\f133"; } 364 | .fi-contrast:before { content: "\f134"; } 365 | .fi-credit-card:before { content: "\f135"; } 366 | .fi-crop:before { content: "\f136"; } 367 | .fi-crown:before { content: "\f137"; } 368 | .fi-css3:before { content: "\f138"; } 369 | .fi-database:before { content: "\f139"; } 370 | .fi-die-five:before { content: "\f13a"; } 371 | .fi-die-four:before { content: "\f13b"; } 372 | .fi-die-one:before { content: "\f13c"; } 373 | .fi-die-six:before { content: "\f13d"; } 374 | .fi-die-three:before { content: "\f13e"; } 375 | .fi-die-two:before { content: "\f13f"; } 376 | .fi-dislike:before { content: "\f140"; } 377 | .fi-dollar-bill:before { content: "\f141"; } 378 | .fi-dollar:before { content: "\f142"; } 379 | .fi-download:before { content: "\f143"; } 380 | .fi-eject:before { content: "\f144"; } 381 | .fi-elevator:before { content: "\f145"; } 382 | .fi-euro:before { content: "\f146"; } 383 | .fi-eye:before { content: "\f147"; } 384 | .fi-fast-forward:before { content: "\f148"; } 385 | .fi-female-symbol:before { content: "\f149"; } 386 | .fi-female:before { content: "\f14a"; } 387 | .fi-filter:before { content: "\f14b"; } 388 | .fi-first-aid:before { content: "\f14c"; } 389 | .fi-flag:before { content: "\f14d"; } 390 | .fi-folder-add:before { content: "\f14e"; } 391 | .fi-folder-lock:before { content: "\f14f"; } 392 | .fi-folder:before { content: "\f150"; } 393 | .fi-foot:before { content: "\f151"; } 394 | .fi-foundation:before { content: "\f152"; } 395 | .fi-graph-bar:before { content: "\f153"; } 396 | .fi-graph-horizontal:before { content: "\f154"; } 397 | .fi-graph-pie:before { content: "\f155"; } 398 | .fi-graph-trend:before { content: "\f156"; } 399 | .fi-guide-dog:before { content: "\f157"; } 400 | .fi-hearing-aid:before { content: "\f158"; } 401 | .fi-heart:before { content: "\f159"; } 402 | .fi-home:before { content: "\f15a"; } 403 | .fi-html5:before { content: "\f15b"; } 404 | .fi-indent-less:before { content: "\f15c"; } 405 | .fi-indent-more:before { content: "\f15d"; } 406 | .fi-info:before { content: "\f15e"; } 407 | .fi-italic:before { content: "\f15f"; } 408 | .fi-key:before { content: "\f160"; } 409 | .fi-laptop:before { content: "\f161"; } 410 | .fi-layout:before { content: "\f162"; } 411 | .fi-lightbulb:before { content: "\f163"; } 412 | .fi-like:before { content: "\f164"; } 413 | .fi-link:before { content: "\f165"; } 414 | .fi-list-bullet:before { content: "\f166"; } 415 | .fi-list-number:before { content: "\f167"; } 416 | .fi-list-thumbnails:before { content: "\f168"; } 417 | .fi-list:before { content: "\f169"; } 418 | .fi-lock:before { content: "\f16a"; } 419 | .fi-loop:before { content: "\f16b"; } 420 | .fi-magnifying-glass:before { content: "\f16c"; } 421 | .fi-mail:before { content: "\f16d"; } 422 | .fi-male-female:before { content: "\f16e"; } 423 | .fi-male-symbol:before { content: "\f16f"; } 424 | .fi-male:before { content: "\f170"; } 425 | .fi-map:before { content: "\f171"; } 426 | .fi-marker:before { content: "\f172"; } 427 | .fi-megaphone:before { content: "\f173"; } 428 | .fi-microphone:before { content: "\f174"; } 429 | .fi-minus-circle:before { content: "\f175"; } 430 | .fi-minus:before { content: "\f176"; } 431 | .fi-mobile-signal:before { content: "\f177"; } 432 | .fi-mobile:before { content: "\f178"; } 433 | .fi-monitor:before { content: "\f179"; } 434 | .fi-mountains:before { content: "\f17a"; } 435 | .fi-music:before { content: "\f17b"; } 436 | .fi-next:before { content: "\f17c"; } 437 | .fi-no-dogs:before { content: "\f17d"; } 438 | .fi-no-smoking:before { content: "\f17e"; } 439 | .fi-page-add:before { content: "\f17f"; } 440 | .fi-page-copy:before { content: "\f180"; } 441 | .fi-page-csv:before { content: "\f181"; } 442 | .fi-page-delete:before { content: "\f182"; } 443 | .fi-page-doc:before { content: "\f183"; } 444 | .fi-page-edit:before { content: "\f184"; } 445 | .fi-page-export-csv:before { content: "\f185"; } 446 | .fi-page-export-doc:before { content: "\f186"; } 447 | .fi-page-export-pdf:before { content: "\f187"; } 448 | .fi-page-export:before { content: "\f188"; } 449 | .fi-page-filled:before { content: "\f189"; } 450 | .fi-page-multiple:before { content: "\f18a"; } 451 | .fi-page-pdf:before { content: "\f18b"; } 452 | .fi-page-remove:before { content: "\f18c"; } 453 | .fi-page-search:before { content: "\f18d"; } 454 | .fi-page:before { content: "\f18e"; } 455 | .fi-paint-bucket:before { content: "\f18f"; } 456 | .fi-paperclip:before { content: "\f190"; } 457 | .fi-pause:before { content: "\f191"; } 458 | .fi-paw:before { content: "\f192"; } 459 | .fi-paypal:before { content: "\f193"; } 460 | .fi-pencil:before { content: "\f194"; } 461 | .fi-photo:before { content: "\f195"; } 462 | .fi-play-circle:before { content: "\f196"; } 463 | .fi-play-video:before { content: "\f197"; } 464 | .fi-play:before { content: "\f198"; } 465 | .fi-plus:before { content: "\f199"; } 466 | .fi-pound:before { content: "\f19a"; } 467 | .fi-power:before { content: "\f19b"; } 468 | .fi-previous:before { content: "\f19c"; } 469 | .fi-price-tag:before { content: "\f19d"; } 470 | .fi-pricetag-multiple:before { content: "\f19e"; } 471 | .fi-print:before { content: "\f19f"; } 472 | .fi-prohibited:before { content: "\f1a0"; } 473 | .fi-projection-screen:before { content: "\f1a1"; } 474 | .fi-puzzle:before { content: "\f1a2"; } 475 | .fi-quote:before { content: "\f1a3"; } 476 | .fi-record:before { content: "\f1a4"; } 477 | .fi-refresh:before { content: "\f1a5"; } 478 | .fi-results-demographics:before { content: "\f1a6"; } 479 | .fi-results:before { content: "\f1a7"; } 480 | .fi-rewind-ten:before { content: "\f1a8"; } 481 | .fi-rewind:before { content: "\f1a9"; } 482 | .fi-rss:before { content: "\f1aa"; } 483 | .fi-safety-cone:before { content: "\f1ab"; } 484 | .fi-save:before { content: "\f1ac"; } 485 | .fi-share:before { content: "\f1ad"; } 486 | .fi-sheriff-badge:before { content: "\f1ae"; } 487 | .fi-shield:before { content: "\f1af"; } 488 | .fi-shopping-bag:before { content: "\f1b0"; } 489 | .fi-shopping-cart:before { content: "\f1b1"; } 490 | .fi-shuffle:before { content: "\f1b2"; } 491 | .fi-skull:before { content: "\f1b3"; } 492 | .fi-social-500px:before { content: "\f1b4"; } 493 | .fi-social-adobe:before { content: "\f1b5"; } 494 | .fi-social-amazon:before { content: "\f1b6"; } 495 | .fi-social-android:before { content: "\f1b7"; } 496 | .fi-social-apple:before { content: "\f1b8"; } 497 | .fi-social-behance:before { content: "\f1b9"; } 498 | .fi-social-bing:before { content: "\f1ba"; } 499 | .fi-social-blogger:before { content: "\f1bb"; } 500 | .fi-social-delicious:before { content: "\f1bc"; } 501 | .fi-social-designer-news:before { content: "\f1bd"; } 502 | .fi-social-deviant-art:before { content: "\f1be"; } 503 | .fi-social-digg:before { content: "\f1bf"; } 504 | .fi-social-dribbble:before { content: "\f1c0"; } 505 | .fi-social-drive:before { content: "\f1c1"; } 506 | .fi-social-dropbox:before { content: "\f1c2"; } 507 | .fi-social-evernote:before { content: "\f1c3"; } 508 | .fi-social-facebook:before { content: "\f1c4"; } 509 | .fi-social-flickr:before { content: "\f1c5"; } 510 | .fi-social-forrst:before { content: "\f1c6"; } 511 | .fi-social-foursquare:before { content: "\f1c7"; } 512 | .fi-social-game-center:before { content: "\f1c8"; } 513 | .fi-social-github:before { content: "\f1c9"; } 514 | .fi-social-google-plus:before { content: "\f1ca"; } 515 | .fi-social-hacker-news:before { content: "\f1cb"; } 516 | .fi-social-hi5:before { content: "\f1cc"; } 517 | .fi-social-instagram:before { content: "\f1cd"; } 518 | .fi-social-joomla:before { content: "\f1ce"; } 519 | .fi-social-lastfm:before { content: "\f1cf"; } 520 | .fi-social-linkedin:before { content: "\f1d0"; } 521 | .fi-social-medium:before { content: "\f1d1"; } 522 | .fi-social-myspace:before { content: "\f1d2"; } 523 | .fi-social-orkut:before { content: "\f1d3"; } 524 | .fi-social-path:before { content: "\f1d4"; } 525 | .fi-social-picasa:before { content: "\f1d5"; } 526 | .fi-social-pinterest:before { content: "\f1d6"; } 527 | .fi-social-rdio:before { content: "\f1d7"; } 528 | .fi-social-reddit:before { content: "\f1d8"; } 529 | .fi-social-skillshare:before { content: "\f1d9"; } 530 | .fi-social-skype:before { content: "\f1da"; } 531 | .fi-social-smashing-mag:before { content: "\f1db"; } 532 | .fi-social-snapchat:before { content: "\f1dc"; } 533 | .fi-social-spotify:before { content: "\f1dd"; } 534 | .fi-social-squidoo:before { content: "\f1de"; } 535 | .fi-social-stack-overflow:before { content: "\f1df"; } 536 | .fi-social-steam:before { content: "\f1e0"; } 537 | .fi-social-stumbleupon:before { content: "\f1e1"; } 538 | .fi-social-treehouse:before { content: "\f1e2"; } 539 | .fi-social-tumblr:before { content: "\f1e3"; } 540 | .fi-social-twitter:before { content: "\f1e4"; } 541 | .fi-social-vimeo:before { content: "\f1e5"; } 542 | .fi-social-windows:before { content: "\f1e6"; } 543 | .fi-social-xbox:before { content: "\f1e7"; } 544 | .fi-social-yahoo:before { content: "\f1e8"; } 545 | .fi-social-yelp:before { content: "\f1e9"; } 546 | .fi-social-youtube:before { content: "\f1ea"; } 547 | .fi-social-zerply:before { content: "\f1eb"; } 548 | .fi-social-zurb:before { content: "\f1ec"; } 549 | .fi-sound:before { content: "\f1ed"; } 550 | .fi-star:before { content: "\f1ee"; } 551 | .fi-stop:before { content: "\f1ef"; } 552 | .fi-strikethrough:before { content: "\f1f0"; } 553 | .fi-subscript:before { content: "\f1f1"; } 554 | .fi-superscript:before { content: "\f1f2"; } 555 | .fi-tablet-landscape:before { content: "\f1f3"; } 556 | .fi-tablet-portrait:before { content: "\f1f4"; } 557 | .fi-target-two:before { content: "\f1f5"; } 558 | .fi-target:before { content: "\f1f6"; } 559 | .fi-telephone-accessible:before { content: "\f1f7"; } 560 | .fi-telephone:before { content: "\f1f8"; } 561 | .fi-text-color:before { content: "\f1f9"; } 562 | .fi-thumbnails:before { content: "\f1fa"; } 563 | .fi-ticket:before { content: "\f1fb"; } 564 | .fi-torso-business:before { content: "\f1fc"; } 565 | .fi-torso-female:before { content: "\f1fd"; } 566 | .fi-torso:before { content: "\f1fe"; } 567 | .fi-torsos-all-female:before { content: "\f1ff"; } 568 | .fi-torsos-all:before { content: "\f200"; } 569 | .fi-torsos-female-male:before { content: "\f201"; } 570 | .fi-torsos-male-female:before { content: "\f202"; } 571 | .fi-torsos:before { content: "\f203"; } 572 | .fi-trash:before { content: "\f204"; } 573 | .fi-trees:before { content: "\f205"; } 574 | .fi-trophy:before { content: "\f206"; } 575 | .fi-underline:before { content: "\f207"; } 576 | .fi-universal-access:before { content: "\f208"; } 577 | .fi-unlink:before { content: "\f209"; } 578 | .fi-unlock:before { content: "\f20a"; } 579 | .fi-upload-cloud:before { content: "\f20b"; } 580 | .fi-upload:before { content: "\f20c"; } 581 | .fi-usb:before { content: "\f20d"; } 582 | .fi-video:before { content: "\f20e"; } 583 | .fi-volume-none:before { content: "\f20f"; } 584 | .fi-volume-strike:before { content: "\f210"; } 585 | .fi-volume:before { content: "\f211"; } 586 | .fi-web:before { content: "\f212"; } 587 | .fi-wheelchair:before { content: "\f213"; } 588 | .fi-widget:before { content: "\f214"; } 589 | .fi-wrench:before { content: "\f215"; } 590 | .fi-x-circle:before { content: "\f216"; } 591 | .fi-x:before { content: "\f217"; } 592 | .fi-yen:before { content: "\f218"; } 593 | .fi-zoom-in:before { content: "\f219"; } 594 | .fi-zoom-out:before { content: "\f21a"; } 595 | -------------------------------------------------------------------------------- /pyprint/background/static/css/foundation-icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RicterZ/pyprint/de96f4e4684f35dafd57f521ba6acb55e80f990e/pyprint/background/static/css/foundation-icons.eot -------------------------------------------------------------------------------- /pyprint/background/static/css/foundation-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RicterZ/pyprint/de96f4e4684f35dafd57f521ba6acb55e80f990e/pyprint/background/static/css/foundation-icons.ttf -------------------------------------------------------------------------------- /pyprint/background/static/css/foundation-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RicterZ/pyprint/de96f4e4684f35dafd57f521ba6acb55e80f990e/pyprint/background/static/css/foundation-icons.woff -------------------------------------------------------------------------------- /pyprint/background/static/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #333; 3 | } 4 | 5 | header { 6 | background: #4CCA83; 7 | color: #FFF; 8 | border: none; 9 | } 10 | 11 | header > h1 { 12 | margin: 13px 10px; 13 | display: inline-block; 14 | font-size: 1.5em; 15 | } 16 | 17 | header > h2 { 18 | margin: 20px 10px; 19 | float: right; 20 | display: inline-block; 21 | } 22 | 23 | header > ul { 24 | position: absolute; 25 | margin: 0; 26 | padding: 0; 27 | width: 180px; 28 | list-style: none; 29 | background: #333; 30 | margin-top: 1px; 31 | border: none; 32 | } 33 | 34 | .navbar > ul > li { 35 | display: list-item; 36 | } 37 | 38 | .panel-container { 39 | box-shadow: #999 1px 1px 2px 1px inset; 40 | background: #EEE; 41 | padding: 20px; 42 | margin-left: 180px; 43 | margin-top: -20px; 44 | } 45 | 46 | .panel { 47 | border-radius: 0px; 48 | min-height: 500px; 49 | } 50 | 51 | .td-operate { 52 | text-align: center; 53 | } 54 | 55 | .td-operate > a { 56 | color: #333; 57 | } 58 | 59 | .td-title a { 60 | word-break: break-all; 61 | color: #666; 62 | } 63 | 64 | .td-title a:hover { 65 | text-decoration: blink; 66 | color: #35aadc; 67 | } 68 | 69 | .submenu { 70 | padding: 13px 0 13px 15px; 71 | text-decoration: blink; 72 | display: block; 73 | color: #FFF; 74 | font-weight: 600; 75 | } 76 | 77 | .selected-item { 78 | background-color: #35aadc; 79 | } 80 | 81 | .arrow::after { 82 | clear: both; 83 | position: absolute; 84 | right: 0px; 85 | content: " "; 86 | width:0; 87 | height:0; 88 | border-width:10px; 89 | border-style:solid dashed dashed dashed; 90 | border-color:transparent #FFF transparent transparent; 91 | -webkit-transition: margin 400ms; 92 | -moz-transition: margin 400ms; 93 | transition: margin 400ms; 94 | pointer-events: none; 95 | } 96 | 97 | .submenu { 98 | -webkit-transition: background 400ms; 99 | -moz-transition: background 400ms; 100 | transition: background 400ms; 101 | } 102 | 103 | .selected-item + .arrow::after { 104 | margin-top: -46px; 105 | } 106 | 107 | /*.selected-item +*/ 108 | .selected-item + a:hover::after{ 109 | margin-top: 0; 110 | } 111 | 112 | .submenu:hover { 113 | background-color: #e14d43; 114 | color: #FFF; 115 | text-decoration: blink; 116 | } 117 | 118 | .submenu:hover + .arrow::after { 119 | margin-top: -46px; 120 | pointer-events: none; 121 | } 122 | 123 | .panel-default > .panel-heading { 124 | background-image: none; 125 | background-color: #EEE; 126 | } 127 | 128 | footer { 129 | font-size: 1.2em; 130 | padding-top: 10px; 131 | text-align: center; 132 | color: #FFF; 133 | } 134 | 135 | .login-form { 136 | width: 50%; 137 | margin: 0 auto; 138 | text-align: center; 139 | padding: 20px; 140 | } 141 | 142 | footer a { 143 | color: #FFF; 144 | } 145 | 146 | footer a:hover { 147 | color: #FFF; 148 | } 149 | 150 | .none-style-button { 151 | background: transparent; 152 | border: none; 153 | } 154 | 155 | .alert { 156 | display: none; 157 | } 158 | 159 | .new-post-button { 160 | margin: -5px; 161 | } 162 | 163 | 164 | input, 165 | button, 166 | select, 167 | option, 168 | textarea { 169 | outline: none; 170 | } 171 | 172 | .post-title { 173 | width: 100%; 174 | font-size: 32px; 175 | padding: 4px 10px; 176 | border: 0; 177 | box-shadow: 0 -1px 4px #FFFFFA inset; 178 | -webkit-transition: box-shadow 400ms; 179 | -moz-transition: box-shadow 400ms; 180 | transition: box-shadow 400ms; 181 | color: #6E6868; 182 | background: #FFFFF9; 183 | } 184 | 185 | .post-title:focus { 186 | box-shadow: 0 -1px 12px #DEE inset; 187 | } 188 | 189 | .post-content { 190 | padding: 5px 10px; 191 | width: 100%; 192 | resize: none; 193 | border: none; 194 | height: 400px; 195 | box-shadow: 0 2px 3px #CCC inset; 196 | background: #FFFFF9; 197 | } 198 | 199 | .post-button { 200 | float: right; 201 | margin-top: -35px; 202 | margin-right: 15px; 203 | } 204 | 205 | @media screen and (max-width:980px){ 206 | .login-form { 207 | width: 100%; 208 | } 209 | 210 | .td-operate { 211 | display: none; 212 | } 213 | 214 | .td-title { 215 | width: 100%; 216 | } 217 | } -------------------------------------------------------------------------------- /pyprint/background/static/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RicterZ/pyprint/de96f4e4684f35dafd57f521ba6acb55e80f990e/pyprint/background/static/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /pyprint/background/static/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RicterZ/pyprint/de96f4e4684f35dafd57f521ba6acb55e80f990e/pyprint/background/static/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /pyprint/background/static/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RicterZ/pyprint/de96f4e4684f35dafd57f521ba6acb55e80f990e/pyprint/background/static/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /pyprint/background/templates/add_post.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block navbar %} 4 | Posts Mangement 5 | Friend Links 6 | {% endblock %} 7 | 8 | {% block body %} 9 | 10 |
11 |
12 | New Article 13 |
14 | 15 |
16 | 17 | 18 | 19 |
20 |
21 | {% endblock %} -------------------------------------------------------------------------------- /pyprint/background/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Background 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 24 | 25 |
26 | {% block body %} 27 | {% endblock %} 28 |
29 | 30 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /pyprint/background/templates/links.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block navbar %} 4 | Posts Mangement 5 | Friend Links 6 | {% endblock %} 7 | 8 | {% block body %} 9 |
10 | 11 | Failed! 12 |
13 |
14 | 15 | Success! 16 |
17 |
18 |
Friends Links 19 |
20 |
21 |
22 |
23 | 24 | 25 |
26 |
27 |
28 |
29 | http:// 30 | 31 |
32 |
33 | 34 |
35 |
36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | {% for link in links %} 47 | 48 | 49 | 50 | 51 | 52 | {% endfor %} 53 | 54 |
NameLinkDelete
{{ link.name }}http://{{ link.url }}
55 |
56 | 57 | {% endblock %} -------------------------------------------------------------------------------- /pyprint/background/templates/login.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block body %} 4 |
5 |
6 | Login 7 |
8 |
9 |
10 | 11 |
12 |
13 |
14 | 15 |
16 |
17 | 18 |
19 |
20 | {% endblock %} -------------------------------------------------------------------------------- /pyprint/background/templates/posts.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block navbar %} 4 | Posts Mangement 5 | Friend Links 6 | {% endblock %} 7 | 8 | {% block body %} 9 |
10 | 11 | Failed! 12 |
13 |
14 | 15 | Success! 16 |
17 |
18 |
PostsNew Article
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | {% for post in posts %} 29 | 30 | 31 | 32 | 33 | 34 | {% endfor %} 35 | 36 |
Aritlce TitleEditDelete
{{ post.title }}
37 | 42 |
43 | 63 | {% endblock %} -------------------------------------------------------------------------------- /pyprint/constants.py: -------------------------------------------------------------------------------- 1 | POST = 'post' 2 | DIARY = 'diary' 3 | 4 | POST_ENUMS = (POST, DIARY, ) -------------------------------------------------------------------------------- /pyprint/database.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy.ext.declarative import declarative_base 2 | from sqlalchemy.orm import scoped_session, sessionmaker 3 | from sqlalchemy import create_engine 4 | 5 | from settings import connect_str 6 | 7 | 8 | engine = create_engine(connect_str, echo=True, pool_recycle=3600) 9 | Base = declarative_base() 10 | db = scoped_session(sessionmaker(bind=engine)) 11 | -------------------------------------------------------------------------------- /pyprint/handler.py: -------------------------------------------------------------------------------- 1 | import tornado.web 2 | from jinja2 import Environment, FileSystemLoader, TemplateNotFound 3 | 4 | import database 5 | from utils import markdown, fix_lazy_load, markdown_image 6 | 7 | 8 | class JinjaEnvironment(object): 9 | _flag = None 10 | _jinja_env = None 11 | _background_env = None 12 | 13 | def __new__(cls, *args, **kwargs): 14 | if not 'path' in kwargs: 15 | raise Exception('Path of FileSystemLoader required') 16 | 17 | if not cls._jinja_env and not kwargs['is_background']: 18 | cls._jinja_env = Environment(loader=FileSystemLoader(kwargs['path'])) 19 | if not cls._background_env and kwargs['is_background']: 20 | cls._background_env = Environment(loader=FileSystemLoader(kwargs['path'])) 21 | 22 | return cls._jinja_env if not kwargs['is_background'] else cls._background_env 23 | 24 | 25 | class JinjaTemplateMixin(object): 26 | """A simple mixin of jinja2 27 | 28 | From: http://bibhas.in/blog/using-jinja2-as-the-template-engine-for-tornado-web-framework/ 29 | """ 30 | def _render(self, path, template_name, is_background=False, **kwargs): 31 | env = JinjaEnvironment(path=path, is_background=is_background) 32 | env.filters['markdown'] = markdown 33 | env.filters['markdown_image'] = markdown_image 34 | env.filters['fix_lazy_load'] = fix_lazy_load 35 | 36 | try: 37 | template = env.get_template(template_name) 38 | except TemplateNotFound: 39 | raise TemplateNotFound(template_name) 40 | return template.render(settings=self.settings, **kwargs) 41 | 42 | def _jinja2_render(self, template_name, **kwargs): 43 | return self._render(self.settings['template_path'], template_name, **kwargs) 44 | 45 | def _background_render(self, template_name, **kwargs): 46 | return self._render(self.settings['background_template_path'], template_name, 47 | is_background=True, **kwargs) 48 | 49 | 50 | class BaseHandler(tornado.web.RequestHandler, JinjaTemplateMixin): 51 | @property 52 | def orm(self): 53 | return database.db() 54 | 55 | def on_finish(self): 56 | database.db.remove() 57 | 58 | def render(self, template_name, headers=None, **kwargs): 59 | """Override render method 60 | """ 61 | if headers: 62 | for key, value in headers.iteritems(): 63 | self.set_header(key, value) 64 | 65 | self.set_header('X-Something', 'cHJwcnBycHJwcnBycHJwcnByLmxvbGkuY2x1Yg') 66 | self.set_header('X-Powered-by', 'PyPrint') 67 | self.write(self._jinja2_render(template_name, is_pjax=bool(self.request.headers.get('X-Pjax', None)), 68 | **kwargs)) 69 | self.finish() 70 | 71 | def background_render(self, template_name, **kwargs): 72 | self.write(self._background_render(template_name, **kwargs)) 73 | self.finish() 74 | 75 | def get_current_user(self): 76 | return self.get_secure_cookie('username') 77 | -------------------------------------------------------------------------------- /pyprint/localsettings.example.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | ROOT_DIR = os.path.abspath('.') 4 | connect_str = 'sqlite:///{path}'.format(path=os.path.join(ROOT_DIR, 'pyprint.db3')) 5 | cookie_secret = '3F8PhdGMSyuI5AjFM5Da8+/X2mP8XEzHtC/j57v3r6E=' 6 | 7 | username = 'admin' 8 | password = 'admin' -------------------------------------------------------------------------------- /pyprint/models.py: -------------------------------------------------------------------------------- 1 | from datetime import date 2 | from hashlib import md5 3 | 4 | from sqlalchemy import Column, Table 5 | from sqlalchemy import Text, String, Date, Integer, ForeignKey, Enum 6 | from sqlalchemy.orm import relationship 7 | 8 | from database import Base, engine 9 | from constants import POST_ENUMS, POST 10 | 11 | 12 | 13 | posts_tags = Table( 14 | 'posts_tags', Base.metadata, 15 | Column('post_id', Integer, ForeignKey('posts.id')), 16 | Column('tag_id', Integer, ForeignKey('tags.id')), 17 | ) 18 | 19 | 20 | class Tag(Base): 21 | __tablename__ = 'tags' 22 | 23 | id = Column(Integer, primary_key=True, autoincrement=True) 24 | slug = Column(String(50), unique=True, nullable=False) 25 | 26 | def __repr__(self): 27 | return '' % self.slug 28 | 29 | 30 | class Post(Base): 31 | __tablename__ = 'posts' 32 | 33 | id = Column(Integer, primary_key=True, autoincrement=True) 34 | title = Column(String(200), unique=True, nullable=False) 35 | tags = relationship('Tag', secondary=posts_tags, backref='posts') 36 | created_time = Column(Date, default=date.today()) 37 | content = Column(Text) 38 | type = Column(Enum(*POST_ENUMS), default=POST) 39 | password = Column(String(10), nullable=True) 40 | 41 | def __repr__(self): 42 | return '' % self.title 43 | 44 | 45 | class Link(Base): 46 | __tablename__ = 'links' 47 | 48 | id = Column(Integer, primary_key=True, autoincrement=True) 49 | name = Column(String(100)) 50 | url = Column(String(100)) 51 | 52 | def __repr__(self): 53 | return '' % self.url 54 | 55 | 56 | class User(Base): 57 | __tablename__ = 'users' 58 | 59 | id = Column(Integer, primary_key=True, autoincrement=True) 60 | username = Column(String(20)) 61 | password = Column(String(32)) 62 | 63 | def check(self, password): 64 | return self.password == md5(password).hexdigest() 65 | 66 | def __repr__(self): 67 | return '' % self.username 68 | 69 | 70 | metadata = Base.metadata 71 | 72 | if __name__ == "__main__": 73 | metadata.create_all(engine) 74 | -------------------------------------------------------------------------------- /pyprint/settings.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | # website settings 3 | username = 'Ricter' 4 | email = 'RicterZheng@gmail.com' 5 | title = 'Ricter\'s Blog' 6 | motto = u'初心を忘れず' 7 | disqus_shortname = 'ricterblog2' 8 | 9 | # themes name 10 | theme = 'mdl' 11 | 12 | # development 13 | debug = True 14 | 15 | 16 | analytics_code = ''' 17 | (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ 18 | (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), 19 | m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) 20 | })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); 21 | 22 | ga('create', 'UA-53662402-1', 'auto'); 23 | ga('send', 'pageview'); 24 | ''' 25 | 26 | post_of_page = 3 27 | 28 | 29 | try: 30 | from localsettings import connect_str, cookie_secret 31 | except ImportError: 32 | raise Exception('Please add connect_str and cookie_secret in localsettings.py') 33 | 34 | 35 | try: 36 | module = __import__('themes.%s.config' % theme, globals(), locals(), ['*']) 37 | for k in dir(module): 38 | locals()[k] = getattr(module, k) 39 | except ImportError: 40 | pass 41 | -------------------------------------------------------------------------------- /pyprint/themes/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RicterZ/pyprint/de96f4e4684f35dafd57f521ba6acb55e80f990e/pyprint/themes/__init__.py -------------------------------------------------------------------------------- /pyprint/themes/clean/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RicterZ/pyprint/de96f4e4684f35dafd57f521ba6acb55e80f990e/pyprint/themes/clean/__init__.py -------------------------------------------------------------------------------- /pyprint/themes/clean/config.py: -------------------------------------------------------------------------------- 1 | # Config file of theme 2 | 3 | post_of_page = 16 4 | -------------------------------------------------------------------------------- /pyprint/themes/clean/static/css/style.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | width: 800px; 3 | margin: 0 auto; 4 | } 5 | 6 | .container { 7 | margin: 0 auto; 8 | } 9 | 10 | .date { 11 | float: right; 12 | } 13 | 14 | input,button,select,textarea{outline:none} 15 | 16 | .name a { 17 | font-size: 48px; 18 | text-decoration: none; 19 | } 20 | 21 | aside { 22 | margin-bottom: 1.2em; 23 | } 24 | 25 | .post-title { 26 | font-size: 2.0em; 27 | } 28 | 29 | .post-title a { 30 | text-decoration: blink; 31 | } 32 | 33 | .center { 34 | display: block; 35 | margin: 0 auto; 36 | text-align: center; 37 | } 38 | 39 | nav.nav { 40 | padding-top: 0.67em; 41 | } 42 | 43 | header > nav > a { 44 | display: inline-block; 45 | padding: 0 12px 46 | } 47 | 48 | .article, .archives { 49 | padding-bottom: 30px; 50 | margin-bottom: 40px; 51 | border-bottom: 2px solid #EEE; 52 | } 53 | 54 | h1,h2,h3,h4,h5,h6 { 55 | font-weight: 100; 56 | } 57 | 58 | .paging { 59 | display: table; 60 | width: 100%; 61 | padding-bottom: 20px; 62 | } 63 | 64 | .next { 65 | float: right; 66 | text-decoration: none; 67 | } 68 | 69 | .prev { 70 | float: left; 71 | text-decoration: none; 72 | } 73 | 74 | 75 | .content { 76 | margin: 0 40px; 77 | } 78 | 79 | .archive { 80 | font-size: 24px; 81 | width: 100%; 82 | white-space: nowrap; 83 | text-overflow: ellipsis; 84 | overflow: hidden; 85 | display: inline-block; 86 | } 87 | 88 | .archive > span { 89 | margin-right: 30px; 90 | } 91 | 92 | .tags { 93 | color: gray; 94 | font-size: 0.9em; 95 | } 96 | 97 | a.tag { 98 | margin: 0 3px; 99 | color: gray; 100 | } 101 | 102 | a.publish { 103 | text-decoration: none; 104 | } 105 | 106 | .pull-right { 107 | float: right; 108 | } 109 | 110 | textarea.post { 111 | resize: vertical; 112 | display: inline-block; 113 | width: 100%; 114 | height: 400px; 115 | border: 3px solid #CCC; 116 | margin-left: -3px; 117 | font-size: 18px; 118 | margin-bottom: 30px; 119 | font-family: "Georgia", "Xin Gothic", "Hiragino Sans GB", "WenQuanYi Micro Hei", "Microsoft YaHei", "SimSun", sans-serif; 120 | } 121 | 122 | @media screen and (max-width: 600px) { 123 | .date { 124 | display: none; 125 | } 126 | 127 | .wrapper { 128 | width: 100%; 129 | } 130 | 131 | .content { 132 | margin: 0; 133 | } 134 | } 135 | 136 | @media screen and (max-width: 980px) { 137 | .wrapper { 138 | width: 100%; 139 | } 140 | 141 | .content { 142 | margin: 0; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /pyprint/themes/clean/static/css/yue.css: -------------------------------------------------------------------------------- 1 | /** 2 | * yue.css 3 | * 4 | * yue.css is designed for readable content. 5 | * 6 | * Copyright (c) 2013 by Hsiaoming Yang. 7 | */ 8 | 9 | 10 | 11 | .yue { 12 | font: 400 18px/1.62 "Georgia", "Xin Gothic", "Hiragino Sans GB", "WenQuanYi Micro Hei", sans-serif; 13 | color: #444443; 14 | } 15 | .yue ::selection { 16 | background-color: rgba(0,0,0,0.2); 17 | } 18 | .yue h1, 19 | .yue h2, 20 | .yue h3, 21 | .yue h4, 22 | .yue h5, 23 | .yue h6 { 24 | font-family: "Georgia", "Xin Gothic", "Hiragino Sans GB", "WenQuanYi Micro Hei", "Microsoft YaHei", "SimSun", sans-serif; 25 | color: #222223; 26 | } 27 | .yue h1 { 28 | font-size: 1.8em; 29 | margin: 0.67em 0; 30 | } 31 | .yue > h1 { 32 | margin-top: 0; 33 | font-size: 2em; 34 | } 35 | .yue h2 { 36 | font-size: 1.5em; 37 | margin: 0.83em 0; 38 | } 39 | .yue h3 { 40 | font-size: 1.17em; 41 | margin: 1em 0; 42 | } 43 | .yue h4, 44 | .yue h5, 45 | .yue h6 { 46 | font-size: 1em; 47 | margin: 1.6em 0 1em 0; 48 | } 49 | .yue h6 { 50 | font-weight: 500; 51 | } 52 | .yue p { 53 | margin-top: 0; 54 | margin-bottom: 1.64em; 55 | } 56 | .yue a { 57 | color: #111; 58 | word-wrap: break-word; 59 | } 60 | .yue a:hover { 61 | color: #555; 62 | } 63 | .yue strong, 64 | .yue b { 65 | font-weight: 700; 66 | color: #222; 67 | } 68 | .yue em, 69 | .yue i { 70 | font-style: italic; 71 | color: #222; 72 | } 73 | .yue img { 74 | max-width: 100%; 75 | height: auto; 76 | margin: 0.2em 0; 77 | } 78 | .yue a img { 79 | /* Remove border on IE */ 80 | border: none; 81 | } 82 | .yue figure { 83 | position: relative; 84 | clear: both; 85 | outline: 0; 86 | margin: 10px 0 30px; 87 | padding: 0; 88 | } 89 | .yue figure img { 90 | display: block; 91 | max-width: 100%; 92 | margin: auto; 93 | -webkit-box-sizing: border-box; 94 | -moz-box-sizing: border-box; 95 | box-sizing: border-box; 96 | } 97 | .yue figure figcaption { 98 | position: relative; 99 | width: 100%; 100 | text-align: center; 101 | left: 0; 102 | margin-top: 10px; 103 | font-weight: 400; 104 | font-size: 14px; 105 | color: #666665; 106 | } 107 | .yue figure figcaption a { 108 | text-decoration: none; 109 | color: #666665; 110 | } 111 | .yue hr { 112 | display: block; 113 | width: 14%; 114 | margin: 40px auto 34px; 115 | border: 0 none; 116 | border-top: 3px solid #dededc; 117 | } 118 | .yue blockquote { 119 | margin: 0 0 1.64em 0; 120 | border-left: 3px solid #dadada; 121 | padding-left: 12px; 122 | color: #666664; 123 | } 124 | .yue blockquote a { 125 | color: #666664; 126 | } 127 | .yue ul, 128 | .yue ol { 129 | margin: 0 0 24px 6px; 130 | padding-left: 16px; 131 | } 132 | .yue ul { 133 | list-style-type: square; 134 | } 135 | .yue ol { 136 | list-style-type: decimal; 137 | } 138 | .yue li { 139 | margin-bottom: 0.2em; 140 | } 141 | .yue li ul, 142 | .yue li ol { 143 | margin-top: 0; 144 | margin-bottom: 0; 145 | margin-left: 14px; 146 | } 147 | .yue li ul { 148 | list-style-type: disc; 149 | } 150 | .yue li ul ul { 151 | list-style-type: circle; 152 | } 153 | .yue li p { 154 | margin: 0.4em 0 0.6em; 155 | } 156 | .yue .unstyled { 157 | list-style-type: none; 158 | margin: 0; 159 | padding: 0; 160 | } 161 | .yue code, 162 | .yue tt { 163 | color: #808080; 164 | font-size: 0.96em; 165 | background-color: #f9f9f7; 166 | padding: 1px 2px; 167 | border: 1px solid #dadada; 168 | border-radius: 3px; 169 | font-family: "Inconsolata", "Menlo", monospace; 170 | } 171 | .yue pre { 172 | margin: 1.64em 0; 173 | padding: 7px; 174 | border: none; 175 | border-left: 3px solid #dadada; 176 | padding-left: 10px; 177 | overflow: auto; 178 | line-height: 1.5; 179 | font-size: 0.96em; 180 | font-family: "Inconsolata", "Menlo", monospace; 181 | color: #4c4c4c; 182 | background-color: #f9f9f7; 183 | } 184 | .yue pre code, 185 | .yue pre tt { 186 | color: #4c4c4c; 187 | border: none; 188 | background: none; 189 | padding: 0; 190 | } 191 | .yue table { 192 | width: 100%; 193 | border-collapse: collapse; 194 | border-spacing: 0; 195 | margin-bottom: 1.5em; 196 | font-size: 0.96em; 197 | } 198 | .yue th, 199 | .yue td { 200 | text-align: left; 201 | padding: 4px 8px 4px 10px; 202 | border: 1px solid #dadada; 203 | } 204 | .yue td { 205 | vertical-align: top; 206 | } 207 | .yue tr:nth-child(even) { 208 | background-color: #efefee; 209 | } 210 | .yue iframe { 211 | display: block; 212 | max-width: 100%; 213 | margin-bottom: 30px; 214 | } 215 | .yue figure iframe { 216 | margin: auto; 217 | } 218 | .yue table pre { 219 | margin: 0; 220 | padding: 0; 221 | border: none; 222 | background: none; 223 | } 224 | .yue .highlight td:first-of-type pre { 225 | text-align: right; 226 | color: #aaa; 227 | } 228 | @media (min-width: 1100px) { 229 | .yue blockquote { 230 | margin-left: -24px; 231 | padding-left: 20px; 232 | border-width: 4px; 233 | } 234 | .yue blockquote blockquote { 235 | margin-left: 0; 236 | } 237 | .yue figure figcaption:before { 238 | width: 25%; 239 | margin-left: 75%; 240 | border-top: 1px solid #dededc; 241 | display: block; 242 | content: ""; 243 | margin-bottom: 10px; 244 | } 245 | .yue figure figcaption { 246 | position: absolute; 247 | left: -172px; 248 | width: 150px; 249 | top: 0; 250 | text-align: right; 251 | margin-top: 0; 252 | } 253 | } 254 | -------------------------------------------------------------------------------- /pyprint/themes/clean/templates/diaries.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block body %} 4 |
    5 | {% for diary in diaries %} 6 |
  • 7 | {{ diary.title }} 8 | {{ diary.created_time }} 9 |
  • 10 | {% endfor %} 11 |
12 | {% endblock %} -------------------------------------------------------------------------------- /pyprint/themes/clean/templates/feed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ settings.username }} 4 | {{ settings.title }} 5 | {{ posts[0].created_time if posts }} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | http://{{ url }} 14 | 15 | {% for post in posts %} 16 | 17 | {{ post.title }} 18 | http://{{ url }}/articles/{{ post.title }} 19 | http://{{ url }}/articles/{{ post.title }} 20 | {{ post.created_time }} 21 | 22 | 23 | {% endfor %} 24 | -------------------------------------------------------------------------------- /pyprint/themes/clean/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block body %} 4 |
    5 | {% for post in data.posts %} 6 |
  • 7 | {{ post.title }} 8 | {{ post.created_time }} 9 |
  • 10 | {% endfor %} 11 |
12 |
13 |
14 | ‹‹ Newer 15 | Older ›› 16 |
17 | {% endblock %} -------------------------------------------------------------------------------- /pyprint/themes/clean/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{ title }} - {{ settings.title }} 9 | 10 | 11 | 12 |
13 |
14 |

{{ settings.username }}

15 | {{ settings.motto }} 16 | 22 |
23 |
24 |
25 | {% block body %} 26 | {% endblock %} 27 |
28 |
29 | {{ settings.username }} © 2015 • All rights reserved 30 |
31 | Theme Clean powered by whtsky & Ricter 32 |
33 |
34 | 37 | 38 | -------------------------------------------------------------------------------- /pyprint/themes/clean/templates/links.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | 4 | {% block body %} 5 |
6 |

About Me

7 |
8 |

9 | 咱是 Ricter,学院倒数前十常驻,生物专业,目前休学,坐标帝都
10 | 安全研究员/CTF 赛棍/Python 渣渣开发者/前端苦手
11 | 勾搭咱第一标准是头像要萌,反正咱没 cp

12 | 哪里能找到我呢=口=..
13 | Email: RicterZheng@gmail.com
14 | QQ: r@loli.club
15 | Github: https://github.com/RicterZ
16 | Twitter: @RicterZ
17 | Weibo: @Ricter(名字经常换

18 | 另外打个广告
19 | 一个叫做 ACG Hacker 的群,总之就是喜欢 ACG 的黑阔的样子,ACG 圈的可以随便加,Hacker 的话头像要萌
20 | 再次强调..加群头像不萌一定会被拒绝,另外太中二的男孩子不要,欢迎妹子>/////<
21 | 反正群主日下来 i-ab、acgzone、bilibili、C站之类的网站一堆(咱不是群主
22 | 群号:

23 |
00110101 00110111 00110011 00110010 00110100 00111000 00110011 00110101
24 | 00110100 01100100 00110100 01100001 00110101 00110111 00110111 00110110
25 | 00110101 01100001 00110111 00110111 00110101 00110111 00110111 00110111
26 | 00110100 00110001 00110100 00110111 00110111 00111001 00110111 01100001
27 | 00110101 01100001 00110101 00110001 00110111 00111000 00110110 01100100
28 | 00110100 01100011 00110100 00110111 00110101 00110111 00110111 01100001
29 | 00110100 00110001 00110100 01100001 00110100 00110100 00110011 00110001
30 | 00110101 01100001 00110101 00110001 00110100 00110001 00110111 00110101
31 | 00110101 01100001 00110101 00110100 00110100 00111000 00110011 00110100
32 | 00110100 00110001 00110110 01100100 00110100 01100011 00110110 01100100
33 | 00110100 00110010 00110101 00110100 00110100 00111001 00110111 00110111
34 | 00110101 00110111 00110011 00110001 00110110 00110110 00110011 00110110
35 | 00110100 00110010 00110111 00110110 00110011 00110000 00110110 01100010
36 | 00110100 01100010 00110100 00110100 00110011 01100100 00110011 01100100

37 |

能解的开吧反正不难(ry

38 |
39 | 40 |

My Friends

41 |
42 |
    43 | {% for link in links %} 44 |
  • {{ link.name }}
  • 45 | {% else %} 46 |

    I am alone ..

    47 | {% endfor %} 48 |
49 |
50 | 51 |
52 | 53 |
54 | 62 | {% endblock %} -------------------------------------------------------------------------------- /pyprint/themes/clean/templates/not_found.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block body %} 4 |

Baka ..

5 |
6 | {% endblock %} -------------------------------------------------------------------------------- /pyprint/themes/clean/templates/post.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | 4 | {% block body %} 5 |
6 | 10 | 11 |
12 | {{ post.content|markdown }} 13 |
14 | 24 |
25 |
26 |
27 |
28 |
29 | {% if post.type == 'post' %} 30 | 38 | {% endif %} 39 | {% endblock %} 40 | 41 | -------------------------------------------------------------------------------- /pyprint/themes/default/static/css/akarin.css: -------------------------------------------------------------------------------- 1 | article.not-found { 2 | text-align: center; 3 | } 4 | 5 | article.not-found > h3 { 6 | font-weight: 100; 7 | } 8 | 9 | article.not-found > img { 10 | width: 300px; 11 | margin: 0 auto; 12 | } -------------------------------------------------------------------------------- /pyprint/themes/default/static/css/archives.css: -------------------------------------------------------------------------------- 1 | ul.posts-group > li { 2 | display: block; 3 | } 4 | 5 | ul.posts-group > li > h2 { 6 | font-weight: 100; 7 | } -------------------------------------------------------------------------------- /pyprint/themes/default/static/css/foundation-icons.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Foundation Icons v 3.0 3 | * Made by ZURB 2013 http://zurb.com/playground/foundation-icon-fonts-3 4 | * MIT License 5 | */ 6 | 7 | @font-face { 8 | font-family: "foundation-icons"; 9 | src: url("foundation-icons.eot"); 10 | src: url("foundation-icons.eot?#iefix") format("embedded-opentype"), 11 | url("foundation-icons.woff") format("woff"), 12 | url("foundation-icons.ttf") format("truetype"), 13 | url("foundation-icons.svg#fontcustom") format("svg"); 14 | font-weight: normal; 15 | font-style: normal; 16 | } 17 | 18 | .fi-address-book:before, 19 | .fi-alert:before, 20 | .fi-align-center:before, 21 | .fi-align-justify:before, 22 | .fi-align-left:before, 23 | .fi-align-right:before, 24 | .fi-anchor:before, 25 | .fi-annotate:before, 26 | .fi-archive:before, 27 | .fi-arrow-down:before, 28 | .fi-arrow-left:before, 29 | .fi-arrow-right:before, 30 | .fi-arrow-up:before, 31 | .fi-arrows-compress:before, 32 | .fi-arrows-expand:before, 33 | .fi-arrows-in:before, 34 | .fi-arrows-out:before, 35 | .fi-asl:before, 36 | .fi-asterisk:before, 37 | .fi-at-sign:before, 38 | .fi-background-color:before, 39 | .fi-battery-empty:before, 40 | .fi-battery-full:before, 41 | .fi-battery-half:before, 42 | .fi-bitcoin-circle:before, 43 | .fi-bitcoin:before, 44 | .fi-blind:before, 45 | .fi-bluetooth:before, 46 | .fi-bold:before, 47 | .fi-book-bookmark:before, 48 | .fi-book:before, 49 | .fi-bookmark:before, 50 | .fi-braille:before, 51 | .fi-burst-new:before, 52 | .fi-burst-sale:before, 53 | .fi-burst:before, 54 | .fi-calendar:before, 55 | .fi-camera:before, 56 | .fi-check:before, 57 | .fi-checkbox:before, 58 | .fi-clipboard-notes:before, 59 | .fi-clipboard-pencil:before, 60 | .fi-clipboard:before, 61 | .fi-clock:before, 62 | .fi-closed-caption:before, 63 | .fi-cloud:before, 64 | .fi-comment-minus:before, 65 | .fi-comment-quotes:before, 66 | .fi-comment-video:before, 67 | .fi-comment:before, 68 | .fi-comments:before, 69 | .fi-compass:before, 70 | .fi-contrast:before, 71 | .fi-credit-card:before, 72 | .fi-crop:before, 73 | .fi-crown:before, 74 | .fi-css3:before, 75 | .fi-database:before, 76 | .fi-die-five:before, 77 | .fi-die-four:before, 78 | .fi-die-one:before, 79 | .fi-die-six:before, 80 | .fi-die-three:before, 81 | .fi-die-two:before, 82 | .fi-dislike:before, 83 | .fi-dollar-bill:before, 84 | .fi-dollar:before, 85 | .fi-download:before, 86 | .fi-eject:before, 87 | .fi-elevator:before, 88 | .fi-euro:before, 89 | .fi-eye:before, 90 | .fi-fast-forward:before, 91 | .fi-female-symbol:before, 92 | .fi-female:before, 93 | .fi-filter:before, 94 | .fi-first-aid:before, 95 | .fi-flag:before, 96 | .fi-folder-add:before, 97 | .fi-folder-lock:before, 98 | .fi-folder:before, 99 | .fi-foot:before, 100 | .fi-foundation:before, 101 | .fi-graph-bar:before, 102 | .fi-graph-horizontal:before, 103 | .fi-graph-pie:before, 104 | .fi-graph-trend:before, 105 | .fi-guide-dog:before, 106 | .fi-hearing-aid:before, 107 | .fi-heart:before, 108 | .fi-home:before, 109 | .fi-html5:before, 110 | .fi-indent-less:before, 111 | .fi-indent-more:before, 112 | .fi-info:before, 113 | .fi-italic:before, 114 | .fi-key:before, 115 | .fi-laptop:before, 116 | .fi-layout:before, 117 | .fi-lightbulb:before, 118 | .fi-like:before, 119 | .fi-link:before, 120 | .fi-list-bullet:before, 121 | .fi-list-number:before, 122 | .fi-list-thumbnails:before, 123 | .fi-list:before, 124 | .fi-lock:before, 125 | .fi-loop:before, 126 | .fi-magnifying-glass:before, 127 | .fi-mail:before, 128 | .fi-male-female:before, 129 | .fi-male-symbol:before, 130 | .fi-male:before, 131 | .fi-map:before, 132 | .fi-marker:before, 133 | .fi-megaphone:before, 134 | .fi-microphone:before, 135 | .fi-minus-circle:before, 136 | .fi-minus:before, 137 | .fi-mobile-signal:before, 138 | .fi-mobile:before, 139 | .fi-monitor:before, 140 | .fi-mountains:before, 141 | .fi-music:before, 142 | .fi-next:before, 143 | .fi-no-dogs:before, 144 | .fi-no-smoking:before, 145 | .fi-page-add:before, 146 | .fi-page-copy:before, 147 | .fi-page-csv:before, 148 | .fi-page-delete:before, 149 | .fi-page-doc:before, 150 | .fi-page-edit:before, 151 | .fi-page-export-csv:before, 152 | .fi-page-export-doc:before, 153 | .fi-page-export-pdf:before, 154 | .fi-page-export:before, 155 | .fi-page-filled:before, 156 | .fi-page-multiple:before, 157 | .fi-page-pdf:before, 158 | .fi-page-remove:before, 159 | .fi-page-search:before, 160 | .fi-page:before, 161 | .fi-paint-bucket:before, 162 | .fi-paperclip:before, 163 | .fi-pause:before, 164 | .fi-paw:before, 165 | .fi-paypal:before, 166 | .fi-pencil:before, 167 | .fi-photo:before, 168 | .fi-play-circle:before, 169 | .fi-play-video:before, 170 | .fi-play:before, 171 | .fi-plus:before, 172 | .fi-pound:before, 173 | .fi-power:before, 174 | .fi-previous:before, 175 | .fi-price-tag:before, 176 | .fi-pricetag-multiple:before, 177 | .fi-print:before, 178 | .fi-prohibited:before, 179 | .fi-projection-screen:before, 180 | .fi-puzzle:before, 181 | .fi-quote:before, 182 | .fi-record:before, 183 | .fi-refresh:before, 184 | .fi-results-demographics:before, 185 | .fi-results:before, 186 | .fi-rewind-ten:before, 187 | .fi-rewind:before, 188 | .fi-rss:before, 189 | .fi-safety-cone:before, 190 | .fi-save:before, 191 | .fi-share:before, 192 | .fi-sheriff-badge:before, 193 | .fi-shield:before, 194 | .fi-shopping-bag:before, 195 | .fi-shopping-cart:before, 196 | .fi-shuffle:before, 197 | .fi-skull:before, 198 | .fi-social-500px:before, 199 | .fi-social-adobe:before, 200 | .fi-social-amazon:before, 201 | .fi-social-android:before, 202 | .fi-social-apple:before, 203 | .fi-social-behance:before, 204 | .fi-social-bing:before, 205 | .fi-social-blogger:before, 206 | .fi-social-delicious:before, 207 | .fi-social-designer-news:before, 208 | .fi-social-deviant-art:before, 209 | .fi-social-digg:before, 210 | .fi-social-dribbble:before, 211 | .fi-social-drive:before, 212 | .fi-social-dropbox:before, 213 | .fi-social-evernote:before, 214 | .fi-social-facebook:before, 215 | .fi-social-flickr:before, 216 | .fi-social-forrst:before, 217 | .fi-social-foursquare:before, 218 | .fi-social-game-center:before, 219 | .fi-social-github:before, 220 | .fi-social-google-plus:before, 221 | .fi-social-hacker-news:before, 222 | .fi-social-hi5:before, 223 | .fi-social-instagram:before, 224 | .fi-social-joomla:before, 225 | .fi-social-lastfm:before, 226 | .fi-social-linkedin:before, 227 | .fi-social-medium:before, 228 | .fi-social-myspace:before, 229 | .fi-social-orkut:before, 230 | .fi-social-path:before, 231 | .fi-social-picasa:before, 232 | .fi-social-pinterest:before, 233 | .fi-social-rdio:before, 234 | .fi-social-reddit:before, 235 | .fi-social-skillshare:before, 236 | .fi-social-skype:before, 237 | .fi-social-smashing-mag:before, 238 | .fi-social-snapchat:before, 239 | .fi-social-spotify:before, 240 | .fi-social-squidoo:before, 241 | .fi-social-stack-overflow:before, 242 | .fi-social-steam:before, 243 | .fi-social-stumbleupon:before, 244 | .fi-social-treehouse:before, 245 | .fi-social-tumblr:before, 246 | .fi-social-twitter:before, 247 | .fi-social-vimeo:before, 248 | .fi-social-windows:before, 249 | .fi-social-xbox:before, 250 | .fi-social-yahoo:before, 251 | .fi-social-yelp:before, 252 | .fi-social-youtube:before, 253 | .fi-social-zerply:before, 254 | .fi-social-zurb:before, 255 | .fi-sound:before, 256 | .fi-star:before, 257 | .fi-stop:before, 258 | .fi-strikethrough:before, 259 | .fi-subscript:before, 260 | .fi-superscript:before, 261 | .fi-tablet-landscape:before, 262 | .fi-tablet-portrait:before, 263 | .fi-target-two:before, 264 | .fi-target:before, 265 | .fi-telephone-accessible:before, 266 | .fi-telephone:before, 267 | .fi-text-color:before, 268 | .fi-thumbnails:before, 269 | .fi-ticket:before, 270 | .fi-torso-business:before, 271 | .fi-torso-female:before, 272 | .fi-torso:before, 273 | .fi-torsos-all-female:before, 274 | .fi-torsos-all:before, 275 | .fi-torsos-female-male:before, 276 | .fi-torsos-male-female:before, 277 | .fi-torsos:before, 278 | .fi-trash:before, 279 | .fi-trees:before, 280 | .fi-trophy:before, 281 | .fi-underline:before, 282 | .fi-universal-access:before, 283 | .fi-unlink:before, 284 | .fi-unlock:before, 285 | .fi-upload-cloud:before, 286 | .fi-upload:before, 287 | .fi-usb:before, 288 | .fi-video:before, 289 | .fi-volume-none:before, 290 | .fi-volume-strike:before, 291 | .fi-volume:before, 292 | .fi-web:before, 293 | .fi-wheelchair:before, 294 | .fi-widget:before, 295 | .fi-wrench:before, 296 | .fi-x-circle:before, 297 | .fi-x:before, 298 | .fi-yen:before, 299 | .fi-zoom-in:before, 300 | .fi-zoom-out:before { 301 | font-family: "foundation-icons"; 302 | font-style: normal; 303 | font-weight: normal; 304 | font-variant: normal; 305 | text-transform: none; 306 | line-height: 1; 307 | -webkit-font-smoothing: antialiased; 308 | display: inline-block; 309 | text-decoration: inherit; 310 | } 311 | 312 | .fi-address-book:before { content: "\f100"; } 313 | .fi-alert:before { content: "\f101"; } 314 | .fi-align-center:before { content: "\f102"; } 315 | .fi-align-justify:before { content: "\f103"; } 316 | .fi-align-left:before { content: "\f104"; } 317 | .fi-align-right:before { content: "\f105"; } 318 | .fi-anchor:before { content: "\f106"; } 319 | .fi-annotate:before { content: "\f107"; } 320 | .fi-archive:before { content: "\f108"; } 321 | .fi-arrow-down:before { content: "\f109"; } 322 | .fi-arrow-left:before { content: "\f10a"; } 323 | .fi-arrow-right:before { content: "\f10b"; } 324 | .fi-arrow-up:before { content: "\f10c"; } 325 | .fi-arrows-compress:before { content: "\f10d"; } 326 | .fi-arrows-expand:before { content: "\f10e"; } 327 | .fi-arrows-in:before { content: "\f10f"; } 328 | .fi-arrows-out:before { content: "\f110"; } 329 | .fi-asl:before { content: "\f111"; } 330 | .fi-asterisk:before { content: "\f112"; } 331 | .fi-at-sign:before { content: "\f113"; } 332 | .fi-background-color:before { content: "\f114"; } 333 | .fi-battery-empty:before { content: "\f115"; } 334 | .fi-battery-full:before { content: "\f116"; } 335 | .fi-battery-half:before { content: "\f117"; } 336 | .fi-bitcoin-circle:before { content: "\f118"; } 337 | .fi-bitcoin:before { content: "\f119"; } 338 | .fi-blind:before { content: "\f11a"; } 339 | .fi-bluetooth:before { content: "\f11b"; } 340 | .fi-bold:before { content: "\f11c"; } 341 | .fi-book-bookmark:before { content: "\f11d"; } 342 | .fi-book:before { content: "\f11e"; } 343 | .fi-bookmark:before { content: "\f11f"; } 344 | .fi-braille:before { content: "\f120"; } 345 | .fi-burst-new:before { content: "\f121"; } 346 | .fi-burst-sale:before { content: "\f122"; } 347 | .fi-burst:before { content: "\f123"; } 348 | .fi-calendar:before { content: "\f124"; } 349 | .fi-camera:before { content: "\f125"; } 350 | .fi-check:before { content: "\f126"; } 351 | .fi-checkbox:before { content: "\f127"; } 352 | .fi-clipboard-notes:before { content: "\f128"; } 353 | .fi-clipboard-pencil:before { content: "\f129"; } 354 | .fi-clipboard:before { content: "\f12a"; } 355 | .fi-clock:before { content: "\f12b"; } 356 | .fi-closed-caption:before { content: "\f12c"; } 357 | .fi-cloud:before { content: "\f12d"; } 358 | .fi-comment-minus:before { content: "\f12e"; } 359 | .fi-comment-quotes:before { content: "\f12f"; } 360 | .fi-comment-video:before { content: "\f130"; } 361 | .fi-comment:before { content: "\f131"; } 362 | .fi-comments:before { content: "\f132"; } 363 | .fi-compass:before { content: "\f133"; } 364 | .fi-contrast:before { content: "\f134"; } 365 | .fi-credit-card:before { content: "\f135"; } 366 | .fi-crop:before { content: "\f136"; } 367 | .fi-crown:before { content: "\f137"; } 368 | .fi-css3:before { content: "\f138"; } 369 | .fi-database:before { content: "\f139"; } 370 | .fi-die-five:before { content: "\f13a"; } 371 | .fi-die-four:before { content: "\f13b"; } 372 | .fi-die-one:before { content: "\f13c"; } 373 | .fi-die-six:before { content: "\f13d"; } 374 | .fi-die-three:before { content: "\f13e"; } 375 | .fi-die-two:before { content: "\f13f"; } 376 | .fi-dislike:before { content: "\f140"; } 377 | .fi-dollar-bill:before { content: "\f141"; } 378 | .fi-dollar:before { content: "\f142"; } 379 | .fi-download:before { content: "\f143"; } 380 | .fi-eject:before { content: "\f144"; } 381 | .fi-elevator:before { content: "\f145"; } 382 | .fi-euro:before { content: "\f146"; } 383 | .fi-eye:before { content: "\f147"; } 384 | .fi-fast-forward:before { content: "\f148"; } 385 | .fi-female-symbol:before { content: "\f149"; } 386 | .fi-female:before { content: "\f14a"; } 387 | .fi-filter:before { content: "\f14b"; } 388 | .fi-first-aid:before { content: "\f14c"; } 389 | .fi-flag:before { content: "\f14d"; } 390 | .fi-folder-add:before { content: "\f14e"; } 391 | .fi-folder-lock:before { content: "\f14f"; } 392 | .fi-folder:before { content: "\f150"; } 393 | .fi-foot:before { content: "\f151"; } 394 | .fi-foundation:before { content: "\f152"; } 395 | .fi-graph-bar:before { content: "\f153"; } 396 | .fi-graph-horizontal:before { content: "\f154"; } 397 | .fi-graph-pie:before { content: "\f155"; } 398 | .fi-graph-trend:before { content: "\f156"; } 399 | .fi-guide-dog:before { content: "\f157"; } 400 | .fi-hearing-aid:before { content: "\f158"; } 401 | .fi-heart:before { content: "\f159"; } 402 | .fi-home:before { content: "\f15a"; } 403 | .fi-html5:before { content: "\f15b"; } 404 | .fi-indent-less:before { content: "\f15c"; } 405 | .fi-indent-more:before { content: "\f15d"; } 406 | .fi-info:before { content: "\f15e"; } 407 | .fi-italic:before { content: "\f15f"; } 408 | .fi-key:before { content: "\f160"; } 409 | .fi-laptop:before { content: "\f161"; } 410 | .fi-layout:before { content: "\f162"; } 411 | .fi-lightbulb:before { content: "\f163"; } 412 | .fi-like:before { content: "\f164"; } 413 | .fi-link:before { content: "\f165"; } 414 | .fi-list-bullet:before { content: "\f166"; } 415 | .fi-list-number:before { content: "\f167"; } 416 | .fi-list-thumbnails:before { content: "\f168"; } 417 | .fi-list:before { content: "\f169"; } 418 | .fi-lock:before { content: "\f16a"; } 419 | .fi-loop:before { content: "\f16b"; } 420 | .fi-magnifying-glass:before { content: "\f16c"; } 421 | .fi-mail:before { content: "\f16d"; } 422 | .fi-male-female:before { content: "\f16e"; } 423 | .fi-male-symbol:before { content: "\f16f"; } 424 | .fi-male:before { content: "\f170"; } 425 | .fi-map:before { content: "\f171"; } 426 | .fi-marker:before { content: "\f172"; } 427 | .fi-megaphone:before { content: "\f173"; } 428 | .fi-microphone:before { content: "\f174"; } 429 | .fi-minus-circle:before { content: "\f175"; } 430 | .fi-minus:before { content: "\f176"; } 431 | .fi-mobile-signal:before { content: "\f177"; } 432 | .fi-mobile:before { content: "\f178"; } 433 | .fi-monitor:before { content: "\f179"; } 434 | .fi-mountains:before { content: "\f17a"; } 435 | .fi-music:before { content: "\f17b"; } 436 | .fi-next:before { content: "\f17c"; } 437 | .fi-no-dogs:before { content: "\f17d"; } 438 | .fi-no-smoking:before { content: "\f17e"; } 439 | .fi-page-add:before { content: "\f17f"; } 440 | .fi-page-copy:before { content: "\f180"; } 441 | .fi-page-csv:before { content: "\f181"; } 442 | .fi-page-delete:before { content: "\f182"; } 443 | .fi-page-doc:before { content: "\f183"; } 444 | .fi-page-edit:before { content: "\f184"; } 445 | .fi-page-export-csv:before { content: "\f185"; } 446 | .fi-page-export-doc:before { content: "\f186"; } 447 | .fi-page-export-pdf:before { content: "\f187"; } 448 | .fi-page-export:before { content: "\f188"; } 449 | .fi-page-filled:before { content: "\f189"; } 450 | .fi-page-multiple:before { content: "\f18a"; } 451 | .fi-page-pdf:before { content: "\f18b"; } 452 | .fi-page-remove:before { content: "\f18c"; } 453 | .fi-page-search:before { content: "\f18d"; } 454 | .fi-page:before { content: "\f18e"; } 455 | .fi-paint-bucket:before { content: "\f18f"; } 456 | .fi-paperclip:before { content: "\f190"; } 457 | .fi-pause:before { content: "\f191"; } 458 | .fi-paw:before { content: "\f192"; } 459 | .fi-paypal:before { content: "\f193"; } 460 | .fi-pencil:before { content: "\f194"; } 461 | .fi-photo:before { content: "\f195"; } 462 | .fi-play-circle:before { content: "\f196"; } 463 | .fi-play-video:before { content: "\f197"; } 464 | .fi-play:before { content: "\f198"; } 465 | .fi-plus:before { content: "\f199"; } 466 | .fi-pound:before { content: "\f19a"; } 467 | .fi-power:before { content: "\f19b"; } 468 | .fi-previous:before { content: "\f19c"; } 469 | .fi-price-tag:before { content: "\f19d"; } 470 | .fi-pricetag-multiple:before { content: "\f19e"; } 471 | .fi-print:before { content: "\f19f"; } 472 | .fi-prohibited:before { content: "\f1a0"; } 473 | .fi-projection-screen:before { content: "\f1a1"; } 474 | .fi-puzzle:before { content: "\f1a2"; } 475 | .fi-quote:before { content: "\f1a3"; } 476 | .fi-record:before { content: "\f1a4"; } 477 | .fi-refresh:before { content: "\f1a5"; } 478 | .fi-results-demographics:before { content: "\f1a6"; } 479 | .fi-results:before { content: "\f1a7"; } 480 | .fi-rewind-ten:before { content: "\f1a8"; } 481 | .fi-rewind:before { content: "\f1a9"; } 482 | .fi-rss:before { content: "\f1aa"; } 483 | .fi-safety-cone:before { content: "\f1ab"; } 484 | .fi-save:before { content: "\f1ac"; } 485 | .fi-share:before { content: "\f1ad"; } 486 | .fi-sheriff-badge:before { content: "\f1ae"; } 487 | .fi-shield:before { content: "\f1af"; } 488 | .fi-shopping-bag:before { content: "\f1b0"; } 489 | .fi-shopping-cart:before { content: "\f1b1"; } 490 | .fi-shuffle:before { content: "\f1b2"; } 491 | .fi-skull:before { content: "\f1b3"; } 492 | .fi-social-500px:before { content: "\f1b4"; } 493 | .fi-social-adobe:before { content: "\f1b5"; } 494 | .fi-social-amazon:before { content: "\f1b6"; } 495 | .fi-social-android:before { content: "\f1b7"; } 496 | .fi-social-apple:before { content: "\f1b8"; } 497 | .fi-social-behance:before { content: "\f1b9"; } 498 | .fi-social-bing:before { content: "\f1ba"; } 499 | .fi-social-blogger:before { content: "\f1bb"; } 500 | .fi-social-delicious:before { content: "\f1bc"; } 501 | .fi-social-designer-news:before { content: "\f1bd"; } 502 | .fi-social-deviant-art:before { content: "\f1be"; } 503 | .fi-social-digg:before { content: "\f1bf"; } 504 | .fi-social-dribbble:before { content: "\f1c0"; } 505 | .fi-social-drive:before { content: "\f1c1"; } 506 | .fi-social-dropbox:before { content: "\f1c2"; } 507 | .fi-social-evernote:before { content: "\f1c3"; } 508 | .fi-social-facebook:before { content: "\f1c4"; } 509 | .fi-social-flickr:before { content: "\f1c5"; } 510 | .fi-social-forrst:before { content: "\f1c6"; } 511 | .fi-social-foursquare:before { content: "\f1c7"; } 512 | .fi-social-game-center:before { content: "\f1c8"; } 513 | .fi-social-github:before { content: "\f1c9"; } 514 | .fi-social-google-plus:before { content: "\f1ca"; } 515 | .fi-social-hacker-news:before { content: "\f1cb"; } 516 | .fi-social-hi5:before { content: "\f1cc"; } 517 | .fi-social-instagram:before { content: "\f1cd"; } 518 | .fi-social-joomla:before { content: "\f1ce"; } 519 | .fi-social-lastfm:before { content: "\f1cf"; } 520 | .fi-social-linkedin:before { content: "\f1d0"; } 521 | .fi-social-medium:before { content: "\f1d1"; } 522 | .fi-social-myspace:before { content: "\f1d2"; } 523 | .fi-social-orkut:before { content: "\f1d3"; } 524 | .fi-social-path:before { content: "\f1d4"; } 525 | .fi-social-picasa:before { content: "\f1d5"; } 526 | .fi-social-pinterest:before { content: "\f1d6"; } 527 | .fi-social-rdio:before { content: "\f1d7"; } 528 | .fi-social-reddit:before { content: "\f1d8"; } 529 | .fi-social-skillshare:before { content: "\f1d9"; } 530 | .fi-social-skype:before { content: "\f1da"; } 531 | .fi-social-smashing-mag:before { content: "\f1db"; } 532 | .fi-social-snapchat:before { content: "\f1dc"; } 533 | .fi-social-spotify:before { content: "\f1dd"; } 534 | .fi-social-squidoo:before { content: "\f1de"; } 535 | .fi-social-stack-overflow:before { content: "\f1df"; } 536 | .fi-social-steam:before { content: "\f1e0"; } 537 | .fi-social-stumbleupon:before { content: "\f1e1"; } 538 | .fi-social-treehouse:before { content: "\f1e2"; } 539 | .fi-social-tumblr:before { content: "\f1e3"; } 540 | .fi-social-twitter:before { content: "\f1e4"; } 541 | .fi-social-vimeo:before { content: "\f1e5"; } 542 | .fi-social-windows:before { content: "\f1e6"; } 543 | .fi-social-xbox:before { content: "\f1e7"; } 544 | .fi-social-yahoo:before { content: "\f1e8"; } 545 | .fi-social-yelp:before { content: "\f1e9"; } 546 | .fi-social-youtube:before { content: "\f1ea"; } 547 | .fi-social-zerply:before { content: "\f1eb"; } 548 | .fi-social-zurb:before { content: "\f1ec"; } 549 | .fi-sound:before { content: "\f1ed"; } 550 | .fi-star:before { content: "\f1ee"; } 551 | .fi-stop:before { content: "\f1ef"; } 552 | .fi-strikethrough:before { content: "\f1f0"; } 553 | .fi-subscript:before { content: "\f1f1"; } 554 | .fi-superscript:before { content: "\f1f2"; } 555 | .fi-tablet-landscape:before { content: "\f1f3"; } 556 | .fi-tablet-portrait:before { content: "\f1f4"; } 557 | .fi-target-two:before { content: "\f1f5"; } 558 | .fi-target:before { content: "\f1f6"; } 559 | .fi-telephone-accessible:before { content: "\f1f7"; } 560 | .fi-telephone:before { content: "\f1f8"; } 561 | .fi-text-color:before { content: "\f1f9"; } 562 | .fi-thumbnails:before { content: "\f1fa"; } 563 | .fi-ticket:before { content: "\f1fb"; } 564 | .fi-torso-business:before { content: "\f1fc"; } 565 | .fi-torso-female:before { content: "\f1fd"; } 566 | .fi-torso:before { content: "\f1fe"; } 567 | .fi-torsos-all-female:before { content: "\f1ff"; } 568 | .fi-torsos-all:before { content: "\f200"; } 569 | .fi-torsos-female-male:before { content: "\f201"; } 570 | .fi-torsos-male-female:before { content: "\f202"; } 571 | .fi-torsos:before { content: "\f203"; } 572 | .fi-trash:before { content: "\f204"; } 573 | .fi-trees:before { content: "\f205"; } 574 | .fi-trophy:before { content: "\f206"; } 575 | .fi-underline:before { content: "\f207"; } 576 | .fi-universal-access:before { content: "\f208"; } 577 | .fi-unlink:before { content: "\f209"; } 578 | .fi-unlock:before { content: "\f20a"; } 579 | .fi-upload-cloud:before { content: "\f20b"; } 580 | .fi-upload:before { content: "\f20c"; } 581 | .fi-usb:before { content: "\f20d"; } 582 | .fi-video:before { content: "\f20e"; } 583 | .fi-volume-none:before { content: "\f20f"; } 584 | .fi-volume-strike:before { content: "\f210"; } 585 | .fi-volume:before { content: "\f211"; } 586 | .fi-web:before { content: "\f212"; } 587 | .fi-wheelchair:before { content: "\f213"; } 588 | .fi-widget:before { content: "\f214"; } 589 | .fi-wrench:before { content: "\f215"; } 590 | .fi-x-circle:before { content: "\f216"; } 591 | .fi-x:before { content: "\f217"; } 592 | .fi-yen:before { content: "\f218"; } 593 | .fi-zoom-in:before { content: "\f219"; } 594 | .fi-zoom-out:before { content: "\f21a"; } 595 | -------------------------------------------------------------------------------- /pyprint/themes/default/static/css/foundation-icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RicterZ/pyprint/de96f4e4684f35dafd57f521ba6acb55e80f990e/pyprint/themes/default/static/css/foundation-icons.eot -------------------------------------------------------------------------------- /pyprint/themes/default/static/css/foundation-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RicterZ/pyprint/de96f4e4684f35dafd57f521ba6acb55e80f990e/pyprint/themes/default/static/css/foundation-icons.ttf -------------------------------------------------------------------------------- /pyprint/themes/default/static/css/foundation-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RicterZ/pyprint/de96f4e4684f35dafd57f521ba6acb55e80f990e/pyprint/themes/default/static/css/foundation-icons.woff -------------------------------------------------------------------------------- /pyprint/themes/default/static/css/layout.css: -------------------------------------------------------------------------------- 1 | * { 2 | padding: 0; 3 | margin: 0; 4 | } 5 | 6 | header{ 7 | width:100%; 8 | padding:50px 0 20px; 9 | background-size:cover; 10 | background-image:linear-gradient(to top,rgba(0,0,0,0.8) 0,rgba(0,0,0,0.0001) 100%),url(/static/imgs/banner.jpg); 11 | box-shadow:0 6px 10px #666;margin-bottom:60px; 12 | } 13 | 14 | .avatar { 15 | box-shadow: 0 0 10px #000; 16 | width: 150px; 17 | height: 150px; 18 | margin: 20px auto; 19 | overflow: hidden; 20 | border: 4px solid #FFF; 21 | border-radius: 100%; 22 | background: #FFF; 23 | -webkit-transition: -webkit-transform 400ms; 24 | -moz-transition: -moz-transform 400ms; 25 | transition: transform 400ms; 26 | } 27 | .avatar:hover { 28 | -webkit-transform:rotate(30deg); 29 | -moz-transform:rotate(30deg); 30 | transform:rotate(30deg); 31 | } 32 | .avatar img{ 33 | height: 100%; 34 | margin: 0; 35 | } 36 | 37 | header > .title { 38 | text-align: center; 39 | } 40 | 41 | .title h1, .title a, .title address, .nav li, .nav a { 42 | color: #CCC; 43 | text-decoration: none; 44 | } 45 | 46 | header > .title > h1 { 47 | margin: 0; 48 | padding: 0; 49 | font-size: 1.4em; 50 | font-weight: 100; 51 | } 52 | 53 | ul.nav { 54 | text-align: center; 55 | padding: 0; 56 | margin: 0; 57 | } 58 | 59 | .nav li { 60 | display: inline-block; 61 | padding: 0 10px; 62 | } 63 | 64 | .nav li > a:hover { 65 | color: #EEE; 66 | } 67 | 68 | footer{ 69 | bottom:0; 70 | position:relative; 71 | border-top:#D1DADF 1px solid; 72 | background:#F1F1F1; 73 | padding:36px; 74 | margin-top:60px; 75 | text-align:center; 76 | } 77 | 78 | footer *{ 79 | color:#BBC7CC; 80 | font-weight:100; 81 | text-decoration: none; 82 | } 83 | 84 | footer .rss{ 85 | color: #666; 86 | font-size:23px; 87 | position:absolute; 88 | padding: 1px; 89 | top:-15px; 90 | left:50%; 91 | margin-left:-15px; 92 | display:block; 93 | width:25px; 94 | height:25px; 95 | border-radius:100%; 96 | background:#FFF; 97 | border:1px solid #D1DADF; 98 | line-height: 10px; 99 | -webkit-transition:box-shadow 400ms; 100 | -moz-transition:box-shadow 400ms; 101 | transition:box-shadow 400ms; 102 | } 103 | 104 | p.footer { 105 | margin-bottom: 0; 106 | } 107 | 108 | footer .rss:hover{ 109 | box-shadow:0 0 12px #D1DADF; 110 | } 111 | 112 | footer .friends{ 113 | font-size:smaller; 114 | } 115 | 116 | .hide { 117 | visibility: hidden; 118 | } 119 | 120 | .wrapper { 121 | width:60%; 122 | max-width:980px; 123 | margin:0 auto; 124 | } 125 | 126 | .pull-right { 127 | float: right; 128 | } 129 | 130 | @media screen and (max-width:980px){ 131 | .wrapper {width:96%;} 132 | } 133 | -------------------------------------------------------------------------------- /pyprint/themes/default/static/css/links.css: -------------------------------------------------------------------------------- 1 | p.about-me { 2 | padding: 0 16px; 3 | } -------------------------------------------------------------------------------- /pyprint/themes/default/static/css/nprogress.css: -------------------------------------------------------------------------------- 1 | /* Make clicks pass-through */ 2 | #nprogress { 3 | pointer-events: none; 4 | } 5 | 6 | #nprogress .bar { 7 | background: #29d; 8 | 9 | position: fixed; 10 | z-index: 1031; 11 | top: 0; 12 | left: 0; 13 | 14 | width: 100%; 15 | height: 4px; 16 | } 17 | 18 | /* Fancy blur effect */ 19 | #nprogress .peg { 20 | display: block; 21 | position: absolute; 22 | right: 0px; 23 | width: 100px; 24 | height: 100%; 25 | box-shadow: 0 0 20px #29d, 0 0 5px #29d; 26 | opacity: 1.0; 27 | 28 | -webkit-transform: rotate(3deg) translate(0px, -4px); 29 | -ms-transform: rotate(3deg) translate(0px, -4px); 30 | transform: rotate(3deg) translate(0px, -4px); 31 | } 32 | 33 | /* Remove these to get rid of the spinner */ 34 | 35 | /* 36 | #nprogress .spinner { 37 | display: block; 38 | position: fixed; 39 | z-index: 1031; 40 | top: 15px; 41 | right: 15px; 42 | } 43 | 44 | #nprogress .spinner-icon { 45 | width: 18px; 46 | height: 18px; 47 | box-sizing: border-box; 48 | 49 | border: solid 2px transparent; 50 | border-top-color: #29d; 51 | border-left-color: #29d; 52 | border-radius: 50%; 53 | 54 | -webkit-animation: nprogress-spinner 400ms linear infinite; 55 | animation: nprogress-spinner 400ms linear infinite; 56 | } 57 | */ 58 | .nprogress-custom-parent { 59 | overflow: hidden; 60 | position: relative; 61 | } 62 | 63 | .nprogress-custom-parent #nprogress .spinner, 64 | .nprogress-custom-parent #nprogress .bar { 65 | position: absolute; 66 | } 67 | 68 | @-webkit-keyframes nprogress-spinner { 69 | 0% { -webkit-transform: rotate(0deg); } 70 | 100% { -webkit-transform: rotate(360deg); } 71 | } 72 | @keyframes nprogress-spinner { 73 | 0% { transform: rotate(0deg); } 74 | 100% { transform: rotate(360deg); } 75 | } 76 | 77 | -------------------------------------------------------------------------------- /pyprint/themes/default/static/css/post.css: -------------------------------------------------------------------------------- 1 | .wrapper > article { 2 | padding-bottom: 60px; 3 | } 4 | 5 | 6 | .wrapper > article > h1.title { 7 | text-align: center; 8 | font-weight: 100; 9 | font-size: 2.4em; 10 | } 11 | 12 | .wrapper > article > h1.title > a { 13 | color: #333; 14 | } 15 | 16 | .wrapper > article > h1.title > a:hover { 17 | color: #999; 18 | } 19 | 20 | .wrapper > article > aside { 21 | text-align: center; 22 | } 23 | 24 | .post-comments { 25 | margin-top: 30px; 26 | } 27 | 28 | .post-tags { 29 | margin-top: 20px; 30 | } 31 | 32 | .post-tags > em { 33 | color: #666; 34 | } -------------------------------------------------------------------------------- /pyprint/themes/default/static/css/yue.css: -------------------------------------------------------------------------------- 1 | /** 2 | * yue.css 3 | * 4 | * yue.css is designed for readable content. 5 | * 6 | * Copyright (c) 2013 by Hsiaoming Yang. 7 | */ 8 | 9 | 10 | 11 | .yue { 12 | font: 400 18px/1.62 "Georgia", "Xin Gothic", "Hiragino Sans GB", "WenQuanYi Micro Hei", sans-serif; 13 | color: #444443; 14 | } 15 | .yue ::selection { 16 | background-color: rgba(0,0,0,0.2); 17 | } 18 | .yue h1, 19 | .yue h2, 20 | .yue h3, 21 | .yue h4, 22 | .yue h5, 23 | .yue h6 { 24 | font-family: "Georgia", "Xin Gothic", "Hiragino Sans GB", "WenQuanYi Micro Hei", "Microsoft YaHei", "SimSun", sans-serif; 25 | color: #222223; 26 | } 27 | .yue h1 { 28 | font-size: 1.8em; 29 | margin: 0.67em 0; 30 | } 31 | .yue > h1 { 32 | margin-top: 0; 33 | font-size: 2em; 34 | } 35 | .yue h2 { 36 | font-size: 1.5em; 37 | margin: 0.83em 0; 38 | } 39 | .yue h3 { 40 | font-size: 1.17em; 41 | margin: 1em 0; 42 | } 43 | .yue h4, 44 | .yue h5, 45 | .yue h6 { 46 | font-size: 1em; 47 | margin: 1.6em 0 1em 0; 48 | } 49 | .yue h6 { 50 | font-weight: 500; 51 | } 52 | .yue p { 53 | margin-top: 0; 54 | margin-bottom: 1.64em; 55 | } 56 | .yue a { 57 | color: #111; 58 | word-wrap: break-word; 59 | } 60 | .yue a:hover { 61 | color: #555; 62 | } 63 | .yue strong, 64 | .yue b { 65 | font-weight: 700; 66 | color: #222; 67 | } 68 | .yue em, 69 | .yue i { 70 | font-style: italic; 71 | color: #222; 72 | } 73 | .yue img { 74 | max-width: 100%; 75 | height: auto; 76 | margin: 0.2em 0; 77 | } 78 | .yue a img { 79 | /* Remove border on IE */ 80 | border: none; 81 | } 82 | .yue figure { 83 | position: relative; 84 | clear: both; 85 | outline: 0; 86 | margin: 10px 0 30px; 87 | padding: 0; 88 | } 89 | .yue figure img { 90 | display: block; 91 | max-width: 100%; 92 | margin: auto; 93 | -webkit-box-sizing: border-box; 94 | -moz-box-sizing: border-box; 95 | box-sizing: border-box; 96 | } 97 | .yue figure figcaption { 98 | position: relative; 99 | width: 100%; 100 | text-align: center; 101 | left: 0; 102 | margin-top: 10px; 103 | font-weight: 400; 104 | font-size: 14px; 105 | color: #666665; 106 | } 107 | .yue figure figcaption a { 108 | text-decoration: none; 109 | color: #666665; 110 | } 111 | .yue hr { 112 | display: block; 113 | width: 14%; 114 | margin: 40px auto 34px; 115 | border: 0 none; 116 | border-top: 3px solid #dededc; 117 | } 118 | .yue blockquote { 119 | margin: 0 0 1.64em 0; 120 | border-left: 3px solid #dadada; 121 | padding-left: 12px; 122 | color: #666664; 123 | } 124 | .yue blockquote a { 125 | color: #666664; 126 | } 127 | .yue ul, 128 | .yue ol { 129 | margin: 0 0 24px 6px; 130 | padding-left: 16px; 131 | } 132 | .yue ul { 133 | list-style-type: square; 134 | } 135 | .yue ol { 136 | list-style-type: decimal; 137 | } 138 | .yue li { 139 | margin-bottom: 0.2em; 140 | } 141 | .yue li ul, 142 | .yue li ol { 143 | margin-top: 0; 144 | margin-bottom: 0; 145 | margin-left: 14px; 146 | } 147 | .yue li ul { 148 | list-style-type: disc; 149 | } 150 | .yue li ul ul { 151 | list-style-type: circle; 152 | } 153 | .yue li p { 154 | margin: 0.4em 0 0.6em; 155 | } 156 | .yue .unstyled { 157 | list-style-type: none; 158 | margin: 0; 159 | padding: 0; 160 | } 161 | .yue code, 162 | .yue tt { 163 | color: #808080; 164 | font-size: 0.96em; 165 | background-color: #f9f9f7; 166 | padding: 1px 2px; 167 | border: 1px solid #dadada; 168 | border-radius: 3px; 169 | font-family: "Inconsolata", "Menlo", monospace; 170 | } 171 | .yue pre { 172 | margin: 1.64em 0; 173 | padding: 7px; 174 | border: none; 175 | border-left: 3px solid #dadada; 176 | padding-left: 10px; 177 | overflow: auto; 178 | line-height: 1.5; 179 | font-size: 0.96em; 180 | font-family: "Inconsolata", "Menlo", monospace; 181 | color: #4c4c4c; 182 | background-color: #f9f9f7; 183 | } 184 | .yue pre code, 185 | .yue pre tt { 186 | color: #4c4c4c; 187 | border: none; 188 | background: none; 189 | padding: 0; 190 | } 191 | .yue table { 192 | width: 100%; 193 | border-collapse: collapse; 194 | border-spacing: 0; 195 | margin-bottom: 1.5em; 196 | font-size: 0.96em; 197 | } 198 | .yue th, 199 | .yue td { 200 | text-align: left; 201 | padding: 4px 8px 4px 10px; 202 | border: 1px solid #dadada; 203 | } 204 | .yue td { 205 | vertical-align: top; 206 | } 207 | .yue tr:nth-child(even) { 208 | background-color: #efefee; 209 | } 210 | .yue iframe { 211 | display: block; 212 | max-width: 100%; 213 | margin-bottom: 30px; 214 | } 215 | .yue figure iframe { 216 | margin: auto; 217 | } 218 | .yue table pre { 219 | margin: 0; 220 | padding: 0; 221 | border: none; 222 | background: none; 223 | } 224 | .yue .highlight td:first-of-type pre { 225 | text-align: right; 226 | color: #aaa; 227 | } 228 | @media (min-width: 1100px) { 229 | .yue blockquote { 230 | margin-left: -24px; 231 | padding-left: 20px; 232 | border-width: 4px; 233 | } 234 | .yue blockquote blockquote { 235 | margin-left: 0; 236 | } 237 | .yue figure figcaption:before { 238 | width: 25%; 239 | margin-left: 75%; 240 | border-top: 1px solid #dededc; 241 | display: block; 242 | content: ""; 243 | margin-bottom: 10px; 244 | } 245 | .yue figure figcaption { 246 | position: absolute; 247 | left: -172px; 248 | width: 150px; 249 | top: 0; 250 | text-align: right; 251 | margin-top: 0; 252 | } 253 | } -------------------------------------------------------------------------------- /pyprint/themes/default/static/imgs/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RicterZ/pyprint/de96f4e4684f35dafd57f521ba6acb55e80f990e/pyprint/themes/default/static/imgs/avatar.jpg -------------------------------------------------------------------------------- /pyprint/themes/default/static/imgs/banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RicterZ/pyprint/de96f4e4684f35dafd57f521ba6acb55e80f990e/pyprint/themes/default/static/imgs/banner.jpg -------------------------------------------------------------------------------- /pyprint/themes/default/static/imgs/not_found.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RicterZ/pyprint/de96f4e4684f35dafd57f521ba6acb55e80f990e/pyprint/themes/default/static/imgs/not_found.jpg -------------------------------------------------------------------------------- /pyprint/themes/default/static/js/jquery.lazyload.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Lazy Load - jQuery plugin for lazy loading images 3 | * 4 | * Copyright (c) 2007-2013 Mika Tuupola 5 | * 6 | * Licensed under the MIT license: 7 | * http://www.opensource.org/licenses/mit-license.php 8 | * 9 | * Project home: 10 | * http://www.appelsiini.net/projects/lazyload 11 | * 12 | * Version: 1.9.3 13 | * 14 | */ 15 | 16 | (function($, window, document, undefined) { 17 | var $window = $(window); 18 | 19 | $.fn.lazyload = function(options) { 20 | var elements = this; 21 | var $container; 22 | var settings = { 23 | threshold : 0, 24 | failure_limit : 0, 25 | event : "scroll", 26 | effect : "show", 27 | container : window, 28 | data_attribute : "alt", 29 | skip_invisible : true, 30 | appear : null, 31 | load : null, 32 | placeholder : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" 33 | }; 34 | 35 | function update() { 36 | var counter = 0; 37 | 38 | elements.each(function() { 39 | var $this = $(this); 40 | if (settings.skip_invisible && !$this.is(":visible")) { 41 | return; 42 | } 43 | if ($.abovethetop(this, settings) || 44 | $.leftofbegin(this, settings)) { 45 | /* Nothing. */ 46 | } else if (!$.belowthefold(this, settings) && 47 | !$.rightoffold(this, settings)) { 48 | $this.trigger("appear"); 49 | /* if we found an image we'll load, reset the counter */ 50 | counter = 0; 51 | } else { 52 | if (++counter > settings.failure_limit) { 53 | return false; 54 | } 55 | } 56 | }); 57 | 58 | } 59 | 60 | if(options) { 61 | /* Maintain BC for a couple of versions. */ 62 | if (undefined !== options.failurelimit) { 63 | options.failure_limit = options.failurelimit; 64 | delete options.failurelimit; 65 | } 66 | if (undefined !== options.effectspeed) { 67 | options.effect_speed = options.effectspeed; 68 | delete options.effectspeed; 69 | } 70 | 71 | $.extend(settings, options); 72 | } 73 | 74 | /* Cache container as jQuery as object. */ 75 | $container = (settings.container === undefined || 76 | settings.container === window) ? $window : $(settings.container); 77 | 78 | /* Fire one scroll event per scroll. Not one scroll event per image. */ 79 | if (0 === settings.event.indexOf("scroll")) { 80 | $container.bind(settings.event, function() { 81 | return update(); 82 | }); 83 | } 84 | 85 | this.each(function() { 86 | var self = this; 87 | var $self = $(self); 88 | 89 | self.loaded = false; 90 | 91 | /* If no src attribute given use data:uri. */ 92 | if ($self.attr("src") === undefined || $self.attr("src") === false) { 93 | if ($self.is("img")) { 94 | $self.attr("src", settings.placeholder); 95 | } 96 | } 97 | 98 | /* When appear is triggered load original image. */ 99 | $self.one("appear", function() { 100 | if (!this.loaded) { 101 | if (settings.appear) { 102 | var elements_left = elements.length; 103 | settings.appear.call(self, elements_left, settings); 104 | } 105 | $("") 106 | .bind("load", function() { 107 | 108 | var original = $self.attr(settings.data_attribute); 109 | $self.hide(); 110 | if ($self.is("img")) { 111 | $self.attr("src", original); 112 | } else { 113 | $self.css("background-image", "url('" + original + "')"); 114 | } 115 | $self[settings.effect](settings.effect_speed); 116 | 117 | self.loaded = true; 118 | 119 | /* Remove image from array so it is not looped next time. */ 120 | var temp = $.grep(elements, function(element) { 121 | return !element.loaded; 122 | }); 123 | elements = $(temp); 124 | 125 | if (settings.load) { 126 | var elements_left = elements.length; 127 | settings.load.call(self, elements_left, settings); 128 | } 129 | }) 130 | .attr("src", $self.attr(settings.data_attribute)); 131 | } 132 | }); 133 | 134 | /* When wanted event is triggered load original image */ 135 | /* by triggering appear. */ 136 | if (0 !== settings.event.indexOf("scroll")) { 137 | $self.bind(settings.event, function() { 138 | if (!self.loaded) { 139 | $self.trigger("appear"); 140 | } 141 | }); 142 | } 143 | }); 144 | 145 | /* Check if something appears when window is resized. */ 146 | $window.bind("resize", function() { 147 | update(); 148 | }); 149 | 150 | /* With IOS5 force loading images when navigating with back button. */ 151 | /* Non optimal workaround. */ 152 | if ((/(?:iphone|ipod|ipad).*os 5/gi).test(navigator.appVersion)) { 153 | $window.bind("pageshow", function(event) { 154 | if (event.originalEvent && event.originalEvent.persisted) { 155 | elements.each(function() { 156 | $(this).trigger("appear"); 157 | }); 158 | } 159 | }); 160 | } 161 | 162 | /* Force initial check if images should appear. */ 163 | $(document).ready(function() { 164 | update(); 165 | }); 166 | 167 | return this; 168 | }; 169 | 170 | /* Convenience methods in jQuery namespace. */ 171 | /* Use as $.belowthefold(element, {threshold : 100, container : window}) */ 172 | 173 | $.belowthefold = function(element, settings) { 174 | var fold; 175 | 176 | if (settings.container === undefined || settings.container === window) { 177 | fold = (window.innerHeight ? window.innerHeight : $window.height()) + $window.scrollTop(); 178 | } else { 179 | fold = $(settings.container).offset().top + $(settings.container).height(); 180 | } 181 | 182 | return fold <= $(element).offset().top - settings.threshold; 183 | }; 184 | 185 | $.rightoffold = function(element, settings) { 186 | var fold; 187 | 188 | if (settings.container === undefined || settings.container === window) { 189 | fold = $window.width() + $window.scrollLeft(); 190 | } else { 191 | fold = $(settings.container).offset().left + $(settings.container).width(); 192 | } 193 | 194 | return fold <= $(element).offset().left - settings.threshold; 195 | }; 196 | 197 | $.abovethetop = function(element, settings) { 198 | var fold; 199 | 200 | if (settings.container === undefined || settings.container === window) { 201 | fold = $window.scrollTop(); 202 | } else { 203 | fold = $(settings.container).offset().top; 204 | } 205 | 206 | return fold >= $(element).offset().top + settings.threshold + $(element).height(); 207 | }; 208 | 209 | $.leftofbegin = function(element, settings) { 210 | var fold; 211 | 212 | if (settings.container === undefined || settings.container === window) { 213 | fold = $window.scrollLeft(); 214 | } else { 215 | fold = $(settings.container).offset().left; 216 | } 217 | 218 | return fold >= $(element).offset().left + settings.threshold + $(element).width(); 219 | }; 220 | 221 | $.inviewport = function(element, settings) { 222 | return !$.rightoffold(element, settings) && !$.leftofbegin(element, settings) && 223 | !$.belowthefold(element, settings) && !$.abovethetop(element, settings); 224 | }; 225 | 226 | /* Custom selectors for your convenience. */ 227 | /* Use as $("img:below-the-fold").something() or */ 228 | /* $("img").filter(":below-the-fold").something() which is faster */ 229 | 230 | $.extend($.expr[":"], { 231 | "below-the-fold" : function(a) { return $.belowthefold(a, {threshold : 0}); }, 232 | "above-the-top" : function(a) { return !$.belowthefold(a, {threshold : 0}); }, 233 | "right-of-screen": function(a) { return $.rightoffold(a, {threshold : 0}); }, 234 | "left-of-screen" : function(a) { return !$.rightoffold(a, {threshold : 0}); }, 235 | "in-viewport" : function(a) { return $.inviewport(a, {threshold : 0}); }, 236 | /* Maintain BC for couple of versions. */ 237 | "above-the-fold" : function(a) { return !$.belowthefold(a, {threshold : 0}); }, 238 | "right-of-fold" : function(a) { return $.rightoffold(a, {threshold : 0}); }, 239 | "left-of-fold" : function(a) { return !$.rightoffold(a, {threshold : 0}); } 240 | }); 241 | 242 | })(jQuery, window, document); -------------------------------------------------------------------------------- /pyprint/themes/default/static/js/nprogress.js: -------------------------------------------------------------------------------- 1 | /* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress 2 | * @license MIT */ 3 | 4 | ;(function(root, factory) { 5 | 6 | if (typeof define === 'function' && define.amd) { 7 | define(factory); 8 | } else if (typeof exports === 'object') { 9 | module.exports = factory(); 10 | } else { 11 | root.NProgress = factory(); 12 | } 13 | 14 | })(this, function() { 15 | var NProgress = {}; 16 | 17 | NProgress.version = '0.1.6'; 18 | 19 | var Settings = NProgress.settings = { 20 | minimum: 0.08, 21 | easing: 'ease', 22 | positionUsing: '', 23 | speed: 200, 24 | trickle: true, 25 | trickleRate: 0.02, 26 | trickleSpeed: 800, 27 | showSpinner: true, 28 | barSelector: '[role="bar"]', 29 | spinnerSelector: '[role="spinner"]', 30 | parent: 'body', 31 | template: '
' 32 | }; 33 | 34 | /** 35 | * Updates configuration. 36 | * 37 | * NProgress.configure({ 38 | * minimum: 0.1 39 | * }); 40 | */ 41 | NProgress.configure = function(options) { 42 | var key, value; 43 | for (key in options) { 44 | value = options[key]; 45 | if (value !== undefined && options.hasOwnProperty(key)) Settings[key] = value; 46 | } 47 | 48 | return this; 49 | }; 50 | 51 | /** 52 | * Last number. 53 | */ 54 | 55 | NProgress.status = null; 56 | 57 | /** 58 | * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`. 59 | * 60 | * NProgress.set(0.4); 61 | * NProgress.set(1.0); 62 | */ 63 | 64 | NProgress.set = function(n) { 65 | var started = NProgress.isStarted(); 66 | 67 | n = clamp(n, Settings.minimum, 1); 68 | NProgress.status = (n === 1 ? null : n); 69 | 70 | var progress = NProgress.render(!started), 71 | bar = progress.querySelector(Settings.barSelector), 72 | speed = Settings.speed, 73 | ease = Settings.easing; 74 | 75 | progress.offsetWidth; /* Repaint */ 76 | 77 | queue(function(next) { 78 | // Set positionUsing if it hasn't already been set 79 | if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS(); 80 | 81 | // Add transition 82 | css(bar, barPositionCSS(n, speed, ease)); 83 | 84 | if (n === 1) { 85 | // Fade out 86 | css(progress, { 87 | transition: 'none', 88 | opacity: 1 89 | }); 90 | progress.offsetWidth; /* Repaint */ 91 | 92 | setTimeout(function() { 93 | css(progress, { 94 | transition: 'all ' + speed + 'ms linear', 95 | opacity: 0 96 | }); 97 | setTimeout(function() { 98 | NProgress.remove(); 99 | next(); 100 | }, speed); 101 | }, speed); 102 | } else { 103 | setTimeout(next, speed); 104 | } 105 | }); 106 | 107 | return this; 108 | }; 109 | 110 | NProgress.isStarted = function() { 111 | return typeof NProgress.status === 'number'; 112 | }; 113 | 114 | /** 115 | * Shows the progress bar. 116 | * This is the same as setting the status to 0%, except that it doesn't go backwards. 117 | * 118 | * NProgress.start(); 119 | * 120 | */ 121 | NProgress.start = function() { 122 | if (!NProgress.status) NProgress.set(0); 123 | 124 | var work = function() { 125 | setTimeout(function() { 126 | if (!NProgress.status) return; 127 | NProgress.trickle(); 128 | work(); 129 | }, Settings.trickleSpeed); 130 | }; 131 | 132 | if (Settings.trickle) work(); 133 | 134 | return this; 135 | }; 136 | 137 | /** 138 | * Hides the progress bar. 139 | * This is the *sort of* the same as setting the status to 100%, with the 140 | * difference being `done()` makes some placebo effect of some realistic motion. 141 | * 142 | * NProgress.done(); 143 | * 144 | * If `true` is passed, it will show the progress bar even if its hidden. 145 | * 146 | * NProgress.done(true); 147 | */ 148 | 149 | NProgress.done = function(force) { 150 | if (!force && !NProgress.status) return this; 151 | 152 | return NProgress.inc(0.3 + 0.5 * Math.random()).set(1); 153 | }; 154 | 155 | /** 156 | * Increments by a random amount. 157 | */ 158 | 159 | NProgress.inc = function(amount) { 160 | var n = NProgress.status; 161 | 162 | if (!n) { 163 | return NProgress.start(); 164 | } else { 165 | if (typeof amount !== 'number') { 166 | amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95); 167 | } 168 | 169 | n = clamp(n + amount, 0, 0.994); 170 | return NProgress.set(n); 171 | } 172 | }; 173 | 174 | NProgress.trickle = function() { 175 | return NProgress.inc(Math.random() * Settings.trickleRate); 176 | }; 177 | 178 | /** 179 | * Waits for all supplied jQuery promises and 180 | * increases the progress as the promises resolve. 181 | * 182 | * @param $promise jQUery Promise 183 | */ 184 | (function() { 185 | var initial = 0, current = 0; 186 | 187 | NProgress.promise = function($promise) { 188 | if (!$promise || $promise.state() == "resolved") { 189 | return this; 190 | } 191 | 192 | if (current == 0) { 193 | NProgress.start(); 194 | } 195 | 196 | initial++; 197 | current++; 198 | 199 | $promise.always(function() { 200 | current--; 201 | if (current == 0) { 202 | initial = 0; 203 | NProgress.done(); 204 | } else { 205 | NProgress.set((initial - current) / initial); 206 | } 207 | }); 208 | 209 | return this; 210 | }; 211 | 212 | })(); 213 | 214 | /** 215 | * (Internal) renders the progress bar markup based on the `template` 216 | * setting. 217 | */ 218 | 219 | NProgress.render = function(fromStart) { 220 | if (NProgress.isRendered()) return document.getElementById('nprogress'); 221 | 222 | addClass(document.documentElement, 'nprogress-busy'); 223 | 224 | var progress = document.createElement('div'); 225 | progress.id = 'nprogress'; 226 | progress.innerHTML = Settings.template; 227 | 228 | var bar = progress.querySelector(Settings.barSelector), 229 | perc = fromStart ? '-100' : toBarPerc(NProgress.status || 0), 230 | parent = document.querySelector(Settings.parent), 231 | spinner; 232 | 233 | css(bar, { 234 | transition: 'all 0 linear', 235 | transform: 'translate3d(' + perc + '%,0,0)' 236 | }); 237 | 238 | if (!Settings.showSpinner) { 239 | spinner = progress.querySelector(Settings.spinnerSelector); 240 | spinner && removeElement(spinner); 241 | } 242 | 243 | if (parent != document.body) { 244 | addClass(parent, 'nprogress-custom-parent'); 245 | } 246 | 247 | parent.appendChild(progress); 248 | return progress; 249 | }; 250 | 251 | /** 252 | * Removes the element. Opposite of render(). 253 | */ 254 | 255 | NProgress.remove = function() { 256 | removeClass(document.documentElement, 'nprogress-busy'); 257 | removeClass(document.querySelector(Settings.parent), 'nprogress-custom-parent') 258 | var progress = document.getElementById('nprogress'); 259 | progress && removeElement(progress); 260 | }; 261 | 262 | /** 263 | * Checks if the progress bar is rendered. 264 | */ 265 | 266 | NProgress.isRendered = function() { 267 | return !!document.getElementById('nprogress'); 268 | }; 269 | 270 | /** 271 | * Determine which positioning CSS rule to use. 272 | */ 273 | 274 | NProgress.getPositioningCSS = function() { 275 | // Sniff on document.body.style 276 | var bodyStyle = document.body.style; 277 | 278 | // Sniff prefixes 279 | var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' : 280 | ('MozTransform' in bodyStyle) ? 'Moz' : 281 | ('msTransform' in bodyStyle) ? 'ms' : 282 | ('OTransform' in bodyStyle) ? 'O' : ''; 283 | 284 | if (vendorPrefix + 'Perspective' in bodyStyle) { 285 | // Modern browsers with 3D support, e.g. Webkit, IE10 286 | return 'translate3d'; 287 | } else if (vendorPrefix + 'Transform' in bodyStyle) { 288 | // Browsers without 3D support, e.g. IE9 289 | return 'translate'; 290 | } else { 291 | // Browsers without translate() support, e.g. IE7-8 292 | return 'margin'; 293 | } 294 | }; 295 | 296 | /** 297 | * Helpers 298 | */ 299 | 300 | function clamp(n, min, max) { 301 | if (n < min) return min; 302 | if (n > max) return max; 303 | return n; 304 | } 305 | 306 | /** 307 | * (Internal) converts a percentage (`0..1`) to a bar translateX 308 | * percentage (`-100%..0%`). 309 | */ 310 | 311 | function toBarPerc(n) { 312 | return (-1 + n) * 100; 313 | } 314 | 315 | 316 | /** 317 | * (Internal) returns the correct CSS for changing the bar's 318 | * position given an n percentage, and speed and ease from Settings 319 | */ 320 | 321 | function barPositionCSS(n, speed, ease) { 322 | var barCSS; 323 | 324 | if (Settings.positionUsing === 'translate3d') { 325 | barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' }; 326 | } else if (Settings.positionUsing === 'translate') { 327 | barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' }; 328 | } else { 329 | barCSS = { 'margin-left': toBarPerc(n)+'%' }; 330 | } 331 | 332 | barCSS.transition = 'all '+speed+'ms '+ease; 333 | 334 | return barCSS; 335 | } 336 | 337 | /** 338 | * (Internal) Queues a function to be executed. 339 | */ 340 | 341 | var queue = (function() { 342 | var pending = []; 343 | 344 | function next() { 345 | var fn = pending.shift(); 346 | if (fn) { 347 | fn(next); 348 | } 349 | } 350 | 351 | return function(fn) { 352 | pending.push(fn); 353 | if (pending.length == 1) next(); 354 | }; 355 | })(); 356 | 357 | /** 358 | * (Internal) Applies css properties to an element, similar to the jQuery 359 | * css method. 360 | * 361 | * While this helper does assist with vendor prefixed property names, it 362 | * does not perform any manipulation of values prior to setting styles. 363 | */ 364 | 365 | var css = (function() { 366 | var cssPrefixes = [ 'Webkit', 'O', 'Moz', 'ms' ], 367 | cssProps = {}; 368 | 369 | function camelCase(string) { 370 | return string.replace(/^-ms-/, 'ms-').replace(/-([\da-z])/gi, function(match, letter) { 371 | return letter.toUpperCase(); 372 | }); 373 | } 374 | 375 | function getVendorProp(name) { 376 | var style = document.body.style; 377 | if (name in style) return name; 378 | 379 | var i = cssPrefixes.length, 380 | capName = name.charAt(0).toUpperCase() + name.slice(1), 381 | vendorName; 382 | while (i--) { 383 | vendorName = cssPrefixes[i] + capName; 384 | if (vendorName in style) return vendorName; 385 | } 386 | 387 | return name; 388 | } 389 | 390 | function getStyleProp(name) { 391 | name = camelCase(name); 392 | return cssProps[name] || (cssProps[name] = getVendorProp(name)); 393 | } 394 | 395 | function applyCss(element, prop, value) { 396 | prop = getStyleProp(prop); 397 | element.style[prop] = value; 398 | } 399 | 400 | return function(element, properties) { 401 | var args = arguments, 402 | prop, 403 | value; 404 | 405 | if (args.length == 2) { 406 | for (prop in properties) { 407 | value = properties[prop]; 408 | if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value); 409 | } 410 | } else { 411 | applyCss(element, args[1], args[2]); 412 | } 413 | } 414 | })(); 415 | 416 | /** 417 | * (Internal) Determines if an element or space separated list of class names contains a class name. 418 | */ 419 | 420 | function hasClass(element, name) { 421 | var list = typeof element == 'string' ? element : classList(element); 422 | return list.indexOf(' ' + name + ' ') >= 0; 423 | } 424 | 425 | /** 426 | * (Internal) Adds a class to an element. 427 | */ 428 | 429 | function addClass(element, name) { 430 | var oldList = classList(element), 431 | newList = oldList + name; 432 | 433 | if (hasClass(oldList, name)) return; 434 | 435 | // Trim the opening space. 436 | element.className = newList.substring(1); 437 | } 438 | 439 | /** 440 | * (Internal) Removes a class from an element. 441 | */ 442 | 443 | function removeClass(element, name) { 444 | var oldList = classList(element), 445 | newList; 446 | 447 | if (!hasClass(element, name)) return; 448 | 449 | // Replace the class name. 450 | newList = oldList.replace(' ' + name + ' ', ' '); 451 | 452 | // Trim the opening and closing spaces. 453 | element.className = newList.substring(1, newList.length - 1); 454 | } 455 | 456 | /** 457 | * (Internal) Gets a space separated list of the class names on the element. 458 | * The list is wrapped with a single space on each end to facilitate finding 459 | * matches within the list. 460 | */ 461 | 462 | function classList(element) { 463 | return (' ' + (element.className || '') + ' ').replace(/\s+/gi, ' '); 464 | } 465 | 466 | /** 467 | * (Internal) Removes an element from the DOM. 468 | */ 469 | 470 | function removeElement(element) { 471 | element && element.parentNode && element.parentNode.removeChild(element); 472 | } 473 | 474 | return NProgress; 475 | }); 476 | 477 | -------------------------------------------------------------------------------- /pyprint/themes/default/templates/archives.html: -------------------------------------------------------------------------------- 1 | {% if is_pjax %} 2 | {% extends "pjax_layout.html" %} 3 | {% else %} 4 | {% extends "layout.html" %} 5 | {% endif %} 6 | 7 | {% block body %} 8 |
    9 | {% for group in posts_groups %} 10 |
  • 11 |

    {{ group.year }}

    12 |
      13 | {% for post in group.posts %} 14 |
    • {{ post.title }}

    • 15 | {% endfor %} 16 |
    17 |
  • 18 | {% endfor %} 19 |
20 | {% endblock %} 21 | -------------------------------------------------------------------------------- /pyprint/themes/default/templates/diaries.html: -------------------------------------------------------------------------------- 1 | {% if is_pjax %} 2 | {% extends "pjax_layout.html" %} 3 | {% else %} 4 | {% extends "layout.html" %} 5 | {% endif %} 6 | 7 | {% block body %} 8 |
    9 | {% for diary in diaries %} 10 |
  • {{ diary.created_time }} / {{ diary.title }}

  • 11 | {% endfor %} 12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /pyprint/themes/default/templates/feed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ settings.username }} 4 | {{ settings.title }} 5 | {{ posts[0].created_time if posts }} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | http://{{ url }} 14 | 15 | {% for post in posts %} 16 | 17 | {{ post.title }} 18 | http://{{ url }}/articles/{{ post.title|urlencode }} 19 | http://{{ url }}/articles/{{ post.title|urlencode }} 20 | {{ post.created_time }} 21 | 22 | 23 | {% endfor %} 24 | 25 | -------------------------------------------------------------------------------- /pyprint/themes/default/templates/index.html: -------------------------------------------------------------------------------- 1 | {% if is_pjax %} 2 | {% extends "pjax_layout.html" %} 3 | {% else %} 4 | {% extends "layout.html" %} 5 | {% endif %} 6 | 7 | 8 | {% block body %} 9 | {% for post in data.posts %} 10 |
11 |

{{ post.title }}

12 | 15 |
16 | {{ post.content|markdown }} 17 |
18 | 28 |
29 | {% endfor %} 30 |
31 | ‹‹ Newer 32 | Older ›› 33 |
34 | {% endblock %} 35 | -------------------------------------------------------------------------------- /pyprint/themes/default/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ title }} - {{ settings.title }} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 | 24 | 32 | {% block head %} 33 | {% endblock %} 34 | 35 | 36 | 37 |
38 |
39 | 40 |
41 |
42 |

{{ settings.motto }}

43 | 44 |
{{ settings.email }}
45 |
46 |
47 | 55 |
56 | 57 |
58 | {% block body %} 59 | {% endblock %} 60 |
61 | 62 |
63 | 64 | 65 | 66 | 72 |
73 | 74 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /pyprint/themes/default/templates/links.html: -------------------------------------------------------------------------------- 1 | {% if is_pjax %} 2 | {% extends "pjax_layout.html" %} 3 | {% else %} 4 | {% extends "layout.html" %} 5 | {% endif %} 6 | 7 | 8 | {% block body %} 9 | 32 | 33 | 41 | {% endblock %} 42 | -------------------------------------------------------------------------------- /pyprint/themes/default/templates/not_found.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block body %} 4 |
5 |

你在看哪里!?

6 | 7 |
8 | {% endblock %} -------------------------------------------------------------------------------- /pyprint/themes/default/templates/pjax_layout.html: -------------------------------------------------------------------------------- 1 | {{ title }} - {{ settings.title }} 2 | 10 | 11 | {% block body %} 12 | {% endblock %} -------------------------------------------------------------------------------- /pyprint/themes/default/templates/post.html: -------------------------------------------------------------------------------- 1 | {% if is_pjax %} 2 | {% extends "pjax_layout.html" %} 3 | {% else %} 4 | {% extends "layout.html" %} 5 | {% endif %} 6 | 7 | 8 | {% block body %} 9 |
10 |

{{ post.title }}

11 | 14 |
15 | {{ post.content|markdown }} 16 |
17 | 27 |
28 |
29 |
30 |
31 | {% if post.type == 'post' %} 32 | 40 | {% endif %} 41 | {% endblock %} 42 | -------------------------------------------------------------------------------- /pyprint/themes/mdl/static/css/font.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Material Icons'; 3 | font-style: normal; 4 | font-weight: 400; 5 | src: local('Material Icons'), local('MaterialIcons-Regular'), url(https://fonts.gstatic.com/s/materialicons/v7/2fcrYFNaTjcS6g4U3t-Y5StnKWgpfO2iSkLzTz-AABg.ttf) format('truetype'); 6 | } 7 | 8 | .material-icons { 9 | font-family: 'Material Icons'; 10 | font-weight: normal; 11 | font-style: normal; 12 | font-size: 24px; 13 | line-height: 1; 14 | letter-spacing: normal; 15 | text-transform: none; 16 | display: inline-block; 17 | word-wrap: normal; 18 | } 19 | -------------------------------------------------------------------------------- /pyprint/themes/mdl/static/css/material-scrolltop.css: -------------------------------------------------------------------------------- 1 | /** 2 | * material-scrolltop 3 | * 4 | * Author: Bartholomej 5 | * Website: https://github.com/bartholomej/material-scrolltop 6 | * Docs: https://github.com/bartholomej/material-scrolltop 7 | * Repo: https://github.com/bartholomej/material-scrolltop 8 | * Issues: https://github.com/bartholomej/material-scrolltop/issues 9 | */ 10 | 11 | .material-scrolltop { 12 | z-index: 999; 13 | display: block; 14 | position: fixed; 15 | width: 0; 16 | height: 0; 17 | bottom: 23px; 18 | right: 23px; 19 | padding: 0; 20 | overflow: hidden; 21 | outline: none; 22 | border: none; 23 | border-radius: 2px; 24 | box-shadow: 0 3px 10px rgba(0, 0, 0, 0.5); 25 | cursor: hand; 26 | border-radius: 50%; 27 | background: #888; 28 | -webkit-transition: all 0.3s cubic-bezier(0.25, 0.25, 0, 1); 29 | -ms-transition: all 0.3s cubic-bezier(0.25, 0.25, 0, 1); 30 | -moz-transition: all 0.3s cubic-bezier(0.25, 0.25, 0, 1); 31 | -o-transition: all 0.3s cubic-bezier(0.25, 0.25, 0, 1); 32 | transition: all 0.3s cubic-bezier(0.25, 0.25, 0, 1); 33 | } 34 | 35 | .material-scrolltop:hover { 36 | background-color: #888; 37 | text-decoration: none; 38 | box-shadow: 0 3px 10px rgba(0, 0, 0, 0.5), 0 3px 15px rgba(0, 0, 0, 0.5); 39 | } 40 | 41 | .material-scrolltop::before { 42 | position: absolute; 43 | top: 50%; 44 | left: 50%; 45 | -webkit-transform: translate(-50%, -50%); 46 | -ms-transform: translate(-50%, -50%); 47 | -moz-transform: translate(-50%, -50%); 48 | -o-transform: translate(-50%, -50%); 49 | transform: translate(-50%, -50%); 50 | content: ""; 51 | width: 0; 52 | border-radius: 100%; 53 | background: #999; 54 | } 55 | 56 | .material-scrolltop:active::before { 57 | width: 120%; 58 | padding-top: 120%; 59 | -webkit-transition: all 0.2s ease-out; 60 | -ms-transition: all 0.2s ease-out; 61 | -moz-transition: all 0.2s ease-out; 62 | -o-transition: all 0.2s ease-out; 63 | transition: all 0.2s ease-out; 64 | } 65 | 66 | .material-scrolltop.reveal { 67 | width: 56px; 68 | height: 56px; 69 | } 70 | 71 | .material-scrolltop span { 72 | display: block; 73 | font-size: 25px; 74 | color: #fff; 75 | } 76 | 77 | .material-scrolltop, 78 | .material-scrolltop::before { 79 | background-image: url(/static/imgs/top-arrow.svg); 80 | background-position: center 50%; 81 | background-repeat: no-repeat; 82 | } 83 | /*# sourceMappingURL=material-scrolltop.css.map */ 84 | -------------------------------------------------------------------------------- /pyprint/themes/mdl/static/css/style.css: -------------------------------------------------------------------------------- 1 | 2 | .avatar { 3 | overflow: hidden; 4 | /* border: 4px solid #FFF; */ 5 | margin: 20px auto; 6 | box-shadow: 0 0 10px #000; 7 | width: 120px; 8 | border-radius: 50%; 9 | -webkit-transition: -webkit-transform 400ms; 10 | -moz-transition: -moz-transform 400ms; 11 | transition: transform 400ms; 12 | } 13 | 14 | 15 | .avatar:hover { 16 | -webkit-transform:rotate(390deg); 17 | -moz-transform:rotate(390deg); 18 | transform:rotate(390deg); 19 | } 20 | 21 | .avatar img { 22 | width: 100%; 23 | border-radius: 50%; 24 | } 25 | 26 | .email { 27 | text-decoration: blink; 28 | } 29 | 30 | .email i { 31 | text-align: center; 32 | font-size: 1.1em; 33 | display: block; 34 | } 35 | 36 | .motto { 37 | margin: auto; 38 | font-size: 1.5em; 39 | text-align: center; 40 | } 41 | 42 | .mdl-navigation > a { 43 | font-weight: 600; 44 | } 45 | 46 | blockquote:before, blockquote:after { 47 | display: none; 48 | } 49 | 50 | .navbar { 51 | z-index: 1; 52 | position: fixed; 53 | } 54 | 55 | 56 | .yue p, .yue ul, .yue ol, .yue blockquote { 57 | font-size: 1.0em; 58 | } 59 | 60 | .yue code { 61 | font-size: 0.8em; 62 | } 63 | 64 | .pull-right { 65 | float: right; 66 | } 67 | 68 | .hide { 69 | display: none 70 | } 71 | 72 | h1.year { 73 | font-weight: 600; 74 | font-size: 2.0em; 75 | } 76 | 77 | .container { 78 | word-break: break-all; 79 | margin: auto; 80 | padding-top: 60px; 81 | } 82 | 83 | .time { 84 | padding-bottom: 20px; 85 | } 86 | 87 | hr.post { 88 | width: 100%; 89 | border: 0; 90 | height: 1px; 91 | background-image: -webkit-linear-gradient(left, rgba(228,228,228,0), rgba(228,228,228,0.75), rgba(228,228,228,0)); 92 | background-image: -moz-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0)); 93 | background-image: -ms-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0)); 94 | background-image: -o-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0)); 95 | margin: 40px 0; 96 | } 97 | 98 | .progress-bar { 99 | width: 100%; 100 | position: absolute; 101 | top: 0; 102 | z-index: 999; 103 | display: none; 104 | } 105 | 106 | .mdl-nav { 107 | color: #666; 108 | font-size: 0.8em; 109 | padding: 16px 40px 0; 110 | position: absolute; 111 | bottom: 0; 112 | } 113 | 114 | .mdl-nav a { 115 | text-decoration: blink; 116 | color: #666; 117 | } 118 | 119 | .not-found { 120 | padding-top: 60px; 121 | } 122 | 123 | .mdl-layout__container { 124 | position: static; 125 | } 126 | -------------------------------------------------------------------------------- /pyprint/themes/mdl/static/css/yue.css: -------------------------------------------------------------------------------- 1 | /** 2 | * yue.css 3 | * 4 | * yue.css is designed for readable content. 5 | * 6 | * Copyright (c) 2013 by Hsiaoming Yang. 7 | */ 8 | 9 | 10 | 11 | .yue { 12 | font: 400 18px/1.62 "Georgia", "Xin Gothic", "Hiragino Sans GB", "WenQuanYi Micro Hei", sans-serif; 13 | color: #444443; 14 | } 15 | .yue ::selection { 16 | background-color: rgba(0,0,0,0.2); 17 | } 18 | .yue h1, 19 | .yue h2, 20 | .yue h3, 21 | .yue h4, 22 | .yue h5, 23 | .yue h6 { 24 | font-family: "Georgia", "Xin Gothic", "Hiragino Sans GB", "WenQuanYi Micro Hei", "Microsoft YaHei", "SimSun", sans-serif; 25 | color: #222223; 26 | } 27 | .yue h1 { 28 | font-size: 1.8em; 29 | margin: 0.67em 0; 30 | } 31 | .yue > h1 { 32 | margin-top: 0; 33 | font-size: 2em; 34 | } 35 | .yue h2 { 36 | font-size: 1.5em; 37 | margin: 0.83em 0; 38 | } 39 | .yue h3 { 40 | font-size: 1.17em; 41 | margin: 1em 0; 42 | } 43 | .yue h4, 44 | .yue h5, 45 | .yue h6 { 46 | font-size: 1em; 47 | margin: 1.6em 0 1em 0; 48 | } 49 | .yue h6 { 50 | font-weight: 500; 51 | } 52 | .yue p { 53 | margin-top: 0; 54 | margin-bottom: 1.64em; 55 | } 56 | .yue a { 57 | color: #111; 58 | word-wrap: break-word; 59 | } 60 | .yue a:hover { 61 | color: #555; 62 | } 63 | .yue strong, 64 | .yue b { 65 | font-weight: 700; 66 | color: #222; 67 | } 68 | .yue em, 69 | .yue i { 70 | font-style: italic; 71 | color: #222; 72 | } 73 | .yue img { 74 | max-width: 100%; 75 | height: auto; 76 | margin: 0.2em 0; 77 | } 78 | .yue a img { 79 | /* Remove border on IE */ 80 | border: none; 81 | } 82 | .yue figure { 83 | position: relative; 84 | clear: both; 85 | outline: 0; 86 | margin: 10px 0 30px; 87 | padding: 0; 88 | } 89 | .yue figure img { 90 | display: block; 91 | max-width: 100%; 92 | margin: auto; 93 | -webkit-box-sizing: border-box; 94 | -moz-box-sizing: border-box; 95 | box-sizing: border-box; 96 | } 97 | .yue figure figcaption { 98 | position: relative; 99 | width: 100%; 100 | text-align: center; 101 | left: 0; 102 | margin-top: 10px; 103 | font-weight: 400; 104 | font-size: 14px; 105 | color: #666665; 106 | } 107 | .yue figure figcaption a { 108 | text-decoration: none; 109 | color: #666665; 110 | } 111 | .yue hr { 112 | display: block; 113 | width: 14%; 114 | margin: 40px auto 34px; 115 | border: 0 none; 116 | border-top: 3px solid #dededc; 117 | } 118 | .yue blockquote { 119 | margin: 0 0 1.64em 0; 120 | border-left: 3px solid #dadada; 121 | padding-left: 12px; 122 | color: #666664; 123 | } 124 | .yue blockquote a { 125 | color: #666664; 126 | } 127 | .yue ul, 128 | .yue ol { 129 | margin: 0 0 24px 6px; 130 | padding-left: 16px; 131 | } 132 | .yue ul { 133 | list-style-type: square; 134 | } 135 | .yue ol { 136 | list-style-type: decimal; 137 | } 138 | .yue li { 139 | margin-bottom: 0.2em; 140 | } 141 | .yue li ul, 142 | .yue li ol { 143 | margin-top: 0; 144 | margin-bottom: 0; 145 | margin-left: 14px; 146 | } 147 | .yue li ul { 148 | list-style-type: disc; 149 | } 150 | .yue li ul ul { 151 | list-style-type: circle; 152 | } 153 | .yue li p { 154 | margin: 0.4em 0 0.6em; 155 | } 156 | .yue .unstyled { 157 | list-style-type: none; 158 | margin: 0; 159 | padding: 0; 160 | } 161 | .yue code, 162 | .yue tt { 163 | color: #808080; 164 | font-size: 0.96em; 165 | background-color: #f9f9f7; 166 | padding: 1px 2px; 167 | border: 1px solid #dadada; 168 | border-radius: 3px; 169 | font-family: "Inconsolata", "Menlo", monospace; 170 | } 171 | .yue pre { 172 | margin: 1.64em 0; 173 | padding: 7px; 174 | border: none; 175 | border-left: 3px solid #dadada; 176 | padding-left: 10px; 177 | overflow: auto; 178 | line-height: 1.5; 179 | font-size: 0.96em; 180 | font-family: "Inconsolata", "Menlo", monospace; 181 | color: #4c4c4c; 182 | background-color: #f9f9f7; 183 | } 184 | .yue pre code, 185 | .yue pre tt { 186 | color: #4c4c4c; 187 | border: none; 188 | background: none; 189 | padding: 0; 190 | } 191 | .yue table { 192 | width: 100%; 193 | border-collapse: collapse; 194 | border-spacing: 0; 195 | margin-bottom: 1.5em; 196 | font-size: 0.96em; 197 | } 198 | .yue th, 199 | .yue td { 200 | text-align: left; 201 | padding: 4px 8px 4px 10px; 202 | border: 1px solid #dadada; 203 | } 204 | .yue td { 205 | vertical-align: top; 206 | } 207 | .yue tr:nth-child(even) { 208 | background-color: #efefee; 209 | } 210 | .yue iframe { 211 | display: block; 212 | max-width: 100%; 213 | margin-bottom: 30px; 214 | } 215 | .yue figure iframe { 216 | margin: auto; 217 | } 218 | .yue table pre { 219 | margin: 0; 220 | padding: 0; 221 | border: none; 222 | background: none; 223 | } 224 | .yue .highlight td:first-of-type pre { 225 | text-align: right; 226 | color: #aaa; 227 | } 228 | @media (min-width: 1100px) { 229 | .yue blockquote { 230 | margin-left: -24px; 231 | padding-left: 20px; 232 | border-width: 4px; 233 | } 234 | .yue blockquote blockquote { 235 | margin-left: 0; 236 | } 237 | .yue figure figcaption:before { 238 | width: 25%; 239 | margin-left: 75%; 240 | border-top: 1px solid #dededc; 241 | display: block; 242 | content: ""; 243 | margin-bottom: 10px; 244 | } 245 | .yue figure figcaption { 246 | position: absolute; 247 | left: -172px; 248 | width: 150px; 249 | top: 0; 250 | text-align: right; 251 | margin-top: 0; 252 | } 253 | } -------------------------------------------------------------------------------- /pyprint/themes/mdl/static/imgs/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RicterZ/pyprint/de96f4e4684f35dafd57f521ba6acb55e80f990e/pyprint/themes/mdl/static/imgs/avatar.jpg -------------------------------------------------------------------------------- /pyprint/themes/mdl/static/imgs/not_found.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RicterZ/pyprint/de96f4e4684f35dafd57f521ba6acb55e80f990e/pyprint/themes/mdl/static/imgs/not_found.gif -------------------------------------------------------------------------------- /pyprint/themes/mdl/static/imgs/top-arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /pyprint/themes/mdl/static/js/material-progress.js: -------------------------------------------------------------------------------- 1 | var componentHandler = (function() { 2 | 'use strict'; 3 | 4 | var registeredComponents_ = []; 5 | var createdComponents_ = []; 6 | var downgradeMethod_ = 'mdlDowngrade_'; 7 | var componentConfigProperty_ = 'mdlComponentConfigInternal_'; 8 | 9 | /** 10 | * Searches registered components for a class we are interested in using. 11 | * Optionally replaces a match with passed object if specified. 12 | * @param {string} name The name of a class we want to use. 13 | * @param {Object=} optReplace Optional object to replace match with. 14 | * @return {Object | boolean} 15 | * @private 16 | */ 17 | function findRegisteredClass_(name, optReplace) { 18 | for (var i = 0; i < registeredComponents_.length; i++) { 19 | if (registeredComponents_[i].className === name) { 20 | if (optReplace !== undefined) { 21 | registeredComponents_[i] = optReplace; 22 | } 23 | return registeredComponents_[i]; 24 | } 25 | } 26 | return false; 27 | } 28 | 29 | /** 30 | * Returns an array of the classNames of the upgraded classes on the element. 31 | * @param {HTMLElement} element The element to fetch data from. 32 | * @return {Array} 33 | * @private 34 | */ 35 | function getUpgradedListOfElement_(element) { 36 | var dataUpgraded = element.getAttribute('data-upgraded'); 37 | // Use `['']` as default value to conform the `,name,name...` style. 38 | return dataUpgraded === null ? [''] : dataUpgraded.split(','); 39 | } 40 | 41 | /** 42 | * Returns true if the given element has already been upgraded for the given 43 | * class. 44 | * @param {HTMLElement} element The element we want to check. 45 | * @param {string} jsClass The class to check for. 46 | * @return boolean 47 | * @private 48 | */ 49 | function isElementUpgraded_(element, jsClass) { 50 | var upgradedList = getUpgradedListOfElement_(element); 51 | return upgradedList.indexOf(jsClass) !== -1; 52 | } 53 | 54 | /** 55 | * Searches existing DOM for elements of our component type and upgrades them 56 | * if they have not already been upgraded. 57 | * @param {!string=} optJsClass the programatic name of the element class we 58 | * need to create a new instance of. 59 | * @param {!string=} optCssClass the name of the CSS class elements of this 60 | * type will have. 61 | */ 62 | function upgradeDomInternal(optJsClass, optCssClass) { 63 | if (optJsClass === undefined && optCssClass === undefined) { 64 | for (var i = 0; i < registeredComponents_.length; i++) { 65 | upgradeDomInternal(registeredComponents_[i].className, 66 | registeredComponents_[i].cssClass); 67 | } 68 | } else { 69 | var jsClass = /** @type {!string} */ (optJsClass); 70 | if (optCssClass === undefined) { 71 | var registeredClass = findRegisteredClass_(jsClass); 72 | if (registeredClass) { 73 | optCssClass = registeredClass.cssClass; 74 | } 75 | } 76 | 77 | var elements = document.querySelectorAll('.' + optCssClass); 78 | for (var n = 0; n < elements.length; n++) { 79 | upgradeElementInternal(elements[n], jsClass); 80 | } 81 | } 82 | } 83 | 84 | /** 85 | * Upgrades a specific element rather than all in the DOM. 86 | * @param {HTMLElement} element The element we wish to upgrade. 87 | * @param {!string=} optJsClass Optional name of the class we want to upgrade 88 | * the element to. 89 | */ 90 | function upgradeElementInternal(element, optJsClass) { 91 | // Verify argument type. 92 | if (!(typeof element === 'object' && element instanceof Element)) { 93 | throw new Error('Invalid argument provided to upgrade MDL element.'); 94 | } 95 | var upgradedList = getUpgradedListOfElement_(element); 96 | var classesToUpgrade = []; 97 | // If jsClass is not provided scan the registered components to find the 98 | // ones matching the element's CSS classList. 99 | if (!optJsClass) { 100 | var classList = element.classList; 101 | registeredComponents_.forEach(function (component) { 102 | // Match CSS & Not to be upgraded & Not upgraded. 103 | if (classList.contains(component.cssClass) && 104 | classesToUpgrade.indexOf(component) === -1 && 105 | !isElementUpgraded_(element, component.className)) { 106 | classesToUpgrade.push(component); 107 | } 108 | }); 109 | } else if (!isElementUpgraded_(element, optJsClass)) { 110 | classesToUpgrade.push(findRegisteredClass_(optJsClass)); 111 | } 112 | 113 | // Upgrade the element for each classes. 114 | for (var i = 0, n = classesToUpgrade.length, registeredClass; i < n; i++) { 115 | registeredClass = classesToUpgrade[i]; 116 | if (registeredClass) { 117 | // Mark element as upgraded. 118 | upgradedList.push(registeredClass.className); 119 | element.setAttribute('data-upgraded', upgradedList.join(',')); 120 | var instance = new registeredClass.classConstructor(element); 121 | instance[componentConfigProperty_] = registeredClass; 122 | createdComponents_.push(instance); 123 | // Call any callbacks the user has registered with this component type. 124 | for (var j = 0, m = registeredClass.callbacks.length; j < m; j++) { 125 | registeredClass.callbacks[j](element); 126 | } 127 | 128 | if (registeredClass.widget) { 129 | // Assign per element instance for control over API 130 | element[registeredClass.className] = instance; 131 | } 132 | } else { 133 | throw new Error( 134 | 'Unable to find a registered component for the given class.'); 135 | } 136 | 137 | var ev = document.createEvent('Events'); 138 | ev.initEvent('mdl-componentupgraded', true, true); 139 | element.dispatchEvent(ev); 140 | } 141 | } 142 | 143 | /** 144 | * Upgrades a specific list of elements rather than all in the DOM. 145 | * @param {HTMLElement | Array | NodeList | HTMLCollection} elements 146 | * The elements we wish to upgrade. 147 | */ 148 | function upgradeElementsInternal(elements) { 149 | if (!Array.isArray(elements)) { 150 | if (typeof elements.item === 'function') { 151 | elements = Array.prototype.slice.call(elements); 152 | } else { 153 | elements = [elements]; 154 | } 155 | } 156 | for (var i = 0, n = elements.length, element; i < n; i++) { 157 | element = elements[i]; 158 | if (element instanceof HTMLElement) { 159 | if (element.children.length > 0) { 160 | upgradeElementsInternal(element.children); 161 | } 162 | upgradeElementInternal(element); 163 | } 164 | } 165 | } 166 | 167 | /** 168 | * Registers a class for future use and attempts to upgrade existing DOM. 169 | * @param {Object} config An object containing: 170 | * {constructor: Constructor, classAsString: string, cssClass: string} 171 | */ 172 | function registerInternal(config) { 173 | var newConfig = { 174 | 'classConstructor': config.constructor, 175 | 'className': config.classAsString, 176 | 'cssClass': config.cssClass, 177 | 'widget': config.widget === undefined ? true : config.widget, 178 | 'callbacks': [] 179 | }; 180 | 181 | registeredComponents_.forEach(function(item) { 182 | if (item.cssClass === newConfig.cssClass) { 183 | throw new Error('The provided cssClass has already been registered.'); 184 | } 185 | if (item.className === newConfig.className) { 186 | throw new Error('The provided className has already been registered'); 187 | } 188 | }); 189 | 190 | if (config.constructor.prototype 191 | .hasOwnProperty(componentConfigProperty_)) { 192 | throw new Error( 193 | 'MDL component classes must not have ' + componentConfigProperty_ + 194 | ' defined as a property.'); 195 | } 196 | 197 | var found = findRegisteredClass_(config.classAsString, newConfig); 198 | 199 | if (!found) { 200 | registeredComponents_.push(newConfig); 201 | } 202 | } 203 | 204 | /** 205 | * Allows user to be alerted to any upgrades that are performed for a given 206 | * component type 207 | * @param {string} jsClass The class name of the MDL component we wish 208 | * to hook into for any upgrades performed. 209 | * @param {!Function} callback The function to call upon an upgrade. This 210 | * function should expect 1 parameter - the HTMLElement which got upgraded. 211 | */ 212 | function registerUpgradedCallbackInternal(jsClass, callback) { 213 | var regClass = findRegisteredClass_(jsClass); 214 | if (regClass) { 215 | regClass.callbacks.push(callback); 216 | } 217 | } 218 | 219 | /** 220 | * Upgrades all registered components found in the current DOM. This is 221 | * automatically called on window load. 222 | */ 223 | function upgradeAllRegisteredInternal() { 224 | for (var n = 0; n < registeredComponents_.length; n++) { 225 | upgradeDomInternal(registeredComponents_[n].className); 226 | } 227 | } 228 | 229 | /** 230 | * Finds a created component by a given DOM node. 231 | * 232 | * @param {!Element} node 233 | * @return {*} 234 | */ 235 | function findCreatedComponentByNodeInternal(node) { 236 | for (var n = 0; n < createdComponents_.length; n++) { 237 | var component = createdComponents_[n]; 238 | if (component.element_ === node) { 239 | return component; 240 | } 241 | } 242 | } 243 | 244 | /** 245 | * Check the component for the downgrade method. 246 | * Execute if found. 247 | * Remove component from createdComponents list. 248 | * 249 | * @param {*} component 250 | */ 251 | function deconstructComponentInternal(component) { 252 | if (component && 253 | component[componentConfigProperty_] 254 | .classConstructor.prototype 255 | .hasOwnProperty(downgradeMethod_)) { 256 | component[downgradeMethod_](); 257 | var componentIndex = createdComponents_.indexOf(component); 258 | createdComponents_.splice(componentIndex, 1); 259 | 260 | var upgrades = component.element_.dataset.upgraded.split(','); 261 | var componentPlace = upgrades.indexOf( 262 | component[componentConfigProperty_].classAsString); 263 | upgrades.splice(componentPlace, 1); 264 | component.element_.dataset.upgraded = upgrades.join(','); 265 | 266 | var ev = document.createEvent('Events'); 267 | ev.initEvent('mdl-componentdowngraded', true, true); 268 | component.element_.dispatchEvent(ev); 269 | } 270 | } 271 | 272 | /** 273 | * Downgrade either a given node, an array of nodes, or a NodeList. 274 | * 275 | * @param {*} nodes 276 | */ 277 | function downgradeNodesInternal(nodes) { 278 | var downgradeNode = function(node) { 279 | deconstructComponentInternal(findCreatedComponentByNodeInternal(node)); 280 | }; 281 | if (nodes instanceof Array || nodes instanceof NodeList) { 282 | for (var n = 0; n < nodes.length; n++) { 283 | downgradeNode(nodes[n]); 284 | } 285 | } else if (nodes instanceof Node) { 286 | downgradeNode(nodes); 287 | } else { 288 | throw new Error('Invalid argument provided to downgrade MDL nodes.'); 289 | } 290 | } 291 | 292 | // Now return the functions that should be made public with their publicly 293 | // facing names... 294 | return { 295 | upgradeDom: upgradeDomInternal, 296 | upgradeElement: upgradeElementInternal, 297 | upgradeElements: upgradeElementsInternal, 298 | upgradeAllRegistered: upgradeAllRegisteredInternal, 299 | registerUpgradedCallback: registerUpgradedCallbackInternal, 300 | register: registerInternal, 301 | downgradeElements: downgradeNodesInternal 302 | }; 303 | })(); 304 | 305 | window.addEventListener('load', function() { 306 | 'use strict'; 307 | 308 | /** 309 | * Performs a "Cutting the mustard" test. If the browser supports the features 310 | * tested, adds a mdl-js class to the element. It then upgrades all MDL 311 | * components requiring JavaScript. 312 | */ 313 | if ('classList' in document.createElement('div') && 314 | 'querySelector' in document && 315 | 'addEventListener' in window && Array.prototype.forEach) { 316 | document.documentElement.classList.add('mdl-js'); 317 | componentHandler.upgradeAllRegistered(); 318 | } else { 319 | componentHandler.upgradeElement = 320 | componentHandler.register = function() {}; 321 | } 322 | }); 323 | 324 | function MaterialProgress(element) { 325 | 'use strict'; 326 | 327 | this.element_ = element; 328 | 329 | // Initialize instance. 330 | this.init(); 331 | } 332 | 333 | /** 334 | * Store constants in one place so they can be updated easily. 335 | * @enum {string | number} 336 | * @private 337 | */ 338 | MaterialProgress.prototype.Constant_ = { 339 | }; 340 | 341 | /** 342 | * Store strings for class names defined by this component that are used in 343 | * JavaScript. This allows us to simply change it in one place should we 344 | * decide to modify at a later date. 345 | * @enum {string} 346 | * @private 347 | */ 348 | MaterialProgress.prototype.CssClasses_ = { 349 | INDETERMINATE_CLASS: 'mdl-progress__indeterminate' 350 | }; 351 | 352 | MaterialProgress.prototype.setProgress = function(p) { 353 | 'use strict'; 354 | 355 | if (this.element_.classList.contains(this.CssClasses_.INDETERMINATE_CLASS)) { 356 | return; 357 | } 358 | 359 | this.progressbar_.style.width = p + '%'; 360 | }; 361 | 362 | MaterialProgress.prototype.setBuffer = function(p) { 363 | 'use strict'; 364 | 365 | this.bufferbar_.style.width = p + '%'; 366 | this.auxbar_.style.width = (100 - p) + '%'; 367 | }; 368 | 369 | /** 370 | * Initialize element. 371 | */ 372 | MaterialProgress.prototype.init = function() { 373 | 'use strict'; 374 | 375 | if (this.element_) { 376 | var el = document.createElement('div'); 377 | el.className = 'progressbar bar bar1'; 378 | this.element_.appendChild(el); 379 | this.progressbar_ = el; 380 | 381 | el = document.createElement('div'); 382 | el.className = 'bufferbar bar bar2'; 383 | this.element_.appendChild(el); 384 | this.bufferbar_ = el; 385 | 386 | el = document.createElement('div'); 387 | el.className = 'auxbar bar bar3'; 388 | this.element_.appendChild(el); 389 | this.auxbar_ = el; 390 | 391 | this.progressbar_.style.width = '0%'; 392 | this.bufferbar_.style.width = '100%'; 393 | this.auxbar_.style.width = '0%'; 394 | 395 | this.element_.classList.add('is-upgraded'); 396 | } 397 | }; 398 | 399 | /* 400 | * Downgrade the component 401 | */ 402 | MaterialProgress.prototype.mdlDowngrade_ = function() { 403 | 'use strict'; 404 | while (this.element_.firstChild) { 405 | this.element_.removeChild(this.element_.firstChild); 406 | } 407 | }; 408 | 409 | // The component registers itself. It can assume componentHandler is available 410 | // in the global scope. 411 | componentHandler.register({ 412 | constructor: MaterialProgress, 413 | classAsString: 'MaterialProgress', 414 | cssClass: 'mdl-js-progress', 415 | widget: true 416 | }); -------------------------------------------------------------------------------- /pyprint/themes/mdl/static/js/material-scrolltop.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Material-scrollTop 3 | * 4 | * Author: Bartholomej 5 | * Website: https://github.com/bartholomej/material-scrollTop 6 | * Docs: https://github.com/bartholomej/material-scrollTop 7 | * Repo: https://github.com/bartholomej/material-scrollTop 8 | * Issues: https://github.com/bartholomej/material-scrollTop/issues 9 | */ 10 | (function($) { 11 | function mScrollTop(element, settings) { 12 | var _ = this, 13 | breakpoint; 14 | var scrollTo = 0; 15 | 16 | _.btnClass = '.material-scrolltop'; 17 | _.revealClass = 'reveal'; 18 | _.btnElement = $(_.btnClass); 19 | 20 | _.initial = { 21 | revealElement: 'body', 22 | revealPosition: 'top', 23 | padding: 0, 24 | duration: 600, 25 | easing: 'swing', 26 | onScrollEnd: false 27 | }; 28 | 29 | _.options = $.extend({}, _.initial, settings); 30 | 31 | _.revealElement = $(_.options.revealElement); 32 | breakpoint = _.options.revealPosition !== 'bottom' ? _.revealElement.offset().top : _.revealElement.offset().top + _.revealElement.height(); 33 | scrollTo = element.offsetTop + _.options.padding; 34 | 35 | $(document).scroll(function() { 36 | if (breakpoint < $(document).scrollTop()) { 37 | _.btnElement.addClass(_.revealClass); 38 | } else { 39 | _.btnElement.removeClass(_.revealClass); 40 | } 41 | }); 42 | 43 | _.btnElement.click(function() { 44 | $('body').animate({ 45 | scrollTop: scrollTo 46 | }, _.options.duration, _.options.easing, _.options.onScrollEnd); 47 | return false; 48 | }); 49 | 50 | } 51 | 52 | $.fn.materialScrollTop = function() { 53 | var _ = this, 54 | opt = arguments[0], 55 | l = _.length, 56 | i = 0; 57 | if (typeof opt == 'object' || typeof opt == 'undefined') { 58 | _[i].materialScrollTop = new mScrollTop(_[i], opt); 59 | } 60 | return _; 61 | }; 62 | }(jQuery)); 63 | -------------------------------------------------------------------------------- /pyprint/themes/mdl/templates/archives.html: -------------------------------------------------------------------------------- 1 | {% if is_pjax %} 2 | {% extends "pjax_layout.html" %} 3 | {% else %} 4 | {% extends "layout.html" %} 5 | {% endif %} 6 | 7 | {% block body %} 8 |
    9 | {% for group in posts_groups %} 10 |
  • 11 |

    {{ group.year }}

    12 |
      13 | {% for post in group.posts %} 14 |
    • {{ post.title }}

    • 15 | {% endfor %} 16 |
    17 |
  • 18 | {% endfor %} 19 |
20 | {% endblock %} 21 | -------------------------------------------------------------------------------- /pyprint/themes/mdl/templates/diaries.html: -------------------------------------------------------------------------------- 1 | {% if is_pjax %} 2 | {% extends "pjax_layout.html" %} 3 | {% else %} 4 | {% extends "layout.html" %} 5 | {% endif %} 6 | 7 | {% block body %} 8 |
    9 | {% for diary in diaries %} 10 |
  • {{ diary.created_time }} / {{ diary.title }}

  • 11 | {% endfor %} 12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /pyprint/themes/mdl/templates/feed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ settings.username }} 4 | {{ settings.title }} 5 | {{ posts[0].created_time if posts }} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | http://{{ url }} 14 | 15 | {% for post in posts %} 16 | 17 | {{ post.title }} 18 | http://{{ url }}/posts/{{ post.title|urlencode }} 19 | http://{{ url }}/posts/{{ post.title|urlencode }} 20 | {{ post.created_time }} 21 | {% if post.password == "" or post.password == None %} 22 | 23 | {% else %} 24 | 25 | {% endif %} 26 | 27 | {% endfor %} 28 | 29 | -------------------------------------------------------------------------------- /pyprint/themes/mdl/templates/index.html: -------------------------------------------------------------------------------- 1 | {% if is_pjax %} 2 | {% extends "pjax_layout.html" %} 3 | {% else %} 4 | {% extends "layout.html" %} 5 | {% endif %} 6 | 7 | {% block body %} 8 | {% for post in data.posts %} 9 |
10 |

{{ post.title }}

11 | 14 | {% if post.password == "" or post.password == None %} 15 |
16 | {{ post.content|markdown }} 17 |
18 | 28 | {% else %} 29 |
30 | Password protected 31 |
32 | {% endif %} 33 | 34 |
35 | {% if not loop.last %} 36 |
37 | {% endif %} 38 | {% endfor %} 39 |
40 | ‹‹ Newer 41 | Older ›› 42 |
43 | {% endblock %} -------------------------------------------------------------------------------- /pyprint/themes/mdl/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ title }} - {{ settings.title }} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | {% block head %}{% endblock %} 17 | 18 | 19 | 20 |
21 |
22 |
23 | 44 |
45 |
46 |
47 |
48 | {% block body %} 49 | {% endblock %} 50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | 58 | 59 | 89 | 90 | -------------------------------------------------------------------------------- /pyprint/themes/mdl/templates/links.html: -------------------------------------------------------------------------------- 1 | {% if is_pjax %} 2 | {% extends "pjax_layout.html" %} 3 | {% else %} 4 | {% extends "layout.html" %} 5 | {% endif %} 6 | 7 | 8 | {% block body %} 9 | 31 | 32 | {% endblock %} 33 | -------------------------------------------------------------------------------- /pyprint/themes/mdl/templates/not_found.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block body %} 4 |
5 |

你在看哪里!?

6 | 7 |
8 | {% endblock %} -------------------------------------------------------------------------------- /pyprint/themes/mdl/templates/pjax_layout.html: -------------------------------------------------------------------------------- 1 | {{ title }} - {{ settings.title }} 2 | 3 | {% block body %} 4 | {% endblock %} -------------------------------------------------------------------------------- /pyprint/themes/mdl/templates/post.html: -------------------------------------------------------------------------------- 1 | {% if is_pjax %} 2 | {% extends "pjax_layout.html" %} 3 | {% else %} 4 | {% extends "layout.html" %} 5 | {% endif %} 6 | 7 | {% block body %} 8 |
9 |

{{ post.title }}

10 | 13 |
14 | {{ post.content|markdown }} 15 |
16 | 26 |
27 |
28 |
29 |
30 | {% endblock %} 31 | -------------------------------------------------------------------------------- /pyprint/themes/none/templates/diaries.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block body %} 4 |
    5 | {% for diary in diaries %} 6 |
  • 7 | {{ diary.title }} 8 | {{ diary.created_time }} 9 |
  • 10 | {% endfor %} 11 |
12 | {% endblock %} -------------------------------------------------------------------------------- /pyprint/themes/none/templates/feed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ settings.username }} 4 | {{ settings.title }} 5 | {{ posts[0].created_time if posts }} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | http://{{ url }} 14 | 15 | {% for post in posts %} 16 | 17 | {{ post.title }} 18 | http://{{ url }}/articles/{{ post.title }} 19 | http://{{ url }}/articles/{{ post.title }} 20 | {{ post.created_time }} 21 | 22 | 23 | {% endfor %} 24 | -------------------------------------------------------------------------------- /pyprint/themes/none/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block body %} 4 | {% for post in data.posts %} 5 |
6 | {{ post.title }} 7 |
 8 | 
 9 | Posted at {{ post.created_time }}
10 | ======================
11 | {{ post.content|markdown_image }}
12 | 
13 | 
14 |
------------------------------------------
15 | {% endfor %} 16 | << Newer 17 | Older >> 18 | {% endblock %} -------------------------------------------------------------------------------- /pyprint/themes/none/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ title }} - {{ settings.title }} 7 | 31 | 32 | 33 | 34 |

{{ settings.username }} - {{ settings.motto }}

35 |
36 | 37 |
------------------------------------------
38 | Posts 39 | Diary 40 | Links 41 | RSS 42 |
------------------------------------------
43 | {% block body %} 44 | {% endblock %} 45 |
------------------------------------------
46 | {{ settings.username }} © 2015 • All rights reserved 47 | 50 | 51 | -------------------------------------------------------------------------------- /pyprint/themes/none/templates/links.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | 4 | {% block body %} 5 |

My Friends

6 | 11 | {% endblock %} -------------------------------------------------------------------------------- /pyprint/themes/none/templates/not_found.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block body %} 4 | Baka 5 | {% endblock %} -------------------------------------------------------------------------------- /pyprint/themes/none/templates/post.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block body %} 4 |
5 | {{ post.title }} 6 |
 7 | 
 8 | Posted at {{ post.created_time }}
 9 | ======================
10 | {{ post.content|markdown_image }}
11 | 
12 | 
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /pyprint/utils.py: -------------------------------------------------------------------------------- 1 | import re 2 | import cgi 3 | from markdown import markdown as md 4 | 5 | 6 | class Storage(dict): 7 | def __getattr__(self, item): 8 | return self[item] 9 | 10 | def __setattr__(self, key, value): 11 | self[key] = value 12 | 13 | 14 | def get_host(url): 15 | return '/'.join(url.split('/')[2:-1]) 16 | 17 | 18 | def markdown(content): 19 | return md(content) 20 | 21 | 22 | def markdown_image(content): 23 | content = cgi.escape(content) 24 | return re.sub('!\[(.*?)\]\((.*?)\)', '\g<1>', content) 25 | 26 | 27 | def fix_lazy_load(content): 28 | return re.sub(r'(.+?)', '', content) 29 | -------------------------------------------------------------------------------- /pyprint/views/__init__.py: -------------------------------------------------------------------------------- 1 | from posts import ListPostsHandler, ListPostsByTagHandler, RetrievePostHandler, ArchiveHandler, FeedHandler 2 | from links import ListLinksHandler 3 | from others import AkarinHandler, NotFoundHandler, HitokotoHandler 4 | from background import SignInHandler, ManagePostHandler, AddLinkHandler, AddPostHandler 5 | from diaries import RetrieveDiaryHandler, ListDiariesHandler 6 | 7 | 8 | handlers = [ 9 | # posts.py 10 | (r'/', ListPostsHandler), 11 | (r'/page/([\d]+)?', ListPostsHandler), 12 | (r'/posts/(.*)', RetrievePostHandler), 13 | (r'/tags/(.*)', ListPostsByTagHandler), 14 | (r'/archives', ArchiveHandler), 15 | (r'/feed', FeedHandler), 16 | 17 | # diaries.py 18 | (r'/diaries', ListDiariesHandler), 19 | (r'/diaries/(.*)', RetrieveDiaryHandler), 20 | 21 | # links.py 22 | (r'/links', ListLinksHandler), 23 | 24 | # background 25 | (r'/login', SignInHandler), 26 | (r'/kamisama/posts', ManagePostHandler), 27 | (r'/kamisama/posts/add', AddPostHandler), 28 | (r'/kamisama/links', AddLinkHandler), 29 | 30 | # others.py 31 | (r'/akarin', AkarinHandler), 32 | (r'/hitokoto', HitokotoHandler), 33 | (r'/(.*)', NotFoundHandler), 34 | ] 35 | -------------------------------------------------------------------------------- /pyprint/views/background.py: -------------------------------------------------------------------------------- 1 | import tornado.web 2 | from datetime import date 3 | from sqlalchemy.orm.exc import NoResultFound 4 | 5 | from pyprint.handler import BaseHandler 6 | from pyprint.models import User, Link, Post 7 | 8 | 9 | class SignInHandler(BaseHandler): 10 | def get(self): 11 | return self.background_render('login.html') 12 | 13 | def post(self): 14 | username = self.get_argument('username', None) 15 | password = self.get_argument('password', None) 16 | 17 | if username and password: 18 | try: 19 | user = self.orm.query(User).filter(User.username == username).one() 20 | except NoResultFound: 21 | return self.redirect('/login') 22 | if user.check(password): 23 | self.set_secure_cookie('username', user.username) 24 | self.redirect('/kamisama/posts') 25 | 26 | return self.redirect('/login') 27 | 28 | 29 | class ManagePostHandler(BaseHandler): 30 | @tornado.web.authenticated 31 | def get(self): 32 | posts = self.orm.query(Post.title, Post.id).order_by(Post.id.desc()).all() 33 | self.background_render('posts.html', posts=posts) 34 | 35 | @tornado.web.authenticated 36 | def post(self): 37 | action = self.get_argument('action', None) 38 | if action == 'del': 39 | post_id = self.get_argument('id', 0) 40 | if post_id: 41 | post = self.orm.query(Post).filter(Post.id == post_id).one() 42 | self.orm.delete(post) 43 | self.orm.commit() 44 | 45 | 46 | class AddPostHandler(BaseHandler): 47 | @tornado.web.authenticated 48 | def get(self): 49 | self.background_render('add_post.html', post=None) 50 | 51 | @tornado.web.authenticated 52 | def post(self): 53 | title = self.get_argument('title', None) 54 | content = self.get_argument('content', None) 55 | tags = self.get_argument('tags', '').strip().split(',') 56 | if not title or not content: 57 | return self.redirect('/kamisama/posts/add') 58 | 59 | post = self.orm.query(Post.title).filter(Post.title == title).all() 60 | if post: 61 | return self.write('') 62 | self.orm.add(Post(title=title, content=content, created_time=date.today())) 63 | self.orm.commit() 64 | return self.redirect('/kamisama/posts') 65 | 66 | 67 | class AddLinkHandler(BaseHandler): 68 | @tornado.web.authenticated 69 | def get(self): 70 | links = self.orm.query(Link).all() 71 | self.background_render('links.html', links=links) 72 | 73 | @tornado.web.authenticated 74 | def post(self): 75 | action = self.get_argument('action', None) 76 | if action == 'add': 77 | name = self.get_argument('name', '') 78 | url = self.get_argument('url', '') 79 | if not name or not url: 80 | return self.redirect('/kamisama/links') 81 | self.orm.add(Link(name=name, url=url)) 82 | self.orm.commit() 83 | return self.redirect('/kamisama/links') 84 | 85 | elif action == 'del': 86 | link_id = self.get_argument('id', 0) 87 | if link_id: 88 | link = self.orm.query(Link).filter(Link.id == link_id).one() 89 | self.orm.delete(link) 90 | self.orm.commit() 91 | -------------------------------------------------------------------------------- /pyprint/views/diaries.py: -------------------------------------------------------------------------------- 1 | #coding: utf-8 2 | import tornado.web 3 | from sqlalchemy import and_ 4 | from sqlalchemy.orm.exc import NoResultFound 5 | from pyprint.handler import BaseHandler 6 | from pyprint.models import Post 7 | from pyprint.constants import DIARY 8 | 9 | 10 | class ListDiariesHandler(BaseHandler): 11 | def get(self): 12 | diaries = self.orm.query(Post.title, Post.created_time).filter(Post.type == DIARY)\ 13 | .order_by(Post.created_time.desc()).all() 14 | return self.render('diaries.html', title='Diaries', diaries=diaries) 15 | 16 | 17 | class RetrieveDiaryHandler(BaseHandler): 18 | def get(self, title): 19 | password = self.get_argument('pass', None) 20 | 21 | try: 22 | post = self.orm.query(Post).filter(and_(Post.title == title, Post.type == 'diary')).one() 23 | except NoResultFound: 24 | return self.redirect('/akarin') 25 | 26 | if post.password and not password == post.password: 27 | raise tornado.web.HTTPError(403, 'Password Protected') 28 | 29 | return self.render('post.html', title=post.title, post=post) 30 | -------------------------------------------------------------------------------- /pyprint/views/links.py: -------------------------------------------------------------------------------- 1 | from pyprint.handler import BaseHandler 2 | from pyprint.models import Link 3 | 4 | 5 | class ListLinksHandler(BaseHandler): 6 | def get(self): 7 | return self.render('links.html', title='Links & About', links=self.orm.query(Link).all()) -------------------------------------------------------------------------------- /pyprint/views/others.py: -------------------------------------------------------------------------------- 1 | import urllib2 2 | from pyprint.handler import BaseHandler 3 | 4 | 5 | class AkarinHandler(BaseHandler): 6 | def get(self): 7 | return self.render('not_found.html', title='404 Not Found') 8 | 9 | 10 | class NotFoundHandler(BaseHandler): 11 | def get(self, path): 12 | return self.redirect('/akarin') 13 | 14 | 15 | class HitokotoHandler(BaseHandler): 16 | def get(self): 17 | hitokoto_url = 'http://api.hitokoto.us/rand?encode=js&charset=utf-8' 18 | self.write(urllib2.urlopen(hitokoto_url).read()) 19 | -------------------------------------------------------------------------------- /pyprint/views/posts.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | import tornado.web 3 | 4 | from itertools import groupby 5 | 6 | from sqlalchemy.orm.exc import NoResultFound 7 | from sqlalchemy import and_ 8 | from pyprint.handler import BaseHandler 9 | from pyprint.models import Post, Tag 10 | from pyprint.utils import get_host 11 | from pyprint import constants 12 | 13 | from pyprint.settings import post_of_page 14 | 15 | 16 | class ListPostsHandler(BaseHandler): 17 | def get(self, page=1): 18 | page = int(page) if int(page) else 1 19 | 20 | posts = self.orm.query(Post).filter(Post.type == constants.POST)\ 21 | .order_by(Post.created_time.desc()).limit(post_of_page).offset( 22 | (page - 1) * post_of_page).all() 23 | 24 | return self.render('index.html', title=u'初心を忘れず', data={ 25 | 'preview': page - 1, 26 | 'next': page + 1, 27 | 'posts': posts 28 | }) 29 | 30 | 31 | class RetrievePostHandler(BaseHandler): 32 | def get(self, title): 33 | password = self.get_argument('pass', None) 34 | 35 | try: 36 | post = self.orm.query(Post).filter(and_(Post.title == title, Post.type == 'post')).one() 37 | except NoResultFound: 38 | return self.redirect('/akarin') 39 | 40 | if post.password and not password == post.password: 41 | raise tornado.web.HTTPError(403, 'Password Protected') 42 | 43 | return self.render('post.html', title=post.title, post=post) 44 | 45 | 46 | class ListPostsByTagHandler(BaseHandler): 47 | def get(self, slug): 48 | try: 49 | tag = self.orm.query(Tag).filter(Tag.slug == slug).one() 50 | except NoResultFound: 51 | return self.redirect('/akarin') 52 | 53 | posts = [post for post in tag.posts if post.type == constants.POST] 54 | return self.render('index.html', title='Tag: %s' % tag.slug, data={ 55 | 'preview': 0, 56 | 'next': 0, 57 | 'posts': posts, 58 | }) 59 | 60 | 61 | class ArchiveHandler(BaseHandler): 62 | def get(self): 63 | posts = self.orm.query(Post.title, Post.created_time).\ 64 | filter(Post.type == constants.POST).order_by(Post.created_time.desc()).all() 65 | 66 | posts_groups = [{'year': year, 'posts': list(posts)} for year, posts in 67 | groupby(posts, key=lambda p: p.created_time.year)] 68 | 69 | return self.render('archives.html', title='Archives', posts_groups=posts_groups) 70 | 71 | 72 | class FeedHandler(BaseHandler): 73 | def get(self): 74 | posts = self.orm.query(Post).filter(Post.type == constants.POST).order_by( 75 | Post.created_time.desc()).limit(3).all() 76 | headers = { 77 | 'Content-Type': 'application/xml', 78 | } 79 | return self.render('feed.xml', posts=posts, 80 | url=get_host(self.request.full_url()), headers=headers) 81 | -------------------------------------------------------------------------------- /requirement.txt: -------------------------------------------------------------------------------- 1 | tornado>=4.0 2 | sqlalchemy>=0.9.7 3 | jinja2>=2.7.3 4 | MySQL-python==1.2.5 5 | markdown==2.4.1 6 | --------------------------------------------------------------------------------