Skip to content

Commit 0a03f74

Browse files
authored
Merge pull request #1230 from epage/cat
fix(paging): Put pages under the correct category
2 parents 5a2d9ec + 3d6e4c0 commit 0a03f74

File tree

4 files changed

+22
-98
lines changed

4 files changed

+22
-98
lines changed

src/pagination/categories.rs

+18-94
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::cmp::Ordering;
1+
use std::collections::BTreeMap;
22

33
use crate::document::Document;
44

@@ -25,107 +25,52 @@ fn distribute_posts_by_categories<'a>(
2525
for post in all_posts {
2626
if let Some(categories) = extract_categories(post.as_view()) {
2727
let categories: Vec<_> = categories.values().collect();
28-
parse_categories_list(&mut root, 1, categories.as_slice(), post)?;
28+
parse_categories_list(&mut root, categories.as_slice(), post)?;
2929
}
3030
}
3131
Ok(root)
3232
}
3333

3434
/// construct a hierarchy of Categories with their posts from a list of categories
3535
fn parse_categories_list<'a>(
36-
parent: &mut Category<'a>,
37-
cur_idx: usize,
38-
cur_post_categories: &[&dyn ValueView],
36+
mut parent: &mut Category<'a>,
37+
post_categories: &[&dyn ValueView],
3938
post: &'a liquid::model::Value,
4039
) -> Result<()> {
41-
if cur_idx <= cur_post_categories.len() {
42-
let cat_full_path = construct_cat_full_path(cur_idx, cur_post_categories);
43-
let cur_cat = if let Ok(idx) = parent.sub_cats.binary_search_by(|c| {
44-
compare_category_path(
45-
c.cat_path.iter().map(|v| v.as_view()),
46-
cat_full_path.iter().copied(),
47-
)
48-
}) {
49-
&mut parent.sub_cats[idx]
50-
} else {
51-
let last_idx = parent.sub_cats.len();
52-
parent
53-
.sub_cats
54-
.push(Category::with_path(cat_full_path.into_iter()));
55-
// need to sort for binary_search_by
56-
parent.sub_cats.sort_by(|c1, c2| {
57-
compare_category_path(
58-
c1.cat_path.iter().map(|v| v.as_view()),
59-
c2.cat_path.iter().map(|v| v.as_view()),
60-
)
61-
});
62-
&mut parent.sub_cats[last_idx]
63-
};
64-
65-
if is_leaf_category(cur_idx, cur_post_categories) {
66-
cur_cat.add_post(post);
67-
} else {
68-
parse_categories_list(cur_cat, next_category(cur_idx), cur_post_categories, post)?;
69-
}
40+
for i in 0..post_categories.len() {
41+
let cat_name = post_categories[i].to_kstr().to_string();
42+
parent = parent
43+
.sub_cats
44+
.entry(cat_name)
45+
.or_insert_with(|| Category::with_path(post_categories[0..=i].iter().copied()));
7046
}
47+
parent.add_post(post);
7148
Ok(())
7249
}
7350

74-
#[derive(Debug)]
51+
#[derive(Default, Debug)]
7552
struct Category<'a> {
7653
cat_path: liquid::model::Array,
7754
posts: Vec<&'a liquid::model::Value>,
78-
sub_cats: Vec<Category<'a>>,
55+
sub_cats: BTreeMap<String, Category<'a>>,
7956
}
8057

8158
impl<'a> Category<'a> {
8259
fn new() -> Self {
83-
Category {
84-
cat_path: vec![],
85-
posts: vec![],
86-
sub_cats: vec![],
87-
}
60+
Default::default()
8861
}
8962

9063
fn with_path<'v>(path: impl Iterator<Item = &'v dyn ValueView>) -> Self {
91-
Category {
92-
cat_path: path.map(|v| v.to_value()).collect(),
93-
posts: vec![],
94-
sub_cats: vec![],
95-
}
64+
let mut c = Self::new();
65+
c.cat_path = path.map(|v| v.to_value()).collect();
66+
c
9667
}
9768

9869
fn add_post(&mut self, post: &'a liquid::model::Value) {
9970
self.posts.push(post);
10071
}
10172
}
10273

103-
fn compare_category_path<'a, C, S>(cur_path: C, seek: S) -> Ordering
104-
where
105-
C: Iterator<Item = &'a dyn ValueView>,
106-
S: Iterator<Item = &'a dyn ValueView>,
107-
{
108-
cur_path
109-
.map(liquid::model::ValueViewCmp::new)
110-
.partial_cmp(seek.map(liquid::model::ValueViewCmp::new))
111-
.expect("Arrays of same hierarchy level should be fully comparable")
112-
}
113-
114-
fn is_leaf_category(cur_idx: usize, categories: &[&dyn ValueView]) -> bool {
115-
cur_idx == categories.len()
116-
}
117-
118-
fn construct_cat_full_path<'v>(
119-
cur_idx: usize,
120-
categories: &[&'v dyn ValueView],
121-
) -> Vec<&'v dyn ValueView> {
122-
categories[..cur_idx].to_vec()
123-
}
124-
125-
fn next_category(cur_idx: usize) -> usize {
126-
cur_idx + 1
127-
}
128-
12974
// walk the categories tree and construct Paginator for each node,
13075
// filling `pages` and `indexes` accordingly
13176
fn walk_categories(
@@ -154,7 +99,7 @@ fn walk_categories(
15499
} else {
155100
cur_cat_paginators_holder.push(Paginator::default());
156101
}
157-
for c in &mut category.sub_cats {
102+
for c in category.sub_cats.values_mut() {
158103
let mut sub_paginators_holder = walk_categories(c, config, doc)?;
159104

160105
if let Some(indexes) = cur_cat_paginators_holder[0].indexes.as_mut() {
@@ -166,24 +111,3 @@ fn walk_categories(
166111
}
167112
Ok(cur_cat_paginators_holder)
168113
}
169-
170-
#[cfg(test)]
171-
mod test {
172-
use super::*;
173-
174-
use liquid::model::ArrayView;
175-
176-
#[test]
177-
fn compare_category_path_test() {
178-
let a = liquid::model::array!(["A"]);
179-
let b = liquid::model::array!(["B"]);
180-
assert_eq!(
181-
Ordering::Less,
182-
compare_category_path(a.values(), b.values())
183-
);
184-
assert_eq!(
185-
Ordering::Greater,
186-
compare_category_path(b.values(), a.values())
187-
);
188-
}
189-
}

tests/cmd/pagination_categories.out/_dest/categories.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ <h1>categories.html</h1>
1010

1111
<ul>
1212

13-
<li><a href="/categories/cat1/">cat1 (1)</a>
13+
<li><a href="/categories/cat1/">cat1 (2)</a>
1414

15-
<li><a href="/categories/cata/">catA (2)</a>
15+
<li><a href="/categories/cata/">catA (1)</a>
1616

1717
</ul>
1818

tests/cmd/pagination_categories.out/_dest/categories/cat1/index.html

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ <h1>categories.html</h1>
2424
<div>Posts in this category:</div>
2525
<ul>
2626

27+
<li><a href="/posts/my-fourth-blogpost.html">My fourth Blogpost</a>
28+
2729
<li><a href="/posts/my-third-blogpost.html">My third Blogpost</a>
2830

2931
</ul>

tests/cmd/pagination_categories.out/_dest/categories/cata/index.html

-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ <h1>categories.html</h1>
2424
<div>Posts in this category:</div>
2525
<ul>
2626

27-
<li><a href="/posts/my-fourth-blogpost.html">My fourth Blogpost</a>
28-
2927
<li><a href="/posts/my-first-blogpost.html">My first Blogpost</a>
3028

3129
</ul>

0 commit comments

Comments
 (0)