1 module.exports.formatOSMType = formatOSMType;
2 module.exports.formatShortOSMType = formatShortOSMType;
3 module.exports.osmLink = osmLink;
4 module.exports.formatLabel = formatLabel;
5 module.exports.detailsURL = detailsURL;
6 module.exports.wikipediaLink = wikipediaLink;
7 module.exports.coverageType = coverageType;
8 module.exports.isAdminBoundary = isAdminBoundary;
9 module.exports.formatAddressRank = formatAddressRank;
10 module.exports.formatPlaceType = formatPlaceType;
11 module.exports.formatAdminLevel = formatAdminLevel;
12 module.exports.formatDistance = formatDistance;
13 module.exports.formatKeywordToken = formatKeywordToken;
14 module.exports.zoomLevels = zoomLevels;
16 const escapeHtml = require('escape-html');
18 function formatOSMType(sType, bExcludeExternal) {
19 if (sType === 'N') return 'node';
20 if (sType === 'W') return 'way';
21 if (sType === 'R') return 'relation';
23 if (!bExcludeExternal) return '';
25 if (sType === 'T') return 'way';
26 if (sType === 'I') return 'way';
31 function formatShortOSMType(sType) {
32 if (sType === 'node') return 'N';
33 if (sType === 'way') return 'W';
34 if (sType === 'relation') return 'R';
38 function osmLink(aPlace) {
39 if (!aPlace.osm_type) return '';
40 var sOSMType = formatOSMType(aPlace.osm_type, false);
41 if (!sOSMType) return '';
43 return '<a href="https://www.openstreetmap.org/' + sOSMType + '/' + aPlace.osm_id + '">' + sOSMType + ' ' + aPlace.osm_id + '</a>'
46 function formatLabel(aPlace) {
47 if (aPlace.label) return aPlace.label;
49 function capitalize(s) {
50 return s && s[0].toUpperCase() + s.slice(1);
53 if (aPlace.type && aPlace.type === 'yes' && aPlace.class) {
54 return capitalize(aPlace.class.replace(/_/g, ' '));
57 return capitalize(aPlace.type.replace(/_/g, ' '));
62 // 'details.html?osmtype=R&osmid=2181874&class=boundary'
63 function detailsURL(aFeature) {
64 if (!aFeature) return '';
66 var sOSMType = aFeature.osm_type;
67 if (sOSMType && sOSMType.length !== 1) {
68 sOSMType = formatShortOSMType(aFeature.osm_type, false); // node => N
70 if (!sOSMType) return '';
72 var sURL = 'details.html?osmtype=' + sOSMType + '&osmid=' + aFeature.osm_id;
74 sURL = sURL + '&class=' + encodeURIComponent(aFeature.class);
75 } else if (aFeature.category) {
76 sURL = sURL + '&class=' +encodeURIComponent(aFeature.category);
81 /* en:London_Borough_of_Redbridge => https://en.wikipedia.org/wiki/London_Borough_of_Redbridge */
82 function wikipediaLink(aPlace) {
83 if (!aPlace.calculated_wikipedia) return '';
85 var parts = aPlace.calculated_wikipedia.split(':', 2);
87 var sTitle = escapeHtml(aPlace.calculated_wikipedia);
88 var sLanguage = escapeHtml(parts[0]);
89 var sArticle = escapeHtml(parts[1]);
91 return '<a href="https://' + sLanguage + '.wikipedia.org/wiki/' + sArticle + '" target="_blank">' + sTitle + '</a>';
94 function coverageType(aPlace) {
95 return (aPlace.isarea ? 'Polygon' : 'Point');
98 function isAdminBoundary(aPlace) {
99 return aPlace.category === 'boundary' && aPlace.type === 'administrative';
102 function formatAddressRank(iRank) {
103 if (iRank < 4) return 'other';
104 if (iRank < 6) return 'country';
105 if (iRank < 8) return 'region';
106 if (iRank < 10) return 'state';
107 if (iRank < 12) return 'state district';
108 if (iRank < 14) return 'county';
109 if (iRank < 16) return 'municipality';
110 if (iRank < 18) return 'city / town / village';
111 if (iRank < 20) return 'city / village district';
112 if (iRank < 22) return 'suburb / hamlet';
113 if (iRank < 24) return 'neighbourhood';
114 if (iRank < 26) return 'city block / square';
115 if (iRank === 26) return 'major street';
116 if (iRank === 27) return 'minory street / path';
117 if (iRank <= 30) return 'house / building';
121 function formatPlaceType(aPlace) {
122 var sOut = aPlace.class + ':' + aPlace.type;
123 if (aPlace.type && aPlace.type === 'administrative' && aPlace.place_type) {
124 sOut = sOut + ' (' + aPlace.place_type + ')';
126 return escapeHtml(sOut);
129 // Any over 15 are invalid data in OSM anyway
130 function formatAdminLevel(iLevel) {
131 return (iLevel < 15 ? iLevel : '');
134 function formatDistance(fDistance, bInMeters) {
136 if (fDistance < 1) return '0';
137 var sFormatted = (fDistance >= 1000)
138 ? Math.round(fDistance / 1000, 1) + ' km'
139 : Math.round(fDistance, 0) + ' m';
141 return '<abbr class="distance" title="' + fDistance + ' meters">~' + sFormatted + '</abbr>';
144 // spheric distance, http://postgis.net/docs/ST_Distance_Spheroid.html
145 if (fDistance === 0) return '0';
147 return '<abbr class="distance" title="spheric distance ' + fDistance + '">~'
148 + (Math.round(fDistance * 1000, 4) / 1000)
152 // mark partial tokens (those starting with a space) with a star for readability
153 function formatKeywordToken(sToken) {
154 return (sToken[0] === ' ' ? '*' : '') + escapeHtml(sToken);
157 function zoomLevels() {
158 const aZoomLevels = [
159 /* 0 */ 'Continent / Sea',
171 /* 12 */ 'Town / Village',