Full document, spreadsheet, slideshow, and diagram tooling
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 64 lines 1.6 kB view raw
1/** 2 * Document Minimap — VS Code-style overview for long documents. 3 * 4 * Pure logic module: heading extraction, viewport calculation. 5 * DOM rendering is handled in main.ts. 6 */ 7 8export interface MinimapHeading { 9 level: number; 10 text: string; 11 id: string; 12} 13 14export interface ViewportIndicator { 15 top: number; // percentage 16 height: number; // percentage 17} 18 19/** 20 * Extract headings from HTML content for the minimap outline. 21 */ 22export function extractHeadings(html: string): MinimapHeading[] { 23 if (!html) return []; 24 25 const headings: MinimapHeading[] = []; 26 // Match h1-h6 tags with optional id attribute 27 const regex = /<h([1-6])(?:\s[^>]*?(?:id="([^"]*)")?[^>]*)?>([\s\S]*?)<\/h\1>/gi; 28 let match; 29 30 while ((match = regex.exec(html)) !== null) { 31 const level = parseInt(match[1], 10); 32 const id = match[2] || ''; 33 // Strip HTML tags from heading text 34 const text = match[3].replace(/<[^>]+>/g, '').trim(); 35 if (text) { 36 headings.push({ level, text, id }); 37 } 38 } 39 40 return headings; 41} 42 43/** 44 * Compute the viewport indicator position and size as percentages. 45 */ 46export function computeViewportIndicator( 47 scrollTop: number, 48 viewportHeight: number, 49 totalHeight: number, 50): ViewportIndicator { 51 if (totalHeight <= 0) { 52 return { top: 0, height: 100 }; 53 } 54 55 const top = Math.max(0, (scrollTop / totalHeight) * 100); 56 let height = Math.max(5, (viewportHeight / totalHeight) * 100); 57 58 // Clamp so it doesn't overflow 59 if (top + height > 100) { 60 height = 100 - top; 61 } 62 63 return { top, height }; 64}