MCPcopy Index your code
hub / github.com/simstudioai/sim / extractDocumentStyle

Function extractDocumentStyle

apps/sim/lib/copilot/vfs/document-style.ts:384–447  ·  view source on GitHub ↗
(
  buffer: Buffer,
  ext: 'docx' | 'pptx' | 'pdf'
)

Source from the content-addressed store, hash-verified

382 * Returns null if the buffer cannot be parsed or yields no useful data.
383 */
384export async function extractDocumentStyle(
385 buffer: Buffer,
386 ext: 'docx' | 'pptx' | 'pdf'
387): Promise<DocumentStyleSummary | null> {
388 if (ext === 'pdf') {
389 return extractPdfStyle(buffer)
390 }
391
392 if (buffer.length < 4) return null
393 for (let i = 0; i < 4; i++) {
394 if (buffer[i] !== ZIP_MAGIC[i]) return null
395 }
396
397 try {
398 const JSZip = (await import('jszip')).default
399 const zip = await JSZip.loadAsync(buffer)
400
401 const themePath = ext === 'docx' ? 'word/theme/theme1.xml' : 'ppt/theme/theme1.xml'
402 const themeFile = zip.file(themePath)
403
404 let theme: DocumentStyleSummary['theme']
405 if (themeFile) {
406 theme = parseThemeXml(await themeFile.async('string'))
407 } else if (ext === 'pptx') {
408 // PPTX without a theme is malformed — nothing useful to return
409 return null
410 }
411 // DOCX without a theme is valid (e.g. LibreOffice-generated); continue with styles only
412
413 const summary: DocumentStyleSummary = { format: ext, ...(theme && { theme }) }
414
415 if (ext === 'docx') {
416 const stylesFile = zip.file('word/styles.xml')
417 if (stylesFile) {
418 const { styles, defaults } = parseDocxStyles(await stylesFile.async('string'), theme?.fonts)
419 if (styles.length > 0) summary.styles = styles
420 if (defaults) summary.defaults = defaults
421 }
422 // If there's neither a theme nor any styles, there's nothing useful to return
423 if (!theme && !summary.styles?.length) return null
424 }
425
426 if (ext === 'pptx') {
427 const presFile = zip.file('ppt/presentation.xml')
428 if (presFile) {
429 const { slideCount, aspectRatio } = parsePptxPresentation(await presFile.async('string'))
430 if (slideCount > 0) summary.slideCount = slideCount
431 summary.aspectRatio = aspectRatio
432 }
433 const masterFile =
434 zip.file('ppt/slideMasters/slideMaster1.xml') ??
435 zip.file('ppt/slidemaster/slidemaster1.xml')
436 if (masterFile) {
437 const bg = parseSlideMasterBackground(await masterFile.async('string'))
438 if (bg) summary.background = bg
439 }
440 }
441

Callers 2

readFileContentMethod · 0.90
route.tsFile · 0.90

Calls 7

toErrorFunction · 0.90
extractPdfStyleFunction · 0.85
parseThemeXmlFunction · 0.85
parseDocxStylesFunction · 0.85
parsePptxPresentationFunction · 0.85
warnMethod · 0.65

Tested by

no test coverage detected