├── docs
├── rustdoc
├── typedoc
├── welcome.ts
├── favicon.ico
├── images
│ ├── deno_logo.png
│ ├── deno_logo_2.gif
│ ├── schematic_v0.2.png
│ └── deno_logo_3.svg
├── toc.js
├── sticky_toc.js
├── manual.html
├── style_guide.html
├── style.css
├── showdown_toc.js
├── app_test.js
├── benchmarks.html
├── style_guide.zh.md
├── index.html
├── app.js
├── style_guide.md
├── manual.zh.md
└── manual.md
├── .mds-list
├── .gitignore
├── sync-en.sh
├── readme.md
├── style_guide.zh.md
├── style_guide.md
├── manual.zh.md
└── manual.md
/docs/rustdoc:
--------------------------------------------------------------------------------
1 | ../target/doc/
--------------------------------------------------------------------------------
/docs/typedoc:
--------------------------------------------------------------------------------
1 | ../target/typedoc/
--------------------------------------------------------------------------------
/.mds-list:
--------------------------------------------------------------------------------
1 | source/manual.md
2 | source/style_guide.md
3 |
--------------------------------------------------------------------------------
/docs/welcome.ts:
--------------------------------------------------------------------------------
1 | console.log("Welcome to Deno 🦕");
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .DS_Store
3 | fork
4 | source
5 | hub-create.sh
--------------------------------------------------------------------------------
/docs/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chinanf-boy/deno-website-zh/master/docs/favicon.ico
--------------------------------------------------------------------------------
/docs/images/deno_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chinanf-boy/deno-website-zh/master/docs/images/deno_logo.png
--------------------------------------------------------------------------------
/docs/images/deno_logo_2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chinanf-boy/deno-website-zh/master/docs/images/deno_logo_2.gif
--------------------------------------------------------------------------------
/docs/images/schematic_v0.2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chinanf-boy/deno-website-zh/master/docs/images/schematic_v0.2.png
--------------------------------------------------------------------------------
/docs/toc.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | let H = `
`;
3 |
4 | function liEl(str, id) {
5 | return `${str} `;
6 | }
7 |
8 | function run() {
9 | setTimeout(() => {
10 | if (window.anchors && window.anchors.elements.length) {
11 | let lis = window.anchors.elements.map(el => {
12 | return liEl(el.innerText, el.id);
13 | });
14 | let result = `${H}${lis.join('\n')} `;
15 | document.getElementsByClassName("toc")[0].innerHTML = result;
16 | } else {
17 | console.log('query anchors again');
18 | run();
19 | }
20 | }, 100);
21 | }
22 |
23 | run();
24 | })();
25 |
--------------------------------------------------------------------------------
/sync-en.sh:
--------------------------------------------------------------------------------
1 | cat './.mds-list' | while read line || [[ -n ${line} ]]
2 | do
3 | testseq="zh.md"
4 | if [[ $line =~ $testseq || "$line" == "" ]]; then
5 | echo "skip $line"
6 | else
7 | lowline=`echo "$line" | awk '{print tolower($0)}'`
8 | # lowwer string
9 | zh=${line//source\//}
10 | dir=$(dirname $zh)
11 |
12 | source_readme="./source/readme.md"
13 | if [[ $lowline == $source_readme ]];then
14 | # source/[readme|REAMDE].md => en.md
15 | filename="en.md"
16 | else
17 | # source/other.md => ./other.md
18 | filename=$(basename $zh)
19 | fi
20 | echo "$line >> $dir/$filename"
21 | mkdir -p $dir && cp $line "$_/$filename"
22 | fi
23 | done
--------------------------------------------------------------------------------
/docs/sticky_toc.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | const isTopOut = function(elem) {
3 | const bounding = elem.getBoundingClientRect();
4 | return bounding.top <= 20 && bounding.left >= 0;
5 | };
6 |
7 | function changePosition(el, add) {
8 | if (add) {
9 | el.style.position = 'fixed'; // actually use fixed
10 | el.style.top = '0em';
11 | el.style.bottom = '1em';
12 | // el.style.right = '0em';
13 | el.style.maxHeight = 'max-content';
14 |
15 | } else {
16 | el.style.position = 'absolute';
17 | // el.style.right = '1em';
18 | el.style.top = '';
19 | el.style.bottom = '';
20 | }
21 | }
22 | let manualEl;
23 | let tocEl;
24 |
25 | window.addEventListener('scroll', event => {
26 | !manualEl && (manualEl = document.getElementById('manual'));
27 | !tocEl && (tocEl = document.getElementsByClassName('toc')[0]);
28 |
29 | if (window.innerWidth >= 1200) {
30 | if (isTopOut(manualEl) && tocEl.style.position != 'fixed') {
31 | changePosition(tocEl, true);
32 | } else if (!isTopOut(manualEl) && tocEl.style.position == 'fixed') {
33 | changePosition(tocEl, false);
34 | }
35 | }
36 | });
37 | })();
38 |
--------------------------------------------------------------------------------
/docs/manual.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Deno Manual
6 |
7 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/docs/style_guide.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Deno Style Guide
6 |
7 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/docs/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: #444;
3 | background: #f0f0f0;
4 | padding: 0;
5 |
6 | line-height: 1.5;
7 | font-family: sans-serif;
8 |
9 | margin: 5ex 10ex;
10 | max-width: 80ex;
11 | }
12 |
13 | #manual img {
14 | width: 100%;
15 | max-width: 800px;
16 | }
17 |
18 | h1,
19 | h2,
20 | h3,
21 | h4 {
22 | font-weight: normal;
23 | margin-bottom: 0;
24 | }
25 |
26 | h1,
27 | h2,
28 | h3,
29 | h4,
30 | p,
31 | table {
32 | margin-left: 8px;
33 | margin-right: 8px;
34 | }
35 |
36 | table {
37 | border-collapse: collapse;
38 | margin-top: 8px;
39 | }
40 | td,
41 | th {
42 | font-weight: normal;
43 | text-align: center;
44 | border: 1px dotted #bbb;
45 | padding: 4px;
46 | }
47 |
48 | svg {
49 | margin: 0px;
50 | width: 100%;
51 | height: 300px;
52 | }
53 |
54 | a {
55 | color: #106ad5;
56 | }
57 |
58 | pre a {
59 | color: #001631;
60 | }
61 |
62 | h2 a,
63 | h3 a {
64 | display: none;
65 | color: #3bace5;
66 | text-decoration: none;
67 | }
68 |
69 | h2:hover a,
70 | h3:hover a {
71 | display: inline;
72 | }
73 |
74 | pre {
75 | /* background: rgba(36, 126, 233, 0.03); */
76 | color: #161616;
77 | background: rgba(36, 126, 233, 0.1);
78 | padding: 15px;
79 | word-wrap: normal;
80 | overflow-x: auto;
81 | }
82 |
83 | header {
84 | display: flex;
85 | align-items: center;
86 | margin: 16px 4px;
87 | }
88 |
89 | header > * {
90 | margin: 8px;
91 | }
92 |
93 | header h1 {
94 | margin: 8px 0;
95 | }
96 |
97 | @media only screen and (max-device-width: 480px) {
98 | body {
99 | margin: 0;
100 | }
101 | }
102 |
103 | code {
104 | background: rgba(36, 126, 233, 0.1);
105 | padding: 2px 5px;
106 | color: #333;
107 | }
108 |
109 | .hljs {
110 | background: transparent;
111 | }
112 |
113 | .toc {
114 | position: relative;
115 | }
116 |
117 | @media only screen and (min-width: 1250px) {
118 | .toc {
119 | background-color: #fbf6ec;
120 | max-width: 40%;
121 | position: absolute;
122 | border: #968674 dashed 3px;
123 | right: 1em;
124 | width: var(--sidebar-width);
125 | overflow-y: auto;
126 | padding: 0 10px;
127 | font-size: 0.875em;
128 | box-sizing: border-box;
129 | -webkit-overflow-scrolling: touch;
130 | overscroll-behavior-y: contain;
131 | background-color: var(--sidebar-bg);
132 | color: var(--sidebar-fg);
133 | }
134 |
135 | .toc li {
136 | padding: 1px 3px;
137 | }
138 |
139 | .toc::-webkit-scrollbar {
140 | display: none;
141 | }
142 | }
143 |
144 |
--------------------------------------------------------------------------------
/docs/showdown_toc.js:
--------------------------------------------------------------------------------
1 | // Extension loading compatible with AMD and CommonJs
2 | (function(extension) {
3 | "use strict";
4 |
5 | if (typeof showdown === "object") {
6 | // global (browser or nodejs global)
7 | showdown.extension("toc", extension());
8 | } else if (typeof define === "function" && define.amd) {
9 | // AMD
10 | define("toc", extension());
11 | } else if (typeof exports === "object") {
12 | // Node, CommonJS-like
13 | module.exports = extension();
14 | } else {
15 | // showdown was not found so we throw
16 | throw Error("Could not find showdown library");
17 | }
18 | })(function() {
19 | function getHeaderEntries(sourceHtml) {
20 | if (typeof window === "undefined") {
21 | return getHeaderEntriesInNodeJs(sourceHtml);
22 | } else {
23 | return getHeaderEntriesInBrowser(sourceHtml);
24 | }
25 | }
26 |
27 | function getHeaderEntriesInNodeJs(sourceHtml) {
28 | var cheerio = require("cheerio");
29 | var $ = cheerio.load(sourceHtml);
30 | var headers = $("h1, h2, h3, h4, h5, h6");
31 |
32 | var headerList = [];
33 | for (var i = 0; i < headers.length; i++) {
34 | var el = headers[i];
35 | headerList.push(new TocEntry(el.name, $(el).text(), $(el).attr("id")));
36 | }
37 |
38 | return headerList;
39 | }
40 |
41 | function getHeaderEntriesInBrowser(sourceHtml) {
42 | // Generate dummy element
43 | var source = document.createElement("div");
44 | source.innerHTML = sourceHtml;
45 |
46 | // Find headers
47 | var headers = source.querySelectorAll("h1, h2, h3, h4, h5, h6");
48 | var headerList = [];
49 | for (var i = 0; i < headers.length; i++) {
50 | var el = headers[i];
51 | headerList.push(new TocEntry(el.tagName, el.textContent, el.id));
52 | }
53 |
54 | return headerList;
55 | }
56 |
57 | function TocEntry(tagName, text, anchor) {
58 | this.tagName = tagName;
59 | this.text = text;
60 | this.anchor = anchor;
61 | this.children = [];
62 | }
63 |
64 | TocEntry.prototype.childrenToString = function() {
65 | if (this.children.length === 0) {
66 | return "";
67 | }
68 | var result = "\n";
69 | for (var i = 0; i < this.children.length; i++) {
70 | result += this.children[i].toString();
71 | }
72 | result += " \n";
73 | return result;
74 | };
75 |
76 | TocEntry.prototype.toString = function() {
77 | var result = "";
78 | if (this.text) {
79 | result += '' + this.text + " ";
80 | }
81 | result += this.childrenToString();
82 | result += " \n";
83 | return result;
84 | };
85 |
86 | function sortHeader(tocEntries, level) {
87 | level = level || 1;
88 | var tagName = "H" + level,
89 | result = [],
90 | currentTocEntry;
91 |
92 | function push(tocEntry) {
93 | if (tocEntry !== undefined) {
94 | if (tocEntry.children.length > 0) {
95 | tocEntry.children = sortHeader(tocEntry.children, level + 1);
96 | }
97 | result.push(tocEntry);
98 | }
99 | }
100 |
101 | for (var i = 0; i < tocEntries.length; i++) {
102 | var tocEntry = tocEntries[i];
103 | if (tocEntry.tagName.toUpperCase() !== tagName) {
104 | if (currentTocEntry === undefined) {
105 | currentTocEntry = new TocEntry();
106 | }
107 | currentTocEntry.children.push(tocEntry);
108 | } else {
109 | push(currentTocEntry);
110 | currentTocEntry = tocEntry;
111 | }
112 | }
113 |
114 | push(currentTocEntry);
115 | return result;
116 | }
117 |
118 | return {
119 | type: "output",
120 | filter: function(sourceHtml) {
121 | var headerList = getHeaderEntries(sourceHtml);
122 |
123 | // No header found
124 | if (headerList.length === 0) {
125 | return sourceHtml;
126 | }
127 |
128 | // Sort header
129 | headerList = sortHeader(headerList);
130 |
131 | // Skip the title.
132 | if (headerList.length == 1) {
133 | headerList = headerList[0].children;
134 | }
135 |
136 | // Build result and replace all [toc]
137 | var result =
138 | '\n
\n' + headerList.join("") + " \n
\n";
139 | return sourceHtml.replace(/\[toc\]/gi, result);
140 | }
141 | };
142 | });
143 |
--------------------------------------------------------------------------------
/docs/app_test.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
2 |
3 | import { test, testPerm, assert, assertEquals } from "../js/test_util.ts";
4 | import {
5 | createBinarySizeColumns,
6 | createExecTimeColumns,
7 | createThreadCountColumns,
8 | createSyscallCountColumns,
9 | createSha1List
10 | } from "./app.js";
11 |
12 | const regularData = [
13 | {
14 | created_at: "2018-01-01T01:00:00Z",
15 | sha1: "abcdef",
16 | binary_size: {
17 | deno: 100000000,
18 | "main.js": 90000000,
19 | "main.js.map": 80000000,
20 | "snapshot_deno.bin": 70000000
21 | },
22 | throughput: {
23 | "100M_tcp": 3.6,
24 | "100M_cat": 3.0,
25 | "10M_tcp": 1.6,
26 | "10M_cat": 1.0
27 | },
28 | req_per_sec: {
29 | node: 16000,
30 | deno: 1000
31 | },
32 | benchmark: {
33 | hello: {
34 | mean: 0.05
35 | },
36 | relative_import: {
37 | mean: 0.06
38 | },
39 | cold_hello: {
40 | mean: 0.05
41 | },
42 | cold_relative_import: {
43 | mean: 0.06
44 | }
45 | },
46 | thread_count: {
47 | set_timeout: 4,
48 | fetch_deps: 6
49 | },
50 | syscall_count: {
51 | hello: 600,
52 | fetch_deps: 700
53 | }
54 | },
55 | {
56 | created_at: "2018-01-02T01:00:00Z",
57 | sha1: "012345",
58 | binary_size: {
59 | deno: 100000001,
60 | "main.js": 90000001,
61 | "main.js.map": 80000001,
62 | "snapshot_deno.bin": 70000001
63 | },
64 | throughput: {
65 | "100M_tcp": 3.6,
66 | "100M_cat": 3.0,
67 | "10M_tcp": 1.6,
68 | "10M_cat": 1.0
69 | },
70 | req_per_sec: {
71 | node: 1600,
72 | deno: 3.0
73 | },
74 | benchmark: {
75 | hello: {
76 | mean: 0.055
77 | },
78 | relative_import: {
79 | mean: 0.065
80 | },
81 | cold_hello: {
82 | mean: 0.055
83 | },
84 | cold_relative_import: {
85 | mean: 0.065
86 | }
87 | },
88 | thread_count: {
89 | set_timeout: 5,
90 | fetch_deps: 7
91 | },
92 | syscall_count: {
93 | hello: 700,
94 | fetch_deps: 800
95 | }
96 | }
97 | ];
98 |
99 | const irregularData = [
100 | {
101 | created_at: "2018-01-01T01:00:00Z",
102 | sha1: "123",
103 | benchmark: {},
104 | throughput: {},
105 | binary_size: {},
106 | thread_count: {},
107 | syscall_count: {}
108 | },
109 | {
110 | created_at: "2018-02-01T01:00:00Z",
111 | sha1: "456",
112 | benchmark: {
113 | hello: {},
114 | relative_import: {},
115 | cold_hello: {},
116 | cold_relative_import: {}
117 | },
118 | throughput: {
119 | "100M_tcp": 3.0
120 | },
121 | binary_size: {
122 | deno: 1
123 | },
124 | thread_count: {
125 | set_timeout: 5,
126 | fetch_deps: 7
127 | },
128 | syscall_count: {
129 | hello: 700,
130 | fetch_deps: 800
131 | }
132 | }
133 | ];
134 |
135 | test(function createExecTimeColumnsRegularData() {
136 | const columns = createExecTimeColumns(regularData);
137 | assertEquals(columns, [
138 | ["hello", 0.05, 0.055],
139 | ["relative_import", 0.06, 0.065],
140 | ["cold_hello", 0.05, 0.055],
141 | ["cold_relative_import", 0.06, 0.065]
142 | ]);
143 | });
144 |
145 | test(function createExecTimeColumnsIrregularData() {
146 | const columns = createExecTimeColumns(irregularData);
147 | assertEquals(columns, [
148 | ["hello", null, null],
149 | ["relative_import", null, null],
150 | ["cold_hello", null, null],
151 | ["cold_relative_import", null, null]
152 | ]);
153 | });
154 |
155 | test(function createBinarySizeColumnsRegularData() {
156 | const columns = createBinarySizeColumns(regularData);
157 | assertEquals(columns, [
158 | ["deno", 100000000, 100000001],
159 | ["main.js", 90000000, 90000001],
160 | ["main.js.map", 80000000, 80000001],
161 | ["snapshot_deno.bin", 70000000, 70000001]
162 | ]);
163 | });
164 |
165 | test(function createBinarySizeColumnsIrregularData() {
166 | const columns = createBinarySizeColumns(irregularData);
167 | assertEquals(columns, [["deno", null, 1]]);
168 | });
169 |
170 | test(function createThreadCountColumnsRegularData() {
171 | const columns = createThreadCountColumns(regularData);
172 | assertEquals(columns, [["set_timeout", 4, 5], ["fetch_deps", 6, 7]]);
173 | });
174 |
175 | test(function createThreadCountColumnsIrregularData() {
176 | const columns = createThreadCountColumns(irregularData);
177 | assertEquals(columns, [["set_timeout", null, 5], ["fetch_deps", null, 7]]);
178 | });
179 |
180 | test(function createSyscallCountColumnsRegularData() {
181 | const columns = createSyscallCountColumns(regularData);
182 | assertEquals(columns, [["hello", 600, 700], ["fetch_deps", 700, 800]]);
183 | });
184 |
185 | test(function createSyscallCountColumnsIrregularData() {
186 | const columns = createSyscallCountColumns(irregularData);
187 | assertEquals(columns, [["hello", null, 700], ["fetch_deps", null, 800]]);
188 | });
189 |
190 | test(function createSha1ListRegularData() {
191 | const sha1List = createSha1List(regularData);
192 | assertEquals(sha1List, ["abcdef", "012345"]);
193 | });
194 |
--------------------------------------------------------------------------------
/docs/benchmarks.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Deno Benchmarks
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Deno Continuous Benchmarks
15 |
16 |
17 | These plots are updated on every commit to
18 | master branch .
19 |
20 |
21 | recent data
22 | all data (takes a moment to load)
23 |
24 | Execution time #
25 |
26 | This shows how much time total it takes to run a few simple deno
27 | programs:
28 |
31 | tests/002_hello.ts
32 | ,
33 | tests/003_relative_import.ts ,
37 | tests/worker_round_robin_bench.ts , and
41 | tests/worker_startup_bench.ts . For deno to execute typescript, it must first compile it to JS. A
45 | warm startup is when deno has a cached JS output already, so it should
46 | be fast because it bypasses the TS compiler. A cold startup is when deno
47 | must compile from scratch.
48 |
49 |
50 |
51 | Throughput #
52 |
53 |
54 | Time it takes to pipe a certain amount of data through Deno.
55 |
56 |
59 | echo_server.ts
60 |
61 | and
62 |
63 | cat.ts . Smaller is better.
65 |
66 |
67 |
68 |
69 | Req/Sec #
70 |
71 |
72 | Tests HTTP server performance. 10 keep-alive connections do as many
73 | hello-world requests as possible. Bigger is better.
74 |
75 |
76 |
117 |
118 |
119 |
120 | Max Latency #
121 |
122 |
123 | Max latency during the same test used above for requests/second. Smaller is better.
124 |
125 |
126 |
127 |
128 | Executable size #
129 | deno ships only a single binary. We track its size here.
130 |
131 |
132 | Thread count #
133 | How many threads various programs use.
134 |
135 |
136 | Syscall count #
137 |
138 | How many total syscalls are performed when executing a given script.
139 |
140 |
141 |
142 |
143 |
144 |
145 |
153 |
154 |
155 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # denoland/deno [![explain]][source] [![translate-svg]][translate-list]
2 |
3 |
4 |
5 | [explain]: http://llever.com/explain.svg
6 | [source]: https://github.com/chinanf-boy/Source-Explain
7 | [translate-svg]: http://llever.com/translate.svg
8 | [translate-list]: https://github.com/chinanf-boy/chinese-translate-list
9 | [size-img]: https://packagephobia.now.sh/badge?p=Name
10 | [size]: https://packagephobia.now.sh/result?p=Name
11 |
12 | 「 JavaScript 和 TypeScript 安全运行时,使用 V8, Rust, 和 Tokio 构建。」
13 |
14 | [中文](./readme.md) | [english](https://github.com/denoland/deno)
15 |
16 | ---
17 |
18 | ## 校对 ✅
19 |
20 |
21 |
22 |
23 |
24 |
25 | | 翻译的原文 | 与日期 | 最新更新 | 更多 |
26 | | ---------- | ------------- | -------- | -------------------------- |
27 | | [commit] | ⏰ 2019-04-07 | ![last] | [中文翻译][translate-list] |
28 |
29 | [last]: https://img.shields.io/github/last-commit/denoland/deno.svg
30 | [commit]: https://github.com/denoland/deno/tree/3324afbd404a4237f0339e50a345a5f20c4ea7dd
31 |
32 |
33 |
34 | 原文:denoland/deno/website
35 |
36 | - [x] readme
37 | - [x] [手册](./manual.zh.md)
38 | - [x] [风格指南](./style_guide.zh.md)
39 |
40 | ### 贡献
41 |
42 | 欢迎 👏 勘误/校对/更新贡献 😊 [具体贡献请看](https://github.com/chinanf-boy/chinese-translate-list#贡献)
43 |
44 | ## 生活
45 |
46 | [help me live , live need money 💰](https://github.com/chinanf-boy/live-need-money)
47 |
48 | ---
49 |
50 |
51 |
52 |
53 | # Deno
54 |
55 | JavaScript 和 TypeScript 安全运行时,使用 V8, Rust, 和 Tokio 构建。
56 |
57 |
126 |
127 | ## 安装
128 |
129 | 使用 Shell:
130 |
131 | ```bash
132 | curl -fsSL https://github.com/denoland/deno_install/blob/master/install.sh | sh
133 | ```
134 |
135 | Or 使用 PowerShell:
136 |
137 | ```
138 | iwr https://github.com/denoland/deno_install/blob/master/install.ps1 | iex
139 | ```
140 |
141 | 查看 [deno_install](https://github.com/denoland/deno_install) ,了解更多
142 |
143 | ## 例子
144 |
145 | 尝试运行一个简单程序:
146 |
147 | ```bash
148 | deno https://deno.land/welcome.ts
149 | ```
150 |
151 | 或更为复杂点的:
152 |
153 | ```typescript
154 | import {serve} from 'https://deno.land/std@v0.3.2/http/server.ts';
155 |
156 | async function main() {
157 | const body = new TextEncoder().encode('Hello World\n');
158 | for await (const req of serve(':8000')) {
159 | req.respond({body});
160 | }
161 | }
162 |
163 | main();
164 | ```
165 |
166 | ## 深挖...
167 |
168 | **[手册](http://llever.com/deno-website-zh/manual.html)**
169 |
170 | [API 参考](https://deno.land/typedoc/)
171 |
172 | [风格指南](http://llever.com/deno-website-zh/style_guide.html)
173 |
174 | [模块 存储库](https://deno.land/x/)
175 |
176 | [Twitter](https://twitter.com/deno_land)
177 |
178 | [发布记录](https://github.com/denoland/deno/blob/master/Releases.md)
179 |
180 | [社区聊天室](https://gitter.im/denolife/Lobby)
181 |
182 | [基准](https://deno.land/benchmarks.html)
183 |
184 | [awesome Deno](https://github.com/denolib/awesome-deno)
185 |
--------------------------------------------------------------------------------
/docs/style_guide.zh.md:
--------------------------------------------------------------------------------
1 | # Deno 风格指南
2 |
3 | ## 使用 TypeScript
4 |
5 | ## 使用术语"模块(module)",而不是"库(library)"或"包(package)"
6 |
7 | 为了明确性和一致性,请避免使用术语"库"和"包"。而是使用"module"来指明单个 JS 或 TS 文件,当然还包括 TS / JS 代码的目录。
8 |
9 | ## 不要使用文件名`"index.ts"或"index.js"`
10 |
11 | Deno 不会对"index.js"或"index.ts"特殊处理。这些文件名的使用,会对当不用它们时,却可以被排除在模块描述之外,感到困惑。
12 |
13 | 如果代码目录需要默认入口点,请使用文件名`mod.ts`。文件名`mod.ts`遵循 Rust 的惯例,比`index.ts`简短,并且没有任何先入为主,关于其应该如何运作的观念。
14 |
15 | ## 在"deno-std"中,不依赖外部代码
16 |
17 | `deno_std`旨在成为所有 Deno 程序可以依赖的地基功能。我们希望向用户保证此代码,不包含可能未经审核的第三方代码。
18 |
19 | ## 在"deno-std"中,最小化依赖关系;不要进行循环导入。
20 |
21 | 虽然`deno_std`是一个独立的代码库,我们仍然必须小心保持,内部依赖关系的简单和易于管理。特别要注意,不要产生(死)循环导入。
22 |
23 | ## 为了保持一致性,文件名请使用下划线,而不是短划线。
24 |
25 | 示例:不是`file-server.ts`,使用`file_server.ts`。
26 |
27 | ## 使用 prettier 格式化代码。
28 |
29 | 更具体地说,代码行应在 80 列内,使用 2 空格缩进,并使用驼峰式。使用`//format.ts`调用 prettier。
30 |
31 | ## 导出的函数:最多 2 个参数,将其余的参数放入 options 对象。
32 |
33 | 设计函数接口时,请遵守以下规则。
34 |
35 | 1. 作为公有 API 一部分的函数需要 0-2 个必需参数,如果需要的话,加上一个选项(options)对象(总共最多 3 个)。
36 |
37 | 2. 可选参数,通常应该放进 options 对象。
38 |
39 | 如果只有一个参数,且我们将来不太可能添加更多可选参数,那么不在选项对象中的可选参数,是能够接受的。
40 |
41 | 3. 'options'参数是唯一的常规'Object'类型。
42 |
43 | 其他参数可以是对象(/容器类型),但它们必须与"普通"对象(`Object`)运行时,区分开来,方法是:
44 |
45 | - 一个有区别的原型(例如`Array`,`Map`,`Date`,`class MyThing`)
46 | - 一个众所周知的符号属性(例如,一个可迭代的`Symbol.iterator`)。
47 |
48 | 这允许 API 以向后兼容的方式扩展,即使选项对象的位置,发生变化也能行。
49 |
50 | ```ts
51 | // 不好的方式: 可选参数,不是options 对象的一部分。 (#2)
52 | export function resolve(
53 | hostname: string,
54 | family?: 'ipv4' | 'ipv6',
55 | timeout?: number
56 | ): IPAddress[] {}
57 |
58 | // 好的方式.
59 | export interface ResolveOptions {
60 | family?: 'ipv4' | 'ipv6';
61 | timeout?: number;
62 | }
63 | export function resolve(
64 | hostname: string,
65 | options: ResolveOptions = {}
66 | ): IPAddress[] {}
67 | ```
68 |
69 | ```ts
70 | export interface Environment {
71 | [key: string]: string;
72 | }
73 |
74 | // 不好的方式: `env` 可能是常规对象,因此无法区分是否为一个选项对象. (#3)
75 | export function runShellWithEnv(cmdline: string, env: Environment): string {}
76 |
77 | // 好的方式.
78 | export interface RunShellOptions {
79 | env: Environment;
80 | }
81 | export function runShellWithEnv(
82 | cmdline: string,
83 | options: RunShellOptions
84 | ): string {}
85 | ```
86 |
87 | ```ts
88 | // 不好的方式: 超过 3 参数 (#1), 过多可选参数 (#2).
89 | export function renameSync(
90 | oldname: string,
91 | newname: string,
92 | replaceExisting?: boolean,
93 | followLinks?: boolean
94 | ) {}
95 |
96 | // 好的方式.
97 | interface RenameOptions {
98 | replaceExisting?: boolean;
99 | followLinks?: boolean;
100 | }
101 | export function renameSync(
102 | oldname: string,
103 | newname: string,
104 | options: RenameOptions = {}
105 | ) {}
106 | ```
107 |
108 | ```ts
109 | // 不好的方式: 过多参数. (#1)
110 | export function pwrite(
111 | fd: number,
112 | buffer: TypedArray,
113 | offset: number,
114 | length: number,
115 | position: number
116 | ) {}
117 |
118 | // 更好.
119 | export interface PWrite {
120 | fd: number;
121 | buffer: TypedArray;
122 | offset: number;
123 | length: number;
124 | position: number;
125 | }
126 | export function pwrite(options: PWrite) {}
127 | ```
128 |
129 | ## TODO 注释(待续讨论)
130 |
131 | TODO 注释应该在括号中,包含问题或作者的 github 用户名。例:
132 |
133 | ```ts
134 | // TODO(ry) Add tests.
135 | // TODO(#123) Support Windows.
136 | ```
137 |
138 | ## 版权标题
139 |
140 | `deno_std`大多数文件,应具有以下版权标题:
141 |
142 | ```ts
143 | // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
144 | ```
145 |
146 | 如果代码来自其他地方,请确保该文件,具有适当的版权标题。我们`deno_std`只允许使用 MIT,BSD 和 Apache 许可代码。
147 |
148 | ## 顶级函数,不应使用箭头语法
149 |
150 | 顶级函数应该使用`function`关键词。箭头语法,应仅限闭包使用。
151 |
152 | 坏
153 |
154 | ```ts
155 | export const foo(): string => {
156 | return "bar";
157 | }
158 | ```
159 |
160 | 好
161 |
162 | ```ts
163 | export function foo(): string {
164 | return 'bar';
165 | }
166 | ```
167 |
168 | ## 不鼓励,使用元编程。包括代理的用法。
169 |
170 | 即使它意味着更多的代码,也要代码具备明确性。
171 |
172 | 在某些情况下,使用这些技术,可能是有意义的,但在绝大多数情况下,没有。
173 |
174 | ## 如果文件名,以下划线开头,请不要链接到它:"\_foo.ts"`
175 |
176 | 有时可能存在内部模块的需要,但其 API 不是稳定或可供链接的情况。在这种情况下,用下划线作为前缀。按照惯例,只有本文件目录中的(文件),才能导入它。
177 |
178 | ## 使用 jsdoc 文档化,导出 API 的情况
179 |
180 | 我们力求完整的文档。理想情况下,每个导出的符号,都应该有文档行。
181 |
182 | 如果可能,请编写 JS 文档。例:
183 |
184 | ```ts
185 | /** foo 做了某 bar. */
186 | export function foo() {
187 | // ...
188 | }
189 | ```
190 |
191 | 重要的是文档,易于给人阅读,但还需要提供额外的样式信息,以确保生成的文档是,更丰富的文本。因此,JSDoc 通常遵循 markdown 标记,来丰富文本。
192 |
193 | 虽然 markdown 支持 HTML 标签,但在 JSDoc 区块中,禁止使用。
194 |
195 | 代码格式字符串,应使用反引号(\`)标记而不是引号。例如:
196 |
197 | ```ts
198 | /** Import something from the `deno` module. */
199 | ```
200 |
201 | 不要文档化函数参数,除非它们的意图不明显(尽管它们,具有不明显意图,但 API 无论如何都应该考虑清楚)。因此`@param`通常,不应该使用。如果`@param`真使用了,那它不应该包括`type`,因为 TypeScript 已经是强类型的。
202 |
203 | ```ts
204 | /**
205 | * 带有不明显意图参数的函数
206 | * @param foo 描述不明显意图的参数
207 | */
208 | ```
209 |
210 | 应尽可能减小垂直间距。因此,单行注释应写为:
211 |
212 | ```ts
213 | /** JSDoc 单行标准写法 */
214 | ```
215 |
216 | 而不是
217 |
218 | ```ts
219 | /**
220 | * JSDoc 差的示例
221 | */
222 | ```
223 |
224 | 代码示例(区块),不应使用三个反引号(\`\`\`)表示。它们应该只用缩进:具体需要在区块之前空一行,并为示例的每一行,添加 6 个额外的空格。这比注释的第一列,多 4 个。例如:
225 |
226 | ```ts
227 | /** A straight forward comment and an example:
228 | *
229 | * import { foo } from "deno";
230 | * foo("bar");
231 | */
232 | ```
233 |
234 | 代码示例,不应包含其他注释。它已经在外注释中。如果它需要进一步的注释,那就不是一个很好的例子。
235 |
236 | ## 每个模块都应该有测试
237 |
238 | 每个模块应该有个测试文件`modulename_test.ts`,作为它的兄弟姐妹。例如模块`foo.ts`应该带着它的兄弟姐妹`foo_test.ts`。
239 |
240 | ## 单元测试应该是明确的
241 |
242 | 为了更好地理解测试,应在整个测试命令中,正确命名函数,比如:
243 |
244 | ```
245 | test myTestFunction ... ok
246 | ```
247 |
248 | 测试示例:
249 |
250 | ```ts
251 | import {assertEquals} from 'https://deno.land/std@v0.3.1/testing/asserts.ts';
252 | import {test} from 'https://deno.land/std@v0.3.1/testing/mod.ts';
253 | import {foo} from './mod.ts';
254 |
255 | test(function myTestFunction() {
256 | assertEquals(foo(), {bar: 'bar'});
257 | });
258 | ```
259 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Deno
6 |
7 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
29 |
30 |
99 |
100 | 安装 #
101 |
102 | 使用 Shell:
103 | curl -fsSL https://deno.land/x/install/install.sh | sh
105 | Or 使用 PowerShell:
106 | iwr https://deno.land/x/install/install.ps1 | iex
108 |
109 | 查看
110 | deno_install
111 | ,了解更多。
112 |
113 |
114 | 例子 #
115 |
116 | 尝试运行一个简单程序:
117 | deno https://deno.land/welcome.ts
118 |
119 | 或更为复杂点的:
120 |
121 | import {serve} from 'https://deno.land/std@v0.3.2/http/server.ts';
122 |
123 | async function main() {
124 | const body = new TextEncoder().encode('Hello World\n');
125 | for await (const req of serve(':8000')) {
126 | req.respond({body});
127 | }
128 | }
129 |
130 | main();
131 |
132 | 深挖... #
133 |
134 |
135 | 手册
136 |
137 |
138 | API 参考
139 |
140 | 风格指南
141 |
142 | 模块 存储库
143 |
144 | Twitter
145 |
146 |
147 | 发布记录
150 |
151 |
152 | 社区聊天室
153 |
154 |
155 | 基准
156 |
157 |
158 |
159 | awesome Deno
160 |
161 |
162 |
170 |
171 |
172 |
173 |
--------------------------------------------------------------------------------
/docs/images/deno_logo_3.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 | Created by potrace 1.15, written by Peter Selinger 2001-2017
9 |
10 |
12 |
87 |
89 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/docs/app.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
2 |
3 | // How much to multiply time values in order to process log graphs properly.
4 | const TimeScaleFactor = 10000;
5 |
6 | export async function getJson(path) {
7 | return (await fetch(path)).json();
8 | }
9 |
10 | function getBenchmarkVarieties(data, benchmarkName) {
11 | // Look at last sha hash.
12 | const last = data[data.length - 1];
13 | return Object.keys(last[benchmarkName]);
14 | }
15 |
16 | export function createColumns(data, benchmarkName) {
17 | const varieties = getBenchmarkVarieties(data, benchmarkName);
18 | return varieties.map(variety => [
19 | variety,
20 | ...data.map(d => {
21 | if (d[benchmarkName] != null) {
22 | if (d[benchmarkName][variety] != null) {
23 | const v = d[benchmarkName][variety];
24 | if (benchmarkName == "benchmark") {
25 | const meanValue = v ? v.mean : 0;
26 | return meanValue || null;
27 | } else {
28 | return v;
29 | }
30 | }
31 | }
32 | return null;
33 | })
34 | ]);
35 | }
36 |
37 | export function createExecTimeColumns(data) {
38 | return createColumns(data, "benchmark");
39 | }
40 |
41 | export function createThroughputColumns(data) {
42 | return createColumns(data, "throughput");
43 | }
44 |
45 | export function createReqPerSecColumns(data) {
46 | return createColumns(data, "req_per_sec");
47 | }
48 |
49 | export function createMaxLatencyColumns(data) {
50 | return createColumns(data, "max_latency");
51 | }
52 |
53 | export function createBinarySizeColumns(data) {
54 | const propName = "binary_size";
55 | const binarySizeNames = Object.keys(data[data.length - 1][propName]);
56 | return binarySizeNames.map(name => [
57 | name,
58 | ...data.map(d => {
59 | const binarySizeData = d["binary_size"];
60 | switch (typeof binarySizeData) {
61 | case "number": // legacy implementation
62 | return name === "deno" ? binarySizeData : 0;
63 | default:
64 | if (!binarySizeData) {
65 | return null;
66 | }
67 | return binarySizeData[name] || null;
68 | }
69 | })
70 | ]);
71 | }
72 |
73 | export function createThreadCountColumns(data) {
74 | const propName = "thread_count";
75 | const threadCountNames = Object.keys(data[data.length - 1][propName]);
76 | return threadCountNames.map(name => [
77 | name,
78 | ...data.map(d => {
79 | const threadCountData = d[propName];
80 | if (!threadCountData) {
81 | return null;
82 | }
83 | return threadCountData[name] || null;
84 | })
85 | ]);
86 | }
87 |
88 | export function createSyscallCountColumns(data) {
89 | const propName = "syscall_count";
90 | const syscallCountNames = Object.keys(data[data.length - 1][propName]);
91 | return syscallCountNames.map(name => [
92 | name,
93 | ...data.map(d => {
94 | const syscallCountData = d[propName];
95 | if (!syscallCountData) {
96 | return null;
97 | }
98 | return syscallCountData[name] || null;
99 | })
100 | ]);
101 | }
102 |
103 | export function createSha1List(data) {
104 | return data.map(d => d.sha1);
105 | }
106 |
107 | export function formatMB(bytes) {
108 | return (bytes / (1024 * 1024)).toFixed(2);
109 | }
110 |
111 | export function formatReqSec(reqPerSec) {
112 | return reqPerSec / 1000;
113 | }
114 |
115 | /**
116 | * @param {string} id The id of dom element
117 | * @param {string[]} categories categories for x-axis values
118 | * @param {any[][]} columns The columns data
119 | * @param {function} onclick action on clicking nodes of chart
120 | * @param {string} yLabel label of y axis
121 | * @param {function} yTickFormat formatter of y axis ticks
122 | */
123 | function generate(
124 | id,
125 | categories,
126 | columns,
127 | onclick,
128 | yLabel = "",
129 | yTickFormat = null
130 | ) {
131 | const yAxis = {
132 | padding: { bottom: 0 },
133 | min: 0,
134 | label: yLabel
135 | };
136 | if (yTickFormat) {
137 | yAxis.tick = {
138 | format: yTickFormat
139 | };
140 | if (yTickFormat == logScale) {
141 | delete yAxis.min;
142 | for (let col of columns) {
143 | for (let i = 1; i < col.length; i++) {
144 | if (col[i] == null) {
145 | continue;
146 | }
147 | col[i] = Math.log10(col[i] * TimeScaleFactor);
148 | }
149 | }
150 | }
151 | }
152 |
153 | // @ts-ignore
154 | c3.generate({
155 | bindto: id,
156 | data: {
157 | columns,
158 | onclick
159 | },
160 | axis: {
161 | x: {
162 | type: "category",
163 | show: false,
164 | categories
165 | },
166 | y: yAxis
167 | }
168 | });
169 | }
170 |
171 | function logScale(t) {
172 | return (Math.pow(10, t) / TimeScaleFactor).toFixed(4);
173 | }
174 |
175 | function formatSecsAsMins(t) {
176 | // TODO use d3.round()
177 | const a = t % 60;
178 | const min = Math.floor(t / 60);
179 | return a < 30 ? min : min + 1;
180 | }
181 |
182 | /**
183 | * @param dataUrl The url of benchramk data json.
184 | */
185 | export function drawCharts(dataUrl) {
186 | // TODO Using window["location"]["hostname"] instead of
187 | // window.location.hostname because when deno runs app_test.js it gets a type
188 | // error here, not knowing about window.location. Ideally Deno would skip
189 | // type check entirely on JS files.
190 | if (window["location"]["hostname"] != "deno.github.io") {
191 | dataUrl = "https://denoland.github.io/deno/" + dataUrl;
192 | }
193 | drawChartsFromBenchmarkData(dataUrl);
194 | }
195 |
196 | /**
197 | * Draws the charts from the benchmark data stored in gh-pages branch.
198 | */
199 | export async function drawChartsFromBenchmarkData(dataUrl) {
200 | const data = await getJson(dataUrl);
201 |
202 | const execTimeColumns = createExecTimeColumns(data);
203 | const throughputColumns = createThroughputColumns(data);
204 | const reqPerSecColumns = createReqPerSecColumns(data);
205 | const maxLatencyColumns = createMaxLatencyColumns(data);
206 | const binarySizeColumns = createBinarySizeColumns(data);
207 | const threadCountColumns = createThreadCountColumns(data);
208 | const syscallCountColumns = createSyscallCountColumns(data);
209 | const sha1List = createSha1List(data);
210 | const sha1ShortList = sha1List.map(sha1 => sha1.substring(0, 6));
211 |
212 | const viewCommitOnClick = _sha1List => d => {
213 | // @ts-ignore
214 | window.open(
215 | `https://github.com/denoland/deno/commit/${_sha1List[d["index"]]}`
216 | );
217 | };
218 |
219 | function gen(id, columns, yLabel = "", yTickFormat = null) {
220 | generate(
221 | id,
222 | sha1ShortList,
223 | columns,
224 | viewCommitOnClick(sha1List),
225 | yLabel,
226 | yTickFormat
227 | );
228 | }
229 |
230 | gen("#exec-time-chart", execTimeColumns, "seconds", logScale);
231 | gen("#throughput-chart", throughputColumns, "seconds", logScale);
232 | gen("#req-per-sec-chart", reqPerSecColumns, "1000 req/sec", formatReqSec);
233 | gen("#max-latency-chart", maxLatencyColumns, "milliseconds", logScale);
234 | gen("#binary-size-chart", binarySizeColumns, "megabytes", formatMB);
235 | gen("#thread-count-chart", threadCountColumns, "threads");
236 | gen("#syscall-count-chart", syscallCountColumns, "syscalls");
237 | }
238 |
--------------------------------------------------------------------------------
/style_guide.zh.md:
--------------------------------------------------------------------------------
1 | # Deno 风格指南
2 |
3 |
4 |
5 |
6 |
7 | - [使用 TypeScript](#%E4%BD%BF%E7%94%A8-typescript)
8 | - [使用术语"模块(module)",而不是"库(library)"或"包(package)"](#%E4%BD%BF%E7%94%A8%E6%9C%AF%E8%AF%AD%E6%A8%A1%E5%9D%97module%E8%80%8C%E4%B8%8D%E6%98%AF%E5%BA%93library%E6%88%96%E5%8C%85package)
9 | - [不要使用文件名`"index.ts"或"index.js"`](#%E4%B8%8D%E8%A6%81%E4%BD%BF%E7%94%A8%E6%96%87%E4%BB%B6%E5%90%8Dindexts%E6%88%96indexjs)
10 | - [在"deno-std"中,不依赖外部代码](#%E5%9C%A8deno-std%E4%B8%AD%E4%B8%8D%E4%BE%9D%E8%B5%96%E5%A4%96%E9%83%A8%E4%BB%A3%E7%A0%81)
11 | - [在"deno-std"中,最小化依赖关系;不要进行循环导入。](#%E5%9C%A8deno-std%E4%B8%AD%E6%9C%80%E5%B0%8F%E5%8C%96%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB%E4%B8%8D%E8%A6%81%E8%BF%9B%E8%A1%8C%E5%BE%AA%E7%8E%AF%E5%AF%BC%E5%85%A5)
12 | - [为了保持一致性,文件名请使用下划线,而不是短划线。](#%E4%B8%BA%E4%BA%86%E4%BF%9D%E6%8C%81%E4%B8%80%E8%87%B4%E6%80%A7%E6%96%87%E4%BB%B6%E5%90%8D%E8%AF%B7%E4%BD%BF%E7%94%A8%E4%B8%8B%E5%88%92%E7%BA%BF%E8%80%8C%E4%B8%8D%E6%98%AF%E7%9F%AD%E5%88%92%E7%BA%BF)
13 | - [使用 prettier 格式化代码。](#%E4%BD%BF%E7%94%A8-prettier-%E6%A0%BC%E5%BC%8F%E5%8C%96%E4%BB%A3%E7%A0%81)
14 | - [导出的函数:最多 2 个参数,将其余的参数放入 options 对象。](#%E5%AF%BC%E5%87%BA%E7%9A%84%E5%87%BD%E6%95%B0%E6%9C%80%E5%A4%9A-2-%E4%B8%AA%E5%8F%82%E6%95%B0%E5%B0%86%E5%85%B6%E4%BD%99%E7%9A%84%E5%8F%82%E6%95%B0%E6%94%BE%E5%85%A5-options-%E5%AF%B9%E8%B1%A1)
15 | - [TODO 注释(待续讨论)](#todo-%E6%B3%A8%E9%87%8A%E5%BE%85%E7%BB%AD%E8%AE%A8%E8%AE%BA)
16 | - [版权标题](#%E7%89%88%E6%9D%83%E6%A0%87%E9%A2%98)
17 | - [顶级函数,不应使用箭头语法](#%E9%A1%B6%E7%BA%A7%E5%87%BD%E6%95%B0%E4%B8%8D%E5%BA%94%E4%BD%BF%E7%94%A8%E7%AE%AD%E5%A4%B4%E8%AF%AD%E6%B3%95)
18 | - [不鼓励,使用元编程。包括代理的用法。](#%E4%B8%8D%E9%BC%93%E5%8A%B1%E4%BD%BF%E7%94%A8%E5%85%83%E7%BC%96%E7%A8%8B%E5%8C%85%E6%8B%AC%E4%BB%A3%E7%90%86%E7%9A%84%E7%94%A8%E6%B3%95)
19 | - [如果文件名,以下划线开头,请不要链接到它:"_foo.ts"`](#%E5%A6%82%E6%9E%9C%E6%96%87%E4%BB%B6%E5%90%8D%E4%BB%A5%E4%B8%8B%E5%88%92%E7%BA%BF%E5%BC%80%E5%A4%B4%E8%AF%B7%E4%B8%8D%E8%A6%81%E9%93%BE%E6%8E%A5%E5%88%B0%E5%AE%83_foots)
20 | - [使用 jsdoc 文档化,导出 API 的情况](#%E4%BD%BF%E7%94%A8-jsdoc-%E6%96%87%E6%A1%A3%E5%8C%96%E5%AF%BC%E5%87%BA-api-%E7%9A%84%E6%83%85%E5%86%B5)
21 | - [每个模块都应该有测试](#%E6%AF%8F%E4%B8%AA%E6%A8%A1%E5%9D%97%E9%83%BD%E5%BA%94%E8%AF%A5%E6%9C%89%E6%B5%8B%E8%AF%95)
22 | - [单元测试应该是明确的](#%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E5%BA%94%E8%AF%A5%E6%98%AF%E6%98%8E%E7%A1%AE%E7%9A%84)
23 |
24 |
25 |
26 | ## 使用 TypeScript
27 |
28 | ## 使用术语"模块(module)",而不是"库(library)"或"包(package)"
29 |
30 | 为了明确性和一致性,请避免使用术语"库"和"包"。而是使用"module"来指明单个 JS 或 TS 文件,当然还包括 TS / JS 代码的目录。
31 |
32 | ## 不要使用文件名`"index.ts"或"index.js"`
33 |
34 | Deno 不会对"index.js"或"index.ts"特殊处理。这些文件名的使用,会对当不用它们时,却可以被排除在模块描述之外,感到困惑。
35 |
36 | 如果代码目录需要默认入口点,请使用文件名`mod.ts`。文件名`mod.ts`遵循 Rust 的惯例,比`index.ts`简短,并且没有任何先入为主,关于其应该如何运作的观念。
37 |
38 | ## 在"deno-std"中,不依赖外部代码
39 |
40 | `deno_std`旨在成为所有 Deno 程序可以依赖的地基功能。我们希望向用户保证此代码,不包含可能未经审核的第三方代码。
41 |
42 | ## 在"deno-std"中,最小化依赖关系;不要进行循环导入。
43 |
44 | 虽然`deno_std`是一个独立的代码库,我们仍然必须小心保持,内部依赖关系的简单和易于管理。特别要注意,不要产生(死)循环导入。
45 |
46 | ## 为了保持一致性,文件名请使用下划线,而不是短划线。
47 |
48 | 示例:不是`file-server.ts`,使用`file_server.ts`。
49 |
50 | ## 使用 prettier 格式化代码。
51 |
52 | 更具体地说,代码行应在 80 列内,使用 2 空格缩进,并使用驼峰式。使用`//format.ts`调用 prettier。
53 |
54 | ## 导出的函数:最多 2 个参数,将其余的参数放入 options 对象。
55 |
56 | 设计函数接口时,请遵守以下规则。
57 |
58 | 1. 作为公有 API 一部分的函数需要 0-2 个必需参数,如果需要的话,加上一个选项(options)对象(总共最多 3 个)。
59 |
60 | 2. 可选参数,通常应该放进 options 对象。
61 |
62 | 如果只有一个参数,且我们将来不太可能添加更多可选参数,那么不在选项对象中的可选参数,是能够接受的。
63 |
64 | 3. 'options'参数是唯一的常规'Object'类型。
65 |
66 | 其他参数可以是对象(/容器类型),但它们必须与"普通"对象(`Object`)运行时,区分开来,方法是:
67 |
68 | - 一个有区别的原型(例如`Array`,`Map`,`Date`,`class MyThing`)
69 | - 一个众所周知的符号属性(例如,一个可迭代的`Symbol.iterator`)。
70 |
71 | 这允许 API 以向后兼容的方式扩展,即使选项对象的位置,发生变化也能行。
72 |
73 | ```ts
74 | // 不好的方式: 可选参数,不是options 对象的一部分。 (#2)
75 | export function resolve(
76 | hostname: string,
77 | family?: 'ipv4' | 'ipv6',
78 | timeout?: number
79 | ): IPAddress[] {}
80 |
81 | // 好的方式.
82 | export interface ResolveOptions {
83 | family?: 'ipv4' | 'ipv6';
84 | timeout?: number;
85 | }
86 | export function resolve(
87 | hostname: string,
88 | options: ResolveOptions = {}
89 | ): IPAddress[] {}
90 | ```
91 |
92 | ```ts
93 | export interface Environment {
94 | [key: string]: string;
95 | }
96 |
97 | // 不好的方式: `env` 可能是常规对象,因此无法区分是否为一个选项对象. (#3)
98 | export function runShellWithEnv(cmdline: string, env: Environment): string {}
99 |
100 | // 好的方式.
101 | export interface RunShellOptions {
102 | env: Environment;
103 | }
104 | export function runShellWithEnv(
105 | cmdline: string,
106 | options: RunShellOptions
107 | ): string {}
108 | ```
109 |
110 | ```ts
111 | // 不好的方式: 超过 3 参数 (#1), 过多可选参数 (#2).
112 | export function renameSync(
113 | oldname: string,
114 | newname: string,
115 | replaceExisting?: boolean,
116 | followLinks?: boolean
117 | ) {}
118 |
119 | // 好的方式.
120 | interface RenameOptions {
121 | replaceExisting?: boolean;
122 | followLinks?: boolean;
123 | }
124 | export function renameSync(
125 | oldname: string,
126 | newname: string,
127 | options: RenameOptions = {}
128 | ) {}
129 | ```
130 |
131 | ```ts
132 | // 不好的方式: 过多参数. (#1)
133 | export function pwrite(
134 | fd: number,
135 | buffer: TypedArray,
136 | offset: number,
137 | length: number,
138 | position: number
139 | ) {}
140 |
141 | // 更好.
142 | export interface PWrite {
143 | fd: number;
144 | buffer: TypedArray;
145 | offset: number;
146 | length: number;
147 | position: number;
148 | }
149 | export function pwrite(options: PWrite) {}
150 | ```
151 |
152 | ## TODO 注释(待续讨论)
153 |
154 | TODO 注释应该在括号中,包含问题或作者的 github 用户名。例:
155 |
156 | ```ts
157 | // TODO(ry) Add tests.
158 | // TODO(#123) Support Windows.
159 | ```
160 |
161 | ## 版权标题
162 |
163 | `deno_std`大多数文件,应具有以下版权标题:
164 |
165 | ```ts
166 | // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
167 | ```
168 |
169 | 如果代码来自其他地方,请确保该文件,具有适当的版权标题。我们`deno_std`只允许使用 MIT,BSD 和 Apache 许可代码。
170 |
171 | ## 顶级函数,不应使用箭头语法
172 |
173 | 顶级函数应该使用`function`关键词。箭头语法,应仅限闭包使用。
174 |
175 | 坏
176 |
177 | ```ts
178 | export const foo(): string => {
179 | return "bar";
180 | }
181 | ```
182 |
183 | 好
184 |
185 | ```ts
186 | export function foo(): string {
187 | return 'bar';
188 | }
189 | ```
190 |
191 | ## 不鼓励,使用元编程。包括代理的用法。
192 |
193 | 即使它意味着更多的代码,也要代码具备明确性。
194 |
195 | 在某些情况下,使用这些技术,可能是有意义的,但在绝大多数情况下,没有。
196 |
197 | ## 如果文件名,以下划线开头,请不要链接到它:"_foo.ts"`
198 |
199 | 有时可能存在内部模块的需要,但其 API 不是稳定或可供链接的情况。在这种情况下,用下划线作为前缀。按照惯例,只有本文件目录中的(文件),才能导入它。
200 |
201 | ## 使用 jsdoc 文档化,导出 API 的情况
202 |
203 | 我们力求完整的文档。理想情况下,每个导出的符号,都应该有文档行。
204 |
205 | 如果可能,请编写 JS 文档。例:
206 |
207 | ```ts
208 | /** foo 做了某 bar. */
209 | export function foo() {
210 | // ...
211 | }
212 | ```
213 |
214 | 重要的是文档,易于给人阅读,但还需要提供额外的样式信息,以确保生成的文档是,更丰富的文本。因此,JSDoc 通常遵循 markdown 标记,来丰富文本。
215 |
216 | 虽然 markdown 支持 HTML 标签,但在 JSDoc 区块中,禁止使用。
217 |
218 | 代码格式字符串,应使用反引号(\`)标记而不是引号。例如:
219 |
220 | ```ts
221 | /** Import something from the `deno` module. */
222 | ```
223 |
224 | 不要文档化函数参数,除非它们的意图不明显(尽管它们,具有不明显意图,但 API 无论如何都应该考虑清楚)。因此`@param`通常,不应该使用。如果`@param`真使用了,那它不应该包括`type`,因为 TypeScript 已经是强类型的。
225 |
226 | ```ts
227 | /**
228 | * 带有不明显意图参数的函数
229 | * @param foo 描述不明显意图的参数
230 | */
231 | ```
232 |
233 | 应尽可能减小垂直间距。因此,单行注释应写为:
234 |
235 | ```ts
236 | /** JSDoc 单行标准写法 */
237 | ```
238 |
239 | 而不是
240 |
241 | ```ts
242 | /**
243 | * JSDoc 差的示例
244 | */
245 | ```
246 |
247 | 代码示例(区块),不应使用三个反引号(\`\`\`)表示。它们应该只用缩进:具体需要在区块之前空一行,并为示例的每一行,添加 6 个额外的空格。这比注释的第一列,多 4 个。例如:
248 |
249 | ```ts
250 | /** A straight forward comment and an example:
251 | *
252 | * import { foo } from "deno";
253 | * foo("bar");
254 | */
255 | ```
256 |
257 | 代码示例,不应包含其他注释。它已经在外注释中。如果它需要进一步的注释,那就不是一个很好的例子。
258 |
259 | ## 每个模块都应该有测试
260 |
261 | 每个模块应该有个测试文件`modulename_test.ts`,作为它的兄弟姐妹。例如模块`foo.ts`应该带着它的兄弟姐妹`foo_test.ts`。
262 |
263 | ## 单元测试应该是明确的
264 |
265 | 为了更好地理解测试,应在整个测试命令中,正确命名函数,比如:
266 |
267 | ```
268 | test myTestFunction ... ok
269 | ```
270 |
271 | 测试示例:
272 |
273 | ```ts
274 | import {assertEquals} from 'https://deno.land/std@v0.3.1/testing/asserts.ts';
275 | import {test} from 'https://deno.land/std@v0.3.1/testing/mod.ts';
276 | import {foo} from './mod.ts';
277 |
278 | test(function myTestFunction() {
279 | assertEquals(foo(), {bar: 'bar'});
280 | });
281 | ```
282 |
--------------------------------------------------------------------------------
/style_guide.md:
--------------------------------------------------------------------------------
1 | # Deno Style Guide
2 |
3 | [toc]
4 |
5 | ## Use TypeScript
6 |
7 | ## Use the term "module" instead of "library" or "package"
8 |
9 | For clarity and consistency avoid the terms "library" and "package". Instead use
10 | "module" to refer to a single JS or TS file and also to refer to a directory of
11 | TS/JS code.
12 |
13 | ## Do not use the filename `index.ts` nor `index.js`
14 |
15 | Deno does not treat "index.js" or "index.ts" in a special way. By using these
16 | filenames, it suggests that they can be left out of the module specifier when
17 | they cannot. This is confusing.
18 |
19 | If a directory of code needs a default entry point, use the filename `mod.ts`.
20 | The filename `mod.ts` follows Rust’s convention, is shorter than `index.ts`, and
21 | doesn’t come with any preconceived notions about how it might work.
22 |
23 | ## Within `deno_std`, do not depend on external code
24 |
25 | `deno_std` is intended to be baseline functionality that all Deno programs can
26 | rely on. We want to guarantee to users that this code does not include
27 | potentially unreviewed third party code.
28 |
29 | ## Within `deno_std`, minimize dependencies; do not make circular imports.
30 |
31 | Although `deno_std` is a standalone codebase, we must still be careful to keep
32 | the internal dependencies simple and manageable. In particular, be careful to
33 | not to introduce circular imports.
34 |
35 | ## For consistency, use underscores, not dashes in filenames.
36 |
37 | Example: Instead of `file-server.ts` use `file_server.ts`.
38 |
39 | ## Format code according using prettier.
40 |
41 | More specifically, code should be wrapped at 80 columns and use 2-space
42 | indentation and use camel-case. Use `//format.ts` to invoke prettier.
43 |
44 | ## Exported functions: max 2 args, put the rest into an options object.
45 |
46 | When designing function interfaces, stick to the following rules.
47 |
48 | 1. A function that is part of the public API takes 0-2 required arguments, plus
49 | (if necessary) an options object (so max 3 total).
50 |
51 | 2. Optional parameters should generally go into the options object.
52 |
53 | An optional parameter that's not in an options object might be acceptable if
54 | there is only one, and it seems inconceivable that we would add more optional
55 | parameters in the future.
56 |
57 | 3. The 'options' argument is the only argument that is a regular 'Object'.
58 |
59 | Other arguments can be objects, but they must be distinguishable from a
60 | 'plain' Object runtime, by having either:
61 |
62 | - a distinguishing prototype (e.g. `Array`, `Map`, `Date`, `class MyThing`)
63 | - a well-known symbol property (e.g. an iterable with `Symbol.iterator`).
64 |
65 | This allows the API to evolve in a backwards compatible way, even when the
66 | position of the options object changes.
67 |
68 | ```ts
69 | // BAD: optional parameters not part of options object. (#2)
70 | export function resolve(
71 | hostname: string,
72 | family?: "ipv4" | "ipv6",
73 | timeout?: number
74 | ): IPAddress[] {}
75 |
76 | // GOOD.
77 | export interface ResolveOptions {
78 | family?: "ipv4" | "ipv6";
79 | timeout?: number;
80 | }
81 | export function resolve(
82 | hostname: string,
83 | options: ResolveOptions = {}
84 | ): IPAddress[] {}
85 | ```
86 |
87 | ```ts
88 | export interface Environment {
89 | [key: string]: string;
90 | }
91 |
92 | // BAD: `env` could be a regular Object and is therefore indistinguishable
93 | // from an options object. (#3)
94 | export function runShellWithEnv(cmdline: string, env: Environment): string {}
95 |
96 | // GOOD.
97 | export interface RunShellOptions {
98 | env: Environment;
99 | }
100 | export function runShellWithEnv(
101 | cmdline: string,
102 | options: RunShellOptions
103 | ): string {}
104 | ```
105 |
106 | ```ts
107 | // BAD: more than 3 arguments (#1), multiple optional parameters (#2).
108 | export function renameSync(
109 | oldname: string,
110 | newname: string,
111 | replaceExisting?: boolean,
112 | followLinks?: boolean
113 | ) {}
114 |
115 | // GOOD.
116 | interface RenameOptions {
117 | replaceExisting?: boolean;
118 | followLinks?: boolean;
119 | }
120 | export function renameSync(
121 | oldname: string,
122 | newname: string,
123 | options: RenameOptions = {}
124 | ) {}
125 | ```
126 |
127 | ```ts
128 | // BAD: too many arguments. (#1)
129 | export function pwrite(
130 | fd: number,
131 | buffer: TypedArray,
132 | offset: number,
133 | length: number,
134 | position: number
135 | ) {}
136 |
137 | // BETTER.
138 | export interface PWrite {
139 | fd: number;
140 | buffer: TypedArray;
141 | offset: number;
142 | length: number;
143 | position: number;
144 | }
145 | export function pwrite(options: PWrite) {}
146 | ```
147 |
148 | ## TODO Comments
149 |
150 | TODO comments should include an issue or the author's github username in
151 | parentheses. Example:
152 |
153 | ```ts
154 | // TODO(ry) Add tests.
155 | // TODO(#123) Support Windows.
156 | ```
157 |
158 | ## Copyright headers
159 |
160 | Most files in `deno_std` should have the following copyright header:
161 |
162 | ```ts
163 | // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
164 | ```
165 |
166 | If the code originates elsewhere, ensure that the file has the proper copyright
167 | headers. We only allow MIT, BSD, and Apache licensed code in `deno_std`.
168 |
169 | ## Top level functions should not use arrow syntax
170 |
171 | Top level functions should use the `function` keyword. Arrow syntax should be
172 | limited to closures.
173 |
174 | Bad
175 |
176 | ```ts
177 | export const foo(): string => {
178 | return "bar";
179 | }
180 | ```
181 |
182 | Good
183 |
184 | ```ts
185 | export function foo(): string {
186 | return "bar";
187 | }
188 | ```
189 |
190 | ## Meta-programming is discouraged. Including the use of Proxy.
191 |
192 | Be explicit even when it means more code.
193 |
194 | There are some situations where it may make sense to use such techniques, but in
195 | the vast majority of cases it does not.
196 |
197 | ## If a filename starts with underscore, do not link to it: `_foo.ts`
198 |
199 | Sometimes there maybe situations where an internal module is necessary but its
200 | API is not meant to be stable or linked to. In this case prefix it with an
201 | underscore. By convention, only files in its own directory should import it.
202 |
203 | ## Use JSDoc to document exported machinery
204 |
205 | We strive for complete documentation. Every exported symbol ideally should have
206 | a documentation line.
207 |
208 | If possible, use a single line for the JS Doc. Example:
209 |
210 | ```ts
211 | /** foo does bar. */
212 | export function foo() {
213 | // ...
214 | }
215 | ```
216 |
217 | It is important that documentation is easily human readable, but there is also a
218 | need to provide additional styling information to ensure generated documentation
219 | is more rich text. Therefore JSDoc should generally follow markdown markup to
220 | enrich the text.
221 |
222 | While markdown supports HTML tags, it is forbidden in JSDoc blocks.
223 |
224 | Code string literals should be braced with the back-tick (\`) instead of quotes.
225 | For example:
226 |
227 | ```ts
228 | /** Import something from the `deno` module. */
229 | ```
230 |
231 | Do not document function arguments unless they are non-obvious of their intent
232 | (though if they are non-obvious intent, the API should be considered anyways).
233 | Therefore `@param` should generally not be used. If `@param` is used, it should
234 | not include the `type` as TypeScript is already strongly typed.
235 |
236 | ```ts
237 | /**
238 | * Function with non obvious param
239 | * @param foo Description of non obvious parameter
240 | */
241 | ```
242 |
243 | Vertical spacing should be minimized whenever possible. Therefore single line
244 | comments should be written as:
245 |
246 | ```ts
247 | /** This is a good single line JSDoc */
248 | ```
249 |
250 | And not
251 |
252 | ```ts
253 | /**
254 | * This is a bad single line JSDoc
255 | */
256 | ```
257 |
258 | Code examples should not utilise the triple-back tick (\`\`\`) notation or tags.
259 | They should just be marked by indentation, which requires a break before the
260 | block and 6 additional spaces for each line of the example. This is 4 more than
261 | the first column of the comment. For example:
262 |
263 | ```ts
264 | /** A straight forward comment and an example:
265 | *
266 | * import { foo } from "deno";
267 | * foo("bar");
268 | */
269 | ```
270 |
271 | Code examples should not contain additional comments. It is already inside a
272 | comment. If it needs further comments is not a good example.
273 |
274 | ## Each module should come with tests
275 |
276 | Each module should come with its test as a sibling with the name
277 | `modulename_test.ts`. For example the module `foo.ts` should come with its
278 | sibling `foo_test.ts`.
279 |
280 | ## Unit Tests should be explicit
281 |
282 | For a better understanding of the tests, function should be correctly named as
283 | its prompted throughout the test command. Like:
284 |
285 | ```
286 | test myTestFunction ... ok
287 | ```
288 |
289 | Example of test:
290 |
291 | ```ts
292 | import { assertEquals } from "https://deno.land/std@v0.3.1/testing/asserts.ts";
293 | import { test } from "https://deno.land/std@v0.3.1/testing/mod.ts";
294 | import { foo } from "./mod.ts";
295 |
296 | test(function myTestFunction() {
297 | assertEquals(foo(), { bar: "bar" });
298 | });
299 | ```
300 |
--------------------------------------------------------------------------------
/docs/style_guide.md:
--------------------------------------------------------------------------------
1 | # Deno Style Guide
2 |
3 | [toc]
4 |
5 | ## Use TypeScript
6 |
7 | ## Use the term "module" instead of "library" or "package"
8 |
9 | For clarity and consistency avoid the terms "library" and "package". Instead use
10 | "module" to refer to a single JS or TS file and also to refer to a directory of
11 | TS/JS code.
12 |
13 | ## Do not use the filename `index.ts` nor `index.js`
14 |
15 | Deno does not treat "index.js" or "index.ts" in a special way. By using these
16 | filenames, it suggests that they can be left out of the module specifier when
17 | they cannot. This is confusing.
18 |
19 | If a directory of code needs a default entry point, use the filename `mod.ts`.
20 | The filename `mod.ts` follows Rust’s convention, is shorter than `index.ts`, and
21 | doesn’t come with any preconceived notions about how it might work.
22 |
23 | ## Within `deno_std`, do not depend on external code
24 |
25 | `deno_std` is intended to be baseline functionality that all Deno programs can
26 | rely on. We want to guarantee to users that this code does not include
27 | potentially unreviewed third party code.
28 |
29 | ## Within `deno_std`, minimize dependencies; do not make circular imports.
30 |
31 | Although `deno_std` is a standalone codebase, we must still be careful to keep
32 | the internal dependencies simple and manageable. In particular, be careful to
33 | not to introduce circular imports.
34 |
35 | ## For consistency, use underscores, not dashes in filenames.
36 |
37 | Example: Instead of `file-server.ts` use `file_server.ts`.
38 |
39 | ## Format code according using prettier.
40 |
41 | More specifically, code should be wrapped at 80 columns and use 2-space
42 | indentation and use camel-case. Use `//format.ts` to invoke prettier.
43 |
44 | ## Exported functions: max 2 args, put the rest into an options object.
45 |
46 | When designing function interfaces, stick to the following rules.
47 |
48 | 1. A function that is part of the public API takes 0-2 required arguments, plus
49 | (if necessary) an options object (so max 3 total).
50 |
51 | 2. Optional parameters should generally go into the options object.
52 |
53 | An optional parameter that's not in an options object might be acceptable if
54 | there is only one, and it seems inconceivable that we would add more optional
55 | parameters in the future.
56 |
57 | 3. The 'options' argument is the only argument that is a regular 'Object'.
58 |
59 | Other arguments can be objects, but they must be distinguishable from a
60 | 'plain' Object runtime, by having either:
61 |
62 | - a distinguishing prototype (e.g. `Array`, `Map`, `Date`, `class MyThing`)
63 | - a well-known symbol property (e.g. an iterable with `Symbol.iterator`).
64 |
65 | This allows the API to evolve in a backwards compatible way, even when the
66 | position of the options object changes.
67 |
68 | ```ts
69 | // BAD: optional parameters not part of options object. (#2)
70 | export function resolve(
71 | hostname: string,
72 | family?: "ipv4" | "ipv6",
73 | timeout?: number
74 | ): IPAddress[] {}
75 |
76 | // GOOD.
77 | export interface ResolveOptions {
78 | family?: "ipv4" | "ipv6";
79 | timeout?: number;
80 | }
81 | export function resolve(
82 | hostname: string,
83 | options: ResolveOptions = {}
84 | ): IPAddress[] {}
85 | ```
86 |
87 | ```ts
88 | export interface Environment {
89 | [key: string]: string;
90 | }
91 |
92 | // BAD: `env` could be a regular Object and is therefore indistinguishable
93 | // from an options object. (#3)
94 | export function runShellWithEnv(cmdline: string, env: Environment): string {}
95 |
96 | // GOOD.
97 | export interface RunShellOptions {
98 | env: Environment;
99 | }
100 | export function runShellWithEnv(
101 | cmdline: string,
102 | options: RunShellOptions
103 | ): string {}
104 | ```
105 |
106 | ```ts
107 | // BAD: more than 3 arguments (#1), multiple optional parameters (#2).
108 | export function renameSync(
109 | oldname: string,
110 | newname: string,
111 | replaceExisting?: boolean,
112 | followLinks?: boolean
113 | ) {}
114 |
115 | // GOOD.
116 | interface RenameOptions {
117 | replaceExisting?: boolean;
118 | followLinks?: boolean;
119 | }
120 | export function renameSync(
121 | oldname: string,
122 | newname: string,
123 | options: RenameOptions = {}
124 | ) {}
125 | ```
126 |
127 | ```ts
128 | // BAD: too many arguments. (#1)
129 | export function pwrite(
130 | fd: number,
131 | buffer: TypedArray,
132 | offset: number,
133 | length: number,
134 | position: number
135 | ) {}
136 |
137 | // BETTER.
138 | export interface PWrite {
139 | fd: number;
140 | buffer: TypedArray;
141 | offset: number;
142 | length: number;
143 | position: number;
144 | }
145 | export function pwrite(options: PWrite) {}
146 | ```
147 |
148 | ## TODO Comments
149 |
150 | TODO comments should include an issue or the author's github username in
151 | parentheses. Example:
152 |
153 | ```ts
154 | // TODO(ry) Add tests.
155 | // TODO(#123) Support Windows.
156 | ```
157 |
158 | ## Copyright headers
159 |
160 | Most files in `deno_std` should have the following copyright header:
161 |
162 | ```ts
163 | // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
164 | ```
165 |
166 | If the code originates elsewhere, ensure that the file has the proper copyright
167 | headers. We only allow MIT, BSD, and Apache licensed code in `deno_std`.
168 |
169 | ## Top level functions should not use arrow syntax
170 |
171 | Top level functions should use the `function` keyword. Arrow syntax should be
172 | limited to closures.
173 |
174 | Bad
175 |
176 | ```ts
177 | export const foo(): string => {
178 | return "bar";
179 | }
180 | ```
181 |
182 | Good
183 |
184 | ```ts
185 | export function foo(): string {
186 | return "bar";
187 | }
188 | ```
189 |
190 | ## Meta-programming is discouraged. Including the use of Proxy.
191 |
192 | Be explicit even when it means more code.
193 |
194 | There are some situations where it may make sense to use such techniques, but in
195 | the vast majority of cases it does not.
196 |
197 | ## If a filename starts with underscore, do not link to it: `_foo.ts`
198 |
199 | Sometimes there maybe situations where an internal module is necessary but its
200 | API is not meant to be stable or linked to. In this case prefix it with an
201 | underscore. By convention, only files in its own directory should import it.
202 |
203 | ## Use JSDoc to document exported machinery
204 |
205 | We strive for complete documentation. Every exported symbol ideally should have
206 | a documentation line.
207 |
208 | If possible, use a single line for the JS Doc. Example:
209 |
210 | ```ts
211 | /** foo does bar. */
212 | export function foo() {
213 | // ...
214 | }
215 | ```
216 |
217 | It is important that documentation is easily human readable, but there is also a
218 | need to provide additional styling information to ensure generated documentation
219 | is more rich text. Therefore JSDoc should generally follow markdown markup to
220 | enrich the text.
221 |
222 | While markdown supports HTML tags, it is forbidden in JSDoc blocks.
223 |
224 | Code string literals should be braced with the back-tick (\`) instead of quotes.
225 | For example:
226 |
227 | ```ts
228 | /** Import something from the `deno` module. */
229 | ```
230 |
231 | Do not document function arguments unless they are non-obvious of their intent
232 | (though if they are non-obvious intent, the API should be considered anyways).
233 | Therefore `@param` should generally not be used. If `@param` is used, it should
234 | not include the `type` as TypeScript is already strongly typed.
235 |
236 | ```ts
237 | /**
238 | * Function with non obvious param
239 | * @param foo Description of non obvious parameter
240 | */
241 | ```
242 |
243 | Vertical spacing should be minimized whenever possible. Therefore single line
244 | comments should be written as:
245 |
246 | ```ts
247 | /** This is a good single line JSDoc */
248 | ```
249 |
250 | And not
251 |
252 | ```ts
253 | /**
254 | * This is a bad single line JSDoc
255 | */
256 | ```
257 |
258 | Code examples should not utilise the triple-back tick (\`\`\`) notation or tags.
259 | They should just be marked by indentation, which requires a break before the
260 | block and 6 additional spaces for each line of the example. This is 4 more than
261 | the first column of the comment. For example:
262 |
263 | ```ts
264 | /** A straight forward comment and an example:
265 | *
266 | * import { foo } from "deno";
267 | * foo("bar");
268 | */
269 | ```
270 |
271 | Code examples should not contain additional comments. It is already inside a
272 | comment. If it needs further comments is not a good example.
273 |
274 | ## Each module should come with tests
275 |
276 | Each module should come with its test as a sibling with the name
277 | `modulename_test.ts`. For example the module `foo.ts` should come with its
278 | sibling `foo_test.ts`.
279 |
280 | ## Unit Tests should be explicit
281 |
282 | For a better understanding of the tests, function should be correctly named as
283 | its prompted throughout the test command. Like:
284 |
285 | ```
286 | test myTestFunction ... ok
287 | ```
288 |
289 | Example of test:
290 |
291 | ```ts
292 | import { assertEquals } from "https://deno.land/std@v0.3.1/testing/asserts.ts";
293 | import { test } from "https://deno.land/std@v0.3.1/testing/mod.ts";
294 | import { foo } from "./mod.ts";
295 |
296 | test(function myTestFunction() {
297 | assertEquals(foo(), { bar: "bar" });
298 | });
299 | ```
300 |
--------------------------------------------------------------------------------
/docs/manual.zh.md:
--------------------------------------------------------------------------------
1 | # Deno 手册
2 |
3 | ## 免责声明
4 |
5 | 警告语:Deno 正在开发中。我们鼓励勇敢的早期采用者,但期望反馈大或小的 Bug。API 如有变更,恕不另行通知。[错误报告](https://github.com/denoland/deno/issues)会有用!
6 |
7 | ## 介绍
8 |
9 | 使用 V8、Rust 和 Tokio 构建的安全 javascript/typescript 运行时
10 |
11 | ### 哲学
12 |
13 | Deno 的目标是为现代程序员提供一个高效、安全的脚本环境。
14 |
15 | 它始终以单个可执行文件形态,作为分发文件,并且该可执行文件,足够运行任何 deno 程序。给定一个 deno 程序的 URL,您应该能够用不超过 50MB 的 Deno 可执行文件,来执行它。
16 |
17 | Deno 明确承担运行时,和包管理器的角色。它用标准的浏览器兼容协议,来加载模块:URLs。
18 |
19 | Deno 为提供了程序访问系统的安全保证,默认情况下,它是最严格的安全沙盒。
20 |
21 | Deno 提供一套经过评审(审核)的标准模块 这保证了与 Deno 的合作。
22 |
23 | ### 目标
24 |
25 | - 支持现成的 typescript。
26 |
27 | - 与浏览器一样,允许(模块)以 URL 形式导入:
28 |
29 | ```ts
30 | import * as log from 'https://deno.land/std/log/mod.ts';
31 | ```
32 |
33 | - 远程代码在第一次执行时,被获取和缓存,并且在使用`--reload`标志,才会更新(同一 URL 路径的代码)。(所以,还能在飞机上使用。见`~/.deno/src`,有关缓存的详细信息。)
34 |
35 | - 使用"ES 模块",不支持`require()`.
36 |
37 | - 为了沙盒代码的运行,会对文件系统和网络访问(权限)有所控制。V8(没权限)和 Rust(权限)之间的访问,只能通过在[flatbuffer](https://github.com/denoland/deno/blob/master/cli/msg.fbs)定义的序列化消息,完成沟通。这使得审计变得容易。例如,要启用 write(写) 访问,请使用标志`--allow-write`,或用于网络访问`--allow-net`。
38 |
39 | - 只运输一个可执行文件。
40 |
41 | - 总是死(崩溃)于,未发现的错误。
42 |
43 | - 浏览器兼容:Deno 程序的子集,完全用 JavaScript 编写,它(或它的功能测试)并没有使用全局`Deno`名称空间,想来应该能够在现代 Web 浏览器上运行,而不需要更改。
44 |
45 | - [目标:支持顶级`await`.](https://github.com/denoland/deno/issues/471)
46 |
47 | - 能够高效地服务 HTTP。([目前,速度比较慢。](https://deno.land/benchmarks.html#req-per-sec))
48 |
49 | - 提供现成的有用工具:
50 | - 命令行调试器[还没有](https://github.com/denoland/deno/issues/1120)
51 | - linter[还没有](https://github.com/denoland/deno/issues/1880)
52 | - 依赖关系检查器(`deno info`)
53 | - 代码格式化程序(`deno fmt`)
54 |
55 | ### 反目标
56 |
57 | - 没有`package.json`.
58 |
59 | - 没有 npm。
60 |
61 | - 与 Node 不显式兼容。
62 |
63 | ## 安装程序
64 |
65 | ### 二进制安装
66 |
67 | Deno 在 OSX、Linux 和 Windows 上工作。deno 是单个二进制可执行文件。它没有外部依赖关系。
68 |
69 | [deno_install](https://github.com/denoland/deno_install)提供方便的脚本,来下载和安装二进制文件。
70 |
71 | 使用 Shell:
72 |
73 | ```shellsession
74 | $ curl -fsSL https://deno.land/x/install/install.sh | sh
75 | ```
76 |
77 | 使用 PowerShell:
78 |
79 | ```shellsession
80 | > iwr https://deno.land/x/install/install.ps1 | iex
81 | ```
82 |
83 | 使用[Scoop](https://scoop.sh/)(Windows):
84 |
85 | ```
86 | scoop install deno
87 | ```
88 |
89 | 也可以通过[github.com/denoland/deno/releases](https://github.com/denoland/deno/releases)下载 tarball 或 zip 文件,手动安装 deno。这些包只包含一个可执行文件。您必须在 Mac 和 Linux 上,设置可执行的环境变量(PATH)。
90 |
91 | 一旦它安装和已在`$PATH`,开始试试吧:
92 |
93 | ```shellsession
94 | $ deno https://deno.land/welcome.ts
95 | ```
96 |
97 | ### 从源代码生成
98 |
99 | ```bash
100 | # 获取 源和开发依赖.
101 | git clone --recurse-submodules https://github.com/denoland/deno.git
102 | cd deno
103 | ./tools/setup.py
104 |
105 | # 你可能需要确保 sccache 是在运行的。
106 | # (TODO 需要与否,其实并不明确.)
107 | # prebuilt/mac/sccache --start-server
108 |
109 | # 构建.
110 | ./tools/build.py
111 |
112 | # 运行.
113 | ./target/debug/deno tests/002_hello.ts
114 |
115 | # 测试.
116 | ./tools/test.py
117 |
118 | # 格式化代码.
119 | ./tools/format.py
120 | ```
121 |
122 | #### 先决条件
123 |
124 | 为了确保构建的可重复性,deno 在 git 子模块中有其大部分依赖项。但是,您需要单独安装:
125 |
126 | 1. [Rust](https://www.rust-lang.org/en-US/install.html)> 1.31.1
127 | 2. [Node](https://nodejs.org/)
128 | 3. Python 2。[不是 3](https://github.com/denoland/deno/issues/464#issuecomment-411795578).
129 |
130 | Mac 用户的额外步骤:安装[XCode](https://developer.apple.com/xcode/) :(
131 |
132 | Windows 用户的额外步骤:
133 |
134 | 1. 添加`python.exe`到`PATH`(例如 `set PATH=%PATH%;C:\Python27\python.exe`)
135 | 2. 得到[VS Community 2017](https://www.visualstudio.com/downloads/),随着"Desktop development with C++"工具包,并确保选择以下列出所有的 C++工具。
136 | - Windows 10 SDK >= 10.0.17134
137 | - X86 和 X64 的 Visual C++ ATL
138 | - X86 和 X64 的 Visual C++ MFC
139 | - C++ profiling 工具
140 | 3. 启用"Windows 调试工具"。转到"控制面板"→"程序"→"程序和功能"→ 选择"Windows 软件开发工具包-Windows 10"→"更改"→"更改"→ 检查"Windows 调试工具"→"更改"->"完成"
141 |
142 | > ("Control Panel" → "Programs" → "Programs and Features" → Select "Windows Software >Development Kit - Windows 10" →
143 | > "Change" → "Change" → Check "Debugging Tools >For Windows" → "Change" -> "Finish")。
144 |
145 | 4. 确保使用的是 Git 2.19.2.Windows.1 或更高版本。
146 |
147 | #### 其他有用的命令
148 |
149 | ```bash
150 | # 手动呼叫 ninja。
151 | ./third_party/depot_tools/ninja -C target/debug
152 |
153 | # 构建发布二进制文件。
154 | ./tools/build.py --release deno
155 |
156 | # 列出可执行目标。
157 | ./third_party/depot_tools/gn ls target/debug //:* --as=output --type=executable
158 |
159 | # 列表构建配置。
160 | ./third_party/depot_tools/gn args target/debug/ --list
161 |
162 | # 编辑构建配置。
163 | ./third_party/depot_tools/gn args target/debug/
164 |
165 | # 描述一个目标。
166 | ./third_party/depot_tools/gn desc target/debug/ :deno
167 | ./third_party/depot_tools/gn help
168 |
169 | # 更新third_party模块
170 | git submodule update
171 | ```
172 |
173 | 环境变量:`DENO_BUILD_MODE`,`DENO_BUILD_PATH`,`DENO_BUILD_ARGS`,`DENO_DIR`。
174 |
175 | ## API 参考
176 |
177 | ### deno --types
178 |
179 | 要获得 Deno 运行时,准确的 API 参考,请在命令行中,运行以下命令:
180 |
181 | ```shellsession
182 | $ deno --types
183 | ```
184 |
185 | [这就是输出的样子。](https://gist.github.com/ry/46da4724168cdefa763e13207d27ede5)
186 |
187 | ### 参考网站
188 |
189 | [TypeScript Deno api](https://deno.land/typedoc/index.html)。
190 |
191 | 如果要在 Rust 程序中,嵌入 deno,请参见[Rust Deno API](https://deno.land/rustdoc/deno/index.html)。
192 |
193 | ## 实例
194 |
195 | ### Unix "cat"程序的实现
196 |
197 | 在这个程序中,每个命令行参数,都被假定为文件名,文件被打开,并打印到 stdout。
198 |
199 | ```ts
200 | (async () => {
201 | for (let i = 1; i < Deno.args.length; i++) {
202 | let filename = Deno.args[i];
203 | let file = await Deno.open(filename);
204 | await Deno.copy(Deno.stdout, file);
205 | file.close();
206 | }
207 | })();
208 | ```
209 |
210 | 这个`copy()`函数,实际上只做了,必要的内核->用户空间->内核副本。也就是说,从文件读取来的数据的相同内存,被写入 stdout。这说明了 deno 中,关于 I/O 流的通用设计目标。
211 |
212 | 尝试程序:
213 |
214 | ```shellsession
215 | $ deno --allow-read https://deno.land/std/examples/cat.ts /etc/passwd
216 | ```
217 |
218 | ### TCP 回音服务器
219 |
220 | 这是一个简单服务器的例子,它接受端口 8080 上的连接,并将它发送的任何内容,返回给客户端。
221 |
222 | ```ts
223 | const {listen, copy} = Deno;
224 |
225 | (async () => {
226 | const addr = '0.0.0.0:8080';
227 | const listener = listen('tcp', addr);
228 | console.log('listening on', addr);
229 | while (true) {
230 | const conn = await listener.accept();
231 | copy(conn, conn);
232 | }
233 | })();
234 | ```
235 |
236 | 启动此程序时,将提示用户,要有在网络上侦听的权限:
237 |
238 | ```shellsession
239 | $ deno https://deno.land/std/examples/echo_server.ts
240 | ⚠️ Deno requests network access to "listen". Grant? [yN] y
241 | listening on 0.0.0.0:8080
242 | ```
243 |
244 | 出于安全原因,Deno 不允许程序,在没有明确许可的情况下访问网络。要避免控制台提示,请使用命令行标志:
245 |
246 | ```shellsession
247 | $ deno https://deno.land/std/examples/echo_server.ts --allow-net
248 | ```
249 |
250 | 要测试它,请尝试使用 curl 向它发送 HTTP 请求。请求会被直接写回客户端。
251 |
252 | ```shellsession
253 | $ curl http://localhost:8080/
254 | GET / HTTP/1.1
255 | Host: localhost:8080
256 | User-Agent: curl/7.54.0
257 | Accept: */*
258 | ```
259 |
260 | 值得注意的是,类似`cat.ts`那个例子,这里的`copy()`函数,也不会进行不必要的内存复制。它从内核接收一个数据包,并发送回来,没有进一步的复杂性。
261 |
262 | ### 检查和撤消权限
263 |
264 | 有时程序可能希望撤消以前授予的权限。当程序在后期需要这些权限时,则向用户显示一个新的提示。
265 |
266 | ```ts
267 | const {permissions, revokePermission, open, remove} = Deno;
268 |
269 | (async () => {
270 | // 查看一个权限
271 | if (!permissions().write) {
272 | throw new Error('need write permission');
273 | }
274 |
275 | const log = await open('request.log', 'a+');
276 |
277 | // 撤消一些权限
278 | revokePermission('read');
279 | revokePermission('write');
280 |
281 | // 使用 log file
282 | await log.write(encoder.encode('hello\n'));
283 |
284 | // 然后提示需要 write 权限或者失败。
285 | await remove('request.log');
286 | })();
287 | ```
288 |
289 | ### 文件服务器
290 |
291 | 这一个在 HTTP 中,提供服务的本地目录。
292 |
293 | ```bash
294 | alias file_server="deno --allow-net --allow-read \
295 | https://deno.land/std/http/file_server.ts"
296 | ```
297 |
298 | 运行它:
299 |
300 | ```shellsession
301 | $ file_server .
302 | Downloading https://deno.land/std/http/file_server.ts...
303 | [...]
304 | HTTP server listening on http://0.0.0.0:4500/
305 | ```
306 |
307 | 如果您想升级到,最新发布的版本:
308 |
309 | ```shellsession
310 | $ file_server --reload
311 | ```
312 |
313 | ### 运行子过程
314 |
315 | [API 参考](https://deno.land/typedoc/index.html#run)
316 |
317 | 例子:
318 |
319 | ```ts
320 | async function main() {
321 | // 创建子进程
322 | const p = Deno.run({
323 | args: ['echo', 'hello']
324 | });
325 |
326 | // await(等待) 完成
327 | await p.status();
328 | }
329 |
330 | main();
331 | ```
332 |
333 | 运行它:
334 |
335 | ```shellsession
336 | $ deno --allow-run ./subprocess_simple.ts
337 | hello
338 | ```
339 |
340 | 默认情况下,`Deno.run()`的子进程,会继承父进程的`stdin`,`stdout`和`stdout`。如果要与已启动的子进程通信,可以使用`"piped"`选项。
341 |
342 | ```ts
343 | async function main() {
344 | const decoder = new TextDecoder();
345 |
346 | const fileNames = Deno.args.slice(1);
347 |
348 | const p = Deno.run({
349 | args: [
350 | 'deno',
351 | '--allow-read',
352 | 'https://deno.land/std/examples/cat.ts',
353 | ...fileNames
354 | ],
355 | stdout: 'piped',
356 | stderr: 'piped'
357 | });
358 |
359 | const {code} = await p.status();
360 |
361 | if (code === 0) {
362 | const rawOutput = await p.output();
363 | Deno.stdout.write(rawOutput);
364 | } else {
365 | const rawError = await p.stderrOutput();
366 | Deno.stdout.write(rawError);
367 | }
368 |
369 | Deno.exit(code);
370 | }
371 |
372 | main();
373 | ```
374 |
375 | 运行时:
376 |
377 | ```shellsession
378 | $ deno ./subprocess.ts --allow-run
379 | [file content]
380 |
381 | $ deno ./subprocess.ts --allow-run non_existent_file.md
382 |
383 | Uncaught NotFound: No such file or directory (os error 2)
384 | at DenoError (deno/js/errors.ts:19:5)
385 | at maybeError (deno/js/errors.ts:38:12)
386 | at handleAsyncMsgFromRust (deno/js/dispatch.ts:27:17)
387 | ```
388 |
389 | ### 链接到第三方代码
390 |
391 | 在上面的例子中,我们看到了 deno 可以用 URL 执行脚本。和浏览器 javascript 一样,deno 可以直接用 URL 导入库。此示例使用 URL 导入,测试运行程序库:
392 |
393 | ```ts
394 | import {test, runIfMain} from 'https://deno.land/std/testing/mod.ts';
395 | import {assertEquals} from 'https://deno.land/std/testing/asserts.ts';
396 |
397 | test(function t1() {
398 | assertEquals('hello', 'hello');
399 | });
400 |
401 | test(function t2() {
402 | assertEquals('world', 'world');
403 | });
404 |
405 | runIfMain(import.meta);
406 | ```
407 |
408 | 尝试运行此:
409 |
410 | ```shellsession
411 | $ deno test.ts
412 | running 2 tests
413 | test t1 ... ok
414 | test t2 ... ok
415 |
416 | test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
417 | ```
418 |
419 | 注意,我们不必提供`--allow-net`此程序的标志,但它访问了网络。事实上,Deno 运行时具有,下载导入(文件),并将其缓存到磁盘的特殊访问权。
420 |
421 | deno 将远程导入,缓存到`$DENO_DIR`环境变量。如果`$DENO_DIR`未指定。下次运行程序时,将不会进行下载。如果程序没有更改,也不会重新编译。默认目录为:
422 |
423 | - 在 Linux/Redox:`$XDG_CACHE_HOME/deno`或`$HOME/.cache/deno`
424 | - 在 Windows 上:`%LOCALAPPDATA%/deno`(`%LOCALAPPDATA%` = `FOLDERID_LocalAppData`)
425 | - 在 MaOS:`$HOME/Library/Caches/deno`
426 | - 如果某件事失败了,它会回到`$HOME/.deno`
427 |
428 | **但是如果`https://deno.land/`失联了?**依赖外部服务器便于开发,但在生产环境中,却很脆弱。生产软件应始终捆绑其依赖项。具体在 deno 的操作是,通过让`$DENO_DIR`,搭上你的源代码管理系统,把运行时的`$DENO_DIR`环境变量,指定为该路径。
429 |
430 | **如何导入到特定版本?**只需在 URL 中,指定版本。例如,此 URL 完全指定,正在运行的代码:`https://unpkg.com/liltest@0.0.5/dist/liltest.js`。 结合上述在生产环境,设置`$DENO_DIR`,来存储代码的方式,你可以完全指定,要运行的确切代码,还可以在没有网络访问的情况下,执行代码。
431 |
432 | **在任何地方导入 URL 似乎都不方便。如果其中一个 URL ,链接到了一个稍微不同的库版本呢?在大型项目中,维护 URL 是否容易出错?**解决方案是在中心`deps.ts`文件,导入和重新导出外部库(与 Node 的`package.json`文件目的相同)。例如,假设您在一个大型项目中,使用了上述测试库。要做的,不是在任何地方导入`"https://deno.land/std/testing/mod.ts"`,而是可以创建一个`deps.ts`,用来导出第三方代码:
433 |
434 | ```ts
435 | export {test, assertEquals} from 'https://deno.land/std/testing/mod.ts';
436 | ```
437 |
438 | 在整个项目中,都可以从`deps.ts`导入,这样就可以避免对同一个 URL 进行多次引用:
439 |
440 | ```ts
441 | import {test, assertEquals} from './deps.ts';
442 | ```
443 |
444 | 这种设计避免了,由于包管理软件、集中的代码库和多余的文件格式,而产生的过多复杂性。
445 |
446 | ### 测试当前文件,是否为主程序
447 |
448 | 通过检查`import.meta.main`,测测当前脚本,是否已作为程序的主输入执行。
449 |
450 | ```ts
451 | if (import.meta.main) {
452 | console.log('main');
453 | }
454 | ```
455 |
456 | ## 命令行界面
457 |
458 | ### 标志
459 |
460 | ```shellsession
461 | $ deno -h
462 | deno
463 |
464 | USAGE:
465 | deno_dev [FLAGS] [OPTIONS] [SUBCOMMAND]
466 |
467 | FLAGS:
468 | -A, --allow-all 允许所有权限
469 | --allow-env 允许环境访问
470 | --allow-net 允许网络访问
471 | --allow-read 允许文件系统读访问权限
472 | --allow-run 允许运行子进程
473 | --allow-write 允许文件系统写访问权限
474 | -h, --help 打印帮助信息
475 | -D, --log-debug 记录调试输出
476 | --no-prompt 不要使用提示
477 | --prefetch 预取依赖项
478 | -r, --reload 重新加载源代码缓存(重新编译 TypeScript)
479 | --types 打印运行时的 TypeScript 声明
480 | --v8-options 打印 V8 命令行选项
481 | -v, --version 打印版本
482 |
483 | OPTIONS:
484 | --v8-flags= 设置V8命令行选项
485 |
486 | SUBCOMMANDS(子命令):
487 |