V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
autoxbc
V2EX  ›  前端开发

20 行代码实现一个外置式 Stylus 扩展

  •  
  •   autoxbc · 2019-10-31 13:37:07 +08:00 · 2744 次点击
    这是一个创建于 1632 天前的主题,其中的信息可能已经有所发展或是发生改变。

    长久以来我对很多浏览器扩展都是不满意的,这次重写 Stylus

    理想中的 User CSS loader 应该符合以下条件

    1 . CSS 应该是外置的,这样才能满足
    1). 方便用顺手的编辑器改写
    2). 使用预处理器
    3). 同时给多个浏览器使用
    4). 避免浏览器崩溃毁数据

    2 . CSS 应该是自匹配的,不需要额外编写规则。把 v2ex.com.css 放在硬盘上,立即对网站生效,删除后立即失效 styles.png

    3 . CSS 模块化,163.com.css 先加载,news.163.com.css 后加载,规则叠加,互不引用 link.png

    4 . CSS 应该有简单的地址查询能力

    >> www.bilibili.com.css
    /*  只对 B 站文章页面生效  */
    html[location*="/read/cv"] {
        ...some code
    }
    
    /*  只对 B 站视频页面生效  */
    html[location*="/video/av"] {
        ...some code
    }
    

    按照这个标准,写了个简易版

    Tampermonkey UserJS

    // ==UserScript==
    // @name   outboard user css loader
    // @author   autoxbc
    // @version   1.0
    // @match   *://*/*
    // @run-at   document-start
    // @require   https://wzrd.in/standalone/tldjs
    // ==/UserScript==
    
    if(location.hostname)
    {
      const root = document.documentElement ;
      root.setAttribute('location', location );
    
      let domain = tldjs.getDomain(location);
      const domains = [ domain ];
    
      const subs = tldjs.getSubdomain(location).split('.').filter( e => e ).reverse();
      subs.forEach( sub => domains.push( domain = sub + '.' + domain ) );
    
      domains.forEach( async domain => {
        const link = Object.assign( document.createElement('link') , {
          rel:'stylesheet',
          href:`https://localhost/styles/${ domain }.css`,
        } );
    
        root.append(link);
    
        const { ok } = await fetch( link.href , {
          mode:'cors',
          cache:'no-cache',
        } );
    
        if(!ok)
          link.remove();
      } );
    }
    

    tld.js 的 standalone 版本地址是 tld.js 作者 oncletom 给出的,比较安全
    https://github.com/oncletom/tld.js/issues/37

    注意:
    既然是外置式,需要准备一个文件服务器来传递数据,这里用 node.js + http-server

    http-server 启动参数

    http-server -a localhost --cors --ssl --cert cert.pem --key key.pem
    

    CORS 标志使得这里不使用特权方法 GM_xmlhttpRequest 也能跨域;
    启用 SSL 避免了浏览器的混合内容安全策略错误,需要给文件服务器添加自签名证书,OpenSSL 或者 LibreSSL 或者在线生成;
    这里也没有使用 GM_addStyle,GM_addStyle 会把 CSS 内嵌,不利于调试;现在这样更容易区分代码来自那个文件

    addStyle.png

    事实上,在我自己的系统里,不止 User CSS 外置,这个加载器也用 Tampermonkey 的 @require 外置了,所有浏览器都可以同时对接这个加载器,即 EaaS -- Extensions as a Service

    有人喜欢 Chrome,有人喜欢 Firefox,如果他们都用外置式的扩展,会不会更有趣?

    第 1 条附言  ·  2020-08-03 02:40:13 +08:00
    对于给文件服务器生成私钥和证书,建议按照 Deno 里的教程操作
    https://github.com/denoland/deno/tree/master/cli/tests/tls
    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5242 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 08:42 · PVG 16:42 · LAX 01:42 · JFK 04:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.