codex-team / editor.js

A block-style editor with clean JSON output
https://editorjs.io
Apache License 2.0
28.52k stars 2.08k forks source link

JSON to back to html, How? #676

Closed linuxtrader closed 3 years ago

linuxtrader commented 5 years ago

So cool that it outputs clean data... Then how do I convert this clean data to html, so I can, as you say, use it it in a web page?

Thanks!

mu-yu commented 5 years ago

we need a readOnly init option but the editor.js doesn't provide.

roennow commented 5 years ago

https://github.com/editor-js/editorjs-php

neSpecc commented 5 years ago

Rendering an Editor.js JSON is a trivial and specific task, that depends on plugins and technologies you use.

For example

{
    "time" : 1550476186479,
    "blocks" : [
        {
            "type" : "paragraph",
            "data" : {
                "text" : "The example of text that was written in <b>one of popular</b> text editors."
            }
        },
        {
            "type" : "header",
            "data" : {
                "text" : "With the header of course",
                "level" : 2
            }
        },
        {
            "type" : "paragraph",
            "data" : {
                "text" : "So what do we have?"
            }
        }
    ],
    "version" : "2.8.1"
}

with the simplest for and switch turnes into

<p>
   The example of text that was written in <b>one of popular</b> text editors.
</p>
<h2>
   With the header of course
</h2>
<p>
   So what do we have?
</p>

We does not know a set of users plugins, so we can not provide a universal rendering tool. But the other side is a freedom of design — you can create any markup and logic you need.

Some simple examples:

Nodejs + Twig

https://github.com/codex-team/codex.docs/blob/master/src/views/pages/page.twig#L36 https://github.com/codex-team/codex.docs/tree/master/src/views/pages/blocks

PHP

https://github.com/codex-team/codex/blob/master/www/application/classes/Controller/Articles/Index.php#L189 https://github.com/codex-team/codex/tree/master/www/application/views/templates/editor/plugins

neSpecc commented 5 years ago

@mu-yu

We thought about readOnly mode. It will come with next updates in this year.

The problem of using this method for rendering an articles is that some of complex plugins provide an UI that different between data filling and rendering. For example, Poll block — in Editor it is a set of inputs, but at article it is a dynamic module with the different UI. And there are some other created tools with similar behaviour. We will search a solution.

rolfo85 commented 5 years ago

https://github.com/editor-js/editorjs-php

Excuse me, I'm super ignorant, but I installed the PHP plugin you mentioned, cause I understood it was supposed to return raw HTML out of the JSON object. But it returns another JSON that is like the . So what is that for? Can I render regular HTML in a div with that PHP plugin?

I'm not understanding how can i just print the editor content in HTML format without having that JSON

Thanks!

roennow commented 5 years ago

Can I render regular HTML in a div with that PHP plugin?

Sorry I haven't looked at the code but the readme said it would output the block objects but apparently not. Guess this it not the case and the true purpose was lost in translation

rolfo85 commented 5 years ago

No worries. I started rendering the HTML manually

niiapa commented 5 years ago

I love this tool but also need raw HTML output. The work we do is a bit too dynamic for switch statements. Can't switch between all the html types... I mean you can, but it's cumbersome and finicky. Looking forward to the update.

ddimitrioglo commented 5 years ago

+1 to have something like readOnly or viewMode or even better to have toHtml() method which will allow to convert blocks into raw html.

sedgeek commented 5 years ago

maybe use contenteditable=false solve problem

this.editor = new EditorJS({
.
.
.
        onReady: () => {
          var elements = document.querySelectorAll('[contenteditable=true]')
          elements.forEach(element => {
            element.setAttribute('contenteditable' , false)
          });
        }
})

and simple css to hide toolbars

#codex-editor .ce-toolbar__plus{ 
     display: none; 
   } 

   #codex-editor .ce-toolbar{ 
     display:none; 
   }

or document.getElementsByClassName('ce-toolbar')[0].style.display="none"

wotta commented 5 years ago

We also had this problem. Our solution is to transform the rendering on the server side.

Since we use Laravel we made a plugin that works with little configuration and is extendable. In case you are interested, I will gladly supply the link. (I won't self advertise it without an actual question to stay respectful for the codex team )

dsignr commented 5 years ago

There is a reason why many editors don't output these sort of JSONs and choose raw HTML instead. Because, to translate that JSON back to HTML, you're going to have to write a parser and that's just basically re-inventing the wheel when you could've started with HTML in the first place. The suggested approach is not worth the business case just to use a text editor - There are tons of HTML tags to switch case, and this is not even including the complex custom blocks that are possible (that for example we've developed). Eg. our plugin has a two column grid which it outputs, now I also need to write a complicated function to parse that, on top of writing the plugin itself. Otherwise, this is such a great idea and project.

For the moment, anyone seeking an alternative, look into this old, simple, well maintained project: https://madebymany.github.io/sir-trevor-js/

It's the same idea, but makes no assumptions about the format (JSON/HTML).

petarmitanoski commented 5 years ago

Hello, @wotta

We're having the same issue. Would you please share your solution with us?

wotta commented 5 years ago

Hello @petarmitanoski,

Hope this reaches you in time since I just woke up. We made a small package that handles the converting the default types that we have included so far. But all the converters that exists can be overwritten and new ones can be created.

Please see the following repository. If you have any questions please open a ticket and I will respond to it as quick as possible.

despeauxz commented 5 years ago

@wotta The package you suggested up there is just for PHP, supposedly, is there any made editor that can be used to convert the Object JSON blocks to raw HTML? Cos I'm working on a project which has been started with EditorJS and wouldn't want to resolve to another WYSIWYG editor? Really need a reply soonest. Thanks

wotta commented 5 years ago

@despeauxz Not really sure if I fully understand your question. The package I linked is to convert the data that we save from EditorJS to the database.

So we save the data from EditorJS to our backend which is saved in the database. But our presentation layer uses the above package to convert the saved data back to HTML.

We don't use a custom editor. I hope this is an answer to your question.

despeauxz commented 5 years ago

@wotta, Got your explanation. I'm currently not working on a PHP project, It's a Javascript/React Project. Could you suggest any package that transforms the data from the JSON block before hitting the database?

wotta commented 5 years ago

@despeauxz Sorry I don't know a package that does that. You could make your own package if you cannot find anything. ( or even anything that fits your needs )

You know the data structure which makes it pretty easy to convert it to HTML. I hope you find something that helps you.

wreiske commented 5 years ago

Just a rough example here how one could go about converting the JSON to HTML.

https://jsfiddle.net/wreiske/5Le9kwcv/

despeauxz commented 5 years ago

Thanks Williams, I already got my head around it. Thanks a lot❤

On Mon, Jul 22, 2019 at 7:08 PM William Reiske notifications@github.com wrote:

Just a rough example here how one could go about converting the JSON to HTML.

https://jsfiddle.net/wreiske/5Le9kwcv/

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/codex-team/editor.js/issues/676?email_source=notifications&email_token=AEATVS3E7DWG7KXW3CXBWB3QAXZTHA5CNFSM4HDKSBDKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2QWGXA#issuecomment-513893212, or mute the thread https://github.com/notifications/unsubscribe-auth/AEATVS5HNQCMRQRBDW7NRK3QAXZTHANCNFSM4HDKSBDA .

despeauxz commented 5 years ago

This might save someone, just want to drop this It converts the JSON blocks back to HTML

https://repl.it/@GodwinOnimisi/heloo

panpansh commented 5 years ago

Thanks to all 👍 here my needs (Header, Paragraph, Table, Checklist, Delimiter) https://github.com/panpansh/editorjs-json-to-html

wotta commented 5 years ago

@panpash I would make it a npm package :)

panpansh commented 5 years ago

@wotta now it's compatible with internet explorer but I have a question, did you have a editorjs.js IE compatible version or exist a polyfill ? Regards

wotta commented 5 years ago

To be honest, I am not sure. I installed editorjs as the docs state so I am not completely sure if it works in IE. ( I don't support IE at all normally )

tkaravou commented 5 years ago

If you don't care about the class names, you already have the html present for you: document.getElementById('editorjs').innerHTML

panpansh commented 5 years ago

@tkaravou , I don't load editorjs scripts and don't init editorjs on read-only view. just taking data and display it as html with some css from editorjs/plugins. editorjs is an html helper for the writter, not the reader (in my opinion).

yaneony commented 5 years ago

Still no progress here?

kosson commented 4 years ago

Based on despeauxz solution presented at https://repl.it/@GodwinOnimisi/heloo, I have completed and fixed some issues and pushed it into the following: https://gist.github.com/kosson/270195dc0c099e5af246e9e11935b991

I have to mention that I use Handlebars for rendering engine.

The magic starts right after you get a reference to content: referenceObj.content.blocks.map(obj => { ... });

sumitvekariya commented 4 years ago

https://medium.com/@sumitvekariya7/editor-js-read-only-mode-in-angular-4f73192ed860

I have created readOnly view mode for angular using switchcase statement based on block type and I have used css classes given in editor.js iteslf, so It creates almost same user interface.

andrewebdev commented 4 years ago

On this topic. I do like the simplicity of EditorJS and don't think HTML output should be "baked in". What I've done in a project I'm working with now, is to create a "renderEngine" that I attach to my editor. When I load or save my content/data, it's done via this engine.

The engine itself is a Class that contains a static property and read and write method. Then, whenever data is loaded into, or saved from the editor, it passes through that renderEngine.

The reason I took this approach, is because we can easily create different "renderEngines". One might save data to localStorage, another might generate html and save it to a textarea etc.

Here is a simple example of my HTML engine generates html and puts it into a textarea. It can also load from the textarea again.

  class HTMLEngine {
    static get generators() {
      return {
        paragraph: (data) => `<p>${data.text}</p>`,

        header: (data) => `<h${data.level}>${data.text}</h${data.level}>`,

        list: (data) => {
          var tagname = data.style.charAt(0) + 'l';
          return `<${tagname}>${data.items.map(item => `<li>${item}</li>`)}</${tagname}>`;
        },
      };
    }

    read() {
      let doc = new DOMParser().parseFromString(inputEl.value, 'text/html');
      var dataTemplate = doc.querySelector('[editorjs-data]');
      if (dataTemplate) {
        if (dataTemplate.innerHTML.length > 2) return JSON.parse(dataTemplate.innerHTML);
      }
      return {};
    }

    write(blocks) {
      var outputStr = '';
      blocks.forEach((block) => { outputStr += this.renderBlock(block); });
      return outputStr;
    }

    renderBlock(block) {
      return HTMLEngine.generators[block.type](block.data) + '\n';
    }
  }

The main Idea with the Generators is that we can now create a library of specific generators, and we will later change our engine class to allow for specifying a list of generators, much the same way that EditorJS lets you specify tools.

alexanderhorner commented 4 years ago

Here's my solution for converting the blocks to html

foreach ($blocks as $block) {

  // paragraph
  if ($block['type'] == 'paragraph') {
    $return .= '<p>'.$block['data']['text']."</p>\n";
  }

  // header
  else if ($block['type'] == 'header') {
    $return .= '<h'.$block['data']['level'].'>'.$block['data']['text'].'</h'.$block['data']['level'].">\n";
  }

  // list
  else if ($block['type'] == 'list') {
    $listtag = ($block['data']['style'] == 'ordered') ? 'ol' : 'ul';
    $return .= '<'.$listtag.">\n";
    foreach ($block['data']['items'] as $itemtext) {
      $return .= "\t<li>".$itemtext."</li>\n";
    }
    $return .= '</'.$listtag.">\n";
  }

}
Murrengan commented 4 years ago

This is my solution for vue.js

fromEditorJStoVuejs.txt

pavittarx commented 4 years ago

I created this simple utility for parsing clean data to html, after going through these issues. I would love if anyone else wanted to use it. Use it in the browser or node, or simply extend it to suit your needs. https://github.com/pavittarx/editorjs-html

dquak commented 4 years ago

@pavittarx Amazing simple and great package! I'm using it in my react project! Thank you very much, definitely saved me few hours!

pavittarx commented 4 years ago

thanks @dquak , I'm glad to see it have been helpful to you. <3 I hope you have starred the repo already.

Also, if you do feel there is something missing, please do let me know.

osman0000 commented 4 years ago

Hello @pavittarx thanks for your package ;) Can you please tell me how to use it right ? I get the json data saved with editor.js from my db and I usi it like this : let html = edjsParser.parse($httpRequest.responseText);` But apparently this is not correct..

dquak commented 4 years ago

Hello @pavittarx thanks for your package ;) Can you please tell me how to use it right ?

I get the json data saved with editor.js from my db and I usi it like this :

let html = edjsParser.parse($httpRequest.responseText);`

But apparently this is not correct..

@osman0000 Are you sure your data is in JSON structure? If not try to ‘JSON.parse’ it before passing is to the parse function

osman0000 commented 4 years ago

Thanks for your reply @dquak ! I tried this : let html = edjsParser.parse(JSON.parse($httpRequest.responseText)); And I now I get this error : TypeError: transforms[block.type] is not a function

dquak commented 4 years ago

You can go deep to the package code, it’s a very simple one and self understanding.. From your error it seem like your blocks doesn’t have the right schema created by the editor JS of {blocks: [{ type:’header’, data:{} }]}

On Sat, 16 May 2020 at 17:48 osman0000 notifications@github.com wrote:

Thanks for your reply @dquak https://github.com/dquak ! I tried this : let html = edjsParser.parse(JSON.parse($httpRequest.responseText)); And I now I get this error : TypeError: transforms[block.type] is not a function

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/codex-team/editor.js/issues/676#issuecomment-629657590, or unsubscribe https://github.com/notifications/unsubscribe-auth/AC43P5LDNMTA7GI6PKL5UR3RR2RVXANCNFSM4HDKSBDA .

osman0000 commented 4 years ago

here is the datas that I saved : [{"type":"paragraph","data":{"text":some text."}},{"type":"paragraph","data":{"text":"more text."}},{"type":"paragraph","data":{"text":"more text."}}] I think I didn't save it right because there is no "{blocks" before the datas Thanks you, I'm going to correct the saving part and try again ;)

pavittarx commented 4 years ago

@osman0000 The problem here lies in the fact that, the parser function for block.type == paragraph has not been defined. So, the parser is clueless when you pass a block of type "paragraph".

If you see the docs, the supported block.types as of now are Header, Lists, Images, Delimeter. I haven't added to much parsing support since, you may want to vary the html markup of your blocks. But, there is support for adding your own parser functions.

So you would simply have to do this:

// define parser function for paragraph block
const paragraph = (data) => {
    return `<p> ${data.text} </p>`;
}

// pass it to the parser intializer function.
const edjsParser =  edjsHTML({ paragraph });

See: https://github.com/pavittarx/editorjs-html#extend-for-custom-blocks

I will add more descriptive errors and paragraph support. Let me know if you still face any problems, Thanks. <3

osman0000 commented 4 years ago

Hey @pavittarx thanks for your reply ! I'll try that ;)

osman0000 commented 4 years ago

I tried that :

const paragraph = (block) => {
    return `<p> ${block.data.text} </p>;
}

const edjsParser =  edjsHTML({ paragraph });
let html = edjsParser.paragraph($httpRequest.responseText);

console.log(html);

But I get this error : 'TypeError: edjsParser.paragraph is not a function'

pavittarx commented 4 years ago

@osman0000 There seems to be some issue with your data, please do pass in generated data as you get from the editorjs. The json gave me error when I tried to parse it. Also, if you have extracted the blocks portion from the generated data, do wrap it inside an object when passing it. It should be like, edjsParser.parse({ blocks }); or you can just pass the data as is as you get it from editorjs.

I have made this working example for you to have a look: https://repl.it/@pavittarx/editorjs-browser

Apologies:

It should be, since only data property is being passed.

let paragraph = (data)=>{
    return `<p> ${data.text}</p>`
}
osman0000 commented 4 years ago

Hello @pavittarx. Thanks for your reply, the way that I saved my data was wrong so I got some error but now everytging is ok ;) Everything works very fine ! Thanks a lot !

eurobob commented 4 years ago

This one is great for React

https://github.com/BomdiZane/EditorJS-React-Renderer

yogaaltariz commented 4 years ago

this is example for vue

https://codepen.io/yogaaltariz/pen/wvMqBNM

JunaidQadirB commented 4 years ago

Here's my solution for converting the blocks to html

foreach ($blocks as $block) {

  // paragraph
  if ($block['type'] == 'paragraph') {
    $return .= '<p>'.$block['data']['text']."</p>\n";
  }

  // header
  else if ($block['type'] == 'header') {
    $return .= '<h'.$block['data']['level'].'>'.$block['data']['text'].'</h'.$block['data']['level'].">\n";
  }

  // list
  else if ($block['type'] == 'list') {
    $listtag = ($block['data']['style'] == 'ordered') ? 'ol' : 'ul';
    $return .= '<'.$listtag.">\n";
    foreach ($block['data']['items'] as $itemtext) {
      $return .= "\t<li>".$itemtext."</li>\n";
    }
    $return .= '</'.$listtag.">\n";
  }

}

Based on this here's a trait

https://gist.github.com/JunaidQadirB/4df3c7daa5cb2ab40639df65e55ced80

miadabdi commented 4 years ago

I've created a package for this purpose. editorjs-parser It supports :

It also is configurable.