Add PRO tab to WebExtension

main
Elbert Alias 4 years ago
parent 6625a034b1
commit 1c716621d8

@ -13,7 +13,7 @@
"software"
],
"homepage": "https://www.wappalyzer.com/",
"version": "6.7.4",
"version": "6.7.5",
"author": "Wappalyzer",
"license": "MIT",
"repository": {

@ -1,100 +1,163 @@
{
"github": { "message": "Fork Wappalyzer on GitHub!" },
"twitter": { "message": "Follow Wappalyzer on Twitter" },
"website": { "message": "Go to wappalyzer.com" },
"options": { "message": "Options" },
"optionsSave": { "message": "Save options" },
"optionsSaved": { "message": "Saved" },
"optionUpgradeMessage": { "message": "Tell me about upgrades" },
"optionDynamicIcon": { "message": "Use technology icon instead of Wappalyzer logo" },
"optionTracking": { "message": "Anonymously send identified technologies to wappalyzer.com" },
"optionThemeMode": { "message": "Enable dark mode compatibility" },
"optionBadge": { "message": "Show the number of identified technologies on the icon" },
"optionShowCached": { "message": "Include cached detections in results" },
"disableOnDomain": { "message": "Disable on this website" },
"clearCache": { "message": "Clear cached detections" },
"nothingToDo": { "message": "Nothing to do here." },
"noAppsDetected": { "message": "No technologies detected." },
"categoryPin": { "message": "Always show icon" },
"termsAccept": { "message": "I'm ok with that" },
"termsDecline": { "message": "Disable" },
"termsContent": { "message": "This extension sends anonymous information about websites you visit, including domain name and identified technologies, to <a href='https://www.wappalyzer.com'>wappalyzer.com</a>. This can be disabled in the settings." },
"privacyPolicy": { "message": "Privacy policy" },
"createAlert": { "message": "Create an alert for this website" },
"leadLists": { "message": "Lead generation tools" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Message boards" },
"categoryName3": { "message": "Database managers" },
"categoryName4": { "message": "Documentation tools" },
"categoryName5": { "message": "Widgets" },
"categoryName6": { "message": "Ecommerce" },
"categoryName7": { "message": "Photo galleries" },
"categoryName8": { "message": "Wikis" },
"categoryName9": { "message": "Hosting panels" },
"categoryName10": { "message": "Analytics" },
"categoryName11": { "message": "Blogs" },
"categoryName12": { "message": "JavaScript frameworks" },
"categoryName13": { "message": "Issue trackers" },
"categoryName14": { "message": "Video players" },
"categoryName15": { "message": "Comment systems" },
"categoryName16": { "message": "Security" },
"categoryName17": { "message": "Font scripts" },
"categoryName18": { "message": "Web frameworks" },
"categoryName19": { "message": "Miscellaneous" },
"categoryName20": { "message": "Editor" },
"categoryName21": { "message": "LMS" },
"categoryName22": { "message": "Web servers" },
"categoryName23": { "message": "Caching" },
"categoryName24": { "message": "Rich text editors" },
"categoryName25": { "message": "JavaScript graphics" },
"categoryName26": { "message": "Mobile frameworks" },
"categoryName27": { "message": "Programming languages" },
"categoryName28": { "message": "Operating systems" },
"categoryName29": { "message": "Search engines" },
"categoryName30": { "message": "Webmail" },
"categoryName31": { "message": "CDN" },
"categoryName32": { "message": "Marketing automation" },
"categoryName33": { "message": "Web server extensions" },
"categoryName34": { "message": "Databases" },
"categoryName35": { "message": "Maps" },
"categoryName36": { "message": "Advertising" },
"categoryName37": { "message": "Network services" },
"categoryName38": { "message": "Media servers" },
"categoryName39": { "message": "Webcams" },
"categoryName40": { "message": "Printers" },
"categoryName41": { "message": "Payment processors" },
"categoryName42": { "message": "Tag managers" },
"categoryName44": { "message": "CI" },
"categoryName46": { "message": "Remote Access" },
"categoryName47": { "message": "Development" },
"categoryName48": { "message": "Network storage" },
"categoryName49": { "message": "Feed readers" },
"categoryName50": { "message": "DMS" },
"categoryName51": { "message": "Page builder" },
"categoryName52": { "message": "Live chat" },
"categoryName53": { "message": "CRM" },
"categoryName54": { "message": "SEO" },
"categoryName55": { "message": "Accounting" },
"categoryName56": { "message": "Cryptominers" },
"categoryName57": { "message": "Static site generators" },
"categoryName58": { "message": "User onboarding" },
"categoryName59": { "message": "JavaScript libraries" },
"categoryName60": { "message": "Containers" },
"categoryName61": { "message": "SaaS" },
"categoryName62": { "message": "PaaS" },
"categoryName63": { "message": "IaaS" },
"categoryName64": { "message": "Reverse proxies" },
"categoryName65": { "message": "Load balancers" },
"categoryName66": { "message": "UI frameworks" },
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "Accessibility" },
"categoryName69": { "message": "Social logins" },
"categoryName70": { "message": "SSL/TLS certificate authorities" },
"categoryName71": { "message": "Affiliate programs" },
"categoryName72": { "message": "Appointment scheduling" },
"categoryName73": { "message": "Surveys" },
"categoryName74": { "message": "A/B testing" },
"categoryName75": { "message": "Email" },
"categoryName76": { "message": "Personalisation" },
"categoryName77": { "message": "Retargeting" }
"github": { "message": "Fork Wappalyzer on GitHub!" },
"twitter": { "message": "Follow Wappalyzer on Twitter" },
"website": { "message": "Go to wappalyzer.com" },
"options": { "message": "Options" },
"optionsSave": { "message": "Save options" },
"optionsSaved": { "message": "Saved" },
"optionUpgradeMessage": { "message": "Tell me about upgrades" },
"optionDynamicIcon": { "message": "Use technology icon instead of Wappalyzer logo" },
"optionTracking": { "message": "Anonymously send identified technologies to wappalyzer.com" },
"optionThemeMode": { "message": "Enable dark mode compatibility" },
"optionBadge": { "message": "Show the number of identified technologies on the icon" },
"optionShowCached": { "message": "Include cached detections in results" },
"optionApiKey": { "message": "API key" },
"optionApiKeyDescription": { "message": "get your API key" },
"disableOnDomain": { "message": "Disable on this website" },
"clearCache": { "message": "Clear cached detections" },
"nothingToDo": { "message": "Nothing to do here." },
"noAppsDetected": { "message": "No technologies detected." },
"categoryPin": { "message": "Always show icon" },
"termsAccept": { "message": "I'm ok with that" },
"termsDecline": { "message": "Disable" },
"termsContent": { "message": "This extension sends anonymous information about websites you visit, including domain name and identified technologies, to <a href='https://www.wappalyzer.com'>wappalyzer.com</a>. This can be disabled in the settings." },
"privacyPolicy": { "message": "Privacy policy" },
"createAlert": { "message": "Create an alert for this website" },
"leadLists": { "message": "Lead generation tools" },
"tabTechnologies": { "message": "Technologies" },
"tabPro": { "message": "Pro" },
"creditBalance": { "message": "Credit balance:" },
"proMessageHeading": { "message": "Unlock PRO features" },
"proMessage": { "message": "Subscribe to a PRO plan to view company and contact information of the websites you visit." },
"proButton": { "message": "Compare plans" },
"proFaq": { "message": "FAQs" },
"formSave": { "message": "Save" },
"setCompany": { "message": "Company information" },
"setKeywords": { "message": "Keywords" },
"setEmail": { "message": "Email addresses" },
"setPhone": { "message": "Phone numbers" },
"setAddress": { "message": "Addresses" },
"setContact": { "message": "Contact details" },
"setSocial": { "message": "Social media accounts" },
"setMeta": { "message": "Metadata" },
"setLocale": { "message": "Locale" },
"setTrackers": { "message": "Trackers" },
"setSecurity": { "message": "Security" },
"attributeIpCountry": { "message": "IP country" },
"attributeIpRegion": { "message": "IP region" },
"attributeLanguage": { "message": "Language" },
"attributeEmail": { "message": "Email address" },
"attributePhone": { "message": "Phone number" },
"attributeSkype": { "message": "Skype" },
"attributeWhatsapp": { "message": "WhatsApp" },
"attributeInferredCompanyName": { "message": "Inferred company name" },
"attributeTwitter": { "message": "Twitter" },
"attributeFacebook": { "message": "Facebook" },
"attributeInstagram": { "message": "Instagram" },
"attributeGithub": { "message": "GitHub" },
"attributeTiktok": { "message": "TikTok" },
"attributeYoutube": { "message": "YouTube" },
"attributePinterest": { "message": "Pinterest" },
"attributeLinkedin": { "message": "LinkedIn" },
"attributeOwler": { "message": "Owler" },
"attributeTitle": { "message": "Title" },
"attributeDescription": { "message": "Description" },
"attributeCopyright": { "message": "Copyright" },
"attributeCopyrightYear": { "message": "Copyright year" },
"attributeResponsive": { "message": "Responsive" },
"attributeCertInfo_issuer": { "message": "Cert issuer" },
"attributeCertInfo_protocol": { "message": "Cert protocol" },
"attributeCertInfo_validTo": { "message": "Cert expiry" },
"attributeHttps": { "message": "SSL/TLS enabled" },
"attributeTrackerGoogleAnalytics": { "message": "Google Analytics" },
"attributeTrackerGoogleAdSense": { "message": "Google AdSense" },
"attributeTrackerMedianet": { "message": "Medianet" },
"attributeTrackerFacebook": { "message": "Facebook" },
"attributeTrackerOptimizely": { "message": "Optimizely" },
"attributeCompanyName": { "message": "Company name" },
"attributeIndustry": { "message": "Industry" },
"attributeAbout": { "message": "About" },
"attributeLocations": { "message": "Locations" },
"attributeCompanySize": { "message": "Company size" },
"attributeCompanyType": { "message": "Company type" },
"attributeCompanyFounded": { "message": "Company founded" },
"attributeKeywords": { "message": "Keywords" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Message boards" },
"categoryName3": { "message": "Database managers" },
"categoryName4": { "message": "Documentation tools" },
"categoryName5": { "message": "Widgets" },
"categoryName6": { "message": "Ecommerce" },
"categoryName7": { "message": "Photo galleries" },
"categoryName8": { "message": "Wikis" },
"categoryName9": { "message": "Hosting panels" },
"categoryName10": { "message": "Analytics" },
"categoryName11": { "message": "Blogs" },
"categoryName12": { "message": "JavaScript frameworks" },
"categoryName13": { "message": "Issue trackers" },
"categoryName14": { "message": "Video players" },
"categoryName15": { "message": "Comment systems" },
"categoryName16": { "message": "Security" },
"categoryName17": { "message": "Font scripts" },
"categoryName18": { "message": "Web frameworks" },
"categoryName19": { "message": "Miscellaneous" },
"categoryName20": { "message": "Editor" },
"categoryName21": { "message": "LMS" },
"categoryName22": { "message": "Web servers" },
"categoryName23": { "message": "Caching" },
"categoryName24": { "message": "Rich text editors" },
"categoryName25": { "message": "JavaScript graphics" },
"categoryName26": { "message": "Mobile frameworks" },
"categoryName27": { "message": "Programming languages" },
"categoryName28": { "message": "Operating systems" },
"categoryName29": { "message": "Search engines" },
"categoryName30": { "message": "Webmail" },
"categoryName31": { "message": "CDN" },
"categoryName32": { "message": "Marketing automation" },
"categoryName33": { "message": "Web server extensions" },
"categoryName34": { "message": "Databases" },
"categoryName35": { "message": "Maps" },
"categoryName36": { "message": "Advertising" },
"categoryName37": { "message": "Network services" },
"categoryName38": { "message": "Media servers" },
"categoryName39": { "message": "Webcams" },
"categoryName40": { "message": "Printers" },
"categoryName41": { "message": "Payment processors" },
"categoryName42": { "message": "Tag managers" },
"categoryName44": { "message": "CI" },
"categoryName46": { "message": "Remote Access" },
"categoryName47": { "message": "Development" },
"categoryName48": { "message": "Network storage" },
"categoryName49": { "message": "Feed readers" },
"categoryName50": { "message": "DMS" },
"categoryName51": { "message": "Page builder" },
"categoryName52": { "message": "Live chat" },
"categoryName53": { "message": "CRM" },
"categoryName54": { "message": "SEO" },
"categoryName55": { "message": "Accounting" },
"categoryName56": { "message": "Cryptominers" },
"categoryName57": { "message": "Static site generators" },
"categoryName58": { "message": "User onboarding" },
"categoryName59": { "message": "JavaScript libraries" },
"categoryName60": { "message": "Containers" },
"categoryName61": { "message": "SaaS" },
"categoryName62": { "message": "PaaS" },
"categoryName63": { "message": "IaaS" },
"categoryName64": { "message": "Reverse proxies" },
"categoryName65": { "message": "Load balancers" },
"categoryName66": { "message": "UI frameworks" },
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "Accessibility" },
"categoryName69": { "message": "Social logins" },
"categoryName70": { "message": "SSL/TLS certificate authorities" },
"categoryName71": { "message": "Affiliate programs" },
"categoryName72": { "message": "Appointment scheduling" },
"categoryName73": { "message": "Surveys" },
"categoryName74": { "message": "A/B testing" },
"categoryName75": { "message": "Email" },
"categoryName76": { "message": "Personalisation" },
"categoryName77": { "message": "Retargeting" }
}

@ -3,14 +3,16 @@
--color-primary-darken: #32067c;
--color-primary-lighten: #f4f1fa;
--color-secondary: #fafafa;
--color-secondary-darken: #f5f5f5;
--color-secondary-darken: #e0e0e0;
--color-text: #4a4a4a;
--color-text-lighten: #7a7a7a;
--color-text-dark: var(--color-primary-lighten);
--color-success: #50b154;
--color-error: #ff5252;
}
* {
box-sizing: border-box;
user-select: none;
}
body {
@ -21,7 +23,7 @@ body {
font-size: .9rem;
line-height: 1.5rem;
margin: 0;
min-width: 24rem;
width: 34rem;
}
a, a:focus, a:hover {
@ -30,6 +32,72 @@ a, a:focus, a:hover {
text-decoration: underline;
}
p {
margin: 0 0 .5rem 0;
}
.input[type="text"], .input[type="password"] {
background: white;
border: 1px solid var(--color-primary);
border-radius: 4px;
color: var(--color-text);
font-size: .9rem;
margin-bottom: 1rem;
padding: .5rem;
width: 100%;
}
.button__link, .button__link:active, .button__link:hover {
color: var(--color-primary);
cursor: pointer;
display: inline-block;
font-size: .85rem;
font-weight: bold;
margin: -.3rem -1rem -.5rem 0;
padding: .4rem 1rem .3rem 1rem;
position: relative;
text-decoration: none;
text-align: right;
}
.button__link:hover:before {
background: var(--color-primary);
border-radius: 4px;
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
opacity: .1;
}
.button__icon {
height: 1.2rem;
margin: 0 -.4rem .1rem .2rem;
width: 1.2rem;
vertical-align: middle;
}
.button__icon--left {
margin: 0 .2rem .2rem -.4rem;
}
.button__icon--right {
margin: 0 -.4rem .2rem .2rem;
}
.label {
font-weight: bold;
display: block;
margin-bottom: .5rem;
}
small {
font-weight: normal;
font-size: .8rem;
}
.header {
align-items: center;
background: var(--color-primary);
@ -74,6 +142,249 @@ a, a:focus, a:hover {
flex-grow: 1;
}
.loading {
padding: 4rem 0;
}
.loading--hidden {
display: none;
}
.progress {
display: block;
width: 100px;
height: 100px;
margin: 0 auto;
opacity: .2;
animation: progress-rotate 1.4s linear infinite;
transform-origin: center center;
transition: all .2s ease-in-out;
transform: rotate(0deg);
}
.progress__circle {
color: var(--color-primary);
fill: transparent;
cx: 40;
cy: 40;
r: 18;
stroke-width: 2;
stroke: currentColor;
transition: all .6s ease-in-out;
animation: progress-dash 1.4s ease-in-out infinite;
stroke-linecap: round;
stroke-dasharray: 80,200;
stroke-dashoffset: 0px;
}
.tabs {
align-items: center;
border-bottom: 1px solid var(--color-secondary-darken);
background: white;
display: flex;
font-size: .8rem;
}
.tab {
color: var(--color-primary);
cursor: pointer;
letter-spacing: .5px;
padding: 1rem 1.5rem .8rem 1.5rem;
text-transform: uppercase;
}
.tab--active {
border-bottom: 2px solid var(--color-primary);
color: var(--color-primary);
}
.tab-item {
background: white;
overflow: hidden;
}
.tab-item--hidden {
display: none;
}
.credits {
color: var(--color-text-lighten);
display: block;
text-align: right;
flex: 1;
padding: 0 1.5rem;
margin-bottom: -3px;
}
.credits--hidden {
display: none;
}
.credits__remaining {
font-weight: bold;
}
.panels {
background: var(--color-secondary);
overflow: hidden;
}
.panels--hidden {
display: none;
}
.panel {
background: white;
border: 1px solid var(--color-secondary-darken);
border-width: 1px 0;
margin: 1rem 0;
}
.panel__header {
font-weight: bold;
padding: 1rem 1.5rem;
}
.panel__content {
}
.panel__content table {
border-collapse: collapse;
margin-bottom: 1rem;
width: 100%;
}
.panel__content tr {
border-bottom: 1px solid var(--color-secondary-darken);
}
.panel__content tr:last-child {
border-bottom: none;
}
.panel__content th {
font-weight: normal;
text-align: left;
width: 33%;
}
.panel__content th, .panel__content td {
padding: .5rem;
}
.panel__content td strong {
display: block;
}
.panel__content th:first-child, .panel__content td:first-child {
padding-left: 1.5rem;
}
.panel__content th:last-child, .panel__content td:last-child {
padding-right: 1.5rem;
}
.panel__content td div {
border-bottom: 1px solid var(--color-secondary-darken);
padding: .5rem 1.5rem .5rem 0;
margin-right: -1.5rem;
}
.panel__content td div:first-child {
padding-top: 0;
}
.panel__content td div:last-child {
border-bottom: none;
padding-bottom: 0;
}
.chip, .chip:focus, .chip:hover {
border: 1px solid var(--color-secondary-darken);
border-radius: 4px;
margin: 0 .5rem .5rem 0;
display: inline-block;
padding: .2rem .5rem;
text-decoration: none;
}
.chip:focus, .chip:hover {
background: var(--color-primary-lighten)
}
.pro-configure {
margin: 1.5rem;
}
.pro-configure--hidden {
display: none;
}
.message {
background: var(--color-primary-lighten);
border-radius: 4px;
color: var(--color-primary);
padding: 1rem 1.5rem;
margin-bottom: 1.5rem;
}
.message__heading {
font-size: .9rem;
font-weight: bold;
margin: .5rem 0;
}
.message__heading__icon {
height: 1.2rem;
margin: 0 .2rem .2rem 0;
width: 1.2rem;
vertical-align: middle;
}
.message__button {
text-align: right;
}
.pro-configure__form {
background: var(--color-primary-lighten);
border-radius: 4px;
color: var(--color-primary);
padding: 1rem 1.5rem;
}
.pro-empty {
text-align: center;
padding: 4rem 1.5rem;
}
.pro-empty--hidden {
display: none;
}
.pro-crawl {
text-align: center;
padding: 4rem 1.5rem;
}
.pro-crawl--hidden {
display: none;
}
.pro-error {
margin: 1.5rem;
}
.pro-error--hidden {
display: none;
}
.pro-error__message {
border: 1px solid var(--color-error);
border-radius: 4px;
color: var(--color-error);
padding: 1rem 1.2rem;
}
.footer {
background: var(--color-primary-lighten);
bottom: 0;
@ -97,6 +408,7 @@ a, a:focus, a:hover {
flex: 1 0;
font-size: .9rem;
font-weight: bold;
margin-bottom: .5rem;
}
.footer--collapsed .footer__heading {
@ -106,6 +418,7 @@ a, a:focus, a:hover {
.footer--collapsed .footer__heading-text {
font-size: .9rem;
font-weight: inherit;
margin-bottom: 0;
opacity: .8;
}
@ -122,8 +435,14 @@ a, a:focus, a:hover {
display: flex;
}
.footer__icon {
height: 1.2rem;
margin: 0 -.4rem .1rem .2rem;
width: 1.2rem;
vertical-align: middle;
}
.footer__toggle {
fle
flex: 1;
text-align: right;
}
@ -133,10 +452,7 @@ a, a:focus, a:hover {
}
.footer__content {
font-size: .85rem;
letter-spacing: .5px;
flex: 1 0 auto;
opacity: .8;
max-width: 400px;
}
@ -148,47 +464,15 @@ a, a:focus, a:hover {
text-align: right;
}
.footer__button-link, .footer__button-link:active, .footer__button-link:hover {
color: var(--color-primary);
display: inline-block;
font-size: .85rem;
font-weight: bold;
margin: -.3rem -1rem -.5rem 0;
padding: .4rem 1rem .3rem 1rem;
position: relative;
text-decoration: none;
text-align: right;
}
.footer__button-link:hover:before {
background: var(--color-primary);
border-radius: 4px;
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
opacity: .1;
}
.footer--collapsed .footer__button {
display: none;
}
.footer__icon {
height: 1.2rem;
margin: 0 -.4rem .1rem .2rem;
width: 1.2rem;
vertical-align: middle;
}
.detections {
background: #fff;
columns: 2;
column-gap: 3rem;
min-height: 200px;
padding: 1.5rem 1.5rem .5rem 1.5rem;
padding: 1rem 1.5rem .5rem 1.5rem;
}
.detections--hidden {
@ -196,10 +480,9 @@ a, a:focus, a:hover {
}
.empty {
background: #fff;
height: calc(100% - 4.5rem);
padding: 2.5rem;
text-align: center;
margin: 2.5rem 0 3.5rem 0;
}
.empty__text {
@ -332,8 +615,7 @@ body.dynamic-icon .category__heading:hover .category__pin {
display: flex;
flex-direction: column;
justify-content: center;
height: 16rem;
width: 36rem;
margin: 3rem 1.5rem;
}
.terms--hidden {
@ -354,14 +636,13 @@ body.dynamic-icon .category__heading:hover .category__pin {
font-size: .9rem;
line-height: 150%;
text-align: center;
margin-bottom: 1rem;
width: 80%;
margin-bottom: 1.5rem;
}
.terms__button {
background-color: #4608ad;
border: none;
border-radius: 3px;
border-radius: 4px;
color: white;
cursor: pointer;
font-size: .9rem;
@ -377,7 +658,7 @@ body.dynamic-icon .category__heading:hover .category__pin {
}
.terms__privacy {
margin-top: 1rem;
margin-top: 1.5rem;
}
.options {
@ -387,7 +668,15 @@ body.dynamic-icon .category__heading:hover .category__pin {
.options__label {
display: block;
margin-bottom: .5rem;
margin-bottom: 1rem;
}
.options__input {
border: 1px solid var(--color-text);
border-radius: 4px;
padding: .5rem;
margin: .2rem 0 .5rem 0;
width: 100%;
}
.options__cache {
@ -466,6 +755,48 @@ body.dynamic-icon .category__heading:hover .category__pin {
color: var(--color-text-dark);
}
.dark a, .dark a:focus, .dark a:hover {
color: var(--color-primary-text);
}
.input[type="text"], .input[type="password"] {
border-color: var(--color-primary-darken);
}
.dark .chip:focus, .dark .chip:hover {
background: var(--color-primary);
}
.dark .message {
background: var(--color-primary);
color: var(--color-text-dark);
}
.dark .message__heading {
color: white;
}
.dark .pro-configure__form {
background: var(--color-primary);
color: var(--color-text-dark);
}
.dark .button__link, .dark .button__link:active, .dark .button__link:hover {
color: var(--color-text-dark);
}
.dark .button__link:hover:before {
background: white;
}
.dark .label {
color: white;
}
.dark .label__description {
color: var(--color-text-dark);
}
.dark .detections {
background: var(--color-primary-darken);
}
@ -486,6 +817,10 @@ body.dynamic-icon .category__heading:hover .category__pin {
opacity: .8;
}
.dark .technology__name:hover {
opacity: 1;
}
.dark .technology__icon {
}
@ -499,6 +834,59 @@ body.dynamic-icon .category__heading:hover .category__pin {
color: var(--color-text-dark);
}
.dark .progress__circle {
color: white;
}
.dark .tabs {
background: var(--color-primary-darken);
border-bottom-color: var(--color-primary);
}
.dark .tab {
color: var(--color-text-dark);
opacity: .8;
}
.dark .tab--active {
border-color: var(--color-text-dark);
opacity: 1;
}
.dark .tab-item {
background: var(--color-primary-darken);
}
.dark .credits {
color: var(--color-text-dark);
opacity: .5;
}
.dark .panels {
background: var(--color-primary-darken);
}
.dark .panel {
background: var(--color-primary-darken);
border-color: var(--color-primary);
}
.dark .panel__content tr {
border-bottom-color: var(--color-primary);
}
.dark .panel__content td {
opacity: .8;
}
.dark .panel__content tr:hover td {
opacity: 1;
}
.dark .panel__content td div {
border-color: var(--color-primary);
}
.dark .footer {
background: var(--color-primary-darken);
border-top: 1px solid var(--color-primary);
@ -513,6 +901,9 @@ body.dynamic-icon .category__heading:hover .category__pin {
background: var(--color-primary-lighten);
}
.dark .footer__content {
opacity: .8;
}
.dark .terms__button {
background-color: white;
@ -528,3 +919,31 @@ body.dynamic-icon .category__heading:hover .category__pin {
.dark .ttt-player-icon {
color: var(--color-primary-lighten);
}
@keyframes progress-rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@keyframes progress-dash {
0% {
stroke-dasharray: 1,200;
stroke-dashoffset: 0px;
}
50% {
stroke-dasharray: 100,200;
stroke-dashoffset: -15px;
}
100% {
stroke-dasharray: 100,200;
stroke-dashoffset: -125px;
}
}

@ -13,6 +13,12 @@
</head>
<body>
<div class="options">
<label class="options__label">
<span data-i18n="optionApiKey">&nbsp;</span>
<input class="options__input" type="password">
</label>
<label class="options__label">
<input class="options__checkbox" type="checkbox">

@ -44,98 +44,188 @@
</svg>
</div>
<div class="empty">
<div class="empty__text" data-i18n="noAppsDetected">&nbsp;</div>
<div class="tabs">
<div class="tab tab--active" data-i18n="tabTechnologies"></div>
<div class="tab" data-i18n="tabPro"></div>
<div class="ttt-game">
<div class="ttt-player">
<svg class="ttt-player-icon ttt-player-icon-x ttt-player-icon--ahead" viewBox="0 0 24 24">
<path fill="currentColor" d="M19,10C19,11.38 16.88,12.5 15.5,12.5C14.12,12.5 12.75,11.38 12.75,10H11.25C11.25,11.38 9.88,12.5 8.5,12.5C7.12,12.5 5,11.38 5,10H4.25C4.09,10.64 4,11.31 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12C20,11.31 19.91,10.64 19.75,10H19M12,4C9.04,4 6.45,5.61 5.07,8H18.93C17.55,5.61 14.96,4 12,4M22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2A10,10 0 0,1 22,12M12,17.23C10.25,17.23 8.71,16.5 7.81,15.42L9.23,14C9.68,14.72 10.75,15.23 12,15.23C13.25,15.23 14.32,14.72 14.77,14L16.19,15.42C15.29,16.5 13.75,17.23 12,17.23Z" />
</svg>
<div class="credits credits--hidden">
<span data-i18n="creditBalance">&nbsp;</span>
<svg class="ttt-player-icon ttt-player-icon--behind ttt-player-icon ttt-player-icon--hidden" viewBox="0 0 24 24">
<path fill="currentColor" d="M20 12A8 8 0 1 0 12 20A8 8 0 0 0 20 12M22 12A10 10 0 1 1 12 2A10 10 0 0 1 22 12M15.5 8A1.5 1.5 0 1 1 14 9.5A1.54 1.54 0 0 1 15.5 8M10 9.5A1.5 1.5 0 1 1 8.5 8A1.54 1.54 0 0 1 10 9.5M17 15H13A4 4 0 0 0 9.53 17L7.8 16A6 6 0 0 1 13 13H17Z" />
</svg>
<span class="credits__remaining">&nbsp;</span>
</div>
</div>
<div class="ttt-score ttt-score-x">0</div>
</div>
<div class="tab-item">
<div class="empty">
<div class="empty__text" data-i18n="noAppsDetected">&nbsp;</div>
<div class="ttt-game">
<div class="ttt-player">
<svg class="ttt-player-icon ttt-player-icon-x ttt-player-icon--ahead" viewBox="0 0 24 24">
<path fill="currentColor" d="M19,10C19,11.38 16.88,12.5 15.5,12.5C14.12,12.5 12.75,11.38 12.75,10H11.25C11.25,11.38 9.88,12.5 8.5,12.5C7.12,12.5 5,11.38 5,10H4.25C4.09,10.64 4,11.31 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12C20,11.31 19.91,10.64 19.75,10H19M12,4C9.04,4 6.45,5.61 5.07,8H18.93C17.55,5.61 14.96,4 12,4M22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2A10,10 0 0,1 22,12M12,17.23C10.25,17.23 8.71,16.5 7.81,15.42L9.23,14C9.68,14.72 10.75,15.23 12,15.23C13.25,15.23 14.32,14.72 14.77,14L16.19,15.42C15.29,16.5 13.75,17.23 12,17.23Z" />
</svg>
<div class="ttt-grid">
<div class="ttt-row">
<div class="ttt-cell"></div><div class="ttt-cell"></div><div class="ttt-cell"></div>
<svg class="ttt-player-icon ttt-player-icon--behind ttt-player-icon ttt-player-icon--hidden" viewBox="0 0 24 24">
<path fill="currentColor" d="M20 12A8 8 0 1 0 12 20A8 8 0 0 0 20 12M22 12A10 10 0 1 1 12 2A10 10 0 0 1 22 12M15.5 8A1.5 1.5 0 1 1 14 9.5A1.54 1.54 0 0 1 15.5 8M10 9.5A1.5 1.5 0 1 1 8.5 8A1.54 1.54 0 0 1 10 9.5M17 15H13A4 4 0 0 0 9.53 17L7.8 16A6 6 0 0 1 13 13H17Z" />
</svg>
<div class="ttt-score ttt-score-x">0</div>
</div>
<div class="ttt-row">
<div class="ttt-cell"></div><div class="ttt-cell"></div><div class="ttt-cell"></div>
<div class="ttt-grid">
<div class="ttt-row">
<div class="ttt-cell"></div><div class="ttt-cell"></div><div class="ttt-cell"></div>
</div>
<div class="ttt-row">
<div class="ttt-cell"></div><div class="ttt-cell"></div><div class="ttt-cell"></div>
</div>
<div class="ttt-row">
<div class="ttt-cell"></div><div class="ttt-cell"></div><div class="ttt-cell"></div>
</div>
</div>
<div class="ttt-row">
<div class="ttt-cell"></div><div class="ttt-cell"></div><div class="ttt-cell"></div>
<div class="ttt-player">
<svg class="ttt-player-icon ttt-player-icon-o" viewBox="0 0 24 24">
<path fill="currentColor" d="M9,11.75A1.25,1.25 0 0,0 7.75,13A1.25,1.25 0 0,0 9,14.25A1.25,1.25 0 0,0 10.25,13A1.25,1.25 0 0,0 9,11.75M15,11.75A1.25,1.25 0 0,0 13.75,13A1.25,1.25 0 0,0 15,14.25A1.25,1.25 0 0,0 16.25,13A1.25,1.25 0 0,0 15,11.75M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20C7.59,20 4,16.41 4,12C4,11.71 4,11.42 4.05,11.14C6.41,10.09 8.28,8.16 9.26,5.77C11.07,8.33 14.05,10 17.42,10C18.2,10 18.95,9.91 19.67,9.74C19.88,10.45 20,11.21 20,12C20,16.41 16.41,20 12,20Z" />
</svg>
<div class="ttt-score ttt-score-o">0</div>
</div>
</div>
<div class="ttt-player">
<svg class="ttt-player-icon ttt-player-icon-o" viewBox="0 0 24 24">
<path fill="currentColor" d="M9,11.75A1.25,1.25 0 0,0 7.75,13A1.25,1.25 0 0,0 9,14.25A1.25,1.25 0 0,0 10.25,13A1.25,1.25 0 0,0 9,11.75M15,11.75A1.25,1.25 0 0,0 13.75,13A1.25,1.25 0 0,0 15,14.25A1.25,1.25 0 0,0 16.25,13A1.25,1.25 0 0,0 15,11.75M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20C7.59,20 4,16.41 4,12C4,11.71 4,11.42 4.05,11.14C6.41,10.09 8.28,8.16 9.26,5.77C11.07,8.33 14.05,10 17.42,10C18.2,10 18.95,9.91 19.67,9.74C19.88,10.45 20,11.21 20,12C20,16.41 16.41,20 12,20Z" />
<svg class="ttt-icon ttt-icon-x" viewBox="0 0 24 24">
<path fill="currentColor" d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" />
</svg>
<div class="ttt-score ttt-score-o">0</div>
<svg class="ttt-icon ttt-icon-o" viewBox="0 0 24 24">
<path fill="currentColor" d="M12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4A8,8 0 0,1 20,12A8,8 0 0,1 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" />
</svg>
</div>
</div>
<svg class="ttt-icon ttt-icon-x" viewBox="0 0 24 24">
<path fill="currentColor" d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" />
</svg>
<div class="detections detections--hidden"></div>
<svg class="ttt-icon ttt-icon-o" viewBox="0 0 24 24">
<path fill="currentColor" d="M12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4A8,8 0 0,1 20,12A8,8 0 0,1 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" />
</svg>
<div class="terms terms--hidden">
<div class="terms__content" data-i18n="termsContent"></div>
<div class="terms__buttons">
<button class="terms__button terms__button--accept" data-i18n="termsAccept">&nbsp;</button>
<button class="terms__button terms__button--decline" data-i18n="termsDecline">&nbsp;</button>
</div>
<a class="terms__privacy" href="https://www.wappalyzer.com/privacy/?utm_source=popup&utm_medium=extension&utm_campaign=wappalyzer" data-i18n="privacyPolicy"></a>
</div>
</div>
<div class="detections detections--hidden"></div>
<div data-template="category" class="category">
<div class="category__heading">
<a class="category__link" href="#"></a>
<svg class="category__pin category__pin--outline" viewBox="0 0 24 24">
<title data-i18n="categoryPin"></title>
<path fill="currentColor" d="M16,12V4H17V2H7V4H8V12L6,14V16H11.2V22H12.8V16H18V14L16,12M8.8,14L10,12.8V4H14V12.8L15.2,14H8.8Z" />
</svg>
<div class="terms terms--hidden">
<div class="terms__content" data-i18n="termsContent"></div>
<svg class="category__pin" viewBox="0 0 24 24">
<title data-i18n="categoryPin"></title>
<path fill="currentColor" d="M16,12V4H17V2H7V4H8V12L6,14V16H11.2V22H12.8V16H18V14L16,12Z" />
</svg>
</div>
<div class="terms__buttons">
<button class="terms__button terms__button--accept" data-i18n="termsAccept">&nbsp;</button>
<button class="terms__button terms__button--decline" data-i18n="termsDecline">&nbsp;</button>
<div class="technologies"></div>
</div>
<a class="terms__privacy" href="https://www.wappalyzer.com/privacy/?utm_source=popup&utm_medium=extension&utm_campaign=wappalyzer" data-i18n="privacyPolicy"></a>
<div data-template="technology" class="technology">
<div class="technology__heading">
<a class="technology__link" href="#">
<div class="technology__icon">
<img alt="" src="../images/icons/default.svg" />
</div>
<span class="technology__name">&nbsp;</span>
<span>
<span class="technology__version">&nbsp;</span>
</span>
<span class="technology__confidence">&nbsp;</span>
</a>
</div>
</div>
</div>
<div data-template="category" class="category">
<div class="category__heading">
<a class="category__link" href="#"></a>
<div class="tab-item tab-item--hidden">
<div class="pro-error pro-error--hidden">
<div class="pro-error__message">
</div>
</div>
<svg class="category__pin category__pin--outline" viewBox="0 0 24 24">
<title data-i18n="categoryPin"></title>
<path fill="currentColor" d="M16,12V4H17V2H7V4H8V12L6,14V16H11.2V22H12.8V16H18V14L16,12M8.8,14L10,12.8V4H14V12.8L15.2,14H8.8Z" />
<div class="loading">
<svg class="progress" viewBox="20 20 40 40">
<circle class="progress__circle"></circle>
</svg>
</div>
<svg class="category__pin" viewBox="0 0 24 24">
<title data-i18n="categoryPin"></title>
<path fill="currentColor" d="M16,12V4H17V2H7V4H8V12L6,14V16H11.2V22H12.8V16H18V14L16,12Z" />
</svg>
<div class="panels panels--hidden">
</div>
<div class="technologies"></div>
</div>
<div class="pro-configure pro-configure--hidden">
<div class="message">
<div class="message__heading">
<svg class="message__heading__icon" viewBox="0 0 24 24">
<path fill="currentColor" d="M10 13C11.1 13 12 13.89 12 15C12 16.11 11.11 17 10 17S8 16.11 8 15 8.9 13 10 13M18 1C15.24 1 13 3.24 13 6V8H4C2.9 8 2 8.9 2 10V20C2 21.1 2.9 22 4 22H16C17.1 22 18 21.1 18 20V10C18 8.9 17.1 8 16 8H15V6C15 4.34 16.34 3 18 3S21 4.34 21 6V8H23V6C23 3.24 20.76 1 18 1M16 10V20H4V10H16Z" />
</svg>
<div data-template="technology" class="technology">
<div class="technology__heading">
<a class="technology__link" href="#">
<div class="technology__icon">
<img alt="" src="../images/icons/default.svg" />
<span data-i18n="proMessageHeading">&nbsp;</span>
</div>
<span class="technology__name">&nbsp;</span>
<p>
<span data-i18n="proMessage">&nbsp;</span>
<small>
(<a href="https://www.wappalyzer.com/faq/extension/?utm_source=popup&utm_medium=extension&utm_campaign=wappalyzer" data-i18n="proFaq">&nbsp;</a>)
</small>
</p>
<div class="message__button button">
<a class="button__link" href="https://www.wappalyzer.com/pricing/?utm_source=popup&utm_medium=extension&utm_campaign=wappalyzer">
<span class="button__text" data-i18n="proButton"></span>
<svg class="button__icon button__icon--right" viewBox="0 0 24 24">
<path fill="currentColor" d="M4,11V13H16L10.5,18.5L11.92,19.92L19.84,12L11.92,4.08L10.5,5.5L16,11H4Z" />
</svg>
</a>
</div>
</div>
<span>
<span class="technology__version">&nbsp;</span>
</span>
<form class="pro-configure__form">
<div class="control">
<span class="label">
<span data-i18n="optionApiKey">&nbsp;</span>
<span class="technology__confidence">&nbsp;</span>
</a>
<small class="label__description">
(<a href="https://www.wappalyzer.com/apikey/?utm_source=popup&utm_medium=extension&utm_campaign=wappalyzer" data-i18n="optionApiKeyDescription"></a>)
</small>
</span>
<input type="password" class="pro-configure__apikey input" />
</div>
<div class="message__button button">
<span class="pro-configure__save button__link">
<svg class="button__icon button__icon--left" viewBox="0 0 24 24">
<path fill="currentColor" d="M15,9H5V5H15M12,19A3,3 0 0,1 9,16A3,3 0 0,1 12,13A3,3 0 0,1 15,16A3,3 0 0,1 12,19M17,3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V7L17,3Z" />
</svg>
<span class="button__text" data-i18n="formSave"></span>
</span>
</div>
</form>
</div>
<div class="pro-empty pro-empty--hidden">
No results found.
</div>
<div class="pro-crawl pro-crawl--hidden">
Website is being analysed, check back later.
</div>
</div>
@ -159,11 +249,11 @@
<p class="footer__content-body">&nbsp;</p>
</div>
<div class="footer__button">
<a class="footer__button-link" href="#">
<span class="footer__button-text">&nbsp;</span>
<div class="footer__button button">
<a class="button__link" href="#">
<span class="button__text">&nbsp;</span>
<svg class="footer__icon" viewBox="0 0 24 24">
<svg class="button__icon button__icon--right" viewBox="0 0 24 24">
<path fill="currentColor" d="M4,11V13H16L10.5,18.5L11.92,19.92L19.84,12L11.92,4.08L10.5,5.5L16,11H4Z" />
</svg>
</a>

@ -18,6 +18,7 @@ const Options = {
['badge', true],
['tracking', true],
['showCached', true],
['apiKey', ''],
].map(async ([option, defaultValue]) => {
const el = document
.querySelector(
@ -27,15 +28,27 @@ const Options = {
)
.parentNode.querySelector('input')
el.checked =
!!(await getOption(option, defaultValue)) &&
(option !== 'tracking' || termsAccepted)
if (el.type === 'checkbox') {
el.checked =
!!(await getOption(option, defaultValue)) &&
(option !== 'tracking' || termsAccepted)
el.addEventListener('click', async () => {
await setOption(option, !!el.checked)
})
el.addEventListener('click', async () => {
await setOption(option, !!el.checked)
})
} else if (el.type === 'password') {
el.value = await getOption(option, defaultValue)
}
})
document
.querySelector('[data-i18n="optionApiKey"]')
.parentNode.querySelector('input')
.addEventListener(
'input',
async (event) => await setOption('apiKey', event.target.value)
)
document
.querySelector('.options__cache')
.addEventListener('click', () => Options.driver('clearCache'))

@ -140,13 +140,15 @@ const Popup = {
})
}
let url
const tabs = await promisify(chrome.tabs, 'query', {
active: true,
currentWindow: true,
})
if (tabs && tabs.length) {
const [{ url }] = tabs
;[{ url }] = tabs
if (url.startsWith('http')) {
const { hostname } = new URL(url)
@ -185,6 +187,23 @@ const Popup = {
}
}
// PRO configuration
const apiKey = document.querySelector('.pro-configure__apikey')
apiKey.value = await getOption('apiKey', '')
document
.querySelector('.pro-configure__save')
.addEventListener('click', async (event) => {
await setOption(
'apiKey',
document.querySelector('.pro-configure__apikey').value
)
await Popup.getPro(url)
})
// Header
document
.querySelector('.header__settings')
.addEventListener('click', () => chrome.runtime.openOptionsPage())
@ -211,6 +230,27 @@ const Popup = {
})
)
// Tabs
const tabHeadings = Array.from(document.querySelectorAll('.tab'))
const tabItems = Array.from(document.querySelectorAll('.tab-item'))
const credits = document.querySelector('.credits')
tabHeadings.forEach((tab, index) => {
tab.addEventListener('click', async () => {
tabHeadings.forEach((tab) => tab.classList.remove('tab--active'))
tabItems.forEach((item) => item.classList.add('tab-item--hidden'))
tab.classList.add('tab--active')
tabItems[index].classList.remove('tab-item--hidden')
credits.classList.add('credits--hidden')
if (index === 1) {
await Popup.getPro(url)
}
})
})
// Footer
const item =
footers[
@ -221,8 +261,9 @@ const Popup = {
document.querySelector('.footer__heading-text').textContent = item.heading
document.querySelector('.footer__content-body').textContent = item.body
document.querySelector('.footer__button-text').textContent = item.buttonText
document.querySelector('.footer__button-link').href = item.buttonLink
document.querySelector('.footer .button__text').textContent =
item.buttonText
document.querySelector('.footer .button__link').href = item.buttonLink
const collapseFooter = await getOption('collapseFooter', false)
@ -252,6 +293,16 @@ const Popup = {
await setOption('collapseFooter', !collapsed)
})
Array.from(document.querySelectorAll('a')).forEach((a) =>
a.addEventListener('click', (event) => {
event.preventDefault()
open(a.href)
return false
})
)
// Apply internationalization
i18n()
},
@ -416,6 +467,232 @@ const Popup = {
i18n()
},
/**
* TODO
*/
async getPro(url) {
const apiKey = await getOption('apiKey', '')
const el = {
loading: document.querySelector('.loading'),
panels: document.querySelector('.panels'),
empty: document.querySelector('.pro-empty'),
crawl: document.querySelector('.pro-crawl'),
error: document.querySelector('.pro-error'),
errorMessage: document.querySelector('.pro-error__message'),
configure: document.querySelector('.pro-configure'),
credits: document.querySelector('.credits'),
creditsRemaining: document.querySelector('.credits__remaining'),
}
el.error.classList.add('pro-error--hidden')
if (apiKey) {
el.loading.classList.remove('loading--hidden')
el.configure.classList.add('pro-configure--hidden')
} else {
el.loading.classList.add('loading--hidden')
el.configure.classList.remove('pro-configure--hidden')
return
}
el.panels.classList.add('panels--hidden')
el.empty.classList.add('pro-empty--hidden')
el.crawl.classList.add('pro-crawl--hidden')
el.error.classList.add('pro-error--hidden')
while (el.panels.lastElementChild) {
el.panels.removeChild(el.panels.lastElementChild)
}
try {
const response = await fetch(
`https://api.wappalyzer.com/pro/v2/${encodeURIComponent(url)}`,
{
method: 'GET',
headers: {
'x-api-key': apiKey,
},
}
)
const data = await response.json()
if (!response.ok) {
const error = new Error()
error.data = data
error.response = response
throw error
}
const { attributes, creditsRemaining, crawl } = data
el.creditsRemaining.textContent = parseInt(
creditsRemaining || 0,
10
).toLocaleString()
el.credits.classList.remove('credits--hidden')
el.loading.classList.add('loading--hidden')
if (crawl) {
document
.querySelector('.pro-crawl')
.classList.remove('pro-crawl--hidden')
return
}
if (!Object.keys(attributes).length) {
el.empty.classList.remove('pro-empty--hidden')
return
}
Object.keys(attributes).forEach((set) => {
const panel = document.createElement('div')
const header = document.createElement('div')
const content = document.createElement('div')
const table = document.createElement('table')
panel.classList.add('panel')
header.classList.add('panel__header')
content.classList.add('panel__content')
header.setAttribute(
'data-i18n',
`set${set.charAt(0).toUpperCase() + set.slice(1)}`
)
Object.keys(attributes[set]).forEach((key) => {
const value = attributes[set][key]
const tr = document.createElement('tr')
const th = document.createElement('th')
const td = document.createElement('td')
th.setAttribute(
'data-i18n',
`attribute${
key.charAt(0).toUpperCase() + key.slice(1).replace('.', '_')
}`
)
if (Array.isArray(value)) {
value.forEach((value) => {
const div = document.createElement('div')
if (typeof value === 'object') {
const a = document.createElement('a')
a.href = value.to
a.textContent = value.text
if (
['social', 'keywords'].includes(set) ||
['phone', 'email'].includes(key)
) {
a.classList.add('chip')
td.appendChild(a)
} else {
div.appendChild(a)
td.appendChild(div)
}
} else if (key === 'employees') {
const [name, title] = value.split(' -- ')
const strong = document.createElement('strong')
const span = document.createElement('span')
strong.textContent = name
span.textContent = title
div.appendChild(strong)
div.appendChild(span)
td.appendChild(div)
} else {
div.textContent = value
td.appendChild(div)
}
})
} else if (key === 'companyName') {
const strong = document.createElement('strong')
strong.textContent = value
td.appendChild(strong)
} else {
td.textContent = value
}
if (key !== 'keywords') {
tr.appendChild(th)
}
tr.appendChild(td)
table.appendChild(tr)
})
content.appendChild(table)
panel.appendChild(header)
panel.appendChild(content)
el.panels.appendChild(panel)
})
el.panels.classList.remove('panels--hidden')
} catch (error) {
Popup.log(error.data)
// eslint-disable-next-line
console.log(error)
el.errorMessage.textContent = `Sorry, something went wrong${
error.response ? ` (${error.response.status})` : ''
}. Please try again later.`
if (error.response) {
if (error.response.status === 403) {
el.errorMessage.textContent =
typeof error.data === 'string'
? error.data
: 'No access. Please check your API key.'
el.configure.classList.remove('pro-configure--hidden')
} else if (error.response.status === 429) {
el.errorMessage.textContent =
'Too many requests. Please try again in a few seconds.'
} else if (
error.response.status === 400 &&
typeof error.data === 'string'
) {
el.errorMessage.textContent = error.data
}
}
el.loading.classList.add('loading--hidden')
el.error.classList.remove('pro-error--hidden')
}
Array.from(document.querySelectorAll('.panels a')).forEach((a) =>
a.addEventListener('click', (event) => {
event.preventDefault()
open(a.href)
return false
})
)
i18n()
},
}
if (/complete|interactive|loaded/.test(document.readyState)) {

@ -4,7 +4,7 @@
"author": "Wappalyzer",
"homepage_url": "https://www.wappalyzer.com/",
"description": "Identify web technologies",
"version": "6.7.4",
"version": "6.7.5",
"default_locale": "en",
"manifest_version": 2,
"icons": {

@ -13,7 +13,7 @@
"software"
],
"homepage": "https://www.wappalyzer.com/",
"version": "6.7.4",
"version": "6.7.5",
"author": "Wappalyzer",
"license": "MIT",
"repository": {

@ -5010,7 +5010,9 @@
"js": {
"corebine": ""
},
"pricing": ["poa"],
"pricing": [
"poa"
],
"website": "https://corebine.com"
},
"Cosmoshop": {
@ -6235,22 +6237,6 @@
"url": "https?://(?:[^/]+\\.)?edgecastcdn\\.net/",
"website": "http://www.edgecast.com"
},
"eDokan": {
"cats": [
6
],
"description": "eDokan is hosted ecommerce platform with drag-drop template builder and zero programming knowledge.",
"icon": "eDokan.png",
"implies": [
"Node.js",
"Angular",
"MongoDB"
],
"dom": "img[src*='cdn.edokan.co']",
"saas": true,
"pricing": ["low", "recurring"],
"website": "https://edokan.co"
},
"Elasticsearch": {
"cats": [
29
@ -9411,9 +9397,12 @@
"js": {
"Intercom": ""
},
"scripts": "(?:api\\.intercom\\.io/api|static\\.intercomcdn\\.com/intercom\\.v1)",
"pricing": [
"mid",
"recurring"
],
"saas": true,
"pricing": ["mid","recurring"],
"scripts": "(?:api\\.intercom\\.io/api|static\\.intercomcdn\\.com/intercom\\.v1)",
"website": "https://www.intercom.com"
},
"Intercom Articles": {
@ -11116,7 +11105,6 @@
6
],
"description": "Localised is local-first ecommerce platform.",
"icon": "Localised.png",
"dom": {
"img[src='.localised.com'": {
"attributes": {
@ -11129,10 +11117,13 @@
}
}
},
"xhr": "api\\.localised\\.com",
"icon": "Localised.png",
"pricing": [
"poa"
],
"saas": true,
"pricing": ["poa"],
"website": "https://www.localised.com"
"website": "https://www.localised.com",
"xhr": "api\\.localised\\.com"
},
"LocomotiveCMS": {
"cats": [
@ -17370,7 +17361,6 @@
}
},
"icon": "Shopify.svg",
"implies": "Shopify",
"scripts": [
"cdn\\.shopify\\.com/shopifycloud/shopify_pay/"
],
@ -18748,17 +18738,21 @@
1
],
"description": "Statamic is an open-source and self-hosted content management system based on the PHP programming language.",
"icon": "Statamic.svg",
"headers": {
"x-powered-by": "^Statamic$"
},
"icon": "Statamic.svg",
"implies": [
"PHP",
"Laravel"
],
"saas": false,
"oss": true,
"pricing": ["freemium", "mid", "payg"],
"pricing": [
"freemium",
"mid",
"payg"
],
"saas": false,
"website": "https://statamic.com"
},
"Statcounter": {
@ -19881,7 +19875,6 @@
"js": {
"TrackJs": ""
},
"scripts": "tracker\\.js",
"website": "http://trackjs.com"
},
"Tradedoubler": {
@ -21702,10 +21695,7 @@
6
],
"description": "WooCommerce is an open-source ecommerce plugin for WordPress.",
"html": [
"<!-- WooCommerce",
"<link rel='[^']+' id='woocommerce-(?:layout|smallscreen|general)-css' href='https?://[^/]+/wp-content/plugins/woocommerce/assets/css/woocommerce(?:-layout|-smallscreen)?\\.css?ver=([\\d.]+)'\\;version:\\1"
],
"dom": ".woocommerce, .woocommerce-no-js, link[rel*='woocommerce']",
"icon": "WooCommerce.svg",
"implies": "WordPress",
"js": {
@ -21715,7 +21705,10 @@
"generator": "WooCommerce ([\\d.]+)\\;version:\\1"
},
"oss": true,
"scripts": "/woocommerce(?:\\.min)?\\.js(?:\\?ver=([0-9.]+))?\\;version:\\1",
"scripts": [
"woocommerce",
"/woocommerce(?:\\.min)?\\.js(?:\\?ver=([0-9.]+))?\\;version:\\1"
],
"website": "https://woocommerce.com"
},
"Woopra": {
@ -22774,6 +22767,25 @@
},
"website": "https://www.eclass.com.hk"
},
"eDokan": {
"cats": [
6
],
"description": "eDokan is hosted ecommerce platform with drag-drop template builder and zero programming knowledge.",
"dom": "img[src*='cdn.edokan.co']",
"icon": "eDokan.png",
"implies": [
"Node.js",
"Angular",
"MongoDB"
],
"pricing": [
"low",
"recurring"
],
"saas": true,
"website": "https://edokan.co"
},
"eSyndiCat": {
"cats": [
1