%--------------------------------------------------------------------------- % Copyright 2013 Microsoft Corporation. % % This is free software; you can redistribute it and/or modify it under the % terms of the Apache License, Version 2.0. A copy of the License can be % found in the file "license.txt" at the root of this distribution. %--------------------------------------------------------------------------- \NeedsTeXFormat{LaTeX2e}[1995/12/01] \RequirePackage{iftex} \RequirePackage{etoolbox} \RequirePackage{xkeyval} \RequirePackage[table]{xcolor} \RequirePackage{mdframed} \RequirePackage{graphicx} \RequirePackage{tablefootnote} % font selection \ifXeTeX\RequirePackage{fontspec}\else \ifLuaTeX\RequirePackage{fontspec}\else \providecommand{\fontspec}[2][]{} \fi\fi % Define CSS 17 standard colors \definecolor{Red}{HTML}{FF0000} \definecolor{Lime}{HTML}{00FF00} \definecolor{Blue}{HTML}{0000FF} \definecolor{Yellow}{HTML}{FFFF00} \definecolor{Cyan}{HTML}{00FFFF} \definecolor{Magenta}{HTML}{FF00FF} \definecolor{Navy}{HTML}{000080} \definecolor{Maroon}{HTML}{800000} \definecolor{Green}{HTML}{008000} \definecolor{Teal}{HTML}{008080} \definecolor{Purple}{HTML}{800080} \definecolor{Olive}{HTML}{808000} \definecolor{Black}{HTML}{000000} \definecolor{Dimgray}{HTML}{696969} \definecolor{Gray}{HTML}{808080} \definecolor{Darkgray}{HTML}{A9A9A9} \definecolor{Silver}{HTML}{C0C0C0} \definecolor{Lightgray}{HTML}{D3D3D3} \definecolor{Gainsboro}{HTML}{DCDCDC} \definecolor{Floralwhite}{HTML}{FFFAF0} \definecolor{Ivory}{HTML}{FFFFF0} \definecolor{White}{HTML}{FFFFFF} \definecolor{Orange}{HTML}{FFA500} \definecolor{Aqua}{HTML}{00FFFF} \definecolor{Fuchsia}{HTML}{FF00FF} \newcommand{\@swap}[2]{#2{#1}} \newcommand{\@expandafter}[2]{\expandafter\@swap\expandafter{#2}{#1}} \newcommand{\eifstrequal}{\expandafter\ifstrequal\expandafter} \newcommand{\eeifstrequal}[2]{\@expandafter{\eifstrequal{#1}}{#2}} \providecommand\providelength[1]{% \begingroup \escapechar\m@ne \xdef\@gtempa{\string#1}% \endgroup \@ifundefined{\@gtempa}% {\newskip#1}% {}% } % is a string an element of a list of (comma separated) strings \newcommand{\eifstrelement}[4]{% \def\@found{}% \@for\@ii:=#2\do{% \eeifstrequal{\@ii}{#1}{\def\@found{true}}{}% }% \ifdefvoid{\@found}{#4}{#3}% } % do two lists of strings intersect? \newcommand{\ifintersect}[4]{% \def\@intersect{}% \@for\@sname:=#1\do{% \ifdefvoid{\@intersect}{% \eifstrelement{\@sname}{#2}{\def\@intersect{true}}{}% }{}% }% \ifdefvoid{\@intersect}{#4}{#3}% } % get string head and tail \def\strsplit#1{\expandafter\strsplitx#1\empty\empty\empty} \def\strsplitx#1#2\empty{% \edef\strhead{#1}% \edef\strtail{#2}% } % normalize colors: to lowercase and then capitalize \newcommand{\cssDefNormalizeColor}[2]{% \expandafter\@cssNormColor#2\empty{#1}\empty% } \def\@cssNormColor#1#2\empty#3\empty{% \uppercase{\def\@hd{#1}}\lowercase{\def\@tl{#2}}% \expandafter\global\expandafter\edef\csname #3\endcsname{\@hd\@tl}% } % --------------------------------------------------- % Some TeX stuff to compose functions % --------------------------------------------------- \newcommand{\apptox}[2]{% apptox{\cmd1}{\cmd2} == newcommand{\cmd1'}[1]{\cmd1{\cmd2{#1}}} \providecommand{#1}[1]{##1}% define it if necessary (as identity) \protected@edef#1##1{#1{\protect #2{##1}}}% } \newcommand{\pretox}[2]{% pretox{\cmd1}{\cmd2} == newcommand{\cmd1'}[1]{\cmd2{\cmd1{#1}}} \providecommand{#1}[1]{##1}% \protected@edef#1##1{\protect #2{#1{##1}}}% } %------------------------------------------------------------- % Save footnotes inside mdframed and minipage environments %------------------------------------------------------------- \newif\if@saveFootnotes \newcommand{\cssSaveFootnotes}% {\if@saveFootnotes\else% \let\footnote\tablefootnote% \fi% \@saveFootnotestrue}% \newcommand{\cssRestoreFootnotes}% {\if@saveFootnotes\else% \tfn@tablefootnoteprintout% \gdef\tfn@fnt{0}% \fi}% %------------------------------------------------------------- % Setup mdframed with default values %------------------------------------------------------------- \newlength{\cssPixel}\setlength{\cssPixel}{0.4pt}% assume 180 dpi \mdfsetup{% leftmargin=0pt,% rightmargin=0pt,% skipabove=0pt,% skipbelow=0pt,% innertopmargin=0pt,% innerbottommargin=0pt,% innerleftmargin=0pt,% innerrightmargin=0pt,% middlelinewidth=0pt,% linewidth=0pt,% outerlinewidth=0pt,innerlinewidth=0pt% } % --------------------------------------------------- % Basic command to process attributes passed to TeX % --------------------------------------------------- \newif\if@usewrap \newcommand{\@doBefore}{} \newcommand{\@doAfter}{} \newcommand{\@wrapCmd}[1]{#1} \newcommand{\@cssUseCmd}{\renewcommand{\@wrapCmd}[1]{##1}\@usewraptrue} \newcommand{\@cssUseEnv}{\renewcommand{\@doBefore}{}\renewcommand{\@doAfter}{}\@usewrapfalse} \newcommand{\@cssApplyCmd}[1]{{\@wrapCmd{#1}}} \newcommand{\@cssApplyBefore}{\@doBefore{}} \newcommand{\@cssApplyAfter}{\@doAfter{}} \newcommand{\@cssProcessAttrs}[2]{% \setkeys*{cssx}{#1}\setrmkeys*{csspre}\setrmkeys*{css}\setrmkeys*{csspost}% defaults \@cssApplyRulesFor{parentclass}{css}{\cssParentClass}% \setkeys*{cssx}{#2}\setrmkeys*{csspre}\setrmkeys*{css}\setrmkeys*{csspost}% regular \protected@edef\cssParentClass{\cssClass}% } \newcommand{\@cmdBefore}[2]{#1#2} \newcommand{\@cmdAfter}[2]{#2#1} \newcommand{\cssWrapCmd}[1]{\apptox{\@wrapCmd}{#1}} \newcommand{\cssDoBefore}[1]{\if@usewrap\cssWrapCmd{\@cmdBefore{#1}}\else #1\fi} \newcommand{\cssDoAfter}[1]{\if@usewrap\cssWrapCmd{\@cmdAfter{#1}}\else\preto\@doAfter{#1}\fi} \newcommand{\cssDoEnv}[1]{\cssDoBefore{\protect\begin{#1}}\cssDoAfter{\protect\end{#1}}} \newcommand{\cssDoEnvOpt}[2]{\cssDoBefore{\begin{#1}[#2]}\cssDoAfter{\end{#1}}} \newcommand{\cssDoEnvArg}[2]{\cssDoBefore{\begin{#1}{#2}}\cssDoAfter{\end{#1}}} \newcommand{\cssDoEnvArgII}[3]{\cssDoBefore{\begin{#1}{#2}{#3}}\cssDoAfter{\end{#1}}} \newcommand{\newKey}[4][]{\define@key{#2}{#3}[#1]{#4}} \newcommand{\newLength}[2]{\providelength{#1}\setlength{#1}{#2}} \newcommand{\@cssReset}{} \newcommand{\cssAddReset}[1]{\appto{\@cssReset}{#1}} \newcommand{\cssNewResetCommand}[2]{\newcommand{#1}{#2}\cssAddReset{\renewcommand{#1}{#2}}} \newlength{\cssFill} \setlength{\cssFill}{2sp plus 1fill minus 2sp} % make \fill unequal to 0pt, and detectable as 2sp \newcommand{\cssNewLengthKey}[4][0pt]{% \newLength{#4}{#1}% \newKey{#2}{#3}{% \ifstrequal{##1}{auto}{\setlength{#4}{\cssFill}}{\setlength{#4}{##1}}% }% \cssAddReset{\setlength{#4}{#1}}% } \newcommand{\cssNewKeyNoReset}[4]{% \newcommand{#3}{#4}% \newKey{#1}{#2}{\renewcommand{#3}{##1}}% } \newcommand{\cssNewKey}[4]{% \cssNewResetCommand{#3}{#4}% \newKey{#1}{#2}{%(#2=##1)%debug key setting \renewcommand{#3}{##1}}% } \newcommand{\cssNewKeyX}[5]{% \cssNewResetCommand{#3}{#4}% \newKey{#1}{#2}{\renewcommand{#3}{##1}#5{##1}}% } \newcommand{\cssNewListKey}[4]{% \cssNewResetCommand{#3}{#4}% \newKey{#1}{#2}{\appto{#3}{,##1}}% } \newcommand{\cssNewListKeyX}[5]{% \cssNewResetCommand{#3}{#4}% \newKey{#1}{#2}{\appto{#3}{,##1}#5{##1}}% } \newcommand{\cssNewPseudoKey}[3]{% \newKey{#1}{#2}{\setkeys{#1}{#3}}% } %------------------------------------------------------------- % css: display %------------------------------------------------------------- \cssNewKey{css}{display}{\cssDisplay}{block} %------------------------------------------------------------- % css: width, height, and margins %------------------------------------------------------------- \cssNewLengthKey{css}{margin-left}{\cssMarginLeft} \cssNewLengthKey{css}{margin-right}{\cssMarginRight} \cssNewLengthKey{css}{margin-top}{\cssMarginTop} \cssNewLengthKey{css}{margin-bottom}{\cssMarginBottom} \cssNewLengthKey[1sp]{css}{width}{\cssWidth} \cssNewLengthKey[1sp]{css}{height}{\cssHeight} \cssNewKey{css}{vertical-align}{\cssVerticalAlign}{} \cssNewPseudoKey{css}{margin}{margin-top=#1,margin-bottom=#1,margin-left=#1,margin-right=#1} \newcommand{\@cssProcessMargins}{% \eifstrequal{\cssDisplay}{block}% {\@cssBlockEndPar\@cssBlockMargins}% {\eifstrequal{\cssDisplay}{block-inline}% {\@cssBlockMargins}% {\@cssInlineMargins}% }% } \newcommand{\@cssBlockEndPar}{% \cssIfHasClass{para-continue,para-block}{}{\cssDoAfter{\relax\ifhmode\par\global\hangindent=0pt\fi}}% } \newif\if@hasdim \newlength{\cssHeightFull} % height including padding and border \newlength{\cssWidthFull} % width including padding and border \newLength{\@cssMarginAfter}{0pt} \newLength{\@cssParSkip}{\parskip} \newLength{\@cssParIndent}{\parindent} \newcommand{\@cssFixMathSpacing}{\strut\vspace{-\baselineskip}} % fixes weird abovedisplay skip spacing \newcommand{\@cssBlockMargins}{% \@hasdimfalse \ifdim\cssWidth=1sp\setlength{\cssWidthFull}{1sp}\else\@hasdimtrue\fi \ifdim\cssHeight=1sp\setlength{\cssHeightFull}{1sp}\else\@hasdimtrue\fi \if@hasdim% % set full height and width \setlength{\cssWidthFull}{\dimexpr\cssWidth+\cssPaddingLeft+\cssPaddingRight\relax}% \eifstrequal{\cssBorderLeftStyle}{none}{}{\addtolength{\cssWidthFull}{\cssBorderWidth}}% \eifstrequal{\cssBorderRightStyle}{none}{}{\addtolength{\cssWidthFull}{\cssBorderWidth}}% \setlength{\cssHeightFull}{\dimexpr\cssHeight+\cssPaddingTop+\cssPaddingBottom\relax}% \eifstrequal{\cssBorderTopStyle}{none}{}{\addtolength{\cssHeightFull}{\cssBorderWidth}}% \eifstrequal{\cssBorderBottomStyle}{none}{}{\addtolength{\cssHeightFull}{\cssBorderWidth}}% % set default width? \ifdim\cssWidth=1sp% in this case, cssWidthFull is just padding and borders \setlength{\cssWidth}{\dimexpr\linewidth-\cssWidthFull-\cssMarginLeft-\cssMarginRight}% \addtolength{\cssWidthFull}{\cssWidth}% \fi% %minipage \ifdim\cssMarginTop=0pt\else\cssDoBefore{\vspace{\cssMarginTop}}\fi \ifdim\cssMarginLeft=0pt\else\cssDoBefore{\hspace*{\cssMarginLeft}}\fi \setlength{\@cssParIndent}{\parindent}% save parskip and parindent since minipage resets it \setlength{\@cssParSkip}{\parskip}% \eifstrequal{\cssVerticalAlign}{bottom}{\def\@cssValign{b}}% {\eifstrequal{\cssVerticalAlign}{center}{\def\@cssValign{c}}% {\eifstrequal{\cssVerticalAlign}{top}{\def\@cssValign{t}}% {\def\@cssValign{c}}}}% including `middle` \ifdim\cssHeight=1sp% \cssDoBefore{\begin{minipage}[\@cssValign]{\cssWidthFull}}% \else \cssDoBefore{\begin{minipage}[\@cssValign][\cssHeightFull]{\cssWidthFull}}% \fi \cssDoBefore{\cssSaveFootnotes\setlength{\parskip}{\@cssParSkip}\setlength{\parindent}{\@cssParIndent}}% %note: DoAfter prepends, so in opposite order \ifdim\cssMarginBottom=0pt\else\cssDoAfter{\vspace{\cssMarginBottom}}\fi \ifdim\cssMarginRight=0pt\else\cssDoAfter{\hspace*{\cssMarginRight}}\fi \cssDoAfter{\end{minipage}\cssRestoreFootnotes}% \else % no height/width: trivlist \@hasdimfalse \ifdim\cssMarginLeft=0pt\else\@hasdimtrue\fi \ifdim\cssMarginRight=0pt\else\@hasdimtrue\fi \ifdim\cssMarginTop=0pt\else\@hasdimtrue\fi \ifdim\cssMarginBottom=0pt\else\@hasdimtrue\fi \if@hasdim \setlength{\@cssMarginAfter}{\dimexpr\cssMarginBottom-\cssMarginTop\relax}% \cssDoEnvArgII{list}{}{% \leftmargin=\cssMarginLeft% \rightmargin=\cssMarginRight% \topsep=\cssMarginTop% \itemsep=0pt% \parsep=0pt% \parskip=0pt% \partopsep=0pt% \listparindent=\parindent% }% \ifdim\@cssMarginAfter=0pt\else\cssDoAfter{\vspace{\@cssMarginAfter}}\fi% \cssIfHasClass{math-display}% {\cssDoBefore{\item\@cssFixMathSpacing}}% {\cssDoBefore{\item}}% \fi \fi \fi } \newcommand{\@cssHide}[1]{} \newcommand{\@cssInlineMargins}{% \ifdim\cssMarginLeft=0pt\else\cssDoBefore{\hspace*{\cssMarginLeft}}\fi \ifdim\cssMarginRight=0pt\else\cssDoAfter{\hspace*{\cssMarginRight}}\fi \ifdim\cssMarginBottom=0pt\else\cssDoBefore{\rule[-\cssMarginBottom]{0pt}{\cssMarginBottom}}\fi \ifdim\cssMarginTop=0pt\else\cssDoBefore{\rule{0pt}{\dimexpr\baselineskip*0.7+\cssMarginTop\relax}}\fi \eifstrequal{\cssDisplay}{hidden}{% \cssWrapCmd{\@cssHide}% }{}% } %------------------------------------------------------------- % css: Borders and padding %------------------------------------------------------------- \cssNewLengthKey{css}{padding-left}{\cssPaddingLeft} \cssNewLengthKey{css}{padding-right}{\cssPaddingRight} \cssNewLengthKey{css}{padding-top}{\cssPaddingTop} \cssNewLengthKey{css}{padding-bottom}{\cssPaddingBottom} \newlength{\cssBorderWidthTotal} \cssNewLengthKey[\cssPixel]{css}{border-width}{\cssBorderWidth} \cssNewKey{css}{border-color}{\cssBorderColor}{black} \cssNewKey{css}{border-top-style}{\cssBorderTopStyle}{none} \cssNewKey{css}{border-bottom-style}{\cssBorderBottomStyle}{none} \cssNewKey{css}{border-left-style}{\cssBorderLeftStyle}{none} \cssNewKey{css}{border-right-style}{\cssBorderRightStyle}{none} \cssNewKey{css}{background-color}{\cssBackgroundColor}{white} \cssNewPseudoKey{css}{padding}{padding-top=#1,padding-bottom=#1,padding-right=#1,padding-left=#1} \cssNewPseudoKey{css}{border-style}% {border-top-style=#1,border-bottom-style=#1,border-left-style=#1,border-right-style=#1} \newcommand{\@cssProcessPadding}{% \eifstrequal{\cssDisplay}{block}% {\@cssBlockPadding}% {\eifstrequal{\cssDisplay}{block-inline}% {\@cssBlockPadding}% {\@cssInlinePadding}% }} % Special math-framed environment that fixes vertical spacing around math display \newenvironment{mdmathframed}[1][]% {\begin{mdframed}[#1]\@cssFixMathSpacing}% {\@cssFixMathSpacing\end{mdframed}} \newif\if@needframe \newLength{\@cssPaddingLength}{0pt} \newcommand{\@cssFramedArgs}{} \newcommand{\@cssBorderStyleAll}{} \newcommand{\@cssBlockPadding}{% \@needframefalse% \eifstrequal{\cssBorderTopStyle}{none}{}{\@needframetrue}% \eifstrequal{\cssBorderBottomStyle}{none}{}{\@needframetrue}% \eifstrequal{\cssBorderLeftStyle}{none}{}{\@needframetrue}% \eifstrequal{\cssBorderRightStyle}{none}{}{\@needframetrue}% \eifstrequal{\cssBackgroundColor}{white}{}{\@needframetrue}% \ifdim\cssPaddingTop=0pt\else\@needframetrue\fi \ifdim\cssPaddingBottom=0pt\else\@needframetrue\fi \ifdim\cssPaddingLeft=0pt\else\@needframetrue\fi \ifdim\cssPaddingRight=0pt\else\@needframetrue\fi \strsplit{\cssBackgroundColor}% \eifstrequal{\strhead}{\#}% {\definecolor{Temp}{HTML}{\strtail}\edef\@@bcolor{Temp}}% {\cssDefNormalizeColor{@bcolor}{\cssBackgroundColor}\edef\@@bcolor{\@bcolor}}% %\expandafter\lowercase\expandafter{\expandafter\def\expandafter\bcolor\expandafter{\cssBackgroundColor}}% \if@needframe% \cssDoAfter{\cssRestoreFootnotes}% first, because post commands are pre-pended \renewcommand{\@cssFramedArgs}{% innertopmargin=\the\cssPaddingTop,% innerbottommargin=\the\cssPaddingBottom,% innerleftmargin=\the\cssPaddingLeft,% innerrightmargin=\the\cssPaddingRight,% linewidth=\the\cssBorderWidth,% linecolor=\cssBorderColor,% backgroundcolor=\@@bcolor% }% \setlength{\cssBorderWidthTotal}{0pt}% \eifstrequal{\cssBorderTopStyle}{none}{\appto{\@cssFramedArgs}{,topline=false}}{}% \eifstrequal{\cssBorderBottomStyle}{none}{\appto{\@cssFramedArgs}{,bottomline=false}}{}% \eifstrequal{\cssBorderLeftStyle}{none}{\appto{\@cssFramedArgs}{,leftline=false}}% {\addtolength{\cssBorderWidthTotal}{\cssBorderWidth}}% \eifstrequal{\cssBorderRightStyle}{none}{\appto{\@cssFramedArgs}{,rightline=false}}% {\addtolength{\cssBorderWidthTotal}{\cssBorderWidth}}% \cssIfHasClass{math-display}% {\@expandafter{\cssDoEnvOpt{mdmathframed}}{\@cssFramedArgs}}% {\@expandafter{\cssDoEnvOpt{mdframed}}{\@cssFramedArgs}}% % insert a minipage if height or width was set so the frame is as large \@hasdimfalse \ifdim\cssWidth=1sp\else\@hasdimtrue\fi \ifdim\cssHeight=1sp\else\@hasdimtrue\fi \if@hasdim% \ifdim\cssHeight=1sp% \cssDoBefore{\begin{minipage}{\cssWidth}}% \else \cssDoBefore{\begin{minipage}[t][\cssHeight]{\cssWidth}}% \fi \cssDoBefore{\setlength{\parskip}{\@cssParSkip}\setlength{\parindent}{\@cssParIndent}}% %note: DoAfter prepends, so in opposite order \cssDoAfter{\end{minipage}}% \fi \cssDoBefore{\cssSaveFootnotes}% \fi } \newcommand{\@robustFramebox}[2]{% \eifstrequal{\cssTextAlign}{center}{\framebox[#1][c]{#2}}% {\eifstrequal{\cssTextAlign}{right}{\framebox[#1][r]{#2}}% {\framebox[#1][l]{#2}}}% } \newcommand{\@robustMakebox}[2]{% \eifstrequal{\cssDisplay}{table-cell}% {\@robustTableParbox{#1}{#2}}% {\eifstrequal{\cssTextAlign}{center}{\makebox[#1][c]{#2}}% {\eifstrequal{\cssTextAlign}{right}{\makebox[#1][r]{#2}}% {\makebox[#1][l]{#2}}}}% } \newcommand{\@robustRaisebox}[2]{% \raisebox{#1}{#2}% } \newcommand{\@robustHeight}[1]{% \eifstrequal{\cssVerticalAlign}{top}% {\raisebox{0pt}[0pt][\cssHeight]{#1}}% {\eifstrequal{\cssVerticalAlign}{middle}% {\raisebox{0pt}[0.5\cssHeight][0.5\cssHeight]{#1}}% {\eifstrequal{\cssVerticalAlign}{baseline}% {\raisebox{0pt}[\dimexpr\cssHeight-\depth\relax][\depth]{#1}}% {\raisebox{0pt}[\cssHeight][0pt]{#1}}% bottom }}% } \newcommand{\@robustTableParbox}[2]{% \eifstrequal{\cssVerticalAlign}{top}{\def\@cssValign{t}}% {\eifstrequal{\cssVerticalAlign}{center}{\def\@cssValign{c}}% {\eifstrequal{\cssVerticalAlign}{middle}{\def\@cssValign{c}}}% {\def\@cssValign{b}}}% \ifdim\cssHeight=1sp% \parbox[\@cssValign]{#1}{#2}% \else% \parbox[\@cssValign][\cssHeight]{#1}{#2}% \fi% } \newcommand{\@cssInlinePadding}{% \eifstrequal{\cssBackgroundColor}{}{}% {\eifstrequal{\cssBackgroundColor}{white}{}% {\strsplit{\cssBackgroundColor}% \eifstrequal{\strhead}{\#}% {\cssWrapCmd{\protect\colorbox[HTML]{\strtail}}}% {\cssWrapCmd{\@robustColorbox{\cssBackgroundColor}}}% }% }% \@needframefalse% \eifstrequal{\cssBorderTopStyle}{none}{}{\@needframetrue}% \eifstrequal{\cssBorderBottomStyle}{none}{}{\@needframetrue}% \eifstrequal{\cssBorderLeftStyle}{none}{}{\@needframetrue}% \eifstrequal{\cssBorderRightStyle}{none}{}{\@needframetrue}% \if@needframe% \setlength{\fboxrule}{\cssBorderWidth}% \ifdim\cssWidth=1sp% \cssWrapCmd{\fbox}% \else \cssWrapCmd{\@robustFramebox{\cssWidth}}% \fi \else \ifdim\cssWidth=1sp\else \cssWrapCmd{\@robustMakebox{\cssWidth}}% \fi \fi % height? \ifdim\cssHeight=1sp\else\cssWrapCmd{\@robustHeight}\fi % raisebox? \eifstrequal{\cssDisplay}{inline}{% \eifstrequal{\cssVerticalAlign}{}{}% {\eifstrequal{\cssVerticalAlign}{top}{}% {\eifstrequal{\cssVerticalAlign}{bottom}{}% {\eifstrequal{\cssVerticalAlign}{middle}{}% {\eifstrequal{\cssVerticalAlign}{baseline}{}% {\cssWrapCmd{\@robustRaisebox{\cssVerticalAlign}}% }}}}}% }{}% % padding \if@needframe \setlength{\fboxsep}{\cssPaddingTop}% todo: define our own box so we can set paddingtop/bot separately \ifdim\cssPaddingBottom>\fboxsep\setlength{\fboxsep}{\cssPaddingBottom}\fi \ifdim\cssPaddingLeft=\fboxsep\else\hspace*{\dimexpr\cssPaddingLeft-\fboxsep\relax}\fi \ifdim\cssPaddingRight=\fboxsep\else\hspace*{\dimexpr\cssPaddingRight-\fboxsep\relax}\fi \else \ifdim\cssPaddingLeft=0pt\else\cssDoBefore{\hspace*{\cssPaddingLeft}}\fi \ifdim\cssPaddingRight=0pt\else\cssDoAfter{\hspace*{\cssPaddingRight}}\fi \ifdim\cssPaddingBottom=0pt\else\cssDoBefore{\protect\rule[-\cssPaddingBottom]{0pt}{\cssPaddingBottom}}\fi \ifdim\cssPaddingTop=0pt\else\cssDoBefore{\protect\rule{0pt}{\dimexpr\cssPaddingTop+0.8em\relax}}\fi \fi } %------------------------------------------------------------- % css: Textalign, textindent etc %------------------------------------------------------------- \cssNewLengthKey{css}{text-indent}{\cssTextIndent} \cssNewKey{css}{text-align}{\cssTextAlign}{justify} \cssNewLengthKey{css}{line-height}{\cssLineHeight} \cssNewKey{css}{float}{\cssFloat}{} \DeclareRobustCommand{\@robustColor}[1]{% \cssDefNormalizeColor{@fcolor}{#1}\color{\@fcolor}% } \DeclareRobustCommand{\@robustColorbox}[2]{% \cssDefNormalizeColor{@bcolor}{#1}\colorbox{\@bcolor}{#2}% } \newcommand{\@cssProcessText}{% \eifstrequal{\cssDisplay}{block}% {\@cssBlockText}% {\eifstrequal{\cssDisplay}{block-inline}% {\@cssBlockText}% {\eifstrequal{\cssDisplay}{table-cell}% {\@cssBlockText}% {\@cssInlineText}% }}} \newcommand{\@cssBlockText}{% \eifstrequal{\cssId}{}{}{\label{\cssId}}% set label \eifstrequal{\cssTextAlign}{left}% {\cssDoBefore{\protect\raggedright}}% {\eifstrequal{\cssTextAlign}{right}% {\cssDoBefore{\protect\raggedleft}}% {\eifstrequal{\cssTextAlign}{center}% {\cssDoBefore{\protect\centering}}% {}}}% \ifdim\cssLineHeight=0pt\else\setlength{\baselineskip}{\cssLineHeight}\fi \noindent\ifdim\cssTextIndent=0pt\else\hspace*{\cssTextIndent}\fi } \newcommand{\@cssInlineText}{% \eifstrequal{\cssId}{}{}{\label{\cssId}}% set label \eifstrequal{\cssFloat}{left}% {\cssDoAfter{\hspace*{\fill}}}% {\eifstrequal{\cssFloat}{right}% {\cssDoBefore{\hspace*{\fill}}}% {\eifstrequal{\cssFloat}{center}% {\cssDoAfter{\hspace*{\fill}}\cssDoBefore{\hspace*{\fill}}}% {}}}% \ifdim\cssLineHeight=0pt\else\cssDoBefore{\rule{0pt}{\cssLineHeight}}\fi } %------------------------------------------------------------- % css: Font attributes %------------------------------------------------------------- \cssNewKey{css}{font-weight}{\cssFontWeight}{} \cssNewKey{css}{font-variant}{\cssFontVariant}{} \cssNewKey{css}{font-style}{\cssFontStyle}{} \cssNewKey{css}{font-size}{\cssFontSize}{} \cssNewKey{css}{font-family}{\cssFontFamily}{} \cssNewKey{css}{color}{\cssColor}{} \cssNewKey{css}{penalty}{\cssPenalty}{} \newcommand{\@cssProcessFont}{% % font family \edef\@fontFamily{\cssFontFamily}% \@for\@ii:=\cssFontFamily\do{% find the last argument in a comma separated list \edef\@fontFamily{\@ii}% }% \eifstrequal{\@fontFamily}{}{}% quick test {\eifstrequal{\@fontFamily}{monospace}% {\cssDoBefore\ttfamily}% {\eifstrequal{\@fontFamily}{serif}% {\cssDoBefore\rmfamily}% {\eifstrequal{\@fontFamily}{sans-serif}% {\cssDoBefore\sffamily}% {\eifstrequal{\@fontFamily}{normal}% {\cssDoBefore\rmfamily}% {\cssDoBefore{\fontspec{\@fontFamily}}}% }}}}% % \eifstrequal{\cssFontWeight}{bold}% {\cssDoBefore\bfseries}% {\eifstrequal{\cssFontWeight}{normal}% {\cssDoBefore\mdseries}% {}}% \eifstrequal{\cssFontVariant}{small-caps}% {\cssDoBefore\scshape}% {\eifstrequal{\cssFontVariant}{normal}% {\cssDoBefore\upshape}% {}}% \eifstrequal{\cssFontStyle}{italic}% {\cssDoBefore\itshape\hspace{-0.2ex}}% {\eifstrequal{\cssFontStyle}{oblique}% {\cssDoBefore\slshape}% {\eifstrequal{\cssFontStyle}{normal}% {\cssDoBefore\upshape}% {}}}% \eifstrequal{\cssFontSize}{}{}% quick test {\eifstrequal{\cssFontSize}{xx-small}% {\cssDoBefore\tiny}% {\eifstrequal{\cssFontSize}{x-small}% {\cssDoBefore\scriptsize}% {\eifstrequal{\cssFontSize}{small}% {\cssDoBefore\small}% {\eifstrequal{\cssFontSize}{medium}% {\cssDoBefore\normalsize}% {\eifstrequal{\cssFontSize}{large}% {\cssDoBefore\large}% {\eifstrequal{\cssFontSize}{x-large}% {\cssDoBefore\Large}% {\eifstrequal{\cssFontSize}{xx-large}% {\cssDoBefore\LARGE}% {}}}}}}}}% % \eifstrequal{\cssColor}{}{}% {\strsplit{\cssColor}% \eifstrequal{\strhead}{\#}% {\cssDoBefore{\protect\color[HTML]{\strtail}}}% {\cssDoBefore{\@robustColor{\cssColor}}}% }% % \eifstrequal{\cssPenalty}{}{}% {\penalty \cssPenalty\relax}% } %------------------------------------------------------------- % Generic css rules for certain classes, ids, or elements %------------------------------------------------------------- \newcommand{\cssRule}[3]{% \@for\@ii:=#2\do{% \csappto{@rule@#1@\@ii}{,#3}% }% }% \newcommand{\cssRuleDo}[3]{% \@for\@ii:=#2\do{% \csappto{@ruleDo@#1@\@ii}{#3}% }% }% \newcommand{\@cssApplyRulesFor}[3]{% \@for\@ii:=#3\do{% \ifcsmacro{@rule@#1@\@ii}{% \edef\@args{\csname @rule@#1@\@ii\endcsname}% \@expandafter{\setkeys{#2}}{\@args}% }{}% }% } \newcommand{\@cssApplyDoRulesFor}[3]{% \@for\@ii:=#3\do{% \ifcsmacro{@ruleDo@#1@\@ii}{% \csname @ruleDo@#1@\@ii\endcsname% }{}% }% } \newcommand{\cssIfHasClass}[3]{% \def\@found{}% \@for\@ii:=\cssClass\do{% \@for\@cname:=#1\do{% \eeifstrequal{\@ii}{\@cname}{% \def\@found{true}% }{}% }% }% \ifdefvoid{\@found}{#3}{#2}% } \newcommand{\cssClassRule}[2]{\cssRule{class}{#1}{#2}} \newcommand{\cssElemRule}[2]{\cssRule{elem}{#1}{#2}} \newcommand{\cssIdRule}[2]{\cssRule{id}{#1}{#2}} \cssNewListKeyX{cssx}{class}{\cssClass}{}{\@cssApplyRulesFor{class}{css}} \cssNewKeyX{cssx}{elem}{\cssElem}{}{\@cssApplyRulesFor{elem}{css}} \cssNewKeyX{cssx}{id}{\cssId}{}{\@cssApplyRulesFor{id}{css}} \newcommand{\cssClassRuleDo}[2]{\cssRuleDo{class}{#1}{#2}} \newcommand{\cssClassRuleCmd}[2]{\cssClassRuleDo{#1}{\cssWrapCmd{#2}}} \newcommand{\cssClassRuleDoBefore}[2]{\cssClassRuleDo{#1}{\cssDoBefore{#2}}} \newcommand{\cssClassRuleDoAfter}[2]{\cssClassRuleDo{#1}{\cssDoAfter{#2}}} \newcommand{\cssClassRuleEnv}[2]{\cssClassRuleDoBefore{#1}{\begin{#2}}\cssClassRuleDoAfter{#1}{#2}} \newcommand{\cssElemRuleDo}[2]{\cssRuleDo{class}{#1}{#2}} \newcommand{\cssElemRuleCmd}[2]{\cssElemRuleDo{#1}{\cssWrapCmd{#2}}} \newcommand{\cssElemRuleDoBefore}[2]{\cssElemRuleDo{#1}{\cssDoBefore{#2}}} \newcommand{\cssElemRuleDoAfter}[2]{\cssElemRuleDo{#1}{\cssDoAfter{#2}}} \newcommand{\cssElemRuleEnv}[2]{\cssElemRuleDo{#1}{\cssDoEnv{#2}}} \newcommand{\@cssClassDoRules}{\@cssApplyDoRulesFor{class}{css}{\cssClass}} \newcommand{\@cssElemDoRules}{% \@cssApplyDoRulesFor{elem}{css}{\cssElem}% \@cssApplyDoRulesFor{id}{css}{\cssId}% } \newcommand{\cssParentClass}{} \newcommand{\cssParentClassRule}[2]{\cssRule{parentclass}{#1}{#2}} %------------------------------------------------------------- % %------------------------------------------------------------- \newenvironment{cssBlockX}[2]% {\@cssReset\@cssUseEnv\@cssProcessAttrs{#1}{#2}% \@cssElemDoRules% \@cssProcessMargins\@cssProcessPadding% \@cssClassDoRules% \@cssProcessText\@cssProcessFont% \@cssApplyBefore}% {\@cssApplyAfter} \newenvironment{cssBlock}[1][]% {\begin{cssBlockX}{}{#1}}{\end{cssBlockX}} \newcommand{\cssInlineX}[4]% {\@cssReset\@cssUseCmd\@cssProcessAttrs{display=inline,#1}{#2}% \@cssElemDoRules% \@cssProcessMargins\@cssProcessPadding% \@cssClassDoRules% #3% \@cssProcessText\@cssProcessFont% \@cssApplyCmd{#4}% }% \newcommand{\cssInline}[2][]{\cssInlineX{}{#1}{}{#2}} \newcommand{\cssInlineCmd}[3][]{\cssInlineX{}{#1}{\cssWrapCmd{#2}}{#3}} \newcommand{\cssNewBlockElem}[3]{% \newenvironment{#1}[1][]{\begin{cssBlockX}{elem=#2,#3}{##1}}{\end{cssBlockX}}} \newcommand{\cssNewInlineElem}[3]{% \newcommand{#1}[2][]{\cssInlineX{elem=#2,#3}{##1}{}{##2}}} \newcommand{\cssNewInlineElemCmd}[4]{% \newcommand{#1}[2][]{\cssInlineX{elem=#2,#3}{##1}{\cssWrapCmd{#4}}{##2}}} \newcommand{\cssInitKeys}[1]{% \@cssReset\@cssUseCmd\@cssProcessAttrs{display=inline}{#1}% } % cssText is just for font attributes; no padding or margins \newcommand{\cssTextX}[2]% {\@cssReset\@cssUseCmd\@cssProcessAttrs{display=inline}{#1}% \@cssElemDoRules% %\@cssProcessMargins\@cssProcessPadding% \@cssClassDoRules% \@cssProcessText\@cssProcessFont% \@cssApplyCmd{#2}% }% \newcommand{\cssText}[2][]{\cssTextX{#1}{#2}}