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 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
@@ -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
+ 2.6.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,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
@@ -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,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,3 @@
1
+ module SlateSerializer
2
+ VERSION = '0.1.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 = '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: []