PageSourceSearch

https://formform.dev/clerk/notebooks/introduction/

html formform.dev collected 2026-10-05 18:10:33 UTC 14,217 bytes, 452 lines download raw bytes

1<!DOCTYPE html>
2<html><head><meta charset="UTF-8"><meta content="width=device-width, initial-scale=1" name="viewport"><meta content="formform (in its current state) has three core modules:" property="og:description"><meta content="Introduction to formform" property="og:title"><meta content="article:clerk" property="og:type"><meta content="summary_large_image" name="twitter:card">
2<script src="https://cdn.tailwindcss.com?plugins=typography" type="text/javascript"></script>
2<script>tailwind.config = {
3  darkMode: "class",
4  content: ["./tw/viewer.js", "./tw/**/*.edn"],
5  safelist: ['dark'],
6  theme: {
7    extend: {},
8    fontFamily: {
9      sans: ["Fira Sans", "-apple-system", "BlinkMacSystemFont", "sans-serif"],
10      serif: ["PT Serif", "serif"],
11      mono: ["Fira Mono", "monospace"]
12    }
13  },
14  variants: {
15    extend: {},
16  },
17  plugins: [],
18}
19</script>
19<style type="text/tailwindcss">@tailwind base;
20@tailwind components;
21@tailwind utilities;
22
23@layer base {
24  html {
25    font-size: 18px;
26  }
27  @media (max-width: 600px) {
28    html {
29      font-size: 16px;
30    }
31  }
32  .font-condensed { font-family: "Fira Sans Condensed", sans-serif; }
33  .font-inter     { font-family: "Inter", sans-serif; }
34  body {
35    @apply font-serif antialiased text-gray-900 sm:overscroll-y-none pb-8;
36  }
37  code, .code {
38    @apply font-mono text-sm text-gray-900 bg-slate-50 px-0.5 py-px rounded dark:bg-gray-800;
39  }
40  code::before, code::after { @apply content-none !important; }
41  h1, h3, h4, h5, h6 {
42    @apply font-condensed font-bold mt-8 first:mt-0;
43  }
44  h2 {
45    /*We cannot collapse margins due to nesting but we want to*/
46    /*keep the h2’s large margin visible*/
47    @apply font-condensed font-bold mt-8 first:mt-2;
48  }
49  h1 { @apply text-4xl; }
50  h2 { @apply text-3xl; }
51  h3 { @apply text-2xl; }
52
53  @media print {
54      h1 { @apply text-2xl !important; }
55      h2 { @apply text-xl !important; }
56      h3 { @apply text-lg !important; }
57  }
58
59  button { @apply focus:outline-none; }
60  strong { @apply font-bold; }
61  em     { @apply italic; }
62  pre    { @apply m-0 font-mono; }
63  table img { @apply inline-block; }
64}
65
66/* Compatibility */
67/* --------------------------------------------------------------- */
68/* TODO: Verify which colors are in use and replace with Tailwind
69   colors accordingly. Move Nj-specific styles out of here. */
70
71:root {
72  --teal-color: #31afd0;
73  --dark-teal-color: #095960;
74  --near-black-color: #2e2e2c;
75  --red-color: #d64242;
76  --dark-blue-color: #1f2937;
77  --dark-blue-60-color: rgba(28, 42, 56, 0.6);
78  --gray-panel-color: rgba(239, 241, 245, 1.000);
79  --brand-color: var(--dark-blue-color);
80  --link-color: #5046e4;
81  --command-bar-selected-color: var(--teal-color);
82}
83
84.serif      { @apply font-serif; }
85.sans-serif { @apply font-sans; }
86.monospace  { @apply font-mono; }
87.inter      { @apply font-inter; }
88
89.border-color-teal { border-color: var(--dark-teal-color); }
90.teal { color: var(--teal-color); }
91.bg-dark-blue { background: var(--dark-blue-color); }
92.bg-dark-blue-60 { background: rgba(28, 42, 56, 0.6); }
93.bg-gray-panel { background: var(--gray-panel-color); }
94.text-dark-blue  { color: var(--dark-blue-color); }
95.text-dark-blue-60 { color: var(--dark-blue-60-color); }
96.border-dark-blue-30 { border-color: rgba(28, 42, 56, 0.6); }
97.text-brand { color: var(--dark-blue-color); }
98.bg-brand { background: var(--dark-blue-color); }
99.text-selected { color: white; }
100.red { color: var(--red-color); }
101
102/* Disclose Button */
103/* --------------------------------------------------------------- */
104
105.disclose {
106  @apply content-none border-solid cursor-pointer inline-block relative mr-[3px] top-[-2px] transition-all;
107  border-color: var(--near-black-color) transparent;
108  border-width: 6px 4px 0;
109}
110.disclose:hover {
111  border-color: var(--near-black-color) transparent;
112}
113.dark .disclose,
114.dark .disclose:hover {
115  border-color: white transparent;
116}
117.disclose.collapsed {
118  @apply rotate-[-90deg];
119}
120
121/* Layout */
122/* --------------------------------------------------------------- */
123
124.page {
125  @apply max-w-5xl mx-auto px-12 box-border flex-shrink-0;
126}
127.max-w-prose { @apply max-w-[46rem] !important; }
128.max-w-wide  { @apply max-w-3xl !important; }
129
130/* List Styles */
131/* --------------------------------------------------------------- */
132
133.task-list-item + .task-list-item,
134.markdown-viewer ul ul {
135  @apply mt-1 mb-0;
136}
137
138/* compact TOC */
139.markdown-viewer .toc ul {
140  list-style: none;
141  @apply my-1;
142}
143
144/* Code Viewer */
145/* --------------------------------------------------------------- */
146
147.code-viewer {
148  @apply font-mono bg-slate-100 rounded-sm text-sm overflow-x-auto dark:bg-gray-800;
149}
150.code-listing  {
151    @apply -ml-8 -mr-8 relative !important;
152}
153.code-viewer .cm-content {
154  @apply py-4 px-8;
155}
156@media (min-width: 960px){
157    .notebook-viewer .code-viewer .cm-content {
158        @apply pl-12;
159    }
160    .notebook-viewer .code-listing {
161        width: 48rem !important;
162        @apply -ml-12 mr-0 !important;
163    }
164}
165/* Don’t show focus outline when double-clicking cell in Safari */
166.cm-scroller { @apply focus:outline-none; }
167
168/* Syntax Highlighting */
169/* --------------------------------------------------------------- */
170
171.inspected-value { @apply text-xs font-mono leading-[1.25rem]; }
172.cmt-strong, .cmt-heading { @apply font-bold; }
173.cmt-italic, .cmt-emphasis { @apply italic; }
174.cmt-strikethrough { @apply line-through; }
175.cmt-link { @apply underline; }
176.untyped-value { @apply whitespace-nowrap; }
177
178.cm-editor, .cmt-default, .result-viewer {
179  @apply text-slate-800 dark:text-slate-300;
180}
181.cmt-keyword {
182  @apply text-purple-800 dark:text-pink-400;
183}
184.cmt-atom, .cmt-bool, .cmt-url, .cmt-contentSeparator, .cmt-labelName {
185  @apply text-blue-900 dark:text-blue-300;
186}
187.cmt-inserted, .cmt-literal {
188  @apply text-emerald-700 dark:text-emerald-200;
189}
190.cmt-string, .cmt-deleted {
191  @apply text-rose-700 dark:text-sky-300;
192}
193.cmt-italic.cmt-string {
194  @apply dark:text-sky-200;
195}
196.cmt-regexp, .cmt-escape {
197  @apply text-orange-500 dark:text-orange-300;
198}
199.cmt-variableName {
200  @apply text-blue-800 dark:text-sky-300;
201}
202.cmt-typeName, .cmt-namespace {
203  @apply text-emerald-600 dark:text-emerald-300;
204}
205.cmt-className {
206  @apply text-teal-600 dark:text-teal-200;
207}
208.cmt-macroName {
209  @apply text-teal-700 dark:text-teal-200;
210}
211.cmt-propertyName {
212  @apply text-blue-700 dark:text-blue-200;
213}
214.cmt-comment {
215  @apply text-slate-500 dark:text-slate-400;
216}
217.cmt-meta {
218  @apply text-slate-600 dark:text-slate-400;
219}
220.cmt-invalid {
221  @apply text-red-500 dark:text-red-300;
222}
223
224.result-data {
225  @apply font-mono text-sm overflow-x-auto whitespace-nowrap leading-normal;
226}
227.result-data::-webkit-scrollbar, .path-nav::-webkit-scrollbar {
228  @apply h-0;
229}
230.result-data-collapsed {
231  @apply whitespace-nowrap;
232}
233.result-data-field {
234  @apply ml-4 whitespace-nowrap;
235}
236.result-data-field-link{
237  @apply ml-4 whitespace-nowrap cursor-pointer;
238}
239.result-data-field-link:hover {
240  @apply text-black bg-black/5;
241}
242.result-text-empty {
243  color: rgba(0,0,0,.3);
244}
245.browsify-button:hover {
246  box-shadow: -2px 0 0 2px #edf2f7;
247}
248
249/* Prose */
250/* --------------------------------------------------------------- */
251
252.notebook-viewer,
253.markdown-viewer {
254  @apply prose
255    dark:prose-invert
256    prose-a:text-blue-600 prose-a:no-underline hover:prose-a:underline
257    dark:prose-a:text-blue-300
258    prose-p:mt-4 prose-p:leading-snug
259    prose-ol:mt-4 prose-ol:mb-6 prose-ol:leading-snug
260    prose-ul:mt-4 prose-ul:mb-6 prose-ul:leading-snug
261    prose-blockquote:mt-4 prose-blockquote:leading-snug
262    prose-hr:mt-6 prose-hr:border-t-2 prose-hr:border-solid prose-hr:border-slate-200
263    prose-figure:mt-4
264    prose-figcaption:mt-2 prose-figcaption:text-xs
265    prose-headings:mb-4
266    prose-table:mt-0
267    prose-th:mb-0
268    prose-img:my-0
269    prose-code:font-medium prose-code:bg-slate-100
270    max-w-none;
271}
272.markdown-viewer blockquote p:first-of-type:before,
273.markdown-viewer blockquote p:last-of-type:after {
274  @apply content-none;
275}
276.markdown-node-viewer.result-viewer.fragment-item {
277    @apply mb-0 !important;
278}
279
280figcaption .markdown-viewer {
281    @apply text-xs text-slate-500;
282}
283
284figcaption .markdown-viewer a {
285    @apply underline;
286}
287/* Images */
288/* --------------------------------------------------------------- */
289
290
291/* Todo Lists */
292/* --------------------------------------------------------------- */
293
294.contains-task-list {
295  @apply pl-6 list-none;
296}
297.contains-task-list input[type="checkbox"] {
298  @apply appearance-none h-4 w-4 rounded border border-slate-200 relative mr-[0.3rem] ml-[-1.5rem] top-[0.15rem];
299}
300.contains-task-list input[type="checkbox"]:checked {
301  @apply border-indigo-600 bg-indigo-600 bg-no-repeat bg-contain;
302  background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
303}
304
305/* Markdown TOC */
306/* --------------------------------------------------------------- */
307
308.markdown-viewer .toc      { @apply mt-4; }
309.markdown-viewer h1 + .toc { @apply mt-8; }
310
311.markdown-viewer .toc h1,
312.markdown-viewer .toc h2,
313.markdown-viewer .toc h3,
314.markdown-viewer .toc h4,
315.markdown-viewer .toc h5,
316.markdown-viewer .toc h6 {
317  @apply text-base text-indigo-600 font-sans my-0;
318}
319.markdown-viewer .toc a {
320  @apply text-indigo-600 font-normal no-underline hover:underline;
321}
322.markdown-viewer .toc li    { @apply m-0; }
323.markdown-viewer .toc ul ul { @apply pl-4; }
324
325/* Notebook Spacing */
326/* --------------------------------------------------------------- */
327
328.markdown-viewer *:first-child:not(.code-viewer):not(li):not(h2):not(.sidenote) { @apply mt-0; }
329/*.viewer + .viewer { @apply mt-6; }*/
330.viewer + .result-viewer { @apply mt-0; }
331.code-viewer + .result-viewer { @apply mt-3; }
332.markdown-viewer + .markdown-viewer { @apply mt-0; }
333
334/* Sidenotes */
335/* --------------------------------------------------------------- */
336
337.sidenote-ref {
338  @apply top-[-0.5em] w-auto h-auto inline border-0 bg-transparent m-0 pointer-events-none;
339}
340.sidenote {
341  @apply block font-sans text-xs mt-4 bg-slate-100 dark:bg-slate-800 p-4;
342  font-style: normal;
343  font-weight: normal;
344}
345.sidenote-container {
346  @apply mb-4;
347}
348.sidenote-main-col *:last-child {
349  @apply mb-0;
350}
351.sidenote-main-col {
352  @apply w-full;
353}
354.sidenote-main-col > ul > li:first-child,
355.sidenote-main-col > ol > li:first-child {
356  @apply mt-0;
357}
358@media (min-width: 860px) {
359  .sidenote sup { @apply inline; }
360  .sidenote-column {
361    @apply w-[165px] -mr-[205px] flex-shrink-0;
362  }
363  .sidenote {
364    @apply bg-transparent dark:bg-transparent p-0;
365  }
366  .sidenote:first-child {
367    @apply mt-1;
368  }
369  .sidenotes-layout .markdown-viewer {
370    @apply pr-[241px];
371  }
372  .sidenote-container {
373    @apply relative flex justify-between;
374  }
375  .sidenote-container > *:not(.sidenote-column) {
376    margin-right: 40px;
377  }
378  .sidenote:last-of-type {
379
380  }
381  .sidenotes-layout h1 {
382    @apply w-[756px] !important;
383  }
384}
385.code-viewer + .viewer:not(.code-viewer):not(.code-viewer-folded),
386.code-viewer-folded + .viewer:not(.code-viewer):not(.code-viewer-folded),
387.result-viewer:not(.markdown-node-viewer) + .result-viewer {
388  @apply mt-2;
389}
390.code-viewer + .code-viewer-folded {
391  @apply mt-4;
392}
393.result-viewer {
394  @apply leading-tight mb-6;
395}
396.code-viewer.fragment-item.result-viewer {
397  @apply mb-0 !important;
398}
399.result-viewer figure {
400  @apply mt-0 !important;
401}
402@media (min-width: 768px) {
403  .devcard-desc > div {
404    @apply max-w-full m-0;
405  }
406}
407
408/* Command Palette */
409/* --------------------------------------------------------------- */
410
411.nj-commands-input {
412  @apply bg-transparent text-white;
413}
414.nj-context-menu-item:hover:not([disabled]) {
415  @apply cursor-pointer;
416  background-color: rgba(255,255,255,.14);
417}
418
419/* Devdocs */
420/* --------------------------------------------------------------- */
421
422.logo, .logo-white {
423  @apply block indent-[-999em];
424  background: url(/images/nextjournal-logo.svg) center center no-repeat;
425}
426.devdocs-body {
427  @apply font-inter;
428}
429
430/* Workarounds */
431/* --------------------------------------------------------------- */
432
433/* Fixes vega viewer resizing into infinity */
434.vega-embed .chart-wrapper { @apply h-auto !important; }
435/* fixes fraction separators being overridden by tw’s border-color */
436.katex * { @apply border-black; }
437
438@media print {
439    .dark-mode-toggle,
440    .toc-toggle { @apply hidden; }
441    .notebook-viewer { @apply pt-0; font-size: 12pt !important; margin-left: 0 !important; }
442    .code-viewer .cm-content,
443    .viewer-code .cm-content { @apply whitespace-pre-wrap !important; overflow: none; }
444    .code-viewer .cm-line { font-size: 12pt !important; }
445    html * { page-break-inside: avoid !important; }
446    .toc-panel { @apply hidden; }
447}
448</style>
448<script src="https://storage.clerk.garden/nextjournal/clerk-assets@3ijeaVdc5TGgRwvmeynCSNH8q7u/viewer.js?immutable=true" type="module"></script>
448<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css" rel="stylesheet" type="text/css"><link href="https://fonts.bunny.net" rel="preconnect"><link href="https://fonts.bunny.net/css?family=fira-mono:400,700%7Cfira-sans:400,400i,500,500i,700,700i%7Cfira-sans-condensed:700,700i%7Cpt-serif:400,400i,700,700i" rel="stylesheet" type="text/css"></head><body class="dark:bg-gray-900"><div id="clerk"></div>
448<script type="module">let viewer = nextjournal.clerk.sci_env
449let state = "{:package :directory, :render-router :fetch-edn, :current-path \"notebooks/introduction\", :resource->url {\"/js/viewer.js\" \"https://storage.clerk.garden/nextjournal/clerk-assets@3ijeaVdc5TGgRwvmeynCSNH8q7u/viewer.js?immutable=true\"}, :index \"notebooks/index.clj\"}".replaceAll('nextjournal.clerk.view/escape-closing-script-tag', 'script')
450viewer.init(viewer.read_string(state))
451</script>
451<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"ce99fea477754e43bf2a625f7940387d","r":1,"spa":2}' crossorigin="anonymous"></script>
451
452</body></html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.