Skip to content
This repository was archived by the owner on Jun 15, 2019. It is now read-only.

Commit e12bcb7

Browse files
committed
feat(Main algorithm and API): 1. Main algorithm was changed to support indentations correctly
2. It (main algorithm) also was highly improved. 3. Two options (WrapOptions) and three methods (Debug) were added to the API: Options: - breakableCharacters - allowedExceedingCharacters Methods: - debug.enable() - debug.disable() - debug.setLog() 4. A `formatter` was added to `Debug` and was used to improve performance (`Debug.formatters.c`).
1 parent 7ea3fca commit e12bcb7

File tree

4 files changed

+198
-122
lines changed

4 files changed

+198
-122
lines changed

jest/unit/text-wrap.ts

Lines changed: 79 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
import * as fs from 'fs'
2-
import * as path from "path"
32
import {sha256} from 'js-sha256'
4-
import TextWrap, {WrapStyle} from '../../src/TextWrap'
3+
import * as path from "path"
4+
import TextWrap, {WrapOptions} from '../../src/TextWrap'
55

66
/**
77
* @author [S. Mahdi Mir-Ismaili](https://mirismaili.github.io)
88
* Created on 1398/2/13 (2019/5/3).
99
*/
1010

11-
const inputExpectedHash = '117677f3e12ded864c527d4f03583d4dd0be3cc0542c3cbbdbb01574dcf280c8'
12-
const outputExpectedHash = '2e1bd0f9ae5b0ee9406908f58bd5b4030bbcdf464e5462e0fd1b142d49dbac2d'
13-
14-
const input = fs.readFileSync(path.resolve(__dirname, 'stub', 'input.txt'), 'utf8')
11+
let originalInput = fs.readFileSync(path.resolve(__dirname, 'stub', 'input.txt'), 'utf8')
1512
.replace(/\r\n|\r/g, '\n')
1613

1714
const allOptions: (Options | undefined)[] = [
@@ -20,23 +17,56 @@ const allOptions: (Options | undefined)[] = [
2017
indents: '\t',
2118
wrapOn: 50,
2219
continuationIndent: '',
20+
expectedOutputHash: 'f90cb72aaae81b846ad5af9d7c03947fb2e858fc7c847f2c54ff1c27fe13ea7e',
2321
},
2422
{
2523
indents: '',
2624
wrapOn: 51,
2725
continuationIndent: '\t',
26+
expectedOutputHash: '0d4bdbb897a39fb462f21e066cbc798266e3ee85e0adaa441a030d333ae306a4',
2827
},
2928
{
3029
indents: '',
3130
wrapOn: 52,
3231
continuationIndent: ' ',
32+
expectedOutputHash: '8ca6cdd09ab4e49adb7dc489c745015c26e242aa70f478373e4ddf5dbcf40329',
33+
},
34+
{
35+
indents: '\t',
36+
wrapOn: 53,
37+
continuationIndent: '\t\t',
38+
tabLength: 2,
39+
expectedOutputHash: 'e2af18c11ebc7a8c7b63b55ed953c0be30f38d7071f717725f6a30ff99e63b18',
40+
},
41+
{
42+
indents: ' ',
43+
wrapOn: 63,
44+
continuationIndent: '\t',
45+
tabLength: 8,
46+
expectedOutputHash: 'da196f9855194d5f90eaff99ecbd655bfa32b0bed918b6f8708dff6d20bfed37',
47+
},
48+
{
49+
indents: '\t ',
50+
wrapOn: 73,
51+
continuationIndent: '\t ',
52+
tabLength: 3,
53+
expectedOutputHash: 'c314c36352e0d0e27643a3100e94047df3af11efa8a1fbde90cb885a533fdfe6',
54+
},
55+
{
56+
indents: '\t',
57+
wrapOn: 74,
58+
continuationIndent: ' ',
59+
tabLength: 6,
60+
enabledDebugNamespace: 'BR',
61+
expectedOutputHash: '337a9d26400205e184ec6ef841cee70714bb4f751be46f877e27016248a3f9b1',
3362
},
3463
]
3564

3665
const outputs: string[] = []
66+
//***********************************************************************************/
3767

3868
describe('Case-specific tests:', () => {
39-
it("Check input's hash", () => expect(sha256(input)).toBe(inputExpectedHash))
69+
it("Check input's hash", () => expect(sha256(originalInput)).toBe('928c256346d0b16e69cd4c4ddd56e5608335f9ad16d1a25c26a9d8ff4b3e4edf'))
4070
})
4171

4272
afterAll(() => {
@@ -47,21 +77,40 @@ afterAll(() => {
4777
for (let testNum = 0; testNum < allOptions.length; ++testNum) {
4878
const options = allOptions[testNum]
4979
const textWrap = new TextWrap(options)
50-
5180
const maxLineLength = textWrap.wrapOn
5281
const continuationIndent = textWrap.continuationIndent
53-
const bc = textWrap.breakableCharactersClass
54-
const ec = textWrap.allowedExceedingCharactersClass
82+
const bc = textWrap.breakableCharacters
83+
const ec = textWrap.allowedExceedingCharacters
5584

56-
const indents = options === undefined ? '' : options.indents
57-
const indentsN = indents + continuationIndent
85+
let indents: string
86+
let expectedOutputHash: string
87+
88+
let input = originalInput
89+
90+
if (options === undefined) { // Default values for first options (that is undefined):
91+
indents = ''
92+
expectedOutputHash = '971346506cad37fecd726196c2d75d577f02f160368953b9a261b36af3dec822'
93+
} else {
94+
indents = options.indents
95+
expectedOutputHash = options.expectedOutputHash
96+
97+
if (options.enabledDebugNamespace) { // Just for test coverage. To cover debug callback functions (formatters)
98+
textWrap.debug.setLog(() => null) // Disable console outputs of `debug`
99+
textWrap.debug.enable(options.enabledDebugNamespace)
100+
input = input.slice(0, 500)
101+
}
102+
}
58103

59104
const wrapResult = textWrap.wrap(input, indents)
105+
106+
const indentsN = indents + continuationIndent
107+
60108
const output = outputs[testNum] = wrapResult.wrappedText
61109
const markers = wrapResult.markers
62110

63111
describe(`General tests [${testNum}]:`, () => {
64-
it('Check num of markers', () => expect(output.length).toBe(input.length + markers.length * ('\n' + indentsN).length))
112+
it('Check num of markers',
113+
() => expect(output.length).toBe(input.length + markers.length * ('\n' + indentsN).length))
65114

66115
it('Reproduce output using markers', () => {
67116
let anotherOutput = ''
@@ -78,12 +127,11 @@ for (let testNum = 0; testNum < allOptions.length; ++testNum) {
78127
})
79128

80129
it('Try to find an illegal short line',
81-
// Two markers which [the distance between the first marker and the first breakable character after the second
82-
// marker] is less than or equal with [maxLineLength]
130+
// Two markers which [the distance between a marker and the first breakable character after next marker] is
131+
// less than or equal with [maxLineLength]
83132
() => {
84133
let a = 0
85-
const regExp = new RegExp(bc.source,
86-
bc.flags.appendIfNot('g'))
134+
const regExp = new RegExp(bc.source, bc.flags.appendIfNot('g'))
87135

88136
for (let b of markers) {
89137
regExp.lastIndex = b
@@ -119,19 +167,19 @@ for (let testNum = 0; testNum < allOptions.length; ++testNum) {
119167
}
120168
})
121169

122-
it("Try to find an illegal long line using RegExp", // Same as above but using RegExp. This one is not strict because can only calculate length, but not vLen (visual-length)
123-
() => {
124-
expect(output).not.toMatch1(
125-
// https://regex101.com/r/OfQoDb/1
126-
new RegExp(
127-
`^(?=.{${indentsN.length},}[^\\w\\xA0\\n](?![^\\S\\n]|$)).{${maxLineLength},}\\S`,
128-
'm'),
129-
`The text will be in ${outputPath(testNum)}`)
130-
})
170+
// it("Try to find an illegal long line using RegExp", // Same as above but using RegExp. This one is not strict and accurate because can only calculate length, but not vLen (visual-length)
171+
// () => {
172+
// expect(output).not.toMatch1(
173+
// // https://regex101.com/r/OfQoDb/1
174+
// new RegExp(
175+
// `^(?=.{${indentsN.length},}[^\\w\\xA0\\n](?![^\\S\\n]|$)).{${maxLineLength},}\\S`,
176+
// 'm'),
177+
// `The text will be in "${outputPath(testNum)}"`)
178+
// })
131179
})
132180

133181
describe(`Case-specific tests [${testNum}]:`, () => {
134-
it("Check output's hash", () => expect(sha256(output)).toBe(outputExpectedHash))
182+
it("Check output's hash", () => expect(sha256(output)).toBe(expectedOutputHash))
135183
})
136184
}
137185
//*************************************************************************************/
@@ -146,7 +194,7 @@ expect.extend({
146194

147195
return passed ?
148196
{
149-
message: message(() => `doesn't match ${regExp}\nFirst match:\n[${match1}]`),
197+
message: message(() => `not match ${regExp}\nFirst match:\n[${match1}]`),
150198
pass: true,
151199
} :
152200
{
@@ -176,8 +224,10 @@ declare global {
176224

177225
//*************************************************************************************/
178226

179-
interface Options extends WrapStyle {
227+
interface Options extends WrapOptions {
180228
indents: string
229+
expectedOutputHash: string
230+
enabledDebugNamespace?: string
181231
}
182232

183233
function outputPath(i: number) {

package-lock.json

Lines changed: 11 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)