TMI below, sorry. This is a fun puzzle (for my simple mind at least) and a worthwhile question. There’s a few things upfront that could be hindering your approach: (1) the elements of lists are item
s (accessed with list.item
), so if you want just one list, that will be the way to go. (2) Making a single list with indentations requires nesting of item
s, and doing so will take care of indentation automatically.
One issue that I didn’t see coming when thinking about this comes from the structure of list
s in Typst. For example, this code…
#repr[
- First point
- Second point
- First subpoint
]
… shows the underlying structure of lists:
sequence(
[ ],
item(body: [First point]),
[ ],
item(body: sequence(
[Second point],
[ ],
item(body: [First subpoint])
),),
[ ],
)
As seen here, when a list item is followed by an increase in indentation (aka a sublist), its item
object is the parent to the sublist as well (see [Second point]
). Therefore, in order to code this correctly, one needs to check if the item in the json
data structure is followed by an array. This means that simple element-wise iteration with a recursive function is not an option here.
To work around this, you might be interested in using only objects, not arrays, in your json
file, like this:
{
"information": {
"First point": null,
"Second point": {"First subpoint": null},
"Third point": {"Second subpoint": {"First subsubpoint": null}}
}
… then pure recursion could be used. But this format is somewhat ugly and tedius, with the null
s required when there are no children. So, I came up with the approach below to work with your original json file instead, which starts by converting the data to a dictionary, and then using recursion.
#let data = json("file.json").at("information")
#let array_to_dict(data) = {
let dict = (:)
let final_indx = data.len() - 1
for (indx, item) in data.enumerate() {
if type(item) == array {continue}
if indx == final_indx or type(data.at(indx + 1)) != array {
dict.insert(item, none)
} else {
dict.insert(item, array_to_dict(data.at(indx + 1)))
}
}
return dict
}
#let list_recursive(dict_data) = {
for (key, val) in dict_data.pairs() {
if val == none {
list.item(key)
} else {
list.item[#key #list_recursive(val)]
}
}
}
#let data_to_list(array_data) = {
let dict_data = array_to_dict(array_data)
list_recursive(dict_data)
}
= Original array data
#data
= Original array data to dict data
#array_to_dict(data)
= Original array data to list
#data_to_list(data)