Skip to content

Commit 50340cf

Browse files
committed
Add JSDoc based types
1 parent 4b8da28 commit 50340cf

File tree

5 files changed

+105
-95
lines changed

5 files changed

+105
-95
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
.DS_Store
2+
*.d.ts
23
*.log
34
coverage/
45
node_modules/

index.js

Lines changed: 62 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,67 @@
11
var own = {}.hasOwnProperty
22

3-
// Transform a string into an array or object of values.
4-
export function toJson(value, options) {
3+
/**
4+
* @typedef {Object} ToJsonOptions
5+
* @property {boolean} [log=true]
6+
* @property {string} [delimiter=':']
7+
* @property {string[]|string|false} [comment='%']
8+
* @property {boolean|'fix'} [forgiving]
9+
*/
10+
11+
/**
12+
* Transform a string into an array or object of values.
13+
*
14+
* @param {string} value
15+
* @param {ToJsonOptions} [options={}]
16+
*/
17+
export function toJson(value, options = {}) {
18+
var log =
19+
options.log === null || options.log === undefined ? true : options.log
20+
var comment =
21+
options.comment === null || options.comment === undefined
22+
? '%'
23+
: options.comment
24+
var comments = comment ? (Array.isArray(comment) ? comment : [comment]) : []
25+
var delimiter = options.delimiter || ':'
26+
var forgiving = options.forgiving
527
var propertyOrValues = {}
6-
var lines
28+
/** @type {boolean} */
729
var isPropertyValuePair
30+
/** @type {Array.<Array.<string>>} */
831
var pairs
9-
var values
10-
var comments
1132

12-
if (!options) {
13-
options = {}
14-
}
15-
16-
if (options.log === null || options.log === undefined) {
17-
options.log = true
18-
}
19-
20-
if (options.comment === null || options.comment === undefined) {
21-
options.comment = '%'
22-
}
33+
var lines = value
34+
.split('\n')
35+
.map((line) => {
36+
var commentIndex = -1
37+
/** @type {number} */
38+
var index
2339

24-
lines = value.split('\n')
40+
while (++commentIndex < comments.length) {
41+
index = line.indexOf(comments[commentIndex])
42+
if (index !== -1) line = line.slice(0, index)
43+
}
2544

26-
comments = options.comment
27-
? Array.isArray(options.comment)
28-
? options.comment
29-
: [options.comment]
30-
: []
45+
return line.trim()
46+
})
47+
.filter(Boolean)
3148

32-
comments.forEach(function (comment) {
33-
lines = lines.map(stripComments(comment))
34-
})
49+
pairs = lines.map(
50+
// Transform `value` to a property--value tuple.
51+
function (value) {
52+
var values = value.split(delimiter)
53+
var result = [values.shift().trim()]
3554

36-
lines = lines.map((d) => d.trim()).filter(Boolean)
55+
if (values.length > 0) {
56+
result.push(values.join(delimiter).trim())
57+
}
3758

38-
pairs = lines.map(toPropertyValuePairs(options.delimiter || ':'))
59+
return result
60+
}
61+
)
3962

4063
pairs.forEach(function (line, index) {
41-
var currentLineIsPropertyValuePair
42-
43-
currentLineIsPropertyValuePair = line.length === 2
64+
var currentLineIsPropertyValuePair = line.length === 2
4465

4566
if (index === 0) {
4667
isPropertyValuePair = currentLineIsPropertyValuePair
@@ -56,8 +77,8 @@ export function toJson(value, options) {
5677

5778
if (own.call(propertyOrValues, line[0])) {
5879
if (
59-
!options.forgiving ||
60-
(options.forgiving === true &&
80+
!forgiving ||
81+
(forgiving === true &&
6182
currentLineIsPropertyValuePair &&
6283
line[1] !== propertyOrValues[line[0]])
6384
) {
@@ -71,11 +92,8 @@ export function toJson(value, options) {
7192
)
7293
}
7394

74-
if (options.log) {
75-
if (
76-
options.forgiving === 'fix' &&
77-
propertyOrValues[line[0]] !== line[1]
78-
) {
95+
if (log) {
96+
if (forgiving === 'fix' && propertyOrValues[line[0]] !== line[1]) {
7997
console.log(
8098
'Overwriting `' +
8199
propertyOrValues[line[0]] +
@@ -97,59 +115,17 @@ export function toJson(value, options) {
97115

98116
if (isPropertyValuePair) {
99117
pairs.sort(sortOnFirstIndex)
100-
values = propertyValuePairsToObject(pairs)
101-
} else {
102-
lines.sort()
118+
return Object.fromEntries(pairs)
103119
}
104120

105-
return values || lines
106-
}
107-
108-
// Transform a list of property--value tuples to an object.
109-
function propertyValuePairsToObject(pairs) {
110-
var values = {}
111-
112-
pairs.forEach(function (pair) {
113-
values[pair[0]] = pair[1]
114-
})
115-
116-
return values
121+
return lines.sort()
117122
}
118123

119-
// Sort on the first (`0`) index.
124+
/**
125+
* Sort on the first (`0`) index.
126+
* @param {Array.<string>} a
127+
* @param {Array.<string>} b
128+
*/
120129
function sortOnFirstIndex(a, b) {
121130
return a[0].charCodeAt(0) - b[0].charCodeAt(0)
122131
}
123-
124-
// Factory to transform lines to property--value tuples.
125-
function toPropertyValuePairs(token) {
126-
return toPropValuePairs
127-
128-
// Transform `value` to a property--value tuple.
129-
function toPropValuePairs(value) {
130-
var values = value.split(token)
131-
var result = [values.shift().trim()]
132-
133-
if (values.length > 0) {
134-
result.push(values.join(token).trim())
135-
}
136-
137-
return result
138-
}
139-
}
140-
141-
// Strip comments factory.
142-
function stripComments(token) {
143-
return strip
144-
145-
// Strip comments.
146-
function strip(value) {
147-
var index = value.indexOf(token)
148-
149-
if (index !== -1) {
150-
value = value.slice(0, index)
151-
}
152-
153-
return value
154-
}
155-
}

package.json

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,31 @@
2121
"sideEffects": false,
2222
"type": "module",
2323
"main": "index.js",
24+
"types": "index.d.ts",
2425
"files": [
26+
"index.d.ts",
2527
"index.js"
2628
],
2729
"devDependencies": {
30+
"@types/tape": "^4.0.0",
2831
"c8": "^7.0.0",
2932
"cept": "^2.0.0",
3033
"prettier": "^2.0.0",
3134
"remark-cli": "^9.0.0",
3235
"remark-preset-wooorm": "^8.0.0",
36+
"rimraf": "^3.0.0",
3337
"tape": "^5.0.0",
38+
"type-coverage": "^2.0.0",
39+
"typescript": "^4.0.0",
3440
"xo": "^0.38.0"
3541
},
3642
"scripts": {
43+
"prepack": "npm run build && npm run format",
44+
"build": "rimraf \"*.d.ts\" && tsc && type-coverage",
3745
"format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix",
3846
"test-api": "node test.js",
3947
"test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov node test.js",
40-
"test": "npm run format && npm run test-coverage"
48+
"test": "npm run build && npm run format && npm run test-coverage"
4149
},
4250
"prettier": {
4351
"tabWidth": 2,
@@ -61,5 +69,10 @@
6169
"plugins": [
6270
"preset-wooorm"
6371
]
72+
},
73+
"typeCoverage": {
74+
"atLeast": 100,
75+
"detail": true,
76+
"strict": true
6477
}
6578
}

test.js

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@ test('Invalid lists', function (t) {
156156

157157
t.test('should log duplicate values when `forgiving`', function (st) {
158158
var stop = cept(console, 'log', hoist)
159-
var parameters
159+
/** @type {Array.<unknown>} */
160+
var parameters = []
160161

161162
toJson('unicorn\nrainbow\nunicorn', {forgiving: true})
162163

@@ -166,12 +167,13 @@ test('Invalid lists', function (t) {
166167
st.end()
167168

168169
function hoist() {
169-
parameters = arguments
170+
parameters = [...arguments]
170171
}
171172
})
172173

173174
t.test('should honour `log: false`', function (st) {
174175
var stop = cept(console, 'log', hoist)
176+
/** @type {Array.<unknown>} */
175177
var parameters
176178

177179
toJson('unicorn\nrainbow\nunicorn', {forgiving: true, log: false})
@@ -182,7 +184,7 @@ test('Invalid lists', function (t) {
182184
st.end()
183185

184186
function hoist() {
185-
parameters = arguments
187+
parameters = [...arguments]
186188
}
187189
})
188190

@@ -208,7 +210,8 @@ test('Invalid objects', function (t) {
208210

209211
t.test('should log duplicate values when `forgiving`', function (st) {
210212
var stop = cept(console, 'log', hoist)
211-
var parameters
213+
/** @type {Array.<unknown>} */
214+
var parameters = []
212215

213216
toJson('doge: so scare\nunicorn: magic creature\ndoge: so scare\n', {
214217
forgiving: true
@@ -220,12 +223,13 @@ test('Invalid objects', function (t) {
220223
st.end()
221224

222225
function hoist() {
223-
parameters = arguments
226+
parameters = [...arguments]
224227
}
225228
})
226229

227230
t.test('should honour `log: false`', function (st) {
228231
var stop = cept(console, 'log', hoist)
232+
/** @type {Array.<unknown>} */
229233
var parameters
230234

231235
toJson('doge: so scare\nunicorn: magic creature\ndoge: so scare\n', {
@@ -239,7 +243,7 @@ test('Invalid objects', function (t) {
239243
st.end()
240244

241245
function hoist() {
242-
parameters = arguments
246+
parameters = [...arguments]
243247
}
244248
})
245249

@@ -263,7 +267,8 @@ test('Invalid objects', function (t) {
263267
'should log for duplicate keys when `forgiving` is `"fix"',
264268
function (st) {
265269
var stop = cept(console, 'log', hoist)
266-
var parameters
270+
/** @type {Array.<unknown>} */
271+
var parameters = []
267272

268273
toJson('doge: so scare\nunicorn: magic creature\ndoge: so scare\n', {
269274
forgiving: true
@@ -275,7 +280,7 @@ test('Invalid objects', function (t) {
275280
st.end()
276281

277282
function hoist() {
278-
parameters = arguments
283+
parameters = [...arguments]
279284
}
280285
}
281286
)

tsconfig.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"include": ["*.js"],
3+
"compilerOptions": {
4+
"target": "ES2020",
5+
"lib": ["ES2020"],
6+
"module": "ES2020",
7+
"moduleResolution": "node",
8+
"allowJs": true,
9+
"checkJs": true,
10+
"declaration": true,
11+
"emitDeclarationOnly": true,
12+
"allowSyntheticDefaultImports": true,
13+
"skipLibCheck": true
14+
}
15+
}

0 commit comments

Comments
 (0)