marktable 0.1.1 → 0.1.2

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: 776f59a6e0c0ee0b8e52f3fd4b9dd7a8ae8e1acbb93ff98504bb382dfecc93e9
4
- data.tar.gz: 8df1d4b723562ced9f83e172165ed07d934e95fe2d9fe7c39411371b960dadfb
3
+ metadata.gz: e7f873538494ff9b1c7c9a5f74b25560c0a329e13ae77ab2648cedbe46dba1e7
4
+ data.tar.gz: 0bfc592905ad86578cf9fcfd953ffd589aebada3120d1f460e0c61818a5bea44
5
5
  SHA512:
6
- metadata.gz: ed5b2e94ca382771d81d5c6423fa43e38dded1cbfe315c6fedd098b0f77efc66d18b7e62372f8ac2e16884a3d3495f5631fee13b96623d8575276e8b6827b619
7
- data.tar.gz: 28d859a6e6c1709ee0be5c3ff7f63fd91f87688d6c5169d0193790889e590ce4b0602afa7c1a5f48693227bf963cca9396a26900f037899351d4c54c69783833
6
+ metadata.gz: da0ff6b0f29523c3b7cd99d31fe08d4cf0c79fb52bca4eb2603096396c560cf1734bf33b21990ba449c73a3b476d71d9985c62e743e8cd3525bd72d45c605937
7
+ data.tar.gz: cb6f9e8813e96393110f52a591d7a61a5b4e66d407db33fee2a8a52f347a934cb9586838d801195248b441b8999cee817819bfda83410faf7db0ff48d2738d0b
data/README.md CHANGED
@@ -60,8 +60,8 @@ expect(html_table).to match_markdown(expected_markdown)
60
60
  ```ruby
61
61
  # From markdown to other formats
62
62
  markdown = <<~MARKDOWN
63
- | Name | Age |
64
- |------|----- |
63
+ | Name | Age |
64
+ |------ | --- |
65
65
  | Alice | 30 |
66
66
  | Bob | 25 |
67
67
  MARKDOWN
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../rspec'
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'capybara'
4
+ require 'nokogiri'
5
+ require 'marktable'
6
+
7
+ # Register the matchers if RSpec is defined
8
+ if defined?(RSpec)
9
+ RSpec::Matchers.define :match_markdown do |expected_markdown|
10
+ chain :with_format do |format|
11
+ @format = format
12
+ end
13
+
14
+ match do |actual|
15
+ @expected_data = parse_input(expected_markdown, :markdown)
16
+ @format ||= infer_format(actual)
17
+ @actual_data = parse_input(actual, @format)
18
+
19
+ # Compare data using to_a for consistent comparison
20
+ @actual_data.to_a == @expected_data.to_a
21
+ end
22
+
23
+ failure_message do
24
+ format_failure_message(@expected_data, @actual_data)
25
+ end
26
+
27
+ failure_message_when_negated do
28
+ "Expected markdown tables to differ, but they match:\n\n" \
29
+ "#{@actual_data.to_md}"
30
+ end
31
+
32
+ private
33
+
34
+ def parse_input(input, format = nil)
35
+ return input if input.is_a?(Marktable::Table)
36
+
37
+ # Handle both Capybara::Node::Element and Capybara::Node::Simple
38
+ if capybara?(input)
39
+ # Convert Capybara element to Nokogiri element or HTML
40
+ input = input.native
41
+ format = :html
42
+ end
43
+
44
+ # Handle Nokogiri elements
45
+ if nokogiri?(input)
46
+ input = input.to_html
47
+ format = :html
48
+ end
49
+
50
+ Marktable::Table.new(input, type: format)
51
+ end
52
+
53
+ def html?(data)
54
+ nokogiri?(data) || capybara?(data)
55
+ end
56
+
57
+ def capybara?(data)
58
+ defined?(Capybara::Node::Base) && data.is_a?(Capybara::Node::Base) ||
59
+ defined?(Capybara::Node::Simple) && data.is_a?(Capybara::Node::Simple) ||
60
+ defined?(Capybara::Node::Element) && data.is_a?(Capybara::Node::Element)
61
+ end
62
+
63
+ def nokogiri?(data)
64
+ defined?(Nokogiri::XML::Node) && data.is_a?(Nokogiri::XML::Node)
65
+ end
66
+
67
+ def infer_format(data)
68
+ case data
69
+ when Array
70
+ :array
71
+ when CSV::Table
72
+ :csv
73
+ when Marktable::Table
74
+ :markdown
75
+ when html?(data)
76
+ :html
77
+ else
78
+ :markdown
79
+ end
80
+ end
81
+
82
+ def format_failure_message(expected_data, actual_data)
83
+ "Expected markdown table to match:\n\n" \
84
+ "Expected:\n#{expected_data.to_md}\n\n" \
85
+ "Actual:\n#{actual_data.to_md}\n\n" \
86
+ "Parsed expected data: #{expected_data.to_a.inspect}\n" \
87
+ "Parsed actual data: #{actual_data.to_a.inspect}"
88
+ end
89
+ end
90
+ end
@@ -14,7 +14,7 @@ module Marktable
14
14
  end
15
15
 
16
16
  def parse
17
- return blank if table.nil? || rows.empty?
17
+ return Tables::Base.blank if table.nil? || rows.empty?
18
18
 
19
19
  if has_headers?
20
20
  headers = extract_row_cells(first_row)
@@ -48,7 +48,31 @@ module Marktable
48
48
  end
49
49
 
50
50
  def extract_row_cells(row)
51
- row.css('th, td').map(&:text)
51
+ row.css('th, td').map do |cell|
52
+ # Get text content
53
+ text = cell.text
54
+
55
+ # Handle JSON content specially to preserve important whitespace
56
+ if text.include?('{') && text.include?('}')
57
+ # Process JSON content more carefully
58
+ # 1. Remove newlines
59
+ # 2. Preserve spaces between JSON delimiters
60
+ # 3. Normalize other whitespace
61
+ json_content = text.gsub(/\r?\n/, ' ') # Replace newlines with spaces
62
+ .gsub(/(\{)\s*/, '\1 ') # Ensure exactly one space after opening brace
63
+ .gsub(/\s*(\})/, ' \1') # Ensure exactly one space before closing brace
64
+ .gsub(/\s+/, ' ') # Collapse other consecutive whitespace
65
+ .gsub(/\A\s+|\s+\z/, '') # Trim leading/trailing whitespace
66
+ .gsub(/\u00A0/, ' ') # Replace &nbsp; with spaces
67
+ json_content
68
+ else
69
+ # For regular content
70
+ text.gsub(/\r?\n/, '') # Remove all newlines completely
71
+ .gsub(/\s+/, ' ') # Collapse consecutive whitespace
72
+ .gsub(/\A\s+|\s+\z/, '') # Trim leading/trailing whitespace
73
+ .gsub(/\u00A0/, ' ') # Replace &nbsp; with spaces
74
+ end
75
+ end
52
76
  end
53
77
 
54
78
  def first_row
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Marktable
4
- VERSION = '0.1.1'
4
+ VERSION = '0.1.2'
5
5
  end
data/lib/marktable.rb CHANGED
@@ -22,3 +22,5 @@ module Marktable
22
22
  Table.new(table, type: :html)
23
23
  end
24
24
  end
25
+
26
+ require_relative 'marktable/rspec' if defined?(RSpec) || defined?(::RSpec::Core)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marktable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Francois Gaspard
@@ -67,6 +67,8 @@ files:
67
67
  - lib/marktable/formatters/html.rb
68
68
  - lib/marktable/formatters/markdown.rb
69
69
  - lib/marktable/row.rb
70
+ - lib/marktable/rspec.rb
71
+ - lib/marktable/rspec/init.rb
70
72
  - lib/marktable/table.rb
71
73
  - lib/marktable/tables/array.rb
72
74
  - lib/marktable/tables/base.rb
@@ -74,7 +76,6 @@ files:
74
76
  - lib/marktable/tables/html.rb
75
77
  - lib/marktable/tables/markdown.rb
76
78
  - lib/marktable/version.rb
77
- - spec/support/matchers/markdown_matchers.rb
78
79
  homepage: https://github.com/Francois-gaspard/marktable
79
80
  licenses:
80
81
  - MIT
@@ -1,57 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'capybara'
4
- require 'nokogiri'
5
-
6
- RSpec::Matchers.define :match_markdown do |expected_markdown|
7
- chain :with_format do |format|
8
- @format = format
9
- end
10
-
11
- match do |actual|
12
- @expected_data = parse_input(expected_markdown, :markdown)
13
- @format ||= infer_format(actual)
14
- @actual_data = parse_input(actual, @format)
15
-
16
- # Compare data using to_a for consistent comparison
17
- @actual_data.to_a == @expected_data.to_a
18
- end
19
-
20
- failure_message do
21
- format_failure_message(@expected_data, @actual_data)
22
- end
23
-
24
- failure_message_when_negated do
25
- "Expected markdown tables to differ, but they match:\n\n" \
26
- "#{@actual_data.to_md}"
27
- end
28
-
29
- private
30
-
31
- def parse_input(input, format = nil)
32
- return input if input.is_a?(Marktable::Table)
33
-
34
- Marktable::Table.new(input, type: format)
35
- end
36
-
37
- def infer_format(data)
38
- case data
39
- when Array
40
- :array
41
- when CSV::Table
42
- :csv
43
- when Marktable::Table
44
- :markdown
45
- else
46
- :markdown
47
- end
48
- end
49
-
50
- def format_failure_message(expected_data, actual_data)
51
- "Expected markdown table to match:\n\n" \
52
- "Expected:\n#{expected_data.to_md}\n\n" \
53
- "Actual:\n#{actual_data.to_md}\n\n" \
54
- "Parsed expected data: #{expected_data.to_a.inspect}\n" \
55
- "Parsed actual data: #{actual_data.to_a.inspect}"
56
- end
57
- end