This website requires JavaScript.
BING
Because the mountain is there
OG

README.md

5,328 words, 13 min read2022/01/27 PM4,234 views

前一周还在上海,重新折腾了一阵子 GitHub 的 README.md profile

看得出来,绝大部分的项目大家都用的是 github-readme-stats 提供的统计图表装饰自己的 profile,包括我之前也是。

项目很棒,但不适用于苛求表达设计的前端,所以我想,有没有可能将设计能力完全开放于他人?

README.md

于是有了 README.md 这个项目。

其实还有一条路是使用 GitHub Actions 执行定时任务,自行维护数据即可,只是有一定的开发成本,还是开箱即用的 “服务” 更加简洁和普适。

先看下我现在的主页:

是啥

说简单点吧:

GitHub README.md profile 允许你定义一个以自己 GitHub username 命名的仓库,并读取此仓库主分支根目录的 README.md 渲染在你的 GitHub 个人主页。

也就意味着,GitHub markdown 支持的最大(UI、编程)能力即是我们可以实践设计(编码)的最大发挥空间。

SVG

原始的 markdown 是无法实现交互、动画、这样的高级渲染的,但 SVG 可以做到,且 SVG 可以被用于 markdown 中的 img 内联。

但在实测过程中发现:

  1. GitHub 对所有 README.md 中引用的外部资源都使用了基于 githubusercontent.com 域名的缓存代理,换句话说,GitHub 不允许自己的主站直接发起任何外部站点的网络请求。
  2. githubusercontent.com 这个域名的 content-security-policy 非常、极其严苛,除去一些限制条件后,仅允许:以 Base64 内联的资源、内联的 CSS 样式,内联的 HTML,且不支持任何类型的 script,总之不能在资源中再引用任何外部资源。

好了,确定好限制之后,我们就知道可以做什么了:

  1. 可以渲染 SVG
  2. SVG 中可以包含内联 CSS
  3. SVG 中可以包含 Base64 格式的图片等媒体资源

以及不可以做什么:

  1. 不支持 SVG 中的 script,即便你写了,script 也不会被执行,所以可以放弃 JS 动画了
  2. 不支持引用任何位置的外部资源,如一张图片、视频、一个 CSS 文件,都是完全不可能的
  3. 不支持 CSS 的动画交互,如 :hover 之类的用户交互行为;因为我们只能通过图片的形式引用 SVG,所以对 markdown 来说,其只负责 “图形的渲染”,而不存在 “图形的交互”

如此,我们便可确定,GitHub 的 markdown 可以引用包含 CSS 动画的 SVG。

HTML

将 SVG 交给用户去实现 “设计” 太不现实了,对大多数用户来说,最好的设计工具一定是最普适、最简单的。

所以可以想到,最完美的设计工具必定是 CSS + HTML,于是我们可以简单实现为基于 foreignObjectSVG<HTML> 渲染机制。

最简单的例子如下:

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
<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 图片了。

Vue

到这里,似乎我们忽略了一个点,假设我们需要渲染一个 user top languages 列表,该如何实现?

我们需要循环一整个列表数据,将每一项转换为指定的 HTML DOM 片段,并最终拼接在一起。

如此,我们需要执行 JavaScript 脚本,那么 JavaScript 在什么时机执行?如何优雅地暴露承载脚本的接口?且同时还需考虑 HTML、CSS 接口的存在。

此刻,似乎 Vue 天生就是为此场景打造的。

我们来看一个简单的 Vue SFC component:

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
<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 图片效果(预置模板):

hello-world

github-contributions-calendar

github-sponsor-button

github-top-languages

TODO

当然接下来还希望可以有一个前端服务,用于用户在 UI 界面编辑、创建自己的自定义模板,及根据简洁的表单直接生成 SVG 图片地址。

希望这个项目对你有所帮助,也欢迎你贡献更多的想法和灵感。

(完)

Creative Commons BY-NC 3.0 CNhttps://surmon.me/article/196
10 / 10 comments
Guest
Join the discussion...
  • 苏蒙
    苏蒙🇨🇳CNShanghaiMac OSChrome
    #2382

    👍👍👍

  • Sky390
    Sky390🇨🇳CNXintaiWindowsEdge
    #2337

    tql %%%

  • YiHei
    Yihei🇨🇳CNChengduWindowsChrome
    #2301

    SSR那里能展开讲讲吗,百度了还是没搞好 😅

    • Surmon
      Surmon🇨🇳CNShanghaiMac OSChrome
      #2338

      reply:

      可以留下你的问题,我将力所能及。

  • YiHei
    Yihei🇨🇳CNChengduWindowsChrome
    #2300

    优秀 👏

  • ShowBuger
    Showbuger🇭🇰HKCentralWindowsChrome
    #2295

    卧槽?这是个人的博客?

    • Surmon
      Surmon🇨🇳CNShanghaiMac OSChrome
      #2297

      reply:

      是  

  • good
    Good🇨🇳CNBaodingWindowsChrome
    #2291

    不错。和不错的

  • 遨游星海
    遨游星海🇨🇳CNChangzhouWindowsQuark
    #2284

    emmm,看了两遍,就是说原来的github简介表达方式有限,后来你做了优化方案,现在可以有更多图形化的展示方式,更美观也更有条理。对阅读者来说更友善也很有趣。可以我手机看主页不大得劲,回去用电脑试试。不错哟,给你点👍

    • Surmon
      Surmon🇨🇳CNShanghaiMac OSChrome
      #2304

      reply:

      Guest 评论修好了!