Closed pixelpax closed 10 months ago
We ran into the same issue and were able to get around it by importing the embed blot from quill and setting the type of the block embed to that type. Also, had to set the class properties within the new class.
import EmbedBlot from 'quill';
let BlockEmbed: EmbedBlot = Quill.import('blots/block/embed');
class DividerBlot extends BlockEmbed {
static blotName = 'divider';
static tagName = 'hr';
}
Quill.register(DividerBlot);
@iblank I am facing the same issue. However, I am unable to import EmbedBlot from quill. I am getting the following error:
Module '"quill"' has no exported member 'EmbedBlot'.)
Can you please help. Thanks.
I had trouble with this, also.
The best I was able to do was work in (the more forgiving) ES6 when defining the CustomBlock:
// in some CustomBlock.js file:
import * as Quill from 'quill';
const BlockEmbed = Quill.import('blots/block/embed');
export class CustomBlock extends BlockEmbed {
// whatever you need your block to do
}
CustomBlock.blotName = 'custom';
CustomBlock.tagName = 'div';
export default CustomBlock;
And then use require()
on the TypeScript side:
// in some Editor.ts file:
// (these are the relevant parts of a larger file)
import * as Quill from 'quill';
const customBlockModule = require('path/to/CustomBlock');
Quill.register(customBlockModule.CustomBlock);
this.editor = new Quill(someElement, someOptions);
this.editor.insertEmbed(someIndex, 'custom');
Is it ideal? No.
Does it work? Yes.
But I like the approach @noomz found much better. (see below)
In my Angular 2 typescript environment,Quill.import()
return any
type which cannot be extended. So this is my approach:
import * as Quill from 'quill';
import * as Parchment from "parchment";
const QuillBlockEmbed = Quill.import('blots/block/embed');
class BlockEmbed extends Parchment.default.Embed {}
BlockEmbed.prototype = QuillBlockEmbed.prototype;
class Video extends BlockEmbed {
}
Thanks @noomz. I took several hours to figure out how to get Quill and Parchment working together in Typescript (Angular 2 env). Your approach saved the day. It would be much easer if parchment typescript definitions were inside quill ts definitions.
@noomz's solution helps my code to type check, but I get a runtime error from webpack when I use it:
Cannot assign to read only property 'prototype' of function 'class BlockEmbed extends __WEBPACK_IMPORTED_MODULE_4_parchment__["default"].Embed
I was able to appease the compiler and avoid the runtime errors by declaring the type of BlockEmbed as Parchment.default.Embed:
import * as Parchment from "parchment"
const BlockEmbed = Quill.import("blots/block/embed") as typeof Parchment.default.Embed;
class Foo extends BlockEmbed {
...
}
I had been using @noomz's approach ( https://github.com/quilljs/quill/issues/1233#issuecomment-288968965 ) - but ran into an error when reading in a saved delta:
ERROR TypeError: Cannot read property 'length' of undefined
(Which seemed to have something to do with the prototype
shenanigans.)
After switching to @splodingsocks' approach ( https://github.com/quilljs/quill/issues/1233#issuecomment-294973856 ) that error went away!
Is it related to tsconfig ? Below is mine:
{
"compilerOptions": {
"baseUrl": "",
"declaration": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": [
"es2015",
"dom"
],
"mapRoot": "./",
"module": "es2015",
"moduleResolution": "node",
"outDir": "../dist/out-tsc",
"sourceMap": true,
"target": "es5"
}
}
Try this:
import * as Quill from 'quill';
import * as Parchment from "parchment";
const Block = Quill.import('blots/block') as typeof Parchment.default.Block;
export class CustomBlockBlot extends Block {
static blotName: string = 'customBlock';
static tagName: string = 'span';
}
After 1.3.6
, the below code works fine:
import { Quill } from 'quill';
import Parchment from 'parchment';
const Block = Quill.import('blots/block') as typeof Parchment.Block;
export class CustomBlockBlot extends Block {
static blotName: string = 'customBlock';
static tagName: string = 'span';
}
I extended emded block as described above, but still getting an error
Error: [Parchment] Unable to create marker blot
what am I doing wrong?
import {Editor} from 'primeng/editor';
import * as Quill from 'quill';
import * as Parchment from 'parchment';
const Block = Quill.import('blots/block/embed');
class BlockEmbed extends Parchment.default.Embed {}
BlockEmbed.prototype = Block.prototype;
export class Variable extends BlockEmbed {
static blotName = 'marker';
static tagName = 'marker';
static create(value: any) {
console.log(value);
const node = (super.create(value) as any);
node.innerHTML = '<span contenteditable=false>' + value + '</span>';
node.setAttribute('contenteditable', false);
return node;
}
}
Variable.blotName = 'marker';
Variable.tagName = 'marker';
Quill.register('formats/marker', Variable);
@Component({
selector: 'manager',
templateUrl: './manager.component.html',
styleUrls: ['./manager.component.css']
})
export class ManagerComponent implements OnInit, AfterViewInit {
private quill: any;
@ViewChild(Editor) editorComponent: Editor;
ngOnInit() {}
// based on primeng github issue this how we can get references to quill
ngAfterViewInit() {
this.quill = this.editorComponent.quill;
}
variableSelected(event) {
// grubbing string variable from event
this.quill.insertEmbed(this.cursor.index || 0, 'marker', event.value);
}
}
Ok, I tried experimenting with your code in my own project and was able to reproduce the error you are getting. Try changing this:
import * as Quill from 'quill';
import * as Parchment from 'parchment';
const Block = Quill.import('blots/block/embed');
class BlockEmbed extends Parchment.default.Embed {}
BlockEmbed.prototype = Block.prototype;
to this:
declare var Quill: any;
const BlockEmbed = Quill.import('blots/block/embed');
@iblank Ian, I'm giving up to understand it.... Why does it work ?
It took a lot of trial and error for me to figure out too. This might not be exactly right but here goes...
Since Quill
is defined globally from the JS file, you can use it here. declare var Quill: any;
just let's typescript know that the variable is defined from outside of the scope of this file. Then your custom blot needs to extend BlockEmbed, so that is the only class you need to import from quill.
@iblank my respect to you, thanks a lot!
That's worked perfectly for me (and without Parchment)
`import * as QuillNamespace from 'quill';
const Quill: any = QuillNamespace; const BlockEmbed = Quill.import('blots/block/embed');
export class HorizontalRule extends BlockEmbed { }
HorizontalRule.blotName = 'divider'; HorizontalRule.tagName = 'hr';
Quill.register(HorizontalRule);`
put this code in the component or module you need, and then Quill will support "\
Source: StackOverFlow
v2.0.0-beta.2 provides TypeScript definitions.
@benbro Do you have any documentation? I couldn't find a description in the documentation https://quilljs.com/docs/guides/cloning-medium-with-parchment#tweets
Today, in 2024 with Quill V2, I am using this:
import { EmbedBlot } from 'parchment';
class Foo extends EmbedBlot {
...
}
this works as well
import Quill, { Parchment } from 'quill';
const EmbedBlot = Quill.import(
'blots/block/embed'
) as typeof Parchment.EmbedBlot;
I'd like to be able to extend native blots as seen in cloning medium w/ parchment. I am using angular2 with typescript, and typescript does not believe that
BlockEmbed
is a real constructor. Steps for ReproductionUsing the following code (pretty much directly from above tutorial): let BlockEmbed = Quill.import('blots/block/embed');
Expected behavior: I expected this to extend BlockEmbed blots.
Actual behavior: I get
TS2507: Type 'any' is not a constructor function type.
Version: 1.1.9