text_alignment 0.5 → 0.6.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: 9f5f7f27c8628123530d51d0a68060aa6fb850bcef8c7089c8bf990f7257a80b
4
- data.tar.gz: 45f768df4e7d89c931295985adb31df9e725156e5a85d7f78a5b7cd26d00be4d
3
+ metadata.gz: c4b2cdf0c257b74c6bec90b93d1907787f3c102108046731c2755684a1b156e9
4
+ data.tar.gz: 85334dad09a046432503183e3d3ad83841612299038f2f2dac1f9d5d208e1939
5
5
  SHA512:
6
- metadata.gz: 4004293fa10eb247110764d16a24900a10e714072227dd6e5626d2123deca4bcec00b7255e1affaba4d7dda75d7e42049aabf6b1e6c51f4c005124443b5f9ffc
7
- data.tar.gz: eb5c8a2c89c8973242bb77457e0f8d9922486d9743e7c39ee12ea4025ece6d888be5308eaddec076e5a21c84149dcb31bc0ed6fcd68881fb6c8c4063e49fb64d
6
+ metadata.gz: 9272bdd6c56717b53d39b3f2009259accb608ea86b99758b6a7ee9cee1e7b275330db55af4e0eba1eba80ee69275a21a3179243394d24139b3018996f659abe1
7
+ data.tar.gz: a6a9d97d2bf81ac0c2972fd6e9d5202116156d8ff2e5e81a9bf0306e313dbc601522f887bcbcebff8b9d888cc06826a8ce69ba908dce29fa8decad85d53008af
@@ -35,6 +35,10 @@ def align_mdoc(source_annotations, target_annotations)
35
35
  source_annotations.each do |annotations|
36
36
  alignment = TextAlignment::TextAlignment.new(annotations[:text], target_annotations[:text])
37
37
 
38
+ puts alignment.alignment_show
39
+ puts "-----"
40
+ puts
41
+
38
42
  # alignment.block_alignments.each do |a|
39
43
  # p {source:a[:source], target:a[:target]}
40
44
  # puts "--"
@@ -133,26 +137,26 @@ else
133
137
 
134
138
  source_text = source_annotations[:text]
135
139
 
136
- # puts "[block alignment]"
137
- puts alignment.alignment_table
138
- # puts "====="
140
+ puts "[block alignment]"
141
+ puts alignment.alignment_show
142
+ puts "====="
139
143
  # exit
140
144
 
141
145
  # verification of source denotations
142
- # puts "[Invalid source denotations]"
143
- # source_annotations[:denotations] do |d|
144
- # p d unless d[:span][:begin] && d[:span][:end] && d[:span][:begin] < d[:span][:end] && d[:span][:begin] >= 0 && d[:span][:end] < source_text.length
145
- # end
146
- # puts "====="
147
- # puts
146
+ puts "[Invalid source denotations]"
147
+ source_annotations[:denotations] do |d|
148
+ p d unless d[:span][:begin] && d[:span][:end] && d[:span][:begin] < d[:span][:end] && d[:span][:begin] >= 0 && d[:span][:end] < source_text.length
149
+ end
150
+ puts "====="
151
+ puts
148
152
 
149
153
  denotations = alignment.transform_hdenotations(source_annotations[:denotations])
150
- # puts "[Invalid transformation]"
151
- # denotations.each do |d|
152
- # p d unless d[:span][:begin] && d[:span][:end] && d[:span][:begin] < d[:span][:end] && d[:span][:begin] >= 0 && d[:span][:end] < target_text.length
153
- # end
154
- # puts "====="
155
- # puts
154
+ puts "[Invalid transformation]"
155
+ denotations.each do |d|
156
+ p d unless d[:span][:begin] && d[:span][:end] && d[:span][:begin] < d[:span][:end] && d[:span][:begin] >= 0 && d[:span][:end] < target_text.length
157
+ end
158
+ puts "====="
159
+ puts
156
160
 
157
161
  lost_annotations += alignment.lost_annotations if alignment.lost_annotations
158
162
 
@@ -33,7 +33,9 @@ class TextAlignment::LCSComparison
33
33
  @str2_match_initial = sdiff[match_initial].new_position
34
34
  @str1_match_final = sdiff[match_final].old_position
35
35
  @str2_match_final = sdiff[match_final].new_position
36
- @similarity = 2 * lcs / ((@str1_match_final - @str1_match_initial + 1) + (@str2_match_final - @str2_match_initial + 1)).to_f
36
+ mlcs = sdiff.count{|d| d.action == '=' && d.old_element =~ /\S/ && d.new_element =~ /\S/}
37
+ @similarity = 2 * mlcs / (str1[@str1_match_initial .. @str1_match_final].scan(/\S/).count + str2[@str2_match_initial .. @str2_match_final].scan(/\S/).count).to_f
38
+ # @similarity = 2 * lcs / (str1[@str1_match_initial .. @str1_match_final].length + str2[@str2_match_initial .. @str2_match_final].length).to_f
37
39
  else
38
40
  @str1_match_initial = 0
39
41
  @str2_match_initial = 0
@@ -8,30 +8,29 @@ module TextAlignment; end unless defined? TextAlignment
8
8
  TextAlignment::PADDING_LETTERS = ['@', '^', '|', '#', '$', '%', '&', '_'] unless defined? TextAlignment::PADDING_LETTERS
9
9
 
10
10
  class TextAlignment::TextAlignment
11
- attr_reader :block_alignments
11
+ attr_reader :block_alignment
12
12
  attr_reader :similarity
13
13
  attr_reader :lost_annotations
14
14
 
15
15
  def initialize(_str1, _str2, _size_ngram = nil, _size_window = nil, _text_similiarity_threshold = nil)
16
16
  raise ArgumentError, "nil string" if _str1.nil? || _str2.nil?
17
17
 
18
- @ostr1 = _str1
19
- @ostr2 = _str2
18
+ @block_alignment = {source_text:_str1, target_text:_str2}
20
19
 
21
20
  str1, str2, mappings = string_preprocessing(_str1, _str2)
22
21
 
23
22
  # try exact match
24
23
  block_begin = str2.index(str1)
25
24
  unless block_begin.nil?
26
- @block_alignments = [{source:{begin:0, end:str1.length}, target:{begin:block_begin, end:block_begin + str1.length}, delta:block_begin}]
27
- return @block_alignments
25
+ @block_alignment[:blocks] = [{source:{begin:0, end:str1.length}, target:{begin:block_begin, end:block_begin + str1.length}, delta:block_begin, alignment: :block}]
26
+ return @block_alignment
28
27
  end
29
28
 
30
29
  # try exact match
31
30
  block_begin = str2.downcase.index(str1.downcase)
32
31
  unless block_begin.nil?
33
- @block_alignments = [{source:{begin:0, end:str1.length}, target:{begin:block_begin, end:block_begin + str1.length}, delta:block_begin}]
34
- return @block_alignments
32
+ @block_alignment[:blocks] = [{source:{begin:0, end:str1.length}, target:{begin:block_begin, end:block_begin + str1.length}, delta:block_begin, alignment: :block}]
33
+ return @block_alignment
35
34
  end
36
35
 
37
36
  anchor_finder = TextAlignment::AnchorFinder.new(str1, str2, _size_ngram, _size_window, _text_similiarity_threshold)
@@ -64,7 +63,7 @@ class TextAlignment::TextAlignment
64
63
  # puts
65
64
 
66
65
  ## To find block alignments
67
- @block_alignments = []
66
+ @block_alignment[:blocks] = []
68
67
  return if mblocks.empty?
69
68
 
70
69
  # Initial step
@@ -73,35 +72,36 @@ class TextAlignment::TextAlignment
73
72
  e2 = mblocks[0][:target][:begin]
74
73
 
75
74
  if mblocks[0][:target][:begin] == 0
76
- @block_alignments << {source:{begin:0, end:e1}, target:{begin:0, end:0}, alignment: :empty}
75
+ @block_alignment[:blocks] << {source:{begin:0, end:e1}, target:{begin:0, end:0}, alignment: :empty}
77
76
  else
78
77
  _str1 = str1[0 ... e1]
79
78
  _str2 = str2[0 ... e2]
80
79
 
81
80
  unless _str1.strip.empty?
82
81
  if _str2.strip.empty?
83
- @block_alignments << {source:{begin:0, end:e1}, target:{begin:0, end:e2}, alignment: :empty}
82
+ @block_alignment[:blocks] << {source:{begin:0, end:e1}, target:{begin:0, end:e2}, alignment: :empty}
84
83
  else
85
84
  len_min = [_str1.length, _str2.length].min
86
85
  len_buffer = (len_min * (1 + TextAlignment::BUFFER_RATE)).to_i + TextAlignment::BUFFER_MIN
87
86
  b1 = _str1.length < len_buffer ? 0 : e1 - len_buffer
88
87
  b2 = _str2.length < len_buffer ? 0 : e2 - len_buffer
89
88
 
90
- @block_alignments << {source:{begin:0, end:b1}, target:{begin:0, end:b2}, alignment: :empty} if b1 > 0
89
+ @block_alignment[:blocks] << {source:{begin:0, end:b1}, target:{begin:0, end:b2}, alignment: :empty} if b1 > 0
91
90
 
92
91
  _str1 = str1[b1 ... e1]
93
92
  _str2 = str2[b2 ... e2]
94
93
  alignment = TextAlignment::MixedAlignment.new(_str1.downcase, _str2.downcase, mappings)
95
- if alignment.similarity < 0.6
96
- @block_alignments << {source:{begin:b1, end:e1}, target:{begin:0, end:e2}, alignment: :empty}
94
+ similarity = alignment_similarity(_str1, _str2, alignment)
95
+ if similarity < 0.6
96
+ @block_alignment[:blocks] << {source:{begin:b1, end:e1}, target:{begin:0, end:e2}, alignment: :empty, similarity: similarity}
97
97
  else
98
- @block_alignments << {source:{begin:b1, end:e1}, target:{begin:0, end:e2}, alignment:alignment}
98
+ @block_alignment[:blocks] << {source:{begin:b1, end:e1}, target:{begin:0, end:e2}, alignment:alignment}
99
99
  end
100
100
  end
101
101
  end
102
102
  end
103
103
  end
104
- @block_alignments << mblocks[0].merge(alignment: :block)
104
+ @block_alignment[:blocks] << mblocks[0].merge(alignment: :block)
105
105
 
106
106
  (1 ... mblocks.length).each do |i|
107
107
  b1 = mblocks[i - 1][:source][:end]
@@ -112,17 +112,18 @@ class TextAlignment::TextAlignment
112
112
  _str2 = str2[b2 ... e2]
113
113
  unless _str1.strip.empty?
114
114
  if _str2.strip.empty?
115
- @block_alignments << {source:{begin:b1, end:e1}, target:{begin:b2, end:e2}, alignment: :empty}
115
+ @block_alignment[:blocks] << {source:{begin:b1, end:e1}, target:{begin:b2, end:e2}, alignment: :empty}
116
116
  else
117
117
  alignment = TextAlignment::MixedAlignment.new(_str1.downcase, _str2.downcase, mappings)
118
- if alignment.similarity < 0.6
119
- @block_alignments << {source:{begin:b1, end:e1}, target:{begin:b2, end:e2}, alignment: :empty}
118
+ similarity = alignment_similarity(_str1, _str2, alignment)
119
+ if similarity < 0.6
120
+ @block_alignment[:blocks] << {source:{begin:b1, end:e1}, target:{begin:b2, end:e2}, alignment: :empty, similarity: similarity}
120
121
  else
121
- @block_alignments << {source:{begin:b1, end:e1}, target:{begin:b2, end:e2}, alignment:alignment}
122
+ @block_alignment[:blocks] << {source:{begin:b1, end:e1}, target:{begin:b2, end:e2}, alignment:alignment}
122
123
  end
123
124
  end
124
125
  end
125
- @block_alignments << mblocks[i].merge(alignment: :block)
126
+ @block_alignment[:blocks] << mblocks[i].merge(alignment: :block)
126
127
  end
127
128
 
128
129
  # Final step
@@ -134,7 +135,7 @@ class TextAlignment::TextAlignment
134
135
 
135
136
  unless _str1.strip.empty?
136
137
  if _str2.strip.empty?
137
- @block_alignments << {source:{begin:b1, end:str1.length}, target:{begin:b2, end:str2.length}, alignment: :empty}
138
+ @block_alignment[:blocks] << {source:{begin:b1, end:str1.length}, target:{begin:b2, end:str2.length}, alignment: :empty}
138
139
  else
139
140
  len_min = [_str1.length, _str2.length].min
140
141
  len_buffer = (len_min * (1 + TextAlignment::BUFFER_RATE)).to_i + TextAlignment::BUFFER_MIN
@@ -144,57 +145,58 @@ class TextAlignment::TextAlignment
144
145
  _str2 = str2[b2 ... e2]
145
146
 
146
147
  alignment = TextAlignment::MixedAlignment.new(_str1.downcase, _str2.downcase, mappings)
147
- if alignment.similarity < 0.6
148
- @block_alignments << {source:{begin:b1, end:e1}, target:{begin:b2, end:e2}, alignment: :empty}
148
+ similarity = alignment_similarity(_str1, _str2, alignment)
149
+ if similarity < 0.6
150
+ @block_alignment[:blocks] << {source:{begin:b1, end:e1}, target:{begin:b2, end:e2}, alignment: :empty, similarity: similarity}
149
151
  else
150
- @block_alignments << {source:{begin:b1, end:e1}, target:{begin:b2, end:e2}, alignment:alignment}
152
+ @block_alignment[:blocks] << {source:{begin:b1, end:e1}, target:{begin:b2, end:e2}, alignment:alignment}
151
153
  end
152
154
 
153
- @block_alignments << {source:{begin:e1, end:-1}, target:{begin:e2, end:-1}, alignment: :empty} if e1 < str1.length
155
+ @block_alignment[:blocks] << {source:{begin:e1, end:-1}, target:{begin:e2, end:-1}, alignment: :empty} if e1 < str1.length
154
156
  end
155
157
  end
156
158
  end
157
159
 
158
- @block_alignments.each do |a|
160
+ @block_alignment[:blocks].each do |a|
159
161
  a[:delta] = a[:target][:begin] - a[:source][:begin]
160
162
  end
161
163
  end
162
164
 
163
165
  def transform_begin_position(begin_position)
164
- i = @block_alignments.index{|b| b[:source][:end] > begin_position}
165
- block_alignment = @block_alignments[i]
166
-
167
- b = if block_alignment[:alignment] == :block
168
- begin_position + block_alignment[:delta]
169
- elsif block_alignment[:alignment] == :empty
170
- if begin_position == block_alignment[:source][:begin]
171
- block_alignment[:target][:begin]
166
+ i = @block_alignment[:blocks].index{|b| b[:source][:end] > begin_position}
167
+ block = @block_alignment[:blocks][i]
168
+
169
+ b = if block[:alignment] == :block
170
+ begin_position + block[:delta]
171
+ elsif block[:alignment] == :empty
172
+ if begin_position == block[:source][:begin]
173
+ block[:target][:begin]
172
174
  else
173
175
  # raise "lost annotation"
174
176
  nil
175
177
  end
176
178
  else
177
- r = block_alignment[:alignment].transform_begin_position(begin_position - block_alignment[:source][:begin])
178
- r.nil? ? nil : r + block_alignment[:target][:begin]
179
+ r = block[:alignment].transform_begin_position(begin_position - block[:source][:begin])
180
+ r.nil? ? nil : r + block[:target][:begin]
179
181
  end
180
182
  end
181
183
 
182
184
  def transform_end_position(end_position)
183
- i = @block_alignments.index{|b| b[:source][:end] >= end_position}
184
- block_alignment = @block_alignments[i]
185
-
186
- e = if block_alignment[:alignment] == :block
187
- end_position + block_alignment[:delta]
188
- elsif block_alignment[:alignment] == :empty
189
- if end_position == block_alignment[:source][:end]
190
- block_alignment[:target][:end]
185
+ i = @block_alignment[:blocks].index{|b| b[:source][:end] >= end_position}
186
+ block = @block_alignment[:blocks][i]
187
+
188
+ e = if block[:alignment] == :block
189
+ end_position + block[:delta]
190
+ elsif block[:alignment] == :empty
191
+ if end_position == block[:source][:end]
192
+ block[:target][:end]
191
193
  else
192
194
  # raise "lost annotation"
193
195
  nil
194
196
  end
195
197
  else
196
- r = block_alignment[:alignment].transform_end_position(end_position - block_alignment[:source][:begin])
197
- r.nil? ? nil : r + block_alignment[:target][:begin]
198
+ r = block[:alignment].transform_end_position(end_position - block[:source][:begin])
199
+ r.nil? ? nil : r + block[:target][:begin]
198
200
  end
199
201
  end
200
202
 
@@ -240,87 +242,23 @@ class TextAlignment::TextAlignment
240
242
  r
241
243
  end
242
244
 
243
- def alignment_table
244
- table = <<-TABLE
245
- <table class='text_alignment_table'>
246
- <thead>
247
- <tr>
248
- <th class='text_alignment_left' style='width:50%'>Text 1</th>
249
- <th class='text_alignment_rigt'>Text 2</th>
250
- </tr>
251
- </thead>
252
- <tbody>
253
- TABLE
254
-
255
- @block_alignments.each do |a|
256
- table += alignment_table_th(a)
257
- table += "<tr>\n" + case a[:alignment]
258
- when :block
259
- "<td colspan='2' class='text_alignment_common'>" +
260
- @ostr1[a[:source][:begin] ... a[:source][:end]] +
261
- "</td>\n"
262
- when :empty
263
- "<td class='text_alignment_left'>" + @ostr1[a[:source][:begin] ... a[:source][:end]] + "</td>\n" +
264
- "<td class='text_alignment_right'>" + @ostr2[a[:target][:begin] ... a[:target][:end]] + "</td>\n"
265
- else
266
- base = a[:source][:begin]
267
- astr1 = a[:alignment].sdiff.map do |c|
268
- case c.action
269
- when '='
270
- @ostr1[c.old_position + base]
271
- when '+'
272
- '_'
273
- when '-'
274
- @ostr1[c.old_position + base]
275
- when '!'
276
- @ostr1[c.old_position + base] + '_'
277
- end
278
- end.join('')
279
-
280
- base = a[:target][:begin]
281
- astr2 = a[:alignment].sdiff.map do |c|
282
- case c.action
283
- when '='
284
- @ostr2[c.new_position + base]
285
- when '+'
286
- @ostr2[c.new_position + base]
287
- when '-'
288
- '_'
289
- when '!'
290
- '_' + @ostr2[c.new_position + base]
291
- end
292
- end.join('')
293
-
294
- "<td class='text_alignment_left'>" + astr1 + "</td>\n" +
295
- "<td class='text_alignment_right'>" + astr2 + "</td>\n"
296
- end + "</tr>\n"
297
- end
298
- table += '</tbody></table>'
299
- end
300
-
301
- def alignment_table_th(a)
302
- "<tr>" +
303
- "<th class='text_alignment_left'>#{a[:source][:begin]} - #{a[:source][:end]}</th>" +
304
- "<th class='text_alignment_right'>#{a[:target][:begin]} - #{a[:target][:end]}</th>" +
305
- "</tr>"
306
- end
307
-
308
245
  def alignment_show
246
+ stext = @block_alignment[:source_text]
247
+ ttext = @block_alignment[:target_text]
248
+
309
249
  show = ''
310
- @block_alignments.each do |a|
250
+ @block_alignment[:blocks].each do |a|
311
251
  show += case a[:alignment]
312
252
  when :block
313
253
  "===== common =====\n" +
314
- @ostr1[a[:source][:begin] ... a[:source][:end]] + "\n\n"
254
+ stext[a[:source][:begin] ... a[:source][:end]] + "\n\n"
315
255
  when :empty
316
- puts "<<<<< string 1"
317
- p @ostr1[a[:source][:begin] ... a[:source][:end]]
318
- puts
319
- puts ">>>>> string 2"
320
- p @ostr2[a[:target][:begin] ... a[:target][:end]]
321
- puts
256
+ "xxxxx disparate texts (similarity: #{a[:similarity]})\n" +
257
+ "<<<<< string 1\n" +
258
+ stext[a[:source][:begin] ... a[:source][:end]] + "\n\n" +
259
+ ">>>>> string 2\n" +
260
+ ttext[a[:target][:begin] ... a[:target][:end]] + "\n\n"
322
261
  else
323
- puts "***** local mismatch"
324
262
  astr1 = ''
325
263
  astr2 = ''
326
264
 
@@ -328,13 +266,13 @@ class TextAlignment::TextAlignment
328
266
  astr1 = a[:alignment].sdiff.map do |c|
329
267
  case c.action
330
268
  when '='
331
- @ostr1[c.old_position + base]
269
+ stext[c.old_position + base]
332
270
  when '+'
333
271
  '_'
334
272
  when '-'
335
- @ostr1[c.old_position + base]
273
+ stext[c.old_position + base]
336
274
  when '!'
337
- @ostr1[c.old_position + base] + '_'
275
+ stext[c.old_position + base] + '_'
338
276
  end
339
277
  end.join('')
340
278
 
@@ -342,21 +280,22 @@ class TextAlignment::TextAlignment
342
280
  astr2 = a[:alignment].sdiff.map do |c|
343
281
  case c.action
344
282
  when '='
345
- @ostr2[c.new_position + base]
283
+ ttext[c.new_position + base]
346
284
  when '+'
347
- @ostr2[c.new_position + base]
285
+ ttext[c.new_position + base]
348
286
  when '-'
349
287
  '_'
350
288
  when '!'
351
- '_' + @ostr2[c.new_position + base]
289
+ '_' + ttext[c.new_position + base]
352
290
  end
353
291
  end.join('')
354
292
 
355
- puts '[' + astr1 + ']'
356
- puts '[' + astr2 + ']'
357
- puts
293
+ "***** local mismatch\n" +
294
+ "[#{astr1}]\n" +
295
+ "[#{astr2}]\n\n"
358
296
  end
359
297
  end
298
+ show
360
299
  end
361
300
 
362
301
  private
@@ -381,15 +320,15 @@ class TextAlignment::TextAlignment
381
320
  pletters = TextAlignment::PADDING_LETTERS
382
321
 
383
322
  # find the padding letter for str1
384
- padding_letter1 = begin
323
+ @padding_letter1 = begin
385
324
  i = pletters.index{|l| str2.index(l).nil?}
386
325
  raise RuntimeError, "Could not find a padding letter for str1" if i.nil?
387
326
  TextAlignment::PADDING_LETTERS[i]
388
327
  end
389
328
 
390
329
  # find the padding letter for str2
391
- padding_letter2 = begin
392
- i = pletters.index{|l| l != padding_letter1 && str1.index(l).nil?}
330
+ @padding_letter2 = begin
331
+ i = pletters.index{|l| l != @padding_letter1 && str1.index(l).nil?}
393
332
  raise RuntimeError, "Could not find a padding letter for str2" if i.nil?
394
333
  TextAlignment::PADDING_LETTERS[i]
395
334
  end
@@ -400,12 +339,12 @@ class TextAlignment::TextAlignment
400
339
  from = f[1]
401
340
 
402
341
  if str2.index(f[0])
403
- to = f[0] + (padding_letter1 * (f[1].length - 1))
342
+ to = f[0] + (@padding_letter1 * (f[1].length - 1))
404
343
  str1.gsub!(from, to)
405
344
  end
406
345
 
407
346
  if str1.index(f[0])
408
- to = f[0] + (padding_letter2 * (f[1].length - 1))
347
+ to = f[0] + (@padding_letter2 * (f[1].length - 1))
409
348
  str2.gsub!(from, to)
410
349
  end
411
350
  end
@@ -414,4 +353,16 @@ class TextAlignment::TextAlignment
414
353
  [str1, str2, mappings]
415
354
  end
416
355
 
356
+ def alignment_similarity(_s1, _s2, alignment)
357
+ return 0 if alignment.sdiff.nil?
358
+
359
+ # compute the lcs only with non-whitespace letters
360
+ lcs = alignment.sdiff.count{|d| d.action == '=' && d.old_element =~ /\S/ && d.new_element =~ /\S/}
361
+
362
+ s1 = _s1.tr(@padding_letter1, ' ')
363
+ s2 = _s2.tr(@padding_letter2, ' ')
364
+
365
+ similarity = 2 * lcs / (s1.scan(/\S/).count + s2.scan(/\S/).count).to_f
366
+ end
367
+
417
368
  end
@@ -1,3 +1,3 @@
1
1
  class TextAlignment
2
- VERSION = '0.5'
2
+ VERSION = '0.6.2'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: text_alignment
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.5'
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jin-Dong Kim
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-04 00:00:00.000000000 Z
11
+ date: 2020-10-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-dictionary