From 0e810b9cdedc283993439e3b760df8bb4c2417ba Mon Sep 17 00:00:00 2001 From: Chris Griffing Date: Sun, 24 Nov 2024 14:04:08 -0800 Subject: [PATCH 01/14] fix: lazy load shiki langauge and theme bundles --- playgrounds/app/src/components/Editor.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/playgrounds/app/src/components/Editor.tsx b/playgrounds/app/src/components/Editor.tsx index a081b87..49e640d 100644 --- a/playgrounds/app/src/components/Editor.tsx +++ b/playgrounds/app/src/components/Editor.tsx @@ -44,6 +44,7 @@ import { Setter, Show, } from 'solid-js' +import type { HighlighterGeneric } from 'shiki' import { createHighlighter, bundledThemes, bundledLanguages } from 'shiki' import { ShikiMagicMove } from 'shiki-magic-move/solid' import { AnimationFrameConfig, SnippetSettings } from '~/types' @@ -106,14 +107,15 @@ export default function Editor(props: EditorProps) { const [isShowingGifDialog, setIsShowingGifDialog] = createSignal(false) const [title, setTitle] = createSignal(props.snippetSettings.title) const [isSaving, setIsSaving] = createSignal(false) + const [highlighter, setHighlighter] = createSignal | undefined>() - const [highlighter] = createResource(async () => { - const newHighlighter = await createHighlighter({ - themes: Object.keys(bundledThemes), - langs: Object.keys(bundledLanguages), + createEffect(() => { + createHighlighter({ + themes: [props.snippetSettings.theme], + langs: [props.snippetSettings.language], + }).then(newHighlighter => { + setHighlighter(newHighlighter) }) - - return newHighlighter }) createEffect(() => { From fb0c40d442d441a1c7f90d2cf88dcaccc4b3c8a4 Mon Sep 17 00:00:00 2001 From: Chris Griffing Date: Sun, 24 Nov 2024 14:30:37 -0800 Subject: [PATCH 02/14] fix: handle container used before defined error --- .../src/solid/ShikiMagicMoveRenderer.tsx | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/packages/shiki-magic-move/src/solid/ShikiMagicMoveRenderer.tsx b/packages/shiki-magic-move/src/solid/ShikiMagicMoveRenderer.tsx index c1cfc35..a03ae84 100644 --- a/packages/shiki-magic-move/src/solid/ShikiMagicMoveRenderer.tsx +++ b/packages/shiki-magic-move/src/solid/ShikiMagicMoveRenderer.tsx @@ -21,15 +21,16 @@ export interface ShikiMagicMoveRendererProps { * A wrapper component to `MagicMoveRenderer` */ export function ShikiMagicMoveRenderer(props: ShikiMagicMoveRendererProps) { - let container: HTMLPreElement - let renderer: Renderer + // eslint-disable-next-line no-undef-init, prefer-const + let container: HTMLPreElement | undefined = undefined + // eslint-disable-next-line no-undef-init + let renderer: Renderer | undefined = undefined const [isMounted, setIsMounted] = createSignal(false) createEffect(() => { - if (!container) return - if (!isMounted()) { + if (container !== undefined && !isMounted()) { // Remove previous content - container.innerHTML = '' + ;(container as HTMLPreElement).innerHTML = '' setIsMounted(true) renderer = new Renderer(container) } @@ -37,16 +38,21 @@ export function ShikiMagicMoveRenderer(props: ShikiMagicMoveRendererProps) { createEffect(() => { async function render() { - if (!renderer) return + if (!renderer) { + return + } Object.assign(renderer.options, props.options) if (props.animate === undefined || props.animate === true) { - if (props.previous) renderer.replace(props.previous) + if (props.previous) { + renderer.replace(props.previous) + } props.onStart?.() await renderer.render(props.tokens) props.onEnd?.() + // eslint-disable-next-line style/brace-style } else { renderer.replace(props.tokens) } @@ -57,7 +63,6 @@ export function ShikiMagicMoveRenderer(props: ShikiMagicMoveRendererProps) { return (
         {isMounted()
           ? undefined
-          : props.tokens?.tokens.map(token => {
+          : props.tokens?.tokens.map((token) => {
               if (token.content === '\n') return 
return ( @@ -77,7 +82,9 @@ export function ShikiMagicMoveRenderer(props: ShikiMagicMoveRendererProps) { ...normalizeCSSProperties(token.htmlStyle), color: token.color, }} - class={['shiki-magic-move-item', token.htmlClass].filter(Boolean).join(' ')} + class={['shiki-magic-move-item', token.htmlClass] + .filter(Boolean) + .join(' ')} > {token.content} From 9eab2caac367cf31b2b8cfd9c083b8913bb6304b Mon Sep 17 00:00:00 2001 From: cmgriffing Date: Sun, 24 Nov 2024 22:30:54 +0000 Subject: [PATCH 03/14] style: auto-format with action --- .../shiki-magic-move/src/solid/ShikiMagicMoveRenderer.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/shiki-magic-move/src/solid/ShikiMagicMoveRenderer.tsx b/packages/shiki-magic-move/src/solid/ShikiMagicMoveRenderer.tsx index a03ae84..ea30dbb 100644 --- a/packages/shiki-magic-move/src/solid/ShikiMagicMoveRenderer.tsx +++ b/packages/shiki-magic-move/src/solid/ShikiMagicMoveRenderer.tsx @@ -73,7 +73,7 @@ export function ShikiMagicMoveRenderer(props: ShikiMagicMoveRendererProps) {
{isMounted() ? undefined - : props.tokens?.tokens.map((token) => { + : props.tokens?.tokens.map(token => { if (token.content === '\n') return
return ( @@ -82,9 +82,7 @@ export function ShikiMagicMoveRenderer(props: ShikiMagicMoveRendererProps) { ...normalizeCSSProperties(token.htmlStyle), color: token.color, }} - class={['shiki-magic-move-item', token.htmlClass] - .filter(Boolean) - .join(' ')} + class={['shiki-magic-move-item', token.htmlClass].filter(Boolean).join(' ')} > {token.content} From dd59f02f963aa70fcbb4528e7f9d1dfe122b4f93 Mon Sep 17 00:00:00 2001 From: Chris Griffing Date: Sun, 24 Nov 2024 15:01:36 -0800 Subject: [PATCH 04/14] fix: try removing the app build from postinstall --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 313bad5..0f07808 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "scripts": { "postinstall": "pnpm build", "dev": "pnpm run --filter ./playgrounds/app dev", - "build": "cd packages/shikicode && pnpm build && cd ../shiki-magic-move && pnpm build && cd ../../playgrounds/app && pnpm build", + "build": "cd packages/shikicode && pnpm build && cd ../shiki-magic-move && pnpm build", "test": "turbo run test --filter=./packages/*", "typecheck": "turbo run typecheck --filter=./packages/*", "build-test": "turbo run build test --filter=./packages/*", From f85c8b40797df17755bfed9c7a6ca87ea9c95f26 Mon Sep 17 00:00:00 2001 From: Chris Griffing Date: Sun, 24 Nov 2024 20:17:50 -0800 Subject: [PATCH 05/14] feat: add video output support --- playgrounds/app/app.config.ts | 3 + playgrounds/app/package.json | 4 + playgrounds/app/src/components/Editor.tsx | 147 +++++++++++++++++- .../app/src/components/ui/progress-circle.tsx | 94 +++++++++++ pnpm-lock.yaml | 44 ++++++ 5 files changed, 291 insertions(+), 1 deletion(-) create mode 100644 playgrounds/app/src/components/ui/progress-circle.tsx diff --git a/playgrounds/app/app.config.ts b/playgrounds/app/app.config.ts index 6cec8cd..1ec635e 100644 --- a/playgrounds/app/app.config.ts +++ b/playgrounds/app/app.config.ts @@ -2,4 +2,7 @@ import { defineConfig } from '@solidjs/start/config' export default defineConfig({ ssr: false, + vite: { + optimizeDeps: { exclude: ['@ffmpeg/ffmpeg', '@ffmpeg/util'] }, + }, }) diff --git a/playgrounds/app/package.json b/playgrounds/app/package.json index 257bc00..fe47637 100644 --- a/playgrounds/app/package.json +++ b/playgrounds/app/package.json @@ -16,6 +16,9 @@ }, "dependencies": { "@corvu/resizable": "^0.2.3", + "@ffmpeg/core": "^0.12.6", + "@ffmpeg/ffmpeg": "^0.12.10", + "@ffmpeg/util": "^0.12.1", "@fontsource/bungee-inline": "^5.1.0", "@fontsource/roboto": "^5.1.0", "@kobalte/core": "^0.13.7", @@ -31,6 +34,7 @@ "diff-match-patch-es": "^0.1.0", "dotenv": "^16.4.5", "drizzle-orm": "^0.35.3", + "idb": "^8.0.0", "jsonwebtoken": "^9.0.2", "modern-gif": "^2.0.3", "nanoid": "^5.0.7", diff --git a/playgrounds/app/src/components/Editor.tsx b/playgrounds/app/src/components/Editor.tsx index 49e640d..3556c01 100644 --- a/playgrounds/app/src/components/Editor.tsx +++ b/playgrounds/app/src/components/Editor.tsx @@ -55,8 +55,20 @@ import { toast } from 'solid-sonner' import { Separator } from './ui/separator' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select' import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from './ui/accordion' +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from './ui/dropdown-menu' import { ShikiCodeBlock } from './ShikiCodeBlock' import { SetStoreFunction } from 'solid-js/store' +import { FFmpeg } from '@ffmpeg/ffmpeg' +import { fetchFile, toBlobURL } from '@ffmpeg/util' +import coreURL from '@ffmpeg/core?url' +import wasmURL from '@ffmpeg/core/wasm?url' +import { openDB } from 'idb' +import { ProgressCircle } from './ui/progress-circle' const animationSeconds = 1 const animationFPS = 30 @@ -109,6 +121,13 @@ export default function Editor(props: EditorProps) { const [isSaving, setIsSaving] = createSignal(false) const [highlighter, setHighlighter] = createSignal | undefined>() + const [isShowingFfmpegDialog, setIsShowingFfmpegDialog] = createSignal(false) + const [ffmpegLoaded, setFfmpegLoaded] = createSignal(false) + const [isDownloadingFfmpeg, setIsDownloadingFfmpeg] = createSignal(false) + const [isGeneratingVideo, setIsGeneratingVideo] = createSignal(false) + const [videoProgress, setVideoProgress] = createSignal(0) + const ffmpeg = new FFmpeg() + createEffect(() => { createHighlighter({ themes: [props.snippetSettings.theme], @@ -129,6 +148,8 @@ export default function Editor(props: EditorProps) { props.snippetSettings.codeLeft !== '' && props.snippetSettings.codeRight !== '' && !isResizing() && + !isShowingGifDialog() && + !isShowingFfmpegDialog() && isLooping() ) { if (toggled()) { @@ -957,16 +978,130 @@ export default function Editor(props: EditorProps) { link.click() }} > - Download + Download GIF + + { + setIsShowingFfmpegDialog(true) + }} + > + Enable Video + + } + > + + + + + Downloading...

}> +

To create video, must download ffmpeg.wasm. It is approximately 30MB.

+
+ + + + +
+
) } +function dataURItoUInt8Array(dataURI: string) { + // convert base64 to raw binary data held in a string + // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this + var byteString = atob(dataURI.split(',')[1]) + + // separate out the mime component + var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0] + + // write the bytes of the string to an ArrayBuffer + var ab = new ArrayBuffer(byteString.length) + + // create a view into the buffer + var ia = new Uint8Array(ab) + + // set the bytes of the buffer to the correct values + for (var i = 0; i < byteString.length; i++) { + ia[i] = byteString.charCodeAt(i) + } + + return ia +} + function dataURItoBlob(dataURI: string) { // convert base64 to raw binary data held in a string // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this @@ -1112,3 +1247,13 @@ async function createAnimationFrame( return ctx.getImageData(0, 0, canvas.width, canvas.height) } + +// Not actually necessary since the browser will cache the wasm file +async function wrappedToBlobURL(url: string, mimeType: string) { + const storeName = 'ffmpegCache' + const db = await openDB(storeName, 1, {}) + + return db.get(storeName, url).catch(() => { + return toBlobURL(url, mimeType) + }) +} diff --git a/playgrounds/app/src/components/ui/progress-circle.tsx b/playgrounds/app/src/components/ui/progress-circle.tsx new file mode 100644 index 0000000..851fbee --- /dev/null +++ b/playgrounds/app/src/components/ui/progress-circle.tsx @@ -0,0 +1,94 @@ +import type { Component, ComponentProps } from 'solid-js' +import { mergeProps, splitProps } from 'solid-js' + +import { cn } from '~/lib/utils' + +type Size = 'xs' | 'sm' | 'md' | 'lg' | 'xl' + +const sizes: Record = { + xs: { radius: 15, strokeWidth: 3 }, + sm: { radius: 19, strokeWidth: 4 }, + md: { radius: 32, strokeWidth: 6 }, + lg: { radius: 52, strokeWidth: 8 }, + xl: { radius: 80, strokeWidth: 10 }, +} + +type ProgressCircleProps = ComponentProps<'div'> & { + value?: number + size?: Size + radius?: number + strokeWidth?: number + showAnimation?: boolean +} + +const ProgressCircle: Component = rawProps => { + const props = mergeProps({ size: 'md' as Size, showAnimation: true }, rawProps) + const [local, others] = splitProps(props, [ + 'class', + 'children', + 'value', + 'size', + 'radius', + 'strokeWidth', + 'showAnimation', + ]) + + const value = () => getLimitedValue(local.value) + const radius = () => local.radius ?? sizes[local.size].radius + const strokeWidth = () => local.strokeWidth ?? sizes[local.size].strokeWidth + const normalizedRadius = () => radius() - strokeWidth() / 2 + const circumference = () => normalizedRadius() * 2 * Math.PI + const strokeDashoffset = () => (value() / 100) * circumference() + const offset = () => circumference() - strokeDashoffset() + + return ( +
+ + + {value() >= 0 ? ( + + ) : null} + +
{local.children}
+
+ ) +} + +function getLimitedValue(input: number | undefined) { + if (input === undefined) { + return 0 + } else if (input > 100) { + return 100 + } + return input +} + +export { ProgressCircle } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2823d32..05f0fe7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -195,6 +195,15 @@ importers: '@corvu/resizable': specifier: ^0.2.3 version: 0.2.3(solid-js@1.9.2) + '@ffmpeg/core': + specifier: ^0.12.6 + version: 0.12.6 + '@ffmpeg/ffmpeg': + specifier: ^0.12.10 + version: 0.12.10 + '@ffmpeg/util': + specifier: ^0.12.1 + version: 0.12.1 '@fontsource/bungee-inline': specifier: ^5.1.0 version: 5.1.0 @@ -240,6 +249,9 @@ importers: drizzle-orm: specifier: ^0.35.3 version: 0.35.3(@libsql/client-wasm@0.14.0)(@libsql/client@0.14.0)(@types/react@18.3.11)(react@18.3.1) + idb: + specifier: ^8.0.0 + version: 8.0.0 jsonwebtoken: specifier: ^9.0.2 version: 9.0.2 @@ -1738,6 +1750,22 @@ packages: resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} + '@ffmpeg/core@0.12.6': + resolution: {integrity: sha512-PrjWBTfGn2WVn9T7wGnzfFwChbqWeZc7tM9vvJZVRadYFUDakfzy7W0LpYC0cvvK0xT82qlBsk38lQhJ/Hps5A==} + engines: {node: '>=16.x'} + + '@ffmpeg/ffmpeg@0.12.10': + resolution: {integrity: sha512-lVtk8PW8e+NUzGZhPTWj2P1J4/NyuCrbDD3O9IGpSeLYtUZKBqZO8CNj1WYGghep/MXoM8e1qVY1GztTkf8YYQ==} + engines: {node: '>=18.x'} + + '@ffmpeg/types@0.12.2': + resolution: {integrity: sha512-NJtxwPoLb60/z1Klv0ueshguWQ/7mNm106qdHkB4HL49LXszjhjCCiL+ldHJGQ9ai2Igx0s4F24ghigy//ERdA==} + engines: {node: '>=16.x'} + + '@ffmpeg/util@0.12.1': + resolution: {integrity: sha512-10jjfAKWaDyb8+nAkijcsi9wgz/y26LOc1NKJradNMyCIl6usQcBbhkjX5qhALrSBcOy6TOeksunTYa+a03qNQ==} + engines: {node: '>=18.x'} + '@floating-ui/core@1.6.8': resolution: {integrity: sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==} @@ -4370,6 +4398,9 @@ packages: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} + idb@8.0.0: + resolution: {integrity: sha512-l//qvlAKGmQO31Qn7xdzagVPPaHTxXx199MhrAFuVBTPqydcPYBWjkrbv4Y0ktB+GmWOiwHl237UUOrLmQxLvw==} + ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -4689,6 +4720,7 @@ packages: libsql@0.4.6: resolution: {integrity: sha512-F5M+ltteK6dCcpjMahrkgT96uFJvVI8aQ4r9f2AzHQjC7BkAYtvfMSTWGvRBezRgMUIU2h1Sy0pF9nOGOD5iyA==} + cpu: [x64, arm64, wasm32] os: [darwin, linux, win32] lilconfig@2.1.0: @@ -8193,6 +8225,16 @@ snapshots: '@fastify/busboy@2.1.1': {} + '@ffmpeg/core@0.12.6': {} + + '@ffmpeg/ffmpeg@0.12.10': + dependencies: + '@ffmpeg/types': 0.12.2 + + '@ffmpeg/types@0.12.2': {} + + '@ffmpeg/util@0.12.1': {} + '@floating-ui/core@1.6.8': dependencies: '@floating-ui/utils': 0.2.8 @@ -11333,6 +11375,8 @@ snapshots: dependencies: safer-buffer: 2.1.2 + idb@8.0.0: {} + ieee754@1.2.1: {} ignore@5.3.2: {} From 810aa02e551b34d7aae3e6d91cfdbf4746fb89e3 Mon Sep 17 00:00:00 2001 From: Chris Griffing Date: Sun, 24 Nov 2024 20:23:51 -0800 Subject: [PATCH 06/14] fix: add a bit about browser caching to the ffmpeg.wasm dowload warning --- playgrounds/app/src/components/Editor.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/playgrounds/app/src/components/Editor.tsx b/playgrounds/app/src/components/Editor.tsx index 3556c01..252e3ea 100644 --- a/playgrounds/app/src/components/Editor.tsx +++ b/playgrounds/app/src/components/Editor.tsx @@ -1031,7 +1031,10 @@ export default function Editor(props: EditorProps) { Downloading...

}> -

To create video, must download ffmpeg.wasm. It is approximately 30MB.

+

+ To create video, must download ffmpeg.wasm. It's approximately 30MB. If you have + downloaded it here before, your browser cache should kick in. +

+ + +
+ + props.setSnippetSettings('theme', newTheme || '')} + placeholder="Search a theme..." + itemComponent={props => ( + + {props.item.rawValue} + + + )} + > + + + + + + +
+ +
+ + props.setSnippetSettings('language', newLanguage || '')} + placeholder="Search a Language..." + itemComponent={props => ( + + {props.item.rawValue} + + + )} + > + + + + + + +
+ + + + + + Background + +
+
+ + + + id="bg-type" + value={bgTypeOptions.find( + option => option.value === props.snippetSettings.bgType, + )} + optionValue="value" + optionTextValue="label" + onChange={newType => + newType && + props.setSnippetSettings( + 'bgType', + newType.value as 'solid' | 'linearGradient', + ) + } + options={bgTypeOptions} + itemComponent={props => ( + {props.item.rawValue.label} + )} + > + + > + {state => state.selectedOption()?.label} + + + + +
+ + {props.snippetSettings.bgType === 'linearGradient' && ( + <> +
+ + { + props.setSnippetSettings('bgGradientColorStart', e.target.value) + }} + /> +
+
+ + { + props.setSnippetSettings('bgGradientColorEnd', e.target.value) + }} + /> +
+ { + props.setSnippetSettings('bgGradientDirection', e[0]) + }} + > +
+ Direction + +
+ + deg +
+
+ + + + +
+ )} - optionValue="value" - optionTextValue="label" - onChange={newType => - newType && - props.setSnippetSettings( - 'bgType', - newType.value as 'solid' | 'linearGradient', - ) - } - options={bgTypeOptions} - itemComponent={props => ( - {props.item.rawValue.label} + {props.snippetSettings.bgType === 'solid' && ( +
+ + { + props.setSnippetSettings('bgColor', e.target.value) + }} + /> +
)} - > - + + + + + Layout + +
+ { + props.setSnippetSettings('snippetWidth', e[0]) + }} > - > - {state => state.selectedOption()?.label} - - - - -
+
+ Width +
+ + px +
+
+ + + + + + + { + props.setSnippetSettings('yPadding', e[0]) + }} + > +
+ Padding (y) +
+ + px +
+
+ + + + +
+ + { + props.setSnippetSettings('xPadding', e[0]) + }} + > +
+ Padding (x) +
+ + px +
+
+ + + + +
+
+
+
- {props.snippetSettings.bgType === 'linearGradient' && ( - <> + + Shadow + +
-
+
-
+
+ { + props.setSnippetSettings('shadowOpacity', e[0]) + }} + > +
+ Opacity + +
+ + + + +
+
+
+ { + props.setSnippetSettings('shadowOffsetY', e[0]) + }} + > +
+ Offset Y +
+ + px +
+
+ + + + +
+
+
+ { + props.setSnippetSettings('shadowBlur', e[0]) + }} + > +
+ Blur +
+ + px +
+
+ + + + +
+
+
+
+
+ + + Font + +
+
+ + + + id="font-family" + value={supportedFontFamilies.find( + option => option.name === props.snippetSettings.fontFamily, + )} + optionValue="name" + optionTextValue="name" + onChange={newFamily => + newFamily && props.setSnippetSettings('fontFamily', newFamily.name) + } + options={supportedFontFamilies} + itemComponent={props => ( + {props.item.rawValue.name} + )} + > + + > + {state => state.selectedOption()?.name} + + + + +
+ { - props.setSnippetSettings('bgGradientDirection', e[0]) + props.setSnippetSettings('fontSize', e[0]) }} > -
- Direction - +
+ Size
- deg + px
- + - - )} - {props.snippetSettings.bgType === 'solid' && ( -
- - { - props.setSnippetSettings('bgColor', e.target.value) - }} - />
- )} -
- - - - - Layout - -
- { - props.setSnippetSettings('snippetWidth', e[0]) - }} - > -
- Width -
- - px -
-
- - - - -
- - { - props.setSnippetSettings('yPadding', e[0]) - }} - > -
- Padding (y) -
- - px -
-
- - - - -
- - { - props.setSnippetSettings('xPadding', e[0]) - }} - > -
- Padding (x) -
- - px -
-
- - - - -
-
-
-
- - - Shadow - -
-
- - { - props.setSnippetSettings( - 'shadowEnabled', - !props.snippetSettings.shadowEnabled, - ) - }} - /> -
- -
- - - props.setSnippetSettings('shadowColor', e.target.value)} - /> -
-
- { - props.setSnippetSettings('shadowOpacity', e[0]) - }} - > -
- Opacity - -
- - - - -
-
-
- { - props.setSnippetSettings('shadowOffsetY', e[0]) - }} - > -
- Offset Y -
- - px -
-
- - - - -
-
-
- { - props.setSnippetSettings('shadowBlur', e[0]) - }} - > -
- Blur -
- - px -
-
- - - - -
-
-
-
-
- - - Font - -
-
- - - - id="font-family" - value={supportedFontFamilies.find( - option => option.name === props.snippetSettings.fontFamily, - )} - optionValue="name" - optionTextValue="name" - onChange={newFamily => - newFamily && props.setSnippetSettings('fontFamily', newFamily.name) - } - options={supportedFontFamilies} - itemComponent={props => ( - {props.item.rawValue.name} - )} - > - - > - {state => state.selectedOption()?.name} - - - - -
- - { - props.setSnippetSettings('fontSize', e[0]) - }} - > -
- Size -
- - px -
-
- - - - -
-
-
-
- + + + + +
- {user()?.githubUsername} + diff --git a/playgrounds/app/src/components/ui/collapsible.tsx b/playgrounds/app/src/components/ui/collapsible.tsx new file mode 100644 index 0000000..e8b8082 --- /dev/null +++ b/playgrounds/app/src/components/ui/collapsible.tsx @@ -0,0 +1,9 @@ +import * as CollapsiblePrimitive from "@kobalte/core/collapsible" + +const Collapsible = CollapsiblePrimitive.Root + +const CollapsibleTrigger = CollapsiblePrimitive.Trigger + +const CollapsibleContent = CollapsiblePrimitive.Content + +export { Collapsible, CollapsibleTrigger, CollapsibleContent } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 05f0fe7..d7dede4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -216,6 +216,9 @@ importers: '@libsql/client': specifier: ^0.14.0 version: 0.14.0 + '@solid-primitives/media': + specifier: ^2.2.9 + version: 2.2.9(solid-js@1.9.2) '@solid-primitives/storage': specifier: ^4.2.1 version: 4.2.1(solid-js@1.9.2) From 0fe2fab2ae0ab4b421098e59b9cd22f2c6a124a2 Mon Sep 17 00:00:00 2001 From: cmgriffing Date: Tue, 26 Nov 2024 01:00:21 +0000 Subject: [PATCH 10/14] style: auto-format with action --- playgrounds/app/src/app.css | 4 +++- playgrounds/app/src/components/ui/collapsible.tsx | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/playgrounds/app/src/app.css b/playgrounds/app/src/app.css index f963b25..5564567 100644 --- a/playgrounds/app/src/app.css +++ b/playgrounds/app/src/app.css @@ -102,7 +102,9 @@ body { @apply bg-background text-foreground; - font-feature-settings: 'rlig' 1, 'calt' 1; + font-feature-settings: + 'rlig' 1, + 'calt' 1; } } diff --git a/playgrounds/app/src/components/ui/collapsible.tsx b/playgrounds/app/src/components/ui/collapsible.tsx index e8b8082..995ee34 100644 --- a/playgrounds/app/src/components/ui/collapsible.tsx +++ b/playgrounds/app/src/components/ui/collapsible.tsx @@ -1,4 +1,4 @@ -import * as CollapsiblePrimitive from "@kobalte/core/collapsible" +import * as CollapsiblePrimitive from '@kobalte/core/collapsible' const Collapsible = CollapsiblePrimitive.Root From 7b00a415fe3b3a02bc3880293ad14d18e4e6987c Mon Sep 17 00:00:00 2001 From: Chris Griffing Date: Mon, 25 Nov 2024 18:52:59 -0800 Subject: [PATCH 11/14] fix: cut off text when vanvas is too narrow instead of squishing text --- playgrounds/app/src/components/Editor.tsx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/playgrounds/app/src/components/Editor.tsx b/playgrounds/app/src/components/Editor.tsx index d65ddb5..63bfe4e 100644 --- a/playgrounds/app/src/components/Editor.tsx +++ b/playgrounds/app/src/components/Editor.tsx @@ -1196,6 +1196,11 @@ async function createAnimationFrame( canvas.width = width + xPadding * 2 canvas.height = height + yPadding * 2 + const textCanvas = document.createElement('canvas') + const textCtx = textCanvas.getContext('2d', { alpha: true })! + textCanvas.width = width + xPadding - 4 + textCanvas.height = height + yPadding + if (backgroundType === 'linearGradient') { // Convert angle to match CSS gradient angle (0deg = to top, 90deg = to right) const cssAngle = (backgroundGradientDirection + 90) % 360 @@ -1266,13 +1271,15 @@ async function createAnimationFrame( [el.color.start || 'rgba(0,0,0,0)', el.color.end || 'rgba(0,0,0,0)'], ) - ctx.font = `${fontSize} ${fontFamily}` - ctx.fillStyle = color - ctx.globalAlpha = opacity - ctx.fillText(htmlDecode(el.el.innerHTML), x, y, width - x + xPadding / 2) + textCtx.font = `${fontSize} ${fontFamily}` + textCtx.fillStyle = color + textCtx.globalAlpha = opacity + textCtx.fillText(htmlDecode(el.el.innerHTML), x, y) }) await Promise.all(elementPromises) + ctx.drawImage(textCanvas, 0, 0) + return ctx.getImageData(0, 0, canvas.width, canvas.height) } From 22dab61fa3f040bf86cf086fb9a4e2dde4ec2943 Mon Sep 17 00:00:00 2001 From: Chris Griffing Date: Mon, 25 Nov 2024 19:25:20 -0800 Subject: [PATCH 12/14] chore: add import sorting --- .prettierrc | 28 +++-- playgrounds/app/package.json | 1 + playgrounds/app/src/app.css | 4 +- playgrounds/app/src/app.tsx | 11 +- playgrounds/app/src/components/Editor.tsx | 109 ++++++++--------- playgrounds/app/src/components/Footer.tsx | 1 + playgrounds/app/src/components/Header.tsx | 34 +++--- .../app/src/components/ShikiCodeBlock.tsx | 5 +- .../app/src/components/SnippetPreview.tsx | 1 + .../app/src/components/theme-switcher.tsx | 3 +- playgrounds/app/src/db/client.ts | 1 + playgrounds/app/src/db/schema.ts | 2 +- playgrounds/app/src/entry-client.tsx | 2 +- playgrounds/app/src/entry-server.tsx | 2 +- playgrounds/app/src/lib/ids.ts | 1 + playgrounds/app/src/lib/middleware.ts | 8 +- playgrounds/app/src/lib/store.ts | 2 + playgrounds/app/src/lib/utils.ts | 1 + playgrounds/app/src/routes/about.tsx | 2 + playgrounds/app/src/routes/api/oauth.ts | 1 + playgrounds/app/src/routes/api/snippets.ts | 3 +- .../src/routes/api/snippets/[snippetId].ts | 1 + playgrounds/app/src/routes/index.tsx | 5 +- playgrounds/app/src/routes/logged-out.tsx | 7 +- playgrounds/app/src/routes/oauth.tsx | 4 +- .../app/src/routes/snippets/[snippetId].tsx | 3 +- playgrounds/app/src/routes/snippets/index.tsx | 7 +- pnpm-lock.yaml | 115 ++++++++++++++++++ 28 files changed, 258 insertions(+), 106 deletions(-) diff --git a/.prettierrc b/.prettierrc index dddf1b3..cf830cf 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,10 +1,22 @@ { - "trailingComma": "all", - "tabWidth": 2, - "printWidth": 100, - "semi": false, - "singleQuote": true, - "useTabs": false, - "arrowParens": "avoid", - "bracketSpacing": true + "trailingComma": "all", + "tabWidth": 2, + "printWidth": 100, + "semi": false, + "singleQuote": true, + "useTabs": false, + "arrowParens": "avoid", + "bracketSpacing": true, + "plugins": ["@trivago/prettier-plugin-sort-imports"], + "importOrder": [ + "^solid-js(.*)$", + "^solid-(.*)$", + "^shiki(.*)$", + "^~/components/ui/(.*)$", + "^~/(.*)$", + "^[./]" + ], + "importOrderGroupNamespaceSpecifiers": true, + "importOrderSeparation": true, + "importOrderSortSpecifiers": true } diff --git a/playgrounds/app/package.json b/playgrounds/app/package.json index 9760e47..7de2ff5 100644 --- a/playgrounds/app/package.json +++ b/playgrounds/app/package.json @@ -59,6 +59,7 @@ "node": ">=18" }, "devDependencies": { + "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/jsonwebtoken": "^9.0.7", "drizzle-kit": "^0.26.2", "tsx": "^4.19.1" diff --git a/playgrounds/app/src/app.css b/playgrounds/app/src/app.css index 5564567..f963b25 100644 --- a/playgrounds/app/src/app.css +++ b/playgrounds/app/src/app.css @@ -102,9 +102,7 @@ body { @apply bg-background text-foreground; - font-feature-settings: - 'rlig' 1, - 'calt' 1; + font-feature-settings: 'rlig' 1, 'calt' 1; } } diff --git a/playgrounds/app/src/app.tsx b/playgrounds/app/src/app.tsx index 5e8df30..5479ae9 100644 --- a/playgrounds/app/src/app.tsx +++ b/playgrounds/app/src/app.tsx @@ -1,11 +1,14 @@ -import { Suspense } from 'solid-js' +import '@fontsource/bungee-inline' +import '@fontsource/roboto' import { Router } from '@solidjs/router' import { FileRoutes } from '@solidjs/start/router' + +import { Suspense } from 'solid-js' + import { Toaster } from 'solid-sonner' + import Header from '~/components/Header' -import Footer from './components/Footer' -import '@fontsource/bungee-inline' -import '@fontsource/roboto' + import './app.css' export default function App() { diff --git a/playgrounds/app/src/components/Editor.tsx b/playgrounds/app/src/components/Editor.tsx index 63bfe4e..fa7598e 100644 --- a/playgrounds/app/src/components/Editor.tsx +++ b/playgrounds/app/src/components/Editor.tsx @@ -1,21 +1,57 @@ -import { interpolate, interpolateColors, Easing } from 'remotion' +import wasmURL from '@ffmpeg/core/wasm?url' +import coreURL from '@ffmpeg/core?url' +import { FFmpeg } from '@ffmpeg/ffmpeg' +import { fetchFile, toBlobURL } from '@ffmpeg/util' +import { useNavigate } from '@solidjs/router' +import clsx from 'clsx' +import { openDB } from 'idb' import { encode } from 'modern-gif' import workerUrl from 'modern-gif/worker?url' +import { Easing, interpolate, interpolateColors } from 'remotion' + +import { Show, createEffect, createMemo, createSignal, onCleanup, onMount } from 'solid-js' +import { SetStoreFunction } from 'solid-js/store' + +import { FaSolidCaretDown, FaSolidCaretUp } from 'solid-icons/fa' +import { HiOutlineCog } from 'solid-icons/hi' +import { toast } from 'solid-sonner' + +import type { HighlighterGeneric } from 'shiki' +import { bundledLanguages, bundledThemes, createHighlighter } from 'shiki' import 'shiki-magic-move/dist/style.css' +import { ShikiMagicMove } from 'shiki-magic-move/solid' +import { MagicMoveElement } from 'shiki-magic-move/types' + import { - ComboboxItem, - ComboboxItemLabel, - ComboboxItemIndicator, + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from '~/components/ui/accordion' +import { Button } from '~/components/ui/button' +import { Checkbox } from '~/components/ui/checkbox' +import { Collapsible, CollapsibleContent } from '~/components/ui/collapsible' +import { + Combobox, + ComboboxContent, ComboboxControl, ComboboxInput, + ComboboxItem, + ComboboxItemIndicator, + ComboboxItemLabel, ComboboxTrigger, - ComboboxContent, - Combobox, } from '~/components/ui/combobox' -import { Button } from '~/components/ui/button' -import { Tabs, TabsContent, TabsList, TabsTrigger } from '~/components/ui/tabs' -import { TextField, TextFieldInput } from '~/components/ui/text-field' -import { MagicMoveElement } from 'shiki-magic-move/types' +import { Dialog, DialogContent, DialogFooter } from '~/components/ui/dialog' +import { Label } from '~/components/ui/label' +import { ProgressCircle } from '~/components/ui/progress-circle' +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '~/components/ui/select' +import { Separator } from '~/components/ui/separator' import { Slider, SliderFill, @@ -24,55 +60,14 @@ import { SliderTrack, SliderValueLabel, } from '~/components/ui/slider' -import clsx from 'clsx' -import { Checkbox } from '~/components/ui/checkbox' -import { Label } from '~/components/ui/label' -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from '~/components/ui/dialog' -import { - createEffect, - createMemo, - createResource, - createSignal, - onCleanup, - Setter, - Show, - onMount, -} from 'solid-js' -import type { HighlighterGeneric } from 'shiki' -import { createHighlighter, bundledThemes, bundledLanguages } from 'shiki' -import { ShikiMagicMove } from 'shiki-magic-move/solid' -import { AnimationFrameConfig, SnippetSettings } from '~/types' -import { authFetch } from '~/lib/utils' -import { useNavigate } from '@solidjs/router' +import { Tabs, TabsContent, TabsList, TabsTrigger } from '~/components/ui/tabs' +import { TextField, TextFieldInput } from '~/components/ui/text-field' + import { authToken } from '~/lib/store' -import { toast } from 'solid-sonner' -import { Separator } from './ui/separator' -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select' -import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from './ui/accordion' -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from './ui/dropdown-menu' +import { authFetch } from '~/lib/utils' +import { AnimationFrameConfig, SnippetSettings } from '~/types' + import { ShikiCodeBlock } from './ShikiCodeBlock' -import { SetStoreFunction } from 'solid-js/store' -import { FFmpeg } from '@ffmpeg/ffmpeg' -import { fetchFile, toBlobURL } from '@ffmpeg/util' -import coreURL from '@ffmpeg/core?url' -import wasmURL from '@ffmpeg/core/wasm?url' -import { openDB } from 'idb' -import { ProgressCircle } from './ui/progress-circle' -import { Collapsible, CollapsibleContent } from './ui/collapsible' -import { FaSolidCaretDown, FaSolidCaretUp } from 'solid-icons/fa' -import { HiOutlineCog } from 'solid-icons/hi' const animationSeconds = 1 const animationFPS = 30 diff --git a/playgrounds/app/src/components/Footer.tsx b/playgrounds/app/src/components/Footer.tsx index 2d3b2b4..f6cf86e 100644 --- a/playgrounds/app/src/components/Footer.tsx +++ b/playgrounds/app/src/components/Footer.tsx @@ -1,4 +1,5 @@ import { A } from '@solidjs/router' + import { linkStyles } from '~/lib/styles' export default function Footer() { diff --git a/playgrounds/app/src/components/Header.tsx b/playgrounds/app/src/components/Header.tsx index 98e8599..b8edec7 100644 --- a/playgrounds/app/src/components/Header.tsx +++ b/playgrounds/app/src/components/Header.tsx @@ -1,29 +1,31 @@ +import { makePersisted } from '@solid-primitives/storage' import { A } from '@solidjs/router' -import { Button } from './ui/button' + +import { Show, createSignal } from 'solid-js' + +import { FaSolidMoon, FaSolidSun } from 'solid-icons/fa' import { OcMarkgithub2, OcQuestion2 } from 'solid-icons/oc' -import { FaSolidSun, FaSolidMoon } from 'solid-icons/fa' -import { createThemeSwitcher } from '~/components/theme-switcher' -import { authToken } from '~/lib/store' -import { createSignal, Show } from 'solid-js' -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from '~/components/ui/dropdown-menu' -import { user } from '~/lib/store' import { TbCode, TbDoorExit, TbQuestionMark } from 'solid-icons/tb' -import { linkStyles } from '~/lib/styles' + +import { Button } from '~/components/ui/button' import { Dialog, DialogContent, DialogDescription, - DialogFooter, DialogHeader, DialogTitle, - DialogTrigger, } from '~/components/ui/dialog' -import { makePersisted } from '@solid-primitives/storage' +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from '~/components/ui/dropdown-menu' + +import { createThemeSwitcher } from '~/components/theme-switcher' +import { authToken } from '~/lib/store' +import { user } from '~/lib/store' +import { linkStyles } from '~/lib/styles' export default function Header() { const [isShowingHelpDialog, setIsShowingHelpDialog] = makePersisted(createSignal(true), { diff --git a/playgrounds/app/src/components/ShikiCodeBlock.tsx b/playgrounds/app/src/components/ShikiCodeBlock.tsx index e9bf3b0..11bd2c2 100644 --- a/playgrounds/app/src/components/ShikiCodeBlock.tsx +++ b/playgrounds/app/src/components/ShikiCodeBlock.tsx @@ -1,7 +1,8 @@ -import { createSignal, onMount, createEffect } from 'solid-js' +import { createEffect, createSignal, onMount } from 'solid-js' + import { createHighlighter } from 'shiki' -import { autoload, hookClosingPairs, hookTab, ShikiCode } from 'shikicode/plugins' import { shikiCode } from 'shikicode' +import { ShikiCode, autoload, hookClosingPairs, hookTab } from 'shikicode/plugins' import { cn } from '~/lib/utils' diff --git a/playgrounds/app/src/components/SnippetPreview.tsx b/playgrounds/app/src/components/SnippetPreview.tsx index bec23cb..ce0662b 100644 --- a/playgrounds/app/src/components/SnippetPreview.tsx +++ b/playgrounds/app/src/components/SnippetPreview.tsx @@ -1,5 +1,6 @@ import { Highlighter } from 'shiki' import { ShikiMagicMove } from 'shiki-magic-move/solid' + import { Snippet } from '~/types' interface SnippetPreviewProps { diff --git a/playgrounds/app/src/components/theme-switcher.tsx b/playgrounds/app/src/components/theme-switcher.tsx index 6f17fbb..019b139 100644 --- a/playgrounds/app/src/components/theme-switcher.tsx +++ b/playgrounds/app/src/components/theme-switcher.tsx @@ -1,6 +1,7 @@ -import { createSignal, createEffect } from 'solid-js' import { makePersisted } from '@solid-primitives/storage' +import { createEffect, createSignal } from 'solid-js' + export function createThemeSwitcher() { const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)') const [isDarkMode, setIsDarkMode] = makePersisted(createSignal(prefersDarkScheme.matches), { diff --git a/playgrounds/app/src/db/client.ts b/playgrounds/app/src/db/client.ts index 656d4b3..a1656c1 100644 --- a/playgrounds/app/src/db/client.ts +++ b/playgrounds/app/src/db/client.ts @@ -1,5 +1,6 @@ import 'dotenv/config' import { drizzle } from 'drizzle-orm/libsql' + import { schema } from './schema' export const db = drizzle({ diff --git a/playgrounds/app/src/db/schema.ts b/playgrounds/app/src/db/schema.ts index 2bc4bb5..97069ed 100644 --- a/playgrounds/app/src/db/schema.ts +++ b/playgrounds/app/src/db/schema.ts @@ -1,4 +1,4 @@ -import { int, sqliteTable, text, real } from 'drizzle-orm/sqlite-core' +import { int, real, sqliteTable, text } from 'drizzle-orm/sqlite-core' export const usersTable = sqliteTable('users_table', { id: text().primaryKey(), diff --git a/playgrounds/app/src/entry-client.tsx b/playgrounds/app/src/entry-client.tsx index 46acd52..ffccf40 100644 --- a/playgrounds/app/src/entry-client.tsx +++ b/playgrounds/app/src/entry-client.tsx @@ -1,4 +1,4 @@ // @refresh reload -import { mount, StartClient } from '@solidjs/start/client' +import { StartClient, mount } from '@solidjs/start/client' mount(() => , document.getElementById('app')!) diff --git a/playgrounds/app/src/entry-server.tsx b/playgrounds/app/src/entry-server.tsx index 0626e99..4c02775 100644 --- a/playgrounds/app/src/entry-server.tsx +++ b/playgrounds/app/src/entry-server.tsx @@ -1,5 +1,5 @@ // @refresh reload -import { createHandler, StartServer } from '@solidjs/start/server' +import { StartServer, createHandler } from '@solidjs/start/server' export default createHandler(() => ( { const user = await getUser(event) diff --git a/playgrounds/app/src/routes/api/snippets/[snippetId].ts b/playgrounds/app/src/routes/api/snippets/[snippetId].ts index c5e2c62..11b1dd4 100644 --- a/playgrounds/app/src/routes/api/snippets/[snippetId].ts +++ b/playgrounds/app/src/routes/api/snippets/[snippetId].ts @@ -1,5 +1,6 @@ import type { APIEvent } from '@solidjs/start/server' import { and, eq } from 'drizzle-orm' + import { db } from '~/db/client' import { snippetsTable } from '~/db/schema' import { getUser } from '~/lib/middleware' diff --git a/playgrounds/app/src/routes/index.tsx b/playgrounds/app/src/routes/index.tsx index 9419fce..8ee38f0 100644 --- a/playgrounds/app/src/routes/index.tsx +++ b/playgrounds/app/src/routes/index.tsx @@ -1,8 +1,9 @@ -import { createSignal } from 'solid-js' import { makePersisted } from '@solid-primitives/storage' + +import { createStore } from 'solid-js/store' + import Editor from '~/components/Editor' import { SnippetSettings } from '~/types' -import { createStore } from 'solid-js/store' const left = ` import { render } from "solid-js/web"; diff --git a/playgrounds/app/src/routes/logged-out.tsx b/playgrounds/app/src/routes/logged-out.tsx index e21a2a7..873ea29 100644 --- a/playgrounds/app/src/routes/logged-out.tsx +++ b/playgrounds/app/src/routes/logged-out.tsx @@ -1,6 +1,9 @@ -import { Button } from '~/components/ui/button' -import { OcMarkgithub2 } from 'solid-icons/oc' import { onMount } from 'solid-js' + +import { OcMarkgithub2 } from 'solid-icons/oc' + +import { Button } from '~/components/ui/button' + import { setAuthToken } from '~/lib/store' export default function LoggedOut() { diff --git a/playgrounds/app/src/routes/oauth.tsx b/playgrounds/app/src/routes/oauth.tsx index 9e3db2b..3e41429 100644 --- a/playgrounds/app/src/routes/oauth.tsx +++ b/playgrounds/app/src/routes/oauth.tsx @@ -1,5 +1,7 @@ import { useNavigate, useSearchParams } from '@solidjs/router' -import { createSignal, onMount, Show } from 'solid-js' + +import { Show, createSignal, onMount } from 'solid-js' + import { setAuthToken, setUser, user } from '~/lib/store' export default function OAuth() { diff --git a/playgrounds/app/src/routes/snippets/[snippetId].tsx b/playgrounds/app/src/routes/snippets/[snippetId].tsx index fefc9be..0f8a46b 100644 --- a/playgrounds/app/src/routes/snippets/[snippetId].tsx +++ b/playgrounds/app/src/routes/snippets/[snippetId].tsx @@ -1,5 +1,6 @@ -import { createEffect, createResource, Show } from 'solid-js' +import { Show, createEffect, createResource } from 'solid-js' import { createStore } from 'solid-js/store' + import Editor from '~/components/Editor' import { authFetch } from '~/lib/utils' import { Snippet, SnippetSettings } from '~/types' diff --git a/playgrounds/app/src/routes/snippets/index.tsx b/playgrounds/app/src/routes/snippets/index.tsx index 3305343..6eaaaea 100644 --- a/playgrounds/app/src/routes/snippets/index.tsx +++ b/playgrounds/app/src/routes/snippets/index.tsx @@ -1,6 +1,9 @@ import { A } from '@solidjs/router' -import { createHighlighter, bundledThemes, bundledLanguages } from 'shiki' -import { createResource, Show } from 'solid-js' + +import { Show, createResource } from 'solid-js' + +import { bundledLanguages, bundledThemes, createHighlighter } from 'shiki' + import { SnippetPreview } from '~/components/SnippetPreview' import { authFetch } from '~/lib/utils' import { Snippet } from '~/types' diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d7dede4..867f737 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -310,6 +310,9 @@ importers: specifier: ^3.23.8 version: 3.23.8 devDependencies: + '@trivago/prettier-plugin-sort-imports': + specifier: ^4.3.0 + version: 4.3.0(@vue/compiler-sfc@3.5.12)(prettier@2.8.3) '@types/jsonwebtoken': specifier: ^9.0.7 version: 9.0.7 @@ -398,6 +401,10 @@ packages: resolution: {integrity: sha512-Oixnb+DzmRT30qu9d3tJSQkxuygWm32DFykT4bRoORPa9hZ/L4KhVB/XiRm6KG+roIEM7DBQlmg27kw2HZkdZg==} engines: {node: '>=6.9.0'} + '@babel/generator@7.17.7': + resolution: {integrity: sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==} + engines: {node: '>=6.9.0'} + '@babel/generator@7.25.7': resolution: {integrity: sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==} engines: {node: '>=6.9.0'} @@ -416,6 +423,18 @@ packages: peerDependencies: '@babel/core': ^7.0.0 + '@babel/helper-environment-visitor@7.24.7': + resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-function-name@7.24.7': + resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-hoist-variables@7.24.7': + resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==} + engines: {node: '>=6.9.0'} + '@babel/helper-member-expression-to-functions@7.25.7': resolution: {integrity: sha512-O31Ssjd5K6lPbTX9AAYpSKrZmLeagt9uwschJd+Ixo6QiRyfpvgtVQp8qrDR9UNFjZ8+DO34ZkdrN+BnPXemeA==} engines: {node: '>=6.9.0'} @@ -456,6 +475,10 @@ packages: resolution: {integrity: sha512-pPbNbchZBkPMD50K0p3JGcFMNLVUCuU/ABybm/PGNj4JiHrpmNyqqCphBk4i19xXtNV0JhldQJJtbSW5aUvbyA==} engines: {node: '>=6.9.0'} + '@babel/helper-split-export-declaration@7.24.7': + resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} + engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.25.7': resolution: {integrity: sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==} engines: {node: '>=6.9.0'} @@ -553,10 +576,18 @@ packages: resolution: {integrity: sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==} engines: {node: '>=6.9.0'} + '@babel/traverse@7.23.2': + resolution: {integrity: sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==} + engines: {node: '>=6.9.0'} + '@babel/traverse@7.25.7': resolution: {integrity: sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==} engines: {node: '>=6.9.0'} + '@babel/types@7.17.0': + resolution: {integrity: sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==} + engines: {node: '>=6.9.0'} + '@babel/types@7.25.8': resolution: {integrity: sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==} engines: {node: '>=6.9.0'} @@ -2413,6 +2444,15 @@ packages: resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} engines: {node: '>= 10'} + '@trivago/prettier-plugin-sort-imports@4.3.0': + resolution: {integrity: sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ==} + peerDependencies: + '@vue/compiler-sfc': 3.x + prettier: 2.x - 3.x + peerDependenciesMeta: + '@vue/compiler-sfc': + optional: true + '@trysound/sax@0.2.0': resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} @@ -4568,6 +4608,9 @@ packages: resolution: {integrity: sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==} engines: {node: 20 || >=22} + javascript-natural-sort@0.7.1: + resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==} + jest-diff@29.7.0: resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -4638,6 +4681,11 @@ packages: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true + jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + jsesc@3.0.2: resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} engines: {node: '>=6'} @@ -6087,6 +6135,10 @@ packages: source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} @@ -7139,6 +7191,12 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/generator@7.17.7': + dependencies: + '@babel/types': 7.25.8 + jsesc: 2.5.2 + source-map: 0.5.7 + '@babel/generator@7.25.7': dependencies: '@babel/types': 7.25.8 @@ -7171,6 +7229,19 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-environment-visitor@7.24.7': + dependencies: + '@babel/types': 7.25.8 + + '@babel/helper-function-name@7.24.7': + dependencies: + '@babel/template': 7.25.7 + '@babel/types': 7.25.8 + + '@babel/helper-hoist-variables@7.24.7': + dependencies: + '@babel/types': 7.25.8 + '@babel/helper-member-expression-to-functions@7.25.7': dependencies: '@babel/traverse': 7.25.7 @@ -7228,6 +7299,10 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-split-export-declaration@7.24.7': + dependencies: + '@babel/types': 7.25.8 + '@babel/helper-string-parser@7.25.7': {} '@babel/helper-validator-identifier@7.25.7': {} @@ -7344,6 +7419,21 @@ snapshots: '@babel/parser': 7.25.8 '@babel/types': 7.25.8 + '@babel/traverse@7.23.2': + dependencies: + '@babel/code-frame': 7.25.7 + '@babel/generator': 7.25.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-function-name': 7.24.7 + '@babel/helper-hoist-variables': 7.24.7 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/parser': 7.25.8 + '@babel/types': 7.25.8 + debug: 4.3.7 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + '@babel/traverse@7.25.7': dependencies: '@babel/code-frame': 7.25.7 @@ -7356,6 +7446,11 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/types@7.17.0': + dependencies: + '@babel/helper-validator-identifier': 7.25.7 + to-fast-properties: 2.0.0 + '@babel/types@7.25.8': dependencies: '@babel/helper-string-parser': 7.25.7 @@ -8935,6 +9030,20 @@ snapshots: '@tootallnate/once@2.0.0': {} + '@trivago/prettier-plugin-sort-imports@4.3.0(@vue/compiler-sfc@3.5.12)(prettier@2.8.3)': + dependencies: + '@babel/generator': 7.17.7 + '@babel/parser': 7.25.8 + '@babel/traverse': 7.23.2 + '@babel/types': 7.17.0 + javascript-natural-sort: 0.7.1 + lodash: 4.17.21 + prettier: 2.8.3 + optionalDependencies: + '@vue/compiler-sfc': 3.5.12 + transitivePeerDependencies: + - supports-color + '@trysound/sax@0.2.0': {} '@types/babel__core@7.20.5': @@ -11534,6 +11643,8 @@ snapshots: dependencies: '@isaacs/cliui': 8.0.2 + javascript-natural-sort@0.7.1: {} + jest-diff@29.7.0: dependencies: chalk: 4.1.2 @@ -11631,6 +11742,8 @@ snapshots: jsesc@0.5.0: {} + jsesc@2.5.2: {} + jsesc@3.0.2: {} json-buffer@3.0.1: {} @@ -13287,6 +13400,8 @@ snapshots: buffer-from: 1.1.2 source-map: 0.6.1 + source-map@0.5.7: {} + source-map@0.6.1: {} source-map@0.7.4: {} From 6cf50c056b400211b237d86caf86b76c77c89744 Mon Sep 17 00:00:00 2001 From: Chris Griffing Date: Mon, 25 Nov 2024 19:28:42 -0800 Subject: [PATCH 13/14] fix: add import sorting at the top level --- package.json | 1 + pnpm-lock.yaml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/package.json b/package.json index 0f07808..4dc6f92 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ }, "devDependencies": { "@changesets/cli": "^2.26.0", + "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/node": "^18.11.18", "concurrently": "^7.6.0", "jsdom": "^21.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 867f737..f267481 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: '@changesets/cli': specifier: ^2.26.0 version: 2.27.9 + '@trivago/prettier-plugin-sort-imports': + specifier: ^4.3.0 + version: 4.3.0(@vue/compiler-sfc@3.5.12)(prettier@2.8.3) '@types/node': specifier: ^18.11.18 version: 18.19.55 From 433128ba5f7c3989977b0283f05384d7956ec08a Mon Sep 17 00:00:00 2001 From: Chris Griffing Date: Mon, 25 Nov 2024 19:31:59 -0800 Subject: [PATCH 14/14] fix: run pnpm install before formatting --- .github/workflows/format.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index eed0982..8ab8c04 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -21,6 +21,12 @@ jobs: # This is important to fetch the changes to the previous commit fetch-depth: 0 + steps: + - uses: pnpm/action-setup@v4 + with: + version: 9 + run_install: true + - name: Prettier Action uses: creyD/prettier_action@v4.3 with: