Phrogz / NeatJSON

Pretty-print your JSON in Ruby, JS, or Lua with more power than JSON.stringify or JSON.pretty_generate
http://phrogz.net/JS/NeatJSON
MIT License
108 stars 19 forks source link

Could we have more fine control over line breaks #10

Open bwl21 opened 8 years ago

bwl21 commented 8 years ago

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:

Of course there is lots of possible desires:

....

Phrogz commented 8 years ago

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?

bwl21 commented 8 years ago

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" ]
    }
  ]
}
matxx commented 7 years ago

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 !