From aaec5d5cc9a9f0a95e6c3423ad62929ada2b67ca Mon Sep 17 00:00:00 2001 From: spring-raining Date: Sun, 14 Dec 2025 23:19:39 +0900 Subject: [PATCH 1/3] chore: Separate the preview page --- .../viola/src/components/panes/preview.tsx | 3 +++ packages/viola/src/components/side-menu.tsx | 15 ++++++++++- packages/viola/src/routeTree.gen.ts | 27 +++++++++++++++++++ .../routes/(main)/_layout/edit/$contentId.tsx | 5 ---- .../src/routes/(main)/_layout/preview.tsx | 18 +++++++++++++ 5 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 packages/viola/src/routes/(main)/_layout/preview.tsx diff --git a/packages/viola/src/components/panes/preview.tsx b/packages/viola/src/components/panes/preview.tsx index 8a0b5b6..24b55ed 100644 --- a/packages/viola/src/components/panes/preview.tsx +++ b/packages/viola/src/components/panes/preview.tsx @@ -1,6 +1,7 @@ import { use } from 'react'; import { ref } from 'valtio'; +import { $project } from '../../stores/project'; import { $viewer } from '../../stores/viewer'; const iframeRef = (el: HTMLIFrameElement | null) => { @@ -8,6 +9,8 @@ const iframeRef = (el: HTMLIFrameElement | null) => { }; const PreviewIframe = () => { + use($project.setupPromise); + const url = use($viewer.setupServer()); return ( diff --git a/packages/viola/src/components/side-menu.tsx b/packages/viola/src/components/side-menu.tsx index 23e950d..850b4c7 100644 --- a/packages/viola/src/components/side-menu.tsx +++ b/packages/viola/src/components/side-menu.tsx @@ -32,7 +32,13 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from '@v/ui/dropdown'; -import { BookOpen, CirclePlus, MoreHorizontal, Palette } from '@v/ui/icon'; +import { + BookOpen, + CirclePlus, + MoreHorizontal, + Palette, + Printer, +} from '@v/ui/icon'; import { cn } from '@v/ui/lib/utils'; import { Sidebar, @@ -84,6 +90,13 @@ function ApplicationDropdownMenu({ children }: React.PropsWithChildren) { {children} + + + + Open Print Preview + + + Print PDF diff --git a/packages/viola/src/routeTree.gen.ts b/packages/viola/src/routeTree.gen.ts index b05aa47..aff1674 100644 --- a/packages/viola/src/routeTree.gen.ts +++ b/packages/viola/src/routeTree.gen.ts @@ -17,6 +17,7 @@ import { Route as mainLayoutImport } from './routes/(main)/_layout' import { Route as DebugAstViewerIndexImport } from './routes/debug/ast-viewer/index' import { Route as mainLayoutIndexImport } from './routes/(main)/_layout/index' import { Route as mainLayoutThemeImport } from './routes/(main)/_layout/theme' +import { Route as mainLayoutPreviewImport } from './routes/(main)/_layout/preview' import { Route as mainLayoutBibliographyImport } from './routes/(main)/_layout/bibliography' import { Route as mainLayoutEditContentIdImport } from './routes/(main)/_layout/edit/$contentId' @@ -54,6 +55,12 @@ const mainLayoutThemeRoute = mainLayoutThemeImport.update({ getParentRoute: () => mainLayoutRoute, } as any) +const mainLayoutPreviewRoute = mainLayoutPreviewImport.update({ + id: '/preview', + path: '/preview', + getParentRoute: () => mainLayoutRoute, +} as any) + const mainLayoutBibliographyRoute = mainLayoutBibliographyImport.update({ id: '/bibliography', path: '/bibliography', @@ -91,6 +98,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof mainLayoutBibliographyImport parentRoute: typeof mainLayoutImport } + '/(main)/_layout/preview': { + id: '/(main)/_layout/preview' + path: '/preview' + fullPath: '/preview' + preLoaderRoute: typeof mainLayoutPreviewImport + parentRoute: typeof mainLayoutImport + } '/(main)/_layout/theme': { id: '/(main)/_layout/theme' path: '/theme' @@ -126,6 +140,7 @@ declare module '@tanstack/react-router' { interface mainLayoutRouteChildren { mainLayoutBibliographyRoute: typeof mainLayoutBibliographyRoute + mainLayoutPreviewRoute: typeof mainLayoutPreviewRoute mainLayoutThemeRoute: typeof mainLayoutThemeRoute mainLayoutIndexRoute: typeof mainLayoutIndexRoute mainLayoutEditContentIdRoute: typeof mainLayoutEditContentIdRoute @@ -133,6 +148,7 @@ interface mainLayoutRouteChildren { const mainLayoutRouteChildren: mainLayoutRouteChildren = { mainLayoutBibliographyRoute: mainLayoutBibliographyRoute, + mainLayoutPreviewRoute: mainLayoutPreviewRoute, mainLayoutThemeRoute: mainLayoutThemeRoute, mainLayoutIndexRoute: mainLayoutIndexRoute, mainLayoutEditContentIdRoute: mainLayoutEditContentIdRoute, @@ -155,6 +171,7 @@ const mainRouteWithChildren = mainRoute._addFileChildren(mainRouteChildren) export interface FileRoutesByFullPath { '/': typeof mainLayoutIndexRoute '/bibliography': typeof mainLayoutBibliographyRoute + '/preview': typeof mainLayoutPreviewRoute '/theme': typeof mainLayoutThemeRoute '/debug/ast-viewer': typeof DebugAstViewerIndexRoute '/edit/$contentId': typeof mainLayoutEditContentIdRoute @@ -162,6 +179,7 @@ export interface FileRoutesByFullPath { export interface FileRoutesByTo { '/bibliography': typeof mainLayoutBibliographyRoute + '/preview': typeof mainLayoutPreviewRoute '/theme': typeof mainLayoutThemeRoute '/': typeof mainLayoutIndexRoute '/debug/ast-viewer': typeof DebugAstViewerIndexRoute @@ -173,6 +191,7 @@ export interface FileRoutesById { '/(main)': typeof mainRouteWithChildren '/(main)/_layout': typeof mainLayoutRouteWithChildren '/(main)/_layout/bibliography': typeof mainLayoutBibliographyRoute + '/(main)/_layout/preview': typeof mainLayoutPreviewRoute '/(main)/_layout/theme': typeof mainLayoutThemeRoute '/(main)/_layout/': typeof mainLayoutIndexRoute '/debug/ast-viewer/': typeof DebugAstViewerIndexRoute @@ -184,12 +203,14 @@ export interface FileRouteTypes { fullPaths: | '/' | '/bibliography' + | '/preview' | '/theme' | '/debug/ast-viewer' | '/edit/$contentId' fileRoutesByTo: FileRoutesByTo to: | '/bibliography' + | '/preview' | '/theme' | '/' | '/debug/ast-viewer' @@ -199,6 +220,7 @@ export interface FileRouteTypes { | '/(main)' | '/(main)/_layout' | '/(main)/_layout/bibliography' + | '/(main)/_layout/preview' | '/(main)/_layout/theme' | '/(main)/_layout/' | '/debug/ast-viewer/' @@ -241,6 +263,7 @@ export const routeTree = rootRoute "parent": "/(main)", "children": [ "/(main)/_layout/bibliography", + "/(main)/_layout/preview", "/(main)/_layout/theme", "/(main)/_layout/", "/(main)/_layout/edit/$contentId" @@ -250,6 +273,10 @@ export const routeTree = rootRoute "filePath": "(main)/_layout/bibliography.tsx", "parent": "/(main)/_layout" }, + "/(main)/_layout/preview": { + "filePath": "(main)/_layout/preview.tsx", + "parent": "/(main)/_layout" + }, "/(main)/_layout/theme": { "filePath": "(main)/_layout/theme.tsx", "parent": "/(main)/_layout" diff --git a/packages/viola/src/routes/(main)/_layout/edit/$contentId.tsx b/packages/viola/src/routes/(main)/_layout/edit/$contentId.tsx index 689361f..6e06465 100644 --- a/packages/viola/src/routes/(main)/_layout/edit/$contentId.tsx +++ b/packages/viola/src/routes/(main)/_layout/edit/$contentId.tsx @@ -25,11 +25,6 @@ export const Route = createFileRoute('/(main)/_layout/edit/$contentId')({ contentId: contentId, title: ref(() => <>Editor), }, - { - id: generateId(), - type: 'preview', - title: ref(() => <>Preview), - }, ]; }, }); diff --git a/packages/viola/src/routes/(main)/_layout/preview.tsx b/packages/viola/src/routes/(main)/_layout/preview.tsx new file mode 100644 index 0000000..891a0c2 --- /dev/null +++ b/packages/viola/src/routes/(main)/_layout/preview.tsx @@ -0,0 +1,18 @@ +import { createFileRoute } from '@tanstack/react-router'; +import { ref } from 'valtio'; + +import { generateId } from '../../../libs/generate-id'; +import { $ui } from '../../../stores/ui'; + +export const Route = createFileRoute('/(main)/_layout/preview')({ + component: () => null, + onEnter: () => { + $ui.tabs = [ + { + id: generateId(), + type: 'preview', + title: ref(() => <>Preview), + }, + ]; + }, +}); From ec717a6a145cf924abcceb3c98593a86a129bccb Mon Sep 17 00:00:00 2001 From: spring-raining Date: Mon, 15 Dec 2025 01:59:17 +0900 Subject: [PATCH 2/3] feat: Update edit URL to persist actual content path --- packages/viola/src/components/side-menu.tsx | 4 +- packages/viola/src/routeTree.gen.ts | 40 +++++++++--------- .../src/routes/(main)/_layout/edit/$.tsx | 33 +++++++++++++++ .../routes/(main)/_layout/edit/$contentId.tsx | 30 ------------- .../viola/src/stores/actions/content-file.ts | 14 ++++--- .../viola/src/stores/actions/setup-project.ts | 42 ++++++++++++------- packages/viola/src/stores/content.ts | 8 ++++ packages/viola/src/stores/sandbox.ts | 5 +++ 8 files changed, 102 insertions(+), 74 deletions(-) create mode 100644 packages/viola/src/routes/(main)/_layout/edit/$.tsx delete mode 100644 packages/viola/src/routes/(main)/_layout/edit/$contentId.tsx diff --git a/packages/viola/src/components/side-menu.tsx b/packages/viola/src/components/side-menu.tsx index 850b4c7..e83730a 100644 --- a/packages/viola/src/components/side-menu.tsx +++ b/packages/viola/src/components/side-menu.tsx @@ -247,8 +247,8 @@ function FileTreeItem({ variant={typeof item === 'string' ? 'default' : 'heading'} asChild > - {typeof item === 'string' ? ( - + {file ? ( + {file?.summary || 'Empty file'} diff --git a/packages/viola/src/routeTree.gen.ts b/packages/viola/src/routeTree.gen.ts index aff1674..7dfe769 100644 --- a/packages/viola/src/routeTree.gen.ts +++ b/packages/viola/src/routeTree.gen.ts @@ -19,7 +19,7 @@ import { Route as mainLayoutIndexImport } from './routes/(main)/_layout/index' import { Route as mainLayoutThemeImport } from './routes/(main)/_layout/theme' import { Route as mainLayoutPreviewImport } from './routes/(main)/_layout/preview' import { Route as mainLayoutBibliographyImport } from './routes/(main)/_layout/bibliography' -import { Route as mainLayoutEditContentIdImport } from './routes/(main)/_layout/edit/$contentId' +import { Route as mainLayoutEditSplatImport } from './routes/(main)/_layout/edit/$' // Create Virtual Routes @@ -67,9 +67,9 @@ const mainLayoutBibliographyRoute = mainLayoutBibliographyImport.update({ getParentRoute: () => mainLayoutRoute, } as any) -const mainLayoutEditContentIdRoute = mainLayoutEditContentIdImport.update({ - id: '/edit/$contentId', - path: '/edit/$contentId', +const mainLayoutEditSplatRoute = mainLayoutEditSplatImport.update({ + id: '/edit/$', + path: '/edit/$', getParentRoute: () => mainLayoutRoute, } as any) @@ -126,11 +126,11 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof DebugAstViewerIndexImport parentRoute: typeof rootRoute } - '/(main)/_layout/edit/$contentId': { - id: '/(main)/_layout/edit/$contentId' - path: '/edit/$contentId' - fullPath: '/edit/$contentId' - preLoaderRoute: typeof mainLayoutEditContentIdImport + '/(main)/_layout/edit/$': { + id: '/(main)/_layout/edit/$' + path: '/edit/$' + fullPath: '/edit/$' + preLoaderRoute: typeof mainLayoutEditSplatImport parentRoute: typeof mainLayoutImport } } @@ -143,7 +143,7 @@ interface mainLayoutRouteChildren { mainLayoutPreviewRoute: typeof mainLayoutPreviewRoute mainLayoutThemeRoute: typeof mainLayoutThemeRoute mainLayoutIndexRoute: typeof mainLayoutIndexRoute - mainLayoutEditContentIdRoute: typeof mainLayoutEditContentIdRoute + mainLayoutEditSplatRoute: typeof mainLayoutEditSplatRoute } const mainLayoutRouteChildren: mainLayoutRouteChildren = { @@ -151,7 +151,7 @@ const mainLayoutRouteChildren: mainLayoutRouteChildren = { mainLayoutPreviewRoute: mainLayoutPreviewRoute, mainLayoutThemeRoute: mainLayoutThemeRoute, mainLayoutIndexRoute: mainLayoutIndexRoute, - mainLayoutEditContentIdRoute: mainLayoutEditContentIdRoute, + mainLayoutEditSplatRoute: mainLayoutEditSplatRoute, } const mainLayoutRouteWithChildren = mainLayoutRoute._addFileChildren( @@ -174,7 +174,7 @@ export interface FileRoutesByFullPath { '/preview': typeof mainLayoutPreviewRoute '/theme': typeof mainLayoutThemeRoute '/debug/ast-viewer': typeof DebugAstViewerIndexRoute - '/edit/$contentId': typeof mainLayoutEditContentIdRoute + '/edit/$': typeof mainLayoutEditSplatRoute } export interface FileRoutesByTo { @@ -183,7 +183,7 @@ export interface FileRoutesByTo { '/theme': typeof mainLayoutThemeRoute '/': typeof mainLayoutIndexRoute '/debug/ast-viewer': typeof DebugAstViewerIndexRoute - '/edit/$contentId': typeof mainLayoutEditContentIdRoute + '/edit/$': typeof mainLayoutEditSplatRoute } export interface FileRoutesById { @@ -195,7 +195,7 @@ export interface FileRoutesById { '/(main)/_layout/theme': typeof mainLayoutThemeRoute '/(main)/_layout/': typeof mainLayoutIndexRoute '/debug/ast-viewer/': typeof DebugAstViewerIndexRoute - '/(main)/_layout/edit/$contentId': typeof mainLayoutEditContentIdRoute + '/(main)/_layout/edit/$': typeof mainLayoutEditSplatRoute } export interface FileRouteTypes { @@ -206,7 +206,7 @@ export interface FileRouteTypes { | '/preview' | '/theme' | '/debug/ast-viewer' - | '/edit/$contentId' + | '/edit/$' fileRoutesByTo: FileRoutesByTo to: | '/bibliography' @@ -214,7 +214,7 @@ export interface FileRouteTypes { | '/theme' | '/' | '/debug/ast-viewer' - | '/edit/$contentId' + | '/edit/$' id: | '__root__' | '/(main)' @@ -224,7 +224,7 @@ export interface FileRouteTypes { | '/(main)/_layout/theme' | '/(main)/_layout/' | '/debug/ast-viewer/' - | '/(main)/_layout/edit/$contentId' + | '/(main)/_layout/edit/$' fileRoutesById: FileRoutesById } @@ -266,7 +266,7 @@ export const routeTree = rootRoute "/(main)/_layout/preview", "/(main)/_layout/theme", "/(main)/_layout/", - "/(main)/_layout/edit/$contentId" + "/(main)/_layout/edit/$" ] }, "/(main)/_layout/bibliography": { @@ -288,8 +288,8 @@ export const routeTree = rootRoute "/debug/ast-viewer/": { "filePath": "debug/ast-viewer/index.tsx" }, - "/(main)/_layout/edit/$contentId": { - "filePath": "(main)/_layout/edit/$contentId.tsx", + "/(main)/_layout/edit/$": { + "filePath": "(main)/_layout/edit/$.tsx", "parent": "/(main)/_layout" } } diff --git a/packages/viola/src/routes/(main)/_layout/edit/$.tsx b/packages/viola/src/routes/(main)/_layout/edit/$.tsx new file mode 100644 index 0000000..b7a6eb1 --- /dev/null +++ b/packages/viola/src/routes/(main)/_layout/edit/$.tsx @@ -0,0 +1,33 @@ +import { createFileRoute, redirect } from '@tanstack/react-router'; +import { ref } from 'valtio'; + +import { generateId } from '../../../../libs/generate-id'; +import { $content } from '../../../../stores/content'; +import { $project } from '../../../../stores/project'; +import { $ui } from '../../../../stores/ui'; + +export const Route = createFileRoute('/(main)/_layout/edit/$')({ + beforeLoad: async ({ params, preload }) => { + if (preload) { + return; + } + await $project.setupPromise; + const [contentId] = $content.getFileByFilename(params._splat || '') || []; + if (!contentId) { + throw redirect({ to: '/' }); + } + if ( + $ui.tabs.some((tab) => tab.type === 'edit' && tab.contentId === contentId) + ) { + return; + } + $ui.tabs = [ + { + id: generateId(), + type: 'edit', + contentId, + title: ref(() => <>Editor), + }, + ]; + }, +}); diff --git a/packages/viola/src/routes/(main)/_layout/edit/$contentId.tsx b/packages/viola/src/routes/(main)/_layout/edit/$contentId.tsx deleted file mode 100644 index 6e06465..0000000 --- a/packages/viola/src/routes/(main)/_layout/edit/$contentId.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { createFileRoute, redirect } from '@tanstack/react-router'; -import { ref } from 'valtio'; - -import { generateId } from '../../../../libs/generate-id'; -import { $content, type ContentId } from '../../../../stores/content'; -import { $ui } from '../../../../stores/ui'; - -export const Route = createFileRoute('/(main)/_layout/edit/$contentId')({ - component: () => null, - beforeLoad: ({ params }) => { - const contentId = params.contentId as ContentId; - if (!$content.files.has(contentId)) { - throw redirect({ to: '/' }); - } - }, - onEnter: ({ params }) => { - const contentId = params.contentId as ContentId; - if (!$content.files.has(contentId)) { - return; - } - $ui.tabs = [ - { - id: generateId(), - type: 'edit', - contentId: contentId, - title: ref(() => <>Editor), - }, - ]; - }, -}); diff --git a/packages/viola/src/stores/actions/content-file.ts b/packages/viola/src/stores/actions/content-file.ts index 61732dd..b23db8e 100644 --- a/packages/viola/src/stores/actions/content-file.ts +++ b/packages/viola/src/stores/actions/content-file.ts @@ -6,7 +6,7 @@ import { ref } from 'valtio'; import { setupEditor } from '../../libs/editor'; import { generateId, generateRandomName } from '../../libs/generate-id'; import { $content, type ContentId } from '../content'; -import { $sandbox } from '../sandbox'; +import { $sandbox, defaultDraftDir } from '../sandbox'; import { $ui } from '../ui'; export async function createContentFile({ @@ -21,18 +21,20 @@ export async function createContentFile({ const contentId = generateId(); const extname = '.md'; const basename = `${generateRandomName()}${extname}`; - const filename = join(prevFileDir || '', basename); + const entryPath = join(prevFileDir || defaultDraftDir, basename); + const filename = join( + $sandbox.vivliostyleConfig.entryContext || '', + entryPath, + ); const index = ((insertAfter && $content.readingOrder.indexOf(insertAfter)) ?? -1) + 1; // update sandbox - $sandbox.files[ - join($sandbox.vivliostyleConfig.entryContext || '', filename) - ] = ref(new Blob([], { type: 'text/markdown' })); + $sandbox.files[filename] = ref(new Blob([], { type: 'text/markdown' })); $sandbox.updateVivliostyleConfig((config) => { config.entry = [$sandbox.vivliostyleConfig.entry] .flat() - .toSpliced(index, 0, filename); + .toSpliced(index, 0, entryPath); }); // update content diff --git a/packages/viola/src/stores/actions/setup-project.ts b/packages/viola/src/stores/actions/setup-project.ts index 923810d..12a9507 100644 --- a/packages/viola/src/stores/actions/setup-project.ts +++ b/packages/viola/src/stores/actions/setup-project.ts @@ -1,3 +1,4 @@ +import { join } from 'pathe'; import { ref } from 'valtio'; import { setupEditor } from '../../libs/editor'; @@ -25,7 +26,6 @@ export async function setupProject(projectId: string) { await root.getDirectoryHandle(projectId, { create: true }), ); $sandbox.updateVivliostyleConfig((config) => { - config.entryContext = 'contents'; config.entry = []; config.theme = ['@vivliostyle/theme-base', './style.css']; }); @@ -37,16 +37,31 @@ export async function setupProject(projectId: string) { url.hostname = `sandbox-${projectId}.${url.hostname}`; $sandbox.sandboxOrigin = url.origin; - const contentIdMap: Record = {}; - for (const [rootFilename, initialFile] of Object.entries($sandbox.files)) { - const matched = rootFilename.match(/^contents\/(?.+)$/); - const name = matched?.groups?.name; - const format = name?.endsWith('.md') ? 'markdown' : undefined; - if (!name || !format) { + const entryContext = $sandbox.vivliostyleConfig.entryContext || ''; + const entryFiles = [$sandbox.vivliostyleConfig.entry].flat().flatMap((it) => { + const entry = typeof it === 'string' ? { path: it } : it; + if (!entry.path) { + return []; + } + const filename = join(entryContext, entry.path); + const format = entry.path.endsWith('.md') + ? ('markdown' as const) + : undefined; + const content = $sandbox.files[filename]; + if (!content) { + return []; + } + return { filename, format, content }; + }); + + const readingOrder: ContentId[] = []; + for (const { filename, format, content } of entryFiles) { + if (!format) { + // TODO: handle other formats continue; } const contentId = generateId(); - const editor = await setupEditor({ contentId, initialFile }); + const editor = await setupEditor({ contentId, initialFile: content }); const summary = editor .getText({ blockSeparator: '\n' }) @@ -54,19 +69,14 @@ export async function setupProject(projectId: string) { .find((s) => s.trim()) ?.trim() || ''; - contentIdMap[name] = contentId; + readingOrder.push(contentId); $content.files.set(contentId, { format, - filename: name, + filename, summary, editor: ref(editor), }); } - $content.readingOrder = [$sandbox.vivliostyleConfig.entry] - .flat() - .flatMap((e) => { - const p = e && typeof e === 'object' ? e.path : e; - return p ? [contentIdMap[p]] : []; - }); + $content.readingOrder = readingOrder; $theme.customCss = await $sandbox.files['style.css'].text(); } diff --git a/packages/viola/src/stores/content.ts b/packages/viola/src/stores/content.ts index 49c9de2..e2c984e 100644 --- a/packages/viola/src/stores/content.ts +++ b/packages/viola/src/stores/content.ts @@ -48,4 +48,12 @@ export const $content = proxy({ ['.'] as HierarchicalReadingOrder, ); }, + + getFileByFilename(filename: string): [ContentId, FileContent] | undefined { + for (const [contentId, file] of this.files.entries()) { + if (file.filename === filename) { + return [contentId, file]; + } + } + }, }); diff --git a/packages/viola/src/stores/sandbox.ts b/packages/viola/src/stores/sandbox.ts index 460d21b..c2e27f0 100644 --- a/packages/viola/src/stores/sandbox.ts +++ b/packages/viola/src/stores/sandbox.ts @@ -7,6 +7,8 @@ import { subscribeKey } from 'valtio/utils'; export type RemoteCli = Comlink.Remote; +export const defaultDraftDir = 'drafts'; + const cliProxy = proxy({ awaiter: undefined as Promise | undefined, fulfilledValue: undefined as RemoteCli | undefined, @@ -113,15 +115,18 @@ export async function loadProjectFromCache() { invariant(projectDir, 'projectDirectoryHandle is not set'); const newFiles: (typeof $sandbox)['files'] = {}; + let configJson: string; try { const configFileHandle = await projectDir.getFileHandle( 'vivliostyle.config.json', ); const file = await configFileHandle.getFile(); newFiles['vivliostyle.config.json'] = ref(file); + configJson = await file.text(); } catch { throw new Error('Project does not exist'); } + vivliostyleConfig.value = JSON.parse(configJson); await readFileSystemRecursive({ dirHandle: projectDir, From fa066f9b4bd10b16e8c745a79948a3c84ddc21d8 Mon Sep 17 00:00:00 2001 From: TAMADA Akihiro Date: Mon, 15 Dec 2025 02:02:26 +0900 Subject: [PATCH 3/3] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- packages/viola/src/components/side-menu.tsx | 2 +- packages/viola/src/routes/(main)/_layout/edit/$.tsx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/viola/src/components/side-menu.tsx b/packages/viola/src/components/side-menu.tsx index e83730a..018a7f4 100644 --- a/packages/viola/src/components/side-menu.tsx +++ b/packages/viola/src/components/side-menu.tsx @@ -248,7 +248,7 @@ function FileTreeItem({ asChild > {file ? ( - + {file?.summary || 'Empty file'} diff --git a/packages/viola/src/routes/(main)/_layout/edit/$.tsx b/packages/viola/src/routes/(main)/_layout/edit/$.tsx index b7a6eb1..ccc47fe 100644 --- a/packages/viola/src/routes/(main)/_layout/edit/$.tsx +++ b/packages/viola/src/routes/(main)/_layout/edit/$.tsx @@ -12,7 +12,8 @@ export const Route = createFileRoute('/(main)/_layout/edit/$')({ return; } await $project.setupPromise; - const [contentId] = $content.getFileByFilename(params._splat || '') || []; + const result = $content.getFileByFilename(params._splat || ''); + const contentId = result?.[0]; if (!contentId) { throw redirect({ to: '/' }); }