Implement escaping in src (org only) and example blocks

inside src example blocks lines starting with `\s*,` are escaped - i.e. org
mode will not try to parse them as e.g. a headline. We don't want to render the
escape commata to html so let's take them out - and put them back in before
rendering to org. Doing it this way allows us to render them correctly even
when the input did not include them.

see https://orgmode.org/manual/Literal-Examples.html#Literal-Examples
This commit is contained in:
Niklas Fasching 2020-04-16 15:49:32 +02:00
parent cbf1b8c38c
commit d417c2a6dd
5 changed files with 65 additions and 2 deletions

View file

@ -19,6 +19,7 @@ type Example struct {
var exampleLineRegexp = regexp.MustCompile(`^(\s*):(\s(.*)|\s*$)`) var exampleLineRegexp = regexp.MustCompile(`^(\s*):(\s(.*)|\s*$)`)
var beginBlockRegexp = regexp.MustCompile(`(?i)^(\s*)#\+BEGIN_(\w+)(.*)`) var beginBlockRegexp = regexp.MustCompile(`(?i)^(\s*)#\+BEGIN_(\w+)(.*)`)
var endBlockRegexp = regexp.MustCompile(`(?i)^(\s*)#\+END_(\w+)`) var endBlockRegexp = regexp.MustCompile(`(?i)^(\s*)#\+END_(\w+)`)
var exampleBlockEscapeRegexp = regexp.MustCompile(`(^|\n)([ \t]*),([ \t]*)(\*|,\*|#\+|,#\+)`)
func lexBlock(line string) (token, bool) { func lexBlock(line string) (token, bool) {
if m := beginBlockRegexp.FindStringSubmatch(line); m != nil { if m := beginBlockRegexp.FindStringSubmatch(line); m != nil {
@ -51,6 +52,9 @@ func (d *Document) parseBlock(i int, parentStop stopFn) (int, Node) {
for ; !stop(d, i); i++ { for ; !stop(d, i); i++ {
rawText += trim(d.tokens[i].matches[0]) + "\n" rawText += trim(d.tokens[i].matches[0]) + "\n"
} }
if name == "EXAMPLE" || (name == "SRC" && len(parameters) >= 1 && parameters[0] == "org") {
rawText = exampleBlockEscapeRegexp.ReplaceAllString(rawText, "$1$2$3$4")
}
block.Children = d.parseRawInline(rawText) block.Children = d.parseRawInline(rawText)
} else { } else {
consumed, nodes := d.parseMany(i, stop) consumed, nodes := d.parseMany(i, stop)

View file

@ -2,6 +2,7 @@ package org
import ( import (
"fmt" "fmt"
"regexp"
"strings" "strings"
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
@ -16,6 +17,8 @@ type OrgWriter struct {
indent string indent string
} }
var exampleBlockUnescapeRegexp = regexp.MustCompile(`(^|\n)([ \t]*)(\*|,\*|#\+|,#\+)`)
var emphasisOrgBorders = map[string][]string{ var emphasisOrgBorders = map[string][]string{
"_": []string{"_", "_"}, "_": []string{"_", "_"},
"*": []string{"*", "*"}, "*": []string{"*", "*"},
@ -90,7 +93,11 @@ func (w *OrgWriter) WriteBlock(b Block) {
if isRawTextBlock(b.Name) { if isRawTextBlock(b.Name) {
w.WriteString(w.indent) w.WriteString(w.indent)
} }
WriteNodes(w, b.Children...) content := w.WriteNodesAsString(b.Children...)
if b.Name == "EXAMPLE" || (b.Name == "SRC" && len(b.Parameters) >= 1 && b.Parameters[0] == "org") {
content = exampleBlockUnescapeRegexp.ReplaceAllString(content, "$1$2,$3")
}
w.WriteString(content)
if !isRawTextBlock(b.Name) { if !isRawTextBlock(b.Name) {
w.WriteString(w.indent) w.WriteString(w.indent)
} }

View file

@ -96,6 +96,24 @@ paragraphs
</li> </li>
</ul> </ul>
</blockquote> </blockquote>
<div class="src src-org">
<div class="highlight">
<pre>
#+BEGIN_SRC bash
echo src (with language org) and example blocks support escaping using commata
#+END_SRC
,* I am not a real headline - commata escape characters aren&#39;t renderered
</pre>
</div>
</div>
<pre class="example">
#+BEGIN_SRC bash
echo src (with language org) and example blocks support escaping using commata
#+END_SRC
,* I am not a real headline - commata escape characters aren&#39;t renderered
</pre>
<script> <script>
console.log("Hello World!") console.log("Hello World!")
</script> </script>

View file

@ -51,6 +51,23 @@ blocks like the quote block parse their content and can contain
it can be made visible using css (e.g. =white-space: pre=). it can be made visible using css (e.g. =white-space: pre=).
#+END_QUOTE #+END_QUOTE
#+BEGIN_SRC org
,#+BEGIN_SRC bash
echo src (with language org) and example blocks support escaping using commata
,#+END_SRC
,,* I am not a real headline - commata escape characters aren't renderered
#+END_SRC
#+BEGIN_EXAMPLE
,#+BEGIN_SRC bash
echo src (with language org) and example blocks support escaping using commata
,#+END_SRC
,,* I am not a real headline - commata escape characters aren't renderered
#+END_EXAMPLE
#+BEGIN_EXPORT html #+BEGIN_EXPORT html
<script> <script>
console.log("Hello World!") console.log("Hello World!")

View file

@ -51,6 +51,23 @@ blocks like the quote block parse their content and can contain
it can be made visible using css (e.g. =white-space: pre=). it can be made visible using css (e.g. =white-space: pre=).
#+END_QUOTE #+END_QUOTE
#+BEGIN_SRC org
,#+BEGIN_SRC bash
echo src (with language org) and example blocks support escaping using commata
,#+END_SRC
,,* I am not a real headline - commata escape characters aren't renderered
#+END_SRC
#+BEGIN_EXAMPLE
,#+BEGIN_SRC bash
echo src (with language org) and example blocks support escaping using commata
,#+END_SRC
,,* I am not a real headline - commata escape characters aren't renderered
#+END_EXAMPLE
#+BEGIN_EXPORT html #+BEGIN_EXPORT html
<script> <script>
console.log("Hello World!") console.log("Hello World!")
@ -80,7 +97,7 @@ this unindented line is outside of the list item
#+BEGIN_QUOTE #+BEGIN_QUOTE
#+BEGIN_EXAMPLE #+BEGIN_EXAMPLE
#+END_QUOTE ,#+END_QUOTE
#+END_EXAMPLE #+END_EXAMPLE
#+END_QUOTE #+END_QUOTE