@@ -0,0 +1,3 @@ | |||||
{ | |||||
"directory": "realms/static/vendor" | |||||
} |
@@ -1,5 +1,8 @@ | |||||
.vagrant | .vagrant | ||||
.idea | .idea | ||||
.webassets-cache | |||||
*.pyc | *.pyc | ||||
packed-*.js | |||||
config.py | config.py | ||||
config.sls | |||||
config.sls | |||||
realms/static/vendor |
@@ -0,0 +1,16 @@ | |||||
{ | |||||
"name": "realms", | |||||
"version": "0.1.1", | |||||
"dependencies": { | |||||
"components-bootstrap": "3.0.0", | |||||
"jquery": "1.9.1", | |||||
"components-underscore": "~1.5.1", | |||||
"requirejs": "~2.1.8", | |||||
"highlightjs": "~7.3.0", | |||||
"handlebars": "~1.0.0", | |||||
"components-font-awesome": "~3.2.1", | |||||
"showdown": "~0.3.1", | |||||
"keymaster": "madrobby/keymaster", | |||||
"ace": "~1.0.0" | |||||
} | |||||
} |
@@ -6,7 +6,7 @@ from threading import Lock | |||||
import rethinkdb as rdb | import rethinkdb as rdb | ||||
from flask import Flask, request, render_template, url_for, redirect, flash | from flask import Flask, request, render_template, url_for, redirect, flash | ||||
from flask.ext.login import LoginManager, login_required | from flask.ext.login import LoginManager, login_required | ||||
from flask.ext.assets import Environment | |||||
from flask.ext.assets import Environment, Bundle | |||||
from recaptcha.client import captcha | from recaptcha.client import captcha | ||||
from werkzeug.routing import BaseConverter | from werkzeug.routing import BaseConverter | ||||
@@ -18,10 +18,18 @@ from models import Site, User, CurrentUser | |||||
from ratelimit import get_view_rate_limit, ratelimiter | from ratelimit import get_view_rate_limit, ratelimiter | ||||
from services import db | from services import db | ||||
# Flask instance container | |||||
instances = {} | instances = {} | ||||
# Flask extension objects | |||||
login_manager = LoginManager() | |||||
assets = Environment() | |||||
class SubdomainDispatcher(object): | class SubdomainDispatcher(object): | ||||
""" | |||||
Application factory | |||||
""" | |||||
def __init__(self, domain, create_app): | def __init__(self, domain, create_app): | ||||
self.domain = domain | self.domain = domain | ||||
self.create_app = create_app | self.create_app = create_app | ||||
@@ -44,6 +52,9 @@ class SubdomainDispatcher(object): | |||||
def init_db(dbname): | def init_db(dbname): | ||||
""" | |||||
Assures DB has minimal setup | |||||
""" | |||||
if not dbname in rdb.db_list().run(db): | if not dbname in rdb.db_list().run(db): | ||||
print "Creating DB %s" % dbname | print "Creating DB %s" % dbname | ||||
rdb.db_create(dbname).run(db) | rdb.db_create(dbname).run(db) | ||||
@@ -65,6 +76,9 @@ def init_db(dbname): | |||||
class RegexConverter(BaseConverter): | class RegexConverter(BaseConverter): | ||||
""" | |||||
Enables Regex matching on endpoints | |||||
""" | |||||
def __init__(self, url_map, *items): | def __init__(self, url_map, *items): | ||||
super(RegexConverter, self).__init__(url_map) | super(RegexConverter, self).__init__(url_map) | ||||
self.regex = items[0] | self.regex = items[0] | ||||
@@ -85,7 +99,17 @@ def validate_captcha(): | |||||
return response.is_valid | return response.is_valid | ||||
def format_subdomain(s): | |||||
s = s.lower() | |||||
s = to_canonical(s) | |||||
if s in ['www']: | |||||
# Not allowed | |||||
s = "" | |||||
return s | |||||
def make_app(subdomain): | def make_app(subdomain): | ||||
subdomain = format_subdomain(subdomain) | |||||
if subdomain and not Wiki.is_registered(subdomain): | if subdomain and not Wiki.is_registered(subdomain): | ||||
return redirect("http://%s/_new/?site=%s" % (config.hostname, subdomain)) | return redirect("http://%s/_new/?site=%s" % (config.hostname, subdomain)) | ||||
return create_app(subdomain) | return create_app(subdomain) | ||||
@@ -100,7 +124,6 @@ def create_app(subdomain=None): | |||||
app.session_interface = RedisSessionInterface() | app.session_interface = RedisSessionInterface() | ||||
app.url_map.converters['regex'] = RegexConverter | app.url_map.converters['regex'] = RegexConverter | ||||
login_manager = LoginManager() | |||||
login_manager.init_app(app) | login_manager.init_app(app) | ||||
login_manager.login_view = 'login' | login_manager.login_view = 'login' | ||||
@@ -108,9 +131,26 @@ def create_app(subdomain=None): | |||||
def load_user(user_id): | def load_user(user_id): | ||||
return CurrentUser(user_id) | return CurrentUser(user_id) | ||||
assets = Environment(app) | |||||
assets.url = app.static_url_path | |||||
assets.directory = app.static_folder | |||||
assets.init_app(app) | |||||
if 'js_common' not in assets._named_bundles: | |||||
js = Bundle('vendor/jquery/jquery.js', | |||||
'vendor/components-underscore/underscore.js', | |||||
'vendor/components-bootstrap/js/bootstrap.js', | |||||
'vendor/handlebars/handlebars.js', | |||||
'vendor/showdown/src/showdown.js', | |||||
'js/html-sanitizer-minified.js', | |||||
'js/wmd.js', | |||||
'vendor/highlightjs/highlight.pack.js', | |||||
filters='uglifyjs', output='packed-common.js') | |||||
assets.register('js_common', js) | |||||
if 'js_editor' not in assets._named_bundles: | |||||
js = Bundle('js/ace/ace.js', | |||||
'js/ace/mode-markdown.js', | |||||
'vendor/keymaster/keymaster.js', | |||||
'js/dillinger.js', | |||||
filters='uglifyjs', output='packed-editor.js') | |||||
assets.register('js_editor', js) | |||||
repo_dir = config.repos['dir'] | repo_dir = config.repos['dir'] | ||||
repo_name = subdomain if subdomain else "_" | repo_name = subdomain if subdomain else "_" | ||||
@@ -1,7 +0,0 @@ | |||||
/*! | |||||
Autosize v1.17.8 - 2013-09-07 | |||||
Automatically adjust textarea height based on user input. | |||||
(c) 2013 Jack Moore - http://www.jacklmoore.com/autosize | |||||
license: http://www.opensource.org/licenses/mit-license.php | |||||
*/ | |||||
(function(e){"function"==typeof define&&define.amd?define(["jquery"],e):e(window.jQuery||window.$)})(function(e){var t,o={className:"autosizejs",append:"",callback:!1,resizeDelay:10},i='<textarea tabindex="-1" style="position:absolute; top:-999px; left:0; right:auto; bottom:auto; border:0; padding: 0; -moz-box-sizing:content-box; -webkit-box-sizing:content-box; box-sizing:content-box; word-wrap:break-word; height:0 !important; min-height:0 !important; overflow:hidden; transition:none; -webkit-transition:none; -moz-transition:none;"/>',n=["fontFamily","fontSize","fontWeight","fontStyle","letterSpacing","textTransform","wordSpacing","textIndent"],s=e(i).data("autosize",!0)[0];s.style.lineHeight="99px","99px"===e(s).css("lineHeight")&&n.push("lineHeight"),s.style.lineHeight="",e.fn.autosize=function(i){return this.length?(i=e.extend({},o,i||{}),s.parentNode!==document.body&&e(document.body).append(s),this.each(function(){function o(){var t,o;"getComputedStyle"in window?(t=window.getComputedStyle(u),o=u.getBoundingClientRect().width,e.each(["paddingLeft","paddingRight","borderLeftWidth","borderRightWidth"],function(e,i){o-=parseInt(t[i],10)}),s.style.width=o+"px"):s.style.width=Math.max(p.width(),0)+"px"}function a(){var a={};if(t=u,s.className=i.className,d=parseInt(p.css("maxHeight"),10),e.each(n,function(e,t){a[t]=p.css(t)}),e(s).css(a),o(),window.chrome){var r=u.style.width;u.style.width="0px",u.offsetWidth,u.style.width=r}}function r(){var e,n;t!==u?a():o(),s.value=u.value+i.append,s.style.overflowY=u.style.overflowY,n=parseInt(u.style.height,10),s.scrollTop=0,s.scrollTop=9e4,e=s.scrollTop,d&&e>d?(u.style.overflowY="scroll",e=d):(u.style.overflowY="hidden",c>e&&(e=c)),e+=f,n!==e&&(u.style.height=e+"px",w&&i.callback.call(u,u))}function l(){clearTimeout(h),h=setTimeout(function(){var e=p.width();e!==g&&(g=e,r())},parseInt(i.resizeDelay,10))}var d,c,h,u=this,p=e(u),f=0,w=e.isFunction(i.callback),z={height:u.style.height,overflow:u.style.overflow,overflowY:u.style.overflowY,wordWrap:u.style.wordWrap,resize:u.style.resize},g=p.width();p.data("autosize")||(p.data("autosize",!0),("border-box"===p.css("box-sizing")||"border-box"===p.css("-moz-box-sizing")||"border-box"===p.css("-webkit-box-sizing"))&&(f=p.outerHeight()-p.height()),c=Math.max(parseInt(p.css("minHeight"),10)-f||0,p.height()),p.css({overflow:"hidden",overflowY:"hidden",wordWrap:"break-word",resize:"none"===p.css("resize")||"vertical"===p.css("resize")?"none":"horizontal"}),"onpropertychange"in u?"oninput"in u?p.on("input.autosize keyup.autosize",r):p.on("propertychange.autosize",function(){"value"===event.propertyName&&r()}):p.on("input.autosize",r),i.resizeDelay!==!1&&e(window).on("resize.autosize",l),p.on("autosize.resize",r),p.on("autosize.resizeIncludeStyle",function(){t=null,r()}),p.on("autosize.destroy",function(){t=null,clearTimeout(h),e(window).off("resize",l),p.off("autosize").off(".autosize").css(z).removeData("autosize")}),r())})):this}}); |
@@ -1,4 +0,0 @@ | |||||
// keymaster.js | |||||
// (c) 2011 Thomas Fuchs | |||||
// keymaster.js may be freely distributed under the MIT license. | |||||
(function(a){function m(a,b,c){a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent&&a.attachEvent("on"+b,function(){c(window.event)})}function l(a){e=a||"all"}function k(a,b,d){var e,h,i,j;d===undefined&&(d=b,b="all"),a=a.replace(/\s/g,""),e=a.split(","),e[e.length-1]==""&&(e[e.length-2]+=",");for(i=0;i<e.length;i++){h=[],a=e[i].split("+");if(a.length>1){h=a.slice(0,a.length-1);for(j=0;j<h.length;j++)h[j]=f[h[j]];a=[a[a.length-1]]}a=a[0],a=g[a]||a.toUpperCase().charCodeAt(0),a in c||(c[a]=[]),c[a].push({shortcut:e[i],scope:b,method:d,key:e[i],mods:h})}}function j(a){var b=a.keyCode,c;if(b==93||b==224)b=91;if(b in d){d[b]=!1;for(c in f)f[c]==b&&(k[c]=!1)}}function i(a){var b,g,i,j,l,m;g=(a.target||a.srcElement).tagName,b=a.keyCode;if(b==93||b==224)b=91;if(b in d){d[b]=!0;for(j in f)f[j]==b&&(k[j]=!0)}else{if(g=="INPUT"||g=="SELECT"||g=="TEXTAREA")return;if(!(b in c))return;for(l=0;l<c[b].length;l++){i=c[b][l];if(i.scope==e||i.scope=="all"){m=i.mods.length>0;for(j in d)if(!d[j]&&h(i.mods,+j)>-1||d[j]&&h(i.mods,+j)==-1)m=!1;(i.mods.length==0&&!d[16]&&!d[18]&&!d[17]&&!d[91]||m)&&i.method(a,i)===!1&&(a.preventDefault?a.preventDefault():a.returnValue=!1,a.stopPropagation&&a.stopPropagation(),a.cancelBubble&&(a.cancelBubble=!0))}}}}function h(a,b){var c=a.length;while(c--)if(a[c]===b)return c;return-1}var b,c={},d={16:!1,18:!1,17:!1,91:!1},e="all",f={"⇧":16,shift:16,"⌥":18,alt:18,option:18,"⌃":17,ctrl:17,control:17,"⌘":91,command:91},g={backspace:8,tab:9,clear:12,enter:13,"return":13,esc:27,escape:27,space:32,left:37,up:38,right:39,down:40,del:46,"delete":46,home:36,end:35,pageup:33,pagedown:34,",":188,".":190,"/":191,"`":192,"-":189,"=":187,";":186,"'":222,"[":219,"]":221,"\\":220};for(b=1;b<20;b++)f["f"+b]=111+b;for(b in f)k[b]=!1;m(document,"keydown",i),m(document,"keyup",j),a.key=k,a.key.setScope=l,typeof module!="undefined"&&(module.exports=key)})(this) |
@@ -1,5 +0,0 @@ | |||||
// | |||||
// Github Extension (WIP) | |||||
// ~~strike-through~~ -> <del>strike-through</del> | |||||
// | |||||
(function(){var a=function(a){return[{type:"lang",regex:"(~T){2}([^~]+)(~T){2}",replace:function(a,b,c,d){return"<del>"+c+"</del>"}}]};typeof window!="undefined"&&window.Showdown&&window.Showdown.extensions&&(window.Showdown.extensions.github=a),typeof module!="undefined"&&(module.exports=a)})(); |
@@ -1,6 +0,0 @@ | |||||
// | |||||
// Google Prettify | |||||
// A showdown extension to add Google Prettify (http://code.google.com/p/google-code-prettify/) | |||||
// hints to showdown's HTML output. | |||||
// | |||||
(function(){var a=function(a){return[{type:"output",filter:function(a){return a.replace(/(<pre>)?<code>/gi,function(a,b){return b?'<pre class="prettyprint linenums" tabIndex="0"><code data-inner="1">':'<code class="prettyprint">'})}}]};typeof window!="undefined"&&window.Showdown&&window.Showdown.extensions&&(window.Showdown.extensions.googlePrettify=a),typeof module!="undefined"&&(module.exports=a)})(); |
@@ -1,105 +0,0 @@ | |||||
/*global module:true*/ | |||||
/* | |||||
* Basic table support with re-entrant parsing, where cell content | |||||
* can also specify markdown. | |||||
* | |||||
* Tables | |||||
* ====== | |||||
* | |||||
* | Col 1 | Col 2 | | |||||
* |======== |====================================================| | |||||
* |**bold** | ![Valid XHTML] (http://w3.org/Icons/valid-xhtml10) | | |||||
* | Plain | Value | | |||||
* | |||||
*/ | |||||
(function(){ | |||||
var table = function(converter) { | |||||
var tables = {}, style = 'text-align:left;', filter; | |||||
tables.th = function(header){ | |||||
if (header.trim() === "") { return "";} | |||||
var id = header.trim().replace(/ /g, '_').toLowerCase(); | |||||
return '<th id="' + id + '" style="'+style+'">' + header + '</th>'; | |||||
}; | |||||
tables.td = function(cell) { | |||||
return '<td style="'+style+'">' + converter.makeHtml(cell) + '</td>'; | |||||
}; | |||||
tables.ths = function(){ | |||||
var out = "", i = 0, hs = [].slice.apply(arguments); | |||||
for (i;i<hs.length;i+=1) { | |||||
out += tables.th(hs[i]) + '\n'; | |||||
} | |||||
return out; | |||||
}; | |||||
tables.tds = function(){ | |||||
var out = "", i = 0, ds = [].slice.apply(arguments); | |||||
for (i;i<ds.length;i+=1) { | |||||
out += tables.td(ds[i]) + '\n'; | |||||
} | |||||
return out; | |||||
}; | |||||
tables.thead = function() { | |||||
var out, i = 0, hs = [].slice.apply(arguments); | |||||
out = "<thead>\n"; | |||||
out += "<tr>\n"; | |||||
out += tables.ths.apply(this, hs); | |||||
out += "</tr>\n"; | |||||
out += "</thead>\n"; | |||||
return out; | |||||
}; | |||||
tables.tr = function() { | |||||
var out, i = 0, cs = [].slice.apply(arguments); | |||||
out = "<tr>\n"; | |||||
out += tables.tds.apply(this, cs); | |||||
out += "</tr>\n"; | |||||
return out; | |||||
}; | |||||
filter = function(text) { | |||||
var i=0, lines = text.split('\n'), tbl = [], line, hs, rows, out = []; | |||||
for (i; i<lines.length;i+=1) { | |||||
line = lines[i]; | |||||
// looks like a table heading | |||||
if (line.trim().match(/^[|]{1}.*[|]{1}$/)) { | |||||
line = line.trim(); | |||||
tbl.push('<table>'); | |||||
hs = line.substring(1, line.length -1).split('|'); | |||||
tbl.push(tables.thead.apply(this, hs)); | |||||
line = lines[++i]; | |||||
if (!line.trim().match(/^[|]{1}[-=| ]+[|]{1}$/)) { | |||||
// not a table rolling back | |||||
line = lines[--i]; | |||||
} | |||||
else { | |||||
line = lines[++i]; | |||||
tbl.push('<tbody>'); | |||||
while (line.trim().match(/^[|]{1}.*[|]{1}$/)) { | |||||
line = line.trim(); | |||||
tbl.push(tables.tr.apply(this, line.substring(1, line.length -1).split('|'))); | |||||
line = lines[++i]; | |||||
} | |||||
tbl.push('</tbody>'); | |||||
tbl.push('</table>'); | |||||
// we are done with this table and we move along | |||||
out.push(tbl.join('\n')); | |||||
continue; | |||||
} | |||||
} | |||||
out.push(line); | |||||
} | |||||
return out.join('\n'); | |||||
}; | |||||
return [ | |||||
{ | |||||
type: 'lang', | |||||
filter: filter | |||||
} | |||||
]; | |||||
}; | |||||
// Client-side export | |||||
if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.table = table; } | |||||
// Server-side export | |||||
if (typeof module !== 'undefined') { | |||||
module.exports = table; | |||||
} | |||||
}()); |
@@ -1,6 +0,0 @@ | |||||
// | |||||
// Twitter Extension | |||||
// @username -> <a href="http://twitter.com/username">@username</a> | |||||
// #hashtag -> <a href="http://twitter.com/search/%23hashtag">#hashtag</a> | |||||
// | |||||
(function(){var a=function(a){return[{type:"lang",regex:"\\B(\\\\)?@([\\S]+)\\b",replace:function(a,b,c){return b==="\\"?a:'<a href="http://twitter.com/'+c+'">@'+c+"</a>"}},{type:"lang",regex:"\\B(\\\\)?#([\\S]+)\\b",replace:function(a,b,c){return b==="\\"?a:'<a href="http://twitter.com/search/%23'+c+'">#'+c+"</a>"}},{type:"lang",regex:"\\\\@",replace:"@"}]};typeof window!="undefined"&&window.Showdown&&window.Showdown.extensions&&(window.Showdown.extensions.twitter=a),typeof module!="undefined"&&(module.exports=a)})(); |
@@ -3,6 +3,10 @@ | |||||
* Copyright (c) 2010 Caolan McMahon | * Copyright (c) 2010 Caolan McMahon | ||||
*/ | */ | ||||
/* | |||||
* Fork of https://github.com/caolan/wmd | |||||
*/ | |||||
function escapeHtml(s) { | function escapeHtml(s) { | ||||
s = ('' + s); /* Coerce to string */ | s = ('' + s); /* Coerce to string */ | ||||
s = s.replace(/&/g, '&'); | s = s.replace(/&/g, '&'); | ||||
@@ -22,7 +26,9 @@ function escapeHtml(s) { | |||||
* @api public | * @api public | ||||
*/ | */ | ||||
var WMD = function (content, options) { | |||||
var WMD = {}; | |||||
WMD.convert = function(content, options) { | |||||
var doc = {raw: content, markdown: content}; | var doc = {raw: content, markdown: content}; | ||||
var opt = WMD.readOptions(options); | var opt = WMD.readOptions(options); | ||||
WMD.preprocess(doc, opt); | WMD.preprocess(doc, opt); |
@@ -10,8 +10,9 @@ | |||||
<link href="/static/css/bootstrap/spacelab.css" rel="stylesheet"> | <link href="/static/css/bootstrap/spacelab.css" rel="stylesheet"> | ||||
<link href="/static/css/font-awesome.min.css" rel="stylesheet"> | <link href="/static/css/font-awesome.min.css" rel="stylesheet"> | ||||
<link href="/static/js/highlight/styles/github.css" rel="stylesheet"> | |||||
<link href="/static/vendor/highlightjs/styles/github.css" rel="stylesheet"> | |||||
<link href="/static/css/style.css" rel="stylesheet"> | <link href="/static/css/style.css" rel="stylesheet"> | ||||
{% block css %}{% endblock %} | |||||
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --> | <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --> | ||||
<!--[if lt IE 9]> | <!--[if lt IE 9]> | ||||
@@ -99,53 +100,35 @@ | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<script src="/static/js/jquery-1.10.2.min.js"></script> | |||||
<script src="/static/js/underscore.js"></script> | |||||
<script src="/static/js/bootstrap.min.js"></script> | |||||
<!--<script src="/static/js/marked.js"></script>--> | |||||
<script src="/static/js/handlebars.js"></script> | |||||
<script src="/static/js/showdown/showdown.js"></script> | |||||
<script src="/static/js/html-sanitizer-minified.js"></script> | |||||
<script src="/static/js/showdown/wmd.js"></script> | |||||
<script src="/static/js/highlight/highlight.pack.js"></script> | |||||
{% assets "js_common" %} | |||||
<script type="text/javascript" src="{{ ASSET_URL }}"></script> | |||||
{% endassets %} | |||||
<script> | <script> | ||||
/* | |||||
marked.setOptions({ | |||||
gfm: true, | |||||
tables: true, | |||||
pedantic: false, | |||||
sanitize: false, | |||||
smartLists: true, | |||||
smartypants: false, | |||||
langPrefix: 'lang-' | |||||
}); | |||||
*/ | |||||
hljs.initHighlightingOnLoad(); | hljs.initHighlightingOnLoad(); | ||||
// Markdown Renderer | // Markdown Renderer | ||||
MDR = { | MDR = { | ||||
doc: null, | doc: null, | ||||
callback: WMD, | |||||
callback: WMD.convert, | |||||
convert: function(md, sanitize){ | convert: function(md, sanitize){ | ||||
this.doc = this.callback(md); | this.doc = this.callback(md); | ||||
md = this.doc.html; | |||||
var html = this.doc.html; | |||||
if (sanitize) { | if (sanitize) { | ||||
md = html_sanitize(md); | |||||
// Causes some problems with inline styles | |||||
html = html_sanitize(html); | |||||
} | } | ||||
md = this.hook(md); | |||||
return md; | |||||
html = this.hook(html); | |||||
return html; | |||||
}, | }, | ||||
hook: function(md) { | |||||
hook: function(html) { | |||||
if (!this.doc.metadata) { | if (!this.doc.metadata) { | ||||
return md; | |||||
return html; | |||||
} | } | ||||
try { | try { | ||||
var template = Handlebars.compile(md); | |||||
var template = Handlebars.compile(html); | |||||
return template(this.doc.metadata); | return template(this.doc.metadata); | ||||
} catch(e) { | } catch(e) { | ||||
return md; | |||||
return html; | |||||
} | } | ||||
} | } | ||||
}; | }; | ||||
@@ -1,21 +1,23 @@ | |||||
{% extends 'layout.html' %} | {% extends 'layout.html' %} | ||||
{% block js %} | {% block js %} | ||||
<script src="/static/js/ace/ace.js"></script> | |||||
<script src="/static/js/ace/mode-markdown.js"></script> | |||||
<script src="/static/js/keymaster.min.js"></script> | |||||
<script src="/static/js/dillinger.js"></script> | |||||
{% assets "js_editor" %} | |||||
<script type="text/javascript" src="{{ ASSET_URL }}"></script> | |||||
{% endassets %} | |||||
{% endblock %} | {% endblock %} | ||||
{% block body %} | {% block body %} | ||||
{% block css %} | |||||
<style> | <style> | ||||
#main-body { | |||||
background: inherit; | |||||
border: inherit; | |||||
padding: 0; | |||||
-webkit-box-shadow: 0; | |||||
-moz-box-shadow: 0; | |||||
box-shadow: 0; | |||||
} | |||||
#main-body { | |||||
background: inherit; | |||||
border: inherit; | |||||
padding: 0; | |||||
-webkit-box-shadow: 0; | |||||
-moz-box-shadow: 0; | |||||
box-shadow: 0; | |||||
} | |||||
</style> | </style> | ||||
{% endblock %} | |||||
<div id="app-wrap" class="container-fluid"> | <div id="app-wrap" class="container-fluid"> | ||||
<div id="app-controls" class="row"> | <div id="app-controls" class="row"> | ||||
@@ -37,7 +39,7 @@ | |||||
<li><a tabindex="-1" href="#" data-value="ace/theme/cobalt" class="">Cobalt</a></li> | <li><a tabindex="-1" href="#" data-value="ace/theme/cobalt" class="">Cobalt</a></li> | ||||
<li><a tabindex="-1" href="#" data-value="ace/theme/crimson_editor" class="">Crimson Editor</a></li> | <li><a tabindex="-1" href="#" data-value="ace/theme/crimson_editor" class="">Crimson Editor</a></li> | ||||
<li><a tabindex="-1" href="#" data-value="ace/theme/dawn" class="selected">Dawn</a></li> | <li><a tabindex="-1" href="#" data-value="ace/theme/dawn" class="selected">Dawn</a></li> | ||||
<li><a tabindex="-1" href="#" data-value="ace/theme/dawn" class="">Dreamweaver</a></li> | |||||
<li><a tabindex="-1" href="#" data-value="ace/theme/dreamweaver" class="">Dreamweaver</a></li> | |||||
<li><a tabindex="-1" href="#" data-value="ace/theme/eclipse" class="">Eclipse</a></li> | <li><a tabindex="-1" href="#" data-value="ace/theme/eclipse" class="">Eclipse</a></li> | ||||
<li><a tabindex="-1" href="#" data-value="ace/theme/idle_fingers" class="">idleFingers</a></li> | <li><a tabindex="-1" href="#" data-value="ace/theme/idle_fingers" class="">idleFingers</a></li> | ||||
<li><a tabindex="-1" href="#" data-value="ace/theme/kr_theme" class="">krTheme</a></li> | <li><a tabindex="-1" href="#" data-value="ace/theme/kr_theme" class="">krTheme</a></li> | ||||
@@ -34,6 +34,7 @@ def unescape_html(s): | |||||
s = s.replace(''', "'") | s = s.replace(''', "'") | ||||
return s | return s | ||||
def mkdir_safe(path): | def mkdir_safe(path): | ||||
if path and not(os.path.exists(path)): | if path and not(os.path.exists(path)): | ||||
os.makedirs(path) | os.makedirs(path) | ||||
@@ -6,6 +6,4 @@ nginx: | |||||
- enable: True | - enable: True | ||||
- reload: True | - reload: True | ||||
- require: | - require: | ||||
- pkg: nginx | |||||
/etc/ | |||||
- pkg: nginx |
@@ -0,0 +1,9 @@ | |||||
node-repos: | |||||
pkgrepo.managed: | |||||
- ppa: chris-lea/node.js | |||||
nodejs: | |||||
pkg: | |||||
- installed | |||||
- require: | |||||
- pkgrepo.managed: node-repos |