editorjs_renderer 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -1
- data/README.md +34 -3
- data/lib/editorjs_renderer/blocks/attaches.rb +38 -0
- data/lib/editorjs_renderer/blocks/checklist.rb +26 -0
- data/lib/editorjs_renderer/blocks/code.rb +18 -0
- data/lib/editorjs_renderer/blocks/delimiter.rb +26 -0
- data/lib/editorjs_renderer/blocks/header.rb +23 -0
- data/lib/editorjs_renderer/blocks/image.rb +21 -0
- data/lib/editorjs_renderer/blocks/list.rb +38 -0
- data/lib/editorjs_renderer/config.rb +1 -1
- data/lib/editorjs_renderer/schemas/attaches.yml +18 -0
- data/lib/editorjs_renderer/schemas/checklist.yml +18 -0
- data/lib/editorjs_renderer/schemas/code.yml +8 -0
- data/lib/editorjs_renderer/schemas/delimiter.yml +3 -0
- data/lib/editorjs_renderer/schemas/header.yml +13 -0
- data/lib/editorjs_renderer/schemas/image.yml +16 -0
- data/lib/editorjs_renderer/schemas/list.yml +16 -0
- data/lib/editorjs_renderer/version.rb +1 -1
- data/lib/editorjs_renderer.rb +4 -12
- metadata +30 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b121c4cae0462b209cc6a06a97d20b604f64532ecde7d0ac17f49590b9071f5
|
4
|
+
data.tar.gz: de06caddb9899d96f371cdae6356d9c62b40aa54082634316e0d6c699e95529d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '00615381d173edec22850e3baee788a845c429fd2e368cb38912ed8da6dca136fa5d21adeff211cf1309fa0f9505675b0e9d218c2d7c68b899af2dbb57cc8c72'
|
7
|
+
data.tar.gz: fd934f5aa5f525ad06aaba16d2dd7671e19c34f1b32e41f95ddd15a49fdca4be7d5723581081bc1546a10f704ea4789281dedf1a00f06ae17df274ae4104d0f3
|
data/CHANGELOG.md
CHANGED
@@ -10,8 +10,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
10
10
|
## [Unreleased]
|
11
11
|
|
12
12
|
---
|
13
|
+
## [0.3.0] - 2025-04-24
|
13
14
|
|
14
|
-
|
15
|
+
### Added
|
16
|
+
- Zeitwerk autoloader support: removed all `require_relative` statements.
|
17
|
+
- New block: `Image` – renders `<img>` tag with optional `<figure>` and `<figcaption>`.
|
18
|
+
- New block: `List` – renders unordered and ordered lists (`<ul>` and `<ol>`).
|
19
|
+
- New block: `Attaches` – renders a download link with file size information.
|
20
|
+
- New block: `Checklist` – renders a checklist with checkboxes (readonly).
|
21
|
+
- New block: `Code` – renders multiline code block as `<pre><code>`.
|
22
|
+
- New block: `Delimiter` – renders horizontal rule (`<hr>`).
|
23
|
+
- Tests for all new blocks: structure validation, HTML output, plain output.
|
24
|
+
- Extended `document_spec.rb` to verify full document rendering with all blocks.
|
25
|
+
|
26
|
+
### Changed
|
27
|
+
- Replaced manual file loading with Zeitwerk's automatic constant loading.
|
28
|
+
|
29
|
+
---
|
30
|
+
|
31
|
+
## [0.2.1] - 2025-04-23
|
15
32
|
|
16
33
|
### Added
|
17
34
|
- New block: `Spoiler` – supports nested content via recursive rendering of inner `Document`.
|
data/README.md
CHANGED
@@ -13,6 +13,8 @@ It allows rendering JSON data generated by Editor.js into safe HTML and plain te
|
|
13
13
|
- Built-in validation using JSON Schema
|
14
14
|
- Secure HTML output via escaping
|
15
15
|
- Configurable block rendering system
|
16
|
+
- Support for nested blocks (blocks within blocks)
|
17
|
+
- Blocks: `Spoiler`, `Table`, `Checklist`, `Attaches`, `Code`, `Delimiter`, etc.
|
16
18
|
- No JavaScript dependencies required on the server side
|
17
19
|
|
18
20
|
---
|
@@ -39,7 +41,12 @@ bundle install
|
|
39
41
|
data = {
|
40
42
|
"time" => "123456789",
|
41
43
|
"blocks" => [
|
42
|
-
{ "type" => "paragraph", "data" => { "text" => "Hello <b>world</b>" } }
|
44
|
+
{ "type" => "paragraph", "data" => { "text" => "Hello <b>world</b>" } },
|
45
|
+
{ "type" => "checklist", "data" => { "items" => [
|
46
|
+
{ "text" => "Buy milk", "checked" => true },
|
47
|
+
{ "text" => "Read book", "checked" => false }
|
48
|
+
]}
|
49
|
+
}
|
43
50
|
]
|
44
51
|
}
|
45
52
|
```
|
@@ -47,10 +54,10 @@ data = {
|
|
47
54
|
```bash
|
48
55
|
document = EditorjsRenderer::Document.new(data)
|
49
56
|
document.render(format: :html)
|
50
|
-
# => "<p>Hello <b>world</b></p>"
|
57
|
+
# => "<p>Hello <b>world</b></p><ul class=\"checklist-block\"><li><input type=\"checkbox\" checked disabled> Buy milk</li><li><input type=\"checkbox\" disabled> Read book</li></ul>"
|
51
58
|
|
52
59
|
document.render(format: :plain)
|
53
|
-
# => "Hello <b>world</b
|
60
|
+
# => "Hello <b>world</b>\n[x] Buy milk\n[ ] Read book"
|
54
61
|
```
|
55
62
|
|
56
63
|
---
|
@@ -75,6 +82,20 @@ end
|
|
75
82
|
Schemas should follow the JSON Schema format and be stored in YAML files.
|
76
83
|
Each block must have a schema named like paragraph.yml, header.yml, etc.
|
77
84
|
|
85
|
+
Example:
|
86
|
+
```yml
|
87
|
+
type: object
|
88
|
+
required:
|
89
|
+
- text
|
90
|
+
properties:
|
91
|
+
text:
|
92
|
+
type: string
|
93
|
+
description: "The main content of the header block"
|
94
|
+
```
|
95
|
+
|
96
|
+
In this schema:
|
97
|
+
- `text` is a required field of type string, which represents the header text.
|
98
|
+
|
78
99
|
---
|
79
100
|
|
80
101
|
## Development
|
@@ -110,6 +131,16 @@ module EditorjsRenderer
|
|
110
131
|
end
|
111
132
|
```
|
112
133
|
|
134
|
+
#### Autoloading with Zeitwerk
|
135
|
+
|
136
|
+
This gem uses Zeitwerk to handle autoloading. Ensure you have Zeitwerk set up in your environment:
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
require "zeitwerk"
|
140
|
+
|
141
|
+
loader = Zeitwerk::Loader.for_gem
|
142
|
+
loader.setup
|
143
|
+
```
|
113
144
|
---
|
114
145
|
|
115
146
|
## Contributing
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# lib/editorjs_renderer/blocks/attaches.rb
|
4
|
+
module EditorjsRenderer
|
5
|
+
module Blocks
|
6
|
+
# Attaches block: renders a file download link with title and optional size.
|
7
|
+
class Attaches < Base
|
8
|
+
def to_html
|
9
|
+
url = ERB::Util.html_escape(block_data.dig("file", "url"))
|
10
|
+
title = ERB::Util.html_escape(block_data["title"].to_s)
|
11
|
+
size = block_data["size"]
|
12
|
+
|
13
|
+
size_str = size ? " (#{format_size(size)})" : ""
|
14
|
+
"<div class=\"attachment-block\"><a href=\"#{url}\" download>#{title}#{size_str}</a></div>"
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_plain
|
18
|
+
url = block_data.dig("file", "url")
|
19
|
+
title = block_data["title"].to_s
|
20
|
+
size = block_data["size"]
|
21
|
+
size_str = size ? " (#{format_size(size)})" : ""
|
22
|
+
"[Attachment] #{title} — #{url}#{size_str}".strip
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def format_size(bytes)
|
28
|
+
return unless bytes.respond_to?(:to_f) && bytes.to_f.positive?
|
29
|
+
|
30
|
+
kb = bytes.to_f / 1024
|
31
|
+
mb = kb / 1024
|
32
|
+
return "#{format("%.1f", mb)} MB" if mb >= 1
|
33
|
+
|
34
|
+
"#{format("%.1f", kb)} KB"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# lib/editorjs_renderer/blocks/checklist.rb
|
4
|
+
module EditorjsRenderer
|
5
|
+
module Blocks
|
6
|
+
# Checklist block: renders a list of checkboxes (readonly)
|
7
|
+
class Checklist < Base
|
8
|
+
def to_html
|
9
|
+
items = block_data["items"].map do |item|
|
10
|
+
text = ERB::Util.html_escape(item["text"].to_s)
|
11
|
+
checked_attr = item["checked"] ? " checked" : ""
|
12
|
+
"<li><input type=\"checkbox\"#{checked_attr} disabled> #{text}</li>"
|
13
|
+
end
|
14
|
+
|
15
|
+
"<ul class=\"checklist-block\">#{items.join}</ul>"
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_plain
|
19
|
+
block_data["items"].map do |item|
|
20
|
+
marker = item["checked"] ? "[x]" : "[ ]"
|
21
|
+
"#{marker} #{item["text"]}"
|
22
|
+
end.join("\n")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# lib/editorjs_renderer/blocks/code.rb
|
4
|
+
module EditorjsRenderer
|
5
|
+
module Blocks
|
6
|
+
# Code block: renders a block of code inside <pre><code>
|
7
|
+
class Code < Base
|
8
|
+
def to_html
|
9
|
+
code = ERB::Util.html_escape(block_data["code"].to_s)
|
10
|
+
"<pre><code>#{code}</code></pre>"
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_plain
|
14
|
+
block_data["code"].to_s
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# lib/editorjs_renderer/blocks/delimiter.rb
|
4
|
+
module EditorjsRenderer
|
5
|
+
module Blocks
|
6
|
+
# Delimiter block: renders a visual separator line (horizontal rule)
|
7
|
+
#
|
8
|
+
# Used to separate content sections, similar to <hr> or "---" in text.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# Delimiter.new({}).to_html
|
12
|
+
# # => '<hr class="delimiter-block">'
|
13
|
+
#
|
14
|
+
# Delimiter.new({}).to_plain
|
15
|
+
# # => "---"
|
16
|
+
class Delimiter < Base
|
17
|
+
def to_html
|
18
|
+
'<hr class="delimiter-block">'
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_plain
|
22
|
+
"---"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# lib/editorjs_renderer/blocks/header.rb
|
4
|
+
module EditorjsRenderer
|
5
|
+
module Blocks
|
6
|
+
# Header block renders a heading tag (<h1>–<h6>) based on level.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# data = { "text" => "Title", "level" => 2 }
|
10
|
+
# Header.new(data).to_html # => "<h2>Title</h2>"
|
11
|
+
class Header < Base
|
12
|
+
def to_html
|
13
|
+
level = block_data["level"].to_i.clamp(1, 6)
|
14
|
+
text = ERB::Util.html_escape(block_data["text"])
|
15
|
+
"<h#{level}>#{text}</h#{level}>"
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_plain
|
19
|
+
block_data["text"].to_s
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# lib/editorjs_renderer/blocks/image.rb
|
4
|
+
module EditorjsRenderer
|
5
|
+
module Blocks
|
6
|
+
# Image block: renders an <img> tag with optional caption
|
7
|
+
class Image < Base
|
8
|
+
def to_html
|
9
|
+
url = ERB::Util.html_escape(block_data["url"])
|
10
|
+
caption = ERB::Util.html_escape(block_data["caption"].to_s)
|
11
|
+
figure = "<img src=\"#{url}\" alt=\"#{caption}\">"
|
12
|
+
caption.empty? ? figure : "<figure>#{figure}<figcaption>#{caption}</figcaption></figure>"
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_plain
|
16
|
+
caption = block_data["caption"].to_s
|
17
|
+
"[Image] #{caption}".strip
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# lib/editorjs_renderer/blocks/list.rb
|
4
|
+
module EditorjsRenderer
|
5
|
+
module Blocks
|
6
|
+
# List block: renders a list as <ul>/<ol> with <li> elements.
|
7
|
+
#
|
8
|
+
# Example block data:
|
9
|
+
# {
|
10
|
+
# "style": "ordered",
|
11
|
+
# "items": ["First", "Second"]
|
12
|
+
# }
|
13
|
+
#
|
14
|
+
# Renders to:
|
15
|
+
# <ol><li>First</li><li>Second</li></ol>
|
16
|
+
#
|
17
|
+
# Or in plain text:
|
18
|
+
# 1. First
|
19
|
+
# 2. Second
|
20
|
+
class List < Base
|
21
|
+
def to_html
|
22
|
+
style = block_data["style"] == "ordered" ? "ol" : "ul"
|
23
|
+
items = block_data["items"].map do |item|
|
24
|
+
"<li>#{ERB::Util.html_escape(item)}</li>"
|
25
|
+
end
|
26
|
+
"<#{style}>#{items.join}</#{style}>"
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_plain
|
30
|
+
if block_data["style"] == "ordered"
|
31
|
+
block_data["items"].each_with_index.map { |item, i| "#{i + 1}. #{item}" }.join("\n")
|
32
|
+
else
|
33
|
+
block_data["items"].map { |item| "- #{item}" }.join("\n")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -11,7 +11,7 @@ module EditorjsRenderer
|
|
11
11
|
|
12
12
|
def initialize
|
13
13
|
@schemas_path = File.join(EditorjsRenderer.root, "lib", "editorjs_renderer", "schemas")
|
14
|
-
@enabled_blocks = %w[paragraph spoiler]
|
14
|
+
@enabled_blocks = %w[paragraph spoiler table header image list attaches checklist code delimiter]
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# lib/editorjs_renderer/schemas/checklist.yml
|
2
|
+
|
3
|
+
type: object
|
4
|
+
required:
|
5
|
+
- items
|
6
|
+
properties:
|
7
|
+
items:
|
8
|
+
type: array
|
9
|
+
items:
|
10
|
+
type: object
|
11
|
+
required:
|
12
|
+
- text
|
13
|
+
- checked
|
14
|
+
properties:
|
15
|
+
text:
|
16
|
+
type: string
|
17
|
+
checked:
|
18
|
+
type: boolean
|
data/lib/editorjs_renderer.rb
CHANGED
@@ -5,6 +5,10 @@ require "yaml"
|
|
5
5
|
require "active_support/all"
|
6
6
|
require "logger"
|
7
7
|
require "json_schemer"
|
8
|
+
require "zeitwerk"
|
9
|
+
|
10
|
+
loader = Zeitwerk::Loader.for_gem
|
11
|
+
loader.setup
|
8
12
|
|
9
13
|
# EditorjsRenderer provides rendering and configuration logic for EditorJS-compatible
|
10
14
|
# data in Ruby applications. It allows transforming structured block-based data
|
@@ -45,15 +49,3 @@ module EditorjsRenderer
|
|
45
49
|
end
|
46
50
|
end
|
47
51
|
end
|
48
|
-
|
49
|
-
require_relative "editorjs_renderer/errors"
|
50
|
-
require_relative "editorjs_renderer/config"
|
51
|
-
require_relative "editorjs_renderer/document"
|
52
|
-
require_relative "editorjs_renderer/renderers/html_renderer"
|
53
|
-
require_relative "editorjs_renderer/renderers/plain_renderer"
|
54
|
-
require_relative "editorjs_renderer/blocks/base"
|
55
|
-
require_relative "editorjs_renderer/blocks/paragraph"
|
56
|
-
require_relative "editorjs_renderer/blocks/spoiler"
|
57
|
-
require_relative "editorjs_renderer/blocks/table"
|
58
|
-
require_relative "editorjs_renderer/version"
|
59
|
-
require_relative "editorjs_renderer/schema_validator"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: editorjs_renderer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Georgy Shcherbakov
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
- Grigory Paraschevin
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2025-04-
|
12
|
+
date: 2025-04-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: actionview
|
@@ -53,6 +53,20 @@ dependencies:
|
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: 2.4.0
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: zeitwerk
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '2.7'
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '2.7'
|
56
70
|
description: Library for rendering and validating Editor.js documents in Rails applications
|
57
71
|
email:
|
58
72
|
- lordsynergymail@gmail.com
|
@@ -70,7 +84,14 @@ files:
|
|
70
84
|
- README.md
|
71
85
|
- Rakefile
|
72
86
|
- lib/editorjs_renderer.rb
|
87
|
+
- lib/editorjs_renderer/blocks/attaches.rb
|
73
88
|
- lib/editorjs_renderer/blocks/base.rb
|
89
|
+
- lib/editorjs_renderer/blocks/checklist.rb
|
90
|
+
- lib/editorjs_renderer/blocks/code.rb
|
91
|
+
- lib/editorjs_renderer/blocks/delimiter.rb
|
92
|
+
- lib/editorjs_renderer/blocks/header.rb
|
93
|
+
- lib/editorjs_renderer/blocks/image.rb
|
94
|
+
- lib/editorjs_renderer/blocks/list.rb
|
74
95
|
- lib/editorjs_renderer/blocks/paragraph.rb
|
75
96
|
- lib/editorjs_renderer/blocks/spoiler.rb
|
76
97
|
- lib/editorjs_renderer/blocks/table.rb
|
@@ -80,7 +101,14 @@ files:
|
|
80
101
|
- lib/editorjs_renderer/renderers/html_renderer.rb
|
81
102
|
- lib/editorjs_renderer/renderers/plain_renderer.rb
|
82
103
|
- lib/editorjs_renderer/schema_validator.rb
|
104
|
+
- lib/editorjs_renderer/schemas/attaches.yml
|
105
|
+
- lib/editorjs_renderer/schemas/checklist.yml
|
106
|
+
- lib/editorjs_renderer/schemas/code.yml
|
107
|
+
- lib/editorjs_renderer/schemas/delimiter.yml
|
83
108
|
- lib/editorjs_renderer/schemas/document.yml
|
109
|
+
- lib/editorjs_renderer/schemas/header.yml
|
110
|
+
- lib/editorjs_renderer/schemas/image.yml
|
111
|
+
- lib/editorjs_renderer/schemas/list.yml
|
84
112
|
- lib/editorjs_renderer/schemas/paragraph.yml
|
85
113
|
- lib/editorjs_renderer/schemas/spoiler.yml
|
86
114
|
- lib/editorjs_renderer/schemas/table.yml
|