Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add complex-paragraphs #176

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions complex-paragraphs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.PHONY: test

PANDOC_COMMAND = pandoc -L complex-paragraphs.lua -t native sample.md

test:
TESTED_FORMAT=context $(PANDOC_COMMAND) -o tests/output.context \
&& diff tests/output.context tests/expected.context
TESTED_FORMAT=openxml $(PANDOC_COMMAND) -o tests/output.docx \
&& diff tests/output.docx tests/expected.docx
TESTED_FORMAT=latex $(PANDOC_COMMAND) -o tests/output.latex \
&& diff tests/output.latex tests/expected.latex \
&& rm tests/output.*
44 changes: 44 additions & 0 deletions complex-paragraphs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Compose complex paragraphs

## Definition

Complex paragraphs are paragraphs composed of different blocks:
normal text, quotations, tables,...

This concept makes sense only if you want to indent all paragraphs
by default, including paragraphs beginning after a quotation block
or a table, for instance. In that case, unindenting a text block means
that it is not to be seen as a new paragraph, but as a the
continuation of the previous text block that has been interrupted by
another block. If you want to prevent the indentation of all
paragraphs following certain types of blocks, please consider using
the [first-line-indent] filter instead.

[first-line-indent]: https://github.com/pandoc/lua-filters/tree/master/first-line-indent

## How to use this filter

To create a complex paragraph in your MD file, simply wrap its
components in a Div with class `.complex-paragraph`. Some
examples are given in `sample.md`.

## What it does

For the moment, it only prevents the indentation of text blocks
other than the first one. More features can be requested.

The Div itself is not removed from the AST, so that you can
pass it through other filters.

## Output formats

The following output formats are supported:

* context
* docx
* latex

Other formats can be added. PRs are welcome. If you prefer to
submit an issue instead, please specify what code should be
used in the targeted format in order to achieve what this filter
does.
75 changes: 75 additions & 0 deletions complex-paragraphs/complex-paragraphs.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
--[[
complex-paragraphs – compose complex paragraphs

Copyright © 2021 Bastien Dumont

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
]]

local is_after_first_block
local RAW_ATTRIBUTE

if FORMAT == 'native' then
RAW_ATTRIBUTE = pandoc.system.environment().TESTED_FORMAT
elseif FORMAT == 'docx' then
RAW_ATTRIBUTE = 'openxml'
elseif FORMAT == 'context' or FORMAT == 'latex' then
RAW_ATTRIBUTE = FORMAT
else
error(FORMAT ..
' output not supported by complex-paragraphs.lua\n')
end

local function make_noindent_code()
if RAW_ATTRIBUTE == 'context' then
return '\\noindentation{}'
elseif RAW_ATTRIBUTE == 'openxml' then
return '<w:pPr>' ..
'<w:pStyle w:val="BodyText"/>' ..
'<w:ind w:hanging="0"/>' ..
'<w:rPr></w:rPr></w:pPr>'
elseif RAW_ATTRIBUTE == 'latex' then
return '\\noindent{}'
end
end

local noindent_rawinline =
pandoc.RawInline(RAW_ATTRIBUTE, make_noindent_code())

local function turn_to_nonindented_textblock(para)
para.c:insert(1, noindent_rawinline)
end

local function unindent_paragraphs_after_first_block_in_complex_para(blocks)
for i = 1, #blocks do
block = blocks[i]
if block.t == 'Para' and is_after_first_block then
turn_to_nonindented_textblock(block)
elseif block.t == 'Div' then
unindent_paragraphs_after_first_block_in_complex_para(block.content)
end
is_after_first_block = true
end
end

local function turn_to_complex_paragraph(div)
unindent_paragraphs_after_first_block_in_complex_para(div.content)
end

function Div(div)
if div.classes[1] == 'complex-paragraph' then
is_after_first_block = false
turn_to_complex_paragraph(div)
return div
end
end
36 changes: 36 additions & 0 deletions complex-paragraphs/sample.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
_Let's begin with a simple test case:_

::: {.complex-paragraph}
When Clovis came in front of the soldier, he smashed his head with
his axe, saying:

> Remember the vase at Soissons!

This was an allusion to the vase that the soldier had broken so that
it could not be returned to Remigius.
:::

_It is not necessary for the first block to be normal text:_

::: {.complex-paragraph}
> Remember the vase at Soissons!

This was an allusion to the vase that the soldier had broken so that
it could not be returned to Remigius.
:::

_Nested Divs are supported:_

::: {.complex-paragraph}
::: {.narrative}
When Clovis came in front of the soldier, he smashed his head with
his axe, saying:

> Remember the vase at Soissons!
:::
::: {.explanation}
This was an allusion to the vase that the soldier had broken so that
it could not be returned to Remigius.
:::
:::

19 changes: 19 additions & 0 deletions complex-paragraphs/tests/expected.context
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[Para [Emph [Str "Let\8217s",Space,Str "begin",Space,Str "with",Space,Str "a",Space,Str "simple",Space,Str "test",Space,Str "case:"]]
,Div ("",["complex-paragraph"],[])
[Para [Str "When",Space,Str "Clovis",Space,Str "came",Space,Str "in",Space,Str "front",Space,Str "of",Space,Str "the",Space,Str "soldier,",Space,Str "he",Space,Str "smashed",Space,Str "his",Space,Str "head",Space,Str "with",SoftBreak,Str "his",Space,Str "axe,",Space,Str "saying:"]
,BlockQuote
[Para [Str "Remember",Space,Str "the",Space,Str "vase",Space,Str "at",Space,Str "Soissons!"]]
,Para [RawInline (Format "context") "\\noindentation{}",Str "This",Space,Str "was",Space,Str "an",Space,Str "allusion",Space,Str "to",Space,Str "the",Space,Str "vase",Space,Str "that",Space,Str "the",Space,Str "soldier",Space,Str "had",Space,Str "broken",Space,Str "so",Space,Str "that",SoftBreak,Str "it",Space,Str "could",Space,Str "not",Space,Str "be",Space,Str "returned",Space,Str "to",Space,Str "Remigius."]]
,Para [Emph [Str "It",Space,Str "is",Space,Str "not",Space,Str "necessary",Space,Str "for",Space,Str "the",Space,Str "first",Space,Str "block",Space,Str "to",Space,Str "be",Space,Str "normal",Space,Str "text:"]]
,Div ("",["complex-paragraph"],[])
[BlockQuote
[Para [Str "Remember",Space,Str "the",Space,Str "vase",Space,Str "at",Space,Str "Soissons!"]]
,Para [RawInline (Format "context") "\\noindentation{}",Str "This",Space,Str "was",Space,Str "an",Space,Str "allusion",Space,Str "to",Space,Str "the",Space,Str "vase",Space,Str "that",Space,Str "the",Space,Str "soldier",Space,Str "had",Space,Str "broken",Space,Str "so",Space,Str "that",SoftBreak,Str "it",Space,Str "could",Space,Str "not",Space,Str "be",Space,Str "returned",Space,Str "to",Space,Str "Remigius."]]
,Para [Emph [Str "Nested",Space,Str "Divs",Space,Str "are",Space,Str "supported:"]]
,Div ("",["complex-paragraph"],[])
[Div ("",["narrative"],[])
[Para [Str "When",Space,Str "Clovis",Space,Str "came",Space,Str "in",Space,Str "front",Space,Str "of",Space,Str "the",Space,Str "soldier,",Space,Str "he",Space,Str "smashed",Space,Str "his",Space,Str "head",Space,Str "with",SoftBreak,Str "his",Space,Str "axe,",Space,Str "saying:"]
,BlockQuote
[Para [Str "Remember",Space,Str "the",Space,Str "vase",Space,Str "at",Space,Str "Soissons!"]]]
,Div ("",["explanation"],[])
[Para [RawInline (Format "context") "\\noindentation{}",Str "This",Space,Str "was",Space,Str "an",Space,Str "allusion",Space,Str "to",Space,Str "the",Space,Str "vase",Space,Str "that",Space,Str "the",Space,Str "soldier",Space,Str "had",Space,Str "broken",Space,Str "so",Space,Str "that",SoftBreak,Str "it",Space,Str "could",Space,Str "not",Space,Str "be",Space,Str "returned",Space,Str "to",Space,Str "Remigius."]]]]
19 changes: 19 additions & 0 deletions complex-paragraphs/tests/expected.docx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[Para [Emph [Str "Let\8217s",Space,Str "begin",Space,Str "with",Space,Str "a",Space,Str "simple",Space,Str "test",Space,Str "case:"]]
,Div ("",["complex-paragraph"],[])
[Para [Str "When",Space,Str "Clovis",Space,Str "came",Space,Str "in",Space,Str "front",Space,Str "of",Space,Str "the",Space,Str "soldier,",Space,Str "he",Space,Str "smashed",Space,Str "his",Space,Str "head",Space,Str "with",SoftBreak,Str "his",Space,Str "axe,",Space,Str "saying:"]
,BlockQuote
[Para [Str "Remember",Space,Str "the",Space,Str "vase",Space,Str "at",Space,Str "Soissons!"]]
,Para [RawInline (Format "openxml") "<w:pPr><w:pStyle w:val=\"BodyText\"/><w:ind w:hanging=\"0\"/><w:rPr></w:rPr></w:pPr>",Str "This",Space,Str "was",Space,Str "an",Space,Str "allusion",Space,Str "to",Space,Str "the",Space,Str "vase",Space,Str "that",Space,Str "the",Space,Str "soldier",Space,Str "had",Space,Str "broken",Space,Str "so",Space,Str "that",SoftBreak,Str "it",Space,Str "could",Space,Str "not",Space,Str "be",Space,Str "returned",Space,Str "to",Space,Str "Remigius."]]
,Para [Emph [Str "It",Space,Str "is",Space,Str "not",Space,Str "necessary",Space,Str "for",Space,Str "the",Space,Str "first",Space,Str "block",Space,Str "to",Space,Str "be",Space,Str "normal",Space,Str "text:"]]
,Div ("",["complex-paragraph"],[])
[BlockQuote
[Para [Str "Remember",Space,Str "the",Space,Str "vase",Space,Str "at",Space,Str "Soissons!"]]
,Para [RawInline (Format "openxml") "<w:pPr><w:pStyle w:val=\"BodyText\"/><w:ind w:hanging=\"0\"/><w:rPr></w:rPr></w:pPr>",Str "This",Space,Str "was",Space,Str "an",Space,Str "allusion",Space,Str "to",Space,Str "the",Space,Str "vase",Space,Str "that",Space,Str "the",Space,Str "soldier",Space,Str "had",Space,Str "broken",Space,Str "so",Space,Str "that",SoftBreak,Str "it",Space,Str "could",Space,Str "not",Space,Str "be",Space,Str "returned",Space,Str "to",Space,Str "Remigius."]]
,Para [Emph [Str "Nested",Space,Str "Divs",Space,Str "are",Space,Str "supported:"]]
,Div ("",["complex-paragraph"],[])
[Div ("",["narrative"],[])
[Para [Str "When",Space,Str "Clovis",Space,Str "came",Space,Str "in",Space,Str "front",Space,Str "of",Space,Str "the",Space,Str "soldier,",Space,Str "he",Space,Str "smashed",Space,Str "his",Space,Str "head",Space,Str "with",SoftBreak,Str "his",Space,Str "axe,",Space,Str "saying:"]
,BlockQuote
[Para [Str "Remember",Space,Str "the",Space,Str "vase",Space,Str "at",Space,Str "Soissons!"]]]
,Div ("",["explanation"],[])
[Para [RawInline (Format "openxml") "<w:pPr><w:pStyle w:val=\"BodyText\"/><w:ind w:hanging=\"0\"/><w:rPr></w:rPr></w:pPr>",Str "This",Space,Str "was",Space,Str "an",Space,Str "allusion",Space,Str "to",Space,Str "the",Space,Str "vase",Space,Str "that",Space,Str "the",Space,Str "soldier",Space,Str "had",Space,Str "broken",Space,Str "so",Space,Str "that",SoftBreak,Str "it",Space,Str "could",Space,Str "not",Space,Str "be",Space,Str "returned",Space,Str "to",Space,Str "Remigius."]]]]
19 changes: 19 additions & 0 deletions complex-paragraphs/tests/expected.latex
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[Para [Emph [Str "Let\8217s",Space,Str "begin",Space,Str "with",Space,Str "a",Space,Str "simple",Space,Str "test",Space,Str "case:"]]
,Div ("",["complex-paragraph"],[])
[Para [Str "When",Space,Str "Clovis",Space,Str "came",Space,Str "in",Space,Str "front",Space,Str "of",Space,Str "the",Space,Str "soldier,",Space,Str "he",Space,Str "smashed",Space,Str "his",Space,Str "head",Space,Str "with",SoftBreak,Str "his",Space,Str "axe,",Space,Str "saying:"]
,BlockQuote
[Para [Str "Remember",Space,Str "the",Space,Str "vase",Space,Str "at",Space,Str "Soissons!"]]
,Para [RawInline (Format "latex") "\\noindent{}",Str "This",Space,Str "was",Space,Str "an",Space,Str "allusion",Space,Str "to",Space,Str "the",Space,Str "vase",Space,Str "that",Space,Str "the",Space,Str "soldier",Space,Str "had",Space,Str "broken",Space,Str "so",Space,Str "that",SoftBreak,Str "it",Space,Str "could",Space,Str "not",Space,Str "be",Space,Str "returned",Space,Str "to",Space,Str "Remigius."]]
,Para [Emph [Str "It",Space,Str "is",Space,Str "not",Space,Str "necessary",Space,Str "for",Space,Str "the",Space,Str "first",Space,Str "block",Space,Str "to",Space,Str "be",Space,Str "normal",Space,Str "text:"]]
,Div ("",["complex-paragraph"],[])
[BlockQuote
[Para [Str "Remember",Space,Str "the",Space,Str "vase",Space,Str "at",Space,Str "Soissons!"]]
,Para [RawInline (Format "latex") "\\noindent{}",Str "This",Space,Str "was",Space,Str "an",Space,Str "allusion",Space,Str "to",Space,Str "the",Space,Str "vase",Space,Str "that",Space,Str "the",Space,Str "soldier",Space,Str "had",Space,Str "broken",Space,Str "so",Space,Str "that",SoftBreak,Str "it",Space,Str "could",Space,Str "not",Space,Str "be",Space,Str "returned",Space,Str "to",Space,Str "Remigius."]]
,Para [Emph [Str "Nested",Space,Str "Divs",Space,Str "are",Space,Str "supported:"]]
,Div ("",["complex-paragraph"],[])
[Div ("",["narrative"],[])
[Para [Str "When",Space,Str "Clovis",Space,Str "came",Space,Str "in",Space,Str "front",Space,Str "of",Space,Str "the",Space,Str "soldier,",Space,Str "he",Space,Str "smashed",Space,Str "his",Space,Str "head",Space,Str "with",SoftBreak,Str "his",Space,Str "axe,",Space,Str "saying:"]
,BlockQuote
[Para [Str "Remember",Space,Str "the",Space,Str "vase",Space,Str "at",Space,Str "Soissons!"]]]
,Div ("",["explanation"],[])
[Para [RawInline (Format "latex") "\\noindent{}",Str "This",Space,Str "was",Space,Str "an",Space,Str "allusion",Space,Str "to",Space,Str "the",Space,Str "vase",Space,Str "that",Space,Str "the",Space,Str "soldier",Space,Str "had",Space,Str "broken",Space,Str "so",Space,Str "that",SoftBreak,Str "it",Space,Str "could",Space,Str "not",Space,Str "be",Space,Str "returned",Space,Str "to",Space,Str "Remigius."]]]]