@notum-cz/strapi-plugin-tiptap-editor 1.0.1 → 1.0.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 +85 -55
- package/dist/_chunks/{RichTextInput-BZQ2iVqa.mjs → RichTextInput-COGVRWOW.mjs} +786 -596
- package/dist/_chunks/RichTextInput-COGVRWOW.mjs.map +1 -0
- package/dist/_chunks/{RichTextInput-BlxoJMa2.js → RichTextInput-Wc2q__HY.js} +785 -595
- package/dist/_chunks/RichTextInput-Wc2q__HY.js.map +1 -0
- package/dist/admin/index.js +23 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +23 -1
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/src/components/BaseTiptapInput.d.ts +1 -0
- package/dist/admin/src/components/EditorErrorBoundary.d.ts +23 -0
- package/dist/admin/src/components/FeatureGuard.d.ts +15 -0
- package/dist/admin/src/components/PresetSelect.d.ts +7 -0
- package/dist/admin/src/extensions/Heading.d.ts +1 -0
- package/dist/admin/src/fields/richTextField.d.ts +18 -0
- package/dist/admin/src/hooks/usePresetConfig.d.ts +6 -0
- package/dist/admin/src/utils/buildExtensions.d.ts +3 -0
- package/dist/server/index.js +154 -6
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +153 -6
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/config/index.d.ts +7 -4
- package/dist/server/src/controllers/index.d.ts +8 -1
- package/dist/server/src/controllers/preset.d.ts +8 -0
- package/dist/server/src/index.d.ts +43 -5
- package/dist/server/src/routes/index.d.ts +15 -1
- package/dist/server/src/services/index.d.ts +9 -1
- package/dist/server/src/services/preset.d.ts +10 -0
- package/dist/shared/types.d.ts +54 -0
- package/package.json +11 -3
- package/dist/_chunks/AccentCursive-CpAPpH9C.mjs +0 -3383
- package/dist/_chunks/AccentCursive-CpAPpH9C.mjs.map +0 -1
- package/dist/_chunks/AccentCursive-D6sTlhub.js +0 -3384
- package/dist/_chunks/AccentCursive-D6sTlhub.js.map +0 -1
- package/dist/_chunks/FormattedHeadingInput-DycgfIze.mjs +0 -101
- package/dist/_chunks/FormattedHeadingInput-DycgfIze.mjs.map +0 -1
- package/dist/_chunks/FormattedHeadingInput-FFjiRSEJ.js +0 -101
- package/dist/_chunks/FormattedHeadingInput-FFjiRSEJ.js.map +0 -1
- package/dist/_chunks/RichTextInput-BZQ2iVqa.mjs.map +0 -1
- package/dist/_chunks/RichTextInput-BbbQxPc-.js +0 -4414
- package/dist/_chunks/RichTextInput-BbbQxPc-.js.map +0 -1
- package/dist/_chunks/RichTextInput-BjLR2pi0.js +0 -4416
- package/dist/_chunks/RichTextInput-BjLR2pi0.js.map +0 -1
- package/dist/_chunks/RichTextInput-BlxoJMa2.js.map +0 -1
- package/dist/_chunks/RichTextInput-Bm3X8fR2.mjs +0 -4400
- package/dist/_chunks/RichTextInput-Bm3X8fR2.mjs.map +0 -1
- package/dist/_chunks/RichTextInput-Bms-gSvK.js +0 -4407
- package/dist/_chunks/RichTextInput-Bms-gSvK.js.map +0 -1
- package/dist/_chunks/RichTextInput-BtNjPJRN.mjs +0 -4400
- package/dist/_chunks/RichTextInput-BtNjPJRN.mjs.map +0 -1
- package/dist/_chunks/RichTextInput-Bw3tcXfp.js +0 -4407
- package/dist/_chunks/RichTextInput-Bw3tcXfp.js.map +0 -1
- package/dist/_chunks/RichTextInput-CsgNpoxq.mjs +0 -4409
- package/dist/_chunks/RichTextInput-CsgNpoxq.mjs.map +0 -1
- package/dist/_chunks/RichTextInput-CwTvEMda.js +0 -4407
- package/dist/_chunks/RichTextInput-CwTvEMda.js.map +0 -1
- package/dist/_chunks/RichTextInput-DG-36krM.js +0 -1181
- package/dist/_chunks/RichTextInput-DG-36krM.js.map +0 -1
- package/dist/_chunks/RichTextInput-DLac-zNQ.mjs +0 -4400
- package/dist/_chunks/RichTextInput-DLac-zNQ.mjs.map +0 -1
- package/dist/_chunks/RichTextInput-DSXttrvi.js +0 -4407
- package/dist/_chunks/RichTextInput-DSXttrvi.js.map +0 -1
- package/dist/_chunks/RichTextInput-DeJ6Exto.mjs +0 -4400
- package/dist/_chunks/RichTextInput-DeJ6Exto.mjs.map +0 -1
- package/dist/_chunks/RichTextInput-DgT88AkO.mjs +0 -1175
- package/dist/_chunks/RichTextInput-DgT88AkO.mjs.map +0 -1
- package/dist/_chunks/RichTextInput-DlMaDJQF.mjs +0 -4400
- package/dist/_chunks/RichTextInput-DlMaDJQF.mjs.map +0 -1
- package/dist/_chunks/RichTextInput-DtaYdjCs.mjs +0 -4400
- package/dist/_chunks/RichTextInput-DtaYdjCs.mjs.map +0 -1
- package/dist/_chunks/RichTextInput-YTKXo5oq.js +0 -4407
- package/dist/_chunks/RichTextInput-YTKXo5oq.js.map +0 -1
- package/dist/_chunks/RichTextInput-tmg-oMJk.mjs +0 -4407
- package/dist/_chunks/RichTextInput-tmg-oMJk.mjs.map +0 -1
- package/dist/_chunks/RichTextInput-umhMsI5o.js +0 -4407
- package/dist/_chunks/RichTextInput-umhMsI5o.js.map +0 -1
- package/dist/admin/src/components/FormattedHeadingInput.d.ts +0 -4
- package/dist/admin/src/extensions/AccentCursive.d.ts +0 -18
- package/dist/admin/src/fields/formattedHeadingField.d.ts +0 -20
- package/dist/admin/src/pluginId.d.ts +0 -1
package/dist/admin/index.js
CHANGED
|
@@ -41,7 +41,29 @@ const richTextField = {
|
|
|
41
41
|
icon: icons.Paragraph,
|
|
42
42
|
// cast to any to avoid some weird non-exported type issue during build
|
|
43
43
|
components: {
|
|
44
|
-
Input: async () => Promise.resolve().then(() => require("../_chunks/RichTextInput-
|
|
44
|
+
Input: async () => Promise.resolve().then(() => require("../_chunks/RichTextInput-Wc2q__HY.js")).then((m) => ({ default: m.default }))
|
|
45
|
+
},
|
|
46
|
+
options: {
|
|
47
|
+
advanced: [
|
|
48
|
+
{
|
|
49
|
+
sectionTitle: null,
|
|
50
|
+
items: [
|
|
51
|
+
{
|
|
52
|
+
name: "options.preset",
|
|
53
|
+
type: "select",
|
|
54
|
+
intlLabel: {
|
|
55
|
+
id: "tiptap-editor.preset.label",
|
|
56
|
+
defaultMessage: "Editor Preset"
|
|
57
|
+
},
|
|
58
|
+
description: {
|
|
59
|
+
id: "tiptap-editor.preset.description",
|
|
60
|
+
defaultMessage: "Select the preset that configures available editing tools."
|
|
61
|
+
},
|
|
62
|
+
options: []
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
]
|
|
45
67
|
}
|
|
46
68
|
};
|
|
47
69
|
const index = {
|
package/dist/admin/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../shared/pluginId.ts","../../admin/src/components/Initializer.tsx","../../shared/fields.ts","../../admin/src/fields/richTextField.ts","../../admin/src/index.ts"],"sourcesContent":["export const PLUGIN_ID = 'tiptap-editor';\n","import { useEffect, useRef } from 'react';\n\nimport { PLUGIN_ID } from '../../../shared/pluginId';\n\ntype InitializerProps = {\n setPlugin: (id: string) => void;\n};\n\nconst Initializer = ({ setPlugin }: InitializerProps) => {\n const ref = useRef(setPlugin);\n\n useEffect(() => {\n ref.current(PLUGIN_ID);\n }, []);\n\n return null;\n};\n\nexport { Initializer };\n","export const RICH_TEXT_FIELD_NAME = 'RichText';\n","import { PLUGIN_ID } from '../../../shared/pluginId';\nimport { Paragraph } from '@strapi/icons';\nimport { ComponentType } from 'react';\nimport { RICH_TEXT_FIELD_NAME } from '../../../shared/fields';\n\nexport const richTextField = {\n name: RICH_TEXT_FIELD_NAME,\n pluginId: PLUGIN_ID,\n type: 'string',\n intlLabel: {\n id: 'tiptap-editor.richText.label',\n defaultMessage: 'Rich Text (Tiptap)',\n },\n intlDescription: {\n id: 'tiptap-editor.richText.description',\n defaultMessage: 'Use this field to create formatted text via Tiptap editor.',\n },\n icon: Paragraph as ComponentType<any>, // cast to any to avoid some weird non-exported type issue during build\n components: {\n Input: async () => import('../components/RichTextInput').then((m) => ({ default: m.default })),\n },\n};\n","import { PLUGIN_ID } from '../../shared/pluginId';\nimport { Initializer } from './components/Initializer';\n\nimport { richTextField } from './fields/richTextField';\n\nexport default {\n register(app: any) {\n app.registerPlugin({\n id: PLUGIN_ID,\n initializer: Initializer,\n isReady: false,\n name: PLUGIN_ID,\n });\n\n app.customFields.register(richTextField);\n },\n\n async registerTrads({ locales }: { locales: string[] }) {\n return Promise.all(\n locales.map(async (locale) => {\n try {\n const { default: data } = await import(`./translations/${locale}.json`);\n\n return { data, locale };\n } catch {\n return { data: {}, locale };\n }\n })\n );\n },\n};\n"],"names":["useRef","useEffect","Paragraph"],"mappings":";;;;;;;;;;;;;;;;;;;AAAO,MAAM,YAAY;ACQzB,MAAM,cAAc,CAAC,EAAE,gBAAkC;AACvD,QAAM,MAAMA,MAAAA,OAAO,SAAS;AAE5BC,QAAAA,UAAU,MAAM;AACd,QAAI,QAAQ,SAAS;AAAA,EACvB,GAAG,CAAA,CAAE;AAEL,SAAO;AACT;AChBO,MAAM,uBAAuB;ACK7B,MAAM,gBAAgB;AAAA,EAC3B,MAAM;AAAA,EACN,UAAU;AAAA,EACV,MAAM;AAAA,EACN,WAAW;AAAA,IACT,IAAI;AAAA,IACJ,gBAAgB;AAAA,EAAA;AAAA,EAElB,iBAAiB;AAAA,IACf,IAAI;AAAA,IACJ,gBAAgB;AAAA,EAAA;AAAA,EAElB,MAAMC,MAAAA;AAAAA;AAAAA,EACN,YAAY;AAAA,IACV,OAAO,YAAY,qCAAO,sCAA6B,CAAA,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU;AAAA,EAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../shared/pluginId.ts","../../admin/src/components/Initializer.tsx","../../shared/fields.ts","../../admin/src/fields/richTextField.ts","../../admin/src/index.ts"],"sourcesContent":["export const PLUGIN_ID = 'tiptap-editor';\n","import { useEffect, useRef } from 'react';\n\nimport { PLUGIN_ID } from '../../../shared/pluginId';\n\ntype InitializerProps = {\n setPlugin: (id: string) => void;\n};\n\nconst Initializer = ({ setPlugin }: InitializerProps) => {\n const ref = useRef(setPlugin);\n\n useEffect(() => {\n ref.current(PLUGIN_ID);\n }, []);\n\n return null;\n};\n\nexport { Initializer };\n","export const RICH_TEXT_FIELD_NAME = 'RichText';\n","import { PLUGIN_ID } from '../../../shared/pluginId';\nimport { Paragraph } from '@strapi/icons';\nimport { ComponentType } from 'react';\nimport { RICH_TEXT_FIELD_NAME } from '../../../shared/fields';\n\nexport const richTextField = {\n name: RICH_TEXT_FIELD_NAME,\n pluginId: PLUGIN_ID,\n type: 'string',\n intlLabel: {\n id: 'tiptap-editor.richText.label',\n defaultMessage: 'Rich Text (Tiptap)',\n },\n intlDescription: {\n id: 'tiptap-editor.richText.description',\n defaultMessage: 'Use this field to create formatted text via Tiptap editor.',\n },\n icon: Paragraph as ComponentType<any>, // cast to any to avoid some weird non-exported type issue during build\n components: {\n Input: async () => import('../components/RichTextInput').then((m) => ({ default: m.default })),\n },\n options: {\n advanced: [\n {\n sectionTitle: null,\n items: [\n {\n name: 'options.preset',\n type: 'select',\n intlLabel: {\n id: 'tiptap-editor.preset.label',\n defaultMessage: 'Editor Preset',\n },\n description: {\n id: 'tiptap-editor.preset.description',\n defaultMessage: 'Select the preset that configures available editing tools.',\n },\n options: [],\n },\n ],\n },\n ],\n },\n};\n","import { PLUGIN_ID } from '../../shared/pluginId';\nimport { Initializer } from './components/Initializer';\n\nimport { richTextField } from './fields/richTextField';\n\nexport default {\n register(app: any) {\n app.registerPlugin({\n id: PLUGIN_ID,\n initializer: Initializer,\n isReady: false,\n name: PLUGIN_ID,\n });\n\n app.customFields.register(richTextField);\n },\n\n async registerTrads({ locales }: { locales: string[] }) {\n return Promise.all(\n locales.map(async (locale) => {\n try {\n const { default: data } = await import(`./translations/${locale}.json`);\n\n return { data, locale };\n } catch {\n return { data: {}, locale };\n }\n })\n );\n },\n};\n"],"names":["useRef","useEffect","Paragraph"],"mappings":";;;;;;;;;;;;;;;;;;;AAAO,MAAM,YAAY;ACQzB,MAAM,cAAc,CAAC,EAAE,gBAAkC;AACvD,QAAM,MAAMA,MAAAA,OAAO,SAAS;AAE5BC,QAAAA,UAAU,MAAM;AACd,QAAI,QAAQ,SAAS;AAAA,EACvB,GAAG,CAAA,CAAE;AAEL,SAAO;AACT;AChBO,MAAM,uBAAuB;ACK7B,MAAM,gBAAgB;AAAA,EAC3B,MAAM;AAAA,EACN,UAAU;AAAA,EACV,MAAM;AAAA,EACN,WAAW;AAAA,IACT,IAAI;AAAA,IACJ,gBAAgB;AAAA,EAAA;AAAA,EAElB,iBAAiB;AAAA,IACf,IAAI;AAAA,IACJ,gBAAgB;AAAA,EAAA;AAAA,EAElB,MAAMC,MAAAA;AAAAA;AAAAA,EACN,YAAY;AAAA,IACV,OAAO,YAAY,qCAAO,sCAA6B,CAAA,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU;AAAA,EAAA;AAAA,EAE/F,SAAS;AAAA,IACP,UAAU;AAAA,MACR;AAAA,QACE,cAAc;AAAA,QACd,OAAO;AAAA,UACL;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA,YACN,WAAW;AAAA,cACT,IAAI;AAAA,cACJ,gBAAgB;AAAA,YAAA;AAAA,YAElB,aAAa;AAAA,cACX,IAAI;AAAA,cACJ,gBAAgB;AAAA,YAAA;AAAA,YAElB,SAAS,CAAA;AAAA,UAAC;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEJ;ACtCA,MAAA,QAAe;AAAA,EACb,SAAS,KAAU;AACjB,QAAI,eAAe;AAAA,MACjB,IAAI;AAAA,MACJ,aAAa;AAAA,MACb,SAAS;AAAA,MACT,MAAM;AAAA,IAAA,CACP;AAED,QAAI,aAAa,SAAS,aAAa;AAAA,EACzC;AAAA,EAEA,MAAM,cAAc,EAAE,WAAkC;AACtD,WAAO,QAAQ;AAAA,MACb,QAAQ,IAAI,OAAO,WAAW;AAC5B,YAAI;AACF,gBAAM,EAAE,SAAS,KAAA,IAAS,MAAM,qCAAA,uBAAA,OAAA,EAAA,0BAAA,MAAA,QAAA,QAAA,EAAA,KAAA,MAAA,QAAA,2BAAA,CAAA,EAAA,CAAA,GAAA,kBAAA,MAAA,SAAA,CAAA;AAEhC,iBAAO,EAAE,MAAM,OAAA;AAAA,QACjB,QAAQ;AACN,iBAAO,EAAE,MAAM,CAAA,GAAI,OAAA;AAAA,QACrB;AAAA,MACF,CAAC;AAAA,IAAA;AAAA,EAEL;AACF;;"}
|
package/dist/admin/index.mjs
CHANGED
|
@@ -40,7 +40,29 @@ const richTextField = {
|
|
|
40
40
|
icon: Paragraph,
|
|
41
41
|
// cast to any to avoid some weird non-exported type issue during build
|
|
42
42
|
components: {
|
|
43
|
-
Input: async () => import("../_chunks/RichTextInput-
|
|
43
|
+
Input: async () => import("../_chunks/RichTextInput-COGVRWOW.mjs").then((m) => ({ default: m.default }))
|
|
44
|
+
},
|
|
45
|
+
options: {
|
|
46
|
+
advanced: [
|
|
47
|
+
{
|
|
48
|
+
sectionTitle: null,
|
|
49
|
+
items: [
|
|
50
|
+
{
|
|
51
|
+
name: "options.preset",
|
|
52
|
+
type: "select",
|
|
53
|
+
intlLabel: {
|
|
54
|
+
id: "tiptap-editor.preset.label",
|
|
55
|
+
defaultMessage: "Editor Preset"
|
|
56
|
+
},
|
|
57
|
+
description: {
|
|
58
|
+
id: "tiptap-editor.preset.description",
|
|
59
|
+
defaultMessage: "Select the preset that configures available editing tools."
|
|
60
|
+
},
|
|
61
|
+
options: []
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
]
|
|
44
66
|
}
|
|
45
67
|
};
|
|
46
68
|
const index = {
|
package/dist/admin/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../shared/pluginId.ts","../../admin/src/components/Initializer.tsx","../../shared/fields.ts","../../admin/src/fields/richTextField.ts","../../admin/src/index.ts"],"sourcesContent":["export const PLUGIN_ID = 'tiptap-editor';\n","import { useEffect, useRef } from 'react';\n\nimport { PLUGIN_ID } from '../../../shared/pluginId';\n\ntype InitializerProps = {\n setPlugin: (id: string) => void;\n};\n\nconst Initializer = ({ setPlugin }: InitializerProps) => {\n const ref = useRef(setPlugin);\n\n useEffect(() => {\n ref.current(PLUGIN_ID);\n }, []);\n\n return null;\n};\n\nexport { Initializer };\n","export const RICH_TEXT_FIELD_NAME = 'RichText';\n","import { PLUGIN_ID } from '../../../shared/pluginId';\nimport { Paragraph } from '@strapi/icons';\nimport { ComponentType } from 'react';\nimport { RICH_TEXT_FIELD_NAME } from '../../../shared/fields';\n\nexport const richTextField = {\n name: RICH_TEXT_FIELD_NAME,\n pluginId: PLUGIN_ID,\n type: 'string',\n intlLabel: {\n id: 'tiptap-editor.richText.label',\n defaultMessage: 'Rich Text (Tiptap)',\n },\n intlDescription: {\n id: 'tiptap-editor.richText.description',\n defaultMessage: 'Use this field to create formatted text via Tiptap editor.',\n },\n icon: Paragraph as ComponentType<any>, // cast to any to avoid some weird non-exported type issue during build\n components: {\n Input: async () => import('../components/RichTextInput').then((m) => ({ default: m.default })),\n },\n};\n","import { PLUGIN_ID } from '../../shared/pluginId';\nimport { Initializer } from './components/Initializer';\n\nimport { richTextField } from './fields/richTextField';\n\nexport default {\n register(app: any) {\n app.registerPlugin({\n id: PLUGIN_ID,\n initializer: Initializer,\n isReady: false,\n name: PLUGIN_ID,\n });\n\n app.customFields.register(richTextField);\n },\n\n async registerTrads({ locales }: { locales: string[] }) {\n return Promise.all(\n locales.map(async (locale) => {\n try {\n const { default: data } = await import(`./translations/${locale}.json`);\n\n return { data, locale };\n } catch {\n return { data: {}, locale };\n }\n })\n );\n },\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAO,MAAM,YAAY;ACQzB,MAAM,cAAc,CAAC,EAAE,gBAAkC;AACvD,QAAM,MAAM,OAAO,SAAS;AAE5B,YAAU,MAAM;AACd,QAAI,QAAQ,SAAS;AAAA,EACvB,GAAG,CAAA,CAAE;AAEL,SAAO;AACT;AChBO,MAAM,uBAAuB;ACK7B,MAAM,gBAAgB;AAAA,EAC3B,MAAM;AAAA,EACN,UAAU;AAAA,EACV,MAAM;AAAA,EACN,WAAW;AAAA,IACT,IAAI;AAAA,IACJ,gBAAgB;AAAA,EAAA;AAAA,EAElB,iBAAiB;AAAA,IACf,IAAI;AAAA,IACJ,gBAAgB;AAAA,EAAA;AAAA,EAElB,MAAM;AAAA;AAAA,EACN,YAAY;AAAA,IACV,OAAO,YAAY,OAAO,uCAA6B,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU;AAAA,EAAA;
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../shared/pluginId.ts","../../admin/src/components/Initializer.tsx","../../shared/fields.ts","../../admin/src/fields/richTextField.ts","../../admin/src/index.ts"],"sourcesContent":["export const PLUGIN_ID = 'tiptap-editor';\n","import { useEffect, useRef } from 'react';\n\nimport { PLUGIN_ID } from '../../../shared/pluginId';\n\ntype InitializerProps = {\n setPlugin: (id: string) => void;\n};\n\nconst Initializer = ({ setPlugin }: InitializerProps) => {\n const ref = useRef(setPlugin);\n\n useEffect(() => {\n ref.current(PLUGIN_ID);\n }, []);\n\n return null;\n};\n\nexport { Initializer };\n","export const RICH_TEXT_FIELD_NAME = 'RichText';\n","import { PLUGIN_ID } from '../../../shared/pluginId';\nimport { Paragraph } from '@strapi/icons';\nimport { ComponentType } from 'react';\nimport { RICH_TEXT_FIELD_NAME } from '../../../shared/fields';\n\nexport const richTextField = {\n name: RICH_TEXT_FIELD_NAME,\n pluginId: PLUGIN_ID,\n type: 'string',\n intlLabel: {\n id: 'tiptap-editor.richText.label',\n defaultMessage: 'Rich Text (Tiptap)',\n },\n intlDescription: {\n id: 'tiptap-editor.richText.description',\n defaultMessage: 'Use this field to create formatted text via Tiptap editor.',\n },\n icon: Paragraph as ComponentType<any>, // cast to any to avoid some weird non-exported type issue during build\n components: {\n Input: async () => import('../components/RichTextInput').then((m) => ({ default: m.default })),\n },\n options: {\n advanced: [\n {\n sectionTitle: null,\n items: [\n {\n name: 'options.preset',\n type: 'select',\n intlLabel: {\n id: 'tiptap-editor.preset.label',\n defaultMessage: 'Editor Preset',\n },\n description: {\n id: 'tiptap-editor.preset.description',\n defaultMessage: 'Select the preset that configures available editing tools.',\n },\n options: [],\n },\n ],\n },\n ],\n },\n};\n","import { PLUGIN_ID } from '../../shared/pluginId';\nimport { Initializer } from './components/Initializer';\n\nimport { richTextField } from './fields/richTextField';\n\nexport default {\n register(app: any) {\n app.registerPlugin({\n id: PLUGIN_ID,\n initializer: Initializer,\n isReady: false,\n name: PLUGIN_ID,\n });\n\n app.customFields.register(richTextField);\n },\n\n async registerTrads({ locales }: { locales: string[] }) {\n return Promise.all(\n locales.map(async (locale) => {\n try {\n const { default: data } = await import(`./translations/${locale}.json`);\n\n return { data, locale };\n } catch {\n return { data: {}, locale };\n }\n })\n );\n },\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAO,MAAM,YAAY;ACQzB,MAAM,cAAc,CAAC,EAAE,gBAAkC;AACvD,QAAM,MAAM,OAAO,SAAS;AAE5B,YAAU,MAAM;AACd,QAAI,QAAQ,SAAS;AAAA,EACvB,GAAG,CAAA,CAAE;AAEL,SAAO;AACT;AChBO,MAAM,uBAAuB;ACK7B,MAAM,gBAAgB;AAAA,EAC3B,MAAM;AAAA,EACN,UAAU;AAAA,EACV,MAAM;AAAA,EACN,WAAW;AAAA,IACT,IAAI;AAAA,IACJ,gBAAgB;AAAA,EAAA;AAAA,EAElB,iBAAiB;AAAA,IACf,IAAI;AAAA,IACJ,gBAAgB;AAAA,EAAA;AAAA,EAElB,MAAM;AAAA;AAAA,EACN,YAAY;AAAA,IACV,OAAO,YAAY,OAAO,uCAA6B,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU;AAAA,EAAA;AAAA,EAE/F,SAAS;AAAA,IACP,UAAU;AAAA,MACR;AAAA,QACE,cAAc;AAAA,QACd,OAAO;AAAA,UACL;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA,YACN,WAAW;AAAA,cACT,IAAI;AAAA,cACJ,gBAAgB;AAAA,YAAA;AAAA,YAElB,aAAa;AAAA,cACX,IAAI;AAAA,cACJ,gBAAgB;AAAA,YAAA;AAAA,YAElB,SAAS,CAAA;AAAA,UAAC;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEJ;ACtCA,MAAA,QAAe;AAAA,EACb,SAAS,KAAU;AACjB,QAAI,eAAe;AAAA,MACjB,IAAI;AAAA,MACJ,aAAa;AAAA,MACb,SAAS;AAAA,MACT,MAAM;AAAA,IAAA,CACP;AAED,QAAI,aAAa,SAAS,aAAa;AAAA,EACzC;AAAA,EAEA,MAAM,cAAc,EAAE,WAAkC;AACtD,WAAO,QAAQ;AAAA,MACb,QAAQ,IAAI,OAAO,WAAW;AAC5B,YAAI;AACF,gBAAM,EAAE,SAAS,KAAA,IAAS,MAAM,qCAAA,uBAAA,OAAA,EAAA,0BAAA,MAAA,OAAA,4BAAA,EAAA,CAAA,GAAA,kBAAA,MAAA,SAAA,CAAA;AAEhC,iBAAO,EAAE,MAAM,OAAA;AAAA,QACjB,QAAQ;AACN,iBAAO,EAAE,MAAM,CAAA,GAAI,OAAA;AAAA,QACrB;AAAA,MACF,CAAC;AAAA,IAAA;AAAA,EAEL;AACF;"}
|
|
@@ -7,6 +7,7 @@ type TiptapInputProps = InputProps & {
|
|
|
7
7
|
editor: Editor;
|
|
8
8
|
field: FieldValue;
|
|
9
9
|
children?: React.ReactNode;
|
|
10
|
+
noPresetConfigured?: boolean;
|
|
10
11
|
};
|
|
11
12
|
declare const BaseTiptapInput: import("react").ForwardRefExoticComponent<TiptapInputProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
12
13
|
export default BaseTiptapInput;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Component, ErrorInfo, ReactNode } from 'react';
|
|
2
|
+
interface Props {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
}
|
|
5
|
+
interface State {
|
|
6
|
+
hasError: boolean;
|
|
7
|
+
error: Error | null;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Error boundary that wraps the editor content area.
|
|
11
|
+
* Catches render errors in children and displays a fallback UI with a retry button.
|
|
12
|
+
* Logs errors with [TiptapEditor] prefix for debugging.
|
|
13
|
+
*
|
|
14
|
+
* Created in Phase 2 but wired into RichTextInput in Phase 3.
|
|
15
|
+
*/
|
|
16
|
+
export declare class EditorErrorBoundary extends Component<Props, State> {
|
|
17
|
+
state: State;
|
|
18
|
+
static getDerivedStateFromError(error: Error): Partial<State>;
|
|
19
|
+
componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
|
|
20
|
+
handleRetry: () => void;
|
|
21
|
+
render(): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element | null | undefined;
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { TiptapPresetConfig } from '../../../shared/types';
|
|
3
|
+
interface FeatureGuardProps {
|
|
4
|
+
/** The feature config value from TiptapPresetConfig (e.g., config.bold, config.heading) */
|
|
5
|
+
featureValue: TiptapPresetConfig[keyof TiptapPresetConfig];
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Conditionally renders children based on whether a feature is enabled in the preset config.
|
|
10
|
+
* When disabled, returns null — children never mount, so any hooks inside are never called.
|
|
11
|
+
* This is the primary mechanism for HOOKS-01/HOOKS-02: hooks don't need internal config gating
|
|
12
|
+
* because FeatureGuard prevents them from being called entirely.
|
|
13
|
+
*/
|
|
14
|
+
export declare function FeatureGuard({ featureValue, children }: FeatureGuardProps): ReactNode;
|
|
15
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Editor } from '@tiptap/core';
|
|
2
|
+
export declare const BaseHeadingWithSEOTag: import("@tiptap/core").Node<import("@tiptap/extension-heading").HeadingOptions, any>;
|
|
2
3
|
export declare const HeadingWithSEOTag: import("@tiptap/core").Node<import("@tiptap/extension-heading").HeadingOptions, any>;
|
|
3
4
|
export declare function useHeading(editor: Editor, props?: {
|
|
4
5
|
disabled?: boolean;
|
|
@@ -17,4 +17,22 @@ export declare const richTextField: {
|
|
|
17
17
|
default: import("react").ForwardRefExoticComponent<import("../utils/tiptapUtils").TiptapInputProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
18
18
|
}>;
|
|
19
19
|
};
|
|
20
|
+
options: {
|
|
21
|
+
advanced: {
|
|
22
|
+
sectionTitle: null;
|
|
23
|
+
items: {
|
|
24
|
+
name: string;
|
|
25
|
+
type: string;
|
|
26
|
+
intlLabel: {
|
|
27
|
+
id: string;
|
|
28
|
+
defaultMessage: string;
|
|
29
|
+
};
|
|
30
|
+
description: {
|
|
31
|
+
id: string;
|
|
32
|
+
defaultMessage: string;
|
|
33
|
+
};
|
|
34
|
+
options: never[];
|
|
35
|
+
}[];
|
|
36
|
+
}[];
|
|
37
|
+
};
|
|
20
38
|
};
|
package/dist/server/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
2
3
|
const bootstrap = ({ strapi }) => {
|
|
3
4
|
};
|
|
4
5
|
const destroy = ({ strapi }) => {
|
|
@@ -17,17 +18,160 @@ const richTextField = {
|
|
|
17
18
|
const register = ({ strapi }) => {
|
|
18
19
|
strapi.customFields.register(richTextField);
|
|
19
20
|
};
|
|
21
|
+
const PRESET_FEATURE_KEYS = [
|
|
22
|
+
"bold",
|
|
23
|
+
"italic",
|
|
24
|
+
"strike",
|
|
25
|
+
"code",
|
|
26
|
+
"codeBlock",
|
|
27
|
+
"blockquote",
|
|
28
|
+
"bulletList",
|
|
29
|
+
"orderedList",
|
|
30
|
+
"hardBreak",
|
|
31
|
+
"horizontalRule",
|
|
32
|
+
"history",
|
|
33
|
+
"heading",
|
|
34
|
+
"link",
|
|
35
|
+
"table",
|
|
36
|
+
"textAlign",
|
|
37
|
+
"superscript",
|
|
38
|
+
"subscript"
|
|
39
|
+
];
|
|
40
|
+
const MINIMAL_PRESET_CONFIG = {
|
|
41
|
+
bold: true,
|
|
42
|
+
italic: true
|
|
43
|
+
};
|
|
44
|
+
const isPlainObject$1 = (value) => {
|
|
45
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
46
|
+
const prototype = Object.getPrototypeOf(value);
|
|
47
|
+
return prototype === Object.prototype || prototype === null;
|
|
48
|
+
};
|
|
49
|
+
const isFeatureEnabled = (value) => {
|
|
50
|
+
if (value === void 0) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
if (typeof value === "boolean") {
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
if (!isPlainObject$1(value)) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
const obj = value;
|
|
60
|
+
if (typeof obj.enabled === "boolean") {
|
|
61
|
+
return obj.enabled;
|
|
62
|
+
}
|
|
63
|
+
if (typeof obj.disabled === "boolean") {
|
|
64
|
+
return !obj.disabled;
|
|
65
|
+
}
|
|
66
|
+
return true;
|
|
67
|
+
};
|
|
68
|
+
const getFeatureOptions = (value, defaults) => {
|
|
69
|
+
if (value === false) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
if (!isPlainObject$1(value)) {
|
|
73
|
+
return defaults;
|
|
74
|
+
}
|
|
75
|
+
const { enabled: _e, disabled: _d, ...rest } = value;
|
|
76
|
+
return { ...defaults, ...rest };
|
|
77
|
+
};
|
|
78
|
+
const isPlainObject = (value) => {
|
|
79
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
80
|
+
const prototype = Object.getPrototypeOf(value);
|
|
81
|
+
return prototype === Object.prototype || prototype === null;
|
|
82
|
+
};
|
|
83
|
+
const FEATURE_KEYS = new Set(PRESET_FEATURE_KEYS);
|
|
84
|
+
const getInvalidKeys = (presetConfig) => {
|
|
85
|
+
if (!isPlainObject(presetConfig)) return [];
|
|
86
|
+
return Object.keys(presetConfig).filter(
|
|
87
|
+
(key) => !FEATURE_KEYS.has(key)
|
|
88
|
+
);
|
|
89
|
+
};
|
|
20
90
|
const config = {
|
|
21
|
-
default: {
|
|
22
|
-
|
|
91
|
+
default: {
|
|
92
|
+
presets: {}
|
|
93
|
+
},
|
|
94
|
+
validator(pluginConfig) {
|
|
95
|
+
if (!isPlainObject(pluginConfig)) {
|
|
96
|
+
throw new Error("tiptap-editor plugin config must be a plain object");
|
|
97
|
+
}
|
|
98
|
+
const typedConfig = pluginConfig;
|
|
99
|
+
const { presets } = typedConfig;
|
|
100
|
+
if (presets === void 0) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (!isPlainObject(presets)) {
|
|
104
|
+
throw new Error("tiptap-editor config.presets must be a plain object");
|
|
105
|
+
}
|
|
106
|
+
const allInvalidKeys = [];
|
|
107
|
+
for (const [presetName, presetConfig] of Object.entries(
|
|
108
|
+
presets
|
|
109
|
+
)) {
|
|
110
|
+
const invalidKeys = getInvalidKeys(presetConfig);
|
|
111
|
+
if (invalidKeys.length > 0) {
|
|
112
|
+
allInvalidKeys.push(...invalidKeys);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (allInvalidKeys.length > 0) {
|
|
116
|
+
throw new Error(
|
|
117
|
+
`tiptap-editor config.presets contains invalid feature keys: ${allInvalidKeys.join(", ")}. Allowed keys: ${PRESET_FEATURE_KEYS.join(", ")}`
|
|
118
|
+
);
|
|
119
|
+
}
|
|
23
120
|
}
|
|
24
121
|
};
|
|
25
122
|
const contentTypes = {};
|
|
26
|
-
const
|
|
123
|
+
const createPresetController = ({ strapi }) => ({
|
|
124
|
+
async find(ctx) {
|
|
125
|
+
const presetService = strapi.plugin("tiptap-editor").service("preset");
|
|
126
|
+
ctx.body = { presets: presetService.listPresetNames() };
|
|
127
|
+
},
|
|
128
|
+
async findOne(ctx) {
|
|
129
|
+
const presetService = strapi.plugin("tiptap-editor").service("preset");
|
|
130
|
+
const presetName = ctx.params?.name;
|
|
131
|
+
const preset = presetService.getPreset(presetName);
|
|
132
|
+
ctx.body = preset ?? MINIMAL_PRESET_CONFIG;
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
const controllers = {
|
|
136
|
+
preset: createPresetController
|
|
137
|
+
};
|
|
27
138
|
const middlewares = {};
|
|
28
139
|
const policies = {};
|
|
29
|
-
const routes = {
|
|
30
|
-
|
|
140
|
+
const routes = {
|
|
141
|
+
"preset-routes": {
|
|
142
|
+
type: "admin",
|
|
143
|
+
routes: [
|
|
144
|
+
{
|
|
145
|
+
method: "GET",
|
|
146
|
+
path: "/presets",
|
|
147
|
+
handler: "preset.find",
|
|
148
|
+
config: { auth: false, policies: [], middlewares: [] }
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
method: "GET",
|
|
152
|
+
path: "/presets/:name",
|
|
153
|
+
handler: "preset.findOne",
|
|
154
|
+
config: { auth: false, policies: [], middlewares: [] }
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
const DEFAULT_CONFIG = { presets: {} };
|
|
160
|
+
const createPresetService = ({ strapi }) => ({
|
|
161
|
+
getConfig() {
|
|
162
|
+
return strapi.config.get("plugin::tiptap-editor", DEFAULT_CONFIG);
|
|
163
|
+
},
|
|
164
|
+
listPresetNames() {
|
|
165
|
+
return Object.keys(this.getConfig().presets || {});
|
|
166
|
+
},
|
|
167
|
+
getPreset(name) {
|
|
168
|
+
const presets = this.getConfig().presets || {};
|
|
169
|
+
return presets[name] ?? null;
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
const services = {
|
|
173
|
+
preset: createPresetService
|
|
174
|
+
};
|
|
31
175
|
const index = {
|
|
32
176
|
register,
|
|
33
177
|
bootstrap,
|
|
@@ -40,5 +184,9 @@ const index = {
|
|
|
40
184
|
policies,
|
|
41
185
|
middlewares
|
|
42
186
|
};
|
|
43
|
-
|
|
187
|
+
exports.MINIMAL_PRESET_CONFIG = MINIMAL_PRESET_CONFIG;
|
|
188
|
+
exports.PRESET_FEATURE_KEYS = PRESET_FEATURE_KEYS;
|
|
189
|
+
exports.default = index;
|
|
190
|
+
exports.getFeatureOptions = getFeatureOptions;
|
|
191
|
+
exports.isFeatureEnabled = isFeatureEnabled;
|
|
44
192
|
//# sourceMappingURL=index.js.map
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../server/src/bootstrap.ts","../../server/src/destroy.ts","../../shared/pluginId.ts","../../shared/fields.ts","../../server/src/fields/richTextField.ts","../../server/src/register.ts","../../server/src/config/index.ts","../../server/src/content-types/index.ts","../../server/src/controllers/index.ts","../../server/src/middlewares/index.ts","../../server/src/policies/index.ts","../../server/src/routes/index.ts","../../server/src/services/index.ts","../../server/src/index.ts"],"sourcesContent":["import type { Core } from '@strapi/strapi';\n\nconst bootstrap = ({ strapi }: { strapi: Core.Strapi }) => {\n // bootstrap phase\n};\n\nexport default bootstrap;\n","import type { Core } from '@strapi/strapi';\n\nconst destroy = ({ strapi }: { strapi: Core.Strapi }) => {\n // destroy phase\n};\n\nexport default destroy;\n","export const PLUGIN_ID = 'tiptap-editor';\n","export const RICH_TEXT_FIELD_NAME = 'RichText';\n","import { PLUGIN_ID } from '../../../shared/pluginId';\nimport { RICH_TEXT_FIELD_NAME } from '../../../shared/fields';\nimport { CustomFieldServerOptions } from '@strapi/types/dist/modules/custom-fields';\n\nexport const richTextField: CustomFieldServerOptions = {\n name: RICH_TEXT_FIELD_NAME,\n plugin: PLUGIN_ID,\n type: 'text',\n inputSize: {\n default: 12,\n isResizable: true,\n },\n};\n","import type { Core } from '@strapi/strapi';\n\nimport { richTextField } from './fields/richTextField';\n\nconst register = ({ strapi }: { strapi: Core.Strapi }) => {\n strapi.customFields.register(richTextField);\n};\n\nexport default register;\n","export default {\n default: {},\n validator() {},\n};\n","export default {};\n","export default {};\n","export default {};\n","export default {};\n","export default {};\n","export default {};\n","/**\n * Application methods\n */\nimport bootstrap from './bootstrap';\nimport destroy from './destroy';\nimport register from './register';\n\n/**\n * Plugin server methods\n */\nimport config from './config';\nimport contentTypes from './content-types';\nimport controllers from './controllers';\nimport middlewares from './middlewares';\nimport policies from './policies';\nimport routes from './routes';\nimport services from './services';\n\nexport default {\n register,\n bootstrap,\n destroy,\n config,\n controllers,\n routes,\n services,\n contentTypes,\n policies,\n middlewares,\n} as const; // Type Assertion necessary due to the error below\n\n/**\n * [ERROR] server/src/index.ts:19:1 - TS2742: The inferred type of 'default' cannot be named without a reference to '@strapi/core/node_modules/@strapi/types/dist/core'. This is likely not portable. A type annotation is necessary.\n */\n"],"names":[],"mappings":";AAEA,MAAM,YAAY,CAAC,EAAE,aAAsC;AAE3D;ACFA,MAAM,UAAU,CAAC,EAAE,aAAsC;AAEzD;ACJO,MAAM,YAAY;ACAlB,MAAM,uBAAuB;ACI7B,MAAM,gBAA0C;AAAA,EACrD,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,WAAW;AAAA,IACT,SAAS;AAAA,IACT,aAAa;AAAA,EAAA;AAEjB;ACRA,MAAM,WAAW,CAAC,EAAE,aAAsC;AACxD,SAAO,aAAa,SAAS,aAAa;AAC5C;ACNA,MAAA,SAAe;AAAA,EACb,SAAS,CAAA;AAAA,EACT,YAAY;AAAA,EAAC;AACf;ACHA,MAAA,eAAe,CAAA;ACAf,MAAA,cAAe,CAAA;ACAf,MAAA,cAAe,CAAA;ACAf,MAAA,WAAe,CAAA;ACAf,MAAA,SAAe,CAAA;ACAf,MAAA,WAAe,CAAA;ACkBf,MAAA,QAAe;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../server/src/bootstrap.ts","../../server/src/destroy.ts","../../shared/pluginId.ts","../../shared/fields.ts","../../server/src/fields/richTextField.ts","../../server/src/register.ts","../../shared/types.ts","../../server/src/config/index.ts","../../server/src/content-types/index.ts","../../server/src/controllers/preset.ts","../../server/src/controllers/index.ts","../../server/src/middlewares/index.ts","../../server/src/policies/index.ts","../../server/src/routes/index.ts","../../server/src/services/preset.ts","../../server/src/services/index.ts","../../server/src/index.ts"],"sourcesContent":["import type { Core } from '@strapi/strapi';\n\nconst bootstrap = ({ strapi }: { strapi: Core.Strapi }) => {\n // bootstrap phase\n};\n\nexport default bootstrap;\n","import type { Core } from '@strapi/strapi';\n\nconst destroy = ({ strapi }: { strapi: Core.Strapi }) => {\n // destroy phase\n};\n\nexport default destroy;\n","export const PLUGIN_ID = 'tiptap-editor';\n","export const RICH_TEXT_FIELD_NAME = 'RichText';\n","import { PLUGIN_ID } from '../../../shared/pluginId';\nimport { RICH_TEXT_FIELD_NAME } from '../../../shared/fields';\nimport { CustomFieldServerOptions } from '@strapi/types/dist/modules/custom-fields';\n\nexport const richTextField: CustomFieldServerOptions = {\n name: RICH_TEXT_FIELD_NAME,\n plugin: PLUGIN_ID,\n type: 'text',\n inputSize: {\n default: 12,\n isResizable: true,\n },\n};\n","import type { Core } from '@strapi/strapi';\n\nimport { richTextField } from './fields/richTextField';\n\nconst register = ({ strapi }: { strapi: Core.Strapi }) => {\n strapi.customFields.register(richTextField);\n};\n\nexport default register;\n","// shared/types.ts\n\n// ─── Option types ───────────────────────────────────────────────────────────\n\nexport type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;\n\nexport type LinkConfig = {\n openOnClick?: boolean;\n HTMLAttributes?: Record<string, string>;\n};\n\nexport type TableConfig = {\n resizable?: boolean;\n};\n\nexport type TextAlignConfig = {\n types?: string[];\n alignments?: Array<'left' | 'center' | 'right' | 'justify'>;\n};\n\nexport type HeadingConfig = {\n levels?: HeadingLevel[];\n};\n\n// ─── Core types ──────────────────────────────────────────────────────────────\n\nexport interface TiptapPresetConfig {\n bold?: boolean | Record<string, unknown>;\n italic?: boolean | Record<string, unknown>;\n strike?: boolean | Record<string, unknown>;\n code?: boolean | Record<string, unknown>;\n codeBlock?: boolean | Record<string, unknown>;\n blockquote?: boolean | Record<string, unknown>;\n bulletList?: boolean | Record<string, unknown>;\n orderedList?: boolean | Record<string, unknown>;\n hardBreak?: boolean | Record<string, unknown>;\n horizontalRule?: boolean | Record<string, unknown>;\n history?: boolean | Record<string, unknown>;\n heading?: boolean | HeadingConfig;\n link?: boolean | LinkConfig;\n table?: boolean | TableConfig;\n textAlign?: boolean | TextAlignConfig;\n superscript?: boolean | Record<string, unknown>;\n subscript?: boolean | Record<string, unknown>;\n}\n\nexport interface TiptapPluginConfig {\n presets: Record<string, TiptapPresetConfig>;\n}\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nexport const PRESET_FEATURE_KEYS: Array<keyof TiptapPresetConfig> = [\n 'bold', 'italic', 'strike', 'code', 'codeBlock', 'blockquote',\n 'bulletList', 'orderedList', 'hardBreak', 'horizontalRule', 'history',\n 'heading', 'link', 'table', 'textAlign', 'superscript', 'subscript',\n];\n\n// Fallback for unconfigured fields — deliberately minimal to prompt developers to configure\nexport const MINIMAL_PRESET_CONFIG: TiptapPresetConfig = {\n bold: true,\n italic: true,\n};\n\n// ─── Internal helpers ────────────────────────────────────────────────────────\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\n\n// ─── Utility functions ───────────────────────────────────────────────────────\n\n/**\n * Returns true when a preset feature value is enabled.\n * NOTE: undefined (absent key) returns true — absent key = feature enabled by default.\n * This DIVERGES from dist where undefined returns false.\n */\nexport const isFeatureEnabled = (\n value: TiptapPresetConfig[keyof TiptapPresetConfig]\n): boolean => {\n if (value === undefined) {\n return true; // TYPES-04: absent key = enabled\n }\n if (typeof value === 'boolean') {\n return value;\n }\n if (!isPlainObject(value)) {\n return false;\n }\n const obj = value as Record<string, unknown>;\n if (typeof obj.enabled === 'boolean') {\n return obj.enabled;\n }\n if (typeof obj.disabled === 'boolean') {\n return !obj.disabled;\n }\n return true;\n};\n\n/**\n * Returns the effective options for a feature.\n * - false → null (feature explicitly disabled, no options)\n * - true | undefined → defaults (feature enabled with default options)\n * - object → merged with defaults (feature enabled with custom options)\n *\n * NOTE: false returns null — DIVERGES from dist where false returns defaults.\n */\nexport const getFeatureOptions = <T extends Record<string, unknown>>(\n value: boolean | T | undefined,\n defaults: T\n): T | null => {\n if (value === false) {\n return null; // TYPES-05: explicitly disabled\n }\n if (!isPlainObject(value)) {\n return defaults; // true or undefined: return defaults\n }\n const { enabled: _e, disabled: _d, ...rest } = value as Record<string, unknown>;\n return { ...defaults, ...rest } as T;\n};\n","import {\n PRESET_FEATURE_KEYS,\n TiptapPluginConfig,\n TiptapPresetConfig,\n} from '../../../shared/types';\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false;\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\n\nconst FEATURE_KEYS = new Set(PRESET_FEATURE_KEYS);\n\nconst getInvalidKeys = (presetConfig: unknown): string[] => {\n if (!isPlainObject(presetConfig)) return [];\n return Object.keys(presetConfig).filter(\n (key) => !FEATURE_KEYS.has(key as keyof TiptapPresetConfig)\n );\n};\n\nconst config = {\n default: {\n presets: {} as Record<string, TiptapPresetConfig>,\n },\n validator(pluginConfig: unknown): void {\n if (!isPlainObject(pluginConfig)) {\n throw new Error('tiptap-editor plugin config must be a plain object');\n }\n\n const typedConfig = pluginConfig as { presets?: unknown };\n const { presets } = typedConfig;\n\n if (presets === undefined) {\n return; // presets key is optional\n }\n\n if (!isPlainObject(presets)) {\n throw new Error('tiptap-editor config.presets must be a plain object');\n }\n\n const allInvalidKeys: string[] = [];\n for (const [presetName, presetConfig] of Object.entries(\n presets as Record<string, unknown>\n )) {\n const invalidKeys = getInvalidKeys(presetConfig);\n if (invalidKeys.length > 0) {\n allInvalidKeys.push(...invalidKeys);\n }\n }\n\n if (allInvalidKeys.length > 0) {\n throw new Error(\n `tiptap-editor config.presets contains invalid feature keys: ${allInvalidKeys.join(', ')}. ` +\n `Allowed keys: ${PRESET_FEATURE_KEYS.join(', ')}`\n );\n }\n },\n} satisfies { default: TiptapPluginConfig; validator: (config: unknown) => void };\n\nexport default config;\n","export default {};\n","import type { Core } from '@strapi/strapi';\nimport { MINIMAL_PRESET_CONFIG } from '../../../shared/types';\n\nconst createPresetController = ({ strapi }: { strapi: Core.Strapi }) => ({\n async find(ctx: any): Promise<void> {\n const presetService = strapi.plugin('tiptap-editor').service('preset') as any;\n ctx.body = { presets: presetService.listPresetNames() };\n },\n\n async findOne(ctx: any): Promise<void> {\n const presetService = strapi.plugin('tiptap-editor').service('preset') as any;\n const presetName: string = ctx.params?.name;\n const preset = presetService.getPreset(presetName);\n // Return MINIMAL_PRESET_CONFIG for unknown presets (never 404) — SERVER-03\n ctx.body = preset ?? MINIMAL_PRESET_CONFIG;\n },\n});\n\nexport default createPresetController;\n","import createPresetController from './preset';\n\nexport default {\n preset: createPresetController,\n};\n","export default {};\n","export default {};\n","export default {\n 'preset-routes': {\n type: 'admin' as const,\n routes: [\n {\n method: 'GET',\n path: '/presets',\n handler: 'preset.find',\n config: { auth: false, policies: [], middlewares: [] },\n },\n {\n method: 'GET',\n path: '/presets/:name',\n handler: 'preset.findOne',\n config: { auth: false, policies: [], middlewares: [] },\n },\n ],\n },\n};\n","import type { Core } from '@strapi/strapi';\nimport {\n TiptapPluginConfig,\n TiptapPresetConfig,\n} from '../../../shared/types';\n\nconst DEFAULT_CONFIG: TiptapPluginConfig = { presets: {} };\n\nconst createPresetService = ({ strapi }: { strapi: Core.Strapi }) => ({\n getConfig(): TiptapPluginConfig {\n return strapi.config.get('plugin::tiptap-editor', DEFAULT_CONFIG) as TiptapPluginConfig;\n },\n\n listPresetNames(): string[] {\n return Object.keys(this.getConfig().presets || {});\n },\n\n getPreset(name: string): TiptapPresetConfig | null {\n const presets = this.getConfig().presets || {};\n return presets[name] ?? null;\n },\n});\n\nexport default createPresetService;\n","import createPresetService from './preset';\n\nexport default {\n preset: createPresetService,\n};\n","/**\n * Application methods\n */\nimport bootstrap from './bootstrap';\nimport destroy from './destroy';\nimport register from './register';\n\n/**\n * Plugin server methods\n */\nimport config from './config';\nimport contentTypes from './content-types';\nimport controllers from './controllers';\nimport middlewares from './middlewares';\nimport policies from './policies';\nimport routes from './routes';\nimport services from './services';\n\nexport default {\n register,\n bootstrap,\n destroy,\n config,\n controllers,\n routes,\n services,\n contentTypes,\n policies,\n middlewares,\n} as const; // Type Assertion necessary due to the error below\n\n/**\n * [ERROR] server/src/index.ts:19:1 - TS2742: The inferred type of 'default' cannot be named without a reference to '@strapi/core/node_modules/@strapi/types/dist/core'. This is likely not portable. A type annotation is necessary.\n */\n\n// Re-export shared types for host app developer access via the ./strapi-server entry point\nexport type { TiptapPresetConfig, TiptapPluginConfig } from '../../shared/types';\nexport {\n PRESET_FEATURE_KEYS,\n MINIMAL_PRESET_CONFIG,\n isFeatureEnabled,\n getFeatureOptions,\n} from '../../shared/types';\n"],"names":["isPlainObject"],"mappings":"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"}
|
package/dist/server/index.mjs
CHANGED
|
@@ -16,17 +16,160 @@ const richTextField = {
|
|
|
16
16
|
const register = ({ strapi }) => {
|
|
17
17
|
strapi.customFields.register(richTextField);
|
|
18
18
|
};
|
|
19
|
+
const PRESET_FEATURE_KEYS = [
|
|
20
|
+
"bold",
|
|
21
|
+
"italic",
|
|
22
|
+
"strike",
|
|
23
|
+
"code",
|
|
24
|
+
"codeBlock",
|
|
25
|
+
"blockquote",
|
|
26
|
+
"bulletList",
|
|
27
|
+
"orderedList",
|
|
28
|
+
"hardBreak",
|
|
29
|
+
"horizontalRule",
|
|
30
|
+
"history",
|
|
31
|
+
"heading",
|
|
32
|
+
"link",
|
|
33
|
+
"table",
|
|
34
|
+
"textAlign",
|
|
35
|
+
"superscript",
|
|
36
|
+
"subscript"
|
|
37
|
+
];
|
|
38
|
+
const MINIMAL_PRESET_CONFIG = {
|
|
39
|
+
bold: true,
|
|
40
|
+
italic: true
|
|
41
|
+
};
|
|
42
|
+
const isPlainObject$1 = (value) => {
|
|
43
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
44
|
+
const prototype = Object.getPrototypeOf(value);
|
|
45
|
+
return prototype === Object.prototype || prototype === null;
|
|
46
|
+
};
|
|
47
|
+
const isFeatureEnabled = (value) => {
|
|
48
|
+
if (value === void 0) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
if (typeof value === "boolean") {
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
if (!isPlainObject$1(value)) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
const obj = value;
|
|
58
|
+
if (typeof obj.enabled === "boolean") {
|
|
59
|
+
return obj.enabled;
|
|
60
|
+
}
|
|
61
|
+
if (typeof obj.disabled === "boolean") {
|
|
62
|
+
return !obj.disabled;
|
|
63
|
+
}
|
|
64
|
+
return true;
|
|
65
|
+
};
|
|
66
|
+
const getFeatureOptions = (value, defaults) => {
|
|
67
|
+
if (value === false) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
if (!isPlainObject$1(value)) {
|
|
71
|
+
return defaults;
|
|
72
|
+
}
|
|
73
|
+
const { enabled: _e, disabled: _d, ...rest } = value;
|
|
74
|
+
return { ...defaults, ...rest };
|
|
75
|
+
};
|
|
76
|
+
const isPlainObject = (value) => {
|
|
77
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
78
|
+
const prototype = Object.getPrototypeOf(value);
|
|
79
|
+
return prototype === Object.prototype || prototype === null;
|
|
80
|
+
};
|
|
81
|
+
const FEATURE_KEYS = new Set(PRESET_FEATURE_KEYS);
|
|
82
|
+
const getInvalidKeys = (presetConfig) => {
|
|
83
|
+
if (!isPlainObject(presetConfig)) return [];
|
|
84
|
+
return Object.keys(presetConfig).filter(
|
|
85
|
+
(key) => !FEATURE_KEYS.has(key)
|
|
86
|
+
);
|
|
87
|
+
};
|
|
19
88
|
const config = {
|
|
20
|
-
default: {
|
|
21
|
-
|
|
89
|
+
default: {
|
|
90
|
+
presets: {}
|
|
91
|
+
},
|
|
92
|
+
validator(pluginConfig) {
|
|
93
|
+
if (!isPlainObject(pluginConfig)) {
|
|
94
|
+
throw new Error("tiptap-editor plugin config must be a plain object");
|
|
95
|
+
}
|
|
96
|
+
const typedConfig = pluginConfig;
|
|
97
|
+
const { presets } = typedConfig;
|
|
98
|
+
if (presets === void 0) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (!isPlainObject(presets)) {
|
|
102
|
+
throw new Error("tiptap-editor config.presets must be a plain object");
|
|
103
|
+
}
|
|
104
|
+
const allInvalidKeys = [];
|
|
105
|
+
for (const [presetName, presetConfig] of Object.entries(
|
|
106
|
+
presets
|
|
107
|
+
)) {
|
|
108
|
+
const invalidKeys = getInvalidKeys(presetConfig);
|
|
109
|
+
if (invalidKeys.length > 0) {
|
|
110
|
+
allInvalidKeys.push(...invalidKeys);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (allInvalidKeys.length > 0) {
|
|
114
|
+
throw new Error(
|
|
115
|
+
`tiptap-editor config.presets contains invalid feature keys: ${allInvalidKeys.join(", ")}. Allowed keys: ${PRESET_FEATURE_KEYS.join(", ")}`
|
|
116
|
+
);
|
|
117
|
+
}
|
|
22
118
|
}
|
|
23
119
|
};
|
|
24
120
|
const contentTypes = {};
|
|
25
|
-
const
|
|
121
|
+
const createPresetController = ({ strapi }) => ({
|
|
122
|
+
async find(ctx) {
|
|
123
|
+
const presetService = strapi.plugin("tiptap-editor").service("preset");
|
|
124
|
+
ctx.body = { presets: presetService.listPresetNames() };
|
|
125
|
+
},
|
|
126
|
+
async findOne(ctx) {
|
|
127
|
+
const presetService = strapi.plugin("tiptap-editor").service("preset");
|
|
128
|
+
const presetName = ctx.params?.name;
|
|
129
|
+
const preset = presetService.getPreset(presetName);
|
|
130
|
+
ctx.body = preset ?? MINIMAL_PRESET_CONFIG;
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
const controllers = {
|
|
134
|
+
preset: createPresetController
|
|
135
|
+
};
|
|
26
136
|
const middlewares = {};
|
|
27
137
|
const policies = {};
|
|
28
|
-
const routes = {
|
|
29
|
-
|
|
138
|
+
const routes = {
|
|
139
|
+
"preset-routes": {
|
|
140
|
+
type: "admin",
|
|
141
|
+
routes: [
|
|
142
|
+
{
|
|
143
|
+
method: "GET",
|
|
144
|
+
path: "/presets",
|
|
145
|
+
handler: "preset.find",
|
|
146
|
+
config: { auth: false, policies: [], middlewares: [] }
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
method: "GET",
|
|
150
|
+
path: "/presets/:name",
|
|
151
|
+
handler: "preset.findOne",
|
|
152
|
+
config: { auth: false, policies: [], middlewares: [] }
|
|
153
|
+
}
|
|
154
|
+
]
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
const DEFAULT_CONFIG = { presets: {} };
|
|
158
|
+
const createPresetService = ({ strapi }) => ({
|
|
159
|
+
getConfig() {
|
|
160
|
+
return strapi.config.get("plugin::tiptap-editor", DEFAULT_CONFIG);
|
|
161
|
+
},
|
|
162
|
+
listPresetNames() {
|
|
163
|
+
return Object.keys(this.getConfig().presets || {});
|
|
164
|
+
},
|
|
165
|
+
getPreset(name) {
|
|
166
|
+
const presets = this.getConfig().presets || {};
|
|
167
|
+
return presets[name] ?? null;
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
const services = {
|
|
171
|
+
preset: createPresetService
|
|
172
|
+
};
|
|
30
173
|
const index = {
|
|
31
174
|
register,
|
|
32
175
|
bootstrap,
|
|
@@ -40,6 +183,10 @@ const index = {
|
|
|
40
183
|
middlewares
|
|
41
184
|
};
|
|
42
185
|
export {
|
|
43
|
-
|
|
186
|
+
MINIMAL_PRESET_CONFIG,
|
|
187
|
+
PRESET_FEATURE_KEYS,
|
|
188
|
+
index as default,
|
|
189
|
+
getFeatureOptions,
|
|
190
|
+
isFeatureEnabled
|
|
44
191
|
};
|
|
45
192
|
//# sourceMappingURL=index.mjs.map
|