@@ -4,124 +4,46 @@ @; This file is licensed under the Blue Oak Model License 1.0.0. @(require "scribble-helpers.rkt") @(require (for-label "../pollen.rkt" - "../dust.rkt" "../crystalize.rkt" + "../cache.rkt" racket/base racket/contract racket/string - deta txexpr - pollen/template - pollen/pagetree - sugar/coerce)) + pollen/pagetree)) -@title{@filepath{crystalize.rkt}} +@title[#:tag "crystalize-rkt"]{Crystalize} @defmodule["crystalize.rkt" #:packages ()] -“Crystalizing” is an extra layer in between docs and templates that destructures the doc and stores -it in various pieces in a SQLite cache. Individual articles save chunks of rendered HTML to the -cache when their individual pages are rendered. When pulling together listings of articles in +“Crystalizing” is an extra layer in between docs and templates that destructures the @tt{doc} and +stores it in various pieces in a SQLite cache. Individual articles save chunks of rendered HTML to +the cache when their individual pages are rendered. When pulling together listings of articles in different contexts that need to be filtered and sorted, a SQL query is much faster than trolling through the Pollen cache for matching docs and regenerating the HTML. -@defproc[(init-cache-db!) void?] - -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. (The -file itself is created at the module level.) - -This function is called automatically in @filepath{pollen.rkt} whenever HTML is the target output. - -@defproc[(parse-and-cache-article! [pagenode pagenode?] [doc txexpr?]) non-empty-string?] - -Returns a string containing the HTML of @racket[_doc]. @margin-note{This is one function that breaks -my convention of using a prefix of @tt{html$-} for functions that return a single string of HTML.} - -Privately, it does a lot of other work. The article is analyzed, additional metadata is constructed, -and it is saved to the SQLite cache. 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 -in the doc, they are parsed and saved individually to the SQLite cache. 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. - -@deftogether[(@defproc[( - [query-func (-> any/c query?)] - [#:series series (or/c string? (listof string? boolean?)) #t] - [#:limit limit integer? -1] - [order stringish? 'desc]) txexpr?] - @defproc[( - [query-func (-> any/c query?)] - [#:series series (or/c string? (listof string? boolean?)) #t] - [#:limit limit integer? -1] - [order stringish? 'desc]) txexpr?] - @defproc[( - [query-func (-> any/c query?)] - [#:series series (or/c string? (listof string? boolean?)) #t] - [#:limit limit integer? -1] - [order stringish? 'desc]) txexpr?])] - -Fetches the HTML for items from the SQLite cache and returns the HTML strings fenced inside -a @racket['style] tagged X-expression. The items will be ordered by publish date according to -@racket[_order] and optionally limited to the series specified in @racket[_series]. - -The @racket[_query-func] should be either @racket[articles], which will create a listing of articles -only, or @racket[articles+notes], which will include notes intermingled with articles. - -@margin-note{Note that the signature shown for the @racket[_query-func] argument above is -incomplete. If you choose to pass a function other than @racket[articles] or -@racket[articles+notes], you must use a function with exactly the same signature as those -functions.} - -If @racket[_series] expression evaluates to @racket[#f], articles will not be filtered by series. If -it evaluates to @racket[#t] (the default), articles will be filtered by those that specify the -current output of @racket[here-output-path] in their @tt{series_pagenode} column in the SQLite -cache. If a string is supplied, articles will be filtered by those containing that exact value in -their @tt{series_pagenode} column in the SQLite cache. - -The @racket[_order] expression must evaluate to either @racket["ASC"] or @racket["DESC"] and the -@racket[_limit] expressions must evaluate to a value suitable for use in the @tt{LIMIT} clause of -@ext-link["https://sqlite.org/lang_select.html"]{a SQLite @tt{SELECT} statement}. An expression that -evaluates to a negative integer (the default) is the same as having no limit. - -The reason for enclosing the results in a @racket['style] txexpr is to prevent the HTML from being -escaped by @racket[->html] in the template. This tag was picked for the job because there will -generally never be a need to include any actual CSS information inside a @tt{"] removed. -The contents of the style tags are left intact. - -Use this with strings returned from @racket[->html] when called on docs that use the -@racket[] tag function or its siblings. - -@defparam[current-plain-title non-empty-string? #:value "void"] - -Contains (or sets) the “plain” title (i.e., with no HTML markup) for the current article based on -analysis done by @racket[parse-and-cache-article!]. If the article did not specify a title, -a default title is supplied. If the article contained a @racket[note] that used the -@code{#:disposition} attribute, the disposition-mark may be included in the title. - -Note that this needs to be called @emph{after} @racket[parse-and-cache-article!] in order to get an -up-to-date value. +@margin-note{These functions are designed to be used within the template for articles and series, +respectively, so that the cache is updated precisely when the web page is rendered.} + +@defproc[(parse-and-cache-article! [pagenode pagenode?] [doc txexpr?]) non-empty-string?]{ + +Returns a string containing the HTML of @racket[_doc]. + +Privately, it does a lot of other work. The article is analyzed, additional metadata is constructed +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] +respectively). 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 on +a 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 empty +string is used. +}