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
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/,
]
}
You can also replace this:
import BubbleTheme from 'quill/themes/bubble'
into this:
const BubbleTheme = Quill.import('themes/bubble')
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 {
...
}
Related
I would like to use annotate classes in my javascript project. I'm using webpack and everything looks working (project compiles) but annotated classes fails to execute.
function annotation(target) {
target.isAnnotated = true;
}
#annotation()
export class Template {
constructor(id, name, subject, type) {
this.id = id;
this.name = name;
this.subject = subject;
this.type = type;
this.message = '';
}
}
My webpack.config.js uses such configuration options:
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
plugins: [
["#babel/plugin-proposal-decorators", { "legacy": true }]
]
}
}
but while runing the code, I get the exception:
Cannot set property 'isAnnotated' of undefined
Either I can't properly create annotation function or there is something more I need to configure but based on this it should be working.
I have simple app wrote in ES6 for the training purpose. I want to use modules in this app, so I installed webpack and babel. Unfortunetaly, when I try to fire my method, I receive the error:
Uncaught ReferenceError: gas is not defined
at HTMLButtonElement.count (bundle.js:113)
So, 'gas' is my instance of the object.
Here are my files:
main.js
'use strict'
import Gas from "./gas";
const count = document.getElementById("gas-count");
const gas = new Gas();
count.addEventListener("click", gas.count);
gas.js
export default class Gas {
constructor() {
}
count() {
// code
}
printResult(result) {
// code
}
_isValid(dist, price, aver) {
// Code
}
};
Finally, here is my Webpack config:
module.exports = {
// Define entry point
entry: "./src/main.js",
// Define output point
output: {
path: __dirname + "/dist",
filename: "bundle.js"
},
module: {
loaders: [{
test: /\.js$/,
exclude: /(node_modules)/,
loader: "babel-loader",
query: {
presets: ["env"]
}
}]
}
};
I'd be really grateful if someone could give me a hint why it's not working. Thank you in advance.
I need to write a module that will be available on the window global.
I'm using es6 to create the module and every single class I define has it's own file.
I'm using webpack to babelify and bundle these classes.
The entry point of my module is also the file containing the global to be exposed.
I've tried every method to make this possibe, icluding:
expose-loader
import-loader
expoert-loader
output: library
black-magic :(
Example of code I've tried:
I want to get: window.MyMod
// mymod.js
export class MyMod {
constructor(aaa) {
this.aaa = aaa;
}
toString() {
return this.aaa;
}
}
// webpack.config
var entries = [
'./src/mymod.js'
];
module.exports = {
...,
module: {
loaders: [
{
test: require.resolve('./src/mymod.js'),
loader: 'expose?MyMod'
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015']
}
}
]
}
This only gets me an object MyMod on the window that contains MyMod as a constructor.
Any help will be appreciated.
You should combine export default class Foo with the library and libraryTarget settings in Webpack's config. Something like:
// src/Foo.js
export default class Foo { ... }
// webpack.config.json
{
"output": {
"library": "Foo",
"libraryTarget": "var"
}
}
You should be able to use the library as window.Foo once the bundle has been loaded.
This is basically the same issue as Exporting a class with Webpack and Babel not working , except that you have a named export instead of a default export. Your entry file should be
import {MyMod} from './mymod';
module.exports = MyMod;
or
module.exports = require('./mymod').MyMod;
If you don't want to do any of these and keep './src/mymod.js' as entry file, use a CommonJS export instead of an ES6 export in that file:
// mymod.js
exports.MyMod = class MyMod {
constructor(aaa) {
this.aaa = aaa;
}
toString() {
return this.aaa;
}
}
So i have this function. I am trying to get a new Test('selector', {}) from outside this js file, it comes undefined and i can't seem to figure out why.
Do i really need to attach it to the window object ?
Can someone explain this ?
TO mention it works from the same file.
let Test = ((window, document, undefined) => {
class test {
constructor(selector, options) {
this.selector = document.querySelector(selector);
this.options = options;
}
}
return test;
})(window, document);
This is my webpack config file:
module.exports = {
entry: './src/test.js',
module: {
loaders: [
{
test: /\.js?$/,
exclude: / (node_modules) /,
loader: 'babel-loader',
query: {
presets: ['es2015', 'stage-0']
}
}
]
},
output: {
path: __dirname + '/src',
filename: 'test.min.js'
}
}
I was clearly misunderstanding what webpack is doing. Webpack turns all your JavaScript files into modules that are not available in the global namespace. That's why we need to use require/import to load them in. In the above example the Test function was never loaded in and is not defined. The default scoping nature of JavaScript no longer exists.
I want to use the css-loader with the 'modules' option of webpack in a React application written in Typescript. This example was my starting point (they are using Babel, webpack and React).
webpack config
var webpack=require('webpack');
var path=require('path');
var ExtractTextPlugin=require("extract-text-webpack-plugin");
module.exports={
entry: ['./src/main.tsx'],
output: {
path: path.resolve(__dirname, "target"),
publicPath: "/assets/",
filename: 'bundle.js'
},
debug: true,
devtool: 'eval-source-map',
plugins: [
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin({minimize: true})
],
resolve: {
extensions: ['', '.jsx', '.ts', '.js', '.tsx', '.css', '.less']
},
module: {
loaders: [
{
test: /\.ts$/,
loader: 'ts-loader'
},
{
test: /\.tsx$/,
loader: 'react-hot!ts-loader'
}, {
test: /\.jsx$/,
exclude: /(node_modules|bower_components)/,
loader: "react-hot!babel-loader"
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: "babel-loader"
}, {
test: /\.css/,
exclude: /(node_modules|bower_components)/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader')
}
]
},
plugins: [
new ExtractTextPlugin("styles.css", {allChunks: true})
],
postcss: function() {
return [require("postcss-cssnext")()]
}
}
This is a React component I want to style with an accompanying CSS file:
import React = require('react');
import styles = require('../../../css/tree.css')
class Tree extends React.Component<{}, TreeState> {
...
render() {
var components = this.state.components
return (
<div>
<h3 className={styles.h3} >Components</h3>
<div id="tree" className="list-group">
...
</div>
</div>
)
}
}
export = Tree
tree.css
.h3{
color: red;
}
No matter what I'm doing (tried changing the import syntax, tried declaring the 'require' for ts-loader, described here, I always get:
Uncaught Error: Cannot find module "../../../css/tree.css"
at runtime and
error TS2307: Cannot find module '../../../css/tree.css'.
by the TS compiler. Whats happening? Seems to me that css-loader is not even emitting ICSS? Or is it ts-loader behaving wrong?
import has special meaning to TypeScript. It means that TypeScript will attempt to load and understand the thing being imported. The right way is to define require like you mentioned but then var instead of import:
var styles = require('../../../css/tree.css')`
Declare 'require' as per ts-loader documentation.
Use 'require' as generic with < any > type: require< any >("../../../css/tree.css").
*.d.ts file
declare var require: {
<T>(path: string): T;
(paths: string[], callback: (...modules: any[]) => void): void;
ensure: (paths: string[], callback: (require: <T>(path: string) => T) => void) => void;
};
*.tsx file with component
const styles = require<any>("../../../css/tree.css");
...
<h3 className={styles.h3}>Components</h3>
I know it was already answered, but I was struggling with it for a while before I realized I need to use generic type specification, without that I wasn't able to access content of CSS file. (I was getting error: Property 'h3' does not exists on type '{}'.)
I had similar problem.
For me, works import:
import '../../../css/tree.css';
Webpack change this like any other normal imports. It change it to
__webpack_require__(id)
One drawback is that you lost control on style variable.
You can use https://github.com/Quramy/typed-css-modules, which creates .d.ts files from CSS Modules .css files. Please see also https://github.com/css-modules/css-modules/issues/61#issuecomment-220684795
A bit late to game but you can create a file called tree.css.d.ts in the same folder as tree.css that has this line:
export const h3: string;
and still use the import statement import * as styles from ... and you will still getcode completion and compile time checking.
You can either manage these definition files manually or you could integrate typed-css-modules into your build pipeline (https://github.com/Quramy/typed-css-modules)