Keep Learning

伪程序员记录点滴

Octopress添加标签

前因

由于之前参考中文的搜索,结果都不理想,推翻重来,直接使用google使用octopress tag关键词搜索到的第一个返回结果来修改,下面记录如下。

显示所有的便签列表

修改source/_layouts/post.html文件,使它们include一个名字为tags.html的新文件。

创建一个新文件source/_includes/post/tags.html,整个文件的内容如下所示:

source/_includes/post/tags.html
1
2
3
4
5
6
7
8
9
10
11
12
<div id="tag_list">
    Tags:
    <ul id="tags_ul">

        <li><a href="/tags/Octopress/">Octopress</a></li>

        <li><a href="/tags/Learning/">Learning</a></li>

        <li><a href="/tags/Github/">Github</a></li>

    </ul>
</div>

sass/custom/_styles.css文件中添加如下内容:

sass/custom/_styles.css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
div#tag_list {
    font-size: 12pt;
}

#tags_ul {
    display: inline;
}

#tags_ul li:last-child:after {
  content: "";
}

#tags_ul li:after {
  content: ", ";
}

#tags_ul li {
    display: inline;
}

创建tag文件和tag云

使用作者提供的perl脚本文件,由于作者使用Octopress生成的文件是直接在public文件夹下面的,但是默认的Octopress生成的博客内容是在/public/blog文件夹下面的,因此作者的提供的perl文件需要进行一个小的改动,若没有改动将无法生成对应的tags,检查是否成功的办法是查看成功的生成了source/_includes/custom/tag_cloud.html文件,该文件的内容类似于下面的方式:

source/_includes/custom/tag_cloud.html
1
2
3
4
5
<div id='tag_cloud'>
<a href="/blog/tags/6LoWPAN/" title="1 entry" class="tag_1">6LoWPAN</a>
<a href="/blog/tags/Arch/" title="1 entry" class="tag_1">Arch</a>
<a href="/blog/tags/AWK/" title="1 entry" class="tag_1">AWK</a>
</div>

文章末尾附上修改后的tagify.pl文件。 在添加了该代码之后,整个生成tag的操作便是下面的步骤

生成tags操作
1
2
3
rake generate
./tagify.pl
rake generate

上面的代码只是需要在每次有新的tag加入的时候需要执行,如果新添加的博客文章没有使用新的tag,则不需要执行这个步骤,只需要按照正常的操作即可。
上面的操作一共干了三件事:

  • 生成source/_includes/custom/tag_cloud.html文件,文件内容如上所述。
  • 对于每个tag标签,在对应的目录下生成一个index.markdown文件,如对于Linux这个标签,将会创建source/tags/Linux/index.markdown这样一个文件。
  • 同时创建了一个source/tags/index.markdown的文件,可以在主页面被引用。

显示tag云标签

为了在右侧显示云标签,需要修改_config.yaml文件,将tag_cloud.html文件添加到default_asides中,目前的博客内容没有显示该分类,若想添加云标签显示可以通过修改_config.yml通过添加该侧边栏完成该功能。
创建source/_includes/asides/tag_cloud.html文件,该文件包含了soure/_includes/custom/tag_cloud.html文件(该文件是由tagify.pl脚本文件生成的),文件的内容如下所示:

source/_includes/asides/tag_cloud.html (tag_cloud.html) download
1
2
3
4
5
6
<section>
    <h1>Tags</h1>
    <div class="tag_cloud">
     {% include custom/tag_cloud.html %}
    </div>
</section>

接下来修改sass/custom/_styles.css文件,添加标签的css示例,该文件内容如下所示:

sass/custom/_styles.css
1
2
3
4
5
6
7
8
9
10
11
12
13
.tag_1 {
    font-weight: 200;
    font-size: 10pt;
}
.tag_2 {
    font-weight: 200;
    font-size: 12pt;
}
...
.tag_10 {
    font-weight: 900;
    font-size: 24pt;
}

最后在导航控制文件source/_includes/custom/navigation.html中增加Tags标签,具体修改文件如下所示:

source/_includes/custom/navigation.html
1
2
3
4
<li><a href="/">Home</a></li>
<li><a href="/blog/archives">Archives</a></li>
+<li><a href="/tags/">Tags</a></li>
<li><a href="/about/">About Me</a></li>

总结

完成上述操作之后,便可以在主页的首部出现一个Tags的导航键,同时可以添加Tags分类标签到页面右侧的侧边栏,目前Tags标签功能似乎不支持中文页面的分类,待测试。

代码附录

修改后的tagify.pl (tagify.pl) download
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
#!/usr/bin/perl

use strict;
use warnings;
use File::Find;
use HTML::TreeBuilder;
use Getopt::Long;

my $octopress_root;

my $options_read = GetOptions("dir=s", \$octopress_root);

############################################################
unless ($options_read && $octopress_root) {
    print "\n";
    print "\n";
    print "usage: tagify.pl --dir d\n";
    print "\n";
    print "where d is the root octopress directory\n";
    print "   - the parent of source, public, etc.\n";
    print "\n";
    exit 1;
}

# The tag cloud HTML gets saved into this file.
# This file is included by two others: 
#  a) The file used for the sidebar aside
#  b) The page used to display all tags 
#     (accessible as /tags/index.html)
#
my $custom_file = "$octopress_root/source/_includes".
                  "/custom/tag_cloud.html";

# This is the data structure that contains all the tag 
# data parsed by the HTML files.
# It's key is the tag name (not case-normalized).
# The value is another hash.  That hash has 2 keys:
#  count - number of pages with that tag
#  range_num - a number from 1 - 10 indicating 
#              popularity (see below)
#  pages - an array of hashes
#
#  Each hash in the pages array has 3 keys: 
#  title - the HTML title of the post
#  file  - the full file name of the HTML file
#  categories - yet another hash
#
#  The categories hash has two keys: 
#  href - the url to the category page (as determined
#         by OctoPress)
#  text - the name of the category (as displayed by 
#         Octopress)
#
my $tag_data      = { };

# This function populates the tag_data data structure
#
find(\&getTags, "$octopress_root/public/blog");

# Find the number of times the most popular tag is used
#
my $max = 1;  # start with 1, not 0 to prevent a 
              # divide-by-zero error later
              # if none of the posts have tags
foreach my $tag (keys %$tag_data) {
    $tag_data->{$tag}->{count} = scalar(@{$tag_data->{$tag}->{pages}});
    if ($tag_data->{$tag}->{count} > $max) {
        $max = $tag_data->{$tag}->{count};
    }
}

# Assign each tag a range number from 1 - 10
# based on popularity.  This range number will
# be used along with CSS to print tags with
# the appropriate size.
#
foreach my $tag (keys %$tag_data) {
    $tag_data->{$tag}->{range_num} =
      int(($tag_data->{$tag}->{count} / $max)
          * 10
          + 0.5); # nearest whole number

    if ($tag_data->{$tag}->{range_num} == 0) {
        $tag_data->{$tag}->{range_num} = 1;
        # we want 1-10, not 0-10
    }
}

# Write the tag cloud file
#
open (O, ">$custom_file") || die;
print O "<div id='tag_cloud'>\n";

# sort by tag name, case insensitive
#
foreach my $tag (sort { lc($a) cmp lc($b)}
                      keys %$tag_data) {

    # give each tag anchor a title, 
    # for screen readers and the like
    #
    my $plural = "y";
    if ($tag_data->{$tag}->{count} > 1) {
        $plural = 'ies';
    }

    print O qq[<a href="/blog/tags/$tag/" ];
    print O qq[title="$tag_data->{$tag}->{count} entr$plural" ];
    print O qq[class="tag_$tag_data->{$tag}->{range_num}">];
    print O qq[$tag];
    print O qq[</a>\n];
}
print O "</div>\n";
close O;


# Now save the individual tag files
# First, clear out the directory because we're gonna 
# regenerate all the files.
#
my $tag_dir = "$octopress_root/source/blog/tags";

# If source/tags exists but is a file
#
die "source/blog/tags is a file" if (-f $tag_dir);

# Create the directory if it doesn't exist
#
if (!-d $tag_dir) {
    mkdir $tag_dir;
    createTagsIndexMarkdown($tag_dir);
}
else {
    # Delete all directories under source/tags.
    # We don't want to delete everything because we 
    # need to preserve tags/index.markdown in case 
    # something was modified there.
    #
    my $dirs = `find $tag_dir/* -type d`;

    my @dirs = split(/[\r\n]+/, $dirs);
    foreach my $dir (@dirs) {
        `/bin/rm -rf $dir`;
    }

}


# Make a file for each tag.
#
foreach my $tag (keys %$tag_data) {
    makeTagFile($tag);
}


##  ####################################################
##  Functions
##  ####################################################

sub makeTagFile {
    my $tag = shift;
    mkdir "source/blog/tags/$tag"
      ||
      die "Couldn't make directory source/blog/tags/$tag";

    open (O, "> source/blog/tags/$tag/index.markdown")
      ||
      die "Can't open source/blog/tags/$tag/index.markdown";

    print O qq^---
layout: page
title: Tag&#58; $tag
footer: false
---

<div id="blog-archives" class="category">
^;

    my $year = 0;

    # Sort by file name descending
    # This is the same as sorting by date descending
    #
    foreach my $file (
               sort { $b->{file} cmp $a->{file} }
                    @{$tag_data->{$tag}->{pages}}) {

        # Get the year month and date
        #
        my ($yyyy, $mm, $dd) = $file->{file} =~
            m!(\d\d\d\d)/(\d\d)/(\d\d)/!;

        # The HTML and associated logic here mimics
        # the HTML of the category pages - print 
        # a H2 for every new year
        #
        if ($yyyy != $year) {
            $year = $yyyy;
            print O "<h2>$year</h2>\n";
        }

        # Construct the URL & date string
        #
        my $url = $file->{file};
        $url =~ s/^$octopress_root\/public//;
        my $title = $file->{title};
        my @months = qw ( x Jan Feb Mar Apr May Jun
                          Jul Aug Sep Oct Nov Dec );
        my $mon = $months[$mm * 1];

        print O qq[
<article>
<h1><a href="$url">$title</a></h1>
<time datetime="$yyyy-$mm-${dd}T00:00:00-06:00" pubdate><span class='month'>$mon</span> <span class='day'>$dd</span> <span class='year'>$yyyy</span></time>
<footer>
<span class="categories">posted in 
];
        # Print each category, separated by commas
        #
        print O join(", ",
            map { "<a href='$_->{href}'>$_->{text}</a>" }
                @{$file->{categories}}
            );

        print O qq[</span>
</footer>
</article>
];
    }

    print O "</div>\n";
    close O;
}



sub getTags {
    my $file = $File::Find::name;

    # Only parse files that look like posts
    #
    return unless $file =~ /\.html$/;
    return unless $file =~ 
          /^$octopress_root\/public\/blog\/\d{4}\/\d{2}\/\d{2}\//;

    # Read the contents of the HTML file
    #
    open (HTML, $_) || die "Can't open $file";
    my $contents = join("", <HTML>);
    close HTML;

    my $tree = HTML::TreeBuilder->new();
    $tree->parse($contents);

    # Get the title
    #
    my $title = $tree->look_down(_tag  => "h1",
                                 class => "entry-title");
    $title = $title->as_trimmed_text();

    # Get the categories
    #
    my $category_ent = $tree->look_down(_tag  => "span",
                                        class => "categories");
    my @as = $category_ent->look_down(_tag  => "a",
                                      class => "category");
    my @categories = ();
    foreach my $a (@as) {
        push(@categories,
            { href => $a->attr('href'),
              text => $a->as_trimmed_text
            });
    }

    # Get the tags
    #
    my $ul = $tree->look_down("_tag", "ul",
                              "id"  , "tags_ul");
    if ($ul) {
        my @items = $ul->look_down("_tag" => "li");
        foreach my $item (@items) {
            my $tag = $item->as_trimmed_text();

            # Finally, populate the data structure
            #
            push (@{$tag_data->{$tag}->{pages}},
                { title      => $title,
                  file       => $file,
                  categories => \@categories
          } );
        }
    }
    else {
        # no tags in this document
    }

    $tree->delete();

}

# This function creates a default 
# source/tags/index.markdown
#
sub createTagsIndexMarkdown {
    my $tag_dir = shift;
    open (O, ">$tag_dir/index.markdown");
    print O qq[---
layout: page
title: Tags
footer: false
---

<div class="tag_page">
 {% include custom/tag_cloud.html %}
</div>
];
    close O;
}

Comments