draftjs_html 0.24.0 → 0.26.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7c2703fb050f796abd4f8af851d16b654a2ab84f03e5f8865c92b373b2acfefa
4
- data.tar.gz: eced6f85cfefd34f4c50c7fc383526675f26dd7c212a4f7de145721d254b1a28
3
+ metadata.gz: 9fe4601ed10ebae8924fe906ffad4cd56bebf7867ec80182876ad0a1b5a3b739
4
+ data.tar.gz: 5d14c45c7192c936fbbe524a72c4886acddaf20f1f2dff5ccf9c1ce3d8de8a5f
5
5
  SHA512:
6
- metadata.gz: 432d7b8900153f89f8ba506ded86208fe71a4b6b832911693059e0f57cb31b93412ef8fa5a40a8f7d857b370b65e8a523f29d0029dfa2ee8f917ebae2235827e
7
- data.tar.gz: 69878d4330ef0d4947f1d95ed165720c0a59b8c0d54793d2e28aad8f5fea40754f95afacc1fc1a29c5b5b9f03e02399d9502924c7c580e7bc953b674f6292644
6
+ metadata.gz: 38f78c86afbac0244a8eb967be90c6b647001e6a3bbbe3a6648190a45ac9cbecc2359c45f1fee5f995ed9584d037b2c337b8e267dece3c38e15a16a4dde8b775
7
+ data.tar.gz: 249423024673740842728d7b5cb8ca4ef1aa9bec1ee521be4402e21d5d89afa7f36563232de9c6af62831ae9cac3768c654537d75a8dbb44e25735f4d2dc0ac1
@@ -0,0 +1,36 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+ workflow_dispatch:
7
+ # schedule:
8
+ # - cron: '42 5 * * *'
9
+
10
+ jobs:
11
+ test:
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ ruby: [ '3.0' ]
16
+
17
+ runs-on: ubuntu-latest
18
+ name: Ruby ${{matrix.ruby}}
19
+ container: ruby:${{matrix.ruby}}
20
+
21
+ steps:
22
+ - uses: actions/checkout@v3
23
+
24
+ - name: Show ruby Version
25
+ run: |
26
+ ruby -v
27
+
28
+ - name: Install Modules
29
+ run: |
30
+ ./bin/setup
31
+
32
+ - name: Run tests
33
+ run: |
34
+ rake spec
35
+
36
+
data/README.md CHANGED
@@ -229,14 +229,43 @@ The callable should return a Hash with symbol keys. The supported values are:
229
229
  - `data` (optional, default `{}`)
230
230
  - an arbitrary data-bag (Hash) of entity data
231
231
 
232
- #### `:is_semantic_markup:`
232
+ ### Spec support
233
233
 
234
- Defaults to `true`.
234
+ To make it easier to test our own code, we've developed a few RSpec matchers that
235
+ make normalization and comparison of raw DraftJS use the RawBuilder DSL. To take
236
+ advantage of this, you can (for RSpec only, currently) include the following in
237
+ your `spec_helper`, or equivalent.
235
238
 
236
- By setting to `false`, the user is stating they want to treat `div` tags as semantic,
237
- block-level tags. In some markup (emails, for example), there are no semantic tags
238
- (read, no `p` tags), so the only indications of whitespace and structure come from
239
- `div` tags. This flag will flush content wrapped in a `div` as a DraftJS block.
239
+ ```ruby
240
+ require 'draftjs_html/spec_support/rspec'
241
+
242
+ RSpec.configure do |config|
243
+ config.include DraftjsHtml::SpecSupport::RSpecMatchers
244
+ end
245
+ ```
246
+
247
+ Then, later in your tests, you can assert on raw DraftJS "json" like this:
248
+
249
+ ```ruby
250
+ my_raw_draftjs_hash = { blocks: [{ key: 'a-random-uuid', text: 'Hi!' }], entityMap: {} }
251
+
252
+ expect(my_raw_draftjs_hash).to eq_raw_draftjs {
253
+ text_block 'Hi!'
254
+ }
255
+ ```
256
+
257
+ This will normalize the `key` values and other IDs to make _actual_ differences
258
+ easier to spot.
259
+
260
+ There's also a matcher called `eq_raw_draftjs_ignoring_keys` that takes an explicit
261
+ raw DraftJS hash on both sides.
262
+
263
+ ```ruby
264
+ my_raw_draftjs_hash = { blocks: [{ key: 'a-random-uuid', text: 'Hi!' }], entityMap: {} }
265
+ my_other_draftjs_hash = { blocks: [{ key: 'a-different-random-uuid', text: 'Hi!' }], entityMap: {} }
266
+
267
+ expect(my_raw_draftjs_hash).to eq_raw_draftjs_ignoring_keys my_other_draftjs_hash
268
+ ```
240
269
 
241
270
  ## Development
242
271
 
@@ -60,6 +60,10 @@ module DraftjsHtml
60
60
  size > 0
61
61
  end
62
62
 
63
+ def more_than_whitespace?
64
+ !text.match?(/^[[:space:]]*$/)
65
+ end
66
+
63
67
  def atomic?
64
68
  @chars.any? && @chars.all?(&:atomic?)
65
69
  end
@@ -1,16 +1,16 @@
1
1
  module DraftjsHtml
2
2
  class FromHtml < Nokogiri::XML::SAX::Document
3
3
  class DepthStack
4
- def initialize(is_semantic_markup: true)
4
+ def initialize(options)
5
5
  @stack = []
6
6
  @nodes = []
7
7
  @list_depth = -1
8
8
  @active_styles = []
9
- @is_semantic_markup = is_semantic_markup
9
+ @options = options
10
10
  end
11
11
 
12
12
  def push(tagname, attrs)
13
- @stack << PendingBlock.from_tag(tagname, attrs, @nodes.dup, @list_depth, is_semantic_markup: @is_semantic_markup)
13
+ @stack << PendingBlock.from_tag(tagname, attrs, @nodes.dup, @list_depth, options: @options)
14
14
  track_block_node(tagname)
15
15
  end
16
16
 
@@ -1,8 +1,9 @@
1
1
  module DraftjsHtml
2
2
  class FromHtml < Nokogiri::XML::SAX::Document
3
3
  INLINE_STYLE_ELEMENTS = HtmlDefaults::HTML_STYLE_TAGS_TO_STYLE.keys.freeze
4
- LIST_PARENT_ELEMENTS = %w[ol ul table].freeze
5
- INLINE_NON_STYLE_ELEMENTS = %w[a abbr cite font img output q samp span thead tbody td time var].freeze
4
+ LIST_PARENT_ELEMENTS = %w[ol ul].freeze
5
+ INLINE_NON_STYLE_ELEMENTS = %w[a abbr cite font img output q samp span table thead tbody td time var].freeze
6
6
  BLOCK_CONTENT_ELEMENTS = %w[p dl h1 h2 h3 h4 h5 h6].freeze
7
+ FLUSH_BOUNDARIES = %w[OPENING div ol ul li tr].freeze
7
8
  end
8
9
  end
@@ -1,7 +1,7 @@
1
1
  module DraftjsHtml
2
2
  class FromHtml < Nokogiri::XML::SAX::Document
3
- PendingBlock = Struct.new(:tagname, :attrs, :chars, :entities, :pending_entities, :parent_tagnames, :depth, :is_semantic_markup, keyword_init: true) do
4
- def self.from_tag(name, attrs, parent_tagnames, depth, is_semantic_markup: true)
3
+ PendingBlock = Struct.new(:tagname, :attrs, :chars, :entities, :pending_entities, :parent_tagnames, :depth, :options, keyword_init: true) do
4
+ def self.from_tag(name, attrs, parent_tagnames, depth, options: {})
5
5
  self.new(
6
6
  tagname: name,
7
7
  attrs: attrs,
@@ -10,7 +10,7 @@ module DraftjsHtml
10
10
  pending_entities: [],
11
11
  depth: depth,
12
12
  parent_tagnames: parent_tagnames,
13
- is_semantic_markup: is_semantic_markup,
13
+ options: options
14
14
  )
15
15
  end
16
16
 
@@ -23,9 +23,7 @@ module DraftjsHtml
23
23
  end
24
24
 
25
25
  def flushable?
26
- %w[OPENING ol ul li table].include?(parent_tagnames.last) ||
27
- (parent_tagnames.last == 'div' && tagname != 'div') ||
28
- (!is_semantic_markup && tagname == 'div')
26
+ FLUSH_BOUNDARIES.include?(parent_tagnames.last)
29
27
  end
30
28
 
31
29
  def consume(other_pending_block)
@@ -35,21 +33,23 @@ module DraftjsHtml
35
33
  end
36
34
 
37
35
  def flush_to(draftjs)
38
- if text_buffer.any?
39
- text_buffer.each_line do |line|
40
- block_type = line.atomic? ? 'atomic' : block_name
41
- draftjs.typed_block(block_type, line.text, depth: [depth, 0].max)
36
+ text_buffer.each_line do |line|
37
+ block_type = line.atomic? ? 'atomic' : block_name
38
+ next unless should_flush_line?(line)
42
39
 
43
- line.entity_ranges.each do |entity_range|
44
- entity = entity_range.entity
45
- draftjs.apply_entity entity[:type], entity_range.range, data: entity[:data], mutability: entity.fetch(:mutability, 'IMMUTABLE')
46
- end
40
+ draftjs.typed_block(block_type, line.text, depth: [depth, 0].max)
47
41
 
48
- line.style_ranges.each do |style_range|
49
- draftjs.inline_style(style_range.style, style_range.range)
50
- end
42
+ line.entity_ranges.each do |entity_range|
43
+ entity = entity_range.entity
44
+ draftjs.apply_entity entity[:type], entity_range.range, data: entity[:data], mutability: entity.fetch(:mutability, 'IMMUTABLE')
45
+ end
46
+
47
+ line.style_ranges.each do |style_range|
48
+ draftjs.inline_style(style_range.style, style_range.range)
51
49
  end
52
50
  end
51
+
52
+ self.text_buffer = CharList.new
53
53
  end
54
54
 
55
55
  def block_name
@@ -65,6 +65,13 @@ module DraftjsHtml
65
65
  def text_buffer=(other)
66
66
  self[:chars] = other
67
67
  end
68
+
69
+ def should_flush_line?(chars)
70
+ return true if chars.atomic?
71
+ return true unless options[:squeeze_whitespace_blocks]
72
+
73
+ options[:squeeze_whitespace_blocks] && chars.more_than_whitespace?
74
+ end
68
75
  end
69
76
  end
70
77
  end
@@ -11,8 +11,8 @@ module DraftjsHtml
11
11
  def initialize(options = {})
12
12
  @draftjs = Draftjs::RawBuilder.new
13
13
  @parser = Nokogiri::HTML4::SAX::Parser.new(self)
14
- @depth_stack = DepthStack.new(is_semantic_markup: options.fetch(:is_semantic_markup, true))
15
14
  @options = ensure_options!(options.dup)
15
+ @depth_stack = DepthStack.new(@options)
16
16
  end
17
17
 
18
18
  def convert(raw_html)
@@ -56,6 +56,7 @@ module DraftjsHtml
56
56
  when *FromHtml::LIST_PARENT_ELEMENTS
57
57
  @depth_stack.push_parent(name, attrs)
58
58
  else
59
+ @depth_stack.flush_to(@draftjs) if FromHtml::FLUSH_BOUNDARIES.include?(name)
59
60
  @depth_stack.push(name, attributes)
60
61
  end
61
62
 
@@ -101,6 +102,7 @@ module DraftjsHtml
101
102
  when 'img' then { type: 'IMAGE', mutability: 'IMMUTABLE', atomic: true, data: attrs }
102
103
  end
103
104
  }
105
+ opts[:squeeze_whitespace_blocks] ||= false
104
106
  opts
105
107
  end
106
108
  end
@@ -1,6 +1,7 @@
1
1
  module DraftjsHtml
2
2
  module HtmlDefaults
3
3
  BLOCK_TYPE_TO_HTML = {
4
+ 'article' => 'p',
4
5
  'paragraph' => 'p',
5
6
  'unstyled' => 'p',
6
7
  'header-one' => 'h1',
@@ -0,0 +1,42 @@
1
+ require 'rspec/expectations'
2
+ require 'draftjs_html/spec_support'
3
+
4
+ module DraftjsHtml
5
+ module SpecSupport
6
+ module RSpecMatchers
7
+ extend RSpec::Matchers::DSL
8
+
9
+ matcher :eq_raw_draftjs do |expected|
10
+ include DraftjsHtml::SpecSupport::KeyNormalization
11
+ match do |actual|
12
+ @raw_draftjs = normalize_keys(DraftjsHtml::Draftjs::RawBuilder.build(&block_arg))
13
+ @actual = normalize_keys(actual)
14
+
15
+ values_match?(@raw_draftjs, @actual)
16
+ end
17
+
18
+ diffable
19
+
20
+ def expected
21
+ @raw_draftjs
22
+ end
23
+ end
24
+
25
+ matcher :eq_raw_draftjs_ignoring_keys do |expected|
26
+ include DraftjsHtml::SpecSupport::KeyNormalization
27
+ match do |actual|
28
+ @raw_draftjs = normalize_keys(expected)
29
+ @actual = normalize_keys(actual)
30
+
31
+ values_match?(@raw_draftjs, @actual)
32
+ end
33
+
34
+ diffable
35
+
36
+ def expected
37
+ @raw_draftjs
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DraftjsHtml
4
+ module SpecSupport
5
+ module KeyNormalization
6
+ def normalize_keys(raw_draftjs)
7
+ draftjs = DraftjsHtml::Draftjs::Content.parse(raw_draftjs)
8
+ draftjs.blocks.each.with_index do |block, i|
9
+ block.key = "block-key-#{i}"
10
+ end
11
+
12
+ draftjs.entity_map.keys.each.with_index do |entity_key, i|
13
+ new_key = "entity-key-#{i}"
14
+ draftjs.entity_map[new_key] = draftjs.entity_map.delete(entity_key)
15
+ matching_entity_ranges = draftjs.blocks.flat_map { |block| block.raw_entity_ranges.select { |entity_range| entity_range['key'] == entity_key } }
16
+ matching_entity_ranges.each { |range| range['key'] = new_key }
17
+ end
18
+
19
+ DraftjsHtml::Draftjs::ToRaw.new.convert(draftjs)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DraftjsHtml
4
- VERSION = "0.24.0"
4
+ VERSION = "0.26.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: draftjs_html
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.24.0
4
+ version: 0.26.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - TJ Taylor
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-12-19 00:00:00.000000000 Z
11
+ date: 2023-01-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -45,6 +45,7 @@ executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files: []
47
47
  files:
48
+ - ".github/workflows/ci.yml"
48
49
  - ".gitignore"
49
50
  - ".rspec"
50
51
  - ".travis.yml"
@@ -76,6 +77,8 @@ files:
76
77
  - lib/draftjs_html/html_depth.rb
77
78
  - lib/draftjs_html/node.rb
78
79
  - lib/draftjs_html/overrideable_map.rb
80
+ - lib/draftjs_html/spec_support.rb
81
+ - lib/draftjs_html/spec_support/rspec.rb
79
82
  - lib/draftjs_html/to_html.rb
80
83
  - lib/draftjs_html/version.rb
81
84
  homepage: https://github.com/dugancathal/draftjs_html