storyblok-richtext-renderer 0.0.1
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 +7 -0
- data/.editorconfig +9 -0
- data/.gitignore +8 -0
- data/Gemfile +3 -0
- data/README.md +23 -0
- data/lib/storyblok/richtext.rb +2 -0
- data/lib/storyblok/richtext/html_renderer.rb +162 -0
- data/lib/storyblok/richtext/html_renderer/marks/bold.rb +14 -0
- data/lib/storyblok/richtext/html_renderer/marks/code.rb +14 -0
- data/lib/storyblok/richtext/html_renderer/marks/italic.rb +14 -0
- data/lib/storyblok/richtext/html_renderer/marks/link.rb +17 -0
- data/lib/storyblok/richtext/html_renderer/marks/mark.rb +24 -0
- data/lib/storyblok/richtext/html_renderer/marks/strike.rb +14 -0
- data/lib/storyblok/richtext/html_renderer/marks/strong.rb +14 -0
- data/lib/storyblok/richtext/html_renderer/marks/underline.rb +14 -0
- data/lib/storyblok/richtext/html_renderer/nodes/blockquote.rb +14 -0
- data/lib/storyblok/richtext/html_renderer/nodes/blok.rb +22 -0
- data/lib/storyblok/richtext/html_renderer/nodes/bullet_list.rb +14 -0
- data/lib/storyblok/richtext/html_renderer/nodes/code_block.rb +20 -0
- data/lib/storyblok/richtext/html_renderer/nodes/hard_break.rb +14 -0
- data/lib/storyblok/richtext/html_renderer/nodes/heading.rb +14 -0
- data/lib/storyblok/richtext/html_renderer/nodes/horizontal_rule.rb +14 -0
- data/lib/storyblok/richtext/html_renderer/nodes/image.rb +17 -0
- data/lib/storyblok/richtext/html_renderer/nodes/list_item.rb +13 -0
- data/lib/storyblok/richtext/html_renderer/nodes/node.rb +37 -0
- data/lib/storyblok/richtext/html_renderer/nodes/ordered_list.rb +14 -0
- data/lib/storyblok/richtext/html_renderer/nodes/paragraph.rb +14 -0
- data/lib/storyblok/richtext/html_renderer/nodes/text.rb +14 -0
- data/lib/storyblok/richtext/version.rb +6 -0
- data/storyblok.gemspec +20 -0
- metadata +105 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2eb892e77eebea9767d260686015cff5f8948508939f2327a1fcab0494e34e78
|
4
|
+
data.tar.gz: 9f685e352c16d6c929bddf591f0f136aa42f5296ecabe29f5603a609b5ed85b9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 73b34ed7f2421bd114e770f4ea122a19d0651602901247c90edf8bf12c3cb68f76ba9e94750ec2258f7070dff6ecb0e9f80032ee5abe8fcf8060c6bd20dcd80c
|
7
|
+
data.tar.gz: 4800002870e1b0d0807ad2a0ded413e6aa4aebf337c4fa16ecec70c75c35309d39bb0a2ea1f7b18e57c4a712e24f0e535fe31c199d1e69a4cb51634a2354ae5d
|
data/.editorconfig
ADDED
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# About
|
2
|
+
|
3
|
+
This is Storyblok's rendering service to render html from the data of the richtext field type. The renderer is also compatible with Prosemirror's json format.
|
4
|
+
|
5
|
+
## How to install
|
6
|
+
|
7
|
+
Add the gem to your Gemfile
|
8
|
+
|
9
|
+
```bash
|
10
|
+
gem 'storyblok-richtext-renderer'
|
11
|
+
```
|
12
|
+
|
13
|
+
### Rendering a richtext field
|
14
|
+
|
15
|
+
```
|
16
|
+
renderer = Storyblok::Richtext::HtmlRenderer.new
|
17
|
+
renderer.render({'type' => 'doc', 'content' => [{'type' => 'paragraph', 'content' => [{'text' => 'Good', 'type' => 'text'}]}]})
|
18
|
+
# -> <p>Good</p>
|
19
|
+
```
|
20
|
+
|
21
|
+
### License
|
22
|
+
|
23
|
+
This project is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require "cgi"
|
2
|
+
|
3
|
+
module Storyblok
|
4
|
+
module Richtext
|
5
|
+
require_relative "html_renderer/marks/mark"
|
6
|
+
require_relative "html_renderer/marks/strike"
|
7
|
+
require_relative "html_renderer/marks/underline"
|
8
|
+
require_relative "html_renderer/marks/bold"
|
9
|
+
require_relative "html_renderer/marks/strong"
|
10
|
+
require_relative "html_renderer/marks/code"
|
11
|
+
require_relative "html_renderer/marks/italic"
|
12
|
+
require_relative "html_renderer/marks/link"
|
13
|
+
require_relative "html_renderer/nodes/node"
|
14
|
+
require_relative "html_renderer/nodes/bullet_list"
|
15
|
+
require_relative "html_renderer/nodes/code_block"
|
16
|
+
require_relative "html_renderer/nodes/hard_break"
|
17
|
+
require_relative "html_renderer/nodes/heading"
|
18
|
+
require_relative "html_renderer/nodes/image"
|
19
|
+
require_relative "html_renderer/nodes/list_item"
|
20
|
+
require_relative "html_renderer/nodes/ordered_list"
|
21
|
+
require_relative "html_renderer/nodes/paragraph"
|
22
|
+
require_relative "html_renderer/nodes/text"
|
23
|
+
require_relative "html_renderer/nodes/blockquote"
|
24
|
+
require_relative "html_renderer/nodes/horizontal_rule"
|
25
|
+
require_relative "html_renderer/nodes/text"
|
26
|
+
require_relative "html_renderer/nodes/blok"
|
27
|
+
|
28
|
+
class HtmlRenderer
|
29
|
+
def initialize
|
30
|
+
@marks = [
|
31
|
+
Storyblok::Richtext::Marks::Bold,
|
32
|
+
Storyblok::Richtext::Marks::Strike,
|
33
|
+
Storyblok::Richtext::Marks::Underline,
|
34
|
+
Storyblok::Richtext::Marks::Strong,
|
35
|
+
Storyblok::Richtext::Marks::Code,
|
36
|
+
Storyblok::Richtext::Marks::Italic,
|
37
|
+
Storyblok::Richtext::Marks::Link
|
38
|
+
]
|
39
|
+
@nodes = [
|
40
|
+
Storyblok::Richtext::Nodes::HorizontalRule,
|
41
|
+
Storyblok::Richtext::Nodes::Blockquote,
|
42
|
+
Storyblok::Richtext::Nodes::BulletList,
|
43
|
+
Storyblok::Richtext::Nodes::CodeBlock,
|
44
|
+
Storyblok::Richtext::Nodes::HardBreak,
|
45
|
+
Storyblok::Richtext::Nodes::Heading,
|
46
|
+
Storyblok::Richtext::Nodes::Image,
|
47
|
+
Storyblok::Richtext::Nodes::ListItem,
|
48
|
+
Storyblok::Richtext::Nodes::OrderedList,
|
49
|
+
Storyblok::Richtext::Nodes::Paragraph,
|
50
|
+
Storyblok::Richtext::Nodes::Text,
|
51
|
+
Storyblok::Richtext::Nodes::Blok
|
52
|
+
]
|
53
|
+
end
|
54
|
+
|
55
|
+
def set_component_resolver(component_resolver)
|
56
|
+
Storyblok::Richtext::Nodes::Blok.define_method :component_resolver, component_resolver
|
57
|
+
end
|
58
|
+
|
59
|
+
def add_node(node)
|
60
|
+
@nodes.push(node)
|
61
|
+
end
|
62
|
+
|
63
|
+
def add_mark(mark)
|
64
|
+
@marks.push(mark)
|
65
|
+
end
|
66
|
+
|
67
|
+
def render(data)
|
68
|
+
html = ""
|
69
|
+
data['content'].each do |node|
|
70
|
+
html += render_node(node)
|
71
|
+
end
|
72
|
+
|
73
|
+
html
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def render_node(item)
|
79
|
+
html = []
|
80
|
+
if item['marks']
|
81
|
+
item['marks'].each do |m|
|
82
|
+
mark = get_matching_mark(m)
|
83
|
+
html.push(render_opening_tag(mark.tag)) if mark
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
node = get_matching_node(item)
|
88
|
+
html.push(render_opening_tag(node.tag)) if node and node.tag
|
89
|
+
|
90
|
+
if item['content']
|
91
|
+
item['content'].each do |content|
|
92
|
+
html.push(render_node(content))
|
93
|
+
end
|
94
|
+
elsif node and node.text
|
95
|
+
html.push(CGI.escapeHTML(node.text))
|
96
|
+
elsif node and node.single_tag
|
97
|
+
html.push(render_tag(node.single_tag))
|
98
|
+
elsif node and node.html
|
99
|
+
html.push(node.html)
|
100
|
+
end
|
101
|
+
|
102
|
+
html.push(render_closing_tag(node.tag)) if node and node.tag
|
103
|
+
if item['marks']
|
104
|
+
item['marks'].reverse.each do |m|
|
105
|
+
mark = get_matching_mark(m)
|
106
|
+
html.push(render_closing_tag(mark.tag)) if mark
|
107
|
+
end
|
108
|
+
end
|
109
|
+
return html.join("")
|
110
|
+
end
|
111
|
+
|
112
|
+
def render_tag(tags, ending = ' /')
|
113
|
+
return "<#{tags}#{ending}>" if tags.is_a? String
|
114
|
+
all = tags.map do |tag|
|
115
|
+
if tag.is_a? String
|
116
|
+
"<#{tag}#{ending}>"
|
117
|
+
else
|
118
|
+
h = "<#{tag[:tag]}"
|
119
|
+
tag[:attrs].to_h.each_pair { |key, value| h += " #{key}=\"#{CGI.escapeHTML(value)}\"" if !value.nil? } if tag[:attrs]
|
120
|
+
"#{h}#{ending}>"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
return all.join('')
|
124
|
+
end
|
125
|
+
|
126
|
+
def render_opening_tag(tags)
|
127
|
+
render_tag(tags, '')
|
128
|
+
end
|
129
|
+
|
130
|
+
def render_closing_tag(tags)
|
131
|
+
return "</#{tags}>" if tags.is_a? String
|
132
|
+
|
133
|
+
all = tags.reverse.map do |tag|
|
134
|
+
if tag.is_a? String
|
135
|
+
"</#{tag}>"
|
136
|
+
else
|
137
|
+
"</#{tag[:tag]}>"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
return all.join('')
|
141
|
+
end
|
142
|
+
|
143
|
+
def get_matching_node(item)
|
144
|
+
return get_matching_class(item, @nodes)
|
145
|
+
end
|
146
|
+
|
147
|
+
def get_matching_mark(item)
|
148
|
+
return get_matching_class(item, @marks)
|
149
|
+
end
|
150
|
+
|
151
|
+
def get_matching_class(node, classes)
|
152
|
+
found = classes.select do |clazz|
|
153
|
+
instance = clazz.new(node)
|
154
|
+
if (instance.matching())
|
155
|
+
return instance
|
156
|
+
end
|
157
|
+
end
|
158
|
+
found.first
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Storyblok::Richtext
|
2
|
+
module Marks
|
3
|
+
class Mark
|
4
|
+
attr_writer :type
|
5
|
+
|
6
|
+
def type
|
7
|
+
@type || 'mark'
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(data)
|
11
|
+
@node = data
|
12
|
+
end
|
13
|
+
|
14
|
+
def matching
|
15
|
+
false
|
16
|
+
end
|
17
|
+
|
18
|
+
def tag
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Storyblok::Richtext
|
2
|
+
module Nodes
|
3
|
+
class Blok < Node
|
4
|
+
|
5
|
+
def matching
|
6
|
+
@node['type'] === 'blok'
|
7
|
+
end
|
8
|
+
|
9
|
+
def html
|
10
|
+
body = ''
|
11
|
+
@node['attrs']['body'].each do |blok|
|
12
|
+
body += component_resolver(blok['component'], blok)
|
13
|
+
end
|
14
|
+
body
|
15
|
+
end
|
16
|
+
|
17
|
+
def component_resolver component, data
|
18
|
+
''
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Storyblok::Richtext
|
2
|
+
module Nodes
|
3
|
+
class CodeBlock < Node
|
4
|
+
|
5
|
+
def matching
|
6
|
+
@node['type'] === 'code_block'
|
7
|
+
end
|
8
|
+
|
9
|
+
def tag
|
10
|
+
[
|
11
|
+
'pre',
|
12
|
+
{
|
13
|
+
tag: 'code',
|
14
|
+
attrs: @node['attrs'].slice('class')
|
15
|
+
}
|
16
|
+
]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Storyblok::Richtext
|
2
|
+
module Nodes
|
3
|
+
|
4
|
+
class Node
|
5
|
+
attr_writer :wrapper
|
6
|
+
attr_writer :type
|
7
|
+
|
8
|
+
def type
|
9
|
+
@type || 'node'
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(data)
|
13
|
+
@node = data
|
14
|
+
end
|
15
|
+
|
16
|
+
def matching
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
def single_tag
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def tag
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def text
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def html
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/storyblok.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.expand_path('../lib/storyblok/richtext/version', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.name = 'storyblok-richtext-renderer'
|
5
|
+
gem.version = Storyblok::Richtext::VERSION
|
6
|
+
gem.summary = 'Storyblok richtext renderer'
|
7
|
+
gem.description = 'This is Storyblok\'s rendering service to render html from the data of the richtext field type. The renderer is compatible with Prosemirror\'s json format.'
|
8
|
+
gem.license = 'MIT'
|
9
|
+
gem.authors = ['Storyblok (Alexander Feiglstorfer)']
|
10
|
+
gem.email = 'it@storyblok.com'
|
11
|
+
gem.homepage = 'https://github.com/storyblok/storyblok-ruby-richtext-renderer'
|
12
|
+
|
13
|
+
gem.files = Dir['{**/}{.*,*}'].select { |path| File.file?(path) && !path.start_with?('pkg') && !path.end_with?('.gem') }
|
14
|
+
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
15
|
+
gem.test_files = gem.files.grep(%r{^spec/})
|
16
|
+
gem.require_paths = ['lib/storyblok']
|
17
|
+
|
18
|
+
gem.add_development_dependency 'bundler', '~> 1.5'
|
19
|
+
gem.add_development_dependency 'rspec', '~> 3'
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: storyblok-richtext-renderer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Storyblok (Alexander Feiglstorfer)
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-09-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3'
|
41
|
+
description: This is Storyblok's rendering service to render html from the data of
|
42
|
+
the richtext field type. The renderer is compatible with Prosemirror's json format.
|
43
|
+
email: it@storyblok.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".DS_Store"
|
49
|
+
- ".editorconfig"
|
50
|
+
- ".gitignore"
|
51
|
+
- ".ruby-version"
|
52
|
+
- Gemfile
|
53
|
+
- README.md
|
54
|
+
- lib/.DS_Store
|
55
|
+
- lib/storyblok/.DS_Store
|
56
|
+
- lib/storyblok/richtext.rb
|
57
|
+
- lib/storyblok/richtext/html_renderer.rb
|
58
|
+
- lib/storyblok/richtext/html_renderer/marks/bold.rb
|
59
|
+
- lib/storyblok/richtext/html_renderer/marks/code.rb
|
60
|
+
- lib/storyblok/richtext/html_renderer/marks/italic.rb
|
61
|
+
- lib/storyblok/richtext/html_renderer/marks/link.rb
|
62
|
+
- lib/storyblok/richtext/html_renderer/marks/mark.rb
|
63
|
+
- lib/storyblok/richtext/html_renderer/marks/strike.rb
|
64
|
+
- lib/storyblok/richtext/html_renderer/marks/strong.rb
|
65
|
+
- lib/storyblok/richtext/html_renderer/marks/underline.rb
|
66
|
+
- lib/storyblok/richtext/html_renderer/nodes/blockquote.rb
|
67
|
+
- lib/storyblok/richtext/html_renderer/nodes/blok.rb
|
68
|
+
- lib/storyblok/richtext/html_renderer/nodes/bullet_list.rb
|
69
|
+
- lib/storyblok/richtext/html_renderer/nodes/code_block.rb
|
70
|
+
- lib/storyblok/richtext/html_renderer/nodes/hard_break.rb
|
71
|
+
- lib/storyblok/richtext/html_renderer/nodes/heading.rb
|
72
|
+
- lib/storyblok/richtext/html_renderer/nodes/horizontal_rule.rb
|
73
|
+
- lib/storyblok/richtext/html_renderer/nodes/image.rb
|
74
|
+
- lib/storyblok/richtext/html_renderer/nodes/list_item.rb
|
75
|
+
- lib/storyblok/richtext/html_renderer/nodes/node.rb
|
76
|
+
- lib/storyblok/richtext/html_renderer/nodes/ordered_list.rb
|
77
|
+
- lib/storyblok/richtext/html_renderer/nodes/paragraph.rb
|
78
|
+
- lib/storyblok/richtext/html_renderer/nodes/text.rb
|
79
|
+
- lib/storyblok/richtext/version.rb
|
80
|
+
- storyblok.gemspec
|
81
|
+
homepage: https://github.com/storyblok/storyblok-ruby-richtext-renderer
|
82
|
+
licenses:
|
83
|
+
- MIT
|
84
|
+
metadata: {}
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options: []
|
87
|
+
require_paths:
|
88
|
+
- lib/storyblok
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
requirements: []
|
100
|
+
rubyforge_project:
|
101
|
+
rubygems_version: 2.7.6
|
102
|
+
signing_key:
|
103
|
+
specification_version: 4
|
104
|
+
summary: Storyblok richtext renderer
|
105
|
+
test_files: []
|