diff --git a/README.org b/README.org index 4eec00e..a1f5d00 100644 --- a/README.org +++ b/README.org @@ -1,44 +1,5 @@ -* go-org -An Org mode parser and static site generator in go. -Take a look at github pages -- for [[https://niklasfasching.github.io/go-org/][org to html conversion]] examples -- for a [[https://niklasfasching.github.io/go-org/blorg][static site]] generated by blorg -- to [[https://niklasfasching.github.io/go-org/convert.html][try it out live]] in your browser +* go-org-orgwiki -[[https://raw.githubusercontent.com/niklasfasching/go-org/master/etc/example.png]] +Thanks to: [[https://github.com/niklasfasching/go-org][go-org]] -Please note -- the goal for the html export is to produce sensible html output, not to exactly reproduce the output of =org-html-export=. -- the goal for the parser is to support a reasonable subset of Org mode. Org mode is *huge* and I like to follow the 80/20 rule. -* usage -** command line -#+begin_src bash -$ go-org -Usage: go-org COMMAND [ARGS]... -Commands: -- render [FILE] FORMAT - FORMAT: org, html, html-chroma - Instead of specifying a file, org mode content can also be passed on stdin -- blorg - - blorg init - - blorg build - - blorg serve -#+end_src -** as a library -see [[https://github.com/niklasfasching/go-org/blob/master/main.go][main.go]] and hugo [[https://github.com/gohugoio/hugo/blob/master/markup/org/convert.go][org/convert.go]] -* development -1. =make setup= -2. change things -3. =make preview= (regenerates fixtures & shows output in a browser) - -in general, have a look at the Makefile - it's short enough. -* resources -- test files - - [[https://raw.githubusercontent.com/kaushalmodi/ox-hugo/master/test/site/content-org/all-posts.org][ox-hugo all-posts.org]] - - https://ox-hugo.scripter.co/doc/examples/ -- https://orgmode.org/manual/ -- https://orgmode.org/worg/dev/org-syntax.html -- https://code.orgmode.org/bzg/org-mode/src/master/lisp/org.el - - 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]] +This fork is used exclusively by [[https://git.fz0x1.wtf/fz0x1/orgwiki][orgwiki]] and includes a few minor modifications tailored for it. diff --git a/etc/generate-gh-pages b/etc/generate-gh-pages index 9bd8cfc..e9c7cee 100755 --- a/etc/generate-gh-pages +++ b/etc/generate-gh-pages @@ -133,7 +133,7 @@ echo "$index" > docs/index.html echo "$convert" > docs/convert.html cp etc/_wasm.go docs/wasm.go GOOS=js GOARCH=wasm go build -o docs/main.wasm docs/wasm.go -cp $(go env GOROOT)/misc/wasm/wasm_exec.js docs/wasm_exec.js +cp $(go env GOROOT)/lib/wasm/wasm_exec.js docs/wasm_exec.js mkdir -p docs/blorg cp -r blorg/testdata/public/* docs/blorg/ diff --git a/go.mod b/go.mod index 0ccf0ce..1ed69ee 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,13 @@ module github.com/niklasfasching/go-org -go 1.18 +go 1.23.0 + +toolchain go1.24.2 require ( github.com/alecthomas/chroma/v2 v2.5.0 github.com/pmezard/go-difflib v1.0.0 - golang.org/x/net v0.23.0 + golang.org/x/net v0.38.0 ) require github.com/dlclark/regexp2 v1.4.0 // indirect diff --git a/go.sum b/go.sum index 78a9162..ed71d32 100644 --- a/go.sum +++ b/go.sum @@ -7,5 +7,5 @@ github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55k github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= diff --git a/org/block.go b/org/block.go index 6907eaa..92469f6 100644 --- a/org/block.go +++ b/org/block.go @@ -157,7 +157,15 @@ func splitParameters(s string) []string { parameters, parts := []string{}, strings.Split(s, " :") lang, rest := strings.TrimSpace(parts[0]), parts[1:] if lang != "" { - parameters = append(parameters, lang) + xs := strings.Fields(lang) + parameters = append(parameters, xs[0]) + for i := 1; i < len(xs); i++ { + k, v := xs[i], "" + if i+1 < len(xs) && xs[i+1][0] != '-' { + v, i = xs[i+1], i+1 + } + parameters = append(parameters, k, v) + } } for _, p := range rest { kv := strings.SplitN(p+" ", " ", 2) diff --git a/org/document.go b/org/document.go index 8dba04f..edbd380 100644 --- a/org/document.go +++ b/org/document.go @@ -29,6 +29,7 @@ type Configuration struct { DefaultSettings map[string]string // Default values for settings that are overriden by setting the same key in BufferSettings. Log *log.Logger // Log is used to print warnings during parsing. ReadFile func(filename string) ([]byte, error) // ReadFile is used to read e.g. #+INCLUDE files. + ResolveLink func(protocol string, description []Node, link string) Node } // Document contains the parsing results and a pointer to the Configuration. @@ -93,6 +94,9 @@ func New() *Configuration { }, Log: log.New(os.Stderr, "go-org: ", 0), ReadFile: ioutil.ReadFile, + ResolveLink: func(protocol string, description []Node, link string) Node { + return RegularLink{protocol, description, link, false} + }, } } @@ -260,7 +264,9 @@ func (d *Document) parseMany(i int, stop stopFn) (int, []Node) { func (d *Document) addHeadline(headline *Headline) int { current := &Section{Headline: headline} d.Outline.last.add(current) - d.Outline.count++ + if !headline.IsExcluded(d) { + d.Outline.count++ + } d.Outline.last = current return d.Outline.count } diff --git a/org/headline.go b/org/headline.go index f9a77c7..b8b7b94 100644 --- a/org/headline.go +++ b/org/headline.go @@ -23,6 +23,7 @@ type Headline struct { Index int Lvl int Status string + IsComment bool Priority string Properties *PropertyDrawer Title []Node @@ -43,9 +44,6 @@ 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 := trimFastTags( strings.FieldsFunc(d.Get("TODO"), func(r rune) bool { return unicode.IsSpace(r) || r == '|' }), @@ -62,12 +60,15 @@ func (d *Document) parseHeadline(i int, parentStop stopFn) (int, Node) { headline.Priority = text[2:3] text = strings.TrimSpace(text[4:]) } - + if strings.HasPrefix(text, "COMMENT ") { + headline.IsComment = true + text = strings.TrimPrefix(text, "COMMENT ") + } if m := tagRegexp.FindStringSubmatch(text); m != nil { text = m[1] headline.Tags = strings.FieldsFunc(m[2], func(r rune) bool { return r == ':' }) } - + headline.Index = d.addHeadline(&headline) headline.Title = d.parseInline(text) stop := func(d *Document, i int) bool { @@ -107,6 +108,9 @@ func (h Headline) ID() string { } func (h Headline) IsExcluded(d *Document) bool { + if h.IsComment { + return true + } for _, excludedTag := range strings.Fields(d.Get("EXCLUDE_TAGS")) { for _, tag := range h.Tags { if tag == excludedTag { diff --git a/org/html_writer.go b/org/html_writer.go index ca9ffb2..878e29a 100644 --- a/org/html_writer.go +++ b/org/html_writer.go @@ -393,16 +393,16 @@ func (w *HTMLWriter) WriteRegularLink(l RegularLink) { if l.Protocol == "file" { url = url[len("file:"):] } - if isRelative := l.Protocol == "file" || l.Protocol == ""; isRelative && w.PrettyRelativeLinks { - if !strings.HasPrefix(url, "/") { - url = "../" + url - } - if strings.HasSuffix(url, ".org") { - url = strings.TrimSuffix(url, ".org") + "/" - } - } else if isRelative && strings.HasSuffix(url, ".org") { - url = strings.TrimSuffix(url, ".org") + ".html" - } + // if isRelative := l.Protocol == "file" || l.Protocol == ""; isRelative && w.PrettyRelativeLinks { + // if !strings.HasPrefix(url, "/") { + // url = "../" + url + // } + // if strings.HasSuffix(url, ".org") { + // url = strings.TrimSuffix(url, ".org") + "/" + // } + // } else if isRelative && strings.HasSuffix(url, ".org") { + // url = strings.TrimSuffix(url, ".org") + ".html" + // } if prefix := w.document.Links[l.Protocol]; prefix != "" { if tag := strings.TrimPrefix(l.URL, l.Protocol+":"); strings.Contains(prefix, "%s") || strings.Contains(prefix, "%h") { url = html.EscapeString(strings.ReplaceAll(strings.ReplaceAll(prefix, "%s", tag), "%h", u.QueryEscape(tag))) diff --git a/org/inline.go b/org/inline.go index dbd20c6..798d30f 100644 --- a/org/inline.go +++ b/org/inline.go @@ -73,7 +73,7 @@ var timestampRegexp = regexp.MustCompile(`^<(\d{4}-\d{2}-\d{2})( [A-Za-z]+)?( \d var footnoteRegexp = regexp.MustCompile(`^\[fn:([\w-]*?)(:(.*?))?\]`) var statisticsTokenRegexp = regexp.MustCompile(`^\[(\d+/\d+|\d+%)\]`) var latexFragmentRegexp = regexp.MustCompile(`(?s)^\\begin{(\w+)}(.*)\\end{(\w+)}`) -var inlineBlockRegexp = regexp.MustCompile(`src_(\w+)(\[(.*)\])?{(.*)}`) +var inlineBlockRegexp = regexp.MustCompile(`src_(\w+)(\[([^\]]*)\])?{([^}]*)}`) var inlineExportBlockRegexp = regexp.MustCompile(`@@(\w+):(.*?)@@`) var macroRegexp = regexp.MustCompile(`{{{(.*)\((.*)\)}}}`) @@ -329,7 +329,7 @@ func (d *Document) parseRegularLink(input string, start int) (int, Node) { if len(linkParts) == 2 { protocol = linkParts[0] } - return consumed, RegularLink{protocol, description, link, false} + return consumed, d.ResolveLink(protocol, description, link) } func (d *Document) parseTimestamp(input string, start int) (int, Node) { diff --git a/org/testdata/headlines.html b/org/testdata/headlines.html index e598777..ce09dc1 100644 --- a/org/testdata/headlines.html +++ b/org/testdata/headlines.html @@ -10,9 +10,9 @@
:PROPERTIES: not a property
:END:
The toc option allows setting a level limit. For this file we set it to 1 - which means that the following headlines won't be included in the table of contents.
-you get the gist…
+world
+
+multiline emphasis is
diff --git a/org/testdata/inline.org b/org/testdata/inline.org
index 7f8b31d..cc0c845 100644
--- a/org/testdata/inline.org
+++ b/org/testdata/inline.org
@@ -11,7 +11,7 @@
- links with slashes do not become /emphasis/: [[https://somelinkshouldntrenderaccidentalemphasis.com]]/ /emphasis/
- _underlined_ *bold* =verbatim= ~code~ +strikethrough+
- *bold string with an *asterisk inside*
-- inline source blocks like src_html[:eval no]{hello
}
+- inline source blocks like src_html[:eval no]{hello
} and this src_schema[:eval no]{world}
- inline export blocks @@html:hello
@@
- =multiline emphasis is
supported - and respects MaxEmphasisNewLines (default: 1)=
diff --git a/org/testdata/inline.pretty_org b/org/testdata/inline.pretty_org
index ab77e41..87238cc 100644
--- a/org/testdata/inline.pretty_org
+++ b/org/testdata/inline.pretty_org
@@ -11,7 +11,7 @@
- links with slashes do not become /emphasis/: [[https://somelinkshouldntrenderaccidentalemphasis.com]]/ /emphasis/
- _underlined_ *bold* =verbatim= ~code~ +strikethrough+
- *bold string with an *asterisk inside*
-- inline source blocks like src_html[:eval no]{hello
}
+- inline source blocks like src_html[:eval no]{hello
} and this src_schema[:eval no]{world}
- inline export blocks @@html:hello
@@
- =multiline emphasis is
supported - and respects MaxEmphasisNewLines (default: 1)=
diff --git a/org/testdata/misc.html b/org/testdata/misc.html
index 6c79fbd..4be094c 100644
--- a/org/testdata/misc.html
+++ b/org/testdata/misc.html
@@ -171,6 +171,8 @@ it's possible to use =#+SETUPFILE= - in this case the setup file contains th
this headline and it's content are not exported as it is marked with an =EXCLUDE_TAGS= tag.
By default =EXCLUDE_TAGS= is just =:noexport:=.
+* TODO [#A] COMMENT commented headline
+this headline is commented out. see [[https://orgmode.org/manual/Comment-Lines.html][comment lines]]
* malformed property drawer
:PROPERTIES:
not a property