-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(strings): Add
stripIndent
utility
- Loading branch information
Showing
3 changed files
with
115 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { stripIndent } from './strip-indent'; | ||
|
||
describe('strip-indent', () => { | ||
it('Returns the string as is if there is no extra indentation and leading/trailing linebreaks', () => { | ||
expect(stripIndent('')).toBe(''); | ||
expect(stripIndent('foo')).toBe('foo'); | ||
expect(stripIndent('foo\n\t\t\tbar\n\nbar')).toBe('foo\n\t\t\tbar\n\nbar'); | ||
}); | ||
|
||
it('Removes leading/trailing linebreaks and lines containing only space\tab characters by default', () => { | ||
expect(stripIndent('\nfoo\n')).toBe('foo'); | ||
expect(stripIndent('\n\t \nfoo\n\t\t \t\t\n')).toBe('foo'); | ||
}); | ||
|
||
it('Preserves leading linebreaks and lines containing only space\tab characters using `trimLeadingSpacings: false`', () => { | ||
expect(stripIndent('\nfoo\n', { trimLeadingSpacings: false })).toBe('\nfoo'); | ||
expect(stripIndent('\n\t \nfoo\n\t\t \t\t\n', { trimLeadingSpacings: false })).toBe('\n\t \nfoo'); | ||
}); | ||
|
||
it('Preserves trailing linebreaks and lines containing only space\tab characters using `trimTrailingSpacings: false`', () => { | ||
expect(stripIndent('\nfoo\n', { trimTrailingSpacings: false })).toBe('foo\n'); | ||
expect(stripIndent('\n\t \nfoo\n\t\t \t\t\n', { trimTrailingSpacings: false })).toBe('foo\n\t\t \t\t\n'); | ||
}); | ||
|
||
it('Removes extra indentation and linebreaks', () => { | ||
expect(stripIndent(` | ||
<div> | ||
<div></div> | ||
</div> | ||
`)).toBe('<div>\n\t<div></div>\n</div>'); | ||
}); | ||
|
||
it('Removes extra indentation and linebreaks considering extra spacings', () => { | ||
expect(stripIndent(` | ||
<div> | ||
<div></div> | ||
<div></div> | ||
<div></div> | ||
</div> | ||
`)).toBe('<div>\n\t<div></div>\n\t <div></div>\n\t\t\t<div></div>\n</div>'); | ||
}); | ||
|
||
it('Removes only extra indentation using `trim[X]Spacings: false`', () => { | ||
expect(stripIndent(` | ||
<div> | ||
<div></div> | ||
</div> | ||
`, { trimLeadingSpacings: false, trimTrailingSpacings: false })).toBe('\n\n<div>\n\t<div></div>\n</div>\n\n\t\t'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { mergeObjects } from '../../objects/merge-objects/merge-objects'; | ||
|
||
const _getMinimalIndent = (input: string) => { | ||
const match = input.match(/^[\t ]*(?=\S)/gm); | ||
if (!match) return 0; | ||
|
||
return match.reduce((minimalIndentation, spacings) => | ||
Math.min(minimalIndentation, spacings.length), Infinity); | ||
}; | ||
|
||
|
||
type Options = { | ||
/** | ||
* Whether to remove leading linebreaks and spacings (before the first non-space character) | ||
* | ||
* @default true | ||
*/ | ||
trimLeadingSpacings: boolean; | ||
|
||
/** | ||
* Whether to remove trailing linebreaks and spacings (after the last non-space character) | ||
* | ||
* @default true | ||
*/ | ||
trimTrailingSpacings: boolean; | ||
}; | ||
|
||
const DEFAULTS: Options = { | ||
trimLeadingSpacings: true, | ||
trimTrailingSpacings: true, | ||
}; | ||
|
||
const _applyOptions = (input: string, options: Options) => { | ||
options.trimLeadingSpacings && (input = input.replace(/^\n\s*(?=\S)/, '')); | ||
options.trimTrailingSpacings && (input = input.replace(/\n\s*$/, '')); | ||
|
||
return input; | ||
}; | ||
|
||
/** | ||
* Removes an extra indentation of the string. \ | ||
* Useful to work with template literal strings. | ||
* | ||
* @param input String to remove an extra indentation. | ||
* @param userOptions Extra options. | ||
* | ||
* @returns The string with minimal required indentation. | ||
*/ | ||
export const stripIndent = (input: string, userOptions?: Partial<Options>) => { | ||
const options = mergeObjects(DEFAULTS, userOptions) as Required<Options>; | ||
|
||
const minIndent = _getMinimalIndent(input); | ||
if (minIndent === 0) return _applyOptions(input, options); | ||
|
||
const regex = new RegExp(`^[\t ]{${minIndent}}`, 'gm'); | ||
|
||
return _applyOptions(input, options).replace(regex, ''); | ||
}; |