46

How do I convert Deltas to pure HTML? I'm using Quill as a rich text editor, but I'm not sure how I would display the existing Deltas in a HTML context. Creating multiple Quill instances wouldn't be reasonable, but I couldn't come up with anything better yet.

I did my research, and I didn't find any way to do this.

km6
  • 2,191
  • 2
  • 15
  • 18

18 Answers18

40

Not very elegant, but this is how I had to do it.

function quillGetHTML(inputDelta) {
    var tempCont = document.createElement("div");
    (new Quill(tempCont)).setContents(inputDelta);
    return tempCont.getElementsByClassName("ql-editor")[0].innerHTML;
}

Obviously this needs quill.js.

km6
  • 2,191
  • 2
  • 15
  • 18
33

I guess you want the HTML inside it. Its fairly simple.

quill.root.innerHTML
Talha
  • 1,546
  • 17
  • 15
20

If I've understood you correctly, there's a quill thread of discussion here, with the key information you're after.

I've quoted what should be of most value to you below:

Quill has always used Deltas as a more consistent and easier to use (no parsing) data structure. There's no reason for Quill to reimplement DOM APIs in addition to this. quill.root.innerHTML or document.querySelector(".ql-editor").innerHTML works just fine (quill.container.firstChild.innerHTML is a bit more brittle as it depends on child ordering) and the previous getHTML implementation did little more than this.

Remy
  • 822
  • 12
  • 18
13

Simple, solution is here: https://www.scalablepath.com/blog/using-quill-js-build-wysiwyg-editor-website/

The main code is:

console.log(quill.root.innerHTML);
11

This is a very common confusion when it comes to Quilljs. The thing is you should NOT retrieve your html just to display it. You should render and display your Quill container just the same way you do when it is an editor. This is one of the major advantages to Quilljs and the ONLY thing you need to do is:

$conf.readOnly = true;

This will remove the toolbar and make the content not editable.

Lejossan
  • 129
  • 1
  • 4
7

I have accomplished it in the backend using php. My input is json encoded delta and my output is the html string. here is the code , if it is of any help to you.This function is still to handle lists though and some other formats but you can always extend those in operate function.

function formatAnswer($answer){
    $formattedAnswer = '';
    $answer = json_decode($answer,true);
    foreach($answer['ops'] as $key=>$element){
        if(empty($element['insert']['image'])){
            $result = $element['insert'];
            if(!empty($element['attributes'])){
                foreach($element['attributes'] as $key=>$attribute){
                    $result = operate($result,$key,$attribute);
                }
            }
        }else{ 
            $image = $element['insert']['image'];
            // if you are getting the image as url
            if(strpos($image,'http://') !== false || strpos($image,'https://') !== false){
                $result = "<img src='".$image."' />";
            }else{
                //if the image is uploaded 
                //saving the image somewhere and replacing it with its url
                $imageUrl = getImageUrl($image);
                $result = "<img src='".$imageUrl."' />";
            }
        }
        $formattedAnswer = $formattedAnswer.$result;
    }
    return nl2br($formattedAnswer);
}

function operate($text,$ops,$attribute){
    $operatedText = null;
    switch($ops){
        case 'bold': 
        $operatedText = '<strong>'.$text.'</strong>';
        break;
        case 'italic':
        $operatedText = '<i>'.$text.'</i>';
        break;
        case 'strike':
        $operatedText = '<s>'.$text.'</s>';
        break;
        case 'underline':
        $operatedText = '<u>'.$text.'</u>';
        break;
        case 'link':
        $operatedText = '<a href="'.$attribute.'" target="blank">'.$text.'</a>';
        break;
        default:
        $operatedText = $text;
    }
    return $operatedText;
}
Ankush Tanwar
  • 239
  • 2
  • 4
6

Here's a full function using quill.root.innerHTML, as the others didn't quite cover the complete usage of it:

function quillGetHTML(inputDelta) {
        var tempQuill=new Quill(document.createElement("div"));
        tempQuill.setContents(inputDelta);
        return tempQuill.root.innerHTML;
    }

This is just a slight different variation of km6's answer.

starball
  • 20,030
  • 7
  • 43
  • 238
6

For Quill version 1.3.6, just use:

quill.root.innerHTML;
Fifi
  • 3,360
  • 2
  • 27
  • 53
  • 2
    I know this is the most simple way to get the html. The problem is, quill is using their own styling (i.e. ql-align-center to center the text). If we want to use the saved html in any environment, we have to add containment to this html. Something like this: `
    [the html result]
    ` so that no matter where anyone open the html, it will get the correct styling.
    – Firanto Jun 03 '20 at 19:41
3

quill.root.innerHTML on the quill object works perfectly.

 $scope.setTerm = function (form) {
                var contents = JSON.stringify(quill.root.innerHTML)
                $("#note").val(contents)
                $scope.main.submitFrm(form)
            }
agrim2936
  • 51
  • 3
3

I put together a node package to convert html or plain text to and from a Quill Delta.

My team used it to update our data model to include both Quill's Delta and HTML. This allows us to render on the client without an instance of Quill.

See node-quill-converter.

It features the following functions: - convertTextToDelta - convertHtmlToDelta - convertDeltaToHtml

Behind the scenes it uses an instance of JSDOM. This may make it best suited for migration scripts as performance has not been tested in a typical app request lifecycle.

Joel Colucci
  • 471
  • 4
  • 9
2

Try

console.log ( $('.ql-editor').html() );
2

Here is how I did it, for you Express folks. It seems to have worked very well in conjunction with express-sanitizer.

app.js

 import expressSanitizer from 'express-sanitizer'

 app.use(expressSanitizer())

 app.post('/route', async (req, res) => {
     const title = req.body.article.title
     const content = req.sanitize(req.body.article.content)
     // Do stuff with content
 })

new.ejs

 <head>
     <link href="https://cdn.quilljs.com/1.3.2/quill.snow.css" rel="stylesheet">
 </head>

 ...

 <form action="/route" method="POST">
     <input type="text" name="article[title]" placeholder="Enter Title">
     <div id="editor"></div>
     <input type="submit" onclick="return quillContents()" />
 </form>

 ...

 <script src="https://cdn.quilljs.com/1.3.2/quill.js"></script>
 <script>
     const quill = new Quill('#editor', {
         theme: 'snow'
     })

     const quillContents = () => {
         const form = document.forms[0]
         const editor = document.createElement('input')

         editor.type = 'hidden'
         editor.name = 'article[content]'
         editor.value = document.querySelector('.ql-editor').innerHTML
         form.appendChild(editor)

         return form.submit()
     }
</script>

express-sanitizer (https://www.npmjs.com/package/express-sanitizer)

document.forms (https://developer.mozilla.org/en-US/docs/Web/API/Document/forms)

My view only has one form, so I used document.forms[0], but if you have multiple or may extend your view in the future to have multiple forms, check out the MDN reference.

What we are doing here is creating a hidden form input that we assign the contents of the Quill Div, and then we bootleg the form submit and pass it through our function to finish it off.

Now, to test it, make a post with <script>alert()</script> in it, and you won't have to worry about injection exploits.

That's all there is to it.

agm1984
  • 15,500
  • 6
  • 89
  • 113
2

Here is a proper way to do it.

var QuillDeltaToHtmlConverter = require('quill-delta-to-html').QuillDeltaToHtmlConverter;

// TypeScript / ES6:
// import { QuillDeltaToHtmlConverter } from 'quill-delta-to-html'; 

var deltaOps =  [
    {insert: "Hello\n"},
    {insert: "This is colorful", attributes: {color: '#f00'}}
];

var cfg = {};

var converter = new QuillDeltaToHtmlConverter(deltaOps, cfg);

var html = converter.convert(); 

Refer https://github.com/nozer/quill-delta-to-html

NR Ganesh
  • 111
  • 5
1

For a jQuery-style solution that allows getting and setting the Quill value I am doing the following:

Quill.prototype.val = function(newVal) {
  if (newVal) {
    this.container.querySelector('.ql-editor').innerHTML = newVal;
  } else {
    return this.container.querySelector('.ql-editor').innerHTML;
  }
};


let editor = new Quill( ... );

//set the value    
editor.val('<h3>My new editor value</h3>');

//get the value
let theValue = editor.val();
Genesis
  • 8,038
  • 3
  • 21
  • 22
0

quill-render looks like it's what you want. From the docs:

var render = require('quill-render');
render([
    {
        "attributes": {
            "bold": true
        },
        "insert": "Hi mom"
    }
]);
// => '<b>Hi mom</b>'
  • 2
    Here's another: [quilljs-renderer](https://github.com/UmbraEngineering/quilljs-renderer). I really wish Quill had this functionality built in. Third party libraries might be fragile, if the specs for Delta change, for example. –  Sep 16 '16 at 04:22
  • 1
    I'd need something that doesn't need Node or anything, just vanillaJS. AFAIK Quill used to have it, but it was removed in v1.0. – km6 Sep 16 '16 at 19:55
  • By Node you mean NPM? –  Sep 21 '16 at 02:28
0

If you want to render quill using nodejs, there is a package quite simple based on jsdom, usefull to render backside (only one file & last update 18 days from now) render quill delta to html string on server

yo_0
  • 21
  • 5
  • 1
    Links to external resources are encouraged, but please add context around the link so your fellow users will have some idea what it is and why it’s there. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline. – pableiros Dec 10 '16 at 00:46
0

Just use this clean library to convert from delta from/to text/html

node-quill-converter

example:

const { convertDeltaToHtml } = require('node-quill-converter');

let html = convertDeltaToHtml(delta);

console.log(html) ; // '<p>hello, <strong>world</strong></p>'
LazerDance
  • 177
  • 1
  • 8
0

I'm simply using in this way in MVC razor view and with javascript:

var txtNotes = document.querySelector(".ql-editor").innerHTML;

and when it come back from database then:

<div id="notes-text" class="text-details">
            @Html.Raw(!string.IsNullOrEmpty(Model.Notes) ? Model.Notes.ReplaceLinks().Replace("\n", "<br />") : "(No call notes were added)")
        </div>
starball
  • 20,030
  • 7
  • 43
  • 238