From 3ecf03966558daa429b10c3ad8d798162383de1b Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Mon, 30 Mar 2020 15:38:40 -0600 Subject: [PATCH] docs: All-new design, along with many content updates in prep for RC1 --- src/docs/index.html | 9 +- src/docs/json/index.html | 14 +- src/docs/markdown/api-tutorial.md | 58 +- src/docs/markdown/automatic-https.md | 37 +- src/docs/markdown/caddyfile-tutorial.md | 41 +- .../markdown/caddyfile/directives/respond.md | 4 + src/docs/markdown/command-line.md | 11 +- src/docs/markdown/conventions.md | 35 +- src/docs/markdown/getting-started.md | 90 ++-- src/docs/markdown/quick-starts.md | 2 +- src/docs/markdown/quick-starts/https.md | 16 +- src/docs/markdown/v2-upgrade.md | 28 +- src/docs/modules/index.html | 53 +- src/includes/docs-details.html | 9 +- src/includes/docs-head.html | 1 + src/includes/footer.html | 28 +- src/index.html | 2 +- src/resources/css/chroma.css | 10 +- src/resources/css/common.css | 16 +- src/resources/css/docs-json.css | 8 +- src/resources/css/docs.css | 494 ++++++++++-------- src/resources/js/docs-api.js | 18 +- src/resources/js/docs.js | 13 +- 23 files changed, 562 insertions(+), 435 deletions(-) diff --git a/src/docs/index.html b/src/docs/index.html index 87703f9..d474bac 100644 --- a/src/docs/index.html +++ b/src/docs/index.html @@ -10,23 +10,20 @@ {{include "/includes/docs-head.html"}} - {{include "/includes/docs-header.html"}}
{{include "/includes/docs-nav.html"}}
-
- Caddy 2 is beta software. It is ready for production, but some things will change between releases; check the release notes before upgrading. -
-
+
+
+
{{markdown $markdownFile.Body}}
- {{include "/includes/footer.html"}} diff --git a/src/docs/json/index.html b/src/docs/json/index.html index 6b3951b..a16c1bc 100644 --- a/src/docs/json/index.html +++ b/src/docs/json/index.html @@ -13,13 +13,13 @@
{{include "/includes/docs-nav.html"}}
- - - {{include "/includes/docs-renderbox.html"}} - -
+
+
+
+ + {{include "/includes/docs-renderbox.html"}} {{include "/includes/docs-details.html"}}
diff --git a/src/docs/markdown/api-tutorial.md b/src/docs/markdown/api-tutorial.md index f204472..a2065ec 100644 --- a/src/docs/markdown/api-tutorial.md +++ b/src/docs/markdown/api-tutorial.md @@ -25,7 +25,7 @@ To start the Caddy daemon, use the `run` subcommand:
caddy run
- + This blocks forever, but what is it doing? At the moment... nothing. By default, Caddy's configuration ("config") is blank. We can verify this using the [admin API](/docs/api) in another terminal: @@ -38,7 +38,7 @@ We can make Caddy useful by giving it a config. One way to do this is by making To prepare our request, we need to make a config. Caddy's configuration is simply a [JSON document](/docs/json/) (or [anything that converts to JSON](/docs/config-adapters)). Save this to a JSON file: @@ -68,12 +68,12 @@ Save this to a JSON file: Then upload it:
curl localhost:2019/load \
-  -X POST \
-  -H "Content-Type: application/json" \
-  -d @caddy.json
+	-X POST \
+	-H "Content-Type: application/json" \
+	-d @caddy.json
 
- + We can verify that Caddy applied our new config with another GET request: @@ -84,7 +84,7 @@ Test that it works by going to [localhost:2015](http://localhost:2015) in your b
curl localhost:2015
 Hello, world!
- + If you see _Hello, world!_, then congrats -- it's working! It's always a good idea to make sure your config works as you expect, especially before deploying into production. @@ -100,12 +100,12 @@ Let's change our welcome message from "Hello world!" to something a little more Save the config file, then update Caddy's active configuration by running the same POST request again:
curl localhost:2019/load \
-  -X POST \
-  -H "Content-Type: application/json" \
-  -d @caddy.json
+	-X POST \
+	-H "Content-Type: application/json" \
+	-d @caddy.json
 
- + For good measure, verify that the config was updated: @@ -116,19 +116,19 @@ Test it by refreshing the page in your browser (or running `curl` again), and yo ## Config traversal +Instead of uploading the entire config file for a small change, let's use a powerful feature of Caddy's API to make the change without ever touching our config file. + -Instead of uploading the entire config file for a small change, let's use a powerful feature of Caddy's API to make the change without ever touching our config file. - Using the request URI's path, we can traverse into the config structure and update only the message string (be sure to scroll right if clipped):
curl \
-  localhost:2019/config/apps/http/servers/example/routes/0/handle/0/body \
-  -X POST \
-  -H "Content-Type: application/json" \
-  -d '"Work smarter, not harder."'
+	localhost:2019/config/apps/http/servers/example/routes/0/handle/0/body \
+	-X POST \
+	-H "Content-Type: application/json" \
+	-d '"Work smarter, not harder."'
 
+ + **Important note:** This should be obvious, but once you use the API to make a change that is not in your original config file, your config file becomes obsolete. There are a few ways to handle this: - Use the `--resume` of the [caddy run](/docs/command-line#caddy-run) command to use the last active config. -- [Export Caddy's new configuration](/docs/api#get-configpath) with a subsequent GET request. - Don't mix the use of config files with changes via the API; have one source of truth. - - +- [Export Caddy's new configuration](/docs/api#get-configpath) with a subsequent GET request (less recommended than the first two options). @@ -166,10 +166,10 @@ Config traversal is certainly useful, but the paths are little long, don't you t We can give our handler object an [`@id` tag](/docs/api#using-id-in-json) to make it easier to access:
curl \
-  localhost:2019/config/apps/http/servers/example/routes/0/handle/0/@id \
-  -X POST \
-  -H "Content-Type: application/json" \
-  -d '"msg"'
+	localhost:2019/config/apps/http/servers/example/routes/0/handle/0/@id \
+	-X POST \
+	-H "Content-Type: application/json" \
+	-d '"msg"'
 
This adds a property to our handler object: `"@id": "msg"`, so it now looks like this: @@ -193,16 +193,16 @@ We can then access it directly: And now we can change the message with a shorter path:
curl \
-  localhost:2019/id/msg/body \
-  -X POST \
-  -H "Content-Type: application/json" \
-  -d '"Some shortcuts are good."'
+	localhost:2019/id/msg/body \
+	-X POST \
+	-H "Content-Type: application/json" \
+	-d '"Some shortcuts are good."'
 
And check it again:
curl localhost:2019/id/msg/body
- + diff --git a/src/docs/markdown/automatic-https.md b/src/docs/markdown/automatic-https.md index 136c26e..bb4647c 100644 --- a/src/docs/markdown/automatic-https.md +++ b/src/docs/markdown/automatic-https.md @@ -6,17 +6,17 @@ title: "Automatic HTTPS" **Caddy is the first and only web server to use HTTPS automatically _and by default_.** - - Automatic HTTPS provisions TLS certificates for all your sites and keeps them renewed. It also redirects HTTP to HTTPS for you! Caddy uses safe and modern defaults -- no downtime or extra configuration required. + + Here's a 28-second video showing how it works: -## tl;dr +## Overview **Caddy serves all sites over HTTPS by default.** @@ -32,7 +32,8 @@ Caddy keeps all certificates renewed, and redirects HTTP (default port 80) to HT **For public domain names:** - + + - If your domain's A/AAAA records point to your server, - ports 80 and 443 are open externally, @@ -42,8 +43,6 @@ Caddy keeps all certificates renewed, and redirects HTTP (default port 80) to HT then sites will be served over HTTPS automatically and without problems. You won't have to know or do anything else about it. It should "just work"! - - If you are still testing your setup, however, please read on or you risk being rate limited by your CA. The rest of this page goes over the details for advanced use cases and troubleshooting purposes. @@ -52,9 +51,9 @@ If you are still testing your setup, however, please read on or you risk being r Caddy implicitly activates automatic HTTPS when it knows a domain name (i.e. hostname) it is serving. Depending on how you run or configure Caddy, there are various ways to tell Caddy which domain names to use: -- The [Caddyfile](/docs/caddyfile/concepts#addresses) -- A [host matcher](/docs/json/apps/http/servers/routes/match/host/) in a route -- Command line flags like [--domain](/command-line#caddy-file-server) or [--from](/docs/command-line#caddy-reverse-proxy) +- A [site address](/docs/caddyfile/concepts#addresses) in the [Caddyfile](/docs/caddyfile) +- A [host matcher](/docs/json/apps/http/servers/routes/match/host/) in a [route](/docs/modules/http#servers/routes) +- Command line flags like [--domain](/docs/command-line#caddy-file-server) or [--from](/docs/command-line#caddy-reverse-proxy) - The [automate](/docs/json/apps/tls/certificates/automate/) certificate loader Any of the following will prevent automatic HTTPS from being activated, either in whole or in part: @@ -70,8 +69,8 @@ Any of the following will prevent automatic HTTPS from being activated, either i When automatic HTTPS is activated, the following occurs: - Certificates are obtained and renewed for [all domain names](#hostname-requirements) -- The default port (if any) is changed to the [HTTPS port](/docs/json/apps/http/https_port/) 443 -- HTTP is redirected to HTTPS (this uses [HTTP port](/docs/json/apps/http/http_port/) 80) +- The default port (if any) is changed to the [HTTPS port](/docs/modules/http#https_port) 443 +- HTTP is redirected to HTTPS (this uses [HTTP port](/docs/modules/http#http_port) 80) Automatic HTTPS never overrides explicit configuration. @@ -86,11 +85,11 @@ All hostnames (domain names and IP addresses) qualify for fully-managed certific - consist only of alphanumerics, hyphens, dots, and wildcard (`*`) - do not start or end with a dot ([RFC 1034](https://tools.ietf.org/html/rfc1034#section-3.5)) -In addition, a hostname qualifies for a publicly-trusted certificate if it: +In addition, hostnams qualify for publicly-trusted certificates if they: -- is not localhost -- is not an IP address -- has only a single wildcard `*` as the left-most label +- are not localhost +- are not an IP address +- have only a single wildcard `*` as the left-most label @@ -104,14 +103,14 @@ Local HTTPS does not use ACME nor does it perform any DNS validation. It works o ### CA Root - - The root's private key is uniquely generated using a cryptographically-secure pseudorandom source and persisted to storage with limited permissions. It is loaded into memory only to perform signing tasks, after which it leaves scope to be garbage-collected. Although Caddy can be configured to sign with the root directly (to support non-compliant clients), this is disabled by default, and the root key is only used to sign intermediates. The first time a root key is used, Caddy will try to install it into the system's local trust store(s). If it does not have permission to do so, it will prompt for a password. This behavior can be disabled in the configuration if it is not desired. + + After Caddy's root CA is installed, you will see it in your local trust store as "Caddy Local Authority" (unless you've configured a different name). You can uninstall it any time if you wish (the [`caddy untrust`](/docs/command-line#caddy-untrust) command makes this easy). @@ -127,7 +126,7 @@ Unlike the root certificate, intermediate certificates have a much shorter lifet ## Testing -To test or experiment with your Caddy configuration, make sure you [change the ACME endpoint](/docs/json/apps/tls/automation/policies/management/acme/ca/) to a staging or development URL, otherwise you are likely to hit rate limits which can block your access to HTTPS for up to a week, depending on which rate limit you hit. +To test or experiment with your Caddy configuration, make sure you [change the ACME endpoint](/docs/modules/tls.issuance.acme#ca) to a staging or development URL, otherwise you are likely to hit rate limits which can block your access to HTTPS for up to a week, depending on which rate limit you hit. Caddy's default CA is [Let's Encrypt](https://letsencrypt.org/), which has a [staging endpoint](https://letsencrypt.org/docs/staging-environment/) that is not subject to the same [rate limits](https://letsencrypt.org/docs/rate-limits/): @@ -199,6 +198,8 @@ Here's what happens if there's an error obtaining or renewing a certificate: - Maximum of 1 day between attempts - For up to 30 days +During retries with Let's Encrypt, Caddy switches to their [staging environment](https://letsencrypt.org/docs/staging-environment/) to avoid rate limit concerns. This isn't a perfect strategy, but in general it's helpful. + ACME challenges take at least a few seconds, and internal rate limiting helps mitigate accidental abuse. Caddy uses internal rate limiting in addition to what you or the CA configure so that you can hand Caddy a platter with a million domain names and it will gradually -- but as fast as it can -- obtain certificates for all of them. Caddy's internal rate limit is currently 10 attempts per ACME account per minute. diff --git a/src/docs/markdown/caddyfile-tutorial.md b/src/docs/markdown/caddyfile-tutorial.md index e7a61cf..bfcec30 100644 --- a/src/docs/markdown/caddyfile-tutorial.md +++ b/src/docs/markdown/caddyfile-tutorial.md @@ -39,17 +39,19 @@ localhost respond "Hello, world!" ``` -Save that and run Caddy: +Save that and run Caddy (since this is a training tutorial, we'll use the `--watch` flag so changes to our Caddyfile are applied automatically): -
caddy run
+
caddy run --watch
-The first time, you'll be asked for your password. This is so Caddy can serve your localhost site over HTTPS. +The first time, you'll be asked for your password. This is so Caddy can serve your site over HTTPS. - + + + Open [localhost](https://localhost) in your browser and see your web server working, complete with HTTPS! -Stop Caddy by pressing Ctrl+C in your terminal. + That's not particularly exciting, so let's change our static response to a [file server](/docs/caddyfile/directives/file_server) with directory listings enabled: @@ -59,9 +61,9 @@ localhost file_server browse ``` -Save your Caddyfile and run Caddy again. Then refresh your browser tab. You should either see a list of files or an HTML page if there is an index file in the current directory. +Save your Caddyfile, then refresh your browser tab. You should either see a list of files or an HTML page if there is an index file in the current directory. - + ## Adding functionality @@ -96,9 +98,7 @@ templates file_server browse ``` - - -Save that, then restart Caddy, then reload the browser tab. You should see: +Save that, then reload the browser tab. You should see: ``` Page loaded at: {{now | date "Mon Jan 2 15:04:05 MST 2006"}} @@ -106,9 +106,9 @@ Page loaded at: {{now | date "Mon Jan 2 15:04:05 MST 2006"}} With Caddy's [templates module](/docs/modules/http.handlers.templates), you can do a lot of useful things with static files, such as including other HTML files, making sub-requests, setting response headers, working with data structures, and more! - + -It's good practice to compress responses with a quick and modern compression algorithm. Let's enable compression using Gzip and Zstandard using the [`encode`](/docs/caddyfile/directives/encode) directive: +It's good practice to compress responses with a quick and modern compression algorithm. Let's enable Gzip and Zstandard support using the [`encode`](/docs/caddyfile/directives/encode) directive: ``` localhost @@ -118,7 +118,10 @@ templates file_server browse ``` - + + + + That's the basic process for getting a semi-advanced, production-ready site up and running! @@ -178,7 +181,7 @@ For multiple sites which share the same configuration, you can add more addresse You can then define as many different sites as you want, as long as each address is unique. - + ## Matchers @@ -194,7 +197,7 @@ file_server reverse_proxy 127.0.0.1:9005 ``` -In practice, we may want to use the reverse proxy only for API requests, i.e. requests with a base path of `/api/`. This is easy to do, by adding a matcher token: +In practice, we may want to use the reverse proxy only for API requests, i.e. requests with a base path of `/api/`. This is easy to do by adding a [matcher token](/docs/caddyfile/matchers#syntax): ``` localhost @@ -207,9 +210,9 @@ There; now the reverse proxy will be prioritized for all requests starting with The `/api/*` token we just added is called a **matcher token**. You can tell it's a matcher token because it starts with a forward slash `/` and it appears right after the directive (but you can always look it up in the [directive's docs](/docs/caddyfile/directives) to be sure). -Matchers are actually really powerful. You can name matchers and use them like `@name` to match on more than just the request path! Take a moment to [learn more about matchers](/docs/caddyfile/matchers) before continuing! +Matchers are really powerful. You can name matchers and use them like `@name` to match on more than just the request path! Take a moment to [learn more about matchers](/docs/caddyfile/matchers) before continuing! - + ## Environment variables @@ -237,7 +240,7 @@ file_server You can use environment variables anywhere in the Caddyfile, for any number of tokens. - + ## Comments @@ -248,7 +251,7 @@ One last thing that you will find most helpful: if you want to remark or note an # this starts a comment ``` - + ## Further reading diff --git a/src/docs/markdown/caddyfile/directives/respond.md b/src/docs/markdown/caddyfile/directives/respond.md index 3d92f09..b420591 100644 --- a/src/docs/markdown/caddyfile/directives/respond.md +++ b/src/docs/markdown/caddyfile/directives/respond.md @@ -23,6 +23,10 @@ respond [] | [] { To clarify, the first non-matcher argument can be either a 3-digit status code or a response body string. If it is a body, the next argument can be the status code. + + ## Examples diff --git a/src/docs/markdown/command-line.md b/src/docs/markdown/command-line.md index 97de375..674fe00 100644 --- a/src/docs/markdown/command-line.md +++ b/src/docs/markdown/command-line.md @@ -249,10 +249,6 @@ This command disables the admin API, making it easier to run multiple instances [--resume] [--watch] - - Runs Caddy and blocks indefinitely; i.e. "daemon" mode. `--config` specifies an initial config file to immediately load and use. If no config is specified, Caddy will run with a blank configuration and use default settings for the [admin API endpoints](/docs/api), which can be used to feed it new configuration. As a special case, if the current working directory has a file called "Caddyfile" and the `caddyfile` config adapter is plugged in (default), then that file will be loaded and used to configure Caddy, even without any command line flags. @@ -265,6 +261,11 @@ Runs Caddy and blocks indefinitely; i.e. "daemon" mode. `--watch` will watch the config file and automatically reload it after it changes. ⚠️ This feature is dangerous in production! Only use it in a local development environment. + + + ### `caddy start` @@ -286,7 +287,7 @@ Once started, you can use [`caddy stop`](#caddy-stop) or [the /stop API endpoint
caddy stop [--address <interface>]
Gracefully stops the running Caddy process (other than the process of the stop command) and causes it to exit. It uses the [/stop endpoint](/docs/api#post-stop) of the admin API to perform a graceful shutdown. diff --git a/src/docs/markdown/conventions.md b/src/docs/markdown/conventions.md index 8948f80..7111e5d 100644 --- a/src/docs/markdown/conventions.md +++ b/src/docs/markdown/conventions.md @@ -9,10 +9,6 @@ The Caddy ecosystem adheres to a few conventions to make things consistent and i ## Network addresses - - When specifying a network address to dial or bind, Caddy accepts a string in the following format: ``` @@ -47,15 +43,19 @@ udp/localhost:9005 unix//path/to/socket ``` + + ## Placeholders +Caddy's configuration supports the use of _placeholders_ (variables). Using placeholders is a simple way to inject dynamic values into a static configuration. + -Caddy's configuration supports the use of _placeholders_ (variables). Using placeholders is a simple way to inject dynamic values into a static configuration. - Placeholders are bounded on either side by curly braces `{ }` and contain the variable name inside, for example: `{foo.bar}`. Placeholder braces can be escaped, `\{like so\}`. Variable names are typically namespaced with dots to avoid collisions across modules. Which placeholders are available depends on the context. Not all placeholders are available in all parts of the config. For example, [the HTTP app sets placeholders](/docs/json/apps/http/) that are only available in areas of the config related to handling HTTP requests. @@ -81,12 +81,12 @@ This section contains information about where to find various files. File and di ### Your config files +There is no single, conventional place for you to put your config files. Put them wherever makes the most sense to you. + -There is no single, conventional place for you to put your config files. Put them wherever makes the most sense to you. - Distributions that ship with a default config file should document where this config file is at, even if it might be obvious to the package/distro maintainers. @@ -98,10 +98,6 @@ If the `XDG_DATA_HOME` environment variable is set, it is `$XDG_DATA_HOME/caddy` Otherwise, its path varies by platform, adhering to OS conventions: - - OS | Data directory path ---|--------------------- **Linux, BSD** | `$HOME/.local/share/caddy` @@ -110,6 +106,8 @@ OS | Data directory path **Plan 9** | `$HOME/lib/caddy` **Android** | `$HOME/caddy` (or `/sdcard/caddy`) +All other OSes use the Linux/BSD directory path. + The data directory must not be treated like a cache. Its contents are not ephemeral or merely for the sake of performance. Caddy stores TLS certificates, private keys, OCSP staples, and other necessary information to the data directory. It should not be purged without an understanding of the implications. It is crucial that this directory is persistent and writeable by Caddy. @@ -117,21 +115,16 @@ It is crucial that this directory is persistent and writeable by Caddy. ### Configuration directory +This is where Caddy may store certain configuration to disk. Most notably, it persists the last active configuration (by default) to this folder for easy resumption later using [`caddy run --resume`](/docs/command-line#caddy-run). + - - -This is where Caddy may store certain configuration to disk. Most notably, it persists the last active configuration (by default) to this folder for easy resumption later using [`caddy run --resume`](/docs/command-line#caddy-run). - If the `XDG_CONFIG_HOME` environment variable is set, it is `$XDG_CONFIG_HOME/caddy`. Otherwise, its path varies by platform, adhering to OS conventions: - OS | Config directory path ---|--------------------- @@ -140,6 +133,8 @@ OS | Config directory path **macOS** | `$HOME/Library/Application Support/Caddy` **Plan 9** | `$HOME/lib/caddy` +All other OSes use the Linux/BSD directory path. + It is crucial that this directory is persistent and writeable by Caddy. @@ -161,4 +156,4 @@ Examples: - `1.5h` - `2h45m` -In the [JSON config](/docs/json/), duration values can also be integers which represents nanoseconds. \ No newline at end of file +In the [JSON config](/docs/json/), duration values can also be integers which represent nanoseconds. \ No newline at end of file diff --git a/src/docs/markdown/getting-started.md b/src/docs/markdown/getting-started.md index 623c0b6..5d562db 100644 --- a/src/docs/markdown/getting-started.md +++ b/src/docs/markdown/getting-started.md @@ -34,15 +34,17 @@ Oops; without a subcommand, the `caddy` command only displays help text. You can To start Caddy as a daemon, use the `run` subcommand: -
caddy run
+ + This blocks forever, but what is it doing? At the moment... nothing. By default, Caddy's configuration ("config") is blank. We can verify this using the [admin API](/docs/api) in another terminal: -
curl localhost:2019/config/
-We can make Caddy useful by giving it a config. This can be done many ways, but we'll start by making a POST request to the [/load](/docs/api#post-load) endpoint using `curl`. + + +We can make Caddy useful by giving it a config. This can be done many ways, but we'll start by making a POST request to the [/load](/docs/api#post-load) endpoint using `curl` in the next section. @@ -50,10 +52,6 @@ We can make Caddy useful by giving it a config. This can be done many ways, but To prepare our request, we need to make a config. At its core, Caddy's configuration is simply a [JSON document](/docs/json/). - - Save this to a JSON file: ```json @@ -78,15 +76,19 @@ Save this to a JSON file: } ``` + + Then upload it:
curl localhost:2019/load \
-  -X POST \
-  -H "Content-Type: application/json" \
-  -d @caddy.json
+	-X POST \
+	-H "Content-Type: application/json" \
+	-d @caddy.json
 
- + We can verify that Caddy applied our new config with another GET request: @@ -97,10 +99,9 @@ Test that it works by going to [localhost:2015](http://localhost:2015) in your b
curl localhost:2015
 Hello, world!
- - If you see _Hello, world!_, then congrats -- it's working! It's always a good idea to make sure your config works as you expect, especially before deploying into production. + ## Your first Caddyfile @@ -115,10 +116,11 @@ Another way to configure Caddy is with the [**Caddyfile**](/docs/caddyfile). The respond "Hello, world!" ``` - Save that to a file named `Caddyfile` (no extension) in the current directory. + + Stop Caddy if it is already running (Ctrl+C), then run:
caddy adapt
@@ -127,31 +129,29 @@ Or if you stored the Caddyfile somewhere else or named it something other than `
caddy adapt --config /path/to/Caddyfile
- - You will see JSON output! What happened here? We just used a [_config adapter_](/docs/config-adapters) to convert our Caddyfile to Caddy's native JSON structure. -While we could take that output and make another API request, we can skip all those steps because the `caddy` command can do it for us. + -Since the Caddyfile is so common, if there is a file called Caddyfile in the current directory and no other config is specified, Caddy will load the Caddyfile, adapt it for us, and run it right away. +While we could take that output and make another API request, we can skip all those steps because the `caddy` command can do it for us. If there is a file called Caddyfile in the current directory and no other config is specified, Caddy will load the Caddyfile, adapt it for us, and run it right away. -So now that there is a Caddyfile in the current folder, let's do `caddy run` again: +Now that there is a Caddyfile in the current folder, let's do `caddy run` again:
caddy run
-Or if your Caddyfile is somewhere else (or named something else): +Or if your Caddyfile is somewhere else: -
caddy run \
-	--config /path/to/Caddyfile \
-	--adapter caddyfile
+
caddy run --config /path/to/Caddyfile
+ +(If it is called something else that doesn't start with "Caddyfile", you will need to specify `--adapter caddyfile`.) You can now try loading your site again and you will see that it is working! - + -As you can see, we can start Caddy with an initial config several ways: +As you can see, there are several ways you can start Caddy with an initial config: - A file named Caddyfile in the current directory - The `--config` flag (optionally with the `--adapter` flag) @@ -160,9 +160,9 @@ As you can see, we can start Caddy with an initial config several ways: ## JSON vs. Caddyfile -Now you know that the Caddyfile is just converted to JSON under the hood. +Now you know that the Caddyfile is just converted to JSON for you. -The Caddyfile seems simpler than the JSON, but should you always use it? There are pros and cons to each approach. The answer depends on your requirements and use case. +The Caddyfile seems easier than JSON, but should you always use it? There are pros and cons to each approach. The answer depends on your requirements and use case. JSON | Caddyfile -----|---------- @@ -182,15 +182,15 @@ Kind of boring | Kind of fun You will need to decide which is best for your use case. - +It is important to note that both JSON and the Caddyfile (and [any other supported config adapter](/docs/config-adapters)) can be used with [Caddy's API](/docs/api). However, you get the full range of Caddy's functionality and API features if you use JSON. If using a config adapter, the only way to load or change the config with the API is the [/load endpoint](/docs/api#post-load). -It is important to note that both JSON and the Caddyfile (and [any other supported config adapter](/docs/config-adapters)) can be used with Caddy's API. However, you get the full range of Caddy's functionality and API features if you use JSON. If using a config adapter, the only way to load or change the config with the API is the [/load endpoint](/docs/api#post-load). + ## API vs. Config files You will also want to decide whether your workflow is API-based or CLI-based. (You _can_ use both the API and config files on the same server, but we don't recommend it: best to have one source of truth.) @@ -204,22 +204,22 @@ Really fun | Also fun **Learn more: [API tutorial](/docs/api-tutorial)** | **Learn more: [Caddyfile tutorial](/docs/caddyfile-tutorial)** -The choice of API or config file workflow is orthogonal to the use of config adapters: you can use JSON but store it in a file and use the command line interface; conversely, you can also use the Caddyfile (e.g. from a template) with the API. +The choice of API or config file workflow is orthogonal to the use of config adapters: you can use JSON but store it in a file and use the command line interface; conversely, you can also use the Caddyfile with the API. But most people will use JSON+API or Caddyfile+CLI combinations. As you can see, Caddy is well-suited for a wide variety of use cases and deployments! - + ## Start, stop, run -Since Caddy is a server, it runs indefinitely. That means your terminal won't unblock (can't be used) after you execute `caddy run` until the process is terminated (usually Ctrl+C). +Since Caddy is a server, it runs indefinitely. That means your terminal won't unblock after you execute `caddy run` until the process is terminated (usually with Ctrl+C). Although `caddy run` is the most common and is usually recommended (especially when making a system service!), you can alternatively use `caddy start` to start Caddy and have it run in the background: @@ -233,27 +233,31 @@ You will then have to stop the process yourself, since Ctrl+C won't stop it for Or use [the /stop endpoint](/docs/api#post-stop) of the API. - + ## Reloading config -Whether using the API or command line, your server can perform zero-downtime config reloads or changes. +Your server can perform zero-downtime config reloads/changes. -All [API endpoints](/docs/api) that load or change config are already graceful with zero downtime. +All [API endpoints](/docs/api) that load or change config are graceful with zero downtime. -When using config files with the CLI, however, it may be tempting to use Ctrl+C to stop your server and restart it again to pick up the new configuration. This is sometimes fine in local dev environments, but is a bad idea on a production server. - -Instead, use the [`caddy reload`](/docs/command-line#caddy-reload) command: +When using the command line, however, it may be tempting to use Ctrl+C to stop your server and then restart it again to pick up the new configuration. Don't do this: stopping and starting the server is orthogonal to config changes, and will result in downtime. +Instead, use the [`caddy reload`](/docs/command-line#caddy-reload) command for a graceful config change: +
caddy reload
-This actually just uses the API under the hood, but it will load and (if necessary) adapt your config file to JSON, then gracefully replace the active configuration without downtime. +This actually just uses the API under the hood. It will load and, if necessary, adapt your config file to JSON, then gracefully replace the active configuration without downtime. If there are any errors loading the new config, Caddy rolls back to the last working config. - \ No newline at end of file + + + \ No newline at end of file diff --git a/src/docs/markdown/quick-starts.md b/src/docs/markdown/quick-starts.md index f386f36..cde6d15 100644 --- a/src/docs/markdown/quick-starts.md +++ b/src/docs/markdown/quick-starts.md @@ -13,6 +13,6 @@ It is **highly recommended** that you follow-up by reading other tutorials and r - #### [Using the API](/docs/quick-starts/api) - #### [Using a Caddyfile](/docs/quick-starts/caddyfile) -- #### [File server](/docs/quick-starts/file-server) +- #### [Static file server](/docs/quick-starts/static-files) - #### [Reverse proxy](/docs/quick-starts/reverse-proxy) - #### [HTTPS](/docs/quick-starts/https) diff --git a/src/docs/markdown/quick-starts/https.md b/src/docs/markdown/quick-starts/https.md index 82bacff..459c62f 100644 --- a/src/docs/markdown/quick-starts/https.md +++ b/src/docs/markdown/quick-starts/https.md @@ -6,6 +6,10 @@ title: HTTPS quick-start This guide will show you how to get up and running with [fully-managed HTTPS](/docs/automatic-https) in no time. + + **Prerequisites:** - Basic terminal / command line skills - Basic understanding of DNS @@ -24,15 +28,15 @@ Before continuing, verify correct records with an authoritative lookup. Replace
curl "https://cloudflare-dns.com/dns-query?name=example.com&type=A" \
   -H "accept: application/dns-json"
- - Also make sure your server is externally reachable on ports 80 and 443 from a public interface. + + All we have to do is start Caddy with your domain name in the config. There are several ways to do this. ## Caddyfile -This is the most common way to get HTTPS; it works for almost any kind of site. +This is the most common way to get HTTPS. Create a file called `Caddyfile` (no extension) where the first line is your domain name, for example: @@ -46,12 +50,12 @@ Then from the same directory, run:
caddy run
-You will see Caddy provision a TLS certificate and serve your site over HTTPS. +You will see Caddy provision a TLS certificate and serve your site over HTTPS. This was possible because your site's address in the Caddyfile contained a domain name. ## The `file-server` command -If all you need is a file server over HTTPS, run this command (replacing your domain name): +If all you need is serving static files over HTTPS, run this command (replacing your domain name):
caddy file-server --domain example.com
@@ -69,7 +73,7 @@ You will see Caddy provision a TLS certificate and serve your site over HTTPS. ## JSON config -The general rule of thumb is that any [host matcher](/docs/json/apps/http/servers/routes/match/host/) with a host that looks like a domain name will trigger automatic HTTPS. +The general rule of thumb is that any [host matcher](/docs/json/apps/http/servers/routes/match/host/) will trigger automatic HTTPS. Thus, a JSON config such as the following will enable production-ready [automatic HTTPS](/docs/automatic-https): diff --git a/src/docs/markdown/v2-upgrade.md b/src/docs/markdown/v2-upgrade.md index 9fa2f29..1efbfe7 100644 --- a/src/docs/markdown/v2-upgrade.md +++ b/src/docs/markdown/v2-upgrade.md @@ -71,7 +71,7 @@ Caddy 2's default protocol is [_always_ HTTPS if a hostname or IP is known](/doc IP addresses and localhost domains will be issued certificates from a [locally-trusted, embedded CA](/docs/automatic-https#local-https). All other domains will use Let's Encrypt. (This is all configurable.) -The storage structure of certificates and ACME resources has changed. Caddy 2 will probably obtain new certificates for your sites; but if you have a lot of certificates you can migrate them manually. See issues [#2955](https://github.com/caddyserver/caddy/issues/2955) and [#3124](https://github.com/caddyserver/caddy/issues/3124) for details. +The storage structure of certificates and ACME resources has changed. Caddy 2 will probably obtain new certificates for your sites; but if you have a lot of certificates you can migrate them manually if it does not do it for you. See issues [#2955](https://github.com/caddyserver/caddy/issues/2955) and [#3124](https://github.com/caddyserver/caddy/issues/3124) for details. ## Command line @@ -96,7 +96,7 @@ Environment variables are no longer relevant, except for `HOME` (and, optionally The [v2 Caddyfile](/docs/caddyfile/concepts) is very similar to what you're already familiar with. The main thing you'll need to do is change your directives. -⚠️ **Do not take this advice at face value!** Especially if your config is more advanced, there are many nuances to consider. These tips will get you mostly switched over pretty quickly, but please read the full documentation for each directive so you can understand the implications of the upgrade. And of course, always test your configs thoroughly before putting them into production. +⚠️ **Be sure to read into the new directives!** Especially if your config is more advanced, there are many nuances to consider. These tips will get you mostly switched over pretty quickly, but please read the full documentation for each directive so you can understand the implications of the upgrade. And of course, always test your configs thoroughly before putting them into production. ### Primary changes @@ -105,15 +105,15 @@ The [v2 Caddyfile](/docs/caddyfile/concepts) is very similar to what you're alre - In v1, you could only filter (or "match") directives by request path. In v2, [request matching](/docs/caddyfile/matchers) is much more powerful. Any v2 directives which add a middleware to the HTTP handler chain or which manipulate the HTTP request/response in any way take advantage of this new matching functionality. [Read more about v2 request matchers.](/docs/caddyfile/matchers) You'll need to know about them to make sense of the v2 Caddyfile. -- Although many [placeholders](/docs/conventions#placeholders) are the same, many have changed, and there are now [many new ones](/docs/modules/http), including [shorthands for the Caddyfile](/docs/caddyfile/concepts#placeholders). +- Although many [placeholders](/docs/conventions#placeholders) are the same, many have changed, and there are now [many new ones](/docs/modules/http#docs), including [shorthands for the Caddyfile](/docs/caddyfile/concepts#placeholders). - Caddy 2 logs are all structured, and the default format is JSON. All log levels can simply go to the same log to be processed (but you can customize this if needed). -- Where you matched requests by path prefix in Caddy 1, path matching is now exact by default in Caddy 2, so if you want to match a prefix, for example `/foo/`, you'll need `/foo/*` in Caddy 2. +- Where you matched requests by path prefix in Caddy 1, path matching is now exact by default in Caddy 2. If you want to match a prefix like `/foo/`, you'll need `/foo/*` in Caddy 2. We'll list some of the most common v1 directives here and describe how to convert them for use in the v2 Caddyfile. -⚠️ **Just because a v1 directive is missing from this page does not mean v2 can't do it!** Some v1 directives aren't needed, don't translate well, or are fulfilled other ways in v2. For some advanced customization, you may need to drop down to the JSON to get what you want. Explore our documentation to find what you need! +⚠️ **Just because a v1 directive is missing from this page does not mean v2 can't do it!** Some v1 directives aren't needed, don't translate well, or are fulfilled other ways in v2. For some advanced customization, you may need to drop down to the JSON to get what you want. Explore [our documentation](/docs/caddyfile) to find what you need! ### browse @@ -143,6 +143,8 @@ Note that the `fastcgi` directive from v1 did a lot under the hood, including tr There is no `php` preset needed in v2, since the `php_fastcgi` directive assumes PHP by default. A line such as `php_fastcgi 127.0.0.1:9000 php` will cause the reverse proxy to think that there is a second backend called `php`, leading to connection errors. +The subdirectives are different in v2 -- you probably will not need any for PHP. + ### gzip @@ -158,15 +160,23 @@ Fun fact: Caddy 2 also supports `zstd` (but no browsers do yet). [Mostly unchanged](/docs/caddyfile/directives/header), but now way more powerful since it can do substring replacements in v2. -- **v1:** `header / Strict-Transport-Security "max-age=31536000;"` -- **v2:** `header Strict-Transport-Security "max-age=31536000;"` +- **v1:** `header / Strict-Transport-Security max-age=31536000;` +- **v2:** `header Strict-Transport-Security max-age=31536000;` ### log Enables access logging; the [`log`](/docs/caddyfile/directives/log) directive can still be used in v2, but all logs are structured, encoded as JSON, by default. -Although we recommend everyone use structured logging (it is much more flexible), you can still write Common Log Format to a file, if you must: +The recommended way to enable access logging is simply: + +``` +log +``` + +which emits structured logs to stderr. (You can also emit to a file or network socket; see docs.) + +Although we recommend everyone use [structured logging](/docs/logging), you can still write Common Log Format (CLF) to a file, if you must: - **v1:** ``` @@ -181,6 +191,8 @@ log { } ``` +But we recommend this only for transitioning while your legacy systems still require CLF. + ### proxy diff --git a/src/docs/modules/index.html b/src/docs/modules/index.html index cb6bc5e..b60d7db 100644 --- a/src/docs/modules/index.html +++ b/src/docs/modules/index.html @@ -13,42 +13,33 @@
{{include "/includes/docs-nav.html"}}
- -
-
-

All Modules

-

- This page lists all registered Caddy modules. -

-

- We recommend using your browser's "Find in page" feature for quick lookups. -

- - - - - - -
Module IDDescription
-
-
- -
-
-

-
+
+
+
+

All Modules

+

+ This page lists all registered Caddy modules. +

+

+ We recommend using your browser's "Find in page" feature for quick lookups. +

+ + + + + + +
Module IDDescription
+
+
+

{{include "/includes/docs-renderbox.html"}} -
- {{include "/includes/docs-details.html"}} -
-
- + {{include "/includes/docs-details.html"}} +
- {{include "/includes/docs-hovercard.html"}} - {{include "/includes/footer.html"}} diff --git a/src/includes/docs-details.html b/src/includes/docs-details.html index 831136e..bc80e01 100644 --- a/src/includes/docs-details.html +++ b/src/includes/docs-details.html @@ -1,7 +1,8 @@ -

+

Description

+
-

-

Field List

-
+
+

Field List

+
\ No newline at end of file diff --git a/src/includes/docs-head.html b/src/includes/docs-head.html index dd72750..c746d68 100644 --- a/src/includes/docs-head.html +++ b/src/includes/docs-head.html @@ -1,4 +1,5 @@ {{include "/includes/head.html"}} + \ No newline at end of file diff --git a/src/includes/footer.html b/src/includes/footer.html index 4385ce8..7ec7438 100644 --- a/src/includes/footer.html +++ b/src/includes/footer.html @@ -1,15 +1,13 @@ -
-
-
- - An open source Go community project -
- in partnership with Ardan Labs -
- -
-
+
+
+ + An open source Go community project +
+ in partnership with Ardan Labs +
+ +
diff --git a/src/index.html b/src/index.html index e94873b..4d19ef5 100644 --- a/src/index.html +++ b/src/index.html @@ -28,7 +28,7 @@
then learn how to get started

- Download v1.0 stable + Download v1.0
Caddy is licensed with the Apache 2.0 open source license. diff --git a/src/resources/css/chroma.css b/src/resources/css/chroma.css index b3c2c52..852e326 100644 --- a/src/resources/css/chroma.css +++ b/src/resources/css/chroma.css @@ -8,7 +8,10 @@ Solarized Light (High Contrast) Derived from http://ethanschoonover.com/solarized */ -.chroma { background-color: #f0f9fb; color: #586e75 } +.chroma { + background: linear-gradient(0deg, #f8fbfd 0%, #edf5fd 100%); + color: #254048; +} .chroma .c { color: #93a1a1 } /* Comment */ .chroma .err { color: #586e75 } /* Error */ .chroma .g { color: #586e75 } /* Generic */ @@ -83,7 +86,10 @@ Solarized Dark (High Contrast) Derived from http://ethanschoonover.com/solarized */ - .chroma { background-color: #002b36; color: #93a1a1 } + .chroma { + background: linear-gradient(0deg, #18384d 0%, #122537 100%); + color: #93a1a1; + } .chroma .c { color: #586e75 } /* Comment */ .chroma .err { color: #93a1a1 } /* Error */ .chroma .g { color: #93a1a1 } /* Generic */ diff --git a/src/resources/css/common.css b/src/resources/css/common.css index 07591f4..e110120 100644 --- a/src/resources/css/common.css +++ b/src/resources/css/common.css @@ -14,16 +14,16 @@ body { #v1-banner { display: block; - background: #5ea9a2; + background: #5c92a4; color: #fff; text-align: center; - padding: 15px 25px; - font-size: 18px; + padding: 10px 20px; + font-size: 14px; text-decoration: none; } #v1-banner:hover { - background: #4e968f; + background: #457a8c; } .wrapper { @@ -89,8 +89,12 @@ header nav > a.current { width: 150px; max-width: 100%; margin-right: 20px; + outline: none; } +#search:focus { + background: #fff; +} /* End Algolia search */ header nav .button { @@ -166,9 +170,7 @@ footer { display: flex; justify-content: space-between; margin-top: 100px; - border-top: 1px solid #CCC; - padding-top: 50px; - padding-bottom: 100px; + padding: 0 50px 100px; line-height: 125%; } diff --git a/src/resources/css/docs-json.css b/src/resources/css/docs-json.css index f44b62e..ae0da31 100644 --- a/src/resources/css/docs-json.css +++ b/src/resources/css/docs-json.css @@ -1,5 +1,9 @@ -pre > code.json { - background-color: #f0f9f8; +article { + padding-top: 0 !important; +} + +article h1 { + padding-top: 8%; } #renderbox { diff --git a/src/resources/css/docs.css b/src/resources/css/docs.css index 90b9711..ad66926 100644 --- a/src/resources/css/docs.css +++ b/src/resources/css/docs.css @@ -1,10 +1,10 @@ body { font-family: Maven Pro, sans-serif; + background: #f1f4f5; } header { - border-bottom: 1px solid #f0f6f7; - padding: 10px 20px; + padding: 20px 40px; } #logo-container { @@ -20,8 +20,9 @@ header { #logo-docs { font-family: Montserrat, sans-serif; + font-weight: bold; text-transform: uppercase; - color: #196165; + color: #0e495e; margin-left: 10px; font-size: 12px; } @@ -37,14 +38,22 @@ header nav .button { } .breadcrumbs { - color: #196165; - border-bottom: 1px solid #f0f6f7; + padding: 10px 20px !important; + margin-bottom: 0 !important; + color: #2861aa; font-size: 16px; - padding: 10px 20px; font-weight: bold; line-height: 1.75em; } +#top-breadcrumb { + font-weight: bold; +} + +#top-breadcrumb:not(:hover) { + color: #2861aa; +} + .breadcrumbs a { font-weight: normal; text-decoration: none; @@ -69,33 +78,26 @@ header nav .button { padding-bottom: 10px; } -#top-breadcrumb { - font-weight: bold; -} - -#top-breadcrumb:not(:hover) { - color: #196165; -} - main { display: flex; -} - -main > .sidebar, -article aside { - width: 20%; + justify-content: center; } main > .sidebar { + width: 18%; flex-shrink: 0; - padding: 20px 0; - border: 0px solid #f0f6f7; + flex-grow: 1; + padding: 20px; + max-width: 400px; } -main nav { - border-right-width: 1px; +main > .sidebar:last-child { + flex-shrink: 1; +} + +main > nav.sidebar { position: relative; - font-size: 18px; + font-size: 16px; } main nav ul { @@ -106,19 +108,19 @@ main nav li { position: relative; } -main nav li a { - padding: 8px 22px; -} - main nav li a { display: block; text-decoration: none; color: inherit; + border-radius: 1.5em; + padding: 6px 18px 6px 28px; + color: #546c75; } + + main nav li a:hover { - background-color: #f8fcff; - color: #196165; + color: #01324b; } main nav li a:before { @@ -128,13 +130,13 @@ main nav li a:before { line-height: 1rem; position: absolute; opacity: 0; - left: 5px; + left: 0; transition: left .15s, opacity .15s; } main nav li a:hover:before { opacity: 1; - left: 10px; + left: .75em; } main nav li li a:hover:before { @@ -142,13 +144,15 @@ main nav li li a:hover:before { } main nav li a.current { - background-color: #f0f6f7; + background-color: #e0e8f0; } main nav li.heading { font-weight: bold; - font-size: 120%; - padding: 10px 20px 5px; + text-transform: uppercase; + font-size: 90%; + letter-spacing: 1px; + padding: 10px 20px 10px 2em; } main nav li.heading:not(:first-child) { @@ -158,33 +162,90 @@ main nav li.heading:not(:first-child) { main nav li li a { padding-top: 6px; padding-bottom: 4px; - padding-left: 2.5em; + padding-left: 3em; font-size: 90%; } -.article-container { - flex-grow: 1; - min-width: 0; +.paper { + position: relative; + flex-shrink: 0; + width: 100%; + + background: white; + border-radius: 4px; + box-shadow: 1px 2px 4px 1px rgba(0, 0, 0, .15); } -article, -.content { - margin: 0 auto; - max-width: 950px; +#paper1, +#paper2 { + background: #f8fafb; + max-height: 1500px; +} + +#paper1 { + top: -20px; + left: 20px; + transform: rotate(3deg); +} + +#paper2 { + top: 30px; + left: -100%; + transform: rotate(-5deg); +} + +.paper3 { + top: 20px; + left: -200%; +} + +.article-container { + display: flex; + align-content: flex-start; + flex-grow: 1; + min-width: 0; + margin: 20px; + width: 100%; + max-width: 1100px; } article { - padding: 40px; + padding-top: 8%; + padding-bottom: 8%; font-size: 20px; word-wrap: break-word; } +/* +while we want most elements that are rendered +server-side from markdown to have a constrained +width, a few elements should be allowed to +extend to the borders of the page +*/ +article > :not(.fullwidth), +article > .fullwidth > * { + padding-left: 8%; + padding-right: 8%; +} +article > :not(h1), +dd, article p, -article pre > code, -article pre.chroma, +article ol, article ul, -article ol { - margin-bottom: 1em; +article pre, +article table { + margin-bottom: 1.5rem; +} +article > .fullwidth { margin-bottom: 1.5rem; } +article > .fullwidth > * { margin-bottom: 0; } + +article > pre.chroma > code { + background: none; + padding: 0; +} +article > pre.chroma { + padding-top: 2em; + padding-bottom: 2em; } article ul, @@ -194,22 +255,45 @@ article ol, margin-left: 2.5em; } +article ul ul, +article ol ol, +article ol ul, +article ul ol { + margin-bottom: 0; +} + article p, article li { line-height: 1.5em; } +h1, +h2, +h3, +h4, +h5, +h6 { + /* to ensure that the anchor-link icons stay inside the heading */ + position: relative; +} + +h1, +h2 { + text-align: center; +} + h1 { - font-size: 80px; - color: #196165; + font-size: 72px; + color: #0e3e5b; + letter-spacing: -2px; margin-bottom: 50px; } h2 { font-size: 46px; padding-bottom: 15px; - border-bottom: 4px solid #a6d0da; - margin: 100px 0 40px; + border-bottom: 4px solid #72abe8; + margin: 100px 0 40px !important; } h3 { @@ -227,35 +311,37 @@ h5 { margin: 2em 0 1em; } -/* Styles from https://github.com/bryanbraun/anchorjs */ -@font-face { - font-family: "anchor-icons"; - src: url(data:n/a;base64,AAEAAAALAIAAAwAwT1MvMg8yG2cAAAE4AAAAYGNtYXDp3gC3AAABpAAAAExnYXNwAAAAEAAAA9wAAAAIZ2x5ZlQCcfwAAAH4AAABCGhlYWQHFvHyAAAAvAAAADZoaGVhBnACFwAAAPQAAAAkaG10eASAADEAAAGYAAAADGxvY2EACACEAAAB8AAAAAhtYXhwAAYAVwAAARgAAAAgbmFtZQGOH9cAAAMAAAAAunBvc3QAAwAAAAADvAAAACAAAQAAAAEAAHzE2p9fDzz1AAkEAAAAAADRecUWAAAAANQA6R8AAAAAAoACwAAAAAgAAgAAAAAAAAABAAADwP/AAAACgAAA/9MCrQABAAAAAAAAAAAAAAAAAAAAAwABAAAAAwBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMCQAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg//0DwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAAIAAAACgAAxAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADAAAAAIAAgAAgAAACDpy//9//8AAAAg6cv//f///+EWNwADAAEAAAAAAAAAAAAAAAAACACEAAEAAAAAAAAAAAAAAAAxAAACAAQARAKAAsAAKwBUAAABIiYnJjQ3NzY2MzIWFxYUBwcGIicmNDc3NjQnJiYjIgYHBwYUFxYUBwYGIwciJicmNDc3NjIXFhQHBwYUFxYWMzI2Nzc2NCcmNDc2MhcWFAcHBgYjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAAADACWAAEAAAAAAAEACAAAAAEAAAAAAAIAAwAIAAEAAAAAAAMACAAAAAEAAAAAAAQACAAAAAEAAAAAAAUAAQALAAEAAAAAAAYACAAAAAMAAQQJAAEAEAAMAAMAAQQJAAIABgAcAAMAAQQJAAMAEAAMAAMAAQQJAAQAEAAMAAMAAQQJAAUAAgAiAAMAAQQJAAYAEAAMYW5jaG9yanM0MDBAAGEAbgBjAGgAbwByAGoAcwA0ADAAMABAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAP) format("truetype"); -} .anchor-link { opacity: 0; - font: 1em / 1 anchor-icons; - text-decoration: none; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - padding-left: 0.375em; + font-size: .6em; + border-radius: 10px; + padding: .3em .5em; + margin-left: .25em; + position: absolute; + top: 5px; } + *:hover > .anchor-link, .anchor-link:focus { opacity: 1; + text-decoration: none; } -code, -pre.chroma { +.anchor-link:hover { + background-color: rgba(0, 0, 0, .075); +} + +pre, +code { font-family: 'PT Mono', 'Source Code Pro', monospace; padding: 3px 6px; - border-radius: 5px; - font-size: 90%; - line-height: 1.4em; + font-size: 95%; + line-height: 1.5em; } code { - background-color: #f0f9fb; + background-color: #e9f1fb; + border-radius: 5px; } code.cmd { @@ -271,15 +357,13 @@ pre.chroma, } pre > code, -pre.chroma { +article > pre { padding: 1em; - border-radius: 10px; overflow: auto; } pre > code.cmd { border-radius: 5px; - tab-size: 2; } code.cmd.bash, @@ -308,7 +392,7 @@ dd { .field-name { display: block; font-family: 'Source Code Pro', monospace; - margin: 0; + margin-top: 2em; font-weight: bold; margin-bottom: .5em; } @@ -316,9 +400,9 @@ dd { .inline-link { text-decoration: none; position: absolute; - margin-left: -1.4em; - margin-top: -.1em; - padding-right: .2em; + margin-left: -1.5em; + /* margin-top: -.1em; */ + padding-right: .3em; padding-left: .2em; visibility: hidden; } @@ -329,8 +413,8 @@ dd { hr { border: none; - border-top: 5px solid #186165; - margin: 2em 0; + border-top: 8px solid #34669b; + margin: 4em 0; } article img { @@ -341,10 +425,6 @@ iframe { margin: 1em 0 2em; } -main > .sidebar:not(:last-child) { - border-right-width: 1px; -} - @@ -357,7 +437,7 @@ main > .sidebar:not(:last-child) { .json .num { color: #038a3f; } .json .bool { color: #9b5e14; } .json .key a:not([href]) { color: #222; } -.json a { +article .json a { text-decoration: none; font-weight: bold; } @@ -485,74 +565,71 @@ main > .sidebar:not(:last-child) { color: #777; } -.beta-warning { - font-size: 14px; - padding: 10px; - border-bottom: 1px solid orange; - background: #fff5e2; - line-height: 1.4em; -} - article aside { - position: absolute; - right: 0; + position: relative; font-size: 16px; - color: #146673; - line-height: 1.4em; - padding: 10px 3.5% 10px 20px; - border: 0px solid #dff9ff; - border-top-width: 1px; - border-left-width: 1px; - background: -webkit-radial-gradient(top left, #d6f0f3, transparent 65%); - background: -moz-radial-gradient(top left, #d6f0f3, transparent 65%); - background: radial-gradient(top left, #d6f0f3, transparent 65%); + margin: 2em auto 3em !important; + max-width: 800px; } -article aside.complete::before, -article aside.tip::before { - text-transform: uppercase; - display: block; - line-height: 1em; - font-weight: 900; +article aside.tip, +article aside.advice { + padding-left: calc(8% + 50px) !important; +} + +article aside.tip::before, +article aside.advice::before { + font-size: 45px; + position: absolute; + top: -4px; + left: 8%; +} + +article aside.tip { + color: #706b95; +} +article aside.advice { + color: #826848; +} + +article aside.tip:nth-child(even)::before { + content: '💁‍♀️'; +} +article aside.tip:nth-child(odd)::before { + content: '💁‍♂️'; +} + +article aside.advice::before { + content: '🤦'; +} + +article aside.complete { + color: #6b6b6b; + border: 2px dotted #88db88; + text-align: center; + max-width: 500px; + padding: 15px 25px !important; } article aside.complete::before { - content: 'complete'; + content: '✅ complete'; + color: #39c849; + text-transform: uppercase; font-size: 14px; - letter-spacing: 2px; - color: #3ea78a; - margin-bottom: 10px; -} - -article aside.tip::before { - content: 'tip'; - color: #d0efef; - position: absolute; - top: -30px; - font-size: 35px; -} - -article aside.warning { - border-top-color: #ffd6a4; - color: #bd6800; - background: -webkit-radial-gradient(top left, #ffd6a4, transparent 65%); - background: -moz-radial-gradient(top left, #ffd6a4, transparent 65%); - background: radial-gradient(top left, #ffd6a4, transparent 65%); -} - -article aside.warning::before { - content: 'warning'; - color: #ffd6a4; - position: absolute; - top: -30px; - font-size: 35px; + font-weight: bold; + letter-spacing: 1px; + margin-right: 2em; + margin-bottom: .5em; } table { table-layout: fixed; border-collapse: collapse; font-size: 16px; - margin: 25px 0; +} + +article > table { + margin: 25px auto; } th, td { @@ -619,10 +696,6 @@ td code { @media (max-width: 1400px) { - article aside { - font-size: 14px; - } - table { font-size: 14px; } @@ -642,53 +715,66 @@ td code { } } -@media (max-width: 1000px) { - main > .sidebar:last-child, - article aside { - display: none; +@media (max-width: 1100px) { + header { + padding-bottom: 0; } main > .sidebar { - width: 30%; - padding: 10px 0; + min-width: 200px; + padding: 20px 10px 0 0; + } + + main > .sidebar:last-child { + display: none; + } + + #paper1, + #paper2 { + display: none; + } + .paper3 { + top: 0; + left: 0; } article { - padding: 20px; - } -} - -@media (max-width: 1000px) and (min-width: 600px) { - main nav li a { - padding: 8px 12px; - } - - main nav li li a { - padding-left: 1.5em; - } - - main nav li a:before { font-size: 18px; - left: -5px; + padding-top: 40px; + padding-bottom: 40px; } - - main nav li a:hover:before { - left: 2px; + + article > :not(.fullwidth), + article > .fullwidth > * { + padding-left: 40px; + padding-right: 40px; } - - main nav li li a:hover:before { - left: .5em; + article > :not(h1) { + margin-bottom: 1.5rem; + } + + article > pre.chroma { + padding-top: 1em; + padding-bottom: 1em; + } + + h1 { + font-size: 45px; + } + + h2 { + font-size: 32px; } } - -@media (max-width: 600px) { +@media (max-width: 700px) { #logo-docs { display: none; } main { flex-direction: column-reverse; + align-items: center; } main > .sidebar { @@ -696,6 +782,20 @@ td code { border-width: 0; border-top-width: 2px; } + + .article-container { + max-width: 100%; /* TODO: why is this necessary?? without it, article overflows super wide on narrow screen */ + margin: 20px 0; + } + + .paper { + border-radius: 0; + box-shadow: none; + } + + .anchor-link { + display: none; + } } @@ -706,10 +806,20 @@ td code { color: #bdd6f7; } - header, - main > .sidebar, - footer { - border-color: #061b35; + #search { + background: rgb(28, 52, 79); + color: #bdd6f7; + } + #search:focus { + background: rgb(46, 70, 96); + } + + #paper1, + #paper2 { + background-color: #030a11; + } + .paper3 { + background-color: #051628; } #logo { @@ -725,8 +835,11 @@ td code { color: #5aa3dc; } + main nav li a { + color: #668d9b; + } + main nav ul li a:hover { - background-color: #13243a; color: #5aa3dc; } @@ -734,8 +847,7 @@ td code { background-color: #061b35; } - .breadcrumbs, - main nav { + .breadcrumbs { border-color: #061b35; } @@ -777,35 +889,9 @@ td code { #hovercard-inline-link { border-color: #0a2b53; } - - .beta-warning { - background-color: #462e00; - color: #ffa500; - } - - article aside { - background: -webkit-radial-gradient(top left, #00515a, transparent 65%); - background: -moz-radial-gradient(top left, #00515a, transparent 65%); - background: radial-gradient(top left, #00515a, transparent 65%); - color: #37c3a9; - border-color: #08575a; - } - - article aside.warning { - border-top-color: #462e00; - color: #e1973b; - background: -webkit-radial-gradient(top left, #462e00, transparent 65%); - background: -moz-radial-gradient(top left, #462e00, transparent 65%); - background: radial-gradient(top left, #462e00, transparent 65%); - border-left-color: #462e00; - } - article aside.warning::before { - color: #e1973b; - } - - article aside.tip:before { - color: #185f5b; + article aside.tip { + color: #8c81e4; } th { diff --git a/src/resources/js/docs-api.js b/src/resources/js/docs-api.js index a05b7dd..08b7ae6 100644 --- a/src/resources/js/docs-api.js +++ b/src/resources/js/docs-api.js @@ -34,7 +34,7 @@ $(function() { // don't allow hoverbox to close anymore, we're re-opening it clearTimeout(hoverTimeout); - var pos = $(this).position(); + var pos = $(this).offset(); // there is a gap between the hoverbox and the link that originated it; // there may be a different link in this gap; if the hover box is visible, @@ -43,7 +43,7 @@ $(function() { // visit the hoverbox while it is over a list of links that are tightly // stacked vertically; if user wants to visit hoverbox for link in this // gap, they can just move the cursor slow enough to fire the timeout - if ($hovercard.is(':visible') && $hovercard.position().top - 10 < pos.top) { + if ($hovercard.is(':visible') && $hovercard.offset().top - 10 < pos.top) { return; } @@ -159,8 +159,16 @@ function beginRendering(json) { renderData(pageData.structure, 0, "", $('
')); console.log("DOCS:", pageDocs); - if ($('#field-list').html().trim()) { - $('#field-list-header').show(); + if ($('#field-list-contents').html().trim()) { + $('#field-list').show(); + } + + // if the browser tried to navigate directly to an element + // on the page when it loaded, it would have failed since + // we hadn't rendered it yet; but now we can scroll to it + // directly since rendering has finished + if (window.location.hash) { + window.location.hash = window.location.hash; } } @@ -291,7 +299,7 @@ function appendToFieldDocs(cleanFieldPath, fieldDoc) { if (canTraverse()) { dt = ''+dt+''; } - $('#field-list').append('
🔗'+dt+'
'+fieldDoc+'
'); + $('#field-list-contents').append('
🔗'+dt+'
'+fieldDoc+'
'); } function indent(nesting, $group) { diff --git a/src/resources/js/docs.js b/src/resources/js/docs.js index 855f699..de45b71 100644 --- a/src/resources/js/docs.js +++ b/src/resources/js/docs.js @@ -18,7 +18,16 @@ $(function() { $currentPageLink.addClass('current'); // add anchor links, inspired by https://github.com/bryanbraun/anchorjs - $('article h1[id],h2[id],h3[id],h4[id],h5[id],h6[id]').each(function() { - $(this).append($('')); + $('article > h1[id], article > h2[id], article > h3[id], article > h4[id], article > h5[id], article > h6[id]').each(function() { + var $anchor = $('🔗'); + $(this).append($anchor); }); + + // the server-side markdown renderer annoyingly renders + // colored code blocks differently from plain ones, in that + // colorized ones do not have the additional inside + // the
; this line finds those and adds a .chroma class
+	// to the outer pre element, and our CSS file has a style to
+	// ensure the inner code block does not produce extra padding
+	$('article > pre:not(.chroma) > code:not(.cmd)').parent().addClass('chroma');
 });
\ No newline at end of file