updates on editor
Former-commit-id: 2928727a06a94c0ea87ed821a472ae662df803d1 [formerly 098bc4234803078aba013f6312d179158194fffb] [formerly d2bb681fe62ba87a29b9866e291fb975489cd3fc [formerly 3d25185a55]]
Former-commit-id: 288ccb95466fbd234d278886800e1d27c54fa8dd [formerly 78c473865b085e97cf435cb230e2afa85559aba0]
Former-commit-id: c5dc56f4d6198c9c306c01573e1a1af5f1827c3a
			
			
				pull/726/head
			
			
		
							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',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -90,7 +90,7 @@
 | 
				
			||||||
  </style>
 | 
					  </style>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  {{- if ne .User.StyleSheet "" -}}
 | 
					  {{- if ne .User.StyleSheet "" -}}
 | 
				
			||||||
  <style>{{ CSS .User.StyleSheet }}</style>
 | 
					    <style>{{ CSS .User.StyleSheet }}</style>
 | 
				
			||||||
  {{- end -}}
 | 
					  {{- end -}}
 | 
				
			||||||
</head>
 | 
					</head>
 | 
				
			||||||
<body>
 | 
					<body>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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>* {
 | 
				
			||||||
| 
						 | 
					@ -123,4 +123,4 @@ main {
 | 
				
			||||||
        margin: 0;
 | 
					        margin: 0;
 | 
				
			||||||
        padding: 0 1em;
 | 
					        padding: 0 1em;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -496,4 +496,4 @@ footer a:hover {
 | 
				
			||||||
        -webkit-transform: rotate(-360deg);
 | 
					        -webkit-transform: rotate(-360deg);
 | 
				
			||||||
        transform: rotate(-360deg);
 | 
					        transform: rotate(-360deg);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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,20 +123,20 @@ 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:"-"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func rawToPretty(config interface{}, parent *Block) *Content {
 | 
					func rawToPretty(config interface{}, parent *Block) *Content {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										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