commit 3942c6b8f01d300148b0c18bb73e531433878dfd Author: Nicholas McDaniel Date: Tue Feb 3 13:06:57 2026 -0500 Initial workspace and initial site representation diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..6e3c965 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +root = true + +[*] +indent_style = space +indent_size = 4 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..63b8e31 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Nicholas McDaniel + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/garden.rkt b/garden.rkt new file mode 100644 index 0000000..3edbc85 --- /dev/null +++ b/garden.rkt @@ -0,0 +1,13 @@ +#lang racket + +(define garden-blog + (blog-builder #:src (glob "./posts/*.scm") + #:markup-parsers (scheme-ml-reader) + #:page-template "./template/post.html")) + +(site #:output-directory "./out" + #:domain-root "https://tty.garden/" + #:builders (list + (blog-builder blog) + (rss-builder (blog->rss blog)) + (static-directory "static"))) diff --git a/nursery/info.rkt b/nursery/info.rkt new file mode 100644 index 0000000..03bfb22 --- /dev/null +++ b/nursery/info.rkt @@ -0,0 +1,9 @@ +#lang info + +(define collection "nursery") +(define version "0.1") + +(define pkg-authors '(nmcdaniel)) +(define license '(MIT)) + +(define deps '("base")) diff --git a/nursery/site-structs.rkt b/nursery/site-structs.rkt new file mode 100644 index 0000000..24e353b --- /dev/null +++ b/nursery/site-structs.rkt @@ -0,0 +1,23 @@ +#lang racket + +; Structure representing a nursery site +(struct site (host + port + prefix + scheme + output-dir + metadata + builders)) + +; Require a site prefix to start and end with a forward slash +(define (valid-prefix? prefix) + (and (string-prefix? prefix "/") (string-suffix? prefix "/"))) + +(provide/contract + (struct site ([host string?] + [port (or/c #f number?)] + [prefix (and/c string? valid-prefix?)] + [scheme string?] + [output-dir path-string?] + [metadata dict?] + [builders list?]))) diff --git a/nursery/site.rkt b/nursery/site.rkt new file mode 100644 index 0000000..84b4f9d --- /dev/null +++ b/nursery/site.rkt @@ -0,0 +1,51 @@ +#lang racket + +(require net/url + "site-structs.rkt") + +; Construct a new site object +(define (make-site #:host [host "example.com"] + #:port [port #f] + #:prefix [prefix "/"] + #:scheme [scheme "https"] + #:output-dir [output-dir "out"] + #:metadata [metadata '()] + #:builders [builders '()]) + ; TODO: Normalize prefix to automatically pass valid-prefix? contract + (site host port prefix scheme output-dir metadata builders)) + +; Produce a URL relative to the site prefix, optionally absolute +; +; Providing a path starting with "/" will bypass the prefix. +(define (site-url site [path ""] [absolute #f]) + ; Base URL including scheme, host, and port if absolute + (define base-url + (url (and absolute (site-scheme site)) #f + (and absolute (site-host site)) + (and absolute (site-port site)) + #f '() '() #f)) + ; Apply path segments to base URL + (for/fold ([acc base-url]) + ([rel (list (site-prefix site) path)]) + (combine-url/relative acc rel))) + +(define (site-url-string site [path ""] [absolute #f]) + (url->string (site-url site path absolute))) + +; Run site builders to populate the build directory +; TODO: Have builders output path and file contents as dictionary for ability +; to dry-run, and improve logging. Perhaps the builder output could be a dictionary +; of file path to lambda that would produce the file contents, for the ability to build +; specific files, and figure out which file exactly causes an error. +(define (site-build site) + (for ([builder (site-builders site)]) + (builder site))) + +(provide (all-from-out "site-structs.rkt")) +(provide/contract + (site-url (-> site? (or/c #f path-string?) boolean? url?)) + (site-url-string (-> site? (or/c #f path-string?) boolean? string?)) + (site-build (-> site? any/c))) + +; Contracts are provided by underlying structure during construction +(provide make-site)