eleventy-generate-posts 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +11 -2
- package/eleventy-generate-posts.js +218 -194
- package/package.json +1 -1
- package/pub.mjs +0 -5
package/changelog.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 20260320 (v0.0.8)
|
|
4
|
+
|
|
5
|
+
After I replaced the random words API URL in the previous version, I realize that I mistakenly assumed that the connection to remote URLs (the random words API and the bacon ipsum API) would always work. It wont, as the previous version proved. Anyway, that caused me to make this update which:
|
|
6
|
+
|
|
7
|
+
* Wraps both API calls in a `try/catch` block
|
|
8
|
+
* Checks fetch responses for HTTP OK (200) before continuing
|
|
9
|
+
|
|
10
|
+
In both cases, when there's a problem with `fetch` completing, the utility displays an error and exits.
|
|
11
|
+
|
|
3
12
|
## 20260320 (v0.0.7)
|
|
4
13
|
|
|
5
14
|
* Added support for timestamps (something I use in my sites instead of a simple article date).
|
|
@@ -18,7 +27,7 @@ Added `-g` parameter used to append generator content to the end of generated po
|
|
|
18
27
|
|
|
19
28
|
## 20230709 - version 0.0.4
|
|
20
29
|
|
|
21
|
-
Made number of posts the first prompt, it
|
|
30
|
+
Made number of posts the first prompt, it seems better this way.
|
|
22
31
|
|
|
23
32
|
## 20230701 - version 0.0.3
|
|
24
33
|
|
|
@@ -26,4 +35,4 @@ Replaced command line options with interactive prompts
|
|
|
26
35
|
|
|
27
36
|
## 20230516
|
|
28
37
|
|
|
29
|
-
Added support for the `-y` flag which saves generated posts to a subfolder for the current year.
|
|
38
|
+
Added support for the `-y` flag which saves generated posts to a subfolder for the current year.
|
|
@@ -1,194 +1,218 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import fs from 'fs-extra';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import boxen from 'boxen';
|
|
5
|
-
import chalk from 'chalk';
|
|
6
|
-
import prompts from 'prompts';
|
|
7
|
-
import YAML from 'yaml';
|
|
8
|
-
import logger from 'cli-logger';
|
|
9
|
-
var log = logger();
|
|
10
|
-
var HighlightType;
|
|
11
|
-
(function (HighlightType) {
|
|
12
|
-
HighlightType[HighlightType["Red"] = 0] = "Red";
|
|
13
|
-
HighlightType[HighlightType["Yellow"] = 1] = "Yellow";
|
|
14
|
-
HighlightType[HighlightType["Green"] = 2] = "Green";
|
|
15
|
-
})(HighlightType || (HighlightType = {}));
|
|
16
|
-
const APP_NAME = '11ty Generate Posts';
|
|
17
|
-
const APP_AUTHOR = 'by John M. Wargo (https://johnwargo.com)\n';
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
var
|
|
28
|
-
var
|
|
29
|
-
var
|
|
30
|
-
var
|
|
31
|
-
var
|
|
32
|
-
var
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (color == HighlightType.
|
|
56
|
-
console.log(chalk.
|
|
57
|
-
if (color == HighlightType.
|
|
58
|
-
console.log(chalk.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
console.log(
|
|
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
|
-
writeConsole(yellow, '
|
|
136
|
-
writeConsole(yellow, '
|
|
137
|
-
writeConsole(yellow, 'Year
|
|
138
|
-
writeConsole(yellow, '
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
let
|
|
159
|
-
let
|
|
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
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import boxen from 'boxen';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import prompts from 'prompts';
|
|
7
|
+
import YAML from 'yaml';
|
|
8
|
+
import logger from 'cli-logger';
|
|
9
|
+
var log = logger();
|
|
10
|
+
var HighlightType;
|
|
11
|
+
(function (HighlightType) {
|
|
12
|
+
HighlightType[HighlightType["Red"] = 0] = "Red";
|
|
13
|
+
HighlightType[HighlightType["Yellow"] = 1] = "Yellow";
|
|
14
|
+
HighlightType[HighlightType["Green"] = 2] = "Green";
|
|
15
|
+
})(HighlightType || (HighlightType = {}));
|
|
16
|
+
const APP_NAME = '11ty Generate Posts';
|
|
17
|
+
const APP_AUTHOR = 'by John M. Wargo (https://johnwargo.com)\n';
|
|
18
|
+
const baconIpsumErrorStr = 'Unable to retrieve bacon ipsum text.';
|
|
19
|
+
const ELEVENTY_FILES = ['.eleventy.js', 'eleventy.config.js'];
|
|
20
|
+
const GENERATOR_CONTENT = '***\n\nPost content generated by [Eleventy Generate Posts](https://www.npmjs.com/package/eleventy-generate-posts)';
|
|
21
|
+
const randomWordsErrorStr = 'Unable to retrieve random words for title.';
|
|
22
|
+
const NEW_LINE = "\n";
|
|
23
|
+
const spaces40 = '-'.repeat(40);
|
|
24
|
+
const red = HighlightType.Red;
|
|
25
|
+
const yellow = HighlightType.Yellow;
|
|
26
|
+
const green = HighlightType.Green;
|
|
27
|
+
var counterLen;
|
|
28
|
+
var counterStr;
|
|
29
|
+
var numPosts;
|
|
30
|
+
var startYear;
|
|
31
|
+
var tag;
|
|
32
|
+
var targetFolder;
|
|
33
|
+
var timestampMode;
|
|
34
|
+
var yearMode;
|
|
35
|
+
const onCancelPrompt = () => {
|
|
36
|
+
log.info('\nOperation cancelled by user!');
|
|
37
|
+
process.exit(0);
|
|
38
|
+
};
|
|
39
|
+
function zeroPad(tmpVal, numChars = 2) {
|
|
40
|
+
return tmpVal.toString().padStart(numChars, '0');
|
|
41
|
+
}
|
|
42
|
+
function directoryExists(filePath) {
|
|
43
|
+
if (fs.existsSync(filePath)) {
|
|
44
|
+
try {
|
|
45
|
+
return fs.lstatSync(filePath).isDirectory();
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
log.error(`checkDirectory error: ${err}`);
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
function writeConsole(color, highlightText, msg) {
|
|
55
|
+
if (color == HighlightType.Red)
|
|
56
|
+
console.log(NEW_LINE + chalk.red(`${highlightText}: `) + msg + NEW_LINE);
|
|
57
|
+
if (color == HighlightType.Yellow)
|
|
58
|
+
console.log(chalk.yellow(`${highlightText}: `) + msg);
|
|
59
|
+
if (color == HighlightType.Green)
|
|
60
|
+
console.log(chalk.green(`${highlightText}: `) + msg);
|
|
61
|
+
}
|
|
62
|
+
function getRandomInt(max) {
|
|
63
|
+
return Math.floor(Math.random() * max) + 1;
|
|
64
|
+
}
|
|
65
|
+
function checkEleventyProject() {
|
|
66
|
+
log.debug('Validating project folder');
|
|
67
|
+
let result = false;
|
|
68
|
+
ELEVENTY_FILES.forEach((file) => {
|
|
69
|
+
let tmpFile = path.join(process.cwd(), file);
|
|
70
|
+
if (fs.existsSync(tmpFile)) {
|
|
71
|
+
result = true;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
if (!checkEleventyProject()) {
|
|
77
|
+
log.error('Current folder is not an Eleventy project folder.');
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
console.log(boxen(APP_NAME, { padding: 1 }));
|
|
81
|
+
console.log(APP_AUTHOR);
|
|
82
|
+
console.log('Add -d to command to enable debug mode, -g to append generator info to post files.\n');
|
|
83
|
+
const debugMode = process.argv.includes('-d');
|
|
84
|
+
if (debugMode) {
|
|
85
|
+
writeConsole(green, 'Debug mode', 'enabled\n');
|
|
86
|
+
}
|
|
87
|
+
log.level(debugMode ? log.DEBUG : log.INFO);
|
|
88
|
+
const generatorInfo = process.argv.includes('-g');
|
|
89
|
+
if (generatorInfo) {
|
|
90
|
+
writeConsole(green, 'Append generator info', 'enabled\n');
|
|
91
|
+
}
|
|
92
|
+
const questions = [
|
|
93
|
+
{
|
|
94
|
+
type: 'number',
|
|
95
|
+
name: 'numPosts',
|
|
96
|
+
initial: 10,
|
|
97
|
+
message: 'Number of posts to generate (1-100)?'
|
|
98
|
+
}, {
|
|
99
|
+
type: 'text',
|
|
100
|
+
name: 'targetFolder',
|
|
101
|
+
initial: 'src/posts',
|
|
102
|
+
message: 'Target folder for generated posts?'
|
|
103
|
+
}, {
|
|
104
|
+
type: 'text',
|
|
105
|
+
name: 'tag',
|
|
106
|
+
message: 'Post tag?',
|
|
107
|
+
initial: 'post'
|
|
108
|
+
}, {
|
|
109
|
+
type: 'number',
|
|
110
|
+
name: 'startYear',
|
|
111
|
+
initial: new Date().getFullYear(),
|
|
112
|
+
message: 'Start year for generated posts?'
|
|
113
|
+
}, {
|
|
114
|
+
type: 'confirm',
|
|
115
|
+
name: 'yearMode',
|
|
116
|
+
initial: true,
|
|
117
|
+
message: 'Use year folder for posts?'
|
|
118
|
+
}, {
|
|
119
|
+
type: 'confirm',
|
|
120
|
+
name: 'timestampMode',
|
|
121
|
+
initial: true,
|
|
122
|
+
message: 'Include timestamp in post metadata?'
|
|
123
|
+
}
|
|
124
|
+
];
|
|
125
|
+
const response = await prompts(questions, { onCancel: onCancelPrompt });
|
|
126
|
+
targetFolder = response.targetFolder;
|
|
127
|
+
numPosts = response.numPosts;
|
|
128
|
+
counterLen = numPosts.toString().length;
|
|
129
|
+
startYear = response.startYear;
|
|
130
|
+
tag = response.tag;
|
|
131
|
+
yearMode = response.yearMode;
|
|
132
|
+
timestampMode = response.timestampMode;
|
|
133
|
+
console.log('\nSettings Summary:');
|
|
134
|
+
console.log(spaces40);
|
|
135
|
+
writeConsole(yellow, 'Number of posts', numPosts.toString());
|
|
136
|
+
writeConsole(yellow, 'Target Folder', targetFolder);
|
|
137
|
+
writeConsole(yellow, 'Start Year', startYear.toString());
|
|
138
|
+
writeConsole(yellow, 'Tag', tag);
|
|
139
|
+
writeConsole(yellow, 'Year mode', yearMode ? 'enabled' : 'disabled');
|
|
140
|
+
writeConsole(yellow, 'Timestamp mode', timestampMode ? 'enabled' : 'disabled');
|
|
141
|
+
if (!(numPosts > 0 && numPosts < 101)) {
|
|
142
|
+
writeConsole(red, 'Error', 'Number of posts must be between 1 and 100');
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
var outputFilePath = path.join(process.cwd(), targetFolder);
|
|
146
|
+
writeConsole(yellow, 'Output folder', outputFilePath);
|
|
147
|
+
if (!directoryExists(outputFilePath)) {
|
|
148
|
+
writeConsole(red, 'Error', 'Output folder does not exist');
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
console.log('\nGenerating posts...');
|
|
152
|
+
console.log(spaces40);
|
|
153
|
+
var currentDate = new Date();
|
|
154
|
+
if (startYear)
|
|
155
|
+
currentDate.setFullYear(startYear);
|
|
156
|
+
numPosts++;
|
|
157
|
+
for (let i = 1; i < numPosts; i++) {
|
|
158
|
+
let wordCount = getRandomInt(4) + 3;
|
|
159
|
+
let letTitleRes;
|
|
160
|
+
log.debug('\nGetting random words (this may take a few seconds)');
|
|
161
|
+
try {
|
|
162
|
+
letTitleRes = await fetch(`https://random-word-api.herokuapp.com/word?number=${wordCount}`);
|
|
163
|
+
if (!letTitleRes.ok) {
|
|
164
|
+
writeConsole(red, 'Error', `${randomWordsErrorStr}\nStatus: ${letTitleRes.status}`);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
writeConsole(red, 'Error', `${randomWordsErrorStr}\nFetch error: ${error.message}`);
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
172
|
+
let titleWords = await letTitleRes.json();
|
|
173
|
+
titleWords = titleWords.map((a) => a.charAt(0).toUpperCase() + a.substr(1));
|
|
174
|
+
let postTitle = titleWords.join(' ');
|
|
175
|
+
log.debug(`Post title: ${postTitle}`);
|
|
176
|
+
currentDate.setDate(currentDate.getDate() - getRandomInt(20));
|
|
177
|
+
let postDate = `${currentDate.getFullYear()}-${zeroPad(currentDate.getMonth() + 1)}-${zeroPad(currentDate.getDate())}`;
|
|
178
|
+
log.debug(`Post date: ${postDate}`);
|
|
179
|
+
var postFm = {
|
|
180
|
+
title: postTitle,
|
|
181
|
+
date: postDate,
|
|
182
|
+
tags: tag
|
|
183
|
+
};
|
|
184
|
+
if (timestampMode) {
|
|
185
|
+
postFm.timestamp = currentDate.toISOString();
|
|
186
|
+
}
|
|
187
|
+
let postContent;
|
|
188
|
+
log.debug('Getting bacon ipsum text (this may take a few seconds)...');
|
|
189
|
+
try {
|
|
190
|
+
let response = await fetch(`https://baconipsum.com/api/?type=all-meat¶s=${getRandomInt(10)}&start-with-lorem=1`);
|
|
191
|
+
if (!response.ok) {
|
|
192
|
+
writeConsole(red, 'Error', `${baconIpsumErrorStr}\nStatus: ${response.status}`);
|
|
193
|
+
process.exit(1);
|
|
194
|
+
}
|
|
195
|
+
postContent = await response.json();
|
|
196
|
+
log.debug(`Post content: ${postContent}`);
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
writeConsole(red, 'Error', `${baconIpsumErrorStr}\nFetch error: ${error.message}`);
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
if (generatorInfo)
|
|
203
|
+
postContent.push(GENERATOR_CONTENT);
|
|
204
|
+
var thePost = '---\n';
|
|
205
|
+
thePost += YAML.stringify(postFm, { logLevel: 'silent' });
|
|
206
|
+
thePost += '---\n\n';
|
|
207
|
+
thePost += postContent.join('\n\n');
|
|
208
|
+
var outputFilePath = path.join(process.cwd(), targetFolder);
|
|
209
|
+
if (yearMode) {
|
|
210
|
+
outputFilePath = path.join(outputFilePath, currentDate.getFullYear().toString());
|
|
211
|
+
if (!fs.existsSync(outputFilePath))
|
|
212
|
+
fs.mkdirSync(outputFilePath, { recursive: true });
|
|
213
|
+
}
|
|
214
|
+
var outputFilePath = path.join(outputFilePath, postTitle.toLowerCase().replaceAll(' ', '-') + '.md');
|
|
215
|
+
counterStr = i.toString().padStart(counterLen);
|
|
216
|
+
writeConsole(green, `[${counterStr}] Writing`, outputFilePath);
|
|
217
|
+
fs.writeFileSync(outputFilePath, thePost, 'utf8');
|
|
218
|
+
}
|
package/package.json
CHANGED