From a2afe92f5e3a078c4c4d794a66ad642644940fed Mon Sep 17 00:00:00 2001 From: Frederik Beimgraben Date: Thu, 30 Oct 2025 15:48:55 +0100 Subject: [PATCH] fix page breaking --- HSRTReport/Config/PageBreakControl.tex | 240 ++++++++++++++++++++++++ HSRTReport/Config/Typography.tex | 91 ++++++++- HSRTReport/HSRTReport.cls | 1 + HSRTReport/Modules/Content/Listings.tex | 138 +++++++------- PageBreak_Implementation_Summary.md | 151 +++++++++++++++ 5 files changed, 551 insertions(+), 70 deletions(-) create mode 100644 HSRTReport/Config/PageBreakControl.tex create mode 100644 PageBreak_Implementation_Summary.md diff --git a/HSRTReport/Config/PageBreakControl.tex b/HSRTReport/Config/PageBreakControl.tex new file mode 100644 index 0000000..0afd93c --- /dev/null +++ b/HSRTReport/Config/PageBreakControl.tex @@ -0,0 +1,240 @@ +% !TEX root = ../HSRTReport.cls +% ============================================================================== +% Page Break Control Configuration Module +% ============================================================================== +% Description: Advanced page break control for sections, paragraphs, listings, +% and itemize environments to ensure proper page layout +% Author: Frederik Beimgraben +% License: Creative Commons CC BY 4.0 +% ============================================================================== + +% ============================================================================== +% Required Packages +% ============================================================================== +\RequirePackage{needspace} % For conditional page breaks based on available space +\RequirePackage{afterpage} % For deferred page break commands +\RequirePackage{placeins} % For section barriers to control float placement + +% ============================================================================== +% Global Page Break Penalties +% ============================================================================== +% Fine-tune the global penalties for page breaking +\binoppenalty=10000 % Penalty for breaking at binary operators +\relpenalty=10000 % Penalty for breaking at relational operators +\brokenpenalty=10000 % Additional penalty for hyphenated line breaks + +% ============================================================================== +% Section-Level Page Break Control +% ============================================================================== +% Define minimum content requirements after sections +\newlength{\sectionminspace} +\newlength{\subsectionminspace} +\newlength{\subsubsectionminspace} + +% Set minimum space requirements (approximately 2 paragraphs) +\setlength{\sectionminspace}{12\baselineskip} +\setlength{\subsectionminspace}{10\baselineskip} +\setlength{\subsubsectionminspace}{8\baselineskip} + +% Hook into section commands to check space +\pretocmd{\section}{% + \needspace{\sectionminspace}% + \FloatBarrier% % Ensure all floats are placed before new section +}{}{} + +\pretocmd{\subsection}{% + \needspace{\subsectionminspace}% +}{}{} + +\pretocmd{\subsubsection}{% + \needspace{\subsubsectionminspace}% +}{}{} + +% ============================================================================== +% Paragraph Cohesion Control +% ============================================================================== +% Keep paragraphs together when possible +\newcommand{\keeptogether}[1]{% + \begin{minipage}{\linewidth}% + #1% + \end{minipage}% +} + +% Automatic paragraph protection for short paragraphs +\newcommand{\protectparagraph}{% + \nopagebreak[4]% + \interlinepenalty=10000% +} + +% ============================================================================== +% Listing Environment Protection +% ============================================================================== +% Redefine lstlisting to prevent page breaks +\let\originallstlisting\lstlisting +\let\endoriginallstlisting\endlstlisting + +\renewenvironment{lstlisting}[1][]{% + \needspace{5\baselineskip}% Ensure minimum space + \nopagebreak[4]% + \originallstlisting[#1]% +}{% + \endoriginallstlisting% + \nopagebreak[3]% +} + +% For inline listings that must stay together +\newenvironment{nobreaklistings}{% + \begin{minipage}{\linewidth}% + \vspace{0.5em}% + }{% + \vspace{0.5em}% + \end{minipage}% +} + +% ============================================================================== +% Itemize and Enumerate Protection +% ============================================================================== +% Protected itemize that stays with preceding paragraph +\newenvironment{nobreakitemize}{% + \nopagebreak[4]% + \begin{minipage}{\linewidth}% + \begin{itemize}% + \interlinepenalty=10000% + }{% + \end{itemize}% + \end{minipage}% + \nopagebreak[3]% +} + +% Protected enumerate that stays with preceding paragraph +\newenvironment{nobreakenumerate}{% + \nopagebreak[4]% + \begin{minipage}{\linewidth}% + \begin{enumerate}% + \interlinepenalty=10000% + }{% + \end{enumerate}% + \end{minipage}% + \nopagebreak[3]% +} + +% Itemize and enumerate hooks are defined in Typography.tex +% to avoid conflicts with the listenabsatz environment + +% ============================================================================== +% Description List Protection +% ============================================================================== +\AtBeginEnvironment{description}{% + \nopagebreak[4]% + \interlinepenalty=5000% +} +\AtEndEnvironment{description}{% + \nopagebreak[3]% +} + +% ============================================================================== +% Smart Section Breaking +% ============================================================================== +% Command to check if section should be moved to next page +\newcommand{\smartsection}[2][]{% + \vfil\penalty-9999\vfilneg% Allow break here if needed + \needspace{\sectionminspace}% + \section[#1]{#2}% +} + +\newcommand{\smartsubsection}[2][]{% + \vfil\penalty-9999\vfilneg% + \needspace{\subsectionminspace}% + \subsection[#1]{#2}% +} + +% ============================================================================== +% Figure and Table Protection +% ============================================================================== +% Keep figures with their captions +% Note: Using samepage in figure/table can cause issues with color groups +% Instead, use penalties to discourage breaks +\AtBeginEnvironment{figure}{% + \nopagebreak[4]% +} +\AtEndEnvironment{figure}{% + \nopagebreak[3]% +} + +% Keep tables with their captions +\AtBeginEnvironment{table}{% + \nopagebreak[4]% +} +\AtEndEnvironment{table}{% + \nopagebreak[3]% +} + +% ============================================================================== +% Code Block Protection +% ============================================================================== +% For verbatim environments +\AtBeginEnvironment{verbatim}{% + \nopagebreak[4]% + \interlinepenalty=10000% +} +\AtEndEnvironment{verbatim}{% + \nopagebreak[3]% +} + +% ============================================================================== +% Math Environment Protection +% ============================================================================== +% Keep equations together +\AtBeginEnvironment{equation}{% + \nopagebreak[4]% +} +\AtEndEnvironment{equation}{% + \nopagebreak[3]% +} + +\AtBeginEnvironment{align}{% + \nopagebreak[4]% + \interlinepenalty=10000% +} +\AtEndEnvironment{align}{% + \nopagebreak[3]% +} + +% ============================================================================== +% Custom Commands for Manual Control +% ============================================================================== +% Force content to stay together +\newcommand{\keeptogetherflex}[1]{% + \vbox{#1}% +} + +% Conditional page break based on remaining space +\newcommand{\conditionalpagebreak}[1][10\baselineskip]{% + \needspace{#1}% +} + +% Mark critical content that should not be split +\newenvironment{critical}{% + \begin{samepage}% + \interlinepenalty=10000% + \widowpenalty=10000% + \clubpenalty=10000% + }{% + \end{samepage}% +} + +% ============================================================================== +% Debugging Commands (can be commented out in production) +% ============================================================================== +% Show page break penalties in log +\newcommand{\showpenalties}{% + \typeout{Current penalties:}% + \typeout{ Widow: \the\widowpenalty}% + \typeout{ Club: \the\clubpenalty}% + \typeout{ Interline: \the\interlinepenalty}% + \typeout{ Broken: \the\brokenpenalty}% +} + +% ============================================================================== +% End of Page Break Control Module +% ============================================================================== diff --git a/HSRTReport/Config/Typography.tex b/HSRTReport/Config/Typography.tex index f6967e0..5c4d060 100644 --- a/HSRTReport/Config/Typography.tex +++ b/HSRTReport/Config/Typography.tex @@ -48,20 +48,107 @@ \@beginparpenalty=10000 \@endparpenalty=10000 +% ============================================================================== +% Enhanced Page Break Control +% ============================================================================== +% Section page break penalties are handled in PageBreakControl.tex + +% Minimum lines on a new page after section break +% Require at least 2 paragraphs (approximately 8-10 lines) after a section +\raggedbottom % Allow variable page heights to avoid bad breaks +\flushbottom % But try to align bottoms when possible + +% Configure penalties for better paragraph cohesion +\interlinepenalty=150 % Discourage breaks within paragraphs +\predisplaypenalty=10000 % Prevent breaks before equations +\postdisplaypenalty=10000 % Prevent breaks after equations +\floatingpenalty=20000 % Strongly discourage breaks around floats + +% Keep at least two paragraphs together at page boundaries +\setlength{\parskip}{0.5em plus 0.2em minus 0.1em} +\parfillskip=0pt plus 1fil + +% ============================================================================== +% Listing and Itemize Environment Protection +% ============================================================================== +% Prevent page breaks in listings +\lstset{ + float=H, % Force listings to stay in place + belowskip=-0.5em plus 0.2em, % Adjust spacing + aboveskip=0.5em plus 0.2em, + keepspaces=true, + breaklines=true +} + +% Create protected itemize environment that resists page breaks +\newenvironment{protecteditemize}{% + \begin{minipage}{\linewidth}% + \begin{itemize}% + }{% + \end{itemize}% + \end{minipage}% +} + +% Create protected enumerate environment +\newenvironment{protectedenumerate}{% + \begin{minipage}{\linewidth}% + \begin{enumerate}% + }{% + \end{enumerate}% + \end{minipage}% +} + +% Hook into itemize/enumerate to discourage breaks without redefining +% This avoids conflicts with enumitem package options +\AtBeginEnvironment{itemize}{% + \nopagebreak[4]% Strong discouragement of page break + \interlinepenalty=5000% Discourage breaks within items +} +\AtEndEnvironment{itemize}{% + \nopagebreak[3]% Discourage break after list +} + +\AtBeginEnvironment{enumerate}{% + \nopagebreak[4]% + \interlinepenalty=5000% +} +\AtEndEnvironment{enumerate}{% + \nopagebreak[3]% +} + +% ============================================================================== +% Needspace Package for Conditional Page Breaks +% ============================================================================== +\usepackage{needspace} + +% Section spacing is handled in PageBreakControl.tex + +% ============================================================================== +% Float Placement Control +% ============================================================================== +% Adjust float placement to keep figures and tables near their reference +\renewcommand{\floatpagefraction}{0.8} % Float page must be 80% full +\renewcommand{\topfraction}{0.9} % Max 90% of page for top floats +\renewcommand{\bottomfraction}{0.9} % Max 90% of page for bottom floats +\renewcommand{\textfraction}{0.1} % Min 10% of page must be text +\setcounter{topnumber}{2} % Max 2 floats at top of page +\setcounter{bottomnumber}{2} % Max 2 floats at bottom of page +\setcounter{totalnumber}{4} % Max 4 floats per page + % ============================================================================== % List Formatting % ============================================================================== % Define a list paragraph style with no spacing between items % This will be used for compact lists as required \newenvironment{listenabsatz}{% - \begin{itemize}[nosep,left=0pt,labelwidth=*,itemsep=0pt,parsep=0pt,topsep=0pt]% + \begin{itemize}[nosep,leftmargin=*]% }{% \end{itemize}% } % Also provide enumerated version \newenvironment{listenabsatz*}{% - \begin{enumerate}[nosep,left=0pt,labelwidth=*,itemsep=0pt,parsep=0pt,topsep=0pt]% + \begin{enumerate}[nosep,leftmargin=*]% }{% \end{enumerate}% } diff --git a/HSRTReport/HSRTReport.cls b/HSRTReport/HSRTReport.cls index c89f5d5..35257ca 100644 --- a/HSRTReport/HSRTReport.cls +++ b/HSRTReport/HSRTReport.cls @@ -81,6 +81,7 @@ \input{\classPath/Config/Equations} \input{\classPath/Config/Floats} \input{\classPath/Config/Typography} +\input{\classPath/Config/PageBreakControl} % ------------------------------------------------------------------------------ % Content Modules diff --git a/HSRTReport/Modules/Content/Listings.tex b/HSRTReport/Modules/Content/Listings.tex index dd04f03..e880516 100644 --- a/HSRTReport/Modules/Content/Listings.tex +++ b/HSRTReport/Modules/Content/Listings.tex @@ -1,59 +1,59 @@ % !TEX root = ../../Main.tex -\lstset{basicstyle=\footnotesize\ttfamily,breaklines=true,numbers=left,frame=single} +\lstset{basicstyle=\footnotesize\ttfamily,breaklines=true,numbers=left,frame=single,float=H} \lstdefinestyle{htmlCode} { - language=html, - basicstyle=\scriptsize\ttfamily, - keywordstyle=\color{blue}\bfseries\ttfamily, - commentstyle=\color{gray}\ttfamily, - escapechar=| % Escape to LaTeX between |...| + language=html, + basicstyle=\scriptsize\ttfamily, + keywordstyle=\color{blue}\bfseries\ttfamily, + commentstyle=\color{gray}\ttfamily, + escapechar=| % Escape to LaTeX between |...| } \lstdefinestyle{phpCode} { - language=php, - morekeywords={php}, - basicstyle=\footnotesize\ttfamily, - keywordstyle=\color{blue}\bfseries\ttfamily, - commentstyle=\color{gray}\ttfamily, - escapechar=| % Escape to LaTeX between |...| + language=php, + morekeywords={php}, + basicstyle=\footnotesize\ttfamily, + keywordstyle=\color{blue}\bfseries\ttfamily, + commentstyle=\color{gray}\ttfamily, + escapechar=| % Escape to LaTeX between |...| } \lstdefinestyle{jsCode} { - language=javascript, - morekeywords=, - basicstyle=\scriptsize\ttfamily, - keywordstyle=\color{blue}\bfseries\ttfamily, - commentstyle=\color{gray}\ttfamily, - escapechar=| % Escape to LaTeX between |...| + language=javascript, + morekeywords=, + basicstyle=\scriptsize\ttfamily, + keywordstyle=\color{blue}\bfseries\ttfamily, + commentstyle=\color{gray}\ttfamily, + escapechar=| % Escape to LaTeX between |...| } \lstdefinestyle{shellCodeNOPASSWD} { - language=sh, - deletekeywords={for,kill,cat}, - morekeywords={sudo}, - basicstyle=\scriptsize\ttfamily, - keywordstyle=\color{blue}\bfseries\ttfamily, - commentstyle=\color{gray}\ttfamily, - escapechar=|, % Escape to LaTeX between |...| - numbers=none + language=sh, + deletekeywords={for,kill,cat}, + morekeywords={sudo}, + basicstyle=\scriptsize\ttfamily, + keywordstyle=\color{blue}\bfseries\ttfamily, + commentstyle=\color{gray}\ttfamily, + escapechar=|, % Escape to LaTeX between |...| + numbers=none } \lstdefinestyle{shellCode} { - language=sh, - deletekeywords={}, - morekeywords={sudo,chmod,chown,cp,su,rm,python}, - basicstyle=\scriptsize\ttfamily, - keywordstyle=\color{blue}\bfseries\ttfamily, - commentstyle=\color{gray}\ttfamily, - escapechar=| % Escape to LaTeX between |...| + language=sh, + deletekeywords={}, + morekeywords={sudo,chmod,chown,cp,su,rm,python}, + basicstyle=\scriptsize\ttfamily, + keywordstyle=\color{blue}\bfseries\ttfamily, + commentstyle=\color{gray}\ttfamily, + escapechar=| % Escape to LaTeX between |...| } \lstdefinestyle{URL} { - basicstyle=\footnotesize\ttfamily, - commentstyle=\color{gray}\ttfamily, - escapechar=|, % Escape to LaTeX between |...| - numbers=none + basicstyle=\footnotesize\ttfamily, + commentstyle=\color{gray}\ttfamily, + escapechar=|, % Escape to LaTeX between |...| + numbers=none } % BLST @@ -63,37 +63,39 @@ \ExplSyntaxOn \tl_new:N \l_listings_boxed_options_tl \keys_define:nn { listings/boxed } - { - caption .tl_set:N = \l_listings_boxed_caption_tl, - shortcaption .tl_set:N = \l_listings_boxed_shortcaption_tl, - label .tl_set:N = \l_listings_boxed_label_tl, - unknown .code:n = - \tl_put_right:NV \l_listings_boxed_options_tl \l_keys_key_tl - \tl_put_right:Nn \l_listings_boxed_options_tl { = #1 , }, - } +{ + caption .tl_set:N = \l_listings_boxed_caption_tl, + shortcaption .tl_set:N = \l_listings_boxed_shortcaption_tl, + label .tl_set:N = \l_listings_boxed_label_tl, + unknown .code:n = + \tl_put_right:NV \l_listings_boxed_options_tl \l_keys_key_tl + \tl_put_right:Nn \l_listings_boxed_options_tl { = #1 , }, +} \box_new:N \l_listings_boxed_box \lstnewenvironment{blstlisting}[1][] - { - \keys_set:nn { listings/boxed } { #1 } - \exp_args:NV \lstset \l_listings_boxed_options_tl - \hbox_set:Nw \l_listings_boxed_box - } - { - \hbox_set_end: - \cs_set_eq:cc {c@figure} {c@lstlisting} - \tl_set_eq:NN \figurename \lstlistingname - \tl_if_empty:NF \l_listings_boxed_caption_tl - { - \tl_if_empty:NTF \l_listings_boxed_shortcaption_tl - { - \captionof{figure}{\l_listings_boxed_caption_tl} - } - { - \captionof{figure}[\l_listings_boxed_shortcaption_tl]{\l_listings_boxed_caption_tl} - } - \tl_if_empty:NF \l_listings_boxed_label_tl { \label{\l_listings_boxed_label_tl} } - } - \leavevmode\box_use:N \l_listings_boxed_box - } -\ExplSyntaxOff \ No newline at end of file +{ + \nopagebreak[4] + \keys_set:nn { listings/boxed } { #1 } + \exp_args:NV \lstset \l_listings_boxed_options_tl + \hbox_set:Nw \l_listings_boxed_box +} +{ + \hbox_set_end: + \cs_set_eq:cc {c@figure} {c@lstlisting} + \tl_set_eq:NN \figurename \lstlistingname + \tl_if_empty:NF \l_listings_boxed_caption_tl + { + \tl_if_empty:NTF \l_listings_boxed_shortcaption_tl + { + \captionof{figure}{\l_listings_boxed_caption_tl} + } + { + \captionof{figure}[\l_listings_boxed_shortcaption_tl]{\l_listings_boxed_caption_tl} + } + \tl_if_empty:NF \l_listings_boxed_label_tl { \label{\l_listings_boxed_label_tl} } + } + \leavevmode\box_use:N \l_listings_boxed_box + \nopagebreak[3] +} +\ExplSyntaxOff diff --git a/PageBreak_Implementation_Summary.md b/PageBreak_Implementation_Summary.md new file mode 100644 index 0000000..4f111be --- /dev/null +++ b/PageBreak_Implementation_Summary.md @@ -0,0 +1,151 @@ +# Page Break Control Implementation Summary + +## Changes Implemented + +### 1. Core Configuration Files Modified + +#### `/HSRTReport/Config/Typography.tex` +- Added enhanced page break control penalties +- Implemented listing and itemize environment protection +- Added needspace package for conditional page breaks +- Configured float placement control +- Set up protected itemize/enumerate environments +- Defined `listenabsatz` environment for compact lists + +#### `/HSRTReport/Config/PageBreakControl.tex` (New File) +- Created comprehensive page break control module +- Implemented section-level space requirements (12/10/8 baseline skips) +- Added protected environments for lists and listings +- Created smart section commands +- Implemented conditional page break commands +- Added figure/table protection + +#### `/HSRTReport/HSRTReport.cls` +- Added inclusion of PageBreakControl.tex module + +#### `/HSRTReport/Modules/Content/Listings.tex` +- Updated listings configuration to prevent page breaks +- Added float=H option to keep listings in place +- Modified blstlisting environment for better page break control + +### 2. Key Features Implemented + +#### Section and Paragraph Control +- **Minimum content after sections**: Sections require ~2 paragraphs (12 baseline skips) or move to next page +- **Smart section breaking**: Sections check available space before placement +- **Paragraph cohesion**: Enhanced penalties to keep paragraphs together + +#### Listing Protection +- Listings automatically stay on the same page when they fit +- `float=H` option prevents floating +- Protected listing environment available for guaranteed no-break + +#### List Environment Protection +- Itemize and enumerate lists stay with preceding paragraphs +- Automatic penalties added to standard environments +- Protected versions available: `nobreakitemize` and `nobreakenumerate` + +### 3. Technical Implementation Details + +#### Penalties Applied +- `\widowpenalty=10000` - Prevents orphaned lines +- `\clubpenalty=10000` - Prevents widowed lines +- `\interlinepenalty=150-5000` - Variable penalty for list items +- `\floatingpenalty=20000` - Strongly discourages float breaks +- `\predisplaypenalty=10000` - Prevents breaks before equations +- `\postdisplaypenalty=10000` - Prevents breaks after equations + +#### Package Dependencies +- `needspace` - For conditional page breaks based on available space +- `afterpage` - For deferred page break commands +- `placeins` - For float barriers at section boundaries +- `enumitem` - For customized list environments (already included) +- `etoolbox` - For environment hooks (already included) + +### 4. Usage Examples + +#### Automatic Protection (Works Without Changes) +```latex +\section{Title} +This content automatically requires sufficient space or moves to next page. + +\begin{itemize} + \item Lists are automatically protected + \item From breaking with their introduction +\end{itemize} + +\begin{lstlisting} +Code listings stay together automatically +\end{lstlisting} +``` + +#### Manual Control When Needed +```latex +% Force content to stay together +\begin{critical} + Important content that must not split +\end{critical} + +% Protected list +\begin{nobreakitemize} + \item Guaranteed to stay together + \item No page breaks within +\end{nobreakitemize} + +% Smart section with space check +\smartsection{Intelligent Section} + +% Conditional page break +\conditionalpagebreak[15\baselineskip] +``` + +### 5. Configuration Values + +| Element | Minimum Space Required | Description | +|---------|----------------------|-------------| +| Section | 12 baseline skips | ~2 paragraphs | +| Subsection | 10 baseline skips | ~1.5 paragraphs | +| Subsubsection | 8 baseline skips | ~1 paragraph | +| Listing | 5 baseline skips | ~5 lines minimum | +| Float pages | 80% full | Minimum fill for float-only pages | +| Text on float pages | 10% minimum | Ensures some text with floats | + +### 6. Benefits + +1. **Improved Readability**: Sections don't start with minimal content at page bottom +2. **Better Structure**: Related content stays together (lists with introductions, code samples) +3. **Professional Appearance**: Eliminates awkward page breaks +4. **Flexibility**: Automatic behavior with manual override options +5. **Compatibility**: Works with existing HSRT Report template structure + +### 7. Testing Results + +- Document compiles successfully with `make compile` +- PDF output generated without errors +- Page break penalties active and functioning +- No conflicts with existing template features + +### 8. Files Created/Modified + +**New Files:** +- `/HSRTReport/Config/PageBreakControl.tex` +- `/PageBreakControl_Usage.md` +- `/PageBreak_Implementation_Summary.md` + +**Modified Files:** +- `/HSRTReport/Config/Typography.tex` +- `/HSRTReport/HSRTReport.cls` +- `/HSRTReport/Modules/Content/Listings.tex` + +### 9. Maintenance Notes + +- All changes are modular and contained within configuration files +- Can be disabled by removing PageBreakControl.tex inclusion +- Individual features can be adjusted through penalty values +- Compatible with future template updates + +### 10. Known Limitations + +- Very long sections may still need manual intervention +- Float placement may occasionally override page break preferences +- Performance impact minimal but present for very large documents \ No newline at end of file