traxxx/src/utils/q.js

177 lines
4.3 KiB
JavaScript
Raw Normal View History

'use strict';
const { JSDOM } = require('jsdom');
const moment = require('moment');
function prefixProtocol(url, protocol = 'https') {
if (protocol && /^\/\//.test(url)) {
return `${protocol}:${url}`;
}
return url;
}
function q(context, selector, attrArg, trim = true) {
const attr = attrArg === true ? 'textContent' : attrArg;
if (attr) {
const value = selector
? context.querySelector(selector)?.[attr]
: context[attr];
return trim ? value?.trim() : value;
}
return context.querySelector(selector);
}
function qall(context, selector, attrArg, trim = true) {
const attr = attrArg === true ? 'textContent' : attrArg;
if (attr) {
return Array.from(context.querySelectorAll(selector), el => (trim ? el[attr]?.trim() : el[attr]));
}
return Array.from(context.querySelectorAll(selector));
}
function qmeta(context, selector, attrArg = 'content', trim = true) {
return q(context, selector, attrArg, trim);
}
function qdate(context, selector, format, match, attr = 'textContent') {
const dateString = selector
? context.querySelector(selector)?.[attr]
: context[attr];
if (!dateString) return null;
if (match) {
const dateStamp = dateString.trim().match(match);
if (dateStamp) return moment.utc(dateStamp[0], format).toDate();
return null;
}
return moment.utc(dateString.trim(), format).toDate();
}
function qimage(context, selector = 'img', attr = 'src', protocol = 'https') {
const image = q(context, selector, attr);
// no attribute means q output will be HTML element
return attr ? prefixProtocol(image, protocol) : image;
}
function qimages(context, selector = 'img', attr = 'src', protocol = 'https') {
const images = qall(context, selector, attr);
return attr ? images.map(image => prefixProtocol(image, protocol)) : images;
}
function qurl(context, selector = 'a', attr = 'href', protocol = 'https') {
const url = q(context, selector, attr);
return attr ? prefixProtocol(url, protocol) : url;
}
function qurls(context, selector = 'a', attr = 'href', protocol = 'https') {
const urls = qall(context, selector, attr);
return attr ? urls.map(url => prefixProtocol(url, protocol)) : urls;
}
function qposter(context, selector = 'video', attr = 'poster', protocol = 'https') {
const poster = q(context, selector, attr);
return attr ? prefixProtocol(poster, protocol) : poster;
}
function qtrailer(context, selector = 'source', attr = 'src', protocol = 'https') {
const trailer = q(context, selector, attr);
return attr ? prefixProtocol(trailer, protocol) : trailer;
}
function qlength(context, selector, attr = 'textContent') {
const durationString = q(context, selector, attr);
const duration = durationString.match(/(\d+:)?\d+:\d+/);
if (duration) {
const segments = ['00'].concat(duration[0].split(':')).slice(-3);
return moment.duration(segments.join(':')).asSeconds();
}
return null;
}
const funcs = {
q,
qall,
qdate,
qimage,
qimages,
qposter,
qlength,
qmeta,
qtrailer,
qurls,
qurl,
qa: qall,
qd: qdate,
qi: qimage,
qis: qimages,
qp: qposter,
ql: qlength,
qm: qmeta,
qt: qtrailer,
qu: qurl,
qus: qurls,
};
function ctx(element, window) {
2020-01-16 20:56:33 +00:00
const contextFuncs = Object.entries(funcs) // dynamically attach methods with context
.reduce((acc, [key, func]) => ({
...acc,
[key]: (...args) => (window && args[0] instanceof window.HTMLElement // allow for different context
? func(...args)
: func(element, ...args)),
}), {});
return {
element,
document: element,
...(window && { window }),
...contextFuncs,
};
}
function ctxa(context, selector, window) {
return Array.from(context.querySelectorAll(selector)).map(element => ctx(element, window));
}
function ex(html, selector) {
const { window } = new JSDOM(html);
if (selector) {
return ctx(window.document.querySelector(selector), window);
}
return ctx(window.document, window);
}
function exa(html, selector) {
const { window } = new JSDOM(html);
return ctxa(window.document, selector, window);
}
module.exports = {
ex,
exa,
ctx,
ctxa,
...funcs,
};