diff --git a/package-lock.json b/package-lock.json index 84e81b1..6396f2f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wegwichtel-next", - "version": "0.12.9", + "version": "0.12.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "wegwichtel-next", - "version": "0.12.9", + "version": "0.12.10", "hasInstallScript": true, "dependencies": { "@file-type/av": "0.2.0", diff --git a/package.json b/package.json index fa5266e..7eebc74 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wegwichtel-next", - "version": "0.12.9", + "version": "0.12.10", "private": true, "description": "GPS-gestützte Lern- und Wanderwege mit GPX, POIs, Bildern und Audioansagen.", "type": "module", diff --git a/public/css/app.css b/public/css/app.css index 1f5bc8f..f869a0c 100644 --- a/public/css/app.css +++ b/public/css/app.css @@ -406,21 +406,26 @@ button, } #slideshow > fieldset { - display: grid; - margin: 0; - grid-template-columns: var(--icon-button-size) minmax(0, 1fr) var(--icon-button-size); - align-items: stretch; + display: flex; + flex-flow: row nowrap; + align-items: center; gap: .5rem; width: 100%; + min-width: 0; box-sizing: border-box; + margin: 0; padding: .65rem; } -#slideshow > fieldset .ui-button { +#slideshow > fieldset > button.ui-button { display: grid; + flex: 0 0 var(--icon-button-size); + align-self: center; place-items: center; - min-width: 0; - min-height: 100%; + width: var(--icon-button-size); + height: var(--icon-button-size); + min-width: var(--icon-button-size); + min-height: var(--icon-button-size); margin: 0; padding: .45rem; } @@ -433,6 +438,8 @@ button, #slideshow > fieldset > div { display: flex; + flex: 1 1 0; + align-self: stretch; min-width: 0; min-height: var(--icon-button-size); padding: .25rem .4rem; diff --git a/src/services/routes-service.js b/src/services/routes-service.js index 21586ac..04d9a9a 100644 --- a/src/services/routes-service.js +++ b/src/services/routes-service.js @@ -21,11 +21,21 @@ const UPDATE_METRICS_SQL = `UPDATE routes SET start_lat=?, start_lon=?, center_lat=?, center_lon=?, min_lat=?, min_lon=?, max_lat=?, max_lon=?, distance_m=?, elevation_gain_m=?, point_count=?, updated_at=CURRENT_TIMESTAMP WHERE id=?`; +function trimEdgeHyphens(value) { + let start = 0; + let end = value.length; + + while (start < end && value[start] === '-') start += 1; + while (end > start && value[end - 1] === '-') end -= 1; + + return value.slice(start, end); +} + function slugify(value) { const normalized = String(value).toLowerCase().normalize('NFKD'); const withoutMarks = normalized.replaceAll(/[\u0300-\u036f]/g, ''); const separated = withoutMarks.replaceAll(/[^a-z0-9]+/g, '-'); - const trimmed = separated.replaceAll(/(?:^-+|-+$)/g, ''); + const trimmed = trimEdgeHyphens(separated); return trimmed.slice(0, 80) || `route-${Date.now()}`; } diff --git a/test/mobile-navigation-ui.test.js b/test/mobile-navigation-ui.test.js index 1807092..bbf82ec 100644 --- a/test/mobile-navigation-ui.test.js +++ b/test/mobile-navigation-ui.test.js @@ -182,7 +182,11 @@ test('POI page uses icon-based back and slideshow controls in a single responsiv assert.match(html, /id="slide-prev"[\s\S]*images\/icons\/chevron-left\.svg/); assert.match(html, /id="slide-next"[\s\S]*images\/icons\/chevron-right\.svg/); assert.match(html, /