OILS / build / wiki.ysh View on Github | oils.pub

224 lines, 85 significant
1#!/usr/bin/env ysh
2#
3# Script to build and deploy the wiki to pages.oils.pub
4# (oils-for-unix.github.io). This is used for the dev guide.
5#
6# # Usage:
7#
8# build/wiki.ysh render
9# build/wiki.ysh build-search-index
10# build/wiki.ysh local-serve
11# build/wiki.ysh commit-push
12# build/wiki.ysh commit-push $customGitUrl
13#
14# # Action: render
15#
16# This will clone the oils-for-unix/oils wiki, and render all of the markdown
17# files using doc tools. The docs are saved to _tmp/wiki/out.
18#
19# # Action: build-search-index
20#
21# This will download the pagefind tool, and run it over the wiki built in
22# build-search-index. This is used for our static wiki-wide search.
23#
24# Pagefind Docs: https://pagefind.app/docs/
25#
26# # Action: local-serve
27#
28# Run a server with the current build locally. This will also copy the contents
29# of web/ into the build folder so that CSS is present in the preview.
30#
31# # Action: commit-push
32#
33# This will get the latest oils-for-unix/oils-for-unix.github.io, copy the wiki
34# build into the clone and then commit + push it.
35#
36# This requires an environment variable to be set (usually in GitHub Actions
37# secrets): `OILS_PAGES_GITHUB_TOKEN`. This is a PAT with `content: write`
38# permissions to the oils-for-unix.github.io repo.
39#
40# Passing a custom git url as a positional argument removes the need for a PAT.
41# It can be used to target a different repository for testing.
42
43const WIKI_OUT_DIR = '_tmp/wiki/out'
44const WIKI_DIR = '_tmp/wiki/git'
45const PAGES_DIR = '_tmp/wiki/oils-for-unix.github.io'
46
47proc pull-latest(dir, repo) {
48 ## Pull the latest commit from $repo to $dir. Will clone if necessary
49
50 if test -d $dir {
51 echo "$repo already cloned to $dir, pulling latest"
52
53 cd $dir {
54 git pull
55 }
56
57 return
58 }
59
60 echo "Cloning $repo to $dir"
61 mkdir -p $dir
62 git clone $repo $dir
63}
64
65
66func slugify(s) {
67 return (s.replace(" ", "-").replace(",", " "))
68}
69
70proc pre-render-wikilinks() {
71 ## GitHub wikis have a unique [[link syntax]] which references topic within
72 ## the wiki.
73 ##
74 ## This function converts that syntax to the traditional
75 ## [link syntax](./link-syntax.html) which will render correctly once fed to
76 ## doctools.
77 for line in (io.stdin) {
78 var mdlink = line.replace(/ '[[' <capture ![']']* as link> ']]' /,
79 ^"[$link]($[slugify(link)].html)")
80 write -- $[mdlink]
81 }
82}
83
84proc render-one(path) {
85 mkdir -p $WIKI_OUT_DIR
86
87 var name = path.replace(/ %start dot* '/' <capture dot* as name> '.md' /, ^"$[slugify(name)]")
88 var title = name.replace('-', ' ')
89 var dest = "$WIKI_OUT_DIR/$name.html"
90
91 fopen >$dest {
92 echo """
93 <!DOCTYPE html>
94 <html>
95 <head>
96 <meta name="viewport" content="width=device-width, initial-scale=1">
97 <title>$title</title>
98
99 <link rel="stylesheet" type="text/css" href="../web/base.css" />
100 <link rel="stylesheet" type="text/css" href="./search.css" />
101 </head>
102 <body class="width40">
103
104 <div id="search"></div>
105 <hr>
106 """
107
108 pre-render-wikilinks <$path | cmark
109
110 echo '''
111 <script src="./pagefind/pagefind-ui.js"></script>
112 <script>
113 window.addEventListener('DOMContentLoaded', (event) => {
114 new PagefindUI({ element: "#search", showSubResults: true });
115 });
116 </script>
117 </body>
118 </html>
119 '''
120 }
121}
122
123proc build-search-index() {
124 python3 -m pip install 'pagefind[extended]'
125 python3 -m pagefind --site $WIKI_OUT_DIR
126}
127
128
129proc render() {
130 ## Pull the latest version of the wiki and render it
131
132 pull-latest $WIKI_DIR https://github.com/oils-for-unix/oils.wiki.git
133 find $WIKI_DIR -name '*.md' -print0 | xargs -I {} -0 -- $0 render-one {}
134
135 fopen >$WIKI_OUT_DIR/search.css {
136 echo '''
137 #search > div {
138 margin-top: 8px;
139 width: 100%;
140 }
141
142 #search input[type=text], #search button {
143 padding: 4px 8px;
144
145 background-color: #EEE;
146 color: #444;
147 }
148
149 /* We cannot control the search UI, so manually calculate widths for sizing */
150 #search input {
151 padding-right: 4px !important; /* Pagefind likes to add a large padding here, disable it */
152
153 width: calc(100%
154 - max(10%, 50px) /* button width */
155 - 20px /* margins */);
156
157 border: 1px solid #EEE;
158 }
159
160 #search button {
161 width: calc(max(10%, 50px));
162
163 border: 1px solid #AAA;
164 }
165
166 /* This is the load more results button */
167 #search .pagefind-ui__drawer button {
168 margin-left: 0;
169 margin-right: 0;
170 width: 100%;
171 }
172 '''
173 }
174}
175
176
177proc local-preview() {
178 cp -r web $WIKI_OUT_DIR/..
179
180 python3 -m http.server -d $WIKI_OUT_DIR/..
181}
182
183
184proc commit-push(customGitUrl="") {
185 ## Commit and push the most recent build to oils-for-unix.github.io
186 ##
187 ## When a customGitUrl is passed, push to that repo instead.
188
189 var GIT_URL
190 if (customGitUrl) {
191 setvar GIT_URL = customGitUrl
192 } else {
193 var PAT = ENV.OILS_PAGES_GITHUB_TOKEN
194 setvar GIT_URL = gitUrl or "https://x-access-token:$PAT@github.com/oils-for-unix/oils-for-unix.github.io.git"
195 }
196
197 rm -rf $PAGES_DIR
198 pull-latest $PAGES_DIR $GIT_URL
199
200 # Stash and pending changes (there should be none)
201 cd $PAGES_DIR {
202 git add .
203 git stash
204 }
205
206 # Update the wiki
207 rm -rf $PAGES_DIR/wiki
208 cp -r $WIKI_OUT_DIR $PAGES_DIR/wiki
209
210 cd $PAGES_DIR {
211 git add wiki
212
213 if git diff --quiet --staged {
214 echo 'No changes, will not commit'
215 } else {
216 var date = $(date --rfc-email)
217 git commit -m "Bump wiki $date"
218 git push
219 }
220 }
221}
222
223
224runproc @ARGV