diff --git a/linphone-desktop/ui/scripts/Utils/uri-tools.js b/linphone-desktop/ui/scripts/Utils/uri-tools.js
index eeedfe941..0ae3fad21 100644
--- a/linphone-desktop/ui/scripts/Utils/uri-tools.js
+++ b/linphone-desktop/ui/scripts/Utils/uri-tools.js
@@ -20,8 +20,8 @@ var URI_UNRESERVED = '[\\w\-\._~]'
// Level 1. --------------------------------------------------------------------
-var URI_HOST = '(' +
- '(' +
+var URI_HOST = '(?:' +
+ '(?:' +
URI_UNRESERVED +
'|' + URI_PCT_ENCODED +
'|' + URI_SUB_DELIMS +
@@ -90,7 +90,7 @@ var URI = (SUPPORTS_URL
) + URI_HIER_PART + '(?:' + '\\?' + URI_QUERY + ')?' +
'(?:' + '#' + URI_FRAGMENT + ')?'
-var URI_REGEX = new RegExp(URI, 'g')
+var URI_REGEX = new RegExp('(' + URI + ')', 'g')
// =============================================================================
diff --git a/linphone-desktop/ui/scripts/Utils/utils.js b/linphone-desktop/ui/scripts/Utils/utils.js
index 1212a7aa0..0b92f6831 100644
--- a/linphone-desktop/ui/scripts/Utils/utils.js
+++ b/linphone-desktop/ui/scripts/Utils/utils.js
@@ -48,40 +48,35 @@ function encodeTextToQmlRichFormat (text, options) {
options = {}
}
- text = text
- .replace(/&/g, '&') // TODO: deal correctly with urls and `&m`
- .replace(//g, '\u2063>')
- .replace(/\r\n|\n/g, '
')
- .replace(/\t/g, ' ')
- .replace(/ /g, ' ')
- .replace(UriTools.URI_REGEX, function (match) {
- // If it's a simple URL, transforms it in URI.
- if (startsWith(match, 'www.')) {
- match = 'http://' + match
- }
+ var formattedText = execAll(UriTools.URI_REGEX, text, function (str, valid) {
+ if (!valid) {
+ return unscapeHtml(str).replace(/\r\n|\n/g, '
')
+ .replace(/\t/g, ' ')
+ .replace(/ /g, ' ')
+ }
- var ext = getExtension(match)
- if (includes([ 'jpg', 'jpeg', 'gif', 'png', 'svg' ], ext)) {
- images += ''
- }
+ var uri = startsWith(str, 'www.') ? 'http://' + str : str
- return '' + match + ''
- })
+ var ext = getExtension(str)
+ if (includes([ 'jpg', 'jpeg', 'gif', 'png', 'svg' ], ext)) {
+ images += '
'
+ }
+ return '' + str + ''
+ }).join('')
if (images.length > 0) {
images = '
' + text + '
') + return images.concat('' + formattedText + '
') } function extractFirstUri (str) { @@ -301,6 +296,40 @@ function dirname (str) { // ----------------------------------------------------------------------------- +function execAll (regex, text, cb) { + var index = 0 + var arr = [] + var match + + if (!cb) { + cb = function (text) { + return text + } + } + + while ((match = regex.exec(text))) { + var curIndex = match.index + var matchStr = match[0] + + if (curIndex > index) { + arr.push(cb(text.substring(index, curIndex), false)) + } + + arr.push(cb(matchStr, true)) + + index = curIndex + matchStr.length + } + + var length = text.length + if (index < length) { + arr.push(cb(text.substring(index, length))) + } + + return arr +} + +// ----------------------------------------------------------------------------- + function extractProperties (obj, pattern) { if (!pattern) { return {} @@ -560,3 +589,13 @@ function times (n, cb, context) { return arr } + +// ----------------------------------------------------------------------------- + +function unscapeHtml (str) { + return str.replace(/&/g, '&') + .replace(//g, '\u2063>') + .replace(/"/g, '"') + .replace(/'/g, ''') +} diff --git a/linphone-desktop/ui/scripts/Utils/utils.spec.qml b/linphone-desktop/ui/scripts/Utils/utils.spec.qml index d73c29c08..a56b613a1 100644 --- a/linphone-desktop/ui/scripts/Utils/utils.spec.qml +++ b/linphone-desktop/ui/scripts/Utils/utils.spec.qml @@ -145,12 +145,76 @@ TestCase { function test_ensureArray (data) { // Use `sort` because transform a object in array hasn't a - // guarantee order. + // guarantee ordering. compare(Utils.ensureArray(data.input).sort(), data.output.sort()) } // --------------------------------------------------------------------------- + function test_execAll_data () { + return [ + { + cb: function () { + return 'failed' + }, + regex: /x/g, + text: '', + + output: [] + }, { + cb: function (c, valid) { + return !valid && c + }, + regex: /x/g, + text: 'n', + + output: [ 'n' ] + }, { + cb: function (c, valid) { + return valid && String.fromCharCode(c.charCodeAt(0) + 1) + }, + regex: /[a-z]/g, + text: 'abcdefgh', + + output: [ 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' ] + }, { + cb: function (n, valid) { + return !valid ? '*' : Math.abs(n) + }, + regex: /\d+/g, + text: 'abc 5 def -4 ghi 452-12', + + output: [ '*', 5, '*', 4, '*', 452, '*', 12 ] + }, { + regex: /candy-shop/g, + text: 'candy-hop candy-shop cndy-shop candyshop', + + output: [ 'candy-hop ', 'candy-shop', ' cndy-shop candyshop' ] + }, { + cb: function (text, valid) { + return valid ? text + ' Batman!' : text + }, + regex: /(?:na)+\.\.\./g, + text: 'Nananana. Nanananananananana... Nanananananananana... Nananananananananananana...', + + output: [ + 'Nananana. Na', + 'nananananananana... Batman!', + ' Na', + 'nananananananana... Batman!', + ' Na', + 'nanananananananananana... Batman!' + ] + } + ] + } + + function test_execAll (data) { + compare(Utils.execAll(data.regex, data.text, data.cb), data.output) + } + + // --------------------------------------------------------------------------- + function test_genRandomNumber_data () { return [ { min: 42, max: 3600 },