Skip to content

Commit

Permalink
feat: show toast for easy jumping to currently edited file
Browse files Browse the repository at this point in the history
  • Loading branch information
jacob-8 committed Apr 16, 2024
1 parent ae91662 commit f09681f
Show file tree
Hide file tree
Showing 14 changed files with 82 additions and 15 deletions.
2 changes: 1 addition & 1 deletion packages/kitbook/kitbook.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default defineConfig({
return `${path}?${params.toString()}`
},
githubURL: 'https://github.com/jacob-8/kitbook/tree/main/packages/kitbook',
// expandTree: true,
expandTree: true,
routesDirectory: 'src/lib/routes',
kitbookRoute: '',
})
6 changes: 3 additions & 3 deletions packages/kitbook/src/docs/why.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

While a lot of great tools exist, they are buggy and/or do not work well for building a simple documentation and prototyping tool for [SvelteKit](https://kit.svelte.dev/) apps and component libraries. A brief list:

- **[Svench](https://svench-docs.vercel.app/)** deserves much of the credit for Kitbook's initial inspiration and is an amazing tool. Unfortunately, it often breaks on Windows, sometimes requiring the dev server to be started twice before success, and has other quirks that have left me without the ability to use my workbench. I attribute these problems simply due to the fact that 1.0 was built long before SvelteKit and while 2.0 will work great if @rixo gets time for that, so far he hasn't updated Svench to work with the current SvelteKit.
- **[Svench](https://svench-docs.vercel.app/)** deserves much of the credit for Kitbook's initial inspiration and is an amazing tool. Unfortunately, it often broke on Windows, sometimes requiring the dev server to be started twice before success, and has other quirks that have left me without the ability to use my workbench. I attribute these problems simply due to the fact that 1.0 was built long before SvelteKit and while 2.0 will work great if @rixo gets time for that, so far he hasn't updated Svench to work with the current SvelteKit.

- **[Storybook](https://codingcat.dev/tutorial/integrating-storybook-with-sveltekit)** was very buggy with SvelteKit for a long time so it pushed me away. Things are better now but Storybook still is not the tool I'm looking for. In short, too many features I don't need, not enough of the ones I do need, and too much boilerplate. [Histoire](https://histoire.dev/) is less bloated but in a similar boat. Both of them are very prototype focused and aren't so great for an easy to read documentation tool I'm looking for. (Histoire's documentation is cordoned off to a little box in the upper right that seems like an afterthought). A prototyping tool should also be a useful place for both developers and non-developers to read documentation, explore components and not get lost in the controls. If developers don't write documentation as they build components, chances are they never will, or they will be sorely out of date.

- **[Bookit](https://bookit.leveluptutorials.com/)** is going the right direction and is the only one listed here allowing SvelteKit imports and features, but it is very feature incomplete and is more of a prototyping tool than a documentation one.
- **Bookit** took a step the right direction its tight SvelteKit integration but Scott stopped working on it.

- **[Vitebook](https://vitebook.dev/)** was visually appealing but was missing many important prototyping features and was discontinued.
- **Vitebook** was visually appealing but was missing many important prototyping features and was discontinued.

All of the above tools, especially Svench, have served as a source of inspiration and ideas for Kitbook.
4 changes: 4 additions & 0 deletions packages/kitbook/src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ export { default as SandboxPage } from './pages/SandboxPage.svelte'
export { sandboxPageLoad } from './pages/sandboxPageLoad'

export { compressToEncodedURIComponent, decompressFromEncodedURIComponent } from './lz/lz-string'

export function delay<T>(value: T, delay_ms = 1000): Promise<T> {
return new Promise(resolve => setTimeout(() => resolve(value), delay_ms))
}
2 changes: 1 addition & 1 deletion packages/kitbook/src/lib/kitbook-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ export interface KitbookSettings {

export interface Viewport {
name?: string
width: number
width: number | null
height: number
}

Expand Down
21 changes: 21 additions & 0 deletions packages/kitbook/src/lib/layout/Layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import { findKitbookPath } from './kitbookPath'
import SearchModal from './sidebar/search/SearchModal.svelte'
import LaunchSearch from './sidebar/search/LaunchSearch.svelte'
import { urlFromPath } from './parseUpdatedPath'
export let settings: KitbookSettings
export let pathname: string
Expand All @@ -30,6 +31,19 @@
}
let SearchModalComponent: SearchModal
let urlForEditedFile: string
if (import.meta.hot) {
import.meta.hot.on('kitbook:route-to-edited-file', ({ filepath }) => {
const url = kitbookPath + urlFromPath(filepath)
const hasPage = !!Object.values(pages).find(page => page.url === url)
if (hasPage && location.pathname !== url)
urlForEditedFile = url
else
urlForEditedFile = null
})
}
</script>

<LayoutPanes>
Expand Down Expand Up @@ -57,6 +71,13 @@

<SearchModal {kitbookPath} bind:this={SearchModalComponent} />

{#if urlForEditedFile}
<a href={urlForEditedFile} on:click={() => urlForEditedFile = null} class="fixed z-50 bottom-3 left-3 p-2 bg-black/75 rounded text-white text-sm">
Jump to view edits: <span class="font-semibold">{urlForEditedFile}</span>
<span class="i-ph-arrow-right-bold -mt-2px" />
</a>
{/if}

<svelte:head>
<meta name="description" content={settings.description} />
</svelte:head>
1 change: 1 addition & 0 deletions packages/kitbook/src/lib/layout/parseModules/parsePath.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export function parsePath(path: string) {
// console.log({ path })
if (path === '/README.md')
return { ext: 'md', name: 'README', dir: '/' }
if (path === '/src/index.md')
Expand Down
33 changes: 33 additions & 0 deletions packages/kitbook/src/lib/layout/parseUpdatedPath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
export function urlFromPath(filepath: string): string | null {
const normalizedPath = filepath.replace(/\\/g, '/')

const match = normalizedPath.match(/^(?:.*\/src\/)(?<path>.+?)\/(?<filename>.+)\.[^\/]+$/)
if (!match?.groups)
return null

const { path, filename } = match.groups
const baseFilename = filename.split('.').shift()
const url = `/${path}/${baseFilename}`
return url
}

if (import.meta.vitest) {
describe(urlFromPath, () => {
test('handles linux filepaths', () => {
expect(urlFromPath('/dev/project/src/lib/components/Foo.svelte'))
.toEqual('/lib/components/Foo')
})
test('handles windows filepaths', () => {
expect(urlFromPath('C:\\dev\\project\\src\\routes\\+layout.svelte'))
.toEqual('/routes/+layout')
})
test('handles named compositions (filenames with multiple dots)', () => {
expect(urlFromPath('/dev/project/src/lib/components/Foo.some.composition'))
.toEqual('/lib/components/Foo')
})
test('return null if path does not match', () => {
expect(urlFromPath('/dev/project/some.config.ts'))
.toBeNull()
})
})
}
6 changes: 4 additions & 2 deletions packages/kitbook/src/lib/layout/sidebar/Header.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
export let githubURL: string = undefined
export let kitbookPath: string
export let activePath: string
$: rootUrl = kitbookPath || '/'
</script>

<header class="flex flex-wrap py-1 pl-1 w-full">
Expand All @@ -15,8 +17,8 @@
<i class="i-ic-round-menu" />
</button>
<a
href={kitbookPath || '/'}
class:text-blue-600={!activePath}
href={rootUrl}
class:text-blue-600={activePath === `${rootUrl}index`}
class="hover:text-blue-700 p-2 text-lg font-semibold flex items-center underline-blue-800 overflow-x-hidden">
<slot>Kitbook</slot>
</a>
Expand Down
3 changes: 1 addition & 2 deletions packages/kitbook/src/lib/layout/sidebar/Header.variants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import type Component from './Header.svelte'
export const viewports: Viewport[] = [
{ height: 200, width: 800 },
{ height: 200, width: 200 },
{ height: 500, width: 200 },
]

export const variants: Variant<Component>[] = [
Expand All @@ -20,7 +19,7 @@ export const variants: Variant<Component>[] = [
description: 'should be blue',
props: {
kitbookPath: '',
activePath: '',
activePath: '/index',
},
},
{
Expand Down
1 change: 1 addition & 0 deletions packages/kitbook/src/lib/open/server-events.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ declare module 'vite/types/customEvent' {

// to client
'kitbook:open-file': { filepath: string; viteBase: string }
'kitbook:route-to-edited-file': { filepath: string }
}
}
5 changes: 3 additions & 2 deletions packages/kitbook/src/lib/pages/MainPage.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
pagesStore,
loadedModules: { variantsModule: initialVariantsModule, compositionsModules: initialCompositionsModules, markdown: initialMarkdown },
pageKey,
settings: { viewports: projectViewports, addLanguageToUrl, githubURL, viewer, title: kitbookTitle, darkMode },
settings,
} = data)
$: ({ viewports: projectViewports, addLanguageToUrl, githubURL, viewer, title: kitbookTitle, darkMode } = settings)
$: pageFromHMR = $pagesStore?.[pageKey]
Expand Down Expand Up @@ -89,7 +90,7 @@
<title>{pageTitle}</title>
</svelte:head>

<Layout settings={data.settings} pages={data.pages} pathname={$page.url.pathname} let:activeLanguages>
<Layout {settings} pages={data.pages} pathname={$page.url.pathname} let:activeLanguages>
{#key $page.url.pathname}
<main style="flex: 1" class="overflow-y-auto bg-white pt-2 px-2">
{#if data.error}
Expand Down
1 change: 1 addition & 0 deletions packages/kitbook/src/lib/plugins/mdsvex.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { shikiTwoslashHighlighter } from '@kitbook/mdsvex-shiki-twoslash'
export { mdsvex } from 'mdsvex'
export const MDSVEX_EXTENSIONS = ['.svx']

/** @deprecated */
export const KITBOOK_MDSVEX_CONFIG = defineMDSveXConfig({
extensions: MDSVEX_EXTENSIONS,
remarkPlugins: [],
Expand Down
4 changes: 4 additions & 0 deletions packages/kitbook/src/lib/plugins/vite/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ export function kitbook(userSettings: Partial<KitbookSettings> = {}): Plugin[] {
console.info(` ${green}${reset} ${bold}Kitbook${reset}: ${green}${server.config.server.https ? 'https' : 'http'}://localhost:${bold}${server.config.server.port}${reset}${green}${languageAwareRoute}${reset}`)
}
}

server.watcher.on('change', (filepath) => {
server.hot.send('kitbook:route-to-edited-file', { filepath })
})
},
}

Expand Down
8 changes: 4 additions & 4 deletions packages/kitbook/src/lib/plugins/vite/viewer/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { access, constants, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import type { Plugin } from 'vite'
import type { HMRBroadcasterClient, Plugin } from 'vite'
import type { KitbookSettings } from 'kitbook'
import { removeQuotesFromSerializedFunctions } from '../../../open/serialize.js'

Expand Down Expand Up @@ -30,11 +30,11 @@ export function kitbookViewer(settings: KitbookSettings): Plugin {
},

configureServer(server) {
server.ws.on('kitbook:ensure-file-exists', ({ filepath, template }, client) => {
server.hot.on('kitbook:ensure-file-exists', ({ filepath, template }, client) => {
writeFileIfNeededThenOpen(filepath, template, settings.viewer.__internal.viteBase, client)
})

server.ws.on('kitbook:open-variants', ({ filepath, props }, client) => {
server.hot.on('kitbook:open-variants', ({ filepath, props }, client) => {
const code = getVariantsTemplate().replace('props: {}', `props: ${JSON.stringify(props, null, 2)}`)
const template = removeQuotesFromSerializedFunctions(code.replace('Template.svelte', filepath.split('/').pop()))

Expand All @@ -56,7 +56,7 @@ function componentListenerCode(): string {
return readFileSync(filepath, 'utf-8')
}

function writeFileIfNeededThenOpen(filepath: string, template: string, viteBase: string, client: any) {
function writeFileIfNeededThenOpen(filepath: string, template: string, viteBase: string, client: HMRBroadcasterClient) {
access(filepath, constants.F_OK, (err) => {
if (err) {
const directory = dirname(filepath)
Expand Down

0 comments on commit f09681f

Please sign in to comment.