Skip to content

Commit c3d1e43

Browse files
committed
feat(src): add isEnd option
1 parent 604b25c commit c3d1e43

File tree

7 files changed

+2206
-36
lines changed

7 files changed

+2206
-36
lines changed

.babelrc

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
11
{
2-
"presets": ["es2015"]
2+
"presets": [
3+
"es2015"
4+
],
5+
"env": {
6+
"development": {
7+
"presets": [
8+
"power-assert"
9+
]
10+
}
11+
}
312
}

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ This library is for [textlint](https://github.com/textlint/textlint "textlint")
1414

1515
The concepts `position` and `index` are the same as those explained in [Constellation/structured-source](https://github.com/Constellation/structured-source).
1616

17-
Please pay extra attention to the `column` property of `position` as it is 0-based index
18-
and defferent from that of `textlint` which is 1-based index.
17+
**Note**: the `column` property of `position` as it is **0-based** index.
1918

2019
## Usage
2120

package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,23 @@
2222
"test": "test"
2323
},
2424
"scripts": {
25-
"build": "babel src --out-dir lib --source-maps",
25+
"build": "NODE_ENV=production babel src --out-dir lib --source-maps",
2626
"watch": "babel src --out-dir lib --watch --source-maps",
2727
"prepublish": "npm run --if-present build",
2828
"test": "mocha test"
2929
},
3030
"devDependencies": {
3131
"babel-cli": "^6.2.0",
3232
"babel-preset-es2015": "^6.1.18",
33-
"espower-babel": "^4.0.0",
34-
"markdown-to-ast": "^3.1.1",
33+
"babel-preset-power-assert": "^1.0.0",
34+
"babel-register": "^6.24.1",
35+
"markdown-to-ast": "^4.0.0",
3536
"mocha": "^3.0.2",
36-
"power-assert": "^1.2.0",
37+
"power-assert": "^1.4.2",
3738
"sentence-splitter": "^2.0.0"
3839
},
3940
"dependencies": {
4041
"object-assign": "^4.0.1",
4142
"structured-source": "^3.0.2"
4243
}
43-
}
44+
}

src/StringSource.js

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"use strict";
33
import ObjectAssign from "object-assign";
44
import StructuredSource from "structured-source";
5+
56
export default class StringSource {
67
constructor(node) {
78
this.rootNode = node;
@@ -21,7 +22,7 @@ export default class StringSource {
2122
// intermediate = trim decoration from Original
2223
// e.g.) [2, 5]
2324
intermediate: [start, end]
24-
// generaged value = "Str"
25+
// generated value = "Str"
2526
// e.g.) [0, 3]
2627
generated : [start, end]
2728
}]
@@ -43,24 +44,27 @@ export default class StringSource {
4344
/**
4445
* @deprecated use originalPositionFromPosition instead of
4546
* @param generatedPosition
47+
* @param {boolean} isEnd - is the position end of the node?
48+
4649
* @returns {Object}
4750
*/
48-
originalPositionFor(generatedPosition) {
49-
return this.originalPositionFromPosition(generatedPosition);
51+
originalPositionFor(generatedPosition, isEnd) {
52+
return this.originalPositionFromPosition(generatedPosition, isEnd);
5053
}
5154

5255
/**
5356
* get original index from generated index value
5457
* @param {number} generatedIndex - position is a index value.
58+
* @param {boolean} isEnd - is the position end of the node?
5559
* @returns {number|undefined} original
5660
*/
57-
originalIndexFromIndex(generatedIndex) {
61+
originalIndexFromIndex(generatedIndex, isEnd = false) {
5862
let hitTokenMaps = this.tokenMaps.filter((tokenMap, index) => {
5963
const generated = tokenMap.generated;
6064
const nextTokenMap = this.tokenMaps[index + 1];
6165
const nextGenerated = nextTokenMap ? nextTokenMap.generated : null;
6266
if (nextGenerated) {
63-
if (generated[0] <= generatedIndex && generatedIndex < nextGenerated[0]) {
67+
if (generated[0] <= generatedIndex && generatedIndex <= nextGenerated[0]) {
6468
return true;
6569
}
6670
} else {
@@ -72,57 +76,70 @@ export default class StringSource {
7276
if (hitTokenMaps.length === 0) {
7377
return;
7478
}
75-
// a bcd
76-
// b = index 1
77-
// original `a` bcd
78-
// originalRange [3, 7]
79-
// adjustedStart = 1
80-
// b's index = 3 + 1
81-
let hitTokenMap = hitTokenMaps[0];
82-
// <----------->\[<------------->|text]
79+
80+
/**
81+
* **Str**ABC
82+
* |
83+
* |
84+
* generatedIndex
85+
*
86+
* If isEnd is true, generatedIndex is end of **Str** node.
87+
* If isEnd is false, generatedIndex is index of ABC node.
88+
*/
89+
90+
const hitTokenMap = isEnd ? hitTokenMaps[0] : hitTokenMaps[hitTokenMaps.length - 1];
91+
// <----------->[<------------->|text]
8392
// ^ ^
8493
// position-generated intermediate-origin
85-
let outAdjust = generatedIndex - hitTokenMap.generated[0];
86-
let inAdjust = hitTokenMap.intermediate[0] - hitTokenMap.original[0];
87-
return outAdjust + inAdjust + hitTokenMap.original[0];
94+
95+
// <-------------->[<------------->|text]
96+
// | |
97+
// outer adjust _
98+
// inner adjust = 1
99+
const outerAdjust = generatedIndex - hitTokenMap.generated[0];
100+
const innerAdjust = hitTokenMap.intermediate[0] - hitTokenMap.original[0];
101+
return outerAdjust + innerAdjust + hitTokenMap.original[0];
88102
}
89103

90104
/**
91105
* get original position from generated position
92106
* @param {object} position
107+
* @param {boolean} isEnd - is the position end of the node?
93108
* @returns {object} original position
94109
*/
95-
originalPositionFromPosition(position) {
110+
originalPositionFromPosition(position, isEnd = false) {
96111
if (typeof position.line === "undefined" || typeof position.column === "undefined") {
97112
throw new Error("position.{line, column} should not undefined: " + JSON.stringify(position));
98113
}
99-
var generatedIndex = this.generatedSource.positionToIndex(position);
114+
const generatedIndex = this.generatedSource.positionToIndex(position);
100115
if (isNaN(generatedIndex)) {
101116
// Not Found
102117
return;
103118
}
104-
let originalIndex = this.originalIndexFromIndex(generatedIndex);
105-
return this.originalSource.indexToPosition(originalIndex);
119+
const originalIndex = this.originalIndexFromIndex(generatedIndex, isEnd);
120+
return this.originalSource.indexToPosition(originalIndex, isEnd);
106121
}
107122

108123
/**
109124
* get original index from generated position
110125
* @param {object} generatedPosition
126+
* @param {boolean} isEnd - is the position end of the node?
111127
* @returns {number} original index
112128
*/
113-
originalIndexFromPosition(generatedPosition) {
129+
originalIndexFromPosition(generatedPosition, isEnd = false) {
114130
const originalPosition = this.originalPositionFromPosition(generatedPosition);
115-
return this.originalSource.positionToIndex(originalPosition);
131+
return this.originalSource.positionToIndex(originalPosition, isEnd);
116132
}
117133

118134
/**
119135
* get original position from generated index
120136
* @param {number} generatedIndex
137+
* @param {boolean} isEnd - is the position end of the node?
121138
* @return {object} original position
122139
*/
123-
originalPositionFromIndex(generatedIndex) {
140+
originalPositionFromIndex(generatedIndex, isEnd = false) {
124141
let originalIndex = this.originalIndexFromIndex(generatedIndex);
125-
return this.originalSource.indexToPosition(originalIndex);
142+
return this.originalSource.indexToPosition(originalIndex, isEnd);
126143
}
127144

128145

test/StringSource-test.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
// LICENSE : MIT
22
"use strict";
3-
import assert from "power-assert"
4-
import {parse} from "markdown-to-ast";
3+
import assert from "assert"
4+
import { parse } from "markdown-to-ast";
55
import StringSource from "../src/StringSource";
6-
import {split as sentenceSplitter} from "sentence-splitter";
6+
import { split as sentenceSplitter } from "sentence-splitter";
7+
78
describe("StringSource", function() {
89
describe("#toString", function() {
910
it("should concat string", function() {
@@ -174,12 +175,20 @@ describe("StringSource", function() {
174175
});
175176

176177
describe("#originalIndexFromIndex", function() {
178+
it("should correct **match** at end", function() {
179+
const AST = parse("**match** text");
180+
const source = new StringSource(AST);
181+
assert.equal(source.originalIndexFromIndex(0), 2);
182+
// isEnd
183+
assert.equal(source.originalIndexFromIndex(5, true), 7);
184+
});
177185
it("Str + Link", function() {
178186
var originalText = "This is [Example!?](http://example.com/)";
179187
let AST = parse(originalText);
180188
let source = new StringSource(AST);
181189
let result = source.toString();
182190
assert.equal(result, "This is Example!?");
191+
assert.ok(originalText.slice(9, 16) === "Example");
183192
var index1 = result.indexOf("Example");
184193
assert.equal(index1, 8);
185194
assert.equal(source.originalIndexFromIndex(index1), 9);

test/mocha.opts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
--compilers js:espower-babel/guess
1+
--compilers js:babel-register

0 commit comments

Comments
 (0)