Closed lamuertepeluda closed 3 months ago
@lamuertepeluda Your code isn't working, there are few typescript validation errors, also a lot of failing statement
import config from "./ckeditor";
does not point to any files.
Can you paste an updated version, please, after some tests I'm still struggling and I get white screen on adding a new field ? (Minimum reproducible)
@ScreamZ can you check that you have this folder structure please? Maybe the paths in the previous message were slightly inaccurate. But this is definitely working for me.
Content of src/extensions/ckeditor5/strapi-server.ts
// Override plugin service as per https://docs.strapi.io/dev-docs/plugins-extension#extending-a-plugin-s-interface
import config from "./ckeditor";
export default (plugin) => {
plugin.services.config = ({ strapi }) => ({
getUploadConfig(name) {
return strapi.plugin("upload").service(name) ?? {};
},
getCKEditorConfig: () => {
// Wrap in a closure
return `(${config.toString()})()`;
},
});
return plugin;
};
Content of src/extensions/ckeditor5/ckeditor.ts
(or config.ts if you prefer, but then change the import above)
I'll pass mine here as an example. The new profile name in strapi is "custom". Keep in mind that this is but one of several possible CKEditor 5 configurations
const config = () => {
const CKEditor5 = globalThis.CKEditor5;
// Same base plugins as in @_sh/strapi-plugin-ckeditor/admin/src/components/Input/CKEditor/configs/base.js
// toolbarEditorConfig basePlugins). Those commented out may be incompatible with others
const basePlugins = [
CKEditor5.alignment.Alignment,
CKEditor5.autoformat.Autoformat,
CKEditor5.image.AutoImage,
// CKEditor5.link.AutoLink,
// CKEditor5.autosave.Autosave,
// CKEditor5.ui.BalloonToolbar,
CKEditor5.blockQuote.BlockQuote,
// CKEditor5.ui.BlockToolbar,
CKEditor5.basicStyles.Bold,
CKEditor5.basicStyles.Code,
CKEditor5.codeBlock.CodeBlock,
// CKEditor5.htmlSupport.DataFilter,
// CKEditor5.htmlSupport.DataSchema,
CKEditor5.list.DocumentList,
CKEditor5.list.DocumentListProperties,
CKEditor5.essentials.Essentials,
// CKEditor5.findAndReplace.FindAndReplace,
// CKEditor5.fontWithPicker.FontBackgroundColor,
// CKEditor5.fontWithPicker.FontColor,
CKEditor5.fontWithPicker.FontFamily,
CKEditor5.fontWithPicker.FontSize,
CKEditor5.htmlSupport.GeneralHtmlSupport,
CKEditor5.heading.Heading,
// CKEditor5.heading.HeadingButtonsUI,
// CKEditor5.highlight.Highlight,
CKEditor5.horizontalLine.HorizontalLine,
// CKEditor5.htmlSupport.HtmlComment,
CKEditor5.htmlEmbed.HtmlEmbed,
CKEditor5.image.Image,
CKEditor5.image.ImageCaption,
CKEditor5.image.ImageInsert,
CKEditor5.image.ImageResize,
CKEditor5.image.ImageStyle,
CKEditor5.image.ImageToolbar,
CKEditor5.image.ImageUpload,
CKEditor5.indent.Indent,
CKEditor5.indent.IndentBlock,
CKEditor5.basicStyles.Italic,
// CKEditor5.link.Link,
// CKEditor5.link.LinkImage,
// CKEditor5.list.List,
// CKEditor5.list.ListProperties,
CKEditor5.mediaEmbed.MediaEmbed,
// CKEditor5.mediaEmbed.MediaEmbedToolbar,
// CKEditor5.mention.Mention,
CKEditor5.pageBreak.PageBreak,
CKEditor5.paragraph.Paragraph,
// CKEditor5.paragraph.ParagraphButtonUI,
CKEditor5.pasteFromOffice.PasteFromOffice,
CKEditor5.removeFormat.RemoveFormat,
CKEditor5.sourceEditing.SourceEditing,
CKEditor5.specialCharacters.SpecialCharacters,
CKEditor5.specialCharacters.SpecialCharactersArrows,
CKEditor5.specialCharacters.SpecialCharactersCurrency,
// CKEditor5.specialCharacters.SpecialCharactersEssentials,
CKEditor5.specialCharacters.SpecialCharactersLatin,
CKEditor5.specialCharacters.SpecialCharactersMathematical,
CKEditor5.specialCharacters.SpecialCharactersText,
CKEditor5.strapiPlugins.StrapiMediaLib,
CKEditor5.strapiPlugins.StrapiUploadAdapter,
CKEditor5.basicStyles.Strikethrough,
CKEditor5.style.Style,
CKEditor5.basicStyles.Subscript,
CKEditor5.basicStyles.Superscript,
CKEditor5.table.Table,
CKEditor5.table.TableCaption,
CKEditor5.table.TableCellProperties,
CKEditor5.table.TableColumnResize,
CKEditor5.table.TableProperties,
CKEditor5.table.TableToolbar,
// CKEditor5.language.TextPartLanguage,
// CKEditor5.list.TodoList,
CKEditor5.basicStyles.Underline,
CKEditor5.wordCount.WordCount,
];
// Extended from @_sh/strapi-plugin-ckeditor/admin/src/components/Input/CKEditor/configs/base.js toolbarEditorConfig
const toolbar = [
{
label: " ",
tooltip: "Formatting",
icon: "paragraph",
items: ["heading", /* "style", */ "SourceEditing"],
},
"|",
{
label: " ",
tooltip: null,
icon: "text",
items: [
"bold",
"italic",
"fontSize",
"fontFamily",
"fontColor",
"fontBackgroundColor",
],
},
{
label: " ",
tooltip: null,
icon: `
<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<rect x="0" fill="none" width="24" height="24"/>
<g>
<path d="M14.348 12H21v2h-4.613c.24.515.368 1.094.368 1.748 0 1.317-.474 2.355-1.423 3.114-.947.76-2.266 1.138-3.956 1.138-1.557 0-2.934-.293-4.132-.878v-2.874c.985.44 1.818.75 2.5.928.682.18 1.306.27 1.872.27.68 0 1.2-.13 1.562-.39.363-.26.545-.644.545-1.158 0-.285-.08-.54-.24-.763-.16-.222-.394-.437-.704-.643-.18-.12-.483-.287-.88-.49H3v-2H14.347zm-3.528-2c-.073-.077-.143-.155-.193-.235-.126-.202-.19-.44-.19-.713 0-.44.157-.795.47-1.068.313-.273.762-.41 1.348-.41.492 0 .993.064 1.502.19.51.127 1.153.35 1.93.67l1-2.405c-.753-.327-1.473-.58-2.16-.76-.69-.18-1.414-.27-2.173-.27-1.544 0-2.753.37-3.628 1.108-.874.738-1.312 1.753-1.312 3.044 0 .302.036.58.088.848h3.318z"/>
</g>
</svg>`,
items: ["underline", "strikethrough", "superscript", "subscript"],
},
"removeFormat",
"|",
"alignment",
"outdent",
"indent",
"|",
"bulletedList",
"numberedList",
"|",
"insertImage",
"mediaEmbed",
"strapiMediaLib",
"link",
"blockquote",
"insertTable",
"specialCharacters",
"htmlEmbed",
"codeBlock",
"|",
"horizontalLine",
"pageBreak",
"|",
"|",
"undo",
"redo",
"|",
];
globalThis.CKEditorConfig = {
theme: {
// set theme always light
light: "light",
dark: "light",
},
configs: {
// define a custom editor preset based on toolbar editor preset
custom: {
field: {
key: "custom",
value: "custom",
metadatas: {
intlLabel: {
id: "ckeditor.preset.custom.label",
defaultMessage: "Custom version",
},
},
},
editorConfig: {
plugins: [
...basePlugins,
// Custom plugins
CKEditor5["enhancedLink"].Link,
],
toolbar,
image: {
toolbar: [
"imageStyle:inline",
"imageStyle:block",
"imageStyle:side",
"|",
"toggleImageCaption",
"imageTextAlternative",
],
},
/* By default, for plugin's UI will use
the language defined in this file
or the preferred language from strapi's user config
and 'en' as a fallback.
language.ui -> preferred language -> 'en' */
/* For content it will use language based on i18n (if! ignorei18n)
or language.content defined here
and it will use UI language as a fallback.
ignorei18n ? language.content : i18n; -> language.ui */
language: {
ignorei18n: true,
ui: "en",
},
},
},
},
};
};
export default config;
About TS validation errors, here's my tsconfig.json
(kinda the default one, if you ask me)
{
"extends": "@strapi/typescript-utils/tsconfigs/server",
"compilerOptions": {
"outDir": "dist",
"rootDir": ".",
"sourceMap": true
},
"include": ["./", "./**/*.ts", "./**/*.js", "src/**/*.json"],
"exclude": [
"node_modules/",
"build/",
"dist/",
".cache/",
".tmp/",
"src/admin/",
"**/*.test.*",
"plugins/**"
]
}
I did this whole process, using the same folder architecture, but I'm getting an error: :Error: Could not find Custom Field: plugin::ckeditor5.CKEditor at Object.get (C:\Users\rhr_c\OneDrive\Área de Trabalho\ckeditor\strapi\node_modules\@strapi\strapi\dist\core\registries\custom-fields.js:31:23) at convertCustomFieldType (C:\Users\rhr_c\OneDrive\Área de Trabalho\ckeditor\strapi\node_modules\@strapi\strapi\dist\utils\convert-custom-field-type.js:13:75) at Strapi.register (C:\Users\rhr_c\OneDrive\Área de Trabalho\ckeditor\strapi\node_modules\@strapi\strapi\dist\Strapi.js:430:49) at async Strapi.load (C:\Users\rhr_c\OneDrive\Área de Trabalho\ckeditor\strapi\node_modules\@strapi\strapi\dist\Strapi.js:493:9) at async workerProcess (C:\Users\rhr_c\OneDrive\Área de Trabalho\ckeditor\strapi\node_modules\@strapi\strapi\dist\commands\actions\develop\action.js:100:28) at async exports.default (C:\Users\rhr_c\OneDrive\Área de Trabalho\ckeditor\strapi\node_modules\@strapi\strapi\dist\commands\actions\develop\action.js:38:20)
I have tried the same thing, created my own custom plugin. But when I try to add it in my custom plugins, I'm getting errors. Even the src/extensions/ckeditor5/strapi-server.ts
file is not being executing.
Tried multiple things, but nothing worked.
@lamuertepeluda I'm new to strapi and I couldn't set it up according to your guide. Can you explain in more detail what the problem might be? Maybe you registered the config as an additional plugin or used middleware?
@lamuertepeluda I'm new to strapi and I couldn't set it up according to your guide. Can you explain in more detail what the problem might be? Maybe you registered the config as an additional plugin or used middleware?
Hi @bogdankorshunov, it's almost 2 years since my original post. In the meanwhile Strapi moved on, and so did I, meaning that I am not using Strapi anymore, almost since then, and Strapi got several updates, and so did CKEditor. So I couldn't tell now if, using my proposed configuration, this would still work. But at the time, following those instructions, you could have updated CKEditor and have TS in the configuration file of the plain text one
@lamuertepeluda Thanks for the reply. And why don't you use it anymore, if it's not a secret. Some alternative to strapi and ckeditor?
@bogdankorshunov no secret at all 😄 : I changed job and in my current company I don't work on projects with Strapi. We use Strapi in my current company too, but I am pretty sure we don't use CKEditor as we have different use cases that do not require and advanced text editor like that.
@lamuertepeluda And what are the other use cases?😊 I'm just trying to set up ckeditor right now, but I think the implementation will really be redundant. In Rich Text, for example, there is no table in ckeditor, well, there are other functions
@bogdankorshunov we have now much simpler use cases. Like bold, italic and that's it. No tables, highlighting whatsoever, and all the advanced features the CKEditor offers wrt the base RichText embedded with Strapi
First of all, thanks for this plugin which is currently more advanced than the "official" one.
Is your feature request related to a problem? Please describe. Using a txt file for configuring the editor is not the best choice in my opinion, especially when the configuration is complex, such as in CKEditor case. The least problem you have is loosing syntax highlight.
Describe the solution you'd like Possibility to use also .ts or .js files. Consider integrating the following solution somehow in the plugin logic. Alternatively, this can be cited in the docs.
Describe alternatives you've considered I have found a working workaround by using Strapi plugin extension feature. This example is in TypeScript as I am using TS in my Strapi projects.
src/extensions/ckeditor5
foldersrc/extensions/ckeditor5/strapi-server.ts
andsrc/extensions/ckeditor5/config.ts
src/extensions/ckeditor5/strapi-server.ts
as followsexport default (plugin) => { plugin.services.config = ({ strapi }) => ({ getUploadConfig(name) { return strapi.plugin("upload").service(name) ?? {}; }, getCKEditorConfig: () => { // Wrap in a closure return
(${config.toString()})()
; }, }); return plugin; };Explanation
The config closure body is stringified and passed to the browser by
strapi-server.ts
. The browser will be able to evaluate it, provided that it does reference only global objects in the browser (i.e. declared in the app.tsx or other frontend libraries), such asCKEditor5
. If using TS, it works since the config.ts gets transpiled to JS before everything above.Advantages over txt file: you get both syntax highlight, formatting (e.g. in IDE/with Prettier) and type checking You still cannot use non-global browser variables (e.g. import ...) but that isn't possible even with .txt. Everything must be defined in the config closure.
You can import your custom plugin and widgets in
src/admin/app.tsx
(check Strapi docs). Those will register their namespace in the global CKEditor5 object in the browser Window. You can then refer them here in the configurationAdditional context The latest CKEditor Release uses TypeScript. I don't see breaking changes and perhaps this is even easier to get integrated with (e.g. importing types in the config).
What do you think?