website
(require website) | package: website |
#lang racket (require website) (define my-site (list (page index.html (html (body (h1 "Hello World")))))) (render my-site #:to "output")
Rendering my-site out to the output directory.
A "site" is just a list of page structures.
Note that the intended dev experience is that you run $ raco website-preview in your output directory, which launches a browser pointing to a locally running webserver. Then you just refresh the page whenever you rerender your site.
struct
(struct page (name content) #:extra-constructor-name make-page) name : (list-of string?) content : page-content?
project: |
index.html |
css/ |
custom.css |
js/ |
custom.js |
This project would be represented as a site with three pages:
(define project (list (page index.html ...) (page css/custom.css ...) (page js/custom.js ...)))
The actual files would be created later, with a call to render.
Note, although a page struct stores its path as a list of strings. You should make use of the fact that the page constructor is actually a macro that parses the first identifier into a list of strings based on the forward slashes. If you don’t want this behaviour, simply pass in a list directly or an id that does not contain slashes or dots.
This example uses all three:
(define my-css-path (list "css" "custom.css")) (define project (list (page (list "index.html") ...) (page my-css-path ...) (page js/custom.js ...)))
As for content, normally, you’ll use the html generating functions that are reprovided by website from scribble/html/html.
Basically, for (almost) every html tag, there is a constructor function with that name. And for (almost) every attribute, there is an identifier ending with a colon. For example:
(html (head (title "My Site")) (body (h1 "My Site") (img src: "path-to-some-image" alt: "alt text") (div style: (properties background-color: "red" color: "green") "I am a weird div tag from the 90s")))
Style attributes can make use of the properties helper which gives a special syntax for constructing css strings.
It is convenient if you want to link from one page to another without thinking about the target page’s path. If you decide to change the path later, the links will update accordingly.
Just use an old-fashioned a tag, though, if you want finer-grained control or if you don’t have the target page in scope.
value
element? : (or/c procedure? outputtable/c)
Or it can be a procedure that would return such a thing. This can be useful in cases like write-img, which will write out an image file at render time, and will return an img element? with the appropriate src: attribute.
value
attribute? : symbol?
(h1 id: "title" "HI")
Becomes:
<h1 id="title">HI</h1> |
value
site? : (listof page?)
Joining two sites together is as simple as using append.
procedure
(get-attribute attr: element) → any/c
attr: : symbol? element : element?
(get-attribute id: (div id: "id"))
Gives "id".
Fails if it doesn’t exist.
procedure
(has-attribute? attr: element) → boolean?
attr: : symbol? element : element?
procedure
(get-property prop: style) → string?
prop: : symbol? style : string?
(get-property color: (get-attribute style: (div style: (properties color: "red"))))
Gives you "red".
procedure
(de-url string-with-url) → string?
string-with-url : string?
syntax
(define/provide-extensible-element name base overrides ...)
(define/provide-extensible-element page-item li (class: "page-item" class-join))
1 Bootstrap
(require website/bootstrap) | package: website |
This provides features for building websites that use bootstrap’s visual vocabularly.
Here’s a (simplified) example from a version of the metacoders.org website (which is built on top of website/bootstrap).
It shows how to construct an index page and three content pages, each connected by links on a bootstrap navbar.
#lang racket (require website/bootstrap) (define index-path (list "index.html")) (define city-search-path (list "city-search.html")) (define learn-more-path (list "learn-more.html")) (define get-to-work-path (list "get-to-work.html")) (define my-nav (navbar #:brand "MetaCoders" (nav-link learn-more-path "Learn More") (nav-link city-search-path "Enroll Kids") (nav-link get-to-work-path "Get To Work"))) (define (normal-content . more) (content my-nav (container more))) (define index (page index-path (normal-content (h1 "Index")))) (define learn-more (page learn-more-path (normal-content (h1 "Learn More")))) (define city-search (page city-search-path (normal-content (h1 "City Search")))) (define get-to-work (page get-to-work-path (normal-content (h1 "Get To Work")))) (define my-site (append (list index learn-more city-search get-to-work) (bootstrap-files))) (render my-site #:to "out")
js/ |
jquery-3.2.1.slim.min.js |
bootstrap.bundle.min.js |
css/ |
bootstrap.min.css |
Note that it’s still up to you to actually include these files in the html pages of your site. For that, you would use include-bootstrap-js usually at the end of the (body ...) portion of a page, include-bootstrap-css usually in the (head ...) portion of a page, or use content to automatically do both.
Use this as the basic building block for any bootstrap-enabled page in your bootstrap-enabled site. (Don’t forget to append the (bootstrap-files) to your site before rendering)
(content (navbar #:brand "My Site" (nav-link "about.html" "About")))
2 Grids
Bootstraps grid system is what allows for responsive design. Constructors are provided for row and columns of various sizes – all of which correspond to Bootstrap classes in a straight-forward way.
procedure
(row #:element element content) → element?
element : div content : (or/c element? attribute?)
#lang racket (require website/bootstrap) (define (normal-content title . stuff) (content (container (h1 title) stuff))) (define my-site (append (bootstrap-files) (list (page index.html (normal-content "Column Demos" (row (col style: "background-color: red" "1") (col-6 style: "background-color: green" "2") (col style: "background-color: blue" "3")) (row (col style: "background-color: red" "1") (col-5 style: "background-color: green" "2") (col style: "background-color: blue" "3")) (row (col-6 class: "col-md-4" style: "background-color: red" "1") (col-6 class: "col-md-4" style: "background-color: green" "1") (col-6 class: "col-md-4" style: "background-color: blue" "1"))))))) (render my-site #:to "out")
procedure
element : div content : (or/c element? attribute?)
procedure
(col-1 #:element element content) → element?
element : div content : (or/c element? attribute?)
procedure
(col-2 #:element element content) → element?
element : div content : (or/c element? attribute?)
procedure
(col-3 #:element element content) → element?
element : div content : (or/c element? attribute?)
procedure
(col-4 #:element element content) → element?
element : div content : (or/c element? attribute?)
procedure
(col-5 #:element element content) → element?
element : div content : (or/c element? attribute?)
procedure
(col-6 #:element element content) → element?
element : div content : (or/c element? attribute?)
procedure
(col-7 #:element element content) → element?
element : div content : (or/c element? attribute?)
procedure
(col-8 #:element element content) → element?
element : div content : (or/c element? attribute?)
procedure
(col-9 #:element element content) → element?
element : div content : (or/c element? attribute?)
procedure
(col-10 #:element element content) → element?
element : div content : (or/c element? attribute?)
procedure
(col-11 #:element element content) → element?
element : div content : (or/c element? attribute?)
procedure
(col-12 #:element element content) → element?
element : div content : (or/c element? attribute?)
Also available (but I am too lazy to list them) are the variants with sm, md, lg, or xl.
Once such example:
procedure
(col-sm-4 #:element element content) → element?
element : div content : (or/c element? attribute?)
3 Tabs
procedure
(nav-tabs #:element element content) → element?
element : div content : (or/c element? attribute?)
procedure
(active-nav-item #:element element content) → element?
element : div content : (or/c element? attribute?)
procedure
(tab-content #:element element content) → element?
element : div content : (or/c element? attribute?)
procedure
(tab-pane #:element element content) → element?
element : div content : (or/c element? attribute?)
procedure
(active-tab-pane #:element element content) → element?
element : div content : (or/c element? attribute?)
procedure
(tab-nav-link #:element element content) → element?
element : div content : (or/c element? attribute?)
procedure
(active-tab-nav-link #:element element content) → element? element : div content : (or/c element? attribute?)
procedure
(tabify content ...) → element?
content : any/c
The hrefs (for nav-link items) and ids (for tab-pane items) must match, as would be the case if you were constructing your Bootstrap HTML by hand.
For example, here are four tabs with four panes.
(tabify (active-tab-nav-link href: "#s-g" "Story to Game") (tab-nav-link href: "#g-s" "Game to Story") (tab-nav-link href: "#g-g" "Game to Game") (tab-nav-link href: "#s-s" "Story to Story") (active-tab-pane id: "s-g" (h3 "Story to Game")) (tab-pane id: "g-s" (h3 "Game to Story")) (tab-pane id: "g-g" (h3 "Game to Game")) (tab-pane id: "s-s" (h3 "Story to Story")))
4 Cards
Bootstrap’s cards are a key aspect of Bootstrap’s visual language.
procedure
(card #:element element content) → element?
element : div content : (or/c element? attribute?)
Things that can be nested inside of it: card-img-top, card-body, card-title, card-subtitle, card-text, and card-link.
Use these as building blocks to make your own sorts of cards.
Examples:
(card (card-img-top) (card-body (card-title "I am a card") (card-subtitle "with a subtitle") (card-text "Lorem ipsum ....") (button-primary "Learn More")))
5 Buttons
There are a variety of constructors for common Bootstrap buttons.
Each is implemented as a psuedo element, meaning that although they return button values, you can still pass in content and attributes as you would with any html element constructors.
procedure
(button-primary #:element element content) → element?
element : button? content : (or/c element? attribute?)
(button-primary id: "main-button" "My Button")
procedure
(button-secondary #:element element content) → element? element : button? content : (or/c element? attribute?)
procedure
(button-success #:element element content) → element?
element : button? content : (or/c element? attribute?)
procedure
(button-danger #:element element content) → element?
element : button? content : (or/c element? attribute?)
procedure
(button-warning #:element element content) → element?
element : button? content : (or/c element? attribute?)
procedure
(button-info #:element element content) → element?
element : button? content : (or/c element? attribute?)
procedure
(button-light #:element element content) → element?
element : button? content : (or/c element? attribute?)
procedure
(button-dark #:element element content) → element?
element : button? content : (or/c element? attribute?)
procedure
(button-link #:element element content) → element?
element : button? content : (or/c element? attribute?)