lines-builder
Version:
Tool and model to handle string lines and indentation.
254 lines (191 loc) • 8.42 kB
Markdown
# lines-builder
    
Tool and model to handle string lines and indentation.
## Usage
To create a **new lines-builder** object:
```typescript
import { lines } from "lines-builder";
const l = lines("Hello World\nThis is the 2nd line");
console.log(l);
// Hello World
// This is the 2nd line
```
The `lines` accepts an optional `options` object and any additional string (or lines-builder) as lines.
### Options
| Option | Type | Description | Default |
| :--------------------- | :--------------- | :--------------------------------------------------------------------------------- | :---------------------- |
| `indent` | `string\|number` | The indentation to use to indent the lines (exact string or the number of spaces). | `null` (no indentation) |
| `indentEmpty` | `boolean` | Whether the empty lines should still be indented. | `false` |
| `skipFirstLevelIndent` | `boolean` | Whether only the nested lines-builders should be indented. | `false` |
| `skipEmpty` | `boolean` | Whether empty lines should be added to the output string. | `false` |
| `trimLeft` | `boolean` | Can trailing white spaces be trimmed from the parsed lines. | `true` |
| `trimRight` | `boolean` | Can leading white spaces be trimmed from the parsed lines. | `true` |
| `eol` | `string` | The line-break to be used. If not set, it is determined based on the platform. | `null` |
### Append
You can **append any lines**, including a new line to the end (in place), passing any string (or lines-builder) as arguments to `append` :
```typescript
l.append("3rd line", null, "4th line\nand 5th line");
console.log(l);
// Hello World
// This is the 2nd line
// 3rd line
//
// 4th line
// 5th line
```
### Prepend
You can **prepend any lines**, including new-line to the beginning (in place), passing any string (or lines-builder) as arguments to `prepend` :
```typescript
l.prepend("This is the title", null, "And the 0th line");
console.log(l);
// This is the title
//
// And the 0th line
// Hello World
// This is the 2nd line
// 3rd line
//
// 4th line
// 5th line
```
### Indent
You can set a **global indentation** to the lines added:
```typescript
const l = lines({ indent: '--' }, "Hello World", "2nd line");
console.log(l);
// --Hello World
// --2nd line
```
By default, **no indentation** is set.
You can also set a **number** as the indentation. In this case, the given number of spaces will be used.
### Trim
By default, lines-builder **trims** the leading and trailing **whitespaces**, but you can turn it off:
```typescript
const l = lines({ trimLeft: false, trimRight: false }, "Hello World ", " 2nd line\n 3rd line");
console.log(l);
// Hello World
// 2nd line
// 3rd line
```
### Nesting
Lines-builder accepts another lines-builder instance instead of any string lines, to be able to nest it:
```typescript
const nested = lines({ indent: '==' }, "1st nested", "2nd nested");
const parent = lines({ indent: '--' }, "1st parent", nested, "2nd parent");
console.log(parent);
// --1st parent
// --==1st nested
// --==2nd nested
// --2nd parent
```
By setting the `skipFirstLevelIndent` option, the lines-builder won't indent the direct lines of the lines-builder,
only starting from the nested ones:
```typescript
const nested = lines(, "1st nested", "2nd nested");
const parent = lines({ skipFirstLevelIndent: true, indent: '--' }, "1st parent", nested, "2nd parent");
console.log(parent);
// 1st parent
// --1st nested
// --2nd nested
// 2nd parent
```
### Default options
As seen above, options can be set per each lines-builder, but if you want to use one set of options,
per each lines-builder you will use, you can use the `setDefaultOptions`.
```typescript
import { lines, setDefaultOptions } from "lines-builder";
setDefaultOptions({ indent: "__" });
const nested = lines("1st nested", "2nd nested");
const parent = lines("1st parent", nested, "2nd parent");
console.log(parent);
// __1st parent
// ____1st nested
// ____2nd nested
// __2nd parent
```
Note that the default options can be reset to the [initial ones](src/index.ts#L20) with the `resetDefaultOptions`.
### EOL
To output/format the lines, the lines-builder will determine the appropriate EOL based on the platform used ( `\r\n` for Windows, `\n` for other OS).
If you need to set explicitly what EOL to use, pass it in any options:
```typescript
// IBM Mainframe EOL
const l = lines({ eol: "\025" }, "Hello", "World");
console.log(l);
// Hello\025World
```
### Filtering
The filter method can be used to filter in place - either to keep or remove lines matching a specific pattern.
```typescript
const l = lines("simple line", "# comment line", "other line");
// the following expression removes lines starting with #
l.filter(/^\s*#/, true);
console.log(l);
// simple line
// other line
```
If filtering needs to be done on a copy of the lines-builder, without touching the original one, the 3rd argument must be set to `false`:
```typescript
const l = lines("simple line", "# comment line", "other line");
// the following expression removes lines starting with # and returns the result
const filtered = l.filter(/^\s*#/, true, false);
console.log(filtered);
// simple line
// other line
console.log(l);
// simple line
// # comment line
// other line
```
The filter function accepts either
1. a `string`, which will be converted to a case-insensitive RegExp
1. a `RegExp`, what will be used as it is
1. a `type LineMatcher = (line: string, i: number) => boolean;` function, what should return `true` in case of a match.
The filter function, based on the `reverse` parameter
1. if `false`, it keeps the line if the matcher is `true`; otherwise, it removes it
1. if `true`, it removes the line if the matcher is `true`; otherwise, it removes it
In the case of nested lines-builder, the same matcher and parameter are applied, and the nested one is kept if it contains any line after the filter.
### Mapping
The map method can be used to map the lines in place, updating all the lines with a function.
```typescript
const l = lines("line a", "line b", lines("nested line"));
// the following add level/index to each line
l.map((line: string, i: number, level: number) => `${level}/${i} - ${line}`);
console.log(l);
// 0/0 - line a
// 0/1 - line b
// 1/0 - nested line
```
If mapping needs to be done on a copy of the lines-builder, without touching the original one, the 2nd argument must be set to `false`:
```typescript
const l = lines("line a", "line b", lines("nested line"));
// the following add level/index to each line
const mapped = l.map((line: string, i: number, level: number) => `${level}/${i} - ${line}`, false);
console.log(mapped);
// 0/0 - line a
// 0/1 - line b
// 1/0 - nested line
console.log(l);
// line a
// line b
// nested line
```
### Copy
The copy method can be used to clone the lines-builder (including the nested lines, with the same options):
```typescript
const l = lines("line a", "line b", lines("nested line"));
const copied = l.copy();
console.log(copied);
// line a
// line b
// nested line
console.log(l);
// line a
// line b
// nested line
```
## Other
For detailed documentation see the [TypeDocs documentation](https://szikszail.github.io/lines-builder/).
This package uses [debug](https://www.npmjs.com/package/debug) for logging, use `lines-builder` to see debug logs:
```shell
DEBUG=lines-builder node my-script.js
```