├── .github └── workflows │ └── publish_release.yml ├── .gitignore ├── README.md ├── demo ├── demo.png ├── index.html └── sample.jpg ├── package-lock.json ├── package.json ├── src ├── ckeditor.js ├── fullscreen-plugin │ ├── README.md │ ├── css │ │ └── style.css │ ├── icons │ │ ├── fullscreen-big.svg │ │ └── fullscreen-cancel.svg │ └── index.js └── strapi-medialib-plugin │ ├── icons │ └── strapi-medialib.svg │ └── index.js └── webpack.config.js /.github/workflows/publish_release.yml: -------------------------------------------------------------------------------- 1 | name: 🚀 Publish and release 2 | 3 | on: 4 | push: 5 | tags: 6 | - v* 7 | 8 | jobs: 9 | publish-and-release: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: ⚙️ Setup node 13 | uses: actions/setup-node@v2 14 | with: 15 | node-version: 14 16 | 17 | - name: 🔃 Checkout 18 | uses: actions/checkout@v2 19 | 20 | - name: 🛠️ Install and build (automatically) 21 | run: npm ci 22 | 23 | - name: ⚙️ Prepare Live Demo files 24 | run: | 25 | cp -R build demo 26 | 27 | - name: 📢 Publish Live Demo 28 | uses: JamesIves/github-pages-deploy-action@4.1.1 29 | with: 30 | branch: gh-pages 31 | folder: demo 32 | 33 | - name: 📦 Pack built files 34 | id: pack 35 | uses: Roslovets-Inc/zip-npm-files@v1 36 | with: 37 | files: build/* 38 | 39 | - name: 🔖 Create Release 40 | uses: softprops/action-gh-release@v1 41 | with: 42 | files: ${{ steps.pack.outputs.archive }} 43 | env: 44 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 45 | 46 | - name: 📢 Publish npm package 47 | uses: JS-DevTools/npm-publish@v1 48 | with: 49 | token: ${{ secrets.NPM_TOKEN }} 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Enhanced build of CKEditor 5 for Strapi 2 | 3 | Enhanced build of [CKEditor 5](https://github.com/ckeditor/ckeditor5) to replace default [Strapi](https://github.com/strapi/strapi) WYSIWYG editor (note: this is just a part of Strapi [plugin](https://github.com/Roslovets-Inc/strapi-plugin-ckeditor5)). 4 | 5 | ![ckeditor5-build-strapi-wysiwyg demo screenshot](/demo/demo.png) 6 | 7 | [👀 **Live Demo**](https://roslovets-inc.github.io/ckeditor5-build-strapi-wysiwyg/) 8 | 9 | ## Features 10 | 11 | - Enhanced build of CKEditor 5 with more capabilities then Classic Editor build has 12 | - Extensive set of features for your rich content 13 | - Automatically upload Inserted images to Strapi Media Library (thanks to [ckeditor5-strapi-upload-plugin](https://github.com/gtomato/ckeditor5-strapi-upload-plugin)) 14 | - Access Strapi Media Library directly from the editor toolbar 🔥 15 | - Full screen mode 🔥 16 | 17 | ## How to try 18 | 19 | Check out [👀 **live demo**](https://roslovets-inc.github.io/ckeditor5-build-strapi-wysiwyg/) where you can test most of the features. 20 | 21 | ## How to try manually 22 | 23 | 1. Clone repository and change directory 24 | 25 | ``` 26 | git clone https://github.com/Roslovets-Inc/ckeditor5-build-strapi-wysiwyg 27 | cd ckeditor5-build-strapi-wysiwyg 28 | ``` 29 | 30 | 2. Install dependencies and build CKEditor (automatically) 31 | 32 | ``` 33 | npm i 34 | ``` 35 | 36 | 3. Open **demo/index.html** in your system browser 37 | 38 | ## How to use 39 | 40 | Just install to your Strapi [strapi-plugin-ckeditor5](https://github.com/Roslovets-Inc/strapi-plugin-ckeditor5) plugin based on this build (recommended). 41 | 42 | If you want to integrate the build manually examine [strapi-plugin-ckeditor5](https://github.com/Roslovets-Inc/strapi-plugin-ckeditor5) source code as an integration example. 43 | 44 | ## How to add more features to the editor 45 | 46 | If you want to see more features in this build feel free to request it in [issues](https://github.com/Roslovets-Inc/ckeditor5-build-strapi-wysiwyg/issues) or create pull request. Together we will build a comprehensive editor for common needs. 47 | 48 | ## Links 49 | 50 | - [NPM package](https://www.npmjs.com/package/ckeditor5-build-strapi-wysiwyg) 51 | - [GitHub repository](https://github.com/Roslovets-Inc/ckeditor5-build-strapi-wysiwyg) 52 | 53 | ## ⭐️ Show your support 54 | 55 | Give a star if this project helped you. 56 | -------------------------------------------------------------------------------- /demo/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Roslovets-Inc/ckeditor5-build-strapi-wysiwyg/787f0e9715a9ce221f6f1e4fe2bea46457824e43/demo/demo.png -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Enhanced build of CKEditor 5 for Strapi – Live Demo 7 | 14 | 15 | 16 | 17 | 18 |

Enhanced Build of CKEditor 5 for Strapi – Live Demo

19 | 20 |

Please note: Insert Image and Media Library buttons work only in Strapi

21 | 22 |
23 |

Your Playground

24 | 25 |

This is an instance of the enhanced 26 | CKEditor 5 build for Strapi. Try to do your usual things.

27 |

Integrate this WYSIWYG-editor into your Strapi with strapi-plugin-ckeditor5: npm i 29 | strapi-plugin-ckeditor5

30 | 31 |
32 | Autumn fields 33 |
Sample image
34 |
35 | 36 |
37 | Custom HTML content preview 38 |
39 | 40 |
41 | 42 | 43 | 44 | 45 | 46 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /demo/sample.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Roslovets-Inc/ckeditor5-build-strapi-wysiwyg/787f0e9715a9ce221f6f1e4fe2bea46457824e43/demo/sample.jpg -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ckeditor5-build-strapi-wysiwyg", 3 | "version": "2.1.1", 4 | "description": "CKEditor 5 build for Strapi WYSIWYG editor replacement", 5 | "author": "Pavel Roslovets (https://github.com/roslovets)", 6 | "license": "GPL-2.0-or-later", 7 | "homepage": "https://github.com/Roslovets-Inc/ckeditor5-build-strapi-wysiwyg", 8 | "bugs": "https://github.com/Roslovets-Inc/ckeditor5-build-strapi-wysiwyg/issues", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/Roslovets-Inc/ckeditor5-build-strapi-wysiwyg.git" 12 | }, 13 | "private": false, 14 | "keywords": [ 15 | "ckeditor5-build", 16 | "ckeditor", 17 | "ckeditor5", 18 | "ckeditor 5", 19 | "wysiwyg", 20 | "rich text", 21 | "editor", 22 | "html", 23 | "contentEditable", 24 | "editing", 25 | "operational transformation", 26 | "ot", 27 | "collaboration", 28 | "collaborative", 29 | "real-time", 30 | "framework", 31 | "strapi" 32 | ], 33 | "main": "./build/ckeditor.js", 34 | "files": [ 35 | "build" 36 | ], 37 | "engines": { 38 | "node": ">=14.0.0", 39 | "npm": ">=5.7.1" 40 | }, 41 | "scripts": { 42 | "build": "webpack --mode development", 43 | "prepare": "npm run build", 44 | "preversion": "npm run build", 45 | "postversion": "git push && git push --tags" 46 | }, 47 | "devDependencies": { 48 | "@ckeditor/ckeditor5-alignment": "^33.0.0", 49 | "@ckeditor/ckeditor5-autoformat": "^33.0.0", 50 | "@ckeditor/ckeditor5-basic-styles": "^33.0.0", 51 | "@ckeditor/ckeditor5-block-quote": "^33.0.0", 52 | "@ckeditor/ckeditor5-ckfinder": "^33.0.0", 53 | "@ckeditor/ckeditor5-code-block": "^33.0.0", 54 | "@ckeditor/ckeditor5-core": "^33.0.0", 55 | "@ckeditor/ckeditor5-dev-utils": "^29.0.2", 56 | "@ckeditor/ckeditor5-dev-webpack-plugin": "^29.0.2", 57 | "@ckeditor/ckeditor5-easy-image": "^33.0.0", 58 | "@ckeditor/ckeditor5-editor-classic": "^33.0.0", 59 | "@ckeditor/ckeditor5-essentials": "^33.0.0", 60 | "@ckeditor/ckeditor5-font": "^33.0.0", 61 | "@ckeditor/ckeditor5-heading": "^33.0.0", 62 | "@ckeditor/ckeditor5-highlight": "^33.0.0", 63 | "@ckeditor/ckeditor5-horizontal-line": "^33.0.0", 64 | "@ckeditor/ckeditor5-html-embed": "^33.0.0", 65 | "@ckeditor/ckeditor5-image": "^33.0.0", 66 | "@ckeditor/ckeditor5-indent": "^33.0.0", 67 | "@ckeditor/ckeditor5-link": "^33.0.0", 68 | "@ckeditor/ckeditor5-list": "^33.0.0", 69 | "@ckeditor/ckeditor5-media-embed": "^33.0.0", 70 | "@ckeditor/ckeditor5-paragraph": "^33.0.0", 71 | "@ckeditor/ckeditor5-paste-from-office": "^33.0.0", 72 | "@ckeditor/ckeditor5-remove-format": "^33.0.0", 73 | "@ckeditor/ckeditor5-source-editing": "^33.0.0", 74 | "@ckeditor/ckeditor5-special-characters": "^33.0.0", 75 | "@ckeditor/ckeditor5-table": "^33.0.0", 76 | "@ckeditor/ckeditor5-theme-lark": "^33.0.0", 77 | "@ckeditor/ckeditor5-typing": "^33.0.0", 78 | "@gtomato/ckeditor5-strapi-upload-plugin": "^1.0.0", 79 | "css-loader": "^5.2.7", 80 | "postcss-loader": "^4.3.0", 81 | "raw-loader": "^4.0.2", 82 | "sanitize-html": "^2.7.0", 83 | "style-loader": "^2.0.0", 84 | "terser-webpack-plugin": "^4.2.3", 85 | "webpack": "^5.70.0", 86 | "webpack-cli": "^4.9.2" 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/ckeditor.js: -------------------------------------------------------------------------------- 1 | import ClassicEditorBase from "@ckeditor/ckeditor5-editor-classic/src/classiceditor"; 2 | import Essentials from "@ckeditor/ckeditor5-essentials/src/essentials"; 3 | import Autoformat from "@ckeditor/ckeditor5-autoformat/src/autoformat"; 4 | import { 5 | Bold, 6 | Italic, 7 | Underline, 8 | Strikethrough, 9 | Subscript, 10 | Superscript, 11 | Code, 12 | } from "@ckeditor/ckeditor5-basic-styles/src/index"; 13 | import RemoveFormat from "@ckeditor/ckeditor5-remove-format/src/removeformat"; 14 | import SourceEditing from "@ckeditor/ckeditor5-source-editing/src/sourceediting"; 15 | 16 | import BlockQuote from "@ckeditor/ckeditor5-block-quote/src/blockquote"; 17 | import Heading from "@ckeditor/ckeditor5-heading/src/heading"; 18 | import Highlight from "@ckeditor/ckeditor5-highlight/src/highlight"; 19 | import { 20 | Image, 21 | ImageInsert, 22 | ImageCaption, 23 | ImageStyle, 24 | ImageToolbar, 25 | ImageResize, 26 | ImageResizeEditing, 27 | ImageResizeButtons, 28 | } from "@ckeditor/ckeditor5-image/src/index"; 29 | import { Indent, IndentBlock } from "@ckeditor/ckeditor5-indent/src/index"; 30 | import { Link, LinkImage, AutoLink } from "@ckeditor/ckeditor5-link/src/index"; 31 | import TodoList from "@ckeditor/ckeditor5-list/src/todolist"; 32 | import ListStyle from "@ckeditor/ckeditor5-list/src/liststyle"; 33 | import MediaEmbed from "@ckeditor/ckeditor5-media-embed/src/mediaembed"; 34 | import Paragraph from "@ckeditor/ckeditor5-paragraph/src/paragraph"; 35 | import PasteFromOffice from "@ckeditor/ckeditor5-paste-from-office/src/pastefromoffice"; 36 | import { 37 | Table, 38 | TableToolbar, 39 | TableProperties, 40 | TableCellProperties, 41 | } from "@ckeditor/ckeditor5-table/src/index"; 42 | import TextTransformation from "@ckeditor/ckeditor5-typing/src/texttransformation"; 43 | import HorizontalLine from "@ckeditor/ckeditor5-horizontal-line/src/horizontalline"; 44 | import Alignment from "@ckeditor/ckeditor5-alignment/src/alignment"; 45 | import { 46 | SpecialCharacters, 47 | SpecialCharactersEssentials, 48 | } from "@ckeditor/ckeditor5-special-characters/src/index"; 49 | import HtmlEmbed from "@ckeditor/ckeditor5-html-embed/src/htmlembed"; 50 | import { Font, FontFamily } from "@ckeditor/ckeditor5-font/src/index"; 51 | import CodeBlock from "@ckeditor/ckeditor5-code-block/src/codeblock"; 52 | import { StrapiUploadAdapter } from "@gtomato/ckeditor5-strapi-upload-plugin"; 53 | import { StrapiMediaLib } from "./strapi-medialib-plugin"; 54 | import sanitizeHtml from "sanitize-html"; 55 | import FullScreen from "./fullscreen-plugin"; 56 | 57 | export default class ClassicEditor extends ClassicEditorBase {} 58 | 59 | // Plugins to include in the build. 60 | ClassicEditor.builtinPlugins = [ 61 | Essentials, 62 | Autoformat, 63 | Bold, 64 | Italic, 65 | Underline, 66 | Strikethrough, 67 | Subscript, 68 | Superscript, 69 | RemoveFormat, 70 | SourceEditing, 71 | Code, 72 | BlockQuote, 73 | Heading, 74 | Highlight, 75 | Image, 76 | ImageInsert, 77 | ImageCaption, 78 | ImageStyle, 79 | ImageToolbar, 80 | ImageResize, 81 | ImageResizeEditing, 82 | ImageResizeButtons, 83 | Indent, 84 | IndentBlock, 85 | Link, 86 | LinkImage, 87 | ListStyle, 88 | TodoList, 89 | MediaEmbed, 90 | Paragraph, 91 | PasteFromOffice, 92 | Table, 93 | TableToolbar, 94 | TextTransformation, 95 | HorizontalLine, 96 | Alignment, 97 | AutoLink, 98 | SpecialCharacters, 99 | SpecialCharactersEssentials, 100 | HtmlEmbed, 101 | StrapiUploadAdapter, 102 | StrapiMediaLib, 103 | Font, 104 | FontFamily, 105 | CodeBlock, 106 | FullScreen, 107 | TableProperties, 108 | TableCellProperties, 109 | ]; 110 | 111 | // Editor configuration. 112 | ClassicEditor.defaultConfig = { 113 | toolbar: { 114 | items: [ 115 | "heading", 116 | "|", 117 | "fontFamily", 118 | "fontSize", 119 | "fontColor", 120 | "highLight", 121 | "|", 122 | "bold", 123 | "italic", 124 | "underline", 125 | "strikethrough", 126 | "subscript", 127 | "superscript", 128 | "removeFormat", 129 | "code", 130 | "link", 131 | "bulletedList", 132 | "numberedList", 133 | "todoList", 134 | "insertImage", 135 | "strapiMediaLib", 136 | "|", 137 | "alignment", 138 | "indent", 139 | "outdent", 140 | "|", 141 | "specialCharacters", 142 | "blockQuote", 143 | "insertTable", 144 | "mediaEmbed", 145 | "htmlEmbed", 146 | "codeBlock", 147 | "horizontalLine", 148 | "|", 149 | "sourceEditing", 150 | "|", 151 | "fullScreen", 152 | "undo", 153 | "redo", 154 | ], 155 | shouldNotGroupWhenFull: true, 156 | }, 157 | image: { 158 | styles: ["alignLeft", "alignCenter", "alignRight"], 159 | resizeOptions: [ 160 | { 161 | name: "resizeImage:original", 162 | value: null, 163 | icon: "original", 164 | }, 165 | { 166 | name: "resizeImage:50", 167 | value: "50", 168 | icon: "medium", 169 | }, 170 | { 171 | name: "resizeImage:75", 172 | value: "75", 173 | icon: "large", 174 | }, 175 | ], 176 | toolbar: [ 177 | "imageStyle:alignLeft", 178 | "imageStyle:alignCenter", 179 | "imageStyle:alignRight", 180 | "|", 181 | "imageTextAlternative", 182 | "|", 183 | "resizeImage:50", 184 | "resizeImage:75", 185 | "resizeImage:original", 186 | "|", 187 | "linkImage", 188 | ], 189 | }, 190 | table: { 191 | contentToolbar: [ 192 | "tableColumn", 193 | "tableRow", 194 | "mergeTableCells", 195 | "tableProperties", 196 | "tableCellProperties", 197 | ], 198 | }, 199 | heading: { 200 | options: [ 201 | { 202 | model: "paragraph", 203 | title: "Paragraph", 204 | class: "ck-heading_paragraph", 205 | }, 206 | { 207 | model: "heading1", 208 | view: "h1", 209 | title: "Heading 1", 210 | class: "ck-heading_heading1", 211 | }, 212 | { 213 | model: "heading2", 214 | view: "h2", 215 | title: "Heading 2", 216 | class: "ck-heading_heading2", 217 | }, 218 | { 219 | model: "heading3", 220 | view: "h3", 221 | title: "Heading 3", 222 | class: "ck-heading_heading3", 223 | }, 224 | { 225 | model: "heading4", 226 | view: "h4", 227 | title: "Heading 4", 228 | class: "ck-heading_heading4", 229 | }, 230 | ], 231 | }, 232 | htmlEmbed: { 233 | showPreviews: true, 234 | sanitizeHtml: (inputHtml) => { 235 | const outputHtml = sanitizeHtml(inputHtml); 236 | return { 237 | html: outputHtml, 238 | hasChanged: true, 239 | }; 240 | }, 241 | }, 242 | htmlSupport: { 243 | allow: [ 244 | { 245 | name: /.*/, 246 | attributes: true, 247 | classes: true, 248 | styles: true, 249 | }, 250 | ], 251 | }, 252 | fontFamily: { 253 | options: [ 254 | "default", 255 | "Arial, Helvetica, sans-serif", 256 | "Courier New, Courier, monospace", 257 | "Georgia, serif", 258 | "Lucida Sans Unicode, Lucida Grande, sans-serif", 259 | "Tahoma, Geneva, sans-serif", 260 | "Times New Roman, Times, serif", 261 | "Trebuchet MS, Helvetica, sans-serif", 262 | "Verdana, Geneva, sans-serif", 263 | "JetBrains Mono, monospace", 264 | "Lato, Inter, sans-serif", 265 | ], 266 | }, 267 | link: { 268 | defaultProtocol: "http://", 269 | decorators: [ 270 | { 271 | mode: "manual", 272 | label: "Open in a new tab", 273 | defaultValue: true, 274 | attributes: { 275 | target: "_blank", 276 | rel: "noopener noreferrer", 277 | }, 278 | }, 279 | { 280 | mode: "manual", 281 | label: "Downloadable", 282 | attributes: { 283 | download: "download", 284 | }, 285 | }, 286 | ], 287 | }, 288 | // This value must be kept in sync with the language defined in webpack.config.js. 289 | language: "en", 290 | }; 291 | -------------------------------------------------------------------------------- /src/fullscreen-plugin/README.md: -------------------------------------------------------------------------------- 1 | Derived from https://github.com/leknoppix/ckeditor5-fullscreen -------------------------------------------------------------------------------- /src/fullscreen-plugin/css/style.css: -------------------------------------------------------------------------------- 1 | #fullscreenoverlay { 2 | overflow: hidden; 3 | } 4 | 5 | #fullscreeneditor { 6 | position: fixed !important; 7 | top: 0; 8 | left: 0; 9 | right: 0; 10 | bottom: 50px; 11 | z-index: 1000; 12 | } 13 | 14 | #fullscreeneditor 15 | .ck-editor__editable.ck-rounded-corners.ck-editor__editable_inline, 16 | #fullscreeneditor .ck.ck-editor__main { 17 | height: 100%; 18 | max-height: 100% !important; 19 | } 20 | -------------------------------------------------------------------------------- /src/fullscreen-plugin/icons/fullscreen-big.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/fullscreen-plugin/icons/fullscreen-cancel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/fullscreen-plugin/index.js: -------------------------------------------------------------------------------- 1 | import Plugin from '@ckeditor/ckeditor5-core/src/plugin'; 2 | import ImageFullBig from './icons/fullscreen-big.svg'; 3 | import ImageFullCancel from './icons/fullscreen-cancel.svg'; 4 | import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview'; 5 | import './css/style.css'; 6 | 7 | export default class FullScreen extends Plugin { 8 | 9 | static get pluginName() { 10 | return 'fullScreen' 11 | } 12 | 13 | init() { 14 | const editor = this.editor; 15 | 16 | editor.ui.componentFactory.add('fullScreen', locale => { 17 | 18 | const view = new ButtonView(locale); 19 | 20 | let normalButtonState = true; // button tooltip suggests to toggle full screen; 21 | 22 | const updateButtonState = function () { 23 | if (normalButtonState) { 24 | editor.sourceElement.nextElementSibling.removeAttribute('id'); 25 | document.body.removeAttribute('id'); 26 | view.set({ 27 | label: 'Full screen', 28 | icon: ImageFullBig, 29 | tooltip: true 30 | }); 31 | normalButtonState = false; 32 | } else { 33 | editor.sourceElement.nextElementSibling.setAttribute('id', 'fullscreeneditor'); 34 | document.body.setAttribute('id', 'fullscreenoverlay'); 35 | view.set({ 36 | label: 'Normal view', 37 | icon: ImageFullCancel, 38 | tooltip: true 39 | }); 40 | normalButtonState = true; 41 | } 42 | } 43 | 44 | updateButtonState(); 45 | 46 | // Callback executed once the image is clicked 47 | view.on('execute', updateButtonState); 48 | 49 | return view; 50 | }); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/strapi-medialib-plugin/icons/strapi-medialib.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/strapi-medialib-plugin/index.js: -------------------------------------------------------------------------------- 1 | import Plugin from '@ckeditor/ckeditor5-core/src/plugin'; 2 | import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview'; 3 | import imageIcon from './icons/strapi-medialib.svg'; 4 | 5 | 6 | export class StrapiMediaLib extends Plugin { 7 | 8 | static get pluginName() { 9 | return 'strapiMediaLib' 10 | } 11 | 12 | init() { 13 | const editor = this.editor; 14 | const config = editor.config.get('strapiMediaLib'); 15 | 16 | editor.ui.componentFactory.add('strapiMediaLib', locale => { 17 | 18 | const view = new ButtonView(locale); 19 | 20 | view.set({ 21 | label: (config && config.label) ? config.label : "Media Library", 22 | icon: imageIcon, 23 | tooltip: true 24 | }); 25 | 26 | view.on('execute', () => { 27 | if (config && config.onToggle) { 28 | config.onToggle(editor); 29 | } 30 | else { 31 | alert('Properly integrate editor into Strapi to make button work'); 32 | }; 33 | }); 34 | 35 | return view; 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const path = require("path"); 4 | const webpack = require("webpack"); 5 | const TerserPlugin = require("terser-webpack-plugin"); 6 | const { bundler, styles } = require("@ckeditor/ckeditor5-dev-utils"); 7 | const CKEditorWebpackPlugin = require("@ckeditor/ckeditor5-dev-webpack-plugin"); 8 | 9 | module.exports = { 10 | devtool: "source-map", 11 | performance: { hints: false }, 12 | 13 | entry: path.resolve(__dirname, "src", "ckeditor.js"), 14 | 15 | output: { 16 | library: "ClassicEditor", 17 | path: path.resolve(__dirname, "build"), 18 | filename: "ckeditor.js", 19 | libraryTarget: "umd", 20 | libraryExport: "default", 21 | }, 22 | 23 | optimization: { 24 | minimizer: [ 25 | new TerserPlugin({ 26 | sourceMap: true, 27 | terserOptions: { 28 | output: { comments: /^!/ }, 29 | }, 30 | extractComments: false, 31 | }), 32 | ], 33 | }, 34 | 35 | plugins: [ 36 | new CKEditorWebpackPlugin({ 37 | language: "en", 38 | additionalLanguages: "all", 39 | }), 40 | new webpack.BannerPlugin({ 41 | banner: bundler.getLicenseBanner(), 42 | raw: true, 43 | }), 44 | ], 45 | 46 | module: { 47 | rules: [ 48 | { 49 | test: /\.svg$/, 50 | use: ["raw-loader"], 51 | }, 52 | { 53 | test: /\.css$/, 54 | use: [ 55 | { 56 | loader: "style-loader", 57 | options: { 58 | injectType: "singletonStyleTag", 59 | attributes: { "data-cke": true }, 60 | }, 61 | }, 62 | "css-loader", 63 | { 64 | loader: "postcss-loader", 65 | options: { 66 | postcssOptions: styles.getPostCssConfig({ 67 | themeImporter: { 68 | themePath: require.resolve( 69 | "@ckeditor/ckeditor5-theme-lark" 70 | ), 71 | }, 72 | minify: true, 73 | }), 74 | }, 75 | }, 76 | ], 77 | }, 78 | ], 79 | }, 80 | }; 81 | --------------------------------------------------------------------------------