diff --git a/assets/public/css/styles.css b/assets/public/css/styles.css index 7fcd44e8..8a609465 100644 --- a/assets/public/css/styles.css +++ b/assets/public/css/styles.css @@ -113,8 +113,8 @@ button, html [type="button"], [type="reset"], [type="submit"] { border: none; border-radius: 2px; display: inline-block; - height: 36px; - line-height: 36px; + height: 2.25em; + line-height: 2.25em; outline: 0; padding: 0 2rem; text-transform: uppercase; @@ -504,6 +504,23 @@ header form input { -webkit-box-flex: 1; -ms-flex-positive: 1; flex-grow: 1; + position: relative; +} +#listing .item .checkbox { + +position: absolute; + +top: 0; + +right: 0; + +border-radius: 50%; + +background: #000; + +border: 0; + +-webkit-appearance: initial; } .item:hover { box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24) !important; @@ -640,3 +657,15 @@ i.spin { #editor fieldset fieldset { margin-left: 1em; } +#editor #submit span { + vertical-align: middle; + transition: 0.2s ease-in-out all; +} +#editor #submit span i { + +vertical-align: sub; + +font-size: 1.3rem; + +margin-right: .2em; +} diff --git a/assets/public/js/application.js b/assets/public/js/application.js index 555dba61..9e0a2d78 100644 --- a/assets/public/js/application.js +++ b/assets/public/js/application.js @@ -455,6 +455,7 @@ var textareaAutoGrow = function() { var handleEditorPage = function () { let container = document.getElementById('editor'); + let button = document.querySelector('#submit span:first-child'); let kind = container.dataset.kind; if (kind != 'frontmatter-only') { @@ -482,9 +483,28 @@ var handleEditorPage = function () { button.addEventListener('click', deleteFrontMatterItem); }); + let addFrontMatterItemButtons = document.getElementsByClassName('add'); + Array.from(addFrontMatterItemButtons).forEach(button => { + button.addEventListener('click', addFrontMatterItem); + }); + document.querySelector('form').addEventListener('submit', (event) => { + event.preventDefault(); - return false; + let data = form2js(document.querySelector('form')); + let html = button.changeToLoading(); + let request = new XMLHttpRequest(); + request.open("PUT", window.location); + request.setRequestHeader('Kind', kind); + request.send(JSON.stringify(data)); + request.onreadystatechange = function() { + if (request.readyState == 4) { + button.changeToDone((request.status != 200), html); + } + } + }); + + return false; } var deleteFrontMatterItem = function(event) { @@ -492,30 +512,42 @@ var deleteFrontMatterItem = function(event) { document.getElementById(this.dataset.delete).remove(); } +const tempID = "_fm_internal_temporary_id" + var addFrontMatterItem = function(event) { - /* event.preventDefault(); - defaultID = "lorem-ipsum-sin-dolor-amet"; - // Remove if there is an incomplete new item - newItem = $("#" + defaultID); - if (newItem.length) { - newItem.remove(); + let newItem = document.getElementById(tempID) + if (newItem) { + newItem.remove(); } - block = $(this).parent().parent(); - blockType = block.data("type"); - blockID = block.attr("id"); + let block = this.parentNode; + let type = block.dataset.type; + let id = block.id; - // If the Block Type is an array - if (blockType == "array") { - newID = blockID + "[]"; - input = blockID; - input = input.replace(/\[/, '\\['); - input = input.replace(/\]/, '\\]'); - block.append('
'); + // If the block is an array + if (type === "array") { + let fieldID = id + "[]" + let input = fieldID + let count = block.querySelectorAll('.group > div').length + input = input.replace(/\[/, '\\['); + input = input.replace(/\]/, '\\]'); + + block.querySelector('.group').insertAdjacentHTML('beforeend', `
+ +
+ close +
+
`); } + + + + /* + + // Main add button, after all blocks if (block.is('div') && block.hasClass("frontmatter")) { block = $('.blocks'); @@ -608,4 +640,6 @@ var addFrontMatterItem = function(event) { return false; */ + + return false; } diff --git a/assets/public/js/form-to-json.js b/assets/public/js/form-to-json.js index 778cf848..4968ad94 100644 --- a/assets/public/js/form-to-json.js +++ b/assets/public/js/form-to-json.js @@ -1,141 +1,349 @@ /** -Author: Jhan Mateo -Date Started: 7/29/2015 -Date Ended: 7/30/2015 -Description: Using native javascript (no js framework), this application will serializes from form data to Json format. -The MIT License (MIT) + * Copyright (c) 2010 Maxim Vasiliev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author Maxim Vasiliev + * Date: 09.09.2010 + * Time: 19:02:33 + */ -Copyright (c) 2015 Jhan Mateo -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following conditions: +(function (root, factory) +{ + if (typeof exports !== 'undefined' && typeof module !== 'undefined' && module.exports) { + // NodeJS + module.exports = factory(); + } + else if (typeof define === 'function' && define.amd) + { + // AMD. Register as an anonymous module. + define(factory); + } + else + { + // Browser globals + root.form2js = factory(); + } +}(this, function () +{ + "use strict"; -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. -**/ + /** + * Returns form values represented as Javascript object + * "name" attribute defines structure of resulting object + * + * @param rootNode {Element|String} root form element (or it's id) or array of root elements + * @param delimiter {String} structure parts delimiter defaults to '.' + * @param skipEmpty {Boolean} should skip empty text values, defaults to true + * @param nodeCallback {Function} custom function to get node value + * @param useIdIfEmptyName {Boolean} if true value of id attribute of field will be used if name of field is empty + */ + function form2js(rootNode, delimiter, skipEmpty, nodeCallback, useIdIfEmptyName, getDisabled) + { + getDisabled = getDisabled ? true : false; + if (typeof skipEmpty == 'undefined' || skipEmpty == null) skipEmpty = true; + if (typeof delimiter == 'undefined' || delimiter == null) delimiter = '.'; + if (arguments.length < 5) useIdIfEmptyName = false; -'use strict'; + rootNode = typeof rootNode == 'string' ? document.getElementById(rootNode) : rootNode; -function formToJson(form){ + var formValues = [], + currNode, + i = 0; - if('form'!==form.nodeName.toLowerCase() && 1!==form.nodeType){ - console.log('Form error'); - return false; + /* If rootNode is array - combine values */ + if (rootNode.constructor == Array || (typeof NodeList != "undefined" && rootNode.constructor == NodeList)) + { + while(currNode = rootNode[i++]) + { + formValues = formValues.concat(getFormValues(currNode, nodeCallback, useIdIfEmptyName, getDisabled)); + } + } + else + { + formValues = getFormValues(rootNode, nodeCallback, useIdIfEmptyName, getDisabled); + } + + return processNameValues(formValues, skipEmpty, delimiter); } - var json_data = {}, new_arr_obj=null, index=null, key=null, input_name=null, new_obj=null; + /** + * Processes collection of { name: 'name', value: 'value' } objects. + * @param nameValues + * @param skipEmpty if true skips elements with value == '' or value == null + * @param delimiter + */ + function processNameValues(nameValues, skipEmpty, delimiter) + { + var result = {}, + arrays = {}, + i, j, k, l, + value, + nameParts, + currResult, + arrNameFull, + arrName, + arrIdx, + namePart, + name, + _nameParts; - for(var i=0,n=form.length; i0) || - (form[i].type==='range' && form[i].value.length>0) || - (form[i].type==='select-one' && form[i].options[form[i].selectedIndex].value.length>0) || - (form[i].type==='select-multiple' && form[i].selectedOptions.length>0) || - (form[i].type==='textarea' && form[i].value.length>0) || - (form[i].type==='number' && form[i].value.length>0) || - (form[i].type==='date' && form[i].value.length>0) || - (form[i].type==='color' && form[i].value.length>0) || - (form[i].type==='month' && form[i].value.length>0) || - (form[i].type==='week' && form[i].value.length>0) || - (form[i].type==='time' && form[i].value.length>0) || - (form[i].type==='datetime' && form[i].value.length>0) || - (form[i].type==='datetime-local' && form[i].value.length>0) || - (form[i].type==='email' && form[i].value.length>0) || - (form[i].type==='search' && form[i].value.length>0) || - (form[i].type==='tel' && form[i].value.length>0) || - (form[i].type==='url' && form[i].value.length>0) || - (form[i].type==='image' && form[i].value.length>0) || - (form[i].type==='file' && form[i].value.length>0) - ){ + name = nameValues[i].name; + _nameParts = name.split(delimiter); + nameParts = []; + currResult = result; + arrNameFull = ''; - /*get the name of the current input*/ - input_name = form[i].name; - - /*array/object*/ - if(input_name.match(/\[.*\]/g)){ - - if(input_name.match(/\[.+\]/g)){ - - /*array object, Object[][name]*/ - if(input_name.match(/\[.+\]/g)[0].match(/\[[0-9]\]/)!==null){ - - new_arr_obj = input_name.replace(/\[.+\]/g,''); //get object name - index = input_name.match(/[0-9]/g)[0]; //get index group - key = input_name.match(/\[.+\]/g)[0].replace(/(\[|\]|[0-9])/g,''); - - /*create an array in an object*/ - if(typeof json_data[new_arr_obj]==='undefined'){ - json_data[new_arr_obj] = []; - } - - /*create an object inside array*/ - if(typeof json_data[new_arr_obj][index]==='undefined'){ - json_data[new_arr_obj][index] = {}; - } - - json_data[new_arr_obj][index][key] = form[i].value; - - }else if(input_name.match(/\[.+\]/g)!==null){ - //to object - //Object[name] - - /*get object name*/ - new_obj = input_name.replace(/\[.+\]/g,''); - - /*set new object*/ - if(typeof json_data[new_obj]==='undefined'){ - json_data[new_obj] = {}; - } - /*assign a key name*/ - key = input_name.match(/\[.+\]/g)[0].replace(/(\[|\])/g,''); - - /*set key and form value*/ - json_data[new_obj][key] = form[i].value; - }else{} - }else{ - - /*to array, Object[]*/ - key = input_name.replace(/\[.*\]/g, ''); - - if(form[i].type==='select-multiple'){ - for(var j=0, m=form[i].selectedOptions.length; j0){ - if(typeof json_data[key]==='undefined'){ - json_data[key] = []; - } - json_data[key].push(form[i].selectedOptions[j].value); - } - } - - }else{ - if(typeof json_data[key]==='undefined'){ - json_data[key] = []; - } - json_data[key].push(form[i].value); + for(j = 0; j < _nameParts.length; j++) + { + namePart = _nameParts[j].split(']['); + if (namePart.length > 1) + { + for(k = 0; k < namePart.length; k++) + { + if (k == 0) + { + namePart[k] = namePart[k] + ']'; + } + else if (k == namePart.length - 1) + { + namePart[k] = '[' + namePart[k]; + } + else + { + namePart[k] = '[' + namePart[k] + ']'; } + arrIdx = namePart[k].match(/([a-z_]+)?\[([a-z_][a-z0-9_]+?)\]/i); + if (arrIdx) + { + for(l = 1; l < arrIdx.length; l++) + { + if (arrIdx[l]) nameParts.push(arrIdx[l]); + } + } + else{ + nameParts.push(namePart[k]); + } } - }else{ - /*basic info*/ - key = form[i].name.replace(/\[.*\]/g, ''); - json_data[key] = form[i].value; + } + else + nameParts = nameParts.concat(namePart); + } + for (j = 0; j < nameParts.length; j++) + { + namePart = nameParts[j]; + + if (namePart.indexOf('[]') > -1 && j == nameParts.length - 1) + { + arrName = namePart.substr(0, namePart.indexOf('[')); + arrNameFull += arrName; + + if (!currResult[arrName]) currResult[arrName] = []; + currResult[arrName].push(value); + } + else if (namePart.indexOf('[') > -1) + { + arrName = namePart.substr(0, namePart.indexOf('[')); + arrIdx = namePart.replace(/(^([a-z_]+)?\[)|(\]$)/gi, ''); + + /* Unique array name */ + arrNameFull += '_' + arrName + '_' + arrIdx; + + /* + * Because arrIdx in field name can be not zero-based and step can be + * other than 1, we can't use them in target array directly. + * Instead we're making a hash where key is arrIdx and value is a reference to + * added array element + */ + + if (!arrays[arrNameFull]) arrays[arrNameFull] = {}; + if (arrName != '' && !currResult[arrName]) currResult[arrName] = []; + + if (j == nameParts.length - 1) + { + if (arrName == '') + { + currResult.push(value); + arrays[arrNameFull][arrIdx] = currResult[currResult.length - 1]; + } + else + { + currResult[arrName].push(value); + arrays[arrNameFull][arrIdx] = currResult[arrName][currResult[arrName].length - 1]; + } + } + else + { + if (!arrays[arrNameFull][arrIdx]) + { + if ((/^[0-9a-z_]+\[?/i).test(nameParts[j+1])) currResult[arrName].push({}); + else currResult[arrName].push([]); + + arrays[arrNameFull][arrIdx] = currResult[arrName][currResult[arrName].length - 1]; + } + } + + currResult = arrays[arrNameFull][arrIdx]; + } + else + { + arrNameFull += namePart; + + if (j < nameParts.length - 1) /* Not the last part of name - means object */ + { + if (!currResult[namePart]) currResult[namePart] = {}; + currResult = currResult[namePart]; + } + else + { + currResult[namePart] = value; + } } } } - }//endfor - document.getElementById('json_result').innerHTML = JSON.stringify(json_data); - console.log("Result: ",json_data); - return false; -}//endfunc + return result; + } + + function getFormValues(rootNode, nodeCallback, useIdIfEmptyName, getDisabled) + { + var result = extractNodeValues(rootNode, nodeCallback, useIdIfEmptyName, getDisabled); + return result.length > 0 ? result : getSubFormValues(rootNode, nodeCallback, useIdIfEmptyName, getDisabled); + } + + function getSubFormValues(rootNode, nodeCallback, useIdIfEmptyName, getDisabled) + { + var result = [], + currentNode = rootNode.firstChild; + + while (currentNode) + { + result = result.concat(extractNodeValues(currentNode, nodeCallback, useIdIfEmptyName, getDisabled)); + currentNode = currentNode.nextSibling; + } + + return result; + } + + function extractNodeValues(node, nodeCallback, useIdIfEmptyName, getDisabled) { + if (node.disabled && !getDisabled) return []; + + var callbackResult, fieldValue, result, fieldName = getFieldName(node, useIdIfEmptyName); + + callbackResult = nodeCallback && nodeCallback(node); + + if (callbackResult && callbackResult.name) { + result = [callbackResult]; + } + else if (fieldName != '' && node.nodeName.match(/INPUT|TEXTAREA/i)) { + fieldValue = getFieldValue(node, getDisabled); + if (null === fieldValue) { + result = []; + } else { + result = [ { name: fieldName, value: fieldValue} ]; + } + } + else if (fieldName != '' && node.nodeName.match(/SELECT/i)) { + fieldValue = getFieldValue(node, getDisabled); + result = [ { name: fieldName.replace(/\[\]$/, ''), value: fieldValue } ]; + } + else { + result = getSubFormValues(node, nodeCallback, useIdIfEmptyName, getDisabled); + } + + return result; + } + + function getFieldName(node, useIdIfEmptyName) + { + if (node.name && node.name != '') return node.name; + else if (useIdIfEmptyName && node.id && node.id != '') return node.id; + else return ''; + } + + + function getFieldValue(fieldNode, getDisabled) + { + if (fieldNode.disabled && !getDisabled) return null; + + switch (fieldNode.nodeName) { + case 'INPUT': + case 'TEXTAREA': + switch (fieldNode.type.toLowerCase()) { + case 'radio': + if (fieldNode.checked && fieldNode.value === "false") return false; + case 'checkbox': + if (fieldNode.checked && fieldNode.value === "true") return true; + if (!fieldNode.checked && fieldNode.value === "true") return false; + if (fieldNode.checked) return fieldNode.value; + break; + + case 'button': + case 'reset': + case 'submit': + case 'image': + return ''; + break; + + default: + return fieldNode.value; + break; + } + break; + + case 'SELECT': + return getSelectedOptionValue(fieldNode); + break; + + default: + break; + } + + return null; + } + + function getSelectedOptionValue(selectNode) + { + var multiple = selectNode.multiple, + result = [], + options, + i, l; + + if (!multiple) return selectNode.value; + + for (options = selectNode.getElementsByTagName("option"), i = 0, l = options.length; i < l; i++) + { + if (options[i].selected) result.push(options[i].value); + } + + return result; + } + + return form2js; + +})); diff --git a/assets/templates/base.tmpl b/assets/templates/base.tmpl index a428f6fc..f2f3656c 100644 --- a/assets/templates/base.tmpl +++ b/assets/templates/base.tmpl @@ -7,6 +7,7 @@ + {{ if ne .Config.StyleSheet "" }}{{ end }} diff --git a/assets/templates/editor.tmpl b/assets/templates/editor.tmpl index dc3fdaf6..512f6767 100644 --- a/assets/templates/editor.tmpl +++ b/assets/templates/editor.tmpl @@ -2,7 +2,7 @@
{{ if or (eq .Class "frontmatter-only") (eq .Class "complete") }} -
+
{{ template "blocks" .FrontMatter }}
@@ -18,7 +18,8 @@ {{ end }}
- +
diff --git a/assets/templates/frontmatter.tmpl b/assets/templates/frontmatter.tmpl index d8af3c50..8d01d6dc 100644 --- a/assets/templates/frontmatter.tmpl +++ b/assets/templates/frontmatter.tmpl @@ -28,30 +28,22 @@ {{ template "fielset" $value }} {{ end }} - - - - {{ end }} {{ define "value" }} {{ if eq .HTMLType "textarea" }} - + {{ else if eq .HTMLType "datetime" }} - + {{ else }} - + {{ end }} {{ end }} {{ define "fielset" }}
-

{{ SplitCapitalize .Title }}

+ {{ if not (eq .Title "") }}

{{ SplitCapitalize .Title }}

{{ end }}
add
diff --git a/assets/templates/listing.tmpl b/assets/templates/listing.tmpl index c2c3ab0b..e6f20c8a 100644 --- a/assets/templates/listing.tmpl +++ b/assets/templates/listing.tmpl @@ -25,6 +25,7 @@

+ {{- end}} diff --git a/internal/assets/binary.go b/internal/assets/binary.go index 0d330776..9f7714d0 100644 --- a/internal/assets/binary.go +++ b/internal/assets/binary.go @@ -2,6 +2,7 @@ // sources: // assets/public/css/styles.css // assets/public/js/application.js +// assets/public/js/form-to-json.js // assets/templates/actions.tmpl // assets/templates/base.tmpl // assets/templates/editor.tmpl @@ -70,6 +71,24 @@ func publicJsApplicationJs() (*asset, error) { return a, err } +// publicJsFormToJsonJs reads file data from disk. It returns an error on failure. +func publicJsFormToJsonJs() (*asset, error) { + path := "D:\\Code\\Go\\src\\github.com\\hacdias\\caddy-filemanager\\assets\\public\\js\\form-to-json.js" + name := "public/js/form-to-json.js" + bytes, err := bindataRead(path, name) + if err != nil { + return nil, err + } + + fi, err := os.Stat(path) + if err != nil { + err = fmt.Errorf("Error reading asset info %s at %s: %v", name, path, err) + } + + a := &asset{bytes: bytes, info: fi} + return a, err +} + // templatesActionsTmpl reads file data from disk. It returns an error on failure. func templatesActionsTmpl() (*asset, error) { path := "D:\\Code\\Go\\src\\github.com\\hacdias\\caddy-filemanager\\assets\\templates\\actions.tmpl" @@ -232,6 +251,7 @@ func AssetNames() []string { var _bindata = map[string]func() (*asset, error){ "public/css/styles.css": publicCssStylesCss, "public/js/application.js": publicJsApplicationJs, + "public/js/form-to-json.js": publicJsFormToJsonJs, "templates/actions.tmpl": templatesActionsTmpl, "templates/base.tmpl": templatesBaseTmpl, "templates/editor.tmpl": templatesEditorTmpl, @@ -286,6 +306,7 @@ var _bintree = &bintree{nil, map[string]*bintree{ }}, "js": &bintree{nil, map[string]*bintree{ "application.js": &bintree{publicJsApplicationJs, map[string]*bintree{}}, + "form-to-json.js": &bintree{publicJsFormToJsonJs, map[string]*bintree{}}, }}, }}, "templates": &bintree{nil, map[string]*bintree{ diff --git a/internal/file/editor.go b/internal/file/editor.go index 8ddb3c9b..89150d20 100644 --- a/internal/file/editor.go +++ b/internal/file/editor.go @@ -78,7 +78,6 @@ func (i *Info) GetEditor() (*Editor, error) { editor.Class = "content-only" editor.Content = i.Content } - return editor, nil } diff --git a/internal/file/frontmatter.go b/internal/file/frontmatter.go index aeedeba4..77f24248 100644 --- a/internal/file/frontmatter.go +++ b/internal/file/frontmatter.go @@ -146,7 +146,7 @@ func handleObjects(content interface{}, parent *Block, name string) *Block { } else if parent.Type == arrayType { c.Name = parent.Name + "[]" } else { - c.Name = parent.Name + "[" + c.Title + "]" + c.Name = parent.Name + "." + c.Title } c.Content = rawToPretty(content, c) @@ -162,7 +162,7 @@ func handleArrays(content interface{}, parent *Block, name string) *Block { if parent.Name == mainName { c.Name = name } else { - c.Name = parent.Name + "[" + name + "]" + c.Name = parent.Name + "." + name } c.Content = rawToPretty(content, c) @@ -199,7 +199,7 @@ func handleFlatValues(content interface{}, parent *Block, name string) *Block { c.Title = content.(string) } else if parent.Type == objectType { c.Title = name - c.Name = parent.Name + "[" + name + "]" + c.Name = parent.Name + "." + name if parent.Name == mainName { c.Name = name diff --git a/internal/file/update.go b/internal/file/update.go index e30e548b..fe473488 100644 --- a/internal/file/update.go +++ b/internal/file/update.go @@ -1,68 +1,134 @@ package file import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io/ioutil" "net/http" + "path/filepath" + "strings" "github.com/hacdias/caddy-filemanager/internal/config" + "github.com/spf13/hugo/parser" ) -// Update is +// Update is used to update a file that was edited func (i *Info) Update(w http.ResponseWriter, r *http.Request, c *config.Config) (int, error) { + var data map[string]interface{} + kind := r.Header.Get("kind") - /* - // POST handles the POST method on editor page - func POST(w http.ResponseWriter, r *http.Request, c *config.Config, filename string) (int, error) { - var data info + // TODO: remove + fmt.Println(i.Name) - // Get the JSON information sent using a buffer - rawBuffer := new(bytes.Buffer) - rawBuffer.ReadFrom(r.Body) - err := json.Unmarshal(rawBuffer.Bytes(), &data) + if kind == "" { + return http.StatusBadRequest, nil + } - fmt.Println(string(rawBuffer.Bytes())) + // Get the JSON information + rawBuffer := new(bytes.Buffer) + rawBuffer.ReadFrom(r.Body) + err := json.Unmarshal(rawBuffer.Bytes(), &data) - if err != nil { - return server.RespondJSON(w, &response{"Error decrypting json."}, http.StatusInternalServerError, err) - } + if err != nil { + return http.StatusInternalServerError, err + } - // Initializes the file content to write - var file []byte - var code int + var file []byte + var code int - switch data.ContentType { - case "frontmatter-only": - file, code, err = parseFrontMatterOnlyFile(data, filename) - if err != nil { - return server.RespondJSON(w, &response{err.Error()}, code, err) - } - case "content-only": - // The main content of the file - mainContent := data.Content["content"].(string) - mainContent = strings.TrimSpace(mainContent) + switch kind { + case "frontmatter-only": + if file, code, err = parseFrontMatterOnlyFile(data, i.Name); err != nil { + return http.StatusInternalServerError, err + } + case "content-only": + mainContent := data["content"].(string) + mainContent = strings.TrimSpace(mainContent) + file = []byte(mainContent) + case "complete": + if file, code, err = parseCompleteFile(data, i.Name); err != nil { + return http.StatusInternalServerError, err + } + default: + return http.StatusBadRequest, nil + } - file = []byte(mainContent) - case "complete": - file, code, err = parseCompleteFile(data, filename, c) - if err != nil { - return server.RespondJSON(w, &response{err.Error()}, code, err) - } - default: - return server.RespondJSON(w, &response{"Invalid content type."}, http.StatusBadRequest, nil) - } + // Write the file + err = ioutil.WriteFile(i.Path, file, 0666) - // Write the file - err = ioutil.WriteFile(filename, file, 0666) + if err != nil { + return http.StatusInternalServerError, err + } - if err != nil { - return server.RespondJSON(w, &response{err.Error()}, http.StatusInternalServerError, err) - } - - if data.Regenerate { - go hugo.Run(c, false) - } - - return server.RespondJSON(w, nil, http.StatusOK, nil) - } - */ - return 0, nil + return code, nil +} + +func parseFrontMatterOnlyFile(data interface{}, filename string) ([]byte, int, error) { + frontmatter := strings.TrimPrefix(filepath.Ext(filename), ".") + var mark rune + + switch frontmatter { + case "toml": + mark = rune('+') + case "json": + mark = rune('{') + case "yaml": + mark = rune('-') + default: + return []byte{}, http.StatusBadRequest, errors.New("Can't define the frontmatter.") + } + + f, err := parser.InterfaceToFrontMatter(data, mark) + fString := string(f) + + // If it's toml or yaml, strip frontmatter identifier + if frontmatter == "toml" { + fString = strings.TrimSuffix(fString, "+++\n") + fString = strings.TrimPrefix(fString, "+++\n") + } + + if frontmatter == "yaml" { + fString = strings.TrimSuffix(fString, "---\n") + fString = strings.TrimPrefix(fString, "---\n") + } + + f = []byte(fString) + + if err != nil { + return []byte{}, http.StatusInternalServerError, err + } + + return f, http.StatusOK, nil +} + +func parseCompleteFile(data map[string]interface{}, filename string) ([]byte, int, error) { + // The main content of the file + mainContent := data["content"].(string) + mainContent = "\n\n" + strings.TrimSpace(mainContent) + "\n" + + // Removes the main content from the rest of the frontmatter + delete(data, "content") + + if _, ok := data["date"]; ok { + data["date"] = data["date"].(string) + ":00" + } + + // Converts the frontmatter in JSON + jsonFrontmatter, err := json.Marshal(data) + + if err != nil { + return []byte{}, http.StatusInternalServerError, err + } + + // Indents the json + frontMatterBuffer := new(bytes.Buffer) + json.Indent(frontMatterBuffer, jsonFrontmatter, "", " ") + + // Generates the final file + f := new(bytes.Buffer) + f.Write(frontMatterBuffer.Bytes()) + f.Write([]byte(mainContent)) + return f.Bytes(), http.StatusOK, nil } diff --git a/utils/_unused/hugo/hugo.go b/utils/_unused/hugo/hugo.go index 69d210e9..acd2978c 100644 --- a/utils/_unused/hugo/hugo.go +++ b/utils/_unused/hugo/hugo.go @@ -27,12 +27,3 @@ func Run(c *config.Config.Config, force bool) { log.Panic(err) } } - -func stringInSlice(a string, list []string) (bool, int) { - for i, b := range list { - if b == a { - return true, i - } - } - return false, 0 -} diff --git a/utils/variables/variables.go b/utils/variables/variables.go index 9d60dabf..7a0168b4 100644 --- a/utils/variables/variables.go +++ b/utils/variables/variables.go @@ -35,3 +35,13 @@ func Dict(values ...interface{}) (map[string]interface{}, error) { return dict, nil } + +// StringInSlice checks if a slice contains a string +func StringInSlice(a string, list []string) (bool, int) { + for i, b := range list { + if b == a { + return true, i + } + } + return false, 0 +}