Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

css-diff #48

Open
webfansplz opened this issue Oct 15, 2020 · 0 comments
Open

css-diff #48

webfansplz opened this issue Oct 15, 2020 · 0 comments

Comments

@webfansplz
Copy link
Owner

Repository (仓库地址) : css-diff

Gain (收获) : css-diff 是一个对比 css 差异的库,使用它可以对比两个 css 文件的差异。收获见以下源码解析~

// a.css

.a {
  font-size: 16px;
  color: #fff;
}

// b.css

.a {
  font-size: 16px;
  color: #fff;
}

.b {
  font-weight: normal;
}
// index.js

require("css-diff")({
  files: ["./a.css", "./b.css"],
  omit: ["comment"],
  visual: true,
}).then(function (diff) {
  console.log(diff.visual); // 见下图
  console.log(diff.different); // ture
});

css-diff

源码解析

require("colors");

var cssParse = require("css-parse");
var Promise = require("bluebird");
var Diff = require("diff");
var Compiler = require("./lib/compiler.js");
var Path = require("path");

module.exports = function (options) {
  this.options = options;

  return (
    getContents
      .call(this, options.files)
      // 将两个css文件的cssom 传递给Diff.diffLines方法进行对比
      .spread(Diff.diffLines)
      // 生成差异
      .then(generateDiff)
      .catch(handleError)
  );
};

function handleError(e) {
  process.stderr.write(("Error: " + e.message + "\n").red.inverse);
  process.exit(1);
}
// 核心实现
function generateDiff(diff) {
  var different = false;
  var visual = diff.reduce(function (prev, part) {
    // 判断block是否有差异,很骚的双三元判断
    /**
     * 新增区域使用绿色渲染差异
     * 移除区域使用红色渲染差异
     * 灰色代表相同部分
     * 总结: 灰色表示相同的部分,绿色表示多出来的部分,红色表示少了的部分.
     */
    var color = part.added ? "green" : part.removed ? "red" : "grey";
    // 灰色,表示两个文件不存在差异
    if (color !== "grey") {
      different = true;
    }

    return prev + part.value[color] + "\n";
  }, "");

  return {
    different: different,
    visual: visual,
  };
}

function getContents(files) {
  var _this = this;

  if (files.length < 2) {
    return new Error("you must pass 2 file paths in");
  }

  return Promise.all(
    files.map(function (path) {
      return Compiler(Path.resolve(path)).then(function (css) {
        // 获取css字符串,使用cssParse将css字符串转换为CSSOM
        // css string -> cssom
        var rules = cssParse(css).stylesheet.rules; // 输出结果可见下图
        // 返回 序列化后的 过滤omit参数选项的cssom规则类型数组
        // 这里有个小技巧,JSON.stringify使用了space参数,用于在输出JSON字符串中插入空格以提高可读性。
        return JSON.stringify(
          rules.filter(function (rule) {
            return !~_this.options.omit.indexOf(rule.type);
          }),
          null,
          4
        );
      });
    })
  );
}

a.css,b.css cssom rules output

rules

思考

// 以下代码,你觉得输出的会是什么呢?

require("css-diff")({
  files: ["./b.css", "./a.css"],
  omit: ["comment"],
  visual: true,
}).then(function (diff) {
  console.log(diff.visual);
  console.log(diff.different);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant