Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add option ensureJekyllData #473

Merged
merged 5 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@

Development:

- Support programmatic text in YAML metadata values.
- Add renderer `jekyllDataProgrammaticString` for processing YAML
string scalars that do not contain markdown markup and are not
intended for typesetting.
(istqborg/istqb_product_base#46, #440, #451, sponsored by @istqborg)
- Add option `ensureJekyllData` for processing standalone YAML files.
- Add renderers `warning` and `error` that represent warnings and errors
produced by the markdown parser. (#452, #473)

Fixes:

Expand All @@ -15,6 +20,7 @@ Fixes:
Deprecation:

- Deprecate `jekyllDataString` renderer and renderer prototype.
Users should use `jekyllDataTypographicString` instead.
(istqborg/istqb_product_base#46, #440, #451, sponsored by @istqborg)

## 3.6.2 (2024-07-14)
Expand Down
151 changes: 139 additions & 12 deletions markdown.dtx
Original file line number Diff line number Diff line change
Expand Up @@ -5892,6 +5892,52 @@ defaultOptions.definitionLists = false
%</lua,lua-cli>
%<*manual-options>

#### Option `ensureJekyllData`

`ensureJekyllData` (default value: `false`)

% \fi
% \begin{markdown}
%
% \Optitem[false]{ensureJekyllData}{\opt{true}, \opt{false}}
%
: false

: When the \Opt{jekyllData} and \Opt{expectJekyllData} options are
enabled, then a markdown document may begin directly with \acro{yaml}
metadata and may contain nothing but \acro{yaml} metadata. Otherwise,
the markdown document is processed as markdown text.

: true

: When the \Opt{jekyllData} and \Opt{expectJekyllData} options are
enabled, then a markdown document must begin directly with \acro{yaml}
metadata and must contain nothing but \acro{yaml} metadata. Otherwise,
an error is produced.

% \end{markdown}
% \iffalse
%</manual-options>
%<*tex>
% \fi
% \begin{macrocode}
\@@_add_lua_option:nnn
{ ensureJekyllData }
{ boolean }
{ false }
% \end{macrocode}
% \iffalse
%</tex>
%<*lua,lua-cli>
% \fi
% \begin{macrocode}
defaultOptions.ensureJekyllData = false
% \end{macrocode}
% \par
% \iffalse
%</lua,lua-cli>
%<*manual-options>

#### Option `expectJekyllData`

`expectJekyllData` (default value: `false`)
Expand Down Expand Up @@ -19956,6 +20002,50 @@ following text:
%
% \begin{markdown}

#### Warning and Error Renderers

The \mdef{markdownRendererWarning} and \mdef{markdownRendererError} macros
represent warnings and errors produced by the markdown parser. Both macros
receive a single parameter with the text of the warning or error.

% \end{markdown}
%
% \iffalse
%</manual-tokens>
%<*tex>
% \fi
%
% \begin{macrocode}
\def\markdownRendererWarning{%
\markdownRendererWarningPrototype}%
\def\markdownRendererError{%
\markdownRendererErrorPrototype}%
\ExplSyntaxOn
\seq_gput_right:Nn
\g_@@_renderers_seq
{ warning }
\prop_gput:Nnn
\g_@@_renderer_arities_prop
{ warning }
{ 1 }
\seq_gput_right:Nn
\g_@@_renderers_seq
{ error }
\prop_gput:Nnn
\g_@@_renderer_arities_prop
{ error }
{ 1 }
\ExplSyntaxOff
% \end{macrocode}
% \par
%
% \iffalse
%</tex>
%<*manual-tokens>
% \fi
%
% \begin{markdown}

#### YAML Metadata Renderers {#yamlmetadatarenderers}

The \mdef{markdownRendererJekyllDataBegin} macro represents the beginning of a
Expand Down Expand Up @@ -25491,6 +25581,30 @@ function M.writer.new(options)
% \par
% \begin{markdown}
%
% Define \luamdef{writer->warning} as a function that will transform an input
% warning `t` to the output format.
%
% \end{markdown}
% \begin{macrocode}
function self.warning(t)
return {"\\markdownRendererWarning{", self.identifier(t), "}"}
end
% \end{macrocode}
% \par
% \begin{markdown}
%
% Define \luamdef{writer->error} as a function that will transform an input
% error `t` to the output format.
%
% \end{markdown}
% \begin{macrocode}
function self.error(t)
return {"\\markdownRendererError{", self.identifier(t), "}"}
end
% \end{macrocode}
% \par
% \begin{markdown}
%
% Define \luamdef{writer->code} as a function that will transform an input
% inline code span `s` with optional attributes `attributes` to the output
% format.
Expand Down Expand Up @@ -28246,7 +28360,7 @@ function M.reader.new(writer, options)
end
local res = lpeg.match(grammar(), str)
if res == nil then
error(format("%s failed on:\n%s", name, str:sub(1,20)))
return writer.error(format("%s failed on:\n%s", name, str:sub(1,20)))
else
return res
end
Expand Down Expand Up @@ -30001,9 +30115,7 @@ end
{ "Blocks",

Blocks = V("InitializeState")
* ( V("ExpectedJekyllData")
* (V("Blank")^0 / writer.interblocksep)
)^-1
* V("ExpectedJekyllData")
* V("Blank")^0
% \end{macrocode}
% \par
Expand Down Expand Up @@ -30039,7 +30151,7 @@ end
)
)^0,

ExpectedJekyllData = parsers.fail,
ExpectedJekyllData = parsers.succeed,

Blank = parsers.Blank,
Reference = parsers.Reference,
Expand Down Expand Up @@ -30346,7 +30458,7 @@ end
end

local blocks_nested_t = util.table_copy(syntax)
blocks_nested_t.ExpectedJekyllData = parsers.fail
blocks_nested_t.ExpectedJekyllData = parsers.succeed
parsers.blocks_nested = Ct(blocks_nested_t)

parsers.blocks = Ct(syntax)
Expand Down Expand Up @@ -30404,7 +30516,7 @@ end
elseif form == "nfkd" then
input = uni_algos.normalize.NFKD(input)
else
error(format("Unknown normalization form %s", form))
return writer.error(format("Unknown normalization form %s", form))
end
end
% \end{macrocode}
Expand Down Expand Up @@ -32822,11 +32934,14 @@ end
% \acro{yaml} metadata block syntax extension. When the
% `expect_jekyll_data` parameter is `true`, then a markdown document
% may begin directly with \acro{yaml} metadata and may contain nothing
% but \acro{yaml} metadata.
% but \acro{yaml} metadata. When both `expect_jekyll_data` and
% `ensure_jekyll_data` parameters are `true`, then a a markdown document must
% begin directly with \acro{yaml} metadata and must contain nothing but
% \acro{yaml} metadata.
%
% \end{markdown}
% \begin{macrocode}
M.extensions.jekyll_data = function(expect_jekyll_data)
M.extensions.jekyll_data = function(expect_jekyll_data, ensure_jekyll_data)
return {
name = "built-in jekyll_data syntax extension",
extend_writer = function(self)
Expand Down Expand Up @@ -32938,8 +33053,9 @@ M.extensions.jekyll_data = function(expect_jekyll_data)
table.insert(buf, k)
table.insert(buf, "}")
else
error(format("Unexpected type %s for value of " ..
"YAML key %s", typ, k))
local error = self.error(format("Unexpected type %s for value of " ..
"YAML key %s", typ, k))
table.insert(buf, error)
end
end
end
Expand Down Expand Up @@ -32994,6 +33110,15 @@ M.extensions.jekyll_data = function(expect_jekyll_data)
* JekyllData
* (P("---") + P("..."))^-1

if ensure_jekyll_data then
ExpectedJekyllData = ExpectedJekyllData
* parsers.eof
else
ExpectedJekyllData = ( ExpectedJekyllData
* (V("Blank")^0 / writer.interblocksep)
)^-1
end

self.insert_pattern("Block before Blockquote",
UnexpectedJekyllData, "UnexpectedJekyllData")
if expect_jekyll_data then
Expand Down Expand Up @@ -33103,7 +33228,7 @@ function M.new(options)

if options.jekyllData then
local jekyll_data_extension = M.extensions.jekyll_data(
options.expectJekyllData)
options.expectJekyllData, options.ensureJekyllData)
table.insert(extensions, jekyll_data_extension)
end

Expand Down Expand Up @@ -33766,6 +33891,8 @@ end
\ExplSyntaxOff
\def\markdownRendererSectionBeginPrototype{}%
\def\markdownRendererSectionEndPrototype{}%
\let\markdownRendererWarningPrototype\markdownWarning
\let\markdownRendererErrorPrototype\markdownError
% \end{macrocode}
% \par
% \begin{markdown}
Expand Down
2 changes: 2 additions & 0 deletions tests/support/keyval-setup.tex
Original file line number Diff line number Diff line change
Expand Up @@ -188,4 +188,6 @@
*(Separator|LineBreak) += {\GOBBLE},
(ellipsis|nbsp|*Brace|*Sign|ampersand|underscore|hash|circumflex|backslash|tilde|pipe|replacementCharacter) += {\GOBBLE},
(ticked|halfTicked|unticked)Box += {\GOBBLE},
warning|error = {%
\TYPE{#0: #1}},
}%
38 changes: 38 additions & 0 deletions tests/testfiles/unit/lunamark-markdown/ensure-jekyll-data.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
\markdownSetup{jekyllData=true, expectJekyllData=true, ensureJekyllData=true}
<<<
title: The document title
author:

- name: Author *One*
affiliation: University of Somewhere
- name: Author **Two**
affiliation: University of Nowhere
date: 2022-01-12
...

This test ensures that the Lua `jekyllData`, `expectJekyllData`, and
`ensureJekyllData` correctly propagate through the plain TeX interface.

A document may contain *multiple* metadata blocks:

---
title: 'This is the title: it contains a colon'
author:
- Author One with `inline` markup in *their name*
- Author Two
keywords:
- nothing
- 123
- true
- false
- ~
- null
abstract: |
This is *the abstract*.

It consists of two paragraphs.
---
>>>
BEGIN document
error: parse_blocks failed on: title: The document
END document