Marguerite Su: Golang/Ruby Programmer, openSUSE Member

为 Discourse 开发一个 Onebox 插件(三)去掉 watir 依赖

我们在前两篇文章中已经基本实现了这个 engine,但是目前有一个非常恼人的依赖问题:由于 build.opensuse.org 的 package build status 是使用 javascript 加载的,而 nokogiri gem 并不支持 javascript,这就造成了我们需要使用 watir gem 去点一下网页上的 refresh 按钮,才能获取正确的 build status: browser = Watir::Browser.new(:chrome, chromeOptions: { args: ['--headless', '--window-size=1200x600', '--no-sandbox', '--disable-dev-shm-usage'] }) browser.goto(link) browser.image(id: reload_id).click 但是随之带来的依赖是非常恐怖的,我们需要一个 chrome-driver 和一个 chromium。要知道 discourse 没有装在本地的,都是装在 VPS 上面,一个 chromium 带来的空间和内存使用是十分恐怖的。于是我们通过这篇文章来教你如何干掉 watir 依赖。 我们测试用的界面是 marketo package,使用 chromium 右键查看网页源代码,我们发现 Refresh 按钮是这样的: <div accesskey='r' class='btn btn-outline-primary build-refresh float-right' onclick='updateBuildResult(&#39;&#39;)' title='Refresh Build Results'> Refresh <i class='fas fa-sync-alt' id='build-reload'></i> </div> 点击它的时候执行的是“updateBuildResult('')”这个 javascript 函数。对于现代网页开发而言,基本上 javascript 都写在一个文件里然后在 html 中引用的,我们翻遍了网页源代码只发现了一个引用: Read more...

为 Discourse 开发一个 Onebox 插件(二)从零开始写 custom engine

上一篇为 Discourse 开发一个 Onebox 插件(一)理解 Onebox gem 里,我们知道了 Onebox 是什么样的结构。这篇我们先来写一个 onebox 的自定义引擎。 我们先准备一个脚手架 openbuildservice_onebox.rb module Onebox module Engine class OpenBuildServiceOnebox include Engine include LayoutSupport include HTML always_https matches_regexp(%r{^(https?://)?build.opensuse.org/\w+/show/(.)+$}) private end end end 我们已经知道了这两个 module Onebox和 module Engine 嵌套 class OpenBuildServiceOnebox 是为什么,为了让 Preview.new 的 ordered_engines能够找到我们这个以 Onebox 结尾的类,并调用它通过 matches_regexp 设置的 @@matcher来与真正的 URI 对比来确定唯一一个 engine。include Engine的作用是为了得到 ClassMethods里面定义的与 URI 做相等比较的方法。另外 OpenBuildServiceOnebox 这个 class 没有 initialize 方法是因为 module Engine里面已经统一实现了,我们可以直接用 @options和 @uri 这样的实例变量。 但是有一个问题是不是我忽略了?没有 to_html 这个最终把 URL 转成 html preview 的函数呀! Read more...

为 Discourse 开发一个 Onebox 插件(一)理解 Onebox gem

为 Discourse 开发一个 Onebox 插件(一)理解 Onebox gem 我们 openSUSE 中文论坛用的是 discourse,有一天给用户贴了一个 OBS 的链接,突然想到是不是可以让它也能像 github 一样有一个漂亮的预览小窗口 🤓 于是说干就干:discourse-openbuildservice-onebox 插件。 以下是教程,由于涉及到目前最大的 Ruby on Rails 程序 discourse,会分成几部分来讲解。第一部分我们来试着理解一下 discourse 出品的 onebox gem。 Ruby 作为一门脚本语言,所有对象的方法都可以被重写。学名叫做 Meta Programming。这是理解 onebox gem 的基础。 我们下面来看 discourse 是怎么使用 onebox gem 的,下面是 app/models/post_analyzer.rb 的 cook 函数,这个函数负责把你输入的文字转为 html 保存在 postgresql 数据库,是最基础的函数之一: def cook(raw, opts = {}) [...] result = Oneboxer.apply(cooked) do |url| @onebox_urls << url if opts[:invalidate_oneboxes] Oneboxer.invalidate(url) InlineOneboxer.invalidate(url) end onebox = Oneboxer. Read more...

Color Emoji in openSUSE

上一篇文章里我们讲了 fontconfig 常见的几个坑,今天我们来继续讲一讲 openSUSE 的 Colored Emoji 支持。也就是如何配置 Noto Color Emoji 这个字体用于网页显示(用于终端显示是另一回事,涉及到比如 vte 的 teminal 之类的,有几个相关的 bug 涉及到比如宽度之类的;GTK/Qt 显示又是另一回事,涉及到 cairo)。 为什么是这个字体呢?我也很无奈啊…Noto 系列是 openSUSE 的默认字体,可以说除了英文 locale 别的都是 Noto 来显示的,Noto Color Emoji 跟其它 Noto 字体的 metrics 兼容。这一点就秒杀了其它 Emoji 字体。再者 Emoji 字体本身就不多,目前为止也就 45-generic.conf 里列出的那么不到十个,EmojiOne Color 因为版权问题不再开发了,真正 Linux 上能用的 Colored Emoji 也就剩下一个 Twitter Color Emoji 了。剩下的要么专有的要么没有颜色。 我们先来回忆一下之前的说法: 除了比如 Unicode Full Emoji List 这种专门用于测试 emoji 显示的 URL,大部分我们常见的网页在 css 里是不写 emoji 字体的。 据我摸索的经验,字体的匹配分为三种场景 第一种是直接去匹配这个字体,fc-match “Noto Color Emoji” 这样,也就是 css 的 font-family 里直接写了这个字体。 Read more...

fontconfig 几个常见的坑

最近 Microsoft 加入 OIN,贡献了它的 60000+ 项专利,这使得 openSUSE 的 freetype2 终于能够开启 ClearType 引擎了。之前 infinality 项目贡献了三大块,我们引入了两大块,但是其中第一大块的 ClearType 引擎没有默认开启,第三大块的非专利色彩滤镜也一直没有。现在专利的问题没有了,freetype2 终于更新到完全体了,它现在有两个引擎,第一个引擎是 Adobe 的 CFF 引擎,主要用于 Noto Sans CJK,第二个引擎就是 infinality 贡献的 ClearType 引擎了。总之都是好东西。 后端更新了,我也需要更新 fonts-config 来默认设置 rgba 和 hintstyle。openSUSE 的 fonts-config 是一系列跟 fontconfig 一样的字体配置文件,已经很老了,于是我需要 modernize 它一下。在这个过程中我几乎看了网上能够找到的全部 fontconfig 相关文章。里面大坑套小坑,有必要专门写文来澄清一下: ##第一个坑:从 monospace 中清除 sans-serif 比如 Hack 字体的官方配置,还有最著名的 eev’s rant about fontconfig,都推荐了这么一种做法: <match> <test name=“family” compare=“eq”> <string>sans-serif</string> </test> <test name=“family” compare=“eq”> <string>monospace</string> </test> <edit name=“family” mode=“delete”/> </match> 意思是如果 pattern 有 sans-serif,还有 monospace,就把 sans-serif 删除。目的是让字体只有一个 generic name。起因在于 /usr/share/fontconfig/conf. Read more...

30 秒钟在 Github Pages 上搭建一个 openSUSE 风格的部落格

之前的 Ghost 管理密码丢了 :-( 昨晚花了一个晚上的时间把之前丢失的部落格文章通过 web.archives.org 找回到了 2011 年。09~10 年的部落格文章等想怀旧的时候再继续找。下一步应该研究的是怎么恢复和整合评论。 不过这个坑就不一定哪天来填啦。 考虑到我博客更新的速度和访问量,我觉得还是不要把它放在论坛服务器上了。毕竟 Ghost 是用 nodejs 的,一直跑着太占资源;搬服务器就要迁移,我这种懒人,迁完论坛就不管的, 博客要么丢文章要么丢评论。还是用 github 来做博客好了。 Github Pages 是由 Jekyll 驱动的静态博客,使用 Markdown 来写文章,用 git 管理,这几个对我来说都不是很难,毕竟我是一个 Ruby 程序猿。Github 自己的文档基本无用,因为文档跟用户之间少了点东西。 它只告诉了我 Github Page 其实就是一个静态网页生成器加 HTTP 服务器,你喂 Markdown 格式的文章给它,它在 yourname.github.io 上显示出来。这用来建立一个单页面是足够的。 但是它并没有说你想做一个博客应该怎么办。因为其实那是 Jekyll 这个静态网页生成器的事情。你需要给它写模板。 所以我参考了 Smashing Magazine 上面的 Build A Blog With Jekyll And Github Pages,找了一个现成的 Jekyll Now 模板。自己简单改了下。风格参考了 Grover Chou 的部落格。我觉得他那个 openSUSE Leap 风格的主题很好看,于是就抄过来了。配色和样式是抄的我们 openSUSE 中文论坛。点我预览。 要是有想要用我这套主题建博客的,建立过程很简单: 去 github 上面 fork 我的 marguerite. Read more...

Introducing the brand new nodejs packaging

There has been no activities for nodejs in openSUSE for a while. (Since 13.2) But it doesn’t mean it’s dead. It’s actually evolving. Today the brand-new nodejs-packaging answers all the questions. For a long time and traditionally we openSUSE prefer to keep consistence with Fedora in RPM packaging (Although small differences still present). So did nodejs packaging. We used the nodejs-packaging tool from Fedora to package for openSUSE before. But it introduced lots of troubles: Read more...

本周开发札记

盘点一下本周自己在 openSUSE 上面做的工作: 解决了 wine 的 desktop file 长期以来位于未知类别的 bug openSUSE 的 wine 从 Ubuntu 抄来了一些 desktop files。而这些文件的 Categories 都是错的(Categories=Wine;Emulator;Documentation;)。根据 freedesktop 的 desktop entry specification 规定,Emulator; 只能跟在 Games; 或者 System; 后面使用,所以是错的,而 Wine; 本身不是一个合法的 Desktop Category; Documentation; 又不符合。统一调整到了 System;Emulator; 类别,而一些可以独立使用的比如 notepad 则视同原生 App 调整到了对应的比如 Utility;Texteditor; 类别。 对 devel:languages:nodejs 源进行了 big cleanup 主要是为了我马上要开发的 nodejs-packaging 做准备。npm 由独立打包回归到了与 nodejs 一同打包,而我开发的 nodejs-packaging 又准备使用 bundled packaging 的模式,那么独立打包 npm 时的一些依赖包就不再需要了。这些依赖很早就被我用自动化脚本(简单的 shell script 和 ruby)从 openSUSE:Factory 批量删除了,现在 d:l:nodejs 源里还有一些 broken 状态的尸体。用自动化脚本批量 revoke 了一些 factory-auto-submit 导致的被 rejected 的 SR,然后跑脚本 wipebinaries 从服务器删除 RPM,从服务器 remote delete 掉。 Read more...

脑洞大开的周末

这个周末其实只打算维护下我的 upstream-notifier 的😂。好吧原来我只是想更新几个软件包,结果觉得既然都去更新包了,不如把给 upnoti 用的 json 也写了。 写的过程中要测试,发现 github 上面的有些项目的 release page 底下没有内容,于是又改 upnoti 的 github mod 支持这种情况。然后又觉得 upnoti 太慢,加了 multithread 支持,然后又开始优化性能,代码风格之类的。 好不容易搞定了,这时 home:opensuse_zh 已经更新完几个包了,没法生产环境测试了,又去 d:l:go 里把 docker 的几个依赖抓回来,发现 golang-packaging 在 sles11 上面 test 宏出错,又给自己加了一项工作任务。 然后在 features.opensuse.org 上看到有个人要 tox 整合进 openSUSE,想起来我还维护着 cutegram 和 qtox,于是去更新 cutegram。 结果觉得我的用 _service 抓 git 的软件包这么多,每次更新基本都是无脑的,干嘛不做个自动化工具呢?于是 obs-scm-autoupdater 就这么诞生了😈 写完 osa 的基本功能,又开始怀疑人生了。rpm 打包这么难,新手不爱学啊!就连我自己也经常是本来要简简单单安装个软件,比如 vokoscreen,录个视频给 konsole 的人看 bug,结果看到 vokoscreen 版本太低去更新,就把报 bug 这事岔开了。生产力就是这么低的!打包不应该那么耗时间,应该简单得像本机编译一样,甚至比那个还简单,新手才喜欢。 关于这个问题有三个办法: 第零个是不学打包直接本地编译。我烦死本地编译了,之前本地编译安装了个 basket,后来时间长了把源代码删了,没法 make uninstall,有洁癖的我就又编译了一遍就是为了卸载掉。哦对了 basket 有 kde5port 了!我当年想学 c++ 其实就是为了维护这个项目,虽然我各种待办事宜软件搞了不少,其实有 todo 的时候多半还是用脑子记,因为要么那时手头没工具要么人太烂,就好比我是学金融的却没老老实实用 skrooge 这样的手帐软件记满哪怕一个月,嘿嘿 Read more...

高手创造工具

今天整理出来了自己这些年碰过的软件包,不算 M17N 之类拥有 repo maintainer 角色的源里的软件包,就有 178 个。加上那些总量要过 300 了。 金融领域,一个基金经理维护 20 只左右股票组成的资产池就需要一个庞大的团队。300+ 的软件包几乎可以说是早到了 upper limit 了。至于技术,基本上再提高就不会是在打包这里了,而是去真正的学习各种编程语言来解决编译错误了,这其实做的已经是 upstream developer 的事情了。我的 github profile 这些年累积下来很好看,它说我的主力编程语言有 4 种(笑~),还被 Google HR 发过邮件(笑~)。 我维护着很多的中文社区相关的包。偶尔有一种莫名其妙的责任感:有用户在 forum.suse.org.cn 说哪个软件 openSUSE 没有,就想赶紧包出来,潇洒一 post。或者谁说 openSUSE 出了什么 bug,感觉就跟自己系统不能用了一样。几乎每天在 build.opensuse.org 和论坛上面站台,打包点东西,帮 factory 修修 bug。 这一年我掉到了 nodejs 和 go 这两个我到现在依然不会写的语言的大坑里去了。npm 有 200+ 个依赖,导致我其它包的维护几乎就是停滞了。 现在来看还是要上帝的归上帝,凯撒的归凯撒。论坛我不去,他们几个管的也挺好的,phoenixlzx 也没伸手要钱; 有些软件包不是我打的,比如 bcloud,大家也用上了;Leap 发布我没组织,用户一样也不少。有些空白总是能够填补的。openSUSE 是一个社区,能成长起来一批有自治意识、能够且有能力自主奉献的人就是对开源的贡献了。 而我自己的打包工作,我学了一些 ruby。元旦把之前实验性的 github.com/marguerite/golang-packaging 形成生产力了。这个项目简单说就是用 ruby 实现了一些 rpm macros。可以让你不需要真正懂 golang 的编译环境是怎么构建的、环境变量是怎么设置的,甚至连最后的 rpm 文件列表(%file)都不用你来写。你都不需要知道 openSUSE 的 golang 软件包安装到什么路径就能做出包,大大降低了打包需要了解的背景知识(当然这些知识还是记录在了 wiki 上面),只需要根据错误提示写固定格式的编译依赖(运行依赖 Requires 和 Provides 是自动处理的。甚至 Requires 都只是为了以后 golang 支持 shared linking 做的准备)。 Read more...
1 of 4 Next Page