react-tiny-link
Advanced tools
Comparing version 1.0.2 to 1.1.0
{ | ||
"name": "react-tiny-link", | ||
"version": "1.0.2", | ||
"version": "1.1.0", | ||
"main": "lib/index.js", | ||
@@ -51,2 +51,3 @@ "dependencies": { | ||
"devDependencies": { | ||
"conventional-github-releaser": "^3.1.2", | ||
"eslint-config-prettier": "^4.0.0", | ||
@@ -63,5 +64,4 @@ "eslint-plugin-prettier": "^3.0.1", | ||
"webpack-merge": "^4.2.1", | ||
"yarn": "^1.15.2", | ||
"conventional-github-releaser": "^3.1.2" | ||
"yarn": "^1.17.3" | ||
} | ||
} |
@@ -1,3 +0,1 @@ | ||
# React-Tiny-Link | ||
@@ -7,9 +5,4 @@ | ||
Yet anotherReact link preview component with cards for web without a specific backend. | ||
[![npm version](https://badge.fury.io/js/react-tiny-link.svg)](https://badge.fury.io/js/react-tiny-link) ![npm](https://img.shields.io/npm/v/react-tiny-link.svg) ![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/winhtaikaung/react-tiny-link.svg) ![NPM](https://img.shields.io/npm/l/react-tiny-link.svg) | ||
@@ -19,19 +12,8 @@ | ||
[![NPM](https://nodei.co/npm/react-tiny-link.png)](https://nodei.co/npm/react-tiny-link/) | ||
## CORS enabled? | ||
No. You may need a `CORS` proxy to use this component. But if you dont have one, we made the component to use https://cors-anywhere.herokuapp.com as default proxy. Thanks to [Rob](https://github.com/Rob--W). [It](https://cors-anywhere.herokuapp.com) saves my time for accessing urls. | ||
## Installation | ||
@@ -47,48 +29,35 @@ | ||
````javascript | ||
```javascript | ||
import ReactTinyLink from 'react-tiny-link' | ||
import ReactTinyLink from 'react-tiny-link'; | ||
<ReactTinyLink | ||
cardSize="small" | ||
showGraphic={true} | ||
maxLine={2} | ||
minLine={1} | ||
url="https://www.amazon.com/Steve-Madden-Mens-Jagwar-10-5/dp/B016X44MKA/ref=lp_18637582011_1_1?srs=18637582011&ie=UTF8&qid=1550721409&sr=8-1" | ||
;<ReactTinyLink | ||
cardSize="small" | ||
showGraphic={true} | ||
maxLine={2} | ||
minLine={1} | ||
url="https://www.amazon.com/Steve-Madden-Mens-Jagwar-10-5/dp/B016X44MKA/ref=lp_18637582011_1_1?srs=18637582011&ie=UTF8&qid=1550721409&sr=8-1" | ||
/> | ||
``` | ||
```` | ||
## Props & methods | ||
| PropName | Description | PropType | value | required | | ||
| ---------------- | -------------------------------------------------------- | -------- | ---------------------------------------------- | -------- | | ||
| **url** | URL to be display as preview | string | | `true` | | ||
| **cardSize** | Size of the card | string | default (`small`) `small`,`large` | `false` | | ||
| **maxLine** | Maximum number of line to ellipsis | number | 2 | `false` | | ||
| **minLine** | Minimum number of line to ellipsis | number | 1 | `false` | | ||
| **width** | Width of the link preview card | number | default(`100vw`) | `false` | | ||
| **header** | Default Header content | string | null | `false` | | ||
| **description** | Default description content | string | null | `false` | | ||
| **proxyUrl** | Proxy URL to pass that resolve CORS | string | default(`https://cors-anywhere.herokuapp.com`) | `false` | | ||
| **showGraphic** | Boolean value to display graphics | boolean | default(`true`) | `false` | | ||
| **autoPlay** | Boolean value to play the media if provided url is video | boolean | default(`false`) | `false` | | ||
| **defaultMedia** | Default value to provide the media for failure cases | string | N.A | `false` | | ||
| PropName | Description|PropType | value | required | ||
|--|--|--|--|--| | ||
|**url** | URL to be display as preview | string | |`true` | ||
|**cardSize** | Size of the card | string |default (`small`) `small`,`large`|`false` | ||
|**maxLine** | Maximum number of line to ellipsis | number | 2 |`false` | ||
|**minLine** | Minimum number of line to ellipsis | number | 1 |`false` | ||
|**width** | Width of the link preview card | number| default(`100vw`)|`false` | ||
|**header** | Default Header content | string | null |`false` | ||
|**description** | Default description content | string | null |`false` | ||
|**proxyUrl** | Proxy URL to pass that resolve CORS | string|default(`https://cors-anywhere.herokuapp.com`) |`false` | ||
|**showGraphic** | Boolean value to display graphics | boolean|default(`true`) |`false` | ||
|**autoPlay** | Boolean value to play the media if provided url is video | boolean|default(`false`) |`false` | ||
## Demo App & | ||
* [Demo](https://winhtaikaung.github.io/react-tiny-link/) | ||
- [Demo](https://winhtaikaung.github.io/react-tiny-link/) | ||
* [SourceCode](https://github.com/winhtaikaung/react-tiny-link/) | ||
- [SourceCode](https://github.com/winhtaikaung/react-tiny-link/) | ||
@@ -101,3 +70,2 @@ ## CodeSandbox | ||
1. Fork it | ||
@@ -129,2 +97,2 @@ | ||
![Twitter Follow](https://img.shields.io/twitter/follow/winhtaikaung.svg?style=social) | ||
![Twitter Follow](https://img.shields.io/twitter/follow/winhtaikaung.svg?style=social) |
@@ -7,3 +7,4 @@ export declare enum ReactTinyLinkType { | ||
TYPE_IMAGE = "TYPE_IMAGE", | ||
TYPE_DEFAULT = "TYPE_DEFAULT" | ||
TYPE_DEFAULT = "TYPE_DEFAULT", | ||
TYPE_INSTAGRAM = "TYPE_INSTAGTAM" | ||
} | ||
@@ -22,2 +23,3 @@ export declare type CardSizeType = 'small' | 'large'; | ||
autoPlay: boolean; | ||
defaultMedia?: string; | ||
} | ||
@@ -24,0 +26,0 @@ export interface IReactTinyLinkData { |
export enum ReactTinyLinkType { | ||
TYPE_AMAZON = 'TYPE_AMAZON', | ||
TYPE_YOUTUBE = 'TYPE_YOUTUBE', | ||
TYPE_AUDIO = 'TYPE_AUDIO', | ||
TYPE_VIDEO = 'TYPE_VIDEO', | ||
TYPE_IMAGE = 'TYPE_IMAGE', | ||
TYPE_DEFAULT = 'TYPE_DEFAULT', | ||
} | ||
TYPE_AMAZON = 'TYPE_AMAZON', | ||
TYPE_YOUTUBE = 'TYPE_YOUTUBE', | ||
TYPE_AUDIO = 'TYPE_AUDIO', | ||
TYPE_VIDEO = 'TYPE_VIDEO', | ||
TYPE_IMAGE = 'TYPE_IMAGE', | ||
TYPE_DEFAULT = 'TYPE_DEFAULT', | ||
TYPE_INSTAGRAM = 'TYPE_INSTAGTAM', | ||
} | ||
export type CardSizeType = 'small' | 'large'; | ||
export type CardSizeType = 'small' | 'large' | ||
export interface IReactTinyLinkProps { | ||
cardSize: CardSizeType; | ||
maxLine: number; | ||
minLine: number; | ||
header: string; | ||
description: string; | ||
url: string; | ||
width: string | number; | ||
proxyUrl: string; | ||
showGraphic: boolean; | ||
autoPlay: boolean; | ||
} | ||
export interface IReactTinyLinkData { | ||
description: string; | ||
image: string[]; | ||
title: string; | ||
type: ReactTinyLinkType; | ||
video: string[]; | ||
url: string; | ||
} | ||
export interface IReactTinyLinkState { | ||
data: IReactTinyLinkData; | ||
loading: boolean; | ||
} | ||
cardSize: CardSizeType | ||
maxLine: number | ||
minLine: number | ||
header: string | ||
description: string | ||
url: string | ||
width: string | number | ||
proxyUrl: string | ||
showGraphic: boolean | ||
autoPlay: boolean | ||
defaultMedia?: string | ||
} | ||
export interface IReactTinyLinkData { | ||
description: string | ||
image: string[] | ||
title: string | ||
type: ReactTinyLinkType | ||
video: string[] | ||
url: string | ||
} | ||
export interface IReactTinyLinkState { | ||
data: IReactTinyLinkData | ||
loading: boolean | ||
} |
import { ReactTinyLinkType } from '../../ReactTinyLinkTypes'; | ||
export declare const ScrapAmazon: (url: any, htmlDoc: any) => Promise<{ | ||
export declare const ScrapAmazon: (url: any, htmlDoc: any, defaultMedia: any) => Promise<{ | ||
title: any; | ||
content: any; | ||
url: any; | ||
image: string[]; | ||
image: any[]; | ||
description: any; | ||
@@ -8,0 +8,0 @@ video: any[]; |
@@ -1,10 +0,13 @@ | ||
import { ReactTinyLinkType } from '../../ReactTinyLinkTypes'; | ||
import { isEmpty, getTitleOfDoc, getAttrOfDocElement, fixRelativeUrls } from "../utils"; | ||
import { ReactTinyLinkType } from '../../ReactTinyLinkTypes' | ||
import { isEmpty, getTitleOfDoc, getAttrOfDocElement, fixRelativeUrls } from '../utils' | ||
export const ScrapAmazon = async (url, htmlDoc) => { | ||
let baseUrl = getAttrOfDocElement(htmlDoc, "base", 'href'); | ||
export const ScrapAmazon = async (url, htmlDoc, defaultMedia) => { | ||
let baseUrl = getAttrOfDocElement(htmlDoc, 'base', 'href') | ||
if (!baseUrl) { | ||
baseUrl = url; | ||
baseUrl = url | ||
} | ||
const image = [ | ||
getAttrOfDocElement(htmlDoc, '.a-dynamic-image', 'data-old-hires'), | ||
getAttrOfDocElement(htmlDoc, '.a-dynamic-image', 'src'), | ||
] | ||
return { | ||
@@ -14,11 +17,6 @@ title: getTitleOfDoc(htmlDoc), | ||
url: getAttrOfDocElement(htmlDoc, "meta[property='og:url']", 'content'), | ||
image: [ | ||
getAttrOfDocElement(htmlDoc, '.a-dynamic-image', 'data-old-hires'), | ||
getAttrOfDocElement(htmlDoc, '.a-dynamic-image', 'src'), | ||
].filter(i => !isEmpty(i)).map((i => fixRelativeUrls(baseUrl, i))), | ||
description: getAttrOfDocElement( | ||
htmlDoc, | ||
"meta[name='description']", | ||
'content', | ||
), | ||
image: !defaultMedia | ||
? image.filter(i => !isEmpty(i)).map(i => fixRelativeUrls(baseUrl, i)) | ||
: [...image, defaultMedia].filter(i => !isEmpty(i)), | ||
description: getAttrOfDocElement(htmlDoc, "meta[name='description']", 'content'), | ||
video: [], | ||
@@ -28,2 +26,2 @@ type: ReactTinyLinkType.TYPE_AMAZON, // MIME Type | ||
} | ||
}; | ||
} |
import { ReactTinyLinkType } from '../../ReactTinyLinkTypes'; | ||
export declare const ScrapAudio: (url: any) => Promise<{ | ||
export declare const ScrapAudio: (url: any, defaultMedia: any) => Promise<{ | ||
title: any; | ||
@@ -4,0 +4,0 @@ description: any; |
@@ -1,5 +0,5 @@ | ||
import { ReactTinyLinkType } from '../../ReactTinyLinkTypes'; | ||
const MusicLogo = require('../../assets/music.svg'); | ||
import { ReactTinyLinkType } from '../../ReactTinyLinkTypes' | ||
import { isEmpty } from '../utils' | ||
export const ScrapAudio = async url => { | ||
export const ScrapAudio = async (url, defaultMedia) => { | ||
return { | ||
@@ -9,6 +9,6 @@ title: url.substring(url.lastIndexOf('/') + 1), | ||
url: url, | ||
image: [MusicLogo], | ||
image: [defaultMedia].filter(i => !isEmpty(i)), | ||
video: [], | ||
type: ReactTinyLinkType.TYPE_AUDIO, | ||
}; | ||
}; | ||
} | ||
} |
import { ReactTinyLinkType } from '../../ReactTinyLinkTypes'; | ||
declare const _default: (url: any, htmlDoc: any) => Promise<{ | ||
declare const _default: (url: any, htmlDoc: any, defaultMedia: any) => Promise<{ | ||
title: any; | ||
@@ -8,5 +8,5 @@ content: any; | ||
video: any[]; | ||
image: string[]; | ||
image: any[]; | ||
type: ReactTinyLinkType; | ||
}>; | ||
export default _default; |
@@ -1,44 +0,38 @@ | ||
import { ReactTinyLinkType } from '../../ReactTinyLinkTypes'; | ||
import { isEmpty, getTitleOfDoc, getAttrOfDocElement, fixRelativeUrls } from "../utils"; | ||
import { ReactTinyLinkType } from '../../ReactTinyLinkTypes' | ||
import { isEmpty, getTitleOfDoc, getAttrOfDocElement, fixRelativeUrls } from '../utils' | ||
export default async (url, htmlDoc) => { | ||
let baseUrl = getAttrOfDocElement(htmlDoc, "base", 'href'); | ||
export default async (url, htmlDoc, defaultMedia) => { | ||
let baseUrl = getAttrOfDocElement(htmlDoc, 'base', 'href') | ||
if (!baseUrl) { | ||
baseUrl = url; | ||
baseUrl = url | ||
} | ||
const image = [ | ||
getAttrOfDocElement(htmlDoc, 'meta[property="og:logo"]', 'content'), | ||
getAttrOfDocElement(htmlDoc, 'meta[itemprop="logo"]', 'content'), | ||
getAttrOfDocElement(htmlDoc, 'img[itemprop="logo"]', 'src'), | ||
getAttrOfDocElement(htmlDoc, "meta[property='og:image']", 'content'), | ||
getAttrOfDocElement(htmlDoc, 'img[class*="logo" i]', 'src'), | ||
getAttrOfDocElement(htmlDoc, 'img[src*="logo" i]', 'src'), | ||
getAttrOfDocElement(htmlDoc, 'meta[property="og:image:secure_url"]', 'content'), | ||
getAttrOfDocElement(htmlDoc, 'meta[property="og:image:url"]', 'content'), | ||
getAttrOfDocElement(htmlDoc, 'meta[property="og:image"]', 'content'), | ||
getAttrOfDocElement(htmlDoc, 'meta[name="twitter:image:src"]', 'content'), | ||
getAttrOfDocElement(htmlDoc, 'meta[name="twitter:image"]', 'content'), | ||
getAttrOfDocElement(htmlDoc, 'meta[itemprop="image"]', 'content'), | ||
] | ||
.filter(i => !isEmpty(i)) | ||
.map(i => fixRelativeUrls(baseUrl, i)) | ||
return { | ||
title: getTitleOfDoc(htmlDoc), | ||
content: getAttrOfDocElement( | ||
htmlDoc, | ||
"meta[name='description']", | ||
'content', | ||
), | ||
content: getAttrOfDocElement(htmlDoc, "meta[name='description']", 'content'), | ||
url: getAttrOfDocElement(htmlDoc, "meta[property='og:url']", 'content'), | ||
description: getAttrOfDocElement( | ||
htmlDoc, | ||
"meta[name='description']", | ||
'content', | ||
), | ||
description: getAttrOfDocElement(htmlDoc, "meta[name='description']", 'content'), | ||
video: [], | ||
image: [ | ||
getAttrOfDocElement(htmlDoc, 'meta[property="og:logo"]', 'content'), | ||
getAttrOfDocElement(htmlDoc, 'meta[itemprop="logo"]', 'content'), | ||
getAttrOfDocElement(htmlDoc, 'img[itemprop="logo"]', 'src'), | ||
getAttrOfDocElement(htmlDoc, "meta[property='og:image']", 'content'), | ||
getAttrOfDocElement(htmlDoc, 'img[class*="logo" i]', 'src'), | ||
getAttrOfDocElement(htmlDoc, 'img[src*="logo" i]', 'src'), | ||
getAttrOfDocElement( | ||
htmlDoc, | ||
'meta[property="og:image:secure_url"]', | ||
'content', | ||
), | ||
getAttrOfDocElement(htmlDoc, 'meta[property="og:image:url"]', 'content'), | ||
getAttrOfDocElement(htmlDoc, 'meta[property="og:image"]', 'content'), | ||
getAttrOfDocElement(htmlDoc, 'meta[name="twitter:image:src"]', 'content'), | ||
getAttrOfDocElement(htmlDoc, 'meta[name="twitter:image"]', 'content'), | ||
getAttrOfDocElement(htmlDoc, 'meta[itemprop="image"]', 'content'), | ||
].filter(i => !isEmpty(i)).map((i => fixRelativeUrls(baseUrl, i))), | ||
image: !defaultMedia | ||
? image.filter(i => !isEmpty(i)).map(i => fixRelativeUrls(baseUrl, i)) | ||
: [...image, defaultMedia].filter(i => !isEmpty(i)), | ||
type: ReactTinyLinkType.TYPE_DEFAULT, // MIME Type | ||
}; | ||
}; | ||
} | ||
} |
import { ReactTinyLinkType } from '../../ReactTinyLinkTypes'; | ||
export declare const ScrapImage: (url: any) => Promise<{ | ||
export declare const ScrapImage: (url: any, defaultMedia: any) => Promise<{ | ||
title: any; | ||
@@ -4,0 +4,0 @@ description: any; |
@@ -1,5 +0,5 @@ | ||
import { ReactTinyLinkType } from '../../ReactTinyLinkTypes'; | ||
import { isEmpty } from '../utils'; | ||
import { ReactTinyLinkType } from '../../ReactTinyLinkTypes' | ||
import { isEmpty } from '../utils' | ||
export const ScrapImage = async url => ({ | ||
export const ScrapImage = async (url, defaultMedia) => ({ | ||
title: url.substring(url.lastIndexOf('/') + 1), | ||
@@ -9,4 +9,4 @@ description: url.substring(url.lastIndexOf('/') + 1), | ||
video: [], | ||
image: [url].filter(i => !isEmpty(i)), | ||
image: [url, defaultMedia].filter(i => !isEmpty(i)), | ||
type: ReactTinyLinkType.TYPE_IMAGE, | ||
}); | ||
}) |
@@ -1,2 +0,2 @@ | ||
export declare const ScraperWraper: (url: any, httpClient: any) => Promise<{ | ||
export declare const ScraperWraper: (url: any, httpClient: any, defaultMedia: any) => Promise<{ | ||
title: any; | ||
@@ -3,0 +3,0 @@ description: any; |
@@ -1,39 +0,32 @@ | ||
import { | ||
isVideo, | ||
isAudio, | ||
isImage, | ||
isYoutubeUrl, | ||
isAmazonUrl, | ||
isEmpty, | ||
} from './utils'; | ||
import { ScrapVideo } from './Video/ScrapVideo'; | ||
import { ScrapAudio } from './Audio/ScrapAudio'; | ||
import { ScrapImage } from './Image/ScrapImage'; | ||
import { ScrapYoutube } from './Youtube/ScrapYoutube'; | ||
import { ScrapAmazon } from './Amazon/ScrapAmazon'; | ||
import ScrapDefault from './Default/ScrapDefault'; | ||
import { isVideo, isAudio, isImage, isYoutubeUrl, isAmazonUrl, isEmpty, isInstagramUrl } from './utils' | ||
import { ScrapVideo } from './Video/ScrapVideo' | ||
import { ScrapAudio } from './Audio/ScrapAudio' | ||
import { ScrapImage } from './Image/ScrapImage' | ||
import { ScrapYoutube } from './Youtube/ScrapYoutube' | ||
import { ScrapAmazon } from './Amazon/ScrapAmazon' | ||
import ScrapDefault from './Default/ScrapDefault' | ||
import ScrapInstagram from './Instagram/ScrapInstagram' | ||
export const ScraperWraper = async (url, httpClient) => { | ||
export const ScraperWraper = async (url, httpClient, defaultMedia) => { | ||
if (!isEmpty(url)) { | ||
const response = await httpClient; | ||
const mimeType = response.headers.get('content-type'); | ||
const data = await response.text(); | ||
const response = await httpClient | ||
const mimeType = response.headers.get('content-type') | ||
const data = await response.text() | ||
const htmlDoc = new DOMParser().parseFromString(data, 'text/html') | ||
if (isVideo(mimeType)) { | ||
return await ScrapVideo(url); | ||
return await ScrapVideo(url, defaultMedia) | ||
} else if (isAudio(mimeType)) { | ||
return await ScrapAudio(url); | ||
return await ScrapAudio(url, defaultMedia) | ||
} else if (isImage(mimeType)) { | ||
return await ScrapImage(url); | ||
return await ScrapImage(url, defaultMedia) | ||
} else if (isInstagramUrl(url)) { | ||
return await ScrapInstagram(url, htmlDoc, data, defaultMedia) | ||
} else if (isYoutubeUrl(url)) { | ||
let htmlDoc = new DOMParser().parseFromString(data, 'text/html'); | ||
return await ScrapYoutube(url, htmlDoc); | ||
return await ScrapYoutube(url, htmlDoc, defaultMedia) | ||
} else if (isAmazonUrl(url)) { | ||
let htmlDoc = new DOMParser().parseFromString(data, 'text/html'); | ||
return await ScrapAmazon(url, htmlDoc); | ||
return await ScrapAmazon(url, htmlDoc, defaultMedia) | ||
} else { | ||
let htmlDoc = new DOMParser().parseFromString(data, 'text/html'); | ||
const resp = await ScrapDefault(url, htmlDoc); | ||
return resp; | ||
return await ScrapDefault(url, htmlDoc, defaultMedia) | ||
} | ||
} | ||
}; | ||
} |
export declare const isAmazonUrl: (url: any) => boolean; | ||
export declare const isYoutubeUrl: (url: any) => boolean; | ||
export declare const isInstagramUrl: (url: any) => boolean; | ||
export declare const isEmpty: (value: any) => any; | ||
@@ -10,2 +11,3 @@ export declare const isAudio: (mimeType: string) => boolean; | ||
export declare const getYoutTubeVideoId: (url: string) => string; | ||
export declare const getInstagramVideo: (htmlDoc: any) => string; | ||
export declare const fixRelativeUrls: (baseUrl: string, itemUrl: string) => string; |
@@ -1,7 +0,10 @@ | ||
const REGEX_AMAZON_URL = /https?:\/\/(.*amazon\..*\/.*|.*amzn\..*\/.*|.*a\.co\/.*)/i; | ||
export const isAmazonUrl = url => REGEX_AMAZON_URL.test(url); | ||
const REGEX_AMAZON_URL = /https?:\/\/(.*amazon\..*\/.*|.*amzn\..*\/.*|.*a\.co\/.*)/i | ||
export const isAmazonUrl = url => REGEX_AMAZON_URL.test(url) | ||
const REGEX_YOUTUBE = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.?be)\/.+$/g; | ||
export const isYoutubeUrl = url => REGEX_YOUTUBE.test(url); | ||
const REGEX_YOUTUBE = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.?be)\/.+$/g | ||
export const isYoutubeUrl = url => REGEX_YOUTUBE.test(url) | ||
const REGEX_INSTAGRAM = /(https?:\/\/www\.)?instagram\.com(\/p\/\w+\/?)/gi | ||
export const isInstagramUrl = url => REGEX_INSTAGRAM.test(url) | ||
export const isEmpty = (value: any) => { | ||
@@ -12,5 +15,5 @@ let isEmptyObject = function(a) { | ||
let hasNonempty = Object.keys(a).some(function nonEmpty(element) { | ||
return !isEmpty(a[element]); | ||
}); | ||
return hasNonempty ? false : isEmptyObject(Object.keys(a)); | ||
return !isEmpty(a[element]) | ||
}) | ||
return hasNonempty ? false : isEmptyObject(Object.keys(a)) | ||
} | ||
@@ -20,5 +23,5 @@ | ||
// check if array is really not empty as JS thinks | ||
return !isEmpty(element); // at least one element should be non-empty | ||
}); | ||
}; | ||
return !isEmpty(element) // at least one element should be non-empty | ||
}) | ||
} | ||
return ( | ||
@@ -29,46 +32,53 @@ value == false || | ||
(typeof value === 'object' && isEmptyObject(value)) | ||
); | ||
}; | ||
) | ||
} | ||
export const isAudio = (mimeType: string) => mimeType.startsWith('audio/'); | ||
export const isVideo = (mimeType: string) => mimeType.startsWith('video/'); | ||
export const isImage = (mimeType: string) => mimeType.startsWith('image/'); | ||
export const isAudio = (mimeType: string) => mimeType.startsWith('audio/') | ||
export const isVideo = (mimeType: string) => mimeType.startsWith('video/') | ||
export const isImage = (mimeType: string) => mimeType.startsWith('image/') | ||
// Basic Scrap Helpers | ||
export const getTitleOfDoc = (htmlDoc: any) => { | ||
const titleEl = htmlDoc.querySelector('title'); | ||
const titleEl = htmlDoc.querySelector('title') | ||
if (!titleEl) { | ||
return null; | ||
return null | ||
} | ||
return titleEl.innerText; | ||
}; | ||
return titleEl.innerText | ||
} | ||
export const getAttrOfDocElement = ( | ||
htmlDoc: any, | ||
query: string, | ||
attr: string, | ||
) => { | ||
const el = htmlDoc.querySelector(query); | ||
export const getAttrOfDocElement = (htmlDoc: any, query: string, attr: string) => { | ||
const el = htmlDoc.querySelector(query) | ||
if (!el) { | ||
return null; | ||
return null | ||
} | ||
return el.getAttribute(attr); | ||
return el.getAttribute(attr) | ||
} | ||
export const getYoutTubeVideoId = (url: string) => { | ||
const parsed = url.match(/^.*((m\.)?youtu\.be\/|vi?\/|u\/\w\/|embed\/|\?vi?=|\&vi?=)([^#\&\?]*).*/); | ||
const parsed = url.match(/^.*((m\.)?youtu\.be\/|vi?\/|u\/\w\/|embed\/|\?vi?=|\&vi?=)([^#\&\?]*).*/) | ||
if (parsed && parsed[3]) { | ||
return parsed[3]; | ||
return parsed[3] | ||
} else { | ||
return null; | ||
return null | ||
} | ||
} | ||
export const getInstagramVideo = (htmlDoc: any) => { | ||
const videoLinkMatcher = /(?:"video_url":")(.*?)(?:")/g | ||
if (videoLinkMatcher.test(htmlDoc)) { | ||
const videoMatches = videoLinkMatcher.exec(htmlDoc) | ||
if (videoMatches && videoMatches.length !== 0) { | ||
return videoMatches[0].split('":"')[1].replace('"', '') | ||
} | ||
} | ||
return null | ||
} | ||
export const fixRelativeUrls = (baseUrl: string, itemUrl: string) => { | ||
const normalizedUrl = itemUrl.toLocaleLowerCase(); | ||
if (normalizedUrl.startsWith("http://") || normalizedUrl.startsWith("https://")) { | ||
return itemUrl; | ||
const normalizedUrl = itemUrl.toLocaleLowerCase() | ||
if (normalizedUrl.startsWith('http://') || normalizedUrl.startsWith('https://')) { | ||
return itemUrl | ||
} | ||
return baseUrl + itemUrl; | ||
return baseUrl + itemUrl | ||
} |
import { ReactTinyLinkType } from '../../ReactTinyLinkTypes'; | ||
export declare const ScrapVideo: (url: any) => Promise<{ | ||
export declare const ScrapVideo: (url: any, defaultMedia: any) => Promise<{ | ||
title: any; | ||
@@ -4,0 +4,0 @@ description: any; |
@@ -1,4 +0,5 @@ | ||
import { ReactTinyLinkType } from '../../ReactTinyLinkTypes'; | ||
import { ReactTinyLinkType } from '../../ReactTinyLinkTypes' | ||
import { isEmpty } from '../utils' | ||
export const ScrapVideo = async url => { | ||
export const ScrapVideo = async (url, defaultMedia) => { | ||
return { | ||
@@ -8,6 +9,6 @@ title: url.substring(url.lastIndexOf('/') + 1), | ||
image: [], | ||
video: [url], | ||
video: [url, defaultMedia].filter(i => !isEmpty(i)), | ||
url: url, | ||
type: ReactTinyLinkType.TYPE_VIDEO, | ||
}; | ||
}; | ||
} | ||
} |
import { ReactTinyLinkType } from '../../ReactTinyLinkTypes'; | ||
export declare const ScrapYoutube: (url: any, htmlDoc: any) => Promise<{ | ||
export declare const ScrapYoutube: (url: any, htmlDoc: any, defaultMedia: any) => Promise<{ | ||
title: any; | ||
@@ -8,3 +8,3 @@ url: any; | ||
video: any[]; | ||
image: string[]; | ||
image: any[]; | ||
}>; |
@@ -1,8 +0,14 @@ | ||
import { ReactTinyLinkType } from '../../ReactTinyLinkTypes'; | ||
import { isEmpty, getYoutTubeVideoId } from "../utils"; | ||
import { ReactTinyLinkType } from '../../ReactTinyLinkTypes' | ||
import { isEmpty, getYoutTubeVideoId } from '../utils' | ||
const titleRegex = /"title":"(.+?)"/g; | ||
const titleRegex = /"title":"(.+?)"/g | ||
export const ScrapYoutube = async (url, htmlDoc) => { | ||
const id = getYoutTubeVideoId(url); | ||
export const ScrapYoutube = async (url, htmlDoc, defaultMedia) => { | ||
const id = getYoutTubeVideoId(url) | ||
const image = [ | ||
`https://img.youtube.com/vi/${id}/0.jpg`, | ||
`https://img.youtube.com/vi/${id}/1.jpg`, | ||
`https://img.youtube.com/vi/${id}/2.jpg`, | ||
`https://img.youtube.com/vi/${id}/3.jpg`, | ||
] | ||
try { | ||
@@ -16,3 +22,3 @@ const { title } = JSON.parse( | ||
}}`, | ||
); | ||
) | ||
return { | ||
@@ -24,9 +30,4 @@ title: title, | ||
video: [], | ||
image: [ | ||
`https://img.youtube.com/vi/${id}/0.jpg`, | ||
`https://img.youtube.com/vi/${id}/1.jpg`, | ||
`https://img.youtube.com/vi/${id}/2.jpg`, | ||
`https://img.youtube.com/vi/${id}/3.jpg`, | ||
].filter(i => !isEmpty(i)), | ||
}; | ||
image: image.filter(i => !isEmpty(i)), | ||
} | ||
} catch (error) { | ||
@@ -39,10 +40,5 @@ return { | ||
video: [], | ||
image: [ | ||
`https://img.youtube.com/vi/${id}/0.jpg`, | ||
`https://img.youtube.com/vi/${id}/1.jpg`, | ||
`https://img.youtube.com/vi/${id}/2.jpg`, | ||
`https://img.youtube.com/vi/${id}/3.jpg`, | ||
].filter(i => !isEmpty(i)), | ||
}; | ||
image: !defaultMedia ? image.filter(i => !isEmpty(i)) : [...image, defaultMedia].filter(i => !isEmpty(i)), | ||
} | ||
} | ||
}; | ||
} |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
52
685979
3084
94