on 015cb5e help sign in
urbit.org/using/udon.md
888 lines 24 kB history raw
1+++
2title = "Udon"
3weight = 8
4template = "doc.html"
5+++
6## Table of Contents
8- #### [Udon: A Guide](#guide)
10- #### [A Simple Udon Blog](#blog)
12- #### [A Static Site](#static)
14## A Guide
16Udon is a way to write content for the web. It's a minimalist
17markup language for creating and rendering text documents, with a
18Markdown-inspired syntax. It's integrated with our Hoon programming language,
19allowing it to be used as standalone prose in its own file or embedded inside a
20Hoon source file, in which case it will be parsed into a tree of HTML nodes
21using Hoon's XML-templating syntax, Sail.
23This document is itself written in Udon, and its source file is of the
24Udon `.udon` extension. As such, we use some `formatted text` to make
25it clear what is and isn't code, and to display that code to you instead of
26actually using its semantics for formatting.
28There are quite a few similarities between Udon and the
29CommonMark standard, but there are enough differences that you shouldn't rely on
30existing knowledge of the latter. Udon generally supports only one
31syntax for each type of HTML node it emits. Udon is also stricter than
32Markdown: some syntax errors will prevent the file from being parsed at all.
34We provide a few simple examples [here](#examples) of how to publish
35Udon files using our web interface.
37### Getting Started
39Before starting, make sure that your urbit is
40[mounted to Unix](https://urbit.org/docs/using/setup/)
42To host Udon and other kinds of files, your ship also has a
43web-server, called [Eyre](https://urbit.org/docs/using/web/), that can be found
44at `http://localhost:8080/` if it’s your first ship that’s running on the
45machine, `http://localhost:8081/` if it’s the second ship on that same machine,
46and so on. If you can't find your ship on one of these for some reason, try the
47next one. When a ship starts, it will print a message like
48`http: live (insecure, public) on 8081` to let you know what port it's using.
50That server has access to source files located in `/<your-urbit>/home/web` and
51any sub-folders thereof (except for `/home/web/pages`, which has special
52rendering rules.) Your ship's `%home` desk is served by default. You can
53[change](https://urbit.org/docs/using/web/) which desk you're serving, however.
55Everything in the `/<your-urbit>/home/web/` directory, with the exception of
56`/home/web/pages`, knows how to interpret and files of `.udon` type. So, to
57experiment with UM, create a `.udon` file in that path, and then try to access it
58at `http://localhost:8080/<yourfile>` in your browser -- no `.udon` required in
59the URL. It's a good idea to copy-paste the following examples into your file to
60see how the code works.
62Make sure that you have proper syntax throughout, and check often that it
63renders properly as you add more code. If you have parser-breaking syntax, then
64the default renderer won't tell you much.
66## Syntax
68### Front Matter
70The first thing on your file is a chunk of code called the front matter. It
71contains metadata about your page, such as date, title, and position relative
72to sibling pages.
74As an example, let's look at the front matter of this very page:
76```
77:- :~ navhome/'/docs/'
78 sort/'11'
79 title/'Udon'
80 ==
81;>
82```
84What's going on here?
86`:-`, the Hoon rune for creating a cell, creates a cell composed of
87the `:~` Hoon rune for creating a list, and `;>`, which is a Sail rune
88for Udon.
90`:~` creates a list out of the three elements: `navhome/'/docs/'`, which
91indicates that navigating "home" will bring you to the urbit.org/docs section
92of the website; `sort/'28',` which assigns it the 28th position of the
93immediate section that contains it, the one you see in the sidebar;
94and `title/'Udon'`, which gives the page its title. The `==` digraph
95terminates the list.
97`;>` is a Sail rune that creates a node that contains everything that follows
98it, telling the parser that that text should be interpreted as Udon.
99It's not technically front matter, but you'll always find it following the
100front matter, since all Udon must come after this rune.
102The categories listed in the example above -- `navhome`, `sort`, and `title` --
103make sense to Eyre by default, but any arbitrary category can be used. The code
104below is valid front matter.
106```
107:- :~ date/~2018.9.12
108 author/~lodleb-ritrul
109 music/'rad'
110 ==
111```
113Note that `~2018.9.12`, `~lodleb-ritrul`, and `'rad'` are all of of atom
114types: `@da`(date), `@p` (ship name), and `@t` (cord), respectively. Only atom
115types work here. Having `music/"rad"` would prevent the source file from
116parsing.
118### Headers
120Headers in Udon begin the line with one or more `#` characters,
121'followed by a single space. After that space comes the actual text to be
122displayed. The number of leading `#`s corresponds to the resulting HTML
123header-size element: `#` yields an `<h1>`, `##` yields an `<h2>`, and so on,
124through `<h6>`. The header for this section is `### Headers`.
126*Example:*
127```
128#### Header (h4)
130##### Header (h5)
131```
132###### Produces:
134#### Header (h4)
136##### Header (h5)
138### Italics and Bold
140Enclosing text with `_` will cause that text to appear italicized, using an `<i>`
141element.
143Enclosing text with `*` will cause that text to appear bolded, using a `<b>`
144element.
147*Example:*
149```
150To get their *attention*, you need that _je ne sais quoi_.
151```
153###### Produces:
155To get their *attention*, you need that _je ne sais quoi_.
157### Line Break
159A blank line is interpreted as a line break, creating a distinct
160paragraph. However, a newline on its own is merely interpreted as a space on
161the _same line_.
163*Example:*
165```
166Here's the first line.
168This second line is separated by two newlines, so it's a separate paragraph.
170This line looks like a distinct paragraph, but...
171It's only separated by a single newline, so it's included in the same paragraph.
172```
173###### Produces:
176Here's the first line.
178This second line is separated by two newlines, so it's a separate paragraph.
180This line looks like a distinct paragraph, but...
181It's only separated by a single newline, so it's included in the same paragraph.
183#### Backslash Line Break
185A backslash at the end of a line inserts a line break (`<br>`)
186after that line. This contrasts with the normal udon behavior of
187converting newlines to spaces.
189*Example:*
190```
191I wonder how long each line
192will be if I put backslashes\
193at the ends of the lines.
194```
195###### Produces:
197I wonder how long each line
198will be if I put backslashes\
199at the ends of the lines.
201### Escape
203A backslash directly _before_ a word (with no spaces) will be interpreted
204as an escape character, causing it to be rendered raw.
206*Example:*
208```
209Here is some *bold* text.
210Here is some \*not bold* text.
211```
213###### Produces:
215Here is some *bold* text.
216Here is some \*not bold* text.
219### List
221A line beginning with a `-` followed by a space is interpreted as an
222element of an *unordered list* (`<ul>`). Each line in an unordered list is
223prepended with a bullet point.
225A line beginning with a `+` followed by a space is interpreted as an element
226of an *ordered list* (`<ol>`). Each line in an ordered list is prepended with
227a number corresponding to its position in that list.
229New list elements are delineated by newlines beginning with list symbols of
230the appropriate type (`-` or `+`).
232Just as with non-list text, text on a bare newline will appear on line before,
233separated by a space. A `\\` is used to create a line-break that isn't the list
234itself and isn't a list. Both of these kinds of newlines must be indented by two
235spaces, or else the page will not parse.
237Indentation is also used for creating nested sub-lists. Sub-lists of one kind
238can be used with parent lists of the other kind. Sub-lists can't be nested
239directly after either kind of aforementioned newline that isn't a list element;
240only lines that are themselves list elements can nest sub-lists.
242A newline after a blank line is interpreted as a new paragraph in normal text.
243Between to list elements, however, a blank line is semantically equivalent to
244a bare newline. To separate two lists with blank space, create a blank line
245followed by a `\\` on its own line.
247*Example:*
249```
250- Eggs
251 (cage-free)
252- Milk
253- Butter
254- Chicken\
255 Make sure that you get enough for the barbecue
256- Bread
257 + Ask the baker what's fresh
258 + Buy the second-freshest batch
259- Cereal
262+ First, separate eggs into a bowl.
263+ Then, add a splash of cream.
264 - If you don't have cream, you can use milk, but cream is preferred.
265 + If you don't have milk or cream, melt an eighth of a stick of butter on
266 a skillet
267 + Scrambled the eggs in the bowl.
268 + Pour the eggs onto the skillet before the butter browns
269+ Heat the skillet
271+ Scramble eggs and put them into skillet
274+ Cool
275+ Alright
276```
278Produces
280- Eggs
281 (cage-free)
282- Milk
283- Butter
284- Chicken\
285 Make sure that you get enough for the barbecue
286- Bread
287 + Ask the baker what's fresh
288 + Buy the second-freshest batch
289- Cereal
292+ First, separate eggs into a bowl.
293+ Then, add a splash of cream.
294 - If you don't have cream, you can use milk, but cream is preferred.
295 + If you don't have milk or cream, melt an eighth of a stick of butter on
296 a skillet
297 + Scrambled the eggs in the bowl.
298 + Pour the eggs onto the skillet before the butter browns
299+ Heat the skillet
301+ Scramble eggs and put them into skillet
304+ Cool
305+ Alright
307### Link
309There are two ways to create links, but both contain the text be hyperlinked
310in `[]` followed by the destination in `()`.
312The first type is an inline-style link, which simply uses the full URL as its
313destination.
315*Example:*
317```
318[I'm an inline-style link](https://www.urbit.org/docs/reference/shell)
319```
321###### Produces:
323[I'm an inline-style link](https://www.urbit.org/docs/reference/shell)
325The second type is a reference-style link, which uses a relative path, based on
326the current page's location. Instead of the full url, we use `..` to fill in
327the all of the URL that the destination has in common with the origin page.
329*Example:*
331```
332[I'm a reference-style link](../shell)
333```
335###### Produces:
337[I'm a reference-style link](../shell)
339If this page is located at `https://www.urbit.org/docs/reference/`, then these two
340examples should have the same destination.
342#### Anchor Link
344A link to a section of the same page is in the style of
345`[text to be linked](#the-destination)`.
347The destination for the anchor link is designated with the HTML element `id`,
348so we need to use some [Sail](#sail). If there are two or more anchors with
349the same `id` on the page, you will arrive at the earliest instance of the the
350anchor.
352###### Example:
354```
355Check out this [section](#the-destination) that we want to jump to.
357Four score and seven years ago....
359It was the best of times, it was the worst of times...
361## Here we are!
362```
364###### Produces
366Check out this [section](#the-destination) that we want to jump to.
368Four score and seven years ago....
370It was the best of times, it was the worst of times...
372## Here we are!
374### Double Quote
376Text enclosed in double quotes (`"`) will be rendered with
377opening and closing quotes -- that is, `“` and `”`.
379*Example:*
380```
381"Yes," he said. "That is the way with him."
382```
384###### Produces:
386"Yes," he said. "That is the way with him."
389### Code Literal
391There are two ways to show the literal text of code without running it: inline
392and block. Both highlight the contained text in another color.
394Note that the backslash, due to its role as the escape character, can only be
395displayed in a code block literal and not as inline code literal. This is a
396bug.
398```
400```
402##### Inline Code Literal
404Enclosing some text in
405```
407```
408characters will cause it to be displayed as code,
409inside a `<code>` HTML element with monospace font and highlighted with a
410different background color.
412Using `` ` \`` is useful when you want to designated only part of a line as code.
413Since this page is written in Udon, we've been using this operation
414throughout this guide to `format text` to distinguish code from prose.
416*Example:*
417```
418`*[a 2 b c] -> *[*[a b] *[a c]]` is like lisp's `apply`.
419```
420###### Produces:
422`*[a 2 b c] -> *[*[a b] *[a c]]` is like lisp's `apply`.
424Also, using the `++` prefix before a word will cause the word to be rendered as
425code with the `++` displayed, since that's the standard notation for an arm in
426Hoon.
428*Example:*
430```
431The ++add arm is used to sum two numbers.
432```
434###### Produces:
436The ++add arm is used to sum two numbers.
438#### Block Code Literal
440By enclosing a block of text in ``` on their own lines
441before and after the contained text, the text will be treated as a code block.
443Most of our examples so far have used.
445*Example:*
448```
449 ```
450 (def Y (fn [f]
451 ((fn [x]
452 (x x))
453 (fn [x]
454 (f (fn [y]
455 ((x x) y)))))))
456 ```
457```
459###### Produces:
461```
462(def Y (fn [f]
463 ((fn [x]
464 (x x))
465 (fn [x]
466 (f (fn [y]
467 ((x x) y)))))))
468```
470### Hoon Constants
472Hoon has several syntactic forms for literals (numbers, strings, dates, etc.)
473that can be used in udon as well. Udon detects such code, and so these
474forms will automatically appear inside a `<code>` element like inline code.
476Example:
478```
479~2017.8.29 \
4800xdead.beef \
481%term
482```
484produces:\
486~2017.8.29 \
4870xdead.beef \
488%term
491### Horizontal Rule
493Three or more hyphens, such as `---`, on their own line produce an `<hr>`
494element, the 'horizontal rule'. This is rendered as a horizontal line the
495width of its containing paragraph.
497###### Example:
499```
500Above the line
501---
502Below the line
503-----
504And below this line, too
505```
507###### Produces:
510Above the line
511---
512Below the line
513-----
514And below this line, too
516### Block Quote
518A section of text with the first line beginning with `>` and a space,
519and each successive newline indented by two spaces yields a
520`<blockquote>` HTML element. This block quote can itself contain more Udon,
521including more block quotes to render nested levels of quotation.
522Inline italicization with `_` does not work, however.
524Blank newlines do not end the block quote, but a blank newline followed by an
525unindented line of text _will_ end the quote.
527*Example:*
529```
530> As Gregor Samsa awoke one morning from uneasy dreams, he
531 found himself transformed in his bed into a *monstrous* vermin.
533Quote break.
535> _See_ the child.
537 He is pale and thin, he wears a thin and ragged linen shirt.
538```
540###### Produces:
542> As Gregor Samsa awoke one morning from uneasy dreams
543 he found himself transformed in his bed into a *monstrous* vermin.
545Quote break.
547> _See_ the child.
549 He is pale and thin, he wears a thin and ragged linen shirt.
552### Poem
554A poem is a section of text with meaningful newlines. Recall that,
555normally in Udon, newlines are treated as spaces and do not create a
556new line of text. If you want to embed text where newlines are retained, then
557indent the text in question with *eight spaces*.
559###### Example:
561```
562 A shape with lion body and the head of a man,
563 A gaze blank and pitiless as the sun,
564 Is moving its slow thighs, while all about it
565 Reel shadows of the indignant desert birds.
566```
567###### Produces:
569 A shape with lion body and the head of a man,
570 A gaze blank and pitiless as the sun,
571 Is moving its slow thighs, while all about it
572 Reel shadows of the indignant desert birds.
575## Sail Expressions
577It's possible to use Udon as an HTML templating language akin to
578PHP, ERB, JSP, or Handlebars templates. This facility derives
579in part from the support for embedding Hoon code inside the markup.
582Sail is a domain-specific language within Hoon for creating XML nodes,
583including HTML. It can be used directly within Udon to provide
584scripting capability with Hoon and also to provide more precise control over the
585resulting HTML. The [Sail guide](../sail) is a good place to learn the
586specifics.
588Example:
590```
591;=
592 ;p
593 ;strong: Don't panic!
594 <br>
595 ;small: [reactive publishing intensifies]
596 ==
597==
598```
600Produces:
603;=
604 ;p
605 ;strong: Don't panic!
606 <br>
607 ;small: [reactive publishing intensifies]
608 ==
609==
612## A Simple Udon Blog
614Publishing using Udon is really easy. It uses the file extension `.udon`. Here we'll create a very simple blog and publish our first posts.
616First, let's setup a desk to serve our posts from:
618```
619|merge %site ~your-urbit %home
620```
622Then let's mount that desk to unix:
624```
625|mount /=site=
626```
628You should now be able to find a `/site` folder inside of your pier
629directory (either `comet/` or `your-urbit/`).
631To begin serving files from this new desk use `|serve`:
633```
634|serve %site
635```
637First let's create the landing page for our blog. Create the file
638`site/web/blog.udon`:
640```
641:- :~ anchor/'none'
642 ==
643;>
645# Hello
647This is a simple blog I built on Urbit.
649;list(dataType "post");
650```
652Try viewing this file at `http://localhost:8080`. Note that `8080` might be
653`8081`, `8082`, and so on, depending if those ports were being used when you
654started your urbit.
656The only special thing about this page is the `anchor/'none'` front-matter
657which simply turns off the Tree navigation. Normally Tree gives navigation
658controls for walking around the filesystem, but taking them away makes
659the page seem more like a landing page.
661The page looks pretty boring now. Let's add our first post. From
662unix run `mkdir your-urbit/site/web/blog; touch
663your-urbit/site/web/blog/post-1.udon`. (Currently [there's a
664bug](https://github.com/urbit/urbit/issues/321) that prevents empty
665directories from getting created, so we have to `touch` a file inside
666them first.) In `blog/post-1.udon` let's add some filler content:
668```
669:- :~ navhome/'/blog'
670 type/'post'
671 date/'~2016.6.20'
672 title/'My first post!'
673 ==
674;>
676Is this a decentralized Medium? Let's find out.
678But first, how about a long quote from Paramenides:
680> True, he said; and therefore when ideas are what they are in
681 relation to one another, their essence is determined by a relation
682 among themselves, and has nothing to do with the resemblances, or
683 whatever they are to be termed, which are in our sphere, and from
684 which we receive this or that name when we partake of them. And
685 the things which are within our sphere and have the same names
686 with them, are likewise only relative to one another, and not to
687 the ideas which have the same names with them, but belong to
688 themselves and not to them.
690Good to get that out of the way.
691```
693You should be able to view this file at:
694`http://localhost:8080/blog/post-1.udon`.
696You'll also notice that
697now the list of posts here: `http://localhost:8080/blog` has
698updated.
700Here we use two pieces of front-matter worth noting: `type` and `navhome`.
702- `type` implies that the page has some special handling by Tree. When `type` is
703 `post` we automatically put in the `date`, `title` and `author` when they're
704 specified and add some styles.
706- `navhome` sets the path used by the home button (the circle in the top left).
707 Since we want to send people back to the root of our blog, we set this to `/blog`
709Adding posts is as easy as dropping Udon files into the `blog/`
710directory. Pretty easy!
712### Blog comments
714Now let's enable comments on a blog post.
716First, turn comments on by editing the frontmatter in `post-1.udon`. Your
717frontmatter should look like this:
719```
720:- :~ navhome/'/blog'
721 type/'post'
722 date/'~2018.6.20'
723 title/'Blog comments'
724 comments/'true'
725 ==
726;>
727```
729Now try loading your post here: `your-urbit.urbit.org/blog/post-1`.
730You should see a comments box at the bottom of the page.
732Try posting a comment! When you do you should see the following in
733your console:
735```
736+ /~your-urbit/home/55/web/blog/post-1/comments/~2016.6.20..23.20.54..0b88/md
737------------[0]
738~your-urbit[tree]: receiving comments, ;join %comments for details
739```
741Comments are written into the filesystem in the `comments/` folder
742relative to the page they're enabled on. When a new comment is posted
743a notification is also posted to the `/comments` `:talk` channel.
745Use `;join` to keep up with comments as they get posted:
747```
748;join ~your-urbit/comments
749```
751That's it! Easy.
753## A Static Site
755Hosting a static tree of content is easy. Let's put together a really
756simple site for an imaginary Urbit meetup group.
758We assume you have at least followed the beginning of [our first
759examples](#blog) and created a desk called `site` and mounted it to
760unix.
762Note: below we use Urbit's implementation of Markdown, [Udon](#udon).
763This markup language allows you to use snippets of Hoon code but not HTML.
764In particular, we use Sail, a subset of Hoon. This Sail is rendered as HTML
765when the file is served to a client. To learn about Sail, head over to
766the [Sail](/docs/learn/arvo/arvo-internals/sail) section of the docs.
768In `site/web/meet.udon` put:
770```
771:- :~ navhome/'/meet'
772 navdpad/'false'
773 navpath/'/meet'
774 navmode/'navbar'
775 ==
776;>
778# Neo-Tokyo Urbit meetup
780![](https://ofheroesandcliches.files.wordpress.com/2014/06/neo-tokyo.png)
782Hi there! We meet once a week at The Chat to work on Urbit projects
783together.
785You can find out more about the group on the [about](about) page and
786follow our projects in [projects](projects).
787```
789This is our landing page. Here we're using a few new bits of frontmatter:
790`navdpad`, `navmode` and `navpath`. `navdpad` just turns off the nav
791arrows. `navmode` can be set to 'navbar' to switch to a horizontal top
792nav instead of a left bar. `navpath` sets the path to load the nav
793items from.
795Let's create `about.udon` and `projects.udon`. From Unix use the
796technique from before to create a new directory: `mkdir
797your-urbit/site/web/meet/; touch your-urbit/site/web/meet/about.udon`.
798Then put the following in `site/web/about.udon`:
800```
801:- :~ navhome/'/meet'
802 navdpad/'false'
803 navpath/'/meet'
804 navmode/'navbar'
805 title/'About'
806 ==
807;>
809# About
811## Mission statement
813The existing framework cannot subdue the new human force that is increasing day
814by day alongside the irresistible development of technology and the
815dissatisfaction of its possible uses in our senseless social life.
817## Members
819Membership is open to anyone. Just send a message to `~talsur-todres`.
821- Shōtarō Kaneda
822- Motoko Kusanagi
823- Ishikawa
824- Faye Valentine
825- Spike Spiegel
826```
828And `site/web/projects.udon`:
830```
831:- :~ navhome/'/meet'
832 navdpad/'false'
833 navpath/'/meet'
834 navmode/'navbar'
835 title/'Projects'
836 ==
837;>
839# Projects
841## Active
843;list;
845## Discussion
847;div(class "mini-module")
848 ;script(src "/~/at/lib/js/urb.js");
849 ;script(src "https://cdn.rawgit.com/seatgeek/react-infinite/0.8.0/dist/react-infinite.js");
850 ;script(src "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.11.2/moment-with-locales.js");
851 ;script(src "https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.1/moment-timezone.js");
852 ;script(src "/talk/main.js");
853 ;link(href "/talk/main.css", rel "stylesheet");
854 ;talk(readonly "", chrono="reverse", station="comments");
855==
856```
858This page introduces a new thing: the `:talk` module. Inside of the
859`mini-module` div we load the scripts needed by the `;talk`
860component. The `;talk` component is a static component for
861displaying a feed from a talk channel inline. Here we're going to
862display the discussion from our active projects inline.
864We'll need a few active projects though. From unix: `mkdir
865your-urbit/site/web/meet/projects; touch
866your-urbit/site/web/meet/projects/bike.udon`.
868In `site/web/meet/projects/bike.udon`:
870```
871:- :~ navhome/'/meet'
872 navdpad/'false'
873 navpath/'/meet'
874 navmode/'navbar'
875 title/'Kaneda's Bike'
876 comments/'true'
877 ==
878;>
880# Urbit on a Motorcycle
882Discussion on getting urbit to power Kaneda's motorcycle.
883```
885Here we just use the `comments` frontmatter to enable comments on the page.
886Adding other imaginary projects is left to the reader.
888Building a static site takes only a few minutes and a few Udon files. Have fun!