From 82d07257478e8c9d27b358b72031893a1d0651e9 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 4 Sep 2016 10:46:54 -0400 Subject: [PATCH] Improve ordering of entries and types --- lib/docs/core/entry_index.rb | 33 +++++++++++++++++++++++-- lib/docs/core/models/entry.rb | 4 --- lib/docs/core/models/type.rb | 10 -------- test/lib/docs/core/entry_index_test.rb | 23 +++++++++++++++-- test/lib/docs/core/models/entry_test.rb | 18 -------------- test/lib/docs/core/models/type_test.rb | 21 ---------------- 6 files changed, 52 insertions(+), 57 deletions(-) diff --git a/lib/docs/core/entry_index.rb b/lib/docs/core/entry_index.rb index 7c4e7a0e..c909c6b6 100644 --- a/lib/docs/core/entry_index.rb +++ b/lib/docs/core/entry_index.rb @@ -46,11 +46,40 @@ module Docs end def entries_as_json - @entries.sort!.map { |entry| entry.as_json } + @entries.sort! { |a, b| sort_fn(a.name, b.name) }.map(&:as_json) end def types_as_json - @types.values.sort!.map { |type| type.as_json } + @types.values.sort! { |a, b| sort_fn(a.name, b.name) }.map(&:as_json) + end + + SPLIT_INTS = /(?<=\d)\.(?=[\s\d])/.freeze + + def sort_fn(a, b) + if (a.getbyte(0) >= 49 && a.getbyte(0) <= 57) || (b.getbyte(0) >= 49 && b.getbyte(0) <= 57) + a_split = a.split(SPLIT_INTS) + b_split = b.split(SPLIT_INTS) + + a_length = a_split.length + b_length = b_split.length + + return a.casecmp(b) if a_length == 1 && b_length == 1 + return 1 if a_length == 1 + return -1 if b_length == 1 + + a_split.each_with_index { |s, i| a_split[i] = s.to_i unless i == a_length - 1 } + b_split.each_with_index { |s, i| b_split[i] = s.to_i unless i == b_length - 1 } + + if b_length > a_length + (b_length - a_length).times { a_split.insert(-2, 0) } + elsif a_length > b_length + (a_length - b_length).times { b_split.insert(-2, 0) } + end + + a_split <=> b_split + else + a.casecmp(b) + end end end end diff --git a/lib/docs/core/models/entry.rb b/lib/docs/core/models/entry.rb index 9e5c6282..c3f5464c 100644 --- a/lib/docs/core/models/entry.rb +++ b/lib/docs/core/models/entry.rb @@ -22,10 +22,6 @@ module Docs other.name == name && other.path == path && other.type == type end - def <=>(other) - name.to_s.casecmp(other.name.to_s) - end - def name=(value) @name = value.try :strip end diff --git a/lib/docs/core/models/type.rb b/lib/docs/core/models/type.rb index b9869ae7..41d115ec 100644 --- a/lib/docs/core/models/type.rb +++ b/lib/docs/core/models/type.rb @@ -7,16 +7,6 @@ module Docs self.count ||= 0 end - STARTS_WITH_INTEGER = /\A\d/ - - def <=>(other) - if name && other && name =~ STARTS_WITH_INTEGER && other.name =~ STARTS_WITH_INTEGER - name.to_i <=> other.name.to_i - else - name.to_s.casecmp(other.name.to_s) - end - end - def slug name.parameterize end diff --git a/test/lib/docs/core/entry_index_test.rb b/test/lib/docs/core/entry_index_test.rb index f52142bf..0f8b0b18 100644 --- a/test/lib/docs/core/entry_index_test.rb +++ b/test/lib/docs/core/entry_index_test.rb @@ -110,8 +110,17 @@ class DocsEntryIndexTest < MiniTest::Spec entry.name = 'B'; index.add(entry) entry.name = 'a'; index.add(entry) entry.name = 'c'; index.add(entry) - entry.name = nil; index.add(entry) - assert_equal [nil, 'a', 'B', 'c'], index.as_json[:entries].map { |e| e[:name] } + assert_equal ['a', 'B', 'c'], index.as_json[:entries].map { |e| e[:name] } + end + + it "sorts numbered names" do + entry.name = '4.2.2. Test'; index.add(entry) + entry.name = '4.20. Test'; index.add(entry) + entry.name = '4.3. Test'; index.add(entry) + entry.name = '4. Test'; index.add(entry) + entry.name = '2 Test'; index.add(entry) + entry.name = 'Test'; index.add(entry) + assert_equal ['4. Test', '4.2.2. Test', '4.3. Test', '4.20. Test', '2 Test', 'Test'], index.as_json[:entries].map { |e| e[:name] } end end @@ -132,6 +141,16 @@ class DocsEntryIndexTest < MiniTest::Spec entry.type = 'c'; index.add(entry) assert_equal ['a', 'B', 'c'], index.as_json[:types].map { |e| e[:name] } end + + it "sorts numbered names" do + entry.type = '1.8.2. Test'; index.add(entry) + entry.type = '1.90. Test'; index.add(entry) + entry.type = '1.9. Test'; index.add(entry) + entry.type = '9. Test'; index.add(entry) + entry.type = '1 Test'; index.add(entry) + entry.type = 'Test'; index.add(entry) + assert_equal ['1.8.2. Test', '1.9. Test', '1.90. Test', '9. Test', '1 Test', 'Test'], index.as_json[:types].map { |e| e[:name] } + end end end diff --git a/test/lib/docs/core/models/entry_test.rb b/test/lib/docs/core/models/entry_test.rb index d5258910..307cdaac 100644 --- a/test/lib/docs/core/models/entry_test.rb +++ b/test/lib/docs/core/models/entry_test.rb @@ -82,24 +82,6 @@ class DocsEntryTest < MiniTest::Spec end end - describe "#<=>" do - it "returns 1 when the other's name is less" do - assert_equal 1, build_entry('b') <=> build_entry('a') - end - - it "returns -1 when the other's name is greater" do - assert_equal -1, build_entry('a') <=> build_entry('b') - end - - it "returns 0 when the other's name is equal" do - assert_equal 0, build_entry('a') <=> build_entry('a') - end - - it "is case-insensitive" do - assert_equal 0, build_entry('a') <=> build_entry('A') - end - end - describe "#root?" do it "returns true when #path is 'index'" do entry.path = 'index' diff --git a/test/lib/docs/core/models/type_test.rb b/test/lib/docs/core/models/type_test.rb index 8450def7..8d95ea36 100644 --- a/test/lib/docs/core/models/type_test.rb +++ b/test/lib/docs/core/models/type_test.rb @@ -18,27 +18,6 @@ class DocsTypeTest < MiniTest::Spec end end - describe "#<=>" do - it "returns 1 when the other type's name is less" do - assert_equal 1, Type.new('b') <=> Type.new('a') - assert_equal 1, Type.new('15 a') <=> Type.new('4 b') - end - - it "returns -1 when the other type's name is greater" do - assert_equal -1, Type.new('a') <=> Type.new('b') - assert_equal -1, Type.new('8 a') <=> Type.new('16 b') - end - - it "returns 0 when the other type's name is equal" do - assert_equal 0, Type.new('a') <=> Type.new('a') - assert_equal 0, Type.new('23 a') <=> Type.new('23 b') - end - - it "is case-insensitive" do - assert_equal 0, Type.new('a') <=> Type.new('A') - end - end - describe "#slug" do it "parameterizes the #name" do name = 'a.b c\/%?#'