-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.xml
6538 lines (5225 loc) · 515 KB
/
index.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>语千·刻一 on 彭浩 ~ Hao Peng</title>
<link>/</link>
<description>Recent content in 语千·刻一 on 彭浩 ~ Hao Peng</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language>
<lastBuildDate>Sat, 01 Jan 2005 00:00:00 +0000</lastBuildDate>
<atom:link href="/" rel="self" type="application/rss+xml" />
<item>
<title>LaTeX 黑魔法(三):定义参数变长的命令 z</title>
<link>/tech/2017/07/30/define-a-new-command-with-different-amount-of-parameters-in-latex/</link>
<pubDate>Sun, 30 Jul 2017 00:00:00 +0000</pubDate>
<guid>/tech/2017/07/30/define-a-new-command-with-different-amount-of-parameters-in-latex/</guid>
<description>
<p><strong>原文地址</strong>:<a href="https://liam0205.me/2017/07/30/define-a-new-command-with-different-amount-of-parameters-in-LaTeX/" target="_blank">https://liam0205.me/2017/07/30/define-a-new-command-with-different-amount-of-parameters-in-LaTeX/</a></p>
<p>在 C++ 中,我们可以为同一个函数赋予不同的执行内容,这种行为称之为「函数重载」。具体重载的函数,共享同一个函数名,但是接收的函数参数在数量、类型上不同。LaTeX 是宏语言,没有一般意义上的参数类型的说法。但是,有没有办法在 LaTeX 中「重载」一个宏,根据输入的参数数量不同,而产生不同的效果呢?</p>
<p>本文给出解决方案。</p>
<p></p>
<h1 id="在-tex-和-latex2e-中定义新命令">在 TeX 和 LaTeX2e 中定义新命令</h1>
<p>TeX 中,定义新命令的标准方法是使用 TeX 原语 <code>\def</code>。它有几个变种,记录如下。</p>
<ul>
<li><code>\def</code>:局部定义,定义时不展开;</li>
<li><code>\edef</code>:局部定义,定义时完全展开;</li>
<li><code>\gdef</code>:相当于 <code>\global\def</code>;</li>
<li><code>\xdef</code>:相当于 <code>\global\edef</code>。</li>
</ul>
<p>建立在 TeX 之上的各种格式,其提供的定义新命令的方案,都是通过这四个 <code>\def</code> 来实现的。LaTeX2e 中定义新命令的标准方法是使用 <code>\newcommand</code>。它也有几个变种,记录如下。</p>
<ul>
<li><code>\newcommand</code>:新定义一个命令,如果该命令已有定义,则报错;</li>
<li><code>\renewcommand</code>:重定义一个命令,如果该命令未定义,则报错;</li>
<li><code>\providecommand</code>:如果该命令未定义,则定义一个新的命令;否则,啥也不干。</li>
</ul>
<p>当然,在 LaTeX2e 中,也有 <code>\DeclareRobustCommand</code> 一系列命令,可以用来定义新的命令。这一系列命令,是 LaTeX2e 针对「脆弱命令」问题,提供的一些保护机制。此处不表。</p>
<p>在标准的方法中,不论是 TeX 还是 LaTeX2e,都没有提供「参数变长」的实现方法。也就是说,如果不引入奇怪的技巧,我们在普通的 LaTeX 文稿中,是无法重载命令的。</p>
<h1 id="ifnextchar"><code>\@ifnextchar</code></h1>
<p><code>\@ifnextchar</code> 是<a href="/2015/04/10/how-to-list-unnumbered-section-in-the-table-of-contents/">一个 LaTeX 内部宏</a>。它的作用,是「预读」输入列表的下一个字符,然后判断预读的字符是否与作者期待的字符一致,执行不同的分支。</p>
<p>例如,我们知道,LaTeX 命令的可选参数,默认是放在所有必选参数之前。那么,我们是否有可能让可选参数放在必选参数之后呢?答案当然是肯定的,利用 <code>\@ifnextchar</code> 就可以做到。</p>
<pre><code class="language-tex">\documentclass{article}
\makeatletter
\newcommand{\foo@helper@i}[1]{One parameter: #1{}.}
\def\foo@helper@ii #1[#2]{Two parameters: #1{}, #2{}.}
\newcommand{\foo}[1]{%
\@ifnextchar[%
{\foo@helper@ii{#1}}%
{\foo@helper@i{#1}}%
}
\makeatother
\begin{document}
\foo{hello}
\foo{hello}[world]
\end{document}
</code></pre>
<p>我们来看 <code>\foo</code> 的定义。它接收一个标准的 LaTeX 参数。因此不管是 <code>\foo{hello}</code> 还是 <code>\foo{hello}[world]</code>,LaTeX 都会把其中的 <code>\foo{hello}</code> 先「吃下去」。接下来,LaTeX 会判断下一个字符是否为 <code>[</code>。对于 <code>\foo{hello}</code> 这种用法,下一个字符是换行符,因此判定失败,执行 <code>\foo@helper@i</code>。而对于 <code>\foo{hello}[world]</code> 这种用法,吃下去 <code>\foo{hello}</code> 之后,输入流中剩下了 <code>[world]...</code>,下一个字符正是 <code>[</code>,因此执行 <code>\foo@helper@ii</code>。</p>
<p>对于 <code>\foo@helper@ii</code>,它是使用 TeX 的原语 <code>\def</code> 定义的命令。参数列表 <code>#1[#2]</code> 表示该命令接受两个参数。第一个参数是标准的 TeX 参数——用分组包括起来。因此,上一步执行的 <code>\foo@helper@ii</code> 将第一个参数喂给了 <code>\foo@helper@ii</code>。接下来,<code>\foo@helper@ii</code> 还要吃下去第二个参数。按照定义,第二个参数被方括号 <code>[]</code> 所包围。因此 <code>[world]</code> 中的 <code>world</code> 被吃掉,作为第二个参数。</p>
<p>最终输出如图。</p>
<p><img src="/images/Tech/LaTeX/option-brackets-later.png" alt="" /></p>
<h1 id="bgroup"><code>\bgroup</code></h1>
<p>上面的 <code>\foo</code> 命令,基本已经达成了我们的目标。只不过,第二个参数必须是用方括号表达的。当然这不是不可以,但强迫症选手们可能会希望第二个参数也能用花括号来界定。于是,强迫症们尝试把 <code>\@ifnextchar[</code> 尝试换成了 <code>\@ifnextchar{</code>。于是它们得到了报错</p>
<pre><code class="language-txt">File ended while scanning use of...
</code></pre>
<p>这是因为,TeX 遇到 <code>{</code> 时,会将其解释为一个分组。因此,这种写法会造成 TeX 读入的分组不匹配。这样一来,我们就必须用 <code>\bgroup</code> 来代替花括号。它的定义是 <code>\let\bgroup={</code>。</p>
<pre><code class="language-tex">\documentclass{article}
\makeatletter
\newcommand{\foo@helper@i}[1]{One parameter: #1{}.}
\newcommand{\foo@helper@ii}[2]{Two parameters: #1{}, #2{}.}
\newcommand{\foo}[1]{%
\@ifnextchar\bgroup%
{\foo@helper@ii{#1}}%
{\foo@helper@i{#1}}%
}
\makeatother
\begin{document}
\foo{hello}
\foo{hello}{world}
\end{document}
</code></pre>
<p>这样一来,我们就实现了一个 <code>\foo</code> 命令,在参数不同的情况下,具有不同的行为。</p>
<h1 id="xparse-宏包"><code>xparse</code> 宏包</h1>
<p>基于 LaTeX3 的 <code>xparse</code> 宏包给了我们新的选项。它提供的 <code>\NewDocumentCommand</code> 命令<sup class="footnote-ref" id="fnref:https-tex-stacke"><a rel="footnote" href="#fn:https-tex-stacke">1</a></sup>,允许用户使用新的接口定义 LaTeX 命令。其形式为</p>
<pre><code class="language-tex">\NewDocumentCommand{&lt;command&gt;}{&lt;parameter specificers&gt;}{&lt;replacement text&gt;}
</code></pre>
<p>比如,以下两个定义,效果是一致的。</p>
<pre><code class="language-tex">\usepackage{xparse}
\newcommand{\baz}[1]{I eat #1{}.}
\NewDocumentCommand{\bar}{m}{I eat #1{}.}
</code></pre>
<p>其中,参数标识符 <code>m</code> 表示 <code>\bar</code> 接收一个标准的 LaTeX 参数。除去 <code>m</code> 之外,<code>xparse</code> 宏包还提供了许多额外的参数标识符(具体参照其手册)。其中,<code>g</code> 表示该参数是一个可选参数,并且以花括号界定其范围。当参数未给出时,参数值为 <code>-NoValue-</code>;否则是实际的参数内容。此时我们可以用 <code>\IfNoValueTF</code> 命令来做分支判断。</p>
<p>于是,上述 <code>\foo</code> 命令可以按如下方式实现。</p>
<pre><code class="language-tex">\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand{\foo}{mg}{%
\IfNoValueTF{#2}%
{One parameter: #1{}.}%
{Two parameters: #1{}, #2{}.}%
}
\begin{document}
\foo{hello}
\foo{hello}{world}
\end{document}
</code></pre>
<p>这样的实现方式,相对在 LaTeX2e 里用 <code>\@ifnextchar\bgroup</code> 判断就简单清晰多了。</p>
<div class="footnotes">
<hr />
<ol>
<li id="fn:https-tex-stacke">可以从<a href="https://tex.stackexchange.com/questions/49056/optional-arguments-in-def" target="_blank">这里</a>学习一个关于 <code>\NewDocumentCommand</code> 命令的更有意思的示例。 <a class="footnote-return" href="#fnref:https-tex-stacke">↩</a></li>
</ol>
</div>
</description>
</item>
<item>
<title>用 minted 宏包实现语法高亮</title>
<link>/tech/2017/07/20/minted/</link>
<pubDate>Thu, 20 Jul 2017 00:00:00 +0000</pubDate>
<guid>/tech/2017/07/20/minted/</guid>
<description>
<h1 id="listings-的麻烦"><code>listings</code> 的麻烦</h1>
<p>在 LaTeX 中实现语法高亮的老牌方案是 <a href="https://www.ctan.org/pkg/listings" target="_blank"><code>listings</code></a>,然而这种方案用起来非常麻烦:</p>
<ol>
<li>默认的字体效果很糟糕,居然是 Serif 系列的;</li>
<li>定义一种新语言需要先耗费大量时间了解帮助手册,还可能需要了解很多奇怪的规则;</li>
<li>代码<strong>跨页</strong>时需要一些<a href="http://bbs.ctex.org/forum.php?mod=viewthread&amp;tid=53451" target="_blank">额外的工作</a>;</li>
<li>代码中的<a href="http://stackoverflow.com/questions/432349/how-do-you-display-straight-quotes-instead-of-curly-quotes-when-using-latexs-l" target="_blank">单引号,双引号问题</a>;</li>
<li><strong>中文</strong>支持<a href="http://bbs.ctex.org/forum.php?mod=viewthread&amp;tid=50241" target="_blank">问题</a><sup class="footnote-ref" id="fnref:CTeX-76123-http"><a rel="footnote" href="#fn:CTeX-76123-http">1</a></sup>。</li>
<li>甚至对 LaTeX 的语法高亮支持也需要做许多<a href="/tech/2011/11/03/lsset-highlight-blackslash/">额外工作</a>。</li>
</ol>
<p></p>
<p>当然,不是说 <code>listings</code> 包的功能不够强大,从《<a href="/tech/2010/02/24/highlight-chunk/">给语法高亮内容中的部分内容进行高亮标识</a>》这个方案可以看到,利用 escape character 除了可以解决中文的问题外,还可以实现更多自定义的效果,比如《<a href="https://tex.stackexchange.com/questions/22635/lstlistings-getting-pretty-equations-in-display-mode" target="_blank">在代码中添加公式</a>》。如果是英文文档,定义一个类似于 <code>\verb|.|</code> 的命令,实现 inline code 式的命令也很容易<sup class="footnote-ref" id="fnref:bug-GitHub-282-h"><a rel="footnote" href="#fn:bug-GitHub-282-h">2</a></sup>。</p>
<p>因此,虽然 <code>listings</code> 包理论上可以满足我们的需求,但是要解决特定的问题往往需要耗费相当的精力和时间,对初学者并不算太友好。</p>
<h1 id="minted-宏包需要的支持"><code>minted</code> 宏包需要的支持</h1>
<p>LaTeX 中的 <code>minted</code> 宏包实际上是调用 Python 的 <code>pygments</code> 来完成语法高亮的,高亮效果好,支持的语法充分,可以实现代码内的公式<sup class="footnote-ref" id="fnref:-"><a rel="footnote" href="#fn:-">3</a></sup>,通过 <code>\mintinline</code> 命令实现<strong>行内代码</strong>的同时<sup class="footnote-ref" id="fnref:Stack-Exchange-4"><a rel="footnote" href="#fn:Stack-Exchange-4">4</a></sup>可以指定语言的名称<sup class="footnote-ref" id="fnref:Stack-Exchange-4"><a rel="footnote" href="#fn:Stack-Exchange-4">5</a></sup>,需要的额外配置少,唯一目前要做就是在安装完 Python 后,通过下面的命令安装 <code>pygments</code>:</p>
<pre><code class="language-bash">pip install pygments
</code></pre>
<p>之后编译时用下面的命令:</p>
<pre><code class="language-bash">xelatex -shell-escape demo.tex
</code></pre>
<p>或</p>
<pre><code class="language-bash">lualatex -shell-escape demo.tex
</code></pre>
<p>对于使用 <a href="http://blog.csdn.net/u011982340/article/details/40261735" target="_blank">WinEdt</a> 或者 <a href="https://tex.stackexchange.com/questions/170723/custom-build-settings-in-sublime" target="_blank">Sublime Text</a> 界面接口的用户,可能选项 <code>-shell-escape</code> 会比较麻烦一些,但由于自己是直接调用 bat 文件来处理编译问题,因此这个选项完全不是问题。</p>
<blockquote>
<p>现在 <code>knitr</code> 转成 pdf 的语法高亮应该也是由 <code>pygments</code> 完成的,并且完全不需要用户干预(不确定在 <code>knitr</code> 时 <code>pygments</code> 是否需要提前安装。)。</p>
</blockquote>
<h2 id="可能的麻烦">可能的麻烦</h2>
<p><strong>提醒</strong>:尝试在 CTeX 2.9.2 下面直接将<a href="https://github.com/gpoore/minted" target="_blank">最新版</a>的 <code>minted</code> 相关文件复制到相应的目录,但结果出错,说找不到 <a href="https://github.com/gpoore/fvextra" target="_blank"><code>fvextra</code></a> 宏包,然而添加了该宏包之后仍然会有其它错误,估计是相关的依赖包没有更新的原因,因此推荐使用最新版的 TeXLive 或者将整个 CTeX 套装的宏包都进行更新来解决这个问题,但是在线更新 MikTeX 之后,再更新相关宏包时,同样会出现各种各样的奇怪问题,像 <code>picins</code> 这要的宏包甚至会认为是过时的而直接删除,导致其它很多麻烦,最终放弃更新 CTeX。</p>
<p>好像更新新的 <code>ctex</code> 宏包后,<code>ctexsetup</code> 命令也不再推荐使用。</p>
<h1 id="简单例子">简单例子</h1>
<p>这个例子来自 <a href="https://zhuanlan.zhihu.com/p/27996164" target="_blank">https://zhuanlan.zhihu.com/p/27996164</a>。</p>
<pre><code class="language-tex">\documentclass[a4paper]{article}
\usepackage{minted}
\usepackage{xcolor}
\definecolor{bg}{rgb}{0.95,0.95,0.95}
\usepackage[margin=2.5cm]{geometry}
\begin{document}
\begin{minted}[bgcolor=bg]{rust}
fn foo(v1: Vec&lt;i32&gt;, v2: Vec&lt;i32&gt;) -&gt; (Vec&lt;i32&gt;, Vec&lt;i32&gt;, i32) {
// Do stuff with `v1` and `v2`.
// Hand back ownership, and the result of our function.
(v1, v2, 42)
}
let v1 = vec![1, 2, 3];
let v2 = vec![1, 2, 3];
let (v1, v2, answer) = foo(v1, v2);
\end{minted}
\begin{minted}[bgcolor=bg]{go}
import &quot;math&quot;
type Shape interface {
Area() float64
}
type Square struct { // Note: no &quot;implements&quot; declaration
side float64
}
func (sq Square) Area() float64 { return sq.side * sq.side }
type Circle struct { // No &quot;implements&quot; declaration here either
radius float64
}
func (c Circle) Area() float64 { return math.Pi * math.Pow(c.radius, 2) }
\end{minted}
\end{document}
</code></pre>
<p>下面是实际的高亮效果:</p>
<p><img src="/images/Tech/LaTeX/minted-exm.png" alt="`minted` 语法高亮" /></p>
<div class="footnotes">
<hr />
<ol>
<li id="fn:CTeX-76123-http">中文支持后期已经基本解决,参考 <a href="http://bbs.ctex.org/forum.php?mod=viewthread&amp;tid=76123" target="_blank">CTeX #76123</a> 和 <a href="http://bbs.ctex.org/forum.php?mod=viewthread&amp;tid=77046" target="_blank">CTeX #77046</a>。 <a class="footnote-return" href="#fnref:CTeX-76123-http">↩</a></li>
<li id="fn:bug-GitHub-282-h">中文里面还有 bug,参见 <a href="https://github.com/CTeX-org/ctex-kit/issues/282" target="_blank">GitHub #282</a> 以及《<a href="/tech/2017/03/07/lstlistings-bgcolor/">语法高亮:在 <code>lstinline</code> 中给行内代码添加背景颜色 z</a>》。 <a class="footnote-return" href="#fnref:bug-GitHub-282-h">↩</a></li>
<li id="fn:-">参见帮助文档。 <a class="footnote-return" href="#fnref:-">↩</a></li>
<li id="fn:Stack-Exchange-4">可进一步参考 <a href="https://tex.stackexchange.com/questions/45756/inline-code-and-short-verb-with-minted" target="_blank">Stack Exchange #45756</a>。 <a class="footnote-return" href="#fnref:Stack-Exchange-4">↩</a></li>
<li id="fn:Stack-Exchange-4">参考 <a href="https://tex.stackexchange.com/questions/45756/inline-code-and-short-verb-with-minted" target="_blank">Stack Exchange #45756</a>,这个功能需要 <code>minted</code> 2.0 以上版本,CTeX 2.9.2 套装默认的版本不行。 <a class="footnote-return" href="#fnref:Stack-Exchange-4">↩</a></li>
</ol>
</div>
</description>
</item>
<item>
<title>在 RStudio 中使用 GitHub</title>
<link>/tech/2017/07/14/github-in-rstudio/</link>
<pubDate>Fri, 14 Jul 2017 00:00:00 +0000</pubDate>
<guid>/tech/2017/07/14/github-in-rstudio/</guid>
<description>
<div id="TOC">
<ul>
<li><a href="#basic-knowledge"><span class="toc-section-number">1</span> 基本知识</a><ul>
<li><a href="#configuration-list"><span class="toc-section-number">1.1</span> 查看配置</a></li>
</ul></li>
<li><a href="#gen-set-keys"><span class="toc-section-number">2</span> 生成、配置密钥</a><ul>
<li><a href="#gen-keys"><span class="toc-section-number">2.1</span> 生成密钥</a></li>
<li><a href="#set-keys"><span class="toc-section-number">2.2</span> 配置密钥</a></li>
<li><a href="#test-connection"><span class="toc-section-number">2.3</span> 测试连接</a></li>
</ul></li>
<li><a href="#-rstudio--github"><span class="toc-section-number">3</span> 在 RStudio 中使用 GitHub</a><ul>
<li><a href="#-github-pages"><span class="toc-section-number">3.1</span> 发布到 GitHub Pages</a></li>
<li><a href="#-github-"><span class="toc-section-number">3.2</span> 连接 GitHub 可能遇到的问题</a></li>
</ul></li>
</ul>
</div>
<div id="basic-knowledge" class="section level1">
<h1><span class="header-section-number">1</span> 基本知识</h1>
<p>Git 共有三个级别的 config 文件,分别是 system、global 和 local。在当前环境中,分别对应 <code>%GitPath%\mingw64\etc\gitconfig</code> 文件、<code>$home\.gitconfig</code> 文件和 <code>%RepoPath%\.git\config</code> 文件。其中 <code>%GitPath%</code> 为 Git 的安装路径,<code>%RepoPath%</code> 为某仓库的本地路径。所以 system 配置整个系统只有一个,global 配置每个账户只有一个,而 local 配置和 git 仓库的数目相同,并且只有在仓库目录才能看到该配置。</p>
<div id="configuration-list" class="section level2">
<h2><span class="header-section-number">1.1</span> 查看配置</h2>
<p>参考资料:<a href="http://www.jianshu.com/p/0ad3d88c51f4" class="uri">http://www.jianshu.com/p/0ad3d88c51f4</a></p>
<p>由于之前已经成功安装 Git 并登陆到过 GitHub,因此查看当前配置时,最后两行会显示用户名及用户密码。</p>
<pre class="bash"><code>$ git config --list | grep user
user.name=xxxxxx
[email protected]</code></pre>
<p>这里的 <code>user.name</code> 和 <code>user.email</code> 就是 Author 信息。此时,上面提到的三个级别都配置了 user 信息。当 <code>git commit</code> 时,Author 信息依次读取 local、global 和 system 的配置,如果找到则不再继续读取。其他配置的读取顺序也是如此。</p>
<p>GitHub 支持 https 和 ssh 协议连接。下面以较为安全的 ssh 方式作为示例进行说明。</p>
</div>
</div>
<div id="gen-set-keys" class="section level1">
<h1><span class="header-section-number">2</span> 生成、配置密钥</h1>
<div id="gen-keys" class="section level2">
<h2><span class="header-section-number">2.1</span> 生成密钥</h2>
<ol style="list-style-type: decimal">
<li>由于之前已经生成过密钥并成功登陆过 GitHub,这里暂时不考虑多账号切换登陆的做法,因此直接 <code>cd ~/.ssh</code> 切换到 SSH 所在目录,将其中的 <code>id_rsa</code> 和 <code>id_rsa.pub</code> 备份好后删除掉。</li>
<li>输入 <code>git config --global user.name &quot;haopen&quot;</code> 和 <code>git config --global user.email [email protected]</code> 切换到新的账号,还可以用 <code>git config --global user.name</code> 和 <code>git config --global user.email</code> 看账号是否添加成功。</li>
</ol>
<pre class="bash"><code>$ git config --global user.name &quot;haopen&quot;
$ git config --global user.email [email protected]
$ git config --global user.name
haopen
$ git config --global user.email
$ git config --list
......
user.name=haopen
[email protected]</code></pre>
<ol start="3" style="list-style-type: decimal">
<li>接下来输入 <code>ssh-keygen -t rsa -C &quot;[email protected]&quot;</code> 生成新的密钥。根据<a href="http://www.cnblogs.com/qcwblog/p/5709720.html">这篇博文</a>的例子,在下面生成密钥文件时一路回车,不指定任何文件名称,直接使用系统默认的名称,到最后一步时密钥生成成功!</li>
</ol>
<pre class="txt"><code>$ ssh-keygen -t rsa -C &quot;[email protected]&quot;
Generating public/private rsa key pair.
Enter file in which to save the key (/c/Users/haopeng/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /c/Users/haopeng/.ssh/id_rsa.
Your public key has been saved in /c/Users/haopeng/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:ZH9aXjek6jUT7DWIe7SBrlFGuy50SjseMTtg5HSZLJw [email protected]
The key&#39;s randomart image is:
+---[RSA 2048]----+
| |
| . o o |
| Eo= . . |
| +oo.. = + |
| +So.*oB.+.|
| . .oB**.=.o|
| o===.B |
| =B o o |
| .ooo |
+----[SHA256]-----+</code></pre>
</div>
<div id="set-keys" class="section level2">
<h2><span class="header-section-number">2.2</span> 配置密钥</h2>
<p>复制前一步中生成的 <code>id_rsa.pub</code> 中的内容,之后登陆到 GitHub,在右上角的头像上点击 <code>Settings - SSH and GPG keys</code>,点击右边的 <code>New SSH Key</code>,然后将复制好的内容粘贴进去,标题自己随意取一个,比如 <code>haopen's key</code>,这样就完成了远程端的配置。</p>
</div>
<div id="test-connection" class="section level2">
<h2><span class="header-section-number">2.3</span> 测试连接</h2>
<p><strong>问题</strong>:在 Git Bash Shell 中输入如下命令后连接<strong>失败</strong>!</p>
<pre class="bash"><code>ssh -T [email protected]</code></pre>
<blockquote>
<p>Warning: Permanently added the RSA host key for IP address ‘192.30.255.112’ to the list of known hosts. Permission denied (publickey).</p>
</blockquote>
<p>在网上查阅资料后,感觉有类似经历的人的解决方法似乎都与自己面临的情况不完全吻合,无意中看到 <code>~/.ssh</code> 目录中有一个名称为 <code>known_hosts</code> 的文件,尝试将其删除后再重新进行了前面的第 1 步和第 2 步,这次再测试时就<strong>成功</strong>了。</p>
<pre class="txt"><code>$ ssh -T [email protected]
The authenticity of host &#39;github.com (192.30.255.113)&#39; can&#39;t be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added &#39;github.com,192.30.255.113&#39; (RSA) to the list of known hosts.
Hi haopen! You&#39;ve successfully authenticated, but GitHub does not provide shell access.</code></pre>
</div>
</div>
<div id="-rstudio--github" class="section level1">
<h1><span class="header-section-number">3</span> 在 RStudio 中使用 GitHub</h1>
<p>到 GitHub 的网站上新添加一个代码仓库(包含 <code>readme.md</code>),然后打开 RStudio,<code>File - New Project - Version Control - Git</code>,输入 <code>Repository URL</code>(要输入的内容可以在 GitHub 代码仓库右方点 <code>Clone or download</code> 找到),其中 <code>Project directory name</code> 用于设定项目所在文件夹的名称,<code>Create project as subdirectory of</code> 用于指定该文件夹所属的父目录,此外勾选 <code>Open in new session</code>,接下来 RStudio 会将该仓库中的内容 Pull 到本地。</p>
<div class="figure">
<img src="/images/Tech/GitHub/RStudio/NewProject-Git-RStudio.png" alt="创建一个 Git Repository:Step 1" />
<p class="caption">创建一个 Git Repository:Step 1</p>
</div>
<div class="figure">
<img src="/images/Tech/GitHub/RStudio/NewProject-Git-RStudio1.png" alt="创建一个 Git Repository:Step 2" />
<p class="caption">创建一个 Git Repository:Step 2</p>
</div>
<div class="figure">
<img src="/images/Tech/GitHub/RStudio/Create-Git-Repository.png" alt="创建一个 Git Repository:Step 3" />
<p class="caption">创建一个 Git Repository:Step 3</p>
</div>
<p>成功之后显示如下内容:</p>
<pre class="txt"><code>C:/Program Files/.../git.exe clone --progress [email protected]:haopen/Blogdown.git Blogdown</code></pre>
<p>尝试添加文件并保存到,点击右边 Git 面板中的 <code>Commit</code>(直接在 Git 面板中某个文件上点右键,选择 <code>ignore</code> 可以指定应忽略跳过的文件),可以在打开的窗口中勾选需要 Commit 的文件,之后在右半边窗口中填写简单的描述文字,之后可以点击下方的 <code>Commit</code>。</p>
<div class="figure">
<img src="/images/Tech/GitHub/RStudio/RStudio-Commit.png" alt="提交一个 Commit" />
<p class="caption">提交一个 Commit</p>
</div>
<p><strong>问题</strong>:Commit 完成之后,刚开始右上角并没有 <code>Pull</code> 向上箭头,并且尝试提交时会出现 <code>unable to access... The requested URL returned error: 403</code> 类的错误,根据<a href="https://stackoverflow.com/questions/7438313/pushing-to-git-returning-error-code-403-fatal-http-request-failed">这个讨论</a>,在本地目录中找到隐藏的 <code>.git/config</code>,将其中的</p>
<pre class="txt"><code>url = https://[email protected]/derekerdmann/lunch_call.git</code></pre>
<p>修改成</p>
<pre><code>url = ssh://[email protected]/haopen/testGit.git</code></pre>
<p>之后再次提交成功,并且上图右上角出现 <code>Pull</code> 向上箭头。当然,<strong>更好的做法</strong>是在点 <code>Clone or download</code> 时,直接点击 <code>Use SSH</code>,然后复制 <code>[email protected]:haopen/testGit.git</code> 即可。</p>
<div id="-github-pages" class="section level2">
<h2><span class="header-section-number">3.1</span> 发布到 GitHub Pages</h2>
<ol style="list-style-type: decimal">
<li>先到 GitHub 创建一个名称为 <code>haopen.github.io</code> 的代码仓库;</li>
<li>之后 Clone 到本地<a href="#fn1" class="footnoteRef" id="fnref1"><sup>1</sup></a>:参考前面在 RStudio 中 Clone Repository 的步骤,也可以先进入到 <code>D:\GitHub</code>,再点击右键,选择 <code>Git GUI Here</code>,在打开的窗口中选择 <code>Clone Existing Repository</code>,参考下图填写内容即可:</li>
</ol>
<div class="figure">
<img src="/images/Tech/GitHub/RStudio/CloneExistingRepository.png" alt="Git 客户端" />
<p class="caption">Git 客户端</p>
</div>
<div class="figure">
<img src="/images/Tech/GitHub/RStudio/CloneExistingRepositoryRStudio.png" alt="RStudio 中的 Git 客户端" />
<p class="caption">RStudio 中的 Git 客户端</p>
</div>
<p>其中 <code>haopen-public</code> 是在 Hugo 中的 <code>.Rprofile</code> 中指定的内容发布目录,对应的绝对地址是 <code>D:\GitHub\haopen-public</code>。</p>
<ol start="3" style="list-style-type: decimal">
<li>做一个 Commit,之后再 Push,等 Push 完成就可以在 <a href="https://haopen.github.io/" class="uri">https://haopen.github.io/</a> 观察到发布后的页面效果。</li>
</ol>
</div>
<div id="-github-" class="section level2">
<h2><span class="header-section-number">3.2</span> 连接 GitHub 可能遇到的问题</h2>
<p><strong>问题</strong>:Push 的时候可能会遇到如下的错误:</p>
<pre class="txt"><code>Git push origin
ssh: Could not resolve hostname ssh.github.com: Name or service not known
fatal: Could not read from remote repository.</code></pre>
<p>参考 <a href="http://blog.csdn.net/qq_17335153/article/details/51701700" class="uri">http://blog.csdn.net/qq_17335153/article/details/51701700</a> 的说明,打开 <code>~/.ssh</code>,在里面新建一个名称为 <code>config</code> 的文件,注意没有扩展名,在其中添加内容:</p>
<pre class="txt"><code>Host github.com
User [email protected]
Hostname ssh.github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_rsa
Port 443</code></pre>
<p>但是通过 <code>ssh -T [email protected]</code> 测试仍然报错:</p>
<pre class="txt"><code>ssh: Could not resolve hostname github.com: Name or service not known
fatal: The remote end hung up unexpectedly</code></pre>
<p>参考 <a href="http://blog.sina.com.cn/s/blog_a3fb1fe30102wieq.html" class="uri">http://blog.sina.com.cn/s/blog_a3fb1fe30102wieq.html</a> 先通过 <code>ping github.com</code> 获得 ip 地址 <code>192.30.255.113</code>,之后在 <code>/etc/hosts</code> 中添加如下内容<a href="#fn2" class="footnoteRef" id="fnref2"><sup>2</sup></a>:</p>
<pre><code>192.30.255.113 github.com</code></pre>
<p>再测试时就没有问题<a href="#fn3" class="footnoteRef" id="fnref3"><sup>3</sup></a>:</p>
<pre class="txt"><code>$ ssh -T [email protected]
The authenticity of host &#39;[ssh.github.com]:443 ([192.30.253.123]:443)&#39; can&#39;t be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added &#39;[ssh.github.com]:443,[192.30.253.123]:443&#39; (RSA) to the list of known hosts.
Hi haopen! You&#39;ve successfully authenticated, but GitHub does not provide shell access.</code></pre>
<p><strong>技巧</strong>:在 RStudio 第一次准备将本地大量文件 Commit 时,右侧 Git 面板中的 <code>Staged</code> 对应的 Checkbox 经常点不动,参考 <a href="https://pages.github.com/" class="uri">https://pages.github.com/</a> 后此时可以考虑从齿轮那里打开 RStudio 带的 Git shell,然后在里面输入<a href="#fn4" class="footnoteRef" id="fnref4"><sup>4</sup></a>:</p>
<pre class="bash"><code>git add --all
~$git commit -m &quot;Initial commit&quot;
~$git push -u origin master</code></pre>
<p>这种命令行的方式此时可能会更加方便一些。</p>
</div>
</div>
<div class="footnotes">
<hr />
<ol>
<li id="fn1"><p>可以考虑使用直接使用 Git GUI Here 客户端,也可以考虑使用 RStudio 提供的界面,通常后者可能会更人性化一些。<a href="#fnref1">↩</a></p></li>
<li id="fn2"><p>修改 <code>C:\Windows\System32\drivers\etc\hosts</code> 这个文件时,经常提示有其它程序占用,因此转而修改 <code>C:\Program Files\Git\etc\hosts</code>,效果也是一样的。<a href="#fnref2">↩</a></p></li>
<li id="fn3"><p>但连接速度真的很慢。<a href="#fnref3">↩</a></p></li>
<li id="fn4"><p>要在这个自带的 Shell 窗口中粘贴内容,只能在窗口的标题栏点击右击,再选择“编辑”,之后选择“粘贴”。<a href="#fnref4">↩</a></p></li>
</ol>
</div>
</description>
</item>
<item>
<title>添加 lightGallery 功能到 Hugo</title>
<link>/tech/2017/07/10/hugo-light-gallery/</link>
<pubDate>Mon, 10 Jul 2017 23:49:00 -2359</pubDate>
<guid>/tech/2017/07/10/hugo-light-gallery/</guid>
<description>
<p>Hexo 中用的 jQuery FancyBox 本来效果也不错,但是在移植这部分功能的时候并不顺利,又在搜索解决方案的时候看到了 lightGallery,配置和使用感觉都非常好,因此决定将 lightGallery 的图片浏览功能移植过来。</p>
<ol>
<li>下载相关文件并复制到恰当的目录;</li>
<li>在模板文件中的适当位置,主要是 <code>header</code> 相关部分添加样式文件,在 <code>footer</code> 相关部分添加 js 相关的文件;</li>
<li>一个比较麻烦的地方是,这个插件要求全部图片按比较规范的格式放到一个有 <code>id</code> 的 html 标记容器之中,思考尝试再三,最后通过 <a href="/js/lgGallery_Prepare.js"><code>lgGallery_Prepare.js</code></a> 文件大致达到了相应的目的;</li>
<li>主要思路是先通过 js 遍历页面中的全部 <code>img</code> 元素,提取 <code>src</code> 属性并在一个隐藏的 <code>div</code> 中按 lightGallery 要求的<a href="http://sachinchoolur.github.io/lightGallery/demos/html-markup.html" target="_blank">格式</a>再动态生成一遍。之后再通过 js 给原有的每张图片添加一个 <code>onclick</code> 属性,用于监听点击事件并通过 js 模拟点击隐藏 <code>div</code> 中对应的图片文件,最后由 lightGallery 监听到隐藏 <code>div</code> 中的点击事件并最终达到浏览图片的目的;
<ul>
<li>不管是用 <code>setAttribute</code> 还是用 <code>createAttributes</code> 创建属性,最后除了 <code>onclick</code> 属性被传递出去外,其它的自定义名称的属性都不成功;</li>
<li>要想在后面的代码中通过 <code>document.getElementById()</code> 的方式获取,就不能用 <code>innerHTML</code> 的方式,而要用 <code>createElement</code> 的方式;</li>
<li>没有通过 <code>addEventListener</code> 给对象添加匿名函数的方式来处理,因为这时还没有完成 <code>div</code> 中内容的生成,这会导致后续的监听处理程序找不到动态生成的对象;</li>
<li>对 <code>onclick</code> 属性,同时传递自身与事件的代码为 <code>javascript: lg_click(event, this);</code>,注意这里的 <code>event</code> 和 <code>this</code> 的顺序不能反,否则后面 <code>lg_click()</code> 中引用时会找不到对象,因此基本可以认为是固定用法。当然,只传递 <code>event</code> 或者 <code>this</code> 在语法上也是可行的;</li>
<li>在 <code>lg_click()</code> 中要记得禁止点击事件向上冒泡;</li>
</ul></li>
</ol>
<p>最后,完整的配置文档可以从<a href="http://sachinchoolur.github.io/lightGallery/docs/api.html" target="_blank">这里</a>找到。根据这个示例<a href="http://www.16css.com/jdt/1304.html" target="_blank">配置文件</a>以及<a href="http://sachinchoolur.github.io/lightGallery/demos/dynamic.html" target="_blank">官方示例文件</a>的说明,其实可以用 js 生成一个指定格式的数据对象,最后交由 lightGallery 来使用,但由于监听事件是与某个具体 <code>id</code> 的容器联系的,因此这种动态的方法与本站需要的点击某张图片打开浏览窗口的需求并不一致。</p>
</description>
</item>
<item>
<title>添加本地搜索功能到 Hugo</title>
<link>/tech/2017/07/10/hugo-local-search/</link>
<pubDate>Mon, 10 Jul 2017 23:13:00 -2323</pubDate>
<guid>/tech/2017/07/10/hugo-local-search/</guid>
<description>
<p>Yihui <a href="https://github.com/yihui/yihui.name" target="_blank">修改过的主题</a>并不提供本地搜索功能,但 <a href="https://hexo.io/" target="_blank">Hexo</a> 的 <a href="http://theme-next.iissnan.com/" target="_blank">NexT</a> 主题却有一个插件(<a href="https://github.com/iissnan/hexo-theme-next/blob/master/layout/_third-party/search/localsearch.swig" target="_blank">JS</a>、<a href="https://github.com/iissnan/hexo-theme-next/blob/master/layout/_partials/search/localsearch.swig" target="_blank">html</a>、<a href="https://github.com/iissnan/hexo-theme-next/blob/master/source/css/_common/components/third-party/localsearch.styl" target="_blank">css</a>)可以实现该功能,可以考虑将这个功能移植过来。</p>
<h1 id="模板文件">模板文件</h1>
<ol>
<li>按 Hugo 的规模将 js, html, css 文件复制到对应的目录,并在模板文件中添加对应的引用;</li>
<li>修改 css 的定义,实现与现有主题的风格搭配;</li>
<li>js 文件中找到关键的三处配置,一是 <code>.xml</code> 数据文件的路径,二是每条 Post 中匹配关键词的文本片断的数量,三是搜索的触发方式是 onkeypress 还是 enter 式,对应于 <code>auto</code> 和 <code>manual</code> 两个选择;</li>
<li><code>$('.popup').detach().appendTo('...')</code> 这里的 <code>appendTo</code> 实际上是随意指定的,要更换成本主题的某个 html 标记容器,这个地方的错误查了将近 7 个小时;</li>
<li>搜索引擎 js 文件可以异步加载,但是 <code>jQuery.min.js</code> 文件却最好直接加载,以避免引起不必要的麻烦;</li>
</ol>
<h1 id="数据文件">数据文件</h1>
<p>xml 数据文件在 Hugo 中的生成有些特殊,可按下面的步骤进行:</p>
<ol>
<li><p>添加如下代码到 <code>\contents\search-index.md</code> 文件:</p>
<pre><code class="language-yaml">---
date: &quot;2017-03-05T21:10:52+01:00&quot;
type: &quot;search&quot;
url: &quot;search.xml&quot;
---
</code></pre></li>
<li><p>添加模板文件到 <code>/layouts/search/single.html</code>。这个文件中的 <code>search</code> 路径由第 1 点中的 <code>type</code> 取舍指定,而 <code>single.html</code> 是 Hugo 的模板优先级规则确定的;</p></li>
</ol>
<p><strong>说明</strong>:根据模板文件生成 xml 文件在 Hugo 中并不方便,原因是 Hugo 会将模板文件中的 <code>&lt;</code> 强制转换成 <code>&amp;lt;</code>,而 <a href="https://github.com/gohugoio/hugo/issues/1740" target="_blank">https://github.com/gohugoio/hugo/issues/1740</a> 提供的 hack 手段比较好的解决了这个问题,具体的实现当然还需要根据实际情况做相应调整,可以参见这个模板文件的内容:</p>
<pre><code class="language-xml">{{ `&lt;?xml` | safeHTML }} version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;!-- Hugo 在转换模板时,&lt; 这个符号总是被强制转换为 &amp;lt; --&gt;
&lt;!-- 根据 https://github.com/gohugoio/hugo/issues/1740 使用如下的 Hack 可以解决 --&gt;
&lt;!-- part1 和 part2 的内容在 &quot;/cn/&quot; 这样的情形中,前者是 cn,后者是 /cn/ --&gt;
&lt;!-- 第一个 if:是不是只有一级路径 /cn/ --&gt;
&lt;!-- 第二个 if:是不是特殊的二级路径 --&gt;
&lt;!-- 第三个 if:是不是特殊的一级路径 --&gt;
&lt;!-- 第四个 if:search.xml 和 主页 --&gt;
&lt;search&gt;
{{ range $index, $page := .Site.Pages }}
{{ $.Scratch.Set &quot;Part1&quot; (replaceRE &quot;^/([^/]+)/.*&quot; &quot;$1&quot; $page.RelPermalink) }}
{{ $.Scratch.Set &quot;Part2&quot; (replaceRE &quot;^/([^/]+)/([^/]+)/.*&quot; &quot;$2&quot; $page.RelPermalink) }}
{{ $.Scratch.Set &quot;Part2&quot; (replace Part2 &quot;/&quot; &quot;&quot; ) }}
&lt;!-- 上面两行在真实代码中被合并成了一行 --&gt;
{{ if not (eq ($.Scratch.Get &quot;Part1&quot;) ($.Scratch.Get &quot;Part2&quot;)) }}
{{ if not (in (split &quot;tags,categories,vitae,about&quot; &quot;,&quot;) ($.Scratch.Get &quot;Part2&quot;)) }}
{{ if not (in (split &quot;tags,categories&quot; &quot;,&quot;) ($.Scratch.Get &quot;Part1&quot;)) }}
{{ if not (or (eq $page.Title &quot;&quot;) (eq $page.RelPermalink &quot;/&quot;)) }}
&lt;entry&gt;
{{ `&lt;title&gt;&lt;!` | safeHTML }}[CDATA[{{ $page.Title }}]]&gt;&lt;/title&gt;
&lt;url&gt;{{ $page.RelPermalink }}&lt;/url&gt;
{{ `&lt;content type=&quot;text&quot;&gt;&lt;!` |safeHTML }}[CDATA[{{ $page.PlainWords }}]]&gt;&lt;/content&gt;
&lt;/entry&gt;
{{ end }}{{ end }}{{ end }}{{ end }}{{ end }}
&lt;/search&gt;
</code></pre>
</description>
</item>
<item>
<title>添加标签云页面到 Hugo</title>
<link>/tech/2017/07/10/tags-cloud/</link>
<pubDate>Mon, 10 Jul 2017 19:22:44 -2300</pubDate>
<guid>/tech/2017/07/10/tags-cloud/</guid>
<description>
<p>Yihui 修改过的主题并不提供分类、标签云这样的分类功能,因此需要自己想办法解决。</p>
<p>由于标签和分类在 Hugo 都属于 Taxonomies 的一种实现,因此两种类别的内容的 Render 都由 <code>list.html</code> 来实现,要使用标签云就需要再单独定义与标签云匹配的模板文件(分为主站模板与 Section 下的模板);</p>
<ol>
<li>整个站点的标签云由 <code>/layouts/taxonomy/tag.terms.html</code> 负责,按这种目录和文件名结构,Huxo 就能<strong>自动</strong>根据该文件中的信息生成 <code>tags/index.html</code>;</li>
<li>调整 <code>/js/tags.js</code> 中的 <code>begin</code> 和 <code>end</code>,用于设定最小字体、最大字体以及每种标签对应的显示颜色;</li>
<li>然而仅仅这样做还不够,因为还还需要生成每个 Section 下的标签云页面:在 <code>/contents/</code> 创建 <code>section-arts.md</code> 文件,并在其中指定 <code>type</code> 和 <code>layout</code> 信息,并且 <code>slug</code> 将文件映射到指定的路径,之后在 <code>/layouts/customterms/tagslist.html</code> 中指定文件的渲染模板,注意这里的 <code>customterms</code> 与前面在 <code>/contents/</code> 中的 <code>tags-*.md</code> 对应;</li>
<li>由于 Hugo 目前无法获取指定 Section 下的 Categories 和 Tags,因此只好用了一些 Hack 的手法,给全部 Post 的 tags 和 categories 信息添加了一个特定的前缀编号(如 <code>4-tagName</code>),之后模板文件利用这些信息再配合 <code>config.yaml</code> 中的信息筛选出当前 Section 下的全部 tags;</li>
<li>一些特殊的代码用于保证在标题中显示的 Section 信息以及 tag 的名称信息是正确的;</li>
<li>Categories 列表的处理这标签基本类似,只是站点下的分类页面使用了默认的 <code>list.html</code> 文件,而 Section 下的分类页面使用了 <code>/layouts/customterms/categorieslist.html</code> 文件;</li>
</ol>
</description>
</item>
<item>
<title>Hugo 模板优先级解读</title>
<link>/tech/2017/07/08/hugo-template-priority/</link>
<pubDate>Sat, 08 Jul 2017 19:09:00 -2100</pubDate>
<guid>/tech/2017/07/08/hugo-template-priority/</guid>
<description>
<h1 id="功能解读">功能解读</h1>
<ul>
<li><code>\layouts\</code> 用于放置模板文件,并且文件在该目录中的名称、文件层次决定了模板应用的优先级。</li>
<li><code>\archetypes\</code> 是内容文件 <code>.md</code> 的模板;</li>
<li><a href="https://gohugo.io/templates/functions/" target="_blank">https://gohugo.io/templates/functions/</a>:方法、函数列表;</li>
<li><a href="https://gohugo.io/templates/variables/" target="_blank">https://gohugo.io/templates/variables/</a>:模板可操作的变量和对象列表;</li>
<li><code>$section</code> 是通过赋值得到的一个可使用的页面级变量,而 <code>.Section</code> 是一个 Hugo 自带的变量;</li>
</ul>
<h1 id="自定义功能实现">自定义功能实现</h1>
<p>目前来说 <code>list.html</code> 可以遍历全部的 Section,但 Taxonomy Terms 只有一个 <code>tags</code> 目录和一个 <code>categories</code> 目录,并不能遍历全部的 Section。</p>
<p><a href="https://discourse.gohugo.io/t/create-section-taxonomies/343" target="_blank">https://discourse.gohugo.io/t/create-section-taxonomies/343</a> 想为每个 Section 都创建 tags 和 categories 页面,但后续的讨论应该是没有成功,个人觉得如果能够返回某个 Section 下的所有 tags 对象和 categories 对象时,这个功能才有可能实现。</p>
<p>根据 <a href="https://discourse.gohugo.io/t/create-page-with-type-or-layout-template-set-in-frontmatter/5265" target="_blank">https://discourse.gohugo.io/t/create-page-with-type-or-layout-template-set-in-frontmatter/5265</a> 和 <a href="https://github.com/gohugoio/hugo/issues/386" target="_blank">https://github.com/gohugoio/hugo/issues/386</a>,虽然可以通过给单独文件定义 <code>type</code> 和 <code>layout</code> 来做一些事情,但由于无法返回指定 Section 下的 Taxonomy Terms 集合,因此为每个 Section 都创建 tags 和 categories 页面的想法仍然无法实现。</p>
<h2 id="文章列表视图">文章列表视图</h2>
<p>根据 <a href="https://gohugo.io/templates/views/" target="_blank">https://gohugo.io/templates/views/</a>,除了 <a href="https://gohugo.io/templates/content/" target="_blank">single</a> 类型的模板外,每个 Section 都可以利用 <a href="https://gohugo.io/templates/list/" target="_blank">list templates</a> 生成各种不同的视图,<a href="https://gohugo.io/templates/homepage/" target="_blank">https://gohugo.io/templates/homepage/</a> 中给出了一个使用摘要视图的例子:</p>
<pre><code class="language-django">{{ range first 10 .Data.Pages }}
{{ .Render &quot;summary&quot;}}
{{ end }}
</code></pre>
<p>其中的 <code>summary</code> 还可以是 <code>li</code> 类型,相关的文件目录结构为:</p>
<pre><code class="language-txt dirTree">▾ layouts/
▾ arts/
li.html
single.html
summary.html
▾ tech/
li.html
single.html
summary.html
</code></pre>
<p>其中 <code>li.html</code> 和 <code>summary.html</code> 实际上在 <code>\layouts\_default\list.html</code> 这样的 list templates 类模板文件中使用,起到循环的作用。<code>list.html</code> 以及这两种元视图文件的示例参考 <a href="https://gohugo.io/templates/views/" target="_blank">https://gohugo.io/templates/views/</a>。</p>
<h2 id="tags-页面">tags 页面</h2>
<p>经试验,<code>\contents\tags\</code> 目录(及子目录)下使用 <code>_index.md</code> 不是使用 <code>terms.html</code> 相关的模板(比如 <code>terms.html</code> 或者 <code>taxonomy/tag.terms.html</code>),而是使用了 <code>list.html</code> 作为模板,换句话讲,要想让不同的 Section 有自己的标签云页面,在 <code>\contents\</code> 下创建如下目录结构的想法<del>行不通</del>:</p>
<pre><code class="language-txt dirTree">└── content
├── tags
| ├── _index.md
| ├── tech
| | └── _index.md
| └── arts
└── tech
├── first.md
└── second.md
</code></pre>
<h1 id="模板部件">模板部件</h1>
<h2 id="页面类型">页面类型</h2>
<p><a href="https://gohugo.io/templates/variables/" target="_blank">变量</a>一节中 Page variables 下的 <code>.Kind</code> 指出,页面的类型有:page, home, section, taxonomy, taxonomyTerm, RSS, sitemap, robotsTXT 以及 404,但是附带的说明还没有看懂<sup class="footnote-ref" id="fnref:but-these-will-o"><a rel="footnote" href="#fn:but-these-will-o">1</a></sup>。</p>
<h2 id="home-page">Home Page</h2>
<p>根据 <a href="https://gohugo.io/templates/homepage/" target="_blank">https://gohugo.io/templates/homepage/</a>,Home page 的模板优先级如下:</p>
<pre><code class="language-txt">/layouts/index.html
/layouts/_default/list.html
/layouts/_default/single.html
</code></pre>
<p>在 Home page 的模板中,可以访问全部 <a href="https://gohugo.io/templates/variables/" target="_blank"><code>page variables</code></a> 和 <a href="https://gohugo.io/templates/variables/" target="_blank"><code>site variables</code></a> 中的变量,除此之外,Home page 可以通过 <code>.Data.Pages</code> 访问全部页面对象,具体方法可以参考 <a href="https://gohugo.io/templates/list/" target="_blank">Lists Template</a> 部分的介绍。</p>
<h2 id="single">single</h2>
<p>根据 <a href="https://gohugo.io/templates/content/" target="_blank">https://gohugo.io/templates/content/</a>,每一篇 post,甚至全部的 <code>_index.md</code> 都可以视为一个单页(但是 list 和 terms.list 类的页面不是)的模板优先级如下:</p>
<pre><code class="language-txt">/layouts/TYPE/LAYOUT.html
/layouts/SECTION/LAYOUT.html
/layouts/TYPE/single.html
/layouts/SECTION/single.html
/layouts/_default/single.html
</code></pre>
<p>其中的 <code>TYPE</code> 和 <code>LAYOUT</code> 可以在单个的 post 之中,以 <code>type</code> 和 <code>layout</code> 属性对的形式出现在 front-matter 之中;<code>SECTION</code> 则是依据 md 文件在 <code>\contents\</code> 中对应的文件夹而确定。</p>
<div class="footnotes">
<hr />
<ol>
<li id="fn:but-these-will-o">but these will only available during rendering of that kind of page, and not available in any of the <code>Pages</code> collections. <a class="footnote-return" href="#fnref:but-these-will-o">↩</a></li>
</ol>
</div>
</description>
</item>
<item>
<title>Hugo 博客平台应用笔记</title>
<link>/tech/2017/07/09/hugo/</link>
<pubDate>Sun, 09 Jul 2017 00:00:00 +0000</pubDate>
<guid>/tech/2017/07/09/hugo/</guid>
<description>
<div id="TOC">
<ul>
<li><a href="#skills"><span class="toc-section-number">1</span> 使用心得</a></li>
<li><a href="#install"><span class="toc-section-number">2</span> 安装与运行</a><ul>
<li><a href="#rstudio-"><span class="toc-section-number">2.1</span> RStudio 安装</a></li>
<li><a href="#hugo-"><span class="toc-section-number">2.2</span> Hugo 安装</a></li>
<li><a href="#building"><span class="toc-section-number">2.3</span> 博客搭建</a><ul>
<li><a href="#-1"><span class="toc-section-number">2.3.1</span> 方法 1</a></li>
<li><a href="#-2"><span class="toc-section-number">2.3.2</span> 方法 2</a></li>
<li><a href="#-3"><span class="toc-section-number">2.3.3</span> 方法 3</a></li>
<li><a href="#-4"><span class="toc-section-number">2.3.4</span> 方法 4(推荐)</a></li>
</ul></li>
</ul></li>
<li><a href="#config-custom"><span class="toc-section-number">3</span> 站点配置与功能订制</a><ul>
<li><a href="#config"><span class="toc-section-number">3.1</span> 站点配置</a></li>
<li><a href="#custom"><span class="toc-section-number">3.2</span> 功能订制</a></li>
<li><a href="#futureFeatures"><span class="toc-section-number">3.3</span> 待实现</a></li>
</ul></li>
<li><a href="#themes"><span class="toc-section-number">4</span> 主题调整</a><ul>
<li><a href="#page-width"><span class="toc-section-number">4.1</span> 页面宽度</a></li>
<li><a href="#font-family"><span class="toc-section-number">4.2</span> 字体</a></li>
</ul></li>
<li><a href="#Hugo-Functions"><span class="toc-section-number">5</span> 功能解读</a></li>
</ul>
</div>
<div id="skills" class="section level1">
<h1><span class="header-section-number">1</span> 使用心得</h1>
<ol style="list-style-type: decimal">
<li>在 yml 头中加入 <code>subtitle: A subtitle</code> 可以为 post 添加一个副标题;</li>
<li>这里是一个 <code>&lt;kbd&gt;...&lt;/kbd&gt;</code> 的例子:<kbd>Ctrl</kbd>;</li>
<li><code>slug: &quot;cn/about&quot;</code> 中的 <code>slug</code> 是 Hugo 特有的一种机制,这里对应的文件实际上只是 <code>\content\cn_about.md</code>,但最终这个文件在 URL 中显示的却是 <code>/cn/about/</code>,所以 Slug 可以同时设定所属的博客子分类以及在 URL 中的文件名称,相当于强制重定向到了某一指定的路径。</li>
<li>要实现 <code><code>$...</code>$</code> 这样的效果,需要使用 <code>&lt;code&gt;</code> 标记,具体参考此处的源代码;</li>
<li>用 R Markdown 时,生成的 toc 如果是全中文的条目,可能链接的下划线无法用 css hack 很好的消除,但给对应的标题一个 <code>{#idName}</code> 时,这个问题自动消失,详细参考本文档上方的目录;</li>
<li><p>R Markdown 的<a href="https://bookdown.org/yihui/blogdown/content.html#body">说明文档</a>中说在 R Markdown 中不能直接使用 Shortcode,而要用下面的语法<a href="#fn1" class="footnoteRef" id="fnref1"><sup>1</sup></a>:</p>
<pre class="r"><code>```{r echo=FALSE}
blogdown::shortcode(&#39;tweet&#39;, &#39;852205086956818432&#39;)
```</code></pre></li>
<li><p>在 md 格式下输入以下内容可以自动将最后一行转换成右对齐的格式(普通的 Rmd 下 knitr 时不支持,但 Blogdown 下的 Rmd 可以):</p>
<pre class="markdown"><code># Quotes
&gt; Let us change our traditional attitude to the construction of programs:
&gt; Instead of imagining that our main task is to instruct a computer what to do,
&gt; let us concentrate rather on explaining to humans what we want the computer to do.
&gt; --- Donald E. Knuth, Literate Programming, 1984</code></pre></li>
</ol>
<p><strong>提示</strong>:下面的内容,没有改模板的需求时,基本不用理会。</p>
</div>
<div id="install" class="section level1">
<h1><span class="header-section-number">2</span> 安装与运行</h1>
<div id="rstudio-" class="section level2">
<h2><span class="header-section-number">2.1</span> RStudio 安装</h2>
<p>暂时不能直接用官方网站的正式版安装,而要用 <a href="https://dailies.rstudio.com/" class="uri">https://dailies.rstudio.com/</a> 提供的开发测试版,否则无法直接通过 RStudio 的新建 Project 向导创建一个 Hugo 的博客站点。</p>
</div>
<div id="hugo-" class="section level2">
<h2><span class="header-section-number">2.2</span> Hugo 安装</h2>
<p><a href="https://gohugo.io/">Hugo</a> 基于 <a href="https://golang.org/">Go</a> 语言编写,与 <a href="https://jekyllrb.com/">Jekyll</a> 和 <a href="https://hexo.io/">Hexo</a> 相比,虽然 Hugo 目前<a href="https://themes.gohugo.io/">主题</a>和插件还不如 Hexo 丰富,但它运行速度极快,并且安装非常容易,用户只需要<a href="https://github.com/gohugoio/hugo/releases">下载</a>主程序 <code>Hugo.exe</code> 并复制到指定目录即可<a href="#fn2" class="footnoteRef" id="fnref2"><sup>2</sup></a>:</p>
<pre class="txt"><code>C:\Users\Howard\AppData\Roaming\Hugo</code></pre>
<p>用户可以参考<a href="https://gohugo.io/overview/introduction/">官方文档</a>(<a href="http://www.gohugo.org/">中文</a>)进一步了解如何使用 Hugo,还可以到 GitHub 了解存在的问题以及目前的开发进度,到 <a href="https://discourse.gohugo.io/">Community</a> 与其他用户讨论使用过程中遇到的各种问题。</p>
</div>
<div id="building" class="section level2">
<h2><span class="header-section-number">2.3</span> 博客搭建</h2>
<div id="-1" class="section level3">
<h3><span class="header-section-number">2.3.1</span> 方法 1</h3>
<p>首先,切换到放置博客文件的目录,比如 <code>D:\GitHub</code>,接下来右键并选择 <code>GUI Bash Here</code>,之后在弹出的命令对话框中输入如下命令:</p>
<pre class="bash"><code>git clone --recursive https://github.com/yihui/blogdown-yihui-template.git</code></pre>
<p>这个命令从谢益辉的 Github 上提取建立博客需要的全部文件到本地 <code>D:\GitHub\blogdown-yihui-template\</code> 目录之中,这是谢根据 <code>hugo-lithium-theme</code> 主题修改后又从自已的站点抽取出来的一个框架,这个目录名称可以自行修改,比如修改成 <code>blogdown_Haopeng</code>,觉得麻烦的话,也可以参考<a href="/tech/2017/07/14/github-in-rstudio/">这里</a>通过 Git 的图形客户端完成整个过程。</p>
<p>其次,打开 RStudio,输入如下命令:</p>
<pre class="r"><code>setwd(&#39;D:/GitHub/blogdown_Haopeng&#39;)
blogdown::serve_site()</code></pre>
<p>当控制台显示 <code>Serving the directory D:\GitHub\blogdown_Haopeng at http://127.0.0.1:4321</code> 类似的文字时,就可以在浏览器中输入 <code>http://127.0.0.1:4321</code> 进行预览,因为具有 Hugo 实时预览功能,因此对目录中相关文件进行修改后,甚至不需要刷新浏览器就可以看到更新后的结果。</p>
</div>
<div id="-2" class="section level3">
<h3><span class="header-section-number">2.3.2</span> 方法 2</h3>
<p>如果没有安装 git 客户端,也可以跳过上面的两个步骤,直接在 RStudio 中输入如下命令:</p>
<pre class="r"><code>setwd(&#39;D:/GitHub/blogdown_Haopeng&#39;)
blogdown::new_site(theme = &#39;yihui/hugo-lithium-theme&#39;)
blogdown::serve_site()</code></pre>
<p>这样生成的博客站点和上面的非常类似,但细节和相关功能上和上面的那个代码仓库相比,可能会有比较多的差别。</p>
</div>
<div id="-3" class="section level3">
<h3><span class="header-section-number">2.3.3</span> 方法 3</h3>
<p>先复制一份打包好的 <code>blogdown_Haopeng</code> 目录到指定位置,然后参考方法 1 第二步进行操作。</p>
</div>
<div id="-4" class="section level3">
<h3><span class="header-section-number">2.3.4</span> 方法 4(推荐)</h3>
<p>2017.07.14 所有一切怪异的源头来自 <code>R/*.*</code>,这里面的文件配合站点下的自定义的 <code>.Rprofile</code> 用于自定义整个站点的渲染过程,相当于一个自定义版本的 <code>blogdown::servesite()</code>,虽然现在已经弄清楚中间发生了什么。这种自定义的方式其实是先将 Rmd 文件通过 knitr 转换成 md 文件,之后再交由 Hugo 的 Markdown 引擎 Blackfriday 来处理,对于一般的文档,这种自定义的方法的最大好处是可以控制更多细节,比较 Rmd 文件中绘制图形的保存路径等,但最大的问题是:</p>
<ol style="list-style-type: decimal">
<li>Blackfriday 处理数学公式的能力远不如 Pandoc;</li>
<li>也无法做到为各级标题自动添加编号;</li>
<li>不能自动给源文档中不连续的有序列表添加连续的编号;</li>
<li>还有一个比较难受的点是,生成的临时 md 文件与原始的 md 混在一起,非常难区分;</li>
</ol>
<p>因此最终还是选择用这里的第 4 种方法:先参考第 2 种方法下载最精简版本的文件,之后再从第 1 种方法下载的文件中提取需要用到的各种文件,再整合到精简版的内容之中。</p>
<p>实际操作过程中,在模板整合完成并调试结束后,可以把其中的内容全部复制出来,再参考<a href="/tech/2017/07/14/github-in-rstudio/">这里</a>将提取出来的内容放到一个 GitHub 的本地代码仓库之中,之后再 Push 到远程仓库。</p>
<hr />
<p>方法 1 和 方法 3 的思路会遇到一个比较奇怪的事情,在 <a href="https://github.com/rstudio/blogdown/issues/140" class="uri">https://github.com/rstudio/blogdown/issues/140</a> 反映了此问题:就是在 Rmd 中<del><strong>无法</strong></del>成功通过如下的设置来生成文章内的目录,并给每个小标题添加编号,</p>
<pre class="yaml"><code>output:
blogdown::html_page:
toc: true
number_sections: true</code></pre>
<p>根据试验的结果来看,直接在 RStudio 中按 <a href="https://bookdown.org/yihui/blogdown/rstudio-ide.html" class="uri">https://bookdown.org/yihui/blogdown/rstudio-ide.html</a> 给出的说明:</p>
<ol style="list-style-type: decimal">
<li>点击 <code>File -&gt; New Project -&gt; New Directory</code>,然后按照下面两张图的设置进行站点初始化:</li>
</ol>
<div class="figure">
<img src="/images/Tech/Hugo/RStudio/NewProject/1.png" alt="Create a new website project in RStudio." />
<p class="caption">Create a new website project in RStudio.</p>
</div>
<div class="figure">
<img src="/images/Tech/Hugo/RStudio/NewProject/2.png" alt="Create a website project based on blogdown." />
<p class="caption">Create a website project based on blogdown.</p>
</div>
<ol start="2" style="list-style-type: decimal">
<li>将 <code>yihui/blogdown-yihui-template.git</code> 下面的 <code>\layouts\*</code> 和 <code>\static\*</code> 复制到 <code>Blogdown</code> 中;</li>
<li>复制 <code>config.yaml</code> 并删除默认的 <code>config.toml</code>;</li>
<li>在 Rmd 文件头中添加上面给出的 <code>output</code> 设置;</li>
<li><del>不复制</del> <code>blogdown-yihui-template\R</code> 中的 <code>build_one.R</code> 和 <code>build.R</code>;</li>
<li>在 RStudio 中运行 <code>blogdown::serve_site()</code>。</li>
</ol>
<p>这样又可以成功得到 Pandoc 风格的 toc 和 编号后的标题。但目前不清楚为什么用方法 1 和方法 3 不能成功,也不确定方法 2 和这里的方法 4 的完整区别(至少方法 4 中的指定 <code>Create project as subdirectory of</code> 是方法 2 默认没有的)。</p>
<blockquote>
<p><strong>注意</strong>:如 <a href="https://bookdown.org/yihui/blogdown/output-format.html" class="uri">https://bookdown.org/yihui/blogdown/output-format.html</a> 最下方指出的,方法 4 可能会导致语法高亮等失效,可以通过 <code>highlight.js</code> 的方法来修正,在实际运行过程中,IE 下在线加载该语法高亮工具的 CSS 文件可能会比较慢,而在 Chrome 下这个过程很迅速。另外,这个页面中说使用 R Markdown 时,公式需要通过 <code>`$...$`</code> 才可以正常工作,但实际上模板已经可以直接用 <code><code>$...</code>$</code> 来完成公式的输入。</p>
</blockquote>
<p><a href="https://support.rbind.io/2017/04/25/yihui-website/" class="uri">https://support.rbind.io/2017/04/25/yihui-website/</a> 是谢益辉对自己网站模板的比较详细的思路介绍,值得多读一下,了解更多的细节。</p>
</div>
</div>
</div>
<div id="config-custom" class="section level1">
<h1><span class="header-section-number">3</span> 站点配置与功能订制</h1>
<div id="config" class="section level2">
<h2><span class="header-section-number">3.1</span> 站点配置</h2>
<p>站点配置主要在 <code>config.yaml</code> 文件中进行,直接参考谢益辉的 <code>config.yaml</code> 文件进行修改即可,注意目前暂时不添加 <code>googleAnalytics</code> 相关的信息,因此这一部分的取值为空。</p>
<blockquote>
<p><strong>说明</strong>:Hugo 的配置包含两部分,一部分位于主题目录之中,比如 <code>themes\hugo-lithium-theme\</code> 下的 <code>static\</code> 或 <code>layout\</code>,另一部分位于站点根目录之中,比如 <code>\layout\</code> 或 <code>\static\</code>,其中后者的优先级要高于前者。在后续的内容中,涉及到相关目录时,如果没有提及“主题中的”相关字眼,通常指的是站点根目录中的相关目录或文件。</p>
</blockquote>
</div>
<div id="custom" class="section level2">
<h2><span class="header-section-number">3.2</span> 功能订制</h2>
<p>功能订制主要是在谢益辉已提供功能的基础上进行修正和添加,首先需要从谢益辉的 <code>\static\</code> 和 <code>\layout\</code> 中复制全部文件到博客的根目录中,接下来<a href="#fn3" class="footnoteRef" id="fnref3"><sup>3</sup></a>,</p>
<ul>
<li><p><strong>公式</strong>:默认的模板公式做的不够好,因此参考 Hexo 的模板加入了公式编号功能,在 <code>/layouts/paritals/footer_mathjax.html</code> 加入了下面的内容:</p>
<pre class="javascript"><code>&lt;script type=&quot;text/x-mathjax-config&quot;&gt;
MathJax.Hub.Config({
TeX: {equationNumbers: {autoNumber: [&quot;AMS&quot;], useLabelIds: true}},
&quot;HTML-CSS&quot;: {linebreaks: {automatic: true}},
SVG: {linebreaks: {automatic: true}}
});
&lt;/script&gt;</code></pre></li>
<li><strong>logo</strong>:在 <code>\static\images\</code> 中放置已经做好的头像文件,如果觉得不满意,可以在 Photoshop 中参考已经做好的头像文件自行调整;</li>
<li><p><strong>disqus</strong>:将 <code>\layouts\partials\disqus.html</code> 文件中的:</p>
<pre class="javascript"><code>var disqus_js = &#39;//{{ .Site.DisqusShortname }}.disqus.com/embed.js&#39;;</code></pre>
<p>替换成:</p>
<pre class="javascript"><code>var disqus_js = &#39;https://{{ .Site.DisqusShortname }}.disqus.com/embed.js&#39;;</code></pre></li>
<li><strong>OK</strong>:关于异步加载字体功能,将 <code>\static\js\load-typekit.js</code> 文件中的 <code>kitId: 'kwz5xar'</code> 修改成 <code>kitId: 'oqz0fck'</code>,这里的 <code>kitId</code> 需要<a href="https://typekit.com/plans">注册</a>获得<a href="#fn4" class="footnoteRef" id="fnref4"><sup>4</sup></a>,目前看来,似乎之前这个账号在新的地址中也可以继续使用;</li>
<li>从 <code>\layouts\partials\head_custom.html</code> 可以看出:
<ul>
<li><strong>OK</strong>:FontAwesome 相关的字体也是异步在线加载的,现在已迁移到本地,否则 Ad block 有可能产生不好的影响,导致图标无法显示;</li>
<li><strong>OK</strong>:只有 <code>cn/</code> 目录下的文章会异步加载思源宋体,已修改,参考 <code>head_custom.html</code>;</li>
<li><strong>OK</strong>:谢益辉设定 2017 年以前的文章会异步加载 <a href="https://github.com/vinta/pangu.js"><code>pangu</code></a> 插件,这里将 <code>{{ if lt (.Date.Year) 2017 }}</code> 修改成 <code>{{ if lt (.Date.Year) 2005 }}</code>,相当于不再加载该插件;</li>
</ul></li>
<li><strong>OK</strong>:时间格式正文页中的时间格式显示比较怪,在没有了解 Hugo 的语法前,将 <code>\layouts\partials\article_meta.html</code> 文件中的 <code>{{ .Date.Format (default &quot;January 2, 2006&quot; .Site.Params.dateFormat ) }}</code> 修改成 <code>{{ .Date.Format &quot;2006/01/02&quot; }}</code>;</li>
<li><strong>OK</strong>:GitHub Edit 在 Windows 上,文件路径中使用 <code>\</code>,而 <code>\layouts\partials\article_meta.html</code> 中没有考虑到这一点,导致生成的链接中包含 <code>%5c</code> 字样,这正是 <code>\</code> 对应的 html 转义码,因此将文件中的<code>{{ $.Scratch.Set &quot;filePath&quot; $.File.Path }}</code> 修改成 <code>{{ $.Scratch.Set &quot;filePath&quot; (replace $.File.Path &quot;\\&quot; &quot;/&quot;) }}</code>,注意不是替换 <code>%5c</code>,而是 <code>\\</code>;</li>
<li><p><strong>OK</strong>:关于页面标题居中通过修改 <code>\layouts\partials\article_meta.html</code> 将“关于”页面的标题剧中,具体的,需要将如下代码</p>
<pre class="html"><code>&lt;h1 class=&quot;article-title&quot;&gt;{{ .Title }}</code></pre>
<p>修改为:</p>
<pre class="html"><code>{{if findRE &quot;-about$&quot; $.File.BaseFileName }}
&lt;h1 class=&quot;article-title&quot; style=&quot;text-align: center;&quot;&gt;{{ .Title }}
{{ else }}
&lt;h1 class=&quot;article-title&quot;&gt;{{ .Title }}
{{ end }}</code></pre></li>
</ul>
</div>
<div id="futureFeatures" class="section level2">
<h2><span class="header-section-number">3.3</span> 待实现</h2>
<ol style="list-style-type: decimal">
<li><strong>已解决</strong>:R Markdown 下面设定超链接在新窗口中打开,Plain Markdown 中在 <code>_config.yaml</code> 的 <code>blackfriday</code> 设置即可;</li>
<li><strong>已解决</strong>:标签和分类相关的问题:
<ul>
<li>标签和分类中的空格会被自动忽略,怎么禁止(做不到,但可以在生成页面时再用 Hugo 的指令替换回来);</li>
<li>标签和分类为中文时,Blogdown 对应的当前分类(标签)条目汇总页无法显示,但是 <a href="https://blog.coderzh.com/categories/读书笔记/" class="uri">https://blog.coderzh.com/categories/读书笔记/</a> 是正常工作的,这说明有可能是 blogdown 或者模板的问题(已得到 Yihui 修正,是 <code>Servr</code> 包的问题);</li>
<li>另一个问题是当前分类(标签)汇总页的标题不能是 <code>.Title</code>,否则取值为 <code>年份</code>,这里由于 <code>tags</code> 和 <code>categories</code> 都位于站点根目录下,因此唯一的可能是获取用户进到本页面之前的前一个页面对应的 section,然后根据该 section 展示一个与 section 有关的标签页或分类页,然而这样做的基础是可以在不同的 section 下面生成各自的 <code>tags</code> 和 <code>categories</code> 页(Terms 页本来也不怎么需要分布,而 Section 的 list pages 分页并不受影响);</li>
<li><strong>已解决</strong>:<strong>标签云</strong>功能的<a href="/tech/2017/07/10/tags-cloud/">实现</a>,默认的分类和标签都是同一类对象,而现在需要将两类对象分离出来,查看 <a href="https://github.com/kakawait/hugo-tranquilpeak-theme" class="uri">https://github.com/kakawait/hugo-tranquilpeak-theme</a> 中 kakawait-tranquilpeak 的主题效果时,发现里面有一个 <code>\layouts\taxonomy</code> 目录,其中包含了 <code>archive.terms.html</code>, <code>category.html</code>, <code>category.terms.html</code>, <code>tag.html</code>, <code>tag.terms.html</code>,再根据 <a href="https://gohugo.io/templates/terms/" class="uri">https://gohugo.io/templates/terms/</a> 的文档说明,显然存档页、分类页、标签页都可以分开定义模板,其中 <code>tag.terms.html</code> 是标签汇总页(标签云),那么 <code>tag.html</code> 就应该是某个标签下的 post 的展示页,暂时不清楚 <code>archive.terms.html</code> 的作用。在 <code>\layouts\taxonomy</code> 中添加了一个自定义的 <code>tag.terms.html</code>,之后就可以生成标签汇总页。具体生成标签汇总页时,发现 <a href="https://www.josephearl.co.uk/tags" class="uri">https://www.josephearl.co.uk/tags</a> 的标签云效果很不错,于是: (1) 到 <a href="https://github.com/josephearl/website" class="uri">https://github.com/josephearl/website</a> 下载了对应的源代码(主题的其它功能可以到 <a href="https://github.com/nodejh/hugo-theme-cactus-plus" class="uri">https://github.com/nodejh/hugo-theme-cactus-plus</a> 查阅),提取其中的 <code>themes\cactus-plus\static\js\js.tags</code> 到自己博客的 <code>\static\js\,(2) 参考这个模板中的</code>\section.html<code>文件的内容,同时参考 &lt;https://github.com/kakawait/hugo-tranquilpeak-theme&gt; 的目录结构,在</code><code>中添加了一个自定义的</code>tag.terms.html<code>,(3) 修改</code>tags.js<code>中的</code>var tagcloudOptions={size:{start:12,end:30,unit:“pt”},color:{start:“#bbbbbb”,end:“#2dbe60”}}<code>,将其中的两个</code>start<code>,</code>end` 修改成现在的取值,用于指定标签云字体的大小和颜色。</li>
<li><a href="https://www.josephearl.co.uk/tags" class="uri">https://www.josephearl.co.uk/tags</a> 是一个非常好的标签云的效果;</li>
</ul></li>
<li><strong>已解决</strong>:标签:正文中的标签,标签汇总页(<strong>已解决</strong>),单个标签对应文章列表(分页,文章多时再解决,这是 Hugo 自动做的事情,完全不是问题);</li>
<li><strong>已解决</strong>:分类:正文中显示所属分类,分类目录页(分页),单个分类中的文章列表(分页,文章多时再解决,这是 Hugo 自动做的事情,完全不是问题);
<ul>
<li><a href="https://tranquilpeak.kakawait.com/categories/" class="uri">https://tranquilpeak.kakawait.com/categories/</a>:这个分类页面显示了标签,还显示了全部 post,不同分类下的 post,值得参考;</li>
</ul></li>
<li><strong>已解决</strong>:除了 EN 下外,其它地方的 tags list/paper list 的标题都用中文,这些地方的标题都居中(技巧是给每个分类以及标签一个 Section 代码前缀);</li>
<li><strong>已解决</strong>:能不能每个 section 中包含一个 <code>tags</code> 和 <code>categories</code> 页面?</li>
<li><strong>已解决</strong>:存档:按年份倒序的存档页(分页),根据 <a href="https://gohugo.io/templates/terms/" class="uri">https://gohugo.io/templates/terms/</a>,可以用 <code>len .Data.Terms</code> 和 <code>len .Data.Pages</code> 得到标签数和页数;</li>
<li><strong>已解决</strong>:Hexo 中的 <code>&lt;ol&gt;</code> 标记默认可以添加一个 <code>start</code> 属性,但是本主题中还不支持,用 R Markdown 可以通过 Pandoc 的能力来实现;</li>
<li><strong>已解决</strong>:FontAwesome 相关的字体也是异步在线加载的,可以考虑将来迁移到本地;</li>
<li><strong>已解决</strong>:只有 <code>cn/</code> 目录下的文章会异步加载思源宋体,需要修改;</li>
<li><strong>已解决</strong>:页面摘要:用 <code>&lt;!--more--&gt;</code> 生成的目录页和存档页不同,这种类型的页面中包含一部分正文内容,并且需要支持分页,对应于模板的 <code>.Summary</code> 和 <code>.li</code> 视图,具体参见<a href="/tech/2017/07/08/hugo-template-priority/">这里</a>;</li>
<li><strong>已解决</strong>:<strong>搜索</strong>功能(实现过程参考<a href="/tech/2017/07/10/hugo-local-search/">这里</a>):
<ul>
<li>可以用 <code>lunr.js</code> 或者其增强版 <a href="http://blog.csdn.net/watkinsong/article/details/47168075"><code>elasticlunr.js</code></a> 来实现,其中 <code>lunr.js</code> 的比较好的主题示例可以参考 <a href="https://themes.gohugo.io/docdock/">DocDock</a>;</li>
<li>另一种方案是 Hexo 的 NexT 主题使用的 <a href="https://github.com/algolia/react-instantsearch/"><code>instantsearch.js</code></a>,<a href="https://community.algolia.com/instantsearch.js/v2/getting-started.html" class="uri">https://community.algolia.com/instantsearch.js/v2/getting-started.html</a> 有一个比较详细的使用步骤介绍,<a href="https://codepen.io/Algolia/pen/ZOyoJg" class="uri">https://codepen.io/Algolia/pen/ZOyoJg</a> 是一个非常好的演示例子。</li>
<li><a href="https://www.josephearl.co.uk/" class="uri">https://www.josephearl.co.uk/</a> 的在线搜索感觉非常轻量,也还不错,一些小细节的 CSS 问题还可以参考 <a href="https://www.josephearl.co.uk/post/css-overlay/" class="uri">https://www.josephearl.co.uk/post/css-overlay/</a>。这个博客用的是 <a href="https://github.com/nodejh/hugo-theme-cactus-plus" class="uri">https://github.com/nodejh/hugo-theme-cactus-plus</a>,从 <a href="https://github.com/josephearl/website" class="uri">https://github.com/josephearl/website</a> 下载的源代码中的 <code>\themes\cactus-plus\static\js</code> 目录中可以发现,同时有 <code>search.js</code> 和 <code>lunr.js</code>,因此感觉应该是一个 <code>lunr.js</code> 的包装,不过这个站点的搜索好像只针对标题和标签,虽然快但是没有全文搜索的能力;</li>
<li>Hexo 的 NexT 主题实际上本人现在用的是一种本地搜索的实现方式,<code>themes\next\layout\_third-party\search</code> 中的 <code>localsearch.swig</code> 以及 <code>next\source\css\_common\components\third-party</code> 中的 <code>localsearch.styl</code> 是两个最为重要的文件,还有一个 <code>next\layout\_partials\search</code> 中的 <code>localsearch.swig</code> 可以参考,这是目前最满意的方案,可惜需要用到 <code>db.json</code>,这个文件目前还没有找到好的方案来生成,但感觉上与 Hugo 的 <code>index.xml</code> 文件的生成有关联。</li>
<li><a href="https://discourse.gohugo.io/t/search-index-json-file-for-lunr-js/6286/8">Search Index .json-file for Lunr.js</a>:没看明白;</li>
<li><a href="https://github.com/gohugoio/hugo/issues/144">Save data to “data/pages.json” #144</a>:没有解决方案;</li>
<li><a href="https://github.com/gohugoio/hugo/pull/1853">Add generator for a search index #1853</a>:没有解决方案;</li>
<li>生成全站的 <code>json</code> 文件(<strong>未解决</strong>):
<ul>
<li><a href="https://bitquabit.com/post/json-feed-with-hugo/" class="uri">https://bitquabit.com/post/json-feed-with-hugo/</a>:已试验不成功;</li>
<li><a href="https://github.com/bep/bepsays.com/commit/1d7bf7fd6e7c637f28a04f93a97ebfed084c27ff" class="uri">https://github.com/bep/bepsays.com/commit/1d7bf7fd6e7c637f28a04f93a97ebfed084c27ff</a>:未试验,但感觉是一个 post 生成一个文件,这个地址来自 <a href="https://discourse.gohugo.io/t/simple-json-site-index-in-hugo/2854">Simple JSON site index in Hugo</a>;</li>
</ul></li>
</ul></li>
<li><strong>已解决</strong>:图片浏览器不再用 <code>fancybox</code>,使用方便程度和整合难度都不太理想,改成用 <a href="/tech/2017/07/10/hugo-light-gallery/"><code>lightGallery</code></a>;</li>
<li><strong>OK</strong>:图片保存的路径,在 <code>\static\images\</code> 中保存是比较好的选择,Rmd 文件生成的图像在 <code>static\figures\</code>之中,不需要人工干预;</li>
<li><p><strong>已解决</strong>:文章内目录:<code>\layouts\_default\single.html</code> 显示目前的主题是支持 toc 功能的,通过 <code>show_toc: true</code> 开启,如果是 Rmd 文件,开启方法参考 Bookdown 即可:</p>
<pre class="yaml"><code>output:
blogdown::html_page:
toc: true
number_sections: true</code></pre></li>
<li><strong>已解决</strong>:文章内的子标题编号,由于 Hugo 的 Markdown 引擎 <a href="https://github.com/russross/blackfriday">blackfriday</a> 还不支持 Auto numbering,因此这个功能暂时不好实现,Rmd 提供了接口,开启方法见上面的示例代码或本文档的源文件;</li>
<li><strong>可解决</strong>:视频文件的特殊显示效果 <code>lightGallery</code> 就可以解决,参考 <a href="https://gohugo.io/extras/shortcodes/">Shortcodes</a> 可以了解更多关于短代码的说明,里面有 Youtube 的支持,但是感觉这会导致不同的系统不兼容,另外还可以参考主题 <code>Castanet</code> 的实现方法;需要进一步了解自己怎样定义好的短代码;</li>
<li><strong>已解决</strong>:图片的标题是用 <code>*...*</code> 还是直接用一个 <code>&lt;p class=&quot;text-align: center&quot;&gt;...&lt;/p&gt;</code>,最终决定定义一个 <code>imgCaption</code> 和 <code>tabCaption</code>,这里使用了 Pandoc 的转换功能,将 Markdown 代码中的可选文本自动转换成 Caption;</li>
<li><strong>可解决</strong>:如果将幻灯片等和本博客集成到一起,需不需要集成,做不了,也没必要,直接再做一个仓库保存幻灯片即可;</li>
<li><strong>OK</strong>:试验添加 <code>Rmd</code> 文件,并在 RStudio 中查看运行效果,原生的 Rmd 格式的 YAML 头和 blogdown 中的并不完全相同,各走各即可,目前使用过程中除 toc 功能外大部分是相同的;</li>
<li><strong>可解决</strong>:不准备做,反正 <code>EN</code> 已经基本的外观。像 <a href="https://github.com/bep/bepsays.com/blob/master/config.toml" class="uri">https://github.com/bep/bepsays.com/blob/master/config.toml</a> 一样,提供不同语言界面的支持,或者像 <a href="https://github.com/kakawait/hugo-tranquilpeak-theme" class="uri">https://github.com/kakawait/hugo-tranquilpeak-theme</a> 中的 <code>hugo-tranquilpeak-theme-master\i18n</code> 那样用不同 YAML 提供语言支持的做法也非常值得参考;</li>
<li><strong>可解决</strong>:多主题:<a href="https://yulinling.net/" class="uri">https://yulinling.net/</a> 中 blog 部分是卡片列表,而相册部分是另外一种主题,不知道是不是可以在不同的 Section 中用不同的主题,还是压根是两个站点,是一个站点,只需要给指定的 Section 一个特殊的 list.html 即可,参考<a href="/tech/2017/07/08/hugo-template-priority/">这里</a>,再移植其它模板的代码即可;</li>
<li><p><strong>别解决</strong>:如何通过 Hugo 删除一些不想要的 post 在 <code>public\</code> 中的 html 存档,html 文档类似于缓存,删除之后下次 Render 时候又要再做一次,所以不要删除;</p></li>
</ol>
</div>
</div>
<div id="themes" class="section level1">
<h1><span class="header-section-number">4</span> 主题调整</h1>
<div id="page-width" class="section level2">
<h2><span class="header-section-number">4.1</span> 页面宽度</h2>
<p>在 <code>static/css/fonts/</code> 中修改 <code>custom.css</code>,相关内容参考该文件中的注释。</p>
</div>
<div id="font-family" class="section level2">
<h2><span class="header-section-number">4.2</span> 字体</h2>
<p>在 <code>static/css/fonts/</code> 中修改 <code>fonts.css</code>,调整字体相关的设置为如下内容:</p>
<pre class="css"><code>body {
font-family: &#39;Alegreya&#39;, &#39;Palatino Linotype&#39;, &#39;Book Antiqua&#39;, Palatino,
&#39;source-han-serif-sc&#39;, &#39;Source Han Serif SC&#39;, &#39;Source Han Serif CN&#39;,
&#39;Source Han Serif TC&#39;, &#39;Source Han Serif TW&#39;, &#39;Source Han Serif&#39;, &#39;Songti SC&#39;,
&#39;仿宋&#39;, &#39;FangSong&#39;, &#39;NSimSun&#39;, &#39;Microsoft YaHei&#39;, serif;
}
blockquote {
font-family: &#39;Source Sans Pro&#39;, Tahoma, Geneva, &#39;STKaiti&#39;, &#39;KaiTi&#39;, &#39;楷体&#39;, &#39;SimKai&#39;,
&#39;DFKai-SB&#39;, &#39;NSimSun&#39;, serif;
}
.cn blockquote {
font-family: &#39;Alegreya&#39;, &#39;Palatino Linotype&#39;, &#39;Book Antiqua&#39;, Palatino, &#39;STKaiti&#39;,
&#39;KaiTi&#39;, &#39;楷体&#39;, &#39;SimKai&#39;, &#39;DFKai-SB&#39;, &#39;NSimSun&#39;, serif;
}
code {
font-family: &#39;PT Mono&#39;, &#39;STKaiti&#39;, &#39;KaiTi&#39;, &#39;SimKai&#39;, monospace;
font-size: 85%;
}
p code, li code {
font-size: 90%;
}
strong {
color: #2dbe60;
}</code></pre>
</div>
</div>
<div id="Hugo-Functions" class="section level1">
<h1><span class="header-section-number">5</span> 功能解读</h1>
<ul>
<li>Hugo 中的相关统计数据,如字数(<code>.WordCount</code>)、估计阅读时间(<code>.ReadingTime</code>)、页数、文章数、分类数等可以参考<a href="https://gohugo.io/templates/variables/">变量列表</a>,特殊功能实现参考<a href="https://gohugo.io/templates/functions/">函数列表</a>;</li>
<li><code>.Site.Params</code> 开头的是站点的<code>全局</code>参数,可以自定义;</li>
<li><code>.Params</code> 开头的是当前文章中的<code>局部</code>参数,在 yml 头中定义,但暂时不清楚是否可以自定义,当然即使可以支持,为了保持和其它系统或 Markdown 的良好兼容,不推荐在文章内用自定义的参数;</li>
<li><p>下面的代码实现了一个循环:</p>
<pre class="html"><code>{{ range .Site.Params.customJS }}
&lt;script async src=&quot;{{ . | relURL }}&quot;&gt;&lt;/script&gt;
{{ end }}</code></pre></li>
<li><code>{{ with FOO }}{{ . }}{{ end }}</code> 是 <code>{{if FOO }}{{ FOO }}{{ end }}</code> 的另一种写法,可以不用写两次 <code>FOO</code>;</li>
<li><code>.Data</code> is dynamic, and its value changes according to the specific list you want to generate. For example, the list page <code>https://xmin.yihui.name/post/</code> only contains pages under <code>content/post/</code>, and <code>https://xmin.yihui.name/note/</code> only contains pages under <code>content/note/</code>;</li>
<li><code>content\</code> 目录下的 <code>_index.md</code> 对应的是存档页,对应 <code>list.html</code>,用于生成全部 post 的存档列表;分类、标签汇总页对应 <code>terms.html</code>,是自动生成的,<code>single.html</code> 对应一篇 post 的生成;分类、汇总还可以通过 <code>list.html</code> 生成各自的存档页,对分类、标签设置不同的模板参考“待解决问题”;</li>
<li><code>_index.md</code> 中有内容时(YAML 除外),本主题将 <code>list.html</code> 转换成一个类似于网站主页说明的 <code>index.html</code>,但这个转换不是用 <code>single.html</code> 的模板,而是 <code>list.html</code> 的 <code>if</code> 分支的模板,没有内容时,填充当前 section 下的全部文章的 list。但不同位置的 <code>_index.md</code> 的管辖范围不同;</li>
<li>模板文件不能用 Markdown,只能用 html 语法格式;</li>
<li><p>主题中一段比较有参考价值的代码的解释:</p></li>
</ul>
<pre class="html"><code>{{ if .File.Path }}
{{ $Rmd := (print .File.BaseFileName &quot;.Rmd&quot;)) }}
{{ if (where (readDir (print &quot;content/&quot; .File.Dir)) &quot;Name&quot; $Rmd) }}
{{ $.Scratch.Set &quot;FilePath&quot; (print .File.Dir $Rmd) }}
{{ else }}