├── .nvmrc ├── .prettierignore ├── .eslintignore ├── assets └── og-image.png ├── test ├── snapshots │ ├── OgImage.test.js.snap │ └── OgImage.test.js.md ├── utils │ ├── directoriesConfig.js │ └── testConstructor.js ├── og-test.og.njk ├── sortObject.test.js ├── mergeOptions.test.js └── OgImage.test.js ├── src ├── utils │ ├── index.js │ ├── sortObject.js │ └── mergeOptions.js └── OgImage.js ├── .github ├── actions │ ├── lint │ │ └── action.yml │ ├── test │ │ └── action.yml │ ├── publint │ │ └── action.yml │ ├── example-build │ │ └── action.yml │ └── setup │ │ └── action.yml ├── dependabot.yml └── workflows │ ├── review.yml │ └── release.yml ├── .releaserc ├── .gitignore ├── example ├── example-page.njk ├── example-draft.njk ├── og-image.og.njk └── .eleventy.js ├── .prettierrc.js ├── .eslintrc.cjs ├── LICENSE ├── index.d.ts ├── package.json ├── .eleventy.js ├── README.md └── CHANGELOG.md /.nvmrc: -------------------------------------------------------------------------------- 1 | 24.11.0 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Build results 2 | /example/_site/ -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | !.eleventy.js 2 | index.d.ts 3 | .eslintrc.cjs 4 | -------------------------------------------------------------------------------- /assets/og-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KiwiKilian/eleventy-plugin-og-image/HEAD/assets/og-image.png -------------------------------------------------------------------------------- /test/snapshots/OgImage.test.js.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KiwiKilian/eleventy-plugin-og-image/HEAD/test/snapshots/OgImage.test.js.snap -------------------------------------------------------------------------------- /src/utils/index.js: -------------------------------------------------------------------------------- 1 | import { mergeOptions } from './mergeOptions.js'; 2 | import { sortObject } from './sortObject.js'; 3 | 4 | export { mergeOptions, sortObject }; 5 | -------------------------------------------------------------------------------- /test/utils/directoriesConfig.js: -------------------------------------------------------------------------------- 1 | /** @type {import('eleventy-plugin-og-image').DirectoriesConfig} */ 2 | export const directoriesConfig = { input: '.', includes: '_includes', data: '_data', output: '_site' }; 3 | -------------------------------------------------------------------------------- /.github/actions/lint/action.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | description: Run linting 3 | 4 | runs: 5 | using: composite 6 | steps: 7 | - uses: ./.github/actions/setup 8 | - run: npm run lint 9 | shell: bash 10 | -------------------------------------------------------------------------------- /.github/actions/test/action.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | description: Run ava tests 3 | 4 | runs: 5 | using: composite 6 | steps: 7 | - uses: ./.github/actions/setup 8 | - run: npm test 9 | shell: bash 10 | -------------------------------------------------------------------------------- /test/og-test.og.njk: -------------------------------------------------------------------------------- 1 | 9 | 10 |
11 | -------------------------------------------------------------------------------- /.github/actions/publint/action.yml: -------------------------------------------------------------------------------- 1 | name: Publint 2 | description: Run packaging linting 3 | 4 | runs: 5 | using: composite 6 | steps: 7 | - uses: ./.github/actions/setup 8 | - run: npx publint --strict 9 | shell: bash 10 | -------------------------------------------------------------------------------- /.github/actions/example-build/action.yml: -------------------------------------------------------------------------------- 1 | name: Example Build 2 | description: Build the example project 3 | 4 | runs: 5 | using: composite 6 | steps: 7 | - uses: ./.github/actions/setup 8 | - run: npm run example:build 9 | shell: bash 10 | -------------------------------------------------------------------------------- /.releaserc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "@semantic-release/commit-analyzer", 4 | "@semantic-release/release-notes-generator", 5 | "@semantic-release/changelog", 6 | "@semantic-release/npm", 7 | "@semantic-release/github", 8 | "@semantic-release/git" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build results 2 | /example/_site/ 3 | /example/.cache/ 4 | 5 | # IDEs 6 | /.idea/ 7 | /.vscode/ 8 | 9 | # Package managers 10 | /node_modules/ 11 | .npm 12 | 13 | # Logs 14 | logs 15 | *.log 16 | npm-debug.log* 17 | yarn-debug.log* 18 | yarn-error.log* 19 | 20 | # Artefacts 21 | .DS_Store 22 | -------------------------------------------------------------------------------- /.github/actions/setup/action.yml: -------------------------------------------------------------------------------- 1 | name: Setup 2 | description: Setup a Node.js and install dependencies 3 | 4 | runs: 5 | using: composite 6 | steps: 7 | - uses: actions/setup-node@v6 8 | with: 9 | cache: npm 10 | node-version-file: '.nvmrc' 11 | - run: npm ci 12 | shell: bash 13 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: / 5 | schedule: 6 | interval: weekly 7 | assignees: [KiwiKilian] 8 | 9 | - package-ecosystem: github-actions 10 | directories: [/, ".github/actions/**"] 11 | schedule: 12 | interval: weekly 13 | assignees: [KiwiKilian] 14 | -------------------------------------------------------------------------------- /test/utils/testConstructor.js: -------------------------------------------------------------------------------- 1 | import { directoriesConfig } from './directoriesConfig.js'; 2 | import { mergeOptions } from '../../src/utils/index.js'; 3 | 4 | export const testConstructor = { 5 | inputPath: './test/og-test.og.njk', 6 | data: undefined, 7 | options: mergeOptions({ 8 | directoriesConfig, 9 | }), 10 | templateConfig: undefined, 11 | }; 12 | -------------------------------------------------------------------------------- /example/example-page.njk: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Eleventy Plugin OG Image 6 | 7 | 8 | {% ogImage "./og-image.og.njk", { title: "Hello World! 👋" } %} 9 | 10 | 11 | 12 |

Eleventy Plugin OG Image

13 | 14 | 15 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | import prettierConfig from '@kiwikilian/prettier-config' with { type: 'json' }; 2 | 3 | /** @type {import('prettier').Config} */ 4 | export default { 5 | ...prettierConfig, 6 | plugins: ['prettier-plugin-jsdoc', 'prettier-plugin-jinja-template'], 7 | overrides: [ 8 | { 9 | files: ['**/*.njk'], 10 | options: { 11 | parser: 'jinja-template', 12 | }, 13 | }, 14 | ], 15 | }; 16 | -------------------------------------------------------------------------------- /src/utils/sortObject.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Sorts an object recursively 3 | * 4 | * @param {object} unordered 5 | * @returns {object} 6 | */ 7 | export function sortObject(unordered) { 8 | const keys = Object.keys(unordered).sort(); 9 | 10 | return keys.reduce((object, key) => { 11 | object[key] = typeof unordered[key] === 'object' ? sortObject(unordered[key]) : unordered[key]; 12 | 13 | return object; 14 | }, {}); 15 | } 16 | -------------------------------------------------------------------------------- /example/example-draft.njk: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: false 3 | --- 4 | 5 | 6 | 7 | 8 | 9 | Eleventy Plugin OG Image 10 | 11 | 12 | {% ogImage "./og-image.og.njk", { title: "This is a draft. 📝" } %} 13 | 14 | 15 | 16 |

Eleventy Plugin OG Image

17 | 18 | 19 | -------------------------------------------------------------------------------- /test/sortObject.test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import { sortObject } from '../src/utils/index.js'; 3 | 4 | test('sorts keys', (t) => { 5 | t.is( 6 | JSON.stringify({ 7 | a: 'a', 8 | b: { 9 | a: 'a', 10 | b: 'b', 11 | }, 12 | }), 13 | JSON.stringify( 14 | sortObject({ 15 | b: { 16 | b: 'b', 17 | a: 'a', 18 | }, 19 | a: 'a', 20 | }), 21 | ), 22 | ); 23 | }); 24 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | require('@kiwikilian/eslint-config/patch/modern-module-resolution'); 2 | 3 | module.exports = { 4 | extends: ['@kiwikilian/eslint-config/profile/node'], 5 | 6 | parserOptions: { 7 | ecmaVersion: 'latest', 8 | sourceType: 'module', 9 | }, 10 | 11 | rules: { 12 | 'import/extensions': [ 13 | 'error', 14 | { 15 | js: 'ignorePackages', 16 | }, 17 | ], 18 | 'import/no-extraneous-dependencies': [ 19 | 'error', 20 | { devDependencies: ['./example/**', './example/.eleventy.js', './test/**'] }, 21 | ], 22 | }, 23 | 24 | overrides: [ 25 | { 26 | files: '.eleventy.js', 27 | rules: { 28 | 'func-names': ['off'], 29 | 'import/no-default-export': ['off'], 30 | }, 31 | }, 32 | { 33 | files: './test/**', 34 | rules: { 35 | 'import/no-unresolved': ['off'], 36 | }, 37 | }, 38 | ], 39 | }; 40 | -------------------------------------------------------------------------------- /.github/workflows/review.yml: -------------------------------------------------------------------------------- 1 | name: Review 2 | 3 | on: 4 | pull_request: 5 | 6 | jobs: 7 | setup: 8 | name: Setup 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v6 12 | - uses: ./.github/actions/setup 13 | lint: 14 | name: Lint 15 | needs: setup 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v6 19 | - uses: ./.github/actions/lint 20 | publint: 21 | name: Publint 22 | needs: setup 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v6 26 | - uses: ./.github/actions/publint 27 | test: 28 | name: Test 29 | needs: setup 30 | runs-on: ubuntu-latest 31 | steps: 32 | - uses: actions/checkout@v6 33 | - uses: ./.github/actions/test 34 | example-build: 35 | name: Example Build 36 | needs: setup 37 | runs-on: ubuntu-latest 38 | steps: 39 | - uses: actions/checkout@v6 40 | - uses: ./.github/actions/example-build 41 | -------------------------------------------------------------------------------- /example/og-image.og.njk: -------------------------------------------------------------------------------- 1 | 36 | 37 |
38 |

{{ title }}

39 |
40 |

{% testShortcode %}

41 |
42 |
43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Kilian Finger 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /test/mergeOptions.test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import { mergeOptions } from '../src/utils/index.js'; 3 | import { directoriesConfig } from './utils/directoriesConfig.js'; 4 | 5 | test('works without pluginOptions', (t) => { 6 | const { satoriOptions, sharpOptions, ...options } = mergeOptions({ directoriesConfig }); 7 | 8 | t.truthy(options); 9 | t.truthy(satoriOptions); 10 | }); 11 | 12 | test('creates default options', (t) => { 13 | const { satoriOptions, sharpOptions, ...options } = mergeOptions({ directoriesConfig }); 14 | 15 | t.is(options.outputFileExtension, 'png'); 16 | t.is(options.inputFileGlob, '**/*.og.*'); 17 | 18 | t.is(satoriOptions.width, 1200); 19 | t.is(satoriOptions.height, 630); 20 | 21 | t.falsy(sharpOptions); 22 | }); 23 | 24 | test('changes previewDir and urlPath if only outputDir is set', (t) => { 25 | const CUSTOM_OUTPUT_DIR = 'custom-output'; 26 | 27 | const { outputDir, previewDir, urlPath } = mergeOptions({ 28 | directoriesConfig, 29 | pluginOptions: { outputDir: CUSTOM_OUTPUT_DIR }, 30 | }); 31 | 32 | t.is(outputDir, `_site/${CUSTOM_OUTPUT_DIR}`); 33 | t.is(previewDir, `_site/${CUSTOM_OUTPUT_DIR}/preview`); 34 | t.is(urlPath, CUSTOM_OUTPUT_DIR); 35 | }); 36 | -------------------------------------------------------------------------------- /test/snapshots/OgImage.test.js.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `test/OgImage.test.js` 2 | 3 | The actual snapshot is saved in `OgImage.test.js.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## html returns html string 8 | 9 | > Snapshot 1 10 | 11 | `␊ 19 | ␊ 20 |
␊ 21 | ` 22 | 23 | ## svg returns svg string 24 | 25 | > Snapshot 1 26 | 27 | '' 28 | -------------------------------------------------------------------------------- /src/utils/mergeOptions.js: -------------------------------------------------------------------------------- 1 | import path from 'node:path'; 2 | 3 | /** 4 | * Merges the plugin options with defaults 5 | * 6 | * @param {DirectoriesConfig} [directoriesConfig] 7 | * @param {EleventyPluginOgImageOptions} [pluginOptions] 8 | * @returns {EleventyPluginOgImageMergedOptions} 9 | */ 10 | export function mergeOptions({ directoriesConfig, pluginOptions }) { 11 | const { outputDir, previewDir, urlPath, OgImage, satoriOptions, ...options } = pluginOptions || {}; 12 | 13 | const eleventyOutput = directoriesConfig ? directoriesConfig.output : ''; 14 | const joinedOutputDir = path.join(eleventyOutput, outputDir || 'og-images'); 15 | 16 | return { 17 | inputFileGlob: '**/*.og.*', 18 | hashLength: 8, 19 | outputFileExtension: 'png', 20 | outputDir: joinedOutputDir, 21 | previewMode: 'auto', 22 | previewDir: path.join(...(previewDir ? [eleventyOutput, previewDir] : [joinedOutputDir, 'preview'])), 23 | urlPath: urlPath || outputDir || 'og-images', 24 | 25 | /** @param {OgImage} ogImage */ 26 | outputFileSlug: (ogImage) => ogImage.hash(), 27 | 28 | /** @param {OgImage} ogImage */ 29 | shortcodeOutput: async (ogImage) => ``, 30 | 31 | ...options, 32 | 33 | satoriOptions: { 34 | width: 1200, 35 | height: 630, 36 | fonts: [], 37 | ...satoriOptions, 38 | }, 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - next 8 | - next-major 9 | - alpha 10 | - beta 11 | 12 | jobs: 13 | setup: 14 | name: Setup 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v6 18 | - uses: ./.github/actions/setup 19 | lint: 20 | name: Lint 21 | needs: setup 22 | runs-on: ubuntu-latest 23 | steps: 24 | - uses: actions/checkout@v6 25 | - uses: ./.github/actions/lint 26 | test: 27 | name: Test 28 | needs: setup 29 | runs-on: ubuntu-latest 30 | steps: 31 | - uses: actions/checkout@v6 32 | - uses: ./.github/actions/test 33 | example-build: 34 | name: Example Build 35 | needs: setup 36 | runs-on: ubuntu-latest 37 | steps: 38 | - uses: actions/checkout@v6 39 | - uses: ./.github/actions/example-build 40 | release: 41 | name: Release 42 | needs: [lint, test, example-build] 43 | runs-on: ubuntu-latest 44 | permissions: 45 | contents: write 46 | issues: write 47 | pull-requests: write 48 | id-token: write 49 | steps: 50 | - uses: actions/checkout@v6 51 | - uses: ./.github/actions/setup 52 | - name: Audit Signatures 53 | run: npm audit signatures 54 | - name: Release 55 | env: 56 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 57 | run: npx semantic-release 58 | -------------------------------------------------------------------------------- /example/.eleventy.js: -------------------------------------------------------------------------------- 1 | import { promises as fs } from 'node:fs'; 2 | import module from 'node:module'; 3 | import twemoji from 'twemoji'; 4 | import EleventyPluginOgImage from '../.eleventy.js'; 5 | 6 | const require = module.createRequire(import.meta.url); 7 | 8 | /** @param {import('@11ty/eleventy/src/UserConfig').default} eleventyConfig */ 9 | export default async function (eleventyConfig) { 10 | eleventyConfig.addShortcode('testShortcode', () => 'Eleventy Plugin OG Image'); 11 | 12 | /** @type {import('eleventy-plugin-og-image').EleventyPluginOgImageOptions} */ 13 | const eleventyPluginOgImageOptions = { 14 | satoriOptions: { 15 | fonts: [ 16 | { 17 | name: 'Inter', 18 | data: await fs.readFile(require.resolve('@fontsource/inter/files/inter-latin-700-normal.woff')), 19 | weight: 700, 20 | style: 'normal', 21 | }, 22 | ], 23 | loadAdditionalAsset: async (languageCode, segment) => { 24 | if (languageCode === 'emoji') { 25 | const emojiUrl = `https://cdnjs.cloudflare.com/ajax/libs/twemoji/14.0.2/svg/${twemoji.convert.toCodePoint( 26 | segment, 27 | )}.svg`; 28 | const emojiSvg = await (await fetch(emojiUrl)).text(); 29 | 30 | return `data:image/svg+xml;base64,${Buffer.from(emojiSvg).toString('base64')}`; 31 | } 32 | 33 | return segment; 34 | }, 35 | }, 36 | }; 37 | 38 | eleventyConfig.addPlugin(EleventyPluginOgImage, eleventyPluginOgImageOptions); 39 | } 40 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | import { SatoriOptions } from 'satori'; 2 | import { FormatEnum, Sharp } from 'sharp'; 3 | 4 | export interface OgImage { 5 | inputPath: string; 6 | 7 | data: Record; 8 | 9 | options: EleventyPluginOgImageMergedOptions; 10 | 11 | templateConfig: typeof import('@11ty/eleventy/src/TemplateConfig').default; 12 | 13 | results: { 14 | html?: string; 15 | svg?: string; 16 | pngBuffer?: Buffer; 17 | }; 18 | 19 | html(): Promise; 20 | 21 | svg(): Promise; 22 | 23 | pngBuffer(): Promise; 24 | 25 | render(): Promise; 26 | 27 | hash(): Promise; 28 | 29 | outputFileSlug(): Promise; 30 | 31 | outputFileName(): Promise; 32 | 33 | outputFilePath(): Promise; 34 | 35 | outputUrl(): Promise; 36 | 37 | cacheFilePath(): Promise; 38 | 39 | shortcodeOutput(): Promise; 40 | 41 | previewFilePath(): string; 42 | 43 | previewHtml(): Promise; 44 | } 45 | 46 | type DirectoriesConfig = { 47 | input: string; 48 | includes: string; 49 | data: string; 50 | layouts?: string; 51 | output: string; 52 | }; 53 | 54 | type SharpFormatOptions = Parameters[1]; 55 | 56 | type EleventyPluginOgImageOptions = { 57 | inputFileGlob?: string; 58 | hashLength?: number; 59 | outputFileExtension?: keyof FormatEnum; 60 | outputDir?: string; 61 | previewMode?: 'auto' | boolean; 62 | previewDir?: string; 63 | urlPath?: string; 64 | 65 | outputFileSlug?(ogImage: OgImage): Promise; 66 | shortcodeOutput?(ogImage: OgImage): Promise; 67 | 68 | OgImage?: OgImage; 69 | 70 | satoriOptions?: Partial; 71 | sharpOptions?: SharpFormatOptions; 72 | }; 73 | 74 | type EleventyPluginOgImageMergedOptions = Omit< 75 | Required, 76 | 'OgImage' | 'satoriOptions' | 'sharpOptions' 77 | > & 78 | Pick & { 79 | satoriOptions: SatoriOptions & { width: number; height: number }; 80 | }; 81 | 82 | export { EleventyPluginOgImageOptions, EleventyPluginOgImageMergedOptions, DirectoriesConfig }; 83 | 84 | export default function ( 85 | eleventyConfig: typeof import('@11ty/eleventy/src/UserConfig').default, 86 | pluginOptions?: EleventyPluginOgImageOptions, 87 | ): Promise; 88 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eleventy-plugin-og-image", 3 | "version": "4.2.1", 4 | "description": "A plugin to create Open Graph Images from JSX for Eleventy.", 5 | "author": { 6 | "name": "Kilian Finger", 7 | "email": "npm@kilianfinger.com", 8 | "url": "https://www.kilianfinger.com/" 9 | }, 10 | "license": "MIT", 11 | "keywords": [ 12 | "11ty", 13 | "eleventy", 14 | "eleventy-plugin", 15 | "og:image" 16 | ], 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/KiwiKilian/eleventy-plugin-og-image.git" 20 | }, 21 | "bugs": { 22 | "url": "https://github.com/KiwiKilian/eleventy-plugin-og-image/issues" 23 | }, 24 | "homepage": "https://github.com/KiwiKilian/eleventy-plugin-og-image#readme", 25 | "main": "./.eleventy.js", 26 | "type": "module", 27 | "exports": { 28 | ".": { 29 | "types": "./index.d.ts", 30 | "default": "./.eleventy.js" 31 | }, 32 | "./package.json": "./package.json", 33 | "./og-image": "./src/OgImage.js", 34 | "./utils": "./src/utils/index.js" 35 | }, 36 | "types": "./index.d.ts", 37 | "files": [ 38 | ".eleventy.js", 39 | "index.d.ts", 40 | "src" 41 | ], 42 | "publishConfig": { 43 | "provenance": true 44 | }, 45 | "scripts": { 46 | "semantic-release": "semantic-release", 47 | "test": "ava test/**/*.test.js", 48 | "lint": "eslint .", 49 | "prettier": "prettier --write .", 50 | "example": "npx @11ty/eleventy --config=example/.eleventy.js --input=example --output=example/_site", 51 | "example:start": "npm run example -- --serve", 52 | "example:build": "npm run example", 53 | "example:clean": "rimraf ./example/_site" 54 | }, 55 | "engines": { 56 | "node": ">=18" 57 | }, 58 | "11ty": { 59 | "compatibility": ">=3.0.0" 60 | }, 61 | "peerDependencies": { 62 | "@11ty/eleventy": ">=3.0.0" 63 | }, 64 | "dependencies": { 65 | "@11ty/eleventy-utils": "^2.0.1", 66 | "@resvg/resvg-js": "^2.6.2", 67 | "satori": "^0.18.3", 68 | "satori-html": "^0.3.2", 69 | "sharp": "^0.34.1" 70 | }, 71 | "devDependencies": { 72 | "@11ty/eleventy": "3.1.2", 73 | "@fontsource/inter": "5.2.8", 74 | "@kiwikilian/eslint-config": "1.1.0", 75 | "@kiwikilian/prettier-config": "1.0.1", 76 | "@semantic-release/changelog": "6.0.3", 77 | "@semantic-release/git": "10.0.1", 78 | "ava": "6.4.1", 79 | "eslint": "8.57.1", 80 | "prettier": "3.6.2", 81 | "prettier-plugin-jinja-template": "2.1.0", 82 | "prettier-plugin-jsdoc": "1.7.0", 83 | "semantic-release": "25.0.2", 84 | "twemoji": "14.0.2" 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /test/OgImage.test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import sharp from 'sharp'; 3 | import { OgImage } from '../src/OgImage.js'; 4 | import { testConstructor } from './utils/testConstructor.js'; 5 | 6 | test('html returns html string', async (t) => { 7 | const ogImage = new OgImage(testConstructor); 8 | 9 | const html = await ogImage.html(); 10 | 11 | t.snapshot(html); 12 | 13 | t.is(typeof html, 'string'); 14 | t.regex(html, /
<\/div>\n$/); 15 | }); 16 | 17 | test('svg returns svg string', async (t) => { 18 | const ogImage = new OgImage(testConstructor); 19 | 20 | const svg = await ogImage.svg(); 21 | 22 | t.snapshot(svg); 23 | 24 | t.is(typeof svg, 'string'); 25 | t.regex(svg, /^ { 29 | const ogImage = new OgImage(testConstructor); 30 | 31 | const pngBuffer = await ogImage.pngBuffer(); 32 | 33 | t.true(pngBuffer instanceof Buffer); 34 | }); 35 | 36 | test('render returns sharp object', async (t) => { 37 | const ogImage = new OgImage(testConstructor); 38 | 39 | const sharpRender = await ogImage.render(); 40 | 41 | t.true(sharpRender instanceof sharp); 42 | }); 43 | 44 | test('respects dimensions', async (t) => { 45 | const ogImage = new OgImage({ 46 | ...testConstructor, 47 | options: { 48 | ...testConstructor.options, 49 | satoriOptions: { width: 120, height: 63 }, 50 | }, 51 | }); 52 | 53 | const { width, height } = await (await ogImage.render()).metadata(); 54 | 55 | t.is(width, 120); 56 | t.is(height, 63); 57 | }); 58 | 59 | test('returns cached result', async (t) => { 60 | const ogImage = new OgImage(testConstructor); 61 | 62 | const firstPngBuffer = await ogImage.pngBuffer(); 63 | const secondPngBuffer = await ogImage.pngBuffer(); 64 | 65 | t.is(firstPngBuffer, secondPngBuffer); 66 | }); 67 | 68 | const PAGE_URL = 'example/url'; 69 | const HASH = '759d60a8'; 70 | 71 | test('hash returns hash', async (t) => { 72 | const ogImage = new OgImage(testConstructor); 73 | 74 | const hash = await ogImage.hash(); 75 | 76 | t.is(hash, HASH); 77 | }); 78 | 79 | test('outputFileSlug returns hash', async (t) => { 80 | const ogImage = new OgImage({ ...testConstructor, data: { page: { url: PAGE_URL } } }); 81 | 82 | t.is(await ogImage.outputFileSlug(), HASH); 83 | }); 84 | 85 | test('outputFileName returns file name', async (t) => { 86 | const ogImage = new OgImage(testConstructor); 87 | 88 | t.is(await ogImage.outputFileName(), `${HASH}.png`); 89 | }); 90 | 91 | test('outputFilePath returns file path', async (t) => { 92 | const ogImage = new OgImage(testConstructor); 93 | 94 | t.is(await ogImage.outputFilePath(), `./_site/og-images/${HASH}.png`); 95 | }); 96 | 97 | test('previewFilePath returns path', (t) => { 98 | const ogImage = new OgImage({ ...testConstructor, data: { page: { url: PAGE_URL } } }); 99 | 100 | t.is(ogImage.previewFilePath(), `./_site/og-images/preview/${PAGE_URL}.png`); 101 | }); 102 | -------------------------------------------------------------------------------- /.eleventy.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-empty */ 2 | import { promises as fs } from 'node:fs'; 3 | import path from 'node:path'; 4 | import { TemplatePath } from '@11ty/eleventy-utils'; 5 | import { mergeOptions } from './src/utils/index.js'; 6 | import { OgImage } from './src/OgImage.js'; 7 | 8 | /** 9 | * @param {import('@11ty/eleventy/src/UserConfig').default} eleventyConfig 10 | * @param {EleventyPluginOgImageOptions} pluginOptions 11 | */ 12 | export default async function (eleventyConfig, pluginOptions) { 13 | /** @type {DirectoriesConfig} */ 14 | let directoriesConfig; 15 | 16 | /** @type {EleventyPluginOgImageMergedOptions} */ 17 | let mergedOptions; 18 | 19 | // Until https://github.com/11ty/eleventy/issues/2729 is fixed 20 | eleventyConfig.on('eleventy.directories', (dir) => { 21 | directoriesConfig = dir; 22 | mergedOptions = mergeOptions({ directoriesConfig, pluginOptions }); 23 | }); 24 | 25 | /** @type {import('@11ty/eleventy/src/TemplateConfig').default} */ 26 | let templateConfig; 27 | 28 | eleventyConfig.on('eleventy.config', (newTemplateConfig) => { 29 | templateConfig = newTemplateConfig; 30 | }); 31 | 32 | /** @type {boolean} */ 33 | let previewEnabled; 34 | 35 | eleventyConfig.on('eleventy.before', async ({ runMode }) => { 36 | try { 37 | await fs.mkdir(mergedOptions.outputDir, { recursive: true }); 38 | } catch {} 39 | 40 | previewEnabled = 41 | mergedOptions.previewMode === 'auto' ? ['watch', 'serve'].includes(runMode) : mergedOptions.previewMode; 42 | 43 | if (previewEnabled) { 44 | try { 45 | await fs.mkdir(mergedOptions.previewDir, { recursive: true }); 46 | } catch {} 47 | } else { 48 | try { 49 | await fs.rm(mergedOptions.previewDir, { recursive: true, force: true }); 50 | } catch {} 51 | } 52 | }); 53 | 54 | eleventyConfig.ignores.add(mergeOptions({ pluginOptions }).inputFileGlob); 55 | 56 | eleventyConfig.addAsyncShortcode( 57 | 'ogImage', 58 | /** 59 | * @param {string} shortcodeInputPath 60 | * @param {Record} [data] 61 | * @returns {Promise} 62 | */ 63 | async function ogImageShortcode(shortcodeInputPath, data) { 64 | if (this.page.url === false) { 65 | return null; 66 | } 67 | 68 | const { satoriOptions, sharpOptions, ...options } = mergedOptions; 69 | 70 | const joinedInputPath = TemplatePath.standardizeFilePath(path.join(directoriesConfig.input, shortcodeInputPath)); 71 | 72 | try { 73 | await fs.access(joinedInputPath); 74 | } catch { 75 | throw new Error(`Could not find file for the \`ogImage\` shortcode, looking for: ${joinedInputPath}`); 76 | } 77 | 78 | const ogImage = new (pluginOptions.OgImage || OgImage)({ 79 | inputPath: joinedInputPath, 80 | data: { 81 | page: this.page, 82 | eleventy: this.eleventy, 83 | eleventyPluginOgImage: { 84 | inputPath: joinedInputPath, 85 | width: satoriOptions.width, 86 | height: satoriOptions.height, 87 | outputFileExtension: options.outputFileExtension, 88 | }, 89 | ...data, 90 | }, 91 | options: mergedOptions, 92 | templateConfig, 93 | }); 94 | 95 | const outputFilePath = await ogImage.outputFilePath(); 96 | const cacheFilePath = await ogImage.cacheFilePath(); 97 | 98 | if (cacheFilePath !== outputFilePath) { 99 | try { 100 | await fs.copyFile(cacheFilePath, outputFilePath); 101 | } catch {} 102 | } 103 | 104 | try { 105 | await fs.access(outputFilePath); 106 | } catch { 107 | const image = await ogImage.render(); 108 | 109 | await image.toFile(outputFilePath); 110 | 111 | eleventyConfig.logger.log( 112 | `Writing ${TemplatePath.stripLeadingDotSlash(outputFilePath)} from ${joinedInputPath}`, 113 | ); 114 | } 115 | 116 | if (previewEnabled) { 117 | const previewFilePath = ogImage.previewFilePath(); 118 | 119 | try { 120 | await fs.mkdir(path.dirname(previewFilePath), { recursive: true }); 121 | } catch {} 122 | 123 | await fs.copyFile(outputFilePath, previewFilePath); 124 | await fs.writeFile(`${previewFilePath}.html`, await ogImage.previewHtml()); 125 | } 126 | 127 | return ogImage.shortcodeOutput(); 128 | }, 129 | ); 130 | } 131 | -------------------------------------------------------------------------------- /src/OgImage.js: -------------------------------------------------------------------------------- 1 | import { RenderPlugin } from '@11ty/eleventy'; 2 | /* eslint-disable import/no-unresolved */ 3 | // https://github.com/import-js/eslint-plugin-import/issues/2132 4 | import { html as htmlToSatori } from 'satori-html'; 5 | /* eslint-enable import/no-unresolved */ 6 | import satori from 'satori'; 7 | import { Resvg } from '@resvg/resvg-js'; 8 | import sharp from 'sharp'; 9 | import crypto from 'node:crypto'; 10 | import { TemplatePath } from '@11ty/eleventy-utils'; 11 | import path from 'node:path'; 12 | import url from 'node:url'; 13 | import { sortObject } from './utils/index.js'; 14 | 15 | /** @implements {import('eleventy-plugin-og-image').OgImage} */ 16 | export class OgImage { 17 | /** @type {string} */ 18 | inputPath; 19 | 20 | /** @type {Record} */ 21 | data; 22 | 23 | /** @type {import('eleventy-plugin-og-image').EleventyPluginOgImageMergedOptions} */ 24 | options; 25 | 26 | /** @type {import('@11ty/eleventy/src/TemplateConfig').default} */ 27 | templateConfig; 28 | 29 | /** 30 | * @private 31 | * @type {{ html?: string; svg?: string; pngBuffer?: Buffer }} 32 | */ 33 | results = { 34 | html: undefined, 35 | svg: undefined, 36 | pngBuffer: undefined, 37 | }; 38 | 39 | /** 40 | * @param {string} inputPath 41 | * @param {Record} data 42 | * @param {import('eleventy-plugin-og-image').EleventyPluginOgImageMergedOptions} options 43 | * @param {import('@11ty/eleventy/src/TemplateConfig').default} templateConfig 44 | */ 45 | constructor({ inputPath, data, options, templateConfig }) { 46 | this.inputPath = inputPath; 47 | this.data = data; 48 | this.options = options; 49 | this.templateConfig = templateConfig; 50 | } 51 | 52 | /** @returns {Promise} */ 53 | async html() { 54 | if (!this.results.html) { 55 | this.results.html = await ( 56 | await RenderPlugin.File(this.inputPath, { templateConfig: this.templateConfig }) 57 | )(this.data); 58 | } 59 | 60 | return this.results.html; 61 | } 62 | 63 | /** @returns {Promise} */ 64 | async svg() { 65 | if (!this.results.svg) { 66 | this.results.svg = await satori(htmlToSatori(await this.html()), this.options.satoriOptions); 67 | } 68 | 69 | return this.results.svg; 70 | } 71 | 72 | /** @returns {Promise} */ 73 | async pngBuffer() { 74 | if (!this.results.pngBuffer) { 75 | this.results.pngBuffer = await new Resvg(await this.svg(), { font: { loadSystemFonts: false } }).render().asPng(); 76 | } 77 | 78 | return this.results.pngBuffer; 79 | } 80 | 81 | /** 82 | * Returns the configured output format 83 | * 84 | * @returns {Promise} 85 | */ 86 | async render() { 87 | return sharp(await this.pngBuffer()).toFormat(this.options.outputFileExtension, this.options.sharpOptions); 88 | } 89 | 90 | /** @returns {Promise} */ 91 | async hash() { 92 | const hash = crypto.createHash('sha256'); 93 | 94 | hash.update(await this.html()); 95 | hash.update(JSON.stringify(sortObject(this.options.satoriOptions || {}))); 96 | hash.update(JSON.stringify(sortObject(this.options.sharpOptions || {}))); 97 | 98 | return hash.digest('hex').substring(0, this.options.hashLength); 99 | } 100 | 101 | /** @returns {Promise} */ 102 | async outputFileSlug() { 103 | return this.options.outputFileSlug(this); 104 | } 105 | 106 | /** @returns {Promise} */ 107 | async outputFileName() { 108 | return `${await this.outputFileSlug()}.${this.options.outputFileExtension}`; 109 | } 110 | 111 | /** @returns {Promise} */ 112 | async outputFilePath() { 113 | return TemplatePath.standardizeFilePath(path.join(this.options.outputDir, await this.outputFileName())); 114 | } 115 | 116 | /** @returns {Promise} */ 117 | async outputUrl() { 118 | const fileUrl = new url.URL('file://'); 119 | fileUrl.pathname = path.join(this.options.urlPath, await this.outputFileName()); 120 | 121 | return fileUrl.pathname; 122 | } 123 | 124 | /** @returns {Promise} */ 125 | async cacheFilePath() { 126 | return this.outputFilePath(); 127 | } 128 | 129 | /** @returns {Promise} */ 130 | async shortcodeOutput() { 131 | return this.options.shortcodeOutput(this); 132 | } 133 | 134 | /** @returns {string} */ 135 | previewFilePath() { 136 | return TemplatePath.standardizeFilePath( 137 | path.join( 138 | this.options.previewDir, 139 | `${this.data.page.url.replace(/\/$/, '') || 'index'}.${this.options.outputFileExtension}`, 140 | ), 141 | ); 142 | } 143 | 144 | /** @returns {Promise} */ 145 | async previewHtml() { 146 | return ` 147 | 148 | OG Image: ${this.data.page.url} 149 | 150 | 164 | 165 | 166 |
${await this.html()}
167 | ${await this.svg()} 168 | OG Image: ${this.data.page.url} 173 | 174 | 175 | `; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Eleventy Plugin OG Image [![npm](https://img.shields.io/npm/v/eleventy-plugin-og-image?color=blue)](https://www.npmjs.com/package/eleventy-plugin-og-image) 2 | 3 | This plugin helps to create Open Graph images in [Eleventy](https://www.11ty.dev/) using HTML[^1] within any supported template language and CSS[^2] via [satori](https://github.com/vercel/satori). No headless browser will be harmed 😉. 4 | 5 | ## Usage 6 | 7 | Install the package: 8 | 9 | ```shell 10 | npm install eleventy-plugin-og-image --save-dev 11 | ``` 12 | 13 | ### ESM 14 | 15 | It's preferred to use this plugin within ESM Eleventy projects. Read more about ESM vs CommonJS on the [Eleventy documentation](https://www.11ty.dev/docs/cjs-esm/). 16 | 17 | ```js 18 | import EleventyPluginOgImage from 'eleventy-plugin-og-image'; 19 | 20 | export default async function (eleventyConfig) { 21 | eleventyConfig.addPlugin(EleventyPluginOgImage, { 22 | satoriOptions: { 23 | fonts: [ 24 | { 25 | name: 'Inter', 26 | data: fs.readFileSync('../path/to/font-file/inter.woff'), 27 | weight: 700, 28 | style: 'normal', 29 | }, 30 | ], 31 | }, 32 | }); 33 | } 34 | ``` 35 | 36 | ### CommonJS 37 | 38 | > [!NOTE] 39 | > This plugin is written in ESM, therefore `require` is not possible. If the .eleventy.js config uses CommonJS, switch to async and create a dynamic import as shown below. 40 | 41 | ```js 42 | module.exports = async function (eleventyConfig) { 43 | const EleventyPluginOgImage = (await import('eleventy-plugin-og-image')).default; 44 | 45 | eleventyConfig.addPlugin(EleventyPluginOgImage, { 46 | // See above for example config 47 | }); 48 | }; 49 | ``` 50 | 51 | ### Add a Template 52 | 53 | Create an OG-image-template anywhere in the input directory. Use only the supported HTML elements[^1] and CSS properties[^2]. CSS in ` 72 | 73 |
74 |

{{ title }}

75 |
76 | ``` 77 | 78 | Call the `ogImage` shortcode inside the `` in a template or layout. The first argument is the `filePath` of the OG-image-template (required, relative to the Eleventy input directory). The second argument is for `data` (optional). Usage example in Nunjucks, e.g. `example-page.njk`: 79 | 80 | ```njk 81 | {% ogImage "./og-image.og.njk", { title: "Hello World!" } %} 82 | ``` 83 | 84 | ### Result 85 | 86 | Generated OG image `_site/og-images/s0m3h4sh.png`: 87 | 88 | ![Generated OG image](./assets/og-image.png) 89 | 90 | HTML output generated by the shortcode into `_site/example-page/index.html` (can be modified via the `shortcodeOutput` option): 91 | 92 | ```html 93 | 94 | ``` 95 | 96 | For applied usage see the [example](./example). 97 | 98 | > [!TIP] 99 | > The template language of the page and OG-image-template can be mixed or matched. 100 | 101 | ## Configuration 102 | 103 | The following options can be passed when adding the plugin: 104 | 105 | | Property | Type | Default | | 106 | | --------------------- | -------------------------------------------------------------------------------------------------------- |-------------------------------------------|--------------------------------------------------------------------------------------------| 107 | | `inputFileGlob` | `glob` | `**/*.og.*` | This must match the OG-image-templates to prevent HTML compilation. | 108 | | `hashLength` | `number` | `8` | | 109 | | `outputFileExtension` | [sharp output file formats](https://sharp.pixelplumbing.com/api-output#toformat) | `png` | | 110 | | `outputDir` | `string` | `og-images` | Directory into which OG images will be emitted. Relative to eleventy `output`. | 111 | | `previewMode` | `auto \| boolean` | `auto` | Enable/disable preview mode. | 112 | | `previewDir` | `string` | `${outputDir}/preview` | Directory used for preview during `watch` or `serve`. Relative to eleventy `output`. | 113 | | `urlPath` | `string` | `${outputDir}` | URL-prefix which will be used in returned meta-tags. | 114 | | `outputFileSlug` | `function` | [See source](src/utils/mergeOptions.js) | Generation of the output file slug, must be url safe and exclude the file extension. | 115 | | `shortcodeOutput` | `function` | [See source](src/utils/mergeOptions.js) | Change the HTML returned by the shortcode in pages. | 116 | | `satoriOptions` | [satori options](https://github.com/search?q=repo:vercel/satori+%22export+type+SatoriOptions%22&type=code) | `{ width: 1200, height: 630, fonts: [] }` | If an OG-image-template contains text, it's **required** to load a font ([example](#esm)). | 117 | | `sharpOptions` | [sharp output options](https://sharp.pixelplumbing.com/api-output#toformat) | `undefined` | Options must be corresponding to chosen `outputFileExtension`. | 118 | | `OgImage` | `class CustomOgImage extends OgImage` | [`OgImage`](src/OgImage.js) | [Extend the `OgImage`](#extending-ogimage-class) class for maximum customization. | 119 | 120 | ## Preview Mode 121 | 122 | The previewMode is intended to ease the styling of OG images. When `previewMode` is set to `auto` (default) the OG images are also copied into the `previewDir` during development with `watch` or `serve`. The files are named by the url slug of the pages they are generated from. Next to it there is a HTML placed which shows the generated HTML, SVG and output image. The `previewDir` will be deleted during a production build. When not actively working on OG images, performance can be improved by disabling `previewMode`. 123 | 124 | ## Caching 125 | 126 | For better performance OG images are cached based on a hash from generated HTML and output options. If the file already exists, further transformations are skipped. 127 | 128 | ## Advanced Usage 129 | 130 | ### Extending OgImage Class 131 | 132 | It's possible to extend and overwrite any of the functions from the [`OgImage`](src/OgImage.js) class. The custom class is passed as the `OgImage` parameter to the plugin. 133 | 134 | ```js 135 | import EleventyPluginOgImage from 'eleventy-plugin-og-image'; 136 | import { OgImage } from 'eleventy-plugin-og-image/og-image'; 137 | 138 | export class CustomOgImage extends BaseOgImage { 139 | async shortcodeOutput() { 140 | return this.outputUrl(); 141 | } 142 | } 143 | 144 | /** @param {import('@11ty/eleventy/src/UserConfig').default} eleventyConfig */ 145 | export default async function (eleventyConfig) { 146 | eleventyConfig.addPlugin(EleventyPluginOgImage, { 147 | OgImage: CustomOgImage, 148 | }); 149 | } 150 | ``` 151 | 152 | ### Custom Shortcode 153 | 154 | A custom shortcode can be created by using the `OgImage` class. 155 | 156 | ```js 157 | import { OgImage } from 'eleventy-plugin-og-image/og-image'; 158 | 159 | const image = await new OgImage({ inputPath, data, options, templateConfig }).render(); 160 | ``` 161 | 162 | ### Capture Output URL 163 | 164 | The plugins shortcode create a `meta` tag per default, modify the `shortcodeOutput` option or class function to directly return the `outputUrl`: 165 | 166 | ```js 167 | eleventyConfig.addPlugin(EleventyPluginOgImage, { 168 | async shortcodeOutput(ogImage) { 169 | return ogImage.outputUrl(); 170 | }, 171 | }); 172 | ``` 173 | 174 | Furthermore, it's possible to capture the `outputUrl` to a variable, e.g. in Nunjucks: 175 | 176 | ```njk 177 | {% setAsync "ogOutputUrl" -%} 178 | {% ogImage "./og-image.og.njk", { title: "Hello World!" } %} 179 | {%- endsetAsync %} 180 | ``` 181 | 182 | And use it anywhere afterward with `{{ ogOutputUrl }}`. 183 | 184 | ## Acknowledgements & Attributions 185 | 186 | This plugin is deeply inspired by [@vercel/og](https://vercel.com/docs/concepts/functions/edge-functions/og-image-generation). 187 | 188 | Furthermore, it would not be possible without: 189 | 190 | - [satori](https://github.com/vercel/satori) 191 | - [resvg](https://github.com/RazrFalcon/resvg/)/[resvg-js](https://github.com/yisibl/resvg-js) 192 | - [sharp](https://github.com/lovell/sharp) 193 | 194 | [^1]: Only a subset of HTML elements is [supported by satori](https://github.com/vercel/satori#html-elements). 195 | 196 | [^2]: Only a subset of CSS properties are supported by [yoga-layout](https://github.com/facebook/yoga), which is [used by satori](https://github.com/vercel/satori#css). 197 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [4.2.1](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v4.2.0...v4.2.1) (2025-10-30) 2 | 3 | 4 | ### Bug Fixes 5 | 6 | * add types for default export ([#367](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/367)) ([37bb900](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/37bb900872a167341228e749b16ea63017874d5c)) 7 | 8 | ## [4.2.1-beta.1](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v4.2.0...v4.2.1-beta.1) (2025-10-29) 9 | 10 | 11 | ### Bug Fixes 12 | 13 | * add types for default export ([#367](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/367)) ([37bb900](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/37bb900872a167341228e749b16ea63017874d5c)) 14 | 15 | # [4.2.0](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v4.1.0...v4.2.0) (2025-07-29) 16 | 17 | 18 | ### Bug Fixes 19 | 20 | * add alt tag to preview ([d8e8430](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/d8e84306057cc3c71b501c07b1cb2a288c5c8c9e)) 21 | 22 | 23 | ### Features 24 | 25 | * bump satori from 0.15.2 to 0.16.1 ([b5c3cc5](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/b5c3cc5fb5be4ef8347f8fad2defb2c86d76fe75)) 26 | 27 | # [4.1.0](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v4.0.1...v4.1.0) (2025-06-28) 28 | 29 | 30 | ### Features 31 | 32 | * add previewMode option ([ac1fcfe](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/ac1fcfe4d6a172c67c1733ad83eecebf6f313105)) 33 | 34 | ## [4.0.1](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v4.0.0...v4.0.1) (2024-11-07) 35 | 36 | 37 | ### Bug Fixes 38 | 39 | * improve types ([b384921](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/b384921af2daa672be75e2af773e3f384aa56b90)) 40 | 41 | # [4.0.0](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v3.1.0...v4.0.0) (2024-10-05) 42 | 43 | 44 | ### Bug Fixes 45 | 46 | * align logging paths ([5491207](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/5491207214f961647249f5f83f7bd307b494a840)) 47 | * allow empty options for mergeOptions ([380a3c3](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/380a3c31b80d5100b36e47b5e712fb9a2dc5cf01)) 48 | * generateHTML and outputURL capitalization ([5e911b0](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/5e911b0e785c7ec1fd8cbb140acd6664bc82318a)) 49 | * generateHTML type ([f86acd4](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/f86acd4ba4cc25a1f8003c0c9f7ac7a00cf4a6d0)) 50 | * hashes without special chars with hex digest ([47fb387](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/47fb387e9515c188a8710878c80e57a0de3a6cca)) 51 | * join directories with output and preview dir ([155c7d8](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/155c7d866d77b4c127ae709eb06388ddc2a0316a)) 52 | * outputUrl on windows with forward slash ([e1bff34](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/e1bff342a878876f6bc840e94edfa39b1ca7fa72)), closes [#234](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/234) 53 | * release ([8d74d25](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/8d74d252673d2592f58062799721647ef7fd392c)) 54 | * RenderPlugin.File import ([#267](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/267)) ([4906d64](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/4906d6420d964df728fe656a7db01449ab8fe907)) 55 | * type imports ([24aa37b](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/24aa37b8f86c16eb1ec947a5b331de60534c90ac)) 56 | * update docs about arrow functions ([e6639e5](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/e6639e5012df1cc0cc3d8c65ef7a990fa38b0e82)), closes [#239](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/239) [#241](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/241) 57 | * use released alpha version ([bb8519c](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/bb8519c7c1e57629804a3937bb1c4f0049c4309c)) 58 | 59 | 60 | ### Features 61 | 62 | * add cache file path ([9b3a1d6](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/9b3a1d60f7e24c7c95283de2b748b32383413575)) 63 | * add caching ([17b46f3](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/17b46f399c43dbabeedcf843b8bec4e6b87e93d7)) 64 | * add eleventyPluginOgImage data to rendering ([b63cc55](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/b63cc55ea57e7aef096181f4edeae6dcbcb4918f)), closes [#215](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/215) 65 | * add exports ([263499b](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/263499b065f81291c8716bd147917f456816e5e9)) 66 | * add previewHtml ([7406914](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/740691462418edc6e45dd6edb7dc6bb0ea708a6f)) 67 | * allow OgImage custom class ([d31d320](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/d31d32036556f84fbfbf146e0aaa5f3dbcd63eb8)) 68 | * improve preview path handling ([4462d10](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/4462d107d5c008b6ef2e650277c3a60c15976467)) 69 | * improve types of this for function parameters ([5b0b269](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/5b0b269814e40cbea00ffcebbc9aaccda35e4cb5)) 70 | * pass instance as parameter ([b04eaf6](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/b04eaf6016038632136879ee33460611bab5c61a)), closes [#252](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/252) 71 | * pass shortcode scoped data to OG templates ([a240aee](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/a240aee5ca49015605c307dc58d64e5ca64373d8)), closes [#211](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/211) 72 | * reduce recalculations ([6a69780](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/6a697800d98af9d4e5b67de86aa4fed04d96cf3c)) 73 | * release with npm provenance ([7123708](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/712370899fca3763b82e02d6aee57fce384d9df7)) 74 | * rename generateHTML to shortcodeOutput ([a5cd8fd](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/a5cd8fd76ac0014e5ba2240875592d2159c554d3)) 75 | * rename getOutputFileSlug to outputFileSlug ([3923a5c](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/3923a5c47da83f8486b54d02f37b5dd4ef48ac2f)) 76 | * set previewDir based on outputDir ([93906ec](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/93906eca0ea989b6e78c6d8c7a2919dcce0d181e)) 77 | * update dependencies ([75aae59](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/75aae59f5c76a1089656927956d902f4c48be3a8)) 78 | * upgrade eleventy depency to stable v3 ([6e96800](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/6e9680084208eb2e853a2240820af1f8f03ee1f0)) 79 | * upgrade sharp ([0fa8b23](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/0fa8b23975a752522606eea6abbb2ce2d20220ba)) 80 | * urlPath default to outputDir ([fe9d54f](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/fe9d54fe7b18860d53cacc221d41055ae6b0804f)) 81 | * use fs promises ([0953dec](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/0953decd79b591f18a8b0344c43dd821c0898fef)) 82 | 83 | 84 | ### BREAKING CHANGES 85 | 86 | * outputFileSlug and shortcodeOutput options get OgImage instance as parameter instead of this 87 | * rename getOutputFileSlug to outputFileSlug 88 | * rename generateHTML to shortcodeOutput 89 | * Plugin structure changed to OgImage class 90 | * Options changed, consult docs before upgrading 91 | 92 | # [4.0.0-beta.10](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2024-10-05) 93 | 94 | 95 | ### Features 96 | 97 | * release with npm provenance ([7123708](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/712370899fca3763b82e02d6aee57fce384d9df7)) 98 | 99 | # [4.0.0-beta.9](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2024-10-05) 100 | 101 | 102 | ### Features 103 | 104 | * update dependencies ([75aae59](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/75aae59f5c76a1089656927956d902f4c48be3a8)) 105 | * upgrade eleventy depency to stable v3 ([6e96800](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/6e9680084208eb2e853a2240820af1f8f03ee1f0)) 106 | 107 | # [4.0.0-beta.8](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2024-07-31) 108 | 109 | 110 | ### Bug Fixes 111 | 112 | * RenderPlugin.File import ([#267](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/267)) ([4906d64](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/4906d6420d964df728fe656a7db01449ab8fe907)) 113 | 114 | # [4.0.0-beta.7](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2024-06-06) 115 | 116 | 117 | ### Features 118 | 119 | * pass instance as parameter ([b04eaf6](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/b04eaf6016038632136879ee33460611bab5c61a)), closes [#252](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/252) 120 | 121 | 122 | ### BREAKING CHANGES 123 | 124 | * outputFileSlug and shortcodeOutput options get OgImage instance as parameter instead of this 125 | 126 | # [4.0.0-beta.6](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2024-04-29) 127 | 128 | 129 | ### Bug Fixes 130 | 131 | * release ([8d74d25](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/8d74d252673d2592f58062799721647ef7fd392c)) 132 | 133 | # [4.0.0-beta.5](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2024-04-28) 134 | 135 | 136 | ### Features 137 | 138 | * add previewHtml ([7406914](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/740691462418edc6e45dd6edb7dc6bb0ea708a6f)) 139 | * rename generateHTML to shortcodeOutput ([a5cd8fd](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/a5cd8fd76ac0014e5ba2240875592d2159c554d3)) 140 | * rename getOutputFileSlug to outputFileSlug ([3923a5c](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/3923a5c47da83f8486b54d02f37b5dd4ef48ac2f)) 141 | 142 | 143 | ### BREAKING CHANGES 144 | 145 | * rename getOutputFileSlug to outputFileSlug 146 | * rename generateHTML to shortcodeOutput 147 | 148 | # [4.0.0-beta.4](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2024-04-15) 149 | 150 | 151 | ### Bug Fixes 152 | 153 | * update docs about arrow functions ([e6639e5](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/e6639e5012df1cc0cc3d8c65ef7a990fa38b0e82)), closes [#239](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/239) [#241](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/241) 154 | 155 | # [4.0.0-beta.3](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2024-04-08) 156 | 157 | 158 | ### Bug Fixes 159 | 160 | * generateHTML and outputURL capitalization ([5e911b0](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/5e911b0e785c7ec1fd8cbb140acd6664bc82318a)) 161 | 162 | # [4.0.0-beta.2](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2024-04-07) 163 | 164 | 165 | ### Features 166 | 167 | * use fs promises ([0953dec](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/0953decd79b591f18a8b0344c43dd821c0898fef)) 168 | 169 | # [4.0.0-beta.1](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v3.2.0-beta.5...v4.0.0-beta.1) (2024-04-07) 170 | 171 | 172 | ### Bug Fixes 173 | 174 | * allow empty options for mergeOptions ([380a3c3](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/380a3c31b80d5100b36e47b5e712fb9a2dc5cf01)) 175 | * generateHTML type ([f86acd4](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/f86acd4ba4cc25a1f8003c0c9f7ac7a00cf4a6d0)) 176 | * join directories with output and preview dir ([155c7d8](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/155c7d866d77b4c127ae709eb06388ddc2a0316a)) 177 | 178 | 179 | ### Features 180 | 181 | * add cache file path ([9b3a1d6](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/9b3a1d60f7e24c7c95283de2b748b32383413575)) 182 | * add caching ([17b46f3](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/17b46f399c43dbabeedcf843b8bec4e6b87e93d7)) 183 | * add exports ([263499b](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/263499b065f81291c8716bd147917f456816e5e9)) 184 | * allow OgImage custom class ([d31d320](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/d31d32036556f84fbfbf146e0aaa5f3dbcd63eb8)) 185 | * improve preview path handling ([4462d10](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/4462d107d5c008b6ef2e650277c3a60c15976467)) 186 | * improve types of this for function parameters ([5b0b269](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/5b0b269814e40cbea00ffcebbc9aaccda35e4cb5)) 187 | * reduce recalculations ([6a69780](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/6a697800d98af9d4e5b67de86aa4fed04d96cf3c)) 188 | * set previewDir based on outputDir ([93906ec](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/93906eca0ea989b6e78c6d8c7a2919dcce0d181e)) 189 | * urlPath default to outputDir ([fe9d54f](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/fe9d54fe7b18860d53cacc221d41055ae6b0804f)) 190 | 191 | 192 | ### BREAKING CHANGES 193 | 194 | * Plugin structure changed to OgImage class 195 | * Options changed, consult docs before upgrading 196 | 197 | # [3.2.0-beta.5](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v3.2.0-beta.4...v3.2.0-beta.5) (2024-03-23) 198 | 199 | 200 | ### Bug Fixes 201 | 202 | * hashes without special chars with hex digest ([47fb387](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/47fb387e9515c188a8710878c80e57a0de3a6cca)) 203 | * outputUrl on windows with forward slash ([e1bff34](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/e1bff342a878876f6bc840e94edfa39b1ca7fa72)), closes [#234](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/234) 204 | 205 | # [3.2.0-beta.4](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v3.2.0-beta.3...v3.2.0-beta.4) (2024-01-14) 206 | 207 | 208 | ### Features 209 | 210 | * add eleventyPluginOgImage data to rendering ([b63cc55](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/b63cc55ea57e7aef096181f4edeae6dcbcb4918f)), closes [#215](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/215) 211 | 212 | # [3.2.0-beta.3](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v3.2.0-beta.2...v3.2.0-beta.3) (2024-01-07) 213 | 214 | 215 | ### Bug Fixes 216 | 217 | * align logging paths ([5491207](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/5491207214f961647249f5f83f7bd307b494a840)) 218 | 219 | 220 | ### Features 221 | 222 | * pass shortcode scoped data to OG templates ([a240aee](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/a240aee5ca49015605c307dc58d64e5ca64373d8)), closes [#211](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/211) 223 | 224 | # [3.2.0-beta.2](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v3.2.0-beta.1...v3.2.0-beta.2) (2023-12-23) 225 | 226 | 227 | ### Bug Fixes 228 | 229 | * type imports ([24aa37b](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/24aa37b8f86c16eb1ec947a5b331de60534c90ac)) 230 | * use released alpha version ([bb8519c](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/bb8519c7c1e57629804a3937bb1c4f0049c4309c)) 231 | 232 | # [3.2.0-beta.1](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v3.1.0...v3.2.0-beta.1) (2023-12-05) 233 | 234 | 235 | ### Features 236 | 237 | * upgrade sharp ([0fa8b23](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/0fa8b23975a752522606eea6abbb2ce2d20220ba)) 238 | 239 | # [3.1.0](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v3.0.0...v3.1.0) (2023-11-11) 240 | 241 | 242 | ### Bug Fixes 243 | 244 | * align outputFilePath format ([7567630](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/75676308ef0ee8d3c909e10740d183f593b6388a)) 245 | * resolve pathes relativ to input ([02647a8](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/02647a843c71d3994b8e7f61cf2f00d3325ca559)) 246 | * upgrade eleventy peerDependency and compatibility ([34223f0](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/34223f0dcf26906ea161da253bfa5e7240a40113)) 247 | 248 | 249 | ### Features 250 | 251 | * improve example font loading ([7261b66](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/7261b660896aed85d57f0e4fb5953090ec362fa3)) 252 | 253 | # [3.0.0](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v2.1.1...v3.0.0) (2023-10-29) 254 | 255 | 256 | ### Features 257 | 258 | * drop node 16 support ([83b88da](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/83b88da1570730d3c4547afd943e62f8ac788c41)) 259 | * switch to ESM module ([21219b6](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/21219b6520660b250e5cd784c178f631957572ff)) 260 | 261 | 262 | ### BREAKING CHANGES 263 | 264 | * This package is now ESM-only to drop postinstall build steps 265 | * node >= 18 required 266 | 267 | ## [2.1.3](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v2.1.2...v2.1.3) (2024-03-23) 268 | 269 | 270 | ### Bug Fixes 271 | 272 | * hashes without special chars with hex digest ([47fb387](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/47fb387e9515c188a8710878c80e57a0de3a6cca)) 273 | 274 | ## [2.1.2](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v2.1.1...v2.1.2) (2024-03-23) 275 | 276 | 277 | ### Bug Fixes 278 | 279 | * outputUrl on windows with forward slash ([e1bff34](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/e1bff342a878876f6bc840e94edfa39b1ca7fa72)), closes [#234](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/234) 280 | 281 | ## [2.1.1](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v2.1.0...v2.1.1) (2023-09-02) 282 | 283 | 284 | ### Bug Fixes 285 | 286 | * @11ty/eleventy >= 2.x.x is required ([#164](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/164)) ([f2d6aa8](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/f2d6aa83da8b4c0eb9faf726236fdb227d0785c7)) 287 | * omit output for permalink false ([#163](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/163)) ([432edd0](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/432edd0ad35de86998569ebdabc57a763cfc3eea)) 288 | 289 | # [2.1.0](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v2.0.1...v2.1.0) (2023-08-30) 290 | 291 | 292 | ### Features 293 | 294 | * add getOutputFileSlug ([#160](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/160)) ([f55cbdc](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/f55cbdcfd561bae388207589ed595a3aa2d99865)) 295 | 296 | ## [2.0.1](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v2.0.0...v2.0.1) (2023-06-13) 297 | 298 | 299 | ### Bug Fixes 300 | 301 | * unify logging ([#131](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/131)) ([de6ca1d](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/de6ca1d0a1a694016e0292b502a9680534d4abc9)) 302 | 303 | # [2.0.0](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v1.6.2...v2.0.0) (2023-06-01) 304 | 305 | 306 | ### Features 307 | 308 | * add development mode ([#123](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/123)) ([8711954](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/8711954c7e5dc58b507b972252a32389dc0fbef7)) 309 | 310 | 311 | ### BREAKING CHANGES 312 | 313 | * switch `renderOgImage` parameters to object style 314 | 315 | ## [1.6.2](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v1.6.1...v1.6.2) (2023-05-24) 316 | 317 | 318 | ### Bug Fixes 319 | 320 | * exports of types ([#120](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/120)) ([e679ebb](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/e679ebb1a7f822ccd518b1af4c17d0629303581f)) 321 | 322 | ## [1.6.1](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v1.6.0...v1.6.1) (2023-03-03) 323 | 324 | 325 | ### Bug Fixes 326 | 327 | * use export to resolve yoga.wasm ([#78](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/78)) ([fdb4d20](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/fdb4d20fd369baac62be428efd3930c040e0c1cb)) 328 | 329 | # [1.6.0](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v1.5.0...v1.6.0) (2023-02-23) 330 | 331 | 332 | ### Features 333 | 334 | * clear outputDir on eleventy.build event ([#74](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/74)) ([3e60531](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/3e60531e01f333c637cd9f330ff1e63bdd2d2945)) 335 | 336 | # [1.5.0](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v1.4.2...v1.5.0) (2023-02-20) 337 | 338 | 339 | ### Features 340 | 341 | * use yoga-wasm-web ([#72](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/72)) ([d189d35](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/d189d351325f1b1b7f550273638977d849b4c37c)) 342 | 343 | ## [1.4.2](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v1.4.1...v1.4.2) (2023-01-25) 344 | 345 | 346 | ### Bug Fixes 347 | 348 | * @11ty/eleventy as peerDependency ([#57](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/57)) ([48b2353](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/48b2353c22ffea76240b9d208ab3da579e690862)) 349 | 350 | ## [1.4.1](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v1.4.0...v1.4.1) (2023-01-16) 351 | 352 | 353 | ### Bug Fixes 354 | 355 | * align node minimum version with eleventy ([#50](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/50)) ([1a55b78](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/1a55b78767fcd42e0f21def605e8b884231fa172)) 356 | 357 | # [1.4.0](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v1.3.0...v1.4.0) (2023-01-11) 358 | 359 | 360 | ### Bug Fixes 361 | 362 | * satori with yoga-layout-prebuilt ([5a91800](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/5a918009bc2e224a368e6aa1384deebb6010b753)) 363 | 364 | 365 | ### Features 366 | 367 | * inputFileGlob now ignores in subDirectories ([#48](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/48)) ([aef85eb](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/aef85eb5238162d5d2c6a287dc45178ba2930da2)) 368 | 369 | # [1.3.0](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v1.2.0...v1.3.0) (2023-01-04) 370 | 371 | 372 | ### Features 373 | 374 | * render og image with templateConfig ([#40](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/40)) ([6884b90](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/6884b90c1e2423527a9b3c864480fee576727e1c)) 375 | 376 | # [1.2.0](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v1.1.1...v1.2.0) (2022-12-30) 377 | 378 | 379 | ### Features 380 | 381 | * add generateHTML option ([#34](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/34)) ([aec8082](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/aec808227bc69866acdf2db11fbc9c7ef94fb113)) 382 | 383 | ## [1.1.1](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v1.1.0...v1.1.1) (2022-12-12) 384 | 385 | 386 | ### Bug Fixes 387 | 388 | * remove ultrahtml override ([#26](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/26)) ([220a965](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/220a965ce319852fd75a913bed4dd0133c7ce698)) 389 | 390 | # [1.1.0](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v1.0.1...v1.1.0) (2022-11-05) 391 | 392 | 393 | ### Features 394 | 395 | * improve output behavior ([fc272c5](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/fc272c50b27bba75d0e2e075bb11b40ad2b76504)), closes [#6](https://github.com/KiwiKilian/eleventy-plugin-og-image/issues/6) 396 | 397 | ## [1.0.1](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v1.0.0...v1.0.1) (2022-11-03) 398 | 399 | 400 | ### Bug Fixes 401 | 402 | * Enable CSS inlining ([592dec0](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/592dec0f86f5e5aa2970c1b929251a11d10af057)) 403 | 404 | # [1.0.0](https://github.com/KiwiKilian/eleventy-plugin-og-image/compare/v0.1.1...v1.0.0) (2022-10-30) 405 | 406 | 407 | ### Features 408 | 409 | * Add shortcode ([ce4df37](https://github.com/KiwiKilian/eleventy-plugin-og-image/commit/ce4df37c0b73b6e6dc0f1e1cc5b4f08ede194b3e)) 410 | 411 | 412 | ### BREAKING CHANGES 413 | 414 | * Use shortcode instead of template functionality 415 | --------------------------------------------------------------------------------