So I've dropped v1.1.0 on PyPI, which adds support for running up a simple just-good-enough Nex server (although, to be fair, Nex is so simple this is probably a fully capable one just by the very nature of how trivial the protocol is).
It's that time again. Time to add another small web protocol to Rogallo. This time it's one I stumbled across a few days ago: the Nex protocol. This one is very simple and straightforward and it seemed like a shame not to support it.
So, as I have with Gemini, Spartan, Gopher and Finger, I've added a dedicated library for dealing with the associated URI, and to provide a client for talking to the server.
While Rogallo is, of course, primarily aimed at loading and rendering Gemtext documents, I have written it so that it'll try and display anything whose content type matches text/*. In most cases this will result in something being shown as plain text and, as of v1.6.0, it will also attempt to add some syntax highlighting where appropriate. So, if you happened to come across a Markdown file in Geminispace, and the server told Rogallo that it was a Markdown file, it would look something like this:
Simply put: raw Markdown but syntax-highlighted.
The thing is, Rogallo contains everything needed to actually render the Markdown; it's carrying that code around due to it being built on top of the Textual framework, so it seemed a shame to not use it. So as of this version, if a Markdown file is encountered, by default it'll be shown as a full Markdown widget.
Having added the above, I got to thinking that it might be interesting to consider other text/* types that I could render in a more Rogallo-friendly way. The next that came to mind was text/html. While it's not going to be that common to encounter HTML on the end of a gemini:// connection, it's not impossible. Initially I did consider going via a route that had me turn the HTML into Markdown and then use the Markdown widget to show the result, but in the end I decided to turn it into Gemtext instead; in part because it's a fun challenge, and in part because it feels more in keeping with the Geminispace aesthetic1.
So, whereas before, if you landed on some HTML in Geminispace, you'd see this:
From now on you'll see something more like this:
This HTML to Gemtext support is still in its infancy so I imagine there's going to be a lot of fun corner cases that don't quite work out, but for me the utility makes it worth working on.
Until now the ToggleView command (bound to F4 by default) simply toggled Gemini-based Gemtext and Gopher maps between their rendered and raw views (acting as a sort of "view source" command). With the addition of richer rendering of Markdown and HTML it will also toggle those content types. The point here being, if you really need to look at the raw content of a Markdown or HTML document found in Geminispace, it's still there for you.
A key feature of Rogallo is the automatic handing off of URIs and MIME types that it can't directly handle. On occasion, though, I find myself wanting to do the same hand-off with a document I'm successfully viewing in Rogallo. This was easy enough to do with the CopyLocationToClipboard command (bound to Ctrl+Shift+c by default), pasting the URI into my normal web browser and going from there. But it felt like this should be a command in its own right.
So now there's HandOffToOperatingSystem (bound to Ctrl+Shift+o by default), which will ask your environment to open the current URI.
Yesterday, I saw a post on Station which was talking about the site logo. The main thrust of it being, while the logo is cool and all, it does use up a fair bit of vertical space that you have to get past to get to the content. I can see this being an a11y issue in some situations, if nothing else.
So I got to thinking: in the case of Station, the author of the site has been kind enough to give the pre-formatted text block some alt-text2, so that means it's possible to have a targeted filter for such well-designed sites. Given this, I've added a method of filtering out pre-formatted blocks, keyed on a URI and alt-text. So now, with the addition of this to my configuration:
I can get straight to the content when landing at the Station:
ℹ️ Note
I did hesitate before adding this. There's a part of me that was thinking "but the creator of the site has designed the site this way, does it make sense to override their choice?" -- but then I decided that, if Geminispace is about anything, it's about privacy, freedom and control over your experience of it. Moreover, using this is a choice on the client side, and like I say, it's in part an a11y feature.
More as an accident of how I was working on things than a conscious choice, the only protocols in Rogallo that also used the content cache were Gemini and Spartan. With this release of Rogallo I've extended it to Gopher responses too. I've made a point of not using the cache for any response that is going to be the result of a search, as that feels like something that's often going to have more dynamic content.
Talking of Gopher: there's also a small fix to Gopher responses in this release. When looking for responses that indicated an error from Gopher servers, Rogallo was a little too keen in how it worked, which could result in a plain text response, that just happened to have a 3 in the first column of any line, being seen as a Gopher map that indicated an error.
This is now fixed.
Which also has me wanting, longer-term, to do the same for Markdown. While using the Markdown widget is neat and all, I think it would be far more in keeping with the purpose of this project to turn Markdown into Gemtext. ↩
As I write more Gemtext myself, I'm going to do my very best to always do the same. ↩
However, earlier today, I ran into a page that was obviously supposed to be plain text, but was being displayed in part like a map. The problem was my attempt at detecting a reply from a Gopher server that looked like it might be an error. This very relaxed approach to "this is likely some Gopher stuff, let's accept it as such" meant that a text file that had a 3 anywhere in the first column was tripping off the "this is likely some Gopher stuff and it looks like there's an error in there" check. The result? Treated like a Gopher map, converted into Gemtext, and displayed in the wrong way.
With these in place, I can update Rogallo so that it's still pretty easy-going when it comes to showing Gopher maps, but isn't quite so laid-back when it comes to finding errors coming back from Gopher servers, and so incorrectly rendering the result.
Yesterday evening, while tinkering with Rogallo, I managed to nerd-snipe myself pretty well. I was playing around with the idea of better presentation of some forms of text/* content. While, of course, Rogallo handles text/gemtext just fine, there are lots of other MIME types that it will show too (pretty much all within text/*). Already, if it can work out an appropriate language, the viewer will do syntax highlighting, and this includes Markdown files. However, Rogallo has a full Markdown widget built right in so I was experimenting with using that as the way to show Markdown content.
Nothing that clever really, all pretty obvious.
But then I got to thinking... In OldNews I heavily rely on html-to-markdown. Given I have a Markdown viewer to hand, if the user ends up trying to look at some text/html, why not convert it over to Markdown and render it that way? That's... doable.
There are, however, some problems with this idea:
As useful as html-to-markdown has been for OldNews, I've found it quite unreliable at times, with the occasional breaking change. I don't mention this as a negative about the project, but I don't want another one of my projects sitting on top of a moving target like that.
Dragging in a reasonably large dependency for what's likely to be a niche requirement doesn't quite feel right.
Textual's Markdown viewer has, to this day, one massive design flaw: links can't be navigated with the keyboard1. I'm doing my absolute best to ensure that Rogallo is keyboard-first. Leaning on this widget for viewing Markdown is one thing, but leaning on the widget for other content types starts to erode that aim.
I did consider the idea of having this feature as an install option, so you'd be able to install rogallo and have it work as normal, or install rogallo[html] (or similar) and it would drag in the ability to render some HTML using this pipeline.
Then I realised: why target Markdown at all? I already have the code for rendering Gemtext, and that solves the keyboard navigation of links problem. How hard could it be to write something to convert HTML to Gemtext?
Turns out, at least for the requirements I have right now, not that hard!
html2gemtext is still in its infancy, but it's doing a passable job of turning most of the HTML I throw at it into reasonable Gemtext. I don't doubt for a moment that there are lots of pages out there that won't turn out right -- for varied values of right -- but so far the results are readable and navigable. The plan now is to keep improving as I run into new cases that could be handled better.
While I've not built this into Rogallo just yet, I think I will make use of it. I'm also giving serious thought to using it for my capsule. Over there I'm adding some posts from this blog and html2gemtext could form the basis of a tool to help automate some of that.
Right now I'm using a script I've written that wraps lowdown to do the Markdown to Gemtext conversion, but the result -- as good as it is -- isn't quite what I'd like. I'm thinking I could tailor the results exactly as I want if I go from this blog's HTML via html2gemtext.
Or, of course, given my blog is written in Markdown, I could next tackle my own just-how-I-need-it Markdown to Gemtext converter...
As for how this new library will go into Rogallo... Using it to render HTML that might be found kicking about in Geminispace or Gopherspace makes sense, I think. That should be enough. It's not like I really need to turn it into an http(s) browser too. Right? Right?!?
This mouse-only problem is a recurring theme in Textual. ↩
I've just made a small release of Rogallo, bumping the version to v1.7.0. Most of the changes in this version aren't very visible, but quite a few things have changed under the hood.
One change that might show up on occasion is the addition of an encoding fallback if you encounter an ISO-8859-1 file out in the wild (oh how that takes me back). Before, Rogallo would pop up an error and refuse to show the file; now it will show it just fine.
I've also made some improvements to how Rogallo navigates Gemtext files being browsed locally in the filesystem. Before now, when viewing local files, if a link was for another local file, it would show an external link icon rather than a Gemini link icon. This is now fixed. The other change is that, if you're browsing local files that have links to a directory rather than a file -- thereby implying that an index.gmi should be looked for -- Rogallo will take a peek at the directory, see if there is an index file available, and take this into account.
This should make it a smoother experience if you're using Rogallo to locally preview some Gemtext files before you upload them to a capsule.
The final noticeable change is the addition of a ViewChangeLog command (AKA !view_change_log in the internal command line). Bound to Ctrl+Shift+l by default, this navigates you to the Gemtext version of the Rogallo ChangeLog.
In addition to this, I've made a lot of changes to some of the internals. The class that handles the main screen of Rogallo was getting pretty large, with a lot of detail of how to handle different protocols sitting in the code. While not causing any runtime issues, it made the code increasingly bloated and untidy (and I really hate large Python files). So I've moved the handling of each of the protocols into their own files. This also has the benefit of making it a little easier and a little more maintainable if/when I add another protocol or two. It should also make the code more readable for anyone else looking over it.
As Rogallo got close to being "stable", I did a fair bit of work on its documentation. Something that I wanted to include in the site was a good collection of up-to-date screenshots. These are all created on the fly. To do this, of course, requires something that looks like a Gemini server.
Initially, this was simple: Rogallo only supported Gemini capsules, so I could illustrate most things just using Gemtext files in the local filesystem (with an admonition in the documentation to point out that Rogallo was for more than viewing local files). This, of course, wasn't going to scale when I added Finger support, and neither was it going to work well for Gopher support.
The solution seemed obvious: use a lightweight local server for these protocols. With this need in place SmolServe was born. As mentioned when I released Rogallo v1.5.0, this isn't a project to build a comprehensive smolweb server. The aim is to build myself a minimal just-good-enough server that helps me with local testing and documentation.
As it stands, SmolServe supports Gemini, Gopher, Finger and Spartan. Or, rather, it supports a just-enough-to-get-by version of each of those protocols. None are implemented in a way that would serve as a "production" server; they're implemented to allow me to generate screenshots for the Rogallo documentation, involving any of the supported protocols, without the need to rely on services I don't control and which aren't local.
The big benefit of SmolServe is the exec support. With this, you can run up the server and then have it run another command. Once that command finishes its work, SmolServe will close down too. This means that, when it comes to producing the Rogallo documentation, I can just have the server running when I need it. Pulling some snippets from the Rogallo Makefile:
The idea is that, when I build the documentation, I actually run smolserve, which in turn runs mkdocs, which then produces the documentation while the local server is available.
My aim now is that, if I add any other protocols to Rogallo, I'll add a just-good-enough version of them to SmolServe to help me with testing and documentation. For the moment, though, I think it's in a stable and usable state.
Rogallov1.6.0 is now available. This release concentrates on the addition of a newly-supported protocol, and improving what can be displayed in the viewer and how it looks.
The headline change is the addition of support for the Spartan protocol. Having run into a couple of sites that either offered this as an alternative access method to their content, or the only access method, and noticing its vague similarity to Gemini (and also its reliance on Gemtext as the main hypertext language), it seemed like an obvious feature to add. So, having built a library to handle the low-level details, I got to adding support for this to Rogallo.
Anyone using Rogallo should find that spartan:// URIs are handled in just the same way as gemini:// URIs are, so following them from within documents, or entering them into the command line all works. On top of this, Rogallo now supports Spartan's =: line type in documents served from a Spartan server. This means that this form of input is now supported.
I suspect this won't be the last of them, but I sense I'm close to adding the most useful ones.
The two other changes in this release are closely related. Rogallo has always handed off any MIME types that it can't directly handle, and the types it could handle were set to a very narrow collection -- Gemtext, Gopher maps and plain text, pretty much. With this release the list has been expanded to anything text/*. Working on the (pretty safe) assumption that any text/ MIME type can be displayed as text, this seemed like a sensible switch to make.
Working in conjunction with this, Rogallo will now also attempt to infer what kind of text is being shown, and apply some syntax highlighting where appropriate. So, for example, if you visit a text file that is Python code, it will be highlighted as Python code (if the server tells us that we're looking at Python code).
One final change in this release is a small fix to Gopher support. Rogallo lets you configure a connection timeout value, but this wasn't being used for Gopher support. This is now fixed.
Now that Rogallo supports multiple protocols, it's tempting to add one or two more. As of the time of writing, alongside Gemini, both Gopher and Finger are supported. While wandering the small web, I stumbled on the Spartan protocol. Given its similarity to Gemini and the fact it uses Gemtext as its main document type, adding it to Rogallo seemed like an obvious thing to do.
In aid of this, I've created Sybaritic. It is, in effect, a sibling library to Wasat, Port70 and Port79. As with the others, it is async-all-the-way and is designed to have a similar API.
With this in place, I can now extend Rogallo to handle spartan:// URIs as first-class citizens.
I've released a small update to Gemtext. At the moment, I'm working on adding Spartan protocol support to Rogallo, and to do this I need to handle a small extension it makes to Gemtext.
While Spartan is quite different from Gemini in the underlying protocol, it uses Gemtext as the default/standard markup language, but with one small difference. To allow uploaded data that is initiated by the markup, rather than by the server, there is a =: line type. In some respects, this is similar to type 7 items in Gopher maps.
Rather than spin up a whole new library just to support this one small difference, and rather than do some special-case nonsense in Rogallo itself, I've added optional (and turned on by default) support for =:. When encountered, this results in a SpartanPrompt object, which simply inherits from a Link.