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 = '
' + images + '
' } - return images.concat('

' + 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 },