-
Notifications
You must be signed in to change notification settings - Fork 523
/
syncBear.js
164 lines (144 loc) · 5.02 KB
/
syncBear.js
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
import fs from 'fs-extra'
import rawFs from 'fs'
import sqlite3 from 'sqlite3'
import moment from 'moment'
import del from 'node-delete'
import jsonfile from 'jsonfile'
const BEAR_PATH = '/Users/MookCake/Library/Containers/net.shinyfrog.bear/Data/Library/Application\ Support/net.shinyfrog.bear'
const NOTE_DATABASE = `${BEAR_PATH}/database.sqlite`
const NOTE_IMAGES_PATH = `${BEAR_PATH}/Local\ Files/Note\ Images`
const itemsDescriptions = jsonfile.readFileSync('./parse-seo.json')
const sqlite = sqlite3.verbose()
const db = new sqlite.Database(NOTE_DATABASE)
const promisify = (target, methods) => {
methods.forEach((method) => {
const oldMethod = target[method]
target[method] = (...args) => new Promise((resolve, reject) => {
oldMethod.apply(target, [...args, (err, rets) => {
if (err) {
console.log('ERROR', err)
reject(err)
} else {
resolve(rets)
}
}])
})
})
}
const util = { del }
promisify(db, ['run', 'all', 'serialize'])
promisify(fs, ['writeFile', 'exists', 'copy', 'access'])
promisify(util, ['del'])
const LESSON_REGX = /(#\s+Lesson\s+([\d\.]+))([::])([\s\S]+?)\n/
const TAG_REGX = /#React.js教程#/
const start = async () => {
await db.serialize()
let notes = await db.all("SELECT * FROM ZSFNOTE")
await util.del('./_posts/*.md')
notes = notes
.filter((note) => note.ZSUBTITLE.match(TAG_REGX))
.map(generateNoteObj)
.sort((a, b) => a.num - b.num)
.map(generatePost)
console.log('\n')
await Promise.all(notes)
console.log('\n DONE!')
}
const SCRIPTOJ_URL = 'http://scriptoj.com'
const generateNoteObj = (rawNote, i) => {
const note = rawNote.ZTEXT
const lessonCaptures = note.match(LESSON_REGX)
const num = +lessonCaptures[2]
const title = lessonCaptures[4].trim()
const text = note
.replace(/\[([^\[]+?)\]\(SCRIPTOJ:(\d+)\)/g, `<a target="_blank" href="${SCRIPTOJ_URL}/problems/$2">$1</a>`)
.replace(LESSON_REGX, '')
.replace(TAG_REGX, '')
.trim()
.replace(/‘|’/g, '\'')
.replace(/\t/g, ' ')
checkTODOsIfExist(text, title)
return { num, title, text }
}
const checkTODOsIfExist = (content, title) => {
if (content.match(/TODO/)) {
console.warn(`WARNING: 文章 "${title}" 存在未完成内容!`)
}
}
const DATE_FORMAT = 'YYYY-MM-DD'
const TEXT_PREFIX = (title, i) => {
const item = itemsDescriptions[i] || {}
const description = item.description || 'React.js 小书是一个开源、免费、专业、简单的 React.js 在线教程。提炼实战经验中基础的、重要的、频繁的知识进行重点讲解,让你能用最少的精力深入了解实战中最需要的 React.js 知识。'
const keywords = item.keywords || 'react.js,web,props,state,javascript'
return `---
layout: post
title: ${title}
description: ${description}
tags: [${keywords}]
---
<ul style='font-size: 14px; margin-top: -10px;'>
<li>
作者:<a href="https://www.zhihu.com/people/hu-zi-da-ha" target="_blank">胡子大哈</a>
</li>
<li>
原文链接:<a href="http://huziketang.com/books/react{{ page.url }}"> http://huziketang.com/books/react{{ page.url }} </a>
</li>
<li>转载请注明出处,保留原文链接和作者信息。</li>
</ul>
`
}
const IMAGE_REGX = /\[image:([\w\d\-]+\/([\w\d\.\-]+.png))\]/g
const IMAGE_REGX_EACH = /\[image:([\w\d\-]+\/([\w\.\d\-]+.png))\]/
const TEXT_SUFFIX = () => `
* * *
> 因为第三方评论工具有问题,对本章节有任何疑问的朋友可以移步到 <a target="_blank" href="${SCRIPTOJ_URL}/category/4/react-js-小书交流区">React.js 小书的论坛</a> 发帖,我会回答大家的疑问。
`
const generatePost = async (note, i) => {
const date = getDate(i)
const postName = `./_posts/${date}-lesson${i + 1}.md`
await copyImagesForNote(note)
replaceImageTag(note, i)
console.log('Creating post', note.title)
return fs.writeFile(
postName,
`${TEXT_PREFIX(note.title, i)}${note.text}${TEXT_SUFFIX()}`,
'utf-8'
)
}
const getDate = (i) => {
return moment('2017-02-15')
.day(i)
.format(DATE_FORMAT)
}
const copyImagesForNote = (note) => {
const captures = note.text.match(IMAGE_REGX)
if (!captures) return []
return Promise.all(captures
.map((imgStr) => {
const cap = imgStr.match(IMAGE_REGX_EACH)
return {
dest: `./assets/img/posts/${cap[2]}`,
src: `${NOTE_IMAGES_PATH}/${cap[1]}`
}
})
.map(checkIfExistsAndCopy)
)
}
const REMOTE_IMG_PATH = 'http://huzidaha.github.io/static/assets/img/posts/'
// const REMOTE_IMG_PATH = 'http://huziketang.com/books/react/assets/img/posts/'
const replaceImageTag = (note, i) => {
const item = itemsDescriptions[i] || { alt: '实例图片' }
note.text = note.text.replace(IMAGE_REGX, `<a href="${REMOTE_IMG_PATH}$2" target="_blank">![${item.alt}](${REMOTE_IMG_PATH}$2)</a>`)
}
const checkIfExistsAndCopy = async (obj) => {
if (
fs.existsSync(obj.src) &&
!fs.existsSync(obj.dest)
) {
console.log('Copying file', obj.dest)
return fs.copy(obj.src, obj.dest)
}
}
start().catch((e) => {
console.log(e.message, e.stack)
})