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

前言

关于博客中的代码高亮, 最早我是 修改 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>

总体效果




评论