Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

challenges in replacing the default wysiwyg editor with a custom plugin ckeditor in strapi v5 #200

Open
maruthasalamr opened this issue Jan 16, 2025 · 1 comment
Labels
issue: question Question about the plugin / Searching for help with the plugin

Comments

@maruthasalamr
Copy link

While replacing the default wysiwyg editor with a custom plugin ckeditor in strapi v5 facing challenges. useLibrary hook function is no longer exist and @strapi/helper-plugin also does not exist in strapi v5. Also cannot able see the custom field in content type builder.
using addFields adding the custom field to replace the existing richtext

Note- same code setup is working fine in strapi v4

Please can you help to fix ? or can you have any examples for strapiv5 ?

plugins/wysiwyg/src/admin/components/index.jsx

Import React, { useState } from 'react';
import { Button, Stack, Flex, Field, FieldLabel, FieldError } from '@strapi/design-system';
import { useLibrary, prefixFileUrlWithBackendUrl } from '@strapi/helper-plugin';
import { CKEditor } from '@ckeditor/ckeditor5-react';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
import './ck-editor.wse.css';

const Wysiwyg = ({ name, onChange, value, required, error, type }) => {
  const [showMediaLibDialog, setShowMediaLibDialog] = useState(false);
  const { components } = useLibrary();
  const MediaLibDialog = components['media-library'];

  const handleToggleMediaLibDialog = () => {
    setShowMediaLibDialog(!showMediaLibDialog);
  };

  const handleSelectAssets = (files) => {
    const formattedFiles = files.map((file) => ({
      alt: file.alternativeText || file.name,
      url: prefixFileUrlWithBackendUrl(file.url),
      mime: file.mime,
    }));
    const images = formattedFiles.map((image) => `<image src='${image.url}' alt='${image.alt}'>`).join();
    onChange({
      target: {
        name: name,
        value: (value || '') + images,
      },
    });
    handleToggleMediaLibDialog();
  };

  return (
    <div>
      <Field name={name} error={error}>
        <Button variant="secondary" onClick={handleToggleMediaLibDialog}>
          MediaLib
        </Button>
        <Stack size={2} padding={2}>
          <Flex>
            <FieldLabel required={required}>{name}</FieldLabel>
          </Flex>
          <div className={error ? 'error-active' : ''}>
            <CKEditor
              id={name}
              config={{
                toolbar: {
                  removeItems: ['uploadImage', 'outdent', 'indent'],
                  shouldNotGroupWhenFull: false,
                },
                link: {
                  decorators: {
                    isExternal: {
                      mode: 'manual',
                      label: 'Open in a new tab',
                      defaultValue: true,
                      value: true,
                      attributes: {
                        target: '_blank'
                      }
                    },
                    canFollow: {
                      mode: 'manual',
                      label: 'No Follow',
                      defaultValue: true,
                      value: true,
                      attributes: {
                        rel: 'nofollow noreferrer noopener'
                      }
                    }
                  }
                },
                contentsCss: './ck-editor.wse.css',
              }}
              name={name}
              editor={ClassicEditor}
              value={value}
              data={value}
              errors={error}
              onChange={(_, editor) => {
                onChange({ target: { name: name, type: type, value: editor.getData() } });
              }}
            />
          </div>
          <FieldError />
        </Stack>
        {showMediaLibDialog && (
          <MediaLibDialog onClose={handleToggleMediaLibDialog} onSelectAssets={handleSelectAssets} />
        )}
      </Field>
    </div>
  );
};

export default Wysiwyg;

plugins/wysiwyg/src/index.js

import pluginPkg from '../../package.json';
import Wysiwyg from './components/Wysiwyg';
import pluginId from './pluginId';
import Initializer from "./components/Initializer";


const name = pluginPkg.strapi.name;

export default {
  register(app) {
    console.log("app",app)
       app.addFields({ type: 'wysiwyg', Component: Wysiwyg });

    app.registerPlugin({
      id: pluginId,
      initializer: Initializer,
      isReady: true,
      name,
    });
    
       
  // eslint-disable-next-line @typescript-eslint/no-empty-function
  bootstrap() {},
};

config/plugin.js

wysiwyg: {
    enabled: true,
    resolve: './src/plugins/wysiwyg', // path to plugin folder
  },
  

Expected behavior
currently it's default richtext
image
Expected
image

System information

  • Node.js version:v18.20.2
  • NPM version:10.5.0
  • Strapi version: v5.5.1
  • Database:PostgreSQL
  • Operating system:Mac Os
@nshenderov nshenderov added the issue: question Question about the plugin / Searching for help with the plugin label Jan 27, 2025
@nshenderov
Copy link
Owner

This plugin uses the Custom Field API. You can explore the code of the v5 plugin in this repository. Strapi v5 brought some significant changes, and they also provided migration guides. Additionally, there is a dedicated channel in the Discord community, 'migration-to-v5,' specifically for cases like yours.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
issue: question Question about the plugin / Searching for help with the plugin
Projects
None yet
Development

No branches or pull requests

2 participants