forked from lyu4321/jellybean
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
225 lines (214 loc) · 7.28 KB
/
index.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
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
import fs, { mkdirSync } from 'fs';
import path from 'path';
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const pkg = require('./package.json');
/**
* Checks to see if an output directory exists and if it does, remove it, then create the directory
* @param {string} directory => path to the directory
*/
const createDirectory = (directory) => {
if (fs.existsSync(directory)) {
fs.rmdirSync(directory, { recursive: true });
}
mkdirSync(directory);
}
/**
* Reads the layout.html file contents
* @return {string} => returns the file contents as a string
*/
const getLayout = () => {
return fs.readFileSync('layout.html', 'utf8');
}
/**
* Creates a layout, replacing placeholders with user input
* @param {string} layout => layout string
* @param {string} stylesheet => replaces {stylesheet} placeholder in layout
* @param {string} nav => replaces {nav} placeholder in layout
* @param {string} title => replaces {title} placeholder in layout
* @param {string} body => replaces {body} placeholder in layout
* @return {string} => returns the layout as a string
*/
const getUpdatedLayout = (layout, stylesheet, title, nav, body) => {
return layout
.replace(/{stylesheet}/g, stylesheet)
.replace(/{title}/g, title)
.replace(/{nav}/g, nav)
.replace(/{body}/g, body)
}
/**
* Creates the nav of a page based on a file or files in a directory
* @param {array} files => a single file path or array of file paths
* @return {string} => returns a string of the html used to create the navigation
*/
const getNav = (files) => {
let index = `<li><a href='./index.html'>Home</a></li>`;
if (!Array.isArray(files)) {
let filename = path.parse(path.basename(files)).name;
return `<div><ul>${index}<li><a href='./${filename}.html'>${filename}</a></li></ul></div>`;
} else {
let links = files.map(file => {
let filename = path.parse(path.basename(file)).name;
return `<li><a href='./${filename}.html'>${filename}</a></li>`;
})
.join(' ');
return `<div><ul>${index}${links}</ul></div>`;
}
}
/**
* Creates the title and body of a page from the contents of a .txt file
* @param {string} file => the file text
* @return {string} => returns an object containing the string for the title and string for the body
*/
const getHtml = (file) => {
let html = {
title: '',
body: ''
}
let tempTitle = file.match(/^.+(\r?\n\r?\n\r?\n)/);
if (tempTitle) {
html.title = tempTitle[0].trim();
}
html.body = file
.split(/\r?\n\r?\n/)
.map(para => {
if (para == html.title) {
`<h1>${para.replace(/\r?\n/, ' ')}</h1>\n`
} else {
return `<p>${para.replace(/\r?\n/, ' ')}</p>\n`;
}
})
.join('');
return html;
}
/**
* Reads a single file and outputs the contents to a .html file in the output directory
* @param {string} file => path to file
* @param {string} directory => path to output directory
* @param {string} stylesheet => path/URL to stylesheet
* @param {string} files => array of all .txt files in a directory
*/
const readFile = (file, directory, stylesheet, files) => {
fs.readFile(file, 'utf8', (err, f) => {
if (err) {
console.log(err);
}
const nav = getNav(files || file);
const html = getHtml(f);
const filename = path.parse(path.basename(file)).name;
let layout = getLayout();
let updatedLayout = getUpdatedLayout(layout, stylesheet, html.title, nav, html.body);
fs.writeFile(`${directory}/${filename}.html`, updatedLayout, 'utf8', (err) => {
if (err) {
console.log(err);
}
})
if (stylesheet == 'style.css') {
let style = fs.readFileSync(stylesheet, 'utf8');
fs.writeFile(`${directory}/${stylesheet}`, style, 'utf8', (err) => {
if (err) {
console.log(err);
}
})
}
})
}
/**
* Creates an index.html page for the generated site
* @param {string} output => path to output directory
* @param {string} stylesheet => path/url to stylesheet
* @param {array} files => array of all .txt files in a directory
*/
const writeIndexPage = (output, stylesheet, files) => {
let layout = getLayout();
let nav = getNav(files);
let updatedLayout = getUpdatedLayout(layout, stylesheet, 'Home', nav, '');
fs.writeFile(`${output}/index.html`, updatedLayout, 'utf8', (err) => {
if (err) {
console.log(err);
}
})
}
/**
* Checks the user input
* @param {string} input => path to a file or directory
* @param {string} output => path to an output directory
* @param {string} stylesheet => stylesheet url
* @return {boolean} => returns true if the user input is valid (valid input and output directory)
*/
const getUserInput = (input, output, stylesheet) => {
let filesArray = [];
// Setting the output directory
if (output) {
if (!fs.existsSync(output)) {
return false;
}
} else {
output = 'dist';
}
// Setting the stylesheet
if (!stylesheet) {
stylesheet = 'style.css';
}
// Setting the input
if (!input || !fs.existsSync(input)) {
return false;
} else {
if (fs.statSync(input).isFile() && path.extname(input) == '.txt') {
createDirectory(output);
writeIndexPage(output, stylesheet, input);
readFile(input, output, stylesheet);
} else if (fs.statSync(input).isDirectory()) {
fs.readdir(input, (err, files) => {
if (err) {
console.log(err);
}
createDirectory(output);
writeIndexPage(output, stylesheet, filesArray);
filesArray = files.filter(f => path.extname(f) == '.txt');
filesArray.forEach(file => {
if (fs.existsSync(`${input}/${file}`)) {
readFile(`${input}/${file}`, output, stylesheet, filesArray);
}
})
});
} else {
return false;
}
}
return true;
}
/**
* Gets the user input from the command line and checks the input, printing an error message if the input argument is invalid
*/
const main = () => {
const argv = yargs(hideBin(process.argv))
.help('h')
.alias('h', 'help')
.version(pkg.name + ' ' + pkg.version)
.alias('v', 'version')
.options('input', {
alias: 'i',
demandOption: true,
describe: 'Path to a .txt file or folder with files',
type: 'array'
})
.option('output', {
alias: 'o',
describe: 'Path to an output directory',
type: 'string'
})
.option('stylesheet', {
alias: 's',
describe: 'Stylesheet URL',
type: 'string'
})
.argv;
let check = getUserInput(argv.input.join(' '), argv.output, argv.stylesheet);
if (!check) {
console.log('Invalid argument entered. Please see --help for options.');
}
}
main();