diff --git a/unified.test.hugo/assets/styles/common.scss b/unified.test.hugo/assets/styles/common.scss index a7aa01d..8370506 100644 --- a/unified.test.hugo/assets/styles/common.scss +++ b/unified.test.hugo/assets/styles/common.scss @@ -2,21 +2,28 @@ @import "common/colors"; @import "common/base"; @import "common/typography"; -@import "common/content"; -@import "common/links"; +@import "common/elements"; + +@import "features/links"; +@import "features/syntax-highlighting"; + +@import "components/table-of-contents"; // default layout @import "layouts/_default/list"; @import "layouts/_default/single"; +@import "features/content"; -@import "layouts/_default/_markup/render-codeblock"; @import "layouts/_default/_markup/render-heading"; @import "layouts/_default/_markup/render-link"; @import "layouts/partials/mf2/h-card"; @import "components/admonition"; @import "components/quote-block"; +@import "components/codeblock"; + +@import "features/footnotes"; // wiki layout @@ -27,6 +34,4 @@ @import "layouts/partials/wiki/breadcrumbs"; @import "features/autonumbering"; -@import "features/search"; - -@import "components/table-of-contents"; \ No newline at end of file +@import "features/search"; \ No newline at end of file diff --git a/unified.test.hugo/assets/styles/common/content.scss b/unified.test.hugo/assets/styles/common/content.scss deleted file mode 100644 index 7b503cc..0000000 --- a/unified.test.hugo/assets/styles/common/content.scss +++ /dev/null @@ -1,139 +0,0 @@ -.hugo-content { - > * { - margin-block: 1em; - &:first-child { - margin-block-start: 0; - } - &:last-child { - margin-block-end: 0; - } - } - /* text */ - line-height: 2; - /* semantics */ - em {font-style: italic} - strong {font-weight: bold} - /* text formatting */ - --script-size: 0.65em; - sup { - position: relative; - font-size: var(--script-size); - inset-block-start: -1em; - } - sub { - position: relative; - font-size: var(--script-size); - } - @supports #{'selector\(:has(kbd))'} { - /* style individual keys only (for the innermost element) */ - kbd kbd, - kbd:not(:has(kbd)) { - font-family: monospace; - padding: 0.25em; - background: var(--ui-overlay); - color: var(--ui-overlay-text); - } - } - @supports not #{'selector\(:has(kbd))'} { - /* style the entire key sequence */ - kbd { - font-family: monospace; - padding: 0.25em; - background: var(--ui-overlay); - color: var(--ui-overlay-text); - } - /* and prevent double-styling for nested keys */ - kbd kbd { - background: none; - } - } - mark { - background: var(--primary-accent-transparent); - color: var(--ui-text); - --pad-x-highlight: 0.125em; - padding-inline-start: var(--pad-x-highlight); - padding-inline-end: var(--pad-x-highlight); - } - abbr[title]:after { - content: '?'; - font-size: var(--script-size); - color: var(--ui-text-muted); - } - >*:not(.highlight) code { - font-family: monospace; - background: var(--ui-overlay); - color: var(--ui-overlay-text); - padding: 0.25rem; - font-size: 1rem; - white-space: pre-wrap; - } - /* lists */ - ul, ol { - padding-inline-start: 0; - margin-block: 1em; - position: relative; - } - ul {list-style: disc;} - ol {list-style: decimal;} - li {margin-block-end: 1em; line-height: 2; margin-inline-start: 1em;} - dl {margin-block: 1em; line-height: 1.4;} - dt {font-weight: 700;} - dd {margin-inline-start: 1em;} - pre:not(.chroma) { - font-family: monospace; - font-size: 1rem; - line-height: 1.4; - overflow: auto; - white-space: pre-wrap; - word-break: break-word; - display: grid; - tab-size: 3; - margin-block-end: 1em; - } - /* tables */ - table {text-align: center;} - thead { - font-weight: 700; - background: var(--ui-overlay); - color: var(--ui-overlay-text); - } - th, td { - border: 1px solid var(--ui-text); - padding: 0.5em; - } - /* hugo-specific citation footnote */ - cite sup { - position: inherit; - font-size: inherit; - a { - padding: 0.25em; - } - &:before { - content: ' ['; - } - &:after { - content: ']'; - } - } - /* the actual footnotes section */ - .footnotes { - hr { - display: flex; - align-items: center; - border: 0; - &:before { - content: 'Footnotes'; - color: var(--ui-text); - text-transform: uppercase; - font-weight: 900; - font-size: 0.8em; - } - &:after { - content: ''; - width: 100%; - margin-inline-start: 1rem; - border-block-end: 1px solid var(--ui-text-muted); - } - } - } -} \ No newline at end of file diff --git a/unified.test.hugo/assets/styles/common/elements.scss b/unified.test.hugo/assets/styles/common/elements.scss new file mode 100644 index 0000000..12c8b3a --- /dev/null +++ b/unified.test.hugo/assets/styles/common/elements.scss @@ -0,0 +1,66 @@ +/* render with slight depth */ +@supports #{'selector\(:has(kbd))'} { + /* style individual keys only (for the innermost element) */ + kbd kbd, + kbd:not(:has(kbd)) { + font-family: monospace; + padding: 0.25em; + background: var(--ui-overlay); + color: var(--ui-overlay-text); + border: 1px solid var(--primary-accent-transparent); + margin-inline: 0.25em; + } +} +@supports not #{'selector\(:has(kbd))'} { + /* style the entire key sequence */ + kbd { + font-family: monospace; + padding: 0.25em; + background: var(--ui-overlay); + color: var(--ui-overlay-text); + } + /* and prevent double-styling for nested keys */ + kbd kbd { + background: none; + } +} +/* render as highlighting */ +mark { + background: var(--primary-accent-transparent); + color: var(--ui-text); + --pad-x-highlight: 0.125em; + padding-inline-start: var(--pad-x-highlight); + padding-inline-end: var(--pad-x-highlight); +} +/* lists */ +ul {list-style: disc;} +ol {list-style: decimal;} +/* tables */ +table {text-align: center;} +thead { + font-weight: bold; + background: var(--ui-overlay); + color: var(--ui-overlay-text); +} +th, td { + border: 1px solid var(--ui-text); + padding: 0.5em; +} +/* figures */ +figure { + margin: 0; +} +figcaption { + padding-block: 1em; + padding-inline: 1em; +} +/* extra style and flair */ +code { + background: var(--ui-overlay); + color: var(--ui-overlay-text); + padding: 0.25rem; +} +/* fix pre */ +pre { + margin: 0; +} \ No newline at end of file diff --git a/unified.test.hugo/assets/styles/common/typography.scss b/unified.test.hugo/assets/styles/common/typography.scss index 427bac5..451e22b 100644 --- a/unified.test.hugo/assets/styles/common/typography.scss +++ b/unified.test.hugo/assets/styles/common/typography.scss @@ -10,3 +10,51 @@ h1, h2, h3, h4, h5, h6 { margin-block-end: 1rem; font-weight: bold; } +body {line-height: 2;} +pre { + line-height: 1.2; + font-family: monospace; + font-size: 1rem; + overflow: auto; + white-space: pre-wrap; + word-break: break-word; + tab-size: 3; +} +ul, ol { + padding-inline-start: 0; +} +li { + margin-inline-start: 1em; + margin-block: 1em; +} +dt { + font-weight: bold; +} +dd { + margin-inline-start: 1em; +} +code { + font-family: monospace; + font-size: 1rem; + white-space: pre-wrap; + word-break: break-word; +} +a { + word-break: break-word; +} +/* semantics */ +em {font-style: italic} +strong {font-weight: bold} +/* script */ +html { + --script-size: 0.8em; +} +sup { + position: relative; + font-size: var(--script-size); + inset-block-start: -1em; +} +sub { + position: relative; + font-size: var(--script-size); +} \ No newline at end of file diff --git a/unified.test.hugo/assets/styles/components/admonition.scss b/unified.test.hugo/assets/styles/components/admonition.scss index 34e48f3..70dd454 100644 --- a/unified.test.hugo/assets/styles/components/admonition.scss +++ b/unified.test.hugo/assets/styles/components/admonition.scss @@ -1,33 +1,33 @@ .admonition { background: var(--ui-overlay-transparent); border-inline-start: 0.4em solid var(--ui-overlay); - border-radius: 0.5em; - padding-inline: 1.5em; - padding-block: 1em; + border-radius: 1em; + padding-block-start: 1em; + padding-block-end: 1em; position: relative; &-header { display: contents; } &__icon { position: absolute; - inset-inline-start: -0.4em; - inset-block-start: -0em; - padding: 0.25em; box-sizing: border-box; - font-size: 3em; - border-radius: 100em; background: var(--ui-overlay); + border-radius: 100em; + /* position the icon */ + font-size: 3em; + padding: 0.25em; + inset-inline-start: -0.175em; + inset-block-start: -0em; } &__title { font-size: 1em; font-weight: bold; padding-inline: 1em; margin-block-start: -0.5em; - margin-inline-start: 0.25em; - margin-block-end: 0; + margin-inline-start: 2em; + margin-block-end: 0.5em; } &__text { - margin-inline-start: 0.25em; padding-inline: 1em; > *:first-child { margin-block-start: 0; diff --git a/unified.test.hugo/assets/styles/components/codeblock.scss b/unified.test.hugo/assets/styles/components/codeblock.scss new file mode 100644 index 0000000..1e8d633 --- /dev/null +++ b/unified.test.hugo/assets/styles/components/codeblock.scss @@ -0,0 +1,12 @@ +.codeblock { + &__header { + background: var(--ui-overlay); + padding-block: 0.25em; + padding-inline: 1em; + } + &__title { + margin: 0; + font-weight: bold; + font-family: monospace; + } +} \ No newline at end of file diff --git a/unified.test.hugo/assets/styles/components/table-of-contents.scss b/unified.test.hugo/assets/styles/components/table-of-contents.scss index 9103b50..d5c7153 100644 --- a/unified.test.hugo/assets/styles/components/table-of-contents.scss +++ b/unified.test.hugo/assets/styles/components/table-of-contents.scss @@ -1,9 +1,15 @@ -.toc-title { - margin-block-end: 0.5em; - font-weight: 900; - text-transform: uppercase; -} -#TableOfContents { +.table-of-contents { + &__title { + margin-block-start: 1em; + margin-block-end: 0.5em; + font-weight: 900; + text-transform: uppercase; + font-size: 1rem; + &:before { + content: '' !important; // if autonumbering is enabled, remove it from the heading + counter-reset: h2 // and don't increment the count for the rest of the content + } + } ul, ol { list-style: none; margin: 0; @@ -12,18 +18,12 @@ li { margin-block: 0.5em; margin-inline: 0; + line-height: 1.5; } a { display: inline; - line-height: 1.5; } li > ul, li > ol { /* indent subheadings */ margin-inline-start: 1em; } -} -.toc details { - max-width: 45ch; - background: rgba(0,0,0,0.1); - padding: 1em; - border-radius: 0.5em; } \ No newline at end of file diff --git a/unified.test.hugo/assets/styles/features/autonumbering.scss b/unified.test.hugo/assets/styles/features/autonumbering.scss index 50acfd6..74c1eb6 100644 --- a/unified.test.hugo/assets/styles/features/autonumbering.scss +++ b/unified.test.hugo/assets/styles/features/autonumbering.scss @@ -1,4 +1,4 @@ -body {counter-reset: h2} +body {counter-reset: h2 figure table} h2 {counter-reset: h3} h3 {counter-reset: h4} h4 {counter-reset: h5} @@ -35,14 +35,14 @@ article[autonumbering] { font-size: 1rem; } - #TableOfContents :is(ol, ul) { + .table-of-contents :is(ol, ul) { /* each list gets a new counter */ counter-reset: item; margin-inline-start: 0; } - #TableOfContents li:before { + .table-of-contents li:before { /* the counter is added as a pseudo-element, and nested counters are joined by a dot @@ -54,12 +54,17 @@ article[autonumbering] { font-weight: bold; margin-inline-end: 1em; } - #TableOfContents > ul > li { - /* - top-level items wrap after the number, - in order to add some visual separation - */ - display: flex; - flex-flow: column; + /* tables and figures */ + caption { + counter-increment: table; + &:before { + content: "Table " counter(table) ": "; + } + } + figcaption { + counter-increment: figure; + &:before { + content: "Figure " counter(figure) ": "; + } } } \ No newline at end of file diff --git a/unified.test.hugo/assets/styles/features/content.scss b/unified.test.hugo/assets/styles/features/content.scss new file mode 100644 index 0000000..d44b04f --- /dev/null +++ b/unified.test.hugo/assets/styles/features/content.scss @@ -0,0 +1,11 @@ +.hugo-content { + > * { + margin-block: 1em; + &:first-child { + margin-block-start: 0; + } + &:last-child { + margin-block-end: 0; + } + } +} \ No newline at end of file diff --git a/unified.test.hugo/assets/styles/features/footnotes.scss b/unified.test.hugo/assets/styles/features/footnotes.scss new file mode 100644 index 0000000..69dc81c --- /dev/null +++ b/unified.test.hugo/assets/styles/features/footnotes.scss @@ -0,0 +1,29 @@ +.footnote-ref { + font-weight: bold; + &:before { + content: " ["; + } + &:after { + content: "] " + } +} +.footnotes { + hr { + display: flex; + align-items: center; + border: 0; + &:before { + content: "Footnotes"; + color: var(--ui-text); + text-transform: uppercase; + font-weight: 900; + font-size: 0.8em; + } + &:after { + content: ''; + width: 100%; + margin-inline-start: 1rem; + border-block-end: 1px solid var(--ui-overlay); + } + } +} \ No newline at end of file diff --git a/unified.test.hugo/assets/styles/common/links.scss b/unified.test.hugo/assets/styles/features/links.scss similarity index 100% rename from unified.test.hugo/assets/styles/common/links.scss rename to unified.test.hugo/assets/styles/features/links.scss diff --git a/unified.test.hugo/assets/styles/layouts/_default/_markup/render-codeblock.scss b/unified.test.hugo/assets/styles/features/syntax-highlighting.scss similarity index 90% rename from unified.test.hugo/assets/styles/layouts/_default/_markup/render-codeblock.scss rename to unified.test.hugo/assets/styles/features/syntax-highlighting.scss index f8e0e06..0e00473 100644 --- a/unified.test.hugo/assets/styles/layouts/_default/_markup/render-codeblock.scss +++ b/unified.test.hugo/assets/styles/features/syntax-highlighting.scss @@ -24,13 +24,13 @@ --error: #cc0000; --keyword: hsl(210, 100%, 75%); - --name: green; + --name: lightgreen; --literal: hsl(210, 100%, 60%); --comment: hsl(210, 50%, 45%); - --generic: purple; + --generic: cyan; --whitespace: black; - --highlight: hsl(210, 100%, 25%); + --highlight: hsl(210, 100%, 20%); --linenos: var(--comment); --linenos-background: hsl(210, 100%, 5%); @@ -39,44 +39,48 @@ color: black; } } - pre.chroma { - overflow: auto; + .chroma { + overflow-inline: auto; + display: grid; span { - -webkit-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; // fix a safari bug font-size: 1em; - } - .ln { - font-size: 1em; - margin-inline-end: 1em; - background: var(--linenos-background); - padding-block: 0.25em; - display: flex; - width: 2em; - } - .hl .ln { - background: var(--highlight); + line-height: 1.5; } .line { display: grid; - grid-template-columns: max-content 1fr; - .cl { - grid-column: 2; - } + grid-template-columns: auto 1fr; } - .cl { - padding-inline: 1em; + .ln { // line number + grid-column: 1; + font-size: 1em; + background: var(--linenos-background); padding-block: 0.25em; - word-break: break-all; + display: flex; + justify-content: end; + margin: 0; } - .line:first-child { - .ln, .cl { - padding-block-start: 1em; + .cl { // code line + grid-column: 2; + > * { + display: inline-flex; + height: 100%; + align-items: center; } + padding-inline: 0.5em; } - .line:last-child { - .ln, .cl { - padding-block-end: 1em; - } + + .line:first-child .cl { + padding-block-start: 1em; + } + .line:last-child .cl { + padding-block-end: 1em; + } + :is(.line:first-child, .line:last-child) .ln ~ .cl { + padding-block: 0em; + } + .hl > * { // highlight + background: var(--highlight); } } } @@ -88,10 +92,9 @@ /* CodeLine */ .chroma .cl { color: var(--text) } /* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; } /* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; } -/* LineHighlight */ .chroma .hl { background-color: var(--highlight) } /* LineNumbersTable */ .chroma .lnt { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: var(--linenos) } /* LineNumbers */ .chroma .ln { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: var(--linenos) } -/* Line */ .chroma .line { display: flex; white-space: pre } +/* Line */ .chroma .line { white-space: pre } /* Keyword */ .chroma .k { color: var(--keyword); font-weight: bold } /* KeywordConstant */ .chroma .kc { color: var(--keyword); font-weight: bold } /* KeywordDeclaration */ .chroma .kd { color: var(--keyword); font-weight: bold } diff --git a/unified.test.hugo/assets/styles/layouts/_default/list.scss b/unified.test.hugo/assets/styles/layouts/_default/list.scss index bb79e07..2edfacd 100644 --- a/unified.test.hugo/assets/styles/layouts/_default/list.scss +++ b/unified.test.hugo/assets/styles/layouts/_default/list.scss @@ -1,26 +1,43 @@ .layout-_default-list { .list-header { - padding: 1em; hr {display: none;} + .container { + max-width: 80ch; + margin-inline: auto; + } } .list-title { - margin-block: 0; + margin-block-start: 0; + font-size: 2.025rem; + line-height: 1.15; + letter-spacing: -0.022rem; + grid-area: title; } .list-author {} - .list-summary {} + .list-summary { + font-style: italic; + font-size: 1.266rem; + line-height: 1.15; + letter-spacing: -0.022rem; + margin-block-start: 0.5rem; + grid-area: summary; + } .list-content {} .list-permalink { .u-url {font-family: monospace;} } .list-pages { - padding-inline: 1em; - .list-of-pages-in-section { + max-width: 80ch; + margin-inline: auto; + .pages-list { list-style: none; padding-inline-start: 0; &__item { - max-width: 80ch; + margin-inline-start: 0; .p-name { font-weight: bold; + font-size: 1em; + display: inline; } .p-summary { font-style: italic; @@ -28,4 +45,9 @@ } } } + @media (min-width: 400px) { + .container { + padding: 0 2em; + } + } } \ No newline at end of file diff --git a/unified.test.hugo/assets/styles/layouts/_default/single.scss b/unified.test.hugo/assets/styles/layouts/_default/single.scss index 231e233..1ecdbb1 100644 --- a/unified.test.hugo/assets/styles/layouts/_default/single.scss +++ b/unified.test.hugo/assets/styles/layouts/_default/single.scss @@ -48,6 +48,7 @@ .page-permalink { margin-block-end: 0; align-self: end; + .u-url {font-family: monospace;} } .page-series { // background: var(--ui-overlay); @@ -79,52 +80,37 @@ } } } - .page-toc { - display: none; - } .page-content { + width: 100%; max-width: 80ch; margin-inline: auto; } .page[has-toc] { padding-block-end: 4em; } + .page > .table-of-contents { + display: none; + } #toc-toggle { display: none; - &:checked ~ .page-toc { + &:checked ~ .table-of-contents { display: block; position: fixed; z-index: 10; - bottom: 5em; - height: 40em; + bottom: 6em; + height: max-content; width: 80%; max-width: 20em; - max-height: 70vh; + max-height: #{min}(40em, 70vh); overflow-y: scroll; right: 1em; background: var(--ui-overlay); border-radius: 1em; @include shadow-low; - padding: 0; + padding-inline: 1em; > .container { padding: 0; } - details { - display: contents; - summary { - display: none; - } - #TableOfContents { - padding: 1em; - &:before { - content: 'Contents'; - font-size: 1em; - font-weight: 900; - color: var(--ui-overlay-text); - text-transform: uppercase; - } - } - } } } label[for="toc-toggle"] { @@ -182,7 +168,7 @@ grid-column: 2 / span 2; } } - .page-toc { + .table-of-contents { display: block; grid-column: 3; grid-row: 2; @@ -202,13 +188,6 @@ &::-webkit-scrollbar-track { background-color: var(--ui-overlay) } - details { - padding: 0; - background: none; - #TableOfContents { - padding-left: 0em; - } - } } .page-content { grid-column: 2; diff --git a/unified.test.hugo/assets/styles/layouts/partials/mf2/h-card.scss b/unified.test.hugo/assets/styles/layouts/partials/mf2/h-card.scss index 34de792..5efec0c 100644 --- a/unified.test.hugo/assets/styles/layouts/partials/mf2/h-card.scss +++ b/unified.test.hugo/assets/styles/layouts/partials/mf2/h-card.scss @@ -1,15 +1,20 @@ .author-card { + display: inline-flex; + align-items: center; + gap: 0.5em; .author-card__link { text-decoration: none; color: inherit; - font-weight: bold; - display: inline-flex; - align-items: center; - gap: 0.5em; + display: contents; + &:after { + display: none; // suppress "external links" icon + } } &__avatar { width: 3em; border-radius: 100em; } - + &__name { + font-weight: bold; + } } \ No newline at end of file diff --git a/unified.test.hugo/assets/styles/screen.scss b/unified.test.hugo/assets/styles/screen.scss index 89020dd..dd9743a 100644 --- a/unified.test.hugo/assets/styles/screen.scss +++ b/unified.test.hugo/assets/styles/screen.scss @@ -1 +1,2 @@ -@import "common"; \ No newline at end of file +@import "common"; + diff --git a/unified.test.hugo/content/_dump/articles/att-ftc-fcc-doublespeak/index.md b/unified.test.hugo/content/_dump/articles/att-ftc-fcc-doublespeak/index.md index bb376e6..5d1800a 100644 --- a/unified.test.hugo/content/_dump/articles/att-ftc-fcc-doublespeak/index.md +++ b/unified.test.hugo/content/_dump/articles/att-ftc-fcc-doublespeak/index.md @@ -2,7 +2,7 @@ title = "AT&T is pulling some serious doublespeak right now." summary = "Is AT&T a common carrier, according to AT&T? It depends on who's asking." date = 2015-01-10T12:00:00-06:00 -tags = [] +tags = ["att", "ftc", "fcc"] categories = [] [[params.inReplyTo]] name = "AT&T defends unlimited data throttling, says the FTC can’t stop it" diff --git a/unified.test.hugo/content/_dump/replies/socialhub-4564-37/index.md b/unified.test.hugo/content/_dump/replies/socialhub-4564-37/index.md index b767ec0..cc7378e 100644 --- a/unified.test.hugo/content/_dump/replies/socialhub-4564-37/index.md +++ b/unified.test.hugo/content/_dump/replies/socialhub-4564-37/index.md @@ -12,7 +12,6 @@ url = "https://socialhub.activitypub.rocks/t/socialwebfoundation-what-do-people- > I think that, before we had an open standard for social networking, protocol experimentation was more important. Now that we have an open standard, with a hundred implementations, tens of thousands of nodes, and tens of millions of users, I think efforts should go into encouraging the use of that standard and enhancing it through backwards-compatible extensions, rather than starting the whole process from the ground up. {cite="https://socialhub.activitypub.rocks/t/socialwebfoundation-what-do-people-think/4564/36" card="socialhub.activitypub.rocks/eprodrom"} - I think this is a bit too conservative of a take regarding backwards-compatibility. I really don’t think we’re at any sort of broad alignment, even within the ActivityPub space alone. Just about the only thing we universally do is POST to inbox. That payload is AS2 Activities. Things tighten up a bit when you consider e.g. the "Mastodon Protocol" as defined by https://docs.joinmastodon.org/spec/activitypub but even then, not everyone follows this protocol, and as a protocol, it’s got a lot of missing bits that are very important for a "social networking protocol" to have, not to mention it doesn’t closely follow the requirements laid out in AP or AS2. The main criticism that several people have raised (@hrefna @stevebate and @jenniferplusplus in particular) is that any interop we have on the fediverse today is more the result of the blood, sweat, and tears of implementers than it is the “open standard” that pretty much no one implements to the letter. The far more common outcome is to reverse-engineer Mastodon, or reverse-engineer Lemmy, with the aid of their documentation, with lots of hours spent looking at the code, and with outreach and collaboration involving other implementers. Honestly, looking at the ActivityPub spec over and over and over and over and over (as I’ve done countless times), the well-defined parts that stick out are: diff --git a/unified.test.hugo/content/_index.md b/unified.test.hugo/content/_index.md index f7ba421..45f67f4 100644 --- a/unified.test.hugo/content/_index.md +++ b/unified.test.hugo/content/_index.md @@ -1,2 +1,4 @@ +++ +title = "~a" +summary = "i have approximate knowledge of many things. perpetual student. (nb/ace/they)" +++ \ No newline at end of file diff --git a/unified.test.hugo/content/_sitemap.md b/unified.test.hugo/content/_sitemap.md new file mode 100644 index 0000000..11596ee --- /dev/null +++ b/unified.test.hugo/content/_sitemap.md @@ -0,0 +1,7 @@ ++++ +title = "Sitemap" +type = "_default" +layout = "sitemap" +_build.list="never" +slug = "sitemap" ++++ \ No newline at end of file diff --git a/unified.test.hugo/content/essays/social-network-vs-social-web/index.md b/unified.test.hugo/content/essays/social-network-vs-social-web/index.md new file mode 100644 index 0000000..e2f4b6f --- /dev/null +++ b/unified.test.hugo/content/essays/social-network-vs-social-web/index.md @@ -0,0 +1,6 @@ ++++ +title = "Social Network versus Social Web" +date = 2024-10-12T13:03:23-06:00 +toc = true +draft = true ++++ \ No newline at end of file diff --git a/unified.test.hugo/content/essays/worse-is-worse/index.md b/unified.test.hugo/content/essays/worse-is-worse/index.md index 7f5b859..413e877 100644 --- a/unified.test.hugo/content/essays/worse-is-worse/index.md +++ b/unified.test.hugo/content/essays/worse-is-worse/index.md @@ -2,6 +2,7 @@ title = "Worse is worse" date = 2024-10-12T13:03:23-06:00 toc = true +draft = true +++ sure, "worse is better", but also, worse is worse. diff --git a/unified.test.hugo/content/monologues/_index.md b/unified.test.hugo/content/monologues/_index.md index fa504da..1f08af0 100644 --- a/unified.test.hugo/content/monologues/_index.md +++ b/unified.test.hugo/content/monologues/_index.md @@ -1,7 +1,7 @@ +++ title = "monologues" name = "~a | monologues" -summary = "mostly a compilation of times i replied to myself on social media or in chat. what you see here is minimally curated and lightly formatted. it might disappear at any time or be upgraded to a proper or formal writing at some point." +summary = "assorted musings. mostly a compilation of times i replied to myself on social media or in chat. what you see here is minimally curated and lightly formatted. it might disappear at any time or be upgraded to a proper or formal writing at some point." [pagination] pagerSize = 100 +++ diff --git a/unified.test.hugo/content/monologues/worse-is-worse/index.md b/unified.test.hugo/content/monologues/worse-is-worse/index.md new file mode 100644 index 0000000..7ec7a25 --- /dev/null +++ b/unified.test.hugo/content/monologues/worse-is-worse/index.md @@ -0,0 +1,12 @@ ++++ +title = "worse is worse" +summary = "sure, \"worse is better\", but also, worse is worse. the main thesis is that a) we keep dooming ourselves to \"worse\" futures than what could have been, b) we ought not to \"settle\" for the \"worse\" thing, c) things can be \"worse\" but do they really have to be *that much* \"worse\"?" +date = "2024-10-12T11:56:00-06:00" +source = "https://mastodon.social/@trwnh/113295504458006091" ++++ + +sure, "worse is better", but also, worse is worse. + +might expand on this when i have the time, but the main thesis is that a) we keep dooming ourselves to "worse" futures than what could have been, b) we ought not to "settle" for the "worse" thing, c) things can be "worse" but they really don't have to be *that much* "worse" + +conclusion: it may be a pattern, but consigning yourself to it as a mindset is a form of abdication \ No newline at end of file diff --git a/unified.test.hugo/content/streams/all/_index.md b/unified.test.hugo/content/streams/all/_index.md new file mode 100644 index 0000000..e03a584 --- /dev/null +++ b/unified.test.hugo/content/streams/all/_index.md @@ -0,0 +1,4 @@ ++++ +title = "All posts" +summary = "Follow this stream to get all of my posts." ++++ \ No newline at end of file diff --git a/unified.test.hugo/content/theorycrafting/_index.md b/unified.test.hugo/content/theorycrafting/_index.md new file mode 100644 index 0000000..5308e8a --- /dev/null +++ b/unified.test.hugo/content/theorycrafting/_index.md @@ -0,0 +1,4 @@ ++++ +title = "theorycrafting" +summary = "explorations and thinkpieces about potential concepts. whether they are of use to anyone else remains to be seen." ++++ \ No newline at end of file diff --git a/unified.test.hugo/content/articles/evolving-orderedcollection-to-be-more-useful/index.md b/unified.test.hugo/content/theorycrafting/evolving-orderedcollection-to-be-more-useful/index.md similarity index 71% rename from unified.test.hugo/content/articles/evolving-orderedcollection-to-be-more-useful/index.md rename to unified.test.hugo/content/theorycrafting/evolving-orderedcollection-to-be-more-useful/index.md index cbcdd6e..db9efb5 100644 --- a/unified.test.hugo/content/articles/evolving-orderedcollection-to-be-more-useful/index.md +++ b/unified.test.hugo/content/theorycrafting/evolving-orderedcollection-to-be-more-useful/index.md @@ -3,6 +3,8 @@ title = "Evolving OrderedCollection to be more useful" date = 2024-10-04T21:50:07-06:00 toc = true autonumbering = true +streams = ["all"] +tags = ["activitypub", "orderedcollection", "as2"] [[params.inReplyTo]] name = "Reordering user-created collections" url = "https://github.com/w3c/activitypub/issues/439" @@ -25,8 +27,8 @@ If you define a Collection in terms of `items`, then it is pretty clearly a Set, If you define OrderedCollection in terms of `orderedItems`, then this is simply a term which defines `as:items` with a `@container: @list`, so declaring `orderedItems` instead of `items` will use the JSON-LD `@list` container instead of using the JSON-LD `@set` container. One notable thing about the `@list` container is that it is not the same as an OrderedSet -- it can actually contain duplicates. In JSON-LD, this is clearly described as an "ordered list". For example: -```json -{"@list": [{"@value": 10.0}, {"@value": 10.0}]} +```json{title="list.jsonld" caption="An ordered list containing the same object twice."} +{"@list": [{"@id": "https://url.example"}, {"@id": "https://url.example"}]} ``` ### The argument for OrderedSet @@ -34,11 +36,10 @@ If you define OrderedCollection in terms of `orderedItems`, then this is simply The problem with taking OrderedCollection to be defined in terms of `orderedItems` is that OrderedCollection in AS2-Vocab is actually defined as *inheriting from* Collection. The actual definitions given are the following: > A `Collection` is a subtype of `Object` that represents ordered or unordered sets of `Object or Link` instances. -{cite="https://www.w3.org/TR/activitystreams-vocabulary/#dfn-collection" name="Activity Vocabulary § 2 \"Core Types\" # Collection"} - +{cite="https://www.w3.org/TR/activitystreams-vocabulary/#dfn-collection" title="Activity Vocabulary" ref="§ 2 \"Core Types\" # Collection"} > A subtype of `Collection` in which members of the logical collection are assumed to always be strictly ordered. -{cite="https://www.w3.org/TR/activitystreams-vocabulary/#dfn-orderedcollection" name="Activity Vocabulary § 2 \"Core Types\" # OrderedCollection"} +{cite="https://www.w3.org/TR/activitystreams-vocabulary/#dfn-orderedcollection" title="Activity Vocabulary" ref="§ 2 \"Core Types\" # OrderedCollection"} So if Collection is a set (ordered or unordered), and OrderedCollection inherits from Collection, then OrderedCollection is logically implied to also be a set (ordered). @@ -50,7 +51,8 @@ Put another way: does Adding an item into an OrderedCollection simply append at To give a concrete example, consider how ActivityPub mandates that OrderedCollection MUST be reverse chronological. (This has been the subject of an errata intending to relax this requirement to only apply to the properties defined as OrderedCollection *within ActivityPub*, but the general problem still applies.) ActivityPub gives this clarifying note: -> What property is used to determine the reverse chronological order is intentionally left as an implementation detail. For example, many SQL-style databases use an incrementing integer as an identifier, which can be reasonably used for handling insertion order in most cases. In other databases, an insertion time timestamp may be preferred. What is used isn't important, but the ordering of elements must remain intact, with newer items first. A property which changes regularly, such a "last updated" timestamp, should not be used. +> What property is used to determine the reverse chronological order is intentionally left as an implementation detail. For example, many SQL-style databases use an incrementing integer as an identifier, which can be reasonably used for handling insertion order in most cases. In other databases, an insertion time timestamp may be preferred. What is used isn't important, but the ordering of elements must remain intact, with newer items first. A property which changes regularly, such a "last updated" timestamp, should not be used. +{cite="https://www.w3.org/TR/activitypub/#collections" title="ActivityPub" ref="§ 5 \"Collections\" # Note 3"} So this clearly points toward using something like "insertion time" or "incrementing integer", which means that an Add targeting an OrderedCollection will by default insert the new item at the end of the `@list`. Or the beginning, once it's reversed. @@ -72,9 +74,9 @@ The ordering happens based on each `https://schema.org/ListItem` having a `https It doesn't immediately make sense to put `nextItem` and `previousItem` style links directly on the object, because an object may be part of multiple collections. I guess you could maybe inject those properties when rendering or presenting an OrderedCollection, but this wouldn't really make sense either. The ordering in an OrderedCollection is already handled by JSON-LD's `@list` container, which in plain JSON would be an ordered array. (With paging, you can follow `as:first`/`as:next`* or you can follow `as:last`/`as:prev`* to traverse the entire OrderedCollection, one OrderedCollectionPage at a time.) -So maybe we could define some property `orderType`, which gives a hint as to how the collection is ordered? The value of this property is left kind of open-ended, but it could be handled by vocabulary terms, if you just define the `orderType` term as `@type: @vocab`. This would allow you to explicitly define classes for things like `ReverseChronological`, `ForwardChronological`, or any other well-defined specific concept: +So maybe we could define some property `orderType`, which gives a hint as to how the collection is ordered? The value of this property is left kind of open-ended, but it could be handled by vocabulary terms, if you just define the `orderType` term as `@type: @vocab`. This would allow you to explicitly define classes for things like `ReverseChronological`, `ForwardChronological`, or any other well-defined specific concept. -```json +```json{title="reversechronological-orderedcollection.jsonld" caption="An OrderedCollection that has been explicitly declared to be reverse chronological, instead of assuming it to be so by default." hl_lines=["5-8","9-10",20]} { "@context": [ "https://www.w3.org/ns/activitystreams", @@ -104,7 +106,7 @@ This at least gives us one more option to be expressive; we are no longer assumi It may be that Adding something into the collection *doesn't* simply append it at the end, but rather causes the entire collection to be re-sorted. For example, consider a collection representing a conversation which is ordered "forward chronologically", but in constructing the collection, we missed an item somewhere in the middle. Rather than start over entirely, or just living with having the missed item be appended out-of-order at the end, we might instead define a new type of collection to handle this use case. Whereas the `Collection` represents an UnorderedSet data type, and an `OrderedCollection` represents an OrderedSet data type, we can define `SortedCollection` to represent a SortedSet. It inherits from OrderedCollection, since a SortedSet is just an OrderedSet that reorders itself upon any new insertion. We can also define a property `sortType` which is an analogue of the `orderType` we defined above. -```json +```json{title="sortedcollection-idea-1.jsonld" caption="A collection that is sorted \"reverse chronologically\"... but what does that mean?" hl_lines=[11,"12-15",19,25] } { "@context": [ "https://www.w3.org/ns/activitystreams", @@ -135,9 +137,9 @@ It may be that Adding something into the collection *doesn't* simply append it a But now we run into a caveat: it might not be sufficient to define classes/types for `sortType`, because the sorting might happen based on some property instead. So it looks like we're gonna need another mechanism... -Maybe something like `sortedBy` and `sortOrder`? These would both be `@type: @vocab`. The `sortedBy` would be a functional property that indicates which property is being used for sorting, for example, we could sort by `as:published` (although perhaps we shouldn't?); the `sortOrder` would take one of two type/class/vocab values: either `Ascending` or `Descending`. So our example object and context is starting to look like this: +Maybe something like `sortedBy` and `sortOrder`? These would both be `@type: @vocab`. The `sortedBy` would be a functional property that indicates which property is being used for sorting, so for example, we could sort by `as:published` (although perhaps we shouldn't?); meanwhile, the `sortOrder` would take one of two type/class/vocab values: either `Ascending` or `Descending`. So our example object and context is starting to look like this: -```json +```json{title="sortedcollection-idea-2.jsonld" caption="A collection that is specifically sorted by the value of as:published in ascending order, i.e. with older dates first."} { "@context": [ "https://www.w3.org/ns/activitystreams", @@ -169,13 +171,13 @@ Maybe something like `sortedBy` and `sortOrder`? These would both be `@type: @vo "https://domain.example/objects/1" ], "sortedBy": "published", - "sortOrder": "Descending" + "sortOrder": "Ascending" } ``` Now finally, we can send an Add and know for sure that it will be inserted in the right index/position of the underlying `@list` container: -```json +```json{title="add-to-sortedcollection.jsonld" caption="Adding an item to a SortedCollection whose sorting key is in the middle of existing items, causing the collection to reorder itself automatically."} { "@context": "https://www.w3.org/ns/activitystreams", "id": "https://domain.example/some-activity", @@ -188,7 +190,7 @@ 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. +We might also need a comparison function, but this is currently left unconsidered. Maybe we can generally assume that strings will be sorted lexically, and anything that can be coerced into a number (i.e. either it is a number in JSON-LD, or it is a `@value` whose `@type` is something like `http://www.w3.org/2001/XMLSchema#integer`) will be coerced into a number and compared by its magnitude. ## Q3: Are there other ways to approach insertion into an OrderedCollection? @@ -200,7 +202,7 @@ In the most basic case, this might be doable with a property like `insertAfter`? Say we have `orderedItems: [4, 2, 1]`. We might formulate the following Add activity: -```json +```json{title="Add-with-insertAfter.jsonld" caption="An Add activity with an insertAfter property."} { "@context": [ "https://www.w3.org/ns/activitystreams", @@ -223,7 +225,7 @@ Did you spot the flaw in this? We have a problem: the receiving server might not This can be fixed by changing the `Add` to an `Insert`. Now, the server has to specifically understand the Insert activity and its side effects, or else the activity will not be processed. -```json +```json{title="insert.jsonld" caption="An Insert activity, using the insertAfter property."} { "@context": [ "https://www.w3.org/ns/activitystreams", @@ -253,13 +255,13 @@ Maybe we could do `"object": {"@list": [...]}` but this might not be friendly to ### 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? +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? What we want in this case is to move `3` to be after `4`. (Alternatively, we can achieve the same result by moving `4` to come before `3`, but we already established that "insert before" is harder than "insert after". If we need to reconsider this, then it can be reconsidered.) -We might formulate "move `3` to be after `4`" with the following Move activity: +We might formulate "move `3` to be after `4`" with the following `Move` activity: -```json +```json{title="Move-within-collection.jsonld" caption="A Move activity which attempts to change an item's position within that collection."} { "@context": [ "https://www.w3.org/ns/activitystreams", @@ -289,11 +291,11 @@ For now, the safest thing is probably to fall back to doing this in 2 activities ### 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...) +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...) -So given the same OrderedCollection, we might consider an `Update` that changes the `orderedItems` around: +So given the same `OrderedCollection`, we might consider an `Update` that changes the `orderedItems` around: -```json +```json{title="Update-orderedItems.jsonld" caption="An Update activity that updates the orderedItems to be in the correct order."} { "@context": "https://www.w3.org/ns/activitystreams", "id": "https://domain.example/some-activity", @@ -311,15 +313,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. +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. +- 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 +- 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 -- it can be generally expected that strings can be sorted lexigraphically and numbers can be sorted by magnitude (with some consideration toward coercing any string literal `@value` if its `@type` is something like `http://www.w3.org/2001/XMLSchema#integer`). +- 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.object` will be inserted. Currently left unconsidered is the possibility of inserting at a specific index numerically (which would likely cause problems if processed out-of-order), as well as the ability to `insertBefore`. + - Inserting multiple objects into an `OrderedCollection` also needs to be thought about. + - `Move`ing 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 a potential `List` which is explicitly allowed to contain the same item multiple times. For this, use the JSON-LD `@list` or the `rdf:List` class with `rdf:first`, `rdf:rest`, and `rdf:nil`. \ No newline at end of file diff --git a/unified.test.hugo/content/theorycrafting/marking-up-quotes/index.md b/unified.test.hugo/content/theorycrafting/marking-up-quotes/index.md new file mode 100644 index 0000000..c1af318 --- /dev/null +++ b/unified.test.hugo/content/theorycrafting/marking-up-quotes/index.md @@ -0,0 +1,163 @@ ++++ +title = "Marking up quotes" +summary = "In which I explore the semantics and properties of a quote, and how it differs from a citation or reference" +date = "2024-10-12T18:07:26-06:00" +streams = ["all"] +toc = true +autonumbering = false ++++ + +## preamble + +i was looking at Hugo's recent-ish feature for render hooks, specifically new support for render-blockquote.html which allows doing some cool things with markdown blockquotes, like rendering them as alerts or admonitions: + +```md{title="alert.md"} +> [!tip] +> lorem ipsum +``` + +you can also set `markup.goldmark.parser.attribute.block = true` in your hugo.toml config file, which enables support for the "block attributes" syntax: + +```md{title="block-attributes.md"} +> lorem ipsum +{cite="http://example.com/something"} +``` + +so i implemented support for these new features using the following logic: + +- if it has an `{{.AlertType}}` then it's not a quote, it's an alert/admonition/tip/note/etc. i choose to render these as `