Skip to content

Commit 0b607ab

Browse files
committed
chore(files): polish style extraction — type narrowing + empty-styles guard
Explicit 'docx' | 'pptx' type annotation after the extension guard in both route.ts and workspace-vfs.ts so TypeScript sees the narrowed type rather than string. Only set summary.styles when the parsed array is non-empty so the JSON response doesn't include "styles": []. Remove redundant inline WHAT-comments from parseColorSlot.
1 parent a0aa8ec commit 0b607ab

3 files changed

Lines changed: 10 additions & 8 deletions

File tree

apps/sim/app/api/workspaces/[id]/files/[fileId]/style/route.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,14 @@ export const GET = withRouteHandler(
3737
return NextResponse.json({ error: 'File not found' }, { status: 404 })
3838
}
3939

40-
const ext = fileRecord.name.split('.').pop()?.toLowerCase()
41-
if (ext !== 'docx' && ext !== 'pptx') {
40+
const rawExt = fileRecord.name.split('.').pop()?.toLowerCase()
41+
if (rawExt !== 'docx' && rawExt !== 'pptx') {
4242
return NextResponse.json(
4343
{ error: 'Style extraction only supports .docx and .pptx files' },
4444
{ status: 422 }
4545
)
4646
}
47+
const ext: 'docx' | 'pptx' = rawExt
4748

4849
let buffer: Buffer
4950
try {

apps/sim/lib/copilot/vfs/document-style.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ function between(xml: string, open: string, close: string): string {
5555
function parseColorSlot(xml: string, slot: string): string {
5656
const inner = between(xml, `<a:${slot}>`, `</a:${slot}>`)
5757
if (!inner) return ''
58+
// srgbClr uses val=; sysClr has val="windowText" but lastClr holds the fallback hex
5859
const srgb = attr(inner, 'val')
5960
if (srgb && inner.includes('<a:srgbClr')) return srgb.toUpperCase()
6061
const lastClr = attr(inner, 'lastClr')
@@ -138,7 +139,6 @@ export async function extractDocumentStyle(
138139
buffer: Buffer,
139140
ext: 'docx' | 'pptx'
140141
): Promise<DocumentStyleSummary | null> {
141-
// Verify ZIP magic bytes
142142
if (buffer.length < 4) return null
143143
for (let i = 0; i < 4; i++) {
144144
if (buffer[i] !== ZIP_MAGIC[i]) return null
@@ -152,14 +152,14 @@ export async function extractDocumentStyle(
152152
const themeFile = zip.file(themePath)
153153
if (!themeFile) return null
154154

155-
const themeXml = await themeFile.async('string')
156-
const theme = parseThemeXml(themeXml)
155+
const theme = parseThemeXml(await themeFile.async('string'))
157156
const summary: DocumentStyleSummary = { format: ext, theme }
158157

159158
if (ext === 'docx') {
160159
const stylesFile = zip.file('word/styles.xml')
161160
if (stylesFile) {
162-
summary.styles = parseDocxStyles(await stylesFile.async('string'))
161+
const styles = parseDocxStyles(await stylesFile.async('string'))
162+
if (styles && styles.length > 0) summary.styles = styles
163163
}
164164
}
165165

apps/sim/lib/copilot/vfs/workspace-vfs.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,9 @@ export class WorkspaceVFS {
462462
try {
463463
const record = await getWorkspaceFile(this._workspaceId, fileId)
464464
if (!record) return null
465-
const ext = record.name.split('.').pop()?.toLowerCase()
466-
if (ext !== 'docx' && ext !== 'pptx') return null
465+
const rawExt = record.name.split('.').pop()?.toLowerCase()
466+
if (rawExt !== 'docx' && rawExt !== 'pptx') return null
467+
const ext: 'docx' | 'pptx' = rawExt
467468
const buffer = await downloadWorkspaceFile(record)
468469
const summary = await extractDocumentStyle(buffer, ext)
469470
if (!summary) return null

0 commit comments

Comments
 (0)