Skip to content

Instantly share code, notes, and snippets.

@timdp
Created June 29, 2020 13:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timdp/67d39ceed9a4cfb3e55c1fa6b9b0b745 to your computer and use it in GitHub Desktop.
Save timdp/67d39ceed9a4cfb3e55c1fa6b9b0b745 to your computer and use it in GitHub Desktop.
YAMLish
const misleadingStrings = ['', 'true', 'false']
const reWhitespaceStart = /^\s/
const reWhitespaceEnd = /\s$/
const reNumeric = /^\s*(?:[0-9]+|[0-9]*\.[0-9]+)\s*$/
const indent = ' '
const maxStringLength = 60
const keysSorted = true
const byKey = (a, b) => a[0].localeCompare(b[0])
const stringRequiresQuotes = str =>
misleadingStrings.includes(str) ||
reWhitespaceStart.test(str) ||
reWhitespaceEnd.test(str) ||
reNumeric.test(str)
const serializeNullish = () => 'null'
const serializeArray = (array, depth) => {
if (array.length === 0) {
return '[]'
}
const pre = indent.repeat(depth)
return (
(depth > 0 ? '\n' : '') +
array.map(entry => pre + '- ' + serialize(entry, depth + 1)).join('\n')
)
}
const serializeObject = (object, depth) => {
const entries = Object.entries(object)
if (entries.length === 0) {
return '{}'
}
if (keysSorted) {
entries.sort(byKey)
}
const pre = indent.repeat(depth)
return (
(depth > 0 ? '\n' : '') +
entries
.map(([name, value]) => pre + name + ': ' + serialize(value, depth + 1))
.join('\n')
)
}
const indentStrings = (strings, depth) => {
const pre = indent.repeat(depth)
return strings.map(str => pre + str).join('\n')
}
const chunkString = (input, max) => {
const result = []
for (let i = 0; i < input.length; i += max) {
result.push(input.substr(i, max))
}
return result
}
const serializeString = (value, depth) => {
if (value.includes('\n')) {
return '|\n' + indentStrings(value.split('\n'), depth)
}
if (value.length > maxStringLength) {
return '>\n' + indentStrings(chunkString(value, maxStringLength), depth)
}
if (stringRequiresQuotes(value)) {
return JSON.stringify(value)
}
return serializeDefault(value)
}
const serializeDefault = value => String(value)
const strategies = {
null: serializeNullish,
array: serializeArray,
object: serializeObject,
string: serializeString
}
const serialize = (value, depth = 0) => {
const type =
value == null ? 'null' : Array.isArray(value) ? 'array' : typeof value
const strategy = strategies[type] || serializeDefault
return strategy(value, depth)
}
console.log(
serialize({
nullish: null,
alsoNullish: undefined,
string: 'foo bar',
object: {
emptyObject: {},
key: 'value',
array: ['one', 2, 'three', true, ['x', 'y', 'z']],
stringWithWhiteSpace: ' foo bar ',
emptyString: '',
numeric: '1234.56',
numericWithWhitespace: ' 78 '
},
emptyArray: [],
nonEmptyArray: [1, null, 2, undefined, 3],
multiline: '<parent>\n <child/>\n</parent>',
longString: '0123456789abcdefghijklmnopqrstuvwxyz/'.repeat(20)
})
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment