Refactor CKEditor integration across application

Replaced `ClassicEditor` with a consistent `classicEditor` and added centralized editor configuration using `editorConfig`. Simplified webpack configuration by removing CKEditor-specific setups and dependencies, improving maintainability.
This commit is contained in:
Julien Fastré 2025-01-30 11:09:45 +01:00 committed by Julie Lenaerts
parent b4d887a372
commit a2fcf039be
11 changed files with 71 additions and 116 deletions

View File

@ -6,12 +6,6 @@
"@apidevtools/swagger-cli": "^4.0.4",
"@babel/core": "^7.20.5",
"@babel/preset-env": "^7.20.2",
"@ckeditor/ckeditor5-build-classic": "^44.1.0",
"@ckeditor/ckeditor5-dev-translations": "^43.0.1",
"@ckeditor/ckeditor5-dev-utils": "^43.0.1",
"@ckeditor/ckeditor5-dev-webpack-plugin": "^31.1.13",
"@ckeditor/ckeditor5-markdown-gfm": "^44.1.0",
"@ckeditor/ckeditor5-theme-lark": "^44.1.0",
"@ckeditor/ckeditor5-vue": "^7.3.0",
"@eslint/js": "^9.14.0",
"@luminateone/eslint-baseline": "^1.0.9",
@ -23,6 +17,7 @@
"bindings": "^1.5.0",
"bootstrap": "5.2.3",
"chokidar": "^3.5.1",
"ckeditor5": "^44.1.0",
"dompurify": "^3.1.0",
"eslint": "^9.14.0",
"eslint-config-prettier": "^9.1.0",

View File

@ -1,30 +1,24 @@
import ClassicEditorBase from "@ckeditor/ckeditor5-editor-classic/src/classiceditor";
import EssentialsPlugin from "@ckeditor/ckeditor5-essentials/src/essentials";
import MarkdownPlugin from "@ckeditor/ckeditor5-markdown-gfm/src/markdown";
import BoldPlugin from "@ckeditor/ckeditor5-basic-styles/src/bold";
import ItalicPlugin from "@ckeditor/ckeditor5-basic-styles/src/italic";
import BlockQuotePlugin from "@ckeditor/ckeditor5-block-quote/src/blockquote";
import HeadingPlugin from "@ckeditor/ckeditor5-heading/src/heading";
import LinkPlugin from "@ckeditor/ckeditor5-link/src/link";
import ListPlugin from "@ckeditor/ckeditor5-list/src/list";
import ParagraphPlugin from "@ckeditor/ckeditor5-paragraph/src/paragraph";
import {
Essentials,
Bold,
Italic,
Paragraph,
Mention,
Markdown,
BlockQuote,
Heading,
Link,
List,
} from 'ckeditor5';
import coreTranslations from 'ckeditor5/translations/fr.js';
import 'ckeditor5/ckeditor5.css';
import "./index.scss";
export default class ClassicEditor extends ClassicEditorBase {}
ClassicEditor.builtinPlugins = [
EssentialsPlugin,
MarkdownPlugin,
BoldPlugin,
ItalicPlugin,
BlockQuotePlugin,
HeadingPlugin,
LinkPlugin,
ListPlugin,
ParagraphPlugin,
];
ClassicEditor.defaultConfig = {
export default {
plugins: [Essentials, Markdown, Bold, Italic, BlockQuote, Heading, Link, List, Paragraph],
toolbar: {
items: [
"heading",
@ -39,6 +33,8 @@ ClassicEditor.defaultConfig = {
"redo",
],
},
language: "fr",
translations: [
coreTranslations
],
licenseKey: "GPL",
};
} ;

View File

@ -1,14 +1,13 @@
import ClassicEditor from "./editor_config";
import config from "./editor_config";
import {ClassicEditor} from "ckeditor5";
const ckeditorFields: NodeListOf<HTMLTextAreaElement> =
document.querySelectorAll("textarea[ckeditor]");
ckeditorFields.forEach((field: HTMLTextAreaElement): void => {
ClassicEditor.create(field)
.then((editor) => {
//console.log( 'CkEditor was initialized', editor );
})
ClassicEditor.create(field, config)
.catch((error) => {
console.error(error.stack);
throw error;
});
});
//Fields.push.apply(Fields, document.querySelectorAll('.cf-fields textarea'));

View File

@ -1,45 +1,3 @@
const { styles } = require("@ckeditor/ckeditor5-dev-utils");
const {
CKEditorTranslationsPlugin,
} = require("@ckeditor/ckeditor5-dev-translations");
buildCKEditor = function (encore) {
encore
.addPlugin(
new CKEditorTranslationsPlugin({
language: "fr",
addMainLanguageTranslationsToAllAssets: true,
verbose: !encore.isProduction(),
strict: true,
}),
)
// Use raw-loader for CKEditor 5 SVG files.
.addRule({
test: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
loader: "raw-loader",
})
// Configure other image loaders to exclude CKEditor 5 SVG files.
.configureLoaderRule("images", (loader) => {
loader.exclude =
/ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/;
})
// Configure PostCSS loader.
.addLoader({
test: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css$/,
loader: "postcss-loader",
options: {
postcssOptions: styles.getPostCssConfig({
themeImporter: {
themePath: require.resolve("@ckeditor/ckeditor5-theme-lark"),
},
minify: true,
}),
},
});
};
// Compile and loads all assets from the Chill Main Bundle
module.exports = function (encore, entries) {
@ -79,8 +37,6 @@ module.exports = function (encore, entries) {
__dirname + "/Resources/public/page/export/download-export.js",
);
buildCKEditor(encore);
// Modules entrypoints
encore.addEntry(
"mod_collection",

View File

@ -16,7 +16,8 @@
<ckeditor
name="content"
:placeholder="$t('comment.content')"
:editor="editor"
:editor="classicEditor"
:config="editorConfig"
v-model="content"
tag-name="textarea"
/>
@ -60,8 +61,9 @@
</template>
<script>
import {ClassicEditor} from "ckeditor5";
import {Ckeditor} from "@ckeditor/ckeditor5-vue";
import ClassicEditor from "../../../../../../ChillMainBundle/Resources/public/module/ckeditor5/editor_config";
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
import { mapState } from "vuex";
export default {
@ -71,7 +73,6 @@ export default {
},
data() {
return {
editor: ClassicEditor,
loading: false,
lastRecordedContent: null,
};
@ -80,6 +81,8 @@ export default {
...mapState({
pinnedComment: (state) => state.accompanyingCourse.pinnedComment,
}),
classicEditor: () => ClassicEditor,
editorConfig: () => classicEditorConfig,
content: {
set(value) {
console.log("new comment value", value);

View File

@ -22,6 +22,7 @@
name="content"
:placeholder="$t('comment_placeholder')"
:editor="editor"
:config="editorConfig"
v-model="content"
tag-name="textarea"
/>
@ -39,7 +40,8 @@
import Modal from "ChillMainAssets/vuejs/_components/Modal.vue";
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
import { Ckeditor }from "@ckeditor/ckeditor5-vue";
import ClassicEditor from "ChillMainAssets/module/ckeditor5/editor_config";
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
import {ClassicEditor} from "ckeditor5";
export default {
name: "WriteComment",
@ -55,7 +57,6 @@ export default {
showModal: false,
modalDialogClass: "modal-dialog-scrollable modal-xl",
},
editor: ClassicEditor,
formdata: {
content: this.resource.comment,
},
@ -71,6 +72,8 @@ export default {
},
},
computed: {
editor: () => ClassicEditor,
editorConfig: () => classicEditorConfig,
content: {
set(value) {
this.formdata.content = value;

View File

@ -36,14 +36,15 @@
<label class="col-form-label">{{ $t("private_comment") }}</label>
<ckeditor
v-model="privateComment"
:editor="editor"
:editor="classicEditor"
:config="editorConfig"
tag-name="textarea"
></ckeditor>
</div>
<div id="comment" class="action-row">
<label class="col-form-label">{{ $t("comments") }}</label>
<ckeditor v-model="note" :editor="editor" tag-name="textarea"></ckeditor>
<ckeditor v-model="note" :editor="classicEditor" :config="editorConfig" tag-name="textarea"></ckeditor>
</div>
<div id="objectives" class="action-row">
@ -438,7 +439,8 @@ import {
ISOToDatetime,
} from "ChillMainAssets/chill/js/date";
import { Ckeditor } from "@ckeditor/ckeditor5-vue";
import ClassicEditor from "ChillMainAssets/module/ckeditor5/editor_config";
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
import {ClassicEditor} from "ckeditor5";
import AddResult from "./components/AddResult.vue";
import AddEvaluation from "./components/AddEvaluation.vue";
import AddPersons from "ChillPersonAssets/vuejs/_components/AddPersons.vue";
@ -521,7 +523,6 @@ export default {
return {
docAnchorId: null,
isExpanded: false,
editor: ClassicEditor,
showAddObjective: false,
showAddEvaluation: false,
handlingThirdPartyPicker: {
@ -588,6 +589,8 @@ export default {
"hasThirdParties",
"hasReferrers",
]),
classicEditor: () => ClassicEditor,
editorConfig: () => classicEditorConfig,
startDate: {
get() {
return this.$store.state.startDate;

View File

@ -89,7 +89,8 @@
}}</label>
<div class="col-sm-12">
<ckeditor
:editor="editor"
:editor="classicEditor"
:config="editorConfig"
:placeholder="$t('evaluation_comment_placeholder')"
v-model="comment"
tag-name="textarea"
@ -276,8 +277,9 @@ import {
ISOToDate,
ISOToDatetime,
} from "ChillMainAssets/chill/js/date";
import {Ckeditor } from "@ckeditor/ckeditor5-vue";
import ClassicEditor from "ChillMainAssets/module/ckeditor5/editor_config";
import {Ckeditor} from "@ckeditor/ckeditor5-vue";
import {ClassicEditor} from "ckeditor5";
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
import { mapGetters, mapState } from "vuex";
import PickTemplate from "ChillDocGeneratorAssets/vuejs/_components/PickTemplate.vue";
import { buildLink } from "ChillDocGeneratorAssets/lib/document-generator";
@ -333,7 +335,6 @@ export default {
i18n,
data() {
return {
editor: ClassicEditor,
template: null,
asyncUploadOptions: {
maxFiles: 1,
@ -374,6 +375,8 @@ export default {
},
computed: {
...mapState(["isPosting", "work", "me"]),
classicEditor: () => ClassicEditor,
editorConfig: () => classicEditorConfig,
AmIRefferer() {
return !(
this.$store.state.work.accompanyingPeriod.user &&

View File

@ -29,7 +29,7 @@
</div>
<div class="item-row comment">
<ckeditor :editor="editor" v-model="comment" tag-name="textarea" />
<ckeditor :editor="classicEditor" :config="editorConfig" v-model="comment" tag-name="textarea" />
</div>
<div class="item-row participation-details">
@ -98,8 +98,9 @@ div.participation-details {
<script>
import { mapGetters } from "vuex";
import PersonRenderBox from "ChillPersonAssets/vuejs/_components/Entity/PersonRenderBox.vue";
import {Ckeditor }from "@ckeditor/ckeditor5-vue";
import ClassicEditor from "ChillMainAssets/module/ckeditor5/editor_config";
import {Ckeditor} from "@ckeditor/ckeditor5-vue";
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
import {ClassicEditor} from "ckeditor5";
export default {
name: "MemberDetails",
@ -108,13 +109,10 @@ export default {
ckeditor: Ckeditor,
},
props: ["conc"],
data() {
return {
editor: ClassicEditor,
};
},
computed: {
...mapGetters(["concByPersonId"]),
classicEditor: () => ClassicEditor,
editorConfig: () => classicEditorConfig,
isHolder() {
return this.conc.holder;
},

View File

@ -1,18 +1,20 @@
<template>
<ckeditor
name="content"
:placeholder="
<ckeditor
name="content"
:placeholder="
$t('household_members_editor.positioning.comment_placeholder')
"
:editor="editor"
v-model="content"
tag-name="textarea"
/>
:editor="editor"
:config="editorConfig"
v-model="content"
tag-name="textarea"
/>
</template>
<script>
import { Ckeditor } from "@ckeditor/ckeditor5-vue";
import ClassicEditor from "ChillMainAssets/module/ckeditor5/editor_config";
import classicEditorConfig from "ChillMainAssets/module/ckeditor5/editor_config";
import {ClassicEditor} from "ckeditor5";
export default {
name: "PersonComment.vue",
@ -20,12 +22,9 @@ export default {
ckeditor: Ckeditor
},
props: ["conc"],
data() {
return {
editor: ClassicEditor,
};
},
computed: {
editor: () => ClassicEditor,
editorConfig: () => classicEditorConfig,
content: {
get() {
return this.$props.conc.comment || "";

View File

@ -43,7 +43,7 @@
</div>
</div>
<div class="item-row">
<div>
<div class="col-12">
<h6>{{ $t("household_members_editor.positioning.comment") }}</h6>
<person-comment :conc="conc" />
</div>