如何编写具有上下跳过的左框架环境而不会干扰文本流?

如何编写具有上下跳过的左框架环境而不会干扰文本流?

我想编写一个环境来实现以下目标:

  1. 左侧有一条垂直线,横跨整个文本高度,并在边距中有一个符号(例如危险标志),
  2. 如果内容太长,当前页面无法容纳,则可以跨页面拆分,
  3. 不干扰主文本流。也就是说,环境内容的排版应与不使用环境时相同。

我设法实现了 1 和 2,主要是 3。但是,我无法获得环境上下间距的一致行为。

作为 MWE,我想出了以下两种可能的解决方案。第一种依赖于包framed,第二种依赖于tcolorbox包。第一种通过了上间距测试,但没有通过下间距测试。第二种没有通过任何测试。

问题是,前面的内容可能会延伸(或不会)到最后一行基线以下。框架内容也是如此。因此,框架内容或其后续内容的高度“在视觉上是错误的”,因为它高于预期并打断了文本流。我希望整个文本看起来就像是自然排版的,基线之间的距离均匀(假设没有任何东西干扰它们,如显示方程式中所示)。

我无法找到一种自动且可靠地解决这个问题的方法。据我所知,该framed软件包没有提供一种方法来了解框架内容最后一行的深度。而且选项after skiptcolorbox无济于事。

实际上,在涉及粘连和弹性垂直长度的某些情况下(例如,当段落之间的距离被拉伸以填充页面时),还存在更多问题(这里没有显示)。

我必须承认这不是一个大问题,但我想知道是否有人能想到一个可行的解决方案。

\documentclass[twoside]{article}

\usepackage{lipsum,multicol}

\columnsep=1.3cm

% Here we define "framedattention" environment

\usepackage{framed,ifoddpage,calc,bclogo}

\usepackage[noadjust]{marginnote}

\makeatletter

\newif\iffirstframe

\def\marginwarning{%
  \checkoddpage%
  \ifoddpage\@reversemargintrue\else\@reversemarginfalse\fi%
  \marginnote{\Large\bcattention}%
}

\newenvironment{framedattention}{%
  \global\firstframetrue%
  \def\FirstFrameCommand##1{%
    \global\firstframefalse%
    \marginwarning%
    \hspace{-6pt}\vrule width 2pt\hspace{4pt}%
    \raisebox{-\height+2ex}[2ex][\height-2ex-20ex]{##1}%
    \global\firstframefalse%
  }%
  \def\FrameCommand##1{%
    \iffirstframe%
      \marginwarning%
    \fi%
    \hspace{-6pt}\vrule width 2pt\hspace{4pt}%
    \raisebox{-\height+2ex}{##1}%
  }%
  \setlength\OuterFrameSep{0pt}%
  \MakeFramed{%
%    \unskip%
    \FrameRestore%
  }%
  \ignorespaces%
}{%
  \endMakeFramed%
  \ignorespacesafterend%
}

% Here we define "tcboxattention" environment

\usepackage{tcolorbox}
\tcbuselibrary{skins,breakable}

\newlength\defparindent
\AtBeginDocument{\defparindent=\parindent}

\tcbset{
  parindent/.style={
    before upper={\parindent=\defparindent},
  }
}

\newtcolorbox{tcboxattention}{
  title=\smash{\bcattention},
  blanker,
  breakable,
  parindent,
  boxsep=0pt,
  left=0pt,
  right=0pt,
  top=0pt,
  bottom=0pt,
  after skip=1ex,
  before skip=1ex,
  attach boxed title to top left={yshift=-25pt,xshift=-30pt},
  borderline west={3pt}{0pt}{black},
  left=10pt,
  grow to left by=10pt,
}%

\begin{document}
  \subsection*{Test of the framedattention environment:}

  \begin{multicols}{2}
    This paragraph has 4 lines and the last one ends with letters extending below the baseline: pppppp pppppp pppppp pppppp pppppp

    \begin{framedattention}
      This paragraph uses the framedattention environment. This is a reference for upper spacing.
    \end{framedattention}

    \vfill\strut

    This paragraph has 4 lines and the last one ends with letters NOT extending below the baseline: aaaaaa aaaaaa aaaaaa aaaaaa

    \begin{framedattention}
      This paragraph uses the framedattention environment. It is at the expected position.
    \end{framedattention}

    \vfill\strut
  \end{multicols}

  \begin{multicols}{2}
    \begin{framedattention}
      This paragraph has 4 lines and the last one ends with letters extending below the baseline: pppppp pppppp pppppp pppppp pppppp
    \end{framedattention}

    This paragraph is a reference for lower spacing.

    \vfill\strut

    \begin{framedattention}
      This paragraph has 4 lines and the last one ends with letters NOT extending below the baseline: aaaaaa aaaaaa aaaaaa aaaaaa
    \end{framedattention}

    This paragraph is higher than expected.

    \vfill\strut
  \end{multicols}

  \subsection*{Test of the tcboxattention environment:}

  \begin{multicols}{2}
    This paragraph has 4 lines and the last one ends with letters extending below the baseline: pppppp pppppp pppppp pppppp pppppp

    \begin{tcboxattention}
      This paragraph uses the tcboxattention environment. This is a reference for upper spacing.
    \end{tcboxattention}

    \vfill\strut

    This paragraph has 4 lines and the last one ends with letters NOT extending below the baseline: aaaaaa aaaaaa aaaaaa aaaaaa

    \begin{tcboxattention}
      This paragraph uses the tcboxattention environment. It is higher than expected.
    \end{tcboxattention}

    \vfill\strut
  \end{multicols}

  \begin{multicols}{2}
    \begin{tcboxattention}
      This paragraph has 4 lines and the last one ends with letters extending below the baseline: pppppp pppppp pppppp pppppp pppppp
    \end{tcboxattention}

    This paragraph is a reference for lower spacing.

    \vfill\strut

    \begin{tcboxattention}
      This paragraph has 4 lines and the last one ends with letters NOT extending below the baseline: aaaaaa aaaaaa aaaaaa aaaaaa
    \end{tcboxattention}

    This paragraph is higher than expected.

    \vfill\strut
  \end{multicols}

\end{document}

这是生成的 PDF 的屏幕截图。我添加了水平绿线来说明问题。偏移不大(可能只有 1 或 2 毫米),所以您可能需要放大图像才能看到它。

问题

答案1

一种可能的解决方案,基于使 mdframed 段落在间距方面表现得像普通段落建议来自锡拉库萨,使用修改后的版本埃格尔的代码。

它似乎适用于延伸到基线以下(如p)或不延伸到基线(如a)的字符,或者延伸到基线以上的字符(如X),无论是在环境内部还是外部。

\documentclass[twoside]{article}

\usepackage{lipsum,multicol}

\columnsep=1.3cm

\usepackage{tcolorbox,calc,bclogo}
\tcbuselibrary{skins,breakable}

\newlength\defparindent
\AtBeginDocument{\defparindent=\parindent}

\tcbset{
  parindent/.style={
    before upper={\parindent=\defparindent},
  }
}

\newtcolorbox{tcboxattention}[1][]{
  title=\smash{\bcattention},
  blanker,
  breakable,
  parindent,
  boxsep=0pt,
  left=0pt,
  right=0pt,
  top=0pt,
  bottom=0pt,
  after skip=0pt,
  attach boxed title to top left={yshift=-25pt,xshift=-30pt},
  borderline west={3pt}{0pt}{black},
  left=10pt,
  grow to left by=10pt,
  #1
}%

\newlength\prefixheight
\newlength\postfixheight

\newenvironment{attention}{%
  \prefixheight=\dimexpr\dp\strutbox-\prevdepth\relax%
  \begin{tcboxattention}[before skip=\prefixheight]%
    \strut%
    \ignorespaces%
}{%
    \par%
    \global\postfixheight=\prevdepth%
  \end{tcboxattention}%
  \par%
  \vskip\dimexpr-\ht\strutbox-\postfixheight\relax%
  \strut%
  \par%
}

\def\ppp{ppp ppp ppp ppp ppp ppp ppp ppp ppp ppp}
\def\aaa{aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa}
\def\XXX{XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX}

\begin{document}
  \begin{multicols}{2}

    \aaa

    \begin{attention}
      \aaa
    \end{attention}

      \ppp

    \begin{attention}
      \ppp
    \end{attention}

    \XXX

    \begin{attention}
      \XXX
    \end{attention}

    \vfill\strut\columnbreak

    \aaa

    \aaa

    \ppp

    \ppp

    \XXX

    \XXX

    \vfill\strut

  \end{multicols}\vspace{-24pt}\color{red}\hrule
\end{document}

这是一个捕获(红线显示一切都按预期对齐)。

问题已解决

相关内容