mirror of
https://github.com/LukeHagar/sveltekit-og.git
synced 2025-12-06 12:47:49 +00:00
Satori Issue
This commit is contained in:
@@ -4,13 +4,14 @@ About
|
||||
Generate Open Graph Images dynamically from HTML/CSS without a browser in SvelteKit.
|
||||
|
||||
## v1.0.0 Update (Breaking Changes)
|
||||
|
||||
Finally, We have added html to react like element like object converter out of the box and with svelte compiler.
|
||||
Now you can use `{ toReactElement }` with `"@ethercorps/sveltekit-og"` like:
|
||||
|
||||
```typescript
|
||||
// +page.server.js
|
||||
|
||||
import { toReactElement, satori } from "@ethercorps/sveltekit-og"
|
||||
import { toReactElement, satori } from '@ethercorps/sveltekit-og';
|
||||
|
||||
const htmlString = `
|
||||
<div tw="bg-gray-50 flex w-full">
|
||||
@@ -58,8 +59,7 @@ export async function load() {
|
||||
- We have changed to function based instead of class based ImageResponse and componentToImageResponse.
|
||||
- Removed `@resvg/resvg-wasm` with `@resvg/resvg-js` because of internal errors.
|
||||
- Removed `satori-html` because now we have `toReactElement` out of the box with svelte compiler.
|
||||
- Access to `satori` directly from `"@ethercorps/sveltekit-og"`. [_source_](/src/routes/test/+page.server.js) · [_demo_](https://sveltekit-og-five.vercel.app/test)
|
||||
> If you find a problem related to undefined a please check [_vite.config.js_](/vite.config.ts) and add ``` define: { _a: 'undefined' } in config.```
|
||||
> If you find a problem related to undefined a please check [_vite.config.js_](/vite.config.ts) and add ` define: { _a: 'undefined' } in config.`
|
||||
|
||||
> If you find any issue and have suggestion for this project please open a ticket and if you want to contribute please create a new discussion.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ImageResponse } from '@ethercorps/sveltekit-og';
|
||||
import type { RequestHandler } from "@sveltejs/kit";
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
|
||||
const template = `
|
||||
<div tw="bg-gray-50 flex w-full h-full items-center justify-center">
|
||||
|
||||
14
package.json
14
package.json
@@ -3,7 +3,7 @@
|
||||
"version": "1.0.0",
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"dev": "vite dev --host",
|
||||
"build:prod": "vite build",
|
||||
"build": "svelte-kit sync && svelte-package",
|
||||
"prepublishOnly": "echo 'Did you mean to publish `./package/`, instead of `./`?' && exit 1",
|
||||
@@ -16,21 +16,27 @@
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.28.1",
|
||||
"@sveltejs/adapter-auto": "next",
|
||||
"@sveltejs/kit": "next",
|
||||
"@sveltejs/kit": "1.0.0-next.581",
|
||||
"@sveltejs/package": "next",
|
||||
"@typescript-eslint/eslint-plugin": "^5.46.0",
|
||||
"@typescript-eslint/parser": "^5.46.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"brace": "^0.11.1",
|
||||
"eslint": "^8.29.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-svelte3": "^4.0.0",
|
||||
"monaco-editor": "^0.34.1",
|
||||
"postcss": "^8.4.19",
|
||||
"prettier": "^2.8.1",
|
||||
"prettier-plugin-svelte": "^2.8.1",
|
||||
"prettier-plugin-svelte": "^2.9.0",
|
||||
"prismjs": "^1.29.0",
|
||||
"svelte": "^3.54.0",
|
||||
"svelte-check": "^2.10.2",
|
||||
"svelte-preprocess": "^4.10.7",
|
||||
"tailwindcss": "^3.2.4",
|
||||
"tslib": "^2.4.1",
|
||||
"typescript": "^4.9.4",
|
||||
"vite": "^3.2.5"
|
||||
"vite": "^4.0.0"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
|
||||
797
pnpm-lock.yaml
generated
797
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
6
postcss.config.cjs
Normal file
6
postcss.config.cjs
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {}
|
||||
}
|
||||
};
|
||||
14
src/app.css
Normal file
14
src/app.css
Normal file
@@ -0,0 +1,14 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@font-face {
|
||||
font-family: 'Ian Mono';
|
||||
src: url('/iaw-mono-var.woff2') format('woff2');
|
||||
}
|
||||
|
||||
@layer base {
|
||||
html {
|
||||
font-family: Ian Mono, monospace;
|
||||
}
|
||||
}
|
||||
157
src/components/AceEditor.svelte
Normal file
157
src/components/AceEditor.svelte
Normal file
@@ -0,0 +1,157 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, tick, onMount, onDestroy } from "svelte";
|
||||
import * as ace from "brace";
|
||||
import "brace/ext/emmet";
|
||||
const EDITOR_ID = `svelte-ace-editor-div:${Math.floor(
|
||||
Math.random() * 10000000000
|
||||
)}`;
|
||||
const dispatch = createEventDispatcher<{
|
||||
init: ace.Editor;
|
||||
input: string;
|
||||
selectionChange: any;
|
||||
blur: void;
|
||||
changeMode: any;
|
||||
commandKey: { err: any; hashId: any; keyCode: any };
|
||||
copy: void;
|
||||
cursorChange: void;
|
||||
cut: void;
|
||||
documentChange: { data: any };
|
||||
focus: void;
|
||||
paste: string;
|
||||
}>();
|
||||
|
||||
/**
|
||||
* translation of vue component to svelte:
|
||||
* @link https://github.com/chairuosen/vue2-ace-editor/blob/91051422b36482eaf94271f1a263afa4b998f099/index.js
|
||||
**/
|
||||
export let value: string = ""; // String, required
|
||||
export let lang: string = "json"; // String
|
||||
export let theme: string = "chrome"; // String
|
||||
export let height: string = "100%"; // null for 100, else integer, used as percent
|
||||
export let width: string = "100%"; // null for 100, else integer, used as percent
|
||||
export let options: any = {}; // Object
|
||||
export let readonly: boolean = false;
|
||||
|
||||
let editor: ace.Editor;
|
||||
let contentBackup: string = "";
|
||||
|
||||
const requireEditorPlugins = () => {};
|
||||
requireEditorPlugins();
|
||||
|
||||
onDestroy(() => {
|
||||
if (editor) {
|
||||
editor.destroy();
|
||||
editor.container.remove();
|
||||
}
|
||||
});
|
||||
|
||||
$: watchValue(value);
|
||||
function watchValue(val: string) {
|
||||
if (contentBackup !== val && editor && typeof val === "string") {
|
||||
editor.session.setValue(val);
|
||||
contentBackup = val;
|
||||
}
|
||||
}
|
||||
|
||||
$: watchTheme(theme);
|
||||
function watchTheme(newTheme: string) {
|
||||
if (editor) {
|
||||
editor.setTheme("ace/theme/" + newTheme);
|
||||
}
|
||||
}
|
||||
|
||||
$: watchMode(lang);
|
||||
function watchMode(newOption: any) {
|
||||
if (editor) {
|
||||
editor.getSession().setMode("ace/mode/" + newOption);
|
||||
}
|
||||
}
|
||||
|
||||
$: watchOptions(options);
|
||||
function watchOptions(newOption: any) {
|
||||
if (editor) {
|
||||
editor.setOptions(newOption);
|
||||
}
|
||||
}
|
||||
|
||||
$: watchReadOnlyFlag(readonly);
|
||||
function watchReadOnlyFlag(flag) {
|
||||
if (editor) {
|
||||
editor.setReadOnly(flag);
|
||||
}
|
||||
}
|
||||
|
||||
const resizeOnNextTick = () =>
|
||||
tick().then(() => {
|
||||
if (editor) {
|
||||
editor.resize();
|
||||
}
|
||||
});
|
||||
|
||||
$: if (height !== null && width !== null) {
|
||||
resizeOnNextTick();
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
lang = lang || "text";
|
||||
theme = theme || "chrome";
|
||||
|
||||
editor = ace.edit(EDITOR_ID);
|
||||
|
||||
dispatch("init", editor);
|
||||
editor.$blockScrolling = Infinity;
|
||||
// editor.setOption("enableEmmet", true);
|
||||
editor.getSession().setMode("ace/mode/" + lang);
|
||||
editor.setTheme("ace/theme/" + theme);
|
||||
editor.setValue(value, 1);
|
||||
editor.setReadOnly(readonly)
|
||||
contentBackup = value;
|
||||
setEventCallBacks();
|
||||
if (options) {
|
||||
editor.setOptions(options);
|
||||
}
|
||||
});
|
||||
|
||||
const ValidPxDigitsRegEx = /^\d*$/;
|
||||
function px(n: string): string {
|
||||
if (ValidPxDigitsRegEx.test(n)) {
|
||||
return n + "px";
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
function setEventCallBacks() {
|
||||
editor.onBlur = () => dispatch("blur");
|
||||
editor.onChangeMode = (obj) => dispatch("changeMode", obj);
|
||||
editor.onCommandKey = (err, hashId, keyCode) =>
|
||||
dispatch("commandKey", { err, hashId, keyCode });
|
||||
editor.onCopy = () => dispatch("copy");
|
||||
editor.onCursorChange = () => dispatch("cursorChange");
|
||||
editor.onCut = () => {
|
||||
const copyText = editor.getCopyText();
|
||||
console.log("cut event : ", copyText);
|
||||
editor.insert("");
|
||||
dispatch("cut");
|
||||
};
|
||||
editor.onDocumentChange = (obj: { data: any }) =>
|
||||
dispatch("documentChange", obj);
|
||||
editor.onFocus = () => dispatch("focus");
|
||||
editor.onPaste = (text) => {
|
||||
console.log("paste event : ", text);
|
||||
editor.insert(text);
|
||||
dispatch("paste", text);
|
||||
};
|
||||
editor.onSelectionChange = (obj) => dispatch("selectionChange", obj);
|
||||
editor.on("change", function () {
|
||||
const content = editor.getValue();
|
||||
value = content;
|
||||
dispatch("input", content);
|
||||
contentBackup = content;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<div style="width:{px(width)};">
|
||||
<h1 class="font-bold mb-2">Editor</h1>
|
||||
<div id={EDITOR_ID} style="width:{px(width)};" class="h-[80vh] rounded rounded-lg border border-gray-500"/>
|
||||
</div>
|
||||
58
src/components/Navbar.svelte
Normal file
58
src/components/Navbar.svelte
Normal file
@@ -0,0 +1,58 @@
|
||||
<script>
|
||||
let menuBar = false
|
||||
</script>
|
||||
|
||||
<!-- navbar goes here -->
|
||||
<nav class="bg-gray-100">
|
||||
<div class="max-w-full mx-auto px-4">
|
||||
<div class="flex justify-between">
|
||||
<div class="flex space-x-4">
|
||||
<!-- logo -->
|
||||
<div>
|
||||
<a href="#" class="flex items-center py-5 px-2 space-x-1 text-gray-700 hover:text-gray-900">
|
||||
<svg
|
||||
viewBox="0 0 75 65"
|
||||
fill="black"
|
||||
class="w-4 h-4 rotate-90"
|
||||
>
|
||||
<path d="M37.59.25l36.95 64H.64l36.95-64z"></path>
|
||||
</svg>
|
||||
<span class="font-bold">Sveltekit-OG Playground</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- secondary nav -->
|
||||
<div class="hidden md:flex items-center space-x-1">
|
||||
<a href="" class="py-5 px-3 underline">Docs</a>
|
||||
<a href="" class="py-5 px-3 underline">Github</a>
|
||||
</div>
|
||||
|
||||
<!-- mobile button goes here -->
|
||||
<div class="md:hidden flex items-center">
|
||||
<button class="mobile-menu-button" on:click={() => {menuBar = !menuBar}}>
|
||||
<svg
|
||||
class="w-6 h-6"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 6h16M4 12h16M4 18h16"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- mobile menu -->
|
||||
<div class="mobile-menu {menuBar ? '': 'hidden'} md:hidden">
|
||||
<a href="#" class="block py-2 px-4 text-sm hover:bg-gray-200">Docs</a>
|
||||
<a href="#" class="block py-2 px-4 text-sm hover:bg-gray-200">Github</a>
|
||||
</div>
|
||||
</nav>
|
||||
9
src/routes/+layout.svelte
Normal file
9
src/routes/+layout.svelte
Normal file
@@ -0,0 +1,9 @@
|
||||
<script>
|
||||
import '../app.css';
|
||||
import Navbar from "../components/Navbar.svelte";
|
||||
</script>
|
||||
<div class="max-h-screen">
|
||||
<Navbar/>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<script lang="ts">
|
||||
import AceEditor from "/src/components/AceEditor.svelte";
|
||||
import "brace/mode/html";
|
||||
import "brace/theme/chrome";
|
||||
let text = "<h1>hii</h1>";
|
||||
</script>
|
||||
|
||||
<div class="grid grid-cols-2 space-x-10 p-10">
|
||||
<AceEditor style="border: solid"
|
||||
on:selectionChange={(obj) => console.log(obj.detail)}
|
||||
on:paste={(obj) => console.log(obj.detail)}
|
||||
on:input={(obj) => console.log(obj.detail)}
|
||||
on:focus={() => console.log('focus')}
|
||||
on:documentChange={(obj) => console.log(`document change : ${obj.detail}`)}
|
||||
on:cut={() => console.log('cut')}
|
||||
on:cursorChange={() => console.log('cursor change')}
|
||||
on:copy={() => console.log('copy')}
|
||||
on:init={(editor) => console.log(editor.detail)}
|
||||
on:commandKey={(obj) => console.log(obj.detail)}
|
||||
on:changeMode={(obj) => console.log(`change mode : ${obj.detail}`)}
|
||||
on:blur={() => console.log('blur')}
|
||||
lang="html"
|
||||
theme="chrome"
|
||||
value={text}
|
||||
/>
|
||||
<div class="grid grid-rows-2 mt-8 space-y-4">
|
||||
<div class="common">
|
||||
Editor Under Development
|
||||
</div>
|
||||
<div class="common">
|
||||
Coming Soon...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.common {
|
||||
@apply border border-gray-800 rounded p-5
|
||||
}
|
||||
</style>
|
||||
|
||||
BIN
static/iaw-mono-var.woff2
Normal file
BIN
static/iaw-mono-var.woff2
Normal file
Binary file not shown.
@@ -5,8 +5,11 @@ import preprocess from 'svelte-preprocess';
|
||||
const config = {
|
||||
// Consult https://github.com/sveltejs/svelte-preprocess
|
||||
// for more information about preprocessors
|
||||
preprocess: preprocess(),
|
||||
|
||||
preprocess: [
|
||||
preprocess({
|
||||
postcss: true
|
||||
})
|
||||
],
|
||||
kit: {
|
||||
adapter: adapter()
|
||||
}
|
||||
|
||||
8
tailwind.config.cjs
Normal file
8
tailwind.config.cjs
Normal file
@@ -0,0 +1,8 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ['./src/**/*.{html,js,svelte,ts}'],
|
||||
theme: {
|
||||
extend: {}
|
||||
},
|
||||
plugins: []
|
||||
};
|
||||
Reference in New Issue
Block a user