You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

323 lines
8.9 KiB

'use strict'
/* eslint-env browser */
/* globals chrome, Utils */
const {
agent,
open,
i18n,
getOption,
setOption,
promisify,
sendMessage,
} = Utils
function setDisabledDomain(enabled) {
if (enabled) {
document
.querySelector('.header__switch--enabled')
.classList.add('header__switch--hidden')
document
.querySelector('.header__switch--disabled')
.classList.remove('header__switch--hidden')
} else {
document
.querySelector('.header__switch--enabled')
.classList.remove('header__switch--hidden')
document
.querySelector('.header__switch--disabled')
.classList.add('header__switch--hidden')
}
}
const Popup = {
/**
* Initialise popup
*/
async init() {
// Templates
Popup.templates = Array.from(
document.querySelectorAll('[data-template]')
).reduce((templates, template) => {
templates[template.dataset.template] = template.cloneNode(true)
template.remove()
return templates
}, {})
// Disabled domains
const dynamicIcon = await getOption('dynamicIcon', false)
if (dynamicIcon) {
document.querySelector('body').classList.add('dynamic-icon')
}
// Disabled domains
let disabledDomains = await getOption('disabledDomains', [])
// Theme mode
const themeMode = await getOption('themeMode', false)
if (themeMode) {
document.querySelector('body').classList.add('theme-mode')
}
// Terms
const termsAccepted =
agent === 'chrome' || (await getOption('termsAccepted', false))
if (termsAccepted) {
document.querySelector('.terms').classList.add('terms--hidden')
document.querySelector('.empty').classList.remove('empty--hidden')
Popup.onGetDetections(await Popup.driver('getDetections'))
} else {
document.querySelector('.terms').classList.remove('terms--hidden')
document.querySelector('.detections').classList.add('detections--hidden')
document.querySelector('.empty').classList.add('empty--hidden')
document
.querySelector('.terms__button--accept')
.addEventListener('click', async () => {
await setOption('termsAccepted', true)
await setOption('tracking', true)
document.querySelector('.terms').classList.add('terms--hidden')
document.querySelector('.empty').classList.remove('empty--hidden')
Popup.onGetDetections(await Popup.driver('getDetections'))
})
document
.querySelector('.terms__button--decline')
.addEventListener('click', async () => {
await setOption('termsAccepted', true)
await setOption('tracking', false)
document.querySelector('.terms').classList.add('terms--hidden')
document.querySelector('.empty').classList.remove('empty--hidden')
Popup.onGetDetections(await Popup.driver('getDetections'))
})
}
const tabs = await promisify(chrome.tabs, 'query', {
active: true,
currentWindow: true,
})
if (tabs && tabs.length) {
const [{ url }] = tabs
if (url.startsWith('http')) {
const { hostname } = new URL(url)
setDisabledDomain(disabledDomains.includes(hostname))
document
.querySelector('.header__switch--disabled')
.addEventListener('click', async () => {
disabledDomains = disabledDomains.filter(
(_hostname) => _hostname !== hostname
)
await setOption('disabledDomains', disabledDomains)
setDisabledDomain(false)
Popup.onGetDetections(await Popup.driver('getDetections'))
})
document
.querySelector('.header__switch--enabled')
.addEventListener('click', async () => {
disabledDomains.push(hostname)
await setOption('disabledDomains', disabledDomains)
setDisabledDomain(true)
Popup.onGetDetections(await Popup.driver('getDetections'))
})
} else {
for (const el of document.querySelectorAll('.header__switch')) {
el.classList.add('header__switch--hidden')
}
}
}
document
.querySelector('.header__settings')
.addEventListener('click', () => chrome.runtime.openOptionsPage())
// Apply internationalization
i18n()
},
driver(func, args) {
return sendMessage('popup.js', func, args)
},
/**
* Log debug messages to the console
* @param {String} message
*/
log(message) {
Popup.driver('log', message)
},
/**
* Group technologies into categories
* @param {Object} technologies
*/
categorise(technologies) {
return Object.values(
technologies
.filter(({ confidence }) => confidence >= 50)
.reduce((categories, technology) => {
technology.categories.forEach((category) => {
categories[category.id] = categories[category.id] || {
...category,
technologies: [],
}
categories[category.id].technologies.push(technology)
})
return categories
}, {})
)
},
/**
* Callback for getDetection listener
* @param {Array} detections
*/
async onGetDetections(detections = []) {
detections = detections
.filter(({ confidence }) => confidence >= 50)
.filter(({ slug }) => slug !== 'cart-functionality')
if (!detections || !detections.length) {
document.querySelector('.empty').classList.remove('empty--hidden')
document.querySelector('.detections').classList.add('detections--hidden')
return
}
document.querySelector('.empty').classList.add('empty--hidden')
const el = document.querySelector('.detections')
el.classList.remove('detections--hidden')
while (el.firstChild) {
el.removeChild(detections.lastChild)
}
const pinnedCategory = await getOption('pinnedCategory')
const categorised = Popup.categorise(detections)
categorised.forEach(({ id, name, slug: categorySlug, technologies }) => {
const categoryNode = Popup.templates.category.cloneNode(true)
const link = categoryNode.querySelector('.category__link')
link.href = `https://www.wappalyzer.com/technologies/${categorySlug}/?utm_source=popup&utm_medium=extension&utm_campaign=wappalyzer`
link.dataset.i18n = `categoryName${id}`
const pins = categoryNode.querySelectorAll('.category__pin')
if (pinnedCategory === id) {
pins.forEach((pin) => pin.classList.add('category__pin--active'))
}
pins.forEach((pin) =>
pin.addEventListener('click', async () => {
const pinnedCategory = await getOption('pinnedCategory')
Array.from(
document.querySelectorAll('.category__pin--active')
).forEach((pin) => pin.classList.remove('category__pin--active'))
if (pinnedCategory === id) {
await setOption('pinnedCategory', null)
} else {
await setOption('pinnedCategory', id)
pins.forEach((pin) => pin.classList.add('category__pin--active'))
}
})
)
technologies.forEach(
({ name, slug, confidence, version, icon, website }) => {
const technologyNode = Popup.templates.technology.cloneNode(true)
const image = technologyNode.querySelector('.technology__icon img')
image.src = `../images/icons/${icon}`
const link = technologyNode.querySelector('.technology__link')
const linkText = technologyNode.querySelector('.technology__name')
link.href = `https://www.wappalyzer.com/technologies/${categorySlug}/${slug}/?utm_source=popup&utm_medium=extension&utm_campaign=wappalyzer`
linkText.textContent = name
const confidenceNode = technologyNode.querySelector(
'.technology__confidence'
)
if (confidence < 100) {
confidenceNode.textContent = `${confidence}% sure`
} else {
confidenceNode.remove()
}
const versionNode = technologyNode.querySelector(
'.technology__version'
)
if (version) {
versionNode.textContent = version
} else {
versionNode.remove()
}
categoryNode
.querySelector('.technologies')
.appendChild(technologyNode)
}
)
document.querySelector('.detections').appendChild(categoryNode)
})
if (categorised.length === 1) {
document
.querySelector('.detections')
.appendChild(Popup.templates.category.cloneNode(true))
}
Array.from(document.querySelectorAll('a')).forEach((a) =>
a.addEventListener('click', (event) => {
event.preventDefault()
open(a.href)
return false
})
)
i18n()
},
}
if (/complete|interactive|loaded/.test(document.readyState)) {
Popup.init()
} else {
document.addEventListener('DOMContentLoaded', Popup.init)
}