From 9995b3cdad4a8aaea06d3574f59c583633b75cd4 Mon Sep 17 00:00:00 2001 From: Niklas Fasching Date: Mon, 25 Oct 2021 16:47:26 +0200 Subject: [PATCH] html: Improve link abbreviation (#+LINK) resolution Handle `%s`/`%h` interpolation and add support for shorthand of prefix only links / links with empty tag (i.e. `[example]` instead of [example:]). See [1] and [2]. As so often we don't match org mode output completely but our output looks sane enough to me so let's move along for now. [1] https://orgmode.org/manual/Link-Abbreviations.html [2] https://github.com/bzg/org-mode/blob/main/lisp/ol.el#L1011 --- org/html_writer.go | 10 +++++++++- org/keyword.go | 2 +- org/testdata/inline.html | 10 +++++++++- org/testdata/inline.org | 10 +++++++++- org/testdata/inline.pretty_org | 10 +++++++++- 5 files changed, 37 insertions(+), 5 deletions(-) diff --git a/org/html_writer.go b/org/html_writer.go index 5ab9d8f..fc0780a 100644 --- a/org/html_writer.go +++ b/org/html_writer.go @@ -10,6 +10,8 @@ import ( "strings" "unicode" + u "net/url" + h "golang.org/x/net/html" "golang.org/x/net/html/atom" ) @@ -361,7 +363,13 @@ func (w *HTMLWriter) WriteRegularLink(l RegularLink) { url = strings.TrimSuffix(url, ".org") + ".html" } if prefix := w.document.Links[l.Protocol]; prefix != "" { - url = html.EscapeString(prefix) + strings.TrimPrefix(url, l.Protocol+":") + 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))) + } else { + url = html.EscapeString(prefix) + tag + } + } else if prefix := w.document.Links[l.URL]; prefix != "" { + url = html.EscapeString(strings.ReplaceAll(strings.ReplaceAll(prefix, "%s", ""), "%h", "")) } switch l.Kind() { case "image": diff --git a/org/keyword.go b/org/keyword.go index c166b95..1af62fc 100644 --- a/org/keyword.go +++ b/org/keyword.go @@ -63,7 +63,7 @@ func (d *Document) parseKeyword(i int, stop stopFn) (int, Node) { case "INCLUDE": return d.parseInclude(k) case "LINK": - if parts := strings.Split(k.Value, " "); len(parts) >= 2 { + if parts := strings.SplitN(k.Value, " ", 2); len(parts) == 2 { d.Links[parts[0]] = parts[1] } return 1, k diff --git a/org/testdata/inline.html b/org/testdata/inline.html index 61bedc9..a4abdc0 100644 --- a/org/testdata/inline.html +++ b/org/testdata/inline.html @@ -55,7 +55,15 @@ not emphasized/
  • -

    #+LINK based links: https://www.example.com/foobar

    +

    #+LINK based links:

    +
  • #+MACROs:

    yolo

    diff --git a/org/testdata/inline.org b/org/testdata/inline.org index 5d66de5..9273e7f 100644 --- a/org/testdata/inline.org +++ b/org/testdata/inline.org @@ -39,7 +39,15 @@ - <2019-01-06 Sun 18:00 +1w> - <2019-01-06 18:00> - <2019-01-06 18:00 +1w> -- =#+LINK= based links: [[example:foobar]] +- =#+LINK= based links: #+LINK: example https://www.example.com/ + #+LINK: example_interpolate_s https://www.example.com?raw_tag=%s + #+LINK: example_interpolate_h https://www.example.com?encoded_tag=%h + - [[example:foobar]] + - [[example:]] + - [[example]] + - [[example][description]] + - [[example_interpolate_s:tag value with specical chars % : &]] (w/o tag [[example_interpolate_s]]) + - [[example_interpolate_h:tag value with specical chars % : &]] (w/o tag [[example_interpolate_h]]) - =#+MACROs=: {{{headline(yolo)}}} #+MACRO: headline @@html:

    $1

    @@ diff --git a/org/testdata/inline.pretty_org b/org/testdata/inline.pretty_org index c9841a9..8d82893 100644 --- a/org/testdata/inline.pretty_org +++ b/org/testdata/inline.pretty_org @@ -39,7 +39,15 @@ - <2019-01-06 Sun 18:00 +1w> - <2019-01-06 Sun 18:00> - <2019-01-06 Sun 18:00 +1w> -- =#+LINK= based links: [[example:foobar]] +- =#+LINK= based links: #+LINK: example https://www.example.com/ + #+LINK: example_interpolate_s https://www.example.com?raw_tag=%s + #+LINK: example_interpolate_h https://www.example.com?encoded_tag=%h + - [[example:foobar]] + - [[example:]] + - [[example]] + - [[example][description]] + - [[example_interpolate_s:tag value with specical chars % : &]] (w/o tag [[example_interpolate_s]]) + - [[example_interpolate_h:tag value with specical chars % : &]] (w/o tag [[example_interpolate_h]]) - =#+MACROs=: {{{headline(yolo)}}} #+MACRO: headline @@html:

    $1

    @@