Skip to content

Commit

Permalink
Merge c09ad28 into 1bcba39
Browse files Browse the repository at this point in the history
  • Loading branch information
ndaidong authored Sep 21, 2022
2 parents 1bcba39 + c09ad28 commit 1a4e6e4
Show file tree
Hide file tree
Showing 14 changed files with 219 additions and 80 deletions.
86 changes: 66 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,28 +64,25 @@ View [more examples](https://github.com/ndaidong/oembed-parser/tree/main/example

## APIs

### `.extract(String url [, Object params])`
### `.extract()`

Load and extract oembed data.

Example:
#### Syntax

```js
import { extract } from 'oembed-parser'
extract(String url)
extract(String url, Object params)
extract(String url, Object params, Object fetchOptions)
```

const getOembed = async (url) => {
try {
const oembed = await extract(url)
return oembed
} catch (err) {
console.trace(err)
return null
}
}
#### Parameters

const data = getOembed('your url')
console.log(data)
```
##### `url` *required*

URL of a valid oEmbed resource, e.g. `https://www.youtube.com/watch?v=x2bqscVkGxk`

##### `params` *optional*

Optional argument `params` can be useful when you want to specify some additional customizations.

Expand All @@ -99,15 +96,62 @@ Here are several popular params:
Note that some params are supported by these providers but not by the others.
Please see the provider's oEmbed API docs carefully for exact information.

##### `fetchOptions` *optional*

You can use this param to set request headers to fetch.

For example:

```js
import { extract } from 'oembed-parser'

const url = 'https://codepen.io/ndaidong/pen/LYmLKBw'
extract(url, null, {
headers: {
'user-agent': 'Opera/9.60 (Windows NT 6.0; U; en) Presto/2.1.1'
}
})
```

You can also specify a proxy endpoint to load remote content, instead of fetching directly.

### `.setProviderList(Array providers)`
For example:

```js
import { extract } from 'oembed-parser'

const url = 'https://codepen.io/ndaidong/pen/LYmLKBw'
extract(url, null, {
headers: {
'user-agent': 'Opera/9.60 (Windows NT 6.0; U; en) Presto/2.1.1'
},
proxy: {
target: 'https://your-secret-proxy.io/loadJson?url=',
headers: {
'Proxy-Authorization': 'Bearer YWxhZGRpbjpvcGVuc2VzYW1l...'
}
}
})
```

With the above setting, request will be forwarded to `https://your-secret-proxy.io/loadJson?url={OEMBED_ENDPOINT}`.


### `.setProviderList()`

Apply a list of providers to use, overriding the [default](https://raw.githubusercontent.com/ndaidong/oembed-parser/master/src/utils/providers.json).

This can be useful for whitelisting only certain providers, or for adding
custom providers.
#### Syntax

Default list of resource providers is synchronized from [oembed.com](http://oembed.com/providers.json).
```js
setProviderList(Array providers)
```

#### Parameters

##### `providers` *required*

List of providers to apply.

For example:

Expand All @@ -134,6 +178,9 @@ const providers = [
setProviderList(providers)
```

Default list of resource providers is synchronized from [oembed.com](http://oembed.com/providers.json).


## Facebook and Instagram

In order to work with the links from Facebook and Instagram, you need a [reviewed Facebook's app](https://developers.facebook.com/docs/app-review) with [oEmbed Read](https://developers.facebook.com/docs/features-reference/oembed-read) permission.
Expand All @@ -149,7 +196,6 @@ export FACEBOOK_CLIENT_TOKEN=your_client_token
npm run eval https://www.instagram.com/tv/CVlR5GFqF68/
```


## License
The MIT License (MIT)

Expand Down
39 changes: 24 additions & 15 deletions dist/cjs/oembed-parser.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// oembed-parser@3.1.0, by @ndaidong - built with esbuild at 2022-09-19T09:58:58.156Z - published under MIT license
// oembed-parser@3.1.1, by @ndaidong - built with esbuild at 2022-09-21T15:03:39.445Z - published under MIT license
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
Expand Down Expand Up @@ -2921,19 +2921,31 @@ var getDomain = (url) => {

// src/utils/retrieve.js
var import_cross_fetch = __toESM(require_node_ponyfill(), 1);
var retrieve_default = async (url) => {
const res = await (0, import_cross_fetch.default)(url, {
headers: {
"user-agent": "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0"
}
var profetch = async (url, proxy = {}) => {
const {
target,
headers = {}
} = proxy;
const res = await (0, import_cross_fetch.default)(target + encodeURIComponent(url), {
headers
});
return res;
};
var retrieve_default = async (url, options = {}) => {
const {
headers = {
"user-agent": "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0"
},
proxy = null
} = options;
const res = proxy ? await profetch(url, proxy) : await (0, import_cross_fetch.default)(url, { headers });
const status = res.status;
if (status >= 400) {
throw new Error(`Request failed with error code ${status}`);
}
try {
const text = await res.text();
return JSON.parse(text);
return JSON.parse(text.trim());
} catch (err) {
throw new Error("Failed to convert data to JSON object");
}
Expand All @@ -2949,10 +2961,7 @@ var getFacebookGraphToken = () => {
const clientToken = env.FACEBOOK_CLIENT_TOKEN;
return `${appId}|${clientToken}`;
};
var getRegularUrl = (query, basseUrl) => {
return basseUrl + "?" + query;
};
var fetchEmbed_default = async (url, params = {}, endpoint = "") => {
var fetchEmbed_default = async (url, params = {}, endpoint = "", options = {}) => {
const query = {
url,
format: "json",
Expand All @@ -2968,8 +2977,8 @@ var fetchEmbed_default = async (url, params = {}, endpoint = "") => {
query.access_token = getFacebookGraphToken();
}
const queryParams = new URLSearchParams(query).toString();
const link = getRegularUrl(queryParams, endpoint);
const body = retrieve_default(link);
const link = endpoint + "?" + queryParams;
const body = retrieve_default(link, options);
return body;
};

Expand Down Expand Up @@ -5057,15 +5066,15 @@ var getEndpoint = (url) => {
};

// src/main.js
var extract = async (url, params = {}) => {
var extract = async (url, params = {}, options = {}) => {
if (!isValid(url)) {
throw new Error("Invalid input URL");
}
const endpoint = getEndpoint(url);
if (!endpoint) {
throw new Error(`No provider found with given url "${url}"`);
}
const data = await fetchEmbed_default(url, params, endpoint);
const data = await fetchEmbed_default(url, params, endpoint, options);
return data;
};
// Annotate the CommonJS export names for ESM import in node:
Expand Down
2 changes: 1 addition & 1 deletion dist/cjs/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "oembed-parser",
"version": "3.1.0",
"version": "3.1.1",
"main": "./oembed-parser.js"
}
39 changes: 24 additions & 15 deletions dist/oembed-parser.esm.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// oembed-parser@3.1.0, by @ndaidong - built with esbuild at 2022-09-19T09:58:58.156Z - published under MIT license
// oembed-parser@3.1.1, by @ndaidong - built with esbuild at 2022-09-21T15:03:39.445Z - published under MIT license

// src/utils/linker.js
var isValid = (url = "") => {
Expand All @@ -18,19 +18,31 @@ var getDomain = (url) => {
var cross_fetch_default = fetch;

// src/utils/retrieve.js
var retrieve_default = async (url) => {
const res = await cross_fetch_default(url, {
headers: {
"user-agent": "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0"
}
var profetch = async (url, proxy = {}) => {
const {
target,
headers = {}
} = proxy;
const res = await cross_fetch_default(target + encodeURIComponent(url), {
headers
});
return res;
};
var retrieve_default = async (url, options = {}) => {
const {
headers = {
"user-agent": "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0"
},
proxy = null
} = options;
const res = proxy ? await profetch(url, proxy) : await cross_fetch_default(url, { headers });
const status = res.status;
if (status >= 400) {
throw new Error(`Request failed with error code ${status}`);
}
try {
const text = await res.text();
return JSON.parse(text);
return JSON.parse(text.trim());
} catch (err) {
throw new Error("Failed to convert data to JSON object");
}
Expand All @@ -46,10 +58,7 @@ var getFacebookGraphToken = () => {
const clientToken = env.FACEBOOK_CLIENT_TOKEN;
return `${appId}|${clientToken}`;
};
var getRegularUrl = (query, basseUrl) => {
return basseUrl + "?" + query;
};
var fetchEmbed_default = async (url, params = {}, endpoint = "") => {
var fetchEmbed_default = async (url, params = {}, endpoint = "", options = {}) => {
const query = {
url,
format: "json",
Expand All @@ -65,8 +74,8 @@ var fetchEmbed_default = async (url, params = {}, endpoint = "") => {
query.access_token = getFacebookGraphToken();
}
const queryParams = new URLSearchParams(query).toString();
const link = getRegularUrl(queryParams, endpoint);
const body = retrieve_default(link);
const link = endpoint + "?" + queryParams;
const body = retrieve_default(link, options);
return body;
};

Expand Down Expand Up @@ -2154,15 +2163,15 @@ var getEndpoint = (url) => {
};

// src/main.js
var extract = async (url, params = {}) => {
var extract = async (url, params = {}, options = {}) => {
if (!isValid(url)) {
throw new Error("Invalid input URL");
}
const endpoint = getEndpoint(url);
if (!endpoint) {
throw new Error(`No provider found with given url "${url}"`);
}
const data = await fetchEmbed_default(url, params, endpoint);
const data = await fetchEmbed_default(url, params, endpoint, options);
return data;
};
export {
Expand Down
16 changes: 11 additions & 5 deletions examples/browser-oembed-parser/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# browser-oembed-parser

Install dependencies:
This demo shows how to use oembed-parser at client side, with or without proxy.

To install:

```bash
npm i
Expand All @@ -14,14 +16,18 @@ Start server:
npm start
```

Open `http://127.0.0.1:3102/` to test.


### Note
Open `http://127.0.0.1:3101/` to test.

Basically `oembed-parser` only works at server side.

However there are some noble providers those enable `Access-Control-Allow-Origin` on their service.
For example with oembed links from YouTube, TED or CodeSandbox, we can parse from browser.

Another ideal environment to run `oembed-parser` directly is browser extensions.

With the remaining cases, we need a proxy layer to bypass CORS policy.

![oembed-parser on browser](https://res.cloudinary.com/pwshub/image/upload/v1663745151/documentation/oembed-parser-on-browser.png)


---
6 changes: 4 additions & 2 deletions examples/browser-oembed-parser/package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
{
"name": "browser-oembed-parser",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "http-server ./public -p 3102"
"start": "node server"
},
"dependencies": {
"http-server": "^14.1.1"
"express": "^4.18.1",
"got": "^12.5.0"
}
}
1 change: 1 addition & 0 deletions examples/browser-oembed-parser/public/chota.min.css

Large diffs are not rendered by default.

Loading

0 comments on commit 1a4e6e4

Please sign in to comment.