On this page:
5.1 Constants
default-authorname
web-root
articles-folder
series-folder
images-folder
articles-pagetree
series-pagetree
here-output-path
here-source-path
checked-in?
here-id
5.2 Metas and txexprs
maybe-attr
maybe-meta
tx-strs
make-tag-predicate
first-words
normalize
5.3 Article parsers and helpers
listing-context
default-title
current-series-pagenode
current-series-noun
current-series-title
invalidate-series
disposition-values
build-note-id
notes->last-disposition-values
5.4 Date formatters
ymd->english
ymd->dateformat
7.7

5 Dust

 (require "dust.rkt")

This is where I put constants and helper functions that are needed pretty much everywhere in the project. In a simpler project these would go in "pollen.rkt" but here I have other modules sitting “behind” that one in the require chain.

5.1 Constants

value

default-authorname : string? = "Joel Dueck"

Used as the default author name for notes, and (possibly in the future) for articles generally.

value

web-root : path-string? = "/"

Specifies the path between the domain name and the root folder of the website generated by this project.

value

articles-folder : path-string? = "articles"

value

series-folder : path-string? = "series"

The names of the folders that contain the Pollen source documents for Articles and Series respectively, relative to the project’s document root.

value

images-folder : path-string? = "images"

The name of the subfolders within articles-folder and series-folder used for holding image files.

procedure

(articles-pagetree)  pagetree?

procedure

(series-pagetree)  pagetree?

These are project-wide pagetrees: articles-pagetree contains a pagenode for every Pollen document contained in articles-folder, and series-pagetree contains a pagenode for every Pollen document in series-folder. The pagenodes themselves point to the rendered .html targets of the source documents.

procedure

(here-output-path)  path?

procedure

(here-source-path)  path?

Returns the path to the current output or source file, relative to current-project-root. If no metas are available, returns (string->path ".").

For the output path, this is similar to the here variable that Pollen provides, except it is available outside templates. As to the source path, Pollen provides it via the 'here-path key in the current metas, but it is a full absolute path, rather then relative to current-project-root.

procedure

(checked-in?)  boolean?

Returns #t if the current article is checked into the Fossil repo, #f otherwise.

procedure

(here-id [suffix])  string?

  suffix : (or/c (listof string?) string? #f) = #f

Returns the 8-character prefix of the SHA1 hash of the current document’s output path. If no metas are available, the hash of (string->path ".") is used. If suffix evaluates to a string or a list of strings, they are appended verbatim to the end of the hash.

This ID is used when creating URL fragment links within an article, such as for footnotes and index entries. As long as the web version of the article is not moved to a new URL, the ID will remain the same, which ensures deep links using the ID don’t break. The ID also ensures each article’s internal links will be unique, so that links do not collide when multiple articles are being shown on a single HTML page.

5.2 Metas and txexprs

procedure

(maybe-attr key attrs [missing-expr])  any/c

  key : symbol?
  attrs : txexpr-attrs?
  missing-expr : any/c = ""

Find the value of key in the supplied list of attributes, returning the value of missing-expr if it’s not there.

I had to write this because attr-ref wants a whole tagged X-expression (not just the attributes); also, by default it raises an exception when key is missing, rather than returning an empty string.

procedure

(maybe-meta key [missing-expr])  any/c

  key : symbolish?
  missing-expr : any/c = ""

Look up a value in (current-metas) that may or may not be present, returning the value of missing-expr if it’s not there.

procedure

(tx-strs tx)  string?

  tx : txexpr?

Finds all the strings from the elements of tx (ignoring attributes) and concatenates them together.

Example:
> (tx-strs '(p [[class "intro"]]
               (em "I’m not opening the safe") ", Wilson remembers thinking."))

"I’m not opening the safe, Wilson remembers thinking."

procedure

(make-tag-predicate sym ...)  (-> any/c boolean?)

  sym : symbol?

Returns a function (or predicate) that returns #t if its argument is a txexpr whose tag matches any sym. This predicate is useful for passing as the pred expression in functions splitf-txexpr and findf-txexpr.

Examples:
> (define is-aside? (make-tag-predicate 'aside 'sidebar))
> (is-aside? '(q "I am not mad, Sir Topas. I say to you this house is dark."))

#f

> (is-aside? '(aside "How smart a lash that speech doth give my Conscience?"))

#t

> (is-aside? '(sidebar "Many copies that we use today are conflated texts."))

#t

procedure

(first-words txprs n)  string?

  txprs : (listof txexpr?)
  n : exact-nonnegative-integer?

Given a list of tagged X-expressions, returns a string containing the first n words found in the string elements of txprs, or all of the words if there are less than n words available. Used by default-title.

This function aims to be smart about punctuation, and equally fast no matter how large the list of elements that you send it.

Examples:
> (define txs-decimals
    '((p "Four score and 7.8 years ago — our fathers etc etc")))
> (define txs-punc-and-split-elems
    '((p "“Stop!” she called.") (p "(She was never one to be silent.)")))
> (define txs-dashes
    '((p [[class "newthought"]] (span [[class "smallcaps"]] "One - and") " only one.")
      (p "That was all she would allow.")))
> (define txs-parens-commas
      '((p "She counted (" (em "one, two") "— silently, eyes unblinking")))
> (define txs-short
    '((span "Not much here!")))
> (first-words txs-decimals 5)

"Four score and 7.8 years"

> (first-words txs-punc-and-split-elems 5)

"Stop! she called. She was"

> (first-words txs-dashes 5)

"One and only one. That"

> (first-words txs-parens-commas 5)

"She counted one two silently"

> (first-words txs-short 5)

"Not much here!"

procedure

(normalize str)  string?

  str : string?
Removes all non-space/non-alphanumeric characters from str, converts it to lowercase, and replaces all spaces with hyphens.

Examples:
> (normalize "Why, Hello World!")

"why-hello-world"

> (normalize "My first-ever 99-argument function, haha")

"my-firstever-99argument-function-haha"

5.3 Article parsers and helpers

parameter

(listing-context)  (or/c 'blog 'feed 'print "")

(listing-context ctxt)  void?
  ctxt : (or/c 'blog 'feed 'print "")
 = ""

A parameter specifying the current context where any listings of articles would appear. Its purpose is to allow articles to exclude themselves from certain special collections (e.g., the blog, the RSS feed, print editions). Any article whose conceal meta matches the current context will not be included in any listings returned by the listing functions in "cache.rkt".

procedure

(default-title body-txprs)  string?

  body-txprs : (listof txexpr?)

Given a list of tagged X-expressions (the elements of an article’s doc, e.g.), returns a string containing a suitable title for the document. (Uses first-words.)

Titles are not required for articles, but there are contexts where you need something that serves as a title if one is not present, and that’s what this function supplies.

Examples:
> (define doc
    '(root (p "If I had been astonished at first catching a glimpse of so outlandish an "
              "individual as Queequeg circulating among the polite society of a civilized "
              "town, that astonishment soon departed upon taking my first daylight "
              "stroll through the streets of New Bedford…")))
> (default-title (get-elements doc))

"“If I had been astonished…”"

procedure

(current-series-pagenode)  pagenode?

If (current-metas) has the key 'series, converts its value to the pagenode pointing to that series, otherwise returns '||.

Examples:
> (require pollen/core)
> (parameterize ([current-metas (hash 'series "marquee-fiction")])
    (current-series-pagenode))

'series/marquee-fiction.html

procedure

(current-series-noun)  string?

If (current-metas) has the key 'series and if there is a corresponding series in the series-list, return its series-noun-singular value; otherwise return "".

procedure

(current-series-title)  string?

If (current-metas) has the key 'series and if there is a corresponding series in the series-list, return its series-title value; otherwise return "".

procedure

(invalidate-series)  (or/c void? boolean?)

If the current article specifies a 'series meta, and if a corresponding ".poly.pm" file exists in series-folder, attempts to “touch” the last-modified timestamp on that file, returning #t on success or #f on failure. If either precondition is not true, returns #<void>.

When an article is being rendered, that means the article has changed, and if the article has changed, its series page (if any) should be updated as well. Touching the ".poly.pm" file for a series page triggers a re-render of that page when running make web to rebuild the web content (see makefile).

Only used in one place, tags-html.rkt.

procedure

(disposition-values str)  any

  str : string?

Given a string str, returns two values: the portion of the string coming before the first space, and the rest of the string.

Example:
> (disposition-values "* thoroughly recanted")

"*"

"thoroughly recanted"

procedure

(build-note-id tx)  non-empty-string?

  tx : txexpr?

Given a note tagged X-expression, returns an identifier string to uniquely identify that note within an article. This identifier is used as an anchor link in the note’s HTML, and as part of the note’s primary key in the SQLite cache database.

Examples:
> (build-note-id '(note [[date "2018-02-19"]] "This is an example note"))

"2018-02-19_Joel%20Dueck"

> (build-note-id '(note [[date "2018-03-19"] [author "Dean"]] "Different author!"))

"2018-03-19_Dean"

procedure

(notes->last-disposition-values txprs)  any

  txprs : (listof txexpr?)

Given a list of tagged X-expressions (ideally a list of notes), returns two values: the value of the 'disposition attribute for the last note that contains one, and the ID of that note.

Examples:
> (define notelist
    (list
      '(note [[date "2018-02-19"] [disposition "* problematic"]] "First note")
      '(note [[date "2018-03-19"]] "Second note")
      '(note [[date "2018-04-19"] [disposition "† recanted"]] "Third note")))
> (notes->last-disposition-values notelist)

"† recanted"

"2018-04-19_Joel%20Dueck"

5.4 Date formatters

procedure

(ymd->english ymd-string)  string?

  ymd-string : string?

Converts a date-string of the form "YYYY-MM-DD" to a string of the form "Monthname D, YYYY".

If the day number is missing from ymd-string, the first day of the month is assumed. If the month number is also missing, January is asssumed. If the string cannot otherwise be parsed as a date, an exception is raised.

If any spaces are present in ymd-string, everything after the first space is ignored.

procedure

(ymd->dateformat ymd_string dateformat)  string?

  ymd_string : string?
  dateformat : string?

Converts a date-string of the form "YYYY-MM-DD" to another string with the same date formatted according to dateformat. The pattern syntax of the date format comes from the Unicode CLDR.