• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

drom / jsof / 29461752646

16 Jul 2026 12:32AM UTC coverage: 93.026% (+10.9%) from 82.09%
29461752646

push

github

drom
modernization

289 of 323 branches covered (89.47%)

517 of 542 new or added lines in 6 files covered. (95.39%)

10 existing lines in 2 files now uncovered.

707 of 760 relevant lines covered (93.03%)

263.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.24
/lib/stringify.js
1
'use strict';
9✔
2

9✔
3
const tag = {
9✔
4
  key: ' [36m',
9✔
5
  boolean: ' [33m',
9✔
6
  number: ' [35m',
9✔
7
  string: ' [32m',
9✔
8
  function: ' [33m',
9✔
9
  reset: ' [0m'
9✔
10
};
9✔
11

9✔
12
const ess = /["'`\n\r]/g;
9✔
13

9✔
14
const eso = {
9✔
15
  '"': '\\"',
9✔
16
  '\n': '\\n',
9✔
17
  '\r': '\\r',
9✔
18
  '\'': '\\\'',
9✔
19
  '`': '\\`'
9✔
20
};
9✔
21

9✔
22
function esf(chr) { return eso[chr]; }
×
23

9✔
24
function escape(str) { return str.replace(ess, esf); }
18✔
25

9✔
26
function quote(str, options) {
15✔
27
  const q = options?.legacy ? '"' : '\'';
15✔
28
  return q + escape(str) + q;
15✔
29
}
15✔
30

9✔
31
function stylize (text, type, options) {
108✔
32
  if (options?.ansi) {
108✔
33
    return tag[type] + text + tag.reset;
3✔
34
  }
3✔
35
  return text;
105✔
36
}
108✔
37

9✔
38
// indentation unit: number -> that many spaces, string -> itself, default 2 spaces
9✔
39
function unit (options) {
18✔
40
  const i = options?.indent;
18✔
41
  if (typeof i === 'number') { return ' '.repeat(i); }
18✔
42
  if (typeof i === 'string') { return i; }
18!
43
  return '  ';
15✔
44
}
18✔
45

9✔
46
function indent (txt, options) {
18✔
47
  const pad = unit(options);
18✔
48
  const arr = txt.split('\n');
18✔
49

18✔
50
  if (arr.length === 1) {
18!
NEW
51
    return pad + txt;
×
UNCOV
52
  }
×
53

18✔
54
  const res = arr.map(function (e) {
18✔
55
    if (e === '') {
42!
56
      return e;
×
UNCOV
57
    }
×
58
    return pad + e;
42✔
59
  });
18✔
60
  return res.join('\n');
18✔
61
}
18✔
62

9✔
63
function formKey (txt, options) {
36✔
64
  let res;
36✔
65
  if (options?.legacy) {
36✔
66
    res = '"' + escape(txt) + '"';
3✔
67
  } else if (txt.match('^[0-9a-zA-Z_]+$')) {
36✔
68
    res = txt;
30✔
69
  } else {
33✔
70
    res = '\'' + txt + '\'';
3✔
71
  }
3✔
72
  return stylize(res, 'key', options);
36✔
73
}
36✔
74

9✔
75
function uniformArray (value, options) {
3✔
76
  if (value.length === 0) {
3!
77
    return '[]';
×
UNCOV
78
  }
×
79
  const el0 = value[0];
3✔
80
  if (typeof el0 === 'object') { // only for scalar values
3!
81
    return null;
×
UNCOV
82
  }
×
83
  for (const el of value) { // only for values of the same type
3✔
84
    if (typeof el !== typeof el0) {
9✔
85
      return null;
3✔
86
    }
3✔
87
  }
9!
88
  const body = [];
×
89
  if (typeof el0 === 'string') {
×
90
    for (const el of value) {
×
91
      body.push(stylize('"' + escape(el) + '"', 'string', options));
×
UNCOV
92
    }
×
93
  } else if (typeof el0 === 'number') {
×
94
    for (const el of value) {
×
95
      body.push(stylize(el.toString(), 'number', options));
×
UNCOV
96
    }
×
97
  } else if (typeof el0 === 'boolean') {
×
98
    for (const el of value) {
×
99
      body.push(stylize(el.toString(), 'boolean', options));
×
UNCOV
100
    }
×
UNCOV
101
  } else {
×
102
    return null;
×
UNCOV
103
  }
×
104
  return '[' + body.join(', ') + ']';
×
105
}
3✔
106

9✔
107
function formObject (value, options) {
18✔
108
  let keys = Object.keys(value);
18✔
109
  if (Array.isArray(options?.replacer)) {
18✔
110
    const allow = options.replacer.map(String);
3✔
111
    keys = keys.filter(function (k) { return allow.includes(k); });
3✔
112
  }
3✔
113
  if (options?.sortKeys) {
18✔
114
    keys = keys.slice().sort();
3✔
115
  }
3✔
116
  const res = keys.map(function (key) {
18✔
117
    let v = value[key];
36✔
118
    if (typeof options?.replacer === 'function') {
36✔
119
      v = options.replacer.call(value, key, v);
6✔
120
    }
6✔
121
    return formKey(key, options) + ': ' + rec(v, options);
36✔
122
  });
18✔
123
  if (res.length < 2) {
18✔
124
    return '{' + res.join(',\n') + '}';
3✔
125
  }
3✔
126
  return '{\n' + indent(res.join(',\n'), options) + '\n}';
15✔
127
}
18✔
128

9✔
129
function formArray (value, options) {
3✔
130
  const uniform = uniformArray(value, options);
3✔
131
  if (uniform) { return uniform; }
3!
132

3✔
133
  const res = value.map(function (e) {
3✔
134
    return rec(e, options);
9✔
135
  });
3✔
136
  if (res.length < 2) {
3!
NEW
137
    return '[' + res.join(', ') + ']';
×
NEW
138
  }
×
139
  return '[\n' + indent(res.join(',\n'), options) + '\n]';
3✔
140
}
3✔
141

9✔
142
function rec (value, options) {
102✔
143
  if (value === undefined) return 'undefined';
102✔
144
  if (value === null) return 'null';
102✔
145
  if (value === true) return stylize('true', 'boolean', options);
102✔
146
  if (value === false) return stylize('false', 'boolean', options);
102✔
147

87✔
148
  const type = Object.prototype.toString.call(value);
87✔
149

87✔
150
  if (Array.isArray(value)) {
102✔
151
    return formArray(value, options);
3✔
152
  }
3✔
153

84✔
154
  switch (typeof value) {
84✔
155
  case 'boolean':
102!
156
    return stylize(value, 'boolean', options);
×
157

102✔
158
  case 'number':
102✔
159
    return stylize(value.toString(), 'number', options);
42✔
160

102✔
161
  case 'string':
102✔
162
    return stylize(quote(value, options), 'string', options);
12✔
163

102✔
164
  case 'bigint':
102✔
165
    // 42n round-trips through parse; legacy JSON has no BigInt -> bare integer
9✔
166
    return stylize(value.toString() + (options?.legacy ? '' : 'n'), 'number', options);
9✔
167

102✔
168
  case 'function':
102✔
169
    return stylize(quote(value.toString(), options), 'function', options);
3✔
170

102✔
171
  case 'object':
102✔
172
    return formObject(value, options);
18✔
173

102✔
174
  default:
102!
175
    return type;
×
176
  }
102✔
177
}
102✔
178

9✔
179
module.exports = rec;
9✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc