1 |
|
2 |
|
3 | import fs from 'fs'
|
4 | import path from 'path'
|
5 | import glob from 'glob'
|
6 | import matter from 'gray-matter';
|
7 | import removeMd from 'remove-markdown';
|
8 | import { stripHtml } from "string-strip-html";
|
9 |
|
10 | const DEFAULT_LANGUAGE = 'ru'
|
11 | const CONTENT_PATH = 'content/**'
|
12 | const OUTPUT_INDEX_FILE = 'public/search-index.json'
|
13 |
|
14 | class HugoIndexer {
|
15 |
|
16 | constructor() {
|
17 | this.input = CONTENT_PATH
|
18 | this.output = OUTPUT_INDEX_FILE;
|
19 | this.baseDir = path.dirname(this.input);
|
20 | this.extensions = ['.md', '.html']
|
21 |
|
22 | this.indexData = {}
|
23 | this.indexData[DEFAULT_LANGUAGE] = []
|
24 |
|
25 | this._parseArgs()
|
26 | }
|
27 |
|
28 | _parseArgs() {
|
29 | if (process.argv.indexOf("-i") != -1) {
|
30 |
|
31 | this.input = process.argv[process.argv.indexOf("-i") + 1];
|
32 | console.log(process.argv.indexOf("-i"))
|
33 | }
|
34 | if (process.argv.indexOf("-o") != -1) {
|
35 |
|
36 | this.output = process.argv[process.argv.indexOf("-o") + 1];
|
37 | }
|
38 | }
|
39 |
|
40 | parseContent(dirPath) {
|
41 | const files = glob.sync(dirPath)
|
42 | for (let file of files) {
|
43 | const stats = fs.lstatSync(file)
|
44 | if (stats.isFile()) {
|
45 | this.parseFile(file)
|
46 | }
|
47 | }
|
48 | }
|
49 |
|
50 | parseFile(filePath) {
|
51 | const ext = path.extname(filePath)
|
52 |
|
53 | if (!this.extensions.includes(ext)) {
|
54 | return
|
55 | }
|
56 |
|
57 | const meta = matter.read(filePath);
|
58 | const { data: postMeta, content: postContent } = meta
|
59 |
|
60 | let plainText = ""
|
61 | if (ext == '.md') {
|
62 | plainText = removeMd(postContent);
|
63 | } else if (ext == '.html') {
|
64 | plainText = stripHtml(postContent);
|
65 | } else {
|
66 | console.log("Sikpped file: " + filePath)
|
67 | }
|
68 |
|
69 | let tags = [];
|
70 |
|
71 | if (postMeta.tags != undefined) {
|
72 | tags = postMeta.tags;
|
73 | }
|
74 |
|
75 | let [lang, uri] = this._getPostUrl(filePath, postMeta)
|
76 |
|
77 | const item = {
|
78 | 'uri': uri,
|
79 | 'title': postMeta.title,
|
80 | 'content': plainText,
|
81 | 'tags': tags
|
82 | };
|
83 |
|
84 | if (lang) {
|
85 | item['lang'] = lang
|
86 | } else {
|
87 | lang = DEFAULT_LANGUAGE
|
88 | }
|
89 |
|
90 | const indexPosts = this.indexData[lang] || []
|
91 | indexPosts.push(item)
|
92 | this.indexData[lang] = indexPosts
|
93 |
|
94 | }
|
95 |
|
96 | _getPostUrl(filePath, postMeta) {
|
97 |
|
98 | let uri = '/' + filePath.substring(0, filePath.lastIndexOf('.'));
|
99 | uri = uri.replace(this.baseDir + '/', '');
|
100 |
|
101 | let lang = path.extname(uri);
|
102 |
|
103 | if (lang) {
|
104 |
|
105 | lang = lang.replace('.', '')
|
106 | uri = uri.substring(0, uri.lastIndexOf('.'));
|
107 | }
|
108 |
|
109 | if (uri.endsWith('/index')) {
|
110 | uri = uri.slice(0, -5)
|
111 | }
|
112 |
|
113 | if (postMeta.slug != undefined) {
|
114 | uri = path.dirname(uri) + postMeta.slug;
|
115 | }
|
116 |
|
117 | if (postMeta.url != undefined) {
|
118 | uri = postMeta.url
|
119 | }
|
120 |
|
121 | return [lang, uri]
|
122 |
|
123 | }
|
124 |
|
125 | _setInput(dirPath) {
|
126 | this.input = dirPath
|
127 | }
|
128 |
|
129 | setOutput(filePath) {
|
130 | this.output = filePath
|
131 | }
|
132 |
|
133 | createIndex() {
|
134 |
|
135 | console.log(`Arguments: input: ${this.input}, output: ${this.output}`)
|
136 |
|
137 | this.stream = fs.createWriteStream(this.output);
|
138 |
|
139 | this.parseContent(this.input)
|
140 |
|
141 | this.stream.write(JSON.stringify(this.indexData, null, 4));
|
142 | this.stream.end()
|
143 |
|
144 | console.info(`Saved index: ${this.output}`)
|
145 |
|
146 | }
|
147 |
|
148 | }
|
149 |
|
150 | export { HugoIndexer, CONTENT_PATH, OUTPUT_INDEX_FILE } |
\ | No newline at end of file |