shithub: hugo

Download patch

ref: 86e8dd62f0b1c8adf14e9369b089d209317aaf2d
parent: a3af4fe46e1e1d184538a83bc8375154a9669316
author: Chase Adams <[email protected]>
date: Mon Feb 20 18:46:03 EST 2017

all: Add org-mode support

Fixes #1483 
See #936 

--- a/docs/content/content/summaries.md
+++ b/docs/content/content/summaries.md
@@ -24,14 +24,14 @@
 
 ## User-defined: manual summary split:
 
-Alternatively, you may add the <code>&#60;&#33;&#45;&#45;more&#45;&#45;&#62;</code> summary divider[^1] where you want to split the article.  Content prior to the summary divider will be used as that content's summary, and stored into the `.Summary` variable with all HTML formatting intact.
+Alternatively, you may add the <code>&#60;&#33;&#45;&#45;more&#45;&#45;&#62;</code> summary divider[^1] (for org content, use <code># more</code>) where you want to split the article.  Content prior to the summary divider will be used as that content's summary, and stored into the `.Summary` variable with all HTML formatting intact.
 
 [^1]: The **summary divider** is also called "more tag", "excerpt separator", etc. in other literature.
 
 * Pros: Freedom, precision, and improved rendering.  All formatting is preserved.
-* Cons: Need to remember to type <code>&#60;&#33;&#45;&#45;more&#45;&#45;&#62;</code> in your content file.  :-)
+* Cons: Need to remember to type <code>&#60;&#33;&#45;&#45;more&#45;&#45;&#62;</code> (or <code># more</code> for org content) in your content file.  :-)
 
-Be careful to enter <code>&#60;&#33;&#45;&#45;more&#45;&#45;&#62;</code> exactly, i.e. all lowercase with no whitespace, otherwise it would be treated as regular comment and ignored.
+Be careful to enter <code>&#60;&#33;&#45;&#45;more&#45;&#45;&#62;</code> (or <code># more</code> for org content) exactly, i.e. all lowercase with no whitespace, otherwise it would be treated as regular comment and ignored.
 
 If there is nothing but spaces and newlines after the summary divider then `.Truncated` will be false.
 
--- a/docs/content/content/supported-formats.md
+++ b/docs/content/content/supported-formats.md
@@ -13,7 +13,7 @@
 toc: true
 ---
 
-  Since 0.14, Hugo has defined a new concept called _external helpers_. It means that you can write your content using Asciidoc[tor], or reStructuredText. If you have files with associated extensions ([details](https://github.com/spf13/hugo/blob/77c60a3440806067109347d04eb5368b65ea0fe8/helpers/general.go#L65)), then Hugo will call external commands to generate the content.
+  Since 0.14, Hugo has defined a new concept called _external helpers_. It means that you can write your content using Asciidoc[tor], reStructuredText or Org-Mode. If you have files with associated extensions ([details](https://github.com/spf13/hugo/blob/77c60a3440806067109347d04eb5368b65ea0fe8/helpers/general.go#L65)), then Hugo will call external commands to generate the content (the exception being Org-Mode content, which is parsed natively).
 
   This means that you will have to install the associated tool on your machine to be able to use those formats.
 
--- a/helpers/content.go
+++ b/helpers/content.go
@@ -24,12 +24,12 @@
 	"unicode"
 	"unicode/utf8"
 
-	"github.com/spf13/hugo/config"
-
+	"github.com/chaseadamsio/goorgeous"
 	"github.com/miekg/mmark"
 	"github.com/mitchellh/mapstructure"
 	"github.com/russross/blackfriday"
 	bp "github.com/spf13/hugo/bufferpool"
+	"github.com/spf13/hugo/config"
 	jww "github.com/spf13/jwalterweatherman"
 
 	"strings"
@@ -415,6 +415,8 @@
 		return c.mmarkRender(ctx)
 	case "rst":
 		return getRstContent(ctx)
+	case "org":
+		return orgRender(ctx, c)
 	}
 }
 
@@ -662,4 +664,11 @@
 	}
 
 	return result[bodyStart+7 : bodyEnd]
+}
+
+func orgRender(ctx *RenderingContext, c ContentSpec) []byte {
+	content := ctx.Content
+	cleanContent := bytes.Replace(content, []byte("# more"), []byte(""), 1)
+	return goorgeous.Org(cleanContent,
+		c.getHTMLRenderer(blackfriday.HTML_TOC, ctx))
 }
--- a/helpers/general.go
+++ b/helpers/general.go
@@ -80,6 +80,8 @@
 		return "rst"
 	case "html", "htm":
 		return "html"
+	case "org":
+		return "org"
 	}
 
 	return "unknown"
--- a/helpers/general_test.go
+++ b/helpers/general_test.go
@@ -36,6 +36,7 @@
 		{"mmark", "mmark"},
 		{"html", "html"},
 		{"htm", "html"},
+		{"org", "org"},
 		{"excel", "unknown"},
 	} {
 		result := GuessType(this.in)
--- a/hugolib/handler_page.go
+++ b/hugolib/handler_page.go
@@ -26,6 +26,7 @@
 	RegisterHandler(new(asciidocHandler))
 	RegisterHandler(new(rstHandler))
 	RegisterHandler(new(mmarkHandler))
+	RegisterHandler(new(orgHandler))
 }
 
 type basicPageHandler Handle
@@ -107,6 +108,15 @@
 
 func (h mmarkHandler) Extensions() []string { return []string{"mmark"} }
 func (h mmarkHandler) PageConvert(p *Page) HandledResult {
+	return commonConvert(p)
+}
+
+type orgHandler struct {
+	basicPageHandler
+}
+
+func (h orgHandler) Extensions() []string { return []string{"org"} }
+func (h orgHandler) PageConvert(p *Page) HandledResult {
 	return commonConvert(p)
 }
 
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -420,7 +420,11 @@
 // rendering engines.
 // TODO(bep) inline replace
 func (p *Page) replaceDivider(content []byte) []byte {
-	sections := bytes.Split(content, helpers.SummaryDivider)
+	summaryDivider := helpers.SummaryDivider
+	if p.Ext() == "org" {
+		summaryDivider = []byte("# more")
+	}
+	sections := bytes.Split(content, summaryDivider)
 
 	// If the raw content has nothing but whitespace after the summary
 	// marker then the page shouldn't be marked as truncated.  This check
--- a/parser/frontmatter.go
+++ b/parser/frontmatter.go
@@ -19,6 +19,7 @@
 	"errors"
 	"strings"
 
+	"github.com/chaseadamsio/goorgeous"
 	toml "github.com/pelletier/go-toml"
 
 	"gopkg.in/yaml.v2"
@@ -154,6 +155,8 @@
 		return &frontmatterType{[]byte(TOMLDelim), []byte(TOMLDelim), HandleTOMLMetaData, false}
 	case '{':
 		return &frontmatterType{[]byte{'{'}, []byte{'}'}, HandleJSONMetaData, true}
+	case '#':
+		return &frontmatterType{[]byte("#+"), []byte("\n"), HandleOrgMetaData, false}
 	default:
 		return nil
 	}
@@ -188,4 +191,8 @@
 	var f interface{}
 	err := json.Unmarshal(datum, &f)
 	return f, err
+}
+
+func HandleOrgMetaData(datum []byte) (interface{}, error) {
+	return goorgeous.OrgHeaders(datum)
 }
--- a/parser/page.go
+++ b/parser/page.go
@@ -21,6 +21,8 @@
 	"regexp"
 	"strings"
 	"unicode"
+
+	"github.com/chaseadamsio/goorgeous"
 )
 
 const (
@@ -91,9 +93,11 @@
 
 	if len(frontmatter) != 0 {
 		fm := DetectFrontMatter(rune(frontmatter[0]))
-		meta, err = fm.Parse(frontmatter)
-		if err != nil {
-			return
+		if fm != nil {
+			meta, err = fm.Parse(frontmatter)
+			if err != nil {
+				return
+			}
 		}
 	}
 	return
@@ -125,6 +129,12 @@
 	if newp.render && isFrontMatterDelim(firstLine) {
 		left, right := determineDelims(firstLine)
 		fm, err := extractFrontMatterDelims(reader, left, right)
+		if err != nil {
+			return nil, err
+		}
+		newp.frontmatter = fm
+	} else if newp.render && goorgeous.IsKeyword(firstLine) {
+		fm, err := goorgeous.ExtractOrgHeaders(reader)
 		if err != nil {
 			return nil, err
 		}
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -33,6 +33,12 @@
 			"revisionTime": "2016-04-08T19:03:23Z"
 		},
 		{
+			"checksumSHA1": "RxIwAgjIuBpwde5BCZRLLK7VRG8=",
+			"path": "github.com/chaseadamsio/goorgeous",
+			"revision": "72a06e1b07db57f3931f5a9c00f3f04e636ad0a8",
+			"revisionTime": "2017-02-17T13:03:04Z"
+		},
+		{
 			"checksumSHA1": "ntacCkWfMT63DaehXLG5FeXWyNM=",
 			"path": "github.com/cpuguy83/go-md2man/md2man",
 			"revision": "a65d4d2de4d5f7c74868dfa9b202a3c8be315aaa",