summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/generic/markdown/markdown.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2024-04-04 20:36:41 +0000
committerKarl Berry <karl@freefriends.org>2024-04-04 20:36:41 +0000
commit3766631c676475fde9421000e98f976f917855d9 (patch)
tree8624914962c8819671d522a5d3c771ce51336e4f /Master/texmf-dist/source/generic/markdown/markdown.dtx
parent5b5f77ecbb8a99ef21467c8dbff74b015e58332e (diff)
markdown (4apr24)
git-svn-id: svn://tug.org/texlive/trunk@70856 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/generic/markdown/markdown.dtx')
-rw-r--r--Master/texmf-dist/source/generic/markdown/markdown.dtx977
1 files changed, 578 insertions, 399 deletions
diff --git a/Master/texmf-dist/source/generic/markdown/markdown.dtx b/Master/texmf-dist/source/generic/markdown/markdown.dtx
index 5ce5a6496e1..dd4c7367fb8 100644
--- a/Master/texmf-dist/source/generic/markdown/markdown.dtx
+++ b/Master/texmf-dist/source/generic/markdown/markdown.dtx
@@ -104,7 +104,13 @@
\newunicodechar{☒}{\markdownRendererTickedBox}
\newunicodechar{⌛}{\markdownRendererHalfTickedBox}
\newunicodechar{☐}{\markdownRendererUntickedBox}
-\newunicodechar{😉}{;-)}
+\usepackage{emoji}
+\makeatletter
+\@ifpackagelater{emoji}{2020/03/16}{
+ \newunicodechar{😉}{\emoji{winking-face}}
+}{
+ \newunicodechar{😉}{;-)}
+}
\makeatother
% Set up the catcodes.
@@ -1881,7 +1887,7 @@ following text:
> \$\\sqrt{-1}\$ *equals* \$i\$.
>
-> <math><mroot><msqrt><mo>−</mo><mn>1</mn></msqrt></mroot></math>
+> <math><msqrt><mo>−</mo><mn>1</mn></msqrt></math>
> *equals*
> <math><mi>i</mi></math>.
@@ -1924,7 +1930,7 @@ following text:
> \$\\sqrt{-1}\$ *equals* \$i\$.
>
-> <math><mroot><msqrt><mo>−</mo><mn>1</mn></msqrt></mroot></math>
+> <math><msqrt><mo>−</mo><mn>1</mn></msqrt></math>
> *equals*
> <math><mi>i</mi></math>.
@@ -1977,7 +1983,7 @@ following text:
> \$\\sqrt{-1}\$ *equals* \$i\$.
>
-> <math><mroot><msqrt><mo>−</mo><mn>1</mn></msqrt></mroot></math>
+> <math><msqrt><mo>−</mo><mn>1</mn></msqrt></math>
> *equals*
> <math><mi>i</mi></math>.
@@ -5563,15 +5569,15 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> Term 1
->
+>
> : Definition 1
->
+>
> Term 2 with *inline markup*
->
+>
> : Definition 2
->
+>
> { some code, part of Definition 2 }
->
+>
> Third paragraph of definition 2.
##### \Hologo{ConTeXt} Example {.unnumbered}
@@ -5605,15 +5611,15 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> Term 1
->
+>
> : Definition 1
->
+>
> Term 2 with *inline markup*
->
+>
> : Definition 2
->
+>
> { some code, part of Definition 2 }
->
+>
> Third paragraph of definition 2.
%</manual-options>
@@ -7157,7 +7163,7 @@ following text:
> \$\\sqrt {-1}\$ *equals* \$i\$.
>
-> <math><mroot><msqrt><mo>−</mo><mn>1</mn></msqrt></mroot></math>
+> <math><msqrt><mo>−</mo><mn>1</mn></msqrt></math>
> *equals*
> <math><mi>i</mi></math>.
@@ -7199,7 +7205,7 @@ following text:
> \$\\sqrt {-1}\$ *equals* \$i\$.
>
-> <math><mroot><msqrt><mo>−</mo><mn>1</mn></msqrt></mroot></math>
+> <math><msqrt><mo>−</mo><mn>1</mn></msqrt></math>
> *equals*
> <math><mi>i</mi></math>.
@@ -7231,7 +7237,7 @@ following text:
> \$\\sqrt {-1}\$ *equals* \$i\$.
>
-> <math><mroot><msqrt><mo>−</mo><mn>1</mn></msqrt></mroot></math>
+> <math><msqrt><mo>−</mo><mn>1</mn></msqrt></math>
> *equals*
> <math><mi>i</mi></math>.
@@ -7263,7 +7269,7 @@ following text:
> \$\\sqrt {-1}\$ *equals* \$i\$.
>
-> <math><mroot><msqrt><mo>−</mo><mn>1</mn></msqrt></mroot></math>
+> <math><msqrt><mo>−</mo><mn>1</mn></msqrt></math>
> *equals*
> <math><mi>i</mi></math>.
@@ -7295,7 +7301,7 @@ following text:
> \$\\sqrt {-1}\$ *equals* \$i\$.
>
-> <math><mroot><msqrt><mo>−</mo><mn>1</mn></msqrt></mroot></math>
+> <math><msqrt><mo>−</mo><mn>1</mn></msqrt></math>
> *equals*
> <math><mi>i</mi></math>.
@@ -8066,20 +8072,20 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> Here is a note reference,[^1] and another.[^longnote]
->
+>
> [^1]: Here is the note.
->
+>
> [^longnote]: Here's one with multiple blocks.
->
+>
> Subsequent paragraphs are indented to show that they
> belong to the previous note.
->
+>
> { some.code }
->
+>
> The whole paragraph can be indented, or just the
> first line. In this way, multi-paragraph notes
> work like multi-paragraph list items.
->
+>
> This paragraph won't be part of the note, because it
> isn't indented.
@@ -8120,20 +8126,20 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> Here is a note reference,[^1] and another.[^longnote]
->
+>
> [^1]: Here is the note.
->
+>
> [^longnote]: Here's one with multiple blocks.
->
+>
> Subsequent paragraphs are indented to show that they
> belong to the previous note.
->
+>
> { some.code }
->
+>
> The whole paragraph can be indented, or just the
> first line. In this way, multi-paragraph notes
> work like multi-paragraph list items.
->
+>
> This paragraph won't be part of the note, because it
> isn't indented.
@@ -9123,13 +9129,13 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> The following list respects the numbers specified in the markup:
->
+>
> 3. third item
> 4. fourth item
> 5. fifth item
>
> The following list does not respect the numbers specified in the markup:
->
+>
> 1. third item
> 2. fourth item
> 3. fifth item
@@ -9168,13 +9174,13 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> The following list respects the numbers specified in the markup:
->
+>
> 3. third item
> 4. fourth item
> 5. fifth item
>
> The following list does not respect the numbers specified in the markup:
->
+>
> 1. third item
> 2. fourth item
> 3. fifth item
@@ -9812,7 +9818,7 @@ following text:
> | 12 | 12 | 12 | 12 |
> | 123 | 123 | 123 | 123 |
> | 1 | 1 | 1 | 1 |
->
+>
> : Demonstration of pipe table syntax.
##### \Hologo{ConTeXt} Example {.unnumbered}
@@ -9850,7 +9856,7 @@ following text:
> | 12 | 12 | 12 | 12 |
> | 123 | 123 | 123 | 123 |
> | 1 | 1 | 1 | 1 |
->
+>
> : Demonstration of pipe table syntax.
%</manual-options>
@@ -10234,7 +10240,7 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> $E=mc^2$
->
+>
> $$\hat{f} \left ( \xi \right )= \int_{-\infty}^{\infty} f\left ( x \right ) e^{-i2\pi \xi x} dx$$
##### \LaTeX{} Example {.unnumbered}
@@ -10262,7 +10268,7 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> $E=mc^2$
->
+>
> $$\hat{f} \left ( \xi \right )= \int_{-\infty}^{\infty} f\left ( x \right ) e^{-i2\pi \xi x} dx$$
##### \Hologo{ConTeXt} Example {.unnumbered}
@@ -10290,7 +10296,7 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> $E=mc^2$
->
+>
> $$\hat{f} \left ( \xi \right )= \int_{-\infty}^{\infty} f\left ( x \right ) e^{-i2\pi \xi x} dx$$
%</manual-options>
@@ -10445,7 +10451,7 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> \\(E=mc^2\\)
->
+>
> \\[\hat{f} \left ( \xi \right )= \int_{-\infty}^{\infty} f\left ( x \right ) e^{-i2\pi \xi x} dx\\]
##### \LaTeX{} Example {.unnumbered}
@@ -10473,7 +10479,7 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> \\(E=mc^2\\)
->
+>
> \\[\hat{f} \left ( \xi \right )= \int_{-\infty}^{\infty} f\left ( x \right ) e^{-i2\pi \xi x} dx\\]
##### \Hologo{ConTeXt} Example {.unnumbered}
@@ -10501,7 +10507,7 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> \\(E=mc^2\\)
->
+>
> \\[\hat{f} \left ( \xi \right )= \int_{-\infty}^{\infty} f\left ( x \right ) e^{-i2\pi \xi x} dx\\]
%</manual-options>
@@ -10656,7 +10662,7 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> \(E=mc^2\)
->
+>
> \[\hat{f} \left ( \xi \right )= \int_{-\infty}^{\infty} f\left ( x \right ) e^{-i2\pi \xi x} dx\]
##### \LaTeX{} Example {.unnumbered}
@@ -10684,7 +10690,7 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> \(E=mc^2\)
->
+>
> \[\hat{f} \left ( \xi \right )= \int_{-\infty}^{\infty} f\left ( x \right ) e^{-i2\pi \xi x} dx\]
##### \Hologo{ConTeXt} Example {.unnumbered}
@@ -10712,7 +10718,7 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> \(E=mc^2\)
->
+>
> \[\hat{f} \left ( \xi \right )= \int_{-\infty}^{\infty} f\left ( x \right ) e^{-i2\pi \xi x} dx\]
%</manual-options>
@@ -10815,21 +10821,21 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> The following list is tight:
->
+>
> - first item
> - second item
> - third item
->
+>
> The following list is loose:
->
+>
> - first item
> - second item that spans
->
+>
> multiple paragraphs
> - third item
->
+>
> The following list is now also loose:
->
+>
> - first item
>
> - second item
@@ -11298,7 +11304,7 @@ following text:
> \$\\sqrt{-1}\$ *equals* \$i\$.
>
-> <math><mroot><msqrt><mo>−</mo><mn>1</mn></msqrt></mroot></math>
+> <math><msqrt><mo>−</mo><mn>1</mn></msqrt></math>
> *equals*
> <math><mi>i</mi></math>.
@@ -11373,10 +11379,10 @@ pdftex --shell-escape document.tex
% ``` tex
% \input markdown
% a
-% b \markdownBegin c
-% d
+% b \markdownBegin c
+% d
% e \markdownEnd f
-% g
+% g
% \bye
% ```````
%
@@ -12696,7 +12702,7 @@ The following ordered list will be preceded by roman numerals:
\end{markdown}
```````
-Furthermore, we can also specify the name of the snippet in the current
+Furthermore, we can also specify the name of the snippet in the current
namespace, which can be different from the name of the snippet in the
`jdoe/lists` theme. For example, we can make the snippet
`jdoe/lists/romanNumerals` available under the name `roman`.
@@ -13532,11 +13538,11 @@ following text:
> This is a tight list (the first item, the second item, and the third item).
>
> This is a loose list:
->
+>
> - This is the first item.
->
+>
> - This is the second item.
->
+>
> - This is the third item.
##### \LaTeX{} Example {.unnumbered}
@@ -13560,7 +13566,7 @@ following content:
},
ulItemEnd = {},
ulEndTight = {).},
- },
+ },
]
This is a tight list
@@ -13579,7 +13585,7 @@ This is a tight list
ulItem = {\item},
ulItemEnd = {.},
ulEnd = {\end{itemize}},
- },
+ },
]
This is a loose list
@@ -13602,11 +13608,11 @@ following text:
> This is a tight list (the first item, the second item, and the third item).
>
> This is a loose list:
->
+>
> - This is the first item.
->
+>
> - This is the second item.
->
+>
> - This is the third item.
##### \Hologo{ConTeXt} Example {.unnumbered}
@@ -13668,11 +13674,11 @@ following text:
> This is a tight list (the first item, the second item, and the third item).
>
> This is a loose list:
->
+>
> - This is the first item.
->
+>
> - This is the second item.
->
+>
> - This is the third item.
%</manual-tokens>
@@ -13800,7 +13806,7 @@ following text:
The \mdef{markdownRendererTextCite} macro represents a string of one or more
text citations. This macro will only be produced, when the
-\Opt{citations} option is enabled. The macro receives parameters in the same
+\Opt{citations} option is enabled. The macro receives parameters in the same
format as the \mref{markdownRendererCite} macro.
% \end{markdown}
@@ -13926,8 +13932,8 @@ filename of a file contaning the code block contents.
The \mdef{markdownRendererInputFencedCode} macro represents a fenced code
block. This macro will only be produced, when the \Opt{fencedCode} option is
enabled. The macro receives three arguments that correspond to the filename of
-a file contaning the code block contents, the fully escaped code fence infostring
-that can be directly typeset, and the raw code fence infostring that can be used
+a file contaning the code block contents, the fully escaped code fence infostring
+that can be directly typeset, and the raw code fence infostring that can be used
outside typesetting.
% \end{markdown}
@@ -14083,7 +14089,7 @@ following text:
>
> \$\\sqrt{-1}\$ *equals* \$i\$.
>
-> <math><mroot><msqrt><mo>−</mo><mn>1</mn></msqrt></mroot></math>
+> <math><msqrt><mo>−</mo><mn>1</mn></msqrt></math>
> *equals*
> <math><mi>i</mi></math>.
@@ -14124,7 +14130,7 @@ following text:
>
> \$\\sqrt{-1}\$ *equals* \$i\$.
>
-> <math><mroot><msqrt><mo>−</mo><mn>1</mn></msqrt></mroot></math>
+> <math><msqrt><mo>−</mo><mn>1</mn></msqrt></math>
> *equals*
> <math><mi>i</mi></math>.
@@ -14161,7 +14167,7 @@ following text:
>
> \$\\sqrt{-1}\$ *equals* \$i\$.
>
-> <math><mroot><msqrt><mo>−</mo><mn>1</mn></msqrt></mroot></math>
+> <math><msqrt><mo>−</mo><mn>1</mn></msqrt></math>
> *equals*
> <math><mi>i</mi></math>.
@@ -15223,7 +15229,7 @@ following text:
> Hello *world*!
>
> *(The end of a block)*
->
+>
> _Foo_ bar!
%</manual-tokens>
@@ -16395,7 +16401,7 @@ following text:
> - Hello *world*!
>
> *(The end of a block)*
->
+>
> _Foo_ bar!
##### \LaTeX{} Example {.unnumbered}
@@ -16432,7 +16438,7 @@ following text:
> - Hello *world*!
>
> *(The end of a block)*
->
+>
> _Foo_ bar!
##### \Hologo{ConTeXt} Example {.unnumbered}
@@ -16464,7 +16470,7 @@ following text:
> - Hello *world*!
>
> *(The end of a block)*
->
+>
> _Foo_ bar!
%</manual-tokens>
@@ -18080,11 +18086,11 @@ following text:
> This is a tight list (the first item, the second item, and the third item).
>
> This is a loose list:
->
+>
> 1. This is the first item.
->
+>
> 2. This is the second item.
->
+>
> 3. This is the third item.
##### \LaTeX{} Example {.unnumbered}
@@ -18113,7 +18119,7 @@ following content:
},
olItemEnd = {},
olEndTight = {).},
- },
+ },
]
This is a tight list
@@ -18143,7 +18149,7 @@ This is a tight list
},
olItemEnd = {.},
olEnd = {\end{enumerate}},
- },
+ },
]
This is a loose list
@@ -18166,11 +18172,11 @@ following text:
> This is a tight list (the first item, the second item, and the third item).
>
> This is a loose list:
->
+>
> 1. This is the first item.
->
+>
> 2. This is the second item.
->
+>
> 3. This is the third item.
##### \Hologo{ConTeXt} Example {.unnumbered}
@@ -18253,11 +18259,11 @@ following text:
> This is a tight list (the first item, the second item, and the third item).
>
> This is a loose list:
->
+>
> 1. This is the first item.
->
+>
> 2. This is the second item.
->
+>
> 3. This is the third item.
%</manual-tokens>
@@ -19323,7 +19329,7 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> $E=mc^2\dots$
->
+>
> $$\hat{f} \left ( \xi \right )= \int_{-\infty}^{\infty} f\left ( x \right ) e^{-i2\pi \xi x} dx\eqno(1)$$
##### \LaTeX{} Example {.unnumbered}
@@ -19352,7 +19358,7 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> $E=mc^2\dots$
->
+>
> $$\hat{f} \left ( \xi \right )= \int_{-\infty}^{\infty} f\left ( x \right ) e^{-i2\pi \xi x} dx\quad(1)$$
##### \Hologo{ConTeXt} Example {.unnumbered}
@@ -19380,7 +19386,7 @@ A PDF document named `document.pdf` should be produced and contain the
following text:
> $E=mc^2\dots$
->
+>
> $$\hat{f} \left ( \xi \right )= \int_{-\infty}^{\infty} f\left ( x \right ) e^{-i2\pi \xi x} dx\quad(1)$$
%</manual-tokens>
@@ -21053,7 +21059,7 @@ following text:
> \$\\sqrt{-1}\$ *equals* \$i\$.
>
-> <math><mroot><msqrt><mo>−</mo><mn>1</mn></msqrt></mroot></math>
+> <math><msqrt><mo>−</mo><mn>1</mn></msqrt></math>
> *equals*
> <math><mi>i</mi></math>.
@@ -21674,7 +21680,7 @@ following text:
> \$\\sqrt{-1}\$ *equals* \$i\$.
>
-> <math><mroot><msqrt><mo>−</mo><mn>1</mn></msqrt></mroot></math>
+> <math><msqrt><mo>−</mo><mn>1</mn></msqrt></math>
> *equals*
> <math><mi>i</mi></math>.
@@ -22057,19 +22063,6 @@ end
% \par
% \begin{markdown}
%
-% The \luamdef{util.lookup_files} method looks up files with filename `f`
-% and returns their paths. Further options for the \pkg{Kpathsea} library
-% can be specified in table `options`. [@luatex21, Section 10.7.4]
-%
-% \end{markdown}
-% \begin{macrocode}
-function util.lookup_files(f, options)
- return kpse.lookup(f, options)
-end
-% \end{macrocode}
-% \par
-% \begin{markdown}
-%
% The \luamdef{util.expand_tabs_in_line} expands tabs in string `s`. If
% `tabstop` is specified, it is used as the tab stop width. Otherwise,
% the tab stop width of 4 characters is used. The method is a copy of the tab
@@ -24509,7 +24502,7 @@ function entities.char_entity(s)
end
local char_table = {}
for _, code_point in ipairs(code_points) do
- table.insert(char_table, unicode.utf8.char(code_point))
+ table.insert(char_table, unicode.utf8.char(code_point))
end
return table.concat(char_table)
end
@@ -24689,9 +24682,10 @@ function M.writer.new(options)
%
% \end{markdown}
% \begin{macrocode}
+ self.interblocksep_text = "\\markdownRendererInterblockSeparator\n{}"
function self.interblocksep()
if not self.is_writing then return "" end
- return "\\markdownRendererInterblockSeparator\n{}"
+ return self.interblocksep_text
end
% \end{macrocode}
% \par
@@ -24704,9 +24698,24 @@ function M.writer.new(options)
%
% \end{markdown}
% \begin{macrocode}
+ self.paragraphsep_text = "\\markdownRendererParagraphSeparator\n{}"
function self.paragraphsep()
if not self.is_writing then return "" end
- return "\\markdownRendererParagraphSeparator\n{}"
+ return self.paragraphsep_text
+ end
+% \end{macrocode}
+% \par
+% \begin{markdown}
+%
+% Define \luamdef{writer->undosep} as a function that will remove the output
+% produced by an immediately preceding block element / paragraph separator.
+%
+% \end{markdown}
+% \begin{macrocode}
+ self.undosep_text = "\\markdownRendererUndoSeparator\n{}"
+ function self.undosep()
+ if not self.is_writing then return "" end
+ return self.undosep_text
end
% \end{macrocode}
% \par
@@ -25378,6 +25387,7 @@ function M.writer.new(options)
if attributes["#" .. self.slice_end_identifier] ~= nil and
self.slice_end_type == "^" then
if self.is_writing then
+ table.insert(buf, self.undosep())
table.insert(buf, tear_down_attributes())
end
self.is_writing = false
@@ -25429,6 +25439,7 @@ function M.writer.new(options)
if attributes["#" .. self.slice_end_identifier] ~= nil
and self.slice_end_type == "$" then
if self.is_writing then
+ table.insert(buf, self.undosep())
table.insert(buf, tear_down_attributes())
end
self.is_writing = false
@@ -25448,55 +25459,55 @@ function M.writer.new(options)
%
% \end{markdown}
% \begin{macrocode}
-local function create_auto_identifier(s)
- local buffer = {}
- local prev_space = false
- local letter_found = false
+ local function create_auto_identifier(s)
+ local buffer = {}
+ local prev_space = false
+ local letter_found = false
- for _, code in utf8.codes(uni_algos.normalize.NFC(s)) do
- local char = utf8.char(code)
+ for _, code in utf8.codes(uni_algos.normalize.NFC(s)) do
+ local char = utf8.char(code)
- -- Remove everything up to the first letter.
- if not letter_found then
- local is_letter = unicode.utf8.match(char, "%a")
- if is_letter then
- letter_found = true
- else
- goto continue
+ -- Remove everything up to the first letter.
+ if not letter_found then
+ local is_letter = unicode.utf8.match(char, "%a")
+ if is_letter then
+ letter_found = true
+ else
+ goto continue
+ end
end
- end
- -- Remove all non-alphanumeric characters, except underscores, hyphens, and periods.
- if not unicode.utf8.match(char, "[%w_%-%.%s]") then
- goto continue
- end
-
- -- Replace all spaces and newlines with hyphens.
- if unicode.utf8.match(char, "[%s\n]") then
- char = "-"
- if prev_space then
+ -- Remove all non-alphanumeric characters, except underscores, hyphens, and periods.
+ if not unicode.utf8.match(char, "[%w_%-%.%s]") then
goto continue
+ end
+
+ -- Replace all spaces and newlines with hyphens.
+ if unicode.utf8.match(char, "[%s\n]") then
+ char = "-"
+ if prev_space then
+ goto continue
+ else
+ prev_space = true
+ end
else
- prev_space = true
+ -- Convert all alphabetic characters to lowercase.
+ char = unicode.utf8.lower(char)
+ prev_space = false
end
- else
- -- Convert all alphabetic characters to lowercase.
- char = unicode.utf8.lower(char)
- prev_space = false
- end
- table.insert(buffer, char)
+ table.insert(buffer, char)
- ::continue::
- end
+ ::continue::
+ end
- if prev_space then
- table.remove(buffer)
- end
+ if prev_space then
+ table.remove(buffer)
+ end
- local identifier = #buffer == 0 and "section" or table.concat(buffer, "")
- return identifier
-end
+ local identifier = #buffer == 0 and "section" or table.concat(buffer, "")
+ return identifier
+ end
% \end{macrocode}
% \begin{markdown}
%
@@ -25504,56 +25515,56 @@ end
%
% \end{markdown}
% \begin{macrocode}
-local function create_gfm_auto_identifier(s)
- local buffer = {}
- local prev_space = false
- local letter_found = false
+ local function create_gfm_auto_identifier(s)
+ local buffer = {}
+ local prev_space = false
+ local letter_found = false
- for _, code in utf8.codes(uni_algos.normalize.NFC(s)) do
- local char = utf8.char(code)
+ for _, code in utf8.codes(uni_algos.normalize.NFC(s)) do
+ local char = utf8.char(code)
- -- Remove everything up to the first non-space.
- if not letter_found then
- local is_letter = unicode.utf8.match(char, "%S")
- if is_letter then
- letter_found = true
- else
- goto continue
+ -- Remove everything up to the first non-space.
+ if not letter_found then
+ local is_letter = unicode.utf8.match(char, "%S")
+ if is_letter then
+ letter_found = true
+ else
+ goto continue
+ end
end
- end
- -- Remove all non-alphanumeric characters, except underscores and hyphens.
- if not unicode.utf8.match(char, "[%w_%-%s]") then
- prev_space = false
- goto continue
- end
-
- -- Replace all spaces and newlines with hyphens.
- if unicode.utf8.match(char, "[%s\n]") then
- char = "-"
- if prev_space then
+ -- Remove all non-alphanumeric characters, except underscores and hyphens.
+ if not unicode.utf8.match(char, "[%w_%-%s]") then
+ prev_space = false
goto continue
+ end
+
+ -- Replace all spaces and newlines with hyphens.
+ if unicode.utf8.match(char, "[%s\n]") then
+ char = "-"
+ if prev_space then
+ goto continue
+ else
+ prev_space = true
+ end
else
- prev_space = true
+ -- Convert all alphabetic characters to lowercase.
+ char = unicode.utf8.lower(char)
+ prev_space = false
end
- else
- -- Convert all alphabetic characters to lowercase.
- char = unicode.utf8.lower(char)
- prev_space = false
- end
- table.insert(buffer, char)
+ table.insert(buffer, char)
- ::continue::
- end
+ ::continue::
+ end
- if prev_space then
- table.remove(buffer)
- end
+ if prev_space then
+ table.remove(buffer)
+ end
- local identifier = #buffer == 0 and "section" or table.concat(buffer, "")
- return identifier
-end
+ local identifier = #buffer == 0 and "section" or table.concat(buffer, "")
+ return identifier
+ end
% \end{macrocode}
% \par
% \begin{markdown}
@@ -25564,6 +25575,8 @@ end
%
% \end{markdown}
% \begin{macrocode}
+ self.secbegin_text = "\\markdownRendererSectionBegin\n"
+ self.secend_text = "\n\\markdownRendererSectionEnd "
function self.heading(s, level, attributes)
local buf = {}
local flat_text, inlines = table.unpack(s)
@@ -25573,8 +25586,8 @@ end
table.insert(buf,
self.push_attributes("heading",
nil,
- "\\markdownRendererSectionBegin\n",
- "\n\\markdownRendererSectionEnd "))
+ self.secbegin_text,
+ self.secend_text))
end
-- pop attributes for sections that have ended
@@ -25595,8 +25608,8 @@ end
-- push attributes for the new section
local start_output = {}
local end_output = {}
- table.insert(start_output, "\\markdownRendererSectionBegin\n")
- table.insert(end_output, "\n\\markdownRendererSectionEnd ")
+ table.insert(start_output, self.secbegin_text)
+ table.insert(end_output, self.secend_text)
table.insert(buf, self.push_attributes("heading",
normalized_attributes,
@@ -25752,7 +25765,6 @@ parsers.letter = R("AZ","az")
parsers.alphanumeric = R("AZ","az","09")
parsers.keyword = parsers.letter
* (parsers.alphanumeric + parsers.dash)^0
-parsers.internal_punctuation = S(":;,.?")
parsers.doubleasterisks = P("**")
parsers.doubleunderscores = P("__")
@@ -25763,7 +25775,50 @@ parsers.any = P(1)
parsers.succeed = P(true)
parsers.fail = P(false)
-parsers.escapable = S("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~")
+parsers.internal_punctuation = S(":;,.?")
+parsers.ascii_punctuation = S("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~")
+% \end{macrocode}
+% \par
+% \begin{markdown}
+%
+%### Unicode punctuation
+% This section documents [the Unicode punctuation][unicode-punctuation]
+% recognized by the markdown reader. The punctuation is organized in the
+% \luamdef{parsers.punctuation} table according to the number of bytes occupied
+% after conversion to \acro{utf}8.
+%
+% [unicode-punctuation]: https://spec.commonmark.org/0.31.2/#unicode-punctuation-character
+% (CommonMark Spec, Version 0.31.2 (2024-01-28))
+%
+% \end{markdown}
+% \begin{macrocode}
+parsers.punctuation = {}
+(function()
+ local pathname = kpse.lookup("UnicodeData.txt")
+ local file = assert(io.open(pathname, "r"),
+ [[Could not open file "UnicodeData.txt"]])
+ for line in file:lines() do
+ local codepoint, major_category = line:match("^(%x+);[^;]*;(%a)")
+ if major_category == "P" or major_category == "S" then
+ local code = unicode.utf8.char(tonumber(codepoint, 16))
+ if parsers.punctuation[#code] == nil then
+ parsers.punctuation[#code] = parsers.fail
+ end
+ local code_parser = parsers.succeed
+ for i = 1, #code do
+ local byte = code:sub(i, i)
+ local byte_parser = S(byte)
+ code_parser = code_parser
+ * byte_parser
+ end
+ parsers.punctuation[#code] = parsers.punctuation[#code]
+ + code_parser
+ end
+ end
+ assert(file:close())
+end)()
+
+parsers.escapable = parsers.ascii_punctuation
parsers.anyescaped = parsers.backslash / "" * parsers.escapable
+ parsers.any
@@ -25812,8 +25867,8 @@ parsers.leader = parsers.space^-3
% \end{markdown}
% \begin{macrocode}
local function has_trail(indent_table)
- return indent_table ~= nil and
- indent_table.trail ~= nil and
+ return indent_table ~= nil and
+ indent_table.trail ~= nil and
next(indent_table.trail) ~= nil
end
@@ -25825,8 +25880,8 @@ end
% \end{markdown}
% \begin{macrocode}
local function has_indents(indent_table)
- return indent_table ~= nil and
- indent_table.indents ~= nil and
+ return indent_table ~= nil and
+ indent_table.indents ~= nil and
next(indent_table.indents) ~= nil
end
@@ -25902,8 +25957,8 @@ end
%
% Process the spacing of a string of spaces and tabs `spacing` with preceding indent width from
% the start of the line `indent` and strip up to `left_strip_length` spaces. Return the remainder
-% `remainder` and whether there is enough spaces to produce a code `is_code`. Return how many
-% spaces were stripped, as well as if the minimum was met `is_minimum` and what remainder it
+% `remainder` and whether there is enough spaces to produce a code `is_code`. Return how many
+% spaces were stripped, as well as if the minimum was met `is_minimum` and what remainder it
% left `minimum_remainder`.
%
% \end{markdown}
@@ -25947,7 +26002,7 @@ local function process_starter_spacing(indent, spacing, minimum, left_strip_leng
minimum_found = true
minimum_remainder = minimum_remainder .. string.rep(" ", count - minimum)
end
-
+
if (code_started) then
code_start = code_start .. character
elseif (count >= minimum + 4) then
@@ -26119,13 +26174,13 @@ end
%
% Apply the patterns decoded from the indents of the indent table `indent_table`
% iteratively starting at position `index` of the string `s`. If the `is_optional`
-% mode is selected, match as many patterns as possible, else match all or fail.
-% With the option `is_blank`, the parsing behaves as optional after the position
+% mode is selected, match as many patterns as possible, else match all or fail.
+% With the option `is_blank`, the parsing behaves as optional after the position
% of a blank-only indent has been surpassed.
%
% \end{markdown}
% \begin{macrocode}
-local function traverse_indent(s, i, indent_table, is_optional, is_blank)
+local function traverse_indent(s, i, indent_table, is_optional, is_blank, current_line_indents)
local new_index = i
local preceding_indentation = 0
@@ -26133,6 +26188,10 @@ local function traverse_indent(s, i, indent_table, is_optional, is_blank)
local blank_starter = left_blank_starter(indent_table)
+ if current_line_indents == nil then
+ current_line_indents = {}
+ end
+
for index = 1,#indent_table.indents do
local value = indent_table.indents[index]
local pattern = decode_pattern(value.name)
@@ -26142,10 +26201,10 @@ local function traverse_indent(s, i, indent_table, is_optional, is_blank)
if new_indent_info == nil then
local blankline_end = lpeg.match(Ct(parsers.blankline * Cg(Cp(), "pos")), s, new_index)
if is_optional or not indent_table.ignore_blockquote_blank or not blankline_end then
- return is_optional, new_index, current_trail
+ return is_optional, new_index, current_trail, current_line_indents
end
- return traverse_indent(s, tonumber(blankline_end.pos), indent_table, is_optional, is_blank)
+ return traverse_indent(s, tonumber(blankline_end.pos), indent_table, is_optional, is_blank, current_line_indents)
end
local raw_last_trail = new_indent_info[1]
@@ -26158,13 +26217,13 @@ local function traverse_indent(s, i, indent_table, is_optional, is_blank)
-- check previous trail
if not space_only and next(current_trail) == nil then
local sp = process_starter_spacing(0, raw_last_trail, 0, 0)
- current_trail = {is_code=sp.is_code, remainder=sp.remainder, total_length=sp.total_length,
+ current_trail = {is_code=sp.is_code, remainder=sp.remainder, total_length=sp.total_length,
full_remainder=sp.full_remainder}
end
if next(current_trail) ~= nil then
if not space_only and current_trail.is_code then
- return is_optional, new_index, current_trail
+ return is_optional, new_index, current_trail, current_line_indents
end
if current_trail.internal_remainder ~= nil then
raw_last_trail = current_trail.internal_remainder
@@ -26196,7 +26255,7 @@ local function traverse_indent(s, i, indent_table, is_optional, is_blank)
local sp = process_starter_spacing(total_indent_level, spacing_to_process, minimum, left_strip_length)
if space_only and not sp.is_minimum then
- return is_optional or (is_blank and blank_starter <= index), new_index, current_trail
+ return is_optional or (is_blank and blank_starter <= index), new_index, current_trail, current_line_indents
end
local indent_length = raw_last_trail_length + delimiter_length + sp.left_total_stripped
@@ -26210,10 +26269,12 @@ local function traverse_indent(s, i, indent_table, is_optional, is_blank)
current_trail = {is_code=sp.is_code, remainder=sp.remainder, internal_remainder=sp.minimum_remainder,
total_length=sp.total_length, full_remainder=sp.full_remainder}
+
+ current_line_indents[#current_line_indents + 1] = new_indent_info
new_index = next_index
end
- return true, new_index, current_trail
+ return true, new_index, current_trail, current_line_indents
end
% \end{macrocode}
@@ -26230,8 +26291,8 @@ end
% \end{macrocode}
% \begin{markdown}
%
-% Check if the current trail of the `indent_table` would produce code if it is expected `expect_code`
-% or it would not if it is not. If there is no trail, process and check the current spacing `spacing`.
+% Check if the current trail of the `indent_table` would produce code if it is expected `expect_code`
+% or it would not if it is not. If there is no trail, process and check the current spacing `spacing`.
%
% \end{markdown}
% \begin{macrocode}
@@ -26242,7 +26303,7 @@ local function check_trail_joined(s, i, indent_table, spacing, expect_code, omit
if has_trail(indent_table) then
local trail = indent_table.trail
is_code = trail.is_code
- if is_code then
+ if is_code then
remainder = trail.remainder
else
remainder = trail.full_remainder
@@ -26250,7 +26311,7 @@ local function check_trail_joined(s, i, indent_table, spacing, expect_code, omit
else
local sp = process_starter_spacing(0, spacing, 0, 0)
is_code = sp.is_code
- if is_code then
+ if is_code then
remainder = sp.remainder
else
remainder = sp.full_remainder
@@ -26291,7 +26352,7 @@ end
% \end{macrocode}
% \begin{markdown}
%
-% Check the indentation of the continuation line, optionally with
+% Check the indentation of the continuation line, optionally with
% the mode `is_optional` selected. Check blank line exclusively with `is_blank`.
%
% \end{markdown}
@@ -26301,9 +26362,11 @@ local function check_continuation_indentation(s, i, indent_table, is_optional, i
return true
end
- local passes, new_index, current_trail = traverse_indent(s, i, indent_table, is_optional, is_blank)
+ local passes, new_index, current_trail, current_line_indents =
+ traverse_indent(s, i, indent_table, is_optional, is_blank)
if passes then
+ indent_table.current_line_indents = current_line_indents
indent_table = add_trail(indent_table, current_trail)
return new_index, indent_table
end
@@ -26341,7 +26404,7 @@ end
% \end{macrocode}
% \begin{markdown}
%
-% Take the trail `trail` or create a new one from `spacing` and comapre it
+% Take the trail `trail` or create a new one from `spacing` and compare it
% with the expected `trail_type`. On success return the index `i` and the
% remainder of the trail.
%
@@ -26394,25 +26457,25 @@ end
% \end{macrocode}
% \begin{markdown}
%
-% Check the indentation of the continuation line, optionally with
-% the mode `is_optional` selected. Check blank line specifically with `is_blank`.
+% Check the indentation of the continuation line, optionally with
+% the mode `is_optional` selected. Check blank line specifically with `is_blank`.
% Additionally, also directly check the new trail with a type `trail_type`.
%
% \end{markdown}
% \begin{macrocode}
local function check_continuation_indentation_and_trail(s, i, indent_table, is_optional, is_blank, trail_type,
- reset_rem, omit_remainder)
+ reset_rem, omit_remainder)
if not has_indents(indent_table) then
local spacing, new_index = lpeg.match(C(parsers.spacechar^0) * Cp(), s, i)
local result, remainder = check_trail_type(s, i, indent_table.trail, spacing, trail_type)
if remainder == nil then
- if result then
+ if result then
return new_index
end
return false
end
- if result then
- return new_index, remainder
+ if result then
+ return new_index, remainder
end
return false
end
@@ -26431,17 +26494,17 @@ local function check_continuation_indentation_and_trail(s, i, indent_table, is_o
end
local result, remainder = check_trail_type(s, new_index, current_trail, spacing, trail_type)
if remainder == nil or omit_remainder then
- if result then
- return new_index
+ if result then
+ return new_index
end
return false
end
-
+
if is_blank and reset_rem then
remainder = remove_remainder_if_blank(indent_table, remainder)
end
- if result then
- return new_index, remainder
+ if result then
+ return new_index, remainder
end
return false
end
@@ -26516,11 +26579,11 @@ parsers.check_minimal_blank_indent_and_full_code_trail = Cmt( Cb("indent_info")
check_continuation_indentation_and_trail)
parsers.check_minimal_indent_and_any_trail = Cmt( Cb("indent_info")
- * Cc(false) * Cc(false) * Cc("full-any") * Cc(true) * Cc(false),
+ * Cc(false) * Cc(false) * Cc("full-any") * Cc(true) * Cc(false),
check_continuation_indentation_and_trail)
parsers.check_minimal_blank_indent_and_any_trail = Cmt( Cb("indent_info")
- * Cc(false) * Cc(true) * Cc("full-any") * Cc(true) * Cc(false),
+ * Cc(false) * Cc(true) * Cc("full-any") * Cc(true) * Cc(false),
check_continuation_indentation_and_trail)
parsers.check_minimal_blank_indent_and_any_trail_no_rem = Cmt( Cb("indent_info")
@@ -26528,11 +26591,11 @@ parsers.check_minimal_blank_indent_and_any_trail_no_rem = Cmt( Cb("indent_info")
check_continuation_indentation_and_trail)
parsers.check_optional_indent_and_any_trail = Cmt( Cb("indent_info")
- * Cc(true) * Cc(false) * Cc("full-any") * Cc(true) * Cc(false),
+ * Cc(true) * Cc(false) * Cc("full-any") * Cc(true) * Cc(false),
check_continuation_indentation_and_trail)
parsers.check_optional_blank_indent_and_any_trail = Cmt( Cb("indent_info")
- * Cc(true) * Cc(true) * Cc("full-any") * Cc(true) * Cc(false),
+ * Cc(true) * Cc(true) * Cc("full-any") * Cc(true) * Cc(false),
check_continuation_indentation_and_trail)
% \end{macrocode}
@@ -26865,10 +26928,10 @@ parsers.block_keyword =
-- end conditions
parsers.html_blankline_end_condition = parsers.linechar^0
- * ( parsers.newline
- * (parsers.check_minimal_blank_indent_and_any_trail
+ * ( parsers.newline
+ * (parsers.check_minimal_blank_indent_and_any_trail
* #parsers.blankline
- + parsers.check_minimal_indent_and_any_trail)
+ + parsers.check_minimal_indent_and_any_trail)
* parsers.linechar^1)^0
* (parsers.newline^-1 / "")
@@ -26877,10 +26940,10 @@ local function remove_trailing_blank_lines(s)
end
parsers.html_until_end = function(end_marker)
- return Cs(Cs((parsers.newline
- * (parsers.check_minimal_blank_indent_and_any_trail
+ return Cs(Cs((parsers.newline
+ * (parsers.check_minimal_blank_indent_and_any_trail
* #parsers.blankline
- + parsers.check_minimal_indent_and_any_trail)
+ + parsers.check_minimal_indent_and_any_trail)
+ parsers.linechar - end_marker)^0
* parsers.linechar^0 * parsers.newline^-1)
/ remove_trailing_blank_lines)
@@ -26896,27 +26959,27 @@ parsers.html_attribute_name = (parsers.letter + parsers.colon + parsers.undersco
* (parsers.alphanumeric + parsers.colon + parsers.underscore
+ parsers.period + parsers.dash)^0
-parsers.html_attribute_value = parsers.squote
- * (parsers.linechar - parsers.squote)^0
+parsers.html_attribute_value = parsers.squote
+ * (parsers.linechar - parsers.squote)^0
* parsers.squote
- + parsers.dquote
- * (parsers.linechar - parsers.dquote)^0
+ + parsers.dquote
+ * (parsers.linechar - parsers.dquote)^0
* parsers.dquote
+ ( parsers.any - parsers.spacechar - parsers.newline
- parsers.dquote - parsers.squote - parsers.backtick
- parsers.equal - parsers.less - parsers.more)^1
-parsers.html_inline_attribute_value = parsers.squote
+parsers.html_inline_attribute_value = parsers.squote
* (V("NoSoftLineBreakEndline")
+ parsers.any
- parsers.blankline^2
- - parsers.squote)^0
+ - parsers.squote)^0
* parsers.squote
- + parsers.dquote
+ + parsers.dquote
* (V("NoSoftLineBreakEndline")
+ parsers.any
- parsers.blankline^2
- - parsers.dquote)^0
+ - parsers.dquote)^0
* parsers.dquote
+ (parsers.any - parsers.spacechar - parsers.newline
- parsers.dquote - parsers.squote - parsers.backtick
@@ -26944,7 +27007,7 @@ parsers.html_non_newline_attribute = parsers.spacechar^1
* parsers.html_attribute_value_specification^-1
parsers.nested_breaking_blank = parsers.newline
- * parsers.check_minimal_blank_indent
+ * parsers.check_minimal_blank_indent
* parsers.blankline
parsers.html_comment_start = P("<!--")
@@ -26953,10 +27016,10 @@ parsers.html_comment_end = P("-->")
parsers.html_comment = Cs( parsers.html_comment_start
* parsers.html_until_end(parsers.html_comment_end))
-
+
parsers.html_inline_comment = (parsers.html_comment_start / "")
* -P(">") * -P("->")
- * Cs((V("NoSoftLineBreakEndline") + parsers.any - P("--")
+ * Cs((V("NoSoftLineBreakEndline") + parsers.any
- parsers.nested_breaking_blank - parsers.html_comment_end)^0)
* (parsers.html_comment_end / "")
@@ -26980,7 +27043,7 @@ parsers.html_declaration = Cs( parsers.html_declaration_start
* parsers.html_until_end(parsers.html_declaration_end))
parsers.html_inline_declaration = parsers.html_declaration_start
- * Cs(V("NoSoftLineBreakEndline") + parsers.any
+ * Cs(V("NoSoftLineBreakEndline") + parsers.any
- parsers.nested_breaking_blank - parsers.html_declaration_end)^0
* parsers.html_declaration_end
@@ -26992,7 +27055,7 @@ parsers.html_instruction = Cs( parsers.html_instruction_start
* parsers.html_until_end(parsers.html_instruction_end))
parsers.html_inline_instruction = parsers.html_instruction_start
- * Cs(V("NoSoftLineBreakEndline") + parsers.any
+ * Cs(V("NoSoftLineBreakEndline") + parsers.any
- parsers.nested_breaking_blank - parsers.html_instruction_end)^0
* parsers.html_instruction_end
@@ -27135,7 +27198,7 @@ parsers.html_any_block = parsers.html_any_block_opening
parsers.html_inline_comment_full = parsers.html_comment_start
* -P(">") * -P("->")
- * Cs((V("NoSoftLineBreakEndline") + parsers.any - P("--")
+ * Cs((V("NoSoftLineBreakEndline") + parsers.any - P("--")
- parsers.nested_breaking_blank - parsers.html_comment_end)^0)
* parsers.html_comment_end
@@ -27367,7 +27430,7 @@ parsers.heading_start = #parsers.hash * C(parsers.hash^-6)
* -parsers.hash / length
-- parse setext header ending and return level
-parsers.heading_level = parsers.nonindentspace * parsers.equal^1 * parsers.optionalspace * #parsers.newline * Cc(1)
+parsers.heading_level = parsers.nonindentspace * parsers.equal^1 * parsers.optionalspace * #parsers.newline * Cc(1)
+ parsers.nonindentspace * parsers.dash^1 * parsers.optionalspace * #parsers.newline * Cc(2)
local function strip_atx_end(s)
@@ -27377,10 +27440,10 @@ end
parsers.atx_heading = parsers.check_trail_no_rem
* Cg(parsers.heading_start, "level")
* (C( parsers.optionalspace
- * parsers.hash^0
+ * parsers.hash^0
* parsers.optionalspace
* parsers.newline)
- + parsers.spacechar^1
+ + parsers.spacechar^1
* C(parsers.line))
% \end{macrocode}
% \par
@@ -27627,7 +27690,7 @@ function M.reader.new(writer, options)
parsers.minimally_indented_par_or_plain = parsers.minimally_indented_paragraph
+ parsers.minimally_indented_plain
- parsers.minimally_indented_par_or_plain_no_blank = parsers.minimally_indented_par_or_plain
+ parsers.minimally_indented_par_or_plain_no_blank = parsers.minimally_indented_par_or_plain
- parsers.minimally_indented_blankline
parsers.minimally_indented_ref = parsers.check_minimal_indent * V("Reference")
@@ -27653,8 +27716,8 @@ function M.reader.new(writer, options)
% \begin{macrocode}
parsers.separator_loop = function(separated_block, paragraph, block_separator, paragraph_separator)
- return separated_block
- + block_separator
+ return separated_block
+ + block_separator
* paragraph
* separated_block
+ paragraph_separator
@@ -27681,20 +27744,20 @@ function M.reader.new(writer, options)
end
parsers.sep_group_no_output = function(blank)
- return blank^0 * parsers.eof
+ return blank^0 * parsers.eof
+ blank^0
end
parsers.content_blank = parsers.minimally_indented_blankline
- parsers.ref_or_block_separated = parsers.sep_group_no_output(parsers.content_blank)
- * ( parsers.minimally_indented_ref
+ parsers.ref_or_block_separated = parsers.sep_group_no_output(parsers.content_blank)
+ * ( parsers.minimally_indented_ref
- parsers.content_blank)
+ parsers.block_sep_group(parsers.content_blank)
- * ( parsers.minimally_indented_block
+ * ( parsers.minimally_indented_block
- parsers.content_blank)
- parsers.loop_body_pair =
+ parsers.loop_body_pair =
parsers.create_loop_body_pair(parsers.ref_or_block_separated,
parsers.minimally_indented_par_or_plain_no_blank,
parsers.block_sep_group(parsers.content_blank),
@@ -27712,7 +27775,7 @@ function M.reader.new(writer, options)
parsers.indented_content = function()
return Ct( (V("Reference") + (parsers.blankline / ""))
* parsers.content_blank^0
- * parsers.check_minimal_indent
+ * parsers.check_minimal_indent
* parsers.content_loop
+ (V("Reference") + (parsers.blankline / ""))
* parsers.content_blank^0
@@ -27758,7 +27821,7 @@ function M.reader.new(writer, options)
* allowed_end
end
- parsers.starter = parsers.bullet(parsers.dash)
+ parsers.starter = parsers.bullet(parsers.dash)
+ parsers.bullet(parsers.asterisk)
+ parsers.bullet(parsers.plus)
+ parsers.enumerator(parsers.period)
@@ -27842,7 +27905,7 @@ function M.reader.new(writer, options)
% \end{macrocode}
% \begin{markdown}
%
-% Render content between the `opening_index` and `closing_index` in the delimiter table `t`
+% Render content between the `opening_index` and `closing_index` in the delimiter table `t`
% as emphasis.
%
% \end{markdown}
@@ -27856,7 +27919,7 @@ function M.reader.new(writer, options)
% \end{macrocode}
% \begin{markdown}
%
-% Render content between the `opening_index` and `closing_index` in the delimiter table `t`
+% Render content between the `opening_index` and `closing_index` in the delimiter table `t`
% as strong emphasis.
%
% \end{markdown}
@@ -27876,8 +27939,8 @@ function M.reader.new(writer, options)
% \end{markdown}
% \begin{macrocode}
local function breaks_three_rule(opening_delimiter, closing_delimiter)
- return (opening_delimiter.is_closing or closing_delimiter.is_opening) and
- ((opening_delimiter.original_count + closing_delimiter.original_count) % 3 == 0) and
+ return (opening_delimiter.is_closing or closing_delimiter.is_opening) and
+ ((opening_delimiter.original_count + closing_delimiter.original_count) % 3 == 0) and
(opening_delimiter.original_count % 3 ~= 0 or closing_delimiter.original_count % 3 ~= 0)
end
@@ -27940,11 +28003,11 @@ function M.reader.new(writer, options)
while current_position <= max_position do
local value = t[current_position]
-
- if value.type ~= "delimiter" or
- value.element ~= "emphasis" or
- not value.is_active or
- not value.is_closing or
+
+ if value.type ~= "delimiter" or
+ value.element ~= "emphasis" or
+ not value.is_active or
+ not value.is_closing or
(value.current_count <= 0) then
current_position = current_position + 1
goto continue
@@ -27978,7 +28041,7 @@ function M.reader.new(writer, options)
t[current_position].current_count = current_closing_count - 1
fill_emph(t, opener_position, current_position)
end
-
+
::continue::
end
end
@@ -28006,7 +28069,6 @@ function M.reader.new(writer, options)
return lpeg.R("\240\244") * cont * cont * cont
end
end
-
% \end{macrocode}
% \begin{markdown}
%
@@ -28024,15 +28086,22 @@ function M.reader.new(writer, options)
else
char_length = pos + 1
end
- c = lpeg.match({ C(utf8_by_byte_count(char_length)) },s,i+pos)
- if (c ~= nil) and (unicode.utf8.match(c, chartype)) then
- return i
+
+ if (chartype == "punctuation") then
+ if lpeg.match(parsers.punctuation[char_length], s, i+pos) then
+ return i
+ end
+ else
+ c = lpeg.match({ C(utf8_by_byte_count(char_length)) },s,i+pos)
+ if (c ~= nil) and (unicode.utf8.match(c, chartype)) then
+ return i
+ end
end
end
end
local function check_preceding_unicode_punctuation(s, i)
- return check_unicode_type(s, i, -4, -1, "%p")
+ return check_unicode_type(s, i, -4, -1, "punctuation")
end
local function check_preceding_unicode_whitespace(s, i)
@@ -28040,19 +28109,19 @@ function M.reader.new(writer, options)
end
local function check_following_unicode_punctuation(s, i)
- return check_unicode_type(s, i, 0, 3, "%p")
+ return check_unicode_type(s, i, 0, 3, "punctuation")
end
local function check_following_unicode_whitespace(s, i)
return check_unicode_type(s, i, 0, 3, "%s")
end
- parsers.unicode_preceding_punctuation = B(parsers.escapable)
+ parsers.unicode_preceding_punctuation = B(parsers.escapable)
+ Cmt(parsers.succeed, check_preceding_unicode_punctuation)
parsers.unicode_preceding_whitespace = Cmt(parsers.succeed, check_preceding_unicode_whitespace)
- parsers.unicode_following_punctuation = #parsers.escapable
+ parsers.unicode_following_punctuation = #parsers.escapable
+ Cmt(parsers.succeed, check_following_unicode_punctuation)
parsers.unicode_following_whitespace = Cmt(parsers.succeed, check_following_unicode_whitespace)
@@ -28064,8 +28133,8 @@ function M.reader.new(writer, options)
end
parsers.left_flanking_delimiter_run = function(character)
- return (B( parsers.any)
- * (parsers.unicode_preceding_punctuation + parsers.unicode_preceding_whitespace)
+ return (B( parsers.any)
+ * (parsers.unicode_preceding_punctuation + parsers.unicode_preceding_whitespace)
+ -B(parsers.any))
* parsers.delimiter_run(character)
* parsers.unicode_following_punctuation
@@ -28079,7 +28148,7 @@ function M.reader.new(writer, options)
* parsers.delimiter_run(character)
* (parsers.unicode_following_punctuation + parsers.unicode_following_whitespace
+ parsers.eof)
- + (B(parsers.any)
+ + (B(parsers.any)
* -(parsers.unicode_preceding_punctuation + parsers.unicode_preceding_whitespace))
* parsers.delimiter_run(character)
end
@@ -28087,13 +28156,13 @@ function M.reader.new(writer, options)
if options.underscores then
parsers.emph_start = parsers.left_flanking_delimiter_run(parsers.asterisk)
+ (-#parsers.right_flanking_delimiter_run(parsers.underscore)
- + (parsers.unicode_preceding_punctuation
+ + (parsers.unicode_preceding_punctuation
* #parsers.right_flanking_delimiter_run(parsers.underscore)))
* parsers.left_flanking_delimiter_run(parsers.underscore)
parsers.emph_end = parsers.right_flanking_delimiter_run(parsers.asterisk)
+ (-#parsers.left_flanking_delimiter_run(parsers.underscore)
- + #(parsers.left_flanking_delimiter_run(parsers.underscore)
+ + #(parsers.left_flanking_delimiter_run(parsers.underscore)
* parsers.unicode_following_punctuation))
* parsers.right_flanking_delimiter_run(parsers.underscore)
else
@@ -28115,7 +28184,7 @@ function M.reader.new(writer, options)
* Cg(Cc(true), "is_opening")
* Cg(Cc(false), "is_closing"))
- parsers.emph_capturing_close = Ct( Cg(Cc("delimiter"), "type")
+ parsers.emph_capturing_close = Ct( Cg(Cc("delimiter"), "type")
* Cg(Cc("emphasis"), "element")
* Cg(C(parsers.emph_end), "content")
* Cg(Cc(false), "is_opening")
@@ -28281,20 +28350,20 @@ function M.reader.new(writer, options)
end
parsers.link_and_emph_endline = parsers.newline
- * ((parsers.check_minimal_indent
- * -V("EndlineExceptions")
- + parsers.check_optional_indent
- * -V("EndlineExceptions")
+ * ((parsers.check_minimal_indent
+ * -V("EndlineExceptions")
+ + parsers.check_optional_indent
+ * -V("EndlineExceptions")
* -parsers.starter) / "")
* parsers.spacechar^0 / "\n"
parsers.link_and_emph_content = Ct( Cg(Cc("content"), "type")
- * Cg(Cs(( parsers.link_emph_precedence
+ * Cg(Cs(( parsers.link_emph_precedence
+ parsers.backslash * parsers.any
+ parsers.link_and_emph_endline
+ (parsers.linechar
- parsers.blankline^2
- - parsers.link_image_open_or_close
+ - parsers.link_image_open_or_close
- parsers.emph_open_or_close))^0), "content"))
parsers.link_and_emph_table = (parsers.link_image_opening + parsers.emph_open)
@@ -28330,7 +28399,7 @@ function M.reader.new(writer, options)
local value = t[i]
if value.type == "delimiter" and
value.is_opening and
- (value.element == "link" or value.element == "image")
+ (value.element == "link" or value.element == "image")
and not value.removed then
if value.is_active then
return i
@@ -28455,8 +28524,8 @@ function M.reader.new(writer, options)
% \end{macrocode}
% \begin{markdown}
%
-% Parse content between two delimiters in the delimiter table `t`. Produce the respective link and image
-% macros.
+% Parse content between two delimiters in the delimiter table `t`. Produce the respective link and image
+% macros.
%
% \end{markdown}
% \begin{macrocode}
@@ -28538,7 +28607,7 @@ function M.reader.new(writer, options)
% \end{macrocode}
% \begin{markdown}
%
-% Resolve an inline link [a](b "c") from the delimiters at `opening_index` and `closing_index`
+% Resolve an inline link [a](b "c") from the delimiters at `opening_index` and `closing_index`
% within a delimiter table `t`. Here, compared to other types of links, no reference definition is needed.
%
% \end{markdown}
@@ -28571,7 +28640,7 @@ function M.reader.new(writer, options)
% \begin{markdown}
%
% Resolve a full link [a][b] from the delimiters at `opening_index` and `closing_index` within a delimiter table `t`.
-% Continue if a tag `b` is not found in the references.
+% Continue if a tag `b` is not found in the references.
%
% \end{markdown}
% \begin{macrocode}
@@ -28581,7 +28650,7 @@ function M.reader.new(writer, options)
local r = self.lookup_reference(next_link_content)
if r then
- local inline_content = resolve_inline_following_content(t, next_link_closing_index, false,
+ local inline_content = resolve_inline_following_content(t, next_link_closing_index, false,
t.match_link_attributes)
r.attributes = join_attributes(r.attributes, inline_content.attributes)
render_link_or_image(t, opening_index, next_link_closing_index, closing_index, r)
@@ -28591,9 +28660,9 @@ function M.reader.new(writer, options)
% \end{macrocode}
% \begin{markdown}
%
-% Resolve a collapsed link [a][] from the delimiters at `opening_index` and `closing_index`
+% Resolve a collapsed link [a][] from the delimiters at `opening_index` and `closing_index`
% within a delimiter table `t`.
-% Continue if a tag `a` is not found in the references.
+% Continue if a tag `a` is not found in the references.
%
% \end{markdown}
% \begin{macrocode}
@@ -28613,7 +28682,7 @@ function M.reader.new(writer, options)
% \begin{markdown}
%
% Parse a table of link and emphasis delimiters `t`.
-% First, iterate over the link delimiters and produce either link or image macros.
+% First, iterate over the link delimiters and produce either link or image macros.
% Then run `process_emphasis` over the entire delimiter table, resolving emphasis and strong
% emphasis and parsing any content outside of closed delimiters.
%
@@ -28625,8 +28694,8 @@ function M.reader.new(writer, options)
end
for i,value in ipairs(t) do
- if not value.is_closing or
- value.type ~= "delimiter" or
+ if not value.is_closing or
+ value.type ~= "delimiter" or
not (value.element == "link" or value.element == "image") then
goto continue
end
@@ -28640,7 +28709,7 @@ function M.reader.new(writer, options)
opening_delimiter.removed = true
local link_type = opening_delimiter.link_type
-
+
if (link_type == "inline") then
resolve_inline_link(t, opener_position, i)
end
@@ -28657,7 +28726,7 @@ function M.reader.new(writer, options)
::continue::
end
- t[#t].content = t[#t].content:gsub("%s*$","")
+ t[#t].content = t[#t].content:gsub("%s*$","")
process_emphasis(t, 1, #t)
local final_result = collect_emphasis_content(t, 1, #t)
@@ -28706,7 +28775,7 @@ function M.reader.new(writer, options)
parsers.interrupting_bullets = parsers.fail
parsers.interrupting_enumerators = parsers.fail
else
- parsers.interrupting_bullets = parsers.bullet(parsers.dash, true)
+ parsers.interrupting_bullets = parsers.bullet(parsers.dash, true)
+ parsers.bullet(parsers.asterisk, true)
+ parsers.bullet(parsers.plus, true)
@@ -28756,17 +28825,17 @@ function M.reader.new(writer, options)
parsers.NoSoftLineBreakEndline
= parsers.newline
- * (parsers.check_minimal_indent
- * -V("NoSoftLineBreakEndlineExceptions")
- + parsers.check_optional_indent
- * -V("NoSoftLineBreakEndlineExceptions")
+ * (parsers.check_minimal_indent
+ * -V("NoSoftLineBreakEndlineExceptions")
+ + parsers.check_optional_indent
+ * -V("NoSoftLineBreakEndlineExceptions")
* -parsers.starter)
* parsers.spacechar^0
/ writer.space
parsers.EndlineBreak = parsers.backslash * parsers.Endline
/ writer.hard_line_break
-
+
parsers.OptionalIndent
= parsers.spacechar^1 / writer.space
@@ -28790,7 +28859,7 @@ function M.reader.new(writer, options)
/ writer.soft_line_break
parsers.NonbreakingSpace
- = parsers.spacechar^2 * parsers.Endline
+ = parsers.spacechar^2 * parsers.Endline
/ writer.hard_line_break
+ parsers.spacechar^1 * parsers.Endline^-1 * parsers.eof / ""
+ parsers.spacechar^1 * parsers.Endline
@@ -28864,23 +28933,23 @@ end
%
% \end{markdown}
% \begin{macrocode}
- parsers.DisplayHtml = Cs(parsers.check_trail
- * ( parsers.html_comment
- + parsers.html_special_block
- + parsers.html_block
- + parsers.html_any_block
- + parsers.html_instruction
- + parsers.html_cdatasection
+ parsers.DisplayHtml = Cs(parsers.check_trail
+ * ( parsers.html_comment
+ + parsers.html_special_block
+ + parsers.html_block
+ + parsers.html_any_block
+ + parsers.html_instruction
+ + parsers.html_cdatasection
+ parsers.html_declaration))
/ writer.block_html_element
parsers.indented_non_blank_line = parsers.indentedline - parsers.blankline
- parsers.Verbatim = Cs(
- parsers.check_code_trail
+ parsers.Verbatim = Cs(
+ parsers.check_code_trail
* (parsers.line - parsers.blankline)
* ((parsers.check_minimal_blank_indent_and_full_code_trail * parsers.blankline)^0
- * ((parsers.check_minimal_indent / "") * parsers.check_code_trail
+ * ((parsers.check_minimal_indent / "") * parsers.check_code_trail
* (parsers.line - parsers.blankline))^1)^0
) / self.expandtabs / writer.verbatim
@@ -28921,23 +28990,23 @@ end
parsers.list_blank = parsers.conditionally_indented_blankline
- parsers.ref_or_block_list_separated = parsers.sep_group_no_output(parsers.list_blank)
+ parsers.ref_or_block_list_separated = parsers.sep_group_no_output(parsers.list_blank)
* parsers.minimally_indented_ref
+ parsers.block_sep_group(parsers.list_blank)
* parsers.minimally_indented_block
parsers.ref_or_block_non_separated = parsers.minimally_indented_ref
- + (parsers.succeed / writer.interblocksep)
+ + (parsers.succeed / writer.interblocksep)
* parsers.minimally_indented_block
- parsers.minimally_indented_blankline
- parsers.tight_list_loop_body_pair =
+ parsers.tight_list_loop_body_pair =
parsers.create_loop_body_pair(parsers.ref_or_block_non_separated,
parsers.minimally_indented_par_or_plain_no_blank,
(parsers.succeed / writer.interblocksep),
(parsers.succeed / writer.paragraphsep))
- parsers.loose_list_loop_body_pair =
+ parsers.loose_list_loop_body_pair =
parsers.create_loop_body_pair(parsers.ref_or_block_list_separated,
parsers.minimally_indented_par_or_plain,
parsers.block_sep_group(parsers.list_blank),
@@ -28969,7 +29038,7 @@ end
* #parsers.list_blank
* remove_indent("li")
+ ( (V("Reference") + (parsers.blankline / ""))
- * parsers.check_minimal_indent
+ * parsers.check_minimal_indent
* parsers.tight_list_content_loop
+ (V("Reference") + (parsers.blankline / ""))
+ (parsers.tickbox^-1 / writer.escape)
@@ -28977,11 +29046,11 @@ end
)
* parsers.list_item_tightness_condition
)
-
+
parsers.indented_content_loose = Ct( (parsers.blankline / "")
* #parsers.list_blank
+ ( (V("Reference") + (parsers.blankline / ""))
- * parsers.check_minimal_indent
+ * parsers.check_minimal_indent
* parsers.loose_list_content_loop
+ (V("Reference") + (parsers.blankline / ""))
+ (parsers.tickbox^-1 / writer.escape)
@@ -29004,7 +29073,7 @@ end
parsers.BulletListOfType = function(bullet_type)
local bullet = parsers.bullet(bullet_type)
- return ( Ct( parsers.TightListItem(bullet)
+ return ( Ct( parsers.TightListItem(bullet)
* ( (parsers.check_minimal_indent / "")
* parsers.TightListItem(bullet)
)^0
@@ -29024,7 +29093,7 @@ end
) / writer.bulletlist
end
- parsers.BulletList = parsers.BulletListOfType(parsers.dash)
+ parsers.BulletList = parsers.BulletListOfType(parsers.dash)
+ parsers.BulletListOfType(parsers.asterisk)
+ parsers.BulletListOfType(parsers.plus)
@@ -29046,11 +29115,11 @@ end
return Cg(enumerator, "listtype")
* (Ct( parsers.TightListItem(Cb("listtype"))
* ((parsers.check_minimal_indent / "") * parsers.TightListItem(enumerator))^0)
- * Cc(true)
- * -#((parsers.list_blank^0 / "")
+ * Cc(true)
+ * -#((parsers.list_blank^0 / "")
* parsers.check_minimal_indent * enumerator)
+ Ct( parsers.LooseListItem(Cb("listtype"))
- * ((parsers.list_blank^0 / "")
+ * ((parsers.list_blank^0 / "")
* (parsers.check_minimal_indent / "") * parsers.LooseListItem(enumerator))^0)
* Cc(false)
) * Ct(Cb("listtype")) / ordered_list
@@ -29090,10 +29159,10 @@ end
parsers.AtxHeading = parsers.check_trail_no_rem
* Cg(parsers.heading_start, "level")
* ((C( parsers.optionalspace
- * parsers.hash^0
+ * parsers.hash^0
* parsers.optionalspace
* parsers.newline)
- + parsers.spacechar^1
+ + parsers.spacechar^1
* C(parsers.line))
/ strip_atx_end
/ parsers.parse_heading_text)
@@ -29108,7 +29177,7 @@ end
* parsers.newline^-1
parsers.SetextHeading = parsers.freeze_trail * parsers.check_trail_no_rem
- * #(parsers.heading_text
+ * #(parsers.heading_text
* parsers.check_minimal_indent * parsers.check_trail * parsers.heading_level)
* Cs(parsers.heading_text)
/ parsers.parse_heading_text
@@ -29637,16 +29706,59 @@ end
table.sort(opt_string)
local salt = table.concat(opt_string, ",") .. "," .. metadata.version
local output
+ local function convert(input)
+ local document = self.parser_functions.parse_blocks(input)
+ local output = util.rope_to_string(writer.document(document))
+% \end{macrocode}
+% \begin{markdown}
+% Remove block element / paragraph separators immediately followed by the
+% output of \luamref{writer->undosep}, possibly interleaved by section ends.
+% Then, remove any leftover output of \luamref{writer->undosep}.
+% \end{markdown}
+% \begin{macrocode}
+ local undosep_start, undosep_end
+ local potential_secend_start, secend_start
+ local potential_sep_start, sep_start
+ while true do
+ -- find a `writer->undosep`
+ undosep_start, undosep_end = output:find(writer.undosep_text, 1, true)
+ if undosep_start == nil then break end
+ -- skip any preceding section ends
+ secend_start = undosep_start
+ while true do
+ potential_secend_start = secend_start - #writer.secend_text
+ if potential_secend_start < 1
+ or output:sub(potential_secend_start, secend_start - 1) ~= writer.secend_text then
+ break
+ end
+ secend_start = potential_secend_start
+ end
+ -- find an immediately preceding block element / paragraph separator
+ sep_start = secend_start
+ potential_sep_start = sep_start - #writer.interblocksep_text
+ if potential_sep_start >= 1
+ and output:sub(potential_sep_start, sep_start - 1) == writer.interblocksep_text then
+ sep_start = potential_sep_start
+ else
+ potential_sep_start = sep_start - #writer.paragraphsep_text
+ if potential_sep_start >= 1
+ and output:sub(potential_sep_start, sep_start - 1) == writer.paragraphsep_text then
+ sep_start = potential_sep_start
+ end
+ end
+ -- remove `writer->undosep` and immediately preceding block element / paragraph separator
+ output = output:sub(1, sep_start - 1)
+ .. output:sub(secend_start, undosep_start - 1)
+ .. output:sub(undosep_end + 1)
+ end
+ return output
+ end
% \end{macrocode}
% \begin{markdown}
% If we cache markdown documents, produce the cache file and transform its
% filename to plain \TeX{} output via the \luamref{writer->pack} method.
% \end{markdown}
% \begin{macrocode}
- local function convert(input)
- local document = self.parser_functions.parse_blocks(input)
- return util.rope_to_string(writer.document(document))
- end
if options.eagerCache or options.finalizeCache then
local name = util.cache(options.cacheDir, input, salt, convert,
".md" .. writer.suffix)
@@ -29840,11 +29952,11 @@ M.extensions.citations = function(citation_nbsps)
+ parsers.bracketed
+ parsers.inticks
+ parsers.autolink
- + V("InlineHtml")
+ + V("InlineHtml")
+ V("Space") + V("Endline")
+ (parsers.anyescaped
- (parsers.newline + parsers.rbracket + parsers.blankline^2))
- - (parsers.spnl * parsers.dash^-1 * parsers.at))^0)
+ - (parsers.spnl * parsers.dash^-1 * parsers.at))^1)
local citation_body_postnote
= Cs((parsers.alphanumeric^1
@@ -29856,18 +29968,28 @@ M.extensions.citations = function(citation_nbsps)
+ (parsers.anyescaped
- (parsers.newline + parsers.rbracket + parsers.semicolon
+ parsers.blankline^2))
- - (parsers.spnl * parsers.rbracket))^0)
+ - (parsers.spnl * parsers.rbracket))^1)
local citation_body_chunk
- = citation_body_prenote
- * parsers.spnlc * citation_name
+ = ( citation_body_prenote
+ * parsers.spnlc_sep
+ + Cc("")
+ * parsers.spnlc
+ )
+ * citation_name
* (parsers.internal_punctuation - parsers.semicolon)^-1
- * parsers.spnlc * citation_body_postnote
+ * ( parsers.spnlc
+ * citation_body_postnote
+ + Cc("")
+ * parsers.spnlc
+ )
local citation_body
= citation_body_chunk
- * (parsers.semicolon * parsers.spnlc
- * citation_body_chunk)^0
+ * ( parsers.semicolon
+ * parsers.spnlc
+ * citation_body_chunk
+ )^0
local citation_headless_body_postnote
= Cs((parsers.alphanumeric^1
@@ -29883,8 +30005,10 @@ M.extensions.citations = function(citation_nbsps)
local citation_headless_body
= citation_headless_body_postnote
- * (parsers.sp * parsers.semicolon * parsers.spnlc
- * citation_body_chunk)^0
+ * ( parsers.semicolon
+ * parsers.spnlc
+ * citation_body_chunk
+ )^0
local citations
= function(text_cites, raw_cites)
@@ -29969,7 +30093,7 @@ M.extensions.content_blocks = function(language_map)
% \begin{macrocode}
local languages_json = (function()
local base, prev, curr
- for _, pathname in ipairs{util.lookup_files(language_map, { all=true })} do
+ for _, pathname in ipairs{kpse.lookup(language_map, { all=true })} do
local file = io.open(pathname, "r")
if not file then goto continue end
local input = assert(file:read("*a"))
@@ -30180,7 +30304,7 @@ M.extensions.definition_lists = function(tight_lists)
local indented_blocks = function(bl)
return Cs( bl
- * (blank^1 * (parsers.check_minimal_indent / "")
+ * (blank^1 * (parsers.check_minimal_indent / "")
* parsers.check_code_trail * -parsers.blankline * bl)^0
* (blank^1 + parsers.eof))
end
@@ -30348,7 +30472,7 @@ M.extensions.fancy_lists = function()
local digit_marker = parsers.dig * parsers.dig^-8
- local markers = {
+ local markers = {
{lowercase_opening_roman_marker, lowercase_roman_marker},
{uppercase_opening_roman_marker, uppercase_roman_marker},
lowercase_letter_marker,
@@ -30358,9 +30482,9 @@ M.extensions.fancy_lists = function()
digit_marker
}
- local delims = {
- parsers.period,
- parsers.rparent
+ local delims = {
+ parsers.period,
+ parsers.rparent
}
local markers_table = combine_markers_and_delims(markers, delims)
@@ -30466,11 +30590,11 @@ M.extensions.fancy_lists = function()
return Cg(enumerator_start, "listtype")
* (Ct( TightListItem(Cb("listtype"))
* ((parsers.check_minimal_indent / "") * TightListItem(enumerator_cont))^0)
- * Cc(true)
- * -#((parsers.conditionally_indented_blankline^0 / "")
+ * Cc(true)
+ * -#((parsers.conditionally_indented_blankline^0 / "")
* parsers.check_minimal_indent * enumerator_cont)
+ Ct( LooseListItem(Cb("listtype"))
- * ((parsers.conditionally_indented_blankline^0 / "")
+ * ((parsers.conditionally_indented_blankline^0 / "")
* (parsers.check_minimal_indent / "") * LooseListItem(enumerator_cont))^0)
* Cc(false)
) * Ct(Cb("listtype")) / fancylist
@@ -30479,10 +30603,10 @@ M.extensions.fancy_lists = function()
local FancyList = join_table_with_func(FancyListOfType, markers_table)
local Endline = parsers.newline
- * (parsers.check_minimal_indent
- * -parsers.EndlineExceptions
- + parsers.check_optional_indent
- * -parsers.EndlineExceptions
+ * (parsers.check_minimal_indent
+ * -parsers.EndlineExceptions
+ + parsers.check_optional_indent
+ * -parsers.EndlineExceptions
* -starter)
* parsers.spacechar^0
/ writer.soft_line_break
@@ -30574,12 +30698,12 @@ M.extensions.fenced_code = function(blank_before_code_fence,
return str:gsub("^%s*(.-)%s*$", "%1")
end
- local tilde_infostring = Cs(Cs((V("HtmlEntity")
- + parsers.anyescaped
+ local tilde_infostring = Cs(Cs((V("HtmlEntity")
+ + parsers.anyescaped
- parsers.newline)^0)
/ strip_enclosing_whitespaces)
- local backtick_infostring = Cs(Cs((V("HtmlEntity")
+ local backtick_infostring = Cs(Cs((V("HtmlEntity")
+ (-#(parsers.backslash * parsers.backtick) * parsers.anyescaped)
- parsers.newline
- parsers.backtick)^0)
@@ -30588,14 +30712,14 @@ M.extensions.fenced_code = function(blank_before_code_fence,
local fenceindent
local function has_trail(indent_table)
- return indent_table ~= nil and
- indent_table.trail ~= nil and
+ return indent_table ~= nil and
+ indent_table.trail ~= nil and
next(indent_table.trail) ~= nil
end
local function has_indents(indent_table)
- return indent_table ~= nil and
- indent_table.indents ~= nil and
+ return indent_table ~= nil and
+ indent_table.indents ~= nil and
next(indent_table.indents) ~= nil
end
@@ -30808,24 +30932,57 @@ M.extensions.fenced_divs = function(blank_before_div_fence)
% \par
% \begin{markdown}
%
-% Initialize a named group named `div_level` for tracking how deep we are
-% nested in divs.
+% Initialize a named group named `fenced_div_level` for tracking how deep
+% we are nested in divs and the named group `fenced_div_num_opening_indents`
+% for tracking the indent of the starting div fence. The former named group
+% is immutable and should roll back properly when we fail to match a fenced
+% div. The latter is mutable and may contain items from unsuccessful matches
+% on top. However, we always know how many items at the head of the latter we
+% can trust by consulting the former.
%
% \end{markdown}
% \begin{macrocode}
- self.initialize_named_group("div_level", "0")
+ self.initialize_named_group("fenced_div_level", "0")
+ self.initialize_named_group("fenced_div_num_opening_indents")
- local function increment_div_level(increment)
- local function update_div_level(s, i, current_level) -- luacheck: ignore s i
- current_level = tonumber(current_level)
- local next_level = tostring(current_level + increment)
- return true, next_level
+ local function increment_div_level()
+ local function push_indent_table(s, i, indent_table, -- luacheck: ignore s i
+ fenced_div_num_opening_indents, fenced_div_level)
+ fenced_div_level = tonumber(fenced_div_level) + 1
+ local num_opening_indents = 0
+ if indent_table.indents ~= nil then
+ num_opening_indents = #indent_table.indents
+ end
+ fenced_div_num_opening_indents[fenced_div_level] = num_opening_indents
+ return true, fenced_div_num_opening_indents
end
- return Cg( Cmt(Cb("div_level"), update_div_level)
- , "div_level")
+ local function increment_level(s, i, fenced_div_level) -- luacheck: ignore s i
+ fenced_div_level = tonumber(fenced_div_level) + 1
+ return true, tostring(fenced_div_level)
+ end
+
+ return Cg( Cmt( Cb("indent_info")
+ * Cb("fenced_div_num_opening_indents")
+ * Cb("fenced_div_level"), push_indent_table)
+ , "fenced_div_num_opening_indents")
+ * Cg( Cmt( Cb("fenced_div_level"), increment_level)
+ , "fenced_div_level")
end
-
+
+ local function decrement_div_level()
+ local function pop_indent_table(s, i, fenced_div_indent_table, fenced_div_level) -- luacheck: ignore s i
+ fenced_div_level = tonumber(fenced_div_level)
+ fenced_div_indent_table[fenced_div_level] = nil
+ return true, tostring(fenced_div_level - 1)
+ end
+
+ return Cg( Cmt( Cb("fenced_div_num_opening_indents")
+ * Cb("fenced_div_level"), pop_indent_table)
+ , "fenced_div_level")
+ end
+
+
local non_fenced_div_block = parsers.check_minimal_indent * V("Block")
- parsers.check_minimal_indent_and_trail * fenced_div_end
@@ -30860,11 +31017,12 @@ M.extensions.fenced_divs = function(blank_before_div_fence)
return attr
end
/ writer.div_begin
- * increment_div_level(1)
+ * increment_div_level()
* parsers.skipblanklines
* Ct(content_loop)
* parsers.minimally_indented_blank^0
- * parsers.check_minimal_indent_and_trail * fenced_div_end * increment_div_level(-1)
+ * parsers.check_minimal_indent_and_trail * fenced_div_end
+ * decrement_div_level()
* (Cc("") / writer.div_end)
self.insert_pattern("Block after Verbatim",
@@ -30878,17 +31036,38 @@ M.extensions.fenced_divs = function(blank_before_div_fence)
%
% If the `blank_before_div_fence` parameter is `false`, we will have the
% closing div at the beginning of a line break the current paragraph if
-% we are currently nested in a div.
+% we are currently nested in a div and the indentation matches the opening
+% div fence.
%
% \end{markdown}
% \begin{macrocode}
- local function check_div_level(s, i, current_level) -- luacheck: ignore s i
- current_level = tonumber(current_level)
- return current_level > 0
+ local function is_inside_div()
+ local function check_div_level(s, i, fenced_div_level) -- luacheck: ignore s i
+ fenced_div_level = tonumber(fenced_div_level)
+ return fenced_div_level > 0
+ end
+
+ return Cmt(Cb("fenced_div_level"), check_div_level)
+ end
+
+ local function check_indent()
+ local function compare_indent(s, i, indent_table, -- luacheck: ignore s i
+ fenced_div_num_opening_indents, fenced_div_level)
+ fenced_div_level = tonumber(fenced_div_level)
+ local num_current_indents = (indent_table.current_line_indents ~= nil and
+ #indent_table.current_line_indents) or 0
+ local num_opening_indents = fenced_div_num_opening_indents[fenced_div_level]
+ return num_current_indents == num_opening_indents
+ end
+
+ return Cmt( Cb("indent_info")
+ * Cb("fenced_div_num_opening_indents")
+ * Cb("fenced_div_level"), compare_indent)
end
- local is_inside_div = Cmt(Cb("div_level"), check_div_level)
- local fencestart = is_inside_div * fenced_div_end
+ local fencestart = is_inside_div()
+ * fenced_div_end
+ * check_indent()
if not blank_before_div_fence then
self.update_rule("EndlineExceptions", function(previous_pattern)
@@ -30945,10 +31124,10 @@ M.extensions.header_attributes = function()
return s:gsub("%s*$","")
end
- local heading_line = (parsers.linechar
+ local heading_line = (parsers.linechar
- (parsers.attributes
* parsers.optionalspace
- * parsers.newline))^1
+ * parsers.newline))^1
- parsers.thematic_break_lines
local heading_text = heading_line
@@ -30956,7 +31135,7 @@ M.extensions.header_attributes = function()
* parsers.newline^-1
local SetextHeading = parsers.freeze_trail * parsers.check_trail_no_rem
- * #(heading_text
+ * #(heading_text
* (parsers.attributes
* parsers.optionalspace
* parsers.newline)^-1
@@ -31131,7 +31310,7 @@ M.extensions.link_attributes = function()
% \begin{macrocode}
local define_reference_parser = (parsers.check_trail / "") * parsers.link_label * parsers.colon
* parsers.spnlc * parsers.url
- * ( parsers.spnlc_sep * parsers.title * (parsers.spnlc * Ct(parsers.attributes))
+ * ( parsers.spnlc_sep * parsers.title * (parsers.spnlc * Ct(parsers.attributes))
* parsers.only_blank
+ parsers.spnlc_sep * parsers.title * parsers.only_blank
+ Cc("") * (parsers.spnlc * Ct(parsers.attributes)) * parsers.only_blank
@@ -31284,7 +31463,7 @@ M.extensions.notes = function(notes, inline_notes)
local indented_blocks = function(bl)
return Cs( bl
- * (blank^1 * (parsers.check_optional_indent / "")
+ * (blank^1 * (parsers.check_optional_indent / "")
* parsers.check_code_trail * -parsers.blankline * bl)^0)
end
@@ -31447,7 +31626,7 @@ M.extensions.pipe_tables = function(table_captions, table_attributes)
, table_hline_separator
, table_hline_column)
- local table_caption_beginning = (parsers.check_minimal_blank_indent_and_any_trail_no_rem
+ local table_caption_beginning = (parsers.check_minimal_blank_indent_and_any_trail_no_rem
* parsers.optionalspace * parsers.newline)^0
* parsers.check_minimal_indent_and_trail
* (P("Table")^-1 * parsers.colon)
@@ -32246,7 +32425,7 @@ function M.new(options)
%
% \end{markdown}
% \begin{macrocode}
- local pathname = util.lookup_files(filename)
+ local pathname = kpse.lookup(filename)
local input_file = assert(io.open(pathname, "r"),
[[Could not open user-defined syntax extension "]]
.. pathname .. [[" for reading]])