diff --git a/README.org b/README.org index 5ee31b1..069794c 100644 --- a/README.org +++ b/README.org @@ -4,12 +4,14 @@ Take a look at [[https://niklasfasching.github.io/go-org/][github pages]] for so * next - more keywords: https://orgmode.org/manual/In_002dbuffer-settings.html - table of contents + - see hugo ExtractTOC + - loop the headlines and print an hX for each headline, ul for children - rethink frontmatter - - keyword customizable mapping. e.g. #+ARRAY_KWS: list kws that should become []string - - json/yaml values. - - +lisp syntax from [[https://github.com/kaushalmodi/ox-hugo/blob/master/ox-hugo.el#L2791][ox-hugo]]+ - - too much complexity and not native to Org mode, i.e. does not even increase compatibility - - use toml/yaml/json frontmatter from hugo (see [[https://github.com/gohugoio/hugo/issues/5436][hugo #5436]]) + - use toml/yaml/json frontmatter from hugo (see [[https://github.com/gohugoio/hugo/issues/5436][hugo #5436]]): + - complex values are a requirement of hugo, not Org mode + - by giving up on the ability to mix front matter in org keyword (=#+=) and other formats we save a lot of complexity (that has little benefit) + - Maybe allow for []string via KEYWORD[]: Tag Foo Bar - can be done in hugo + -> the other problem is that org mode normally allows markup in the title - but we would have to render - and to what format ** headlines - auto-generate unique ids: see [[https://github.com/kaushalmodi/ox-hugo/blob/8472cf2d8667754c9da3728255634e8001a1da6d/ox-hugo.el#L1785-L1850][ox-hugo]] - what about name conflicts? @@ -41,3 +43,4 @@ Nonetheless, the html output can be compared by taking a look in the developer c - https://code.orgmode.org/bzg/org-mode/src/master/lisp/org-element.el - mostly those & ox-html.el, but yeah, all of [[https://code.orgmode.org/bzg/org-mode/src/master/lisp/]] - existing Org mode implementations: [[https://github.com/emacsmirror/org][org]], [[https://github.com/bdewey/org-ruby/blob/master/spec/html_examples][org-ruby]], [[https://github.com/chaseadamsio/goorgeous/][goorgeous]], [[https://github.com/jgm/pandoc/][pandoc]] + diff --git a/org/document.go b/org/document.go index 3b5e8fa..7f12479 100644 --- a/org/document.go +++ b/org/document.go @@ -15,6 +15,7 @@ type Document struct { tokens []token Nodes []Node Footnotes Footnotes + Outline Outline StatusKeywords []string MaxEmphasisNewLines int AutoLink bool @@ -71,6 +72,7 @@ func FrontMatterHandler(fm FrontMatter, k, v string) error { } func NewDocument() *Document { + outlineSection := &Section{} return &Document{ Footnotes: Footnotes{ Title: "Footnotes", @@ -78,6 +80,7 @@ func NewDocument() *Document { }, AutoLink: true, MaxEmphasisNewLines: 1, + Outline: Outline{outlineSection, outlineSection, 0}, BufferSettings: map[string]string{}, DefaultSettings: map[string]string{ "TODO": "TODO | DONE", @@ -232,6 +235,12 @@ func (d *Document) addFootnote(name string, definition *FootnoteDefinition) { d.Footnotes.addOrder = append(d.Footnotes.addOrder, name) } +func (d *Document) addHeadline(headline *Headline) int { + d.Outline.last.add(&Section{Headline: headline}) + d.Outline.count++ + return d.Outline.count +} + func tokenize(line string) token { for _, lexFn := range lexFns { if token, ok := lexFn(line); ok { diff --git a/org/headline.go b/org/headline.go index b082ac3..74ff99e 100644 --- a/org/headline.go +++ b/org/headline.go @@ -1,12 +1,26 @@ package org import ( + "fmt" "regexp" "strings" "unicode" ) +type Outline struct { + *Section + last *Section + count int +} + +type Section struct { + Headline *Headline + Parent *Section + Children []*Section +} + type Headline struct { + Index int Lvl int Status string Priority string @@ -29,6 +43,9 @@ func lexHeadline(line string) (token, bool) { func (d *Document) parseHeadline(i int, parentStop stopFn) (int, Node) { t, headline := d.tokens[i], Headline{} headline.Lvl = len(t.matches[1]) + + headline.Index = d.addHeadline(&headline) + text := t.content todoKeywords := strings.FieldsFunc(d.Get("TODO"), func(r rune) bool { return unicode.IsSpace(r) || r == '|' }) for _, k := range todoKeywords { @@ -64,3 +81,19 @@ func (d *Document) parseHeadline(i int, parentStop stopFn) (int, Node) { headline.Children = nodes return consumed + 1, headline } + +func (h Headline) ID() string { + if customID, ok := h.Properties.Get("CUSTOM_ID"); ok { + return customID + } + return fmt.Sprintf("headline-%d", h.Index) +} + +func (parent *Section) add(current *Section) { + if parent.Headline == nil || parent.Headline.Lvl < current.Headline.Lvl { + parent.Children = append(parent.Children, current) + current.Parent = parent + } else { + parent.Parent.add(current) + } +} diff --git a/org/html.go b/org/html.go index 4bc048e..b9fa41c 100644 --- a/org/html.go +++ b/org/html.go @@ -4,6 +4,7 @@ import ( "fmt" "html" "log" + "regexp" "strings" "unicode" @@ -42,6 +43,8 @@ var listItemStatuses = map[string]string{ "X": "checked", } +var cleanHeadlineTitleForHTMLAnchorRegexp = regexp.MustCompile(`?a[^>]*>`) // nested a tags are not valid HTML + func NewHTMLWriter() *HTMLWriter { return &HTMLWriter{ htmlEscape: true, @@ -66,6 +69,7 @@ func (w *HTMLWriter) nodesAsString(nodes ...Node) string { func (w *HTMLWriter) before(d *Document) { w.excludeTags = strings.Fields(d.Get("EXCLUDE_TAGS")) w.log = d.Log + w.writeOutline(d) } func (w *HTMLWriter) after(d *Document) { @@ -201,6 +205,31 @@ func (w *HTMLWriter) writeFootnotes(d *Document) { w.WriteString("\n\n") } +func (w *HTMLWriter) writeOutline(d *Document) { + if len(d.Outline.Children) != 0 { + w.WriteString("\n") + } +} + +func (w *HTMLWriter) writeSection(section *Section) { + w.WriteString("
diff --git a/org/testdata/headlines.html b/org/testdata/headlines.html index 814a27e..88d9672 100644 --- a/org/testdata/headlines.html +++ b/org/testdata/headlines.html @@ -1,4 +1,26 @@ -
[1/2]
TODO
[B]
Headline with todo status & priority
@@ -32,7 +54,7 @@ Headline with TODO status
we can link to headlines that define a custom_id: #this-will-be-the-id-of-the-headline
-
+
[A]
Headline with tags & priority
@@ -45,7 +67,7 @@ This is inside the drawer
Still outside the drawer
-
+
CUSTOM
headline with custom status
diff --git a/org/testdata/misc.html b/org/testdata/misc.html
index df15f4b..a6f9657 100644
--- a/org/testdata/misc.html
+++ b/org/testdata/misc.html
@@ -1,12 +1,88 @@
-
+
+
issues from goorgeous (free test cases, yay!)
-
+
DONE
#19: Support #+HTML
neato!
-
+
DONE
#29: Support verse block
@@ -23,7 +99,7 @@ or even a totally custom kind of block
crazy ain't it?
-
+
DONE
#31: Support #+INCLUDE
@@ -115,7 +191,7 @@ deploy:
code
wrapped text gets joined
this
or that
foo.
either this
or that
foo.
-code
— as code plus dash
just a space as title…
-Foo paragraph.
-Bar paragraph
-footnotes can contain markup - and other elements and stuff 2
-@@ -346,7 +422,7 @@ Hello, I'm writing hugo blogs using org-mode.
When inserting an image link like , hugo doesn't export the image.