add undraft command

This commit is contained in:
Joel Scoble 2015-03-15 17:32:41 -05:00 committed by spf13
parent 563a6302a0
commit b4871787f0
4 changed files with 232 additions and 2 deletions

View File

@ -75,6 +75,7 @@ func AddCommands() {
HugoCmd.AddCommand(convertCmd)
HugoCmd.AddCommand(newCmd)
HugoCmd.AddCommand(listCmd)
HugoCmd.AddCommand(undraftCmd)
}
//Initializes flags

157
commands/undraft.go Normal file
View File

@ -0,0 +1,157 @@
// Copyright © 2013 Steve Francia <spf@spf13.com>.
//
// Licensed under the Simple Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://opensource.org/licenses/Simple-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package commands
import (
"bytes"
"fmt"
"os"
"time"
"github.com/spf13/cobra"
"github.com/spf13/hugo/parser"
jww "github.com/spf13/jwalterweatherman"
)
var undraftCmd = &cobra.Command{
Use: "undraft path/to/content",
Short: "Undraft changes the content's draft status from 'True' to 'False'",
Long: `Undraft changes the content's draft status from 'True' to 'False' and updates the date to the current date and time. If the content's draft status is 'False', nothing is done`,
Run: Undraft,
}
// Publish publishes the specified content by setting its draft status
// to false and setting its publish date to now. If the specified content is
// not a draft, it will log an error.
func Undraft(cmd *cobra.Command, args []string) {
InitializeConfig()
if len(args) < 1 {
cmd.Usage()
jww.FATAL.Fatalln("a piece of content needs to be specified")
}
location := args[0]
// open the file
f, err := os.Open(location)
if err != nil {
jww.ERROR.Print(err)
return
}
// get the page from file
p, err := parser.ReadFrom(f)
f.Close()
if err != nil {
jww.ERROR.Print(err)
return
}
w, err := undraftContent(p)
if err != nil {
jww.ERROR.Printf("an error occurred while undrafting %q: %s", location, err)
return
}
f, err = os.OpenFile(location, os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
jww.ERROR.Printf("%q not be undrafted due to error opening file to save changes: %q\n", location, err)
return
}
defer f.Close()
_, err = w.WriteTo(f)
if err != nil {
jww.ERROR.Printf("%q not be undrafted due to save error: %q\n", location, err)
}
return
}
// undraftContent: if the content is a draft, change it's draft status to
// 'false' and set the date to time.Now(). If the draft status is already
// 'false', don't do anything.
func undraftContent(p parser.Page) (bytes.Buffer, error) {
var buff bytes.Buffer
// get the metadata; easiest way to see if it's a draft
meta, err := p.Metadata()
if err != nil {
return buff, err
}
// since the metadata was obtainable, we can also get the key/value separator for
// Front Matter
fm := p.FrontMatter()
if fm == nil {
err := fmt.Errorf("Front Matter was found, nothing was finalized")
return buff, err
}
var isDraft, gotDate bool
var date string
L:
for k, v := range meta.(map[string]interface{}) {
switch k {
case "draft":
if !v.(bool) {
return buff, fmt.Errorf("not a Draft: nothing was done")
}
isDraft = true
if gotDate {
break L
}
case "date":
date = v.(string) // capture the value to make replacement easier
gotDate = true
if isDraft {
break L
}
}
}
// if draft wasn't found in FrontMatter, it isn't a draft.
if !isDraft {
return buff, fmt.Errorf("not a Draft: nothing was done")
}
// get the front matter as bytes and split it into lines
var lineEnding []byte
fmLines := bytes.Split(fm, parser.UnixEnding)
if len(fmLines) == 1 { // if the result is only 1 element, try to split on dos line endings
fmLines = bytes.Split(fm, parser.DosEnding)
if len(fmLines) == 1 {
return buff, fmt.Errorf("unable to split FrontMatter into lines")
}
lineEnding = append(lineEnding, parser.DosEnding...)
} else {
lineEnding = append(lineEnding, parser.UnixEnding...)
}
// Write the front matter lines to the buffer, replacing as necessary
for _, v := range fmLines {
pos := bytes.Index(v, []byte("draft"))
if pos != -1 {
v = bytes.Replace(v, []byte("true"), []byte("false"), 1)
goto write
}
pos = bytes.Index(v, []byte("date"))
if pos != -1 { // if date field wasn't found, add it
v = bytes.Replace(v, []byte(date), []byte(time.Now().Format(time.RFC3339)), 1)
}
write:
buff.Write(v)
buff.Write(lineEnding)
}
// append the actual content
buff.Write([]byte(p.Content()))
return buff, nil
}

72
commands/undraft_test.go Normal file
View File

@ -0,0 +1,72 @@
package commands
// TODO Support Mac Encoding (\r)
import (
"bytes"
"strings"
"testing"
"time"
"github.com/spf13/hugo/parser"
)
var (
jsonFM = "{\n \"date\": \"12-04-06\",\n \"title\": \"test json\"\n}"
jsonDraftFM = "{\n \"draft\": true,\n \"date\": \"12-04-06\",\n \"title\":\"test json\"\n}"
tomlFM = "+++\n date= \"12-04-06\"\n title= \"test toml\"\n+++"
tomlDraftFM = "+++\n draft= true\n date= \"12-04-06\"\n title=\"test toml\"\n+++"
yamlFM = "---\n date: \"12-04-06\"\n title: \"test yaml\"\n---"
yamlDraftFM = "---\n draft: true\n date: \"12-04-06\"\n title: \"test yaml\"\n---"
)
func TestUndraftContent(t *testing.T) {
tests := []struct {
fm string
expectedErr string
}{
{jsonFM, "not a Draft: nothing was done"},
{jsonDraftFM, ""},
{tomlFM, "not a Draft: nothing was done"},
{tomlDraftFM, ""},
{yamlFM, "not a Draft: nothing was done"},
{yamlDraftFM, ""},
}
for _, test := range tests {
r := bytes.NewReader([]byte(test.fm))
p, _ := parser.ReadFrom(r)
res, err := undraftContent(p)
if test.expectedErr != "" {
if err == nil {
t.Error("Expected error, got none")
continue
}
if err.Error() != test.expectedErr {
t.Errorf("Expected %q, got %q", test.expectedErr, err)
continue
}
} else {
r = bytes.NewReader(res.Bytes())
p, _ = parser.ReadFrom(r)
meta, err := p.Metadata()
if err != nil {
t.Errorf("unexpected error %q", err)
continue
}
for k, v := range meta.(map[string]interface{}) {
if k == "draft" {
if v.(bool) {
t.Errorf("Expected %q to be \"false\", got \"true\"", k)
continue
}
}
if k == "date" {
if !strings.HasPrefix(v.(string), time.Now().Format("2006-01-02")) {
t.Errorf("Expected %v to start with %v", v.(string), time.Now().Format("2006-01-02"))
}
}
}
}
}
}

View File

@ -30,8 +30,8 @@ var (
[]byte(JSON_LEAD),
}
unixEnding = []byte("\n")
dosEnding = []byte("\r\n")
UnixEnding = []byte("\n")
DosEnding = []byte("\r\n")
)
type FrontMatter []byte