npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@instaceof/b-util

v1.1.1

Published

common use js tools lib

Downloads

3

Readme

##结构

.eslintignore eslint 验证过滤

Install

npm install @instaceof/b-util  -D


//1、
import {isArray,isString} from '@instaceof/b-util';
console.log(isArray([])); // ture
console.log(isString('String')); // ture

//2、
import B from '@instaceof/b-util';
console.dir(B);
console.log(B.isArray([])); // ture
console.log(B.isString('String')); // ture

//3、
 import isArray from '@instaceof/b-util/isArray';  // [each,inArray,index,lastIndex,addDays,addYear,formatDate,getweek,now,nowTick,later]
 import isString from '@instaceof/b-util/isString';
 console.log(isArray([])); // ture
 console.log(isString('String')); // ture

//4、
import isNo from '@instaceof/b-util/isNo';  //  [arrayModel,dateModel,functionModel,isNo,link,media,objectModel,string,validate]
console.log(isNo)
console.log(isNo.isArray([])); // ture
console.log(isNo.isString('String')); // ture

examples

src
├── arrayModel
│   ├── each.js
│   ├── inArray.js
│   ├── index.js
│   └── lastIndex.js
├── dateModel
│   ├── addDays.js
│   ├── addYear.js
│   ├── formatDate.js
│   ├── getweek.js
│   ├── now.js
│   └── nowTick.js
├── functionModel
│   └── later.js
├── isNo
│   ├── is.js
│   ├── isArray.js
│   ├── isBoolean.js
│   ├── isDate.js
│   ├── isEmptyObject.js
│   ├── isFunction.js
│   ├── isHttps.js
│   ├── isNull.js
│   ├── isNumber.js
│   ├── isObject.js
│   ├── isRegExp.js
│   ├── isString.js
│   └── isUndefined.js
├── link
│   ├── cookie.js
│   ├── localStorage.js
│   ├── sessionStorage.js
│   ├── uri.js
│   ├── urlAddParam.js
│   ├── urlDecode.js
│   └── urlEncode.js
├── media
│   └── UA.js
├── objectModel
│   ├── _mix.js
│   ├── cleanObject.js
│   ├── clone.js
│   ├── keys.js
│   └── mix.js
├── string
│   └── strTemplate.js
└── validate
    ├── isBankCard.js
    ├── isIdCard.js
    ├── isPhoneNum.js
    └── validateMobile.js

API

See this dir

├── arrayModel
          /**
           * 循环操作
           * @param object
           * @param fn
           * @param context
           * @returns {*}
           */
│   ├── each.js
          /**
           * 检查是否包含在数组中
           * @param item
           * @param arr
           * @returns {boolean}
           * inArray(item,arr)
           */
│   ├── inArray.js
          /**
           * 检查指定的参数在数组中的位置  不存在 返回-1
           * @param item
           * @param arr
           * @param fromIndex
           * @returns {*}
           * index(item, arr, fromIndex)
           **/
│   ├── index.js
           /**
            * 与 index类似 arr倒序计算位置
            * @param item
            * @param arr
            * @param fromIndex
            * @returns {*}
            * lastIndex (item, arr, fromIndex)
            */
│   └── lastIndex.js
├── dateModel
            /**
             * 添加天数
             * @param date
             * @param days
             * @returns {*}
             * addDays(date, days)  
             */
│   ├── addDays.js
            /**
             * 添加年
             * @param date
             * @param days
             * @returns {*}
             * addYear(date, year)
             */
│   ├── addYear.js
            /**
             * 格式化时间
             * @param date
             * @param strFormat   //yyyy.MM.dd hh:mm:ss q   月(M)、日(d)、小时(h)、分(m) 、秒(s)、  毫秒(S) 季度(q)
             * @param sms  默认秒  // ms 毫秒  s 秒
             * @returns {*}
             * formatDate(date, strFormat, sms)
             */
│   ├── formatDate.js
            /**
             * 获取当前星期日期
             * @param date
             * @param isChEn  // 默认中文  'en'  英文
             * @returns {string}
             * getweek (date, isChEn)
             */
│   ├── getweek.js
            /**
             * 现在的时间
             * @returns {Date}
             * now()
             */
│   ├── now.js
            /**
             * 现在的时间
             * @returns {Date}
             * now()
             */
│   └── nowTick.js
├── functionModel
        /**
         * 定时器
         * @param method
         * @param time
         * @param isInterval
         * @param context
         * @param data
         * @returns {{cancel: cancel, timer: number, isInterval: *}}
         * timer:0   
         * timer= later(()=>{console.log(500) }, 500); // 500毫秒后执行  
         * timer= later(() => {}, 1000, true);  // 1000秒 循环执行
         * timer.cancel(); // 关闭定时器
         */
│   └── later.js
├── isNo
│   ├── is.js
          /**
           * 数组类型判断
           * @param obj
           * @returns {*|boolean}
           * isArray(obj)
           */      
│   ├── isArray.js
            /**
             * 布尔类型判断
             * @param obj
             * @returns {boolean|*|Boolean}
             * isBoolean(obj)  
             */
│   ├── isBoolean.js
            /**
             * 时间类型判断
             * @param obj
             * @returns {boolean|*|Boolean}
             * isDate(obj)
             */
│   ├── isDate.js
            /**
             * 对象是否为空判断
             * @param obj
             * @returns {boolean|*}
             * isEmptyObject(obj)
             */
│   ├── isEmptyObject.js
            /**
             * fun 类型判断
             * @param obj
             * @returns {*|boolean}
             * isFunction(obj)
             */
│   ├── isFunction.js
            /**
             * 判断是否是https地址
             * @param obj // 默认 window.document.location.protocol
             * @returns {boolean}
             * isHttps(obj)
             */
│   ├── isHttps.js
            /**
             * null类型判断
             * @param obj
             * @returns {*|boolean}
             * isNull(obj)
             */
│   ├── isNull.js
            /**
             * 数字类型判断
             * @param obj
             * @returns {*|boolean}
             * isNumber(obj)
             */
│   ├── isNumber.js
            /**
             * 对象类型判断
             * @param obj
             * @returns {*|boolean}
             * isObject(obj)
             */
│   ├── isObject.js
            /**
             * 是否是正则表达式判断
             * @param obj
             * @returns {*|boolean}
             * isRegExp(obj)
             */
│   ├── isRegExp.js
            /**
             * 字符串类型判断
             * @param obj
             * @returns {*|boolean}
             * isString(obj)
             */
│   ├── isString.js
            /**
             * undefined 类型判断
             * @param obj
             * @returns {*|boolean}
             * isUndefined(obj)
             */
│   └── isUndefined.js
├── link
            /**
             * cookie操作
             * @type {{set: cookie.set, get: cookie.get, clear: cookie.clear}}
             * cookie.set(name, value, minutes, domain)  
             * cookie.get(name)
             * cookie.clear(name, domain)
             */
│   ├── cookie.js
            /**
             * 本地储存-浏览器关闭销毁
             * @type {{set: set, get: (function(*): any|string), clear: clear}}
             * sessionStorage.set(name, val)
             * sessionStorage.get(name)
             * sessionStorage.clear(name)
             */
│   ├── localStorage.js
            /**
             * 本地储存-永久
             * @type {{set: set, get: (function(*=): any|string), clear: clear}}
             * localStorage.set(name, val)
             * localStorage.get(name)
             * localStorage.clear(name)
             */
│   ├── sessionStorage.js
            /**
             * 获取页面参数
             * @param url // 默认 location.href
             * @returns {*}
             * uri(url)
             * uri() // 全部参数
             * uri().name  // 获取指定name参数
             */
│   ├── uri.js
            /**
             * 传入对象返回url参数
             * @param data
             * @param iSquestionMark // true 默认带 ?   false 不带?
             * @returns {string|string|string}
             * urlAddParam({url1:'url1',url2:'url2'})
             */
│   ├── urlAddParam.js
            /**
             * url解码
             * @param  url
             * @param {String} url 这是url的一部分被解码.
             * @return {String} 解码的url部分字符串
             *  urlAddParam=(data, iSquestionMark=true)
             * urlAddParam({url1:'url1',url2:'url2'})
             */
│   ├── urlDecode.js
            /**
             * url编码
             * @param  url
             * @return {String} 已编码的url部分字符串
             * urlEncode(url)
             */
│   └── urlEncode.js
├── media
        /**
         * 终端识别
         * @type {{trident: undefined, opera: undefined, chrome: undefined, safari: undefined, os: undefined, phantomjs: undefined, firefox: undefined, android: undefined, mobile: undefined, nodejs: undefined, webkit: undefined, ios: undefined, iphone: undefined, ipod: undefined, core: undefined, gecko: undefined, shell: undefined, ipad: undefined, ie: undefined, presto: undefined, ieMode: undefined}}   
         * UA() 
         */
│   └── UA.js
├── objectModel
            /**
             * 对象混合
             * @param target
             * @param resource
             * @private
             * _mix(target, resource)
             */
│   ├──  _mix.js
        /**
         * 扩展
         * @param target    当前对象
         * @param resource  资源对象
         * @param overwrite 是否重写
         * @param whiteList 白名单
         * @param deep      是否深度复制
         * mix (target, resource, overwrite, whiteList, deep)
         */
│   ├──  mix.js
            /**
             * 去除对象中value为空(null,undefined,'')的属性,举个栗子:
             * @param object
             * @returns {{}|*}
             * B.cleanObject({"name":'','go':'123456'}
             */
│   ├── cleanObject.js
            /**
             * 克隆对象
             * @param obj
             * @returns {*}
             * clone(obj)
             */
│   ├── clone.js
            /**
             * 获取对象属性名
             * keys(obj)
             */
│   └── keys.js
├── string
            /**
             * 待删除 
             * 替换模块字符串中的占位符
             * ,例如s = <span id="aaa">{{a}}</span>
             * val = {a:111}
             * 结果为:<span id="aaa">111</span>
             * 如果,
             * val = [{a:111}, {a:222}]
             * split = <br/>
             * 结果为:
             * <span id="aaa">111</span><br/><span id="aaa">222</span>
             *
             * @param {string} s 模板字符串,例如<span>{{b}}</span>
             * @param {Object|array} val 值
             * @param {string} split 数组分割字符
             */
│   └── strTemplate.js
└── validate
    /**
     * 国际标准的银行卡号(储蓄卡和信用卡),注意:不包括各个银行的企业账户
     * @param str
     * @returns {boolean}
     * isIdCard(str)
     */
    ├── isBankCard.js
    /**
     * 中国的身份证号码
     * isIdCard(str)
     */
    ├── isIdCard.js
    /**
     * 中国三大运营商的电话号码
     * isPhoneNum(str)
     */
    ├── isPhoneNum.js
    /**
     * 手机号码格式验证
     * @param rule
     * @param value
     * @param callback
     * validateMobile(rule, value, callback)
     */
    └── validateMobile.js

bai-util.js

npm

A small JavaScript utility library.

Package with rollup.js, exported as iife amd cmd cjs umd es6 module.

Support most modern browsers, not include IE. Support Node 8+.

框架搭建教程:打造一个类似于lodash的现代前端工具库

API

See this dir

License

Released under the MIT Licenses.

参考博客:https://www.dgg.red/

一、分析借鉴目前最主流的前端工具库

我分析了github上多个前端工具库的设计,以lodash为例说明:

lodash的工程,有master、npm、npm-package、amd分支,以及 多种类型的tag:

4.17.10(umd)

4.17.10-npm

4.17.10-es

4.17.10-amd

这 4个分支 + 4个tag 的代码甚至工程结构,都不太一样。

我目前还看不明白它这么多套代码,是分开维护的,还是只维护一套,其他都是自动生成的?

因为所有8个分支的配置我都检查过了,并没有发现自动生成多份代码的相关配置。

而且lodash工程里面并没有babel的配置,难道lodash各个版本的代码是分开维护的?



本来想模仿lodash的工程脚手架,无奈看了半天看不懂。但是它的功能我基本清楚了:

1、umd模块,分为 lodash-core.js 和 lodash.js 、lodash-fp.js 三部分,提供了 未压缩包和压缩包(貌似没有看到source map)。

  lodash-fp 即 (Functional Programming)函数式编程,对于_.map等部分方法,lodash提供了FP版本。

2、npm模块(也是CommonJS版),有各个主功能模块(比如array),都是require和module.export形式,除了lodash.js提供了min压缩版,其他都是源码无压缩。

3、AMD版,全部都是源码无压缩,有主功能模块(比如array),都是define引入/导出模式,但是没有lodash.js统一入口模块。

4、es模块,全部都是源码无压缩,主功能模块全部提供了 default引入形式(例如array.default.js)以便支持 import array from 'lodash/array'。

5、npm模块,分成很多子项目,每一个函数都可以单独install。



除了lodash,我还分析了vue和react的工程构建方式,并学习了rollup、jest等。



二、设计前端工具库



我想达到的目的:

1、要支持 es6、node-cjs 和 浏览器 script直接引入,暂时不单独考虑支持amd;

2、只维护一套代码,其他均有工具自动生成;

3、浏览器版本的,支持source map,其他版本都是源码形式提供;

4、cjs、es6版本,支持按函数和主功能模块(例如array、date)引入,es6版本还提供对import xxx 这种形式的支持;

5、浏览器版本的,暂时不分模块,只能支持全部引入,后面根据情况可以提供core等精简版本。



关于源码的书写和维护:

目前大多数工具库,都是用的es6语法,我看vue源码是用的带type类型的es6(好像叫flow),lodash源码好像是es6(master分支),而react用的好像也是自家的flow,只有谷歌的angular2用的typescript。

所以我考虑采用 es6来编写,但不排除以后换成ts。



具体做法:



使用es6语法来编写工具类,并把源代码原原本本提供出去,同时生成一份umd格式的,包含源码、压缩包和source map。

整个target(dist)内容示例如下:

// 所有函数
isArray.js
isString.js
...
collection.js // 主功能模块
collection.default.js // xxx.default.js用于支持es6的直接import
...
bai-util.esm.js // 主模块es源码,相当于 index.js、main.js
bai-util.esm.default.js // xxx.default.js用于支持es6的直接import xxx from 'xxx.js',并且用它来生成umd版本
bai-util.js // umd版本的源码,根据bai-util.esm.default.js自动生成
bai-util.min.js // umd版本压缩后的代码
bai-util.min.map // umd版本压缩代码的source map


xxx.default.js 说明

以collection.js为例:

collection.default.js代码如下:

import toMapKey from './toMapKey.js';
import toMapValue from './toMapValue.js';
// 支持单个引入 import { toMapKey, toMapValue } from 'collection.default'
// 也可以像这样全部引入 import * as coll from 'collection.default';
export default {
toMapKey,
toMapValue,
}
collection.js代码如下:

// 支持单个引入 import { toMapKey, toMapValue } from 'collection'
export { default as toMapKey } from './toMapKey.js';
export { default as toMapValue } from './toMapValue.js';
 
// 支持default(默认)引入 import coll from 'collection'
export { default } from './collection.default.js';
即 collection.default.js 只是供 collection.js 来引入的,其作用是为它提供 export default 的功能,以支持能直接 import coll from 'collection'。



上面是target(dist)的目录,那么源码src目录应该是怎样呢?

维护源码的时候,应该分模块,比如 集合相关的工具函数,放到 src/collection/ 目录下

src / 

|--collection / 

|  |--- toMapValue.js

|  |--- toMapKey.js

|  |---  ......

|--array / 

|-- .....

|--bai-util.js

|_______________

构建的时候,将所有模块都拷贝到target(dist)目录下,同时自动生成各模块的主module和总module。



关于构建工具

经我广泛的研究,结论如下:

1、应用类的工程,用webpack来打包;

2、工具类的工程,用rollup来打包,例如vue和react,都是用的rollup来打包。



所以,这个工程,决定用rollup来打包,而不是webpack。

rollup打包出来,代码更干净,就像自己写的代码一样,而webpack打包出来,会添加很多其他的代码。



其他功能

1、单元测试

使用jest来做单元测试。



2、持续集成

使用 travis。



git代码地址:https://github.com/instanceofs/B.js

npm仓库地址:https://www.npmjs.com/package/@instaceof/b-util



三、架构和技术说明



技术列表如下:



核心技术:

babel
rollup
jest
terser
eslint


辅助技术

cross-env
commitlint // 检查git commit,要求其符合规范
semantic-release
husky // 拦截不符合规范的git commit和push
travis-deploy-once
 
codecov
jshint
editorconfig
browserslist


技术说明:



使用rollup构建

配置在根目录下面的 rollup.config.js 



在使用 rollup 构建之前,会先准备打包文件,会执行node build/prepare

build/prepare.js的基本作用是 把 src 下面的文件拷贝 到 tmp 目录,同时生成 子模块的js,例如 bai-util.esm.js、collection.js、collection.default.js

同时,会修正js中import的路径。



需要说明的是,rollup.config.js配置中的

globals(),

builtins(),

localResolve(),

resolve()

commonjs()

这些应该暂时还没用到。

export出的配置,是一个数组,不同的input文件,输出配置不一样,

例如 对于 tmp/main.js (实际上为bai-util.esm.js)文件,输出了 umd、iife、cjs 三种格式,

同时,在bai-util.esm.js的基础上,再次转换成  bai-util.es.js (es6 module的es5语法的文件),之所以要转换成 es5语法,其初衷是想它被其他模块引入时,不需要babel转换也能直接使用,bai-util.es.js会被当做本js库的package.json的main入口。(其实,我也不确定这样做到底有多少意义),具体参见这篇文章的描述:https://loveky.github.io/2018/02/26/tree-shaking-and-pkg.module/



其配置文档,参见:

深入学习rollup来进行打包

JS打包工具rollup——完全入门指南

使用模块化工具打包自己开发的JS库

https://rollupjs.org/guide/zh#npm-packages

https://github.com/rollup/rollup



使用terser压缩es6语法的 js

terser是uglify-es6的增强版,因为uglify不支持es6,而uglify-es6又停止更新了,故推出了terser

terser支持和rollup集成,但是我在rollup打包过程不包含js压缩,为更灵活的控制 js压缩,我单独写了个脚本 ,执行node build/minify来处理压缩。



我是用的terser默认的配置,只是添加了 sourcemap的生成。



terser使用文档如下:

https://github.com/terser-js/terser



babel 及 browserslist 配置

rollup构建时,引入了  rollup-plugin-babel 插件,会调用 babel 对js进行处理。

babel的配置文件为:.babelrc.js

我使用 的是 babel 7(@babel/[email protected]),其配置和 babel 6有很大的不一样。

目前,只配置了一个babel-preset-env,其说明参见:

https://babeljs.io/docs/en/babel-preset-env/#how-it-works

https://www.babeljs.cn/docs/setup#installation

另外,babel 默认使用 .browserslistrc 的配置,其内容如下:

> 5%
current node
not dead
等价于 在package.json中配置 [ "browserslist": "> 5%, current node, not dead" ]

对于browserslist的使用,参见其说明文档:https://github.com/browserslist/browserslist



jest 单元测试配置

配置放在 jest.config.js 文件中

主要设置了 "verbose": true 以报告每个测试的执行情况,显示执行时间。

其配置文档参见:https://jestjs.io/docs/zh-Hans/configuration



注意,jest 需要依赖 babel-jest,要依赖babel 6,需要安装 babel 6 和 babel 7的桥接。

babel-jest,文档:https://www.npmjs.com/package/babel-jest

文档中说,如果使用babel 7的话,需要安装babel 6~7的桥接版本'babel-core@^7.0.0-bridge'



单元测试的代码,统一放在了 __test__ 目录下,这个是 jest 默认扫描的目录之一(该目录下面的js文件都会执行),无需配置。



注意,jest 测试代码,我也用的是 es6语法。



IDE(VS Code)使用 eslint 插件检查和自动更正 js 代码



在 vs code 编辑器中 安装了 eslint 插件,

并在IDE中配置了如下(setting.json):

{
  "terminal.integrated.shell.windows": "D:\\C\\Program Files\\Git\\bin\\bash.exe",
  "eslint.autoFixOnSave": true,
  "eslint.options": {
    "plugins": ["html"],
    "extensions": [".js", ".vue"]
  },
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    {
      "language": "vue",
      "autoFix": true
    },
    {
      "language": "html",
      "autoFix": true
    }
  ],
  "vue-peek.supportedLanguages": ["vue"],
  "vue-peek.targetFileExtensions": [".vue", ".js"],
 
  // 开启保存时自动format,一定要配合下面的format组件一起使用
  "editor.formatOnSave": true,
    // 使用prettier来format代码,相关配置如下:
  "prettier.singleQuote": true,
  "prettier.semi": false,
  "vetur.format.defaultFormatterOptions": {
    "prettier": {
      "singleQuote": true,
      "semi": false
    }
  },
  // 使用js-beautify替换prettier
  // "vetur.format.defaultFormatter.html": "js-beautify-html",
    "explorer.autoReveal": false,
  "workbench.editor.enablePreview": false,
  "terminal.integrated.scrollback": 10000,
  "javascript.updateImportsOnFileMove.enabled": "always",
  "files.associations": {
    ".jshintrc": "jsonc",
    ".eslintrc": "jsonc"
  }
}
注意到上面的,files.associations 这个配置是为了 在json中支持注释。



另外,我配置了 .eslintignore,用来排除 部分目录和代码,不进行eslint 校验。



另外,我安装了jshint插件(本工程无需这个插件),需要在工程根目录 新建 .jshintrc 文件,内容如下;

{
 "undef": true,
 "unused": true,
 "esversion": 6,
 "asi": true
}
jshint详细配置参见:https://jshint.com/docs/options/



命令行使用 eslint 检查 js 代码

运行 eslint --ext .js ./src 即可检查 js 源码是否符合规范。

eslint的配置文件为 .eslintrc,内容如下:

{
  "extends": "airbnb-base",
  "env": {
    "jest": true,
    "browser": true,
    "node": true,
    "es6": true
  },
  "rules": {
    "semi": [0, "never"],
    "semi-spacing": [2, {
      "before": false,
      "after": true
    }]
  }
}
semi": [0, "never"] 代表,js无 分号结尾,0代表有分号结尾也不报错。

其配置说明参见:

https://eslint.org/docs/rules/

https://blog.csdn.net/helpzp2008/article/details/51507428



使用 commitlint 检查 git commit规范

使用的@commitlint这个插件,其配置文件commitlint.config.js 如下:

module.exports = {
  extends: ['@commitlint/config-angular']
};
其允许的注释前缀如下:

['build',
  'ci',
  'docs',
  'feat',
  'fix',
  'perf',
  'refactor',
  'revert',
  'style',
  'test'
]

feat: feature缩写,用户相关的新功能,构建脚本功能除外
fix: 修改 bug
perf: 更改代码,以提高性能(在不影响代码内部行为的前提下,对程序性能进行优化)
refactor: 为了可读性或者性能,在不改变原有功能的前提下做的修改
docs: 文档的变更
style: 代码格式修改, 注意不是 css 修改(例如分号修改)
test: 增加或重构了测试代码,但没有增加产品代码
build: 影响项目构建或依赖项修改
revert: 恢复上一次提交
ci: 持续集成相关文件修改
chore: 更新构建脚本,但是不会更新产品代码
release: 发布新版本
workflow: 工作流相关文件修改

例如 git commit -a -m 'build: refactor' 是合格的注释。



具体参见:

https://www.npmjs.com/package/@commitlint/config-angular

https://github.com/webpack-contrib/terser-webpack-plugin/blob/master/commitlint.config.js



使用 IDE 的 EditorConfig 插件规范 文件文本格式

vscode 请安装插件:CTRL+SHIFT+X 搜索 EditorConfig 并安装,

然后在项目中新建 .editorconfig 文件,内容如下:

root = true
 
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
 
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false
这个工具的一个重要作用是,将新建文件和保存的文件,自动更正 为 lf 换行符。(不然的话,windows默认的换行符是 crlf)