# 9.4 Pagetree

► |  | Pollen: the book is a program

1 | Installation
2 | Quick tour
3 | Backstory
4 | The big picture
5 | First tutorial
6 | Using raco pollen
7 | File formats
8 | ◊ command overview
9 | Module reference
10 | Acknowledgments
11 | License & source code
| Index

▼ | 9 | Module reference

9.1 | Cache
9.2 | Decode
9.3 | File
9.4 | Pagetree
9.5 | Render
9.6 | Template
9.7 | Tag
9.8 | Top
9.9 | World

► | 9.4 | Pagetree

9.4.1 | Navigation
9.4.2 | Utilities

On this page:

pagetree?
validate-pagetree
pagenode?
pagenodeish?
->pagenode
9.4.1`` Navigation
current-pagetree
parent
children
siblings
previous
previous*
next
next*
9.4.2`` Utilities
pagetree->list
in-pagetree?
path->pagenode

6.0.1
top ← prev up next →

#### 9.4`` Pagetree

( require pollen/pagetree ) | package: pollen

A pagetree is a hierarchical list of Pollen output files. A pagetree source file has the extension .ptree. 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 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.

> > procedure

> > (pagetree? possible-pagetree) → boolean?

> possible-pagetree : any/c

Test whether possible-pagetree is a valid pagetree. It must be a txexpr? where all elements are pagenode?, and each is unique within possible-pagetree (not counting the root node).

Examples:

> > (pagetree? '(root index.html))
> #t
> > (pagetree? '(root duplicate.html duplicate.html))
> #f
> > (pagetree? '(root index.html "string.html"))
> #f
> > ( define nested-ptree '(root 1.html 2.html (3.html 3a.html 3b.html)))

> > (pagetree? nested-ptree)
> #t
> > (pagetree? `(root index.html ,nested-ptree (subsection.html more.html)))
> #t
> ; Nesting a subtree twice creates duplication
> > (pagetree? `(root index.html ,nested-ptree (subsection.html ,nested-ptree)))
> #f

> > procedure

> > (validate-pagetree possible-pagetree) → pagetree?

> possible-pagetree : any/c

Like pagetree?, but raises a descriptive error if possible-pagetree is invalid, and otherwise returns possible-pagetree itself.

Examples:

> > (validate-pagetree '(root (mama.html son.html daughter.html) uncle.html))
> '(root (mama.html son.html daughter.html) uncle.html)
> > (validate-pagetree `(root (, + son.html daughter.html) uncle.html))
> #f
> > (validate-pagetree '(root (mama.html son.html son.html) mama.html))
> validate-pagetree: items aren’t unique: (son.html mama.html)

> > procedure

> > (pagenode? possible-pagenode) → boolean?

> possible-pagenode : any/c

Test whether possible-pagenode is a valid pagenode. A pagenode can be any symbol? that is not whitespace/nbsp? Every leaf of a pagetree is a pagenode. In practice, your pagenodes will likely be names of output files.

> > > 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:

> ; Three symbols, the third one annoying but valid
> > ( map pagenode? '(symbol index.html | silly |))
> '(#t #t #t)
> ; A number, a string, a txexpr, and a whitespace symbol
> > ( map pagenode? '(9.999 "index.html" (p "Hello") | |))
> '(#f #f #f #f)

> > procedure

> > (pagenodeish? v) → boolean?

> v : any/c

Return #t if v can be converted with ->pagenode.

Example:

> > ( map pagenodeish? '(9.999 "index.html" | |))
> '(#t #t #f)

> > procedure

> > (->pagenode v) → pagenode?

> v : pagenodeish?

Convert v to a pagenode.

Examples:

> > ( map pagenodeish? '(symbol 9.999 "index.html" | silly |))
> '(#t #t #t #t)
> > ( map ->pagenode '(symbol 9.999 "index.html" | silly |))
> '(symbol |9.999| index.html | silly |)

##### 9.4.1`` Navigation

> > parameter

> > (current-pagetree) → pagetree?

> (current-pagetree pagetree) → void?
> pagetree : pagetree?

A parameter that defines the default pagetree used by pagetree navigation functions (e.g., parent-pagenode, chidren, et al.) if another is not explicitly specified. Initialized to #f.

> > procedure

> > (parent p [pagetree]) → ( or/c #f pagenode?)

> p : ( or/c #f pagenodeish?)
> pagetree : pagetree? = (current-pagetree)

Find the parent pagenode of p within pagetree. Return #f if there isn’t one.

Examples:

> > (current-pagetree '(root (mama.html son.html daughter.html) uncle.html))

> > (parent 'son.html)
> 'mama.html
> > (parent "mama.html")
> 'root
> > (parent (parent 'son.html))
> 'root
> > (parent (parent (parent 'son.html)))
> #f

> > procedure

> > (children p [pagetree]) → ( or/c #f pagenode?)

> p : ( or/c #f pagenodeish?)
> pagetree : pagetree? = (current-pagetree)

Find the child pagenodes of p within pagetree. Return #f if there aren’t any.

Examples:

> > (current-pagetree '(root (mama.html son.html daughter.html) uncle.html))

> > (children 'mama.html)
> '(son.html daughter.html)
> > (children 'uncle.html)
> #f
> > (children 'root)
> '(mama.html uncle.html)
> > ( map children (children 'root))
> '((son.html daughter.html) #f)

> > procedure

> > (siblings p [pagetree]) → ( or/c #f pagenode?)

> p : ( or/c #f pagenodeish?)
> pagetree : pagetree? = (current-pagetree)

Find the sibling pagenodes of p within pagetree. The list will include p itself. But the function will still return #f if pagetree is #f.

Examples:

> > (current-pagetree '(root (mama.html son.html daughter.html) uncle.html))

> > (siblings 'son.html)
> '(son.html daughter.html)
> > (siblings 'daughter.html)
> '(son.html daughter.html)
> > (siblings 'mama.html)
> '(mama.html uncle.html)

> > procedure

> > (previous p [pagetree]) → ( or/c #f pagenode?)

> p : ( or/c #f pagenodeish?)
> pagetree : pagetree? = (current-pagetree)

> > procedure

> > (previous* p [pagetree]) → ( or/c #f ( listof pagenode?))

> p : ( or/c #f pagenodeish?)
> pagetree : pagetree? = (current-pagetree)

Return the pagenode immediately before p. For previous*, return all the pagenodes before p, in sequence. In both cases, return #f if there aren’t any pagenodes. The root pagenode is ignored.

Examples:

> > (current-pagetree '(root (mama.html son.html daughter.html) uncle.html))

> > (previous 'daughter.html)
> 'son.html
> > (previous 'son.html)
> 'mama.html
> > (previous (previous 'daughter.html))
> 'mama.html
> > (previous 'mama.html)
> #f
> > (previous* 'daughter.html)
> '(mama.html son.html)
> > (previous* 'uncle.html)
> '(mama.html son.html daughter.html)

> > procedure

> > (next p [pagetree]) → ( or/c #f pagenode?)

> p : ( or/c #f pagenodeish?)
> pagetree : pagetree? = (current-pagetree)

> > procedure

> > (next* p [pagetree]) → ( or/c #f ( listof pagenode?))

> p : ( or/c #f pagenodeish?)
> pagetree : pagetree? = (current-pagetree)

Return the pagenode immediately after p. For next*, return all the pagenodes after p, in sequence. In both cases, return #f if there aren’t any pagenodes. The root pagenode is ignored.

Examples:

> > (current-pagetree '(root (mama.html son.html daughter.html) uncle.html))

> > (next 'son.html)
> 'daughter.html
> > (next 'daughter.html)
> 'uncle.html
> > (next (next 'son.html))
> 'uncle.html
> > (next 'uncle.html)
> #f
> > (next* 'mama.html)
> '(son.html daughter.html uncle.html)
> > (next* 'daughter.html)
> '(uncle.html)

##### 9.4.2`` Utilities

> > procedure

> > (pagetree->list pagetree) → list?

> pagetree : pagetree?

Convert pagetree to a simple list. Equivalent to a pre-order depth-first traversal of pagetree.

> > procedure

> > (in-pagetree? pagenode [pagetree]) → boolean?

> pagenode : pagenode?
> pagetree : pagetree? = (current-pagetree)

Report whether pagenode is in pagetree.

> > procedure

> > (path->pagenode p) → pagenode?

> p : pathish?

Convert path p to a pagenode — meaning, make it relative to current-project-root, run it through ->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 in-pagetree?).
top ← prev up next →