Commit graph

7 commits

Author SHA1 Message Date
Niklas Fasching
5464ab37d2 Fix race condition surrounding global orgWriter
Since writers are normally only used synchronously (i.e. to write one document
at a time), we don't guard modifications to their internal
state (e.g. temporarily replacing the string.Builder in WriteNodesAsString)
against race conditions.

The package global `orgWriter` and corresponding use cases of it (`org.String`,
`$node.String`) break that pattern - the writer is potentially used from
multiple go routines at the same time. This results in race conditions that
manifest as error messages like e.g.

    could not write output: runtime error: invalid memory address or nil pointer dereference. Using unrendered content.

Additionally, since we catch panics in `Document.Write`, the corresponding
stack trace is lost and dependents of go-org never know what hit them.

As using a writer across simultaneously across go routines is not a standard
pattern, we'll sync the use of the global `orgWriter` instead of trying to make
the actual writer threadsafe; less code noise for the common use case.
2023-03-12 11:28:55 +01:00
Niklas Fasching
b61e49eb85 Preserve whitespace (indentation) inside paragraphs
We want original whitespace to be rendered in some cases (e.g. verse
blocks). This requires information about the original whitespace to be
preserved during paragraph parsing. As html ignores (collapses) whitespace by
default we don't have to adapt the html writer and can just selectively enable
rendering of the preseverved whitespace wherever we want it using
css (white-space: pre).

To differentiate meaningful whitespace from document structure based
indentation (i.e. list item base indentation) we need to introduce
document.baseLvl. A paragraph by itself does not have enough information to
differentiate both kinds of whitespace and needs this information as context
[0].

As we're already touching list indentation i went along and improved (fixed?)
descriptive list item indentation rendering in the org writer (it should match
emacs tab behavior - i.e. indent subsequent lines up to the `:: `).

[0] e.g. list items can contain blank lines - a paragraph starting with a blank
line would not know that it is part of a list item / has a base indentation -
the blank line would suggest a baseLvl of 0.
2019-12-22 14:17:14 +01:00
Niklas Fasching
9a0a9c11eb Export WriteNodesAsString on writer interface
WriteNodesAsString is simple enough to implement but exposing it is helpful in
the implementation of extending writers and we don't aim to keep writer a small
interface so let's expose it.
2019-11-02 23:44:16 +01:00
Niklas Fasching
bd33e8885e Add String() method to Node interface
Being able to very easily get the original [1] Org mode content seems like
something that will come up quite often and is very little code.

[1] it's not really the original content, but rather the pretty printed version
of that - as the semantics don't change it shouldn't matter.
2019-01-06 20:50:02 +01:00
Niklas Fasching
6637e63892 Fix multiline emphasis
I didn't have a test case for this and broke it when i introduced Line nodes to
support printing back to org mode. Oops
2018-12-10 17:53:12 +01:00
Niklas Fasching
ed8764940f Fix paragraphs: Empty lines separate paragraphs
Somehow i thought it was 2 empty lines rather than 1 - makes more sense this
way... :D
2018-12-03 01:44:35 +01:00
Niklas Fasching
fc982125c9 Restructure directory layout: org subpackage 2018-12-02 18:37:55 +01:00
Renamed from paragraph.go (Browse further)