mirror of
https://github.com/gohugoio/hugo.git
synced 2025-04-20 16:33:32 +00:00
command: Remove undraft command
According to @bep, it is easier to undraft content by editing manually the frontmatter of said content by setting the draft flag to `false`, or removing it completely, than to rely on the undraft command which is a source of many bugs. Fixes #4353
This commit is contained in:
parent
b6f3f087aa
commit
2fa70c9344
7 changed files with 2 additions and 296 deletions
|
@ -208,7 +208,6 @@ func AddCommands() {
|
||||||
HugoCmd.AddCommand(convertCmd)
|
HugoCmd.AddCommand(convertCmd)
|
||||||
HugoCmd.AddCommand(newCmd)
|
HugoCmd.AddCommand(newCmd)
|
||||||
HugoCmd.AddCommand(listCmd)
|
HugoCmd.AddCommand(listCmd)
|
||||||
HugoCmd.AddCommand(undraftCmd)
|
|
||||||
HugoCmd.AddCommand(importCmd)
|
HugoCmd.AddCommand(importCmd)
|
||||||
|
|
||||||
HugoCmd.AddCommand(genCmd)
|
HugoCmd.AddCommand(genCmd)
|
||||||
|
|
|
@ -1,157 +0,0 @@
|
||||||
// Copyright 2015 The Hugo Authors. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache 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://www.apache.org/licenses/LICENSE-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"
|
|
||||||
"errors"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/parser"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
var undraftCmd = &cobra.Command{
|
|
||||||
Use: "undraft path/to/content",
|
|
||||||
Short: "Undraft resets the content's draft status",
|
|
||||||
Long: `Undraft resets the content's draft status
|
|
||||||
and updates the date to the current date and time.
|
|
||||||
If the content's draft status is 'False', nothing is done.`,
|
|
||||||
RunE: Undraft,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Undraft 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) error {
|
|
||||||
c, err := InitializeConfig(false, nil)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(args) < 1 {
|
|
||||||
return newUserError("a piece of content needs to be specified")
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := c.DepsCfg
|
|
||||||
|
|
||||||
location := args[0]
|
|
||||||
// open the file
|
|
||||||
f, err := cfg.Fs.Source.Open(location)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the page from file
|
|
||||||
p, err := parser.ReadFrom(f)
|
|
||||||
f.Close()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
w, err := undraftContent(p)
|
|
||||||
if err != nil {
|
|
||||||
return newSystemErrorF("an error occurred while undrafting %q: %s", location, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err = cfg.Fs.Source.OpenFile(location, os.O_WRONLY|os.O_TRUNC, 0644)
|
|
||||||
if err != nil {
|
|
||||||
return newSystemErrorF("%q not be undrafted due to error opening file to save changes: %q\n", location, err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
_, err = w.WriteTo(f)
|
|
||||||
if err != nil {
|
|
||||||
return newSystemErrorF("%q not be undrafted due to save error: %q\n", location, err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// undraftContent: if the content is a draft, change its 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 {
|
|
||||||
return buff, errors.New("Front Matter was found, nothing was finalized")
|
|
||||||
}
|
|
||||||
|
|
||||||
var isDraft, gotDate bool
|
|
||||||
var date string
|
|
||||||
L:
|
|
||||||
for k, v := range meta {
|
|
||||||
switch k {
|
|
||||||
case "draft":
|
|
||||||
if !v.(bool) {
|
|
||||||
return buff, errors.New("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, errors.New("not a Draft: nothing was done")
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the front matter as bytes and split it into lines
|
|
||||||
var lineEnding []byte
|
|
||||||
fmLines := bytes.Split(fm, []byte("\n"))
|
|
||||||
if len(fmLines) == 1 { // if the result is only 1 element, try to split on dos line endings
|
|
||||||
fmLines = bytes.Split(fm, []byte("\r\n"))
|
|
||||||
if len(fmLines) == 1 {
|
|
||||||
return buff, errors.New("unable to split FrontMatter into lines")
|
|
||||||
}
|
|
||||||
lineEnding = append(lineEnding, []byte("\r\n")...)
|
|
||||||
} else {
|
|
||||||
lineEnding = append(lineEnding, []byte("\n")...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the front matter lines to the buffer, replacing as necessary
|
|
||||||
for _, v := range fmLines {
|
|
||||||
pos := bytes.Index(v, []byte("draft"))
|
|
||||||
if pos != -1 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
buff.Write(v)
|
|
||||||
buff.Write(lineEnding)
|
|
||||||
}
|
|
||||||
|
|
||||||
// append the actual content
|
|
||||||
buff.Write(p.Content())
|
|
||||||
|
|
||||||
return buff, nil
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
// Copyright 2015 The Hugo Authors. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache 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://www.apache.org/licenses/LICENSE-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
|
|
||||||
|
|
||||||
// TODO Support Mac Encoding (\r)
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gohugoio/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---"
|
|
||||||
yamlYesDraftFM = "---\n draft: yes\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, ""},
|
|
||||||
{yamlYesDraftFM, ""},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, test := range tests {
|
|
||||||
r := bytes.NewReader([]byte(test.fm))
|
|
||||||
p, _ := parser.ReadFrom(r)
|
|
||||||
res, err := undraftContent(p)
|
|
||||||
if test.expectedErr != "" {
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("[%d] Expected error, got none", i)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err.Error() != test.expectedErr {
|
|
||||||
t.Errorf("[%d] Expected %q, got %q", i, test.expectedErr, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
r = bytes.NewReader(res.Bytes())
|
|
||||||
p, _ = parser.ReadFrom(r)
|
|
||||||
meta, err := p.Metadata()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("[%d] unexpected error %q", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for k, v := range meta {
|
|
||||||
if k == "draft" {
|
|
||||||
if v.(bool) {
|
|
||||||
t.Errorf("[%d] Expected %q to be \"false\", got \"true\"", i, k)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if k == "date" {
|
|
||||||
if !strings.HasPrefix(v.(string), time.Now().Format("2006-01-02")) {
|
|
||||||
t.Errorf("[%d] Expected %v to start with %v", i, v.(string), time.Now().Format("2006-01-02"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -75,7 +75,6 @@ hugo [flags]
|
||||||
* [hugo list](/commands/hugo_list/) - Listing out various types of content
|
* [hugo list](/commands/hugo_list/) - Listing out various types of content
|
||||||
* [hugo new](/commands/hugo_new/) - Create new content for your site
|
* [hugo new](/commands/hugo_new/) - Create new content for your site
|
||||||
* [hugo server](/commands/hugo_server/) - A high performance webserver
|
* [hugo server](/commands/hugo_server/) - A high performance webserver
|
||||||
* [hugo undraft](/commands/hugo_undraft/) - Undraft resets the content's draft status
|
|
||||||
* [hugo version](/commands/hugo_version/) - Print the version number of Hugo
|
* [hugo version](/commands/hugo_version/) - Print the version number of Hugo
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra on 25-Jan-2018
|
###### Auto generated by spf13/cobra on 25-Jan-2018
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
---
|
|
||||||
date: 2018-01-25T10:24:52+01:00
|
|
||||||
title: "hugo undraft"
|
|
||||||
slug: hugo_undraft
|
|
||||||
url: /commands/hugo_undraft/
|
|
||||||
---
|
|
||||||
## hugo undraft
|
|
||||||
|
|
||||||
Undraft resets the content's draft status
|
|
||||||
|
|
||||||
### Synopsis
|
|
||||||
|
|
||||||
Undraft resets the content's draft status
|
|
||||||
and updates the date to the current date and time.
|
|
||||||
If the content's draft status is 'False', nothing is done.
|
|
||||||
|
|
||||||
```
|
|
||||||
hugo undraft path/to/content [flags]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Options
|
|
||||||
|
|
||||||
```
|
|
||||||
-h, --help help for undraft
|
|
||||||
```
|
|
||||||
|
|
||||||
### Options inherited from parent commands
|
|
||||||
|
|
||||||
```
|
|
||||||
--config string config file (default is path/config.yaml|json|toml)
|
|
||||||
--debug debug output
|
|
||||||
--log enable Logging
|
|
||||||
--logFile string log File path (if set, logging enabled automatically)
|
|
||||||
--quiet build in quiet mode
|
|
||||||
-v, --verbose verbose output
|
|
||||||
--verboseLog verbose logging
|
|
||||||
```
|
|
||||||
|
|
||||||
### SEE ALSO
|
|
||||||
|
|
||||||
* [hugo](/commands/hugo/) - hugo builds your site
|
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra on 25-Jan-2018
|
|
|
@ -53,7 +53,6 @@ Available Commands:
|
||||||
list Listing out various types of content
|
list Listing out various types of content
|
||||||
new Create new content for your site
|
new Create new content for your site
|
||||||
server A high performance webserver
|
server A high performance webserver
|
||||||
undraft Undraft resets the content's draft status
|
|
||||||
version Print the version number of Hugo
|
version Print the version number of Hugo
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
|
|
|
@ -75,13 +75,9 @@ hugo new about.md
|
||||||
The preceding example for the about page leverages archetypes to scaffold a new content file with preconfigured front matter. [Find out more about Hugo's archetypes](/content-management/archetypes/).
|
The preceding example for the about page leverages archetypes to scaffold a new content file with preconfigured front matter. [Find out more about Hugo's archetypes](/content-management/archetypes/).
|
||||||
{{% /note %}}
|
{{% /note %}}
|
||||||
|
|
||||||
Now you can edit `contents/about.md` in your text editor of choice, but this is not necessary for the purposes of this guide. Running the following command will build your Hugo site into the `public` directory. We have added `undraft` to ensure that the example page is no longer in draft mode:
|
Now you can edit `contents/about.md` in your text editor of choice, but this is not necessary for the purposes of this guide. Running the following command will build your Hugo site into the `public` directory.
|
||||||
|
|
||||||
{{< code file="hugo-build-undraft.sh" >}}
|
Once the website is build, it's a good idea to run the following command to start a local server and ensure you're changes have been implemented:
|
||||||
hugo undraft content/about.md
|
|
||||||
{{< /code >}}
|
|
||||||
|
|
||||||
Once the website is build, t's a good idea to run the following command to start a local server and ensure you're changes have been implemented:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
hugo server --theme=herring-cove
|
hugo server --theme=herring-cove
|
||||||
|
|
Loading…
Add table
Reference in a new issue