Repository: dderevjanik/github-vscode-icons Branch: master Commit: c68bd7fb3281 Files: 54 Total size: 74.9 KB Directory structure: gitextract_x3fazdhg/ ├── .github/ │ └── workflows/ │ └── test.yml ├── .gitignore ├── .prettierrc ├── .vscode/ │ ├── extensions.json │ └── settings.json ├── CHANGELOG.md ├── CREDITS.md ├── LICENSE ├── README.md ├── build/ │ ├── background.html │ ├── content.css │ ├── manifest.json │ ├── popup.css │ └── popup.html ├── dist/ │ └── .gitignore ├── package.json ├── packages/ │ ├── ManifesFirefox.ts │ ├── ManifestChrome.ts │ ├── ManifestEdge.ts │ ├── background/ │ │ └── Background.ts │ ├── common/ │ │ ├── HostData.ts │ │ ├── LocalStorage.ts │ │ ├── Messenger.ts │ │ └── SupportedHostings.ts │ ├── content/ │ │ ├── Content.ts │ │ ├── data/ │ │ │ └── PastebinSyntaxesToIcon.json │ │ ├── pages/ │ │ │ ├── BitBucket.ts │ │ │ ├── GistGitHub.ts │ │ │ ├── GitHub.ts │ │ │ ├── GitLab.ts │ │ │ ├── PasteBin.ts │ │ │ └── SourceForge.ts │ │ └── utils/ │ │ ├── Dev.ts │ │ ├── Icons.ts │ │ ├── PageDetect.ts │ │ └── showIconsForHosting.ts │ └── popup/ │ └── Popup.tsx ├── scripts/ │ ├── create-manifest.ts │ ├── make-dist-zip.script.ts │ └── utils.ts ├── tests/ │ ├── packages/ │ │ └── content/ │ │ └── pages/ │ │ ├── BitBucket.test.ts │ │ ├── GistGitHub.test.ts │ │ ├── GitHub.test.ts │ │ ├── GitLab.test.ts │ │ └── SourceForge.test.ts │ ├── tsconfig.tests.json │ └── utils.ts ├── tsconfig.json ├── typings/ │ ├── fastdom/ │ │ └── index.d.ts │ ├── icons.d.ts │ ├── languages-vscode.d.ts │ ├── languages-vsi.d.ts │ └── select-dom/ │ └── index.d.ts └── webpack.config.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/test.yml ================================================ name: Test on: pull_request: push: workflow_dispatch: schedule: - cron: "0 8 * * *" # Every day at 8:00 UTC https://crontab.guru/#0_8_*_*_* jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Install dependencies run: npm ci - name: Run prettier linting run: npm run lint - name: Run unit tests run: npm test - name: Run build run: npm run build:prod - name: Upload dist bundle uses: actions/upload-artifact@v2 with: name: test-build path: dist - name: Codecov Upload uses: codecov/codecov-action@v1 with: file: ./coverage/lcov.info ================================================ FILE: .gitignore ================================================ .idea/ # Build build/*.js # Maps build/*.js.map # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* # Libs node_modules # local coverage coverage ================================================ FILE: .prettierrc ================================================ { "printWidth": 120, "parser": "typescript", "singleQuote": true } ================================================ FILE: .vscode/extensions.json ================================================ { "recommendations": [ "esbenp.prettier-vscode" ] } ================================================ FILE: .vscode/settings.json ================================================ { "typescript.tsdk": "node_modules/typescript/lib", "tslint.enable": false, "search.exclude": { "**/node_modules": true, "**/bower_components": true, "**/dist": true }, "workbench.colorCustomizations": { "activityBar.background": "#192963", "titleBar.activeBackground": "#23398B", "titleBar.activeForeground": "#FAFBFE" } } ================================================ FILE: CHANGELOG.md ================================================ # Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) ## [1.0.24] - 2021-09-30 - Updated `vscode-icons` to 11.6.0 - Over 200 new filenames, folders and extension - Over 20 new icons ## [1.0.23] - 2021-02-13 - Updated `vscode-icons` to 11.1.0 - Various improvements [#27](https://github.com/dderevjanik/github-vscode-icons/pull/27), thanks to [kidonng](https://github.com/kidonng) - Better github url detection [#26](https://github.com/dderevjanik/github-vscode-icons/pull/26), thanks to [kidonng](https://github.com/kidonng) - Test for queries [#24](https://github.com/dderevjanik/github-vscode-icons/pull/24), thanks to [s-weigand](https://github.com/s-weigand) - Vertically adjuested icons [#28](https://github.com/dderevjanik/github-vscode-icons/pull/30), thanks to [antoinerousseau](https://github.com/antoinerousseau) ## [1.0.22] - 2020-06-30 ### Fixes - Fixed new github UI design [#21](https://github.com/dderevjanik/github-vscode-icons/issues/21) ## [1.0.21] - 2020-06-20 ### Fixes - Fixed Infinite spinner issue [#13](https://github.com/dderevjanik/github-vscode-icons/issues/13) and [#17](https://github.com/dderevjanik/github-vscode-icons/issues/17), thanks to [s-weigand](https://github.com/s-weigand) ## Changed - Updated `vscode-icons` to 10.1.1 [changelog](https://marketplace.visualstudio.com/items/vscode-icons-team.vscode-icons/changelog). Since last version (`9.3.0`), there are - over 180 new filenames and extensions - over 60 new folders - 142 new icons and 51 changed ## [1.0.20] - 2020-02-24 ### Fixes - Fixed [GH issue](https://github.com/dderevjanik/github-vscode-icons/issues/13) - Fixed [GH not displaying submodule](https://github.com/dderevjanik/github-vscode-icons/issues/11) ## [1.0.19] - 2019-05-20 ### Fixes - Fixed (again) [issue with Refined Github](https://github.com/dderevjanik/github-vscode-icons/issues/8) ### Changed - Added support [for symlink directory](https://github.com/dderevjanik/github-vscode-icons/issues/9) (`octicon-file-symlink-directory`) - Added better error reporting - In console, you can see better error messages - If icon cannot be set, leave loading icon ## [1.0.18] - 2019-04-26 ### Fixes - Fixed [issue with Refined Github](https://github.com/dderevjanik/github-vscode-icons/issues/8) ## [1.0.17] - 2019-04-23 ### Changed - Updated `vscode-icons` to 8.6.0 [changelog](https://marketplace.visualstudio.com/items/robertohuertasm.vscode-icons/changelog)[changelog] - Feature: Support for `coverage` folder. ([@robertohuertasm](https://github.com/robertohuertasm) in [#2015](https://github.com/vscode-icons/vscode-icons/pull/2015)) - Feature: Support for `azure-pipelines` folder. ([@robertohuertasm](https://github.com/robertohuertasm) in [#2014](https://github.com/vscode-icons/vscode-icons/pull/2014)) - Feature: Support for `interfaces` folder. ([@KingDarBoja](https://github.com/KingDarBoja) & [@robertohuertasm](https://github.com/robertohuertasm) in [#2013](https://github.com/vscode-icons/vscode-icons/pull/2013)) - Feature: Support for `notifications & event` folders. ([@KingDarBoja](https://github.com/KingDarBoja) in [#2012](https://github.com/vscode-icons/vscode-icons/pull/2012)) - Feature: Support for `theme` folder. ([@KingDarBoja](https://github.com/KingDarBoja) in [#2011](https://github.com/vscode-icons/vscode-icons/pull/2011)) - Feature: Support for `services` folder. ([@KingDarBoja](https://github.com/KingDarBoja) in [#2010](https://github.com/vscode-icons/vscode-icons/pull/2010)) - Feature: Support for `middleware` folder. ([@KingDarBoja](https://github.com/KingDarBoja) in [#2009](https://github.com/vscode-icons/vscode-icons/pull/2009)) - Feature: Support for `mock` folder. ([@JimiC](https://github.com/JimiC) in [#2008](https://github.com/vscode-icons/vscode-icons/pull/2008)) - Feature: Support for `blueprint` folder. ([@JimiC](https://github.com/JimiC) in [#2007](https://github.com/vscode-icons/vscode-icons/pull/2007)) - Feature: Support for `controllers` folder. ([@JimiC](https://github.com/JimiC) in [#2006](https://github.com/vscode-icons/vscode-icons/pull/2006)) - Enhancement: Updated `Google Cloud` folder icon. ([@JimiC](https://github.com/JimiC) in [#2005](https://github.com/vscode-icons/vscode-icons/pull/2005)) - Feature: Support for `certificates` folder. ([@JimiC](https://github.com/JimiC) & [@robertohuertasm](https://github.com/robertohuertasm) in [#2004](https://github.com/vscode-icons/vscode-icons/pull/2004)) - Feature: Support for `minikube` folder. ([@JimiC](https://github.com/JimiC) in [#2003](https://github.com/vscode-icons/vscode-icons/pull/2003)) - Feature: Support for `entities` folder. ([@JimiC](https://github.com/JimiC) in [#2002](https://github.com/vscode-icons/vscode-icons/pull/2002)) - Feature: Support for `repo` folder. ([@JimiC](https://github.com/JimiC) in [#2001](https://github.com/vscode-icons/vscode-icons/pull/2001)) - Feature: Support for `sounds` folder. ([@JimiC](https://github.com/JimiC) in [#2000](https://github.com/vscode-icons/vscode-icons/pull/2000)) - Feature: Support for more `config` names for folders. ([@JimiC](https://github.com/JimiC) in [#1999](https://github.com/vscode-icons/vscode-icons/pull/1999)) - Feature: Support for `Stories` folder. ([@JimiC](https://github.com/JimiC) in [#1998](https://github.com/vscode-icons/vscode-icons/pull/1998)) - Feature: Support for `Stories` folder. ([@JimiC](https://github.com/JimiC) in [#1997](https://github.com/vscode-icons/vscode-icons/pull/1997)) - Feature: Support for `_locales` folder. ([@JimiC](https://github.com/JimiC) in [#1996](https://github.com/vscode-icons/vscode-icons/pull/1996)) - Feature: Support for `cmake` folder. ([@JimiC](https://github.com/JimiC) in [#1995](https://github.com/vscode-icons/vscode-icons/pull/1995)) - Feature: Support for `Gulp` folder. ([@JimiC](https://github.com/JimiC) in [#1994](https://github.com/vscode-icons/vscode-icons/pull/1994)) - Feature: Support for `Electron` folder. ([@JimiC](https://github.com/JimiC) in [#1993](https://github.com/vscode-icons/vscode-icons/pull/1993)) - Feature: Support for `Cuda` folder. ([@JimiC](https://github.com/JimiC) in [#1992](https://github.com/vscode-icons/vscode-icons/pull/1992)) - Feature: Support for `vsixmanifest` folder. ([@JimiC](https://github.com/JimiC) in [#1991](https://github.com/vscode-icons/vscode-icons/pull/1991)) - Feature: Support for `cli` folder. ([@KingDarBoja](https://github.com/KingDarBoja) & [@JimiC](https://github.com/JimiC) in [#1990](https://github.com/vscode-icons/vscode-icons/pull/1990)) - Feature: Support for `Buildkite` folder. ([@KingDarBoja](https://github.com/KingDarBoja) in [#1989](https://github.com/vscode-icons/vscode-icons/pull/1989)) - Feature: Support for `Grunt` folder. ([@KingDarBoja](https://github.com/KingDarBoja) in [#1988](https://github.com/vscode-icons/vscode-icons/pull/1988)) - Feature: Support for `windows, linux & macos` folders. ([@KingDarBoja](https://github.com/KingDarBoja) in [#1986](https://github.com/vscode-icons/vscode-icons/pull/1986)) - Feature: Support for `modules` folder. ([@KingDarBoja](https://github.com/KingDarBoja) in [#1985](https://github.com/vscode-icons/vscode-icons/pull/1985)) - Feature: Support for `Sentry`. ([@KingDarBoja](https://github.com/KingDarBoja) in [#1984](https://github.com/vscode-icons/vscode-icons/pull/1984)) - Feature: Support for `JSS`. ([@KingDarBoja](https://github.com/KingDarBoja) in [#1983](https://github.com/vscode-icons/vscode-icons/pull/1983)) - Feature: Support for `Moleculer`. ([@icebob](https://github.com/icebob) in [#1980](https://github.com/vscode-icons/vscode-icons/pull/1980)) - Feature: Support for `APL`. ([@KingDarBoja](https://github.com/KingDarBoja) in [#1978](https://github.com/vscode-icons/vscode-icons/pull/1978)) ## [1.0.16] - 2019-04-12 ### Changed - Updated `vscode-icons` to 8.5.0 [changelog](https://marketplace.visualstudio.com/items/robertohuertasm.vscode-icons/changelog) - Over 122 new icons ## [1.0.14] - 2018-09-12 ### Fixes - vscode-icons not showing after latest GH update ## [1.0.13] - 2018-08-02 ### Changed - Updated `vscode-icons` to 7.25.0 [changelog](https://marketplace.visualstudio.com/items/robertohuertasm.vscode-icons/changelog) ### Fixes - Filenames like `Jenkinsfile`, which are defined by vscode language extension, now works ## [1.0.12] - 2018-06-07 ### Changed - Updated `vscode-icons` to 7.23.0, added 15 new icons [changelog](https://marketplace.visualstudio.com/items/robertohuertasm.vscode-icons/changelog) ## [1.0.11] - 2018-05-02 ### Fixes - Showing loading icon instead of file icon in Gitlab - Loading icon in Bitbucket ## [1.0.10] - 2018-03-23 ### Changed - Updated `vscode-icons` to 7.22.0, added 13 new icons [changelog](https://marketplace.visualstudio.com/items/robertohuertasm.vscode-icons/changelog) ## [1.0.9] - 2018-03-18 ### Changed - Updated `vscode-icons` to 7.21.0 [changelog](https://marketplace.visualstudio.com/items/robertohuertasm.vscode-icons/changelog) ## [1.0.8] - 2018-02-18 ### Added - Support for [gitlab.com](https://about.gitlab.com/) - Display icons in Repo Tree - Support for [bitbucket.org](https://bitbucket.org/) - Display icons in Repo Tree - Support for [pastebin.com](https://pastebin.com/) - Display icons in user profile - Support for [sourceforge.com](https://sourceforge.net) - Display icons in project files ### Changed - Updated `vscode-icons` to 7.19.0, added 25 new icons, read more at vscode-icons [changelog](https://marketplace.visualstudio.com/items/robertohuertasm.vscode-icons/changelog) - Changed structure of project to be more abstract for several web-based GIT hostings (Github, Gitlab, Bitbucket and Gist) and even for Pastebin ### Fixes - [Github] no icon for submodule - [Github] temporally fixed bug with `symlink` files - [Github] not showing file icons ## [1.0.6] - 2017-10-29 - updated `vscode-icons` to 7.17.0, added 24 new icons, read more at vscode-icons [changelog](https://github.com/vscode-icons/vscode-icons/blob/master/CHANGELOG.md#7170-october-28-2017) - changed orange logo back to blue one, read more about this change at [vscode blogpost](https://code.visualstudio.com/blogs/2017/10/24/theicon) ## [1.0.5] - 2017-10-24 ### Changed - `vscode-icons` updated to `7.16.0`, added 25 new icons, read more at vscode-icons [changelog](https://github.com/vscode-icons/vscode-icons/blob/master/CHANGELOG.md#7160-october-22-2017) ## [1.0.4] - 2017-10-20 ### Changed - Blue logo to orange one, read more about this change at [vscode blogpost](https://code.visualstudio.com/updates/v1_17#_new-visual-studio-code-logo) - Name of extension from `vscode-github-icons` to `github-vscode-icons` in chrome store - Project Structure, now is more readable and better self-explanatory - Better performance (~25%) thanks to optimizing `getIcons` functions ### Added - Support for filenames with several extensions like `content.js.map`, `index.test.tsx`, etc - Opera browser extension - Loading icon when `vscode-icons` is loading - Test for *getIcons* functions ## [1.0.3] - 2017-10-10 ### Fixes - Showing light version of icons should work correctly ## [1.0.2] - 2017-10-08 ### Fixes - Icons are now showed properly in github repo tree ### Added - Travis Support ### Changed - Default theme for icons is `light` now (before it was `dark`) - [vscode-icons](https://github.com/vscode-icons/vscode-icons) version changed to `7.15.0`, see [CHANGELOG.md](https://github.com/vscode-icons/vscode-icons/blob/master/CHANGELOG.md) ## [1.0.1] - 2017-10-06 ### Added - Showing icons on `gist.github` - This changelog file - `CREDITS.md` ### Changed - Script is running on proper GH pages (so it'll no trying to render file icons on account settings page) ## [1.0.0] - 2017-10-03 - Initial version ================================================ FILE: CREDITS.md ================================================ # Credits ## Contributors - [dderevjanik](https://github.com/dderevjanik) - [s-weigand](https://github.com/s-weigand) - [kidonng](https://github.com/kidonng) - [antoinerousseau](https://github.com/antoinerousseau) ## Projects - [vscode-icons](https://github.com/vscode-icons/vscode-icons) for providing beautiful icons and their definitions - [refined-github](https://github.com/sindresorhus/refined-github/blob/master/src/libs/page-detect.js) for github page detect functions - [hide-files-on-github](https://github.com/sindresorhus/hide-files-on-github) for `pjax:end` event listener + observerFragment ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2018 Daniel Derevjanik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # Github-vscode-icons [![Build Status](https://travis-ci.org/dderevjanik/github-vscode-icons.svg?branch=master)](https://travis-ci.org/dderevjanik/github-vscode-icons) [![Known Vulnerabilities](https://snyk.io/test/github/dderevjanik/github-vscode-icons/badge.svg)](https://snyk.io/test/github/dderevjanik/github-vscode-icons) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier) Chrome webstore: ![Chrome Web Store](https://img.shields.io/chrome-web-store/rating/hoccpcefjcgnabbmojbfoflggkecmpgd) **Download:** [![Chrome Web Store](https://img.shields.io/chrome-web-store/v/hoccpcefjcgnabbmojbfoflggkecmpgd)](https://chrome.google.com/webstore/detail/vscode-github-icons/hoccpcefjcgnabbmojbfoflggkecmpgd?utm_source=github) [![Mozilla Add-on](https://img.shields.io/amo/v/github-vscode-icons)](https://addons.mozilla.org/en-GB/firefox/addon/github-vscode-icons/) **Supported websites:** ![github-favicon](build/favicons/github-favicon.ico) Github (also Gist), ![gitlab-favicon](build/favicons/gitlab-favicon.ico) Gitlab, ![pastebin-favicon](build/favicons/pastebin-favicon.ico) Pastebin, ![sourceforge-favicon](./build/favicons/sourceforge-favicon.ico) SourceForge ## About Extension for browser, which displays [vscode-icons](https://github.com/vscode-icons/vscode-icons) in Github (including Gist), Gitlab and Bitbucket repositories. It also displays `vscode-icons` in user's Pastebin list and in Sourceforge projects. If you're familiar with beautiful extension for vscode called `vscode-icons`, then you know that you need also one for Web. Brain will recognize different icons much faster and when you're spending several hours per day on websites like github, gitlab or bitbucket, this extension is for you. If you look at github repository with displayed `vscode-icons`, you'll get instant overview of used technologies by their specific icons (*look at screenshots below*). Go to [changelog](./CHANGELOG.md) to see latest changes ## Screenshots ![screen_repo](./docs/screenshots/repo_screens.png) ## Development To stay updated with `vscode-icons`, you need to extract compiled `icons.json` from `vscode-icons` everytime when it updates. After that, you need run script called `npm run preprocess`, which will generate definition chunks (categorized icons) from `icons.json` for easier and faster work with them. ## Related - [vscode-icons](https://github.com/vscode-icons/vscode-icons) extension for vscode - [vscode-icons-js](https://github.com/dderevjanik/vscode-icons-js) File specific icons from vscode [vscode-icons](https://github.com/vscode-icons/vscode-icons) extension inspired by file-icons-js ================================================ FILE: build/background.html ================================================ ================================================ FILE: build/content.css ================================================ /** * Github */ td.icon { min-width: 26px; /* make sure that icon will not blink after replacing old one */ } td.icon > .octicon { display: none; /* don't show old icon */ width: 16px; } td.icon > .spinner { display: block !important; /* show loading icon while replacing old one */ } td.icon > img { /* copied from original icon */ position: relative; top: 3px; margin-top: -3px; margin-left: -2px; } .js-path-segment > a > img { vertical-align: middle; } .js-path-segment:before { /* min-width: 16px; display: inline-block; content: "\00a0 "; */ } .final-path > img { vertical-align: middle; } /* diff icons - WIP */ .vsi-icon-diff { vertical-align: middle; } .vscode-icon { vertical-align: -3px; height: 16px; } /** * BitBucket */ .bb-icon { height: 24px !important; vertical-align: text-top; } /* .aui-iconfont-devtools-folder-closed:before { width: 16px; height: 16px; background-image: url('chrome-extension://__MSG_@@extension_id__/images/animation.gif'); background-size: 16px 16px; } .aui-iconfont-devtools-submodule:before { width: 16px; height: 16px; background-image: url('chrome-extension://__MSG_@@extension_id__/images/animation.gif'); background-size: 16px 16px; } .aui-iconfont-devtools-file:before { width: 16px; height: 16px; background-image: url('chrome-extension://__MSG_@@extension_id__/images/animation.gif'); background-size: 16px 16px; } .aui-iconfont-devtools-folder-closed:before { content: "" !important; } .aui-iconfont-devtools-submodule:before { content: "" !important; } .aui-iconfont-devtools-file:before { content: "" !important; } */ /** * GitLab */ .tree-item > td > .fa.fa-folder.fa-fw { width: 18px; height: 14px; background-image: url('chrome-extension://__MSG_@@extension_id__/images/animation.gif'); background-size: 18px 14px; } .tree-item > td > .fa.fa-file-text-o.fa-fw { width: 18px; height: 14px; background-image: url('chrome-extension://__MSG_@@extension_id__/images/animation.gif'); background-size: 18px 14px; } .tree-item > td > .fa.fa-file-folder-o.fa-fw { width: 18px; height: 14px; background-image: url('chrome-extension://__MSG_@@extension_id__/images/animation.gif'); background-size: 18px 14px; } .tree-item > td > .fa.fa-folder.fa-fw::before { content: ""; } .tree-item > td > .fa.fa-file-text-o.fa-fw::before { content: ""; } .tree-item > td > .fa.fa-file-folder-o.fa-fw::before { content: ""; } /** * Pastebin */ .vsi-pb { margin: 10px 7px 0 -5px } /** * Source Forge */ .vscode-icon.sf-icon { margin-right: 0.5rem; width: 20px; height: 20px; } ================================================ FILE: build/manifest.json ================================================ { "manifest_version": 2, "name": "github-vscode-icons", "description": "This extension shows a VS Code icons in Github Repositories", "icons": { "16": "icon16.png", "48": "icon48.png", "128": "icon128.png" }, "version": "1.24", "author": "Daniel Derevjanik ", "offline_enabled": true, "browser_action": { "default_icon": { "48": "icon48.png", "128": "icon128.png" } }, "background": { "scripts": [ "background.js" ], "persistent": false }, "web_accessible_resources": [ "icons/*.svg", "images/*.gif" ], "content_scripts": [ { "css": [ "content.css" ], "matches": [ "*://*/*" ], "js": [ "content.js" ], "run_at": "document_idle" } ], "permissions": [ "storage", "*://bitbucket.org/*", "*://github.com/*", "*://gist.github.com/*", "*://gitlab.com/*", "*://pastebin.com/*", "*://sourceforge.net/*" ], "-ms-preload": { "backgroundScript": "backgroundScriptsAPIBridge.js", "contentScript": "contentScriptsAPIBridge.js" } } ================================================ FILE: build/popup.css ================================================ html { width: 300px; } body { width: 300px; padding: 10px; } .vsi-icon { width: 16px; height: 16px; } ================================================ FILE: build/popup.html ================================================ Surfable: Command Palette
================================================ FILE: dist/.gitignore ================================================ * !.gitignore ================================================ FILE: package.json ================================================ { "name": "github-vscode-icons", "version": "1.0.24", "description": "show vscode-icons in github repository", "main": "index.js", "private": true, "scripts": { "script:make-zip": "ts-node ./scripts/make-dist-zip.script.ts", "clean": "rimraf build/*.map", "dev": "npm run build:dev", "manifest:firefox": "ts-node ./scripts/create-manifest.ts", "manifest:chrome": "BROWSER=CHROME ts-node ./scripts/create-manifest.ts", "manifest:edge": "BROWSER=EDGE ts-node ./scripts/create-manifest.ts", "manifest:dev": "NODE_ENV=development npm run manifest:chrome", "build:firefox": "BROWSER=FIREFOX run-s manifest:firefox script:make-zip", "build:chrome": "BROWSER=CHROME run-s manifest:chrome script:make-zip", "build:edge": "BROWSER=EDGE run-s manifest:edge script:make-zip", "build:dev": "NODE_ENV=development; webpack -w --mode development", "build:prod": "NODE_ENV=production; webpack --mode production --config webpack.config.js; run-s clean build:firefox build:chrome build:edge", "dist": "npm run build:prod", "lint": "run-s lint:packages lint:json lint:typings", "lint:packages": "prettier --check ./packages/**/*.{ts,d.ts,tsx}", "lint:json": "prettier --parser json --check ./{*,tests/*}.json", "lint:typings": "prettier --check ./typings/**/*.d.ts", "format": "run-s format:packages format:json format:typings", "format:packages": "prettier --write ./packages/**/*.{ts,d.ts,tsx}", "format:json": "prettier --parser json --write ./{*,tests/*}.json", "format:typings": "prettier --write ./typings/**/*.d.ts", "test": "jest --coverage" }, "jest": { "preset": "jest-puppeteer", "globals": { "extensionsToTreatAsEsm": [ ".ts" ], "ts-jest": { "tsconfig": "tests/tsconfig.tests.json", "useESM": true } }, "transform": { "^.+(\\.(ts|tsx)|select-dom/.+\\.js)$": "ts-jest" }, "transformIgnorePatterns": [ "/node_modules/(?!select-dom)" ], "testRegex": "(/tests/.*\\.(test|spec))\\.(ts|tsx|js)$", "moduleFileExtensions": [ "ts", "tsx", "js" ], "coveragePathIgnorePatterns": [ "/node_modules/", "/tests/" ], "collectCoverageFrom": [ "packages/**/*.{js,ts,tsx}" ] }, "repository": { "type": "git", "url": "git+https://github.com/dderevjanik/github-vscode-icons" }, "author": { "email": "daniel.derevjanik@gmail.com", "name": "Daniel Derevjanik" }, "license": "MIT", "bugs": { "url": "https://github.com/dderevjanik/github-vscode-icons/issues" }, "homepage": "https://github.com/dderevjanik/github-vscode-icons#readme", "dependencies": { "fastdom": "^1.0.10", "github-url-detection": "^2.0.5", "react": "^17.0.1", "react-dom": "^17.0.1", "select-dom": "^7.1.0", "selector-observer": "^2.1.6", "vscode-icons-js": "^11.6.0" }, "devDependencies": { "@types/archiver": "^5.1.0", "@types/chalk": "^0.4.31", "@types/chrome": "0.0.130", "@types/jest": "^26.0.20", "@types/jest-environment-puppeteer": "^4.4.1", "@types/jsdom": "^16.2.6", "@types/node": "^14.14.27", "@types/node-fetch": "^2.5.8", "@types/puppeteer": "^5.4.3", "@types/react": "^17.0.2", "@types/react-dom": "^17.0.1", "archiver": "^5.2.0", "chalk": "^4.1.0", "cross-env": "^7.0.3", "jest": "^27.0.0-next.7", "jest-puppeteer": "^4.4.0", "jsdom": "^16.4.0", "node-fetch": "^2.6.1", "npm-run-all": "^4.1.5", "prettier": "^2.2.1", "puppeteer": "^7.1.0", "rimraf": "^3.0.2", "ts-jest": "^27.0.0-next.10", "ts-loader": "^8.0.17", "ts-node": "^9.1.1", "typescript": "^4.1.5", "webpack": "^5.21.2", "webpack-cli": "^4.5.0" } } ================================================ FILE: packages/ManifesFirefox.ts ================================================ import { createChromeManifest } from './ManifestChrome'; export const createFirefoxManifest = () => { const manifest = createChromeManifest(); delete manifest['offline_enabled']; delete manifest['background']['persistent']; return manifest; }; ================================================ FILE: packages/ManifestChrome.ts ================================================ /** * This template is used to generate 'build/manifest.json' by `npm run manifest` * In order to test some features only in 'dev' environment */ const manifest = { manifest_version: 2, name: 'github-vscode-icons', description: 'This extension shows a VS Code icons in Github Repositories', icons: { '128': 'icon128.png', '48': 'icon48.png', '16': 'icon16.png', }, version: '1.24', author: 'Daniel Derevjanik ', offline_enabled: true, browser_action: { default_icon: { '128': 'icon128.png', '48': 'icon48.png', }, }, background: { scripts: ['background.js'], persistent: false, }, web_accessible_resources: ['icons/*.svg', 'images/*.gif'], content_scripts: [ { css: ['content.css'], matches: ['*://*/*'], js: ['content.js'], run_at: 'document_idle', }, ], permissions: [ 'storage', '*://bitbucket.org/*', '*://github.com/*', '*://gist.github.com/*', '*://gitlab.com/*', '*://pastebin.com/*', '*://sourceforge.net/*', ], }; export const createChromeManifest = () => { if (process.env.NODE_ENV === 'development') { // FOR DEVELOPMENT; (manifest.browser_action as any)['default_popup'] = 'popup.html'; } return manifest; }; ================================================ FILE: packages/ManifestEdge.ts ================================================ /** * In order to make this extension works on Microsoft Edge, we need to edit chrome manifest */ import { createChromeManifest } from './ManifestChrome'; export const createEdgeManifest = () => { const manifest = createChromeManifest(); /** * API Bridge polyfill * https://docs.microsoft.com/en-us/microsoft-edge/extensions/guides/porting-chrome-extensions */ // @ts-ignore manifest['-ms-preload'] = { backgroundScript: 'backgroundScriptsAPIBridge.js', contentScript: 'contentScriptsAPIBridge.js', }; return manifest; }; ================================================ FILE: packages/background/Background.ts ================================================ import { LocalStorage, initialStorage, getStorage, setStorage, resetStorage } from '../common/LocalStorage'; import { onMessage, sendMessage } from '../common/Messenger'; onMessage(async (message, _, sendResponse) => { switch (message.type) { case 'STORAGE_GET': { const storage = await getStorage(); sendResponse(storage); break; } case 'STORAGE_SET': { const storage = message.storage; setStorage(storage); break; } case 'STORAGE_RESET': { resetStorage(); break; } } }); ================================================ FILE: packages/common/HostData.ts ================================================ import { SupportedHostings } from './SupportedHostings'; type HostData = { /** * Hosting full name */ fullName: string; /** * Favicon url */ favicon: string; /** * Used to match host url */ host: string; }; const hostData: { [H in SupportedHostings]: HostData } = { bitbucket: { fullName: 'Bitbucket', favicon: 'bitbucket-favicon.ico', host: 'bitbucket', }, github: { fullName: 'Github', favicon: 'github-favicon.ico', host: 'github', }, githubgist: { fullName: 'Github Gist', favicon: 'github-favicon.ico', host: 'gist.github', }, gitlab: { fullName: 'Gitlab', favicon: 'gitlab-favicon.ico', host: 'gitlab', }, pastebin: { fullName: 'Pastebin', favicon: 'pastebin-favicon.ico', host: 'pastebin', }, sourceforge: { fullName: 'Sourceforge', favicon: 'sourceforge-favicon.ico', host: 'sourceforge', }, }; export function getHostData(host: SupportedHostings) { return hostData[host]; } ================================================ FILE: packages/common/LocalStorage.ts ================================================ /** * This file is accessible only from extension's Background */ import { SupportedHostings } from './SupportedHostings'; export type LocalStorage = { /** * Extension version */ version: string; /** * List of showed/hidden icons for specific hosts */ showIcons: { [Hosting in SupportedHostings]: boolean }; }; export const initialStorage: LocalStorage = { version: chrome.runtime.getManifest().version, showIcons: { github: true, githubgist: false, gitlab: true, bitbucket: true, pastebin: false, sourceforge: true, }, }; export function getStorage(): Promise { return new Promise((resolve, reject) => { if (chrome.storage === undefined) { reject(new Error('Storage is not accessible from this part of extension')); } chrome.storage.local.get((storage) => { const store = storage as LocalStorage; if (store.version === undefined) { // When version doesn't exists, it means that storage is empty and user is running // extension for first time, so use initial storage chrome.storage.local.set(initialStorage); resolve(initialStorage); } resolve(store); }); }); } export function setStorage(storage: LocalStorage) { if (chrome.storage === undefined) { throw new Error('Storage is not accessible from this part of extension'); } chrome.storage.local.set(storage); } export function resetStorage() { if (chrome.storage === undefined) { throw new Error('Storage is not accessible from this part of extension'); } chrome.storage.local.set(initialStorage); return initialStorage; } ================================================ FILE: packages/common/Messenger.ts ================================================ import { LocalStorage } from './LocalStorage'; type CreateMessage = { type: Type } & Payload; type Message = | CreateMessage<'STORAGE_SET', { storage: LocalStorage }> | CreateMessage<'STORAGE_GET', {}> | CreateMessage<'STORAGE_RESET', {}>; export function sendMessage(message: Message) { return new Promise((resolve, _) => { chrome.runtime.sendMessage(message, (response) => { resolve(response); }); }); } export function onMessage(callback: (message: Message, sender: any, sendResponse: (response?: any) => void) => void) { chrome.runtime.onMessage.addListener((internalMessage, internalSender, internalSendResponse) => { callback(internalMessage, internalSender, internalSendResponse); return true; }); } ================================================ FILE: packages/common/SupportedHostings.ts ================================================ export type SupportedHostings = 'github' | 'githubgist' | 'gitlab' | 'bitbucket' | 'pastebin' | 'sourceforge'; ================================================ FILE: packages/content/Content.ts ================================================ // Internal import { LocalStorage } from '../common/LocalStorage'; import { sendMessage } from '../common/Messenger'; import { getHostData } from '../common/HostData'; import { SupportedHostings } from '../common/SupportedHostings'; import { showIconsForHosting } from './utils/showIconsForHosting'; // Supported pages import { initGithub } from './pages/GitHub'; import { initGitLab } from './pages/GitLab'; import { initBitBucket } from './pages/BitBucket'; import { initGistGithub } from './pages/GistGitHub'; import { initPasteBin } from './pages/PasteBin'; import { initSourceForge } from './pages/SourceForge'; const hostLocation = location.host; (async function () { const storage = (await sendMessage({ type: 'STORAGE_GET' })) as LocalStorage; const hosts = Object.keys(storage.showIcons) as SupportedHostings[]; for (const host of hosts) { const hostingData = getHostData(host); const isShowIconsTurnedOn = storage.showIcons[host]; if (isShowIconsTurnedOn && hostLocation.includes(hostingData.host)) { showIconsForHosting(host); break; // we don't need to iterate over another hostings when already displayed icons } } })(); ================================================ FILE: packages/content/data/PastebinSyntaxesToIcon.json ================================================ { "4CS": "", "6502 ACME Cross Assembler": "file_type_assembly.svg", "6502 Kick Assembler": "file_type_assembly.svg", "6502 TASM/64TASS": "file_type_assembly.svg", "ABAP": "", "ActionScript": "file_type_actionscript.svg", "ActionScript 3": "file_type_actionscript.svg", "Ada": "", "AIMMS": "", "ALGOL 68": "", "Apache Log": "", "AppleScript": "file_type_applescript.svg", "APT Sources": "", "ARM": "", "ASM (NASM)": "file_type_assembly.svg", "ASP": "file_type_asp.svg", "Asymptote": "", "autoconf": "", "Autohotkey": "file_type_autohotkey.svg", "AutoIt": "file_type_autoit.svg", "Avisynth": "", "Awk": "", "BASCOM AVR": "", "Bash": "file_type_shell.svg", "Basic4GL": "", "Batch": "file_type_shell.svg", "BibTeX": "", "Blitz Basic": "", "Blitz3D": "", "BlitzMax": "", "BNF": "", "BOO": "", "BrainFuck": "", "C": "file_type_c.svg", "C (WinAPI)": "file_type_c.svg", "C for Macs": "file_type_c.svg", "C Intermediate Language": "file_type_c.svg", "C#": "file_type_csharp.svg", "C++": "file_type_cpp.svg", "C++ (WinAPI)": "file_type_cpp.svg", "C++ (with Qt extensions)": "file_type_cpp.svg", "C: Loadrunner": "file_type_c.svg", "CAD DCL": "", "CAD Lisp": "", "Ceylon": "", "CFDG": "", "ChaiScript": "", "Chapel": "", "Clojure": "file_type_clojure.svg", "Clone C": "", "Clone C++": "", "CMake": "file_type_cmake.svg", "COBOL": "file_type_cobol.svg", "CoffeeScript": "file_type_coffeescript.svg", "ColdFusion": "", "CSS": "file_type_css.svg", "Cuesheet": "", "D": "file_type_dlang.svg", "Dart": "file_type_dartlang.svg", "DCL": "", "DCPU-16": "", "DCS": "", "Delphi": "", "Delphi Prism (Oxygene)": "", "Diff": "file_type_diff.svg", "DIV": "", "DOT": "", "E": "", "Easytrieve": "", "ECMAScript": "file_type_light_js.svg", "Eiffel": "", "Email": "", "EPC": "", "Erlang": "", "Euphoria": "", "F#": "file_type_fsharp.svg", "Falcon": "", "Filemaker": "", "FO Language": "", "Formula One": "", "Fortran": "file_type_fortran.svg", "FreeBasic": "", "FreeSWITCH": "", "GAMBAS": "", "Game Maker": "file_type_gamemaker.svg", "GDB": "", "Genero": "", "Genie": "", "GetText": "", "Go": "file_type_go.svg", "Groovy": "file_type_groovy.svg", "GwBasic": "", "Haskell": "file_type_haskell.svg", "Haxe": "file_type_haxe.svg", "HicEst": "", "HQ9 Plus": "", "HTML": "file_type_html.svg", "HTML 5": "file_type_html.svg", "Icon": "", "IDL": "", "INI file": "file_type_light_ini.svg", "Inno Script": "", "INTERCAL": "", "IO": "", "ISPF Panel Definition": "", "J": "", "Java": "file_type_java.svg", "Java 5": "file_type_java.svg", "JavaScript": "file_type_light_js.svg", "JCL": "", "jQuery": "file_type_light_js.svg", "JSON": "file_type_light_json.svg", "Julia": "file_type_julia.svg", "KiXtart": "", "Kotlin": "file_type_kotlin.svg", "Latex": "file_type_light_tex.svg", "LDIF": "", "Liberty BASIC": "", "Linden Scripting": "", "Lisp": "file_type_lisp.svg", "LLVM": "", "Loco Basic": "", "Logtalk": "", "LOL Code": "", "Lotus Formulas": "", "Lotus Script": "", "LScript": "", "Lua": "file_type_lua.svg", "M68000 Assembler": "", "MagikSF": "", "Make": "file_type_makefile.svg", "MapBasic": "", "Markdown": "file_type_markdown.svg", "MatLab": "file_type_matlab.png", "mIRC": "", "MIX Assembler": "", "Modula 2": "", "Modula 3": "", "Motorola 68000 HiSoft Dev": "", "MPASM": "", "MXML": "", "MySQL": "file_type_sql.svg", "Nagios": "", "NetRexx": "", "newLISP": "", "Nginx": "", "Nimrod": "", "None": "", "NullSoft Installer": "", "Oberon 2": "", "Objeck Programming Langua": "", "Objective C": "file_type_objectivec.svg", "OCalm Brief": "file_type_ocaml.svg", "OCaml": "file_type_ocaml.svg", "Octave": "", "Open Object Rexx": "", "OpenBSD PACKET FILTER": "", "OpenGL Shading": "", "Openoffice BASIC": "", "Oracle 11": "", "Oracle 8": "", "Oz": "", "ParaSail": "", "PARI/GP": "", "Pascal": "file_type_delphi.svg", "Pawn": "", "PCRE": "", "Per": "", "Perl": "file_type_perl.svg", "Perl 6": "file_type_perl.svg", "PHP": "file_type_php.svg", "PHP Brief": "file_type_php.svg", "Pic 16": "", "Pike": "", "Pixel Bender": "", "PL/I": "", "PL/SQL": "file_type_sql.svg", "PostgreSQL": "file_type_sql.svg", "PostScript": "", "POV-Ray": "", "Power Shell": "file_type_powershell.svg", "PowerBuilder": "", "ProFTPd": "", "Progress": "", "Prolog": "file_type_prolog.svg", "Properties": "", "ProvideX": "", "Puppet": "", "PureBasic": "", "PyCon": "", "Python": "file_type_python.svg", "Python for S60": "file_type_python.svg", "q/kdb+": "", "QBasic": "", "QML": "", "R": "file_type_r.svg", "Racket": "", "Rails": "", "RBScript": "", "REBOL": "", "REG": "", "Rexx": "", "Robots": "", "RPM Spec": "", "Ruby": "file_type_ruby.svg", "Ruby Gnuplot": "file_type_ruby.svg", "Rust": "file_type_rust.svg", "SAS": "", "Scala": "file_type_scala.svg", "Scheme": "", "Scilab": "file_type_scilab.svg", "SCL": "", "SdlBasic": "", "Smalltalk": "", "Smarty": "file_type_smarty.svg", "SPARK": "", "SPARQL": "", "SQF": "", "SQL": "file_type_sql.svg", "StandardML": "", "StoneScript": "", "SuperCollider": "", "Swift": "file_type_swift.svg", "SystemVerilog": "", "T-SQL": "", "TCL": "", "Tera Term": "", "thinBasic": "", "TypoScript": "", "Unicon": "", "UnrealScript": "", "UPC": "", "Urbi": "", "Vala": "", "VB.NET": "file_type_vb.svg", "VBScript": "file_type_vb.svg", "Vedit": "", "VeriLog": "", "VHDL": "", "VIM": "", "Visual Pro Log": "", "VisualBasic": "file_type_vb.svg", "VisualFoxPro": "", "WhiteSpace": "", "WHOIS": "", "Winbatch": "", "XBasic": "", "XML": "file_type_xml.svg", "Xorg Config": "", "XPP": "", "YAML": "file_type_light_yaml.svg", "Z80 Assembler": "", "ZXBasic": "" } ================================================ FILE: packages/content/pages/BitBucket.ts ================================================ import { getIconForFile, getIconForFolder, getIconForOpenFolder, getIconUrl, DEFAULT_ROOT } from '../utils/Icons'; import { getFileIcon, getFolderIcon } from '../utils/Dev'; import { isBitBucketRepo } from '../utils/PageDetect'; import { mutate } from 'fastdom'; export const QUERY_FILE_TABLE_ROWS = 'table[data-qa="repository-directory"] > tbody > tr'; export const QUERY_ICONS_TO_REPLACE = `${QUERY_FILE_TABLE_ROWS} a svg`; function showRepoTreeIcons() { if (!isBitBucketRepo()) return; if (!document.querySelector(QUERY_FILE_TABLE_ROWS) || !document.querySelector(QUERY_ICONS_TO_REPLACE)) return; const treeItems = document.querySelectorAll(QUERY_FILE_TABLE_ROWS); for (let i = 0; i < treeItems.length; i++) { /** * [TR: * [TD: [DIV: [A: [SPAN: [SVG: icon]]]]] * [TD: [A: name]] * ] */ const itemEl = treeItems[i] as HTMLDivElement; const iconAnchorEl = itemEl.firstChild!.firstChild!.firstChild! as HTMLAnchorElement; const iconEl = iconAnchorEl.firstChild! as HTMLSpanElement; const nameAnchorEl = itemEl.children[1].firstChild! as HTMLAnchorElement; if (document.querySelector(`${QUERY_FILE_TABLE_ROWS}:nth-child(${i + 1}) img.vscode-icon.bb-icon`)) { continue; } const newIconEl = document.createElement('img'); newIconEl.setAttribute('class', 'vscode-icon bb-icon'); const replaceNodeIfExists = (newIconEl: HTMLImageElement) => { // used to prevent replacing of none existing nodes if (!document.querySelector(`${QUERY_FILE_TABLE_ROWS}:nth-child(${i + 1}) img.vscode-icon.bb-icon`)) { iconAnchorEl.replaceChild(newIconEl, iconEl); } }; if (iconAnchorEl.href === '..') { // .. continue; } else if (iconAnchorEl.href.endsWith('/')) { // FOLDER const name = nameAnchorEl.innerText.toLowerCase(); const iconPath = getFolderIcon(name); mutate(() => { newIconEl.setAttribute('src', getIconUrl(iconPath)); replaceNodeIfExists(newIconEl); }); } else if (itemEl.className.includes('subreponame')) { // TODO: SUBMODULE const iconEl = itemEl.firstElementChild! as HTMLSpanElement; mutate(() => { newIconEl.setAttribute('src', getIconUrl(getIconForFolder('submodules'))); replaceNodeIfExists(newIconEl); }); } else { // FILE const name = nameAnchorEl.innerText.toLowerCase(); const iconPath = getFileIcon(name); mutate(() => { newIconEl.setAttribute('src', getIconUrl(iconPath)); replaceNodeIfExists(newIconEl); }); } } } function update(e?: any) { showRepoTreeIcons(); } export function initBitBucket() { update(); window.addEventListener('message', update); } ================================================ FILE: packages/content/pages/GistGitHub.ts ================================================ import { isGist } from 'github-url-detection'; import { getIconForFile, getIconUrl } from '../utils/Icons'; import { mutate } from 'fastdom'; export const QUERY_FILE_INFO = '.file-info'; const showGistIcons = async () => { const fileInfos = document.querySelectorAll(QUERY_FILE_INFO); for (let i = 0; i < fileInfos.length; i++) { /** * [DIV: * [SPAN: [SVG: icon]], * [A: [STRONG: name]] * ] */ const fileInfo = fileInfos[i] as HTMLDivElement; const gistName = (fileInfo.lastElementChild!.firstElementChild as HTMLSpanElement).innerText; const iconPath = getIconForFile(gistName); mutate(() => { fileInfo.firstElementChild!.innerHTML = `icon`; }); } }; function update(e?: any) { if (isGist()) { showGistIcons(); } } export function initGistGithub() { update(); } ================================================ FILE: packages/content/pages/GitHub.ts ================================================ import { getIconForFolder, getIconForOpenFolder, getIconForFile, getIconUrl, DEFAULT_ROOT_OPENED, DEFAULT_ROOT, DEFAULT_FILE, } from '../utils/Icons'; import { isCommit, isRepoRoot, isSingleFile, isRepoTree } from 'github-url-detection'; import { isHistoryForFile } from '../utils/PageDetect'; import { mutate } from 'fastdom'; import { getFileIcon, getFolderIcon } from '../utils/Dev'; import { observe } from 'selector-observer'; export const QUERY_FILE_TABLE_ITEMS = 'div.js-navigation-container>div.js-navigation-item'; export const QUERY_PATH_SEGMENTS = '.repository-content .js-path-segment a'; export const QUERY_PJAX_CONTAINER = 'main'; export const QUERY_LAST_PATH_SEGMENT = '.final-path'; /** * Show icon for path segments */ function showIconsForSegments() { if (!((!isRepoRoot() && isRepoTree()) || isSingleFile() || isHistoryForFile())) return; const aSegments = document.querySelectorAll(QUERY_PATH_SEGMENTS); const firstSegment = aSegments[0]; const finalSegment = document.querySelector(QUERY_LAST_PATH_SEGMENT) as HTMLSpanElement | undefined; // first segment has always root folder icon if (firstSegment) { const spanEl = firstSegment.children[0] as HTMLSpanElement; spanEl.innerHTML = `icon ${ spanEl.innerText }`; } // check if final segment is file or folder if (finalSegment) { const iconPath = window.location.href.includes('/blob/') ? getIconForFile(finalSegment.innerText) : getIconForOpenFolder(finalSegment.innerText); finalSegment.innerHTML = `icon ${ finalSegment.innerText }`; } // segments between first and last are always folders for (let i = 1; i < aSegments.length; i++) { const spanEl = aSegments[i]; const aEl = spanEl.firstChild as HTMLAnchorElement; const iconPath = getIconForOpenFolder(aEl.innerText); aEl.innerHTML = `icon ${aEl.innerText}`; } } /** * Show icons for repository files */ function showRepoTreeIcons(rowEl: Element) { const iconEl = rowEl.children[0] as HTMLTableCellElement; const iconSVGEl = iconEl.querySelector('.octicon'); if (!iconSVGEl) { // ... (up) return; } /** *
*
, * , * , *
{time}, *
*/ const contentEl = rowEl.children[1] as Element; const linkToEl = contentEl.firstElementChild.firstElementChild as HTMLAnchorElement; let iconPath = ''; if (iconSVGEl) { const iconSVGClassName = iconSVGEl.className.baseVal; if (iconSVGClassName.includes('octicon-file-text') || iconSVGClassName.includes('octicon-file ')) { iconPath = getFileIcon(linkToEl.innerText.toLowerCase()); } else if (iconSVGClassName.includes('octicon-file-directory')) { const name = linkToEl.innerText.toLowerCase(); iconPath = getFolderIcon(name.split('/').shift()); } else if (iconSVGClassName.includes('octicon-file-submodule')) { iconPath = getIconForFolder('submodules'); } else if (iconSVGClassName.includes('octicon-file-symlink-file')) { iconPath = DEFAULT_FILE; } else if (iconSVGClassName.includes('octicon-file-symlink-directory')) { iconPath = DEFAULT_FILE; } else { console.error(`Unknown filetype: "${iconSVGClassName}", please report`); return; } const x = mutate(() => { iconSVGEl.outerHTML = `icon`; }); } // else { // console.error(`Error during parsing: "td.icon > svg.octoicon" doesnt exists for ${i}. row`); // } } function update(e?: any) { showIconsForSegments(); if (isCommit()) { // showDiffIcon(); } } export function initGithub() { // Update on fragment update observe(QUERY_FILE_TABLE_ITEMS, { add(rowEl) { showRepoTreeIcons(rowEl); }, }); update(); document.addEventListener('pjax:end', update); // Update on page change } ================================================ FILE: packages/content/pages/GitLab.ts ================================================ import { getIconForFile, getIconForFolder, getIconForOpenFolder, getIconUrl } from '../utils/Icons'; import { isGitLabRepo } from '../utils/PageDetect'; import { mutate } from 'fastdom'; import { getFolderIcon, getFileIcon } from '../utils/Dev'; export const QUERY_TREE_ITEMS = '.tree-item'; function showRepoTreeIcons() { const treeItems = document.querySelectorAll(QUERY_TREE_ITEMS); for (let i = 0; i < treeItems.length; i++) { /** * [TR: * [TD: [[I: icon], [A: [SPAN: name]]]], * [TD: [SPAN: [A: message]]], * [TD: [TIME: ago]] * ] */ const itemEl = treeItems[i]; const newIconEl = document.createElement('img'); const iconAndNameEls = itemEl.firstElementChild!; const iconEl = iconAndNameEls.firstElementChild!; const nameEl = iconAndNameEls.lastElementChild as HTMLAnchorElement; const name = nameEl.innerText.toLowerCase(); if (i === 0 && name === '..') { continue; } const iconPath = nameEl.href.indexOf('/tree/') > 0 ? getFolderIcon(name) : getFileIcon(name); mutate(() => { newIconEl.setAttribute('src', getIconUrl(iconPath)); newIconEl.setAttribute('class', 'vscode-icon'); iconAndNameEls.replaceChild(newIconEl, iconEl); }); } } function update(e?: any) { if (isGitLabRepo()) { showRepoTreeIcons(); } } export function initGitLab() { update(); } ================================================ FILE: packages/content/pages/PasteBin.ts ================================================ import { getIconForPBSyntax, getIconUrl, DEFAULT_FILE } from '../utils/Icons'; import { isPastebinUserList, isPasteOpen } from '../utils/PageDetect'; import { mutate } from 'fastdom'; const QUERY_PASTEBIN_ITEMS = '.maintable>tbody>tr'; const QUERY_PASTEBIN_PASTE = '#code_buttons>span:last-child'; function showIconsForFiles() { const pastes = document.querySelectorAll(QUERY_PASTEBIN_ITEMS); // skip first tr, which is header for (let i = 1; i < pastes.length; i++) { /** * [TR: * [TD: [[IMAGE: icon], [A: name]]], * [TD: added], * [TD: expires], * [TD: hits], * [TD: [A: syntax]], * [TD: ?] * ] */ const item = pastes[i]; const iconAndNameEl = item.firstElementChild as HTMLTableDataCellElement; const iconEl = iconAndNameEl.firstElementChild as HTMLImageElement; const syntaxEl = item.childNodes[9] as HTMLAnchorElement; const syntaxName = syntaxEl.innerText; const iconPath = getIconForPBSyntax(syntaxName); const newIconEl = document.createElement('img'); mutate(() => { newIconEl.setAttribute('src', getIconUrl(iconPath)); newIconEl.setAttribute('class', 'vscode-icon vsi-pb'); iconAndNameEl.replaceChild(newIconEl, iconEl); }); } } function showIconForPaste() { // TODO: } const domLoaded = new Promise((resolve) => { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', resolve); } else { resolve(null); } }); function update(e?: any) { if (isPastebinUserList) { showIconsForFiles(); } else if (isPasteOpen) { showIconForPaste(); } } export function initPasteBin() { update(); } ================================================ FILE: packages/content/pages/SourceForge.ts ================================================ import { getIconForFile, getIconForFolder, getIconUrl } from '../utils/Icons'; import { isSourceForgeFiles } from '../utils/PageDetect'; import { mutate } from 'fastdom'; import { getFolderIcon, getFileIcon } from '../utils/Dev'; export const QUERY_SOURCEFORGE_ITEMS = '#files_list>tbody>tr'; function showIconsForFiles() { const items = document.querySelectorAll(QUERY_SOURCEFORGE_ITEMS); for (let i = 0; i < items.length; i++) { const item = items[i]; const newIconEl = document.createElement('img'); newIconEl.setAttribute('class', 'vscode-icon sf-icon'); const iconAndNameEl = item.firstElementChild.firstElementChild as HTMLTableHeaderCellElement; const isFolder = item.className.includes('folder'); if (isFolder) { /** * [TR: * [TH: [A: [SVG: icon], [SPAN: folderName]]], * [TD: [ABBR: date]], * [TD: size], * [TD: [DIV: Populated by JS], [DIV: [A: chart]]], * ] */ const iconEl = iconAndNameEl.firstElementChild as SVGAElement; const nameEl = iconAndNameEl.lastElementChild as HTMLAnchorElement; const name = nameEl.innerText.toLowerCase(); const iconPath = getFolderIcon(name); mutate(() => { newIconEl.setAttribute('src', getIconUrl(iconPath)); iconAndNameEl.replaceChild(newIconEl, iconEl); }); } else { /** * [TR: * [TH: [A: [SVG: icon]]], * [TD: [ABBR: date]], * [TD: size], * [TD: [DIV: Populated by JS], [DIV: [A: chart]]], * ] */ const nameEl = iconAndNameEl.firstElementChild as HTMLAnchorElement; const name = nameEl.innerText.toLowerCase(); const iconPath = getFileIcon(name); mutate(() => { newIconEl.setAttribute('src', getIconUrl(iconPath)); iconAndNameEl.insertBefore(newIconEl, nameEl); }); } } } function update(e?: any) { if (isSourceForgeFiles()) { showIconsForFiles(); } } export function initSourceForge() { update(); } ================================================ FILE: packages/content/utils/Dev.ts ================================================ import * as VSCJS from 'vscode-icons-js'; export const getFolderIcon = process.env.NODE_ENV === 'production' ? VSCJS.getIconForFolder : (folderName: string): string => { const folderIcon = VSCJS.getIconForFolder(folderName); if (folderIcon === VSCJS.DEFAULT_FOLDER) { save('FOLDER', folderName); } return folderIcon; }; export const getFileIcon = process.env.NODE_ENV === 'production' ? VSCJS.getIconForFile : (filename: string): string => { const fileIcon = VSCJS.getIconForFile(filename); if (fileIcon === VSCJS.DEFAULT_FILE) { save('FILE', filename); } return fileIcon; }; type Items = { folders: { [folderName: string]: number; }; files: { [fileName: string]: number; }; }; /** * Save name of file/folder that doesn't have an icon */ export const save = (type: 'FOLDER' | 'FILE', name: string) => { console.log('tracking: ', type, name); const allItemsStr = localStorage.getItem('items'); if (allItemsStr) { const items = JSON.parse(allItemsStr) as Items; const names = type === 'FOLDER' ? items.folders : items.files; if (name in names) { names[name] = names[name] + 1; } else { names[name] = 1; } localStorage.setItem('items', JSON.stringify(items)); } else { const items = { folders: {}, files: {} } as Items; const names = type === 'FOLDER' ? items.folders : items.files; names[name] = 1; localStorage.setItem('items', JSON.stringify(items)); } }; /** * Load name of file/folder that doesn't have an icon */ export const load = (): Items => { const allItemsStr = localStorage.getItem('items'); if (allItemsStr) { return JSON.parse(allItemsStr); } else { return { files: {}, folders: {}, }; } }; ================================================ FILE: packages/content/utils/Icons.ts ================================================ type NAME_TO_ICON = { [name: string]: string }; export { getIconForFile, getIconForFolder, getIconForOpenFolder, DEFAULT_FILE, DEFAULT_FOLDER, DEFAULT_FOLDER_OPENED, DEFAULT_ROOT_OPENED, DEFAULT_ROOT, } from 'vscode-icons-js'; import { DEFAULT_FILE } from 'vscode-icons-js'; const PBSyntaxesToIcon = require('../data/PastebinSyntaxesToIcon.json') as NAME_TO_ICON; /** * Retrieve url of icon within chrome */ export const getIconUrl = (iconFileName: string) => chrome.runtime.getURL('icons/' + iconFileName); /** * Get icon for a pastebin syntaxes * @desc list of supported syntaxes https://pastebin.com/languages * @param syntaxName name of syntax to icon for * @return icon filename */ export function getIconForPBSyntax(syntaxName: string) { const syntaxIcon = PBSyntaxesToIcon[syntaxName]; if (syntaxIcon !== undefined && syntaxIcon !== '') { return syntaxIcon; } return DEFAULT_FILE; } ================================================ FILE: packages/content/utils/PageDetect.ts ================================================ import * as select from 'select-dom'; import { isRepo, utils } from 'github-url-detection'; export const isHistoryForFile = () => isRepo() && /^\/commits\/[0-9a-f]{5,40}\/.+/.test(utils.getRepoPath()); /** * BitBucket related detections */ export const isBitBucketRepo = () => location.href.indexOf('bitbucket.org/') > 0; /** * GitLab related detections */ export const isGitLabRepo = () => select.exists('.tree-content-holder'); /** * Pastebin related detections */ export const isPastebinUserList = () => location.href.indexOf('pastebin.com/u/') > 0 && select.exists('table.maintable'); export const isPasteOpen = () => select.exists('#code_frame2'); /** * SourceForge related detections */ export const isSourceForgeFiles = () => select.exists('#files_list'); ================================================ FILE: packages/content/utils/showIconsForHosting.ts ================================================ import { SupportedHostings } from '../../common/SupportedHostings'; import { initBitBucket } from '../pages/BitBucket'; import { initGistGithub } from '../pages/GistGitHub'; import { initGithub } from '../pages/GitHub'; import { initGitLab } from '../pages/GitLab'; import { initPasteBin } from '../pages/PasteBin'; import { initSourceForge } from '../pages/SourceForge'; /** * @param host - will show icons on page for host */ export function showIconsForHosting(host: SupportedHostings) { const funcsToShowIcons: { [H in SupportedHostings]: () => void } = { bitbucket: initBitBucket, githubgist: initGistGithub, github: initGithub, gitlab: initGitLab, pastebin: initPasteBin, sourceforge: initSourceForge, }; funcsToShowIcons[host](); } ================================================ FILE: packages/popup/Popup.tsx ================================================ import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { LocalStorage } from '../common/LocalStorage'; import { sendMessage } from '../common/Messenger'; import { getHostData } from '../common/HostData'; type State = { storage: LocalStorage; isSomethingChanged: boolean; }; type Props = { storage: LocalStorage; }; class Popup extends React.Component { constructor(props: Props) { super(props); this.state = { storage: props.storage, isSomethingChanged: false, }; } handleToggleClick = (hosting: keyof LocalStorage['showIcons']) => { const prevStorage = this.state.storage; const newStorage: LocalStorage = { ...prevStorage, showIcons: { ...prevStorage.showIcons, [hosting]: !prevStorage.showIcons[hosting], }, }; sendMessage({ type: 'STORAGE_SET', storage: newStorage }); this.setState({ storage: newStorage, isSomethingChanged: true, }); }; handleResetButton = async () => { const defaultState = (await sendMessage({ type: 'STORAGE_RESET' })) as LocalStorage; this.setState({ storage: defaultState, }); }; render() { const hostings = Object.keys(this.props.storage.showIcons) as (keyof LocalStorage['showIcons'])[]; const changedText = this.state.isSomethingChanged ? (

In order to see changes on pages, please reload them using refresh button

) : null; return (

display icons for:

{hostings.map((hosting, index) => { const hostData = getHostData(hosting); return (
); })} {changedText}
{/* */}
); } } (async function () { const storage = (await sendMessage({ type: 'STORAGE_GET' })) as LocalStorage; ReactDOM.render(, document.getElementById('app') as HTMLDivElement); })(); ================================================ FILE: scripts/create-manifest.ts ================================================ /** * Compress build/ folder to create archive which will be consumed by browser */ import { script } from './utils'; import { writeFileSync } from 'fs'; import { createChromeManifest } from '../packages/ManifestChrome'; import { createEdgeManifest } from '../packages/ManifestEdge'; import { createFirefoxManifest } from '../packages/ManifesFirefox'; if (process.env.BROWSER) { script(__filename, `Creating manifest.json`, (_, exit) => { let manifest; switch(process.env.BROWSER) { case 'EDGE': { manifest = createEdgeManifest(); break; } case 'FIREFOX': { manifest = createFirefoxManifest(); break; } case 'CHROME': { manifest = createChromeManifest(); break; } default: { throw new Error(`unknown BROWSER env '${process.env.BROWSER}'. Please use 'EDGE', 'FIREFOX' or 'CHROME'`); } } const manifestJSON = JSON.stringify(manifest, null, 2); writeFileSync('./build/manifest.json', manifestJSON); exit(); }); } else { throw new Error('No browser selected, please add BROWSER env'); } ================================================ FILE: scripts/make-dist-zip.script.ts ================================================ /** * Compress build/ folder to create archive which will be consumed by browser */ import { script } from './utils'; import { createWriteStream } from 'fs'; import * as Archiver from 'archiver'; const manifest = require('../build/manifest.json'); const manifestVersion = manifest.version; const archiveName = 'github-vsci'; if (process.env.BROWSER && ['CHROME', 'FIREFOX', 'EDGE'].includes(process.env.BROWSER)) { const name = process.env.BROWSER.toLowerCase(); script(__filename, `Creating '${name}-${archiveName}-${manifestVersion}.zip' ready to upload to stores`, ({ log, Ch }, exit) => { const distZip = createWriteStream(`${process.cwd()}/dist/${name}-${archiveName}-${manifestVersion}.zip`); const archive = Archiver('zip', { zlib: { level: 9 } }); // On end, print total bytes distZip.on('close', () => { log(archive.pointer() + ' total bytes'); log(Ch.green(`> '${name}-${archiveName}-${manifestVersion}.zip' file created`)); exit(); }); archive.pipe(distZip); archive.directory('./build', false); archive.finalize(); }); } else { throw new Error('Please, set BROWSER env to CHROME, FIREFOX or EDGE'); } ================================================ FILE: scripts/utils.ts ================================================ import * as Path from 'path'; import * as Ch from 'chalk'; const log = console.log; export async function script(filename: string, desc: string, callback: (tools: { log: Console['log'], Ch: typeof Ch }, exit: (error?: any) => void) => Promise | void) { const baseName = Path.basename(filename); log(Ch.bgYellow(`(${baseName}) ${desc}`)); const sTime = Date.now(); try { callback({ log, Ch }, (error?: any) => { const diff = Date.now() - sTime; if (error) { console.log(`Execution time: ${Ch.bgRed(diff.toString() + 'ms')}`); } else { console.log(`Execution time: ${Ch.bgGreen(diff.toString() + 'ms')}`); } }); } catch (error) { const diff = Date.now() - sTime; console.log(`Execution time: ${Ch.bgRed(diff.toString() + 'ms')}`); } } ================================================ FILE: tests/packages/content/pages/BitBucket.test.ts ================================================ import { fetchRenderedDocument,SITE_RETRIEVE_TIMEOUT } from '../../../utils'; import { QUERY_FILE_TABLE_ROWS, QUERY_ICONS_TO_REPLACE } from '../../../../packages/content/pages/BitBucket'; describe('Test Bitbucket queries', () => { it('Repo root', async () => { const renderedDocument = await fetchRenderedDocument('https://bitbucket.org/pypa/distlib/src/master/'); expect(renderedDocument.querySelectorAll(QUERY_FILE_TABLE_ROWS).length).not.toBe(0); expect(renderedDocument.querySelectorAll(QUERY_ICONS_TO_REPLACE).length).not.toBe(0); },SITE_RETRIEVE_TIMEOUT); it('Subfolder with filetable', async () => { const renderedDocument = await fetchRenderedDocument('https://bitbucket.org/pypa/distlib/src/master/tests/'); expect(renderedDocument.querySelectorAll(QUERY_FILE_TABLE_ROWS).length).not.toBe(0); expect(renderedDocument.querySelectorAll(QUERY_ICONS_TO_REPLACE).length).not.toBe(0); },SITE_RETRIEVE_TIMEOUT); it('Open file', async () => { const renderedDocument = await fetchRenderedDocument( 'https://bitbucket.org/pypa/distlib/src/master/README.rst', null ); expect(renderedDocument.querySelectorAll(QUERY_FILE_TABLE_ROWS).length).toBe(0); expect(renderedDocument.querySelectorAll(QUERY_ICONS_TO_REPLACE).length).toBe(0); },SITE_RETRIEVE_TIMEOUT); }); ================================================ FILE: tests/packages/content/pages/GistGitHub.test.ts ================================================ import { fetchDocument,SITE_RETRIEVE_TIMEOUT } from '../../../utils'; import { QUERY_FILE_INFO } from '../../../../packages/content/pages/GistGitHub'; it('Test GistGitHub query', async () => { const fetchedDocument = await fetchDocument('https://gist.github.com/spences10/5c492e197e95158809a83650ff97fc3a'); expect(fetchedDocument.querySelectorAll(QUERY_FILE_INFO).length).not.toBe(0); }, SITE_RETRIEVE_TIMEOUT); ================================================ FILE: tests/packages/content/pages/GitHub.test.ts ================================================ /** * @jest-environment jsdom */ import { fetchDocument, SITE_RETRIEVE_TIMEOUT } from '../../../utils'; import { QUERY_FILE_TABLE_ITEMS, QUERY_PATH_SEGMENTS, QUERY_PJAX_CONTAINER, QUERY_LAST_PATH_SEGMENT } from '../../../../packages/content/pages/GitHub'; describe('Test Github queries', () => { it('Repo root', async () => { const fetchedDocument = await fetchDocument('https://github.com/dderevjanik/github-vscode-icons'); expect(fetchedDocument.querySelectorAll(QUERY_FILE_TABLE_ITEMS).length).not.toBe(0); expect(fetchedDocument.querySelectorAll(QUERY_PATH_SEGMENTS).length).toBe(0); expect(fetchedDocument.querySelectorAll(QUERY_PJAX_CONTAINER).length).not.toBe(0); expect(fetchedDocument.querySelectorAll(QUERY_LAST_PATH_SEGMENT).length).toBe(0); }, SITE_RETRIEVE_TIMEOUT); it('Subfolder with filetable', async () => { const fetchedDocument = await fetchDocument( 'https://github.com/dderevjanik/github-vscode-icons/tree/master/packages/content/pages' ); expect(fetchedDocument.querySelectorAll(QUERY_FILE_TABLE_ITEMS).length).not.toBe(0); expect(fetchedDocument.querySelectorAll(QUERY_PATH_SEGMENTS).length).not.toBe(0); expect(fetchedDocument.querySelectorAll(QUERY_PJAX_CONTAINER).length).not.toBe(0); expect(fetchedDocument.querySelectorAll(QUERY_LAST_PATH_SEGMENT).length).not.toBe(0); }, SITE_RETRIEVE_TIMEOUT); it('Open file', async () => { const fetchedDocument = await fetchDocument( 'https://github.com/dderevjanik/github-vscode-icons/blob/master/packages/content/pages/GitHub.ts' ); expect(fetchedDocument.querySelectorAll(QUERY_FILE_TABLE_ITEMS).length).toBe(0); expect(fetchedDocument.querySelectorAll(QUERY_PATH_SEGMENTS).length).not.toBe(0); expect(fetchedDocument.querySelectorAll(QUERY_PJAX_CONTAINER).length).not.toBe(0); expect(fetchedDocument.querySelectorAll(QUERY_LAST_PATH_SEGMENT).length).not.toBe(0); }, SITE_RETRIEVE_TIMEOUT); }); ================================================ FILE: tests/packages/content/pages/GitLab.test.ts ================================================ import { fetchRenderedDocument, SITE_RETRIEVE_TIMEOUT} from '../../../utils'; import { QUERY_TREE_ITEMS } from '../../../../packages/content/pages/GitLab'; describe('Test Gitlab queries', () => { it('Repo root', async () => { const renderedDocument = await fetchRenderedDocument('https://gitlab.com/pycqa/flake8', '.tree-table'); expect(renderedDocument.querySelectorAll(QUERY_TREE_ITEMS).length).not.toBe(0); }, SITE_RETRIEVE_TIMEOUT); it('Subfolder with filetable', async () => { const renderedDocument = await fetchRenderedDocument( 'https://gitlab.com/pycqa/flake8/-/tree/master/src/flake8', '.tree-table' ); expect(renderedDocument.querySelectorAll(QUERY_TREE_ITEMS).length).not.toBe(0); }, SITE_RETRIEVE_TIMEOUT); it('Open file', async () => { const renderedDocument = await fetchRenderedDocument( 'https://gitlab.com/pycqa/flake8/-/blob/master/src/flake8/__init__.py', null ); expect(renderedDocument.querySelectorAll(QUERY_TREE_ITEMS).length).toBe(0); }, SITE_RETRIEVE_TIMEOUT); }); ================================================ FILE: tests/packages/content/pages/SourceForge.test.ts ================================================ import { fetchDocument, SITE_RETRIEVE_TIMEOUT } from '../../../utils'; import { QUERY_SOURCEFORGE_ITEMS } from '../../../../packages/content/pages/SourceForge'; describe('Test SourceForge queries', () => { it('Repo root', async () => { const fetchedDocument = await fetchDocument('https://sourceforge.net/projects/python-fire.mirror/files/'); expect(fetchedDocument.querySelectorAll(QUERY_SOURCEFORGE_ITEMS).length).not.toBe(0); }, SITE_RETRIEVE_TIMEOUT); it('Subfolder with filetable', async () => { const fetchedDocument = await fetchDocument('https://sourceforge.net/projects/python-fire.mirror/files/v0.3.1/'); expect(fetchedDocument.querySelectorAll(QUERY_SOURCEFORGE_ITEMS).length).not.toBe(0); }, SITE_RETRIEVE_TIMEOUT); }); ================================================ FILE: tests/tsconfig.tests.json ================================================ { "extends": "../tsconfig.json", "compilerOptions": { "esModuleInterop": true, "noImplicitAny": false /* Raise error on expressions and declarations with an implied 'any' type. */ } } ================================================ FILE: tests/utils.ts ================================================ import { JSDOM } from 'jsdom'; import fetch from 'node-fetch'; import { table } from 'console'; export const SITE_RETRIEVE_TIMEOUT = 30000; export const getElementFromSource = (elementSource: string): Document => { const dom = new JSDOM(elementSource); return dom.window.document; // const parser = new DOMParser(); // return parser.parseFromString(elementSource, 'text/html').documentElement; }; export const fetchDocument = async (url: string): Promise => { const response = await fetch(url); const pageSource = await response.text(); return getElementFromSource(pageSource); }; export const fetchRenderedDocument = async (url: string, waitSelector: string | null = 'table'): Promise => { await page.goto(url, { waitUntil: 'networkidle2' }); if (waitSelector !== null) { await page.waitForSelector(waitSelector); } const renderedPageSource = await page.evaluate(() => { const nrOfFoundTables = document.querySelector('html').outerHTML; return nrOfFoundTables; }); return getElementFromSource(renderedPageSource); }; ================================================ FILE: tsconfig.json ================================================ { "compilerOptions": { /* Basic Options */ "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */, "module": "commonjs" /* Specify module code generation: 'none', commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, "lib": ["dom", "es2015", "es6", "es7"] /* Specify library files to be included in the compilation: */, "allowJs": true /* Allow javascript files to be compiled. */, "checkJs": true /* Report errors in .js files. */, "jsx": "react" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */, // "declaration": true, /* Generates corresponding '.d.ts' file. */ // "sourceMap": true, /* Generates corresponding '.map' file. */ // "outFile": "./", /* Concatenate and emit output to single file. */ // "outDir": "./", /* Redirect output structure to the directory. */ // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ // "removeComments": true, /* Do not emit comments to output. */ // "noEmit": true, /* Do not emit outputs. */ // "importHelpers": true, /* Import emit helpers from 'tslib'. */ // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ /* Strict Type-Checking Options */ "strict": true /* Enable all strict type-checking options. */, "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */, "strictNullChecks": false /* Enable strict null checks. */, // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ /* Additional Checks */ // "noUnusedLocals": true, /* Report errors on unused locals. */ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ "typeRoots": ["node_modules/@types", "typings"] /* List of folders to include type definitions from. */ // "types": [], /* Type declaration files to be included in compilation. */ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ /* Source Map Options */ // "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ // "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */ // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ /* Experimental Options */ // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ // "skipLibCheck": true }, "include": ["./packages/**/*.d.ts", "./scripts/**/*.ts"], "exclude": ["node_modules"] } ================================================ FILE: typings/fastdom/index.d.ts ================================================ declare module 'fastdom' { /** * Clears any scheduled job. */ export const clear: () => void; /** * Schedules a job for the 'measure' queue. Returns a unique ID that can be used to clear the scheduled job. */ export const measure: (callback: () => void) => void; /** * Schedules a job for the 'mutate' queue. Returns a unique ID that can be used to clear the scheduled job. */ export const mutate: (callback: () => void) => void; export const extend: () => void; } ================================================ FILE: typings/icons.d.ts ================================================ declare module '*icons.json' { const json: { iconDefinitions: { [iconKey: string]: { iconPath: string } }; folderNames: { [folderName: string]: string }; fileExtensions: { [fileExtension: string]: string; }; fileNames: { [fileName: string]: string }; languagesIds: { [languageId: string]: string }; light: { folderNames: { [folderName: string]: string }; fileExtensions: { [fileExtension: string]: string; }; fileNames: { [fileName: string]: string }; languagesIds: { [languageId: string]: string }; }; }; export default json; } ================================================ FILE: typings/languages-vscode.d.ts ================================================ declare module '*languages-vscode.json' { const json: { [languageId: string]: { extensions: string[]; filenames: string[]; }; }; export default json; } ================================================ FILE: typings/languages-vsi.d.ts ================================================ declare module '*languages-vsi.json' { const json: { [languageId: string]: { defaultExtension: string; }; }; export default json; } ================================================ FILE: typings/select-dom/index.d.ts ================================================ declare module 'select-dom' { /** * Check if any element with inserted query exists */ export function exists(query: string): boolean; } ================================================ FILE: webpack.config.js ================================================ const path = require('path'); const Webpack = require('webpack'); const baseConfig = { devtool: 'source-map', entry: { content: './packages/content/Content.ts', popup: './packages/popup/Popup.tsx', background: './packages/background/Background.ts' }, output: { path: path.resolve(__dirname, 'build'), filename: '[name].js' }, devServer: { contentBase: __dirname + '/public' }, resolve: { // Add '.ts' and '.tsx' as a resolvable extension. extensions: ['.webpack.js', '.web.js', '.ts', '.tsx', '.js', '.json'] }, module: { rules: [ // all files with a '.ts' or '.tsx' extension will be handled by 'ts-loader' { test: /\.tsx?$/, use: 'ts-loader' } ] }, plugins: [] }; module.exports = baseConfig;