Skip to content

Commit 8f86652

Browse files
committed
iconfont cache
1 parent 28470c5 commit 8f86652

File tree

9 files changed

+758
-124
lines changed

9 files changed

+758
-124
lines changed

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,5 +117,8 @@
117117
"release": true
118118
}
119119
},
120-
"packageManager": "[email protected]"
120+
"packageManager": "[email protected]",
121+
"dependencies": {
122+
"crypto-js": "^4.2.0"
123+
}
121124
}
Lines changed: 76 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,61 @@
11
import outlineStroke from 'svg-outline-stroke'
22
import { asyncForEach, getCompileOptions, getPackageDir, HOME_DIR, readSvgs } from '../../../.build/helpers.mjs'
33
import fs from 'fs'
4-
import { resolve } from 'path'
4+
import { resolve, basename } from 'path'
5+
import crypto from 'crypto'
6+
import { glob } from 'glob'
7+
import { execSync } from 'child_process'
58

69
const DIR = getPackageDir('icons-webfont')
710

811
const buildOutline = async () => {
9-
let files = readSvgs()
10-
const compileOptions = getCompileOptions()
12+
let files = readSvgs(),
13+
filesList = []
1114

12-
const iconfontUnicode = JSON.parse(fs.readFileSync(resolve(HOME_DIR, 'tags.json'), 'utf-8'))
15+
const compileOptions = getCompileOptions(),
16+
iconfontUnicode = JSON.parse(fs.readFileSync(resolve(HOME_DIR, 'tags.json'), 'utf-8'))
1317

14-
await asyncForEach(files, async function({ name, contents }) {
18+
await asyncForEach(files, async function ({ name, contents }) {
1519
if (compileOptions.includeIcons.length === 0 || compileOptions.includeIcons.indexOf(name) >= 0) {
1620

1721
if (iconfontUnicode[name]) {
1822
const unicode = iconfontUnicode[name].unicode
19-
await console.log('Stroke for:', name, unicode)
23+
console.log('Stroke for:', name, unicode)
24+
25+
let filename = `${name}.svg`
26+
if (unicode) {
27+
filename = `u${unicode.toUpperCase()}-${name}.svg`
28+
}
29+
30+
filesList.push(filename)
2031

2132
contents = contents
22-
.replace('width="24"', 'width="1000"')
23-
.replace('height="24"', 'height="1000"')
33+
.replace('width="24"', 'width="1000"')
34+
.replace('height="24"', 'height="1000"')
2435

2536
if (compileOptions.strokeWidth) {
2637
contents = contents
27-
.replace('stroke-width="2"', `stroke-width="${compileOptions.strokeWidth}"`)
38+
.replace('stroke-width="2"', `stroke-width="${compileOptions.strokeWidth}"`)
39+
}
40+
41+
const cachedFilename = `u${unicode.toUpperCase()}-${name}.svg`;
42+
43+
if (unicode && fs.existsSync(resolve(DIR, `icons-outlined/${cachedFilename}`))) {
44+
// Get content
45+
let cachedContent = fs.readFileSync(resolve(DIR, `icons-outlined/${cachedFilename}`), 'utf-8')
46+
47+
// Get hash
48+
let cachedHash = '';
49+
cachedContent = cachedContent.replace(/<!--\!cache:([a-z0-9]+)-->/, function (m, hash) {
50+
cachedHash = hash;
51+
return '';
52+
})
53+
54+
// Check hash
55+
if (crypto.createHash('sha1').update(cachedContent).digest("hex") === cachedHash) {
56+
console.log('Cached stroke for:', name, unicode)
57+
return true;
58+
}
2859
}
2960

3061
await outlineStroke(contents, {
@@ -35,15 +66,44 @@ const buildOutline = async () => {
3566
fixedWidth: false,
3667
color: 'black'
3768
}).then(outlined => {
38-
if (unicode) {
39-
fs.writeFileSync(resolve(DIR, `icons-outlined/u${unicode.toUpperCase()}-${name}.svg`), outlined, 'utf-8')
40-
} else {
41-
fs.writeFileSync(resolve(DIR, `icons-outlined/${name}.svg`), outlined, 'utf-8')
42-
}
43-
}).catch(error => console.log(error))
44-
}
69+
filesList[filename]
70+
71+
// Save file
72+
fs.writeFileSync(resolve(DIR, `icons-outlined/${filename}`), outlined, 'utf-8')
73+
74+
// Fix outline
75+
execSync(`fontforge -lang=py -script .build/fix-outline.py icons-outlined/${filename}`)
76+
execSync(`svgo icons-outlined/${filename}`)
77+
78+
// Add hash
79+
const fixedFileContent = fs
80+
.readFileSync(resolve(DIR, `icons-outlined/${filename}`), 'utf-8')
81+
.replace(/\n/g, ' ')
82+
.trim(),
83+
hashString = `<!--!cache:${crypto.createHash('sha1').update(fixedFileContent).digest("hex")}-->`
84+
85+
// Save file
86+
fs.writeFileSync(
87+
resolve(DIR, `icons-outlined/${filename}`),
88+
fixedFileContent + hashString,
89+
'utf-8'
90+
)
91+
}).catch(error => console.log(error))
92+
}
4593
}
4694
})
95+
96+
// Remove old files
97+
const existedFiles = (await glob(resolve(DIR, `icons-outlined/*.svg`))).map(file => basename(file))
98+
99+
existedFiles.forEach(file => {
100+
if (filesList.indexOf(file) === -1) {
101+
console.log('Remove:', file)
102+
fs.unlinkSync(resolve(DIR, `icons-outlined/${file}`))
103+
}
104+
})
105+
106+
console.log('Done')
47107
}
48108

49109
await buildOutline()
Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,17 @@
11
import os
22
import fontforge
33

4-
# svg2ttf library does not support fill-rule="evenodd" so after converting icons to outlineStroke we fix path directions to work with "nonzero"
5-
# more: https://github.com/tabler/tabler-icons/issues/13 - thanks for awesome suggestions in the issue
6-
7-
8-
print ("Running fontforge to fix svg outline directions!")
9-
10-
def files(path):
11-
for file in os.listdir(path):
12-
if os.path.isfile(os.path.join(path, file)):
13-
yield file
14-
15-
# refer to https://fontforge.org/docs/scripting/python/fontforge.html for documentation
16-
# inspiration from https://github.com/FontCustom/fontcustom/blob/master/lib/fontcustom/scripts/generate.py
4+
file = sys.argv[1]
175

186
font = fontforge.font()
19-
for file in files("./icons-outlined"):
20-
print (f"Correcting outline for {file}")
21-
glyph = font.createChar(123, file)
22-
glyph.importOutlines("./icons-outlined/" + file)
23-
glyph.round()
24-
glyph.simplify()
25-
glyph.simplify()
26-
glyph.correctDirection()
27-
glyph.export("./icons-outlined/" + file)
28-
glyph.clear()
29-
7+
print (f"Correcting outline for {file}")
8+
glyph = font.createChar(123, file)
9+
glyph.importOutlines("./" + file)
10+
glyph.round()
11+
glyph.simplify()
12+
glyph.simplify()
13+
glyph.correctDirection()
14+
glyph.export("./" + file)
15+
glyph.clear()
3016

3117
print ("Finished fixing svg outline directions!")
1.26 KB
Binary file not shown.
1.26 KB
Binary file not shown.
888 Bytes
Binary file not shown.
176 Bytes
Binary file not shown.

packages/icons-webfont/package.json

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,12 @@
1616
"directory": "packages/icons-webfont"
1717
},
1818
"scripts": {
19-
"build": "pnpm run clean && pnpm run copy && pnpm run build:prepare && pnpm run build:outline && pnpm run build:optimize && pnpm run build:fix-outline && pnpm run build:webfont && pnpm run build:css && pnpm run build:clean",
20-
"build:prepare": "mkdir -p icons-outlined fonts && rm -fd icons-outlined/* fonts/*",
19+
"build": "pnpm run copy && pnpm run build:prepare && pnpm run build:outline && pnpm run build:webfont && pnpm run build:css",
20+
"build:prepare": "mkdir -p icons-outlined fonts && rm -fd fonts/*",
2121
"build:outline": "node .build/build-outline.mjs",
22-
"build:optimize": "svgo icons-outlined/*",
23-
"build:fix-outline": "fontforge -lang=py -script .build/fix-outline.py",
2422
"build:webfont": "rm -fd fonts/* && node .build/build-webfont.mjs",
2523
"build:css": "sass tabler-icons.scss tabler-icons.css --style expanded && sass tabler-icons.scss tabler-icons.min.css --style compressed",
2624
"build:clean": "rm -rf ./icons-outlined",
27-
"clean": "rm -rf ./iconfont",
2825
"copy": "pnpm run copy:license",
2926
"copy:license": "cp ../../LICENSE ./LICENSE"
3027
},

0 commit comments

Comments
 (0)