@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.
@@ -12,18 +12,18 @@ const path = require('path');
12
12
  const { requireHugoSite, DEFAULTS } = require('./config');
13
13
 
14
14
  function main() {
15
- requireHugoSite();
15
+ requireHugoSite();
16
16
 
17
- const dest = path.join(process.cwd(), '.hugo-tools.json');
17
+ const dest = path.join(process.cwd(), '.hugo-tools.json');
18
18
 
19
- if (fs.existsSync(dest)) {
20
- process.stderr.write('Error: .hugo-tools.json already exists.\n');
21
- process.exit(1);
22
- }
19
+ if (fs.existsSync(dest)) {
20
+ process.stderr.write('Error: .hugo-tools.json already exists.\n');
21
+ process.exit(1);
22
+ }
23
23
 
24
- fs.writeFileSync(dest, JSON.stringify(DEFAULTS, null, 2) + '\n', 'utf8');
25
- console.log(`Created ${dest}`);
26
- console.log('Edit the values to match your Hugo site layout.');
24
+ fs.writeFileSync(dest, JSON.stringify(DEFAULTS, null, 2) + '\n', 'utf8');
25
+ console.log(`Created ${dest}`);
26
+ console.log('Edit the values to match your Hugo site layout.');
27
27
  }
28
28
 
29
29
  main();
package/src/config.js CHANGED
@@ -4,38 +4,40 @@ const fs = require('fs');
4
4
  const path = require('path');
5
5
 
6
6
  const DEFAULTS = {
7
- timezone: 'America/Chicago',
8
- postsDir: 'content/posts',
9
- draftsDir: 'content/drafts',
10
- notesDir: 'content/notes',
11
- booksDir: 'content/books',
12
- imagesDir: 'assets/images',
13
- vscodeDir: '.vscode',
7
+ timezone: 'America/Chicago',
8
+ postsDir: 'content/posts',
9
+ draftsDir: 'content/drafts',
10
+ notesDir: 'content/notes',
11
+ booksDir: 'content/books',
12
+ imagesDir: 'assets/images',
13
+ vscodeDir: '.vscode',
14
14
  };
15
15
 
16
16
  let override = {};
17
17
  const configPath = path.join(process.cwd(), '.hugo-tools.json');
18
+
18
19
  try {
19
- if (fs.existsSync(configPath)) {
20
- override = JSON.parse(fs.readFileSync(configPath, 'utf8'));
21
- }
20
+ if (fs.existsSync(configPath)) {
21
+ override = JSON.parse(fs.readFileSync(configPath, 'utf8'));
22
+ }
22
23
  } catch (e) {
23
- process.stderr.write(`Warning: could not read .hugo-tools.json: ${e.message}\n`);
24
+ process.stderr.write(`Warning: could not read .hugo-tools.json: ${e.message}\n`);
24
25
  }
25
26
 
26
27
  const HUGO_CONFIGS = [
27
- 'hugo.toml', 'hugo.yaml', 'hugo.yml', 'hugo.json',
28
- 'config.toml', 'config.yaml', 'config.yml', 'config.json',
29
- 'config',
28
+ 'hugo.toml', 'hugo.yaml', 'hugo.yml', 'hugo.json',
29
+ 'config.toml', 'config.yaml', 'config.yml', 'config.json',
30
+ 'config',
30
31
  ];
31
32
 
32
33
  function requireHugoSite() {
33
- const cwd = process.cwd();
34
- const found = HUGO_CONFIGS.some(name => fs.existsSync(path.join(cwd, name)));
35
- if (!found) {
36
- process.stderr.write('Error: no Hugo config file found. Run this command from the root of your Hugo site.\n');
37
- process.exit(1);
38
- }
34
+ const cwd = process.cwd();
35
+ const found = HUGO_CONFIGS.some((name) => fs.existsSync(path.join(cwd, name)));
36
+
37
+ if (!found) {
38
+ process.stderr.write('Error: no Hugo config file found. Run this command from the root of your Hugo site.\n');
39
+ process.exit(1);
40
+ }
39
41
  }
40
42
 
41
43
  module.exports = { ...DEFAULTS, ...override, requireHugoSite, DEFAULTS };
package/src/draft.js CHANGED
@@ -17,61 +17,63 @@ const { execFileSync } = require('child_process');
17
17
  const config = require('./config');
18
18
 
19
19
  function timestampFilename() {
20
- const now = new Date();
21
- const parts = new Intl.DateTimeFormat('en-CA', {
22
- timeZone: config.timezone,
23
- year: 'numeric',
24
- month: '2-digit',
25
- day: '2-digit',
26
- hour: '2-digit',
27
- minute: '2-digit',
28
- second: '2-digit',
29
- hour12: false,
30
- }).formatToParts(now);
31
- const get = (type) => parts.find(p => p.type === type).value;
32
- let hour = get('hour');
33
- if (hour === '24') hour = '00';
34
- return `${get('year')}${get('month')}${get('day')}-${hour}${get('minute')}${get('second')}`;
20
+ const now = new Date();
21
+ const parts = new Intl.DateTimeFormat('en-CA', {
22
+ timeZone: config.timezone,
23
+ year: 'numeric',
24
+ month: '2-digit',
25
+ day: '2-digit',
26
+ hour: '2-digit',
27
+ minute: '2-digit',
28
+ second: '2-digit',
29
+ hour12: false,
30
+ }).formatToParts(now);
31
+ const get = (type) => parts.find((p) => p.type === type).value;
32
+ let hour = get('hour');
33
+
34
+ if (hour === '24') hour = '00';
35
+
36
+ return `${get('year')}${get('month')}${get('day')}-${hour}${get('minute')}${get('second')}`;
35
37
  }
36
38
 
37
39
  function buildArchetype() {
38
- return [
39
- '---',
40
- 'title: ""',
41
- 'description: ""',
42
- 'draft: true',
43
- 'images:',
44
- ' -',
45
- 'categories:',
46
- ' -',
47
- 'tags:',
48
- ' -',
49
- '---',
50
- '',
51
- ].join('\n');
40
+ return [
41
+ '---',
42
+ 'title: ""',
43
+ 'description: ""',
44
+ 'draft: true',
45
+ 'images:',
46
+ ' -',
47
+ 'categories:',
48
+ ' -',
49
+ 'tags:',
50
+ ' -',
51
+ '---',
52
+ '',
53
+ ].join('\n');
52
54
  }
53
55
 
54
56
  function main() {
55
- config.requireHugoSite();
57
+ config.requireHugoSite();
56
58
 
57
- const stamp = timestampFilename();
58
- const draftsDir = path.join(process.cwd(), config.draftsDir);
59
- const destPath = path.join(draftsDir, `${stamp}.md`);
59
+ const stamp = timestampFilename();
60
+ const draftsDir = path.join(process.cwd(), config.draftsDir);
61
+ const destPath = path.join(draftsDir, `${stamp}.md`);
60
62
 
61
- fs.mkdirSync(draftsDir, { recursive: true });
62
- fs.writeFileSync(destPath, buildArchetype(), 'utf8');
63
+ fs.mkdirSync(draftsDir, { recursive: true });
64
+ fs.writeFileSync(destPath, buildArchetype(), 'utf8');
63
65
 
64
- console.log(destPath);
66
+ console.log(destPath);
65
67
 
66
- try {
67
- execFileSync('code', [destPath], { stdio: 'ignore' });
68
- } catch {
69
- // VS Code not available — silently continue
70
- }
68
+ try {
69
+ execFileSync('code', [destPath], { stdio: 'ignore' });
70
+ } catch {
71
+ // VS Code not available — silently continue
72
+ }
71
73
  }
72
74
 
73
75
  if (require.main === module) {
74
- main();
76
+ main();
75
77
  }
76
78
 
77
79
  module.exports = { buildArchetype, timestampFilename };
@@ -10,42 +10,45 @@ const { buildArchetype, timestampFilename } = require('./draft.js');
10
10
  // ---------------------------------------------------------------------------
11
11
 
12
12
  test('buildArchetype: starts with front matter delimiter', () => {
13
- assert.ok(buildArchetype().startsWith('---\n'));
13
+ assert.ok(buildArchetype().startsWith('---\n'));
14
14
  });
15
15
 
16
16
  test('buildArchetype: contains blank title', () => {
17
- assert.ok(buildArchetype().includes('title: ""'));
17
+ assert.ok(buildArchetype().includes('title: ""'));
18
18
  });
19
19
 
20
20
  test('buildArchetype: contains blank description', () => {
21
- assert.ok(buildArchetype().includes('description: ""'));
21
+ assert.ok(buildArchetype().includes('description: ""'));
22
22
  });
23
23
 
24
24
  test('buildArchetype: sets draft true', () => {
25
- assert.ok(buildArchetype().includes('draft: true'));
25
+ assert.ok(buildArchetype().includes('draft: true'));
26
26
  });
27
27
 
28
28
  test('buildArchetype: contains images placeholder', () => {
29
- const out = buildArchetype();
30
- assert.ok(out.includes('images:\n -'));
29
+ const out = buildArchetype();
30
+
31
+ assert.ok(out.includes('images:\n -'));
31
32
  });
32
33
 
33
34
  test('buildArchetype: contains categories placeholder', () => {
34
- const out = buildArchetype();
35
- assert.ok(out.includes('categories:\n -'));
35
+ const out = buildArchetype();
36
+
37
+ assert.ok(out.includes('categories:\n -'));
36
38
  });
37
39
 
38
40
  test('buildArchetype: contains tags placeholder', () => {
39
- const out = buildArchetype();
40
- assert.ok(out.includes('tags:\n -'));
41
+ const out = buildArchetype();
42
+
43
+ assert.ok(out.includes('tags:\n -'));
41
44
  });
42
45
 
43
46
  test('buildArchetype: does not contain a date key', () => {
44
- assert.ok(!buildArchetype().includes('date:'));
47
+ assert.ok(!buildArchetype().includes('date:'));
45
48
  });
46
49
 
47
50
  test('buildArchetype: ends with closing delimiter and trailing newline', () => {
48
- assert.ok(buildArchetype().endsWith('---\n'));
51
+ assert.ok(buildArchetype().endsWith('---\n'));
49
52
  });
50
53
 
51
54
  // ---------------------------------------------------------------------------
@@ -53,25 +56,27 @@ test('buildArchetype: ends with closing delimiter and trailing newline', () => {
53
56
  // ---------------------------------------------------------------------------
54
57
 
55
58
  test('timestampFilename: matches YYYYMMDD-HHMMSS format', () => {
56
- assert.match(timestampFilename(), /^\d{8}-\d{6}$/);
59
+ assert.match(timestampFilename(), /^\d{8}-\d{6}$/);
57
60
  });
58
61
 
59
62
  test('timestampFilename: date portion is a plausible date', () => {
60
- const stamp = timestampFilename();
61
- const year = parseInt(stamp.slice(0, 4), 10);
62
- const month = parseInt(stamp.slice(4, 6), 10);
63
- const day = parseInt(stamp.slice(6, 8), 10);
64
- assert.ok(year >= 2024);
65
- assert.ok(month >= 1 && month <= 12);
66
- assert.ok(day >= 1 && day <= 31);
63
+ const stamp = timestampFilename();
64
+ const year = parseInt(stamp.slice(0, 4), 10);
65
+ const month = parseInt(stamp.slice(4, 6), 10);
66
+ const day = parseInt(stamp.slice(6, 8), 10);
67
+
68
+ assert.ok(year >= 2024);
69
+ assert.ok(month >= 1 && month <= 12);
70
+ assert.ok(day >= 1 && day <= 31);
67
71
  });
68
72
 
69
73
  test('timestampFilename: time portion is a plausible time', () => {
70
- const stamp = timestampFilename();
71
- const hour = parseInt(stamp.slice(9, 11), 10);
72
- const minute = parseInt(stamp.slice(11, 13), 10);
73
- const second = parseInt(stamp.slice(13, 15), 10);
74
- assert.ok(hour >= 0 && hour <= 23);
75
- assert.ok(minute >= 0 && minute <= 59);
76
- assert.ok(second >= 0 && second <= 59);
74
+ const stamp = timestampFilename();
75
+ const hour = parseInt(stamp.slice(9, 11), 10);
76
+ const minute = parseInt(stamp.slice(11, 13), 10);
77
+ const second = parseInt(stamp.slice(13, 15), 10);
78
+
79
+ assert.ok(hour >= 0 && hour <= 23);
80
+ assert.ok(minute >= 0 && minute <= 59);
81
+ assert.ok(second >= 0 && second <= 59);
77
82
  });