eleventy-generate-posts 0.0.1 → 0.0.3

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 CHANGED
@@ -1 +1,9 @@
1
1
  # Changelog
2
+
3
+ ## 20230701
4
+
5
+ Replaced command line options with interactive prompts
6
+
7
+ ## 20230516
8
+
9
+ Added support for the `-y` flag which saves generated posts to a subfolder for the current year.
@@ -1,135 +1,171 @@
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 { Command } from 'commander';
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)';
18
- const ELEVENTY_FILES = ['.eleventy.js', 'eleventy.config.js'];
19
- const NEW_LINE = "\n";
20
- const red = HighlightType.Red;
21
- const yellow = HighlightType.Yellow;
22
- const green = HighlightType.Green;
23
- function zeroPad(tmpVal, numChars = 2) {
24
- return tmpVal.toString().padStart(numChars, '0');
25
- }
26
- function directoryExists(filePath) {
27
- if (fs.existsSync(filePath)) {
28
- try {
29
- return fs.lstatSync(filePath).isDirectory();
30
- }
31
- catch (err) {
32
- log.error(`checkDirectory error: ${err}`);
33
- return false;
34
- }
35
- }
36
- return false;
37
- }
38
- function writeConsole(color, highlightText, msg) {
39
- if (color == HighlightType.Red)
40
- console.log(NEW_LINE + chalk.red(`${highlightText}: `) + msg + NEW_LINE);
41
- if (color == HighlightType.Yellow)
42
- console.log(chalk.yellow(`${highlightText}: `) + msg);
43
- if (color == HighlightType.Green)
44
- console.log(chalk.green(`${highlightText}: `) + msg);
45
- }
46
- function getRandomInt(max) {
47
- return Math.floor(Math.random() * max) + 1;
48
- }
49
- function checkEleventyProject() {
50
- log.debug('Validating project folder');
51
- let result = false;
52
- ELEVENTY_FILES.forEach((file) => {
53
- let tmpFile = path.join(process.cwd(), file);
54
- if (fs.existsSync(tmpFile)) {
55
- result = true;
56
- }
57
- });
58
- return result;
59
- }
60
- if (!checkEleventyProject()) {
61
- log.error('Current folder is not an Eleventy project folder.');
62
- process.exit(1);
63
- }
64
- const program = new Command();
65
- program
66
- .name('11ty-gp')
67
- .description('Generate a set of posts for an Eleventy project')
68
- .argument('<numPosts>', 'Number of posts to generate')
69
- .argument('<targetFolder>', 'Target folder for generated posts files')
70
- .argument('<tag>', 'Tag to apply to all generated posts')
71
- .argument('[startYear]', 'Start year for generated posts')
72
- .option('-d, --debug', 'Debug mode')
73
- .action(async (numPosts, targetFolder, tag, startYear) => {
74
- console.log(boxen(APP_NAME, { padding: 1 }));
75
- console.log(APP_AUTHOR);
76
- const options = program.opts();
77
- const debugMode = options.debug;
78
- if (debugMode) {
79
- console.log('Debug mode enabled.');
80
- }
81
- log.level(debugMode ? log.DEBUG : log.INFO);
82
- writeConsole(yellow, 'Number of posts', numPosts);
83
- writeConsole(yellow, 'Target Folder', targetFolder);
84
- if (startYear)
85
- writeConsole(yellow, 'Start Year', startYear);
86
- writeConsole(yellow, 'Tag', tag);
87
- if (!Number.isInteger(parseInt(numPosts))) {
88
- writeConsole(red, 'Error', 'Number of posts must be an integer');
89
- process.exit(1);
90
- }
91
- if (!(numPosts > 0 && numPosts < 101)) {
92
- writeConsole(red, 'Error', 'Number of posts must be between 1 and 100');
93
- process.exit(1);
94
- }
95
- var outputFilePath = path.join(process.cwd(), targetFolder);
96
- writeConsole(yellow, 'Output folder', outputFilePath);
97
- if (!directoryExists(outputFilePath)) {
98
- writeConsole(red, 'Error', 'Target folder does not exist');
99
- process.exit(1);
100
- }
101
- var currentDate = new Date();
102
- if (startYear)
103
- currentDate.setFullYear(startYear);
104
- numPosts++;
105
- for (let i = 1; i < numPosts; i++) {
106
- log.debug('\nGetting random words (this may take a few seconds)');
107
- let wordCount = getRandomInt(4) + 3;
108
- let letTitleRes = await fetch(`https://random-word-api.vercel.app/api?words=${wordCount}`);
109
- let titleWords = await letTitleRes.json();
110
- titleWords = titleWords.map((a) => a.charAt(0).toUpperCase() + a.substr(1));
111
- let postTitle = titleWords.join(' ');
112
- log.debug(`Post title: ${postTitle}`);
113
- currentDate.setDate(currentDate.getDate() - getRandomInt(20));
114
- let postDate = `${currentDate.getFullYear()}-${zeroPad(currentDate.getMonth() + 1)}-${zeroPad(currentDate.getDate())}`;
115
- log.debug(`Post date: ${postDate}`);
116
- var postFm = {
117
- title: postTitle,
118
- date: postDate,
119
- tags: tag
120
- };
121
- log.debug('Getting bacon ipsum text (this may take a few seconds)...');
122
- let response = await fetch(`https://baconipsum.com/api/?type=all-meat&paras=${getRandomInt(10)}&start-with-lorem=1`);
123
- let postContent = await response.json();
124
- log.debug(`Post content: ${postContent}`);
125
- var thePost = '---\n';
126
- thePost += YAML.stringify(postFm, { logLevel: 'silent' });
127
- thePost += '---\n\n';
128
- thePost += postContent.join('\n\n');
129
- var outputFilePath = path.join(targetFolder, postTitle.toLowerCase().replaceAll(' ', '-') + '.md');
130
- writeConsole(green, 'Writing', outputFilePath);
131
- fs.writeFileSync(outputFilePath, thePost, 'utf8');
132
- }
133
- });
134
- console.log();
135
- program.parse();
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 ELEVENTY_FILES = ['.eleventy.js', 'eleventy.config.js'];
19
+ const NEW_LINE = "\n";
20
+ const spaces40 = '-'.repeat(40);
21
+ const red = HighlightType.Red;
22
+ const yellow = HighlightType.Yellow;
23
+ const green = HighlightType.Green;
24
+ var numPosts;
25
+ var startYear;
26
+ var tag;
27
+ var targetFolder;
28
+ var yearMode;
29
+ function zeroPad(tmpVal, numChars = 2) {
30
+ return tmpVal.toString().padStart(numChars, '0');
31
+ }
32
+ function directoryExists(filePath) {
33
+ if (fs.existsSync(filePath)) {
34
+ try {
35
+ return fs.lstatSync(filePath).isDirectory();
36
+ }
37
+ catch (err) {
38
+ log.error(`checkDirectory error: ${err}`);
39
+ return false;
40
+ }
41
+ }
42
+ return false;
43
+ }
44
+ function writeConsole(color, highlightText, msg) {
45
+ if (color == HighlightType.Red)
46
+ console.log(NEW_LINE + chalk.red(`${highlightText}: `) + msg + NEW_LINE);
47
+ if (color == HighlightType.Yellow)
48
+ console.log(chalk.yellow(`${highlightText}: `) + msg);
49
+ if (color == HighlightType.Green)
50
+ console.log(chalk.green(`${highlightText}: `) + msg);
51
+ }
52
+ function getRandomInt(max) {
53
+ return Math.floor(Math.random() * max) + 1;
54
+ }
55
+ function checkEleventyProject() {
56
+ log.debug('Validating project folder');
57
+ let result = false;
58
+ ELEVENTY_FILES.forEach((file) => {
59
+ let tmpFile = path.join(process.cwd(), file);
60
+ if (fs.existsSync(tmpFile)) {
61
+ result = true;
62
+ }
63
+ });
64
+ return result;
65
+ }
66
+ if (!checkEleventyProject()) {
67
+ log.error('Current folder is not an Eleventy project folder.');
68
+ process.exit(1);
69
+ }
70
+ console.log(boxen(APP_NAME, { padding: 1 }));
71
+ console.log(APP_AUTHOR);
72
+ const debugMode = process.argv.includes('-d');
73
+ if (debugMode) {
74
+ writeConsole(green, 'Debug mode', 'enabled\n');
75
+ }
76
+ log.level(debugMode ? log.DEBUG : log.INFO);
77
+ const questions = [
78
+ {
79
+ type: 'text',
80
+ name: 'targetFolder',
81
+ initial: 'src/posts',
82
+ message: 'Target folder for generated posts?'
83
+ },
84
+ {
85
+ type: 'number',
86
+ name: 'numPosts',
87
+ initial: 10,
88
+ message: 'Number of posts to generate?'
89
+ },
90
+ {
91
+ type: 'text',
92
+ name: 'tag',
93
+ message: 'Post tag?',
94
+ initial: 'post'
95
+ },
96
+ {
97
+ type: 'number',
98
+ name: 'startYear',
99
+ initial: new Date().getFullYear(),
100
+ message: 'Start year for generated posts?'
101
+ },
102
+ {
103
+ type: 'confirm',
104
+ name: 'yearMode',
105
+ initial: true,
106
+ message: 'Use year folder for posts?'
107
+ },
108
+ ];
109
+ const response = await prompts(questions);
110
+ targetFolder = response.targetFolder;
111
+ numPosts = response.numPosts;
112
+ startYear = response.startYear;
113
+ tag = response.tag;
114
+ yearMode = response.yearMode;
115
+ console.log('\nSettings Summary:');
116
+ console.log(spaces40);
117
+ writeConsole(yellow, 'Number of posts', numPosts.toString());
118
+ writeConsole(yellow, 'Target Folder', targetFolder);
119
+ writeConsole(yellow, 'Start Year', startYear.toString());
120
+ writeConsole(yellow, 'Tag', tag);
121
+ writeConsole(yellow, 'Year mode', yearMode ? 'enabled' : 'disabled');
122
+ if (!(numPosts > 0 && numPosts < 101)) {
123
+ writeConsole(red, 'Error', 'Number of posts must be between 1 and 100');
124
+ process.exit(1);
125
+ }
126
+ var outputFilePath = path.join(process.cwd(), targetFolder);
127
+ writeConsole(yellow, 'Output folder', outputFilePath);
128
+ if (!directoryExists(outputFilePath)) {
129
+ writeConsole(red, 'Error', 'Output folder does not exist');
130
+ process.exit(1);
131
+ }
132
+ console.log('\nGenerating posts...');
133
+ console.log(spaces40);
134
+ var currentDate = new Date();
135
+ if (startYear)
136
+ currentDate.setFullYear(startYear);
137
+ numPosts++;
138
+ for (let i = 1; i < numPosts; i++) {
139
+ log.debug('\nGetting random words (this may take a few seconds)');
140
+ let wordCount = getRandomInt(4) + 3;
141
+ let letTitleRes = await fetch(`https://random-word-api.vercel.app/api?words=${wordCount}`);
142
+ let titleWords = await letTitleRes.json();
143
+ titleWords = titleWords.map((a) => a.charAt(0).toUpperCase() + a.substr(1));
144
+ let postTitle = titleWords.join(' ');
145
+ log.debug(`Post title: ${postTitle}`);
146
+ currentDate.setDate(currentDate.getDate() - getRandomInt(20));
147
+ let postDate = `${currentDate.getFullYear()}-${zeroPad(currentDate.getMonth() + 1)}-${zeroPad(currentDate.getDate())}`;
148
+ log.debug(`Post date: ${postDate}`);
149
+ var postFm = {
150
+ title: postTitle,
151
+ date: postDate,
152
+ tags: tag
153
+ };
154
+ log.debug('Getting bacon ipsum text (this may take a few seconds)...');
155
+ let response = await fetch(`https://baconipsum.com/api/?type=all-meat&paras=${getRandomInt(10)}&start-with-lorem=1`);
156
+ let postContent = await response.json();
157
+ log.debug(`Post content: ${postContent}`);
158
+ var thePost = '---\n';
159
+ thePost += YAML.stringify(postFm, { logLevel: 'silent' });
160
+ thePost += '---\n\n';
161
+ thePost += postContent.join('\n\n');
162
+ var outputFilePath = path.join(process.cwd(), targetFolder);
163
+ if (yearMode) {
164
+ outputFilePath = path.join(outputFilePath, currentDate.getFullYear().toString());
165
+ if (!fs.existsSync(outputFilePath))
166
+ fs.mkdirSync(outputFilePath, { recursive: true });
167
+ }
168
+ var outputFilePath = path.join(outputFilePath, postTitle.toLowerCase().replaceAll(' ', '-') + '.md');
169
+ writeConsole(green, 'Writing', outputFilePath);
170
+ fs.writeFileSync(outputFilePath, thePost, 'utf8');
171
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eleventy-generate-posts",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Generates batches of Eleventy posts",
5
5
  "author": "John M. Wargo",
6
6
  "license": "MIT",
@@ -19,7 +19,7 @@
19
19
  ],
20
20
  "scripts": {
21
21
  "test": "echo \"Error: no test specified\" && exit 1",
22
- "start": "tsc && node eleventy-generate-posts.js 5 posts post"
22
+ "start": "tsc && node eleventy-generate-posts.js"
23
23
  },
24
24
  "dependencies": {
25
25
  "boxen": "^7.0.2",
@@ -27,6 +27,7 @@
27
27
  "cli-logger": "^0.5.40",
28
28
  "commander": "^10.0.1",
29
29
  "fs-extra": "^11.1.1",
30
+ "prompts": "^2.4.2",
30
31
  "yaml": "^2.2.2"
31
32
  },
32
33
  "devDependencies": {
package/pub.mjs ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env zx
2
+
3
+ await $`npm version patch`;
4
+ await $`git push`;
5
+ await $`npm publish`;
package/readme.md CHANGED
@@ -4,7 +4,9 @@ A simple command-line utility that creates a batch of new posts for an [Eleventy
4
4
 
5
5
  When you're testing out some aspect of an Eleventy site or doing a demo, you often need to populate the site with a set of posts to flesh out the site. Copying a single post or set of posts repeatedly into the site works, but an automated solution is better. This is that solution.
6
6
 
7
- The utility generates batches of Eleventy site posts, populating the post title with a random quantity of random words and populating the post body with a random number of paragraphs of [Bacon Ipsum](https://baconipsum.com/) text.
7
+ The utility generates batches of Eleventy site posts, populating the post title with a random quantity of random words using the [Rando Free Random Word Generator API](https://random-word-api.vercel.app/) and populating the post body with a random number of paragraphs of [Bacon Ipsum](https://baconipsum.com/) text.
8
+
9
+ The original version of this utility used command-line arguments, but this version replaces them with prompts.
8
10
 
9
11
  ## Installation
10
12
 
@@ -17,41 +19,67 @@ npm install -g eleventy-generate-posts
17
19
  This adds a `11ty-gp` command to the system.
18
20
 
19
21
  You don't have to install the package to use it; simply open a terminal window or command prompt to your Eleventy project folder and execute the command using `npx eleventy-generate-posts` and the command-line options described in the following section.
22
+
20
23
  ## Usage
21
24
 
22
- Execute the command using the following command-line parameters:
25
+ Execute the command using the following command:
23
26
 
24
27
  ```shell
25
- 11ty-gp [options] <numPosts> <targetFolder> <tag> [startYear]
28
+ 11ty-gp
26
29
  ```
27
30
 
28
- Supported command-line options are:
29
-
30
- * `numPosts` (required) An integer value representing the number of posts generated.
31
- * `targetFolder` (required) Relative path pointing to the Eleventy project's posts folder; use `.` for the current folder.
32
- * `tag` (required) The post tag applied to the generated posts
33
- * `startYear` (optional) The starting year used for post date in the generated posts. The command uses the current date or the current date with the specified year (when provided) to for the post date for the first generated post. For subsequent post dates, the command randomly decrements the day.
34
-
35
- As an example, to generate 10 posts in the project's `posts` folder using a `tags` value of `post`, use:
36
-
37
- ```shell
38
- 11ty-gp 10 posts post
31
+ The module will prompt you for all the required options:
32
+
33
+ ```text
34
+ ┌─────────────────────────┐
35
+ │ │
36
+ │ 11ty Generate Posts │
37
+ │ │
38
+ └─────────────────────────┘
39
+ by John M. Wargo (https://johnwargo.com)
40
+
41
+ Target folder for generated posts? ... posts
42
+ √ Number of posts to generate? ... 10
43
+ √ Post tag? ... post
44
+ √ Start year for generated posts? ... 2023
45
+ √ Use year folder for posts? ... yes
46
+
47
+ Settings Summary:
48
+ ----------------------------------------
49
+ Number of posts: 10
50
+ Target Folder: posts
51
+ Start Year: 2023
52
+ Tag: post
53
+ Year mode: enabled
54
+ Output folder: D:\dev\node\11ty-generate-posts\posts
55
+
56
+ Generating posts...
57
+ ----------------------------------------
58
+ Writing: D:\dev\node\11ty-generate-posts\posts\2023\navigator-washbasin-dramatize-landside-sensation.md
59
+ Writing: D:\dev\node\11ty-generate-posts\posts\2023\amusing-peculiar-surgical-borough-impotency-surround-tubular.md
60
+ Writing: D:\dev\node\11ty-generate-posts\posts\2023\maturely-convene-squishier-verify.md
61
+ Writing: D:\dev\node\11ty-generate-posts\posts\2023\matchless-overlaid-expend-oxidation-tribesman.md
62
+ Writing: D:\dev\node\11ty-generate-posts\posts\2023\basis-brunt-swaddling-ladylike-support-epidemic-graded.md
63
+ Writing: D:\dev\node\11ty-generate-posts\posts\2023\certify-unsheathe-undress-obstacle-tweak-tray-ridden.md
64
+ Writing: D:\dev\node\11ty-generate-posts\posts\2023\matching-enjoying-contact-atlas.md
65
+ Writing: D:\dev\node\11ty-generate-posts\posts\2023\android-gecko-penalize-possum.md
66
+ Writing: D:\dev\node\11ty-generate-posts\posts\2023\contempt-acquire-filtrate-defense-ergonomic-acts.md
67
+ Writing: D:\dev\node\11ty-generate-posts\posts\2023\splinter-ecology-computer-nearby-shorts-feminize.md
39
68
  ```
40
69
 
41
- This command sets the post date for the current post to the current date, then works backwards (random days) for each subsequent generated post.
42
-
43
- To generate 20 posts starting in 2021, use the following:
70
+ Configuration options are:
44
71
 
45
- ```shell
46
- 11ty-gp 20 posts post 2021
47
- ```
72
+ * **Posts Folder:** Relative path pointing to the Eleventy project's posts folder; use `.` for the current folder.
73
+ * **Number of Posts:** An integer value between 1 and 100 representing the number of posts generated.
74
+ * **Post Tag:** The front matter `tag` property applied to the generated posts
75
+ * **Start Year:** The starting year used for post date in the generated posts. The command uses the current date or the current date with the specified year (when provided) to for the post date for the first generated post. For subsequent post dates, the command randomly decrements the day.
76
+ * **Use Year Folder:** specifies whether the module writes generated posts to the Posts folder (`N`) or into a separate folder for each year (`Y`).
48
77
 
49
- This command sets the post date for the current post to the current month/day plus the provided year, then works backwards (random days) for each subsequent generated post. So, if you execute the command on May 10, 2023, the command sets the post date for the first post to May 10, 2021 and works (randomly) backwards from there.
78
+ Obviously if you generate enough posts to push into the previous year, the posts will save into a folder for the previous year.
50
79
 
51
- Supported command-line options (flags) are:
80
+ To enable debug mode, pass a `-d` flag on the command-line; in this mode, the module writes additional information to the console as it executes.
52
81
 
53
- * `-d` or `--debug`: Enables debug mode which generates additional content to the terminal during execution
54
- * `h` or `--help`: Displays usage information in the terminal
82
+ ## Example Post
55
83
 
56
84
  A sample generated post looks like the following:
57
85
 
@@ -73,7 +101,7 @@ pastrami burgdoggen meatball. Frankfurter kevin pig, hamburger andouille tail m
73
101
  ribs prosciutto. Meatloaf chislic flank tri-tip swine filet mignon brisket sirloin turkey porchetta.
74
102
  ```
75
103
 
76
- ### Getting Help Or Making Changes
104
+ ## Getting Help Or Making Changes
77
105
 
78
106
  Use [GitHub Issues](https://github.com/johnwargo/eleventy-generate-posts/issues) to get help with this module.
79
107