@chriswiegman/hugo-tools 0.2.0 → 0.2.1

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
@@ -5,6 +5,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
6
6
  and is generated by [Changie](https://github.com/miniscruff/changie).
7
7
 
8
+ ## 0.2.1 - 2026-07-04
9
+
10
+ ### Chores
11
+
12
+ * Add Eslint file formatting for easier development
13
+ * Correct all linting issues with new formatter.
14
+
8
15
  ## 0.2.0 - 2026-05-09
9
16
 
10
17
  ### Features
package/README.md CHANGED
@@ -2,12 +2,16 @@
2
2
 
3
3
  A collection of CLI tools for Hugo bloggers. Run them directly from the root of your Hugo site via `npx` or install globally.
4
4
 
5
+ > **Never invoke these with `node path/to/script.js`.** Every command below is registered as a proper CLI via the `bin` field in `package.json`, so once installed you run it by name (`draft`, `publish`, ...) — see [Installation](#installation) for the three ways to do that.
6
+
5
7
  ## Requirements
6
8
 
7
9
  - Node.js 18 or later
8
10
 
9
11
  ## Installation
10
12
 
13
+ Whichever route you pick, you're done as soon as you can run a bare command name (`draft`, `publish`, ...) — you should never need to reference a file path under `node_modules/` directly.
14
+
11
15
  **Run without installing (recommended):**
12
16
 
13
17
  ```sh
@@ -27,7 +31,14 @@ npx -p @chriswiegman/hugo-tools publish content/drafts/my-post.md now
27
31
  npm install --save-dev @chriswiegman/hugo-tools
28
32
  ```
29
33
 
30
- Then run commands via `npx` (no `-p` flag needed once installed) or add them as scripts in your `package.json`:
34
+ Then run commands via `npx` (no `-p` flag needed once installed):
35
+
36
+ ```sh
37
+ npx draft
38
+ npx publish content/drafts/my-post.md now
39
+ ```
40
+
41
+ ...or add them as scripts in your `package.json` so `npm run publish` works too:
31
42
 
32
43
  ```json
33
44
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chriswiegman/hugo-tools",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "A set of tools to make blogging easier with Hugo.",
5
5
  "keywords": [
6
6
  "hugo",
@@ -45,8 +45,9 @@
45
45
  },
46
46
  "devDependencies": {
47
47
  "@eslint/js": "^10.0.1",
48
- "changie": "^1.24.0",
49
- "eslint": "^10.3.0",
50
- "globals": "^17.6.0"
48
+ "@stylistic/eslint-plugin": "^5.10.0",
49
+ "changie": "^1.25.0",
50
+ "eslint": "^10.6.0",
51
+ "globals": "^17.7.0"
51
52
  }
52
- }
53
+ }
package/src/add-tags.js CHANGED
@@ -16,128 +16,131 @@ const DATA_FILE = path.join(process.cwd(), config.vscodeDir, 'tags-categories.js
16
16
  * Display menu and get user selection
17
17
  */
18
18
  async function getSelection(prompt, options) {
19
- const rl = readline.createInterface({
20
- input: process.stdin,
21
- output: process.stdout
22
- });
23
-
24
- return new Promise((resolve) => {
25
- console.log(`\n${prompt}`);
26
- options.forEach((opt, idx) => {
27
- console.log(` ${idx + 1}. ${opt}`);
28
- });
29
- console.log(` 0. Done/Skip`);
30
-
31
- rl.question('\nEnter number: ', (answer) => {
32
- rl.close();
33
- const num = parseInt(answer, 10);
34
- if (num === 0) {
35
- resolve(null);
36
- } else if (num > 0 && num <= options.length) {
37
- resolve(options[num - 1]);
38
- } else {
39
- console.log('Invalid selection');
40
- resolve(null);
41
- }
42
- });
43
- });
19
+ const rl = readline.createInterface({
20
+ input: process.stdin,
21
+ output: process.stdout,
22
+ });
23
+
24
+ return new Promise((resolve) => {
25
+ console.log(`\n${prompt}`);
26
+ options.forEach((opt, idx) => {
27
+ console.log(` ${idx + 1}. ${opt}`);
28
+ });
29
+ console.log(' 0. Done/Skip');
30
+
31
+ rl.question('\nEnter number: ', (answer) => {
32
+ rl.close();
33
+ const num = parseInt(answer, 10);
34
+
35
+ if (num === 0) {
36
+ resolve(null);
37
+ } else if (num > 0 && num <= options.length) {
38
+ resolve(options[num - 1]);
39
+ } else {
40
+ console.log('Invalid selection');
41
+ resolve(null);
42
+ }
43
+ });
44
+ });
44
45
  }
45
46
 
46
47
  /**
47
48
  * Get multiple selections
48
49
  */
49
50
  async function getMultipleSelections(prompt, options) {
50
- const selections = [];
51
- let done = false;
52
-
53
- while (!done) {
54
- const remaining = options.filter(opt => !selections.includes(opt));
55
- if (remaining.length === 0) {
56
- break;
57
- }
58
-
59
- const selection = await getSelection(
60
- selections.length === 0 ? prompt : `${prompt} (Selected: ${selections.join(', ')})`,
61
- remaining
62
- );
63
-
64
- if (selection === null) {
65
- done = true;
66
- } else {
67
- selections.push(selection);
68
- }
69
- }
70
-
71
- return selections;
51
+ const selections = [];
52
+ let done = false;
53
+
54
+ while (!done) {
55
+ const remaining = options.filter((opt) => !selections.includes(opt));
56
+
57
+ if (remaining.length === 0) {
58
+ break;
59
+ }
60
+
61
+ const selection = await getSelection(
62
+ selections.length === 0 ? prompt : `${prompt} (Selected: ${selections.join(', ')})`,
63
+ remaining,
64
+ );
65
+
66
+ if (selection === null) {
67
+ done = true;
68
+ } else {
69
+ selections.push(selection);
70
+ }
71
+ }
72
+
73
+ return selections;
72
74
  }
73
75
 
74
76
  /**
75
77
  * Format frontmatter list
76
78
  */
77
79
  function formatList(items) {
78
- if (items.length === 0) {
79
- return ' -';
80
- }
81
- return items.map(item => ` - ${item}`).join('\n');
80
+ if (items.length === 0) {
81
+ return ' -';
82
+ }
83
+
84
+ return items.map((item) => ` - ${item}`).join('\n');
82
85
  }
83
86
 
84
87
  /**
85
88
  * Main execution
86
89
  */
87
90
  async function main() {
88
- config.requireHugoSite();
89
-
90
- console.log('=== Hugo Draft Tags & Categories Helper ===\n');
91
-
92
- // Check if data file exists
93
- if (!fs.existsSync(DATA_FILE)) {
94
- console.error(`Error: Data file not found at ${DATA_FILE}`);
95
- console.error('Run "extract-tags" first to generate the data file.');
96
- process.exit(1);
97
- }
98
-
99
- // Load data
100
- const data = JSON.parse(fs.readFileSync(DATA_FILE, 'utf8'));
101
-
102
- console.log(`Loaded ${data.categories.length} categories and ${data.tags.length} tags`);
103
- console.log(`(Generated from ${data.stats.totalFiles} posts on ${new Date(data.stats.generatedAt).toLocaleDateString()})\n`);
104
-
105
- // Get category selection
106
- const category = await getSelection(
107
- 'Select a category:',
108
- data.categories
109
- );
110
-
111
- // Get tag selections
112
- const tags = await getMultipleSelections(
113
- 'Select tags (you can select multiple):',
114
- data.tags
115
- );
116
-
117
- // Generate output
118
- console.log('\n=== Generated Frontmatter ===\n');
119
-
120
- if (category) {
121
- console.log('categories:');
122
- console.log(` - ${category}`);
123
- } else {
124
- console.log('categories:');
125
- console.log(' -');
126
- }
127
-
128
- console.log('tags:');
129
- console.log(formatList(tags));
130
-
131
- console.log('\n=== Copy the above into your draft frontmatter ===\n');
91
+ config.requireHugoSite();
92
+
93
+ console.log('=== Hugo Draft Tags & Categories Helper ===\n');
94
+
95
+ // Check if data file exists
96
+ if (!fs.existsSync(DATA_FILE)) {
97
+ console.error(`Error: Data file not found at ${DATA_FILE}`);
98
+ console.error('Run "extract-tags" first to generate the data file.');
99
+ process.exit(1);
100
+ }
101
+
102
+ // Load data
103
+ const data = JSON.parse(fs.readFileSync(DATA_FILE, 'utf8'));
104
+
105
+ console.log(`Loaded ${data.categories.length} categories and ${data.tags.length} tags`);
106
+ console.log(`(Generated from ${data.stats.totalFiles} posts on ${new Date(data.stats.generatedAt).toLocaleDateString()})\n`);
107
+
108
+ // Get category selection
109
+ const category = await getSelection(
110
+ 'Select a category:',
111
+ data.categories,
112
+ );
113
+
114
+ // Get tag selections
115
+ const tags = await getMultipleSelections(
116
+ 'Select tags (you can select multiple):',
117
+ data.tags,
118
+ );
119
+
120
+ // Generate output
121
+ console.log('\n=== Generated Frontmatter ===\n');
122
+
123
+ if (category) {
124
+ console.log('categories:');
125
+ console.log(` - ${category}`);
126
+ } else {
127
+ console.log('categories:');
128
+ console.log(' -');
129
+ }
130
+
131
+ console.log('tags:');
132
+ console.log(formatList(tags));
133
+
134
+ console.log('\n=== Copy the above into your draft frontmatter ===\n');
132
135
  }
133
136
 
134
137
  // Handle Ctrl+C gracefully
135
138
  process.on('SIGINT', () => {
136
- console.log('\n\nCancelled.');
137
- process.exit(0);
139
+ console.log('\n\nCancelled.');
140
+ process.exit(0);
138
141
  });
139
142
 
140
- main().catch(err => {
141
- console.error('Error:', err);
142
- process.exit(1);
143
+ main().catch((err) => {
144
+ console.error('Error:', err);
145
+ process.exit(1);
143
146
  });