-
-
Notifications
You must be signed in to change notification settings - Fork 170
A lua filter enabling multiple columns in Latex, PDF, and HTML documents #191
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
base: master
Are you sure you want to change the base?
Changes from 11 commits
af727e8
5296ecd
9d650d4
2cc9018
c887e85
f4e7a64
9918551
f9167f8
cfc9479
f3ede85
cf96742
3371914
47ea5cd
580baa9
ce4993c
8fc1044
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
DIFF ?= diff --strip-trailing-cr -u | ||
|
||
.PHONY: test | ||
|
||
test: test_latex test_html | ||
|
||
test_html: sample.md expected.html column-div.lua | ||
@pandoc -s --lua-filter column-div.lua --to=html $< \ | ||
| $(DIFF) expected.html - | ||
|
||
test_latex: sample.md expected.tex column-div.lua | ||
@pandoc --lua-filter column-div.lua --to=latex $< \ | ||
| $(DIFF) expected.tex - | ||
|
||
expected.html: sample.md column-div.lua | ||
pandoc -s --lua-filter column-div.lua --output $@ $< | ||
|
||
expected.tex: sample.md column-div.lua | ||
pandoc --lua-filter column-div.lua --output $@ $< |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
--- | ||
title: "Column Div - leverage Pandoc native divs to make columns | ||
and other things" | ||
author: "Christophe Agathon" | ||
--- | ||
|
||
Column Div | ||
======= | ||
|
||
Columns and other things with Pandoc's markdown | ||
|
||
This Lua filter for Pandoc improves Pandoc's Div usage.Especially | ||
fenced divs witten in Pandocs markdown. | ||
|
||
v1.0. Copyright: © 2021 Christophe Agathon | ||
<[email protected]> | ||
License: MIT - see LICENSE file for details. | ||
|
||
Introduction | ||
------------ | ||
Pandoc fenced divs can be very powerful allowing providing, in | ||
theory many document formating possibilities. Unfortunately, plain | ||
Panfoc processing doesn't make full adventage of it and discards | ||
some formating in HTML outputs and most of it in Latex outputs. | ||
|
||
Multiple columns in document are only partialy accessible in | ||
Beamer (not plain Latex) and HTML outputs. | ||
|
||
As a result, it's not possible to render fancy multi columns | ||
PDF document from markdown sources. | ||
|
||
The main purpose of this filter is to make it possible and give | ||
similar formating features for both Latex/PDF and HTML outputs. | ||
|
||
My guidelines are : | ||
|
||
1) Use Pandoc divs like many already have proposed for uneven and even columns | ||
2) Same functionalities and rendering in HTML and Latex+PDF | ||
3) Mess the least possible with plain Pandoc processing which is quite OK already for HTML (miss only column-count for even columning). | ||
4) Allow users to use unknown Latex environments from exotic packages if they wish, provided they include them in the preamble. | ||
|
||
|
||
Usage | ||
----- | ||
|
||
### Basic usage | ||
|
||
Copy `column-div.lua` in your document folder or in your pandoc | ||
data directory (details in | ||
[Pandoc's manual](https://pandoc.org/MANUAL.html#option--lua-filter)). | ||
Run it on your document with a `--luafilter` option: | ||
|
||
```bash | ||
pandoc --luafilter column-div.lua SOURCE.md -o OUTPUT.pdf | ||
|
||
``` | ||
|
||
or specify it in a defaults file (details in | ||
[Pandoc's manual](https://pandoc.org/MANUAL.html#option--defaults)). | ||
|
||
This will generate consistent HTML, Latex and PDF outputs from | ||
Pandoc markdown files. | ||
|
||
### Formating the document | ||
|
||
Everything is done with Pandoc's fenced divs with class names and | ||
attributes. The attributes are similar to those from HTML styling and/or | ||
Latex. | ||
|
||
#### Multiple even columns | ||
For Latex and PDF output, you will need to call the multicol | ||
package. This can be done un the YAML header. | ||
|
||
**Example:** | ||
|
||
```markdown | ||
--- | ||
header-includes: | ||
- | | ||
```{=latex} | ||
\usepackage{multicol} | ||
|
||
``` | ||
--- | ||
|
||
Some regular text | ||
|
||
:::: {.multicols column-count="2"} | ||
Some text formatted on 2 columns | ||
:::: | ||
``` | ||
|
||
* Latex output is done with `multicols` environment. | ||
* HTML output uses `style="column-count: 2"` on a div block. | ||
|
||
#### Uneven columns | ||
|
||
No specific Latex package are needed. We use Nested Pandoc divs in | ||
the same way that columns and column environments are used in | ||
Beamer/Latex. | ||
|
||
**Example:** | ||
|
||
```markdown | ||
|
||
:::::::: {.columns} | ||
:::: {.column width="20%" valign="c"} | ||
Some text or image using 20% of the page width. | ||
:::: | ||
:::: {.column width="80%" valign="c"} | ||
Some text or image using 80% of the page with. | ||
:::: | ||
:::::::: | ||
``` | ||
|
||
* Beamer/Latex output is based on columns and column environments | ||
* Plain Latex (and PDF) rendering use minipage environments | ||
* HTML rendering is not affected by this filter since Pandoc do it | ||
well already (based on divs with `width` attributes). | ||
|
||
#### Other usages | ||
|
||
For HTML outputs, you already can create divs with whatever class names you | ||
like and style them with `style=" … "` attributes. This is | ||
processed by Pandoc and has nothing to do with this filter. | ||
|
||
This filter allows to do the same in Latex (and PDF). | ||
You can create whatever environment you need. The environment name is the | ||
class name given to the fenced div. In case of multiple class names, the | ||
first one is used. Other are ignored but allowed to help you to maintain | ||
a single markdown source for PDF and HTML outputs. | ||
The `data-latex=" … "` attribute allows you to pass options and | ||
parameters to the `\begin` environment instruction. | ||
|
||
To Do | ||
----- | ||
|
||
Others multi column features could be implemented as column | ||
spacing, rules, etc. | ||
|
||
Since Pandoc does a very good job with the `width` styling | ||
attribute to implement variable column width, it could easily | ||
support HTML even column via the `column-count` attribute. | ||
|
||
Contributing | ||
------------ | ||
|
||
PRs welcome. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
--[[ | ||
column-div - leverage Pandoc native divs to make balanced and unbalanced column | ||
and other things based on class name and attributes. | ||
|
||
Copyright: © 2021 Christophe Agathon <[email protected]> | ||
License: MIT – see LICENSE file for details | ||
|
||
Credits: Romain Lesur and Yihui Xie for the original column filter | ||
implementation (output in beamer format). | ||
|
||
Output: latex, pdf, html | ||
|
||
Usage: classname attributes | ||
balanced columns .columns column-count | ||
columns(container) .columns | ||
column(each column) .column width(percent) valign(t|c|b) | ||
other divs .<somename> data-latex | ||
|
||
See README.md for details | ||
|
||
Note: You need to include multicol latex package to get balanced columns | ||
in latex or pdf | ||
I tried to use well known html or latex parameter. | ||
Even if lua doen't like hyphens like in column-count. | ||
|
||
Bugs: * html rendering throws a warning [WARNING] Ignoring duplicate attribute style="width:60%;". | ||
when widht AND color are set and totally ignore the width | ||
attribute. Don't know if this bug is mine | ||
--]] | ||
local List = require 'pandoc.List' | ||
|
||
function Div(div) | ||
local options = '' | ||
local env = '' | ||
local returned_list | ||
local begin_env | ||
local end_env | ||
local opt | ||
|
||
-- if the div has no class, the object is left unchanged | ||
-- if the div has no class but an id, div.classes ~= nil | ||
-- TODO: use a div with no class to build a 'scope' in Latex | ||
-- usefull for user who would throw inline Latex code and limit it's | ||
-- effect. | ||
if not div.classes or #div.classes == 0 then return nil end | ||
|
||
-- if the format is latex then do minipage and others (like multicol) | ||
if FORMAT:match 'latex' then | ||
-- build the returned list of blocks | ||
if div.classes:includes('column') then | ||
env = 'column' | ||
opt = div.attributes.width | ||
if opt then | ||
local width=tonumber(string.match(opt,'(%f[%d]%d[,.%d]*%f[%D])%%'))/100 | ||
options = '{' .. tostring(width) | ||
if div.attributes['background-color'] then | ||
-- fix the width for the \colorbox | ||
options = '{\\dimexpr' .. tostring(width) | ||
.. '\\columnwidth-4\\fboxsep\\relax}' | ||
else | ||
options = '{' .. tostring(width) .. '\\columnwidth}' | ||
end | ||
end | ||
|
||
opt = div.attributes.valign | ||
if opt then options = '[' .. opt .. ']' .. options end | ||
|
||
begin_env = List:new{pandoc.RawBlock('tex', | ||
'\\begin{minipage}' .. options)} | ||
end_env = List:new{pandoc.RawBlock('tex', '\\end{minipage}')} | ||
|
||
-- add support for color | ||
opt = div.attributes.color | ||
if opt then | ||
begin_env = begin_env .. List:new{pandoc.RawBlock('tex', | ||
'\\color{' .. opt .. '}')} | ||
div.attributes.color = nil -- consume attribute | ||
end | ||
|
||
opt = div.attributes['background-color'] | ||
if opt then | ||
begin_env = List:new{pandoc.RawBlock('tex', | ||
'\\colorbox{' .. opt .. '}{')} | ||
.. begin_env | ||
end_env = end_env .. List:new{pandoc.RawBlock('tex', '}')} | ||
div.attributes['background-color'] = nil -- consume attribute | ||
end | ||
|
||
returned_list = begin_env .. div.content .. end_env | ||
|
||
elseif div.classes:includes('columns') then | ||
-- it turns-out that asimple Tex \mbox do the job | ||
begin_env = List:new{pandoc.RawBlock('tex', '\\mbox{')} | ||
end_env = List:new{pandoc.RawBlock('tex', '}')} | ||
returned_list = begin_env .. div.content .. end_env | ||
|
||
else | ||
-- other environments ex: multicols | ||
if div.classes:includes('multicols') then | ||
env = 'multicols' | ||
-- process supported options | ||
opt = div.attributes['column-count'] | ||
if opt then options = '{' .. opt .. '}' end | ||
--[[ This functionality will be moved in another filter since it can't be consistent with the positionless classname requirement | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. c.f. Comment on L151. |
||
else | ||
-- Latex skilled users can use arbitrary environments passed as | ||
-- the first (and only signifiant) class name. | ||
env = div.classes[1] | ||
-- default if no known options | ||
if options == '' and div.attributes['data-latex'] then | ||
options = div.attributes['data-latex'] | ||
end | ||
--]] | ||
end | ||
|
||
begin_env = List:new{pandoc.RawBlock('tex', | ||
'\\begin{' .. env .. '}' .. options)} | ||
end_env = List:new{pandoc.RawBlock('tex', '\\end{' .. env .. '}')} | ||
returned_list = begin_env .. div.content .. end_env | ||
end | ||
|
||
-- if the format is html add what is not already done by plain pandoc | ||
elseif FORMAT:match 'html' then | ||
local style | ||
-- add support for multi columns | ||
opt = div.attributes['column-count'] | ||
if opt then | ||
-- add column-count to style | ||
style = 'column-count: ' .. opt .. ';' .. (style or '') | ||
div.attributes['column-count'] = nil | ||
-- column-count is "consumed" by the filter otherwise it would appear as | ||
-- data-column-count="…" in the resulting document | ||
end | ||
-- add support for color | ||
opt = div.attributes.color | ||
if opt then | ||
-- add color to style | ||
style = 'color: ' .. opt .. ';' .. (style or '') | ||
div.attributes.color = nil -- consume attribute | ||
end | ||
opt = div.attributes['background-color'] | ||
if opt then | ||
-- add color to style | ||
style = 'background-color: ' .. opt .. ';' .. (style or '') | ||
div.attributes['background-color'] = nil -- consume attribute | ||
end | ||
-- if we have style then build returned list | ||
if style then | ||
div.attributes.style = style .. (div.attributes.style or '') | ||
returned_list = List:new{pandoc.Div(div.content, div.attr)} | ||
--returned_list = List:new{pandoc.Div(div.content)} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I realize I'm reviewing this still in Draft mode so it might be too early, but just as a note for when this is ready for review lets cleanup the code so there are not instances of commented out bits without explanation for why the logic is not transparent. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Of course ! |
||
end | ||
end | ||
return returned_list | ||
end |
Uh oh!
There was an error while loading. Please reload this page.