(xml: string)
| 340 | } |
| 341 | |
| 342 | function parsePptxPresentation(xml: string): { |
| 343 | slideCount: number |
| 344 | aspectRatio: '16:9' | '4:3' | 'custom' |
| 345 | } { |
| 346 | // Count sldId elements inside sldIdLst |
| 347 | const sldIdLst = between(xml, '<p:sldIdLst>', '</p:sldIdLst>') |
| 348 | const slideCount = (sldIdLst.match(/<p:sldId\b/g) ?? []).length |
| 349 | |
| 350 | // Slide size in EMU — 1 inch = 914400 EMU. Capture cx/cy independently so |
| 351 | // attribute order (LibreOffice/Google Slides may write cy before cx) doesn't matter. |
| 352 | const cxMatch = /<p:sldSz\b[^>]*\bcx="(\d+)"/.exec(xml) |
| 353 | const cyMatch = /<p:sldSz\b[^>]*\bcy="(\d+)"/.exec(xml) |
| 354 | let aspectRatio: '16:9' | '4:3' | 'custom' = 'custom' |
| 355 | if (cxMatch && cyMatch) { |
| 356 | const cx = Number.parseInt(cxMatch[1]) |
| 357 | const cy = Number.parseInt(cyMatch[1]) |
| 358 | const ratio = cx / cy |
| 359 | if (Math.abs(ratio - 16 / 9) < 0.01) aspectRatio = '16:9' |
| 360 | else if (Math.abs(ratio - 4 / 3) < 0.01) aspectRatio = '4:3' |
| 361 | } |
| 362 | |
| 363 | return { slideCount, aspectRatio } |
| 364 | } |
| 365 | |
| 366 | function parseSlideMasterBackground(xml: string): string | undefined { |
| 367 | // Look for a solid fill color in the slide master background |
no test coverage detected