Refactor code base for better enhancement and approach
11
.editorconfig
Normal file
@ -0,0 +1,11 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
indent_style = tab
|
@ -1,11 +1,11 @@
|
||||
{
|
||||
"extends": ["airbnb", "prettier"],
|
||||
"plugins": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": ["error"]
|
||||
},
|
||||
"globals": {
|
||||
"window": true,
|
||||
"document": true
|
||||
}
|
||||
}
|
||||
"extends": ["airbnb", "prettier"],
|
||||
"plugins": ["prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": ["error"]
|
||||
},
|
||||
"globals": {
|
||||
"window": true,
|
||||
"document": true
|
||||
}
|
||||
}
|
||||
|
137
.gitignore
vendored
@ -1,125 +1,18 @@
|
||||
dist/
|
||||
temp/
|
||||
.vscode/
|
||||
material-icons-github-chrome-extension.zip
|
||||
material-icons-firefox-extension.zip
|
||||
src/iconsCache.js
|
||||
src/iconMap.json
|
||||
optimizedSVGs/
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
# Directories/files that may be generated by this project
|
||||
dist
|
||||
temp
|
||||
node_modules
|
||||
optimizedSVGs
|
||||
src/iconMap.json
|
||||
src/iconsCache.js
|
||||
material-icons-github-edge-extension.zip
|
||||
material-icons-github-chrome-extension.zip
|
||||
material-icons-github-firefox-extension.zip
|
||||
|
||||
# Gatsby files
|
||||
# Directories/files that may appear in your environment
|
||||
*.log
|
||||
.idea
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
.vscode/
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"printWidth": 100,
|
||||
"singleQuote": true
|
||||
}
|
||||
"printWidth": 100,
|
||||
"singleQuote": true
|
||||
}
|
||||
|
3
.vscode/settings.json
vendored
@ -1,3 +0,0 @@
|
||||
{
|
||||
"dimmer.enabled": false
|
||||
}
|
4
LICENSE
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Claudio Santos and Richard Lam
|
||||
Copyright (c) 2020 Claudio Santos, Shiva Poudel and Richard Lam
|
||||
(MIT) Copyright (c) 2020 Philipp Kief (VSCode Material Icon Theme)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
@ -19,4 +19,4 @@ 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.
|
||||
SOFTWARE.
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
<b>Install directly from the <a href="https://chrome.google.com/webstore/detail/material-icons-for-github/bggfcpfjbdkhfhfmkjpbhnkhnpjjeomc">Chrome Web Store</a> or the <a href="https://addons.mozilla.org/en-US/firefox/addon/material-icons-for-github/">Addons for Firefox</a></b></div>
|
||||
|
||||
|
||||
---
|
||||
|
||||
### About
|
||||
@ -42,13 +41,13 @@ Build only files from `src` folder, without re-downloading dependencies from [Ma
|
||||
npm run build-src
|
||||
```
|
||||
|
||||
Rebuild extension logos from `src/logo.svg`. _This script needs [Inkscape](https://inkscape.org/) to be available on PATH_
|
||||
Rebuild extension logos from `src/logo.svg`.
|
||||
|
||||
```shell
|
||||
npm run rebuild-logos
|
||||
```
|
||||
|
||||
Zip `dist` folder for upload to Chrome Web Store and Firefox. *This script needs 7z (7zip) to be available on PATH*
|
||||
Zip `dist` folder for upload to Chrome Web Store and Firefox. _This script needs Zip to be available on PATH_
|
||||
|
||||
```shell
|
||||
npm run bundle
|
||||
|
BIN
assets/logo.png
Normal file
After Width: | Height: | Size: 17 KiB |
4949
package-lock.json
generated
86
package.json
@ -1,38 +1,52 @@
|
||||
{
|
||||
"name": "material-icons-github-chrome-extension",
|
||||
"version": "1.3.0",
|
||||
"description": "Chrome Extension that enhances the GitHub file browser with material icons",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "npx rimraf ./dist && npx run-s build-dependencies build-src bundle",
|
||||
"build-dependencies": "node ./scripts/build-dependencies.js",
|
||||
"build-src": "node ./scripts/build-src.js",
|
||||
"rebuild-logos": "node ./scripts/build-extensionIcons.js",
|
||||
"bundle": "run-p bundle-chrome bundle-firefox",
|
||||
"bundle-chrome": "7z a material-icons-github-chrome-extension.zip dist",
|
||||
"bundle-firefox": "web-ext -s ./dist/ -n material-icons-firefox-extension.zip -a . build",
|
||||
"parcel": "parcel build ./src/main.js"
|
||||
},
|
||||
"author": "",
|
||||
"devDependencies": {
|
||||
"eslint": "^7.2.0",
|
||||
"eslint-config": "^0.3.0",
|
||||
"eslint-config-airbnb": "^18.2.0",
|
||||
"eslint-config-prettier": "^6.14.0",
|
||||
"eslint-plugin-prettier": "^3.1.4",
|
||||
"fs-extra": "^9.0.1",
|
||||
"mkdirp": "^1.0.4",
|
||||
"node-html-parser": "^2.0.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"parcel-bundler": "^1.12.4",
|
||||
"prettier": "^2.1.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"simple-git": "^2.31.0",
|
||||
"svgo": "^1.3.2",
|
||||
"web-ext": "^5.5.0"
|
||||
},
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"selector-observer": "^2.1.6"
|
||||
}
|
||||
"name": "github-material-icons-extension",
|
||||
"version": "1.3.0",
|
||||
"description": "Browser Extension that enhances the GitHub file browser with material icons.",
|
||||
"main": "src/main.js",
|
||||
"author": "Claudio Santos",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/Claudiohbsantos/github-material-icons-extension#readme",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/Claudiohbsantos/github-material-icons-extension.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/Claudiohbsantos/github-material-icons-extension/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0",
|
||||
"npm": ">=6.9.0 <7"
|
||||
},
|
||||
"dependencies": {
|
||||
"selector-observer": "2.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "7.29.0",
|
||||
"eslint-config": "0.3.0",
|
||||
"eslint-config-airbnb": "18.2.1",
|
||||
"eslint-config-prettier": "8.3.0",
|
||||
"eslint-plugin-prettier": "3.4.0",
|
||||
"fs-extra": "10.0.0",
|
||||
"mkdirp": "1.0.4",
|
||||
"node-html-parser": "3.3.5",
|
||||
"npm-run-all": "4.1.5",
|
||||
"parcel-bundler": "1.12.5",
|
||||
"prettier": "2.3.1",
|
||||
"rimraf": "3.0.2",
|
||||
"sharp": "0.28.3",
|
||||
"simple-git": "2.40.0",
|
||||
"svgo": "2.3.0",
|
||||
"web-ext": "6.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npx rimraf ./dist && npx run-s build-dependencies build-src bundle",
|
||||
"build-dependencies": "node ./scripts/build-dependencies.js",
|
||||
"build-src": "node ./scripts/build-src.js",
|
||||
"rebuild-logos": "node ./scripts/build-extensionIcons.js",
|
||||
"bundle": "run-p bundle-edge bundle-chrome bundle-firefox",
|
||||
"bundle-edge": "zip -r material-icons-github-edge-extension.zip dist",
|
||||
"bundle-chrome": "zip -r material-icons-github-chrome-extension.zip dist",
|
||||
"bundle-firefox": "web-ext -s ./dist/ -n material-icons-github-firefox-extension.zip -a . build",
|
||||
"parcel": "parcel build ./src/main.js"
|
||||
}
|
||||
}
|
||||
|
@ -1,48 +1,43 @@
|
||||
const git = require('simple-git')();
|
||||
const child_process = require('child_process');
|
||||
/**
|
||||
* External depedencies
|
||||
*/
|
||||
const path = require('path');
|
||||
const mkdirp = require('mkdirp');
|
||||
const fs = require('fs-extra');
|
||||
const git = require('simple-git')();
|
||||
const mkdirp = require('mkdirp');
|
||||
const rimraf = require('rimraf');
|
||||
const child_process = require('child_process');
|
||||
|
||||
const destSVGPath = path.resolve(__dirname, '..', 'optimizedSVGs');
|
||||
const vsExtPath = path.resolve(__dirname, '..', 'temp');
|
||||
/**
|
||||
* Internal depedencies
|
||||
*/
|
||||
const srcPath = path.resolve(__dirname, '..', 'src');
|
||||
const vsExtPath = path.resolve(__dirname, '..', 'temp');
|
||||
const destSVGPath = path.resolve(__dirname, '..', 'optimizedSVGs');
|
||||
const vsExtExecOptions = {
|
||||
cwd: vsExtPath,
|
||||
stdio: 'inherit',
|
||||
};
|
||||
const distIconsExecOptions = {
|
||||
cwd: path.resolve(destSVGPath),
|
||||
stdio: 'inherit',
|
||||
};
|
||||
|
||||
// Copy dependencies from vs code extension
|
||||
|
||||
// Copy dependencies from vs code extension.
|
||||
rimraf.sync(vsExtPath);
|
||||
rimraf.sync(destSVGPath);
|
||||
mkdirp(destSVGPath)
|
||||
.then(() => git.clone(`https://github.com/PKief/vscode-material-icon-theme.git`, 'temp'))
|
||||
.then(npmInstallExt)
|
||||
.then(() => fs.copy(path.resolve(vsExtPath, 'icons'), path.resolve(destSVGPath)))
|
||||
.then(optimizeSVGs)
|
||||
.then(npmBuildExt)
|
||||
.then(() =>
|
||||
fs.copy(
|
||||
path.resolve(vsExtPath, 'dist', 'material-icons.json'),
|
||||
path.resolve(srcPath, 'iconMap.json')
|
||||
)
|
||||
)
|
||||
.then(() => rimraf.sync(vsExtPath))
|
||||
////
|
||||
|
||||
const vsExtExecOptions = {
|
||||
cwd: vsExtPath,
|
||||
stdio: 'inherit',
|
||||
};
|
||||
|
||||
function npmInstallExt() {
|
||||
child_process.execSync(`npm install`, vsExtExecOptions);
|
||||
}
|
||||
|
||||
function npmBuildExt() {
|
||||
child_process.execSync(`npm run build`, vsExtExecOptions);
|
||||
}
|
||||
|
||||
const distIconsExecOptions = { cwd: path.resolve(destSVGPath), stdio: 'inherit' };
|
||||
|
||||
function optimizeSVGs() {
|
||||
child_process.exec(`npx svgo --disable=removeViewBox .`, distIconsExecOptions);
|
||||
}
|
||||
.then(() =>
|
||||
git.clone(`https://github.com/PKief/vscode-material-icon-theme.git`, 'temp', ['--depth', '1'])
|
||||
)
|
||||
.then(() => child_process.execSync(`npm install`, vsExtExecOptions))
|
||||
.then(() => fs.copy(path.resolve(vsExtPath, 'icons'), path.resolve(destSVGPath)))
|
||||
.then(() => child_process.exec(`npx svgo --disable=removeViewBox .`, distIconsExecOptions))
|
||||
.then(() => child_process.execSync(`npm run build`, vsExtExecOptions))
|
||||
.then(() =>
|
||||
fs.copy(
|
||||
path.resolve(vsExtPath, 'dist', 'material-icons.json'),
|
||||
path.resolve(srcPath, 'iconMap.json')
|
||||
)
|
||||
)
|
||||
.then(() => rimraf.sync(vsExtPath));
|
||||
|
@ -1,52 +1,33 @@
|
||||
// DEPENDS ON INKSCAPE 1.x on the PATH
|
||||
|
||||
// renders src/logo.svg to desired icon sizes for the extension
|
||||
const child_process = require('child_process');
|
||||
const mkdirp = require('mkdirp');
|
||||
/**
|
||||
* External depedencies
|
||||
*/
|
||||
const path = require('path');
|
||||
const sharp = require('sharp');
|
||||
const mkdirp = require('mkdirp');
|
||||
|
||||
const extIconsPath = path.resolve(__dirname, '..', 'src', 'extensionIcons');
|
||||
const srcPath = path.resolve(__dirname, '..', 'src');
|
||||
const svgPath = path.resolve(srcPath, 'logo.svg');
|
||||
/**
|
||||
* Internal depedencies
|
||||
*/
|
||||
const svgPath = path.resolve(__dirname, '..', 'src', 'logo.svg');
|
||||
const iconsPath = path.resolve(__dirname, '..', 'src', 'extensionIcons');
|
||||
const targetSizes = [16, 32, 48, 128];
|
||||
|
||||
const execOptions = {
|
||||
cwd: extIconsPath,
|
||||
stdio: 'inherit',
|
||||
};
|
||||
// Build extension icons.
|
||||
mkdirp(iconsPath).then(generateIcons);
|
||||
|
||||
// ensure inkscape 1.x is available
|
||||
child_process.exec('inkscape --version', execOptions, (error, stout) => {
|
||||
if (error)
|
||||
console.error(
|
||||
`inkscape doesn't seem to be available. Make sure you have inkscape 1.0.1 or later installed on the PATH`
|
||||
);
|
||||
else {
|
||||
// check version
|
||||
const versionRgx = /Inkscape (?<major>\d+).\d+.\d+/;
|
||||
const major = versionRgx.exec(stout)?.groups?.major;
|
||||
if (!major || +major < 1)
|
||||
console.error(
|
||||
`inkscape version is not compatible with this script. Make sure to install v1.x or later.`
|
||||
);
|
||||
|
||||
buildIcons();
|
||||
}
|
||||
});
|
||||
// build icons
|
||||
function buildIcons() {
|
||||
mkdirp(extIconsPath).then(Promise.all(targetSizes.map((size) => generateImage(svgPath, size))));
|
||||
}
|
||||
|
||||
function generateImage(svgPath, size) {
|
||||
return new Promise((resolve, reject) => {
|
||||
child_process.exec(
|
||||
`inkscape -h ${size} -w ${size} -o icon${size}.png ${svgPath}`,
|
||||
execOptions,
|
||||
(err, stout) => {
|
||||
if (err) reject(err);
|
||||
else resolve(stout);
|
||||
}
|
||||
);
|
||||
});
|
||||
/**
|
||||
* Generate extension icons.
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
function generateIcons() {
|
||||
targetSizes.map((size) => {
|
||||
sharp(svgPath)
|
||||
.png()
|
||||
.resize({ width: size, height: size })
|
||||
.toFile(`${iconsPath}/icon${size}.png`)
|
||||
.catch(function (err) {
|
||||
console.log(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,41 +1,62 @@
|
||||
/**
|
||||
* External depedencies
|
||||
*/
|
||||
const path = require('path');
|
||||
const mkdirp = require('mkdirp');
|
||||
const fs = require('fs-extra');
|
||||
const mkdirp = require('mkdirp');
|
||||
const Parcel = require('parcel-bundler');
|
||||
const extractSVGs = require('./extract-svgHtml');
|
||||
|
||||
const destSVGPath = path.resolve(__dirname, '..', 'optimizedSVGs');
|
||||
const distPath = path.resolve(__dirname, '..', 'dist');
|
||||
/**
|
||||
* Internal depedencies
|
||||
*/
|
||||
const srcPath = path.resolve(__dirname, '..', 'src');
|
||||
const distPath = path.resolve(__dirname, '..', 'dist');
|
||||
const destSVGPath = path.resolve(__dirname, '..', 'optimizedSVGs');
|
||||
|
||||
mkdirp(distPath).then(createIconsCache).then(src);
|
||||
// copy src files to dist.
|
||||
mkdirp(distPath).then(createIconsCache).then(copySrc);
|
||||
|
||||
// copy src files
|
||||
/**
|
||||
* Copy the src files.
|
||||
*
|
||||
* @since 1.4.0
|
||||
*
|
||||
* @returns a newly generated promise object.
|
||||
*/
|
||||
function copySrc() {
|
||||
// Copy manifest file.
|
||||
const copyManifest = fs.copy(
|
||||
path.resolve(srcPath, 'manifest.json'),
|
||||
path.resolve(distPath, 'manifest.json')
|
||||
);
|
||||
|
||||
function src() {
|
||||
const entryFile = path.resolve(srcPath, 'main.js');
|
||||
const parcelOptions = {
|
||||
watch: false,
|
||||
minify: true,
|
||||
};
|
||||
const bundler = new Parcel(entryFile, parcelOptions);
|
||||
const bundleMainScript = bundler.bundle();
|
||||
// Copy extension icon.
|
||||
const copyExtensionLogos = fs.copy(
|
||||
path.resolve(srcPath, "extensionIcons"),
|
||||
path.resolve(distPath, "icons")
|
||||
);
|
||||
|
||||
const copyManifest = fs.copy(
|
||||
path.resolve(srcPath, 'manifest.json'),
|
||||
path.resolve(distPath, 'manifest.json')
|
||||
);
|
||||
// Bundle the main script.
|
||||
const entryFile = path.resolve(srcPath, 'main.js');
|
||||
const bundleMainScript = new Parcel(entryFile, {
|
||||
watch: false,
|
||||
minify: true,
|
||||
}).bundle();
|
||||
|
||||
const copyExtensionLogos = fs.copy(path.resolve(srcPath, 'extensionIcons'), distPath);
|
||||
|
||||
return Promise.all([copyManifest, copyExtensionLogos, bundleMainScript]);
|
||||
return Promise.all([copyManifest, copyExtensionLogos, bundleMainScript]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create icons cache.
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
function createIconsCache() {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.copy(path.resolve(srcPath, 'customIcons'), destSVGPath)
|
||||
.then(() => extractSVGs())
|
||||
.then(resolve)
|
||||
.catch(reject);
|
||||
});
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.copy(path.resolve(srcPath, 'customIcons'), destSVGPath)
|
||||
.then(() => extractSVGs())
|
||||
.then(resolve)
|
||||
.catch(reject);
|
||||
});
|
||||
}
|
||||
|
@ -1,40 +1,58 @@
|
||||
/**
|
||||
* External depedencies
|
||||
*/
|
||||
const path = require('path');
|
||||
const fs = require('fs').promises;
|
||||
const { parse } = require('node-html-parser');
|
||||
|
||||
/**
|
||||
* Retrieve the SVG elements.
|
||||
*
|
||||
* @since 1.4.0
|
||||
*
|
||||
* @returns a newly generated promise object.
|
||||
*/
|
||||
module.exports = function extractSVGs() {
|
||||
const iconsPath = path.resolve(__dirname, '..', 'optimizedSVGs');
|
||||
const destCachePath = path.resolve(__dirname, '..', 'src', 'iconsCache.js');
|
||||
const iconsPath = path.resolve(__dirname, '..', 'optimizedSVGs');
|
||||
const destCachePath = path.resolve(__dirname, '..', 'src', 'iconsCache.js');
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readdir(iconsPath)
|
||||
.then((iconsNames) =>
|
||||
Promise.all(
|
||||
iconsNames.map((name) => fs.readFile(path.resolve(iconsPath, name), { encoding: 'utf8' }))
|
||||
).then((svgStrs) => svgStrs.map((svgStr, i) => [iconsNames[i], parse(svgStr)]))
|
||||
)
|
||||
.then((svgElsEntries) =>
|
||||
svgElsEntries.map((entry) => [
|
||||
entry[0],
|
||||
{
|
||||
innerHtml: entry[1].firstChild.innerHTML,
|
||||
viewBox: entry[1].firstChild.getAttribute('viewBox'),
|
||||
},
|
||||
])
|
||||
)
|
||||
.then((cacheEntries) => Object.fromEntries(cacheEntries))
|
||||
.then((svgsObj) => fs.writeFile(destCachePath, formatCache(svgsObj)))
|
||||
.then(resolve)
|
||||
.catch(reject);
|
||||
});
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readdir(iconsPath)
|
||||
.then((iconsNames) =>
|
||||
Promise.all(
|
||||
iconsNames.map((name) => fs.readFile(path.resolve(iconsPath, name), { encoding: 'utf8' }))
|
||||
).then((svgStrs) => svgStrs.map((svgStr, i) => [iconsNames[i], parse(svgStr)]))
|
||||
)
|
||||
.then((svgElsEntries) =>
|
||||
svgElsEntries.map((entry) => [
|
||||
entry[0],
|
||||
{
|
||||
innerHtml: entry[1].firstChild.innerHTML,
|
||||
viewBox: entry[1].firstChild.getAttribute('viewBox'),
|
||||
},
|
||||
])
|
||||
)
|
||||
.then((cacheEntries) => Object.fromEntries(cacheEntries))
|
||||
.then((svgsObj) => fs.writeFile(destCachePath, formatCache(svgsObj)))
|
||||
.then(resolve)
|
||||
.catch(reject);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Format icons cache.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param {*} obj SVG Object.
|
||||
* @returns Cache file contents.
|
||||
*/
|
||||
function formatCache(obj) {
|
||||
const declaration = `const cache = `;
|
||||
const cacheObj = JSON.stringify(obj);
|
||||
const bottomExport = `export default cache;`;
|
||||
const declaration = `const cache = `;
|
||||
const cacheObj = JSON.stringify(obj);
|
||||
const bottomExport = `export default cache;`;
|
||||
|
||||
const fileContents = `${declaration}${cacheObj}\n\n${bottomExport}`;
|
||||
const fileContents = `${declaration}${cacheObj}\n\n${bottomExport}`;
|
||||
|
||||
return fileContents;
|
||||
return fileContents;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 558 B After Width: | Height: | Size: 730 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 2.5 KiB |
106
src/main.js
@ -1,61 +1,87 @@
|
||||
/**
|
||||
* External depedencies
|
||||
*/
|
||||
import { observe } from 'selector-observer';
|
||||
import iconsCache from './iconsCache';
|
||||
import iconMap from './iconMap';
|
||||
|
||||
// run on load
|
||||
/**
|
||||
* Internal depedencies
|
||||
*/
|
||||
import iconMap from './iconMap';
|
||||
import iconsCache from './iconsCache';
|
||||
|
||||
// Monitor DOM elements that match a CSS selector.
|
||||
const iconSelector = '.js-navigation-container > .js-navigation-item';
|
||||
|
||||
observe(iconSelector, {
|
||||
add(row) {
|
||||
replaceIcon(row, iconMap);
|
||||
},
|
||||
add(row) {
|
||||
replaceIcon(row, iconMap);
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Replace file/folder icons.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param {*} fileRow File Row.
|
||||
* @param {*} iconMap Icon Map.
|
||||
* @returns Replace icon with material icon.
|
||||
*/
|
||||
function replaceIcon(fileRow, iconMap) {
|
||||
// get file/folder name
|
||||
const fileName = fileRow.querySelector('[role=rowheader]')?.firstElementChild?.firstElementChild
|
||||
?.innerText;
|
||||
if (!fileName) return; // fileName couldn't be found or we don't have a match for it
|
||||
// get file/folder name.
|
||||
const fileName = fileRow.querySelector('[role=rowheader]')?.firstElementChild?.firstElementChild
|
||||
?.innerText;
|
||||
if (!fileName) return; // fileName couldn't be found or we don't have a match for it.
|
||||
|
||||
// svg to be replaced
|
||||
const svgEl = fileRow.querySelector('.octicon');
|
||||
if (!svgEl) return; // couldn't find svg element
|
||||
// svg to be replaced.
|
||||
const svgEl = fileRow.querySelector('.octicon');
|
||||
if (!svgEl) return; // couldn't find svg element.
|
||||
|
||||
// get type. Directory or File
|
||||
const isDir = svgEl.getAttribute('aria-label') === 'Directory';
|
||||
// get Directory or File type.
|
||||
const isDir = svgEl.getAttribute('aria-label') === 'Directory';
|
||||
|
||||
// get icon filename
|
||||
const iconName = lookForMatch(fileName, isDir, iconMap); // returns iconname if found or undefined
|
||||
if (!iconName) return;
|
||||
// get icon filename.
|
||||
const iconName = lookForMatch(fileName, isDir, iconMap); // returns iconname if found or undefined.
|
||||
if (!iconName) return;
|
||||
|
||||
const { innerHtml, viewBox } = iconsCache[iconName + '.svg'];
|
||||
if (!innerHtml || !viewBox) return;
|
||||
const { innerHtml, viewBox } = iconsCache[iconName + '.svg'];
|
||||
if (!innerHtml || !viewBox) return;
|
||||
|
||||
// must first reset innerHTML on svgEl to innerHTML of our svg
|
||||
svgEl.innerHTML = innerHtml;
|
||||
// then must set viewBox on svgEl to viewBox on our icon
|
||||
svgEl.setAttribute('viewBox', viewBox);
|
||||
// must first reset innerHTML on svgEl to innerHTML of our svg.
|
||||
svgEl.innerHTML = innerHtml;
|
||||
// then must set viewBox on svgEl to viewBox on our icon.
|
||||
svgEl.setAttribute('viewBox', viewBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup for matched icon name.
|
||||
*
|
||||
* @since 1.4.0
|
||||
*
|
||||
* @param {*} fileName File name.
|
||||
* @param {*} isDir Check if directory or file type.
|
||||
* @param {*} iconMap Icon map.
|
||||
* @returns the matched icon name.
|
||||
*/
|
||||
function lookForMatch(fileName, isDir, iconMap) {
|
||||
// returns icon name string if matches otherwise undefined
|
||||
const lowerFileName = fileName.toLowerCase();
|
||||
// first look in fileNames and folderNames
|
||||
if (iconMap.fileNames[fileName] && !isDir) return iconMap.fileNames[fileName];
|
||||
if (iconMap.folderNames[fileName] && isDir) return iconMap.folderNames[fileName];
|
||||
// returns icon name string if matches otherwise undefined.
|
||||
const lowerFileName = fileName.toLowerCase();
|
||||
// first look in fileNames and folderNames.
|
||||
if (iconMap.fileNames[fileName] && !isDir) return iconMap.fileNames[fileName];
|
||||
if (iconMap.folderNames[fileName] && isDir) return iconMap.folderNames[fileName];
|
||||
|
||||
// then check all lowercase
|
||||
if (iconMap.fileNames[lowerFileName] && !isDir) return iconMap.fileNames[lowerFileName];
|
||||
if (iconMap.folderNames[lowerFileName] && isDir) return iconMap.folderNames[lowerFileName];
|
||||
// then check all lowercase.
|
||||
if (iconMap.fileNames[lowerFileName] && !isDir) return iconMap.fileNames[lowerFileName];
|
||||
if (iconMap.folderNames[lowerFileName] && isDir) return iconMap.folderNames[lowerFileName];
|
||||
|
||||
// look for extension in fileExtensions and languageIds
|
||||
const captureExtension = /.+(?<=\.)(.+)$/;
|
||||
const extension = fileName.match(captureExtension)?.[1];
|
||||
// look for extension in fileExtensions and languageIds.
|
||||
const captureExtension = /.+(?<=\.)(.+)$/;
|
||||
const extension = fileName.match(captureExtension)?.[1];
|
||||
|
||||
if (iconMap.fileExtensions[extension] && !isDir) return iconMap.fileExtensions[extension];
|
||||
if (iconMap.languageIds[extension] && !isDir) return iconMap.languageIds[extension];
|
||||
if (iconMap.fileExtensions[extension] && !isDir) return iconMap.fileExtensions[extension];
|
||||
if (iconMap.languageIds[extension] && !isDir) return iconMap.languageIds[extension];
|
||||
|
||||
// fallback into default file or folder if no matches
|
||||
if (!isDir) return 'file';
|
||||
if (isDir) return 'folder';
|
||||
// fallback into default file or folder if no matches.
|
||||
if (!isDir) return 'file';
|
||||
if (isDir) return 'folder';
|
||||
}
|
||||
|
@ -1,20 +1,24 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Material Icons for Github",
|
||||
"version": "1.3",
|
||||
"description": "Replace the file/folder icons on github file browsers with icons representing the file's type and which tool it is used by.",
|
||||
"icons": {
|
||||
"16": "icon16.png",
|
||||
"32": "icon32.png",
|
||||
"48": "icon48.png",
|
||||
"128": "icon128.png"
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["*://*.github.com/*"],
|
||||
"js": ["./main.js"],
|
||||
"run_at": "document_start"
|
||||
}
|
||||
],
|
||||
"homepage_url": "https://github.com/Claudiohbsantos/github-material-icons-extension"
|
||||
}
|
||||
"name": "Material Icons for Github",
|
||||
"version": "1.0.0",
|
||||
"manifest_version": 2,
|
||||
"description": "Replace the file/folder icons on the GitHub file browser with icons representing the file's type and which tool it is used by.",
|
||||
"homepage_url": "https://github.com/Claudiohbsantos/github-material-icons-extension",
|
||||
"icons": {
|
||||
"16": "icons/icon16.png",
|
||||
"32": "icons/icon32.png",
|
||||
"48": "icons/icon48.png",
|
||||
"128": "icons/icon128.png"
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": [
|
||||
"*://*.github.com/*"
|
||||
],
|
||||
"js": [
|
||||
"./main.js"
|
||||
],
|
||||
"run_at": "document_start"
|
||||
}
|
||||
]
|
||||
}
|
||||
|