Commit 50d190a2 authored by Ronan Abhamon's avatar Ronan Abhamon

feat(Utils): `encodeUrisToQmlFormat` supports images

parent 3ce0f2f2
...@@ -165,9 +165,9 @@ ColumnLayout { ...@@ -165,9 +165,9 @@ ColumnLayout {
ListElement { $dateSection: 1465389121000; $outgoing: true; $timestamp: 1465389121000; $type: 'message'; $content: "<img src='http://html.com/wp-content/uploads/html-com-1.png' width='50%' height='50%' />www.google.fr" } ListElement { $dateSection: 1465389121000; $outgoing: true; $timestamp: 1465389121000; $type: 'message'; $content: "<img src='http://html.com/wp-content/uploads/html-com-1.png' width='50%' height='50%' />www.google.fr" }
ListElement { $dateSection: 1465389121000; $outgoing: true; $timestamp: 1465389121000; $type: 'message'; $content: "<a href='mailto:qq1@qqpart.com'>Contact mail</a>" } ListElement { $dateSection: 1465389121000; $outgoing: true; $timestamp: 1465389121000; $type: 'message'; $content: "<a href='mailto:qq1@qqpart.com'>Contact mail</a>" }
ListElement { $dateSection: 1465389121000; $timestamp: 1465389133000; $type: 'event'; $content: 'incoming_call' } ListElement { $dateSection: 1465389121000; $timestamp: 1465389133000; $type: 'event'; $content: 'incoming_call' }
ListElement { $dateSection: 1465389121000; $timestamp: 1465389439000; $type: 'message'; $content: '<blink>Perfect!</blink> bg g vg gv v g v hgv gv gv jhb jh b jb jh hg vg cfcy f v u uyg f tf tf ft f tf t t fy ft f tu ty f rd rd d d uu gu y gg y f r dr ' } ListElement { $dateSection: 1465389121000; $timestamp: 1465389439000; $type: 'message'; $content: 'www.test.fr<blink>Perfect!</blink> bg g vg gv v g v hgv gv gv jhb jh b jb jh hg vg cfcy f v u uyg f tf tf ft f tf t t fy ft f tu ty f rd rd d d uu gu y gg y f r dr ' }
ListElement { $dateSection: 1465389121000; $timestamp: 1465389500000; $type: 'event'; $content: 'end_call' } ListElement { $dateSection: 1465389121000; $timestamp: 1465389500000; $type: 'event'; $content: 'end_call' }
ListElement { $dateSection: 1465994221000; $outgoing: true; $timestamp: 1465924321000; $type: 'message'; $content: 'You\'ve heard the expression, "Just believe it and it will come." Well, technically, that is true, however, \'believing\' is not just thinking that you can have it...' } ListElement { $dateSection: 1465994221000; $outgoing: true; $timestamp: 1465924321000; $type: 'message'; $content: 'https://cdn.pixabay.com/photo/2014/03/29/09/17/cat-300572_960_720.jpg You\'ve heard the expression, "Just believe it and http://writm.com/wp-content/uploads/2016/08/Cat-hd-wallpapers.jpg it will https://cdn.pixabay.com/photo/2014/03/29/09/17/cat-300572_960_720.jpg come." http://html.com/wp-content/uploads/html-com-1.png Well, technically, that is true, https://cdn.pixabay.com/photo/2014/03/29/09/17/cat-300572_960_720.jpg however, \'believing\' is not just thinking that you can have it...' }
ListElement { $dateSection: 1465994221000; $timestamp: 1465924391000; $type: 'event'; $content: 'lost_incoming_call' } ListElement { $dateSection: 1465994221000; $timestamp: 1465924391000; $type: 'event'; $content: 'lost_incoming_call' }
} }
} }
......
...@@ -45,7 +45,7 @@ Item { ...@@ -45,7 +45,7 @@ Item {
// See http://doc.qt.io/qt-5/qml-qtquick-text.html#textFormat-prop // See http://doc.qt.io/qt-5/qml-qtquick-text.html#textFormat-prop
// and http://doc.qt.io/qt-5/richtext-html-subset.html // and http://doc.qt.io/qt-5/richtext-html-subset.html
textFormat: Text.StyledText textFormat: Text.RichText
onLinkActivated: Qt.openUrlExternally(link) onLinkActivated: Qt.openUrlExternally(link)
......
...@@ -4,6 +4,12 @@ ...@@ -4,6 +4,12 @@
.pragma library .pragma library
// Options.
// If true, strings starting with `www.` can be detected.
// Not standard but helpful.
var SUPPORTS_URL = true
// Level 0. ---------------------------------------------------------- // Level 0. ----------------------------------------------------------
var URI_PCT_ENCODED = '%[A-Fa-f\\d]{2}' var URI_PCT_ENCODED = '%[A-Fa-f\\d]{2}'
...@@ -78,9 +84,11 @@ var URI_HIER_PART = '(?:' + ...@@ -78,9 +84,11 @@ var URI_HIER_PART = '(?:' +
// Regex to match URI. It respects the RFC 3986. // Regex to match URI. It respects the RFC 3986.
// But many features are not supported like IP format. // But many features are not supported like IP format.
var URI = URI_SCHEME + ':' + URI_HIER_PART + '(?:' + var URI = (SUPPORTS_URL
'\\?' + URI_QUERY + ? '(?:' + URI_SCHEME + ':' + '|' + 'www\\.' + ')'
')?' + '(?:' + '#' + URI_FRAGMENT + ')?' : URI_SCHEME + ':'
) + URI_HIER_PART + '(?:' + '\\?' + URI_QUERY + ')?' +
'(?:' + '#' + URI_FRAGMENT + ')?'
var URI_REGEX = new RegExp(URI, 'g') var URI_REGEX = new RegExp(URI, 'g')
......
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
.import 'uri-tools.js' as UriTools .import 'uri-tools.js' as UriTools
// ===================================================================
// QML helpers.
// ===================================================================
// Load by default a window in the ui/views folder. // Load by default a window in the ui/views folder.
// If options.isString is equals to true, a marshalling component can // If options.isString is equals to true, a marshalling component can
// be used. // be used.
...@@ -67,24 +71,6 @@ function openConfirmDialog (parent, options) { ...@@ -67,24 +71,6 @@ function openConfirmDialog (parent, options) {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
function _computeOptimizedCb (func, context) {
return (context != null)
? (function () {
return func.apply(context, arguments)
}) : func
}
// -------------------------------------------------------------------
// Convert a snake_case string to a lowerCamelCase string.
function snakeToCamel (s) {
return s.replace(/(\_\w)/g, function (matches) {
return matches[1].toUpperCase()
})
}
// -------------------------------------------------------------------
// A copy of `Window.setTimeout` from js. // A copy of `Window.setTimeout` from js.
// delay is in milliseconds. // delay is in milliseconds.
function setTimeout (parent, delay, cb) { function setTimeout (parent, delay, cb) {
...@@ -121,15 +107,6 @@ function connectOnce (signal, cb) { ...@@ -121,15 +107,6 @@ function connectOnce (signal, cb) {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Basic assert function.
function assert (condition, message) {
if (!condition) {
throw new Error('Assert: ' + message)
}
}
// -------------------------------------------------------------------
// Returns the top (root) parent of one object. // Returns the top (root) parent of one object.
function getTopParent (object, useFakeParent) { function getTopParent (object, useFakeParent) {
function _getTopParent (object, useFakeParent) { function _getTopParent (object, useFakeParent) {
...@@ -165,6 +142,36 @@ function qmlTypeof (object, className) { ...@@ -165,6 +142,36 @@ function qmlTypeof (object, className) {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
function encodeUrisToQmlFormat (text) {
var images = ''
text = text
.replace(/</g, '\u2063&lt;')
.replace(/>/g, '\u2063&gt;')
.replace(UriTools.URI_REGEX, function (match) {
// If it's a simple URL, transforms it in URI.
if (startsWith(match, 'www.')) {
match = 'http://' + match
}
var ext = getExtension(match)
if (includes([ 'jpg', 'jpeg', 'gif', 'png', 'svg' ], ext)) {
images += '<a href="' + match +
'"><img width="auto" height="48" src="' + match + '" /></a>'
}
return '<a href="' + match + '">' + match + '</a>'
})
if (images.length > 0) {
images = '<div>' + images + '</div>'
}
return images.concat(text)
}
// -------------------------------------------------------------------
// Test if a point is in a item. // Test if a point is in a item.
// //
// `source` is the item that generated the point. // `source` is the item that generated the point.
...@@ -181,6 +188,55 @@ function pointIsInItem (source, target, point) { ...@@ -181,6 +188,55 @@ function pointIsInItem (source, target, point) {
) )
} }
// ===================================================================
// GENERIC.
// ===================================================================
function _computeOptimizedCb (func, context) {
return (context != null)
? (function () {
return func.apply(context, arguments)
}) : func
}
// -------------------------------------------------------------------
// Convert a snake_case string to a lowerCamelCase string.
function snakeToCamel (s) {
return s.replace(/(\_\w)/g, function (matches) {
return matches[1].toUpperCase()
})
}
// -------------------------------------------------------------------
// Basic assert function.
function assert (condition, message) {
if (!condition) {
throw new Error('Assert: ' + message)
}
}
// -------------------------------------------------------------------
// Returns the extension of a filename.
function getExtension (str) {
var index = str.lastIndexOf('.')
if (index === -1) {
return ''
}
return str.slice(index + 1)
}
// -------------------------------------------------------------------
// Test if a string starts by a given string.
function startsWith (str, searchStr) {
return str.slice(0, searchStr.length) === searchStr
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Invoke a `cb` function with each value of the interval: `[0, n[`. // Invoke a `cb` function with each value of the interval: `[0, n[`.
...@@ -198,7 +254,12 @@ function times (n, cb, context) { ...@@ -198,7 +254,12 @@ function times (n, cb, context) {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Test if a var is a string. function isArray (array) {
return (array instanceof Array)
}
// -------------------------------------------------------------------
function isString (string) { function isString (string) {
return typeof string === 'string' || string instanceof String return typeof string === 'string' || string instanceof String
} }
...@@ -245,11 +306,40 @@ function genRandomNumberBetweenIntervals (intervals) { ...@@ -245,11 +306,40 @@ function genRandomNumberBetweenIntervals (intervals) {
// ------------------------------------------------------------------- // -------------------------------------------------------------------
function encodeUrisToQmlFormat (text) { // Returns an array from a `object` or `array` argument.
return text function ensureArray (obj) {
.replace(/</g, '&lt;') if (isArray(obj)) {
.replace(/>/g, '&gt;') return obj
.replace(UriTools.URI_REGEX, function (match) { }
return '<a href="' + match + '">' + match + '</a>'
}) var keys = Object.keys(obj)
var length = keys.length
var values = Array(length)
for (var i = 0; i < length; i++) {
values[i] = obj[keys[i]]
}
return values
}
// -------------------------------------------------------------------
// Test if a value is included in an array or object.
function includes (obj, value, startIndex) {
obj = ensureArray(obj)
if (startIndex == null) {
startIndex = 0
}
var length = obj.length
for (var i = startIndex; i < length; i++) {
if (value === obj[i]) {
return true
}
}
return false
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment