Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@
"name": "linebreak",
"version": "1.1.0",
"description": "An implementation of the Unicode Line Breaking Algorithm (UAX #14)",
"source": "src/linebreaker.js",
"source": "src/main.ts",
"type": "module",
"main": "dist/main.cjs",
"module": "dist/module.mjs",
"exports": {
"import": "./dist/module.mjs",
"require": "./dist/main.cjs"
"import": {
"types": "./dist/types.d.ts",
"default": "./dist/module.mjs"
},
"require": {
"types": "./dist/types.d.ts",
"default": "./dist/main.cjs"
}
},
"types": "./dist/types.d.ts",
"files": [
"dist"
],
Expand All @@ -32,12 +39,15 @@
"unicode-trie": "^2.0.0"
},
"devDependencies": {
"@parcel/packager-ts": "^2.13.3",
"@parcel/transformer-typescript-types": "^2.13.3",
"mocha": "^10.0.0",
"parcel": "^2.13.3",
"request": "^2.88.0"
"request": "^2.88.0",
"typescript": "^5.9.2"
},
"scripts": {
"test": "parcel build && mocha test/index.js --reporter landing",
"test": "parcel build && mocha test/index.js test/iter.js --reporter landing",
"build": "parcel build",
"prepublishOnly": "parcel build"
},
Expand Down
50 changes: 36 additions & 14 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,49 @@ it could be used for other things as well.

You can install via npm

npm install linebreak
```sh
npm install linebreak
```

## Examples

## Example
### Using Iterable Protocol and `for...of`

```javascript
var LineBreaker = require('linebreak');
import LineBreaker from 'linebreak';

const text = 'Hello world...\n1.5, 2.\n(Hello, world?)\nfoo(bar), foo_bar, foo-bar.';

for (const bk of new LineBreaker(text)) {
console.log(bk.substring.replace(/ $/, '~') + (bk.required ? '<brk>' : ''));
}

var lorem = 'lorem ipsum...';
var breaker = new LineBreaker(lorem);
var last = 0;
var bk;
// Hello~
// world...
// <brk>
// 1.5,~
// 2.
// <brk>
// (Hello,~
// world?)
// <brk>
// foo(bar),~
// foo_bar,~
// foo-
// bar.
```

### Using `nextBreak()`

```javascript
const breaker = new LineBreaker(text);
let last = 0;
let bk = null;

while (bk = breaker.nextBreak()) {
// get the string between the last break and this one
var word = lorem.slice(last, bk.position);
console.log(word);

// you can also check bk.required to see if this was a required break...
if (bk.required) {
console.log('\n\n');
}
const substring = text.slice(last, bk.position);
console.log(substring.replace(/ $/, '~') + (bk.required ? '<brk>' : ''));

last = bk.position;
}
Expand Down
12 changes: 11 additions & 1 deletion src/linebreaker.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,16 @@ class LineBreaker {

return null;
}

*[Symbol.iterator]() {
let breakInfo = null;
let last = 0;
while ((breakInfo = this.nextBreak()) != null) {
const substring = this.string.slice(last, breakInfo.position);
last = breakInfo.position;
yield Object.assign({ substring }, breakInfo);
};
}
}

module.exports = LineBreaker;
export default LineBreaker;
19 changes: 19 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// @ts-ignore next line
import _LineBreaker from "./linebreaker.js";

interface Break {
position: number;
required: boolean;
}

interface BreakInfo extends Break {
substring: string;
}

interface LineBreaker {
new(input: string): LineBreaker;
nextBreak(): Break | null;
[Symbol.iterator](): Generator<BreakInfo, undefined, undefined>;
}

export default _LineBreaker as LineBreaker;
94 changes: 94 additions & 0 deletions test/iter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import LineBreaker from 'linebreak';
import assert from 'assert';

describe('[Symbol.iterator]', function () {
const text = 'Hello world...\n1.5, 2.\n(Hello, world?)\nfoo(bar), foo_bar, foo-bar.';

it('works with `for...of` loop', () => {
const log = [];
const console = { log: (msg) => log.push(msg) };
const breaker = new LineBreaker(text);

for (const bk of breaker) {
console.log(
bk.substring.replace(/ $/, '~') + (bk.required ? '<brk>' : ''),
);
}

assert.deepStrictEqual(log, [
'Hello~',
'world...\n<brk>',
'1.5,~',
'2.\n<brk>',
'(Hello,~',
'world?)\n<brk>',
'foo(bar),~',
'foo_bar,~',
'foo-',
'bar.',
]);

// already consumed, so no more results
assert.deepStrictEqual([...breaker], []);
});

it('iterates to array', () => {
const expected = [
{
position: 6,
required: false,
substring: 'Hello '
},
{
position: 15,
required: true,
substring: 'world...\n'
},
{
position: 20,
required: false,
substring: '1.5, '
},
{
position: 23,
required: true,
substring: '2.\n'
},
{
position: 31,
required: false,
substring: '(Hello, '
},
{
position: 39,
required: true,
substring: 'world?)\n'
},
{
position: 49,
required: false,
substring: 'foo(bar), '
},
{
position: 58,
required: false,
substring: 'foo_bar, '
},
{
position: 62,
required: false,
substring: 'foo-'
},
{
position: 66,
required: false,
substring: 'bar.'
}
];

const breaker = new LineBreaker(text);
assert.deepStrictEqual([...breaker], expected);
// already consumed, so no more results
assert.deepStrictEqual([...breaker], []);
});
});
6 changes: 6 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"compilerOptions": {
"strict": true,
"lib": ["ES2020"]
}
}
Loading