├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── LICENSE
├── README.md
├── assets
└── _custom.scss
├── config.toml
├── content
├── _index.md
├── docs
│ ├── _index.md
│ └── review
│ │ ├── _index.md
│ │ ├── developer
│ │ ├── _index.md
│ │ ├── cl-descriptions.md
│ │ ├── handling-comments.md
│ │ └── small-cls.md
│ │ ├── emergencies.md
│ │ └── reviewer
│ │ ├── _index.md
│ │ ├── comments.md
│ │ ├── looking-for.md
│ │ ├── navigate.md
│ │ ├── pushback.md
│ │ ├── speed.md
│ │ └── standard.md
└── menu
│ └── index.md
├── cover-thumbnail.jpg
├── cover.jpg
└── themes
└── hugo-book
├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── LICENSE
├── README.md
├── archetypes
├── docs.md
└── posts.md
├── assets
├── _custom.scss
├── _fonts.scss
├── _markdown.scss
├── _shortcodes.scss
├── _utils.scss
├── _variables.scss
├── book.scss
├── normalize.css
├── search-data.js
└── search.js
├── exampleSite
├── assets
│ └── _custom.scss
├── config.toml
├── config.yaml
├── content
│ ├── _index.md
│ ├── docs
│ │ ├── introduction
│ │ │ ├── _index.md
│ │ │ └── examples
│ │ │ │ ├── _index.md
│ │ │ │ ├── shortcodes.md
│ │ │ │ ├── with-toc.md
│ │ │ │ └── without-toc.md
│ │ └── more-examples
│ │ │ ├── _index.md
│ │ │ ├── advanced.md
│ │ │ ├── client.md
│ │ │ ├── hidden.md
│ │ │ └── server.md
│ ├── menu
│ │ └── index.md
│ └── posts
│ │ ├── creating-a-new-theme.md
│ │ ├── goisforlovers.md
│ │ ├── hugoisforlovers.md
│ │ └── migrate-from-jekyll.md
└── resources
│ └── _gen
│ └── assets
│ ├── js
│ ├── search-data.js_da973b2166501f614a67d55884e62fdb.content
│ ├── search-data.js_da973b2166501f614a67d55884e62fdb.json
│ ├── search.js_db9e329433ffca0798ed12c88043b3b3.content
│ └── search.js_db9e329433ffca0798ed12c88043b3b3.json
│ └── scss
│ ├── book.scss_48b060fe05b0a273d182ef83c0605941.content
│ └── book.scss_48b060fe05b0a273d182ef83c0605941.json
├── images
├── screenshot.png
└── tn.png
├── layouts
├── 404.html
├── docs
│ ├── baseof.html
│ ├── list.html
│ └── single.html
├── home.html
├── partials
│ └── docs
│ │ ├── brand.html
│ │ ├── git-footer.html
│ │ ├── html-head.html
│ │ ├── inject
│ │ ├── body.html
│ │ ├── footer.html
│ │ ├── head.html
│ │ ├── menu-after.html
│ │ └── menu-before.html
│ │ ├── menu-bundle.html
│ │ ├── menu-filetree.html
│ │ ├── menu.html
│ │ ├── mobile-header.html
│ │ ├── search.html
│ │ ├── title.html
│ │ └── toc.html
├── posts
│ ├── baseof.html
│ ├── list.html
│ └── single.html
├── shortcodes
│ ├── button.html
│ ├── columns.html
│ ├── expand.html
│ ├── katex.html
│ ├── mermaid.html
│ ├── tab.html
│ └── tabs.html
└── taxonomy
│ ├── list.html
│ └── taxonomy.html
├── static
├── favicon.png
├── fonts
│ ├── roboto-mono-v6-latin-regular.woff
│ ├── roboto-mono-v6-latin-regular.woff2
│ ├── roboto-v19-latin-300italic.woff
│ ├── roboto-v19-latin-300italic.woff2
│ ├── roboto-v19-latin-700.woff
│ ├── roboto-v19-latin-700.woff2
│ ├── roboto-v19-latin-regular.woff
│ └── roboto-v19-latin-regular.woff2
├── lunr.min.js
├── mermaid.min.js
└── svg
│ ├── calendar.svg
│ ├── edit.svg
│ └── menu.svg
└── theme.toml
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: build-and-deploy
2 | on: push
3 | jobs:
4 | deploy:
5 | runs-on: ubuntu-18.04
6 | steps:
7 | - name: Git checkout
8 | uses: actions/checkout@v2
9 |
10 | - name: Setup hugo
11 | uses: peaceiris/actions-hugo@v2
12 | with:
13 | hugo-version: '0.58.3'
14 | extended: true
15 | - name: Build
16 | # remove --minify tag if you do not need it
17 | # docs: https://gohugo.io/hugo-pipes/minification/
18 | run: hugo
19 | - name: Deploy
20 | uses: peaceiris/actions-gh-pages@v3
21 | with:
22 | deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
23 | publish_dir: ./public
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | _site
2 | .DS_Store
3 | resources
4 | public
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Creative Commons Legal Code
2 |
3 | Attribution 3.0 Unported
4 |
5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
6 | LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
9 | REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
10 | DAMAGES RESULTING FROM ITS USE.
11 |
12 | License
13 |
14 | THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
15 | COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
16 | COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
17 | AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
18 |
19 | BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
20 | TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
21 | BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
22 | CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
23 | CONDITIONS.
24 |
25 | 1. Definitions
26 |
27 | a. "Adaptation" means a work based upon the Work, or upon the Work and
28 | other pre-existing works, such as a translation, adaptation,
29 | derivative work, arrangement of music or other alterations of a
30 | literary or artistic work, or phonogram or performance and includes
31 | cinematographic adaptations or any other form in which the Work may be
32 | recast, transformed, or adapted including in any form recognizably
33 | derived from the original, except that a work that constitutes a
34 | Collection will not be considered an Adaptation for the purpose of
35 | this License. For the avoidance of doubt, where the Work is a musical
36 | work, performance or phonogram, the synchronization of the Work in
37 | timed-relation with a moving image ("synching") will be considered an
38 | Adaptation for the purpose of this License.
39 | b. "Collection" means a collection of literary or artistic works, such as
40 | encyclopedias and anthologies, or performances, phonograms or
41 | broadcasts, or other works or subject matter other than works listed
42 | in Section 1(f) below, which, by reason of the selection and
43 | arrangement of their contents, constitute intellectual creations, in
44 | which the Work is included in its entirety in unmodified form along
45 | with one or more other contributions, each constituting separate and
46 | independent works in themselves, which together are assembled into a
47 | collective whole. A work that constitutes a Collection will not be
48 | considered an Adaptation (as defined above) for the purposes of this
49 | License.
50 | c. "Distribute" means to make available to the public the original and
51 | copies of the Work or Adaptation, as appropriate, through sale or
52 | other transfer of ownership.
53 | d. "Licensor" means the individual, individuals, entity or entities that
54 | offer(s) the Work under the terms of this License.
55 | e. "Original Author" means, in the case of a literary or artistic work,
56 | the individual, individuals, entity or entities who created the Work
57 | or if no individual or entity can be identified, the publisher; and in
58 | addition (i) in the case of a performance the actors, singers,
59 | musicians, dancers, and other persons who act, sing, deliver, declaim,
60 | play in, interpret or otherwise perform literary or artistic works or
61 | expressions of folklore; (ii) in the case of a phonogram the producer
62 | being the person or legal entity who first fixes the sounds of a
63 | performance or other sounds; and, (iii) in the case of broadcasts, the
64 | organization that transmits the broadcast.
65 | f. "Work" means the literary and/or artistic work offered under the terms
66 | of this License including without limitation any production in the
67 | literary, scientific and artistic domain, whatever may be the mode or
68 | form of its expression including digital form, such as a book,
69 | pamphlet and other writing; a lecture, address, sermon or other work
70 | of the same nature; a dramatic or dramatico-musical work; a
71 | choreographic work or entertainment in dumb show; a musical
72 | composition with or without words; a cinematographic work to which are
73 | assimilated works expressed by a process analogous to cinematography;
74 | a work of drawing, painting, architecture, sculpture, engraving or
75 | lithography; a photographic work to which are assimilated works
76 | expressed by a process analogous to photography; a work of applied
77 | art; an illustration, map, plan, sketch or three-dimensional work
78 | relative to geography, topography, architecture or science; a
79 | performance; a broadcast; a phonogram; a compilation of data to the
80 | extent it is protected as a copyrightable work; or a work performed by
81 | a variety or circus performer to the extent it is not otherwise
82 | considered a literary or artistic work.
83 | g. "You" means an individual or entity exercising rights under this
84 | License who has not previously violated the terms of this License with
85 | respect to the Work, or who has received express permission from the
86 | Licensor to exercise rights under this License despite a previous
87 | violation.
88 | h. "Publicly Perform" means to perform public recitations of the Work and
89 | to communicate to the public those public recitations, by any means or
90 | process, including by wire or wireless means or public digital
91 | performances; to make available to the public Works in such a way that
92 | members of the public may access these Works from a place and at a
93 | place individually chosen by them; to perform the Work to the public
94 | by any means or process and the communication to the public of the
95 | performances of the Work, including by public digital performance; to
96 | broadcast and rebroadcast the Work by any means including signs,
97 | sounds or images.
98 | i. "Reproduce" means to make copies of the Work by any means including
99 | without limitation by sound or visual recordings and the right of
100 | fixation and reproducing fixations of the Work, including storage of a
101 | protected performance or phonogram in digital form or other electronic
102 | medium.
103 |
104 | 2. Fair Dealing Rights. Nothing in this License is intended to reduce,
105 | limit, or restrict any uses free from copyright or rights arising from
106 | limitations or exceptions that are provided for in connection with the
107 | copyright protection under copyright law or other applicable laws.
108 |
109 | 3. License Grant. Subject to the terms and conditions of this License,
110 | Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
111 | perpetual (for the duration of the applicable copyright) license to
112 | exercise the rights in the Work as stated below:
113 |
114 | a. to Reproduce the Work, to incorporate the Work into one or more
115 | Collections, and to Reproduce the Work as incorporated in the
116 | Collections;
117 | b. to create and Reproduce Adaptations provided that any such Adaptation,
118 | including any translation in any medium, takes reasonable steps to
119 | clearly label, demarcate or otherwise identify that changes were made
120 | to the original Work. For example, a translation could be marked "The
121 | original work was translated from English to Spanish," or a
122 | modification could indicate "The original work has been modified.";
123 | c. to Distribute and Publicly Perform the Work including as incorporated
124 | in Collections; and,
125 | d. to Distribute and Publicly Perform Adaptations.
126 | e. For the avoidance of doubt:
127 |
128 | i. Non-waivable Compulsory License Schemes. In those jurisdictions in
129 | which the right to collect royalties through any statutory or
130 | compulsory licensing scheme cannot be waived, the Licensor
131 | reserves the exclusive right to collect such royalties for any
132 | exercise by You of the rights granted under this License;
133 | ii. Waivable Compulsory License Schemes. In those jurisdictions in
134 | which the right to collect royalties through any statutory or
135 | compulsory licensing scheme can be waived, the Licensor waives the
136 | exclusive right to collect such royalties for any exercise by You
137 | of the rights granted under this License; and,
138 | iii. Voluntary License Schemes. The Licensor waives the right to
139 | collect royalties, whether individually or, in the event that the
140 | Licensor is a member of a collecting society that administers
141 | voluntary licensing schemes, via that society, from any exercise
142 | by You of the rights granted under this License.
143 |
144 | The above rights may be exercised in all media and formats whether now
145 | known or hereafter devised. The above rights include the right to make
146 | such modifications as are technically necessary to exercise the rights in
147 | other media and formats. Subject to Section 8(f), all rights not expressly
148 | granted by Licensor are hereby reserved.
149 |
150 | 4. Restrictions. The license granted in Section 3 above is expressly made
151 | subject to and limited by the following restrictions:
152 |
153 | a. You may Distribute or Publicly Perform the Work only under the terms
154 | of this License. You must include a copy of, or the Uniform Resource
155 | Identifier (URI) for, this License with every copy of the Work You
156 | Distribute or Publicly Perform. You may not offer or impose any terms
157 | on the Work that restrict the terms of this License or the ability of
158 | the recipient of the Work to exercise the rights granted to that
159 | recipient under the terms of the License. You may not sublicense the
160 | Work. You must keep intact all notices that refer to this License and
161 | to the disclaimer of warranties with every copy of the Work You
162 | Distribute or Publicly Perform. When You Distribute or Publicly
163 | Perform the Work, You may not impose any effective technological
164 | measures on the Work that restrict the ability of a recipient of the
165 | Work from You to exercise the rights granted to that recipient under
166 | the terms of the License. This Section 4(a) applies to the Work as
167 | incorporated in a Collection, but this does not require the Collection
168 | apart from the Work itself to be made subject to the terms of this
169 | License. If You create a Collection, upon notice from any Licensor You
170 | must, to the extent practicable, remove from the Collection any credit
171 | as required by Section 4(b), as requested. If You create an
172 | Adaptation, upon notice from any Licensor You must, to the extent
173 | practicable, remove from the Adaptation any credit as required by
174 | Section 4(b), as requested.
175 | b. If You Distribute, or Publicly Perform the Work or any Adaptations or
176 | Collections, You must, unless a request has been made pursuant to
177 | Section 4(a), keep intact all copyright notices for the Work and
178 | provide, reasonable to the medium or means You are utilizing: (i) the
179 | name of the Original Author (or pseudonym, if applicable) if supplied,
180 | and/or if the Original Author and/or Licensor designate another party
181 | or parties (e.g., a sponsor institute, publishing entity, journal) for
182 | attribution ("Attribution Parties") in Licensor's copyright notice,
183 | terms of service or by other reasonable means, the name of such party
184 | or parties; (ii) the title of the Work if supplied; (iii) to the
185 | extent reasonably practicable, the URI, if any, that Licensor
186 | specifies to be associated with the Work, unless such URI does not
187 | refer to the copyright notice or licensing information for the Work;
188 | and (iv) , consistent with Section 3(b), in the case of an Adaptation,
189 | a credit identifying the use of the Work in the Adaptation (e.g.,
190 | "French translation of the Work by Original Author," or "Screenplay
191 | based on original Work by Original Author"). The credit required by
192 | this Section 4 (b) may be implemented in any reasonable manner;
193 | provided, however, that in the case of a Adaptation or Collection, at
194 | a minimum such credit will appear, if a credit for all contributing
195 | authors of the Adaptation or Collection appears, then as part of these
196 | credits and in a manner at least as prominent as the credits for the
197 | other contributing authors. For the avoidance of doubt, You may only
198 | use the credit required by this Section for the purpose of attribution
199 | in the manner set out above and, by exercising Your rights under this
200 | License, You may not implicitly or explicitly assert or imply any
201 | connection with, sponsorship or endorsement by the Original Author,
202 | Licensor and/or Attribution Parties, as appropriate, of You or Your
203 | use of the Work, without the separate, express prior written
204 | permission of the Original Author, Licensor and/or Attribution
205 | Parties.
206 | c. Except as otherwise agreed in writing by the Licensor or as may be
207 | otherwise permitted by applicable law, if You Reproduce, Distribute or
208 | Publicly Perform the Work either by itself or as part of any
209 | Adaptations or Collections, You must not distort, mutilate, modify or
210 | take other derogatory action in relation to the Work which would be
211 | prejudicial to the Original Author's honor or reputation. Licensor
212 | agrees that in those jurisdictions (e.g. Japan), in which any exercise
213 | of the right granted in Section 3(b) of this License (the right to
214 | make Adaptations) would be deemed to be a distortion, mutilation,
215 | modification or other derogatory action prejudicial to the Original
216 | Author's honor and reputation, the Licensor will waive or not assert,
217 | as appropriate, this Section, to the fullest extent permitted by the
218 | applicable national law, to enable You to reasonably exercise Your
219 | right under Section 3(b) of this License (right to make Adaptations)
220 | but not otherwise.
221 |
222 | 5. Representations, Warranties and Disclaimer
223 |
224 | UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
225 | OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
226 | KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
227 | INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
228 | FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
229 | LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
230 | WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION
231 | OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
232 |
233 | 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
234 | LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
235 | ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
236 | ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
237 | BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
238 |
239 | 7. Termination
240 |
241 | a. This License and the rights granted hereunder will terminate
242 | automatically upon any breach by You of the terms of this License.
243 | Individuals or entities who have received Adaptations or Collections
244 | from You under this License, however, will not have their licenses
245 | terminated provided such individuals or entities remain in full
246 | compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
247 | survive any termination of this License.
248 | b. Subject to the above terms and conditions, the license granted here is
249 | perpetual (for the duration of the applicable copyright in the Work).
250 | Notwithstanding the above, Licensor reserves the right to release the
251 | Work under different license terms or to stop distributing the Work at
252 | any time; provided, however that any such election will not serve to
253 | withdraw this License (or any other license that has been, or is
254 | required to be, granted under the terms of this License), and this
255 | License will continue in full force and effect unless terminated as
256 | stated above.
257 |
258 | 8. Miscellaneous
259 |
260 | a. Each time You Distribute or Publicly Perform the Work or a Collection,
261 | the Licensor offers to the recipient a license to the Work on the same
262 | terms and conditions as the license granted to You under this License.
263 | b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
264 | offers to the recipient a license to the original Work on the same
265 | terms and conditions as the license granted to You under this License.
266 | c. If any provision of this License is invalid or unenforceable under
267 | applicable law, it shall not affect the validity or enforceability of
268 | the remainder of the terms of this License, and without further action
269 | by the parties to this agreement, such provision shall be reformed to
270 | the minimum extent necessary to make such provision valid and
271 | enforceable.
272 | d. No term or provision of this License shall be deemed waived and no
273 | breach consented to unless such waiver or consent shall be in writing
274 | and signed by the party to be charged with such waiver or consent.
275 | e. This License constitutes the entire agreement between the parties with
276 | respect to the Work licensed here. There are no understandings,
277 | agreements or representations with respect to the Work not specified
278 | here. Licensor shall not be bound by any additional provisions that
279 | may appear in any communication from You. This License may not be
280 | modified without the mutual written agreement of the Licensor and You.
281 | f. The rights granted under, and the subject matter referenced, in this
282 | License were drafted utilizing the terminology of the Berne Convention
283 | for the Protection of Literary and Artistic Works (as amended on
284 | September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
285 | Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996
286 | and the Universal Copyright Convention (as revised on July 24, 1971).
287 | These rights and subject matter take effect in the relevant
288 | jurisdiction in which the License terms are sought to be enforced
289 | according to the corresponding provisions of the implementation of
290 | those treaty provisions in the applicable national law. If the
291 | standard suite of rights granted under applicable copyright law
292 | includes additional rights not granted under this License, such
293 | additional rights are deemed to be included in the License; this
294 | License is not intended to restrict the license of any rights under
295 | applicable law.
296 |
297 |
298 | Creative Commons Notice
299 |
300 | Creative Commons is not a party to this License, and makes no warranty
301 | whatsoever in connection with the Work. Creative Commons will not be
302 | liable to You or any party on any legal theory for any damages
303 | whatsoever, including without limitation any general, special,
304 | incidental or consequential damages arising in connection to this
305 | license. Notwithstanding the foregoing two (2) sentences, if Creative
306 | Commons has expressly identified itself as the Licensor hereunder, it
307 | shall have all rights and obligations of Licensor.
308 |
309 | Except for the limited purpose of indicating to the public that the
310 | Work is licensed under the CCPL, Creative Commons does not authorize
311 | the use by either party of the trademark "Creative Commons" or any
312 | related trademark or logo of Creative Commons without the prior
313 | written consent of Creative Commons. Any permitted use will be in
314 | compliance with Creative Commons' then-current trademark usage
315 | guidelines, as may be published on its website or otherwise made
316 | available upon request from time to time. For the avoidance of doubt,
317 | this trademark restriction does not form part of this License.
318 |
319 | Creative Commons may be contacted at https://creativecommons.org/.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 谷歌工程实践文档
2 |
3 | Google 有许多通用工程实践,几乎涵盖所有语言和项目。此文档为长期积累的最佳实践,是集体经验的结晶。我们尽可能地将其公之于众,您的组织和开源项目也会从中受益。
4 |
5 |
10 |
11 | 当前包含以下文档:
12 |
13 | * Google 代码审查指南,实则两套指南:
14 | * 代码审查者指南
15 | * 代码开发者指南
16 |
17 | 在线浏览:
18 |
19 | ## 译者序
20 |
21 | 此仓库翻译自 [google/eng-practices](https://github.com/google/eng-practices),目前为止的主要内容为 Google 总结的如何进行 **Code Review(代码审查)** 指南,根据原 Github 仓库的标题判断以后会追加更多 Google 工程实践的内容。
22 |
23 | 译者:[Jimmy Song](https://jimmysong.io)
24 |
25 | ## 术语
26 |
27 | 文档中使用了 Google 内部术语,在此为外部读者澄清:
28 |
29 | * **CL**:代表“变更列表(Change List)”,表示已提交到版本控制或正在进行代码审查的自包含更改。有的组织会将其称为“变更(change)”或“补丁(patch)”。
30 | * **LGTM**:意思是“我觉得不错(Looks Good to Me)”。这是批准 CL 时代码审查者所说的。
31 |
32 | ## License
33 |
34 | 本项目中的文档适用于 [CC-By 3.0 许可证](https://creativecommons.org/licenses/by/3.0),该许可证鼓励您共享这些文档。
35 |
--------------------------------------------------------------------------------
/assets/_custom.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
--------------------------------------------------------------------------------
/config.toml:
--------------------------------------------------------------------------------
1 | # hugo server --minify --themesDir ... --baseURL=http://0.0.0.0:1313/example
2 |
3 | baseURL = 'https://jimmysong.io/eng-practices'
4 | title = '谷歌工程实践'
5 | theme = 'hugo-book'
6 | disableKinds = ['taxonomy', 'taxonomyTerm']
7 |
8 | # Book configuration
9 | disablePathToLower = true
10 | enableGitInfo = true
11 |
12 | # Code highlight
13 | pygmentsStyle = 'monokailight'
14 | pygmentsCodeFences = true
15 | googleAnalytics = "UA-93485976-1"
16 |
17 | [params]
18 | # (Optional, default 6) Set how many table of contents levels to be showed on page.
19 | # Use false to hide ToC, note that 0 will default to 6 (https://gohugo.io/functions/default/)
20 | # You can also specify this parameter per page in front matter
21 | BookToC = 3
22 |
23 | # (Optional, default none) Set the path to a logo for the book. If the logo is
24 | # /static/logo.png then the path would be logo.png
25 | # BookLogo = 'logo.png'
26 |
27 | # (Optional, default none) Set leaf bundle to render as side menu
28 | # When not specified file structure and weights will be used
29 | BookMenuBundle = '/menu'
30 |
31 | # (Optional, default docs) Specify section of content to render as menu
32 | # You can also set value to '*' to render all sections to menu
33 | BookSection = 'docs'
34 |
35 | # (Optional) This value is duplicate of $link-color for making active link highlight in menu bundle mode
36 | # BookMenuBundleActiveLinkColor = '\#004ed0'
37 |
38 | # Set source repository location.
39 | # Used for 'Last Modified' and 'Edit this page' links.
40 | BookRepo = 'https://github.com/rootsongjc/eng-practices'
41 |
42 | # Enable "Edit this page" links for 'doc' page type.
43 | # Disabled by default. Uncomment to enable. Requires 'BookRepo' param.
44 | # Path must point to 'content' directory of repo.
45 | BookEditPath = 'edit/master/content'
46 |
47 | # Configure the date format used on the pages
48 | # - In git information
49 | # - In blog posts
50 | BookDateFormat = 'Jan 2, 2006'
51 |
52 | # (Optional, default true) Enables search function with lunr.js,
53 | # Index is built on fly, therefore it might slowdown your website.
54 | BookSearch = true
55 |
56 | # Website analytics
57 | baiduKey = "11f7d254cfa4e0ca44b175c66d379ecc"
58 |
--------------------------------------------------------------------------------
/content/_index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 谷歌工程实践
3 | type: docs
4 | ---
5 |
6 | # 谷歌工程实践文档
7 |
8 | Google 有许多通用工程实践,几乎涵盖所有语言和项目。此文档为长期积累的最佳实践,是集体经验的结晶。我们尽可能地将其公之于众,您的组织和开源项目也会从中受益。
9 |
10 | 当前包含以下文档:
11 |
12 | - [Google 代码审查指南](docs/review),实则两套指南:
13 | - [代码审查者指南](docs/review/reviewer)
14 | - [代码开发者指南](docs/review/developer)
15 |
16 | ## 术语
17 |
18 | 文档中使用了 Google 内部术语,在此为外部读者澄清:
19 |
20 | - **CL**:代表“变更列表(changelist)”,表示已提交到版本控制或正在进行代码审查的自包含更改。有的组织会将其称为“变更(change)”或“补丁(patch)”。
21 | - **LGTM**:意思是“我觉得不错(Looks Good to Me)”。这是批准 CL 时代码审查者所说的。
22 |
23 | ## 译者序
24 |
25 | 此仓库翻译自 [google/eng-practices](https://github.com/google/eng-practices),目前为止的主要内容为 Google 总结的如何进行 **Code Review(代码审查)** 指南,根据原 Github 仓库的标题判断以后会追加更多 Google 工程实践的内容。
26 |
27 | - 本文档的 Github 地址:,点击页面底部的 `Edit this page` 链接可以编辑页面。
28 | - 其他语言的版本请访问 。
29 | - 感谢 [Ta-Ching Chen](https://github.com/life1347) 的审阅。
30 | - 译者:[Jimmy Song](https://jimmysong.io)
31 | - 本网站使用 [Hugo](https://gohugo.io) 构建。
32 | - 本网站使用 [hugo-book](https://github.com/alex-shpak/hugo-book) 主题。
33 |
34 | ## License
35 |
36 | 本项目中的文档适用于 CC-By 3.0 许可证,该许可证鼓励您共享这些文档。有关详细信息,请参阅 。
37 |
38 |
--------------------------------------------------------------------------------
/content/docs/_index.md:
--------------------------------------------------------------------------------
1 | ---
2 | weight: 1
3 | bookFlatSection: true
4 | title: 谷歌工程实践
5 | ---
6 |
7 | # 谷歌工程实践
8 |
9 | ## 简介 {#intro}
10 |
11 | 代码审查是除了代码作者之外,其他人检查代码的过程。
12 |
13 | Google 通过 Code Review 来维护代码和产品质量。
14 |
15 | 此文档是 Google Code Review 流程和政策的规范说明。
16 |
17 | 此页面是我们进行 Code Review 流程的概述。本指南还有另外两套文档:
18 |
19 | - **如何进行 Code Review**:针对代码审查者的详细指南。
20 | - **代码开发者指南**:针对 CL 开发者的的详细指南。
21 |
--------------------------------------------------------------------------------
/content/docs/review/_index.md:
--------------------------------------------------------------------------------
1 | ---
2 | weight: 1
3 | bookFlatSection: true
4 | title: 开发者代码审查指南
5 | ---
6 |
7 | # 开发者代码审查指南
8 |
9 | ## 简介 {#intro}
10 |
11 | 代码审查是除了代码作者之外,其他人检查代码的过程。
12 |
13 | Google 通过 Code Review 来维护代码和产品质量。
14 |
15 | 此文档是 Google Code Review 流程和政策的规范说明。
16 |
17 | 此页面是我们进行 Code Review 流程的概述。本指南还有另外两套文档:
18 |
19 | - **[如何进行 Code Review](reviewer/)**:针对代码审查者的详细指南。
20 | - **[代码开发者指南](developer/)**:针对 CL 开发者的的详细指南。
21 |
22 | ## 代码审查者应该关注哪些方面? {#look_for}
23 |
24 | 代码审查时应该关注以下方面:
25 |
26 | - **设计**:代码是否经过精心设计并适合您的系统?
27 | - **功能**:代码的行为是否与作者的意图相同?代码是否可以正常响应用户的行为?
28 | - **复杂度**:代码能更简单吗?将来其他开发人员能轻松理解并使用此代码吗?
29 | - **测试**:代码是否具有正确且设计良好的自动化测试?
30 | - **命名**:开发人员是否为变量、类、方法等选择了明确的名称?
31 | - **注释**:注释是否清晰有用?
32 | - **风格**:代码是否遵守了[风格指南](http://google.github.io/styleguide/)?
33 | - **文档**:开发人员是否同时更新了相关文档?
34 |
35 | 参阅**[如何进行 Code Review](reviewer/)** 获取更多资料。
36 |
37 | ### 选择最合适审查者 {#best_reviewers}
38 |
39 | 一般而言,您希望找到能在合理的时间内回复您的评论的最合适的审查者。
40 |
41 | 最合适的审查者应该是能彻底了解和审查您代码的人。他们通常是代码的所有者,可能是 OWNERS 文件中的人,也可能不是。有时 CL 的不同部分可能需要不同的人审查。
42 |
43 | 如果您找到了理想的审查者但他们又没空,那您也至少要抄送他们。
44 |
45 | ### 面对面审查 {#in_person}
46 |
47 | 如果您与有资格做代码审查的人一起结对编程了一段代码,那么该代码将被视为已审查。
48 |
49 | 您还可以进行面对面的代码审查,审查者提问,CL 的开发人员作答。
50 |
51 | ## 参考 {#seealso}
52 |
53 | - [如何进行 Code Review](reviewer/):针对代码审查者的详细指南。
54 | - [代码开发者指南](developer/):针对 CL 开发者的的详细指南。
55 |
--------------------------------------------------------------------------------
/content/docs/review/developer/_index.md:
--------------------------------------------------------------------------------
1 | ---
2 | weight: 2
3 | bookFlatSection: true
4 | title: 代码开发者指南
5 | ---
6 |
7 | # 代码开发者指南
8 |
9 | 本节页面的内容为开发人员进行代码审查的最佳实践。这些指南可帮助您更快地完成审核并获得更高质量的结果。您不必全部阅读它们,但它们适用于每个 Google 开发人员,并且许阅读全文通常会很有帮助。
10 |
11 | - [写好 CL 描述](cl-descriptions)
12 | - [小型 CL](small-cls)
13 | - [如何处理审查者的评论](handling-comments)
14 |
15 | 另请参阅[代码审查者指南](../reviewer/),它为代码审阅者提供了详细的指导。
16 |
17 |
--------------------------------------------------------------------------------
/content/docs/review/developer/cl-descriptions.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 写好 CL 描述
3 | ---
4 |
5 | # 写好 CL 描述
6 |
7 | CL 描述是进行了**哪些更改**以及**为何更改**的公开记录。CL 将作为版本控制系统中的永久记录,可能会在长时期内被除审查者之外的数百人阅读。
8 |
9 | 开发者将来会根据描述搜索您的 CL。有人可能会仅凭有关联性的微弱印象,但没有更多具体细节的情况下,来查找你的改动。如果所有重要信息都在代码而不是描述中,那么会让他们更加难以找到你的 CL 。
10 |
11 | ## 首行 {#firstline}
12 |
13 | - 正在做什么的简短摘要。
14 | - 完整的句子,使用祈使句。
15 | - 后面跟一个空行。
16 |
17 | CL 描述的**第一行**应该是关于这个 CL 是**做什么**的简短摘要,后面跟一个空白行。这是将来大多数的代码搜索者在浏览代码的版本控制历史时,最常被看到的内容,因此第一行应该提供足够的信息,以便他们不必阅读 CL 的整个描述就可以获得这个 CL 实际上是做了什么的信息。
18 |
19 | 按照传统,CL 描述的第一行应该是一个完整的句子,就好像是一个命令(一个命令句)。例如,“**Delete** the FizzBuzz RPC and **replace** it with the new system.”而不是“**Deleting** the FizzBuzz RPC and **replacing** it with the new system.“ 但是,您不必把其余的描述写成祈使句。
20 |
21 | ## Body 是信息丰富的 {#informative}
22 |
23 | 其余描述应该是提供信息的。可能包括对正在解决的问题的简要描述,以及为什么这是最好的方法。如果方法有任何缺点,应该提到它们。如果相关,请包括背景信息,例如错误编号,基准测试结果以及设计文档的链接。
24 |
25 | 即使是小型 CL 也需要注意细节。在 CL 描述中提供上下文以供参照。
26 |
27 | ## 糟糕的 CL 描述 {#bad}
28 |
29 | “Fix bug ”是一个不充分的 CL 描述。什么 bug?你做了什么修复?其他类似的不良描述包括:
30 |
31 | - "Fix build."
32 | - "Add patch."
33 | - "Moving code from A to B."
34 | - "Phase 1."
35 | - "Add convenience functions."
36 | - "kill weird URLs."
37 |
38 | 其中一些是真正的 CL 描述。他们的作者可能认为自己提供了有用的信息,却没有达到 CL 描述的目的。
39 |
40 | ## 好的 CL 描述 {#good}
41 |
42 | 以下是一些很好的描述示例。
43 |
44 | ### 功能更新
45 |
46 | > rpc:删除 RPC 服务器消息 freelist 上的大小限制。
47 | >
48 | > 像 FIzzBuzz 这样的服务器有非常大的消息,并且可以从重用中受益。增大 freelist,添加一个 goroutine,缓慢释放 freelist 条目,以便空闲服务器最终释放所有 freelist 条目。
49 |
50 | 前几个词描述了CL实际上做了什么。其余的描述讨论了正在解决的问题,为什么这是一个很好的解决方案,以及有关具体实现的更多信息。
51 |
52 | ### 重构
53 |
54 | > Construct a Task with a TimeKeeper to use its TimeStr and Now methods.
55 | >
56 | > Add a Now method to Task, so the borglet() getter method can be removed (which was only used by OOMCandidate to call borglet's Now method). This replaces the methods on Borglet that delegate to a TimeKeeper.
57 | >
58 | > Allowing Tasks to supply Now is a step toward eliminating the dependency on Borglet. Eventually, collaborators that depend on getting Now from the Task should be changed to use a TimeKeeper directly, but this has been an accommodation to refactoring in small steps.
59 | >
60 | > Continuing the long-range goal of refactoring the Borglet Hierarchy.
61 |
62 | 第一行描述了 CL 的作用以及改变。其余的描述讨论了具体的实现,CL 的背景,解决方案并不理想,以及未来的可能方向。它还解释了为什么正在进行此更改。
63 |
64 | ### 需要上下文的 小 CL
65 |
66 | > Create a Python3 build rule for status.py.
67 | >
68 | > This allows consumers who are already using this as in Python3 to depend on a rule that is next to the original status build rule instead of somewhere in their own tree. It encourages new consumers to use Python3 if they can, instead of Python2, and significantly simplifies some automated build file refactoring tools being worked on currently.
69 |
70 | 第一句话描述实际做了什么。其余的描述解释了为什么正在进行更改并为审查者提供了大量背景信息。
71 |
72 | ## 在提交 CL 前审查描述
73 |
74 | CL 在审查期间可能会发生重大变更。在提交 CL 之前检查 CL 描述是必要的,以确保描述仍然反映了 CL 的作用。
75 |
76 | 下一篇:[小型 CL](../small-cls)
--------------------------------------------------------------------------------
/content/docs/review/developer/handling-comments.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 如何处理审查者的评论
3 | ---
4 |
5 | # 如何处理审查者的评论
6 |
7 | 当您发送 CL 进行审查时,您的审查者可能会对您的 CL 发表一些评论。以下是处理审查者评论的一些有用信息。
8 |
9 | ## 不是针对您 {#personal}
10 |
11 | 审查的目标是保持代码库和产品的质量。当审查者对您的代码提出批评时,请将其视为在帮助您、代码库和 Google,而不是对您或您的能力的个人攻击。
12 |
13 | 有时,审查者会感到沮丧并在评论中表达他们的挫折感。对于审查者来说,这不是一个好习惯,但作为开发人员,您应该为此做好准备。问问自己,“审查者试图与我沟通的建设性意见是什么?”然后像他们实际说的那样操作。
14 |
15 | **永远不要愤怒地回应代码审查评论。**这严重违反了专业礼仪且将永远存在于代码审查工具中。如果您太生气或恼火而无法好好的回应,那么请离开电脑一段时间,或者做一些别的事情,直到您感到平静,可以礼貌地回答。
16 |
17 | 一般来说,如果审查者没有以建设性和礼貌的方式提供反馈,请亲自向他们解释。如果您无法亲自或通过视频通话与他们交谈,请向他们发送私人电子邮件。以友善的方式向他们解释您不喜欢的东西以及您希望他们以怎样不同的方式来做些什么。如果他们也以非建设性的方式回复此私人讨论,或者没有预期的效果,那么请酌情上报给您的经理。
18 |
19 | ## 修复代码 {#code}
20 |
21 | 如果审查者说他们不了解您的代码中的某些内容,那么您的第一反应应该是澄清代码本身。 如果无法澄清代码,请添加代码注释,以解释代码存在的原因。 只有在想增加的注释看起来毫无意义时,您才能在代码审查工具中进行回复与解释。
22 |
23 | 如果审查者不理解您的某些代码,那么代码的未来读者可能也不会理解。在代码审查工具中回复对未来的代码读者没有帮助,但澄清代码或添加代码注释确可以实实在在得帮助他们。
24 |
25 | ## 自我反思 {#think}
26 |
27 | 编写 CL 可能需要做很多工作。在终于发送一个 CL 用于审查后,我们通常会感到满足的,认为它已经完成,并且非常确定不需要进一步的工作。这通常是令人满意的。因此,当审查者回复对可以改进的事情的评论时,很容易本能地认为评论是错误的,审查者正在不必要地阻止您,或者他们应该让您提交 CL。但是,**无论您目前多么确定**,请花一点时间退一步,考虑审查者是否提供有助于对代码库和对 Google 的有价值的反馈。您首先应该想到的应该是,“审查者是否正确?”
28 |
29 | 如果您无法回答这个问题,那么审查者可能需要澄清他们的意见。
30 |
31 | 如果您已经考虑过并且仍然认为自己是正确的,请随时回答一下为什么您的方法对代码库、用户和/或 Google 更好。通常,审查者实际上是在提供建议,他们希望您自己思考什么是最好的。您可能实际上对审阅者不知道的用户、代码库或 CL 有所了解。所以提供并告诉他们更多的上下文。通常,您可以根据技术事实在自己和审查者之间达成一些共识。
32 |
33 | ## 解决冲突 {#conflicts}
34 |
35 | 解决冲突的第一步应该是尝试与审查者达成共识。 如果您无法达成共识,请参阅“[代码审查标准](../../reviewer/standard)”,该标准提供了在这种情况下遵循的原则。
--------------------------------------------------------------------------------
/content/docs/review/developer/small-cls.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 小型 CL
3 | ---
4 |
5 | # 小型 CL
6 |
7 | ## 为什么提交小型 CL? {#why}
8 |
9 | 小且简单的 CL 是指:
10 |
11 | - **审查更快。**审查者更容易抽多次五分钟时间来审查小型 CL,而不是留出 30 分钟来审查一个大型 CL。
12 | - **审查得更彻底。**如果是大的变更,审查者和提交者往往会因为大量细节的讨论翻来覆去而感到沮丧——有时甚至到了重要点被遗漏或丢失的程度。
13 | - **不太可能引入错误。** 由于您进行的变更较少,您和您的审查者可以更轻松有效地推断 CL 的影响,并查看是否已引入错误。
14 | - **如果被拒绝,减少浪费的工作。** 如果您写了一个巨大的 CL,您的评论者说整个 CL 的方向都错误了,你就浪费了很多精力和时间。
15 | - **更容易合并。** 处理大型 CL 需要很长时间,在合并时会出现很多冲突,并且必须经常合并。
16 | - **更容易设计好。** 打磨一个小变更的设计和代码健康状况比完善一个大变更的所有细节要容易得多。
17 | - **减少对审查的阻碍。** 发送整体变更的自包含部分可让您在等待当前 CL 审核时继续编码。
18 | - **更简单的回滚。** 大型 CL 更有可能触及在初始 CL 提交和回滚 CL 之间更新的文件,从而使回滚变得复杂(中间的 CL 也可能需要回滚)。
19 |
20 | 请注意,**审查者可以仅凭 CL 过大而自行决定完全拒绝您的变更。**通常他们会感谢您的贡献,但要求您以某种方式将其 CL 改成一系列较小的变更。在您编写完变更后,或者需要花费大量时间来讨论为什么审查者应该接受您的大变更,这可能需要做很多工作。首先编写小型 CL 更容易。
21 |
22 | ## 什么是小型 CL? {#what_is_small}
23 |
24 | 一般来说,CL 的正确大小是**自包含的变更**。这意味着:
25 |
26 | - CL 进行了一项最小的变更,**只解决了一件事**。通常只是功能的一部分,而不是一个完整的功能。一般来说,因为编写过小的 CL 而犯错也比过大的 CL 犯错要好。与您的审查者讨论以确定可接受的大小。
27 | - 审查者需要了解的关于 CL 的所有内容(除了未来的开发)都在 CL 的描述、现有的代码库或已经审查过的 CL 中。
28 | - 对其用户和开发者来说,在签入 CL 后系统能继续良好的工作。
29 | - CL 不会过小以致于其含义难以理解。如果您添加新 API,则应在同一 CL 中包含 API 的用法,以便审查者可以更好地了解 API 的使用方式。这也可以防止签入未使用的 API。
30 |
31 | 关于多大算“太大”没有严格的规则。对于 CL 来说,100 行通常是合理的大小,1000 行通常太大,但这取决于您的审查者的判断。变更中包含的文件数也会影响其“大小”。一个文件中的 200 行变更可能没问题,但是分布在 50 个文件中通常会太大。
32 |
33 | 请记住,尽管从开始编写代码开始就您就已经密切参与了代码,但审查者通常不清楚背景信息。对您来说,看起来像是一个可接受的大小的 CL 对您的审查者来说可能是压倒性的。如有疑问,请编写比您认为需要编写的要小的 CL。审查者很少抱怨收到过小的 CL 提交。
34 |
35 | ## 什么时候大 CL 是可以的? {#large_okay}
36 |
37 | 在某些情况下,大变更也是可以接受的:
38 |
39 | - 您通常可以将整个文件的删除视为一行变更,因为审核人员不需要很长时间审核。
40 | - 有时一个大的 CL 是由您完全信任的自动重构工具生成的,而审查者的工作只是检查并确定想要这样的变更。但这些 CL 可以更大,尽管上面的一些警告(例如合并和测试)仍然适用。
41 |
42 | ### 按文件拆分 {#splitting-files}
43 |
44 | 拆分 CL 的另一种方法是对文件进行分组,这些文件需要不同的审查者,否则就是自包含的变更。
45 |
46 | 例如:您发送一个 CL 以修改协议缓冲区,另一个 CL 发送变更使用该原型的代码。您必须在代码 CL 之前提交 proto CL,但它们都可以同时进行审查。如果这样做,您可能希望通知两组审查者审查您编写的其他 CL,以便他们对您的变更具有更充足的上下文。
47 |
48 | 另一个例子:你发送一个 CL 用于代码更改,另一个用于使用该代码的配置或实验;如果需要,这也更容易回滚,因为配置/实验文件有时会比代码变更更快地推向生产。
49 |
50 | ## 分离出重构 {#refactoring}
51 |
52 | 通常最好在功能变更或错误修复的单独 CL 中进行重构。例如,移动和重命名类应该与修复该类中的错误的 CL 不同。审查者更容易理解每个 CL 在单独时引入的更改。
53 |
54 | 但是,修复本地变量名称等小清理可以包含在功能变更或错误修复 CL 中。如果重构大到包含在您当前的 CL 中,会使审查更加困难的话,需要开发者和审查者一起判断是否将其拆开。
55 |
56 | ## 将相关的测试代码保存在同一个 CL 中 {#test_code}
57 |
58 | 避免将测试代码拆分为单独的 CL。验证代码修改的测试应该进入相同的 CL,即使它增加了代码行数。
59 |
60 | 但是,独立的测试修改可以首先进入单独的 CL,类似于[重构指南](#refactoring)。包括:
61 |
62 | - 使用新测试验证预先存在的已提交代码。
63 | - 重构测试代码(例如引入辅助函数)。
64 | - 引入更大的测试框架代码(例如集成测试)。
65 |
66 | ## 不要破坏构建 {#break}
67 |
68 | 如果您有几个相互依赖的 CL,您需要找到一种方法来确保在每次提交 CL 后整个系统能够继续运作。否则可能会在您的 CL 提交的几分钟内打破所有开发人员的构建(如果您之后的 CL 提交意外出错,时间可能会甚至更长)。
69 |
70 | ## 如果不能让它足够小 {#cant}
71 |
72 | 有时你会遇到看起来您的 CL 必须如此庞大,但这通常很少是正确的。习惯于编写小型 CL 的提交者几乎总能找到将功能分解为一系列小变更的方法。
73 |
74 | 在编写大型 CL 之前,请考虑在重构 CL 之前是否可以为更清晰的实现铺平道路。与你的同伴聊聊,看看是否有人想过如何在小型 CL 中实现这些功能。
75 |
76 | 如果以上的努力都失败了(这应该是非常罕见的),那么请在事先征得审查者的同意后提交大型 CL,以便他们收到有关即将发生的事情的警告。在这种情况下,做好完成审查过程需要很长一段时间的准备,对不引入错误保持警惕,并且在编写测试时要更下功夫。
77 |
78 | 下一篇:[如何处理审查者评论](../handling-comments)
79 |
--------------------------------------------------------------------------------
/content/docs/review/emergencies.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 紧急情况
3 | ---
4 |
5 | # 紧急情况
6 |
7 | 有时候紧急 CL 必须尽快通过 code review 过程。
8 |
9 | ## 什么是紧急情况? {#what}
10 |
11 | 紧急 CL 是这样的**小**更新:允许主要发布继续而不是回滚,修复显著影响用户生产的错误,处理紧迫的法律问题,关闭主要安全漏洞等。
12 |
13 | 在紧急情况下,我们确实关心 Code Review 的整体速度,而不仅仅是响应的速度。仅在这种情况下,审查人员应该更关心审查的速度和代码的正确性(是否解决了紧急情况?)。此外(显然)这类状况的审查应该优先于所有其他 code reivew。
14 |
15 | 但是,在紧急情况解决后,您应该再次查看紧急 CL 并进行[更彻底的审查](reviewer/looking-for)。
16 |
17 | ## 什么不是紧急情况? {#not}
18 |
19 | 需要说明的是,以下情况并非紧急情况:
20 |
21 | - 想要在本周而不是下周推出(除非有一些实际[硬性截止日期](#deadlines),例如合作伙伴协议)。
22 | - 开发人员已经在很长一段时间内完成了一项功能想要获得 CL。
23 | - 审查者都在另一个时区,目前是夜间或他们已离开现场。
24 | - 现在是星期五,在开发者在过周末之前获得这个 CL 会很棒。
25 | - 今天因为[软(非硬)截止日期](#deadlines),经理表示必须完成此审核并签入 CL。
26 | - 回滚导致测试失败或构建破坏的 CL。
27 |
28 | 等等。
29 |
30 | ## 什么是 Hard Deadline? {#deadlines}
31 |
32 | 硬性截止日期(Hard Deadline)是指如果你错过它会发生灾难性的事情。例如:
33 |
34 | - 对于合同义务,必须在特定日期之前提交 CL。
35 | - 如果在某个日期之前没有发布,您的产品将在市场上完全失败。
36 | - 一些硬件制造商每年只发送一次新硬件。如果您错过了向他们提交代码的截止日期,那么这可能是灾难性的,具体取决于您尝试发布的代码类型。
37 |
38 | 延迟发布一周并不是灾难性的。错过重要会议可能是灾难性的,但往往不是。
39 |
40 | 大多数截止日期都是软截止日期,而非最后期限。软截止日期表示希望在特定时间内完成某项功能。它们很重要,但你不应该以牺牲代码健康为前提来达到。
41 |
42 | 如果您的发布周期很长(几周),那么在下一个周期之前就可能会牺牲代码审查质量来获取功能。然而,如果重复这种模式,往往会给项目建立压倒性技术债务。如果开发人员在周期结束时经常提交 CL,只需要进行表面评审就必须“进入”,那么团队应该修改其流程,以便在周期的早期发生大的功能变更,并有足够的时间进行良好的审查。
43 |
--------------------------------------------------------------------------------
/content/docs/review/reviewer/_index.md:
--------------------------------------------------------------------------------
1 | ---
2 | weight: 3
3 | bookFlatSection: true
4 | title: 代码审查者指南
5 | ---
6 |
7 | # 代码审查者指南
8 |
9 | 本节是基于过往经验编写的 Code Review 最佳方式建议。其中分为了很多独立的部分,共同组成完整的文档。虽然您不必阅读文档,但通读一遍会对您自己和团队很有帮助。
10 |
11 | - [Code Review 标准](standard)
12 | - [Code Review 要点](looking-for)
13 | - [查看 CL 的步骤](navigate)
14 | - [Code Review 速度](speed)
15 | - [如何撰写 Code Review 评论](comments)
16 | - [处理 Code Review 中的抵触](pushback)
17 |
18 | 另请参阅[代码开发者指南](../developer/),该指南为正在进行 Code Review 的开发开发者提供详细指导。
--------------------------------------------------------------------------------
/content/docs/review/reviewer/comments.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 如何撰写 Code Review 评论
3 | ---
4 |
5 | # 如何撰写 Code Review 评论
6 |
7 | ## 总结
8 |
9 | - 保持友善。
10 | - 解释你的推理。
11 | - 在给出明确的指示与只指出问题并让开发人员自己决定间做好平衡。
12 | - 鼓励开发人员简化代码或添加代码注释,而不仅仅是向你解释复杂性。
13 |
14 | ## 礼貌
15 |
16 | 一般而言,对于那些正在被您审查代码的人,除了保持有礼貌且尊重以外,重要的是还要确保您(的评论)是非常清楚且有帮助的。你并不总是必须遵循这种做法,但在说出可能令人不安或有争议的事情时你绝对应该使用它。 例如:
17 |
18 | 糟糕的示例:“为什么这里**你**使用了线程,显然并发并没有带来什么好处?”
19 |
20 | 好的示例:“这里的并发模型增加了系统的复杂性,但没有任何实际的性能优势,因为没有性能优势,最好是将这些代码作为单线程处理而不是使用多线程。”
21 |
22 | ## 解释为什么{#why}
23 |
24 | 关于上面的“好”示例,您会注意到的一件事是,它可以帮助开发人员理解您发表评论的原因。 并不总是需要您在审查评论中包含此信息,但有时候提供更多解释,对于表明您的意图,您在遵循的最佳实践,或为您建议如何提高代码健康状况是十分恰当的。
25 |
26 | ## 给予指导 {#guidance}
27 |
28 | **一般来说,修复 CL 是开发人员的责任,而不是审查者。** 您无需为开发人员详细设计解决方案或编写代码。
29 |
30 | 但这并不意味着审查者应该没有帮助。一般来说,您应该在指出问题和提供直接指导之间取得适当的平衡。指出问题并让开发人员做出决定通常有助于开发人员学习,并使代码审查变得更容易。它还可能产生更好的解决方案,因为开发人员比审查者更接近代码。
31 |
32 | 但是,有时直接说明,建议甚至代码会更有帮助。代码审查的主要目标是尽可能获得最佳 CL。第二个目标是提高开发人员的技能,以便他们随着时间的推移需要的审查越来越少。
33 |
34 | ## 接受解释 {#explanations}
35 |
36 | 如果您要求开发人员解释一段您不理解的代码,那通常会导致他们**更清楚地重写代码**。偶尔,在代码中添加注释也是一种恰当的响应,只要它不仅仅是解释过于复杂的代码。
37 |
38 | **仅在代码审查工具中编写的解释对未来的代码阅读者没有帮助。**这仅在少数情况下是可接受的,例如当您查看一个您不熟悉的领域时,开发人员会用来向您解释普通读者已经知道的内容。
39 |
40 | 下一篇:[处理 Code Review 中的拖延](../pushback)
41 |
42 |
--------------------------------------------------------------------------------
/content/docs/review/reviewer/looking-for.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Code Review 要点
3 | ---
4 |
5 | # Code Review 要点
6 |
7 | 注意:在考虑这些要点时,请谨记 “[Code Review 标准](../standard)”。
8 |
9 | ## 设计
10 |
11 | 审查中最重要的是 CL 的整体设计。CL 中各种代码的交互是否有意义?此变更是属于您的代码库(codebase)还是属于库(library)?它是否与您系统的其他部分很好地集成?现在是添加此功能的好时机吗?
12 |
13 | ## 功能
14 |
15 | 这个 CL 是否符合开发者的意图?开发者的意图对代码的用户是否是好的? “用户”通常都是最终用户(当他们受到变更影响时)和开发者(将来必须“使用”此代码)。
16 |
17 | 大多数情况下,我们希望开发者能够很好地测试 CL,以便在审查时代码能够正常工作。但是,作为审查者,仍然应该考虑边缘情况,寻找并发问题,尝试像用户一样思考,并确保您单纯透过阅读方式审查时,代码没有包含任何 bug。
18 |
19 | 当要检查 CL 的行为会对用户有重大影响时,验证 CL 的变化将变得十分重要。例如 **UI 变更**。当您只是阅读代码时,很难理解某些变更会如何影响用户。如果在 CL 中打 patch 或自行尝试这样的变更太不方便,您可以让开发人员为您提供功能演示。
20 |
21 | 另一个在代码审查期间特别需要考虑功能的时机,就是如果 CL 中存在某种**并行编程**,理论上可能导致死锁或竞争条件。通过运行代码很难检测到这些类型的问题,并且通常需要某人(开发者和审查者)仔细思考它们以确保不会引入问题。 (请注意,这也是在可能出现竞争条件或死锁的情况下,不使用并发模型的一个很好的理由——它会使代码审查或理解代码变得非常复杂。)
22 |
23 | ## 复杂度
24 |
25 | CL 是否已经超过它原本所必须的复杂度?针对任何层级的 CL 请务必确认这点——每行程序是否过于复杂? 功能太复杂了吗?类太复杂了吗? “太复杂”通常意味着**“阅读代码的人无法快速理解**。”也可能意味着**“开发者在尝试调用或修改此代码时可能会引入错误。”**
26 |
27 | 其中一种复杂性就是**过度工程(over-engineering)**,如开发人员使代码过度通用,超过它原本所需的,或者添加系统当前不需要的功能。审查者应特别警惕过度工程。未来的问题应该在它实际到达后解决,且届时才能更清晰的看到其真实样貌及在现实环境里的需求,鼓励开发人员解决他们现在需要解决的问题,而不是开发人员推测**可能**需要在未来解决的问题。
28 |
29 | ## 测试
30 |
31 | 将要求单元、集成或端到端测试视为应该做的适当变更。通常,除非 CL 处理[紧急情况](../../emergencies),否则应在与生产代码相同的 CL 中添加测试。
32 |
33 | 确保 CL 中的测试正确,合理且有用。测试并非用来测试自己本身,且我们很少为测试编写测试——人类必须确保测试有效。
34 |
35 | 当代码被破坏时,测试是否真的会失败? 如果代码发生变化时,它们会开始产生误报吗? 每个测试都会做出简单而有用的断言吗? 不同测试方法的测试是否适当分开?
36 |
37 | 请记住,测试也是必须维护的代码。不要仅仅因为它们不是主二进制文件的一部分而接受测试中的复杂性。
38 |
39 | ## 命名
40 |
41 | 开发人员是否为所有内容选择了好名字? 一个好名字应该足够长,可以完全传达项目的内容或作用,但又不会太长,以至于难以阅读。
42 |
43 | ## 注释
44 |
45 | 开发者是否用可理解的英语撰写了清晰的注释?所有注释都是必要的吗?通常,注释**解释为什么**某些代码存在时很有用,且不应该用来解释某些代码正在做什么。如果代码无法清楚到去解释自己时,那么代码应该变得更简单。有一些例外(正则表达式和复杂算法通常会从解释他们正在做什么事情的注释中获益很多),但大多数注释都是针对代码本身可能无法包含的信息,例如决策背后的推理。
46 |
47 | 查看此 CL 之前的注释也很有帮助。 也许有一个 TODO 现在可以删除,一个注释建议不要进行这种改变,等等。
48 |
49 | 请注意,注释与类、模块或函数的**文档**不同,它们应该代表一段代码的目的,如何使用它,以及使用时它的行为方式。
50 |
51 | ## 风格
52 |
53 | Google 提供了所有主要语言的[风格指南](http://google.github.io/styleguide/),甚至包括大多数小众语言。确保 CL 遵循适当的风格指南。
54 |
55 | 如果您想改进风格指南中没有的一些样式点,请在评论前加上“Nit:”,让开发人员知道这是您认为可改善代码的小瑕疵,但不是强制性的。不要仅根据个人风格偏好阻止提交 CL。
56 |
57 | CL 的作者不应在主要风格变更中,包括与其他种类的变更。它会使得很难看到 CL 中的变更了什么,使合并和回滚更复杂,并导致其他问题。例如,如果作者想要重新格式化整个文件,让他们只将重新格式化变为一个 CL,其后再发送另一个包含功能变更的 CL。
58 |
59 | ## 文档
60 |
61 | 如果 CL 变更了用户构建、测试、交互或发布代码的方式,请检查相关文档是否有更新,包括 README、g3doc 页面和任何生成的参考文档。如果 CL 删除或弃用代码,请考虑是否也应删除文档。 如果缺少文档,请询问。
62 |
63 | ## 每一行 {#every_line}
64 |
65 | 查看分配给您审查的**每行**代码。有时如数据文件、生成的代码或大型数据结构等东西,您可以快速扫过。但不要快速扫过人类编写的类、函数或代码块,并假设其中的内容是 OK 的。显然,某些代码需要比其他代码更仔细的审查——这是您必须做出的判断——但您至少应该确定您**理解**所有代码正在做什么。
66 |
67 | 如果您觉得这些代码太难以阅读了并减慢您审查的速度,您应该在您尝试继续审核前要让开发者知道这件事,并等待他们为程序做出解释、澄清。在 Google,我们聘请了优秀的软件工程师,您就是其中之一。如果您无法理解代码,那么很可能其他开发人员也不会。因此,当您要求开发人员澄清此代码时,您也会帮助未来的开发人员理解这些代码。
68 |
69 | 如果您了解代码但觉得没有资格做某些部分的审查,请确保 CL 上有一个合格的审查人,特别是对于安全性、并发性、可访问性、国际化等复杂问题。
70 |
71 | ## 上下文
72 |
73 | 在广泛的上下文下查看 CL 通常很有帮助。通常,代码审查工具只会显示变更的部分的周围的几行。有时您必须查看整个文件以确保变更确实有意义。例如,您可能只看到添加了四行新代码,但是当您查看整个文件时,您会看到这四行是添加在一个 50 行的方法里,现在确实需要将它们分解为更小的方法。
74 |
75 | 在整个系统的上下文中考虑 CL 也很有用。 这个 CL 是否改善了系统的代码健康状况,还是使整个系统更复杂,测试更少等等?**不要接受降低系统代码运行状况的 CL**。大多数系统通过许多小的变化而变得复杂,因此防止新变更引入即便很小的复杂性也非常重要。
76 |
77 | ## 好的事情 {#good_things}
78 |
79 | 如果您在 CL 中看到一些不错的东西,请告诉开发者,特别是当他们以一种很好的方式解决了您的的一个评论时。代码审查通常只关注错误,但也应该为良好实践提供鼓励。在指导方面,比起告诉他们他们做错了什么,有时更有价值的是告诉开发人员他们做对了什么。
80 |
81 | ## 总结
82 |
83 | 在进行代码审查时,您应该确保:
84 |
85 | - 代码设计精良。
86 | - 该功能对代码用户是有好处的。
87 | - 任何 UI 变更都是合理的且看起来是好的。
88 | - 其中任何并行编程都是安全的。
89 | - 代码并不比它需要的复杂。
90 | - 开发人员没有实现他们将来**可能**需要,但不知道他们现在是否需要的东西。
91 | - 代码有适当的单元测试。
92 | - 测试精心设计。
93 | - 开发人员使用了清晰的名称。
94 | - 注释清晰有用,且大多用来解释**为什么**而不是**做什么**。
95 | - 代码有适当记录成文件(通常在 g3doc 中)。
96 | - 代码符合我们的风格指南。
97 |
98 | 确保查看您被要求查看的**每一行**代码,查看**上下文**,确保您**提高代码健康状况**,并赞扬开发人员所做的**好事**。
99 |
100 | 下一篇:[查看 CL 的步骤](../navigate)
101 |
--------------------------------------------------------------------------------
/content/docs/review/reviewer/navigate.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 查看 CL 的步骤
3 | ---
4 |
5 | # 查看 CL 的步骤
6 |
7 | ## 总结
8 |
9 | 现在您已经知道了 [Code Review 要点](../looking-for),那么管理分布在多个文件中的评论的最有效方法是什么?
10 |
11 | 1. 变更是否有意义?它有很好的描述吗?
12 | 1. 首先看一下变更中最重要的部分。整体设计得好吗?
13 | 1. 以适当的顺序查看 CL 的其余部分。
14 |
15 | ## 第一步:全面了解变更 {#step_one}
16 |
17 | 查看 [CL 描述](../../developer/cl-descriptions)和 CL 大致上用来做什么事情。这种变更是否有意义?如果在最初不应该发生这样的变更,请立即回复,说明为什么不应该进行变更。当您拒绝这样的变更时,向开发人员建议应该做什么也是一个好主意。
18 |
19 | 例如,您可能会说“看起来你已经完成一些不错的工作,谢谢!但实际上,我们正朝着删除您在这里修改的 FooWidget 系统的方向演进,所以我们不想对它进行任何新的修改。不过,您来重构下新的 BarWidget 类怎么样?“
20 |
21 | 请注意,审查者不仅拒绝了当前的 CL 并提供了替代建议,而且他们保持礼貌地这样做。这种礼貌很重要,因为我们希望表明,即使不同意,我们也会相互尊重。
22 |
23 | 如果您获得了多个您不想变更的 CL,您应该考虑重整开发团队的开发过程或外部贡献者的发布过程,以便在编写CL之前有更多的沟通。最好在他们完成大量工作之前说“不”,避免已经投入心血的工作现在必须被抛弃或彻底重写。
24 |
25 | ## 第二步:检查 CL 的主要部分 {#step_two}
26 |
27 | 查找作为此 CL “主要”部分的文件。通常,包含大量的逻辑变更的文件就是 CL 的主要部分。先看看这些主要部分。这有助于为 CL 的所有较小部分提供上下文,并且通常可以加速代码审查。如果 CL 太大而无法确定哪些部分是主要部分,请向开发人员询问您应该首先查看的内容,或者要求他们[将 CL 拆分为多个 CL](../../developer/small-cls)。
28 |
29 | 如果在该部分发现存在一些主要的设计问题时,即使没有时间立即查看 CL 的其余部分,也应立即留下评论告知此问题。因为事实上,因为该设计问题足够严重的话,继续审查其余部分很可能只是浪费宝贵的时间,因为其他正在审查的程序可能都将无关或消失。
30 |
31 | 立即发送这些主要设计评论非常重要,有两个主要原因:
32 |
33 | - 通常开发者在发出 CL 后,在等待审查时立即开始基于该 CL 的新工作。如果您正在审查的 CL 中存在重大设计问题,那么他们以后的 CL 也必须要返工。您应该赶在他们在有问题的设计上做了太多无用功之前通知他们。
34 | - 主要的设计变更比起小的变更来说需要更长的时间才能完成。开发人员基本都有截止日期;为了完成这些截止日期并且在代码库中仍然保有高质量代码,开发人员需要尽快开始 CL 的任何重大工作。
35 |
36 | ## 第三步:以适当的顺序查看 CL 的其余部分 {#step_three}
37 |
38 | 一旦您确认整个 CL 没有重大的设计问题,试着找出一个逻辑顺序来查看文件,同时确保您不会错过查看任何文件。 通常在查看主要文件之后,最简单的方法是按照代码审查工具向您提供的顺序浏览每个文件。有时在阅读主代码之前先阅读测试也很有帮助,因为这样您就可以了解该变更应当做些什么。
39 |
40 | 下一篇:[Code Review 速度](../speed)
41 |
--------------------------------------------------------------------------------
/content/docs/review/reviewer/pushback.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 处理 Code Review 中的拖延
3 | ---
4 |
5 | # 处理 Code Review 中的拖延
6 |
7 | 有时开发人员会拖延(Pushback)代码审查。他们要么不同意您的建议,要么抱怨您太严格。
8 |
9 | ## 谁是对的? {#who_is_right}
10 |
11 | 当开发人员不同意您的建议时,请先花点时间考虑一下是否正确。通常,他们比你更接近代码,所以他们可能真的对它的某些方面有更好的洞察力。他们的论点有意义吗?从代码健康的角度来看它是否有意义?如果是这样,让他们知道他们是对的,把问题解决。
12 |
13 | 但是,开发人员并不总是对的。在这种情况下,审查人应进一步解释为什么认为他们的建议是正确的。好的解释在描述对开发人员回复的理解的同时,还会解释为什么请求更改。
14 |
15 | 特别是,当审查人员认为他们的建议会改善代码健康状况时,他们应该继续提倡更改,如果他们认为最终的代码质量改进能够证明所需的额外工作是合理的。**提高代码健康状况往往只需很小的几步。**
16 |
17 | 有时需要几轮解释一个建议才能才能让对方真正理解你的用意。只要确保始终保持[礼貌](../comments#courtesy),让开发人员知道你有听到他们在说什么,只是你不同意该论点而已。
18 |
19 | ## 沮丧的开发者 {#upsetting_developers}
20 |
21 | 审查者有时认为,如果审查者人坚持改进,开发人员会感到不安。有时候开发人员会感到很沮丧,但这样的感觉通常只会持续很短的时间,后来他们会非常感谢您在提高代码质量方面给他们的帮助。通常情况下,如果您在评论中表现得很有[礼貌](../comments#courtesy),开发人员实际上根本不会感到沮丧,这些担忧都仅存在于审核者心中而已。开发者感到沮丧通常更多地与[评论的写作方式](../comments#courtesy)有关,而不是审查者对代码质量的坚持。
22 |
23 | ## 稍后清理 {#later}
24 |
25 | 开发人员拖延的一个常见原因是开发人员(可以理解)希望完成任务。他们不想通过另一轮审查来完成该 CL。所以他们说会在以后的 CL 中清理一些东西,所以您现在应该 LGTM 这个 CL。一些开发人员非常擅长这一点,并会立即编写一个修复问题的后续 CL。但是,经验表明,在开发人员编写原始 CL 后,经过越长的时间这种清理发生的可能性就越小。实际上,通常除非开发人员在当前 CL 之后立即进行清理,否则它就永远不会发生。这不是因为开发人员不负责任,而是因为他们有很多工作要做,清理工作在其他工作中被丢失或遗忘。因此,在代码进入代码库并“完成”之前,通常最好坚持让开发人员现在清理他们的 CL。让人们“稍后清理东西”是代码库质量退化的常见原因。
26 |
27 | 如果 CL 引入了新的复杂性,除非是[紧急情况]({{< relref "/docs/review/emergencies" >}}),否则必须在提交之前将其清除。如果 CL 暴露了相关的问题并且现在无法解决,那么开发人员应该将 bug 记录下来并分配给自己,避免后续被遗忘。又或者他们可以选择在程序中留下 TODO 的注释并连结到刚记录下的 bug。
28 |
29 | ## 关于严格性的抱怨 {#strictness}
30 |
31 | 如果您以前有相当宽松的代码审查,并转而进行严格的审查,一些开发人员会抱怨得非常大声。通常提高代码审查的[速度](../speed)会让这些抱怨逐渐消失。
32 |
33 | 有时,这些投诉可能需要数月才会消失,但最终开发人员往往会看到严格的代码审查的价值,因为他们会看到代码审查帮助生成的优秀代码。而且一旦发生某些事情时,最响亮的抗议者甚至可能会成为你最坚定的支持者,因为他们会看到审核变严格后所带来的价值。
34 |
35 | ## 解决冲突 {#conflicts}
36 |
37 | 如果上述所有操作仍无法解决您与开发人员之间的冲突,请参阅 “[Code Review 标准](../standard)”以获取有助于解决冲突的指导和原则。
--------------------------------------------------------------------------------
/content/docs/review/reviewer/speed.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Code Review 速度
3 | ---
4 |
5 | # Code Review 速度
6 |
7 | ## 为什么尽快进行 Code Review? {#why}
8 |
9 | **在Google,我们优化了开发团队共同开发产品的速度**,而不是优化单个开发者编写代码的速度。个人开发的速度很重要,它并不如整个团队的速度那么重要。
10 |
11 | 当代码审查很慢时,会发生以下几件事:
12 |
13 | * **整个团队的速度降低了。**是的,对审查没有快速响应的个人的确完成了其他工作。但是,对于团队其他人来说重要的新功能与缺陷修復将会被延迟数天、数周甚至数月,只因为每个 CL 正在等待审查和重新审查。
14 | * **开发者开始抗议代码审查流程。**如果审查者每隔几天只响应一次,但每次都要求对 CL 进行重大更改,那么开发者可能会变得沮丧。通常,开发者将表达对审查者过于“严格”的抱怨。如果审查者请求相同实质性更改(确实可以改善代码健康状况),但每次开发者进行更新时都会快速响应,则抱怨会逐渐消失。**大多数关于代码审查流程的投诉实际上是通过加快流程来解决的。**
15 | * **代码健康状况可能会受到影响。**如果审查速度很慢,则造成开发者提交不尽如人意的 CL 的压力会越来越大。审查太慢还会阻止代码清理、重构以及对现有 CL 的进一步改进。
16 |
17 | ## Code Review 应该有多快? {#fast}
18 |
19 | 如果您没有处于重点任务的中,那么您应该在**收到代码审查后尽快开始**。
20 |
21 | **一个工作日**是应该响应代码审查请求所需的最长时间(即第二天早上的第一件事)。
22 |
23 | 遵循这些指导意味着典型的 CL 应该在一天内进行多轮审查(如果需要)。
24 |
25 | ## 速度 vs. 中断 {#interruption}
26 |
27 | 有一种情况下个人速度胜过团队速度。**如果您正处于重点任务中,例如编写代码,请不要打断自己进行代码审查。**研究表明,开发人员在被打断后需要很长时间才能恢复到顺畅的开发流程中。因此,编写代码时打断自己实际上比让另一位开发人员等待代码审查的代价更加昂贵。
28 |
29 | 相反,在回复审查请求之前,请等待工作中断点。可能是当你的当前编码任务完成,午餐后,从会议返回,从厨房回来等等。
30 |
31 | ## 快速响应 {#responses}
32 |
33 | 当我们谈论代码审查的速度时,我们关注的是响应时间,而不是 CL 需要多长时间才能完成整个审查并提交。理想情况下,整个过程也应该是快速的,**快速的个人响应比整个过程快速发生更为重要**。
34 |
35 | 即使有时需要很久才能完成整个审查流程,但在整个过程中获得审查者的快速响应可以显着减轻开发人员对“慢速”代码审查感到的挫败感。
36 |
37 | 如果您太忙而无法对 CL 进行全面审查,您仍然可以发送快速回复,让开发人员知道您什么时候可以开始,或推荐其他能够更快回复的审查人员,或者[提供一些大体的初步评论](../navigate)。 (注意:这并不意味着您应该中断编码,即使发送这样的响应,也要在工作中的合理断点处发出响应。)
38 |
39 | 重要的是,审查人员要花足够的时间进行审查,确信他们的“LGTM”意味着“此代码符合我们的[标准](../standard)。”但是,理想情况下,个人反应仍然应该很[快](#fast)。
40 |
41 | ## 跨时区审查 {#tz}
42 |
43 | 在处理时区差异时,尝试在他们还在办公室时回复作者。 如果他们已经下班回家了,那么请确保在第二天回到办公室之前完成审查。
44 |
45 | ## 带评论的 LGTM {#lgtm-with-comments}
46 |
47 | 为了加快代码审查,在某些情况下,即使他们也在 CL 上留下未解决的评论,审查者也应该给予 LGTM/Approval,这可以是以下任何一种情况:
48 |
49 | - 审查者确信开发人员将适当地处理所有审查者的剩余评论。
50 | - 其余的更改很小,不必由开发者完成。
51 |
52 | 如果不清楚的话,审查者应该指定他们想要哪些选项。
53 |
54 | 当开发者和审查者处于不同的时区时,带评论的 LGTM 尤其值得考虑,否则开发者将等待一整天才能获得 “LGTM,Approval”。
55 |
56 | ## 大型 CL {#large}
57 |
58 | 如果有人向您发送了代码审查太大,您不确定何时有时间查看,那么您应该要求开发者[将 CL 拆分为几个较小的 CL](../../developer/small-cls) 而不是一次审查的一个巨大的 CL。这通常可行,对审查者非常有帮助,即使需要开发人员的额外工作。
59 |
60 | 如果 CL 无法分解为较小的 CL,并且您没有时间快速查看整个内容,那么至少要对 CL 的整体设计写一些评论并将其发送回开发人员以进行改进。作为审查者,您的目标之一应该在不牺牲代码健康状况的前提下,始终减少开发者能够快速采取某种进一步的操作的阻力。
61 |
62 | ## 代码审查随时间推移而改进 {#time}
63 |
64 | 如果您遵循这些准则,并且您对代码审查非常严格,那么您应该会发现整个代码审核流程会随着时间的推移而变得越来越快。开发者可以了解健康代码所需的内容,并向您发送从一开始就很棒的 CL,且需要的审查时间越来越短。审查者学会快速响应,而不是在审查过程中添加不必要的延迟。但是,从长远来看,**不要为了提高想象中的代码审查速度,而在[代码审查标准](../standard)或质量方面妥协,实际上这样做对于长期来说不会有任何帮助。**
65 |
66 | ## 紧急情况
67 |
68 | 还有一些[紧急情况](../../emergencies),CL 必须非常快速地通过整个审查流程,并且质量准则将放宽。请查看[什么是紧急情况?](../../emergencies#what) 中描述的哪些情况属于紧急情况,哪些情况不属于紧急情况。
69 |
70 | 下一篇:[如何撰写 Code Review 评论](../comments)
--------------------------------------------------------------------------------
/content/docs/review/reviewer/standard.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Code Review 标准
3 | ---
4 |
5 | # Code Review 标准
6 |
7 | 代码审查的主要目的是确保逐步改善 Google 代码库的整体健康状况。代码审查的所有工具和流程都是为此而设计的。
8 |
9 | 为了实现此目标,必须做出一系列权衡。
10 |
11 | 首先,开发人员必须能够对任务进行**改进**。如果开发者从未向代码库提交过代码,那么代码库的改进也就无从谈起。此外,如果审核人员对代码吹毛求疵,那么开发人员以后也很难再做出改进。
12 |
13 | 另外,审查者有责任确保随着时间的推移,CL 的质量不会使代码库的整体健康状况下降。这可能很棘手,因为通常情况下,代码库健康状况会随着时间的而下降,特别是在对团队有严格的时间要求时,团队往往会采取捷径来达成他们的目标。
14 |
15 | 此外,审查者应对正在审核的代码负责并拥有所有权。审查者希望确保代码库保持一致、可维护及 [Code Review 要点](../looking-for)中所提及的所有其他内容。
16 |
17 | 因此,我们将以下规则作为 Code Review 中期望的标准:
18 |
19 | **一般来说,审核人员应该倾向于批准 CL,只要 CL 确实可以提高系统的整体代码健康状态,即使 CL 并不完美。**
20 |
21 | 这是所有 Code Review 指南中的**高级**原则。
22 |
23 | 当然,也有一些限制。例如,如果 CL 添加了审查者认为系统中不需要的功能,那么即使代码设计良好,审查者依然可以拒绝批准它。
24 |
25 | 此处有一个关键点就是没有“完美”的代码,只有**更好的**代码。审查者不该要求开发者在批准程序前仔细清理、润色 CL 每个角落。相反,审查者应该在变更的重要性与取得进展之间取得平衡。审查者不应该追求完美,而应是追求持续改进。不要因为一个 CL不是“完美的”,就将可以提高系统的可维护性、可读性和可理解性的 CL 延迟数天或数周才批准。
26 |
27 | 审核者应该随时在可以改善的地方留下审核评论,但如果评论不是很重要,请在评论语句前加上“Nit:”之类的内容,让开发者知道这条评论是用来指出可以润色的地方,而他们可以选择是否忽略。
28 |
29 | 注意:本文档中没有任何内容证明检查 CL 肯定会使系统的整体代码健康状况恶化。您会做这种事情应该只有在[紧急情况](../../emergencies)时。
30 |
31 | ## 指导
32 |
33 | 代码审查具有向开发人员传授语言、框架或通用软件设计原则新内容的重要功能。留下评论可以帮助开发人员学习新东西,这总归是很好的。分享知识是随着长年累月改善系统代码健康状况的一部分。请记住,如果您的评论纯粹是教育性的,且对于本文档中描述的标准并不重要,请在其前面添加“Nit:”或以其他方式表明作者不必在此 CL 中解决它。
34 |
35 | ## 原则 {#principles}
36 |
37 | * 基于技术事实和数据否决意见和个人偏好。
38 | * 关于代码风格问题,[风格指南](http://google.github.io/styleguide/)是绝对权威。任何不在风格指南中的纯粹风格点(例如空白等)都是个人偏好的问题。代码风格应该与风格指南中的一致。如果没有以前的风格,请接受作者的风格。
39 | * **软件设计方面几乎不是纯粹的风格或个人偏好问题。**软件设计基于基本原则且应该权衡这些原则,而不仅仅是个人意见。有时候会有多种有效的选择。如果作者可以证明(通过数据或基于可靠的工程原理)该方法同样有效,那么审查者应该接受作者的偏好。否则,就要取决于软件设计的标准原则。
40 | * 如果没有其他适用规则,则审查者可以要求作者与当前代码库中的内容保持一致,只要不恶化系统的整体代码健康状况即可。
41 |
42 | ## 解决冲突 {#conflicts}
43 |
44 | 如果在代码审查过程中有任何冲突,第一步应该始终是开发人员和审查者根据本文档中的 [CL 开发者指南](../../developer/)和[审查者指南](../../)达成共识。
45 |
46 | 当达成共识变得特别困难时,审阅者和开发者可以进行面对面的会议,或者有 VC 参与调停,而不仅仅是试着通过代码审查评论来解决冲突。 (但是,如果您这样做了,请确保在 CL 的评论中记录讨论结果,以供将来的读者使用。)
47 |
48 | 如果这样还不能解决问题,那么解决该问题最常用方法是将问题升级。通常是将问题升级为更广泛的团队讨论,有一个 TL 权衡,要求维护人员对代码作出决定,或要求工程经理的帮助。 **不要因为 CL 的开发者和审查者不能达成一致,就让 CL 在那里卡壳。**
49 |
50 | 下一篇:[Code Review 要点](../looking-for)
51 |
--------------------------------------------------------------------------------
/content/menu/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | headless: true
3 | ---
4 |
5 | - [**首页**](https://jimmysong.io)
6 | - [**谷歌代码审查指南**]({{< relref "/docs/review" >}})
7 | - [**代码审查者指南**]({{< relref "/docs/review/reviewer" >}})
8 | - [Code Review 标准]({{< relref "/docs/review/reviewer/standard" >}})
9 | - [Code Review 要点]({{< relref "/docs/review/reviewer/looking-for" >}})
10 | - [查看 CL 的步骤]({{< relref "/docs/review/reviewer/navigate" >}})
11 | - [Code Review 速度]({{< relref "/docs/review/reviewer/speed" >}})
12 | - [如何撰写 Code Review 评论]({{< relref "/docs/review/reviewer/comments" >}})
13 | - [处理 Code Review 中的拖延]({{< relref "/docs/review/reviewer/pushback" >}})
14 | - [**代码开发者指南**]({{< relref "/docs/review/developer" >}})
15 | - [写好 CL 描述]({{< relref "/docs/review/developer/cl-descriptions" >}})
16 | - [小型 CL]({{< relref "/docs/review/developer/small-cls" >}})
17 | - [如何处理审查者的评论]({{< relref "/docs/review/developer/handling-comments" >}})
18 |
--------------------------------------------------------------------------------
/cover-thumbnail.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootsongjc/eng-practices/b79a51589a24d84d6060e2ac8dd627a47cd4a431/cover-thumbnail.jpg
--------------------------------------------------------------------------------
/cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootsongjc/eng-practices/b79a51589a24d84d6060e2ac8dd627a47cd4a431/cover.jpg
--------------------------------------------------------------------------------
/themes/hugo-book/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Build with Hugo
2 |
3 | on: [push]
4 |
5 | jobs:
6 | hugo:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@master
10 |
11 | - name: Install Hugo
12 | run: |
13 | wget https://github.com/gohugoio/hugo/releases/download/v0.57.2/hugo_0.57.2_Linux-64bit.deb -O /tmp/hugo.deb
14 | sudo dpkg -i /tmp/hugo.deb
15 |
16 | - name: Run Hugo
17 | working-directory: exampleSite
18 | run: hugo --themesDir ../..
19 |
--------------------------------------------------------------------------------
/themes/hugo-book/.gitignore:
--------------------------------------------------------------------------------
1 | public/
2 | exampleSite/public/
--------------------------------------------------------------------------------
/themes/hugo-book/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Alex Shpak
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/themes/hugo-book/README.md:
--------------------------------------------------------------------------------
1 | # Hugo Book Theme
2 |
3 | [](https://gohugo.io)
4 | [](LICENSE)
5 |
6 | ### [Hugo](https://gohugo.io) documentation theme as simple as plain book
7 |
8 | 
9 |
10 | - [Features](#features)
11 | - [Installation](#installation)
12 | - [Menu](#menu)
13 | - [Configuration](#configuration)
14 | - [Shortcodes](#shortcodes)
15 | - [Contributing](#contributing)
16 |
17 | ## Features
18 |
19 | - Clean simple design
20 | - Mobile friendly
21 | - Customisable
22 | - Designed to not interfere with other layouts
23 | - Zero initial configuration
24 | - Handy shortcodes
25 |
26 | ## Requirements
27 |
28 | - Hugo 0.55 or higher
29 | - Hugo extended version, read more [here](https://gohugo.io/news/0.48-relnotes/)
30 |
31 | ## Installation
32 |
33 | Navigate to your hugo project root and run:
34 |
35 | ```
36 | git submodule add https://github.com/alex-shpak/hugo-book themes/book
37 | ```
38 |
39 | Then run hugo (or set `theme = "book"`/`theme: book` in configuration file)
40 |
41 | ```
42 | hugo server --minify --theme book
43 | ```
44 |
45 | ### Creating site from scratch
46 |
47 | Below is example how to create new site from scratch
48 |
49 | ```sh
50 | hugo new site mydocs; cd mydocs
51 | git init
52 | git submodule add https://github.com/alex-shpak/hugo-book themes/book
53 | cp -R themes/book/exampleSite/content .
54 | ```
55 |
56 | ```sh
57 | hugo server --minify --theme book
58 | ```
59 |
60 | ## Menu
61 |
62 | ### File tree menu (default)
63 |
64 | By default theme will render pages from `content/docs` section as menu in a tree structure.
65 | You can set `title` and `weight` in front matter of pages to adjust order and titles in menu.
66 |
67 | ### Leaf bundle menu
68 |
69 | You can also use leaf bundle and content of it's `index.md` as menu.
70 | Given you have this file structure
71 |
72 | ```
73 | ├── content
74 | │ ├── docs
75 | │ │ ├── page-one.md
76 | │ │ └── page-two.md
77 | │ └── posts
78 | │ ├── post-one.md
79 | │ └── post-two.md
80 | ```
81 |
82 | Create file `content/docs/menu/index.md` with content
83 |
84 | ```md
85 | +++
86 | headless = true
87 | +++
88 |
89 | - [Book Example](/docs/)
90 | - [Page One](/docs/page-one)
91 | - [Page Two](/docs/page-two)
92 | - [Blog](/posts)
93 | ```
94 |
95 | And Enable it by settings `BookMenuBundle: /menu` in Site configuration
96 |
97 | - [Example menu](https://github.com/alex-shpak/hugo-book/blob/master/exampleSite/content/menu/index.md)
98 | - [Example config file](https://github.com/alex-shpak/hugo-book/blob/master/exampleSite/config.yaml)
99 | - [Leaf bundles](https://gohugo.io/content-management/page-bundles/)
100 |
101 | ## Blog
102 |
103 | Simple blog supported for section `posts`
104 |
105 | ## Configuration
106 |
107 | ### Site Configuration
108 |
109 | There are few configuration options you can add to your `config.toml` file.
110 | You can also see `yaml` example [here](https://github.com/alex-shpak/hugo-book/blob/master/exampleSite/config.yaml).
111 |
112 | ```toml
113 | # (Optional) Set this to true if you use capital letters in file names
114 | disablePathToLower = true
115 |
116 | # (Optional) Set this to true to enable 'Last Modified by' date and git author
117 | # information on 'doc' type pages.
118 | enableGitInfo = true
119 |
120 | # (Optional) Theme is intended for documentation use, therefore it doesn't render taxonomy.
121 | # You can remove related files with config below
122 | disableKinds = ['taxonomy', 'taxonomyTerm']
123 |
124 | [params]
125 | # (Optional, default 6) Set how many table of contents levels to be showed on page.
126 | # Use false to hide ToC, note that 0 will default to 6 (https://gohugo.io/functions/default/)
127 | # You can also specify this parameter per page in front matter
128 | BookToC = 3
129 |
130 | # (Optional, default none) Set the path to a logo for the book. If the logo is
131 | # /static/logo.png then the path would be 'logo.png'
132 | BookLogo = 'logo.png'
133 |
134 | # (Optional, default none) Set leaf bundle to render as side menu
135 | # When not specified file structure and weights will be used
136 | BookMenuBundle = '/menu'
137 |
138 | # (Optional, default docs) Specify section of content to render as menu
139 | # You can also set value to "*" to render all sections to menu
140 | BookSection = 'docs'
141 |
142 | # (Optional) This value is duplicate of $link-color for making active link highlight in menu bundle mode
143 | # BookMenuBundleActiveLinkColor = '\#004ed0'
144 |
145 | # Set source repository location.
146 | # Used for 'Last Modified' and 'Edit this page' links.
147 | BookRepo = 'https://github.com/alex-shpak/hugo-book'
148 |
149 | # Enable 'Edit this page' links for 'doc' page type.
150 | # Disabled by default. Uncomment to enable. Requires 'BookRepo' param.
151 | # Path must point to 'content' directory of repo.
152 | BookEditPath = 'edit/master/exampleSite/content'
153 |
154 | # (Optional, default January 2, 2006) Configure the date format used on the pages
155 | # - In git information
156 | # - In blog posts
157 | BookDateFormat = 'Jan 2, 2006'
158 |
159 | # (Optional, default true) Enables search function with lunr.js,
160 | # Index is built on fly, therefore it might slowdown your website.
161 | BookSearch = true
162 | ```
163 |
164 | ### Page Configuration
165 |
166 | You can specify additional params per page in front matter
167 |
168 | ```toml
169 | # Set type to 'docs' if you want to render page outside of configured section or if you render section other than 'docs'
170 | type = 'docs'
171 |
172 | # Set page weight to re-arrange items in file-tree menu (if BookMenuBundle not set)
173 | weight = 10
174 |
175 | # (Optional) Set to mark page as flat section in file-tree menu (if BookMenuBundle not set)
176 | bookFlatSection = true
177 |
178 | # (Optional) Set true to hide page or section from side menu (if BookMenuBundle not set)
179 | bookHidden = true
180 |
181 | # (Optional) Set how many levels of ToC to show. use 'false' to hide ToC completely
182 | bookToC = 3
183 | ```
184 |
185 | ### Partials
186 |
187 | There are few empty partials you can override in `layouts/partials/`
188 |
189 | | Partial | Placement |
190 | | ----------------------------------------------- | -------------------------------------- |
191 | | `layouts/partials/docs/inject/head.html` | Before closing `` tag |
192 | | `layouts/partials/docs/inject/body.html` | Before closing `` tag |
193 | | `layouts/partials/docs/inject/footer.html` | After page content |
194 | | `layouts/partials/docs/inject/menu-before.html` | At the beginning of `` menu block |
195 | | `layouts/partials/docs/inject/menu-after.html` | At the end of `` menu block |
196 |
197 | ### Extra Customisation
198 |
199 | | File | Description |
200 | | --------------------- | ------------------------------------------------------------------------------------- |
201 | | `static/favicon.png` | Override default favicon |
202 | | `assets/_custom.scss` | Customise or override scss styles |
203 | | `assets/_fonts.scss` | Replace default font with custom fonts (e.g. local files or remote like google fonts) |
204 |
205 | ## Shortcodes
206 |
207 | ### Expand
208 |
209 | Provides clickable panel that show extra hidden content.
210 |
211 | ```
212 | {{< expand >}}
213 | ## Markdown content
214 | {{< /expand >}}
215 | ```
216 |
217 | ### Tabs
218 |
219 | Useful if you want to show alternative information per platform or setting.
220 |
221 | ```
222 | {{< tabs "uniqueid" >}}
223 | {{< tab "MacOS" >}} # MacOS Content {{< /tab >}}
224 | {{< tab "Linux" >}} # Linux Content {{< /tab >}}
225 | {{< tab "Windows" >}} # Windows Content {{< /tab >}}
226 | {{< /tabs >}}
227 | ```
228 |
229 | ### Multi column text
230 |
231 | Organize text in 2 or more columns to use space efficiently.
232 |
233 | ```html
234 | {{< columns >}}
235 |
236 | # Left Content Lorem markdownum insigne...
237 |
238 | <--->
239 |
240 | # Mid Content Lorem markdownum insigne...
241 |
242 | <--->
243 |
244 | # Right Content Lorem markdownum insigne...
245 | {{< /columns >}}
246 | ```
247 |
248 | ### Mermaid Chat
249 |
250 | Render various charts with [mermaidjs](https://mermaidjs.github.io/)
251 |
252 | ```
253 | {{< mermaid >}}
254 | sequenceDiagram
255 | Alice->>Bob: Hello Bob, how are you?
256 | alt is sick
257 | Bob->>Alice: Not so good :(
258 | else is well
259 | Bob->>Alice: Feeling fresh like a daisy
260 | end
261 | opt Extra response
262 | Bob->>Alice: Thanks for asking
263 | end
264 | {{< /mermaid >}}
265 | ```
266 |
267 | ### KaTeX Syntax
268 |
269 | Render math formulas with [KaTeX](https://katex.org/)
270 |
271 | ```
272 | {{< katex >}}
273 | x = \begin{cases}
274 | a &\text{if } b \\
275 | c &\text{if } d
276 | \end{cases}
277 | {{< /katex >}}
278 | ```
279 |
280 | ## Contributing
281 |
282 | ### [Extra credits to contributors](https://github.com/alex-shpak/hugo-book/graphs/contributors)
283 |
284 | Contributions are welcome and I will review and consider pull requests.
285 | Primary goals are:
286 |
287 | - Keep it simple
288 | - Keep minimal (or zero) default configuration
289 | - Avoid interference with user-defined layouts
290 |
291 | Feel free to open issue if you missing some configuration or customisation option.
292 |
--------------------------------------------------------------------------------
/themes/hugo-book/archetypes/docs.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "{{ .Name | humanize | title }}"
3 | weight: 1
4 | # bookFlatSection: false
5 | # bookShowToC: true
6 | ---
7 |
--------------------------------------------------------------------------------
/themes/hugo-book/archetypes/posts.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "{{ replace .Name "-" " " | title }}"
3 | date: {{ .Date }}
4 | ---
5 |
--------------------------------------------------------------------------------
/themes/hugo-book/assets/_custom.scss:
--------------------------------------------------------------------------------
1 | /* To be overridden by theme user */
2 | // @import "variables";
3 |
--------------------------------------------------------------------------------
/themes/hugo-book/assets/_fonts.scss:
--------------------------------------------------------------------------------
1 | /* roboto-300italic - latin */
2 | @font-face {
3 | font-family: 'Roboto';
4 | font-style: italic;
5 | font-weight: 300;
6 | src: local('Roboto Light Italic'), local('Roboto-LightItalic'),
7 | url('fonts/roboto-v19-latin-300italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
8 | url('fonts/roboto-v19-latin-300italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
9 | }
10 | /* roboto-regular - latin */
11 | @font-face {
12 | font-family: 'Roboto';
13 | font-style: normal;
14 | font-weight: 400;
15 | src: local('Roboto'), local('Roboto-Regular'),
16 | url('fonts/roboto-v19-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
17 | url('fonts/roboto-v19-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
18 | }
19 | /* roboto-700 - latin */
20 | @font-face {
21 | font-family: 'Roboto';
22 | font-style: normal;
23 | font-weight: 700;
24 | src: local('Roboto Bold'), local('Roboto-Bold'),
25 | url('fonts/roboto-v19-latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
26 | url('fonts/roboto-v19-latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
27 | }
28 |
29 | /* roboto-mono-regular - latin */
30 | @font-face {
31 | font-family: 'Roboto Mono';
32 | font-style: normal;
33 | font-weight: 400;
34 | src: local('Roboto Mono'), local('RobotoMono-Regular'),
35 | url('fonts/roboto-mono-v6-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
36 | url('fonts/roboto-mono-v6-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
37 | }
38 |
39 | body {
40 | font-family: 'Roboto', sans-serif;
41 | }
42 |
43 | code {
44 | font-family: 'Roboto Mono', monospace;
45 | }
46 |
--------------------------------------------------------------------------------
/themes/hugo-book/assets/_markdown.scss:
--------------------------------------------------------------------------------
1 | @import 'variables';
2 |
3 | .markdown {
4 | line-height: 1.6;
5 |
6 | h1, h2, h3, h4, h5 {
7 | font-weight: normal;
8 | line-height: 1;
9 | margin-top: 1.5em;
10 | margin-bottom: $padding-16;
11 | }
12 |
13 | // remove padding at the beginning of page
14 | > :first-child {
15 | margin-top: 0;
16 | }
17 |
18 | b, optgroup, strong {
19 | font-weight: bolder;
20 | }
21 |
22 | a {
23 | text-decoration: none;
24 |
25 | &:hover {
26 | text-decoration: underline;
27 | }
28 | }
29 |
30 | img {
31 | max-width: 100%;
32 | }
33 |
34 | code {
35 | padding: 0 $padding-4;
36 | background: $gray-200;
37 | border-radius: $border-radius;
38 | font-size: .875em;
39 | }
40 |
41 | pre {
42 | padding: $padding-16;
43 | background: $gray-100;
44 | border-radius: $border-radius;
45 | overflow-x: auto;
46 |
47 | code {
48 | padding: 0;
49 | background: none;
50 | }
51 | }
52 |
53 | blockquote {
54 | margin: $padding-16 0;
55 | padding: $padding-4 ($padding-16 - $padding-4); //to keep total left space 16dp
56 |
57 | border-left: $padding-4 solid $gray-200;
58 | border-radius: $border-radius;
59 |
60 | :first-child { margin-top: 0; }
61 | :last-child { margin-bottom: 0; }
62 | }
63 |
64 | table {
65 | overflow: auto;
66 | display: block;
67 | border-spacing: 0;
68 | border-collapse: collapse;
69 | margin-top: $padding-16;
70 | margin-bottom: $padding-16;
71 |
72 | tr th, tr td {
73 | padding: $padding-8 $padding-16;
74 | line-height: 1;
75 | border: $padding-1 solid $gray-200;
76 | }
77 |
78 | tr:nth-child(2n) {
79 | background: $gray-100;
80 | }
81 | }
82 |
83 | hr {
84 | height: $padding-1;
85 | border: none;
86 | background: $gray-200;
87 | }
88 |
89 | ul, ol {
90 | padding-left: $padding-16 * 2;
91 | }
92 |
93 | dl {
94 | // padding-left: $padding-16;
95 | dt {
96 | font-weight: bolder;
97 | margin-top: $padding-16;
98 | }
99 |
100 | dd {
101 | margin-left: $padding-16 * 2;
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/themes/hugo-book/assets/_shortcodes.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | .markdown-inner {
4 | // Util class to remove extra margin in nested markdown content
5 | > :first-child {
6 | margin-top: 0;
7 | }
8 | > :last-child {
9 | margin-bottom: 0;
10 | }
11 | }
12 |
13 | // {{< expand "Label" "icon" >}}
14 | .book-expand {
15 | margin-top: $padding-16;
16 | margin-bottom: $padding-16;
17 |
18 | border: $padding-1 solid $gray-200;
19 | border-radius: $border-radius;
20 |
21 | overflow: hidden;
22 |
23 | .book-expand-head {
24 | background: $gray-100;
25 | padding: $padding-8 $padding-16;
26 | cursor: pointer;
27 | }
28 |
29 | .book-expand-content {
30 | display: none;
31 | padding: $padding-16;
32 | }
33 |
34 | input[type="checkbox"]:checked + .book-expand-content {
35 | display: block;
36 | }
37 | }
38 |
39 | // {{< tabs >}}
40 | .book-tabs {
41 | margin-top: $padding-16;
42 | margin-bottom: $padding-16;
43 |
44 | border: $padding-1 solid $gray-200;
45 | border-radius: $border-radius;
46 |
47 | overflow: hidden;
48 |
49 | display: flex;
50 | flex-wrap: wrap;
51 |
52 | label {
53 | display: inline-block;
54 | padding: $padding-8 $padding-16;
55 | border-bottom: $padding-1 transparent;
56 | cursor: pointer;
57 | }
58 |
59 | .book-tabs-content {
60 | order: 999; //Move content blocks to the end
61 | width: 100%;
62 | border-top: $padding-1 solid $gray-100;
63 | padding: $padding-16;
64 | display: none;
65 | }
66 |
67 | input[type="radio"]:checked + label {
68 | border-bottom: $padding-1 solid $color-link;
69 | }
70 | input[type="radio"]:checked + label + .book-tabs-content {
71 | display: block;
72 | }
73 | }
74 |
75 | // {{< columns >}}
76 | .book-columns {
77 | margin-left: -$padding-16;
78 | margin-right: -$padding-16;
79 |
80 | > div {
81 | margin: $padding-16 0;
82 | // max-width: 50%;
83 | min-width: $body-min-width * 0.66;
84 | padding: 0 $padding-16;
85 | }
86 | }
87 |
88 | // {{< button >}}
89 | a.book-btn {
90 | display: inline-block;
91 | color: $color-link !important;
92 | text-decoration: none !important;
93 | border: $padding-1 solid $color-link;
94 | border-radius: $border-radius;
95 | padding: $padding-4 $padding-16;
96 | margin-top: $padding-8;
97 | margin-bottom: $padding-8;
98 | cursor: pointer;
99 | }
100 |
--------------------------------------------------------------------------------
/themes/hugo-book/assets/_utils.scss:
--------------------------------------------------------------------------------
1 | .flex {
2 | display: flex;
3 | }
4 |
5 | .flex-auto {
6 | flex: 1 1 auto;
7 | }
8 |
9 | .flex-even {
10 | flex: 1 1;
11 | }
12 |
13 | .flex-wrap {
14 | flex-wrap: wrap;
15 | }
16 |
17 | .justify-start {
18 | justify-content: flex-start;
19 | }
20 |
21 | .justify-end {
22 | justify-content: flex-end;
23 | }
24 |
25 | .justify-center {
26 | justify-content: center;
27 | }
28 |
29 | .justify-between {
30 | justify-content: space-between;
31 | }
32 |
33 | .align-center {
34 | align-items: center;
35 | }
36 |
37 | .mx-auto {
38 | margin: 0 auto;
39 | }
40 |
41 | .text-center {
42 | text-align: center;
43 | }
44 |
45 | .hidden {
46 | display: none;
47 | }
48 |
49 | @mixin spin($duration) {
50 | animation: spin $duration ease infinite;
51 | @keyframes spin {
52 | 100% {
53 | transform: rotate(360deg);
54 | }
55 | }
56 | }
57 |
58 | @mixin fixed {
59 | position: fixed;
60 | top: 0;
61 | bottom: 0;
62 | overflow-x: hidden;
63 | overflow-y: auto;
64 | }
65 |
66 | @mixin dark-links {
67 | a {
68 | color: $color-dark-link;
69 | }
70 |
71 | a.active {
72 | color: $color-link;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/themes/hugo-book/assets/_variables.scss:
--------------------------------------------------------------------------------
1 | // Used in layout
2 | $padding-1: 1px;
3 | $padding-4: 0.25rem;
4 | $padding-8: 0.5rem;
5 | $padding-16: 1rem;
6 |
7 | $font-size-base: 16px;
8 | $font-size-12: 0.75rem;
9 | $font-size-14: 0.875rem;
10 | $font-size-16: 1rem;
11 |
12 | $border-radius: 0.15rem;
13 |
14 | // Grayscale
15 | $white: #ffffff;
16 | $gray-100: #f8f9fa;
17 | $gray-200: #e9ecef;
18 | $gray-300: #dee2e6;
19 | $gray-400: #ced4da;
20 | $gray-500: #adb5bd;
21 | $gray-600: #868e96;
22 | $gray-700: #495057;
23 | $gray-800: #343a40;
24 | $gray-900: #212529;
25 | $black: #000;
26 |
27 | $color-link: #004ed0;
28 | $color-visited-link: #8440f1;
29 | $color-dark-link: $gray-800;
30 |
31 | $body-background: white;
32 | $body-font-color: $gray-800;
33 | $body-font-weight: normal;
34 |
35 | $body-min-width: 20rem;
36 | $container-max-width: 80rem;
37 |
38 | $header-height: 3.5rem;
39 | $menu-width: 16rem;
40 | $toc-width: 16rem;
41 |
42 | $md-breakpoint: $menu-width + $body-min-width * 1.25 + $toc-width;
43 | $sm-breakpoint: $menu-width + $body-min-width;
44 |
--------------------------------------------------------------------------------
/themes/hugo-book/assets/book.scss:
--------------------------------------------------------------------------------
1 | @import "normalize";
2 | @import "variables";
3 | @import "utils";
4 | @import "markdown";
5 | @import "shortcodes";
6 |
7 | html {
8 | font-size: $font-size-base;
9 | letter-spacing: 0.33px;
10 | scroll-behavior: smooth;
11 | }
12 |
13 | html,
14 | body {
15 | min-width: $body-min-width;
16 | overflow-x: hidden;
17 | }
18 |
19 | body {
20 | color: $body-font-color;
21 | background: $body-background;
22 |
23 | font-family: sans-serif;
24 | font-weight: $body-font-weight;
25 |
26 | text-rendering: optimizeLegibility;
27 | -webkit-font-smoothing: antialiased;
28 | -moz-osx-font-smoothing: grayscale;
29 |
30 | box-sizing: border-box;
31 | * {
32 | box-sizing: inherit;
33 | }
34 | }
35 |
36 | h1,
37 | h2,
38 | h3,
39 | h4,
40 | h5 {
41 | font-weight: $body-font-weight;
42 | }
43 |
44 | a {
45 | text-decoration: none;
46 | color: $color-link;
47 |
48 | &:visited {
49 | color: $color-visited-link;
50 | }
51 | }
52 |
53 | img {
54 | vertical-align: baseline;
55 | }
56 |
57 | aside nav ul {
58 | padding: 0;
59 | margin: 0;
60 | list-style: none;
61 |
62 | li {
63 | margin: 1em 0;
64 | }
65 |
66 | a {
67 | display: block;
68 | }
69 |
70 | a:hover {
71 | opacity: 0.5;
72 | }
73 |
74 | ul {
75 | padding-left: $padding-16;
76 | }
77 | }
78 |
79 | ul.pagination {
80 | display: flex;
81 | justify-content: center;
82 | list-style-type: none;
83 |
84 | .page-item a {
85 | padding: $padding-16;
86 | }
87 | }
88 |
89 | .container {
90 | max-width: $container-max-width;
91 | margin: 0 auto;
92 | }
93 |
94 | .book-brand {
95 | margin-top: 0;
96 |
97 | img {
98 | height: 1.5em;
99 | width: auto;
100 | vertical-align: middle;
101 | margin-right: $padding-8;
102 | }
103 | }
104 |
105 | .book-menu {
106 | flex: 0 0 $menu-width;
107 | font-size: $font-size-14;
108 |
109 | nav {
110 | width: $menu-width;
111 | padding: $padding-16;
112 |
113 | @include fixed;
114 | }
115 |
116 | @include dark-links;
117 | }
118 |
119 | .book-section-flat {
120 | margin-bottom: $padding-16 * 2;
121 |
122 | &:not(:first-child) {
123 | margin-top: $padding-16 * 2;
124 | }
125 |
126 | > a,
127 | > span {
128 | font-weight: bolder;
129 | }
130 |
131 | > ul {
132 | padding-left: 0;
133 | }
134 | }
135 |
136 | .book-page {
137 | min-width: $body-min-width;
138 | flex-grow: 1;
139 | padding: $padding-16;
140 | }
141 |
142 | .book-header {
143 | margin-bottom: $padding-16;
144 | display: none;
145 | }
146 |
147 | .book-search {
148 | position: relative;
149 | margin: $padding-16 0;
150 | border-bottom: 1px solid transparent;
151 |
152 | &::after {
153 | display: block;
154 | content: "";
155 | clear: both;
156 | }
157 |
158 | input {
159 | width: 100%;
160 | padding: $padding-8;
161 |
162 | border: 0;
163 | border-radius: $padding-4;
164 |
165 | background: $gray-100;
166 |
167 | &:required + .book-search-spinner {
168 | display: block;
169 | }
170 | }
171 |
172 | .book-search-spinner {
173 | position: absolute;
174 | margin: $padding-8;
175 | right: 0;
176 | top: 0;
177 |
178 | width: $padding-16;
179 | height: $padding-16;
180 |
181 | border: $padding-1 solid transparent;
182 | border-top-color: $body-font-color;
183 | border-radius: 50%;
184 |
185 | @include spin(1s);
186 | }
187 | }
188 |
189 | .book-toc {
190 | flex: 0 0 $toc-width;
191 | font-size: $font-size-14;
192 |
193 | nav {
194 | width: $toc-width;
195 | padding: $padding-16;
196 |
197 | @include fixed;
198 | }
199 |
200 | img {
201 | height: 1em;
202 | }
203 |
204 | nav > ul > li:first-child {
205 | margin-top: 0;
206 | }
207 |
208 | // Classes to hide nested levels of ToC (can be replaced by @for, but it's more clear like this)
209 | &.level-1 ul ul,
210 | &.level-2 ul ul ul,
211 | &.level-3 ul ul ul ul,
212 | &.level-4 ul ul ul ul ul,
213 | &.level-5 ul ul ul ul ul ul,
214 | &.level-6 ul ul ul ul ul ul ul {
215 | display: none;
216 | }
217 | }
218 |
219 | .book-footer {
220 | display: flex;
221 | padding-top: $padding-16;
222 | font-size: $font-size-14;
223 |
224 | img {
225 | height: 1em;
226 | }
227 | }
228 |
229 | .book-posts {
230 | min-width: $body-min-width;
231 | max-width: $body-min-width * 2;
232 | flex-grow: 1;
233 | padding: $padding-16;
234 |
235 | article {
236 | padding-bottom: $padding-16;
237 | }
238 | }
239 |
240 | .book-home {
241 | padding: $padding-16;
242 | }
243 |
244 | // Responsive styles
245 | aside nav,
246 | .book-page,
247 | .book-posts,
248 | .markdown {
249 | transition: 0.2s ease-in-out;
250 | transition-property: transform, margin-left, opacity;
251 | will-change: transform, margin-left;
252 | }
253 |
254 | @media screen and (max-width: $md-breakpoint) {
255 | .book-toc {
256 | display: none;
257 | }
258 | }
259 |
260 | @media screen and (max-width: $sm-breakpoint) {
261 | .book-menu {
262 | margin-left: -$menu-width;
263 | font-size: $font-size-base;
264 | }
265 |
266 | .book-header {
267 | display: flex;
268 | }
269 |
270 | #menu-control:checked + main {
271 | .book-menu nav,
272 | .book-page,
273 | .book-posts {
274 | transform: translateX($menu-width);
275 | }
276 |
277 | .book-header label {
278 | transform: rotate(90deg);
279 | }
280 |
281 | .markdown {
282 | opacity: 0.25;
283 | }
284 | }
285 | }
286 |
287 | // Extra space for big screens
288 | @media screen and (min-width: $container-max-width) {
289 | .book-page,
290 | .book-posts,
291 | .book-menu nav,
292 | .book-toc nav {
293 | padding: $padding-16 * 2 $padding-16;
294 | }
295 | }
296 |
297 | // Add fonts
298 | @import "fonts";
299 |
300 | // Add custom defined styles
301 | @import "custom";
302 |
--------------------------------------------------------------------------------
/themes/hugo-book/assets/normalize.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
2 |
3 | /* Document
4 | ========================================================================== */
5 |
6 | /**
7 | * 1. Correct the line height in all browsers.
8 | * 2. Prevent adjustments of font size after orientation changes in iOS.
9 | */
10 |
11 | html {
12 | line-height: 1.15; /* 1 */
13 | -webkit-text-size-adjust: 100%; /* 2 */
14 | }
15 |
16 | /* Sections
17 | ========================================================================== */
18 |
19 | /**
20 | * Remove the margin in all browsers.
21 | */
22 |
23 | body {
24 | margin: 0;
25 | }
26 |
27 | /**
28 | * Render the `main` element consistently in IE.
29 | */
30 |
31 | main {
32 | display: block;
33 | }
34 |
35 | /**
36 | * Correct the font size and margin on `h1` elements within `section` and
37 | * `article` contexts in Chrome, Firefox, and Safari.
38 | */
39 |
40 | h1 {
41 | font-size: 2em;
42 | margin: 0.67em 0;
43 | }
44 |
45 | /* Grouping content
46 | ========================================================================== */
47 |
48 | /**
49 | * 1. Add the correct box sizing in Firefox.
50 | * 2. Show the overflow in Edge and IE.
51 | */
52 |
53 | hr {
54 | box-sizing: content-box; /* 1 */
55 | height: 0; /* 1 */
56 | overflow: visible; /* 2 */
57 | }
58 |
59 | /**
60 | * 1. Correct the inheritance and scaling of font size in all browsers.
61 | * 2. Correct the odd `em` font sizing in all browsers.
62 | */
63 |
64 | pre {
65 | font-family: monospace, monospace; /* 1 */
66 | font-size: 1em; /* 2 */
67 | }
68 |
69 | /* Text-level semantics
70 | ========================================================================== */
71 |
72 | /**
73 | * Remove the gray background on active links in IE 10.
74 | */
75 |
76 | a {
77 | background-color: transparent;
78 | }
79 |
80 | /**
81 | * 1. Remove the bottom border in Chrome 57-
82 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
83 | */
84 |
85 | abbr[title] {
86 | border-bottom: none; /* 1 */
87 | text-decoration: underline; /* 2 */
88 | text-decoration: underline dotted; /* 2 */
89 | }
90 |
91 | /**
92 | * Add the correct font weight in Chrome, Edge, and Safari.
93 | */
94 |
95 | b,
96 | strong {
97 | font-weight: bolder;
98 | }
99 |
100 | /**
101 | * 1. Correct the inheritance and scaling of font size in all browsers.
102 | * 2. Correct the odd `em` font sizing in all browsers.
103 | */
104 |
105 | code,
106 | kbd,
107 | samp {
108 | font-family: monospace, monospace; /* 1 */
109 | font-size: 1em; /* 2 */
110 | }
111 |
112 | /**
113 | * Add the correct font size in all browsers.
114 | */
115 |
116 | small {
117 | font-size: 80%;
118 | }
119 |
120 | /**
121 | * Prevent `sub` and `sup` elements from affecting the line height in
122 | * all browsers.
123 | */
124 |
125 | sub,
126 | sup {
127 | font-size: 75%;
128 | line-height: 0;
129 | position: relative;
130 | vertical-align: baseline;
131 | }
132 |
133 | sub {
134 | bottom: -0.25em;
135 | }
136 |
137 | sup {
138 | top: -0.5em;
139 | }
140 |
141 | /* Embedded content
142 | ========================================================================== */
143 |
144 | /**
145 | * Remove the border on images inside links in IE 10.
146 | */
147 |
148 | img {
149 | border-style: none;
150 | }
151 |
152 | /* Forms
153 | ========================================================================== */
154 |
155 | /**
156 | * 1. Change the font styles in all browsers.
157 | * 2. Remove the margin in Firefox and Safari.
158 | */
159 |
160 | button,
161 | input,
162 | optgroup,
163 | select,
164 | textarea {
165 | font-family: inherit; /* 1 */
166 | font-size: 100%; /* 1 */
167 | line-height: 1.15; /* 1 */
168 | margin: 0; /* 2 */
169 | }
170 |
171 | /**
172 | * Show the overflow in IE.
173 | * 1. Show the overflow in Edge.
174 | */
175 |
176 | button,
177 | input { /* 1 */
178 | overflow: visible;
179 | }
180 |
181 | /**
182 | * Remove the inheritance of text transform in Edge, Firefox, and IE.
183 | * 1. Remove the inheritance of text transform in Firefox.
184 | */
185 |
186 | button,
187 | select { /* 1 */
188 | text-transform: none;
189 | }
190 |
191 | /**
192 | * Correct the inability to style clickable types in iOS and Safari.
193 | */
194 |
195 | button,
196 | [type="button"],
197 | [type="reset"],
198 | [type="submit"] {
199 | -webkit-appearance: button;
200 | }
201 |
202 | /**
203 | * Remove the inner border and padding in Firefox.
204 | */
205 |
206 | button::-moz-focus-inner,
207 | [type="button"]::-moz-focus-inner,
208 | [type="reset"]::-moz-focus-inner,
209 | [type="submit"]::-moz-focus-inner {
210 | border-style: none;
211 | padding: 0;
212 | }
213 |
214 | /**
215 | * Restore the focus styles unset by the previous rule.
216 | */
217 |
218 | button:-moz-focusring,
219 | [type="button"]:-moz-focusring,
220 | [type="reset"]:-moz-focusring,
221 | [type="submit"]:-moz-focusring {
222 | outline: 1px dotted ButtonText;
223 | }
224 |
225 | /**
226 | * Correct the padding in Firefox.
227 | */
228 |
229 | fieldset {
230 | padding: 0.35em 0.75em 0.625em;
231 | }
232 |
233 | /**
234 | * 1. Correct the text wrapping in Edge and IE.
235 | * 2. Correct the color inheritance from `fieldset` elements in IE.
236 | * 3. Remove the padding so developers are not caught out when they zero out
237 | * `fieldset` elements in all browsers.
238 | */
239 |
240 | legend {
241 | box-sizing: border-box; /* 1 */
242 | color: inherit; /* 2 */
243 | display: table; /* 1 */
244 | max-width: 100%; /* 1 */
245 | padding: 0; /* 3 */
246 | white-space: normal; /* 1 */
247 | }
248 |
249 | /**
250 | * Add the correct vertical alignment in Chrome, Firefox, and Opera.
251 | */
252 |
253 | progress {
254 | vertical-align: baseline;
255 | }
256 |
257 | /**
258 | * Remove the default vertical scrollbar in IE 10+.
259 | */
260 |
261 | textarea {
262 | overflow: auto;
263 | }
264 |
265 | /**
266 | * 1. Add the correct box sizing in IE 10.
267 | * 2. Remove the padding in IE 10.
268 | */
269 |
270 | [type="checkbox"],
271 | [type="radio"] {
272 | box-sizing: border-box; /* 1 */
273 | padding: 0; /* 2 */
274 | }
275 |
276 | /**
277 | * Correct the cursor style of increment and decrement buttons in Chrome.
278 | */
279 |
280 | [type="number"]::-webkit-inner-spin-button,
281 | [type="number"]::-webkit-outer-spin-button {
282 | height: auto;
283 | }
284 |
285 | /**
286 | * 1. Correct the odd appearance in Chrome and Safari.
287 | * 2. Correct the outline style in Safari.
288 | */
289 |
290 | [type="search"] {
291 | -webkit-appearance: textfield; /* 1 */
292 | outline-offset: -2px; /* 2 */
293 | }
294 |
295 | /**
296 | * Remove the inner padding in Chrome and Safari on macOS.
297 | */
298 |
299 | [type="search"]::-webkit-search-decoration {
300 | -webkit-appearance: none;
301 | }
302 |
303 | /**
304 | * 1. Correct the inability to style clickable types in iOS and Safari.
305 | * 2. Change font properties to `inherit` in Safari.
306 | */
307 |
308 | ::-webkit-file-upload-button {
309 | -webkit-appearance: button; /* 1 */
310 | font: inherit; /* 2 */
311 | }
312 |
313 | /* Interactive
314 | ========================================================================== */
315 |
316 | /*
317 | * Add the correct display in Edge, IE 10+, and Firefox.
318 | */
319 |
320 | details {
321 | display: block;
322 | }
323 |
324 | /*
325 | * Add the correct display in all browsers.
326 | */
327 |
328 | summary {
329 | display: list-item;
330 | }
331 |
332 | /* Misc
333 | ========================================================================== */
334 |
335 | /**
336 | * Add the correct display in IE 10+.
337 | */
338 |
339 | template {
340 | display: none;
341 | }
342 |
343 | /**
344 | * Add the correct display in IE 10.
345 | */
346 |
347 | [hidden] {
348 | display: none;
349 | }
350 |
--------------------------------------------------------------------------------
/themes/hugo-book/assets/search-data.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | const pages = [
3 | {{ range $index, $page := .Site.Pages }}
4 | {{- if $index -}},{{- end }}
5 | {
6 | "idx": {{ $index }},
7 | "href": "{{ $page.RelPermalink }}",
8 | "title": {{ (partial "docs/title" $page) | jsonify }},
9 | "content": {{ $page.Plain | jsonify }}
10 | }
11 | {{- end -}}
12 | ];
13 |
14 | window.bookSearch = {
15 | pages: pages,
16 | idx: lunr(function() {
17 | this.ref("idx");
18 | this.field("title");
19 | this.field("content");
20 |
21 | pages.forEach(this.add, this);
22 | }),
23 | }
24 | })();
25 |
--------------------------------------------------------------------------------
/themes/hugo-book/assets/search.js:
--------------------------------------------------------------------------------
1 | {{- $searchData := resources.Get "search-data.js" | resources.ExecuteAsTemplate "search-data.js" . | resources.Minify | resources.Fingerprint }}
2 |
3 | (function() {
4 | const input = document.querySelector("#book-search-input");
5 | const results = document.querySelector("#book-search-results");
6 |
7 | input.addEventListener("focus", init);
8 | input.addEventListener("keyup", search);
9 |
10 | function init() {
11 | input.removeEventListener("focus", init); //init once
12 | input.required = true;
13 |
14 | loadScript("{{ "lunr.min.js" | relURL }}");
15 | loadScript("{{ $searchData.RelPermalink }}", function() {
16 | input.readOnly = false;
17 | input.required = false;
18 | search();
19 | });
20 | }
21 |
22 | function search() {
23 | while (results.firstChild) {
24 | results.removeChild(results.firstChild);
25 | }
26 |
27 | if (!input.value) {
28 | return;
29 | }
30 |
31 | const terms = lunr.tokenizer(input.value);
32 | const searchHits = window.bookSearch.idx.query(function(query) {
33 | query.term(terms, {
34 | boost: 100
35 | });
36 | query.term(terms, {
37 | boost: 10,
38 | wildcard: lunr.Query.wildcard.LEADING | lunr.Query.wildcard.TRAILING
39 | });
40 | query.term(terms, {
41 | editDistance: 2
42 | });
43 | });
44 |
45 | searchHits.slice(0, 10).forEach(function(hit) {
46 | const page = window.bookSearch.pages[hit.ref];
47 | const li = document.createElement("li"),
48 | a = li.appendChild(document.createElement("a"));
49 |
50 | a.href = page.href;
51 | a.textContent = page.title;
52 |
53 | results.appendChild(li);
54 | });
55 | }
56 |
57 | function loadScript(src, callback) {
58 | const script = document.createElement("script");
59 | script.defer = true;
60 | script.src = src;
61 | script.onload = callback;
62 |
63 | document.head.append(script);
64 | }
65 | })();
66 |
--------------------------------------------------------------------------------
/themes/hugo-book/exampleSite/assets/_custom.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
--------------------------------------------------------------------------------
/themes/hugo-book/exampleSite/config.toml:
--------------------------------------------------------------------------------
1 | # hugo server --minify --themesDir ... --baseURL=http://0.0.0.0:1313/example
2 |
3 | baseURL = 'https://example.com/'
4 | title = 'Hugo Book'
5 | theme = 'hugo-book'
6 | disableKinds = ['taxonomy', 'taxonomyTerm']
7 | themesDir = '../..'
8 |
9 | # Book configuration
10 | disablePathToLower = true
11 | enableGitInfo = true
12 |
13 | # Code highlight
14 | # pygmentsStyle = 'monokailight'
15 | pygmentsCodeFences = true
16 |
17 | [params]
18 | # (Optional, default 6) Set how many table of contents levels to be showed on page.
19 | # Use false to hide ToC, note that 0 will default to 6 (https://gohugo.io/functions/default/)
20 | # You can also specify this parameter per page in front matter
21 | BookToC = 3
22 |
23 | # (Optional, default none) Set the path to a logo for the book. If the logo is
24 | # /static/logo.png then the path would be logo.png
25 | # BookLogo = 'logo.png'
26 |
27 | # (Optional, default none) Set leaf bundle to render as side menu
28 | # When not specified file structure and weights will be used
29 | BookMenuBundle = '/menu'
30 |
31 | # (Optional, default docs) Specify section of content to render as menu
32 | # You can also set value to '*' to render all sections to menu
33 | BookSection = 'docs'
34 |
35 | # (Optional) This value is duplicate of $link-color for making active link highlight in menu bundle mode
36 | # BookMenuBundleActiveLinkColor = '\#004ed0'
37 |
38 | # Set source repository location.
39 | # Used for 'Last Modified' and 'Edit this page' links.
40 | BookRepo = 'https://github.com/alex-shpak/hugo-book'
41 |
42 | # Enable "Edit this page" links for 'doc' page type.
43 | # Disabled by default. Uncomment to enable. Requires 'BookRepo' param.
44 | # Path must point to 'content' directory of repo.
45 | BookEditPath = 'edit/master/exampleSite/content'
46 |
47 | # Configure the date format used on the pages
48 | # - In git information
49 | # - In blog posts
50 | BookDateFormat = 'Jan 2, 2006'
51 |
52 | # (Optional, default true) Enables search function with lunr.js,
53 | # Index is built on fly, therefore it might slowdown your website.
54 | BookSearch = true
55 |
--------------------------------------------------------------------------------
/themes/hugo-book/exampleSite/config.yaml:
--------------------------------------------------------------------------------
1 | # hugo server --minify --themesDir ... --baseURL=http://0.0.0.0:1313/example
2 |
3 | baseURL: https://example.com/
4 | title: Hugo Book
5 | theme: hugo-book
6 | disableKinds: ['taxonomy', 'taxonomyTerm']
7 | # themesDir: ../..
8 |
9 | # Book configuration
10 | disablePathToLower: true
11 | enableGitInfo: true
12 |
13 | # Code highlight
14 | # pygmentsStyle: monokailight
15 | pygmentsCodeFences: true
16 |
17 | params:
18 | # (Optional, default 6) Set how many table of contents levels to be showed on page.
19 | # Use false/off to hide ToC, note that 0 will default to 6 (https://gohugo.io/functions/default/)
20 | # You can also specify this parameter per page in front matter
21 | BookToC: 3
22 |
23 | # (Optional, default none) Set the path to a logo for the book. If the logo is
24 | # /static/logo.png then the path would be /logo.png
25 | # BookLogo: /logo.png
26 |
27 | # (Optional, default none) Set leaf bundle to render as side menu
28 | # When not specified file structure and weights will be used
29 | BookMenuBundle: /menu
30 |
31 | # (Optional, default docs) Specify section of content to render as menu
32 | # You can also set value to '*' to render all sections to menu
33 | BookSection: docs
34 |
35 | # (Optional) This value is duplicate of $link-color for making active link highlight in menu bundle mode
36 | # BookMenuBundleActiveLinkColor: "\#004ed0"
37 |
38 | # Set source repository location.
39 | # Used for 'Last Modified' and 'Edit this page' links.
40 | BookRepo: https://github.com/alex-shpak/hugo-book
41 |
42 | # Enable "Edit this page" links for 'doc' page type.
43 | # Disabled by default. Uncomment to enable. Requires 'BookRepo' param.
44 | # Path must point to 'content' directory of repo.
45 | BookEditPath: edit/master/exampleSite/content
46 |
47 | # Configure the date format used on the pages
48 | # - In git information
49 | # - In blog posts
50 | BookDateFormat: 'Jan 2, 2006'
51 |
52 | # (Optional, default true) Enables search function with lunr.js,
53 | # Index is built on fly, therefore it might slowdown your website.
54 | BookSearch: true
55 |
--------------------------------------------------------------------------------
/themes/hugo-book/exampleSite/content/_index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Introduction
3 | type: docs
4 | ---
5 |
6 | # Acerbo datus maxime
7 |
8 | {{< columns >}}
9 | ## Astris ipse furtiva
10 |
11 | Est in vagis et Pittheus tu arge accipiter regia iram vocatur nurus. Omnes ut
12 | olivae sensit **arma sorori** deducit, inesset **crudus**, ego vetuere aliis,
13 | modo arsit? Utinam rapta fiducia valuere litora _adicit cursu_, ad facies
14 |
15 | <--->
16 |
17 | ## Suis quot vota
18 |
19 | Ea _furtique_ risere fratres edidit terrae magis. Colla tam mihi tenebat:
20 | miseram excita suadent es pecudes iam. Concilio _quam_ velatus posset ait quod
21 | nunc! Fragosis suae dextra geruntur functus vulgata.
22 | {{< /columns >}}
23 |
24 |
25 | ## Tempora nisi nunc
26 |
27 | Lorem **markdownum** emicat gestu. Cannis sol pressit ducta. **Est** Idaei,
28 | tremens ausim se tutaeque, illi ulnis hausit, sed, lumina cutem. Quae avis
29 | sequens!
30 |
31 | var panel = ram_design;
32 | if (backup + system) {
33 | file.readPoint = network_native;
34 | sidebar_engine_device(cell_tftp_raster,
35 | dual_login_paper.adf_vci.application_reader_design(
36 | graphicsNvramCdma, lpi_footer_snmp, integer_model));
37 | }
38 | public_keyboard_docking += error.controller_gibibyte_plug.ip(4,
39 | asciiPetaflops, software(supercomputer_compatible_status + 4));
40 | dynamic_disk.indexModeLaptop = bufferTftpReality;
41 | var export_vlog_sequence = trinitron_flowchart + supercomputer_cluster_rj(
42 | -1, toolbar_powerpoint_query, -2 / multiprocessing_impression);
43 |
44 | ## Locis suis novi cum suoque decidit eadem
45 |
46 | Idmoniae ripis, at aves, ali missa adest, ut _et autem_, et ab? Venit spes
47 | versus finis sermonibus patefecit murum nec est sine oculis. _Ille_ inmota
48 | macies domoque caelestia cadit tantummodo scelus procul, corde!
49 |
50 | 1. Dolentem capi parte rostro alvum habentem pudor
51 | 2. Fulgentia sanguine paret
52 | 3. E punior consurgit lentus
53 | 4. Vox hasta eras micantes
54 |
55 | ## Facibus pharetrae indetonsusque indulsit sic incurrite foliis
56 |
57 | Nefandam et prisci palmas! Blandita cutis flectitur montis macies, te _nati_
58 | Latiis; turbaque inferias. Virginis tibi peracta avidusque facies caper nec, e
59 | at ademptae, mira.
60 |
61 | direct *= font(inputScareware(sliHome), crossplatform.byte(
62 | ppl_encryption.excel_e_rte(integratedModelModifier), timeVirtual,
63 | floating_speakers.media_printer(us, yahoo, primaryPhp)));
64 | friendly_metal_flatbed(cd, isoPrimaryStorage(reader), dmaMirrored);
65 | if (parse_flash_cron.metalGif(1, adServiceDevice, utility)) {
66 | adf -= operation_cdma_samba;
67 | imapGif.switch += torrent;
68 | } else {
69 | pmu.disk_captcha = digital_ppp_pci + recursionTransistor(5, dram);
70 | ajax_service += grayscalePythonLock;
71 | google_scroll_capacity = ftp + engine_dslam_sidebar / tape - 1;
72 | }
73 | drive_rw = zipTftp;
74 | var suffix = software_router_extension.dimm_ddr(-5,
75 | kernel_digital_minisite);
76 |
77 | Vocavit toto; alas **mitis** maestus in liquidarum ab legi finitimosque dominam
78 | tibi subitus; Orionis vertitur nota. Currere alti etiam seroque cernitis
79 | innumeris miraturus amplectique collo sustinet quemque! Litora ante turba?
80 |
--------------------------------------------------------------------------------
/themes/hugo-book/exampleSite/content/docs/introduction/_index.md:
--------------------------------------------------------------------------------
1 | ---
2 | weight: 1
3 | bookFlatSection: true
4 | ---
5 |
6 | # Introduction
7 |
8 | ## Ferre hinnitibus erat accipitrem dixi Troiae tollens
9 |
10 | Lorem markdownum, a quoque nutu est *quodcumque mandasset* veluti. Passim
11 | inportuna totidemque nympha fert; repetens pendent, poenarum guttura sed vacet
12 | non, mortali undas. Omnis pharetramque gramen portentificisque membris servatum
13 | novabis fallit de nubibus atque silvas mihi. **Dixit repetitaque Quid**; verrit
14 | longa; sententia [mandat](http://pastor-ad.io/questussilvas) quascumque nescio
15 | solebat [litore](http://lacrimas-ab.net/); noctes. *Hostem haerentem* circuit
16 | [plenaque tamen](http://www.sine.io/in).
17 |
18 | - Pedum ne indigenae finire invergens carpebat
19 | - Velit posses summoque
20 | - De fumos illa foret
21 |
22 | ## Est simul fameque tauri qua ad
23 |
24 | Locum nullus nisi vomentes. Ab Persea sermone vela, miratur aratro; eandem
25 | Argolicas gener.
26 |
27 | ## Me sol
28 |
29 | Nec dis certa fuit socer, Nonacria **dies** manet tacitaque sibi? Sucis est
30 | iactata Castrumque iudex, et iactato quoque terraeque es tandem et maternos
31 | vittis. Lumina litus bene poenamque animos callem ne tuas in leones illam dea
32 | cadunt genus, et pleno nunc in quod. Anumque crescentesque sanguinis
33 | [progenies](http://www.late.net/alimentavirides) nuribus rustica tinguet. Pater
34 | omnes liquido creditis noctem.
35 |
36 | if (mirrored(icmp_dvd_pim, 3, smbMirroredHard) != lion(clickImportQueue,
37 | viralItunesBalancing, bankruptcy_file_pptp)) {
38 | file += ip_cybercrime_suffix;
39 | }
40 | if (runtimeSmartRom == netMarketingWord) {
41 | virusBalancingWin *= scriptPromptBespoke + raster(post_drive,
42 | windowsSli);
43 | cd = address_hertz_trojan;
44 | soap_ccd.pcbServerGigahertz(asp_hardware_isa, offlinePeopleware, nui);
45 | } else {
46 | megabyte.api = modem_flowchart - web + syntaxHalftoneAddress;
47 | }
48 | if (3 < mebibyteNetworkAnimated) {
49 | pharming_regular_error *= jsp_ribbon + algorithm * recycleMediaKindle(
50 | dvrSyntax, cdma);
51 | adf_sla *= hoverCropDrive;
52 | templateNtfs = -1 - vertical;
53 | } else {
54 | expressionCompressionVariable.bootMulti = white_eup_javascript(
55 | table_suffix);
56 | guidPpiPram.tracerouteLinux += rtfTerabyteQuicktime(1,
57 | managementRosetta(webcamActivex), 740874);
58 | }
59 | var virusTweetSsl = nullGigo;
60 |
61 | ## Trepident sitimque
62 |
63 | Sentiet et ferali errorem fessam, coercet superbus, Ascaniumque in pennis
64 | mediis; dolor? Vidit imi **Aeacon** perfida propositos adde, tua Somni Fluctibus
65 | errante lustrat non.
66 |
67 | Tamen inde, vos videt e flammis Scythica parantem rupisque pectora umbras. Haec
68 | ficta canistris repercusso simul ego aris Dixit! Esse Fama trepidare hunc
69 | crescendo vigor ululasse vertice *exspatiantur* celer tepidique petita aversata
70 | oculis iussa est me ferro.
71 |
--------------------------------------------------------------------------------
/themes/hugo-book/exampleSite/content/docs/introduction/examples/_index.md:
--------------------------------------------------------------------------------
1 | # Ubi loqui
2 |
3 | ## Mentem genus facietque salire tempus bracchia
4 |
5 | Lorem markdownum partu paterno Achillem. Habent amne generosi aderant ad pellem
6 | nec erat sustinet merces columque haec et, dixit minus nutrit accipiam subibis
7 | subdidit. Temeraria servatum agros qui sed fulva facta. Primum ultima, dedit,
8 | suo quisque linguae medentes fixo: tum petis.
9 |
10 | ## Rapit vocant si hunc siste adspice
11 |
12 | Ora precari Patraeque Neptunia, dixit Danae [Cithaeron
13 | armaque](http://mersis-an.org/litoristum) maxima in **nati Coniugis** templis
14 | fluidove. Effugit usus nec ingreditur agmen *ac manus* conlato. Nullis vagis
15 | nequiquam vultibus aliquos altera *suum venis* teneas fretum. Armos [remotis
16 | hoc](http://tutum.io/me) sine ferrea iuncta quam!
17 |
18 | ## Locus fuit caecis
19 |
20 | Nefas discordemque domino montes numen tum humili nexilibusque exit, Iove. Quae
21 | miror esse, scelerisque Melaneus viribus. Miseri laurus. Hoc est proposita me
22 | ante aliquid, aura inponere candidioribus quidque accendit bella, sumpta.
23 | Intravit quam erat figentem hunc, motus de fontes parvo tempestate.
24 |
25 | iscsi_virus = pitch(json_in_on(eupViral),
26 | northbridge_services_troubleshooting, personal(
27 | firmware_rw.trash_rw_crm.device(interactive_gopher_personal,
28 | software, -1), megabit, ergonomicsSoftware(cmyk_usb_panel,
29 | mips_whitelist_duplex, cpa)));
30 | if (5) {
31 | managementNetwork += dma - boolean;
32 | kilohertz_token = 2;
33 | honeypot_affiliate_ergonomics = fiber;
34 | }
35 | mouseNorthbridge = byte(nybble_xmp_modem.horse_subnet(
36 | analogThroughputService * graphicPoint, drop(daw_bit, dnsIntranet),
37 | gateway_ospf), repository.domain_key.mouse(serverData(fileNetwork,
38 | trim_duplex_file), cellTapeDirect, token_tooltip_mashup(
39 | ripcordingMashup)));
40 | module_it = honeypot_driver(client_cold_dvr(593902, ripping_frequency) +
41 | coreLog.joystick(componentUdpLink), windows_expansion_touchscreen);
42 | bashGigabit.external.reality(2, server_hardware_codec.flops.ebookSampling(
43 | ciscNavigationBacklink, table + cleanDriver), indexProtocolIsp);
44 |
45 | ## Placabilis coactis nega ingemuit ignoscat nimia non
46 |
47 | Frontis turba. Oculi gravis est Delphice; *inque praedaque* sanguine manu non.
48 |
49 | if (ad_api) {
50 | zif += usb.tiffAvatarRate(subnet, digital_rt) + exploitDrive;
51 | gigaflops(2 - bluetooth, edi_asp_memory.gopher(queryCursor, laptop),
52 | panel_point_firmware);
53 | spyware_bash.statePopApplet = express_netbios_digital(
54 | insertion_troubleshooting.brouter(recordFolderUs), 65);
55 | }
56 | recursionCoreRay = -5;
57 | if (hub == non) {
58 | portBoxVirus = soundWeb(recursive_card(rwTechnologyLeopard),
59 | font_radcab, guidCmsScalable + reciprocalMatrixPim);
60 | left.bug = screenshot;
61 | } else {
62 | tooltipOpacity = raw_process_permalink(webcamFontUser, -1);
63 | executable_router += tape;
64 | }
65 | if (tft) {
66 | bandwidthWeb *= social_page;
67 | } else {
68 | regular += 611883;
69 | thumbnail /= system_lag_keyboard;
70 | }
71 |
72 | ## Caesorum illa tu sentit micat vestes papyriferi
73 |
74 | Inde aderam facti; Theseus vis de tauri illa peream. Oculos **uberaque** non
75 | regisque vobis cursuque, opus venit quam vulnera. Et maiora necemque, lege modo;
76 | gestanda nitidi, vero? Dum ne pectoraque testantur.
77 |
78 | Venasque repulsa Samos qui, exspectatum eram animosque hinc, [aut
79 | manes](http://www.creveratnon.net/apricaaetheriis), Assyrii. Cupiens auctoribus
80 | pariter rubet, profana magni super nocens. Vos ius sibilat inpar turba visae
81 | iusto! Sedes ante dum superest **extrema**.
82 |
--------------------------------------------------------------------------------
/themes/hugo-book/exampleSite/content/docs/introduction/examples/shortcodes.md:
--------------------------------------------------------------------------------
1 | ---
2 | weight: 3
3 | ---
4 |
5 | # Shortcodes
6 |
7 | ## Expand shortcode
8 |
9 | ### Default
10 |
11 | ```tpl
12 | {{* expand */>}}
13 | ## Markdown content
14 | Lorem markdownum insigne...
15 | {{* /expand */>}}
16 | ```
17 |
18 | {{< expand >}}
19 | ## Markdown content
20 | Lorem markdownum insigne...
21 | {{< /expand >}}
22 |
23 | ### With Custom Label
24 |
25 | ```tpl
26 | {{* expand "Custom Label" "..." */>}}
27 | ## Markdown content
28 | Lorem markdownum insigne...
29 | {{* /expand */>}}
30 | ```
31 |
32 | {{< expand "Custom Label" "..." >}}
33 | ## Markdown content
34 | Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
35 | stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa
36 | protulit, sed sed aere valvis inhaesuro Pallas animam: qui _quid_, ignes.
37 | Miseratus fonte Ditis conubia.
38 | {{< /expand >}}
39 |
40 | ## Buttons
41 |
42 | ```tpl
43 | {{* button relref="/" [class="..."] */>}}Get Home{{* /button */>}}
44 | {{* button href="https://github.com/alex-shpak/hugo-book" */>}}Contribute{{* /button */>}}
45 | ```
46 |
47 | {{< button relref="/" >}}Get Home{{< /button >}}
48 | {{< button href="https://github.com/alex-shpak/hugo-book" >}}Contribute{{< /button >}}
49 |
50 | ## Tabs
51 |
52 | ```tpl
53 | {{* tabs "uniqueid" */>}}
54 | {{* tab "MacOS" */>}} # MacOS Content {{* /tab */>}}
55 | {{* tab "Linux" */>}} # Linux Content {{* /tab */>}}
56 | {{* tab "Windows" */>}} # Windows Content {{* /tab */>}}
57 | {{* /tabs */>}}
58 | ```
59 |
60 | {{< tabs "uniqueid" >}}
61 | {{< tab "MacOS" >}}
62 | # MacOS
63 |
64 | This is tab **MacOS** content.
65 |
66 | Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
67 | stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa
68 | protulit, sed sed aere valvis inhaesuro Pallas animam: qui _quid_, ignes.
69 | Miseratus fonte Ditis conubia.
70 | {{< /tab >}}
71 |
72 | {{< tab "Linux" >}}
73 |
74 | # Linux
75 |
76 | This is tab **Linux** content.
77 |
78 | Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
79 | stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa
80 | protulit, sed sed aere valvis inhaesuro Pallas animam: qui _quid_, ignes.
81 | Miseratus fonte Ditis conubia.
82 | {{< /tab >}}
83 |
84 | {{< tab "Windows" >}}
85 |
86 | # Windows
87 |
88 | This is tab **Windows** content.
89 |
90 | Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
91 | stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa
92 | protulit, sed sed aere valvis inhaesuro Pallas animam: qui _quid_, ignes.
93 | Miseratus fonte Ditis conubia.
94 | {{< /tab >}}
95 | {{< /tabs >}}
96 |
97 | ## Columns
98 |
99 | ```html
100 | {{* columns */>}}
101 | # Left Content
102 | Lorem markdownum insigne...
103 |
104 | <--->
105 |
106 | # Mid Content
107 | Lorem markdownum insigne...
108 |
109 | <--->
110 |
111 | # Right Content
112 | Lorem markdownum insigne...
113 | {{* /columns */>}}
114 | ```
115 |
116 | {{< columns >}}
117 | ## Left Content
118 | Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
119 | stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa
120 | protulit, sed sed aere valvis inhaesuro Pallas animam: qui _quid_, ignes.
121 | Miseratus fonte Ditis conubia.
122 |
123 | <--->
124 |
125 | ## Mid Content
126 | Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
127 | stringit, frustra Saturnius uteroque inter!
128 |
129 | <--->
130 |
131 | ## Right Content
132 | Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
133 | stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa
134 | protulit, sed sed aere valvis inhaesuro Pallas animam: qui _quid_, ignes.
135 | Miseratus fonte Ditis conubia.
136 | {{< /columns >}}
137 |
138 |
139 | ## Mermaid Chart
140 |
141 | {{< columns >}}
142 | ```tpl
143 | {{* mermaid [class="text-center"]*/>}}
144 | sequenceDiagram
145 | Alice->>Bob: Hello Bob, how are you?
146 | alt is sick
147 | Bob->>Alice: Not so good :(
148 | else is well
149 | Bob->>Alice: Feeling fresh like a daisy
150 | end
151 | opt Extra response
152 | Bob->>Alice: Thanks for asking
153 | end
154 | {{* /mermaid */>}}
155 | ```
156 |
157 | <--->
158 |
159 | {{< mermaid >}}
160 | sequenceDiagram
161 | Alice->>Bob: Hello Bob, how are you?
162 | alt is sick
163 | Bob->>Alice: Not so good :(
164 | else is well
165 | Bob->>Alice: Feeling fresh like a daisy
166 | end
167 | opt Extra response
168 | Bob->>Alice: Thanks for asking
169 | end
170 | {{< /mermaid >}}
171 |
172 | {{< /columns >}}
173 |
174 |
175 | ## KaTeX
176 |
177 | {{< columns >}}
178 |
179 | ```latex
180 | {{* katex */>}}
181 | x = \begin{cases}
182 | a &\text{if } b \\
183 | c &\text{if } d
184 | \end{cases}
185 | {{* /katex */>}}
186 | ```
187 |
188 | <--->
189 |
190 | {{< katex >}}
191 | x = \begin{cases}
192 | a &\text{if } b \\
193 | c &\text{if } d
194 | \end{cases}
195 | {{< /katex >}}
196 |
197 | {{< /columns >}}
198 |
199 |
200 |
--------------------------------------------------------------------------------
/themes/hugo-book/exampleSite/content/docs/introduction/examples/with-toc.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: With Table of Contents
3 | weight: 1
4 | ---
5 | # Caput vino delphine in tamen vias
6 |
7 | ## Cognita laeva illo fracta
8 |
9 | Lorem markdownum pavent auras, surgit nunc cingentibus libet **Laomedonque que**
10 | est. Pastor [An](http://est.org/ire.aspx) arbor filia foedat, ne [fugit
11 | aliter](http://www.indiciumturbam.org/moramquid.php), per. Helicona illas et
12 | callida neptem est *Oresitrophos* caput, dentibus est venit. Tenet reddite
13 | [famuli](http://www.antro-et.net/) praesentem fortibus, quaeque vis foret si
14 | frondes *gelidos* gravidae circumtulit [inpulit armenta
15 | nativum](http://incurvasustulit.io/illi-virtute.html).
16 |
17 | 1. Te at cruciabere vides rubentis manebo
18 | 2. Maturuit in praetemptat ruborem ignara postquam habitasse
19 | 3. Subitarum supplevit quoque fontesque venabula spretis modo
20 | 4. Montis tot est mali quasque gravis
21 | 5. Quinquennem domus arsit ipse
22 | 6. Pellem turis pugnabant locavit
23 |
24 | ## Natus quaerere
25 |
26 | Pectora et sine mulcere, coniuge dum tincta incurvae. Quis iam; est dextra
27 | Peneosque, metuis a verba, primo. Illa sed colloque suis: magno: gramen, aera
28 | excutiunt concipit.
29 |
30 | > Phrygiae petendo suisque extimuit, super, pars quod audet! Turba negarem.
31 | > Fuerat attonitus; et dextra retinet sidera ulnas undas instimulat vacuae
32 | > generis? *Agnus* dabat et ignotis dextera, sic tibi pacis **feriente at mora**
33 | > euhoeque *comites hostem* vestras Phineus. Vultuque sanguine dominoque [metuit
34 | > risi](http://iuvat.org/eundem.php) fama vergit summaque meus clarissimus
35 | > artesque tinguebat successor nominis cervice caelicolae.
36 |
37 | ## Limitibus misere sit
38 |
39 | Aurea non fata repertis praerupit feruntur simul, meae hosti lentaque *citius
40 | levibus*, cum sede dixit, Phaethon texta. *Albentibus summos* multifidasque
41 | iungitur loquendi an pectore, mihi ursaque omnia adfata, aeno parvumque in animi
42 | perlucentes. Epytus agis ait vixque clamat ornum adversam spondet, quid sceptra
43 | ipsum **est**. Reseret nec; saeva suo passu debentia linguam terga et aures et
44 | cervix [de](http://www.amnem.io/pervenit.aspx) ubera. Coercet gelidumque manus,
45 | doluit volvitur induta?
46 |
47 | ## Enim sua
48 |
49 | Iuvenilior filia inlustre templa quidem herbis permittat trahens huic. In
50 | cruribus proceres sole crescitque *fata*, quos quos; merui maris se non tamen
51 | in, mea.
52 |
53 | ## Germana aves pignus tecta
54 |
55 | Mortalia rudibusque caelum cognosceret tantum aquis redito felicior texit, nec,
56 | aris parvo acre. Me parum contulerant multi tenentem, gratissime suis; vultum tu
57 | occupat deficeret corpora, sonum. E Actaea inplevit Phinea concepit nomenque
58 | potest sanguine captam nulla et, in duxisses campis non; mercede. Dicere cur
59 | Leucothoen obitum?
60 |
61 | Postibus mittam est *nubibus principium pluma*, exsecratur facta et. Iunge
62 | Mnemonidas pallamque pars; vere restitit alis flumina quae **quoque**, est
63 | ignara infestus Pyrrha. Di ducis terris maculatum At sede praemia manes
64 | nullaque!
65 |
--------------------------------------------------------------------------------
/themes/hugo-book/exampleSite/content/docs/introduction/examples/without-toc.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Without Table of Contents
3 | weight: 2
4 | bookToc: false
5 | ---
6 |
7 | # At me ipso nepotibus nunc celebratior genus
8 |
9 | ## Tanto oblite
10 |
11 | Lorem markdownum pectora novis patenti igne sua opus aurae feras materiaque
12 | illic demersit imago et aristas questaque posset. Vomit quoque suo inhaesuro
13 | clara. Esse cumque, per referri triste. Ut exponit solisque communis in tendens
14 | vincetis agisque iamque huic bene ante vetat omina Thebae rates. Aeacus servat
15 | admonitu concidit, ad resimas vultus et rugas vultu **dignamque** Siphnon.
16 |
17 | Quam iugulum regia simulacra, plus meruit humo pecorumque haesit, ab discedunt
18 | dixit: ritu pharetramque. Exul Laurenti orantem modo, per densum missisque labor
19 | manibus non colla unum, obiectat. Tu pervia collo, fessus quae Cretenque Myconon
20 | crate! Tegumenque quae invisi sudore per vocari quaque plus ventis fluidos. Nodo
21 | perque, fugisse pectora sorores.
22 |
23 | ## Summe promissa supple vadit lenius
24 |
25 | Quibus largis latebris aethera versato est, ait sentiat faciemque. Aequata alis
26 | nec Caeneus exululat inclite corpus est, ire **tibi** ostendens et tibi. Rigent
27 | et vires dique possent lumina; **eadem** dixit poma funeribus paret et felix
28 | reddebant ventis utile lignum.
29 |
30 | 1. Remansit notam Stygia feroxque
31 | 2. Et dabit materna
32 | 3. Vipereas Phrygiaeque umbram sollicito cruore conlucere suus
33 | 4. Quarum Elis corniger
34 | 5. Nec ieiunia dixit
35 |
36 | Vertitur mos ortu ramosam contudit dumque; placabat ac lumen. Coniunx Amoris
37 | spatium poenamque cavernis Thebae Pleiadasque ponunt, rapiare cum quae parum
38 | nimium rima.
39 |
40 | ## Quidem resupinus inducto solebat una facinus quae
41 |
42 | Credulitas iniqua praepetibus paruit prospexit, voce poena, sub rupit sinuatur,
43 | quin suum ventorumque arcadiae priori. Soporiferam erat formamque, fecit,
44 | invergens, nymphae mutat fessas ait finge.
45 |
46 | 1. Baculum mandataque ne addere capiti violentior
47 | 2. Altera duas quam hoc ille tenues inquit
48 | 3. Sicula sidereus latrantis domoque ratae polluit comites
49 | 4. Possit oro clausura namque se nunc iuvenisque
50 | 5. Faciem posuit
51 | 6. Quodque cum ponunt novercae nata vestrae aratra
52 |
53 | Ite extrema Phrygiis, patre dentibus, tonso perculit, enim blanda, manibus fide
54 | quos caput armis, posse! Nocendo fas Alcyonae lacertis structa ferarum manus
55 | fulmen dubius, saxa caelum effuge extremis fixum tumor adfecit **bella**,
56 | potentes? Dum nec insidiosa tempora tegit
57 | [spirarunt](http://mihiferre.net/iuvenes-peto.html). Per lupi pars foliis,
58 | porreximus humum negant sunt subposuere Sidone steterant auro. Memoraverit sine:
59 | ferrum idem Orion caelum heres gerebat fixis?
60 |
--------------------------------------------------------------------------------
/themes/hugo-book/exampleSite/content/docs/more-examples/_index.md:
--------------------------------------------------------------------------------
1 | ---
2 | weight: 2
3 | bookFlatSection: true
4 | ---
5 |
--------------------------------------------------------------------------------
/themes/hugo-book/exampleSite/content/docs/more-examples/advanced.md:
--------------------------------------------------------------------------------
1 | # Vagus elidunt
2 |
3 | ## Mole et vultus populifer quaque primoque non
4 |
5 | Lorem **markdownum pignora pelle** est tota propiore conpellat pectoribus de
6 | pectora summo. Redit teque digerit hominumque toris verebor lumina non cervice
7 | subde tollit usus habet Arctonque, furores quas nec ferunt. Quoque montibus nunc
8 | caluere tempus inhospita parcite confusaque translucet patri vestro qui optatis
9 | lumine cognoscere flos nubis! Fronde ipsamque patulos Dryopen deorum.
10 |
11 | 1. Exierant elisi ambit vivere dedere
12 | 2. Duce pollice
13 | 3. Eris modo
14 | 4. Spargitque ferrea quos palude
15 |
16 | Rursus nulli murmur; hastile inridet ut ab gravi sententia! Nomine potitus
17 | silentia flumen, sustinet placuit petis in dilapsa erat sunt. [Atria
18 | tractus](http://agendo-dis.io/) malis.
19 |
20 | 1. Comas hunc haec pietate fetum procerum dixit
21 | 2. Post torum vates letum Tiresia
22 | 3. Flumen querellas
23 | 4. Arcanaque montibus omnes
24 | 5. Quidem et
25 |
26 | ## Mane refeci capiebant unda mulcebat
27 |
28 | Victa caducifer, [malo vulnere](http://www.nec.org/iactorcolonos.php) contra
29 | dicere aurato, ludit regale, voca! Retorsit colit est profanae esse virescere
30 | furit nec; iaculi [matertera](http://iugis-thalamique.com/pecus) et visa est,
31 | viribus. Divesque creatis, tecta novat collumque vulnus
32 | [est](http://canentiet.net/lateri.php), parvas. **Faces illo pepulere** tempus
33 | adest. Tendit flamma, ab opes virum sustinet, sidus sequendo urbis.
34 |
35 | var multiplatform = cifs(illegal, zip, memory) / pcbPowerJavascript;
36 | hdmi -= 3;
37 | tunneling(constant(service_fi_hyper, avatarBar), matrixUmlMbps);
38 | frequency /= nat(keyboardRecycle, programmingGnuPerl) + icfExbibyteCursor;
39 | io_dithering(-5, markup / languageShortcut - driveHtml);
40 |
41 | Iubar proles corpore raptos vero auctor imperium; sed et huic: manus caeli
42 | Lelegas tu lux. Verbis obstitit intus oblectamina fixis linguisque ausus sperare
43 | Echionides cornuaque tenent clausit possit. Omnia putatur. Praeteritae refert
44 | ausus; ferebant e primus lora nutat, vici quae mea ipse. Et iter nil spectatae
45 | vulnus haerentia iuste et exercebat, sui et.
46 |
47 | Eurytus Hector, [materna](http://mandereevincitque.net/), ipsumque ut Politen,
48 | nec, nate, ignari, vernum cohaesit sequitur. Vel **mitis temploque** vocatus,
49 | inque alis, *oculos nomen* non silvis corpore coniunx ne displicet illa.
50 | Crescunt non unus, vidit visa quantum inmiti flumina mortis facto sic: undique a
51 | alios vincula sunt iactata abdita! Suspenderat ego fuit tendit: luna, ante urbem
52 | Propoetides **parte**.
--------------------------------------------------------------------------------
/themes/hugo-book/exampleSite/content/docs/more-examples/client.md:
--------------------------------------------------------------------------------
1 | # Ista qua aera
2 |
3 | ## Tetigisse hac duc omnipotens urbis per sapiente
4 |
5 | Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
6 | stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa
7 | protulit, sed sed aere valvis inhaesuro Pallas animam: qui *quid*, ignes.
8 | Miseratus fonte Ditis conubia.
9 |
10 | var mnemonicPcmcia = file;
11 | if (bookmarkMultiprocessing) {
12 | core.intranetDigitize = menu(vdslWordart(enterprise,
13 | dviRealityTeraflops));
14 | } else {
15 | portal_socket.jsp_shareware_digital = multicasting(component_uml);
16 | memory.ppc_title_hit(lunWebFormat + fontSmartphoneView, tween *
17 | default_hard, 5 + laptopMethod);
18 | wddm_tablet_null.widgetFileRate(3, leakMaskResponsive);
19 | }
20 | var siteRjSoftware = installer;
21 | html.text = address + nasSystemDns;
22 |
23 | ## Lac roratis Diomede
24 |
25 | *Aut in vivitur* quam ibi is veniebat Herculis mihi hominem! In matrem gesserit
26 | manus [coniuge silva](http://etinachus.org/cornibusalter.html) pectore simul nec
27 | felix in haud ostendit lacrimavit mora. Digna adspice temptata, Palaestina armis
28 | at crura centum tellus ni tibi Amphiona mansit, bello tibi pugnat fuit. Sidera
29 | nec ambo temporis summe tempore, falsa committere, pater horrenda, erat ast
30 | cadunt preces.
31 |
32 | 1. Ventorum pariturae cum discors fit dabat inguina
33 | 2. Armeniae viscera
34 | 3. Et monitusque boum misereri
35 | 4. Obliquaque primasque suae
36 |
37 | ## Ovaque in tendens tibi Iovis iuga
38 |
39 | Vagatur laboribus vocandus [honorque segnior
40 | inclinat](http://www.neve-tellus.io/) petentes manere ut terram fundit; sunt.
41 | Pressit eodem inmotae quasque linguam, sub famem animos dei nocte futura
42 | Laconide India. Posset iter nata negarit *limina latus postquam* serior, cum dic
43 | area iamdudum non! Et curaque [me illo](http://testudine-est.com/): addidit
44 | tuam, Cerealia, fila undae Ilithyiam proceresque tegens numero dominaeque
45 | **regna** humanis. Multo [adstringit hirsutaque](http://www.e.org/est.php)
46 | crimine postquam perfudit illis, a mutua, memorant.
47 |
48 | ## His nocte ipse cum oculorum recepta ignorat
49 |
50 | Minos ad carmina exire studiosior Talia tamen, est a hi de quae ipsa et quoniam.
51 | Se victus at unca tantae eurus Euippe Bacchumque vocantia.
52 |
53 | Ullum frena statione de at praeferret classi Acarnanum iacuit lacertis gemino;
54 | ad caperet **finiat**! Utque videt ingemuit Dulichium paravi portaque te et, tot
55 | ab caesariem sumit, vias in rerum te.
--------------------------------------------------------------------------------
/themes/hugo-book/exampleSite/content/docs/more-examples/hidden.md:
--------------------------------------------------------------------------------
1 | ---
2 | bookHidden: true
3 | ---
4 |
5 | # This page is hidden in menu
6 |
7 | # Quondam non pater est dignior ille Eurotas
8 |
9 | ## Latent te facies
10 |
11 | Lorem markdownum arma ignoscas vocavit quoque ille texit mandata mentis ultimus,
12 | frementes, qui in vel. Hippotades Peleus [pennas
13 | conscia](http://gratia.net/tot-qua.php) cuiquam Caeneus quas.
14 |
15 | - Pater demittere evincitque reddunt
16 | - Maxime adhuc pressit huc Danaas quid freta
17 | - Soror ego
18 | - Luctus linguam saxa ultroque prior Tatiumque inquit
19 | - Saepe liquitur subita superata dederat Anius sudor
20 |
21 | ## Cum honorum Latona
22 |
23 | O fallor [in sustinui
24 | iussorum](http://www.spectataharundine.org/aquas-relinquit.html) equidem.
25 | Nymphae operi oris alii fronde parens dumque, in auro ait mox ingenti proxima
26 | iamdudum maius?
27 |
28 | reality(burnDocking(apache_nanometer),
29 | pad.property_data_programming.sectorBrowserPpga(dataMask, 37,
30 | recycleRup));
31 | intellectualVaporwareUser += -5 * 4;
32 | traceroute_key_upnp /= lag_optical(android.smb(thyristorTftp));
33 | surge_host_golden = mca_compact_device(dual_dpi_opengl, 33,
34 | commerce_add_ppc);
35 | if (lun_ipv) {
36 | verticalExtranet(1, thumbnail_ttl, 3);
37 | bar_graphics_jpeg(chipset - sector_xmp_beta);
38 | }
39 |
40 | ## Fronde cetera dextrae sequens pennis voce muneris
41 |
42 | Acta cretus diem restet utque; move integer, oscula non inspirat, noctisque
43 | scelus! Nantemque in suas vobis quamvis, et labori!
44 |
45 | var runtimeDiskCompiler = home - array_ad_software;
46 | if (internic > disk) {
47 | emoticonLockCron += 37 + bps - 4;
48 | wan_ansi_honeypot.cardGigaflops = artificialStorageCgi;
49 | simplex -= downloadAccess;
50 | }
51 | var volumeHardeningAndroid = pixel + tftp + onProcessorUnmount;
52 | sector(memory(firewire + interlaced, wired));
--------------------------------------------------------------------------------
/themes/hugo-book/exampleSite/content/docs/more-examples/server.md:
--------------------------------------------------------------------------------
1 | # Nimium sacravere cetera exorata multifidasque satia
2 |
3 | ## Datum perierunt nato
4 |
5 | Lorem markdownum. Sit en turpe, recessit nominibus et sanguis totis. Unaque
6 | cognitius docuit sensimus mutasse terra flammas. Nec nunc sustinet Coeranon
7 | figura Erecthida saepe *gestu vel*: quod mei. Docto interdum quasi labefactus
8 | nocentius miserrimus pars cum missi matrem, ipse fletus
9 | [illo](http://fuerit-cultus.net/) super.
10 |
11 | 1. Metuunt non paene iniectis licuit
12 | 2. Extemplo iugulum relictis reddidit caput
13 | 3. Frustra adspiceres viae
14 | 4. Non fluctibus civiliter pater procedit non
15 | 5. Deos spumis ille aderam semper Stygios quantum
16 | 6. Orgia hoc
17 |
18 | ## Dare hirtus cervice Cecropis
19 |
20 | Si veteris alas proelia, sic remotis in portus nisi minimae acerris carina: et
21 | ne. Crimina longis, visae, quae et cur innuba dabat Haedis non. **Multorumque**
22 | damus qua, circumtulit teli, nec cum ait, o procul miserabile cursus. Tuam
23 | Rhodanumque ipse **scelus** humum fratrem volucrumque tandem seque domus fuerat
24 | quam per quidem ululasse ab aquas vocari.
25 |
26 | 1. Inperfecta frugum sed perennis deposuit
27 | 2. Quem cortice penthea venerisque perque perque deditque
28 | 3. Cerno impete
29 |
30 | ## Daedalon inguina mea Autolycus caeleste lumina et
31 |
32 | Cupiere adulter parentum, semineces malit nec seu luce superos integer
33 | inritaturque antro cum. Aegeus sic tabe nulla satyri notissima inmensa et aquas
34 | et. Digiti quis addit *materna*, et arma tu aegide dixit. *Traxerat* ubera, fuit
35 | se cacumine praeteritae corpore esse pendentem Diana gratissima dolor generi
36 | clamoribus occupat; flavam arma. Ponat invidiosa honores.
37 |
38 | var nybble_computer_market = client_sd_webmail.margin(romGamma(nui,
39 | internet, 78) + p_malware_algorithm(thyristorCloneBare, backup,
40 | multicastingHsf));
41 | circuit(thickDesktopPpm, computer(protocol_alert(sla)));
42 | if (integrated_memory_rich(array_printer.thermistor_lock_web(
43 | camera.gnu_read_engine.third(4, rom_point_risc), piracy(
44 | paste_analyst, os, multiprocessingKilohertz)))) {
45 | click_samba = 1;
46 | }
47 |
48 | Liber virorum acervo quaecumque placabat Luna recessit utque, nox cum nymphae
49 | licet? Arce tibi commissus letalis ambo fuit bis deus? Dixit mea, non [Quid
50 | potentior osculaque](http://ibat.org/) factis opposuitque semel perspexerat
51 | posuitque parte quas [sive](http://www.est.com/seanimos).
--------------------------------------------------------------------------------
/themes/hugo-book/exampleSite/content/menu/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | headless: true
3 | ---
4 |
5 | - [**Introduction**]({{< relref "/docs/introduction" >}})
6 | - [Examples]({{< relref "/docs/introduction/examples" >}})
7 | - [With Table of Contents]({{< relref "/docs/introduction/examples/with-toc" >}})
8 | - [Without Table of Contents]({{< relref "/docs/introduction/examples/without-toc" >}})
9 | - [Shortcodes]({{< relref "/docs/introduction/examples/shortcodes" >}})
10 | - **More Examples**
11 | - [Server]({{< relref "/docs/more-examples/server" >}})
12 | - [Client]({{< relref "/docs/more-examples/client" >}})
13 | - [Advanced]({{< relref "/docs/more-examples/advanced" >}})
14 | - [**Blog**]({{< relref "/posts" >}})
15 |
--------------------------------------------------------------------------------
/themes/hugo-book/exampleSite/content/posts/goisforlovers.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "(Hu)go Template Primer"
3 | description = ""
4 | tags = [
5 | "go",
6 | "golang",
7 | "templates",
8 | "themes",
9 | "development",
10 | ]
11 | date = "2014-04-02"
12 | categories = [
13 | "Development",
14 | "golang",
15 | ]
16 | menu = "main"
17 | +++
18 |
19 | Hugo uses the excellent [Go][] [html/template][gohtmltemplate] library for
20 | its template engine. It is an extremely lightweight engine that provides a very
21 | small amount of logic. In our experience that it is just the right amount of
22 | logic to be able to create a good static website. If you have used other
23 | template systems from different languages or frameworks you will find a lot of
24 | similarities in Go templates.
25 |
26 | This document is a brief primer on using Go templates. The [Go docs][gohtmltemplate]
27 | provide more details.
28 |
29 | ## Introduction to Go Templates
30 |
31 | Go templates provide an extremely simple template language. It adheres to the
32 | belief that only the most basic of logic belongs in the template or view layer.
33 | One consequence of this simplicity is that Go templates parse very quickly.
34 |
35 | A unique characteristic of Go templates is they are content aware. Variables and
36 | content will be sanitized depending on the context of where they are used. More
37 | details can be found in the [Go docs][gohtmltemplate].
38 |
39 | ## Basic Syntax
40 |
41 | Golang templates are HTML files with the addition of variables and
42 | functions.
43 |
44 | **Go variables and functions are accessible within {{ }}**
45 |
46 | Accessing a predefined variable "foo":
47 |
48 | {{ foo }}
49 |
50 | **Parameters are separated using spaces**
51 |
52 | Calling the add function with input of 1, 2:
53 |
54 | {{ add 1 2 }}
55 |
56 | **Methods and fields are accessed via dot notation**
57 |
58 | Accessing the Page Parameter "bar"
59 |
60 | {{ .Params.bar }}
61 |
62 | **Parentheses can be used to group items together**
63 |
64 | {{ if or (isset .Params "alt") (isset .Params "caption") }} Caption {{ end }}
65 |
66 |
67 | ## Variables
68 |
69 | Each Go template has a struct (object) made available to it. In hugo each
70 | template is passed either a page or a node struct depending on which type of
71 | page you are rendering. More details are available on the
72 | [variables](/layout/variables) page.
73 |
74 | A variable is accessed by referencing the variable name.
75 |
76 | {{ .Title }}
77 |
78 | Variables can also be defined and referenced.
79 |
80 | {{ $address := "123 Main St."}}
81 | {{ $address }}
82 |
83 |
84 | ## Functions
85 |
86 | Go template ship with a few functions which provide basic functionality. The Go
87 | template system also provides a mechanism for applications to extend the
88 | available functions with their own. [Hugo template
89 | functions](/layout/functions) provide some additional functionality we believe
90 | are useful for building websites. Functions are called by using their name
91 | followed by the required parameters separated by spaces. Template
92 | functions cannot be added without recompiling hugo.
93 |
94 | **Example:**
95 |
96 | {{ add 1 2 }}
97 |
98 | ## Includes
99 |
100 | When including another template you will pass to it the data it will be
101 | able to access. To pass along the current context please remember to
102 | include a trailing dot. The templates location will always be starting at
103 | the /layout/ directory within Hugo.
104 |
105 | **Example:**
106 |
107 | {{ template "chrome/header.html" . }}
108 |
109 |
110 | ## Logic
111 |
112 | Go templates provide the most basic iteration and conditional logic.
113 |
114 | ### Iteration
115 |
116 | Just like in Go, the Go templates make heavy use of range to iterate over
117 | a map, array or slice. The following are different examples of how to use
118 | range.
119 |
120 | **Example 1: Using Context**
121 |
122 | {{ range array }}
123 | {{ . }}
124 | {{ end }}
125 |
126 | **Example 2: Declaring value variable name**
127 |
128 | {{range $element := array}}
129 | {{ $element }}
130 | {{ end }}
131 |
132 | **Example 2: Declaring key and value variable name**
133 |
134 | {{range $index, $element := array}}
135 | {{ $index }}
136 | {{ $element }}
137 | {{ end }}
138 |
139 | ### Conditionals
140 |
141 | If, else, with, or, & and provide the framework for handling conditional
142 | logic in Go Templates. Like range, each statement is closed with `end`.
143 |
144 |
145 | Go Templates treat the following values as false:
146 |
147 | * false
148 | * 0
149 | * any array, slice, map, or string of length zero
150 |
151 | **Example 1: If**
152 |
153 | {{ if isset .Params "title" }}{{ index .Params "title" }} {{ end }}
154 |
155 | **Example 2: If -> Else**
156 |
157 | {{ if isset .Params "alt" }}
158 | {{ index .Params "alt" }}
159 | {{else}}
160 | {{ index .Params "caption" }}
161 | {{ end }}
162 |
163 | **Example 3: And & Or**
164 |
165 | {{ if and (or (isset .Params "title") (isset .Params "caption")) (isset .Params "attr")}}
166 |
167 | **Example 4: With**
168 |
169 | An alternative way of writing "if" and then referencing the same value
170 | is to use "with" instead. With rebinds the context `.` within its scope,
171 | and skips the block if the variable is absent.
172 |
173 | The first example above could be simplified as:
174 |
175 | {{ with .Params.title }}{{ . }} {{ end }}
176 |
177 | **Example 5: If -> Else If**
178 |
179 | {{ if isset .Params "alt" }}
180 | {{ index .Params "alt" }}
181 | {{ else if isset .Params "caption" }}
182 | {{ index .Params "caption" }}
183 | {{ end }}
184 |
185 | ## Pipes
186 |
187 | One of the most powerful components of Go templates is the ability to
188 | stack actions one after another. This is done by using pipes. Borrowed
189 | from unix pipes, the concept is simple, each pipeline's output becomes the
190 | input of the following pipe.
191 |
192 | Because of the very simple syntax of Go templates, the pipe is essential
193 | to being able to chain together function calls. One limitation of the
194 | pipes is that they only can work with a single value and that value
195 | becomes the last parameter of the next pipeline.
196 |
197 | A few simple examples should help convey how to use the pipe.
198 |
199 | **Example 1 :**
200 |
201 | {{ if eq 1 1 }} Same {{ end }}
202 |
203 | is the same as
204 |
205 | {{ eq 1 1 | if }} Same {{ end }}
206 |
207 | It does look odd to place the if at the end, but it does provide a good
208 | illustration of how to use the pipes.
209 |
210 | **Example 2 :**
211 |
212 | {{ index .Params "disqus_url" | html }}
213 |
214 | Access the page parameter called "disqus_url" and escape the HTML.
215 |
216 | **Example 3 :**
217 |
218 | {{ if or (or (isset .Params "title") (isset .Params "caption")) (isset .Params "attr")}}
219 | Stuff Here
220 | {{ end }}
221 |
222 | Could be rewritten as
223 |
224 | {{ isset .Params "caption" | or isset .Params "title" | or isset .Params "attr" | if }}
225 | Stuff Here
226 | {{ end }}
227 |
228 |
229 | ## Context (aka. the dot)
230 |
231 | The most easily overlooked concept to understand about Go templates is that {{ . }}
232 | always refers to the current context. In the top level of your template this
233 | will be the data set made available to it. Inside of a iteration it will have
234 | the value of the current item. When inside of a loop the context has changed. .
235 | will no longer refer to the data available to the entire page. If you need to
236 | access this from within the loop you will likely want to set it to a variable
237 | instead of depending on the context.
238 |
239 | **Example:**
240 |
241 | {{ $title := .Site.Title }}
242 | {{ range .Params.tags }}
243 | {{ . }} - {{ $title }}
244 | {{ end }}
245 |
246 | Notice how once we have entered the loop the value of {{ . }} has changed. We
247 | have defined a variable outside of the loop so we have access to it from within
248 | the loop.
249 |
250 | # Hugo Parameters
251 |
252 | Hugo provides the option of passing values to the template language
253 | through the site configuration (for sitewide values), or through the meta
254 | data of each specific piece of content. You can define any values of any
255 | type (supported by your front matter/config format) and use them however
256 | you want to inside of your templates.
257 |
258 |
259 | ## Using Content (page) Parameters
260 |
261 | In each piece of content you can provide variables to be used by the
262 | templates. This happens in the [front matter](/content/front-matter).
263 |
264 | An example of this is used in this documentation site. Most of the pages
265 | benefit from having the table of contents provided. Sometimes the TOC just
266 | doesn't make a lot of sense. We've defined a variable in our front matter
267 | of some pages to turn off the TOC from being displayed.
268 |
269 | Here is the example front matter:
270 |
271 | ```
272 | ---
273 | title: "Permalinks"
274 | date: "2013-11-18"
275 | aliases:
276 | - "/doc/permalinks/"
277 | groups: ["extras"]
278 | groups_weight: 30
279 | notoc: true
280 | ---
281 | ```
282 |
283 | Here is the corresponding code inside of the template:
284 |
285 | {{ if not .Params.notoc }}
286 |
287 | {{ .TableOfContents }}
288 |
289 | {{ end }}
290 |
291 |
292 |
293 | ## Using Site (config) Parameters
294 | In your top-level configuration file (eg, `config.yaml`) you can define site
295 | parameters, which are values which will be available to you in chrome.
296 |
297 | For instance, you might declare:
298 |
299 | ```yaml
300 | params:
301 | CopyrightHTML: "Copyright © 2013 John Doe. All Rights Reserved."
302 | TwitterUser: "spf13"
303 | SidebarRecentLimit: 5
304 | ```
305 |
306 | Within a footer layout, you might then declare a `