feat(fontmin): 完成基础的动态字体生成功能

This commit is contained in:
崮生 2021-03-12 16:20:36 +08:00
parent 88f21ef2f6
commit fdde780528
9 changed files with 1818 additions and 110 deletions

View File

@ -1,3 +1,6 @@
{
"git.ignoreLimitWarning": true
"git.ignoreLimitWarning": true,
"cSpell.words": [
"Fontmin"
]
}

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# web font serverless 版
[在线尝试地址](http://webfontserverless.shenzilong.cn/)

View File

@ -2,8 +2,9 @@ targets:
- backend
malagu:
# serve-static:
# root: .malagu/frontend/dist
serve-static:
# apiPath: /*
apiPath: /api/*
faas-adapter:
customDomain:
@ -11,3 +12,8 @@ malagu:
service:
name: web_font # 默认值是 malagu
includeModules: true
webpack:
config:
externals: fontmin

View File

@ -12,7 +12,9 @@
"dependencies": {
"@malagu/fc-adapter": "latest",
"@malagu/mvc": "latest",
"@malagu/serve-static": "latest"
"@malagu/serve-static": "latest",
"fontmin": "^0.9.8",
"zip-a-folder": "^0.1.0"
},
"devDependencies": {
"@malagu/cli": "latest",

View File

@ -0,0 +1,91 @@
import { Controller, File, Get, Query } from "@malagu/mvc/lib/node";
import { Context } from "@malagu/web/lib/node";
import { createHash } from "crypto";
//@ts-ignore
import * as Fontmin from "fontmin";
import { promises as fs } from "fs";
import * as path from "path";
import { join } from "path";
//@ts-ignore
import { zip } from "zip-a-folder";
import { Stream } from "stream";
const font_src = path.join(__dirname, "../../frontend/font");
console.log("[__dirname]", __dirname);
console.log("[font_src]", font_src);
@Controller("api")
export class FontMinController {
@Get("generate_fonts_dynamically")
@File()
async generate_fonts_dynamically(
@Query("text") text: string,
@Query("font") font: string,
@Query("temp") temp: string = "true",
@Query("type") type: string = "ttf",
) {
console.log("字体请求", { text, font, temp, type });
text += "●";
const res = Context.getResponse();
const hash = createHash("md5");
hash.update(`${type}${font}${text}`);
const hash_str = hash.digest("hex");
const srcPath = path.join(font_src, `${font.replace(/.ttf$/, "")}.ttf`); // 字体源文件
const outPath = `asset/dynamically/${hash_str}`;
const destPath = `./${outPath}`; // 输出路径
const full_path = join(__dirname, "../../", destPath, `${font}.${type}`);
/** 需要持久化 */
if (temp !== "true") {
try {
return await fs.readFile(full_path);
} catch (error) {
console.log(`开始生成 ${full_path}`, error);
}
}
// 初始化
const fontmin = new Fontmin()
.src(srcPath) // 输入配置
.use(
Fontmin.glyph({
text, // 所需文字
}),
);
if ("eot" === type) {
fontmin.use(Fontmin.ttf2eot()); // eot 转换插件
}
if ("woff" === type) {
fontmin.use(Fontmin.ttf2woff()); // eot 转换插件
}
if ("svg" === type) {
fontmin.use(Fontmin.ttf2svg()); // eot 转换插件
}
/** 缓存数据 */
if (temp !== "true") {
fontmin.dest(destPath);
}
// 执行
return new Promise((resolve, reject) => {
fontmin.run(async function (err: Error, files: any[]) {
if (err) {
// 异常捕捉
reject(err);
} else {
const buffer = files.filter((f) =>
/** 筛选需要的类型 */
(f.history[f.history.length - 1] as string).endsWith(type),
)[0]._contents;
console.log("[buffer]", Buffer.isBuffer(buffer));
const bufferStream = new Stream.PassThrough();
bufferStream.end(buffer);
bufferStream.pipe(res);
// resolve(buffer); // 成功
}
});
});
}
}

View File

@ -1,12 +0,0 @@
import { Controller, Get, Text } from "@malagu/mvc/lib/node";
@Controller()
export class HomeController {
@Get("/12")
@Text()
home(): string {
console.log(222);
return "Welcome to Malagu";
}
}

View File

@ -1,5 +1,4 @@
import './home-controller';
import './fontmin';
import { autoBind } from '@malagu/core';
console.log("app start");
export default autoBind();

View File

@ -1,27 +1,80 @@
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Hello Vue 3 + TypeScript + Vite" />
<h1>
web font 字体裁剪工具 (<a href="https://github.com/cellbang/malagu"
>serverless版</a
>)
</h1>
<label style="display: flex; width: 100%">
<span style="width: 30%; flex-shrink: 0">使用该字体的文字</span>
<input type="text" v-model="text" style="flex: 1" />
</label>
<label style="display: flex; width: 100%">
<span style="width: 30%; flex-shrink: 0">选择使用的字体</span>
<input disabled type="text" v-model="font" style="flex: 1" />
</label>
<label style="display: flex; width: 100%">
<span style="width: 30%; flex-shrink: 0">选择字体类型</span>
<input disabled type="text" v-model="type" style="flex: 1" />
</label>
<span>你可以直接 copy 下面的 css 去使用</span>
<textarea
v-model="cssCode"
disabled
:cols="20"
:rows="16"
style="width: 95%; font-family: test"
/>
<footer>
<a href="https://github.com/2234839/web-font/tree/serverless"
>github repo</a
>
</footer>
<div v-html="style" />
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import HelloWorld from './components/HelloWorld.vue'
import { computed, defineComponent, ref } from "vue";
export default defineComponent({
name: 'App',
components: {
HelloWorld
}
})
export default defineComponent({
name: "App",
setup() {
const text = ref("千图小兔体webfont字体裁剪工具(serverless版)");
const font = ref("千图小兔体.ttf");
const temp = ref("true");
const type = ref("ttf");
const cssCode = computed(
() => `* { font-family: test}\n
@font-face {
font-family: "test";
src: url("http://webfontserverless.shenzilong.cn/api/generate_fonts_dynamically?text=${text.value.trim()}&font=${
font.value
}&temp=${temp.value}&type=${type.value}")
format("truetype");
font-style: normal;
font-weight: normal;
}`,
);
const style = computed(() => `<style>${cssCode.value}</style>`);
return { cssCode, style, text, font, temp, type };
},
});
const defaultCssCode = ``;
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
#app {
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
display: flex;
flex-direction: column;
align-items: center;
}
#app,
textarea,
input {
font-size: 1.3em;
}
</style>

1707
yarn.lock

File diff suppressed because it is too large Load Diff