烧饼论坛 LZ.SB
登录

Blogger/blogspot 引入 google 的 code-prettify 实现代码高亮 并保留手动设置的文字颜色

412
  • crazypeace
    UID 313Lv.3 初识社区

    前言

    关于博客中的代码高亮, 最早我是 修改 blockquote 的CSS 来实现 代码段 的显示效果

    后来实验  引入google的code-prettify实现代码高亮 把blockquote转换为pre code

    最后 因为代码高亮会把我在代码段中设置的文字底色清除, 换回了 修改 blockquote 的CSS 来实现 代码段 的效果

    现在我让 blogger编辑器可以输入pre和code了, 所以我用 blockquote 真的去表示引用, 引用我发送给 Agent 的自然语言, 这也确实是我最近几个月使用非常多的场景.

    我也通过 Agent 操作Blogger API 帮助我把历史博文中的 blockquote 换成了 pre

    现在我重新考虑代码高亮的问题.

    面向 Agent 开发

    Hermes 对接 白嫖 公益站agentrouter 的 deepseek-v4-flash

    思路 1

    我现在想把 google 的 code-prettify 代码高亮 功能加回来

    但是, 还是面临 代码高亮会把我在代码段中设置的文字底色清除 的问题

    我一开始的想法是, 

    在 Blogger/blogspot 模板中, 加一个 script 用来给 pre 加 class="prettyprint".
    那么这个脚本可以分析 pre 中是否有手动设置文字颜色 的情况.
    如果有手动设置文字颜色, 那么就不给这个 pre 加 class="prettyprint"

    我就是把上面这段话发给 Agent 修改 Blogger/blogspot 的 xml 模板

    关键函数

    <!-- 为所有 pre 添加 class='prettyprint'(pre 内部已手动设置颜色/背景色的则不添加) -->
    <script type='text/javascript'>
    //<![CDATA[
    (function(){
      /* 判断某个元素及其所有子孙元素是否设置了颜色或背景色 */
      function hasCustomColor(root){
        var elements=[root].concat(Array.prototype.slice.call(root.querySelectorAll('*')));
        for(var i=0;i<elements.length;i++){
          var el=elements[i];
          /* 1. 行内 style 中的 color / background-color / background */
          var styleAttr=el.getAttribute('style');
          if(styleAttr&&/(^|;|\s)(color|background-color|background)\s*:/i.test(styleAttr))return true;
          /* 2. 旧式 HTML 属性 bgcolor / color(如 <font color="red">) */
          if(el.hasAttribute('bgcolor')||el.hasAttribute('color'))return true;
        }
        return false;
      }
      function markPre(){
        document.querySelectorAll('pre').forEach(function(el){
          if(!hasCustomColor(el))el.classList.add('prettyprint');
        });
      }
      function run(){
        markPre();
        if(window.PR&&typeof PR.prettyPrint==='function')PR.prettyPrint();
      }
      if(document.readyState==='loading'){
        document.addEventListener('DOMContentLoaded',run);
      }else{
        run();
      }
      /* 兜底: run_prettify.js 异步就绪后一定能高亮 */
      window.addEventListener('load',function(){
        if(window.PR&&typeof PR.prettyPrint==='function')PR.prettyPrint();
      });
    })();
    //]]>
    </script>
    

    但是, 这样的话, 没有经过 prettify 处理的 pre 和经过了处理的 pre, 有了较大的不同.

    思路 2

    那么, 还有没有什么办法可以保留 pre 中手动设置的文字颜色呢?

    我找到了 google 的 code-prettify 的源码 https://github.com/googlearchive/code-prettify 让 Agent 结合我的博客 html 一起分析.

    分析结果是:

    1. pre 中手动设置了文字的颜色, 再经过 prettify 处理, 会变成这样

    <span style="color:red"><span class="pun">红色文字</span></span>
    

    2. 显色的原理
    外层 style 设置为红色, 里层 class 根据 prettify 的 CSS 设置颜色

    3. 解决方案
    设置 CSS, 当 prettify 的 class 的父元素 是手动设置颜色的, 那么 prettify 的 class 颜色无效

    pre.prettyprinted :is(span[style*="color"], span[style*="background"], font[color], [bgcolor])
      :is(.pln,.kwd,.str,.com,.typ,.lit,.pun,.opn,.clo,.tag,.atn,.atv,.dec,.var,.fun) {
      color: inherit !important;
    }
    

    相应的, 给 pre 加 class="prettyprint" 的脚本也大大简化

    <!-- 为所有 pre 添加 class='prettyprint'; 手动颜色由 b:skin 中 CSS 保护 -->
    <script type='text/javascript'>
    //<![CDATA[
    (function(){
      function run(){
        document.querySelectorAll('pre').forEach(function(el){el.classList.add('prettyprint')});
        if(window.PR&&typeof PR.prettyPrint==='function')PR.prettyPrint();
      }
      if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',run);else run();
      /* 兜底: run_prettify.js 异步就绪后一定能高亮 */
      window.addEventListener('load',function(){if(window.PR&&typeof PR.prettyPrint==='function')PR.prettyPrint();});
    })();
    //]]>
    </script>
    

    总体效果

  • 收藏支持反对打赏

2 条回复

  • mubdao
    UID 1206Lv.12 热心成员
    #1

    bd 支持

  • Kutnahola
    UID 3059Lv.5 小有收获
    #2

    原来是大神级

发表回复