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")) } } } } } }
func (p *Page) parse(reader io.Reader) error { psr, err := parser.ReadFrom(reader) if err != nil { return err } p.renderable = psr.IsRenderable() p.frontmatter = psr.FrontMatter() p.rawContent = psr.Content() p.lang = p.Source.File.Lang() meta, err := psr.Metadata() if meta != nil { if err != nil { jww.ERROR.Printf("Error parsing page meta data for %s", p.File.Path()) jww.ERROR.Println(err) return err } if err = p.update(meta); err != nil { return err } } return nil }
func (page *Page) parse(reader io.Reader) error { psr, err := parser.ReadFrom(reader) if err != nil { return err } page.renderable = psr.IsRenderable() page.frontmatter = psr.FrontMatter() meta, err := psr.Metadata() if meta != nil { if err != nil { jww.ERROR.Printf("Error parsing page meta data for %s", page.FileName) jww.ERROR.Println(err) return err } if err = page.update(meta); err != nil { return err } } page.rawContent = psr.Content() page.setSummary() return nil }
func (page *Page) parse(reader io.Reader) error { p, err := parser.ReadFrom(reader) if err != nil { return err } page.renderable = p.IsRenderable() front := p.FrontMatter() if len(front) != 0 { fm := page.detectFrontMatter(rune(front[0])) meta, err := fm.parse(front) if err != nil { return err } if err = page.update(meta); err != nil { return err } } page.rawContent = p.Content() page.setSummary() return nil }
func (page *Page) parse(reader io.Reader) error { p, err := parser.ReadFrom(reader) if err != nil { return err } page.renderable = p.IsRenderable() front := p.FrontMatter() if len(front) != 0 { fm := page.detectFrontMatter(rune(front[0])) meta, err := fm.parse(front) if err != nil { return err } if err = page.update(meta); err != nil { return err } } switch page.guessMarkupType() { case "md", "markdown", "mdown": page.convertMarkdown(bytes.NewReader(p.Content())) case "rst": page.convertRestructuredText(bytes.NewReader(p.Content())) case "html": fallthrough default: page.Content = template.HTML(p.Content()) } return nil }
func (p Page) contentRead(filename string) (*Content, error) { file, err := os.Open(filename) if err != nil { return nil, err } defer file.Close() parser, err := parser.ReadFrom(file) if err != nil { return nil, err } rawdata, err := parser.Metadata() if err != nil { return nil, err } metadata, err := cast.ToStringMapE(rawdata) if err != nil { return nil, err } return &Content{ Path: filename, Metadata: metadata, Body: string(parser.Content()), }, nil }
// NewContent creates a new content file in the content directory based upon the // given kind, which is used to lookup an archetype. func NewContent(fs afero.Fs, kind, name string) (err error) { jww.INFO.Println("attempting to create ", name, "of", kind) location := FindArchetype(fs, kind) var by []byte if location != "" { by, err = afero.ReadFile(fs, location) if err != nil { jww.ERROR.Println(err) } } if location == "" || err != nil { by = []byte("+++\n title = \"title\"\n draft = true \n+++\n") } psr, err := parser.ReadFrom(bytes.NewReader(by)) if err != nil { return err } metadata, err := createMetadata(psr, name) if err != nil { jww.ERROR.Printf("Error processing archetype file %s: %s\n", location, err) return err } page, err := hugolib.NewPage(name) if err != nil { return err } if err = page.SetSourceMetaData(metadata, parser.FormatToLeadRune(viper.GetString("metaDataFormat"))); err != nil { return } page.SetSourceContent(psr.Content()) if err = page.SafeSaveSourceAs(filepath.Join(viper.GetString("contentDir"), name)); err != nil { return } jww.FEEDBACK.Println(helpers.AbsPathify(filepath.Join(viper.GetString("contentDir"), name)), "created") editor := viper.GetString("newContentEditor") if editor != "" { jww.FEEDBACK.Printf("Editing %s with %q ...\n", name, editor) cmd := exec.Command(editor, helpers.AbsPathify(path.Join(viper.GetString("contentDir"), name))) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr return cmd.Run() } return nil }
func convertJekyllPost(path, relPath, targetDir string, draft bool) error { jww.TRACE.Println("Converting", path) filename := filepath.Base(path) postDate, postName, err := parseJekyllFilename(filename) if err != nil { jww.WARN.Printf("Failed to parse filename '%s': %s. Skipping.", filename, err) return nil } jww.TRACE.Println(filename, postDate, postName) targetFile := filepath.Join(targetDir, relPath) targetParentDir := filepath.Dir(targetFile) os.MkdirAll(targetParentDir, 0777) contentBytes, err := ioutil.ReadFile(path) if err != nil { jww.ERROR.Println("Read file error:", path) return err } psr, err := parser.ReadFrom(bytes.NewReader(contentBytes)) if err != nil { jww.ERROR.Println("Parse file error:", path) return err } metadata, err := psr.Metadata() if err != nil { jww.ERROR.Println("Processing file error:", path) return err } newmetadata, err := convertJekyllMetaData(metadata, postName, postDate, draft) if err != nil { jww.ERROR.Println("Convert metadata error:", path) return err } jww.TRACE.Println(newmetadata) content := convertJekyllContent(newmetadata, string(psr.Content())) page, err := hugolib.NewPage(filename) if err != nil { jww.ERROR.Println("New page error", filename) return err } page.SetDir(targetParentDir) page.SetSourceContent([]byte(content)) page.SetSourceMetaData(newmetadata, parser.FormatToLeadRune("yaml")) page.SaveSourceAs(targetFile) jww.TRACE.Println("Target file:", targetFile) return nil }
func convertContents(mark rune) (err error) { InitializeConfig() site := &hugolib.Site{} if err := site.Initialise(); err != nil { return err } if site.Source == nil { panic(fmt.Sprintf("site.Source not set")) } if len(site.Source.Files()) < 1 { return fmt.Errorf("No source files found") } jww.FEEDBACK.Println("processing", len(site.Source.Files()), "content files") for _, file := range site.Source.Files() { jww.INFO.Println("Attempting to convert", file.LogicalName) page, err := hugolib.NewPage(file.LogicalName) if err != nil { return err } psr, err := parser.ReadFrom(file.Contents) if err != nil { jww.ERROR.Println("Error processing file:", path.Join(file.Dir, file.LogicalName)) return err } metadata, err := psr.Metadata() if err != nil { jww.ERROR.Println("Error processing file:", path.Join(file.Dir, file.LogicalName)) return err } page.Dir = file.Dir page.SetSourceContent(psr.Content()) page.SetSourceMetaData(metadata, mark) if OutputDir != "" { page.SaveSourceAs(path.Join(OutputDir, page.FullFilePath())) } else { if Unsafe { page.SaveSource() } else { jww.FEEDBACK.Println("Unsafe operation not allowed, use --unsafe or set a different output path") } } } return }
// 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 }
// 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 { if err := InitializeConfig(); err != nil { return err } if len(args) < 1 { return newUserError("a piece of content needs to be specified") } location := args[0] // open the file f, err := hugofs.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 = hugofs.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 }
func getMetadata(path string) (map[string]interface{}, string, error) { contentBytes, err := ioutil.ReadFile(path) if err != nil { return nil, "", err } psr, err := parser.ReadFrom(bytes.NewReader(contentBytes)) if err != nil { return nil, "", err } m, err := psr.Metadata() if err != nil { return nil, "", err } metadata, err := cast.ToStringMapE(m) if err != nil { return nil, "", err } return metadata, string(psr.Content()), nil }
func (s *server) loadComicDetails() error { s.comicDB = make(map[string]*Comic) matches, err := filepath.Glob("./comics/*.md") if err != nil { return err } for _, match := range matches { file, err := os.Open(match) if err != nil { return err } basename := filepath.Base(match) slug := strings.TrimSuffix(basename, filepath.Ext(basename)) comic := &Comic{ Slug: slug, } page, err := parser.ReadFrom(file) if err != nil { return err } metaData, err := page.Metadata() if err != nil { return err } jsonStr, err := json.Marshal(metaData) if err != nil { return err } if err := json.Unmarshal(jsonStr, &comic); err != nil { return err } comic.Description = string(blackfriday.MarkdownCommon(page.Content())) s.comicDB[comic.Slug] = comic } return nil }
func NewContent(kind, name string) (err error) { jww.INFO.Println("attempting to create ", name, "of", kind) location := FindArchetype(kind) var by []byte if location != "" { by, err = ioutil.ReadFile(location) if err != nil { jww.ERROR.Println(err) } } if location == "" || err != nil { by = []byte("+++\n title = \"title\"\n draft = true \n+++\n") } psr, err := parser.ReadFrom(bytes.NewReader(by)) if err != nil { return err } metadata, err := psr.Metadata() if err != nil { return err } newmetadata, err := cast.ToStringMapE(metadata) if err != nil { return err } for k, _ := range newmetadata { switch strings.ToLower(k) { case "date": newmetadata[k] = time.Now() case "title": newmetadata[k] = helpers.MakeTitle(helpers.Filename(name)) } } caseimatch := func(m map[string]interface{}, key string) bool { for k, _ := range m { if strings.ToLower(k) == strings.ToLower(key) { return true } } return false } if !caseimatch(newmetadata, "date") { newmetadata["date"] = time.Now() } if !caseimatch(newmetadata, "title") { newmetadata["title"] = helpers.MakeTitle(helpers.Filename(name)) } page, err := hugolib.NewPage(name) if err != nil { return err } if x := viper.GetString("MetaDataFormat"); x == "json" || x == "yaml" || x == "toml" { newmetadata["date"] = time.Now().Format(time.RFC3339) } page.Dir = viper.GetString("sourceDir") page.SetSourceMetaData(newmetadata, parser.FormatToLeadRune(viper.GetString("MetaDataFormat"))) if err = page.SafeSaveSourceAs(path.Join(viper.GetString("contentDir"), name)); err != nil { return } jww.FEEDBACK.Println(helpers.AbsPathify(path.Join(viper.GetString("contentDir"), name)), "created") return nil }
func processFile(filename string, in io.ReadSeeker, out io.Writer, stdin bool) error { if in == nil { f, err := os.Open(filename) if err != nil { return err } defer f.Close() in = f } // slurp in the whole file for comparison later src, err := ioutil.ReadAll(in) if err != nil { return err } in.Seek(0, 0) // parse the file with hugo/parser to extract front matter page, err := parser.ReadFrom(in) if err != nil { return err } md, err := markdown.Process(filename, page.Content(), nil) if err != nil { return err } // If we have front matter, insert a newline to separate the front matter // from the markdown content. sep := "" if len(page.FrontMatter()) > 0 { sep = "\n" } res := make([]byte, len(page.FrontMatter())+len(sep)+len(md)) copy(res, append(append(page.FrontMatter(), []byte(sep)...), md...)) if !bytes.Equal(src, res) { // formatting has changed if *list { fmt.Fprintln(out, filename) } if *write { err = ioutil.WriteFile(filename, res, 0) if err != nil { return err } } if *doDiff { data, err := diff(src, res) if err != nil { return fmt.Errorf("computing diff: %s", err) } fmt.Printf("diff %s mdfmt/%s\n", filename, filename) out.Write(data) } } if !*list && !*write && !*doDiff { _, err = out.Write(res) } return err }
// GET handles the GET method on editor page func GET(w http.ResponseWriter, r *http.Request, c *config.Config, filename string) (int, error) { // Check if the file format is supported. If not, send a "Not Acceptable" // header and an error if !utils.CanBeEdited(filename) { return http.StatusNotAcceptable, errors.New("File format not supported.") } // Check if the file exists. If it doesn't, send a "Not Found" message if _, err := os.Stat(filename); os.IsNotExist(err) { return http.StatusNotFound, nil } // Open the file and check if there was some error while opening file, err := ioutil.ReadFile(filename) if err != nil { return http.StatusInternalServerError, err } // Create a new editor variable and set the extension page := new(editor) page.Mode = strings.TrimPrefix(filepath.Ext(filename), ".") page.Name = strings.Replace(filename, c.Path, "", 1) page.Config = c page.IsPost = false // Sanitize the extension page.Mode = sanitizeMode(page.Mode) // Handle the content depending on the file extension switch page.Mode { case "markdown", "asciidoc", "rst": if hasFrontMatterRune(file) { // Starts a new buffer and parses the file using Hugo's functions buffer := bytes.NewBuffer(file) file, err := parser.ReadFrom(buffer) if err != nil { return http.StatusInternalServerError, err } if strings.Contains(string(file.FrontMatter()), "date") { page.IsPost = true } // Parses the page content and the frontmatter page.Content = strings.TrimSpace(string(file.Content())) page.FrontMatter, page.Name, err = frontmatter.Pretty(file.FrontMatter()) page.Class = "complete" } else { // The editor will handle only content page.Class = "content-only" page.Content = string(file) } case "json", "toml", "yaml": // Defines the class and declares an error page.Class = "frontmatter-only" var err error // Checks if the file already has the frontmatter rune and parses it if hasFrontMatterRune(file) { page.FrontMatter, _, err = frontmatter.Pretty(file) } else { page.FrontMatter, _, err = frontmatter.Pretty(appendFrontMatterRune(file, page.Mode)) } // Check if there were any errors if err != nil { return http.StatusInternalServerError, err } default: // The editor will handle only content page.Class = "content-only" page.Content = string(file) } // Create the functions map, then the template, check for erros and // execute the template if there aren't errors functions := template.FuncMap{ "SplitCapitalize": utils.SplitCapitalize, "Defined": utils.Defined, } tpl, err := utils.GetTemplate(r, functions, "editor", "frontmatter") if err != nil { return http.StatusInternalServerError, err } return http.StatusOK, tpl.Execute(w, page) }
func convertContents(mark rune) (err error) { if err := InitializeConfig(); err != nil { return err } site := &hugolib.Site{} if err := site.Initialise(); err != nil { return err } if site.Source == nil { panic(fmt.Sprintf("site.Source not set")) } if len(site.Source.Files()) < 1 { return fmt.Errorf("No source files found") } jww.FEEDBACK.Println("processing", len(site.Source.Files()), "content files") for _, file := range site.Source.Files() { jww.INFO.Println("Attempting to convert", file.LogicalName()) page, err := hugolib.NewPage(file.LogicalName()) if err != nil { return err } psr, err := parser.ReadFrom(file.Contents) if err != nil { jww.ERROR.Println("Error processing file:", file.Path()) return err } metadata, err := psr.Metadata() if err != nil { jww.ERROR.Println("Error processing file:", file.Path()) return err } // better handling of dates in formats that don't have support for them if mark == parser.FormatToLeadRune("json") || mark == parser.FormatToLeadRune("yaml") || mark == parser.FormatToLeadRune("toml") { newmetadata := cast.ToStringMap(metadata) for k, v := range newmetadata { switch vv := v.(type) { case time.Time: newmetadata[k] = vv.Format(time.RFC3339) } } metadata = newmetadata } page.SetDir(filepath.Join(helpers.AbsPathify(viper.GetString("ContentDir")), file.Dir())) page.SetSourceContent(psr.Content()) page.SetSourceMetaData(metadata, mark) if outputDir != "" { page.SaveSourceAs(filepath.Join(outputDir, page.FullFilePath())) } else { if unsafe { page.SaveSource() } else { jww.FEEDBACK.Println("Unsafe operation not allowed, use --unsafe or set a different output path") } } } return }
func (u *editHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { dir := strings.TrimPrefix(r.URL.Path, cfgRoot+"/edit/") filename := r.FormValue("filename") if filename != "" { dir = path.Join(dir, filename) } schema := defaultSchema archetype := findArchetype(u.root, dir) if archetype != "" { log.Info("Found archetype: %s", archetype) schemaFileName := path.Join(u.root, "archetypes", archetype+".json") targetSchema, err := ioutil.ReadFile(schemaFileName) if err != nil { log.Error(err) } else { schema = string(targetSchema) } } else { log.Info("Archetype not found") } var body []byte targetfilename := path.Join(u.root, dir) extension := filepath.Ext(targetfilename) if stringInSlice(extension, []string{".jpg", ".gif"}) { http.ServeFile(w, r, targetfilename) return } if r.Method == "POST" { var y map[string]interface{} body, _ = ioutil.ReadAll(r.Body) json.Unmarshal(body, &y) //log.Info(extension) //log.Info(body) switch { case extension == ".json": var z interface{} err2 := json.Unmarshal(body, &z) if err2 != nil { log.Error(err2) } log.Info("%v", z) body, _ = json.MarshalIndent(z, "", " ") err := ioutil.WriteFile(targetfilename, body, 0644) if err != nil { log.Warning(err) } case extension == ".md": var z interface{} if val, ok := y["frontmatter"]; ok { z = val } else { z = y } body, err := json.Marshal(z) if err != nil { log.Warning(err) } newbody := y["body"] body, _ = json.MarshalIndent(z, "", " ") result := fmt.Sprintf("%s\n\n%s", body, newbody) err = ioutil.WriteFile(targetfilename, []byte(result), 0644) if err != nil { log.Warning(err) } } } else { if _, err := os.Stat(targetfilename); os.IsNotExist(err) { // path/to/whatever does not exist } else { switch { case extension == ".json": body, err = ioutil.ReadFile(targetfilename) if err != nil { log.Error(err) } case extension == ".md": f, err := os.Open(targetfilename) if err != nil { log.Warning(err) } defer f.Close() //body, err=ioutil.ReadFile(targetfilename) p, err := parser.ReadFrom(f) if err != nil { log.Warning(err) } log.Warning(string(p.Content())) log.Warning(string(p.FrontMatter())) metadata, err := p.Metadata() if err != nil { log.Warning(err) } j := make(map[string]interface{}) j["frontmatter"] = metadata j["body"] = string(p.Content()) body, _ = json.Marshal(j) default: http.ServeFile(w, r, targetfilename) return } } } html, _ := Asset(u.tmpl) funcMap := template.FuncMap{ /* "humanizeBytes": humanizeBytes, "humanizeTime": humanizeTime, "isZip": isZip, */ } t, err := template.New("").Funcs(funcMap).Parse(string(html)) if err != nil { log.Warning("error %s", err) } //files, err := ioutil.ReadDir(path.Join(v.root, r.URL.Path)) //sort.Sort(byName(files)) //url := r.Header.Get("Referer") url := path.Join(cfgRoot+"/ui", path.Dir(dir)) t.Execute(w, struct { FileName string StartValue string Referer string Schema string RootUrl string }{ dir, string(body), url, schema, cfgRoot, }) }