Open mswolfe opened 6 years ago
Update:
From what I can tell there are no styles available for sequences because they would be specified in the type definition here (https://github.com/nodeca/js-yaml/blob/master/lib/js-yaml/type/seq.js) similar to how the styles for the int type are specified here: https://github.com/nodeca/js-yaml/blob/master/lib/js-yaml/type/int.js#L160-L164
I have gotten it to work by adding a new state variable to force sequences into flow mode. You can see the code here: https://github.com/mswolfe/js-yaml/pull/1
Please let me know if this feature is something that belongs here or if there is a different way to achieve the results. I'm happy to work on this code and submit an official PR to get this change merged in.
Thanks!
I'd like this as well. I'm dumping 3d graphics state and having every matrix and vector come out one element per line is super verbose looking. I'd much prefer them in flow style, but they're not always at the same level so I'd need something like @mswolfe 's solution. Specifically in my case I'd like all sequences that don't contain objects (i.e. just strings & numbers) to be in flow style.
@garyo
Maybe like this? https://github.com/nodeca/js-yaml/blob/3db03f295865cf58ec9f4257894b55a6ad52e9ed/lib/js-yaml/dumper.js#L739
let anyObject = false
for(let i of state.dump) {
if(_toString.call(i) === '[object Object]') {
anyObject = true
break
}
}
if (block && (state.dump.length !== 0) && anyObject) {
EDIT: This creates an issue in cases with STYLE_FOLDED example: https://codepen.io/alexholly/pen/jONLzLj?editors=1010
I'd really appreciate this as well.
@AlexHolly yes that looks exactly like what I'd like. I don't use folded style but if there's an update to your patch that doesn't have that issue, perhaps that could be included in js-yaml?
I'm dumping 3d graphics state and having every matrix and vector come out one element per line is super verbose looking.
You can use this hack at your own risk:
const yaml = require('js-yaml');
function Format(data) {
if (!(this instanceof Format)) return new Format(data);
this.data = data;
}
let CustomFormatType = new yaml.Type('!format', {
kind: 'scalar',
resolve: () => false,
instanceOf: Format,
represent: f => f.data
});
let schema = yaml.DEFAULT_SCHEMA.extend({ implicit: [ CustomFormatType ] });
function replacer(key, value) {
if (Array.isArray(value) && !value.filter(x => typeof x !== 'number').length) {
return Format(yaml.dump(value, { flowLevel: 0 }).trim());
}
return value;
}
console.log(yaml.dump({
matrix: [
[ 4, -7, 5, 0 ],
[ -2, 0, 11, 8 ],
[ 19, 1, -3, 12 ]
]
}, { schema, replacer }));
/* outputs:
matrix:
- [4, -7, 5, 0]
- [-2, 0, 11, 8]
- [19, 1, -3, 12]
*/
Another approach could be to have something like JSON.rawJSON()
, e.g., yaml.rawYAML()
, which unlike JSON.rawJSON()
accepts any valid YAML string.
function replacer(_, value) {
if (Array.isArray(value) && value.every(v => typeof v === 'number')) {
return yaml.rawYAML(yaml.dump(value, { flowLevel: 0 }).trim())
}
return value
}
console.log(yaml.dump({
matrix: [
[ 4, -7, 5, 0 ],
[ -2, 0, 11, 8 ],
[ 19, 1, -3, 12 ]
]
}, { replacer }))
You can use this hack at your own risk:
const yaml = require('js-yaml'); function Format(data) { if (!(this instanceof Format)) return new Format(data); this.data = data; } let CustomFormatType = new yaml.Type('!format', { kind: 'scalar', resolve: () => false, instanceOf: Format, represent: f => f.data }); let schema = yaml.DEFAULT_SCHEMA.extend({ implicit: [ CustomFormatType ] }); function replacer(key, value) { if (Array.isArray(value) && !value.filter(x => typeof x !== 'number').length) { return Format(yaml.dump(value, { flowLevel: 0 }).trim()); } return value; } console.log(yaml.dump({ matrix: [ [ 4, -7, 5, 0 ], [ -2, 0, 11, 8 ], [ 19, 1, -3, 12 ] ] }, { schema, replacer })); /* outputs: matrix: - [4, -7, 5, 0] - [-2, 0, 11, 8] - [19, 1, -3, 12] */
Alternate suggestion:
import yaml from 'js-yaml'
let NumberArrayFormatType = new yaml.Type('!numberArray', {
kind: 'sequence',
resolve: () => false,
instanceOf: Array,
predicate: (obj) => obj.every((v) => typeof v === 'number'),
represent: (obj) => yaml.dump(obj, { flowLevel: 0 }).trim(),
})
let schema = yaml.DEFAULT_SCHEMA.extend({ implicit: [NumberArrayFormatType] })
console.log(yaml.dump({
matrix: [
[ 4, -7, 5, 0 ],
[ -2, 0, 11, 8 ],
[ 19, 1, -3, 12 ]
]
}, { schema }));
I have an object that I need to dump to YAML which contains many nested objects (5+ levels deep). I do not want to specify the flowLevel because I would like everything but the YAML sequences (JS array's) to be written in block form.
I have tried setting the style option for the '!!seq' tag, but i don't see any difference in the output. For example:
const yamlExportedString = yaml.dump(objectToWrite, { lineWidth: 999999, sortKeys: true, styles: { '!!seq': 'flow' }});
Am I setting this correctly? Is block versus flow formatting only based on the flowLevel option?
Thank you in advance for your help!