Why is text turning white (possible scope leak?) after page break and listings + tcolorbox + xelatex?

There's some strange interaction between listings wrapped in a tcolorbox and xelatex. I recommend to use a special \newtcblisting and use this (in the outer wrapper, if really needed ;-))

In this case the text does not vanish, regardless whether it is compiled with pdflatex, xelatex or lualatex.

\documentclass{article}
\usepackage{fontspec}%compile with xelatex
\usepackage{xparse}%for latex3 NewDocumentEnvironemnt
\usepackage[most]{tcolorbox}% for newtcolorbox and colorlet

\lstnewenvironment{mylstcode}[1][]{\lstset{#1,basicstyle=\ttfamily,columns=fullflexible,keepspaces=true,basewidth=0.5em,breaklines=true}}{} % for general code

\newtcblisting{myexamplelisting}[3][]{%
  listing only,
  listing options={#1,basicstyle=\ttfamily,columns=fullflexible,keepspaces=true,basewidth=0.5em,breaklines=true},
  empty,% Empty previously set parameters
  title={Example: #2},% use \thetcbcounter to access the ithexample counter text
  % Attaching a box requires an overlay
  breakable,%=unlimited,
  attach boxed title to top left,
  % Ensures proper line breaking in longer titles
    minipage boxed title,
    % (boxed title style requires an overlay)
    boxed title style={empty,size=minimal,toprule=0pt,top=4pt,left=3mm,overlay={}},
    coltitle=colexam,fonttitle=\bfseries,
    before=\par\medskip\noindent,parbox=false,boxsep=0pt,left=3mm,right=0mm,top=2pt,breakable,pad at break=0mm,
    before upper=\csname @totalleftmargin\endcsname0pt, % Use instead of parbox=true. This ensures parskip is inherited by box.
    % Handles box when it exists on one page only
    overlay unbroken={\draw[colexam,line width=.5pt] ([xshift=-0pt]title.north west) -- ([xshift=-0pt]frame.south west); },
    % Handles multipage box: first page
    overlay first={\draw[colexam,line width=.5pt] ([xshift=-0pt]title.north west) -- ([xshift=-0pt]frame.south west); },
    % Handles multipage box: middle page
    overlay middle={\draw[colexam,line width=.5pt] ([xshift=-0pt]frame.north west) -- ([xshift=-0pt]frame.south west); },
    % Handles multipage box: last page
    overlay last={\draw[colexam,line width=.5pt] ([xshift=-0pt]frame.north west) -- ([xshift=-0pt]frame.south west); },%
    #3%
}

\NewDocumentEnvironment{myexample}{ O{} O{} }
{%
  \colorlet{colexam}{blue!50!black} % The maximal total height of the upper and of the lower part of normal breakable tcolorboxes is about 65536pt (ca. 2300cm).
  \myexamplelisting{#1}{#2}%
}
{\endmyexamplelisting\endlist}
\begin{document}
\begingroup
\obeylines
1
1
1
1
\endgroup
\vspace{-1ex} % Forcefully squeeze the two environments together
\begin{myexample}[for i in \{1..40\}; do echo \$i; done]
\begin{mylstcode}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
\end{mylstcode}
\end{myexample}
Here is a sentence that turns white.

Here is a sentence that turns white.

Here is a sentence that turns white.

Here is a sentence that turns white.
\end{document}

enter image description here


Update 2016-09-16

Thomas F. Sturm mentions in the question comment that this problem may no longer exist, possibly due to a change in xelatex, but not due to a change in tcolorbox.


Solution until Compatibility Fix

In your Preamble add the following line to explicitly reset the font color to black after each tcolorbox:

  • \AfterEndEnvironment{myexample}{\color{black}}

Embedding tcolorbox within a list will negate the aforementioned fix outside of the list's scope. Therefore also add the following:

  • \AfterEndEnvironment{itemize}{\color{black}}
  • \AfterEndEnvironment{enumerate}{\color{black}}
  • \AfterEndEnvironment{description}{\color{black}}

Loading xcolor explicitly calls \color{black}.

Update 2016-05-12: Instead of explicitly setting "black", you could use \AtBeginDocument{\colorlet{defaultcolor}{.}} to make a defaultcolor colorlet that can be used after each myexample environment to restore the default color--at least until the packages/compiler work in harmony someday. See answers at xcolor - What is the equivalent of default text color?


Related Questions

  • How do I get fontspec to work with text color white in XeLaTeX
  • Last xe(la)tex colors text in white in some circumstances
  • xelatex and tcolorbox incompatibility?
  • https://tex.stackexchange.com/questions/287580/does-tcolorbox-3-11-have-a-problem-with-page-breaks-causing-invisible-text-whit

mdframed Approach

Note this has a deal-breaker limitation

It has the disadvantage that the embedded listings environment does not properly break over pages.

Also, I've had about as much grief as I can handle with the listings package. It seems to frequently cause mysterious character issues.

\documentclass{article}
\usepackage{fontspec}% typeset with xelatex
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage[framemethod=tikz]{mdframed} % Add easy frames to paragraphs
\usepackage{xparse}
\usepackage{listings}

\lstnewenvironment{mylstcode}[1][]{\lstset{#1,basicstyle=\ttfamily,columns=fullflexible,keepspaces=true,basewidth=0.5em,breaklines=true}}{} % for general code

\mdfdefinestyle{exampledefault}{%
hidealllines=true,
linecolor=blue!20!black,
fontcolor=blue!20!black,
rightline=false,
leftline=true,
bottomline=false,
topline=false,
innerleftmargin=10pt,innerrightmargin=10,
frametitlerule=false,
frametitlerulecolor=blue!20!black,
frametitlebackgroundcolor=white,
frametitlerulewidth=1pt,
 firstextra={\path let \p1=(P), \p2=(O) in ($(\x2,0)+0.5*(0,\y1)$)
                           node[] {};},%
 secondextra={\path let \p1=(P), \p2=(O) in ($(\x2,0)+0.5*(0,\y1)$)
                           node[] {};},%
 middleextra={\path let \p1=(P), \p2=(O) in ($(\x2,0)+0.5*(0,\y1)$)
                           node[] {};},%
 singleextra={\path let \p1=(P), \p2=(O) in ($(\x2,0)+0.5*(0,\y1)$)
                           node[] {};},%
}
\NewDocumentEnvironment{myexample}{ O{} O{} }
{\begin{mdframed}[style=exampledefault,frametitle={Example: #1}]}
{\end{mdframed}}

\begin{document}
\begin{myexample}[for i in \{1..40\}; do echo \$i; done]
\begin{mylstcode}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
\end{mylstcode}
\end{myexample}
\end{document}