From a0810fc71e707905aa57e3be3163fbe10ee18a25 Mon Sep 17 00:00:00 2001 From: Shav Kinderlehrer Date: Wed, 8 Nov 2023 00:40:24 -0500 Subject: [PATCH] Implement basic site --- spec/molerat-v0.1.0-alpha.html | 683 +++++++++++++++++++++++++++ src/app.css | 395 ++++++++++++++++ src/routes/+layout.svelte | 43 ++ src/routes/+page.svelte | 9 +- src/routes/software/+page.svelte | 19 + src/routes/v0-1-0-alpha/+page.svelte | 7 + style.css | 395 ++++++++++++++++ svelte.config.js | 6 +- 8 files changed, 1554 insertions(+), 3 deletions(-) create mode 100644 spec/molerat-v0.1.0-alpha.html create mode 100644 src/app.css create mode 100644 src/routes/+layout.svelte create mode 100644 src/routes/software/+page.svelte create mode 100644 src/routes/v0-1-0-alpha/+page.svelte create mode 100644 style.css diff --git a/spec/molerat-v0.1.0-alpha.html b/spec/molerat-v0.1.0-alpha.html new file mode 100644 index 0000000..94ac79b --- /dev/null +++ b/spec/molerat-v0.1.0-alpha.html @@ -0,0 +1,683 @@ + + + + + + Molerat Protocol Specification + + + + + +
+

Molerat Protocol Specification

+
+ +
+

1 molerat v0.1.0-alpha

+

Molerat is yet another protocol like Gemini or http/html/css. It features extended functionality over Gemini while keeping a low bar-of-entry.

+

1.0.1 The Name

+

In nature, naked mole-rats are unusually resistant to cancer. This reflects the philosophy of Molerat- to provide a useable platform, resistant to feature creep.

+

Not only are naked mole-rats highly resistant to cancer, but they also have unusually long life-spans for rodents. This is interpreted as a good omen for the Molerat project- may it live a long and cancer-free life.

+

1.0.2 Inspiration

+

Molerat is heavily inspired by http and Gemini choosing to adopt many principles from both. A core philosophy for Molerat is don’t do it differently just because someone else is already doing it. This is also known as steal good features.

+

1.0.3 Mascot

+

Molerat is represented by Potat the naked mole-rat.

+
+Potat, the naked mole-rat. + +
+

1.1 Overview

+

molerat adopts the TOFU TLS TOFU TLS stands for trust on first use transport layer security. It is a system of securing against MITM (man in the middle) attacks where a malicious actor impersonates the server in order to serve altered content.
+
+
standard from Gemini. TOFU works by storing an id or key for a specific server. On future connections, the client will check to make sure the key still matches the original. If it does not it will produce an error and alert the user as the client may be connected to an impersonator instead.

+

For data transfer, Molerat uses request and response headers to define different types of operations like getting, or putting data.

+

For markup, Molerat uses a markdown-like syntax to define page content like links, text formats, and user-interaction.

+

1.2 Molerat URI Scheme

+

Molerat mostly conforms to the base URI syntax defined in RFC 3986. Similar to Gemini, Molerat does not use the userinfo component of URIs.

+

Molerat URIs use the scheme “molerat” and a default port of 2693.

+

1.3 Requests

+

Basic Molerat requests are built using the format

+
<kind> <url>
+<crlf>
+<crlf>
+

Where

+ +

Molerat supports three different request types. Those are;

+ +

1.3.1 Get

+

In Molerat, get is used to request content from a server. The server need only respond with the content, no other action is necessary.

+

Here is an example get request for the content at molerat://example.com/:

+
get example.com/
+

To get the content at molerat://example.com/resource

+
get example.com/resource
+

To get the content at molerat://example.com/path/to/resource?with=query#and-fragment

+
get example.com/path/to/resource?with=query#and-fragment
+

Note that every request must end with a double crlf. They are not visible when rendered on this page, however to a standard Molerat request in bash one would have to include them like this:

+
echo 'get example.com/resource\r\n\r\n'
+

1.3.2 Put

+

put is used to send content to a server. What is done with that content is up to the server, but it is generally expected to update a record, or create a new one with the data provided. The server may then respond with a new page for the client to display.

+

put also includes the data being sent as a list of <key>:<value> records. These records are delimited by a <tab><crlf> and are formatted as <key>:<value>. A <tab><crlf> following the final key is optional.

+

Here is an example of a put request to submit a username/password for a login page:

+
put example.com/login
+length:32
+hash:02f53083ac99d85db16d2226b370c8137e6d2f4f8a5a52dad84d12d6a9f6f471
+
+username:potat
+password:molerat
+

As you can see, there are two separate sections to a form. These sections are delimited with a \r\n\r\n and they give the server information about the form being submitted. For more information on these header keys, see Section 3.4

+

Multi line form values are also allowed as long as they do not contain a tab directly followed by a crlf:

+
put example.com/submit/story
+length:64
+hash:336ef7e928bfa7de38f84917a976728daca6e67160e6aac7b9fa6ec16784151d
+
+username:potat
+story:Once upon a time...
+There was a beautiful naked mole-rat named Potat. Potat loved things such as marshmallows and stargazing, he found every part of his life to be enjoyable.
+

Keys must not be empty. For example, this would be an invalid put request:

+
put example.com/submit/story
+length:22
+hash:3a9d888ce6913876fdc2258fac9f31aacaa222fa4258f394a22a3f58d4586375
+
+username:potat
+story:
+

Servers implementing the Molerat protocol should reject put requests with empty keys.

+

Note that keys can, however, be solely whitespace. This counts as not being an empty key.

+

Here is a valid put request printed in bash:

+
echo 'put example.com/login\r\nlength:64\t\r\nhash:336ef7e928bfa7de38f84917a976728daca6e67160e6aac7b9fa6ec16784151d\r\n\r\nusername:potat\t\r\npassword:molerat'
+

1.3.3 Del

+

del is used to delete a resource. It is syntactically the same as a get request. A del request can be used to clear up the put request. Since otherwise it would have to be used to request deletion of a resource in a server.

+

Here is an example of a del request:

+
del example.com/item/potat
+

del can use the same form headers and content as put, so it is possible to send authentication via login/password with a del request.

+

1.3.4 All three

+

Here is an example of a typical user session on a theoretical social media site using Molerat requests:

+
    +
  1. get other user’s posts:
  2. +
+
get example.com/
+
    +
  1. put a post:
  2. +
+
put example.com/posts
+username:potat
+content:Hi! I'm the new mascot for the Molerat protocol!
+
    +
  1. del an older post:
  2. +
+
del example.com/posts/1
+
    +
  1. View other posts:
  2. +
+
get example.com/posts
+

1.4 Responses

+

Molerat formats responses as

+
status<crlf>
+message:<value><tab>
+<crlf>
+type:<value><tab>
+<crlf>
+length:<value><tab>
+<crlf>
+hash:<value>
+<crlf>
+<crlf>
+<content>
+

Where

+ +

In a response containing no content, length and hash should not be included. Additionally, the type component should not be included.

+

Molerat responses are really just key-values with an optional content section at the endNote that the exception to this is the status field. Status is just the first line of the response indicating the server and response status.
+
+
. Here is another way to write the template above:

+
status
+message:
+type:
+length:
+hash:
+
+<content>
+

Here is an example valid call and response for a get request:

+

Request:

+
get example.com/
+

Response:

+
10
+message:Success
+type:text/plain
+length:18
+hash:c28de73edf48cbc93eafb11f7266fc2268b9c7c77f9df02e74e0561e6cea7595
+
+Hello, from Potat.
+

Or, using escape codes:

+
# Request
+echo 'get example.com/\r\n\r\n'
+
+# Response
+echo '10\r\nmessage:Success\t\r\ntype:text/plain\t\r\nlength:18\t\r\nhash:c28de73edf48cbc93eafb11f7266fc2268b9c7c77f9df02e74e0561e6cea7595\r\n\r\n'
+

Note that as with put requests, the final form delimiter <tab><crlf> is not necessary in a response.

+

Molerat mandates a hash key to allow clients to optionally cache pages. It should not be used to reliably validate them, however. Instead, a client may read the hash key before allocating memory to load the content, and if it finds an identical one in it’s store, it may display that page instead. This can be used to ease-up on network strain for long documents, as Molerat does not support compression during transport.

+

Clients are not required to keep a hash cache, and if they do, user options to control the hash should be available.

+

1.5 Status Codes

+

Molerat specifies several types of responses status codes:

+ +

1.5.1 1x Codes

+

1x codes are success messages. They indicate that the client request has succeeded.

+

1.5.1.1 10

+

Success. Everything went OK and the new page is attached.

+

1.5.1.2 11

+

Content unchanged. The request was a success, but the client should not update the page.

+

1.5.2 2x Codes

+

2x codes indicate redirection. The server may tell the client see another resource. The redirect location should be an encoded URL in the message component of the response. The server may optionally include content to be displayed while the redirection is taking place.

+

1.5.2.1 20

+

Permanent redirect. The client should not make further requests to this resource.

+

1.5.2.2 21

+

Temporary redirect. The client should temporarily see another source, but not cache the redirect.

+

1.5.3 3x Codes

+

3x codes are for client errors. These should be sent as a response using the message component to explain the error. Servers may optionally include content to display a richer error to the user. Otherwise, the client should display a generated error page.

+

1.5.3.1 30

+

Malformed request. Due to an error with the client, the server was unable to parse the request being sent.

+

1.5.3.2 31

+

Invalid request. The server was able to parse the request, but the data included is not valid in this context. This code should be used for authentication failures and put requests containing data that the server cannot accept.

+

1.5.3.3 32

+

Not available. The requested resource does not exist or is not available to the client. This code can be used for both nonexistent resources, and for cases where the client does not have access to the resource.

+

1.5.4 4x Codes

+

4x codes indicate an unrecoverable failure on the server. If possible, the server should catch internal errors and respond with a 4x code.

+

1.5.4.1 40

+

Internal error. The server cannot proceed as it has encountered an error it does not know how to handle.

+

1.5.4.2 41

+

Not supported. The server does not support or allow access to this resource by the client.

+

1.5.4.3 42

+

Slow down. The client is being rate limited. The message component should be a number corresponding to the seconds a client must wait before making another request to the server.

+

1.5.5 5x Codes

+

5x codes are used for when the server requires a client key to access a resource.

+

1.5.5.1 50

+

Client certificate required. The server requires that the client provides a certificate to proceed. The client should retry the request using a certificate.

+

1.6 MIME Types

+

In responses, the server may specify any valid MIME type. It is up to the client to determine how best to display or open the file. Molerat also supports parameters for MIME types like charset. As with Gemini, the default charset is UTF-8 for text content.

+

1.7 TLS

+

Molerat chooses to adopt many standards from Gemini for TLS. As with Gemini, use of TLS for Molerat requests and responses is required. Additionally, as with Gemini, use of the Server Name Indication extension is TLS is also required. This allows multiple domains to be hosted on a single server while remaining secure.

+

Molerat expects that clients and servers use TLS version 1.2 or higher.

+

1.7.1 Client

+

Clients may use certificate to identify themselves to a server, but a Molerat client should not use a certificate by default.

+

If a resource requires a certificate (via the 50 status code) then the client should allow the user to specify whether to use a short-lived certificate, or a long-lived one.

+

1.7.2 Validation

+

Molerat recommends the same methods of server certificate validation as Gemini (TOFU). Clients may validate server certificates however they want, including not at allNo matter how a client validates a server certificate, it should always strive to be transparent with the user on how it does so.
+
+
.

+

Molerat is a simple protocol, so the need for CA certificates is overly-complex. Of course, a client and server may implement it, but clients should . Of course, a client and server may implement it, but clients should accept self-signed keys by default.

+

1.8 Molerat Text (mtxt)

+

Molerat text, or mtxtis the format that Molerat uses to present pre formatted text.

+

mtxt supports several features, but not all of them must be implemented by every client. A server serving mtxt should use a MIME Type of text/molerat. Like Gemini, Molerat supports an optional lang parameter in addition to charset. Clients may use this for any purpose such as displaying text in the correct direction, or auto-translating to a different language. As with Gemini, the lang parameter accepts comma separated language tags from the IANA Language Registry www.iana.org/assignments/language-subtag-registry/language-subtag-registry
+
+

+
...
+type:text/molerat; lang=en
+...
+
+

Specifies a mtxt document that is in English.

+
+

1.8.1 Headings

+

Molerat supports three levels of heading denoted by a hashtag (#) and then a space. The number of #s denotes the level of heading.

+
# Title Heading
+
+## Subtitle Heading
+
+### Sub-Subtitle Heading
+

Rendered in HTML, it would look like this:

+
+

+Title Heading +

+

+Subtitle Heading +

+

+Sub-Subtitle Heading +

+
+

1.8.2 Text

+

Regular text is simply written on a standalone line. Line breaks are ignored unless there are two in a row. mtxt should not be manually line-wrapped when written, clients should instead choose how and where to wrap text.

+
This is a regular paragraph. The client will choose when to break the line, to better accommodate the user and their device.
+
+
+This line has a break,
+but it will not show up when rendered since it is only one break. 
+People can use a single line break to make it easier to write
+mtxt without changing the end-result.
+
+
+This line has a manual break,
+
+This line will show up on a new line after the previous.
+
+People can use this to separate paragraphs, and other distinguished content.
+

This is how the previous text should look:

+
+

This is a regular paragraph. The client will choose when to break the line, to better accommodate the user and their device.

+

This line has a break, but it will not show up when rendered since it is only one break. People can use a single line break to make it easier to write mtxt without changing the end-result.

+

This line has a manual break,

+

This line will show up on a new line after the previous.

+

People can use this to separate paragraphs, and other distinguished content.

+
+

1.8.3 Subtext formatting

+

Like Markdown, asterisks (*) can be used to format text inside a paragraph.

+
*This text is italic*
+
+**This text is bold**
+
+***This text is italic and bold***
+
+

This text is italic

+

This text is bold

+

This text is italic and bold

+
+

Text surrounded by a single asterisk will be italic, double asterisks will be bold, and triple asterisks should be italic and bold. Asterisks should not style text if surrounded by whitespace.

+
This word is italic: *Potat*
+
+This word is NOT italic: *Potat *
+
+Neither is this one: * Potat*
+
+And DEFINITELY not this one: * Potat *
+
+

This word is italic: Potat

+

This word is NOT italic: *Potat *

+

Neither is this one: * Potat*

+

And DEFINITELY not this one: * Potat *

+
+

Asterisks can be escaped with a backslash (\) character.

+
*I should be italic, but I'm not\*
+
+\*I have fallen to the same predicament*
+
+\*I have too...\*
+
+

*I should be italic, but I’m not*

+

*I have fallen to the same predicament*

+

*I have too…*

+
+ +

Inline links can be specified via the [[ and ]] Characters. Links can link to any type of content like mtxt, images, audio, videos, and even to other pages on other protocols.

+

The following is a link to another Molerat page:

+
[[This links to example.com!]molerat://example.com]
+

It would be displayed like this:

+

This links to example.com!

+

A link in mtxt consists of three parts:

+ +

1.8.4.1 Display Text

+

In a link, the text at the very center of the double braces ([[ and ]]) is the text that the client should display to the user. If no text is specified, then the client should display the URL.

+

1.8.4.2 The URL

+

The URL is a link to the resource that the client should fetch. It is located on the right-hand side of the double braces. If there is no protocol (or scheme) specified (like http://, gemini://, or molerat://), then the client should treat the URL as a relative link on the same website. i.e. if a URL is /about, and the user is on molerat://example.com/login, then the client should interpret the URL as molerat://example.com/about.
+
+

+

1.8.4.3 The Media Type

+

The media type goes on the left-hand side of the double braces and specifies the type of data that is being linked to. By default, it is mtxt, so it can be left blank for regular links to other webpages.

+

If the link is to a media-type that is uncommon, or widely unsupported by the client, then the media type may be a MIME type.

+

Molerat also supports several shorthand media types.

+ +

Here are some examples:

+
[[see here for more info]molerat://example.com/info]
+

Links to molerat://example.com/info and has the text “see here for more info”. It looks like this:

+

see here for more info

+
+
[[]molerat://example.com]
+

Links to molerat://example.com without any text. It looks like this:

+

molerat://example.com

+
+
[![A naked mole-rat.]https://upload.wikimedia.org/wikipedia/commons/0/02/Nacktmull.jpg]
+

If the client supports it, this will embed an image into the text content. Otherwise it will appear as a linkClients without image support should provide some visual way to distinguish regular links and images.
+
+
. Images with display text should use it as an alt text for screen readers.

+

It should look like this:

+
+A naked mole-rat. + +
+
+
[#[Mystery media.]molerat://example.com/media]
+

For links with the # media type, the client should use the type parameter from the server if the link uses the molerat:// scheme. Otherwise, the client may do anything (or nothing at all) to discern the type of media.

+
+
[-[An image of a naked mole-rat.]https://upload.wikimedia.org/wikipedia/commons/0/02/Nacktmull.jpg]
+

This link uses the - media type which means that the client should not attempt to display it as an inline image. Instead, it should look like this:

+

An image of a naked mole-rat.

+

1.8.5 Lists

+

Lists in mtxt can be ordered or unordered.

+

1.8.5.1 Unordered Lists

+

Unordered lists are any sequence of characters preceded by a - (dash) and a space.

+
- item one
+- item two
+- item three
+

Would look like

+
+ +
+

In mtxt, lists do not nest.

+

1.8.5.2 Ordered Lists

+

Ordered lists are any sequence of lines beginning with a sequential number followed by a period and a space.

+
1. item one
+2. item two
+3. item three
+

Would look like

+
+
    +
  1. item one
  2. +
  3. item two
  4. +
  5. item three
  6. +
+
+

mtxt lists can start at any number.

+
5. item one
+6. item two
+7. item three
+

Would look like

+
+
    +
  1. item one
  2. +
  3. item two
  4. +
  5. item three
  6. +
+
+

The only restriction is that the numbers must be sequential going up. This would be an invalid list in mtxt:

+
1. item one
+5. item two.
+10. item three.
+

That means that numbers going down would also be invalid, here is an example of that:

+
3. item one
+2. item two
+1. item three
+

1.8.6 Code Blocks

+

mtxt supports fenced code blocks. Fenced code blocks inherit the same format as Markdown.

+
```
+#include <stdio.h>
+
+int main(void) {
+    printf("hello, world!\n");
+}
+```
+

Fenced code blocks can be any text enclosed in triple backticks (`). Code blocks will have their whitespace preserved. They should also be displayed in a way that distinguishes them from the rest of the document flow such as a mono font, or with a different background color. Exact implementation is up to clients.

+

For example, the above example could be displayed like this:

+
#include <stdio.h>
+
+int main(void) {
+    printf("hello, world!\n");
+}
+

mtxt also supports language specifiers for code blocks. After the opening triple backticks, a language can be specified which the client may use for language highlighting or any other purpose.

+

For example, a code block specifying that its contents are in the c language would look like this:

+
```c
+#include <stdio.h>
+
+int main(void) {
+    printf("hello, world!\n");
+}
+```
+

There is no formal list of supported languages for syntax highlighting, but as a general rule, using the file’s extension name should work. c code should use c, c++ code should use cpp, and JavaScript code should use js.

+

The above code may be syntax highlighted by the client to look something like this:

+
#include <stdio.h>
+
+int main(void) {
+    printf("hello, world!\n");
+}
+

Clients may force-wrap code blocks if necessary, but should avoid doing so to preserve the original formatting.

+

1.8.6.1 Inline Code

+

In addition to code blocks, mtxt also supports inline code snippets. Inline code follows the same way as Subtext Formatting (see Section 3.8.3)

+

This is an example of inline code:

+
I am an example paragraph. I have inline `code` which can be inside the regular text.
+

1.8.7 Horizontal Breaks

+

Three dashes (-) alone on a line will become a horizontal break.

+
Closing paragraph.
+
+---
+
+New paragraph.
+

This would be rendered like this:

+

Closing paragraph.

+
+

New paragraph.

+

A client may display a horizontal break however it likes, but it should be clear that it is a separator between content.

+

1.8.8 Input

+

mtxt allows for text input. An input field looks like this:

+
|Placeholder text..|[id text]
+

That would look like this:

+

+

Input fields are made up of three parts:

+ +

1.8.8.1 Placeholder text

+

Placeholder text is optional. If specified, it will be shown as a prompt for the input. Placeholder text does not support subtext formatting.

+

Here is an example of an input with placeholder text:

+
|Name|[id text]
+

It would look like this:

+

+
+

Without a placeholder text:

+
||[id text]
+

+

1.8.8.2 ID

+

The id is the only mandatory part of an input field. It is what the client will use to identify this input field in the submit request. If two inputs have the same ID on the same page, the client should use the most recent unsubmitted one.

+

1.8.8.3 Type

+

The type is a hint to the client as to what data this form wishes to accept. The client may choose to disregard this, so servers should not expect input to be validated already.

+

These are the types that clients should support:

+ +

1.8.9 Submitting Input

+

To submit input forms on a page, there is a special element:

+
|Submit|(/login get)
+

Depending on the client, this can be rendered as a link or a button:

+

Submit

+ +

Submit elements use parentheses (( and ) ) instead of braces ([ and ]) to specify that they do not accept input, they merely submit it.

+

Submit elements submit every input that came before it on a page. But they ignore inputs that come after themselves.

+

A submit element is made up of three parts:

+ +

1.8.10 Input Form Flow

+

Here is an example of a login page in mtxt:

+
# Login
+
+Please login to the site below:
+
+|username|[username text]
+|password|[password private]
+
+|Login|(/login get)
+

This would look like this:

+
+
+

+Login +

+

+Please login to the site below: +

+
+

+ +
+
+
+
+ + + diff --git a/src/app.css b/src/app.css new file mode 100644 index 0000000..14ed7f1 --- /dev/null +++ b/src/app.css @@ -0,0 +1,395 @@ +html { + font-family: "Lato", sans-serif; + color: #1a1a1a; + background-color: #fdfdfd; +} +body { + margin: 0 auto; + max-width: 36em; + padding-left: 50px; + padding-right: 50px; + padding-top: 50px; + padding-bottom: 50px; + hyphens: auto; + overflow-wrap: break-word; + text-rendering: optimizeLegibility; + font-kerning: normal; +} +@media (max-width: 600px) { + body { + font-size: 0.9em; + padding: 12px; + } + h1 { + font-size: 1.8em; + } +} +@media print { + html { + background-color: white; + } + body { + background-color: transparent; + color: black; + font-size: 12pt; + } + p, h2, h3 { + orphans: 3; + widows: 3; + } + h2, h3, h4 { + page-break-after: avoid; + } +} +p { + margin: 1em 0; +} +a { + color: #1a1a1a; +} +a:visited { + color: #1a1a1a; +} +img { + max-width: 100%; +} +svg { + height: auto; + max-width: 100%; +} +h1, h2, h3, h4, h5, h6 { + margin-top: 1.4em; +} +h5, h6 { + font-size: 1em; + font-style: italic; +} +h6 { + font-weight: normal; +} +ol, ul { + padding-left: 1.7em; + margin-top: 1em; +} +li > ol, li > ul { + margin-top: 0; +} +blockquote { + margin: 1em 0 1em 1.7em; + padding-left: 1em; + border-left: 2px solid #e6e6e6; + color: #606060; +} +code { + font-family: "JetBrainsMono Nerd Font Mono", monospace; + font-size: 85%; + margin: 0; + hyphens: manual; +} +pre { + margin: 1em 0; + overflow: auto; +} +pre code { + padding: 0; + overflow: visible; + overlow-wrap: normal; +} +.sourceCode { + background-color: transparent; + overflow: visible; +} +hr { + background-color: #1a1a1a; + border: none; + height: 1px; + margin: 1em 0; +} +table { + margin: 1em 0; + border-collapse: collapse; + width: 100%; + overflow-x: auto; + display: block; + font-variant-numeric: lining-nums tabular-nums; +} +table caption { + margin-bottom: 0.75em; +} +tbody { + margin-top: 0.5em; + border-top: 1px solid #1a1a1a; + border-bottom: 1px solid #1a1a1a; +} +th { + border-top: 1px solid #1a1a1a; + padding: 0.25em 0.5em 0.25em 0.5em; +} +td { + padding: 0.125em 0.5em 0.25em 0.5em; +} +header { + margin-bottom: 4em; + text-align: center; +} +#TOC li { + list-style: none; +} +#TOC ul { + padding-left: 1.3em; +} +#TOC > ul { + padding-left: 0; +} +#TOC a:not(:hover) { + text-decoration: none; +} +code{white-space: pre-wrap;} +span.smallcaps{font-variant: small-caps;} +div.columns{display: flex; gap: min(4vw, 1.5em);} +div.column{flex: auto; overflow-x: auto;} +div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} +/* The extra [class] is a hack that increases specificity enough to + override a similar rule in reveal.js */ +ul.task-list[class]{list-style: none;} +ul.task-list li input[type="checkbox"] { + font-size: inherit; + width: 0.8em; + margin: 0 0.8em 0.2em -1.6em; + vertical-align: middle; +} +.display.math{display: block; text-align: center; margin: 0.5rem auto;} +/* CSS for syntax highlighting */ +pre > code.sourceCode { white-space: pre; position: relative; } +pre > code.sourceCode > span { line-height: 1.25; } +pre > code.sourceCode > span:empty { height: 1.2em; } +.sourceCode { overflow: visible; } +code.sourceCode > span { color: inherit; text-decoration: inherit; } +div.sourceCode { margin: 1em 0; } +pre.sourceCode { margin: 0; } +@media screen { + div.sourceCode { overflow: auto; } +} +@media print { + pre > code.sourceCode { white-space: pre-wrap; } + pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; } +} +pre.numberSource code +{ counter-reset: source-line 0; } +pre.numberSource code > span +{ position: relative; left: -4em; counter-increment: source-line; } +pre.numberSource code > span > a:first-child::before +{ content: counter(source-line); + position: relative; left: -1em; text-align: right; vertical-align: baseline; + border: none; display: inline-block; + -webkit-touch-callout: none; -webkit-user-select: none; + -khtml-user-select: none; -moz-user-select: none; + -ms-user-select: none; user-select: none; + padding: 0 4px; width: 4em; + background-color: #ffffff; + color: #a0a0a0; +} +pre.numberSource { margin-left: 3em; border-left: 1px solid #a0a0a0; padding-left: 4px; } +div.sourceCode +{ color: #1f1c1b; background-color: #ffffff; } +@media screen { + pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; } +} +code span { color: #1f1c1b; } /* Normal */ +code span.al { color: #bf0303; background-color: #f7e6e6; font-weight: bold; } /* Alert */ +code span.an { color: #ca60ca; } /* Annotation */ +code span.at { color: #0057ae; } /* Attribute */ +code span.bn { color: #b08000; } /* BaseN */ +code span.bu { color: #644a9b; font-weight: bold; } /* BuiltIn */ +code span.cf { color: #1f1c1b; font-weight: bold; } /* ControlFlow */ +code span.ch { color: #924c9d; } /* Char */ +code span.cn { color: #aa5500; } /* Constant */ +code span.co { color: #898887; } /* Comment */ +code span.cv { color: #0095ff; } /* CommentVar */ +code span.do { color: #607880; } /* Documentation */ +code span.dt { color: #0057ae; } /* DataType */ +code span.dv { color: #b08000; } /* DecVal */ +code span.er { color: #bf0303; text-decoration: underline; } /* Error */ +code span.ex { color: #0095ff; font-weight: bold; } /* Extension */ +code span.fl { color: #b08000; } /* Float */ +code span.fu { color: #644a9b; } /* Function */ +code span.im { color: #ff5500; } /* Import */ +code span.in { color: #b08000; } /* Information */ +code span.kw { color: #1f1c1b; font-weight: bold; } /* Keyword */ +code span.op { color: #1f1c1b; } /* Operator */ +code span.ot { color: #006e28; } /* Other */ +code span.pp { color: #006e28; } /* Preprocessor */ +code span.re { color: #0057ae; background-color: #e0e9f8; } /* RegionMarker */ +code span.sc { color: #3daee9; } /* SpecialChar */ +code span.ss { color: #ff5500; } /* SpecialString */ +code span.st { color: #bf0303; } /* String */ +code span.va { color: #0057ae; } /* Variable */ +code span.vs { color: #bf0303; } /* VerbatimString */ +code span.wa { color: #bf0303; } /* Warning */ + +/* figures */ +figure { + text-align: center; +} + +figcaption { + color: #aaa; +} + +img.nofig + figcaption { + display: none; +} + +/* chapter numbers */ +.toc-section-number, +.header-section-number { + color: #aaa; +} + +:is(h4, h5, h6) > .header-section-number, +h4 > .header-section-number, +h5 > .header-section-number, +h6 > .header-section-number { + display: none; +} + +.header-section-number { + font-size: 0.7em; +} + +.header-section-number::before { + content: "Section "; +} +.header-section-number::after { + content: ":\a"; + white-space: pre; +} + +/* sourcecode and sidenotes frame */ +pre:not(.sourceCode), +div.sourceCode, +.sidenote { + padding: 5px; + + border-radius: 3px; + + border: 1px solid #e3e3e3; + background-color: #f5f5f5; +} + +.sidenote br:last-child { + display: none; +} + +/* Sidenotes */ +main { + counter-reset: sidenote-counter; +} + +.sidenote-number { + counter-increment: sidenote-counter; +} + +.sidenote-number::before, +.sidenote::before +/*.sidenote-number::after*/ { + + color: #666; + content: "⊕"; + position: relative; +} + +nav#TOC label, +label.margin-toggle:not(.sidenote-number), +.sidenote::before, +.sidenote-number::before { + vertical-align: baseline; + position: relative; + top: -0.4rem; + + font-size: 0.9rem; +} + +.sidenote-number::before { + top: 0 !important; +} + +.sidenote::before { + left: -6px; +} +.sidenote { + text-indent: 9px; + font-size: 0.8rem; +} + +input.margin-toggle { + display: none; +} + +label.margin-toggle:not(.sidenote-number) { + display: none; +} +label.sidenote-number { + display: inline; +} + +@media (max-width: 750px) { + .margin-toggle:checked + .sidenote, + .margin-toggle:checked + .marginnote { + vertical-align: baseline; + } + + .sidenote-number::before, + .sidenote::before + /*.sidenote-number::after*/ { + content: "⦾"; + } + + label.margin-toggle { + /*color: ;*/ + } + + label.margin-toggle:not(.sidenote-number) { + display: inline; + } + + label { + cursor: pointer; + } + + .sidenote-number::after, + .sidenote, + .marginnote { + display: none; + } + + .margin-toggle:checked + .sidenote, + .margin-toggle:checked + .marginnote { + display: block; + float: left; + clear: both; + width: 100%; + max-width: 100%; + } + .margin-toggle:checked + .sidenote::before { + content: "⦿"; + } +} + +.sidenote-number::after, +.sidenote, +.marginnote { + --max-width: min(calc((100vw - 36em) / 2 - 1em), 18em); + --width: calc(var(--max-width) - 0.5em); +} + +.sidenote, +.marginnote { + float: right; + position: relative; + + width: var(--width); + max-width: var(--max-width); + + margin-right: calc(-1 * ((100vw - 36em) / 2 - 5rem)); +} diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte new file mode 100644 index 0000000..4a5706b --- /dev/null +++ b/src/routes/+layout.svelte @@ -0,0 +1,43 @@ + + +
+
+ + diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 5982b0a..cfe25a8 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,2 +1,7 @@ -

Welcome to SvelteKit

-

Visit kit.svelte.dev to read the documentation

+ + +
+ {@html spec} +
diff --git a/src/routes/software/+page.svelte b/src/routes/software/+page.svelte new file mode 100644 index 0000000..9de32e7 --- /dev/null +++ b/src/routes/software/+page.svelte @@ -0,0 +1,19 @@ +
+

Molerat Implementations

+ +
+

Servers

+
    +
  • + Moleserv - Python library + for creating Molerat servers. +
  • +
+
+ +
+

Clients

+
    +
+
+
diff --git a/src/routes/v0-1-0-alpha/+page.svelte b/src/routes/v0-1-0-alpha/+page.svelte new file mode 100644 index 0000000..cfe25a8 --- /dev/null +++ b/src/routes/v0-1-0-alpha/+page.svelte @@ -0,0 +1,7 @@ + + +
+ {@html spec} +
diff --git a/style.css b/style.css new file mode 100644 index 0000000..14ed7f1 --- /dev/null +++ b/style.css @@ -0,0 +1,395 @@ +html { + font-family: "Lato", sans-serif; + color: #1a1a1a; + background-color: #fdfdfd; +} +body { + margin: 0 auto; + max-width: 36em; + padding-left: 50px; + padding-right: 50px; + padding-top: 50px; + padding-bottom: 50px; + hyphens: auto; + overflow-wrap: break-word; + text-rendering: optimizeLegibility; + font-kerning: normal; +} +@media (max-width: 600px) { + body { + font-size: 0.9em; + padding: 12px; + } + h1 { + font-size: 1.8em; + } +} +@media print { + html { + background-color: white; + } + body { + background-color: transparent; + color: black; + font-size: 12pt; + } + p, h2, h3 { + orphans: 3; + widows: 3; + } + h2, h3, h4 { + page-break-after: avoid; + } +} +p { + margin: 1em 0; +} +a { + color: #1a1a1a; +} +a:visited { + color: #1a1a1a; +} +img { + max-width: 100%; +} +svg { + height: auto; + max-width: 100%; +} +h1, h2, h3, h4, h5, h6 { + margin-top: 1.4em; +} +h5, h6 { + font-size: 1em; + font-style: italic; +} +h6 { + font-weight: normal; +} +ol, ul { + padding-left: 1.7em; + margin-top: 1em; +} +li > ol, li > ul { + margin-top: 0; +} +blockquote { + margin: 1em 0 1em 1.7em; + padding-left: 1em; + border-left: 2px solid #e6e6e6; + color: #606060; +} +code { + font-family: "JetBrainsMono Nerd Font Mono", monospace; + font-size: 85%; + margin: 0; + hyphens: manual; +} +pre { + margin: 1em 0; + overflow: auto; +} +pre code { + padding: 0; + overflow: visible; + overlow-wrap: normal; +} +.sourceCode { + background-color: transparent; + overflow: visible; +} +hr { + background-color: #1a1a1a; + border: none; + height: 1px; + margin: 1em 0; +} +table { + margin: 1em 0; + border-collapse: collapse; + width: 100%; + overflow-x: auto; + display: block; + font-variant-numeric: lining-nums tabular-nums; +} +table caption { + margin-bottom: 0.75em; +} +tbody { + margin-top: 0.5em; + border-top: 1px solid #1a1a1a; + border-bottom: 1px solid #1a1a1a; +} +th { + border-top: 1px solid #1a1a1a; + padding: 0.25em 0.5em 0.25em 0.5em; +} +td { + padding: 0.125em 0.5em 0.25em 0.5em; +} +header { + margin-bottom: 4em; + text-align: center; +} +#TOC li { + list-style: none; +} +#TOC ul { + padding-left: 1.3em; +} +#TOC > ul { + padding-left: 0; +} +#TOC a:not(:hover) { + text-decoration: none; +} +code{white-space: pre-wrap;} +span.smallcaps{font-variant: small-caps;} +div.columns{display: flex; gap: min(4vw, 1.5em);} +div.column{flex: auto; overflow-x: auto;} +div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} +/* The extra [class] is a hack that increases specificity enough to + override a similar rule in reveal.js */ +ul.task-list[class]{list-style: none;} +ul.task-list li input[type="checkbox"] { + font-size: inherit; + width: 0.8em; + margin: 0 0.8em 0.2em -1.6em; + vertical-align: middle; +} +.display.math{display: block; text-align: center; margin: 0.5rem auto;} +/* CSS for syntax highlighting */ +pre > code.sourceCode { white-space: pre; position: relative; } +pre > code.sourceCode > span { line-height: 1.25; } +pre > code.sourceCode > span:empty { height: 1.2em; } +.sourceCode { overflow: visible; } +code.sourceCode > span { color: inherit; text-decoration: inherit; } +div.sourceCode { margin: 1em 0; } +pre.sourceCode { margin: 0; } +@media screen { + div.sourceCode { overflow: auto; } +} +@media print { + pre > code.sourceCode { white-space: pre-wrap; } + pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; } +} +pre.numberSource code +{ counter-reset: source-line 0; } +pre.numberSource code > span +{ position: relative; left: -4em; counter-increment: source-line; } +pre.numberSource code > span > a:first-child::before +{ content: counter(source-line); + position: relative; left: -1em; text-align: right; vertical-align: baseline; + border: none; display: inline-block; + -webkit-touch-callout: none; -webkit-user-select: none; + -khtml-user-select: none; -moz-user-select: none; + -ms-user-select: none; user-select: none; + padding: 0 4px; width: 4em; + background-color: #ffffff; + color: #a0a0a0; +} +pre.numberSource { margin-left: 3em; border-left: 1px solid #a0a0a0; padding-left: 4px; } +div.sourceCode +{ color: #1f1c1b; background-color: #ffffff; } +@media screen { + pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; } +} +code span { color: #1f1c1b; } /* Normal */ +code span.al { color: #bf0303; background-color: #f7e6e6; font-weight: bold; } /* Alert */ +code span.an { color: #ca60ca; } /* Annotation */ +code span.at { color: #0057ae; } /* Attribute */ +code span.bn { color: #b08000; } /* BaseN */ +code span.bu { color: #644a9b; font-weight: bold; } /* BuiltIn */ +code span.cf { color: #1f1c1b; font-weight: bold; } /* ControlFlow */ +code span.ch { color: #924c9d; } /* Char */ +code span.cn { color: #aa5500; } /* Constant */ +code span.co { color: #898887; } /* Comment */ +code span.cv { color: #0095ff; } /* CommentVar */ +code span.do { color: #607880; } /* Documentation */ +code span.dt { color: #0057ae; } /* DataType */ +code span.dv { color: #b08000; } /* DecVal */ +code span.er { color: #bf0303; text-decoration: underline; } /* Error */ +code span.ex { color: #0095ff; font-weight: bold; } /* Extension */ +code span.fl { color: #b08000; } /* Float */ +code span.fu { color: #644a9b; } /* Function */ +code span.im { color: #ff5500; } /* Import */ +code span.in { color: #b08000; } /* Information */ +code span.kw { color: #1f1c1b; font-weight: bold; } /* Keyword */ +code span.op { color: #1f1c1b; } /* Operator */ +code span.ot { color: #006e28; } /* Other */ +code span.pp { color: #006e28; } /* Preprocessor */ +code span.re { color: #0057ae; background-color: #e0e9f8; } /* RegionMarker */ +code span.sc { color: #3daee9; } /* SpecialChar */ +code span.ss { color: #ff5500; } /* SpecialString */ +code span.st { color: #bf0303; } /* String */ +code span.va { color: #0057ae; } /* Variable */ +code span.vs { color: #bf0303; } /* VerbatimString */ +code span.wa { color: #bf0303; } /* Warning */ + +/* figures */ +figure { + text-align: center; +} + +figcaption { + color: #aaa; +} + +img.nofig + figcaption { + display: none; +} + +/* chapter numbers */ +.toc-section-number, +.header-section-number { + color: #aaa; +} + +:is(h4, h5, h6) > .header-section-number, +h4 > .header-section-number, +h5 > .header-section-number, +h6 > .header-section-number { + display: none; +} + +.header-section-number { + font-size: 0.7em; +} + +.header-section-number::before { + content: "Section "; +} +.header-section-number::after { + content: ":\a"; + white-space: pre; +} + +/* sourcecode and sidenotes frame */ +pre:not(.sourceCode), +div.sourceCode, +.sidenote { + padding: 5px; + + border-radius: 3px; + + border: 1px solid #e3e3e3; + background-color: #f5f5f5; +} + +.sidenote br:last-child { + display: none; +} + +/* Sidenotes */ +main { + counter-reset: sidenote-counter; +} + +.sidenote-number { + counter-increment: sidenote-counter; +} + +.sidenote-number::before, +.sidenote::before +/*.sidenote-number::after*/ { + + color: #666; + content: "⊕"; + position: relative; +} + +nav#TOC label, +label.margin-toggle:not(.sidenote-number), +.sidenote::before, +.sidenote-number::before { + vertical-align: baseline; + position: relative; + top: -0.4rem; + + font-size: 0.9rem; +} + +.sidenote-number::before { + top: 0 !important; +} + +.sidenote::before { + left: -6px; +} +.sidenote { + text-indent: 9px; + font-size: 0.8rem; +} + +input.margin-toggle { + display: none; +} + +label.margin-toggle:not(.sidenote-number) { + display: none; +} +label.sidenote-number { + display: inline; +} + +@media (max-width: 750px) { + .margin-toggle:checked + .sidenote, + .margin-toggle:checked + .marginnote { + vertical-align: baseline; + } + + .sidenote-number::before, + .sidenote::before + /*.sidenote-number::after*/ { + content: "⦾"; + } + + label.margin-toggle { + /*color: ;*/ + } + + label.margin-toggle:not(.sidenote-number) { + display: inline; + } + + label { + cursor: pointer; + } + + .sidenote-number::after, + .sidenote, + .marginnote { + display: none; + } + + .margin-toggle:checked + .sidenote, + .margin-toggle:checked + .marginnote { + display: block; + float: left; + clear: both; + width: 100%; + max-width: 100%; + } + .margin-toggle:checked + .sidenote::before { + content: "⦿"; + } +} + +.sidenote-number::after, +.sidenote, +.marginnote { + --max-width: min(calc((100vw - 36em) / 2 - 1em), 18em); + --width: calc(var(--max-width) - 0.5em); +} + +.sidenote, +.marginnote { + float: right; + position: relative; + + width: var(--width); + max-width: var(--max-width); + + margin-right: calc(-1 * ((100vw - 36em) / 2 - 5rem)); +} diff --git a/svelte.config.js b/svelte.config.js index 1cf26a0..2034aa1 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -11,7 +11,11 @@ const config = { // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. // If your environment is not supported or you settled on a specific environment, switch out the adapter. // See https://kit.svelte.dev/docs/adapters for more information about adapters. - adapter: adapter() + adapter: adapter(), + + alias: { + "spec/*": "spec/*" + } } };