l1n6yun's Blog

记录学习的技能和遇到的问题

0%

执行reg

1
2
3
4
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\Background]
"OEMBackground"=dword:00000001

添加图片

打开文件夹C:\Windows\System32\oobe\info\backgrounds(如果没有这个文件夹的请自行创建)。

添加自己选择好的图片,文件名修改成backgroundDefault.jpg.

注:我们编辑好的登录界面的背景图片backgroundDefault.jpg,其体积一定控制在250KB以内;否则,我们修改后的登录界面的背景图片就无法了.

此文档包含了用Chart.js创建漂亮图表的所有知识。

起步

引入Chart.js文件

首先我们需要在页面中引入Chart.js文件。此工具库在全局命名空间中定义了Chart变量。

1
<script src="Chart.js"></script>

创建图表

为了创建图表,我们要实例化一个Chart对象。为了完成前面的步骤,首先需要需要传入一个绘制图表的2d context。以下是案例。

1
<canvas id="myChart" width="400" height="400"></canvas>
1
2
3
//Get the context of the canvas element we want to select
var ctx = document.getElementById("myChart").getContext("2d");
var myNewChart = new Chart(ctx).PolarArea(data);

我们还可以用jQuery获取canvas的context。首先从jQuery集合中获取我们需要的DOM节点,然后在这个DOM节点上调用 getContext(“2d”) 方法。

1
2
3
4
//Get context with jQuery - using jQuery's .get() method.
var ctx = $("#myChart").get(0).getContext("2d");
//This will get the first returned node in the jQuery collection.
var myNewChart = new Chart(ctx);

当我们完成了在指定的canvas上实例化Chart对象之后,Chart.js会自动针对retina屏幕做缩放。

Chart对象设置完成后,我们就可以继续创建Chart.js中提供的具体类型的图表了。下面这个案例中,我们将展示如何绘制一幅极地区域图(Polar area chart)。

1
new Chart(ctx).PolarArea(data,options);

We call a method of the name of the chart we want to create. We pass in the data for that chart type, and the options for that chart as parameters. Chart.js will merge the options you pass in with the default options for that chart type.

曲线图(Line chart)

简介

曲线图就是将数据标于曲线上的一种图表。

一般用于展示趋势数据,和比较两组数据集。

使用案例

1
new Chart(ctx).Line(data,options);

数据结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var data = {
labels : ["January","February","March","April","May","June","July"],
datasets : [
{
fillColor : "rgba(220,220,220,0.5)",
strokeColor : "rgba(220,220,220,1)",
pointColor : "rgba(220,220,220,1)",
pointStrokeColor : "#fff",
data : [65,59,90,81,56,55,40]
},
{
fillColor : "rgba(151,187,205,0.5)",
strokeColor : "rgba(151,187,205,1)",
pointColor : "rgba(151,187,205,1)",
pointStrokeColor : "#fff",
data : [28,48,40,19,96,27,100]
}
]
}

The line chart requires an array of labels for each of the data points. This is show on the X axis.

The data for line charts is broken up into an array of datasets. Each dataset has a colour for the fill, a colour for the line and colours for the points and strokes of the points. These colours are strings just like CSS. You can use RGBA, RGB, HEX or HSL notation.

图表参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
Line.defaults = {

//Boolean - If we show the scale above the chart data
scaleOverlay : false,

//Boolean - If we want to override with a hard coded scale
scaleOverride : false,

//** Required if scaleOverride is true **
//Number - The number of steps in a hard coded scale
scaleSteps : null,
//Number - The value jump in the hard coded scale
scaleStepWidth : null,
//Number - The scale starting value
scaleStartValue : null,

//String - Colour of the scale line
scaleLineColor : "rgba(0,0,0,.1)",

//Number - Pixel width of the scale line
scaleLineWidth : 1,

//Boolean - Whether to show labels on the scale
scaleShowLabels : false,

//Interpolated JS string - can access value
scaleLabel : "<%=value%>",

//String - Scale label font declaration for the scale label
scaleFontFamily : "'Arial'",

//Number - Scale label font size in pixels
scaleFontSize : 12,

//String - Scale label font weight style
scaleFontStyle : "normal",

//String - Scale label font colour
scaleFontColor : "#666",

///Boolean - Whether grid lines are shown across the chart
scaleShowGridLines : true,

//String - Colour of the grid lines
scaleGridLineColor : "rgba(0,0,0,.05)",

//Number - Width of the grid lines
scaleGridLineWidth : 1,

//Boolean - Whether the line is curved between points
bezierCurve : true,

//Boolean - Whether to show a dot for each point
pointDot : true,

//Number - Radius of each point dot in pixels
pointDotRadius : 3,

//Number - Pixel width of point dot stroke
pointDotStrokeWidth : 1,

//Boolean - Whether to show a stroke for datasets
datasetStroke : true,

//Number - Pixel width of dataset stroke
datasetStrokeWidth : 2,

//Boolean - Whether to fill the dataset with a colour
datasetFill : true,

//Boolean - Whether to animate the chart
animation : true,

//Number - Number of animation steps
animationSteps : 60,

//String - Animation easing effect
animationEasing : "easeOutQuart",

//Function - Fires when the animation is complete
onAnimationComplete : null

}

柱状图(Bar chart)

简介

A bar chart is a way of showing data as bars.

It is sometimes used to show trend data, and the comparison of multiple data sets side by side.

使用案例

1
new Chart(ctx).Bar(data,options);

数据结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var data = {
labels : ["January","February","March","April","May","June","July"],
datasets : [
{
fillColor : "rgba(220,220,220,0.5)",
strokeColor : "rgba(220,220,220,1)",
data : [65,59,90,81,56,55,40]
},
{
fillColor : "rgba(151,187,205,0.5)",
strokeColor : "rgba(151,187,205,1)",
data : [28,48,40,19,96,27,100]
}
]
}

The bar chart has the a very similar data structure to the line chart, and has an array of datasets, each with colours and an array of data. Again, colours are in CSS format.

We have an array of labels too for display. In the example, we are showing the same data as the previous line chart example.

图表参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
Bar.defaults = {

//Boolean - If we show the scale above the chart data
scaleOverlay : false,

//Boolean - If we want to override with a hard coded scale
scaleOverride : false,

//** Required if scaleOverride is true **
//Number - The number of steps in a hard coded scale
scaleSteps : null,
//Number - The value jump in the hard coded scale
scaleStepWidth : null,
//Number - The scale starting value
scaleStartValue : null,

//String - Colour of the scale line
scaleLineColor : "rgba(0,0,0,.1)",

//Number - Pixel width of the scale line
scaleLineWidth : 1,

//Boolean - Whether to show labels on the scale
scaleShowLabels : false,

//Interpolated JS string - can access value
scaleLabel : "<%=value%>",

//String - Scale label font declaration for the scale label
scaleFontFamily : "'Arial'",

//Number - Scale label font size in pixels
scaleFontSize : 12,

//String - Scale label font weight style
scaleFontStyle : "normal",

//String - Scale label font colour
scaleFontColor : "#666",

///Boolean - Whether grid lines are shown across the chart
scaleShowGridLines : true,

//String - Colour of the grid lines
scaleGridLineColor : "rgba(0,0,0,.05)",

//Number - Width of the grid lines
scaleGridLineWidth : 1,

//Boolean - If there is a stroke on each bar
barShowStroke : true,

//Number - Pixel width of the bar stroke
barStrokeWidth : 2,

//Number - Spacing between each of the X value sets
barValueSpacing : 5,

//Number - Spacing between data sets within X values
barDatasetSpacing : 1,

//Boolean - Whether to animate the chart
animation : true,

//Number - Number of animation steps
animationSteps : 60,

//String - Animation easing effect
animationEasing : "easeOutQuart",

//Function - Fires when the animation is complete
onAnimationComplete : null

}

雷达图或蛛网图(Radar chart)

简介

A radar chart is a way of showing multiple data points and the variation between them.

They are often useful for comparing the points of two or more different data sets

使用案例

1
new Chart(ctx).Radar(data,options);

数据结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var data = {
labels : ["Eating","Drinking","Sleeping","Designing","Coding","Partying","Running"],
datasets : [
{
fillColor : "rgba(220,220,220,0.5)",
strokeColor : "rgba(220,220,220,1)",
pointColor : "rgba(220,220,220,1)",
pointStrokeColor : "#fff",
data : [65,59,90,81,56,55,40]
},
{
fillColor : "rgba(151,187,205,0.5)",
strokeColor : "rgba(151,187,205,1)",
pointColor : "rgba(151,187,205,1)",
pointStrokeColor : "#fff",
data : [28,48,40,19,96,27,100]
}
]
}

For a radar chart, usually you will want to show a label on each point of the chart, so we include an array of strings that we show around each point in the chart. If you do not want this, you can either not include the array of labels, or choose to hide them in the chart options.

For the radar chart data, we have an array of datasets. Each of these is an object, with a fill colour, a stroke colour, a colour for the fill of each point, and a colour for the stroke of each point. We also have an array of data values.

图表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
Radar.defaults = {

//Boolean - If we show the scale above the chart data
scaleOverlay : false,

//Boolean - If we want to override with a hard coded scale
scaleOverride : false,

//** Required if scaleOverride is true **
//Number - The number of steps in a hard coded scale
scaleSteps : null,
//Number - The value jump in the hard coded scale
scaleStepWidth : null,
//Number - The centre starting value
scaleStartValue : null,

//Boolean - Whether to show lines for each scale point
scaleShowLine : true,

//String - Colour of the scale line
scaleLineColor : "rgba(0,0,0,.1)",

//Number - Pixel width of the scale line
scaleLineWidth : 1,

//Boolean - Whether to show labels on the scale
scaleShowLabels : false,

//Interpolated JS string - can access value
scaleLabel : "<%=value%>",

//String - Scale label font declaration for the scale label
scaleFontFamily : "'Arial'",

//Number - Scale label font size in pixels
scaleFontSize : 12,

//String - Scale label font weight style
scaleFontStyle : "normal",

//String - Scale label font colour
scaleFontColor : "#666",

//Boolean - Show a backdrop to the scale label
scaleShowLabelBackdrop : true,

//String - The colour of the label backdrop
scaleBackdropColor : "rgba(255,255,255,0.75)",

//Number - The backdrop padding above & below the label in pixels
scaleBackdropPaddingY : 2,

//Number - The backdrop padding to the side of the label in pixels
scaleBackdropPaddingX : 2,

//Boolean - Whether we show the angle lines out of the radar
angleShowLineOut : true,

//String - Colour of the angle line
angleLineColor : "rgba(0,0,0,.1)",

//Number - Pixel width of the angle line
angleLineWidth : 1,

//String - Point label font declaration
pointLabelFontFamily : "'Arial'",

//String - Point label font weight
pointLabelFontStyle : "normal",

//Number - Point label font size in pixels
pointLabelFontSize : 12,

//String - Point label font colour
pointLabelFontColor : "#666",

//Boolean - Whether to show a dot for each point
pointDot : true,

//Number - Radius of each point dot in pixels
pointDotRadius : 3,

//Number - Pixel width of point dot stroke
pointDotStrokeWidth : 1,

//Boolean - Whether to show a stroke for datasets
datasetStroke : true,

//Number - Pixel width of dataset stroke
datasetStrokeWidth : 2,

//Boolean - Whether to fill the dataset with a colour
datasetFill : true,

//Boolean - Whether to animate the chart
animation : true,

//Number - Number of animation steps
animationSteps : 60,

//String - Animation easing effect
animationEasing : "easeOutQuart",

//Function - Fires when the animation is complete
onAnimationComplete : null

}

极地区域图(Polar area chart)

简介

Polar area charts are similar to pie charts, but each segment has the same angle - the radius of the segment differs depending on the value.

This type of chart is often useful when we want to show a comparison data similar to a pie chart, but also show a scale of values for context.

使用案例

1
new Chart(ctx).PolarArea(data,options);

数据结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var data = [
{
value : 30,
color: "#D97041"
},
{
value : 90,
color: "#C7604C"
},
{
value : 24,
color: "#21323D"
},
{
value : 58,
color: "#9D9B7F"
},
{
value : 82,
color: "#7D4F6D"
},
{
value : 8,
color: "#584A5E"
}
]

As you can see, for the chart data you pass in an array of objects, with a value and a colour. The value attribute should be a number, while the color attribute should be a string. Similar to CSS, for this string you can use HEX notation, RGB, RGBA or HSL.

图表

These are the default chart options. By passing in an object with any of these attributes, Chart.js will merge these objects and the graph accordingly. Explanations of each option are commented in the code below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
PolarArea.defaults = {

//Boolean - Whether we show the scale above or below the chart segments
scaleOverlay : true,

//Boolean - If we want to override with a hard coded scale
scaleOverride : false,

//** Required if scaleOverride is true **
//Number - The number of steps in a hard coded scale
scaleSteps : null,
//Number - The value jump in the hard coded scale
scaleStepWidth : null,
//Number - The centre starting value
scaleStartValue : null,

//Boolean - Show line for each value in the scale
scaleShowLine : true,

//String - The colour of the scale line
scaleLineColor : "rgba(0,0,0,.1)",

//Number - The width of the line - in pixels
scaleLineWidth : 1,

//Boolean - whether we should show text labels
scaleShowLabels : true,

//Interpolated JS string - can access value
scaleLabel : "<%=value%>",

//String - Scale label font declaration for the scale label
scaleFontFamily : "'Arial'",

//Number - Scale label font size in pixels
scaleFontSize : 12,

//String - Scale label font weight style
scaleFontStyle : "normal",

//String - Scale label font colour
scaleFontColor : "#666",

//Boolean - Show a backdrop to the scale label
scaleShowLabelBackdrop : true,

//String - The colour of the label backdrop
scaleBackdropColor : "rgba(255,255,255,0.75)",

//Number - The backdrop padding above & below the label in pixels
scaleBackdropPaddingY : 2,

//Number - The backdrop padding to the side of the label in pixels
scaleBackdropPaddingX : 2,

//Boolean - Stroke a line around each segment in the chart
segmentShowStroke : true,

//String - The colour of the stroke on each segement.
segmentStrokeColor : "#fff",

//Number - The width of the stroke value in pixels
segmentStrokeWidth : 2,

//Boolean - Whether to animate the chart or not
animation : true,

//Number - Amount of animation steps
animationSteps : 100,

//String - Animation easing effect.
animationEasing : "easeOutBounce",

//Boolean - Whether to animate the rotation of the chart
animateRotate : true,

//Boolean - Whether to animate scaling the chart from the centre
animateScale : false,

//Function - This will fire when the animation of the chart is complete.
onAnimationComplete : null
}

饼图(Pie chart)

简介

Pie charts are probably the most commonly used chart there are. They are divided into segments, the arc of each segment shows a the proportional value of each piece of data.

They are excellent at showing the relational proportions between data.

使用案例

1
new Chart(ctx).Pie(data,options);

数据结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var data = [
{
value: 30,
color:"#F38630"
},
{
value : 50,
color : "#E0E4CC"
},
{
value : 100,
color : "#69D2E7"
}
]

For a pie chart, you must pass in an array of objects with a value and a color property. The value attribute should be a number, Chart.js will total all of the numbers and calculate the relative proportion of each. The color attribute should be a string. Similar to CSS, for this string you can use HEX notation, RGB, RGBA or HSL.

图表

These are the default options for the Pie chart. Pass in an object with any of these attributes to override them.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Pie.defaults = {
//Boolean - Whether we should show a stroke on each segment
segmentShowStroke : true,

//String - The colour of each segment stroke
segmentStrokeColor : "#fff",

//Number - The width of each segment stroke
segmentStrokeWidth : 2,

//Boolean - Whether we should animate the chart
animation : true,

//Number - Amount of animation steps
animationSteps : 100,

//String - Animation easing effect
animationEasing : "easeOutBounce",

//Boolean - Whether we animate the rotation of the Pie
animateRotate : true,

//Boolean - Whether we animate scaling the Pie from the centre
animateScale : false,

//Function - Will fire on animation completion.
onAnimationComplete : null
}

环形图(Doughnut chart)

简介

Doughnut charts are similar to pie charts, however they have the centre cut out, and are therefore shaped more like a doughnut than a pie!

They are aso excellent at showing the relational proportions between data.

使用案例

1
new Chart(ctx).Doughnut(data,options);

数据结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var data = [
{
value: 30,
color:"#F7464A"
},
{
value : 50,
color : "#E2EAE9"
},
{
value : 100,
color : "#D4CCC5"
},
{
value : 40,
color : "#949FB1"
},
{
value : 120,
color : "#4D5360"
}

]

For a doughnut chart, you must pass in an array of objects with a value and a color property. The value attribute should be a number, Chart.js will total all of the numbers and calculate the relative proportion of each. The color attribute should be a string. Similar to CSS, for this string you can use HEX notation, RGB, RGBA or HSL.

图表

These are the default options for the doughnut chart. Pass in an object with any of these attributes to override them.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Doughnut.defaults = {
//Boolean - Whether we should show a stroke on each segment
segmentShowStroke : true,

//String - The colour of each segment stroke
segmentStrokeColor : "#fff",

//Number - The width of each segment stroke
segmentStrokeWidth : 2,

//The percentage of the chart that we cut out of the middle.
percentageInnerCutout : 50,

//Boolean - Whether we should animate the chart
animation : true,

//Number - Amount of animation steps
animationSteps : 100,

//String - Animation easing effect
animationEasing : "easeOutBounce",

//Boolean - Whether we animate the rotation of the Doughnut
animateRotate : true,

//Boolean - Whether we animate scaling the Doughnut from the centre
animateScale : false,

//Function - Will fire on animation completion.
onAnimationComplete : null
}

General issues

Chart interactivity

If you are looking to add interaction as a layer to charts, Chart.js is not the library for you. A better option would be using SVG, as this will let you attach event listeners to any of the elements in the chart, as these are all DOM nodes.

Chart.js uses the canvas element, which is a single DOM node, similar in characteristics to a static image. This does mean that it has a wider scope for compatibility, and less memory implications than SVG based charting solutions. The canvas element also allows for saving the contents as a base 64 string, allowing saving the chart as an image.

In SVG, all of the lines, data points and everything you see is a DOM node. As a result of this, complex charts with a lot of intricacies, or many charts on the page will often see dips in performance when scrolling or generating the chart, especially when there are multiple on the page. SVG also has relatively poor mobile support, with Android not supporting SVG at all before version 3.0, and iOS before 5.0. (caniuse.com/svg-html5).

浏览器支持

所有现代浏览器和大部分手机浏览器都支持canvas(caniuse.com/canvas)。

对于IE8及以下版本的浏览器,建议使用ExplorerCanvas - 见 https://code.google.com/p/explorercanvas/。对于不支持canvas的IE会自动降级为VML格式。使用方法:

1
2
3
4
5
<head>
<!--[if lte IE 8]>
<script src="excanvas.js"></script>
<![endif]-->
</head>

Usually I would recommend feature detection to choose whether or not to load a polyfill, rather than IE conditional comments, however in this case, VML is a Microsoft proprietary format, so it will only work in IE.

Some important points to note in my experience using ExplorerCanvas as a fallback.

  • Initialise charts on load rather than DOMContentReady when using the library, as sometimes a race condition will occur, and it will result in an error when trying to get the 2d context of a canvas.

  • New VML DOM elements are being created for each animation frame and there is no hardware acceleration. As a result animation is usually slow and jerky, with flashing text. It is a good idea to dynamically turn off animation based on canvas support. I recommend using the excellent Modernizr to do this.

  • When declaring fonts, the library explorercanvas requires the font name to be in single quotes inside the string. For example, instead of your scaleFontFamily property being simply “Arial”, explorercanvas support, use “‘Arial’” instead. Chart.js does this for default values.

Bugs & issues

Please report these on the Github page - at github.com/nnnick/Chart.js.

New contributions to the library are welcome.

License

Chart.js is open source and available under the MIT license.

目录

  • HTML
    • 语法
    • HTML5 doctype
    • 语言属性(Language attribute)
    • 字符编码
    • IE 兼容模式
    • 引入 CSS 和 JavaScript 文件
    • 实用为王
    • 属性顺序
    • 布尔(boolean)型属性
    • 减少标签的数量
    • JavaScript 生成的标签
  • CSS
    • 语法
    • 声明顺序
    • 媒体查询(Media query)的位置
    • 带前缀的属性
    • 单行规则声明
    • 简写形式的属性声明
    • Less 和 Sass 中的嵌套
    • 注释
    • class 命名
    • 选择器
    • 代码组织

黄金定律

永远遵循同一套编码规范 – 可以是这里列出的,也可以是你自己总结的。如果你发现本规范中有任何错误,敬请指正。通过 open an issue on GitHub为本规范添加或贡献内容。

不管有多少人共同参与同一项目,一定要确保每一行代码都像是同一个人编写的。

HTML

语法

  • 用两个空格来代替制表符(tab) – 这是唯一能保证在所有环境下获得一致展现的方法。
  • 嵌套元素应当缩进一次(即两个空格)。
  • 对于属性的定义,确保全部使用双引号,绝不要使用单引号。
  • 不要在自闭合(self-closing)元素的尾部添加斜线 – HTML5 规范中明确说明这是可选的。
  • 不要省略可选的结束标签(closing tag)(例如,</li></body>)。
1
2
3
4
5
6
7
8
9
10
<!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 页面的第一行添加标准模式(standard mode)的声明,这样能够确保在每个浏览器中拥有一致的展现。

1
2
3
4
5
<!DOCTYPE html>
<html>
<head>
</head>
</html>

语言属性

根据 HTML5 规范:

强烈建议为 html 根元素指定 lang 属性,从而为文档设置正确的语言。这将有助于语音合成工具确定其所应该采用的发音,有助于翻译工具确定其翻译时所应遵守的规则等等。
更多关于 lang 属性的知识可以从 此规范 中了解。

这里列出了语言代码表

1
2
3
<html lang="zh-CN">
<!-- ... -->
</html>

IE 兼容模式

IE 支持通过特定的 <meta> 标签来确定绘制当前页面所应该采用的 IE 版本。除非有强烈的特殊需求,否则最好是设置为 edge mode,从而通知 IE 采用其所支持的最新的模式。

阅读这篇 stack overflow 上的文章可以获得更多有用的信息。

1
<meta http-equiv="X-UA-Compatible" content="IE=Edge">

字符编码

通过明确声明字符编码,能够确保浏览器快速并容易的判断页面内容的渲染方式。这样做的好处是,可以避免在 HTML 中使用字符实体标记(character entity),从而全部与文档编码一致(一般采用 UTF-8 编码)。

1
2
3
<head>
<meta charset="UTF-8">
</head>

引入 CSS 和 JavaScript 文件

根据 HTML5 规范,在引入 CSS 和 JavaScript 文件时一般不需要指定 type 属性,因为 text/css 和 text/javascript 分别是它们的默认值。

1
2
3
4
5
6
7
8
9
10
<!-- 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
  • title, alt
  • aria-*, role

class 用于标识高度可复用组件,因此应该排在首位。id 用于标识具体组件,应当谨慎使用(例如,页面内的书签),因此排在第二位。

1
2
3
4
5
6
7
<a class="..." id="..." data-modal="toggle" href="#">
Example link
</a>

<input class="form-control" type="text">

<img src="..." alt="...">

布尔(boolean)型属性

布尔型属性可以在声明时不赋值。XHTML 规范要求为其赋值,但是 HTML5 规范不需要。

更多信息请参考 WhatWG section on boolean attributes

元素的布尔型属性如果有值,就是 true,如果没有值,就是 false。

如果一定要为其赋值的话,请参考 WhatWG 规范:

如果属性存在,其值必须是空字符串或 […] 属性的规范名称,并且不要再收尾添加空白符。

简单来说,就是不用赋值。

1
2
3
4
5
6
7
<input type="text" disabled>

<input type="checkbox" value="1" checked>

<select>
<option value="1" selected>1</option>
</select>

减少标签的数量

编写 HTML 代码时,尽量避免多余的父元素。很多时候,这需要迭代和重构来实现。请看下面的案例:

1
2
3
4
5
6
7
<!-- Not so great -->
<span class="avatar">
<img src="...">
</span>

<!-- Better -->
<img class="avatar" src="...">

JavaScript 生成的标签

通过 JavaScript 生成的标签让内容变得不易查找、编辑,并且降低性能。能避免时尽量避免。

CSS

语法

  • 用两个空格来代替制表符(tab) – 这是唯一能保证在所有环境下获得一致展现的方法。
  • 为选择器分组时,将单独的选择器单独放在一行。
  • 为了代码的易读性,在每个声明块的左花括号前添加一个空格。
  • 声明块的右花括号应当单独成行。
  • 每条声明语句的 : 后应该插入一个空格。
  • 为了获得更准确的错误报告,每条声明都应该独占一行。
  • 所有声明语句都应当以分号结尾。最后一条声明语句后面的分号是可选的,但是,如果省略这个分号,你的代码可能更易出错。
  • 对于以逗号分隔的属性值,每个逗号后面都应该插入一个空格(例如,box-shadow)。
  • 不要在 rgb()rgba()hsl()hsla()rect() 值的内部的逗号后面插入空格。这样利于从多个属性值(既加逗号也加空格)中区分多个颜色值(只加逗号,不加空格)。
  • 对于属性值或颜色参数,省略小于 1 的小数前面的 0 (例如,.5 代替 0.5-.5px 代替 -0.5px)。
  • 十六进制值应该全部小写,例如,#fff。在扫描文档时,小写字符易于分辨,因为他们的形式更易于区分。
  • 尽量使用简写形式的十六进制值,例如,用 #fff 代替 #ffffff
  • 为选择器中的属性添加双引号,例如,input[type="text"]只有在某些情况下是可选的,但是,为了代码的一致性,建议都加上双引号。
  • 避免为 0 值指定单位,例如,用 margin: 0; 代替 margin: 0px;

对于这里用到的术语有疑问吗?请参考 Wikipedia 上的 syntax section of the Cascading Style Sheets article

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* Bad CSS */
.selector, .selector-secondary, .selector[type=text] {
padding:15px;
margin:0px 0px 15px;
background-color:rgba(0, 0, 0, 0.5);
box-shadow:0px 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)可以从正常的文档流中移除元素,并且还能覆盖盒模型(box model)相关的样式,因此排在首位。盒模型排在第二位,因为它决定了组件的尺寸和位置。

其他属性只是影响组件的内部(inside)或者是不影响前两组属性,因此排在后面。

完整的属性列表及其排列顺序请参考 Recess

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.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;
}

不要使用 @import

<link> 标签相比,@import 指令要慢很多,不光增加了额外的请求次数,还会导致不可预料的问题。替代办法有以下几种:

  • 使用多个 <link> 元素
  • 通过 Sass 或 Less 类似的 CSS 预处理器将多个 CSS 文件编译为一个文件
  • 通过 Rails、Jekyll 或其他系统中提供过 CSS 文件合并功能

请参考 Steve Souders 的文章了解更多知识。

1
2
3
4
5
6
7
<!-- Use link elements -->
<link rel="stylesheet" href="core.css">

<!-- Avoid @imports -->
<style>
@import url("more.css");
</style>

媒体查询(Media query)的位置

将媒体查询放在尽可能相关规则的附近。不要将他们打包放在一个单一样式文件中或者放在文档底部。如果你把他们分开了,将来只会被大家遗忘。下面给出一个典型的实例。

1
2
3
4
5
6
7
8
9
.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 (⌃⇧↓)。

1
2
3
4
5
/* 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 行有语法错误。如果是单行单条声明,你就不会忽略这个错误;如果是单行多条声明的话,你就要仔细分析避免漏掉错误了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* 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 的 heading 元素只需要设置上、下边距(margin)的值,因此,在必要的时候,只需覆盖这两个值就可以。过度使用简写形式的属性声明会导致代码混乱,并且会对属性值带来不必要的覆盖从而引起意外的副作用。

MDN(Mozilla Developer Network)上一片非常好的关于 shorthand properties 的文章,对于不太熟悉简写属性声明及其行为的用户很有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
 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 中的嵌套

避免非必要的嵌套。这是因为虽然你可以使用嵌套,但是并不意味着应该使用嵌套。只有在必须将样式限制在父元素内(也就是后代选择器),并且存在多个需要嵌套的元素时才使用嵌套。

1
2
3
4
5
6
7
8
9
// Without nesting
.table > thead > tr > th { … }
.table > thead > tr > td { … }

// With nesting
.table > thead > tr {
> th { … }
> td { … }
}

注释

代码是由人编写并维护的。请确保你的代码能够自描述、注释良好并且易于他人理解。好的代码注释能够传达上下文关系和代码目的。不要简单地重申组件或 class 名称。

对于较长的注释,务必书写完整的句子;对于一般性注解,可以书写简洁的短语。

1
2
3
4
5
6
7
8
9
10
11
/* Bad example */
/* Modal header */
.modal-header {
...
}

/* Good example */
/* Wrapping element for .modal-title and .modal-close */
.modal-header {
...
}

class 命名

  • class 名称中只能出现小写字符和破折号(dashe)(不是下划线,也不是驼峰命名法)。破折号应当用于相关 class 的命名(类似于命名空间)(例如,.btn.btn-danger)。
  • 避免过度任意的简写。.btn 代表 button,但是 .s 不能表达任何意思。
  • class 名称应当尽可能短,并且意义明确。
  • 使用有意义的名称。使用有组织的或目的明确的名称,不要使用表现形式(presentational)的名称。
  • 基于最近的父 class 或基本(base) class 作为新 class 的前缀。
  • 使用 .js-* class 来标识行为(与样式相对),并且不要将这些 class 包含到 CSS 文件中。

在为 Sass 和 Less 变量命名是也可以参考上面列出的各项规范。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/* Bad example */
.t { ... }
.red { ... }
.header { ... }

/* Good example */
.tweet { ... }
.important { ... }
.tweet-header { ... }
~~~

## 选择器
* 对于通用元素使用 class ,这样利于渲染性能的优化。
* 对于经常出现的组件,避免使用属性选择器(例如,[class^="..."])。浏览器的性能会受到这些因素的影响。
* 选择器要尽可能短,并且尽量限制组成选择器的元素个数,建议不要超过 3
* **只有**在必要的时候才将 class 限制在最近的父元素内(也就是后代选择器)(例如,不使用带前缀的 class 时 -- 前缀类似于命名空间)。

扩展阅读:

* [Scope CSS classes with prefixes](http://markdotto.com/2012/02/16/scope-css-classes-with-prefixes/)
* [Stop the cascade](http://markdotto.com/2012/03/02/stop-the-cascade/)

```CSS
/* Bad example */
span { ... }
.page-container #stream .stream-item .tweet .tweet-header .username { ... }
.avatar { ... }

/* Good example */
.avatar { ... }
.tweet-header .username { ... }
.tweet .avatar { ... }

代码组织

  • 以组件为单位组织代码段。
  • 制定一致的注释规范。
  • 使用一致的空白符将代码分隔成块,这样利于扫描较大的文档。
  • 如果使用了多个 CSS 文件,将其按照组件而非页面的形式分拆,因为页面会被重组,而组件只会被移动。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
* 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 { ... }

编辑器配置

将你的编辑器按照下面的配置进行设置,以避免常见的代码不一致和差异:

  • 用两个空格代替制表符(soft-tab 即用空格代表 tab 符)。
  • 保存文件时,删除尾部的空白符。
  • 设置文件编码为 UTF-8。
  • 在文件结尾添加一个空白行。

参照文档并将这些配置信息添加到项目的 editorconfig 文件中。例如:Bootstrap 中的 .editorconfig 实例。更多信息请参考 about EditorConfig

<3

Heavily inspired by Idiomatic CSS and the GitHub Styleguide. Made with all the love in the world by @mdo.

一、事件查看器

开始 → 程序 → 管理工具 → 计算机管理 → 系统工具 → 事件查看器 → 清除日志。

二、日志文件

Windows2000的日志文件通常有应用程序日志安全日志系统日志DNS服务器日志FTP日志WWW日志等等。

日志文件默认位置:

应用程序日志、安全日志、系统日志、DNS日志默认位置:%systemroot%\system32\config,默认文件大小512KB,管理员都会改变这个默认大小。

安全日志文件:%systemroot%\system32\config\SecEvent.EVT

系统日志文件:%systemroot%\system32\config\SysEvent.EVT

应用程序日志文件:%systemroot%\system32\config\AppEvent.EVT

Internet信息服务FTP日志默认位置:%systemroot%\system32\log\filesmsftpsvc1,默认每天一个日志;

Internet信息服务WWW日志默认位置:%systemroot%\system32\log\filesw3svc1,默认每天一个日志;

Scheduler服务日志默认位置:%systemroot%\schedlgu.txt

以上日志在注册表里的键:

应用程序日志,安全日志,系统日志,DNS服务器日志,它们这些LOG文件在注册表中的:

HKEY_LOCAL_MACHINE\system\Current\Control\Set\Services\Eventlog

有的管理员很可能将这些日志重定位。其中EVENTLOG下面有很多的子表,里面可查到以上日志的定位目录。

Schedluler服务日志在注册表中

HKEY_LOCAL_MACHINESOFTWAREMicrosoftSchedulingAgent

FTP和WWW日志详解:

FTP日志和WWW日志默认情况,每天生成一个日志文件,包含了该日的一切记录,文件名通常为ex(年份)(月份)(日期),例如ex001023,就是2000年10月23日产生的日志,用记事本就可直接打开,如下例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#Software: Microsoft Internet Information Services 5.0  (微软IIS5.0)
#Version: 1.0 (版本1.0)
#Date: 20001023 0315 (服务启动时间日期)
#Fields: time cip csmethod csuristem scstatus
0315 127.0.0.1 [1]USER administator 331 (IP地址为127.0.0.1用户名为administator试图登录)
0318 127.0.0.1 [1]PASS –530 (登录失败)
032:04 127.0.0.1 [1]USER nt 331 (IP地址为127.0.0.1用户名为nt的用户试图登录)
032:06 127.0.0.1 [1]PASS –530 (登录失败)
032:09 127.0.0.1 [1]USER cyz 331 (IP地址为127.0.0.1用户名为cyz的用户试图登录)
0322 127.0.0.1 [1]PASS –530 (登录失败)
0322 127.0.0.1 [1]USER administrator 331 (IP地址为127.0.0.1用户名为administrator试图登录)
0324 127.0.0.1 [1]PASS –230 (登录成功)
0321 127.0.0.1 [1]MKD nt 550 (新建目录失败)
0325 127.0.0.1 [1]QUIT –550 (退出FTP程序)

从 日志里就能看出IP地址为127.0.0.1的用户一直试图登录系统,换了四次用户名和密码才成功,管理员立即就可以得知管理员的入侵时间、IP地址以及 探测的用户名,如上例入侵者最终是用administrator用户名进入的,那么就要考虑更换此用户名的密码,或者重命名administrator 用户。

WWW日志:

WWW服务同FTP服务一样,产生的日志也是在%sys temroot%sys tem32LogFilesW3SVC1目录下,默认是每天一个日志文件,下面是一个典型的WWW日志文件

1
2
3
4
5
6
#Software: Microsoft Internet Information Services 5.0
#Version: 1.0
#Date: 20001023 03:091
#Fields: date time cip csusername sip sport csmethod csuristem csuriquery scstatus cs(UserAgent)
20001023 03:091 192.168.1.26 192.168.1.37 80 GET /iisstart.asp 200 Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)
20001023 03:094 192.168.1.26 192.168.1.37 80 GET /pagerror.gif 200 Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)

通 过分析第六行,可以看出2000年10月23日,IP地址为192.168.1.26的用户通过访问IP地址为192.168.1.37机器的80端口, 查看了一个页面iisstart.asp,这位用户的浏览器为compatible; MSIE 5.0; Windows 98 DigExt,有经验的管理员就可通过安全日志、FTP日志和WWW日志来确定入侵者的IP地址以及入侵时间。

既使你删掉FTP和WWW日志,但是还是会在系统日志和安全日志里记录下来,但是较好的是只显示了你的机器名,并没有你的IP。

属性里记录了出现警告的原因,是因为有人试图用administator用户名登录,出现一个错误,来源是FTP服务。

这里有两种图标:钥匙(表示成功)和锁(表示当用户在做什么时被系统停止)。接连四个锁图标,表示四次失败审核,事件类型是帐户登录和登录、注销失败,日期为2000年10月18日,时间为1002,这就需要重点观察。

双点第一个失败审核事件的,即得到此事件的详细描述。

经过分析我们可以得知有个CYZ的工作站,用administator用户名登录本机,但是因为用户名未知或密码错误(实际为密码错误)未能成功。另外还有DNS服务器日志,不太重要,就此略过(其实是我没有看过它)。

知道了Windows2000日志的详细情况,下面就要学会怎样删除这些日志:

通 过上面,得知日志文件通常有某项服务在后台保护,除了系统日志、安全日志、应用程序日志等等,它们的服务是Windos2000的关键进程,而且与注册表 文件在一块,当Windows2000启动后,启动服务来保护这些文件,所以很难删除,而FTP日志和WWW日志以及Scedlgu日志都是可以轻易地删 除的。首先要取得Admnistrator密码或Administrators组成员之一, www.2cto.com 然后Telnet到远程主机,先来试着删除FTP日志:

1
2
D:SERVER>del schedlgu.txt
D:SERVERSchedLgU.Txt

进程无法访问文件,因为另一个程序正在使用此文件。说过了,后台有服务保护,先把服务停掉!

1
D:SERVER>net stop "task scheduler"

下面的服务依赖于Task Scheduler 服务。停止Task Scheduler 服务也会停止这些服务。

1
2
3
4
5
6
Remote Storage Engine
是否继续此操作? (Y/N) [N]: y
Remote Storage Engine 服务正在停止….
Remote Storage Engine 服务已成功停止。
Task Scheduler 服务正在停止.
Task Scheduler 服务已成功停止。

OK,它的服务停掉了,同时也停掉了与它有依赖关系的服务。再来试着删一下!

1
2
D:\SERVER>del schedlgu.txt
D:\SERVER>

没有反应?成功了!下一个是FTP日志和WWW日志,原理都是一样,先停掉相关服务,然后再删日志!

1
2
D:\SERVER\system32\LogFiles\MSFTPSVC1>del ex*.log
D:\SERVER\system32\LogFiles\MSFTPSVC1>

以上操作成功删除FTP日志!再来WWW日志!

1
2
D:SERVERsystem32LogFilesW3SVC1>del ex*.log
D:SERVERsystem32LogFilesW3SVC1>

OK!恭喜,现在简单的日志都已成功删除。下面就是很难的安全日志和系统日志了,守护这些日志的服务是Event Log,试着停掉它!

1
D:SERVERsystem32LogFilesW3SVC1>net stop eventlog

这 项服务无法接受请求的 “暂停” 或 “停止” 操作。没办法,它是关键服务。如果不用第三方工具,在命令行上根本没有删除安全日志和系统日志的可能!所以还是得用虽然简单但是速度慢得死机的办法:打开 “控制面板”的“管理工具”中的“事件查看器”(98没有,知道用Win2k的好处了吧),在菜单的“操作”项有一个名为“连接到另一台计算机”的菜单, 点击它,输入远程计算机的IP,然后等上数十分钟,接着选择远程计算机的安全性日志,右键选择它的属性:点击属性里的“清除日志”按钮,OK!安全日志清 除完毕!同样的忍受痛苦去清除系统日志! 目前在不借助第三工具的情况下,能很快,很顺利地清除FTP、WWW还有Schedlgu日志,就是系统日志和安全日志属于Windows2000的严密守护,只能用本地的事件查看器来打开它,因为在图形界面下,加 之网速又慢,如果你银子多,时间闲,还是可以清除它的。综上所述,介绍了Windows2000的日志文件以及删除方法,但是你必须是Administrator,注意必须作为管理员或管理组的成员登录才能打开安全日志记录。该过程适用于Windows 2000 Professional 计算机,也适用于作为独立服务器或成员服务器运行的Windows 2000 Server 计算机。

至 此,Windows2000安全知识基础讲座完毕,还有几句话要讲,大家也看出来了,虽然FTP等等日志可以很快清除,但是系统日志和安全日志却不是那么 快、那么顺利地能删除,如果遇到聪明的管理员,将日志文件转移到另一个地方,那更是难上加难,所以奉劝大家,千万不要拿国内的主机做试验,国内的法律很严 呀!今天吃饭时,听说有两个人开玩笑,一个人把另外一个人的东西藏起来了,结果那个人一急,报案了,于是藏东西那个人被判四年刑!!法官说法律是不开玩笑 的!!!所以大家一定要牢记这点!

Standard Markdown

Strong and Emphasize

1
2
*emphasize*   **strong**
_emphasize_ __strong__

Inline:

1
An [example](http://url.com/ "Title")

Reference-style labels (titles are optional):

1
2
3
4
5

An [example][id]. Then, anywhere
else in the doc, define the link:

[id]: http://example.com/ "Title"

Email:

1
An email <example@example.com> link.

Images

Inline (titles are optional):

1
![alt text](/path/img.jpg "Title")

Reference-style:

1
2
3
![alt text][id]

[id]: /url/to/img.jpg "Title"

Headers

1
2
3
4
5
6
7
Setext-style:

Header 1
========

Header 2
--------

atx-style (closing #’s are optional):

1
2
3
4
5
# Header 1 #

## Header 2 ##

###### Header 6

Lists

Ordered, without paragraphs:

1
2
1.  Foo
2. Bar

Unordered, with paragraphs:

1
2
3
4
5
*   A list item.

With multiple paragraphs.

* Bar

You can nest them:

1
2
3
4
5
6
7
8
*   Abacus
* answer
* Bubbles
1. bunk
2. bupkis
* BELITTLER
3. burper
* Cunning

Blockquotes

1
2
3
4
5
6
7
8
9
> Email-style angle brackets
> are used for blockquotes.

> > And, they can be nested.

> #### Headers in blockquotes
>
> * You can quote a list.
> * Etc.

Inline Code

1
2
3
4
5
`<code>` spans are delimited
by backticks.

You can include literal backticks
like `` `this` ``.

Block Code

Indent every line of a code block by at least 4 spaces or 1 tab.

1
2
3
4
This is a normal paragraph.

This is a preformatted
code block.

Horizontal Rules

Three or more dashes or asterisks:

1
2
3
4
5
---

* * *

- - - -

Hard Line Breaks

End a line with two or more spaces:

Roses are red, Violets are blue.