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()