@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 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-DB8F5E26.mjs";
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-CsjxcNiy.js");
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
- const resolved = new URL(stylesheet, document.baseURI).href;
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
- await reconcileThemeStyles(themeStyles);
88
- ref.current(PLUGIN_ID);
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-NZH5L_pW.mjs").then((m) => ({ default: m.default }))
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
- const resolved = new URL(stylesheet, document.baseURI).href;
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
- await reconcileThemeStyles(themeStyles);
89
- ref.current(PLUGIN_ID);
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-zyphJZp3.js")).then((m) => ({ default: m.default }))
150
+ Input: async () => Promise.resolve().then(() => require("./RichTextInput-EtL-yFqV.js")).then((m) => ({ default: m.default }))
140
151
  },
141
152
  options: {
142
153
  advanced: [
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
- const index = require("../_chunks/index-CsjxcNiy.js");
2
+ const index = require("../_chunks/index-yXpX_VsO.js");
3
3
  module.exports = index.index;
@@ -1,4 +1,4 @@
1
- import { i } from "../_chunks/index-DB8F5E26.mjs";
1
+ import { i } from "../_chunks/index-sX8SY6P-.mjs";
2
2
  export {
3
3
  i as default
4
4
  };
@@ -17,13 +17,18 @@ export type ThemeColorEntry = {
17
17
  label: string;
18
18
  color: string;
19
19
  };
20
- export type TiptapThemeConfig = {
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
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.3-rc.6",
2
+ "version": "1.1.1",
3
3
  "keywords": [
4
4
  "strapi",
5
5
  "plugin",