Skip to content

Commit a6db5a6

Browse files
authored
[Chores] Update package dependencies 2025-10 (#602)
* update some libs * update `cheerio` import * oembed: fix getting iframe * html-utils: update cheerio usage to generate html code * fix oembed-description cheerio usage * review cheerio usage, add comments * fix tumblr.text * fix youtube.video * simpler oembed.js * update `cheerio.load` usage * remove todos * fix `tumblr.api` cheerio usage * fix `tumblr` cheerio usage * oembed: getIframe - reorganize ifs * update `supertest` 6.3.3 to 7.1.4 * remove `mocha` obsolete dependency * update `chai` from 4.3.2 to 6.2.0 * add new verion of `mocha` * fix node supported to 20 only * use pnpm for tests * update `chokidar` * tests: fix install pnpm * force fix deep dependencies * replace `_.find` to native array method * Delete pnpm-workspace.yaml * fix lock file * Revert "fix lock file" This reverts commit 78e0dd4. * Revert "Delete pnpm-workspace.yaml" This reverts commit 3ddd6ac. * try fix pnpm workspace * tests: fix pnpm version * Revert "try fix pnpm workspace" This reverts commit fb53400. * `.keys` -> `Object.keys` * `_.extend` -> `Object.assign` * `_.values` -> `Object.values` * `_.all -> array.every` * `_.compact` -> `array.filter(Boolean)` * `_.flatten` -> `array.flat` * `_.isString` -> typeof * remove `_.isArray` and `_.object` * move `mocha` to `devDependencies` * fix parsing multiple cookies * remove debug log * bugfix unefined * bugfix in log * remove underscore
1 parent d512a1b commit a6db5a6

File tree

34 files changed

+999
-880
lines changed

34 files changed

+999
-880
lines changed

.github/workflows/tests.yml

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,25 @@ jobs:
99

1010
strategy:
1111
matrix:
12-
node-version: ['18.x', '20.x']
12+
node-version: ['20.x']
1313

1414
steps:
1515
- uses: actions/checkout@v4
16+
17+
- name: Setup pnpm
18+
uses: pnpm/action-setup@v4
19+
with:
20+
version: 10
21+
run_install: false
22+
1623
- name: Use Node.js ${{ matrix.node-version }}
1724
uses: actions/setup-node@v4
1825
with:
1926
node-version: ${{ matrix.node-version }}
20-
cache: 'npm'
27+
cache: 'pnpm'
28+
2129
- name: Install dependencies
22-
run: npm i
30+
run: pnpm install
31+
2332
- name: Running tests
24-
run: npm test
33+
run: pnpm test

lib/core.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11

2-
import * as _ from 'underscore';
32
import * as urlLib from 'url';
43
import * as pluginUtils from './loader/utils.js';
54
import * as utils from './utils.js';
@@ -12,6 +11,7 @@
1211
import * as htmlUtils from './html-utils.js';
1312
import * as metaUtils from './plugins/system/meta/utils.js';
1413
import mediaPlugin from './plugins/validators/media.js';
14+
import { difference, intersection } from '../utils.js';
1515

1616
const plugins = pluginLoader._plugins,
1717
pluginsModules = pluginLoader._pluginsModules,
@@ -92,7 +92,7 @@
9292
* mandatoryParams - list of new params not used by plugins. Core will find what can use them.
9393
* 'mandatoryParams' enables mandatory mode: function will use _only_ methods which has this input 'mandatoryParams'.
9494
* This is used for "go down by tree" algorithm.
95-
* var mandatoryParams = _.difference(loadedParams, Object.keys(usedParams));
95+
* var mandatoryParams = difference(loadedParams, Object.keys(usedParams));
9696
* mandatoryParams = [
9797
* paramName
9898
* ]
@@ -140,13 +140,13 @@
140140

141141
// If mandatory params mode.
142142
if (mandatoryParams && mandatoryParams.length > 0) {
143-
if (_.intersection(params, mandatoryParams).length === 0) {
143+
if (intersection(params, mandatoryParams).length === 0) {
144144
// Skip method if its not using mandatory params.
145145
continue;
146146
}
147147
}
148148

149-
var absentParams = _.difference(params, loadedParams);
149+
var absentParams = difference(params, loadedParams);
150150

151151
// If "__" (as in "__statusCode") or "...Error" (as in "oembedError")
152152
// super mandatory params are absent - skip the plugin.
@@ -362,7 +362,7 @@
362362

363363
var loadedParams = Object.keys(context);
364364

365-
// var mandatoryParams = _.difference(loadedParams, Object.keys(usedParams));
365+
// var mandatoryParams = difference(loadedParams, Object.keys(usedParams));
366366

367367
// Reset scanned plugins for each iteration.
368368
var scannedPluginsIds = {};
@@ -523,7 +523,7 @@
523523
for(var k = 0; k < paramPlugins.length; k++) {
524524
var foundPluginId = paramPlugins[k];
525525

526-
var exists = _.find(initialPlugins, function(plugin) {
526+
var exists = initialPlugins.find(function(plugin) {
527527
return plugin.id === foundPluginId;
528528
});
529529
if (!exists) {
@@ -830,7 +830,7 @@
830830
usedPluginMethods[method.name] = usedPluginMethods[method.name] - 1;
831831

832832
if (r.error && options.debug) {
833-
console.error(" -- Plugin error", method.pluginId, method.name, result.error);
833+
console.error(" -- Plugin error", method.pluginId, method.name, r.error);
834834
}
835835

836836
// Collect total result.
@@ -1013,7 +1013,7 @@
10131013
links = [links];
10141014
}
10151015

1016-
links = _.compact(links);
1016+
links = links.filter(Boolean);
10171017

10181018
for(var j = 0; j < links.length; j++) {
10191019
var link = links[j];
@@ -1296,7 +1296,7 @@
12961296

12971297
// Sort links in order of REL according to CONFIG.REL_GROUPS.
12981298
function getRelIndex(rel) {
1299-
var rels = _.intersection(rel, CONFIG.REL_GROUPS);
1299+
var rels = intersection(rel, CONFIG.REL_GROUPS);
13001300
var gr = CONFIG.REL_GROUPS.length + 1;
13011301
if (rels.length > 0) {
13021302
for(var i = 0; i < rels.length; i++) {

lib/fetch.js

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ function doFetch(fetch_func, h1_fetch_func, options) {
6161
a_fetch_func(uri, fetch_options)
6262
.then(response => {
6363
var headers = response.headers.plain();
64+
var cookies = response.headers.raw()['set-cookie'];
65+
if (cookies) {
66+
// Keep cookies as array of strings.
67+
headers['set-cookie'] = cookies;
68+
}
6469
var stream = response.body;
6570
stream.on('end', () => {
6671
clearTimeout(timeoutTimerId);
@@ -264,20 +269,32 @@ const cookiesOptions = [
264269
'SameSite',
265270
];
266271

267-
export function extendCookiesJar(jar, headers) {
268-
if (headers && headers['set-cookie']) {
269-
var cookies = parseCookie(headers['set-cookie']);
270-
// Filter cookies options.
271-
cookies = Object.fromEntries(Object.entries(cookies).filter(([k,v]) => !cookiesOptions.includes(k)));
272-
jar = jar || {};
273-
jar = {...jar, ...cookies};
272+
export function extendCookiesJar(uri, jar, headers) {
273+
var cookiesValue = headers && headers['set-cookie'];
274+
if (cookiesValue) {
275+
var cookiesArray = Array.isArray(cookiesValue) ? cookiesValue : [cookiesValue];
276+
try {
277+
var cookies = cookiesArray.reduce((allCookies, cookieStr) => {
278+
return { ...allCookies, ...parseCookie(cookieStr) };
279+
}, {});
280+
// Filter cookies options.
281+
cookies = Object.fromEntries(Object.entries(cookies).filter(([k,v]) => !cookiesOptions.includes(k)));
282+
jar = jar || {};
283+
jar = {...jar, ...cookies};
284+
} catch(ex) {
285+
log('Error parse cookie', uri, ex.message);
286+
}
274287
}
275288
return jar;
276289
}
277290

278-
export function setCookieFromJar(headers, jar) {
291+
export function setCookieFromJar(uri, headers, jar) {
279292
if (jar) {
280-
var cookies = Object.entries(jar).map(([k,v]) => serializeCookie(k, v)).join('; ');
281-
headers['Cookie'] = cookies;
293+
try{
294+
var cookies = Object.entries(jar).map(([k,v]) => serializeCookie(k, v)).join('; ');
295+
headers['Cookie'] = cookies;
296+
} catch(ex) {
297+
log('Error serialize cookie', uri, ex.message);
298+
}
282299
}
283300
}

lib/html-utils.js

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
import cheerio from 'cheerio';
2-
3-
import * as _ from 'underscore';
1+
import * as cheerio from 'cheerio';
42
import CONFIG from '../config.loader.js';
53

64
var defaultPaddingBottom = 100 / CONFIG.DEFAULT_ASPECT_RATIO;
75

6+
function createCheerioElement(name) {
7+
return cheerio.load(`<${name}></${name}>`)(name);
8+
}
9+
810
function wrapContainer($element, data, options) {
911

1012
var aspectWrapperClass = options && options.aspectWrapperClass;
@@ -30,7 +32,7 @@
3032
}
3133
}
3234

33-
var $container = cheerio('<div>')
35+
var $container = createCheerioElement('div')
3436
.append($element);
3537

3638
if (aspectWrapperClass) {
@@ -45,7 +47,7 @@
4547
var hasMaxWidth = media && (media["max-width"] || media["min-width"] || media["width"] || verticalAspect);
4648

4749
if (hasMaxWidth || forceWidthLimitContainer) {
48-
$widthLimitContainer = cheerio('<div>')
50+
$widthLimitContainer = createCheerioElement('div')
4951
.append($container);
5052
}
5153

@@ -166,7 +168,7 @@
166168
&& data.href;
167169
},
168170
generate: function(data) {
169-
var $img = cheerio('<img>')
171+
var $img = createCheerioElement('img')
170172
.attr('src', data.href);
171173
if (data.title) {
172174
$img
@@ -190,7 +192,7 @@
190192
var givf = data.rel.indexOf('gifv') > -1;
191193
var autoplay = data.rel.indexOf('autoplay') > -1 || givf;
192194

193-
var $video = cheerio('<video' + (givf ? ' loop muted webkit-playsinline' : ' controls') + (autoplay ? ' autoplay' : '') + '>Your browser does not support HTML5 video.</video>');
195+
var $video = cheerio.load('<video' + (givf ? ' loop muted webkit-playsinline' : ' controls') + (autoplay ? ' autoplay' : '') + '>Your browser does not support HTML5 video.</video>')('video');
194196

195197
if (iframelyData && iframelyData.links) {
196198

@@ -279,8 +281,7 @@
279281
return data.type === "text/html" && data.href;
280282
},
281283
generate: function(data, options) {
282-
283-
var $iframe = cheerio('<iframe>')
284+
var $iframe = createCheerioElement('iframe')
284285
.attr('src', data.href)
285286
.css('border', '0')
286287
.attr('allowfullscreen', '');
@@ -334,25 +335,15 @@
334335
}
335336
};
336337

337-
export function generateElementWrapperHtml(element, link, options) {
338-
339-
if (typeof element === 'string') {
340-
element = cheerio(element);
341-
}
342-
343-
var $el = wrapContainer(element, link, options);
344-
return cheerio('<div>').append($el).html();
345-
};
346-
347338
export function generateLinkElementHtml(link, options) {
348339
var $el = generateLinkElement(link, options);
349-
if (_.isString($el)) {
340+
if (typeof $el === 'string') {
350341
return $el;
351342
} else if ($el) {
352343
if (options && options.canonical && link.href !== options.canonical) {
353344
$el.attr('data-embed-canonical', options.canonical);
354345
}
355-
return cheerio('<div>').append($el).html();
346+
return $el.prop('outerHTML');
356347
} else {
357348
return '';
358349
}
@@ -647,7 +638,7 @@
647638
sortLinks(iframely_data.links, options.autoplayMode);
648639
}
649640

650-
var player = iframely_data && _.find(iframely_data.links, findPlayer);
641+
var player = iframely_data?.links.find(findPlayer);
651642

652643
if (player) {
653644

@@ -674,7 +665,7 @@
674665
}
675666

676667
function getInlineApp(iframely_data) {
677-
return iframely_data && _.find(iframely_data.links, function(l) {
668+
return iframely_data?.links.find(function(l) {
678669
// `html` can be added by `generateLinksHtml`, so also check if no `href`.
679670
return l.html && !l.href && l.type === 'text/html';
680671
});
@@ -706,4 +697,4 @@
706697
}
707698

708699
return selectedLink;
709-
};
700+
};

lib/oembed.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import * as _ from 'underscore';
21
import * as htmlUtils from './html-utils.js';
2+
import { intersection } from '../utils.js';
33

44
export function getOembed(uri, data, options) {
55

@@ -63,7 +63,7 @@ export function getOembed(uri, data, options) {
6363

6464
var link;
6565
htmlUtils.sortLinks(data.links);
66-
var foundRel = _.find(options && options.mediaPriority ? CONFIG.OEMBED_RELS_MEDIA_PRIORITY : CONFIG.OEMBED_RELS_PRIORITY, function(rel) {
66+
var foundRel = (options?.mediaPriority ? CONFIG.OEMBED_RELS_MEDIA_PRIORITY : CONFIG.OEMBED_RELS_PRIORITY).find(function(rel) {
6767
link = htmlUtils.filterLinksByRel(rel, data.links, {
6868
returnOne: true,
6969
excludeRel: CONFIG.R.autoplay
@@ -72,15 +72,15 @@ export function getOembed(uri, data, options) {
7272
});
7373

7474
if (!link) {
75-
link = _.find(data.links, function(link) {
75+
link = data.links.find(function(link) {
7676
return link.type.indexOf('image') === 0 && link.rel.indexOf(CONFIG.R.file) > -1;
7777
});
7878
if (link) {
7979
foundRel = CONFIG.R.image;
8080
}
8181
}
8282

83-
var inlineReader = link && _.intersection(link.rel, [CONFIG.R.inline, CONFIG.R.reader]).length == 2;
83+
var inlineReader = link && intersection(link.rel, [CONFIG.R.inline, CONFIG.R.reader]).length == 2;
8484

8585
var m = link && link.media;
8686
if (m) {
@@ -136,7 +136,7 @@ export function getOembed(uri, data, options) {
136136
};
137137

138138
if (CONFIG.GENERATE_LINK_PARAMS) {
139-
_.extend(generateLinkOptions, CONFIG.GENERATE_LINK_PARAMS);
139+
Object.assign(generateLinkOptions, CONFIG.GENERATE_LINK_PARAMS);
140140
}
141141

142142
oembed.html = htmlUtils.generateLinkElementHtml(link, generateLinkOptions);

lib/plugins/system/cheerio.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import cheerio from 'cheerio';
1+
import * as cheerio from 'cheerio';
22
import htmlparser2 from "htmlparser2";
33
var DomHandler = htmlparser2.DomHandler;
44

@@ -24,4 +24,4 @@ export default {
2424
htmlparser.addHandler(domHandler);
2525
}
2626

27-
};
27+
};

lib/plugins/system/htmlparser/htmlparser.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export default {
126126
// Prevent cache self redirect. Some sites changes cookies and stops redirect loop (e.g. https://miro.com/app/live-embed/o9J_lBwNMhI=/?embedAutoplay=true)
127127
const redirectUrl = urlLib.resolve(url, headers.location);
128128
const preventCache = redirectUrl === url;
129-
options.jar = extendCookiesJar(options.jar, headers);
129+
options.jar = extendCookiesJar(url, options.jar, headers);
130130
// TODO: do not cache when has unique cookie???
131131
if (options2.maxRedirects && (!options.redirectsHistory || options.redirectsHistory.length === 0)) {
132132
options.maxRedirects = options2.maxRedirects; // Maybe set in prepareRequestOptions for a proxy.

lib/plugins/system/oembed/oembed.js

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as oembedUtils from './oembedUtils.js';
2-
import cheerio from 'cheerio';
2+
import * as cheerio from 'cheerio';
33

44
import * as entities from 'entities';
55
import * as URL from 'url';
@@ -44,20 +44,21 @@ function _getOembedIframe(oembed) {
4444
html = entities.decodeHTML(html);
4545
}
4646

47-
var $container = cheerio('<div>');
47+
var $iframe = null;
4848
try {
49-
$container.html(html);
49+
var $iframe = cheerio.load(html)('iframe');
5050
} catch (ex) {}
51-
var $iframe = $container.find('iframe');
5251

53-
if ($iframe.length === 2 && /<iframe>$/i.test(html)) {
54-
// Forgive mis-closed iFrame tag
55-
$iframe = $iframe.first();
56-
}
57-
58-
if ($iframe.length === 1) {
59-
_iframe = fixOembedIframeAttributes($iframe[0].attribs);
60-
_iframe.placeholder = oembed.thumbnail_url;
52+
if ($iframe) {
53+
if ($iframe.length === 2 && /<iframe>$/i.test(html)) {
54+
// Forgive mis-closed iFrame tag
55+
$iframe = $iframe.first();
56+
}
57+
58+
if ($iframe.length === 1) {
59+
_iframe = fixOembedIframeAttributes($iframe[0].attribs);
60+
_iframe.placeholder = oembed.thumbnail_url;
61+
}
6162
}
6263

6364
// When oembed is in fact iframe from domain fallbacks on oEmbedError

0 commit comments

Comments
 (0)