react-native-link-preview
Advanced tools
Comparing version 1.2.0 to 1.2.1
@@ -1,2 +0,2 @@ | ||
export const REGEX_VALID_URL = new RegExp( | ||
exports.REGEX_VALID_URL = new RegExp( | ||
"^" + | ||
@@ -36,2 +36,2 @@ // protocol identifier | ||
"$", "i" | ||
) | ||
); |
277
index.js
@@ -7,179 +7,186 @@ /** | ||
const urlObj = require('url'); | ||
const { fetch } = require('cross-fetch'); | ||
import { REGEX_VALID_URL } from './constants'; | ||
const { REGEX_VALID_URL } = require('./constants'); | ||
export default class LinkPreview { | ||
static getPreview(text) { | ||
return new Promise((resolve, reject) => { | ||
if (!text) { | ||
reject({ error: 'React-Native-Link-Preview did not receive either a url or text' }); | ||
} | ||
exports.getPreview = function(text) { | ||
return new Promise((resolve, reject) => { | ||
if (!text) { | ||
reject({ | ||
error: 'React-Native-Link-Preview did not receive either a url or text' | ||
}); | ||
} | ||
let detectedUrl = null; | ||
let detectedUrl = null; | ||
text.split(' ').forEach(token => { | ||
if (REGEX_VALID_URL.test(token) && !detectedUrl) { | ||
detectedUrl = token; | ||
} | ||
}); | ||
text.split(' ').forEach(token => { | ||
if (REGEX_VALID_URL.test(token) && !detectedUrl) { | ||
detectedUrl = token; | ||
} | ||
}); | ||
if (detectedUrl) { | ||
fetch(detectedUrl) | ||
if (detectedUrl) { | ||
fetch(detectedUrl) | ||
.then(response => response.text()) | ||
.then(text => { | ||
resolve(this._parseResponse(text, detectedUrl)); | ||
resolve(parseResponse(text, detectedUrl)); | ||
}) | ||
.catch(error => reject({ error })); | ||
} else { | ||
reject({ error: 'React-Native-Preview-Link did not find a link in the text' }); | ||
} | ||
}); | ||
} | ||
} else { | ||
reject({ | ||
error: 'React-Native-Preview-Link did not find a link in the text' | ||
}); | ||
} | ||
}); | ||
}; | ||
const parseResponse = function(body, url) { | ||
const doc = cheerio.load(body); | ||
static _parseResponse(body, url) { | ||
const doc = cheerio.load(body); | ||
return { | ||
url, | ||
title: getTitle(doc), | ||
description: getDescription(doc), | ||
mediaType: getMediaType(doc) || 'website', | ||
images: getImages(doc, url), | ||
videos: getVideos(doc) | ||
}; | ||
}; | ||
return { | ||
url, | ||
title: this._getTitle(doc), | ||
description: this._getDescription(doc), | ||
mediaType: this._getMediaType(doc) || 'website', | ||
images: this._getImages(doc, url), | ||
videos: this._getVideos(doc) | ||
}; | ||
const getTitle = function(doc) { | ||
let title = doc("meta[property='og:title']").attr('content'); | ||
if (!title) { | ||
title = doc('title').text(); | ||
} | ||
static _getTitle(doc) { | ||
let title = doc('meta[property=\'og:title\']').attr('content'); | ||
return title; | ||
}; | ||
if (!title) { | ||
title = doc('title').text(); | ||
} | ||
const getDescription = function(doc) { | ||
let description = doc('meta[name=description]').attr('content'); | ||
return title; | ||
if (description === undefined) { | ||
description = doc('meta[name=Description]').attr('content'); | ||
} | ||
static _getDescription(doc) { | ||
let description = doc('meta[name=description]').attr('content'); | ||
if (description === undefined) { | ||
description = doc("meta[property='og:description']").attr('content'); | ||
} | ||
if (description === undefined) { | ||
description = doc('meta[name=Description]').attr('content'); | ||
} | ||
return description; | ||
}; | ||
if (description === undefined) { | ||
description = doc('meta[property=\'og:description\']').attr('content'); | ||
} | ||
const getMediaType = function(doc) { | ||
const node = doc('meta[name=medium]'); | ||
return description; | ||
if (node.length) { | ||
const content = node.attr('content'); | ||
return content === 'image' ? 'photo' : content; | ||
} else { | ||
return doc("meta[property='og:type']").attr('content'); | ||
} | ||
}; | ||
static _getMediaType(doc) { | ||
const node = doc('meta[name=medium]'); | ||
const getImages = function(doc, rootUrl) { | ||
let images = [], | ||
nodes, | ||
src, | ||
dic; | ||
if (node.length) { | ||
const content = node.attr('content'); | ||
return content === 'image' ? 'photo' : content; | ||
} else { | ||
return doc('meta[property=\'og:type\']').attr('content'); | ||
} | ||
} | ||
nodes = doc("meta[property='og:image']"); | ||
static _getImages(doc, rootUrl) { | ||
let images = [], | ||
nodes, | ||
src, | ||
dic; | ||
nodes = doc('meta[property=\'og:image\']'); | ||
if (nodes.length) { | ||
nodes.each((index, node) => { | ||
src = node.attribs.content; | ||
if (src) { | ||
src = urlObj.resolve(rootUrl, src); | ||
images.push(src); | ||
} | ||
}); | ||
} | ||
if (images.length <= 0) { | ||
src = doc('link[rel=image_src]').attr('href'); | ||
if (nodes.length) { | ||
nodes.each((index, node) => { | ||
src = node.attribs.content; | ||
if (src) { | ||
src = urlObj.resolve(rootUrl, src); | ||
images = [src]; | ||
} else { | ||
nodes = doc('img'); | ||
images.push(src); | ||
} | ||
}); | ||
} | ||
if (nodes.length) { | ||
dic = {}; | ||
images = []; | ||
nodes.each((index, node) => { | ||
src = node.attribs.src; | ||
if (src && !dic[src]) { | ||
dic[src] = 1; | ||
// width = node.attribs.width; | ||
// height = node.attribs.height; | ||
images.push(urlObj.resolve(rootUrl, src)); | ||
} | ||
}); | ||
} | ||
if (images.length <= 0) { | ||
src = doc('link[rel=image_src]').attr('href'); | ||
if (src) { | ||
src = urlObj.resolve(rootUrl, src); | ||
images = [src]; | ||
} else { | ||
nodes = doc('img'); | ||
if (nodes.length) { | ||
dic = {}; | ||
images = []; | ||
nodes.each((index, node) => { | ||
src = node.attribs.src; | ||
if (src && !dic[src]) { | ||
dic[src] = 1; | ||
// width = node.attribs.width; | ||
// height = node.attribs.height; | ||
images.push(urlObj.resolve(rootUrl, src)); | ||
} | ||
}); | ||
} | ||
} | ||
return images; | ||
} | ||
static _getVideos(doc) { | ||
const videos = []; | ||
let nodeTypes; | ||
let nodeSecureUrls; | ||
let nodeType; | ||
let nodeSecureUrl; | ||
let video; | ||
let videoType; | ||
let videoSecureUrl; | ||
let width; | ||
let height; | ||
let videoObj; | ||
let index; | ||
return images; | ||
}; | ||
const nodes = doc('meta[property=\'og:video\']'); | ||
const length = nodes.length; | ||
const getVideos = function(doc) { | ||
const videos = []; | ||
let nodeTypes; | ||
let nodeSecureUrls; | ||
let nodeType; | ||
let nodeSecureUrl; | ||
let video; | ||
let videoType; | ||
let videoSecureUrl; | ||
let width; | ||
let height; | ||
let videoObj; | ||
let index; | ||
if (length) { | ||
nodeTypes = doc('meta[property=\'og:video:type\']'); | ||
nodeSecureUrls = doc('meta[property=\'og:video:secure_url\']'); | ||
width = doc('meta[property=\'og:video:width\']').attr('content'); | ||
height = doc('meta[property=\'og:video:height\']').attr('content'); | ||
const nodes = doc("meta[property='og:video']"); | ||
const length = nodes.length; | ||
for (index = 0; index < length; index++) { | ||
video = nodes[index].attribs.content; | ||
if (length) { | ||
nodeTypes = doc("meta[property='og:video:type']"); | ||
nodeSecureUrls = doc("meta[property='og:video:secure_url']"); | ||
width = doc("meta[property='og:video:width']").attr('content'); | ||
height = doc("meta[property='og:video:height']").attr('content'); | ||
nodeType = nodeTypes[index]; | ||
videoType = nodeType ? nodeType.attribs.content : null; | ||
for (index = 0; index < length; index++) { | ||
video = nodes[index].attribs.content; | ||
nodeSecureUrl = nodeSecureUrls[index]; | ||
videoSecureUrl = nodeSecureUrl ? nodeSecureUrl.attribs.content : null; | ||
nodeType = nodeTypes[index]; | ||
videoType = nodeType ? nodeType.attribs.content : null; | ||
videoObj = { url: video, secureUrl: videoSecureUrl, type: videoType, width, height }; | ||
if (videoType.indexOf('video/') === 0) { | ||
videos.splice(0, 0, videoObj); | ||
} else { | ||
videos.push(videoObj); | ||
} | ||
nodeSecureUrl = nodeSecureUrls[index]; | ||
videoSecureUrl = nodeSecureUrl ? nodeSecureUrl.attribs.content : null; | ||
videoObj = { | ||
url: video, | ||
secureUrl: videoSecureUrl, | ||
type: videoType, | ||
width, | ||
height | ||
}; | ||
if (videoType.indexOf('video/') === 0) { | ||
videos.splice(0, 0, videoObj); | ||
} else { | ||
videos.push(videoObj); | ||
} | ||
} | ||
return videos; | ||
} | ||
// static _parseMediaResponse(res, contentType, url) { | ||
// if (contentType.indexOf('image/') === 0) { | ||
// return createResponseData(url, false, '', '', contentType, 'photo', [url]); | ||
// } else { | ||
// return createResponseData(url, false, '', '', contentType); | ||
// } | ||
// } | ||
return videos; | ||
}; | ||
} | ||
// const parseMediaResponse = function(res, contentType, url) { | ||
// if (contentType.indexOf('image/') === 0) { | ||
// return createResponseData(url, false, '', '', contentType, 'photo', [url]); | ||
// } else { | ||
// return createResponseData(url, false, '', '', contentType); | ||
// } | ||
// } |
{ | ||
"name": "react-native-link-preview", | ||
"version": "1.2.0", | ||
"version": "1.2.1", | ||
"description": "", | ||
@@ -18,2 +18,3 @@ "main": "index.js", | ||
"cheerio-without-node-native": "^0.20.1", | ||
"cross-fetch": "0.0.8", | ||
"url": "^0.11.0" | ||
@@ -35,5 +36,4 @@ }, | ||
"expect.js": "^0.3.1", | ||
"jest": "^16.0.2", | ||
"node-fetch": "^1.6.3" | ||
"jest": "^16.0.2" | ||
} | ||
} |
@@ -6,2 +6,5 @@ | ||
## NodeJS support | ||
Library should now work on node environments, thanks to @uriva and @itaibs, I will not rename the library because it may cause confusion for people who try to run in a CORS protected environment (ex. google chrome), since this does not happen for RN that was the original intention of the package. | ||
## Getting started | ||
@@ -14,8 +17,4 @@ | ||
1.0.x versions: | ||
The parsing is done automatically via [Autolinker](https://github.com/gregjacobs/Autolinker.js/), if you have problems getting your URL recognized you can dig their documentation for a valid regex. | ||
URL parsing is done via: https://gist.github.com/dperini/729294 | ||
1.1.x versions: | ||
Parsing is simplified to avoid dependency on Autolinker and having to double check for malformed URLs, basically: string is splitted by space characters and each token is tested against propper regex (https://gist.github.com/dperini/729294), if you have any problems with this please create a ticket, haven't tested all possible cases where this could fail. | ||
```javascript | ||
@@ -22,0 +21,0 @@ import LinkPreview from 'react-native-link-preview'; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
14
246
143022
3
15
45
+ Addedcross-fetch@0.0.8
+ Addedcross-fetch@0.0.8(transitive)
+ Addedencoding@0.1.13(transitive)
+ Addediconv-lite@0.6.3(transitive)
+ Addedis-stream@1.1.0(transitive)
+ Addednode-fetch@1.7.3(transitive)
+ Addedwhatwg-fetch@2.0.3(transitive)