diff --git a/README.md b/README.md index 73e794fa..dcbedc84 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,18 @@ [GitHub Actions badge]: https://img.shields.io/github/workflow/status/pandoc/lua-filters/CI?logo=github [GitHub Actions]: https://github.com/pandoc/lua-filters/actions +-------------------------------------------------------- + +**DISCLAIMER : This repositoy is not active any more.** + +**See [hk-pandoc-filters](https://github.com/chrisaga/hk-pandoc-filters)** + +**I started this fork almost when pandoc/lus-filters stoped accepting third party contributions.** +**Hence I started a fresh new repository to host my own lua filters.** +**As soon as they'll provide a way to contribute or be referenced, I will apply.** + +-------------------------------------------------------- + A collection of Lua filters for pandoc. To learn about Lua filters, see the [documentation]. diff --git a/column-div/Makefile b/column-div/Makefile new file mode 100644 index 00000000..0d00387e --- /dev/null +++ b/column-div/Makefile @@ -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 -s --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 -s --lua-filter column-div.lua --output $@ $< diff --git a/column-div/README.md b/column-div/README.md new file mode 100644 index 00000000..c16f7673 --- /dev/null +++ b/column-div/README.md @@ -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 + +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. + diff --git a/column-div/column-div.lua b/column-div/column-div.lua new file mode 100644 index 00000000..81adf739 --- /dev/null +++ b/column-div/column-div.lua @@ -0,0 +1,161 @@ +--[[ +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 +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) + + See README.md for details + +Note: You don't need to include multicol latex package to get balanced + columns in latex or pdf. The filter does it. + + I tried to use well known html or latex parameter. + Even if lua doen't like hyphens like in column-count. + +--]] +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 + 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 + 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 + -- process width attribute since Pandoc complains about duplicate + -- style attribute and ignores it. + opt = div.attributes.width + if opt then + style = 'width: ' .. opt .. ';' .. (style or '') + div.attributes.width = nil -- consume attribute + end + div.attributes.style = style .. (div.attributes.style or '') + returned_list = List:new{pandoc.Div(div.content, div.attr)} + end + end + return returned_list +end + +function Meta(meta) + -- Include multicol latex package to get balanced columns in latex or pdf + + includes = [[\usepackage{multicol}]] + + if FORMAT:match 'latex' then + if meta['header-includes'] then + table.insert(meta['header-includes'], pandoc.RawBlock('tex', includes)) + else + meta['header-includes'] = List:new{pandoc.RawBlock('tex', includes)} + end + end + + return meta +end diff --git a/column-div/expected.html b/column-div/expected.html new file mode 100644 index 00000000..82895ad4 --- /dev/null +++ b/column-div/expected.html @@ -0,0 +1,216 @@ + + + + + + + Test + + + + +
+

Test

+
+

column-div test

+

content…

+
+

content…

+
+

Three columns

+
+

content…

+

content…

+

content…

+
+

Two uneven columns

+
+
+

contents…

+
+

contents…

+
+
+

Columns in columns

+
+
+
+

contents…

+
+

contents…

+
+
+
+
+

contents…

+
+

contents…

+
+
+
+
+

contents…

+
+

contents…

+
+
+
+

Columns and Colors

+
+
+

blue content…

+
+

content on red background…

+
+
+
+
+

blue content on red background…

+
+

contents…

+
+
+ + diff --git a/column-div/expected.tex b/column-div/expected.tex new file mode 100644 index 00000000..2909e8d7 --- /dev/null +++ b/column-div/expected.tex @@ -0,0 +1,201 @@ +% Options for packages loaded elsewhere +\PassOptionsToPackage{unicode}{hyperref} +\PassOptionsToPackage{hyphens}{url} +% +\documentclass[ +]{article} +\usepackage{amsmath,amssymb} +\usepackage{lmodern} +\usepackage{iftex} +\ifPDFTeX + \usepackage[T1]{fontenc} + \usepackage[utf8]{inputenc} + \usepackage{textcomp} % provide euro and other symbols +\else % if luatex or xetex + \usepackage{unicode-math} + \defaultfontfeatures{Scale=MatchLowercase} + \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1} +\fi +% Use upquote if available, for straight quotes in verbatim environments +\IfFileExists{upquote.sty}{\usepackage{upquote}}{} +\IfFileExists{microtype.sty}{% use microtype if available + \usepackage[]{microtype} + \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts +}{} +\makeatletter +\@ifundefined{KOMAClassName}{% if non-KOMA class + \IfFileExists{parskip.sty}{% + \usepackage{parskip} + }{% else + \setlength{\parindent}{0pt} + \setlength{\parskip}{6pt plus 2pt minus 1pt}} +}{% if KOMA class + \KOMAoptions{parskip=half}} +\makeatother +\usepackage{xcolor} +\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available +\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}} +\hypersetup{ + pdftitle={Test}, + hidelinks, + pdfcreator={LaTeX via pandoc}} +\urlstyle{same} % disable monospaced font for URLs +\setlength{\emergencystretch}{3em} % prevent overfull lines +\providecommand{\tightlist}{% + \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} +\setcounter{secnumdepth}{-\maxdimen} % remove section numbering +\usepackage{multicol} +\ifLuaTeX + \usepackage{selnolig} % disable illegal ligatures +\fi + +\title{Test} +\author{} +\date{} + +\begin{document} +\maketitle + +\hypertarget{column-div-test}{% +\section{column-div test}\label{column-div-test}} + +content\ldots{} + +\leavevmode\vadjust pre{\hypertarget{thisdivdoesnothing}{}}% +content\ldots{} + +\hypertarget{three-columns}{% +\subsection{Three columns}\label{three-columns}} + +\begin{multicols}{3} + +content\ldots{} + +content\ldots{} + +content\ldots{} + +\end{multicols} + +\hypertarget{two-uneven-columns}{% +\subsection{Two uneven columns}\label{two-uneven-columns}} + +\mbox{ + +\begin{minipage}[b]{0.3\columnwidth} + +contents\ldots{} + +\end{minipage} + +\begin{minipage}[b]{0.7\columnwidth} + +contents\ldots{} + +\end{minipage} + +} + +\hypertarget{columns-in-columns}{% +\subsection{Columns in columns}\label{columns-in-columns}} + +\begin{multicols}{3} + +\mbox{ + +\begin{minipage}[b]{0.2\columnwidth} + +contents\ldots{} + +\end{minipage} + +\begin{minipage}[b]{0.8\columnwidth} + +contents\ldots{} + +\end{minipage} + +} + +\mbox{ + +\begin{minipage}[b]{0.2\columnwidth} + +contents\ldots{} + +\end{minipage} + +\begin{minipage}[b]{0.8\columnwidth} + +contents\ldots{} + +\end{minipage} + +} + +\mbox{ + +\begin{minipage}[b]{0.2\columnwidth} + +contents\ldots{} + +\end{minipage} + +\begin{minipage}[b]{0.8\columnwidth} + +contents\ldots{} + +\end{minipage} + +} + +\end{multicols} + +\hypertarget{columns-and-colors}{% +\subsection{Columns and Colors}\label{columns-and-colors}} + +\mbox{ + +\begin{minipage}{0.4\columnwidth} + +\color{blue} + +blue content\ldots{} + +\end{minipage} + +\colorbox{red}{ + +\begin{minipage}{\dimexpr0.6\columnwidth-4\fboxsep\relax} + +content on red background\ldots{} + +\end{minipage} + +} + +} + +\mbox{ + +\colorbox{red}{ + +\begin{minipage}{\dimexpr0.6\columnwidth-4\fboxsep\relax} + +\color{blue} + +blue content on red background\ldots{} + +\end{minipage} + +} + +\begin{minipage}{0.4\columnwidth} + +contents\ldots{} + +\end{minipage} + +} + +\end{document} diff --git a/column-div/sample.md b/column-div/sample.md new file mode 100644 index 00000000..ccfe7bbb --- /dev/null +++ b/column-div/sample.md @@ -0,0 +1,80 @@ +--- +title : Test + +--- + +# column-div test +content... + +::: {#thisdivdoesnothing} +content... +::: + +## Three columns +::: {.anotherclassname .multicols column-count="3"} +content... + +content... + +content... +::: + +## Two uneven columns +:::::: {.columns} +::: {.column width="30%" valign="b"} +contents... +::: +::: {.column width="70%" valign="b"} +contents... +::: +:::::: + +## Columns in columns + +::::::::: {.multicols column-count="3"} +:::::: {.columns} +::: {.column width="20%" valign="b"} +contents... +::: +::: {.column width="80%" valign="b"} +contents... +::: +:::::: +:::::: {.columns} +::: {.column width="20%" valign="b"} +contents... +::: +::: {.column width="80%" valign="b"} +contents... +::: +:::::: +:::::: {.columns} +::: {.column width="20%" valign="b"} +contents... +::: +::: {.column width="80%" valign="b"} +contents... +::: +:::::: +::::::::: + + +## Columns and Colors + +:::::: {.columns} +::: {.column width="40%" color="blue"} +blue content... +::: +::: {.column width="60%" background-color="red"} +content on red background... +::: +:::::: + +:::::: {.columns} +::: {.column width="60%" color="blue" background-color="red"} +blue content on red background... +::: +::: {.column width="40%" } +contents... +::: +:::::: \ No newline at end of file