Tidy up styling, add basic ToC component.
This commit is contained in:
parent
54ad373744
commit
3b464c523e
@ -9,10 +9,10 @@
|
||||
<meta name="description" content="{{ description | join(' ') }}"/>
|
||||
{% eleventyGoogleFonts 'https://fonts.googleapis.com/css2?family=Fredoka:wght@300;400;500&display=swap' %}
|
||||
</head>
|
||||
<body class="text-base">
|
||||
{{ Node('Navbar', {}, page) }}
|
||||
<body class="text-base pt-16">
|
||||
{{ Node('Navbar', {}, { headings: headings, url: page.url }) }}
|
||||
{% for child in children %}
|
||||
{{ Node(child.type, child, page) }}
|
||||
{{ Node(child.type, child, { headings: headings, url: page.url }) }}
|
||||
{% endfor %}
|
||||
<script type="module" src="/main.js"></script>
|
||||
</body>
|
||||
|
@ -1,11 +1,11 @@
|
||||
{% macro render(node) %}
|
||||
{% if node.variant == 'small' %}
|
||||
<div class="flex gap-2 items-center">
|
||||
<div class="flex gap-2 items-center {{node.class}}">
|
||||
<img src="/logo.png" class="w-8 h-8" alt=""/>
|
||||
<span class="text-3xl text-transparent bg-clip-text bg-gradient-to-b from-primary-400 to-primary-600">Terrace</span>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="flex gap-4 items-center">
|
||||
<div class="flex gap-4 items-center {{node.class}}">
|
||||
<img src="/logo.png" class="w-8 h-8 md:w-16 md:h-16" alt=""/>
|
||||
<h1 class="text-xl md:text-5xl text-transparent bg-clip-text bg-gradient-to-b from-primary-400 to-primary-600">Terrace</h1>
|
||||
</div>
|
||||
|
@ -1,13 +1,11 @@
|
||||
{% from "./Node.njk" import Node %}
|
||||
|
||||
{{ page | dump }}
|
||||
|
||||
{% macro navlink(href, text, active) %}
|
||||
<a href="{{ href }}" class="flex items-center hover:text-primary-400 {{ 'text-primary-400' if href in active }}">{{ text }}</a>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render(node, page) %}
|
||||
<nav class="fixed left-0 right-0 top-0 lg:relative bg-neutral-800 text-neutral-50 h-20 flex items-center z-10">
|
||||
{% macro render(node, ctx) %}
|
||||
<nav class="fixed left-0 right-0 top-0 lg:absolute bg-neutral-800 text-neutral-50 h-20 flex items-center z-10">
|
||||
<div class="container mx-auto px-8 flex items-center space-between">
|
||||
<a id="nav" class="peer" href="#nav" aria-hidden="true" tabindex="-1"></a>
|
||||
|
||||
@ -29,10 +27,10 @@
|
||||
lg:pointer-events-auto
|
||||
lg:relative lg:top-0 lg:px-0 lg:flex-row lg:flex-1 lg:h-20 lg:bg-neutral-800 lg:text-white
|
||||
">
|
||||
{{ navlink("/docs/", "Docs", page.url) }}
|
||||
{{ navlink("/examples/", "Examples", page.url) }}
|
||||
{{ navlink("/about/", "About", page.url) }}
|
||||
{{ navlink("/contribute/", "Contribute", page.url) }}
|
||||
{{ navlink("/docs/", "Docs", ctx.url) }}
|
||||
{{ navlink("/examples/", "Examples", ctx.url) }}
|
||||
{{ navlink("/about/", "About", ctx.url) }}
|
||||
{{ navlink("/contribute/", "Contribute", ctx.url) }}
|
||||
<a href="/docs/" class="flex items-center hover:text-primary-400">Contribute</a>
|
||||
<div class="-order-1 lg:order-2 flex items-center">{{ Node('SearchBox', { class: 'w-full lg:w-72' }) }}</div>
|
||||
<a href="https://git.thederf.com/thederf/Terrace" target="_blank" class="flex items-center hover:text-primary-400 order-3">
|
||||
|
@ -1,4 +1,4 @@
|
||||
{% macro Node(name, params, page) %}
|
||||
{% macro Node(name, params, ctx) %}
|
||||
{% from "./" + name + ".njk" import render %}
|
||||
{{ render(params, page) }}
|
||||
{{ render(params, ctx) }}
|
||||
{% endmacro %}
|
||||
|
@ -6,14 +6,14 @@
|
||||
}
|
||||
%}
|
||||
|
||||
{% macro render(node, page) %}
|
||||
{% macro render(node, ctx) %}
|
||||
<svg class="w-full -mt-[55px] {{ 'text-neutral-50' if node.variant == 'light' else 'text-neutral-800' }}" viewBox="0 0 1920 55">
|
||||
<path d="M0 55H1920V6.99994C1811 55 1150 55 403.5 6.99994C141.541 -9.84407 0 6.99996 0 55Z" fill="currentColor"/>
|
||||
</svg>
|
||||
<section class="group/{{node.variant}} {{ variants[node.variant] }}">
|
||||
<div class="{{ node.class }} container mx-auto px-8 pt-16 md:pt-8 pb-32">
|
||||
<div class="{{ node.class }} container mx-auto px-8 pt-16 pb-48">
|
||||
{% for child in node.children %}
|
||||
{{ Node(child.type, child, page) }}
|
||||
{{ Node(child.type, child, ctx) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</section>
|
||||
|
19
docs/src/_includes/nodes/TableOfContents.njk
Normal file
19
docs/src/_includes/nodes/TableOfContents.njk
Normal file
@ -0,0 +1,19 @@
|
||||
{% macro renderHeadings(headings) %}
|
||||
<ul class="pl-4">
|
||||
{% for heading in headings %}
|
||||
<li class="my-4">
|
||||
<a href="#{{ heading.slug }}" class="hover:text-primary-400">{{ heading.text }}</a>
|
||||
{% if heading.children %}
|
||||
{{ renderHeadings(heading.children)}}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render(node, ctx) %}
|
||||
<div class="my-4 font-medium text-2xl">Table of Contents</div>
|
||||
<div class="-ml-3">
|
||||
{{ renderHeadings(ctx.headings) }}
|
||||
</div>
|
||||
{% endmacro %}
|
@ -5,229 +5,250 @@ description
|
||||
Terrace gets out of your way to let you just write
|
||||
|
||||
Section dark
|
||||
class pt-40 md:pt-32 max-w-prose
|
||||
class flex flex-col md:flex-row gap-16
|
||||
|
||||
Heading 1 About Terrace
|
||||
Block
|
||||
class w-full lg:w-1/3
|
||||
|
||||
Markdown
|
||||
Terrace is a tiny system for storing data in human-friendly text files.
|
||||
TableOfContents
|
||||
|
||||
It allows you to mix all sorts of text and data formats together in an intuitive way without getting caught up in syntax pomp and ceremony.
|
||||
Block
|
||||
class max-w-prose
|
||||
|
||||
CodeBlock terrace
|
||||
title An Essay on Rockets
|
||||
date 2022-02-22
|
||||
by John Doe
|
||||
Heading 1 About Terrace
|
||||
|
||||
heading The ideal rocket equation
|
||||
Markdown
|
||||
Terrace is a tiny system for storing data in human-friendly text files.
|
||||
|
||||
equation LaTeX
|
||||
\Delta v=v_{\text{e}}\ln {\frac {m_{0}}{m_{f}}}=I_{\text{sp}}g_{0}\ln {\frac {m_{0}}{m_{f}}}
|
||||
It allows you to mix all sorts of text and data formats together in an intuitive way without getting caught up in syntax pomp and ceremony.
|
||||
|
||||
markdown
|
||||
A fundamental equation in astrophysics, the *ideal rocket equation* describes the total potential velocity of an idealized vehicle propelled by expelling some of its own mass.
|
||||
CodeBlock terrace
|
||||
title An Essay on Rockets
|
||||
date 2022-02-22
|
||||
by John Doe
|
||||
|
||||
...
|
||||
heading The ideal rocket equation
|
||||
|
||||
Markdown
|
||||
class prose-invert
|
||||
You can use Terrace to write documents, web pages, configuration files, data storage, or whatever else you come up with!
|
||||
equation LaTeX
|
||||
\Delta v=v_{\text{e}}\ln {\frac {m_{0}}{m_{f}}}=I_{\text{sp}}g_{0}\ln {\frac {m_{0}}{m_{f}}}
|
||||
|
||||
[This page](https://git.thederf.com/thederf/Terrace/src/branch/main/docs/src/about.tce) is written using Terrace!
|
||||
markdown
|
||||
A fundamental equation in astrophysics, the *ideal rocket equation* describes the total potential velocity of an idealized vehicle propelled by expelling some of its own mass.
|
||||
|
||||
...
|
||||
|
||||
Markdown
|
||||
class prose-invert
|
||||
You can use Terrace to write documents, web pages, configuration files, data storage, or whatever else you come up with!
|
||||
|
||||
[This page](https://git.thederf.com/thederf/Terrace/src/branch/main/docs/src/about.tce) is written using Terrace!
|
||||
|
||||
Section light
|
||||
class max-w-prose
|
||||
Heading 2 Background
|
||||
class flex flex-col md:flex-row gap-16
|
||||
|
||||
Markdown
|
||||
Terrace was originally envisioned out of frustration at the massive usability gulf for embedding custom blocks in simple, human-friendly markup formats such as [Markdown](), and capable but complex block-based systems such as [Project Gutenberg](https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/writing-your-first-block-type/) and [Editor.js](https://editorjs.io/saving-data/).
|
||||
Block
|
||||
class w-1/3
|
||||
|
||||
Heading 3 The Complexity Problem
|
||||
class mt-8 mb-4
|
||||
Block
|
||||
class max-w-prose
|
||||
|
||||
Markdown
|
||||
**A simple markdown document:**
|
||||
Heading 2 Background
|
||||
|
||||
CodeBlock markdown
|
||||
# My Page Title
|
||||
Markdown
|
||||
Terrace was originally envisioned out of frustration at the massive usability gulf for embedding custom blocks in simple, human-friendly markup formats such as [Markdown](), and capable but complex block-based systems such as [Project Gutenberg](https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/writing-your-first-block-type/) and [Editor.js](https://editorjs.io/saving-data/).
|
||||
|
||||
Occaecat fugiat est ullamco aliqua ea dolor nostrud. Reprehenderit nisi minim sit commodo deserunt ullamco deserunt aute ex exercitation Lorem deserunt ad.
|
||||
Heading 3 The Complexity Problem
|
||||
class mt-8 mb-4
|
||||
|
||||
1. Magna id sint consequat quis esse tempor.
|
||||
2. Veniam eu id esse occaecat eu.
|
||||
3. Minim commodo nostrud eiusmod excepteur ea sint in enim esse aliqua.
|
||||
Markdown
|
||||
**A simple markdown document:**
|
||||
|
||||
[Put my-custom-component here somehow]
|
||||
CodeBlock markdown
|
||||
# My Page Title
|
||||
|
||||
Dolor adipisicing amet aliquip nulla occaecat Lorem excepteur veniam. Voluptate pariatur sint anim tempor aliquip in. Id nulla est irure officia occaecat enim.
|
||||
|
||||
Markdown
|
||||
**That same document in a *simplified* Editor.js schema:**
|
||||
|
||||
CodeBlock javascript
|
||||
class max-h-[500px] overflow-y-auto
|
||||
[
|
||||
{
|
||||
type: "header",
|
||||
data: {
|
||||
level: 1,
|
||||
text: "My Page Title"
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "paragraph",
|
||||
data: {
|
||||
text: "Occaecat fugiat est ullamco aliqua ea dolor nostrud. Reprehenderit nisi minim sit commodo deserunt ullamco deserunt aute ex exercitation Lorem deserunt ad."
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
data: {
|
||||
style: "ordered",
|
||||
items: [
|
||||
"Magna id sint consequat quis esse tempor.",
|
||||
"Veniam eu id esse occaecat eu.",
|
||||
"Minim commodo nostrud eiusmod excepteur ea sint in enim esse aliqua."
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "my-custom-component",
|
||||
data: {
|
||||
option1: "value",
|
||||
option2: "value",
|
||||
text: "Text"
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "paragraph",
|
||||
data: {
|
||||
text: "Dolor adipisicing amet aliquip nulla occaecat Lorem excepteur veniam. Voluptate pariatur sint anim tempor aliquip in. Id nulla est irure officia occaecat enim."
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
Heading 3 MDX & MDC
|
||||
class mt-16 mb-4
|
||||
|
||||
Markdown
|
||||
Other attempts, such as [MDX](https://mdxjs.com/) and [MDC](https://content.nuxtjs.org/guide/writing/mdc/) have been made to solve this problem, allowing you to incorporate complex content *inside* markup documents.
|
||||
|
||||
However, they suffer from a number of problems:
|
||||
|
||||
1. Tightly coupled to the JavaScript ecosystem
|
||||
2. Lock you out of other markup formats, such as [AsciiDoc](https://asciidoc.org/)
|
||||
3. Difficult to parse - Markdown was not intended as a general-purpose syntax
|
||||
4. Data can't be extracted from markup without rendering the entire document to HTML
|
||||
5. Ugly. Just look at this:
|
||||
|
||||
CodeBlock markdown
|
||||
# My Page Title
|
||||
|
||||
Occaecat fugiat est ullamco aliqua ea dolor nostrud. Reprehenderit nisi minim sit commodo deserunt ullamco deserunt aute ex exercitation Lorem deserunt ad.
|
||||
|
||||
1. Magna id sint consequat quis esse tempor.
|
||||
2. Veniam eu id esse occaecat eu.
|
||||
3. Minim commodo nostrud eiusmod excepteur ea sint in enim esse aliqua.
|
||||
|
||||
[MDX Example]
|
||||
<MyCustomComponent option1={{'value'}} option2={{'value'}}>
|
||||
Text
|
||||
</MyCustomComponent>
|
||||
|
||||
[MDC Example]
|
||||
::MyCustomComponent{option1="value", option2="value"}
|
||||
Text
|
||||
::
|
||||
|
||||
|
||||
Dolor adipisicing amet aliquip nulla occaecat Lorem excepteur veniam. Voluptate pariatur sint anim tempor aliquip in. Id nulla est irure officia occaecat enim.
|
||||
|
||||
Heading 3 Terrace Prototype
|
||||
class mt-16 mb-4
|
||||
|
||||
Markdown
|
||||
I first attempted to solve this problem using an [S-Expression](https://en.wikipedia.org/wiki/S-expression)-based syntax for defining blocks.
|
||||
|
||||
CodeBlock lisp
|
||||
(heading
|
||||
(level 1)
|
||||
My Page Title
|
||||
)
|
||||
|
||||
(markdown
|
||||
Occaecat fugiat est ullamco aliqua ea dolor nostrud. Reprehenderit nisi minim sit commodo deserunt ullamco deserunt aute ex exercitation Lorem deserunt ad.
|
||||
|
||||
1. Magna id sint consequat quis esse tempor.
|
||||
2. Veniam eu id esse occaecat eu.
|
||||
3. Minim commodo nostrud eiusmod excepteur ea sint in enim esse aliqua.
|
||||
)
|
||||
|
||||
(my-custom-component
|
||||
(option1 value)
|
||||
(option2 value)
|
||||
Text
|
||||
)
|
||||
|
||||
(markdown
|
||||
Dolor adipisicing amet aliquip nulla occaecat Lorem excepteur veniam. Voluptate pariatur sint anim tempor aliquip in. Id nulla est irure officia occaecat enim.
|
||||
)
|
||||
|
||||
Markdown
|
||||
While quite flexible and clean-looking, problems became apparent with handling whitespace and escaping parenthesis in text.
|
||||
The parser quickly became much more extensive than initially envisioned.
|
||||
|
||||
Nevertheless, it proved the concept that cleanly combining functional blocks and markup text was quite reasonable.
|
||||
|
||||
Not long after, I stumbled upon [Tree Notation](https://treenotation.org) by [Brek Yunits](https://www.breckyunits.com/). Playing around with it, the potential of just *getting rid of the parenthesis* was quite apparent. Simpler syntax for humans to write, and far less work required for parsing & escaping since the only control characters are newlines and spaces:
|
||||
|
||||
CodeBlock terrace
|
||||
heading My Page Title
|
||||
level 1
|
||||
|
||||
markdown
|
||||
Occaecat fugiat est ullamco aliqua ea dolor nostrud. Reprehenderit nisi minim sit commodo deserunt ullamco deserunt aute ex exercitation Lorem deserunt ad.
|
||||
|
||||
1. Magna id sint consequat quis esse tempor.
|
||||
2. Veniam eu id esse occaecat eu.
|
||||
3. Minim commodo nostrud eiusmod excepteur ea sint in enim esse aliqua.
|
||||
|
||||
my-custom-block
|
||||
option1 value
|
||||
option2 value
|
||||
Text
|
||||
[Put my-custom-component here somehow]
|
||||
|
||||
markdown
|
||||
Dolor adipisicing amet aliquip nulla occaecat Lorem excepteur veniam. Voluptate pariatur sint anim tempor aliquip in. Id nulla est irure officia occaecat enim.
|
||||
|
||||
Markdown
|
||||
Ultimately though, using Tree Notation still proved too messy. After working with the grammar system and spreadsheet-style data model for a good while, my gut said all this use case needed was a simple line-based parser.
|
||||
Markdown
|
||||
**That same document in a *simplified* Editor.js schema:**
|
||||
|
||||
I started Terrace to implement a similar syntax, but with the following goals:
|
||||
CodeBlock javascript
|
||||
class max-h-[500px] overflow-y-auto
|
||||
[
|
||||
{
|
||||
type: "header",
|
||||
data: {
|
||||
level: 1,
|
||||
text: "My Page Title"
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "paragraph",
|
||||
data: {
|
||||
text: "Occaecat fugiat est ullamco aliqua ea dolor nostrud. Reprehenderit nisi minim sit commodo deserunt ullamco deserunt aute ex exercitation Lorem deserunt ad."
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "list",
|
||||
data: {
|
||||
style: "ordered",
|
||||
items: [
|
||||
"Magna id sint consequat quis esse tempor.",
|
||||
"Veniam eu id esse occaecat eu.",
|
||||
"Minim commodo nostrud eiusmod excepteur ea sint in enim esse aliqua."
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "my-custom-component",
|
||||
data: {
|
||||
option1: "value",
|
||||
option2: "value",
|
||||
text: "Text"
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "paragraph",
|
||||
data: {
|
||||
text: "Dolor adipisicing amet aliquip nulla occaecat Lorem excepteur veniam. Voluptate pariatur sint anim tempor aliquip in. Id nulla est irure officia occaecat enim."
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
1. Make as few decisions as possible for the user
|
||||
2. Be as fast, tiny, and light on resources as possible
|
||||
Heading 3 MDX & MDC
|
||||
class mt-16 mb-4
|
||||
|
||||
Six or seven parser rewrites later, it finally works mostly how I envisioned it. :)
|
||||
Markdown
|
||||
Other attempts, such as [MDX](https://mdxjs.com/) and [MDC](https://content.nuxtjs.org/guide/writing/mdc/) have been made to solve this problem, allowing you to incorporate complex content *inside* markup documents.
|
||||
|
||||
However, they suffer from a number of problems:
|
||||
|
||||
1. Tightly coupled to the JavaScript ecosystem
|
||||
2. Lock you out of other markup formats, such as [AsciiDoc](https://asciidoc.org/)
|
||||
3. Difficult to parse - Markdown was not intended as a general-purpose syntax
|
||||
4. Data can't be extracted from markup without rendering the entire document to HTML
|
||||
5. Ugly. Just look at this:
|
||||
|
||||
CodeBlock markdown
|
||||
# My Page Title
|
||||
|
||||
Occaecat fugiat est ullamco aliqua ea dolor nostrud. Reprehenderit nisi minim sit commodo deserunt ullamco deserunt aute ex exercitation Lorem deserunt ad.
|
||||
|
||||
1. Magna id sint consequat quis esse tempor.
|
||||
2. Veniam eu id esse occaecat eu.
|
||||
3. Minim commodo nostrud eiusmod excepteur ea sint in enim esse aliqua.
|
||||
|
||||
[MDX Example]
|
||||
<MyCustomComponent option1={{'value'}} option2={{'value'}}>
|
||||
Text
|
||||
</MyCustomComponent>
|
||||
|
||||
[MDC Example]
|
||||
::MyCustomComponent{option1="value", option2="value"}
|
||||
Text
|
||||
::
|
||||
|
||||
|
||||
Dolor adipisicing amet aliquip nulla occaecat Lorem excepteur veniam. Voluptate pariatur sint anim tempor aliquip in. Id nulla est irure officia occaecat enim.
|
||||
|
||||
Heading 3 Terrace Prototype
|
||||
class mt-16 mb-4
|
||||
|
||||
Markdown
|
||||
I first attempted to solve this problem using an [S-Expression](https://en.wikipedia.org/wiki/S-expression)-based syntax for defining blocks.
|
||||
|
||||
CodeBlock lisp
|
||||
(heading
|
||||
(level 1)
|
||||
My Page Title
|
||||
)
|
||||
|
||||
(markdown
|
||||
Occaecat fugiat est ullamco aliqua ea dolor nostrud. Reprehenderit nisi minim sit commodo deserunt ullamco deserunt aute ex exercitation Lorem deserunt ad.
|
||||
|
||||
1. Magna id sint consequat quis esse tempor.
|
||||
2. Veniam eu id esse occaecat eu.
|
||||
3. Minim commodo nostrud eiusmod excepteur ea sint in enim esse aliqua.
|
||||
)
|
||||
|
||||
(my-custom-component
|
||||
(option1 value)
|
||||
(option2 value)
|
||||
Text
|
||||
)
|
||||
|
||||
(markdown
|
||||
Dolor adipisicing amet aliquip nulla occaecat Lorem excepteur veniam. Voluptate pariatur sint anim tempor aliquip in. Id nulla est irure officia occaecat enim.
|
||||
)
|
||||
|
||||
Markdown
|
||||
While quite flexible and clean-looking, problems became apparent with handling whitespace and escaping parenthesis in text.
|
||||
The parser quickly became much more extensive than initially envisioned.
|
||||
|
||||
Nevertheless, it proved the concept that cleanly combining functional blocks and markup text was quite reasonable.
|
||||
|
||||
Not long after, I stumbled upon [Tree Notation](https://treenotation.org) by [Brek Yunits](https://www.breckyunits.com/). Playing around with it, the potential of just *getting rid of the parenthesis* was quite apparent. Simpler syntax for humans to write, and far less work required for parsing & escaping since the only control characters are newlines and spaces:
|
||||
|
||||
CodeBlock terrace
|
||||
heading My Page Title
|
||||
level 1
|
||||
|
||||
markdown
|
||||
Occaecat fugiat est ullamco aliqua ea dolor nostrud. Reprehenderit nisi minim sit commodo deserunt ullamco deserunt aute ex exercitation Lorem deserunt ad.
|
||||
|
||||
1. Magna id sint consequat quis esse tempor.
|
||||
2. Veniam eu id esse occaecat eu.
|
||||
3. Minim commodo nostrud eiusmod excepteur ea sint in enim esse aliqua.
|
||||
|
||||
my-custom-block
|
||||
option1 value
|
||||
option2 value
|
||||
Text
|
||||
|
||||
markdown
|
||||
Dolor adipisicing amet aliquip nulla occaecat Lorem excepteur veniam. Voluptate pariatur sint anim tempor aliquip in. Id nulla est irure officia occaecat enim.
|
||||
|
||||
Markdown
|
||||
Ultimately though, using Tree Notation still proved too messy. After working with the grammar system and spreadsheet-style data model for a good while, my gut said all this use case needed was a simple line-based parser.
|
||||
|
||||
I started Terrace to implement a similar syntax, but with the following goals:
|
||||
|
||||
1. Make as few decisions as possible for the user
|
||||
2. Be as fast, tiny, and light on resources as possible
|
||||
|
||||
Six or seven parser rewrites later, it finally works mostly how I envisioned it. :)
|
||||
|
||||
Section dark
|
||||
class max-w-prose
|
||||
class flex flex-col md:flex-row gap-16
|
||||
|
||||
Heading 2 Development Goals
|
||||
Block
|
||||
class w-1/3
|
||||
|
||||
Markdown
|
||||
class prose-invert
|
||||
Terrace development is guided by the following goals.
|
||||
Block
|
||||
class max-w-prose
|
||||
|
||||
- **Tiny, primitive core - no “framework”**
|
||||
- Use the most boring patterns possible for implementing the core library.
|
||||
- Avoid dependencies
|
||||
- Easily port Terrace in any language or environment
|
||||
- **Avoid dynamic allocation**
|
||||
- Since we can work directly off of string slices without the need for ASTs and escaping systems, might as well avoid dynamic allocations altogether!
|
||||
- **Minimize assumptions**
|
||||
- Let people use Terrace as a building block for all sorts of languages
|
||||
Heading 2 Development Goals
|
||||
|
||||
Make note of this before submitting change requests. If your changes don't fit these goals, they may be denied. In which case, you could try building a separate library on top of the Terrace cor.
|
||||
Markdown
|
||||
class prose-invert
|
||||
Terrace development is guided by the following goals.
|
||||
|
||||
Footer
|
||||
- **Tiny, primitive core - no “framework”**
|
||||
- Use the most boring patterns possible for implementing the core library.
|
||||
- Avoid dependencies
|
||||
- Easily port Terrace in any language or environment
|
||||
- **Avoid dynamic allocation**
|
||||
- Since we can work directly off of string slices without the need for ASTs and escaping systems, might as well avoid dynamic allocations altogether!
|
||||
- **Minimize assumptions**
|
||||
- Let people use Terrace as a building block for all sorts of languages
|
||||
|
||||
Make note of this before submitting change requests. If your changes don't fit these goals, they may be denied. In which case, you could try building a separate library on top of the Terrace cor.
|
||||
|
||||
Footer
|
||||
|
@ -5,10 +5,12 @@ description
|
||||
Terrace gets out of your way to let you just write
|
||||
|
||||
Section light
|
||||
class pt-40 md:pt-36 pb-48 md:pb-64 flex flex-col gap-16 md:flex-row md:gap-48
|
||||
class pt-24 flex flex-col gap-16 md:flex-row lg:gap-48
|
||||
Block
|
||||
class flex flex-col gap-8 w-full items-start
|
||||
Logo light
|
||||
class hidden lg:flex
|
||||
|
||||
Markdown
|
||||
class prose-ul:list-none
|
||||
A simple structured data syntax for
|
||||
@ -74,7 +76,7 @@ Section dark
|
||||
Heading 2 Uses
|
||||
|
||||
Block
|
||||
class flex flex-col space-between gap-16 md:flex-row md:gap-48
|
||||
class flex flex-col space-between gap-16 md:flex-row lg:gap-48
|
||||
|
||||
Block
|
||||
class max-w-prose
|
||||
@ -122,7 +124,7 @@ Section light
|
||||
Heading 2 Core
|
||||
|
||||
Block
|
||||
class flex flex-col space-between gap-16 md:flex-row md:gap-48
|
||||
class flex flex-col space-between gap-16 md:flex-row lg:gap-48
|
||||
|
||||
Block
|
||||
Heading 3 Tiny - <strong>Really Tiny</strong>
|
||||
@ -165,7 +167,7 @@ Section dark
|
||||
Heading 2 Learn More
|
||||
|
||||
Block
|
||||
class flex flex-col space-between gap-16 md:flex-row md:gap-48
|
||||
class flex flex-col space-between gap-16 md:flex-row lg:gap-48
|
||||
|
||||
Block
|
||||
class max-w-prose
|
||||
|
@ -4,7 +4,7 @@ module.exports = async function (doc, rootLevel, pageData) {
|
||||
|
||||
const { next, line, match, tail, level, head } = doc
|
||||
|
||||
const headingLevel = tail().split(' ')[0]
|
||||
const headingLevel = +tail().split(' ')[0]
|
||||
const text = tail().split(' ').slice(1).join(' ')
|
||||
const slug = slugify(text)
|
||||
|
||||
@ -13,7 +13,8 @@ module.exports = async function (doc, rootLevel, pageData) {
|
||||
level: headingLevel,
|
||||
text,
|
||||
slug,
|
||||
class: ''
|
||||
class: '',
|
||||
children: []
|
||||
}
|
||||
|
||||
while (await next(rootLevel)) {
|
||||
|
23
docs/src/parser/nodes/Logo.js
Normal file
23
docs/src/parser/nodes/Logo.js
Normal file
@ -0,0 +1,23 @@
|
||||
const { contentAsText } = require('../helpers.js')
|
||||
|
||||
module.exports = async function (doc, rootLevel) {
|
||||
const { next, line, match, tail, level, head } = doc
|
||||
|
||||
const node = {
|
||||
type: head(),
|
||||
variant: tail() || 'neutral',
|
||||
class: '',
|
||||
href: '',
|
||||
text: ''
|
||||
}
|
||||
|
||||
while (await next(rootLevel)) {
|
||||
if (match('class')) node.class = tail()
|
||||
else if (match('href')) node.href = tail()
|
||||
else {
|
||||
node.text = await contentAsText(doc, rootLevel, true)
|
||||
}
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
14
docs/src/parser/nodes/TableOfContents.js
Normal file
14
docs/src/parser/nodes/TableOfContents.js
Normal file
@ -0,0 +1,14 @@
|
||||
module.exports = async function (doc, rootLevel) {
|
||||
const { next, head, tail, match } = doc
|
||||
|
||||
const node = {
|
||||
type: head(),
|
||||
class: '',
|
||||
}
|
||||
|
||||
while (await next(rootLevel)) {
|
||||
if (match('class')) node.class = tail()
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
@ -5,6 +5,7 @@ module.exports.Section = async (doc, rootLevel, ...args) => {
|
||||
const variant = doc.tail()
|
||||
return { variant, ...(await parseNode(doc, rootLevel, ...args)) }
|
||||
}
|
||||
module.exports.TableOfContents = require('./TableOfContents.js')
|
||||
module.exports.Heading = require('./Heading.js')
|
||||
module.exports.Button = require('./Button.js')
|
||||
module.exports.Icon = require('./Icon.js')
|
||||
@ -12,9 +13,6 @@ module.exports.Icon = require('./Icon.js')
|
||||
module.exports.Markdown = require('./Markdown.js')
|
||||
module.exports.CodeBlock = require('./CodeBlock.js')
|
||||
module.exports.CodeExample = require('./CodeExample.js')
|
||||
module.exports.Logo = doc => ({
|
||||
type: `Logo`,
|
||||
variant: doc.tail() || 'light'
|
||||
})
|
||||
module.exports.Logo = require('./Logo.js')
|
||||
|
||||
module.exports.Footer = require('./Footer.js')
|
||||
|
@ -27,7 +27,20 @@ module.exports = async function(doc) {
|
||||
}
|
||||
}
|
||||
|
||||
console.dir(pageData, { depth: null })
|
||||
// Structure headings into tree.
|
||||
pageData.headings.forEach((heading, index) => {
|
||||
let parent = null
|
||||
for (let i = index; i > 0; --i) {
|
||||
if (pageData.headings[i].level === heading.level - 1) {
|
||||
parent = pageData.headings[i]
|
||||
}
|
||||
}
|
||||
|
||||
if (parent) parent.children.push(heading)
|
||||
})
|
||||
|
||||
pageData.headings = pageData.headings.filter(h => h.level === 2)
|
||||
console.dir(pageData.headings, { depth: null })
|
||||
|
||||
return pageData
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user