From 6625acc3bb103284316d7f32a11d8a2600c7078b Mon Sep 17 00:00:00 2001 From: nshenderov Date: Wed, 11 Dec 2024 13:35:10 +0300 Subject: [PATCH] feat: new plugin configuration method (#191) BREAKING CHANGE: ckeditor.js|ts file is no longer supported for plugin configuration. The plugin now requires using the setPluginConfig method for configuration. Existing setups must be updated to call this method before the admin panel's bootstrap lifecycle. dontMergePresets and dontMergeTheme options have been removed. User-provided configuration objects now completely overwrite the default ones. --- admin/custom.d.ts | 3 + admin/src/components/CKEReact.tsx | 7 +- admin/src/components/EditorLayout.tsx | 4 +- admin/src/components/EditorProvider.tsx | 24 ++- admin/src/components/Field.tsx | 2 +- admin/src/components/GlobalStyling.tsx | 9 +- admin/src/components/MediaLib.tsx | 8 +- admin/src/config/defaultPreset.ts | 12 +- admin/src/config/expToGlobal.ts | 19 --- admin/src/config/index.ts | 2 - admin/src/config/pluginConfig.ts | 67 ++++++--- admin/src/config/presets.ts | 57 -------- admin/src/config/types.ts | 161 ++++++++++++++------- admin/src/exports.ts | 11 +- admin/src/index.ts | 34 ++++- admin/src/plugins/StrapiUploadAdapter.ts | 36 ++--- admin/src/utils/index.ts | 3 +- admin/src/utils/isImageResponsive.ts | 5 + package.json | 4 +- server/src/controllers/configController.ts | 19 --- server/src/controllers/index.ts | 5 - server/src/index.ts | 18 ++- server/src/register.ts | 10 -- server/src/routes/index.ts | 15 -- server/src/services/configService.ts | 53 ------- server/src/services/index.ts | 5 - server/src/utils/pluginId.ts | 5 - 27 files changed, 262 insertions(+), 336 deletions(-) delete mode 100644 admin/src/config/expToGlobal.ts delete mode 100644 admin/src/config/presets.ts create mode 100644 admin/src/utils/isImageResponsive.ts delete mode 100644 server/src/controllers/configController.ts delete mode 100644 server/src/controllers/index.ts delete mode 100644 server/src/register.ts delete mode 100644 server/src/routes/index.ts delete mode 100644 server/src/services/configService.ts delete mode 100644 server/src/services/index.ts delete mode 100644 server/src/utils/pluginId.ts diff --git a/admin/custom.d.ts b/admin/custom.d.ts index 26db8f3..564534a 100644 --- a/admin/custom.d.ts +++ b/admin/custom.d.ts @@ -5,5 +5,8 @@ declare global { strapi: { backendURL: string; }; + SH_CKE: { + IS_UPLOAD_RESPONSIVE: boolean; + }; } } diff --git a/admin/src/components/CKEReact.tsx b/admin/src/components/CKEReact.tsx index 8d4e3a7..2a6b3e2 100644 --- a/admin/src/components/CKEReact.tsx +++ b/admin/src/components/CKEReact.tsx @@ -6,7 +6,7 @@ import { CKEditor } from '@ckeditor/ckeditor5-react'; import 'ckeditor5/ckeditor5.css'; import { useEditorContext } from './EditorProvider'; -import { getStoredToken } from '../utils'; +import { getStoredToken, prefixFileUrlWithBackendUrl } from '../utils'; import { MediaLib } from './MediaLib'; import type { StrapiMediaLibPlugin, @@ -130,12 +130,9 @@ export function CKEReact() { 'StrapiUploadAdapter' ) as StrapiUploadAdapterPlugin; const token = getStoredToken(); - const { backendURL } = window.strapi; const config: StrapiUploadAdapterConfig = { - uploadUrl: `${backendURL}/upload`, - backendUrl: backendURL, + uploadUrl: prefixFileUrlWithBackendUrl('/upload'), headers: { Authorization: `Bearer ${token}` }, - responsive: window.SH_CKE_UPLOAD_ADAPTER_IS_RESPONSIVE, }; StrapiUploadAdapterPlugin.initAdapter(config); diff --git a/admin/src/components/EditorLayout.tsx b/admin/src/components/EditorLayout.tsx index c69982a..0d123ff 100644 --- a/admin/src/components/EditorLayout.tsx +++ b/admin/src/components/EditorLayout.tsx @@ -3,7 +3,7 @@ import { Box, Flex, IconButton, FocusTrap, Portal } from '@strapi/design-system' import { Expand, Collapse } from '@strapi/icons'; import { css, styled } from 'styled-components'; -import type { Styles } from 'src/config'; +import type { CSS } from '../config'; import { useEditorContext } from './EditorProvider'; export function EditorLayout({ children }: { children: ReactNode }) { @@ -85,7 +85,7 @@ export function EditorLayout({ children }: { children: ReactNode }) { const EditorWrapper = styled('div')<{ $isExpanded: boolean; $hasError: boolean; - $presetStyles?: Styles; + $presetStyles?: CSS; }>` position: relative; width: 100%; diff --git a/admin/src/components/EditorProvider.tsx b/admin/src/components/EditorProvider.tsx index 511bfd0..af2e592 100644 --- a/admin/src/components/EditorProvider.tsx +++ b/admin/src/components/EditorProvider.tsx @@ -1,7 +1,7 @@ import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'; import type { InputProps } from '@strapi/strapi/admin'; -import { type Preset, getClonedPreset, setUpLanguage } from '../config'; +import { type Preset, setUpLanguage, getPluginConfig } from '../config'; import type { WordCountPluginStats } from './CKEReact'; type EditorProviderBaseProps = Pick< @@ -54,8 +54,8 @@ export function EditorProvider({ useEffect(() => { (async () => { - const currentPreset = getClonedPreset(presetName); - + const { presets } = getPluginConfig(); + const currentPreset = clonePreset(presets[presetName]); await setUpLanguage(currentPreset.editorConfig, isFieldLocalized); if (placeholder) { @@ -132,3 +132,21 @@ export function EditorProvider({ return {children}; } + +function clonePreset(preset: Preset): Preset { + const clonedPreset = { + ...preset, + editorConfig: { + ...preset.editorConfig, + }, + }; + + Object.entries(clonedPreset.editorConfig).forEach(([key, val]) => { + if (val && typeof val === 'object' && Object.getPrototypeOf(val) === Object.prototype) { + // @ts-ignore + clonedPreset.editorConfig[key] = { ...val }; + } + }); + + return clonedPreset; +} diff --git a/admin/src/components/Field.tsx b/admin/src/components/Field.tsx index 7d10808..007933c 100644 --- a/admin/src/components/Field.tsx +++ b/admin/src/components/Field.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { type InputProps, type FieldValue } from '@strapi/strapi/admin'; +import type { InputProps, FieldValue } from '@strapi/strapi/admin'; import { Editor } from './Editor'; import { EditorProvider } from './EditorProvider'; diff --git a/admin/src/components/GlobalStyling.tsx b/admin/src/components/GlobalStyling.tsx index f80395b..b585ed7 100644 --- a/admin/src/components/GlobalStyling.tsx +++ b/admin/src/components/GlobalStyling.tsx @@ -1,14 +1,13 @@ import React from 'react'; import { createGlobalStyle, css } from 'styled-components'; -import { defaultTheme } from '../theme'; import { getProfileTheme } from '../utils'; -import type { Theme, Styles } from '../config'; +import { type Theme, type CSS, getPluginConfig } from '../config'; const GlobalStyle = createGlobalStyle<{ $editortTheme?: Theme; $variant: 'light' | 'dark'; - $presetStyles?: Styles; + $presetStyles?: CSS; }>` ${({ $editortTheme, $variant }) => $editortTheme && @@ -23,11 +22,9 @@ const getSystemColorScheme = (): 'light' | 'dark' => window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; function GlobalStyling() { - const { theme: userTheme, dontMergeTheme } = window.SH_CKE_CONFIG || {}; - + const { theme } = getPluginConfig(); const profileTheme = getProfileTheme(); const variant = profileTheme && profileTheme !== 'system' ? profileTheme : getSystemColorScheme(); - const theme = dontMergeTheme ? userTheme : { ...defaultTheme, ...userTheme }; return ; } diff --git a/admin/src/components/MediaLib.tsx b/admin/src/components/MediaLib.tsx index 326b3df..930cea5 100644 --- a/admin/src/components/MediaLib.tsx +++ b/admin/src/components/MediaLib.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { useStrapiApp } from '@strapi/strapi/admin'; -import { prefixFileUrlWithBackendUrl } from '../utils'; +import { prefixFileUrlWithBackendUrl, isImageResponsive } from '../utils'; type MediaLibProps = { isOpen: boolean; @@ -34,8 +34,8 @@ function MediaLib({ isOpen = false, toggle, handleChangeAssets }: MediaLibProps) assets.forEach(({ name, url, alt, formats, mime, width, height }: any) => { if (mime.includes('image')) { - if (formats && window.SH_CKE_UPLOAD_ADAPTER_IS_RESPONSIVE) { - const set = formSet(formats); + if (formats && isImageResponsive(formats)) { + const set = formSrcSet(formats); newElems += `${alt}`; } else { newElems += `${alt}`; @@ -53,7 +53,7 @@ function MediaLib({ isOpen = false, toggle, handleChangeAssets }: MediaLibProps) return newElems; } - function formSet(formats: any): string { + function formSrcSet(formats: any): string { let set = ''; const keys = Object.keys(formats).sort((a, b) => formats[a].width - formats[b].width); keys.forEach(k => { diff --git a/admin/src/config/defaultPreset.ts b/admin/src/config/defaultPreset.ts index 67b0e4c..7fff80c 100644 --- a/admin/src/config/defaultPreset.ts +++ b/admin/src/config/defaultPreset.ts @@ -355,15 +355,7 @@ const defaultEditorConfig: EditorConfig = { }; export const defaultPreset: Preset = { - field: { - key: 'default', - value: 'default', - metadatas: { - intlLabel: { - id: 'ckeditor.preset.default.label', - defaultMessage: 'default', - }, - }, - }, + name: 'default', + description: 'default', editorConfig: defaultEditorConfig, }; diff --git a/admin/src/config/expToGlobal.ts b/admin/src/config/expToGlobal.ts deleted file mode 100644 index 70545f4..0000000 --- a/admin/src/config/expToGlobal.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as CKE from 'ckeditor5'; - -import { StrapiMediaLib, StrapiUploadAdapter } from '../plugins'; -import { materialColors } from './colors'; - -export type ExportToGlobal = typeof CKE & { - StrapiMediaLib: typeof StrapiMediaLib; - StrapiUploadAdapter: typeof StrapiUploadAdapter; - MaterialColors: typeof materialColors; -}; - -export function exportToGlobal(): void { - window.SH_CKE = { - ...CKE, - StrapiMediaLib, - StrapiUploadAdapter, - MaterialColors: materialColors, - }; -} diff --git a/admin/src/config/index.ts b/admin/src/config/index.ts index 41cd632..6e1b1fa 100644 --- a/admin/src/config/index.ts +++ b/admin/src/config/index.ts @@ -3,5 +3,3 @@ export * from './language'; export * from './pluginConfig'; export * from './colors'; export * from './defaultPreset'; -export * from './presets'; -export * from './expToGlobal'; diff --git a/admin/src/config/pluginConfig.ts b/admin/src/config/pluginConfig.ts index c11be93..76b50c8 100644 --- a/admin/src/config/pluginConfig.ts +++ b/admin/src/config/pluginConfig.ts @@ -1,27 +1,56 @@ -import type { PluginConfig } from './types'; -import { PLUGIN_ID } from '../utils'; +import { defaultTheme } from '../theme'; +import { defaultPreset } from './defaultPreset'; +import type { PluginConfig, UserPluginConfig } from './types'; -export async function getPluginConfig(): Promise { - const config = await loadConfig().catch(error => console.error('CKEditor: ', error)); +const PLUGIN_CONFIG: PluginConfig = { + presets: { + default: defaultPreset, + }, + theme: defaultTheme, +}; - return config || null; -} +/** + * Sets a configuration for the plugin. + * + * @remarks + * + * - The function must be invoked before the admin panel's bootstrap lifecycle function. + * + * - Provided objects will overwrite the default configuration values. + * + * - The provided configuration will be frozen after the first invocation, preventing further modifications. + * + * @param userConfig - The configuration object provided by the user. + * + * @public + */ +export function setPluginConfig(userConfig: UserPluginConfig): void { + const { presets, theme } = userConfig || {}; -async function loadConfig(): Promise { - return new Promise((resolve, reject) => { - const { backendURL } = window.strapi; - const url = - backendURL !== '/' - ? `${backendURL}/${PLUGIN_ID}/config/ckeditor` - : `/${PLUGIN_ID}/config/ckeditor`; + if (presets) { + presets.forEach(preset => { + PLUGIN_CONFIG.presets[preset.name] = preset; + }); + } - const script = document.createElement('script'); - script.id = 'ckeditor-config'; - script.src = url; + if (theme) { + PLUGIN_CONFIG.theme = theme; + } - script.onload = () => resolve(window.SH_CKE_CONFIG); - script.onerror = () => reject(new Error('Failed loading config script')); + deepFreeze(PLUGIN_CONFIG); +} - document.body.appendChild(script); +export function getPluginConfig(): PluginConfig { + if (!Object.isFrozen(PLUGIN_CONFIG)) deepFreeze(PLUGIN_CONFIG); + return PLUGIN_CONFIG; +} + +function deepFreeze(obj: Object): Readonly { + (Object.keys(obj) as (keyof typeof obj)[]).forEach(p => { + if (typeof obj[p] === 'object' && obj[p] !== null && !Object.isFrozen(obj[p])) { + deepFreeze(obj[p]); + } }); + + return Object.freeze(obj); } diff --git a/admin/src/config/presets.ts b/admin/src/config/presets.ts deleted file mode 100644 index 4e2a59d..0000000 --- a/admin/src/config/presets.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { defaultPreset } from './defaultPreset'; -import type { Field, PluginConfig, Preset } from './types'; - -export const pluginPresets: Record = { - default: defaultPreset, -}; - -export function getClonedPreset(presetName: string): Preset { - const { presets: userPresets, dontMergePresets } = window.SH_CKE_CONFIG || {}; - - if (dontMergePresets && !userPresets) { - console.error('CKEditor: No presets found'); - } - - const preset = - dontMergePresets && userPresets ? userPresets[presetName] : pluginPresets[presetName]; - - const clonedPreset = { - ...preset, - editorConfig: { - ...preset.editorConfig, - }, - }; - - return clonedPreset; -} - -export function getPresetsFields(config: PluginConfig | null): Field[] { - const { presets: userPresets = {}, dontMergePresets = false } = config ?? {}; - - if (!dontMergePresets && userPresets) { - mergePresets(userPresets as Record, pluginPresets); - } - - const fields: Field[] = []; - Object.values(pluginPresets).forEach(preset => fields.push(preset.field)); - - return fields; -} - -function mergePresets(from: Record, to: Record): void { - Object.keys(from).forEach(presetName => { - if (to[presetName]) { - to[presetName].field = { - ...to[presetName].field, - ...from[presetName].field, - }; - to[presetName].styles = from[presetName].styles || to[presetName].styles; - to[presetName].editorConfig = { - ...to[presetName].editorConfig, - ...from[presetName].editorConfig, - }; - } else { - to[presetName] = from[presetName]; - } - }); -} diff --git a/admin/src/config/types.ts b/admin/src/config/types.ts index 496db66..70681d1 100644 --- a/admin/src/config/types.ts +++ b/admin/src/config/types.ts @@ -1,74 +1,125 @@ import type { EditorConfig as CKE5EditorConfig } from 'ckeditor5'; import type { Interpolation } from 'styled-components'; -import type { ExportToGlobal } from './expToGlobal'; -export type PluginConfig = - | { - dontMergePresets: true; - presets: Record; - dontMergeTheme?: boolean; - theme?: Theme; - } - | { - dontMergePresets?: false; - presets?: { - default: Partial; - /** - * New presets must use Preset type. - * Partial is included only for compatibility - * with previous versions and should not be used. - */ - [k: string]: Preset | PartialIsNotAllowedForNewPresets; - }; - dontMergeTheme?: boolean; - theme?: Theme; - }; - -export type Theme = { - common?: Styles; - light?: Styles; - dark?: Styles; - additional?: Styles; -}; - -export type Preset = { - field: Field; - styles?: Styles; - editorConfig: Partial; +/** + * @internal + */ +export type PluginConfig = { + presets: Record; + theme: Theme; }; -export type PartialIsNotAllowedForNewPresets = { - field?: Field; - styles?: Styles; - editorConfig?: Partial; -}; - -export type EditorConfig = CKE5EditorConfig; - -export type Field = { - metadatas: Metadata; +/** + * Used to register a preset option in the admin panel. + * + * @see {@link https://docs.strapi.io/dev-docs/custom-fields#options | Strapi documentation} + * + * @internal + */ +export type Option = { + metadatas: Metadatas; key: string | number; + /** + * @remarks + * + * The value must match the corresponding key in the presets. + */ value: string | number; }; -export type Metadata = { +/** + * Used to register a preset option in the admin panel. + * + * @see {@link https://docs.strapi.io/dev-docs/custom-fields#options | Strapi documentation} + * + * @internal + */ +export type Metadatas = { intlLabel: IntlLabel; - disabled?: boolean; - hidden?: boolean; }; +/** + * Used to register a preset option in the admin panel. + * + * @see {@link https://docs.strapi.io/dev-docs/custom-fields#options | Strapi documentation} + * + * @internal + */ export type IntlLabel = { id: string; defaultMessage: string; values?: object; }; -export type Styles = string | Interpolation[]; +/** + * @public + */ +export type UserPluginConfig = { + presets?: Preset[]; + /** + * Styles applied globally to every editor instance. + */ + theme?: Theme; +}; + +/** + * @public + */ +export type Theme = { + /** + * Core styles. + */ + common?: CSS; + /** + * Styles apllied in light mode. + */ + light?: CSS; + /** + * Styles apllied in dark mode. + */ + dark?: CSS; + /** + * Additional styles that complement the theme. + */ + additional?: CSS; +}; + +/** + * CSS, can either be a string or an array of interpolated objects. + * + * @public + */ +export type CSS = string | Interpolation[]; -declare global { - interface Window { - SH_CKE: ExportToGlobal; - SH_CKE_CONFIG: PluginConfig | null; - SH_CKE_UPLOAD_ADAPTER_IS_RESPONSIVE: boolean; - } -} +/** + * @public + */ +export type Preset = { + /** + * Preset name, will be shown in the schema. + */ + name: string; + /** + * Preset description, will be shown in the content-type builder. + */ + description: string; + /** + * Styles applied to the editor instance in addition to the theme. + */ + styles?: CSS; + /** + * CKEditor configuration. + * + * @see {@link https://ckeditor.com/docs/ckeditor5/latest/getting-started/setup/configuration.html | CKEditor documentation} + */ + editorConfig: EditorConfig; +}; + +/** + * CKEditor configuration. + * + * @see {@link https://ckeditor.com/docs/ckeditor5/latest/getting-started/setup/configuration.html | CKEditor documentation} + * + * @public + */ +export type EditorConfig = CKE5EditorConfig; diff --git a/admin/src/exports.ts b/admin/src/exports.ts index 61f8f64..e367ecf 100644 --- a/admin/src/exports.ts +++ b/admin/src/exports.ts @@ -1,2 +1,9 @@ -export type * from './config/types'; -export { defaultPreset } from './config'; +export type { + UserPluginConfig as PluginConfig, + EditorConfig, + Preset, + Theme, + CSS, +} from './config/types'; +export { setPluginConfig, defaultPreset, materialColors } from './config'; +export { StrapiMediaLib, StrapiUploadAdapter } from './plugins'; diff --git a/admin/src/index.ts b/admin/src/index.ts index fd7c9d6..d61ff60 100644 --- a/admin/src/index.ts +++ b/admin/src/index.ts @@ -1,16 +1,38 @@ import * as yup from 'yup'; import { PLUGIN_ID } from './utils'; -import { getPresetsFields, getPluginConfig, exportToGlobal } from './config'; +import { getPluginConfig, type Option } from './config'; import { CKEditorIcon } from './components/CKEditorIcon'; +export * from './exports'; + +const AVAILABLE_OPTIONS: Option[] = []; + +function fillAvailableOptions(): void { + const { presets } = getPluginConfig(); + + Object.values(presets).forEach(({ name, description }) => { + const option: Option = { + key: name, + value: name, + metadatas: { + intlLabel: { + id: `${PLUGIN_ID}.preset.${name}.label`, + defaultMessage: description, + }, + }, + }; + + AVAILABLE_OPTIONS.push(option); + }); +} + // eslint-disable-next-line import/no-default-export export default { + bootstrap() { + fillAvailableOptions(); + }, async register(app: any): Promise { - exportToGlobal(); - const pluginConfig = await getPluginConfig(); - const optionsPreset = getPresetsFields(pluginConfig); - app.customFields.register({ name: 'CKEditor', type: 'richtext', @@ -43,7 +65,7 @@ export default { }, name: 'options.preset', type: 'select', - options: optionsPreset, + options: AVAILABLE_OPTIONS, }, ], advanced: [ diff --git a/admin/src/plugins/StrapiUploadAdapter.ts b/admin/src/plugins/StrapiUploadAdapter.ts index 7fc1dd3..3a2fb4f 100644 --- a/admin/src/plugins/StrapiUploadAdapter.ts +++ b/admin/src/plugins/StrapiUploadAdapter.ts @@ -8,10 +8,9 @@ import { type UploadResponse, } from 'ckeditor5'; -export interface StrapiUploadAdapterConfig extends SimpleUploadConfig { - backendUrl?: string; - responsive?: boolean; -} +import { isImageResponsive, prefixFileUrlWithBackendUrl } from '../utils'; + +export interface StrapiUploadAdapterConfig extends SimpleUploadConfig {} export interface StrapiUploadAdapterPlugin extends Plugin { initAdapter: (config: StrapiUploadAdapterConfig) => void; @@ -138,28 +137,21 @@ class Adapter implements StrapiAdapter { ); } - const { backendUrl, responsive } = this.config || {}; - const { name, url, alternativeText, formats, provider } = response[0]; - const defaultUrl = provider !== 'local' ? url : backendUrl + url; + const { name, url, alternativeText, formats } = response[0]; + const urls: { [k: string]: string } = { default: prefixFileUrlWithBackendUrl(url) }; + const alt = alternativeText || name; - if (formats && responsive) { - const urls: { [k: string]: string } = { default: defaultUrl }; - const keys = Object.keys(formats).sort((a, b) => formats[a].width - formats[b].width); - keys.forEach(k => { - urls[formats[k].width] = provider !== 'local' ? url : backendUrl + formats[k].url; - }); - resolve({ alt: alternativeText || name, urls }); - } else { - resolve( - url - ? { - alt: alternativeText || name, - urls: { default: defaultUrl }, - } - : {} + if (formats && isImageResponsive(formats)) { + const sortedFormatsKeys = Object.keys(formats).sort( + (a, b) => formats[a].width - formats[b].width ); + sortedFormatsKeys.forEach(k => { + urls[formats[k].width] = prefixFileUrlWithBackendUrl(formats[k].url); + }); } + resolve(url ? { alt, urls } : {}); + return undefined; }); diff --git a/admin/src/utils/index.ts b/admin/src/utils/index.ts index 5023e64..a1c4015 100644 --- a/admin/src/utils/index.ts +++ b/admin/src/utils/index.ts @@ -1,3 +1,4 @@ export * from './pluginId'; -export * from './prefixWithBackendUrl'; export * from './localStorage'; +export * from './isImageResponsive'; +export * from './prefixWithBackendUrl'; diff --git a/admin/src/utils/isImageResponsive.ts b/admin/src/utils/isImageResponsive.ts new file mode 100644 index 0000000..37fc1a5 --- /dev/null +++ b/admin/src/utils/isImageResponsive.ts @@ -0,0 +1,5 @@ +export function isImageResponsive(imgFormats: { [k: string]: Object }): boolean { + const formats = Object.keys(imgFormats); + const isResponsive = !(formats.length === 1 && formats[0] === 'thumbnail'); + return isResponsive; +} diff --git a/package.json b/package.json index cbc4f0b..5ea8337 100644 --- a/package.json +++ b/package.json @@ -29,8 +29,8 @@ "exports": { "./package.json": "./package.json", ".": { - "types": "./dist/admin/src/exports.d.ts", - "source": "./admin/src/exports.ts", + "types": "./dist/admin/src/index.d.ts", + "source": "./admin/src/index.ts", "import": "./dist/admin/index.mjs", "require": "./dist/admin/index.js", "default": "./dist/admin/index.js" diff --git a/server/src/controllers/configController.ts b/server/src/controllers/configController.ts deleted file mode 100644 index b2cb52f..0000000 --- a/server/src/controllers/configController.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type { Core } from '@strapi/strapi'; -import PLUGIN_ID from '../utils/pluginId'; - -export default function configController({ strapi }: { strapi: Core.Strapi }): Core.Controller { - return { - async getConfig(ctx): Promise { - const { responsiveDimensions = false } = await strapi - .plugin('upload') - .service('upload') - .getSettings(); - - let config = await strapi.plugin(PLUGIN_ID).service('configService').readConfig(); - config += `window.SH_CKE_UPLOAD_ADAPTER_IS_RESPONSIVE = ${responsiveDimensions}\n`; - - ctx.type = 'application/javascript'; - ctx.send(config); - }, - }; -} diff --git a/server/src/controllers/index.ts b/server/src/controllers/index.ts deleted file mode 100644 index 31cd936..0000000 --- a/server/src/controllers/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import configController from './configController'; - -export default { - configController, -}; diff --git a/server/src/index.ts b/server/src/index.ts index 70c2369..5a23475 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -1,11 +1,13 @@ -import register from './register'; -import controllers from './controllers'; -import routes from './routes'; -import services from './services'; +import type { Core } from '@strapi/strapi'; + +import pluginPkg from '../../package.json'; export default { - register, - controllers, - routes, - services, + register: ({ strapi }: { strapi: Core.Strapi }) => { + strapi.customFields.register({ + name: 'CKEditor', + plugin: pluginPkg.strapi.name, + type: 'richtext', + }); + }, }; diff --git a/server/src/register.ts b/server/src/register.ts deleted file mode 100644 index 66aa189..0000000 --- a/server/src/register.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { Core } from '@strapi/strapi'; -import pluginId from './utils/pluginId'; - -export default function register({ strapi }: { strapi: Core.Strapi }): void { - strapi.customFields.register({ - name: 'CKEditor', - plugin: pluginId, - type: 'richtext', - }); -} diff --git a/server/src/routes/index.ts b/server/src/routes/index.ts deleted file mode 100644 index ad258db..0000000 --- a/server/src/routes/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -export default { - config: { - type: 'admin', - routes: [ - { - method: 'GET', - path: '/config/ckeditor', - handler: 'configController.getConfig', - config: { - auth: false, - }, - }, - ], - }, -}; diff --git a/server/src/services/configService.ts b/server/src/services/configService.ts deleted file mode 100644 index 0d0572a..0000000 --- a/server/src/services/configService.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { existsSync } from 'fs'; -import { readFile } from 'fs/promises'; -import type { Core } from '@strapi/strapi'; - -export default function configService(): Core.Service { - return { - async readConfig(): Promise { - const configFileContent = await readConfigFile(); - let config = configFileContent && trimConfig(configFileContent); - config &&= `${config}\nwindow.SH_CKE_CONFIG = CKEConfig()\n`; - config ??= `window.SH_CKE_CONFIG = null\n`; - - return config; - }, - }; -} - -function readConfigFile(): Promise { - const appDir = process.cwd(); - const isTSProject = existsSync(`${appDir}/dist`); - const envName = process.env.NODE_ENV; - - const cfgDir = isTSProject ? `${appDir}/dist/config` : `${appDir}/config`; - const cfgFileName = 'ckeditor.js'; - - const envFilePath = `${cfgDir}/env/${envName}/${cfgFileName}`; - const baseFilePath = `${cfgDir}/${cfgFileName}`; - - if (existsSync(envFilePath)) { - return readFile(envFilePath, 'utf8'); - } - - if (existsSync(baseFilePath)) { - return readFile(baseFilePath, 'utf8'); - } - - return null; -} - -function trimConfig(rawBuf: string): string | null { - let config: string | null = null; - - ['const CKEConfig', 'function CKEConfig'].some(func => { - const idx = rawBuf.indexOf(func); - if (idx >= 0) { - config = `${rawBuf.substring(idx)}`; - return true; - } - return false; - }); - - return config; -} diff --git a/server/src/services/index.ts b/server/src/services/index.ts deleted file mode 100644 index 8d435a6..0000000 --- a/server/src/services/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import configService from './configService'; - -export default { - configService, -}; diff --git a/server/src/utils/pluginId.ts b/server/src/utils/pluginId.ts deleted file mode 100644 index 6f66bf9..0000000 --- a/server/src/utils/pluginId.ts +++ /dev/null @@ -1,5 +0,0 @@ -import pluginPkg from '../../../package.json'; - -const PLUGIN_ID = pluginPkg.strapi.name; - -export default PLUGIN_ID;