◊(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
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.

@defproc[(here-output-path) path?]
@deftogether[(@defproc[(here-output-path) path?]
              @defproc[(here-source-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.
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
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
53
54
55
56
57
58
59










60
61
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76
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)
  (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))]
  (->output-path (here-source-path)))
        [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)) ""))
115
116
117
118
119
120
121










122
123
124
125
126
127
128
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
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
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
102
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
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
113
114
115







+
+
+
+
+
+
+
+
+
+








+






+












-
-
+
+




-
-
-
+
+
+



-
+





-
-
-
+
+
+







  (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>}]
        [else "</section></article>"]))

(define (html$-article-listing-short pagenode pubdate title)
  ◊string-append{
 <article class="short-listing"><a href="/◊(symbol->string pagenode)">
  <time datetime="◊pubdate" class="caps">◊(ymd->english pubdate)</time>
  <h3>◊|title|</h3>
 <time datetime="◊pubdate" class="caps">◊(ymd->english pubdate)</time>
 <h3>◊|title|</h3>
 </a></article>})

(define (html$-article-excerpt pagenode excerpt-tx)
  ◊string-append{
   ◊(->html excerpt-tx #:splice? #t)
   <p class="further-reading"><a href="◊|web-root|◊symbol->string[pagenode]">Read more…</a></p>
})
 ◊(->html excerpt-tx #:splice? #t)
 <p class="further-reading"><a href="◊|web-root|◊symbol->string[pagenode]">Read more…</a></p>
 })

(define (html$-page-footer)
  ◊string-append{
<footer id="main">
 <footer id="main">
 <p class="title">
 <img src="◊|web-root|web-extra/images/small-rule.png" width="145" height="11" alt="* * *" />
 <br>
 The Local Yarn</p>
 <nav><a href="/index.html">Home</a> •
    <a href="/blog-pg1.html">Blog</a> •
    <a href="/keyword-index.html">Keyword Index</a> •
    <a href="/code"><i><code>◊"◊"(Source&nbsp;Code)</code></i></a>
 <a href="/blog-pg1.html">Blog</a> •
 <a href="/keyword-index.html">Keyword Index</a> •
 <a href="/code"><i><code>◊"◊"(Source&nbsp;Code)</code></i></a>
 </nav>
 ◊(html$-series-list)
 </footer>})

(define (html$-page-body-close)
  ◊string-append{
 </main>

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

391
392
393
394
395
396
397




















398
399
400
401
402
403
404
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
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  .";
               "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
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;
        }