Skip to content

davidscottmills/goeditorjs

Repository files navigation

davidscottmills/goeditorjs

An extensible library that converts editor.js data into HTML or markdown.

test and build Coverage Status Go Report Card Documentation GitHub issues license GitHub go.mod Go version of a Go module

Installation

go get github.com/davidscottmills/goeditorjs

Usage

package main

import (
	"io/ioutil"
	"log"

	"github.com/davidscottmills/goeditorjs"
)

func main() {
	content, err := ioutil.ReadFile("editorjs_output.json")
	if err != nil {
		log.Fatal(err)
	}

	ejs := string(content)

    // HTML
    // Get the HTML engine
    htmlEngine := goeditorjs.NewHTMLEngine()
    // Register the handlers you wish to use
	htmlEngine.RegisterBlockHandlers(
		&goeditorjs.HeaderHandler{},
		&goeditorjs.ParagraphHandler{},
		&goeditorjs.ListHandler{},
		&goeditorjs.CodeBoxHandler{},
	)
    // Generate the html
	html, err := htmlEngine.GenerateHTML(ejs)
	if err != nil {
		log.Fatal(err)
    }

    // Do something with the html output. In this case, write it to a file.
	err = ioutil.WriteFile("editorjs.html", []byte(html), 0644)
	if err != nil {
		log.Fatal(err)
	}

    // Generate markdown and save it to a file
    // Get the markdown engine
	markdownEngine := goeditorjs.NewMarkdownEngine()
    // Register the handlers you wish to use
	markdownEngine.RegisterBlockHandlers(
		&goeditorjs.HeaderHandler{},
		&goeditorjs.ParagraphHandler{},
		&goeditorjs.ListHandler{},
		&goeditorjs.CodeBoxHandler{},
    )
    // Generate the markdown
	md, err := markdownEngine.GenerateMarkdown(ejs)
	if err != nil {
		log.Fatal(err)
	}

    // Do something with the md output. In this case, write it to a file.
	err = ioutil.WriteFile("editorjs.md", []byte(md), 0644)
	if err != nil {
		log.Fatal(err)
	}
}

Using a Custom Handler

You can create and use your own handler in either engine by implementing the required interface and registering it. This package provides two interfaces for handlers.

  • HTMLBlockHandler

    type HTMLBlockHandler interface {
        Type() string // Type returns the type the block handler supports as a string
        GenerateHTML(editorJSBlock EditorJSBlock) (string, error) // Return associated HTML
    }
  • MarkdownBlockHandler

    type MarkdownBlockHandler interface {
        Type() string // Type returns the type the block handler supports as a string
        GenerateMarkdown(editorJSBlock EditorJSBlock) (string, error) // Return associated markdown
    }

If you're only planning to use the HTMLEngine, then you only need to implement the HTMLBlockHandler interface. The same goes for markdown.

Once you've met the required interface, register the handler for use in the engine.

htmlEngine := goeditorjs.NewHTMLEngine()
// Register the handlers you wish to use
htmlEngine.RegisterBlockHandlers(
    &MyCustomBlockHandler{},
)

Below is an example of how the header handle is implemented.

package header

import (
	"encoding/json"
	"fmt"
)

// HeaderHandler is the default HeaderHandler for EditorJS HTML generation
type HeaderHandler struct {
    // Notice that you could put some configurable options in this struct and then use them in your handler
}

// Header represents header data from EditorJS
type Header struct {
	Text  string `json:"text"`
	Level int    `json:"level"`
}

func (*HeaderHandler) parse(editorJSBlock EditorJSBlock) (*Header, error) {
	header := &Header{}
	return header, json.Unmarshal(editorJSBlock.Data, header)
}

// Type "header"
func (*HeaderHandler) Type() string {
	return "header"
}

// GenerateHTML generates html for HeaderBlocks
func (h *HeaderHandler) GenerateHTML(editorJSBlock EditorJSBlock) (string, error) {
	header, err := h.parse(editorJSBlock)
	if err != nil {
		return "", err
	}

	return fmt.Sprintf("<h%d>%s</h%d>", header.Level, header.Text, header.Level), nil
}

// GenerateMarkdown generates markdown for HeaderBlocks
func (h *HeaderHandler) GenerateMarkdown(editorJSBlock EditorJSBlock) (string, error) {
	header, err := h.parse(editorJSBlock)
	if err != nil {
		return "", err
	}

	return fmt.Sprintf("%s %s", strings.Repeat("#", header.Level), header.Text), nil
}

TODO

  • Provide more handlers (table, etc.)