# Apache / LiteSpeed configuration for the built documentation site.
#
# Shipped from docs/public/, so it lands in dist/ on every build. GitHub Pages
# ignores it; Hostinger and any other Apache-family host read it.

# ── URLs without a trailing slash ────────────────────────────────────────────
# The site is built with trailingSlash: 'never', so /docs/x is canonical. Apache
# would answer that with a 301 to /docs/x/ because a directory of that name
# exists, redirecting every URL to a form the canonical tags disown. Serving the
# index directly keeps the address the reader asked for.
DirectorySlash Off
Options -Indexes

<IfModule mod_rewrite.c>
    RewriteEngine On

    # ── Old documentation URLs ───────────────────────────────────────────────
    # The previous site was MkDocs with mike, which published each minor version
    # under its own prefix plus a "latest" alias, and every page with a trailing
    # slash:
    #
    #     /docs/latest/getting-started/installation/
    #     /docs/1.5/getting-started/installation/
    #
    # Page paths are otherwise unchanged, so the prefix and the slash are all
    # that has to go. Anything still linking to a version keeps working.
    # MkDocs kept the index segment in the URL where Starlight drops it, so
    # /docs/latest/tutorial/index/ has to lose that too.
    RewriteRule ^docs/(?:latest|[0-9]+\.[0-9]+)/(.+?)/index/?$ /docs/$1 [R=301,L]
    RewriteRule ^docs/(?:latest|[0-9]+\.[0-9]+)/(.+?)/?$ /docs/$1 [R=301,L]
    RewriteRule ^docs/(?:latest|[0-9]+\.[0-9]+)/?$ /docs/getting-started/installation [R=301,L]

    # Before mike was moved under /docs/, it published each version at the site
    # root instead — /1.0/, /1.2/, /1.3/ — and one deploy nested a full copy of
    # every older version inside the newest, leaving paths like /1.3/1.2/topics/.
    # Strip the leading version segments however many there are. The bare-version
    # rule has to come first, or /1.3/1.2 is read as version 1.3 of a page named
    # "1.2" and redirects to /docs/1.2.
    RewriteRule ^(?:[0-9]+\.[0-9]+/)+(.+?)/index/?$ /docs/$1 [R=301,L]
    RewriteRule ^(?:[0-9]+\.[0-9]+/?)+$ /docs/getting-started/installation [R=301,L]
    RewriteRule ^(?:[0-9]+\.[0-9]+/)+(.+?)/?$ /docs/$1 [R=301,L]

    # /docs itself was the landing page under mike's default alias. The new site
    # has no index there, so send it to where a reader would have been going.
    RewriteRule ^docs/?$ /docs/getting-started/installation [R=301,L]

    # An existing file or the root is served as-is. This has to come before the
    # rules below, which ask whether a path has an index.html and would answer
    # 404 for a real file like /docs/topics/orm/aggregates.md.
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_URI} ^/$
    RewriteRule ^ - [L]

    # A sidebar grouping — /docs/topics/orm, /docs/reference — is a directory
    # with no index.html, because Starlight writes no page for it. DirectorySlash
    # Off is meant to stop the server adding a trailing slash to those, but this
    # host adds it anyway, and the rule below then takes it off again: the two
    # bounce off each other until the browser gives up. 404 is the honest answer,
    # since there is no such page.
    RewriteCond %{DOCUMENT_ROOT}/$1/index.html !-f
    RewriteRule ^(.+?)/?$ - [R=404,L]

    # The old site put a trailing slash on every URL; this one has none. Old
    # inbound links land on the canonical form rather than being served at an
    # address the page itself disowns.
    RewriteCond %{REQUEST_URI} !^/$
    RewriteRule ^(.+)/$ /$1 [R=301,L]

    # /docs/x  ->  /docs/x/index.html, without a redirect.
    RewriteCond %{DOCUMENT_ROOT}/$1/index.html -f
    RewriteRule ^(.+?)/?$ /$1/index.html [L]
</IfModule>

ErrorDocument 404 /404.html

# ── Raw Markdown ─────────────────────────────────────────────────────────────
# Every page is also published at its path plus .md for the copy and "open in
# AI" actions. It is the same content as the HTML, so it must not be indexed
# separately. robots.txt already asks crawlers not to fetch these; this is the
# instruction they cannot ignore, and the reason it is worth hosting here.
<FilesMatch "\.md$">
    Header set X-Robots-Tag "noindex, nofollow"
</FilesMatch>

# ── Caching ──────────────────────────────────────────────────────────────────
# Everything under /_astro/ carries a content hash in its name, so it can never
# go stale. HTML must always be revalidated or a deploy goes unnoticed.
<IfModule mod_headers.c>
    <FilesMatch "\.(html|xml|txt)$">
        Header set Cache-Control "public, max-age=0, must-revalidate"
    </FilesMatch>
</IfModule>

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType text/css "access plus 1 year"
    ExpiresByType application/javascript "access plus 1 year"
    ExpiresByType image/svg+xml "access plus 1 month"
    ExpiresByType font/woff2 "access plus 1 year"
</IfModule>

# ── Compression ──────────────────────────────────────────────────────────────
<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/css text/plain text/xml \
        application/javascript application/json image/svg+xml
</IfModule>
