◊(Local Yarn Code "Check-in [6c254e3e]")

Overview
Comment:Add version control links to articles ([678cc6aeca1d9d31])
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 6c254e3e611df5d0cc16046f24ea32e7a70e899db7d3dc253fc3eb28278f3985
User & Date: joel on 2020-03-14 20:21:53
Other Links: manifest | tags
Context
2020-03-14
20:48
Add quote from Thomas Macaulay check-in: 7047176b user: joel tags: trunk, content
20:21
Add version control links to articles ([678cc6aeca1d9d31]) check-in: 6c254e3e user: joel tags: trunk
00:20
Add ‘Quarantine Without Children’ check-in: ea197535 user: joel tags: trunk, content
Changes

Modified code-docs/dust.scrbl from [73710a17] to [ed5349c7].

56
57
58
59
60
61
62
63

64
65
66

67











68
69
70
71
72
73
74
              @defproc[(series-pagetree) pagetree?])]

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

@defproc[(here-output-path) path?]


Returns the path to the current output file, relative to @racket[current-project-root]. If no metas
are available, returns @racket[(string->path ".")]. This is like what you can get from the @tt{here}

variable that Pollen provides, except it is available outside templates.












@defproc[(here-id [suffix (or/c (listof string?) string? #f) #f]) string?]

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








|
>

|
|
>
|
>
>
>
>
>
>
>
>
>
>
>







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
              @defproc[(series-pagetree) pagetree?])]

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

@deftogether[(@defproc[(here-output-path) path?]
              @defproc[(here-source-path) path?])]{

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

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

}

@defproc[(checked-in?) boolean?]{

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

}

@defproc[(here-id [suffix (or/c (listof string?) string? #f) #f]) string?]

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

Modified dust.rkt from [bed6133b] to [eb603279].

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
         pollen/setup
         pollen/file
         net/uri-codec
         file/sha1
         gregor
         txexpr
         racket/list


         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-id
         listing-context
         series-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
         invalidate-series

         make-tag-predicate
         tx-strs
         ymd->english
         ymd->dateformat
         default-authorname
         default-title
         web-root







>
>








>






>







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
         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
         series-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
         invalidate-series
         checked-in?
         make-tag-predicate
         tx-strs
         ymd->english
         ymd->dateformat
         default-authorname
         default-title
         web-root
52
53
54
55
56
57
58










59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

(define (default-title body-txprs)
  (format "“~a…”" (first-words body-txprs 5)))

(define (maybe-meta m [missing ""])
  (cond [(current-metas) (or (select-from-metas m (current-metas)) missing)]
        [else missing]))











;; Return the current output path, relative to (current-project-root)
;; Similar to the variable 'here' which is only accessible in Pollen templates,
;; except this is an actual path, not a string.
(define (here-output-path)
  (cond [(current-metas)
         (define-values (_ rel-path-parts)
           (drop-common-prefix (explode-path (current-project-root))
                               (explode-path (string->path (select-from-metas 'here-path (current-metas))))))
         (->output-path (apply build-path rel-path-parts))]
        [else (string->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)) ""))







>
>
>
>
>
>
>
>
>
>





<
<
<
<
|
<







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77




78

79
80
81
82
83
84
85

(define (default-title body-txprs)
  (format "“~a…”" (first-words body-txprs 5)))

(define (maybe-meta m [missing ""])
  (cond [(current-metas) (or (select-from-metas m (current-metas)) missing)]
        [else missing]))

;; Return the current source path, relative to (current-project-root)
(define (here-source-path)
  (match (current-metas)
    [(? hash? m)
     (define-values (_ rel-path-parts)
       (drop-common-prefix (explode-path (current-project-root))
                           (explode-path (string->path (hash-ref m 'here-path)))))
     (apply build-path rel-path-parts)]
    [_ (string->path ".")]))

;; Return the current output path, relative to (current-project-root)
;; Similar to the variable 'here' which is only accessible in Pollen templates,
;; except this is an actual path, not a string.
(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)) ""))
115
116
117
118
119
120
121










122
123
124
125
126
127
128
    (define series-file (build-path (current-project-root)
                                    series-folder
                                    (format "~a.poly.pm" series-name)))
    (when (file-exists? series-file)
      (case (system-type 'os)
        [(windows) (system (format "type nul >> ~a" series-file))]
        [else (system (format "touch ~a" series-file))]))))











;; ~~~ Project-wide Pagetrees ~~~

(define (include-in-pagetree folder extension)
  (define (matching-file? f)
    (string-suffix? f extension))
  (define (file->output-pagenode f)







>
>
>
>
>
>
>
>
>
>







124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
    (define series-file (build-path (current-project-root)
                                    series-folder
                                    (format "~a.poly.pm" series-name)))
    (when (file-exists? series-file)
      (case (system-type 'os)
        [(windows) (system (format "type nul >> ~a" series-file))]
        [else (system (format "touch ~a" series-file))]))))

;; Determine if the current article has been checked into Fossil repo
(define (checked-in?)
  (cond [(current-metas)
         (define articles-path (build-path (current-project-root) articles-folder))
         (define checked-in
           (with-output-to-string
             (lambda () (system (format "/usr/local/bin/fossil ls ~a" articles-path)))))
         (string-contains? checked-in (path->string (here-source-path)))]
        [else #f]))

;; ~~~ Project-wide Pagetrees ~~~

(define (include-in-pagetree folder extension)
  (define (matching-file? f)
    (string-suffix? f extension))
  (define (file->output-pagenode f)

Modified snippets-html.rkt from [9e18f871] to [b8d08650].

1
2
3
4
5
6
7

8
9
10
11
12
13
14
#lang pollen/mode racket/base

; SPDX-License-Identifier: BlueOak-1.0.0
; This file is licensed under the Blue Oak Model License 1.0.0.

;; Provides functions for displaying content in HTML templates.
(require pollen/template

         pollen/decode
         pollen/private/version
         racket/string
         racket/function
         racket/list
         txexpr
         "cache.rkt"







>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#lang pollen/mode racket/base

; SPDX-License-Identifier: BlueOak-1.0.0
; This file is licensed under the Blue Oak Model License 1.0.0.

;; Provides functions for displaying content in HTML templates.
(require pollen/template
         pollen/core
         pollen/decode
         pollen/private/version
         racket/string
         racket/function
         racket/list
         txexpr
         "cache.rkt"
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
  (define body-class (if (non-empty-string? class) (format " class=\"~a\"" class) ""))
  ◊string-append{<body◊|body-class|><main>
 <a href="/index.html"><header>
 <img src="/web-extra/mark.svg" alt="The Local Yarn" height="103" class="logo">
 <h1>The Local Yarn</h1>
 </header></a>})











(define (html$-article-open pagenode title? title-tx published)
  (cond
    [title?
     ◊string-append{<article class="with-title hentry">
      ◊(->html `(h1 [[class "entry-title"]] ,@(get-elements title-tx)))
      <p class="time"><a href="/◊(symbol->string pagenode)" class="rel-bookmark">
      <time datetime="◊published" class="published">◊ymd->english[published]</time>
      </a></p>

      <section class="entry-content">}]
    [else
     ◊string-append{<article class="no-title hentry">
      <h1><a href="/◊(symbol->string pagenode)" class="rel-bookmark">
      <time datetime="◊published" class="entry-title">◊ymd->english[published]</time>
      </a></h1>

      <section class="entry-content">}]))

(define (html$-article-close footertext)
  (cond [(non-empty-string? footertext)
         ◊string-append{</section>
          <footer class="article-info"><span class="x">(</span>◊|footertext|<span class="x">)</span></footer>
          </article>}]







>
>
>
>
>
>
>
>
>
>








>






>







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
75
76
77
78
79
80
81
82
  (define body-class (if (non-empty-string? class) (format " class=\"~a\"" class) ""))
  ◊string-append{<body◊|body-class|><main>
 <a href="/index.html"><header>
 <img src="/web-extra/mark.svg" alt="The Local Yarn" height="103" class="logo">
 <h1>The Local Yarn</h1>
 </header></a>})

(define (html$-repo-links)
  (define here (path->string (here-source-path)))
  (cond
    [(checked-in?)
     ◊string-append{<div class="scm-links">
      <a title="source" href="/code/file/◊here">&sect;</a>
      <a title="changes" href="/code/finfo?name=◊here">¢</a>
      </div>}]
    [else (format "<!-- ~a -->" here) ]))

(define (html$-article-open pagenode title? title-tx published)
  (cond
    [title?
     ◊string-append{<article class="with-title hentry">
      ◊(->html `(h1 [[class "entry-title"]] ,@(get-elements title-tx)))
      <p class="time"><a href="/◊(symbol->string pagenode)" class="rel-bookmark">
      <time datetime="◊published" class="published">◊ymd->english[published]</time>
      </a></p>
      ◊(html$-repo-links)
      <section class="entry-content">}]
    [else
     ◊string-append{<article class="no-title hentry">
      <h1><a href="/◊(symbol->string pagenode)" class="rel-bookmark">
      <time datetime="◊published" class="entry-title">◊ymd->english[published]</time>
      </a></h1>
      ◊(html$-repo-links)
      <section class="entry-content">}]))

(define (html$-article-close footertext)
  (cond [(non-empty-string? footertext)
         ◊string-append{</section>
          <footer class="article-info"><span class="x">(</span>◊|footertext|<span class="x">)</span></footer>
          </article>}]

Modified web-extra/martin.css.pp from [846cd06d] to [49239008].

391
392
393
394
395
396
397




















398
399
400
401
402
403
404
    color: ◊color-bodytext;
    font-size: ◊x-lineheight[1];
    line-height: ◊x-lineheight[1];
    text-align: center;
    display: block;
    margin: ◊x-lineheight[1] 0;
}





















p {
    margin: 0;
    text-indent: 0;
}

p + p {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
    color: ◊color-bodytext;
    font-size: ◊x-lineheight[1];
    line-height: ◊x-lineheight[1];
    text-align: center;
    display: block;
    margin: ◊x-lineheight[1] 0;
}

/* Fossil info links */
.scm-links { 
    color: #888;
    font-size: 0.5rem;
    white-space: nowrap;
    float: right;
    text-align: right;
    margin-top: -◊x-lineheight[2.01];
    padding-right: 1ch;
    font-family: ◊mono-font;
    font-style: italic;
}

.scm-links a {
    display: inline-block;
    text-align: center;
    width: 0.9rem;
    color: #727070;
}

p {
    margin: 0;
    text-indent: 0;
}

p + p {
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
        
        article {
            display: grid;
            grid-template-columns: 8rem 7fr 1fr;
            grid-template-rows: auto auto auto;
            grid-template-areas: 
               "corner title title"
               "margin main  .";
            align-items: start;     /* Puts everything at the top */
            margin-bottom: 0;
            grid-column-gap: 1rem;
            box-shadow: 0.4em 0.4em 10px #e3e3e3;
            background: white;
            border: solid 1px #dedede;
            border-radius: 2px;







|







837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
        
        article {
            display: grid;
            grid-template-columns: 8rem 7fr 1fr;
            grid-template-rows: auto auto auto;
            grid-template-areas: 
               "corner title title"
               "margin main rightmargin";
            align-items: start;     /* Puts everything at the top */
            margin-bottom: 0;
            grid-column-gap: 1rem;
            box-shadow: 0.4em 0.4em 10px #e3e3e3;
            background: white;
            border: solid 1px #dedede;
            border-radius: 2px;
863
864
865
866
867
868
869












870
871
872
873
874
875
876
            padding-left: 3px;
        }

        article.no-title footer.article-info {
            margin-top: 1.5rem;
            padding-top: 0;
        }












        
        section.entry-content {
            grid-area: main;
            /* Prevent content from overriding grid column sizing */
            /* See https://css-tricks.com/preventing-a-grid-blowout/ */
            min-width: 0;
        }







>
>
>
>
>
>
>
>
>
>
>
>







883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
            padding-left: 3px;
        }

        article.no-title footer.article-info {
            margin-top: 1.5rem;
            padding-top: 0;
        }

        .scm-links {
            float: none;
            grid-area: rightmargin;
            height: 100%;
        }

        .scm-links a:hover {
            color: #2176ff;
            background: none;
        }

        
        section.entry-content {
            grid-area: main;
            /* Prevent content from overriding grid column sizing */
            /* See https://css-tricks.com/preventing-a-grid-blowout/ */
            min-width: 0;
        }