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

How to build from source using Laravel Mix? #23

Closed
kanalumaddela opened this issue Jan 17, 2019 · 29 comments
Closed

How to build from source using Laravel Mix? #23

kanalumaddela opened this issue Jan 17, 2019 · 29 comments
Labels
resolution:resolved This issue was already resolved (e.g. by another ticket).

Comments

@kanalumaddela
Copy link

kanalumaddela commented Jan 17, 2019

If this should be posted in the main repo, I'll do that

I'm currently trying to build CKE5 from source for vue using Laravel Mix. When I attempt to add the Link plugin, it fails because it can't seem the find a mixin, but when I remove that plugin, it'll build fine, but then error in console.

I wouldn't be surprised if there's something wrong with my setup, but I tried following the advanced setup guide in the docs as opposed to building from source vue guide since that was related to vue cli.

side question: how to include the css in my app.css file during the build process?

CKE5 packages installed (the build version is there when i was testing CKE before wanting to build from source)

"@ckeditor/ckeditor5-alignment": "^10.0.4",
"@ckeditor/ckeditor5-autoformat": "^10.0.4",
"@ckeditor/ckeditor5-basic-styles": "^10.1.0",
"@ckeditor/ckeditor5-block-quote": "^10.1.1",
"@ckeditor/ckeditor5-build-classic": "^11.2.0",
"@ckeditor/ckeditor5-core": "^11.1.0",
"@ckeditor/ckeditor5-dev-utils": "^11.0.1",
"@ckeditor/ckeditor5-dev-webpack-plugin": "^7.0.1",
"@ckeditor/ckeditor5-editor-classic": "^11.0.2",
"@ckeditor/ckeditor5-essentials": "^10.1.3",
"@ckeditor/ckeditor5-heading": "^10.1.1",
"@ckeditor/ckeditor5-image": "^12.0.0",
"@ckeditor/ckeditor5-link": "^10.1.0",
"@ckeditor/ckeditor5-list": "^11.0.3",
"@ckeditor/ckeditor5-markdown-gfm": "^10.0.4",
"@ckeditor/ckeditor5-media-embed": "^10.1.0",
"@ckeditor/ckeditor5-paragraph": "^10.0.4",
"@ckeditor/ckeditor5-table": "^11.0.1",
"@ckeditor/ckeditor5-theme-lark": "^12.0.0",
"@ckeditor/ckeditor5-ui": "^11.2.0",
"@ckeditor/ckeditor5-upload": "^10.0.4",
"@ckeditor/ckeditor5-vue": "^1.0.0-beta.1",

3rd party packages (just in case there's some conflict I don't know)

"axios": "^0.18",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"bootstrap": "^4.0.0",
"browser-sync": "^2.26.3",
"browser-sync-webpack-plugin": "^2.0.1",
"cross-env": "^5.1",
"jquery": "^3.2",
"laravel-mix": "^4.0.7",
"lodash": "^4.17.5",
"popper.js": "^1.12",
"postcss-loader": "^3.0.0",
"raw-loader": "^0.5.1",
"resolve-url-loader": "^2.3.1",
"sass": "^1.15.2",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"tiptap": "^1.7.0",
"tiptap-commands": "^1.3.0",
"tiptap-extensions": "^1.7.0",
"tiptap-utils": "^1.1.0",
"vue": "^2.5.17",
"vue-template-compiler": "^2.5.22",
"vue-tippy": "^2.0.24",
"webpack": "^4.28.4",
"webpack-cli": "^3.2.1"

webpack.mix.js

const mix = require('laravel-mix');

// cke stuff
const CKEditorWebpackPlugin = require( '@ckeditor/ckeditor5-dev-webpack-plugin' );
const CKEStyles =  require( '@ckeditor/ckeditor5-dev-utils' ).styles;

// mix stuff
mix.options({
    uglify: {
        comments: false
    }
});

mix.webpackConfig({
    devtool: "inline-source-map",
    module: {
        rules: [
            {
                test: /ckeditor5-[^/]+\/theme\/icons\/[^/]+\.svg$/,
                use: [ 'raw-loader' ]
            },
            {
                test: /ckeditor5-[^/]+\/theme\/[\w-/]+\.css$/,
                use: [
                    {
                        loader: 'style-loader',
                        options: {
                            singleton: true
                        }
                    },
                    {
                        loader: 'postcss-loader',
                        options: CKEStyles.getPostCssConfig( {
                            themeImporter: {
                                themePath: require.resolve( '@ckeditor/ckeditor5-theme-lark' )
                            },
                            minify: true
                        } )
                    },
                ]
            }
        ]
    },
    plugins: [
        new CKEditorWebpackPlugin({
            language: 'en'
        })
    ]
});

mix.js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css');

app.js

// ...
import CKEditor from '@ckeditor/ckeditor5-vue';
import CKEditorClassicCustom from './components/ckeditor-classic-custom';

Vue.use(CKEditor);
Vue.component('ckeditor-classic-custom', CKEditorClassicCustom);
// ...

ckeditor-classic-custom.vue component (link plugin is commented out cause build fails when adding it)

<template>
    <ckeditor :editor="editor" v-model="editorData" :config="editorConfig"></ckeditor>
</template>

<script>
    import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';

    import EssentialsPlugin from '@ckeditor/ckeditor5-essentials/src/essentials';
    import BoldPlugin from '@ckeditor/ckeditor5-basic-styles/src/bold';
    import ItalicPlugin from '@ckeditor/ckeditor5-basic-styles/src/italic';
    // import LinkPlugin from '@ckeditor/ckeditor5-link/src/link';
    import ParagraphPlugin from '@ckeditor/ckeditor5-paragraph/src/paragraph';


    export default {
        name: 'ckeditor-classic-custom',
        data() {
            return {
                editor: ClassicEditor,
                editorData: '<p>Hello there.</p>',
                editorConfig: {
                    plugins: [
                        EssentialsPlugin,
                        BoldPlugin,
                        ItalicPlugin,
                        //LinkPlugin,
                        ParagraphPlugin
                    ],

                    toolbar: {
                        items: [
                            'bold',
                            'italic',
                            //'link',
                            '|',
                            'undo',
                            'redo'
                        ]
                    }
                }
            };
        }
    };
</script>
  1. Issue when not using the Link plugin
    image
    image

  2. Build issue when using the Link plugin (boxed issues)
    image
    (I tried that npm install --save command, but that didn't work)

@kanalumaddela
Copy link
Author

kanalumaddela commented Jan 17, 2019

Updated the regex rules in the webpack config after looking at another somewhat similar issue. Commented out the ones I had
reference: ckeditor/ckeditor5-react#42

mix.webpackConfig({
    devtool: "inline-source-map",
    module: {
        rules: [
            {
                test: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
                //test: /ckeditor5-[^/]+\/theme\/icons\/[^/]+\.svg$/,
                use: [ 'raw-loader' ]
            },
            {
                test: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/,
                //test: /ckeditor5-[^/]+\/theme\/[\w-/]+\.css$/,
                use: [
                    {
                        loader: 'style-loader',
                        options: {
                            singleton: true
                        }
                    },
                    {
                        loader: 'postcss-loader',
                        options: CKEStyles.getPostCssConfig( {
                            themeImporter: {
                                themePath: require.resolve( '@ckeditor/ckeditor5-theme-lark' )
                            },
                            minify: true
                        } )
                    },
                ]
            }
        ]
    },
    plugins: [
        new CKEditorWebpackPlugin({
            language: 'en'
        })
    ]
});

error (all 9 of those errors are the same as below)
image

@oleq
Copy link
Member

oleq commented Jan 17, 2019

The very first question is: does using the editor from source with ckeditor5-vue work for you without any Laravel stuff (pure vanilla code like the guide) in the first place?

In other words: if you copy&paste the entire guide code in a new empty project that has nothing to do with your application, does it compile and run?

@kanalumaddela
Copy link
Author

kanalumaddela commented Jan 17, 2019

Building the editor from source in an empty vue project via vue-cli does work. I assume your suggestion would be to build separately and make a npm package for the custom component?

side question: Is there a way to build the css separately and not as a part of the vue component where it gets injected?

@oleq
Copy link
Member

oleq commented Jan 18, 2019

I assume your suggestion would be to build separately and make a npm package for the custom component?

Not exactly, I wanted to first make sure your env is OK and there's nothing wrong with ckeditor5-vue itself.

Is there any chance you can publish a (minimal) PoC somewhere (like a public GitHub repo) so we can debug this thing?

side question: Is there a way to build the css separately and not as a part of the vue component where it gets injected?

Like, for instance, extracting them to a separate file?

@kanalumaddela
Copy link
Author

Is there any chance you can publish a (minimal) PoC somewhere (like a public GitHub repo) so we can debug this thing?

sure thing, https://github.com/kanalumaddela/laravel-ckeditor5-vue-debug
my timezone's est and it's 5:28am as of commenting, so my next comment could be in a couple of hours

Like, for instance, extracting them to a separate file?

oops, guess I was kinda focused on the primary webpack config

@oleq
Copy link
Member

oleq commented Jan 18, 2019

I checked your app and I reproduced the issue. My first guess is that the CSS files are processed twice by Webpack.

It happened in the past, for instance in the official react integration where we had to exclude ckeditor5/.../*.css files from the default CSS processing chain (search for "Exclude CSS files used by CKEditor 5 from project’s CSS loader").

Maybe if you figured how to exclude these CSS files in your app, things would work out. I'm not really into Laravel so I don't really know where the rest (the default) webpack config is and how it works.

@kanalumaddela
Copy link
Author

kanalumaddela commented Jan 18, 2019

It happened in the past, for instance in the official react integration where we had to exclude ckeditor5/.../*.css files from the default CSS processing chain (search for "Exclude CSS files used by CKEditor 5 from project’s CSS loader").

Maybe if you figured how to exclude these CSS files in your app, things would work out. I'm not really into Laravel so I don't really know where the rest (the default) webpack config is and how it works.

I imported the default config into the webpack.config.js file where you can access the rules by defaultConfig.module.rules I found this issue which supposedly fixed the issue via excludes, but it never worked for me: laravel-mix/laravel-mix#1397

this was the code I had tried which modified the default config
webpack.config.js

const defaultConfig = require('laravel-mix/setup/webpack.config');

/**
 * CKE stuff
 */
const CKEStyles = require('@ckeditor/ckeditor5-dev-utils').styles;
const CKERegex = {
    svg: /ckeditor5-[^/]+\/theme\/icons\/[^/]+\.svg$/,
    css: /ckeditor5-[^/]+\/theme\/[\w-/]+\.css$/,
}
const CKERules = [
    {
        test: CKERegex['svg'],
        use: [ 'raw-loader' ]
    },
    {
        test: CKERegex['css'],
        use: [
            {
                loader: 'style-loader',
                options: {
                    singleton: true
                }
            },
            {
                loader: 'postcss-loader',
                options: CKEStyles.getPostCssConfig( {
                    themeImporter: {
                        themePath: require.resolve('@ckeditor/ckeditor5-theme-lark')
                    },
                    minify: true
                } )
            },
        ]
    }
]

// exclude CKE from generic css and svg rules
defaultConfig.module.rules = defaultConfig.module.rules.map(rule => {
    for (let key in CKERegex) {
        if (`test.${key}`.match(rule.test)) {
            if (rule.exclude) {
                if (rule.exclude instanceof Array)
                    rule.exclude.push(CKERegex[key]);
                else
                    rule.exclude = [rule.exclude, CKERegex[key]];
            } else
                rule.exclude = CKERegex[key];
        }
    }

    return rule;
});

defaultConfig.module.rules = defaultConfig.module.rules.concat(CKERules);

// debug purposes
console.log(defaultConfig.module.rules);

module.exports = defaultConfig;

When console.log()'ng the rules, it shows the cke regex as part of the excludes, but it doesn't seem to have any effect.
image
(Just realized the rules are there twice because I'm already adding them in webpack.mix.js)

@kanalumaddela
Copy link
Author

kanalumaddela commented Jan 18, 2019

I tried something different with the excludes by only editing the webpack.mix.js and adding this shoddy code in:

Mix.listen('configReady', webpackConfig => {
    const rules = webpackConfig.module.rules;
    const targetSVG = /(\.(png|jpe?g|gif|webp)$|^((?!font).)*\.svg$)/;
    const targetCSS = /\.css$/;

    for (let rule of rules) {
        if (rule.test.toString() === targetSVG.toString()) {
            rule.exclude = /\.svg$/;
            //rule.exclude = CKERegex.svg;
        }
        else if (rule.test.toString() === targetCSS.toString()) {
            rule.exclude = CKERegex.css;
        }
    }
});

and updating the rules like so:

\\ ...
    module: {
        rules: [
            {
                test: /\.svg$/,
                //test: CKERegex.svg,
                use: [ 'raw-loader' ]
            },
\\ ...

This removed svgs from the original image rule and I then also used the "generic" svg rule instead of the ckeditor specific one. This allowed the build to work (when the Link plugin isn't included however), but I think the issue may be the regex used.

image

The svgs are now included, but not all the CSS required for ckeditor is there. I tried extracting, but that didn't do anything which I also assume is due to the regex. I can't match general css cause that cause more conflicts than intended (plus laravel mix errors when I do so).

My guess is that the regex isn't properly matching? At the moment I don't have an issue with using the general regex for svgs, but I can't seem to write a regex that works for the ckeditor css.

@kanalumaddela
Copy link
Author

kanalumaddela commented Jan 19, 2019

EDIT: See #23 (comment) for those using Font plugin(s)


I don't know why I didn't try this regex sooner, but I used the regex in the react doc you linked and that worked! The regex in the react doc is different than that in the general webpack docs

/ckeditor5-[^/]+\/theme\/icons\/[^/]+\.svg$/
/ckeditor5-[^/]+\/theme\/[\w-/]+\.css$/

vs 

/ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/
/ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/

Final partial of webpack.mix.js

\\ ...

/**
 * CKE stuff
 */
const CKEditorWebpackPlugin = require( '@ckeditor/ckeditor5-dev-webpack-plugin' );
const CKEStyles = require('@ckeditor/ckeditor5-dev-utils').styles;
const CKERegex = {
    svg: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
    css: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/,
};

Mix.listen('configReady', webpackConfig => {
    const rules = webpackConfig.module.rules;
    const targetSVG = /(\.(png|jpe?g|gif|webp)$|^((?!font).)*\.svg$)/;
    const targetCSS = /\.css$/;

    // exclude CKE regex from mix's default rules
    // if there's a better way to loop/change this, open to suggestions
    for (let rule of rules) {
        if (rule.test.toString() === targetSVG.toString()) {
            rule.exclude = CKERegex.svg;
        }
        else if (rule.test.toString() === targetCSS.toString()) {
            rule.exclude = CKERegex.css;
        }
    }
});

mix.webpackConfig({
    plugins: [
        new CKEditorWebpackPlugin({
            language: 'en'
        })
    ],
    module: {
        rules: [
            {
                test: CKERegex.svg,
                use: [ 'raw-loader' ]
            },
            {
                test: CKERegex.css,
                use: [
                    {
                        loader: 'style-loader',
                        options: {
                            singleton: true
                        }
                    },
                    {
                        loader: 'postcss-loader',
                        options: CKEStyles.getPostCssConfig({
                            themeImporter: {
                                themePath: require.resolve('@ckeditor/ckeditor5-theme-lark')
                            },
                            minify: true
                        })
                    },
                ]
            }
        ]
    }
});

\\ ...

Since the regex finally matches properly, I assume extracting the css out should work also, but I'll leave this issue open till I test that in a couple of mins.

Extracting CSS works perfectly, closing the issue.

@kanalumaddela
Copy link
Author

Just another minor note for future people who come across this. When using the FontFamily and FontSize plugins, you will need to add excludes to the font related rule set by mix since the svgs contain font in their filename.

the Mix.listen() should be updated to the following (unless someone has a better way of going through the rules and adding the excludes.

Mix.listen('configReady', webpackConfig => {
    const rules = webpackConfig.module.rules;
    const targetSVG = /(\.(png|jpe?g|gif|webp)$|^((?!font).)*\.svg$)/;
    const targetFont = /(\.(woff2?|ttf|eot|otf)$|font.*\.svg$)/;
    const targetCSS = /\.css$/;

    // exclude CKE regex from mix's default rules
    for (let rule of rules) {
        if (rule.test.toString() === targetSVG.toString()) {
            rule.exclude = CKERegex.svg;
        }
        else if (rule.test.toString() === targetFont.toString()) {
            rule.exclude = CKERegex.svg;
        }
        else if (rule.test.toString() === targetCSS.toString()) {
            rule.exclude = CKERegex.css;
        }
    }
});

@svkmedia
Copy link

Thank you @kanalumaddela you saved my day! I spent 3 hours trying to fix font plugin icons in webpack... Maybe edit your first solution because I missed your next comment about font plugin :)

@kfirba
Copy link

kfirba commented Apr 2, 2020

@kanalumaddela Hey!

I've just tried doing exactly what you have here, but it did not work. I get an error that it can't find the .svg files:

These dependencies were not found:
[0] 
[0] * @ckeditor/ckeditor5-core/theme/icons/pilcrow.svg in ./node_modules/@ckeditor/ckeditor5-ui/src/toolbar/block/blocktoolbar.js
[0] * @ckeditor/ckeditor5-core/theme/icons/eraser.svg in ./node_modules/@ckeditor/ckeditor5-highlight/src/highlightui.js, ./node_modules/@ckeditor/ckeditor5-font/src/ui/colortableview.js
[0] * @ckeditor/ckeditor5-core/theme/icons/quote.svg in ./node_modules/@ckeditor/ckeditor5-block-quote/src/blockquoteui.js
[0] * @ckeditor/ckeditor5-core/theme/icons/three-vertical-dots.svg in ./node_modules/@ckeditor/ckeditor5-ui/src/toolbar/toolbarview.js
[0] * @ckeditor/ckeditor5-core/theme/icons/low-vision.svg in ./node_modules/@ckeditor/ckeditor5-image/src/imagetextalternative/imagetextalternativeui.js
[0] * @ckeditor/ckeditor5-core/theme/icons/object-full-width.svg in ./node_modules/@ckeditor/ckeditor5-image/src/imagestyle/utils.js
[0] * @ckeditor/ckeditor5-core/theme/icons/object-right.svg in ./node_modules/@ckeditor/ckeditor5-image/src/imagestyle/utils.js
[0] * @ckeditor/ckeditor5-core/theme/icons/object-center.svg in ./node_modules/@ckeditor/ckeditor5-image/src/imagestyle/utils.js
[0] * @ckeditor/ckeditor5-core/theme/icons/object-left.svg in ./node_modules/@ckeditor/ckeditor5-image/src/imagestyle/utils.js
[0] * @ckeditor/ckeditor5-core/theme/icons/cancel.svg in ./node_modules/@ckeditor/ckeditor5-media-embed/src/ui/mediaformview.js, ./node_modules/@ckeditor/ckeditor5-link/src/ui/linkformview.js and 1 other
[0] * @ckeditor/ckeditor5-core/theme/icons/check.svg in ./node_modules/@ckeditor/ckeditor5-media-embed/src/ui/mediaformview.js, ./node_modules/@ckeditor/ckeditor5-link/src/ui/linkformview.js and 1 other
[0] * @ckeditor/ckeditor5-core/theme/icons/pencil.svg in ./node_modules/@ckeditor/ckeditor5-link/src/ui/linkactionsview.js
[0] * @ckeditor/ckeditor5-core/theme/icons/image.svg in ./node_modules/@ckeditor/ckeditor5-image/src/imageupload/imageuploadui.js
[0] 
[0] To install them, you can run: npm install --save @ckeditor/ckeditor5-core/theme/icons/pilcrow.svg @ckeditor/ckeditor5-core/theme/icons/eraser.svg @ckeditor/ckeditor5-core/theme/icons/quote.svg @ckeditor/ckeditor5-core/theme/icons/three-vertical-dots.svg @ckeditor/ckeditor5-core/theme/icons/low-vision.svg @ckeditor/ckeditor5-core/theme/icons/object-full-width.svg @ckeditor/ckeditor5-core/theme/icons/object-right.svg @ckeditor/ckeditor5-core/theme/icons/object-center.svg @ckeditor/ckeditor5-core/theme/icons/object-left.svg @ckeditor/ckeditor5-core/theme/icons/cancel.svg @ckeditor/ckeditor5-core/theme/icons/check.svg @ckeditor/ckeditor5-core/theme/icons/pencil.svg @ckeditor/ckeditor5-core/theme/icons/image.svg
[0] 
[0] 
[0] These relative modules were not found:
[0] 
[0] * ../../theme/icons/image_placeholder.svg in ./node_modules/@ckeditor/ckeditor5-image/src/imageupload/imageuploadprogress.js
[0] * ../theme/icons/remove-format.svg in ./node_modules/@ckeditor/ckeditor5-remove-format/src/removeformatui.js
[0] * ../../theme/icons/underline.svg in ./node_modules/@ckeditor/ckeditor5-basic-styles/src/underline/underlineui.js
[0] * ../theme/icons/redo.svg in ./node_modules/@ckeditor/ckeditor5-undo/src/undoui.js
[0] * ../theme/icons/undo.svg in ./node_modules/@ckeditor/ckeditor5-undo/src/undoui.js
[0] * ../../../theme/icons/dropdown-arrow.svg in ./node_modules/@ckeditor/ckeditor5-ui/src/dropdown/button/dropdownbuttonview.js, ./node_modules/@ckeditor/ckeditor5-ui/src/dropdown/button/splitbuttonview.js
[0] * ../../../theme/icons/previous-arrow.svg in ./node_modules/@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon.js
[0] * ../../../theme/icons/next-arrow.svg in ./node_modules/@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon.js
[0] * ../../theme/icons/strikethrough.svg in ./node_modules/@ckeditor/ckeditor5-basic-styles/src/strikethrough/strikethroughui.js
[0] * ../../theme/icons/italic.svg in ./node_modules/@ckeditor/ckeditor5-basic-styles/src/italic/italicui.js
[0] * ../../theme/icons/bold.svg in ./node_modules/@ckeditor/ckeditor5-basic-styles/src/bold/boldui.js
[0] * ../theme/icons/horizontalline.svg in ./node_modules/@ckeditor/ckeditor5-horizontal-line/src/horizontallineui.js
[0] * ../../theme/icons/font-size.svg in ./node_modules/@ckeditor/ckeditor5-font/src/fontsize/fontsizeui.js
[0] * ../../theme/icons/font-color.svg in ./node_modules/@ckeditor/ckeditor5-font/src/fontcolor/fontcolorui.js
[0] * ./../theme/icons/table-merge-cell.svg in ./node_modules/@ckeditor/ckeditor5-table/src/tableui.js
[0] * ./../theme/icons/table-row.svg in ./node_modules/@ckeditor/ckeditor5-table/src/tableui.js
[0] * ./../theme/icons/table-column.svg in ./node_modules/@ckeditor/ckeditor5-table/src/tableui.js
[0] * ./../theme/icons/table.svg in ./node_modules/@ckeditor/ckeditor5-table/src/tableui.js
[0] * ../theme/icons/outdent.svg in ./node_modules/@ckeditor/ckeditor5-indent/src/indentui.js
[0] * ../theme/icons/media.svg in ./node_modules/@ckeditor/ckeditor5-media-embed/src/mediaembedui.js
[0] * ../theme/icons/link.svg in ./node_modules/@ckeditor/ckeditor5-link/src/linkui.js
[0] * ../theme/icons/drag-handle.svg in ./node_modules/@ckeditor/ckeditor5-widget/src/utils.js
[0] * ../../theme/icons/unlink.svg in ./node_modules/@ckeditor/ckeditor5-link/src/ui/linkactionsview.js
[0] * ./../theme/icons/pen.svg in ./node_modules/@ckeditor/ckeditor5-highlight/src/highlightui.js
[0] * ./../theme/icons/marker.svg in ./node_modules/@ckeditor/ckeditor5-highlight/src/highlightui.js
[0] * ../theme/icons/indent.svg in ./node_modules/@ckeditor/ckeditor5-indent/src/indentui.js
[0] * ../theme/icons/media-placeholder.svg in ./node_modules/@ckeditor/ckeditor5-media-embed/src/mediaregistry.js
[0] * ../theme/icons/bulletedlist.svg in ./node_modules/@ckeditor/ckeditor5-list/src/listui.js
[0] * ../theme/icons/numberedlist.svg in ./node_modules/@ckeditor/ckeditor5-list/src/listui.js
[0] * ../../theme/icons/color-tile-check.svg in ./node_modules/@ckeditor/ckeditor5-ui/src/colorgrid/colortileview.js

my webpack.mix.js file contains:

const CKEditorWebpackPlugin = require('@ckeditor/ckeditor5-dev-webpack-plugin');
const CKEStyles = require('@ckeditor/ckeditor5-dev-utils').styles;
const CKERegex = {
  svg: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
  css: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/,
};

Mix.listen('configReady', webpackConfig => {
  const rules = webpackConfig.module.rules;
  const targetSVG = /(\.(png|jpe?g|gif|webp)$|^((?!font).)*\.svg$)/;
  const targetFont = /(\.(woff2?|ttf|eot|otf)$|font.*\.svg$)/;
  const targetCSS = /\.css$/;

  // exclude CKE regex from mix's default rules
  for (let rule of rules) {
    if (rule.test.toString() === targetSVG.toString()) {
      rule.exclude = CKERegex.svg;
    }
    else if (rule.test.toString() === targetFont.toString()) {
      rule.exclude = CKERegex.svg;
    }
    else if (rule.test.toString() === targetCSS.toString()) {
      rule.exclude = CKERegex.css;
    }
  }
});

mix.webpackConfig({
  plugins: [
    new CKEditorWebpackPlugin({
      language: 'he',
    }),
  ],
  module: {
    rules: [
      {
        test: CKERegex.svg,
        use: ['raw-loader'],
      },
      {
        test: CKERegex.css,
        use: [
          {
            loader: 'style-loader',
            options: {
              singleton: true,
            },
          },
          {
            loader: 'postcss-loader',
            options: CKEStyles.getPostCssConfig({
              themeImporter: {
                themePath: require.resolve('@ckeditor/ckeditor5-theme-lark'),
              },
              minify: true,
            }),
          },
        ],
      },
    ],
  },
});

The file in which I'm building my editor:

import BalloonBlockEditor from '@ckeditor/ckeditor5-editor-balloon/src/ballooneditor';
import Autoformat from '@ckeditor/ckeditor5-autoformat/src/autoformat';
import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
import BlockQuote from '@ckeditor/ckeditor5-block-quote/src/blockquote';
import Heading from '@ckeditor/ckeditor5-heading/src/heading';
import Image from '@ckeditor/ckeditor5-image/src/image';
import ImageCaption from '@ckeditor/ckeditor5-image/src/imagecaption';
import ImageStyle from '@ckeditor/ckeditor5-image/src/imagestyle';
import ImageToolbar from '@ckeditor/ckeditor5-image/src/imagetoolbar';
import ImageUpload from '@ckeditor/ckeditor5-image/src/imageupload';
import Indent from '@ckeditor/ckeditor5-indent/src/indent';
import Link from '@ckeditor/ckeditor5-link/src/link';
import List from '@ckeditor/ckeditor5-list/src/list';
import MediaEmbed from '@ckeditor/ckeditor5-media-embed/src/mediaembed';
import PasteFromOffice from '@ckeditor/ckeditor5-paste-from-office/src/pastefromoffice';
import Table from '@ckeditor/ckeditor5-table/src/table';
import TableToolbar from '@ckeditor/ckeditor5-table/src/tabletoolbar';
import Strikethrough from '@ckeditor/ckeditor5-basic-styles/src/strikethrough';
import FontColor from '@ckeditor/ckeditor5-font/src/fontcolor';
import FontSize from '@ckeditor/ckeditor5-font/src/fontsize';
import Highlight from '@ckeditor/ckeditor5-highlight/src/highlight';
import HorizontalLine from '@ckeditor/ckeditor5-horizontal-line/src/horizontalline';
import RemoveFormat from '@ckeditor/ckeditor5-remove-format/src/removeformat';
import Underline from '@ckeditor/ckeditor5-basic-styles/src/underline';
import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
import BlockToolbar from '@ckeditor/ckeditor5-ui/src/toolbar/block/blocktoolbar';

export default class Editor extends BalloonBlockEditor {}

// Plugins to include in the build.
Editor.builtinPlugins = [
  Autoformat,
  Bold,
  Italic,
  BlockQuote,
  Heading,
  Image,
  ImageCaption,
  ImageStyle,
  ImageToolbar,
  ImageUpload,
  Indent,
  Link,
  List,
  MediaEmbed,
  PasteFromOffice,
  Table,
  TableToolbar,
  Strikethrough,
  FontColor,
  FontSize,
  Highlight,
  HorizontalLine,
  RemoveFormat,
  Underline,
  Essentials,
  Paragraph,
  BlockToolbar,
];

Any idea why is this happening? Tried to debug the svg problem for a few hours now... :/

@svkmedia
Copy link

svkmedia commented Apr 2, 2020

@kfirba did you install ckeditor theme?

@kfirba
Copy link

kfirba commented Apr 2, 2020

@svkmedia yea I have it all installed. Grabbed the build from their online builder. The SVG files are there but it complains about it unable to find/load the files

@kanalumaddela
Copy link
Author

@kfirba do you think you could provide a debug repo to replicate the issue?

@kfirba
Copy link

kfirba commented Apr 5, 2020

@kanalumaddela it turns out I was missing the raw-loader for some reason. I installed it and now everything works as expected.

It's not related to this issue, but have you managed to return custom HTML for one of your data downcasting? If so, maybe you can help me with the following: ckeditor/ckeditor5#1126 (comment)

@aske-cph
Copy link

aske-cph commented Oct 9, 2020

Thanks so much for the webpack config code but this doesn't seem to work with Laravels new Jetstream scaffolding (laravel 8).

Probably because that implementation tries to run PostCss on the entire output (so ckeditor gets run thorugh posts css , twice?), so i get:

ERROR in ./node_modules/@ckeditor/ckeditor5-engine/theme/placeholder.css (./node_modules/css-loader??ref--6-1!./node_modules/postcss-loader/src??ref--6-2!./node_modules/style-loader??ref--12-0!./node_modules/postcss-loader/src??ref--12-1!./node_modules/@ckeditor/ckeditor5-engine/theme/placeholder.css)
Module build failed (from ./node_modules/postcss-loader/src/index.js):
SyntaxError

(2:1) Unknown word

  1 |
> 2 | var content = require("!!../../../postcss-loader/src/index.js??ref--12-1!./placeholder.css");

My webpack.mix.js is exactly as @kanalumaddela provided, only it already has the Laravel Jetstream code as follows:

mix.js('resources/js/app.js', 'public/js')
    .postCss('resources/css/app.css', 'public/css', [
        require('postcss-import'),
        require('tailwindcss'),
    ]);

I think i have to exclude Laravel Mix's postcss from doing anything in the node_modules/ckeditor folder but i can't get i to work.
Any clues as to how you can exclude Laravel Mix postcss from running twice (or over the already Post Css'ed ckeditor folder)?

@icreatestuff
Copy link

I also can't get this webpack config code to work with Laravel Mix v6.0.10 and some of the latest versions of the CKEditor packages.

I get similar errors to those @aske-cph mentions such as:

ERROR in ./node_modules/@ckeditor/ckeditor5-widget/theme/widgettypearound.css (./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[5].oneOf[1].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[5].oneOf[1].use[2]!./node_modules/style-loader/dist/cjs.js??ruleSet[1].rules[11].use[0]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[11].use[1]!./node_modules/@ckeditor/ckeditor5-widget/theme/widgettypearound.css)
Module build failed (from ./node_modules/postcss-loader/dist/cjs.js):
SyntaxError

(1:1) /path/to/file/node_modules/@ckeditor/ckeditor5-widget/theme/widgettypearound.css Unknown word

> 1 | var api = require("!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js");
    | ^
  2 |             var content = require("!!../../../postcss-loader/dist/cjs.js??ruleSet[1].rules[11].use[1]!./widgettypearound.css");
  3 | 

However I am using not Laravel Mix's PostCSS compiler directly at all.

package.json

"devDependencies": {
    "laravel-mix": "^6.0.10",
    "postcss": "^8.2.4",
  },
  "dependencies": {
    "@ckeditor/ckeditor5-alignment": "^24.0.0",
    "@ckeditor/ckeditor5-autoformat": "^24.0.0",
    "@ckeditor/ckeditor5-basic-styles": "^24.0.0",
    "@ckeditor/ckeditor5-block-quote": "^24.0.0",
    "@ckeditor/ckeditor5-dev-utils": "^24.0.1",
    "@ckeditor/ckeditor5-dev-webpack-plugin": "^24.0.1",
    "@ckeditor/ckeditor5-editor-classic": "^24.0.0",
    "@ckeditor/ckeditor5-essentials": "^24.0.0",
    "@ckeditor/ckeditor5-heading": "^24.0.0",
    "@ckeditor/ckeditor5-image": "^24.0.0",
    "@ckeditor/ckeditor5-link": "^24.0.0",
    "@ckeditor/ckeditor5-list": "^24.0.0",
    "@ckeditor/ckeditor5-media-embed": "^24.0.0",
    "@ckeditor/ckeditor5-paragraph": "^24.0.0",
    "@ckeditor/ckeditor5-theme-lark": "^24.0.0",
    "@ckeditor/ckeditor5-upload": "^24.0.0",
    "@ckeditor/ckeditor5-word-count": "^24.0.0",
    "postcss-loader": "^4.1.0",
    "raw-loader": "^3.1.0",
    "style-loader": "^1.2.1",
  }

webpack.mix.js

const mix = require('laravel-mix');

const CKEditorWebpackPlugin = require('@ckeditor/ckeditor5-dev-webpack-plugin');
const { styles } = require('@ckeditor/ckeditor5-dev-utils');
const CKERegex = {
    svg: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
    css: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/,
};

Mix.listen('configReady', webpackConfig => {
    const rules = webpackConfig.module.rules;
    const targetSVG = /(\.(png|jpe?g|gif|webp)$|^((?!font).)*\.svg$)/;
    const targetFont = /(\.(woff2?|ttf|eot|otf)$|font.*\.svg$)/;
    const targetCSS = /\.css$/;

    // exclude CKE regex from mix's default rules
    for (let rule of rules) {
        if (rule.test.toString() === targetSVG.toString()) {
            rule.exclude = CKERegex.svg;
        }
        else if (rule.test.toString() === targetFont.toString()) {
            rule.exclude = CKERegex.svg;
        }
        else if (rule.test.toString() === targetCSS.toString()) {
            rule.exclude = CKERegex.css;
        }
    }
});

mix.webpackConfig({
    plugins: [
        new CKEditorWebpackPlugin({
            language: 'en',
            addMainLanguageTranslationsToAllAssets: true
        })
    ],
    module: {
        rules: [
            {
                test: CKERegex.svg,
                use: ['raw-loader']
            },
            {
                test: CKERegex.css,
                use: [
                    {
                        loader: 'style-loader',
                        options: {
                            injectType: 'singletonStyleTag',
                            attributes: {
                                'data-cke': true
                            }
                        }
                    },
                    {
                        loader: 'postcss-loader',
                        options: styles.getPostCssConfig({
                            themeImporter: {
                                themePath: require.resolve('@ckeditor/ckeditor5-theme-lark')
                            },
                            minify: true
                        })
                    }
                ]
            }
        ]
    }
});

mix.setPublicPath('public')

mix.js('src/js/app.js', 'js');

/src/js/app.js

import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
import Alignment from '@ckeditor/ckeditor5-alignment/src/alignment';
import Autoformat from '@ckeditor/ckeditor5-autoformat/src/autoformat';
import BlockQuote from '@ckeditor/ckeditor5-block-quote/src/blockquote';
import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
import Heading from '@ckeditor/ckeditor5-heading/src/heading';
import Image from '@ckeditor/ckeditor5-image/src/image';
import ImageCaption from '@ckeditor/ckeditor5-image/src/imagecaption';
import ImageResize from '@ckeditor/ckeditor5-image/src/imageresize';
import ImageStyle from '@ckeditor/ckeditor5-image/src/imagestyle';
import ImageToolbar from '@ckeditor/ckeditor5-image/src/imagetoolbar';
import ImageUpload from '@ckeditor/ckeditor5-image/src/imageupload';
import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
import Link from '@ckeditor/ckeditor5-link/src/link';
import LinkImage from '@ckeditor/ckeditor5-link/src/linkimage';
import List from '@ckeditor/ckeditor5-list/src/list';
import ListStyle from '@ckeditor/ckeditor5-list/src/liststyle';
import MediaEmbed from '@ckeditor/ckeditor5-media-embed/src/mediaembed';
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
import SimpleUploadAdapter from '@ckeditor/ckeditor5-upload/src/adapters/simpleuploadadapter';
import Strikethrough from '@ckeditor/ckeditor5-basic-styles/src/strikethrough';
import WordCount from '@ckeditor/ckeditor5-word-count/src/wordcount';


if (document.querySelector('.editor')) {
    ClassicEditor.create(document.querySelector('.editor'), {
        plugins: [
            Alignment,
            Autoformat,
            BlockQuote,
            Bold,
            Essentials,
            Heading,
            Image,
            ImageCaption,
            ImageResize,
            ImageStyle,
            ImageToolbar,
            ImageUpload,
            Italic,
            Link,
            LinkImage,
            List,
            ListStyle,
            MediaEmbed,
            Paragraph,
            SimpleUploadAdapter,
            Strikethrough,
            WordCount,
        ],
        alignment: {
            options: ['left', 'center', 'right']
        },
        heading: {
            options: [
                { model: 'paragraph', title: 'Paragraph Text', class: 'ck-heading_paragraph' },
                { model: 'heading2', view: 'h2', title: 'Heading 1', class: 'ck-heading_heading2' },
                { model: 'heading3', view: 'h3', title: 'Heading 2', class: 'ck-heading_heading3' },
                { model: 'heading4', view: 'h4', title: 'Heading 3', class: 'ck-heading_heading4' }
            ]
        },
        image: {
            toolbar: [
                'imageStyle:full',
                'imageStyle:side',
                '|',
                'imageResize:original',
                'imageResize:25',
                'imageResize:50',
                'imageResize:75',
                '|',
                'imageTextAlternative'
            ],
            upload: {
                types: ['jpeg', 'png', 'gif']
            },
            resizeUnit: '%',
            resizeOptions: [
                {
                    name: 'imageResize:original',
                    value: null,
                    icon: 'original'
                },
                {
                    name: 'imageResize:25',
                    value: '25',
                    icon: 'small'
                },
                {
                    name: 'imageResize:50',
                    value: '50',
                    icon: 'medium'
                },
                {
                    name: 'imageResize:75',
                    value: '75',
                    icon: 'large'
                }
            ]
        },
        link: {
            decorators: {
                openInNewTab: {
                    mode: 'manual',
                    label: 'Open in a new tab',
                    defaultValue: true,			// This option will be selected by default.
                    attributes: {
                        target: '_blank',
                        rel: 'noopener noreferrer'
                    }
                }
            }
        },
        mediaEmbed: {
            previewsInData: false,
            removeProviders: [ 'instagram', 'twitter', 'googleMaps', 'flickr', 'facebook']
        },
        simpleUpload: {
            headers: {
                'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
            },
            uploadUrl: window.location.origin + '/img/upload/' + window.location.pathname.split('/')[2],
        },
        toolbar: {
            items: [
                'heading',
                '|',
                'bold',
                'italic',
                'strikethrough',
                'blockQuote',
                '|',
                'alignment',
                '|',
                'bulletedList',
                'numberedList',
                '|',
                'link',
                'imageUpload',
                'mediaEmbed',
                '|',
                'undo',
                'redo'
            ]
        },
        language: 'en'
    })
    .catch( error => {
        console.error( error );
    });
}

Additional note

The CKEditor5 Docs indicate to use style-loader@1 which I think must've changed the available options. i.e. singleton:true from earlier examples on this thread failed.

@XGhozt
Copy link

XGhozt commented Jan 20, 2021

I have the exact same problem as @icreatestuff above except I also noticed this in the console:

Cannot find the CKEditor 5 core translation package (which defaults to `@ckeditor/ckeditor5-core`).

This shows up in the log before it completes but I'm not sure if it's related.

That said.. I was able to get this to work but I believe the problem is a bit complicated including multiple packages.

The mix configReady snippet above from @kanalumaddela that has this part:

const targetCSS = /\.css$/

Needs to be changed to this:
const targetCSS = /\.p?css$/

I'm not sure WHY exactly but this must have been a change in the new version of mix/webpack because the for loop wasn't actually excluding the CSS files anymore and when I looked at the matching rules it was .p?css. This then caused another error which had to do with postcss apparent syntax change in the options object.

I found this, mentioned here:
ckeditor/ckeditor5#8315 (comment)

That led me here:
ckeditor/ckeditor5-dev#673

Which turns out the problem is because of this file:
https://github.com/ckeditor/ckeditor5-dev/blob/master/packages/ckeditor5-dev-utils/lib/styles/getpostcssconfig.js

As you can see "plugins" here should be postcssOptions.plugins (and this might be included in the incomplete pull request above).

	const config = {
		postcssOptions: {
			plugins: [
				require( 'postcss-import' )(),
				require( './themeimporter' )( options.themeImporter ),
				require( 'postcss-mixins' )(),
				require( 'postcss-nesting' )(),
				require( './themelogger' )()
			]
		}
	};

I just made the change locally to confirm it worked and.. it did.

I'm not sure what to make of all this, but maybe someone else more familiar with webpack and postcss can step in from here?

XGhozt added a commit to XGhozt/ckeditor5-dev that referenced this issue Jan 20, 2021
@icreatestuff
Copy link

icreatestuff commented Jan 25, 2021

Thanks for posting your findings @XGhozt. I've tried working through your steps to:

  1. Alter the targetCSS variable
  2. Edit the node_modules/@ckeditor/ckeditor5-dev-utils/lib/styles/getpostcssconfig.js file
  3. Edit the relevant part of the webpack config in my webpack.mix.js file to use
loader: 'postcss-loader',
options: {
    postcssOptions: styles.getPostCssConfig({
        themeImporter: {
            themePath: require.resolve('@ckeditor/ckeditor5-theme-lark')
        },
        minify: true
    })
}

I'm now seeing a ton of You did not set any plugins, parser, or stringifier. Right now, PostCSS does nothing. Pick plugins for your case on https://www.postcss.parts/ and use them in postcss.config.js.

and errors such as

ERROR in ./node_modules/@ckeditor/ckeditor5-block-quote/theme/blockquote.css (./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[11].use[1]!./node_modules/@ckeditor/ckeditor5-block-quote/theme/blockquote.css) 6:0
Module parse failed: Unexpected token (6:0)
File was processed with these loaders:
 * ./node_modules/postcss-loader/dist/cjs.js
You may need an additional loader to handle the result of these loaders.
|  */
| 
> .ck-content blockquote {
|       /* See #12 */
|       overflow: hidden;

Are you seeing the same or have you managed to get this to run successfully?

I know Laravel Mix 6 requires Webpack 5 and PostCSS 8. Is anyone aware if CKEditor5s roadmap includes native support for those packages too as far as I can see it's recommended/locked to Webpack ^4.

@XGhozt
Copy link

XGhozt commented Feb 12, 2021

Sorry @icreatestuff -- after how much trouble it gave me I ended up just forking the main repo and compiling separately as a custom package in composer. Not as convenient but it compiles faster anyway. I didn't go any further than the above.

@MehdiAghighi
Copy link

MehdiAghighi commented Aug 29, 2021

has anybody find any solutions to this ?

i get this error

ERROR in ./node_modules/@ckeditor/ckeditor5-widget/theme/widgettypearound.css (./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[5].oneOf[1].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[5].oneOf[1].use[2]!./node_modules/style-loader/dist/cjs.js??ruleSet[1].rules[11].use[0]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[11].use[1]!./node_modules/@ckeditor/ckeditor5-widget/theme/widgettypearound.css)
Module build failed (from ./node_modules/postcss-loader/dist/cjs.js):
SyntaxError

(1:1) /path/to/file/node_modules/@ckeditor/ckeditor5-widget/theme/widgettypearound.css Unknown word

> 1 | var api = require("!../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js");
    | ^
  2 |             var content = require("!!../../../postcss-loader/dist/cjs.js??ruleSet[1].rules[11].use[1]!./widgettypearound.css");
  3 | 

i am using laravel mix 6

@Kwaadpepper
Copy link

Same issue here, still a pain to make a custom build using laravel-mix

@gnsJhenJie
Copy link

gnsJhenJie commented Oct 5, 2021

Same issue here. @MehdiAghighi, have you found any solution?

@eele94
Copy link

eele94 commented Oct 11, 2021

bump

@hamza-topo
Copy link

@MehdiAghighi have the same issue , did you found a solution for that ?

@hamza-topo
Copy link

hamza-topo commented Nov 22, 2021

``@kanalumaddela , thank u for your answear , i follow what you have done in your webpack configuration, but it seems that the regex rules affect my other javascript files : so this my error log


production
mix --production

✖ Mix
Compiled with some errors in 2.24s

ERROR in ./resources/css/leaflet.css
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/laravel-mix/node_modules/postcss-loader/dist/cjs.js):
SyntaxError

(1:1) /var/www/html/resources/css/leaflet.css Unknown word

1 | var api = require("!../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js");
| ^
2 | var content = require("!!../../node_modules/postcss-loader/src/index.js??ruleSet[1].rules[12].use[1]!./leaflet.css");


my webpack config looks like that :
`
const mix = require('laravel-mix');

mix.options({
processCssUrls: false
});

const CKEditorWebpackPlugin = require('@ckeditor/ckeditor5-dev-webpack-plugin');
const styles = require('@ckeditor/ckeditor5-dev-utils').styles;
const CKERegex = {
svg: /ckeditor5-[^/\\]+[/\]theme[/\]icons[/\][^/\\]+.svg$/,
css: /ckeditor5-[^/\\]+[/\]theme[/\].+.css/,
font: /ckeditor5-[^/\\]+[/\]theme[/\]icons[/\][^/\\]+.svg$/
};
Mix.listen('configReady', webpackConfig => {
const rules = webpackConfig.module.rules;
const targetSVG = /(.(png|jpe?g|gif|webp)$|^((?!font).).svg$)/;
const targetFont = /(.(woff2?|ttf|eot|otf)$|font.
.svg$)/;
const targetCSS = /.css$/;

// exclude CKE regex from mix's default rules
// if there's a better way to loop/change this, open to suggestions
for (let rule of rules) {
if (rule.test.toString() === targetSVG.toString()) {
rule.exclude = CKERegex.svg;
}
else if (rule.test.toString() === targetFont.toString()) {
rule.exclude = CKERegex.svg;
}
else if (rule.test.toString() === targetCSS.toString()) {
rule.exclude = CKERegex.css;
}
}
});

mix.webpackConfig({
module: {
rules: [
{
test: CKERegex.svg,
use: [ 'raw-loader' ]
},
{
test: CKERegex.styles,
use: [
{
loader: 'style-loader',
options: {
injectType: 'singletonStyleTag',
attributes: {
'data-cke': true
}
}
},
{
loader: 'postcss-loader',
options: styles.getPostCssConfig( {
themeImporter: {
themePath: require.resolve( '@ckeditor/ckeditor5-theme-lark' )
},
minify: true
} )
}
]
},
]
}
});

//back resources
mix.js('resources/js/editor.js', 'public/js');
//resource css
mix.js('resources/js/back.js', 'public/js')
.js('resources/js/leaflet.js', 'public/js')
.postCss('resources/css/back.css', 'public/css', [
require('postcss-import'),
require('tailwindcss'),
])
.postCss('resources/css/leaflet.css', 'public/leaflet', [
require('postcss-import'),
require('tailwindcss'),
]);

if (mix.inProduction()) {
mix.version();
}
`

@fabiang
Copy link

fabiang commented May 5, 2022

I was able to make it work. The whole system with Laravel Mix and Webpack is pretty unstable, when one thing changes your whole config breaks.

You guys were missing two essential things in your config:

  1. css-loader needs to be added as loader for the CSS files -> triggers the "Unknown word" error when not
  2. the rules in Webpack were changed for CSS/Font/SVGs, so you'll make sure you adjust them according to the version you're using

webpack.mix.js:

const mix = require('laravel-mix');

const CKEditorWebpackPlugin = require('@ckeditor/ckeditor5-dev-webpack-plugin');
const {styles} = require('@ckeditor/ckeditor5-dev-utils');

// make sure you copy these two regexes from the CKEdidtor docs: 
// https://ckeditor.com/docs/ckeditor5/latest/installation/advanced/alternative-setups/integrating-from-source.html#webpack-configuration 
const CKERegex = {
  svg: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
  css: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css$/,
};

Mix.listen('configReady', webpackConfig => {
  const rules = webpackConfig.module.rules;

  // these change often! Make sure you copy the correct regexes for your Webpack version!
  const targetSVG = /(\.(png|jpe?g|gif|webp|avif)$|^((?!font).)*\.svg$)/;
  const targetFont = /(\.(woff2?|ttf|eot|otf)$|font.*\.svg$)/;
  const targetCSS = /\.p?css$/;

  // exclude CKE regex from mix's default rules
  for (let rule of rules) {
    // console.log(rule.test) // uncomment to check the CURRENT rules

    if (rule.test.toString() === targetSVG.toString()) {
      rule.exclude = CKERegex.svg;
    } else if (rule.test.toString() === targetFont.toString()) {
      rule.exclude = CKERegex.svg;
    } else if (rule.test.toString() === targetCSS.toString()) {
      rule.exclude = CKERegex.css;
    }
  }
});

mix.webpackConfig({
  plugins: [
    new CKEditorWebpackPlugin({
      language: 'en',
      addMainLanguageTranslationsToAllAssets: true
    })
  ],
  module: {
    rules: [
      {
        test: CKERegex.svg,
        use: ['raw-loader']
      },
      {
        test: CKERegex.css,
        use: [
          {
            loader: 'style-loader',
            options: {
              injectType: 'singletonStyleTag',
              attributes: {
                'data-cke': true
              }
            }
          },
          'css-loader', // ADDED
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: styles.getPostCssConfig({ // moved into option `postcssOptions`
                themeImporter: {
                  themePath: require.resolve('@ckeditor/ckeditor5-theme-lark')
                },
                minify: true
              })
            }
          }
        ]
      }
    ]
  }
});

mix.setPublicPath('public')

mix.js('resources/js/app.js', 'public/js');
mix.sass('resources/css/app.scss', 'public/css', [
  //
]);

Versions I'm using:

  • CKEditor: 34.0.0
  • @ckeditor/ckeditor5-dev-utils & @ckeditor/ckeditor5-dev-webpack-plugin: 30.1.3
  • webpack: 5
  • webpack-cli: 4
  • postcss-loader: 4
  • raw-loader: 4
  • style-loader: 2
  • postcss: 8.4
  • resolve-url-loader: 5.0

@Reinmar Reinmar added resolution:resolved This issue was already resolved (e.g. by another ticket). and removed resolution:solved labels Jul 13, 2022
@cseahosan
Copy link

After struggling 8 Hrs.

const CKERegex = {
  svg: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
  css: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css$/
}

Mix.listen('configReady', webpackConfig => {
  const rules = webpackConfig.module.rules
  const targetSVG = /(\.(png|jpe?g|gif|webp|avif)$|^((?!font).)*\.svg$)/
  const targetFont = /(\.(woff2?|ttf|eot|otf)$|font.*\.svg$)/
  const targetCSS = /\.p?css$/

  // Exclude CK Editor regex from mix's default rules
  for (let rule of rules) {
    // console.log(rule.test.toString())
    if (rule.test.toString() === targetSVG.toString()) {
      // console.log(1, rule.test.toString())
      rule.exclude = CKERegex.svg
    } else if (rule.test.toString() === targetFont.toString()) {
      // console.log(2, rule.test.toString())
      rule.exclude = CKERegex.svg
    } else if (rule.test.toString() === targetCSS.toString()) {
      // console.log(3, rule.test.toString())
      rule.exclude = CKERegex.css
    }
  }
})

webpack: https://gist.github.com/cseahosan/5acf1213e35fbe72daf4ba97df8d2b49

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
resolution:resolved This issue was already resolved (e.g. by another ticket).
Projects
None yet
Development

No branches or pull requests