2015-12-07 13:57:01 -05:00
// Copyright 2015 The Hugo Authors. All rights reserved.
2014-05-01 13:23:32 -04:00
//
2015-11-23 22:16:36 -05:00
// Licensed under the Apache License, Version 2.0 (the "License");
2014-05-01 13:23:32 -04:00
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
2015-11-23 22:16:36 -05:00
// http://www.apache.org/licenses/LICENSE-2.0
2014-05-01 13:23:32 -04:00
//
// 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 (
2016-11-18 16:54:57 -05:00
"errors"
2014-05-01 13:23:32 -04:00
"fmt"
2014-11-19 16:24:30 -05:00
"path/filepath"
"time"
2014-05-29 18:40:16 -04:00
"github.com/spf13/cast"
2014-05-01 13:23:32 -04:00
"github.com/spf13/cobra"
"github.com/spf13/hugo/hugolib"
"github.com/spf13/hugo/parser"
)
2015-03-06 09:58:14 -05:00
var outputDir string
var unsafe bool
2014-05-01 13:23:32 -04:00
var convertCmd = & cobra . Command {
Use : "convert" ,
2015-08-04 05:15:12 -04:00
Short : "Convert your content to different formats" ,
2015-10-12 14:47:06 -04:00
Long : ` Convert your content ( e . g . front matter ) to different formats .
2015-08-04 05:15:12 -04:00
See convert ' s subcommands toJSON , toTOML and toYAML for more information . ` ,
2015-12-02 05:42:53 -05:00
RunE : nil ,
2014-05-01 13:23:32 -04:00
}
var toJSONCmd = & cobra . Command {
Use : "toJSON" ,
Short : "Convert front matter to JSON" ,
2015-08-04 05:15:12 -04:00
Long : ` toJSON converts all front matter in the content directory
to use JSON for the front matter . ` ,
2015-12-02 05:42:53 -05:00
RunE : func ( cmd * cobra . Command , args [ ] string ) error {
2016-03-23 09:51:16 -04:00
return convertContents ( rune ( [ ] byte ( parser . JSONLead ) [ 0 ] ) )
2014-05-01 13:23:32 -04:00
} ,
}
var toTOMLCmd = & cobra . Command {
Use : "toTOML" ,
Short : "Convert front matter to TOML" ,
2015-08-04 05:15:12 -04:00
Long : ` toTOML converts all front matter in the content directory
to use TOML for the front matter . ` ,
2015-12-02 05:42:53 -05:00
RunE : func ( cmd * cobra . Command , args [ ] string ) error {
2016-03-23 09:51:16 -04:00
return convertContents ( rune ( [ ] byte ( parser . TOMLLead ) [ 0 ] ) )
2014-05-01 13:23:32 -04:00
} ,
}
var toYAMLCmd = & cobra . Command {
Use : "toYAML" ,
Short : "Convert front matter to YAML" ,
2015-08-04 05:15:12 -04:00
Long : ` toYAML converts all front matter in the content directory
to use YAML for the front matter . ` ,
2015-12-02 05:42:53 -05:00
RunE : func ( cmd * cobra . Command , args [ ] string ) error {
2016-03-23 09:51:16 -04:00
return convertContents ( rune ( [ ] byte ( parser . YAMLLead ) [ 0 ] ) )
2014-05-01 13:23:32 -04:00
} ,
}
func init ( ) {
convertCmd . AddCommand ( toJSONCmd )
convertCmd . AddCommand ( toTOMLCmd )
convertCmd . AddCommand ( toYAMLCmd )
2015-03-06 09:58:14 -05:00
convertCmd . PersistentFlags ( ) . StringVarP ( & outputDir , "output" , "o" , "" , "filesystem path to write files to" )
2016-02-05 16:58:17 -05:00
convertCmd . PersistentFlags ( ) . StringVarP ( & source , "source" , "s" , "" , "filesystem path to read files relative from" )
2015-03-06 09:58:14 -05:00
convertCmd . PersistentFlags ( ) . BoolVar ( & unsafe , "unsafe" , false , "enable less safe operations, please backup first" )
2015-12-16 01:41:10 -05:00
convertCmd . PersistentFlags ( ) . SetAnnotation ( "source" , cobra . BashCompSubdirsInDir , [ ] string { } )
2014-05-01 13:23:32 -04:00
}
2017-01-03 11:28:51 -05:00
func convertContents ( mark rune ) error {
cfg , err := InitializeConfig ( )
if err != nil {
2015-12-02 05:42:53 -05:00
return err
}
2014-05-01 13:23:32 -04:00
2017-02-04 22:20:06 -05:00
h , err := hugolib . NewHugoSites ( * cfg )
2016-09-13 03:59:18 -04:00
if err != nil {
return err
}
site := h . Sites [ 0 ]
if err = site . Initialise ( ) ; err != nil {
2014-05-01 13:23:32 -04:00
return err
}
if site . Source == nil {
2016-11-18 16:38:41 -05:00
panic ( "site.Source not set" )
2014-05-01 13:23:32 -04:00
}
if len ( site . Source . Files ( ) ) < 1 {
2016-11-18 16:54:57 -05:00
return errors . New ( "No source files found" )
2014-05-01 13:23:32 -04:00
}
2017-02-04 22:20:06 -05:00
contentDir := site . PathSpec . AbsPathify ( site . Cfg . GetString ( "contentDir" ) )
site . Log . FEEDBACK . Println ( "processing" , len ( site . Source . Files ( ) ) , "content files" )
2014-05-01 13:23:32 -04:00
for _ , file := range site . Source . Files ( ) {
2017-02-04 22:20:06 -05:00
site . Log . INFO . Println ( "Attempting to convert" , file . LogicalName ( ) )
2017-01-03 11:28:51 -05:00
page , err := site . NewPage ( file . LogicalName ( ) )
2014-05-01 13:23:32 -04:00
if err != nil {
return err
}
psr , err := parser . ReadFrom ( file . Contents )
if err != nil {
2017-02-04 22:20:06 -05:00
site . Log . ERROR . Println ( "Error processing file:" , file . Path ( ) )
2014-05-01 13:23:32 -04:00
return err
}
metadata , err := psr . Metadata ( )
if err != nil {
2017-02-04 22:20:06 -05:00
site . Log . ERROR . Println ( "Error processing file:" , file . Path ( ) )
2014-05-01 13:23:32 -04:00
return err
}
2014-05-29 18:40:16 -04:00
// better handling of dates in formats that don't have support for them
2014-08-17 23:02:52 -04:00
if mark == parser . FormatToLeadRune ( "json" ) || mark == parser . FormatToLeadRune ( "yaml" ) || mark == parser . FormatToLeadRune ( "toml" ) {
2014-05-29 18:40:16 -04:00
newmetadata := cast . ToStringMap ( metadata )
for k , v := range newmetadata {
switch vv := v . ( type ) {
case time . Time :
newmetadata [ k ] = vv . Format ( time . RFC3339 )
}
}
metadata = newmetadata
}
2016-11-06 18:10:32 -05:00
page . SetDir ( filepath . Join ( contentDir , file . Dir ( ) ) )
2014-05-01 13:23:32 -04:00
page . SetSourceContent ( psr . Content ( ) )
2016-09-13 04:49:19 -04:00
if err = page . SetSourceMetaData ( metadata , mark ) ; err != nil {
2017-02-04 22:20:06 -05:00
site . Log . ERROR . Printf ( "Failed to set source metadata for file %q: %s. For more info see For more info see https://github.com/spf13/hugo/issues/2458" , page . FullFilePath ( ) , err )
2016-09-19 04:52:07 -04:00
continue
2016-09-13 04:49:19 -04:00
}
2014-05-01 13:23:32 -04:00
2015-03-06 09:58:14 -05:00
if outputDir != "" {
2016-09-13 04:49:19 -04:00
if err = page . SaveSourceAs ( filepath . Join ( outputDir , page . FullFilePath ( ) ) ) ; err != nil {
2016-09-13 13:11:36 -04:00
return fmt . Errorf ( "Failed to save file %q: %s" , page . FullFilePath ( ) , err )
2016-09-13 04:49:19 -04:00
}
2014-05-01 13:23:32 -04:00
} else {
2015-03-06 09:58:14 -05:00
if unsafe {
2016-09-13 04:49:19 -04:00
if err = page . SaveSource ( ) ; err != nil {
2016-09-13 13:11:36 -04:00
return fmt . Errorf ( "Failed to save file %q: %s" , page . FullFilePath ( ) , err )
2016-09-13 04:49:19 -04:00
}
2014-05-01 13:23:32 -04:00
} else {
2017-02-04 22:20:06 -05:00
site . Log . FEEDBACK . Println ( "Unsafe operation not allowed, use --unsafe or set a different output path" )
2014-05-01 13:23:32 -04:00
}
}
}
2017-01-03 11:28:51 -05:00
return nil
2014-05-01 13:23:32 -04:00
}