From 5770cacc0b89b3764d034783145b61b82da590e4 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Tue, 18 Jul 2017 16:17:52 +0100 Subject: [PATCH] Build assets Former-commit-id: 6120690135d01eb433007a5428c4137d84c8b69f [formerly c1848ff09d902d8e7c53bde6219a2e8bc43f94ff] [formerly 3b1cef773ebae303bb6f149f7c6cd0ebb130943e [formerly 0ae8aa5e19c349564df718c7af43a449b4af77a2]] Former-commit-id: b7beb1d31b8ea24a78410e089fa498f238c32f86 [formerly b0c28eb4f0fd4f0b1b88d2afe5ccd9fbe50b30b3] Former-commit-id: 87e10e61eb829526619b29e67e65dfde64bcf670 --- caddy/hugo/rice-box.go | 4 ++-- rice-box.go.REMOVED.git-id | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/caddy/hugo/rice-box.go b/caddy/hugo/rice-box.go index 1f8c4d66..56f5127c 100644 --- a/caddy/hugo/rice-box.go +++ b/caddy/hugo/rice-box.go @@ -25,8 +25,8 @@ func init() { } file5 := &embedded.EmbeddedFile{ Filename: `rice-box.go`, - FileModTime: time.Unix(1500388549, 0), - Content: string("package hugo\n\nimport (\n\t\"github.com/GeertJohan/go.rice/embedded\"\n\t\"time\"\n)\n\nfunc init() {\n\n\t// define files\n\tfile2 := &embedded.EmbeddedFile{\n\t\tFilename: `README.md`,\n\t\tFileModTime: time.Unix(1500388454, 0),\n\t\tContent: string(\"# hugo - a caddy plugin\\n\\n[![community](https://img.shields.io/badge/community-forum-ff69b4.svg?style=flat-square)](https://caddy.community)\\n\\nhugo fills the gap between Hugo and the browser. [Hugo][6] 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.\\n\\nUsing 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. It is an implementation of [hacdias/filemanager][1] library.\\n\\n**Requirements:** you need to have the hugo executable in your PATH. You can download it from its [official page][6].\\n\\n## Get Started\\n\\nTo start using this plugin you just need to go to the [download Caddy page][3] and choose `http.hugo` in the directives section. For further information on how Caddy works refer to [its documentation][4].\\n\\nThe default credentials are `admin` for both the user and the password. It is highy recommended to change them after logging in for the first time and to use HTTPS. You can create more users and define their own permissions using the web interface.\\n\\n## Syntax\\n\\n```\\nhugo [directory] [admin] {\\n database path\\n}\\n```\\n\\n+ `directory` is the path, relative or absolute to the directory of your Hugo files. Defaults to `./`.\\n+ `admin` is the URL path where you will access the admin interface. Defaults to `/admin`.\\n+ `path` is the database path where the settings will be stored. By default, the settings will be stored on [`.caddy`][5] folder.\\n\\n## Database\\n\\nBy default the database will be stored on [`.caddy`][5] directory, in a sub-directory called `hugo`. Each file name is an hash of the combination of the host and the base URL.\\n\\nIf you don't set a database path, you will receive a warning like this:\\n\\n> [WARNING] A database is going to be created for your File Manager instace at ~/.caddy/hugo/xxx.db. It is highly recommended that you set the 'database' option to 'xxx.db'\\n\\nWhy? If you don't set a database path and you change the host or the base URL, your settings will be reseted. So it is *highly* recommended to set this option.\\n\\nWhen you set a relative path, such as `xxxxxxxxxx.db`, it will always be relative to `.caddy/hugo` directory. Although, you may also use an absolute path if you wish to store the database in other place.\\n\\n## Examples\\n\\nManage the current working directory's Hugo website at `/admin`.\\n\\n```\\nroot public\\nhugo {\\n database myinstance.db\\n}\\n```\\n\\nManage the Hugo website located at `/var/www/mysite` at `/admin`.\\n\\n```\\nroot /var/www/mysite/public\\nhugo /var/www/mysite {\\n database myinstance.db\\n}\\n```\\n\\nManage the Hugo website located at `/var/www/mysite` at `/private`.\\n\\n```\\nroot /var/www/mysite/public\\nhugo /var/www/mysite /private {\\n database myinstance.db\\n}\\n```\\n\\n## Known Issues\\n\\nIf you are having troubles **handling large files** you might need to check out the [`timeouts`][2] plugin, which can be used to change the default HTTP Timeouts.\\n\\n[1]:https://github.com/hacdias/filemanager\\n[2]:https://caddyserver.com/docs/timeouts\\n[3]:https://caddyserver.com/download\\n[4]:https://caddyserver.com/docs\\n[5]:https://caddyserver.com/docs/automatic-https#dot-caddy\\n[6]:http://gohugo.io\\n\"),\n\t}\n\tfile3 := &embedded.EmbeddedFile{\n\t\tFilename: `hugo.go`,\n\t\tFileModTime: time.Unix(1500387945, 0),\n\t\tContent: string(\"package hugo\\r\\n\\r\\nimport (\\r\\n\\t\\\"log\\\"\\r\\n\\t\\\"net/http\\\"\\r\\n\\t\\\"os\\\"\\r\\n\\t\\\"path/filepath\\\"\\r\\n\\t\\\"strings\\\"\\r\\n\\t\\\"time\\\"\\r\\n\\r\\n\\trice \\\"github.com/GeertJohan/go.rice\\\"\\r\\n\\t\\\"github.com/hacdias/filemanager\\\"\\r\\n\\t\\\"github.com/hacdias/filemanager/variables\\\"\\r\\n\\t\\\"github.com/robfig/cron\\\"\\r\\n)\\r\\n\\r\\ntype hugo struct {\\r\\n\\t// Website root\\r\\n\\tRoot string `description:\\\"The relative or absolute path to the place where your website is located.\\\"`\\r\\n\\t// Public folder\\r\\n\\tPublic string `description:\\\"The relative or absolute path to the public folder.\\\"`\\r\\n\\t// Hugo executable path\\r\\n\\tExe string `description:\\\"The absolute path to the Hugo executable or the command to execute.\\\"`\\r\\n\\t// Hugo arguments\\r\\n\\tArgs []string `description:\\\"The arguments to run when running Hugo\\\"`\\r\\n\\t// Indicates if we should clean public before a new publish.\\r\\n\\tCleanPublic bool `description:\\\"Indicates if the public folder should be cleaned before publishing the website.\\\"`\\r\\n\\r\\n\\t// TODO: admin interface to cgange options\\r\\n}\\r\\n\\r\\nfunc (h hugo) BeforeAPI(c *filemanager.RequestContext, w http.ResponseWriter, r *http.Request) (int, error) {\\r\\n\\t// If we are using the 'magic url' for the settings, we should redirect the\\r\\n\\t// request for the acutual path.\\r\\n\\tif r.URL.Path == \\\"/settings/\\\" || r.URL.Path == \\\"/settings\\\" {\\r\\n\\t\\tvar frontmatter string\\r\\n\\t\\tvar err error\\r\\n\\r\\n\\t\\tif _, err = os.Stat(filepath.Join(h.Root, \\\"config.yaml\\\")); err == nil {\\r\\n\\t\\t\\tfrontmatter = \\\"yaml\\\"\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tif _, err = os.Stat(filepath.Join(h.Root, \\\"config.json\\\")); err == nil {\\r\\n\\t\\t\\tfrontmatter = \\\"json\\\"\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tif _, err = os.Stat(filepath.Join(h.Root, \\\"config.toml\\\")); err == nil {\\r\\n\\t\\t\\tfrontmatter = \\\"toml\\\"\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tr.URL.Path = \\\"/config.\\\" + frontmatter\\r\\n\\t\\treturn 0, nil\\r\\n\\t}\\r\\n\\r\\n\\t// From here on, we only care about 'hugo' router so we can bypass\\r\\n\\t// the others.\\r\\n\\tif c.Router != \\\"hugo\\\" {\\r\\n\\t\\treturn 0, nil\\r\\n\\t}\\r\\n\\r\\n\\t// If we are not using HTTP Post, we shall return Method Not Allowed\\r\\n\\t// since we are only working with this method.\\r\\n\\tif r.Method != http.MethodPost {\\r\\n\\t\\treturn http.StatusMethodNotAllowed, nil\\r\\n\\t}\\r\\n\\r\\n\\t// If we are creating a file built from an archetype.\\r\\n\\tif r.Header.Get(\\\"Archetype\\\") != \\\"\\\" {\\r\\n\\t\\tif !c.User.AllowNew {\\r\\n\\t\\t\\treturn http.StatusForbidden, nil\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tfilename := filepath.Join(string(c.User.FileSystem), r.URL.Path)\\r\\n\\t\\tfilename = strings.TrimPrefix(filename, \\\"/\\\")\\r\\n\\t\\tarchetype := r.Header.Get(\\\"archetype\\\")\\r\\n\\r\\n\\t\\text := filepath.Ext(filename)\\r\\n\\r\\n\\t\\t// If the request isn't for a markdown file, we can't\\r\\n\\t\\t// handle it.\\r\\n\\t\\tif ext != \\\".markdown\\\" && ext != \\\".md\\\" {\\r\\n\\t\\t\\treturn http.StatusBadRequest, errUnsupportedFileType\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\t// Tries to create a new file based on this archetype.\\r\\n\\t\\targs := []string{\\\"new\\\", filename, \\\"--kind\\\", archetype}\\r\\n\\t\\tif err := Run(h.Exe, args, h.Root); err != nil {\\r\\n\\t\\t\\treturn http.StatusInternalServerError, err\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\t// Writes the location of the new file to the Header.\\r\\n\\t\\tw.Header().Set(\\\"Location\\\", \\\"/files/content/\\\"+filename)\\r\\n\\t\\treturn http.StatusCreated, nil\\r\\n\\t}\\r\\n\\r\\n\\t// If we are trying to regenerate the website.\\r\\n\\tif r.Header.Get(\\\"Regenerate\\\") == \\\"true\\\" {\\r\\n\\t\\tif !c.User.Permissions[\\\"allowPublish\\\"] {\\r\\n\\t\\t\\treturn http.StatusForbidden, nil\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tfilename := filepath.Join(string(c.User.FileSystem), r.URL.Path)\\r\\n\\t\\tfilename = strings.TrimPrefix(filename, \\\"/\\\")\\r\\n\\r\\n\\t\\t// Before save command handler.\\r\\n\\t\\tif err := c.FM.Runner(\\\"before_publish\\\", filename); err != nil {\\r\\n\\t\\t\\treturn http.StatusInternalServerError, err\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\t// We only run undraft command if it is a file.\\r\\n\\t\\tif !strings.HasSuffix(filename, \\\"/\\\") {\\r\\n\\t\\t\\targs := []string{\\\"undraft\\\", filename}\\r\\n\\t\\t\\tif err := Run(h.Exe, args, h.Root); err != nil {\\r\\n\\t\\t\\t\\treturn http.StatusInternalServerError, err\\r\\n\\t\\t\\t}\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\t// Regenerates the file\\r\\n\\t\\th.run(false)\\r\\n\\r\\n\\t\\t// Executed the before publish command.\\r\\n\\t\\tif err := c.FM.Runner(\\\"before_publish\\\", filename); err != nil {\\r\\n\\t\\t\\treturn http.StatusInternalServerError, err\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\treturn http.StatusOK, nil\\r\\n\\t}\\r\\n\\r\\n\\tif r.Header.Get(\\\"Schedule\\\") != \\\"\\\" {\\r\\n\\t\\tif !c.User.Permissions[\\\"allowPublish\\\"] {\\r\\n\\t\\t\\treturn http.StatusForbidden, nil\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\treturn h.schedule(c, w, r)\\r\\n\\t}\\r\\n\\r\\n\\treturn http.StatusNotFound, nil\\r\\n}\\r\\n\\r\\nfunc (h hugo) AfterAPI(c *filemanager.RequestContext, w http.ResponseWriter, r *http.Request) (int, error) {\\r\\n\\treturn 0, nil\\r\\n}\\r\\n\\r\\nfunc (h hugo) JavaScript() string {\\r\\n\\treturn rice.MustFindBox(\\\"./\\\").MustString(\\\"hugo.js\\\")\\r\\n}\\r\\n\\r\\n// run runs Hugo with the define arguments.\\r\\nfunc (h hugo) run(force bool) {\\r\\n\\t// If the CleanPublic option is enabled, clean it.\\r\\n\\tif h.CleanPublic {\\r\\n\\t\\tos.RemoveAll(h.Public)\\r\\n\\t}\\r\\n\\r\\n\\t// Prevent running if watching is enabled\\r\\n\\tif b, pos := variables.StringInSlice(\\\"--watch\\\", h.Args); b && !force {\\r\\n\\t\\tif len(h.Args) > pos && h.Args[pos+1] != \\\"false\\\" {\\r\\n\\t\\t\\treturn\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tif len(h.Args) == pos+1 {\\r\\n\\t\\t\\treturn\\r\\n\\t\\t}\\r\\n\\t}\\r\\n\\r\\n\\tif err := Run(h.Exe, h.Args, h.Root); err != nil {\\r\\n\\t\\tlog.Println(err)\\r\\n\\t}\\r\\n}\\r\\n\\r\\n// schedule schedules a post to be published later.\\r\\nfunc (h hugo) schedule(c *filemanager.RequestContext, w http.ResponseWriter, r *http.Request) (int, error) {\\r\\n\\tt, err := time.Parse(\\\"2006-01-02T15:04\\\", r.Header.Get(\\\"Schedule\\\"))\\r\\n\\tpath := filepath.Join(string(c.User.FileSystem), r.URL.Path)\\r\\n\\tpath = filepath.Clean(path)\\r\\n\\r\\n\\tif err != nil {\\r\\n\\t\\treturn http.StatusInternalServerError, err\\r\\n\\t}\\r\\n\\r\\n\\tscheduler := cron.New()\\r\\n\\tscheduler.AddFunc(t.Format(\\\"05 04 15 02 01 *\\\"), func() {\\r\\n\\t\\targs := []string{\\\"undraft\\\", path}\\r\\n\\t\\tif err := Run(h.Exe, args, h.Root); err != nil {\\r\\n\\t\\t\\tlog.Printf(err.Error())\\r\\n\\t\\t\\treturn\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\th.run(false)\\r\\n\\t})\\r\\n\\r\\n\\tscheduler.Start()\\r\\n\\treturn http.StatusOK, nil\\r\\n}\\r\\n\"),\n\t}\n\tfile4 := &embedded.EmbeddedFile{\n\t\tFilename: `hugo.js`,\n\t\tFileModTime: time.Unix(1500387945, 0),\n\t\tContent: string(\"'use strict';\\r\\n\\r\\n(function () {\\r\\n if (window.plugins === undefined || window.plugins === null) {\\r\\n window.plugins = []\\r\\n }\\r\\n\\r\\n let regenerate = function (data, url) {\\r\\n url = data.api.removePrefix(url)\\r\\n\\r\\n return new Promise((resolve, reject) => {\\r\\n let request = new window.XMLHttpRequest()\\r\\n request.open('POST', `${data.store.state.baseURL}/api/hugo${url}`, true)\\r\\n request.setRequestHeader('Authorization', `Bearer ${data.store.state.jwt}`)\\r\\n request.setRequestHeader('Regenerate', 'true')\\r\\n\\r\\n request.onload = () => {\\r\\n if (request.status === 200) {\\r\\n resolve()\\r\\n } else {\\r\\n reject(request.responseText)\\r\\n }\\r\\n }\\r\\n\\r\\n request.onerror = (error) => reject(error)\\r\\n request.send()\\r\\n })\\r\\n }\\r\\n\\r\\n let newArchetype = function (data, url, type) {\\r\\n url = data.api.removePrefix(url)\\r\\n\\r\\n return new Promise((resolve, reject) => {\\r\\n let request = new window.XMLHttpRequest()\\r\\n request.open('POST', `${data.store.state.baseURL}/api/hugo${url}`, true)\\r\\n request.setRequestHeader('Authorization', `Bearer ${data.store.state.jwt}`)\\r\\n request.setRequestHeader('Archetype', encodeURIComponent(type))\\r\\n\\r\\n request.onload = () => {\\r\\n if (request.status === 200) {\\r\\n resolve(request.getResponseHeader('Location'))\\r\\n } else {\\r\\n reject(request.responseText)\\r\\n }\\r\\n }\\r\\n\\r\\n request.onerror = (error) => reject(error)\\r\\n request.send()\\r\\n })\\r\\n }\\r\\n\\r\\n let schedule = function (data, file, date) {\\r\\n file = data.api.removePrefix(file)\\r\\n\\r\\n return new Promise((resolve, reject) => {\\r\\n let request = new window.XMLHttpRequest()\\r\\n request.open('POST', `${data.store.state.baseURL}/api/hugo${file}`, true)\\r\\n request.setRequestHeader('Authorization', `Bearer ${data.store.state.jwt}`)\\r\\n request.setRequestHeader('Schedule', date)\\r\\n\\r\\n request.onload = () => {\\r\\n if (request.status === 200) {\\r\\n resolve(request.getResponseHeader('Location'))\\r\\n } else {\\r\\n reject(request.responseText)\\r\\n }\\r\\n }\\r\\n\\r\\n request.onerror = (error) => reject(error)\\r\\n request.send()\\r\\n })\\r\\n }\\r\\n\\r\\n window.plugins.push({\\r\\n name: 'hugo',\\r\\n credits: 'With a flavour of Hugo.',\\r\\n header: {\\r\\n visible: [\\r\\n {\\r\\n if: function (data, route) {\\r\\n return (data.store.state.req.kind === 'editor' &&\\r\\n !data.store.state.loading &&\\r\\n data.store.state.req.metadata !== undefined &&\\r\\n data.store.state.req.metadata !== null &&\\r\\n data.store.state.user.allowEdit &\\r\\n data.store.state.user.permissions.allowPublish)\\r\\n },\\r\\n click: function (event, data, route) {\\r\\n event.preventDefault()\\r\\n document.getElementById('save-button').click()\\r\\n // TODO: wait for save to finish?\\r\\n data.buttons.loading('publish')\\r\\n\\r\\n regenerate(data, route.path)\\r\\n .then(() => {\\r\\n data.buttons.done('publish')\\r\\n data.store.commit('showSuccess', 'Post published!')\\r\\n data.store.commit('setReload', true)\\r\\n })\\r\\n .catch((error) => {\\r\\n data.buttons.done('publish')\\r\\n data.store.commit('showError', error)\\r\\n })\\r\\n },\\r\\n id: 'publish-button',\\r\\n icon: 'send',\\r\\n name: 'Publish'\\r\\n }\\r\\n ],\\r\\n hidden: [\\r\\n {\\r\\n if: function (data, route) {\\r\\n return (data.store.state.req.kind === 'editor' &&\\r\\n !data.store.state.loading &&\\r\\n data.store.state.req.metadata !== undefined &&\\r\\n data.store.state.req.metadata !== null &&\\r\\n data.store.state.user.permissions.allowPublish)\\r\\n },\\r\\n click: function (event, data, route) {\\r\\n document.getElementById('save-button').click()\\r\\n data.store.commit('showHover', 'schedule')\\r\\n },\\r\\n id: 'schedule-button',\\r\\n icon: 'alarm',\\r\\n name: 'Schedule'\\r\\n }\\r\\n ]\\r\\n },\\r\\n sidebar: [\\r\\n {\\r\\n click: function (event, data, route) {\\r\\n data.router.push({ path: '/files/settings' })\\r\\n },\\r\\n icon: 'settings',\\r\\n name: 'Hugo Settings'\\r\\n },\\r\\n {\\r\\n click: function (event, data, route) {\\r\\n data.store.commit('showHover', 'new-archetype')\\r\\n },\\r\\n if: function (data, route) {\\r\\n return data.store.state.user.allowNew\\r\\n },\\r\\n icon: 'merge_type',\\r\\n name: 'Hugo New'\\r\\n } /* ,\\r\\n {\\r\\n click: function (event, data, route) {\\r\\n console.log('evt')\\r\\n },\\r\\n icon: 'remove_red_eye',\\r\\n name: 'Preview'\\r\\n } */\\r\\n ],\\r\\n prompts: [\\r\\n {\\r\\n name: 'new-archetype',\\r\\n title: 'New file',\\r\\n description: 'Create a new post based on an archetype. Your file will be created on content folder.',\\r\\n inputs: [\\r\\n {\\r\\n type: 'text',\\r\\n name: 'file',\\r\\n placeholder: 'File name'\\r\\n },\\r\\n {\\r\\n type: 'text',\\r\\n name: 'archetype',\\r\\n placeholder: 'Archetype'\\r\\n }\\r\\n ],\\r\\n ok: 'Create',\\r\\n submit: function (event, data, route) {\\r\\n event.preventDefault()\\r\\n\\r\\n let file = event.currentTarget.querySelector('[name=\\\"file\\\"]').value\\r\\n let type = event.currentTarget.querySelector('[name=\\\"archetype\\\"]').value\\r\\n if (type === '') type = 'default'\\r\\n\\r\\n data.store.commit('closeHovers')\\r\\n\\r\\n newArchetype(data, '/' + file, type)\\r\\n .then((url) => {\\r\\n data.router.push({ path: url })\\r\\n })\\r\\n .catch(error => {\\r\\n data.store.commit('showError', error)\\r\\n })\\r\\n }\\r\\n },\\r\\n {\\r\\n name: 'schedule',\\r\\n title: 'Schedule',\\r\\n description: 'Pick a date and time to schedule the publication of this post.',\\r\\n inputs: [\\r\\n {\\r\\n type: 'datetime-local',\\r\\n name: 'date',\\r\\n placeholder: 'Date'\\r\\n }\\r\\n ],\\r\\n ok: 'Schedule',\\r\\n submit: function (event, data, route) {\\r\\n event.preventDefault()\\r\\n data.buttons.loading('schedule')\\r\\n\\r\\n let date = event.currentTarget.querySelector('[name=\\\"date\\\"]').value\\r\\n if (date === '') {\\r\\n data.buttons.done('schedule')\\r\\n data.store.commit('showError', 'The date must not be empty.')\\r\\n return\\r\\n }\\r\\n\\r\\n schedule(data, route.path, date)\\r\\n .then(() => {\\r\\n data.buttons.done('schedule')\\r\\n data.store.commit('showSuccess', 'Post scheduled!')\\r\\n })\\r\\n .catch((error) => {\\r\\n data.buttons.done('schedule')\\r\\n data.store.commit('showError', error)\\r\\n })\\r\\n }\\r\\n }\\r\\n ]\\r\\n })\\r\\n})()\\r\\n\"),\n\t}\n\tfile5 := &embedded.EmbeddedFile{\n\t\tFilename: `rice-box.go`,\n\t\tFileModTime: time.Unix(1500387945, 0),\n\t\tContent: string(\"package hugo\\r\\n\\r\\nimport (\\r\\n\\t\\\"github.com/GeertJohan/go.rice/embedded\\\"\\r\\n\\t\\\"time\\\"\\r\\n)\\r\\n\\r\\nfunc init() {\\r\\n\\r\\n\\t// define files\\r\\n\\tfile2 := &embedded.EmbeddedFile{\\r\\n\\t\\tFilename: `README.md`,\\r\\n\\t\\tFileModTime: time.Unix(1500364498, 0),\\r\\n\\t\\tContent: string(\\\"# hugo - a caddy plugin\\\\n\\\\n[![community](https://img.shields.io/badge/community-forum-ff69b4.svg?style=flat-square)](https://caddy.community)\\\\n\\\\nhugo fills the gap between Hugo and the browser. [Hugo][6] 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.\\\\n\\\\nUsing 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. It is an implementation of [hacdias/filemanager][1] library.\\\\n\\\\n**Requirements:** you need to have the hugo executable in your PATH. You can download it from its [official page][6].\\\\n\\\\n## Get Started\\\\n\\\\nTo start using this plugin you just need to go to the [download Caddy page][3] and choose `http.hugo` in the directives section. For further information on how Caddy works refer to [its documentation][4].\\\\n\\\\nThe default credentials are `admin` for both the user and the password. It is highy recommended to change them after logging in for the first time and to use HTTPS. You can create more users and define their own permissions using the web interface.\\\\n\\\\n## Syntax\\\\n\\\\n```\\\\nhugo [directory] [admin] {\\\\n database path\\\\n}\\\\n```\\\\n\\\\n+ `directory` is the path, relative or absolute to the directory of your Hugo files. Defaults to `./`.\\\\n+ `admin` is the URL path where you will access the admin interface. Defaults to `/admin`.\\\\n+ `path` is the database path where the settings will be stored. By default, the settings will be stored on [`.caddy`][5] folder.\\\\n\\\\n## Database\\\\n\\\\nBy default the database will be stored on [`.caddy`][5] directory, in a sub-directory called `hugo`. Each file name is an hash of the combination of the host and the base URL.\\\\n\\\\nIf you don't set a database path, you will receive a warning like this:\\\\n\\\\n> [WARNING] A database is going to be created for your File Manager instace at ~/.caddy/hugo/xxx.db. It is highly recommended that you set the 'database' option to 'xxx.db'\\\\n\\\\nWhy? If you don't set a database path and you change the host or the base URL, your settings will be reseted. So it is *highly* recommended to set this option.\\\\n\\\\nWhen you set a relative path, such as `xxxxxxxxxx.db`, it will always be relative to `.caddy/hugo` directory. Although, you may also use an absolute path if you wish to store the database in other place.\\\\n\\\\n## Examples\\\\n\\\\nManage the current working directory's Hugo website at `/admin`.\\\\n\\\\n```\\\\nhugo {\\\\n database myinstance.db\\\\n}\\\\n```\\\\n\\\\nManage the Hugo website located at `/var/www/mysite` at `/admin`.\\\\n\\\\n```\\\\nhugo /var/www/mysite {\\\\n database myinstance.db\\\\n}\\\\n```\\\\n\\\\nManage the Hugo website located at `/var/www/mysite` at `/private`.\\\\n\\\\n```\\\\nhugo /var/www/mysite /private {\\\\n database myinstance.db\\\\n}\\\\n```\\\\n\\\\n## Known Issues\\\\n\\\\nIf you are having troubles **handling large files** you might need to check out the [`timeouts`][2] plugin, which can be used to change the default HTTP Timeouts.\\\\n\\\\n[1]:https://github.com/hacdias/filemanager\\\\n[2]:https://caddyserver.com/docs/timeouts\\\\n[3]:https://caddyserver.com/download\\\\n[4]:https://caddyserver.com/docs\\\\n[5]:https://caddyserver.com/docs/automatic-https#dot-caddy\\\\n[6]:http://gohugo.io\\\\n\\\"),\\r\\n\\t}\\r\\n\\tfile3 := &embedded.EmbeddedFile{\\r\\n\\t\\tFilename: `hugo.go`,\\r\\n\\t\\tFileModTime: time.Unix(1500017442, 0),\\r\\n\\t\\tContent: string(\\\"package hugo\\\\n\\\\nimport (\\\\n\\\\t\\\\\\\"log\\\\\\\"\\\\n\\\\t\\\\\\\"net/http\\\\\\\"\\\\n\\\\t\\\\\\\"os\\\\\\\"\\\\n\\\\t\\\\\\\"path/filepath\\\\\\\"\\\\n\\\\t\\\\\\\"strings\\\\\\\"\\\\n\\\\t\\\\\\\"time\\\\\\\"\\\\n\\\\n\\\\trice \\\\\\\"github.com/GeertJohan/go.rice\\\\\\\"\\\\n\\\\t\\\\\\\"github.com/hacdias/filemanager\\\\\\\"\\\\n\\\\t\\\\\\\"github.com/hacdias/filemanager/variables\\\\\\\"\\\\n\\\\t\\\\\\\"github.com/robfig/cron\\\\\\\"\\\\n)\\\\n\\\\ntype hugo struct {\\\\n\\\\t// Website root\\\\n\\\\tRoot string `description:\\\\\\\"The relative or absolute path to the place where your website is located.\\\\\\\"`\\\\n\\\\t// Public folder\\\\n\\\\tPublic string `description:\\\\\\\"The relative or absolute path to the public folder.\\\\\\\"`\\\\n\\\\t// Hugo executable path\\\\n\\\\tExe string `description:\\\\\\\"The absolute path to the Hugo executable or the command to execute.\\\\\\\"`\\\\n\\\\t// Hugo arguments\\\\n\\\\tArgs []string `description:\\\\\\\"The arguments to run when running Hugo\\\\\\\"`\\\\n\\\\t// Indicates if we should clean public before a new publish.\\\\n\\\\tCleanPublic bool `description:\\\\\\\"Indicates if the public folder should be cleaned before publishing the website.\\\\\\\"`\\\\n\\\\n\\\\t// TODO: admin interface to cgange options\\\\n}\\\\n\\\\nfunc (h hugo) BeforeAPI(c *filemanager.RequestContext, w http.ResponseWriter, r *http.Request) (int, error) {\\\\n\\\\t// If we are using the 'magic url' for the settings, we should redirect the\\\\n\\\\t// request for the acutual path.\\\\n\\\\tif r.URL.Path == \\\\\\\"/settings/\\\\\\\" || r.URL.Path == \\\\\\\"/settings\\\\\\\" {\\\\n\\\\t\\\\tvar frontmatter string\\\\n\\\\t\\\\tvar err error\\\\n\\\\n\\\\t\\\\tif _, err = os.Stat(filepath.Join(h.Root, \\\\\\\"config.yaml\\\\\\\")); err == nil {\\\\n\\\\t\\\\t\\\\tfrontmatter = \\\\\\\"yaml\\\\\\\"\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\tif _, err = os.Stat(filepath.Join(h.Root, \\\\\\\"config.json\\\\\\\")); err == nil {\\\\n\\\\t\\\\t\\\\tfrontmatter = \\\\\\\"json\\\\\\\"\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\tif _, err = os.Stat(filepath.Join(h.Root, \\\\\\\"config.toml\\\\\\\")); err == nil {\\\\n\\\\t\\\\t\\\\tfrontmatter = \\\\\\\"toml\\\\\\\"\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\tr.URL.Path = \\\\\\\"/config.\\\\\\\" + frontmatter\\\\n\\\\t\\\\treturn 0, nil\\\\n\\\\t}\\\\n\\\\n\\\\t// From here on, we only care about 'hugo' router so we can bypass\\\\n\\\\t// the others.\\\\n\\\\tif c.Router != \\\\\\\"hugo\\\\\\\" {\\\\n\\\\t\\\\treturn 0, nil\\\\n\\\\t}\\\\n\\\\n\\\\t// If we are not using HTTP Post, we shall return Method Not Allowed\\\\n\\\\t// since we are only working with this method.\\\\n\\\\tif r.Method != http.MethodPost {\\\\n\\\\t\\\\treturn http.StatusMethodNotAllowed, nil\\\\n\\\\t}\\\\n\\\\n\\\\t// If we are creating a file built from an archetype.\\\\n\\\\tif r.Header.Get(\\\\\\\"Archetype\\\\\\\") != \\\\\\\"\\\\\\\" {\\\\n\\\\t\\\\tif !c.User.AllowNew {\\\\n\\\\t\\\\t\\\\treturn http.StatusForbidden, nil\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\tfilename := filepath.Join(string(c.User.FileSystem), r.URL.Path)\\\\n\\\\t\\\\tfilename = strings.TrimPrefix(filename, \\\\\\\"/\\\\\\\")\\\\n\\\\t\\\\tarchetype := r.Header.Get(\\\\\\\"archetype\\\\\\\")\\\\n\\\\n\\\\t\\\\text := filepath.Ext(filename)\\\\n\\\\n\\\\t\\\\t// If the request isn't for a markdown file, we can't\\\\n\\\\t\\\\t// handle it.\\\\n\\\\t\\\\tif ext != \\\\\\\".markdown\\\\\\\" && ext != \\\\\\\".md\\\\\\\" {\\\\n\\\\t\\\\t\\\\treturn http.StatusBadRequest, errUnsupportedFileType\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\t// Tries to create a new file based on this archetype.\\\\n\\\\t\\\\targs := []string{\\\\\\\"new\\\\\\\", filename, \\\\\\\"--kind\\\\\\\", archetype}\\\\n\\\\t\\\\tif err := Run(h.Exe, args, h.Root); err != nil {\\\\n\\\\t\\\\t\\\\treturn http.StatusInternalServerError, err\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\t// Writes the location of the new file to the Header.\\\\n\\\\t\\\\tw.Header().Set(\\\\\\\"Location\\\\\\\", \\\\\\\"/files/content/\\\\\\\"+filename)\\\\n\\\\t\\\\treturn http.StatusCreated, nil\\\\n\\\\t}\\\\n\\\\n\\\\t// If we are trying to regenerate the website.\\\\n\\\\tif r.Header.Get(\\\\\\\"Regenerate\\\\\\\") == \\\\\\\"true\\\\\\\" {\\\\n\\\\t\\\\tif !c.User.Permissions[\\\\\\\"allowPublish\\\\\\\"] {\\\\n\\\\t\\\\t\\\\treturn http.StatusForbidden, nil\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\tfilename := filepath.Join(string(c.User.FileSystem), r.URL.Path)\\\\n\\\\t\\\\tfilename = strings.TrimPrefix(filename, \\\\\\\"/\\\\\\\")\\\\n\\\\n\\\\t\\\\t// Before save command handler.\\\\n\\\\t\\\\tif err := c.FM.Runner(\\\\\\\"before_publish\\\\\\\", filename); err != nil {\\\\n\\\\t\\\\t\\\\treturn http.StatusInternalServerError, err\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\t// We only run undraft command if it is a file.\\\\n\\\\t\\\\tif !strings.HasSuffix(filename, \\\\\\\"/\\\\\\\") {\\\\n\\\\t\\\\t\\\\targs := []string{\\\\\\\"undraft\\\\\\\", filename}\\\\n\\\\t\\\\t\\\\tif err := Run(h.Exe, args, h.Root); err != nil {\\\\n\\\\t\\\\t\\\\t\\\\treturn http.StatusInternalServerError, err\\\\n\\\\t\\\\t\\\\t}\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\t// Regenerates the file\\\\n\\\\t\\\\th.run(false)\\\\n\\\\n\\\\t\\\\t// Executed the before publish command.\\\\n\\\\t\\\\tif err := c.FM.Runner(\\\\\\\"before_publish\\\\\\\", filename); err != nil {\\\\n\\\\t\\\\t\\\\treturn http.StatusInternalServerError, err\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\treturn http.StatusOK, nil\\\\n\\\\t}\\\\n\\\\n\\\\tif r.Header.Get(\\\\\\\"Schedule\\\\\\\") != \\\\\\\"\\\\\\\" {\\\\n\\\\t\\\\tif !c.User.Permissions[\\\\\\\"allowPublish\\\\\\\"] {\\\\n\\\\t\\\\t\\\\treturn http.StatusForbidden, nil\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\treturn h.schedule(c, w, r)\\\\n\\\\t}\\\\n\\\\n\\\\treturn http.StatusNotFound, nil\\\\n}\\\\n\\\\nfunc (h hugo) AfterAPI(c *filemanager.RequestContext, w http.ResponseWriter, r *http.Request) (int, error) {\\\\n\\\\treturn 0, nil\\\\n}\\\\n\\\\nfunc (h hugo) JavaScript() string {\\\\n\\\\treturn rice.MustFindBox(\\\\\\\"./\\\\\\\").MustString(\\\\\\\"hugo.js\\\\\\\")\\\\n}\\\\n\\\\n// run runs Hugo with the define arguments.\\\\nfunc (h hugo) run(force bool) {\\\\n\\\\t// If the CleanPublic option is enabled, clean it.\\\\n\\\\tif h.CleanPublic {\\\\n\\\\t\\\\tos.RemoveAll(h.Public)\\\\n\\\\t}\\\\n\\\\n\\\\t// Prevent running if watching is enabled\\\\n\\\\tif b, pos := variables.StringInSlice(\\\\\\\"--watch\\\\\\\", h.Args); b && !force {\\\\n\\\\t\\\\tif len(h.Args) > pos && h.Args[pos+1] != \\\\\\\"false\\\\\\\" {\\\\n\\\\t\\\\t\\\\treturn\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\tif len(h.Args) == pos+1 {\\\\n\\\\t\\\\t\\\\treturn\\\\n\\\\t\\\\t}\\\\n\\\\t}\\\\n\\\\n\\\\tif err := Run(h.Exe, h.Args, h.Root); err != nil {\\\\n\\\\t\\\\tlog.Println(err)\\\\n\\\\t}\\\\n}\\\\n\\\\n// schedule schedules a post to be published later.\\\\nfunc (h hugo) schedule(c *filemanager.RequestContext, w http.ResponseWriter, r *http.Request) (int, error) {\\\\n\\\\tt, err := time.Parse(\\\\\\\"2006-01-02T15:04\\\\\\\", r.Header.Get(\\\\\\\"Schedule\\\\\\\"))\\\\n\\\\tpath := filepath.Join(string(c.User.FileSystem), r.URL.Path)\\\\n\\\\tpath = filepath.Clean(path)\\\\n\\\\n\\\\tif err != nil {\\\\n\\\\t\\\\treturn http.StatusInternalServerError, err\\\\n\\\\t}\\\\n\\\\n\\\\tscheduler := cron.New()\\\\n\\\\tscheduler.AddFunc(t.Format(\\\\\\\"05 04 15 02 01 *\\\\\\\"), func() {\\\\n\\\\t\\\\targs := []string{\\\\\\\"undraft\\\\\\\", path}\\\\n\\\\t\\\\tif err := Run(h.Exe, args, h.Root); err != nil {\\\\n\\\\t\\\\t\\\\tlog.Printf(err.Error())\\\\n\\\\t\\\\t\\\\treturn\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\th.run(false)\\\\n\\\\t})\\\\n\\\\n\\\\tscheduler.Start()\\\\n\\\\treturn http.StatusOK, nil\\\\n}\\\\n\\\"),\\r\\n\\t}\\r\\n\\tfile4 := &embedded.EmbeddedFile{\\r\\n\\t\\tFilename: `hugo.js`,\\r\\n\\t\\tFileModTime: time.Unix(1500385310, 0),\\r\\n\\t\\tContent: string(\\\"'use strict';\\\\n\\\\n(function () {\\\\n if (window.plugins === undefined || window.plugins === null) {\\\\n window.plugins = []\\\\n }\\\\n\\\\n let regenerate = function (data, url) {\\\\n url = data.api.removePrefix(url)\\\\n\\\\n return new Promise((resolve, reject) => {\\\\n let request = new window.XMLHttpRequest()\\\\n request.open('POST', `${data.store.state.baseURL}/api/hugo${url}`, true)\\\\n request.setRequestHeader('Authorization', `Bearer ${data.store.state.jwt}`)\\\\n request.setRequestHeader('Regenerate', 'true')\\\\n\\\\n request.onload = () => {\\\\n if (request.status === 200) {\\\\n resolve()\\\\n } else {\\\\n reject(request.responseText)\\\\n }\\\\n }\\\\n\\\\n request.onerror = (error) => reject(error)\\\\n request.send()\\\\n })\\\\n }\\\\n\\\\n let newArchetype = function (data, url, type) {\\\\n url = data.api.removePrefix(url)\\\\n\\\\n return new Promise((resolve, reject) => {\\\\n let request = new window.XMLHttpRequest()\\\\n request.open('POST', `${data.store.state.baseURL}/api/hugo${url}`, true)\\\\n request.setRequestHeader('Authorization', `Bearer ${data.store.state.jwt}`)\\\\n request.setRequestHeader('Archetype', encodeURIComponent(type))\\\\n\\\\n request.onload = () => {\\\\n if (request.status === 200) {\\\\n resolve(request.getResponseHeader('Location'))\\\\n } else {\\\\n reject(request.responseText)\\\\n }\\\\n }\\\\n\\\\n request.onerror = (error) => reject(error)\\\\n request.send()\\\\n })\\\\n }\\\\n\\\\n let schedule = function (data, file, date) {\\\\n file = data.api.removePrefix(file)\\\\n\\\\n return new Promise((resolve, reject) => {\\\\n let request = new window.XMLHttpRequest()\\\\n request.open('POST', `${data.store.state.baseURL}/api/hugo${file}`, true)\\\\n request.setRequestHeader('Authorization', `Bearer ${data.store.state.jwt}`)\\\\n request.setRequestHeader('Schedule', date)\\\\n\\\\n request.onload = () => {\\\\n if (request.status === 200) {\\\\n resolve(request.getResponseHeader('Location'))\\\\n } else {\\\\n reject(request.responseText)\\\\n }\\\\n }\\\\n\\\\n request.onerror = (error) => reject(error)\\\\n request.send()\\\\n })\\\\n }\\\\n\\\\n window.plugins.push({\\\\n name: 'hugo',\\\\n credits: 'With a flavour of Hugo.',\\\\n header: {\\\\n visible: [\\\\n {\\\\n if: function (data, route) {\\\\n return (data.store.state.req.kind === 'editor' &&\\\\n !data.store.state.loading &&\\\\n data.store.state.req.metadata !== undefined &&\\\\n data.store.state.req.metadata !== null &&\\\\n data.store.state.user.allowEdit &\\\\n data.store.state.user.permissions.allowPublish)\\\\n },\\\\n click: function (event, data, route) {\\\\n event.preventDefault()\\\\n document.getElementById('save-button').click()\\\\n // TODO: wait for save to finish?\\\\n data.buttons.loading('publish')\\\\n\\\\n regenerate(data, route.path)\\\\n .then(() => {\\\\n data.buttons.done('publish')\\\\n data.store.commit('showSuccess', 'Post published!')\\\\n data.store.commit('setReload', true)\\\\n })\\\\n .catch((error) => {\\\\n data.buttons.done('publish')\\\\n data.store.commit('showError', error)\\\\n })\\\\n },\\\\n id: 'publish-button',\\\\n icon: 'send',\\\\n name: 'Publish'\\\\n }\\\\n ],\\\\n hidden: [\\\\n {\\\\n if: function (data, route) {\\\\n return (data.store.state.req.kind === 'editor' &&\\\\n !data.store.state.loading &&\\\\n data.store.state.req.metadata !== undefined &&\\\\n data.store.state.req.metadata !== null &&\\\\n data.store.state.user.permissions.allowPublish)\\\\n },\\\\n click: function (event, data, route) {\\\\n document.getElementById('save-button').click()\\\\n data.store.commit('showHover', 'schedule')\\\\n },\\\\n id: 'schedule-button',\\\\n icon: 'alarm',\\\\n name: 'Schedule'\\\\n }\\\\n ]\\\\n },\\\\n sidebar: [\\\\n {\\\\n click: function (event, data, route) {\\\\n data.router.push({ path: '/files/settings' })\\\\n },\\\\n icon: 'settings',\\\\n name: 'Hugo Settings'\\\\n },\\\\n {\\\\n click: function (event, data, route) {\\\\n data.store.commit('showHover', 'new-archetype')\\\\n },\\\\n if: function (data, route) {\\\\n return data.store.state.user.allowNew\\\\n },\\\\n icon: 'merge_type',\\\\n name: 'Hugo New'\\\\n } /* ,\\\\n {\\\\n click: function (event, data, route) {\\\\n console.log('evt')\\\\n },\\\\n icon: 'remove_red_eye',\\\\n name: 'Preview'\\\\n } */\\\\n ],\\\\n prompts: [\\\\n {\\\\n name: 'new-archetype',\\\\n title: 'New file',\\\\n description: 'Create a new post based on an archetype. Your file will be created on content folder.',\\\\n inputs: [\\\\n {\\\\n type: 'text',\\\\n name: 'file',\\\\n placeholder: 'File name'\\\\n },\\\\n {\\\\n type: 'text',\\\\n name: 'archetype',\\\\n placeholder: 'Archetype'\\\\n }\\\\n ],\\\\n ok: 'Create',\\\\n submit: function (event, data, route) {\\\\n event.preventDefault()\\\\n\\\\n let file = event.currentTarget.querySelector('[name=\\\\\\\"file\\\\\\\"]').value\\\\n let type = event.currentTarget.querySelector('[name=\\\\\\\"archetype\\\\\\\"]').value\\\\n if (type === '') type = 'default'\\\\n\\\\n data.store.commit('closeHovers')\\\\n\\\\n newArchetype(data, '/' + file, type)\\\\n .then((url) => {\\\\n data.router.push({ path: url })\\\\n })\\\\n .catch(error => {\\\\n data.store.commit('showError', error)\\\\n })\\\\n }\\\\n },\\\\n {\\\\n name: 'schedule',\\\\n title: 'Schedule',\\\\n description: 'Pick a date and time to schedule the publication of this post.',\\\\n inputs: [\\\\n {\\\\n type: 'datetime-local',\\\\n name: 'date',\\\\n placeholder: 'Date'\\\\n }\\\\n ],\\\\n ok: 'Schedule',\\\\n submit: function (event, data, route) {\\\\n event.preventDefault()\\\\n data.buttons.loading('schedule')\\\\n\\\\n let date = event.currentTarget.querySelector('[name=\\\\\\\"date\\\\\\\"]').value\\\\n if (date === '') {\\\\n data.buttons.done('schedule')\\\\n data.store.commit('showError', 'The date must not be empty.')\\\\n return\\\\n }\\\\n\\\\n schedule(data, route.path, date)\\\\n .then(() => {\\\\n data.buttons.done('schedule')\\\\n data.store.commit('showSuccess', 'Post scheduled!')\\\\n })\\\\n .catch((error) => {\\\\n data.buttons.done('schedule')\\\\n data.store.commit('showError', error)\\\\n })\\\\n }\\\\n }\\\\n ]\\\\n })\\\\n})()\\\\n\\\"),\\r\\n\\t}\\r\\n\\tfile5 := &embedded.EmbeddedFile{\\r\\n\\t\\tFilename: `setup.go`,\\r\\n\\t\\tFileModTime: time.Unix(1500361773, 0),\\r\\n\\t\\tContent: string(\\\"package hugo\\\\n\\\\nimport (\\\\n\\\\t\\\\\\\"crypto/md5\\\\\\\"\\\\n\\\\t\\\\\\\"encoding/hex\\\\\\\"\\\\n\\\\t\\\\\\\"errors\\\\\\\"\\\\n\\\\t\\\\\\\"fmt\\\\\\\"\\\\n\\\\t\\\\\\\"net/http\\\\\\\"\\\\n\\\\t\\\\\\\"os\\\\\\\"\\\\n\\\\t\\\\\\\"os/exec\\\\\\\"\\\\n\\\\t\\\\\\\"path/filepath\\\\\\\"\\\\n\\\\t\\\\\\\"strings\\\\\\\"\\\\n\\\\n\\\\t\\\\\\\"github.com/hacdias/filemanager\\\\\\\"\\\\n\\\\t\\\\\\\"github.com/mholt/caddy\\\\\\\"\\\\n\\\\t\\\\\\\"github.com/mholt/caddy/caddyhttp/httpserver\\\\\\\"\\\\n\\\\t\\\\\\\"golang.org/x/net/webdav\\\\\\\"\\\\n)\\\\n\\\\nvar (\\\\n\\\\terrHugoNotFound = errors.New(\\\\\\\"It seems that tou don't have 'hugo' on your PATH\\\\\\\")\\\\n\\\\terrUnsupportedFileType = errors.New(\\\\\\\"The type of the provided file isn't supported for this action\\\\\\\")\\\\n)\\\\n\\\\n// setup configures a new FileManager middleware instance.\\\\nfunc setup(c *caddy.Controller) error {\\\\n\\\\tconfigs, err := parse(c)\\\\n\\\\tif err != nil {\\\\n\\\\t\\\\treturn err\\\\n\\\\t}\\\\n\\\\n\\\\thttpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {\\\\n\\\\t\\\\treturn plugin{Configs: configs, Next: next}\\\\n\\\\t})\\\\n\\\\n\\\\treturn nil\\\\n}\\\\n\\\\nfunc parse(c *caddy.Controller) ([]*filemanager.FileManager, error) {\\\\n\\\\tvar (\\\\n\\\\t\\\\tconfigs []*filemanager.FileManager\\\\n\\\\t)\\\\n\\\\n\\\\tfor c.Next() {\\\\n\\\\t\\\\t// hugo [directory] [admin] {\\\\n\\\\t\\\\t// \\\\t\\\\tdatabase path\\\\n\\\\t\\\\t// }\\\\n\\\\t\\\\tdirectory := \\\\\\\".\\\\\\\"\\\\n\\\\t\\\\tadmin := \\\\\\\"/admin\\\\\\\"\\\\n\\\\t\\\\tdatabase := \\\\\\\"\\\\\\\"\\\\n\\\\n\\\\t\\\\t// Get the baseURL and baseScope\\\\n\\\\t\\\\targs := c.RemainingArgs()\\\\n\\\\n\\\\t\\\\tif len(args) == 1 {\\\\n\\\\t\\\\t\\\\tdirectory = args[0]\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\tif len(args) > 1 {\\\\n\\\\t\\\\t\\\\tadmin = args[1]\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\tfor c.NextBlock() {\\\\n\\\\t\\\\t\\\\tswitch c.Val() {\\\\n\\\\t\\\\t\\\\tcase \\\\\\\"database\\\\\\\":\\\\n\\\\t\\\\t\\\\t\\\\tif !c.NextArg() {\\\\n\\\\t\\\\t\\\\t\\\\t\\\\treturn nil, c.ArgErr()\\\\n\\\\t\\\\t\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\t\\\\t\\\\tdatabase = c.Val()\\\\n\\\\t\\\\t\\\\t}\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\tcaddyConf := httpserver.GetConfig(c)\\\\n\\\\n\\\\t\\\\tpath := filepath.Join(caddy.AssetsPath(), \\\\\\\"hugo\\\\\\\")\\\\n\\\\t\\\\terr := os.MkdirAll(path, 0700)\\\\n\\\\t\\\\tif err != nil {\\\\n\\\\t\\\\t\\\\treturn nil, err\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\t// if there is a database path and it is not absolute,\\\\n\\\\t\\\\t// it will be relative to \\\\\\\".caddy\\\\\\\" folder.\\\\n\\\\t\\\\tif !filepath.IsAbs(database) && database != \\\\\\\"\\\\\\\" {\\\\n\\\\t\\\\t\\\\tdatabase = filepath.Join(path, database)\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\t// If there is no database path on the settings,\\\\n\\\\t\\\\t// store one in .caddy/hugo/{name}.db.\\\\n\\\\t\\\\tif database == \\\\\\\"\\\\\\\" {\\\\n\\\\t\\\\t\\\\t// The name of the database is the hashed value of a string composed\\\\n\\\\t\\\\t\\\\t// by the host, address path and the baseurl of this File Manager\\\\n\\\\t\\\\t\\\\t// instance.\\\\n\\\\t\\\\t\\\\thasher := md5.New()\\\\n\\\\t\\\\t\\\\thasher.Write([]byte(caddyConf.Addr.Host + caddyConf.Addr.Path + admin))\\\\n\\\\t\\\\t\\\\tsha := hex.EncodeToString(hasher.Sum(nil))\\\\n\\\\t\\\\t\\\\tdatabase = filepath.Join(path, sha+\\\\\\\".db\\\\\\\")\\\\n\\\\n\\\\t\\\\t\\\\tfmt.Println(\\\\\\\"[WARNING] A database is going to be created for your Hugo instace at \\\\\\\" + database +\\\\n\\\\t\\\\t\\\\t\\\\t\\\\\\\". It is highly recommended that you set the 'database' option to '\\\\\\\" + sha + \\\\\\\".db'\\\\\\\\n\\\\\\\")\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\tm, err := filemanager.New(database, filemanager.User{\\\\n\\\\t\\\\t\\\\tUsername: \\\\\\\"admin\\\\\\\",\\\\n\\\\t\\\\t\\\\tPassword: \\\\\\\"admin\\\\\\\",\\\\n\\\\t\\\\t\\\\tAllowCommands: true,\\\\n\\\\t\\\\t\\\\tAllowEdit: true,\\\\n\\\\t\\\\t\\\\tAllowNew: true,\\\\n\\\\t\\\\t\\\\tPermissions: map[string]bool{},\\\\n\\\\t\\\\t\\\\tCommands: []string{\\\\\\\"git\\\\\\\", \\\\\\\"svn\\\\\\\", \\\\\\\"hg\\\\\\\"},\\\\n\\\\t\\\\t\\\\tRules: []*filemanager.Rule{{\\\\n\\\\t\\\\t\\\\t\\\\tRegex: true,\\\\n\\\\t\\\\t\\\\t\\\\tAllow: false,\\\\n\\\\t\\\\t\\\\t\\\\tRegexp: &filemanager.Regexp{Raw: \\\\\\\"\\\\\\\\\\\\\\\\/\\\\\\\\\\\\\\\\..+\\\\\\\"},\\\\n\\\\t\\\\t\\\\t}},\\\\n\\\\t\\\\t\\\\tCSS: \\\\\\\"\\\\\\\",\\\\n\\\\t\\\\t\\\\tFileSystem: webdav.Dir(directory),\\\\n\\\\t\\\\t})\\\\n\\\\n\\\\t\\\\tif err != nil {\\\\n\\\\t\\\\t\\\\treturn nil, err\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\t// Initialize the default settings for Hugo.\\\\n\\\\t\\\\thugo := &hugo{\\\\n\\\\t\\\\t\\\\tRoot: directory,\\\\n\\\\t\\\\t\\\\tPublic: filepath.Join(directory, \\\\\\\"public\\\\\\\"),\\\\n\\\\t\\\\t\\\\tArgs: []string{},\\\\n\\\\t\\\\t\\\\tCleanPublic: true,\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\t// Try to find the Hugo executable path.\\\\n\\\\t\\\\tif hugo.Exe, err = exec.LookPath(\\\\\\\"hugo\\\\\\\"); err != nil {\\\\n\\\\t\\\\t\\\\treturn nil, errHugoNotFound\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\terr = m.RegisterPlugin(\\\\\\\"hugo\\\\\\\", hugo)\\\\n\\\\t\\\\tif err != nil {\\\\n\\\\t\\\\t\\\\treturn nil, err\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\terr = m.RegisterEventType(\\\\\\\"before_publish\\\\\\\")\\\\n\\\\t\\\\tif err != nil {\\\\n\\\\t\\\\t\\\\treturn nil, err\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\terr = m.RegisterEventType(\\\\\\\"after_publish\\\\\\\")\\\\n\\\\t\\\\tif err != nil {\\\\n\\\\t\\\\t\\\\treturn nil, err\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\terr = m.RegisterPermission(\\\\\\\"allowPublish\\\\\\\", true)\\\\n\\\\t\\\\tif err != nil {\\\\n\\\\t\\\\t\\\\treturn nil, err\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\tm.SetBaseURL(admin)\\\\n\\\\t\\\\tm.SetPrefixURL(strings.TrimSuffix(caddyConf.Addr.Path, \\\\\\\"/\\\\\\\"))\\\\n\\\\t\\\\tconfigs = append(configs, m)\\\\n\\\\t}\\\\n\\\\n\\\\treturn configs, nil\\\\n}\\\\n\\\\n// ServeHTTP determines if the request is for this plugin, and if all prerequisites are met.\\\\nfunc (p plugin) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {\\\\n\\\\tfor i := range p.Configs {\\\\n\\\\t\\\\t// Checks if this Path should be handled by File Manager.\\\\n\\\\t\\\\tif !httpserver.Path(r.URL.Path).Matches(p.Configs[i].BaseURL) {\\\\n\\\\t\\\\t\\\\tcontinue\\\\n\\\\t\\\\t}\\\\n\\\\n\\\\t\\\\treturn p.Configs[i].ServeHTTP(w, r)\\\\n\\\\t}\\\\n\\\\n\\\\treturn p.Next.ServeHTTP(w, r)\\\\n}\\\\n\\\\nfunc init() {\\\\n\\\\tcaddy.RegisterPlugin(\\\\\\\"hugo\\\\\\\", caddy.Plugin{\\\\n\\\\t\\\\tServerType: \\\\\\\"http\\\\\\\",\\\\n\\\\t\\\\tAction: setup,\\\\n\\\\t})\\\\n}\\\\n\\\\ntype plugin struct {\\\\n\\\\tNext httpserver.Handler\\\\n\\\\tConfigs []*filemanager.FileManager\\\\n}\\\\n\\\"),\\r\\n\\t}\\r\\n\\tfile6 := &embedded.EmbeddedFile{\\r\\n\\t\\tFilename: `utils.go`,\\r\\n\\t\\tFileModTime: time.Unix(1499867704, 0),\\r\\n\\t\\tContent: string(\\\"package hugo\\\\n\\\\nimport (\\\\n\\\\t\\\\\\\"errors\\\\\\\"\\\\n\\\\t\\\\\\\"os/exec\\\\\\\"\\\\n)\\\\n\\\\n// Run executes an external command\\\\nfunc Run(command string, args []string, path string) error {\\\\n\\\\tcmd := exec.Command(command, args...)\\\\n\\\\tcmd.Dir = path\\\\n\\\\tout, err := cmd.CombinedOutput()\\\\n\\\\n\\\\tif err != nil {\\\\n\\\\t\\\\treturn errors.New(string(out))\\\\n\\\\t}\\\\n\\\\n\\\\treturn nil\\\\n}\\\\n\\\"),\\r\\n\\t}\\r\\n\\r\\n\\t// define dirs\\r\\n\\tdir1 := &embedded.EmbeddedDir{\\r\\n\\t\\tFilename: ``,\\r\\n\\t\\tDirModTime: time.Unix(1499788789, 0),\\r\\n\\t\\tChildFiles: []*embedded.EmbeddedFile{\\r\\n\\t\\t\\tfile2, // README.md\\r\\n\\t\\t\\tfile3, // hugo.go\\r\\n\\t\\t\\tfile4, // hugo.js\\r\\n\\t\\t\\tfile5, // setup.go\\r\\n\\t\\t\\tfile6, // utils.go\\r\\n\\r\\n\\t\\t},\\r\\n\\t}\\r\\n\\r\\n\\t// link ChildDirs\\r\\n\\tdir1.ChildDirs = []*embedded.EmbeddedDir{}\\r\\n\\r\\n\\t// register embeddedBox\\r\\n\\tembedded.RegisterEmbeddedBox(`./`, &embedded.EmbeddedBox{\\r\\n\\t\\tName: `./`,\\r\\n\\t\\tTime: time.Unix(1499788789, 0),\\r\\n\\t\\tDirs: map[string]*embedded.EmbeddedDir{\\r\\n\\t\\t\\t\\\"\\\": dir1,\\r\\n\\t\\t},\\r\\n\\t\\tFiles: map[string]*embedded.EmbeddedFile{\\r\\n\\t\\t\\t\\\"README.md\\\": file2,\\r\\n\\t\\t\\t\\\"hugo.go\\\": file3,\\r\\n\\t\\t\\t\\\"hugo.js\\\": file4,\\r\\n\\t\\t\\t\\\"setup.go\\\": file5,\\r\\n\\t\\t\\t\\\"utils.go\\\": file6,\\r\\n\\t\\t},\\r\\n\\t})\\r\\n}\\r\\n\"),\n\t}\n\tfile6 := &embedded.EmbeddedFile{\n\t\tFilename: `setup.go`,\n\t\tFileModTime: time.Unix(1500387945, 0),\n\t\tContent: string(\"package hugo\\r\\n\\r\\nimport (\\r\\n\\t\\\"crypto/md5\\\"\\r\\n\\t\\\"encoding/hex\\\"\\r\\n\\t\\\"errors\\\"\\r\\n\\t\\\"fmt\\\"\\r\\n\\t\\\"net/http\\\"\\r\\n\\t\\\"os\\\"\\r\\n\\t\\\"os/exec\\\"\\r\\n\\t\\\"path/filepath\\\"\\r\\n\\t\\\"strings\\\"\\r\\n\\r\\n\\t\\\"github.com/hacdias/filemanager\\\"\\r\\n\\t\\\"github.com/mholt/caddy\\\"\\r\\n\\t\\\"github.com/mholt/caddy/caddyhttp/httpserver\\\"\\r\\n\\t\\\"golang.org/x/net/webdav\\\"\\r\\n)\\r\\n\\r\\nvar (\\r\\n\\terrHugoNotFound = errors.New(\\\"It seems that tou don't have 'hugo' on your PATH\\\")\\r\\n\\terrUnsupportedFileType = errors.New(\\\"The type of the provided file isn't supported for this action\\\")\\r\\n)\\r\\n\\r\\n// setup configures a new FileManager middleware instance.\\r\\nfunc setup(c *caddy.Controller) error {\\r\\n\\tconfigs, err := parse(c)\\r\\n\\tif err != nil {\\r\\n\\t\\treturn err\\r\\n\\t}\\r\\n\\r\\n\\thttpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {\\r\\n\\t\\treturn plugin{Configs: configs, Next: next}\\r\\n\\t})\\r\\n\\r\\n\\treturn nil\\r\\n}\\r\\n\\r\\nfunc parse(c *caddy.Controller) ([]*filemanager.FileManager, error) {\\r\\n\\tvar (\\r\\n\\t\\tconfigs []*filemanager.FileManager\\r\\n\\t)\\r\\n\\r\\n\\tfor c.Next() {\\r\\n\\t\\t// hugo [directory] [admin] {\\r\\n\\t\\t// \\t\\tdatabase path\\r\\n\\t\\t// }\\r\\n\\t\\tdirectory := \\\".\\\"\\r\\n\\t\\tadmin := \\\"/admin\\\"\\r\\n\\t\\tdatabase := \\\"\\\"\\r\\n\\r\\n\\t\\t// Get the baseURL and baseScope\\r\\n\\t\\targs := c.RemainingArgs()\\r\\n\\r\\n\\t\\tif len(args) == 1 {\\r\\n\\t\\t\\tdirectory = args[0]\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tif len(args) > 1 {\\r\\n\\t\\t\\tadmin = args[1]\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tfor c.NextBlock() {\\r\\n\\t\\t\\tswitch c.Val() {\\r\\n\\t\\t\\tcase \\\"database\\\":\\r\\n\\t\\t\\t\\tif !c.NextArg() {\\r\\n\\t\\t\\t\\t\\treturn nil, c.ArgErr()\\r\\n\\t\\t\\t\\t}\\r\\n\\r\\n\\t\\t\\t\\tdatabase = c.Val()\\r\\n\\t\\t\\t}\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tcaddyConf := httpserver.GetConfig(c)\\r\\n\\r\\n\\t\\tpath := filepath.Join(caddy.AssetsPath(), \\\"hugo\\\")\\r\\n\\t\\terr := os.MkdirAll(path, 0700)\\r\\n\\t\\tif err != nil {\\r\\n\\t\\t\\treturn nil, err\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\t// if there is a database path and it is not absolute,\\r\\n\\t\\t// it will be relative to \\\".caddy\\\" folder.\\r\\n\\t\\tif !filepath.IsAbs(database) && database != \\\"\\\" {\\r\\n\\t\\t\\tdatabase = filepath.Join(path, database)\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\t// If there is no database path on the settings,\\r\\n\\t\\t// store one in .caddy/hugo/{name}.db.\\r\\n\\t\\tif database == \\\"\\\" {\\r\\n\\t\\t\\t// The name of the database is the hashed value of a string composed\\r\\n\\t\\t\\t// by the host, address path and the baseurl of this File Manager\\r\\n\\t\\t\\t// instance.\\r\\n\\t\\t\\thasher := md5.New()\\r\\n\\t\\t\\thasher.Write([]byte(caddyConf.Addr.Host + caddyConf.Addr.Path + admin))\\r\\n\\t\\t\\tsha := hex.EncodeToString(hasher.Sum(nil))\\r\\n\\t\\t\\tdatabase = filepath.Join(path, sha+\\\".db\\\")\\r\\n\\r\\n\\t\\t\\tfmt.Println(\\\"[WARNING] A database is going to be created for your Hugo instace at \\\" + database +\\r\\n\\t\\t\\t\\t\\\". It is highly recommended that you set the 'database' option to '\\\" + sha + \\\".db'\\\\n\\\")\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tm, err := filemanager.New(database, filemanager.User{\\r\\n\\t\\t\\tUsername: \\\"admin\\\",\\r\\n\\t\\t\\tPassword: \\\"admin\\\",\\r\\n\\t\\t\\tAllowCommands: true,\\r\\n\\t\\t\\tAllowEdit: true,\\r\\n\\t\\t\\tAllowNew: true,\\r\\n\\t\\t\\tPermissions: map[string]bool{},\\r\\n\\t\\t\\tCommands: []string{\\\"git\\\", \\\"svn\\\", \\\"hg\\\"},\\r\\n\\t\\t\\tRules: []*filemanager.Rule{{\\r\\n\\t\\t\\t\\tRegex: true,\\r\\n\\t\\t\\t\\tAllow: false,\\r\\n\\t\\t\\t\\tRegexp: &filemanager.Regexp{Raw: \\\"\\\\\\\\/\\\\\\\\..+\\\"},\\r\\n\\t\\t\\t}},\\r\\n\\t\\t\\tCSS: \\\"\\\",\\r\\n\\t\\t\\tFileSystem: webdav.Dir(directory),\\r\\n\\t\\t})\\r\\n\\r\\n\\t\\tif err != nil {\\r\\n\\t\\t\\treturn nil, err\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\t// Initialize the default settings for Hugo.\\r\\n\\t\\thugo := &hugo{\\r\\n\\t\\t\\tRoot: directory,\\r\\n\\t\\t\\tPublic: filepath.Join(directory, \\\"public\\\"),\\r\\n\\t\\t\\tArgs: []string{},\\r\\n\\t\\t\\tCleanPublic: true,\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\t// Try to find the Hugo executable path.\\r\\n\\t\\tif hugo.Exe, err = exec.LookPath(\\\"hugo\\\"); err != nil {\\r\\n\\t\\t\\treturn nil, errHugoNotFound\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\terr = m.RegisterPlugin(\\\"hugo\\\", hugo)\\r\\n\\t\\tif err != nil {\\r\\n\\t\\t\\treturn nil, err\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\terr = m.RegisterEventType(\\\"before_publish\\\")\\r\\n\\t\\tif err != nil {\\r\\n\\t\\t\\treturn nil, err\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\terr = m.RegisterEventType(\\\"after_publish\\\")\\r\\n\\t\\tif err != nil {\\r\\n\\t\\t\\treturn nil, err\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\terr = m.RegisterPermission(\\\"allowPublish\\\", true)\\r\\n\\t\\tif err != nil {\\r\\n\\t\\t\\treturn nil, err\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tm.SetBaseURL(admin)\\r\\n\\t\\tm.SetPrefixURL(strings.TrimSuffix(caddyConf.Addr.Path, \\\"/\\\"))\\r\\n\\t\\tconfigs = append(configs, m)\\r\\n\\t}\\r\\n\\r\\n\\treturn configs, nil\\r\\n}\\r\\n\\r\\n// ServeHTTP determines if the request is for this plugin, and if all prerequisites are met.\\r\\nfunc (p plugin) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {\\r\\n\\tfor i := range p.Configs {\\r\\n\\t\\t// Checks if this Path should be handled by File Manager.\\r\\n\\t\\tif !httpserver.Path(r.URL.Path).Matches(p.Configs[i].BaseURL) {\\r\\n\\t\\t\\tcontinue\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\treturn p.Configs[i].ServeHTTP(w, r)\\r\\n\\t}\\r\\n\\r\\n\\treturn p.Next.ServeHTTP(w, r)\\r\\n}\\r\\n\\r\\nfunc init() {\\r\\n\\tcaddy.RegisterPlugin(\\\"hugo\\\", caddy.Plugin{\\r\\n\\t\\tServerType: \\\"http\\\",\\r\\n\\t\\tAction: setup,\\r\\n\\t})\\r\\n}\\r\\n\\r\\ntype plugin struct {\\r\\n\\tNext httpserver.Handler\\r\\n\\tConfigs []*filemanager.FileManager\\r\\n}\\r\\n\"),\n\t}\n\tfile7 := &embedded.EmbeddedFile{\n\t\tFilename: `utils.go`,\n\t\tFileModTime: time.Unix(1500387945, 0),\n\t\tContent: string(\"package hugo\\r\\n\\r\\nimport (\\r\\n\\t\\\"errors\\\"\\r\\n\\t\\\"os/exec\\\"\\r\\n)\\r\\n\\r\\n// Run executes an external command\\r\\nfunc Run(command string, args []string, path string) error {\\r\\n\\tcmd := exec.Command(command, args...)\\r\\n\\tcmd.Dir = path\\r\\n\\tout, err := cmd.CombinedOutput()\\r\\n\\r\\n\\tif err != nil {\\r\\n\\t\\treturn errors.New(string(out))\\r\\n\\t}\\r\\n\\r\\n\\treturn nil\\r\\n}\\r\\n\"),\n\t}\n\n\t// define dirs\n\tdir1 := &embedded.EmbeddedDir{\n\t\tFilename: ``,\n\t\tDirModTime: time.Unix(1500387945, 0),\n\t\tChildFiles: []*embedded.EmbeddedFile{\n\t\t\tfile2, // README.md\n\t\t\tfile3, // hugo.go\n\t\t\tfile4, // hugo.js\n\t\t\tfile5, // rice-box.go\n\t\t\tfile6, // setup.go\n\t\t\tfile7, // utils.go\n\n\t\t},\n\t}\n\n\t// link ChildDirs\n\tdir1.ChildDirs = []*embedded.EmbeddedDir{}\n\n\t// register embeddedBox\n\tembedded.RegisterEmbeddedBox(`./`, &embedded.EmbeddedBox{\n\t\tName: `./`,\n\t\tTime: time.Unix(1500387945, 0),\n\t\tDirs: map[string]*embedded.EmbeddedDir{\n\t\t\t\"\": dir1,\n\t\t},\n\t\tFiles: map[string]*embedded.EmbeddedFile{\n\t\t\t\"README.md\": file2,\n\t\t\t\"hugo.go\": file3,\n\t\t\t\"hugo.js\": file4,\n\t\t\t\"rice-box.go\": file5,\n\t\t\t\"setup.go\": file6,\n\t\t\t\"utils.go\": file7,\n\t\t},\n\t})\n}\n"), + FileModTime: time.Unix(1500389971, 0), + Content: string("package hugo\n\nimport (\n\t\"github.com/GeertJohan/go.rice/embedded\"\n\t\"time\"\n)\n\nfunc init() {\n\n\t// define files\n\tfile2 := &embedded.EmbeddedFile{\n\t\tFilename: `README.md`,\n\t\tFileModTime: time.Unix(1500389874, 0),\n\t\tContent: string(\"# hugo - a caddy plugin\\n\\n[![community](https://img.shields.io/badge/community-forum-ff69b4.svg?style=flat-square)](https://caddy.community)\\n\\nhugo fills the gap between Hugo and the browser. [Hugo][6] 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.\\n\\nUsing 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. It is an implementation of [hacdias/filemanager][1] library.\\n\\n**Requirements:** you need to have the hugo executable in your PATH. You can download it from its [official page][6].\\n\\n## Get Started\\n\\nTo start using this plugin you just need to go to the [download Caddy page][3] and choose `http.hugo` in the directives section. For further information on how Caddy works refer to [its documentation][4].\\n\\nThe default credentials are `admin` for both the user and the password. It is highy recommended to change them after logging in for the first time and to use HTTPS. You can create more users and define their own permissions using the web interface.\\n\\n## Syntax\\n\\n```\\nhugo [directory] [admin] {\\n database path\\n}\\n```\\n\\n+ `directory` is the path, relative or absolute to the directory of your Hugo files. Defaults to `./`.\\n+ `admin` is the URL path where you will access the admin interface. Defaults to `/admin`.\\n+ `path` is the database path where the settings will be stored. By default, the settings will be stored on [`.caddy`][5] folder.\\n\\n## Database\\n\\nBy default the database will be stored on [`.caddy`][5] directory, in a sub-directory called `hugo`. Each file name is an hash of the combination of the host and the base URL.\\n\\nIf you don't set a database path, you will receive a warning like this:\\n\\n> [WARNING] A database is going to be created for your File Manager instace at ~/.caddy/hugo/xxx.db. It is highly recommended that you set the 'database' option to 'xxx.db'\\n\\nWhy? If you don't set a database path and you change the host or the base URL, your settings will be reseted. So it is *highly* recommended to set this option.\\n\\nWhen you set a relative path, such as `xxxxxxxxxx.db`, it will always be relative to `.caddy/hugo` directory. Although, you may also use an absolute path if you wish to store the database in other place.\\n\\n## Examples\\n\\nManage the current working directory's Hugo website at `/admin` and display the ```public``` folder to the user.\\n\\n```\\nroot public\\nhugo {\\n database myinstance.db\\n}\\n```\\n\\nManage the Hugo website located at `/var/www/mysite` at `/admin` and display the ```public``` folder to the user.\\n\\n```\\nroot /var/www/mysite/public\\nhugo /var/www/mysite {\\n database myinstance.db\\n}\\n```\\n\\nManage the Hugo website located at `/var/www/mysite` at `/private` and display the ```public``` folder to the user.\\n\\n```\\nroot /var/www/mysite/public\\nhugo /var/www/mysite /private {\\n database myinstance.db\\n}\\n```\\n\\n## Known Issues\\n\\nIf you are having troubles **handling large files** you might need to check out the [`timeouts`][2] plugin, which can be used to change the default HTTP Timeouts.\\n\\n[1]:https://github.com/hacdias/filemanager\\n[2]:https://caddyserver.com/docs/timeouts\\n[3]:https://caddyserver.com/download\\n[4]:https://caddyserver.com/docs\\n[5]:https://caddyserver.com/docs/automatic-https#dot-caddy\\n[6]:http://gohugo.io\\n\"),\n\t}\n\tfile3 := &embedded.EmbeddedFile{\n\t\tFilename: `hugo.go`,\n\t\tFileModTime: time.Unix(1500387945, 0),\n\t\tContent: string(\"package hugo\\r\\n\\r\\nimport (\\r\\n\\t\\\"log\\\"\\r\\n\\t\\\"net/http\\\"\\r\\n\\t\\\"os\\\"\\r\\n\\t\\\"path/filepath\\\"\\r\\n\\t\\\"strings\\\"\\r\\n\\t\\\"time\\\"\\r\\n\\r\\n\\trice \\\"github.com/GeertJohan/go.rice\\\"\\r\\n\\t\\\"github.com/hacdias/filemanager\\\"\\r\\n\\t\\\"github.com/hacdias/filemanager/variables\\\"\\r\\n\\t\\\"github.com/robfig/cron\\\"\\r\\n)\\r\\n\\r\\ntype hugo struct {\\r\\n\\t// Website root\\r\\n\\tRoot string `description:\\\"The relative or absolute path to the place where your website is located.\\\"`\\r\\n\\t// Public folder\\r\\n\\tPublic string `description:\\\"The relative or absolute path to the public folder.\\\"`\\r\\n\\t// Hugo executable path\\r\\n\\tExe string `description:\\\"The absolute path to the Hugo executable or the command to execute.\\\"`\\r\\n\\t// Hugo arguments\\r\\n\\tArgs []string `description:\\\"The arguments to run when running Hugo\\\"`\\r\\n\\t// Indicates if we should clean public before a new publish.\\r\\n\\tCleanPublic bool `description:\\\"Indicates if the public folder should be cleaned before publishing the website.\\\"`\\r\\n\\r\\n\\t// TODO: admin interface to cgange options\\r\\n}\\r\\n\\r\\nfunc (h hugo) BeforeAPI(c *filemanager.RequestContext, w http.ResponseWriter, r *http.Request) (int, error) {\\r\\n\\t// If we are using the 'magic url' for the settings, we should redirect the\\r\\n\\t// request for the acutual path.\\r\\n\\tif r.URL.Path == \\\"/settings/\\\" || r.URL.Path == \\\"/settings\\\" {\\r\\n\\t\\tvar frontmatter string\\r\\n\\t\\tvar err error\\r\\n\\r\\n\\t\\tif _, err = os.Stat(filepath.Join(h.Root, \\\"config.yaml\\\")); err == nil {\\r\\n\\t\\t\\tfrontmatter = \\\"yaml\\\"\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tif _, err = os.Stat(filepath.Join(h.Root, \\\"config.json\\\")); err == nil {\\r\\n\\t\\t\\tfrontmatter = \\\"json\\\"\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tif _, err = os.Stat(filepath.Join(h.Root, \\\"config.toml\\\")); err == nil {\\r\\n\\t\\t\\tfrontmatter = \\\"toml\\\"\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tr.URL.Path = \\\"/config.\\\" + frontmatter\\r\\n\\t\\treturn 0, nil\\r\\n\\t}\\r\\n\\r\\n\\t// From here on, we only care about 'hugo' router so we can bypass\\r\\n\\t// the others.\\r\\n\\tif c.Router != \\\"hugo\\\" {\\r\\n\\t\\treturn 0, nil\\r\\n\\t}\\r\\n\\r\\n\\t// If we are not using HTTP Post, we shall return Method Not Allowed\\r\\n\\t// since we are only working with this method.\\r\\n\\tif r.Method != http.MethodPost {\\r\\n\\t\\treturn http.StatusMethodNotAllowed, nil\\r\\n\\t}\\r\\n\\r\\n\\t// If we are creating a file built from an archetype.\\r\\n\\tif r.Header.Get(\\\"Archetype\\\") != \\\"\\\" {\\r\\n\\t\\tif !c.User.AllowNew {\\r\\n\\t\\t\\treturn http.StatusForbidden, nil\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tfilename := filepath.Join(string(c.User.FileSystem), r.URL.Path)\\r\\n\\t\\tfilename = strings.TrimPrefix(filename, \\\"/\\\")\\r\\n\\t\\tarchetype := r.Header.Get(\\\"archetype\\\")\\r\\n\\r\\n\\t\\text := filepath.Ext(filename)\\r\\n\\r\\n\\t\\t// If the request isn't for a markdown file, we can't\\r\\n\\t\\t// handle it.\\r\\n\\t\\tif ext != \\\".markdown\\\" && ext != \\\".md\\\" {\\r\\n\\t\\t\\treturn http.StatusBadRequest, errUnsupportedFileType\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\t// Tries to create a new file based on this archetype.\\r\\n\\t\\targs := []string{\\\"new\\\", filename, \\\"--kind\\\", archetype}\\r\\n\\t\\tif err := Run(h.Exe, args, h.Root); err != nil {\\r\\n\\t\\t\\treturn http.StatusInternalServerError, err\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\t// Writes the location of the new file to the Header.\\r\\n\\t\\tw.Header().Set(\\\"Location\\\", \\\"/files/content/\\\"+filename)\\r\\n\\t\\treturn http.StatusCreated, nil\\r\\n\\t}\\r\\n\\r\\n\\t// If we are trying to regenerate the website.\\r\\n\\tif r.Header.Get(\\\"Regenerate\\\") == \\\"true\\\" {\\r\\n\\t\\tif !c.User.Permissions[\\\"allowPublish\\\"] {\\r\\n\\t\\t\\treturn http.StatusForbidden, nil\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tfilename := filepath.Join(string(c.User.FileSystem), r.URL.Path)\\r\\n\\t\\tfilename = strings.TrimPrefix(filename, \\\"/\\\")\\r\\n\\r\\n\\t\\t// Before save command handler.\\r\\n\\t\\tif err := c.FM.Runner(\\\"before_publish\\\", filename); err != nil {\\r\\n\\t\\t\\treturn http.StatusInternalServerError, err\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\t// We only run undraft command if it is a file.\\r\\n\\t\\tif !strings.HasSuffix(filename, \\\"/\\\") {\\r\\n\\t\\t\\targs := []string{\\\"undraft\\\", filename}\\r\\n\\t\\t\\tif err := Run(h.Exe, args, h.Root); err != nil {\\r\\n\\t\\t\\t\\treturn http.StatusInternalServerError, err\\r\\n\\t\\t\\t}\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\t// Regenerates the file\\r\\n\\t\\th.run(false)\\r\\n\\r\\n\\t\\t// Executed the before publish command.\\r\\n\\t\\tif err := c.FM.Runner(\\\"before_publish\\\", filename); err != nil {\\r\\n\\t\\t\\treturn http.StatusInternalServerError, err\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\treturn http.StatusOK, nil\\r\\n\\t}\\r\\n\\r\\n\\tif r.Header.Get(\\\"Schedule\\\") != \\\"\\\" {\\r\\n\\t\\tif !c.User.Permissions[\\\"allowPublish\\\"] {\\r\\n\\t\\t\\treturn http.StatusForbidden, nil\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\treturn h.schedule(c, w, r)\\r\\n\\t}\\r\\n\\r\\n\\treturn http.StatusNotFound, nil\\r\\n}\\r\\n\\r\\nfunc (h hugo) AfterAPI(c *filemanager.RequestContext, w http.ResponseWriter, r *http.Request) (int, error) {\\r\\n\\treturn 0, nil\\r\\n}\\r\\n\\r\\nfunc (h hugo) JavaScript() string {\\r\\n\\treturn rice.MustFindBox(\\\"./\\\").MustString(\\\"hugo.js\\\")\\r\\n}\\r\\n\\r\\n// run runs Hugo with the define arguments.\\r\\nfunc (h hugo) run(force bool) {\\r\\n\\t// If the CleanPublic option is enabled, clean it.\\r\\n\\tif h.CleanPublic {\\r\\n\\t\\tos.RemoveAll(h.Public)\\r\\n\\t}\\r\\n\\r\\n\\t// Prevent running if watching is enabled\\r\\n\\tif b, pos := variables.StringInSlice(\\\"--watch\\\", h.Args); b && !force {\\r\\n\\t\\tif len(h.Args) > pos && h.Args[pos+1] != \\\"false\\\" {\\r\\n\\t\\t\\treturn\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tif len(h.Args) == pos+1 {\\r\\n\\t\\t\\treturn\\r\\n\\t\\t}\\r\\n\\t}\\r\\n\\r\\n\\tif err := Run(h.Exe, h.Args, h.Root); err != nil {\\r\\n\\t\\tlog.Println(err)\\r\\n\\t}\\r\\n}\\r\\n\\r\\n// schedule schedules a post to be published later.\\r\\nfunc (h hugo) schedule(c *filemanager.RequestContext, w http.ResponseWriter, r *http.Request) (int, error) {\\r\\n\\tt, err := time.Parse(\\\"2006-01-02T15:04\\\", r.Header.Get(\\\"Schedule\\\"))\\r\\n\\tpath := filepath.Join(string(c.User.FileSystem), r.URL.Path)\\r\\n\\tpath = filepath.Clean(path)\\r\\n\\r\\n\\tif err != nil {\\r\\n\\t\\treturn http.StatusInternalServerError, err\\r\\n\\t}\\r\\n\\r\\n\\tscheduler := cron.New()\\r\\n\\tscheduler.AddFunc(t.Format(\\\"05 04 15 02 01 *\\\"), func() {\\r\\n\\t\\targs := []string{\\\"undraft\\\", path}\\r\\n\\t\\tif err := Run(h.Exe, args, h.Root); err != nil {\\r\\n\\t\\t\\tlog.Printf(err.Error())\\r\\n\\t\\t\\treturn\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\th.run(false)\\r\\n\\t})\\r\\n\\r\\n\\tscheduler.Start()\\r\\n\\treturn http.StatusOK, nil\\r\\n}\\r\\n\"),\n\t}\n\tfile4 := &embedded.EmbeddedFile{\n\t\tFilename: `hugo.js`,\n\t\tFileModTime: time.Unix(1500387945, 0),\n\t\tContent: string(\"'use strict';\\r\\n\\r\\n(function () {\\r\\n if (window.plugins === undefined || window.plugins === null) {\\r\\n window.plugins = []\\r\\n }\\r\\n\\r\\n let regenerate = function (data, url) {\\r\\n url = data.api.removePrefix(url)\\r\\n\\r\\n return new Promise((resolve, reject) => {\\r\\n let request = new window.XMLHttpRequest()\\r\\n request.open('POST', `${data.store.state.baseURL}/api/hugo${url}`, true)\\r\\n request.setRequestHeader('Authorization', `Bearer ${data.store.state.jwt}`)\\r\\n request.setRequestHeader('Regenerate', 'true')\\r\\n\\r\\n request.onload = () => {\\r\\n if (request.status === 200) {\\r\\n resolve()\\r\\n } else {\\r\\n reject(request.responseText)\\r\\n }\\r\\n }\\r\\n\\r\\n request.onerror = (error) => reject(error)\\r\\n request.send()\\r\\n })\\r\\n }\\r\\n\\r\\n let newArchetype = function (data, url, type) {\\r\\n url = data.api.removePrefix(url)\\r\\n\\r\\n return new Promise((resolve, reject) => {\\r\\n let request = new window.XMLHttpRequest()\\r\\n request.open('POST', `${data.store.state.baseURL}/api/hugo${url}`, true)\\r\\n request.setRequestHeader('Authorization', `Bearer ${data.store.state.jwt}`)\\r\\n request.setRequestHeader('Archetype', encodeURIComponent(type))\\r\\n\\r\\n request.onload = () => {\\r\\n if (request.status === 200) {\\r\\n resolve(request.getResponseHeader('Location'))\\r\\n } else {\\r\\n reject(request.responseText)\\r\\n }\\r\\n }\\r\\n\\r\\n request.onerror = (error) => reject(error)\\r\\n request.send()\\r\\n })\\r\\n }\\r\\n\\r\\n let schedule = function (data, file, date) {\\r\\n file = data.api.removePrefix(file)\\r\\n\\r\\n return new Promise((resolve, reject) => {\\r\\n let request = new window.XMLHttpRequest()\\r\\n request.open('POST', `${data.store.state.baseURL}/api/hugo${file}`, true)\\r\\n request.setRequestHeader('Authorization', `Bearer ${data.store.state.jwt}`)\\r\\n request.setRequestHeader('Schedule', date)\\r\\n\\r\\n request.onload = () => {\\r\\n if (request.status === 200) {\\r\\n resolve(request.getResponseHeader('Location'))\\r\\n } else {\\r\\n reject(request.responseText)\\r\\n }\\r\\n }\\r\\n\\r\\n request.onerror = (error) => reject(error)\\r\\n request.send()\\r\\n })\\r\\n }\\r\\n\\r\\n window.plugins.push({\\r\\n name: 'hugo',\\r\\n credits: 'With a flavour of Hugo.',\\r\\n header: {\\r\\n visible: [\\r\\n {\\r\\n if: function (data, route) {\\r\\n return (data.store.state.req.kind === 'editor' &&\\r\\n !data.store.state.loading &&\\r\\n data.store.state.req.metadata !== undefined &&\\r\\n data.store.state.req.metadata !== null &&\\r\\n data.store.state.user.allowEdit &\\r\\n data.store.state.user.permissions.allowPublish)\\r\\n },\\r\\n click: function (event, data, route) {\\r\\n event.preventDefault()\\r\\n document.getElementById('save-button').click()\\r\\n // TODO: wait for save to finish?\\r\\n data.buttons.loading('publish')\\r\\n\\r\\n regenerate(data, route.path)\\r\\n .then(() => {\\r\\n data.buttons.done('publish')\\r\\n data.store.commit('showSuccess', 'Post published!')\\r\\n data.store.commit('setReload', true)\\r\\n })\\r\\n .catch((error) => {\\r\\n data.buttons.done('publish')\\r\\n data.store.commit('showError', error)\\r\\n })\\r\\n },\\r\\n id: 'publish-button',\\r\\n icon: 'send',\\r\\n name: 'Publish'\\r\\n }\\r\\n ],\\r\\n hidden: [\\r\\n {\\r\\n if: function (data, route) {\\r\\n return (data.store.state.req.kind === 'editor' &&\\r\\n !data.store.state.loading &&\\r\\n data.store.state.req.metadata !== undefined &&\\r\\n data.store.state.req.metadata !== null &&\\r\\n data.store.state.user.permissions.allowPublish)\\r\\n },\\r\\n click: function (event, data, route) {\\r\\n document.getElementById('save-button').click()\\r\\n data.store.commit('showHover', 'schedule')\\r\\n },\\r\\n id: 'schedule-button',\\r\\n icon: 'alarm',\\r\\n name: 'Schedule'\\r\\n }\\r\\n ]\\r\\n },\\r\\n sidebar: [\\r\\n {\\r\\n click: function (event, data, route) {\\r\\n data.router.push({ path: '/files/settings' })\\r\\n },\\r\\n icon: 'settings',\\r\\n name: 'Hugo Settings'\\r\\n },\\r\\n {\\r\\n click: function (event, data, route) {\\r\\n data.store.commit('showHover', 'new-archetype')\\r\\n },\\r\\n if: function (data, route) {\\r\\n return data.store.state.user.allowNew\\r\\n },\\r\\n icon: 'merge_type',\\r\\n name: 'Hugo New'\\r\\n } /* ,\\r\\n {\\r\\n click: function (event, data, route) {\\r\\n console.log('evt')\\r\\n },\\r\\n icon: 'remove_red_eye',\\r\\n name: 'Preview'\\r\\n } */\\r\\n ],\\r\\n prompts: [\\r\\n {\\r\\n name: 'new-archetype',\\r\\n title: 'New file',\\r\\n description: 'Create a new post based on an archetype. Your file will be created on content folder.',\\r\\n inputs: [\\r\\n {\\r\\n type: 'text',\\r\\n name: 'file',\\r\\n placeholder: 'File name'\\r\\n },\\r\\n {\\r\\n type: 'text',\\r\\n name: 'archetype',\\r\\n placeholder: 'Archetype'\\r\\n }\\r\\n ],\\r\\n ok: 'Create',\\r\\n submit: function (event, data, route) {\\r\\n event.preventDefault()\\r\\n\\r\\n let file = event.currentTarget.querySelector('[name=\\\"file\\\"]').value\\r\\n let type = event.currentTarget.querySelector('[name=\\\"archetype\\\"]').value\\r\\n if (type === '') type = 'default'\\r\\n\\r\\n data.store.commit('closeHovers')\\r\\n\\r\\n newArchetype(data, '/' + file, type)\\r\\n .then((url) => {\\r\\n data.router.push({ path: url })\\r\\n })\\r\\n .catch(error => {\\r\\n data.store.commit('showError', error)\\r\\n })\\r\\n }\\r\\n },\\r\\n {\\r\\n name: 'schedule',\\r\\n title: 'Schedule',\\r\\n description: 'Pick a date and time to schedule the publication of this post.',\\r\\n inputs: [\\r\\n {\\r\\n type: 'datetime-local',\\r\\n name: 'date',\\r\\n placeholder: 'Date'\\r\\n }\\r\\n ],\\r\\n ok: 'Schedule',\\r\\n submit: function (event, data, route) {\\r\\n event.preventDefault()\\r\\n data.buttons.loading('schedule')\\r\\n\\r\\n let date = event.currentTarget.querySelector('[name=\\\"date\\\"]').value\\r\\n if (date === '') {\\r\\n data.buttons.done('schedule')\\r\\n data.store.commit('showError', 'The date must not be empty.')\\r\\n return\\r\\n }\\r\\n\\r\\n schedule(data, route.path, date)\\r\\n .then(() => {\\r\\n data.buttons.done('schedule')\\r\\n data.store.commit('showSuccess', 'Post scheduled!')\\r\\n })\\r\\n .catch((error) => {\\r\\n data.buttons.done('schedule')\\r\\n data.store.commit('showError', error)\\r\\n })\\r\\n }\\r\\n }\\r\\n ]\\r\\n })\\r\\n})()\\r\\n\"),\n\t}\n\tfile5 := &embedded.EmbeddedFile{\n\t\tFilename: `rice-box.go`,\n\t\tFileModTime: time.Unix(1500388549, 0),\n\t\tContent: string(\"package hugo\\n\\nimport (\\n\\t\\\"github.com/GeertJohan/go.rice/embedded\\\"\\n\\t\\\"time\\\"\\n)\\n\\nfunc init() {\\n\\n\\t// define files\\n\\tfile2 := &embedded.EmbeddedFile{\\n\\t\\tFilename: `README.md`,\\n\\t\\tFileModTime: time.Unix(1500388454, 0),\\n\\t\\tContent: string(\\\"# hugo - a caddy plugin\\\\n\\\\n[![community](https://img.shields.io/badge/community-forum-ff69b4.svg?style=flat-square)](https://caddy.community)\\\\n\\\\nhugo fills the gap between Hugo and the browser. [Hugo][6] 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.\\\\n\\\\nUsing 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. It is an implementation of [hacdias/filemanager][1] library.\\\\n\\\\n**Requirements:** you need to have the hugo executable in your PATH. You can download it from its [official page][6].\\\\n\\\\n## Get Started\\\\n\\\\nTo start using this plugin you just need to go to the [download Caddy page][3] and choose `http.hugo` in the directives section. For further information on how Caddy works refer to [its documentation][4].\\\\n\\\\nThe default credentials are `admin` for both the user and the password. It is highy recommended to change them after logging in for the first time and to use HTTPS. You can create more users and define their own permissions using the web interface.\\\\n\\\\n## Syntax\\\\n\\\\n```\\\\nhugo [directory] [admin] {\\\\n database path\\\\n}\\\\n```\\\\n\\\\n+ `directory` is the path, relative or absolute to the directory of your Hugo files. Defaults to `./`.\\\\n+ `admin` is the URL path where you will access the admin interface. Defaults to `/admin`.\\\\n+ `path` is the database path where the settings will be stored. By default, the settings will be stored on [`.caddy`][5] folder.\\\\n\\\\n## Database\\\\n\\\\nBy default the database will be stored on [`.caddy`][5] directory, in a sub-directory called `hugo`. Each file name is an hash of the combination of the host and the base URL.\\\\n\\\\nIf you don't set a database path, you will receive a warning like this:\\\\n\\\\n> [WARNING] A database is going to be created for your File Manager instace at ~/.caddy/hugo/xxx.db. It is highly recommended that you set the 'database' option to 'xxx.db'\\\\n\\\\nWhy? If you don't set a database path and you change the host or the base URL, your settings will be reseted. So it is *highly* recommended to set this option.\\\\n\\\\nWhen you set a relative path, such as `xxxxxxxxxx.db`, it will always be relative to `.caddy/hugo` directory. Although, you may also use an absolute path if you wish to store the database in other place.\\\\n\\\\n## Examples\\\\n\\\\nManage the current working directory's Hugo website at `/admin`.\\\\n\\\\n```\\\\nroot public\\\\nhugo {\\\\n database myinstance.db\\\\n}\\\\n```\\\\n\\\\nManage the Hugo website located at `/var/www/mysite` at `/admin`.\\\\n\\\\n```\\\\nroot /var/www/mysite/public\\\\nhugo /var/www/mysite {\\\\n database myinstance.db\\\\n}\\\\n```\\\\n\\\\nManage the Hugo website located at `/var/www/mysite` at `/private`.\\\\n\\\\n```\\\\nroot /var/www/mysite/public\\\\nhugo /var/www/mysite /private {\\\\n database myinstance.db\\\\n}\\\\n```\\\\n\\\\n## Known Issues\\\\n\\\\nIf you are having troubles **handling large files** you might need to check out the [`timeouts`][2] plugin, which can be used to change the default HTTP Timeouts.\\\\n\\\\n[1]:https://github.com/hacdias/filemanager\\\\n[2]:https://caddyserver.com/docs/timeouts\\\\n[3]:https://caddyserver.com/download\\\\n[4]:https://caddyserver.com/docs\\\\n[5]:https://caddyserver.com/docs/automatic-https#dot-caddy\\\\n[6]:http://gohugo.io\\\\n\\\"),\\n\\t}\\n\\tfile3 := &embedded.EmbeddedFile{\\n\\t\\tFilename: `hugo.go`,\\n\\t\\tFileModTime: time.Unix(1500387945, 0),\\n\\t\\tContent: string(\\\"package hugo\\\\r\\\\n\\\\r\\\\nimport (\\\\r\\\\n\\\\t\\\\\\\"log\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"net/http\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"os\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"path/filepath\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"strings\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"time\\\\\\\"\\\\r\\\\n\\\\r\\\\n\\\\trice \\\\\\\"github.com/GeertJohan/go.rice\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"github.com/hacdias/filemanager\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"github.com/hacdias/filemanager/variables\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"github.com/robfig/cron\\\\\\\"\\\\r\\\\n)\\\\r\\\\n\\\\r\\\\ntype hugo struct {\\\\r\\\\n\\\\t// Website root\\\\r\\\\n\\\\tRoot string `description:\\\\\\\"The relative or absolute path to the place where your website is located.\\\\\\\"`\\\\r\\\\n\\\\t// Public folder\\\\r\\\\n\\\\tPublic string `description:\\\\\\\"The relative or absolute path to the public folder.\\\\\\\"`\\\\r\\\\n\\\\t// Hugo executable path\\\\r\\\\n\\\\tExe string `description:\\\\\\\"The absolute path to the Hugo executable or the command to execute.\\\\\\\"`\\\\r\\\\n\\\\t// Hugo arguments\\\\r\\\\n\\\\tArgs []string `description:\\\\\\\"The arguments to run when running Hugo\\\\\\\"`\\\\r\\\\n\\\\t// Indicates if we should clean public before a new publish.\\\\r\\\\n\\\\tCleanPublic bool `description:\\\\\\\"Indicates if the public folder should be cleaned before publishing the website.\\\\\\\"`\\\\r\\\\n\\\\r\\\\n\\\\t// TODO: admin interface to cgange options\\\\r\\\\n}\\\\r\\\\n\\\\r\\\\nfunc (h hugo) BeforeAPI(c *filemanager.RequestContext, w http.ResponseWriter, r *http.Request) (int, error) {\\\\r\\\\n\\\\t// If we are using the 'magic url' for the settings, we should redirect the\\\\r\\\\n\\\\t// request for the acutual path.\\\\r\\\\n\\\\tif r.URL.Path == \\\\\\\"/settings/\\\\\\\" || r.URL.Path == \\\\\\\"/settings\\\\\\\" {\\\\r\\\\n\\\\t\\\\tvar frontmatter string\\\\r\\\\n\\\\t\\\\tvar err error\\\\r\\\\n\\\\r\\\\n\\\\t\\\\tif _, err = os.Stat(filepath.Join(h.Root, \\\\\\\"config.yaml\\\\\\\")); err == nil {\\\\r\\\\n\\\\t\\\\t\\\\tfrontmatter = \\\\\\\"yaml\\\\\\\"\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\tif _, err = os.Stat(filepath.Join(h.Root, \\\\\\\"config.json\\\\\\\")); err == nil {\\\\r\\\\n\\\\t\\\\t\\\\tfrontmatter = \\\\\\\"json\\\\\\\"\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\tif _, err = os.Stat(filepath.Join(h.Root, \\\\\\\"config.toml\\\\\\\")); err == nil {\\\\r\\\\n\\\\t\\\\t\\\\tfrontmatter = \\\\\\\"toml\\\\\\\"\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\tr.URL.Path = \\\\\\\"/config.\\\\\\\" + frontmatter\\\\r\\\\n\\\\t\\\\treturn 0, nil\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t// From here on, we only care about 'hugo' router so we can bypass\\\\r\\\\n\\\\t// the others.\\\\r\\\\n\\\\tif c.Router != \\\\\\\"hugo\\\\\\\" {\\\\r\\\\n\\\\t\\\\treturn 0, nil\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t// If we are not using HTTP Post, we shall return Method Not Allowed\\\\r\\\\n\\\\t// since we are only working with this method.\\\\r\\\\n\\\\tif r.Method != http.MethodPost {\\\\r\\\\n\\\\t\\\\treturn http.StatusMethodNotAllowed, nil\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t// If we are creating a file built from an archetype.\\\\r\\\\n\\\\tif r.Header.Get(\\\\\\\"Archetype\\\\\\\") != \\\\\\\"\\\\\\\" {\\\\r\\\\n\\\\t\\\\tif !c.User.AllowNew {\\\\r\\\\n\\\\t\\\\t\\\\treturn http.StatusForbidden, nil\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\tfilename := filepath.Join(string(c.User.FileSystem), r.URL.Path)\\\\r\\\\n\\\\t\\\\tfilename = strings.TrimPrefix(filename, \\\\\\\"/\\\\\\\")\\\\r\\\\n\\\\t\\\\tarchetype := r.Header.Get(\\\\\\\"archetype\\\\\\\")\\\\r\\\\n\\\\r\\\\n\\\\t\\\\text := filepath.Ext(filename)\\\\r\\\\n\\\\r\\\\n\\\\t\\\\t// If the request isn't for a markdown file, we can't\\\\r\\\\n\\\\t\\\\t// handle it.\\\\r\\\\n\\\\t\\\\tif ext != \\\\\\\".markdown\\\\\\\" && ext != \\\\\\\".md\\\\\\\" {\\\\r\\\\n\\\\t\\\\t\\\\treturn http.StatusBadRequest, errUnsupportedFileType\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\t// Tries to create a new file based on this archetype.\\\\r\\\\n\\\\t\\\\targs := []string{\\\\\\\"new\\\\\\\", filename, \\\\\\\"--kind\\\\\\\", archetype}\\\\r\\\\n\\\\t\\\\tif err := Run(h.Exe, args, h.Root); err != nil {\\\\r\\\\n\\\\t\\\\t\\\\treturn http.StatusInternalServerError, err\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\t// Writes the location of the new file to the Header.\\\\r\\\\n\\\\t\\\\tw.Header().Set(\\\\\\\"Location\\\\\\\", \\\\\\\"/files/content/\\\\\\\"+filename)\\\\r\\\\n\\\\t\\\\treturn http.StatusCreated, nil\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t// If we are trying to regenerate the website.\\\\r\\\\n\\\\tif r.Header.Get(\\\\\\\"Regenerate\\\\\\\") == \\\\\\\"true\\\\\\\" {\\\\r\\\\n\\\\t\\\\tif !c.User.Permissions[\\\\\\\"allowPublish\\\\\\\"] {\\\\r\\\\n\\\\t\\\\t\\\\treturn http.StatusForbidden, nil\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\tfilename := filepath.Join(string(c.User.FileSystem), r.URL.Path)\\\\r\\\\n\\\\t\\\\tfilename = strings.TrimPrefix(filename, \\\\\\\"/\\\\\\\")\\\\r\\\\n\\\\r\\\\n\\\\t\\\\t// Before save command handler.\\\\r\\\\n\\\\t\\\\tif err := c.FM.Runner(\\\\\\\"before_publish\\\\\\\", filename); err != nil {\\\\r\\\\n\\\\t\\\\t\\\\treturn http.StatusInternalServerError, err\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\t// We only run undraft command if it is a file.\\\\r\\\\n\\\\t\\\\tif !strings.HasSuffix(filename, \\\\\\\"/\\\\\\\") {\\\\r\\\\n\\\\t\\\\t\\\\targs := []string{\\\\\\\"undraft\\\\\\\", filename}\\\\r\\\\n\\\\t\\\\t\\\\tif err := Run(h.Exe, args, h.Root); err != nil {\\\\r\\\\n\\\\t\\\\t\\\\t\\\\treturn http.StatusInternalServerError, err\\\\r\\\\n\\\\t\\\\t\\\\t}\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\t// Regenerates the file\\\\r\\\\n\\\\t\\\\th.run(false)\\\\r\\\\n\\\\r\\\\n\\\\t\\\\t// Executed the before publish command.\\\\r\\\\n\\\\t\\\\tif err := c.FM.Runner(\\\\\\\"before_publish\\\\\\\", filename); err != nil {\\\\r\\\\n\\\\t\\\\t\\\\treturn http.StatusInternalServerError, err\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\treturn http.StatusOK, nil\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\tif r.Header.Get(\\\\\\\"Schedule\\\\\\\") != \\\\\\\"\\\\\\\" {\\\\r\\\\n\\\\t\\\\tif !c.User.Permissions[\\\\\\\"allowPublish\\\\\\\"] {\\\\r\\\\n\\\\t\\\\t\\\\treturn http.StatusForbidden, nil\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\treturn h.schedule(c, w, r)\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\treturn http.StatusNotFound, nil\\\\r\\\\n}\\\\r\\\\n\\\\r\\\\nfunc (h hugo) AfterAPI(c *filemanager.RequestContext, w http.ResponseWriter, r *http.Request) (int, error) {\\\\r\\\\n\\\\treturn 0, nil\\\\r\\\\n}\\\\r\\\\n\\\\r\\\\nfunc (h hugo) JavaScript() string {\\\\r\\\\n\\\\treturn rice.MustFindBox(\\\\\\\"./\\\\\\\").MustString(\\\\\\\"hugo.js\\\\\\\")\\\\r\\\\n}\\\\r\\\\n\\\\r\\\\n// run runs Hugo with the define arguments.\\\\r\\\\nfunc (h hugo) run(force bool) {\\\\r\\\\n\\\\t// If the CleanPublic option is enabled, clean it.\\\\r\\\\n\\\\tif h.CleanPublic {\\\\r\\\\n\\\\t\\\\tos.RemoveAll(h.Public)\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t// Prevent running if watching is enabled\\\\r\\\\n\\\\tif b, pos := variables.StringInSlice(\\\\\\\"--watch\\\\\\\", h.Args); b && !force {\\\\r\\\\n\\\\t\\\\tif len(h.Args) > pos && h.Args[pos+1] != \\\\\\\"false\\\\\\\" {\\\\r\\\\n\\\\t\\\\t\\\\treturn\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\tif len(h.Args) == pos+1 {\\\\r\\\\n\\\\t\\\\t\\\\treturn\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\tif err := Run(h.Exe, h.Args, h.Root); err != nil {\\\\r\\\\n\\\\t\\\\tlog.Println(err)\\\\r\\\\n\\\\t}\\\\r\\\\n}\\\\r\\\\n\\\\r\\\\n// schedule schedules a post to be published later.\\\\r\\\\nfunc (h hugo) schedule(c *filemanager.RequestContext, w http.ResponseWriter, r *http.Request) (int, error) {\\\\r\\\\n\\\\tt, err := time.Parse(\\\\\\\"2006-01-02T15:04\\\\\\\", r.Header.Get(\\\\\\\"Schedule\\\\\\\"))\\\\r\\\\n\\\\tpath := filepath.Join(string(c.User.FileSystem), r.URL.Path)\\\\r\\\\n\\\\tpath = filepath.Clean(path)\\\\r\\\\n\\\\r\\\\n\\\\tif err != nil {\\\\r\\\\n\\\\t\\\\treturn http.StatusInternalServerError, err\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\tscheduler := cron.New()\\\\r\\\\n\\\\tscheduler.AddFunc(t.Format(\\\\\\\"05 04 15 02 01 *\\\\\\\"), func() {\\\\r\\\\n\\\\t\\\\targs := []string{\\\\\\\"undraft\\\\\\\", path}\\\\r\\\\n\\\\t\\\\tif err := Run(h.Exe, args, h.Root); err != nil {\\\\r\\\\n\\\\t\\\\t\\\\tlog.Printf(err.Error())\\\\r\\\\n\\\\t\\\\t\\\\treturn\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\th.run(false)\\\\r\\\\n\\\\t})\\\\r\\\\n\\\\r\\\\n\\\\tscheduler.Start()\\\\r\\\\n\\\\treturn http.StatusOK, nil\\\\r\\\\n}\\\\r\\\\n\\\"),\\n\\t}\\n\\tfile4 := &embedded.EmbeddedFile{\\n\\t\\tFilename: `hugo.js`,\\n\\t\\tFileModTime: time.Unix(1500387945, 0),\\n\\t\\tContent: string(\\\"'use strict';\\\\r\\\\n\\\\r\\\\n(function () {\\\\r\\\\n if (window.plugins === undefined || window.plugins === null) {\\\\r\\\\n window.plugins = []\\\\r\\\\n }\\\\r\\\\n\\\\r\\\\n let regenerate = function (data, url) {\\\\r\\\\n url = data.api.removePrefix(url)\\\\r\\\\n\\\\r\\\\n return new Promise((resolve, reject) => {\\\\r\\\\n let request = new window.XMLHttpRequest()\\\\r\\\\n request.open('POST', `${data.store.state.baseURL}/api/hugo${url}`, true)\\\\r\\\\n request.setRequestHeader('Authorization', `Bearer ${data.store.state.jwt}`)\\\\r\\\\n request.setRequestHeader('Regenerate', 'true')\\\\r\\\\n\\\\r\\\\n request.onload = () => {\\\\r\\\\n if (request.status === 200) {\\\\r\\\\n resolve()\\\\r\\\\n } else {\\\\r\\\\n reject(request.responseText)\\\\r\\\\n }\\\\r\\\\n }\\\\r\\\\n\\\\r\\\\n request.onerror = (error) => reject(error)\\\\r\\\\n request.send()\\\\r\\\\n })\\\\r\\\\n }\\\\r\\\\n\\\\r\\\\n let newArchetype = function (data, url, type) {\\\\r\\\\n url = data.api.removePrefix(url)\\\\r\\\\n\\\\r\\\\n return new Promise((resolve, reject) => {\\\\r\\\\n let request = new window.XMLHttpRequest()\\\\r\\\\n request.open('POST', `${data.store.state.baseURL}/api/hugo${url}`, true)\\\\r\\\\n request.setRequestHeader('Authorization', `Bearer ${data.store.state.jwt}`)\\\\r\\\\n request.setRequestHeader('Archetype', encodeURIComponent(type))\\\\r\\\\n\\\\r\\\\n request.onload = () => {\\\\r\\\\n if (request.status === 200) {\\\\r\\\\n resolve(request.getResponseHeader('Location'))\\\\r\\\\n } else {\\\\r\\\\n reject(request.responseText)\\\\r\\\\n }\\\\r\\\\n }\\\\r\\\\n\\\\r\\\\n request.onerror = (error) => reject(error)\\\\r\\\\n request.send()\\\\r\\\\n })\\\\r\\\\n }\\\\r\\\\n\\\\r\\\\n let schedule = function (data, file, date) {\\\\r\\\\n file = data.api.removePrefix(file)\\\\r\\\\n\\\\r\\\\n return new Promise((resolve, reject) => {\\\\r\\\\n let request = new window.XMLHttpRequest()\\\\r\\\\n request.open('POST', `${data.store.state.baseURL}/api/hugo${file}`, true)\\\\r\\\\n request.setRequestHeader('Authorization', `Bearer ${data.store.state.jwt}`)\\\\r\\\\n request.setRequestHeader('Schedule', date)\\\\r\\\\n\\\\r\\\\n request.onload = () => {\\\\r\\\\n if (request.status === 200) {\\\\r\\\\n resolve(request.getResponseHeader('Location'))\\\\r\\\\n } else {\\\\r\\\\n reject(request.responseText)\\\\r\\\\n }\\\\r\\\\n }\\\\r\\\\n\\\\r\\\\n request.onerror = (error) => reject(error)\\\\r\\\\n request.send()\\\\r\\\\n })\\\\r\\\\n }\\\\r\\\\n\\\\r\\\\n window.plugins.push({\\\\r\\\\n name: 'hugo',\\\\r\\\\n credits: 'With a flavour of Hugo.',\\\\r\\\\n header: {\\\\r\\\\n visible: [\\\\r\\\\n {\\\\r\\\\n if: function (data, route) {\\\\r\\\\n return (data.store.state.req.kind === 'editor' &&\\\\r\\\\n !data.store.state.loading &&\\\\r\\\\n data.store.state.req.metadata !== undefined &&\\\\r\\\\n data.store.state.req.metadata !== null &&\\\\r\\\\n data.store.state.user.allowEdit &\\\\r\\\\n data.store.state.user.permissions.allowPublish)\\\\r\\\\n },\\\\r\\\\n click: function (event, data, route) {\\\\r\\\\n event.preventDefault()\\\\r\\\\n document.getElementById('save-button').click()\\\\r\\\\n // TODO: wait for save to finish?\\\\r\\\\n data.buttons.loading('publish')\\\\r\\\\n\\\\r\\\\n regenerate(data, route.path)\\\\r\\\\n .then(() => {\\\\r\\\\n data.buttons.done('publish')\\\\r\\\\n data.store.commit('showSuccess', 'Post published!')\\\\r\\\\n data.store.commit('setReload', true)\\\\r\\\\n })\\\\r\\\\n .catch((error) => {\\\\r\\\\n data.buttons.done('publish')\\\\r\\\\n data.store.commit('showError', error)\\\\r\\\\n })\\\\r\\\\n },\\\\r\\\\n id: 'publish-button',\\\\r\\\\n icon: 'send',\\\\r\\\\n name: 'Publish'\\\\r\\\\n }\\\\r\\\\n ],\\\\r\\\\n hidden: [\\\\r\\\\n {\\\\r\\\\n if: function (data, route) {\\\\r\\\\n return (data.store.state.req.kind === 'editor' &&\\\\r\\\\n !data.store.state.loading &&\\\\r\\\\n data.store.state.req.metadata !== undefined &&\\\\r\\\\n data.store.state.req.metadata !== null &&\\\\r\\\\n data.store.state.user.permissions.allowPublish)\\\\r\\\\n },\\\\r\\\\n click: function (event, data, route) {\\\\r\\\\n document.getElementById('save-button').click()\\\\r\\\\n data.store.commit('showHover', 'schedule')\\\\r\\\\n },\\\\r\\\\n id: 'schedule-button',\\\\r\\\\n icon: 'alarm',\\\\r\\\\n name: 'Schedule'\\\\r\\\\n }\\\\r\\\\n ]\\\\r\\\\n },\\\\r\\\\n sidebar: [\\\\r\\\\n {\\\\r\\\\n click: function (event, data, route) {\\\\r\\\\n data.router.push({ path: '/files/settings' })\\\\r\\\\n },\\\\r\\\\n icon: 'settings',\\\\r\\\\n name: 'Hugo Settings'\\\\r\\\\n },\\\\r\\\\n {\\\\r\\\\n click: function (event, data, route) {\\\\r\\\\n data.store.commit('showHover', 'new-archetype')\\\\r\\\\n },\\\\r\\\\n if: function (data, route) {\\\\r\\\\n return data.store.state.user.allowNew\\\\r\\\\n },\\\\r\\\\n icon: 'merge_type',\\\\r\\\\n name: 'Hugo New'\\\\r\\\\n } /* ,\\\\r\\\\n {\\\\r\\\\n click: function (event, data, route) {\\\\r\\\\n console.log('evt')\\\\r\\\\n },\\\\r\\\\n icon: 'remove_red_eye',\\\\r\\\\n name: 'Preview'\\\\r\\\\n } */\\\\r\\\\n ],\\\\r\\\\n prompts: [\\\\r\\\\n {\\\\r\\\\n name: 'new-archetype',\\\\r\\\\n title: 'New file',\\\\r\\\\n description: 'Create a new post based on an archetype. Your file will be created on content folder.',\\\\r\\\\n inputs: [\\\\r\\\\n {\\\\r\\\\n type: 'text',\\\\r\\\\n name: 'file',\\\\r\\\\n placeholder: 'File name'\\\\r\\\\n },\\\\r\\\\n {\\\\r\\\\n type: 'text',\\\\r\\\\n name: 'archetype',\\\\r\\\\n placeholder: 'Archetype'\\\\r\\\\n }\\\\r\\\\n ],\\\\r\\\\n ok: 'Create',\\\\r\\\\n submit: function (event, data, route) {\\\\r\\\\n event.preventDefault()\\\\r\\\\n\\\\r\\\\n let file = event.currentTarget.querySelector('[name=\\\\\\\"file\\\\\\\"]').value\\\\r\\\\n let type = event.currentTarget.querySelector('[name=\\\\\\\"archetype\\\\\\\"]').value\\\\r\\\\n if (type === '') type = 'default'\\\\r\\\\n\\\\r\\\\n data.store.commit('closeHovers')\\\\r\\\\n\\\\r\\\\n newArchetype(data, '/' + file, type)\\\\r\\\\n .then((url) => {\\\\r\\\\n data.router.push({ path: url })\\\\r\\\\n })\\\\r\\\\n .catch(error => {\\\\r\\\\n data.store.commit('showError', error)\\\\r\\\\n })\\\\r\\\\n }\\\\r\\\\n },\\\\r\\\\n {\\\\r\\\\n name: 'schedule',\\\\r\\\\n title: 'Schedule',\\\\r\\\\n description: 'Pick a date and time to schedule the publication of this post.',\\\\r\\\\n inputs: [\\\\r\\\\n {\\\\r\\\\n type: 'datetime-local',\\\\r\\\\n name: 'date',\\\\r\\\\n placeholder: 'Date'\\\\r\\\\n }\\\\r\\\\n ],\\\\r\\\\n ok: 'Schedule',\\\\r\\\\n submit: function (event, data, route) {\\\\r\\\\n event.preventDefault()\\\\r\\\\n data.buttons.loading('schedule')\\\\r\\\\n\\\\r\\\\n let date = event.currentTarget.querySelector('[name=\\\\\\\"date\\\\\\\"]').value\\\\r\\\\n if (date === '') {\\\\r\\\\n data.buttons.done('schedule')\\\\r\\\\n data.store.commit('showError', 'The date must not be empty.')\\\\r\\\\n return\\\\r\\\\n }\\\\r\\\\n\\\\r\\\\n schedule(data, route.path, date)\\\\r\\\\n .then(() => {\\\\r\\\\n data.buttons.done('schedule')\\\\r\\\\n data.store.commit('showSuccess', 'Post scheduled!')\\\\r\\\\n })\\\\r\\\\n .catch((error) => {\\\\r\\\\n data.buttons.done('schedule')\\\\r\\\\n data.store.commit('showError', error)\\\\r\\\\n })\\\\r\\\\n }\\\\r\\\\n }\\\\r\\\\n ]\\\\r\\\\n })\\\\r\\\\n})()\\\\r\\\\n\\\"),\\n\\t}\\n\\tfile5 := &embedded.EmbeddedFile{\\n\\t\\tFilename: `rice-box.go`,\\n\\t\\tFileModTime: time.Unix(1500387945, 0),\\n\\t\\tContent: string(\\\"package hugo\\\\r\\\\n\\\\r\\\\nimport (\\\\r\\\\n\\\\t\\\\\\\"github.com/GeertJohan/go.rice/embedded\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"time\\\\\\\"\\\\r\\\\n)\\\\r\\\\n\\\\r\\\\nfunc init() {\\\\r\\\\n\\\\r\\\\n\\\\t// define files\\\\r\\\\n\\\\tfile2 := &embedded.EmbeddedFile{\\\\r\\\\n\\\\t\\\\tFilename: `README.md`,\\\\r\\\\n\\\\t\\\\tFileModTime: time.Unix(1500364498, 0),\\\\r\\\\n\\\\t\\\\tContent: string(\\\\\\\"# hugo - a caddy plugin\\\\\\\\n\\\\\\\\n[![community](https://img.shields.io/badge/community-forum-ff69b4.svg?style=flat-square)](https://caddy.community)\\\\\\\\n\\\\\\\\nhugo fills the gap between Hugo and the browser. [Hugo][6] 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.\\\\\\\\n\\\\\\\\nUsing 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. It is an implementation of [hacdias/filemanager][1] library.\\\\\\\\n\\\\\\\\n**Requirements:** you need to have the hugo executable in your PATH. You can download it from its [official page][6].\\\\\\\\n\\\\\\\\n## Get Started\\\\\\\\n\\\\\\\\nTo start using this plugin you just need to go to the [download Caddy page][3] and choose `http.hugo` in the directives section. For further information on how Caddy works refer to [its documentation][4].\\\\\\\\n\\\\\\\\nThe default credentials are `admin` for both the user and the password. It is highy recommended to change them after logging in for the first time and to use HTTPS. You can create more users and define their own permissions using the web interface.\\\\\\\\n\\\\\\\\n## Syntax\\\\\\\\n\\\\\\\\n```\\\\\\\\nhugo [directory] [admin] {\\\\\\\\n database path\\\\\\\\n}\\\\\\\\n```\\\\\\\\n\\\\\\\\n+ `directory` is the path, relative or absolute to the directory of your Hugo files. Defaults to `./`.\\\\\\\\n+ `admin` is the URL path where you will access the admin interface. Defaults to `/admin`.\\\\\\\\n+ `path` is the database path where the settings will be stored. By default, the settings will be stored on [`.caddy`][5] folder.\\\\\\\\n\\\\\\\\n## Database\\\\\\\\n\\\\\\\\nBy default the database will be stored on [`.caddy`][5] directory, in a sub-directory called `hugo`. Each file name is an hash of the combination of the host and the base URL.\\\\\\\\n\\\\\\\\nIf you don't set a database path, you will receive a warning like this:\\\\\\\\n\\\\\\\\n> [WARNING] A database is going to be created for your File Manager instace at ~/.caddy/hugo/xxx.db. It is highly recommended that you set the 'database' option to 'xxx.db'\\\\\\\\n\\\\\\\\nWhy? If you don't set a database path and you change the host or the base URL, your settings will be reseted. So it is *highly* recommended to set this option.\\\\\\\\n\\\\\\\\nWhen you set a relative path, such as `xxxxxxxxxx.db`, it will always be relative to `.caddy/hugo` directory. Although, you may also use an absolute path if you wish to store the database in other place.\\\\\\\\n\\\\\\\\n## Examples\\\\\\\\n\\\\\\\\nManage the current working directory's Hugo website at `/admin`.\\\\\\\\n\\\\\\\\n```\\\\\\\\nhugo {\\\\\\\\n database myinstance.db\\\\\\\\n}\\\\\\\\n```\\\\\\\\n\\\\\\\\nManage the Hugo website located at `/var/www/mysite` at `/admin`.\\\\\\\\n\\\\\\\\n```\\\\\\\\nhugo /var/www/mysite {\\\\\\\\n database myinstance.db\\\\\\\\n}\\\\\\\\n```\\\\\\\\n\\\\\\\\nManage the Hugo website located at `/var/www/mysite` at `/private`.\\\\\\\\n\\\\\\\\n```\\\\\\\\nhugo /var/www/mysite /private {\\\\\\\\n database myinstance.db\\\\\\\\n}\\\\\\\\n```\\\\\\\\n\\\\\\\\n## Known Issues\\\\\\\\n\\\\\\\\nIf you are having troubles **handling large files** you might need to check out the [`timeouts`][2] plugin, which can be used to change the default HTTP Timeouts.\\\\\\\\n\\\\\\\\n[1]:https://github.com/hacdias/filemanager\\\\\\\\n[2]:https://caddyserver.com/docs/timeouts\\\\\\\\n[3]:https://caddyserver.com/download\\\\\\\\n[4]:https://caddyserver.com/docs\\\\\\\\n[5]:https://caddyserver.com/docs/automatic-https#dot-caddy\\\\\\\\n[6]:http://gohugo.io\\\\\\\\n\\\\\\\"),\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\tfile3 := &embedded.EmbeddedFile{\\\\r\\\\n\\\\t\\\\tFilename: `hugo.go`,\\\\r\\\\n\\\\t\\\\tFileModTime: time.Unix(1500017442, 0),\\\\r\\\\n\\\\t\\\\tContent: string(\\\\\\\"package hugo\\\\\\\\n\\\\\\\\nimport (\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"log\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"net/http\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"os\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"path/filepath\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"strings\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"time\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\n\\\\\\\\trice \\\\\\\\\\\\\\\"github.com/GeertJohan/go.rice\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"github.com/hacdias/filemanager\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"github.com/hacdias/filemanager/variables\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"github.com/robfig/cron\\\\\\\\\\\\\\\"\\\\\\\\n)\\\\\\\\n\\\\\\\\ntype hugo struct {\\\\\\\\n\\\\\\\\t// Website root\\\\\\\\n\\\\\\\\tRoot string `description:\\\\\\\\\\\\\\\"The relative or absolute path to the place where your website is located.\\\\\\\\\\\\\\\"`\\\\\\\\n\\\\\\\\t// Public folder\\\\\\\\n\\\\\\\\tPublic string `description:\\\\\\\\\\\\\\\"The relative or absolute path to the public folder.\\\\\\\\\\\\\\\"`\\\\\\\\n\\\\\\\\t// Hugo executable path\\\\\\\\n\\\\\\\\tExe string `description:\\\\\\\\\\\\\\\"The absolute path to the Hugo executable or the command to execute.\\\\\\\\\\\\\\\"`\\\\\\\\n\\\\\\\\t// Hugo arguments\\\\\\\\n\\\\\\\\tArgs []string `description:\\\\\\\\\\\\\\\"The arguments to run when running Hugo\\\\\\\\\\\\\\\"`\\\\\\\\n\\\\\\\\t// Indicates if we should clean public before a new publish.\\\\\\\\n\\\\\\\\tCleanPublic bool `description:\\\\\\\\\\\\\\\"Indicates if the public folder should be cleaned before publishing the website.\\\\\\\\\\\\\\\"`\\\\\\\\n\\\\\\\\n\\\\\\\\t// TODO: admin interface to cgange options\\\\\\\\n}\\\\\\\\n\\\\\\\\nfunc (h hugo) BeforeAPI(c *filemanager.RequestContext, w http.ResponseWriter, r *http.Request) (int, error) {\\\\\\\\n\\\\\\\\t// If we are using the 'magic url' for the settings, we should redirect the\\\\\\\\n\\\\\\\\t// request for the acutual path.\\\\\\\\n\\\\\\\\tif r.URL.Path == \\\\\\\\\\\\\\\"/settings/\\\\\\\\\\\\\\\" || r.URL.Path == \\\\\\\\\\\\\\\"/settings\\\\\\\\\\\\\\\" {\\\\\\\\n\\\\\\\\t\\\\\\\\tvar frontmatter string\\\\\\\\n\\\\\\\\t\\\\\\\\tvar err error\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\tif _, err = os.Stat(filepath.Join(h.Root, \\\\\\\\\\\\\\\"config.yaml\\\\\\\\\\\\\\\")); err == nil {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tfrontmatter = \\\\\\\\\\\\\\\"yaml\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\tif _, err = os.Stat(filepath.Join(h.Root, \\\\\\\\\\\\\\\"config.json\\\\\\\\\\\\\\\")); err == nil {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tfrontmatter = \\\\\\\\\\\\\\\"json\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\tif _, err = os.Stat(filepath.Join(h.Root, \\\\\\\\\\\\\\\"config.toml\\\\\\\\\\\\\\\")); err == nil {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tfrontmatter = \\\\\\\\\\\\\\\"toml\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\tr.URL.Path = \\\\\\\\\\\\\\\"/config.\\\\\\\\\\\\\\\" + frontmatter\\\\\\\\n\\\\\\\\t\\\\\\\\treturn 0, nil\\\\\\\\n\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t// From here on, we only care about 'hugo' router so we can bypass\\\\\\\\n\\\\\\\\t// the others.\\\\\\\\n\\\\\\\\tif c.Router != \\\\\\\\\\\\\\\"hugo\\\\\\\\\\\\\\\" {\\\\\\\\n\\\\\\\\t\\\\\\\\treturn 0, nil\\\\\\\\n\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t// If we are not using HTTP Post, we shall return Method Not Allowed\\\\\\\\n\\\\\\\\t// since we are only working with this method.\\\\\\\\n\\\\\\\\tif r.Method != http.MethodPost {\\\\\\\\n\\\\\\\\t\\\\\\\\treturn http.StatusMethodNotAllowed, nil\\\\\\\\n\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t// If we are creating a file built from an archetype.\\\\\\\\n\\\\\\\\tif r.Header.Get(\\\\\\\\\\\\\\\"Archetype\\\\\\\\\\\\\\\") != \\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\" {\\\\\\\\n\\\\\\\\t\\\\\\\\tif !c.User.AllowNew {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\treturn http.StatusForbidden, nil\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\tfilename := filepath.Join(string(c.User.FileSystem), r.URL.Path)\\\\\\\\n\\\\\\\\t\\\\\\\\tfilename = strings.TrimPrefix(filename, \\\\\\\\\\\\\\\"/\\\\\\\\\\\\\\\")\\\\\\\\n\\\\\\\\t\\\\\\\\tarchetype := r.Header.Get(\\\\\\\\\\\\\\\"archetype\\\\\\\\\\\\\\\")\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\text := filepath.Ext(filename)\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\t// If the request isn't for a markdown file, we can't\\\\\\\\n\\\\\\\\t\\\\\\\\t// handle it.\\\\\\\\n\\\\\\\\t\\\\\\\\tif ext != \\\\\\\\\\\\\\\".markdown\\\\\\\\\\\\\\\" && ext != \\\\\\\\\\\\\\\".md\\\\\\\\\\\\\\\" {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\treturn http.StatusBadRequest, errUnsupportedFileType\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\t// Tries to create a new file based on this archetype.\\\\\\\\n\\\\\\\\t\\\\\\\\targs := []string{\\\\\\\\\\\\\\\"new\\\\\\\\\\\\\\\", filename, \\\\\\\\\\\\\\\"--kind\\\\\\\\\\\\\\\", archetype}\\\\\\\\n\\\\\\\\t\\\\\\\\tif err := Run(h.Exe, args, h.Root); err != nil {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\treturn http.StatusInternalServerError, err\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\t// Writes the location of the new file to the Header.\\\\\\\\n\\\\\\\\t\\\\\\\\tw.Header().Set(\\\\\\\\\\\\\\\"Location\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\"/files/content/\\\\\\\\\\\\\\\"+filename)\\\\\\\\n\\\\\\\\t\\\\\\\\treturn http.StatusCreated, nil\\\\\\\\n\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t// If we are trying to regenerate the website.\\\\\\\\n\\\\\\\\tif r.Header.Get(\\\\\\\\\\\\\\\"Regenerate\\\\\\\\\\\\\\\") == \\\\\\\\\\\\\\\"true\\\\\\\\\\\\\\\" {\\\\\\\\n\\\\\\\\t\\\\\\\\tif !c.User.Permissions[\\\\\\\\\\\\\\\"allowPublish\\\\\\\\\\\\\\\"] {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\treturn http.StatusForbidden, nil\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\tfilename := filepath.Join(string(c.User.FileSystem), r.URL.Path)\\\\\\\\n\\\\\\\\t\\\\\\\\tfilename = strings.TrimPrefix(filename, \\\\\\\\\\\\\\\"/\\\\\\\\\\\\\\\")\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\t// Before save command handler.\\\\\\\\n\\\\\\\\t\\\\\\\\tif err := c.FM.Runner(\\\\\\\\\\\\\\\"before_publish\\\\\\\\\\\\\\\", filename); err != nil {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\treturn http.StatusInternalServerError, err\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\t// We only run undraft command if it is a file.\\\\\\\\n\\\\\\\\t\\\\\\\\tif !strings.HasSuffix(filename, \\\\\\\\\\\\\\\"/\\\\\\\\\\\\\\\") {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\targs := []string{\\\\\\\\\\\\\\\"undraft\\\\\\\\\\\\\\\", filename}\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tif err := Run(h.Exe, args, h.Root); err != nil {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\t\\\\\\\\treturn http.StatusInternalServerError, err\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\t// Regenerates the file\\\\\\\\n\\\\\\\\t\\\\\\\\th.run(false)\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\t// Executed the before publish command.\\\\\\\\n\\\\\\\\t\\\\\\\\tif err := c.FM.Runner(\\\\\\\\\\\\\\\"before_publish\\\\\\\\\\\\\\\", filename); err != nil {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\treturn http.StatusInternalServerError, err\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\treturn http.StatusOK, nil\\\\\\\\n\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\tif r.Header.Get(\\\\\\\\\\\\\\\"Schedule\\\\\\\\\\\\\\\") != \\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\" {\\\\\\\\n\\\\\\\\t\\\\\\\\tif !c.User.Permissions[\\\\\\\\\\\\\\\"allowPublish\\\\\\\\\\\\\\\"] {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\treturn http.StatusForbidden, nil\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\treturn h.schedule(c, w, r)\\\\\\\\n\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\treturn http.StatusNotFound, nil\\\\\\\\n}\\\\\\\\n\\\\\\\\nfunc (h hugo) AfterAPI(c *filemanager.RequestContext, w http.ResponseWriter, r *http.Request) (int, error) {\\\\\\\\n\\\\\\\\treturn 0, nil\\\\\\\\n}\\\\\\\\n\\\\\\\\nfunc (h hugo) JavaScript() string {\\\\\\\\n\\\\\\\\treturn rice.MustFindBox(\\\\\\\\\\\\\\\"./\\\\\\\\\\\\\\\").MustString(\\\\\\\\\\\\\\\"hugo.js\\\\\\\\\\\\\\\")\\\\\\\\n}\\\\\\\\n\\\\\\\\n// run runs Hugo with the define arguments.\\\\\\\\nfunc (h hugo) run(force bool) {\\\\\\\\n\\\\\\\\t// If the CleanPublic option is enabled, clean it.\\\\\\\\n\\\\\\\\tif h.CleanPublic {\\\\\\\\n\\\\\\\\t\\\\\\\\tos.RemoveAll(h.Public)\\\\\\\\n\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t// Prevent running if watching is enabled\\\\\\\\n\\\\\\\\tif b, pos := variables.StringInSlice(\\\\\\\\\\\\\\\"--watch\\\\\\\\\\\\\\\", h.Args); b && !force {\\\\\\\\n\\\\\\\\t\\\\\\\\tif len(h.Args) > pos && h.Args[pos+1] != \\\\\\\\\\\\\\\"false\\\\\\\\\\\\\\\" {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\treturn\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\tif len(h.Args) == pos+1 {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\treturn\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\tif err := Run(h.Exe, h.Args, h.Root); err != nil {\\\\\\\\n\\\\\\\\t\\\\\\\\tlog.Println(err)\\\\\\\\n\\\\\\\\t}\\\\\\\\n}\\\\\\\\n\\\\\\\\n// schedule schedules a post to be published later.\\\\\\\\nfunc (h hugo) schedule(c *filemanager.RequestContext, w http.ResponseWriter, r *http.Request) (int, error) {\\\\\\\\n\\\\\\\\tt, err := time.Parse(\\\\\\\\\\\\\\\"2006-01-02T15:04\\\\\\\\\\\\\\\", r.Header.Get(\\\\\\\\\\\\\\\"Schedule\\\\\\\\\\\\\\\"))\\\\\\\\n\\\\\\\\tpath := filepath.Join(string(c.User.FileSystem), r.URL.Path)\\\\\\\\n\\\\\\\\tpath = filepath.Clean(path)\\\\\\\\n\\\\\\\\n\\\\\\\\tif err != nil {\\\\\\\\n\\\\\\\\t\\\\\\\\treturn http.StatusInternalServerError, err\\\\\\\\n\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\tscheduler := cron.New()\\\\\\\\n\\\\\\\\tscheduler.AddFunc(t.Format(\\\\\\\\\\\\\\\"05 04 15 02 01 *\\\\\\\\\\\\\\\"), func() {\\\\\\\\n\\\\\\\\t\\\\\\\\targs := []string{\\\\\\\\\\\\\\\"undraft\\\\\\\\\\\\\\\", path}\\\\\\\\n\\\\\\\\t\\\\\\\\tif err := Run(h.Exe, args, h.Root); err != nil {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tlog.Printf(err.Error())\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\treturn\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\th.run(false)\\\\\\\\n\\\\\\\\t})\\\\\\\\n\\\\\\\\n\\\\\\\\tscheduler.Start()\\\\\\\\n\\\\\\\\treturn http.StatusOK, nil\\\\\\\\n}\\\\\\\\n\\\\\\\"),\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\tfile4 := &embedded.EmbeddedFile{\\\\r\\\\n\\\\t\\\\tFilename: `hugo.js`,\\\\r\\\\n\\\\t\\\\tFileModTime: time.Unix(1500385310, 0),\\\\r\\\\n\\\\t\\\\tContent: string(\\\\\\\"'use strict';\\\\\\\\n\\\\\\\\n(function () {\\\\\\\\n if (window.plugins === undefined || window.plugins === null) {\\\\\\\\n window.plugins = []\\\\\\\\n }\\\\\\\\n\\\\\\\\n let regenerate = function (data, url) {\\\\\\\\n url = data.api.removePrefix(url)\\\\\\\\n\\\\\\\\n return new Promise((resolve, reject) => {\\\\\\\\n let request = new window.XMLHttpRequest()\\\\\\\\n request.open('POST', `${data.store.state.baseURL}/api/hugo${url}`, true)\\\\\\\\n request.setRequestHeader('Authorization', `Bearer ${data.store.state.jwt}`)\\\\\\\\n request.setRequestHeader('Regenerate', 'true')\\\\\\\\n\\\\\\\\n request.onload = () => {\\\\\\\\n if (request.status === 200) {\\\\\\\\n resolve()\\\\\\\\n } else {\\\\\\\\n reject(request.responseText)\\\\\\\\n }\\\\\\\\n }\\\\\\\\n\\\\\\\\n request.onerror = (error) => reject(error)\\\\\\\\n request.send()\\\\\\\\n })\\\\\\\\n }\\\\\\\\n\\\\\\\\n let newArchetype = function (data, url, type) {\\\\\\\\n url = data.api.removePrefix(url)\\\\\\\\n\\\\\\\\n return new Promise((resolve, reject) => {\\\\\\\\n let request = new window.XMLHttpRequest()\\\\\\\\n request.open('POST', `${data.store.state.baseURL}/api/hugo${url}`, true)\\\\\\\\n request.setRequestHeader('Authorization', `Bearer ${data.store.state.jwt}`)\\\\\\\\n request.setRequestHeader('Archetype', encodeURIComponent(type))\\\\\\\\n\\\\\\\\n request.onload = () => {\\\\\\\\n if (request.status === 200) {\\\\\\\\n resolve(request.getResponseHeader('Location'))\\\\\\\\n } else {\\\\\\\\n reject(request.responseText)\\\\\\\\n }\\\\\\\\n }\\\\\\\\n\\\\\\\\n request.onerror = (error) => reject(error)\\\\\\\\n request.send()\\\\\\\\n })\\\\\\\\n }\\\\\\\\n\\\\\\\\n let schedule = function (data, file, date) {\\\\\\\\n file = data.api.removePrefix(file)\\\\\\\\n\\\\\\\\n return new Promise((resolve, reject) => {\\\\\\\\n let request = new window.XMLHttpRequest()\\\\\\\\n request.open('POST', `${data.store.state.baseURL}/api/hugo${file}`, true)\\\\\\\\n request.setRequestHeader('Authorization', `Bearer ${data.store.state.jwt}`)\\\\\\\\n request.setRequestHeader('Schedule', date)\\\\\\\\n\\\\\\\\n request.onload = () => {\\\\\\\\n if (request.status === 200) {\\\\\\\\n resolve(request.getResponseHeader('Location'))\\\\\\\\n } else {\\\\\\\\n reject(request.responseText)\\\\\\\\n }\\\\\\\\n }\\\\\\\\n\\\\\\\\n request.onerror = (error) => reject(error)\\\\\\\\n request.send()\\\\\\\\n })\\\\\\\\n }\\\\\\\\n\\\\\\\\n window.plugins.push({\\\\\\\\n name: 'hugo',\\\\\\\\n credits: 'With a flavour of Hugo.',\\\\\\\\n header: {\\\\\\\\n visible: [\\\\\\\\n {\\\\\\\\n if: function (data, route) {\\\\\\\\n return (data.store.state.req.kind === 'editor' &&\\\\\\\\n !data.store.state.loading &&\\\\\\\\n data.store.state.req.metadata !== undefined &&\\\\\\\\n data.store.state.req.metadata !== null &&\\\\\\\\n data.store.state.user.allowEdit &\\\\\\\\n data.store.state.user.permissions.allowPublish)\\\\\\\\n },\\\\\\\\n click: function (event, data, route) {\\\\\\\\n event.preventDefault()\\\\\\\\n document.getElementById('save-button').click()\\\\\\\\n // TODO: wait for save to finish?\\\\\\\\n data.buttons.loading('publish')\\\\\\\\n\\\\\\\\n regenerate(data, route.path)\\\\\\\\n .then(() => {\\\\\\\\n data.buttons.done('publish')\\\\\\\\n data.store.commit('showSuccess', 'Post published!')\\\\\\\\n data.store.commit('setReload', true)\\\\\\\\n })\\\\\\\\n .catch((error) => {\\\\\\\\n data.buttons.done('publish')\\\\\\\\n data.store.commit('showError', error)\\\\\\\\n })\\\\\\\\n },\\\\\\\\n id: 'publish-button',\\\\\\\\n icon: 'send',\\\\\\\\n name: 'Publish'\\\\\\\\n }\\\\\\\\n ],\\\\\\\\n hidden: [\\\\\\\\n {\\\\\\\\n if: function (data, route) {\\\\\\\\n return (data.store.state.req.kind === 'editor' &&\\\\\\\\n !data.store.state.loading &&\\\\\\\\n data.store.state.req.metadata !== undefined &&\\\\\\\\n data.store.state.req.metadata !== null &&\\\\\\\\n data.store.state.user.permissions.allowPublish)\\\\\\\\n },\\\\\\\\n click: function (event, data, route) {\\\\\\\\n document.getElementById('save-button').click()\\\\\\\\n data.store.commit('showHover', 'schedule')\\\\\\\\n },\\\\\\\\n id: 'schedule-button',\\\\\\\\n icon: 'alarm',\\\\\\\\n name: 'Schedule'\\\\\\\\n }\\\\\\\\n ]\\\\\\\\n },\\\\\\\\n sidebar: [\\\\\\\\n {\\\\\\\\n click: function (event, data, route) {\\\\\\\\n data.router.push({ path: '/files/settings' })\\\\\\\\n },\\\\\\\\n icon: 'settings',\\\\\\\\n name: 'Hugo Settings'\\\\\\\\n },\\\\\\\\n {\\\\\\\\n click: function (event, data, route) {\\\\\\\\n data.store.commit('showHover', 'new-archetype')\\\\\\\\n },\\\\\\\\n if: function (data, route) {\\\\\\\\n return data.store.state.user.allowNew\\\\\\\\n },\\\\\\\\n icon: 'merge_type',\\\\\\\\n name: 'Hugo New'\\\\\\\\n } /* ,\\\\\\\\n {\\\\\\\\n click: function (event, data, route) {\\\\\\\\n console.log('evt')\\\\\\\\n },\\\\\\\\n icon: 'remove_red_eye',\\\\\\\\n name: 'Preview'\\\\\\\\n } */\\\\\\\\n ],\\\\\\\\n prompts: [\\\\\\\\n {\\\\\\\\n name: 'new-archetype',\\\\\\\\n title: 'New file',\\\\\\\\n description: 'Create a new post based on an archetype. Your file will be created on content folder.',\\\\\\\\n inputs: [\\\\\\\\n {\\\\\\\\n type: 'text',\\\\\\\\n name: 'file',\\\\\\\\n placeholder: 'File name'\\\\\\\\n },\\\\\\\\n {\\\\\\\\n type: 'text',\\\\\\\\n name: 'archetype',\\\\\\\\n placeholder: 'Archetype'\\\\\\\\n }\\\\\\\\n ],\\\\\\\\n ok: 'Create',\\\\\\\\n submit: function (event, data, route) {\\\\\\\\n event.preventDefault()\\\\\\\\n\\\\\\\\n let file = event.currentTarget.querySelector('[name=\\\\\\\\\\\\\\\"file\\\\\\\\\\\\\\\"]').value\\\\\\\\n let type = event.currentTarget.querySelector('[name=\\\\\\\\\\\\\\\"archetype\\\\\\\\\\\\\\\"]').value\\\\\\\\n if (type === '') type = 'default'\\\\\\\\n\\\\\\\\n data.store.commit('closeHovers')\\\\\\\\n\\\\\\\\n newArchetype(data, '/' + file, type)\\\\\\\\n .then((url) => {\\\\\\\\n data.router.push({ path: url })\\\\\\\\n })\\\\\\\\n .catch(error => {\\\\\\\\n data.store.commit('showError', error)\\\\\\\\n })\\\\\\\\n }\\\\\\\\n },\\\\\\\\n {\\\\\\\\n name: 'schedule',\\\\\\\\n title: 'Schedule',\\\\\\\\n description: 'Pick a date and time to schedule the publication of this post.',\\\\\\\\n inputs: [\\\\\\\\n {\\\\\\\\n type: 'datetime-local',\\\\\\\\n name: 'date',\\\\\\\\n placeholder: 'Date'\\\\\\\\n }\\\\\\\\n ],\\\\\\\\n ok: 'Schedule',\\\\\\\\n submit: function (event, data, route) {\\\\\\\\n event.preventDefault()\\\\\\\\n data.buttons.loading('schedule')\\\\\\\\n\\\\\\\\n let date = event.currentTarget.querySelector('[name=\\\\\\\\\\\\\\\"date\\\\\\\\\\\\\\\"]').value\\\\\\\\n if (date === '') {\\\\\\\\n data.buttons.done('schedule')\\\\\\\\n data.store.commit('showError', 'The date must not be empty.')\\\\\\\\n return\\\\\\\\n }\\\\\\\\n\\\\\\\\n schedule(data, route.path, date)\\\\\\\\n .then(() => {\\\\\\\\n data.buttons.done('schedule')\\\\\\\\n data.store.commit('showSuccess', 'Post scheduled!')\\\\\\\\n })\\\\\\\\n .catch((error) => {\\\\\\\\n data.buttons.done('schedule')\\\\\\\\n data.store.commit('showError', error)\\\\\\\\n })\\\\\\\\n }\\\\\\\\n }\\\\\\\\n ]\\\\\\\\n })\\\\\\\\n})()\\\\\\\\n\\\\\\\"),\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\tfile5 := &embedded.EmbeddedFile{\\\\r\\\\n\\\\t\\\\tFilename: `setup.go`,\\\\r\\\\n\\\\t\\\\tFileModTime: time.Unix(1500361773, 0),\\\\r\\\\n\\\\t\\\\tContent: string(\\\\\\\"package hugo\\\\\\\\n\\\\\\\\nimport (\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"crypto/md5\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"encoding/hex\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"errors\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"fmt\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"net/http\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"os\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"os/exec\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"path/filepath\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"strings\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"github.com/hacdias/filemanager\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"github.com/mholt/caddy\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"github.com/mholt/caddy/caddyhttp/httpserver\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"golang.org/x/net/webdav\\\\\\\\\\\\\\\"\\\\\\\\n)\\\\\\\\n\\\\\\\\nvar (\\\\\\\\n\\\\\\\\terrHugoNotFound = errors.New(\\\\\\\\\\\\\\\"It seems that tou don't have 'hugo' on your PATH\\\\\\\\\\\\\\\")\\\\\\\\n\\\\\\\\terrUnsupportedFileType = errors.New(\\\\\\\\\\\\\\\"The type of the provided file isn't supported for this action\\\\\\\\\\\\\\\")\\\\\\\\n)\\\\\\\\n\\\\\\\\n// setup configures a new FileManager middleware instance.\\\\\\\\nfunc setup(c *caddy.Controller) error {\\\\\\\\n\\\\\\\\tconfigs, err := parse(c)\\\\\\\\n\\\\\\\\tif err != nil {\\\\\\\\n\\\\\\\\t\\\\\\\\treturn err\\\\\\\\n\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\thttpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {\\\\\\\\n\\\\\\\\t\\\\\\\\treturn plugin{Configs: configs, Next: next}\\\\\\\\n\\\\\\\\t})\\\\\\\\n\\\\\\\\n\\\\\\\\treturn nil\\\\\\\\n}\\\\\\\\n\\\\\\\\nfunc parse(c *caddy.Controller) ([]*filemanager.FileManager, error) {\\\\\\\\n\\\\\\\\tvar (\\\\\\\\n\\\\\\\\t\\\\\\\\tconfigs []*filemanager.FileManager\\\\\\\\n\\\\\\\\t)\\\\\\\\n\\\\\\\\n\\\\\\\\tfor c.Next() {\\\\\\\\n\\\\\\\\t\\\\\\\\t// hugo [directory] [admin] {\\\\\\\\n\\\\\\\\t\\\\\\\\t// \\\\\\\\t\\\\\\\\tdatabase path\\\\\\\\n\\\\\\\\t\\\\\\\\t// }\\\\\\\\n\\\\\\\\t\\\\\\\\tdirectory := \\\\\\\\\\\\\\\".\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\tadmin := \\\\\\\\\\\\\\\"/admin\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\tdatabase := \\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\t// Get the baseURL and baseScope\\\\\\\\n\\\\\\\\t\\\\\\\\targs := c.RemainingArgs()\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\tif len(args) == 1 {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tdirectory = args[0]\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\tif len(args) > 1 {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tadmin = args[1]\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\tfor c.NextBlock() {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tswitch c.Val() {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tcase \\\\\\\\\\\\\\\"database\\\\\\\\\\\\\\\":\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\t\\\\\\\\tif !c.NextArg() {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\t\\\\\\\\t\\\\\\\\treturn nil, c.ArgErr()\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\t\\\\\\\\tdatabase = c.Val()\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\tcaddyConf := httpserver.GetConfig(c)\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\tpath := filepath.Join(caddy.AssetsPath(), \\\\\\\\\\\\\\\"hugo\\\\\\\\\\\\\\\")\\\\\\\\n\\\\\\\\t\\\\\\\\terr := os.MkdirAll(path, 0700)\\\\\\\\n\\\\\\\\t\\\\\\\\tif err != nil {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\treturn nil, err\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\t// if there is a database path and it is not absolute,\\\\\\\\n\\\\\\\\t\\\\\\\\t// it will be relative to \\\\\\\\\\\\\\\".caddy\\\\\\\\\\\\\\\" folder.\\\\\\\\n\\\\\\\\t\\\\\\\\tif !filepath.IsAbs(database) && database != \\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\" {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tdatabase = filepath.Join(path, database)\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\t// If there is no database path on the settings,\\\\\\\\n\\\\\\\\t\\\\\\\\t// store one in .caddy/hugo/{name}.db.\\\\\\\\n\\\\\\\\t\\\\\\\\tif database == \\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\" {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\t// The name of the database is the hashed value of a string composed\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\t// by the host, address path and the baseurl of this File Manager\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\t// instance.\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\thasher := md5.New()\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\thasher.Write([]byte(caddyConf.Addr.Host + caddyConf.Addr.Path + admin))\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tsha := hex.EncodeToString(hasher.Sum(nil))\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tdatabase = filepath.Join(path, sha+\\\\\\\\\\\\\\\".db\\\\\\\\\\\\\\\")\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tfmt.Println(\\\\\\\\\\\\\\\"[WARNING] A database is going to be created for your Hugo instace at \\\\\\\\\\\\\\\" + database +\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\t\\\\\\\\t\\\\\\\\\\\\\\\". It is highly recommended that you set the 'database' option to '\\\\\\\\\\\\\\\" + sha + \\\\\\\\\\\\\\\".db'\\\\\\\\\\\\\\\\n\\\\\\\\\\\\\\\")\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\tm, err := filemanager.New(database, filemanager.User{\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tUsername: \\\\\\\\\\\\\\\"admin\\\\\\\\\\\\\\\",\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tPassword: \\\\\\\\\\\\\\\"admin\\\\\\\\\\\\\\\",\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tAllowCommands: true,\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tAllowEdit: true,\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tAllowNew: true,\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tPermissions: map[string]bool{},\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tCommands: []string{\\\\\\\\\\\\\\\"git\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\"svn\\\\\\\\\\\\\\\", \\\\\\\\\\\\\\\"hg\\\\\\\\\\\\\\\"},\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tRules: []*filemanager.Rule{{\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\t\\\\\\\\tRegex: true,\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\t\\\\\\\\tAllow: false,\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\t\\\\\\\\tRegexp: &filemanager.Regexp{Raw: \\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\..+\\\\\\\\\\\\\\\"},\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\t}},\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tCSS: \\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\",\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tFileSystem: webdav.Dir(directory),\\\\\\\\n\\\\\\\\t\\\\\\\\t})\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\tif err != nil {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\treturn nil, err\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\t// Initialize the default settings for Hugo.\\\\\\\\n\\\\\\\\t\\\\\\\\thugo := &hugo{\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tRoot: directory,\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tPublic: filepath.Join(directory, \\\\\\\\\\\\\\\"public\\\\\\\\\\\\\\\"),\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tArgs: []string{},\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tCleanPublic: true,\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\t// Try to find the Hugo executable path.\\\\\\\\n\\\\\\\\t\\\\\\\\tif hugo.Exe, err = exec.LookPath(\\\\\\\\\\\\\\\"hugo\\\\\\\\\\\\\\\"); err != nil {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\treturn nil, errHugoNotFound\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\terr = m.RegisterPlugin(\\\\\\\\\\\\\\\"hugo\\\\\\\\\\\\\\\", hugo)\\\\\\\\n\\\\\\\\t\\\\\\\\tif err != nil {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\treturn nil, err\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\terr = m.RegisterEventType(\\\\\\\\\\\\\\\"before_publish\\\\\\\\\\\\\\\")\\\\\\\\n\\\\\\\\t\\\\\\\\tif err != nil {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\treturn nil, err\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\terr = m.RegisterEventType(\\\\\\\\\\\\\\\"after_publish\\\\\\\\\\\\\\\")\\\\\\\\n\\\\\\\\t\\\\\\\\tif err != nil {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\treturn nil, err\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\terr = m.RegisterPermission(\\\\\\\\\\\\\\\"allowPublish\\\\\\\\\\\\\\\", true)\\\\\\\\n\\\\\\\\t\\\\\\\\tif err != nil {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\treturn nil, err\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\tm.SetBaseURL(admin)\\\\\\\\n\\\\\\\\t\\\\\\\\tm.SetPrefixURL(strings.TrimSuffix(caddyConf.Addr.Path, \\\\\\\\\\\\\\\"/\\\\\\\\\\\\\\\"))\\\\\\\\n\\\\\\\\t\\\\\\\\tconfigs = append(configs, m)\\\\\\\\n\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\treturn configs, nil\\\\\\\\n}\\\\\\\\n\\\\\\\\n// ServeHTTP determines if the request is for this plugin, and if all prerequisites are met.\\\\\\\\nfunc (p plugin) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {\\\\\\\\n\\\\\\\\tfor i := range p.Configs {\\\\\\\\n\\\\\\\\t\\\\\\\\t// Checks if this Path should be handled by File Manager.\\\\\\\\n\\\\\\\\t\\\\\\\\tif !httpserver.Path(r.URL.Path).Matches(p.Configs[i].BaseURL) {\\\\\\\\n\\\\\\\\t\\\\\\\\t\\\\\\\\tcontinue\\\\\\\\n\\\\\\\\t\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\t\\\\\\\\treturn p.Configs[i].ServeHTTP(w, r)\\\\\\\\n\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\treturn p.Next.ServeHTTP(w, r)\\\\\\\\n}\\\\\\\\n\\\\\\\\nfunc init() {\\\\\\\\n\\\\\\\\tcaddy.RegisterPlugin(\\\\\\\\\\\\\\\"hugo\\\\\\\\\\\\\\\", caddy.Plugin{\\\\\\\\n\\\\\\\\t\\\\\\\\tServerType: \\\\\\\\\\\\\\\"http\\\\\\\\\\\\\\\",\\\\\\\\n\\\\\\\\t\\\\\\\\tAction: setup,\\\\\\\\n\\\\\\\\t})\\\\\\\\n}\\\\\\\\n\\\\\\\\ntype plugin struct {\\\\\\\\n\\\\\\\\tNext httpserver.Handler\\\\\\\\n\\\\\\\\tConfigs []*filemanager.FileManager\\\\\\\\n}\\\\\\\\n\\\\\\\"),\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\tfile6 := &embedded.EmbeddedFile{\\\\r\\\\n\\\\t\\\\tFilename: `utils.go`,\\\\r\\\\n\\\\t\\\\tFileModTime: time.Unix(1499867704, 0),\\\\r\\\\n\\\\t\\\\tContent: string(\\\\\\\"package hugo\\\\\\\\n\\\\\\\\nimport (\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"errors\\\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\\\\\\\\"os/exec\\\\\\\\\\\\\\\"\\\\\\\\n)\\\\\\\\n\\\\\\\\n// Run executes an external command\\\\\\\\nfunc Run(command string, args []string, path string) error {\\\\\\\\n\\\\\\\\tcmd := exec.Command(command, args...)\\\\\\\\n\\\\\\\\tcmd.Dir = path\\\\\\\\n\\\\\\\\tout, err := cmd.CombinedOutput()\\\\\\\\n\\\\\\\\n\\\\\\\\tif err != nil {\\\\\\\\n\\\\\\\\t\\\\\\\\treturn errors.New(string(out))\\\\\\\\n\\\\\\\\t}\\\\\\\\n\\\\\\\\n\\\\\\\\treturn nil\\\\\\\\n}\\\\\\\\n\\\\\\\"),\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t// define dirs\\\\r\\\\n\\\\tdir1 := &embedded.EmbeddedDir{\\\\r\\\\n\\\\t\\\\tFilename: ``,\\\\r\\\\n\\\\t\\\\tDirModTime: time.Unix(1499788789, 0),\\\\r\\\\n\\\\t\\\\tChildFiles: []*embedded.EmbeddedFile{\\\\r\\\\n\\\\t\\\\t\\\\tfile2, // README.md\\\\r\\\\n\\\\t\\\\t\\\\tfile3, // hugo.go\\\\r\\\\n\\\\t\\\\t\\\\tfile4, // hugo.js\\\\r\\\\n\\\\t\\\\t\\\\tfile5, // setup.go\\\\r\\\\n\\\\t\\\\t\\\\tfile6, // utils.go\\\\r\\\\n\\\\r\\\\n\\\\t\\\\t},\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t// link ChildDirs\\\\r\\\\n\\\\tdir1.ChildDirs = []*embedded.EmbeddedDir{}\\\\r\\\\n\\\\r\\\\n\\\\t// register embeddedBox\\\\r\\\\n\\\\tembedded.RegisterEmbeddedBox(`./`, &embedded.EmbeddedBox{\\\\r\\\\n\\\\t\\\\tName: `./`,\\\\r\\\\n\\\\t\\\\tTime: time.Unix(1499788789, 0),\\\\r\\\\n\\\\t\\\\tDirs: map[string]*embedded.EmbeddedDir{\\\\r\\\\n\\\\t\\\\t\\\\t\\\\\\\"\\\\\\\": dir1,\\\\r\\\\n\\\\t\\\\t},\\\\r\\\\n\\\\t\\\\tFiles: map[string]*embedded.EmbeddedFile{\\\\r\\\\n\\\\t\\\\t\\\\t\\\\\\\"README.md\\\\\\\": file2,\\\\r\\\\n\\\\t\\\\t\\\\t\\\\\\\"hugo.go\\\\\\\": file3,\\\\r\\\\n\\\\t\\\\t\\\\t\\\\\\\"hugo.js\\\\\\\": file4,\\\\r\\\\n\\\\t\\\\t\\\\t\\\\\\\"setup.go\\\\\\\": file5,\\\\r\\\\n\\\\t\\\\t\\\\t\\\\\\\"utils.go\\\\\\\": file6,\\\\r\\\\n\\\\t\\\\t},\\\\r\\\\n\\\\t})\\\\r\\\\n}\\\\r\\\\n\\\"),\\n\\t}\\n\\tfile6 := &embedded.EmbeddedFile{\\n\\t\\tFilename: `setup.go`,\\n\\t\\tFileModTime: time.Unix(1500387945, 0),\\n\\t\\tContent: string(\\\"package hugo\\\\r\\\\n\\\\r\\\\nimport (\\\\r\\\\n\\\\t\\\\\\\"crypto/md5\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"encoding/hex\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"errors\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"fmt\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"net/http\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"os\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"os/exec\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"path/filepath\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"strings\\\\\\\"\\\\r\\\\n\\\\r\\\\n\\\\t\\\\\\\"github.com/hacdias/filemanager\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"github.com/mholt/caddy\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"github.com/mholt/caddy/caddyhttp/httpserver\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"golang.org/x/net/webdav\\\\\\\"\\\\r\\\\n)\\\\r\\\\n\\\\r\\\\nvar (\\\\r\\\\n\\\\terrHugoNotFound = errors.New(\\\\\\\"It seems that tou don't have 'hugo' on your PATH\\\\\\\")\\\\r\\\\n\\\\terrUnsupportedFileType = errors.New(\\\\\\\"The type of the provided file isn't supported for this action\\\\\\\")\\\\r\\\\n)\\\\r\\\\n\\\\r\\\\n// setup configures a new FileManager middleware instance.\\\\r\\\\nfunc setup(c *caddy.Controller) error {\\\\r\\\\n\\\\tconfigs, err := parse(c)\\\\r\\\\n\\\\tif err != nil {\\\\r\\\\n\\\\t\\\\treturn err\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\thttpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {\\\\r\\\\n\\\\t\\\\treturn plugin{Configs: configs, Next: next}\\\\r\\\\n\\\\t})\\\\r\\\\n\\\\r\\\\n\\\\treturn nil\\\\r\\\\n}\\\\r\\\\n\\\\r\\\\nfunc parse(c *caddy.Controller) ([]*filemanager.FileManager, error) {\\\\r\\\\n\\\\tvar (\\\\r\\\\n\\\\t\\\\tconfigs []*filemanager.FileManager\\\\r\\\\n\\\\t)\\\\r\\\\n\\\\r\\\\n\\\\tfor c.Next() {\\\\r\\\\n\\\\t\\\\t// hugo [directory] [admin] {\\\\r\\\\n\\\\t\\\\t// \\\\t\\\\tdatabase path\\\\r\\\\n\\\\t\\\\t// }\\\\r\\\\n\\\\t\\\\tdirectory := \\\\\\\".\\\\\\\"\\\\r\\\\n\\\\t\\\\tadmin := \\\\\\\"/admin\\\\\\\"\\\\r\\\\n\\\\t\\\\tdatabase := \\\\\\\"\\\\\\\"\\\\r\\\\n\\\\r\\\\n\\\\t\\\\t// Get the baseURL and baseScope\\\\r\\\\n\\\\t\\\\targs := c.RemainingArgs()\\\\r\\\\n\\\\r\\\\n\\\\t\\\\tif len(args) == 1 {\\\\r\\\\n\\\\t\\\\t\\\\tdirectory = args[0]\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\tif len(args) > 1 {\\\\r\\\\n\\\\t\\\\t\\\\tadmin = args[1]\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\tfor c.NextBlock() {\\\\r\\\\n\\\\t\\\\t\\\\tswitch c.Val() {\\\\r\\\\n\\\\t\\\\t\\\\tcase \\\\\\\"database\\\\\\\":\\\\r\\\\n\\\\t\\\\t\\\\t\\\\tif !c.NextArg() {\\\\r\\\\n\\\\t\\\\t\\\\t\\\\t\\\\treturn nil, c.ArgErr()\\\\r\\\\n\\\\t\\\\t\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\t\\\\t\\\\tdatabase = c.Val()\\\\r\\\\n\\\\t\\\\t\\\\t}\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\tcaddyConf := httpserver.GetConfig(c)\\\\r\\\\n\\\\r\\\\n\\\\t\\\\tpath := filepath.Join(caddy.AssetsPath(), \\\\\\\"hugo\\\\\\\")\\\\r\\\\n\\\\t\\\\terr := os.MkdirAll(path, 0700)\\\\r\\\\n\\\\t\\\\tif err != nil {\\\\r\\\\n\\\\t\\\\t\\\\treturn nil, err\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\t// if there is a database path and it is not absolute,\\\\r\\\\n\\\\t\\\\t// it will be relative to \\\\\\\".caddy\\\\\\\" folder.\\\\r\\\\n\\\\t\\\\tif !filepath.IsAbs(database) && database != \\\\\\\"\\\\\\\" {\\\\r\\\\n\\\\t\\\\t\\\\tdatabase = filepath.Join(path, database)\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\t// If there is no database path on the settings,\\\\r\\\\n\\\\t\\\\t// store one in .caddy/hugo/{name}.db.\\\\r\\\\n\\\\t\\\\tif database == \\\\\\\"\\\\\\\" {\\\\r\\\\n\\\\t\\\\t\\\\t// The name of the database is the hashed value of a string composed\\\\r\\\\n\\\\t\\\\t\\\\t// by the host, address path and the baseurl of this File Manager\\\\r\\\\n\\\\t\\\\t\\\\t// instance.\\\\r\\\\n\\\\t\\\\t\\\\thasher := md5.New()\\\\r\\\\n\\\\t\\\\t\\\\thasher.Write([]byte(caddyConf.Addr.Host + caddyConf.Addr.Path + admin))\\\\r\\\\n\\\\t\\\\t\\\\tsha := hex.EncodeToString(hasher.Sum(nil))\\\\r\\\\n\\\\t\\\\t\\\\tdatabase = filepath.Join(path, sha+\\\\\\\".db\\\\\\\")\\\\r\\\\n\\\\r\\\\n\\\\t\\\\t\\\\tfmt.Println(\\\\\\\"[WARNING] A database is going to be created for your Hugo instace at \\\\\\\" + database +\\\\r\\\\n\\\\t\\\\t\\\\t\\\\t\\\\\\\". It is highly recommended that you set the 'database' option to '\\\\\\\" + sha + \\\\\\\".db'\\\\\\\\n\\\\\\\")\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\tm, err := filemanager.New(database, filemanager.User{\\\\r\\\\n\\\\t\\\\t\\\\tUsername: \\\\\\\"admin\\\\\\\",\\\\r\\\\n\\\\t\\\\t\\\\tPassword: \\\\\\\"admin\\\\\\\",\\\\r\\\\n\\\\t\\\\t\\\\tAllowCommands: true,\\\\r\\\\n\\\\t\\\\t\\\\tAllowEdit: true,\\\\r\\\\n\\\\t\\\\t\\\\tAllowNew: true,\\\\r\\\\n\\\\t\\\\t\\\\tPermissions: map[string]bool{},\\\\r\\\\n\\\\t\\\\t\\\\tCommands: []string{\\\\\\\"git\\\\\\\", \\\\\\\"svn\\\\\\\", \\\\\\\"hg\\\\\\\"},\\\\r\\\\n\\\\t\\\\t\\\\tRules: []*filemanager.Rule{{\\\\r\\\\n\\\\t\\\\t\\\\t\\\\tRegex: true,\\\\r\\\\n\\\\t\\\\t\\\\t\\\\tAllow: false,\\\\r\\\\n\\\\t\\\\t\\\\t\\\\tRegexp: &filemanager.Regexp{Raw: \\\\\\\"\\\\\\\\\\\\\\\\/\\\\\\\\\\\\\\\\..+\\\\\\\"},\\\\r\\\\n\\\\t\\\\t\\\\t}},\\\\r\\\\n\\\\t\\\\t\\\\tCSS: \\\\\\\"\\\\\\\",\\\\r\\\\n\\\\t\\\\t\\\\tFileSystem: webdav.Dir(directory),\\\\r\\\\n\\\\t\\\\t})\\\\r\\\\n\\\\r\\\\n\\\\t\\\\tif err != nil {\\\\r\\\\n\\\\t\\\\t\\\\treturn nil, err\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\t// Initialize the default settings for Hugo.\\\\r\\\\n\\\\t\\\\thugo := &hugo{\\\\r\\\\n\\\\t\\\\t\\\\tRoot: directory,\\\\r\\\\n\\\\t\\\\t\\\\tPublic: filepath.Join(directory, \\\\\\\"public\\\\\\\"),\\\\r\\\\n\\\\t\\\\t\\\\tArgs: []string{},\\\\r\\\\n\\\\t\\\\t\\\\tCleanPublic: true,\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\t// Try to find the Hugo executable path.\\\\r\\\\n\\\\t\\\\tif hugo.Exe, err = exec.LookPath(\\\\\\\"hugo\\\\\\\"); err != nil {\\\\r\\\\n\\\\t\\\\t\\\\treturn nil, errHugoNotFound\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\terr = m.RegisterPlugin(\\\\\\\"hugo\\\\\\\", hugo)\\\\r\\\\n\\\\t\\\\tif err != nil {\\\\r\\\\n\\\\t\\\\t\\\\treturn nil, err\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\terr = m.RegisterEventType(\\\\\\\"before_publish\\\\\\\")\\\\r\\\\n\\\\t\\\\tif err != nil {\\\\r\\\\n\\\\t\\\\t\\\\treturn nil, err\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\terr = m.RegisterEventType(\\\\\\\"after_publish\\\\\\\")\\\\r\\\\n\\\\t\\\\tif err != nil {\\\\r\\\\n\\\\t\\\\t\\\\treturn nil, err\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\terr = m.RegisterPermission(\\\\\\\"allowPublish\\\\\\\", true)\\\\r\\\\n\\\\t\\\\tif err != nil {\\\\r\\\\n\\\\t\\\\t\\\\treturn nil, err\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\tm.SetBaseURL(admin)\\\\r\\\\n\\\\t\\\\tm.SetPrefixURL(strings.TrimSuffix(caddyConf.Addr.Path, \\\\\\\"/\\\\\\\"))\\\\r\\\\n\\\\t\\\\tconfigs = append(configs, m)\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\treturn configs, nil\\\\r\\\\n}\\\\r\\\\n\\\\r\\\\n// ServeHTTP determines if the request is for this plugin, and if all prerequisites are met.\\\\r\\\\nfunc (p plugin) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {\\\\r\\\\n\\\\tfor i := range p.Configs {\\\\r\\\\n\\\\t\\\\t// Checks if this Path should be handled by File Manager.\\\\r\\\\n\\\\t\\\\tif !httpserver.Path(r.URL.Path).Matches(p.Configs[i].BaseURL) {\\\\r\\\\n\\\\t\\\\t\\\\tcontinue\\\\r\\\\n\\\\t\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\t\\\\treturn p.Configs[i].ServeHTTP(w, r)\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\treturn p.Next.ServeHTTP(w, r)\\\\r\\\\n}\\\\r\\\\n\\\\r\\\\nfunc init() {\\\\r\\\\n\\\\tcaddy.RegisterPlugin(\\\\\\\"hugo\\\\\\\", caddy.Plugin{\\\\r\\\\n\\\\t\\\\tServerType: \\\\\\\"http\\\\\\\",\\\\r\\\\n\\\\t\\\\tAction: setup,\\\\r\\\\n\\\\t})\\\\r\\\\n}\\\\r\\\\n\\\\r\\\\ntype plugin struct {\\\\r\\\\n\\\\tNext httpserver.Handler\\\\r\\\\n\\\\tConfigs []*filemanager.FileManager\\\\r\\\\n}\\\\r\\\\n\\\"),\\n\\t}\\n\\tfile7 := &embedded.EmbeddedFile{\\n\\t\\tFilename: `utils.go`,\\n\\t\\tFileModTime: time.Unix(1500387945, 0),\\n\\t\\tContent: string(\\\"package hugo\\\\r\\\\n\\\\r\\\\nimport (\\\\r\\\\n\\\\t\\\\\\\"errors\\\\\\\"\\\\r\\\\n\\\\t\\\\\\\"os/exec\\\\\\\"\\\\r\\\\n)\\\\r\\\\n\\\\r\\\\n// Run executes an external command\\\\r\\\\nfunc Run(command string, args []string, path string) error {\\\\r\\\\n\\\\tcmd := exec.Command(command, args...)\\\\r\\\\n\\\\tcmd.Dir = path\\\\r\\\\n\\\\tout, err := cmd.CombinedOutput()\\\\r\\\\n\\\\r\\\\n\\\\tif err != nil {\\\\r\\\\n\\\\t\\\\treturn errors.New(string(out))\\\\r\\\\n\\\\t}\\\\r\\\\n\\\\r\\\\n\\\\treturn nil\\\\r\\\\n}\\\\r\\\\n\\\"),\\n\\t}\\n\\n\\t// define dirs\\n\\tdir1 := &embedded.EmbeddedDir{\\n\\t\\tFilename: ``,\\n\\t\\tDirModTime: time.Unix(1500387945, 0),\\n\\t\\tChildFiles: []*embedded.EmbeddedFile{\\n\\t\\t\\tfile2, // README.md\\n\\t\\t\\tfile3, // hugo.go\\n\\t\\t\\tfile4, // hugo.js\\n\\t\\t\\tfile5, // rice-box.go\\n\\t\\t\\tfile6, // setup.go\\n\\t\\t\\tfile7, // utils.go\\n\\n\\t\\t},\\n\\t}\\n\\n\\t// link ChildDirs\\n\\tdir1.ChildDirs = []*embedded.EmbeddedDir{}\\n\\n\\t// register embeddedBox\\n\\tembedded.RegisterEmbeddedBox(`./`, &embedded.EmbeddedBox{\\n\\t\\tName: `./`,\\n\\t\\tTime: time.Unix(1500387945, 0),\\n\\t\\tDirs: map[string]*embedded.EmbeddedDir{\\n\\t\\t\\t\\\"\\\": dir1,\\n\\t\\t},\\n\\t\\tFiles: map[string]*embedded.EmbeddedFile{\\n\\t\\t\\t\\\"README.md\\\": file2,\\n\\t\\t\\t\\\"hugo.go\\\": file3,\\n\\t\\t\\t\\\"hugo.js\\\": file4,\\n\\t\\t\\t\\\"rice-box.go\\\": file5,\\n\\t\\t\\t\\\"setup.go\\\": file6,\\n\\t\\t\\t\\\"utils.go\\\": file7,\\n\\t\\t},\\n\\t})\\n}\\n\"),\n\t}\n\tfile6 := &embedded.EmbeddedFile{\n\t\tFilename: `setup.go`,\n\t\tFileModTime: time.Unix(1500387945, 0),\n\t\tContent: string(\"package hugo\\r\\n\\r\\nimport (\\r\\n\\t\\\"crypto/md5\\\"\\r\\n\\t\\\"encoding/hex\\\"\\r\\n\\t\\\"errors\\\"\\r\\n\\t\\\"fmt\\\"\\r\\n\\t\\\"net/http\\\"\\r\\n\\t\\\"os\\\"\\r\\n\\t\\\"os/exec\\\"\\r\\n\\t\\\"path/filepath\\\"\\r\\n\\t\\\"strings\\\"\\r\\n\\r\\n\\t\\\"github.com/hacdias/filemanager\\\"\\r\\n\\t\\\"github.com/mholt/caddy\\\"\\r\\n\\t\\\"github.com/mholt/caddy/caddyhttp/httpserver\\\"\\r\\n\\t\\\"golang.org/x/net/webdav\\\"\\r\\n)\\r\\n\\r\\nvar (\\r\\n\\terrHugoNotFound = errors.New(\\\"It seems that tou don't have 'hugo' on your PATH\\\")\\r\\n\\terrUnsupportedFileType = errors.New(\\\"The type of the provided file isn't supported for this action\\\")\\r\\n)\\r\\n\\r\\n// setup configures a new FileManager middleware instance.\\r\\nfunc setup(c *caddy.Controller) error {\\r\\n\\tconfigs, err := parse(c)\\r\\n\\tif err != nil {\\r\\n\\t\\treturn err\\r\\n\\t}\\r\\n\\r\\n\\thttpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {\\r\\n\\t\\treturn plugin{Configs: configs, Next: next}\\r\\n\\t})\\r\\n\\r\\n\\treturn nil\\r\\n}\\r\\n\\r\\nfunc parse(c *caddy.Controller) ([]*filemanager.FileManager, error) {\\r\\n\\tvar (\\r\\n\\t\\tconfigs []*filemanager.FileManager\\r\\n\\t)\\r\\n\\r\\n\\tfor c.Next() {\\r\\n\\t\\t// hugo [directory] [admin] {\\r\\n\\t\\t// \\t\\tdatabase path\\r\\n\\t\\t// }\\r\\n\\t\\tdirectory := \\\".\\\"\\r\\n\\t\\tadmin := \\\"/admin\\\"\\r\\n\\t\\tdatabase := \\\"\\\"\\r\\n\\r\\n\\t\\t// Get the baseURL and baseScope\\r\\n\\t\\targs := c.RemainingArgs()\\r\\n\\r\\n\\t\\tif len(args) == 1 {\\r\\n\\t\\t\\tdirectory = args[0]\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tif len(args) > 1 {\\r\\n\\t\\t\\tadmin = args[1]\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tfor c.NextBlock() {\\r\\n\\t\\t\\tswitch c.Val() {\\r\\n\\t\\t\\tcase \\\"database\\\":\\r\\n\\t\\t\\t\\tif !c.NextArg() {\\r\\n\\t\\t\\t\\t\\treturn nil, c.ArgErr()\\r\\n\\t\\t\\t\\t}\\r\\n\\r\\n\\t\\t\\t\\tdatabase = c.Val()\\r\\n\\t\\t\\t}\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tcaddyConf := httpserver.GetConfig(c)\\r\\n\\r\\n\\t\\tpath := filepath.Join(caddy.AssetsPath(), \\\"hugo\\\")\\r\\n\\t\\terr := os.MkdirAll(path, 0700)\\r\\n\\t\\tif err != nil {\\r\\n\\t\\t\\treturn nil, err\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\t// if there is a database path and it is not absolute,\\r\\n\\t\\t// it will be relative to \\\".caddy\\\" folder.\\r\\n\\t\\tif !filepath.IsAbs(database) && database != \\\"\\\" {\\r\\n\\t\\t\\tdatabase = filepath.Join(path, database)\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\t// If there is no database path on the settings,\\r\\n\\t\\t// store one in .caddy/hugo/{name}.db.\\r\\n\\t\\tif database == \\\"\\\" {\\r\\n\\t\\t\\t// The name of the database is the hashed value of a string composed\\r\\n\\t\\t\\t// by the host, address path and the baseurl of this File Manager\\r\\n\\t\\t\\t// instance.\\r\\n\\t\\t\\thasher := md5.New()\\r\\n\\t\\t\\thasher.Write([]byte(caddyConf.Addr.Host + caddyConf.Addr.Path + admin))\\r\\n\\t\\t\\tsha := hex.EncodeToString(hasher.Sum(nil))\\r\\n\\t\\t\\tdatabase = filepath.Join(path, sha+\\\".db\\\")\\r\\n\\r\\n\\t\\t\\tfmt.Println(\\\"[WARNING] A database is going to be created for your Hugo instace at \\\" + database +\\r\\n\\t\\t\\t\\t\\\". It is highly recommended that you set the 'database' option to '\\\" + sha + \\\".db'\\\\n\\\")\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tm, err := filemanager.New(database, filemanager.User{\\r\\n\\t\\t\\tUsername: \\\"admin\\\",\\r\\n\\t\\t\\tPassword: \\\"admin\\\",\\r\\n\\t\\t\\tAllowCommands: true,\\r\\n\\t\\t\\tAllowEdit: true,\\r\\n\\t\\t\\tAllowNew: true,\\r\\n\\t\\t\\tPermissions: map[string]bool{},\\r\\n\\t\\t\\tCommands: []string{\\\"git\\\", \\\"svn\\\", \\\"hg\\\"},\\r\\n\\t\\t\\tRules: []*filemanager.Rule{{\\r\\n\\t\\t\\t\\tRegex: true,\\r\\n\\t\\t\\t\\tAllow: false,\\r\\n\\t\\t\\t\\tRegexp: &filemanager.Regexp{Raw: \\\"\\\\\\\\/\\\\\\\\..+\\\"},\\r\\n\\t\\t\\t}},\\r\\n\\t\\t\\tCSS: \\\"\\\",\\r\\n\\t\\t\\tFileSystem: webdav.Dir(directory),\\r\\n\\t\\t})\\r\\n\\r\\n\\t\\tif err != nil {\\r\\n\\t\\t\\treturn nil, err\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\t// Initialize the default settings for Hugo.\\r\\n\\t\\thugo := &hugo{\\r\\n\\t\\t\\tRoot: directory,\\r\\n\\t\\t\\tPublic: filepath.Join(directory, \\\"public\\\"),\\r\\n\\t\\t\\tArgs: []string{},\\r\\n\\t\\t\\tCleanPublic: true,\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\t// Try to find the Hugo executable path.\\r\\n\\t\\tif hugo.Exe, err = exec.LookPath(\\\"hugo\\\"); err != nil {\\r\\n\\t\\t\\treturn nil, errHugoNotFound\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\terr = m.RegisterPlugin(\\\"hugo\\\", hugo)\\r\\n\\t\\tif err != nil {\\r\\n\\t\\t\\treturn nil, err\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\terr = m.RegisterEventType(\\\"before_publish\\\")\\r\\n\\t\\tif err != nil {\\r\\n\\t\\t\\treturn nil, err\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\terr = m.RegisterEventType(\\\"after_publish\\\")\\r\\n\\t\\tif err != nil {\\r\\n\\t\\t\\treturn nil, err\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\terr = m.RegisterPermission(\\\"allowPublish\\\", true)\\r\\n\\t\\tif err != nil {\\r\\n\\t\\t\\treturn nil, err\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tm.SetBaseURL(admin)\\r\\n\\t\\tm.SetPrefixURL(strings.TrimSuffix(caddyConf.Addr.Path, \\\"/\\\"))\\r\\n\\t\\tconfigs = append(configs, m)\\r\\n\\t}\\r\\n\\r\\n\\treturn configs, nil\\r\\n}\\r\\n\\r\\n// ServeHTTP determines if the request is for this plugin, and if all prerequisites are met.\\r\\nfunc (p plugin) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {\\r\\n\\tfor i := range p.Configs {\\r\\n\\t\\t// Checks if this Path should be handled by File Manager.\\r\\n\\t\\tif !httpserver.Path(r.URL.Path).Matches(p.Configs[i].BaseURL) {\\r\\n\\t\\t\\tcontinue\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\treturn p.Configs[i].ServeHTTP(w, r)\\r\\n\\t}\\r\\n\\r\\n\\treturn p.Next.ServeHTTP(w, r)\\r\\n}\\r\\n\\r\\nfunc init() {\\r\\n\\tcaddy.RegisterPlugin(\\\"hugo\\\", caddy.Plugin{\\r\\n\\t\\tServerType: \\\"http\\\",\\r\\n\\t\\tAction: setup,\\r\\n\\t})\\r\\n}\\r\\n\\r\\ntype plugin struct {\\r\\n\\tNext httpserver.Handler\\r\\n\\tConfigs []*filemanager.FileManager\\r\\n}\\r\\n\"),\n\t}\n\tfile7 := &embedded.EmbeddedFile{\n\t\tFilename: `utils.go`,\n\t\tFileModTime: time.Unix(1500387945, 0),\n\t\tContent: string(\"package hugo\\r\\n\\r\\nimport (\\r\\n\\t\\\"errors\\\"\\r\\n\\t\\\"os/exec\\\"\\r\\n)\\r\\n\\r\\n// Run executes an external command\\r\\nfunc Run(command string, args []string, path string) error {\\r\\n\\tcmd := exec.Command(command, args...)\\r\\n\\tcmd.Dir = path\\r\\n\\tout, err := cmd.CombinedOutput()\\r\\n\\r\\n\\tif err != nil {\\r\\n\\t\\treturn errors.New(string(out))\\r\\n\\t}\\r\\n\\r\\n\\treturn nil\\r\\n}\\r\\n\"),\n\t}\n\n\t// define dirs\n\tdir1 := &embedded.EmbeddedDir{\n\t\tFilename: ``,\n\t\tDirModTime: time.Unix(1500387945, 0),\n\t\tChildFiles: []*embedded.EmbeddedFile{\n\t\t\tfile2, // README.md\n\t\t\tfile3, // hugo.go\n\t\t\tfile4, // hugo.js\n\t\t\tfile5, // rice-box.go\n\t\t\tfile6, // setup.go\n\t\t\tfile7, // utils.go\n\n\t\t},\n\t}\n\n\t// link ChildDirs\n\tdir1.ChildDirs = []*embedded.EmbeddedDir{}\n\n\t// register embeddedBox\n\tembedded.RegisterEmbeddedBox(`./`, &embedded.EmbeddedBox{\n\t\tName: `./`,\n\t\tTime: time.Unix(1500387945, 0),\n\t\tDirs: map[string]*embedded.EmbeddedDir{\n\t\t\t\"\": dir1,\n\t\t},\n\t\tFiles: map[string]*embedded.EmbeddedFile{\n\t\t\t\"README.md\": file2,\n\t\t\t\"hugo.go\": file3,\n\t\t\t\"hugo.js\": file4,\n\t\t\t\"rice-box.go\": file5,\n\t\t\t\"setup.go\": file6,\n\t\t\t\"utils.go\": file7,\n\t\t},\n\t})\n}\n"), } file6 := &embedded.EmbeddedFile{ Filename: `setup.go`, diff --git a/rice-box.go.REMOVED.git-id b/rice-box.go.REMOVED.git-id index 7e4ac0dc..b8db4f69 100644 --- a/rice-box.go.REMOVED.git-id +++ b/rice-box.go.REMOVED.git-id @@ -1 +1 @@ -f948f6de5b44d3495f83775a44d228f1c7f77719 \ No newline at end of file +7c28579ca6eca580689b9d8fe02b8a145a70dc24 \ No newline at end of file