umap-project 2.1.3__py3-none-any.whl → 2.2.0b0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of umap-project might be problematic. Click here for more details.
- umap/__init__.py +1 -1
- umap/context_processors.py +1 -0
- umap/locale/br/LC_MESSAGES/django.mo +0 -0
- umap/locale/en/LC_MESSAGES/django.po +32 -32
- umap/locale/hu/LC_MESSAGES/django.mo +0 -0
- umap/locale/it/LC_MESSAGES/django.mo +0 -0
- umap/locale/ms/LC_MESSAGES/django.mo +0 -0
- umap/migrations/0020_alter_tilelayer_url_template.py +19 -0
- umap/migrations/0021_remove_map_description.py +16 -0
- umap/models.py +8 -6
- umap/settings/base.py +1 -0
- umap/static/umap/base.css +29 -151
- umap/static/umap/content.css +7 -25
- umap/static/umap/css/icon.css +112 -0
- umap/static/umap/css/panel.css +140 -0
- umap/static/umap/img/16-white.svg +5 -1
- umap/static/umap/img/16.svg +7 -4
- umap/static/umap/img/24-white.svg +3 -1
- umap/static/umap/img/24.svg +3 -4
- umap/static/umap/img/source/16-white.svg +176 -940
- umap/static/umap/img/source/16.svg +8 -5
- umap/static/umap/img/source/24-white.svg +5 -3
- umap/static/umap/img/source/24.svg +6 -7
- umap/static/umap/js/modules/browser.js +82 -73
- umap/static/umap/js/modules/dompurify.js +12 -0
- umap/static/umap/js/modules/facets.js +148 -0
- umap/static/umap/js/modules/global.js +9 -1
- umap/static/umap/js/modules/i18n.js +7 -0
- umap/static/umap/js/modules/orderable.js +84 -0
- umap/static/umap/js/modules/panel.js +76 -0
- umap/static/umap/js/modules/request.js +0 -1
- umap/static/umap/js/modules/schema.js +324 -223
- umap/static/umap/js/modules/urls.js +1 -16
- umap/static/umap/js/modules/utils.js +340 -0
- umap/static/umap/js/umap.controls.js +183 -330
- umap/static/umap/js/umap.core.js +60 -364
- umap/static/umap/js/umap.datalayer.permissions.js +1 -1
- umap/static/umap/js/umap.features.js +60 -40
- umap/static/umap/js/umap.forms.js +111 -25
- umap/static/umap/js/umap.icon.js +11 -4
- umap/static/umap/js/umap.importer.js +24 -17
- umap/static/umap/js/umap.js +170 -145
- umap/static/umap/js/umap.layer.js +71 -40
- umap/static/umap/js/umap.permissions.js +9 -11
- umap/static/umap/js/umap.popup.js +10 -21
- umap/static/umap/js/umap.share.js +11 -8
- umap/static/umap/js/umap.tableeditor.js +4 -6
- umap/static/umap/js/umap.ui.js +0 -51
- umap/static/umap/locale/am_ET.js +242 -227
- umap/static/umap/locale/am_ET.json +18 -7
- umap/static/umap/locale/ar.js +242 -227
- umap/static/umap/locale/ar.json +18 -7
- umap/static/umap/locale/ast.js +242 -227
- umap/static/umap/locale/ast.json +18 -7
- umap/static/umap/locale/bg.js +242 -227
- umap/static/umap/locale/bg.json +18 -7
- umap/static/umap/locale/br.js +252 -237
- umap/static/umap/locale/br.json +22 -11
- umap/static/umap/locale/ca.js +242 -227
- umap/static/umap/locale/ca.json +18 -7
- umap/static/umap/locale/cs_CZ.js +242 -227
- umap/static/umap/locale/cs_CZ.json +18 -7
- umap/static/umap/locale/da.js +242 -227
- umap/static/umap/locale/da.json +18 -7
- umap/static/umap/locale/de.js +242 -227
- umap/static/umap/locale/de.json +18 -7
- umap/static/umap/locale/el.js +242 -227
- umap/static/umap/locale/el.json +18 -7
- umap/static/umap/locale/en.js +242 -234
- umap/static/umap/locale/en.json +19 -8
- umap/static/umap/locale/en_US.json +18 -7
- umap/static/umap/locale/es.js +242 -227
- umap/static/umap/locale/es.json +18 -7
- umap/static/umap/locale/et.js +242 -227
- umap/static/umap/locale/et.json +18 -7
- umap/static/umap/locale/eu.js +227 -199
- umap/static/umap/locale/eu.json +1 -1
- umap/static/umap/locale/fa_IR.js +242 -227
- umap/static/umap/locale/fa_IR.json +18 -7
- umap/static/umap/locale/fi.js +242 -227
- umap/static/umap/locale/fi.json +18 -7
- umap/static/umap/locale/fr.js +242 -234
- umap/static/umap/locale/fr.json +18 -7
- umap/static/umap/locale/gl.js +242 -227
- umap/static/umap/locale/gl.json +18 -7
- umap/static/umap/locale/he.js +242 -227
- umap/static/umap/locale/he.json +18 -7
- umap/static/umap/locale/hr.js +242 -227
- umap/static/umap/locale/hr.json +18 -7
- umap/static/umap/locale/hu.js +242 -234
- umap/static/umap/locale/hu.json +18 -7
- umap/static/umap/locale/id.js +242 -227
- umap/static/umap/locale/id.json +18 -7
- umap/static/umap/locale/is.js +242 -227
- umap/static/umap/locale/is.json +18 -7
- umap/static/umap/locale/it.js +242 -234
- umap/static/umap/locale/it.json +18 -7
- umap/static/umap/locale/ja.js +242 -227
- umap/static/umap/locale/ja.json +18 -7
- umap/static/umap/locale/ko.js +242 -227
- umap/static/umap/locale/ko.json +18 -7
- umap/static/umap/locale/lt.js +242 -227
- umap/static/umap/locale/lt.json +18 -7
- umap/static/umap/locale/ms.js +242 -234
- umap/static/umap/locale/ms.json +19 -8
- umap/static/umap/locale/nl.js +245 -230
- umap/static/umap/locale/nl.json +18 -7
- umap/static/umap/locale/no.js +242 -227
- umap/static/umap/locale/no.json +18 -7
- umap/static/umap/locale/pl.js +242 -227
- umap/static/umap/locale/pl.json +18 -7
- umap/static/umap/locale/pl_PL.json +18 -7
- umap/static/umap/locale/pt.js +242 -227
- umap/static/umap/locale/pt.json +18 -7
- umap/static/umap/locale/pt_BR.js +242 -227
- umap/static/umap/locale/pt_BR.json +18 -7
- umap/static/umap/locale/pt_PT.js +242 -227
- umap/static/umap/locale/pt_PT.json +18 -7
- umap/static/umap/locale/ro.js +242 -227
- umap/static/umap/locale/ro.json +18 -7
- umap/static/umap/locale/ru.js +242 -227
- umap/static/umap/locale/ru.json +18 -7
- umap/static/umap/locale/si.js +1 -1
- umap/static/umap/locale/si.json +1 -1
- umap/static/umap/locale/sk_SK.js +242 -227
- umap/static/umap/locale/sk_SK.json +18 -7
- umap/static/umap/locale/sl.js +242 -227
- umap/static/umap/locale/sl.json +18 -7
- umap/static/umap/locale/sr.js +242 -227
- umap/static/umap/locale/sr.json +18 -7
- umap/static/umap/locale/sv.js +242 -227
- umap/static/umap/locale/sv.json +18 -7
- umap/static/umap/locale/th_TH.js +242 -227
- umap/static/umap/locale/th_TH.json +18 -7
- umap/static/umap/locale/tr.js +242 -227
- umap/static/umap/locale/tr.json +18 -7
- umap/static/umap/locale/uk_UA.js +242 -227
- umap/static/umap/locale/uk_UA.json +18 -7
- umap/static/umap/locale/vi.js +242 -227
- umap/static/umap/locale/vi.json +18 -7
- umap/static/umap/locale/vi_VN.json +18 -7
- umap/static/umap/locale/zh.js +242 -227
- umap/static/umap/locale/zh.json +18 -7
- umap/static/umap/locale/zh_CN.json +18 -7
- umap/static/umap/locale/zh_TW.Big5.json +18 -7
- umap/static/umap/locale/zh_TW.js +242 -234
- umap/static/umap/locale/zh_TW.json +18 -7
- umap/static/umap/map.css +114 -265
- umap/static/umap/test/DataLayer.js +463 -0
- umap/static/umap/test/Feature.js +0 -226
- umap/static/umap/test/TableEditor.js +104 -0
- umap/static/umap/test/Util.js +0 -521
- umap/static/umap/test/index.html +0 -1
- umap/static/umap/unittests/URLs.js +1 -1
- umap/static/umap/unittests/utils.js +610 -0
- umap/static/umap/vars.css +9 -0
- umap/static/umap/vendors/dompurify/purify.es.mjs +1525 -0
- umap/static/umap/vendors/iconlayers/iconLayers.js +1 -1
- umap/templates/umap/css.html +2 -0
- umap/templates/umap/js.html +0 -1
- umap/templates/umap/map_detail.html +4 -0
- umap/templates/umap/map_table.html +12 -10
- umap/templatetags/umap_tags.py +5 -0
- umap/tests/integration/conftest.py +12 -1
- umap/tests/integration/test_anonymous_owned_map.py +6 -5
- umap/tests/integration/test_browser.py +12 -25
- umap/tests/integration/test_choropleth.py +1 -1
- umap/tests/integration/test_dashboard.py +10 -0
- umap/tests/integration/test_datalayer.py +8 -6
- umap/tests/integration/test_edit_datalayer.py +24 -19
- umap/tests/integration/test_edit_map.py +182 -2
- umap/tests/integration/test_edit_marker.py +120 -0
- umap/tests/integration/test_edit_polygon.py +122 -0
- umap/tests/integration/test_facets_browser.py +104 -14
- umap/tests/integration/test_import.py +70 -20
- umap/tests/integration/test_map.py +19 -17
- umap/tests/integration/test_map_list.py +28 -0
- umap/tests/integration/test_owned_map.py +10 -10
- umap/tests/integration/test_picto.py +5 -5
- umap/tests/integration/test_querystring.py +9 -15
- umap/tests/integration/test_slideshow.py +0 -5
- umap/tests/integration/test_statics.py +3 -2
- umap/tests/integration/test_tableeditor.py +1 -5
- umap/tests/integration/test_view_marker.py +64 -0
- umap/tests/integration/test_view_polygon.py +59 -0
- umap/tests/integration/test_view_polyline.py +51 -0
- umap/tests/test_map_views.py +13 -0
- {umap_project-2.1.3.dist-info → umap_project-2.2.0b0.dist-info}/METADATA +8 -8
- {umap_project-2.1.3.dist-info → umap_project-2.2.0b0.dist-info}/RECORD +194 -178
- umap/static/umap/vendors/dompurify/purify.min.js +0 -3
- umap/static/umap/vendors/dompurify/purify.min.js.map +0 -1
- /umap/tests/integration/{test_polygon.py → test_draw_polygon.py} +0 -0
- /umap/tests/integration/{test_polyline.py → test_draw_polyline.py} +0 -0
- {umap_project-2.1.3.dist-info → umap_project-2.2.0b0.dist-info}/WHEEL +0 -0
- {umap_project-2.1.3.dist-info → umap_project-2.2.0b0.dist-info}/entry_points.txt +0 -0
- {umap_project-2.1.3.dist-info → umap_project-2.2.0b0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,19 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
// https://github.com/Leaflet/Leaflet/blob/108c6717b70f57c63645498f9bd66b6677758786/src/core/Util.js#L132-L151
|
|
3
|
-
var templateRe = /\{ *([\w_ -]+) *\}/g
|
|
4
|
-
|
|
5
|
-
function template(str, data) {
|
|
6
|
-
return str.replace(templateRe, function (str, key) {
|
|
7
|
-
var value = data[key]
|
|
8
|
-
|
|
9
|
-
if (value === undefined) {
|
|
10
|
-
throw new Error('No value provided for variable ' + str)
|
|
11
|
-
} else if (typeof value === 'function') {
|
|
12
|
-
value = value(data)
|
|
13
|
-
}
|
|
14
|
-
return value
|
|
15
|
-
})
|
|
16
|
-
}
|
|
1
|
+
import { template } from "./utils.js"
|
|
17
2
|
|
|
18
3
|
export default class URLs {
|
|
19
4
|
constructor(serverUrls) {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { default as DOMPurifyInitializer } from '../../vendors/dompurify/purify.es.mjs'
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Generate a pseudo-unique identifier (5 chars long, mixed-case alphanumeric)
|
|
3
5
|
*
|
|
@@ -22,3 +24,341 @@ export function checkId(string) {
|
|
|
22
24
|
if (typeof string !== 'string') return false
|
|
23
25
|
return /^[A-Za-z0-9]{5}$/.test(string)
|
|
24
26
|
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Compute the impacts for a given list of fields.
|
|
30
|
+
*
|
|
31
|
+
* Return an array of unique impacts.
|
|
32
|
+
*
|
|
33
|
+
* @param {fields} list[fields]
|
|
34
|
+
* @returns Array[string]
|
|
35
|
+
*/
|
|
36
|
+
export function getImpactsFromSchema(fields, schema) {
|
|
37
|
+
schema = schema || U.SCHEMA
|
|
38
|
+
let impacted = fields
|
|
39
|
+
.map((field) => {
|
|
40
|
+
// remove the option prefix for fields
|
|
41
|
+
// And only keep the first part in case of a subfield
|
|
42
|
+
// (e.g "options.limitBounds.foobar" will just return "limitBounds")
|
|
43
|
+
return field.replace('options.', '').split('.')[0]
|
|
44
|
+
})
|
|
45
|
+
.reduce((acc, field) => {
|
|
46
|
+
// retrieve the "impacts" field from the schema
|
|
47
|
+
// and merge them together using sets
|
|
48
|
+
const impacts = schema[field]?.impacts || []
|
|
49
|
+
impacts.forEach((impact) => acc.add(impact))
|
|
50
|
+
return acc
|
|
51
|
+
}, new Set())
|
|
52
|
+
|
|
53
|
+
return Array.from(impacted)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Import DOM purify, and initialize it.
|
|
58
|
+
*
|
|
59
|
+
* If the context is a node server, uses jsdom to provide
|
|
60
|
+
* DOM APIs
|
|
61
|
+
*/
|
|
62
|
+
export default function getPurify() {
|
|
63
|
+
if (typeof window === 'undefined') {
|
|
64
|
+
return DOMPurifyInitializer(new global.JSDOM('').window)
|
|
65
|
+
} else {
|
|
66
|
+
return DOMPurifyInitializer(window)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function escapeHTML(s) {
|
|
71
|
+
s = s ? s.toString() : ''
|
|
72
|
+
s = getPurify().sanitize(s, {
|
|
73
|
+
USE_PROFILES: { html: true },
|
|
74
|
+
ADD_TAGS: ['iframe'],
|
|
75
|
+
ALLOWED_TAGS: [
|
|
76
|
+
'h3',
|
|
77
|
+
'h4',
|
|
78
|
+
'h5',
|
|
79
|
+
'hr',
|
|
80
|
+
'strong',
|
|
81
|
+
'em',
|
|
82
|
+
'ul',
|
|
83
|
+
'li',
|
|
84
|
+
'a',
|
|
85
|
+
'div',
|
|
86
|
+
'iframe',
|
|
87
|
+
'img',
|
|
88
|
+
'br',
|
|
89
|
+
],
|
|
90
|
+
ADD_ATTR: ['target', 'allow', 'allowfullscreen', 'frameborder', 'scrolling'],
|
|
91
|
+
ALLOWED_ATTR: ['href', 'src', 'width', 'height'],
|
|
92
|
+
// Added: `geo:` URL scheme as defined in RFC5870:
|
|
93
|
+
// https://www.rfc-editor.org/rfc/rfc5870.html
|
|
94
|
+
// The base RegExp comes from:
|
|
95
|
+
// https://github.com/cure53/DOMPurify/blob/main/src/regexp.js#L10
|
|
96
|
+
ALLOWED_URI_REGEXP:
|
|
97
|
+
/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|geo):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i,
|
|
98
|
+
})
|
|
99
|
+
return s
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function toHTML(r, options) {
|
|
103
|
+
if (!r) return ''
|
|
104
|
+
const target = (options && options.target) || 'blank'
|
|
105
|
+
let ii
|
|
106
|
+
|
|
107
|
+
// detect newline format
|
|
108
|
+
const newline = r.indexOf('\r\n') != -1 ? '\r\n' : r.indexOf('\n') != -1 ? '\n' : ''
|
|
109
|
+
|
|
110
|
+
// headings and hr
|
|
111
|
+
r = r.replace(/^### (.*)/gm, '<h5>$1</h5>')
|
|
112
|
+
r = r.replace(/^## (.*)/gm, '<h4>$1</h4>')
|
|
113
|
+
r = r.replace(/^# (.*)/gm, '<h3>$1</h3>')
|
|
114
|
+
r = r.replace(/^---/gm, '<hr>')
|
|
115
|
+
|
|
116
|
+
// bold, italics
|
|
117
|
+
r = r.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
|
|
118
|
+
r = r.replace(/\*(.*?)\*/g, '<em>$1</em>')
|
|
119
|
+
|
|
120
|
+
// unordered lists
|
|
121
|
+
r = r.replace(/^\*\* (.*)/gm, '<ul><ul><li>$1</li></ul></ul>')
|
|
122
|
+
r = r.replace(/^\* (.*)/gm, '<ul><li>$1</li></ul>')
|
|
123
|
+
for (ii = 0; ii < 3; ii++)
|
|
124
|
+
r = r.replace(new RegExp(`</ul>${newline}<ul>`, 'g'), newline)
|
|
125
|
+
|
|
126
|
+
// links
|
|
127
|
+
r = r.replace(/(\[\[http)/g, '[[h_t_t_p') // Escape for avoiding clash between [[http://xxx]] and http://xxx
|
|
128
|
+
r = r.replace(/({{http)/g, '{{h_t_t_p')
|
|
129
|
+
r = r.replace(/(=http)/g, '=h_t_t_p') // http://xxx as query string, see https://github.com/umap-project/umap/issues/607
|
|
130
|
+
r = r.replace(/(https?:[^ \<)\n]*)/g, `<a target="_${target}" href="$1">$1</a>`)
|
|
131
|
+
r = r.replace(
|
|
132
|
+
/\[\[(h_t_t_ps?:[^\]|]*?)\]\]/g,
|
|
133
|
+
`<a target="_${target}" href="$1">$1</a>`
|
|
134
|
+
)
|
|
135
|
+
r = r.replace(
|
|
136
|
+
/\[\[(h_t_t_ps?:[^|]*?)\|(.*?)\]\]/g,
|
|
137
|
+
`<a target="_${target}" href="$1">$2</a>`
|
|
138
|
+
)
|
|
139
|
+
r = r.replace(/\[\[([^\]|]*?)\]\]/g, `<a target="_${target}" href="$1">$1</a>`)
|
|
140
|
+
r = r.replace(/\[\[([^|]*?)\|(.*?)\]\]/g, `<a target="_${target}" href="$1">$2</a>`)
|
|
141
|
+
|
|
142
|
+
// iframe
|
|
143
|
+
r = r.replace(
|
|
144
|
+
/{{{(h_t_t_ps?[^ |{]*)}}}/g,
|
|
145
|
+
'<div><iframe frameborder="0" src="$1" width="100%" height="300px"></iframe></div>'
|
|
146
|
+
)
|
|
147
|
+
r = r.replace(
|
|
148
|
+
/{{{(h_t_t_ps?[^ |{]*)\|(\d*)(px)?}}}/g,
|
|
149
|
+
'<div><iframe frameborder="0" src="$1" width="100%" height="$2px"></iframe></div>'
|
|
150
|
+
)
|
|
151
|
+
r = r.replace(
|
|
152
|
+
/{{{(h_t_t_ps?[^ |{]*)\|(\d*)(px)?\*(\d*)(px)?}}}/g,
|
|
153
|
+
'<div><iframe frameborder="0" src="$1" width="$4px" height="$2px"></iframe></div>'
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
// images
|
|
157
|
+
r = r.replace(/{{([^\]|]*?)}}/g, '<img src="$1">')
|
|
158
|
+
r = r.replace(
|
|
159
|
+
/{{([^|]*?)\|(\d*?)(px)?}}/g,
|
|
160
|
+
'<img src="$1" style="width:$2px;min-width:$2px;">'
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
//Unescape http
|
|
164
|
+
r = r.replace(/(h_t_t_p)/g, 'http')
|
|
165
|
+
|
|
166
|
+
// Preserver line breaks
|
|
167
|
+
if (newline) r = r.replace(new RegExp(`${newline}(?=[^]+)`, 'g'), `<br>${newline}`)
|
|
168
|
+
|
|
169
|
+
r = escapeHTML(r)
|
|
170
|
+
|
|
171
|
+
return r
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export function isObject(what) {
|
|
175
|
+
return typeof what === 'object' && what !== null
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export function CopyJSON(geojson) {
|
|
179
|
+
return JSON.parse(JSON.stringify(geojson))
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function detectFileType(f) {
|
|
183
|
+
const filename = f.name ? escape(f.name.toLowerCase()) : ''
|
|
184
|
+
function ext(_) {
|
|
185
|
+
return filename.indexOf(_) !== -1
|
|
186
|
+
}
|
|
187
|
+
if (f.type === 'application/vnd.google-earth.kml+xml' || ext('.kml')) {
|
|
188
|
+
return 'kml'
|
|
189
|
+
}
|
|
190
|
+
if (ext('.gpx')) return 'gpx'
|
|
191
|
+
if (ext('.geojson') || ext('.json')) return 'geojson'
|
|
192
|
+
if (f.type === 'text/csv' || ext('.csv') || ext('.tsv') || ext('.dsv')) {
|
|
193
|
+
return 'csv'
|
|
194
|
+
}
|
|
195
|
+
if (ext('.xml') || ext('.osm')) return 'osm'
|
|
196
|
+
if (ext('.umap')) return 'umap'
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export function usableOption(options, option) {
|
|
200
|
+
return options[option] !== undefined && options[option] !== ''
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Processes a template string by replacing placeholders with corresponding
|
|
205
|
+
* data values.
|
|
206
|
+
*
|
|
207
|
+
* Supports dot notation for nested objects and optional static fallbacks.
|
|
208
|
+
* If a value is not found, the placeholder is replaced with an empty string
|
|
209
|
+
* or left unchanged when 'ignore' is true.
|
|
210
|
+
*
|
|
211
|
+
* @param {string} str - The template string with placeholders.
|
|
212
|
+
* @param {Object} data - The data object from which to pull replacement values.
|
|
213
|
+
* @param {boolean} [ignore=false] - If true, leaves placeholders unchanged when no value is found.
|
|
214
|
+
* @returns {string} The processed string with placeholders replaced.
|
|
215
|
+
*/
|
|
216
|
+
export function greedyTemplate(str, data, ignore) {
|
|
217
|
+
function getValue(data, path) {
|
|
218
|
+
let value = data
|
|
219
|
+
for (let i = 0; i < path.length; i++) {
|
|
220
|
+
value = value[path[i]]
|
|
221
|
+
if (value === undefined) break
|
|
222
|
+
}
|
|
223
|
+
return value
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (typeof str !== 'string') return ''
|
|
227
|
+
|
|
228
|
+
return str.replace(
|
|
229
|
+
/\{ *([^\{\}/\-]+)(?:\|("[^"]*"))? *\}/g,
|
|
230
|
+
(str, key, staticFallback) => {
|
|
231
|
+
const vars = key.split('|')
|
|
232
|
+
let value
|
|
233
|
+
let path
|
|
234
|
+
if (staticFallback !== undefined) {
|
|
235
|
+
vars.push(staticFallback)
|
|
236
|
+
}
|
|
237
|
+
for (let i = 0; i < vars.length; i++) {
|
|
238
|
+
path = vars[i]
|
|
239
|
+
if (path.startsWith('"') && path.endsWith('"'))
|
|
240
|
+
value = path.substring(1, path.length - 1) // static default value.
|
|
241
|
+
else value = getValue(data, path.split('.'))
|
|
242
|
+
if (value !== undefined) break
|
|
243
|
+
}
|
|
244
|
+
if (value === undefined) {
|
|
245
|
+
if (ignore) value = str
|
|
246
|
+
else value = ''
|
|
247
|
+
}
|
|
248
|
+
return value
|
|
249
|
+
}
|
|
250
|
+
)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export function naturalSort(a, b, lang) {
|
|
254
|
+
return a
|
|
255
|
+
.toString()
|
|
256
|
+
.toLowerCase()
|
|
257
|
+
.localeCompare(b.toString().toLowerCase(), lang || 'en', {
|
|
258
|
+
sensitivity: 'base',
|
|
259
|
+
numeric: true,
|
|
260
|
+
})
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export function sortFeatures(features, sortKey, lang) {
|
|
264
|
+
const sortKeys = (sortKey || 'name').split(',')
|
|
265
|
+
|
|
266
|
+
const sort = (a, b, i) => {
|
|
267
|
+
let sortKey = sortKeys[i],
|
|
268
|
+
reverse = 1
|
|
269
|
+
if (sortKey[0] === '-') {
|
|
270
|
+
reverse = -1
|
|
271
|
+
sortKey = sortKey.substring(1)
|
|
272
|
+
}
|
|
273
|
+
let score
|
|
274
|
+
const valA = a.properties[sortKey] || ''
|
|
275
|
+
const valB = b.properties[sortKey] || ''
|
|
276
|
+
if (!valA) score = -1
|
|
277
|
+
else if (!valB) score = 1
|
|
278
|
+
else score = naturalSort(valA, valB, lang)
|
|
279
|
+
if (score === 0 && sortKeys[i + 1]) return sort(a, b, i + 1)
|
|
280
|
+
return score * reverse
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
features.sort((a, b) => {
|
|
284
|
+
if (!a.properties || !b.properties) {
|
|
285
|
+
return 0
|
|
286
|
+
}
|
|
287
|
+
return sort(a, b, 0)
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
return features
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export function flattenCoordinates(coords) {
|
|
294
|
+
while (coords[0] && typeof coords[0][0] !== 'number') coords = coords[0]
|
|
295
|
+
return coords
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export function buildQueryString(params) {
|
|
299
|
+
const query_string = []
|
|
300
|
+
for (const key in params) {
|
|
301
|
+
query_string.push(`${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
|
|
302
|
+
}
|
|
303
|
+
return query_string.join('&')
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export function getBaseUrl() {
|
|
307
|
+
return `//${window.location.host}${window.location.pathname}`
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export function hasVar(value) {
|
|
311
|
+
return typeof value === 'string' && value.indexOf('{') != -1
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export function isPath(value) {
|
|
315
|
+
return value && value.length && value.startsWith('/')
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export function isRemoteUrl(value) {
|
|
319
|
+
return value && value.length && value.startsWith('http')
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export function isDataImage(value) {
|
|
323
|
+
return value && value.length && value.startsWith('data:image')
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Normalizes the input string by converting to lowercase
|
|
328
|
+
* and removing diacritics.
|
|
329
|
+
*
|
|
330
|
+
* If the input is nullish, it defaults to an empty string.
|
|
331
|
+
*
|
|
332
|
+
* @param {string} s - The string to be normalized.
|
|
333
|
+
* @returns {string} - The normalized string with lowercase
|
|
334
|
+
* characters and no diacritics.
|
|
335
|
+
*/
|
|
336
|
+
export function normalize(s) {
|
|
337
|
+
return (s || '')
|
|
338
|
+
.toLowerCase()
|
|
339
|
+
.normalize('NFD')
|
|
340
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Vendorized from leaflet.utils
|
|
344
|
+
// https://github.com/Leaflet/Leaflet/blob/108c6717b70f57c63645498f9bd66b6677758786/src/core/Util.js#L132-L151
|
|
345
|
+
var templateRe = /\{ *([\w_ -]+) *\}/g
|
|
346
|
+
|
|
347
|
+
export function template(str, data) {
|
|
348
|
+
return str.replace(templateRe, function (str, key) {
|
|
349
|
+
var value = data[key]
|
|
350
|
+
|
|
351
|
+
if (value === undefined) {
|
|
352
|
+
throw new Error('No value provided for variable ' + str)
|
|
353
|
+
} else if (typeof value === 'function') {
|
|
354
|
+
value = value(data)
|
|
355
|
+
}
|
|
356
|
+
return value
|
|
357
|
+
})
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
export function parseNaiveDate(value) {
|
|
361
|
+
const naive = new Date(value)
|
|
362
|
+
// Let's pretend naive date are UTC, and remove time…
|
|
363
|
+
return new Date(Date.UTC(naive.getFullYear(), naive.getMonth(), naive.getDate()))
|
|
364
|
+
}
|