@notum-cz/strapi-plugin-tiptap-editor 1.0.3-rc.6 → 1.1.1
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 +103 -0
- package/dist/_chunks/{RichTextInput-NZH5L_pW.mjs → RichTextInput-B8CLPOyo.mjs} +1 -1
- package/dist/_chunks/{RichTextInput-zyphJZp3.js → RichTextInput-EtL-yFqV.js} +1 -1
- package/dist/_chunks/{index-DB8F5E26.mjs → index-sX8SY6P-.mjs} +15 -4
- package/dist/_chunks/{index-CsjxcNiy.js → index-yXpX_VsO.js} +15 -4
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/shared/types.d.ts +8 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -88,7 +88,11 @@
|
|
|
88
88
|
- [Links](#links)
|
|
89
89
|
- [Tables](#tables)
|
|
90
90
|
- [Text Alignment](#text-alignment)
|
|
91
|
+
- [Text Color \& Highlight Color](#text-color--highlight-color)
|
|
91
92
|
- [Images](#images)
|
|
93
|
+
- [Theme](#theme)
|
|
94
|
+
- [Colors](#colors)
|
|
95
|
+
- [Custom Stylesheet](#custom-stylesheet)
|
|
92
96
|
- [Configuration Reference](#configuration-reference)
|
|
93
97
|
- [Feature Values](#feature-values)
|
|
94
98
|
- [Full Preset Example](#full-preset-example)
|
|
@@ -393,6 +397,22 @@ Enables all four alignment buttons (left, center, right, justify).
|
|
|
393
397
|
}
|
|
394
398
|
```
|
|
395
399
|
|
|
400
|
+
### Text Color & Highlight Color
|
|
401
|
+
|
|
402
|
+
| Key | Description | Toolbar |
|
|
403
|
+
| ---------------- | --------------------------------- | ---------------------- |
|
|
404
|
+
| `textColor` | Change the color of selected text | Font color picker |
|
|
405
|
+
| `highlightColor` | Apply a background highlight | Highlight color picker |
|
|
406
|
+
|
|
407
|
+
Both features use a color picker popover that displays the colors defined in the [theme configuration](#colors). If no colors are configured, the buttons will not appear.
|
|
408
|
+
|
|
409
|
+
```ts
|
|
410
|
+
{
|
|
411
|
+
textColor: true,
|
|
412
|
+
highlightColor: true,
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
396
416
|
### Images
|
|
397
417
|
|
|
398
418
|
| Key | Description | Toolbar |
|
|
@@ -416,6 +436,85 @@ The image stores both the URL (`src`) and the Strapi asset ID (`data-asset-id`)
|
|
|
416
436
|
}
|
|
417
437
|
```
|
|
418
438
|
|
|
439
|
+
## Theme
|
|
440
|
+
|
|
441
|
+
The `theme` key in the plugin config lets you define colors for the color pickers and inject custom CSS into the editor.
|
|
442
|
+
|
|
443
|
+
### Colors
|
|
444
|
+
|
|
445
|
+
Define a `colors` array to populate the text color and highlight color pickers. Each entry needs a `label` (shown as a tooltip) and a `color` value (hex, rgb, rgba, hsl, hsla, or CSS variable).
|
|
446
|
+
|
|
447
|
+
```ts
|
|
448
|
+
// config/plugins.ts
|
|
449
|
+
|
|
450
|
+
export default () => ({
|
|
451
|
+
'tiptap-editor': {
|
|
452
|
+
config: {
|
|
453
|
+
theme: {
|
|
454
|
+
colors: [
|
|
455
|
+
{ label: 'Black', color: '#000000' },
|
|
456
|
+
{ label: 'Dark gray', color: '#4A4A4A' },
|
|
457
|
+
{ label: 'Red', color: '#E53E3E' },
|
|
458
|
+
{ label: 'Orange', color: '#DD6B20' },
|
|
459
|
+
{ label: 'Blue', color: '#3182CE' },
|
|
460
|
+
{ label: 'Green', color: '#38A169' },
|
|
461
|
+
{ label: 'Brand primary', color: 'var(--color-primary)' },
|
|
462
|
+
],
|
|
463
|
+
},
|
|
464
|
+
presets: {
|
|
465
|
+
blog: {
|
|
466
|
+
bold: true,
|
|
467
|
+
italic: true,
|
|
468
|
+
textColor: true,
|
|
469
|
+
highlightColor: true,
|
|
470
|
+
},
|
|
471
|
+
},
|
|
472
|
+
},
|
|
473
|
+
},
|
|
474
|
+
});
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### Custom Stylesheet
|
|
478
|
+
|
|
479
|
+
You can inject custom CSS to style the editor content area. There are two options — use one or the other, not both.
|
|
480
|
+
|
|
481
|
+
**Option 1: `css`** — Inline CSS content (recommended for monorepos and production deployments)
|
|
482
|
+
|
|
483
|
+
Read the file at Strapi startup so the CSS is captured as a string. This works reliably across all environments (local dev, Docker, Azure Container Apps, etc.) because the file is resolved in your app's Node process at boot time.
|
|
484
|
+
|
|
485
|
+
```ts
|
|
486
|
+
// config/plugins.ts
|
|
487
|
+
import { readFileSync } from 'fs';
|
|
488
|
+
|
|
489
|
+
export default () => ({
|
|
490
|
+
'tiptap-editor': {
|
|
491
|
+
config: {
|
|
492
|
+
theme: {
|
|
493
|
+
css: readFileSync(require.resolve('@repo/design-system/strapi-styles.css'), 'utf-8'),
|
|
494
|
+
},
|
|
495
|
+
},
|
|
496
|
+
},
|
|
497
|
+
});
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
**Option 2: `stylesheet`** — A URL the browser can fetch directly
|
|
501
|
+
|
|
502
|
+
Use this when the stylesheet is hosted at a known URL (CDN, public path, etc.).
|
|
503
|
+
|
|
504
|
+
```ts
|
|
505
|
+
// config/plugins.ts
|
|
506
|
+
|
|
507
|
+
export default () => ({
|
|
508
|
+
'tiptap-editor': {
|
|
509
|
+
config: {
|
|
510
|
+
theme: {
|
|
511
|
+
stylesheet: 'https://cdn.example.com/editor-styles.css',
|
|
512
|
+
},
|
|
513
|
+
},
|
|
514
|
+
},
|
|
515
|
+
});
|
|
516
|
+
```
|
|
517
|
+
|
|
419
518
|
## Configuration Reference
|
|
420
519
|
|
|
421
520
|
### Feature Values
|
|
@@ -474,6 +573,10 @@ export default () => ({
|
|
|
474
573
|
// Text alignment (left, center, right, justify)
|
|
475
574
|
textAlign: true,
|
|
476
575
|
|
|
576
|
+
// Text and highlight colors (requires theme.colors)
|
|
577
|
+
textColor: true,
|
|
578
|
+
highlightColor: true,
|
|
579
|
+
|
|
477
580
|
// Images from Strapi Media Library
|
|
478
581
|
mediaLibrary: true,
|
|
479
582
|
},
|
|
@@ -6,7 +6,7 @@ import ReactDOM, { flushSync } from "react-dom";
|
|
|
6
6
|
import styled from "styled-components";
|
|
7
7
|
import { useField, useFetchClient } from "@strapi/strapi/admin";
|
|
8
8
|
import { Quotes, Code as Code$1, NumberList, BulletList as BulletList$1, StrikeThrough, Underline as Underline$1, Italic as Italic$1, Bold as Bold$1, Link as Link$1, Trash, Image as Image$1, GridNine } from "@strapi/icons";
|
|
9
|
-
import { g as getMediaLibraryComponent, a as getThemeCache } from "./index-
|
|
9
|
+
import { g as getMediaLibraryComponent, a as getThemeCache } from "./index-sX8SY6P-.mjs";
|
|
10
10
|
var shim = { exports: {} };
|
|
11
11
|
var useSyncExternalStoreShim_production = {};
|
|
12
12
|
/**
|
|
@@ -8,7 +8,7 @@ const ReactDOM = require("react-dom");
|
|
|
8
8
|
const styled = require("styled-components");
|
|
9
9
|
const admin = require("@strapi/strapi/admin");
|
|
10
10
|
const icons = require("@strapi/icons");
|
|
11
|
-
const index = require("./index-
|
|
11
|
+
const index = require("./index-yXpX_VsO.js");
|
|
12
12
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
13
13
|
const React__default = /* @__PURE__ */ _interopDefault(React);
|
|
14
14
|
const ReactDOM__default = /* @__PURE__ */ _interopDefault(ReactDOM);
|
|
@@ -47,7 +47,13 @@ function reconcileThemeStyles(theme) {
|
|
|
47
47
|
document.head.appendChild(style);
|
|
48
48
|
return Promise.resolve();
|
|
49
49
|
}
|
|
50
|
-
|
|
50
|
+
let resolved;
|
|
51
|
+
try {
|
|
52
|
+
resolved = new URL(stylesheet, document.baseURI).href;
|
|
53
|
+
} catch {
|
|
54
|
+
console.warn("[TiptapEditor] Invalid stylesheet URL:", stylesheet);
|
|
55
|
+
return Promise.resolve();
|
|
56
|
+
}
|
|
51
57
|
if (existing && existing.tagName === "LINK" && existing.href === resolved && existing.sheet) {
|
|
52
58
|
return Promise.resolve();
|
|
53
59
|
}
|
|
@@ -84,8 +90,13 @@ const Initializer = ({ setPlugin }) => {
|
|
|
84
90
|
} catch (error) {
|
|
85
91
|
console.warn("[TiptapEditor] Failed to fetch theme config:", error);
|
|
86
92
|
}
|
|
87
|
-
|
|
88
|
-
|
|
93
|
+
try {
|
|
94
|
+
await reconcileThemeStyles(themeStyles);
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.warn("[TiptapEditor] Failed to reconcile theme styles:", error);
|
|
97
|
+
} finally {
|
|
98
|
+
ref.current(PLUGIN_ID);
|
|
99
|
+
}
|
|
89
100
|
};
|
|
90
101
|
fetchTheme();
|
|
91
102
|
}, []);
|
|
@@ -135,7 +146,7 @@ const richTextField = {
|
|
|
135
146
|
},
|
|
136
147
|
icon: Paragraph,
|
|
137
148
|
components: {
|
|
138
|
-
Input: async () => import("./RichTextInput-
|
|
149
|
+
Input: async () => import("./RichTextInput-B8CLPOyo.mjs").then((m) => ({ default: m.default }))
|
|
139
150
|
},
|
|
140
151
|
options: {
|
|
141
152
|
advanced: [
|
|
@@ -48,7 +48,13 @@ function reconcileThemeStyles(theme) {
|
|
|
48
48
|
document.head.appendChild(style);
|
|
49
49
|
return Promise.resolve();
|
|
50
50
|
}
|
|
51
|
-
|
|
51
|
+
let resolved;
|
|
52
|
+
try {
|
|
53
|
+
resolved = new URL(stylesheet, document.baseURI).href;
|
|
54
|
+
} catch {
|
|
55
|
+
console.warn("[TiptapEditor] Invalid stylesheet URL:", stylesheet);
|
|
56
|
+
return Promise.resolve();
|
|
57
|
+
}
|
|
52
58
|
if (existing && existing.tagName === "LINK" && existing.href === resolved && existing.sheet) {
|
|
53
59
|
return Promise.resolve();
|
|
54
60
|
}
|
|
@@ -85,8 +91,13 @@ const Initializer = ({ setPlugin }) => {
|
|
|
85
91
|
} catch (error) {
|
|
86
92
|
console.warn("[TiptapEditor] Failed to fetch theme config:", error);
|
|
87
93
|
}
|
|
88
|
-
|
|
89
|
-
|
|
94
|
+
try {
|
|
95
|
+
await reconcileThemeStyles(themeStyles);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
console.warn("[TiptapEditor] Failed to reconcile theme styles:", error);
|
|
98
|
+
} finally {
|
|
99
|
+
ref.current(PLUGIN_ID);
|
|
100
|
+
}
|
|
90
101
|
};
|
|
91
102
|
fetchTheme();
|
|
92
103
|
}, []);
|
|
@@ -136,7 +147,7 @@ const richTextField = {
|
|
|
136
147
|
},
|
|
137
148
|
icon: icons.Paragraph,
|
|
138
149
|
components: {
|
|
139
|
-
Input: async () => Promise.resolve().then(() => require("./RichTextInput-
|
|
150
|
+
Input: async () => Promise.resolve().then(() => require("./RichTextInput-EtL-yFqV.js")).then((m) => ({ default: m.default }))
|
|
140
151
|
},
|
|
141
152
|
options: {
|
|
142
153
|
advanced: [
|
package/dist/admin/index.js
CHANGED
package/dist/admin/index.mjs
CHANGED
package/dist/shared/types.d.ts
CHANGED
|
@@ -17,13 +17,18 @@ export type ThemeColorEntry = {
|
|
|
17
17
|
label: string;
|
|
18
18
|
color: string;
|
|
19
19
|
};
|
|
20
|
-
|
|
21
|
-
colors?: ThemeColorEntry[];
|
|
20
|
+
type ThemeStyleSource = {
|
|
22
21
|
/** A browser-fetchable URL for an external stylesheet */
|
|
23
22
|
stylesheet?: string;
|
|
23
|
+
css?: never;
|
|
24
|
+
} | {
|
|
25
|
+
stylesheet?: never;
|
|
24
26
|
/** Inline CSS content to inject via a <style> tag */
|
|
25
27
|
css?: string;
|
|
26
28
|
};
|
|
29
|
+
export type TiptapThemeConfig = {
|
|
30
|
+
colors?: ThemeColorEntry[];
|
|
31
|
+
} & ThemeStyleSource;
|
|
27
32
|
export interface TiptapPresetConfig {
|
|
28
33
|
bold?: boolean | Record<string, unknown>;
|
|
29
34
|
italic?: boolean | Record<string, unknown>;
|
|
@@ -67,3 +72,4 @@ export declare const isFeatureEnabled: (value: TiptapPresetConfig[keyof TiptapPr
|
|
|
67
72
|
* NOTE: false returns null — DIVERGES from dist where false returns defaults.
|
|
68
73
|
*/
|
|
69
74
|
export declare const getFeatureOptions: <T extends Record<string, unknown>>(value: boolean | T | undefined, defaults: T) => T | null;
|
|
75
|
+
export {};
|
package/package.json
CHANGED