@uploadcare/ai-enhancer 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,314 +1,128 @@
1
- # @uploadcare/ai-enhancer
1
+ <p align="center">
2
+ <a href="https://uploadcare.com/?ref=ai-enhancer">
3
+ <picture>
4
+ <source media="(prefers-color-scheme: light)" srcset="https://ucarecdn.com/1b4714cd-53be-447b-bbde-e061f1e5a22f/logosafespacetransparent.svg">
5
+ <source media="(prefers-color-scheme: dark)" srcset="https://ucarecdn.com/3b610a0a-780c-4750-a8b4-3bf4a8c90389/logotransparentinverted.svg">
6
+ <img width=250 alt="Uploadcare logo" src="https://ucarecdn.com/1b4714cd-53be-447b-bbde-e061f1e5a22f/logosafespacetransparent.svg">
7
+ </picture>
8
+ </a>
9
+ </p>
10
+ <p align="center">
11
+ <a href="https://uploadcare.com/?ref=ai-enhancer">Website</a> •
12
+ <a href="https://uploadcare.github.io/ai-enhancer/">Docs</a> •
13
+ <a href="https://uploadcare.com/blog?ref=ai-enhancer">Blog</a> •
14
+ <a href="https://twitter.com/Uploadcare?ref=ai-enhancer">Twitter</a>
15
+ </p>
16
+
17
+ # Uploadcare AI Enhancer
18
+
19
+ [![NPM version][npm-img]][npm-url]
20
+ [![Build Status][badge-build]][build-url]
21
+ [![GitHub release][badge-release-img]][badge-release-url]
2
22
 
3
23
  AI image generation and editing for [Uploadcare](https://uploadcare.com/) — a
4
- framework-agnostic `<uc-ai-enhancer>` web component, plus an optional plugin that
5
- adds an **AI Edit** action and a **Generate image** source to the
24
+ framework-agnostic `<uc-ai-enhancer>` web component, plus an optional plugin
25
+ that adds an **AI Edit** action and a **Generate image** source to the
6
26
  [Uploadcare File Uploader](https://uploadcare.com/docs/file-uploader/). Generate
7
- images from a text prompt, edit existing ones by uuid, pick aspect ratios, and
8
- commit the result back as an already-uploaded Uploadcare file.
27
+ images from a text prompt, edit existing ones by uuid, and commit the result
28
+ back as an already-uploaded Uploadcare file.
9
29
 
10
- ```sh
11
- npm install @uploadcare/ai-enhancer
12
- # or
13
- pnpm add @uploadcare/ai-enhancer
14
- yarn add @uploadcare/ai-enhancer
15
- ```
16
-
17
- Two entry points, imported independently so you only pull in what you use:
18
-
19
- | Import | What it gives you |
20
- |---|---|
21
- | `@uploadcare/ai-enhancer` | Registers the `<uc-ai-enhancer>` element and exports its public types, the provider, and the localization helpers. |
22
- | `@uploadcare/ai-enhancer/plugin` | Just the `AiEnhancerPlugin` for the File Uploader — no eager component registration. |
23
-
24
- > The plugin entry needs `@uploadcare/file-uploader` **≥ 1.31.2** as a
25
- > peer dependency (it relies on `uploaderApi.replaceFile`). The standalone editor
26
- > has no peer dependency.
27
-
28
- You need an Uploadcare **public key** (from the
29
- [dashboard](https://app.uploadcare.com/)) to generate or edit images.
30
-
31
- ## Use as a File Uploader plugin
32
-
33
- Register the plugin on `<uc-config>` and add `ai-enhancer` to the source list.
34
- The plugin reads its settings (public key, CDN config, locale, …) straight from
35
- the uploader config — there's nothing extra to wire up.
36
-
37
- ```ts
38
- import * as UC from '@uploadcare/file-uploader'
39
- import { AiEnhancerPlugin } from '@uploadcare/ai-enhancer/plugin'
30
+ ## Quick start
40
31
 
41
- UC.defineComponents(UC)
32
+ 1. Install the package:
42
33
 
43
- const config = document.querySelector('uc-config')
44
- config.plugins = [AiEnhancerPlugin]
45
- ```
46
-
47
- ```html
48
- <uc-file-uploader-regular ctx-name="my-uploader"></uc-file-uploader-regular>
49
- <uc-config
50
- ctx-name="my-uploader"
51
- pubkey="YOUR_PUBLIC_KEY"
52
- source-list="local, url, camera, ai-enhancer"
53
- ></uc-config>
54
- <uc-upload-ctx-provider ctx-name="my-uploader"></uc-upload-ctx-provider>
34
+ ```bash
35
+ npm install @uploadcare/ai-enhancer
55
36
  ```
56
37
 
57
- The plugin contributes two affordances:
58
-
59
- - **Generate image** — an upload source (shown because `ai-enhancer` is in
60
- `source-list`). Opens the editor in generate mode; the committed result is
61
- **added** as a new file (sourced to `ai-enhancer`).
62
- - **AI Edit** — a file action on already-uploaded images. Opens the editor in
63
- edit mode on that image; the committed result **replaces the original entry in
64
- place** (same list position; the entry gets a new `internalId`) and keeps the
65
- original file's name.
66
-
67
- ### Configuration
68
-
69
- The plugin consumes these `<uc-config>` keys (all standard uploader config — set
70
- them as attributes or properties):
38
+ 2. Use the [standalone editor][docs-getting-started] — importing the package
39
+ registers the element; configure it via [properties][docs-api] and pick a
40
+ [layout][docs-layout], [theme][docs-theming], and [locale][docs-l10n]:
71
41
 
72
- | Key | Required | Purpose |
73
- |---|---|---|
74
- | `pubkey` | ✅ | Uploadcare public key. Without it the editor is disabled. |
75
- | `baseUrl` | | Upload API base URL (defaults to the SDK default). |
76
- | `cdnCname` | | CDN cname for resolving results. |
77
- | `cdnCnamePrefixed` | | Base domain for public-key-prefixed CDN URLs. |
78
- | `cropPreset` | | Reused to derive the editor's offered aspect ratios. |
79
- | `metadata` | | Key/value metadata attached to the AI result, like a regular upload. A `MetadataCallback` is resolved against the source entry in edit mode; in generate mode (no input file) only the static object form applies. |
80
- | `localeName` | | Drives the editor language (lazy-loaded; see [Localization](#localization)). |
81
- | `localeDefinitionOverride` | | Per-locale string overrides, layered onto the editor's built-ins. |
82
- | `secureDeliveryProxyUrlResolver` | | Signs/proxies the CDN URLs the editor renders (secure delivery). |
83
- | `useAiEditor` | | Plugin option (mirrors `useCloudImageEditor`). Show the **AI Edit** file action (default `true`). Set `false` / `use-ai-editor="false"` to hide it. |
84
-
85
- Importing the plugin augments the uploader's config types, so `useAiEditor`
86
- is type-checked on `<uc-config>` (reference `@uploadcare/ai-enhancer/plugin`
87
- types if your project doesn't pick it up automatically).
88
-
89
- > **Already-edited images:** the AI Edit action hides itself for images that
90
- > already carry CDN modifiers (e.g. edited with the Cloud Image Editor) — AI Edit
91
- > works on the original file and can't carry those modifiers over.
92
-
93
- ## Use the standalone editor
94
-
95
- `<uc-ai-enhancer>` works without the uploader. Importing the package registers the
96
- element; configure it via attributes/properties and listen for `uc:*` events.
97
-
98
- ```ts
99
- import '@uploadcare/ai-enhancer'
42
+ ```js
43
+ import '@uploadcare/ai-enhancer';
100
44
  ```
101
45
 
102
46
  ```html
103
47
  <uc-ai-enhancer pubkey="YOUR_PUBLIC_KEY"></uc-ai-enhancer>
104
48
  ```
105
49
 
106
- ```ts
107
- const editor = document.querySelector('uc-ai-enhancer')
108
-
109
- editor.addEventListener('uc:done', (e) => {
110
- const { uuid, cdnUrl, file } = e.detail // file: UploadcareFile
111
- // persist / display the committed result…
112
- })
113
- editor.addEventListener('uc:cancel', () => {/* closed without committing */})
114
- editor.addEventListener('uc:error', (e) => console.warn(e.detail.error))
115
-
116
- // Edit an existing image instead of generating from scratch:
117
- editor.sourceUuid = 'c2499162-eb07-4b93-b31e-94a89a47e858'
118
- ```
119
-
120
- **No bundler?** Load it from a CDN — [esm.run](https://esm.run) bundles the
121
- dependencies, and lazy-loaded locales resolve from the same CDN automatically
122
- (pin a version in production):
123
-
124
- ```html
125
- <script type="module">
126
- import 'https://esm.run/@uploadcare/ai-enhancer@0.1.0'
127
- </script>
128
- <uc-ai-enhancer pubkey="YOUR_PUBLIC_KEY" locale-name="de"></uc-ai-enhancer>
129
- ```
130
-
131
- ### `<uc-ai-enhancer>` properties
132
-
133
- | Property | Attribute | Type | Description |
134
- |---|---|---|---|
135
- | `pubkey` | `pubkey` | `string` | Uploadcare public key. Required to enable generate/edit. |
136
- | `sourceUuid` | `source-uuid` | `string \| null` | UUID of an image to edit. Absent → generate mode. Use either this or `sourceFileInfo`, not both. |
137
- | `sourceFileInfo` | — | `UploadcareFile` | Property only. The source image as an `UploadcareFile` (e.g. the object returned by `@uploadcare/upload-client`, or the `fileInfo` of a File Uploader output entry). An alternative to `sourceUuid` that hands the editor the file directly instead of having it look it up from the uuid. |
138
- | `outputFilename` | — | `string \| (originalFilename, counter) => string` | Property only. Names the result. A string is used verbatim; a function receives the source's original filename (`undefined` when generating from scratch) and the 1-based history counter (first is `1`). Unset → keep the source's original name. |
139
- | `baseUrl` | `base-url` | `string` | Upload API base URL. |
140
- | `cdnCname` | `cdn-cname` | `string` | CDN cname for resolving results. |
141
- | `cdnCnamePrefixed` | `cdn-cname-prefixed` | `string` | Base domain for prefixed CDN URLs. |
142
- | `aspectRatios` | `aspect-ratios` | `AspectRatio[] \| null` | Ratios offered in generate mode, e.g. `aspect-ratios="16:9 5:4 1:1"`. Empty → popular set. |
143
- | `presetsOnly` | `presets-only` | `boolean` | Hide the free-text prompt; preset chips only, and picking one generates immediately. |
144
- | `presets` | — | `AiPresets` | Property only. Quick-prompt chips keyed by mode, e.g. `{ generate: [{ label, prompt }], edit: [...] }`. Clicking a chip fills the prompt. Modes left out use the built-in set; an empty array (`{ generate: [] }`) hides that mode's chips. Keyed by mode, so future modes extend it without breaking existing configs. |
145
- | `metadata` | — | `Metadata \| MetadataCallback \| null` | Property only. Same shape as the file uploader's `metadata` config: a static key/value bag (`Record<string, string>`, e.g. `{ source: 'ai-enhancer' }`) or a `MetadataCallback` the editor calls at generation time with the source file (optionally async). The callback only runs when there's a source to pass it (editing an existing image); when generating from scratch it's skipped, so use the static object form there. |
146
- | `composerPlacement` | `composer-placement` | `ComposerPlacement` | Which edge the composer sits on: `bottom` (default) or `top`. |
147
- | `canvasFit` | `canvas-fit` | `CanvasFit` | How the canvas sizes relative to the composer: `available` (default) shrinks the canvas to the space left by the composer (docked outside the image; history chips still overlay it); `full` lets the canvas fill the area with the composer floating over it. |
148
- | `historyPlacement` | `history-placement` | `HistoryPlacement` | Where the history strip sits: `composer-above` (default) / `composer-below` (relative to the composer) or `canvas-top` / `canvas-bottom` (pinned to the canvas edge). |
149
- | `composerAutoHide` | `composer-auto-hide` | `boolean` | Once an image exists, dock the composer down to a small peek; it raises when the pointer nears its edge or it gains focus. Always floats the composer, so it implies `canvas-fit="full"`. Off by default. |
150
- | `toolbarPlacement` | `toolbar-placement` | `ToolbarPlacement` | Where the Cancel / Done toolbar sits: `bottom` (default) or `top`. |
151
- | `localeName` | `locale-name` | `string` | Active locale (default `en`); the editor lazy-loads that locale's built-in strings. |
152
- | `localeDefinitionOverride` | — | `Record<string, Partial<AiEnhancerLocale>>` | Per-locale string overrides, keyed by locale name (see [Localization](#localization)). |
153
- | `secureDeliveryProxyUrlResolver` | — | `SecureDeliveryProxyUrlResolver` | Property only. Signs/proxies rendered CDN URLs. |
154
-
155
- ### `<uc-ai-enhancer>` events
156
-
157
- All events bubble and are `composed`.
158
-
159
- | Event | `detail` | Fired when |
160
- |---|---|---|
161
- | `uc:done` | `DoneDetail` | The user commits a result. |
162
- | `uc:cancel` | — | The user closes without committing. |
163
- | `uc:error` | `{ error: unknown }` | A generation/edit fails. |
164
-
165
- ```ts
166
- type DoneDetail = {
167
- url: string
168
- uuid: string // same as file.uuid
169
- prompt: string
170
- mode: 'generate' | 'edit'
171
- aspectRatio?: AspectRatio
172
- file: UploadcareFile // the committed result
173
- }
50
+ ```js
51
+ const editor = document.querySelector('uc-ai-enhancer');
52
+ editor.addEventListener('uc:done', (e) => console.log(e.detail.url));
174
53
  ```
175
54
 
176
- ### Edit vs. generate mode
177
-
178
- Mode is **derived**, not set explicitly: the editor is in `edit` mode whenever
179
- there's a current image — an input source (`sourceUuid` / `sourceFileInfo`) or a
180
- generation result — and `generate` otherwise. So the first successful generation
181
- flips the editor into edit mode for free, and a "Start over" affordance appears
182
- (only for generate sessions — editing an existing source has nothing to start
183
- over to).
55
+ All `uc:*` events and their payloads are listed in the [API reference][docs-api].
184
56
 
185
- ## Framework usage
57
+ > **Client-only:** importing the package registers custom elements, so it must
58
+ > run in the browser — in SSR apps load it behind a client boundary (see
59
+ > [Bundlers & SSR][docs-ssr]), or use the SSR-safe
60
+ > [React wrapper][docs-react].
186
61
 
187
- `<uc-ai-enhancer>` is a standard custom element, so it works in any framework. Two
188
- things to wire up: object/function values (`metadata`, `presets`,
189
- `sourceFileInfo`, `outputFilename`, ) must be set as **DOM properties**, not
190
- string attributes, and `uc:*` events are plain DOM events.
191
-
192
- For **React**, install the [`@uploadcare/react-ai-enhancer`](../react-ai-enhancer)
193
- wrapper — typed props + `onDone` / `onCancel` / `onError` callbacks:
62
+ Or as a [File Uploader plugin][docs-plugin], assuming a working
63
+ [File Uploader](https://uploadcare.com/docs/file-uploader/) setup
64
+ (`@uploadcare/file-uploader` **≥ 1.31.2**) the plugin reads its settings
65
+ from the uploader config:
194
66
 
195
67
  ```bash
196
- npm install @uploadcare/react-ai-enhancer
68
+ npm install @uploadcare/ai-enhancer @uploadcare/file-uploader
197
69
  ```
198
70
 
199
- ```tsx
200
- import { AiEnhancer } from '@uploadcare/react-ai-enhancer'
71
+ ```js
72
+ import * as UC from '@uploadcare/file-uploader';
73
+ import { AiEnhancerPlugin } from '@uploadcare/ai-enhancer/plugin';
201
74
 
202
- <AiEnhancer pubkey="YOUR_PUBLIC_KEY" onDone={(d) => console.log(d.url)} />
75
+ UC.defineComponents(UC);
76
+ document.querySelector('uc-config').plugins = [AiEnhancerPlugin];
203
77
  ```
204
78
 
205
- ```vue
206
- <!-- Vue 3: mark `uc-` tags as custom elements (vite.config / compilerOptions),
207
- then bind properties with `.prop` and events with `@`. -->
208
- <uc-ai-enhancer :pubkey="key" .metadata="meta" @uc:done="onDone" />
209
- ```
210
-
211
- - **Angular** — add `CUSTOM_ELEMENTS_SCHEMA`; bind `[prop]` and `(uc:done)`.
212
- - **Svelte** — works natively: attributes/properties and `on:uc:done`.
213
-
214
- ## Bundlers & SSR
215
-
216
- The two entry points are imported independently, so you only ship what you use,
217
- and the editor's styles live in its shadow DOM there's no separate CSS import.
218
-
219
- **SSR (Next.js, Nuxt, …):** the editor is a browser web component — register it
220
- **client-side only** (e.g. a dynamic `import('@uploadcare/ai-enhancer')` inside an
221
- effect, or a `'use client'` component), never during server render.
222
-
223
- ## TypeScript
224
-
225
- - Event details are typed cast `e.detail` to `DoneDetail` (exported), or augment
226
- your framework's event map.
227
- - Importing `@uploadcare/ai-enhancer/plugin` augments the uploader's config types
228
- (`useAiEditor`, the editor's locale keys). If your project doesn't pick that up
229
- automatically, reference it once: `/// <reference types="@uploadcare/ai-enhancer/plugin" />`.
230
-
231
- ## Theming
232
-
233
- The editor is styled entirely through CSS custom properties on the element. When
234
- used as a plugin, most tokens inherit from the uploader's `--uc-*` theme
235
- automatically. Set any of these to customize:
236
-
237
- ```css
238
- uc-ai-enhancer {
239
- --uc-ai-primary: #6d28d9;
240
- --uc-ai-radius: 20px;
241
- --uc-ai-dot-grid-color: #2a2a2a;
242
- }
243
- ```
244
-
245
- | Token group | Tokens |
246
- |---|---|
247
- | Color | `--uc-ai-foreground`, `--uc-ai-background`, `--uc-ai-floating`, `--uc-ai-floating-border`, `--uc-ai-muted`, `--uc-ai-muted-foreground`, `--uc-ai-primary`, `--uc-ai-primary-hover`, `--uc-ai-primary-foreground`, `--uc-ai-primary-transparent`, `--uc-ai-secondary`, `--uc-ai-secondary-hover`, `--uc-ai-secondary-foreground`, `--uc-ai-border`, `--uc-ai-destructive`, `--uc-ai-destructive-foreground` |
248
- | Shape | `--uc-ai-radius`, `--uc-ai-radius-button`, `--uc-ai-radius-card`, `--uc-ai-radius-frame`, `--uc-ai-radius-input` |
249
- | Layout & type | `--uc-ai-padding`, `--uc-ai-button-size`, `--uc-ai-font-family`, `--uc-ai-font-size` |
250
- | Canvas / motion | `--uc-ai-dot-grid-color`, `--uc-ai-shadow-color`, `--uc-ai-dialog-shadow`, `--uc-ai-transition`, `--uc-ai-ease-in-out`, `--uc-ai-ease-out` |
251
- | Prompt | `--uc-ai-prompt-max-height`, `--uc-ai-prompt-max-lines` |
252
-
253
- ## Localization
254
-
255
- The editor ships English eagerly and lazy-loads 34 other locales. Set the active
256
- language with `localeName`; the editor loads that locale's built-in strings on
257
- demand. Customize individual strings with `localeDefinitionOverride` — **keyed by
258
- locale name**, the same shape as the file uploader's config. As a plugin, both
259
- follow the uploader's `localeName` / `localeDefinitionOverride` automatically.
260
-
261
- ```ts
262
- // Standalone: pick the language and override specific strings per locale.
263
- editor.localeName = 'de'
264
- editor.localeDefinitionOverride = {
265
- en: { 'ai-enhancer-cancel': 'Dismiss' },
266
- de: { 'ai-enhancer-generate-btn': 'Los!' },
267
- }
268
- ```
269
-
270
- Supported locales: `en ar az ca cs da de el es et fi fr he hy is it ja ka kk ko
271
- lv nb nl pl pt ro ru sk sr sv tr uk vi zh` (and `zh-TW`). Error-code messages
272
- (`ai-enhancer-error-<code>`) are optional per locale and fall back to the generic
273
- message. `enLocale` is exported for looking up strings outside the element.
274
-
275
- ## API reference
276
-
277
- Everything below is exported from `@uploadcare/ai-enhancer` (the plugin and its
278
- types come from `@uploadcare/ai-enhancer/plugin`).
279
-
280
- ### Plugin — `@uploadcare/ai-enhancer/plugin`
281
-
282
- - **`AiEnhancerPlugin`** — `UploaderPlugin`. Add to `config.plugins`.
283
- - **`AiEditorActivityParams`** — `{ sourceInternalId?: string }`. Activity params;
284
- presence of `sourceInternalId` means edit mode (the source uuid + file info are
285
- read from that entry, and `uc:done` replaces it in place).
286
- - **`aspectRatiosFromCropPreset(cropPreset: string): AspectRatio[] | null`** —
287
- translate the uploader's `cropPreset` into the editor's offered ratios.
288
-
289
- ### Editor
290
-
291
- - **`UcAiEnhancer`** (`<uc-ai-enhancer>`) — the editor element (see properties /
292
- events above).
293
- - Types: **`DoneDetail`**, **`OutputFilenameResolver`** (`(originalFilename, counter) => string`),
294
- **`MetadataCallback`** (`(fileInfo: UploadcareFile) => Metadata | Promise<Metadata>`),
295
- **`ComposerPlacement`**, **`CanvasFit`**, **`HistoryPlacement`**,
296
- **`ToolbarPlacement`**, **`AspectRatio`**, **`AiPreset`** (`{ label, prompt }`),
297
- **`AiPresets`** (`Partial<Record<AiEditorMode, AiPreset[]>>`),
298
- **`AiEditorMode`** (`'generate' | 'edit'`).
299
-
300
- ### Localization & secure delivery
301
-
302
- - **`enLocale`**, **`AiEnhancerLocale`** — look up / type editor strings.
303
- - **`SecureDeliveryProxyUrlResolver`**, **`SecureDeliveryUrlParts`** — sign /
304
- proxy the CDN URLs the editor renders.
305
-
306
- ## Useful links
307
-
308
- - [Uploadcare File Uploader](https://uploadcare.com/docs/file-uploader/)
309
- - [Uploadcare CDN & transformations](https://uploadcare.com/docs/transformations/image/)
310
- - [Secure delivery](https://uploadcare.com/docs/security/secure-delivery/)
311
-
312
- ## License
313
-
314
- MIT
79
+ Add `ai-enhancer` to the config's `source-list` to expose the **Generate
80
+ image** source; the **AI Edit** action appears on uploaded images
81
+ automatically. Full setup in the [plugin guide][docs-plugin].
82
+
83
+ You need an Uploadcare **public key** from the
84
+ [dashboard](https://app.uploadcare.com/). Using React? See
85
+ [`@uploadcare/react-ai-enhancer`][docs-react].
86
+
87
+ ## Documentation
88
+
89
+ Everything else lives in the [docs][docs]:
90
+
91
+ - [Getting started][docs-getting-started]install, entry points, first render
92
+ - [Integrating into your app][docs-integrating] — Vue, Angular, Svelte, bundlers, SSR
93
+ - [File Uploader plugin][docs-plugin] configuration and behavior
94
+ - [UI & layout][docs-layout], [Theming][docs-theming], [Localization][docs-l10n]
95
+ - [API reference][docs-api] properties, events, exported types
96
+
97
+ ## Security issues
98
+
99
+ If you think you ran into something in Uploadcare libraries that might have
100
+ security implications, please hit us up at
101
+ [bugbounty@uploadcare.com][uc-email-bounty] or Hackerone.
102
+
103
+ We'll contact you personally in a short time to fix an issue through co-op and
104
+ prior to any public disclosure.
105
+
106
+ ## Feedback
107
+
108
+ Issues and PRs are welcome. You can provide your feedback or drop us a support
109
+ request at [hello@uploadcare.com][uc-email-hello].
110
+
111
+ [docs]: https://uploadcare.github.io/ai-enhancer/
112
+ [docs-getting-started]: https://uploadcare.github.io/ai-enhancer/guide/getting-started
113
+ [docs-integrating]: https://uploadcare.github.io/ai-enhancer/guide/integrating
114
+ [docs-react]: https://uploadcare.github.io/ai-enhancer/guide/react
115
+ [docs-plugin]: https://uploadcare.github.io/ai-enhancer/guide/plugin
116
+ [docs-ssr]: https://uploadcare.github.io/ai-enhancer/guide/integrating#bundlers-ssr
117
+ [docs-layout]: https://uploadcare.github.io/ai-enhancer/guide/layout
118
+ [docs-theming]: https://uploadcare.github.io/ai-enhancer/guide/theming
119
+ [docs-l10n]: https://uploadcare.github.io/ai-enhancer/guide/localization
120
+ [docs-api]: https://uploadcare.github.io/ai-enhancer/api/
121
+ [uc-email-bounty]: mailto:bugbounty@uploadcare.com
122
+ [uc-email-hello]: mailto:hello@uploadcare.com
123
+ [npm-img]: https://img.shields.io/npm/v/@uploadcare/ai-enhancer.svg
124
+ [npm-url]: https://www.npmjs.com/package/@uploadcare/ai-enhancer
125
+ [badge-build]: https://github.com/uploadcare/ai-enhancer/actions/workflows/checks.yml/badge.svg
126
+ [build-url]: https://github.com/uploadcare/ai-enhancer/actions/workflows/checks.yml
127
+ [badge-release-img]: https://img.shields.io/github/release/uploadcare/ai-enhancer.svg
128
+ [badge-release-url]: https://github.com/uploadcare/ai-enhancer/releases