@explorable-viz/fluid 0.7.101 → 0.7.103

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@explorable-viz/fluid",
3
- "version": "0.7.101",
3
+ "version": "0.7.103",
4
4
  "description": "Fluid is an experimental programming language which integrates a bidirectional dynamic analysis to connect outputs to data sources in a fine-grained way. Fluid is implemented in PureScript and runs in the browser.",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -25,6 +25,9 @@
25
25
  "script/util/clean.sh",
26
26
  "script/util/lisp-case.sh",
27
27
  "website/article",
28
+ "website/css",
29
+ "website/font",
30
+ "website/shared",
28
31
  "script/install-article.sh",
29
32
  "script/util/serve.sh"
30
33
  ],
@@ -22,6 +22,11 @@ PREFIX_=${PREFIX:+$PREFIX/}
22
22
  echo "Cleaning dist/$WEBSITE"
23
23
  . "${PREFIX_}script/util/clean.sh" $WEBSITE
24
24
 
25
+ for DIR in css font shared; do
26
+ echo "Processing $DIR files:"
27
+ cp -rL "website/$WEBSITE/$DIR" "dist/$WEBSITE/$DIR"
28
+ done
29
+
25
30
  shopt -s nullglob
26
31
 
27
32
  echo "Processing other static files:"
@@ -0,0 +1,357 @@
1
+ @charset "UTF-8";
2
+ @import url("https://fonts.googleapis.com/css2?family=Fira+Code&display=swap");
3
+ @import url('https://fonts.googleapis.com/css2?family=Ubuntu+Mono&display=swap');
4
+
5
+ @font-face {
6
+ font-family: 'OdiseanTech';
7
+ src: url('/font/OdiseanTech.woff2') format('woff2');
8
+ font-weight: normal;
9
+ font-style: normal;
10
+ }
11
+
12
+ @font-face {
13
+ font-family: 'GraphikLight';
14
+ src: url('/font/GraphikLight.woff2') format('woff2');
15
+ font-weight: 300;
16
+ font-style: normal;
17
+ }
18
+
19
+ @font-face {
20
+ font-family: 'GraphikLightItalic';
21
+ src: url('/font/GraphikLightItalic.woff2') format('woff2');
22
+ font-weight: 300;
23
+ font-style: italic;
24
+ }
25
+
26
+ @font-face {
27
+ font-family: 'GraphikMedium';
28
+ src: url('/font/GraphikMedium.woff2') format('woff2');
29
+ font-weight: 500;
30
+ font-style: normal;
31
+ }
32
+
33
+ @font-face {
34
+ font-family: 'GraphikMediumItalic';
35
+ src: url('/font/GraphikMediumItalic.woff2') format('woff2');
36
+ font-weight: 500;
37
+ font-style: italic;
38
+ }
39
+
40
+ .fluid-logo {
41
+ margin-bottom: 0;
42
+ }
43
+
44
+ .fluid-subtitle {
45
+ margin-bottom: 0;
46
+ margin-top: 0;
47
+ font-size: 12pt;
48
+ }
49
+
50
+ a:link {
51
+ color: darkslategray;
52
+ }
53
+
54
+ a:visited {
55
+ color: #004d40;
56
+ }
57
+
58
+ a:hover {
59
+ color: #009688;
60
+ }
61
+
62
+ a:active {
63
+ color: #003d33;
64
+ }
65
+
66
+ .right-justified {
67
+ margin-left: auto;
68
+ width: fit-content;
69
+ }
70
+
71
+ .nowrap {
72
+ white-space: nowrap;
73
+ }
74
+
75
+ code {
76
+ font-family: 'Ubuntu Mono', monospace;
77
+ }
78
+
79
+ body {
80
+ font-size: 12pt;
81
+ font-family: "GraphikLight", sans-serif;
82
+ font-weight: 300;
83
+ line-height: 1.25;
84
+ padding: 0;
85
+ margin: 0;
86
+ background-color: #FFFFFF;
87
+ color: #404040;
88
+ margin-bottom: 10em;
89
+ }
90
+
91
+ .para-text {
92
+ font-size: 9pt;
93
+ }
94
+
95
+ p {
96
+ margin-top: 1em;
97
+ margin-bottom: 1em;
98
+ }
99
+
100
+ p + p {
101
+ margin-top: 0;
102
+ }
103
+
104
+ svg {
105
+ overflow: visible;
106
+ }
107
+
108
+ .faq-question {
109
+ font-family: 'GraphikMedium';
110
+ color: darkslategrey;
111
+ }
112
+
113
+ .highlight {
114
+ font-family: 'GraphikMedium';
115
+ }
116
+
117
+ .align-right {
118
+ text-align: right;
119
+ }
120
+
121
+ h2 {
122
+ font-size: 18pt;
123
+ }
124
+
125
+ h3 {
126
+ width: 100%;
127
+ font-size: 16pt;
128
+ font-weight: bold;
129
+ margin-top: 10pt;
130
+ margin-bottom: 4pt;
131
+ border-bottom: 0.5px solid lightgray;
132
+ }
133
+
134
+ h4 {
135
+ font-size: 16pt;
136
+ font-weight: bold;
137
+ margin-top: 0.4em;
138
+ margin-bottom: 0;
139
+ }
140
+
141
+ .sub-header * {
142
+ font-size: 16pt;
143
+ margin-bottom: 4px;
144
+ }
145
+
146
+ ul {
147
+ padding-left: 20px;
148
+ margin-top: 0;
149
+ margin-bottom: 0;
150
+ }
151
+
152
+ li {
153
+ margin-bottom: 1ex;
154
+ }
155
+
156
+ li:last-child {
157
+ margin-bottom: 0;
158
+ }
159
+
160
+ .table-caption {
161
+ text-align: left;
162
+ }
163
+
164
+ nav ul {
165
+ padding-left: 0;
166
+ list-style: none;
167
+ }
168
+
169
+ nav ul li {
170
+ float: left;
171
+ overflow: hidden;
172
+ margin-bottom: 0;
173
+ }
174
+
175
+ nav ul li:not(:last-child)::after {
176
+ content: "•";
177
+ margin-right: 5px;
178
+ margin-left: 5px;
179
+ }
180
+
181
+ nav ul li.active-page a {
182
+ pointer-events: none;
183
+ color: inherit;
184
+ text-decoration: none;
185
+ cursor: default;
186
+ font-weight: bold;
187
+ color: rgb(135, 129, 255);
188
+ }
189
+
190
+ .cm-editor {
191
+ background: #2D2D2D;
192
+ color: #F0F0F0;
193
+ }
194
+
195
+ .cm-line {
196
+ font-family: 'Ubuntu Mono';
197
+ font-size: 10pt;
198
+ }
199
+
200
+ .cm-gutter {
201
+ background-color: #232323;
202
+ }
203
+
204
+ .cm-gutterElement {
205
+ font-family: 'Ubuntu Mono';
206
+ font-size: 10pt;
207
+ color: #88C0D0;
208
+ }
209
+
210
+ .right-border {
211
+ border-right: 0.5px solid lightgray;
212
+ padding-right: 6px;
213
+ }
214
+
215
+ .right-border + div {
216
+ padding-left: 4px
217
+ }
218
+
219
+ .header-grid-container {
220
+ display: grid;
221
+ background-color: #f0f0f0;
222
+ width: 100%;
223
+ grid-template-columns: 30% 1fr;
224
+ padding-top: 7px;
225
+ padding-bottom: 7px;
226
+ }
227
+
228
+ .footer-grid-container {
229
+ display: grid;
230
+ background-color: #f0f0f0;
231
+ width: 100%;
232
+ grid-template-columns: 30% 1fr;
233
+ margin-top: 10px;
234
+ }
235
+
236
+ :root {
237
+ --toggle-button-width: 24px;
238
+ --text-pane-width: 800px;
239
+ }
240
+
241
+ .grid-container {
242
+ display: grid;
243
+ grid-template-columns: auto var(--toggle-button-width) var(--text-pane-width);
244
+ justify-content: center;
245
+ }
246
+
247
+ .grid-container.data-pane-hidden {
248
+ grid-template-columns: 0 var(--toggle-button-width) var(--text-pane-width);
249
+ }
250
+
251
+ .grid-container.double-size {
252
+ max-width: 66.7vw; /* undo effect of transform: scale(1.5) for layout purposes */
253
+ }
254
+
255
+ .grid-container > :last-child {
256
+ padding-right: 10px;
257
+ }
258
+
259
+ .flex-bottom-align {
260
+ display: flex;
261
+ flex-direction: row;
262
+ }
263
+
264
+ .flex-bottom-align:first-child {
265
+ margin-top: auto;
266
+ }
267
+
268
+ .flex-left-align {
269
+ display: flex;
270
+ flex-direction: column;
271
+ align-items: start;
272
+ }
273
+
274
+ .flex-right-align {
275
+ display: flex;
276
+ flex-direction: column;
277
+ align-items: flex-end;
278
+ }
279
+
280
+ .flex-top-align {
281
+ display: flex;
282
+ flex-direction: row;
283
+ align-items: flex-start;
284
+ }
285
+
286
+ .flex-bottom-align {
287
+ display: flex;
288
+ flex-direction: row;
289
+ align-items: flex-end;
290
+ }
291
+
292
+ .data-pane-button {
293
+ font-size: 10pt;
294
+ }
295
+
296
+ .toggle-button {
297
+ color: #CCCCCC;
298
+ user-select: none;
299
+ }
300
+
301
+ .toggle-button:hover {
302
+ color: #999999;
303
+ cursor: pointer;
304
+ }
305
+
306
+ .data-pane-column {
307
+ border-right: 1px dotted #CCCCCC;
308
+ }
309
+
310
+ .data-pane-hidden .data-pane {
311
+ visibility: hidden;
312
+ }
313
+
314
+ .data-pane-hidden .data-pane * {
315
+ display: none;
316
+ }
317
+
318
+ .data-pane * {
319
+ font-size: 10pt;
320
+ }
321
+
322
+ .data-pane p {
323
+ margin-right: 3px;
324
+ }
325
+
326
+ /* Not actually double-size any more.. */
327
+ .double-size {
328
+ transform: scale(1.5);
329
+ transform-origin: top;
330
+ --text-pane-width: 600px;
331
+ }
332
+
333
+ body.standalone {
334
+ height: 100%;
335
+ display: grid;
336
+ justify-items: center;
337
+ align-items: start;
338
+ }
339
+
340
+ /* Needed for contained height specifications to work */
341
+ html {
342
+ height: 100%;
343
+ }
344
+
345
+ @keyframes fadeIn {
346
+ from { opacity: 0; }
347
+ to { opacity: 1; }
348
+ }
349
+
350
+ .fig-loading:only-child {
351
+ color: fuchsia;
352
+ animation: fadeIn 2s ease-in-out infinite alternate;
353
+ }
354
+
355
+ .fig-loading:not(:only-child) {
356
+ display: none;
357
+ }
@@ -0,0 +1,190 @@
1
+ .legend-box {
2
+ stroke: lightgray;
3
+ stroke-width: 0.5px;
4
+ fill: none;
5
+ }
6
+
7
+ .legend-text {
8
+ font-size: 9pt;
9
+ }
10
+
11
+ .title-text {
12
+ fill: Black;
13
+ font-size: 9pt;
14
+ }
15
+
16
+ .table-view th {
17
+ font-size: 11px;
18
+ text-align: left;
19
+ border-bottom: 'thin solid';
20
+ }
21
+
22
+ .table-view td {
23
+ font-size: 11px;
24
+ }
25
+
26
+ .table-view td:nth-child(1) {
27
+ color: lightgray;
28
+ }
29
+
30
+ table {
31
+ border-collapse: collapse;
32
+ }
33
+
34
+ thead {
35
+ border-top: 0.5px solid lightgray;
36
+ }
37
+
38
+ .table-cell {
39
+ border-radius: 0px;
40
+ }
41
+
42
+ td.table-cell {
43
+ background-color: white;
44
+ }
45
+
46
+ .table-cell.inert {
47
+ color: lightgrey;
48
+ }
49
+
50
+ .table-cell.selected-primary-persistent {
51
+ background-color: #93E9BE;
52
+ }
53
+
54
+ .table-cell.selected-secondary-persistent {
55
+ background-color: rgb(226, 226, 226);
56
+ }
57
+
58
+ .table-cell.selected-primary-transient {
59
+ color: blue;
60
+ font-weight: 600;
61
+ }
62
+
63
+ .table-cell.selected-secondary-transient {
64
+ /* color: royalblue; */
65
+ }
66
+
67
+ .table-row {
68
+ display: table-row;
69
+ }
70
+
71
+ .table-row.hidden {
72
+ visibility: collapse;
73
+ }
74
+
75
+ /* hack to match Safari-only */
76
+ @supports (hanging-punctuation: first) and (font: -apple-system-body) and (-webkit-appearance: none) {
77
+ .table-row.hidden {
78
+ display: none; /* suboptimal for table rows but Safari doesn't support visibility: collapse */
79
+ }
80
+ }
81
+
82
+ .linked-text {
83
+ border-radius: 0px;
84
+ background-color: White;
85
+ border-bottom-style: solid;
86
+ border-bottom-color: white;
87
+ border-bottom-width: 1px;
88
+ display: inline;
89
+ }
90
+
91
+ .linked-text.inert {
92
+ fill: lightgrey;
93
+ }
94
+
95
+ .linked-text.selected-primary-persistent {
96
+ background-color: #93E9BE;
97
+ }
98
+
99
+ .linked-text.selected-primary-transient {
100
+ border-bottom-color: blue;
101
+ }
102
+
103
+ .linked-text.selected-secondary-persistent {
104
+ background-color: rgb(226, 226, 226);
105
+ }
106
+
107
+ .linked-text.selected-secondary-transient {
108
+ border-bottom-color: lightblue;
109
+ }
110
+
111
+ .matrix-cell {
112
+ stroke: DarkGray;
113
+ fill: White;
114
+ }
115
+
116
+ .matrix-cell.inert {
117
+ stroke: DarkGray;
118
+ fill: rgb(185, 185, 185);
119
+ }
120
+
121
+ .matrix-cell.selected-primary-persistent {
122
+ fill: LightGreen;
123
+ }
124
+
125
+ .matrix-cell.selected-secondary-persistent {
126
+ fill: rgb(214, 240, 214)
127
+ }
128
+
129
+ .matrix-cell.selected-primary-transient {
130
+ }
131
+
132
+ .matrix-cell.selected-secondary-transient {
133
+ }
134
+
135
+ .matrix-cell-text {
136
+ font-size: 10pt;
137
+ font-family: "GraphikLight", sans-serif;
138
+ color: rgb(205, 205, 205)
139
+ }
140
+
141
+ .matrix-cell-text.selected-primary-persistent {
142
+ font-weight: 400;
143
+ color: darkgreen
144
+ }
145
+
146
+ .matrix-cell-text.selected-secondary-persistent {
147
+ color: green
148
+ }
149
+
150
+ .matrix-cell-text.selected-primary-transient {
151
+ font-weight: 400;
152
+ color: blue
153
+ }
154
+
155
+ .matrix-cell-text.selected-secondary-transient {
156
+ color: royalblue
157
+ }
158
+
159
+ .scatterplot-point {
160
+ fill: white;
161
+ stroke: black;
162
+ }
163
+
164
+ .scatterplot-point.inert {
165
+ fill: rgb(185,185,185);
166
+ stroke: black;
167
+ }
168
+
169
+ .scatterplot-point.selected-primary-persistent {
170
+ fill: LightGreen;
171
+ stroke: teal;
172
+ }
173
+
174
+ .scatterplot-point.selected-secondary-transient {
175
+ stroke: blue;
176
+ stroke-width: 1;
177
+ }
178
+
179
+ .scatterplot-point.selected-primary-transient {
180
+ stroke: blue;
181
+ stroke-width: 1;
182
+ }
183
+
184
+ .scatterplot-point.selected-secondary-persistent {
185
+ fill: rgb(226, 226, 226);
186
+ }
187
+
188
+ .scatterplot-point.selected-secondary-transient {
189
+ stroke-width: 1;
190
+ }
Binary file
Binary file
Binary file
@@ -0,0 +1,6 @@
1
+ <div class="footer-grid-container">
2
+ <div></div>
3
+ <div class="flex-left-align">
4
+ <p>© Fluid Contributors 2019–2025</p>
5
+ </div>
6
+ </div>
@@ -0,0 +1,27 @@
1
+ <div class="header-grid-container">
2
+ <div class="flex-right-align right-border">
3
+ <img class="fluid-logo" src="/image/fluid-logo.png" width="150px">
4
+ <h2 class="fluid-subtitle">explorable, self-explanatory research outputs</h2>
5
+ </div>
6
+ <div class="flex-left-align" style="justify-content: center; margin-left: 5px;">
7
+ <nav>
8
+ <ul>
9
+ <li><a href="https://github.com/explorable-viz/fluid">GitHub</a></li>
10
+ <li><a href="https://dl.acm.org/doi/10.1145/3498668">POPL 2022 paper</a></li>
11
+ <li><a href="https://www.youtube.com/watch?v=M_ePrtD9axk">POPL 2022 talk</a></li>
12
+ <li><a href="https://www.youtube.com/watch?v=2-S6yVyzypU">PROPL 2024</a></li>
13
+ <li><a href="https://www.youtube.com/watch?v=F3JaftEnFfM">ICCS Summer School</a></li>
14
+ <li><a href="https://arxiv.org/abs/2403.04403">ESOP 2025 preprint</a></li>
15
+ </ul>
16
+ </nav>
17
+ <nav>
18
+ <ul>
19
+ <li><a href="/">Overview</a></li>
20
+ <li><a href="/faq">FAQ</a></li>
21
+ <li><a href="/contributors">Contributors &amp; Funding</a></li>
22
+ <li><a href="/student-projects">Student Projects</a></li>
23
+ </ul>
24
+ </nav>
25
+ <div></div>
26
+ </div>
27
+ </div>
@@ -0,0 +1,12 @@
1
+ <div></div>
2
+ <div></div>
3
+ <div>
4
+ <h3 class="title">Overview</h3>
5
+ <nav class="sub-header">
6
+ <ul>
7
+ <li><a href="/">Transparent research outputs</a></li>
8
+ <li><a href="/convolution">Matrix convolution</a></li>
9
+ <li><a href="/moving-average">Moving average</a></li>
10
+ </ul>
11
+ </nav>
12
+ </div>
@@ -0,0 +1,72 @@
1
+ function loadHeader () {
2
+ fetch('/shared/header.html')
3
+ .then(response => response.text())
4
+ .then(data => {
5
+ const header = document.createElement('div')
6
+ header.innerHTML = data
7
+ activateCurrentLink(header)
8
+ const divElement = header.children[0]
9
+ const grid = document.getElementById('grid')
10
+ grid.parentNode.insertBefore(divElement, grid)
11
+ })
12
+ .catch(error => console.error('Error loading shared HTML:', error))
13
+
14
+ fetch('/shared/footer.html')
15
+ .then(response => response.text())
16
+ .then(data => {
17
+ const footer = document.createElement('div')
18
+ footer.innerHTML = data
19
+ const divElement = footer.children[0]
20
+ const grid = document.getElementById('grid')
21
+ grid.parentNode.appendChild(divElement)
22
+ })
23
+ .catch(error => console.error('Error loading shared HTML:', error))
24
+ }
25
+
26
+ function eqPaths (path1, path2) {
27
+ const trailingSlashes = /\/+$/
28
+ return path1.replace(trailingSlashes, '') === path2.replace(trailingSlashes, '')
29
+ }
30
+
31
+ function activateCurrentLink (el) {
32
+ const listItems = el.querySelectorAll('li')
33
+ const n_ = Array.from(listItems).findIndex(li => {
34
+ const link = li.querySelector('a')
35
+ return link && eqPaths(link.getAttribute('href'), window.location.pathname)
36
+ })
37
+ if (n_ !== -1) {
38
+ listItems[n_].classList.add('active-page')
39
+ }
40
+ }
41
+
42
+ function loadSubHeader () {
43
+ fetch('/shared/sub-header.html')
44
+ .then(response => response.text())
45
+ .then(data => {
46
+ const header = document.createElement('div')
47
+ header.innerHTML = data
48
+ activateCurrentLink(header)
49
+ const divElements = header.children
50
+ const grid = document.getElementById('grid')
51
+ for (let i = Math.min(4, divElements.length - 1); i >= 0; --i) {
52
+ grid.insertBefore(divElements[i], grid.firstChild)
53
+ }
54
+ })
55
+ .catch(error => console.error('Error loading shared HTML:', error))
56
+ }
57
+
58
+ function toggleDataPane(gridId) {
59
+ const grid = document.getElementById(gridId)
60
+ const hidden = grid.classList.contains('data-pane-hidden')
61
+ const dataPaneButton = document.querySelector('.data-pane-button')
62
+
63
+ if (hidden) {
64
+ grid.classList.remove('data-pane-hidden')
65
+ dataPaneButton.classList.remove('fa-eye-slash')
66
+ dataPaneButton.classList.add('fa-eye')
67
+ } else {
68
+ grid.classList.add('data-pane-hidden')
69
+ dataPaneButton.classList.remove('fa-eye')
70
+ dataPaneButton.classList.add('fa-eye-slash')
71
+ }
72
+ }