eslint-plugin-jsdoc 48.0.0 → 48.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/WarnSettings.js +34 -0
- package/src/alignTransform.js +356 -0
- package/src/defaultTagOrder.js +168 -0
- package/src/exportParser.js +957 -0
- package/src/getDefaultTagStructureForMode.js +969 -0
- package/src/index.js +266 -0
- package/src/iterateJsdoc.js +2555 -0
- package/src/jsdocUtils.js +1693 -0
- package/src/rules/checkAccess.js +45 -0
- package/src/rules/checkAlignment.js +63 -0
- package/src/rules/checkExamples.js +594 -0
- package/src/rules/checkIndentation.js +75 -0
- package/src/rules/checkLineAlignment.js +364 -0
- package/src/rules/checkParamNames.js +404 -0
- package/src/rules/checkPropertyNames.js +152 -0
- package/src/rules/checkSyntax.js +30 -0
- package/src/rules/checkTagNames.js +314 -0
- package/src/rules/checkTypes.js +535 -0
- package/src/rules/checkValues.js +220 -0
- package/src/rules/emptyTags.js +88 -0
- package/src/rules/implementsOnClasses.js +64 -0
- package/src/rules/importsAsDependencies.js +131 -0
- package/src/rules/informativeDocs.js +182 -0
- package/src/rules/matchDescription.js +286 -0
- package/src/rules/matchName.js +147 -0
- package/src/rules/multilineBlocks.js +333 -0
- package/src/rules/noBadBlocks.js +109 -0
- package/src/rules/noBlankBlockDescriptions.js +69 -0
- package/src/rules/noBlankBlocks.js +53 -0
- package/src/rules/noDefaults.js +85 -0
- package/src/rules/noMissingSyntax.js +195 -0
- package/src/rules/noMultiAsterisks.js +134 -0
- package/src/rules/noRestrictedSyntax.js +91 -0
- package/src/rules/noTypes.js +73 -0
- package/src/rules/noUndefinedTypes.js +328 -0
- package/src/rules/requireAsteriskPrefix.js +189 -0
- package/src/rules/requireDescription.js +161 -0
- package/src/rules/requireDescriptionCompleteSentence.js +333 -0
- package/src/rules/requireExample.js +118 -0
- package/src/rules/requireFileOverview.js +154 -0
- package/src/rules/requireHyphenBeforeParamDescription.js +178 -0
- package/src/rules/requireJsdoc.js +629 -0
- package/src/rules/requireParam.js +592 -0
- package/src/rules/requireParamDescription.js +89 -0
- package/src/rules/requireParamName.js +55 -0
- package/src/rules/requireParamType.js +89 -0
- package/src/rules/requireProperty.js +48 -0
- package/src/rules/requirePropertyDescription.js +25 -0
- package/src/rules/requirePropertyName.js +25 -0
- package/src/rules/requirePropertyType.js +25 -0
- package/src/rules/requireReturns.js +238 -0
- package/src/rules/requireReturnsCheck.js +141 -0
- package/src/rules/requireReturnsDescription.js +59 -0
- package/src/rules/requireReturnsType.js +51 -0
- package/src/rules/requireThrows.js +111 -0
- package/src/rules/requireYields.js +216 -0
- package/src/rules/requireYieldsCheck.js +208 -0
- package/src/rules/sortTags.js +557 -0
- package/src/rules/tagLines.js +359 -0
- package/src/rules/textEscaping.js +146 -0
- package/src/rules/validTypes.js +368 -0
- package/src/tagNames.js +234 -0
- package/src/utils/hasReturnValue.js +549 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import iterateJsdoc from '../iterateJsdoc.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {string} str
|
|
5
|
+
* @param {string[]} excludeTags
|
|
6
|
+
* @returns {string}
|
|
7
|
+
*/
|
|
8
|
+
const maskExcludedContent = (str, excludeTags) => {
|
|
9
|
+
const regContent = new RegExp(`([ \\t]+\\*)[ \\t]@(?:${excludeTags.join('|')})(?=[ \\n])([\\w|\\W]*?\\n)(?=[ \\t]*\\*(?:[ \\t]*@\\w+\\s|\\/))`, 'gu');
|
|
10
|
+
|
|
11
|
+
return str.replace(regContent, (_match, margin, code) => {
|
|
12
|
+
return (margin + '\n').repeat(code.match(/\n/gu).length);
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {string} str
|
|
18
|
+
* @returns {string}
|
|
19
|
+
*/
|
|
20
|
+
const maskCodeBlocks = (str) => {
|
|
21
|
+
const regContent = /([ \t]+\*)[ \t]```[^\n]*?([\w|\W]*?\n)(?=[ \t]*\*(?:[ \t]*(?:```|@\w+\s)|\/))/gu;
|
|
22
|
+
|
|
23
|
+
return str.replaceAll(regContent, (_match, margin, code) => {
|
|
24
|
+
return (margin + '\n').repeat(code.match(/\n/gu).length);
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default iterateJsdoc(({
|
|
29
|
+
sourceCode,
|
|
30
|
+
jsdocNode,
|
|
31
|
+
report,
|
|
32
|
+
context,
|
|
33
|
+
}) => {
|
|
34
|
+
const options = context.options[0] || {};
|
|
35
|
+
const /** @type {{excludeTags: string[]}} */ {
|
|
36
|
+
excludeTags = [
|
|
37
|
+
'example',
|
|
38
|
+
],
|
|
39
|
+
} = options;
|
|
40
|
+
|
|
41
|
+
const reg = /^(?:\/?\**|[ \t]*)\*[ \t]{2}/gmu;
|
|
42
|
+
const textWithoutCodeBlocks = maskCodeBlocks(sourceCode.getText(jsdocNode));
|
|
43
|
+
const text = excludeTags.length ? maskExcludedContent(textWithoutCodeBlocks, excludeTags) : textWithoutCodeBlocks;
|
|
44
|
+
|
|
45
|
+
if (reg.test(text)) {
|
|
46
|
+
const lineBreaks = text.slice(0, reg.lastIndex).match(/\n/gu) || [];
|
|
47
|
+
report('There must be no indentation.', null, {
|
|
48
|
+
line: lineBreaks.length,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}, {
|
|
52
|
+
iterateAllJsdocs: true,
|
|
53
|
+
meta: {
|
|
54
|
+
docs: {
|
|
55
|
+
description: 'Reports invalid padding inside JSDoc blocks.',
|
|
56
|
+
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-indentation.md#repos-sticky-header',
|
|
57
|
+
},
|
|
58
|
+
schema: [
|
|
59
|
+
{
|
|
60
|
+
additionalProperties: false,
|
|
61
|
+
properties: {
|
|
62
|
+
excludeTags: {
|
|
63
|
+
items: {
|
|
64
|
+
pattern: '^\\S+$',
|
|
65
|
+
type: 'string',
|
|
66
|
+
},
|
|
67
|
+
type: 'array',
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
type: 'object',
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
type: 'layout',
|
|
74
|
+
},
|
|
75
|
+
});
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import alignTransform from '../alignTransform.js';
|
|
2
|
+
import iterateJsdoc from '../iterateJsdoc.js';
|
|
3
|
+
import {
|
|
4
|
+
transforms,
|
|
5
|
+
} from 'comment-parser';
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
flow: commentFlow,
|
|
9
|
+
} = transforms;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {{
|
|
13
|
+
* postDelimiter: import('../iterateJsdoc.js').Integer,
|
|
14
|
+
* postHyphen: import('../iterateJsdoc.js').Integer,
|
|
15
|
+
* postName: import('../iterateJsdoc.js').Integer,
|
|
16
|
+
* postTag: import('../iterateJsdoc.js').Integer,
|
|
17
|
+
* postType: import('../iterateJsdoc.js').Integer,
|
|
18
|
+
* }} CustomSpacings
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {import('../iterateJsdoc.js').Utils} utils
|
|
23
|
+
* @param {import('comment-parser').Spec & {
|
|
24
|
+
* line: import('../iterateJsdoc.js').Integer
|
|
25
|
+
* }} tag
|
|
26
|
+
* @param {CustomSpacings} customSpacings
|
|
27
|
+
*/
|
|
28
|
+
const checkNotAlignedPerTag = (utils, tag, customSpacings) => {
|
|
29
|
+
/*
|
|
30
|
+
start +
|
|
31
|
+
delimiter +
|
|
32
|
+
postDelimiter +
|
|
33
|
+
tag +
|
|
34
|
+
postTag +
|
|
35
|
+
type +
|
|
36
|
+
postType +
|
|
37
|
+
name +
|
|
38
|
+
postName +
|
|
39
|
+
description +
|
|
40
|
+
end +
|
|
41
|
+
lineEnd
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @typedef {"tag"|"type"|"name"|"description"} ContentProp
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
/** @type {("postDelimiter"|"postTag"|"postType"|"postName")[]} */
|
|
49
|
+
let spacerProps;
|
|
50
|
+
/** @type {ContentProp[]} */
|
|
51
|
+
let contentProps;
|
|
52
|
+
const mightHaveNamepath = utils.tagMightHaveNamepath(tag.tag);
|
|
53
|
+
if (mightHaveNamepath) {
|
|
54
|
+
spacerProps = [
|
|
55
|
+
'postDelimiter', 'postTag', 'postType', 'postName',
|
|
56
|
+
];
|
|
57
|
+
contentProps = [
|
|
58
|
+
'tag', 'type', 'name', 'description',
|
|
59
|
+
];
|
|
60
|
+
} else {
|
|
61
|
+
spacerProps = [
|
|
62
|
+
'postDelimiter', 'postTag', 'postType',
|
|
63
|
+
];
|
|
64
|
+
contentProps = [
|
|
65
|
+
'tag', 'type', 'description',
|
|
66
|
+
];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const {
|
|
70
|
+
tokens,
|
|
71
|
+
} = tag.source[0];
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @param {import('../iterateJsdoc.js').Integer} idx
|
|
75
|
+
* @param {(notRet: boolean, contentProp: ContentProp) => void} [callbck]
|
|
76
|
+
*/
|
|
77
|
+
const followedBySpace = (idx, callbck) => {
|
|
78
|
+
const nextIndex = idx + 1;
|
|
79
|
+
|
|
80
|
+
return spacerProps.slice(nextIndex).some((spacerProp, innerIdx) => {
|
|
81
|
+
const contentProp = contentProps[nextIndex + innerIdx];
|
|
82
|
+
|
|
83
|
+
const spacePropVal = tokens[spacerProp];
|
|
84
|
+
|
|
85
|
+
const ret = spacePropVal;
|
|
86
|
+
|
|
87
|
+
if (callbck) {
|
|
88
|
+
callbck(!ret, contentProp);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return ret && (callbck || !contentProp);
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const postHyphenSpacing = customSpacings?.postHyphen ?? 1;
|
|
96
|
+
const exactHyphenSpacing = new RegExp(`^\\s*-\\s{${postHyphenSpacing},${postHyphenSpacing}}(?!\\s)`, 'u');
|
|
97
|
+
const hasNoHyphen = !(/^\s*-(?!$)(?=\s)/u).test(tokens.description);
|
|
98
|
+
const hasExactHyphenSpacing = exactHyphenSpacing.test(
|
|
99
|
+
tokens.description,
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
// If checking alignment on multiple lines, need to check other `source`
|
|
103
|
+
// items
|
|
104
|
+
// Go through `post*` spacing properties and exit to indicate problem if
|
|
105
|
+
// extra spacing detected
|
|
106
|
+
const ok = !spacerProps.some((spacerProp, idx) => {
|
|
107
|
+
const contentProp = contentProps[idx];
|
|
108
|
+
const contentPropVal = tokens[contentProp];
|
|
109
|
+
const spacerPropVal = tokens[spacerProp];
|
|
110
|
+
const spacing = customSpacings?.[spacerProp] || 1;
|
|
111
|
+
|
|
112
|
+
// There will be extra alignment if...
|
|
113
|
+
|
|
114
|
+
// 1. The spaces don't match the space it should have (1 or custom spacing) OR
|
|
115
|
+
return spacerPropVal.length !== spacing && spacerPropVal.length !== 0 ||
|
|
116
|
+
|
|
117
|
+
// 2. There is a (single) space, no immediate content, and yet another
|
|
118
|
+
// space is found subsequently (not separated by intervening content)
|
|
119
|
+
spacerPropVal && !contentPropVal && followedBySpace(idx);
|
|
120
|
+
}) && (hasNoHyphen || hasExactHyphenSpacing);
|
|
121
|
+
if (ok) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const fix = () => {
|
|
126
|
+
for (const [
|
|
127
|
+
idx,
|
|
128
|
+
spacerProp,
|
|
129
|
+
] of spacerProps.entries()) {
|
|
130
|
+
const contentProp = contentProps[idx];
|
|
131
|
+
const contentPropVal = tokens[contentProp];
|
|
132
|
+
|
|
133
|
+
if (contentPropVal) {
|
|
134
|
+
const spacing = customSpacings?.[spacerProp] || 1;
|
|
135
|
+
tokens[spacerProp] = ''.padStart(spacing, ' ');
|
|
136
|
+
followedBySpace(idx, (hasSpace, contentPrp) => {
|
|
137
|
+
if (hasSpace) {
|
|
138
|
+
tokens[contentPrp] = '';
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
} else {
|
|
142
|
+
tokens[spacerProp] = '';
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (!hasExactHyphenSpacing) {
|
|
147
|
+
const hyphenSpacing = /^\s*-\s+/u;
|
|
148
|
+
tokens.description = tokens.description.replace(
|
|
149
|
+
hyphenSpacing, '-' + ''.padStart(postHyphenSpacing, ' '),
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
utils.setTag(tag, tokens);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
utils.reportJSDoc('Expected JSDoc block lines to not be aligned.', tag, fix, true);
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* @param {object} cfg
|
|
161
|
+
* @param {CustomSpacings} cfg.customSpacings
|
|
162
|
+
* @param {string} cfg.indent
|
|
163
|
+
* @param {import('comment-parser').Block} cfg.jsdoc
|
|
164
|
+
* @param {import('eslint').Rule.Node & {
|
|
165
|
+
* range: [number, number]
|
|
166
|
+
* }} cfg.jsdocNode
|
|
167
|
+
* @param {boolean} cfg.preserveMainDescriptionPostDelimiter
|
|
168
|
+
* @param {import('../iterateJsdoc.js').Report} cfg.report
|
|
169
|
+
* @param {string[]} cfg.tags
|
|
170
|
+
* @param {import('../iterateJsdoc.js').Utils} cfg.utils
|
|
171
|
+
* @param {string} cfg.wrapIndent
|
|
172
|
+
* @returns {void}
|
|
173
|
+
*/
|
|
174
|
+
const checkAlignment = ({
|
|
175
|
+
customSpacings,
|
|
176
|
+
indent,
|
|
177
|
+
jsdoc,
|
|
178
|
+
jsdocNode,
|
|
179
|
+
preserveMainDescriptionPostDelimiter,
|
|
180
|
+
report,
|
|
181
|
+
tags,
|
|
182
|
+
utils,
|
|
183
|
+
wrapIndent,
|
|
184
|
+
}) => {
|
|
185
|
+
const transform = commentFlow(
|
|
186
|
+
alignTransform({
|
|
187
|
+
customSpacings,
|
|
188
|
+
indent,
|
|
189
|
+
preserveMainDescriptionPostDelimiter,
|
|
190
|
+
tags,
|
|
191
|
+
wrapIndent,
|
|
192
|
+
}),
|
|
193
|
+
);
|
|
194
|
+
const transformedJsdoc = transform(jsdoc);
|
|
195
|
+
|
|
196
|
+
const comment = '/*' +
|
|
197
|
+
/**
|
|
198
|
+
* @type {import('eslint').Rule.Node & {
|
|
199
|
+
* range: [number, number], value: string
|
|
200
|
+
* }}
|
|
201
|
+
*/ (jsdocNode).value + '*/';
|
|
202
|
+
|
|
203
|
+
const formatted = utils.stringify(transformedJsdoc)
|
|
204
|
+
.trimStart();
|
|
205
|
+
|
|
206
|
+
if (comment !== formatted) {
|
|
207
|
+
report(
|
|
208
|
+
'Expected JSDoc block lines to be aligned.',
|
|
209
|
+
/** @type {import('eslint').Rule.ReportFixer} */ (fixer) => {
|
|
210
|
+
return fixer.replaceText(jsdocNode, formatted);
|
|
211
|
+
},
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
export default iterateJsdoc(({
|
|
217
|
+
indent,
|
|
218
|
+
jsdoc,
|
|
219
|
+
jsdocNode,
|
|
220
|
+
report,
|
|
221
|
+
context,
|
|
222
|
+
utils,
|
|
223
|
+
}) => {
|
|
224
|
+
const {
|
|
225
|
+
tags: applicableTags = [
|
|
226
|
+
'param', 'arg', 'argument', 'property', 'prop', 'returns', 'return',
|
|
227
|
+
],
|
|
228
|
+
preserveMainDescriptionPostDelimiter,
|
|
229
|
+
customSpacings,
|
|
230
|
+
wrapIndent = '',
|
|
231
|
+
} = context.options[1] || {};
|
|
232
|
+
|
|
233
|
+
if (context.options[0] === 'always') {
|
|
234
|
+
// Skip if it contains only a single line.
|
|
235
|
+
if (!(
|
|
236
|
+
/**
|
|
237
|
+
* @type {import('eslint').Rule.Node & {
|
|
238
|
+
* range: [number, number], value: string
|
|
239
|
+
* }}
|
|
240
|
+
*/
|
|
241
|
+
(jsdocNode).value.includes('\n')
|
|
242
|
+
)) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
checkAlignment({
|
|
247
|
+
customSpacings,
|
|
248
|
+
indent,
|
|
249
|
+
jsdoc,
|
|
250
|
+
jsdocNode,
|
|
251
|
+
preserveMainDescriptionPostDelimiter,
|
|
252
|
+
report,
|
|
253
|
+
tags: applicableTags,
|
|
254
|
+
utils,
|
|
255
|
+
wrapIndent,
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const foundTags = utils.getPresentTags(applicableTags);
|
|
262
|
+
if (context.options[0] !== 'any') {
|
|
263
|
+
for (const tag of foundTags) {
|
|
264
|
+
checkNotAlignedPerTag(
|
|
265
|
+
utils,
|
|
266
|
+
/**
|
|
267
|
+
* @type {import('comment-parser').Spec & {
|
|
268
|
+
* line: import('../iterateJsdoc.js').Integer
|
|
269
|
+
* }}
|
|
270
|
+
*/
|
|
271
|
+
(tag),
|
|
272
|
+
customSpacings,
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
for (const tag of foundTags) {
|
|
278
|
+
if (tag.source.length > 1) {
|
|
279
|
+
let idx = 0;
|
|
280
|
+
for (const {
|
|
281
|
+
tokens,
|
|
282
|
+
// Avoid the tag line
|
|
283
|
+
} of tag.source.slice(1)) {
|
|
284
|
+
idx++;
|
|
285
|
+
|
|
286
|
+
if (
|
|
287
|
+
!tokens.description ||
|
|
288
|
+
// Avoid first lines after multiline type
|
|
289
|
+
tokens.type ||
|
|
290
|
+
tokens.name
|
|
291
|
+
) {
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Don't include a single separating space/tab
|
|
296
|
+
if (tokens.postDelimiter.slice(1) !== wrapIndent) {
|
|
297
|
+
utils.reportJSDoc('Expected wrap indent', {
|
|
298
|
+
line: tag.source[0].number + idx,
|
|
299
|
+
}, () => {
|
|
300
|
+
tokens.postDelimiter = tokens.postDelimiter.charAt(0) + wrapIndent;
|
|
301
|
+
});
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}, {
|
|
308
|
+
iterateAllJsdocs: true,
|
|
309
|
+
meta: {
|
|
310
|
+
docs: {
|
|
311
|
+
description: 'Reports invalid alignment of JSDoc block lines.',
|
|
312
|
+
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-line-alignment.md#repos-sticky-header',
|
|
313
|
+
},
|
|
314
|
+
fixable: 'whitespace',
|
|
315
|
+
schema: [
|
|
316
|
+
{
|
|
317
|
+
enum: [
|
|
318
|
+
'always', 'never', 'any',
|
|
319
|
+
],
|
|
320
|
+
type: 'string',
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
additionalProperties: false,
|
|
324
|
+
properties: {
|
|
325
|
+
customSpacings: {
|
|
326
|
+
additionalProperties: false,
|
|
327
|
+
properties: {
|
|
328
|
+
postDelimiter: {
|
|
329
|
+
type: 'integer',
|
|
330
|
+
},
|
|
331
|
+
postHyphen: {
|
|
332
|
+
type: 'integer',
|
|
333
|
+
},
|
|
334
|
+
postName: {
|
|
335
|
+
type: 'integer',
|
|
336
|
+
},
|
|
337
|
+
postTag: {
|
|
338
|
+
type: 'integer',
|
|
339
|
+
},
|
|
340
|
+
postType: {
|
|
341
|
+
type: 'integer',
|
|
342
|
+
},
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
preserveMainDescriptionPostDelimiter: {
|
|
346
|
+
default: false,
|
|
347
|
+
type: 'boolean',
|
|
348
|
+
},
|
|
349
|
+
tags: {
|
|
350
|
+
items: {
|
|
351
|
+
type: 'string',
|
|
352
|
+
},
|
|
353
|
+
type: 'array',
|
|
354
|
+
},
|
|
355
|
+
wrapIndent: {
|
|
356
|
+
type: 'string',
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
type: 'object',
|
|
360
|
+
},
|
|
361
|
+
],
|
|
362
|
+
type: 'layout',
|
|
363
|
+
},
|
|
364
|
+
});
|