Start working on docs site.

This commit is contained in:
Joshua Bemenderfer 2023-02-11 22:30:10 -05:00
parent cb09652f61
commit bc2fc78c96
37 changed files with 1747 additions and 3087 deletions

31
docs/.eleventy.js Normal file
View File

@ -0,0 +1,31 @@
const EleventyVitePlugin = require('@11ty/eleventy-plugin-vite')
const { useDocument } = require('@terrace/js/document')
const { createFileReader } = require('@terrace/js/readers/node-readline')
const parsePage = require('./parser/page.js')
module.exports = function (config) {
config.addPlugin(EleventyVitePlugin)
config.addPassthroughCopy('src/public')
config.addPassthroughCopy('src/styles')
config.addPassthroughCopy('src/main.js')
config.addTemplateFormats('tce')
config.addExtension('tce', {
async compile(content) {
return async () => content
},
async getData(inputPath) {
const doc = useDocument(createFileReader(inputPath))
return await parsePage(doc)
}
})
return {
dir: {
input: 'src',
output: '_site'
},
passthroughFileCopy: true
}
}

1
docs/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
_site

1
docs/dsl/.gitignore vendored
View File

@ -1 +0,0 @@
node_modules

View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2022 Joshua Michael Bemenderfer
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,31 +0,0 @@
import { document } from '../../../implementations/js/packages/core/src/terrace.js'
import fs from 'node:fs'
import readline from 'node:readline/promises'
import markdown from '../../../packages/js/block-markdown/index.js'
async function main() {
const mdHandler = markdown({})
const it = readline.createInterface({
input: fs.createReadStream('./test.tce', 'utf-8'),
})[Symbol.asyncIterator]()
const doc = document(async () => (await it.next()).value)
async function mainHandler({ line, lineData, ended, next, current }, page) {
if (ended) return page
if (line.startsWith('markdown')) {
lineData.offset = 'markdown'.length
page.body += await mdHandler(current(), mainHandler)
lineData.offset = 0
return mainHandler(current(), page)
}
return mainHandler(await next(), page)
}
console.log(await mainHandler(await doc.next(), { body: '' }))
}
main()

View File

@ -1,23 +0,0 @@
import { describe, it } from "vitest"
import { document } from '../../../implementations/js/packages/core/src/terrace.js'
import fs from 'node:fs'
import readline from 'node:readline/promises'
describe('Terrace DSL: thederf.com', () => {
it('loads', async () => {
const it = readline.createInterface({
input: fs.createReadStream('./test.tce', 'utf-8'),
})[Symbol.asyncIterator]()
const getLine = async () => {
console.log(1)
console.log('GETLINE', await it.next())
console.log(2)
const val = (await it.next()).value
return val
}
const doc = document(getLine, ' ')
doc.next(() => {})
})
})

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +0,0 @@
{
"name": "@terrace/dsl-terrace-docs",
"version": "0.0.1",
"type": "module",
"scripts": {
"test": "vitest"
},
"devDependencies": {
"vitest": "^0.24.5"
}
}

View File

@ -1,15 +0,0 @@
title TEST
markdown
# Title
Dolore do do sit velit ullamco labore nisi laborum ut.
List time
- List 1
- List 2
markdown
# Title 2
Incididunt qui nulla est enim officia ad sunt excepteur consequat sunt.

View File

@ -1 +0,0 @@
node_modules/

View File

@ -1,9 +0,0 @@
{
"type": "module",
"dependencies": {
"@terrace/core": "workspace:*"
},
"scripts": {
"example": "node ./parsers/v5/example.js"
}
}

View File

@ -1,135 +0,0 @@
import { createLineData, useDocument } from '@terrace/core'
import { createStringReader } from '@terrace/core/readers/js-string'
export const SYMBOLS = {
TAIL: Symbol('TAIL'),
UNMATCHED: Symbol('UNMATCHED')
}
export const BASE_MACROS = {
string({ tail }) {
return tail.toString()
},
number({ tail }) {
const num = +tail
if (isNaN(num) || tail === '') return
return num
},
primitive({ macros }) {
const num = macros.number(args)
return num !== undefined ? num : macros.string(args)
},
any(args) {
const macro = args.macros[args.head]
if (macro) return macro(args)
const numResult = args.macros.number(args)
if (numResult !== undefined) return numResult
args.tail = args.line
return args.macros.string(args)
},
scope({ addScope, head, tail, line }, definition) {
return addScope({ definition, head, tail, line })
}
}
export function getTail(key, macro) {
return args => {
const scope = args.scope
const result = macro(args)
if (result === undefined) return
if (!scope[key]) scope[key] = []
scope[key].push(result)
}
}
export function getText(key, macro) {
return (args) => {
const scope = args.scope
const result = macro({...args, tail: args.line })
if (result === undefined) return
if (!scope[key]) scope[key] = []
scope[key].push(result)
}
}
export function getUnmatched(macro) {
return (args) => {
const key = args.head
const scope = args.scope
const result = macro(args)
if (result === undefined) return
if (!scope[key]) scope[key] = []
scope[key].push(result)
}
}
export function isMacro (macro) {
return (args) => args.macros[macro](args)
}
export function isCollection (macro) {
return (args) => ({ [args.head]: macro(args) })
}
export function isScope (definition) {
return (args) => args.macros.scope(args, definition)
}
export async function parse(lines, schema) {
const doc = useDocument(createStringReader(lines))
const macros = schema.macros
const handlers = [schema.root]
const scopes = [{}]
function addScope({ head, tail, line, definition }) {
const scope = {}
if (definition[SYMBOLS.TAIL]) {
const result = definition[SYMBOLS.TAIL]({ macros, scope, head, tail, line, addScope })
Object.assign(scope, result)
}
scopes[scopes.length] = scope
handlers[handlers.length] = definition
return scope
}
let ended = false
while (!ended) {
ended = await doc.next()
if (ended) break;
if (doc.line() === '') continue;
const level = doc.level()
handlers.length = level + 1
scopes.length = level + 1
const line = doc.line()
const head = doc.head()
const tail = doc.tail().slice(1)
const options = handlers[level]
const scope = scopes[level]
const matches = {
head: options?.[doc.head()],
unmatched: options?.[SYMBOLS.UNMATCHED]
}
if (matches.head) {
const result = matches.head({macros, scope, head, tail, line, addScope })
if (!scope[head]) scope[head] = []
scope[head].push(result)
continue
}
if (matches.unmatched) {
const result = matches.unmatched({ macros, scope, head, tail, line, addScope })
Object.assign(scope, result)
}
}
return scopes[0]
}

View File

@ -1,118 +0,0 @@
import { SYMBOLS, parse, isScope, isMacro, getTail, getText, getUnmatched, isCollection } from './core.js'
const schemaTCE = `
macros
primitive match number string
section
pos number tail
content string unmatched
position number
options
parameter1 number
parameter2 string
literal unmatched string
unmatched primitive
root
title string
options options collection
subsection section
list
- string array
collection
section collection
collection2
unmatched collection
`
const schema = {
macros: {
string({ tail }) {
return tail.toString()
},
number({ tail }) {
const num = +tail
if (isNaN(num) || tail === '') return
return num
},
primitive({ macros }) {
const num = macros.number(args)
return num !== undefined ? num : macros.string(args)
},
scope({ addScope, head, tail, line }, definition) {
return addScope({ definition, head, tail, line })
},
section: isScope({
[SYMBOLS.TAIL]: getTail('pos', isMacro('number')),
[SYMBOLS.UNMATCHED]: getText('content', isMacro('string')),
position: isMacro('number')
}),
options: isScope({
parameter1: isMacro('number'),
parameter2: isMacro('string'),
unmatched: isMacro('string'),
[SYMBOLS.UNMATCHED]: getUnmatched(isMacro('any')),
}),
any(args) {
const macro = args.macros[args.head]
if (macro) return macro(args)
const numResult = args.macros.number(args)
if (numResult !== undefined) return numResult
args.tail = args.line
return args.macros.string(args)
},
},
root: {
title: isMacro('string'),
options: isMacro('options'),
subsection: isMacro('section'),
list: isScope({
'-': isMacro('string')
}),
collection: isScope({
section: isCollection(isMacro('section'))
}),
collection2: isScope({
[SYMBOLS.UNMATCHED]: getUnmatched(isMacro('any'))
})
}
}
const lines = [
`title Example`,
`options`,
` parameter1 30`,
` parameter2 Enim eu id anim minim reprehenderit nostrud eu amet deserunt ea ut do cupidatat ea.`,
`options`,
` parameter1 0`,
` parameter2 Esse incididunt et est adipisicing eiusmod aliqua enim ea aliqua id enim.`,
`subsection`,
` position 1`,
` Ea dolore in aliquip fugiat anim adipisicing amet aute tempor et deserunt est duis sint.`,
`subsection 2`,
` position 2`,
` Aute deserunt incididunt ad in sint adipisicing est officia velit pariatur ipsum deserunt quis nulla.`,
` Ea dolore in aliquip fugiat anim adipisicing amet aute tempor et deserunt est duis sint.`,
`list`,
` - item 1`,
` - item 2`,
`collection`,
` section`,
` lorem ipsum 1`,
` section`,
` lorem ipsum 2`,
`collection2`,
` section`,
` position 3`,
` Laborum aute anim occaecat occaecat pariatur tempor proident magna sit magna non non.`,
` list`,
` 1`,
` 2`
]
async function main() {
console.dir(await parse(lines, schema), { depth: null })
}
main()

View File

@ -1,126 +0,0 @@
import { useDocument } from '@terrace/core'
import { createStringReader } from '@terrace/core/readers/js-string'
const lines = [
`name @terrace/core`,
`version 0.0.1`,
`randomthing test`,
`license MIT`,
`license GPL`,
`exports`,
` .`,
` import ./dist/index.js`,
` require ./dist/index.cjs`,
` ./parser`,
` import ./dist/parser.js`,
` require ./dist/parser.cjs`,
``,
` ./document`,
` import ./dist/document.js`,
` require ./dist/document.cjs`,
``,
` ./readers/node-readline`,
` import ./dist/readers/node-readline.js`,
` require ./dist/readers/node-readline.cjs`,
``,
` ./readers/js-string`,
` import ./dist/readers/js-string.js`,
` require ./dist/readers/js-string.cjs`,
`scripts`,
` test vitest ./src`,
` build vite build`,
`devDependencies`,
` vite ^3.2.3`,
` vitest ^0.24.5`,
``,
`authors`,
` author`,
` name Joshua Bemenderfer`,
` email josh@thederf.com`,
``,
` Further comments below. As I will now demonstrate, there is no simple`,
` even if embedded`,
` way of dealing with this problem.`,
` author`,
` name Second Person`,
` email second@secondperson.com`,
` More text,`,
` across two lines.`,
`list`,
` - item1`,
` - item2`
]
// Schema
// name tail
// version tail
// license tail
// exports object
// #any object
// import tail
// require tail
// scripts object
// #any tail
// devDependencies
// #any tail
// author object
// name tail
// email tail
// #text
async function main() {
const { head, tail, next, match, level, line } = useDocument(createStringReader(lines))
const structure = {}
async function kvObject(handle) {
const obj = {}
const l = level()
while (await next(l)) {
if (!head()) continue
obj[head()] = handle ? await handle(level()) : tail().trim()
}
return obj
}
while (await next()) {
if (match('name')) structure.name = tail().trim()
if (match('version')) structure.version = tail().trim()
if (match('exports')) structure.exports = await kvObject(async l => {
const obj = {}
while (await next(l)) {
if (match('import')) obj.import = tail().trim()
if (match('require')) obj.require = tail().trim()
}
return obj
})
if (match('scripts')) structure.scripts = await kvObject()
if (match('devDependencies')) structure.devDependencies = await kvObject()
if (match('author')) {
if (!structure.authors) structure.authors = []
const author = {}
structure.authors.push(author)
const l = level()
while (await next(l)) {
if (!head()) continue
if (match('name')) author.name = tail().trim()
else if (match('email')) author.email = tail().trim()
else {
if (!author['#text']) author['#text'] = [line(l + 1)]
// Loop through all remaining lines to avoid re-matching name or email above.
while(await next(l)) {
author['#text'].push(line(l + 1))
}
}
}
}
}
console.dir(structure, { depth: null })
}
main()

17
docs/package.json Normal file
View File

@ -0,0 +1,17 @@
{
"name": "@terrace/docs",
"private": true,
"license": "MIT",
"scripts": {
"dev": "eleventy --serve --incremental",
"build": "eleventy"
},
"devDependencies": {
"@terrace/js": "workspace:*",
"@11ty/eleventy": "^2.0.0",
"@11ty/eleventy-plugin-vite": "^4.0.0",
"@tailwindcss/typography": "^0.5.9",
"tailwindcss": "^3.2.6",
"vite": "^3.2.3"
}
}

View File

@ -1,2 +0,0 @@
title Terrace - A fast, flexible, metamarkup language
description

31
docs/parser/page.js Normal file
View File

@ -0,0 +1,31 @@
const parseSection = require('./section.js')
module.exports = async function(doc) {
const { next, line, match, tail, level, head } = doc
const pageData = {
title: '',
description: [],
layout: '',
sections: []
}
while(await next()) {
if (!line()) continue
if (match('title')) pageData.title = tail()
else if (match('layout')) pageData.layout = tail()
else if (match('description')) {
const l = level()
while(await next(l)) {
pageData.description.push(line(l))
}
}
else if (match('section')) {
pageData.sections.push(await parseSection(doc, level()))
}
}
console.dir(pageData, { depth: null })
return pageData
}

27
docs/parser/section.js Normal file
View File

@ -0,0 +1,27 @@
const parseSection = require('./section.js')
const knownBlocks = {
'logo': () => {},
'div': () => {},
'markdown': () => {},
}
module.exports = async function(doc, rootLevel) {
const { next, line, match, tail, level, head } = doc
const section = {
class: '',
children: []
}
while (await next(rootLevel)) {
if (!head()) continue
const block = head()
if (!knownBlocks[block]) continue
// TODO: Start Parsing
section.children.push(line())
}
return section
}

6
docs/postcss.config.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

View File

@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title }}</title>
<meta name="description" content="{{ description | join(' ') }}"/>
</head>
<body>
<script type="module" src="/main.js"></script>
</body>
</html>

65
docs/src/index.tce Normal file
View File

@ -0,0 +1,65 @@
layout layout.njk
title Terrace - A simple structured data language
description
A simple structured data syntax for configuration, content authoring, and DSLs.
Terrace gets out of your way to let you just write
section light
class flex gap-16
div
class flex flex-column gap-16
logo
markdown
A simple structured data syntax for
- **Configuration**
- **Content authoring**
- **DSLs**
Terrace gets out of your way to let you
- **just write**
code-example
terrace
title Terrace - A simple structured data language
description
A simple structured data syntax for configuration, content authoring, and DSLs.
Terrace gets out of your way to let you just write
markdown
A simple structured data syntax for
- **Configuration**
- **Content authoring**
- **DSLs**
Terrace gets out of your way to let you
- **just write**
json
{
"title": "Terrace - A simple structured data language",
"description": "A simple structured data syntax for configuration, content authoring, and DSLs.\nTerrace gets out of your way to let you just write",
"markdown": "A simple structured data syntax for\n - **Configuration**\n - **Content authoring**\n - **DSLs**\nTerrace gets out of your way to let you\n - **just write**"
}
yaml
title: Terrace - A simple structured data language
description: |
A simple structured data syntax for configuration, content authoring, and DSLs.
Terrace gets out of your way to let you just write
markdown: |
A simple structured data syntax for
- **Configuration**
- **Content authoring**
- **DSLs**
Terrace gets out of your way to let you
- **just write**
toml
title = "Terrace - A simple structured data language"
description = """
A simple structured data syntax for configuration, content authoring, and DSLs.
Terrace gets out of your way to let you just write"""
markdown = """
A simple structured data syntax for
- **Configuration**
- **Content authoring**
- **DSLs**
Terrace gets out of your way to let you
- **just write**"""

1
docs/src/main.js Normal file
View File

@ -0,0 +1 @@
import './styles/main.css'

3
docs/src/styles/main.css Normal file
View File

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

14
docs/tailwind.config.js Normal file
View File

@ -0,0 +1,14 @@
const defaultTheme = require('tailwindcss/defaultTheme');
module.exports = {
content: ['./src/**/*.html', './src/**/*.tce'],
theme: {
extend: {
fontFamily: {
sans: ['Inter var', ...defaultTheme.fontFamily.sans],
},
},
},
variants: {},
plugins: [require('@tailwindcss/typography')],
};

3
docs/vite.config.js Normal file
View File

@ -0,0 +1,3 @@
import { defineConfig } from 'vite';
export default defineConfig()

View File

@ -9,7 +9,7 @@
"test": "turbo run test --filter=@terrace/test --no-cache --force" "test": "turbo run test --filter=@terrace/test --no-cache --force"
}, },
"devDependencies": { "devDependencies": {
"@terrace/core": "workspace:*", "@terrace/js": "workspace:*",
"turbo": "^1.7.3", "turbo": "^1.7.3",
"jest": "^29.4.1" "jest": "^29.4.1"
} }

File diff suppressed because it is too large Load Diff

View File

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

View File

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

1534
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
packages: packages:
- "./docs"
- "./test" - "./test"
- "./packages/*" - "./packages/*"
- "./experiments/*" - "./experiments/*"

View File

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

View File

@ -11,6 +11,6 @@ scripts
test turbo run test --filter=@terrace/test --no-cache --force test turbo run test --filter=@terrace/test --no-cache --force
devDependencies devDependencies
@terrace/core workspace:* @terrace/js workspace:*
turbo ^1.7.3 turbo ^1.7.3
jest ^29.4.1 jest ^29.4.1

View File

@ -12,4 +12,4 @@ pipeline
dependsOn build dependsOn build
test test
dependsOn build build:test dependsOn build ^build ^build:test

View File

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

View File

@ -5,6 +5,8 @@
"test": "NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 jest" "test": "NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 jest"
}, },
"dependencies": { "dependencies": {
"@terrace/core": "workspace:*" "@terrace/js": "workspace:*",
"@terrace/c": "workspace:*",
"@terrace/python": "workspace:*"
} }
} }

View File

@ -20,7 +20,8 @@
"test": { "test": {
"dependsOn": [ "dependsOn": [
"build", "build",
"build:test" "^build",
"^build:test"
] ]
} }
} }