Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

merging with upstream

  • Loading branch information...
commit 9d3880b4ceb74060a5491a9668838dfdb5ef73fd 2 parents 522ca1e + 21d2eb5
Philip Stark hellerbarde authored
7 .gitignore
... ... @@ -1,4 +1,3 @@
1   -/settings.pyc
2   -/simple.db
3   -
4   -/settings.py
  1 +*.pyc
  2 +*.db
  3 +/settings.py
4 README.md
Source Rendered
@@ -12,6 +12,10 @@ Installation
12 12 Its quite simple. Go download Python 2.7+, Flask, Sqlalchemy and flask-sqlalchemy and you are good to go.
13 13 To create a settings file run create_config.py and enter some details, then run simple.py.
14 14
  15 +Example
  16 +============
  17 +You can see my blog running this software [here](http://tomforb.es).
  18 +
15 19 Screenshots
16 20 ===========
17 21 ![Admin](http://i.imgur.com/vWfOs.png)
0  REQUIRES → requirements.txt
File renamed without changes
66 simple.py
... ... @@ -1,6 +1,6 @@
1 1 from functools import wraps
2 2 import hashlib
3   -from flask import render_template, request, Response, Flask, flash, redirect, url_for, abort, jsonify, Response
  3 +from flask import render_template, request, Flask, flash, redirect, url_for, abort, jsonify, Response, make_response
4 4 import re
5 5 from unicodedata import normalize
6 6 from flaskext.sqlalchemy import SQLAlchemy
@@ -17,10 +17,11 @@
17 17 class Post(db.Model):
18 18 __tablename__ = "posts"
19 19 id = db.Column(db.Integer, primary_key=True)
20   - title = db.Column(db.String(), unique=True)
  20 + title = db.Column(db.String())
21 21 slug = db.Column(db.String(), unique=True)
22 22 text = db.Column(db.String(), default="")
23 23 draft = db.Column(db.Boolean(), index=True, default=True)
  24 + views = db.Column(db.Integer(), default=0)
24 25 created_at = db.Column(db.DateTime, index=True)
25 26 updated_at = db.Column(db.DateTime)
26 27
@@ -46,7 +47,7 @@ def _auth_decorator(*args, **kwargs):
46 47 @app.route("/")
47 48 def index():
48 49 page = request.args.get("page", 0, type=int)
49   - posts_master = db.session.query(Post).filter_by(draft=False).order_by(Post.created_at.asc())
  50 + posts_master = db.session.query(Post).filter_by(draft=False).order_by(Post.created_at.desc())
50 51 posts_count = posts_master.count()
51 52
52 53 posts = posts_master.limit(app.config["POSTS_PER_PAGE"]).offset(page*app.config["POSTS_PER_PAGE"]).all()
@@ -62,6 +63,9 @@ def view_post(post_id):
62 63 except Exception:
63 64 return abort(404)
64 65
  66 + db.session.query(Post).filter_by(id=post_id).update({Post.views:Post.views+1})
  67 + db.session.commit()
  68 +
65 69 return render_template("view.html", post=post)
66 70
67 71 @app.route("/<slug>")
@@ -71,8 +75,10 @@ def view_post_slug(slug):
71 75 except Exception:
72 76 return abort(404)
73 77
74   - pid = request.args.get("pid", "0")
  78 + db.session.query(Post).filter_by(slug=slug).update({Post.views:Post.views+1})
  79 + db.session.commit()
75 80
  81 + pid = request.args.get("pid", "0")
76 82 return render_template("view.html", post=post, pid=pid)
77 83
78 84 @app.route("/new", methods=["POST", "GET"])
@@ -100,11 +106,10 @@ def edit(id):
100 106 if request.method == "GET":
101 107 return render_template("edit.html", post=post)
102 108 else:
103   - title = request.form.get("post_title","")
104   - text = request.form.get("post_content","")
105   - post.title = title
106   - post.slug = slugify(post.title)
107   - post.text = text
  109 + if post.title != request.form.get("post_title", ""):
  110 + post.title = request.form.get("post_title","")
  111 + post.slug = slugify(post.title)
  112 + post.text = request.form.get("post_content","")
108 113 post.updated_at = datetime.datetime.now()
109 114
110 115 if any(request.form.getlist("post_draft", type=int)):
@@ -145,9 +150,9 @@ def save_post(id):
145 150 post = db.session.query(Post).filter_by(id=id).one()
146 151 except Exception:
147 152 return abort(404)
148   -
149   - post.title = request.form.get("title","")
150   - post.slug = slugify(post.title)
  153 + if post.title != request.form.get("title", ""):
  154 + post.title = request.form.get("title","")
  155 + post.slug = slugify(post.title)
151 156 post.text = request.form.get("content", "")
152 157 post.updated_at = datetime.datetime.now()
153 158 db.session.add(post)
@@ -166,28 +171,11 @@ def preview(id):
166 171
167 172 @app.route("/posts.rss")
168 173 def feed():
169   - def generate_feed():
170   - yield '<?xml version="1.0" encoding="UTF-8"?>\n'
171   - yield '<rss version="2.0">\n'
172   - yield ' <channel>\n'
173   - yield ' <title>%s</title>\n'%app.config["BLOG_TITLE"]
174   - yield ' <description>%s</title>\n'%app.config["BLOG_TAGLINE"]
175   - yield ' <link>%s</link>\n'%app.config["BLOG_URL"]
176   - for post in db.session.query(Post).filter_by(draft=False).order_by(Post.created_at.desc()).all():
177   - yield " <item>\n"
178   - yield " <title>%s</title>\n"%post.title
179   - if post.text:
180   - yield " <description>%s</description>\n"%post.render_content()
181   - else:
182   - yield " <description>No content</description>\n"
183   - yield " <pubDate>%s</pubDate>\n"%post.created_at.strftime('%B %d, %Y')
184   - yield " <link>%s</link>\n"%("%s/%s"%(app.config["BLOG_URL"], post.slug ))
185   - yield " <guid>%s</guid>\n"%("%s/%s"%(app.config["BLOG_URL"], post.slug ))
186   - yield " </item>\n"
187   - yield " </channel>\n"
188   - yield "</rss>"
189   -
190   - return Response(generate_feed(), mimetype="application/rss+xml")
  174 + posts = db.session.query(Post).filter_by(draft=False).order_by(Post.created_at.desc()).limit(10).all()
  175 +
  176 + r = make_response(render_template('index.xml', posts=posts))
  177 + r.mimetype = "application/xml"
  178 + return r
191 179
192 180 def slugify(text, delim=u'-'):
193 181 """Generates an slightly worse ASCII-only slug."""
@@ -196,8 +184,14 @@ def slugify(text, delim=u'-'):
196 184 word = normalize('NFKD', unicode(word)).encode('ascii', 'ignore')
197 185 if word:
198 186 result.append(word)
199   - return unicode(delim.join(result))
200   -
  187 + slug = unicode(delim.join(result))
  188 + # This could have issues if a post is marked as draft, then live, then draft, then live and there are > 1 posts
  189 + # with the same slug. Oh well.
  190 + _c = db.session.query(Post).filter_by(slug=slug).count()
  191 + if _c > 0:
  192 + return "%s%s%s"%(slug, delim, _c)
  193 + else:
  194 + return slug
201 195
202 196 if __name__ == "__main__":
203 197 app.run()
71 static/css/posts.css
@@ -21,27 +21,44 @@ body {
21 21 color: #222; }
22 22
23 23 body, textarea, pre, input {
24   - font-family: 'Lato', Helvetica, sans-serif;
25   - line-height: 1.8em;
26   - font-size: 16px;
27   - font-weight: 400; }
  24 + font-family: 'Lato', Helvetica, sans-serif;
  25 + line-height: 1.8em;
  26 + font-size: 15px;
  27 + font-weight: 400; }
28 28
29 29 h1, h2, h3, h4, h5 {
30 30 font-weight: 900;
31 31 word-wrap: break-word;
32 32 line-height: 1.3em; }
33 33
34   -h1, .expandingArea.text-title pre, .expandingArea.text-title textarea {
35   - font-weight: 900;
36   - font-size: 35px; }
  34 +h1,
  35 +.expandingArea.text-title pre,
  36 +.expandingArea.text-title textarea {
  37 + font-weight: 900;
  38 + font-size: 30px; }
37 39
38 40 p {
39 41 color: #555; }
40 42
41   -a, a:visited a:active {
42   - color: #000;
43   - text-decoration: none;
44   - border-bottom: 1px solid #ddd; }
  43 +code.prettyprint {
  44 + line-height: 1.2em;
  45 +}
  46 +
  47 +
  48 +div.bottom_right {
  49 + display: block;
  50 + position: absolute;
  51 + bottom: 0;
  52 + right: 0;
  53 + width: 350px;
  54 +}
  55 +
  56 +a,
  57 +a:visited
  58 +a:active {
  59 + color: #000;
  60 + text-decoration: none;
  61 + border-bottom: 1px solid #ddd; }
45 62
46 63 a:hover {
47 64 color: red; }
@@ -300,10 +317,11 @@ label {
300 317 #admin .col ul li h3 a {
301 318 border: none; }
302 319 #admin textarea, #admin pre {
303   - margin: 0;
304   - padding: 0;
305   - outline: 0;
306   - border: 0; }
  320 + border: 1px solid rgba(128,128,128,.3);
  321 + margin: 0;
  322 + padding: 0;
  323 + outline: 0;
  324 + border: 0; }
307 325 #admin .expandingArea {
308 326 position: relative; }
309 327 #admin .expandingArea > textarea, #admin .expandingArea > pre {
@@ -311,17 +329,18 @@ label {
311 329 white-space: pre-wrap;
312 330 word-wrap: break-word; }
313 331 #admin .expandingArea > textarea {
314   - /* The border-box box model is used to allow
315   - * padding whilst still keeping the overall width
316   - * at exactly that of the containing element.
317   - */
318   - -webkit-box-sizing: border-box;
319   - -moz-box-sizing: border-box;
320   - -ms-box-sizing: border-box;
321   - box-sizing: border-box;
322   - width: 100%;
323   - /* This height is used when JS is disabled */
324   - height: 100px; }
  332 + /* The border-box box model is used to allow
  333 + * padding whilst still keeping the overall width
  334 + * at exactly that of the containing element.
  335 + */
  336 + overflow: hidden;
  337 + -webkit-box-sizing: border-box;
  338 + -moz-box-sizing: border-box;
  339 + -ms-box-sizing: border-box;
  340 + box-sizing: border-box;
  341 + width: 100%;
  342 + /* This height is used when JS is disabled */
  343 + height: 100px; }
325 344 #admin .expandingArea.active > textarea {
326 345 /* Hide any scrollbars */
327 346 overflow: hidden;
461 static/css/posts.css.scss
... ... @@ -1,461 +0,0 @@
1   -/* shamelessly stolen from https://github.com/NateW/obtvse/blob/master/app/assets/stylesheets/posts.css.scss */
2   -$linkhover: red;
3   -
4   -
5   -aside {position:relative; display:block;}
6   -ul {list-style-type:none;}
7   -.hide {visibility:hidden; height:1px; clip:rect(0 0 0 0); position:absolute;}
8   -input, textarea {outline:none; background:none;}
9   -
10   -body {
11   - background: #fff;
12   - color: #222;
13   -}
14   -
15   -body, textarea, pre, input {
16   - font-family: 'Lato', Helvetica, sans-serif;
17   - line-height: 1.8em;
18   - font-size: 16px;
19   - font-weight: 400;
20   -}
21   -
22   -h1,h2,h3,h4,h5 {
23   - font-weight: 900;
24   - word-wrap: break-word;
25   - line-height: 1.3em;
26   -}
27   -
28   -h1,
29   -.expandingArea.text-title pre,
30   -.expandingArea.text-title textarea {
31   - font-weight: 900;
32   - font-size: 35px;
33   -}
34   -
35   -p {
36   - color: #555;
37   -}
38   -
39   -a,
40   -a:visited
41   -a:active {
42   - color: #000;
43   - text-decoration: none;
44   - border-bottom: 1px solid #ddd;
45   -}
46   -
47   -a:hover {
48   - color: $linkhover;
49   -}
50   -
51   -header {
52   - width: 162px;
53   - border-right: 1px solid #DDD;
54   - position: fixed;
55   - top: 0;
56   - bottom: 0;
57   - padding: 20px 40px;
58   -
59   -span {
60   - color: #888;
61   - font-weight: 500;
62   -
63   -&.powered-by {
64   - position: absolute;
65   - bottom: 20px;
66   - font-size: 11px;
67   -}
68   - }
69   -
70   -ul {
71   - padding: 0;
72   - margin: 50px 0;
73   -}
74   -
75   -li {
76   - margin: 0 0 3px 0;
77   -
78   -a {
79   - padding: 2px 0;
80   - color: #888;
81   - border-bottom: 2px solid #eee;
82   -
83   -&:hover {
84   - border-color: #777;
85   - color: #444;
86   -}
87   - }
88   - }
89   - }
90   -
91   -#container {
92   - margin-left: 243px;
93   - position: relative;
94   -
95   -time {
96   - display: block;
97   - padding: 20px 0 20px 50px;
98   - text-transform: uppercase;
99   - font-weight: 900;
100   - font-size: 12px;
101   - border-bottom: 1px solid #ddd;
102   -}
103   - }
104   -
105   -#content {
106   -section {
107   - padding: 26px 0 40px 50px;
108   - border-bottom: 1px solid #ddd;
109   - position: relative;
110   -}
111   -
112   -h1.aside {
113   - font-size: 18px;
114   -}
115   - }
116   -
117   -.show #content section {
118   - border-bottom: none;
119   -}
120   -
121   -code {
122   - font-size: 13px;
123   - background: #F2F2F2;
124   - padding: 20px;
125   - margin: 20px;
126   - display: block;
127   -}
128   -
129   -.contain,
130   -#new_post, .edit_post {
131   - width: 580px;
132   -}
133   -
134   -.contain img {
135   - max-width: 100%;
136   - height: auto;
137   -}
138   -
139   -#new_post, .edit_post {
140   - padding: 88px 0;
141   - margin: 0 auto;
142   -}
143   -
144   -fieldset.markdown {
145   - position: relative;
146   - border: none;
147   - margin: 0;
148   - padding: 0;
149   -}
150   -
151   -.markdown::before {
152   - display: block;
153   - content: "";
154   - width: 39px;
155   - height: 24px;
156   - position: absolute;
157   - top: 4px;
158   - left: -60px;
159   - background: url(/assets/markdown.png) no-repeat top left;
160   -}
161   -
162   -#post_title {
163   - width: 100%;
164   - border: none;
165   - background: none;
166   - line-height: 45px;
167   - margin: 0 0 20px 0;
168   -}
169   -
170   -#post_content {
171   - border: none;
172   - width: 100%;
173   - position: relative;
174   - margin: 0 0 80px 0;
175   -}
176   -
177   -#publish-bar {
178   - position: fixed;
179   - bottom: 0;
180   - left: 0;
181   - background: #222;
182   - color: #fff;
183   - width: 100%;
184   - text-align: center;
185   - padding: 20px 0;
186   -
187   -.contain {
188   - margin: 0 auto;
189   - width: 700px;
190   -}
191   - }
192   -
193   -#publish-bar input[type=submit],
194   -#publish-bar a,
195   -.button {
196   - display: inline-block;
197   - background: #000;
198   - padding: 10px;
199   - font-weight: bold;
200   - border: none;
201   - color: #fff;
202   - border-radius: 5px;
203   - -moz-border-radius: 5px;
204   - -webkit-border-radius: 5px;
205   -}
206   -
207   -.button.secondary {
208   - padding: 0 5px;
209   - background: #aaa;
210   - font-size: 12px;
211   -}
212   -
213   -#publish-bar input[type=submit]:hover,
214   -#publish-bar a:hover,
215   -.col h1 a:hover,
216   -.col h2 a:hover,
217   -.button:hover,
218   -.button.secondary:hover {
219   - background: $linkhover;
220   - color: #fff;
221   -}
222   -
223   -.button.space-top {
224   - margin-top: 100px;
225   -}
226   -
227   -.left {
228   - float: left;
229   -}
230   -
231   -.right {
232   - float: right;
233   -}
234   -
235   -.actions {
236   - position: absolute;
237   - top: 10px;
238   - right: 10px;
239   - font-size: 12px;
240   - margin: 0;
241   - padding: 0;
242   -}
243   -
244   -.actions li {
245   - display: inline-block;
246   - margin: 0 10px 0 0;
247   -}
248   -
249   -label {
250   - font-size: 20px;
251   - color: #fff;
252   - font-weight: bold;
253   - margin: 0 4px 0 15px;
254   -}
255   -
256   -#post_draft {
257   - position: relative;
258   - margin: 0 20px 0 0;
259   -}
260   -
261   -.admin-links {
262   - position: absolute;
263   - text-align: right;
264   - top: 18px;
265   - right: 20px;
266   - margin: 0;
267   -
268   -li {float: left; margin-left: 6px;}
269   -a {float: left;}
270   - }
271   -
272   -.notice {
273   - background: lightYellow;
274   - width: 100%;
275   - display: block;
276   - text-align: center;
277   - padding: 6px 0;
278   -}
279   -
280   -#admin {
281   - width: 808px;
282   - margin: 0 auto;
283   - position: relative;
284   -
285   -#drafts {
286   - float: left;
287   - border: 4px solid #000;
288   - border-top: none;
289   - background: #fff;
290   - margin: 0 0 20px 0;
291   - padding-top: 10px;
292   -
293   -form {
294   - margin: 20px 0 20px -20px;
295   - padding: 0 0 0 20px;
296   - border-left: 4px solid lightblue;
297   -}
298   -
299   -#post_title {
300   - width: 350px;
301   - font-size: 16px;
302   - font-weight: 400;
303   - margin: 0;
304   - border-bottom: 1px solid #ddd;
305   -}
306   - }
307   -
308   -#published {
309   - float: right;
310   -
311   -h2 {color: #999;}
312   -h2 a {margin-top: -2px;}
313   - }
314   -
315   -.col h1,
316   -.col h2 {
317   - position: relative;
318   - text-transform: uppercase;
319   -}
320   -
321   -.col h1 a,
322   -.col h2 a {
323   - position: absolute;
324   - top: 0;
325   - right: 0;
326   - font-size: 12px;
327   - padding: 2px 10px;
328   - line-height: 2.7em;
329   - margin: 5px 0 0;
330   -}
331   -
332   -.col {
333   - width: 360px;
334   - padding: 20px;
335   -
336   -h2 a {
337   - background: #999;
338   -
339   -&:hover {
340   - background: $linkhover;
341   -}
342   - }
343   -
344   -ul {
345   - padding: 0;
346   -
347   -li {
348   - border-bottom: 1px solid #ddd;
349   - padding: 15px;
350   - position: relative;
351   -
352   -&:hover .links {
353   - visibility: visible;
354   -}
355   -
356   -.links {
357   - position: absolute;
358   - right: 0;
359   - top: 14px;
360   - background: #fff;
361   - padding: 1px 8px;
362   - visibility: hidden;
363   -
364   -a {
365   - color: #999;
366   - border-radius: 5px;
367   - -moz-border-radius: 5px;
368   - -webkit-border-radius: 5px;
369   -
370   -&:hover {
371   - color: $linkhover;
372   -}
373   - }
374   - }
375   -
376   -h3 {
377   - margin: 0;
378   - font-size: 16px;
379   - max-width: 100%;
380   - text-overflow: ellipsis;
381   - overflow: hidden;
382   -
383   -a {
384   - border: none;
385   -}
386   - }
387   - }
388   - }
389   - }
390   -
391   -textarea,pre {
392   - margin: 0;
393   - padding: 0;
394   - outline: 0;
395   - border: 0;
396   -}
397   -
398   -.expandingArea {
399   - position: relative;
400   -}
401   -
402   -.expandingArea > textarea,
403   -.expandingArea > pre {
404   - background: transparent;
405   - white-space: pre-wrap;
406   - word-wrap: break-word;
407   -}
408   -
409   -.expandingArea > textarea {
410   - /* The border-box box model is used to allow
411   - * padding whilst still keeping the overall width
412   - * at exactly that of the containing element.
413   - */
414   - -webkit-box-sizing: border-box;
415   - -moz-box-sizing: border-box;
416   - -ms-box-sizing: border-box;
417   - box-sizing: border-box;
418   - width: 100%;
419   - /* This height is used when JS is disabled */
420   - height: 100px;
421   -}
422   -
423   -.expandingArea.active > textarea {
424   - /* Hide any scrollbars */
425   - overflow: hidden;
426   - position: absolute;
427   - top: 0;
428   - left: 0;
429   - height: 100%;
430   - /* Remove WebKit user-resize widget */
431   - resize: none;
432   -}
433   -
434   -.expandingArea > pre {
435   - display: none;
436   -}
437   -
438   -.expandingArea.active > pre {
439   - display: block;
440   - /* Hide the text; just using it for sizing */
441   - visibility: hidden;
442   -}
443   - }
444   -
445   -.admin-view {
446   - font-size: 11px;
447   - margin: 0 10px 2px 0;
448   - font-weight: 900;
449   - text-transform: uppercase;
450   -}
451   -
452   -nav.pagination {
453   - position: absolute;
454   - bottom: 20px;
455   - right: 20px;
456   - font-size: 16px;
457   - font-weight: 900;
458   - text-transform: uppercase;
459   - margin: 0;
460   - padding: 0;
461   -}
83 static/js/functions.js
... ... @@ -1,23 +1,44 @@
1   -function makeExpandingArea(container) {
2   - var area = container.querySelector('textarea'),
3   - span = container.querySelector('span');
4   -
5   - if (area.addEventListener) {
6   - area.addEventListener('input', function() {
7   - span.textContent = area.value;
8   - }, false);
9   - span.textContent = area.value;
10   - } else if (area.attachEvent) {
11   - // IE8 compatibility
12   - area.attachEvent('onpropertychange', function() {
13   - span.innerText = area.value;
14   - });
15   - span.innerText = area.value;
16   - }
17   -
18   - // Enable extra CSS
19   - container.className += ' active';
20   -}
  1 +// 100% stolen from yiransheng/simple
  2 +$.fn.autogrow = function(options) {
  3 +
  4 + this.filter('textarea').each(function() {
  5 +
  6 + var $this = $(this),
  7 + minHeight = $this.height(),
  8 + lineHeight = $this.css('lineHeight');
  9 +
  10 + var shadow = $('<div></div>').css({
  11 + position: 'absolute',
  12 + top: -10000,
  13 + left: -10000,
  14 + width: $(this).width(),
  15 + fontSize: $this.css('fontSize'),
  16 + fontFamily: $this.css('fontFamily'),
  17 + lineHeight: $this.css('lineHeight'),
  18 + resize: 'none'
  19 + }).appendTo(document.body);
  20 +
  21 + var update = function() {
  22 +
  23 + var val = this.value.replace(/</g, '&lt;')
  24 + .replace(/>/g, '&gt;')
  25 + .replace(/&/g, '&amp;')
  26 + .replace(/\n/g, '<br/>');
  27 +
  28 + shadow.html(val);
  29 + $(this).css('height', Math.max(shadow.height() + 60, minHeight));
  30 + }
  31 +
  32 + $(this).change(update).keyup(update).keydown(update);
  33 +
  34 + update.apply(this);
  35 +
  36 + });
  37 +
  38 + return this;
  39 +
  40 +};
  41 +
21 42
22 43 function issueSaveAjax(id, redirect){
23 44 var ptitle = $("#post_title").val();
@@ -38,25 +59,5 @@ function issueSaveAjax(id, redirect){
38 59 }
39 60
40 61 $(function() {
41   - var textarea = document.getElementById("post_content");
42   -
43   - if (textarea) {
44   - textarea.onkeydown = function() {
45   - textarea.style.height = ""; /* Reset the height*/
46   - textarea.style.height = textarea.scrollHeight + "px";
47   - };
48   - }
  62 + $('textarea').autogrow();
49 63 });
50   -
51   -$(function() {
52   - // Auto-expanding height for editor textareas
53   - var areas = document.querySelectorAll('.expandingArea');
54   - var l = areas.length;
55   -
56   - while (l--) {
57   - makeExpandingArea(areas[l]);
58   - }
59   -
60   - // Set minimum height of content textarea
61   - $('#post_content').css('min-height', $(window).height() - $('#post_title').height() - 130);
62   -});
1  templates/admin_template.html
@@ -8,6 +8,7 @@
8 8 <link href='http://fonts.googleapis.com/css?family=Lato:300,900' rel='stylesheet' type='text/css' />
9 9 <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
10 10 <script src="https://github.com/rails/jquery-ujs/raw/master/src/rails.js"></script>
  11 + {% block head %}{% endblock %}
11 12 </head>
12 13
13 14 <body class="admin">
18 templates/edit.html
... ... @@ -1,17 +1,29 @@
1 1 {% extends "admin_template.html" %}
2 2
  3 +{% block head %}
  4 + {% if post.draft %}
  5 + <script type="text/javascript">
  6 + function SaveTick(){
  7 + issueSaveAjax({{ post.id }}, false);
  8 + setTimeout("SaveTick()", 10000)
  9 + }
  10 + $(document).ready(function(){
  11 + setTimeout("SaveTick();", 10000);
  12 + })
  13 + </script>
  14 + {% endif %}
  15 +{% endblock %}
  16 +
3 17 {% block content %}
4 18
5 19 <form accept-charset="UTF-8" action="" class="edit_post" id="edit_post_{{ post.id }}" method="post">
6 20 <div class="contain">
7 21
8 22 <div class="expandingArea text-title">
9   - <pre><span></span><br></pre>
10 23 <textarea cols="40" id="post_title" name="post_title" placeholder="Title here" rows="1">{{ post.title }}</textarea>
11 24 </div>
12 25 <fieldset class="markdown">
13 26 <div class="expandingArea text-content">
14   - <pre><span></span><br></pre>
15 27 <textarea cols="40" id="post_content" name="post_content" placeholder="Write post here" rows="20">{{ post.text }}</textarea>
16 28 </div>
17 29 </fieldset>
@@ -26,7 +38,7 @@
26 38 <label for="post_draft">Draft</label>
27 39 <input name="post_draft" type="hidden" value="0" /><input id="post_draft" name="post_draft" type="checkbox" value="1" {% if post.draft %}checked{% endif %} />
28 40 {% if post.draft %}
29   - <a href onclick="issueSaveAjax({{ post.id }}, true)" target="_blank">Preview</a>
  41 + <a href="#" onclick="issueSaveAjax({{ post.id }}, true); return false;" target="_blank">Preview</a>
30 42 {% else %}
31 43 <a href="{{ url_for('view_post_slug', slug=post.slug) }}" target="_blank">View live</a>
32 44 {% endif %}
18 templates/index.xml
... ... @@ -0,0 +1,18 @@
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<rss version="2.0">
  3 + <channel>
  4 + <title>{{ config.BLOG_TITLE }}</title>
  5 + <description>{{ config.BLOG_TAGLINE }}</description>
  6 + <link>{{ config.BLOG_URL }}</link>
  7 + {% for post in posts %}
  8 + {% set p_url=config.BLOG_URL + url_for('view_post_slug', slug=post.slug) %}
  9 + <item>
  10 + <title>{{ post.title }}</title>
  11 + <description>{{ post.render_content() }}</description>
  12 + <pubDate>{{ post.created_at.strftime('%b %d, %Y') }}</pubDate>
  13 + <link>{{ p_url }}</link>
  14 + <guid>{{ p_url }}</guid>
  15 + </item>
  16 + {% endfor %}
  17 + </channel>
  18 +</rss>
12 templates/layout.html
@@ -7,9 +7,11 @@
7 7 <meta name="author" content="{{ config.AUTHOR }}">
8 8 <link href="{{ url_for('feed') }}" rel="alternate" title="RSS" type="application/rss+xml" />
9 9 <link href='http://fonts.googleapis.com/css?family=Lato:300,900' rel='stylesheet' type='text/css' />
  10 + <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" rel="stylesheet" type="text/css">
  11 + <script src="http://cdnjs.cloudflare.com/ajax/libs/prettify/188.0.0/prettify.js" type="text/javascript"></script>
10 12 </head>
11 13
12   -<body>
  14 +<body onload="prettyPrint()">
13 15 <header>
14 16 <h1><a href="{{ url_for('index') }}">{{ config.BLOG_TITLE }}</a></h1>
15 17 <span>{{ config.BLOG_TAGLINE }}</span>
@@ -20,7 +22,15 @@
20 22 {% if config.CONTACT_EMAIL %}
21 23 <li><a href="mailto:{{ config.CONTACT_EMAIL }}?subject:Howdy">Email me</a></li>
22 24 {% endif %}
  25 + {% if config.TWITTER_HANDLE %}
  26 + <li><a href="https://twitter.com/{{ config.TWITTER_HANDLE }}/">Twitter</a></li>
  27 + {% endif %}
  28 + {% if config.GOOGLE_PLUS_PROFILE %}
  29 + <li><a href="https://plus.google.com/{{ config.GOOGLE_PLUS_PROFILE }}/posts">Google+</a></li>
  30 + {% endif %}
  31 +
23 32 <li><a href="{{ url_for('feed') }}">Feed</a></li>
  33 + {% block sidebar %}{% endblock %}
24 34 </ul>
25 35 <span class="powered-by">
26 36 Powered by <a href="http://github.com/orf/simple">Simple</a>,
4 templates/post_preview.html
@@ -7,9 +7,11 @@
7 7 <meta name="author" content="{{ config.AUTHOR }}">
8 8 <link href="/posts.rss" rel="alternate" title="RSS" type="application/rss+xml" />
9 9 <link href='http://fonts.googleapis.com/css?family=Lato:300,900' rel='stylesheet' type='text/css' />
  10 + <link href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" rel="stylesheet" type="text/css">
  11 + <script src="http://cdnjs.cloudflare.com/ajax/libs/prettify/188.0.0/prettify.js" type="text/javascript"></script>
10 12 </head>
11 13
12   - <body style="margin:10px 50px;">
  14 + <body style="margin:10px 50px;" onload="prettyPrint()">
13 15 <div>
14 16 <div id="content">
15 17 <div class="post contain">
5 templates/view.html
@@ -2,6 +2,11 @@
2 2
3 3 {% block title %}{{ post.title }} - {{ config.BLOG_TITLE }}{% endblock %}
4 4
  5 +{% block sidebar %}
  6 + <br />
  7 + Views: {{ post.views }}
  8 +{% endblock %}
  9 +
5 10 {% block content %}
6 11 <section id="post-{{ post.id }}">
7 12 <div class="post contain">

0 comments on commit 9d3880b

Please sign in to comment.
Something went wrong with that request. Please try again.