Skip to content

Commit

Permalink
feat: update CLI help and finish README and example
Browse files Browse the repository at this point in the history
  • Loading branch information
Zhengqbbb committed Mar 20, 2023
1 parent f12a7c0 commit a77f4ce
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 16 deletions.
163 changes: 163 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,169 @@
<video src="https://user-images.githubusercontent.com/40693636/226353532-1d6fa4b7-02e9-4a30-8dde-f0f8e3dd9fe0.mp4"/>
</p>

## Getting Started

```sh
npm install -D x-satori
```

<details>
<summary>Using CLI</summary><br>

- Dependence: **Vue | Vite**

```sh
$ npx x-satori --help

SYNOPSIS:
x-satori --template <vue_file_path> --config <satori_config_path> [ --output <path> | --dev ]

OPTIONS:
-d|--dev Turn on Dev mode
-t|--template <path> The Vue template file path
-c|--config <path> The export satori configure file path
-o|--output <path> Target output SVG path

EXAMPLES:
x-satori --config "./satori.js" --template "./Template.vue" --dev
x-satori --config "./satori.js" --template "./Template.vue"
x-satori --config "./satori.js" --template "./Template.vue" -o image.svg
```

### Configure

- Extends Satori options and add Vue file props option

```mjs
import { defineSatoriConfig } from 'x-satori/vue'

export default defineSatoriConfig({
// ... Satori options
props: {
// ...Vue SFC props options
// title: "Hello world"
},
})
```
### Vue template file

- **Only the template syntax is used**, and props are only used for hint completion
- [→ Satori supports common CSS features](https://github.com/vercel/satori#css)
- [→ Tailwindcss documentation](https://tailwindcss.com/docs/customizing-colors)

```html
<script setup lang="ts">
const props = defineProps({
title: String,
})
</script>
<template>
<div class="w-full h-full flex text-white bg-blue-500 items-center justify-center">
<h1 :style="{ fontSize: '70px' }">
{{ title }} 👋
</h1>
</div>
</template>
```

Example: [`playground/`](./playground/)

<br></details>

<details>
<summary>Using ESM script</summary><br>

- Dependence: **Vue**

```mjs
import { defineSatoriConfig, satoriVue } from 'x-satori/vue'

function main() {
const _DIRNAME = typeof __dirname !== 'undefined'
? __dirname
: dirname(fileURLToPath(import.meta.url))
const _OUTPUT = resolve(_DIRNAME, './image/og.png')

const templateStr = await readFile(resolve(_DIRNAME, './Template.vue'), 'utf8')
const opt = defineSatoriConfig({
// ... Satori options
props: {
// ...Vue SFC props options
// title: "Hello world"
},
})
const strSVG = await satoriVue(opt, templateStr)
console.log(strSVG)
}
main()
```
Example: [`examples/run-esm-script`](./examples/run-esm-script/)
```sh
npm run gen:svg
npm run gen:png
```
</details>
## How it works
1. ▲ [Satori](https://github.com/vercel/satori) is an amazing library for generating SVG strings from pure HTML and CSS.
2. Unfortunately, it is built on top of React's JSX and expects ["React-elements-like objects"](https://github.com/vercel/satori#use-without-jsx).
3. Thank an other library [natemoo-re/satori-html](https://github.com/natemoo-re/satori-html) can to generate the necessary VDOM object from a string of HTML.
4. So the key is to **convert the Vue SFC file to an HTML string**, and here I used transform so that I could generate it via script (Only the template syntax is used)
- `@vue/compiler-sfc`: to parse Vue SFC file
- `vue - createSSRApp` and `vue/server-renderer`: transform HTML string
## Why developed
> My Weekend Pilot Project
1. This processing logic, **initially used in my Vite-SSG person website** [qbb.sh](https://github.com/Zhengqbbb/qbb.sh/blob/790c47026cb1baac34dee8642150ec1729fb0f39/package.json#L18), I prefer to run the script to generate e.g `tsx gen-og.mts` at my build time rather than the edge Fn
2. And personally, I think Vue SFC File would be better in expressing this SVG structure, but I only use the template syntax and props, and the css would use tailwindcss.
3. I did a experiment this weekend, using Vite HRM to improve DX, and developed a CLI so that I could run command and generated the SVG directly.
I'm happy that I finally finished this series of experiments and results this weekend. <br>
<table>
<tr>
<td>
<img alt="demo-img-1"src="https://user-images.githubusercontent.com/40693636/226387222-e2de688d-bbb6-41a2-9454-d10d8fd7784d.png">
</td>
<td>
<img alt="demo-img-2"src="https://user-images.githubusercontent.com/40693636/226387730-d639cc13-1bb2-42da-a2f3-3bbce12bb6d4.png">
</td>
</tr>
<tr>
<td>
<img alt="demo-img-3"src="https://user-images.githubusercontent.com/40693636/226387837-18ec7fde-b4a1-4248-8bab-6aed67ce8d38.png">
</td>
<td>
<img alt="demo-img-4"src="https://user-images.githubusercontent.com/40693636/226387925-57b58c6a-6677-44d4-a7a0-6939193704b3.png">
</td>
</tr>
<tr>
<td align="center" colspan="2">
ESM script source:
<a href="https://github.com/Zhengqbbb/qbb.sh/blob/main/build/node/og/main.mts">qbb.sh /node/og/main.mts</a>
</td>
</tr>
</table>
## Related Links
- [nuxt-og-image](https://github.com/harlan-zw/nuxt-og-image) - Nuxt or want to use edge Fn
## FAQ
<details>
<summary>CJS support ?</summary><br>
**Not supported**, waiting for upstream library [natemoo-re/ultrahtml](https://github.com/natemoo-re/ultrahtml/tree/main)
</details>
> I did it step by step according to the documentation of Vue and Vite, if you are interested, PR welcome 🤗
## LICENSE
MIT
Expand Down
2 changes: 1 addition & 1 deletion playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@
"@types/node": "^18.15.3",
"tsx": "^3.12.5",
"vite": "^4.2.0",
"x-satori": "0.0.5"
"x-satori": "0.1.0"
}
}
30 changes: 15 additions & 15 deletions src/command/help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,26 @@ export const generateHelp = (version: string, code = 0) => {
// prettier-ignore
console.log(
`${style.yellow('NAME:')}
${style.green('x-satori')} - use Vue files to generate SVG images using Satori
${style.green('x-satori')} - use Vue files to generate SVG images using Satori
${style.yellow('WEBSITE:')}
${style.underline('https://github.com/Zhengqbbb/x-satori')}
${style.yellow('WEBSITE:')}
${style.underline('https://github.com/Zhengqbbb/x-satori')}
${style.yellow('VERSION:')} ${version}
${style.yellow('VERSION:')} ${version}
${style.yellow('SYNOPSIS:')}
x-satori --template <vue_file_path> --config <satori_config_path> [ --output <path> | --dev ]
${style.yellow('SYNOPSIS:')}
x-satori --template <vue_file_path> --config <satori_config_path> [ --output <path> | --dev ]
${style.yellow('OPTIONS:')}
${style.cyan('-d|--dev')} ${style.red('Turn on Dev mode')}
${style.cyan('-t|--template <path>')} ${style.red('The Vue template file path')}
${style.cyan('-c|--config <path>')} ${style.red('The export satori configure file path')}
${style.cyan('-o|--output <path>')} ${style.red('Target output SVG path')}
${style.yellow('OPTIONS:')}
${style.cyan('-d|--dev')} ${style.red('Turn on Dev mode')}
${style.cyan('-t|--template <path>')} ${style.red('The Vue template file path')}
${style.cyan('-c|--config <path>')} ${style.red('The export satori configure file path')}
${style.cyan('-o|--output <path>')} ${style.red('Target output SVG path')}
${style.yellow('EXAMPLES:')}
${style.cyan('x-satori --config "./satori.js" --template "./Template.vue" --dev')}
${style.cyan('x-satori --config "./satori.js" --template "./Template.vue"')}
${style.cyan('x-satori --config "./satori.js" --template "./Template.vue" -o image.svg')}
${style.yellow('EXAMPLES:')}
${style.cyan('x-satori --config "./satori.js" --template "./Template.vue" --dev')}
${style.cyan('x-satori --config "./satori.js" --template "./Template.vue"')}
${style.cyan('x-satori --config "./satori.js" --template "./Template.vue" -o image.svg')}
`)
process.exit(code)
}

0 comments on commit a77f4ce

Please sign in to comment.