Laravel-mix: CKEditor 5 SVGs do not build properly

Created on 8 Jan 2018  路  14Comments  路  Source: JeffreyWay/laravel-mix

  • Laravel Mix Version: 1.7.2
  • Node Version: v8.9.4
  • NPM Version: 5.6.0
  • Yarn Version: 1.3.2
  • OS: Fedora release 27

Description:

I am attempting to use the new CKEditor 5 Framework with Mix. As described in the CKEditor Quick Start Guide I have imported CKEditor libs into app.js (and removed everything else) then I built the file. The results seem to show the SVGs are not loaded properly and the icons in the editor toolbar are missing.

https://screenshots.firefox.com/LEYu0SnGQVMaew0E/127.0.0.1

I also receive this error output in the console.

XML Parsing Error: not well-formed
Location: http://127.0.0.1:8000/
Line Number 1, Column 1:
127.0.0.1:8000:1:1

I then attempted to fix the svg loader issue with the webpack config recommended on the guide.

mix.js('resources/assets/js/app.js', 'public/js').webpackConfig({
  module: {
    rules: [{
      test: /ckeditor5-[^/]+\/theme\/icons\/[^/]+\.svg$/,

      use: ['raw-loader']

    }]
  }
});

It produces the same result. I also tried the full webpack config:

mix.js('resources/assets/js/app.js', 'public/js').webpackConfig({
  module: {
    rules: [{
      test: /ckeditor5-[^/]+\/theme\/icons\/[^/]+\.svg$/,

      use: ['raw-loader']

    }, {
      test: /ckeditor5-[^/]+\/theme\/[^/]+\.scss$/,

      use: [
        'style-loader',
        'css-loader',
        'sass-loader'
      ]
    }]
  }
});

But I get errors:

ERROR  Failed to compile with 1 errors                                                                                                                                                                    17:29:16

 error  in ./node_modules/@ckeditor/ckeditor5-editor-classic/theme/theme.scss

Module build failed: 
// Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
^
      Invalid CSS after "...load the styles": expected 1 selector or at-rule, was "var content = requi"
      in /home/ryan/Sites/ckeditortesting/node_modules/@ckeditor/ckeditor5-editor-classic/theme/theme.scss (line 1, column 1)

 @ ./node_modules/@ckeditor/ckeditor5-editor-classic/theme/theme.scss 4:14-198
 @ ./node_modules/@ckeditor/ckeditor5-editor-classic/src/classiceditor.js
 @ ./resources/assets/js/app.js
 @ multi ./resources/assets/js/app.js

Here is the app.js

// app.js
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [ Essentials, Paragraph, Bold, Italic ],
        toolbar: [ 'bold', 'italic' ]
    } )
    .then( editor => {
        console.log( 'Editor was initialized', editor );
    } )
    .catch( error => {
        console.error( error.stack );
    } );

Without the custom webpack configurations mix says the SVGs are exported. I'm not sure where they are being exported.

 DONE  Compiled successfully in 2812ms                                                                                                                                                                     17:39:08

                                                                                                Asset       Size  Chunks                    Chunk Names
          fonts/vendor/@ckeditor/ckeditor5-undo/theme/icons/undo.svg?2753736cbcf3b2effb8d48c0814062a9  233 bytes          [emitted]         
          fonts/vendor/@ckeditor/ckeditor5-undo/theme/icons/redo.svg?8ea320f1905146e40376ea5ff82ef1c8  234 bytes          [emitted]         
  fonts/vendor/@ckeditor/ckeditor5-basic-styles/theme/icons/bold.svg?436104cc4191810a16da276b12d62720    1.14 kB          [emitted]         
fonts/vendor/@ckeditor/ckeditor5-basic-styles/theme/icons/italic.svg?42697e1fe4701d27b907ce418d5266dc  663 bytes          [emitted]         
                                                                                           /js/app.js    1.97 MB       0  [emitted]  [big]  /js/app
Done in 4.47s.

Steps To Reproduce:

  1. Create a new Laravel Project
  2. Add CKEditor via yarn/npm
yarn && yarn add \@ckeditor/ckeditor5-editor-classic \
    @ckeditor/ckeditor5-essentials \
    @ckeditor/ckeditor5-paragraph \
    @ckeditor/ckeditor5-basic-styles
  1. Add the previous app.js and build the js with yarn dev
  2. Set the welcome.blade.php file to the following:
<!doctype html>
<html lang="{{ app()->getLocale() }}">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <title>Laravel</title>

  <!-- Fonts -->
  <link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css">
</head>

<body>
  <div id="editor">
    <p>Editor content goes here.</p>
  </div>

  <script src="js/app.js"></script>
</body>

</html>
  1. Load the project homepage.
stale

Most helpful comment

Here's how i ended up overriding the default laravel-mix to correctly compile CKEditor5 without modifying it

  • Removed all --config=node_modules/laravel-mix/setup/webpack.config.js in package.json scripts
  • Then imported laravel-mix default config and override in webpack.config.js
const defaultConfig = require('laravel-mix/setup/webpack.config.js')
const { styles } = require('@ckeditor/ckeditor5-dev-utils')

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

defaultConfig.module.rules.map(rule => {
  for (let key in ckeditor5_pattern) {
    if (`test.${key}`.match(rule.test)) {
      if (rule.exclude) {
        if (rule.exclude instanceof Array)
          rule.exclude.push(ckeditor5_pattern[key])
        else
          rule.exclude = [rule.exclude, ckeditor5_pattern[key]]
      } else
        rule.exclude = ckeditor5_pattern[key]
    }
  }

  return rule
})

const rules = [
  {
    test: ckeditor5_pattern['svg'],
    use: [ 'raw-loader' ]
  },
  {
    test: ckeditor5_pattern['css'],
    use: [
      {
        loader: 'style-loader',
        options: {
          singleton: true
        }
      },
      {
        loader: 'postcss-loader',
        options: styles.getPostCssConfig( {
          themeImporter: {
            themePath: require.resolve('@ckeditor/ckeditor5-theme-lark')
          },
          minify: true
        } )
      },
    ]
  }
]

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

module.exports = defaultConfig

All 14 comments

any news?

maybe that is fixed with the changed behavior as of v2.0 see #1367

I am having this exact problem.

I have tried both senario 1 and senario 2 from this guide https://docs.ckeditor.com/ckeditor5/latest/builds/guides/integration/advanced-setup.html

Also just tried it again using laravel-mix v2.0 and still see the same behavior for both senarios.

With a clean install of react they both worked without problems.

This must be the 20% use case. Darn!

I will give v2 a try this weekend

v2 does not work... because laravel-mix use file-loader for SVG. And this can not be overridden.

Yeah no 2.0 doesn't work

I can see that #1466 may solve this issue soon (馃), but in the meantime, I wrote a comment in https://github.com/ckeditor/ckeditor5/issues/987#issuecomment-383501672 on how to integrate CKEditor 5 into a Laravel app.

@Reinmar I look forward to trying it.

@Reinmar #1466 will not be merged. It was written before @JeffreyWay changed laravel-mix to be plugin-based and the code conflicts with the new concept. I'm gonna close #1466 now.

Here's how i ended up overriding the default laravel-mix to correctly compile CKEditor5 without modifying it

  • Removed all --config=node_modules/laravel-mix/setup/webpack.config.js in package.json scripts
  • Then imported laravel-mix default config and override in webpack.config.js
const defaultConfig = require('laravel-mix/setup/webpack.config.js')
const { styles } = require('@ckeditor/ckeditor5-dev-utils')

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

defaultConfig.module.rules.map(rule => {
  for (let key in ckeditor5_pattern) {
    if (`test.${key}`.match(rule.test)) {
      if (rule.exclude) {
        if (rule.exclude instanceof Array)
          rule.exclude.push(ckeditor5_pattern[key])
        else
          rule.exclude = [rule.exclude, ckeditor5_pattern[key]]
      } else
        rule.exclude = ckeditor5_pattern[key]
    }
  }

  return rule
})

const rules = [
  {
    test: ckeditor5_pattern['svg'],
    use: [ 'raw-loader' ]
  },
  {
    test: ckeditor5_pattern['css'],
    use: [
      {
        loader: 'style-loader',
        options: {
          singleton: true
        }
      },
      {
        loader: 'postcss-loader',
        options: styles.getPostCssConfig( {
          themeImporter: {
            themePath: require.resolve('@ckeditor/ckeditor5-theme-lark')
          },
          minify: true
        } )
      },
    ]
  }
]

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

module.exports = defaultConfig

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

If the above solution does not work for you see: https://github.com/ckeditor/ckeditor5-vue/issues/23#issuecomment-455756667 (plus the following comment) which uses Mix.listen() and Mix.webpackConfig() and a different regex.

Here's how i ended up overriding the default laravel-mix to correctly compile CKEditor5 without modifying it

  • Removed all --config=node_modules/laravel-mix/setup/webpack.config.js in package.json scripts
  • Then imported laravel-mix default config and override in webpack.config.js
const defaultConfig = require('laravel-mix/setup/webpack.config.js')
const { styles } = require('@ckeditor/ckeditor5-dev-utils')

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

defaultConfig.module.rules.map(rule => {
  for (let key in ckeditor5_pattern) {
    if (`test.${key}`.match(rule.test)) {
      if (rule.exclude) {
        if (rule.exclude instanceof Array)
          rule.exclude.push(ckeditor5_pattern[key])
        else
          rule.exclude = [rule.exclude, ckeditor5_pattern[key]]
      } else
        rule.exclude = ckeditor5_pattern[key]
    }
  }

  return rule
})

const rules = [
  {
    test: ckeditor5_pattern['svg'],
    use: [ 'raw-loader' ]
  },
  {
    test: ckeditor5_pattern['css'],
    use: [
      {
        loader: 'style-loader',
        options: {
          singleton: true
        }
      },
      {
        loader: 'postcss-loader',
        options: styles.getPostCssConfig( {
          themeImporter: {
            themePath: require.resolve('@ckeditor/ckeditor5-theme-lark')
          },
          minify: true
        } )
      },
    ]
  }
]

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

module.exports = defaultConfig

@hanreev thank you a lot! )

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sdebacker picture sdebacker  路  3Comments

wendt88 picture wendt88  路  3Comments

hasnatbabur picture hasnatbabur  路  3Comments

mementoneli picture mementoneli  路  3Comments

RomainGoncalves picture RomainGoncalves  路  3Comments