ckeditor / ckeditor5

Powerful rich text editor framework with a modular architecture, modern integrations, and features like collaborative editing.
https://ckeditor.com/ckeditor-5
Other
9.58k stars 3.7k forks source link

Cannot build from source on Rails & Webpacker #1723

Closed robypez closed 5 years ago

robypez commented 5 years ago

I don't know is this is the right repo, but I follow these instruction and I have some errors

CKEditor Advanced Setup

I'm under Rails & Webpacker 4 This is my environment.js

const { environment } = require('@rails/webpacker')
const erb =  require('./loaders/erb')
const { VueLoaderPlugin } = require('vue-loader')
const vue = require('./loaders/vue')
const datatables = require('./loaders/datatables')
const ckeditorSVG = require('./loaders/ckeditor-svg')
const ckeditorCSS = require('./loaders/ckeditor-css')
const webpack = require('webpack')
const CKEditorWebpackPlugin = require( '@ckeditor/ckeditor5-dev-webpack-plugin' )
const log = require('webpack-log')
const logger = log({ name: 'wds' })

environment.loaders.append('datatables', datatables)

environment.plugins.append('Provide', new webpack.ProvidePlugin({
  $: "jquery",
  jQuery: "jquery",
  "window.jQuery": "jquery",
  "window.$": "jquery",
  Popper: ['popper.js', 'default']
}));

environment.plugins.prepend('CKEditor',new CKEditorWebpackPlugin({
  language: 'it'
  })
)

environment.loaders.prepend('erb', erb)
environment.plugins.append('VueLoaderPlugin', new VueLoaderPlugin())
environment.loaders.prepend('vue', vue)
environment.loaders.append('ckeditorCSS', ckeditorCSS)
environment.loaders.append('ckeditorSVG', ckeditorSVG)

logger.info(environment.loaders);

module.exports = environment

I create two loader for svg and css

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

module.exports = {
  test: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/,
  use: [
      {
          loader: 'style-loader',
          options: {
              singleton: true
          }
      },
      {
          loader: 'postcss-loader',
          options: styles.getPostCssConfig( {
              themeImporter: {
                  themePath: require.resolve( '@ckeditor/ckeditor5-theme-lark' )
              },
              minify: true
          } )
      },
  ]
}

and

 module.exports = {
  test: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
  use: [ 'raw-loader' ]
}

I append the loader in my config

environment.loaders.append('ckeditorCSS', ckeditorCSS)
environment.loaders.append('ckeditorSVG', ckeditorSVG)

I log the environment

20:57:07 webpacker.1 | ℹ 「wds」:  ConfigList [
20:57:07 webpacker.1 |   { key: 'vue', value: { test: /\.vue(\.erb)?$/, use: [Array] } },
20:57:07 webpacker.1 |   { key: 'erb',
20:57:07 webpacker.1 |     value:
20:57:07 webpacker.1 |      { test: /\.erb$/,
20:57:07 webpacker.1 |        enforce: 'pre',
20:57:07 webpacker.1 |        exclude: /node_modules/,
20:57:07 webpacker.1 |        use: [Array] } },
20:57:07 webpacker.1 |   { key: 'file',
20:57:07 webpacker.1 |     value:
20:57:07 webpacker.1 |      { test:
20:57:07 webpacker.1 |         /(.jpg|.jpeg|.png|.gif|.tiff|.ico|.svg|.eot|.otf|.ttf|.woff|.woff2)$/i,
20:57:07 webpacker.1 |        use: [Array] } },
20:57:07 webpacker.1 |   { key: 'css',
20:57:07 webpacker.1 |     value:
20:57:07 webpacker.1 |      { test: /\.(css)$/i,
20:57:07 webpacker.1 |        use: [Array],
20:57:07 webpacker.1 |        sideEffects: true,
20:57:07 webpacker.1 |        exclude: /\.module\.[a-z]+$/ } },
20:57:07 webpacker.1 |   { key: 'sass',
20:57:07 webpacker.1 |     value:
20:57:07 webpacker.1 |      { test: /\.(scss|sass)$/i,
20:57:07 webpacker.1 |        use: [Array],
20:57:07 webpacker.1 |        sideEffects: true,
20:57:07 webpacker.1 |        exclude: /\.module\.[a-z]+$/ } },
20:57:07 webpacker.1 |   { key: 'moduleCss',
20:57:07 webpacker.1 |     value:
20:57:07 webpacker.1 |      { test: /\.(css)$/i,
20:57:07 webpacker.1 |        use: [Array],
20:57:07 webpacker.1 |        sideEffects: false,
20:57:07 webpacker.1 |        include: /\.module\.[a-z]+$/ } },
20:57:07 webpacker.1 |   { key: 'moduleSass',
20:57:07 webpacker.1 |     value:
20:57:07 webpacker.1 |      { test: /\.(scss|sass)$/i,
20:57:07 webpacker.1 |        use: [Array],
20:57:07 webpacker.1 |        sideEffects: false,
20:57:07 webpacker.1 |        include: /\.module\.[a-z]+$/ } },
20:57:07 webpacker.1 |   { key: 'nodeModules',
20:57:07 webpacker.1 |     value:
20:57:07 webpacker.1 |      { test: /\.(js|mjs)$/,
20:57:07 webpacker.1 |        include: /node_modules/,
20:57:07 webpacker.1 |        exclude: /@babel(?:\/|\\{1,2})runtime/,
20:57:07 webpacker.1 |        use: [Array] } },
20:57:07 webpacker.1 |   { key: 'babel',
20:57:07 webpacker.1 |     value:
20:57:07 webpacker.1 |      { test: /\.(js|jsx|mjs)?(\.erb)?$/,
20:57:07 webpacker.1 |        include: [Array],
20:57:07 webpacker.1 |        exclude: /node_modules/,
20:57:07 webpacker.1 |        use: [Array] } },
20:57:07 webpacker.1 |   { key: 'datatables',
20:57:07 webpacker.1 |     value:
20:57:07 webpacker.1 |      { test: /datatables\.net.*/,
20:57:07 webpacker.1 |        loader: 'imports-loader?define=>false' } },
20:57:07 webpacker.1 |   { key: 'ckeditorCSS',
20:57:07 webpacker.1 |     value:
20:57:07 webpacker.1 |      { test: /ckeditor5-[^\/\\]+[\/\\]theme[\/\\].+\.css/,
20:57:07 webpacker.1 |        use: [Array] } },
20:57:07 webpacker.1 |   { key: 'ckeditorSVG',
20:57:07 webpacker.1 |     value:
20:57:07 webpacker.1 |      { test:
20:57:07 webpacker.1 |         /ckeditor5-[^\/\\]+[\/\\]theme[\/\\]icons[\/\\][^\/\\]+\.svg$/,
20:57:07 webpacker.1 |        use: [Array] } } ]

It doesn't compile

20:57:16 webpacker.1 | ERROR in ./node_modules/@ckeditor/ckeditor5-ui/theme/components/panel/balloonpanel.css (./node_modules/css-loader/dist/cjs.js??ref--4-1!./node_modules/postcss-loader/src??ref--4-2!./node_modules/style-loader??ref--11-0!./node_modules/postcss-loader/src??ref--11-1!./node_modules/@ckeditor/ckeditor5-ui/theme/components/panel/balloonpanel.css)
20:57:16 webpacker.1 | Module build failed (from ./node_modules/postcss-loader/src/index.js):
20:57:16 webpacker.1 | SyntaxError
20:57:16 webpacker.1 |
20:57:16 webpacker.1 | (2:1) Unknown word
20:57:16 webpacker.1 |
20:57:16 webpacker.1 |   1 |
20:57:16 webpacker.1 | > 2 | var content = require("!!../../../../../postcss-loader/src/index.js??ref--11-1!./balloonpanel.css");
20:57:16 webpacker.1 |     | ^
20:57:16 webpacker.1 |   3 |
20:57:16 webpacker.1 |   4 | if(typeof content === 'string') content = [[module.id, content, '']];
20:57:16 webpacker.1 |
20:57:16 webpacker.1 |
20:57:16 webpacker.1 | ERROR in ./node_modules/@ckeditor/ckeditor5-ui/theme/components/button/button.css (./node_modules/css-loader/dist/cjs.js??ref--4-1!./node_modules/postcss-loader/src??ref--4-2!./node_modules/style-loader??ref--11-0!./node_modules/postcss-loader/src??ref--11-1!./node_modules/@ckeditor/ckeditor5-ui/theme/components/button/button.css)
20:57:16 webpacker.1 | Module build failed (from ./node_modules/postcss-loader/src/index.js):
20:57:16 webpacker.1 | SyntaxError
20:57:16 webpacker.1 |
20:57:16 webpacker.1 | (2:1) Unknown word
20:57:16 webpacker.1 |
20:57:16 webpacker.1 |   1 |
20:57:16 webpacker.1 | > 2 | var content = require("!!../../../../../postcss-loader/src/index.js??ref--11-1!./button.css");
20:57:16 webpacker.1 |     | ^
20:57:16 webpacker.1 |   3 |
20:57:16 webpacker.1 |   4 | if(typeof content === 'string') content = [[module.id, content, '']];
20:57:16 webpacker.1 |
20:57:16 webpacker.1 |
20:57:16 webpacker.1 | ERROR in ./node_modules/@ckeditor/ckeditor5-ui/theme/components/dropdown/dropdown.css (./node_modules/css-loader/dist/cjs.js??ref--4-1!./node_modules/postcss-loader/src??ref--4-2!./node_modules/style-loader??ref--11-0!./node_modules/postcss-loader/src??ref--11-1!./node_modules/@ckeditor/ckeditor5-ui/theme/components/dropdown/dropdown.css)
20:57:16 webpacker.1 | Module build failed (from ./node_modules/postcss-loader/src/index.js):
20:57:16 webpacker.1 | SyntaxError
20:57:16 webpacker.1 |
20:57:16 webpacker.1 | (2:1) Unknown word
20:57:16 webpacker.1 |
20:57:16 webpacker.1 |   1 |
20:57:16 webpacker.1 | > 2 | var content = require("!!../../../../../postcss-loader/src/index.js??ref--11-1!./dropdown.css");
20:57:16 webpacker.1 |     | ^
20:57:16 webpacker.1 |   3 |
20:57:16 webpacker.1 |   4 | if(typeof content === 'string') content = [[module.id, content, '']];
20:57:16 webpacker.1 |
20:57:16 webpacker.1 |
Mgsy commented 5 years ago

@ma2ciek, could you take a look at this one?

ma2ciek commented 5 years ago

Hi @robypez!

The error shows up because you use two loaders on the CKEditor 5 CSS files:

 { key: 'css',
20:57:07 webpacker.1 |     value:
20:57:07 webpacker.1 |      { test: /\.(css)$/i,
20:57:07 webpacker.1 |        use: [Array],
20:57:07 webpacker.1 |        sideEffects: true,
20:57:07 webpacker.1 |        exclude: /\.module\.[a-z]+$/ } },

{ key: 'ckeditorCSS',
20:57:07 webpacker.1 |     value:
20:57:07 webpacker.1 |      { test: /ckeditor5-[^\/\\]+[\/\\]theme[\/\\].+\.css/,
20:57:07 webpacker.1 |        use: [Array] } },

You should exclude the ckeditor5-* from the first loader.

robypez commented 5 years ago

Thank you @ma2ciek, I try (with the Rails wrapper is not so easy but I try)

robypez commented 5 years ago

@ma2ciek I'm not so skilled in regex, is correct to use

/ckeditor5-[^\/\\]+[\/\\]theme[\/\\].+\.css/|/\.module\.[a-z]+$/

to add the ckeditor regex test rule to the rails css loader exclude directive?

ma2ciek commented 5 years ago

I guess you can also pass an array of regexps here. It will be easier.

robypez commented 5 years ago

@ma2ciek

Now it compiles

I add

const cssLoader = environment.loaders.get('css');
cssLoader.exclude = /(\.module\.[a-z]+$)|(ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css)/

And the result is

14:52:43 webpacker.1 | ℹ 「wds」:  ConfigList [
14:52:43 webpacker.1 |   { key: 'vue', value: { test: /\.vue(\.erb)?$/, use: [Array] } },
14:52:43 webpacker.1 |   { key: 'erb',
14:52:43 webpacker.1 |     value:
14:52:43 webpacker.1 |      { test: /\.erb$/,
14:52:43 webpacker.1 |        enforce: 'pre',
14:52:43 webpacker.1 |        exclude: /node_modules/,
14:52:43 webpacker.1 |        use: [Array] } },
14:52:43 webpacker.1 |   { key: 'file',
14:52:43 webpacker.1 |     value:
14:52:43 webpacker.1 |      { test:
14:52:43 webpacker.1 |         /(.jpg|.jpeg|.png|.gif|.tiff|.ico|.svg|.eot|.otf|.ttf|.woff|.woff2)$/i,
14:52:43 webpacker.1 |        use: [Array] } },
14:52:43 webpacker.1 |   { key: 'css',
14:52:43 webpacker.1 |     value:
14:52:43 webpacker.1 |      { test: /\.(css)$/i,
14:52:43 webpacker.1 |        use: [Array],
14:52:43 webpacker.1 |        sideEffects: true,
14:52:43 webpacker.1 |        exclude:
14:52:43 webpacker.1 |         /(\.module\.[a-z]+$)|(ckeditor5-[^\/\\]+[\/\\]theme[\/\\].+\.css)/ } },
14:52:43 webpacker.1 |   { key: 'sass',
14:52:43 webpacker.1 |     value:
14:52:43 webpacker.1 |      { test: /\.(scss|sass)$/i,
14:52:43 webpacker.1 |        use: [Array],
14:52:43 webpacker.1 |        sideEffects: true,
14:52:43 webpacker.1 |        exclude: /\.module\.[a-z]+$/ } },
14:52:43 webpacker.1 |   { key: 'moduleCss',
14:52:43 webpacker.1 |     value:
14:52:43 webpacker.1 |      { test: /\.(css)$/i,
14:52:43 webpacker.1 |        use: [Array],
14:52:43 webpacker.1 |        sideEffects: false,
14:52:43 webpacker.1 |        include: /\.module\.[a-z]+$/ } },
14:52:43 webpacker.1 |   { key: 'moduleSass',
14:52:43 webpacker.1 |     value:
14:52:43 webpacker.1 |      { test: /\.(scss|sass)$/i,
14:52:43 webpacker.1 |        use: [Array],
14:52:43 webpacker.1 |        sideEffects: false,
14:52:43 webpacker.1 |        include: /\.module\.[a-z]+$/ } },
14:52:43 webpacker.1 |   { key: 'nodeModules',
14:52:43 webpacker.1 |     value:
14:52:43 webpacker.1 |      { test: /\.(js|mjs)$/,
14:52:43 webpacker.1 |        include: /node_modules/,
14:52:43 webpacker.1 |        exclude: /@babel(?:\/|\\{1,2})runtime/,
14:52:43 webpacker.1 |        use: [Array] } },
14:52:43 webpacker.1 |   { key: 'babel',
14:52:43 webpacker.1 |     value:
14:52:43 webpacker.1 |      { test: /\.(js|jsx|mjs)?(\.erb)?$/,
14:52:43 webpacker.1 |        include: [Array],
14:52:43 webpacker.1 |        exclude: /node_modules/,
14:52:43 webpacker.1 |        use: [Array] } },
14:52:43 webpacker.1 |   { key: 'datatables',
14:52:43 webpacker.1 |     value:
14:52:43 webpacker.1 |      { test: /datatables\.net.*/,
14:52:43 webpacker.1 |        loader: 'imports-loader?define=>false' } },
14:52:43 webpacker.1 |   { key: 'ckeditorCSS',
14:52:43 webpacker.1 |     value:
14:52:43 webpacker.1 |      { test: /ckeditor5-[^\/\\]+[\/\\]theme[\/\\].+\.css/,
14:52:43 webpacker.1 |        use: [Array] } },
14:52:43 webpacker.1 |   { key: 'ckeditorSVG',
14:52:43 webpacker.1 |     value:
14:52:43 webpacker.1 |      { test:
14:52:43 webpacker.1 |         /ckeditor5-[^\/\\]+[\/\\]theme[\/\\]icons[\/\\][^\/\\]+\.svg$/,
14:52:43 webpacker.1 |        use: [Array] } } ]

But when in my page

TypeError: Cannot read property 'getAttribute' of null
    at IconView._updateXMLContent (iconview.js:136)
    at IconView.render (iconview.js:109)
    at IconView.<anonymous> (observablemixin.js:262)
    at IconView.fire (emittermixin.js:242)
    at IconView.(anonymous function) [as render] (http://localhost:5000/packs/js/admin-b72d7f06c5de391440e0.js:91079:19)
    at ViewCollection.<anonymous> (viewcollection.js:92)
    at ViewCollection.fire (emittermixin.js:242)
    at ViewCollection.add (collection.js:174)
    at ButtonView.render (buttonview.js:205)
    at ButtonView.<anonymous> (observablemixin.js:262)

Maybe I'm using another loader for SVG and I have to exclude also the svg ckeditor path?

ma2ciek commented 5 years ago

Now it compiles

🎉

Maybe I'm using another loader for SVG and I have to exclude also the svg ckeditor path?

Yep, exactly.

robypez commented 5 years ago

@ma2ciek

If you want to improve the docs here is the config for Rails + Webpacker 4

create a file ckeditor-css.js

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

module.exports = {
  test: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/,
  use: [
      {
          loader: 'style-loader',
          options: {
              singleton: true
          }
      },
      {
          loader: 'postcss-loader',
          options: styles.getPostCssConfig( {
              themeImporter: {
                  themePath: require.resolve( '@ckeditor/ckeditor5-theme-lark' )
              },
              minify: true
          } )
      },
  ]
}

create a file ckeditor-svg.js

module.exports = {
  test: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
  use: [ 'raw-loader' ]
}

in environment.js

const ckeditorSVG = require('./loaders/ckeditor-svg')
const ckeditorCSS = require('./loaders/ckeditor-css')
const CKEditorWebpackPlugin = require( '@ckeditor/ckeditor5-dev-webpack-plugin' )

.....

environment.plugins.prepend('CKEditor',new CKEditorWebpackPlugin({
  language: 'it'
  })
)

environment.loaders.append('ckeditorCSS', ckeditorCSS)
environment.loaders.append('ckeditorSVG', ckeditorSVG)

const cssLoader = environment.loaders.get('css');
cssLoader.exclude = /(\.module\.[a-z]+$)|(ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css)/

const fileLoader = environment.loaders.get('file');
fileLoader.exclude = /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/
ma2ciek commented 5 years ago

Thanks for sharing it!

I don't know if we gonna add it to official docs, but somebody looking for such config will found it here now 😀

robypez commented 5 years ago

Maybe you need to specify that with Rails, laravel, etc you have to exclude CKeditor SVG and CSS from default loading rules...

ksouthworth commented 4 years ago

@ma2ciek

If you want to improve the docs here is the config for Rails + Webpacker 4

create a file ckeditor-css.js

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

module.exports = {
  test: /ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css/,
  use: [
      {
          loader: 'style-loader',
          options: {
              singleton: true
          }
      },
      {
          loader: 'postcss-loader',
          options: styles.getPostCssConfig( {
              themeImporter: {
                  themePath: require.resolve( '@ckeditor/ckeditor5-theme-lark' )
              },
              minify: true
          } )
      },
  ]
}

create a file ckeditor-svg.js

module.exports = {
  test: /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/,
  use: [ 'raw-loader' ]
}

in environment.js

const ckeditorSVG = require('./loaders/ckeditor-svg')
const ckeditorCSS = require('./loaders/ckeditor-css')
const CKEditorWebpackPlugin = require( '@ckeditor/ckeditor5-dev-webpack-plugin' )

.....

environment.plugins.prepend('CKEditor',new CKEditorWebpackPlugin({
  language: 'it'
  })
)

environment.loaders.append('ckeditorCSS', ckeditorCSS)
environment.loaders.append('ckeditorSVG', ckeditorSVG)

const cssLoader = environment.loaders.get('css');
cssLoader.exclude = /(\.module\.[a-z]+$)|(ckeditor5-[^/\\]+[/\\]theme[/\\].+\.css)/

const fileLoader = environment.loaders.get('file');
fileLoader.exclude = /ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/

@robypez THANK YOU! This helped immensely on a Rails 6 and Webpacker 5 project as well.

I just made one tweak to your ckeditor-css.js snippet to use injectType instead of the singleton option, which fixes a build error I was getting:

    {
      loader: "style-loader",
      options: {
        injectType: "singletonStyleTag",
      },
    },