ACE Code Editor for Pages and Blogs

This commit is contained in:
Noah 2017-12-23 15:29:38 -08:00
parent d8254826c2
commit 9e58456aaa
6 changed files with 150 additions and 17 deletions

View File

@ -20,11 +20,11 @@ import (
// AdminRoutes attaches the admin routes to the app.
func (b *Blog) AdminRoutes(r *mux.Router) {
adminRouter := mux.NewRouter().PathPrefix("/admin").Subrouter().StrictSlash(false)
r.HandleFunc("/admin", b.AdminHandler) // so as to not be "/admin/"
adminRouter := mux.NewRouter().PathPrefix("/admin").Subrouter().StrictSlash(true)
adminRouter.HandleFunc("/", b.AdminHandler)
adminRouter.HandleFunc("/settings", b.SettingsHandler)
adminRouter.HandleFunc("/editor", b.EditorHandler)
adminRouter.PathPrefix("/").HandlerFunc(b.PageHandler)
// r.HandleFunc("/admin", b.AdminHandler)
r.PathPrefix("/admin").Handler(negroni.New(
negroni.HandlerFunc(b.LoginRequired),
negroni.Wrap(adminRouter),

View File

@ -58,8 +58,9 @@ func (b *Blog) PageHandler(w http.ResponseWriter, r *http.Request) {
title, _ := TitleFromMarkdown(body)
b.RenderTemplate(w, r, ".markdown", NewVars(map[interface{}]interface{}{
"Title": title,
"HTML": template.HTML(html),
"Title": title,
"HTML": template.HTML(html),
"MarkdownFile": filepath.URI,
}))
return
}

View File

@ -81,7 +81,7 @@
{{ if and .CurrentUser.Admin .Editable }}
<p class="mt-4">
<strong>Admin:</strong> [<a href="/admin/editor?file={{ TemplateName }}">edit this page</a>]
<strong>Admin:</strong> [<a href="/admin/editor?file={{ or .Data.MarkdownFile TemplateName }}">edit this page</a>]
</p>
{{ end }}
</div>
@ -197,7 +197,6 @@
</div>
</footer>
<script type="text/javascript" src="/js/bootstrap.min.js"></script>
{{ template "scripts" or "" }}
</body>

View File

@ -1,10 +1,10 @@
# About Blog
This is a simple web blog and content management system written in Go.
## Features
* Web blog
* Draft, Private Posts
* Page editor
* You can edit any page from the front-end.
# About Blog
This is a simple web blog and content management system written in Go.
## Features
* Web blog
* Draft, Private Posts
* Page editor
* You can edit any page from the front-end.

View File

@ -9,6 +9,25 @@
</p>
{{ end }}
<style type="text/css" media="screen">
#editor-box {
position: relative;
display: none;
width: 100%;
height: 500px;
}
#ace-editor {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
#ace-buttons {
display: none;
}
</style>
<form action="/admin/editor" method="POST">
<input type="hidden" name="_csrf" value="{{ .CSRF }}">
<input type="hidden" name="save" value="true">
@ -31,6 +50,18 @@
<label for="body">
Content:
</label>
<div id="editor-box">
<div id="ace-editor">{{ .Data.Body }}</div>
</div>
<div id="ace-buttons">
Syntax:
<a href="#" onClick="return setSyntax('html')" class="btn btn-secondary btn-sm">HTML</a>
<a href="#" onClick="return setSyntax('markdown')" class="btn btn-secondary btn-sm">Markdown</a>
<a href="#" onClick="return setSyntax('javascript')" class="btn btn-secondary btn-sm">JS</a>
<a href="#" onClick="return setSyntax('css')" class="btn btn-secondary btn-sm">CSS</a>
<a href="#" onClick="return setSyntax('text')" class="btn btn-secondary btn-sm">None</a>
</div>
<textarea
cols="40"
rows="12"
@ -45,4 +76,49 @@
<button type="submit" name="action" value="delete" class="btn btn-danger" onClick="return window.confirm('Are you sure?')">Delete Page</button>
</p>
</form>
<script src="/js/ace-editor/src-min-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
<script>
var ACE;
(function() {
var editor = ace.edit("ace-editor");
ACE = editor;
document.querySelector("#editor-box").style.display = "block";
document.querySelector("#ace-buttons").style.display = "block";
document.querySelector("#body").style.display = "none";
// Default editor settings
editor.setTheme("ace/theme/monokai");
var ses = editor.getSession();
ses.setTabSize(4);
ses.setUseSoftTabs(true);
// On save.
ses.on("change", function() {
document.getElementById("body").value = editor.getValue();
});
var filename = "{{ .Data.File }}";
var parts = filename.split(".");
var ext = parts.pop().toLowerCase();
if (ext === "js") {
ses.setMode("ace/mode/javascript");
} else if (ext === "gohtml" || ext === "html") {
ses.setMode("ace/mode/html");
} else if (ext === "md" || ext === "markdown") {
ses.setMode("ace/mode/markdown");
ses.setTabSize(2);
} else if (ext === "css") {
ses.setMode("ace/mode/css");
}
})();
function setSyntax(lang) {
if (typeof(ACE) !== undefined) {
ACE.getSession().setMode("ace/mode/"+lang);
}
return false;
}
</script>
{{ end }}

View File

@ -13,6 +13,22 @@
</div>
{{ end }}
<style type="text/css" media="screen">
#editor-box {
position: relative;
display: none;
width: 100%;
height: 500px;
}
#ace-editor {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
</style>
{{ with .Data.post }}
<input type="hidden" name="id" value="{{ .ID }}">
<div class="card">
@ -52,6 +68,7 @@
class="form-check-input"
name="content-type"
value="markdown"
onChange="setSyntax(this.value)"
{{ if eq .ContentType "markdown" }}checked{{ end }}
> Markdown
</label>
@ -62,15 +79,21 @@
class="form-check-input"
name="content-type"
value="html"
onChange="setSyntax(this.value)"
{{ if eq .ContentType "html" }}checked{{ end }}
> Raw HTML
</label>
</div>
<div id="editor-box">
<div id="ace-editor">{{ .Body }}</div>
</div>
<textarea class="form-control"
cols="80"
rows="12"
name="body"
id="body"
placeholder="Post body goes here">{{ .Body }}</textarea>
</div>
@ -137,4 +160,38 @@
{{ end }}
</form>
<script src="/js/ace-editor/src-min-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
<script>
var ACE;
(function() {
var editor = ace.edit("ace-editor");
ACE = editor;
document.querySelector("#editor-box").style.display = "block";
document.querySelector("#body").style.display = "none";
// Default editor settings
editor.setTheme("ace/theme/monokai");
var ses = editor.getSession();
ses.setTabSize(4);
ses.setUseSoftTabs(true);
// On save.
ses.on("change", function() {
document.getElementById("body").value = editor.getValue();
});
setSyntax("markdown");
})();
function setSyntax(lang) {
if (typeof(ACE) !== undefined) {
ACE.getSession().setMode("ace/mode/"+lang);
if (lang === "markdown") {
ACE.getSession().setTabSize(2);
}
}
return false;
}
</script>
{{ end }}