目录
Naming Project
HTML
- 语法
- HTML5 doctype
- 语言属性
- 字符编码
- IE 兼容模式
- 引入 CSS 和 JavaScript
- 实用高于完美
- 属性顺序
- Boolean 属性
- 减少标签数量
- JavaScript 生成标签
CSS
- CSS 语法
- 声明顺序
- 不要用 @import
- 媒体查询位置
- 前缀属性
- 单条声明的声明块
- 属性简写
- Less 和 Sass 中的嵌套
- 代码注释
- Class 命名
- 选择器
- 代码组织
- Harry Roberts写的CSS最佳指引
JavaScript
- Indentation,分号,单行长度
- 空行
- 变量命名
- 字符常量
- null使用场景
- undefined使用场景
- Object 字面量
- Array 字面量
- 单行注释
- 多行注释
- 文档注释
- 括号对齐
- if else
- switch
- for
- 变量声明
- 函数声明
- 杂项
- 编辑器配置
- GitHub上更加大而全的JavaScript代码规范
黄金定律
永远遵循同一套编码规范 -- 可以是这里列出的,也可以是你自己总结的。如果你发现本规范中有任何错误,敬请指正。通过open an issue为本规范添加或贡献内容。不管有多少人共同参与同一项目,一定要确保每一行代码都像是同一个人编写的。
项目命名
项目名全部采用小写方式, 以中划线分隔。 比如: my-project-name
目录名
目录名参照上一条规则,有复数结构时,要采用复数命名法,比如说: scripts, styles, images, data-models
JavaScript文件命名
所有js文件名,多个单词组成时,采用中划线连接方式,比如说: 账号模型文件 account-model.js
CSS,SCSS文件命名
多个单词组成时,采用中划线连接方式,比如说:retina-sprites.scss
HTML文件命名
多个单词组成时,采用中划线连接方式,比如说: error-report.html
HTML
语法
- 使用四个空格的 soft tabs — 这是保证代码在各种环境下显示一致的唯一方式。
- 嵌套的节点应该缩进(四个空格)。
- 在属性上,使用双引号,不要使用单引号。
- 不要在自动闭合标签结尾处使用斜线 - HTML5 规范 指出他们是可选的。
- 不要忽略可选的关闭标签(例如,
</li>
和</body>
)。
<!DOCTYPE html>
<html>
<head>
<title>Page title</title>
</head>
<body>
<img src="images/company-logo.png" alt="Company">
<h1 class="hello-world">Hello, world!</h1>
</body>
</html>
HTML5 doctype
在每个 HTML 页面开头使用这个简单地 doctype 来启用标准模式,使其每个浏览器中尽可能一致的展现。
虽然doctype不区分大小写,但是按照惯例,doctype大写 关于html属性,大写还是小写的一篇文章<!DOCTYPE html>
<html>
<head>
</head>
</html>
语言属性
根据 HTML5 规范:
强烈建议为 html 根元素指定 lang 属性,从而为文档设置正确的语言。这将有助于语音合成工具确定其所应该采用的发音,有助于翻译工具确定其翻译时所应遵守的规则等等。
更多关于 lang
属性的知识可以从 此规范.
这里列出了语言代码表。
以上只是给出了语言代码的大类,比如说中文就只给出了ZH,但是没有区分香港,台湾,大陆等。而微软给出的一份细分了zh-cn,zh-hk,zh-tw, Head to Microsoft for a detail list of language codes.
知乎贴:网页头部的声明应该是用 lang="zh" 还是 lang="zh-cn"?
但考虑到兼容性,目前需要指定中文的网页都统一用zh-CN
<html lang="en-us">
<!-- ... -->
</html>
IE compatibility mode
IE 支持通过特定的 <meta>
标签来确定绘制当前页面所应该采用的 IE 版本。除非有强烈的特殊需求,否则最好是设置为 edge mode,从而通知 IE 采用其所支持的最新的模式。
阅读这篇 stack overflow 上的文章可以获得更多有用的信息。
不同 doctype 在不同浏览器下的不同渲染模式,诡异模式总结的很到位.<meta http-equiv="X-UA-Compatible" content="IE=Edge">
字符编码
通过声明一个明确的字符编码,让浏览器轻松、快速的确定适合网页内容的渲染方式。同时你也应该避免使用类似于<这种字符Entities, 而使用他们的entity_code <
<head>
<meta charset="UTF-8">
</head>
引入 CSS 和 JavaScript
根据 HTML5 规范, 通常在引入 CSS 和 JavaScript 时不需要指明 type
,因为 text/css
和 text/javascript
分别是他们的默认值。
HTML5 规范链接
<!-- External CSS -->
<link rel="stylesheet" href="code-guide.css">
<!-- In-document CSS -->
<style>
/* ... */
</style>
<!-- JavaScript -->
<script src="code-guide.js"></script>
实用高于完美
尽量遵循 HTML 标准和语义,但是不应该以浪费实用性作为代价。任何时候都要用尽量小的复杂度和尽量少的标签来解决问题。
属性顺序
HTML 属性应该按照特定的顺序出现以保证易读性。
class
id
name
data-*
src
,for
,type
,href
,value
,max-length
,max
,min
,pattern
placeholder
,title
,alt
aria-*
,role
required
,readonly
,disabled
Classes 是为高可复用组件设计的,理论上他们应处在第一位。Ids 更加具体而且应该尽量少使用(例如, 页内书签),所以他们处在第二位。
<a id="..." class="..." data-modal="toggle" href="#">
Example link
</a>
<input class="form-control" type="text">
<img src="..." alt="...">
Boolean 属性
Boolean 属性指不需要声明取值的属性。XHTML 需要每个属性声明取值,但是 HTML5 并不需要。
了解更多内容,参考 WhatWG section on boolean attributes:
一个元素中 Boolean 属性的存在表示取值 true,不存在则表示取值 false。
如果你必须为属性添加并不需要的取值,参照 WhatWG 的指引:
简而言之,不要为 Boolean 属性添加取值。如果属性存在,他的取值必须是空字符串或者 [...] 属性的规范名称,不要在首尾包含空白字符。
<input type="text" disabled>
<input type="checkbox" value="1" checked>
<select>
<option value="1" selected>1</option>
</select>
减少标签数量
在编写 HTML 代码时,需要尽量避免多余的父节点。很多时候,需要通过迭代和重构来使 HTML 变得更少。 参考下面的示例:
<!-- Not so great -->
<span class="avatar">
<img src="...">
</span>
<!-- Better -->
<img class="avatar" src="...">
JavaScript 生成标签
在 JavaScript 文件中生成标签让内容变得更难查找,更难编辑,性能更差。应该尽量避免这种情况的出现。
CSS
语法
- 使用四个空格的 soft tabs — 这是保证代码在各种环境下显示一致的唯一方式。
- 使用组合选择器时,保持每个独立的选择器占用一行。
- 为了代码的易读性,在每个声明的左括号前增加一个空格。
- 声明块的右括号应该另起一行。
- 每条声明
:
后应该插入一个空格。 - 每条声明应该只占用一行来保证错误报告更加准确。
- 所有声明应该以分号结尾。虽然最后一条声明后的分号是可选的,但是如果没有他,你的代码会更容易出错。
- 逗号分隔的取值,都应该在逗号之后增加一个空格。比如说box-shadow
- 不要在颜色值
rgb()
rgba()
hsl()
hsla()
和rect()
中增加空格,并且不要带有取值前面不必要的 0 (比如,使用 .5 替代 0.5)。This helps differentiate multiple color values (comma, no space) from multiple property values (comma with space). - 所有的十六进制值都应该使用小写字母,例如
#fff
。因为小写字母有更多样的外形,在浏览文档时,他们能够更轻松的被区分开来。 - 尽可能使用短的十六进制数值,例如使用
#fff
替代#ffffff
。 - 为选择器中的属性取值添加引号,例如
input[type="text"]
。 他们只在某些情况下可有可无,所以都使用引号可以增加一致性。 - 不要为 0 指明单位,比如使用
margin: 0;
而不是margin: 0px;
。
/* Bad CSS */
.selector, .selector-secondary, .selector[type=text] {
padding: 15px;
margin: 0px 0px 15px;
background-color: rgba(0, 0, 0, 0.5);
box-shadow: 0 1px 2px #CCC, inset 0 1px 0 #FFFFFF
}
/* Good CSS */
.selector,
.selector-secondary,
.selector[type="text"] {
padding: 15px;
margin-bottom: 15px;
background-color: rgba(0,0,0,.5);
box-shadow: 0 1px 2px #ccc, inset 0 1px 0 #fff;
}
声明顺序
相关的属性声明应该以下面的顺序分组处理:
- Positioning
- Box model 盒模型
- Typographic 排版
- Visual 外观
Positioning 处在第一位,因为他可以使一个元素脱离正常文本流,并且覆盖盒模型相关的样式。盒模型紧跟其后,因为他决定了一个组件的大小和位置。
其他属性只在组件 内部 起作用或者不会对前面两种情况的结果产生影响,所以他们排在后面。
关于完整的属性以及他们的顺序,请参考 Recess。.declaration-order {
/* Positioning */
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 100;
/* Box-model */
display: block;
float: right;
width: 100px;
height: 100px;
/* Typography */
font: normal 13px "Helvetica Neue", sans-serif;
line-height: 1.5;
color: #333;
text-align: center;
/* Visual */
background-color: #f5f5f5;
border: 1px solid #e5e5e5;
border-radius: 3px;
/* Misc */
opacity: 1;
}
// 为了方便查阅, 我把Recess的order贴了一份过来, 引入时间2014-05-05
// css property order
var order = [
'position'
, 'top'
, 'right'
, 'bottom'
, 'left'
, 'z-index'
, 'display'
, 'float'
, 'width'
, 'height'
, 'max-width'
, 'max-height'
, 'min-width'
, 'min-height'
, 'padding'
, 'padding-top'
, 'padding-right'
, 'padding-bottom'
, 'padding-left'
, 'margin'
, 'margin-top'
, 'margin-right'
, 'margin-bottom'
, 'margin-left'
, 'margin-collapse'
, 'margin-top-collapse'
, 'margin-right-collapse'
, 'margin-bottom-collapse'
, 'margin-left-collapse'
, 'overflow'
, 'overflow-x'
, 'overflow-y'
, 'clip'
, 'clear'
, 'font'
, 'font-family'
, 'font-size'
, 'font-smoothing'
, 'osx-font-smoothing'
, 'font-style'
, 'font-weight'
, 'hyphens'
, 'src'
, 'line-height'
, 'letter-spacing'
, 'word-spacing'
, 'color'
, 'text-align'
, 'text-decoration'
, 'text-indent'
, 'text-overflow'
, 'text-rendering'
, 'text-size-adjust'
, 'text-shadow'
, 'text-transform'
, 'word-break'
, 'word-wrap'
, 'white-space'
, 'vertical-align'
, 'list-style'
, 'list-style-type'
, 'list-style-position'
, 'list-style-image'
, 'pointer-events'
, 'cursor'
, 'background'
, 'background-attachment'
, 'background-color'
, 'background-image'
, 'background-position'
, 'background-repeat'
, 'background-size'
, 'border'
, 'border-collapse'
, 'border-top'
, 'border-right'
, 'border-bottom'
, 'border-left'
, 'border-color'
, 'border-image'
, 'border-top-color'
, 'border-right-color'
, 'border-bottom-color'
, 'border-left-color'
, 'border-spacing'
, 'border-style'
, 'border-top-style'
, 'border-right-style'
, 'border-bottom-style'
, 'border-left-style'
, 'border-width'
, 'border-top-width'
, 'border-right-width'
, 'border-bottom-width'
, 'border-left-width'
, 'border-radius'
, 'border-top-right-radius'
, 'border-bottom-right-radius'
, 'border-bottom-left-radius'
, 'border-top-left-radius'
, 'border-radius-topright'
, 'border-radius-bottomright'
, 'border-radius-bottomleft'
, 'border-radius-topleft'
, 'content'
, 'quotes'
, 'outline'
, 'outline-offset'
, 'opacity'
, 'filter'
, 'visibility'
, 'size'
, 'zoom'
, 'transform'
, 'box-align'
, 'box-flex'
, 'box-orient'
, 'box-pack'
, 'box-shadow'
, 'box-sizing'
, 'table-layout'
, 'animation'
, 'animation-delay'
, 'animation-duration'
, 'animation-iteration-count'
, 'animation-name'
, 'animation-play-state'
, 'animation-timing-function'
, 'animation-fill-mode'
, 'transition'
, 'transition-delay'
, 'transition-duration'
, 'transition-property'
, 'transition-timing-function'
, 'background-clip'
, 'backface-visibility'
, 'resize'
, 'appearance'
, 'user-select'
, 'interpolation-mode'
, 'direction'
, 'marks'
, 'page'
, 'set-link-source'
, 'unicode-bidi'
, 'speak'
]
不要使用 @import
与 <link>
标签相比,@import
指令要慢很多,不光增加了额外的请求次数,还会导致不可预料的问题。替代办法有以下几种:
- 使用多个
<link>
元素 - 通过 Sass 或 Less 类似的 CSS 预处理器将多个 CSS 文件编译为一个文件
- 通过 Rails、Jekyll 或其他系统中提供过 CSS 文件合并功能
<!-- Use link elements -->
<link rel="stylesheet" href="core.css">
<!-- Avoid @imports -->
<style>
@import url("more.css");
</style>
媒体查询位置
尽量将媒体查询的位置靠近他们相关的规则。不要将他们一起放到一个独立的样式文件中,或者丢在文档的最底部。这样做只会让大家以后更容易忘记他们。这里是一个典型的案例。
.element { ... }
.element-avatar { ... }
.element-selected { ... }
@media (min-width: 480px) {
.element { ...}
.element-avatar { ... }
.element-selected { ... }
}
前缀属性
当使用厂商前缀属性时,通过缩进使取值垂直对齐以便多行编辑。
在 Textmate 中,使用 Text → Edit Each Line in Selection (⌃⌘A)。 在 Sublime Text 2 中, 使用 Selection → Add Previous Line (⌃⇧↑) 和 Selection → Add Next Line (⌃⇧↓)。/* Prefixed properties */
.selector {
-webkit-box-shadow: 0 1px 2px rgba(0,0,0,.15);
box-shadow: 0 1px 2px rgba(0,0,0,.15);
}
单条声明的声明块
在一个声明块中只包含一条声明的情况下,为了易读性和快速编辑可以考虑移除其中的换行。所有包含多条声明的声明块应该分为多行。
这样做的关键因素是错误检测 - 例如,一个 CSS 验证程序显示你在 183 行有一个语法错误,如果是一个单条声明的行,那就是他了。在多个声明的情况下,你必须为哪里出错了费下脑子。
/* Single declarations on one line */
.span1 { width: 60px; }
.span2 { width: 140px; }
.span3 { width: 220px; }
/* Multiple declarations, one per line */
.sprite {
display: inline-block;
width: 16px;
height: 15px;
background-image: url(../img/sprite.png);
}
.icon { background-position: 0 0; }
.icon-home { background-position: 0 -20px; }
.icon-account { background-position: 0 -40px; }
属性简写
坚持限制属性取值简写的使用,属性简写需要你必须显式设置所有取值。常见的属性简写滥用包括:
padding
margin
font
background
border
border-radius
大多数情况下,我们并不需要设置属性简写中包含的所有值。例如,HTML 头部只设置上下的 margin,所以如果需要,只设置这两个值。过度使用属性简写往往会导致更混乱的代码,其中包含不必要的重写和意想不到的副作用。
Mozilla Developer Network 有一篇对不熟悉属性简写及其行为的人来说很棒的关于 shorthand properties 的文章。/* Bad example */
.element {
margin: 0 0 10px;
background: red;
background: url("image.jpg");
border-radius: 3px 3px 0 0;
}
/* Good example */
.element {
margin-bottom: 10px;
background-color: red;
background-image: url("image.jpg");
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
Less 和 Sass 中的嵌套
避免不必要的嵌套。可以进行嵌套,不意味着你应该这样做。只有在需要给父元素增加样式并且同时存在多个子元素时才需要考虑嵌套。
// Without nesting
.table > thead > tr > th { … }
.table > thead > tr > td { … }
// With nesting
.table > thead > tr {
> th { … }
> td { … }
}
Class 命名
- 保持 Class 命名为全小写,可以使用短划线(不要使用下划线和 camelCase 命名)。短划线应该作为相关类的自然间断。(例如,
.btn
和.btn-danger
)。 - 避免过度使用简写。
.btn
可以很好地描述 button,但是.s
不能代表任何元素。 - Class 的命名应该尽量短,也要尽量明确。
- 使用有意义的名称;使用结构化或者作用目标相关,而不是抽象的名称。
- 命名时使用最近的父节点或者父 class 作为前缀。
- 使用
.js-*
classes 来表示行为(相对于样式),但是不要在 CSS 中包含这些 classes。
/* Bad example */
.t { ... }
.red { ... }
.header { ... }
/* Good example */
.tweet { ... }
.important { ... }
.tweet-header { ... }
选择器
- 使用 classes 而不是通用元素标签来优化渲染性能。
- 避免在经常出现的组件中使用一些属性选择器 (例如,
[class^="..."]
)。浏览器性能会受到这些情况的影响。 - 减少选择器的长度,每个组合选择器选择器的条目应该尽量控制在 3 个以内。
- 只在必要的情况下使用后代选择器 (例如,没有使用带前缀 classes 的情况).
扩展阅读:
/* Bad example */
span { ... }
.page-container #stream .stream-item .tweet .tweet-header .username { ... }
.avatar { ... }
/* Good example */
.avatar { ... }
.tweet-header .username { ... }
.tweet .avatar { ... }
代码组织
- 以组件为单位组织代码。
- 制定一个一致的注释层级结构。
- 使用一致的空白来分割代码块,这样做在查看大的文档时更有优势。
- 当使用多个 CSS 文件时,通过组件而不是页面来区分他们。页面会被重新排列,而组件移动就可以了。
/*
* Component section heading
*/
.element { ... }
/*
* Component section heading
*
* Sometimes you need to include optional context for the entire component. Do that up here if it's important enough.
*/
.element { ... }
/* Contextual sub-component or modifer */
.element-heading { ... }
编辑器配置
根据以下的设置来配置你的编辑器,来避免常见的代码不一致和丑陋的 diffs。
- 使用四个空格的 soft-tabs。
- 在保存时删除尾部的空白字符。
- 在保存时删除尾部的空白字符。 为什么这么做?
- 设置文件编码为 UTF-8。
- 在文件结尾添加一个空白行。
- 在文件结尾添加一个空白行。为什么这么做?
.editorconfig
文件。 例如,Bootstrap 中的 .editorconfig
文件。 通过 关于 EditorConfig 了解更多内容。
JavaScript
Indentation,分号,单行长度
- 一律使用4个空格
- continuation-indentation 同样适用4个空格,跟上一行对齐
- Statement 之后一律以分号结束, 不可以省略
- 单行长度,理论上不要超过80列,不过如果编辑器开启 soft wrap 的话可以不考虑单行长度
- 接上一条,如果需要换行,存在操作符的情况,一定在操作符后换行,然后换的行缩进4个空格
- 这里要注意,如果是多次换行的话就没有必要继续缩进了,比如说右边第二段这种就是最佳格式。
if (typeof qqfind === "undefined" ||
typeof qqfind.cdnrejected === "undefined" ||
qqfind.cdnrejected !== true) {
url = "http://pub.idqqimg.com/qqfind/js/location4.js";
} else {
url = "http://find.qq.com/js/location4.js";
}
空行
- 方法之间加
- 单行或多行注释前加
- 逻辑块之间加空行增加可读性
变量命名
- 标准变量采用驼峰标识
- 使用的ID的地方一定全大写
- 使用的URL的地方一定全大写, 比如说 reportURL
- 涉及Android的,一律大写第一个字母
- 涉及iOS的,一律小写第一个,大写后两个字母
- 常量采用大写字母,下划线连接的方式
- 构造函数,大写第一个字母
var thisIsMyName;
var goodID;
var AndroidVersion;
var iOSVersion;
var MAX_COUNT = 10;
function Person(name) {
this.name = name
}
字符常量
- 一般情况下统一使用 '' 单引号
null的使用场景
- To initialize a variable that may later be assigned an object value
- To compare against an initialized variable that may or may not have an object value
- To pass into a function where an object is expected
- To return from a function where an object is expected
不适合null的使用场景
- Do not use null to test whether an argument was supplied
- Do not test an uninitialized variable for the value null
undefined使用场景
- 永远不要直接使用undefined进行变量判断
- 使用字符串 "undefined" 对变量进行判断
// Bad
var person;
console.log(person === undefined); //true
// Good
console.log(typeof person); // "undefined"
Object Literals
// Bad
var team = new Team();
team.title = "AlloyTeam";
team.count = 25;
// Good semi colon 采用 Followed by space 的形式
var team = {
title: "AlloyTeam",
count: 25
};
Array Literals
// Bad
var colors = new Array("red", "green", "blue");
var numbers = new Array(1, 2, 3, 4);
// Good
var colors = [ "red", "green", "blue" ];
var numbers = [ 1, 2, 3, 4 ];
括号对齐
- 标准示例 括号前后有空格, 花括号起始 不另换行,结尾新起一行
- 花括号必须要, 即使内容只有一行, 决不允许右边第二种情况
- 涉及 if for while do...while try...catch...finally 的地方都必须使用花括号
// Good
if (condition) {
doSomething();
}
if (condition)
doSomething();
doSomethingElse();
if else else前后留有空格
if (condition) {
doSomething();
} else {
doSomethingElse();
}
switch
- 采用右边的格式, switch和括号之间有空格, case需要缩进, break之后跟下一个case中间留一个blank line
- 花括号必须要, 即使内容只有一行。
- 如右侧第二种情况,switch 的 falling through 一定要有注释特别说明, no default 的情况也需要注释特别说明况
switch (condition) {
case "first":
// code
break;
case "third":
// code
break;
default:
// code
}
switch (condition) {
// obvious fall through // 这里为啥JSHint默认就会放过,因为 case "first" 内无内容
case "first":
case "second":
// code
break;
case "third":
// code
/* falls through */ // 这里为啥要加这样的注释, 明确告知JSHint放过此处告警
default:
// code
}
switch(condition) {
case "first":
// code
break;
case "second":
// code
break;
// no default
}
for
- 普通for循环, 分号后留有一个空格, 判断条件等内的操作符两边不留空格, 前置条件如果有多个,逗号后留一个空格
- for-in 一定要有 hasOwnProperty 的判断, 否则 JSLint 或者 JSHint 都会有一个 warn
var values = [ 1, 2, 3, 4, 5, 6, 7 ],
i, len;
for (i=0, len=values.length; i<len; i++) {
process(values[i]);
}
var prop;
for (prop in object) {
// 注意这里一定要有 hasOwnProperty 的判断, 否则 JSLint 或者 JSHint 都会有一个 warn !
if (object.hasOwnProperty(prop)) {
console.log("Property name is " + prop);
console.log("Property value is " + object[prop]);
}
}
变量声明
- 所有函数内变量声明放在函数内头部,只使用一个 var(多了JSLint报错), 一个变量一行, 在行末跟注释, 注释啊,注释啊,亲
function doSomethingWithItems(items) {
var value = 10, // 注释啊,注释啊,亲
result = value + 10, // 注释啊,注释啊
i, // 注释啊,注释啊,亲
len; // 注释啊,注释啊,亲
for (i=0, len=items.length; i < len; i++) {
doSomething(items[i]);
}
}
函数声明
- 一定先声明再使用, 不要利用 JavaScript engine的hoist特性, 违反了这个规则 JSLint 和 JSHint都会报 warn
- function declaration 和 function expression 的不同,function expression 的()前后必须有空格,而function declaration 在有函数名的时候不需要空格, 没有函数名的时候需要空格。
- 函数调用括号前后不需要空格
- 立即执行函数的写法, 最外层必须包一层括号
- "use strict" 决不允许全局使用, 必须放在函数的第一行, 可以用自执行函数包含大的代码段, 如果 "use strict" 在函数外使用, JSLint 和 JSHint 均会报错
function doSomething(item) {
// do something
}
var doSomething = function (item) {
// do something
}
// Good
doSomething(item);
// Bad: Looks like a block statement
doSomething (item);
// Good
var value = (function() {
// function body
return {
message: "Hi"
}
}());
// Good
(function() {
"use strict";
function doSomething() {
// code
}
function doSomethingElse() {
// code
}
})();
杂项
- 完全避免 == != 的使用, 用严格比较条件 === !==
- eval 非特殊业务, 禁用!!!
- with 非特殊业务, 禁用!!!
编辑器配置
根据以下的设置来配置你的编辑器,来避免常见的代码不一致和丑陋的 diffs。
参照文档,将这些设置应用到项目的 .editorconfig
文件。 例如,Bootstrap 中的 .editorconfig
文件。 通过 关于 EditorConfig 了解更多内容。