Automatically adds page breaks before section headers in Word documents
Size
7.9 KB
Version
1.1.1
Created
Feb 25, 2026
Updated
25 days ago
1// ==UserScript==
2// @name OneDrive Auto Page Break Inserter
3// @description Automatically adds page breaks before section headers in Word documents
4// @version 1.1.1
5// @match https://*.onedrive.live.com/*
6// @icon https://res.public.onecdn.static.microsoft/officeonline/wv/s/h461C01F586C5322D_resources/1033/FavIcon_Word.ico
7// ==/UserScript==
8(function() {
9 'use strict';
10
11 console.log('OneDrive Auto Page Break Inserter loaded');
12
13 // Debounce function to avoid excessive processing
14 function debounce(func, wait) {
15 let timeout;
16 return function executedFunction(...args) {
17 const later = () => {
18 clearTimeout(timeout);
19 func(...args);
20 };
21 clearTimeout(timeout);
22 timeout = setTimeout(later, wait);
23 };
24 }
25
26 // Function to check if a paragraph looks like a section header
27 function isSectionHeader(text) {
28 if (!text || text.trim().length === 0) return false;
29
30 const trimmedText = text.trim();
31
32 // Check for patterns like "Narrative Report: Day X", "Date: ...", "Agenda: ..."
33 const headerPatterns = [
34 /^Narrative Report:\s*Day\s*\d+/i,
35 /^Date:\s*.+/i,
36 /^Agenda:\s*.+/i,
37 /^Day\s*\d+/i,
38 /^Chapter\s*\d+/i,
39 /^Section\s*\d+/i
40 ];
41
42 return headerPatterns.some(pattern => pattern.test(trimmedText));
43 }
44
45 // Function to add page breaks before section headers
46 async function addPageBreaks() {
47 console.log('Checking for section headers...');
48
49 // Wait for the document to be fully loaded
50 await new Promise(resolve => setTimeout(resolve, 2000));
51
52 // Find all paragraphs in the Word Online editor
53 const paragraphs = document.querySelectorAll('div[role="textbox"] p, div.OutlineElement p, div[class*="paragraph"]');
54
55 if (paragraphs.length === 0) {
56 console.log('No paragraphs found yet, will retry...');
57 return;
58 }
59
60 console.log(`Found ${paragraphs.length} paragraphs`);
61
62 let processedCount = 0;
63
64 paragraphs.forEach((paragraph, index) => {
65 const text = paragraph.textContent;
66
67 if (isSectionHeader(text)) {
68 console.log(`Found section header: "${text}"`);
69
70 // Check if there's already a page break before this paragraph
71 const prevElement = paragraph.previousElementSibling;
72 const hasPageBreak = prevElement && (
73 prevElement.style.pageBreakBefore === 'always' ||
74 prevElement.style.breakBefore === 'page'
75 );
76
77 if (!hasPageBreak && index > 0) {
78 // Add page break style to the paragraph
79 paragraph.style.pageBreakBefore = 'always';
80 paragraph.style.breakBefore = 'page';
81 processedCount++;
82 console.log(`Added page break before: "${text}"`);
83 }
84 }
85 });
86
87 if (processedCount > 0) {
88 console.log(`Successfully added ${processedCount} page breaks`);
89 }
90 }
91
92 // Function to add a button to manually trigger page breaks
93 function addControlButton() {
94 // Wait for the Word Online interface to load
95 setTimeout(() => {
96 // Try multiple locations for the button
97 const toolbar = document.querySelector('div[role="toolbar"], div[class*="CommandBar"], div[id*="RibbonContainer"]');
98
99 if (document.getElementById('auto-page-break-btn')) {
100 return;
101 }
102
103 // Create a container for the button
104 const buttonContainer = document.createElement('div');
105 buttonContainer.id = 'auto-page-break-container';
106 buttonContainer.style.cssText = `
107 position: fixed;
108 top: 80px;
109 right: 20px;
110 z-index: 10000;
111 display: flex;
112 flex-direction: column;
113 gap: 10px;
114 `;
115
116 const button = document.createElement('button');
117 button.id = 'auto-page-break-btn';
118 button.innerHTML = '📄 Auto Page Breaks';
119 button.style.cssText = `
120 padding: 12px 20px;
121 background: linear-gradient(135deg, #0078d4 0%, #106ebe 100%);
122 color: white;
123 border: none;
124 border-radius: 8px;
125 cursor: pointer;
126 font-size: 16px;
127 font-weight: 600;
128 box-shadow: 0 4px 12px rgba(0, 120, 212, 0.4);
129 transition: all 0.3s ease;
130 min-width: 180px;
131 text-align: center;
132 `;
133
134 button.addEventListener('mouseenter', () => {
135 button.style.transform = 'translateY(-2px)';
136 button.style.boxShadow = '0 6px 16px rgba(0, 120, 212, 0.6)';
137 });
138
139 button.addEventListener('mouseleave', () => {
140 button.style.transform = 'translateY(0)';
141 button.style.boxShadow = '0 4px 12px rgba(0, 120, 212, 0.4)';
142 });
143
144 button.addEventListener('click', async () => {
145 button.innerHTML = '⏳ Processing...';
146 button.disabled = true;
147 button.style.background = 'linear-gradient(135deg, #ffa500 0%, #ff8c00 100%)';
148 button.style.cursor = 'not-allowed';
149
150 await addPageBreaks();
151
152 button.innerHTML = '✅ Done!';
153 button.style.background = 'linear-gradient(135deg, #28a745 0%, #20c997 100%)';
154 setTimeout(() => {
155 button.innerHTML = '📄 Auto Page Breaks';
156 button.disabled = false;
157 button.style.background = 'linear-gradient(135deg, #0078d4 0%, #106ebe 100%)';
158 button.style.cursor = 'pointer';
159 }, 2000);
160 });
161
162 // Add status indicator
163 const statusDiv = document.createElement('div');
164 statusDiv.id = 'page-break-status';
165 statusDiv.style.cssText = `
166 padding: 8px 12px;
167 background: rgba(255, 255, 255, 0.95);
168 color: #333;
169 border-radius: 6px;
170 font-size: 13px;
171 text-align: center;
172 box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
173 display: none;
174 `;
175
176 buttonContainer.appendChild(button);
177 buttonContainer.appendChild(statusDiv);
178 document.body.appendChild(buttonContainer);
179 console.log('Auto Page Break button added to page');
180 }, 3000);
181 }
182
183 // Initialize the extension
184 function init() {
185 console.log('Initializing Auto Page Break extension...');
186
187 // Add the control button
188 addControlButton();
189
190 // Automatically process page breaks when document loads
191 setTimeout(() => {
192 addPageBreaks();
193 }, 3000);
194
195 // Watch for document changes and reprocess
196 const debouncedAddPageBreaks = debounce(addPageBreaks, 2000);
197
198 const observer = new MutationObserver(debouncedAddPageBreaks);
199
200 // Observe the document body for changes
201 observer.observe(document.body, {
202 childList: true,
203 subtree: true
204 });
205
206 console.log('Auto Page Break extension initialized');
207 }
208
209 // Start when the page is ready
210 if (document.readyState === 'loading') {
211 document.addEventListener('DOMContentLoaded', init);
212 } else {
213 init();
214 }
215})();