lwe_slate_serializer 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1e1afc95f11d60edc3272a0097520e1bddca78ee9a8c37cd6908ff63ed0563bd
4
+ data.tar.gz: 98c0ee15eebb1e2e5e7537419c4144d2985121487c8fa65cc26064da3871b02f
5
+ SHA512:
6
+ metadata.gz: 4d84ccba0d9b4027b1888696aa01a34de921d51826c0665671497c640b9d559ddbfa739b09a1d5c0a946671a5539b29b26149ad4056466ae44404351109f4f9b
7
+ data.tar.gz: e5f8ff256e04ef82167592b755699ebe1fa80506edcb0d4f99bf46ccc5474f4454011cb32488b50fb08a8882034ae36d7a1d8bcd1a78614af96bac7d4a62dbb9
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.0.2
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.6.2
7
+ before_install: gem install bundler -v 1.17.2
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in slate_serializer.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,41 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ lwe_slate_serializer (1.0.0)
5
+ nokogiri (~> 1.11)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.4.4)
11
+ mini_portile2 (2.8.0)
12
+ nokogiri (1.13.3)
13
+ mini_portile2 (~> 2.8.0)
14
+ racc (~> 1.4)
15
+ racc (1.6.0)
16
+ rake (13.0.3)
17
+ rspec (3.10.0)
18
+ rspec-core (~> 3.10.0)
19
+ rspec-expectations (~> 3.10.0)
20
+ rspec-mocks (~> 3.10.0)
21
+ rspec-core (3.10.1)
22
+ rspec-support (~> 3.10.0)
23
+ rspec-expectations (3.10.1)
24
+ diff-lcs (>= 1.2.0, < 2.0)
25
+ rspec-support (~> 3.10.0)
26
+ rspec-mocks (3.10.2)
27
+ diff-lcs (>= 1.2.0, < 2.0)
28
+ rspec-support (~> 3.10.0)
29
+ rspec-support (3.10.2)
30
+
31
+ PLATFORMS
32
+ ruby
33
+
34
+ DEPENDENCIES
35
+ bundler (~> 2.2)
36
+ lwe_slate_serializer!
37
+ rake (~> 13.0)
38
+ rspec (~> 3.0)
39
+
40
+ BUNDLED WITH
41
+ 2.2.22
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([...]) => text
26
+ $ SlateSerializer::Plain.deserializer(text) => [...]
27
+
28
+ To convert between html and Slate document use:
29
+
30
+ $ SlateSerializer::Html.deserializer(html) => [...]
31
+
32
+ ## Contributing
33
+
34
+ Bug reports and pull requests are welcome on GitHub at https://github.com/wesleystam/slate_serializer.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
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,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,188 @@
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
+ 'ol1': 'ordered-list',
14
+ 'ola': 'alpha-ordered-list',
15
+ 'ol': 'ordered-list',
16
+ 'ul': 'unordered-list',
17
+ 'table': 'table',
18
+ 'tbody': 'tbody',
19
+ 'tr': 'tr',
20
+ 'td': 'td',
21
+ 'text': 'text',
22
+ 'hr': 'hr',
23
+ 'figure': 'figure',
24
+ 'figcaption': 'figcaption'
25
+ }.freeze
26
+ # Default block types list
27
+ BLOCK_ELEMENTS = %w[figure figcaption hr img li p ol ul table tbody tr td].freeze
28
+ # Default inline types list
29
+ INLINE_ELEMENTS = %w[a].freeze
30
+ # Default mark types list
31
+ MARK_ELEMENTS = {
32
+ 'em': 'italic',
33
+ 'strong': 'bold',
34
+ 'u': 'underline'
35
+ }.freeze
36
+
37
+ class << self
38
+ # Convert html to a Slate document
39
+ #
40
+ # @param html format [String] the HTML
41
+ # @param options [Hash]
42
+ # @option options [Array] :elements Lookup list to convert html tags to object types
43
+ # @option options [Array] :block_elemnts List of block types
44
+ # @option options [Array] :inline_elemnts List of inline types
45
+ # @option options [Array] :mark_elemnts List of mark types
46
+ def deserializer(html, options = {})
47
+ return empty_state if html.nil? || html == ''
48
+
49
+ self.elements = options[:elements] || ELEMENTS
50
+ self.block_elements = options[:block_elements] || BLOCK_ELEMENTS
51
+ self.inline_elements = options[:inline_elements] || INLINE_ELEMENTS
52
+ self.mark_elements = options[:mark_elements] || MARK_ELEMENTS
53
+
54
+ html = html.gsub('<br>', "\n")
55
+ Nokogiri::HTML.fragment(html).elements.map do |element|
56
+ element_to_node(element)
57
+ end
58
+ end
59
+
60
+ # Convert html to a Slate document
61
+ #
62
+ # @param value format [Hash] the Slate document
63
+ # @return [String] plain text version of the Slate documnent
64
+ def serializer(value)
65
+ return '' unless value.is_a?(Array)
66
+
67
+ value.map { |n| serialize_node(n) }.join
68
+ end
69
+
70
+ private
71
+
72
+ attr_accessor :elements, :block_elements, :inline_elements, :mark_elements
73
+
74
+ def element_to_node(element)
75
+ type = convert_name_to_type(element)
76
+ children = element.children.flat_map do |child|
77
+ if block?(child)
78
+ element_to_node(child)
79
+ elsif inline?(child)
80
+ element_to_inline(child)
81
+ else
82
+ next if child.text.strip == ''
83
+
84
+ element_to_texts(child)
85
+ end
86
+ end.compact
87
+
88
+ children << { text: '' } if children.empty? && type != 'image'
89
+
90
+ node = {
91
+ children: children,
92
+ type: type
93
+ }
94
+
95
+ type.is_a?(Proc) ? type.call(node, element) : node
96
+ end
97
+
98
+ def element_to_inline(element)
99
+ type = convert_name_to_type(element)
100
+ nodes = element.children.flat_map do |child|
101
+ element_to_texts(child)
102
+ end
103
+
104
+ {
105
+ children: nodes,
106
+ type: type
107
+ }
108
+ end
109
+
110
+ def element_to_texts(element)
111
+ nodes = []
112
+ mark = convert_name_to_mark(element.name)
113
+
114
+ if element.class == Nokogiri::XML::Element
115
+ element.children.each do |child|
116
+ nodes << element_to_text(child, mark)
117
+ end
118
+ else
119
+ nodes << element_to_text(element)
120
+ end
121
+
122
+ nodes
123
+ end
124
+
125
+ def element_to_text(element, mark = nil)
126
+ {
127
+ text: element.text
128
+ }.tap do |text|
129
+ [mark, convert_name_to_mark(element.name)].compact.each do |m|
130
+ text[m[:type].to_sym] = true
131
+ end
132
+ end
133
+ end
134
+
135
+ def convert_name_to_type(element)
136
+ type = [element.name, element.attributes['type']&.value].compact.join
137
+ elements[type.to_sym] || elements[:p]
138
+ end
139
+
140
+ def convert_name_to_mark(name)
141
+ type = mark_elements[name.to_sym]
142
+
143
+ return nil unless type
144
+
145
+ {
146
+ type: type
147
+ }
148
+ end
149
+
150
+ def block?(element)
151
+ block_elements.include?(element.name)
152
+ end
153
+
154
+ def inline?(element)
155
+ inline_elements.include?(element.name)
156
+ end
157
+
158
+ def empty_state
159
+ [
160
+ {
161
+ type: 'paragraph',
162
+ children: [
163
+ {
164
+ text: ''
165
+ }
166
+ ]
167
+ }
168
+ ]
169
+ end
170
+
171
+ def serialize_node(node)
172
+ if node[:text]
173
+ node[:text]
174
+ else
175
+ children = node[:children].map { |n| serialize_node(n) }.join
176
+
177
+ element = ELEMENTS.find { |_, v| v == node[:type] }[0]
178
+
179
+ if %i[ol1 ola].include?(element)
180
+ element = :ol
181
+ end
182
+
183
+ "<#{element}>#{children}</#{element}>"
184
+ end
185
+ end
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,69 @@
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
+ text = '' if text.nil?
11
+
12
+ lines = split_text_into_lines(text)
13
+ convert_lines_into_nodes(lines)
14
+ end
15
+
16
+ # Convert a Slate Document to plain text
17
+ #
18
+ # @param value format [Hash] the Slate document
19
+ # @param options format [Hash] options for the serializer, delimitter defaults to "\n"
20
+ # @return [String] plain text version of the Slate documnent
21
+ def serializer(value, options = {})
22
+ return '' unless value.is_a?(Array)
23
+
24
+ options[:delimiter] = "\n" unless options.key?(:delimiter)
25
+
26
+ value.map { |n| serialize_node(n, options) }.join(options[:delimiter])
27
+ end
28
+
29
+ private
30
+
31
+ def split_text_into_lines(text)
32
+ lines = text.strip.split("\n").map(&:strip)
33
+ blocks = []
34
+
35
+ loop do
36
+ index = lines.find_index('')
37
+ if index.nil?
38
+ blocks << lines.join("\n")
39
+ break
40
+ end
41
+
42
+ blocks << lines[0...index].join("\n")
43
+ lines.shift(index + 1)
44
+ end
45
+
46
+ blocks.length == 1 ? blocks : blocks.reject { |block| block == '' }
47
+ end
48
+
49
+ def convert_lines_into_nodes(lines)
50
+ lines.map do |line|
51
+ {
52
+ type: 'paragraph',
53
+ children: [
54
+ text: line
55
+ ]
56
+ }
57
+ end
58
+ end
59
+
60
+ def serialize_node(node, options)
61
+ if node[:text]
62
+ node[:text]
63
+ else
64
+ node[:children].map { |n| serialize_node(n, options) }.join(options[:delimiter])
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,3 @@
1
+ module SlateSerializer
2
+ VERSION = '1.0.0'.freeze
3
+ end
@@ -0,0 +1,7 @@
1
+ require 'slate_serializer/html'
2
+ require 'slate_serializer/plain'
3
+ require 'slate_serializer/version'
4
+
5
+ # Main module
6
+ module SlateSerializer
7
+ 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 = 'lwe_slate_serializer'
7
+ spec.version = SlateSerializer::VERSION
8
+ spec.authors = ['Wesley Stam', 'Paul Crabtree']
9
+ spec.email = ['wesley@stam.me', 'paul@learningwithexperts.com']
10
+ spec.license = 'MIT'
11
+
12
+ spec.summary = 'Serializer for Slate documents written in Ruby'
13
+ spec.homepage = 'https://github.com/learningwithexperts/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.11'
25
+ spec.add_development_dependency 'bundler', '~> 2.2'
26
+ spec.add_development_dependency 'rake', '~> 13.0'
27
+ spec.add_development_dependency 'rspec', '~> 3.0'
28
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lwe_slate_serializer
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Wesley Stam
8
+ - Paul Crabtree
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2022-03-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.11'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.11'
28
+ - !ruby/object:Gem::Dependency
29
+ name: bundler
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '2.2'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '2.2'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rake
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '13.0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '13.0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rspec
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '3.0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '3.0'
70
+ description:
71
+ email:
72
+ - wesley@stam.me
73
+ - paul@learningwithexperts.com
74
+ executables: []
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - ".gitignore"
79
+ - ".rspec"
80
+ - ".ruby-version"
81
+ - ".travis.yml"
82
+ - Gemfile
83
+ - Gemfile.lock
84
+ - README.md
85
+ - Rakefile
86
+ - bin/console
87
+ - bin/setup
88
+ - lib/slate_serializer.rb
89
+ - lib/slate_serializer/html.rb
90
+ - lib/slate_serializer/plain.rb
91
+ - lib/slate_serializer/version.rb
92
+ - slate_serializer.gemspec
93
+ homepage: https://github.com/learningwithexperts/slate_serializer
94
+ licenses:
95
+ - MIT
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubygems_version: 3.3.8
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: Serializer for Slate documents written in Ruby
116
+ test_files: []