diff --git a/package.json b/package.json index acd193ae..ab5994b4 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "showdown": "^1.8.6", "stream": "^0.0.3", "superagent": "^3.5.2", + "tag2link": "^2025.5.21", "terra-draw": "^1.1.0", "terra-draw-maplibre-gl-adapter": "^1.0.1" }, diff --git a/src/components/element_info.js b/src/components/element_info.js index dab90b57..7fb2c3b5 100644 --- a/src/components/element_info.js +++ b/src/components/element_info.js @@ -8,6 +8,7 @@ import { Dropdown } from './dropdown'; import { Button } from './button'; import thumbsDown from '../assets/thumbs-down.svg'; import type { RootStateType } from '../store'; +import { TagValue } from './tag_value.js'; /* * Displays info about an element that was created/modified/deleted. @@ -303,7 +304,9 @@ function TagsTable({ action }) { {key} - {newval} + + + ); @@ -314,7 +317,9 @@ function TagsTable({ action }) { {key} - {newval} + + + ); @@ -325,7 +330,9 @@ function TagsTable({ action }) { {key} - {oldval} + + + ); @@ -336,9 +343,13 @@ function TagsTable({ action }) { {key} - {oldval} + + + {' → '} - {newval} + + + ); diff --git a/src/components/tag_value.js b/src/components/tag_value.js new file mode 100644 index 00000000..6959b3a3 --- /dev/null +++ b/src/components/tag_value.js @@ -0,0 +1,56 @@ +// @ts-check +import { Fragment } from 'react'; +import tag2linkRaw from 'tag2link'; + +const RANKS = ['deprecated', 'normal', 'preferred']; + +/** + * @typedef {{ + * key: `Key:${string}`; + * url: string; + * source: string; + * rank: "normal" | "preferred"; + * }} Tag2LinkItem + */ + +/** @param {Tag2LinkItem[]} input */ +function convertSourceData(input) { + /** @type {Record} */ + const output = {}; + + const allKeys = new Set(input.map(item => item.key)); + + for (const key of allKeys) { + // find the item with the best rank + const bestDefinition = input + .filter(item => item.key === key) + .sort((a, b) => RANKS.indexOf(b.rank) - RANKS.indexOf(a.rank))[0]; + + output[key.replace('Key:', '')] = bestDefinition.url; + } + + return output; +} + +export const TAG2LINK = convertSourceData(tag2linkRaw); + +/** @type {React.FC<{ k: string; v: string }>} */ +export const TagValue = ({ k, v }) => { + const placeholderUrl = TAG2LINK[k]; + + // simple key, not clickable + if (!placeholderUrl) return v; + + return v.split(';').map((chunk, index) => (( + + {!!index && ';'} + + {chunk} + + + ))); +}; diff --git a/yarn.lock b/yarn.lock index a04d581c..5994df2d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14381,6 +14381,11 @@ table@4.0.2: slice-ansi "1.0.0" string-width "^2.1.1" +tag2link@^2025.5.21: + version "2025.5.21" + resolved "https://registry.yarnpkg.com/tag2link/-/tag2link-2025.5.21.tgz#5f02fd412e854744a141b4d6217e6acf33e23d93" + integrity sha512-vcz6/6U5V3QYPA7geLrtzLMqhCwg6OvoGP665DbGgPRSWASjFn0J4jA/NyifD3Tmp2yf8RnEuI6QBvhXGBVSHg== + tailwindcss@^3.0.2: version "3.4.15" resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.15.tgz#04808bf4bf1424b105047d19e7d4bfab368044a9"