Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interprets excludedPaths as path prefixes in the SiteMap generator #65

Merged

Conversation

bensyverson
Copy link
Contributor

Summary

Currently, the SiteMapGenerator uses exact matches when comparing a path to exclude from the SiteMap.

This PR changes that behavior, such that the excludedPaths are interpreted as excluded path prefixes.

Discussion

Real world example: I have a Publish site which has a Photography Section, with several Items in a subfolder:

📂 Content/
    📂 photography/
        📝 index.md
        📂 photos/
            📝 2020-01-26.md
            📝 2020-01-27.md            
            📝 2020-01-28.md

I'd like the SiteMap to include /photography/index.html but not any of the /photography/photos/ pages. In Publish as it stands, that's impossible, because it's doing an exact match on the path for each Item:

photography/photos/2020-01-26
photography/photos/2020-01-27
photography/photos/2020-01-28

This PR changes the matching behavior so that the excludedPaths are treated as excluded prefixes for a given path. So if you pass in: "photography/photos/" it will block all of the Items which share that prefix.

Implications & Alternatives

An advantage of this approach is that you can exclude more than one branch or Section with a single prefix; "pho" will exclude /photography as well as /phone.

The obvious "gotcha" is that this could have unintended consequences; if you have both foo and food sections, then excluding foo will exclude all of food too. One solution is to include the trailing slash; foo/, however that will only block foo's items, not its index.

Alternative: wildcards

One alternative would be to support wildcard syntax, so that you could pass in photography/* or foo* to explicitly "opt-in" to prefix matching. While totally reasonable, this may be overkill?

Thanks again John for your very thoughtful work. Sorry for all the PRs—these are just the nips and tucks I'm finding as I dig into the frameworks!


import Foundation

internal extension Collection where Element: StringWrapper {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is an unnecessary abstraction, given that it's only being used in a single place.


internal extension Collection where Element: StringWrapper {
func containsPrefixFor(_ string: String) -> Bool {
reduce(false){ $0 || string.hasPrefix($1.string) }
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will needlessly iterate through the collection every time, even if a match was found, making us turn an O(1) operation (checking if a set contains a member) into an operation that always is O(N) (not only in the worst case). I would suggest using the contains(where:) API instead:

contains(where: { $0.string.hasPrefix(string) })

@@ -27,11 +27,17 @@ struct SiteMapGenerator<Site: Website> {
}
}

internal extension Collection where Element: StringWrapper {
func containsPath(_ path: Path) -> Bool {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the extension you added in a new file could simply be inlined here.

@bensyverson
Copy link
Contributor Author

Thanks for reviewing, @JohnSundell! I finally got around to updating this PR and adding some test cases to verify the new behavior. Take a look and let me know what you think!

@magnuskahr
Copy link

Spend all night trying to handle this problem with the API, then I saw this. I need this.

Copy link
Owner

@JohnSundell JohnSundell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot @bensyverson!

@JohnSundell JohnSundell merged commit e36464a into JohnSundell:master Dec 30, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants