GitMaster裏面展示項目結構時,同時也顯示了對應的icon。
看起來和Octotree是沒什麼區別,但其實在維護和更新上是有顯著區別的。
Octotree是直接從file-icons/atom複製相關樣式和字體文件到項目裏,這樣耦合的方式很不利於維護,所以我在處理文件圖標時進行了額外的處理,把所有文件圖標通過npm包的形式引入。
大家可能好奇為什麼不直接用file-icons/atom,沒有采用的原因有幾個:
css樣式經過Content Script方式注入會污染全局樣式- 缺少
Octicons圖標 woff2文件指向不對
方案
經過考量,最終採用通過腳本處理文件,然後發佈npm包: ineo6/file-icons。
下載 file-icons/atom
使用download-git-repo從GitHub下載代碼。
還使用npm開發過程中常用的chalk和ora。
ora是一個終端加載動畫的庫,有了它,你的終端不會再蒼白。
chalk的作用是豐富終端文字樣式。
const path = require('path');
const chalk = require('chalk');
const fs = require('fs');
const os = require('os');
const ora = require('ora');
const download = require('download-git-repo');
const cwd = process.cwd();
const origin = 'file-icons/atom';
const branch = "#master";
const tmpDirPrefix = path.join(os.tmpdir(), '.tmp');
const tmpDir = fs.mkdtempSync(tmpDirPrefix);
const spinner = ora(`downloading ${origin}...`);
spinner.start();
download(`${origin}${branch}`, tmpDir, { clone: false }, function (err) {
spinner.stop();
if (err) {
console.log(chalk.red(`Failed to download repo https://github.com/${origin}${branch}`, err));
} else {
console.log(chalk.green(`Success to download repo https://github.com/${origin}${branch}`));
const spinnerExtract = ora('Extract Data...');
spinnerExtract.start();
try {
// 處理代碼的邏輯
spinnerExtract.stop();
console.log(chalk.green('Done!'));
} catch (e) {
spinnerExtract.stop();
console.log(e.message);
}
}
})
less處理
替換@font-face url
文件 styles/fonts.less 裏面的內容是如下格式:
@font-face {
font-family: FontAwesome;
font-weight: normal;
font-style: normal;
src: url("atom://file-icons/fonts/fontawesome.woff2");
}
這個顯然無法在前端項目甚至Chrome擴展里正確引用woff2字體。
因為在Chrome擴展裏無法引入遠程的woff2,所以改為引入擴展目錄中的字體,即改成如下格式:
@font-face {
font-family: FontAwesome;
font-weight: normal;
font-style: normal;
src: url("@{ICON_PATH}/fonts/fontawesome.woff2");
}
然後在webpack裏設置less變量ICON_PATH
'less-loader',
{
loader: 'less-loader',
options: {
javascriptEnabled: true,
modifyVars: {
ICON_PATH: 'chrome-extension://__MSG_@@extension_id__'
},
},
},
如何修改less文件
推薦使用gonzales-pe,它能夠解析SCSS, Sass, LESS,並轉為AST抽象語法樹。
然後我們根據需要修改AST的結構,最終調用astNode.tostring()轉換得到代碼。
const { parse } = require('gonzales-pe');
const fs = require('fs');
const chalk = require('chalk');
function replaceAtomHost(content) {
if (content.includes('atom://file-icons/')) {
content = content.replace('atom://file-icons/', '@{ICON_PATH}/');
}
return content;
}
function replaceUrlHost(ast) {
ast.traverseByType('uri', (node) => {
node.traverse(item => {
if (item.is('string')) {
item.content = replaceAtomHost(item.content)
}
});
});
return ast;
}
function replaceDeclaration(ast) {
ast.traverseByType('declaration', (decl) => {
let isVariable = false;
decl.traverse((item) => {
if (item.type === 'property') {
item.traverse((childNode) => {
if (childNode.content === 'custom-font-path') {
isVariable = true;
}
});
}
if (isVariable) {
if (item.type === 'value') {
const node = item.content[0];
node.content = replaceAtomHost(node.content)
}
}
return item;
});
});
return ast;
}
function processFonts(lessFile) {
const content = fs.readFileSync(lessFile).toString();
if (content && content.length > 0) {
let astTree;
try {
astTree = parse(content, {
syntax: 'less'
})
} catch (e) {
console.log(chalk.red(`parse error: ${e}`));
return;
}
try {
astTree = replaceUrlHost(astTree);
astTree = replaceDeclaration(astTree);
return astTree;
} catch (e) {
console.log(chalk.red(`transform error: ${e}`));
}
}
}
module.exports = function (file) {
const ast = processFonts(file);
if (ast) {
fs.writeFileSync(file, ast.toString());
}
}
文件處理
.
├── bin
├── index.js
├── index.less // 入口樣式
├── lib // 完成的樣式,字體
└── resource // 待合併資源
從file-icons/atom複製以下文件到lib:
fontsstyleslib/iconslib/utils.js
從resource裏面內容複製到lib。
在index.less裏面內容如下:
@import "lib/styles/colours.less";
@import "lib/styles/fonts.less";
@import "lib/styles/octicons.less";
.file-icons-wrapper {
@import "lib/styles/icons.less";
@import "lib/styles/fix.less";
}
這裏通過添加父級file-icons-wrapper來控制樣式影響範圍。
至此,大致完成了針對file-icons/atom的定製工作。
總結
最終我們通過npm run build命令完成拉取代碼,處理文件的。
對應的腳本在bin/update.js
當然最後可以優化的是讓任務自動執行,這點可以結合GitHub Actions的定時任務實現。本文就暫不花費篇幅介紹了,感興趣的可以摸索下。