From 4a2c632dc883ab0b1bb19c077d8527863f069126 Mon Sep 17 00:00:00 2001 From: Tom Meagher Date: Fri, 9 Feb 2024 14:14:19 -0500 Subject: [PATCH] feat(dev): show frame routes --- src/dev/components.tsx | 47 +++++++++++++++++++++++++++++++++++------- src/dev/utils.ts | 12 +++++++++++ src/farc.tsx | 12 ++++++++--- 3 files changed, 61 insertions(+), 10 deletions(-) diff --git a/src/dev/components.tsx b/src/dev/components.tsx index fb42ef85..01385324 100644 --- a/src/dev/components.tsx +++ b/src/dev/components.tsx @@ -11,15 +11,16 @@ import { type State } from './utils.js' export type AppProps = { baseUrl: string frame: FrameType + routes: readonly string[] state: State } export function App(props: AppProps) { - const { baseUrl, frame, state } = props + const { baseUrl, frame, routes, state } = props return (
- +
) } @@ -27,21 +28,25 @@ export function App(props: AppProps) { type PreviewProps = { baseUrl: string frame: FrameType + routes: readonly string[] state: State } export function Preview(props: PreviewProps) { - const { baseUrl, frame, state } = props + const { baseUrl, frame, routes, state } = props const hxTarget = 'preview' return (
- +
+ + +
) @@ -196,6 +201,30 @@ const redirectIcon = ( ) +type NavigatorProps = { + baseUrl: string + routes: readonly string[] +} + +function Navigator(props: NavigatorProps) { + const { baseUrl, routes } = props + const url = new URL(baseUrl) + return ( + + ) +} + type InspectorProps = { frame: FrameType state: { @@ -308,7 +337,9 @@ async function Inspector(props: InspectorProps) { ) } -function Header() { +type HeaderProps = {} + +function Header(_props: HeaderProps) { return (
𝑭𝒂𝒓𝒄 ▶︎ @@ -493,6 +524,7 @@ export function DevStyles() { .border-t-0 { border-top-width: 0; } .cursor-pointer { cursor: pointer; } .font-bold { font-weight: 700; } + .font-mono { font-family: monospace; } .flex { display: flex; } .flex-col { flex-direction: column; } .flex-row { flex-direction: row; } @@ -530,6 +562,7 @@ export function DevStyles() { .text-sm { font-size: 0.875rem; } .text-xs { font-size: 0.75rem; } .w-full { width: 100%; } + .whitespace-nowrap { white-space: nowrap; } .text-fg2 { color: var(--fg2); } diff --git a/src/dev/utils.ts b/src/dev/utils.ts index 6d8c06d7..f3a5aff2 100644 --- a/src/dev/utils.ts +++ b/src/dev/utils.ts @@ -1,4 +1,6 @@ import { Window } from 'happy-dom' +import { inspectRoutes } from 'hono/dev' + import { type FrameContext, type FrameImageAspectRatio, @@ -219,3 +221,13 @@ export function htmlToFrame(html: string) { title: properties.title, } satisfies Frame } + +export function getFrameRoutes(routes: ReturnType) { + const frameRoutes = [] + for (const route of routes) { + if (route.isMiddleware) continue + if (route.method !== 'ALL') continue + frameRoutes.push(route.path) + } + return frameRoutes +} diff --git a/src/farc.tsx b/src/farc.tsx index 2d09bd22..cf69f34f 100644 --- a/src/farc.tsx +++ b/src/farc.tsx @@ -10,9 +10,10 @@ import { Hono } from 'hono' import { ImageResponse } from 'hono-og' import { jsxRenderer } from 'hono/jsx-renderer' import { type Env, type Schema } from 'hono/types' +import { inspectRoutes } from 'hono/dev' import { App, DevStyles, Preview } from './dev/components.js' -import { htmlToFrame, htmlToState } from './dev/utils.js' +import { getFrameRoutes, htmlToFrame, htmlToState } from './dev/utils.js' import { type FrameContext, type FrameImageAspectRatio, @@ -154,9 +155,12 @@ export class Farc< const baseUrl = c.req.url.replace('/dev', '') const response = await fetch(baseUrl) const text = await response.text() + const frame = htmlToFrame(text) const state = htmlToState(text) - return c.render() + const routes = getFrameRoutes(inspectRoutes(this)) + + return c.render() }) .post(async (c) => { const baseUrl = c.req.url.replace('/dev', '') @@ -265,11 +269,13 @@ export class Farc< }), }) const text = await response.text() + // TODO: handle redirects const frame = htmlToFrame(text) const state = htmlToState(text) + const routes = getFrameRoutes(inspectRoutes(this)) - return c.render() + return c.render() }) } }