Merge pull request #1162 from umap-project/link-target

Control links target
This commit is contained in:
Yohan Boniface 2023-06-23 15:25:34 +02:00 committed by GitHub
commit c3aa2aeb30
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 32 additions and 22 deletions

View file

@ -73,8 +73,9 @@ L.Util.escapeHTML = (s) => {
}) })
return s return s
} }
L.Util.toHTML = (r) => { L.Util.toHTML = (r, options) => {
if (!r) return '' if (!r) return ''
const target = options && options.target || 'blank'
let ii let ii
// detect newline format // detect newline format
@ -100,14 +101,14 @@ L.Util.toHTML = (r) => {
r = r.replace(/(\[\[http)/g, '[[h_t_t_p') // Escape for avoiding clash between [[http://xxx]] and http://xxx r = r.replace(/(\[\[http)/g, '[[h_t_t_p') // Escape for avoiding clash between [[http://xxx]] and http://xxx
r = r.replace(/({{http)/g, '{{h_t_t_p') r = r.replace(/({{http)/g, '{{h_t_t_p')
r = r.replace(/(=http)/g, '=h_t_t_p') // http://xxx as query string, see https://github.com/umap-project/umap/issues/607 r = r.replace(/(=http)/g, '=h_t_t_p') // http://xxx as query string, see https://github.com/umap-project/umap/issues/607
r = r.replace(/(https?:[^ \<)\n]*)/g, '<a target="_blank" href="$1">$1</a>') r = r.replace(/(https?:[^ \<)\n]*)/g, `<a target="_${target}" href="$1">$1</a>`)
r = r.replace(/\[\[(h_t_t_ps?:[^\]|]*?)\]\]/g, '<a target="_blank" href="$1">$1</a>') r = r.replace(/\[\[(h_t_t_ps?:[^\]|]*?)\]\]/g, `<a target="_${target}" href="$1">$1</a>`)
r = r.replace( r = r.replace(
/\[\[(h_t_t_ps?:[^|]*?)\|(.*?)\]\]/g, /\[\[(h_t_t_ps?:[^|]*?)\|(.*?)\]\]/g,
'<a target="_blank" href="$1">$2</a>' `<a target="_${target}" href="$1">$2</a>`
) )
r = r.replace(/\[\[([^\]|]*?)\]\]/g, '<a href="$1">$1</a>') r = r.replace(/\[\[([^\]|]*?)\]\]/g, `<a target="_${target}" href="$1">$1</a>`)
r = r.replace(/\[\[([^|]*?)\|(.*?)\]\]/g, '<a href="$1">$2</a>') r = r.replace(/\[\[([^|]*?)\|(.*?)\]\]/g, `<a target="_${target}" href="$1">$2</a>`)
// iframe // iframe
r = r.replace( r = r.replace(

View file

@ -57,8 +57,8 @@ L.U.FeatureMixin = {
view: function (e) { view: function (e) {
if (this.map.editEnabled) return if (this.map.editEnabled) return
const outlink = this.properties._umap_options.outlink, const outlink = this.getOption('outlink'),
target = this.properties._umap_options.outlinkTarget target = this.getOption('outlinkTarget')
if (outlink) { if (outlink) {
switch (target) { switch (target) {
case 'self': case 'self':
@ -173,6 +173,8 @@ L.U.FeatureMixin = {
'properties._umap_options.showLabel', 'properties._umap_options.showLabel',
'properties._umap_options.labelDirection', 'properties._umap_options.labelDirection',
'properties._umap_options.labelInteractive', 'properties._umap_options.labelInteractive',
'properties._umap_options.outlink',
'properties._umap_options.outlinkTarget',
] ]
}, },
@ -1046,19 +1048,6 @@ L.U.Polygon = L.Polygon.extend({
inheritable: true, inheritable: true,
}, },
], ],
[
'properties._umap_options.outlink',
{
label: L._('Link to…'),
helpEntries: 'outlink',
placeholder: 'http://...',
inheritable: true,
},
],
[
'properties._umap_options.outlinkTarget',
{ handler: 'OutlinkTarget', label: L._('Open link in…'), inheritable: true },
],
] ]
return options.concat(L.U.FeatureMixin.getInteractionOptions()) return options.concat(L.U.FeatureMixin.getInteractionOptions())
}, },

View file

@ -1045,6 +1045,17 @@ L.U.FormBuilder = L.FormBuilder.extend({
label: L._('Labels are clickable'), label: L._('Labels are clickable'),
inheritable: true, inheritable: true,
}, },
outlink: {
label: L._('Link to…'),
helpEntries: 'outlink',
placeholder: 'http://...',
inheritable: true,
},
outlinkTarget: {
handler: 'OutlinkTarget',
label: L._('Open link in…'),
inheritable: true,
},
labelKey: { labelKey: {
helpEntries: 'labelKey', helpEntries: 'labelKey',
placeholder: L._('Default: name'), placeholder: L._('Default: name'),

View file

@ -862,6 +862,7 @@ L.U.DataLayer = L.Evented.extend({
'options.showLabel', 'options.showLabel',
'options.labelDirection', 'options.labelDirection',
'options.labelInteractive', 'options.labelInteractive',
'options.outlinkTarget',
] ]
builder = new L.U.FormBuilder(this, popupFields, { callback: redrawCallback }) builder = new L.U.FormBuilder(this, popupFields, { callback: redrawCallback })
const popupFieldset = L.DomUtil.createFieldset( const popupFieldset = L.DomUtil.createFieldset(

View file

@ -98,6 +98,7 @@ L.U.PopupTemplate.Default = L.Class.extend({
renderBody: function () { renderBody: function () {
const template = this.feature.getOption('popupContentTemplate') const template = this.feature.getOption('popupContentTemplate')
const target = this.feature.getOption('outlinkTarget')
const container = L.DomUtil.create('div', 'umap-popup-container') const container = L.DomUtil.create('div', 'umap-popup-container')
let content = '' let content = ''
let properties let properties
@ -109,7 +110,7 @@ L.U.PopupTemplate.Default = L.Class.extend({
properties properties
) )
content = L.Util.greedyTemplate(template, properties) content = L.Util.greedyTemplate(template, properties)
content = L.Util.toHTML(content) content = L.Util.toHTML(content, {target: target})
container.innerHTML = content container.innerHTML = content
return container return container
}, },

View file

@ -84,6 +84,13 @@ describe('L.Util', function () {
) )
}) })
it('should handle target option', function () {
assert.equal(
L.Util.toHTML('A simple http://osm.org link', {target: 'self'}),
'A simple <a href="http://osm.org" target="_self">http://osm.org</a> link'
)
})
it('should handle image', function () { it('should handle image', function () {
assert.equal( assert.equal(
L.Util.toHTML('A simple image: {{http://osm.org/pouet.png}}'), L.Util.toHTML('A simple image: {{http://osm.org/pouet.png}}'),