More complete support for arrays and collections.

This commit is contained in:
Joshua Bemenderfer 2022-11-13 16:12:57 -05:00
parent 787b918b70
commit a6435368aa

View File

@ -16,7 +16,13 @@ root object
title string title string
options options options options
options2 options options2 options
subsection section subsection
type section
collate collection
list array
- string
collection collection
section section
` `
const schema = { const schema = {
@ -39,6 +45,12 @@ const schema = {
parameter1: 'number', parameter1: 'number',
parameter2: 'string' parameter2: 'string'
} }
},
advList: {
type: 'array',
values: {
section: 'section'
}
} }
}, },
root: { root: {
@ -49,6 +61,24 @@ const schema = {
options2: 'options', options2: 'options',
subsection: { subsection: {
type: 'section', type: 'section',
// Allows a particular repeated key to collect itself under a multi-value root as an array.
collate: 'collection'
},
list: {
// Defines an array where all entries must conform to specific types. No other keys are permitted.
// Ex: [ value, value ]
type: 'array',
values: {
'-': 'string'
}
},
collection: {
// Defines an array where all entries must conform to specific types. They will be segregated by key. No other keys are permitted.
// Ex: [ {key: value }, { key: value }]
type: 'collection',
values: {
section: 'section'
}
} }
} }
} }
@ -68,7 +98,16 @@ const lines = [
`subsection 2`, `subsection 2`,
` position 2`, ` position 2`,
` Aute deserunt incididunt ad in sint adipisicing est officia velit pariatur ipsum deserunt quis nulla.`, ` 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.` ` 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`
] ]
@ -79,31 +118,103 @@ const typeHandlers = {
number (doc) { number (doc) {
return +doc.tail().slice(1) return +doc.tail().slice(1)
}, },
object (doc, handlers, definition) { object (doc, handlers, definition, level) {
level = level != null ? level : doc.level() + 1
definition = lookup(definition) definition = lookup(definition)
const object = {} const object = {}
for (let [key, child] of Object.entries(definition.values)) {
for (const [key, child] of Object.entries(definition.values)) { child = lookup(child)
addHandler(handlers, doc.level() + 1, key, child, (key, value) => { addHandler(handlers, level, key, child, (key, value) => {
object[key] = value if (child.collate === 'array') {
if (!object[key]) object[key] = []
object[key].push(value)
return
} else if (child.collate === 'collection') {
if (!object[key]) object[key] = []
object[key].push({ [key]: value })
return
} else {
object[key] = value
}
}) })
} }
if (definition.tail) { if (definition.tail) {
object[definition.tail] = typeHandlers[definition.values[definition.tail]](doc, handlers) const tailKey = definition.tail
const tailType = definition.values[tailKey]
object[tailKey] = typeHandlers[tailType](doc, handlers)
} }
if (definition.text) { if (definition.text) {
const textKey = definition.text const textKey = definition.text
const textType = definition.values[textKey]
object[textKey] = '' object[textKey] = ''
addHandler(handlers, doc.level() + 1, '', definition.values[textKey], (key, value) => { addHandler(handlers, level, '', textType, (key, value) => {
object[textKey] += object[textKey] ? `\n${doc.line()}` : doc.line() object[textKey] += object[textKey] ? `\n${doc.line()}` : doc.line()
}) })
} }
return object return object
} },
array (doc, handlers, definition, level) {
level = level != null ? level : doc.level() + 1
definition = lookup(definition)
const array = []
for (let [key, child] of Object.entries(definition.values)) {
child = lookup(child)
addHandler(handlers, level, key, child, (key, value) => {
array.push(value)
})
}
// if (definition.tail) {
// const tailKey = definition.tail
// const tailType = definition.values[tailKey]
// object[tailKey] = typeHandlers[tailType](doc, handlers)
// }
// if (definition.text) {
// const textKey = definition.text
// const textType = definition.values[textKey]
// object[textKey] = ''
// addHandler(handlers, level, '', textType, (key, value) => {
// object[textKey] += object[textKey] ? `\n${doc.line()}` : doc.line()
// })
// }
return array
},
collection (doc, handlers, definition, level) {
level = level != null ? level : doc.level() + 1
definition = lookup(definition)
const collection = []
for (let [key, child] of Object.entries(definition.values)) {
child = lookup(child)
addHandler(handlers, level, key, child, (key, value) => {
collection.push({ [key]: value })
})
}
// if (definition.tail) {
// const tailKey = definition.tail
// const tailType = definition.values[tailKey]
// object[tailKey] = typeHandlers[tailType](doc, handlers)
// }
// if (definition.text) {
// const textKey = definition.text
// const textType = definition.values[textKey]
// object[textKey] = ''
// addHandler(handlers, level, '', textType, (key, value) => {
// object[textKey] += object[textKey] ? `\n${doc.line()}` : doc.line()
// })
// }
return collection
},
} }
function lookup (definition) { function lookup (definition) {
@ -136,26 +247,22 @@ async function main() {
registerTypes(typeHandlers, schema.types) registerTypes(typeHandlers, schema.types)
const root = {} const root = typeHandlers.object(doc, handlers, schema.root, 0)
for (const [key, child] of Object.entries(schema.root.values)) {
addHandler(handlers, 0, key, child, (k, v) => (root[k] = v))
}
let ended = false let ended = false
let lastLevel = 0
while (!ended) { while (!ended) {
ended = await doc.next() ended = await doc.next()
if (ended) break; if (ended) break;
const level = doc.level() const level = doc.level()
handlers.length = level + 1 handlers.length = level + 1
const unmatchedHandler = handlers[level].find(h => h.key === '') const unmatchedHandler = handlers[level]?.find(h => h.key === '')
let matched = false let matched = false
for (const { key, definition, resolve, handler } of handlers[level] || []) { for (const { key, definition, resolve, handler } of handlers[level] || []) {
if (doc.head() !== key) continue; if (doc.head() !== key) continue;
resolve(doc.head(), handler(doc, handlers, definition)) resolve(doc.head(), handler(doc, handlers, definition))
matched = true matched = true
break
} }
if (!matched && unmatchedHandler) { if (!matched && unmatchedHandler) {
const { resolve, definition, handler } = unmatchedHandler const { resolve, definition, handler } = unmatchedHandler