Minimal and Clean blog theme for Hugo

用html字符串生成dom元素


https://stackoverflow.com/a/35385518/6021280

/**
 * @param {String} HTML representing a single element
 * @return {Element}
 */
function htmlToElement(html) {
    var template = document.createElement('template');
    html = html.trim(); // Never return a text node of whitespace as the result
    template.innerHTML = html;
    return template.content.firstChild;
}

var td = htmlToElement('<td>foo</td>'),
    div = htmlToElement('<div><span>nested</span> <span>stuff</span></div>');

/**
 * @param {String} HTML representing any number of sibling elements
 * @return {NodeList} 
 */
function htmlToElements(html) {
    var template = document.createElement('template');
    template.innerHTML = html;
    return template.content.childNodes;
}

var rows = htmlToElements('<tr><td>foo</td></tr><tr><td>bar</td></tr>');
Read more ⟶

监听dom元素的class值变化


参考资料:

  1. stackoverflow
  2. MDN文档:MutationObserver

MutationObserver

这个类可以监听指定 DOM 的变化。

下面的代码创建监听了一个元素,并在class变化时出发回调函数。

let targetNode = document.getElementById('test')

function workOnClassAdd() {
    alert("I'm triggered when the class is added")
}

function workOnClassRemoval() {
    alert("I'm triggered when the class is removed")
}

// watch for a specific class change
let classWatcher = new ClassWatcher(targetNode, 'trigger', workOnClassAdd, workOnClassRemoval)

// tests:
targetNode.classList.add('trigger') // triggers workOnClassAdd callback
targetNode.classList.add('trigger') // won't trigger (class is already exist)
targetNode.classList.add('another-class') // won't trigger (class is not watched)
targetNode.classList.remove('trigger') // triggers workOnClassRemoval callback
targetNode.classList.remove('trigger') // won't trigger (class was already removed)
targetNode.setAttribute('disabled', true) // won't trigger (the class is unchanged)
class ClassWatcher {

    constructor(targetNode, classToWatch, classAddedCallback, classRemovedCallback) {
        this.targetNode = targetNode
        this.classToWatch = classToWatch
        this.classAddedCallback = classAddedCallback
        this.classRemovedCallback = classRemovedCallback
        this.observer = null
        this.lastClassState = targetNode.classList.contains(this.classToWatch)

        this.init()
    }

    init() {
        this.observer = new MutationObserver(this.mutationCallback)
        this.observe()
    }

    observe() {
        this.observer.observe(this.targetNode, { attributes: true })
    }

    disconnect() {
        this.observer.disconnect()
    }

    mutationCallback = mutationsList => {
        for(let mutation of mutationsList) {
            if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
                let currentClassState = mutation.target.classList.contains(this.classToWatch)
                if(this.lastClassState !== currentClassState) {
                    this.lastClassState = currentClassState
                    if(currentClassState) {
                        this.classAddedCallback()
                    }
                    else {
                        this.classRemovedCallback()
                    }
                }
            }
        }
    }
}
Read more ⟶

调试proxy对象


当我们打了断点时,proxy对象的属性看到的都是...,很不方便。

这些对象都可以在console中打印出来。利用这一点,我们可以先将lodash引入到console中,利用_.cloneDeep方法,将proxy对象的属性克隆一份,然后再打印出来。

fetch('https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js')
    .then(response => response.text())
    .then(text => eval(text))
_.cloneDeep(this.queryOptions)
Read more ⟶

正则表达式怎么用


reg, _ := regexp.Compile(`\s+`)
r := reg.ReplaceAll(resBody, []byte(""))

compile string to regexp, then replace all

Read more ⟶

趣闻轶事


Read more ⟶

protocol-buffer使用记录


参考资料:

  1. https://developers.google.com/protocol-buffers/docs/gotutorial
  2. https://developers.google.com/protocol-buffers/docs/reference/go-generated#package

内容

  1. 根据自己的需要,定义protocol buffer,定义请求、相应、service。
  2. protoc生成grpc.go和pb.go文件
  3. 实现grpc的service接口
  4. 调用service实现
syntax = "proto3";
package tutorial; // 定义报名,避免命名冲突

option go_package="/services";

import "google/protobuf/timestamp.proto";

message Person {
  string name = 1; // 
  int32 id = 2;  // Unique ID number for this person.
  string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    string number = 1;
    PhoneType type = 2;
  }

  repeated PhoneNumber phones = 4;

  google.protobuf.Timestamp last_updated = 5;
}

// Our address book file is just one of these.
message AddressBook {
  repeated Person people = 1;
}

每个元素上的“= 1”、“= 2”标记标识字段在二进制编码中使用的唯一“标签”。标记数字 1-15 需要比更高数字少一个字节来编码,因此作为一种优化,您可以决定将这些标记用于常用或重复的元素,而将标记 16 和更高的标记用于不太常用的可选元素。重复字段中的每个元素都需要重新编码标签编号,因此重复字段特别适合这种优化。

Read more ⟶

Uml


摘要,显示在meta的description中
Read more ⟶

设置自动引入为单引号


WebStorm设置
Read more ⟶

Chrome插件开发


background-warp.js

background.js

// 监听页面的加载完成事件
chrome.webNavigation.onCompleted.addListener(
  function (data) {
    // 调用sotrage存放或设置一些数据
    chrome.storage.local.set({ resolvedBuildValue }, function () {
      console.log('Value is set to ' + resolvedBuildValue);
    });
    
    // 调用scripting执行插入脚本的操作
    chrome.scripting.executeScript({
      target: { tabId: data.tabId },
      function: function(){
        // 可以正常的调用document的相关api控制页面内的元素
      },
      // files: ['content-script.js'],
    });

    // 调用scripting执行插入css样式的操作
    chrome.scripting.insertCSS(
      {
        target: { tabId: data.tabId },
        css: 'body{background: red;}', // 一个css样式的字符串
      }
    );
  }
)
interface data {
  frameId: number
  parentFrameId: number
  processId: number
  tabId: number
  timeStamp: number
  url: string

}
interface target {
  tabId:;
  allFrame?: boolean;
}

exceScript

Read more ⟶

企业微信机器人


机器人

hover机器人,卡片右上角的编辑按钮可以看到机器人配置说明。 gitlab的webhook可以在mr时发一个请求。企业微信的机器人可以接受消息,但是两边的消息格式不同,需要有一个中间人进行翻译。

总体流程是:发生了mr,发请求到服务器,服务器根据mr消息中的user找到user所属的群,向该群的机器人发送一条消息,同时消息内容要根据mr的action应该不同,有些mr消息(更新,关闭等)不需要处理。

解析mr

mr的数据我们只需要其中几条信息。

{
  "user": {
    "name": "",
  },
  "object_attributes": {
    "url":"",
    "action":"",
  }
}

人与机器人的映射

需要两个表来实现这个映射。

  1. user <-> group
  2. group <-> robot

因为关系比较简单,可以暂时不用数据库,就手动创建好变量,在代码中维护就行。但是如果数据多来还是需要用数据库。

给机器人的消息

发给机器人的消息格式(https://work.weixin.qq.com/api/doc/90000/90136/91770)

我们使用markdown格式,可以把长长的链接写成一个超链接的形式:

{
    "msgtype": "markdown",
    "text": {
        "content": "【张三】【发起或合并】了mr【[编号](http://123456)】",
        "mentioned_list":["wangqing","@all"]
    }
}
Read more ⟶