@hellospruce/strapi-custom-ckeditor5
v1.1.1
Published
Custom CkEditor for Strapi
Downloads
1
Readme
Custom Editor for Strapi, It was build on top of CKEditor 5 balloon block editor build
Documentation
See:
- Installation for how to install this package and what it contains.
- Basic API for how to create an editor and interact with it.
- Configuration for how to configure the editor.
- Creating custom builds for how to customize the build (configure and rebuild the editor bundle).
Quick start
First, install the build from npm:
npm install --save @hellospruce/strapi-custom-ckeditor5
or
yarn add @hellospruce/strapi-custom-ckeditor5
And use it in on strapi: Create the CKEditor component at:
strapi/app/extensions/content-manager/admin/src/components/CKEditor/index.js
import { CKEditor } from '@ckeditor/ckeditor5-react';
import PropTypes from 'prop-types';
import React, { useState, useEffect } from 'react';
import { auth } from 'strapi-helper-plugin'
import cheerio from 'cheerio'
import CustomEditor from '@hellospruce/strapi-custom-ckeditor5'
const Editor = ({ onChange, name, value }) => {
const uploadUrl = `${strapi.backendURL}/upload`;
const [content, setContent] = useState();
const headers = {
Authorization: 'Bearer ' + auth.getToken(),
};
useEffect(()=>{
if(value){
const $ = cheerio.load(value, null, false);
const videos = $('.w-richtext-figure-type-video iframe');
for(let i=0; i< videos.length; i++){
let video = videos[i];
let source = video.attribs['src'];
video.parent.attribs['data-oembed-url']= source;
}
setContent($.html());
}
}, [value]);
return (
<div>
<CKEditor
editor={CustomEditor}
data={content}
onChange={(event, editor) => {
const data = editor.getData();
onChange({ target: { name, value: data } });
}}
config={{
strapiUpload: {
uploadUrl,
headers,
}
}}
/>
</div>
);
};
Editor.propTypes = {
onChange: PropTypes.func.isRequired,
name: PropTypes.string.isRequired,
value: PropTypes.string,
};
export default Editor;
Create a component to override the default strapi rich text component:
strapi/app/extensions/content-manager/admin/src/components/WysiwygWithErrors/index.js
import React from 'react';
import PropTypes from 'prop-types';
import { isEmpty } from 'lodash';
import { Label, InputDescription, InputErrors } from 'strapi-helper-plugin';
import Editor from '../CKEditor';
const WysiwygWithErrors = ({
inputDescription,
errors,
label,
name,
noErrorsDescription,
onChange,
value,
}) => {
let spacer = !isEmpty(inputDescription) ? (
<div style={{ height: '.4rem' }} />
) : (
<div />
);
if (!noErrorsDescription && !isEmpty(errors)) {
spacer = <div />;
}
return (
<div
style={{
marginBottom: '1.6rem',
fontSize: '1.3rem',
fontFamily: 'Lato',
}}
>
<Label htmlFor={name} message={label} style={{ marginBottom: 10 }} />
<Editor name={name} onChange={onChange} value={value} />
<InputDescription
message={inputDescription}
style={!isEmpty(inputDescription) ? { marginTop: '1.4rem' } : {}}
/>
<InputErrors
errors={(!noErrorsDescription && errors) || []}
name={name}
/>
{spacer}
</div>
);
};
WysiwygWithErrors.defaultProps = {
errors: [],
label: '',
noErrorsDescription: false,
value: '',
};
WysiwygWithErrors.propTypes = {
errors: PropTypes.array,
inputDescription: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func,
PropTypes.shape({
id: PropTypes.string,
params: PropTypes.object,
}),
]),
label: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func,
PropTypes.shape({
id: PropTypes.string,
params: PropTypes.object,
}),
]),
name: PropTypes.string.isRequired,
noErrorsDescription: PropTypes.bool,
onChange: PropTypes.func.isRequired,
value: PropTypes.string,
};
export default WysiwygWithErrors;