mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-08 03:06:40 +02:00
linkify keys & tags in the preset docs from the wiki (#10763)
This commit is contained in:
@@ -40,6 +40,7 @@ _Breaking developer changes, which may affect downstream projects or sites that
|
||||
#### :sparkles: Usability & Accessibility
|
||||
* Autocomplete changeset `source` tag with sources of the previous 100 changesets of the user ([#10764], thanks [@k-yle])
|
||||
* Also show search result for coordinates in `lon/lat` order in search results ([#10720], thanks [@Deeptanshu-sankhwar])
|
||||
* Linkify keys & tags in the preset docs from the wiki ([#10763], thanks [@k-yle])
|
||||
* Allow broken (unclosed) areas to be continued ([#9635], thanks [@k-yle])
|
||||
#### :scissors: Operations
|
||||
* Fix splitting of closed ways (or areas) when two or more split-points are selected
|
||||
@@ -69,6 +70,7 @@ _Breaking developer changes, which may affect downstream projects or sites that
|
||||
[#10747]: https://github.com/openstreetmap/iD/issues/10747
|
||||
[#10748]: https://github.com/openstreetmap/iD/issues/10748
|
||||
[#10755]: https://github.com/openstreetmap/iD/issues/10755
|
||||
[#10763]: https://github.com/openstreetmap/iD/pull/10763
|
||||
[#10764]: https://github.com/openstreetmap/iD/issues/10764
|
||||
[#10766]: https://github.com/openstreetmap/iD/pull/10766
|
||||
[@hlfan]: https://github.com/hlfan
|
||||
|
||||
@@ -102,6 +102,38 @@ export default {
|
||||
return result.replace(/_/g, ' ').trim();
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts text like `tag:...=...` into clickable links
|
||||
*
|
||||
* @param {string} unsafeText - unsanitized text
|
||||
*/
|
||||
linkifyWikiText(unsafeText) {
|
||||
/** @param {import('d3').Selection} selection */
|
||||
return (selection) => {
|
||||
const segments = unsafeText.split(/(key|tag):([\w-]+)(=([\w-]+))?/g);
|
||||
|
||||
for (let i = 0; i < segments.length; i += 5) {
|
||||
const [plainText, , key, , value] = segments.slice(i);
|
||||
|
||||
if (plainText) {
|
||||
selection
|
||||
.append('span')
|
||||
.text(plainText);
|
||||
}
|
||||
|
||||
if (key) {
|
||||
selection
|
||||
.append('a')
|
||||
.attr('href', `https://wiki.openstreetmap.org/wiki/${this.toSitelink(key, value)}`)
|
||||
.attr('target', '_blank')
|
||||
.attr('rel', 'noreferrer')
|
||||
.append('code')
|
||||
.text(`${key}=${value || '*'}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
//
|
||||
// Pass params object of the form:
|
||||
@@ -269,7 +301,7 @@ export default {
|
||||
// prepare result
|
||||
var result = {
|
||||
title: entity.title,
|
||||
description: description ? description.value : '',
|
||||
description: that.linkifyWikiText(description?.value || ''),
|
||||
descriptionLocaleCode: description ? description.language : '',
|
||||
editURL: 'https://wiki.openstreetmap.org/wiki/' + entity.title
|
||||
};
|
||||
|
||||
@@ -53,7 +53,7 @@ export function uiTagReference(what) {
|
||||
_body
|
||||
.append('img')
|
||||
.attr('class', 'tag-reference-wiki-image')
|
||||
.attr('alt', docs.description)
|
||||
.attr('alt', docs.title)
|
||||
.attr('src', docs.imageURL)
|
||||
.on('load', function() { done(); })
|
||||
.on('error', function() { d3_select(this).remove(); done(); });
|
||||
@@ -69,7 +69,7 @@ export function uiTagReference(what) {
|
||||
tagReferenceDescription = tagReferenceDescription
|
||||
.attr('class', 'localized-text')
|
||||
.attr('lang', docs.descriptionLocaleCode || 'und')
|
||||
.text(docs.description);
|
||||
.call(docs.description);
|
||||
} else {
|
||||
tagReferenceDescription = tagReferenceDescription
|
||||
.call(t.append('inspector.no_documentation_key'));
|
||||
|
||||
@@ -331,4 +331,75 @@ describe('iD.serviceOsmWikibase', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('linkifyWikiText', () => {
|
||||
it('handles normal text', () => {
|
||||
const main = document.createElement('main');
|
||||
d3.select(main).call(iD.serviceOsmWikibase.linkifyWikiText('hello'));
|
||||
|
||||
expect(main.innerHTML).toBe('<span>hello</span>');
|
||||
expect(main.textContent).toBe('hello');
|
||||
});
|
||||
|
||||
it('prevents XSS attacks', () => {
|
||||
const main = document.createElement('main');
|
||||
d3.select(main).call(iD.serviceOsmWikibase.linkifyWikiText('123 <script>bad</script> 456'));
|
||||
|
||||
expect(main.innerHTML).toBe('<span>123 <script>bad</script> 456</span>');
|
||||
expect(main.textContent).toBe('123 <script>bad</script> 456');
|
||||
});
|
||||
|
||||
it('linkifies the tag: and key: syntax', () => {
|
||||
const main = document.createElement('main');
|
||||
d3.select(main).call(iD.serviceOsmWikibase.linkifyWikiText('use tag:natural=water with key:water instead'));
|
||||
|
||||
expect(main.innerHTML).toBe([
|
||||
'<span>use </span>',
|
||||
'<a href="https://wiki.openstreetmap.org/wiki/Tag:natural=water" target="_blank" rel="noreferrer"><code>natural=water</code></a>',
|
||||
'<span> with </span>',
|
||||
'<a href="https://wiki.openstreetmap.org/wiki/Key:water" target="_blank" rel="noreferrer"><code>water=*</code></a>',
|
||||
'<span> instead</span>'
|
||||
].join(''));
|
||||
expect(main.textContent).toBe('use natural=water with water=* instead');
|
||||
});
|
||||
|
||||
it('works if the string is 100% a link', () => {
|
||||
const main = document.createElement('main');
|
||||
d3.select(main).call(iD.serviceOsmWikibase.linkifyWikiText('tag:natural=water'));
|
||||
|
||||
expect(main.innerHTML).toBe([
|
||||
'<a href="https://wiki.openstreetmap.org/wiki/Tag:natural=water" target="_blank" rel="noreferrer"><code>natural=water</code></a>',
|
||||
].join(''));
|
||||
expect(main.textContent).toBe('natural=water');
|
||||
});
|
||||
|
||||
it('works if the link is the first part of the string', () => {
|
||||
const main = document.createElement('main');
|
||||
d3.select(main).call(iD.serviceOsmWikibase.linkifyWikiText('tag:craft=sailmaker is better'));
|
||||
|
||||
expect(main.innerHTML).toBe([
|
||||
'<a href="https://wiki.openstreetmap.org/wiki/Tag:craft=sailmaker" target="_blank" rel="noreferrer"><code>craft=sailmaker</code></a>',
|
||||
'<span> is better</span>'
|
||||
].join(''));
|
||||
expect(main.textContent).toBe('craft=sailmaker is better');
|
||||
});
|
||||
|
||||
it('works if the link is the last part of the string', () => {
|
||||
const main = document.createElement('main');
|
||||
d3.select(main).call(iD.serviceOsmWikibase.linkifyWikiText('prefer tag:craft=sailmaker'));
|
||||
|
||||
expect(main.innerHTML).toBe([
|
||||
'<span>prefer </span>',
|
||||
'<a href="https://wiki.openstreetmap.org/wiki/Tag:craft=sailmaker" target="_blank" rel="noreferrer"><code>craft=sailmaker</code></a>',
|
||||
].join(''));
|
||||
expect(main.textContent).toBe('prefer craft=sailmaker');
|
||||
});
|
||||
|
||||
it('handles empty strings', () => {
|
||||
const main = document.createElement('main');
|
||||
d3.select(main).call(iD.serviceOsmWikibase.linkifyWikiText(''));
|
||||
|
||||
expect(main.innerHTML).toBe('');
|
||||
expect(main.textContent).toBe('');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user