diff --git a/CHANGELOG.md b/CHANGELOG.md index f6cd87a646e..f03acd2b653 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ _Breaking developer changes, which may affect downstream projects or sites that #### :white_check_mark: Validation * Don't error on features with a sole `note` tag ([#11522]) #### :bug: Bugfixes +* Fix some gpx/geojson properties not visible, such as numbers or complex data structures ([#11636], thanks [@k-yle]) #### :earth_asia: Localization #### :hourglass: Performance #### :mortar_board: Walkthrough / Help @@ -51,6 +52,7 @@ _Breaking developer changes, which may affect downstream projects or sites that [#11522]: https://github.com/openstreetmap/iD/issues/11522 +[#11636]: https://github.com/openstreetmap/iD/pull/11636 # v2.37.3 ##### 2025-10-31 diff --git a/modules/ui/data_editor.js b/modules/ui/data_editor.js index fc14e16ac20..611d49ba852 100644 --- a/modules/ui/data_editor.js +++ b/modules/ui/data_editor.js @@ -1,7 +1,7 @@ import { t } from '../core/localizer'; import { modeBrowse } from '../modes/browse'; import { svgIcon } from '../svg/icon'; - +import { stringifyProperties } from '../util/object'; import { uiDataHeader } from './data_header'; import { uiSectionRawTagEditor } from './sections/raw_tag_editor'; @@ -64,7 +64,7 @@ export function uiDataEditor(context) { .attr('class', 'raw-tag-editor data-editor') .merge(rte) .call(rawTagEditor - .tags((_datum && _datum.properties) || {}) + .tags(stringifyProperties(_datum?.properties || {})) .state('hover') .render ) diff --git a/modules/util/index.js b/modules/util/index.js index f88ba1c7f65..7451eaef15d 100644 --- a/modules/util/index.js +++ b/modules/util/index.js @@ -33,7 +33,7 @@ export { utilHashcode } from './util'; export { utilHighlightEntities } from './util'; export { utilKeybinding } from './keybinding'; export { utilNoAuto } from './util'; -export { utilObjectOmit, utilCheckTagDictionary } from './object'; +export { utilObjectOmit, utilCheckTagDictionary, stringifyProperties } from './object'; export { utilCompareIDs } from './util'; export { utilOldestID } from './util'; export { utilPrefixCSSProperty } from './util'; diff --git a/modules/util/object.js b/modules/util/object.js index e83ca5e51e8..f8595fa2ae6 100644 --- a/modules/util/object.js +++ b/modules/util/object.js @@ -29,3 +29,28 @@ export function utilCheckTagDictionary(tags, tagDictionary) { } return undefined; } + +/** + * converts every value in an object to a string, if + * it's not already a string. + * @param {Record} object + */ +export function stringifyProperties(object) { + /** @type {Tags} */ + const tags = {}; + for (const key in object) { + switch (typeof object[key]) { + case 'undefined': + break; // skip property + case 'string': + tags[key] = object[key]; + break; + default: + tags[key] = JSON.stringify( + object[key], + (_, value) => typeof value === 'bigint' ? value.toString() : value + ); + } + } + return tags; +} diff --git a/test/spec/util/object.js b/test/spec/util/object.ts similarity index 61% rename from test/spec/util/object.js rename to test/spec/util/object.ts index cd81a7267d0..19a0802e4f2 100644 --- a/test/spec/util/object.js +++ b/test/spec/util/object.ts @@ -20,3 +20,26 @@ describe('iD.utilCheckTagDictionary', () => { expect(iD.utilCheckTagDictionary({ surface: 'paved' }, dictionary)).toBe(0); }); }); + +describe('stringifyProperties', () => { + it('converts object properties to a string', () => { + const input = { + a: 'a', + b: 1, + c: null, + d: undefined, + e: { f: 1 }, + g: [1, 2n], + h: 1n, + }; + expect(iD.stringifyProperties(input)).toStrictEqual({ + a: 'a', + b: '1', + c: 'null', + // d (undefined) is skipped + e: '{"f":1}', + g: '[1,"2"]', + h: '"1"', + }); + }); +});