Commit 42d632ef authored by Diegodlh's avatar Diegodlh
Browse files

Fix #T305900: Switch to one-based numbering

parent 2fef3392
...@@ -496,7 +496,7 @@ ...@@ -496,7 +496,7 @@
"config": { "config": {
"title": "Configuration", "title": "Configuration",
"description": "One or more comma-separated ranges: \"start(:end)\", \"start:\" or \":end\".", "description": "One or more comma-separated ranges: \"start(:end)\", \"start:\" or \":end\".",
"options": { "infoText": "Ranges are zero-based, meaning that the first item is item 0" }, "options": { "infoText": "Ranges use one-based numbering, meaning that the first item is item 1" },
"type": "string" "type": "string"
}, },
"itemwise": { "itemwise": {
......
...@@ -304,7 +304,7 @@ describe("Configuration revisions", () => { ...@@ -304,7 +304,7 @@ describe("Configuration revisions", () => {
transformations: [ transformations: [
{ {
type: "range", type: "range",
config: "0", config: "1",
itemwise: true, itemwise: true,
}, },
{ {
...@@ -361,7 +361,7 @@ describe("Configuration revisions", () => { ...@@ -361,7 +361,7 @@ describe("Configuration revisions", () => {
transformations: [ transformations: [
{ {
type: "range", type: "range",
config: "0", config: "1",
itemwise: true, itemwise: true,
}, },
], ],
......
...@@ -108,7 +108,7 @@ export const fallbackTemplate: FallbackTemplateDefinition = { ...@@ -108,7 +108,7 @@ export const fallbackTemplate: FallbackTemplateDefinition = {
"transformations": [ "transformations": [
{ {
"type": "range", "type": "range",
"config": "0", "config": "1",
"itemwise": false "itemwise": false
} }
] ]
......
...@@ -26,7 +26,7 @@ it("applies a translation procedure", () => { ...@@ -26,7 +26,7 @@ it("applies a translation procedure", () => {
new CitoidSelection("authorFirst"), new CitoidSelection("authorFirst"),
]; ];
procedure.transformations = [ procedure.transformations = [
new RangeTransformation(undefined, "1,2,0"), new RangeTransformation(undefined, "2,3,1"),
new JoinTransformation(), new JoinTransformation(),
]; ];
return procedure.translate(target).then((output) => { return procedure.translate(target).then((output) => {
...@@ -88,7 +88,7 @@ it("constructor optionally skips invalid translation step definitions", () => { ...@@ -88,7 +88,7 @@ it("constructor optionally skips invalid translation step definitions", () => {
transformations: [ transformations: [
{ {
type: "range", type: "range",
config: "0", config: "1",
itemwise: true, itemwise: true,
}, },
{ {
...@@ -115,7 +115,7 @@ it("constructor optionally skips invalid translation step definitions", () => { ...@@ -115,7 +115,7 @@ it("constructor optionally skips invalid translation step definitions", () => {
transformations: [ transformations: [
{ {
type: "range", type: "range",
config: "0", config: "1",
itemwise: true, itemwise: true,
}, },
], ],
......
...@@ -124,81 +124,81 @@ describe("Date transformation", () => { ...@@ -124,81 +124,81 @@ describe("Date transformation", () => {
}); });
describe("Range transformation", () => { describe("Range transformation", () => {
const input = ["zero", "one", "two", "three"]; const input = ["one", "two", "three", "four"];
it("selects single item", async () => { it("selects single item", async () => {
const transformation = new RangeTransformation(); const transformation = new RangeTransformation();
transformation.config = "1"; transformation.config = "2";
expect(await transformation.transform(input)).toEqual(["one"]); expect(await transformation.transform(input)).toEqual(["two"]);
transformation.config = "1:1"; transformation.config = "2:2";
expect(await transformation.transform(input)).toEqual(["one"]); expect(await transformation.transform(input)).toEqual(["two"]);
transformation.config = "1,"; transformation.config = "2,";
expect(await transformation.transform(input)).toEqual(["one"]); expect(await transformation.transform(input)).toEqual(["two"]);
}); });
it("selects multiple single items", async () => { it("selects multiple single items", async () => {
const transformation = new RangeTransformation(); const transformation = new RangeTransformation();
transformation.config = "1,0"; transformation.config = "2,1";
expect(await transformation.transform(input)).toEqual(["one", "zero"]); expect(await transformation.transform(input)).toEqual(["two", "one"]);
}); });
it("selects single range with start and end", async () => { it("selects single range with start and end", async () => {
const transformation = new RangeTransformation(); const transformation = new RangeTransformation();
transformation.config = "1:2"; transformation.config = "2:3";
expect(await transformation.transform(input)).toEqual(["one", "two"]); expect(await transformation.transform(input)).toEqual(["two", "three"]);
}); });
it("selects single range without end", async () => { it("selects single range without end", async () => {
const transformation = new RangeTransformation(); const transformation = new RangeTransformation();
transformation.config = "1:"; transformation.config = "2:";
expect(await transformation.transform(input)).toEqual([ expect(await transformation.transform(input)).toEqual([
"one",
"two", "two",
"three", "three",
"four",
]); ]);
}); });
it("selects single range without start", async () => { it("selects single range without start", async () => {
const transformation = new RangeTransformation(); const transformation = new RangeTransformation();
transformation.config = ":2"; transformation.config = ":3";
expect(await transformation.transform(input)).toEqual([ expect(await transformation.transform(input)).toEqual([
"zero",
"one", "one",
"two", "two",
"three",
]); ]);
}); });
it("selects multiple ranges", async () => { it("selects multiple ranges", async () => {
const transformation = new RangeTransformation(); const transformation = new RangeTransformation();
transformation.config = "1:2,:2, 1:"; transformation.config = "2:3,:3, 2:";
expect(await transformation.transform(input)).toEqual([ expect(await transformation.transform(input)).toEqual([
"one",
"two", "two",
"zero", "three",
"one", "one",
"two", "two",
"one", "three",
"two", "two",
"three", "three",
"four",
]); ]);
}); });
it("tolerates too wide ranges", async () => { it("tolerates too wide ranges", async () => {
const transformation = new RangeTransformation(); const transformation = new RangeTransformation();
transformation.config = "1:1000"; transformation.config = "2:1000";
expect(await transformation.transform(input)).toEqual([ expect(await transformation.transform(input)).toEqual([
"one",
"two", "two",
"three", "three",
"four",
]); ]);
transformation.config = "100:1000"; transformation.config = "100:1000";
expect(await transformation.transform(input)).toEqual([]); expect(await transformation.transform(input)).toEqual([]);
}); });
it("tolerates impossible ranges", async () => { it("tolerates impossible ranges", async () => {
const transformation = new RangeTransformation(); const transformation = new RangeTransformation();
transformation.config = "2:1"; transformation.config = "3:2";
expect(await transformation.transform(input)).toEqual([]); expect(await transformation.transform(input)).toEqual([]);
}); });
it("ignores empty range configurations", async () => { it("ignores empty range configurations", async () => {
const transformation = new RangeTransformation(); const transformation = new RangeTransformation();
transformation.config = ",1:2,,1"; transformation.config = ",2:3,,2";
expect(await transformation.transform(input)).toEqual([ expect(await transformation.transform(input)).toEqual([
"one",
"two", "two",
"one", "three",
"two",
]); ]);
transformation.config = ""; transformation.config = "";
expect(await transformation.transform(input)).toEqual([]); expect(await transformation.transform(input)).toEqual([]);
...@@ -220,6 +220,15 @@ describe("Range transformation", () => { ...@@ -220,6 +220,15 @@ describe("Range transformation", () => {
TransformationConfigTypeError TransformationConfigTypeError
); );
}); });
it("rejects zero indices", async () => {
const transformation = new RangeTransformation();
expect(() => (transformation.config = "0")).toThrow(
TransformationConfigTypeError
);
expect(() => (transformation.config = ":0")).toThrow(
TransformationConfigTypeError
);
});
}); });
describe("Match transformation", () => { describe("Match transformation", () => {
......
...@@ -192,7 +192,7 @@ function isDateConfig(config: string): config is DateConfig { ...@@ -192,7 +192,7 @@ function isDateConfig(config: string): config is DateConfig {
} }
export class RangeTransformation extends Transformation { export class RangeTransformation extends Transformation {
constructor(itemwise = false, range = "0:") { constructor(itemwise = false, range = "1:") {
super("range", itemwise); super("range", itemwise);
this.config = range; this.config = range;
} }
...@@ -201,7 +201,11 @@ export class RangeTransformation extends Transformation { ...@@ -201,7 +201,11 @@ export class RangeTransformation extends Transformation {
let ranges = config.replace(/\s/g, "").split(","); let ranges = config.replace(/\s/g, "").split(",");
// ignore empty ranges, i.e., successive commas // ignore empty ranges, i.e., successive commas
ranges = ranges.filter((range) => range); ranges = ranges.filter((range) => range);
if (ranges.every((range) => /^(\d+(:(\d+)?)?|:\d+)$/.test(range))) { if (
ranges.every((range) =>
/^([1-9]\d*(:([1-9]\d*)?)?|:[1-9]\d*)$/.test(range)
)
) {
this._config = ranges.join(","); this._config = ranges.join(",");
} else { } else {
throw new TransformationConfigTypeError(this.type, config); throw new TransformationConfigTypeError(this.type, config);
...@@ -241,12 +245,12 @@ export class RangeTransformation extends Transformation { ...@@ -241,12 +245,12 @@ export class RangeTransformation extends Transformation {
const [start, end] = rangeString.split(":"); const [start, end] = rangeString.split(":");
const range: Range = { const range: Range = {
// see https://github.com/microsoft/TypeScript/issues/41638 // see https://github.com/microsoft/TypeScript/issues/41638
start: start === "" ? 0 : parseInt(start as string), start: start === "" ? 0 : parseInt(start as string) - 1,
}; };
if (end === undefined) { if (end === undefined) {
range.end = range.start; range.end = range.start;
} else if (end !== "") { } else if (end !== "") {
range.end = parseInt(end); range.end = parseInt(end) - 1;
} }
ranges.push(range); ranges.push(range);
return ranges; return ranges;
......
...@@ -142,7 +142,7 @@ export abstract class TranslationField { ...@@ -142,7 +142,7 @@ export abstract class TranslationField {
{ type: "citoid", config: "code" }, { type: "citoid", config: "code" },
{ type: "citoid", config: "reporter" }, { type: "citoid", config: "reporter" },
], ],
transformations: [{ type: "range", config: "0", itemwise: false }], transformations: [{ type: "range", config: "1", itemwise: false }],
}, },
control: false, control: false,
}, },
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment