forked from
anil.recoil.org/monopam-myspace
My aggregated monorepo of OCaml code, automaintained
1<?xml version="1.0" encoding="UTF-8"?>
2<feed xmlns="http://www.w3.org/2005/Atom">
3 <contributor>
4 <name>Jon Sterling</name>
5 <uri>https://www.forester-notes.org/jonmsterling/</uri>
6 </contributor>
7 <updated>2025-03-25T13:44:56Z</updated>
8 <title>Forester Blog</title>
9 <id>https://www.forester-notes.org/30FM/</id>
10 <link rel="alternate" href="https://www.forester-notes.org/30FM/" />
11 <link rel="self" href="https://www.forester-notes.org/30FM/atom.xml" />
12 <entry>
13 <title>Towards Forester 5.0 II: a design for canonical URLs</title>
14 <published>2025-03-25T13:44:56Z</published>
15 <updated>2025-03-25T13:44:56Z</updated>
16 <author>
17 <name>Jon Sterling</name>
18 <uri>https://www.forester-notes.org/jonmsterling/</uri>
19 </author>
20 <link rel="alternate" type="text/html" href="https://www.forester-notes.org/JVIT/" />
21 <id>https://www.forester-notes.org/JVIT/</id>
22 <content type="xhtml">
23 <div xmlns="http://www.w3.org/1999/xhtml">
24 <p>One of the goals of <a href="https://www.forester-notes.org/jms-011P/">Forester 5.0</a> is <em>lightweight federation</em>—the ability to have two forests participate in the same graph and therefore provide backlinks, etc. In a previous post (<a href="https://www.forester-notes.org/OYOJ/">Towards <a href="https://www.forester-notes.org/jms-011P/">Forester 5.0</a>: a design for global identity</a>), I talked about some of the difficulties that arise when dealing with identities of people and references that have global scope but could nonetheless be described by trees in many forests. I proposed that such things should be addressed by canonical URIs (e.g. DIDs, DOIs, etc.) and that Forester should grow the ability to bind a canonical URI to multiple trees, which are then gathered into a disambiguation page.</p>
25 <p>Today I want to broaden the discussion to cover the difficulties of addressing trees themselves (as opposed to the global entities they may describe). <mark>This is a proposal and I welcome feedback.</mark></p>
26 <section>
27 <header>
28 <h2>Forester must become part of the Web</h2>
29 </header>
30 <p>I have been working on developing the prerequisites for Forester to emit RSS and Atom feeds for blogs, and I realised that the problem I was trying to solve <a href="https://www.forester-notes.org/OYOJ/">earlier this month</a> is a more multifaceted than I originally thought. It comes down to analysing what is needed for Forester to be a good citizen of the World Wide Web: in particular, <mark>if we emit an RSS feed that has hyperlinks to some trees in it, those links <em>must</em> refer to an actual page on the actual web rather than something specific to Forester’s ontology.</mark></p>
31 <p>This may seem downright obvious in hindsight, but you must understand that for the longest time I was not thinking of Forester as a tool for progressively enhancing the Web, but rather as a tool for building fully-local life-wikis or Zettelkästen; I no longer believe that my former viewpoint is reasonable, and I have concluded that we must integrate Forester into the Web or else we will be buried under friction. This post is the start of a design for how to do this.</p>
32 <p>Forget what you know about how either <a href="https://www.forester-notes.org/jms-011P/">Forester 5.0</a> or previous versions currently work; in order to solve these problems in a reasonable way, we cannot be bound by the past versions of an experimental tool. What we <em>are</em> bound by is the architecture of the World Wide Web, and that will be reflected in the design.</p>
33 </section>
34 <section>
35 <header>
36 <h2>What is the proposal?</h2>
37 </header>
38 <p>Here is the essence of the proposal:</p>
39 <ol><li>We get rid of the <code>forest://host/addr</code> scheme. Instead, trees are globally addressed by a canonical URL.</li>
40 <li>The canonical URL of a tree can in principle be arbitrary, but in practice you will want it to be a place where that tree can be viewed — e.g. the place to which it will be uploaded and served via HTTP(S). Indeed, a default scheme will be provided so as to enable files to be rendered with names and relative locations consistent with the intended global addressing scheme; it is also possible to imagine customisation of this without disturbing the overall design.</li>
41 <li>The canonical URLs are now the vertices of the graph.</li>
42 <li>In Forester source code, a hyperlink like <code><]]></code> would be resolved right away to <code><]]></code> or something, using information supplied in the user’s forest; the same goes for transclusion.</li>
43
44 <li>Links to trees in foreign forests must, for now, be totally explicit (but we can imagine relaxing this in the future). Importantly, this approach does not require knowing what is in the forest at evaluation-time.</li></ol>
45 </section>
46 <section>
47 <header>
48 <h2>What about replication and mirroring?</h2>
49 </header>
50 <p>It may seem annoying to have canonical URLs. For example, a forest that contains vital information might need to be published in multiple places. That much is true, but the fact that the physical publication of a forest is replicated should not allowed to impact the graph or fill it with redundant vertices and edges (e.g. should two mirrors become federated). So the only problem with replication is that hyperlinks might take you to the original forest instead of keeping you in the mirror, but I think this should be resolved by some kind of middleware that rewrites links, just as the <a href="https://web.archive.org/">Wayback machine</a> rewrites links in its snapshots. That can be handled outside of Forester.</p>
51 </section>
52 <section>
53 <header>
54 <h2>What about viewing my forest locally?</h2>
55 </header>
56 <p>Most of the time, an author is working with their forest on their own machine rather than on the web. It is important that links and transclusions point to the local content rather than whatever (if anything) is stored in the “global” canonical URL. I believe this is not actually a problem: although things like RSS feeds and perhaps even published websites would have all the hyperlinks point to the canonical URLs, there is no reason that this should be required for all renderers. It is easy to imagine making this a configurable flag for the default renderer, and for the upcoming “dynamic”/interactive HTML server we would emit links back to the local server rather than to the canonical URLs.</p>
57 <p>Similarly, there may be projects where there is no intention at all of online publication. In such cases, the scheme for assigning canonical URLs can be arbitrary.</p>
58 </section>
59 <section>
60 <header>
61 <h2>What about access control?</h2>
62 </header>
63 <p>Forester does not currently support any kind of access control, but this is indeed an important area that we are considering carefully in order to enable institutional use of Forester, and ease the burden of collaboration in the usual case of a forest that contains a mixture of data with varying levels of confidentiality. I believe that the current design is compatible with essentially any approach to access control that we might adopt, but I am interested in feedback to the contrary.</p>
64 </section>
65 </div>
66 </content>
67 </entry>
68 <entry>
69 <title>Towards Forester 5.0: a design for global identity</title>
70 <published>2025-03-08T12:17:14Z</published>
71 <updated>2025-03-08T12:17:14Z</updated>
72 <author>
73 <name>Jon Sterling</name>
74 <uri>https://www.forester-notes.org/jonmsterling/</uri>
75 </author>
76 <link rel="alternate" type="text/html" href="https://www.forester-notes.org/OYOJ/" />
77 <id>https://www.forester-notes.org/OYOJ/</id>
78 <content type="xhtml">
79 <div xmlns="http://www.w3.org/1999/xhtml">
80 <p>As we move closer to <a href="https://www.forester-notes.org/jms-011P/">Forester 5.0</a>, which <a href="https://www.forester-notes.org/30FN/">introduces</a> rudimentary federation capabilities, we must address new problems that did not arise in the days when no two <a href="https://www.forester-notes.org/tfmt-000R/">forests</a> interacted or linked to each other. The most immediate issue is that trees describing entities with “global” identity (including actual people as well as bibliographic references) will naturally be duplicated across many forests. For example, this happens when one person authors trees in multiple forests, and it happens even more often with bibliographic entries (both for the entries themselves and their author attributions). It is very important to handle this problem properly <em>now</em> in a way that (1) minimises friction and (2) enables us to quietly evolve toward <a href="https://www.forester-notes.org/klepmann-et-al-atproto-2024/">more Web-centric approaches to identity as they emerge</a>.</p>
81 <p>Below, I survey some existing approaches to identity that we would hope to be compatible with at some level. If you want to skip to my concrete proposal, see <a href="https://www.forester-notes.org/OYOR/">§ OYOR/</a>.</p>
82 <section>
83 <header>
84 <h2>Survey of global identification schemes</h2>
85 </header>
86 <p>There are several extant schemes for identifying individuals, organisations, and artefacts. Some are centralised, and others are decentralised. Centralisation of identity is not necessarily a bad thing, but it is most viable when nearly everyone agrees on the central authority; on the other hand, decentralisation can help in situations where a single central authority has not accumulated enough trust or prestige to be viable.</p>
87 <section>
88 <header>
89 <h3>Centralised identification via DOIs and ORCIDs</h3>
90 </header>
91 <p>Nearly every scholarly paper and book published has a <em>Digital Object Identifier</em> (DOI) assigned to it, which are managed by a single authority (<a href="https://www.doi.org/">The DOI Foundation</a>); this applies to both traditional publishers and eprint servers like the arXiv. Services like <a href="https://zenodo.org/">Zenodo</a> allow individuals to mint their own DOIs and pin resources and artefacts to them. Due to their widespread adoption, DOIs are a completely viable way to identify published papers and books—and I would argue that any attempt to replace DOIs with a decentralised identifier is likely to be counterproductive as the goal should not not be decentralisation <em>per se</em> but rather to have a reliable, universal way to refer to scholarly content and artefacts.</p>
92 <p>What DOIs do for artefacts, the <em>Open Researcher and Contributor ID</em> (ORCID) aims to do for <em>people</em> acting within the framework of open science. ORCIDs seem to do their job well, but not everyone has or should have an ORCID—nor would every person who does have one voluntarily choose to pin their entire identity to it. Therefore, although I happily use them, I think ORCIDs are likely to face more of an uphill battle than the DOI—which needed buy-in only from major publishers and eprint servers to reach hegemony.</p>
93 </section>
94 <section>
95 <header>
96 <h3>Informal decentralised identification via web addresses</h3>
97 </header>
98 <p>A particularly simple way to identify a single person or organisation is by means of a web domain or an email address. Although not everyone has a domain name, many people have email addresses. On the other hand, people often have many domain names and their email address may change over time; and when people die, their presence on the web is often erased or lost. Therefore, although widespread, this approach may create difficulties with longevity and stability.</p>
99 </section>
100 <section>
101 <header>
102 <h3>General-purpose decentralised identification via DIDs</h3>
103 </header>
104 <p>When reading about the paper of <a href="https://www.forester-notes.org/klepmann-et-al-atproto-2024/">Klepmann et al.</a> outlining Bluesky’s AT Protocol, I learned of <a href="https://www.w3.org/TR/did-1.0/"><em>Decentralised Identifiers</em> (DIDs)</a>. In essence, DIDs are URIs of the form <code>did:method:path</code> where <code>method</code> identifies <em>how</em> the DID is intended to be resolved and <code>path</code> is a colon-separated path that should be resolved by means of that method. In either case, a DID is intended to be resolved to a JSON document that contains information about the resource or entity being described, as well as various methods (like public keys) for verifying the integrity of that information. The <em>methods</em> are somewhat open-ended, but two important methods have emerged.</p>
105 <section>
106 <header>
107 <h4>W3C’s <code>did:web</code> method</h4>
108 </header>
109 <p><a href="https://w3c-ccg.github.io/did-method-web/">W3C have specified the <code>did:web</code> method</a>, which in which the <code>path</code> is intended to be a web domain. Simplifying somewhat, a DID like <code>did:web:jonmsterling.com</code> would be substantiated by responding to the HTTPS request <code>https://jonmsterling.com/.well-known/did.json</code> with a document in the appropriate format. The upside is that the owner of a web domain is <em>their own</em> identity authority; in this sense <code>did:web</code> is a truly decentralised identification scheme. The downside is that you have to have a web domain, and you also can never change it ever—the <a href="https://www.forester-notes.org/OYOK/">same disadvantage of informal decentralised identification which we have discussed</a>.</p>
110 </section>
111 <section>
112 <header>
113 <h4>Bluesky’s <code>did:plc</code> method</h4>
114 </header>
115 <p>For a social network like Bluesky, it is critical that users be able to migrate their identity from one domain to another. Obviously users may change or lose their domain over time, but it is important to keep in mind that the vast majority of users will <em>never</em> have their own domain and so they will over the course of their lives jump from one subsidiary domain that they don’t control to the next—just as Mastodon users are constantly migrating from instance to instance, driven to wander endlessly by either the petty tyranny of instance maintainers who think they know best, or by the natural quiescence of instances caused by lack of funds or time, or (in many cases) a combination of the two.</p>
116 <p>It seems that there is no way to address this problem without introducing some central authority—a <em>directory</em> of permanent identifiers that are then resolved to documents that establish cryptographically verified bidirectional links with more ephemeral and human-readable forms of identification (such as web domains). This is essentially the design of Bluesky’s <code>did:plc</code> method, as explained by <a href="https://www.forester-notes.org/klepmann-et-al-atproto-2024/">Klepmann et al.</a>:</p>
117 <ol><li>On your own domain, which serves as your (ephemeral) handle, you place a DNS TXT record or file that contains a DID like <code>did:plc:asdlkfh9q8034baliufhbcailurb</code>.</li>
118 <li>Someone resolves this DID to a document by querying a central <em>directory server</em> (such as <a href="https://web.plc.directory/">Bluesky’s own</a>). This document contains a link back to the domain; signatures are used to ensure that every update to the document has been authorised by whoever signed it when it was first minted.</li></ol>
119 <p>Although some centralisation is required here, the use of cryptographic proof ensures that the central authority does not need to be trusted (to a certain extent).</p>
120 </section>
121 </section>
122 </section>
123 <section>
124 <header>
125 <h2>Analysis of global identity in Forester</h2>
126 </header>
127 <p>Although Forester aims to become a better citizen of the Web and integrate with emerging protocols, it is a non-negotiable design constraint that Forester still remain usable by people who don’t control a domain name, cannot run software on their web host, cannot set DNS records, and could not care less what a <a href="https://www.forester-notes.org/OYON/">DID</a> is. I also have a feeling that there will not be a single protocol that fits all use cases; what I am noticing, however, is that there are commonalities to all the protocols, and that we ought to be informed by these commonalities. For example, in every case an identity is resolved from a URI of some kind—for example, DIDs and DOIs and ORCIDs all have canonical URIs.</p>
128 <p>Therefore, it strikes me that Forester’s approach to global identity must rest on the axiom that an identity is nothing more or less than a URI; we can place no constraints whatsoever on what form this URI takes, and we should also remain flexible as to compatibility with future replacements of URIs (whether in the form of IRIs, or the <a href="https://www.forester-notes.org/jms-011R/">URL non-“standard”</a>, etc.).</p>
129 <p>If we start from that point of view, there some problems to address:</p>
130 <ol><li>Even if an identity is not canonically addressed by a tree in a forest, an identity still often needs to <em>have</em> a tree in the forest. One wants to store biographical and bibliographic information, and maybe even personal notes, etc., and at the very least it is very important to be able to browse backlinks on a biographical page even if the page itself has no content of its own.</li>
131 <li>Not only must we be able to attach a tree to an identity: we must be able to attach <em>many</em> trees to an identity. This is a requirement of federation.</li></ol>
132 </section>
133 <section>
134 <header>
135 <h2>A plan for global identity in Forester</h2>
136 </header>
137 <p>Building on my <a href="https://www.forester-notes.org/OYOQ/">analysis</a>, I propose that Forester allow any tree to declare that it “describes” a given global identity in the form of a URI. At a first cut this can be done via datalog (but we would probably hide this behind something):</p>
138 <pre><![CDATA[\execute\datalog{
139 -: {\rel/describes \current-tree @{https://orcid.org/0000-0002-0585-5564}}
140}]]></pre>
141 <p>Now it remains to explain how we shall surface the fact that a given entity is described by some tree.</p>
142 <ol><li>For any identity in this relation, we should automatically create a “disambiguation page” that transcludes all the attached trees.</li>
143 <li>When a hyperlink points to a URI that lies in this relation, it should be directed to the disambiguation page.</li></ol>
144 <p>There are further implications for such a feature—for instance, in the future we might automatically populate bibliographic information, etc. (But we have to be careful due to the near-universal unusably low quality of bibliographic databases keyed by DOIs, etc.)</p>
145 <p>We will need to provide guidance as to how identities should be assigned to (e.g.) people who don’t control an online identity, etc. The rule of thumb should be that we always defer to the preferences of the described person, and to the version of record in the case of an artefact. When there is no canonical choice, users of Forester should do what they like, but they should be willing to update their references in the future should a canonical global entity emerge.</p>
146 </section>
147 <section>
148 <header>
149 <h2>Request for comment</h2>
150 </header>
151 <p>I am hoping to hear other people’s thoughts on this proposal, including any constructive criticisms or suggestions for how we might go about implementing it. You can write to me or the <a href="mailto:~jonsterling/forester-discuss@lists.sr.ht">mailing list</a> with your feedback.</p>
152 </section>
153 </div>
154 </content>
155 </entry>
156 <entry>
157 <title>Build your own Stacks Project in 10 minutes</title>
158 <published>2023-05-14T00:00:00Z</published>
159 <updated>2024-04-25T00:00:00Z</updated>
160 <author>
161 <name>Jon Sterling</name>
162 <uri>https://www.forester-notes.org/jonmsterling/</uri>
163 </author>
164 <link rel="alternate" type="text/html" href="https://www.forester-notes.org/jms-0052/" />
165 <id>https://www.forester-notes.org/jms-0052/</id>
166 <content type="xhtml">
167 <div xmlns="http://www.w3.org/1999/xhtml">
168 <p><a href="https://www.forester-notes.org/stacks-project/">The Stacks project</a> is the most successful scientific hypertext project in history. Its goal is to lay the foundations for the theory of algebraic stacks; to facilitate its scalable and sustainable development, several important innovations have been introduced, with the <em>tags</em> system being the most striking.</p>
169 <blockquote>Each tag refers to a unique item (section, lemma, theorem, etc.) in order for this project to be referenceable. These tags don't change even if the item moves within the text. (<a href="https://stacks.math.columbia.edu/tags">Tags explained</a>, <a href="https://www.forester-notes.org/stacks-project/">The Stacks Project</a>).</blockquote>
170 <p>Many working scientists, students, and hobbyists have wished to create their own tag-based hypertext knowledge base, but the combination of tools historically required to make this happen are extremely daunting. Both the <a href="https://www.forester-notes.org/stacks-project/">Stacks project</a> and <a href="https://www.forester-notes.org/kerodon/">Kerodon</a> use a cluster of software called <a href="https://www.forester-notes.org/gerby/">Gerby</a>, but bitrot has set in and it is <a href="https://github.com/gerby-project/plastex/issues/60">no longer possible</a> to build its dependencies on a modern environment without significant difficulty, raising questions of longevity.</p>
171 <p>Moreover, <a href="https://www.forester-notes.org/gerby/">Gerby</a>’s deployment involves running a database on a server (in spite of the fact that almost the entire functionality is static HTML), an architecture that is incompatible with the constraints of the everyday working scientist or student who knows <em>at most</em> how to upload static files to their university-provided public storage. The recent experience of the <a href="https://ncatlab.org/nlab/show/HomePage">nLab</a>’s pandemic-era hiatus and near death experience has demonstrated with some urgency the pracarity faced by any project relying heavily on volunteer system administrators.</p>
172 <section>
173 <header>
174 <h2>Introducing <a href="https://www.forester-notes.org/index/"><em>Forester</em></a>: a <a href="https://www.forester-notes.org/tfmt-0002/">tool for scientific thought</a></h2>
175 </header>
176 <p>After spending two years exploring the <a href="https://www.forester-notes.org/tfmt-0001/">design of tools for scientific thought</a> that meet the unique needs of real, scalable scientific writing in hypertext, I have created a tool called <strong><a href="https://www.forester-notes.org/index/">Forester</a></strong> which has the following benefits:</p>
177 <ol><li><a href="https://www.forester-notes.org/index/">Forester</a> is tag-based like <a href="https://www.forester-notes.org/gerby/">Gerby</a>, and can therefore power large-scale generational projects like <a href="https://www.forester-notes.org/stacks-project/">Stacks</a> and <a href="https://www.forester-notes.org/kerodon/">Kerodon</a>.</li>
178 <li><a href="https://www.forester-notes.org/index/">Forester</a> produces static content that <a href="https://www.forester-notes.org/jms-007R/">can be uploaded to any web hosting service</a> without needing to run or install any serverside software.</li>
179 <li><a href="https://www.forester-notes.org/index/">Forester</a> is <a href="https://www.forester-notes.org/jms-006W/">easy to install</a> on your own machine.</li>
180 <li>To prevent bitrot, <a href="https://www.forester-notes.org/index/">Forester</a> is a single tool rather than a composition of several tools.</li>
181 <li><a href="https://www.forester-notes.org/index/">Forester</a> satisfies <em>all</em> the <a href="https://www.forester-notes.org/tfmt-000E/">requirements of serious scientific writing</a>, including sophisticated notational macros, typesetting of diagrams, etc.</li></ol>
182 <p><a href="https://www.forester-notes.org/index/">Forester</a> combines <a href="https://www.forester-notes.org/tfmt-0005/">associative and hierarchical</a> networks of <a href="https://www.forester-notes.org/tfmt-0003/">evergreen notes</a> (called “trees”) into hypertext sites called “forests”.</p>
183 <section>
184 <header>
185 <h3>Forests and trees of evergreen notes</h3>
186 </header>
187 <p>A <em>forest of <a href="https://www.forester-notes.org/tfmt-0003/">evergreen notes</a></em> (or a <em>forest</em> for short) is loosely defined to be a collection of <a href="https://www.forester-notes.org/tfmt-0003/">evergreen notes</a> in which multiple <a href="https://www.forester-notes.org/tfmt-0005/">hierarchical structures</a> are allowed to emerge and evolve over time. Concretely, one note may contextualize several other notes via transclusion within its textual structure; in the context of a forest, we refer to an individual note as a <em>tree</em>. Of course, a tree can be viewed as a forest that has a root node.</p>
188 </section>
189 <p>Trees correspond roughly to what are referred to as “tags” in the <a href="https://www.forester-notes.org/stacks-project/">Stacks Project</a>.</p>
190 </section>
191 <p>In this article, I will show you how to set up your own <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> using the <a href="https://www.forester-notes.org/index/">Forester</a> software. <mark>These instructions pertain to the <a href="https://www.forester-notes.org/jms-00S9/">Forester 4.1</a> version.</mark></p>
192 <section>
193 <header>
194 <h2>Preparing to run the <a href="https://www.forester-notes.org/index/">Forester</a> software</h2>
195 </header>
196 <p>In this section, we will walk through the installation of the <a href="https://www.forester-notes.org/index/">Forester</a> software.</p>
197 <section>
198 <header>
199 <h3>System requirements of <a href="https://www.forester-notes.org/index/">Forester</a></h3>
200 </header>
201 <section>
202 <header>
203 <h4>A unix-based system</h4>
204 </header>
205 <p><a href="https://www.forester-notes.org/index/">Forester</a> requires a unix-based system to run; it has been tested on both macOS and Linux. Windows support is <a href="https://todo.sr.ht/~jonsterling/forester/6">desirable</a>, but there are no concrete plans to implement it at this time.</p>
206 </section>
207 <section>
208 <header>
209 <h4>A working OCaml 5 installation</h4>
210 </header>
211 <p><a href="https://www.forester-notes.org/index/">Forester</a> is written in the <a href="https://www.ocaml.org/">OCaml</a> programming language, and makes use of the latest features of OCaml 5. Most users should install <a href="https://www.forester-notes.org/index/">Forester</a> through OCaml's <a href="https://opam.ocaml.org/">opam</a> package manager; instructions to install opam and OCaml simultaneously can be found <a href="https://opam.ocaml.org/">here</a>.</p>
212 </section>
213 <section>
214 <header>
215 <h4>A working <code>\LaTeX </code> installation</h4>
216 </header>
217 <p>If you intend to <a href="https://www.forester-notes.org/tfmt-000L/">embed <code>\LaTeX </code>-rendered diagrams</a> in your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a>, you will need to have a working installation of <code>\LaTeX </code> installed, such as <a href="https://tug.org/texlive/">TeX Live</a>. If all your mathematical expressions are supported by <a href="https://katex.org/"><code>\KaTeX </code></a>, this is not necessary.</p>
218 </section>
219 <section>
220 <header>
221 <h4>The <a href="https://git-scm.com/">git</a> distributed version control system</h4>
222 </header>
223 <p>It is best practice to maintain your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> inside of <a href="https://en.wikipedia.org/wiki/Distributed_version_control">distributed version control</a>. This serves not only as a way to prevent data loss (because you will be pushing frequently to a remote repository); it also allows you to easily roll back to an earlier version of your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a>, or to create “branches” in which you prepare <a href="https://www.forester-notes.org/tfmt-000R/">trees</a> that are not yet ready to be integrated into the <a href="https://www.forester-notes.org/tfmt-000R/">forest</a>.</p>
224 <p>The recommended <a href="https://en.wikipedia.org/wiki/Distributed_version_control">distributed version control</a> system is <a href="https://git-scm.com/">git</a>, which comes preinstalled on many unix-based systems and is easy to install otherwise. <a href="https://git-scm.com/">Git</a> is not the most user-friendly piece of software, unfortunately, but it is ubiquitous. It is possible (but not recommended) to use <a href="https://www.forester-notes.org/index/">Forester</a> without version control, but note that the simplest way to <a href="https://www.forester-notes.org/jms-006X/">initialize your own <a href="https://www.forester-notes.org/tfmt-000R/">forest</a></a> involves cloning a <a href="https://git-scm.com/">git</a> repository.</p>
225 </section>
226 </section>
227 <section>
228 <header>
229 <h3>Installing the <a href="https://www.forester-notes.org/index/">Forester</a> software</h3>
230 </header>
231 <p>Once you have met the <a href="https://www.forester-notes.org/jms-006S/">system requirements</a>, installing <a href="https://www.forester-notes.org/index/">Forester</a> requires only a single shell command:</p>
232 <pre><![CDATA[opam install forester]]></pre>
233 <p>To verify that <a href="https://www.forester-notes.org/index/">Forester</a> is installed, please run <code>forester --version</code> in your shell.</p>
234 </section>
235 </section>
236 <section>
237 <header>
238 <h2>Setting up your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> from the template</h2>
239 </header>
240 <p>Now that you have <a href="https://www.forester-notes.org/jms-006W/">installed</a> the <a href="https://www.forester-notes.org/index/">Forester</a> software, it is time to set up your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a>. <a href="https://www.forester-notes.org/index/">Forester</a> provides a simple command to initialise a fresh <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> within a folder. We’ll call our folder <code>forest</code>, but you can call it anything you want.</p>
241 <pre><![CDATA[mkdir forest
242cd forest]]></pre>
243 <p>Now that we are inside our new directory, we can instruct <a href="https://www.forester-notes.org/index/">Forester</a> to initialise a <a href="https://www.forester-notes.org/tfmt-000R/">forest</a>.</p>
244 <pre>forester init</pre>
245 <p>This command initialises a <a href="https://git-scm.com/">git</a> repository with the skeleton of a <a href="https://www.forester-notes.org/tfmt-000R/">forest</a>, which contains a configuration file named <code>forest.toml</code>; this file specifies the locations of your trees, assets, etc. There is also a <a href="https://git-scm.com/">git</a> submodule bound to the <code>theme/</code> directory (pointing to the <a href="https://git.sr.ht/~jonsterling/forester-base-theme">base theme</a> repository) that contains the stylesheets that web browsers will need in order to render your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> as HTML.</p>
246 <section>
247 <header>
248 <h3>Tree addresses in a <a href="https://www.forester-notes.org/tfmt-000R/">forest</a></h3>
249 </header>
250 <p>A <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> in <a href="https://www.forester-notes.org/index/">Forester</a> is usually associated to an address of the form <code>xxx-NNNN</code> where <code>xxx</code> is <em>your</em> chosen “namespace” (most likely your initials) and <code>NNNN</code> is a four-digit <a href="https://www.forester-notes.org/jms-0074/">base-36 number</a>. The purpose of the namespace and the <a href="https://www.forester-notes.org/jms-0074/">base-36</a> code is to uniquely identify a <a href="https://www.forester-notes.org/tfmt-000R/">tree</a>, not only within your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> but across all <a href="https://www.forester-notes.org/tfmt-000R/">forests</a>. A tree with address <code>xxx-NNNN</code> is stored in a file named <code>xxx-NNNN.tree</code> (unless it is emitted from inside another tree by means of the <a href="https://www.forester-notes.org/jms-00O4/">inline subtrees</a> feature).</p>
251 <p>Note that the format of <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> addresses is purely a matter of convention, and is not forced by the <a href="https://www.forester-notes.org/index/">Forester</a> tool. Users are free to use their own format for tree addresses, and in some cases alternative (human-readable) formats may be desirable: this includes trees representing bibliographic references, as well as biographical trees.</p>
252 </section>
253 <section>
254 <header>
255 <h3>Building and viewing your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> for the first time</h3>
256 </header>
257 <p>To build your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a>, you can run the following command of <a href="https://www.forester-notes.org/index/">Forester</a>'s executable in your shell:</p>
258 <pre>forester build forest.toml</pre>
259 <p>The <code>--dev</code> flag is optional, and when activated supplies metadata to the generated website to support an “edit button” on each tree; this flag is meant to be used when developing your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> locally, and should not be used when building the <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> to be uploaded to your public web host.</p>
260 <section>
261 <header>
262 <h4><a href="https://www.forester-notes.org/index/">Forester</a> renders each tree to an XML document</h4>
263 </header>
264 <p><a href="https://www.forester-notes.org/index/">Forester</a> renders your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> to some XML files in the <code>output/</code> directory; XML is, like HTML, a format for structured documents that can be displayed by web browsers. The <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> template comes equipped with a built-in XSLT stylesheet (<code>theme/default.xsl</code>) which is used to instruct web browsers how to render your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> into a pleasing and readable format.</p>
265 </section>
266 <section>
267 <header>
268 <h4>Serving and viewing your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> from a local web server</h4>
269 </header>
270 <p>The recommended and most secure way to view your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> while editing it is to <em>serve</em> it from a local web server. To do this, first ensure that you have <a href="https://www.python.org/downloads/">Python 3</a> correctly installed. Then run the following command from the root directory of your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a>:</p>
271 <pre>python3 -m http.server 1313 -d output</pre>
272 <p>While this command is running, you will be able to access your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> by navigating to <a href="http://localhost:1313/index.xml"><code>localhost:1313/index.xml</code></a> in your preferred web browser.</p>
273 <p>In the future, <a href="https://www.forester-notes.org/index/">Forester</a> <a href="https://todo.sr.ht/~jonsterling/forester/15">may be able to run its own local server</a> to avoid the dependency on external tools like Python.</p>
274 </section>
275 <section>
276 <header>
277 <h4>Viewing your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> locally without a local web server</h4>
278 </header>
279 <p>It is also possible to open the generated file <code>output/index.xml</code> <em>directly</em> in your web browser. Unfortunately, modern web browsers by default prevent the use of XSLT stylesheets on the local file system for security reasons. Because <a href="https://www.forester-notes.org/jms-007G/"><a href="https://www.forester-notes.org/index/">Forester</a>'s output format is XML</a>, the output cannot be viewed directly in your web browser without disabling this security feature (at your own risk). Users who do not understand the risks involved should <a href="https://www.forester-notes.org/jms-007I/">turn back and use a local web server instead</a>, which is more secure; if you understand and are willing to accept the risks, you may proceed as follows depending on your browser.</p>
280 <section>
281 <header>
282 <h5>Configuring Firefox for viewing a local <a href="https://www.forester-notes.org/tfmt-000R/">forest</a></h5>
283 </header>
284 <p>To configure Firefox for viewing your local <a href="https://www.forester-notes.org/tfmt-000R/">forest</a>, navigate to <code>about:config</code> in your address bar.</p>
285 <ol><li>Firefox will present a page warning you to <em>“Proceed with Caution”</em>: you must <em>“Accept the Risk and Continue”</em>.</li>
286 <li>In the “Search preference name” box, search for <code>security.fileuri.strict_origin_policy</code>.</li>
287 <li>Most likely, the <code>security.fileuri.strict_origin_policy</code> will appear set to <code>true</code>. Double click on the word <code>true</code> to toggle it to <code>false</code>.</li></ol>
288 </section>
289 <section>
290 <header>
291 <h5>Configuring Safari for viewing a local <a href="https://www.forester-notes.org/tfmt-000R/">forest</a></h5>
292 </header>
293 <p>To configure Safari for viewing your local <a href="https://www.forester-notes.org/tfmt-000R/">forest</a>, you must activate the <em>Develop</em> menu and then toggle one setting.</p>
294 <ol><li>Open Safari's settings window.</li>
295 <li>In the <em>Advanced</em> tab, check the <em>“Show Develop menu in menu bar”</em> checkbox at the bottom.</li>
296 <li>Open the <em>Develop</em> menu in the menubar, and select <em>“Disable Local File Restrictions”</em>.</li></ol>
297 </section>
298 </section>
299 </section>
300 </section>
301 <section>
302 <header>
303 <h2>Creating your personal biographical <a href="https://www.forester-notes.org/tfmt-000R/">tree</a></h2>
304 </header>
305 <p>The first <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> that you should create is a biographical tree to represent your own identity; ultimately you will link to this tree when you set the <a href="https://www.forester-notes.org/tfmt-000S/">authors</a> of other <a href="https://www.forester-notes.org/tfmt-000R/">trees</a> that you create later on. Although most <a href="https://www.forester-notes.org/tfmt-000R/">trees</a> will be addressed by <a href="https://www.forester-notes.org/jms-0073/">identifiers of the form <code>xxx-NNNN</code></a>, it is convenient to simply use a person’s full name to address a biographical <a href="https://www.forester-notes.org/tfmt-000R/">tree</a>. <a href="https://www.forester-notes.org/jonmsterling/">My own biographical tree</a> is located at <code>trees/people/jonmsterling.tree</code> and contains the following source code:</p>
306 <pre><![CDATA[\title{Jon Sterling}
307\taxon{Person}
308\meta{external}{https://www.jonmsterling.com/}
309\meta{institution}{[[ucam]]}
310\meta{orcid}{0000-0002-0585-5564}
311\meta{position}{Associate Professor}
312
313\p{Associate Professor in Logical Foundations and Formal Methods at University of Cambridge. Formerly a [Marie Skłodowska-Curie Postdoctoral Fellow](jms-0061) hosted at Aarhus University by [Lars Birkedal](larsbirkedal), and before this a PhD student of [Robert Harper](robertharper).}]]></pre>
314 <p>Let’s break this code down to understand what it does.</p>
315 <ol><li>The declaration <code><![CDATA[\title{Jon Sterling}]]></code> sets the title of the <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> to my name.</li>
316 <li>The <code><![CDATA[\taxon{Person}]]></code> declaration informs <a href="https://www.forester-notes.org/index/">Forester</a> that the <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> is biographical. Not ever <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> needs to have a taxon; common taxa include <code>person</code>, <code>theorem</code>, <code>definition</code>, <code>lemma</code>, <code>blog</code>, etc. You are free to use whatever you want, but some taxa are treated specially by <a href="https://www.forester-notes.org/index/">Forester</a>.</li>
317 <li>The subsequent <code><![CDATA[\meta]]></code> declarations attach additional information to the tree that can be used during rendering. These declarations are optional, and you are free to put whatever metadata you want.</li>
318 <li>Like in HTML, paragraphs must be wrapped in <code><![CDATA[\p{...}]]></code>.</li></ol>
319 <p>Do not hard-wrap your text, as this can have visible impact on how <a href="https://www.forester-notes.org/tfmt-000R/">trees</a> are rendered; it is recommended that you use a text editor with good support for soft-wrapping, like <a href="https://code.visualstudio.com/">Visual Studio Code</a>.</p>
320 <p>You can see that the <a href="https://www.forester-notes.org/jms-007N/">concrete syntax of <a href="https://www.forester-notes.org/index/">Forester</a>'s <a href="https://www.forester-notes.org/tfmt-000R/">trees</a></a> looks superficially like a combination of <code>\LaTeX </code> and Markdown; Markdown-style links are used both for links to other trees <em>and</em> for links to external URLs. <a href="https://www.forester-notes.org/index/">Forester</a>'s concrete syntax is not fully documented, but it is less ambiguous than both <code>\LaTeX </code> and Markdown.</p>
321 </section>
322 <section>
323 <header>
324 <h2>Creating a new <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> using <code>forester new</code></h2>
325 </header>
326 <p>Creating a new <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> in your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> is as simple as adding a <code>.tree</code> file to the <code>trees</code> folder. Because it is hard to manually choose the <a href="https://www.forester-notes.org/jms-0073/">next incremental tree address</a>, <a href="https://www.forester-notes.org/index/">Forester</a> provides a command to do this automatically. If your chosen <a href="https://www.forester-notes.org/jms-0073/">namespace prefix</a> is <code>xxx</code>, then you should use the following command in your shell to create a new tree:</p>
327 <pre>forester new forest.toml --dest=trees --prefix=xxx</pre>
328 <p>In return, <a href="https://www.forester-notes.org/index/">Forester</a> should output the location of the new tree, e.g. <code>trees/xxx-0002.tree</code>. If we look at the contents of this new file, we will see that it is empty except for metadata assigning a date to the tree:</p>
329 <pre><![CDATA[\date{2023-08-15}]]></pre>
330 <p><strong>Most <a href="https://www.forester-notes.org/tfmt-000R/">trees</a> should have a <code><![CDATA[\date]]></code> annotation;</strong> this date is meant to be the date of the <a href="https://www.forester-notes.org/tfmt-000R/">tree</a>'s creation. You should proceed by adding further metadata: the title and the <a href="https://www.forester-notes.org/tfmt-000S/">author</a>; for the latter, you will use the address of your <a href="https://www.forester-notes.org/jms-007K/">personal biographical tree</a>.</p>
331 <pre><![CDATA[\title{My first tree}
332\author{jonmsterling}]]></pre>
333 <p><a href="https://www.forester-notes.org/tfmt-000R/">Tree</a> titles should be given in lower case (except for proper names, etc.); these titles will be <em>rendered</em> by <a href="https://www.forester-notes.org/index/">Forester</a> in sentence case. A <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> can have as many <code><![CDATA[\author]]></code> declarations as it has <a href="https://www.forester-notes.org/tfmt-000S/">authors</a>; these will be rendered in their order of appearance.</p>
334 <p>Now you can begin to populate the tree with its content, written in the <a href="https://www.forester-notes.org/jms-007N/"><a href="https://www.forester-notes.org/index/">Forester</a> markup language</a>. <a href="https://www.forester-notes.org/tfmt-0007/">Think carefully about keeping each tree relatively independent and atomic</a>.</p>
335 </section>
336 <section>
337 <header>
338 <h2>Bottom-up hierarchy via <em>transclusion</em></h2>
339 </header>
340 <p>You may be used to writing <code>\LaTeX </code> documents, where you work from the top down: you create some section headings, put some text under those headings, make some deeper section headings, put more text, etc. <a href="https://www.forester-notes.org/tfmt-000R/">Forests</a> work in the opposite way, from the bottom up: you start by writing independent, <a href="https://www.forester-notes.org/tfmt-0007/">atomic</a> notes/<a href="https://www.forester-notes.org/tfmt-000R/">trees</a> and then only later start to (sparingly) assemble these into a hierarchy in order to reify the emerging structure.</p>
341 <p><a href="https://www.forester-notes.org/index/">Forester</a>’s bottom-up approach to section hierarchy works via something called <em>transclusion</em>. The idea is that at any time, you can include (“transclude”) the full contents of another <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> into the current tree as a subsection by adding the following code:</p>
342 <pre><![CDATA[\transclude{xxx-NNNN}]]></pre>
343 <p>This is kind of like <code>\LaTeX </code>’s <code><![CDATA[\input]]></code> command, but much better behaved: for instance, section levels are computed on the fly depending on the position in the hierarchy. This <a href="https://www.forester-notes.org/jms-0052/">entire tutorial</a> is cobbled together by transcluding many smaller <a href="https://www.forester-notes.org/tfmt-000R/">trees</a>, each with their own independent existence. For example, the following two sections are transcluded from an <a href="https://www.forester-notes.org/tfmt-0001/">entirely different part</a> of my forest:</p>
344 <section>
345 <header>
346 <h3>The best structure to impose is relatively flat</h3>
347 </header>
348 <p>It is easy to make the mistake of prematurely imposing a complex hierarchical structure on a network of notes, which leads to excessive refactoring. Hierarchy should be used sparingly, and its strength is for the large-scale organization of ideas. The best structure to impose on a network of many small related ideas is a relatively flat one. I believe that this is one of the mistakes made in the writing of the <em>foundations of relative category theory</em>, whose hierarchical nesting was too complex and quite beholden to my experience with pre-hypertext media.</p>
349 </section>
350 <p>One of the immediate impacts and strengths of <a href="https://www.forester-notes.org/index/">Forester</a>’s transclusion model is that a given <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> has no canonical “geographic” location in the <a href="https://www.forester-notes.org/tfmt-000R/">forest</a>. One <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> can appear as a child of many other <a href="https://www.forester-notes.org/tfmt-000R/">trees</a>, which allows the same content to be incorporated into different textual and intellectual narratives.</p>
351 <section>
352 <header>
353 <h3>Hierarchical structure as non-unique narrative</h3>
354 </header>
355 <p>Multiple hierarchical structures can be imposed on the same associative network of nodes; a hierarchical structure amounts to a “narrative” that contextualizes a given subgraph of the network. One example could be the construction of lecture notes; another example could be a homework sheet; a further example could be a book chapter or scientific article. Although these may draw from the same body of definitions, theorems, examples, and exercises, these objects are contextualized within a different narrative, often toward fundamentally different ends.</p>
356 <p>As a result, any interface for navigating the neighbor-relation in hierarchically organized notes would need to take account of the multiplicity of parent nodes. Most hypertext tools assume that the position of a node in the hierarchy is unique, and therefore have a single “next/previous” navigation interface; we must investigate the design of interfaces that surface all parent/neighbor relations.</p>
357 </section>
358 </section>
359 <section>
360 <header>
361 <h2>The <a href="https://www.forester-notes.org/index/">Forester</a> markup language</h2>
362 </header>
363 <p>A <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> in <a href="https://www.forester-notes.org/index/">Forester</a> is a single file written in a markup language designed specifically for scientific writing <a href="https://www.forester-notes.org/jms-007L/">with bottom-up hierarchy via transclusion</a>. A <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> has two components: the <a href="https://www.forester-notes.org/jms-007P/">frontmatter</a> and the <a href="https://www.forester-notes.org/jms-007O/">mainmatter</a>.</p>
364 <section>
365 <header>
366 <h3><a href="https://www.forester-notes.org/index/">Forester</a> markup: frontmatter</h3>
367 </header>
368<p>The frontmatter of a <a href="https://www.forester-notes.org/index/">Forester</a> <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> is a sequence of declarations that we summarize below.</p>
369 <table>
370
371 <tr>
372
373 <th>Declaration</th>
374
375
376 <th>Meaning</th>
377
378 </tr>
379
380
381 <tr>
382 <td style="white-space:nowrap">
383 <code><![CDATA[\title{...}]]></code>
384 </td>
385 <td>
386 sets the title of the <a href="https://www.forester-notes.org/tfmt-000R/">tree</a>; can contain <a href="https://www.forester-notes.org/jms-007O/">mainmatter</a> markup
387 </td>
388 </tr>
389
390
391 <tr>
392 <td style="white-space:nowrap">
393 <code><![CDATA[\author{name}]]></code>
394 </td>
395 <td>
396 sets the <a href="https://www.forester-notes.org/tfmt-000S/">author</a> of the <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> to be the biographical tree at address <code>name</code>
397 </td>
398 </tr>
399
400
401 <tr>
402 <td style="white-space:nowrap">
403 <code><![CDATA[\date{YYYY-MM-DD}]]></code>
404 </td>
405 <td>sets the creation date of the <a href="https://www.forester-notes.org/tfmt-000R/">tree</a></td>
406 </tr>
407
408
409 <tr>
410 <td style="white-space:nowrap">
411 <code><![CDATA[\taxon{Taxon}]]></code>
412 </td>
413 <td>sets the taxon of the <a href="https://www.forester-notes.org/tfmt-000R/">tree</a>; example taxa include <code>lemma</code>, <code>theorem</code>, <code>person</code>, <code>reference</code>; the latter two taxa are treated specially by <a href="https://www.forester-notes.org/index/">Forester</a> for tracking biographical and bibliographical <a href="https://www.forester-notes.org/tfmt-000R/">trees</a> respectively</td>
414 </tr>
415
416
417 <tr>
418 <td style="white-space:nowrap">
419 <code><![CDATA[\def\ident[x][y]{body}]]></code>
420 </td>
421 <td>
422 defines and exports from the current <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> a function named <code><![CDATA[\ident]]></code> with two arguments; subsequently, the expression <code><![CDATA[\ident{u}{v}]]></code> would expand to <code>body</code> with the values of <code>u,v</code> substituted for <code><![CDATA[\x,\y]]></code>
423 </td>
424 </tr>
425
426
427 <tr>
428 <td style="white-space:nowrap">
429 <code><![CDATA[\import{xxx-NNNN}]]></code>
430 </td>
431 <td>
432 brings the functions exported by the tree <code>xxx-NNNN</code> into scope
433 </td>
434 </tr>
435
436
437 <tr>
438 <td style="white-space:nowrap">
439 <code><![CDATA[\export{xxx-NNNN}]]></code>
440 </td>
441 <td>
442 brings the functions exported by the tree <code>xxx-NNNN</code> into scope, and exports them from the current tree
443 </td>
444 </tr>
445
446</table>
447 </section>
448 <section>
449 <header>
450 <h3><a href="https://www.forester-notes.org/index/">Forester</a> markup: mainmatter</h3>
451 </header>
452<p>Below we summarize the concrete syntax of the <em>mainmatter</em> in a <a href="https://www.forester-notes.org/index/">Forester</a> <a href="https://www.forester-notes.org/tfmt-000R/">tree</a>.</p>
453 <table>
454
455 <tr>
456
457 <th>Function</th>
458
459
460 <th>Meaning</th>
461
462 </tr>
463
464
465 <tr>
466 <td style="white-space:nowrap">
467 <code><![CDATA[\p{...}]]></code>
468 </td>
469 <td>creates a paragraph containing <code>...</code>; unlike Markdown, it is mandatory to annotate paragraphs explicitly</td>
470 </tr>
471
472
473 <tr>
474 <td style="white-space:nowrap">
475 <code><![CDATA[\em{...}]]></code>
476 </td>
477 <td>typesets the content in italics</td>
478 </tr>
479
480
481 <tr>
482 <td style="white-space:nowrap">
483 <code><![CDATA[\strong{...}]]></code>
484 </td>
485 <td>typesets the content in boldface</td>
486 </tr>
487
488
489
490 <tr>
491 <td style="white-space:nowrap">
492 <code><![CDATA[\ol{...}]]></code>
493 </td>
494 <td>creates an ordered list</td>
495 </tr>
496
497
498
499 <tr>
500 <td style="white-space:nowrap">
501 <code><![CDATA[\ul{...}]]></code>
502 </td>
503 <td>creates an unordered list</td>
504 </tr>
505
506
507
508 <tr>
509 <td style="white-space:nowrap">
510 <code><![CDATA[\li{...}]]></code>
511 </td>
512 <td>creates a list item</td>
513 </tr>
514
515
516
517 <tr>
518 <td style="white-space:nowrap">
519 <code><![CDATA[ #{...}]]></code>
520 </td>
521 <td>typesets the content in (inline) math mode using <code>\KaTeX </code>; note that math mode is idempotent in <a href="https://www.forester-notes.org/index/">Forester</a></td>
522 </tr>
523
524
525 <tr>
526 <td style="white-space:nowrap">
527 <code><![CDATA[ ##{...}]]></code>
528 </td>
529 <td>typesets the content in (display) math mode using <code>\KaTeX </code></td>
530 </tr>
531
532
533 <tr>
534 <td style="white-space:nowrap">
535 <code><![CDATA[\transclude{xxx-NNNN}]]></code>
536 </td>
537 <td><a href="https://www.forester-notes.org/jms-007L/">transcludes</a> the <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> at address <code>xxx-NNNN</code> as a subsection</td>
538 </tr>
539
540
541 <tr>
542 <td style="white-space:nowrap">
543 <code><]]></code>
544 </td>
545 <td>
546 formats the text <code>title</code> as a hyperlink to address <code>address</code>; if <code>address</code> is the address of a <a href="https://www.forester-notes.org/tfmt-000R/">tree</a>, the link will point to that tree, and otherwise it is treated as a URL
547 </td>
548 </tr>
549
550
551 <tr>
552 <td style="white-space:nowrap">
553 <code><![CDATA[\let\ident[x][y]{body}]]></code>
554 </td>
555 <td>
556 defines a local function named <code><![CDATA[\ident]]></code> with two arguments; subsequently, the expression <code><![CDATA[\ident{u}{v}]]></code> would expand to <code>body</code> with the values of <code>u,v</code> substituted for <code><![CDATA[\x,\y]]></code>.
557 </td>
558 </tr>
559
560
561 <tr>
562 <td style="white-space:nowrap">
563 <code><![CDATA[\code{...}]]></code>
564 </td>
565 <td>typesets the content in monospace</td>
566 </tr>
567
568
569 <tr>
570 <td style="white-space:nowrap">
571 <code><![CDATA[\tex{preamble}{body}]]></code>
572 </td>
573 <td>typesets the <code>body</code> externally using <code>\LaTeX </code> using <code>preamble</code> as preamble code (e.g. to set up tikz packages, etc.). It can be useful to wrap this in your own macro in order to insert your preamble code automatically.</td>
574 </tr>
575
576</table>
577 </section>
578 <section>
579 <header>
580 <h3>An complete worked example <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> in <a href="https://www.forester-notes.org/index/">Forester</a></h3>
581 </header>
582 <p>An example of a complete <a href="https://www.forester-notes.org/tfmt-000R/">tree</a> in the <a href="https://www.forester-notes.org/index/">Forester</a> markup language can be seen below.</p>
583 <pre><![CDATA[\title{Creation of (co)limits}
584\date{2023-02-11}
585\taxon{Definition}
586\author{jonmsterling}
587
588\def\CCat{#{\mathcal{C}}}
589\def\DCat{#{\mathcal{D}}}
590\def\ICat{#{\mathcal{I}}}
591\def\Mor[arg1][arg2][arg3]{#{{\arg2}\xrightarrow{\arg1}{\arg3}}}
592
593\p{Let \Mor{U}{\CCat}{\DCat} be a functor and let \ICat be a category. The functor #{U} is said to \em{create (co)limits of #{\ICat}-figures} when for any diagram \Mor{C_\bullet}{\ICat}{\CCat} such that #{\ICat\xrightarrow{C_\bullet}\CCat\xrightarrow{F}\DCat} has a (co)limit, then #{C_\bullet} has a (co)limit that is both preserved and reflected by #{F}.}]]></pre>
594 <p>The code above results in the following tree:</p>
595 <section>
596 <header>
597 <h4>Creation of (co)limits</h4>
598 </header>
599 <p>Let <code>{<code>\mathcal {C}</code>}\xrightarrow {U}{<code>\mathcal {D}</code>}</code> be a functor and let <code>\mathcal {I}</code> be a category. The functor <code>U</code> is said to <em>create (co)limits of <code><code>\mathcal {I}</code></code>-figures</em> when for any diagram <code>{<code>\mathcal {I}</code>}\xrightarrow {C_\bullet }{<code>\mathcal {C}</code>}</code> such that <code><code>\mathcal {I}</code>\xrightarrow {C_\bullet }<code>\mathcal {C}</code>\xrightarrow {F}<code>\mathcal {D}</code></code> has a (co)limit, then <code>C_\bullet </code> has a (co)limit that is both preserved and reflected by <code>F</code>.</p>
600 </section>
601 </section>
602 </section>
603 <section>
604 <header>
605 <h2>Deploying your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> to a web host</h2>
606 </header>
607 <p>Now that you have <a href="https://www.forester-notes.org/jms-006X/">created your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a></a> and <a href="https://www.forester-notes.org/jms-007K/">added a few</a> <a href="https://www.forester-notes.org/jms-007H/"><a href="https://www.forester-notes.org/tfmt-000R/">trees</a> of your own</a>, it is time to upload it to your web host. Many users of <a href="https://www.forester-notes.org/index/">Forester</a> will have university-supplied static web hosting, and others may prefer to use GitHub pages; deploying a <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> works the same way in either case.</p>
608 <ol><li>First, make sure your <a href="https://www.forester-notes.org/tfmt-000R/">forest</a> is built using <a href="https://www.forester-notes.org/jms-007D/">the earlier instructions</a>.</li>
609 <li>Then take the entire contents of your <code>output</code> directory and upload them to your preferred web host.</li></ol>
610 </section>
611 <section>
612 <header>
613 <h2>Let a hundred <a href="https://www.forester-notes.org/tfmt-000R/">forests</a> bloom!</h2>
614 </header>
615 <p>I am eager to see the new <a href="https://www.forester-notes.org/tfmt-000R/">forests</a> that people create using <a href="https://www.forester-notes.org/index/">Forester</a>. I am happy to offer personal assistance via the <a href="https://lists.sr.ht/~jonsterling/forester-discuss">mailing list</a>.</p>
616 <p>Many aspects of <a href="https://www.forester-notes.org/index/">Forester</a> are in flux and not fully documented; it will often be instructive to consult the source of existings <a href="https://www.forester-notes.org/tfmt-000R/">forests</a>, such as <a href="https://git.sr.ht/~jonsterling/forester-notes.org">this one</a>.</p>
617 <p>Have fun, and be sure to send me links to your <a href="https://www.forester-notes.org/tfmt-000R/">forests</a> when you have made them!</p>
618 </section>
619 </div>
620 </content>
621 </entry>
622</feed>