From 2d9e83d58a5ca049e54e114d02bb5b4d4867492c Mon Sep 17 00:00:00 2001 From: Danila Poyarkov Date: Fri, 25 Sep 2026 15:42:42 +0400 Subject: [PATCH] refactor(export): derive export format lists from the IO registry (#755) The Export panel, SDK helpers, app menus, and CLI each kept their own hand-written format lists, so new formats such as PPTX reached some surfaces and not others. Scene Graph now owns the persisted export-setting format ids, Core IO adapters carry literal ids so that list is checked against real adapters, and the panel labels, scale handling, app format types, and CLI format validation/help are derived from the registry. PPTX joins the Export panel as a result. --- CHANGELOG.md | 4 +++ packages/cli/src/commands/export.ts | 25 +++++++++++-------- packages/core/src/io/formats.ts | 22 ++++++++-------- packages/core/src/io/index.ts | 1 + packages/core/src/io/registry.ts | 4 +-- packages/core/src/io/types.ts | 4 +-- .../sdk/api/composables/use-export.md | 2 +- .../sdk/api/composables/use-export.md | 2 +- .../sdk/api/composables/use-export.md | 5 ++-- .../sdk/api/composables/use-export.md | 2 +- packages/fig/src/node-change/plugin-data.ts | 7 +----- packages/scene-graph/src/export-format.ts | 12 +++++++++ packages/scene-graph/src/index.ts | 1 + packages/scene-graph/src/types.ts | 3 +-- packages/vue/src/document/export/helpers.ts | 23 ++++++++++++++--- packages/vue/src/document/export/use.ts | 4 ++- packages/vue/src/index.ts | 2 +- src/app/document/export/create.ts | 11 +++----- src/app/document/export/files.ts | 16 +++++------- src/app/shell/menu/app-menu.ts | 3 ++- src/components/properties/ExportSection.vue | 14 +++-------- tests/e2e/export/basic.spec.ts | 12 ++++++++- tests/engine/io/export-formats.test.ts | 19 ++++++++++++++ .../io/fig/roundtrip/export-settings.test.ts | 3 ++- 24 files changed, 127 insertions(+), 74 deletions(-) create mode 100644 packages/scene-graph/src/export-format.ts create mode 100644 tests/engine/io/export-formats.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 61d4f28a7..f6f741047 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ - The desktop app now requires macOS 13 or later; the web app supports Chrome 111, Edge 111, Firefox 128, and Safari 16.4 or later. +### Added + +- Choose PPTX in the Export panel's format list, alongside PNG, JPG, WEBP, SVG, and PDF. + ### Fixed - Show what to update instead of a blank window when the browser or system WebView is too old, naming the detected macOS, Safari, Chrome, Edge, Firefox, WebKitGTK, or WebView2 version and linking a prefilled bug report, and explain a failed start the same way (#744). diff --git a/packages/cli/src/commands/export.ts b/packages/cli/src/commands/export.ts index b87edf015..41d494ad0 100644 --- a/packages/cli/src/commands/export.ts +++ b/packages/cli/src/commands/export.ts @@ -5,7 +5,6 @@ import { defineCommand } from 'citty' import { decodeBase64 } from '@open-pencil/core/bytes' import { BUILTIN_IO_FORMATS, IORegistry } from '@open-pencil/core/io' -import type { RasterExportFormat } from '@open-pencil/core/io' import { exportHTMLBundle, sceneGraphToDesignDocument, @@ -19,8 +18,14 @@ import { ok, printError } from '#cli/format' import { loadDocument, populateDocumentPage, populateWholeDocument } from '#cli/headless' const io = new IORegistry(BUILTIN_IO_FORMATS) -const RASTER_FORMATS = ['PNG', 'JPG', 'WEBP'] -const ALL_FORMATS = new Set([...RASTER_FORMATS, 'SVG', 'PDF', 'PPTX', 'JSX', 'FIG', 'HTML']) +// HTML goes through the DOM/CSS bundle exporter; every other format is a Core IO adapter. +const FORMAT_IDS = [...io.listExportFormats('node').map((format) => format.id), 'html'] +const ALL_FORMATS = new Set(FORMAT_IDS.map((id) => id.toUpperCase())) +const FORMAT_LIST = `${FORMAT_IDS.slice(0, -1).join(', ')}, or ${FORMAT_IDS.at(-1)}` + +function formatSupportsScale(format: string): boolean { + return io.getFormat(format.toLowerCase())?.exportOptions?.scale ?? false +} const JSX_STYLES = new Set(['openpencil', 'tailwind']) const HTML_STYLES = new Set(['inline', 'tailwind']) const HTML_MODES = new Set(['fragment', 'standalone']) @@ -242,7 +247,7 @@ async function exportFromFile(format: string, args: ExportArgs) { options = { format: args.style } } else if (format === 'FIG') { options = { renderThumbnail: true } - } else if (format === 'PNG' || format === 'JPG' || format === 'WEBP') { + } else if (formatSupportsScale(format)) { options = { format, scale: Number(args.scale), @@ -256,7 +261,7 @@ async function exportFromFile(format: string, args: ExportArgs) { exportFileName( defaultName, result.extension, - format === 'PNG' || format === 'JPG' || format === 'WEBP' ? Number(args.scale) : undefined + formatSupportsScale(format) ? Number(args.scale) : undefined ) ) await writeAndLog(output, result.data as string | Uint8Array) @@ -264,7 +269,7 @@ async function exportFromFile(format: string, args: ExportArgs) { } export default defineCommand({ - meta: { description: 'Export a document to PNG, JPG, WEBP, SVG, PDF, PPTX, JSX, HTML, or .fig' }, + meta: { description: `Export a document to ${FORMAT_LIST}` }, args: { file: { type: 'positional', @@ -280,7 +285,7 @@ export default defineCommand({ format: { type: 'string', alias: 'f', - description: 'Export format: png, jpg, webp, svg, pdf, pptx, jsx, html, fig (default: png)', + description: `Export format: ${FORMAT_IDS.join(', ')} (default: png)`, default: 'png' }, scale: { type: 'string', alias: 's', description: 'Export scale (default: 1)', default: '1' }, @@ -336,11 +341,9 @@ export default defineCommand({ ...appTargetOptions }, async run({ args }) { - const format = args.format.toUpperCase() as RasterExportFormat | 'SVG' | 'JSX' | 'FIG' | 'HTML' + const format = args.format.toUpperCase() if (!ALL_FORMATS.has(format)) { - printError( - `Invalid format "${args.format}". Use png, jpg, webp, svg, pdf, pptx, jsx, html, or fig.` - ) + printError(`Invalid format "${args.format}". Use ${FORMAT_LIST}.`) process.exit(1) } diff --git a/packages/core/src/io/formats.ts b/packages/core/src/io/formats.ts index dccb3b2bd..223adfa6e 100644 --- a/packages/core/src/io/formats.ts +++ b/packages/core/src/io/formats.ts @@ -93,8 +93,8 @@ async function renderRaster( }) } -function rasterFormat(format: RasterExportFormat): IOFormatAdapter { - const extension = format === 'JPG' ? 'jpg' : format.toLowerCase() +function rasterFormat(format: F): IOFormatAdapter> { + const extension = format.toLowerCase() as Lowercase let mimeType = 'image/png' if (format === 'JPG') mimeType = 'image/jpeg' else if (format === 'WEBP') mimeType = 'image/webp' @@ -138,7 +138,7 @@ function rasterFormat(format: RasterExportFormat): IOFormatAdapter { } } -export const figFormat: IOFormatAdapter = { +export const figFormat: IOFormatAdapter<'fig'> = { id: 'fig', label: 'OpenPencil Document', role: 'native-document', @@ -198,7 +198,7 @@ export const figFormat: IOFormatAdapter = { } } -export const penFormat: IOFormatAdapter = { +export const penFormat: IOFormatAdapter<'pen'> = { id: 'pen', label: 'Pencil Document', role: 'interchange-document', @@ -222,7 +222,7 @@ export const pngFormat = rasterFormat('PNG') export const jpgFormat = rasterFormat('JPG') export const webpFormat = rasterFormat('WEBP') -export const svgFormat: IOFormatAdapter = { +export const svgFormat: IOFormatAdapter<'svg'> = { id: 'svg', label: 'SVG', role: 'derived-export', @@ -255,7 +255,7 @@ export const svgFormat: IOFormatAdapter = { } } -export const pdfFormat: IOFormatAdapter = { +export const pdfFormat: IOFormatAdapter<'pdf'> = { id: 'pdf', label: 'PDF', role: 'derived-export', @@ -300,7 +300,7 @@ function resolvePPTXExportNodes( return { pageId: pages[0].id, nodeIds: pages.flatMap((page) => page.childIds) } } -export const pptxFormat: IOFormatAdapter = { +export const pptxFormat: IOFormatAdapter<'pptx'> = { id: 'pptx', label: 'PowerPoint', role: 'derived-export', @@ -335,7 +335,7 @@ export const pptxFormat: IOFormatAdapter = { } } -export const jsxFormat: IOFormatAdapter = { +export const jsxFormat: IOFormatAdapter<'jsx'> = { id: 'jsx', label: 'JSX', role: 'derived-export', @@ -370,7 +370,7 @@ export const jsxFormat: IOFormatAdapter = { } } -export const BUILTIN_IO_FORMATS: IOFormatAdapter[] = [ +export const BUILTIN_IO_FORMATS = [ figFormat, penFormat, pngFormat, @@ -380,4 +380,6 @@ export const BUILTIN_IO_FORMATS: IOFormatAdapter[] = [ pdfFormat, pptxFormat, jsxFormat -] +] as const satisfies readonly IOFormatAdapter[] + +export type BuiltinIOFormatId = (typeof BUILTIN_IO_FORMATS)[number]['id'] diff --git a/packages/core/src/io/index.ts b/packages/core/src/io/index.ts index 38e15bdc0..c43df14d2 100644 --- a/packages/core/src/io/index.ts +++ b/packages/core/src/io/index.ts @@ -2,6 +2,7 @@ export { IORegistry } from './registry' export { extractExportGraph } from './subgraph' export { BUILTIN_IO_FORMATS, + type BuiltinIOFormatId, figFormat, penFormat, pngFormat, diff --git a/packages/core/src/io/registry.ts b/packages/core/src/io/registry.ts index 2c1135cd2..d4a3b9ac5 100644 --- a/packages/core/src/io/registry.ts +++ b/packages/core/src/io/registry.ts @@ -3,9 +3,9 @@ import type { SceneGraph } from '@open-pencil/scene-graph' import type { ExportRequest, IOContext, IOFormatAdapter, ReadDocumentInput } from './types' export class IORegistry { - constructor(private readonly adapters: IOFormatAdapter[]) {} + constructor(private readonly adapters: readonly IOFormatAdapter[]) {} - listFormats(): IOFormatAdapter[] { + listFormats(): readonly IOFormatAdapter[] { return this.adapters } diff --git a/packages/core/src/io/types.ts b/packages/core/src/io/types.ts index 38934a493..8192c8dcd 100644 --- a/packages/core/src/io/types.ts +++ b/packages/core/src/io/types.ts @@ -109,8 +109,8 @@ export interface IOFormatExportOptions { colorSpace?: boolean } -export interface IOFormatAdapter { - id: string +export interface IOFormatAdapter { + id: Id label: string role: IOFormatRole category: IOFormatCategory diff --git a/packages/docs/de/programmable/sdk/api/composables/use-export.md b/packages/docs/de/programmable/sdk/api/composables/use-export.md index 8d47a1c83..724cfe56a 100644 --- a/packages/docs/de/programmable/sdk/api/composables/use-export.md +++ b/packages/docs/de/programmable/sdk/api/composables/use-export.md @@ -44,7 +44,7 @@ exportState.addSetting() ```ts exportState.updateScale(0, 2) -exportState.updateFormat(0, 'WEBP') +exportState.updateFormat(0, 'webp') ``` ## Siehe auch diff --git a/packages/docs/pl/programmable/sdk/api/composables/use-export.md b/packages/docs/pl/programmable/sdk/api/composables/use-export.md index 60beb34e2..50a7b1a05 100644 --- a/packages/docs/pl/programmable/sdk/api/composables/use-export.md +++ b/packages/docs/pl/programmable/sdk/api/composables/use-export.md @@ -44,7 +44,7 @@ exportState.addSetting() ```ts exportState.updateScale(0, 2) -exportState.updateFormat(0, 'WEBP') +exportState.updateFormat(0, 'webp') ``` ## Zobacz też diff --git a/packages/docs/programmable/sdk/api/composables/use-export.md b/packages/docs/programmable/sdk/api/composables/use-export.md index 71ded50d5..16908f215 100644 --- a/packages/docs/programmable/sdk/api/composables/use-export.md +++ b/packages/docs/programmable/sdk/api/composables/use-export.md @@ -12,7 +12,7 @@ It manages: - export settings rows - selected node ids - export name labeling -- supported scales and formats +- supported scales and formats (`formats` ids and labeled `formatOptions`) ## Usage @@ -30,6 +30,7 @@ const { nodeName, scales, formats, + formatOptions, addSetting, updateScale, updateFormat, @@ -48,7 +49,7 @@ exportState.addSetting() ```ts exportState.updateScale(0, 2) -exportState.updateFormat(0, 'WEBP') +exportState.updateFormat(0, 'webp') ``` ## Related APIs diff --git a/packages/docs/ru/programmable/sdk/api/composables/use-export.md b/packages/docs/ru/programmable/sdk/api/composables/use-export.md index 386f94906..e2e6dd241 100644 --- a/packages/docs/ru/programmable/sdk/api/composables/use-export.md +++ b/packages/docs/ru/programmable/sdk/api/composables/use-export.md @@ -48,7 +48,7 @@ exportState.addSetting() ```ts exportState.updateScale(0, 2) -exportState.updateFormat(0, 'WEBP') +exportState.updateFormat(0, 'webp') ``` ## Связанные API diff --git a/packages/fig/src/node-change/plugin-data.ts b/packages/fig/src/node-change/plugin-data.ts index 7457a2f67..d787df47e 100644 --- a/packages/fig/src/node-change/plugin-data.ts +++ b/packages/fig/src/node-change/plugin-data.ts @@ -2,6 +2,7 @@ import type { NodeChange, PluginData, PluginRelaunchData } from '@open-pencil/ki import { guidToString } from '@open-pencil/kiwi/fig/guid' import { clampExportScale, + isExportFormatId, type ExportFormatId, type ExportSetting, type PluginDataEntry, @@ -135,12 +136,6 @@ export function extractBoundVariables(nc: NodeChange): Record { return bindings } -function isExportFormatId(value: unknown): value is ExportFormatId { - return ( - value === 'png' || value === 'jpg' || value === 'webp' || value === 'svg' || value === 'pdf' - ) -} - function parseExportSettingsPluginValue(value: string | null): ExportSetting[] | null { if (!value) return null try { diff --git a/packages/scene-graph/src/export-format.ts b/packages/scene-graph/src/export-format.ts new file mode 100644 index 000000000..44282b85a --- /dev/null +++ b/packages/scene-graph/src/export-format.ts @@ -0,0 +1,12 @@ +/** + * Formats a node's export settings may persist. Each id must name a Core IO + * export adapter that supports node export; labels and options come from that + * adapter, so this list only decides what the Export panel offers. + */ +export const EXPORT_FORMAT_IDS = ['png', 'jpg', 'webp', 'svg', 'pdf', 'pptx'] as const + +export type ExportFormatId = (typeof EXPORT_FORMAT_IDS)[number] + +export function isExportFormatId(value: unknown): value is ExportFormatId { + return EXPORT_FORMAT_IDS.some((id) => id === value) +} diff --git a/packages/scene-graph/src/index.ts b/packages/scene-graph/src/index.ts index d5fe00ab2..6aee0c87f 100644 --- a/packages/scene-graph/src/index.ts +++ b/packages/scene-graph/src/index.ts @@ -21,6 +21,7 @@ export { type InstanceOverrideState } from './instance-overrides' export * from './snap' +export * from './export-format' export * from './export-scale' export * from './coordinate' export * from './constants' diff --git a/packages/scene-graph/src/types.ts b/packages/scene-graph/src/types.ts index f898928d9..f355bdc65 100644 --- a/packages/scene-graph/src/types.ts +++ b/packages/scene-graph/src/types.ts @@ -1,5 +1,6 @@ /* eslint-disable max-lines -- scene node contracts are kept together as the public graph type surface */ +import type { ExportFormatId } from './export-format' import type { CanvasGuide } from './guides' import type { InstanceOverrideState } from './instance-overrides' import type { Color, Matrix, Rect, Vector } from './primitives' @@ -305,8 +306,6 @@ export interface PluginDataEntry { value: string } -export type ExportFormatId = 'png' | 'jpg' | 'webp' | 'svg' | 'pdf' - export interface ExportSetting { scale: number format: ExportFormatId diff --git a/packages/vue/src/document/export/helpers.ts b/packages/vue/src/document/export/helpers.ts index 78477ede8..74241a6bc 100644 --- a/packages/vue/src/document/export/helpers.ts +++ b/packages/vue/src/document/export/helpers.ts @@ -2,14 +2,25 @@ import { computed } from 'vue' import type { ComputedRef } from 'vue' import type { Editor } from '@open-pencil/core/editor' -import { BUILTIN_IO_FORMATS, IORegistry } from '@open-pencil/core/io' -import { MAX_EXPORT_SCALE, MIN_EXPORT_SCALE, clampExportScale } from '@open-pencil/scene-graph' +import { BUILTIN_IO_FORMATS, IORegistry, type BuiltinIOFormatId } from '@open-pencil/core/io' +import { + EXPORT_FORMAT_IDS, + MAX_EXPORT_SCALE, + MIN_EXPORT_SCALE, + clampExportScale +} from '@open-pencil/scene-graph' import type { ExportFormatId, ExportSetting, PluginDataEntry } from '@open-pencil/scene-graph' import { useSceneComputed } from '#vue/internal/scene-computed/use' export const EXPORT_SCALES = [0.5, 0.75, 1, 1.5, 2, 3, 4] as const -export const EXPORT_FORMATS: ExportFormatId[] = ['png', 'jpg', 'webp', 'svg', 'pdf'] +// Persisted export-setting formats must name built-in IO adapters. +export const EXPORT_FORMATS = EXPORT_FORMAT_IDS satisfies readonly BuiltinIOFormatId[] + +export interface ExportFormatOption { + value: ExportFormatId + label: string +} export type ExportPanelTarget = 'selection' | 'page' @@ -22,6 +33,12 @@ export { MIN_EXPORT_SCALE, MAX_EXPORT_SCALE, clampExportScale } const io = new IORegistry(BUILTIN_IO_FORMATS) +/** Short, extension-style labels for the node export formats (PNG, PDF, PPTX, …). */ +export const EXPORT_FORMAT_OPTIONS: ExportFormatOption[] = EXPORT_FORMATS.map((id) => ({ + value: id, + label: (io.getFormat(id)?.extensions[0] ?? id).toUpperCase() +})) + export function createDefaultExportSetting(): ExportSetting { return { scale: 1, format: 'png' } } diff --git a/packages/vue/src/document/export/use.ts b/packages/vue/src/document/export/use.ts index 5f8d1d497..dd722f22f 100644 --- a/packages/vue/src/document/export/use.ts +++ b/packages/vue/src/document/export/use.ts @@ -1,5 +1,6 @@ import { EXPORT_FORMATS, + EXPORT_FORMAT_OPTIONS, EXPORT_SCALES, MAX_EXPORT_SCALE, MIN_EXPORT_SCALE, @@ -12,7 +13,7 @@ import { useEditor } from '#vue/editor/context' import { useSceneComputed } from '#vue/internal/scene-computed/use' export type { ExportFormatId, ExportSetting } from '@open-pencil/scene-graph' -export type { ExportPanelTarget } from '#vue/document/export/helpers' +export type { ExportFormatOption, ExportPanelTarget } from '#vue/document/export/helpers' export function useExport() { const editor = useEditor() @@ -30,6 +31,7 @@ export function useExport() { minScale: MIN_EXPORT_SCALE, clampExportScale, formats: EXPORT_FORMATS, + formatOptions: EXPORT_FORMAT_OPTIONS, formatSupportsScale, ...targetState, ...settingActions diff --git a/packages/vue/src/index.ts b/packages/vue/src/index.ts index 9f56d9a84..663ad608e 100644 --- a/packages/vue/src/index.ts +++ b/packages/vue/src/index.ts @@ -107,7 +107,7 @@ export type { UseDocumentWorkspaceOptions } from '#vue/document/workspace/use' export { useExport } from '#vue/document/export/use' -export type { ExportFormatId, ExportSetting } from '#vue/document/export/use' +export type { ExportFormatId, ExportFormatOption, ExportSetting } from '#vue/document/export/use' export { useFillControls } from '#vue/controls/fill/use' export { useColorVariableBinding } from '#vue/controls/color-variable-binding/use' export { useNumberVariableBinding } from '#vue/controls/number-variable-binding/use' diff --git a/src/app/document/export/create.ts b/src/app/document/export/create.ts index ca7e4a7b6..bad1146e5 100644 --- a/src/app/document/export/create.ts +++ b/src/app/document/export/create.ts @@ -1,5 +1,5 @@ import type { Editor, EditorState } from '@open-pencil/core/editor' -import type { ExportRequest, IORegistry } from '@open-pencil/core/io' +import type { BuiltinIOFormatId, ExportRequest, IORegistry } from '@open-pencil/core/io' import { bundleExportFiles, @@ -38,7 +38,7 @@ export function createDocumentExportActions( const format = io.getFormat(formatId) if (!format) throw new Error(`Unknown export format: ${formatId}`) - const exportOptions = getExportOptions(formatId, options) + const exportOptions = getExportOptions(format, options) const result = await io.exportContent( formatId, @@ -50,7 +50,7 @@ export function createDocumentExportActions( const baseName = getExportBaseName(editor.graph, target) return { bytes: getExportBytes(result.data), - fileName: getExportFileName(baseName, formatId, result.extension, options), + fileName: getExportFileName(baseName, format, result.extension, options), format: format.label, ext: `.${result.extension}`, mime: result.mimeType @@ -103,10 +103,7 @@ export function createDocumentExportActions( ) } - async function exportSelection( - scale: number, - formatId: 'png' | 'jpg' | 'webp' | 'svg' | 'pdf' | 'pptx' | 'fig' - ) { + async function exportSelection(scale: number, formatId: BuiltinIOFormatId) { await exportTarget(getSelectionExportTarget(), formatId, { scale }) } diff --git a/src/app/document/export/files.ts b/src/app/document/export/files.ts index 738e004ee..4272cd806 100644 --- a/src/app/document/export/files.ts +++ b/src/app/document/export/files.ts @@ -74,25 +74,21 @@ export function getExportBaseName(graph: SceneGraph, target: ExportRequest['targ return 'Export' } -export function getExportOptions(formatId: string, options?: ExportOptions): unknown { - if (formatId === 'png' || formatId === 'jpg' || formatId === 'webp') { - return { - format: formatId.toUpperCase(), - scale: options?.scale ?? 1, - quality: options?.quality - } +export function getExportOptions(format: IOFormatAdapter, options?: ExportOptions): unknown { + if (format.exportOptions?.scale) { + return { scale: options?.scale ?? 1, quality: options?.quality } } - if (formatId === 'jsx') return { format: options?.jsxFormat ?? 'openpencil' } + if (format.id === 'jsx') return { format: options?.jsxFormat ?? 'openpencil' } return undefined } export function getExportFileName( baseName: string, - formatId: string, + format: IOFormatAdapter, extension: string, options?: ExportOptions ): string { - return formatId === 'png' || formatId === 'jpg' || formatId === 'webp' + return format.exportOptions?.scale ? `${baseName}@${options?.scale ?? 1}x.${extension}` : `${baseName}.${extension}` } diff --git a/src/app/shell/menu/app-menu.ts b/src/app/shell/menu/app-menu.ts index 632403a8b..0d58f292d 100644 --- a/src/app/shell/menu/app-menu.ts +++ b/src/app/shell/menu/app-menu.ts @@ -15,6 +15,7 @@ import IconUndo from '~icons/lucide/undo-2' import IconZoomIn from '~icons/lucide/zoom-in' import IconZoomOut from '~icons/lucide/zoom-out' +import type { BuiltinIOFormatId } from '@open-pencil/core/io' import type { CommandPaletteGroup, CommandPaletteItem, MenuEntry } from '@open-pencil/vue' import { shortcutPlatform, useEditorCommands, useI18n } from '@open-pencil/vue' @@ -143,7 +144,7 @@ export function useAppMenu() { })) ) - function exportSelection(format: 'png' | 'svg' | 'pptx' | 'fig') { + function exportSelection(format: BuiltinIOFormatId) { if (store.state.selectedIds.size > 0) void store.exportSelection(1, format) } diff --git a/src/components/properties/ExportSection.vue b/src/components/properties/ExportSection.vue index f96fca71a..ade4626ff 100644 --- a/src/components/properties/ExportSection.vue +++ b/src/components/properties/ExportSection.vue @@ -3,7 +3,6 @@ import { tryOnScopeDispose, useObjectUrl } from '@vueuse/core' import { computed, onActivated, onDeactivated, ref, shallowRef, watch } from 'vue' import { useExport, useI18n, useRetainedActivity } from '@open-pencil/vue' -import type { ExportFormatId } from '@open-pencil/vue' import { useEditorStore } from '@/app/editor/active-store' import ExportScaleInput from '@/components/properties/ExportScaleInput.vue' @@ -28,18 +27,11 @@ const { updateScale, updateFormat, formatSupportsScale, + formatOptions, scales, clampExportScale } = useExport() -const FORMAT_OPTIONS: { value: ExportFormatId; label: string }[] = [ - { value: 'png', label: 'PNG' }, - { value: 'jpg', label: 'JPG' }, - { value: 'webp', label: 'WEBP' }, - { value: 'svg', label: 'SVG' }, - { value: 'pdf', label: 'PDF' } -] - const previewBlob = shallowRef(null) const previewURL = useObjectUrl(previewBlob) const showPreview = ref(false) @@ -155,11 +147,11 @@ watch(previewKey, updatePreview, { flush: 'post' })