├── .gitignore ├── go.mod ├── util.go ├── .github └── workflows │ ├── test.yaml │ └── coverage.yaml ├── util_test.go ├── go.sum ├── LICENSE ├── html.go ├── examples ├── main.go └── test.json ├── markdown.go ├── types.go ├── html_test.go ├── markdown_test.go ├── README.md ├── handlers.go └── handlers_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | examples/editorjs.* -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/davidscottmills/goeditorjs 2 | 3 | go 1.15 4 | 5 | require github.com/stretchr/testify v1.6.1 6 | -------------------------------------------------------------------------------- /util.go: -------------------------------------------------------------------------------- 1 | package goeditorjs 2 | 3 | import "encoding/json" 4 | 5 | // parseEditorJSON parses editorJS data 6 | func parseEditorJSON(editorJSData string) (*editorJS, error) { 7 | result := &editorJS{} 8 | err := json.Unmarshal([]byte(editorJSData), result) 9 | if err != nil { 10 | return nil, err 11 | } 12 | return result, err 13 | } 14 | -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | name: test and build 6 | jobs: 7 | test: 8 | strategy: 9 | matrix: 10 | go-version: [1.14.x, 1.15.x] 11 | os: [ubuntu-latest] 12 | runs-on: ${{ matrix.os }} 13 | steps: 14 | - name: Install Go 15 | uses: actions/setup-go@v2 16 | with: 17 | go-version: ${{ matrix.go-version }} 18 | - name: Checkout code 19 | uses: actions/checkout@v2 20 | - name: Test 21 | run: go test -v -race ./... -------------------------------------------------------------------------------- /util_test.go: -------------------------------------------------------------------------------- 1 | package goeditorjs 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func Test_parseEditorJSON(t *testing.T) { 10 | editorJSData := `{"time": 1607709186831,"blocks": [{"type": "header","data": {"text": "Heading 1","level": 1}}],"version": "2.19.1"}` 11 | editorJS, err := parseEditorJSON(editorJSData) 12 | require.NoError(t, err) 13 | require.Len(t, editorJS.Blocks, 1) 14 | } 15 | 16 | func Test_parseEditorJSON_Err_Empty(t *testing.T) { 17 | editorJSData := `` 18 | 19 | _, err := parseEditorJSON(editorJSData) 20 | require.Error(t, err) 21 | } 22 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | name: coverage 6 | jobs: 7 | coverage: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Install Go 11 | if: success() 12 | uses: actions/setup-go@v2 13 | with: 14 | go-version: 1.14.x 15 | - name: Checkout code 16 | uses: actions/checkout@v2 17 | - name: Calc coverage 18 | run: go test -v -covermode=count -coverprofile=coverage.out 19 | - name: Convert coverage to lcov 20 | uses: jandelgado/gcov2lcov-action@v1.0.0 21 | with: 22 | infile: coverage.out 23 | outfile: coverage.lcov 24 | - name: Coveralls 25 | uses: coverallsapp/github-action@v1.1.2 26 | with: 27 | github-token: ${{ secrets.github_token }} 28 | path-to-lcov: coverage.lcov -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 4 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 5 | github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= 6 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 7 | github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= 8 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 9 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 10 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 11 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 12 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 davidscottmills 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /html.go: -------------------------------------------------------------------------------- 1 | package goeditorjs 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // HTMLEngine is the engine that creates the HTML from EditorJS blocks 8 | type HTMLEngine struct { 9 | BlockHandlers map[string]HTMLBlockHandler 10 | } 11 | 12 | // HTMLBlockHandler is an interface for a plugable EditorJS HTML generator 13 | type HTMLBlockHandler interface { 14 | Type() string // Type returns the type the block handler supports as a string 15 | GenerateHTML(editorJSBlock EditorJSBlock) (string, error) 16 | } 17 | 18 | // NewHTMLEngine creates a new HTMLEngine 19 | func NewHTMLEngine() *HTMLEngine { 20 | bhs := make(map[string]HTMLBlockHandler) 21 | return &HTMLEngine{BlockHandlers: bhs} 22 | } 23 | 24 | // RegisterBlockHandlers registers or overrides a block handlers for blockType given by HTMLBlockHandler.Type() 25 | func (htmlEngine *HTMLEngine) RegisterBlockHandlers(handlers ...HTMLBlockHandler) { 26 | for _, bh := range handlers { 27 | htmlEngine.BlockHandlers[bh.Type()] = bh 28 | } 29 | } 30 | 31 | // GenerateHTML generates html from the editorJS using configured set of HTML handlers 32 | func (htmlEngine *HTMLEngine) GenerateHTML(editorJSData string) (string, error) { 33 | result := "" 34 | ejs, err := parseEditorJSON(editorJSData) 35 | if err != nil { 36 | return "", err 37 | } 38 | for _, block := range ejs.Blocks { 39 | if generator, ok := htmlEngine.BlockHandlers[block.Type]; ok { 40 | html, err := generator.GenerateHTML(block) 41 | if err != nil { 42 | return result, err 43 | } 44 | result += html 45 | } else { 46 | return "", fmt.Errorf("%w, Block Type: %s", ErrBlockHandlerNotFound, block.Type) 47 | } 48 | } 49 | 50 | return result, nil 51 | } 52 | -------------------------------------------------------------------------------- /examples/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io/ioutil" 5 | "log" 6 | 7 | "github.com/davidscottmills/goeditorjs" 8 | ) 9 | 10 | func main() { 11 | content, err := ioutil.ReadFile("test.json") 12 | if err != nil { 13 | log.Fatal(err) 14 | } 15 | 16 | ejs := string(content) 17 | 18 | // Generate HTML and save it to a file 19 | htmlEngine := goeditorjs.NewHTMLEngine() 20 | htmlEngine.RegisterBlockHandlers( 21 | &goeditorjs.HeaderHandler{}, 22 | &goeditorjs.ParagraphHandler{}, 23 | &goeditorjs.ListHandler{}, 24 | &goeditorjs.CodeBoxHandler{}, 25 | &goeditorjs.RawHTMLHandler{}, 26 | &goeditorjs.ImageHandler{Options: &goeditorjs.ImageHandlerOptions{ 27 | StretchClass: "imageStretched", 28 | BorderClass: "imageBorder", 29 | BackgroundClass: "imageBackground"}}, 30 | ) 31 | html, err := htmlEngine.GenerateHTML(ejs) 32 | if err != nil { 33 | log.Fatal(err) 34 | } 35 | 36 | err = ioutil.WriteFile("editorjs.html", []byte(html), 0644) 37 | if err != nil { 38 | log.Fatal(err) 39 | } 40 | 41 | // Generate markdown and save it to a file 42 | markdownEngine := goeditorjs.NewMarkdownEngine() 43 | markdownEngine.RegisterBlockHandlers( 44 | &goeditorjs.HeaderHandler{}, 45 | &goeditorjs.ParagraphHandler{}, 46 | &goeditorjs.ListHandler{}, 47 | &goeditorjs.CodeBoxHandler{}, 48 | &goeditorjs.RawHTMLHandler{}, 49 | &goeditorjs.ImageHandler{Options: &goeditorjs.ImageHandlerOptions{ 50 | StretchClass: "imageStretched", 51 | BorderClass: "imageBorder", 52 | BackgroundClass: "imageBackground"}}, 53 | ) 54 | md, err := markdownEngine.GenerateMarkdown(ejs) 55 | if err != nil { 56 | log.Fatal(err) 57 | } 58 | 59 | err = ioutil.WriteFile("editorjs.md", []byte(md), 0644) 60 | if err != nil { 61 | log.Fatal(err) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /markdown.go: -------------------------------------------------------------------------------- 1 | package goeditorjs 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | // MarkdownEngine is the engine that creates the HTML from EditorJS blocks 9 | type MarkdownEngine struct { 10 | BlockHandlers map[string]MarkdownBlockHandler 11 | } 12 | 13 | // MarkdownBlockHandler is an interface for a plugable EditorJS HTML generator 14 | type MarkdownBlockHandler interface { 15 | Type() string // Type returns the type the block handler supports as a string 16 | GenerateMarkdown(editorJSBlock EditorJSBlock) (string, error) 17 | } 18 | 19 | // NewMarkdownEngine creates a new MarkdownEngine 20 | func NewMarkdownEngine() *MarkdownEngine { 21 | bhs := make(map[string]MarkdownBlockHandler) 22 | return &MarkdownEngine{BlockHandlers: bhs} 23 | } 24 | 25 | // RegisterBlockHandlers registers or overrides a block handlers for blockType given by MarkdownBlockHandler.Type() 26 | func (markdownEngine *MarkdownEngine) RegisterBlockHandlers(handlers ...MarkdownBlockHandler) { 27 | for _, bh := range handlers { 28 | markdownEngine.BlockHandlers[bh.Type()] = bh 29 | } 30 | } 31 | 32 | // GenerateMarkdown generates markdown from the editorJS using configured set of markdown handlers 33 | func (markdownEngine *MarkdownEngine) GenerateMarkdown(editorJSData string) (string, error) { 34 | results := []string{} 35 | ejs, err := parseEditorJSON(editorJSData) 36 | if err != nil { 37 | return "", err 38 | } 39 | for _, block := range ejs.Blocks { 40 | if generator, ok := markdownEngine.BlockHandlers[block.Type]; ok { 41 | md, err := generator.GenerateMarkdown(block) 42 | if err != nil { 43 | return "", err 44 | } 45 | results = append(results, md) 46 | } else { 47 | return "", fmt.Errorf("%w, Block Type: %s", ErrBlockHandlerNotFound, block.Type) 48 | } 49 | } 50 | 51 | return strings.Join(results, "\n\n"), nil 52 | } 53 | -------------------------------------------------------------------------------- /types.go: -------------------------------------------------------------------------------- 1 | package goeditorjs 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | ) 7 | 8 | // editorJS rpresents the Editor JS data 9 | type editorJS struct { 10 | Blocks []EditorJSBlock `json:"blocks"` 11 | } 12 | 13 | // EditorJSBlock type 14 | type EditorJSBlock struct { 15 | Type string `json:"type"` 16 | // Data is the Data for an editorJS block in the form of RawMessage ([]byte). It is left up to the Handler to parse the Data field 17 | Data json.RawMessage `json:"data"` 18 | } 19 | 20 | var ( 21 | //ErrBlockHandlerNotFound is returned from GenerateHTML when the HTML engine doesn't have a registered handler 22 | //for that type and the HTMLEngine is set to return on errors. 23 | ErrBlockHandlerNotFound = errors.New("Handler not found for block type") 24 | ) 25 | 26 | // header represents header data from EditorJS 27 | type header struct { 28 | Text string `json:"text"` 29 | Level int `json:"level"` 30 | } 31 | 32 | // paragraph represents paragraph data from EditorJS 33 | type paragraph struct { 34 | Text string `json:"text"` 35 | Alignment string `json:"alignment"` 36 | } 37 | 38 | // list represents list data from EditorJS 39 | type list struct { 40 | Style string `json:"style"` 41 | Items []string `json:"items"` 42 | } 43 | 44 | // codeBox represents code box data from EditorJS 45 | type codeBox struct { 46 | Code string `json:"code"` 47 | Language string `json:"language"` 48 | } 49 | 50 | // raw represents raw html data from EditorJS 51 | type raw struct { 52 | HTML string `json:"html"` 53 | } 54 | 55 | // image represents image data from EditorJS 56 | type image struct { 57 | File file `json:"file"` 58 | Caption string `json:"caption"` 59 | WithBorder bool `json:"withBorder"` 60 | WithBackground bool `json:"withBackground"` 61 | Stretched bool `json:"stretched"` 62 | } 63 | 64 | type file struct { 65 | URL string `json:"url"` 66 | } 67 | -------------------------------------------------------------------------------- /html_test.go: -------------------------------------------------------------------------------- 1 | package goeditorjs_test 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | 7 | "github.com/davidscottmills/goeditorjs" 8 | "github.com/stretchr/testify/mock" 9 | "github.com/stretchr/testify/require" 10 | ) 11 | 12 | type mockHTMLBlockHandler struct { 13 | mock.Mock 14 | typeName string 15 | } 16 | 17 | func (m *mockHTMLBlockHandler) GenerateHTML(editorJSBlock goeditorjs.EditorJSBlock) (string, error) { 18 | args := m.Called(editorJSBlock) 19 | return args.String(0), args.Error(1) 20 | } 21 | 22 | func (m *mockHTMLBlockHandler) Type() string { 23 | return m.typeName 24 | } 25 | 26 | func Test_NewHTMLEngine(t *testing.T) { 27 | eng := goeditorjs.NewHTMLEngine() 28 | require.NotNil(t, eng) 29 | require.NotNil(t, eng.BlockHandlers) 30 | } 31 | 32 | func Test_HTMLEngine_RegisterBlockHandler(t *testing.T) { 33 | bh1 := &mockHTMLBlockHandler{typeName: "header"} 34 | bh2 := &mockHTMLBlockHandler{typeName: "list"} 35 | eng := &goeditorjs.HTMLEngine{BlockHandlers: make(map[string]goeditorjs.HTMLBlockHandler)} 36 | eng.RegisterBlockHandlers(bh1, bh2) 37 | require.Equal(t, eng.BlockHandlers["header"], bh1) 38 | require.Equal(t, eng.BlockHandlers["list"], bh2) 39 | } 40 | 41 | func Test_GenerateHTML_Returns_Parse_Err(t *testing.T) { 42 | eng := &goeditorjs.HTMLEngine{BlockHandlers: make(map[string]goeditorjs.HTMLBlockHandler)} 43 | _, err := eng.GenerateHTML(``) 44 | require.Error(t, err) 45 | } 46 | 47 | func Test_GenerateHTML_NoHandler_Should_Err(t *testing.T) { 48 | editorJSData := `{"time": 1607709186831,"blocks": [{"type": "header","data": {"text": "Heading 1","level": 1}}],"version": "2.19.1"}` 49 | eng := &goeditorjs.HTMLEngine{BlockHandlers: make(map[string]goeditorjs.HTMLBlockHandler)} 50 | _, err := eng.GenerateHTML(editorJSData) 51 | require.Error(t, err) 52 | require.True(t, errors.Is(err, goeditorjs.ErrBlockHandlerNotFound)) 53 | } 54 | 55 | func Test_GenerateHTML_Returns_Err_From_Handler(t *testing.T) { 56 | bh := &mockHTMLBlockHandler{} 57 | mockErr := errors.New("Mock Error") 58 | bh.On("GenerateHTML", mock.Anything).Return("", mockErr) 59 | editorJSData := `{"time": 1607709186831,"blocks": [{"type": "header","data": {"text": "Heading 1","level": 1}}],"version": "2.19.1"}` 60 | eng := &goeditorjs.HTMLEngine{BlockHandlers: make(map[string]goeditorjs.HTMLBlockHandler)} 61 | eng.BlockHandlers["header"] = bh 62 | _, err := eng.GenerateHTML(editorJSData) 63 | require.Error(t, err) 64 | require.Equal(t, mockErr, err) 65 | bh.AssertCalled(t, "GenerateHTML", mock.Anything) 66 | } 67 | 68 | func Test_GenerateHTML_Result_Includes_Handler_Result(t *testing.T) { 69 | bh := &mockHTMLBlockHandler{} 70 | handlerResult := "
%s
`, paragraph.Alignment, paragraph.Text), nil 66 | } 67 | 68 | return fmt.Sprintf(`%s
`, paragraph.Text), nil 69 | } 70 | 71 | // GenerateMarkdown generates markdown for ParagraphBlocks 72 | func (h *ParagraphHandler) GenerateMarkdown(editorJSBlock EditorJSBlock) (string, error) { 73 | paragraph, err := h.parse(editorJSBlock) 74 | if err != nil { 75 | return "", err 76 | } 77 | 78 | if paragraph.Alignment != "left" { 79 | // Native markdown doesn't support alignment, so we'll use html instead. 80 | return fmt.Sprintf(`%s
`, paragraph.Alignment, paragraph.Text), nil 81 | } 82 | 83 | return paragraph.Text, nil 84 | } 85 | 86 | // ListHandler is the default ListHandler for EditorJS HTML generation 87 | type ListHandler struct{} 88 | 89 | func (*ListHandler) parse(editorJSBlock EditorJSBlock) (*list, error) { 90 | list := &list{} 91 | return list, json.Unmarshal(editorJSBlock.Data, list) 92 | } 93 | 94 | // Type "list" 95 | func (*ListHandler) Type() string { 96 | return "list" 97 | } 98 | 99 | // GenerateHTML generates html for ListBlocks 100 | func (h *ListHandler) GenerateHTML(editorJSBlock EditorJSBlock) (string, error) { 101 | list, err := h.parse(editorJSBlock) 102 | if err != nil { 103 | return "", err 104 | } 105 | 106 | result := "" 107 | if list.Style == "ordered" { 108 | result = "%s`, codeBox.Language, codeBox.Code), nil
164 | }
165 |
166 | // GenerateMarkdown generates markdown for CodeBoxBlocks
167 | func (h *CodeBoxHandler) GenerateMarkdown(editorJSBlock EditorJSBlock) (string, error) {
168 | codeBox, err := h.parse(editorJSBlock)
169 | if err != nil {
170 | return "", err
171 | }
172 |
173 | codeBox.Code = strings.ReplaceAll(codeBox.Code, "paragraph
", html) 89 | } 90 | 91 | func Test_ParagraphHandler_GenerateHTML_Center_Right(t *testing.T) { 92 | bph := &goeditorjs.ParagraphHandler{} 93 | testData := []struct { 94 | alignment string 95 | data string 96 | }{ 97 | {alignment: "center", data: `{"text": "paragraph","alignment": "center"}`}, 98 | {alignment: "right", data: `{"text": "paragraph","alignment": "right"}`}, 99 | } 100 | 101 | for _, td := range testData { 102 | jsonData := []byte(td.data) 103 | ejsBlock := goeditorjs.EditorJSBlock{Type: "paragraph", Data: jsonData} 104 | html, _ := bph.GenerateHTML(ejsBlock) 105 | require.Equal(t, fmt.Sprintf(`paragraph
`, td.alignment), html) 106 | } 107 | } 108 | 109 | func Test_ParagraphHandler_GenerateMarkdown_Returns_Parse_Err(t *testing.T) { 110 | h := &goeditorjs.ParagraphHandler{} 111 | _, err := h.GenerateMarkdown(goeditorjs.EditorJSBlock{Type: "paragraph", Data: []byte{}}) 112 | require.Error(t, err) 113 | } 114 | 115 | func Test_ParagraphHandler_GenerateMarkdown_Left(t *testing.T) { 116 | bph := &goeditorjs.ParagraphHandler{} 117 | jsonData := []byte(`{"text": "paragraph","alignment": "left"}`) 118 | ejsBlock := goeditorjs.EditorJSBlock{Type: "paragraph", Data: jsonData} 119 | md, _ := bph.GenerateMarkdown(ejsBlock) 120 | require.Equal(t, "paragraph", md) 121 | } 122 | 123 | func Test_ParagraphHandler_GenerateMarkdown_Center_Right(t *testing.T) { 124 | bph := &goeditorjs.ParagraphHandler{} 125 | testData := []struct { 126 | alignment string 127 | data string 128 | }{ 129 | {alignment: "center", data: `{"text": "paragraph","alignment": "center"}`}, 130 | {alignment: "right", data: `{"text": "paragraph","alignment": "right"}`}, 131 | } 132 | 133 | for _, td := range testData { 134 | jsonData := []byte(td.data) 135 | ejsBlock := goeditorjs.EditorJSBlock{Type: "paragraph", Data: jsonData} 136 | md, _ := bph.GenerateMarkdown(ejsBlock) 137 | require.Equal(t, fmt.Sprintf(`paragraph
`, td.alignment), md) 138 | } 139 | } 140 | 141 | func Test_ListHandler_Type(t *testing.T) { 142 | h := &goeditorjs.ListHandler{} 143 | require.Equal(t, "list", h.Type()) 144 | } 145 | 146 | func Test_ListHandler_GenerateHTML_Returns_Parse_Err(t *testing.T) { 147 | h := &goeditorjs.ListHandler{} 148 | _, err := h.GenerateHTML(goeditorjs.EditorJSBlock{Type: "list", Data: []byte{}}) 149 | require.Error(t, err) 150 | } 151 | 152 | func Test_ListHandler_GenerateHTML(t *testing.T) { 153 | blh := &goeditorjs.ListHandler{} 154 | testData := []struct { 155 | data string 156 | expectedResult string 157 | }{ 158 | {data: `{"style": "ordered", "items": ["one", "two", "three"]}`, 159 | expectedResult: "func main(){fmt.Println("HelloWorld")}`
214 | html, _ := bcbh.GenerateHTML(ejsBlock)
215 | require.Equal(t, expectedResult, html)
216 | }
217 |
218 | func Test_CodeBoxHandler_GenerateMarkdown_Returns_Parse_Err(t *testing.T) {
219 | h := &goeditorjs.CodeBoxHandler{}
220 | _, err := h.GenerateMarkdown(goeditorjs.EditorJSBlock{Type: "codeBox", Data: []byte{}})
221 | require.Error(t, err)
222 | }
223 |
224 | func Test_CodeBoxHandler_GenerateMarkdown(t *testing.T) {
225 | bcbh := &goeditorjs.CodeBoxHandler{}
226 | jsonData := []byte(`{"language": "go", "code": "func main(){fmt.Println(\"HelloWorld\")}"}`)
227 | ejsBlock := goeditorjs.EditorJSBlock{Type: "codeBox", Data: jsonData}
228 | expectedResult := "```go\nfunc main(){fmt.Println(\"HelloWorld\")}\n```"
229 | md, _ := bcbh.GenerateMarkdown(ejsBlock)
230 | require.Equal(t, expectedResult, md)
231 | }
232 |
233 | func Test_CodeBoxHandler_GenerateMarkdown_Clean(t *testing.T) {
234 | bcbh := &goeditorjs.CodeBoxHandler{}
235 | jsonData := []byte(`{"language": "go", "code": "package main
`},
298 | // No captions
299 | {data: `{"file":{"url": "https://www.w3schools.com/html/pic_trulli.jpg"},"caption": "","withBorder": true,"stretched": true,"withBackground": true}`,
300 | expectedResult: `
`},
301 | // Border
302 | {data: `{"file":{"url": "https://www.w3schools.com/html/pic_trulli.jpg"},"caption": "","withBorder": true,"stretched": false,"withBackground": false}`,
303 | expectedResult: `
`},
304 | // Stretch
305 | {data: `{"file":{"url": "https://www.w3schools.com/html/pic_trulli.jpg"},"caption": "","withBorder": false,"stretched": true,"withBackground": false}`,
306 | expectedResult: `
`},
307 | // Background
308 | {data: `{"file":{"url": "https://www.w3schools.com/html/pic_trulli.jpg"},"caption": "","withBorder": false,"stretched": false,"withBackground": true}`,
309 | expectedResult: `
`},
310 | // No classes
311 | {data: `{"file":{"url": "https://www.w3schools.com/html/pic_trulli.jpg"},"caption": "","withBorder": false,"stretched": false,"withBackground": false}`,
312 | expectedResult: `
`},
313 | }
314 |
315 | for _, td := range testData {
316 | jsonData := []byte(td.data)
317 | ejsBlock := goeditorjs.EditorJSBlock{Type: "image", Data: jsonData}
318 | result, _ := h.GenerateHTML(ejsBlock)
319 | require.Equal(t, td.expectedResult, result)
320 | }
321 | }
322 |
323 | func Test_ImageHandler_GenerateMarkdown_Returns_Parse_Err(t *testing.T) {
324 | h := &goeditorjs.ImageHandler{}
325 | _, err := h.GenerateMarkdown(goeditorjs.EditorJSBlock{Type: "image", Data: []byte{}})
326 | require.Error(t, err)
327 | }
328 |
329 | func Test_ImageHandler_GenerateMarkdown(t *testing.T) {
330 | h := &goeditorjs.ImageHandler{}
331 |
332 | testData := []struct {
333 | data string
334 | expectedResult string
335 | }{
336 | // Full test with defaults
337 | {data: `{"file":{"url": "https://www.w3schools.com/html/pic_trulli.jpg"},"caption": "Example Captions","withBorder": true,"stretched": true,"withBackground": true}`,
338 | expectedResult: `
`},
339 | // No captions
340 | {data: `{"file":{"url": "https://www.w3schools.com/html/pic_trulli.jpg"},"caption": "","withBorder": true,"stretched": true,"withBackground": true}`,
341 | expectedResult: `
`},
342 | // Border
343 | {data: `{"file":{"url": "https://www.w3schools.com/html/pic_trulli.jpg"},"caption": "","withBorder": true,"stretched": false,"withBackground": false}`,
344 | expectedResult: `
`},
345 | // Stretch
346 | {data: `{"file":{"url": "https://www.w3schools.com/html/pic_trulli.jpg"},"caption": "","withBorder": false,"stretched": true,"withBackground": false}`,
347 | expectedResult: `
`},
348 | // Background
349 | {data: `{"file":{"url": "https://www.w3schools.com/html/pic_trulli.jpg"},"caption": "","withBorder": false,"stretched": false,"withBackground": true}`,
350 | expectedResult: `
`},
351 | // No classes or caption
352 | {data: `{"file":{"url": "https://www.w3schools.com/html/pic_trulli.jpg"},"caption": "","withBorder": false,"stretched": false,"withBackground": false}`,
353 | expectedResult: ``},
354 | // No classes
355 | {data: `{"file":{"url": "https://www.w3schools.com/html/pic_trulli.jpg"},"caption": "Some caption","withBorder": false,"stretched": false,"withBackground": false}`,
356 | expectedResult: ``},
357 | }
358 |
359 | for _, td := range testData {
360 | jsonData := []byte(td.data)
361 | ejsBlock := goeditorjs.EditorJSBlock{Type: "image", Data: jsonData}
362 | result, _ := h.GenerateMarkdown(ejsBlock)
363 | require.Equal(t, td.expectedResult, result)
364 | }
365 | }
366 |
--------------------------------------------------------------------------------