itemize 中的微类型引号在项目开头未正确对齐

itemize 中的微类型引号在项目开头未正确对齐

一位 LaTeX 用户在 itemize/enumerate 环境中使用引号时遇到了问题。当在项目的开头使用 csquotes 的自动引号时,引号无法正确突出到“边距”中。有没有办法以可持续的方式解决这个问题?

理想情况下,我试图找到一个解决方案,它由一些可以包含在文档序言中的代码组成,之后每个 \item“引号”实例都会自动具有正确的突出部分。否则,我将不得不手动更改文档中的数百个引号,这将非常痛苦。

LaTeX 版本

pdfTeX 3.141592653-2.6-1.40.23 (TeX Live 2022/dev)

LuaLaTeX 版本(这是此 MWP 中使用的内容,尽管看起来没有什么区别)

This is LuaHBTeX, Version 1.13.2 (TeX Live 2021)

最小工作示例:

%!TEX TS-program = lualatex

\documentclass[12pt]{article}
\usepackage{fontspec}
\usepackage{libertinus-otf}
\usepackage{lipsum}
\usepackage{csquotes} \MakeOuterQuote{"}
\usepackage{microtype}
\SetProtrusion
{ encoding = *}
{
% char   right left
  {.} = {    , 1000},
  {,} = {    , 1000},
  {«} = {1000,     },
  {»} = {    , 1000},
  {(} = {1000,     },
  {)} = {    , 1000},
  {-} = {    , 500 },
  \textquotedblleft
      = {1000,     },
  \textquotedblright
      = {    , 1000},
  \quotedblbase
      = {1000,     }
}
\begin{document}
\noindent
"\lipsum[1-1]"

\begin{enumerate}
  \item First regular item, without quotations.
  \item "Second item with quotation marks."
  \item First multi-line item, contains content that is deliberately very, very long: "with multiple clauses that are designed to trigger a line break," so that it will wrap around and create multiple rows.
  \item "Second multi-line item, but keep in mind it is different from the first since it is quoted. However it also contains content that is deliberately very, very long: with multiple clauses just like the first."
  \item "Multiple quoted lines with a single item"
  \item \leftprotrusion 

  "This is the second quoted line"

  This is a third unquoted line.
\end{enumerate}
\end{document}

尝试修复:按以下方式添加 \items 似乎可以解决问题:

\item \leftprotrusion ``quotes''

但是,这意味着需要进行大量的手动调整。(顺便说一句,此解决方法也不能与一起使用csquotes,也就是说\item \leftprotrusion "something in quotes"也无法得到正确的结果。)

列表中项目开头错误对齐的引号的可视化

答案1

我现在没时间解释,所以现在我只会添加代码。(如果你在 2021-01-10 之后读到这篇文章,而到现在为止还没有用适当的解释来代替这篇文章,请随时提醒我。)

需要 LuaLaTeX。

%!TEX TS-program = lualatex

\documentclass[12pt]{article}
\usepackage{fontspec}
\usepackage{libertinus-otf}
\usepackage{lipsum}
\usepackage{csquotes} \MakeOuterQuote{"}
\usepackage{microtype}
\SetProtrusion
{ encoding = *}
{
% char   right left
  {.} = {    , 1000},
  {,} = {    , 1000},
  {«} = {1000,     },
  {»} = {    , 1000},
  {(} = {1000,     },
  {)} = {    , 1000},
  {-} = {    , 500 },
  \textquotedblleft
      = {1000,     },
  \textquotedblright
      = {    , 1000},
  \quotedblbase
      = {1000,     }
}

\directlua{
  local func = luatexbase.new_luafunction'betterprotrusionboundary'
  local my_whatsit = luatexbase.new_whatsit'betterprotrusionboundary'
  local whatsit_id = node.id'whatsit'
  local glyph_id = node.id'glyph'
  local user_defined = node.subtype'user_defined'
  token.set_lua('betterprotrusionboundary', func, 'protected')
  local modes = tex.getmodevalues()
  lua.get_functions_table()[func] = function()
    local mode = tex.nest.top.mode
    if mode < 0 then mode = -mode end
    if modes[mode] == 'vertical' then
    token.put_next(token.new(func, token.command_id'lua_call'))
      return tex.forcehmode()
    end
    local n = node.new(whatsit_id, user_defined)
    n.user_id = my_whatsit
    n.type = 100
    n.value = token.scan_int()
    node.write(n)
  end

  luatexbase.add_to_callback('pre_linebreak_filter', function(head)
    for n, s in node.traverse_id(whatsit_id, head) do if s == user_defined and n.user_id == my_whatsit then
      assert(n.value == 1, 'boundarytypes beside 1 not yet supported')
      if n.value & 1 == 1 then
        for nn, id in node.traverse(n.next) do
          local char, fid = node.is_glyph(nn)
          if char then
            token.put_next(token.create'lpcode', token.new(fid, token.command_id'set_font'), token.new(char, token.command_id'char_given'))
            local width = (font.getparameters(fid).quad or 0) * token.scan_int() // 1000
            if not (width == 0) then
              local kern = node.new('kern', 1)
              % local kern = node.new('margin_kern', 0)
              kern.kern = -width
              % kern.glyph = char
              head = node.insert_after(head, n, kern)
            end
            break
          elseif not node.protrusion_skippable(nn) then
            break
          elseif fid == whatsit_id and nn.subtype == user_defined and nn.user_id == my_whatsit and nn.value & 1 == 1 then
            break
          end
        end
      end
      if n.value & 2 == 2 then
        local nn = n.prev
        while nn do
          local char, fid = node.is_glyph(nn)
          if char then
            token.put_next(token.create'rpcode', token.new(fid, token.command_id'set_font'), token.new(char, token.command_id'char_given'))
            local width = (font.getparameters(fid).quad or 0) * token.scan_int() // 1000
            if not (width == 0) then
              local kern = node.new('kern', 1)
              % local kern = node.new('margin_kern', 1)
              kern.kern = -width
              % kern.glyph = char
              head = node.insert_before(head, n, kern)
            end
            break
          elseif not node.protrusion_skippable(nn) then
            break
          end
          nn = nn.prev
        end
      end
      head = node.remove(head, n)
    end end
    return head
  end, 'betterprotrusionboundary')
}

\begin{document}
\showoutput
\renewcommand\leftprotrusion{\betterprotrusionboundary1\relax}
\noindent
"\lipsum[1-1]"

\begin{enumerate}
  \item First regular item, without quotations.
  \item "Second item with quotation marks."
  \item First multi-line item, contains content that is deliberately very, very long: "with multiple clauses that are designed to trigger a line break," so that it will wrap around and create multiple rows.
  \item "Second multi-line item, but keep in mind it is different from the first since it is quoted. However it also contains content that is deliberately very, very long: with multiple clauses just like the first."
  \item "Multiple quoted lines with a single item"
  \item \leftprotrusion ``quotes''

  "This is the second quoted line"

  This is a third unquoted line.
\end{enumerate}
\end{document}

在此处输入图片描述

相关内容