summaryrefslogtreecommitdiff
path: root/Master/texmf-dist
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist')
-rw-r--r--Master/texmf-dist/doc/lualatex/lua-typo/README.md7
-rw-r--r--Master/texmf-dist/doc/lualatex/lua-typo/lua-typo-demo.pdfbin16859 -> 16859 bytes
-rw-r--r--Master/texmf-dist/doc/lualatex/lua-typo/lua-typo-fr.pdfbin106625 -> 107474 bytes
-rw-r--r--Master/texmf-dist/doc/lualatex/lua-typo/lua-typo.pdfbin208526 -> 217771 bytes
-rw-r--r--Master/texmf-dist/source/lualatex/lua-typo/lua-typo.dtx588
-rw-r--r--Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.cfg9
-rw-r--r--Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.sty226
7 files changed, 590 insertions, 240 deletions
diff --git a/Master/texmf-dist/doc/lualatex/lua-typo/README.md b/Master/texmf-dist/doc/lualatex/lua-typo/README.md
index 526538afb05..8f974434faa 100644
--- a/Master/texmf-dist/doc/lualatex/lua-typo/README.md
+++ b/Master/texmf-dist/doc/lualatex/lua-typo/README.md
@@ -90,7 +90,7 @@ Changes
* v.0.70:
- Options handled via `ltkeys` instead of `kvoptions`.
- - code cleaning, bug fixes.
+ - Code cleaning, bug fixes.
* v.0.80:
- Config file `lua-typo.cfg` changed (new colours added, all colour
@@ -99,6 +99,11 @@ Changes
added for lines affected by multiple flaws (f.i. widow+overfull).
- Bug fix (file `.typo`): in footnotes, line numbers for homeoarchy
were not reset.
+
+* v.0.85:
+ - A warning is issued if some pages fail to be checked properly.
+ - Margin notes checking added (over/underfull lines, position).
+ - Code cleaning, bug fixes.
--
Copyright 2020--2023 Daniel Flipo
diff --git a/Master/texmf-dist/doc/lualatex/lua-typo/lua-typo-demo.pdf b/Master/texmf-dist/doc/lualatex/lua-typo/lua-typo-demo.pdf
index 6606b65d368..e82b355c627 100644
--- a/Master/texmf-dist/doc/lualatex/lua-typo/lua-typo-demo.pdf
+++ b/Master/texmf-dist/doc/lualatex/lua-typo/lua-typo-demo.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/lualatex/lua-typo/lua-typo-fr.pdf b/Master/texmf-dist/doc/lualatex/lua-typo/lua-typo-fr.pdf
index 88dea3e4dee..b117378ac8a 100644
--- a/Master/texmf-dist/doc/lualatex/lua-typo/lua-typo-fr.pdf
+++ b/Master/texmf-dist/doc/lualatex/lua-typo/lua-typo-fr.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/lualatex/lua-typo/lua-typo.pdf b/Master/texmf-dist/doc/lualatex/lua-typo/lua-typo.pdf
index b43a1f75fe4..be36b78a7e3 100644
--- a/Master/texmf-dist/doc/lualatex/lua-typo/lua-typo.pdf
+++ b/Master/texmf-dist/doc/lualatex/lua-typo/lua-typo.pdf
Binary files differ
diff --git a/Master/texmf-dist/source/lualatex/lua-typo/lua-typo.dtx b/Master/texmf-dist/source/lualatex/lua-typo/lua-typo.dtx
index 4ec480c9211..7809a013774 100644
--- a/Master/texmf-dist/source/lualatex/lua-typo/lua-typo.dtx
+++ b/Master/texmf-dist/source/lualatex/lua-typo/lua-typo.dtx
@@ -204,7 +204,7 @@
% \pkg{lua-typo}, il suffit d’ajouter dans le préambule la ligne %\\
% |\usepackage[All]{lua-typo}|
%
-% La version courante (0.80) nécessite un noyau LaTeX récent,
+% La version courante (0.85) nécessite un noyau LaTeX récent,
% 2022/06/01 ou ultérieur. Ceux qui ne disposent que d’un noyau
% antérieur à 2021/06/01 reçoivent un message d’erreur
% «\texttt{Unable to register callback}» ; une version «rollback »
@@ -269,6 +269,7 @@
% consécutives ?\\
% FootnoteSplit & Fin de note de bas de page sur page suivante?\\
% ShortFinalWord & Mot de fin de phrase court en haut de page\\
+% MarginparPos & Note marginale se terminant trop bas\\
% \hline
% \end{tabular}
% \end{table}
@@ -363,7 +364,7 @@
% La valeur donnée doit être un entier supérieur ou égal à~100,
% cette valeur 100 correspond à l’étirement maximal prévu par la
% fonte (|\fontdimen3|) ; avec ce réglage attendez-vous à trouver
-% une kyrielle de lignes les creuses ! En fait la valeur par défaut
+% une kyrielle de lignes creuses ! En fait la valeur par défaut
% (200) correspond approximativement à ce que TeX, avec les
% réglages par défaut (|\tolerance=200|, |\hbadness=1000|),
% considère comme \emph{Underfull hbox}.
@@ -380,7 +381,7 @@
% (trois lettres en commun), mais « mon » et « mont » en début de
% ligne échappent à la détection.
%
-% \item[EOLShortWords:] cette option signale la présence en fin de
+% \item[EOLShortWords:] cette option signale la présence en fin de
% ligne de mots très courts (une ou deux lettres)
% qui sont répertoriés dans une des listes
% suivantes (elles dépendent de la langue courante) :\\
@@ -405,6 +406,12 @@
% caractères}, donc entourée de simples ou doubles
% \emph{quotes} \textsc{ascii} et composées de mots séparés
% par des espaces comme dans les exemples ci-dessus.
+%
+% \item[\cs{luatypoMarginparTol}] est une \emph{dimension} qui vaut
+% |\baselineskip| par défaut; les notes marginales qui se
+% terminent à plus de |\luatypoMarginparTol| en dessous de la
+% dernière ligne de la page sont déclarées fautives.
+%
% \end{description}
%
% À chacune des vérifications faites par \pkg{lua-typo} peut être
@@ -432,6 +439,7 @@
% \luatypoSetColor{14}{cyan} % Note de bas de page éclatée
% \luatypoSetColor{15}{red} % Mot de fin de phrase en haut de page
% \luatypoSetColor{16}{LTline}% Ligne présentant plusieurs "défauts"
+% \luatypoSetColor{17}{red} % Note marginale se terminant trop bas
% \end{verbatim}
% \pkg{lua-typo} charge les extensions \pkg{luacolor} et donc
% \pkg{color}. Seules les couleurs portant un nom (\emph{named
@@ -512,7 +520,8 @@
% for them, a ``rollback’’ version of \pkg{lua-typo} is provided,
% it can be loaded this way: |\usepackage[All]{lua-typo}[=v0.4]|.
%
-% Version 0.80 requires a LaTeX kernel dated 2022/06/01 or later.
+% \enlargethispage*{\baselineskip}
+% Version 0.85 requires a LaTeX kernel dated 2022/06/01 or later.
% Another ``rollback’’ version |[=v0.65]| has been added for those
% who run an older kernel.
%
@@ -558,6 +567,7 @@
% LastWordMatch & same (part of) word ending two consecutive lines?\\
% FootnoteSplit & footnotes spread over two pages or more?\\
% ShortFinalWord & Short word ending a sentence on the next page\\
+% MarginparPos & Margin note ending too low on the page\\
% \hline
% \end{tabular}\\[12pt]
% For example, if you want \pkg{lua-typo} to only warn about overfull
@@ -574,6 +584,7 @@
% this option provides an easy way to get their names without having
% to look into the documentation.
%
+% \newpage
% With option \opt{None}, \pkg{lua-typo} \emph{does absolutely
% nothing}, all checks are disabled as the main function is not added
% to any LuaTeX callback. It not quite equivalent to commenting out
@@ -594,7 +605,8 @@
% \item[ShortFinalWord :] the first word on a page is highlighted
% if it ends a sentence and is short (up to |\luatypoMinLen=4|
% letters).
-% \end{description}
+%
+% \end{description}
%
% \section{Customisation}
%
@@ -682,7 +694,12 @@
% (\emph{i.e.} surrounded by single or double \textsc{ascii}
% quotes) made of your words separated by spaces.
%
-% \end{description}
+% \item[\cs{luatypoMarginparTol}] is a \emph{dimension} which
+% defaults to |\baselineskip|; marginal notes trigger a flaw
+% if they end lower than |\luatypoMarginparTol| under the page’s
+% last line.
+%
+% \end{description}
%
% It is possible to define a specific colour for each
% typographic flaws that \pkg{lua-typo} deals with.
@@ -706,8 +723,8 @@
% \luatypoSetColor{13}{LTgrey}% Paragraph’s last line nearly full
% \luatypoSetColor{14}{cyan} % Footnotes spread over two pages
% \luatypoSetColor{15}{red} % Short final word on top of the page
-% \luatypoSetColor{16}{LTline}% Line color for multiple flaws\end{verbatim}
-%
+% \luatypoSetColor{16}{LTline}% Line color for multiple flaws
+% \luatypoSetColor{17}{red} % Margin note ending too low\end{verbatim}
% \pkg{lua-typo} loads the \pkg{luacolor} package which loads the
% \pkg{color} package from the LaTeX graphic bundle.
% |\luatypoSetColor| requires named colours, so you can either use
@@ -728,7 +745,7 @@
%<+scan>\ProvidesPackage{scan-page}
%<+dtx>\ProvidesFile{lua-typo.dtx}
%<*dtx|sty|scan>
- [2023-04-28 v.0.80 Daniel Flipo]
+ [2023-09-13 v.0.85 Daniel Flipo]
%</dtx|sty|scan>
%<*sty>
% \fi
@@ -746,7 +763,7 @@
% \begin{macrocode}
\DeclareRelease{v0.4}{2021-01-01}{lua-typo-2021-04-18.sty}
\DeclareRelease{v0.65}{2023-03-08}{lua-typo-2023-03-08.sty}
-\DeclareCurrentRelease{}{2023-04-12}
+\DeclareCurrentRelease{}{2023-09-13}
% \end{macrocode}
%
% This package only runs with LuaLaTeX and requires packages
@@ -769,6 +786,7 @@
\newdimen\luatypoLLminWD
\newdimen\luatypoBackPI
\newdimen\luatypoBackFuzz
+\newdimen\luatypoMarginparTol
\newcount\luatypoStretchMax
\newcount\luatypoHyphMax
\newcount\luatypoPageMin
@@ -814,6 +832,7 @@ luatypo = { }
LastWordMatch.if = LT@LastWordMatch ,
FootnoteSplit.if = LT@FootnoteSplit ,
ShortFinalWord.if = LT@ShortFinalWord ,
+ MarginparPos.if = LT@MarginparPos ,
All.if = LT@All ,
All.code = \LT@ShortLinestrue \LT@ShortPagestrue
\LT@OverfullLinestrue \LT@UnderfullLinestrue
@@ -822,7 +841,7 @@ luatypo = { }
\LT@ParLastHyphentrue \LT@EOLShortWordstrue
\LT@FirstWordMatchtrue \LT@LastWordMatchtrue
\LT@BackParindenttrue \LT@FootnoteSplittrue
- \LT@ShortFinalWordtrue
+ \LT@ShortFinalWordtrue \LT@MarginparPostrue
}
\ProcessKeyOptions[luatypo]
% \end{macrocode}
@@ -929,6 +948,12 @@ luatypo = { }
\else
\directlua{ luatypo.ShortFinalWord = false }%
\fi
+ \ifLT@MarginparPos
+ \advance\luatypo@options by 1
+ \directlua{ luatypo.MarginparPos = true }%
+ \else
+ \directlua{ luatypo.MarginparPos = false }%
+ \fi
}
% \end{macrocode}
%
@@ -958,6 +983,7 @@ luatypo = { }
LastWordMatch [false]\MessageBreak
FootnoteSplit [false]\MessageBreak
ShortFinalWord [false]\MessageBreak
+ MarginparPos [false]\MessageBreak
\MessageBreak
*********************************************%
\MessageBreak Lua-typo [ShowOptions]
@@ -979,11 +1005,12 @@ luatypo = { }
% \end{macrocode}
% Ensure |MinFull|$\leq$|MinPart|.
% \begin{macrocode}
- luatypo.MinFull = math.min(luatypo.MinPart,luatypo.MinFull)
- luatypo.MinLen = tex.count.luatypoMinLen
- luatypo.LLminWD = tex.dimen.luatypoLLminWD
- luatypo.BackPI = tex.dimen.luatypoBackPI
- luatypo.BackFuzz = tex.dimen.luatypoBackFuzz
+ luatypo.MinFull = math.min(luatypo.MinPart,luatypo.MinFull)
+ luatypo.MinLen = tex.count.luatypoMinLen
+ luatypo.LLminWD = tex.dimen.luatypoLLminWD
+ luatypo.BackPI = tex.dimen.luatypoBackPI
+ luatypo.BackFuzz = tex.dimen.luatypoBackFuzz
+ luatypo.MParTol = tex.dimen.luatypoMarginparTol
% \end{macrocode}
% \changes{0.80}{2023/04/28}{New table `luatypo.map’ for colours.}
%
@@ -1006,6 +1033,16 @@ luatypo = { }
% (very) end of document and write the report file on disc,
% unless option |None| has been selected.
%
+% On every page, at least one line of text should be found.
+% Otherwise, \pkg{lua-typo} presumes something went wrong and
+% writes the page number to a |failedlist| list.
+% In case |pagelist| is empty \emph{and} |failedlist| \emph{is not},
+% a warning is issued instead of the \texttt{No Typo Flaws found.}
+% message (new to version~0.85).
+%
+% \changes{0.85}{2023/09/07}{Warn in case some pages failed to
+% be checked properly.}
+%
% \begin{macrocode}
\AtVeryEndDocument{%
\ifnum\luatypo@options = 0 \LT@Nonetrue \fi
@@ -1023,14 +1060,27 @@ luatypo = { }
texio.write_nl(' ')
texio.write_nl('*************************************')
if luatypo.pagelist == " " then
- texio.write_nl('*** lua-typo: No Typo Flaws found.')
+ if luatypo.failedlist == " " then
+ texio.write_nl('*** lua-typo: No Typo Flaws found.')
+ else
+ texio.write_nl('*** WARNING: ')
+ texio.write('lua-typo failed to scan these pages:')
+ texio.write_nl('***' .. luatypo.failedlist)
+ texio.write_nl('*** Please report to the maintainer.')
+ end
else
texio.write_nl('*** lua-typo: WARNING *************')
texio.write_nl('The following pages need attention:')
texio.write(luatypo.pagelist)
end
- texio.write_nl('***********************************')
+ texio.write_nl('*************************************')
texio.write_nl(' ')
+ if luatypo.failedlist == " " then
+ else
+ local prt = "WARNING: lua-typo failed to scan pages " ..
+ luatypo.failedlist .. "\string\n\string\n"
+ luatypo.buffer = prt .. luatypo.buffer
+ end
local fileout= tex.jobname .. ".typo"
local out=io.open(fileout,"w+")
out:write(luatypo.buffer)
@@ -1060,7 +1110,7 @@ luatypo = { }
local s = utf8.char(c)
luatypo.single[langno] = luatypo.single[langno] .. s
end
-%<dbg> texio.write_nl("SINGLE=" .. luatypo.single[langno])
+%<dbg> texio.write_nl('SINGLE=' .. luatypo.single[langno])
%<dbg> texio.write_nl(' ')
}%
\else
@@ -1079,7 +1129,7 @@ luatypo = { }
local s = utf8.char(c)
luatypo.double[langno] = luatypo.double[langno] .. s
end
-%<dbg> texio.write_nl("DOUBLE=" .. luatypo.double[langno])
+%<dbg> texio.write_nl('DOUBLE=' .. luatypo.double[langno])
%<dbg> texio.write_nl(' ')
}%
\else
@@ -1113,13 +1163,14 @@ luatypo = { }
%
% \begin{macrocode}
\begin{luacode}
-luatypo.colortbl = { }
-luatypo.map = { }
-luatypo.single = { }
-luatypo.double = { }
-luatypo.pagelist = " "
-luatypo.buffer = "List of typographic flaws found for "
- .. tex.jobname .. ".pdf:\string\n\string\n"
+luatypo.colortbl = { }
+luatypo.map = { }
+luatypo.single = { }
+luatypo.double = { }
+luatypo.pagelist = " "
+luatypo.failedlist = " "
+luatypo.buffer = "List of typographic flaws found for "
+ .. tex.jobname .. ".pdf:\string\n\string\n"
local char_to_discard = { }
char_to_discard[string.byte(",")] = true
@@ -1535,12 +1586,12 @@ local check_line_last_word =
new = utf8_gsub(new, "_+$", "") -- $
new = utf8_gsub(new, "^_+", "")
maxlen = math.min(utf8_len(old), utf8_len(new))
-%<dbg> texio.write_nl("EOLsigold=" .. old)
-%<dbg> texio.write(" EOLsig=" .. new)
+%<dbg> texio.write_nl('EOLsigold=' .. old)
+%<dbg> texio.write(' EOLsig=' .. new)
% \end{macrocode}
-% When called with flag |false|, |check_line_last_word| returns
-% the last word’s signature, but doesn’t compare it with the
-% previous line’s.
+% When called with flag |false|, |check_line_last_word| doesn’t
+% compare it with the previous line’s, but just returns the
+% last word’s signature.
% \begin{macrocode}
if flag and old ~= "" then
% \end{macrocode}
@@ -1571,11 +1622,11 @@ local check_line_last_word =
end
end
if oldsub == newsub then
-%<dbg> texio.write_nl("EOLnewsub=" .. newsub)
+%<dbg> texio.write_nl('EOLnewsub=' .. newsub)
match = true
end
if oldlast == newlast and utf8_len(newlast) >= MinFull then
-%<dbg> texio.write_nl("EOLnewlast=" .. newlast)
+%<dbg> texio.write_nl('EOLnewlast=' .. newlast)
if utf8_len(newlast) > MinPart or not match then
oldsub = oldlast
newsub = newlast
@@ -1621,13 +1672,13 @@ local check_line_last_word =
local c = nn.char
if not char_to_discard[c] then l = l + 1 end
end
-%<dbg> texio.write_nl("l (box)=" .. l)
+%<dbg> texio.write_nl('l (box)=' .. l)
elseif n then
color_node(n, COLOR)
li, newsub = signature(n, newsub, swap)
l = l + li - lo
lo = li
-%<dbg> texio.write_nl("l=" .. l)
+%<dbg> texio.write_nl('l=' .. l)
end
n = n.prev
end
@@ -1688,12 +1739,12 @@ local check_line_first_word =
new = utf8_gsub(new, "_+$", "") -- $
new = utf8_gsub(new, "^_+", "")
maxlen = math.min(utf8_len(old), utf8_len(new))
-%<dbg> texio.write_nl("BOLsigold=" .. old)
-%<dbg> texio.write(" BOLsig=" .. new)
+%<dbg> texio.write_nl('BOLsigold=' .. old)
+%<dbg> texio.write(' BOLsig=' .. new)
% \end{macrocode}
-% When called with flag |false|, |check_line_first_word| returns
-% the first word’s signature, but doesn’t compare it with the
-% previous line’s.
+% When called with flag |false|, |check_line_first_word| doesn’t
+% compare it with the previous line’s, but returns
+% the first word’s signature.
% \begin{macrocode}
if flag and old ~= "" then
local oldfirst = utf8_gsub (old, "_.*", "")
@@ -1713,11 +1764,11 @@ local check_line_first_word =
end
end
if oldsub == newsub then
-%<dbg> texio.write_nl("BOLnewsub=" .. newsub)
+%<dbg> texio.write_nl('BOLnewsub=' .. newsub)
match = true
end
if oldfirst == newfirst and utf8_len(newfirst) >= MinFull then
-%<dbg> texio.write_nl("BOLnewfirst=" .. newfirst)
+%<dbg> texio.write_nl('BOLnewfirst=' .. newfirst)
if utf8_len(newfirst) > MinPart or not match then
oldsub = oldfirst
newsub = newfirst
@@ -1741,7 +1792,7 @@ local check_line_first_word =
end
end
newsub = utf8_gsub(newsub, "_+$", "") --$
-%<dbg> texio.write_nl("BOLfullmatch=" .. newsub)
+%<dbg> texio.write_nl('BOLfullmatch=' .. newsub)
local msg = "B.O.L. MATCH=" .. newsub
log_flaw(msg, line, colno, footnote)
% \end{macrocode}
@@ -1832,7 +1883,7 @@ local check_page_first_word = function (node, colno, footnote)
match = true
end
end
-%<dbg> texio.write_nl("FinalWord=" .. new)
+%<dbg> texio.write_nl('FinalWord=' .. new)
if match then
local msg = "ShortFinalWord=" .. new
log_flaw(msg, 1, colno, footnote)
@@ -1981,11 +2032,11 @@ local footnoterule_ahead = function (head)
if totalht == 0 or totalht == ruleht then
flag = true
else
-%<dbg> texio.write_nl(" ")
-%<dbg> texio.write_nl("Not a footnoterule:")
-%<dbg> texio.write(" KERN height=" .. ht1)
-%<dbg> texio.write(" RULE height=" .. ht2)
-%<dbg> texio.write(" KERN height=" .. ht3)
+%<dbg> texio.write_nl(' ')
+%<dbg> texio.write_nl('Not a footnoterule:')
+%<dbg> texio.write(' KERN height=' .. ht1)
+%<dbg> texio.write(' RULE height=' .. ht2)
+%<dbg> texio.write(' KERN height=' .. ht3)
end
end
end
@@ -2013,15 +2064,108 @@ local check_EOP = function (node)
body_bot = true
elseif footnoterule_ahead(n) then
body_bot = true
-%<dbg> texio.write_nl("=> FOOTNOTE RULE ahead")
-%<dbg> texio.write_nl("check_vtop: last line before footnotes")
-%<dbg> texio.write_nl(" ")
+%<dbg> texio.write_nl('=> FOOTNOTE RULE ahead')
+%<dbg> texio.write_nl('check_vtop: last line before footnotes')
+%<dbg> texio.write_nl(' ')
end
return page_bot, body_bot
end
% \end{macrocode}
% \end{macro}
%
+% \changes{v0.85}{2023/09/07}{New function `check\_marginnote’.}
+%
+% \begin{macro}{check-marginnote}
+% This function checks margin notes for overfull/underfull lines;
+% It also warns if a margin note ends too low under the last line
+% of text.
+% \begin{macrocode}
+local check_marginnote = function (head, line, colno, vpos, bpmn)
+ local OverfullLines = luatypo.OverfullLines
+ local UnderfullLines = luatypo.UnderfullLines
+ local MarginparPos = luatypo.MarginparPos
+ local margintol = luatypo.MParTol
+ local marginpp = tex.getdimen("marginparpush")
+ local pflag = false
+ local ofirst = true
+ local ufirst = true
+ local n = head.head
+ local bottom = vpos
+ if vpos <= bpmn then
+ bottom = bpmn + marginpp
+ end
+%<dbg> texio.write_nl('*** Margin note? ***')
+ repeat
+ if n and (n.id == GLUE or n.id == PENALTY) then
+%<dbg> texio.write_nl(' Found GLUE or PENALTY')
+ n = n.next
+ elseif n and n.id == VLIST then
+%<dbg> texio.write_nl(' Found VLIST')
+ n = n.head
+ end
+ until not n or (n.id == HLIST and n.subtype == LINE)
+ local head = n
+ if head then
+%<dbg> texio.write_nl(' Found HLIST')
+ else
+%<dbg> texio.write_nl(' No text line found.')
+ end
+%<dbg> local l = 0
+ local last = head
+ while head do
+ local next = head.next
+ if head.id == HLIST and head.subtype == LINE then
+%<dbg> l = l + 1
+%<dbg> texio.write_nl(' Checking line ' .. l)
+ bottom = bottom + head.height + head.depth
+ local first = head.head
+ local linewd = head.width
+ local hmax = linewd + tex.hfuzz
+ local w,h,d = dimensions(1,2,0, first)
+ local Stretch = math.max(luatypo.Stretch/100,1)
+ if w > hmax and OverfullLines then
+%<dbg> texio.write(': Overfull!')
+ pflag = true
+ local COLOR = luatypo.colortbl[8]
+ color_line (head, COLOR)
+ if ofirst then
+ local msg = "OVERFULL line(s) in margin note"
+ log_flaw(msg, line, colno, false)
+ ofirst = false
+ end
+ elseif head.glue_set > Stretch and head.glue_sign == 1 and
+ head.glue_order == 0 and UnderfullLines then
+%<dbg> texio.write(': Underfull!')
+ pflag = true
+ local COLOR = luatypo.colortbl[9]
+ color_line (head, COLOR)
+ if ufirst then
+ local msg = "UNDERFULL line(s) in margin note"
+ log_flaw(msg, line, colno, false)
+ ufirst = false
+ end
+ end
+ end
+ last = head
+ head = next
+ end
+ local textht = tex.getdimen("textheight")
+%<dbg> local tht = string.format("%.1fpt", textht/65536)
+%<dbg> local bott = string.format("%.1fpt", bottom/65536)
+%<dbg> texio.write_nl(' Bottom=' .. bott)
+%<dbg> texio.write(' TextBottom=' ..tht)
+ if bottom > textht + margintol and MarginparPos then
+ pflag = true
+ local COLOR = luatypo.colortbl[17]
+ color_line (last, COLOR)
+ local msg = "Margin note too low"
+ log_flaw(msg, line, colno, false)
+ end
+ return bottom, pflag
+end
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{get-pagebody}
% The next function scans the \node{vlist}s on the current
% page in search of the page body.
@@ -2038,29 +2182,29 @@ local get_pagebody = function (head)
repeat
fn = fn.next
until fn.id == VLIST and fn.height > 0
-%<dbg> texio.write_nl(" ")
+%<dbg> texio.write_nl(' ')
%<dbg> local ht = string.format("%.1fpt", fn.height/65536)
%<dbg> local dp = string.format("%.1fpt", fn.depth/65536)
-%<dbg> texio.write_nl("get_pagebody: TOP VLIST")
-%<dbg> texio.write(" ht=" .. ht .. " dp=" .. dp)
+%<dbg> texio.write_nl('get_pagebody: TOP VLIST')
+%<dbg> texio.write(' ht=' .. ht .. ' dp=' .. dp)
first = fn.list
for n in traverse_id(VLIST,first) do
if n.subtype == 0 and n.height == textht then
%<dbg> local ht = string.format("%.1fpt", n.height/65536)
-%<dbg> texio.write_nl("BODY found: ht=" .. ht)
-%<dbg> texio.write_nl(" ")
+%<dbg> texio.write_nl('BODY found: ht=' .. ht)
+%<dbg> texio.write_nl(' ')
body = n
break
else
-%<dbg> texio.write_nl("Skip short VLIST:")
+%<dbg> texio.write_nl('Skip short VLIST:')
%<dbg> local ht = string.format("%.1fpt", n.height/65536)
%<dbg> local dp = string.format("%.1fpt", n.depth/65536)
-%<dbg> texio.write(" ht=" .. ht .. " dp=" .. dp)
+%<dbg> texio.write(' ht=' .. ht .. ' dp=' .. dp)
first = n.list
for n in traverse_id(VLIST,first) do
if n.subtype == 0 and n.height == textht then
%<dbg> local ht = string.format("%.1fpt", n.height/65536)
-%<dbg> texio.write_nl(" BODY: ht=" .. ht)
+%<dbg> texio.write_nl(' BODY: ht=' .. ht)
body = n
break
end
@@ -2068,7 +2212,7 @@ local get_pagebody = function (head)
end
end
if not body then
- texio.write_nl("***lua-typo ERROR: PAGE BODY *NOT* FOUND!***")
+ texio.write_nl('***lua-typo ERROR: PAGE BODY *NOT* FOUND!***')
end
return body
end
@@ -2120,6 +2264,7 @@ check_vtop = function (top, colno, vpos)
vpos_min = vpos_min * 1.5
local linewd = tex.getdimen("textwidth")
local first_bot = true
+ local done = false
local footnote = false
local ftnsplit = false
local orphanflag = false
@@ -2135,6 +2280,7 @@ check_vtop = function (top, colno, vpos)
local pageline = 0
local ftnline = 0
local line = 0
+ local bpmn = 0
local body_bottom = false
local page_bottom = false
local pageflag = false
@@ -2154,9 +2300,11 @@ check_vtop = function (top, colno, vpos)
% \end{macrocode}
% This is a text line, store its width, increment counters
% |pageline| or |ftnline| and |line| (for |log_flaw|).
-% Let’s update |vpos| (vertical position in `sp’ units) too.
+% Let’s update |vpos| (vertical position in `sp’ units) and
+% set flag |done| to |true|.
% \begin{macrocode}
vpos = vpos + head.height + head.depth
+ done = true
local linewd = head.width
local first = head.head
local ListItem = false
@@ -2256,15 +2404,15 @@ check_vtop = function (top, colno, vpos)
% Does the first word and the one on the previous line match
% (except lists)?
% \begin{macrocode}
- if FirstWordMatch then
- local flag = not ListItem and (line > 1)
- firstwd, flag =
- check_line_first_word(firstwd, first, line, colno,
- flag, footnote)
- if flag then
- pageflag = true
- end
+ if FirstWordMatch then
+ local flag = not ListItem and (line > 1)
+ firstwd, flag =
+ check_line_first_word(firstwd, first, line, colno,
+ flag, footnote)
+ if flag then
+ pageflag = true
end
+ end
% \end{macrocode}
% Check the page’s first word (end of sentence?).
% \begin{macrocode}
@@ -2277,12 +2425,19 @@ check_vtop = function (top, colno, vpos)
% and |pn| are the last two nodes.
% \begin{macrocode}
local ln = slide(first)
+% \end{macrocode}
+% Skip a possible RULE pointing an overfull line.
+% \begin{macrocode}
+ if ln.id == RULE and ln.subtype == 0 then
+ ln = ln.prev
+ end
local pn = ln.prev
if pn and pn.id == GLUE and pn.subtype == PARFILL then
% \end{macrocode}
% CASE 1: this line ends the paragraph, reset |ftnsplit| and |orphan|
% flags to false…
% \begin{macrocode}
+%<dbg> texio.write_nl('EOL CASE 1: end of paragraph')
hyphcount = 0
ftnsplit = false
orphanflag = false
@@ -2302,8 +2457,8 @@ check_vtop = function (top, colno, vpos)
local llwd = linewd - PFskip
%<dbg> local PFskip_pt = string.format("%.1fpt", PFskip/65536)
%<dbg> local llwd_pt = string.format("%.1fpt", llwd/65536)
-%<dbg> texio.write_nl("PFskip= " .. PFskip_pt)
-%<dbg> texio.write(" llwd= " .. llwd_pt)
+%<dbg> texio.write_nl('PFskip= ' .. PFskip_pt)
+%<dbg> texio.write(' llwd= ' .. llwd_pt)
% \end{macrocode}
% |llwd| is the line’s length. Is it too short?
% \begin{macrocode}
@@ -2347,6 +2502,7 @@ check_vtop = function (top, colno, vpos)
% \end{macrocode}
% CASE 2: the current line ends with an hyphen.
% \begin{macrocode}
+%<dbg> texio.write_nl('EOL CASE 2: hyphen')
hyphcount = hyphcount + 1
if hyphcount > HYPHmax and RepeatedHyphens then
local COLOR = luatypo.colortbl[3]
@@ -2400,10 +2556,11 @@ check_vtop = function (top, colno, vpos)
end
% \end{macrocode}
% CASE 3: the current line ends with anything else (\node{glyph},
-% \node{mkern}, \node{hlist}, etc.), reset |hyphcount|, check for
-% `LastWordMatch’ and `EOLShortWords’.
+% \node{mkern}, \node{hlist}, etc.), then reset |hyphcount| and
+% check for `LastWordMatch’ and `EOLShortWords’.
% \begin{macrocode}
else
+%<dbg> texio.write_nl('EOL CASE 3')
hyphcount = 0
% \end{macrocode}
% Track matching words at end of line and short words.
@@ -2485,6 +2642,36 @@ check_vtop = function (top, colno, vpos)
color_line (head, COLOR)
backpar = false
end
+ elseif head and head.id == HLIST and head.subtype == BOX and
+ head.width > 0 then
+ if head.height == 0 then
+% \end{macrocode}
+% This is a possible margin note.
+% \begin{macrocode}
+ bpmn, pflag = check_marginnote(head, line, colno, vpos, bpmn)
+ if pflag then pageflag = true end
+ else
+% \end{macrocode}
+% Leave |check_vtop| if a two columns box starts.
+% \begin{macrocode}
+ local hf = head.list
+ if hf and hf.id == VLIST and hf.subtype == 0 then
+%<dbg> texio.write_nl('check_vtop: BREAK => multicol')
+%<dbg> texio.write_nl(' ')
+ break
+ else
+% \end{macrocode}
+% \changes{v0.80}{2023/04/18}{hlist-2: added detection of page bottom
+% and increment line number and vpos.}
+% This is an |\hbox| (f.i.\ centred), let’s update |vpos|, line
+% and check for page bottom
+% \begin{macrocode}
+ vpos = vpos + head.height + head.depth
+ pageline = pageline + 1
+ line = pageline
+ page_bottom, body_bottom = check_EOP (nextnode)
+ end
+ end
elseif head.id == HLIST and
(head.subtype == EQN or head.subtype == ALIGN) and
(head.height > 0 or head.depth > 0) then
@@ -2561,8 +2748,8 @@ check_vtop = function (top, colno, vpos)
% If it is, set the |footnote| flag and reset some counters
% and flags for the coming footnote lines.
% \begin{macrocode}
-%<dbg> texio.write_nl("check_vtop: footnotes start")
-%<dbg> texio.write_nl(" ")
+%<dbg> texio.write_nl('check_vtop: footnotes start')
+%<dbg> texio.write_nl(' ')
footnote = true
ftnline = 0
body_bottom = false
@@ -2580,15 +2767,15 @@ check_vtop = function (top, colno, vpos)
if first_bot then
%<dbg> local vpos_pt = string.format("%.1fpt", vpos/65536)
%<dbg> local vmin_pt = string.format("%.1fpt", vpos_min/65536)
-%<dbg> texio.write_nl("pageline=" .. pageline)
-%<dbg> texio.write_nl("vpos=" .. vpos_pt)
-%<dbg> texio.write(" vpos_min=" .. vmin_pt)
+%<dbg> texio.write_nl('pageline=' .. pageline)
+%<dbg> texio.write_nl('vpos=' .. vpos_pt)
+%<dbg> texio.write(' vpos_min=' .. vmin_pt)
%<dbg> if page_bottom then
%<dbg> local tht = tex.getdimen("textheight")
%<dbg> local tht_pt = string.format("%.1fpt", tht/65536)
-%<dbg> texio.write(" textheight=" .. tht_pt)
+%<dbg> texio.write(' textheight=' .. tht_pt)
%<dbg> end
-%<dbg> texio.write_nl(" ")
+%<dbg> texio.write_nl(' ')
if pageline > 1 and pageline < PAGEmin
and vpos < vpos_min and ShortPages then
pageshort = true
@@ -2619,38 +2806,20 @@ check_vtop = function (top, colno, vpos)
% This is a |\vbox|, let’s update |vpos|.
% \begin{macrocode}
vpos = vpos + head.height + head.depth
- elseif head.id == HLIST and head.subtype == BOX then
-% \end{macrocode}
-% \changes{v0.80}{2023/04/18}{hlist-2: added detection of page bottom
-% and increment line number and vpos.}
-%
-% This is an |\hbox| (f.i.\ centred), let’s update |vpos|, line
-% and check for page bottom
-% \begin{macrocode}
- vpos = vpos + head.height + head.depth
- pageline = pageline + 1
- line = pageline
- page_bottom, body_bottom = check_EOP (nextnode)
- local hf = head.list
-% \end{macrocode}
-% Leave |check_vtop| if a two columns box starts.
-% \begin{macrocode}
- if hf and hf.id == VLIST and hf.subtype == 0 then
-%<dbg> texio.write_nl("check_vtop: BREAK => multicol")
-%<dbg> texio.write_nl(" ")
- break
- end
+%<dbg> local tht = head.height + head.depth
+%<dbg> local tht_pt = string.format("%.1fpt", tht/65536)
+%<dbg> texio.write(' vbox: height=' .. tht_pt)
end
head = nextnode
end
%<dbg> if nextnode then
-%<dbg> texio.write("Exit check_vtop, next=")
+%<dbg> texio.write('Exit check_vtop, next=')
%<dbg> texio.write(tostring(node.type(nextnode.id)))
-%<dbg> texio.write("-".. nextnode.subtype)
+%<dbg> texio.write('-'.. nextnode.subtype)
%<dbg> else
-%<dbg> texio.write_nl("Exit check_vtop, next=nil")
+%<dbg> texio.write_nl('Exit check_vtop, next=nil')
%<dbg> end
-%<dbg> texio.write_nl("")
+%<dbg> texio.write_nl('')
% \end{macrocode}
% Update the list of flagged pages avoiding duplicates:
% \begin{macrocode}
@@ -2661,9 +2830,10 @@ check_vtop = function (top, colno, vpos)
luatypo.pagelist = luatypo.pagelist .. tostring(pageno) .. ", "
end
end
- return head
+ return head, done
% \end{macrocode}
% |head| is nil unless |check_vtop| exited on a two column start.
+% |done| is true unless |check_vtop| found no text line.
% \begin{macrocode}
end
% \end{macrocode}
@@ -2686,49 +2856,71 @@ end
% \begin{macrocode}
luatypo.check_page = function (head)
local textwd = tex.getdimen("textwidth")
- local vpos = 0
- local n2, n3, col, colno
+ local textht = tex.getdimen("textheight")
+ local checked, boxed, n2, n3, col, colno
local body = get_pagebody(head)
+ local pageno = tex.getcount("c@page")
+ local vpos = 0
local footnote = false
local top = body
local first = body.list
- if (first and first.id == HLIST and first.subtype == BOX) or
- (first and first.id == VLIST and first.subtype == 0) then
+ local next
+ local count = 0
+%<dbg> texio.write_nl('Body=' .. tostring(node.type(top.id)))
+%<dbg> texio.write('-' .. tostring(top.subtype))
+%<dbg> texio.write('; First=' .. tostring(node.type(first.id)))
+%<dbg> texio.write('-' .. tostring(first.subtype))
+%<dbg> texio.write_nl(' ')
+ if ((first and first.id == HLIST and first.subtype == BOX) or
+ (first and first.id == VLIST and first.subtype == 0)) and
+ (first.width == textwd and first.height > 0 and not boxed) then
% \end{macrocode}
% Some classes (\cls{memoir}, \cls{tugboat} …) use one more level
-% of bowing, let’s step down one level.
+% of bowing for two columns, let’s step down one level.
% \begin{macrocode}
%<dbg> local boxwd = string.format("%.1fpt", first.width/65536)
-%<dbg> texio.write_nl("One step down: boxwd=" .. boxwd)
-%<dbg> texio.write_nl(" ")
+%<dbg> texio.write_nl('One step down: boxwd=' .. boxwd)
+%<dbg> texio.write_nl(' ')
top = body.list
- first = top.list
+% \end{macrocode}
+% A float on top of a page is a VLIST-0 included in a VLIST-0 (body),
+% it should not trigger this step down. Workaround: the body will be
+% read again.
+% \begin{macrocode}
+ if first.id == VLIST then
+ boxed = body
+ end
end
% \end{macrocode}
% Main loop:
% \begin{macrocode}
while top do
first = top.list
-%<dbg> texio.write_nl("Page loop: top=" .. tostring(node.type(top.id)))
-%<dbg> texio.write("-" .. top.subtype)
-%<dbg> texio.write_nl(" ")
+ next = top.next
+%<dbg> count = count + 1
+%<dbg> texio.write_nl('Page loop' .. count)
+%<dbg> texio.write(': top=' .. tostring(node.type(top.id)))
+%<dbg> texio.write('-' .. tostring(top.subtype))
+%<dbg> if first then
+%<dbg> texio.write(' first=' .. tostring(node.type(first.id)))
+%<dbg> texio.write('-' .. tostring(first.subtype))
+%<dbg> end
if top and top.id == VLIST and top.subtype == 0 and
- top.width > textwd/2 then
+ top.width > textwd/2 then
% \end{macrocode}
% Single column, run |check_vtop| on the top vlist.
% \begin{macrocode}
%<dbg> local boxht = string.format("%.1fpt", top.height/65536)
%<dbg> local boxwd = string.format("%.1fpt", top.width/65536)
-%<dbg> texio.write_nl("**VLIST: ")
+%<dbg> texio.write_nl('**VLIST: ')
%<dbg> texio.write(tostring(node.type(top.id)))
-%<dbg> texio.write("-" .. top.subtype)
-%<dbg> texio.write(" wd=" .. boxwd .. " ht=" .. boxht)
-%<dbg> texio.write_nl(" ")
- local next = check_vtop(top,colno,vpos)
- if next then
- top = next
- elseif top then
- top = top.next
+%<dbg> texio.write('-' .. tostring(top.subtype))
+%<dbg> texio.write(' wd=' .. boxwd .. ' ht=' .. boxht)
+%<dbg> texio.write_nl(' ')
+ local n, ok = check_vtop(top,colno,vpos)
+ if ok then checked = true end
+ if n then
+ next = n
end
elseif (top and top.id == HLIST and top.subtype == BOX) and
(first and first.id == VLIST and first.subtype == 0) and
@@ -2737,23 +2929,24 @@ luatypo.check_page = function (head)
% Two or more columns, each one is boxed in a vlist.\par
% Run |check_vtop| on every column.
% \begin{macrocode}
-%<dbg> texio.write_nl("**MULTICOL type1:")
-%<dbg> texio.write_nl(" ")
+%<dbg> texio.write_nl('**MULTICOL type1:')
+%<dbg> texio.write_nl(' ')
colno = 0
for col in traverse_id(VLIST, first) do
colno = colno + 1
-%<dbg> texio.write_nl("Start of col." .. colno)
-%<dbg> texio.write_nl(" ")
- check_vtop(col,colno,vpos)
-%<dbg> texio.write_nl("End of col." .. colno)
-%<dbg> texio.write_nl(" ")
+%<dbg> texio.write_nl('Start of col.' .. colno)
+%<dbg> texio.write_nl(' ')
+ local n, ok = check_vtop(col,colno,vpos)
+ if ok then checked = true end
+%<dbg> texio.write_nl('End of col.' .. colno)
+%<dbg> texio.write_nl(' ')
end
colno = nil
top = top.next
-%<dbg> texio.write_nl("MULTICOL type1 END: next=")
+%<dbg> texio.write_nl('MULTICOL type1 END: next=')
%<dbg> texio.write(tostring(node.type(top.id)))
-%<dbg> texio.write("-" .. top.subtype)
-%<dbg> texio.write_nl(" ")
+%<dbg> texio.write('-' .. tostring(top.subtype))
+%<dbg> texio.write_nl(' ')
elseif (top and top.id == HLIST and top.subtype == BOX) and
(first and first.id == HLIST and first.subtype == BOX) and
(first.height > 0 and first.width > 0) then
@@ -2762,25 +2955,38 @@ luatypo.check_page = function (head)
% holds a vlist.\par
% Run |check_vtop| on every column.
% \begin{macrocode}
-%<dbg> texio.write_nl("**MULTICOL type2:")
-%<dbg> texio.write_nl(" ")
+%<dbg> texio.write_nl('**MULTICOL type2:')
+%<dbg> texio.write_nl(' ')
colno = 0
for n in traverse_id(HLIST, first) do
colno = colno + 1
local col = n.list
if col and col.list then
-%<dbg> texio.write_nl("Start of col." .. colno)
-%<dbg> texio.write_nl(" ")
- check_vtop(col,colno,vpos)
-%<dbg> texio.write_nl("End of col." .. colno)
-%<dbg> texio.write_nl(" ")
+%<dbg> texio.write_nl('Start of col.' .. colno)
+%<dbg> texio.write_nl(' ')
+ local n, ok = check_vtop(col,colno,vpos)
+ if ok then checked = true end
+%<dbg> texio.write_nl('End of col.' .. colno)
+%<dbg> texio.write_nl(' ')
end
end
colno = nil
- top = top.next
- else
- top = top.next
end
+% \end{macrocode}
+% Workaround for top floats: check the whole body again.
+% \begin{macrocode}
+ if boxed and not next then
+ next = boxed
+ boxed = nil
+ end
+ top = next
+ end
+ if not checked then
+ luatypo.failedlist = luatypo.failedlist .. tostring(pageno) .. ", "
+%<dbg> texio.write_nl(' ')
+%<dbg> texio.write_nl('WARNING: no text line found on page ')
+%<dbg> texio.write(tostring(pageno))
+%<dbg> texio.write_nl(' ')
end
return true
end
@@ -2842,6 +3048,7 @@ return luatypo.check_page
\luatypoSetColor{14}{cyan}% Footnote split
\luatypoSetColor{15}{red}% Too short first (final) word on the page
\luatypoSetColor{16}{LTline}% Line color for multiple flaws
+ \luatypoSetColor{17}{red}% Margin note ending too low
\luatypoBackPI=1em\relax
\luatypoBackFuzz=2pt\relax
\ifdim\parindent=0pt \luatypoLLminWD=20pt\relax
@@ -2852,12 +3059,13 @@ return luatypo.check_page
\luatypoMinFull=3\relax
\luatypoMinPart=4\relax
\luatypoMinLen=4\relax
+ \luatypoMarginparTol=\baselineskip
}%
% \end{macrocode}
% \iffalse
%</sty>
% \fi
-% \clearpage
+%
% \section{Configuration file}
%
% \iffalse
@@ -2892,8 +3100,12 @@ return luatypo.check_page
\luatypoMinPart=4\relax
%% Minimum number of characters for the first word on a page if it ends
-%% a sentence.
-\luatypoMinLen=4\relax
+%% a sentence (version >= 0.65).
+\ifdefined\luatypoMinLen \luatypoMinLen=4\relax\fi
+
+%% Acceptable marginpars must end at |\luatypoMarginparTol| under
+%% the page’s last line or above (version >= 0.85).
+\ifdefined\luatypoMarginparTol \luatypoMarginparTol=\baselineskip \fi
%% Default colours = red, cyan, blue, LTgrey, LTred, LTline.
\definecolor{LTgrey}{gray}{0.6}
@@ -2915,6 +3127,7 @@ return luatypo.check_page
\luatypoSetColor{14}{cyan}% Footnote split
\luatypoSetColor{15}{red}% Too short first (final) word on the page
\luatypoSetColor{16}{LTline}% Line color for multiple flaws
+\luatypoSetColor{17}{red}% Margin note ending too low
%% Language specific settings (example for French):
%% short words (two letters max) to be avoided at end of lines.
@@ -2984,12 +3197,12 @@ return luatypo.check_page
\AtVeryEndDocument{%
\directlua{
- texio.write_nl(" ")
- texio.write_nl("***************************")
- texio.write_nl("*** PAGE SCANNING ONLY: ***")
- texio.write_nl("*** NO CHECK PERFORMED! ***")
- texio.write_nl("***************************")
- texio.write_nl(" ")
+ texio.write_nl(' ')
+ texio.write_nl('***************************')
+ texio.write_nl('*** PAGE SCANNING ONLY: ***')
+ texio.write_nl('*** NO CHECK PERFORMED! ***')
+ texio.write_nl('***************************')
+ texio.write_nl(' ')
}%
}
@@ -3003,6 +3216,7 @@ luatypo.single = { }
luatypo.double = { }
luatypo.colortbl = { }
luatypo.pagelist = " "
+luatypo.failedlist = " "
local hyphcount = 0
local pageno = 0
@@ -3055,20 +3269,20 @@ local get_pagebody = function (head)
for n in traverse_id(VLIST,first) do
if n.subtype == 0 and n.height == textht then
local ht = string.format("%.1fpt", n.height/65536)
- texio.write_nl(" BODY: " .. ht)
- texio.write_nl(" ")
+ texio.write_nl(' BODY: ' .. ht)
+ texio.write_nl(' ')
body = n
break
else
local ht = string.format("%.1fpt", n.height/65536)
local dp = string.format("%.1fpt", n.depth/65536)
- texio.write_nl(" SKIP vlist: ht=" .. ht .. " dp=" .. dp)
+ texio.write_nl(' SKIP vlist: ht=' .. ht .. ' dp=' .. dp)
first = n.list
for n in traverse_id(VLIST,first) do
if n.subtype == 0 and n.height == textht then
ht = string.format("%.1fpt", n.height/65536)
- texio.write_nl(" BODY: " .. ht)
- texio.write_nl(" ")
+ texio.write_nl(' BODY: ' .. ht)
+ texio.write_nl(' ')
body = n
break
end
@@ -3076,7 +3290,7 @@ local get_pagebody = function (head)
end
end
if not body then
- texio.write_nl("***lua-typo ERROR: PAGE BODY *NOT* FOUND!***")
+ texio.write_nl('***lua-typo ERROR: PAGE BODY *NOT* FOUND!***')
end
return body
end
@@ -3088,7 +3302,7 @@ local print_subtype = function (node,parent)
elseif n.id == GLUE then
texio.write(tostring(n.subtype))
real_pt = string.format("%.1fpt", effective_glue(n,parent)/65536)
- texio.write(" realwd=" .. real_pt)
+ texio.write(' realwd=' .. real_pt)
elseif n.id == DISC then
local c = ""
if n.replace then
@@ -3102,24 +3316,24 @@ local print_subtype = function (node,parent)
for nn in traverse_id(GLYPH, n.pre) do
c = c .. utf8.char(nn.char)
end
- texio.write(" pre=" .. c)
+ texio.write(' pre=' .. c)
end
if n.post then
c = ""
for nn in traverse_id(GLYPH, n.post) do
c = c .. utf8.char(nn.char)
end
- texio.write(" post=" .. c)
+ texio.write(' post=' .. c)
end
elseif n.subtype and n.subtype < 256 then
texio.write(tostring(n.subtype))
if n.height and n.depth then
ht_pt = string.format("%.1fpt", n.height/65536)
dp_pt = string.format("%.1fpt", n.depth/65536)
- texio.write(" ht=" .. ht_pt .. " dp=" .. dp_pt)
+ texio.write(' ht=' .. ht_pt .. ' dp=' .. dp_pt)
if n.width then
wd_pt = string.format("%.1fpt", n.width/65536)
- texio.write(" wd=" .. wd_pt)
+ texio.write(' wd=' .. wd_pt)
end
end
end
@@ -3133,58 +3347,62 @@ local scanvlist = function (head)
local textht = tex.getdimen("textheight")
local textwd = tex.getdimen("textwidth")
local pageno = tex.getcount("c@page")
- texio.write_nl("PAGE " .. pageno)
- texio.write(" textheight=".. string.format("%.1fpt", textht/65536))
- texio.write(" textwidth=" .. string.format("%.1fpt", textwd/65536))
+ texio.write_nl('PAGE ' .. pageno)
+ texio.write(' textheight='.. string.format("%.1fpt", textht/65536))
+ texio.write(' textwidth=' .. string.format("%.1fpt", textwd/65536))
local linecount = 0
local body, parent, ht_pt, dp_pt, real_pt
body = get_pagebody(head)
if body then
parent = body
head = body.head
+ texio.write_nl('Enter outer vbox (body) of type ')
+ texio.write(tostring(node.type(body.id)))
+ texio.write('-')
+ texio.write(tostring(body.subtype))
end
- while (head) do
+ while head do
texio.write_nl(tostring(node.type(head.id)))
- texio.write("-")
+ texio.write('-')
print_subtype(head,body)
if head.kern then
ht_pt = string.format("%.1fpt", head.kern/65536)
- texio.write(" KERN ht/wd=" .. ht_pt)
+ texio.write(' KERN ht/wd=' .. ht_pt)
end
local next = head.next
local first = head.head
for n in traverse(first) do
parent = head
- texio.write_nl(" " .. tostring(node.type(n.id)))
- texio.write("-")
+ texio.write_nl(' ' .. tostring(node.type(n.id)))
+ texio.write('-')
print_subtype(n,head)
if n.id == VLIST or n.id == HLIST then
local ff = n.head
for nn in traverse(ff) do
parent = n
- texio.write_nl(" " .. tostring(node.type(nn.id)))
- texio.write("-")
+ texio.write_nl(' ' .. tostring(node.type(nn.id)))
+ texio.write('-')
print_subtype(nn,n)
if nn.id == VLIST or nn.id == HLIST then
local f3 = nn.head
for n3 in traverse(f3) do
parent = nn
- texio.write_nl(" " .. tostring(node.type(n3.id)))
- texio.write("-")
+ texio.write_nl(' ' .. tostring(node.type(n3.id)))
+ texio.write('-')
print_subtype(n3,nn)
if n3.id == VLIST or n3.id == HLIST then
local f4 = n3.head
for n4 in traverse(f4) do
parent = n3
- texio.write_nl(" " .. tostring(node.type(n4.id)))
- texio.write("-")
+ texio.write_nl(' ' .. tostring(node.type(n4.id)))
+ texio.write('-')
print_subtype(n4,n3)
if n4.id == VLIST or n4.id == HLIST then
local f5 = n4.head
for n5 in traverse(f5) do
parent = n4
- texio.write_nl(" " .. tostring(node.type(n4.id)))
- texio.write("-")
+ texio.write_nl(' ' .. tostring(node.type(n5.id)))
+ texio.write('-')
print_subtype(n5,n4)
end
end
diff --git a/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.cfg b/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.cfg
index fe9b2438312..32f6ade6cf8 100644
--- a/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.cfg
+++ b/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.cfg
@@ -24,8 +24,12 @@
\luatypoMinPart=4\relax
%% Minimum number of characters for the first word on a page if it ends
-%% a sentence.
-\luatypoMinLen=4\relax
+%% a sentence (version >= 0.65).
+\ifdefined\luatypoMinLen \luatypoMinLen=4\relax\fi
+
+%% Acceptable marginpars must end at |\luatypoMarginparTol| under
+%% the page’s last line or above (version >= 0.85).
+\ifdefined\luatypoMarginparTol \luatypoMarginparTol=\baselineskip \fi
%% Default colours = red, cyan, blue, LTgrey, LTred, LTline.
\definecolor{LTgrey}{gray}{0.6}
@@ -47,6 +51,7 @@
\luatypoSetColor{14}{cyan}% Footnote split
\luatypoSetColor{15}{red}% Too short first (final) word on the page
\luatypoSetColor{16}{LTline}% Line color for multiple flaws
+\luatypoSetColor{17}{red}% Margin note ending too low
%% Language specific settings (example for French):
%% short words (two letters max) to be avoided at end of lines.
diff --git a/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.sty b/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.sty
index ef9040c4013..92f1c05ba18 100644
--- a/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.sty
+++ b/Master/texmf-dist/tex/lualatex/lua-typo/lua-typo.sty
@@ -11,10 +11,10 @@
%%
\NeedsTeXFormat{LaTeX2e}[2021/06/01]
\ProvidesPackage{lua-typo}
- [2023-04-28 v.0.80 Daniel Flipo]
+ [2023-09-13 v.0.85 Daniel Flipo]
\DeclareRelease{v0.4}{2021-01-01}{lua-typo-2021-04-18.sty}
\DeclareRelease{v0.65}{2023-03-08}{lua-typo-2023-03-08.sty}
-\DeclareCurrentRelease{}{2023-04-12}
+\DeclareCurrentRelease{}{2023-09-13}
\ifdefined\directlua
\RequirePackage{luatexbase,luacode,luacolor,atveryend}
\else
@@ -24,6 +24,7 @@
\newdimen\luatypoLLminWD
\newdimen\luatypoBackPI
\newdimen\luatypoBackFuzz
+\newdimen\luatypoMarginparTol
\newcount\luatypoStretchMax
\newcount\luatypoHyphMax
\newcount\luatypoPageMin
@@ -56,6 +57,7 @@ luatypo = { }
LastWordMatch.if = LT@LastWordMatch ,
FootnoteSplit.if = LT@FootnoteSplit ,
ShortFinalWord.if = LT@ShortFinalWord ,
+ MarginparPos.if = LT@MarginparPos ,
All.if = LT@All ,
All.code = \LT@ShortLinestrue \LT@ShortPagestrue
\LT@OverfullLinestrue \LT@UnderfullLinestrue
@@ -64,7 +66,7 @@ luatypo = { }
\LT@ParLastHyphentrue \LT@EOLShortWordstrue
\LT@FirstWordMatchtrue \LT@LastWordMatchtrue
\LT@BackParindenttrue \LT@FootnoteSplittrue
- \LT@ShortFinalWordtrue
+ \LT@ShortFinalWordtrue \LT@MarginparPostrue
}
\ProcessKeyOptions[luatypo]
\AtEndOfPackage{%
@@ -163,6 +165,12 @@ luatypo = { }
\else
\directlua{ luatypo.ShortFinalWord = false }%
\fi
+ \ifLT@MarginparPos
+ \advance\luatypo@options by 1
+ \directlua{ luatypo.MarginparPos = true }%
+ \else
+ \directlua{ luatypo.MarginparPos = false }%
+ \fi
}
\ifLT@ShowOptions
\GenericWarning{* }{%
@@ -187,6 +195,7 @@ luatypo = { }
LastWordMatch [false]\MessageBreak
FootnoteSplit [false]\MessageBreak
ShortFinalWord [false]\MessageBreak
+ MarginparPos [false]\MessageBreak
\MessageBreak
*********************************************%
\MessageBreak Lua-typo [ShowOptions]
@@ -199,11 +208,12 @@ luatypo = { }
luatypo.Stretch = tex.count.luatypoStretchMax
luatypo.MinFull = tex.count.luatypoMinFull
luatypo.MinPart = tex.count.luatypoMinPart
- luatypo.MinFull = math.min(luatypo.MinPart,luatypo.MinFull)
- luatypo.MinLen = tex.count.luatypoMinLen
- luatypo.LLminWD = tex.dimen.luatypoLLminWD
- luatypo.BackPI = tex.dimen.luatypoBackPI
- luatypo.BackFuzz = tex.dimen.luatypoBackFuzz
+ luatypo.MinFull = math.min(luatypo.MinPart,luatypo.MinFull)
+ luatypo.MinLen = tex.count.luatypoMinLen
+ luatypo.LLminWD = tex.dimen.luatypoLLminWD
+ luatypo.BackPI = tex.dimen.luatypoBackPI
+ luatypo.BackFuzz = tex.dimen.luatypoBackFuzz
+ luatypo.MParTol = tex.dimen.luatypoMarginparTol
local tbl = luatypo.colortbl
local map = { }
for i,v in ipairs (luatypo.colortbl) do
@@ -230,14 +240,27 @@ luatypo = { }
texio.write_nl(' ')
texio.write_nl('*************************************')
if luatypo.pagelist == " " then
- texio.write_nl('*** lua-typo: No Typo Flaws found.')
+ if luatypo.failedlist == " " then
+ texio.write_nl('*** lua-typo: No Typo Flaws found.')
+ else
+ texio.write_nl('*** WARNING: ')
+ texio.write('lua-typo failed to scan these pages:')
+ texio.write_nl('***' .. luatypo.failedlist)
+ texio.write_nl('*** Please report to the maintainer.')
+ end
else
texio.write_nl('*** lua-typo: WARNING *************')
texio.write_nl('The following pages need attention:')
texio.write(luatypo.pagelist)
end
- texio.write_nl('***********************************')
+ texio.write_nl('*************************************')
texio.write_nl(' ')
+ if luatypo.failedlist == " " then
+ else
+ local prt = "WARNING: lua-typo failed to scan pages " ..
+ luatypo.failedlist .. "\string\n\string\n"
+ luatypo.buffer = prt .. luatypo.buffer
+ end
local fileout= tex.jobname .. ".typo"
local out=io.open(fileout,"w+")
out:write(luatypo.buffer)
@@ -285,13 +308,14 @@ luatypo = { }
\endgroup
}
\begin{luacode}
-luatypo.colortbl = { }
-luatypo.map = { }
-luatypo.single = { }
-luatypo.double = { }
-luatypo.pagelist = " "
-luatypo.buffer = "List of typographic flaws found for "
- .. tex.jobname .. ".pdf:\string\n\string\n"
+luatypo.colortbl = { }
+luatypo.map = { }
+luatypo.single = { }
+luatypo.double = { }
+luatypo.pagelist = " "
+luatypo.failedlist = " "
+luatypo.buffer = "List of typographic flaws found for "
+ .. tex.jobname .. ".pdf:\string\n\string\n"
local char_to_discard = { }
char_to_discard[string.byte(",")] = true
@@ -894,6 +918,75 @@ local check_EOP = function (node)
end
return page_bot, body_bot
end
+local check_marginnote = function (head, line, colno, vpos, bpmn)
+ local OverfullLines = luatypo.OverfullLines
+ local UnderfullLines = luatypo.UnderfullLines
+ local MarginparPos = luatypo.MarginparPos
+ local margintol = luatypo.MParTol
+ local marginpp = tex.getdimen("marginparpush")
+ local pflag = false
+ local ofirst = true
+ local ufirst = true
+ local n = head.head
+ local bottom = vpos
+ if vpos <= bpmn then
+ bottom = bpmn + marginpp
+ end
+ repeat
+ if n and (n.id == GLUE or n.id == PENALTY) then
+ n = n.next
+ elseif n and n.id == VLIST then
+ n = n.head
+ end
+ until not n or (n.id == HLIST and n.subtype == LINE)
+ local head = n
+ if head then
+ else
+ end
+ local last = head
+ while head do
+ local next = head.next
+ if head.id == HLIST and head.subtype == LINE then
+ bottom = bottom + head.height + head.depth
+ local first = head.head
+ local linewd = head.width
+ local hmax = linewd + tex.hfuzz
+ local w,h,d = dimensions(1,2,0, first)
+ local Stretch = math.max(luatypo.Stretch/100,1)
+ if w > hmax and OverfullLines then
+ pflag = true
+ local COLOR = luatypo.colortbl[8]
+ color_line (head, COLOR)
+ if ofirst then
+ local msg = "OVERFULL line(s) in margin note"
+ log_flaw(msg, line, colno, false)
+ ofirst = false
+ end
+ elseif head.glue_set > Stretch and head.glue_sign == 1 and
+ head.glue_order == 0 and UnderfullLines then
+ pflag = true
+ local COLOR = luatypo.colortbl[9]
+ color_line (head, COLOR)
+ if ufirst then
+ local msg = "UNDERFULL line(s) in margin note"
+ log_flaw(msg, line, colno, false)
+ ufirst = false
+ end
+ end
+ end
+ last = head
+ head = next
+ end
+ local textht = tex.getdimen("textheight")
+ if bottom > textht + margintol and MarginparPos then
+ pflag = true
+ local COLOR = luatypo.colortbl[17]
+ color_line (last, COLOR)
+ local msg = "Margin note too low"
+ log_flaw(msg, line, colno, false)
+ end
+ return bottom, pflag
+end
local get_pagebody = function (head)
local textht = tex.getdimen("textheight")
local fn = head.list
@@ -917,7 +1010,7 @@ local get_pagebody = function (head)
end
end
if not body then
- texio.write_nl("***lua-typo ERROR: PAGE BODY *NOT* FOUND!***")
+ texio.write_nl('***lua-typo ERROR: PAGE BODY *NOT* FOUND!***')
end
return body
end
@@ -949,6 +1042,7 @@ check_vtop = function (top, colno, vpos)
vpos_min = vpos_min * 1.5
local linewd = tex.getdimen("textwidth")
local first_bot = true
+ local done = false
local footnote = false
local ftnsplit = false
local orphanflag = false
@@ -964,6 +1058,7 @@ check_vtop = function (top, colno, vpos)
local pageline = 0
local ftnline = 0
local line = 0
+ local bpmn = 0
local body_bottom = false
local page_bottom = false
local pageflag = false
@@ -973,6 +1068,7 @@ check_vtop = function (top, colno, vpos)
if head.id == HLIST and head.subtype == LINE and
(head.height > 0 or head.depth > 0) then
vpos = vpos + head.height + head.depth
+ done = true
local linewd = head.width
local first = head.head
local ListItem = false
@@ -1024,20 +1120,23 @@ check_vtop = function (top, colno, vpos)
elseif not footnote then
parline = parline + 1
end
- if FirstWordMatch then
- local flag = not ListItem and (line > 1)
- firstwd, flag =
- check_line_first_word(firstwd, first, line, colno,
- flag, footnote)
- if flag then
- pageflag = true
- end
+ if FirstWordMatch then
+ local flag = not ListItem and (line > 1)
+ firstwd, flag =
+ check_line_first_word(firstwd, first, line, colno,
+ flag, footnote)
+ if flag then
+ pageflag = true
end
+ end
if ShortFinalWord and pageline == 1 and parline > 1 and
check_page_first_word(first, colno, footnote) then
pageflag = true
end
local ln = slide(first)
+ if ln.id == RULE and ln.subtype == 0 then
+ ln = ln.prev
+ end
local pn = ln.prev
if pn and pn.id == GLUE and pn.subtype == PARFILL then
hyphcount = 0
@@ -1189,6 +1288,22 @@ check_vtop = function (top, colno, vpos)
color_line (head, COLOR)
backpar = false
end
+ elseif head and head.id == HLIST and head.subtype == BOX and
+ head.width > 0 then
+ if head.height == 0 then
+ bpmn, pflag = check_marginnote(head, line, colno, vpos, bpmn)
+ if pflag then pageflag = true end
+ else
+ local hf = head.list
+ if hf and hf.id == VLIST and hf.subtype == 0 then
+ break
+ else
+ vpos = vpos + head.height + head.depth
+ pageline = pageline + 1
+ line = pageline
+ page_bottom, body_bottom = check_EOP (nextnode)
+ end
+ end
elseif head.id == HLIST and
(head.subtype == EQN or head.subtype == ALIGN) and
(head.height > 0 or head.depth > 0) then
@@ -1268,15 +1383,6 @@ check_vtop = function (top, colno, vpos)
vpos = vpos + head.kern
elseif head.id == VLIST then
vpos = vpos + head.height + head.depth
- elseif head.id == HLIST and head.subtype == BOX then
- vpos = vpos + head.height + head.depth
- pageline = pageline + 1
- line = pageline
- page_bottom, body_bottom = check_EOP (nextnode)
- local hf = head.list
- if hf and hf.id == VLIST and hf.subtype == 0 then
- break
- end
end
head = nextnode
end
@@ -1287,30 +1393,37 @@ check_vtop = function (top, colno, vpos)
luatypo.pagelist = luatypo.pagelist .. tostring(pageno) .. ", "
end
end
- return head
+ return head, done
end
luatypo.check_page = function (head)
local textwd = tex.getdimen("textwidth")
- local vpos = 0
- local n2, n3, col, colno
+ local textht = tex.getdimen("textheight")
+ local checked, boxed, n2, n3, col, colno
local body = get_pagebody(head)
+ local pageno = tex.getcount("c@page")
+ local vpos = 0
local footnote = false
local top = body
local first = body.list
- if (first and first.id == HLIST and first.subtype == BOX) or
- (first and first.id == VLIST and first.subtype == 0) then
+ local next
+ local count = 0
+ if ((first and first.id == HLIST and first.subtype == BOX) or
+ (first and first.id == VLIST and first.subtype == 0)) and
+ (first.width == textwd and first.height > 0 and not boxed) then
top = body.list
- first = top.list
+ if first.id == VLIST then
+ boxed = body
+ end
end
while top do
first = top.list
+ next = top.next
if top and top.id == VLIST and top.subtype == 0 and
- top.width > textwd/2 then
- local next = check_vtop(top,colno,vpos)
- if next then
- top = next
- elseif top then
- top = top.next
+ top.width > textwd/2 then
+ local n, ok = check_vtop(top,colno,vpos)
+ if ok then checked = true end
+ if n then
+ next = n
end
elseif (top and top.id == HLIST and top.subtype == BOX) and
(first and first.id == VLIST and first.subtype == 0) and
@@ -1318,7 +1431,8 @@ luatypo.check_page = function (head)
colno = 0
for col in traverse_id(VLIST, first) do
colno = colno + 1
- check_vtop(col,colno,vpos)
+ local n, ok = check_vtop(col,colno,vpos)
+ if ok then checked = true end
end
colno = nil
top = top.next
@@ -1330,14 +1444,20 @@ luatypo.check_page = function (head)
colno = colno + 1
local col = n.list
if col and col.list then
- check_vtop(col,colno,vpos)
+ local n, ok = check_vtop(col,colno,vpos)
+ if ok then checked = true end
end
end
colno = nil
- top = top.next
- else
- top = top.next
end
+ if boxed and not next then
+ next = boxed
+ boxed = nil
+ end
+ top = next
+ end
+ if not checked then
+ luatypo.failedlist = luatypo.failedlist .. tostring(pageno) .. ", "
end
return true
end
@@ -1374,6 +1494,7 @@ return luatypo.check_page
\luatypoSetColor{14}{cyan}% Footnote split
\luatypoSetColor{15}{red}% Too short first (final) word on the page
\luatypoSetColor{16}{LTline}% Line color for multiple flaws
+ \luatypoSetColor{17}{red}% Margin note ending too low
\luatypoBackPI=1em\relax
\luatypoBackFuzz=2pt\relax
\ifdim\parindent=0pt \luatypoLLminWD=20pt\relax
@@ -1384,6 +1505,7 @@ return luatypo.check_page
\luatypoMinFull=3\relax
\luatypoMinPart=4\relax
\luatypoMinLen=4\relax
+ \luatypoMarginparTol=\baselineskip
}%
%%
%%