AngularJS+Gulp开发极速静态博客系统(四)

在前端获取文章并构建索引

之前我们在后端已经通过 Gulp 任务创建了博客文章的索引,现在我们需要在前端对其进行一些处理以便我们的页面上能够获取文章的链接、分类等。

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
angular.module 'tini'
.factory 'index', ($rootScope, $filter, req) ->
index = null
(cb) ->
(index && cb? index) || req.index (data) ->
return (cb? index) if index
# 按时间新到旧排序文章
posts = data.posts.sort (a, b) ->
b.date - a.date
# 建立文章索引
indexes = {}
categories = {}
tags = {}
archives = {}
for post, i in posts
post.index = i
indexes[post.id = post.path.substr 0, post.path.indexOf '.'] = post
if post.categories
for category in post.categories
if categories[category]
categories[category].push post
else
categories[category] = [post]
if post.tags
for tag in post.tags
if tags[tag]
tags[tag].push post
else
tags[tag] = [post]
date = $filter('date') post.date, 'yyyy-MM'
if archives[date]
archives[date].push post
else
archives[date] = [post]
# 重新排序 tag
tagsSorted = []
for tag, posts of tags
tagsSorted.push
name: tag
posts: posts
count: posts.length
tagsSorted.sort (a, b) ->
b.count - a.count
# 根据标签名索引排序后的标签
tagNamesSorted = []
for tag in tagsSorted
tagNamesSorted.push tag.name
# 排序后的存档
archivesSorted = []
for archive, posts of archives
archivesSorted.push
name: archive
posts: posts
count: posts.length
archivesSorted.sort (a, b) ->
b.posts[0].date - a.posts[0].date
extend data,
indexes: indexes
categories: categories
tags: tags
tagsSorted: tagsSorted
tagNamesSorted: tagNamesSorted
archives: archives
archivesSorted: archivesSorted
extend $rootScope, data
$rootScope.all = data.posts
index = data
cb? data

编写一个指令来对文章内容做一些小处理

我们需要以 more 为分隔,来显示文章的概览,以及“继续阅读”的内容。

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
angular.module 'tini'
.directive 'post', ($parse, req) ->
(scope, element, attrs) ->
postFn = $parse attrs.post
scope.$watch attrs.post, (post) ->
if post
archive = $parse('archive') scope
proc = (post, content) ->
moreIndex = content.indexOf '<a id=more></a>'
hasMore = post.hasMore = moreIndex > -1
post.content = content
post.intro = if hasMore then content.substr 0, moreIndex else content
post
render = (element, post, archive) ->
if archive && post.hasMore
post.more = true
element.html post.intro
else
post.more = false
element.html post.content
assign = (post) ->
render element, post, archive
postFn.assign scope, post
if post.content
assign post
else
req.post post, (content) ->
assign proc post, content

完成页面的控制器部分

在控制器的部分中,我们需要获取页码、获取当前的文章列表、分页列表等。

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
tini = angular.module 'tini'
.controller 'home', ($scope, $routeParams, $timeout, $anchorScroll, index, title) ->
markAsArchive $scope
title()
index (data) ->
procArchivePosts $scope, $routeParams, data.posts
scrollToAnchor $timeout, $anchorScroll
.controller 'post', ($scope, $location, $timeout, $anchorScroll, index, title) ->
id = $location.path().substr 1
index (data) ->
post = data.indexes[id]
if post
$scope.post = post
title post.title
scrollToAnchor $timeout, $anchorScroll
else
$location.path '/'
angular.forEach
category: 'categories'
tag: 'tags'
archive: 'archives'
, (indexName, type) ->
tini.controller type, [
'$scope'
'$location'
'$routeParams'
'$timeout'
'$anchorScroll'
'index'
'title'
($scope, $location, $routeParams, $timeout, $anchorScroll, index, title) ->
name = $routeParams[type]
markAsArchive $scope
title name
index (data) ->
if data[indexName][name]
procArchivePosts $scope, $routeParams, data[indexName][name]
scrollToAnchor $timeout, $anchorScroll
else
$location.path '/'
]
# 获取当前页码
getPage = ($scope, $routeParams) ->
page = parseInt $routeParams.page
$scope.page = page || 1
# 根据页码获取当前页的文章列表
getPosts = ($scope, src, page) ->
postPerPage = $scope.config.postPerPage
start = postPerPage * (page - 1)
start = if start < src.length || start > -1 then start else 0
end = start + postPerPage
end = if end < src.length then end else src.length
$scope.posts = src.slice start, end
# 分页列表
getPagination = ($scope, src, page) ->
postPerPage = $scope.config.postPerPage
max = Math.ceil src.length / postPerPage
$scope.pagination = [1..max]
path = $scope.global.path
pathPageIndex = path.indexOf '/page/'
path = path.substr(0, pathPageIndex) if pathPageIndex > -1
path = '' if path == '/'
$scope.base = path
# 处理存档页
procArchivePosts = ($scope, $routeParams, src) ->
page = getPage $scope, $routeParams
getPosts $scope, src, page
getPagination $scope, src, page
markAsArchive = ($scope) ->
$scope.archive = true
# 控制滚动条
scrollToAnchor = ($timeout, $anchorScroll) ->
$timeout ->
$anchorScroll()
, 300

至此,再增加一些细节的处理,我们的博客已经可以跑起来了~
有兴趣的同学可以 git clone Tini
依次运行以下任务,即可体验一下。

  1. new 创建新文章
  2. publish 将已有文章编译与索引
  3. theme 编译主题包
  4. server 提供一个本地的服务器以便及时编译修改的文章并预览效果