• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

brahma-dev / metafetch / 15269065998

27 May 2025 07:20AM UTC coverage: 100.0%. Remained the same
15269065998

push

github

snyk-bot
fix: upgrade axios from 1.6.8 to 1.9.0

Snyk has created this PR to upgrade axios from 1.6.8 to 1.9.0.

See this package in npm:
axios

See this project in Snyk:
https://app.snyk.io/org/brahma-dev/project/e2347875-ea35-4b9b-9c6f-63a922ca3ec3?utm_source=github&utm_medium=referral&page=upgrade-pr

118 of 118 branches covered (100.0%)

Branch coverage included in aggregate %.

136 of 136 relevant lines covered (100.0%)

192.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/src/parser.ts
1
import cheerio, { CheerioAPI } from "cheerio";
4✔
2
import { URL } from 'url';
4✔
3
import langs, { Language } from "langs";
4✔
4
import { RawAxiosRequestHeaders } from "axios";
5
export interface MetafetchResponse {
6
        title?: string,
7
        charset?: string,
8
        images?: Array<string>,
9
        links?: Array<string>,
10
        language?: string | Language,
11
        description?: string,
12
        type?: string,
13
        url?: URL,
14
        originalURL?: string,
15
        ampURL?: string,
16
        siteName?: string,
17
        image?: string,
18
        meta?: { [x: string]: string },
19
        headers?: RawAxiosRequestHeaders,
20
}
21
export default function (url: string, options: any, body: string, headers: RawAxiosRequestHeaders, franc: ((value?: string | undefined) => string) | ((arg0: string) => string)): MetafetchResponse {
4✔
22
        if (!body.includes("html"))
44✔
23
                throw new Error("Invalid HTML");
4✔
24
        let $: CheerioAPI;
25
        $ = cheerio.load(body);
40✔
26
        $('script').remove();
40✔
27
        $('style').remove();
40✔
28
        $('applet').remove();
40✔
29
        $('embed').remove();
40✔
30
        $('object').remove();
40✔
31
        $('noscript').remove();
40✔
32
        let response: MetafetchResponse = {};
40✔
33
        let title;
34
        if (options.title) {
40✔
35
                title = $('title').text();
36✔
36
        }
37
        if (options.charset) {
40✔
38
                response.charset = $("meta[charset]").attr("charset") || (headers['content-type']?.toString().match(/charset=(.+)/) || []).pop();
36✔
39
        }
40
        if (options.images) {
40✔
41
                var imagehash: { [x: string]: boolean } = {};
28✔
42
                response.images = $('img').map(function () {
28✔
43
                        let src: string | undefined = $(this).attr('src') || $(this).attr('data-src');
336✔
44
                        if (src) {
336✔
45
                                return (new URL(src, url)).href;
324✔
46
                        } else {
47
                                return "";
12✔
48
                        }
49
                }).filter(function (e, f) {
50
                        return (f.match(/\.(jpeg|jpg|gif|png|JPEG|JPG|GIF|PNG)$/) !== null);
336✔
51
                }).filter(function (i, item) {
52
                        return imagehash.hasOwnProperty(item) ? false : (imagehash[item] = true);
120✔
53
                }).get();
54
                const imageCandidateRegex = /\s*([^,]\S*[^,](?:\s+[^,]+)?)\s*(?:,|$)/;
28✔
55
                $('img').map(function () {
28✔
56
                        let src: string | undefined = $(this).attr('srcset') || $(this).attr('data-srcset');
336✔
57
                        if (src) {
336✔
58
                                return src.split(imageCandidateRegex)
132✔
59
                                        .filter((part, index) => index % 2 === 1)
2,260✔
60
                                        .forEach(part => {
61
                                                let [imgurl, ...descriptors] = part.trim().split(/\s+/);
1,064✔
62
                                                imgurl = (new URL(imgurl, url)).href;
1,064✔
63
                                                imagehash.hasOwnProperty(imgurl) ? false : ((imagehash[imgurl] = true) && response.images?.push(imgurl));
1,064✔
64
                                        });
65
                        } else {
66
                                return "";
204✔
67
                        }
68
                });
69
        }
70
        if (options.links) {
40✔
71
                var linkhash: { [x: string]: boolean } = {};
28✔
72
                response.links = $('a').map(function () {
28✔
73
                        let href: string | undefined = $(this).attr('href');
2,024✔
74
                        if (href && href.trim().length && href[0] !== "#") {
2,024✔
75
                                return (new URL(href, url)).href;
1,988✔
76
                        } else {
77
                                return "";
36✔
78
                        }
79
                }).filter(function (i, item) {
80
                        if (item === "") {
2,024✔
81
                                return false;
36✔
82
                        }
83
                        return linkhash.hasOwnProperty(item) ? false : (linkhash[item] = true);
1,988✔
84
                }).get();
85
        }
86
        let meta = $('meta'),
40✔
87
                canonicalURL = $("link[rel=canonical]").attr('href'),
40✔
88
                ampURL = $("link[rel=amphtml]").attr('href'),
40✔
89
                metaData: { [x: string]: string } = {};
40✔
90
        if (ampURL) {
40✔
91
                ampURL = (new URL(ampURL, url)).href;
8✔
92
        }
93
        Object.keys(meta).forEach(function (key: string) {
40✔
94
                //@ts-ignore
95
                var attribs = meta[key].attribs;
932✔
96
                if (attribs) {
932✔
97
                        if (attribs.property) {
772✔
98
                                metaData[attribs.property.toLowerCase()] = attribs.content;
244✔
99
                        }
100
                        if (attribs.name) {
772✔
101
                                metaData[attribs.name.toLowerCase()] = attribs.content;
436✔
102
                        }
103
                        if (attribs['http-equiv']) {
772✔
104
                                headers[attribs['http-equiv']] = attribs.content;
16✔
105
                        }
106
                }
107
        });
108
        if (options.language) {
40✔
109
                response.language = $("html").attr("lang") || $("html").attr("xml:lang") || headers["Content-Language"]?.toString() || headers["content-language"]?.toString();
36✔
110
                if (typeof response.language == "string") {
36✔
111
                        response.language = response.language.split("-")[0];
28✔
112
                } else {
113
                        response.language = langs.where("2", franc($('body').text().replace(/\n\s*\n/g, '\n')))
8✔
114
                        response.language = response.language && response.language[1];
8✔
115
                }
116
        }
117

118
        // response.uri = uri;
119

120
        if (options.title) {
40✔
121
                response.title = title;
36✔
122
        }
123
        if (options.description) {
40✔
124
                response.description = metaData['og:description'] || metaData.description;
36✔
125
        }
126
        if (options.type) {
40✔
127
                response.type = metaData['og:type'];
36✔
128
        }
129
        if (options.url) {
40✔
130
                response.url = (new URL(canonicalURL || metaData['og:url'] || url, url));
36✔
131
                response.originalURL = url;
36✔
132
                response.ampURL = ampURL || undefined;
36✔
133
        }
134
        if (options.siteName) {
40✔
135
                response.siteName = metaData['og:site_name'];
36✔
136
        }
137
        if (options.image) {
40✔
138
                response.image = metaData['og:image'];
36✔
139
        }
140
        if (options.meta) {
40✔
141
                response.meta = metaData;
36✔
142
        }
143
        if (options.headers) {
40✔
144
                response.headers = headers;
36✔
145
        }
146
        return response;
40✔
147
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc