2022-11-13 09:50:23 -05:00

140 lines
3.5 KiB
JavaScript

import { createLineData, useDocument } from '@terrace/core'
import { createStringReader } from '@terrace/core/readers/js-string'
const schema = {
types: {
subsection: {
type: 'object',
text: 'content',
tail: 'number',
values: {
position: {
type: 'number'
}
}
},
options: {
type: 'object',
values: {
parameter1: 'number',
parameter2: 'string'
}
}
},
root: {
type: 'object',
values: {
title: 'string',
options: 'options',
options2: 'options',
subsection: {
type: 'collection',
collection: 'subsection'
}
}
}
}
const lines = [
`title Example`,
`options`,
` parameter1 30`,
` parameter2 Enim eu id anim minim reprehenderit nostrud eu amet deserunt ea ut do cupidatat ea.`,
`options2`,
` 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.`
]
const typeHandlers = {
string (key, definition, add) {
return (doc, handlers) => {
if (doc.head() !== key) return
add(key, doc.tail().slice(1))
}
},
number (key, definition, add) {
return (doc, handlers) => {
if (doc.head() !== key) return
add(key, +doc.tail().slice(1))
}
},
object (key, definition, add) {
definition = resolve(definition)
return (doc, handlers) => {
if (doc.head() !== key) return
const object = {}
add(key, object)
for (const [key, child] of Object.entries(definition.values)) {
addHandler(handlers, doc.level() + 1, key, child, (key, value) => (object[key] = value))
}
}
},
collection (key, definition, add) {
return (doc, handlers) => {
if (doc.head() !== key) return
const collection = []
add(key, collection)
const child = resolve(definition.collection)
addHandler(handlers, doc.level() + 1, '*', child, (key, value) => ( collection.push(value) ))
}
}
}
function resolve (definition) {
const type = typeof definition === 'string' ? definition : definition.type
if (schema.types[type]) return schema.types[type]
else return definition
}
function registerTypes(typeHandlers, types) {
for (const [key, definition] of Object.entries(types)) {
const existingType = typeof definition === 'string' ? definition : definition.type
typeHandlers[key] = typeHandlers[existingType]
}
}
function addHandler(handlers, level, key, definition, add) {
const type = typeof definition === 'string' ? definition : definition.type
if (!handlers[level]) handlers[level] = []
handlers[level].push(typeHandlers[type](key, definition, add))
}
async function main() {
const doc = useDocument(createStringReader(lines))
const handlers = []
registerTypes(typeHandlers, schema.types)
const root = {}
for (const [key, child] of Object.entries(schema.root.values)) {
addHandler(handlers, 0, key, child, (key, value) => (root[key] = value))
}
let ended = false
let lastLevel = 0
while (!ended) {
ended = await doc.next()
if (ended) break;
const level = doc.level()
handlers.length = level + 1
for (const handler of handlers[level] || []) {
handler(doc, handlers)
}
}
console.log(root)
}
main()