pull/9/head
Matthew Butterick 10 years ago
parent 04e7a63583
commit 1e523376c9

@ -30,9 +30,9 @@ clone copies rendered files to desktop
#| #|
[("render") `(begin [("render") `(begin
;; todo: take extensions off the comand line ;; todo: take extensions off the comand line
(displayln "Render preproc & pagemap files ...") (displayln "Render preproc & pagetree files ...")
(require "render.rkt" "file-tools.rkt" "world.rkt") (require "render.rkt" "file-tools.rkt" "world.rkt")
(apply render-batch (append-map project-files-with-ext (list world:preproc-source-ext world:pagemap-source-ext))))] (apply render-batch (append-map project-files-with-ext (list world:preproc-source-ext world:pagetree-source-ext))))]
[("clone") (let ([target-path [("clone") (let ([target-path
(if (> (len args) 1) (if (> (len args) 1)
(->path (get args 1)) (->path (get args 1))
@ -47,7 +47,7 @@ clone copies rendered files to desktop
markup-source? markup-source?
preproc-source? preproc-source?
template-source? template-source?
pagemap-source? pagetree-source?
pollen-script? pollen-script?
magic-directory? magic-directory?
racket-file?))) racket-file?)))

@ -21,7 +21,7 @@
;; helper function for pagemap ;; helper function for pagetree
;; make paths absolute to test whether files exist, ;; make paths absolute to test whether files exist,
;; then convert back to relative ;; then convert back to relative
(define+provide/contract (visible? path) (define+provide/contract (visible? path)
@ -87,7 +87,7 @@
(make-source-utility-functions preproc) (make-source-utility-functions preproc)
(make-source-utility-functions null) (make-source-utility-functions null)
(make-source-utility-functions pagemap) (make-source-utility-functions pagetree)
(make-source-utility-functions markup) (make-source-utility-functions markup)
(make-source-utility-functions template) (make-source-utility-functions template)
(make-source-utility-functions scribble) (make-source-utility-functions scribble)

@ -30,7 +30,7 @@
(let* ([file-ext-pattern (pregexp "\\w+$")] (let* ([file-ext-pattern (pregexp "\\w+$")]
[here-ext (string->symbol (car (regexp-match file-ext-pattern here-path)))]) [here-ext (string->symbol (car (regexp-match file-ext-pattern here-path)))])
(cond (cond
[(equal? here-ext world:pagemap-source-ext) world:reader-mode-pagemap] [(equal? here-ext world:pagetree-source-ext) world:reader-mode-pagetree]
[(equal? here-ext world:markup-source-ext) world:reader-mode-markup] [(equal? here-ext world:markup-source-ext) world:reader-mode-markup]
[(equal? here-ext world:markdown-source-ext) world:reader-mode-markdown] [(equal? here-ext world:markdown-source-ext) world:reader-mode-markdown]
[else world:reader-mode-preproc])) [else world:reader-mode-preproc]))
@ -63,7 +63,7 @@
;; set up the 'doc export ;; set up the 'doc export
(require pollen/decode) (require pollen/decode)
(define doc (apply (cond (define doc (apply (cond
[(equal? parser-mode world:reader-mode-pagemap) (λ xs ((dynamic-require 'pollen/pagemap 'decode-pagemap) xs))] [(equal? parser-mode world:reader-mode-pagetree) (λ xs ((dynamic-require 'pollen/pagetree 'decode-pagetree) xs))]
;; 'root is the hook for the decoder function. ;; 'root is the hook for the decoder function.
;; If it's not a defined identifier, it just hits #%top and becomes `(root ,@body ...) ;; If it's not a defined identifier, it just hits #%top and becomes `(root ,@body ...)
[(or (equal? parser-mode world:reader-mode-markup) [(or (equal? parser-mode world:reader-mode-markup)

@ -1,121 +0,0 @@
#lang racket/base
(require racket/path)
(require "tools.rkt" "world.rkt" "decode.rkt" sugar txexpr "cache.rkt")
(define+provide current-pagemap (make-parameter #f))
(define+provide (node? x)
(->boolean (and (symbol? x) (try (not (whitespace/nbsp? (->string x)))
(except [exn:fail? (λ(e) #f)])))))
(define+provide (nodeish? x)
(try (node? (->symbol x))
(except [exn:fail? (λ(e) #f)])))
(define/contract+provide (->node x)
(nodeish? . -> . node?)
(->symbol x))
(define+provide/contract (decode-pagemap xs)
(txexpr-elements? . -> . any/c) ; because pagemap is being explicitly validated
(validate-pagemap
(decode (cons world:pagemap-root-node xs)
#:txexpr-elements-proc (λ(xs) (filter (compose1 not whitespace?) xs))
#:string-proc string->symbol))) ; because faster than ->node
(define+provide (validate-pagemap x)
(let ([nodes (pagemap->list x)])
(and
(andmap (λ(p) (or (node? p) (error (format "validate-pagemap: \"~a\" is not a valid node" p)))) nodes)
(try (members-unique?/error nodes)
(except [exn:fail? (λ(e) (error (format "validate-pagemap: ~a" (exn-message e))))]))
x)))
(define+provide (pagemap? x)
(try (->boolean (validate-pagemap x))
(except [exn:fail? (λ(e) #f)])))
;; Try loading from pagemap file, or failing that, synthesize pagemap.
(define+provide/contract (make-project-pagemap project-dir)
(pathish? . -> . pagemap?)
(define pagemap-source (build-path project-dir world:default-pagemap))
(cached-require pagemap-source world:main-pollen-export))
(define+provide/contract (parent-node p [pagemap (current-pagemap)])
(((or/c #f nodeish?)) (pagemap?) . ->* . (or/c #f node?))
(and pagemap p
(let ([node (->node p)])
(if (member node (map (λ(x) (if (list? x) (car x) x)) (cdr pagemap)))
(car pagemap)
(ormap (λ(x) (parent-node node x)) (filter list? pagemap))))))
(define+provide/contract (child-nodes p [pagemap (current-pagemap)])
(((or/c #f nodeish?)) (pagemap?) . ->* . (or/c #f (listof node?)))
(and pagemap p
(let ([node (->node p)])
(if (equal? node (car pagemap))
(map (λ(x) (if (list? x) (car x) x)) (cdr pagemap))
(ormap (λ(x) (child-nodes node x)) (filter list? pagemap))))))
(define+provide/contract (sibling-nodes p [pagemap (current-pagemap)])
(((or/c #f nodeish?)) (pagemap?) . ->* . (or/c #f (listof node?)))
(child-nodes (parent-node p pagemap) pagemap))
;; flatten tree to sequence
(define+provide/contract (pagemap->list pagemap)
(pagemap? . -> . (listof node?))
; use cdr to get rid of root tag at front
(cdr (flatten pagemap)))
(define (adjacent-nodes side p [pagemap (current-pagemap)])
; ((symbol? (or/c #f nodeish?)) (pagemap?) . ->* . (or/c #f (listof node?)))
(and pagemap p
(let* ([node (->node p)]
[proc (if (equal? side 'left) takef takef-right)]
[result (proc (pagemap->list pagemap) (λ(x) (not (equal? node x))))])
(and (not (empty? result)) result))))
(define+provide/contract (previous-nodes node [pagemap (current-pagemap)])
(((or/c #f nodeish?)) (pagemap?) . ->* . (or/c #f (listof node?)))
(adjacent-nodes 'left node pagemap))
(define+provide/contract (next-nodes node [pagemap (current-pagemap)])
(((or/c #f nodeish?)) (pagemap?) . ->* . (or/c #f (listof node?)))
(adjacent-nodes 'right node pagemap))
(define+provide/contract (previous-node node [pagemap (current-pagemap)])
(((or/c #f nodeish?)) (pagemap?) . ->* . (or/c #f node?))
(let ([result (previous-nodes node pagemap)])
(and result (last result))))
(define+provide/contract (next-node node [pagemap (current-pagemap)])
(((or/c #f nodeish?)) (pagemap?) . ->* . (or/c #f node?))
(let ([result (next-nodes node pagemap)])
(and result (first result))))
(define/contract+provide (path->node path)
(coerce/path? . -> . coerce/symbol?)
(->output-path (find-relative-path (world:current-project-root) (->complete-path path))))
(define+provide/contract (node-in-pagemap? node [pagemap (current-pagemap)])
(((or/c #f nodeish?)) (pagemap?) . ->* . boolean?)
(->boolean (and node (member node (pagemap->list pagemap)))))

@ -0,0 +1,121 @@
#lang racket/base
(require racket/path)
(require "tools.rkt" "world.rkt" "decode.rkt" sugar txexpr "cache.rkt")
(define+provide current-pagetree (make-parameter #f))
(define+provide (pagenode? x)
(->boolean (and (symbol? x) (try (not (whitespace/nbsp? (->string x)))
(except [exn:fail? (λ(e) #f)])))))
(define+provide (pagenodeish? x)
(try (pagenode? (->symbol x))
(except [exn:fail? (λ(e) #f)])))
(define/contract+provide (->pagenode x)
(pagenodeish? . -> . pagenode?)
(->symbol x))
(define+provide/contract (decode-pagetree xs)
(txexpr-elements? . -> . any/c) ; because pagetree is being explicitly validated
(validate-pagetree
(decode (cons world:pagetree-root-node xs)
#:txexpr-elements-proc (λ(xs) (filter (compose1 not whitespace?) xs))
#:string-proc string->symbol))) ; because faster than ->pagenode
(define+provide (validate-pagetree x)
(let ([pagenodes (pagetree->list x)])
(and
(andmap (λ(p) (or (pagenode? p) (error (format "validate-pagetree: \"~a\" is not a valid pagenode" p)))) pagenodes)
(try (members-unique?/error pagenodes)
(except [exn:fail? (λ(e) (error (format "validate-pagetree: ~a" (exn-message e))))]))
x)))
(define+provide (pagetree? x)
(try (->boolean (validate-pagetree x))
(except [exn:fail? (λ(e) #f)])))
;; Try loading from pagetree file, or failing that, synthesize pagetree.
(define+provide/contract (make-project-pagetree project-dir)
(pathish? . -> . pagetree?)
(define pagetree-source (build-path project-dir world:default-pagetree))
(cached-require pagetree-source world:main-pollen-export))
(define+provide/contract (parent pnish [pt (current-pagetree)])
(((or/c #f pagenodeish?)) (pagetree?) . ->* . (or/c #f pagenode?))
(and pt pnish
(let ([pagenode (->pagenode pnish)])
(if (member pagenode (map (λ(x) (if (list? x) (car x) x)) (cdr pt)))
(car pt)
(ormap (λ(x) (parent pagenode x)) (filter list? pt))))))
(define+provide/contract (children p [pt (current-pagetree)])
(((or/c #f pagenodeish?)) (pagetree?) . ->* . (or/c #f (listof pagenode?)))
(and pt p
(let ([pagenode (->pagenode p)])
(if (equal? pagenode (car pt))
(map (λ(x) (if (list? x) (car x) x)) (cdr pt))
(ormap (λ(x) (children pagenode x)) (filter list? pt))))))
(define+provide/contract (siblings pnish [pt (current-pagetree)])
(((or/c #f pagenodeish?)) (pagetree?) . ->* . (or/c #f (listof pagenode?)))
(children (parent pnish pt) pt))
;; flatten tree to sequence
(define+provide/contract (pagetree->list pt)
(pagetree? . -> . (listof pagenode?))
; use cdr to get rid of root tag at front
(cdr (flatten pt)))
(define (adjacents side pnish [pt (current-pagetree)])
; ((symbol? (or/c #f pagenodeish?)) (pagetree?) . ->* . (or/c #f (listof pagenode?)))
(and pt pnish
(let* ([pagenode (->pagenode pnish)]
[proc (if (equal? side 'left) takef takef-right)]
[result (proc (pagetree->list pt) (λ(x) (not (equal? pagenode x))))])
(and (not (empty? result)) result))))
(define+provide/contract (previous* pnish [pt (current-pagetree)])
(((or/c #f pagenodeish?)) (pagetree?) . ->* . (or/c #f (listof pagenode?)))
(adjacents 'left pnish pt))
(define+provide/contract (next* pnish [pt (current-pagetree)])
(((or/c #f pagenodeish?)) (pagetree?) . ->* . (or/c #f (listof pagenode?)))
(adjacents 'right pnish pt))
(define+provide/contract (previous pnish [pt (current-pagetree)])
(((or/c #f pagenodeish?)) (pagetree?) . ->* . (or/c #f pagenode?))
(let ([result (previous* pnish pt)])
(and result (last result))))
(define+provide/contract (next pnish [pt (current-pagetree)])
(((or/c #f pagenodeish?)) (pagetree?) . ->* . (or/c #f pagenode?))
(let ([result (next* pnish pt)])
(and result (first result))))
(define/contract+provide (path->pagenode path)
(coerce/path? . -> . coerce/symbol?)
(->output-path (find-relative-path (world:current-project-root) (->complete-path path))))
(define+provide/contract (in-pagetree? pnish [pt (current-pagetree)])
(((or/c #f pagenodeish?)) (pagetree?) . ->* . boolean?)
(->boolean (and pnish (member pnish (pagetree->list pt)))))

@ -1,4 +1,4 @@
#lang racket/base #lang racket/base
(require pollen/lang/reader-base) (require pollen/lang/reader-base)
(make-reader-with-mode world:reader-mode-pagemap) (make-reader-with-mode world:reader-mode-pagetree)

@ -1,6 +1,6 @@
#lang racket/base #lang racket/base
(require racket/file racket/rerequire racket/path racket/match) (require racket/file racket/rerequire racket/path racket/match)
(require sugar "file.rkt" "cache.rkt" "world.rkt" "debug.rkt" "pagemap.rkt" "project-requires.rkt") (require sugar "file.rkt" "cache.rkt" "world.rkt" "debug.rkt" "pagetree.rkt" "project-requires.rkt")
;; when you want to generate everything fresh, ;; when you want to generate everything fresh,
@ -49,12 +49,12 @@
(for-each render-to-file-if-needed xs)) (for-each render-to-file-if-needed xs))
(define/contract+provide (render-pagemap pagemap-or-path) (define/contract+provide (render-pagetree pagetree-or-path)
((or/c pagemap? pathish?) . -> . void?) ((or/c pagetree? pathish?) . -> . void?)
(define pagemap (if (pagemap? pagemap-or-path) (define pagetree (if (pagetree? pagetree-or-path)
pagemap-or-path pagetree-or-path
(cached-require pagemap-or-path world:main-pollen-export))) (cached-require pagetree-or-path world:main-pollen-export)))
(apply render-batch (pagemap->list pagemap))) (apply render-batch (pagetree->list pagetree)))
(define/contract+provide (render-for-dev-server so-pathish #:force [force #f]) (define/contract+provide (render-for-dev-server so-pathish #:force [force #f])
@ -64,7 +64,7 @@
[(ormap (λ(test) (test so-path)) (list has/is-null-source? has/is-preproc-source? has/is-markup-source? has/is-scribble-source?)) [(ormap (λ(test) (test so-path)) (list has/is-null-source? has/is-preproc-source? has/is-markup-source? has/is-scribble-source?))
(let-values ([(source-path output-path) (->source+output-paths so-path)]) (let-values ([(source-path output-path) (->source+output-paths so-path)])
(render-to-file-if-needed source-path output-path #:force force))] (render-to-file-if-needed source-path output-path #:force force))]
[(pagemap-source? so-path) (render-pagemap so-path)])) [(pagetree-source? so-path) (render-pagetree so-path)]))
(void)) (void))
@ -163,7 +163,7 @@
,(require-project-require-files source-path) ,(require-project-require-files source-path)
(let ([doc (cached-require ,source-path ',world:main-pollen-export)] (let ([doc (cached-require ,source-path ',world:main-pollen-export)]
[metas (cached-require ,source-path ',world:meta-pollen-export)]) [metas (cached-require ,source-path ',world:meta-pollen-export)])
(local-require pollen/pagemap pollen/template pollen/top) (local-require pollen/pagetree pollen/template pollen/top)
(define here (metas->here metas)) (define here (metas->here metas))
(include-template #:command-char ,world:template-field-delimiter ,(->string (find-relative-path source-dir template-path)))))) (include-template #:command-char ,world:template-field-delimiter ,(->string (find-relative-path source-dir template-path))))))
@ -224,7 +224,7 @@
pollen/decode pollen/decode
pollen/file pollen/file
pollen/main pollen/main
pollen/pagemap pollen/pagetree
pollen/cache pollen/cache
sugar sugar
txexpr txexpr
@ -244,7 +244,7 @@
(list? . -> . bytes?) (list? . -> . bytes?)
(parameterize ([current-namespace (make-base-namespace)] (parameterize ([current-namespace (make-base-namespace)]
[current-output-port (current-error-port)] [current-output-port (current-error-port)]
[current-pagemap (make-project-pagemap (world:current-project-root))]) [current-pagetree (make-project-pagetree (world:current-project-root))])
(for-each (λ(mod-name) (namespace-attach-module cache-ns mod-name)) (for-each (λ(mod-name) (namespace-attach-module cache-ns mod-name))
`(web-server/templates `(web-server/templates
xml xml
@ -257,7 +257,7 @@
pollen/debug pollen/debug
pollen/decode pollen/decode
pollen/file pollen/file
pollen/pagemap pollen/pagetree
pollen/cache pollen/cache
sugar sugar
txexpr txexpr

@ -7,5 +7,6 @@
@include-section["cache.scrbl"] @include-section["cache.scrbl"]
@include-section["decode.scrbl"] @include-section["decode.scrbl"]
@include-section["file.scrbl"] @include-section["file.scrbl"]
@include-section["pagemap.scrbl"] @include-section["pagetree.scrbl"]
@include-section["render.scrbl"] @include-section["render.scrbl"]
@include-section["template.scrbl"]

@ -1,213 +0,0 @@
#lang scribble/manual
@(require scribble/eval pollen/cache pollen/world (for-label racket (except-in pollen #%module-begin) pollen/world pollen/pagemap txexpr pollen/decode pollen/file))
@(define my-eval (make-base-eval))
@(my-eval `(require pollen pollen/pagemap txexpr))
@title{Pagemaps}
@defmodule[pollen/pagemap]
A @italic{pagemap} is a hierarchical list of Pollen output files. A pagemap source file has the extension @code[(format ".~a" world:pagemap-source-ext)]. A pagemap provides a convenient way of separating the structure of the pages from the page sources, and navigating around this structure.
Pagemaps are made of @italic{nodes}. Usually these nodes will be names of output files in your project. (If you think it would've been more logical to call them ``pages,'' perhaps. When I think of a web page, I think of a file on a disk. Whereas nodes may — and often do — refer to files that don't yet exist.)
Books and other long documents are usually organized in a structured way — at minimum they have a sequence of pages, but more often they have sections with subsequences within. Individual Pollen source files don't know anything about how they're connected to other files. In theory, you could maintain this information within each source file. This would be a poor use of human energy. Let the pagemap figure it out.
@defproc[
(pagemap?
[possible-pagemap any/c])
boolean?]
Test whether @racket[_possible-pagemap] is a valid pagemap. It must be a @racket[txexpr?] where all elements are @racket[node?] and unique within @racket[_possible-pagemap] (not counting the root node).
@examples[#:eval my-eval
(pagemap? '(root index.html))
(pagemap? '(root index.html index.html))
(pagemap? '(root index.html "index.html"))
(define nested-pmap '(root 1.html 2.html (3.html 3a.html 3b.html)))
(pagemap? nested-pmap)
(pagemap? `(root index.html ,nested-pmap (subsection.html more.html)))
(pagemap? `(root index.html ,nested-pmap (subsection.html ,nested-pmap)))
]
@defproc[
(validate-pagemap
[possible-pagemap any/c])
pagemap?]
Like @racket[pagemap?], but raises a descriptive error if @racket[_possible-pagemap] is invalid, and otherwise returns @racket[_possible-pagemap] itself.
@examples[#:eval my-eval
(validate-pagemap '(root (mama.html son.html daughter.html) uncle.html))
(validate-pagemap `(root (,+ son.html daughter.html) uncle.html))
(validate-pagemap '(root (mama.html son.html son.html) mama.html))
]
@defproc[
(node?
[possible-node any/c])
boolean?]
Test whether @racket[_possible-node] is a valid node (short for ``pagemap node''). A node can be any @racket[symbol?] that is not @racket[whitespace/nbsp?] Every leaf of a pagemap is a node. In practice, your nodes will likely be names of output files.
@margin-note{Nodes are symbols (rather than strings) so that pagemaps will be valid tagged X-expressions, which is a more convenient format for validation & processing.}
@examples[#:eval my-eval
(map node? '(symbol index.html | silly |))
(map node? '(9.999 "index.html" (p "Hello") | |))
]
@defproc[
(nodeish?
[v any/c])
boolean?]
Return @racket[#t] if @racket[_v] can be converted with @racket[->node].
@examples[#:eval my-eval
(map nodeish? '(9.999 "index.html" | |))
]
@defproc[
(->node
[v nodeish?])
node?]
Convert @racket[_v] to a node.
@examples[#:eval my-eval
(map nodeish? '(symbol 9.999 "index.html" | silly |))
(map ->node '(symbol 9.999 "index.html" | silly |))
]
@section{Navigation}
@defparam[current-pagemap pagemap pagemap?
#:value #f]{
A parameter that defines the default pagemap used by pagemap navigation functions (e.g., @racket[parent-node], @racket[chidren], et al.) if another is not explicitly specified. Initialized to @racket[#f].}
@defproc[
(parent-node
[p (or/c #f nodeish?)]
[pagemap pagemap? (current-pagemap)])
(or/c #f node?)]
Find the parent-node node of @racket[_p] within @racket[_pagemap]. Return @racket[#f] if there isn't one.
@examples[#:eval my-eval
(current-pagemap '(root (mama.html son.html daughter.html) uncle.html))
(parent-node 'son.html)
(parent-node "mama.html")
(parent-node (parent-node 'son.html))
(parent-node (parent-node (parent-node 'son.html)))
]
@defproc[
(child-nodes
[p (or/c #f nodeish?)]
[pagemap pagemap? (current-pagemap)])
(or/c #f node?)]
Find the child nodes of @racket[_p] within @racket[_pagemap]. Return @racket[#f] if there aren't any.
@examples[#:eval my-eval
(current-pagemap '(root (mama.html son.html daughter.html) uncle.html))
(child-nodes 'mama.html)
(child-nodes 'uncle.html)
(child-nodes 'root)
(map child-nodes (child-nodes 'root))
]
@defproc[
(sibling-nodes
[p (or/c #f nodeish?)]
[pagemap pagemap? (current-pagemap)])
(or/c #f node?)]
Find the sibling nodes of @racket[_p] within @racket[_pagemap]. The list will include @racket[_p] itself. But the function will still return @racket[#f] if @racket[_pagemap] is @racket[#f].
@examples[#:eval my-eval
(current-pagemap '(root (mama.html son.html daughter.html) uncle.html))
(sibling-nodes 'son.html)
(sibling-nodes 'daughter.html)
(sibling-nodes 'mama.html)
]
@deftogether[(
@defproc[
(previous-node
[p (or/c #f nodeish?)]
[pagemap pagemap? (current-pagemap)])
(or/c #f node?)]
@defproc[
(previous-nodes
[p (or/c #f nodeish?)]
[pagemap pagemap? (current-pagemap)])
(or/c #f (listof node?))]
)]
Return the node immediately before @racket[_p]. For @racket[previous-nodes], return all the nodes before @racket[_p], in sequence. In both cases, return @racket[#f] if there aren't any nodes. The root node is ignored.
@examples[#:eval my-eval
(current-pagemap '(root (mama.html son.html daughter.html) uncle.html))
(previous-node 'daughter.html)
(previous-node 'son.html)
(previous-node (previous-node 'daughter.html))
(previous-node 'mama.html)
(previous-nodes 'daughter.html)
(previous-nodes 'uncle.html)
]
@deftogether[(
@defproc[
(next-node
[p (or/c #f nodeish?)]
[pagemap pagemap? (current-pagemap)])
(or/c #f node?)]
@defproc[
(next-nodes
[p (or/c #f nodeish?)]
[pagemap pagemap? (current-pagemap)])
(or/c #f (listof node?))]
)]
Return the node immediately after @racket[_p]. For @racket[next-nodes], return all the nodes after @racket[_p], in sequence. In both cases, return @racket[#f] if there aren't any nodes. The root node is ignored.
@examples[#:eval my-eval
(current-pagemap '(root (mama.html son.html daughter.html) uncle.html))
(next-node 'son.html)
(next-node 'daughter.html)
(next-node (next-node 'son.html))
(next-node 'uncle.html)
(next-nodes 'mama.html)
(next-nodes 'daughter.html)
]
@section{Utilities}
@defproc[
(pagemap->list
[pagemap pagemap?])
list?
]
Convert @racket[_pagemap] to a simple list, preserving order.
@defproc[
(node-in-pagemap?
[node node?]
[pagemap pagemap? (current-pagemap)])
boolean?
]
Report whether @racket[_node] is in @racket[_pagemap].
@defproc[
(path->node
[p pathish?])
node?
]
Convert path @racket[_p] to a node — meaning, make it relative to @racket[world:current-project-root], run it through @racket[->output-path], and convert it to a symbol. Does not tell you whether the resultant node actually exists in the current pagemap (for that, use @racket[node-in-pagemap?]).

@ -0,0 +1,213 @@
#lang scribble/manual
@(require scribble/eval pollen/cache pollen/world (for-label racket (except-in pollen #%module-begin) pollen/world pollen/pagetree txexpr pollen/decode pollen/file))
@(define my-eval (make-base-eval))
@(my-eval `(require pollen pollen/pagetree txexpr))
@title{Pagetrees}
@defmodule[pollen/pagetree]
A @italic{pagetree} is a hierarchical list of Pollen output files. A pagetree source file has the extension @code[(format ".~a" world:pagetree-source-ext)]. A pagetree provides a convenient way of separating the structure of the pages from the page sources, and navigating around this structure.
Pagetrees are made of @italic{pagenodes}. Usually these pagenodes will be names of output files in your project. (If you think it would've been more logical to just call them ``pages,'' perhaps. When I think of a web page, I think of a file on a disk. Whereas pagenodes may — and often do — refer to files that don't yet exist.)
Books and other long documents are usually organized in a structured way — at minimum they have a sequence of pages, but more often they have sections with subsequences within. Individual Pollen source files don't know anything about how they're connected to other files. In theory, you could maintain this information within each source file. This would be a poor use of human energy. Let the pagetree figure it out.
@defproc[
(pagetree?
[possible-pagetree any/c])
boolean?]
Test whether @racket[_possible-pagetree] is a valid pagetree. It must be a @racket[txexpr?] where all elements are @racket[pagenode?] and unique within @racket[_possible-pagetree] (not counting the root node).
@examples[#:eval my-eval
(pagetree? '(root index.html))
(pagetree? '(root index.html index.html))
(pagetree? '(root index.html "index.html"))
(define nested-ptree '(root 1.html 2.html (3.html 3a.html 3b.html)))
(pagetree? nested-ptree)
(pagetree? `(root index.html ,nested-ptree (subsection.html more.html)))
(pagetree? `(root index.html ,nested-ptree (subsection.html ,nested-ptree)))
]
@defproc[
(validate-pagetree
[possible-pagetree any/c])
pagetree?]
Like @racket[pagetree?], but raises a descriptive error if @racket[_possible-pagetree] is invalid, and otherwise returns @racket[_possible-pagetree] itself.
@examples[#:eval my-eval
(validate-pagetree '(root (mama.html son.html daughter.html) uncle.html))
(validate-pagetree `(root (,+ son.html daughter.html) uncle.html))
(validate-pagetree '(root (mama.html son.html son.html) mama.html))
]
@defproc[
(pagenode?
[possible-pagenode any/c])
boolean?]
Test whether @racket[_possible-pagenode] is a valid pagenode. A pagenode can be any @racket[symbol?] that is not @racket[whitespace/nbsp?] Every leaf of a pagetree is a pagenode. In practice, your pagenodes will likely be names of output files.
@margin-note{Pagenodes are symbols (rather than strings) so that pagetrees will be valid tagged X-expressions, which is a more convenient format for validation & processing.}
@examples[#:eval my-eval
(map pagenode? '(symbol index.html | silly |))
(map pagenode? '(9.999 "index.html" (p "Hello") | |))
]
@defproc[
(pagenodeish?
[v any/c])
boolean?]
Return @racket[#t] if @racket[_v] can be converted with @racket[->pagenode].
@examples[#:eval my-eval
(map pagenodeish? '(9.999 "index.html" | |))
]
@defproc[
(->pagenode
[v pagenodeish?])
pagenode?]
Convert @racket[_v] to a pagenode.
@examples[#:eval my-eval
(map pagenodeish? '(symbol 9.999 "index.html" | silly |))
(map ->pagenode '(symbol 9.999 "index.html" | silly |))
]
@section{Navigation}
@defparam[current-pagetree pagetree pagetree?
#:value #f]{
A parameter that defines the default pagetree used by pagetree navigation functions (e.g., @racket[parent-pagenode], @racket[chidren], et al.) if another is not explicitly specified. Initialized to @racket[#f].}
@defproc[
(parent
[p (or/c #f pagenodeish?)]
[pagetree pagetree? (current-pagetree)])
(or/c #f pagenode?)]
Find the parent pagenode of @racket[_p] within @racket[_pagetree]. Return @racket[#f] if there isn't one.
@examples[#:eval my-eval
(current-pagetree '(root (mama.html son.html daughter.html) uncle.html))
(parent 'son.html)
(parent "mama.html")
(parent (parent 'son.html))
(parent (parent (parent 'son.html)))
]
@defproc[
(children
[p (or/c #f pagenodeish?)]
[pagetree pagetree? (current-pagetree)])
(or/c #f pagenode?)]
Find the child pagenodes of @racket[_p] within @racket[_pagetree]. Return @racket[#f] if there aren't any.
@examples[#:eval my-eval
(current-pagetree '(root (mama.html son.html daughter.html) uncle.html))
(children 'mama.html)
(children 'uncle.html)
(children 'root)
(map children (children 'root))
]
@defproc[
(siblings
[p (or/c #f pagenodeish?)]
[pagetree pagetree? (current-pagetree)])
(or/c #f pagenode?)]
Find the sibling pagenodes of @racket[_p] within @racket[_pagetree]. The list will include @racket[_p] itself. But the function will still return @racket[#f] if @racket[_pagetree] is @racket[#f].
@examples[#:eval my-eval
(current-pagetree '(root (mama.html son.html daughter.html) uncle.html))
(siblings 'son.html)
(siblings 'daughter.html)
(siblings 'mama.html)
]
@deftogether[(
@defproc[
(previous
[p (or/c #f pagenodeish?)]
[pagetree pagetree? (current-pagetree)])
(or/c #f pagenode?)]
@defproc[
(previous*
[p (or/c #f pagenodeish?)]
[pagetree pagetree? (current-pagetree)])
(or/c #f (listof pagenode?))]
)]
Return the pagenode immediately before @racket[_p]. For @racket[previous*], return all the pagenodes before @racket[_p], in sequence. In both cases, return @racket[#f] if there aren't any pagenodes. The root pagenode is ignored.
@examples[#:eval my-eval
(current-pagetree '(root (mama.html son.html daughter.html) uncle.html))
(previous 'daughter.html)
(previous 'son.html)
(previous (previous 'daughter.html))
(previous 'mama.html)
(previous* 'daughter.html)
(previous* 'uncle.html)
]
@deftogether[(
@defproc[
(next
[p (or/c #f pagenodeish?)]
[pagetree pagetree? (current-pagetree)])
(or/c #f pagenode?)]
@defproc[
(next*
[p (or/c #f pagenodeish?)]
[pagetree pagetree? (current-pagetree)])
(or/c #f (listof pagenode?))]
)]
Return the pagenode immediately after @racket[_p]. For @racket[next*], return all the pagenodes after @racket[_p], in sequence. In both cases, return @racket[#f] if there aren't any pagenodes. The root pagenode is ignored.
@examples[#:eval my-eval
(current-pagetree '(root (mama.html son.html daughter.html) uncle.html))
(next 'son.html)
(next 'daughter.html)
(next (next 'son.html))
(next 'uncle.html)
(next* 'mama.html)
(next* 'daughter.html)
]
@section{Utilities}
@defproc[
(pagetree->list
[pagetree pagetree?])
list?
]
Convert @racket[_pagetree] to a simple list, preserving order.
@defproc[
(in-pagetree?
[pagenode pagenode?]
[pagetree pagetree? (current-pagetree)])
boolean?
]
Report whether @racket[_pagenode] is in @racket[_pagetree].
@defproc[
(path->pagenode
[p pathish?])
pagenode?
]
Convert path @racket[_p] to a pagenode — meaning, make it relative to @racket[world:current-project-root], run it through @racket[->output-path], and convert it to a symbol. Does not tell you whether the resultant pagenode actually exists in the current pagetree (for that, use @racket[pagenode-in-pagetree?]).

@ -6,7 +6,9 @@
@(my-eval `(require pollen)) @(my-eval `(require pollen))
@title{Pollen: the book is a program} @title[#:style 'toc]{Pollen: the book is a program}
@author[(author+email "Matthew Butterick" "mb@mbtype.com")] @author[(author+email "Matthew Butterick" "mb@mbtype.com")]
@ -22,6 +24,9 @@ That language is Racket. I chose Racket because while the idea for Pollen had be
Or, if you can find a better digital book-publishing tool, use that. Personally, I'm never going back to the way I used to work. Or, if you can find a better digital book-publishing tool, use that. Personally, I'm never going back to the way I used to work.
@local-table-of-contents[]
@section{Installation} @section{Installation}
Install Racket, which includes DrRacket. Install Racket, which includes DrRacket.

@ -66,9 +66,9 @@ Render multiple @racket[_source-paths] in one go. This can be faster than @racke
@defproc*[ @defproc*[
( (
[(render-pagemap [pagemap pagemap?]) void?] [(render-pagetree [pagetree pagetree?]) void?]
[(render-pagemap [pagemap-source pathish?]) void?])] [(render-pagetree [pagetree-source pathish?]) void?])]
Using @racket[_pagemap], or a pagemap loaded from @racket[_pagemap-source], render the files included in that pagemap using @racket[render-batch]. Using @racket[_pagetree], or a pagetree loaded from @racket[_pagetree-source], render the files included in that pagetree using @racket[render-batch].
@defproc[ @defproc[
(get-template-for (get-template-for

@ -1,6 +1,6 @@
#lang scribble/manual #lang scribble/manual
@(require scribble/eval pollen/cache pollen/world (for-label racket (except-in pollen #%module-begin) pollen/template pollen/render xml)) @(require scribble/eval pollen/cache pollen/world (for-label racket (except-in pollen #%module-begin) pollen/template pollen/render xml pollen/pagetree))
@(define my-eval (make-base-eval)) @(define my-eval (make-base-eval))
@(my-eval `(require pollen pollen/template xml)) @(my-eval `(require pollen pollen/template xml))
@ -22,3 +22,64 @@ Convert @racket[_xexpr] to an HTML string. Similar to @racket[xexpr->string], bu
(xexpr->string tx) (xexpr->string tx)
(->html tx) (->html tx)
] ]
Be careful not to pass existing HTML strings into this function, because the @code{<} and @code{>} symbols will be escaped. Fine if that's what you want, but you probably don't.
@examples[#:eval my-eval
(define tx '(p "You did" (em "what?")))
(->html tx)
(->html (->html tx))
]
@deftogether[(
@defproc[
(from
[query symbolish?]
[pagenode pagenodeish?])
(or/c #f txexpr-element?)]
@defproc[
(from*
[query symbolish?]
[pagenode pagenodeish?])
(or/c #f (listof txexpr-element?))]
)]
Find matches for @racket[_query] in @racket[_pagenode], first by looking in its @code{metas} (using @racket[from-metas]) and then by looking in its @code{doc} (using @racket[from-doc]). With @racket[from], you get the first result; with @racket[from*], you get them all. In both cases, you get @racket[#f] if there are no matches.
@defproc[
(from-metas
[query symbolish?]
[meta-source (or/c pagenodeish? hash?)])
(or/c #f txexpr-element?)]
Look up the value of @racket[_query] in @racket[_meta-source]. The @racket[_meta-source] argument can be either a set of metas (i.e., a @racket[hash]) or a @racket[pagenode?], from which metas are pulled. If no value exists for @racket[_query], you get @racket[#f].
@examples[#:eval my-eval
(define my-metas (hash 'template "sub.xml.pt" 'target "print"))
(from-metas 'template my-metas)
('target . from-metas . my-metas)
(from-metas 'nonexistent-key my-metas)
]
@defproc[
(from-doc
[query symbolish?]
[doc-source (or/c pagenodeish? txexpr?)])
(or/c #f txexpr-element?)]
Look up the value of @racket[_query] in @racket[_doc-source]. The @racket[_doc-source] argument can be either be a @code{doc} (i.e., a @racket[txexpr]) or a @racket[pagenode?], from which doc is pulled. If no value exists for @racket[_query], you get @racket[#f].
@examples[#:eval my-eval
(define my-doc '(body (question "Gelato?")
(answer "Nocciola") (answer "Pistachio")))
(from-doc 'question my-doc)
('answer . from-doc . my-doc)
(from-doc 'nonexistent-key my-doc)
]

@ -5,7 +5,7 @@
(require web-server/http/request-structs) (require web-server/http/request-structs)
(require web-server/http/response-structs) (require web-server/http/response-structs)
(require 2htdp/image) (require 2htdp/image)
(require "world.rkt" "render.rkt" sugar txexpr "file.rkt" "debug.rkt" "pagemap.rkt" "cache.rkt") (require "world.rkt" "render.rkt" sugar txexpr "file.rkt" "debug.rkt" "pagetree.rkt" "cache.rkt")
(module+ test (require rackunit)) (module+ test (require rackunit))
@ -173,12 +173,12 @@
(cond ; in cell (cond ; in cell
[source (cons (format "in/~a" source) "in")] [source (cons (format "in/~a" source) "in")]
[(or (pagemap-source? filename) (sourceish? filename)) (cons (format "in/~a" filename) "in")] [(or (pagetree-source? filename) (sourceish? filename)) (cons (format "in/~a" filename) "in")]
[else empty-cell]) [else empty-cell])
(cond ; out cell (cond ; out cell
[(directory-exists? (build-path dashboard-dir filename)) (cons #f #f)] [(directory-exists? (build-path dashboard-dir filename)) (cons #f #f)]
[(pagemap-source? filename) empty-cell] [(pagetree-source? filename) empty-cell]
[else (cons (format "out/~a" filename) "out")])))))) [else (cons (format "out/~a" filename) "out")]))))))
(define (ineligible-path? x) (or (not (visible? x)) (member x world:reserved-paths))) (define (ineligible-path? x) (or (not (visible? x)) (member x world:reserved-paths)))
@ -190,16 +190,16 @@
(define path-is-directory? (λ(f) (directory-exists? (build-path dashboard-dir f)))) (define path-is-directory? (λ(f) (directory-exists? (build-path dashboard-dir f))))
(define subdirectories (filter path-is-directory? all-paths)) (define subdirectories (filter path-is-directory? all-paths))
(define files (filter-not path-is-directory? all-paths)) (define files (filter-not path-is-directory? all-paths))
(define pagemap-sources (filter pagemap-source? files)) (define pagetree-sources (filter pagetree-source? files))
(define other-files (filter-not pagemap-source? files)) (define other-files (filter-not pagetree-source? files))
(define (sort-names xs) (sort xs #:key ->string string<?)) (define (sort-names xs) (sort xs #:key ->string string<?))
;; put subdirs in list ahead of files (so they appear at the top) ;; put subdirs in list ahead of files (so they appear at the top)
(append (sort-names subdirectories) (sort-names pagemap-sources) (sort-names other-files))) (append (sort-names subdirectories) (sort-names pagetree-sources) (sort-names other-files)))
(define project-paths (define project-paths
(filter-not ineligible-path? (filter-not ineligible-path?
(if (file-exists? dashboard-pmap) (if (file-exists? dashboard-pmap)
(map ->path (pagemap->list (cached-require (->path dashboard-pmap) world:main-pollen-export))) (map ->path (pagetree->list (cached-require (->path dashboard-pmap) world:main-pollen-export)))
(unique-sorted-output-paths (directory-list dashboard-dir))))) (unique-sorted-output-paths (directory-list dashboard-dir)))))
(body-wrapper (body-wrapper

@ -13,7 +13,7 @@
(define-values (pollen-servlet _) (define-values (pollen-servlet _)
(dispatch-rules (dispatch-rules
[((string-arg) ... (? pagemap-source?)) route-dashboard] [((string-arg) ... (? pagetree-source?)) route-dashboard]
[((string-arg) ... "in" (string-arg)) route-in] [((string-arg) ... "in" (string-arg)) route-in]
[((string-arg) ... "out" (string-arg)) route-out] [((string-arg) ... "out" (string-arg)) route-out]
[((string-arg) ... "xexpr" (string-arg)) route-xexpr] [((string-arg) ... "xexpr" (string-arg)) route-xexpr]

@ -1,7 +1,7 @@
#lang racket/base #lang racket/base
(require (for-syntax racket/base)) (require (for-syntax racket/base))
(require racket/string xml xml/path sugar/define sugar/container sugar/coerce/contract) (require racket/string xml xml/path sugar/define sugar/container sugar/coerce/contract)
(require "tools.rkt" txexpr "world.rkt" "cache.rkt" "pagemap.rkt") (require "tools.rkt" txexpr "world.rkt" "cache.rkt" "pagetree.rkt")
(require sugar/coerce/value) (require sugar/coerce/value)
@ -9,73 +9,63 @@
(define/contract+provide (metas->here metas) (define/contract+provide (metas->here metas)
(hash? . -> . node?) (hash? . -> . pagenode?)
(path->node ('here-path . from-metas . metas))) (path->pagenode ('here-path . from-metas . metas)))
(define/contract (get-doc node-or-path) (define/contract (get-doc pagenode-or-path)
((or/c node? pathish?) . -> . (or/c txexpr? string?)) ((or/c pagenode? pathish?) . -> . (or/c txexpr? string?))
(define source-path (->source-path (cond (define source-path (->source-path (cond
[(node? node-or-path) (node->path node-or-path)] [(pagenode? pagenode-or-path) (pagenode->path pagenode-or-path)]
[else node-or-path]))) [else pagenode-or-path])))
(if source-path (if source-path
(cached-require source-path world:main-pollen-export) (cached-require source-path world:main-pollen-export)
(error (format "get-doc: no source found for '~a' in directory ~a" node-or-path (current-directory))))) (error (format "get-doc: no source found for '~a' in directory ~a" pagenode-or-path (current-directory)))))
(define/contract (get-metas node-or-path) (define/contract (get-metas pagenode-or-path)
((or/c node? pathish?) . -> . hash?) ((or/c pagenode? pathish?) . -> . hash?)
(define source-path (->source-path (cond (define source-path (->source-path (cond
[(node? node-or-path) (node->path node-or-path)] [(pagenode? pagenode-or-path) (pagenode->path pagenode-or-path)]
[else node-or-path]))) [else pagenode-or-path])))
(if source-path (if source-path
(cached-require source-path world:meta-pollen-export) (cached-require source-path world:meta-pollen-export)
(error (format "get-metas: no source found for '~a' in directory ~a" node-or-path (current-directory))))) (error (format "get-metas: no source found for '~a' in directory ~a" pagenode-or-path (current-directory)))))
(define (node->path node) (define (pagenode->path pagenode)
(build-path (world:current-project-root) (symbol->string node))) (build-path (world:current-project-root) (symbol->string pagenode)))
(define+provide/contract (from-node query node) (define+provide/contract (from query pagenode)
(coerce/symbol? coerce/symbol? . -> . (or/c #f txexpr-element?)) (coerce/symbol? coerce/symbol? . -> . (or/c #f txexpr-element?))
(define result (from-node* query node)) (define result (from* query pagenode))
(if (null? result) #f (car result))) (if (null? result) #f (car result)))
(define+provide/contract (from-node* query node) (define+provide/contract (from* query pagenode)
(coerce/symbol? coerce/symbol? . -> . (listof txexpr-element?)) (coerce/symbol? coerce/symbol? . -> . (or/c #f (listof txexpr-element?)))
(define meta-result (from-metas query node)) (define meta-result (from-metas query pagenode))
(append (if meta-result (list meta-result) null) (from-doc query node))) (define doc-result (from-doc query pagenode))
(define combined-result (append (if meta-result (list meta-result) null)
(or doc-result null)))
(if (null? combined-result) #f combined-result))
(define/contract+provide (from-metas query node-or-metas) (define/contract+provide (from-metas query meta-source)
(coerce/symbol? (or/c node? hash?) . -> . (or/c #f txexpr-element?)) (coerce/symbol? (or/c pagenode? hash?) . -> . (or/c #f txexpr-element?))
(let ([metas (or (and (node? node-or-metas) (get-metas node-or-metas)) node-or-metas)]) (let ([metas (or (and (pagenode? meta-source) (get-metas meta-source)) meta-source)])
(with-handlers ([exn:fail? (λ(e) #f)]) (with-handlers ([exn:fail? (λ(e) #f)])
(hash-ref metas query)))) (hash-ref metas query))))
(define/contract+provide (from-doc query node-or-doc) (define/contract+provide (from-doc query doc-source)
(coerce/symbol? (or/c node? txexpr?) . -> . (or/c #f txexpr-elements?)) (coerce/symbol? (or/c pagenode? txexpr?) . -> . (or/c #f txexpr-elements?))
(let ([doc (or (and (node? node-or-doc) (get-doc node-or-doc)) node-or-doc)]) (let ([doc (or (and (pagenode? doc-source) (get-doc doc-source)) doc-source)])
(with-handlers ([exn:fail? (λ(e) null)]) (with-handlers ([exn:fail? (λ(e) #f)])
(se-path*/list (list query) doc)))) (se-path*/list (list query) doc))))
;; turns input into xexpr-elements so they can be spliced into template
;; (as opposed to dropped in as a full txexpr)
;; by returning a list, pollen rules will automatically merge into main flow
;; todo: explain why
;; todo: do I need this?
(define+provide/contract (splice x)
((or/c txexpr? txexpr-elements? string?) . -> . txexpr-elements?)
(cond
[(txexpr? x) (get-elements x)]
[(txexpr-elements? x) x]
[(string? x) (->list x)]))
(define+provide/contract (->html x) (define+provide/contract (->html x)
(xexpr? . -> . string?) (xexpr? . -> . string?)
(xexpr->html x)) (xexpr->html x))

@ -71,9 +71,9 @@
(check-false (preproc-source? #f))) (check-false (preproc-source? #f)))
(module+ test (module+ test
(check-true (pagemap-source? (format "foo.~a" world:pagemap-source-ext))) (check-true (pagetree-source? (format "foo.~a" world:pagetree-source-ext)))
(check-false (pagemap-source? (format "~a.foo" world:pagemap-source-ext))) (check-false (pagetree-source? (format "~a.foo" world:pagetree-source-ext)))
(check-false (pagemap-source? #f))) (check-false (pagetree-source? #f)))
(module+ test (module+ test
(check-true (markup-source? "foo.pm")) (check-true (markup-source? "foo.pm"))
(check-false (markup-source? "foo.p")) (check-false (markup-source? "foo.p"))

@ -1,69 +1,69 @@
#lang racket/base #lang racket/base
(require rackunit) (require rackunit)
(require "../pagemap.rkt" "../world.rkt") (require "../pagetree.rkt" "../world.rkt")
(check-false (node? "foo-bar")) (check-false (pagenode? "foo-bar"))
(check-false (node? "Foo_Bar_0123")) (check-false (pagenode? "Foo_Bar_0123"))
(check-true (node? 'foo-bar)) (check-true (pagenode? 'foo-bar))
(check-false (node? "foo-bar.p")) (check-false (pagenode? "foo-bar.p"))
(check-false (node? "/Users/MB/foo-bar")) (check-false (pagenode? "/Users/MB/foo-bar"))
(check-false (node? #f)) (check-false (pagenode? #f))
(check-false (node? "")) (check-false (pagenode? ""))
(check-false (node? " ")) (check-false (pagenode? " "))
(check-true (pagemap? '(foo))) (check-true (pagetree? '(foo)))
(check-true (pagemap? '(foo (hee)))) (check-true (pagetree? '(foo (hee))))
(check-true (pagemap? '(foo (hee (uncle foo))))) (check-true (pagetree? '(foo (hee (uncle foo)))))
(check-false (pagemap? '(foo (hee hee (uncle foo))))) (check-false (pagetree? '(foo (hee hee (uncle foo)))))
(define test-pagemap-main `(pagemap-main foo bar (one (two three)))) (define test-pagetree-main `(pagetree-main foo bar (one (two three))))
(define test-pagemap (pagemap-root->pagemap test-pagemap-main)) (define test-pagetree (pagetree-root->pagetree test-pagetree-main))
(check-equal? (parent 'three test-pagemap) 'two) (check-equal? (parent 'three test-pagetree) 'two)
(check-equal? (parent "three" test-pagemap) 'two) (check-equal? (parent "three" test-pagetree) 'two)
(check-false (parent #f test-pagemap)) (check-false (parent #f test-pagetree))
(check-false (parent 'nonexistent-name test-pagemap)) (check-false (parent 'nonexistent-name test-pagetree))
(check-equal? (children 'one test-pagemap) '(two)) (check-equal? (children 'one test-pagetree) '(two))
(check-equal? (children 'two test-pagemap) '(three)) (check-equal? (children 'two test-pagetree) '(three))
(check-false (children 'three test-pagemap)) (check-false (children 'three test-pagetree))
(check-false (children #f test-pagemap)) (check-false (children #f test-pagetree))
(check-false (children 'fooburger test-pagemap)) (check-false (children 'fooburger test-pagetree))
(check-equal? (siblings 'one test-pagemap) '(foo bar one)) (check-equal? (siblings 'one test-pagetree) '(foo bar one))
(check-equal? (siblings 'foo test-pagemap) '(foo bar one)) (check-equal? (siblings 'foo test-pagetree) '(foo bar one))
(check-equal? (siblings 'two test-pagemap) '(two)) (check-equal? (siblings 'two test-pagetree) '(two))
(check-false (siblings #f test-pagemapap)) (check-false (siblings #f test-pagetree))
(check-false (siblings 'invalid-key test-pagemap)) (check-false (siblings 'invalid-key test-pagetree))
(check-equal? (previous* 'one test-pagemap) '(foo bar)) (check-equal? (previous* 'one test-pagetree) '(foo bar))
(check-equal? (previous* 'three test-pagemap) '(foo bar one two)) (check-equal? (previous* 'three test-pagetree) '(foo bar one two))
(check-false (previous* 'foo test-pagemap)) (check-false (previous* 'foo test-pagetree))
(check-equal? (previous 'one test-pagemap) 'bar) (check-equal? (previous 'one test-pagetree) 'bar)
(check-equal? (previous 'three test-pagemap) 'two) (check-equal? (previous 'three test-pagetree) 'two)
(check-false (previous 'foo test-pagemap)) (check-false (previous 'foo test-pagetree))
(check-equal? (next 'foo test-pagemap) 'bar) (check-equal? (next 'foo test-pagetree) 'bar)
(check-equal? (next 'one test-pagemap) 'two) (check-equal? (next 'one test-pagetree) 'two)
(check-false (next 'three test-pagemap)) (check-false (next 'three test-pagetree))
(check-equal? (pagemap->list test-pagemap) '(foo bar one two three)) (check-equal? (pagetree->list test-pagetree) '(foo bar one two three))
(let ([sample-main `(world:pollen-tree-root-name foo bar (one (two three)))]) (let ([sample-main `(world:pollen-tree-root-name foo bar (one (two three)))])
(check-equal? (pagemap-root->pagemap sample-main) (check-equal? (pagetree-root->pagetree sample-main)
`(world:pollen-tree-root-name foo bar (one (two three))))) `(world:pollen-tree-root-name foo bar (one (two three)))))
(define files '("foo.html" "bar.html" "bar.html.p" "zap.html" "zap.xml")) (define files '("foo.html" "bar.html" "bar.html.p" "zap.html" "zap.xml"))
(check-equal? (node->url/paths 'foo.html files) "foo.html") (check-equal? (pagenode->url/paths 'foo.html files) "foo.html")
(check-equal? (node->url/paths 'bar.html files) "bar.html") (check-equal? (pagenode->url/paths 'bar.html files) "bar.html")
;; (check-equal? (name->url 'zap files) 'error) ;; todo: how to test error? ;; (check-equal? (name->url 'zap files) 'error) ;; todo: how to test error?
(check-false (node->url/paths 'hee files)) (check-false (pagenode->url/paths 'hee files))
(set! test-pagemap-main `(,world:pagemap-root-node foo bar (one (two three)))) (set! test-pagetree-main `(,world:pagetree-root-node foo bar (one (two three))))
(check-equal? (pagemap-root->pagemap test-pagemap-main) (check-equal? (pagetree-root->pagetree test-pagetree-main)
`(,world:pagemap-root-node foo bar (one (two three)))) `(,world:pagetree-root-node foo bar (one (two three))))

@ -8,7 +8,7 @@
(define markup-source-ext 'pm) (define markup-source-ext 'pm)
(define markdown-source-ext 'pmd) (define markdown-source-ext 'pmd)
(define null-source-ext 'p) (define null-source-ext 'p)
(define pagemap-source-ext 'pmap) (define pagetree-source-ext 'ptree)
(define template-source-ext 'pt) (define template-source-ext 'pt)
(define scribble-source-ext 'scrbl) (define scribble-source-ext 'scrbl)
@ -17,12 +17,12 @@
(define reader-mode-preproc 'pre) (define reader-mode-preproc 'pre)
(define reader-mode-markup 'markup) (define reader-mode-markup 'markup)
(define reader-mode-markdown 'markdown) (define reader-mode-markdown 'markdown)
(define reader-mode-pagemap 'pmap) (define reader-mode-pagetree 'ptree)
(define decodable-extensions (list markup-source-ext pagemap-source-ext)) (define decodable-extensions (list markup-source-ext pagetree-source-ext))
(define default-pagemap "index.pmap") (define default-pagetree "index.ptree")
(define pagemap-root-node 'pagemap-root) (define pagetree-root-node 'pagetree-root)
(define template-source-prefix "-") (define template-source-prefix "-")
(define expression-delimiter #\◊) (define expression-delimiter #\◊)

Loading…
Cancel
Save