markdown-tables 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/markdown-tables.rb +146 -79
  3. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d81c56a6b5704f57fe1b02ecf891051306873b50
4
- data.tar.gz: 78e3d1343aaadb46e5ea768b498960c73f1ea699
3
+ metadata.gz: ce5cc9285eabf5477a6520866af564cd1d8f90b6
4
+ data.tar.gz: 73042b5f303ff8d1c703a67d62244937206845f1
5
5
  SHA512:
6
- metadata.gz: f31cc74738da99e034bfef0791247d24c7bba6425295c183f95cd2f4ff0928f78bfec11747ebb078c2de6d6cec314a4f8fdec350200458f0721120658dfcb0c5
7
- data.tar.gz: 6295dd0283ae39e794cec164469114faa379331271c46ee364d8b7d4c9b88909a7bc8e28e0e5ec68ce78bac94264b2429fe20b49055872c52ba55ce24657b1e3
6
+ metadata.gz: 0d8a6a6fa9cd1029568c54c2e6da2d0145c5b06f6a9a0f68c9e09240bc0d3c6d4c26533d4c676a1f91385294893da1f6eab01e9affc0e6730e6c90079af52f54
7
+ data.tar.gz: 56ac0af7a9e34b01ae7f2dfb0a2dd7c285cb06f9d3a86434268d4299aad09346004074411c04eafd7edc16ddd7ef1572c5797b69588851f3eeec33906685280a
@@ -1,89 +1,156 @@
1
- # Sanity checks for make_table.
2
- def validate(labels, data, align, is_rows)
3
- if labels.class != Array
4
- raise('labels must be an Array')
5
- elsif data.class != Array || data.any? {|datum| datum.class != Array}
6
- raise('data must be a two-dimensional array')
7
- elsif labels.empty?
8
- raise('No column labels given')
9
- elsif data.empty?
10
- raise('No columns given')
11
- elsif data.all? {|datum| datum.empty?}
12
- raise('No cells given')
13
- elsif labels.any? {|label| !label.respond_to?(:to_s)}
14
- raise('One or more column labels cannot be made into a string')
15
- elsif data.any? {|datum| datum.any? {|cell| !cell.respond_to?(:to_s)}}
16
- raise('One or more cells cannot be made into a string')
17
- elsif ![String, Array].include?(align.class)
18
- raise('align must be a String or Array')
19
- elsif align.class == Array && align.any? {|val| val.class != String}
20
- raise('One or more align values is not a String')
21
- elsif !is_rows && data.length > labels.length
22
- raise('Too many data columns given')
23
- elsif is_rows && data.any? {|row| row.length > labels.length}
24
- raise('One or more rows has too many cells')
1
+ class MarkdownTables
2
+
3
+ # Generate a Markdown table.
4
+ # labels and data are one and two-dimensional arrays, respectively.
5
+ # All input must have a to_s method.
6
+ # Pass align: 'l' for left alignment or 'r' for right alignment. Anything
7
+ # else will result in cells being centered. Pass an array of align values
8
+ # to specify alignment per column.
9
+ # If is_rows is true, then each sub-array represents a row.
10
+ # Conversely, if is_rows is false, each sub-array of data represents a column.
11
+ # Empty cells can be given with nil or an empty string.
12
+ def self.make_table(labels, data, align: '', is_rows: false)
13
+ labels = Marshal.load(Marshal.dump(labels))
14
+ data = Marshal.load(Marshal.dump(data))
15
+ validate(labels, data, align, is_rows)
16
+ sanitize!(labels, data)
17
+
18
+ header_line = labels.join('|')
19
+ alignment_line = alignment(align, labels.length)
20
+
21
+ if is_rows
22
+ rows = data.map {|row| row.join('|')}
23
+ else
24
+ max_len = data.map(&:size).max
25
+ rows = []
26
+ max_len.times do |i|
27
+ row = []
28
+ data.each {|col| row.push(col[i])}
29
+ rows.push(row.join('|'))
30
+ end
31
+ end
32
+
33
+ return [header_line, alignment_line, rows.join("\n")].join("\n")
25
34
  end
26
- end
27
35
 
28
- # Convert all input to strings and replace any '|' characters with
29
- # non-breaking equivalents,
30
- def sanitize!(labels, data)
31
- bar = '|' # Non-breaking HTML vertical bar.
32
- labels.map! {|label| label.to_s.gsub('|', bar)}
33
- data.length.times {|i| data[i].map! {|cell| cell.to_s.gsub('|', bar)}}
34
- end
36
+ # Convert a Markdown table into human-readable form.
37
+ def self.plain_text(md_table)
38
+ lines = md_table.split("\n")
39
+ labels = lines[0].split('|')
40
+ alignments = lines[1].split('|')
41
+ rows = lines[2..-1].map {|line| line.split('|')}
42
+
43
+ # Replace non-breaking HTML characters with their plaintext counterparts.
44
+ rows.each do |row|
45
+ row.each do |cell|
46
+ cell.gsub!(/( )|(|)/, ' ' => ' ', '|' => '|')
47
+ end
48
+ end
49
+
50
+ # Get the width for each column.
51
+ widths = labels.map(&:length) # Lengths of each column's longest element.
52
+ rows.length.times do |i|
53
+ rows[i].length.times do |j|
54
+ rows[i][j].length > widths[j] && widths[j] = rows[i][j].length
55
+ end
56
+ end
57
+ widths.map! {|w| w + 2} # Add padding on each side.
58
+
59
+ # Align the column labels.
60
+ labels.length.times do |i|
61
+ label_length = labels[i].length
62
+ start = align_cell(label_length, widths[i], alignments[i])
63
+
64
+ labels[i].prepend(' ' * start)
65
+ labels[i] += ' ' * (widths[i] - start - label_length)
66
+ end
35
67
 
36
- # Generate the alignment line from a string or array.
37
- # align must be a string or array or strings.
38
- # n: number of labels in the table to be created.
39
- def alignment(align, n)
40
- if align.class == String
41
- alignment = align == 'l' ? ':-' : align == 'r' ? '-:' : ':-:'
42
- alignment_line = ([alignment] * n).join('|')
43
- else
44
- alignments = align.map {
45
- |a| a.downcase == 'l' ? ':-' : a.downcase == 'r' ? '-:' : ':-l'
46
- }
47
- if alignments.length < n
48
- alignments += [':-:'] * (n - alignments.length)
68
+ # Align the cells.
69
+ rows.each do |row|
70
+ row.length.times do |i|
71
+ cell_length = row[i].length
72
+ start = align_cell(cell_length, widths[i], alignments[i])
73
+ row[i].prepend(' ' * start)
74
+ row[i] += ' ' * (widths[i] - start - cell_length)
75
+ end
49
76
  end
50
- alignment_line = alignments.join('|')
77
+
78
+ border = "\n|" + widths.map {|w| '=' * w}.join('|') + "|\n"
79
+ separator = border.gsub('=', '-')
80
+
81
+ table = border[1..-1] # Don't include the first newline.
82
+ table += '|' + labels.join('|') + '|'
83
+ table += border
84
+ table += rows.map {|row| '|' + row.join('|') + '|'}.join(separator)
85
+ table += border
86
+
87
+ return table.chomp
51
88
  end
52
- return alignment_line
53
- end
54
89
 
55
- # Generate a Markdown table.
56
- # labels and data are one and two-dimensional arrays, respectively.
57
- # All input must have a to_s method.
58
- # Pass align: 'l' for left alignment or 'r' for right alignment. Anything
59
- # else will result in cells being centered. Pass an array of align values
60
- # to specify alignment per column.
61
- # If is_rows is true, then each sub-array represents a row.
62
- # Conversely, if is_rows is false, each sub-array of data represents a column.
63
- # Empty cells can be given with nil or an empty string.
64
- def make_table(labels, data, align: '', is_rows: false)
65
- labels = Marshal.load(Marshal.dump(labels))
66
- data = Marshal.load(Marshal.dump(data))
67
- validate(labels, data, align, is_rows)
68
- sanitize!(labels, data)
69
-
70
- header_line = labels.join('|')
71
- alignment_line = alignment(align, labels.length)
72
-
73
- if is_rows
74
- rows = data.map {|row| row.join('|')}
75
- else
76
- max_len = data.map(&:size).max
77
- rows = []
78
- max_len.times do |i|
79
- row = []
80
- data.each {|col| row.push(col[i])}
81
- rows.push(row.join('|'))
90
+ # Sanity checks for make_table.
91
+ private_class_method def self.validate(labels, data, align, is_rows)
92
+ if labels.class != Array
93
+ raise('labels must be an Array')
94
+ elsif data.class != Array || data.any? {|datum| datum.class != Array}
95
+ raise('data must be a two-dimensional array')
96
+ elsif labels.empty?
97
+ raise('No column labels given')
98
+ elsif data.empty?
99
+ raise('No columns given')
100
+ elsif data.all? {|datum| datum.empty?}
101
+ raise('No cells given')
102
+ elsif labels.any? {|label| !label.respond_to?(:to_s)}
103
+ raise('One or more column labels cannot be made into a string')
104
+ elsif data.any? {|datum| datum.any? {|cell| !cell.respond_to?(:to_s)}}
105
+ raise('One or more cells cannot be made into a string')
106
+ elsif ![String, Array].include?(align.class)
107
+ raise('align must be a String or Array')
108
+ elsif align.class == Array && align.any? {|val| val.class != String}
109
+ raise('One or more align values is not a String')
110
+ elsif !is_rows && data.length > labels.length
111
+ raise('Too many data columns given')
112
+ elsif is_rows && data.any? {|row| row.length > labels.length}
113
+ raise('One or more rows has too many cells')
82
114
  end
83
115
  end
84
116
 
85
- return [header_line, alignment_line, rows.join("\n")].join("\n")
86
- end
117
+ # Convert all input to strings and replace any '|' characters with
118
+ # non-breaking equivalents,
119
+ private_class_method def self.sanitize!(labels, data)
120
+ bar = '&#124;' # Non-breaking HTML vertical bar.
121
+ labels.map! {|label| label.to_s.gsub('|', bar)}
122
+ data.length.times {|i| data[i].map! {|cell| cell.to_s.gsub('|', bar)}}
123
+ end
87
124
 
88
- # Print out a Markdown table in human-readable form.
89
- def print_table(table) end
125
+ # Generate the alignment line from a string or array.
126
+ # align must be a string or array or strings.
127
+ # n: number of labels in the table to be created.
128
+ private_class_method def self.alignment(align, n)
129
+ if align.class == String
130
+ alignment = align == 'l' ? ':-' : align == 'r' ? '-:' : ':-:'
131
+ alignment_line = ([alignment] * n).join('|')
132
+ else
133
+ alignments = align.map {
134
+ |a| a.downcase == 'l' ? ':-' : a.downcase == 'r' ? '-:' : ':-:'
135
+ }
136
+ if alignments.length < n
137
+ alignments += [':-:'] * (n - alignments.length)
138
+ end
139
+ alignment_line = alignments.join('|')
140
+ end
141
+ return alignment_line
142
+ end
143
+
144
+ # Get the starting index of a cell's text from the text's length, the cell's
145
+ # width, and the alignment.
146
+ private_class_method def self.align_cell(length, width, align)
147
+ if align =~ /:-+:/
148
+ return (width / 2) - (length / 2)
149
+ elsif align =~ /-+:/
150
+ return width - length - 1
151
+ else
152
+ return 1
153
+ end
154
+ end
155
+
156
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: markdown-tables
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris de Graaf
@@ -29,7 +29,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: '0'
32
+ version: 2.1.0
33
33
  required_rubygems_version: !ruby/object:Gem::Requirement
34
34
  requirements:
35
35
  - - ">="
@@ -40,5 +40,5 @@ rubyforge_project:
40
40
  rubygems_version: 2.6.8
41
41
  signing_key:
42
42
  specification_version: 4
43
- summary: Utilities for creating and displaying Markdown tables in Ruby
43
+ summary: Utilities for creating and displaying Markdown tables in Ruby.
44
44
  test_files: []