弱点
人的
前一周还在上海,重新折腾了一阵子 GitHub 的 README.md profile 。
看得出来,绝大部分的项目大家都用的是 github-readme-stats 提供的统计图表装饰自己的 profile,包括我之前也是。
项目很棒,但不适用于苛求表达设计的前端,所以我想,有没有可能将设计能力完全开放于他人?
于是有了 README.md 这个项目。
其实还有一条路是使用 GitHub Actions 执行定时任务,自行维护数据即可,只是有一定的开发成本,还是开箱即用的 “服务” 更加简洁和普适。
先看下我现在的主页:
说简单点吧:
GitHub README.md profile 允许你定义一个以自己 GitHub username 命名的仓库,并读取此仓库主分支根目录的 README.md 渲染在你的 GitHub 个人主页。
也就意味着,GitHub markdown 支持的最大(UI、编程)能力即是我们可以实践设计(编码)的最大发挥空间。
原始的 markdown 是无法实现交互、动画、这样的高级渲染的,但 SVG 可以做到,且 SVG 可以被用于 markdown 中的 img
内联。
但在实测过程中发现:
githubusercontent.com
域名的缓存代理,换句话说,GitHub 不允许自己的主站直接发起任何外部站点的网络请求。githubusercontent.com
这个域名的 content-security-policy
非常、极其严苛,除去一些限制条件后,仅允许:以 Base64 内联的资源、内联的 CSS 样式,内联的 HTML,且不支持任何类型的 script,总之不能在资源中再引用任何外部资源。好了,确定好限制之后,我们就知道可以做什么了:
以及不可以做什么:
:hover
之类的用户交互行为;因为我们只能通过图片的形式引用 SVG,所以对 markdown 来说,其只负责 “图形的渲染”,而不存在 “图形的交互”如此,我们便可确定,GitHub 的 markdown 可以引用包含 CSS 动画的 SVG。
将 SVG 交给用户去实现 “设计” 太不现实了,对大多数用户来说,最好的设计工具一定是最普适、最简单的。
所以可以想到,最完美的设计工具必定是 CSS + HTML,于是我们可以简单实现为基于 foreignObject 的 SVG<HTML>
渲染机制。
最简单的例子如下:
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
fill="none"
${your_custom_svg_attrs.join(' ')}
>
<foreignObject width="100%" height="100%">
<body xmlns="http://www.w3.org/1999/xhtml">
<style>${your_css}</style>
${your_html}
</body>
</foreignObject>
</svg>
如此,用户仅需提供 HTML 和 CSS,即可将其渲染为一个可以被 markdown 正常引用的 SVG 图片了。
到这里,似乎我们忽略了一个点,假设我们需要渲染一个 user top languages 列表,该如何实现?
我们需要循环一整个列表数据,将每一项转换为指定的 HTML DOM 片段,并最终拼接在一起。
如此,我们需要执行 JavaScript 脚本,那么 JavaScript 在什么时机执行?如何优雅地暴露承载脚本的接口?且同时还需考虑 HTML、CSS 接口的存在。
此刻,似乎 Vue 天生就是为此场景打造的。
我们来看一个简单的 Vue SFC component:
<template>
<ul class="languages">
<li class="item" v-for="lang in languages">{{ lang.name }}</li>
</ul>
</template>
<script>
export default {
name: "GitHubTopLanguages",
props: {
username: {
type: String,
required: true,
},
},
setup(props) {
// fetch languages ...
return {
languages,
};
},
};
</script>
<style>
.languages {
padding: 0;
}
.item {
color: red;
}
</style>
实在是太契合了!
我们将 template
中的模板部分通过在 Node.js 渲染层通过 Vue SSR 渲染为 HTML,并直接输出至 SVG 的 foreignObject
中。
同时我们拿到了用户定义的 Pure CSS 内容,直接消费于 SVG 渲染器即可。
而 script
则更简单了,Vue SSR 渲染的过程即是执行 script
的过程,自然而然。
Vue SFC 带来的好处可不仅如此,props
的描述能力又恰巧天然可以完整描述一个 component 的 API,虽然只能描述基本类型,但在 README.md 项目中这完全足够且刚好足够了!
最终我基于 Vue > SSR render > SVG render
的渲染机制实现了一套程序并部署在 Vercel serverless,作为一项免费的公共服务提供于外部。
简单的工作流程如下图:
在 Node.js 服务端,我使用 GitHub 的公读 AK 拉取各种 UI 可能需要的数据,并 注入至 Node.js SSR render 时的 Sandbox ,这样即实现了开发者的 “各取所需”,当然背后是基于 GitHub 的 GraphQL API。
相关代码在这里 。
一个 Vue 组件即一个 template
,README.md 项目内置了一些 漂亮的预置模板 ,当然你可以可以通过 template_url
template_string
参数 指定你的自定义模板 。
具体详细的 API 和开发指南可以参考 README.md 项目的 README.md 。
一些 SVG 图片效果(预置模板):
当然接下来还希望可以有一个前端服务,用于用户在 UI 界面编辑、创建自己的自定义模板,及根据简洁的表单直接生成 SVG 图片地址。
希望这个项目对你有所帮助,也欢迎你贡献更多的想法和灵感。
(完)
👍👍👍
tql %%%
SSR那里能展开讲讲吗,百度了还是没搞好 😅
reply:
可以留下你的问题,我将力所能及。
reply:
回复了你的回复
优秀 👏
卧槽?这是个人的博客?
reply:
是
不错。和不错的
emmm,看了两遍,就是说原来的github简介表达方式有限,后来你做了优化方案,现在可以有更多图形化的展示方式,更美观也更有条理。对阅读者来说更友善也很有趣。可以我手机看主页不大得劲,回去用电脑试试。不错哟,给你点👍
reply:
Guest 评论修好了!