From 4629fad05442c542bdca9d62c38f40f4bf027f48 Mon Sep 17 00:00:00 2001 From: a Date: Sat, 5 Oct 2024 23:56:30 -0500 Subject: [PATCH] WIP: table of contents sticky on articles --- .../assets/styles/common/content.scss | 3 ++ .../styles/layouts/_default/single.scss | 49 ++++++++++++++++++- .../styles/partials/wiki/breadcrumbs.scss | 16 ++++-- .../index.md | 34 +++++++++++-- .../_markup/render-heading.html | 2 +- .../_markup/render-link.html | 0 .../layouts/_default/single.html | 17 ++++++- 7 files changed, 108 insertions(+), 13 deletions(-) rename unified.test.hugo/layouts/{wiki => _default}/_markup/render-heading.html (71%) rename unified.test.hugo/layouts/{wiki => _default}/_markup/render-link.html (100%) diff --git a/unified.test.hugo/assets/styles/common/content.scss b/unified.test.hugo/assets/styles/common/content.scss index 4cf6910..82a3d87 100644 --- a/unified.test.hugo/assets/styles/common/content.scss +++ b/unified.test.hugo/assets/styles/common/content.scss @@ -1,4 +1,7 @@ .hugo-content { + *:first-child { + margin-block-start: 0; + } /* text */ p, li {max-inline-size: 80ch;} h1 {font-size: 1.8em} diff --git a/unified.test.hugo/assets/styles/layouts/_default/single.scss b/unified.test.hugo/assets/styles/layouts/_default/single.scss index 0ef8eac..49776fd 100644 --- a/unified.test.hugo/assets/styles/layouts/_default/single.scss +++ b/unified.test.hugo/assets/styles/layouts/_default/single.scss @@ -1,6 +1,5 @@ .layout-_default-single { .page-header { - padding: 2em 1em; hr {display: none;} .container { max-width: 80ch; @@ -34,8 +33,56 @@ margin-block-end: 0; align-self: end; } + .page-toc { + display: none; + } .page-content { max-width: 80ch; margin-inline: auto; } + @media (min-width: 60rem) { + .container {padding: 0;} + .page[has-toc] { + display: grid; + grid-template-columns: 1fr minmax(37em, 80ch) minmax(17em, 20em) 1fr; + grid-template-rows: auto 1fr; + gap: 2em; + .page-header { + grid-column: 1 / span 4; + grid-row: 1; + display: grid; + grid-template-columns: 1fr minmax(37em, 80ch) minmax(17em, 20em) 1fr; + gap: 2em; + .container { + max-width: unset; + grid-column: 2 / span 2; + } + } + .page-toc { + display: block; + grid-column: 3; + grid-row: 2; + position: sticky; + top: 2em; + align-self: start; + justify-self: start; + max-width: unset; + details { + padding: 0; + background: none; + #TableOfContents { + padding-left: 0em; + } + } + } + .page-content { + grid-column: 2; + grid-row: 2; + max-width: unset; + .toc { + display: none; + } + } + } + } } \ No newline at end of file diff --git a/unified.test.hugo/assets/styles/partials/wiki/breadcrumbs.scss b/unified.test.hugo/assets/styles/partials/wiki/breadcrumbs.scss index 2eb7645..b951364 100644 --- a/unified.test.hugo/assets/styles/partials/wiki/breadcrumbs.scss +++ b/unified.test.hugo/assets/styles/partials/wiki/breadcrumbs.scss @@ -3,14 +3,20 @@ flex-flow: row wrap; padding: 0; li:not(:first-child) { - margin-inline-start: 1.5rem; + margin-inline-start: 1rem; margin-block-end: 1rem; } - li::marker { - content: "/ "; + li { + list-style: none; } - li:first-child::marker { - content: ""; + li:not(:first-child) { + &:before { + content: " / "; + } + a { + display: inline-block; + margin-inline-start: 0.5rem; + } } li:first-child { margin-inline-start: 0; diff --git a/unified.test.hugo/content/articles/evolving-orderedcollection-to-be-more-useful/index.md b/unified.test.hugo/content/articles/evolving-orderedcollection-to-be-more-useful/index.md index 7bdfae9..b892f4e 100644 --- a/unified.test.hugo/content/articles/evolving-orderedcollection-to-be-more-useful/index.md +++ b/unified.test.hugo/content/articles/evolving-orderedcollection-to-be-more-useful/index.md @@ -7,12 +7,15 @@ syndication = [ inReplyTo = [ "https://github.com/w3c/activitypub/issues/439" ] +toc = true +++ Continuing from (and expanding on) this GitHub issue: https://github.com/w3c/activitypub/issues/439 Recently I've been thinking about OrderedCollection again and how the way it's specified doesn't actually match up with the way it's defined, or with what you'd need for it to be a useful data type. Some issues I could identify are laid out below. +{{}} + ## Q1: Is it a List or a Set? Put another way: can you Add an item into an OrderedCollection more than once? @@ -183,11 +186,13 @@ Now finally, we can send an Add and know for sure that it will be inserted in th We now expect that the result will be `[4, 3, 2, 1]` instead of `[3,4,2,1]`. +We might also need a comparison function, but this is currently left unconsidered. + ## Q3: Are there other ways to approach insertion into an OrderedCollection? We might not *want* our OrderedSet to be a SortedSet specifically. We might want some specific ordering that is also specifically not sorted according to any criteria or property. -### Adding a new item at a specific position +### Inserting a new item at a specific position In the most basic case, this might be doable with a property like `insertAfter`? This would allow us to specify where in the `@list` to insert the new item. @@ -238,9 +243,13 @@ This can be fixed by changing the `Add` to an `Insert`. Now, the server has to s We could also define an `insertBefore` property, but I think this isn't necessary and overall just complicates things. Generally when updating a linked list, you traverse it going forwards; the `@list` of `orderedItems` is also presented in forward ordering. It therefore makes the implementation simpler at a data structure level to only define `insertAfter` and no `insertBefore`. -One remaining caveat has to do with ActivityPub delivery. In the case that we send an activity to our local server via C2S, we are not guaranteed that it will have any side effects processed; the activity may be malformed or otherwise not processable. But the presence of addressing properties like `to`, `cc` and `audience` will cause the activity to be delivered to the recipients regardless of whether it had any local side effects -- perhaps the remote server will know what to do with the activity. If the remote server also doesn't know how to process the activity, then you end up with a no-op on both your local server and on the remote server. Perhaps some human reading their `inbox` might be able to derive some meaning from it...? +One remaining caveat has to do with ActivityPub delivery. In the case that we send an activity to our local server via C2S, we are not guaranteed that it will have any side effects processed; the activity may be malformed or otherwise not processable. But the presence of addressing properties like `to`, `cc` and `audience` will cause the activity to be delivered to the recipients regardless of whether it had any local side effects -- perhaps the remote server will know what to do with the activity. If the remote server also doesn't know how to process the activity, then you end up with a no-op on both your local server and on the remote server. Perhaps some client reading their `inbox` might be able to derive some meaning from it...? -### Moving an item to a new position in the list? +#### Inserting multiple items? (WIP) + +Maybe we could do `"object": {"@list": [...]}` but this might not be friendly to LD-unaware processors. Also this doesn't allow for inserting multiple items at different locations, but maybe those should be separate Insert activities/operations anyway. + +### Moving an item to a new position in the list? (WIP) Just like we defined an Insert activity earlier, we might want to use something like a Move activity to reorder our OrderedCollection. Say we have a list in the form `orderedItems: [3, 4, 2, 1]`, perhaps by some permutation of aware or unaware servers leading to the error case from before. Well, how do we fix this? @@ -264,12 +273,18 @@ We might formulate "move `3` to be after `4`" with the following Move activity: "actor": "https://domain.example/some-actor", "type": "Move", "object": "https://domain.example/objects/3", + "origin": "https://domain.example/some-collection", + "target": "https://domain.example/some-collection", "insertAfter": "https://domain.example/objects/4" } ``` This `Move` activity is equivalent to doing a `Remove` first, followed by a new `Insert`; compare to a `Move` activity normally being equivalent to doing a `Remove` first and then following up with an `Add`. +But we run into the same problem as before -- namely, it's not clear whether `Move` in this case means "Remove from `origin` and Add to `target`", or if it means "Remove from `origin` and Insert into `target`". So we probably need a new activity type for this kind of operation. I have no idea what to call it. + +For now, the safest thing is probably to fall back to doing this in 2 activities: first, send a `Remove`, then send an `Insert`. + ### Completely reordering the items Given a complex enough OrderedCollection, you might find it easier to just create a new collection and Add or Insert items as appropriate... but this is not an option if you want to preserve the collection's id. (Well, it could be an option, but you'd have to define a mechanism to reassign identifiers first. Perhaps a `Migrate` activity could be defined in some other FEP? Alternatively, `Move` might work, but I'd be wary of overloading the semantics of "moving" an object. Of course, Mastodon's "account migration" feature already uses `Move` in exactly this overloading way, so...) @@ -294,4 +309,15 @@ So given the same OrderedCollection, we might consider an `Update` that changes } ``` -In the case where an OrderedCollection is *unpaged* but just very very large, then the answer is to simply construct a similarly large Update activity. But the larger the collection grows, the more likely it is to be paged. So if the OrderedCollection is paged and the pages are reified, you might only be able to Update one page at a time. You might even find yourself needing to Move items between one reified page and another! So maybe you can construct a new OrderedCollectionPage and carefully update the `next` and `prev` links of what is effectively a linked list. The exact algorithm for doing this is left as an exercise for the reader, because this is already getting to be a very long post, and adding more examples for this increasingly niche and situation-dependent use case is going to make it even longer... eh, perhaps in a follow-up. \ No newline at end of file +In the case where an OrderedCollection is *unpaged* but just very very large, then the answer is to simply construct a similarly large Update activity. But the larger the collection grows, the more likely it is to be paged. So if the OrderedCollection is paged and the pages are reified, you might only be able to Update one page at a time. You might even find yourself needing to Move items between one reified page and another! So maybe you can construct a new OrderedCollectionPage and carefully update the `next` and `prev` links of what is effectively a linked list. The exact algorithm for doing this is left as an exercise for the reader, because this is already getting to be a very long post, and adding more examples for this increasingly niche and situation-dependent use case is going to make it even longer... eh, perhaps in a follow-up. + +## Current summary and conclusions + +- An OrderedCollection's items are expressed in JSON-LD as a `@list` but the data type is more correctly an ordered set, not an ordered list. This is because of the AS2-Vocab definitions. This means that items can only be included in a Collection at most once. +- Ordering is determined by time-of-insertion and can be signalled by something like a property `orderType` and some classes like `ForwardChronological` and `ReverseChronological` to indicate if the latest appended item will be the first item (LIFO/FILO) or if the latest appended item will be the last item (LILO/FIFO). +- We could define a new type `SortedCollection` specifically for collections that are not only ordered, but also sorted according to some criteria. Time-of-insertion doesn't matter here, as any newly inserted item will take its place within the sorting. We might define the `sortType` somehow using vocab terms again, but it is more useful to use `sortedBy` pointing to a property name, and `sortOrder` can be one of two classes, either `Ascending` (smallest first) or `Descending` (largest first). We might also need a comparison function, but this is currently left unconsidered. +- For cases where the collection is ordered but not sorted, we could define an `Insert` activity and an `insertAfter` property to point to the object after which the Insert's object will be inserted. Currently left unconsidered is the possibility of inserting at a specific index numerically, as well as the ability to `insertBefore`. + - Inserting multiple objects into an OrderedCollection also needs to be thought about. + - Moving items typically is equivalent to Remove then Add. We might need an activity that is equivalent to Remove then Insert, but I have no idea what to call it. For now, the safest thing is probably to fall back to doing this in 2 activities: first, send a `Remove`, then send an `Insert`. + - Items might be completely reordered with an Update targeting the orderedItems property but this can be kinda complicated when dealing with paged collections, especially if pages are reified. You will possibly have to construct new pages and manipulate the `next`/`prev` links between them. +- For now, we neglect to consider or define non-set types, such as List which is explicitly allowed to contain the same item multiple times. \ No newline at end of file diff --git a/unified.test.hugo/layouts/wiki/_markup/render-heading.html b/unified.test.hugo/layouts/_default/_markup/render-heading.html similarity index 71% rename from unified.test.hugo/layouts/wiki/_markup/render-heading.html rename to unified.test.hugo/layouts/_default/_markup/render-heading.html index 1076ca4..4e82fbf 100644 --- a/unified.test.hugo/layouts/wiki/_markup/render-heading.html +++ b/unified.test.hugo/layouts/_default/_markup/render-heading.html @@ -1,4 +1,4 @@ - + {{.Text | safeHTML}} [link] diff --git a/unified.test.hugo/layouts/wiki/_markup/render-link.html b/unified.test.hugo/layouts/_default/_markup/render-link.html similarity index 100% rename from unified.test.hugo/layouts/wiki/_markup/render-link.html rename to unified.test.hugo/layouts/_default/_markup/render-link.html diff --git a/unified.test.hugo/layouts/_default/single.html b/unified.test.hugo/layouts/_default/single.html index 425da3e..e381e76 100644 --- a/unified.test.hugo/layouts/_default/single.html +++ b/unified.test.hugo/layouts/_default/single.html @@ -1,8 +1,11 @@ +{{ define "head" }} +{{ end }} + {{ define "body" }}
-
-