diff --git a/lib/node_modules/@stdlib/_tools/repl-txt/rules/no-premature-wrap/lib/collapse_continuations.js b/lib/node_modules/@stdlib/_tools/repl-txt/rules/no-premature-wrap/lib/collapse_continuations.js new file mode 100644 index 000000000000..16675293a7ee --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/repl-txt/rules/no-premature-wrap/lib/collapse_continuations.js @@ -0,0 +1,71 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// VARIABLES // + +var RE_PROSE_START = /^[a-zA-Z`(*'"[\u0080-￿]/; +var RE_NUMBERED = /^\d+\. /; + + +// MAIN // + +/** +* Collapses continuation lines within prose paragraphs while preserving blank lines, sub-indented content, list items, and table rows. +* +* @private +* @param {string} text - text with indent already stripped +* @returns {string} text with continuation lines joined +*/ +function collapseContinuations( text ) { + var current; + var parts; + var lines; + var line; + var i; + + lines = text.split( '\n' ); + parts = []; + current = []; + for ( i = 0; i < lines.length; i++ ) { + line = lines[ i ]; + if ( + line.length > 0 && + RE_PROSE_START.test( line ) && + !RE_NUMBERED.test( line ) + ) { + current.push( line ); + } else { + if ( current.length > 0 ) { + parts.push( current.join( ' ' ) ); + current = []; + } + parts.push( line ); + } + } + if ( current.length > 0 ) { + parts.push( current.join( ' ' ) ); + } + return parts.join( '\n' ); +} + + +// EXPORTS // + +module.exports = collapseContinuations; diff --git a/lib/node_modules/@stdlib/_tools/repl-txt/rules/no-premature-wrap/lib/index.js b/lib/node_modules/@stdlib/_tools/repl-txt/rules/no-premature-wrap/lib/index.js new file mode 100644 index 000000000000..2edfc86ad854 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/repl-txt/rules/no-premature-wrap/lib/index.js @@ -0,0 +1,39 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Lint rule to detect premature line wrapping in `repl.txt` files. +* +* @module @stdlib/_tools/repl-txt/rules/no-premature-wrap +* +* @example +* var rule = require( '@stdlib/_tools/repl-txt/rules/no-premature-wrap' ); +* +* console.log( rule ); +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/lib/node_modules/@stdlib/_tools/repl-txt/rules/no-premature-wrap/lib/main.js b/lib/node_modules/@stdlib/_tools/repl-txt/rules/no-premature-wrap/lib/main.js new file mode 100644 index 000000000000..3ae9379f11ae --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/repl-txt/rules/no-premature-wrap/lib/main.js @@ -0,0 +1,208 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var repeat = require( '@stdlib/string/repeat' ); +var rtrim = require( '@stdlib/string/right-trim' ); +var ltrim = require( '@stdlib/string/left-trim' ); +var wrap = require( '@stdlib/_tools/repl-txt/wrap-text' ); +var unwrap = require( './unwrap.js' ); + + +// VARIABLES // + +var MAX_WIDTH = 80; +var DESC_INDENT = 4; +var TAG_INDENT = 8; +var TAG_PREFIX = repeat( ' ', TAG_INDENT ); +var DESC_OPTS = { + 'indent': DESC_INDENT, + 'maxWidth': MAX_WIDTH +}; +var TAG_OPTS = { + 'indent': TAG_INDENT, + 'maxWidth': MAX_WIDTH +}; + + +// FUNCTIONS // + +/** +* Finds the first premature wrap by comparing original lines against rewrapped lines. +* +* @private +* @param {Array} olines - original lines +* @param {Array} rlines - rewrapped lines +* @returns {(Object|null)} object with `idx` and `extra` properties, or null +*/ +function findPrematureWrap( olines, rlines ) { + var extra; + var i; + + for ( i = 0; i < olines.length; i++ ) { + if ( olines[ i ] !== rlines[ i ] ) { + if ( rlines[ i ] && rlines[ i ].length > olines[ i ].length ) { + extra = ltrim( rlines[ i ].substring( olines[ i ].length ) ); + if ( extra ) { + return { + 'idx': i, + 'extra': extra + }; + } + } + return null; + } + } + return null; +} + +/** +* Finds the line number where a tag description begins within a section. +* +* @private +* @param {Object} section - section node +* @param {Object} tag - tag object +* @returns {NonNegativeInteger} line number of the tag description start +*/ +function findTagDescriptionLine( section, tag ) { + var firstLine; + var content; + var idx; + + content = section.content; + firstLine = tag.description.split( '\n' )[ 0 ]; + idx = content.indexOf( TAG_PREFIX + firstLine ); + if ( idx < 0 ) { + return section.start; + } + return section.start + 2 + content.substring( 0, idx ).split( '\n' ).length; +} + + +// MAIN // + +/** +* Rule for detecting premature line wrapping in the `repl.txt` files. +* +* @param {Context} context - lint context +* @returns {Object} validators +*/ +function main( context ) { + /** + * Checks whether a description has premature line wrapping. + * + * @private + * @param {Object} description - description node + */ + function checkDescription( description ) { + var unwrapped; + var rewrapped; + var result; + var line; + var raw; + + raw = rtrim( description.raw ); + unwrapped = unwrap( raw, DESC_INDENT ); + rewrapped = wrap( unwrapped, DESC_OPTS ); + if ( rewrapped === raw ) { + return; + } + result = findPrematureWrap( raw.split( '\n' ), rewrapped.split( '\n' ) ); + if ( result ) { + line = description.start + result.idx + 1; + context.report( '"' + result.extra + '" can fit on the previous line', { + 'start': line, + 'end': line + }); + } + } + + /** + * Checks whether tag descriptions have premature line wrapping. + * + * @private + * @param {Object} section - parameters or returns section + * @param {string} label - section label + */ + function checkTags( section, label ) { + var rewrappedLines; + var unwrapped; + var rewrapped; + var baseLine; + var olines; + var result; + var tags; + var line; + var i; + + tags = section.tags; + if ( !tags ) { + return; + } + for ( i = 0; i < tags.length; i++ ) { + unwrapped = unwrap( TAG_PREFIX + tags[ i ].description, TAG_INDENT ); + rewrapped = wrap( unwrapped, TAG_OPTS ); + rewrappedLines = rewrapped.split( '\n' ); + rewrappedLines[ 0 ] = rewrappedLines[ 0 ].substring( TAG_OPTS.indent ); // eslint-disable-line max-len + olines = tags[ i ].description.split( '\n' ); + result = findPrematureWrap( olines, rewrappedLines ); + if ( result ) { + baseLine = findTagDescriptionLine( section, tags[ i ] ); + line = baseLine + result.idx + 1; + context.report( 'In ' + label + ' "' + tags[ i ].name + '", "' + result.extra + '" can fit on the previous line', { + 'start': line, + 'end': line + }); + } + } + } + + /** + * Checks whether parameter tag descriptions have premature line wrapping. + * + * @private + * @param {Object} section - parameters section + */ + function checkParameters( section ) { + checkTags( section, 'parameter' ); + } + + /** + * Checks whether return tag descriptions have premature line wrapping. + * + * @private + * @param {Object} section - returns section + */ + function checkReturns( section ) { + checkTags( section, 'return' ); + } + + return { + 'description': checkDescription, + 'parameters': checkParameters, + 'returns': checkReturns + }; +} + + +// EXPORTS // + +module.exports = main; diff --git a/lib/node_modules/@stdlib/_tools/repl-txt/rules/no-premature-wrap/lib/unwrap.js b/lib/node_modules/@stdlib/_tools/repl-txt/rules/no-premature-wrap/lib/unwrap.js new file mode 100644 index 000000000000..3fecf898c6f9 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/repl-txt/rules/no-premature-wrap/lib/unwrap.js @@ -0,0 +1,56 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var startsWith = require( '@stdlib/string/starts-with' ); +var repeat = require( '@stdlib/string/repeat' ); +var collapseContinuations = require( './collapse_continuations.js' ); + + +// MAIN // + +/** +* Un-wraps text by stripping a leading indent and collapsing continuation lines. +* +* @private +* @param {string} text - indented text +* @param {NonNegativeInteger} indent - number of leading spaces to strip +* @returns {string} un-wrapped text +*/ +function unwrap( text, indent ) { + var prefix; + var lines; + var i; + + prefix = repeat( ' ', indent ); + lines = text.split( '\n' ); + for ( i = 0; i < lines.length; i++ ) { + if ( startsWith( lines[ i ], prefix ) ) { + lines[ i ] = lines[ i ].substring( indent ); + } + } + return collapseContinuations( lines.join( '\n' ) ); +} + + +// EXPORTS // + +module.exports = unwrap; diff --git a/lib/node_modules/@stdlib/_tools/repl-txt/rules/no-premature-wrap/package.json b/lib/node_modules/@stdlib/_tools/repl-txt/rules/no-premature-wrap/package.json new file mode 100644 index 000000000000..9514d0ddaa35 --- /dev/null +++ b/lib/node_modules/@stdlib/_tools/repl-txt/rules/no-premature-wrap/package.json @@ -0,0 +1,63 @@ +{ + "name": "@stdlib/_tools/repl-txt/rules/no-premature-wrap", + "version": "0.0.0", + "description": "Lint rule to detect premature line wrapping in `repl.txt` files.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "bin": {}, + "main": "./lib", + "directories": { + "lib": "./lib" + }, + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "tools", + "tool", + "repl.txt", + "repl", + "lint", + "custom", + "rules", + "rule", + "plugin", + "code", + "style", + "wrap", + "premature" + ] +}