ES6/Babel Class constructor cannot be invoked without 'new'
Asked Answered
K

3

8

I'm trying to create a custom Quill theme, extending the bubble one. I'm facing a strange ES6 inheritance problem, where it seems I cannot call super() in my constructor. Here is my code:

import BubbleTheme, { BubbleTooltip } from 'quill/themes/bubble'

class LoopTheme extends BubbleTheme {
  constructor (quill, options) {
    super(quill, options)
  }

  extendToolbar (toolbar) {
    super.extendToolbar(toolbar)
    this.tooltip = new LoopTooltip(this.quill, this.options.bounds);
    this.tooltip.root.appendChild(toolbar.container);
  }
}

class LoopTooltip extends BubbleTooltip {

}

LoopTooltip.TEMPLATE = [
  '<span class="ql-tooltip-arrow"></span>',
  '<div class="ql-tooltip-editor">',
    '<input type="text" data-formula="e=mc^2" data-link="https://myurl.com" data-video="Embed URL">',
    '<a class="ql-close"></a>',
  '</div>'
].join('');

export { LoopTooltip, LoopTheme as default }

Bubble theme could be found here

My Babel presets:

{
    "presets": [
        "es2015",
        "es2016",
        "stage-0",
        "react"
    ]
}

Webpack js file config:

  module: {
    rules: [
      {
        test: /\.js$/,
        include: [
          resolve(__dirname, 'app')
        ],
        loader: 'babel-loader',
        exclude: /node_modules/
      }, {...

Output generated code:

var LoopTheme = function (_BubbleTheme) {
  _inherits(LoopTheme, _BubbleTheme);

  function LoopTheme() {
    _classCallCheck(this, LoopTheme);

    return _possibleConstructorReturn(this, (LoopTheme.__proto__ || Object.getPrototypeOf(LoopTheme)).apply(this, arguments));
  }

  _createClass(LoopTheme, [{
    key: 'extendToolbar',
    value: function extendToolbar(toolbar) {
      _get(LoopTheme.prototype.__proto__ || Object.getPrototypeOf(LoopTheme.prototype), 'extendToolbar', this).call(this, toolbar);
      this.tooltip = new LoopTooltip(this.quill, this.options.bounds);
      this.tooltip.root.appendChild(toolbar.container);
    }
  }]);

  return LoopTheme;
}(_bubble2.default);

var LoopTooltip = function (_BubbleTooltip) {
  _inherits(LoopTooltip, _BubbleTooltip);

  function LoopTooltip() {
    _classCallCheck(this, LoopTooltip);

    return _possibleConstructorReturn(this, (LoopTooltip.__proto__ || Object.getPrototypeOf(LoopTooltip)).apply(this, arguments));
  }

  return LoopTooltip;
}(_bubble.BubbleTooltip);

LoopTooltip.TEMPLATE = ['<span class="ql-tooltip-arrow"></span>', '<div class="ql-tooltip-editor">', '<input type="text" data-formula="e=mc^2" data-link="myurl.com" data-video="Embed URL">', '<a class="ql-close"></a>', '</div>'].join('');

exports.LoopTooltip = LoopTooltip;
exports.default = LoopTheme;

I'm having the following error: events.js:59 Uncaught TypeError: Class constructor BubbleTheme cannot be invoked without 'new'. However, the LoopTheme is correctly called with new by Quill here. When I debug step by step, I correctly enter the LoopTheme constructor, and the error is raised when super is called.

Am I missing something here? I've always used inheritance, and I use it elsewhere in my code (between my classes), where here am I having trouble?

Thanks for your help

Khufu answered 19/6, 2017 at 8:41 Comment(11)
And where exactly these classes are used? Consider providing stackoverflow.com/help/mcve . A plunk that can replicate the issue would help.Gass
Please post here presets you're using. Mb complied code would be useful as well. Is this super(quill, options) line 19?Geoponic
Hi there, indeed, I added my babel presets and the output generated code. Would you need something more? I may try to add a jsbin/fiddle example? cc @estusKhufu
Is BubbleTheme transpiled as well?Danyelledanyette
Posting a plunk/fiddle or a repo that can replicate the problem will increase the chances to solve the problem.Gass
@Danyelledanyette I suppose so, github.com/quilljs/quill/blob/develop/themes/bubble.js uses es6 tooKhufu
past the snippet where you create the instance of the child class, something like: var foo = new Foo() because it seems you are missing the new operator and calling the class as a normal function var foo = Foo()Domesticate
@Domesticate may be not clear enough, but I already put a link to that call on Quill side : github.com/quilljs/quill/blob/develop/core/quill.js#L84 the new operator is present I've checked that too :(Khufu
@Khufu No, that it uses ES6 does not mean it is automatically transpiled. And actually the transpilation of the super(toolbar) call - that _get(…).call(this, toolbar); thing - does not use new, which appears to be the very problem.Danyelledanyette
@Danyelledanyette I don't understand why importing that ES6 Quill source code in my project to extend it won't be transpiled by webpack. I do it a lot with other libs, like emitter3 and stuff. Why would it be different for Quill ? I added part of my webpack config above. Thx$Khufu
I would suspect it has to do with the exclude: /node_modules/, but I have no idea about webpack.Danyelledanyette
B
14

I ran into the exact same issue while extending Quill’s BaseTheme.

As Bergi correctly pointed out in the comments above, this has to do with the fact that babel-loader isn’t transpiling Quill’s modules because they're inside node_modules/, which is excluded.

You can either update the exclude option in your Webpack config and use a regex to skip the node_modules/quill/ folder or use include instead:

{
  test: /\.js$/,
  loader: 'babel-loader',
  include: [
    path.join(__dirname, '../src'), // + any other paths that need to be transpiled
    /\/node_modules\/quill/,
  ]
}
Beitris answered 7/8, 2017 at 12:43 Comment(4)
Do you have any ideas to have the same behavior with angular-cli ?Concordat
Thanks Raphael that was that! Next problem is now svg assets required in ui/icons.. do you have a specific webpack loader need for that ones ? I tried to include them to my already existing ones but without any luck. ThanksKhufu
Yeah, you need to pass them through html-loader. The following lines worked for me: gist.github.com/raphaelsaunier/5e296aad093cdc5035827660f95b42bfBeitris
@Beitris thanks a bunch. I also found the Quill documentation explaining how to integrate it into your webpack assets pipeline. Your answer + that worked like a charm! Merci :)Khufu
R
5

You can also replace this:

import BubbleTheme from 'quill/themes/bubble'

into this:

const BubbleTheme = Quill.import('themes/bubble')
Rorqual answered 10/6, 2018 at 14:0 Comment(1)
Thank you x1000! Worked for me.Swinger
W
0

I would like to suggest another way. In case you are not building quill in you pipe line, you could very well reference the runtime constructor above the extended class.

    import { sanitize } from 'quill/formats/link';

    let BlockEmbed = window['Quill'].import('blots/block/embed');

    export class MediaBlot extends BlockEmbed {
        ...
    }
Washedup answered 10/12, 2018 at 13:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.