Overview
Context
Changes
Modified cache.rkt
from [cd0a6087]
to [22c08e42].
| 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2021
22
23
24
25
26
27
28
2930
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
5152
53
54
55
56
57
58
59 | 
#lang racket/base
; SPDX-License-Identifier: BlueOak-1.0.0
; This file is licensed under the Blue Oak Model License 1.0.0.
(require deta
         db/base
         db/sqlite3
         threading
         pollen/setup
         racket/match
"dust.rkt"
         (except-in pollen/core select))
(provide init-cache-db!
         cache-conn                     ; The most eligible bachelor in Neo Yokyo
         (schema-out cache:article)
         (schema-out cache:note)         (rename-in racket/list                    (group-by group-list-by))(schema-out cache:index-entry)
         (schema-out listing)
         delete-article!
         delete-notes!
         articles
         articles+notes
         listing-htmls
         fenced-listing         (schema-out cache:series)         unfence
;; Cache DB and Schemas
(define DBFILE (build-path (current-project-root) "vitreous.sqlite"))
(define cache-conn (make-parameter (sqlite3-connect #:database DBFILE #:mode 'create)))
(define-schema cache:article #:table "articles"
  ([id                   id/f #:primary-key #:auto-increment]
   [page                 symbol/f]
   [title-plain          string/f]
   [title-html-flow      string/f]
   [title-specified?     boolean/f]
   [published            string/f]
   [updated              string/f]
   [author               string/f]
   [conceal              string/f]
   [series-page          symbol/f]
   [noun-singular        string/f]
   [note-count           integer/f]         preheat-series!         series-grouped-list)   [content-html[disposition          string/f]
   [disp-html-anchor     string/f]
   [listing-full-html    string/f]   ; full content but without notes
   [listing-excerpt-html string/f]   ; Not used for now
   [listing-short-html   string/f])) ; Date and title only
(define-schema cache:note #:table "notes"    string/f] | 
<
<
<
|
<
<
|
 | 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
 | 
#lang racket/base
; SPDX-License-Identifier: BlueOak-1.0.0
; This file is licensed under the Blue Oak Model License 1.0.0.
(require deta
         db/base
         db/sqlite3
         threading
         pollen/setup
         racket/match
         "dust.rkt"
         (except-in pollen/core select))
(provide init-cache-db!
         cache-conn                     ; The most eligible bachelor in Neo Yokyo
         (schema-out cache:article)
         (schema-out cache:note)
         (schema-out cache:index-entry)
         (schema-out listing)
         delete-article!
         delete-notes!
         articles
         articles+notes
         listing-htmls
         fenced-listing
         unfence)
;; Cache DB and Schemas
(define DBFILE (build-path (current-project-root) "vitreous.sqlite"))
(define cache-conn (make-parameter (sqlite3-connect #:database DBFILE #:mode 'create)))
(define-schema cache:article #:table "articles"
  ([id                   id/f #:primary-key #:auto-increment]
   [page                 symbol/f]
   [title-plain          string/f]
   [title-html-flow      string/f]
   [title-specified?     boolean/f]
   [published            string/f]
   [updated              string/f]
   [author               string/f]
   [conceal              string/f]
   [series-page          symbol/f]
   [noun-singular        string/f]
   [note-count           integer/f]
   [content-html         string/f]
   [disposition          string/f]
   [disp-html-anchor     string/f]
   [listing-full-html    string/f]   ; full content but without notes
   [listing-excerpt-html string/f]   ; Not used for now
   [listing-short-html   string/f])) ; Date and title only
(define-schema cache:note #:table "notes"
 | 
| ︙ |  |  | ︙ |  | 
| 
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102103
104
105
106
107
108
109
110 | 
   [content-html         string/f]
   [series-page          symbol/f]
   [conceal              string/f]
   [listing-full-html    string/f]
   [listing-excerpt-html string/f]   ; Not used for now
   [listing-short-html   string/f])) ; Date and title only
(define-schema cache:index-entry #:table "index_entries"
  ([id          id/f #:primary-key #:auto-increment]
   [entry       string/f]
   [subentry    string/f]
   [page        symbol/f]
   [html-anchor string/f]))
(define-schema listing
  #:virtual
  ([path        string/f]
   [title       string/f]
   [author      string/f]
   [published   string/f]
   [updated     string/f]
   [html        string/f]))
(define (init-cache-db!)
  (create-table! (cache-conn) 'cache:article)
  (create-table! (cache-conn) 'cache:note)(define-schema cache:series #:table "series"  ([id            id/f #:primary-key #:auto-increment]   [page          symbol/f]   [title         string/f]   [published     string/f]   [noun-plural   string/f]   [noun-singular string/f]))(create-table! (cache-conn) 'cache:index-entry))
(define (delete-article! page)
  (query-exec (cache-conn)
              (~> (from cache:article #:as a)
                  (where (= a.page ,(format "~a" page)))
                  delete)))  (create-table! (cache-conn) 'cache:series) | 
<
<
<
<
<
<
<
<
<
 | 
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
 | 
   [content-html         string/f]
   [series-page          symbol/f]
   [conceal              string/f]
   [listing-full-html    string/f]
   [listing-excerpt-html string/f]   ; Not used for now
   [listing-short-html   string/f])) ; Date and title only
(define-schema cache:index-entry #:table "index_entries"
  ([id          id/f #:primary-key #:auto-increment]
   [entry       string/f]
   [subentry    string/f]
   [page        symbol/f]
   [html-anchor string/f]))
(define-schema listing
  #:virtual
  ([path        string/f]
   [title       string/f]
   [author      string/f]
   [published   string/f]
   [updated     string/f]
   [html        string/f]))
(define (init-cache-db!)
  (create-table! (cache-conn) 'cache:article)
  (create-table! (cache-conn) 'cache:note)
  (create-table! (cache-conn) 'cache:index-entry))
(define (delete-article! page)
  (query-exec (cache-conn)
              (~> (from cache:article #:as a)
                  (where (= a.page ,(format "~a" page)))
                  delete)))
 | 
| ︙ |  |  | ︙ |  | 
| 
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
 | 
(define (fenced-listing q)
  `(style ,@(listing-htmls q)))
;; Remove "<style>" and "</style>" introduced by using ->html on docs containing output from
;; listing functions
(define (unfence html-str)
  (regexp-replace* #px"<[\\/]{0,1}style>" html-str ""))
;;;;  ~~~ Fetching series ~~~;;(define (series-grouped-list)  (~> (for/list ([row (in-entities (cache-conn)                                    (order-by (from cache:series #:as s)                                             ([s.noun-plural #:asc])))]) row)      (group-list-by cache:series-noun-plural _ string-ci=?)));; Preloads the SQLite cache with info about each series.;; I may not actually need this but I’m leaving it for now.(define (preheat-series!)  (query-exec (cache-conn)              (~> (from cache:series #:as s)                  (where 1)                  delete))  (define series-rows    (for/list ([series-pagenode (in-list (cdr (series-pagetree)))])      (define series-metas (get-metas series-pagenode))      (make-cache:series       #:page series-pagenode       #:title (hash-ref series-metas 'title)       #:published (hash-ref series-metas 'published "")       #:noun-plural (hash-ref series-metas 'noun-plural "")       #:noun-singular (hash-ref series-metas 'noun-singular ""))))  (void (apply insert! (cache-conn) series-rows))) | 
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
 | 
192
193
194
195
196
197
198
 | 
(define (fenced-listing q)
  `(style ,@(listing-htmls q)))
;; Remove "<style>" and "</style>" introduced by using ->html on docs containing output from
;; listing functions
(define (unfence html-str)
  (regexp-replace* #px"<[\\/]{0,1}style>" html-str ""))
 | 
Modified code-docs/cache.scrbl
from [bc87f6f5]
to [ed5e44d9].
| ︙ |  |  | ︙ |  | 
| 
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 | 
Creates and initializes the SQLite database cache file (named @filepath{vitreous.sqlite} and located
in the project root folder) by running queries to create tables in the database if they do not
exist.
}
@section{Retrieving cached data}
Some of this looks a little wacky, but it’s a case of putting a little extra complextity into the
back end to make things simple on the front end. These functions are most commonly used inside the
@emph{body} of a Pollen document (i.e., series pages). 
@filebox["series/my-series.poly.pm"@defproc[(preheat-series!) void?]{Save info about each series in @racket[series-folder] to the cache.} | 
<
<
<
<
<
<
 | 
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 | 
Creates and initializes the SQLite database cache file (named @filepath{vitreous.sqlite} and located
in the project root folder) by running queries to create tables in the database if they do not
exist.
}
@section{Retrieving cached data}
Some of this looks a little wacky, but it’s a case of putting a little extra complextity into the
back end to make things simple on the front end. These functions are most commonly used inside the
@emph{body} of a Pollen document (i.e., series pages). 
@filebox["series/my-series.poly.pm"
 | 
| ︙ |  |  | ︙ |  | 
| 
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162 | 
The contents of the style tags are left intact.
Use this in templates with strings returned from @racket[->html] when called on docs that use the
@racket[fenced-listing] tag function.
}
@section{Deleting records}
@deftogether[(@defproc[(delete-article! [page stringish?]) void?]
              @defproc[(delete-notes!   [page stringish?]) void?])]{
              
Delete a particular article, or all notes for a particular article, respectively.@defproc[(series-grouped-list) (listof (listof cache:series?))]{Return a list of lists of all @racket[cache:series] in the cache database. The series are grouped sothat series using the same value in the @tt{noun_plural} column appear together.} | 
<
<
<
<
<
<
<
 | 
136
137
138
139
140
141
142
143
144
145
146
147
148
149
 | 
The contents of the style tags are left intact.
Use this in templates with strings returned from @racket[->html] when called on docs that use the
@racket[fenced-listing] tag function.
}
@section{Deleting records}
@deftogether[(@defproc[(delete-article! [page stringish?]) void?]
              @defproc[(delete-notes!   [page stringish?]) void?])]{
              
Delete a particular article, or all notes for a particular article, respectively.
 | 
| ︙ |  |  | ︙ |  | 
| 
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241 | 
                        [listing-full-html    string/f]
                        [listing-excerpt-html string/f]
                        [listing-short-html   string/f])
                       #:constructor-name make-cache:note]{
Table holding cached information on notes.
}
@defstruct*[cache:index-entry ([id id/f]
                               [entry       string/f]
                               [subentry    string/f]
                               [page        symbol/f]
                               [html-anchor string/f])}@defstruct*[cache:series ([id            id/f]                          [page          symbol/f]                          [title         string/f]                          [published     string/f]                          [noun-plural   string/f]                          [noun-singular string/f])                         #:constructor-name make-cache:series]{Table holding cached information on series. | 
<
<
<
<
<
<
<
<
<
<
<
<
 | 
203
204
205
206
207
208
209
210
211
212
213
214
215
216
 | 
                        [listing-full-html    string/f]
                        [listing-excerpt-html string/f]
                        [listing-short-html   string/f])
                       #:constructor-name make-cache:note]{
Table holding cached information on notes.
}
@defstruct*[cache:index-entry ([id id/f]
                               [entry       string/f]
                               [subentry    string/f]
                               [page        symbol/f]
                               [html-anchor string/f])
 | 
| ︙ |  |  | ︙ |  | 
Modified code-docs/crystalize.scrbl
from [ca8a0906]
to [d002cd00].
| ︙ |  |  | ︙ |  | 
| 
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
 | 
and saved to the SQLite cache and saved using @racket[make-cache:article]. If the article specifies
a @racket['series] meta, information about that series is fetched and used in the rendering of the
article. If there are @racket[note]s or @racket[index] tags in the doc, they are parsed and saved
individually to the SQLite cache (using @racket[make-cache:note] and
@racket[make-cache:index-entry]). If any of the notes use the @code{#:disposition} attribute,
information about the disposition is parsed out and used in the rendering of the article. 
}
@defproc[(cache-series!) void?]{Attempts to look up certain values in @racket[current-metas] which we expect to be defined ona typical series page, and saves them to the cache using @racket[make-cache:series]. If @tt{title}is not defined in the current metas, you’ll get an error. If any of the others are missing, an emptystring is used.} | 
<
<
<
<
<
<
<
<
<
 | 
41
42
43
44
45
46
47
48
 | 
and saved to the SQLite cache and saved using @racket[make-cache:article]. If the article specifies
a @racket['series] meta, information about that series is fetched and used in the rendering of the
article. If there are @racket[note]s or @racket[index] tags in the doc, they are parsed and saved
individually to the SQLite cache (using @racket[make-cache:note] and
@racket[make-cache:index-entry]). If any of the notes use the @code{#:disposition} attribute,
information about the disposition is parsed out and used in the rendering of the article. 
}
 | 
Modified code-docs/dust.scrbl
from [ed5349c7]
to [6b21bda7].
| 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 | 
#lang scribble/manual
@; SPDX-License-Identifier: BlueOak-1.0.0
@; This file is licensed under the Blue Oak Model License 1.0.0.
@(require "scribble-helpers.rkt"
          scribble/example)
@(require (for-label "../pollen.rkt"
                     "../dust.rkt"
                     "../cache.rkt"
                     racket/base
                     racket/contract
                     txexpr
                     sugar/coerce
                     pollen/tag
                     pollen/setup
                     pollen/pagetree
 | 
>
 | 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 | 
#lang scribble/manual
@; SPDX-License-Identifier: BlueOak-1.0.0
@; This file is licensed under the Blue Oak Model License 1.0.0.
@(require "scribble-helpers.rkt"
          scribble/example)
@(require (for-label "../pollen.rkt"
                     "../dust.rkt"
                     "../cache.rkt"
                     "../series-list.rkt"
                     racket/base
                     racket/contract
                     txexpr
                     sugar/coerce
                     pollen/tag
                     pollen/setup
                     pollen/pagetree
 | 
| ︙ |  |  | ︙ |  | 
| 
180
181
182
183
184
185
186
187
188
189
190
191192
193194
195
196197
198199
200
201
202
203
204
205
206
207 | 
(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))]
@defproc[(If @code{(current-metas)} has the key @racket['series], converts its value to the pagenode pointing to
that series, otherwise returns @racket['||].metas-series-pagenode) pagenode?]@defproc[(series-metas-noun) string?]If @code{(current-metas)} has the key @racket['series],and if the corresponding series defines a metavalue for @racket['noun-singular], then return it, otherwise return @racket[""].@defproc[(series-metas-title) string?]If @code{(current-metas)} has the key @racket['series],and if the corresponding series defines a meta@defproc[(invalidate-series) (or/c void? boolean?)]
If the current article specifies a @racket['series] meta, and if a corresponding @filepath{.poly.pm}
file exists in @racket[series-folder], attempts to “touch” the last-modified timestamp on that file,
returning @racket[#t] on success or @racket[#f] on failure. If either precondition is not true,
returns @|void-const|.value for @racket['title], then return it, otherwise return @racket[""]. | 
|
>
>
>
>
|
>
|
>
|
|
|
>
|
 | 
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
 | 
(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))]
@defproc[(current-series-pagenode) pagenode?]
If @code{(current-metas)} has the key @racket['series], converts its value to the pagenode pointing to
that series, otherwise returns @racket['||].
@examples[#:eval dust-eval
(require pollen/core)
(parameterize ([current-metas (hash 'series "marquee-fiction")])
  (current-series-pagenode))]
@defproc[(current-series-noun) string?]
If @code{(current-metas)} has the key @racket['series] and if there is a corresponding
@racket[series] in the @racket[series-list], return its @racket[series-noun-singular] value;
otherwise return @racket[""].
@defproc[(current-series-title) string?]
If @code{(current-metas)} has the key @racket['series] and if there is a corresponding
@racket[series] in the @racket[series-list], return its @racket[series-title] value;
otherwise return @racket[""].
@defproc[(invalidate-series) (or/c void? boolean?)]
If the current article specifies a @racket['series] meta, and if a corresponding @filepath{.poly.pm}
file exists in @racket[series-folder], attempts to “touch” the last-modified timestamp on that file,
returning @racket[#t] on success or @racket[#f] on failure. If either precondition is not true,
returns @|void-const|.
 | 
| ︙ |  |  | ︙ |  | 
Modified code-docs/main.scrbl
from [d030a01e]
to [1cad1ba1].
| ︙ |  |  | ︙ |  | 
| 
47
48
49
50
51
52
53
54
55
56
57
58
 | 
cached metas of every article looking for matching articles.
@local-table-of-contents[]
@include-section["tour.scrbl"]
@include-section["design.scrbl"]
@include-section["pollen.scrbl"]  @; pollen.rkt
@include-section["dust.scrbl"]    @; dust.rkt
@include-section["snippets-html.scrbl"] @; you get the idea
@include-section["cache.scrbl"]
@include-section["crystalize.scrbl"]
@include-section["other-files.scrbl"]
 | 
>
 | 
47
48
49
50
51
52
53
54
55
56
57
58
59
 | 
cached metas of every article looking for matching articles.
@local-table-of-contents[]
@include-section["tour.scrbl"]
@include-section["design.scrbl"]
@include-section["pollen.scrbl"]  @; pollen.rkt
@include-section["series.scrbl"]
@include-section["dust.scrbl"]    @; dust.rkt
@include-section["snippets-html.scrbl"] @; you get the idea
@include-section["cache.scrbl"]
@include-section["crystalize.scrbl"]
@include-section["other-files.scrbl"]
 | 
Added code-docs/series.scrbl version [09dae3f6].
| 
 | 
 | 
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
 | 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
 | 
#lang scribble/manual
@; SPDX-License-Identifier: BlueOak-1.0.0
@; This file is licensed under the Blue Oak Model License 1.0.0.
@(require "scribble-helpers.rkt"
          scribble/example)
@(require (for-label "../pollen.rkt"
                     "../series-list.rkt"
                     "../dust.rkt"
                     "../cache.rkt"
                     pollen/core
                     racket/base
                     racket/contract))
@title{Defining Series}
To create a new series:
@itemlist[#:style 'ordered
  @item{Create a file @filepath{my-key.poly.pm} inside @racket[series-folder] and include a call
  to @racket[fenced-listing] to list all the articles and notes that will be included in the series:
  @codeblock|{
#lang pollen
◊(define-meta title "My New Series")
◊block{Here’s what we call a bunch of similar articles:
◊(fenced-listing (articles 'short))
}
  }|
  }
  
  @item{Add an entry for @racket[_my-key] to @racket[series-list] in @filepath{series-list.rkt}}
  @item{Use @racket[(define-meta series "my-key")] in articles to add them to the series.}
  @item{If @racket[series-ptree-ordered?] is @racket[#t], create a @seclink["Pagetree" #:doc '(lib
  "pollen/scribblings/pollen.scrbl")]{pagetree} file in @racket[series-folder] named
  @filepath{my-key.ptree}.}
  ]
@section{Series list}
@defmodule["series-list.rkt" #:packages ()]
This module contains the most commonly used bits of meta-info about @tech{series}. Storing these
bits in a hash table of structs makes them faster to retrieve than when they are stored inside the
metas of the Pollen documents for the series themselves.
@defthing[series-list hash?]{
An immutable hash containing all the title and noun info for each @tech{series}. Each key is
a string and each value is a @racket[series] struct.
}
@defstruct[series ([key            string?]
                   [title          string?]
                   [noun-plural    string?]
                   [noun-singular  string?]
                   [ptree-ordered? boolean?])]{
Struct for holding metadata for a @tech{series}. The @racket[_ptree-ordered?] value should be
@racket[#t] if there is a @filepath{@italic{key}.ptree} file in @racket[series-folder] that provides
information on how articles in the series are ordered.
}
 | 
Modified crystalize.rkt
from [121eb65c]
to [7aa92528].
| ︙ |  |  | ︙ |  | 
| 
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 | 
         pollen/template
         pollen/decode
         (except-in pollen/core select) ; avoid conflict with deta
         )
(require "dust.rkt" "cache.rkt" "snippets-html.rkt")
(provide parse-and-cache-article!
(define current-title       (make-parameter #f))
(define current-excerpt     (make-parameter #f))
(define current-notes       (make-parameter '()))
(define current-disposition (make-parameter ""))
(define current-disp-id     (make-parameter ""))         cache-series!) | 
|
<
 | 
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 | 
         pollen/template
         pollen/decode
         (except-in pollen/core select) ; avoid conflict with deta
         )
(require "dust.rkt" "cache.rkt" "snippets-html.rkt")
(provide parse-and-cache-article!)
(define current-title       (make-parameter #f))
(define current-excerpt     (make-parameter #f))
(define current-notes       (make-parameter '()))
(define current-disposition (make-parameter ""))
(define current-disp-id     (make-parameter ""))
 | 
| ︙ |  |  | ︙ |  | 
| 
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 | 
                                          title-val
                                          body-txpr
                                          (current-disposition)
                                          (current-disp-id))]
         [title-html  (->html title-tx #:splice? #t)]
         [title-plain (tx-strs title-tx)]
         [header      (html$-article-open pagenode title-specified? title-tx pubdate)]
         [series-node ([footertext  (make-article-footertext pagenode
                                               series-node
                                               (current-disposition)
                                               (current-disp-id)
                                               (length (current-notes)))]
         [footer (html$-article-close footertext)]
         [listing-short (html$-article-listing-short pagenode pubdate title-html)]metas-series-pagenode)] | 
|
 | 
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
 | 
                                          title-val
                                          body-txpr
                                          (current-disposition)
                                          (current-disp-id))]
         [title-html  (->html title-tx #:splice? #t)]
         [title-plain (tx-strs title-tx)]
         [header      (html$-article-open pagenode title-specified? title-tx pubdate)]
         [series-node (current-series-pagenode)]
         [footertext  (make-article-footertext pagenode
                                               series-node
                                               (current-disposition)
                                               (current-disp-id)
                                               (length (current-notes)))]
         [footer (html$-article-close footertext)]
         [listing-short (html$-article-listing-short pagenode pubdate title-html)]
 | 
| ︙ |  |  | ︙ |  | 
| 
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 | 
                  #:title-html-flow title-html
                  #:title-specified? title-specified?
                  #:published pubdate
                  #:updated (maybe-meta 'updated)
                  #:author (maybe-meta 'author default-authorname)
                  #:conceal (maybe-meta 'conceal)
                  #:series-page series-node
                  #:noun-singular (maybe-meta 'noun (serie#:note-count (length (current-notes))
                  #:content-html doc-html
                  #:disposition (current-disposition)
                  #:disp-html-anchor (current-disp-id)
                  #:listing-full-html listing-full
                  #:listing-excerpt-html listing-excerpt
                  #:listing-short-html listing-short))s-metas-noun)) | 
|
 | 
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
 | 
                  #:title-html-flow title-html
                  #:title-specified? title-specified?
                  #:published pubdate
                  #:updated (maybe-meta 'updated)
                  #:author (maybe-meta 'author default-authorname)
                  #:conceal (maybe-meta 'conceal)
                  #:series-page series-node
                  #:noun-singular (maybe-meta 'noun (current-series-noun))
                  #:note-count (length (current-notes))
                  #:content-html doc-html
                  #:disposition (current-disposition)
                  #:disp-html-anchor (current-disp-id)
                  #:listing-full-html listing-full
                  #:listing-excerpt-html listing-excerpt
                  #:listing-short-html listing-short))
 | 
| ︙ |  |  | ︙ |  | 
| 
117
118
119
120
121
122
123
124
125
126127
128
129
130
131
132
133
134 | 
          [else ""]))
  ;; Returns a txexpr, the tag will be discarded by the template/snippets
  `(title ,@title-elems ,disposition-part))
;; Convert a bunch of information about an article into some nice English and links.
(define (make-article-footertext pagenode series disposition disp-note-id note-count)
  (define series-part
    (match (serie[(? non-empty-string? s-title)
       (format "<span class=\"series-part\">This is ~a, part of <a href=\"/~a\">‘~a’</a>.</span>"s-metas-title)               (serieseries
               s-title)]
      [_ ""]))
  (define disp-part
    (cond [(non-empty-string? disposition)
           (define-values (mark verb) (disposition-values disposition))
           (format "Now considered <a href=\"/~a#~a\">~a</a>."s-metas-noun) | 
|
|
 | 
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
 | 
          [else ""]))
  ;; Returns a txexpr, the tag will be discarded by the template/snippets
  `(title ,@title-elems ,disposition-part))
;; Convert a bunch of information about an article into some nice English and links.
(define (make-article-footertext pagenode series disposition disp-note-id note-count)
  (define series-part
    (match (current-series-title)
      [(? non-empty-string? s-title)
       (format "<span class=\"series-part\">This is ~a, part of <a href=\"/~a\">‘~a’</a>.</span>"
               (current-series-noun)
               series
               s-title)]
      [_ ""]))
  (define disp-part
    (cond [(non-empty-string? disposition)
           (define-values (mark verb) (disposition-values disposition))
           (format "Now considered <a href=\"/~a#~a\">~a</a>."
 | 
| ︙ |  |  | ︙ |  | 
| 
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214 | 
                  #:html-anchor note-id
                  #:title-html-flow title-html
                  #:title-plain (tx-strs title-tx)
                  #:published note-date
                  #:author author
                  #:author-url author-url
                  #:disposition disposition-attr
                  #:series-page (#:conceal (or (maybe-attr 'conceal attrs #f) (maybe-meta 'conceal))
                  #:content-html content-html
                  #:listing-full-html listing-full
                  #:listing-excerpt-html listing-full
                  #:listing-short-html ""))
    (html$-note-in-article note-id note-date content-html author author-url)))metas-series-pagenode) | 
|
 | 
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
 | 
                  #:html-anchor note-id
                  #:title-html-flow title-html
                  #:title-plain (tx-strs title-tx)
                  #:published note-date
                  #:author author
                  #:author-url author-url
                  #:disposition disposition-attr
                  #:series-page (current-series-pagenode)
                  #:conceal (or (maybe-attr 'conceal attrs #f) (maybe-meta 'conceal))
                  #:content-html content-html
                  #:listing-full-html listing-full
                  #:listing-excerpt-html listing-full
                  #:listing-short-html ""))
    (html$-note-in-article note-id note-date content-html author author-url)))
 | 
| ︙ |  |  | ︙ |  | 
| 
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
 | 
  (query-exec (cache-conn) (delete (~> (from cache:index-entry #:as entry)
                                       (where (= entry.page ,(symbol->string pagenode))))))
  (unless (null? entry-txs)
    (void
     (apply insert! (cache-conn)
            (for/list ([etx (in-list entry-txs)])
              (txexpr->index-entry etx pagenode))))))
;; Save the current article to the `series` table of the SQLite cache;; Should be called from a template for series pages(define (cache-series!)  (define here-page (path->string (here-output-path)))  (query-exec (cache-conn)              (delete (~> (from cache:series #:as s)                          (where (= s.page ,here-page)))))  (void   (insert-one! (cache-conn)                (make-cache:series                 #:page (string->symbol here-page)                 #:title (hash-ref (current-metas) 'title)                 #:published (hash-ref (current-metas) 'published "")                 #:noun-plural (hash-ref (current-metas) 'noun-plural "")                 #:noun-singular (hash-ref (current-metas) 'noun-singular ""))))) | 
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
 | 
250
251
252
253
254
255
256
 | 
  (query-exec (cache-conn) (delete (~> (from cache:index-entry #:as entry)
                                       (where (= entry.page ,(symbol->string pagenode))))))
  (unless (null? entry-txs)
    (void
     (apply insert! (cache-conn)
            (for/list ([etx (in-list entry-txs)])
              (txexpr->index-entry etx pagenode))))))
 | 
Modified dust.rkt
from [eb603279]
to [aa082dfb].
| 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 | 
#lang racket/base
; SPDX-License-Identifier: BlueOak-1.0.0
; This file is licensed under the Blue Oak Model License 1.0.0.
(require pollen/core
         pollen/pagetree
         pollen/setup
         pollen/file
         net/uri-codec
         file/sha1
         gregor
         txexpr
         racket/list
         racket/match
         racket/port
         racket/system
         racket/string)
;; Provides common helper functions used throughout the project
(provide maybe-meta     ; Select from (current-metas) or default value ("") if not available
         maybe-attr     ; Return an attribute’s value or a default ("") if not available
         here-output-path
         here-source-path
         here-id
         listing-context
         serieinvalidate-series
         checked-in?
         make-tag-predicate
         tx-strs
         ymd->english
         ymd->dateformat
         default-authornames-metas-noun    ; Retrieve noun-singular from current 'series meta, or""series-metas-title   ; Retrieve title of series in current 'series meta, or""metas-series-pagenode | 
>
>
|
|
|
 | 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 | 
#lang racket/base
; SPDX-License-Identifier: BlueOak-1.0.0
; This file is licensed under the Blue Oak Model License 1.0.0.
(require pollen/core
         "series-list.rkt"
         pollen/pagetree
         pollen/setup
         pollen/file
         net/uri-codec
         threading
         file/sha1
         gregor
         txexpr
         racket/list
         racket/match
         racket/port
         racket/system
         racket/string)
;; Provides common helper functions used throughout the project
(provide maybe-meta     ; Select from (current-metas) or default value ("") if not available
         maybe-attr     ; Return an attribute’s value or a default ("") if not available
         here-output-path
         here-source-path
         here-id
         listing-context
         current-series-noun    ; Retrieve noun-singular from current 'series meta, or #f
         current-series-title   ; Retrieve title of series in current 'series meta, or #f
         current-series-pagenode
         invalidate-series
         checked-in?
         make-tag-predicate
         tx-strs
         ymd->english
         ymd->dateformat
         default-authorname
 | 
| ︙ |  |  | ︙ |  | 
| 
77
78
79
80
81
82
83
84
85
86
87
88
89
9091
92
93
94
95
9697
98
99
100
101
102
103
104
105
106
107
108 | 
(define (here-output-path)
  (->output-path (here-source-path)))
(define listing-context (make-parameter ""))
;; Checks current-metas for a 'series meta and returns the pagenode of that series,
;; or '|| if no series is specified.
(define (metas-series-pagenode)
  (define maybe-series (or (select-from-metas 'series(current-metas)) ""))  (cond[(non-empty-string? maybe-series)(->pagenode(format "~a/~a.html" series-foldermaybe-series))]    [else '||]))(define (series-metas-noun)
  (define series-pnode(metas-series-pagenode)) (case series-pnode['||""]; noseriesspecified[else (or (select-from-metas 'noun-singular series-pnode) "")]))(define (series-metas-title)
  (define series-pnode(metas-series-pagenode))   (define article-ids (make-hash))
;; Generates a short ID for the current article
(define (here-id [suffix #f])
  (define maybe-hash (hash-ref article-ids (here-output-path) #f))
  (define here-hash(caseseries-pnode['||""]; noseries specified[else (or (select-from-metas 'title series-pnode) "")])) | 
|
|
<
|
|
>
|
|
|
|
|
|
>
|
|
>
|
|
|
 | 
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
 | 
(define (here-output-path)
  (->output-path (here-source-path)))
(define listing-context (make-parameter ""))
;; Checks current-metas for a 'series meta and returns the pagenode of that series,
;; or '|| if no series is specified.
(define (current-series-pagenode)
  (or (and~> (current-metas)
             (hash-ref 'series #f)
             (format "~a/~a.html" series-folder _)
             ->pagenode)
      '||))
(define (current-series-noun)
  (or (and~> (current-metas)
             (hash-ref 'series #f)
             (hash-ref series-list _ #f)
             series-noun-singular)
      ""))
(define (current-series-title)
  (or (and~> (current-metas)
             (hash-ref 'series #f)
             (hash-ref series-list _ #f)
             series-title)
      ""))
(define article-ids (make-hash))
;; Generates a short ID for the current article
(define (here-id [suffix #f])
  (define maybe-hash (hash-ref article-ids (here-output-path) #f))
  (define here-hash
 | 
| ︙ |  |  | ︙ |  | 
Modified makefile
from [fae17d31]
to [7107d1ff].
| 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | 
# SPDX-License-Identifier: BlueOak-1.0.0
# This file is licensed under the Blue Oak Model License 1.0.0.
SHELL = /bin/bash
# ~~~ Variables used by rules ~~~
#
core-files := pollen.rkt dust.rkt
html-deps  := snippets-html.rkt tags-html.rkt crystalize.rkt cache.rkt
article-sources := $(wildcard articles/*.poly.pm)
articles-html   := $(patsubst %.poly.pm, %.html, $(article-sources))
articles-pdf    := $(patsubst %.poly.pm, %.pdf,  $(article-sources))
series-sources  := $(wildcard series/*.poly.pm)
series-html     := $(patsubst %.poly.pm, %.html, $(series-sources)) | 
|
 | 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 | 
# SPDX-License-Identifier: BlueOak-1.0.0
# This file is licensed under the Blue Oak Model License 1.0.0.
SHELL = /bin/bash
# ~~~ Variables used by rules ~~~
#
core-files := pollen.rkt dust.rkt
html-deps  := snippets-html.rkt tags-html.rkt crystalize.rkt cache.rkt series-list.rkt
article-sources := $(wildcard articles/*.poly.pm)
articles-html   := $(patsubst %.poly.pm, %.html, $(article-sources))
articles-pdf    := $(patsubst %.poly.pm, %.pdf,  $(article-sources))
series-sources  := $(wildcard series/*.poly.pm)
series-html     := $(patsubst %.poly.pm, %.html, $(series-sources))
 | 
| ︙ |  |  | ︙ |  | 
Modified pollen.rkt
from [ecc1875a]
to [0c603aac].
| ︙ |  |  | ︙ |  | 
| 
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
 | 
  (define block-tags (append '(title style dt note) default-block-tags))
  (define-runtime-path tags-html.rkt     "tags-html.rkt")
  (define-runtime-path snippets-html.rkt "snippets-html.rkt")
  (define-runtime-path dust.rkt          "dust.rkt")
  (define-runtime-path crystalize.rkt    "crystalize.rkt")
  (define-runtime-path cache.rkt         "cache.rkt")
  (define cache-watchlist
    (map resolve-module-path
         (list tags-html.rkt
               snippets-html.rkt
               dust.rkt
               cache.rkt
               crystalize.rkt))))
;; Macro for defining tag functions that automatically branch based on the 
;; current output format and the list of poly-targets in the setup module.
;; Use this macro when you know you will need keyword arguments.
;;
(define-syntax (poly-branch-kwargs-tag stx)
 | 
>
>
 | 
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
 | 
  (define block-tags (append '(title style dt note) default-block-tags))
  (define-runtime-path tags-html.rkt     "tags-html.rkt")
  (define-runtime-path snippets-html.rkt "snippets-html.rkt")
  (define-runtime-path dust.rkt          "dust.rkt")
  (define-runtime-path crystalize.rkt    "crystalize.rkt")
  (define-runtime-path cache.rkt         "cache.rkt")
  (define-runtime-path series-list.rkt   "series-list.rkt")
  (define cache-watchlist
    (map resolve-module-path
         (list tags-html.rkt
               snippets-html.rkt
               dust.rkt
               cache.rkt
               series-list.rkt
               crystalize.rkt))))
;; Macro for defining tag functions that automatically branch based on the 
;; current output format and the list of poly-targets in the setup module.
;; Use this macro when you know you will need keyword arguments.
;;
(define-syntax (poly-branch-kwargs-tag stx)
 | 
| ︙ |  |  | ︙ |  | 
Added series-list.rkt version [88c1de55].
| 
 | 
 | 
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
 | 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 | 
#lang racket/base
; SPDX-License-Identifier: BlueOak-1.0.0
; This file is licensed under the Blue Oak Model License 1.0.0.
;; Provides fast metadata for series.
;; TO MAKE A NEW SERIES:
;;   1. Create series/my-key.poly.pm
;;   2. Add an entry for my-key to series-list below
;;   3. Use ◊define-meta[series "my-key"] in articles to add them to the series.
;;   4. If ptree-ordered is #t, also create series/my-key.ptree
(require racket/list)
(struct series (key title noun-plural noun-singular ptree-ordered?))
(define series-list
  (make-immutable-hash
   (list
   ;; ------- DEFINE SERIES HERE -----------
            ; Key               Title              plural noun    singular noun phrase
   (+series "marquee-fiction"   "Marquee Fiction" "inventions"    "an invention"         #f)
   )))
(define (series-grouped-list)
  (group-by series-noun-plural (hash-values series-list)))
;; Quick macro to save a little typing
(define-syntax-rule (+series key title plural singular ptree)
  (cons key (series key title plural singular ptree)))
(provide (struct-out series)
         series-list
         series-grouped-list)
 | 
Modified series/template.html.p
from [7a674800]
to [7e883695].
| 
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | 
<!DOCTYPE html>
<html lang="en">
◊html$-page-head[(select-from-metas 'title metas)]
◊html$-page-body-open["series-page"]
◊(unfence (->html doc #:splice? #t))
◊html$-page-body-close[]
</html>◊cache-series![] | 
<
 | 
1
2
3
4
5
6
7
8
9
10
11
12
13
 | 
<!DOCTYPE html>
<html lang="en">
◊html$-page-head[(select-from-metas 'title metas)]
◊html$-page-body-open["series-page"]
◊(unfence (->html doc #:splice? #t))
◊html$-page-body-close[]
</html>
 | 
Modified snippets-html.rkt
from [79ce1a10]
to [9c1944e9].
| ︙ |  |  | ︙ |  | 
| 
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 | 
         pollen/decode
         pollen/private/version
         racket/string
         racket/function
         racket/list
         txexpr
         "cache.rkt"
         "dust.rkt")
(provide html$-page-head
         html$-page-body-open
         html$-series-list
         html$-article-open
         html$-article-close
 | 
>
 | 
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 | 
         pollen/decode
         pollen/private/version
         racket/string
         racket/function
         racket/list
         txexpr
         "cache.rkt"
         "series-list.rkt"
         "dust.rkt")
(provide html$-page-head
         html$-page-body-open
         html$-series-list
         html$-article-open
         html$-article-close
 | 
| ︙ |  |  | ︙ |  | 
| 
236
237
238
239
240
241
242
243
244
245
246
247
248249
250 | 
    (if (eq? pagecount pagenum)
        "<li class=\"nav-text inactive-link\">Older→</li>"
        (page-func (+ pagenum 1) "Older →" "nav-text")))
  (string-join `(,prev-link ,@page-group ,next-link)))
(define (series->txpr s)
  `(li (a [[href ,(string-append web-root ((define (html$-series-list)
  (define series-list-items
    (for/list ([group (in-list (series-grouped-list))])symbol->string (cache:series-pages)))]]
          (i ,(cache:series-title s)))))      `(div (h2 ,((->html `(section [[class "column-list"] [style "margin-top: 1.3rem"]] ,@series-list-items)))cache:series-noun-plural (first group))) (ul ,@(map series->txpr group))))) | 
|
|
|
 | 
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
 | 
    (if (eq? pagecount pagenum)
        "<li class=\"nav-text inactive-link\">Older→</li>"
        (page-func (+ pagenum 1) "Older →" "nav-text")))
  (string-join `(,prev-link ,@page-group ,next-link)))
(define (series->txpr s)
  `(li (a [[href ,(string-append web-root (format "~a/~a.html" series-folder (series-key s)))]]
          (i ,(series-title s)))))
(define (html$-series-list)
  (define series-list-items
    (for/list ([group (in-list (series-grouped-list))])
      `(div (h2 ,(series-noun-plural (first group))) (ul ,@(map series->txpr group)))))
  (->html `(section [[class "column-list"] [style "margin-top: 1.3rem"]] ,@series-list-items)))
 | 
Modified util/init.rkt
from [41c57f81]
to [ae86fdec].
| 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | 
#lang racket/base
(require racket/file
         pollen/setup
         "../cache.rkt"
         "../snippets-html.rkt")
(provide main)
(define (main)
  (init-cache-db!)
(display-to-file (html$-page-footer)
                   (build-path (current-project-root) "scribbled" "site-footer.html")
                   #:exists 'replace))  (preheat-series!) | 
<
 | 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 | 
#lang racket/base
(require racket/file
         pollen/setup
         "../cache.rkt"
         "../snippets-html.rkt")
(provide main)
(define (main)
  (init-cache-db!)
  
  (display-to-file (html$-page-footer)
                   (build-path (current-project-root) "scribbled" "site-footer.html")
                   #:exists 'replace))
 |