updates on editor
Former-commit-id: 2928727a06a94c0ea87ed821a472ae662df803d1 [formerly 098bc4234803078aba013f6312d179158194fffb] [formerly d2bb681fe62ba87a29b9866e291fb975489cd3fc [formerly 3d25185a557dab1fa529499572c0e6d5bf187ca1]] Former-commit-id: 288ccb95466fbd234d278886800e1d27c54fa8dd [formerly 78c473865b085e97cf435cb230e2afa85559aba0] Former-commit-id: c5dc56f4d6198c9c306c01573e1a1af5f1827c3a
This commit is contained in:
parent
90ba8e18da
commit
cc462c8bca
|
@ -9,7 +9,7 @@ install:
|
||||||
- go get github.com/gordonklaus/ineffassign
|
- go get github.com/gordonklaus/ineffassign
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- sed -i 's/\_ \"github.com\/mholt\/caddy\/caddyhttp\"/\_ \"github.com\/mholt\/caddy\/caddyhttp\"\n\_ \"github.com\/hacdias\/filemanager\/caddy\"/g' $GOPATH/src/github.com/mholt/caddy/caddy/caddymain/run.go
|
- sed -i 's/\_ \"github.com\/mholt\/caddy\/caddyhttp\"/\_ \"github.com\/mholt\/caddy\/caddyhttp\"\n\_ \"github.com\/hacdias\/filemanager\/caddy\/filemanager\"/g' $GOPATH/src/github.com/mholt/caddy/caddy/caddymain/run.go
|
||||||
- go build -o binary github.com/mholt/caddy/caddy
|
- go build -o binary github.com/mholt/caddy/caddy
|
||||||
- go build github.com/hacdias/filemanager
|
- go build github.com/hacdias/filemanager
|
||||||
- ineffassign .
|
- ineffassign .
|
|
@ -30,27 +30,3 @@
|
||||||
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
{{ define "value" }}
|
|
||||||
{{- if eq .HTMLType "textarea" }}
|
|
||||||
<textarea class="scroll" name="{{ .Name }}" id="{{.Name }}" data-parent-type="{{ .Parent.Type }}">{{ .Content.Other }}</textarea>
|
|
||||||
{{- else if eq .HTMLType "datetime" }}
|
|
||||||
<input name="{{ .Name }}" id="{{ .Name }}" value="{{ .Content.Other.Format "2006-01-02T15:04" }}" type="datetime-local" data-parent-type="{{ .Parent.Type }}"></input>
|
|
||||||
{{- else }}
|
|
||||||
<input name="{{ .Name }}" id="{{ .Name }}" value="{{ .Content.Other }}" type="{{ .HTMLType }}" data-parent-type="{{ .Parent.Type }}"></input>
|
|
||||||
{{- end }}
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
{{ define "fielset" }}
|
|
||||||
<fieldset id="{{ .Name }}" data-type="{{ .Type }}">
|
|
||||||
{{- if not (eq .Title "") }}
|
|
||||||
<h3>{{ .Name }}</h3>
|
|
||||||
{{- end }}
|
|
||||||
<div class="action add">
|
|
||||||
<i class="material-icons" title="Add">add</i>
|
|
||||||
</div>
|
|
||||||
<div class="action delete" data-delete="{{ .Name }}">
|
|
||||||
<i class="material-icons" title="Close">close</i>
|
|
||||||
</div>
|
|
||||||
{{- template "blocks" .Content }}
|
|
||||||
</fieldset>
|
|
||||||
{{ end }}
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
{{ define "sidebar-addon" }}
|
|
||||||
<a class="action" href="{{ .BaseURL }}/content/">
|
|
||||||
<i class="material-icons">subject</i>
|
|
||||||
<span>Posts and Pages</span>
|
|
||||||
</a>
|
|
||||||
<a class="action" href="{{ .BaseURL }}/themes/">
|
|
||||||
<i class="material-icons">format_paint</i>
|
|
||||||
<span>Themes</span>
|
|
||||||
</a>
|
|
||||||
<a class="action" href="{{ .BaseURL }}/settings/">
|
|
||||||
<i class="material-icons">settings</i>
|
|
||||||
<span>Settings</span>
|
|
||||||
</a>
|
|
||||||
{{ end }}
|
|
|
@ -1,23 +0,0 @@
|
||||||
{{ define "templates" }}
|
|
||||||
<template id="question-template">
|
|
||||||
<form class="prompt">
|
|
||||||
<h3></h3>
|
|
||||||
<p></p>
|
|
||||||
<input autofocus type="text">
|
|
||||||
<div>
|
|
||||||
<button type="submit" autofocus class="ok">OK</button>
|
|
||||||
<button class="cancel" onclick="closePrompt(event);">Cancel</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template id="message-template">
|
|
||||||
<div class="prompt">
|
|
||||||
<h3></h3>
|
|
||||||
<p></p>
|
|
||||||
<div>
|
|
||||||
<button type="submit" onclick="closePrompt(event);" class="ok">OK</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
{{ end }}
|
|
|
@ -41,6 +41,11 @@ module.exports = {
|
||||||
loader: 'vue-loader',
|
loader: 'vue-loader',
|
||||||
options: vueLoaderConfig
|
options: vueLoaderConfig
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
test: /\.css$/,
|
||||||
|
include: /node_modules/,
|
||||||
|
loader: 'style!css'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
test: /\.js$/,
|
test: /\.js$/,
|
||||||
loader: 'babel-loader',
|
loader: 'babel-loader',
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
<i class="material-icons">folder</i>
|
<i class="material-icons">folder</i>
|
||||||
<span>My Files</span>
|
<span>My Files</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div v-if="user.allowNew">
|
<div v-if="user.allowNew">
|
||||||
<button @click="$store.commit('showNewDir', true)" aria-label="New directory" title="New directory" class="action">
|
<button @click="$store.commit('showNewDir', true)" aria-label="New directory" title="New directory" class="action">
|
||||||
<i class="material-icons">create_new_folder</i>
|
<i class="material-icons">create_new_folder</i>
|
||||||
|
@ -36,6 +37,14 @@
|
||||||
<span>New file</span>
|
<span>New file</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-for="plugin in plugins">
|
||||||
|
<button v-for="action in plugin.sidebar" @click="action.click" :aria-label="action.name" :title="action.name" class="action">
|
||||||
|
<i class="material-icons">{{ action.icon }}</i>
|
||||||
|
<span>{{ action.name }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button class="action" id="logout" tabindex="0" role="button" aria-label="Log out">
|
<button class="action" id="logout" tabindex="0" role="button" aria-label="Log out">
|
||||||
<i class="material-icons" title="Logout">exit_to_app</i>
|
<i class="material-icons" title="Logout">exit_to_app</i>
|
||||||
<span>Logout</span>
|
<span>Logout</span>
|
||||||
|
@ -134,10 +143,19 @@ export default {
|
||||||
'showDownload'
|
'showDownload'
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
data: function () {
|
||||||
|
return {
|
||||||
|
plugins: []
|
||||||
|
}
|
||||||
|
},
|
||||||
mounted: function () {
|
mounted: function () {
|
||||||
updateColumnSizes()
|
updateColumnSizes()
|
||||||
window.addEventListener('resize', updateColumnSizes)
|
window.addEventListener('resize', updateColumnSizes)
|
||||||
|
|
||||||
|
if (window.plugins !== undefined || window.plugins !== null) {
|
||||||
|
this.plugins = window.plugins
|
||||||
|
}
|
||||||
|
|
||||||
document.title = this.req.data.name
|
document.title = this.req.data.name
|
||||||
window.history.replaceState({
|
window.history.replaceState({
|
||||||
url: window.location.pathname,
|
url: window.location.pathname,
|
||||||
|
|
|
@ -1,16 +1,30 @@
|
||||||
<template>
|
<template>
|
||||||
<form id="editor">
|
<form id="editor">
|
||||||
<h2 v-if="editor.type == 'complete'">Metadata</h2>
|
<h2 v-if="req.data.editor.type == 'complete'">Metadata</h2>
|
||||||
|
|
||||||
<h2 v-if="editor.type == 'complete'">Body</h2>
|
<h2 v-if="req.data.editor.type == 'complete'">Body</h2>
|
||||||
|
|
||||||
|
<div v-if="req.data.editor.type !== 'frontmatter-only'" class="content">
|
||||||
|
<div id="ace"></div>
|
||||||
|
<textarea id="source" name="content">{{ req.data.content }}</textarea>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { mapState } from 'vuex'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'editor',
|
name: 'editor',
|
||||||
|
computed: mapState(['req']),
|
||||||
data: function () {
|
data: function () {
|
||||||
return window.info.req.data
|
return {
|
||||||
|
codemirror: null,
|
||||||
|
simplemde: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted: function () {
|
||||||
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
<template>
|
||||||
|
<fieldset :id="name" :data-type="type">
|
||||||
|
<h3 v-if="title !== ''">{{ name }}</h3>
|
||||||
|
<div class="action add">
|
||||||
|
<i class="material-icons" title="Add">add</i>
|
||||||
|
</div>
|
||||||
|
<div class="action delete" :data-delete="name">
|
||||||
|
<i class="material-icons" title="Close">close</i>
|
||||||
|
</div>
|
||||||
|
<!-- template blocks w/ content -->
|
||||||
|
</fieldset>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'array-object',
|
||||||
|
props: ['name', 'type', 'title', 'content']
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,28 @@
|
||||||
|
<template>
|
||||||
|
<textarea v-if="htmlType === 'textarea'"
|
||||||
|
class="scroll"
|
||||||
|
:name="name"
|
||||||
|
:id="name"
|
||||||
|
:data-parent-type="parentType">
|
||||||
|
{{ content.other }}
|
||||||
|
</textarea>
|
||||||
|
<input v-else-if="htmlType ==='datatime'"
|
||||||
|
:name="name"
|
||||||
|
:id="name"
|
||||||
|
:value="content.other"
|
||||||
|
type="datetime-local"
|
||||||
|
:data-parent-type="parentType"></input>
|
||||||
|
<input v-else
|
||||||
|
:name="name"
|
||||||
|
:id="name"
|
||||||
|
:value="content.other"
|
||||||
|
:type="htmlType"
|
||||||
|
:data-parent-type="parentType"></input>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'value',
|
||||||
|
props: ['htmlType', 'name', 'parentType', 'content']
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -26,7 +26,12 @@ export default {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
if (this.new === '') return
|
if (this.new === '') return
|
||||||
|
|
||||||
let url = window.location.pathname + this.name + '/'
|
let url = window.location.pathname
|
||||||
|
if (this.$store.state.req.kind !== 'listing') {
|
||||||
|
url = page.removeLastDir(url) + '/'
|
||||||
|
}
|
||||||
|
|
||||||
|
url += this.name + '/'
|
||||||
url = url.replace('//', '/')
|
url = url.replace('//', '/')
|
||||||
|
|
||||||
// buttons.setLoading('newDir')
|
// buttons.setLoading('newDir')
|
||||||
|
|
|
@ -26,11 +26,19 @@ export default {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
if (this.new === '') return
|
if (this.new === '') return
|
||||||
|
|
||||||
|
let url = window.location.pathname
|
||||||
|
if (this.$store.state.req.kind !== 'listing') {
|
||||||
|
url = page.removeLastDir(url) + '/'
|
||||||
|
}
|
||||||
|
|
||||||
|
url += this.name
|
||||||
|
url = url.replace('//', '/')
|
||||||
|
|
||||||
// buttons.setLoading('newFile')
|
// buttons.setLoading('newFile')
|
||||||
webdav.create(window.location.pathname + this.name)
|
webdav.create(url)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// buttons.setDone('newFile')
|
// buttons.setDone('newFile')
|
||||||
page.open(window.location.pathname + this.name)
|
page.open(url)
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
// buttons.setDone('newFile', false)
|
// buttons.setDone('newFile', false)
|
||||||
|
|
|
@ -51,6 +51,7 @@ export default {
|
||||||
},
|
},
|
||||||
back: function (event) {
|
back: function (event) {
|
||||||
let url = page.removeLastDir(window.location.pathname)
|
let url = page.removeLastDir(window.location.pathname)
|
||||||
|
if (url === '') url = '/'
|
||||||
page.open(url)
|
page.open(url)
|
||||||
},
|
},
|
||||||
allowEdit: function (event) {
|
allowEdit: function (event) {
|
||||||
|
|
|
@ -94,9 +94,9 @@ nav .action {
|
||||||
padding: .5em;
|
padding: .5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav>div {
|
nav > .action:last-child,
|
||||||
|
nav > div {
|
||||||
border-top: 1px solid rgba(0, 0, 0, 0.05);
|
border-top: 1px solid rgba(0, 0, 0, 0.05);
|
||||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nav .action>* {
|
nav .action>* {
|
||||||
|
|
|
@ -15,7 +15,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hacdias/filemanager"
|
. "github.com/hacdias/filemanager"
|
||||||
"github.com/mholt/caddy"
|
"github.com/mholt/caddy"
|
||||||
"github.com/mholt/caddy/caddyhttp/httpserver"
|
"github.com/mholt/caddy/caddyhttp/httpserver"
|
||||||
)
|
)
|
||||||
|
@ -27,18 +27,22 @@ func init() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileManager is an http.Handler that can show a file listing when
|
type plugin struct {
|
||||||
// directories in the given paths are specified.
|
|
||||||
type FileManager struct {
|
|
||||||
Next httpserver.Handler
|
Next httpserver.Handler
|
||||||
Configs []*filemanager.FileManager
|
Configs []*config
|
||||||
|
}
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
*FileManager
|
||||||
|
baseURL string
|
||||||
|
webDavURL string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeHTTP determines if the request is for this plugin, and if all prerequisites are met.
|
// ServeHTTP determines if the request is for this plugin, and if all prerequisites are met.
|
||||||
func (f FileManager) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
func (f plugin) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||||
for i := range f.Configs {
|
for i := range f.Configs {
|
||||||
// Checks if this Path should be handled by File Manager.
|
// Checks if this Path should be handled by File Manager.
|
||||||
if !httpserver.Path(r.URL.Path).Matches(f.Configs[i].BaseURL) {
|
if !httpserver.Path(r.URL.Path).Matches(f.Configs[i].baseURL) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,21 +60,21 @@ func setup(c *caddy.Controller) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
|
httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
|
||||||
return FileManager{Configs: configs, Next: next}
|
return plugin{Configs: configs, Next: next}
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parse(c *caddy.Controller) ([]*filemanager.FileManager, error) {
|
func parse(c *caddy.Controller) ([]*config, error) {
|
||||||
var (
|
var (
|
||||||
configs []*filemanager.FileManager
|
configs []*config
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
for c.Next() {
|
for c.Next() {
|
||||||
var (
|
var (
|
||||||
m = filemanager.New(".")
|
m = &config{FileManager: New(".")}
|
||||||
u = m.User
|
u = m.User
|
||||||
name = ""
|
name = ""
|
||||||
)
|
)
|
||||||
|
@ -79,7 +83,7 @@ func parse(c *caddy.Controller) ([]*filemanager.FileManager, error) {
|
||||||
|
|
||||||
m.SetPrefixURL(strings.TrimSuffix(caddyConf.Addr.Path, "/"))
|
m.SetPrefixURL(strings.TrimSuffix(caddyConf.Addr.Path, "/"))
|
||||||
m.Commands = []string{"git", "svn", "hg"}
|
m.Commands = []string{"git", "svn", "hg"}
|
||||||
m.Rules = append(m.Rules, &filemanager.Rule{
|
m.Rules = append(m.Rules, &Rule{
|
||||||
Regex: true,
|
Regex: true,
|
||||||
Allow: false,
|
Allow: false,
|
||||||
Regexp: regexp.MustCompile("\\/\\..+"),
|
Regexp: regexp.MustCompile("\\/\\..+"),
|
||||||
|
@ -89,18 +93,19 @@ func parse(c *caddy.Controller) ([]*filemanager.FileManager, error) {
|
||||||
args := c.RemainingArgs()
|
args := c.RemainingArgs()
|
||||||
|
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
|
m.baseURL = args[0]
|
||||||
|
m.webDavURL = "/webdav"
|
||||||
m.SetBaseURL(args[0])
|
m.SetBaseURL(args[0])
|
||||||
m.SetWebDavURL("/webdav")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for c.NextBlock() {
|
for c.NextBlock() {
|
||||||
switch c.Val() {
|
switch c.Val() {
|
||||||
case "before_save":
|
case "before_save":
|
||||||
if m.BeforeSave, err = makeCommand(c); err != nil {
|
if m.BeforeSave, err = makeCommand(c, m); err != nil {
|
||||||
return configs, err
|
return configs, err
|
||||||
}
|
}
|
||||||
case "after_save":
|
case "after_save":
|
||||||
if m.AfterSave, err = makeCommand(c); err != nil {
|
if m.AfterSave, err = makeCommand(c, m); err != nil {
|
||||||
return configs, err
|
return configs, err
|
||||||
}
|
}
|
||||||
case "webdav":
|
case "webdav":
|
||||||
|
@ -108,6 +113,7 @@ func parse(c *caddy.Controller) ([]*filemanager.FileManager, error) {
|
||||||
return configs, c.ArgErr()
|
return configs, c.ArgErr()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m.webDavURL = "c.Val()"
|
||||||
m.SetWebDavURL(c.Val())
|
m.SetWebDavURL(c.Val())
|
||||||
case "show":
|
case "show":
|
||||||
if !c.NextArg() {
|
if !c.NextArg() {
|
||||||
|
@ -185,7 +191,7 @@ func parse(c *caddy.Controller) ([]*filemanager.FileManager, error) {
|
||||||
ruleType += "_r"
|
ruleType += "_r"
|
||||||
}
|
}
|
||||||
|
|
||||||
rule := &filemanager.Rule{
|
rule := &Rule{
|
||||||
Allow: ruleType == "allow" || ruleType == "allow_r",
|
Allow: ruleType == "allow" || ruleType == "allow_r",
|
||||||
Regex: ruleType == "allow_r" || ruleType == "block_r",
|
Regex: ruleType == "allow_r" || ruleType == "block_r",
|
||||||
}
|
}
|
||||||
|
@ -215,14 +221,16 @@ func parse(c *caddy.Controller) ([]*filemanager.FileManager, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m.baseURL = strings.TrimSuffix(m.baseURL, "/")
|
||||||
|
m.webDavURL = strings.TrimSuffix(m.webDavURL, "/")
|
||||||
configs = append(configs, m)
|
configs = append(configs, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
return configs, nil
|
return configs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeCommand(c *caddy.Controller) (filemanager.Command, error) {
|
func makeCommand(c *caddy.Controller, m *config) (Command, error) {
|
||||||
fn := func(r *http.Request, c *filemanager.FileManager, u *filemanager.User) error { return nil }
|
fn := func(r *http.Request, c *FileManager, u *User) error { return nil }
|
||||||
|
|
||||||
args := c.RemainingArgs()
|
args := c.RemainingArgs()
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
|
@ -241,8 +249,8 @@ func makeCommand(c *caddy.Controller) (filemanager.Command, error) {
|
||||||
return fn, c.Err(err.Error())
|
return fn, c.Err(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn = func(r *http.Request, c *filemanager.FileManager, u *filemanager.User) error {
|
fn = func(r *http.Request, c *FileManager, u *User) error {
|
||||||
path := strings.Replace(r.URL.Path, c.WebDavURL, "", 1)
|
path := strings.Replace(r.URL.Path, m.baseURL+m.webDavURL, "", 1)
|
||||||
path = u.Scope() + "/" + path
|
path = u.Scope() + "/" + path
|
||||||
path = filepath.Clean(path)
|
path = filepath.Clean(path)
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
# hugo - a caddy plugin
|
||||||
|
|
||||||
|
[](https://caddy.community)
|
||||||
|
|
||||||
|
hugo fills the gap between Hugo and the browser. [Hugo](http://gohugo.io/) is an easy and fast static website generator. This plugin fills the gap between Hugo and the end-user, providing you a web interface to manage the whole website.
|
||||||
|
|
||||||
|
Using this plugin, you won't need to have your own computer to edit posts, neither regenerate your static website, because you can do all of that just through your browser.
|
||||||
|
|
||||||
|
**Requirements:** you need to have the hugo executable in your PATH. You can download it from its [official page](http://gohugo.io).
|
||||||
|
|
||||||
|
### Syntax
|
||||||
|
|
||||||
|
```
|
||||||
|
hugo [directory] [admin] {
|
||||||
|
clean_public [true|false]
|
||||||
|
before_publish command
|
||||||
|
after_publish command
|
||||||
|
flag name [value]
|
||||||
|
# other file manager compatible options
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
All of the options above are optional.
|
||||||
|
|
||||||
|
* **directory** is the folder where the commands are going to be executed. By default, it is the current working directory. Default: `./`.
|
||||||
|
* **admin** is the path where you will find your administration interface. Default: `/admin`.
|
||||||
|
* **clean_public** sets if the `public` folder should be removed before generating the website again. Default: `true`.
|
||||||
|
* **before_publish** and **after_publish** allow you to set a custom command to be executed before publishing and after publishing a post/page. The placeholder `{path}` can be used and it will be replaced by the file path.
|
||||||
|
* **name** refers to the Hugo available flags. Please use their long form without `--` in the beginning. If no **value** is set, it will be evaluated as `true`.
|
||||||
|
|
||||||
|
In spite of these options, you can also use the [filemanager](https://caddyserver.com/docs/http.filemanager) so you can have more control about what can be acceded, the permissions of each user, and so on.
|
||||||
|
|
||||||
|
This directive should be used with [root](https://caddyserver.com/docs/root), [basicauth](https://caddyserver.com/docs/basicauth) and [errors](https://caddyserver.com/docs/errors) middleware to have the best experience. See the examples to know more.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
If you don't already have an Hugo website, don't worry. This plugin will auto-generate it for you. But that's not everything. It is recommended that you take a look at Hugo [documentation](http://gohugo.io/themes/overview/) to learn more about themes, content types, and so on.
|
||||||
|
|
||||||
|
A simple Caddyfile to use with Hugo static website generator:
|
||||||
|
|
||||||
|
```
|
||||||
|
root public # the folder where Hugo generates the website
|
||||||
|
basicauth /admin user pass # protect the admin area using HTTP basic auth
|
||||||
|
hugo # enable the admin panel
|
||||||
|
```
|
||||||
|
|
||||||
|
### Screenshots
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|

|
|
@ -0,0 +1 @@
|
||||||
|
package hugo
|
|
@ -0,0 +1,42 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
if (window.plugins === undefined || window.plugins === null) {
|
||||||
|
window.plugins = []
|
||||||
|
}
|
||||||
|
|
||||||
|
window.plugins.append({
|
||||||
|
sidebar: [
|
||||||
|
{
|
||||||
|
click: function (event) {
|
||||||
|
console.log('evt')
|
||||||
|
},
|
||||||
|
icon: 'settings_applications',
|
||||||
|
name: 'Settings'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
click: function (event) {
|
||||||
|
console.log('evt')
|
||||||
|
},
|
||||||
|
icon: 'remove_red_eye',
|
||||||
|
name: 'Preview'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
{{ define "sidebar-addon" }}
|
||||||
|
<a class="action" href="{{ .BaseURL }}/content/">
|
||||||
|
<i class="material-icons">subject</i>
|
||||||
|
<span>Posts and Pages</span>
|
||||||
|
</a>
|
||||||
|
<a class="action" href="{{ .BaseURL }}/themes/">
|
||||||
|
<i class="material-icons">format_paint</i>
|
||||||
|
<span>Themes</span>
|
||||||
|
</a>
|
||||||
|
<a class="action" href="{{ .BaseURL }}/settings/">
|
||||||
|
<i class="material-icons">settings</i>
|
||||||
|
<span>Settings</span>
|
||||||
|
</a>
|
||||||
|
{{ end }}
|
||||||
|
*/
|
|
@ -1,31 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/hacdias/filemanager"
|
|
||||||
)
|
|
||||||
|
|
||||||
var m *filemanager.FileManager
|
|
||||||
|
|
||||||
func handler(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// TODO: review return codes and return 0 when everything works.
|
|
||||||
|
|
||||||
code, err := m.ServeHTTP(w, r)
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if code != 0 {
|
|
||||||
w.WriteHeader(code)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
m = filemanager.New("D:\\TEST")
|
|
||||||
m.SetBaseURL("/vaca")
|
|
||||||
m.Commands = []string{"git"}
|
|
||||||
http.HandleFunc("/", handler)
|
|
||||||
http.ListenAndServe(":80", nil)
|
|
||||||
}
|
|
|
@ -123,19 +123,19 @@ func Marshal(data interface{}, mark rune) ([]byte, error) {
|
||||||
|
|
||||||
// Content is the block content
|
// Content is the block content
|
||||||
type Content struct {
|
type Content struct {
|
||||||
Other interface{}
|
Other interface{} `json:"other"`
|
||||||
Fields []*Block
|
Fields []*Block `json:"fields"`
|
||||||
Arrays []*Block
|
Arrays []*Block `json:"arrays"`
|
||||||
Objects []*Block
|
Objects []*Block `json:"objects"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block is a block
|
// Block is a block
|
||||||
type Block struct {
|
type Block struct {
|
||||||
Name string
|
Name string `json:"name"`
|
||||||
Title string
|
Title string `json:"title"`
|
||||||
Type string
|
Type string `json:"type"`
|
||||||
HTMLType string
|
HTMLType string `json:"htmlType"`
|
||||||
Content *Content
|
Content *Content `json:"content"`
|
||||||
Parent *Block `json:"-"`
|
Parent *Block `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
http.go
2
http.go
|
@ -27,7 +27,7 @@ func serveHTTP(c *requestContext, w http.ResponseWriter, r *http.Request) (int,
|
||||||
|
|
||||||
// Checks if the URL contains the baseURL. If so, it strips it. Otherwise,
|
// Checks if the URL contains the baseURL. If so, it strips it. Otherwise,
|
||||||
// it throws an error.
|
// it throws an error.
|
||||||
if p := strings.TrimPrefix(r.URL.Path, c.fm.baseURL); len(p) < len(r.URL.Path) {
|
if p := strings.TrimPrefix(r.URL.Path, c.fm.baseURL); len(p) < len(r.URL.Path) || len(c.fm.baseURL) == 0 {
|
||||||
r.URL.Path = p
|
r.URL.Path = p
|
||||||
} else {
|
} else {
|
||||||
return http.StatusNotFound, nil
|
return http.StatusNotFound, nil
|
||||||
|
|
Loading…
Reference in New Issue