ACE Code Editor for Pages and Blogs
This commit is contained in:
parent
d8254826c2
commit
9e58456aaa
|
@ -20,11 +20,11 @@ import (
|
||||||
|
|
||||||
// AdminRoutes attaches the admin routes to the app.
|
// AdminRoutes attaches the admin routes to the app.
|
||||||
func (b *Blog) AdminRoutes(r *mux.Router) {
|
func (b *Blog) AdminRoutes(r *mux.Router) {
|
||||||
adminRouter := mux.NewRouter().PathPrefix("/admin").Subrouter().StrictSlash(false)
|
adminRouter := mux.NewRouter().PathPrefix("/admin").Subrouter().StrictSlash(true)
|
||||||
r.HandleFunc("/admin", b.AdminHandler) // so as to not be "/admin/"
|
adminRouter.HandleFunc("/", b.AdminHandler)
|
||||||
adminRouter.HandleFunc("/settings", b.SettingsHandler)
|
adminRouter.HandleFunc("/settings", b.SettingsHandler)
|
||||||
adminRouter.HandleFunc("/editor", b.EditorHandler)
|
adminRouter.HandleFunc("/editor", b.EditorHandler)
|
||||||
adminRouter.PathPrefix("/").HandlerFunc(b.PageHandler)
|
// r.HandleFunc("/admin", b.AdminHandler)
|
||||||
r.PathPrefix("/admin").Handler(negroni.New(
|
r.PathPrefix("/admin").Handler(negroni.New(
|
||||||
negroni.HandlerFunc(b.LoginRequired),
|
negroni.HandlerFunc(b.LoginRequired),
|
||||||
negroni.Wrap(adminRouter),
|
negroni.Wrap(adminRouter),
|
||||||
|
|
|
@ -60,6 +60,7 @@ func (b *Blog) PageHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
b.RenderTemplate(w, r, ".markdown", NewVars(map[interface{}]interface{}{
|
b.RenderTemplate(w, r, ".markdown", NewVars(map[interface{}]interface{}{
|
||||||
"Title": title,
|
"Title": title,
|
||||||
"HTML": template.HTML(html),
|
"HTML": template.HTML(html),
|
||||||
|
"MarkdownFile": filepath.URI,
|
||||||
}))
|
}))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@
|
||||||
|
|
||||||
{{ if and .CurrentUser.Admin .Editable }}
|
{{ if and .CurrentUser.Admin .Editable }}
|
||||||
<p class="mt-4">
|
<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>
|
</p>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -197,7 +197,6 @@
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script type="text/javascript" src="/js/bootstrap.min.js"></script>
|
|
||||||
{{ template "scripts" or "" }}
|
{{ template "scripts" or "" }}
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -9,6 +9,25 @@
|
||||||
</p>
|
</p>
|
||||||
{{ end }}
|
{{ 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">
|
<form action="/admin/editor" method="POST">
|
||||||
<input type="hidden" name="_csrf" value="{{ .CSRF }}">
|
<input type="hidden" name="_csrf" value="{{ .CSRF }}">
|
||||||
<input type="hidden" name="save" value="true">
|
<input type="hidden" name="save" value="true">
|
||||||
|
@ -31,6 +50,18 @@
|
||||||
<label for="body">
|
<label for="body">
|
||||||
Content:
|
Content:
|
||||||
</label>
|
</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
|
<textarea
|
||||||
cols="40"
|
cols="40"
|
||||||
rows="12"
|
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>
|
<button type="submit" name="action" value="delete" class="btn btn-danger" onClick="return window.confirm('Are you sure?')">Delete Page</button>
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</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 }}
|
{{ end }}
|
||||||
|
|
|
@ -13,6 +13,22 @@
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ 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 }}
|
{{ with .Data.post }}
|
||||||
<input type="hidden" name="id" value="{{ .ID }}">
|
<input type="hidden" name="id" value="{{ .ID }}">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
|
@ -52,6 +68,7 @@
|
||||||
class="form-check-input"
|
class="form-check-input"
|
||||||
name="content-type"
|
name="content-type"
|
||||||
value="markdown"
|
value="markdown"
|
||||||
|
onChange="setSyntax(this.value)"
|
||||||
{{ if eq .ContentType "markdown" }}checked{{ end }}
|
{{ if eq .ContentType "markdown" }}checked{{ end }}
|
||||||
> Markdown
|
> Markdown
|
||||||
</label>
|
</label>
|
||||||
|
@ -62,15 +79,21 @@
|
||||||
class="form-check-input"
|
class="form-check-input"
|
||||||
name="content-type"
|
name="content-type"
|
||||||
value="html"
|
value="html"
|
||||||
|
onChange="setSyntax(this.value)"
|
||||||
{{ if eq .ContentType "html" }}checked{{ end }}
|
{{ if eq .ContentType "html" }}checked{{ end }}
|
||||||
> Raw HTML
|
> Raw HTML
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="editor-box">
|
||||||
|
<div id="ace-editor">{{ .Body }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<textarea class="form-control"
|
<textarea class="form-control"
|
||||||
cols="80"
|
cols="80"
|
||||||
rows="12"
|
rows="12"
|
||||||
name="body"
|
name="body"
|
||||||
|
id="body"
|
||||||
placeholder="Post body goes here">{{ .Body }}</textarea>
|
placeholder="Post body goes here">{{ .Body }}</textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -137,4 +160,38 @@
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
</form>
|
</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 }}
|
{{ end }}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user