add revert page
This commit is contained in:
parent
9fed2175de
commit
a16b45cdba
|
@ -226,20 +226,30 @@ def create_app(subdomain=None):
|
||||||
User.logout()
|
User.logout()
|
||||||
return redirect(url_for('root'))
|
return redirect(url_for('root'))
|
||||||
|
|
||||||
@app.route("/commit/<sha>/<name>")
|
@app.route("/_commit/<sha>/<name>")
|
||||||
def commit_sha(name, sha):
|
def commit_sha(name, sha):
|
||||||
cname = to_canonical(name)
|
cname = to_canonical(name)
|
||||||
|
|
||||||
data = w.get_page(cname, sha=sha)
|
data = w.get_page(cname, sha=sha)
|
||||||
if data:
|
if data:
|
||||||
return render_template('page/page.html', page=data)
|
return render_template('page/page.html', name=name, page=data, commit=sha)
|
||||||
else:
|
else:
|
||||||
return redirect('/create/'+cname)
|
return redirect('/create/'+cname)
|
||||||
|
|
||||||
@app.route("/compare/<name>/<regex('[^.]+'):fsha><regex('\.{2,3}'):dots><regex('.+'):lsha>")
|
@app.route("/_compare/<name>/<regex('[^.]+'):fsha><regex('\.{2,3}'):dots><regex('.+'):lsha>")
|
||||||
def compare(name, fsha, dots, lsha):
|
def compare(name, fsha, dots, lsha):
|
||||||
diff = w.compare(name, fsha, lsha)
|
diff = w.compare(name, fsha, lsha)
|
||||||
return render_template('page/compare.html', name=name, diff=diff)
|
return render_template('page/compare.html', name=name, diff=diff, old=fsha, new=lsha)
|
||||||
|
|
||||||
|
@app.route("/_revert", methods=['POST'])
|
||||||
|
def revert():
|
||||||
|
if request.method == 'POST':
|
||||||
|
name = request.form.get('name')
|
||||||
|
commit = request.form.get('commit')
|
||||||
|
cname = to_canonical(name)
|
||||||
|
w.revert_page(name, commit, message="Reverting %s" % cname, username=CurrentUser.get('username'))
|
||||||
|
flash('Page reverted', 'success')
|
||||||
|
return redirect("/" + cname)
|
||||||
|
|
||||||
@app.route("/register", methods=['GET', 'POST'])
|
@app.route("/register", methods=['GET', 'POST'])
|
||||||
def register():
|
def register():
|
||||||
|
@ -263,12 +273,12 @@ def create_app(subdomain=None):
|
||||||
else:
|
else:
|
||||||
return render_template('account/login.html')
|
return render_template('account/login.html')
|
||||||
|
|
||||||
@app.route("/history/<name>")
|
@app.route("/_history/<name>")
|
||||||
def history(name):
|
def history(name):
|
||||||
history = w.get_history(name)
|
history = w.get_history(name)
|
||||||
return render_template('page/history.html', name=name, history=history)
|
return render_template('page/history.html', name=name, history=history)
|
||||||
|
|
||||||
@app.route("/edit/<name>", methods=['GET', 'POST'])
|
@app.route("/_edit/<name>", methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def edit(name):
|
def edit(name):
|
||||||
data = w.get_page(name)
|
data = w.get_page(name)
|
||||||
|
@ -277,7 +287,8 @@ def create_app(subdomain=None):
|
||||||
edit_cname = to_canonical(request.form['name'])
|
edit_cname = to_canonical(request.form['name'])
|
||||||
if edit_cname.lower() != cname.lower():
|
if edit_cname.lower() != cname.lower():
|
||||||
w.rename_page(cname, edit_cname)
|
w.rename_page(cname, edit_cname)
|
||||||
w.write_page(edit_cname, request.form['content'], message=request.form['message'],
|
w.write_page(edit_cname, request.form['content'],
|
||||||
|
message=request.form['message'],
|
||||||
username=CurrentUser.get('username'))
|
username=CurrentUser.get('username'))
|
||||||
return redirect("/" + edit_cname)
|
return redirect("/" + edit_cname)
|
||||||
else:
|
else:
|
||||||
|
@ -288,13 +299,13 @@ def create_app(subdomain=None):
|
||||||
else:
|
else:
|
||||||
return redirect('/create/'+cname)
|
return redirect('/create/'+cname)
|
||||||
|
|
||||||
@app.route("/delete/<name>", methods=['POST'])
|
@app.route("/_delete/<name>", methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def delete(name):
|
def delete(name):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@app.route("/create/", methods=['GET', 'POST'])
|
@app.route("/_create/", methods=['GET', 'POST'])
|
||||||
@app.route("/create/<name>", methods=['GET', 'POST'])
|
@app.route("/_create/<name>", methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def create(name=None):
|
def create(name=None):
|
||||||
cname = ""
|
cname = ""
|
||||||
|
@ -304,12 +315,14 @@ def create_app(subdomain=None):
|
||||||
# Page exists, edit instead
|
# Page exists, edit instead
|
||||||
return redirect("/edit/" + cname)
|
return redirect("/edit/" + cname)
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
w.write_page(request.form['name'], request.form['content'], message=request.form['message'], create=True)
|
w.write_page(request.form['name'], request.form['content'],
|
||||||
|
message=request.form['message'],
|
||||||
|
create=True,
|
||||||
|
username=CurrentUser.get('username'))
|
||||||
return redirect("/" + cname)
|
return redirect("/" + cname)
|
||||||
else:
|
else:
|
||||||
return render_template('page/edit.html', name=cname, content="")
|
return render_template('page/edit.html', name=cname, content="")
|
||||||
|
|
||||||
|
|
||||||
@app.route("/<name>")
|
@app.route("/<name>")
|
||||||
def render(name):
|
def render(name):
|
||||||
cname = to_canonical(name)
|
cname = to_canonical(name)
|
||||||
|
|
|
@ -102,9 +102,6 @@ class CurrentUser():
|
||||||
if id:
|
if id:
|
||||||
user = User()
|
user = User()
|
||||||
session['user'] = user.get_by_id(id)
|
session['user'] = user.get_by_id(id)
|
||||||
#import sys
|
|
||||||
#sys.exit()
|
|
||||||
#session['user'] = to_dict(user.get_one(id, 'id'), True)
|
|
||||||
|
|
||||||
def get_id(self):
|
def get_id(self):
|
||||||
return self.id
|
return self.id
|
||||||
|
|
|
@ -93,6 +93,12 @@ body {
|
||||||
box-shadow: 0 1px 2px rgba(0,0,0,.15);
|
box-shadow: 0 1px 2px rgba(0,0,0,.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#page-action-bar {
|
||||||
|
position: relative;
|
||||||
|
z-index: 100;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
.user-avatar a img {
|
.user-avatar a img {
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
|
|
|
@ -10,7 +10,6 @@ $(function(){
|
||||||
|
|
||||||
var editor
|
var editor
|
||||||
, autoInterval
|
, autoInterval
|
||||||
, keyCheck // used to detect changes not made via keyup
|
|
||||||
, profile =
|
, profile =
|
||||||
{
|
{
|
||||||
theme: 'ace/theme/idle_fingers'
|
theme: 'ace/theme/idle_fingers'
|
||||||
|
@ -331,11 +330,6 @@ $(function(){
|
||||||
* @return {Void}
|
* @return {Void}
|
||||||
*/
|
*/
|
||||||
function saveFile(isManual){
|
function saveFile(isManual){
|
||||||
if (!keyCheck && profile.currentMd != editor.getSession().getValue()) {
|
|
||||||
previewMd();
|
|
||||||
console.log(keyCheck);
|
|
||||||
}
|
|
||||||
keyCheck = false;
|
|
||||||
updateUserProfile({currentMd: editor.getSession().getValue()});
|
updateUserProfile({currentMd: editor.getSession().getValue()});
|
||||||
|
|
||||||
if (isManual) {
|
if (isManual) {
|
||||||
|
@ -536,8 +530,7 @@ $(function(){
|
||||||
* @return {Void}
|
* @return {Void}
|
||||||
*/
|
*/
|
||||||
function bindPreview(){
|
function bindPreview(){
|
||||||
$('#editor').bind('keyup', function() {
|
editor.getSession().on('change', function(e) {
|
||||||
keyCheck = true;
|
|
||||||
previewMd();
|
previewMd();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -635,19 +635,18 @@ scope:scope,method:method,key:keys[i],mods:mods})}}function unbindKey(key,scope)
|
||||||
scope)handlers.splice(i,1);else i++}}function getKeys(key){var keys;key=key.replace(/\s/g,"");keys=key.split(",");if(keys[keys.length-1]=="")keys[keys.length-2]+=",";return keys}function getMods(key){var mods=key.slice(0,key.length-1);for(var mi=0;mi<mods.length;mi++)mods[mi]=_MODIFIERS[mods[mi]];return mods}function addEvent(object,event,method){if(object.addEventListener)object.addEventListener(event,method,false);else if(object.attachEvent)object.attachEvent("on"+event,function(){method(window.event)})}
|
scope)handlers.splice(i,1);else i++}}function getKeys(key){var keys;key=key.replace(/\s/g,"");keys=key.split(",");if(keys[keys.length-1]=="")keys[keys.length-2]+=",";return keys}function getMods(key){var mods=key.slice(0,key.length-1);for(var mi=0;mi<mods.length;mi++)mods[mi]=_MODIFIERS[mods[mi]];return mods}function addEvent(object,event,method){if(object.addEventListener)object.addEventListener(event,method,false);else if(object.attachEvent)object.attachEvent("on"+event,function(){method(window.event)})}
|
||||||
addEvent(document,"keydown",function(event){dispatch(event)});addEvent(document,"keyup",clearModifier);addEvent(window,"focus",resetModifiers);var previousKey=global.key;function noConflict(){var k=global.key;global.key=previousKey;return k}global.key=assignKey;global.key.setScope=setScope;global.key.getScope=getScope;global.key.deleteScope=deleteScope;global.key.filter=filter;global.key.isPressed=isPressed;global.key.getPressedKeyCodes=getPressedKeyCodes;global.key.noConflict=noConflict;global.key.unbind=
|
addEvent(document,"keydown",function(event){dispatch(event)});addEvent(document,"keyup",clearModifier);addEvent(window,"focus",resetModifiers);var previousKey=global.key;function noConflict(){var k=global.key;global.key=previousKey;return k}global.key=assignKey;global.key.setScope=setScope;global.key.getScope=getScope;global.key.deleteScope=deleteScope;global.key.filter=filter;global.key.isPressed=isPressed;global.key.getPressedKeyCodes=getPressedKeyCodes;global.key.noConflict=noConflict;global.key.unbind=
|
||||||
unbindKey;if(typeof module!=="undefined")module.exports=key})(this);
|
unbindKey;if(typeof module!=="undefined")module.exports=key})(this);
|
||||||
$(function(){var $theme=$("#theme-list"),$preview=$("#preview"),$autosave=$("#autosave"),$wordcount=$("#wordcount"),$wordcounter=$("#wordcounter"),$pagename=$("#page-name");var editor,autoInterval,keyCheck,profile={theme:"ace/theme/idle_fingers",currentMd:"",autosave:{enabled:true,interval:3E3},current_filename:$pagename.val()};var dillinger="dillinger",dillingerElem=document.createElement(dillinger),dillingerStyle=dillingerElem.style,domPrefixes="Webkit Moz O ms Khtml".split(" ");function asyncLoad(filename,
|
$(function(){var $theme=$("#theme-list"),$preview=$("#preview"),$autosave=$("#autosave"),$wordcount=$("#wordcount"),$wordcounter=$("#wordcounter"),$pagename=$("#page-name");var editor,autoInterval,profile={theme:"ace/theme/idle_fingers",currentMd:"",autosave:{enabled:true,interval:3E3},current_filename:$pagename.val()};var dillinger="dillinger",dillingerElem=document.createElement(dillinger),dillingerStyle=dillingerElem.style,domPrefixes="Webkit Moz O ms Khtml".split(" ");function asyncLoad(filename,
|
||||||
cb){(function(d,t){var leScript=d.createElement(t),scripts=d.getElementsByTagName(t)[0];leScript.async=1;leScript.src=filename;scripts.parentNode.insertBefore(leScript,scripts);leScript.onload=function(){cb&&cb()}})(document,"script")}function hasLocalStorage(){var storage;try{if(localStorage.getItem)storage=localStorage}catch(e){}return storage}function getUserProfile(){var p;try{p=JSON.parse(localStorage.profile);p=$.extend(true,profile,p)}catch(e){p=profile}if(p.filename!=$pagename.val())updateUserProfile({filename:$pagename.val(),
|
cb){(function(d,t){var leScript=d.createElement(t),scripts=d.getElementsByTagName(t)[0];leScript.async=1;leScript.src=filename;scripts.parentNode.insertBefore(leScript,scripts);leScript.onload=function(){cb&&cb()}})(document,"script")}function hasLocalStorage(){var storage;try{if(localStorage.getItem)storage=localStorage}catch(e){}return storage}function getUserProfile(){var p;try{p=JSON.parse(localStorage.profile);p=$.extend(true,profile,p)}catch(e){p=profile}if(p.filename!=$pagename.val())updateUserProfile({filename:$pagename.val(),
|
||||||
currentMd:""});profile=p}function updateUserProfile(obj){localStorage.clear();localStorage.profile=JSON.stringify($.extend(true,profile,obj))}function prefixed(prop){return testPropsAll(prop,"pfx")}function testProps(props,prefixed){for(var i in props)if(dillingerStyle[props[i]]!==undefined)return prefixed==="pfx"?props[i]:true;return false}function testPropsAll(prop,prefixed){var ucProp=prop.charAt(0).toUpperCase()+prop.substr(1),props=(prop+" "+domPrefixes.join(ucProp+" ")+ucProp).split(" ");return testProps(props,
|
currentMd:""});profile=p}function updateUserProfile(obj){localStorage.clear();localStorage.profile=JSON.stringify($.extend(true,profile,obj))}function prefixed(prop){return testPropsAll(prop,"pfx")}function testProps(props,prefixed){for(var i in props)if(dillingerStyle[props[i]]!==undefined)return prefixed==="pfx"?props[i]:true;return false}function testPropsAll(prop,prefixed){var ucProp=prop.charAt(0).toUpperCase()+prop.substr(1),props=(prop+" "+domPrefixes.join(ucProp+" ")+ucProp).split(" ");return testProps(props,
|
||||||
prefixed)}function normalizeTransitionEnd(){var transEndEventNames={"WebkitTransition":"webkitTransitionEnd","MozTransition":"transitionend","OTransition":"oTransitionEnd","msTransition":"msTransitionEnd","transition":"transitionend"};return transEndEventNames[prefixed("transition")]}function getCurrentFilenameFromField(){return $('#filename > span[contenteditable="true"]').text()}function setCurrentFilenameField(str){$('#filename > span[contenteditable="true"]').text(str||profile.current_filename||
|
prefixed)}function normalizeTransitionEnd(){var transEndEventNames={"WebkitTransition":"webkitTransitionEnd","MozTransition":"transitionend","OTransition":"oTransitionEnd","msTransition":"msTransitionEnd","transition":"transitionend"};return transEndEventNames[prefixed("transition")]}function getCurrentFilenameFromField(){return $('#filename > span[contenteditable="true"]').text()}function setCurrentFilenameField(str){$('#filename > span[contenteditable="true"]').text(str||profile.current_filename||
|
||||||
"Untitled Document")}function getTextInElement(node){if(node.nodeType===3)return node.data;var txt="";if(node=node.firstChild){do txt+=getTextInElement(node);while(node=node.nextSibling)}return txt}function countWords(string){var words=string.replace(/W+/g," ").match(/\S+/g);return words&&words.length||0}function init(){if(!hasLocalStorage())sadPanda();else{$.support.transitionEnd=normalizeTransitionEnd();getUserProfile();initAce();initUi();bindPreview();bindNav();bindKeyboard();autoSave()}}function initAce(){editor=
|
"Untitled Document")}function getTextInElement(node){if(node.nodeType===3)return node.data;var txt="";if(node=node.firstChild){do txt+=getTextInElement(node);while(node=node.nextSibling)}return txt}function countWords(string){var words=string.replace(/W+/g," ").match(/\S+/g);return words&&words.length||0}function init(){if(!hasLocalStorage())sadPanda();else{$.support.transitionEnd=normalizeTransitionEnd();getUserProfile();initAce();initUi();bindPreview();bindNav();bindKeyboard();autoSave()}}function initAce(){editor=
|
||||||
ace.edit("editor")}function initUi(){fetchTheme(profile.theme,function(){$theme.find('li > a[data-value="'+profile.theme+'"]').addClass("selected");editor.getSession().setUseWrapMode(true);editor.setShowPrintMargin(false);editor.getSession().setMode("ace/mode/markdown");editor.getSession().setValue(profile.currentMd||editor.getSession().getValue());previewMd()});$autosave.html(profile.autosave.enabled?'<i class="icon-remove"></i> Disable Autosave':'<i class="icon-ok"></i> Enable Autosave');
|
ace.edit("editor")}function initUi(){fetchTheme(profile.theme,function(){$theme.find('li > a[data-value="'+profile.theme+'"]').addClass("selected");editor.getSession().setUseWrapMode(true);editor.setShowPrintMargin(false);editor.getSession().setMode("ace/mode/markdown");editor.getSession().setValue(profile.currentMd||editor.getSession().getValue());previewMd()});$autosave.html(profile.autosave.enabled?'<i class="icon-remove"></i> Disable Autosave':'<i class="icon-ok"></i> Enable Autosave');
|
||||||
$wordcount.html(!profile.wordcount?'<i class="icon-remove"></i> Disabled Word Count':'<i class="icon-ok"></i> Enabled Word Count');setCurrentFilenameField();$(".dropdown-toggle").dropdown()}function clearSelection(){editor.getSession().setValue("");previewMd()}function saveFile(isManual){if(!keyCheck&&profile.currentMd!=editor.getSession().getValue()){previewMd();console.log(keyCheck)}keyCheck=false;updateUserProfile({currentMd:editor.getSession().getValue()});if(isManual){updateUserProfile({currentMd:""});
|
$wordcount.html(!profile.wordcount?'<i class="icon-remove"></i> Disabled Word Count':'<i class="icon-ok"></i> Enabled Word Count');setCurrentFilenameField();$(".dropdown-toggle").dropdown()}function clearSelection(){editor.getSession().setValue("");previewMd()}function saveFile(isManual){updateUserProfile({currentMd:editor.getSession().getValue()});if(isManual){updateUserProfile({currentMd:""});var data={name:$pagename.val(),message:$("#page-message").val(),content:editor.getSession().getValue()};
|
||||||
var data={name:$pagename.val(),message:$("#page-message").val(),content:editor.getSession().getValue()};$.post(window.location,data,function(){location.href="/"+data["name"]})}}function autoSave(){if(profile.autosave.enabled)autoInterval=setInterval(function(){saveFile()},profile.autosave.interval);else clearInterval(autoInterval)}$("#save-native").on("click",function(){saveFile(true)});function resetProfile(){localStorage.clear();profile.autosave.enabled=false;delete localStorage.profile;window.location.reload()}
|
$.post(window.location,data,function(){location.href="/"+data["name"]})}}function autoSave(){if(profile.autosave.enabled)autoInterval=setInterval(function(){saveFile()},profile.autosave.interval);else clearInterval(autoInterval)}$("#save-native").on("click",function(){saveFile(true)});function resetProfile(){localStorage.clear();profile.autosave.enabled=false;delete localStorage.profile;window.location.reload()}function changeTheme(e){var $target=$(e.target);if($target.attr("data-value")===profile.theme)return;
|
||||||
function changeTheme(e){var $target=$(e.target);if($target.attr("data-value")===profile.theme)return;else{$theme.find("li > a.selected").removeClass("selected");$target.addClass("selected");var newTheme=$target.attr("data-value");$(e.target).blur();fetchTheme(newTheme,function(){})}}function fetchTheme(th,cb){var name=th.split("/").pop();asyncLoad("/static/js/ace/theme-"+name+".js",function(){editor.setTheme(th);cb&&cb();updateBg(name);updateUserProfile({theme:th})})}function updateBg(name){}function previewMd(){var unmd=
|
else{$theme.find("li > a.selected").removeClass("selected");$target.addClass("selected");var newTheme=$target.attr("data-value");$(e.target).blur();fetchTheme(newTheme,function(){})}}function fetchTheme(th,cb){var name=th.split("/").pop();asyncLoad("/static/js/ace/theme-"+name+".js",function(){editor.setTheme(th);cb&&cb();updateBg(name);updateUserProfile({theme:th})})}function updateBg(name){}function previewMd(){var unmd=editor.getSession().getValue(),md=MDR.convert(unmd,true);$preview.html("").html(md)}
|
||||||
editor.getSession().getValue(),md=MDR.convert(unmd,true);$preview.html("").html(md)}function updateFilename(str){var f;if(typeof str==="string")f=str;else f=getCurrentFilenameFromField();updateUserProfile({current_filename:f})}function showHtml(){var unmd=editor.getSession().getValue();function _doneHandler(jqXHR,data,response){var resp=JSON.parse(response.responseText);$("#myModalBody").text(resp.data);$("#myModal").modal()}function _failHandler(){alert("Roh-roh. Something went wrong. :(")}var config=
|
function updateFilename(str){var f;if(typeof str==="string")f=str;else f=getCurrentFilenameFromField();updateUserProfile({current_filename:f})}function showHtml(){var unmd=editor.getSession().getValue();function _doneHandler(jqXHR,data,response){var resp=JSON.parse(response.responseText);$("#myModalBody").text(resp.data);$("#myModal").modal()}function _failHandler(){alert("Roh-roh. Something went wrong. :(")}var config={type:"POST",data:"unmd="+encodeURIComponent(unmd),dataType:"json",url:"/factory/fetch_html_direct",
|
||||||
{type:"POST",data:"unmd="+encodeURIComponent(unmd),dataType:"json",url:"/factory/fetch_html_direct",error:_failHandler,success:_doneHandler};$.ajax(config)}function sadPanda(){alert("Sad Panda - No localStorage for you!")}function toggleAutoSave(){$autosave.html(profile.autosave.enabled?'<i class="icon-remove"></i> Disable Autosave':'<i class="icon-ok"></i> Enable Autosave');updateUserProfile({autosave:{enabled:!profile.autosave.enabled}});autoSave()}function bindPreview(){$("#editor").bind("keyup",
|
error:_failHandler,success:_doneHandler};$.ajax(config)}function sadPanda(){alert("Sad Panda - No localStorage for you!")}function toggleAutoSave(){$autosave.html(profile.autosave.enabled?'<i class="icon-remove"></i> Disable Autosave':'<i class="icon-ok"></i> Enable Autosave');updateUserProfile({autosave:{enabled:!profile.autosave.enabled}});autoSave()}function bindPreview(){editor.getSession().on("change",function(e){previewMd()})}function bindNav(){$theme.find("li > a").bind("click",function(e){changeTheme(e);
|
||||||
function(){keyCheck=true;previewMd()})}function bindNav(){$theme.find("li > a").bind("click",function(e){changeTheme(e);return false});$("#clear").on("click",function(){clearSelection();return false});$("#autosave").on("click",function(){toggleAutoSave();return false});$("#reset").on("click",function(){resetProfile();return false});$("#cheat").on("click",function(){window.open("https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet","_blank");return false})}function bindKeyboard(){key("command+s, ctrl+s",
|
return false});$("#clear").on("click",function(){clearSelection();return false});$("#autosave").on("click",function(){toggleAutoSave();return false});$("#reset").on("click",function(){resetProfile();return false});$("#cheat").on("click",function(){window.open("https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet","_blank");return false})}function bindKeyboard(){key("command+s, ctrl+s",function(e){saveFile(true);e.preventDefault()});var saveCommand={name:"save",bindKey:{mac:"Command-S",
|
||||||
function(e){saveFile(true);e.preventDefault()});var saveCommand={name:"save",bindKey:{mac:"Command-S",win:"Ctrl-S"},exec:function(){saveFile(true)}};editor.commands.addCommand(saveCommand)}init()});
|
win:"Ctrl-S"},exec:function(){saveFile(true)}};editor.commands.addCommand(saveCommand)}init()});function getScrollHeight($prevFrame){if($prevFrame[0].scrollHeight!==undefined)return $prevFrame[0].scrollHeight;else if($prevFrame.find("html")[0].scrollHeight!==undefined&&$prevFrame.find("html")[0].scrollHeight!==0)return $prevFrame.find("html")[0].scrollHeight;else return $prevFrame.find("body")[0].scrollHeight}
|
||||||
function getScrollHeight($prevFrame){if($prevFrame[0].scrollHeight!==undefined)return $prevFrame[0].scrollHeight;else if($prevFrame.find("html")[0].scrollHeight!==undefined&&$prevFrame.find("html")[0].scrollHeight!==0)return $prevFrame.find("html")[0].scrollHeight;else return $prevFrame.find("body")[0].scrollHeight}
|
|
||||||
function syncPreview(){var $ed=window.ace.edit("editor");var $prev=$("#preview");var editorScrollRange=$ed.getSession().getLength();var previewScrollRange=getScrollHeight($prev);var scrollFactor=$ed.getFirstVisibleRow()/editorScrollRange;$prev.scrollTop(scrollFactor*previewScrollRange)}
|
function syncPreview(){var $ed=window.ace.edit("editor");var $prev=$("#preview");var editorScrollRange=$ed.getSession().getLength();var previewScrollRange=getScrollHeight($prev);var scrollFactor=$ed.getFirstVisibleRow()/editorScrollRange;$prev.scrollTop(scrollFactor*previewScrollRange)}
|
||||||
window.onload=function(){var $loading=$("#loading");if($.support.transition)$loading.bind($.support.transitionEnd,function(){$("#main").removeClass("bye");$loading.remove()}).addClass("fade_slow");else{$("#main").removeClass("bye");$loading.remove()}window.ace.edit("editor").session.on("changeScrollTop",syncPreview);window.ace.edit("editor").session.selection.on("changeCursor",syncPreview)};
|
window.onload=function(){var $loading=$("#loading");if($.support.transition)$loading.bind($.support.transitionEnd,function(){$("#main").removeClass("bye");$loading.remove()}).addClass("fade_slow");else{$("#main").removeClass("bye");$loading.remove()}window.ace.edit("editor").session.on("changeScrollTop",syncPreview);window.ace.edit("editor").session.selection.on("changeCursor",syncPreview)};
|
||||||
|
|
|
@ -43,10 +43,10 @@
|
||||||
<i class="icon-caret-down"></i></a>
|
<i class="icon-caret-down"></i></a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li class="dropdown-header">Page Options</li>
|
<li class="dropdown-header">Page Options</li>
|
||||||
<li><a href="/create/">Create Page</a></li>
|
<li><a href="/_create/">Create Page</a></li>
|
||||||
{% if name %}
|
{% if name %}
|
||||||
<li><a href="/edit/{{ name }}">Edit Page</a></li>
|
<li><a href="/_edit/{{ name }}">Edit Page</a></li>
|
||||||
<li><a href="/history/{{ name }}">History</a></li>
|
<li><a href="/_history/{{ name }}">History</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li class="divider"></li>
|
<li class="divider"></li>
|
||||||
<li class="dropdown-header">Site Options</li>
|
<li class="dropdown-header">Site Options</li>
|
||||||
|
|
|
@ -2,15 +2,19 @@
|
||||||
{% block body %}
|
{% block body %}
|
||||||
|
|
||||||
<h2>History for <strong>{{ name }}</strong></h2>
|
<h2>History for <strong>{{ name }}</strong></h2>
|
||||||
|
<div class="pull-right">
|
||||||
|
<a href="/_commit/{{ old }}/{{ name }}" class="btn btn-default btn-sm">View Old</a>
|
||||||
|
<a href="/_commit/{{ new }}/{{ name }}" class="btn btn-info btn-sm">View New</a>
|
||||||
|
</div>
|
||||||
<p>
|
<p>
|
||||||
<a class="btn btn-default btn-sm" href="/history/{{ name }}">Back to History</a>
|
<a class="btn btn-default btn-sm" href="/_history/{{ name }}">Back to History</a>
|
||||||
<a href="" class="btn btn-default btn-sm">Revert Changes</a>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
{{ diff|safe }}
|
{{ diff|safe }}
|
||||||
<p></p>
|
<p></p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<a class="btn btn-default btn-sm" href="/history/{{ name }}">Back to History</a>
|
<a class="btn btn-default btn-sm" href="/_history/{{ name }}">Back to History</a>
|
||||||
</p>
|
</p>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -21,7 +21,7 @@
|
||||||
<input type="checkbox" name="versions[]" value="{{ h.sha }}" />
|
<input type="checkbox" name="versions[]" value="{{ h.sha }}" />
|
||||||
</td>
|
</td>
|
||||||
<td>{{ h.author }}</td>
|
<td>{{ h.author }}</td>
|
||||||
<td><a href="/commit/{{ h.sha }}/{{ name }}" class='label label-primary'>{{ h.sha|truncate(7, True, end="") }}</a> {{ h.message }} </td>
|
<td><a href="/_commit/{{ h.sha }}/{{ name }}" class='label label-primary'>View</a> {{ h.message }} </td>
|
||||||
<td>{{ h.time|datetime }}</td>
|
<td>{{ h.time|datetime }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -50,8 +50,9 @@ $(function(){
|
||||||
$.each($cs, function(i, v){
|
$.each($cs, function(i, v){
|
||||||
revs.push(v.value);
|
revs.push(v.value);
|
||||||
});
|
});
|
||||||
revs = revs.join("...");
|
revs.reverse();
|
||||||
location.href = "/compare/{{ name }}/" + revs;
|
revs = revs.join("..");
|
||||||
|
location.href = "/_compare/{{ name }}/" + revs;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,13 +1,21 @@
|
||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% block page_menu %}
|
{% block page_menu %}
|
||||||
<div class="controls pull-right">
|
<div class="controls pull-right">
|
||||||
<a class="btn btn-default btn-sm" href="/edit/{{ name }}">Edit</a>
|
<a class="btn btn-default btn-sm" href="/_edit/{{ name }}">Edit</a>
|
||||||
<a class="btn btn-default btn-sm" href="/history/{{ name }}">History</a>
|
<a class="btn btn-default btn-sm" href="/_history/{{ name }}">History</a>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
|
{% if commit %}
|
||||||
|
<div id="page-action-bar">
|
||||||
|
<form method="POST" action="/_revert">
|
||||||
|
<input type="hidden" value="{{ name }}" name="name" />
|
||||||
|
<input type="hidden" value="{{ commit }}" name="commit" />
|
||||||
|
<input type="submit" class="btn btn-danger btn-sm" title="Revert back to this revision" value="Revert" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
<div id="page-content" style="display:none">
|
<div id="page-content" style="display:none">
|
||||||
{{ page.data }}
|
{{ page.data }}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import lxml.html
|
||||||
from lxml.html import clean
|
from lxml.html import clean
|
||||||
import ghdiff
|
import ghdiff
|
||||||
|
|
||||||
|
import gittle.utils
|
||||||
from gittle import Gittle
|
from gittle import Gittle
|
||||||
from dulwich.repo import NotGitRepository
|
from dulwich.repo import NotGitRepository
|
||||||
|
|
||||||
|
@ -68,6 +69,15 @@ class Wiki():
|
||||||
s = Site()
|
s = Site()
|
||||||
return True if s.get_by_name(name) else False
|
return True if s.get_by_name(name) else False
|
||||||
|
|
||||||
|
def revert_page(self, name, commit_sha, message, username):
|
||||||
|
page = self.get_page(name, commit_sha)
|
||||||
|
if not page:
|
||||||
|
# Page not found
|
||||||
|
return None
|
||||||
|
commit_info = gittle.utils.git.commit_info(self.repo[commit_sha])
|
||||||
|
message = commit_info['message']
|
||||||
|
return self.write_page(name, page['data'], message=message, username=username)
|
||||||
|
|
||||||
def write_page(self, name, content, message=None, create=False, username=None, email=None):
|
def write_page(self, name, content, message=None, create=False, username=None, email=None):
|
||||||
|
|
||||||
# prevents p tag from being added, we remove this later
|
# prevents p tag from being added, we remove this later
|
||||||
|
@ -76,13 +86,14 @@ class Wiki():
|
||||||
|
|
||||||
tree = lxml.html.fromstring(content)
|
tree = lxml.html.fromstring(content)
|
||||||
|
|
||||||
cleaner = clean.Cleaner(remove_unknown_tags=False, style=False, safe_attrs_only=False)
|
cleaner = clean.Cleaner(remove_unknown_tags=False, kill_tags=set(['style']), safe_attrs_only=False)
|
||||||
tree = cleaner.clean_html(tree)
|
tree = cleaner.clean_html(tree)
|
||||||
|
|
||||||
content = lxml.html.tostring(tree, encoding='utf-8', method='html')
|
content = lxml.html.tostring(tree, encoding='utf-8', method='html')
|
||||||
|
|
||||||
# post processing to fix errors
|
# post processing to fix errors
|
||||||
content = content[5:-6]
|
content = content[5:-6]
|
||||||
|
# FIXME this is for block quotes, doesn't work for double ">"
|
||||||
content = re.sub(r"(\n>)", "\n>", content)
|
content = re.sub(r"(\n>)", "\n>", content)
|
||||||
content = re.sub(r"(^>)", ">", content)
|
content = re.sub(r"(^>)", ">", content)
|
||||||
content = re.sub(r"```(.*?)```", unescape_repl, content, flags=re.DOTALL)
|
content = re.sub(r"```(.*?)```", unescape_repl, content, flags=re.DOTALL)
|
||||||
|
@ -118,6 +129,7 @@ class Wiki():
|
||||||
files=[old_name])
|
files=[old_name])
|
||||||
|
|
||||||
def get_page(self, name, sha='HEAD'):
|
def get_page(self, name, sha='HEAD'):
|
||||||
|
commit = gittle.utils.git.commit_info(self.repo[sha])
|
||||||
name = self.cname_to_filename(name)
|
name = self.cname_to_filename(name)
|
||||||
try:
|
try:
|
||||||
return self.repo.get_commit_files(sha, paths=[name]).get(name)
|
return self.repo.get_commit_files(sha, paths=[name]).get(name)
|
||||||
|
@ -125,10 +137,9 @@ class Wiki():
|
||||||
# HEAD doesn't exist yet
|
# HEAD doesn't exist yet
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def compare(self, name, new_sha, old_sha):
|
def compare(self, name, old_sha, new_sha):
|
||||||
old = self.get_page(name, sha=old_sha)
|
old = self.get_page(name, sha=old_sha)
|
||||||
new = self.get_page(name, sha=new_sha)
|
new = self.get_page(name, sha=new_sha)
|
||||||
|
|
||||||
return ghdiff.diff(old['data'], new['data'])
|
return ghdiff.diff(old['data'], new['data'])
|
||||||
|
|
||||||
def get_history(self, name):
|
def get_history(self, name):
|
||||||
|
|
Loading…
Reference in a new issue