diff --git a/.eslintrc.js b/.eslintrc.js
index 8ff448efd..f91394cce 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -2,19 +2,18 @@ module.exports = {
root: true,
env: {
browser: true,
- node: true
+ node: true,
},
parserOptions: {
- parser: 'babel-eslint'
+ parser: 'babel-eslint',
},
extends: [
'@nuxtjs',
'prettier',
'prettier/vue',
'plugin:prettier/recommended',
- 'plugin:nuxt/recommended'
- ],
- plugins: [
- 'prettier'
+ 'plugin:nuxt/recommended',
+ 'plugin:json/recommended',
],
+ plugins: ['prettier'],
}
diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml
new file mode 100644
index 000000000..e9041ab8f
--- /dev/null
+++ b/.github/workflows/validate.yml
@@ -0,0 +1,25 @@
+name: Validate
+on:
+ push:
+ pull_request:
+
+jobs:
+ validate:
+ name: Validate
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2.3.3
+ - uses: actions/setup-node@v2.1.2
+ with:
+ node-version: '14'
+ - name: Restore npm cache
+ uses: actions/cache@v2
+ with:
+ path: ~/.npm
+ key: ${{ runner.os }}-node-${{ hashFiles('**/package.json') }}
+ restore-keys: |
+ ${{ runner.os }}-node-
+ - name: Install dependencies
+ run: npm install
+ - name: Validate
+ run: npm run validate
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 000000000..253e4a11f
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,37 @@
+# Contributing
+
+Wappalyzer is an [MIT-licensed](https://github.com/aliasio/wappalyzer/blob/master/LICENSE), open source project written in JavaScript. Anyone is welcome to contribute.
+
+## Getting started
+
+To get started, see the [README](https://github.com/aliasio/wappalyzer/blob/master/README.md).
+
+## Submitting changes
+
+- First, run `yarn run validate` to identify any issues.
+- Use descriptive commit messages, e.g. 'Add WordPress detection'.
+- Push your commits to a new branch on your own fork.
+- Finally, submit a [pull request](https://help.github.com/articles/about-pull-requests/) and describe your changes.
+
+## Adding a new technology
+
+Wappalyzer uses [regular expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions) to fingerprint technologies. Refer to the [specification](https://github.com/AliasIO/wappalyzer/blob/master/README.md#specification) for detail.
+
+- Add a new block to [`src/technologies.json`](https://github.com/aliasio/wappalyzer/blob/master/src/technologies.json).
+- Add an icon to [`src/drivers/webextension/images/icons`](https://github.com/aliasio/wappalyzer/tree/master/src/drivers/webextension/images/icons). The image must be square, either SVG or PNG (32 x 32 pixels).
+
+Only widely used technologies are accepted. When creating a pull request, include ten or more links to websites that use the application, a GitHub page with at least 1,000 stars or anything that will help establish the size of the user base.
+
+## Adding a new category
+
+Please [open an issue on GitHub](https://github.com/aliasio/wappalyzer/issues) first to discuss the need for a new category.
+
+To add a category, edit [`src/technologies.json`](https://github.com/aliasio/wappalyzer/blob/master/src/technologies.json) and update every [locale](https://github.com/aliasio/wappalyzer/tree/master/src/drivers/webextension/_locales). You may use the English category name in all of them.
+
+## Adding a new translation
+
+To add a new translation, copy the `en` folder in [`src/drivers/webextension/_locales`](https://github.com/aliasio/wappalyzer/tree/master/src/drivers/webextension/_locales), rename it to the relevant two-letter country code and update the containing `messages.json` file.
+
+## Adding a new feature
+
+Please [open an issue on GitHub](https://github.com/aliasio/wappalyzer/issues) first. New features and large changes are rarely accepted without prior discussion.
diff --git a/README.md b/README.md
index 97fdd7fc3..024c403fd 100644
--- a/README.md
+++ b/README.md
@@ -1,21 +1,19 @@
# Wappalyzer [![Travis](https://travis-ci.org/aliasio/wappalyzer.svg?branch=master)](https://travis-ci.org/aliasio/wappalyzer/)
-[Wappalyzer](https://www.wappalyzer.com) identifies technologies on websites.
-It detects content management systems, ecommerce platforms, JavaScript frameworks,
-analytics tools and [much more](https://www.wappalyzer.com/technologies).
+[Wappalyzer](https://www.wappalyzer.com) identifies technologies on websites, including content management systems, ecommerce platforms, JavaScript frameworks, analytics tools and [much more](https://www.wappalyzer.com/technologies).
* [wappalyzer on NPM](https://www.npmjs.com/package/wappalyzer)
* [wappalyzer-core on NPM](https://www.npmjs.com/package/wappalyzer-core)
* [Chrome extension](https://chrome.google.com/webstore/detail/wappalyzer/gppongmhjkpfnbhagpmjfkannfbllamg)
* [Firefox add-on](https://addons.mozilla.org/en-US/firefox/addon/wappalyzer/)
* [Edge extension](https://microsoftedge.microsoft.com/addons/detail/mnbndgmknlpdjdnjfmfcdjoegcckoikn)
-* [Bookmarklet](https://www.wappalyzer.com/download)
-* [wappalyzer/cli on Docker Hub](https://hub.docker.com/r/wappalyzer/cli/)
* [Wappalyzer REST APIs](https://www.wappalyzer.com/api/)
-## Documentation
+## Prerequisites
-Please read the [developer documentation](https://www.wappalyzer.com/docs).
+- [Git](https://git-scm.com)
+- [Node.js](https://nodejs.org) version 12 or higher
+- [Yarn](https://yarnpkg.com)
## Quick start
@@ -46,3 +44,423 @@ node src/drivers/npm/cli.js https://example.com
* Go go `about:debugging#/runtime/this-firefox`
* Click 'Load Temporary Add-on'
* Select `src/drivers/webextension/manifest.json`
+
+## Specification
+
+A long list of [regular expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions) is used to identify technologies on web pages. Wappalyzer inspects HTML code, as well as JavaScript variables, response headers and more.
+
+Patterns (regular expressions) are kept in [`src/technologies.json`](https://github.com/aliasio/wappalyzer/blob/master/src/technologies.json). The following is an example of an application fingerprint.
+
+#### Example
+
+```json
+"Example": {
+ "description": "A short description of the technology.",
+ "cats": [
+ "1"
+ ],
+ "cookies": {
+ "cookie_name": "Example"
+ },
+ "dom": {
+ "#example-id": {
+ "attributes": {
+ "class": "example-class"
+ },
+ "properties": {
+ "example-property": ""
+ },
+ "text": "Example text content"
+ }
+ },
+ "dns": {
+ "MX": [
+ "example\\.com"
+ ]
+ },
+ "js": {
+ "Example.method": ""
+ },
+ "excludes": "Example",
+ "headers": {
+ "X-Powered-By": "Example"
+ },
+ "html": " ]example\\.css",
+ "css": "\\.example-class",
+ "robots": "Disallow: /unique-path/",
+ "implies": "PHP\\;confidence:50",
+ "meta": {
+ "generator": "(?:Example|Another Example)"
+ },
+ "script": "example-([0-9.]+)\\.js\\;confidence:50\\;version:\\1",
+ "url": ".+\\.example\\.com",
+ "oss": true,
+ "saas": true,
+ "pricing": ["low", "medium", "high", "freemium", "onetime", "recurring", "poa"],
+ "website": "https://example.com",
+}
+```
+
+## JSON fields
+
+Find the JSON schema at [`schema.json`](https://github.com/aliasio/wappalyzer/blob/master/schema.json).
+
+### Required properties
+
+
+
+
+ Field
+ Type
+ Description
+ Example
+
+
+
+
+ cats
+ Array
+
+ One or more category IDs.
+
+ [1, 6]
+
+
+ website
+ String
+ URL of the application's website.
+
+ "https://example.com"
+
+
+
+
+
+### Optional properties
+
+
+
+
+ Field
+ Type
+ Description
+ Example
+
+
+
+
+ description
+ String
+
+ A short description of the technology in British English (max.
+ 250 characters). Write in a neutral, factual tone; not like an
+ ad.
+
+ "A short description."
+
+
+ icon
+ String
+ Application icon filename.
+ "WordPress.svg"
+
+
+ cpe
+ String
+
+ The
+ CPE
+ is a structured naming scheme for applications, see the
+ specification .
+
+ "cpe:/a:apache:http_server"
+
+
+ saas
+ Boolean
+
+ The technology is offered as a Software-as-a-Service (SaaS), i.e. hosted or cloud-based.
+
+ true
+
+
+ oss
+ Boolean
+
+ The technology has an open-source license.
+
+ true
+
+
+ pricing
+ Array
+
+Cost indicator (based on a typical plan or average monthly price) and available pricing models. For paid products only.
+
+One of:
+
+ low
Up to US 100 / mo
+ mid
Up US 1,000 / mo
+ high
More than 10,000 / mo
+
+
+Plus any of:
+
+ freemium
Free plan available
+ onetime
One-time payments accepted
+ recurring
Subscriptions available
+ poa
Price on asking
+ payg
Pay as you go (e.g. commissions or usage-based fees)
+
+
+ ["low", "freemium"]
+
+
+
+
+### Implies and excludes (optional)
+
+
+
+
+
+ Field
+ Type
+ Description
+ Example
+
+
+
+
+ implies
+ String | Array
+
+ The presence of one application can imply the presence of
+ another, e.g. WordpPress means PHP is also in use.
+
+ "PHP"
+
+
+ excludes
+ String | Array
+
+ Opposite of implies. The presence of one application can exclude
+ the presence of another.
+
+ "Apache"
+
+
+
+
+### Patterns (optional)
+
+
+
+
+ Field
+ Type
+ Description
+ Example
+
+
+
+
+ cookies
+ Object
+ Cookies.
+ { "cookie_name": "Cookie value" }
+
+
+ dom
+ Object
+
+ Uses a
+ query selector
+ to inspect element properties, attributes and text content.
+
+
+ { "#example-id": { "property": { "example-prop": "" } }
+ }
+
+
+
+ dns
+ Object
+
+ DNS records: supports MX, TXT, SOA and NS (NPM driver only).
+
+
+ { "MX": "example\\.com" }
+
+
+
+ js
+ Object
+
+ JavaScript properties (case sensitive). Avoid short property
+ names to prevent matching minified code.
+
+ { "jQuery.fn.jquery": "" }
+
+
+ headers
+ Object
+ HTTP response headers.
+ { "X-Powered-By": "^WordPress$" }
+
+
+ html
+ String | Array
+
+ HTML source code. Patterns must include an HTML opening tag to
+ avoid matching plain text. For performance reasons, avoid
+ html
where possible and use
+ dom
instead.
+
+ "<a [^>]*href=\"index.html"
+
+
+ css
+ String | Array
+
+ CSS rules. Unavailable when a website enforces a same-origin
+ policy. For performance reasons, only a portion of the available
+ CSS rules are used to find matches.
+
+ "\\.example-class"
+
+
+ robots
+ String | Array
+
+ Robots.txt contents.
+
+ "Disallow: /unique-path/"
+
+
+ url
+ String
+ Full URL of the page.
+ "^https?//.+\\.wordpress\\.com"
+
+
+ meta
+ Object
+ HTML meta tags, e.g. generator.
+ { "generator": "^WordPress$" }
+
+
+ scripts
+ String | Array
+
+ URLs of JavaScript files included on the page.
+
+ "jquery\\.js"
+
+
+
+
+## Patterns
+
+Patterns are essentially JavaScript regular expressions written as strings, but with some additions.
+
+### Quirks and pitfalls
+
+- Because of the string format, the escape character itself must be escaped when using special characters such as the dot (`\\.`). Double quotes must be escaped only once (`\"`). Slashes do not need to be escaped (`/`).
+- Flags are not supported. Regular expressions are treated as case-insensitive.
+- Capture groups (`()`) are used for version detection. In other cases, use non-capturing groups (`(?:)`).
+- Use start and end of string anchors (`^` and `$`) where possible for optimal performance.
+- Short or generic patterns can cause applications to be identified incorrectly. Try to find unique strings to match.
+
+### Tags
+
+Tags (a non-standard syntax) can be appended to patterns (and implies and excludes, separated by `\\;`) to store additional information.
+
+
+
+
+
+ Tag
+ Description
+ Example
+
+
+
+
+ confidence
+
+ Indicates a less reliable pattern that may cause false
+ positives. The aim is to achieve a combined confidence of 100%.
+ Defaults to 100% if not specified.
+
+
+ "js": { "Mage": "\\;confidence:50" }
+
+
+
+ version
+
+ Gets the version number from a pattern match using a special
+ syntax.
+
+
+ "scripts": "jquery-([0-9.]+)\.js\\;version:\\1"
+
+
+
+
+
+### Version syntax
+
+Application version information can be obtained from a pattern using a capture group. A condition can be evaluated using the ternary operator (`?:`).
+
+
+
+
+
+ Example
+ Description
+
+
+
+
+ \\1
+ Returns the first match.
+
+
+ \\1?a:
+
+ Returns a if the first match contains a value, nothing
+ otherwise.
+
+
+
+ \\1?a:b
+
+ Returns a if the first match contains a value, b otherwise.
+
+
+
+ \\1?:b
+
+ Returns nothing if the first match contains a value, b
+ otherwise.
+
+
+
+ foo\\1
+
+ Returns foo with the first match appended.
+
+
+
+
diff --git a/bin/validate.js b/bin/validate.js
index 2b9274734..7c9c9b238 100755
--- a/bin/validate.js
+++ b/bin/validate.js
@@ -6,171 +6,167 @@ const { technologies, categories } = JSON.parse(
fs.readFileSync('./src/technologies.json')
)
-try {
- Object.keys(technologies).forEach((name) => {
- const technology = technologies[name]
-
- // Validate regular expressions
- ;['url', 'html', 'meta', 'headers', 'cookies', 'script', 'js'].forEach(
- (type) => {
- if (technology[type]) {
- const keyed =
- typeof technology[type] === 'string' ||
- Array.isArray(technology[type])
- ? { _: technology[type] }
- : technology[type]
-
- Object.keys(keyed).forEach((key) => {
- const patterns = Array.isArray(keyed[key])
- ? keyed[key]
- : [keyed[key]]
-
- patterns.forEach((pattern, index) => {
- const id = `${name}: ${type}[${key === '_' ? `${index}` : key}]`
-
- const [regex, ...flags] = pattern.split('\\;')
-
- let maxGroups = 0
-
- flags.forEach((flag) => {
- const [key, value] = flag.split(':')
-
- if (key === 'version') {
- const refs = value.match(/\\(\d+)/g)
-
- if (refs) {
- maxGroups = refs.reduce((max, ref) =>
- Math.max(max, parseInt(refs[1] || 0))
- )
- }
- } else if (key === 'confidence') {
- if (
- !/^\d+$/.test(value) ||
- parseInt(value, 10) < 0 ||
- parseInt(value, 10) > 99
- ) {
- throw new Error(
- `Confidence value must a number between 0 and 99: ${value} (${id})`
- )
- }
- } else {
- throw new Error(`Invalid flag: ${key} (${id})`)
- }
- })
-
- // Validate regular expression
- try {
- // eslint-disable-next-line no-new
- new RegExp(regex)
- } catch (error) {
- throw new Error(`${error.message} (${id})`)
- }
-
- // Count capture groups
- const groups = new RegExp(`${regex}|`).exec('').length - 1
+Object.keys(technologies).forEach((name) => {
+ const technology = technologies[name]
- if (groups > maxGroups) {
- throw new Error(
- `Too many non-capturing groups, expected ${maxGroups}: ${regex} (${id})`
- )
- }
+ // Validate regular expressions
+ ;['url', 'html', 'meta', 'headers', 'cookies', 'script', 'js'].forEach(
+ (type) => {
+ if (technology[type]) {
+ const keyed =
+ typeof technology[type] === 'string' ||
+ Array.isArray(technology[type])
+ ? { _: technology[type] }
+ : technology[type]
- if (type === 'html' && !/[<>]/.test(regex)) {
- throw new Error(
- `HTML pattern must include < or >: ${regex} (${id})`
- )
- }
- })
- })
- }
- }
- )
+ Object.keys(keyed).forEach((key) => {
+ const patterns = Array.isArray(keyed[key]) ? keyed[key] : [keyed[key]]
- // Validate categories
- technology.cats.forEach((id) => {
- if (!categories[id]) {
- throw new Error(`No such category: ${id} (${name})`)
- }
- })
+ patterns.forEach((pattern, index) => {
+ const id = `${name}: ${type}[${key === '_' ? `${index}` : key}]`
- // Validate icons
- if (technology.icon && !fs.existsSync(`${iconPath}/${technology.icon}`)) {
- throw new Error(`No such icon: ${technology.icon} (${name})`)
- }
+ const [regex, ...flags] = pattern.split('\\;')
- // Validate website URLs
- try {
- // eslint-disable-next-line no-new
- const { protocol } = new URL(technology.website)
+ let maxGroups = 0
- if (protocol !== 'http:' && protocol !== 'https:') {
- throw new Error('Invalid protocol')
- }
- } catch (error) {
- throw new Error(`Invalid website URL: ${technology.website} (${name})`)
- }
+ flags.forEach((flag) => {
+ const [key, value] = flag.split(':')
- // Validate implies and excludes
- const { implies, excludes } = technology
+ if (key === 'version') {
+ const refs = value.match(/\\(\d+)/g)
- if (implies) {
- ;(Array.isArray(implies) ? implies : [implies]).forEach((implied) => {
- const [_name, ...flags] = implied.split('\\;')
+ if (refs) {
+ maxGroups = refs.reduce((max, ref) =>
+ Math.max(max, parseInt(refs[1] || 0))
+ )
+ }
+ } else if (key === 'confidence') {
+ if (
+ !/^\d+$/.test(value) ||
+ parseInt(value, 10) < 0 ||
+ parseInt(value, 10) > 99
+ ) {
+ throw new Error(
+ `Confidence value must a number between 0 and 99: ${value} (${id})`
+ )
+ }
+ } else {
+ throw new Error(`Invalid flag: ${key} (${id})`)
+ }
+ })
- const id = `${name}: implies[${implied}]`
+ // Validate regular expression
+ try {
+ // eslint-disable-next-line no-new
+ new RegExp(regex)
+ } catch (error) {
+ throw new Error(`${error.message} (${id})`)
+ }
- if (!technologies[_name]) {
- throw new Error(`Implied technology does not exist: ${_name} (${id})`)
- }
+ // Count capture groups
+ const groups = new RegExp(`${regex}|`).exec('').length - 1
- flags.forEach((flag) => {
- const [key, value] = flag.split(':')
+ if (groups > maxGroups) {
+ throw new Error(
+ `Too many non-capturing groups, expected ${maxGroups}: ${regex} (${id})`
+ )
+ }
- if (key === 'confidence') {
- if (
- !/^\d+$/.test(value) ||
- parseInt(value, 10) < 0 ||
- parseInt(value, 10) > 99
- ) {
+ if (type === 'html' && !/[<>]/.test(regex)) {
throw new Error(
- `Confidence value must a number between 0 and 99: ${value} (${id})`
+ `HTML pattern must include < or >: ${regex} (${id})`
)
}
- } else {
- throw new Error(`Invalid flag: ${key} (${id})`)
- }
+ })
})
- })
+ }
}
+ )
- if (excludes) {
- ;(Array.isArray(excludes) ? excludes : [excludes]).forEach((excluded) => {
- const id = `${name}: excludes[${excluded}]`
-
- if (!technologies[excluded]) {
- throw new Error(
- `Excluded technology does not exist: ${excluded} (${id})`
- )
- }
- })
+ // Validate categories
+ technology.cats.forEach((id) => {
+ if (!categories[id]) {
+ throw new Error(`No such category: ${id} (${name})`)
}
})
// Validate icons
- fs.readdirSync(iconPath).forEach((file) => {
- const filePath = `${iconPath}/${file}`
+ if (technology.icon && !fs.existsSync(`${iconPath}/${technology.icon}`)) {
+ throw new Error(`No such icon: ${technology.icon} (${name})`)
+ }
+
+ // Validate website URLs
+ try {
+ // eslint-disable-next-line no-new
+ const { protocol } = new URL(technology.website)
+
+ if (protocol !== 'http:' && protocol !== 'https:') {
+ throw new Error('Invalid protocol')
+ }
+ } catch (error) {
+ throw new Error(`Invalid website URL: ${technology.website} (${name})`)
+ }
+
+ // Validate implies and excludes
+ const { implies, excludes } = technology
+
+ if (implies) {
+ ;(Array.isArray(implies) ? implies : [implies]).forEach((implied) => {
+ const [_name, ...flags] = implied.split('\\;')
+
+ const id = `${name}: implies[${implied}]`
- if (fs.statSync(filePath).isFile() && !file.startsWith('.')) {
- if (!/^(png|svg)$/i.test(file.split('.').pop())) {
- throw new Error(`Incorrect file type, expected PNG or SVG: ${filePath}`)
+ if (!technologies[_name]) {
+ throw new Error(`Implied technology does not exist: ${_name} (${id})`)
}
- if (!Object.values(technologies).some(({ icon }) => icon === file)) {
- throw new Error(`Extraneous file: ${filePath}}`)
+ flags.forEach((flag) => {
+ const [key, value] = flag.split(':')
+
+ if (key === 'confidence') {
+ if (
+ !/^\d+$/.test(value) ||
+ parseInt(value, 10) < 0 ||
+ parseInt(value, 10) > 99
+ ) {
+ throw new Error(
+ `Confidence value must a number between 0 and 99: ${value} (${id})`
+ )
+ }
+ } else {
+ throw new Error(`Invalid flag: ${key} (${id})`)
+ }
+ })
+ })
+ }
+
+ if (excludes) {
+ ;(Array.isArray(excludes) ? excludes : [excludes]).forEach((excluded) => {
+ const id = `${name}: excludes[${excluded}]`
+
+ if (!technologies[excluded]) {
+ throw new Error(
+ `Excluded technology does not exist: ${excluded} (${id})`
+ )
}
+ })
+ }
+})
+
+// Validate icons
+fs.readdirSync(iconPath).forEach((file) => {
+ const filePath = `${iconPath}/${file}`
+
+ if (fs.statSync(filePath).isFile() && !file.startsWith('.')) {
+ if (!/^(png|svg)$/i.test(file.split('.').pop())) {
+ throw new Error(`Incorrect file type, expected PNG or SVG: ${filePath}`)
}
- })
-} catch (error) {
- // eslint-disable-next-line no-console
- console.error(error.message)
-}
+
+ if (
+ !Object.values(technologies).some(({ icon }) => icon === file) &&
+ file !== 'default.svg'
+ ) {
+ throw new Error(`Extraneous file: ${filePath}}`)
+ }
+ }
+})
diff --git a/package.json b/package.json
index c24bd1c32..6e6ff2e39 100644
--- a/package.json
+++ b/package.json
@@ -8,15 +8,17 @@
"@nuxtjs/eslint-config": "^3.1.0",
"@nuxtjs/eslint-module": "^2.0.0",
"babel-eslint": "^10.1.0",
- "eslint": "^7.7.0",
- "eslint-config-prettier": "^6.11.0",
+ "eslint": "^7.13.0",
+ "eslint-config-prettier": "^6.15.0",
+ "eslint-plugin-json": "^2.1.2",
"eslint-plugin-nuxt": "^1.0.0",
"eslint-plugin-prettier": "^3.1.4",
- "prettier": "^2.1.0"
+ "prettier": "^2.1.2"
},
"scripts": {
"link": "node ./bin/link.js",
- "lint": "eslint --fix src/**/*.js",
+ "lint": "eslint src/**/*.{js,json}",
+ "lint:fix": "eslint --fix src/**/*.{js,json}",
"validate": "yarn run lint && jsonlint -qV ./schema.json ./src/technologies.json && node ./bin/validate.js",
"convert": "cd ./src/drivers/webextension/images/icons ; cp *.svg converted ; cd converted ; convert-svg-to-png *.svg --width 32 --height 32 ; rm *.svg",
"prettify": "jsonlint -si --trim-trailing-commas --enforce-double-quotes ./src/technologies.json",
diff --git a/schema.json b/schema.json
index 21ad68335..82f938070 100644
--- a/schema.json
+++ b/schema.json
@@ -41,6 +41,19 @@
"type": "string",
"pattern": "^.{0,500}$"
},
+ "oss": {
+ "type": "boolean"
+ },
+ "saas": {
+ "type": "boolean"
+ },
+ "pricing": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "pattern": "^(low|mid|high|freemium|poa|payg|onetime|recurring)$"
+ }
+ },
"cats": {
"type": "array",
"items": {
@@ -73,6 +86,22 @@
}
}
},
+ "dom": {
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ }
+ }
+ },
+ "dns": {
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^.+$": {
+ }
+ }
+ },
"headers": {
"type": "object",
"additionalProperties": false,
diff --git a/src/drivers/npm/README.md b/src/drivers/npm/README.md
index 9bba60c30..7c1d950e6 100644
--- a/src/drivers/npm/README.md
+++ b/src/drivers/npm/README.md
@@ -66,9 +66,9 @@ const options = {
htmlMaxRows: 2000,
};
-;(async function() {
- const wappalyzer = await new Wappalyzer(options)
+const wappalyzer = new Wappalyzer(options)
+;(async function() {
try {
await wappalyzer.init()
@@ -98,9 +98,9 @@ const Wappalyzer = require('wappalyzer');
const urls = ['https://www.wappalyzer.com', 'https://www.example.com']
-;(async function() {
- const wappalyzer = await new Wappalyzer()
+const wappalyzer = new Wappalyzer()
+;(async function() {
try {
await wappalyzer.init()
diff --git a/src/drivers/npm/cli.js b/src/drivers/npm/cli.js
index 1cab50af9..9e2644bdb 100755
--- a/src/drivers/npm/cli.js
+++ b/src/drivers/npm/cli.js
@@ -77,7 +77,7 @@ Options:
}
;(async function () {
- const wappalyzer = await new Wappalyzer(options)
+ const wappalyzer = new Wappalyzer(options)
try {
await wappalyzer.init()
diff --git a/src/drivers/npm/driver.js b/src/drivers/npm/driver.js
index 8e9a62156..52f40d865 100644
--- a/src/drivers/npm/driver.js
+++ b/src/drivers/npm/driver.js
@@ -1,5 +1,6 @@
const { URL } = require('url')
const fs = require('fs')
+const dns = require('dns').promises
const path = require('path')
const http = require('http')
const https = require('https')
@@ -67,12 +68,41 @@ function analyzeJs(js) {
)
}
+function analyzeDom(dom) {
+ return Array.prototype.concat.apply(
+ [],
+ dom.map(({ name, selector, text, property, attribute, value }) => {
+ const technology = Wappalyzer.technologies.find(
+ ({ name: _name }) => name === _name
+ )
+
+ if (text) {
+ return analyzeManyToMany(technology, 'dom.text', { [selector]: [text] })
+ }
+
+ if (property) {
+ return analyzeManyToMany(technology, `dom.properties.${property}`, {
+ [selector]: [value],
+ })
+ }
+
+ if (attribute) {
+ return analyzeManyToMany(technology, `dom.attributes.${attribute}`, {
+ [selector]: [value],
+ })
+ }
+
+ return []
+ })
+ )
+}
+
function get(url) {
if (['http:', 'https:'].includes(url.protocol)) {
const { get } = url.protocol === 'http:' ? http : https
return new Promise((resolve, reject) =>
- get(url.href, (response) => {
+ get(url, { rejectUnauthorized: false }, (response) => {
if (response.statusCode >= 400) {
return reject(
new Error(`${response.statusCode} ${response.statusMessage}`)
@@ -86,7 +116,7 @@ function get(url) {
response.on('data', (data) => (body += data))
response.on('error', (error) => reject(new Error(error.message)))
response.on('end', () => resolve(body))
- })
+ }).on('error', (error) => reject(new Error(error.message)))
)
} else {
throw new Error(`Invalid protocol: ${url.protocol}`)
@@ -127,6 +157,8 @@ class Driver {
try {
this.browser = await puppeteer.launch({
+ ignoreHTTPSErrors: true,
+ acceptInsecureCerts: true,
args: chromiumArgs,
executablePath: await chromiumBin,
})
@@ -135,10 +167,15 @@ class Driver {
this.log('Browser disconnected')
if (!this.destroyed) {
- await this.init()
+ try {
+ await this.init()
+ } catch (error) {
+ this.log(error.toString())
+ }
}
})
} catch (error) {
+ console.log('a', error)
throw new Error(error.toString())
}
}
@@ -154,6 +191,7 @@ class Driver {
this.log('Browser closed')
} catch (error) {
+ console.log('b', error)
throw new Error(error.toString())
}
}
@@ -173,7 +211,11 @@ class Driver {
class Site {
constructor(url, headers = {}, driver) {
- ;({ options: this.options, browser: this.browser } = driver)
+ ;({
+ options: this.options,
+ browser: this.browser,
+ init: this.initDriver,
+ } = driver)
this.options.headers = {
...this.options.headers,
@@ -185,6 +227,7 @@ class Site {
try {
this.originalUrl = new URL(url)
} catch (error) {
+ console.log('c', error)
throw new Error(error.toString())
}
@@ -194,6 +237,8 @@ class Site {
this.listeners = {}
this.pages = []
+
+ this.dns = []
}
log(message, source = 'driver', type = 'log') {
@@ -263,7 +308,11 @@ class Site {
}
if (!this.browser) {
- throw new Error('Browser closed')
+ await this.initDriver()
+
+ if (!this.browser) {
+ throw new Error('Browser closed')
+ }
}
const page = await this.browser.newPage()
@@ -299,6 +348,7 @@ class Site {
request.continue({ headers })
}
} catch (error) {
+ console.log('d', error)
this.error(error)
}
})
@@ -337,10 +387,11 @@ class Site {
this.onDetect(analyze({ headers, certIssuer }))
- await this.emit('response', { page, response })
+ await this.emit('response', { page, response, headers, certIssuer })
}
}
} catch (error) {
+ console.log('e', error)
this.error(error)
}
})
@@ -357,6 +408,8 @@ class Site {
await sleep(1000)
+ // page.on('console', (message) => this.log(message.text()))
+
// Links
const links = await this.promiseTimeout(
(
@@ -480,11 +533,88 @@ class Site {
)
)
+ // DOM
+ const dom = await this.promiseTimeout(
+ page.evaluate(
+ (technologies) => {
+ return technologies.reduce((technologies, { name, dom }) => {
+ const toScalar = (value) =>
+ typeof value === 'string' || typeof value === 'number'
+ ? value
+ : !!value
+
+ Object.keys(dom).forEach((selector) => {
+ const nodes = document.querySelectorAll(selector)
+
+ if (!nodes.length) {
+ return
+ }
+
+ dom[selector].forEach(({ text, properties, attributes }) => {
+ nodes.forEach((node) => {
+ if (text) {
+ const value = node.textContent.trim()
+
+ if (value) {
+ technologies.push({
+ name,
+ selector,
+ text: value,
+ })
+ }
+ }
+
+ if (properties) {
+ Object.keys(properties).forEach((property) => {
+ if (
+ Object.prototype.hasOwnProperty.call(node, property)
+ ) {
+ const value = node[property]
+
+ if (typeof value !== 'undefined') {
+ technologies.push({
+ name,
+ selector,
+ property,
+ value: toScalar(value),
+ })
+ }
+ }
+ })
+ }
+
+ if (attributes) {
+ Object.keys(attributes).forEach((attribute) => {
+ if (node.hasAttribute(attribute)) {
+ const value = node.getAttribute(attribute)
+
+ technologies.push({
+ name,
+ selector,
+ attribute,
+ value: toScalar(value),
+ })
+ }
+ })
+ }
+ })
+ })
+ })
+
+ return technologies
+ }, [])
+ },
+ Wappalyzer.technologies
+ .filter(({ dom }) => dom)
+ .map(({ name, dom }) => ({ name, dom }))
+ )
+ )
+
// Cookies
const cookies = (await page.cookies()).reduce(
(cookies, { name, value }) => ({
...cookies,
- [name]: [value],
+ [name.toLowerCase()]: [value],
}),
{}
)
@@ -513,8 +643,63 @@ class Site {
html = batches.join('\n')
}
+ // DNS
+ if (!Object.keys(this.dns).length) {
+ const records = {}
+ const resolve = (func, hostname) => {
+ return this.promiseTimeout(
+ func(hostname).catch((error) => {
+ if (error.code !== 'ENODATA') {
+ this.error(error)
+ }
+
+ return []
+ })
+ )
+ }
+
+ const domain = url.hostname.replace(/^www\./, '')
+
+ ;[
+ records.cname,
+ records.ns,
+ records.mx,
+ records.txt,
+ records.soa,
+ ] = await Promise.all([
+ resolve(dns.resolveCname, url.hostname),
+ resolve(dns.resolveNs, domain),
+ resolve(dns.resolveMx, domain),
+ resolve(dns.resolveTxt, domain),
+ resolve(dns.resolveSoa, domain),
+ ])
+
+ this.dns = Object.keys(records).reduce((dns, type) => {
+ dns[type] = dns[type] || []
+
+ Array.prototype.push.apply(
+ dns[type],
+ Array.isArray(records[type])
+ ? records[type].map((value) => {
+ return typeof value === 'object'
+ ? Object.values(value).join(' ')
+ : value
+ })
+ : [Object.values(records[type]).join(' ')]
+ )
+
+ return dns
+ }, {})
+
+ this.onDetect(analyze({ dns: this.dns }))
+ }
+
// Validate response
- if (url.protocol !== 'file:' && !this.analyzedUrls[url.href].status) {
+ if (
+ url.protocol !== 'file:' &&
+ this.analyzedUrls[url.href] &&
+ !this.analyzedUrls[url.href].status
+ ) {
await page.close()
this.log('Page closed')
@@ -522,8 +707,8 @@ class Site {
throw new Error('No response from server')
}
+ this.onDetect(analyzeDom(dom))
this.onDetect(analyzeJs(js))
-
this.onDetect(
analyze({
url,
@@ -546,9 +731,8 @@ class Site {
) &&
link.protocol &&
link.protocol.match(/https?:/) &&
- link.rel !== 'nofollow' &&
link.hostname === url.hostname &&
- extensions.test(link.pathname)
+ extensions.test(link.pathname.slice(-5))
) {
results.push(new URL(link.href.split('#')[0]))
}
@@ -567,6 +751,7 @@ class Site {
meta,
js,
links: reducedLinks,
+ dns: this.dns,
})
await page.close()
@@ -575,10 +760,15 @@ class Site {
return reducedLinks
} catch (error) {
+ console.log('f', error)
if (error.constructor.name === 'TimeoutError') {
throw new Error('The website took too long to respond')
}
+ if (error.message.includes('net::ERR_NAME_NOT_RESOLVED')) {
+ throw new Error('Hostname could not be resolved')
+ }
+
throw new Error(error.message)
}
}
@@ -599,6 +789,7 @@ class Site {
await this.batch(links.slice(0, this.options.maxUrls), depth + 1)
}
} catch (error) {
+ console.log('g', error)
this.analyzedUrls[url.href] = {
status: 0,
error: error.message || error.toString(),
diff --git a/src/drivers/npm/package.json b/src/drivers/npm/package.json
index f156672ac..b80ce1a4b 100644
--- a/src/drivers/npm/package.json
+++ b/src/drivers/npm/package.json
@@ -13,7 +13,7 @@
"software"
],
"homepage": "https://www.wappalyzer.com/",
- "version": "6.3.6",
+ "version": "6.5.22",
"author": "Wappalyzer",
"license": "MIT",
"repository": {
@@ -25,7 +25,7 @@
"url": "https://github.com/sponsors/aliasio"
},
{
- "url": "https://paypal.me/aliasio"
+ "url": "https://paypal.me/elbertalias"
}
],
"main": "driver.js",
@@ -42,4 +42,4 @@
"dependencies": {
"puppeteer": "^5.3.0"
}
-}
+}
\ No newline at end of file
diff --git a/src/drivers/webextension/_locales/ca/messages.json b/src/drivers/webextension/_locales/ca/messages.json
index c5053ff24..6c155e8a4 100644
--- a/src/drivers/webextension/_locales/ca/messages.json
+++ b/src/drivers/webextension/_locales/ca/messages.json
@@ -1,24 +1,26 @@
{
- "github": { "message": "Fork Wappalyzer a GitHub!" },
+ "github": { "message": "Bifurcar Wappalyzer a GitHub" },
"twitter": { "message": "Seguir Wappalyzer a Twitter" },
"website": { "message": "Anar a wappalyzer.com" },
"options": { "message": "Opcions" },
"optionsSave": { "message": "Desar opcions" },
"optionsSaved": { "message": "Desat" },
- "optionUpgradeMessage": { "message": "Avisar-me quan hi hagi una actualització disponible" },
+ "optionUpgradeMessage": { "message": "Notificar les actualitzacions disponibles" },
"optionDynamicIcon": { "message": "Utilitzar la icona de la tecnologia enlloc del logotip de Wappalyzer" },
"optionTracking": { "message": "Enviar les tecnologies identificades de forma anònima a wappalyzer.com" },
- "optionThemeMode": { "message": "Habilitar la compatibilitat de la manera fosc." },
- "optionBadge": { "message": "Show the number of identified technologies on the icon" },
- "disableOnDomain": { "message": "Disable on this website" },
- "clearCache": { "message": "Clear cached detections" },
+ "optionThemeMode": { "message": "Habilitar la compatibilitat de l'aspecte fosc" },
+ "optionBadge": { "message": "Mostrar el nombre de tecnologies identificades en la icona" },
+ "disableOnDomain": { "message": "Desactivar en aquest web" },
+ "clearCache": { "message": "Esborrar la memòria cau de les deteccions" },
"nothingToDo": { "message": "Res a fer aquí." },
"noAppsDetected": { "message": "No s'ha detectat cap tecnologia." },
"categoryPin": { "message": "Mostrar sempre la icona" },
- "termsAccept": { "message": "Acceptar" },
+ "termsAccept": { "message": "M'està bé" },
+ "termsDecline": { "message": "Desactivar" },
"termsContent": { "message": "Aquesta extensió envia informació anònima sobre els llocs web que visiteu, inclosos el nom de domini i les tecnologies identificades a wappalyzer.com . Això pot desactivar-se a Opcions." },
"privacyPolicy": { "message": "Política de privadesa" },
- "createAlert": { "message": "Create an alert for this website" },
+ "createAlert": { "message": "Crear una alerta per aquest web" },
+ "leadLists": { "message": "Lead generation tools" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Taulers de missatgeria" },
"categoryName3": { "message": "Gestor de bases de dades" },
@@ -35,7 +37,7 @@
"categoryName14": { "message": "Reproductors de vídeo" },
"categoryName15": { "message": "Sistemes de comentaris" },
"categoryName16": { "message": "Security" },
- "categoryName17": { "message": "Font Script" },
+ "categoryName17": { "message": "Tipografies" },
"categoryName18": { "message": "Marcs web" },
"categoryName19": { "message": "Miscel·lània" },
"categoryName20": { "message": "Editors" },
@@ -50,7 +52,7 @@
"categoryName29": { "message": "Motors de cerca" },
"categoryName30": { "message": "Correu web" },
"categoryName31": { "message": "CDN" },
- "categoryName32": { "message": "Marketing Automation" },
+ "categoryName32": { "message": "Automatitzacions de màrqueting" },
"categoryName33": { "message": "Extensions del servidor web" },
"categoryName34": { "message": "Bases de dades" },
"categoryName35": { "message": "Mapes" },
@@ -64,7 +66,7 @@
"categoryName43": { "message": "Paywall" },
"categoryName44": { "message": "Sistemes Build/CI" },
"categoryName45": { "message": "Sistemes SCADA" },
- "categoryName46": { "message": "Accés remot" },
+ "categoryName46": { "message": "Accessos remots" },
"categoryName47": { "message": "Eines de desenvolupament" },
"categoryName48": { "message": "Emmagatzematge de xarxa" },
"categoryName49": { "message": "Lectors de canals" },
@@ -76,7 +78,7 @@
"categoryName55": { "message": "Comptabilitat" },
"categoryName56": { "message": "Cryptominer" },
"categoryName57": { "message": "Generadors de llocs estàtics" },
- "categoryName58": { "message": "User Onboarding" },
+ "categoryName58": { "message": "Incorporacions d'usuaris" },
"categoryName59": { "message": "Llibreries JavaScript" },
"categoryName60": { "message": "Contenidors" },
"categoryName61": { "message": "SaaS" },
@@ -84,9 +86,14 @@
"categoryName63": { "message": "IaaS" },
"categoryName64": { "message": "Proxys invers" },
"categoryName65": { "message": "Balanceigs de càrrega" },
- "categoryName66": { "message": "UI Frameworks" },
+ "categoryName66": { "message": "Marcs UI" },
"categoryName67": { "message": "Cookie compliance" },
- "categoryName68": { "message": "Accessibility"},
- "categoryName69": { "message": "Social login"},
- "categoryName70": { "message": "SSL/TLS certificate authority"}
+ "categoryName68": { "message": "Accesibilitat" },
+ "categoryName69": { "message": "Inicis de sessió socials" },
+ "categoryName70": { "message": "Autoritats de certificació SSL/TLS" },
+ "categoryName71": { "message": "Programes d'afiliació" },
+ "categoryName72": { "message": "Programacions de cites" },
+ "categoryName73": { "message": "Enquestes" },
+ "categoryName74": { "message": "Testeigs A/B" },
+ "categoryName75": { "message": "Correus electrònics" }
}
diff --git a/src/drivers/webextension/_locales/de/messages.json b/src/drivers/webextension/_locales/de/messages.json
index 631d7010d..1ebb87c26 100644
--- a/src/drivers/webextension/_locales/de/messages.json
+++ b/src/drivers/webextension/_locales/de/messages.json
@@ -1,92 +1,99 @@
{
- "github": { "message": "Forke Wappalyzer bei GitHub!" },
- "twitter": { "message": "Folge Wappalyzer bei Twitter" },
- "website": { "message": "Gehe zu wappalyzer.com" },
- "options": { "message": "Optionen" },
- "optionsSave": { "message": "Optionen speichern" },
- "optionsSaved": { "message": "Gespeichert" },
- "optionUpgradeMessage": { "message": "Benachrichtige mich bei Upgrades" },
- "optionDynamicIcon": { "message": "Applikations Icon anstatt des Wappalyzer Icons verwenden" },
- "optionTracking": { "message": "Anonyme Statistiken an wappalyzer.com übermitteln" },
- "optionThemeMode": { "message": "Aktivieren dunklen Modus Kompatibilität." },
- "optionBadge": { "message": "Show the number of identified technologies on the icon" },
- "disableOnDomain": { "message": "Disable on this website" },
- "clearCache": { "message": "Clear cached detections" },
- "nothingToDo": { "message": "Nichts zu tun." },
- "noAppsDetected": { "message": "Keine Applikation entdeckt." },
- "categoryPin": { "message": "Immer Icon anzeigen" },
- "termsAccept": { "message": "Accept" },
- "termsContent": { "message": "This extension sends anonymous information about websites you visit, including domain name and identified technologies, to wappalyzer.com . This can be disabled in the settings." },
- "privacyPolicy": { "message": "Privacy policy" },
- "createAlert": { "message": "Create an alert for this website" },
- "categoryName1": { "message": "CMS" },
- "categoryName2": { "message": "Nachrichten Board" },
- "categoryName3": { "message": "Datenbankverwaltung" },
- "categoryName4": { "message": "Dokumentations Tool" },
- "categoryName5": { "message": "Widget" },
- "categoryName6": { "message": "Ecommerce" },
- "categoryName7": { "message": "Fotogalerien" },
- "categoryName8": { "message": "Wikis" },
- "categoryName9": { "message": "Hosting-Panels" },
- "categoryName10": { "message": "Statistiken" },
- "categoryName11": { "message": "Blog" },
- "categoryName12": { "message": "JavaScript Framework" },
- "categoryName13": { "message": "Fehlertracker" },
- "categoryName14": { "message": "Videospieler" },
- "categoryName15": { "message": "Kommentarsystem" },
- "categoryName16": { "message": "Security" },
- "categoryName17": { "message": "Schrift Script" },
- "categoryName18": { "message": "Web Framework" },
- "categoryName19": { "message": "Sonstiges" },
- "categoryName20": { "message": "Editor" },
- "categoryName21": { "message": "LMS" },
- "categoryName22": { "message": "Web Server" },
- "categoryName23": { "message": "Cache Tool" },
- "categoryName24": { "message": "Rich Text Editor" },
- "categoryName25": { "message": "JavaScript Graphics" },
- "categoryName26": { "message": "Mobile Framework" },
- "categoryName27": { "message": "Programmiersprache" },
- "categoryName28": { "message": "Betriebssystem" },
- "categoryName29": { "message": "Suchmaschine" },
- "categoryName30": { "message": "Webmail" },
- "categoryName31": { "message": "CDN" },
- "categoryName32": { "message": "Marketing Automation" },
- "categoryName33": { "message": "Web Server Erweiterung" },
- "categoryName34": { "message": "Datenbank" },
- "categoryName35": { "message": "Map" },
- "categoryName36": { "message": "Werbenetzwerk" },
- "categoryName37": { "message": "Netzwerkdienst" },
- "categoryName38": { "message": "Medienserver" },
- "categoryName39": { "message": "Webcam" },
- "categoryName40": { "message": "Drucker" },
- "categoryName41": { "message": "Zahlungsverarbeiter" },
- "categoryName42": { "message": "Schlagwort Manager" },
- "categoryName43": { "message": "Bezahlblockade" },
- "categoryName44": { "message": "Build/CI-System" },
- "categoryName45": { "message": "SCADA System" },
- "categoryName46": { "message": "Fernzugriff" },
- "categoryName47": { "message": "Entwicklungswerkzeug" },
- "categoryName48": { "message": "Netzwerkspeicher" },
- "categoryName49": { "message": "Feedleser" },
- "categoryName50": { "message": "Dokumentmanagementsysteme" },
- "categoryName51": { "message": "Startseitenersteller" },
- "categoryName52": { "message": "Live-Chat" },
- "categoryName53": { "message": "CRM" },
+ "github": { "message": "Forke Wappalyzer bei GitHub!" },
+ "twitter": { "message": "Folge Wappalyzer bei Twitter" },
+ "website": { "message": "Gehe zu wappalyzer.com" },
+ "options": { "message": "Optionen" },
+ "optionsSave": { "message": "Optionen speichern" },
+ "optionsSaved": { "message": "Gespeichert" },
+ "optionUpgradeMessage": { "message": "Benachrichtige mich bei Upgrades" },
+ "optionDynamicIcon": { "message": "Applikations Icon anstatt des Wappalyzer Icons verwenden" },
+ "optionTracking": { "message": "Anonyme Statistiken an wappalyzer.com übermitteln" },
+ "optionThemeMode": { "message": "Dunkel-Modus aktivieren" },
+ "optionBadge": { "message": "Anzahl der identifizierten Optionen am Icon anzeigen" },
+ "disableOnDomain": { "message": "Auf dieser Website deaktivieren" },
+ "clearCache": { "message": "Cache leeren" },
+ "nothingToDo": { "message": "Nichts zu tun." },
+ "noAppsDetected": { "message": "Keine Applikationen gefunden" },
+ "categoryPin": { "message": "Icon immer anzeigen" },
+ "termsAccept": { "message": "I'm ok with that" },
+ "termsDecline": { "message": "Disable" },
+ "termsContent": { "message": "Diese Erweiterung sendet anonyme Informationen über Websites, die Sie besuchen, einschließlich der Domain und der identifizierten Technologien, an wappalyzer.com . Dies kann in den Einstellungen deaktiviert werden." },
+ "privacyPolicy": { "message": "Datenschutzerklärung" },
+ "createAlert": { "message": "Alarm für diese Website erstellen" },
+ "leadLists": { "message": "Lead generation tools" },
+ "categoryName1": { "message": "CMS" },
+ "categoryName2": { "message": "Nachrichten Board" },
+ "categoryName3": { "message": "Datenbankverwaltung" },
+ "categoryName4": { "message": "Dokumentations Tool" },
+ "categoryName5": { "message": "Widget" },
+ "categoryName6": { "message": "E-Commerce" },
+ "categoryName7": { "message": "Fotogalerien" },
+ "categoryName8": { "message": "Wikis" },
+ "categoryName9": { "message": "Hosting-Panels" },
+ "categoryName10": { "message": "Statistiken" },
+ "categoryName11": { "message": "Blog" },
+ "categoryName12": { "message": "JavaScript Frameworks" },
+ "categoryName13": { "message": "Ticketsysteme" },
+ "categoryName14": { "message": "Videoplayer" },
+ "categoryName15": { "message": "Kommentarsystem" },
+ "categoryName16": { "message": "Security" },
+ "categoryName17": { "message": "Schrift Script" },
+ "categoryName18": { "message": "Web Frameworks" },
+ "categoryName19": { "message": "Sonstiges" },
+ "categoryName20": { "message": "Editor" },
+ "categoryName21": { "message": "LMS" },
+ "categoryName22": { "message": "Web Server" },
+ "categoryName23": { "message": "Cache Tool" },
+ "categoryName24": { "message": "Rich Text Editor" },
+ "categoryName25": { "message": "JavaScript Graphics" },
+ "categoryName26": { "message": "Mobile Framework" },
+ "categoryName27": { "message": "Programmiersprache" },
+ "categoryName28": { "message": "Betriebssysteme" },
+ "categoryName29": { "message": "Suchmaschinen" },
+ "categoryName30": { "message": "Webmail" },
+ "categoryName31": { "message": "CDN" },
+ "categoryName32": { "message": "Marketing Automation" },
+ "categoryName33": { "message": "Web Server Erweiterungen" },
+ "categoryName34": { "message": "Datenbanken" },
+ "categoryName35": { "message": "Karten" },
+ "categoryName36": { "message": "Werbenetzwerke" },
+ "categoryName37": { "message": "Netzwerkdienste" },
+ "categoryName38": { "message": "Medienserver" },
+ "categoryName39": { "message": "Web-Kameras" },
+ "categoryName40": { "message": "Drucker" },
+ "categoryName41": { "message": "Zahlungsverarbeiter" },
+ "categoryName42": { "message": "Tag Manager" },
+ "categoryName43": { "message": "Bezahlblockade" },
+ "categoryName44": { "message": "CI-Systeme" },
+ "categoryName45": { "message": "SCADA System" },
+ "categoryName46": { "message": "Fernzugriff" },
+ "categoryName47": { "message": "Entwicklungswerkzeuge" },
+ "categoryName48": { "message": "Netzwerkspeicher" },
+ "categoryName49": { "message": "Feedleser" },
+ "categoryName50": { "message": "Dokumentmanagementsysteme" },
+ "categoryName51": { "message": "Website Baukästen" },
+ "categoryName52": { "message": "Live-Chat" },
+ "categoryName53": { "message": "CRM" },
"categoryName54": { "message": "SEO" },
- "categoryName55": { "message": "Buchhaltung" },
- "categoryName56": { "message": "Cryptominer" },
- "categoryName57": { "message": "Statischer Seitengenerator" },
- "categoryName58": { "message": "Benutzer-Einbindung" },
- "categoryName59": { "message": "JavaScript Bibliotheken" },
- "categoryName60": { "message": "Containers" },
- "categoryName61": { "message": "SaaS" },
- "categoryName62": { "message": "PaaS" },
- "categoryName63": { "message": "IaaS" },
- "categoryName64": { "message": "Reverse Proxy" },
- "categoryName65": { "message": "Load Balancer" },
- "categoryName66": { "message": "UI Frameworks" },
- "categoryName67": { "message": "Cookie compliance" },
- "categoryName68": { "message": "Accessibility"},
- "categoryName69": { "message": "Social login"},
- "categoryName70": { "message": "SSL/TLS certificate authority"}
+ "categoryName55": { "message": "Buchhaltung" },
+ "categoryName56": { "message": "Cryptominer" },
+ "categoryName57": { "message": "Statischer Seitengenerator" },
+ "categoryName58": { "message": "Benutzer-Onboarding" },
+ "categoryName59": { "message": "JavaScript Bibliotheken" },
+ "categoryName60": { "message": "Container" },
+ "categoryName61": { "message": "SaaS" },
+ "categoryName62": { "message": "PaaS" },
+ "categoryName63": { "message": "IaaS" },
+ "categoryName64": { "message": "Reverse Proxies" },
+ "categoryName65": { "message": "Load Balancer" },
+ "categoryName66": { "message": "UI Frameworks" },
+ "categoryName67": { "message": "Cookie compliance" },
+ "categoryName68": { "message": "Barrierefreiheit" },
+ "categoryName69": { "message": "Social Login" },
+ "categoryName70": { "message": "SSL/TLS certificate authority" },
+ "categoryName71": { "message": "Partnerprogram" },
+ "categoryName72": { "message": "Appointment scheduling" },
+ "categoryName73": { "message": "Surveys" },
+ "categoryName74": { "message": "A/B testing" },
+ "categoryName75": { "message": "Email" }
}
diff --git a/src/drivers/webextension/_locales/el/messages.json b/src/drivers/webextension/_locales/el/messages.json
index d96216826..da4d31f66 100644
--- a/src/drivers/webextension/_locales/el/messages.json
+++ b/src/drivers/webextension/_locales/el/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "Καμία ενέργεια." },
"noAppsDetected": { "message": "Δεν ανιχνεύθηκαν εφαρμογές." },
"categoryPin": { "message": "Always show icon" },
- "termsAccept": { "message": "Accept" },
+ "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 wappalyzer.com . 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": "Διαδικτυακό Φόρουμ" },
"categoryName3": { "message": "Διαχειριστής Βάσης Δεδομένων" },
@@ -83,6 +85,11 @@
"categoryName66": { "message": "UI Frameworks" },
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "Accessibility" },
- "categoryName69": { "message": "Social login" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "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" }
}
diff --git a/src/drivers/webextension/_locales/en/messages.json b/src/drivers/webextension/_locales/en/messages.json
index 453b284bb..f4430eef6 100644
--- a/src/drivers/webextension/_locales/en/messages.json
+++ b/src/drivers/webextension/_locales/en/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "Nothing to do here." },
"noAppsDetected": { "message": "No technologies detected." },
"categoryPin": { "message": "Always show icon" },
- "termsAccept": { "message": "Accept" },
+ "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 wappalyzer.com . 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" },
@@ -85,6 +87,11 @@
"categoryName66": { "message": "UI frameworks" },
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "Accessibility" },
- "categoryName69": { "message": "Social login" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "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" }
}
diff --git a/src/drivers/webextension/_locales/es/messages.json b/src/drivers/webextension/_locales/es/messages.json
index b073fb5aa..8862e3e0c 100644
--- a/src/drivers/webextension/_locales/es/messages.json
+++ b/src/drivers/webextension/_locales/es/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "Nada que hacer aquí." },
"noAppsDetected": { "message": "Aplicaciones no detectadas." },
"categoryPin": { "message": "Always show icon" },
- "termsAccept": { "message": "Accept" },
+ "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 wappalyzer.com . 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": "Gestor de Contenido" },
"categoryName2": { "message": "Foro" },
"categoryName3": { "message": "Gestor de Bases de Datos" },
@@ -55,7 +57,7 @@
"categoryName34": { "message": "Base de Datos" },
"categoryName35": { "message": "Mapa" },
"categoryName36": { "message": "Red de Publicidad" },
- "categoryName37": { "message": "Network Sevice" },
+ "categoryName37": { "message": "Network Service" },
"categoryName38": { "message": "Media Server" },
"categoryName39": { "message": "Webcam" },
"categoryName40": { "message": "Printer" },
@@ -87,6 +89,11 @@
"categoryName66": { "message": "UI Frameworks" },
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "Accessibility" },
- "categoryName69": { "message": "Social login" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "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" }
}
diff --git a/src/drivers/webextension/_locales/fa/messages.json b/src/drivers/webextension/_locales/fa/messages.json
index a1e65d234..b4db06e3b 100644
--- a/src/drivers/webextension/_locales/fa/messages.json
+++ b/src/drivers/webextension/_locales/fa/messages.json
@@ -15,10 +15,12 @@
"clearCache": { "message": "پاکسازی شناسایی های کش شده" },
"noAppsDetected": { "message": "هیچ فنآوری شناسایی نشده است." },
"categoryPin": { "message": "همیشه نماد را نشان بده" },
- "termsAccept": { "message": "قبول" },
+ "termsAccept": { "message": "I'm ok with that" },
+ "termsDecline": { "message": "Disable" },
"termsContent": { "message": "این افزونه اطلاعات وبسایتهای بازدید شده توسط شما را به صورت ناشناس ارسال میکند، مانند آدرس سایت و تکنولوژیهای استفاده شده در آن سایت را ارسال میکند. اطلاعات بیشتر در wappalyzer.com . شما میتوانید این افزونه را غیرفعال کنید." },
"privacyPolicy": { "message": "سیاست حفظ حریم خصوصی" },
"createAlert": { "message": "ساخت یک هشدار برای این وبسایت" },
+ "leadLists": { "message": "Lead generation tools" },
"categoryName1": { "message": "سیستم مدیریت محتوا" },
"categoryName2": { "message": "انجمن پیام" },
"categoryName3": { "message": "مدیریت پایگاه داده" },
@@ -88,5 +90,10 @@
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "دسترسی" },
"categoryName69": { "message": "ورود به شبکه های اجتماعی" },
- "categoryName70": { "message": "صادر کننده SSL/TLS" }
+ "categoryName70": { "message": "صادر کننده SSL/TLS" },
+ "categoryName71": { "message": "Affiliate programs" },
+ "categoryName72": { "message": "Appointment scheduling" },
+ "categoryName73": { "message": "Surveys" },
+ "categoryName74": { "message": "A/B testing" },
+ "categoryName75": { "message": "Email" }
}
diff --git a/src/drivers/webextension/_locales/fr/messages.json b/src/drivers/webextension/_locales/fr/messages.json
index 9f58d9b7f..a2ec5644f 100644
--- a/src/drivers/webextension/_locales/fr/messages.json
+++ b/src/drivers/webextension/_locales/fr/messages.json
@@ -15,10 +15,12 @@
"twitter": { "message": "Suivre Wappalyzer sur Twitter" },
"website": { "message": "Aller sur wappalyzer.com" },
"categoryPin": { "message": " Toujours afficher l'icône" },
- "termsAccept": { "message": "Accept" },
+ "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 wappalyzer.com . 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": "Forum" },
"categoryName3": { "message": "Gestionnaire de base de données" },
@@ -87,6 +89,11 @@
"categoryName66": { "message": "UI Frameworks" },
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "Accessibility" },
- "categoryName69": { "message": "Social login" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "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" }
}
diff --git a/src/drivers/webextension/_locales/gl_ES/messages.json b/src/drivers/webextension/_locales/gl_ES/messages.json
index fb8fa26fd..fd48da1b0 100644
--- a/src/drivers/webextension/_locales/gl_ES/messages.json
+++ b/src/drivers/webextension/_locales/gl_ES/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "Nada que facer por aquí." },
"noAppsDetected": { "message": "Non se identificaron aplicativos." },
"categoryPin": { "message": "Amosar sempre icono" },
- "termsAccept": { "message": "Aceptar" },
+ "termsAccept": { "message": "I'm ok with that" },
+ "termsDecline": { "message": "Disable" },
"termsContent": { "message": "Esta extensión envía anonimamente información acerca das webs que visitas, incluindo dominio e aplicativos identificados, a wappalyzer.com . Isto pode ser desactivado nas preferencias." },
"privacyPolicy": { "message": "Política de privacidade" },
"createAlert": { "message": "Create an alert for this website" },
+ "leadLists": { "message": "Lead generation tools" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Taboleiro de mensaxes" },
"categoryName3": { "message": "Xestor de base de datos" },
@@ -87,6 +89,11 @@
"categoryName66": { "message": "UI Frameworks" },
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "Accessibility" },
- "categoryName69": { "message": "Social login" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "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" }
}
diff --git a/src/drivers/webextension/_locales/gr/messages.json b/src/drivers/webextension/_locales/gr/messages.json
index fcd10ad82..e46f38736 100644
--- a/src/drivers/webextension/_locales/gr/messages.json
+++ b/src/drivers/webextension/_locales/gr/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "Καμία ενέργεια." },
"noAppsDetected": { "message": "Δεν ανιχνεύθηκαν εφαρμογές." },
"categoryPin": { "message": "Always show icon" },
- "termsAccept": { "message": "Accept" },
+ "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 wappalyzer.com . 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": "Διαδικτυακό Φόρουμ" },
"categoryName3": { "message": "Διαχειριστής Βάσης Δεδομένων" },
@@ -83,6 +85,11 @@
"categoryName66": { "message": "UI Frameworks" },
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "Accessibility" },
- "categoryName69": { "message": "Social login" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "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" }
}
diff --git a/src/drivers/webextension/_locales/id/messages.json b/src/drivers/webextension/_locales/id/messages.json
index a0d1b2897..bee46f188 100644
--- a/src/drivers/webextension/_locales/id/messages.json
+++ b/src/drivers/webextension/_locales/id/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "Tak ada yang dilakukan disini." },
"noAppsDetected": { "message": "Tidak ada aplikasi yang terdeteksi." },
"categoryPin": { "message": "Always show icon" },
- "termsAccept": { "message": "Accept" },
+ "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 wappalyzer.com . 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": "Sistem Pengelola Konten" },
"categoryName2": { "message": "Papan Pesan" },
"categoryName3": { "message": "Pengelola Basis Data" },
@@ -87,6 +89,11 @@
"categoryName66": { "message": "UI Frameworks" },
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "Accessibility" },
- "categoryName69": { "message": "Social login" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "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" }
}
diff --git a/src/drivers/webextension/_locales/it/messages.json b/src/drivers/webextension/_locales/it/messages.json
index a80798521..2a066531b 100644
--- a/src/drivers/webextension/_locales/it/messages.json
+++ b/src/drivers/webextension/_locales/it/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "Niente da fare qui." },
"noAppsDetected": { "message": "Nessuna applicazione rilevata." },
"categoryPin": { "message": "Always show icon" },
- "termsAccept": { "message": "Accept" },
+ "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 wappalyzer.com . 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": "Forum" },
"categoryName3": { "message": "Gestore di Database" },
@@ -88,5 +90,10 @@
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "Accessibility" },
"categoryName69": { "message": "Social login" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "categoryName70": { "message": "SSL/TLS certificate authority" },
+ "categoryName71": { "message": "Affiliate program" },
+ "categoryName72": { "message": "Appointment scheduling" },
+ "categoryName73": { "message": "Surveys" },
+ "categoryName74": { "message": "A/B testing" },
+ "categoryName75": { "message": "Email" }
}
diff --git a/src/drivers/webextension/_locales/ja/messages.json b/src/drivers/webextension/_locales/ja/messages.json
index 656901314..c74f77a5e 100644
--- a/src/drivers/webextension/_locales/ja/messages.json
+++ b/src/drivers/webextension/_locales/ja/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "ここでは特定出来ません。" },
"noAppsDetected": { "message": "技術は検出されませんでした。" },
"categoryPin": { "message": "常にアイコンを表示" },
- "termsAccept": { "message": "受諾する" },
+ "termsAccept": { "message": "I'm ok with that" },
+ "termsDecline": { "message": "Disable" },
"termsContent": { "message": "この拡張機能は、ドメイン名や特定された技術など、アクセスしたWebサイトに関する匿名情報をwappalyzer.com に送信します。これは設定で無効にできます。" },
"privacyPolicy": { "message": "プライバシーポリシー" },
"createAlert": { "message": "Create an alert for this website" },
+ "leadLists": { "message": "Lead generation tools" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "メッセージボード" },
"categoryName3": { "message": "データベースマネージャー" },
@@ -88,5 +90,10 @@
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "Accessibility" },
"categoryName69": { "message": "Social login" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "categoryName70": { "message": "SSL/TLS certificate authority" },
+ "categoryName71": { "message": "Affiliate program" },
+ "categoryName72": { "message": "Appointment scheduling" },
+ "categoryName73": { "message": "Surveys" },
+ "categoryName74": { "message": "A/B testing" },
+ "categoryName75": { "message": "Email" }
}
diff --git a/src/drivers/webextension/_locales/ko/messages.json b/src/drivers/webextension/_locales/ko/messages.json
index 86a217896..d981343b6 100644
--- a/src/drivers/webextension/_locales/ko/messages.json
+++ b/src/drivers/webextension/_locales/ko/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "여기에는 할 일이 없네요." },
"noAppsDetected": { "message": "식별된 기술이 없습니다." },
"categoryPin": { "message": "항상 아이콘 보이기" },
- "termsAccept": { "message": "수락" },
+ "termsAccept": { "message": "I'm ok with that" },
+ "termsDecline": { "message": "Disable" },
"termsContent": { "message": "이 확장 기능은 사이트의 도메인과 식별된 기술을 포함한 익명 정보를 wappalyzer.com 에 전송합니다. 이 기능은 설정에서 비활성화 할 수 있습니다." },
"privacyPolicy": { "message": "개인정보처리방침" },
"createAlert": { "message": "이 웹 사이트에 대한 알림 받기" },
+ "leadLists": { "message": "Lead generation tools" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "포럼 소프트웨어" },
"categoryName3": { "message": "데이터베이스 관리 도구" },
@@ -86,5 +88,10 @@
"categoryName67": { "message": "쿠키 동의" },
"categoryName68": { "message": "접근성" },
"categoryName69": { "message": "소셜 로그인" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "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" }
}
diff --git a/src/drivers/webextension/_locales/pl/messages.json b/src/drivers/webextension/_locales/pl/messages.json
index d000e321f..98c81a5c7 100644
--- a/src/drivers/webextension/_locales/pl/messages.json
+++ b/src/drivers/webextension/_locales/pl/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "Nic tu nie ma." },
"noAppsDetected": { "message": "Nie wykryto żadnych aplikacji." },
"categoryPin": { "message": "Zawsze pokazuj tą ikonę" },
- "termsAccept": { "message": "Akceptuj" },
+ "termsAccept": { "message": "I'm ok with that" },
+ "termsDecline": { "message": "Disable" },
"termsContent": { "message": "To rozszerzenie wysyła anonimowe informacje o stronach, które odwiedzasz, uwzględniając nazwy domen i zidentyfikowane technologie do wappalyzer.com . Opcja może zostać wyłączona w ustawieniach." },
"privacyPolicy": { "message": "Privacy policy" },
"createAlert": { "message": "Create an alert for this website" },
+ "leadLists": { "message": "Lead generation tools" },
"categoryName1": { "message": "System zarządzania treścią" },
"categoryName2": { "message": "Forum" },
"categoryName3": { "message": "Menedżer baz danych" },
@@ -87,6 +89,11 @@
"categoryName66": { "message": "UI Frameworks" },
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "Accessibility" },
- "categoryName69": { "message": "Social login" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "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" }
}
diff --git a/src/drivers/webextension/_locales/pt/messages.json b/src/drivers/webextension/_locales/pt/messages.json
index c4c41277d..38569e6ea 100644
--- a/src/drivers/webextension/_locales/pt/messages.json
+++ b/src/drivers/webextension/_locales/pt/messages.json
@@ -15,10 +15,12 @@
"twitter": { "message": "Seguir Wappalyzer no Twitter" },
"website": { "message": "Ir para wappalyzer.com" },
"categoryPin": { "message": "Mostrar sempre ícone" },
- "termsAccept": { "message": "Aceitar" },
+ "termsAccept": { "message": "I'm ok with that" },
+ "termsDecline": { "message": "Disable" },
"termsContent": { "message": "Esta extensão envia informações anónimas sobre os sites que visitas, incluindo o nome de domínio e as tecnologias identificadas, para o wappalyzer.com . Isso pode ser desativado nas configurações." },
"privacyPolicy": { "message": "Políticas de Privacidade" },
"createAlert": { "message": "Create an alert for this website" },
+ "leadLists": { "message": "Lead generation tools" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Fórum" },
"categoryName3": { "message": "Gestor de Base de Dados" },
@@ -87,6 +89,11 @@
"categoryName66": { "message": "UI Frameworks" },
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "Accessibility" },
- "categoryName69": { "message": "Social login" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "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" }
}
diff --git a/src/drivers/webextension/_locales/pt_BR/messages.json b/src/drivers/webextension/_locales/pt_BR/messages.json
index 36f90a93f..5d36f4b55 100644
--- a/src/drivers/webextension/_locales/pt_BR/messages.json
+++ b/src/drivers/webextension/_locales/pt_BR/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "Nada a fazer aqui." },
"noAppsDetected": { "message": "Nenhuma tecnologia identificada." },
"categoryPin": { "message": "Sempre mostrar ícone" },
- "termsAccept": { "message": "Aceitar" },
+ "termsAccept": { "message": "I'm ok with that" },
+ "termsDecline": { "message": "Disable" },
"termsContent": { "message": "Esta extensão envia informações anônimas sobre os sites que você visita, incluindo domínio e tecnologias identificadas para wappalyzer.com . Este comportamento pode ser desativado nas configurações." },
"privacyPolicy": { "message": "Privacy policy" },
"createAlert": { "message": "Create an alert for this website" },
+ "leadLists": { "message": "Lead generation tools" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Fórum" },
"categoryName3": { "message": "Gestão de Banco de Dados" },
@@ -87,6 +89,11 @@
"categoryName66": { "message": "UI Frameworks" },
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "Accessibility" },
- "categoryName69": { "message": "Social login" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "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" }
}
diff --git a/src/drivers/webextension/_locales/ro/messages.json b/src/drivers/webextension/_locales/ro/messages.json
index fb621d40c..7bea53eee 100644
--- a/src/drivers/webextension/_locales/ro/messages.json
+++ b/src/drivers/webextension/_locales/ro/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "Nimic de făcut pe pagina curentă." },
"noAppsDetected": { "message": "Nici o aplicație detectată." },
"categoryPin": { "message": "Afișează icon tot timpul" },
- "termsAccept": { "message": "Accept" },
+ "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 wappalyzer.com . 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": "Forum de discuții" },
"categoryName3": { "message": "Manager baze de date" },
@@ -83,6 +85,11 @@
"categoryName66": { "message": "UI Frameworks" },
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "Accessibility" },
- "categoryName69": { "message": "Social login" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "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" }
}
diff --git a/src/drivers/webextension/_locales/ru/messages.json b/src/drivers/webextension/_locales/ru/messages.json
index e1fd536ee..a1561c268 100644
--- a/src/drivers/webextension/_locales/ru/messages.json
+++ b/src/drivers/webextension/_locales/ru/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "Здесь нечего делать" },
"noAppsDetected": { "message": "Не удалось определить ни одну технологию" },
"categoryPin": { "message": "Всегда отображать эту категорию иконкой"},
- "termsAccept": { "message": "Принять" },
+ "termsAccept": { "message": "I'm ok with that" },
+ "termsDecline": { "message": "Disable" },
"termsContent": { "message": "Расширение отправляет обезличенную статистику посещенных сайтов, включая доменное имя и распознанные технологии на wappalyzer.com . Это можно отключить в настройках." },
"privacyPolicy": { "message": "Политика конфиденциальности" },
"createAlert": { "message": "Отправить жалобу на этот сайт" },
+ "leadLists": { "message": "Lead generation tools" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Форум" },
"categoryName3": { "message": "Менеджер БД" },
@@ -85,6 +87,11 @@
"categoryName66": { "message": "UI Фреймворк" },
"categoryName67": { "message": "Соответствие cookie" },
"categoryName68": { "message": "Доступность" },
- "categoryName69": { "message": "Social login" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "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" }
}
diff --git a/src/drivers/webextension/_locales/sk/messages.json b/src/drivers/webextension/_locales/sk/messages.json
index f5095fa72..d65f4b933 100644
--- a/src/drivers/webextension/_locales/sk/messages.json
+++ b/src/drivers/webextension/_locales/sk/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "Nie je tu čo robiť." },
"noAppsDetected": { "message": "Žiadne aplikácie neboli zistené." },
"categoryPin": { "message": "Always show icon" },
- "termsAccept": { "message": "Accept" },
+ "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 wappalyzer.com . 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 Board" },
"categoryName3": { "message": "Správca databáz" },
@@ -87,6 +89,11 @@
"categoryName66": { "message": "UI Frameworks" },
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "Accessibility" },
- "categoryName69": { "message": "Social login" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "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" }
}
diff --git a/src/drivers/webextension/_locales/tr/messages.json b/src/drivers/webextension/_locales/tr/messages.json
index 832a58bc3..a69f197f9 100644
--- a/src/drivers/webextension/_locales/tr/messages.json
+++ b/src/drivers/webextension/_locales/tr/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "Burada yapacak birşey yok." },
"noAppsDetected": { "message": "Uygulamalar tespit edilemedi." },
"categoryPin": { "message": "Her zaman bu kategorinin ikonunu kullan" },
- "termsAccept": { "message": "Kabul Ediyorum" },
+ "termsAccept": { "message": "I'm ok with that" },
+ "termsDecline": { "message": "Disable" },
"termsContent": { "message": "Bu eklenti, ziyaret ettiğiniz web site bilgilerini, alan adları ve tespit edilen teknolojiler ile beraber anonim olarak wappalyzer.com 'a gönderir. Bunu, eklenti ayarlarından değiştirebilirsiniz." },
"privacyPolicy": { "message": "Privacy policy" },
"createAlert": { "message": "Create an alert for this website" },
+ "leadLists": { "message": "Lead generation tools" },
"categoryName1": { "message": "İçerik Yönetim Sistemi" },
"categoryName2": { "message": "Mesaj Tahtası" },
"categoryName3": { "message": "Veritabanı Yöneticisi" },
@@ -87,6 +89,11 @@
"categoryName66": { "message": "UI Frameworks" },
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "Accessibility" },
- "categoryName69": { "message": "Social login" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "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" }
}
diff --git a/src/drivers/webextension/_locales/uk/messages.json b/src/drivers/webextension/_locales/uk/messages.json
index a6f7d5daa..29dc12412 100644
--- a/src/drivers/webextension/_locales/uk/messages.json
+++ b/src/drivers/webextension/_locales/uk/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "Тут нічого робити." },
"noAppsDetected": { "message": "Нічого не знайдено." },
"categoryPin": { "message": "Завжди показувати іконку Wappalyzer" },
- "termsAccept": { "message": "Доступ" },
+ "termsAccept": { "message": "I'm ok with that" },
+ "termsDecline": { "message": "Disable" },
"termsContent": { "message": "Це розширення надсилає на Wapplayzer.com анонімну інформацію про відвідувані вами веб-сайти, включаючи доменні імена та визначені технології. Це можна відключити в налаштуваннях." },
"privacyPolicy": { "message": "Політика приватності" },
"createAlert": { "message": "Поскаржитись на цей сайт" },
+ "leadLists": { "message": "Lead generation tools" },
"categoryName1": { "message": "CMS" },
"categoryName2": { "message": "Форум" },
"categoryName3": { "message": "Менеджер БД" },
@@ -87,6 +89,11 @@
"categoryName66": { "message": "UI Каркаси" },
"categoryName67": { "message": "Відповідність файлам cookie" },
"categoryName68": { "message": "Доступність" },
- "categoryName69": { "message": "Social login" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "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" }
}
diff --git a/src/drivers/webextension/_locales/uz/messages.json b/src/drivers/webextension/_locales/uz/messages.json
index af62b2567..7f1989fa2 100644
--- a/src/drivers/webextension/_locales/uz/messages.json
+++ b/src/drivers/webextension/_locales/uz/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "Bu yerda tekshirib bolmaydi." },
"noAppsDetected": { "message": "Hech qanday dastur aniqlanmadi." },
"categoryPin": { "message": "Always show icon" },
- "termsAccept": { "message": "Accept" },
+ "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 wappalyzer.com . 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 (KBT)" },
"categoryName2": { "message": "Forum" },
"categoryName3": { "message": "MB boshqaruvi" },
@@ -86,7 +88,12 @@
"categoryName65": { "message": "Load Balancer" },
"categoryName66": { "message": "UI Frameworks" },
"categoryName67": { "message": "Cookie compliance" },
- "categoryName68": { "message": "Accessibility"},
- "categoryName69": { "message": "Social login"},
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "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" }
}
diff --git a/src/drivers/webextension/_locales/zh_CN/messages.json b/src/drivers/webextension/_locales/zh_CN/messages.json
index 8a37b95ca..280d0bdf3 100644
--- a/src/drivers/webextension/_locales/zh_CN/messages.json
+++ b/src/drivers/webextension/_locales/zh_CN/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "这里无事可做。" },
"noAppsDetected": { "message": "未检测到任何技术。" },
"categoryPin": { "message": "总是显示图标" },
- "termsAccept": { "message": "接受" },
+ "termsAccept": { "message": "I'm ok with that" },
+ "termsDecline": { "message": "Disable" },
"termsContent": { "message": "此扩展程序会匿名发送您访问的网站信息至 wappalyzer.com ,包含域名和检测到的技术。这可以在设置中禁用。" },
"privacyPolicy": { "message": "隐私政策" },
"createAlert": { "message": "为该网站创建提醒" },
+ "leadLists": { "message": "Lead generation tools" },
"categoryName1": { "message": "内容管理系统(CMS)" },
"categoryName2": { "message": "信息板" },
"categoryName3": { "message": "数据库管理器" },
@@ -84,7 +86,10 @@
"categoryName65": { "message": "负载均衡" },
"categoryName66": { "message": "用户界面(UI)框架" },
"categoryName67": { "message": "Cookie 合规" },
- "categoryName68": { "message": "辅助功能"},
- "categoryName69": { "message": "社交登录"},
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "categoryName68": { "message": "辅助功能" },
+ "categoryName69": { "message": "社交登录" },
+ "categoryName70": { "message": "SSL/TLS certificate authority" },
+ "categoryName71": { "message": "Affiliate program" },
+ "categoryName74": { "message": "A/B testing" },
+ "categoryName75": { "message": "Email" }
}
diff --git a/src/drivers/webextension/_locales/zh_TW/messages.json b/src/drivers/webextension/_locales/zh_TW/messages.json
index 575a241f0..3a1950994 100644
--- a/src/drivers/webextension/_locales/zh_TW/messages.json
+++ b/src/drivers/webextension/_locales/zh_TW/messages.json
@@ -15,10 +15,12 @@
"nothingToDo": { "message": "這裡什麼也沒有。" },
"noAppsDetected": { "message": "未識別到技術。" },
"categoryPin": { "message": "永遠顯示圖示" },
- "termsAccept": { "message": "接受" },
+ "termsAccept": { "message": "I'm ok with that" },
+ "termsDecline": { "message": "Disable" },
"termsContent": { "message": "這個擴充功能將你所造訪網站的網域名稱和識別到的技術等資訊,匿名傳送至 wappalyzer.com 。你可以在選項中停用。" },
"privacyPolicy": { "message": "Privacy policy" },
"createAlert": { "message": "Create an alert for this website" },
+ "leadLists": { "message": "Lead generation tools" },
"categoryName1": { "message": "內容管理系統(CMS)" },
"categoryName2": { "message": "留言板/討論區" },
"categoryName3": { "message": "資料庫管理" },
@@ -88,5 +90,10 @@
"categoryName67": { "message": "Cookie compliance" },
"categoryName68": { "message": "Accessibility" },
"categoryName69": { "message": "Social login" },
- "categoryName70": { "message": "SSL/TLS certificate authority" }
+ "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" }
}
diff --git a/src/drivers/webextension/css/styles.css b/src/drivers/webextension/css/styles.css
index 45bd52ab3..74bd77181 100644
--- a/src/drivers/webextension/css/styles.css
+++ b/src/drivers/webextension/css/styles.css
@@ -44,6 +44,7 @@ a:hover {
border-bottom: 1px solid var(--color-secondary);
display: flex;
height: 4.5rem;
+ justify-content: space-between;
}
.header__logo {
@@ -67,19 +68,26 @@ a:hover {
width: 100%;
}
-.alerts {
+.footer__cta {
+ text-align: right;
+ margin-right: 1.5rem;
white-space: nowrap;
}
-.alerts--hidden {
- visibility: hidden;
+.footer__cta a {
+ border-bottom: 1px solid var(--color-secondary);
+ text-decoration: none;
+}
+
+.footer__cta a:hover {
+ border-bottom: 1px solid var(--color-primary);
}
-.alerts__icon {
+.footer__open-in-new {
color: var(--color-primary);
height: 1.1rem;
- margin-right: .5rem;
- vertical-align: text-bottom;
+ margin-left: .1rem;
+ vertical-align: middle;
width: 1.1rem;
}
@@ -195,6 +203,21 @@ a:hover {
.technology__link {
color: var(--color-text);
+ display: block;
+ width: 100%;
+}
+
+.technology__link .technology__name {
+ border-bottom: 1px solid var(--color-secondary);
+}
+
+.technology__link:hover {
+ text-decoration: none;
+}
+
+.technology__link:hover .technology__name {
+ border-bottom: 1px solid var(--color-primary);
+ color: var(--color-primary);
}
.technology__confidence {
@@ -208,7 +231,7 @@ a:hover {
border-radius: 3px;
font-size: .7rem;
padding: .1rem .3rem;
- margin-left: .4rem;
+ margin-left: .2rem;
vertical-align: middle;
}
@@ -218,7 +241,7 @@ a:hover {
flex-direction: column;
justify-content: center;
padding: 1.5rem 1.5rem 1rem 1.5rem;
- height: 12rem;
+ height: 14rem;
width: 36rem;
}
@@ -244,18 +267,25 @@ a:hover {
width: 80%;
}
-.terms__accept {
+.terms__buttons {
+}
+
+.terms__button {
background-color: #4608ad;
border: none;
border-radius: 3px;
color: white;
cursor: pointer;
font-size: .9rem;
- padding: .8rem 3rem;
+ padding: 0 2rem;
+ margin: 0 .2rem;
+ height: 3rem;
}
-.terms__accept:hover {
- background-color: #4107a1;
+.terms__button--decline {
+ background-color: white;
+ border: 1px solid #4608ad;
+ color: #4608ad;
}
.terms__privacy {
@@ -305,6 +335,11 @@ a:hover {
color: #fff
}
+ .theme-mode .technology__link:hover .technology__name {
+ border-bottom: 1px solid var(--color-text-dark);
+ color: var(--color-text-dark);
+ }
+
.theme-mode .technology__confidence {
}
@@ -321,7 +356,15 @@ a:hover {
color: var(--color-text-dark);
}
- .theme-mode .alerts__icon {
- color:var(--color-text-dark);
+ .theme-mode .footer__icon {
+ color: #fff;
+ }
+
+ .theme-mode .footer__open-in-new {
+ color: #fff;
+ }
+
+ .theme-mode .technology__open-in-new {
+ color: #fff;
}
}
diff --git a/src/drivers/webextension/html/options.html b/src/drivers/webextension/html/options.html
index 3dfc531d4..b07b09cab 100644
--- a/src/drivers/webextension/html/options.html
+++ b/src/drivers/webextension/html/options.html
@@ -43,7 +43,7 @@
-
+