1
0
Fork 0
mirror of https://git.sr.ht/~seirdy/seirdy.one synced 2024-09-19 20:02:10 +00:00

Compare commits

...

8 commits

Author SHA1 Message Date
Rohan Kumar
00d3b170b2
Fix bad markup 2022-06-10 19:41:35 -07:00
Rohan Kumar
7833fcd15d
Revert changes to mention-work 2022-06-10 19:35:33 -07:00
Rohan Kumar
f230a23b55
Typo 2022-06-10 19:33:36 -07:00
Rohan Kumar
a502691c38
New post: CLI best practices 2022-06-10 19:24:54 -07:00
Rohan Kumar
0e86aa6ba7
Clarify implicit CSP directives in privacy policy 2022-06-10 19:22:55 -07:00
Rohan Kumar
c41e602ed1
Add info on site design 2022-06-10 18:49:31 -07:00
Rohan Kumar
21aca6d4fe
Fix: don't put onion links in gemini capsule 2022-06-10 18:41:21 -07:00
Rohan Kumar
666342d867
mention Brave SpeedReader 2022-06-10 17:25:16 -07:00
12 changed files with 504 additions and 16 deletions

View file

@ -117,20 +117,22 @@ deploy-prod: .prepare-deploy
.PHONY: deploy-onion
deploy-onion:
@$(MAKE) WWW_ROOT=/var/www/seirdy.onion HUGO_BASEURL='http://wgq3bd2kqoybhstp77i3wrzbfnsyd27wt34psaja4grqiezqircorkyd.onion/' OUTPUT_DIR=public_onion deploy-prod
@$(MAKE) WWW_ROOT=/var/www/seirdy.onion HUGO_BASEURL='http://wgq3bd2kqoybhstp77i3wrzbfnsyd27wt34psaja4grqiezqircorkyd.onion/' OUTPUT_DIR=public_onion .prepare-deploy
@$(MAKE) WWW_ROOT=/var/www/seirdy.onion HUGO_BASEURL='http://wgq3bd2kqoybhstp77i3wrzbfnsyd27wt34psaja4grqiezqircorkyd.onion/' OUTPUT_DIR=public_onion compress
@$(MAKE) WWW_ROOT=/var/www/seirdy.onion HUGO_BASEURL='http://wgq3bd2kqoybhstp77i3wrzbfnsyd27wt34psaja4grqiezqircorkyd.onion/' OUTPUT_DIR=public_onion deploy-html
# we only deploy html to the staging site
.PHONY: deploy-staging
deploy-staging:
@$(MAKE) DOMAIN=staging.seirdy.one USER=deploy@seirdy.one OUTPUT_DIR=public_staging .prepare-deploy
@$(MAKE) DOMAIN=staging.seirdy.one USER=deploy@seirdy.one OUTPUT_DIR=public_staging compress
@$(MAKE) DOMAIN=staging.seirdy.one USER=deploy@seirdy.one OUTPUT_DIR=public_staging deploy-html
@$(MAKE) HUGO_FLAGS=-DF DOMAIN=staging.seirdy.one USER=deploy@seirdy.one OUTPUT_DIR=public_staging .prepare-deploy
@$(MAKE) HUGO_FLAGS=-DF DOMAIN=staging.seirdy.one USER=deploy@seirdy.one OUTPUT_DIR=public_staging compress
@$(MAKE) HUGO_FLAGS=-DF DOMAIN=staging.seirdy.one USER=deploy@seirdy.one OUTPUT_DIR=public_staging deploy-html
.PHONY: lint-and-deploy-staging
lint-and-deploy-staging:
@$(MAKE) HUGO_FLAGS='' DOMAIN=staging.seirdy.one USER=deploy@seirdy.one OUTPUT_DIR=public_staging .prepare-deploy
@$(MAKE) HUGO_FLAGS='' DOMAIN=staging.seirdy.one USER=deploy@seirdy.one OUTPUT_DIR=public_staging compress lint-local
@$(MAKE) HUGO_FLAGS='' DOMAIN=staging.seirdy.one USER=deploy@seirdy.one OUTPUT_DIR=public_staging deploy-html
@$(MAKE) HUGO_FLAGS='-DF' DOMAIN=staging.seirdy.one USER=deploy@seirdy.one OUTPUT_DIR=public_staging .prepare-deploy
@$(MAKE) HUGO_FLAGS='-DF' DOMAIN=staging.seirdy.one USER=deploy@seirdy.one OUTPUT_DIR=public_staging compress lint-local
@$(MAKE) HUGO_FLAGS='-DF' DOMAIN=staging.seirdy.one USER=deploy@seirdy.one OUTPUT_DIR=public_staging deploy-html
.PHONY: deploy-envs
deploy-envs:

View file

@ -6,7 +6,7 @@ Online Handle: Seirdy
I'm known as Rohan and as Seirdy. There are some differences between these personas, but the line between the two is blurry. It's fine to mix them up.
## Other versions of this website
## About this capsule
This page's canonical location is on seirdy.one:
@ -27,6 +27,9 @@ My Web and Gemini content may be slightly different: I often phrase things diffe
I have a Tor hidden Web service which mirrors this site's contents, except for the fact that it replaces some SVGs with PNGs.
=> http://wgq3bd2kqoybhstp77i3wrzbfnsyd27wt34psaja4grqiezqircorkyd.onion/
Featured in:
=> gemini://nightfall.city/writers-lane/ Writer's Lane, Nightfall City
## Location (Rohan, He/Him, meatspace)
Currently living at home in California, USA

View file

@ -144,8 +144,8 @@ I think that at least one entry in that list has some problematic messages, but
I've put together a periodically-updated [list of tracks](../music.txt) that I've rated 8/10 or higher in my mpd stickers database, auto-generated by some of my [mpd-scripts](https://git.sr.ht/~seirdy/mpd-scripts/tree/master/smart-playlists). I'm a fan of glitch, trailer music, and symphonic and power metal; I've also recently been getting into Japanese rock thanks to a few anime openings. Some of my favorite artists are The Glitch Mob, Pretty Lights, Beats Antique, Hammerfall, Badflower, Celldweller and Scandroid, Helloween, Two Steps from Hell, Nightwish, Mili, and MYTH & ROID.
Meta: other versions of this website
------------------------------------
Meta: other versions of this site
---------------------------------
This website's canonical location is on seirdy.one.

View file

@ -0,0 +1,185 @@
This began as a reply to another article by Lucas F. Costa; it lists practices to improve user-experience (UX) of command-line interfaces (CLIs). It comes from a good place, and has some good advice: I particularly like its advice on input-validation and understandable errors. Unfortunately, a number of its suggestions are problematic, particularly from an accessibility perspective.
=> https://lucasfcosta.com/2022/06/01/ux-patterns-cli-tools.html Lucas' article
Note: this article specifically concerns CLIs, not full-blown textual user interfaces (TUIs). It also focuses on utilities for UNIX-like shells; other command-line environments may have different conventions.
## Problematic patterns
The “Getting Started Experience” section of Lucas article has a GIF video of a CLI utility printing "--help" output, featuring a decorative border.
**Code snippet 1** (console): Lucas article leads with an example "--help" output thats surrounded by a decorative textual border. This is a transcription of the output, wrapped to a narrower width.
```
$ tool --help
╔ Getting started ════════════════════════════════════════╗
║ ║
║ To scaffold a new project, run: ║
║ ║
║ $ mytool init <directory> ║
║ ║
║ If you already have a project set up and would like to ║
║ add, remove, or update its structure, run: ║
║ ║
║ $ mytool manage ║
║ ║
╚═════════════════════════════════════════════════════════╝
Usage: tool <command> [options]
Commands:
tool init [directory] creates a new project
tool manage allows you to manage an existing project
Options:
--help Show help [boolean]
--version Show version number [boolean]
```
1. Borders in TUIs should always be drawn with characters specifically intended for textual interfaces (e.g., boxdraw characters). While I do think the GIF followed this advice, I think its worth explicitly saying it. Accessible terminal emulators can figure out what these mean and factor them into what they report through an accessibility API. But breaking these borders up with descriptive text makes detection of readable text error-prone.
2. Decorative content in CLI output should be limited, since the output of CLI utilities can be piped through other programs. At the very least, these tools should be able to detect whether their standard output is being re-directed or piped and sanitize output accordingly.
The “Colours, Emojis, and Layouting” (sic) section has similar issues:
1. Nearly all animated spinners are extremely problematic for screenreaders. A simple progress meter and/or numeric percentage combined with flags to enable/disable them is preferable.
2. Excessive animation and color can be harmful to users with attention and/or vestibular disorders, and some on the autism spectrum. Many tools offer a "--color[=WHEN]" flag where "WHEN" is "always", "never", or "auto". Expecting users to learn all the color configurations for all their tools is unrealistic; tools should respect the "NO_COLOR" environment variable.
=> https://no-color.org/ no-color.org
## Recommen­dations
This is a non-exhaustive list of simple, baseline recommendations for designing CLI utilities.
1. Send your tools output through a program like espeak-ng and listen to it. Can you make sense of the output?
2. How “unique” is your tools output? Output should look as similar to other common utilities as possible, to reduce the learning curve. Keep it boring.
3. Refer to the latest WCAG publication (currently WCAG 2.2) and take a look at the applicable criteria. Many have accompanying techniques for plain-text interfaces:
=> https://w3c.github.io/wcag/techniques/#text WCAG techniques page
Avoiding reliance on color and using whitespace and/or indentation for pseudo-headings are two sample recommendations from the WCAG.
4. Write man pages! Man pages have a standardized,[1] predictable, searchable format. Many screen-reader users actually have special scripts to make it easy to read man pages. A man page is also trivial to convert to HTML for people who prefer web-based documentation.[2] If your utility has a config file with special syntax or vocabulary, write a dedicated man page for it in section 5 and mention it in a “SEE ALSO” section.[3]
5. Try adding shell completions for your program, so users can tab-complete options. This is particularly helpful in shells like Zsh that support help-text in tab completions, especially when combined with plugins like fzf-tab that enable fuzzy-searching help-text (see "code snippet 2")
=> https://github.com/Aloxaf/fzf-tab fzf-tab on GitHub
6. Related to no. 5: use a well-understood format for "-h" and "--help" output. This makes auto-generating shell completions much easier. Alternatively, delegate the generation of both to a library that follows this advice.
7. Follow convention: use POSIX-like options. Consider supplementing them with GNU-style long options if your tool has a significant number of them.[4]
8. Either delegate output wrapping to the terminal, or detect the number of columns and format output to fit. Prefer the former when given a choice, especially when the output is not a TTY.
9. Make sure your web-based documentation and forge frontends are accessible, or are mirrored somewhere with good accessibility. I love what the Gitea folks are doing, but sadly their web frontend has a number of critical issues.[5] For now, if your forge has accessibility issues, mirroring to GitHub and/or Sourcehut seems like a good option.
10. Avoid breaking changes to you programs CLI. Remember that its argument parsing is an API, unless documentation explicitly states otherwise.[6] Semantic versioning is your friend.
11. Be predictable. Users expect "git log" to print a commit log. Users do not expect "git log" to make network connections, write something to their filesystem, etc. Try to only perform the minimum functionality suggested by the command. Naturally, this disqualifies opt-out telemetry.
Code snippet 2 (console): This is what tab-completion for MOAC looks like with fzf-tab.
```
$ moac -
> -p
9/11 (0)
-P -- power available to the computer (W)
> -p -- password to analyze
-s -- password entropy
-h -- display this help message
-r -- interactively enter a password in the terminal; overrides -p
-T -- temperature of the system (K)
-m -- mass at attacker's disposal (kg)
-q -- account for quantum computers using Grover's algorithm
```
=> https://sr.ht/~seirdy/moac MOAC
### More opinionated considerations
These considerations are far more subjective, debatable, and deserving of skepticism than the previous recommendations. Theres a reason I call this section “considerations”, not “recommendations”. Exceptions abound; Im not here to think on your behalf.
1. Remember that users arent always at their best when they read "--help" output; they could be trying to solve a frustrating problem, feeling a great deal of anxiety. Keep the output clean, predictable, boring, and *fast.* A 2-second delay and spinning fans will probably be extremely unpleasant for already-stressed users, especially if they need to use it often.[7]
2. Include example usage in your man pages and accompanying documentation. Consider submitting the example usage to the tldr-pages project if your tool gets popular:
=> https://tldr.sh/ tldr-pages
3. Include an extended list of example command invocations and expected output. Make that document double as a test suite. My "moac" and "moac-pwgen" testdata scripts are good examples. This can serve as a check for API stability, and even as a source of documentation.
=> https://git.sr.ht/~seirdy/moac/tree/master/item/cmd/moac/testdata/scripts moac testdata
=> https://git.sr.ht/~seirdy/moac/tree/master/item/cmd/moac-pwgen/testdata/scripts moac-pwgen testdata
4. Make your man pages as similar to other man pages on the target OS as possible. Many programs parse man pages, and expect them to follow a predictable structure. Try testing your man pages in multiple programs, just as people test Web pages in multiple browser engines. w3mman (included in w3m) is a good example to make sure auto-hyperlinking works. Pandoc is another tool worth trying.
=> https://manpages.debian.org/unstable/w3m/w3mman.1.en.html w3mman man page
=> https://pandoc.org/ Pandoc
5. Conform to tools that share a similar niche. If youre using Rust to make a fast alternative to popular coreutils: model its behavior, help-text, and man pages after ripgrep and fd. If youre making a linter for Go: copy "go vet".
6. If you want to keep your tool simple, make the output readable to both humans and machines; it should work well when streamed to another programs standard input and when parsed by a person. This is especially useful when people redirect output streams to log files.
7. Consider splitting related functionality between many executables (the UNIX way) and/or sub-commands (like Git). I split MOACs functionality across both moac and moac-pwgen, and gave moac three subcommands. The “Consistent commands trees” section of Lucas article has good advice.
8. Dont conflate CLIs and TUIs. A CLI should be non-interactive; a TUI should be interactive. Exceptions exist for really simple interfaces (e.g. Magic-Wormhole and others like it) that accept user input; however, as the interface grows more complex, consider splitting the program into two sibling programs, one of which can have a “pure” non-interactive CLI.
9. Go above and beyond by writing separate integrations for environments like Emacspeak.[8]
=> http://emacspeak.sourceforge.net/ Emacspeak homepage
## Name conflicts
This section might be the most important part of this post. If a CLI executable has a binary name conflict, packagers may have to re-name it. Otherwise, users will have to juggle $PATH overrides.[9]
Before publishing your software, test for binary name conflicts. Many package managers have built-in functionality to search for package files. I recommend doing so with large repositories to test for conflicts.
**Code snippet 3** (console): On Fedora and derivatives, use DNF to query package contents. You can also check cht.sh for other common commands.
```
$ dnf provides /usr/bin/p
Last metadata expiration check: 0:48:19 ago [...]
perl-App-p-0.0400-19.fc36.noarch : Steroids for your perl one-liners
Repo : fedora
Matched from:
Filename : /usr/bin/p
$ curl https://cht.sh/fly
# fly
# Command-line tool for concourse-ci.
# More information: <https://concourse-ci.org/fly.html>.
[...]
```
Thanks to Emily for reminding me of this on Fedi.
## References and further reading
1. Harini Sampath, Alice Merrick, and Andrew Macvean. 2021. Accessibility of Command Line Interfaces. In CHI Conference on Human Factors in Computing Systems (CHI 21), May 813, 2021, Yokohama, Japan. ACM, New York, NY, USA 10 Pages. <https://doi.org/10.1145/3411764.3445544>
=> https://dl.acm.org/doi/fullHtml/10.1145/3411764.3445544 Accessibility of Command Line Interfaces
2. Techniques for WCAG 2.2. Alastair Campbell, Michael Cooper, Andrew Kirkpatrick. W3C. 2022-05-30.
=> https://www.w3.org/WAI/WCAG22/Techniques/#text Techniques for WCAG 2.2
3. Command Line Interface Guidelines. Aanand Prasad, Ben Firshman, Carl Tashian, Eva Parish. Commit 89d755c, 2022-04-19.
=> https://clig.dev/ Command Line Interface Guidelines
## Footnotes
1. Well, theyre *somewhat* standardized compared to plain stdout.
2. My other article on accessible textual websites is probably relevant when it comes to Web-based documentation:
=> gemini://seirdy.one/posts/2020/11/23/website-best-practices/ Best practices for inclusive textual websites
3. For more on man page sections, see the "man" man page.
4. I need to take my own advice for programs like MOAC. Ugh.
5. See this Fediverse thread about forge accessibility:
=> https://mastodon.technology/@codeberg/108403449317373462
6. For a good example, see Gits distinction between regular output and porcelain-friendly output. The instability of the former and stability of the latter are explicitly documented in the Git man pages and in the official Git book.
7. The slow responses to basic flags like "--help" is one of many reasons I dislike Java command-line utilities (signal-cli, Nu HTML Checker). I believe Im not alone when I say this.
8. I used to not-very-seriously claim that Neovim, my preferred $EDITOR, is better than Emacs. Then I tried Emacspeak. I still make the same claim, but more softly and with an exception for Emacspeak.
9. A notable exception is executables that are supposed to conflict with others. Distributions like Fedora, Debian, and derivatives have an “alternatives” system to manage these overrides using symlinks. Examples include toolchains (`cc` and `ld` could point to their GCC or Clang implementations) and mail transfer agents (`sendmail` and `mta` have been re-implemented many times over).

View file

@ -0,0 +1,192 @@
---
title: "Best practices for inclusive CLIs"
description: "A response to some problematic CLI UX advice, with alternative recommendations for designing more accessible CLI utilities."
date: 2022-06-10T19:24:54-07:00
replyURI: "https://lucasfcosta.com/2022/06/01/ux-patterns-cli-tools.html"
replyTitle: "UX patterns for CLI tools"
replyType: "BlogPosting"
replyAuthor: "Lucas F. Costa"
replyAuthorURI: "https://lucasfcosta.com/"
evergreen: true
tags:
- accessibility
outputs:
- html
---
This began as a reply to another article by Lucas F. Costa; it lists practices to improve user-experience (<abbr title="User Experience">UX</abbr>) of command-line interfaces (<abbr title="Command-Line Interface">CLIs</abbr>). It comes from a good place, and has some good advice: I particularly like its advice on input-validation and understandable errors. Unfortunately, a number of its suggestions are problematic, particularly from an accessibility perspective.
<p role="doc-tip">Note: this article specifically concerns CLIs, not full-blown textual user interfaces (<abbr title="Textual User Interfaces">TUIs</abbr>). It also focuses on utilities for UNIX-like shells; other command-line environments may have different conventions.</p>
Problematic patterns
--------------------
The "Getting Started Experience" section of Lucas' article has a GIF video of a CLI utility printing `--help` output, featuring a decorative border.
{{<codefigure samp="true">}} {{< codecaption lang="console" >}} Lucas' article leads with an example `--help` output that's surrounded by a decorative textual border. This is a transcription of the output, wrapped to a narrower width. {{< /codecaption >}}
```figure {samp=true}
$ tool --help
╔ Getting started ════════════════════════════════════════╗
║ ║
║ To scaffold a new project, run: ║
║ ║
║ $ mytool init <directory>
║ ║
║ If you already have a project set up and would like to ║
║ add, remove, or update its structure, run: ║
║ ║
║ $ mytool manage ║
║ ║
╚═════════════════════════════════════════════════════════╝
Usage: tool <command> [options]
Commands:
tool init [directory] creates a new project
tool manage allows you to manage an existing project
Options:
--help Show help [boolean]
--version Show version number [boolean]
```
{{</codefigure>}}
1. Borders in TUIs should always be drawn with characters specifically intended for textual interfaces (e.g., boxdraw characters). While I do think the GIF followed this advice, I think it's worth explicitly saying it. Accessible terminal emulators can figure out what these mean and factor them into what they report through an accessibility API. But breaking these borders up with descriptive text makes detection of readable text error-prone.
2. Decorative content in CLI output should be limited, since the output of CLI utilities can be piped through other programs. At the very least, these tools should be able to detect whether their standard output is being re-directed or piped and sanitize output accordingly.
The "Colours, Emojis, and Layouting" (sic) section has similar issues:
1. Nearly all animated spinners are extremely problematic for screenreaders. A simple progress meter and/or numeric percentage combined with flags to enable/disable them is preferable.
2. Excessive animation and color can be harmful to users with attention and/or vestibular disorders, and some on the autism spectrum. Many tools offer a `--color[=WHEN]` flag where `WHEN` is `always`, `never`, or `auto`. Expecting users to learn all the color configurations for all their tools is unrealistic; tools should [respect the `NO_COLOR` environment variable.](https://no-color.org/)
Recommen&shy;dations {#recommendations}
--------------------
This is a non-exhaustive list of simple, baseline recommendations for designing CLI utilities.
1. Send your tool's output through a program like `espeak-ng` and listen to it. Can you make sense of the output?
2. How "unique" is your tool's output? Output should look as similar to other common utilities as possible, to reduce the learning curve. Keep it boring.
3. Refer to the latest <abbr title="Web Content Accessibility Guidelines">WCAG</abbr> publication (currently WCAG 2.2) and take a look at the applicable criteria. Many have [accompanying techniques for plain-text interfaces.](https://w3c.github.io/wcag/techniques/#text). Avoiding reliance on color and using whitespace and/or indentation for pseudo-headings are two sample recommendations from the WCAG.
4. Write man pages! Man pages have a standardized,[^1] predictable, searchable format. Many screen-reader users actually have special scripts to make it easy to read man pages. A man page is also trivial to convert to HTML for people who prefer web-based documentation.[^2] If your utility has a config file with special syntax or vocabulary, write a dedicated man page for it in section 5 and mention it in a "SEE ALSO" section.[^3]
5. Try adding shell completions for your program, so users can tab-complete options. This is particularly helpful in shells like Zsh that support help-text in tab completions, especially when combined with plugins like [fzf-tab](https://github.com/Aloxaf/fzf-tab) that enable fuzzy-searching help-text (see [code snippet 2](#code-2)).
6. Related to no. 5: use a well-understood format for `-h` and `--help` output. This makes auto-generating shell completions much easier. Alternatively, delegate the generation of both to a library that follows this advice.
7. Follow convention: use POSIX-like options. Consider supplementing them with GNU-style long options if your tool has a significant number of them.[^4]
8. Either delegate output wrapping to the terminal, or detect the number of columns and format output to fit. Prefer the former when given a choice, especially when the output is not a TTY.
9. Make sure your web-based documentation and forge frontends are accessible, or are mirrored somewhere with good accessibility. I love what the Gitea folks are doing, but sadly their web frontend has a number of critical issues.[^5] For now, if your forge has accessibility issues, mirroring to GitHub and/or Sourcehut seems like a good option.
10. Avoid breaking changes to you program's CLI. Remember that its argument parsing is an API, unless documentation explicitly states otherwise.[^6] Semantic versioning is your friend.
11. Be predictable. Users expect `git log` to print a commit log. Users do not expect `git log` to make network connections, write something to their filesystem, etc. Try to only perform the minimum functionality suggested by the command. Naturally, this disqualifies opt-out telemetry.
{{<codefigure samp="true">}} {{< codecaption lang="console" >}} This is what tab-completion for [MOAC](https://sr.ht/~seirdy/moac) looks like with fzf-tab. {{< /codecaption >}}
```figure {samp=true}
$ moac -
> -p
9/11 (0)
-P -- power available to the computer (W)
> -p -- password to analyze
-s -- password entropy
-h -- display this help message
-r -- interactively enter a password in the terminal; overrides -p
-T -- temperature of the system (K)
-m -- mass at attacker's disposal (kg)
-q -- account for quantum computers using Grover's algorithm
```
{{</codefigure>}}
### More opinionated considerations
These considerations are far more subjective, debatable, and deserving of skepticism than the previous recommendations. There's a reason I call this section "considerations", not "recommendations". Exceptions abound; I'm not here to think on your behalf.
1. Remember that users aren't always at their best when they read `--help` output; they could be trying to solve a frustrating problem, feeling a great deal of anxiety. Keep the output clean, predictable, boring, and _fast._ A 2-second delay and spinning fans will probably be extremely unpleasant for already-stressed users, especially if they need to use it often.[^7]
2. Include example usage in your man pages and accompanying documentation. Consider submitting the example usage to the [tldr pages](https://tldr.sh/) project if your tool gets popular.
3. Include an extended list of example command invocations and expected output. Make that document double as a test suite. My [`moac` testdata](https://git.sr.ht/~seirdy/moac/tree/master/item/cmd/moac/testdata/scripts) and [`moac-pwgen` testdata](https://git.sr.ht/~seirdy/moac/tree/master/item/cmd/moac-pwgen/testdata/scripts) scripts are good examples. This can serve as a check for API stability, and even as a source of documentation.
4. Make your man pages as similar to other man pages on the target OS as possible. Many programs parse man pages, and expect them to follow a predictable structure. Try testing your man pages in multiple programs, just as people test Web pages in multiple browser engines. [`w3mman`](https://manpages.debian.org/unstable/w3m/w3mman.1.en.html) (included in [w3m](https://github.com/tats/w3m)) is a good example to make sure auto-hyperlinking works. [Pandoc](https://pandoc.org/) is another tool worth trying.
5. Conform to tools that share a similar niche. If you're using Rust to make a fast alternative to popular coreutils: model its behavior, help-text, and man pages after `ripgrep` and `fd`. If you're making a linter for Go: copy `go vet`.
6. If you want to keep your tool simple, make the output readable to both humans and machines; it should work well when streamed to another program's standard input and when parsed by a person. This is especially useful when people redirect output streams to log files.
7. Consider splitting related functionality between many executables (the UNIX way) and/or sub-commands (like Git). I split [MOAC's](https://sr.ht/~seirdy/moac) functionality across both `moac` and `moac-pwgen`, and gave `moac` three subcommands. The ["Consistent commands trees"](https://lucasfcosta.com/2022/06/01/ux-patterns-cli-tools.html#consistent-commands-trees) section of Lucas' article has good advice.
8. Don't conflate CLIs and TUIs. A CLI should be non-interactive; a TUI should be interactive. Exceptions exist for really simple interfaces (e.g. Magic-Wormhole and others like it) that accept user input; however, as the interface grows more complex, consider splitting the program into two sibling programs, one of which can have a "pure" non-interactive CLI.
9. Go above and beyond by writing separate integrations for environments like [Emacspeak](http://emacspeak.sourceforge.net/).[^8]
Name conflicts
--------------
This section might be the most important part of this post. If a CLI executable has a binary name conflict, packagers may have to re-name it. Otherwise, users will have to juggle `$PATH` overrides.[^9]
Before publishing your software, test for binary name conflicts. Many package managers have built-in functionality to search for package files. I recommend doing so with large repositories to test for conflicts.
{{<codefigure samp="true">}} {{< codecaption lang="console" >}} On Fedora and derivatives, use DNF to query package contents. You can also check `cht.sh` for other common commands. {{< /codecaption >}}
```figure {samp=true}
$ dnf provides /usr/bin/p
Last metadata expiration check: 0:48:19 ago [...]
perl-App-p-0.0400-19.fc36.noarch : Steroids for your perl one-liners
Repo : fedora
Matched from:
Filename : /usr/bin/p
$ curl https://cht.sh/fly
# fly
# Command-line tool for concourse-ci.
# More information: <https://concourse-ci.org/fly.html>.
[...]
```
{{</codefigure>}}
Thanks to Emily for <a href="https://sparkly.uni.horse/@emily/108451871152495325">reminding me of name conflicts.</a>
<section role="doc-bibliography">
References and further reading
------------------------------
<ol>
<li><p>{{<mention-work itemprop="citation" role="doc-credit" itemtype="ScholarlyArticle">}}Harini Sampath, Alice Merrick, and Andrew Macvean. 2021. _{{<cited-work url="https://dl.acm.org/doi/fullHtml/10.1145/3411764.3445544" name="Accessibility of Command Line Interfaces" extraName="headline">}}. In CHI Conference on Human Factors in Computing Systems (CHI '21), May 813, 2021, Yokohama, Japan._ ACM, New York, NY, USA 10 Pages. <https://doi.org/10.1145/3411764.3445544>{{</mention-work>}}</p></li>
<li><p>{{<mention-work itemprop="citation" role="doc-credit" itemtype="TechArticle">}}{{<cited-work url="https://www.w3.org/WAI/WCAG22/Techniques/#text" name="Techniques for WCAG 2.2" extraName="headline">}}. Alastair Campbell, Michael Cooper, Andrew Kirkpatrick. W3C. <time datetime="2022-05-30">2022-05-30</time>.{{</mention-work>}}</p></li>
<li><p>{{<mention-work itemprop="citation" role="doc-credit" itemtype="Book">}}{{<cited-work url="https://clig.dev/" name="Command Line Interface Guidelines">}}. Aanand Prasad, Ben Firshman, Carl Tashian, Eva Parish. Commit `89d755c`, <time datetime="2022-04-19">2022-04-19</time>.{{</mention-work>}}</p></li>
</ol>
</section>
[^1]: Well, they're _somewhat_ standardized compared to plain stdout.
[^2]: [My other article on accessible textual websites](https://seirdy.one/posts/2020/11/23/website-best-practices/) is probably relevant when it comes to Web-based documentation
[^3]: For more on man page sections, see the [`man(1)`](https://man.openbsd.org/man) man page.
[^4]: I need to take my own advice for programs like [moac](https://sr.ht/~seirdy/moac). Ugh.
[^5]: See [this Fediverse thread](https://mastodon.technology/@codeberg/108403449317373462) about forge accessibility.
[^6]: For a good example, see Git's distinction between regular output and porcelain-friendly output. The instability of the former and stability of the latter are explicitly documented in the Git man pages and in the official Git book.
[^7]: The slow responses to basic flags like `--help` is one of many reasons I dislike Java command-line utilities (signal-cli, Nu HTML Checker). I believe I'm not alone when I say this.
[^8]: I used to not-very-seriously claim that Neovim, my preferred `$EDITOR`, is better than Emacs. Then I tried Emacspeak. I still make the same claim, but more softly and with an exception for Emacspeak.
[^9]: A notable exception is executables that are supposed to conflict with others. Distributions like Fedora, Debian, and derivatives have an "alternatives" system to manage these overrides using symlinks. Examples include toolchains (`cc` and `ld` could point to their GCC or Clang implementations) and mail transfer agents (`sendmail` and `mta` have been re-implemented many times over).

View file

@ -1127,10 +1127,11 @@ The WAI's Cognitive and Learning Disabilities Accessibility Task Force recommend
Fully standards-compliant browsers aren't the only programs people use. They also use "reading mode" tools and services.
Reading modes leverage article extractors such as Readability.js (integrated into Firefox, Epiphany, Brave, Vivaldi, and others), DOM Distiller (integrated into Chromium), and Trafilatura (powers a variety of tools and services). A host of other proprietary options exist: Diffbot powers services like Instapaper, Mozilla's Pocket has its own secret parsers, and countless "send to e-reader" services have amassed loyal users.
Reading modes leverage article extractors such as Readability.js (integrated into Firefox, Epiphany, Brave, Vivaldi, and others), DOM Distiller (integrated into Chromium), Brave SpeedReader, and Trafilatura (powers a variety of tools and services). A host of other proprietary options exist: Diffbot powers services like Instapaper, Mozilla's Pocket has its own secret parsers, and countless "send to e-reader" services have amassed loyal users.
=> https://github.com/mozilla/readability Readability.js
=> https://chromium.googlesource.com/chromium/dom-distiller/ DOM Distiller
=> https://github.com/brave/brave-core/tree/master/components/speedreader/rust/lib Brave SpeedReader
=> https://trafilatura.readthedocs.io/en/latest/ Trafilatura
Safari's proprietary fork of Readability has grown quite complex compared to upstream; Edge's Immersive Reader is a mystery to me, with a problematic stylesheet:

View file

@ -1156,7 +1156,7 @@ Non-<wbr />brow&shy;sers: reading mode {#non-browsers-reading-mode}
Fully standards-compliant browsers aren't the only programs people use. They also use "reading mode" tools and services.
Reading modes leverage article extractors such as <span translate="no">[Readability](https://github.com/mozilla/readability)</span> (integrated into Firefox, Epiphany, Brave, Vivaldi, and others), [DOM Distiller](https://chromium.googlesource.com/chromium/dom-distiller/) (integrated into Chromium), and [Trafilatura](https://trafilatura.readthedocs.io/en/latest/) (powers a variety of tools and services). A host of other proprietary options exist: Diffbot powers services like Instapaper, Mozilla's Pocket has its own secret parsers, and countless "send to e-reader" services have amassed loyal users. Safari's proprietary fork of <span translate="no">Readability</span> has grown quite complex compared to upstream; Edge's Immersive Reader is [a mystery to me](https://techcommunity.microsoft.com/t5/discussions/documentation-on-huerestics-used-during-article-distillation-in/m-p/3266436), with [a problematic stylesheet](https://feedbackportal.microsoft.com/feedback/idea/e0d9b299-e3b6-ec11-a81c-000d3a7ce453).
Reading modes leverage article extractors such as <span translate="no">[Readability](https://github.com/mozilla/readability)</span> (integrated into Firefox, Epiphany, Brave, Vivaldi, and others), [DOM Distiller](https://chromium.googlesource.com/chromium/dom-distiller/) (integrated into Chromium), [Brave SpeedReader](https://github.com/brave/brave-core/tree/master/components/speedreader/rust/lib), and [Trafilatura](https://trafilatura.readthedocs.io/en/latest/) (powers a variety of tools and services). A host of other proprietary options exist: Diffbot powers services like Instapaper, Mozilla's Pocket has its own secret parsers, and countless "send to e-reader" services have amassed loyal users. Safari's proprietary fork of <span translate="no">Readability</span> has grown quite complex compared to upstream; Edge's Immersive Reader is [a mystery to me](https://techcommunity.microsoft.com/t5/discussions/documentation-on-huerestics-used-during-article-distillation-in/m-p/3266436), with [a problematic stylesheet](https://feedbackportal.microsoft.com/feedback/idea/e0d9b299-e3b6-ec11-a81c-000d3a7ce453).
I don't recommend catering to each tool's non-standard quirks. Studying their design reveals that they observe open standards, to varying degrees. <span translate="no">Readability</span>, DOM Distiller, and Trafilatura understand plain-old, semantic HTML (<abbr title="Plain-Old, Semantic HTML">POSH</abbr>).

View file

@ -91,7 +91,7 @@ By default, web browsers may share pages a user visits with third parties by loa
By default, web browsers may share arbitrary information with a server through HTTP headers; these headers could include fingerprintable information unintentionally (client-hints, do-not-track) or intentionally (Chromium's upcoming advertising identifiers). I do not log any HTTP headers not explicitly mentioned in the "Web server logs" section, but I cannot prevent user agents from sending a header ahead of time.
By default, web browsers can share near-arbitrary identifying data with a server by executing near-arbitrary JavaScript, or store this information for future transmission. I have disabled this behavior with a "Content-Security-Policy" HTTP header that forbids script loading ("script-src: none"), script execution ("sandbox"), and making connections for any purpose other than downloading a page a user navigated to ("connect-src").
By default, web browsers can share near-arbitrary identifying data with a server by executing near-arbitrary JavaScript, or store this information for future transmission. I have disabled this behavior with a "Content-Security-Policy" HTTP header. It contains explicit and implicit directives that forbid script loading ("script-src: none"), script execution ("sandbox"), and making connections for any purpose other than downloading a page a user navigated to ("connect-src").
By default, user agents using HTTPS may contact a certificate authority to check the revocation status of an TLS certificate. I have disabled and replaced this behavior by including an "OCSP Must-Staple" directive in the TLS certificates used by my Web servers.

View file

@ -91,7 +91,7 @@ By default, web browsers may share pages a user visits with third parties by loa
By default, web browsers may share arbitrary information with a server through HTTP headers; these headers could include fingerprintable information unintentionally (client-hints, do-not-track) or intentionally (Chromium's upcoming advertising identifiers). I do not log any HTTP headers not explicitly mentioned in the "Web server logs" section, but I cannot prevent user agents from sending a header ahead of time.
By default, web browsers can share near-arbitrary identifying data with a server by executing near-arbitrary JavaScript, or store this information for future transmission. I have disabled this behavior with a `Content-Security-Policy` HTTP header that forbids script loading (`script-src: none`), script execution (`sandbox`), and making connections for any purpose other than downloading a page a user navigated to (`connect-src`).
By default, web browsers can share near-arbitrary identifying data with a server by executing near-arbitrary JavaScript, or store this information for future transmission. I have disabled this behavior with a `Content-Security-Policy` HTTP header. It contains explicit and implicit directives that forbid script loading (`script-src: none`), script execution (`sandbox`), and making connections for any purpose other than downloading a page a user navigated to (`connect-src`).
By default, user agents using HTTPS may contact a certificate authority to check the revocation status of an TLS certificate. I have disabled and replaced this behavior by including an "OCSP Must-Staple" directive in the TLS certificates used by my Web servers.

101
content/site-design.md Normal file
View file

@ -0,0 +1,101 @@
---
outputs:
- html
title: Site design standards
description: "The accessibility statement and design standards I hold myself to when creating seirdy.one"
date: "2022-06-10T00:00:00+00:00"
---
This site may look simple on the surface, but I put a _lot_ of thought into it. I hold myself to a long list of requirements concerning accessibility, compatibility, privacy, security, and machine-friendliness.
<p role="doc-tip">Note: all references to "pixels" (px) in this section refer to CSS pixels.</p>
Accessibility statement
-----------------------
I've made every effort to make seirdy.one as accessible as possible.
### Conformance status
The [Web Content Accessibility Guidelines (WCAG)](https://www.w3.org/WAI/standards-guidelines/wcag/) defines requirements for designers and developers to improve accessibility for people with disabilities. It defines three levels of conformance: Level A, Level AA, and Level AAA. I've made sure seirdy.one is fully conformant with WCAG 2.2 level AA.
<dfn>Fully conformant</dfn> means that the content fully conforms to the accessibility standard without any exceptions.
### Additional accessibility considerations
Additionally, I strive to conform to WCAG 2.2 level AAA wherever applicable. There are some AAA criteria that I do not currently meet:
SC 1.4.8 Visual Presentation
: I am in partial compliance with this criterion. Long article body text for articles should conform; with default browser fonts, they have an average character count per line below 80 characters. However, some lines may occasionally exceed this limit. Text outside of long article bodies has a longer line width, though.
SC 2.4.9 Link Purpose (Link Only)
: I'm actually trying to follow this criterion, but it's a work in progress. Let me know if any link names can be improved! Link purpose _in context_ always makes sense.
SC 3.1.5 Reading Level
: The required reading ability often exceeds the lower secondary education level, especially on more technical articles.
SC 3.1.6 Pronunciation
: I do not yet provide any pronunciation information.
I have only tested WCAG compliance in mainstream browser engines (Blink, Gecko, WebKit).
I also go further than WCAG in many aspects:
- Rather than follow SC 2.5.5's requirement to achieve a minimum tap target size of 44 by 44 pixels, I follow Google's more strict guidelines. These guidelines mandate that targets are at least 48-by-48 pixels, with no overlap against any other targets in a 56-by-56 pixel range. I try to follow this guideline for any interactive element that isn't a hyperlink surrounded by body text.
- I ensure at least one such 56-by-56&nbsp;px non-interactive region exists on the page, for users with hand tremors or or anyone who wants to tap the screen without clicking something.
- I only set custom colors in response to the `prefers-color-scheme: dark` media query. These custom colors pass APCA contrast ratios, all being close to the ideal lightness contrast of 90. They are also autism- and overstimulation-friendly colors: yellow links are significantly de-saturated to reduce harshness.
- I ensure that the page works on extremely narrow viewports without triggering two-dimensional scaling. It should work at widths well below 200 CSS pixels.
### Assessment and evaluation
I test each WCAG success criterion myself using the mainstream browser engines (Blink, Gecko, WebKit). I test using multiple screen readers: Orca (primary, with Firefox and Epiphany), NVDA (with Firefox and Chromium), Windows Narrator (with Microsoft Edge), Apple VoiceOver (with desktop and mobile Safari), and Android TalkBack (with Chromium).
I also accept user feedback. Users are free to contact me through any means linked on my [About page](../about/).
Finally, I supplement manual testing with automated tools. I run [axe-core](https://github.com/dequelabs/axe-core), the [IBM Equal Access Accessibility Checker](https://www.ibm.com/able/toolkit/verify/automated), [AInspector](https://github.com/ainspector/ainspector-for-firefox), the [WAVE Web Accessibility Evaluation Tool](https://wave.webaim.org/), and [ARC Toolkit](https://www.tpgi.com/arc-platform/arc-toolkit/). WAVE reports no errors; AXE is unable to determine certain contrast errors, but it otherwise reports no errors; IBM Equal Access reports no errors but some items that need review.
Browser engine compatibility
----------------------------
This site sticks to Web standards: I regularly run [the Nu HTML Checker](https://github.com/validator/validator) and `xmllint` on every page and see no errors (I do [filter out false Nu positives](https://git.sr.ht/~seirdy/seirdy.one/tree/master/item/linter-configs/vnu_filter.jq) and report them upstream when I can).
I also do cross-browser testing for both HTML and XHTML versions of my pages:
- I maintain excellent compatibility with **mainstream engines:** Blink (Chromium and Edge), WebKit (Safari, Epiphany), and Gecko (Firefox). The hidden service also works well with the Tor Browser.
- The site works well with **textual browsers.** Lynx and Links2 are first-class citizens for which all features work as intended. [w3m doesn't support soft hyphens](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=830173), but the site is still otherwise usable in it. I maintain compatibility with these engines by making CSS a strictly-optional progressive enhancement and using semantic markup.
- I also regularly test compatibility with **current alternative engines:** the SerenityOS browser, Servo, NetSurf, Dillo, and Goanna (Pale Moon's Gecko fork). I have excellent compatibility with Goanna and Servo. The site is usable in NetSurf, Dillo, and the SerenityOS browser; the always-expanded `<details>` elements might look odd. [The SerenityOS browser doesn't support ECDSA certificates](https://github.com/SerenityOS/serenity/issues/14160), but the Tildeverse mirror works fine. It also has some issues displaying my SVG avatar; it does not attempt to use the PNG fallback.
- I occasionally test **abandoned engines,** sometimes with a TLS-terminating proxy if necessary. These engines include Tkhtml, KHTML, Internet Explorer (with and without compatibility mode), Netscape Navigator, and outdated versions of current browsers. The aforementioned issue with `<details>` applies to all of these choices. I use Linux, but testing in browsers like Internet Explorer depends on my access to a Windows machine.
Machine-friendliness
--------------------
I think making a site machine-friendly is a great alternative perspective to traditional SEO, the latter of which I think tends to incentivise low-quality content and makes searching difficult.
This site is **parser-friendly.** It uses polygot (X)HTML5 markup containing schema.org microdata, microformats2, and legacy microformats. Microformats are useful for IndieWeb compatibility; schema.org microdata is useful for various forms of content-extraction (such as "reading mode" implementations). I've also sprinkled in some Creative Commons vocabulary using RDFa syntax.
I make Atom feeds available for articles and notes, and have a combined Atom feed for both. These feeds are enhanced with Ostatus and ActivityStreams XML namespaces.
All HTML pages have an XHTML5 counterpart, which is currently the same except for the presence of an XML declaration. To see this counterpart, add "index.xhtml" to the end of a URL or request a page with an `Accept` header containing `application/xhtml+xml` but not `text/html`. All pages parse correctly using all the XHTML browser parsers I could try.
### Reading mode compatibility
The aforementioned metadata (microdata, microformats) has improved reading-mode compatibility.
This site should fully support the Readability algorithm. The Readability algorithm is used by Firefox and Vivaldi. It's the basis of one of multiple distillers used by Brave; Brave typically uses its Readability-based logic on seirdy.one. Readability is the only article distillation algorithm I try to actively support.
This site happens to fully supports Apple's Reader Mode and Azure Immersive Reader (AIR), the latter of which powers Microsoft Edge's reading mode. Unfortunately, AIR applies a stylesheet atop the extracted article that makes figures difficult to read: it centers text in figures, included pre-formatted blocks. I filed an issue on AIR's feedback forum, but that forum was subsequently deleted.
This site works well in the Diffbot article extractor. Diffbot powers a variety of services, including Instapaper.
This site does not work well in Chromium's DOM Distiller. DOM Distiller removes all level-2 headings in article bodies. This is likely because they appear alongside section permalinks, which combines poorly with a DOM-Distiller heuristic that strips out sections with a high link-density. DOM Distiller also does not show footnotes, and sometimes cuts off final sections (acknowledgements, conclusions).
Privacy
-------
This site is **privacy-respecting.** Its CSP blocks all scripts, third-party content, and other problematic features. I describe how I go out of my way to reduce the information you can transmit on this site in [my privacy policy](../privacy/).

View file

@ -20,6 +20,9 @@
<li>
<a href="{{ site.BaseURL }}privacy/">Privacy</a>
</li>
<li>
<a href="{{ site.BaseURL }}site-design/">Site design standards</a>
</li>
<li>
<a href="{{ site.BaseURL }}about/#location-seirdy-online">Contact</a>
</li>

View file

@ -2,6 +2,7 @@
{{- with .Get "itemprop" -}}
{{ $itemprop = . }}
{{- end -}}
<span class="h-cite{{ with .Get "reply" }} in-reply-to{{ end }}" itemprop="{{ $itemprop }}"{{ with .Get "role" }} role="{{ . }}"{{ end }} itemscope="" itemtype="https://schema.org/{{ .Get "itemtype" }}">
<span
class="h-cite{{ with .Get "reply" }} in-reply-to{{ end }}" itemprop="{{ $itemprop }}"{{ with .Get "role" }} role="{{ . }}"{{ end }} itemscope="" itemtype="https://schema.org/{{ .Get "itemtype" }}">
{{- .Inner | markdownify | safeHTML -}}
</span>
</span>