Updates.
This commit is contained in:
1
docs/pages/docs/go.tce
Normal file
1
docs/pages/docs/go.tce
Normal file
@@ -0,0 +1 @@
|
||||
Include ../../../packages/go/docs/index.tce
|
||||
1
docs/pages/docs/python.tce
Normal file
1
docs/pages/docs/python.tce
Normal file
@@ -0,0 +1 @@
|
||||
Include ../../../packages/python/docs/index.tce
|
||||
1
docs/pages/docs/rust.tce
Normal file
1
docs/pages/docs/rust.tce
Normal file
@@ -0,0 +1 @@
|
||||
Include /home/sysadmin/Experiments/Terrace/packages/rust/docs/index.tce
|
||||
@@ -1,16 +1,26 @@
|
||||
|
||||
export async function contentAsText (doc, rootLevel, includeCurrent = false) {
|
||||
const { level, next, line, head } = doc
|
||||
export async function contentAsText(parentNode, includeCurrent = false) {
|
||||
const linesAsArray = []
|
||||
if (includeCurrent) linesAsArray.push(line())
|
||||
let contentDepth = includeCurrent ? level() : -1
|
||||
if (includeCurrent) linesAsArray.push(parentNode.content)
|
||||
let contentDepth = includeCurrent ? parentNode.level : -1
|
||||
|
||||
while(await next(rootLevel)) {
|
||||
if (contentDepth === -1 && !!line()) contentDepth = level()
|
||||
for await (const child of parentNode.children()) {
|
||||
if (contentDepth === -1) contentDepth = child.level
|
||||
|
||||
const indent = ''.padStart(level() - contentDepth, ' ')
|
||||
linesAsArray.push(indent + line())
|
||||
const indent = ''.padStart(child.level - contentDepth, ' ')
|
||||
linesAsArray.push(indent + child.content.trimEnd())
|
||||
}
|
||||
|
||||
return linesAsArray.join('\n')
|
||||
}
|
||||
|
||||
// New helper for getting all child content as structured data
|
||||
export async function getChildrenByType(parentNode) {
|
||||
const result = {}
|
||||
for await (const child of parentNode.children()) {
|
||||
if (!child.head) continue
|
||||
if (!result[child.head]) result[child.head] = []
|
||||
result[child.head].push(child)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -5,10 +5,9 @@ import { createFileReader } from '@terrace-lang/js/readers/node-readline'
|
||||
import process from 'node:process'
|
||||
import path from 'node:path'
|
||||
|
||||
export default async function(filePath) {
|
||||
export default async function (filePath) {
|
||||
filePath = path.resolve(filePath)
|
||||
const doc = useDocument(createFileReader(filePath))
|
||||
const { next, line, match, tail, level, head } = doc
|
||||
const doc = useDocument(createFileReader(filePath), ' ')
|
||||
|
||||
const page = {
|
||||
type: `Page`,
|
||||
@@ -25,21 +24,20 @@ export default async function(filePath) {
|
||||
}
|
||||
|
||||
const originalCWD = process.cwd()
|
||||
while(await next()) {
|
||||
if (!line()) continue
|
||||
if (match('title')) page.title = tail()
|
||||
else if (match('layout')) page.layout = tail()
|
||||
else if (match('description')) {
|
||||
const l = level()
|
||||
while(await next(l)) {
|
||||
page.description.push(line(l))
|
||||
for await (const node of doc) {
|
||||
if (node.isEmpty()) continue
|
||||
if (node.is('title')) page.title = node.tail
|
||||
else if (node.is('layout')) page.layout = node.tail
|
||||
else if (node.is('description')) {
|
||||
for await (const child of node.children()) {
|
||||
page.description.push(child.content)
|
||||
}
|
||||
}
|
||||
else if (match('Section')) {
|
||||
page.children.push(await knownNodes.Section(doc, level(), context))
|
||||
else if (node.is('Section')) {
|
||||
page.children.push(await knownNodes.Section(doc, node, context))
|
||||
}
|
||||
else if (match('Include')) {
|
||||
page.children.push(await knownNodes.Include(doc, level(), context))
|
||||
else if (node.is('Include')) {
|
||||
page.children.push(await knownNodes.Include(doc, node, context))
|
||||
}
|
||||
}
|
||||
process.chdir(originalCWD)
|
||||
|
||||
@@ -1,23 +1,43 @@
|
||||
import { contentAsText } from '../helpers.js'
|
||||
|
||||
export default async function (doc, rootLevel) {
|
||||
const { next, line, match, tail, level, head } = doc
|
||||
|
||||
export default async function (doc, rootNode) {
|
||||
const node = {
|
||||
type: head(),
|
||||
variant: tail() || 'neutral',
|
||||
type: rootNode.head,
|
||||
variant: '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)
|
||||
const tail = rootNode.tail || ''
|
||||
const tailParts = tail.split(' ')
|
||||
const firstWord = tailParts[0]
|
||||
if (firstWord === 'primary' || firstWord === 'neutral') {
|
||||
node.variant = firstWord
|
||||
const tailText = tailParts.slice(1).join(' ')
|
||||
if (tailText) node.text = tailText
|
||||
} else {
|
||||
node.variant = 'neutral'
|
||||
if (tail) node.text = tail
|
||||
}
|
||||
|
||||
for await (const child of rootNode.children()) {
|
||||
if (child.is('class')) node.class = child.tail
|
||||
else if (child.is('href')) node.href = child.tail
|
||||
else if (!node.text) {
|
||||
// If it's not a recognized attribute, treat the entire content as button text
|
||||
node.text = child.content.trim()
|
||||
}
|
||||
}
|
||||
|
||||
const next = await rootNode._document._getNextNode()
|
||||
if (next && next.level > rootNode.level && !next.isEmpty() && !next.head) {
|
||||
if (!node.text) {
|
||||
node.text = await contentAsText(next, true)
|
||||
}
|
||||
} else if (next) {
|
||||
rootNode._document._pushBack(next)
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
import { contentAsText } from '../helpers.js'
|
||||
|
||||
export default async (doc, rootLevel) => {
|
||||
const { next, level, line, head, tail, match } = doc
|
||||
|
||||
export default async (doc, rootNode) => {
|
||||
const node = {
|
||||
type: head(),
|
||||
language: tail(),
|
||||
type: rootNode.head,
|
||||
language: rootNode.tail.trim(),
|
||||
class: '',
|
||||
text: ''
|
||||
}
|
||||
|
||||
while (await next(rootLevel)) {
|
||||
if (match('class')) node.class = tail()
|
||||
else node.text = await contentAsText(doc, rootLevel, true)
|
||||
let codeText = ''
|
||||
for await (const child of rootNode.children()) {
|
||||
if (child.is('class')) node.class = child.tail
|
||||
else codeText += await contentAsText(child, true) + '\n'
|
||||
}
|
||||
|
||||
node.text = node.text.trimEnd()
|
||||
node.text = codeText.trimEnd()
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
@@ -2,28 +2,25 @@ import { contentAsText } from '../helpers.js'
|
||||
|
||||
const languages = ['terrace', 'json', 'yaml', 'toml', 'javascript', 'typescript', 'c', 'python', 'sh']
|
||||
|
||||
export default async (doc, rootLevel) => {
|
||||
const { next, level, line, head, tail, match } = doc
|
||||
|
||||
export default async (doc, rootNode) => {
|
||||
const node = {
|
||||
type: head(),
|
||||
type: rootNode.head,
|
||||
class: '',
|
||||
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()
|
||||
for await (const child of rootNode.children()) {
|
||||
if (child.is('class')) node.class = child.tail
|
||||
if (child.is('summary-class')) node.summaryClass = child.tail
|
||||
if (child.is('pre-class')) node.preClass = child.tail
|
||||
|
||||
const exampleLevel = level()
|
||||
if (languages.includes(head())) {
|
||||
if (languages.includes(child.head)) {
|
||||
node.examples.push({
|
||||
language: head(),
|
||||
name: tail() || '',
|
||||
code: (await contentAsText(doc, exampleLevel)).trimEnd('\n')
|
||||
language: child.head.trim(),
|
||||
name: child.tail || '',
|
||||
code: (await contentAsText(child, true)).trimEnd('\n')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import slugify from '@sindresorhus/slugify'
|
||||
|
||||
export default async function (doc, rootLevel, context) {
|
||||
const { next, line, match, tail, level, head } = doc
|
||||
|
||||
const headingLevel = +tail().split(' ')[0]
|
||||
const text = tail().split(' ').slice(1).join(' ')
|
||||
export default async function (doc, rootNode, context) {
|
||||
const headingLevel = +rootNode.tail.split(' ')[0]
|
||||
const text = rootNode.tail.split(' ').slice(1).join(' ')
|
||||
const slug = slugify(text)
|
||||
|
||||
const node = {
|
||||
type: head(),
|
||||
type: rootNode.head,
|
||||
level: headingLevel,
|
||||
text,
|
||||
slug,
|
||||
@@ -17,9 +15,9 @@ export default async function (doc, rootLevel, context) {
|
||||
children: []
|
||||
}
|
||||
|
||||
while (await next(rootLevel)) {
|
||||
if (match('class')) node.class = tail()
|
||||
if (match('href')) node.href = tail()
|
||||
for await (const child of rootNode.children()) {
|
||||
if (child.is('class')) node.class = child.tail
|
||||
if (child.is('href')) node.href = child.tail
|
||||
}
|
||||
|
||||
context.page.headings.push(node)
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
export default async function (doc) {
|
||||
const { head, tail } = doc
|
||||
|
||||
export default async function (doc, rootNode) {
|
||||
const node = {
|
||||
type: head(),
|
||||
icon: tail()
|
||||
type: rootNode.head,
|
||||
icon: rootNode.tail
|
||||
}
|
||||
|
||||
return node
|
||||
|
||||
@@ -5,29 +5,36 @@ import path from 'path'
|
||||
import process from 'node:process'
|
||||
import knownNodes from './index.js'
|
||||
|
||||
export default async function (originalDoc, rootLevel, context) {
|
||||
const includePath = originalDoc.tail()
|
||||
export default async function (originalDoc, rootNode, context) {
|
||||
const includePath = rootNode.tail
|
||||
const includedDoc = useDocument(createFileReader(includePath))
|
||||
const { next, head, tail, level } = includedDoc
|
||||
|
||||
const node = {
|
||||
type: originalDoc.head(),
|
||||
type: rootNode.head,
|
||||
class: '',
|
||||
children: []
|
||||
}
|
||||
|
||||
|
||||
const root = path.dirname(context.filePath)
|
||||
const originalFilepath = context.filePath
|
||||
context.filePath = includePath
|
||||
|
||||
process.chdir(path.dirname(originalFilepath))
|
||||
while (await next()) {
|
||||
if (!head()) continue
|
||||
const block = head()
|
||||
|
||||
if (!knownNodes[block]) continue
|
||||
node.children.push(await knownNodes[block](includedDoc, level(), context))
|
||||
for await (const childNode of includedDoc) {
|
||||
if (childNode.isEmpty()) continue
|
||||
if (childNode.is('title')) context.page.title = childNode.tail
|
||||
else if (childNode.is('layout')) context.page.layout = childNode.tail
|
||||
else if (childNode.is('description')) {
|
||||
for await (const grandchild of childNode.children()) {
|
||||
context.page.description.push(grandchild.content)
|
||||
}
|
||||
}
|
||||
else if (!childNode.head) continue
|
||||
else {
|
||||
const block = childNode.head
|
||||
if (!knownNodes[block]) continue
|
||||
node.children.push(await knownNodes[block](includedDoc, childNode, context))
|
||||
}
|
||||
}
|
||||
|
||||
process.chdir(path.dirname(originalFilepath))
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import { contentAsText } from '../helpers.js'
|
||||
|
||||
export default async function (doc, rootLevel) {
|
||||
const { next, line, match, tail, level, head } = doc
|
||||
|
||||
export default async function (doc, rootNode) {
|
||||
const node = {
|
||||
type: head(),
|
||||
variant: tail() || 'neutral',
|
||||
type: rootNode.head,
|
||||
variant: rootNode.tail || 'neutral',
|
||||
class: ''
|
||||
}
|
||||
|
||||
while (await next(rootLevel)) {
|
||||
if (match('class')) node.class = tail()
|
||||
for await (const child of rootNode.children()) {
|
||||
if (child.is('class')) node.class = child.tail
|
||||
}
|
||||
|
||||
return node
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import { contentAsText } from '../helpers.js'
|
||||
import { parse } from 'marked'
|
||||
|
||||
export default async function (doc, rootLevel) {
|
||||
const { next, line, match, tail, level, head } = doc
|
||||
|
||||
export default async function (doc, rootNode) {
|
||||
const node = {
|
||||
type: head(),
|
||||
type: rootNode.head,
|
||||
class: '',
|
||||
text: ''
|
||||
}
|
||||
|
||||
while (await next(rootLevel)) {
|
||||
if (match('class')) node.class = tail()
|
||||
else node.text = parse(await contentAsText(doc, rootLevel, true))
|
||||
let markdownText = ''
|
||||
for await (const child of rootNode.children()) {
|
||||
if (child.is('class')) node.class = child.tail
|
||||
else markdownText += await contentAsText(child, true) + '\n'
|
||||
}
|
||||
node.text = parse(markdownText.trim())
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
import knownNodes from './index.js'
|
||||
|
||||
export default async function (doc, rootLevel, ...args) {
|
||||
const { next, line, match, tail, level, head } = doc
|
||||
|
||||
export default async function (doc, rootNode, ...args) {
|
||||
const node = {
|
||||
type: head(),
|
||||
type: rootNode.head,
|
||||
class: '',
|
||||
children: []
|
||||
}
|
||||
|
||||
while (await next(rootLevel)) {
|
||||
if (!head()) continue
|
||||
const block = head()
|
||||
for await (const child of rootNode.children()) {
|
||||
if (!child.head) continue
|
||||
const block = child.head
|
||||
|
||||
if (match('class')) {
|
||||
node.class = tail()
|
||||
if (child.is('class')) {
|
||||
node.class = child.tail
|
||||
continue
|
||||
}
|
||||
|
||||
if (!knownNodes[block]) continue
|
||||
node.children.push(await knownNodes[block](doc, level(), ...args))
|
||||
node.children.push(await knownNodes[block](doc, child, ...args))
|
||||
}
|
||||
|
||||
return node
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
export default async function (doc, rootLevel) {
|
||||
const { next, head, tail, match } = doc
|
||||
|
||||
export default async function (doc, rootNode) {
|
||||
const node = {
|
||||
type: head(),
|
||||
type: rootNode.head,
|
||||
class: '',
|
||||
}
|
||||
|
||||
while (await next(rootLevel)) {
|
||||
if (match('class')) node.class = tail()
|
||||
for await (const child of rootNode.children()) {
|
||||
if (child.is('class')) node.class = child.tail
|
||||
}
|
||||
|
||||
return node
|
||||
|
||||
@@ -11,9 +11,9 @@ import Logo from './Logo.js'
|
||||
import Footer from './Footer.js'
|
||||
|
||||
const Block = parseNode
|
||||
const Section = async (doc, rootLevel, ...args) => {
|
||||
const variant = doc.tail()
|
||||
return { variant, ...(await parseNode(doc, rootLevel, ...args)) }
|
||||
const Section = async (doc, node, ...args) => {
|
||||
const variant = node.tail
|
||||
return { variant, ...(await parseNode(doc, node, ...args)) }
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% macro render(node) %}
|
||||
{% if node.variant == 'small' %}
|
||||
{% if node.variant == 'light' %}
|
||||
<div class="flex gap-2 items-center {{node.class}}">
|
||||
<img src="/public/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>
|
||||
|
||||
@@ -10,7 +10,10 @@ const pages = {
|
||||
'/': './pages/index.tce',
|
||||
'/about/': './pages/about.tce',
|
||||
'/docs/javascript/': './pages/docs/javascript.tce',
|
||||
'/docs/c/': './pages/docs/c.tce'
|
||||
'/docs/c/': './pages/docs/c.tce',
|
||||
'/docs/go/': './pages/docs/go.tce',
|
||||
'/docs/rust/': './pages/docs/rust.tce',
|
||||
'/docs/python/': './pages/docs/python.tce'
|
||||
}
|
||||
|
||||
async function render() {
|
||||
|
||||
Reference in New Issue
Block a user