UNPKG

3.43 kBJavaScriptView Raw
1'use strict';
2
3var yaml = require('yaml-js')
4var path = require('path')
5var fs = require('fs')
6var _ = require('lodash')
7var util = require('../util')
8var debug = require('debug')('darko')
9
10
11var PTN_POST_FILE = /(\d{4}-\d{1,2}-\d{1,2})-([^\\]+?)(\.\w+)$/
12
13
14function Post(attrs) {
15 var fpath = attrs.fpath
16 var m = fpath.match(PTN_POST_FILE)
17
18 if (!m) {
19 debug('Ignored ' + path.relative(attrs.site.cwd, attrs.fpath))
20 return
21 }
22 var date = m[1].split('-')
23
24 this.site = attrs.site
25 this.categories = attrs.categories || []
26 this.path = path.relative(this.site.cwd, fpath)
27 this.slug = m[2]
28 this.ext = m[3]
29 this.date = new Date(
30 parseInt(date[0], 10),
31 parseInt(date[1], 10) - 1, // Starts from 0
32 parseInt(date[2], 10)
33 )
34 this.title = util.capitalize(this.slug)
35
36 if (fs.existsSync(fpath)) {
37 var content = fs.readFileSync(fpath, this.site.encoding)
38 var parts = content.split('---')
39
40 if (parts.length >= 3) {
41 _.extend(this, yaml.load(parts[1]))
42 this.content = parts.slice(2).join('---').trim()
43 var caret = this.content.indexOf('\n\n')
44 this.excerpt = caret > 0 ? this.content.slice(0, caret) : this.content
45 }
46 else {
47 throw new Error('Failed to parse YAML front matter from ' + fpath)
48 }
49 }
50
51 if (this.categories.length === 0) {
52 if (this.category) {
53 this.categories = this.category
54 delete this.category
55 }
56 else {
57 var parentFolders = path.relative(this.site.cwd, path.dirname(fpath))
58 this.categories = _.without(parentFolders.split(path.sep), '_posts', '_drafts')
59 }
60 }
61
62 // In YAML front matters, categories and tags are specified in list or space
63 // separated string. Let's make sure they are arrays now.
64 if (_.isString(this.categories)) {
65 this.categories = this.categories.split(' ')
66 }
67 if (_.isString(this.tags)) {
68 this.tags = this.tags.split(' ')
69 }
70
71 // We can specify date in YAML front matters too. Can we?
72 if (_.isString(this.date)) {
73 this.date = new Date(this.date)
74 }
75
76 if (!this.hasOwnProperty('published')) {
77 this.published = true
78 }
79
80 var data = {
81 year: this.date.getFullYear(),
82 i_month: this.date.getMonth() + 1,
83 i_day: this.date.getDate(),
84 title: this.slug,
85 categories: this.categories ? this.categories[0] : ''
86 }
87
88 data.month = util.pad(data.i_month, '0', 2)
89 data.day = util.pad(data.i_day, '0', 2)
90
91 this.url = this.site.permalink
92 .replace(/:(\w+)/g, function(m, key) {
93 return data[key] || ''
94 })
95 .replace(/\/{2,}/g, '/')
96
97 this.id = path.join(path.dirname(this.url), path.basename(this.url, '.html'))
98
99 this.dest = path.join(this.site.dest, this.site.baseurl.slice(1), this.url)
100 if (path.extname(this.dest) !== '.html') {
101 this.dest = this.dest.replace(/\/?$/, '/index.html')
102 }
103}
104
105Object.defineProperties(Post.prototype, {
106 valid: {
107 get: function() {
108 return /(_posts|_drafts)$/.test(path.dirname(this.path)) &&
109 PTN_POST_FILE.test(path.basename(this.path))
110 }
111 },
112
113 future: {
114 get: function() {
115 var now = new Date()
116 var tomorrow = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1)
117
118 return tomorrow.getTime() <= this.date.getTime()
119 }
120 },
121
122 publishable: {
123 get: function() {
124 return this.valid &&
125 (this.published || this.site.includeDrafts) &&
126 (!this.future || this.site.includeFuture)
127 }
128 }
129})
130
131
132module.exports = Post