diff --git a/lib/exporter/extras.overrides.test.ts b/lib/exporter/extras.overrides.test.ts new file mode 100644 index 0000000..e1c6bbd --- /dev/null +++ b/lib/exporter/extras.overrides.test.ts @@ -0,0 +1,47 @@ +import { describe, it, expect } from 'vitest' +import { pageSchema, type Page } from '@/lib/schema/page' +import { buildExtrasForPage } from '@/lib/exporter/extras' + +function makePage(): Page { + return pageSchema.parse({ + title: 'Overrides Demo', + locale: 'en', + theme: { primaryColor: '#123456', fontFamily: 'Inter' }, + sections: [ + { type: 'hero', props: { heading: 'Hello', subheading: 'World', imageUrl: 'https://img.example/hero.png' } }, + ], + form: { actionUrl: '', fields: [], spamProtection: { honeypotFieldName: '_hp', minSubmitSeconds: 2 } }, + seo: { title: 'Overrides', description: 'Desc' }, + }) +} + +describe('extras overrides', () => { + it('allows overriding robots.txt content', () => { + const page = makePage() + const extras = buildExtrasForPage(page, { + robotsText: 'User-agent: *\nDisallow: /private', + }) + const robots = new TextDecoder().decode(extras['robots.txt']) + expect(robots).toContain('Disallow: /private') + }) + + it('allows overriding manifest fields (name, short_name, start_url, display, theme_color)', () => { + const page = makePage() + const extras = buildExtrasForPage(page, { + manifest: { + name: 'Custom Name', + short_name: 'Custom', + start_url: '/home', + display: 'minimal-ui', + theme_color: '#abcdef', + }, + }) + const manifestRaw = new TextDecoder().decode(extras['site.webmanifest']) + const manifest = JSON.parse(manifestRaw) + expect(manifest.name).toBe('Custom Name') + expect(manifest.short_name).toBe('Custom') + expect(manifest.start_url).toBe('/home') + expect(manifest.display).toBe('minimal-ui') + expect(manifest.theme_color).toBe('#abcdef') + }) +}) diff --git a/lib/exporter/extras.ts b/lib/exporter/extras.ts index e112772..8b9fa4d 100644 --- a/lib/exporter/extras.ts +++ b/lib/exporter/extras.ts @@ -1,13 +1,25 @@ import type { Page } from '@/lib/schema/page' +type ExtrasOverrides = { + robotsText?: string + manifest?: Partial<{ + name: string + short_name: string + start_url: string + display: string + theme_color: string + }> +} + // Sheets 템플릿 등 ZIP 루트/서브 경로에 포함할 추가 파일(extras)을 구성한다. // - actionUrl이 비어있을 때만 Google Apps Script 템플릿을 포함한다. -export function buildExtrasForPage(page: Page): Record { +export function buildExtrasForPage(page: Page, overrides?: ExtrasOverrides): Record { const extras: Record = {} const te = new TextEncoder() // Always provide a baseline robots.txt - const robots = `User-agent: *\nDisallow:` + const robotsDefault = `User-agent: *\nDisallow:` + const robots = overrides?.robotsText ?? robotsDefault extras['robots.txt'] = te.encode(robots) // Provide a minimal site.webmanifest derived from Page @@ -20,6 +32,13 @@ export function buildExtrasForPage(page: Page): Record { start_url: '/', display: 'standalone', theme_color: page.theme?.primaryColor ?? '#000000', + ...((overrides?.manifest as object) || {}), + } as { + name: string + short_name: string + start_url: string + display: string + theme_color: string } extras['site.webmanifest'] = te.encode(JSON.stringify(manifest)) } catch {}