UNPKG

webextension-store-meta

Version:

Get browser extension(webextension) item meta from Chrome Web Store and Firefox add-ons.

200 lines 6.98 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ChromeWebStore = void 0; const node_querystring_1 = require("node:querystring"); const domhandler_1 = require("domhandler"); const Parser_1 = require("htmlparser2/lib/Parser"); const dom_1 = require("../utils/dom"); const fetch_text_1 = require("../utils/fetch-text"); const parse_1 = require("../utils/parse"); class ChromeWebStore { id; options; qs; _dom = null; _cache = new Map(); constructor({ id, options, qs }) { this.id = id; this.options = options; this.qs = (0, node_querystring_1.stringify)(typeof qs === "string" ? (0, node_querystring_1.parse)(qs.replace(/^\?/, "")) : qs || {}); } static async load(options) { const instance = new ChromeWebStore(options); await instance.load(); return instance; } async load() { const url = `https://chromewebstore.google.com/detail/${this.id}?${this.qs}`; const html = await (0, fetch_text_1.fetchText)(url, this.options); const handler = new domhandler_1.DomHandler(); new Parser_1.Parser(handler).end(html); this._dom = handler.dom; return this; } meta() { return { name: this.name(), description: this.description(), url: this.url(), image: this.image(), ratingValue: this.ratingValue(), ratingCount: this.ratingCount(), users: this.users(), version: this.version(), size: this.size(), lastUpdated: this.lastUpdated(), }; } name() { return this._og("og:title"); } description() { return this._og("og:description"); } url() { let url = this._og("og:url"); if (url) return url; const urlElem = (0, dom_1.findOne)((elem) => elem.name === "link" && elem.attribs.rel === "canonical", this.dom); if (urlElem) { url = urlElem.attribs.href; if (url) { this._cache.set("og:url", url); return url; } } return null; } image() { return this._og("og:image"); } ratingValue() { return this._parseRating("ratingValue"); } ratingCount() { return this._parseRating("ratingCount"); } users() { if (!this._cache.has("users")) { const container = (0, dom_1.queryOne)(this.dom, "F9iKBc"); if (container) { for (let i = 0; i < container.children.length; i++) { const node = container.children[i]; if ((0, domhandler_1.isText)(node)) { const content = (0, dom_1.getText)(node); const match = /[\d,]+/.exec(content); if (match) { this._cache.set("users", match[0]); break; } } } } if (!this._cache.has("users")) { this._cache.set("users", null); } } return this._cache.get("users") ?? null; } version() { if (!this._cache.has("version")) { const el = (0, dom_1.queryOne)(this.dom, "nBZElf") || (0, dom_1.queryOne)(this.dom, "N3EXSc"); this._cache.set("version", (el && (0, parse_1.parseVersion)((0, dom_1.getText)(el))) || parseVersionFromManifest(this.dom)); } return this._cache.get("version") ?? null; } size() { if (!this._cache.has("size")) { const el = (0, dom_1.queryOne)(this.dom, "ZSMSLb"); this._cache.set("size", (0, dom_1.getText)(el?.lastChild) || null); } return this._cache.get("size") ?? null; } lastUpdated() { if (!this._cache.has("lastUpdated")) { const el = (0, dom_1.queryOne)(this.dom, "uBIrad"); this._cache.set("lastUpdated", (0, dom_1.getText)(el?.lastChild) || null); } return this._cache.get("lastUpdated") ?? null; } get dom() { if (!this._dom) { throw new Error("Item not loaded. Please run `await instance.load()` first.`"); } return this._dom; } _og(property) { if (!this._cache.has(property)) { (0, dom_1.findOne)((elem) => { if (elem.attribs.property == null) return false; this._cache.set(elem.attribs.property, elem.attribs.content); return elem.attribs.property === property; }, this.dom); if (!this._cache.has(property)) { this._cache.set(property, null); } } return this._cache.get(property) ?? null; } _parseRating(key) { if (!this._cache.has(key)) { const result = parseRating(this.dom); this._cache.set("ratingValue", result?.ratingValue ?? null); this._cache.set("ratingCount", result?.ratingCount ?? null); } return this._cache.get(key) ?? null; } } exports.ChromeWebStore = ChromeWebStore; exports.default = ChromeWebStore; function parseRating(dom) { const container = (0, dom_1.queryOne)(dom, "j3zrsd"); if (container) { const result = { ratingValue: null, ratingCount: null, }; const ratingValueEl = (0, dom_1.queryOne)(container, "Vq0ZA"); if (ratingValueEl) { const ratingValue = (0, dom_1.getText)(ratingValueEl); if (/^\d+\.?\d*$/.test(ratingValue)) { result.ratingValue = ratingValue; } } const ratingCountEl = (0, dom_1.queryOne)(container, "xJEoWe"); if (ratingCountEl) { result.ratingCount = (0, dom_1.getText)(ratingCountEl).replace(/\s*ratings$/, ""); } if (result.ratingValue !== null || result.ratingCount !== null) { return result; } } return null; } function parseVersionFromManifest(maybeNode) { const nodes = Array.isArray(maybeNode) ? maybeNode : [maybeNode]; for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; if (!(0, domhandler_1.isTag)(node)) { continue; } if (node.tagName === "script") { const content = (0, dom_1.getText)(node); if (content.includes("AF_initDataCallback")) { const match = /\\"version\\":\s*\\"([\d.]+)\\"/.exec(content); if (match) { return match[1]; } } } if (node.children.length > 0) { const version = parseVersionFromManifest(node.children); if (version) { return version; } } } return null; } //# sourceMappingURL=index.js.map