slate_serializer 0.1.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 +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +39 -0
- data/README.md +34 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/slate_serializer/html.rb +158 -0
- data/lib/slate_serializer/plain.rb +83 -0
- data/lib/slate_serializer/version.rb +3 -0
- data/lib/slate_serializer.rb +7 -0
- data/slate_serializer.gemspec +28 -0
- metadata +114 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e7c0aa192fb18f0531d3df4352d3dccf7ec8db7381255b616280fbad341f7ae8
|
4
|
+
data.tar.gz: 1caa16f6f8bd5a6b278ebe5926388a748e6609a155022a0b7085d6e4f76750a8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b9172bda2bef9997675359dd0f13544468ad30cd52528b985b63fca9cb8898e7aec2d34c03f3df5c1a0a8d1224adb28ba661dafaf9083c831918a67801a36fcd
|
7
|
+
data.tar.gz: 7f696b95baaffec89ec730375e294acb4e37a1e4ed800a1eb705c23a3295946a5894997ab41738276ab7d8e61e2e32fdcc34e5c859a54f2ada9c23fd78e0c999
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.6.2
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
slate_serializer (0.1.0)
|
5
|
+
nokogiri (~> 1.10)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
diff-lcs (1.3)
|
11
|
+
mini_portile2 (2.4.0)
|
12
|
+
nokogiri (1.10.3)
|
13
|
+
mini_portile2 (~> 2.4.0)
|
14
|
+
rake (10.5.0)
|
15
|
+
rspec (3.8.0)
|
16
|
+
rspec-core (~> 3.8.0)
|
17
|
+
rspec-expectations (~> 3.8.0)
|
18
|
+
rspec-mocks (~> 3.8.0)
|
19
|
+
rspec-core (3.8.0)
|
20
|
+
rspec-support (~> 3.8.0)
|
21
|
+
rspec-expectations (3.8.3)
|
22
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
23
|
+
rspec-support (~> 3.8.0)
|
24
|
+
rspec-mocks (3.8.0)
|
25
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
26
|
+
rspec-support (~> 3.8.0)
|
27
|
+
rspec-support (3.8.0)
|
28
|
+
|
29
|
+
PLATFORMS
|
30
|
+
ruby
|
31
|
+
|
32
|
+
DEPENDENCIES
|
33
|
+
bundler (~> 1.17)
|
34
|
+
rake (~> 10.0)
|
35
|
+
rspec (~> 3.0)
|
36
|
+
slate_serializer!
|
37
|
+
|
38
|
+
BUNDLED WITH
|
39
|
+
1.17.2
|
data/README.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# SlateSerializer
|
2
|
+
|
3
|
+
SlateSerializer de- and serializer text and html to Slate document values in Ruby.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'slate_serializer'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install slate_serializer
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
To convert between plain text and Slate document use:
|
24
|
+
|
25
|
+
$ SlateSerializer::Plain.serializer({ document: {...}}) => text
|
26
|
+
$ SlateSerializer::Plain.deserializer(text) => { document: {...}}
|
27
|
+
|
28
|
+
To convert between html and Slate document use:
|
29
|
+
|
30
|
+
$ SlateSerializer::Html.deserializer(text) => { document: {...}}
|
31
|
+
|
32
|
+
## Contributing
|
33
|
+
|
34
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/wesleystam/slate_serializer.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'slate_serializer'
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'irb'
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module SlateSerializer
|
4
|
+
# Html de- and serializer
|
5
|
+
class Html
|
6
|
+
# Default lookup list to convert html tags to object types
|
7
|
+
ELEMENTS = {
|
8
|
+
'a': 'link',
|
9
|
+
'img': 'image',
|
10
|
+
'li': 'list-item',
|
11
|
+
'p': 'paragraph',
|
12
|
+
'div': 'paragraph',
|
13
|
+
'ola': 'alpha-ordered-list',
|
14
|
+
'ol': 'ordered-list',
|
15
|
+
'ul': 'unordered-list',
|
16
|
+
'table': 'table',
|
17
|
+
'tbody': 'tbody',
|
18
|
+
'tr': 'tr',
|
19
|
+
'td': 'td',
|
20
|
+
'text': 'text'
|
21
|
+
}.freeze
|
22
|
+
# Default block types list
|
23
|
+
BLOCK_ELEMENTS = %w[img li p ol ul table tbody tr td].freeze
|
24
|
+
# Default inline types list
|
25
|
+
INLINE_ELEMENTS = %w[a].freeze
|
26
|
+
# Default mark types list
|
27
|
+
MARK_ELEMENTS = {
|
28
|
+
'em': 'italic',
|
29
|
+
'strong': 'bold',
|
30
|
+
'u': 'underline'
|
31
|
+
}.freeze
|
32
|
+
|
33
|
+
class << self
|
34
|
+
# Convert html to a Slare document
|
35
|
+
#
|
36
|
+
# @param html format [String] the HTML
|
37
|
+
# @param options [Hash]
|
38
|
+
# @option options [Array] :elements Lookup list to convert html tags to object types
|
39
|
+
# @option options [Array] :block_elemnts List of block types
|
40
|
+
# @option options [Array] :inline_elemnts List of inline types
|
41
|
+
# @option options [Array] :mark_elemnts List of mark types
|
42
|
+
def deserializer(html, options = {})
|
43
|
+
return {} if html.nil?
|
44
|
+
|
45
|
+
self.elements = options[:elements] || ELEMENTS
|
46
|
+
self.block_elements = options[:block_elements] || BLOCK_ELEMENTS
|
47
|
+
self.inline_elements = options[:inline_elements] || INLINE_ELEMENTS
|
48
|
+
self.mark_elements = options[:mark_elements] || MARK_ELEMENTS
|
49
|
+
|
50
|
+
html = html.gsub('<br>', "\n")
|
51
|
+
nodes = Nokogiri::HTML.fragment(html).elements.map do |element|
|
52
|
+
element_to_node(element)
|
53
|
+
end
|
54
|
+
|
55
|
+
{
|
56
|
+
document: {
|
57
|
+
nodes: nodes
|
58
|
+
}
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
attr_accessor :elements, :block_elements, :inline_elements, :mark_elements
|
65
|
+
|
66
|
+
def element_to_node(element)
|
67
|
+
type = convert_name_to_type(element)
|
68
|
+
|
69
|
+
nodes = element.children.map do |child|
|
70
|
+
next if child.text.strip == '' && child.type == 'img'
|
71
|
+
|
72
|
+
if block?(child)
|
73
|
+
element_to_node(child)
|
74
|
+
elsif inline?(child)
|
75
|
+
element_to_inline(child)
|
76
|
+
else
|
77
|
+
next if child.text.strip == ''
|
78
|
+
|
79
|
+
element_to_text(child)
|
80
|
+
end
|
81
|
+
end.compact
|
82
|
+
|
83
|
+
{
|
84
|
+
data: element.attributes.each_with_object({}) { |a, h| h[a[1].name] = a[1].value },
|
85
|
+
object: 'block',
|
86
|
+
nodes: nodes,
|
87
|
+
type: type
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
def element_to_inline(element)
|
92
|
+
type = convert_name_to_type(element)
|
93
|
+
nodes = element.children.map do |child|
|
94
|
+
element_to_text(child)
|
95
|
+
end
|
96
|
+
|
97
|
+
{
|
98
|
+
data: element.attributes.each_with_object({}) { |a, h| h[a[1].name] = a[1].value },
|
99
|
+
object: 'inline',
|
100
|
+
nodes: nodes,
|
101
|
+
type: type
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
def element_to_text(element)
|
106
|
+
leaves = []
|
107
|
+
mark = convert_name_to_mark(element.name)
|
108
|
+
|
109
|
+
if element.class == Nokogiri::XML::Element
|
110
|
+
element.children.each do |child|
|
111
|
+
leaves << element_to_leave(child, mark)
|
112
|
+
end
|
113
|
+
else
|
114
|
+
leaves << element_to_leave(element)
|
115
|
+
end
|
116
|
+
|
117
|
+
{
|
118
|
+
leaves: leaves,
|
119
|
+
object: 'text'
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
123
|
+
def element_to_leave(element, mark = nil)
|
124
|
+
marks = [mark, convert_name_to_mark(element.name)].compact
|
125
|
+
{
|
126
|
+
marks: marks,
|
127
|
+
object: 'leaf',
|
128
|
+
text: element.text
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
def convert_name_to_type(element)
|
133
|
+
type = [element.name, element.attributes['type']&.value].compact.join
|
134
|
+
elements[type.to_sym]
|
135
|
+
end
|
136
|
+
|
137
|
+
def convert_name_to_mark(name)
|
138
|
+
type = mark_elements[name.to_sym]
|
139
|
+
|
140
|
+
return nil unless type
|
141
|
+
|
142
|
+
{
|
143
|
+
data: [],
|
144
|
+
object: 'mark',
|
145
|
+
type: type
|
146
|
+
}
|
147
|
+
end
|
148
|
+
|
149
|
+
def block?(element)
|
150
|
+
block_elements.include?(element.name)
|
151
|
+
end
|
152
|
+
|
153
|
+
def inline?(element)
|
154
|
+
inline_elements.include?(element.name)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module SlateSerializer
|
2
|
+
# Text de- and serializer
|
3
|
+
class Plain
|
4
|
+
class << self
|
5
|
+
# Convert text to a Slate document
|
6
|
+
#
|
7
|
+
# @param text format [String] the text
|
8
|
+
# return [Hash] Slate document
|
9
|
+
def deserializer(text)
|
10
|
+
return {} if text.nil?
|
11
|
+
|
12
|
+
lines = split_text_into_lines(text)
|
13
|
+
{
|
14
|
+
document: {
|
15
|
+
object: 'document',
|
16
|
+
nodes: convert_lines_into_nodes(lines)
|
17
|
+
}
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
# Convert a Slate Document to plain text
|
22
|
+
#
|
23
|
+
# @param value format [Hash] the Slate document
|
24
|
+
# @param options format [Hash] options for the serializer, delimitter defaults to "\n"
|
25
|
+
# @return [String] plain text version of the Slate documnent
|
26
|
+
def serializer(value, options = {})
|
27
|
+
return '' unless value.key?(:document)
|
28
|
+
|
29
|
+
options[:delimiter] = "\n" unless options.key?(:delimiter)
|
30
|
+
serialize_node(value[:document], options)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def split_text_into_lines(text)
|
36
|
+
lines = text.strip.split("\n").map(&:strip)
|
37
|
+
blocks = []
|
38
|
+
|
39
|
+
loop do
|
40
|
+
index = lines.find_index('')
|
41
|
+
if index.nil?
|
42
|
+
blocks << lines.join("\n")
|
43
|
+
break
|
44
|
+
end
|
45
|
+
|
46
|
+
blocks << lines[0...index].join("\n")
|
47
|
+
lines.shift(index + 1)
|
48
|
+
end
|
49
|
+
|
50
|
+
blocks.reject { |block| block == '' }
|
51
|
+
end
|
52
|
+
|
53
|
+
def convert_lines_into_nodes(lines)
|
54
|
+
lines.map do |line|
|
55
|
+
{
|
56
|
+
object: 'block',
|
57
|
+
type: 'paragraph',
|
58
|
+
data: {},
|
59
|
+
nodes: [
|
60
|
+
object: 'text',
|
61
|
+
data: {},
|
62
|
+
leaves: [
|
63
|
+
{
|
64
|
+
object: 'leaf',
|
65
|
+
text: line,
|
66
|
+
marks: []
|
67
|
+
}
|
68
|
+
]
|
69
|
+
]
|
70
|
+
}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def serialize_node(node, options)
|
75
|
+
if node[:object] == 'document' || node[:object] == 'block'
|
76
|
+
node[:nodes].map { |n| serialize_node(n, options) }.join(options[:delimiter])
|
77
|
+
else
|
78
|
+
node[:leaves].map { |l| l[:text] }.join(' ')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'slate_serializer/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'slate_serializer'
|
7
|
+
spec.version = SlateSerializer::VERSION
|
8
|
+
spec.authors = ['Wesley Stam']
|
9
|
+
spec.email = ['wesley@stam.me']
|
10
|
+
spec.license = "MIT"
|
11
|
+
|
12
|
+
spec.summary = 'Serializer for Slate documents written in Ruby'
|
13
|
+
spec.homepage = 'https://github.com/wesleystam/slate_serializer'
|
14
|
+
|
15
|
+
# Specify which files should be added to the gem when it is released.
|
16
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
17
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
18
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
+
end
|
20
|
+
spec.bindir = 'exe'
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ['lib']
|
23
|
+
|
24
|
+
spec.add_dependency 'nokogiri', '~> 1.10'
|
25
|
+
spec.add_development_dependency 'bundler', '~> 1.17'
|
26
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
27
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: slate_serializer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Wesley Stam
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-05-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: nokogiri
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.10'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.17'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.17'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- wesley@stam.me
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rspec"
|
78
|
+
- ".ruby-version"
|
79
|
+
- ".travis.yml"
|
80
|
+
- Gemfile
|
81
|
+
- Gemfile.lock
|
82
|
+
- README.md
|
83
|
+
- Rakefile
|
84
|
+
- bin/console
|
85
|
+
- bin/setup
|
86
|
+
- lib/slate_serializer.rb
|
87
|
+
- lib/slate_serializer/html.rb
|
88
|
+
- lib/slate_serializer/plain.rb
|
89
|
+
- lib/slate_serializer/version.rb
|
90
|
+
- slate_serializer.gemspec
|
91
|
+
homepage: https://github.com/wesleystam/slate_serializer
|
92
|
+
licenses:
|
93
|
+
- MIT
|
94
|
+
metadata: {}
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
requirements: []
|
110
|
+
rubygems_version: 3.0.3
|
111
|
+
signing_key:
|
112
|
+
specification_version: 4
|
113
|
+
summary: Serializer for Slate documents written in Ruby
|
114
|
+
test_files: []
|