picocms / Pico

Pico is a stupidly simple, blazing fast, flat file CMS.
http://picocms.org/
MIT License
3.81k stars 616 forks source link

Sorting for next_page and previous_page #615

Closed notakoder closed 2 years ago

notakoder commented 2 years ago

Is there any sorting methods that we can specify for next_page and previous_page twig variables? Eg, data/time of the article or perhaps treating the url as an integer to sort numbered urls properly. Currently it is alphabetical or lexicographic.

mayamcdougall commented 2 years ago

Hi there. πŸ‘‹πŸ»

The next_page and previous_page variables are determined based on the sort order in your config. Pico can order its pages however you want. By default, Pico supports sorting both alphabetically and by date. However there's also a third option to sort by a meta property of your choice, which can also be used to create a hard-coded order for your pages.

If you started with Pico's provided config.yml.template, look for the following lines in config.yml (and if you started with a blank config.yml, you can simply copy these lines into it instead).

pages_order_by_meta: author         # Sort pages by meta value "author" (set "pages_order_by" to "meta")
pages_order_by: alpha               # Change how Pico sorts pages ("alpha" for alphabetical order, "date", or "meta")
pages_order: asc                    # Sort pages in ascending ("asc") or descending ("desc") order

The alpha, date, asc and desc options are all pretty self explanatory, but the meta option I mentioned does need some explanation.

If you set pages_order_by: meta, you can sort pages using a page metadata item of your choice, which goes in the option above it. In the example, pages_order_by_meta: author would sort pages based on the author property in each page's YAML header (the part at the top between the two --- lines).

So if you wanted to give each page a hard-coded order, you could set it to pages_order_by: meta and pages_order_by_meta: index, and then give each page an index: 0, index: 1, index: 2 value in its YAML header.

Hopefully this helps with what you were looking for. If not, don't be afraid to ask more questions, I'm happy to help. πŸ˜‰


I'm usually a little more thorough, but I did gloss over a few things in my explanation here that I wasn't 100% positive on, off the top of my head. Including them here just so they don't end up biting you:

I'd usually go spin up my test instance and figure these things out, but they're probably not that important, so I just wanted to get you an answer and not spend all testing pointless tiny details. πŸ˜…


I'm always here and always happy to help, so let me know if this gets you going in the right direction. There's no such thing as a stupid question. I try to be detailed enough without sounding condescending (by breaking things down too far) but I'm happy to go into more detail if you need it. 😁

mayamcdougall commented 2 years ago

I just realized you also specifically asked about sorting by numbered urls. That's probably a bit trickier.

I could probably come up with some Twig hackery to sort pages by a known url format (eg the numbers always being in the same place), but it wouldn't affect next_page and previous_page in that case. We'd have to assign a separate pair of variables like sorted_next_page and sorted_previous_page instead.

It's all probably doable, just a bit hacky. Sorting pages automatically based on their url would definitely be something better handled as a Plugin, but that's not my area of expertise (I'm great with Twig... not so much with PHP). πŸ˜…

I didn't mean to overlook this in my first comment, I just got caught up writing that explanation. If you decide you really need automatic sorting by url instead of metadata let me know and we can get more hacky (πŸ˜‚). *cracks knuckles*

Edit: Apparently I like a challenge too, because now I'm accidentally brainstorming how this could work and it's not actually that crazy sounding. πŸ€”πŸ˜‚ (As long as you don't mind adding the extra Twig code to your Theme.)

notakoder commented 2 years ago

I think sorting with a page meta data will work as long as I number the YAML header with the same number as the URL. But I wish to know that if this change in sorting can be applied to one specific folder rather than site wide. Changes to config.yml will affect the entire site to my knowledge.

I am glad to read your extensive reply and enthusiasm. Thank you.

mayamcdougall commented 2 years ago

Ah, okay. You didn't mention the folder thing before.

Yes, changes to config.yml are global across the entire site. There unfortunately isn't any built-in solution for having different page sorting depending on the folder.

I've spent a while brainstorming with Twig, but I haven't really come up with a great way to do this. πŸ˜“

Can you give me some more context on what you're building / how you'd like it to work?

So far I've gathered that: You'd like to have pages that are numbered in their filenames (meaning those numbers will also be shown in the url). You'd like to sort that folder by those filenames. And you only want to use this sorting method in that specific folder?


@PhrozenByte would you have any input on this issue?

Twig apparently doesn't want to work for me today, as every attempt I've made has kind of backfired and I've been going in circles for awhile now. πŸ˜“

PhrozenByte commented 2 years ago

@PhrozenByte would you have any input on this issue?

Sure. Didn't read the full issue, so please forgive me if I'm suggesting stuff that has been sorted out already:

Use the pages() function to get all pages within the requested folder, sort them using the sort_by filter and then get the prev/next page from the iteration.

Or: Assuming that the page order is correct for all pages except the first and last page within the folder, one could alternatively check whether the prev/next page is within the same folder and, if not, use the pages() function to get the respective first/last page in this folder instead.

Which solution is better depends on the exact use case. Both should work, but personally I'd rather create a plugin.

notakoder commented 2 years ago

Ah, okay. You didn't mention the folder thing before.

Sorry. I didn't know this was important.

So far I've gathered that: You'd like to have pages that are numbered in their filenames (meaning those numbers will also be shown in the url). You'd like to sort that folder by those filenames. And you only want to use this sorting method in that specific folder?

Correct. But because I am not using the sorted results anywhere in the site, I think I can mange sorting it site wide and see if next_page and previous_page works as intended. The only other page where page sorting matters is in the main listing page which manually sorts the listing by time. So I guess, changing site wide will not break the site. I shall try that although this isn't the optimal solution.

Use the pages() function to get all pages within the requested folder, sort them using the sort_by filter and then get the prev/next page from the iteration.

I had tried this though. <a href="{{ previous_page.id|link|sort_by("time")|reverse }}">←Previous</a>, but didn't work. The page wasn't even rendered: had some HTTP error.

I am sure there would be solutions if you put enough time into it, but I suggest that you both don't do so. I was hoping for a quick fix like a config setting, hence opened this issue. I will try what I mentioned earlier and if it does not work, I will let it go.

However, I wish to raise one inherent problem with the next_page and previous_page variables. If I add them to files inside a folder, and if there sibling folders to that folder, the previous button is displayed on the first file of the folder and next button is displayed on the last file of that folder, each linking to files in the sibling folders. This is bad design. Ideally, it must restrict it's operations to the folder it is in. The first file inside my articles directory should not have a previous link and the most recent file should not have a next link.

mayamcdougall commented 2 years ago

@PhrozenByte

Use the pages() function to get all pages within the requested folder, sort them using the sort_by filter and then get the prev/next page from the iteration.

I tried this, but I couldn't figure out a good way to get the "next" page via iteration. I was hoping it'd be as simple as grabbing the next page by index (sorted_pages[loop.index0 + 1]), but that wasn't working. I'm assuming that's because Pages is actually a dictionary, not an array.

I suppose I could just store the sorted page id's in an array, and use those (in fact, I just now wrote some test code that does), but that felt like I was heading down the rabbit hole of "too hacky", and that there should probably have been a better way.

but personally I'd rather create a plugin.

Of course you would. πŸ˜‚

Some of us find PHP to be a headache though, and with the username of "@notakoder", I'm guessing I'm not alone there. πŸ˜‰


@notakoder

<a href="{{ previous_page.id|link|sort_by("time")|reverse }}">←Previous

Yeah, there's a number of reasons why that didn't work. I won't go into it in too much detail, but a quick breakdown of the filter pipeline you have there says you're trying to do the following:

Get the previous page id. Convert that to the url of the previous page (a single string). Then... sort that single url? ... And reverse it? Yeah, not so good. A for effort though, and I know you found part of that from the "Blogging" example in the docs. It's always good to experiment! I just thought I'd let you know why that wasn't really doing what you thought it might.

I think I'm in a better place mentally to help out with this today. I think I can write some more streamlined code for this after all.

Is it just the one articles folder that you're looking to have its own sorting, or are there multiple folders?

Do you need to use this sorting from outside of that folder? What I mean by this is, for example, from your main page would you need to know the proper sorting of the articles pages, or only from one article to another? I guess it doesn't really matter, I'll work something up and we can take it from there.

However, I wish to raise one inherent problem with the next_page and previous_page variables.

I mean, the next_page and previous_page variables are meant to be global across your entire site. I could argue that you're the one not using them as intended here. πŸ˜…

You mention that Pico should restrict them to just a particular folder... but Pico's overall philosophy is to not restrict anything. Pico tries to be open and flexible to however a user wants to design their website, and forcing them to use this folder-restricted behavior wouldn't really align with that goal.

That's not to say it wouldn't be a neat feature, but it would fall more inline with what a Plugin or Theme should provide. It's a behavior that, while useful to some, would be specific to an individual's use case and not really a good default.

Anyway, I'll be back in a little bit with a Twig snippet that replaces next_page and previous_page for you. I think we can get your use case sorted out for you. 😁

Just remember, Pico is incredibly flexible, but that flexibility often comes at the cost of having to provide some of the functionality yourself. Sometimes, you've just got to get your hands dirty and dig into the code. πŸ˜‰

mayamcdougall commented 2 years ago

Alright, here's what I've got.

I thought it might be handy to put these in config.yml, but you can hard-code them instead if you'd rather.

sort_directory: articles
sort_meta: Index

Put this somewhere before your next and previous links (Thanks to @PhrozenByte for the optimization. πŸ˜‰).

{% if config.sort_directory and current_page.id starts with config.sort_directory ~ "/" %}
    {% set sorted_page_ids = pages(config.sort_directory, depth=null)|sort_by(["meta", config.sort_meta], "remove")|keys %}
    {% for page_id in sorted_page_ids %}
        {% if page_id == current_page.id %}
            {% set previous_page = pages[sorted_page_ids[loop.index0-1]] %}
            {% set next_page = pages[sorted_page_ids[loop.index0+1]] %}
        {% endif %}
    {% endfor %}
{% endif %}

And if you don't already, you might want your next and previous links in an if statement. Otherwise if they don't exist (on the first and last page), you'll end up with a link to your main page instead (That's just what the link filter seems to default to if you don't pass it anything).

{% if previous_page %}
    <a href="{{ previous_page.id|link }}">Prev Page</a>
{% else %}
    Prev Page
{% endif %} | 
{% if next_page %}
    <a href="{{ next_page.id|link }}">Next Page</a>
{% else %}
    Next Page
{% endif %}

(Removed older conversation that's not relevant anymore)

We weren't sure whether you wanted subfolders inside articles to be included or not. If you remove the depth=null parameter, they'll stop being included, and they'll revert to using Pico's global page order. It wouldn't really be a good UX like that, as to an end user it would almost seem like they were linking to random next and previous pages.

...But making the code work recursively, separating each individual folder level, would be a lot more work, and would probably add additional slowdown that you don't want/need (and definitely not a good task for Twig).

And keep in mind that this will only override next_page and previous_page when you're within a page in articles. From anywhere else on your site, they'll still be in whatever global order they would have been.

@notakoder Let me know how this lines up with what you were looking for and I can tweak it however needed. 😁

PhrozenByte commented 2 years ago

I tried this, but I couldn't figure out a good way to get the "next" page via iteration.

With Twig you have to run the full iteration. Very heavy-handed (or "hacky"), that's the reason why I'd rather create a plugin :see_no_evil:

See the suggestion below based on Maya's snippet, it's better. ```twig {% set my_current_page = null %} {% set my_previous_page = null %} {% set my_next_page = null %} {% for page in pages(…)|sort_by(…) %} {% if page.id == current_page.id %}{% set my_current_page = page %}{% endif %} {% if my_current_page is null %}{% set my_previous_page = page %}{% endif %} {% if my_current_page is not null and my_next_page is null %}{% set my_next_page = page %}{% endif %} {% endfor %} ```

However, if the order within the folder is as expected (something one can easily ensure by adding numeric prefixes to the file names), one can simply check whether the referenced prev/next page is within the expected folder:

{% set my_previous_page = previous_page.id starts with "articles/" ? previous_page : null %}
{% set my_next_page = next_page.id starts with "articles/" ? next_page : null %}

However, I wish to raise one inherent problem with the next_page and previous_page variables. […] Ideally, it must restrict it's operations to the folder it is in.

This highly depends on the directory structure used. Pico assumes no special meaning for directories, because whether they have special meaning or not depends on the use case. A lot users create blogs and to organize their articles they create dated folders like 2021-12. Interpreting directories as boundaries would break this.

PhrozenByte commented 2 years ago

@PhrozenByte, if you have time, you want to just glance over this for a quick sanity check?

[loop.index0-1] works? Nice, somehow I was convinced that Twig can't handle this. Even better.

Just two small suggestions: Instead of the loop to create sorted_page_ids you can use sorty_by(…, 'remove') and keys. To also include sub-folders you can use pages(…, depth=null) (however, directories aren't treated as boundaries then; if this isn't desired simply remove it).

{% if config.sort_directory and current_page.id starts with config.sort_directory ~ "/" %}
    {% set sorted_page_ids = pages(config.sort_directory, depth=null)|sort_by(["meta", config.sort_meta], "remove")|keys %}
    {% for page_id in sorted_page_ids %}
        {% if page_id == current_page.id %}
            {% set previous_page = pages[sorted_page_ids[loop.index0-1]] %}
            {% set next_page = pages[sorted_page_ids[loop.index0+1]] %}
        {% endif %}
    {% endfor %}
{% endif %}
mayamcdougall commented 2 years ago

Lmao at the timing of your reply. I guess we were both working on it. πŸ˜‚

Mmhmm, yep, I see. *nod nod*

I overcomplicated it by getting hung up on using indexes. πŸ˜’ πŸ˜…

Or not, I guess, because you liked my approach better (with your simplification). πŸ˜‚

[loop.index0-1] was only working because I made a separate array for them. I didn't think using |keys would do that, but it does seem to work too. πŸ‘πŸ»

I started to mention depth=null as an idea in my last comment, but then I realized it would lump all the subfolders together, so I dropped it in favor of "maybe this behavior should be different". Idk, UX is a pain sometimes. Trying to write code that behaves as expected under all circumstances is tough. πŸ€”

With Twig you have to run the full iteration. Very heavy-handed (or "hacky"), that's the reason why I'd rather create a plugin πŸ™ˆ

Absolutely. I often wonder how well some of my Twig code scales. Like how many pages does it take to make this code lag? Could Twig get stuck running so long that the page loading times out? I'm not asking, just being rhetorical. It would be really cool to run the numbers on it though for someone else to I mean. Pico performance testing, lol. Make some graphs!

Anyway, @notakoder I'm going to go back and update my example above to match @PhrozenByte's improvements (that way it's all in one place when you come back).

notakoder commented 2 years ago

First of all, my apologies for late reply.

Some of us find PHP to be a headache though, and with the username of "@notakoder", I'm guessing I'm not alone there.

Well, I am way below your league. :D I am literally not a coder, but I understand computer logic and can read and understand some code: that's how I am surviving Pico :smile:. I liked the simplicity and performance of Pico, which is why I take the trouble of setting it up over Wordpress.

Yeah, there's a number of reasons why that didn't work.

Corrent. I just didn't want to seem like a guy who didn't try anything at all to fix it. Hence summed it up. :smile:

I think I'm in a better place mentally to help out with this today.

Thank you. But as I said, I wouldn't suggest anyone going through the pain of fixing something as time consuming as this, when I can't compensate you in any manner. But on the other hand, there must be an improvement as well for the next_page and previous_page variables to handle multiple cases (discussed later). So...

Is it just the one articles folder that you're looking to have its own sorting, or are there multiple folders?

What I am trying to achieve is to apply the Next and Previous links to the contents (not to be confused with the directory name) of a single directory inside the contents folderβ€”because each folder represents a particular classification. For eg,

I experienced two issues:

First is with regard to sorting. The filename of the articles inside each folder are numbered as per when it was published. But the default sorting works alphabetically. So 10, 11, and 12 are lesser than 2. If I click the next button on sports/1, I get sports/10 instead of sports/2. This is the default behaviour and I guess it should be so, because most url aren't numbered and has a meaningful name. I like the configuration of sorting which you suggested, but it affects the whole site. In most cases, this shouldn't matter (in my case too). But let's assume that only the filenames inside sports directory are numbered; and the rest are properly named. In this case, the sorting messes up the order of these folders. Which is why I asked if there was a way to specify the sorting for a directory. And thanks to you @mayamcdougall for your solution. But because you said,

Anyway, @notakoder I'm going to go back and update my example above to match @PhrozenByte's improvements (that way it's all in one place when you come back).

I assume that there is some more optimisation to be done. So I shall wait before trying out your code.

The second issue is more of a problem caused by the templating, which @mayamcdougall already addressed as well. If, 1.md and 9.md are the first (oldest) and last (latest) files inside the sports directory, sports/1 shouldn't have the previous button and sports/9 shouldn't have the next button, because in most cases, folders are categories. However, the default behaviour is otherwise with the previous button of sports/1 linking politics/9 and the next button in sports/9 linking technology/1. I used an if statement (in a worse way than you suggested) to eliminate the previous and next buttons in the first and last pages. As @PhrozenByte pointed out,

A lot users create blogs and to organize their articles they create dated folders like 2021-12. Interpreting directories as boundaries would break this.

So, I am suggesting that there are two use cases: one that makes sense linking and the other that does not makes sense linking. So if it is possible, Pico should have this 'restriction within a folder' as a configurable option. This will improve the product.

I mean, both the solutions to both issues (directory specific sorting and the appearance of next and previous buttons), if technically viable, must be added as a configurable option because such use cases are common.

PhrozenByte commented 2 years ago

The filename of the articles inside each folder are numbered as per when it was published. But the default sorting works alphabetically. So 10, 11, and 12 are lesser than 2. If I click the next button on sports/1, I get sports/10 instead of sports/2. This is the default behaviour and I guess it should be so, because most url aren't numbered and has a meaningful name.

That's because computers sort numbers different than humans. However, this is very easy to solve: Use sports/01.md instead.

By the way, if you want to get rid of those prefixes in your URLs, try https://github.com/PhrozenByte/pico-file-prefixes

A lot users create blogs and to organize their articles they create dated folders like 2021-12. Interpreting directories as boundaries would break this.

So, I am suggesting that there are two use cases: one that makes sense linking and the other that does not makes sense linking. So if it is possible, Pico should have this 'restriction within a folder' as a configurable option. This will improve the product.

Yeah, I agree, this is a valid feature request. I've just added it to our backlog (#317), but I'm afraid this isn't going to be implemented soon due to very limited time :unamused:

notakoder commented 2 years ago

That's because computers sort numbers different than humans. However, this is very easy to solve: Use sports/01.md instead.

If my understanding is right, Pico or PHP is sorting numbers as strings instead of integers, thus resulting in an alphabetical order. I think it is called lexicographic sorting (forgive me if I am wrong) formally. So my point is, sometimes when numbers are put in the url, they are there for the integer they are. Therefore I should not remove the number with the prefix remover as well.

With regard to naming 01, 02..., this restricts the number of files to 99. 001, 002... to 999. One can also prefix the number with more zeros to broaden the max number of files. But I guess, after some point it is just not aesthetical... Consider sports/0000001. Moreover this is a workaround, not a solution per se. Anyway, this can be solved by meta property as suggested by @mayamcdougall. I am only suggesting that this be a configurable option too, ie, if you find it valid.

but I'm afraid this isn't going to be implemented soon due to very limited time

That's alright. Glad that it is in. I think @mayamcdougall already gave a better if condition as a temporary fix.

mayamcdougall commented 2 years ago

No worries, you're not the only one running behind. πŸ˜“

I liked the simplicity and performance of Pico, which is why I take the trouble of setting it up over Wordpress.

(That's why we like it too. πŸ˜‰)

I assume that there is some more optimisation to be done. So I shall wait before trying out your code.

No, it was done, lol. I just edited my previous comment that way all the code examples (config, sorting, and if links) were all in one place. I didn't want you to have to combine the code from both mine and @PhrozenByte's comment. Either way, it sounds like it doesn't exactly fit yet, since it only supports one sorted folder. It shouldn't be too hard to make it operate on a few different categories (it still won't support any recursion though).

Pico or PHP is sorting numbers as strings instead of integers... So my point is, sometimes when numbers are put in the url, they are there for the integer they are.

I know it doesn't seem logical to sort them as strings... but its actually a lot harder than you'd think to convert strings to integers. While yes many programming languages support converting strings to integers, you're talking about converting a user supplied string to an integer for sorting. Since the user could name their page almost anything, how do you pick out the integer part and sort by that? Also, you've still got to sort the rest of the characters alphabetically too.

Heck, I seem to remember that Windows even struggled with this at some point when it came to file and folder names (pretty sure they fixed it at some point, but I have no idea off the top of my head).

Not saying that it's impossible (I mean, there's probably a bunch of libraries out there that could accomplish it too), just that it's not a "simple" problem. Since the intention is that users would probably want to name their page (and their url) something easily readable, it's never really been something worth stressing over.

Honestly, if I were doing it, I'd probably skip organizing by index (which would be tedious for a large number of files), and just use leading 0's. Start with however many you think you'll need. Will you have tens, hundreds, or thousands or articles? At a certain point, it becomes unlikely that you'd ever actually need more (will you really need thousands, or is that just wishful thinking?). And, if you ever did cross that threshold, you could just use a batch file renaming tool to add another 0 to everything. (For simplicity, I'll ignore the fact that doing that would break any older links people have made to your pages. I'm more suggesting it would be inconvenient, but not the end of the world.)

You can tackle it however you'd like though, that's just my opinion. Though, I understand all too well the uncompromising, perfectionist feeling of "No, it has to be this way!", so I won't judge. πŸ˜‚

One can also prefix the number with more zeros to broaden the max number of files. But I guess, after some point it is just not aesthetical... Consider sports/0000001

I mean, at that point I think you've got to ask yourself why you're numbering your pages. sports/0000001 might look bad... but arguably so would sports/1000000. Probably why CMS's usually default to a url scheme like page-titles-with-hyphens instead of numbering.

That's alright. Glad that it is in. I think @mayamcdougall already gave a better if condition as a temporary fix.

I mean... I guess, but it wasn't really the if statement doing the heavy lifting there. πŸ˜‰ When this code is determining the correct next and prev page, it just doesn't bother to link the first and last page together (it could, if you wanted, but it didn't sound like that fit your plan).

(On a side note, I'm kind of surprised that the first page trying to look up an index of -1 didn't accidentally link to the last page automatically, but I guess Twig's just not that smart.)

So, the links surrounding the first and last page were just naturally empty. The if statement was just to prevent the |link filter from making a link to / when it was given an empty string of a page.id.

Also, by not wrapping the text in an <a> tag at all, we get the nice behavior of "Oh, this must be the first/last page because the text is black", lol.

Anyway, sorry for rambling a little here. I'll go add some multi-directory support to that code example.

But as I said, I wouldn't suggest anyone going through the pain of fixing something as time consuming as this, when I can't compensate you in any manner.

It's what I do. πŸ˜‰

I'd like to see Pico's user base grow. If I can keep a Pico user around by walking them through their problems than that's a win.

I'd rather help someone solve their Pico use case than have them leave frustrated by it. As long as you've got the patience to work through it, I'm happy to help with any Pico issues I can. ❀️

(Unfortunately, adding new features to Pico itself is solely @PhrozenByte's territory, and he's usually too busy these days to do much work on it. Everything about Pico is done entirely as volunteer work after all!

...and while I'd love to help with Pico's core, I don't know if I have it in me to master PHP just yet. πŸ˜‚)

mayamcdougall commented 2 years ago
sort_directories:
  - technology
  - sports
  - politics
sort_meta: Index
{% set sort_directory = "" %}
{% for directory in config.sort_directories %}
    {% if current_page.id starts with directory ~ "/" %}
        {% set sort_directory = directory %}
    {% endif %}
{% endfor %}
{% if sort_directory %}
    {% set sorted_page_ids = pages(sort_directory, depth=null)|sort_by(["meta", config.sort_meta], "remove")|keys %}
    {% for page_id in sorted_page_ids %}
        {% if page_id == current_page.id %}
            {% set previous_page = pages[sorted_page_ids[loop.index0-1]] %}
            {% set next_page = pages[sorted_page_ids[loop.index0+1]] %}
        {% endif %}
    {% endfor %}
{% endif %}

This should give it multi-directory support.

I couldn't think of any way to combine in and starts with, so I just looped over each provided sort directory. It could probably be done by using |split instead of starts with, and chopping up the current_page.id based on the slashes /, but that could get messy. πŸ€·πŸ»β€β™€οΈ

Also, if you decide you don't want to sort by Index (or anything else), you can just remove the |sort_by(["meta", config.sort_meta], "remove") filter and the code should still work (though there's probably a much simpler way we could have written the code to only check if next_page/previous_page are in the current directory. πŸ˜… )

Let me know what you think and we can take it further from here. 😁

github-actions[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in two days if no further activity occurs. Thank you for your contributions! :+1:

notakoder commented 2 years ago

Apologies for the late reply.

I know it doesn't seem logical to sort them as strings... but its actually a lot harder than you'd think to convert strings to integers.

I understand. Perhaps this can be tackled as an update in the next release. For now, I'll go with the sorting meta.

I mean, at that point I think you've got to ask yourself why you're numbering your pages.

My reason was simple, that it is easy to open the nth article by just adjusting the url.

Unfortunately, adding new features to Pico itself is solely @PhrozenByte's territory

Judging by his previous comment, I believe that he is aware of the issue and have taken a note of it.

As long as you've got the patience to work through it, I'm happy to help with any Pico issues I can.

Thank you.. :smile: I've been busy lately. I'll try the code for sorting using meta and update the issue. I only have one directory to sort, the multiple directories I mentioned was to make my case and for discussion. Anyway, I'll make some dummy directories for testing.

notakoder commented 2 years ago

I realised that I can achieve the same order of numbered urls by sorting using the date YAML header. So I added

sort_directories:
  - articles
pages_order_by: date
pages_order: asc 

and removed |sort_by(["meta", config.sort_meta], "remove") as you suggested. The next_page and previous_page are limited to the articles folder.

Also, the list of directory/directories to sort must be configured in multiple lines like your most recent code, than a single line as here.

sort_directories: articles

did not work, but

sort_directories:
  - articles

worked.

So anyway, thanks to both of you @mayamcdougall and @PhrozenByte. I hope some of the things we discussed here reflects in the next update.

mayamcdougall commented 2 years ago

No worries about the delay. I've been sick since Christmas with a bad cold (not you-know-what, but still a bit rough). Finally starting to get back into things.

Also, don't mind the github-actions bot. It likes to go around threatening to close things. πŸ˜‰

I think it might be a little too aggressive with it, but most people do tend to leave their issues open when they're done, so... πŸ€·πŸ»β€β™€οΈ

Feel free to reopen this issue if you want / whenever you're ready to continue. Or, we can keep discussing on the closed issue, it doesn't really make a difference to me. πŸ˜‰

I mean, at that point I think you've got to ask yourself why you're numbering your pages.

My reason was simple, that it is easy to open the nth article by just adjusting the url.

I was just trying to be a little funny, saying that by the millionth article, it's gonna look bad with or without those leading 0's. I wasn't trying to be too critical of the pragmatism of that approach, just suggesting that in the real world, you'd probably reconsider how you were labeling them sometime before hitting the seventh decimal place, lol. πŸ˜‚

Also, the list of directory/directories to sort must be configured in multiple lines

Yeah, sorry, I guess I forgot to mention that. It's because the code is expecting an Array now. You could make it more flexible by changing the beginning to something like this:

{% set sort_directory = "" %}
{% set sort_directories = config.sort_directories %}

{% if sort_directories is not iterable %}
  {% set sort_directories = [sort_directories] %}
{% endif %}

{% for directory in sort_directories %}
...

It just does a quick check to see if config.sort_directories is "iterable" or not. That is to say, if it contains multiple items that can be iterated over (such as in the for loop). If not, it wraps it in an Array ([ ]), that way it will be. The for loop doesn't know what to do if it's given a single item, and needs an Array or other "iterable" container object to work with.

I've been using this approach lately in my own code to make it more flexible. It does overcomplicate it a little though, so if you can just remember to use multiple lines in your YML, that's probably simpler. πŸ˜‰

I haven't actually tested that code above, I just wrote it here in the comment box, so probably consider it more of a lesson or a neat trick than an actual example. πŸ˜…

Anyway, good luck with your project. Don't be afraid to ask any other questions you might have. πŸ˜πŸ‘πŸ»

notakoder commented 2 years ago

I've been sick since Christmas with a bad cold (not you-know-what, but still a bit rough). Finally starting to get back into things.

Well, I am glad to hear you are getting back. Thanks for taking the time to reply nonetheless.

how you were labeling them sometime before hitting the seventh decimal place, lol. πŸ˜‚

Haha.. yeah, that makes sense.

if you can just remember to use multiple lines in your YML, that's probably simpler. πŸ˜‰

Yes, and currently that is what I've employed. But glad to see another bit of code that can be experimented with.

Anyway, good luck with your project. Don't be afraid to ask any other questions you might have. πŸ˜πŸ‘πŸ»

Thank you. With you guys available for help, I'm sure things will go just fine.

There is one essential refactoring in my opinion, and that is the if statement put in https://github.com/picocms/Pico/issues/615#issuecomment-995163515

The ideal aesthetic is to have only the next link on the first article and only the previous link on the most recent article. So I made the following modifications to the code.

{% if previous_page %}
  <a href="{{ previous_page.id|link }}">Previous</a>
{% endif %} | 
{% if next_page %}
  <a href="{{ next_page.id|link }}">Next</a>
{% endif %}

The problem is the pipe character, which must not appear unless both next and previous links are rendered. And I understand why it appears otherwiseβ€”it is not a part of the if condition. You cannot add | inside any of the a tags because that will make the | a hyperlink too, which is not aesthetic. I guess the solution is a completely new conditional statement or a combination of if and switch statements.

mayamcdougall commented 2 years ago

You cannot add | inside any of the a tags because that will make the | a hyperlink too, which is not aesthetic.

No, but the area around the <a> tags are also inside the if statement, so there's no reason they'd have to be part of the link. That doesn't solve the real problem though.

I guess the solution is a completely new conditional statement

Since you only want it to appear if both previous_page and next_page are defined, it should be as simple as wrapping it in its own if block that says as much. πŸ˜‰

{% if previous_page and next_page %} | {% endif %}
notakoder commented 2 years ago

That's a simpler fix! Thanks.. :smile: