Skip to content

Commit

Permalink
Extract 'getBlockStringIndentation' function
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanGoncharov committed Mar 26, 2019
1 parent dce2b6f commit c6e5ef2
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 16 deletions.
37 changes: 36 additions & 1 deletion src/language/__tests__/blockString-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@

import { expect } from 'chai';
import { describe, it } from 'mocha';
import { dedentBlockStringValue, printBlockString } from '../blockString';
import {
dedentBlockStringValue,
getBlockStringIndentation,
printBlockString,
} from '../blockString';

function joinLines(...args) {
return args.join('\n');
Expand Down Expand Up @@ -99,6 +103,37 @@ describe('dedentBlockStringValue', () => {
});
});

describe('getBlockStringIndentation', () => {
it('returns zero for an empty array', () => {
expect(getBlockStringIndentation([])).to.equal(0);
});

it('do not take first line into account', () => {
expect(getBlockStringIndentation([' a'])).to.equal(0);
expect(getBlockStringIndentation([' a', ' b'])).to.equal(2);
});

it('returns minimal indentation length', () => {
expect(getBlockStringIndentation(['', ' a', ' b'])).to.equal(1);
expect(getBlockStringIndentation(['', ' a', ' b'])).to.equal(1);
expect(getBlockStringIndentation(['', ' a', ' b', 'c'])).to.equal(0);
});

it('count both tab and space as single character', () => {
expect(getBlockStringIndentation(['', '\ta', ' b'])).to.equal(1);
expect(getBlockStringIndentation(['', '\t a', ' b'])).to.equal(2);
expect(getBlockStringIndentation(['', ' \t a', ' b'])).to.equal(3);
});

it('do not take empty lines into account', () => {
expect(getBlockStringIndentation(['a', '\t'])).to.equal(0);
expect(getBlockStringIndentation(['a', ' '])).to.equal(0);
expect(getBlockStringIndentation(['a', ' ', ' b'])).to.equal(2);
expect(getBlockStringIndentation(['a', ' ', ' b'])).to.equal(2);
expect(getBlockStringIndentation(['a', '', ' b'])).to.equal(1);
});
});

describe('printBlockString', () => {
it('by default print block strings as single line', () => {
const str = 'one liner';
Expand Down
39 changes: 24 additions & 15 deletions src/language/blockString.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,9 @@ export function dedentBlockStringValue(rawString: string): string {
const lines = rawString.split(/\r\n|[\n\r]/g);

// Remove common indentation from all lines but first.
let commonIndent = null;
for (let i = 1; i < lines.length; i++) {
const line = lines[i];
const indent = leadingWhitespace(line);
if (
indent < line.length &&
(commonIndent === null || indent < commonIndent)
) {
commonIndent = indent;
if (commonIndent === 0) {
break;
}
}
}
const commonIndent = getBlockStringIndentation(lines);

if (commonIndent) {
if (commonIndent !== 0) {
for (let i = 1; i < lines.length; i++) {
lines[i] = lines[i].slice(commonIndent);
}
Expand All @@ -51,6 +38,28 @@ export function dedentBlockStringValue(rawString: string): string {
return lines.join('\n');
}

// @internal
export function getBlockStringIndentation(lines: Array<string>): number {
let commonIndent = null;

for (let i = 1; i < lines.length; i++) {
const line = lines[i];
const indent = leadingWhitespace(line);
if (indent === line.length) {
continue; // skip empty lines
}

if (commonIndent === null || indent < commonIndent) {
commonIndent = indent;
if (commonIndent === 0) {
break;
}
}
}

return commonIndent === null ? 0 : commonIndent;
}

function leadingWhitespace(str) {
let i = 0;
while (i < str.length && (str[i] === ' ' || str[i] === '\t')) {
Expand Down

0 comments on commit c6e5ef2

Please sign in to comment.