diff --git a/conclusions/LICENSE.txt b/conclusions/LICENSE.txt new file mode 100644 index 0000000..551b50b --- /dev/null +++ b/conclusions/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright © 2024 Bastien Dumont + +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/conclusions/README.md b/conclusions/README.md new file mode 100644 index 0000000..e672329 --- /dev/null +++ b/conclusions/README.md @@ -0,0 +1,20 @@ +# Typographically distinguish conclusions from the surrounding text + +`conclusions` is a Lua filter for Pandoc +that inserts blank spaces or headers before the conclusions. + +Conclusions must be wrapped in a div with a class `.ccl` or `.conclusion` +and a `level` attribute corresponding to the level of the section to be closed. + +All configuration options have to be set in the YAML metadata block +under the `conclusions` configuration variable: + + * Headers will be inserted before conclusions + of level `innermost-level-header` or less. + * The title of these headers can be set with the variable + `ccl-explicit-titles` (a list of Markdown chunks). + * A vertical space will be inserted before conclusions + of level higher than `innermost-level-header` + down to `innermost-level-space`. + +An example can be found in `test.md`. diff --git a/conclusions/conclusions.lua b/conclusions/conclusions.lua new file mode 100644 index 0000000..e73109b --- /dev/null +++ b/conclusions/conclusions.lua @@ -0,0 +1,100 @@ +-- conclusions.lua +-- A Pandoc Lua filter to distinguish conclusions from the surrounding text. +-- Copyright 2024 Bastien Dumont (bastien.dumont [at] posteo.net) +-- This file is under the MIT License: see LICENSE for more details + +local MAX_HEADER_LEVEL = 6 + +local config = { + innermost_level_header = 2, + innermost_level_space = 3, + ccl_explicit_titles = { + 'Conclusion de la partie', + 'Conclusion du chapitre' + } +} + +local function check_validity(key, value) + if key ~= 'ccl-explicit-titles' + and (value == nil or value < 1 or value > MAX_HEADER_LEVEL) + then + error(key .. ' must be a numeric value ' .. + 'comprised between 1 and ' .. MAX_HEADER_LEVEL .. '.\n') + end +end + +local function get_config(meta) + if meta.conclusions then + for key, value in pairs(meta.conclusions) do + if key ~= 'ccl-explicit-titles' then + value = math.tointeger(value[1].text) + end + check_validity(key, value) + config[string.gsub(key, '-', '_')] = value + end + end +end + +local function set_raw_space() + local raw_space + if FORMAT == 'native' then + FORMAT = pandoc.system.environment().TESTED_FORMAT + set_raw_space() + elseif FORMAT == 'context' then + raw_space = pandoc.RawBlock('tex', '\\blank[big]') + elseif FORMAT == 'docx' then + raw_space = pandoc.RawBlock('openxml', '') + elseif FORMAT == 'latex' then + raw_space = pandoc.RawBlock('tex', '\\bigskip') + else + error(FORMAT .. + ' output not supported by complex-paragraphs.lua\n') + end + return raw_space +end + +local raw_space = set_raw_space() + +local function get_level(div) + local level = MAX_HEADER_LEVEL + 1 + local set_value = div.attributes.level + if set_value then + set_value = math.tointeger(set_value) + check_validity('level', set_value) + level = set_value + else + io.stderr:write('level attribute missing to a div ' .. + 'with class conclusion or ccl, nothing done.\n') + end + return level +end + +local function get_separator_as_list(level) + local separator = {} + if level <= config.innermost_level_header then + local header = + pandoc.Header(level + 1, config.ccl_explicit_titles[level]) + table.insert(header.classes, 'unnumbered') + separator = { header } + elseif level <= config.innermost_level_space then + separator = { raw_space } + end + return separator +end + +function Div(div) + local classes = div.classes + if classes:includes('conclusion') + or classes:includes('ccl') + then + local level = get_level(div) + local formatted_conclusion = get_separator_as_list(level) + table.insert(formatted_conclusion, div) + return formatted_conclusion + end +end + +return { + { Meta = get_config }, + { Div = Div } +} diff --git a/conclusions/test.md b/conclusions/test.md new file mode 100644 index 0000000..232ebe6 --- /dev/null +++ b/conclusions/test.md @@ -0,0 +1,57 @@ +--- +conclusions: + innermost-level-header: 3 + innermost-level-space: 4 + ccl-explicit-titles: + - "Conclusion of level 1" + - "Conclusion of level 2" + - "Conclusion of level 3" +--- + +# Title 1 + +Text level 1 + +## Title 1.1 + +Text level 2 + +### Title 1.1.1 + +Text level 3 + +#### Title 1.1.1.1 + +Text level 4 + +##### Title 1.1.1.1.1 + +Text level 5 + +###### Title 1.1.1.1.1.1 + +Text level 6 + +::: {.ccl level=6} +My conclusion level 6 +::: + +::: {.ccl level=5} +My conclusion level 5 +::: + +::: {.ccl level=4} +My conclusion level 4 +::: + +::: {.ccl level=3} +My conclusion level 3 +::: + +::: {.ccl level=2} +My conclusion level 2 +::: + +::: {.ccl level=1} +My conclusion level 1 +:::