diff --git a/.README/rules/check-line-alignment.md b/.README/rules/check-line-alignment.md
index 6757f2a36..dd87be7bc 100644
--- a/.README/rules/check-line-alignment.md
+++ b/.README/rules/check-line-alignment.md
@@ -9,17 +9,16 @@ for example.
This rule allows one optional string argument. If it is `"always"` then a
problem is raised when the lines are not aligned. If it is `"never"` then
a problem should be raised when there is more than one space between each
-line's parts. Defaults to `"never"`.
+line's parts. If it is `"any"`, no alignment is made. Defaults to `"never"`.
-Note that in addition to alignment, both options will ensure at least one
-space is present after the asterisk delimiter.
+Note that in addition to alignment, the "never" and "always" options will both
+ensure that at least one space is present after the asterisk delimiter.
After the string, an options object is allowed with the following properties.
##### `tags`
-Use this to change the tags which are sought for alignment changes. *Currently*
-*only works with the "never" option.* Defaults to an array of
+Use this to change the tags which are sought for alignment changes. Defaults to an array of
`['param', 'arg', 'argument', 'property', 'prop', 'returns', 'return']`.
##### `customSpacings`
@@ -34,10 +33,20 @@ An object with any of the following keys set to an integer. Affects spacing:
If a spacing is not defined, it defaults to one.
+##### `preserveMainDescriptionPostDelimiter`
+
+A boolean to determine whether to preserve the post-delimiter spacing of the
+main description. If `false` or unset, will be set to a single space.
+
+##### `wrapIndent`
+
+The indent that will be applied for tag text after the first line.
+Default to the empty string (no indent).
+
|||
|---|---|
|Context|everywhere|
-|Options|(a string matching `"always" or "never"` and optional object with `tags` and `customSpacings`)|
+|Options|(a string matching `"always"`, `"never"`, or `"any"` and optional object with `tags`, `customSpacings`, `preserveMainDescriptionPostDelimiter`, and `wrapIndent`)|
|Tags|`param`, `property`, `returns` and others added by `tags`|
|Aliases|`arg`, `argument`, `prop`, `return`|
|Recommended|false|
diff --git a/README.md b/README.md
index a7a054495..570abd8bd 100644
--- a/README.md
+++ b/README.md
@@ -2031,10 +2031,10 @@ for example.
This rule allows one optional string argument. If it is `"always"` then a
problem is raised when the lines are not aligned. If it is `"never"` then
a problem should be raised when there is more than one space between each
-line's parts. Defaults to `"never"`.
+line's parts. If it is `"any"`, no alignment is made. Defaults to `"never"`.
-Note that in addition to alignment, both options will ensure at least one
-space is present after the asterisk delimiter.
+Note that in addition to alignment, the "never" and "always" options will both
+ensure that at least one space is present after the asterisk delimiter.
After the string, an options object is allowed with the following properties.
@@ -2042,8 +2042,7 @@ After the string, an options object is allowed with the following properties.
##### tags
-Use this to change the tags which are sought for alignment changes. *Currently*
-*only works with the "never" option.* Defaults to an array of
+Use this to change the tags which are sought for alignment changes. Defaults to an array of
`['param', 'arg', 'argument', 'property', 'prop', 'returns', 'return']`.
@@ -2060,10 +2059,24 @@ An object with any of the following keys set to an integer. Affects spacing:
If a spacing is not defined, it defaults to one.
+
+
+##### preserveMainDescriptionPostDelimiter
+
+A boolean to determine whether to preserve the post-delimiter spacing of the
+main description. If `false` or unset, will be set to a single space.
+
+
+
+##### wrapIndent
+
+The indent that will be applied for tag text after the first line.
+Default to the empty string (no indent).
+
|||
|---|---|
|Context|everywhere|
-|Options|(a string matching `"always" or "never"` and optional object with `tags` and `customSpacings`)|
+|Options|(a string matching `"always"`, `"never"`, or `"any"` and optional object with `tags`, `customSpacings`, `preserveMainDescriptionPostDelimiter`, and `wrapIndent`)|
|Tags|`param`, `property`, `returns` and others added by `tags`|
|Aliases|`arg`, `argument`, `prop`, `return`|
|Recommended|false|
@@ -2508,6 +2521,53 @@ const fn = ( lorem, sit ) => {}
const fn = ( lorem, sit ) => {}
// "jsdoc/check-line-alignment": ["error"|"warn", "never",{"customSpacings":{"postHyphen":2}}]
// Message: Expected JSDoc block lines to not be aligned.
+
+/**
+ * @param {string} lorem Description
+ * with multiple lines.
+ */
+function quux () {
+}
+// "jsdoc/check-line-alignment": ["error"|"warn", "any",{"wrapIndent":" "}]
+// Message: Expected wrap indent
+
+/**
+ * Function description.
+ *
+ * @param {string} lorem Description.
+ * @param {int} sit Description multi
+ * line with asterisks.
+ */
+const fn = ( lorem, sit ) => {}
+// "jsdoc/check-line-alignment": ["error"|"warn", "always",{"wrapIndent":" "}]
+// Message: Expected JSDoc block lines to be aligned.
+
+/**
+ * My function.
+ *
+ * @param {string} lorem Description.
+ * @param {int} sit Description multiple
+ * lines.
+ */
+const fn = ( lorem, sit ) => {}
+// "jsdoc/check-line-alignment": ["error"|"warn", "never",{"wrapIndent":" "}]
+// Message: Expected JSDoc block lines to not be aligned.
+
+/**
+ * @property {boolean} tls_verify_client_certificate - Whether our API should
+ * enable TLS client authentication
+ */
+function quux () {}
+// "jsdoc/check-line-alignment": ["error"|"warn", "never",{"wrapIndent":" "}]
+// Message: Expected wrap indent
+
+/**
+ * @property {boolean} tls_verify_client_certificate - Whether our API should
+ * enable TLS client authentication
+ */
+function quux () {}
+// "jsdoc/check-line-alignment": ["error"|"warn", "never",{"wrapIndent":""}]
+// Message: Expected wrap indent
````
The following patterns are not considered problems:
@@ -2865,11 +2925,59 @@ const fn = ( lorem, sit ) => {};
const fn = ( a, b ) => {};
// "jsdoc/check-line-alignment": ["error"|"warn", "always"]
+/**
+ * @param {string} lorem Description
+ * with multiple lines.
+ */
+function quux () {
+}
+// "jsdoc/check-line-alignment": ["error"|"warn", "any",{"wrapIndent":" "}]
+
+/**
+ * @param {string} lorem Description
+ * with multiple lines.
+ */
+function quux () {
+}
+// "jsdoc/check-line-alignment": ["error"|"warn", "never",{"wrapIndent":" "}]
+
+/**
+ * Function description.
+ *
+ * @param {string} lorem Description.
+ * @param {int} sit Description multi
+ * line with asterisks.
+ */
+const fn = ( lorem, sit ) => {}
+// "jsdoc/check-line-alignment": ["error"|"warn", "always",{"wrapIndent":" "}]
+
+/**
+ * Function description.
+ *
+ * @param {string} lorem Description.
+ * @param {int} sit Description multi
+ * line with
+ * asterisks.
+ */
+const fn = ( lorem, sit ) => {}
+// "jsdoc/check-line-alignment": ["error"|"warn", "always",{"wrapIndent":" "}]
+
+/**
+ * @param {
+ * string | number
+ * } lorem Description
+ * with multiple lines.
+ */
+function quux () {
+}
+// "jsdoc/check-line-alignment": ["error"|"warn", "never",{"wrapIndent":" "}]
+
/**
* @param {string|string[]|TemplateResult|TemplateResult[]} event.detail.description -
* Notification description
*/
function quux () {}
+// "jsdoc/check-line-alignment": ["error"|"warn", "never",{"wrapIndent":" "}]
````
diff --git a/src/alignTransform.js b/src/alignTransform.js
index dbf83e26e..a634dfc6d 100644
--- a/src/alignTransform.js
+++ b/src/alignTransform.js
@@ -104,6 +104,7 @@ const alignTransform = ({
tags,
indent,
preserveMainDescriptionPostDelimiter,
+ wrapIndent,
}) => {
let intoTags = false;
let width;
@@ -180,10 +181,11 @@ const alignTransform = ({
return tokens;
};
- const update = (line, index, source, typelessInfo) => {
+ const update = (line, index, source, typelessInfo, indentTag) => {
const tokens = {
...line.tokens,
};
+
if (tokens.tag !== '') {
intoTags = true;
}
@@ -204,21 +206,19 @@ const alignTransform = ({
};
}
- /* eslint-disable indent */
switch (tokens.delimiter) {
- case Markers.start:
- tokens.start = indent;
- break;
- case Markers.delim:
- tokens.start = indent + ' ';
- break;
- default:
- tokens.delimiter = '';
-
- // compensate delimiter
- tokens.start = indent + ' ';
+ case Markers.start:
+ tokens.start = indent;
+ break;
+ case Markers.delim:
+ tokens.start = indent + ' ';
+ break;
+ default:
+ tokens.delimiter = '';
+
+ // compensate delimiter
+ tokens.start = indent + ' ';
}
- /* eslint-enable */
if (!intoTags) {
if (tokens.description === '') {
@@ -240,16 +240,16 @@ const alignTransform = ({
);
// Not align.
- if (!shouldAlign(tags, index, source)) {
- return {
- ...line,
- tokens,
- };
+ if (shouldAlign(tags, index, source)) {
+ alignTokens(tokens, typelessInfo);
+ if (indentTag) {
+ tokens.postDelimiter += wrapIndent;
+ }
}
return {
...line,
- tokens: alignTokens(tokens, typelessInfo),
+ tokens,
};
};
@@ -263,10 +263,19 @@ const alignTransform = ({
const typelessInfo = getTypelessInfo(fields);
+ let tagIndentMode = false;
+
return rewireSource({
...fields,
source: source.map((line, index) => {
- return update(line, index, source, typelessInfo);
+ const indentTag = tagIndentMode && !line.tokens.tag && line.tokens.description;
+ const ret = update(line, index, source, typelessInfo, indentTag);
+
+ if (line.tokens.tag) {
+ tagIndentMode = true;
+ }
+
+ return ret;
}),
});
};
diff --git a/src/rules/checkLineAlignment.js b/src/rules/checkLineAlignment.js
index 12435bc54..c4e144b4e 100644
--- a/src/rules/checkLineAlignment.js
+++ b/src/rules/checkLineAlignment.js
@@ -137,6 +137,7 @@ const checkAlignment = ({
report,
tags,
utils,
+ wrapIndent,
}) => {
const transform = commentFlow(
alignTransform({
@@ -144,6 +145,7 @@ const checkAlignment = ({
indent,
preserveMainDescriptionPostDelimiter,
tags,
+ wrapIndent,
}),
);
const transformedJsdoc = transform(jsdoc);
@@ -176,6 +178,7 @@ export default iterateJsdoc(({
],
preserveMainDescriptionPostDelimiter,
customSpacings,
+ wrapIndent = '',
} = context.options[1] || {};
if (context.options[0] === 'always') {
@@ -193,14 +196,48 @@ export default iterateJsdoc(({
report,
tags: applicableTags,
utils,
+ wrapIndent,
});
return;
}
const foundTags = utils.getPresentTags(applicableTags);
+ if (context.options[0] !== 'any') {
+ for (const tag of foundTags) {
+ checkNotAlignedPerTag(utils, tag, customSpacings);
+ }
+ }
+
for (const tag of foundTags) {
- checkNotAlignedPerTag(utils, tag, customSpacings);
+ if (tag.source.length > 1) {
+ let idx = 0;
+ for (const {
+ tokens,
+ // Avoid the tag line
+ } of tag.source.slice(1)) {
+ idx++;
+
+ if (
+ !tokens.description ||
+ // Avoid first lines after multiline type
+ tokens.type ||
+ tokens.name
+ ) {
+ continue;
+ }
+
+ // Don't include a single separating space/tab
+ if (tokens.postDelimiter.slice(1) !== wrapIndent) {
+ utils.reportJSDoc('Expected wrap indent', {
+ line: tag.source[0].number + idx,
+ }, () => {
+ tokens.postDelimiter = tokens.postDelimiter.charAt() + wrapIndent;
+ });
+ return;
+ }
+ }
+ }
}
}, {
iterateAllJsdocs: true,
@@ -213,7 +250,7 @@ export default iterateJsdoc(({
schema: [
{
enum: [
- 'always', 'never',
+ 'always', 'never', 'any',
],
type: 'string',
},
@@ -250,6 +287,9 @@ export default iterateJsdoc(({
},
type: 'array',
},
+ wrapIndent: {
+ type: 'string',
+ },
},
type: 'object',
},
diff --git a/test/rules/assertions/checkLineAlignment.js b/test/rules/assertions/checkLineAlignment.js
index 1e928e447..91a140f71 100644
--- a/test/rules/assertions/checkLineAlignment.js
+++ b/test/rules/assertions/checkLineAlignment.js
@@ -1359,6 +1359,165 @@ export default {
const fn = ( lorem, sit ) => {}
`,
},
+ {
+ code: `
+ /**
+ * @param {string} lorem Description
+ * with multiple lines.
+ */
+ function quux () {
+ }
+ `,
+ errors: [
+ {
+ line: 4,
+ message: 'Expected wrap indent',
+ type: 'Block',
+ },
+ ],
+ options: [
+ 'any',
+ {
+ wrapIndent: ' ',
+ },
+ ],
+ output: `
+ /**
+ * @param {string} lorem Description
+ * with multiple lines.
+ */
+ function quux () {
+ }
+ `,
+ },
+ {
+ code: `
+ /**
+ * Function description.
+ *
+ * @param {string} lorem Description.
+ * @param {int} sit Description multi
+ * line with asterisks.
+ */
+ const fn = ( lorem, sit ) => {}
+ `,
+ errors: [
+ {
+ line: 2,
+ message: 'Expected JSDoc block lines to be aligned.',
+ type: 'Block',
+ },
+ ],
+ options: [
+ 'always',
+ {
+ wrapIndent: ' ',
+ },
+ ],
+ output: `
+ /**
+ * Function description.
+ *
+ * @param {string} lorem Description.
+ * @param {int} sit Description multi
+ * line with asterisks.
+ */
+ const fn = ( lorem, sit ) => {}
+ `,
+ },
+ {
+ code: `
+ /**
+ * My function.
+ *
+ * @param {string} lorem Description.
+ * @param {int} sit Description multiple
+ * lines.
+ */
+ const fn = ( lorem, sit ) => {}
+ `,
+ errors: [
+ {
+ line: 6,
+ message: 'Expected JSDoc block lines to not be aligned.',
+ type: 'Block',
+ },
+ ],
+ options: [
+ 'never',
+ {
+ wrapIndent: ' ',
+ },
+ ],
+ output: `
+ /**
+ * My function.
+ *
+ * @param {string} lorem Description.
+ * @param {int} sit Description multiple
+ * lines.
+ */
+ const fn = ( lorem, sit ) => {}
+ `,
+ },
+ {
+ code: `
+ /**
+ * @property {boolean} tls_verify_client_certificate - Whether our API should
+ * enable TLS client authentication
+ */
+ function quux () {}
+ `,
+ errors: [
+ {
+ line: 4,
+ message: 'Expected wrap indent',
+ type: 'Block',
+ },
+ ],
+ options: [
+ 'never',
+ {
+ wrapIndent: ' ',
+ },
+ ],
+ output: `
+ /**
+ * @property {boolean} tls_verify_client_certificate - Whether our API should
+ * enable TLS client authentication
+ */
+ function quux () {}
+ `,
+ },
+ {
+ code: `
+ /**
+ * @property {boolean} tls_verify_client_certificate - Whether our API should
+ * enable TLS client authentication
+ */
+ function quux () {}
+ `,
+ errors: [
+ {
+ line: 4,
+ message: 'Expected wrap indent',
+ type: 'Block',
+ },
+ ],
+ options: [
+ 'never',
+ {
+ wrapIndent: '',
+ },
+ ],
+ output: `
+ /**
+ * @property {boolean} tls_verify_client_certificate - Whether our API should
+ * enable TLS client authentication
+ */
+ function quux () {}
+ `,
+ },
],
valid: [
{
@@ -1909,6 +2068,93 @@ export default {
'always',
],
},
+ {
+ code: `
+ /**
+ * @param {string} lorem Description
+ * with multiple lines.
+ */
+ function quux () {
+ }
+ `,
+ options: [
+ 'any',
+ {
+ wrapIndent: ' ',
+ },
+ ],
+ },
+ {
+ code: `
+ /**
+ * @param {string} lorem Description
+ * with multiple lines.
+ */
+ function quux () {
+ }
+ `,
+ options: [
+ 'never',
+ {
+ wrapIndent: ' ',
+ },
+ ],
+ },
+ {
+ code: `
+ /**
+ * Function description.
+ *
+ * @param {string} lorem Description.
+ * @param {int} sit Description multi
+ * line with asterisks.
+ */
+ const fn = ( lorem, sit ) => {}
+ `,
+ options: [
+ 'always',
+ {
+ wrapIndent: ' ',
+ },
+ ],
+ },
+ {
+ code: `
+ /**
+ * Function description.
+ *
+ * @param {string} lorem Description.
+ * @param {int} sit Description multi
+ * line with
+ * asterisks.
+ */
+ const fn = ( lorem, sit ) => {}
+ `,
+ options: [
+ 'always',
+ {
+ wrapIndent: ' ',
+ },
+ ],
+ },
+ {
+ code: `
+ /**
+ * @param {
+ * string | number
+ * } lorem Description
+ * with multiple lines.
+ */
+ function quux () {
+ }
+ `,
+ options: [
+ 'never',
+ {
+ wrapIndent: ' ',
+ },
+ ],
+ },
{
code: `
/**
@@ -1917,6 +2163,12 @@ export default {
*/
function quux () {}
`,
+ options: [
+ 'never',
+ {
+ wrapIndent: ' ',
+ },
+ ],
},
],
};