From ebdd2c5c026531b6ffa23403985063483ea994b4 Mon Sep 17 00:00:00 2001 From: jdutant <34026710+jdutant@users.noreply.github.com> Date: Fri, 19 Mar 2021 17:00:44 +0000 Subject: [PATCH 1/3] description --- first-line-indent/LICENSE | 21 +++++++++++++ first-line-indent/README.md | 50 +++++++++++++++++++++++++++++++ first-line-indent/indentation.lua | 26 ++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 first-line-indent/LICENSE create mode 100644 first-line-indent/README.md create mode 100644 first-line-indent/indentation.lua diff --git a/first-line-indent/LICENSE b/first-line-indent/LICENSE new file mode 100644 index 00000000..b4e8923c --- /dev/null +++ b/first-line-indent/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Julien Dutant + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/first-line-indent/README.md b/first-line-indent/README.md new file mode 100644 index 00000000..62c9f203 --- /dev/null +++ b/first-line-indent/README.md @@ -0,0 +1,50 @@ +--- +title: "First Line Indent - First-line idented paragraphs + in Pandoc's markdown" +author: "Julien Dutant" +--- + +Indentation +======= + +Paragraph indentation control in pandoc's markdown. + +This Lua filter for Pandoc prepares document for separating +paragraphs with a first-line indentation rather than vertical +whitespace. + +v1.0. Copyright: © 2021 Julien Dutant +License: MIT - see LICENSE file for details. + +Introduction +------------ + +Pandoc's default output templates separate paragraphs +with vertical whitespace rather than an idented first line (a style +that is common on the web but uncommon in books). This filter prepares +documents for outputs with the first-line ident style instead. + +1) In some typographic traditions (*e.g.* English) when the first-line +indent style is used paragraphs are *not* indented after headings, +blockquotes, code blocks and lists. By default the filter follows this +convention and removes (typically unwanted) indent from paragraphs +that follow blockquotes, code blocks, lists. The user can override +this by inserting `\indent` at the beginning of a paragraph that does +require a first-line indent even though it is after a list, quote or +code-block. 2) Other typographic traditions (*e.g.* French) indent all +paragraphs, even after headings, blockquotes, code blocks and lists. +The filter offers that option. (TO DO: and tries to make a sensible +guess based on language specification?) 3) the filter generates +default LaTeX / HTML outputs with first-line indent style. That +default behaviour can be deactivated in case the user prefers to +provide their own templates that handle first-line indent formatting. +The filter does this by inserting code in the document's metadata +`header-includes` field. It will still work if a document has its own +`header-includes` field, but not if a `header-includes` value is given +to Pandoc via the command line. + +Other outputs (docx, ...) are not covered. + +Usage +----- + diff --git a/first-line-indent/indentation.lua b/first-line-indent/indentation.lua new file mode 100644 index 00000000..df228a01 --- /dev/null +++ b/first-line-indent/indentation.lua @@ -0,0 +1,26 @@ +--[[-- # First Line Indent - First-line idented paragraphs + in Pandoc's markdown. +@author Julien Dutant +@copyright 2021 Julien Dutant +@license MIT - see LICENSE file for details. +@release 0.1 +]] + +-- # Parameters + +--- Options map, including defaults. +-- @param header_code boolean whether to include support code in the header (true). +-- @param convert_rules boolean whether to convert horinzontal rules to half length. +local options = { + header_code = true, + convert_rules = true, +} + +--- list of formats for which we process the filter. +local target_formats = { + 'html.*', + 'latex', + 'jats', + 'native', + 'markdown' +} From 9d46f97d5d46b70050a178844d36dcbd9fe8a0a3 Mon Sep 17 00:00:00 2001 From: jdutant <34026710+jdutant@users.noreply.github.com> Date: Sun, 21 Mar 2021 15:34:08 +0000 Subject: [PATCH 2/3] first working version --- first-line-indent/Makefile | 19 +++ first-line-indent/README.md | 72 ++++++----- first-line-indent/expected.tex | 66 ++++++++++ first-line-indent/first-line-indent.lua | 155 ++++++++++++++++++++++++ first-line-indent/indentation.lua | 26 ---- first-line-indent/sample.md | 49 ++++++++ first-line-indent/targethtmlcode.html | 38 ++++++ first-line-indent/test.tex | 153 +++++++++++++++++++++++ 8 files changed, 524 insertions(+), 54 deletions(-) create mode 100644 first-line-indent/Makefile create mode 100644 first-line-indent/expected.tex create mode 100644 first-line-indent/first-line-indent.lua delete mode 100644 first-line-indent/indentation.lua create mode 100644 first-line-indent/sample.md create mode 100644 first-line-indent/targethtmlcode.html create mode 100644 first-line-indent/test.tex diff --git a/first-line-indent/Makefile b/first-line-indent/Makefile new file mode 100644 index 00000000..09fdfcfe --- /dev/null +++ b/first-line-indent/Makefile @@ -0,0 +1,19 @@ +DIFF ?= diff --strip-trailing-cr -u + +.PHONY: test + +test: test_latex + +test_html: sample.md expected.html first-line-indent.lua + @pandoc --lua-filter first-line-indent.lua --to=html $< \ + | $(DIFF) expected.html - + +test_latex: sample.md expected.tex first-line-indent.lua + @pandoc --lua-filter first-line-indent.lua --to=latex $< \ + | $(DIFF) expected.tex - + +expected.html: sample.md first-line-indent.lua + pandoc --lua-filter first-line-indent.lua --output $@ $< + +expected.tex: sample.md first-line-indent.lua + pandoc --lua-filter first-line-indent.lua --output $@ $< diff --git a/first-line-indent/README.md b/first-line-indent/README.md index 62c9f203..d43d5482 100644 --- a/first-line-indent/README.md +++ b/first-line-indent/README.md @@ -9,9 +9,9 @@ Indentation Paragraph indentation control in pandoc's markdown. -This Lua filter for Pandoc prepares document for separating -paragraphs with a first-line indentation rather than vertical -whitespace. +This Lua filter for Pandoc improves Pandoc's first-line ident +paragraph separation style by removing first-line idents after +blockquotes, lists and code blocks unless specified otherwise. v1.0. Copyright: © 2021 Julien Dutant License: MIT - see LICENSE file for details. @@ -19,31 +19,47 @@ License: MIT - see LICENSE file for details. Introduction ------------ -Pandoc's default output templates separate paragraphs -with vertical whitespace rather than an idented first line (a style -that is common on the web but uncommon in books). This filter prepares -documents for outputs with the first-line ident style instead. - -1) In some typographic traditions (*e.g.* English) when the first-line -indent style is used paragraphs are *not* indented after headings, -blockquotes, code blocks and lists. By default the filter follows this -convention and removes (typically unwanted) indent from paragraphs -that follow blockquotes, code blocks, lists. The user can override -this by inserting `\indent` at the beginning of a paragraph that does -require a first-line indent even though it is after a list, quote or -code-block. 2) Other typographic traditions (*e.g.* French) indent all -paragraphs, even after headings, blockquotes, code blocks and lists. -The filter offers that option. (TO DO: and tries to make a sensible -guess based on language specification?) 3) the filter generates -default LaTeX / HTML outputs with first-line indent style. That -default behaviour can be deactivated in case the user prefers to -provide their own templates that handle first-line indent formatting. -The filter does this by inserting code in the document's metadata -`header-includes` field. It will still work if a document has its own -`header-includes` field, but not if a `header-includes` value is given -to Pandoc via the command line. - -Other outputs (docx, ...) are not covered. +In typography paragraphs can be distinguished in two ways: by vertical +whitespace (a style common on the web) or by indenting their first +line (a style common in books). For the latter conventions vary across +typographic traditions: some (*e.g.* French) indent the first line of +every paragraph while others (*e.g.* English) don't indent paragraphs +after section headings and most indented material such as blockquotes +or lists. + +In Pandoc the default output uses the vertical whitespace style but +can be switched in some formats (PDF via `LaTeX`, though not in `docx` +or `html`) to the first-line indent style by setting the metadata +variable `indent` to `true` and the `lang` variable is used to decide +which convention to follow (the default is the English one). + +However the default first-line indent style output still adds first-line indents to every paragraph that starts after a blockquote, list, code +block, etc. These are typically (though not always) unwanted, namely when +the text after the blockquote or list is a continuation of the same +paragraph. + +This filter improves the handling of first-line indent following +indented material such as blockquotes and provides first-line indent +style for html outputs: + +1) The filter activates Pandoc's first-line indent style by setting + the metadata variable `indent` to true, unless otherwise specified. +2) The filter generates HTML outputs with first-line indent style. That + is done by inserting CSS code in the document's metadata + `header-includes` field. (Note that this still works if the document + has its own `header-includes` material, but not if a + `header-includes` value is given to Pandoc via the command line.) + This default behaviour can be deactivated in case the user prefers + relying on a custom HTML template to handle first-line indent + formatting. +3) The filter removes (typically unwanted) first-line indents after + blockquotes, lists, code blocks and the like. The user can + override this by inserting `\indent` at the beginning of a paragraph + that does require a first-line indent. By default first-line indent + is removed after the block of the following types, though this can + be customized by the user: block quotes, lists (of all types: + unordered, ordered, numbered examples, definition lists), + horizontal rules. Usage ----- diff --git a/first-line-indent/expected.tex b/first-line-indent/expected.tex new file mode 100644 index 00000000..30ebd582 --- /dev/null +++ b/first-line-indent/expected.tex @@ -0,0 +1,66 @@ +First paragraph. Usually without first-line indent. Lorem ipsum dolor +sit amet, consectetur adipiscing elit. Donec tincidunt lacinia metus id +ullamcorper. Integer eget magna quis ipsum lobortis dignissim. + +This paragraph should start with a first-line indent. But after this +quote: + +\begin{quote} +Lorem ipsum dolor sit amet, consectetur adipiscing elit. +\end{quote} + +\noindent The paragraph continues, so there should not be a first-line +indent. + +The quote below ends a paragraph: + +\begin{quote} +Lorem ipsum dolor sit amet, consectetur adipiscing elit. +\end{quote} + +\indent This paragraph, then, is genuinely a new paragraph and starts +with a first-line indent. + +\hypertarget{further-tests}{% +\section{Further tests}\label{further-tests}} + +After a heading (in English typographic style) the paragraph does not +have a first-line indent. + +In the couple couple of paragraphs that follow the quotes below, we have +manually specified \texttt{\textbackslash{}noindent} and +\texttt{\textbackslash{}indent} respectively. This is to check that the +filter doesn't add its own commands to those. + +\begin{quote} +Lorem ipsum dolor sit amet, consectetur adipiscing elit. +\end{quote} + +\noindent Manually specified no first line indent. + +\indent Manually specified first line ident. + +We can also check that indent is removed after lists: + +\begin{itemize} +\tightlist +\item + A bullet +\item + list +\end{itemize} + +\noindent And after code blocks: + +\begin{Shaded} +\begin{Highlighting}[] +\KeywordTok{local}\NormalTok{ variable }\OperatorTok{=} \StringTok{"value"} +\end{Highlighting} +\end{Shaded} + +\noindent Or horizontal rules. + +\begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} + +\noindent Last but not least, you can fiddle with the filter options in +the document metadata and see what happens. diff --git a/first-line-indent/first-line-indent.lua b/first-line-indent/first-line-indent.lua new file mode 100644 index 00000000..81fb5bdf --- /dev/null +++ b/first-line-indent/first-line-indent.lua @@ -0,0 +1,155 @@ +--[[-- # First-line-indent - First-line idented paragraphs + in Pandoc's markdown. + +@author Julien Dutant +@copyright 2021 Julien Dutant +@license MIT - see LICENSE file for details. +@release 0.1 +]] + +-- # Parameters + +--- Options map, including defaults. +-- @param set_metadata_variable boolean whether to set the `indent` +-- metadata variable. +-- @param set_header_includes boolean whether to add formatting code in +-- header-includes to handle first-line indent paragraph style. +-- @param auto_remove_indents boolean whether to automatically remove +-- indents after blockquotes and the like. +-- @param remove_indent_after list of strings, Pandoc AST block types +-- after which first-line indents should be automatically removed. +local options = { + set_metadata_variable = true, + set_header_includes = true, + auto_remove = true, + remove_indent_after = { + 'BlockQuote', + 'BulletList', + 'CodeBlock', + 'DefinitionList', + 'HorizontalRule', + 'OrderedList', + } +} + +--- Global variables +-- @utils pandoc's module of utilities functions +-- @param block_types: List of block types after which first-line idents +-- should be we automatically removed. +-- @param code_indent Pandoc object for LaTeX indent code +-- @param code_noindent Pandoc object for LaTeX noindent code +local utils = pandoc.utils +local block_types = pandoc.List(options.remove_indent_after) +local code_indent = pandoc.RawInline('tex', '\\indent ') +local code_noindent = pandoc.RawInline('tex', '\\noindent ') + +--- process_metadata: filter for the metablock. +-- reads the user options. +-- sets the metadata variable `indent` to `true` unless otherwise specified. +-- adds formatting code to `header-includes` unless otherwise specified. +function process_metadata(meta) + + -- read user options + if meta['first-line-indent'] then + + local user_options = meta['first-line-indent'] + + if not(user_options['set-metadata-variable'] == nil) + and user_options['set-metadata-variable'] == false then + options.set_metadata_variable = false + + end + + if not(user_options['set-header-includes'] == nil) + and user_options['set-header-includes'] == false then + options.set_header_includes = false + end + + if not(user_options['auto-remove'] == nil) + and user_options['auto-remove'] == false then + options.auto_remove = false + end + + if (user_options['remove-after']) then + -- @todo process this option (either single string or list) + end + + if (user_options['dont-remove-after']) then + -- @todo process this option (either single string or list) + end + + end + + -- set the `indent` metadata variable unless otherwise specified or + -- already set to false + if options.set_metadata_variable and not(meta.indent == false) then + meta.indent = true + return meta + end + + -- @todo add `header-include` code + +end + + +--- process_body: process the document's body text. +-- unless otherwise specified, automatically adds no-first-line-indent +-- on every paragraph following one of the block types +local function process_body(doc) + + if options.auto_remove then + + local do_not_indent_next_block = false + + for _,elem in pairs(doc.blocks) do + + if elem.t == "Para" and do_not_indent_next_block then + + do_not_indent_next_block = false + + -- check that the paragraph doesn't already explictly specifies + -- its ident + if elem.content[1] and not (utils.equals(elem.content[1], + code_noindent) or utils.equals(elem.content[1],code_indent)) + then + + if FORMAT:match('latex') then + content = pandoc.List(elem.content) + content:insert(1, pandoc.RawInline('latex', '\\noindent ')) + elem.content = content + elseif FORMAT:matches('html*') then + -- to be handled! + end + + end + + elseif block_types:includes(elem.t) then + + do_not_indent_next_block = true + + else + + do_not_indent_next_block = false + + end + + end + + return doc + + end + +end + +--- Main code +-- Returns the filters in the desired order of execution +local metadata_filter = { + Meta = process_metadata +} +local body_filter = { + Pandoc = process_body +} +return { + metadata_filter, + body_filter +} diff --git a/first-line-indent/indentation.lua b/first-line-indent/indentation.lua deleted file mode 100644 index df228a01..00000000 --- a/first-line-indent/indentation.lua +++ /dev/null @@ -1,26 +0,0 @@ ---[[-- # First Line Indent - First-line idented paragraphs - in Pandoc's markdown. -@author Julien Dutant -@copyright 2021 Julien Dutant -@license MIT - see LICENSE file for details. -@release 0.1 -]] - --- # Parameters - ---- Options map, including defaults. --- @param header_code boolean whether to include support code in the header (true). --- @param convert_rules boolean whether to convert horinzontal rules to half length. -local options = { - header_code = true, - convert_rules = true, -} - ---- list of formats for which we process the filter. -local target_formats = { - 'html.*', - 'latex', - 'jats', - 'native', - 'markdown' -} diff --git a/first-line-indent/sample.md b/first-line-indent/sample.md new file mode 100644 index 00000000..69512839 --- /dev/null +++ b/first-line-indent/sample.md @@ -0,0 +1,49 @@ +--- +title: "Sample first line indent" +first-line-indent: + set-metadata-variable: true # make it false to revert to vertical whitespace separation instead +--- + +First paragraph. Usually without first-line indent. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec tincidunt lacinia metus id ullamcorper. Integer eget magna quis ipsum lobortis dignissim. + +This paragraph should start with a first-line indent. But after this quote: + +> Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +The paragraph continues, so there should not be a first-line indent. + +The quote below ends a paragraph: + +> Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +\indent This paragraph, then, is genuinely a new paragraph and starts with +a first-line indent. + +# Further tests + +After a heading (in English typographic style) the paragraph does not have a first-line indent. + +In the couple couple of paragraphs that follow the quotes below, we have manually specified `\noindent` and `\indent` respectively. This is to check that the filter doesn't add its own commands to those. + +> Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +\noindent Manually specified no first line indent. + +\indent Manually specified first line ident. + +We can also check that indent is removed after lists: + +* A bullet +* list + +And after code blocks: + +```lua +local variable = "value" +``` + +Or horizontal rules. + +--- + +Last but not least, you can fiddle with the filter options in the document metadata and see what happens. diff --git a/first-line-indent/targethtmlcode.html b/first-line-indent/targethtmlcode.html new file mode 100644 index 00000000..a5e4bcb5 --- /dev/null +++ b/first-line-indent/targethtmlcode.html @@ -0,0 +1,38 @@ + + +Html code for first-line indent paragraphs + + + +
+

This paragraph should start with a first-line indent. But after this quote:

+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

+
+

The paragraph continues, so there should not be a first-line indent.

+

The quote below ends a paragraph:

+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

+
+

This paragraph, then, is genuinely a new paragraph and starts with a first-line indent.

+

Further tests

+

After a heading (in English typographic style) the paragraph does not have a first-line indent.

+ + +
+ diff --git a/first-line-indent/test.tex b/first-line-indent/test.tex new file mode 100644 index 00000000..88d505f9 --- /dev/null +++ b/first-line-indent/test.tex @@ -0,0 +1,153 @@ +% 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 +}{} +\usepackage{xcolor} +\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available +\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}} +\hypersetup{ + pdftitle={Sample first line indent}, + hidelinks, + pdfcreator={LaTeX via pandoc}} +\urlstyle{same} % disable monospaced font for URLs +\usepackage{color} +\usepackage{fancyvrb} +\newcommand{\VerbBar}{|} +\newcommand{\VERB}{\Verb[commandchars=\\\{\}]} +\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}} +% Add ',fontsize=\small' for more characters per line +\newenvironment{Shaded}{}{} +\newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}} +\newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} +\newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.49,0.56,0.16}{#1}} +\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} +\newcommand{\BuiltInTok}[1]{#1} +\newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} +\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{#1}}} +\newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} +\newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.53,0.00,0.00}{#1}} +\newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}} +\newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{#1}} +\newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} +\newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.73,0.13,0.13}{\textit{#1}}} +\newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}} +\newcommand{\ExtensionTok}[1]{#1} +\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} +\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{#1}} +\newcommand{\ImportTok}[1]{#1} +\newcommand{\InformationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} +\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}} +\newcommand{\NormalTok}[1]{#1} +\newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.40,0.40,0.40}{#1}} +\newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{#1}} +\newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.74,0.48,0.00}{#1}} +\newcommand{\RegionMarkerTok}[1]{#1} +\newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} +\newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.73,0.40,0.53}{#1}} +\newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} +\newcommand{\VariableTok}[1]{\textcolor[rgb]{0.10,0.09,0.49}{#1}} +\newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} +\newcommand{\WarningTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} +\setlength{\emergencystretch}{3em} % prevent overfull lines +\providecommand{\tightlist}{% + \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} +\setcounter{secnumdepth}{-\maxdimen} % remove section numbering +\ifLuaTeX + \usepackage{selnolig} % disable illegal ligatures +\fi + +\title{Sample first line indent} +\author{} +\date{} + +\begin{document} +\maketitle + +First paragraph. Usually without first-line indent. Lorem ipsum dolor +sit amet, consectetur adipiscing elit. Donec tincidunt lacinia metus id +ullamcorper. Integer eget magna quis ipsum lobortis dignissim. + +This paragraph should start with a first-line indent. But after this +quote: + +\begin{quote} +Lorem ipsum dolor sit amet, consectetur adipiscing elit. +\end{quote} + +\noindent The paragraph continues, so there should not be a first-line +indent. + +The quote below ends a paragraph: + +\begin{quote} +Lorem ipsum dolor sit amet, consectetur adipiscing elit. +\end{quote} + +\indent This paragraph, then, is genuinely a new paragraph and starts +with a first-line indent. + +\hypertarget{further-tests}{% +\section{Further tests}\label{further-tests}} + +After a heading (in English typographic style) the paragraph does not +have a first-line indent. + +In the couple couple of paragraphs that follow the quotes below, we have +manually specified \texttt{\textbackslash{}noindent} and +\texttt{\textbackslash{}indent} respectively. This is to check that the +filter doesn't add its own commands to those. + +\begin{quote} +Lorem ipsum dolor sit amet, consectetur adipiscing elit. +\end{quote} + +\noindent Manually specified no first line indent. + +\indent Manually specified first line ident. + +We can also check that indent is removed after lists: + +\begin{itemize} +\tightlist +\item + A bullet +\item + list +\end{itemize} + +\noindent And after code blocks: + +\begin{Shaded} +\begin{Highlighting}[] +\KeywordTok{local}\NormalTok{ variable }\OperatorTok{=} \StringTok{"value"} +\end{Highlighting} +\end{Shaded} + +\noindent Or horizontal rules. + +\begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} + +\noindent Last but not least, you can fiddle with the filter options in +the document metadata and see what happens. + +\end{document} From 838ac8ba055c3d6e4fd243c9937ec65538f31c13 Mon Sep 17 00:00:00 2001 From: jdutant <34026710+jdutant@users.noreply.github.com> Date: Sun, 21 Mar 2021 20:12:37 +0000 Subject: [PATCH 3/3] Added options, completed README.md --- first-line-indent/Makefile | 10 +- first-line-indent/README.md | 178 ++++++++++++- first-line-indent/expected.html | 317 ++++++++++++++++++++++++ first-line-indent/expected.tex | 149 ++++++++++- first-line-indent/first-line-indent.lua | 274 ++++++++++++++++---- first-line-indent/sample.md | 39 ++- first-line-indent/targethtmlcode.html | 38 --- first-line-indent/test.tex | 153 ------------ 8 files changed, 904 insertions(+), 254 deletions(-) create mode 100644 first-line-indent/expected.html delete mode 100644 first-line-indent/targethtmlcode.html delete mode 100644 first-line-indent/test.tex diff --git a/first-line-indent/Makefile b/first-line-indent/Makefile index 09fdfcfe..62bfcbae 100644 --- a/first-line-indent/Makefile +++ b/first-line-indent/Makefile @@ -2,18 +2,18 @@ DIFF ?= diff --strip-trailing-cr -u .PHONY: test -test: test_latex +test: test_latex test_html test_html: sample.md expected.html first-line-indent.lua - @pandoc --lua-filter first-line-indent.lua --to=html $< \ + @pandoc -s --lua-filter first-line-indent.lua --to=html $< \ | $(DIFF) expected.html - test_latex: sample.md expected.tex first-line-indent.lua - @pandoc --lua-filter first-line-indent.lua --to=latex $< \ + @pandoc -s --lua-filter first-line-indent.lua --to=latex $< \ | $(DIFF) expected.tex - expected.html: sample.md first-line-indent.lua - pandoc --lua-filter first-line-indent.lua --output $@ $< + pandoc -s --lua-filter first-line-indent.lua --output $@ $< expected.tex: sample.md first-line-indent.lua - pandoc --lua-filter first-line-indent.lua --output $@ $< + pandoc -s --lua-filter first-line-indent.lua --output $@ $< diff --git a/first-line-indent/README.md b/first-line-indent/README.md index d43d5482..c4328829 100644 --- a/first-line-indent/README.md +++ b/first-line-indent/README.md @@ -4,10 +4,10 @@ title: "First Line Indent - First-line idented paragraphs author: "Julien Dutant" --- -Indentation +First Line Indent ======= -Paragraph indentation control in pandoc's markdown. +First-line idented paragraphs in Pandoc's markdown. This Lua filter for Pandoc improves Pandoc's first-line ident paragraph separation style by removing first-line idents after @@ -49,10 +49,13 @@ style for html outputs: `header-includes` field. (Note that this still works if the document has its own `header-includes` material, but not if a `header-includes` value is given to Pandoc via the command line.) - This default behaviour can be deactivated in case the user prefers - relying on a custom HTML template to handle first-line indent - formatting. -3) The filter removes (typically unwanted) first-line indents after + This default behaviour can be deactivated if the user wants to handle + first-line indent formatting with a custom pandoc template. +3) If the user manually specifies `\indent` (resp., `\noindent`) at the start + of a paragraph (in markdown source), the paragraphs are typeset with + (resp., without) first-line indentation in HTML output as well as + LaTeX output. +4) The filter removes (typically unwanted) first-line indents after blockquotes, lists, code blocks and the like. The user can override this by inserting `\indent` at the beginning of a paragraph that does require a first-line indent. By default first-line indent @@ -60,7 +63,170 @@ style for html outputs: be customized by the user: block quotes, lists (of all types: unordered, ordered, numbered examples, definition lists), horizontal rules. +5) A custom size for the first-line indentation in HTML and LaTeX output + can be specified. Usage ----- +### Basic usage + +Copy `first-line-indent.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 +command line option: + +```bash +pandoc --luafilter first-line-indent.lua SOURCE.md -o OUTPUT.html + +pandoc -L first-line-indent.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 HTML and PDF outputs in first-line indent paragraph +separation style with the indent automatically removed after headings, +blockquotes, lists of all kinds and horizontal rules. + +If you want to keep the first-line indent of a certain paragraph after +a list or blockquote, this must be done in markdown (convert your +source to markdown first with pandoc). You simply add `\indent` at the +beginning of the paragraph: + +```markdown +> This is a blockquote + +\indent This paragraph will have an indent even though it follows a +blockquote. +``` + +### Advanced usage + +The filter has options that can be specified in a [pandoc default +file](https://pandoc.org/MANUAL.html#option--defaults) or, if the +source is markdown, in the source document's metadata block. +Either way they are specified as sub-fields of a `first-line-indent` +field. In the source's metadata block, they are specified as +follows (these are the default values): + +```yaml +first-line-indent: + size: 1em + auto-remove: true + set-metadata-variable: true + set-header-includes: true + remove-after: + - BlockQuote + - BulletList + - CodeBlock + - DefinitionList + - HorizontalRule + - OrderedList + dont-remove-after: Table +``` + +And as follows in a default file: + +```yaml +metadata: + first-line-indent: + size: 1em + auto-remove: true + set-metadata-variable: true + set-header-includes: true + remove-after: + - BlockQuote + - BulletList + - CodeBlock + - DefinitionList + - HorizontalRule + - OrderedList + dont-remove-after: Table +``` + +The options are described below. + +* `size`: string specificing size of the first-line indent. Must be in a + format suitable for all desired outputs. `1.5em`, `2ex`, `.5pc`, `10pt`, + `25mm`, `2.5cm`, `0.3in`, all work in LaTeX and HTML. `25px` only works + in HTML. LaTeX commands (`\textheight`) are not supported. +* `auto-remove`: whether the filter automatically removes first-line + indent from paragraphs that follow blockquotes and the like, unless + they start with the `\indent` string. (Default: true) +* `set-metadata-variable`: whether the filter should tell Pandoc to use + first-line-indent paragraph separation style by setting the metadata + variable `indent` to `true`. (Default: true) +* `set-header-includes`: whether the filter should add formatting code + to the document's `header-includes` metadata field. Set it to false if + you use a custom template instead. +* `remove-after`, `dont-remove-after`: use these options to customize + the automatic removal of first-line indent on paragraphs following + blocks of a certain type. These options can be a single string or + an list of strings. The strings are case-sensitive and should be + those corresponding to [block types in Lua + filters](https://pandoc.org/lua-filters.html#type-block): BlockQuote, + BulletList, CodeBlock, DefinitionList, Div, Header, HorizontalRule, + LineBlock, Null, OrderedList, Para, Plain, RawBlock, Table. + +To illustrate the last option, suppose you don't want to filter to remove +first-line indent after definition lists. You can add the following +lines in the document's metadata block (if the source is markdown): + +```yaml +first-line-indent: + dont-remove-after: DefinitionList +``` + +### Styling the outputs + +In LaTeX output the filters adds `\noindent` commands at beginning of +paragraphs that shouldn't be indented. These can be controlled in +LaTeX as usual. + +In HTML output paragraphs that are explicitly marked to have no first-line +indent are preceded by an empty `div` with class `no-first-line-indent-after` +and those that are explictly marked (with `\indent` in the markdown +source) to have a first-line indent are preceded by an empty `div` with class +`first-line-indent-after`, as follows: + +```html +
    +
  • A bullet
  • +
  • list
  • +
+
+

This paragraph should not have first-line indent.

+... +
+

This paragraph should have first-line indent.

+``` + +These can be styled in CSS as follows: + +```css +p { + text-indent: 1em; + margin: 0; +} +:is(h1, h2, h3, h4, h5, h6) + p { + text-indent: 0em; +} +:is(div.no-first-line-indent-after) + p { + text-indent: 0em; +} +:is(div.first-line-indent-after) + p { + text-indent: 1em; +} +``` + +The `p` rule adds a first-line identation to every paragraph (and `margin: 0` removes the default vertical space between paragraphs). The +`is(h1, h2, h3, h4, h5, h6) + p` rule removes first-line indentation from +every paragraph that follows a heading. The +`:is(div.no-first-line-indent-after) + p` and +`:is(div.first-line-indent-after) + p` rules remove/add first-line indentation +from every paragraph that follows `div`s of the classes `no-first-line-indent-after` and `first-line-indent-after`, respectively. + +Contributing +------------ + +PRs welcome. + diff --git a/first-line-indent/expected.html b/first-line-indent/expected.html new file mode 100644 index 00000000..7957cfb5 --- /dev/null +++ b/first-line-indent/expected.html @@ -0,0 +1,317 @@ + + + + + + + Sample first line indent + + + + + +
+

Sample first line indent

+
+

First paragraph. In English-style typography, the first paragraph shouldn’t have a first-line indent, nor the paragraphs below headers.

+

This paragraph should start with a first-line indent. But after this quote:

+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

+
+
+

the paragraph continues, so there should not be a first-line indent.

+

The quote below ends a paragraph:

+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

+
+
+

This paragraph, then, is genuinely a new paragraph and starts with a first-line indent.

+

Further tests

+

After a heading (in English typographic style) the paragraph does not have a first-line indent.

+

In the couple couple of paragraphs that follow the quotes below, we have manually specified \noindent and \indent respectively. This is to check that the filter doesn’t add its own commands to those.

+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

+
+
+

Manually specified no first line indent.

+
+

Manually specified first line ident.

+

We can also check that indent is removed after lists:

+
    +
  • A bullet
  • +
  • list
  • +
+
+

And after code blocks:

+
local variable = "value"
+
+

Or horizontal rules.

+
+
+

In this document we added a few custom filter options. The size of first-line indents is 2em instead of the standard 1em. We also added an option to remove indent after tables:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Demonstration of simple table syntax.
RightLeftCenterDefault
12121212
123123123123
1111
+
+

So this paragraph’s first line is not indented. And we included custom options not to remove ident after ordered lists and definition lists:

+
+
Definition
+
This is a definition block. +
+
+

This paragraph is indented.

+
    +
  1. An ordered
  2. +
  3. list
  4. +
+

This paragraph is indented.

+ + diff --git a/first-line-indent/expected.tex b/first-line-indent/expected.tex index 30ebd582..23e9a1d9 100644 --- a/first-line-indent/expected.tex +++ b/first-line-indent/expected.tex @@ -1,6 +1,101 @@ -First paragraph. Usually without first-line indent. Lorem ipsum dolor -sit amet, consectetur adipiscing elit. Donec tincidunt lacinia metus id -ullamcorper. Integer eget magna quis ipsum lobortis dignissim. +% 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 +}{} +\usepackage{xcolor} +\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available +\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}} +\hypersetup{ + pdftitle={Sample first line indent}, + hidelinks, + pdfcreator={LaTeX via pandoc}} +\urlstyle{same} % disable monospaced font for URLs +\usepackage{color} +\usepackage{fancyvrb} +\newcommand{\VerbBar}{|} +\newcommand{\VERB}{\Verb[commandchars=\\\{\}]} +\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}} +% Add ',fontsize=\small' for more characters per line +\newenvironment{Shaded}{}{} +\newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}} +\newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} +\newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.49,0.56,0.16}{#1}} +\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} +\newcommand{\BuiltInTok}[1]{#1} +\newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} +\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{#1}}} +\newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} +\newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.53,0.00,0.00}{#1}} +\newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}} +\newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{#1}} +\newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} +\newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.73,0.13,0.13}{\textit{#1}}} +\newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}} +\newcommand{\ExtensionTok}[1]{#1} +\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} +\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{#1}} +\newcommand{\ImportTok}[1]{#1} +\newcommand{\InformationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} +\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}} +\newcommand{\NormalTok}[1]{#1} +\newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.40,0.40,0.40}{#1}} +\newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{#1}} +\newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.74,0.48,0.00}{#1}} +\newcommand{\RegionMarkerTok}[1]{#1} +\newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} +\newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.73,0.40,0.53}{#1}} +\newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} +\newcommand{\VariableTok}[1]{\textcolor[rgb]{0.10,0.09,0.49}{#1}} +\newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} +\newcommand{\WarningTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} +\usepackage{longtable,booktabs,array} +\usepackage{calc} % for calculating minipage widths +% Correct order of tables after \paragraph or \subparagraph +\usepackage{etoolbox} +\makeatletter +\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{} +\makeatother +% Allow footnotes in longtable head/foot +\IfFileExists{footnotehyper.sty}{\usepackage{footnotehyper}}{\usepackage{footnote}} +\makesavenoteenv{longtable} +\setlength{\emergencystretch}{3em} % prevent overfull lines +\providecommand{\tightlist}{% + \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} +\setcounter{secnumdepth}{-\maxdimen} % remove section numbering +\setlength{\parindent}{2em} +\ifLuaTeX + \usepackage{selnolig} % disable illegal ligatures +\fi + +\title{Sample first line indent} +\author{} +\date{} + +\begin{document} +\maketitle + +First paragraph. In English-style typography, the first paragraph +shouldn't have a first-line indent, nor the paragraphs below headers. This paragraph should start with a first-line indent. But after this quote: @@ -9,7 +104,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. \end{quote} -\noindent The paragraph continues, so there should not be a first-line +\noindent the paragraph continues, so there should not be a first-line indent. The quote below ends a paragraph: @@ -62,5 +157,47 @@ \section{Further tests}\label{further-tests}} \begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} -\noindent Last but not least, you can fiddle with the filter options in -the document metadata and see what happens. +\noindent In this document we added a few custom filter options. The +size of first-line indents is 2em instead of the standard 1em. We also +added an option to remove indent after tables: + +\begin{longtable}[]{@{}rlcl@{}} +\caption{Demonstration of simple table syntax.}\tabularnewline +\toprule +Right & Left & Center & Default \\ +\midrule +\endfirsthead +\toprule +Right & Left & Center & Default \\ +\midrule +\endhead +12 & 12 & 12 & 12 \\ +123 & 123 & 123 & 123 \\ +1 & 1 & 1 & 1 \\ +\bottomrule +\end{longtable} + +\noindent So this paragraph's first line is not indented. And we +included custom options \emph{not} to remove ident after ordered lists +and definition lists: + +\begin{description} +\tightlist +\item[Definition] +This is a definition block. +\end{description} + +This paragraph is indented. + +\begin{enumerate} +\def\labelenumi{\arabic{enumi}.} +\tightlist +\item + An ordered +\item + list +\end{enumerate} + +This paragraph is indented. + +\end{document} diff --git a/first-line-indent/first-line-indent.lua b/first-line-indent/first-line-indent.lua index 81fb5bdf..98899a77 100644 --- a/first-line-indent/first-line-indent.lua +++ b/first-line-indent/first-line-indent.lua @@ -7,7 +7,7 @@ @release 0.1 ]] --- # Parameters +-- # Options --- Options map, including defaults. -- @param set_metadata_variable boolean whether to set the `indent` @@ -18,32 +18,92 @@ -- indents after blockquotes and the like. -- @param remove_indent_after list of strings, Pandoc AST block types -- after which first-line indents should be automatically removed. +-- @param size string a CSS / LaTeX specification of the first line +-- indent length local options = { set_metadata_variable = true, set_header_includes = true, auto_remove = true, - remove_indent_after = { + remove_indent_after = pandoc.List({ 'BlockQuote', 'BulletList', 'CodeBlock', 'DefinitionList', 'HorizontalRule', 'OrderedList', - } + }), + size = "1em", } ---- Global variables +-- # Filter global variables -- @utils pandoc's module of utilities functions --- @param block_types: List of block types after which first-line idents --- should be we automatically removed. --- @param code_indent Pandoc object for LaTeX indent code --- @param code_noindent Pandoc object for LaTeX noindent code +-- @param code map of pandoc objects for indent/noindent Raw code +-- @param header_code map of pandoc code to add to header-includes local utils = pandoc.utils -local block_types = pandoc.List(options.remove_indent_after) -local code_indent = pandoc.RawInline('tex', '\\indent ') -local code_noindent = pandoc.RawInline('tex', '\\noindent ') +local code = { + latex = { + indent = pandoc.RawInline('tex', '\\indent '), + noindent = pandoc.RawInline('tex', '\\noindent '), + }, + html = { + indent = pandoc.RawBlock('html', + '
'), + noindent = pandoc.RawBlock('html', + '
'), + } +} +local header_code = { + html = [[ + +]], +} + +--- Add a block to the document's header-includes meta-data field. +-- @param meta the document's metadata block +-- @param blocks list of Pandoc block elements (e.g. RawBlock or Para) +-- to be added to the header-includes of meta +-- @return meta the modified metadata block +local function add_header_includes(meta, blocks) + + local header_includes = pandoc.List(blocks) + + -- add any exisiting meta['header-includes'] + -- it could be a MetaList or a single String + if meta['header-includes'] then + if meta['header-includes'].t == 'MetaList' then + header_includes:extend(meta['header-includes']) + else + header_includes:insert(meta['header-includes']) + end + end + + meta['header-includes'] = pandoc.MetaBlocks(header_includes) + + return meta + +end + +-- # Filter functions + ---- process_metadata: filter for the metablock. +--- Filter for the metablock. -- reads the user options. -- sets the metadata variable `indent` to `true` unless otherwise specified. -- adds formatting code to `header-includes` unless otherwise specified. @@ -71,74 +131,204 @@ function process_metadata(meta) end if (user_options['remove-after']) then - -- @todo process this option (either single string or list) + + if user_options['remove-after'].t == 'MetaInlines' or + user_options['remove-after'].t == 'MetaList' then + + if user_options['remove-after'].t == 'MetaInlines' then + + options.remove_indent_after:insert ( + utils.stringify(user_options['remove-after'])) + + else + + for _,item in ipairs(user_options['remove-after']) do + + options.remove_indent_after:insert(utils.stringify(item)) + + end + + end + + end end if (user_options['dont-remove-after']) then - -- @todo process this option (either single string or list) + + if user_options['dont-remove-after'].t == 'MetaInlines' or + user_options['dont-remove-after'].t == 'MetaList' then + + -- list of strings to be removed + local blacklist = pandoc.List({}) + + if user_options['dont-remove-after'].t == 'MetaInlines' then + + blacklist:insert ( + utils.stringify(user_options['dont-remove-after'])) + + else + + for _,item in ipairs(user_options['dont-remove-after']) do + + blacklist:insert(utils.stringify(item)) + + end + + end + + -- filter the options.remove_indent_after list to only + -- include items that are not blacklisted + predicate = function (str) + return not(blacklist:includes(str)) + end + + options.remove_indent_after = + options.remove_indent_after:filter(predicate) + + end + end + + if not(user_options['size'] == nil) then + + -- @todo using stringify means that LaTeX commands in + -- size are erased. But it ensures that the filter gets + -- a string. Improvement: check that we have a string + -- and throw a warning otherwise + options.size = utils.stringify(user_options['size']) + end end + -- variable to track whether we've changed `meta` + changes = false + -- set the `indent` metadata variable unless otherwise specified or -- already set to false if options.set_metadata_variable and not(meta.indent == false) then meta.indent = true - return meta + changes = true + end + + -- set the `header-includes` metadata variable + if options.set_header_includes then + + if FORMAT:match('html*') then + + header_code.html = string.gsub(header_code.html, "SIZE", options.size) + add_header_includes(meta, { pandoc.RawBlock('html', header_code.html) }) + + elseif FORMAT:match('latex') and not(options.size == "1em") then + + add_header_includes(meta, { pandoc.RawBlock('tex', + '\\setlength{\\parindent}{'.. options.size ..'}') }) + + end + end - -- @todo add `header-include` code + if changes then return meta end end +--- Add format-specific explicit indent markup to a paragraph. +-- @param type string 'indent' or 'noindent', type of markup to add +-- @param elem pandoc AST paragraph +-- @return a list of blocks (containing a single paragraph element or +-- a rawblock and a paragraph element, depending on output format) +local function indent_markup(type, elem) ---- process_body: process the document's body text. --- unless otherwise specified, automatically adds no-first-line-indent --- on every paragraph following one of the block types -local function process_body(doc) + if FORMAT:match('latex') and (type == 'indent' or type == 'noindent') then - if options.auto_remove then + -- in LaTeX, replace any `\indent` or `\noindent` command at + -- the start of the paragraph with the desired one, add it otherwise - local do_not_indent_next_block = false + local content = pandoc.List(elem.content) - for _,elem in pairs(doc.blocks) do + if content[1] and (utils.equals(content[1], + code.latex.indent) or utils.equals(content[1], + code.latex.noindent)) then - if elem.t == "Para" and do_not_indent_next_block then + content[1] = code.latex[type] - do_not_indent_next_block = false + else - -- check that the paragraph doesn't already explictly specifies - -- its ident - if elem.content[1] and not (utils.equals(elem.content[1], - code_noindent) or utils.equals(elem.content[1],code_indent)) - then + content:insert(1, code.latex[type]) - if FORMAT:match('latex') then - content = pandoc.List(elem.content) - content:insert(1, pandoc.RawInline('latex', '\\noindent ')) - elem.content = content - elseif FORMAT:matches('html*') then - -- to be handled! - end + end + + elem.content = content + return({ elem }) + + -- in HTML, insert a block (div) before the paragraph + + elseif FORMAT:match('html*') and (type == 'indent' or type == 'noindent') then + + return({ code.html[type], elem }) + else + + return({elem}) + + end + +end + +--- Process indents in the document's body text. +-- Adds output code for explicitly specified first-line indents, +-- automatically removes first-line indents after blocks of the +-- designed types unless otherwise specified. +local function process_body(doc) + + -- result will be the new doc.blocks + local result = pandoc.List({}) + local do_not_indent_next_block = false + + for _,elem in pairs(doc.blocks) do + + if elem.t == "Para" then + + -- if explicit indentation marking, leave as is and style output + if elem.content[1] and (utils.equals(elem.content[1], + code.latex.indent) or utils.equals(elem.content[1], + code.latex.noindent)) then + + if utils.equals(elem.content[1], code.latex.indent) then + result:extend(indent_markup('indent', elem)) + else + result:extend(indent_markup('noindent', elem)) end - elseif block_types:includes(elem.t) then + -- if auto_remove is on remove the first-line indent if needed + elseif options.auto_remove and do_not_indent_next_block then - do_not_indent_next_block = true + result:extend(indent_markup('noindent', elem)) else - do_not_indent_next_block = false + result:insert(elem) end - end + do_not_indent_next_block = false + + elseif options.remove_indent_after:includes(elem.t) then + + do_not_indent_next_block = true + result:insert(elem) - return doc + else + + do_not_indent_next_block = false + result:insert(elem) + + end end + doc.blocks = result + return doc + end --- Main code diff --git a/first-line-indent/sample.md b/first-line-indent/sample.md index 69512839..f4ddd383 100644 --- a/first-line-indent/sample.md +++ b/first-line-indent/sample.md @@ -1,16 +1,25 @@ --- title: "Sample first line indent" +# Filter options. These are defaults, you will get the same +# if you don't specify anything. See the README.md for details. first-line-indent: - set-metadata-variable: true # make it false to revert to vertical whitespace separation instead + set-metadata-variable: true + set-header-includes: true + auto-remove: true + remove-after: Table + dont-remove-after: + - DefinitionList + - OrderedList + size: "2em" --- -First paragraph. Usually without first-line indent. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec tincidunt lacinia metus id ullamcorper. Integer eget magna quis ipsum lobortis dignissim. +First paragraph. In English-style typography, the first paragraph shouldn't have a first-line indent, nor the paragraphs below headers. This paragraph should start with a first-line indent. But after this quote: > Lorem ipsum dolor sit amet, consectetur adipiscing elit. -The paragraph continues, so there should not be a first-line indent. +the paragraph continues, so there should not be a first-line indent. The quote below ends a paragraph: @@ -46,4 +55,26 @@ Or horizontal rules. --- -Last but not least, you can fiddle with the filter options in the document metadata and see what happens. +In this document we added a few custom filter options. The size of first-line +indents is 2em instead of the standard 1em. We also added an option to remove indent after tables: + + Right Left Center Default +------- ------ ---------- ------- + 12 12 12 12 + 123 123 123 123 + 1 1 1 1 + +Table: Demonstration of simple table syntax. + +So this paragraph's first line is not indented. And we included custom options +*not* to remove ident after ordered lists and definition lists: + +Definition +: This is a definition block. + +This paragraph is indented. + +1. An ordered +2. list + +This paragraph is indented. diff --git a/first-line-indent/targethtmlcode.html b/first-line-indent/targethtmlcode.html deleted file mode 100644 index a5e4bcb5..00000000 --- a/first-line-indent/targethtmlcode.html +++ /dev/null @@ -1,38 +0,0 @@ - - -Html code for first-line indent paragraphs - - - -
-

This paragraph should start with a first-line indent. But after this quote:

-
-

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

-
-

The paragraph continues, so there should not be a first-line indent.

-

The quote below ends a paragraph:

-
-

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

-
-

This paragraph, then, is genuinely a new paragraph and starts with a first-line indent.

-

Further tests

-

After a heading (in English typographic style) the paragraph does not have a first-line indent.

- - -
- diff --git a/first-line-indent/test.tex b/first-line-indent/test.tex deleted file mode 100644 index 88d505f9..00000000 --- a/first-line-indent/test.tex +++ /dev/null @@ -1,153 +0,0 @@ -% 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 -}{} -\usepackage{xcolor} -\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available -\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}} -\hypersetup{ - pdftitle={Sample first line indent}, - hidelinks, - pdfcreator={LaTeX via pandoc}} -\urlstyle{same} % disable monospaced font for URLs -\usepackage{color} -\usepackage{fancyvrb} -\newcommand{\VerbBar}{|} -\newcommand{\VERB}{\Verb[commandchars=\\\{\}]} -\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}} -% Add ',fontsize=\small' for more characters per line -\newenvironment{Shaded}{}{} -\newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}} -\newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} -\newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.49,0.56,0.16}{#1}} -\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} -\newcommand{\BuiltInTok}[1]{#1} -\newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} -\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{#1}}} -\newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} -\newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.53,0.00,0.00}{#1}} -\newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}} -\newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{#1}} -\newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} -\newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.73,0.13,0.13}{\textit{#1}}} -\newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}} -\newcommand{\ExtensionTok}[1]{#1} -\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} -\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{#1}} -\newcommand{\ImportTok}[1]{#1} -\newcommand{\InformationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} -\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}} -\newcommand{\NormalTok}[1]{#1} -\newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.40,0.40,0.40}{#1}} -\newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{#1}} -\newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.74,0.48,0.00}{#1}} -\newcommand{\RegionMarkerTok}[1]{#1} -\newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} -\newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.73,0.40,0.53}{#1}} -\newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} -\newcommand{\VariableTok}[1]{\textcolor[rgb]{0.10,0.09,0.49}{#1}} -\newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} -\newcommand{\WarningTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} -\setlength{\emergencystretch}{3em} % prevent overfull lines -\providecommand{\tightlist}{% - \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} -\setcounter{secnumdepth}{-\maxdimen} % remove section numbering -\ifLuaTeX - \usepackage{selnolig} % disable illegal ligatures -\fi - -\title{Sample first line indent} -\author{} -\date{} - -\begin{document} -\maketitle - -First paragraph. Usually without first-line indent. Lorem ipsum dolor -sit amet, consectetur adipiscing elit. Donec tincidunt lacinia metus id -ullamcorper. Integer eget magna quis ipsum lobortis dignissim. - -This paragraph should start with a first-line indent. But after this -quote: - -\begin{quote} -Lorem ipsum dolor sit amet, consectetur adipiscing elit. -\end{quote} - -\noindent The paragraph continues, so there should not be a first-line -indent. - -The quote below ends a paragraph: - -\begin{quote} -Lorem ipsum dolor sit amet, consectetur adipiscing elit. -\end{quote} - -\indent This paragraph, then, is genuinely a new paragraph and starts -with a first-line indent. - -\hypertarget{further-tests}{% -\section{Further tests}\label{further-tests}} - -After a heading (in English typographic style) the paragraph does not -have a first-line indent. - -In the couple couple of paragraphs that follow the quotes below, we have -manually specified \texttt{\textbackslash{}noindent} and -\texttt{\textbackslash{}indent} respectively. This is to check that the -filter doesn't add its own commands to those. - -\begin{quote} -Lorem ipsum dolor sit amet, consectetur adipiscing elit. -\end{quote} - -\noindent Manually specified no first line indent. - -\indent Manually specified first line ident. - -We can also check that indent is removed after lists: - -\begin{itemize} -\tightlist -\item - A bullet -\item - list -\end{itemize} - -\noindent And after code blocks: - -\begin{Shaded} -\begin{Highlighting}[] -\KeywordTok{local}\NormalTok{ variable }\OperatorTok{=} \StringTok{"value"} -\end{Highlighting} -\end{Shaded} - -\noindent Or horizontal rules. - -\begin{center}\rule{0.5\linewidth}{0.5pt}\end{center} - -\noindent Last but not least, you can fiddle with the filter options in -the document metadata and see what happens. - -\end{document}