Source code
// Marks reports the outlet itself labels as opinion: by a section in the
// link (such as /opinion/) or by a category in its own feed. Opinion is shown
// with an "Opinion" tag and does not count toward an outlet's news score.
const PATHS = /\/(opinion|opinions|commentary|op-ed|op-eds|oped|editorial|editorials|columnists?|columns|commentisfree|perspective|perspectives|restoring-america)(\/|$)/i;
const CATEGORIES = /^(opinion|opinions|commentary|op-?ed|editorials?|columns?|columnists?|perspectives?)$/i;
function isOpinion(link, categories = []) {
let path = '';
try { path = new URL(link).pathname; } catch { path = String(link || ''); }
return PATHS.test(path) || (categories || []).some((c) => CATEGORIES.test(String(c).trim()));
}
module.exports = { isOpinion, PATHS, CATEGORIES };