Skip to content

Instantly share code, notes, and snippets.

@westc
Last active February 12, 2022 18:59
Show Gist options
  • Save westc/ff0ef084a92bd9b1aea8072c90916501 to your computer and use it in GitHub Desktop.
Save westc/ff0ef084a92bd9b1aea8072c90916501 to your computer and use it in GitHub Desktop.
yamlize() - A simple way to turn JSON objects into YAML strings.
function yamlize(value, spaces) {
function recurseYamlize(value, level) {
if (value == null) {
return 'null';
}
var indentation = spacing.repeat(level);
const typeName = Object.prototype.toString.call(value).slice(8, -1);
if (typeName === 'Array') {
return value.length
? value.map(v => {
return '\n' + indentation + '- ' + recurseYamlize(v, level + 1);
}).join('')
: '[]';
}
else if (typeName === 'Number' || typeName === 'Boolean') {
return `${value}`;
}
else if (typeName === 'String') {
// If starts with punctuation or whitespace or ends with ":" or "-" or is
// the empty string or is surrounded by single or double quotes or ends
// with a hyphen or a colon or contains a # or a tab or a non-printable
// character or is one of the following: true, false, null, or a number.
if (/^[~`!@#$%^&*()\-+={}\[\]\|\\;:<>?,.\/]|^(?:"[^]*"|'[^]*'|true|false|null|\d+(?:\.\d+)?|)$|[\-:]$|[#\t\u0000-\u0008\u000B-\u001F\u007F-\u009F\u2000-\u200F\u2028-\u202F\u205F-\u206F\u3000\uFEFF]/i.test(value)) {
return JSON.stringify(value);
}
// If no leading or trailing spaces and no line breaks.
if (!/^ |\n| $/.test(value)) {
return value;
}
return '|'
+ (/^\n* +/.test(value) ? spaces : '')
+ (value.endsWith('\n\n') ? '+' : value.endsWith('\n') ? '' : '-')
+ '\n'
+ value.replace(/^(?!$)/gm, indentation + (level === 0 ? spacing : '')).replace(/\n$/, '');
}
else if (typeName === 'Date') {
return value.toJSON();
}
value = Object(value);
const keys = Object.keys(value);
if (!keys.length) {
return '{}';
}
return keys.map(k => {
const v = value[k];
// If starts with punctuation or whitespace or ends with ":" or "-" or is
// the empty string or is surrounded by single or double quotes or ends
// with a hyphen or a colon or contains a # or a tab or a newline
// character or a non-printable character or is one of the following:
// true, false, null, or a number.
if (/^[~`!@#$%^&*()\-+={}\[\]\|\\;:<>?,.\/\s]|^(?:"[^]*"|'[^]*'|true|false|null|\d+(?:\.\d+)?|)$|[\-:\s]$|[#\t\n\u0000-\u0008\u000B-\u001F\u007F-\u009F\u2000-\u200F\u2028-\u202F\u205F-\u206F\u3000\uFEFF]/i.test(k)) {
k = JSON.stringify(k);
}
return '\n' + indentation + k + ': ' + recurseYamlize(v, level + 1);
}).join('');
}
const spacing = ' '.repeat(spaces = spaces || 2);
return recurseYamlize(value, 0).trimLeft();
}
function runIOApp(input, spaces) {
return yamlize(JSON.parse(input), +spaces || 2);
}
{
// Where the JS code lies
"files": ["yamlize.js", "~io-app.js"],
// Name of the function responsable for transforming the input into the output.
"transform": "runIOApp",
// Arguments that will be passed to the function by name.
"params": [
{
"name": "spaces",
"label": "Number of spaces to indent with:",
"type": "number",
"min": 1,
"max": 8,
"step": 1,
"value": 2
}
],
// Input setup
"input": { "language": "json" },
// Output setup
"output": { "language": "yaml" },
// Type of YourJS IO-App
"type": "split"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment