Started working on JS docs.

This commit is contained in:
Joshua Bemenderfer 2023-02-14 22:24:59 -05:00
parent 91ca89f158
commit 4156e3bf91
24 changed files with 364 additions and 69 deletions

View File

@ -3,8 +3,8 @@ const EleventyGoogleFonts = require("eleventy-google-fonts");
const EleventyFeatherIcons = require('eleventy-plugin-feathericons');
const HighlightJS = require('highlight.js')
const { useDocument } = require('@terrace/js/document')
const { createFileReader } = require('@terrace/js/readers/node-readline')
const { useDocument } = require('@terrace-lang/js/document')
const { createFileReader } = require('@terrace-lang/js/readers/node-readline')
const parsePage = require('./src/parser/page.js');
module.exports = function (config) {

View File

@ -1,5 +1,5 @@
{
"name": "@terrace/docs",
"name": "@terrace-lang/docs",
"private": true,
"license": "MIT",
"scripts": {
@ -11,7 +11,7 @@
"@11ty/eleventy-plugin-vite": "^4.0.0",
"@sindresorhus/slugify": "^2.2.0",
"@tailwindcss/typography": "^0.5.9",
"@terrace/js": "workspace:*",
"@terrace-lang/js": "workspace:*",
"eleventy-google-fonts": "^0.1.0",
"eleventy-plugin-feathericons": "^1.0.1",
"highlight.js": "^11.7.0",

View File

@ -1,5 +1,9 @@
{% macro render(node) %}
<pre
class="my-8 p-4 bg-neutral-900 text-neutral-50 rounded-md whitespace-pre-wrap {{ node.class }}"
class="
my-8 p-4
bg-neutral-900 text-neutral-50 rounded-md whitespace-pre-wrap text-sm
{{ node.class }}
"
>{{ node.text | highlight(node.language) | safe }}</pre>
{% endmacro %}

View File

@ -13,7 +13,7 @@ set languageMeta = {
{% macro render(node) %}
<div class="text-white text-sm md:text-base relative flex w-full {{ node.class }}">
{% macro Language(id, code, isFirst) %}
{% macro Language(node, example, isFirst) %}
<details
{{ 'open' if isFirst else '' }}
class="group first:rounded-tl-md last:rounded-tr-md overflow-hidden"
@ -23,25 +23,26 @@ set languageMeta = {
class="
flex gap-2 items-center px-4 py-2 cursor-pointer
text-neutral-50 group-open:text-primary-500 bg-neutral-800 border-b-2 border-b-neutral-50/25 group-open:border-b-primary-600
h-12 mb-[400px]
h-12 {{ node.summaryClass }}
"
>
<div class="w-[16px] h-[16px] hidden md:block">{{ languageMeta[id].icon | safe }}</div>
{{ languageMeta[id].name }}
<div class="w-[16px] h-[16px] hidden md:block">{{ languageMeta[example.language].icon | safe }}</div>
{{ example.name or languageMeta[example.language].name }}
</summary>
<pre
class="
absolute top-12 left-0 right-0 w-full bg-neutral-900 text-neutral-50 p-4 rounded-bl-md rounded-br-md rounded-tr-md whitespace-pre-wrap
max-h-[400px] overflow-x-none overflow-y-auto
absolute top-12 left-0 right-0 w-full
bg-neutral-900 text-neutral-50 p-4 rounded-bl-md rounded-br-md rounded-tr-md whitespace-pre-wrap text-sm
overflow-x-none overflow-y-auto {{ node.preClass }}
"
onclick="event.preventDefault(); event.stopPropagation();"
>{{ code | highlight(id) | safe }}</pre>
>{{ example.code | highlight(example.language) | safe }}</pre>
</details>
{% endmacro %}
{% set isFirst = true %}
{% for id, code in node.languages %}
{{ Language(id, code, true if isFirst else false) }}
{% for example in node.examples %}
{{ Language(node, example, true if isFirst else false) }}
{% set isFirst = false %}
{% endfor %}
</div>

View File

@ -4,13 +4,26 @@
'3': 'text-lg md:text-2xl font-light'
} %}
{% set levelLinkClasses = {
'1': 'border-transparent hover:border-primary-600',
'2': 'border-transparent hover:border-primary-600',
'3': 'border-transparent hover:border-current'
} %}
{% macro render(node) %}
<h{{ node.level }}
id="{{ node.slug }}"
{% if levelClasses[node.level] %}
class="{{ levelClasses[node.level] }} {{ node.class }}"
class="
{{ levelClasses[node.level] }}
{{ node.class }}
"
{% endif %}
>
{{ node.text | safe }}
{% if node.href %}
<a href="{{ node.href }}" class="border-b-2 {{ levelLinkClasses[node.level] }}">{{ node.text | safe }}</a>
{% else %}
{{ node.text | safe }}
{% endif %}
</h{{ node.level }}>
{% endmacro %}

View File

@ -27,11 +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/c/", "Docs", ctx.url) }}
{{ navlink("/docs/javascript/", "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">
{{ Node('Icon', { icon: 'github' }) }}<div class="ml-4 lg:hidden">Code</div>

View File

@ -1,5 +1,5 @@
layout layout.njk
title Documentation - Terrace
title C Documentation - Terrace
description
C language documentation for the Terrace programming language
@ -19,7 +19,7 @@ Section light
Markdown
Documentation is available for the following languages:
- [C](/docs/c/) - 10% Complete
- [JavaScript](/docs/javascript/) - 0% Complete
- [JavaScript](/docs/javascript/) - 20% Complete
- [Python](/docs/python/) - 0% Complete
Heading 2 Getting Started
@ -111,11 +111,20 @@ Section light
Heading 2 Core API
class mt-12
Heading 3 Type: terrace_linedata_t
Heading 3 terrace_linedata_t
class my-6
CodeBlock c
typedef struct terrace_linedata_s {
char indent;
unsigned int level;
unsigned int offsetHead;
unsigned int offsetTail;
} terrace_linedata_t;
Heading 3 Function: terrace_parse_line
Heading 3 terrace_parse_line()
class my-6
CodeBlock c
void terrace_parse_line(char* line, terrace_linedata_t *lineData)
Heading 2 Contributing
class mt-12

View File

@ -0,0 +1,262 @@
layout layout.njk
title JavaScript Documentation - Terrace
description
JavaScript language documentation for the Terrace programming language
Section light
class flex flex-col md:flex-row gap-16
Block
class w-full lg:w-1/3
TableOfContents
Block
class max-w-prose
Heading 1 Terrace JavaScript Documentation
class -ml-2
Markdown
Documentation is available for the following languages:
- [C](/docs/c/) - 10% Complete
- [JavaScript](/docs/javascript/) - 20% Complete
- [Python](/docs/python/) - 0% Complete
Heading 2 Getting Started
class mt-12 mb-6
Markdown
Install Terrace using [NPM](https://www.npmjs.com/):
CodeBlock bash
# NPM (https://npmjs.com)
$ npm install @terrace-lang/js
# PNPM (https://pnpm.io/)
$ pnpm install @terrace-lang/js
# Yarn (https://yarnpkg.com/)
$ yarn add @terrace-lang/js
Heading 2 Recipes
class mt-12
Heading 3 Read object properties
class mb-2
Markdown
Read known properties from a Terrace block and write them to an object.
CodeBlock javascript
// Provides simple convenience functions over the core parser
// CommonJS: const { useDocument } = require('@terrace-lang/js/document')
import { useDocument } from '@terrace-lang/js/document'
// A helper for iterating over a string line-by-line
// CommonJS: const { createStringReader } = require('@terrace-lang/js/readers/js-string')
import { createStringReader } from '@terrace-lang/js/readers/js-string'
const input = `
object
string_property An example string
numeric_property An example property
`
const output = {
string_property: null,
numeric_property: null
}
// useDocument returns convenience functions
const { next, level, head, tail, match } = useDocument(createStringReader(input))
// next() parses the next line in the document
while (await next()) {
// match('object') is equivalent to head() === 'object'
// Essentially: "If the current line starts with 'object'"
if (match('object')) {
const objectLevel = level()
// When we call next with a parent level it,
// only iterates over lines inside the parent block
while (await next(objectLevel)) {
// tail() returns the part of the current line after the first space
if (match('string_property')) output.string_property = tail()
// parseFloat() here the string tail() to a numeric float value
if (match('numeric_property')) output.numeric_property = parseFloat(tail())
}
}
}
console.dir(output)
Markdown
Read *all* properties as strings from a Terrace block and write them to an object.
CodeBlock javascript
// Provides simple convenience functions over the core parser
// CommonJS: const { useDocument } = require('@terrace-lang/js/document')
import { useDocument } from '@terrace-lang/js/document'
// A helper for iterating over a string line-by-line
// CommonJS: const { createStringReader } = require('@terrace-lang/js/readers/js-string')
import { createStringReader } from '@terrace-lang/js/readers/js-string'
const input = `
object
property1 Value 1
property2 Value 2
random_property igazi3ii4quaC5OdoB5quohnah1beeNg
`
const output = {}
// useDocument returns convenience functions
const { next, level, head, tail, match } = useDocument(createStringReader(input))
// next() parses the next line in the document
while (await next()) {
// match('object') is equivalent to head() === 'object'
// Essentially: "If the current line starts with 'object'"
if (match('object')) {
const objectLevel = level()
// When we call next with a parent level it,
// only iterates over lines inside the parent block
while (await next(objectLevel)) {
// Skip empty lines
if (!line()) continue
// Add any properties to the object as strings using the
// line head() as the key and tail() as the value
output[head()] = tail()
}
}
}
console.dir(output)
Heading 2 Core API
class mt-12
Heading 3 LineData
class my-6
CodeBlock typescript
type LineData = {
line: string;
indent: string;
level: number;
offsetHead: number;
offsetTail: number;
}
Heading 3 createLineData()
class my-6
CodeBlock typescript
function createLineData(line: string = '', indent: string = ' '): LineData
CodeBlock javascript
import { createLineData } from '@terrace-lang/js/parser'
Heading 3 parseLine()
class my-6
CodeBlock typescript
function parseLine(lineData: LineData): LineData
CodeBlock javascript
import { parseLine } from '@terrace-lang/js/parser'
Heading 2 Document API
class mt-12
Heading 3 useDocument()
class my-6
CodeBlock typescript
function useDocument (reader: Reader, indent: string = ' '): Document
CodeBlock javascript
import { useDocument } from '@terrace-lang/js/document'
Heading 3 Document
class my-6
CodeBlock typescript
type Document = {
next: (startLevel?: number) => Promise<boolean>
level: () => number,
line: (startOffset?: number) => string,
head: () => string,
tail: () => string,
match: (matchHead: string) => boolean
}
Heading 3 Document.next()
class my-6
CodeBlock typescript
next: (startLevel?: number) => Promise<boolean>
CodeBlock javascript
import { useDocument } from '@terrace-lang/js/document'
const { next } = useDocument(...)
Heading 3 Document.level()
class my-6
CodeBlock typescript
level: () => number
CodeBlock javascript
import { useDocument } from '@terrace-lang/js/document'
const { level } = useDocument(...)
Heading 3 Document.line()
class my-6
CodeBlock typescript
line: (startOffset?: number) => string
CodeBlock javascript
import { useDocument } from '@terrace-lang/js/document'
const { line } = useDocument(...)
Heading 3 Document.head()
class my-6
CodeBlock typescript
head: () => string
CodeBlock javascript
import { useDocument } from '@terrace-lang/js/document'
const { head } = useDocument(...)
Heading 3 Document.tail()
class my-6
CodeBlock typescript
tail: () => string
CodeBlock javascript
import { useDocument } from '@terrace-lang/js/document'
const { tail } = useDocument(...)
Heading 3 Document.match()
class my-6
CodeBlock typescript
match: (matchValue: string) => boolean
CodeBlock javascript
import { useDocument } from '@terrace-lang/js/document'
const { match } = useDocument(...)
Heading 2 Reader API
class mt-12
Heading 3 Reader
class my-6
CodeBlock typescript
type Reader = () => string|null|Promise<string|null>
Heading 3 createStringReader()
class my-6
CodeBlock typescript
function createFileReader(path: string): Reader
CodeBlock javascript
import { createStdinReader } from '@terrace-lang/js/readers/js-string'
Heading 3 createFileReader()
class my-6
CodeBlock typescript
function createFileReader(path: string): Reader
CodeBlock javascript
import { createStdinReader } from '@terrace-lang/js/readers/node-readline'
Heading 3 createStdinReader()
class my-6
CodeBlock typescript
function createStdinReader(): Reader
CodeBlock javascript
import { createStdinReader } from '@terrace-lang/js/readers/node-readline'
Heading 2 Contributing
class mt-12
Section dark
Footer
class w-full

View File

@ -21,11 +21,11 @@ Section light
Terrace gets out of your way to let you
- **just write**
Button primary
href /docs/getting-started
href /docs/javascript/#getting-started
Get Started
CodeExample
class min-h-[350px]
height 350px
terrace
title Terrace - A simple structured data language
description
@ -175,6 +175,7 @@ Section dark
class flex gap-4 items-center mb-4
Icon info
Heading 3 About
href /about/
class mb-0
Markdown
Why does Terrace exist? What is it based on? What are the development goals?
@ -185,6 +186,7 @@ Section dark
class flex gap-4 items-center mb-4
Icon file-text
Heading 3 Documentation
href /docs/javascript/
class mb-0
Markdown
Setup instructions, API documentation, and recipes for how to perform common tasks with Terrace.

View File

@ -8,15 +8,23 @@ module.exports = async (doc, rootLevel) => {
const node = {
type: head(),
class: '',
languages: {}
summaryClass: 'mb-[400px]',
preClass: 'max-h-[400px]',
examples: []
}
while (await next(rootLevel)) {
if (match('class')) node.class = tail()
if (match('summary-class')) node.summaryClass = tail()
if (match('pre-class')) node.preClass = tail()
const languageLevel = level()
const exampleLevel = level()
if (languages.includes(head())) {
node.languages[head()] = await contentAsText(doc, languageLevel)
node.examples.push({
language: head(),
name: tail() || '',
code: await contentAsText(doc, exampleLevel)
})
}
}

View File

@ -14,11 +14,13 @@ module.exports = async function (doc, rootLevel, pageData) {
text,
slug,
class: '',
href: '',
children: []
}
while (await next(rootLevel)) {
if (match('class')) node.class = tail()
if (match('href')) node.href = tail()
}
pageData.headings.push(node)

View File

@ -6,17 +6,11 @@ module.exports = async function (doc, rootLevel) {
const node = {
type: head(),
variant: tail() || 'neutral',
class: '',
href: '',
text: ''
class: ''
}
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

View File

@ -38,7 +38,8 @@ module.exports = {
info: colors.sky,
},
fontSize: {
sm: '0.8rem',
xs: '0.8rem',
sm: '1rem',
base: '1.125rem',
xl: '1.25rem',
'2xl': '1.563rem',

View File

@ -1,15 +1,15 @@
{
"name": "@terrace/repo",
"name": "@terrace-lang/repo",
"private": true,
"type": "module",
"scripts": {
"build:repo": "node ./repo/build.js",
"build": "turbo run build --cache-dir=.turbo",
"dev": "turbo run dev --no-cache --force",
"test": "turbo run test --filter=@terrace/test --no-cache --force"
"test": "turbo run test --filter=@terrace-lang/test --no-cache --force"
},
"devDependencies": {
"@terrace/js": "workspace:*",
"@terrace-lang/js": "workspace:*",
"turbo": "^1.7.3",
"jest": "^29.4.1"
}

View File

@ -1,5 +1,5 @@
{
"name": "@terrace/c",
"name": "@terrace-lang/c",
"version": "0.0.1",
"license": "MIT",
"scripts": {

View File

@ -1,5 +1,5 @@
{
"name": "@terrace/js",
"name": "@terrace-lang/js",
"version": "0.0.1",
"license": "MIT",
"type": "module",

View File

@ -7,7 +7,7 @@ export type Document = {
line: (startOffset?: number) => string,
head: () => string,
tail: () => string,
match: (matchHead: string) => boolean
match: (matchValue: string) => boolean
}
export function useDocument (reader: Reader, indent: string = ' '): Document {
@ -43,7 +43,7 @@ export function useDocument (reader: Reader, indent: string = ' '): Document {
const line = (startOffset: number = lineData.offsetHead) => lineData.line.slice(startOffset)
const head = () => lineData.line.slice(lineData.offsetHead, lineData.offsetTail)
const tail = () => lineData.line.slice(lineData.offsetTail + 1) // Skip the space
const match = (matchHead: string): boolean => matchHead === head()
const match = (matchValue: string): boolean => matchValue === head()
return {
next,

View File

@ -1,5 +1,5 @@
import { createLineData, parseLine, useDocument } from '@terrace/js'
import { createStdinReader } from '@terrace/js/readers/node-readline'
import { createLineData, parseLine, useDocument } from '@terrace-lang/js'
import { createStdinReader } from '@terrace-lang/js/readers/node-readline'
const testName = process.argv[2]

View File

@ -1,5 +1,5 @@
{
"name": "@terrace/python",
"name": "@terrace-lang/python",
"version": "0.0.1",
"license": "MIT",
"scripts": {

24
pnpm-lock.yaml generated
View File

@ -4,11 +4,11 @@ importers:
.:
specifiers:
'@terrace/js': workspace:*
'@terrace-lang/js': workspace:*
jest: ^29.4.1
turbo: ^1.7.3
devDependencies:
'@terrace/js': link:packages/js
'@terrace-lang/js': link:packages/js
jest: 29.4.1
turbo: 1.7.3
@ -18,7 +18,7 @@ importers:
'@11ty/eleventy-plugin-vite': ^4.0.0
'@sindresorhus/slugify': ^2.2.0
'@tailwindcss/typography': ^0.5.9
'@terrace/js': workspace:*
'@terrace-lang/js': workspace:*
eleventy-google-fonts: ^0.1.0
eleventy-plugin-feathericons: ^1.0.1
highlight.js: ^11.7.0
@ -30,7 +30,7 @@ importers:
'@11ty/eleventy-plugin-vite': 4.0.0
'@sindresorhus/slugify': 2.2.0
'@tailwindcss/typography': 0.5.9_tailwindcss@3.2.6
'@terrace/js': link:../packages/js
'@terrace-lang/js': link:../packages/js
eleventy-google-fonts: 0.1.0
eleventy-plugin-feathericons: 1.0.1
highlight.js: 11.7.0
@ -40,13 +40,13 @@ importers:
experiments/lesson-plans:
specifiers:
'@terrace/js': workspace:*
'@terrace-lang/js': workspace:*
ejs: ^3.1.8
humanize-duration: ^3.27.3
nunjucks: ^3.2.3
parse-duration: ^1.0.2
dependencies:
'@terrace/js': link:../../packages/js
'@terrace-lang/js': link:../../packages/js
ejs: 3.1.8
humanize-duration: 3.28.0
nunjucks: 3.2.3
@ -68,13 +68,13 @@ importers:
test:
specifiers:
'@terrace/c': workspace:*
'@terrace/js': workspace:*
'@terrace/python': workspace:*
'@terrace-lang/c': workspace:*
'@terrace-lang/js': workspace:*
'@terrace-lang/python': workspace:*
dependencies:
'@terrace/c': link:../packages/c
'@terrace/js': link:../packages/js
'@terrace/python': link:../packages/python
'@terrace-lang/c': link:../packages/c
'@terrace-lang/js': link:../packages/js
'@terrace-lang/python': link:../packages/python
packages:

View File

@ -1,6 +1,6 @@
import fs from 'node:fs/promises'
import { useDocument } from '@terrace/js'
import { createFileReader } from '@terrace/js/readers/node-readline'
import { useDocument } from '@terrace-lang/js'
import { createFileReader } from '@terrace-lang/js/readers/node-readline'
function useHelpers({ next, level, head, tail }) {

View File

@ -1,6 +1,6 @@
#schema package
name @terrace/repo
name @terrace-lang/repo
private true
type module
@ -8,9 +8,9 @@ scripts
build:repo node ./repo/build.js
build turbo run build --cache-dir=.turbo
dev turbo run dev --no-cache --force
test turbo run test --filter=@terrace/test --no-cache --force
test turbo run test --filter=@terrace-lang/test --no-cache --force
devDependencies
@terrace/js workspace:*
@terrace-lang/js workspace:*
turbo ^1.7.3
jest ^29.4.1

View File

@ -1,8 +1,8 @@
import { expect } from 'chai'
import fs from 'node:fs/promises'
import { execSync } from 'node:child_process'
import { useDocument } from '@terrace/js'
import { createFileReader } from '@terrace/js/readers/node-readline'
import { useDocument } from '@terrace-lang/js'
import { createFileReader } from '@terrace-lang/js/readers/node-readline'
export async function loadTestMap(path) {
const { next, level, head, tail, line, match } = useDocument(createFileReader(path))

View File

@ -1,12 +1,12 @@
{
"name": "@terrace/test",
"name": "@terrace-lang/test",
"type": "module",
"scripts": {
"test": "NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 jest"
},
"dependencies": {
"@terrace/js": "workspace:*",
"@terrace/c": "workspace:*",
"@terrace/python": "workspace:*"
"@terrace-lang/js": "workspace:*",
"@terrace-lang/c": "workspace:*",
"@terrace-lang/python": "workspace:*"
}
}