diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4c4069fd6..f2be97297 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,7 +5,8 @@ All notable changes to this project will be documented in this file. For change
- put future changes here
- Improve chinese translation
-- Standardize on capitalizeFirstLetter meta key
+- Standardize capitalizeFirstLetter meta key
+- Change instructions object customization to options.hooks.tokenizedInstruction
# 0.0.7 2016-11-10
diff --git a/Readme.md b/Readme.md
index 96405aad9..0e8bb9f17 100644
--- a/Readme.md
+++ b/Readme.md
@@ -18,7 +18,10 @@ osrm-text-instructions transforms OSRM route responses into text instructions. I
### Javascript Usage
```
-var osrmTextInstructions = require('osrm-text-instructions')('v5', 'en');
+var version = 'v5';
+var language = 'en';
+var options = {};
+var osrmTextInstructions = require('osrm-text-instructions')(version, language, options);
// make your request against the API
@@ -29,6 +32,12 @@ response.legs.forEach(function(leg) {
});
```
+parameter | required? | values | description
+---|----|----|---
+`version` | required | `v5` | Major OSRM version
+`language` | required | `en` `de` `zh-Hans` `fr` `nl` | Language identifier
+`options.hooks.tokenizedIstruction` | optional | `function(instruction)` | A function to change the raw instruction string before tokens are replaced. Useful to inject custom markup for tokens
+
### Development
#### Architecture
diff --git a/index.js b/index.js
index 3508b59fc..169f5f447 100644
--- a/index.js
+++ b/index.js
@@ -1,17 +1,16 @@
-module.exports = function(version, language) {
+module.exports = function(version, language, options) {
+ // load instructions
var instructions = require('./instructions').get(language);
if (Object !== instructions.constructor) throw 'instructions must be object';
-
if (!instructions[version]) { throw 'invalid version ' + version; }
- var o = {
- instructions: instructions,
+ return {
capitalizeFirstLetter: function(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
},
ordinalize: function(number) {
// Transform numbers to their translated ordinalized value
- return this.instructions[version].constants.ordinalize[number.toString()] || '';
+ return instructions[version].constants.ordinalize[number.toString()] || '';
},
directionFromDegree: function(degree) {
// Transform degrees to their translated compass direction
@@ -19,23 +18,23 @@ module.exports = function(version, language) {
// step had no bearing_after degree, ignoring
return '';
} else if (degree >= 0 && degree <= 20) {
- return this.instructions[version].constants.direction.north;
+ return instructions[version].constants.direction.north;
} else if (degree > 20 && degree < 70) {
- return this.instructions[version].constants.direction.northeast;
+ return instructions[version].constants.direction.northeast;
} else if (degree >= 70 && degree < 110) {
- return this.instructions[version].constants.direction.east;
+ return instructions[version].constants.direction.east;
} else if (degree >= 110 && degree <= 160) {
- return this.instructions[version].constants.direction.southeast;
+ return instructions[version].constants.direction.southeast;
} else if (degree > 160 && degree <= 200) {
- return this.instructions[version].constants.direction.south;
+ return instructions[version].constants.direction.south;
} else if (degree > 200 && degree < 250) {
- return this.instructions[version].constants.direction.southwest;
+ return instructions[version].constants.direction.southwest;
} else if (degree >= 250 && degree <= 290) {
- return this.instructions[version].constants.direction.west;
+ return instructions[version].constants.direction.west;
} else if (degree > 290 && degree < 340) {
- return this.instructions[version].constants.direction.northwest;
+ return instructions[version].constants.direction.northwest;
} else if (degree >= 340 && degree <= 360) {
- return this.instructions[version].constants.direction.north;
+ return instructions[version].constants.direction.north;
} else {
throw new Error('Degree ' + degree + ' invalid');
}
@@ -70,7 +69,7 @@ module.exports = function(version, language) {
if (!type) { throw new Error('Missing step maneuver type'); }
if (type !== 'depart' && type !== 'arrive' && !modifier) { throw new Error('Missing step maneuver modifier'); }
- if (!this.instructions[version][type]) {
+ if (!instructions[version][type]) {
// Log for debugging
console.log('Encountered unknown instruction type: ' + type); // eslint-disable-line no-console
// OSRM specification assumes turn types can be added without
@@ -79,25 +78,25 @@ module.exports = function(version, language) {
type = 'turn';
}
- // Use special this.instructions if available, otherwise `defaultinstruction`
+ // Use special instructions if available, otherwise `defaultinstruction`
var instructionObject;
- if (this.instructions[version].modes[mode]) {
- instructionObject = this.instructions[version].modes[mode];
- } else if (this.instructions[version][type][modifier]) {
- instructionObject = this.instructions[version][type][modifier];
+ if (instructions[version].modes[mode]) {
+ instructionObject = instructions[version].modes[mode];
+ } else if (instructions[version][type][modifier]) {
+ instructionObject = instructions[version][type][modifier];
} else {
- instructionObject = this.instructions[version][type].default;
+ instructionObject = instructions[version][type].default;
}
// Special case handling
var laneInstruction;
switch (type) {
case 'use lane':
- laneInstruction = this.instructions[version].constants.lanes[this.laneConfig(step)];
+ laneInstruction = instructions[version].constants.lanes[this.laneConfig(step)];
if (!laneInstruction) {
// If the lane combination is not found, default to continue straight
- instructionObject = this.instructions[version]['use lane'].no_lanes;
+ instructionObject = instructions[version]['use lane'].no_lanes;
}
break;
case 'rotary':
@@ -148,6 +147,11 @@ module.exports = function(version, language) {
instruction = instructionObject.default;
}
+ var tokenizedInstructionHook = ((options || {}).hooks || {}).tokenizedInstruction;
+ if (tokenizedInstructionHook) {
+ instruction = tokenizedInstructionHook(instruction);
+ }
+
// Replace tokens
// NOOP if they don't exist
var nthWaypoint = ''; // TODO, add correct waypoint counting
@@ -157,18 +161,16 @@ module.exports = function(version, language) {
.replace('{exit_number}', this.ordinalize(step.maneuver.exit || 1))
.replace('{rotary_name}', step.rotary_name)
.replace('{lane_instruction}', laneInstruction)
- .replace('{modifier}', this.instructions[version].constants.modifier[modifier])
+ .replace('{modifier}', instructions[version].constants.modifier[modifier])
.replace('{direction}', this.directionFromDegree(step.maneuver.bearing_after))
.replace('{nth}', nthWaypoint)
.replace(/ {2}/g, ' '); // remove excess spaces
- if (this.instructions.meta.capitalizeFirstLetter) {
+ if (instructions.meta.capitalizeFirstLetter) {
instruction = this.capitalizeFirstLetter(instruction);
}
return instruction;
}
};
-
- return o;
};
diff --git a/test/index_test.js b/test/index_test.js
index 7295e1781..6e2962dee 100644
--- a/test/index_test.js
+++ b/test/index_test.js
@@ -115,4 +115,23 @@ tape.test('v5 compile', function(t) {
assert.end();
});
+
+ t.test('respects options.instructionStringHook', function(assert) {
+ var v5Instructions = instructions('v5', 'en', {
+ hooks: {
+ tokenizedInstruction: function(instruction) {
+ return instruction.replace('{way_name}', '');
+ }
+ }
+ });
+
+ assert.equal(v5Instructions.compile({
+ "maneuver": {
+ "type": "turn",
+ "modifier": "left"
+ },
+ "name": "Way Name"
+ }), 'Turn left onto ');
+ assert.end();
+ });
});