├── .gitignore
├── LICENSE
├── README.md
├── images
├── amcharts.png
├── amp.png
├── angular.png
├── angularjs.png
├── anime.png
├── aurelia.png
├── backbone.png
├── bootstrap.png
├── chartjs.png
├── clojurescript.png
├── cyclejs.png
├── d3.png
├── dio.png
├── dojo.png
├── echarts.png
├── elm.png
├── ember.png
├── emotion.png
├── enyo.png
├── epoch.png
├── extjs.png
├── foundation.png
├── gatsby.png
├── glamorous.png
├── handlebars.png
├── highcharts.png
├── icon.png
├── icon128.png
├── icon16.png
├── icon48.png
├── immutable.png
├── inferno.png
├── jquery.png
├── jqueryui.png
├── kendoui.png
├── knockback.png
├── knockout.png
├── lodash.png
├── maquette.png
├── marionette.png
├── marko.png
├── materialize.png
├── meteor.png
├── mithril.png
├── mobx.png
├── modernizr.png
├── moment.png
├── moon.png
├── mootools.png
├── nextjs.png
├── p5.png
├── phaser.png
├── pixijs.png
├── polymer.png
├── preact.png
├── purescript.png
├── ractive.png
├── radium.png
├── raphael.png
├── react.png
├── reason.png
├── requirejs.png
├── riot.png
├── scalajs.png
├── semanticui.png
├── socketio.png
├── styledcomponents.png
├── svelte.png
├── ui5.png
├── uikit.png
├── vue.png
├── webix.png
├── webpack.png
├── whsjs.png
├── yalla.png
└── yui.png
├── manifest.json
├── package.json
├── src
├── checker.ts
├── checks
│ ├── doesAnyElement.ts
│ ├── errorHiding.ts
│ ├── index.ts
│ ├── isObjectWithProperties.ts
│ └── types.ts
├── content.ts
├── popup.html
└── popup.ts
├── tsconfig.json
├── webpack.config.js
├── webpack.config.production.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Stanislav Iliev
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | :mag: A Chrome extension that lets you inspect a website's framework and libraries
6 |
7 |
8 |
9 |
10 |
11 |
12 | # How to install?
13 |
14 | [](https://chrome.google.com/webstore/detail/ui-stack/ijagbooglignnjecmjnmdfapfbgblkdk)
15 |
16 | You can install the extension from the [Chrome Web Store](https://chrome.google.com/webstore/detail/ui-stack/ijagbooglignnjecmjnmdfapfbgblkdk)
17 |
18 | You can also install it locally by cloning this repo and following the [official tutorial](https://developer.chrome.com/extensions/getstarted#unpacked)
19 |
20 | # Contribution
21 |
22 | 1. Clone this repository
23 | 2. Run `yarn install` to fetch dependencies and `yarn build` to start the build script
24 | 3. Open the `src/checks/index.ts` file and add your own checker function
25 | 4. Open `src/checker.ts` and add your function to the list
26 | 5. Make sure your code works
27 | 6. Make a pull request :rocket:
28 |
29 | # Support
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/images/amcharts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/amcharts.png
--------------------------------------------------------------------------------
/images/amp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/amp.png
--------------------------------------------------------------------------------
/images/angular.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/angular.png
--------------------------------------------------------------------------------
/images/angularjs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/angularjs.png
--------------------------------------------------------------------------------
/images/anime.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/anime.png
--------------------------------------------------------------------------------
/images/aurelia.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/aurelia.png
--------------------------------------------------------------------------------
/images/backbone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/backbone.png
--------------------------------------------------------------------------------
/images/bootstrap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/bootstrap.png
--------------------------------------------------------------------------------
/images/chartjs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/chartjs.png
--------------------------------------------------------------------------------
/images/clojurescript.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/clojurescript.png
--------------------------------------------------------------------------------
/images/cyclejs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/cyclejs.png
--------------------------------------------------------------------------------
/images/d3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/d3.png
--------------------------------------------------------------------------------
/images/dio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/dio.png
--------------------------------------------------------------------------------
/images/dojo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/dojo.png
--------------------------------------------------------------------------------
/images/echarts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/echarts.png
--------------------------------------------------------------------------------
/images/elm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/elm.png
--------------------------------------------------------------------------------
/images/ember.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/ember.png
--------------------------------------------------------------------------------
/images/emotion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/emotion.png
--------------------------------------------------------------------------------
/images/enyo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/enyo.png
--------------------------------------------------------------------------------
/images/epoch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/epoch.png
--------------------------------------------------------------------------------
/images/extjs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/extjs.png
--------------------------------------------------------------------------------
/images/foundation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/foundation.png
--------------------------------------------------------------------------------
/images/gatsby.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/gatsby.png
--------------------------------------------------------------------------------
/images/glamorous.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/glamorous.png
--------------------------------------------------------------------------------
/images/handlebars.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/handlebars.png
--------------------------------------------------------------------------------
/images/highcharts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/highcharts.png
--------------------------------------------------------------------------------
/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/icon.png
--------------------------------------------------------------------------------
/images/icon128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/icon128.png
--------------------------------------------------------------------------------
/images/icon16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/icon16.png
--------------------------------------------------------------------------------
/images/icon48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/icon48.png
--------------------------------------------------------------------------------
/images/immutable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/immutable.png
--------------------------------------------------------------------------------
/images/inferno.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/inferno.png
--------------------------------------------------------------------------------
/images/jquery.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/jquery.png
--------------------------------------------------------------------------------
/images/jqueryui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/jqueryui.png
--------------------------------------------------------------------------------
/images/kendoui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/kendoui.png
--------------------------------------------------------------------------------
/images/knockback.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/knockback.png
--------------------------------------------------------------------------------
/images/knockout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/knockout.png
--------------------------------------------------------------------------------
/images/lodash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/lodash.png
--------------------------------------------------------------------------------
/images/maquette.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/maquette.png
--------------------------------------------------------------------------------
/images/marionette.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/marionette.png
--------------------------------------------------------------------------------
/images/marko.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/marko.png
--------------------------------------------------------------------------------
/images/materialize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/materialize.png
--------------------------------------------------------------------------------
/images/meteor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/meteor.png
--------------------------------------------------------------------------------
/images/mithril.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/mithril.png
--------------------------------------------------------------------------------
/images/mobx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/mobx.png
--------------------------------------------------------------------------------
/images/modernizr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/modernizr.png
--------------------------------------------------------------------------------
/images/moment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/moment.png
--------------------------------------------------------------------------------
/images/moon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/moon.png
--------------------------------------------------------------------------------
/images/mootools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/mootools.png
--------------------------------------------------------------------------------
/images/nextjs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/nextjs.png
--------------------------------------------------------------------------------
/images/p5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/p5.png
--------------------------------------------------------------------------------
/images/phaser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/phaser.png
--------------------------------------------------------------------------------
/images/pixijs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/pixijs.png
--------------------------------------------------------------------------------
/images/polymer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/polymer.png
--------------------------------------------------------------------------------
/images/preact.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/preact.png
--------------------------------------------------------------------------------
/images/purescript.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/purescript.png
--------------------------------------------------------------------------------
/images/ractive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/ractive.png
--------------------------------------------------------------------------------
/images/radium.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/radium.png
--------------------------------------------------------------------------------
/images/raphael.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/raphael.png
--------------------------------------------------------------------------------
/images/react.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/react.png
--------------------------------------------------------------------------------
/images/reason.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/reason.png
--------------------------------------------------------------------------------
/images/requirejs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/requirejs.png
--------------------------------------------------------------------------------
/images/riot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/riot.png
--------------------------------------------------------------------------------
/images/scalajs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/scalajs.png
--------------------------------------------------------------------------------
/images/semanticui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/semanticui.png
--------------------------------------------------------------------------------
/images/socketio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/socketio.png
--------------------------------------------------------------------------------
/images/styledcomponents.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/styledcomponents.png
--------------------------------------------------------------------------------
/images/svelte.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/svelte.png
--------------------------------------------------------------------------------
/images/ui5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/ui5.png
--------------------------------------------------------------------------------
/images/uikit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/uikit.png
--------------------------------------------------------------------------------
/images/vue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/vue.png
--------------------------------------------------------------------------------
/images/webix.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/webix.png
--------------------------------------------------------------------------------
/images/webpack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/webpack.png
--------------------------------------------------------------------------------
/images/whsjs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/whsjs.png
--------------------------------------------------------------------------------
/images/yalla.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/yalla.png
--------------------------------------------------------------------------------
/images/yui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gigobyte/ui-stack/2b37367941dfc4251a8f54a0739cf5ccc24aaadc/images/yui.png
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 2,
3 | "name": "UI Stack",
4 | "description": "A Chrome extension that lets you see a website's framework and libraries",
5 | "version": "1.3",
6 | "author": "Stanislav Iliev",
7 | "permissions": ["activeTab", "storage", "tabs"],
8 | "browser_action": {
9 | "default_icon": "images/icon.png",
10 | "default_popup": "src/popup.html"
11 | },
12 | "content_scripts": [
13 | {
14 | "matches": [""],
15 | "js": ["build/content.js"]
16 | }
17 | ],
18 | "web_accessible_resources": ["build/checker.js"],
19 | "icons": {
20 | "16": "images/icon16.png",
21 | "48": "images/icon48.png",
22 | "128": "images/icon128.png"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "devDependencies": {
3 | "ts-loader": "^3.1.0",
4 | "typescript": "^2.5.3",
5 | "webpack": "^3.8.1"
6 | },
7 | "name": "ui-stack",
8 | "version": "1.0.0",
9 | "main": "index.js",
10 | "repository": "https://github.com/gigobyte/ui-stack.git",
11 | "author": "gigobyte ",
12 | "license": "MIT",
13 | "scripts": {
14 | "build": "webpack -w",
15 | "build-release": "webpack --config webpack.config.production.js"
16 | },
17 | "dependencies": {
18 | "@types/chrome": "^0.0.50"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/checker.ts:
--------------------------------------------------------------------------------
1 | import * as checks from './checks/index'
2 | import { Library } from './checks/types'
3 |
4 | let appendedLibs = false
5 |
6 | const runCheck = () => {
7 | const body = document.getElementsByTagName('body')[0]
8 |
9 | const libs = [
10 | // languages
11 | checks.elm(),
12 | checks.scalajs(),
13 | checks.reason(),
14 | checks.purescript(),
15 | checks.clojurescript(),
16 |
17 | // frameworks
18 | checks.angular(),
19 | checks.react(),
20 | checks.vue(),
21 | checks.angularjs(),
22 | checks.backbone(),
23 | checks.knockout(),
24 | checks.ember(),
25 | checks.knockback(),
26 | checks.polymer(),
27 | checks.mithril(),
28 | checks.aurelia(),
29 | checks.dojo(),
30 | checks.meteor(),
31 | checks.kendoui(),
32 | checks.nextjs(),
33 | checks.gatsby(),
34 | checks.ui5(),
35 | checks.marko(),
36 | checks.svelte(),
37 | checks.marionette(),
38 | checks.inferno(),
39 | checks.dio(),
40 | checks.extjs(),
41 | checks.yui(),
42 | checks.enyo(),
43 | checks.riot(),
44 | checks.phaser(),
45 | checks.webix(),
46 | checks.preact(),
47 | checks.amp(),
48 | checks.uikit(),
49 | checks.ractive(),
50 | checks.semantic(),
51 | checks.bootstrap(),
52 | checks.foundation(),
53 |
54 | // libraries
55 | checks.jquery(),
56 | checks.moment(),
57 | checks.socketio(),
58 | checks.cyclejs(),
59 | checks.styledComponents(),
60 | checks.emotion(),
61 | checks.glamorous(),
62 | checks.radium(),
63 | checks.modernizr(),
64 | checks.mobx(),
65 | checks.materialize(),
66 | checks.d3(),
67 | checks.whitestormjs(),
68 | checks.mootools(),
69 | checks.p5(),
70 | checks.pixijs(),
71 | checks.immutable(),
72 | checks.jqueryui(),
73 | checks.moon(),
74 | checks.chartjs(),
75 | checks.raphael(),
76 | checks.amcharts(),
77 | checks.echarts(),
78 | checks.lodash(),
79 | checks.highcharts(),
80 | checks.handlebars(),
81 | checks.anime(),
82 | checks.yalla(),
83 | checks.epoch(),
84 | checks.maquette(),
85 |
86 | // tools
87 | checks.require(),
88 | checks.webpack()
89 | ].filter(Boolean) as Library[]
90 |
91 | if (libs.length === 0) {
92 | appendedLibs = true
93 |
94 | const noLibEl = document.createElement('div')
95 | noLibEl.className = 'ui-stack-no-libs'
96 | body.appendChild(noLibEl)
97 | } else {
98 | appendedLibs = true
99 |
100 | libs.forEach(x => {
101 | const libEl = document.createElement('div')
102 | libEl.setAttribute('data-title', x.title)
103 | libEl.setAttribute('data-slug', x.slug)
104 | libEl.setAttribute('data-version', x.version || '')
105 | libEl.setAttribute('data-website', x.website || '')
106 | libEl.className = 'ui-stack-lib'
107 | body.appendChild(libEl)
108 | })
109 | }
110 | }
111 |
112 | runCheck()
113 |
114 | setInterval(() => {
115 | if (appendedLibs) {
116 | const libElementAdded = Boolean(
117 | document.querySelector('.ui-stack-lib, .ui-stack-no-libs')
118 | )
119 |
120 | if (!libElementAdded) {
121 | appendedLibs = false
122 | runCheck()
123 | }
124 | }
125 | }, 1500)
126 |
--------------------------------------------------------------------------------
/src/checks/doesAnyElement.ts:
--------------------------------------------------------------------------------
1 | const doesAnyElement = (
2 | document: Document,
3 | predicate: (el: HTMLElement) => boolean
4 | ): boolean => {
5 | return ([...(document.querySelectorAll('*') as any)] as HTMLElement[]).some(
6 | predicate
7 | )
8 | }
9 |
10 | export default doesAnyElement
11 |
--------------------------------------------------------------------------------
/src/checks/errorHiding.ts:
--------------------------------------------------------------------------------
1 | export const safeCall = (fn?: Function, ...args) => {
2 | try {
3 | if (fn && typeof fn === 'function') {
4 | return fn(...args)
5 | }
6 | } catch {}
7 | }
8 |
9 | export const safeGet = (object: Object, ...path: string[]): any => {
10 | return path.reduce((value, getter) => {
11 | try {
12 | if (!value) {
13 | return value
14 | }
15 |
16 | return value[getter]
17 | } catch {}
18 | }, object)
19 | }
20 |
21 | export const safeGetValues = (object: Object): any => {
22 | try {
23 | return Object.values(object)
24 | } catch {}
25 | }
26 |
27 | export const safeRequire = (window: Window, requiredPackage: string): any => {
28 | try {
29 | return window['require'] && window['require'](requiredPackage)
30 | } catch {}
31 | }
32 |
--------------------------------------------------------------------------------
/src/checks/index.ts:
--------------------------------------------------------------------------------
1 | import { Check } from './types'
2 | import { safeGet, safeCall, safeRequire, safeGetValues } from './errorHiding'
3 | import isObjectWithProperties from './isObjectWithProperties'
4 | import doesAnyElement from './doesAnyElement'
5 |
6 | export const angularjs: Check = () => {
7 | const ANGULARJS_SELECTOR =
8 | '[ng-app],[ng-model],[ng-controller],[ng-scope],.ng-hide'
9 |
10 | if (document.querySelector(ANGULARJS_SELECTOR)) {
11 | return {
12 | title: 'AngularJS',
13 | slug: 'angularjs',
14 | website: 'https://angularjs.org/',
15 | version: safeGet(window, 'angular', 'version', 'full')
16 | }
17 | }
18 | }
19 |
20 | export const jquery: Check = () => {
21 | const jqKey = Object.getOwnPropertyNames(window).find(x =>
22 | safeGet(window, x, 'fn', 'jquery')
23 | )
24 |
25 | if (jqKey) {
26 | return {
27 | title: 'jQuery',
28 | slug: 'jquery',
29 | website: 'https://jquery.com/',
30 | version: safeGet(window, jqKey, 'fn', 'jquery').split(' ')[0]
31 | }
32 | }
33 | }
34 |
35 | export const react: Check = () => {
36 | const REACT_SELECTOR = '[data-reactroot],[data-reactid]'
37 | const importedReact =
38 | window['React'] ||
39 | safeRequire(window, 'React') ||
40 | safeRequire(window, 'react')
41 | const isReactFound = doesAnyElement(document, el =>
42 | Object.keys(el).some(key => key.startsWith('__react'))
43 | )
44 |
45 | if (document.querySelector(REACT_SELECTOR) || importedReact || isReactFound) {
46 | return {
47 | title: 'React',
48 | slug: 'react',
49 | website: 'https://reactjs.org/',
50 | version: safeGet(importedReact, 'version')
51 | }
52 | }
53 | }
54 |
55 | export const angular: Check = () => {
56 | const ANGULAR_SELECTOR = '[_nghost-c0],[_ngcontent-c0],[ng-version],[ng-for]'
57 | const angularVersionEl = document.querySelector('[ng-version]')
58 |
59 | if (document.querySelector(ANGULAR_SELECTOR)) {
60 | return {
61 | title: 'Angular',
62 | slug: 'angular',
63 | website: 'https://angular.io/',
64 | version:
65 | (angularVersionEl && angularVersionEl.getAttribute('ng-version')) ||
66 | undefined
67 | }
68 | }
69 | }
70 |
71 | export const vue: Check = () => {
72 | const isVueFound = doesAnyElement(document, el => {
73 | const attributes = Array.from(el.attributes).map(attr => attr.nodeName)
74 | const vueAttr = attributes.find(x => x.startsWith('data-v-'))
75 |
76 | if (el['__vue__'] || (vueAttr && !el.getAttribute(vueAttr))) {
77 | return true
78 | }
79 |
80 | return false
81 | })
82 |
83 | if (window['Vue'] || isVueFound) {
84 | return {
85 | title: 'Vue.js',
86 | slug: 'vue',
87 | website: 'https://vuejs.org/'
88 | }
89 | }
90 | }
91 |
92 | export const moment: Check = () => {
93 | if (safeGet(window, 'moment', 'version')) {
94 | return {
95 | title: 'Moment.js',
96 | slug: 'moment',
97 | website: 'https://momentjs.com/',
98 | version: safeGet(window, 'moment', 'version')
99 | }
100 | }
101 | }
102 |
103 | export const backbone: Check = () => {
104 | const backbone =
105 | safeGet(window, 'Backbone') || safeRequire(window, 'backbone')
106 |
107 | if (safeGet(backbone, 'VERSION')) {
108 | return {
109 | title: 'Backbone.js',
110 | slug: 'backbone',
111 | website: 'http://backbonejs.org/',
112 | version: safeGet(backbone, 'VERSION')
113 | }
114 | }
115 | }
116 |
117 | export const knockout: Check = () => {
118 | const knockout = safeGet(window, 'ko') || safeRequire(window, 'knockout')
119 |
120 | if (safeGet(knockout, 'version')) {
121 | return {
122 | title: 'Knockout',
123 | slug: 'knockout',
124 | website: 'http://knockoutjs.com/',
125 | version: safeGet(knockout, 'version')
126 | }
127 | }
128 | }
129 |
130 | export const ember: Check = () => {
131 | const version = safeGet(window, 'Ember', 'VERSION')
132 |
133 | if (version || document.querySelector('.ember-application')) {
134 | return {
135 | title: 'Ember.js',
136 | slug: 'ember',
137 | website: 'https://www.emberjs.com/',
138 | version
139 | }
140 | }
141 | }
142 |
143 | export const knockback: Check = () => {
144 | const version = safeGet(window, 'kb', 'VERSION')
145 |
146 | if (document.querySelectorAll('[kb-inject]').length > 0 || version) {
147 | return {
148 | title: 'Knockback.js',
149 | slug: 'knockback',
150 | website: 'http://kmalakoff.github.io/knockback/',
151 | version
152 | }
153 | }
154 | }
155 |
156 | export const require: Check = () => {
157 | if (
158 | typeof window['require'] === 'function' &&
159 | typeof window['requirejs'] === 'function'
160 | ) {
161 | return {
162 | title: 'RequireJS',
163 | slug: 'requirejs',
164 | website: 'http://requirejs.org/',
165 | version: safeGet(window, 'require', 'version')
166 | }
167 | }
168 | }
169 |
170 | export const webpack: Check = () => {
171 | if (window['webpackJsonp']) {
172 | return {
173 | title: 'Webpack',
174 | slug: 'webpack',
175 | website: 'https://webpack.js.org/'
176 | }
177 | }
178 | }
179 |
180 | export const polymer: Check = () => {
181 | if (safeGet(window, 'Polymer', 'version')) {
182 | return {
183 | title: 'Polymer',
184 | slug: 'polymer',
185 | website: 'https://www.polymer-project.org/',
186 | version: safeGet(window, 'Polymer', 'version')
187 | }
188 | }
189 | }
190 |
191 | export const mithril: Check = () => {
192 | const isMithrilObject = x =>
193 | isObjectWithProperties(window[x], ['component', 'render', 'route', 'prop'])
194 | const mKey = Object.getOwnPropertyNames(window).find(isMithrilObject)
195 |
196 | if (mKey) {
197 | return {
198 | title: 'Mithril',
199 | slug: 'mithril',
200 | website: 'https://mithril.js.org/'
201 | }
202 | }
203 | }
204 |
205 | export const aurelia: Check = () => {
206 | if (document.querySelector('[aurelia-app]')) {
207 | return {
208 | title: 'Aurelia',
209 | slug: 'aurelia',
210 | website: 'http://aurelia.io/'
211 | }
212 | }
213 | }
214 |
215 | export const dojo: Check = () => {
216 | const version = safeGet(window, 'dojo', 'version', 'toString')
217 |
218 | if (version) {
219 | return {
220 | title: 'Dojo',
221 | slug: 'dojo',
222 | website: 'https://dojotoolkit.org/',
223 | version: version()
224 | }
225 | }
226 | }
227 |
228 | export const socketio: Check = () => {
229 | const isSocketIoObject = x =>
230 | isObjectWithProperties(window[x], [
231 | 'Manager',
232 | 'Socket',
233 | 'connect',
234 | 'managers'
235 | ])
236 | const ioKey = Object.getOwnPropertyNames(window).find(isSocketIoObject)
237 |
238 | if (ioKey) {
239 | return {
240 | title: 'socket.io',
241 | slug: 'socketio',
242 | website: 'https://socket.io/'
243 | }
244 | }
245 | }
246 |
247 | export const cyclejs: Check = () => {
248 | if (safeGet(window, 'Cyclejs', 'sinks')) {
249 | return {
250 | title: 'Cycle.js',
251 | slug: 'cyclejs',
252 | website: 'https://cycle.js.org/'
253 | }
254 | }
255 | }
256 |
257 | export const meteor: Check = () => {
258 | const version = safeGet(window, 'Meteor', 'release')
259 |
260 | if (version) {
261 | return {
262 | title: 'Meteor',
263 | slug: 'meteor',
264 | website: 'https://www.meteor.com/',
265 | version: version.split('@').pop()
266 | }
267 | }
268 | }
269 |
270 | export const kendoui: Check = () => {
271 | if (safeGet(window, 'kendo', 'version')) {
272 | return {
273 | title: 'KendoUI',
274 | slug: 'kendoui',
275 | website: 'https://www.telerik.com/kendo-ui',
276 | version: safeGet(window, 'kendo', 'version')
277 | }
278 | }
279 | }
280 |
281 | export const styledComponents: Check = () => {
282 | if (document.querySelector('style[data-styled-components]')) {
283 | return {
284 | title: 'styled-components',
285 | slug: 'styledcomponents',
286 | website: 'https://www.styled-components.com/'
287 | }
288 | }
289 | }
290 |
291 | export const emotion: Check = () => {
292 | if (document.querySelector('style[data-emotion]')) {
293 | return {
294 | title: 'emotion',
295 | slug: 'emotion',
296 | website: 'https://emotion.sh/'
297 | }
298 | }
299 | }
300 |
301 | export const glamorous: Check = () => {
302 | if (document.querySelector('style[data-glamor]')) {
303 | return {
304 | title: 'glamorous',
305 | slug: 'glamorous',
306 | website: 'https://glamorous.rocks/'
307 | }
308 | }
309 | }
310 |
311 | export const radium: Check = () => {
312 | if (document.querySelector('[data-radium]')) {
313 | return {
314 | title: 'Radium',
315 | slug: 'radium',
316 | website: 'http://formidable.com/open-source/radium/'
317 | }
318 | }
319 | }
320 |
321 | export const nextjs: Check = () => {
322 | if (
323 | safeGet(window, 'next', 'ErrorComponent') ||
324 | safeGet(window, '__NEXT_DATA__')
325 | ) {
326 | return {
327 | title: 'Next.js',
328 | slug: 'nextjs',
329 | website: 'https://zeit.co/next'
330 | }
331 | }
332 | }
333 |
334 | export const elm: Check = () => {
335 | if (typeof window['Elm'] === 'object') {
336 | return {
337 | title: 'Elm',
338 | slug: 'elm',
339 | website: 'http://elm-lang.org/'
340 | }
341 | }
342 | }
343 |
344 | export const scalajs: Check = () => {
345 | if (window['__ScalaJSExportsNamespace']) {
346 | return {
347 | title: 'Scala.js',
348 | slug: 'scalajs',
349 | website: 'https://www.scala-js.org/'
350 | }
351 | }
352 | }
353 |
354 | export const reason: Check = () => {
355 | if (safeGet(window, 'ocaml', 'version')) {
356 | return {
357 | title: 'Reason',
358 | slug: 'reason',
359 | website: 'https://reasonml.github.io/',
360 | version: safeGet(window, 'ocaml', 'version')
361 | }
362 | }
363 | }
364 |
365 | export const gatsby: Check = () => {
366 | if (document.querySelector('#___gatsby')) {
367 | return {
368 | title: 'Gatsby',
369 | slug: 'gatsby',
370 | website: 'https://www.gatsbyjs.org/'
371 | }
372 | }
373 | }
374 |
375 | export const modernizr: Check = () => {
376 | if (safeGet(window, 'Modernizr', '_version')) {
377 | return {
378 | title: 'Modernizr',
379 | slug: 'modernizr',
380 | website: 'https://modernizr.com/',
381 | version: safeGet(window, 'Modernizr', '_version')
382 | }
383 | }
384 | }
385 |
386 | export const mobx: Check = () => {
387 | const isStore = x => safeGet(x, '$mobx')
388 | const isRootStore = x =>
389 | window[x] &&
390 | safeGetValues(window[x]) &&
391 | safeGetValues(window[x]).some(isStore)
392 | const mobxKey = Object.getOwnPropertyNames(window).find(isRootStore)
393 |
394 | if (
395 | mobxKey ||
396 | safeRequire(window, 'mobx') ||
397 | window['__mobxInstanceCount'] ||
398 | window['__mobxGlobal']
399 | ) {
400 | return {
401 | title: 'MobX',
402 | slug: 'mobx',
403 | website: 'https://mobx.js.org/'
404 | }
405 | }
406 | }
407 |
408 | export const materialize: Check = () => {
409 | if (typeof window['Materialize'] === 'object') {
410 | return {
411 | title: 'Materialize',
412 | slug: 'materialize',
413 | website: 'http://materializecss.com/'
414 | }
415 | }
416 | }
417 |
418 | export const d3: Check = () => {
419 | if (safeGet(window, 'd3', 'version')) {
420 | return {
421 | title: 'D3.js',
422 | slug: 'd3',
423 | website: 'https://d3js.org/',
424 | version: safeGet(window, 'd3', 'version')
425 | }
426 | }
427 | }
428 |
429 | export const whitestormjs: Check = () => {
430 | if (typeof window['WHS'] === 'object') {
431 | return {
432 | title: 'whs.js',
433 | slug: 'whsjs',
434 | website: 'https://whs.io/'
435 | }
436 | }
437 | }
438 |
439 | export const purescript: Check = () => {
440 | if (safeGet(window, 'PS', 'Main')) {
441 | return {
442 | title: 'PureScript',
443 | slug: 'purescript',
444 | website: 'http://www.purescript.org/'
445 | }
446 | }
447 | }
448 |
449 | export const mootools: Check = () => {
450 | if (safeGet(window, 'MooTools', 'version')) {
451 | return {
452 | title: 'MooTools',
453 | slug: 'mootools',
454 | website: 'https://mootools.net/',
455 | version: safeGet(window, 'MooTools', 'version')
456 | }
457 | }
458 | }
459 |
460 | export const clojurescript: Check = () => {
461 | if (safeGet(window, 'cljs', 'core')) {
462 | return {
463 | title: 'ClojureScript',
464 | slug: 'clojurescript',
465 | website: 'https://clojurescript.org/'
466 | }
467 | }
468 | }
469 |
470 | export const p5: Check = () => {
471 | if (typeof window['p5'] === 'function') {
472 | return {
473 | title: 'p5.js',
474 | slug: 'p5',
475 | website: 'https://p5js.org/'
476 | }
477 | }
478 | }
479 |
480 | export const pixijs: Check = () => {
481 | if (safeGet(window, 'PIXI', 'VERSION')) {
482 | return {
483 | title: 'PixiJS',
484 | slug: 'pixijs',
485 | website: 'http://www.pixijs.com/',
486 | version: safeGet(window, 'PIXI', 'VERSION')
487 | }
488 | }
489 | }
490 |
491 | export const ui5: Check = () => {
492 | if (safeGet(window, 'sap', 'ui', 'version')) {
493 | return {
494 | title: 'UI5',
495 | slug: 'ui5',
496 | website: 'http://openui5.org/',
497 | version: safeGet(window, 'sap', 'ui', 'version')
498 | }
499 | }
500 | }
501 |
502 | export const marko: Check = () => {
503 | if (document.querySelector('[data-marko],[data-marko-key]')) {
504 | return {
505 | title: 'Marko',
506 | slug: 'marko',
507 | website: 'https://markojs.com/'
508 | }
509 | }
510 | }
511 |
512 | export const svelte: Check = () => {
513 | if (safeGet(window, 'svelte', 'VERSION')) {
514 | return {
515 | title: 'Svelte',
516 | slug: 'svelte',
517 | website: 'https://svelte.technology/',
518 | version: safeGet(window, 'svelte', 'VERSION')
519 | }
520 | }
521 | }
522 |
523 | export const marionette: Check = () => {
524 | if (safeGet(window, 'Marionette', 'VERSION')) {
525 | return {
526 | title: 'Marionette',
527 | slug: 'marionette',
528 | website: 'https://marionettejs.com/',
529 | version: safeGet(window, 'Marionette', 'VERSION')
530 | }
531 | }
532 | }
533 |
534 | export const inferno: Check = () => {
535 | if (safeGet(window, 'Inferno', 'version')) {
536 | return {
537 | title: 'Inferno',
538 | slug: 'inferno',
539 | website: 'https://infernojs.org/',
540 | version: safeGet(window, 'Inferno', 'version')
541 | }
542 | }
543 | }
544 |
545 | export const dio: Check = () => {
546 | if (safeGet(window, 'dio', 'version')) {
547 | return {
548 | title: 'DIO',
549 | slug: 'dio',
550 | website: 'https://dio.js.org/',
551 | version: safeGet(window, 'dio', 'version')
552 | }
553 | }
554 | }
555 |
556 | export const extjs: Check = () => {
557 | if (safeGet(window, 'Ext', 'version')) {
558 | return {
559 | title: 'Ext JS',
560 | slug: 'extjs',
561 | website: 'https://www.sencha.com/products/extjs/',
562 | version: safeGet(window, 'Ext', 'version')
563 | }
564 | }
565 | }
566 |
567 | export const yui: Check = () => {
568 | if (safeGet(window, 'YUI', 'version')) {
569 | return {
570 | title: 'YUI',
571 | slug: 'yui',
572 | website: 'https://yuilibrary.com/',
573 | version: safeGet(window, 'YUI', 'version')
574 | }
575 | }
576 | }
577 |
578 | export const enyo: Check = () => {
579 | const enyo = safeGet(window, 'enyo')
580 | const enyoRequire = safeGet(enyo, 'require')
581 |
582 | if (enyo || safeGet(window, 'EnyoJS')) {
583 | return {
584 | title: 'Enyo',
585 | slug: 'enyo',
586 | website: 'http://enyojs.com/',
587 | version:
588 | safeGet(enyo, 'version') ||
589 | safeGet(enyo, 'version', 'enyo') ||
590 | safeGet(safeCall(enyoRequire, 'enyo'), 'version')
591 | }
592 | }
593 | }
594 |
595 | export const immutable: Check = () => {
596 | const im = safeGet(window, 'Immutable') || safeRequire(window, 'immutable')
597 |
598 | if (im) {
599 | return {
600 | title: 'Immutable.js',
601 | slug: 'immutable',
602 | website: 'https://facebook.github.io/immutable-js/',
603 | version: safeGet(im, 'version')
604 | }
605 | }
606 | }
607 |
608 | export const jqueryui: Check = () => {
609 | const jqKey = Object.getOwnPropertyNames(window).find(x =>
610 | safeGet(window, x, 'ui', 'version')
611 | )
612 |
613 | if (jqKey) {
614 | return {
615 | title: 'jQuery UI',
616 | slug: 'jqueryui',
617 | website: 'https://jqueryui.com/',
618 | version: safeGet(window, jqKey, 'ui', 'version')
619 | }
620 | }
621 | }
622 |
623 | export const moon: Check = () => {
624 | const m = safeGet(window, 'Moon') || safeRequire(window, 'moonjs')
625 | if (m) {
626 | return {
627 | title: 'Moon',
628 | slug: 'moon',
629 | website: 'http://moonjs.ga/',
630 | version: safeGet(m, 'version')
631 | }
632 | }
633 | }
634 |
635 | export const riot: Check = () => {
636 | const r = safeGet(window, 'riot') || safeRequire(window, 'riot')
637 |
638 | if (r) {
639 | return {
640 | title: 'Riot',
641 | slug: 'riot',
642 | website: 'http://riotjs.com/',
643 | version: safeGet(r, 'version')
644 | }
645 | }
646 | }
647 |
648 | export const phaser: Check = () => {
649 | if (safeGet(window, 'Phaser', 'VERSION')) {
650 | return {
651 | title: 'Phaser',
652 | slug: 'phaser',
653 | website: 'https://phaser.io/',
654 | version: safeGet(window, 'Phaser', 'VERSION')
655 | }
656 | }
657 | }
658 |
659 | export const webix: Check = () => {
660 | if (safeGet(window, 'webix', 'version')) {
661 | return {
662 | title: 'webix',
663 | slug: 'webix',
664 | website: 'https://webix.com/',
665 | version: safeGet(window, 'webix', 'version')
666 | }
667 | }
668 | }
669 |
670 | export const preact: Check = () => {
671 | const preact = safeGet(window, 'preact') || safeRequire(window, 'preact')
672 | const isPreactFound = doesAnyElement(
673 | document,
674 | el => el[Symbol.for('preactattr')] || el['__preactattr_']
675 | )
676 |
677 | if (preact || isPreactFound) {
678 | return {
679 | title: 'Preact',
680 | slug: 'preact',
681 | website: 'https://preactjs.com/',
682 | version: safeGet(preact, 'version')
683 | }
684 | }
685 | }
686 |
687 | export const chartjs: Check = () => {
688 | if (safeGet(window, 'Chart', 'instances')) {
689 | return {
690 | title: 'Chart.js',
691 | slug: 'chartjs',
692 | website: 'http://www.chartjs.org/'
693 | }
694 | }
695 | }
696 |
697 | export const raphael: Check = () => {
698 | if (safeGet(window, 'Raphael', 'version')) {
699 | return {
700 | title: 'Raphaël',
701 | slug: 'raphael',
702 | website: 'http://www.raphaeljs.com/',
703 | version: safeGet(window, 'Raphael', 'version')
704 | }
705 | }
706 | }
707 |
708 | export const amcharts: Check = () => {
709 | if (safeGet(window, 'AmCharts') || safeGet(window, 'amcharts2')) {
710 | return {
711 | title: 'amCharts',
712 | slug: 'amcharts',
713 | website: 'https://www.amcharts.com/'
714 | }
715 | }
716 | }
717 |
718 | export const echarts: Check = () => {
719 | if (safeGet(window, 'echarts', 'version')) {
720 | return {
721 | title: 'ECharts',
722 | slug: 'echarts',
723 | website: 'http://echarts.baidu.com/',
724 | version: safeGet(window, 'echarts', 'version')
725 | }
726 | }
727 | }
728 |
729 | export const lodash: Check = () => {
730 | if (safeGet(window, '_', 'VERSION')) {
731 | return {
732 | title: 'Lodash',
733 | slug: 'lodash',
734 | website: 'https://lodash.com/',
735 | version: safeGet(window, '_', 'VERSION')
736 | }
737 | }
738 | }
739 |
740 | export const amp: Check = () => {
741 | if (
742 | safeGet(window, 'AMP') ||
743 | safeGet(window, 'AMP_TAG') ||
744 | safeGet(window, 'AMP_MODE')
745 | ) {
746 | return {
747 | title: 'AMP',
748 | slug: 'amp',
749 | website: 'https://www.ampproject.org/',
750 | version: safeGet(window, 'AMP_MODE', 'version')
751 | }
752 | }
753 | }
754 |
755 | export const highcharts: Check = () => {
756 | if (safeGet(window, 'Highcharts', 'version')) {
757 | return {
758 | title: 'Highscharts',
759 | slug: 'highcharts',
760 | website: 'https://www.highcharts.com/',
761 | version: safeGet(window, 'Highcharts', 'version')
762 | }
763 | }
764 | }
765 |
766 | export const handlebars: Check = () => {
767 | if (safeGet(window, 'Handlebars', 'VERSION')) {
768 | return {
769 | title: 'Handlebars',
770 | slug: 'handlebars',
771 | website: 'http://handlebarsjs.com/',
772 | version: safeGet(window, 'Handlebars', 'VERSION')
773 | }
774 | }
775 | }
776 |
777 | export const anime: Check = () => {
778 | if (safeGet(window, 'anime', 'version')) {
779 | return {
780 | title: 'anime',
781 | slug: 'anime',
782 | website: 'http://animejs.com/',
783 | version: safeGet(window, 'anime', 'version')
784 | }
785 | }
786 | }
787 |
788 | export const uikit: Check = () => {
789 | if (safeGet(window, 'UIkit', 'version')) {
790 | return {
791 | title: 'UIkit',
792 | slug: 'uikit',
793 | website: 'https://getuikit.com/',
794 | version: safeGet(window, 'UIkit', 'version')
795 | }
796 | }
797 | }
798 |
799 | export const yalla: Check = () => {
800 | if (safeGet(window, 'yalla')) {
801 | return {
802 | title: 'YallaJS',
803 | slug: 'yalla',
804 | website: 'http://yallajs.io/'
805 | }
806 | }
807 | }
808 |
809 | export const epoch: Check = () => {
810 | if (safeGet(window, 'Epoch')) {
811 | return {
812 | title: 'Epoch',
813 | slug: 'epoch',
814 | website: 'https://epochjs.github.io/epoch/'
815 | }
816 | }
817 | }
818 |
819 | export const ractive: Check = () => {
820 | if (safeGet(window, 'Ractive')) {
821 | return {
822 | title: 'Ractive',
823 | slug: 'ractive',
824 | website: 'https://ractive.js.org/',
825 | version: safeGet(window, 'Ractive', 'VERSION')
826 | }
827 | }
828 | }
829 |
830 | export const semantic: Check = () => {
831 | if (safeGet(window, 'semantic')) {
832 | return {
833 | title: 'Semantic UI',
834 | slug: 'semanticui',
835 | website: 'https://semantic-ui.com/'
836 | }
837 | }
838 | }
839 |
840 | export const bootstrap: Check = () => {
841 | if (safeGet(window, 'bootstrap')) {
842 | return {
843 | title: 'Bootstrap',
844 | slug: 'bootstrap',
845 | website: 'https://getbootstrap.com/'
846 | }
847 | }
848 | }
849 |
850 | export const foundation: Check = () => {
851 | if (safeGet(window, 'Foundation')) {
852 | return {
853 | title: 'Foundation',
854 | slug: 'foundation',
855 | website: 'https://foundation.zurb.com/',
856 | version: safeGet(window, 'Foundation', 'version')
857 | }
858 | }
859 | }
860 |
861 | export const maquette: Check = () => {
862 | if (safeGet(window, 'maquette')) {
863 | return {
864 | title: 'Мaquette',
865 | slug: 'maquette',
866 | website: 'https://maquettejs.org/'
867 | }
868 | }
869 | }
870 |
--------------------------------------------------------------------------------
/src/checks/isObjectWithProperties.ts:
--------------------------------------------------------------------------------
1 | const isObjectWithProperties = (object: any, props: string[]) => {
2 | return (
3 | object && props.every(x => Object.getOwnPropertyNames(object).includes(x))
4 | )
5 | }
6 |
7 | export default isObjectWithProperties
8 |
--------------------------------------------------------------------------------
/src/checks/types.ts:
--------------------------------------------------------------------------------
1 | export interface Library {
2 | readonly title: string
3 | readonly slug: string
4 | readonly website: string
5 | readonly version?: string
6 | }
7 |
8 | export type Check = () => Library | undefined
9 |
--------------------------------------------------------------------------------
/src/content.ts:
--------------------------------------------------------------------------------
1 | const injectScript = (file: string, node: string) => {
2 | const th = document.getElementsByTagName(node)[0]
3 | const s = document.createElement('script')
4 | s.setAttribute('type', 'text/javascript')
5 | s.setAttribute('src', file)
6 | th.appendChild(s)
7 | }
8 |
9 | let cachedResult
10 |
11 | chrome.runtime.onMessage.addListener((request, _, sendResponse) => {
12 | if (request.type === 'GET_STACK') {
13 | if (!cachedResult) {
14 | injectScript(chrome.extension.getURL('./build/checker.js'), 'body')
15 |
16 | const libInterval = setInterval(() => {
17 | const libs = ([
18 | ...(document.querySelectorAll('.ui-stack-lib') as any)
19 | ] as HTMLElement[]).map(x => ({ ...x.dataset }))
20 | const noLibsFound = Boolean(document.querySelector('.ui-stack-no-libs'))
21 |
22 | if (noLibsFound) {
23 | cachedResult = []
24 | sendResponse([])
25 | clearInterval(libInterval)
26 | }
27 |
28 | if (libs.length !== 0) {
29 | cachedResult = libs
30 | sendResponse(libs)
31 | clearInterval(libInterval)
32 | }
33 | }, 1000)
34 | } else {
35 | sendResponse(cachedResult)
36 | }
37 | }
38 |
39 | return true
40 | })
41 |
--------------------------------------------------------------------------------
/src/popup.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
66 |
67 |
68 |
71 |
72 |