NeatJSON
NeatJSON copied to clipboard
Could we have more fine control over line breaks
The approach to determine the line breaks by wrapping works in many - but not in all cases.
Would it be possible to provide a list of keys and applicable policies, for example
{
"wrap" : 40,
"policies" : [
{
"keys" : ["policies", "keys", "display"],
"display" : "block"
},
{
"contentOf" : ["keys"],
"display" : "inline"
}
]
}
This specifies:
- policies, keys, display start on a new line and are formatted as an indented block
- content of keys; is never wrapped
Of course there is lots of possible desires:
- consider object in content
- inlineWrap which would add linebreak not on every element but only if the line is full
....
I would be happy to consider a pull request with this feature. I do not understand your example, however. Before you spend time working on a syntax that I might ask you to change the wording of, I'd suggest discussing here more clearly how this works. Are the only options "block"
and "inline"
? If so, I might suggest either:
{
policies : {
inline: ["keys"],
block: ["policies", "display"]
}
}
or
{
contentDisplay : {
policies : "block",
display : "block",
keys : "inline"
}
}
Perhaps the best way to work on this feature would be for you to include here a set of unit tests, showing some sample data, formatting options, and the result you expect. I can see that you are trying to provide different wrapping behavior for "keys" versus "content", but I'm not sure what that really means.
Consider: Does this work with the short
option, or not? What happens when the content has no whitespace? What about a single long string?
This topic tends to get complicated. And a full solution would end up in some css selects and the values of the display property (which is none | block | inline).
So, i will go back to the use case: If I look at a JSON like this, you see that "extract/0" is formatted inline while extract/1 is formatted as block.
{
"produce" : [0, 1, 2],
"extract" : {
"0" : {"legend": {"pos": [10, 10], "spos": [10, 17]}},
"1" : {
"legend" : {"pos": [361, 58], "spos": [360, 27]},
"lyrics" : {"x": {"verses": [1], "pos": [350, 70]}}
}
}
}
If I could state:
{
"policies" : {
"block" : [ "0", "1", "2", "3" ],
"inline" : [ "lyrics", "legend" ]
}
}
It would yield:
{
"produce" : [0, 1, 2],
"extract" : {
"0" : {
"legend": {"pos": [10, 10], "spos": [10, 17]}
},
"1" : {
"legend" : {"pos": [361, 58], "spos": [360, 27]},
"lyrics" : {"x": {"verses": [1], "pos": [350, 70]}}
}
}
}
Maybe we can achieve the same by
{
"wrap" : [
{"col" : 100, "elements" : [ "legend", "lyrics" ]},
{
"col" : 10,
"elements" : [ "0", "1", "2", "3", "4" ]
}
]
}
Couldn't it be something like in the native JSON.pretty_generate :
You can override options per object.
class ArrayWithoutIndent < Array
def to_json(state = nil, *)
super(state.to_h.merge({ array_nl: ' ', indent: '' }))
end
end
You could test if obj.respond_to?(:neat_options)
for example and override global options with the object options
I would love this feature !