1<!DOCTYPE html><html lang="en" class=""><head><style>.ͼ1.cm-editor.cm-focused {outline: 1px dotted #212121;} 2.ͼ1.cm-editor {position: relative !important; box-sizing: border-box; display: flex !important; flex-direction: column;} 3.ͼ1 .cm-scroller {display: flex !important; align-items: flex-start !important; font-family: monospace; line-height: 1.4; height: 100%; overflow-x: auto; position: relative; z-index: 0;} 4.ͼ1 .cm-content[contenteditable=true] {-webkit-user-modify: read-write-plaintext-only;} 5.ͼ1 .cm-content {margin: 0; flex-grow: 2; flex-shrink: 0; min-height: 100%; display: block; white-space: pre; word-wrap: normal; box-sizing: border-box; padding: 4px 0; outline: none;} 6.ͼ1 .cm-lineWrapping {white-space: pre-wrap; white-space: break-spaces; word-break: break-word; overflow-wrap: anywhere; flex-shrink: 1;} 7.ͼ2 .cm-content {caret-color: black;} 8.ͼ3 .cm-content {caret-color: white;} 9.ͼ1 .cm-line {display: block; padding: 0 2px 0 4px;} 10.ͼ1 .cm-selectionLayer {z-index: -1; contain: size style;} 11.ͼ1 .cm-selectionBackground {position: absolute;} 12.ͼ2 .cm-selectionBackground {background: #d9d9d9;} 13.ͼ3 .cm-selectionBackground {background: #222;} 14.ͼ2.cm-focused .cm-selectionBackground {background: #d7d4f0;} 15.ͼ3.cm-focused .cm-selectionBackground {background: #233;} 16.ͼ1 .cm-cursorLayer {z-index: 100; contain: size style; pointer-events: none;} 17.ͼ1.cm-focused .cm-cursorLayer {animation: steps(1) cm-blink 1.2s infinite;} 18@keyframes cm-blink {50% {opacity: 0;}} 19@keyframes cm-blink2 {50% {opacity: 0;}} 20.ͼ1 .cm-cursor, .ͼ1 .cm-dropCursor {position: absolute; border-left: 1.2px solid black; margin-left: -0.6px; pointer-events: none;} 21.ͼ1 .cm-cursor {display: none;} 22.ͼ3 .cm-cursor {border-left-color: #444;} 23.ͼ1.cm-focused .cm-cursor {display: block;} 24.ͼ2 .cm-activeLine {background-color: #f3f9ff;} 25.ͼ3 .cm-activeLine {background-color: #223039;} 26.ͼ2 .cm-specialChar {color: red;} 27.ͼ3 .cm-specialChar {color: #f78;} 28.ͼ1 .cm-gutters {flex-shrink: 0; display: flex; height: 100%; box-sizing: border-box; left: 0; z-index: 200;} 29.ͼ2 .cm-gutters {background-color: #f5f5f5; color: #6c6c6c; border-right: 1px solid #ddd;} 30.ͼ3 .cm-gutters {background-color: #333338; color: #ccc;} 31.ͼ1 .cm-gutter {display: flex !important; flex-direction: column; flex-shrink: 0; box-sizing: border-box; min-height: 100%; overflow: hidden;} 32.ͼ1 .cm-gutterElement {box-sizing: border-box;} 33.ͼ1 .cm-lineNumbers .cm-gutterElement {padding: 0 3px 0 5px; min-width: 20px; text-align: right; white-space: nowrap;} 34.ͼ2 .cm-activeLineGutter {background-color: #e2f2ff;} 35.ͼ3 .cm-activeLineGutter {background-color: #222227;} 36.ͼ1 .cm-panels {box-sizing: border-box; position: sticky; left: 0; right: 0;} 37.ͼ2 .cm-panels {background-color: #f5f5f5; color: black;} 38.ͼ2 .cm-panels-top {border-bottom: 1px solid #ddd;} 39.ͼ2 .cm-panels-bottom {border-top: 1px solid #ddd;} 40.ͼ3 .cm-panels {background-color: #333338; color: white;} 41.ͼ1 .cm-tab {display: inline-block; overflow: hidden; vertical-align: bottom;} 42.ͼ1 .cm-widgetBuffer {vertical-align: text-top; height: 1em; width: 0; display: inline;} 43.ͼ1 .cm-placeholder {color: #888; display: inline-block; vertical-align: top;} 44.ͼ1 .cm-button {vertical-align: middle; color: inherit; font-size: 70%; padding: .2em 1em; border-radius: 1px;} 45.ͼ2 .cm-button:active {background-image: linear-gradient(#b4b4b4, #d0d3d6);} 46.ͼ2 .cm-button {background-image: linear-gradient(#eff1f5, #d9d9df); border: 1px solid #888;} 47.ͼ3 .cm-button:active {background-image: linear-gradient(#111, #333);} 48.ͼ3 .cm-button {background-image: linear-gradient(#393939, #111); border: 1px solid #888;} 49.ͼ1 .cm-textfield {vertical-align: middle; color: inherit; font-size: 70%; border: 1px solid silver; padding: .2em .5em;} 50.ͼ2 .cm-textfield {background-color: white;} 51.ͼ3 .cm-textfield {border: 1px solid #555; background-color: inherit;} 52.ͼo .cm-scroller {font-family: var(--font-mono);} 53.ͼo .cm-gutters {background: var(--bg); border: none;} 54.ͼo .cm-lineNumbers .cm-gutterElement {font-size: 12px; padding-top: 2px; padding-right: 7px; min-width: 10px;} 55.ͼo .cm-highlight {padding: 0 2px; margin: -1px -2px; border-radius: 2px;} 56.ͼ5 {color: #7a757a;} 57.ͼ6 {text-decoration: underline;} 58.ͼ7 {text-decoration: underline; font-weight: bold;} 59.ͼ8 {font-style: italic;} 60.ͼ9 {font-weight: bold;} 61.ͼa {text-decoration: line-through;} 62.ͼb {color: #708;} 63.ͼc {color: #219;} 64.ͼd {color: #164;} 65.ͼe {color: #a11;} 66.ͼf {color: #e40;} 67.ͼg {color: #00f;} 68.ͼh {color: #30a;} 69.ͼi {color: #085;} 70.ͼj {color: #167;} 71.ͼk {color: #256;} 72.ͼl {color: #00c;} 73.ͼm {color: #940;} 74.ͼn {color: #f00;} 75</style><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta property="og:title" content="Nota Integration Guide"><meta property="og:type" content="article"><meta property="og:description" content="Making a world where you never have to use LaTeX again."><meta property="og:image" content="https://nota-lang.org/android-chrome-512x512.png"><meta name="twitter:card" content="summary"><title>Nota Integration Guide</title><link href="/index.css" rel="stylesheet"></head><body class="base-style"><header><div class="logo"><a href="/"><span class="fancy">N</span>ota</a></div><nav><a href="/examples.html">Examples</a><a href="/playground.html">Playground</a><a href="/reference.html">Reference</a><a href="/integration.html">Integration</a></nav></header><div id="root"><div class="nota-document"><div class="document-title">Nota Integration Guide</div><p>After <a href="/#def-usage">installing Nota</a>, the simplest way to use it is to input a single document and output a single web page. For example, by running:</p><div class="listing"><div class="cm-editor ͼ1 ͼ2 ͼo"><div aria-live="polite" style="position: absolute; top: -10000px;"></div><div tabindex="-1" class="cm-scroller"><div class="cm-gutters" aria-hidden="true" style="min-height: 55.5938px; position: sticky;"><div class="cm-gutter cm-lineNumbers"><div class="cm-gutterElement" style="height: 0px; visibility: hidden; pointer-events: none;">9</div><div class="cm-gutterElement" style="height: 23.7969px; margin-top: 4px;">1</div><div class="cm-gutterElement" style="height: 23.7969px;">2</div></div></div><div spellcheck="false" autocorrect="off" autocapitalize="off" translate="no" contenteditable="false" class="cm-content cm-lineWrapping" style="tab-size: 4" role="textbox" aria-multiline="true"><div class="cm-line">nota edit index.nota</div><div class="cm-line">nota build index.nota</div></div></div></div></div><p>You can write the document using the first command. The second command generates a directory <code>dist</code> containing the ready-to-distribute files, including HTML, CSS, Javascript, and other assets like images. You can put these files on any web hosting service, such as <a href="https://pages.github.com/">Github Pages</a>.</p><p>If you want to use Nota in a broader context, such as a personal website or an online academic journal, the remainder of this guide will explain Nota's overall architecture, and how it can fit into your use case.</p><div class="toc-wrapper"><div class="toc"><div class="toc-header">Table of Contents</div><ol><li><a href="#def-section-1" class="ref">Architecture</a></li><li><a href="#def-section-2" class="ref">Building</a><ol><li><a href="#def-section-2.1" class="ref">esbuild</a></li></ol></li><li><a href="#def-section-3" class="ref">Editing</a><ol><li><a href="#def-section-3.1" class="ref">Build configuration</a></li><li><a href="#def-section-3.2" class="ref">Asset folder</a></li></ol></li></ol></div></div><section><h1 class="section-title"><div id="def-section-1" class="definition"><span class="section-number">1</span> Architecture</div></h1><p>A Nota document is a <a href="https://reactjs.org/">React</a> program. Therefore Nota can be used anywhere React can be used. More specifically, Nota is comprised of three main pieces:</p><ol><li><p><a href="https://github.com/nota-lang/nota/tree/master/packages/nota-syntax"><code>@nota-lang/nota-syntax</code></a>: A document-authoring language that compiles to React JavaScript.</p></li><li><p><a href="https://github.com/nota-lang/nota/tree/master/packages/nota-components"><code>@nota-lang/nota-components</code></a>: A set of React components for structuring documents.</p></li><li><p><a href="https://github.com/nota-lang/nota/tree/master/packages/nota-editor"><code>
75@nota-lang/nota-editor</code></a>: An editor designed for Nota documents.</p></li></ol><p>The complete Nota pipeline (in the <a href="https://github.com/nota-lang/nota/tree/master/packages/nota"><code>@nota-lang/nota</code></a> package) turns a Nota document into a standalone web page. This pipeline includes bundling via <a href="https://esbuild.github.io/">esbuild</a>, as well as server-side rendering via <a href="https://reactjs.org/docs/react-dom-server.html">ReactDOMServer</a>.</p></section><section><h1 class="section-title"><div id="def-section-2" class="definition"><span class="section-number">2</span> Building</div></h1><p>The <code>@nota-lang/nota-syntax</code> package exports two key functions:</p><div class="listing"><div class="cm-editor ͼ1 ͼ2 ͼo"><div aria-live="polite" style="position: absolute; top: -10000px;"></div><div tabindex="-1" class="cm-scroller"><div class="cm-gutters" aria-hidden="true" style="min-height: 52.7812px; position: sticky;"><div class="cm-gutter cm-lineNumbers"><div class="cm-gutterElement" style="height: 0px; visibility: hidden; pointer-events: none;">9</div><div class="cm-gutterElement" style="height: 22.3906px; margin-top: 4px;">1</div><div class="cm-gutterElement" style="height: 22.3906px;">2</div></div></div><div spellcheck="false" autocorrect="off" autocapitalize="off" translate="no" contenteditable="false" class="cm-content cm-lineWrapping" style="tab-size: 4;" role="textbox" aria-multiline="true"><div class="cm-line"><span class="ͼb">let</span> <span class="ͼg">tryParse</span>(<span class="ͼg">input</span>: <span class="ͼi">string</span>): <span class="ͼi">Result</span><<span class="ͼi">lezer</span>.<span class="ͼi">Tree</span>>;</div><div class="cm-line"><span class="ͼb">let</span> <span class="ͼg">translate</span>(<span class="ͼg">input</span>: <span class="ͼi">string</span>, <span class="ͼg">tree</span>: <span class="ͼi">lezer</span>.<span class="ͼi">Tree</span>): {<span class="ͼl">code</span>: <span class="ͼi">string</span>; <span class="ͼl">map</span>?: <span class="ͼi">string</span>};</div></div></div></div></div><p>These functions parse and translate, respectively, a Nota document into a React program (via a <a href="https://lezer.codemirror.net/">Lezer</a> tree). If possible, you should not call these functions directly but rather use a bundler integration. Currently we only support <a href="https://esbuild.github.io/">esbuild</a>, but other integrations are welcome!</p><section><h2 class="section-title"><div id="def-section-2.1" class="definition"><span class="section-number">2.1</span> esbuild</div></h2><p>First, import <code>notaPlugin</code> and add it to your list of plugins:</p><div class="listing"><div class="cm-editor ͼ1 ͼ2 ͼo"><div aria-live="polite" style="position: absolute; top: -10000px;"></div><div tabindex="-1" class="cm-scroller"><div class="cm-gutters" aria-hidden="true" style="min-height: 98px; position: sticky;"><div class="cm-gutter cm-lineNumbers"><div class="cm-gutterElement" style="height: 0px; visibility: hidden; pointer-events: none;">9</div><div class="cm-gutterElement" style="height: 14px;">1</div><div class="cm-gutterElement" style="height: 14px;">2</div><div class="cm-gutterElement" style="height: 14px;">3</div><div class="cm-gutterElement" style="height: 14px;">4</div><div class="cm-gutterElement" style="height: 14px;">5</div><div class="cm-gutterElement" style="height: 14px;">6</div><div class="cm-gutterElement" style="height: 14px;">7</div></div></div><div spellcheck="false" autocorrect="off" autocapitalize="off" translate="no" contenteditable="false" class="cm-content cm-lineWrapping" style="tab-size: 4" role="textbox" aria-multiline="true"><div class="cm-line"><span class="ͼb">import</span> { <span class="ͼg">notaPlugin</span> } <span class="ͼb">from</span> <span class="ͼe">"@nota-lang/nota-syntax/dist/esbuild-plugin.js"</span>;</div><div class="cm-line"><span class="ͼb">import</span> <span class="ͼg">esbuild</span> <span class="ͼb">from</span> <span class="ͼe">"esbuild"</span>;</div><div class="cm-line"><br></div><div class="cm-line">esbuild.build({</div><div class="cm-line"> <span class="ͼm">/* your configuration... */</span></div><div class="cm-line"> <span class="ͼl">plugins</span>: [notaPlugin()]</div><div class="cm-line">})</div></div></div></div></div><p>This plugin will allow you to import a file with a <code>.nota</code> extension. The file's default export will be the document's React component. For example:</p><div class="listing"><div class="cm-editor ͼ1 ͼ2 ͼo"><div aria-live="polite" style="position: absolute; top: -10000px;"></div><div tabindex="-1" class="cm-scroller"><div class="cm-gutters" aria-hidden="true" style="min-height: 140px; position: sticky;"><div class="cm-gutter cm-lineNumbers"><div class="cm-gutterElement" style="height: 0px; visibility: hidden; pointer-events: none;">
7599</div><div class="cm-gutterElement" style="height: 14px;">1</div><div class="cm-gutterElement" style="height: 14px;">2</div><div class="cm-gutterElement" style="height: 14px;">3</div><div class="cm-gutterElement" style="height: 14px;">4</div><div class="cm-gutterElement" style="height: 14px;">5</div><div class="cm-gutterElement" style="height: 14px;">6</div><div class="cm-gutterElement" style="height: 14px;">7</div><div class="cm-gutterElement" style="height: 14px;">8</div><div class="cm-gutterElement" style="height: 14px;">9</div><div class="cm-gutterElement" style="height: 14px;">10</div></div></div><div spellcheck="false" autocorrect="off" autocapitalize="off" translate="no" contenteditable="false" class="cm-content cm-lineWrapping" style="tab-size: 4" role="textbox" aria-multiline="true"><div class="cm-line"><span class="ͼb">import</span> <span class="ͼg">React</span> <span class="ͼb">from</span> <span class="ͼe">"react"</span>;</div><div class="cm-line"><span class="ͼb">import</span> <span class="ͼg">ReactDOM</span> <span class="ͼb">from</span> <span class="ͼe">"react-dom"</span>;</div><div class="cm-line"><span class="ͼb">import</span> <span class="ͼg">Doc</span> <span class="ͼb">from</span> <span class="ͼe">"./index.nota"</span>;</div><div class="cm-line"><br></div><div class="cm-line"><span class="ͼb">let</span> <span class="ͼg">App</span> = () => <
75<span class="ͼi">div</span>></div><div class="cm-line"> <<span class="ͼi">h1</span>>My Website</<span class="ͼi">h1</span>></div><div class="cm-line"> <<span class="ͼi">Doc</span> /></div><div class="cm-line"></<span class="ͼi">div</span>>;</div><div class="cm-line"><br></div><div class="cm-line">ReactDOM.renderToString(<<span class="ͼi">App</span> />, document.getElementById(<span class="ͼe">'app'</span>));</div></div></div></div></div><p>If you follow the approach above, all pipeline issues like bundling and server-side rendering are up to you. Alternatively, you can use the <a href="https://github.com/nota-lang/nota/tree/master/packages/esbuild-utils"><code>@nota-lang/esbuild-utils</code></a> package to get a simple Nota-enabled static site generator that includes bundling and SSR. Check out the <code>build.mjs</code> file for <a href="https://github.com/nota-lang/nota-lang.org">nota-lang.org</a> and <a href="https://github.com/willcrichton/willcrichton.github.io">willcrichton.net</a> as examples.</p></section></section><section><h1 class="section-title"><div id="def-section-3" class="definition"><span class="section-number">3</span> Editing</div></h1><p>You can still use the Nota editor on documents that are not built via <code>nota build</code>. The <code>nota edit</code> command can take additional flags to interoperate with your personal build pipeline. </p><section><h2 class="section-title"><div id="def-section-3.1" class="definition"><span class="section-number">3.1</span> Build configuration</div></h2><p>If you are using esbuild and have custom esbuild flags, e.g. a plugin like <a href="https://github.com/glromeo/esbuild-sass-plugin">esbuild-sass-plugin</a>, then you can define a configuration file like so:</p><div class="listing"><div class="cm-editor ͼ1 ͼ2 ͼo"><div aria-live="polite" style="position: absolute; top: -10000px;"></div><div tabindex="-1" class="cm-scroller"><div class="cm-gutters" aria-hidden="true" style="min-height: 84px; position: sticky;"><div class="cm-gutter cm-lineNumbers"><div class="cm-gutterElement" style="height: 0px; visibility: hidden; pointer-events: none;">9</div><div class="cm-gutterElement" style="height: 14px;">1</div><div class="cm-gutterElement" style="height: 14px;">2</div><div class="cm-gutterElement" style="height: 14px;">3</div><div class="cm-gutterElement" style="height: 14px;">4</div><div class="cm-gutterElement" style="height: 14px;">5</div><div class="cm-gutterElement" style="height: 14px;">6</div></div></div><div spellcheck="false" autocorrect="off" autocapitalize="off" translate="no" contenteditable="false" class="cm-content cm-lineWrapping" style="tab-size: 4" role="textbox" aria-multiline="true"><div class="cm-line"><span class="ͼm">// nota.config.mjs</span></div><div class="cm-line"><span class="ͼb">import</span> { <span class="ͼg">sassPlugin</span> } <span class="ͼb">from</span> <span class="ͼe">"esbuild-sass-plugin"</span>;</div><div class="cm-line"><br></div><div class="cm-line"><span class="ͼb">export</span> <span class="ͼb">default</span> {</div><div class="cm-line"> <span class="ͼl">plugins</span>: [sassPlugin()];</div><div class="cm-line">}</div></div></div></div></div><p>Then incorporate it into your build script:</p><div class="listing"><div class="cm-editor ͼ1 ͼ2 ͼo"><div aria-live="polite" style="position: absolute; top: -10000px;"></div><div tabindex="-1" class="cm-scroller"><div class="cm-gutters" aria-hidden="true" style="min-height: 112px; position: sticky;"><div class="cm-gutter cm-lineNumbers"><div class="cm-gutterElement" style="height: 0px; visibility: hidden; pointer-events: none;">9</div><div class="cm-gutterElement" style="height: 14px;">1</div><div class="cm-gutterElement" style="height: 14px;">2</div><div class="cm-gutterElement" style="height: 14px;">3</div><div class="cm-gutterElement" style="height: 14px;">4</div><div class="cm-gutterElement" style="height: 14px;">5</div><div class="cm-gutterElement" style="height: 14px;">6</div><div class="cm-gutterElement" style="height: 14px;">7</div><div class="cm-gutterElement" style="height: 14px;">8</div></div></div><div spellcheck="false" autocorrect="off" autocapitalize="off" translate="no" contenteditable="false" class="cm-content cm-lineWrapping" style="tab-size: 4" role="textbox" aria-multiline="true"><div class="cm-line"><span class="ͼm">// build.mjs</span></div><div class="cm-line"><span class="ͼb">
75import</span> <span class="ͼg">config</span> <span class="ͼb">from</span> <span class="ͼe">"./nota.config.mjs"</span>;</div><div class="cm-line"><span class="ͼb">import</span> <span class="ͼg">esbuild</span> <span class="ͼb">from</span> <span class="ͼe">"esbuild"</span>;</div><div class="cm-line"><br></div><div class="cm-line">esbuild.build({</div><div class="cm-line"> <span class="ͼl">entryPoints</span>: [<span class="ͼe">"./src/index.nota"</span>],</div><div class="cm-line"> ...config</div><div class="cm-line">})</div></div></div></div></div><p>And then provide the configuration path to the editor:</p><div class="listing"><div class="cm-editor ͼ1 ͼ2 ͼo"><div aria-live="polite" style="position: absolute; top: -10000px;"></div><div tabindex="-1" class="cm-scroller"><div class="cm-gutters" aria-hidden="true" style="min-height: 14px; position: sticky;"><div class="cm-gutter cm-lineNumbers"><div class="cm-gutterElement" style="height: 0px; visibility: hidden; pointer-events: none;">9</div><div class="cm-gutterElement" style="height: 14px;">1</div></div></div><div spellcheck="false" autocorrect="off" autocapitalize="off" translate="no" contenteditable="false" class="cm-content cm-lineWrapping" style="tab-size: 4" role="textbox" aria-multiline="true"><div class="cm-line">nota edit src/index.nota --config nota.config.mjs</div></div></div></div></div></section><section><h2 class="section-title"><div id="def-section-3.2" class="definition"><span class="section-number">3.2</span> Asset folder</div></h2><p>If your document contains local URLs to assets like images, then you can configure the editor to serve files out of a given directory:</p><div class="listing"><div class="cm-editor ͼ1 ͼ2 ͼo"><div aria-live="polite" style="position: absolute; top: -10000px;"></div><div tabindex="-1" class="cm-scroller"><div class="cm-gutters" aria-hidden="true" style="min-height: 14px; position: sticky;"><div class="cm-gutter cm-lineNumbers"><div class="cm-gutterElement" style="height: 0px; visibility: hidden; pointer-events: none;">9</div><div class="cm-gutterElement" style="height: 14px;">1</div></div></div><div spellcheck="false" autocorrect="off" autocapitalize="off" translate="no" contenteditable="false" class="cm-content cm-lineWrapping" style="tab-size: 4" role="textbox" aria-multiline="true"><div class="cm-line">nota edit src/index.nota --static assets</div></div></div></div></div></section></section><div class="logger"></div><div class="portal"></div></div></div>
75<script src="./integration.mjs" type="module" async=""></script>
75</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.