worklog-opsdevnz 0.1.2__tar.gz → 0.2.0__tar.gz

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.
Files changed (22) hide show
  1. {worklog_opsdevnz-0.1.2/src/worklog_opsdevnz.egg-info → worklog_opsdevnz-0.2.0}/PKG-INFO +4 -1
  2. {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.2.0}/README.md +2 -0
  3. {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.2.0}/pyproject.toml +2 -1
  4. {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.2.0}/src/worklog_opsdevnz/config.py +3 -0
  5. worklog_opsdevnz-0.2.0/src/worklog_opsdevnz/template.py +94 -0
  6. {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.2.0/src/worklog_opsdevnz.egg-info}/PKG-INFO +4 -1
  7. {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.2.0}/src/worklog_opsdevnz.egg-info/requires.txt +1 -0
  8. worklog_opsdevnz-0.2.0/tests/test_template.py +285 -0
  9. worklog_opsdevnz-0.1.2/src/worklog_opsdevnz/template.py +0 -46
  10. worklog_opsdevnz-0.1.2/tests/test_template.py +0 -45
  11. {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.2.0}/LICENSE +0 -0
  12. {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.2.0}/setup.cfg +0 -0
  13. {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.2.0}/src/worklog_opsdevnz/__init__.py +0 -0
  14. {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.2.0}/src/worklog_opsdevnz/cli.py +0 -0
  15. {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.2.0}/src/worklog_opsdevnz/paths.py +0 -0
  16. {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.2.0}/src/worklog_opsdevnz.egg-info/SOURCES.txt +0 -0
  17. {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.2.0}/src/worklog_opsdevnz.egg-info/dependency_links.txt +0 -0
  18. {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.2.0}/src/worklog_opsdevnz.egg-info/entry_points.txt +0 -0
  19. {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.2.0}/src/worklog_opsdevnz.egg-info/top_level.txt +0 -0
  20. {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.2.0}/tests/test_cli.py +0 -0
  21. {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.2.0}/tests/test_config.py +0 -0
  22. {worklog_opsdevnz-0.1.2 → worklog_opsdevnz-0.2.0}/tests/test_paths.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: worklog-opsdevnz
3
- Version: 0.1.2
3
+ Version: 0.2.0
4
4
  Summary: Configurable worklog management CLI for dated development logs
5
5
  Author-email: "OpsDev.nz Collective" <john@opsdev.nz>
6
6
  License: Apache-2.0
@@ -29,6 +29,7 @@ Requires-Dist: pytest-cov>=4.0; extra == "dev"
29
29
  Requires-Dist: pytest-mock>=3.10; extra == "dev"
30
30
  Requires-Dist: ruff>=0.4; extra == "dev"
31
31
  Requires-Dist: mypy>=1.0; extra == "dev"
32
+ Requires-Dist: zensical>=0.0.44; extra == "dev"
32
33
  Dynamic: license-file
33
34
 
34
35
  # worklog-opsdevnz
@@ -60,6 +61,7 @@ worklog_dir = "docs/worklog"
60
61
  structure = "year" # "flat", "year", or "year-month"
61
62
  author = "Your Name"
62
63
  editor = "nvim" # optional, overridden by -e / $VISUAL / $EDITOR
64
+ template = "my-template.md" # optional custom body template
63
65
  default_tags = ["worklog", "log"]
64
66
 
65
67
  [[sections]]
@@ -81,6 +83,7 @@ title = "Next"
81
83
  - Three directory structure modes: `flat`, `year`, `year-month`
82
84
  - YAML frontmatter: date, author, tags, draft status
83
85
  - Configurable section headers per project
86
+ - Custom body templates with `{{DATE}}` and `{{TITLE}}` placeholders
84
87
  - Editor integration: `-e` flag → config → `$VISUAL` → `$EDITOR`
85
88
  - `--version` flag for installed version
86
89
 
@@ -27,6 +27,7 @@ worklog_dir = "docs/worklog"
27
27
  structure = "year" # "flat", "year", or "year-month"
28
28
  author = "Your Name"
29
29
  editor = "nvim" # optional, overridden by -e / $VISUAL / $EDITOR
30
+ template = "my-template.md" # optional custom body template
30
31
  default_tags = ["worklog", "log"]
31
32
 
32
33
  [[sections]]
@@ -48,6 +49,7 @@ title = "Next"
48
49
  - Three directory structure modes: `flat`, `year`, `year-month`
49
50
  - YAML frontmatter: date, author, tags, draft status
50
51
  - Configurable section headers per project
52
+ - Custom body templates with `{{DATE}}` and `{{TITLE}}` placeholders
51
53
  - Editor integration: `-e` flag → config → `$VISUAL` → `$EDITOR`
52
54
  - `--version` flag for installed version
53
55
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "worklog-opsdevnz"
7
- version = "0.1.2"
7
+ version = "0.2.0"
8
8
  description = "Configurable worklog management CLI for dated development logs"
9
9
  readme = "README.md"
10
10
  license = {text = "Apache-2.0"}
@@ -37,6 +37,7 @@ dev = [
37
37
  "pytest-mock>=3.10",
38
38
  "ruff>=0.4",
39
39
  "mypy>=1.0",
40
+ "zensical>=0.0.44",
40
41
  ]
41
42
 
42
43
  [project.urls]
@@ -67,5 +67,8 @@ def get_config() -> dict[str, Any]:
67
67
  worklog_dir = merged["worklog_dir"]
68
68
  if not Path(worklog_dir).is_absolute():
69
69
  merged["worklog_dir"] = str(config_path.parent / worklog_dir)
70
+ template = merged.get("template")
71
+ if template and not Path(template).is_absolute():
72
+ merged["template"] = str(config_path.parent / template)
70
73
  return merged
71
74
  return dict(DEFAULT_CONFIG)
@@ -0,0 +1,94 @@
1
+ """Frontmatter and body generation for worklog entries."""
2
+
3
+ from typing import Any
4
+
5
+
6
+ def generate_frontmatter(
7
+ config: dict[str, Any],
8
+ iso_date: str,
9
+ ) -> str:
10
+ """Generate YAML frontmatter."""
11
+ title = f"Work Log - {iso_date}"
12
+ tags = "\n".join(f" - {t}" for t in config.get("default_tags", []))
13
+ author = config.get("author", "unknown")
14
+
15
+ return f"""---
16
+ title: "{title}"
17
+ date: {iso_date}
18
+ author: {author}
19
+ tags:
20
+ {tags}
21
+ draft: false
22
+ ---
23
+ """
24
+
25
+
26
+ def generate_body(config: dict[str, Any]) -> str:
27
+ """Generate section headers from config."""
28
+ sections = config.get("sections", [])
29
+ lines = []
30
+ for section in sections:
31
+ title = section.get("title", "")
32
+ content = section.get("content", "")
33
+ lines.append(f"## {title}\n")
34
+ if content:
35
+ lines.append(f"{content}\n")
36
+ return "\n".join(lines)
37
+
38
+
39
+ def _render_tags(tags: list[str]) -> str:
40
+ """Render tags as a block-style YAML list substitution.
41
+
42
+ Empty list → '[]'. Populated list → leading newline followed by
43
+ each tag on its own indented line with '-' prefix.
44
+ """
45
+ if not tags:
46
+ return "[]"
47
+ return "\n" + "\n".join(f" - {t}" for t in tags)
48
+
49
+
50
+ def render_template(
51
+ template_path: str,
52
+ iso_date: str,
53
+ config: dict[str, Any],
54
+ ) -> str:
55
+ """Render a custom Markdown template with placeholder substitution.
56
+
57
+ Supports {{DATE}}, {{TITLE}}, {{AUTHOR}}, and {{TAGS}} placeholders.
58
+ All placeholders are case-sensitive.
59
+ """
60
+ title = f"Work Log - {iso_date}"
61
+ tags = _render_tags(config.get("default_tags", []))
62
+ author = config.get("author", "unknown")
63
+ with open(template_path) as f:
64
+ content = f.read()
65
+ content = content.replace("{{DATE}}", iso_date)
66
+ content = content.replace("{{TITLE}}", title)
67
+ content = content.replace("{{AUTHOR}}", author)
68
+ content = content.replace("{{TAGS}}", tags)
69
+ # Clean trailing whitespace (avoids artifacts when placeholder
70
+ # substitution leaves space before a newline, e.g. 'tags: \n')
71
+ content = "\n".join(line.rstrip() for line in content.split("\n"))
72
+ return content
73
+
74
+
75
+ def generate_content(
76
+ config: dict[str, Any],
77
+ iso_date: str,
78
+ ) -> str:
79
+ """Generate full worklog content.
80
+
81
+ If a 'template' field is set in config, the template defines the
82
+ complete entry (including YAML frontmatter). Placeholders are
83
+ substituted but nothing else is prepended.
84
+
85
+ Otherwise uses the built-in default: config-driven frontmatter and
86
+ sections-based body.
87
+ """
88
+ template_path = config.get("template")
89
+ if template_path:
90
+ return render_template(template_path, iso_date, config)
91
+
92
+ frontmatter = generate_frontmatter(config, iso_date)
93
+ body = generate_body(config)
94
+ return f"{frontmatter}\n{body}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: worklog-opsdevnz
3
- Version: 0.1.2
3
+ Version: 0.2.0
4
4
  Summary: Configurable worklog management CLI for dated development logs
5
5
  Author-email: "OpsDev.nz Collective" <john@opsdev.nz>
6
6
  License: Apache-2.0
@@ -29,6 +29,7 @@ Requires-Dist: pytest-cov>=4.0; extra == "dev"
29
29
  Requires-Dist: pytest-mock>=3.10; extra == "dev"
30
30
  Requires-Dist: ruff>=0.4; extra == "dev"
31
31
  Requires-Dist: mypy>=1.0; extra == "dev"
32
+ Requires-Dist: zensical>=0.0.44; extra == "dev"
32
33
  Dynamic: license-file
33
34
 
34
35
  # worklog-opsdevnz
@@ -60,6 +61,7 @@ worklog_dir = "docs/worklog"
60
61
  structure = "year" # "flat", "year", or "year-month"
61
62
  author = "Your Name"
62
63
  editor = "nvim" # optional, overridden by -e / $VISUAL / $EDITOR
64
+ template = "my-template.md" # optional custom body template
63
65
  default_tags = ["worklog", "log"]
64
66
 
65
67
  [[sections]]
@@ -81,6 +83,7 @@ title = "Next"
81
83
  - Three directory structure modes: `flat`, `year`, `year-month`
82
84
  - YAML frontmatter: date, author, tags, draft status
83
85
  - Configurable section headers per project
86
+ - Custom body templates with `{{DATE}}` and `{{TITLE}}` placeholders
84
87
  - Editor integration: `-e` flag → config → `$VISUAL` → `$EDITOR`
85
88
  - `--version` flag for installed version
86
89
 
@@ -7,3 +7,4 @@ pytest-cov>=4.0
7
7
  pytest-mock>=3.10
8
8
  ruff>=0.4
9
9
  mypy>=1.0
10
+ zensical>=0.0.44
@@ -0,0 +1,285 @@
1
+ """Tests for frontmatter and body generation."""
2
+
3
+ import pytest
4
+
5
+ from worklog_opsdevnz.template import (
6
+ generate_frontmatter,
7
+ generate_body,
8
+ generate_content,
9
+ render_template,
10
+ )
11
+
12
+
13
+ def test_generate_frontmatter():
14
+ config = {
15
+ "author": "Test Author",
16
+ "default_tags": ["internal", "test"],
17
+ }
18
+ fm = generate_frontmatter(config, "2026-05-23")
19
+ assert "title: " in fm
20
+ assert "Work Log - 2026-05-23" in fm
21
+ assert "date: 2026-05-23" in fm
22
+ assert "author: Test Author" in fm
23
+ assert " - internal" in fm
24
+ assert " - test" in fm
25
+ assert "draft: false" in fm
26
+ assert fm.startswith("---")
27
+ assert fm.strip().endswith("---")
28
+
29
+
30
+ def test_generate_body_with_sections():
31
+ config = {
32
+ "sections": [
33
+ {"title": "Focus", "content": ""},
34
+ {"title": "Notes", "content": "some note"},
35
+ ]
36
+ }
37
+ body = generate_body(config)
38
+ assert "## Focus" in body
39
+ assert "## Notes" in body
40
+ assert "some note" in body
41
+
42
+
43
+ def test_generate_content_full():
44
+ config = {
45
+ "author": "opsdev",
46
+ "default_tags": ["log"],
47
+ "sections": [{"title": "Today", "content": ""}],
48
+ }
49
+ content = generate_content(config, "2026-05-23")
50
+ assert content.startswith("---")
51
+ assert "Work Log - 2026-05-23" in content
52
+ assert "## Today" in content
53
+
54
+
55
+ def test_render_template_with_placeholders(tmp_path):
56
+ template = tmp_path / "my-template.md"
57
+ template.write_text(
58
+ "---\n"
59
+ 'title: "{{TITLE}}"\n'
60
+ "date: {{DATE}}\n"
61
+ "author: {{AUTHOR}}\n"
62
+ "tags: {{TAGS}}\n"
63
+ "draft: false\n"
64
+ "---\n\n"
65
+ "# {{TITLE}}\n\n"
66
+ "Date: {{DATE}}\n\n"
67
+ "Free-form notes."
68
+ )
69
+
70
+ config = {"author": "opsdev", "default_tags": ["dev", "log"]}
71
+ result = render_template(str(template), "2026-05-26", config)
72
+
73
+ # Placeholders replaced
74
+ assert "{{DATE}}" not in result
75
+ assert "{{TITLE}}" not in result
76
+ assert "{{AUTHOR}}" not in result
77
+ assert "{{TAGS}}" not in result
78
+
79
+ # Content verified
80
+ assert "# Work Log - 2026-05-26" in result
81
+ assert "Date: 2026-05-26" in result
82
+ assert "Free-form notes." in result
83
+ assert 'title: "Work Log - 2026-05-26"' in result
84
+ assert "date: 2026-05-26" in result
85
+ assert "author: opsdev" in result
86
+ assert "draft: false" in result
87
+
88
+ # Tags rendered as block-style YAML
89
+ assert " - dev" in result
90
+ assert " - log" in result
91
+
92
+
93
+ def test_render_template_file_not_found():
94
+ with pytest.raises(FileNotFoundError):
95
+ render_template("/nonexistent/template.md", "2026-05-26", {})
96
+
97
+
98
+ def test_generate_content_with_template(tmp_path):
99
+ """When template is set, it defines the complete entry.
100
+
101
+ No auto-generated frontmatter is prepended.
102
+ """
103
+ template = tmp_path / "my-template.md"
104
+ template.write_text(
105
+ "---\n"
106
+ 'title: "{{TITLE}}"\n'
107
+ "date: {{DATE}}\n"
108
+ "author: {{AUTHOR}}\n"
109
+ "tags: {{TAGS}}\n"
110
+ "draft: false\n"
111
+ "---\n\n"
112
+ "# {{TITLE}}\n\n"
113
+ "Date: {{DATE}}"
114
+ )
115
+
116
+ config = {
117
+ "author": "opsdev",
118
+ "default_tags": ["log"],
119
+ "template": str(template),
120
+ }
121
+ content = generate_content(config, "2026-05-26")
122
+
123
+ # Template defines the full entry — its frontmatter is present
124
+ assert content.startswith("---")
125
+ assert 'title: "Work Log - 2026-05-26"' in content
126
+ assert "date: 2026-05-26" in content
127
+ assert "author: opsdev" in content
128
+ assert " - log" in content
129
+ assert "draft: false" in content
130
+
131
+ # Body comes from template
132
+ assert "# Work Log - 2026-05-26" in content
133
+ assert "Date: 2026-05-26" in content
134
+
135
+ # No duplicate frontmatter — only one '---' block
136
+ assert content.count("---") == 2 # opening + closing
137
+
138
+ # Sections are NOT present (template controls everything)
139
+ assert "## Focus for Today" not in content
140
+
141
+
142
+ def test_generate_content_without_template():
143
+ """No template field → built-in sections body, unchanged behaviour."""
144
+ config = {
145
+ "author": "opsdev",
146
+ "default_tags": ["log"],
147
+ "sections": [{"title": "Today", "content": ""}],
148
+ }
149
+ content = generate_content(config, "2026-05-26")
150
+ assert "## Today" in content
151
+
152
+
153
+ # ── {{TAGS}} rendering ────────────────────────────────────────────
154
+
155
+
156
+ def test_render_template_tags_empty(tmp_path):
157
+ """Empty default_tags → {{TAGS}} substitutes as '[]'."""
158
+ template = tmp_path / "t.md"
159
+ template.write_text("tags: {{TAGS}}\n")
160
+
161
+ result = render_template(str(template), "2026-06-01", {"default_tags": []})
162
+ assert "tags: []" in result
163
+ assert "{{TAGS}}" not in result
164
+
165
+
166
+ def test_render_template_tags_populated(tmp_path):
167
+ """Populated default_tags → {{TAGS}} renders as block-style YAML list."""
168
+ template = tmp_path / "t.md"
169
+ template.write_text("tags: {{TAGS}}\n")
170
+
171
+ config = {"default_tags": ["dev", "log", "ops"]}
172
+ result = render_template(str(template), "2026-06-01", config)
173
+
174
+ # Block-style: leading newline + indented items, no trailing whitespace
175
+ assert "tags:\n - dev\n - log\n - ops" in result
176
+ assert "{{TAGS}}" not in result
177
+
178
+
179
+ def test_render_template_tags_not_configured(tmp_path):
180
+ """No default_tags in config → {{TAGS}} substitutes as '[]'."""
181
+ template = tmp_path / "t.md"
182
+ template.write_text("tags: {{TAGS}}\n")
183
+
184
+ result = render_template(str(template), "2026-06-01", {})
185
+ assert "tags: []" in result
186
+
187
+
188
+ # ── {{AUTHOR}} rendering ──────────────────────────────────────────
189
+
190
+
191
+ def test_render_template_author_configured(tmp_path):
192
+ """{{AUTHOR}} pulls the author value from config."""
193
+ template = tmp_path / "t.md"
194
+ template.write_text("author: {{AUTHOR}}\n")
195
+
196
+ result = render_template(str(template), "2026-06-01", {"author": "opsdev"})
197
+ assert "author: opsdev" in result
198
+ assert "{{AUTHOR}}" not in result
199
+
200
+
201
+ def test_render_template_author_fallback(tmp_path):
202
+ """{{AUTHOR}} falls back to 'unknown' when not in config."""
203
+ template = tmp_path / "t.md"
204
+ template.write_text("author: {{AUTHOR}}\n")
205
+
206
+ result = render_template(str(template), "2026-06-01", {})
207
+ assert "author: unknown" in result
208
+
209
+
210
+ # ── Full-entry template edge cases ────────────────────────────────
211
+
212
+
213
+ def test_generate_content_template_defines_full_entry(tmp_path):
214
+ """Template with custom YAML fields — the tool only substitutes placeholders."""
215
+ template = tmp_path / "custom.md"
216
+ template.write_text(
217
+ "---\n"
218
+ 'title: "{{TITLE}}"\n'
219
+ "date: {{DATE}}\n"
220
+ "author: {{AUTHOR}}\n"
221
+ "tags: {{TAGS}}\n"
222
+ "mood: creative\n"
223
+ "project: outcome-engineering\n"
224
+ "draft: false\n"
225
+ "---\n\n"
226
+ "# {{TITLE}}\n\n"
227
+ "Custom body content."
228
+ )
229
+
230
+ config = {
231
+ "author": "opsdev",
232
+ "default_tags": ["dev"],
233
+ "template": str(template),
234
+ }
235
+ content = generate_content(config, "2026-06-05")
236
+
237
+ # Custom fields preserved verbatim
238
+ assert "mood: creative" in content
239
+ assert "project: outcome-engineering" in content
240
+
241
+ # Placeholders substituted
242
+ assert 'title: "Work Log - 2026-06-05"' in content
243
+ assert "date: 2026-06-05" in content
244
+ assert "author: opsdev" in content
245
+ assert " - dev" in content
246
+
247
+ # Body preserved
248
+ assert "Custom body content." in content
249
+
250
+ # No auto-generated frontmatter prepended
251
+ assert content.count("---") == 2 # only the template's opening/closing
252
+
253
+
254
+ def test_generate_content_template_no_frontmatter(tmp_path):
255
+ """Template without frontmatter — entry has no frontmatter at all."""
256
+ template = tmp_path / "body-only.md"
257
+ template.write_text("# {{TITLE}}\n\nJust body content.")
258
+
259
+ config = {"template": str(template)}
260
+ content = generate_content(config, "2026-06-05")
261
+
262
+ # No frontmatter markers, just the rendered template
263
+ assert "---" not in content
264
+ assert "# Work Log - 2026-06-05" in content
265
+ assert "Just body content." in content
266
+
267
+
268
+ def test_render_template_case_sensitive(tmp_path):
269
+ """Lowercase placeholders are NOT substituted."""
270
+ template = tmp_path / "t.md"
271
+ template.write_text(
272
+ "title: {{title}}\n"
273
+ "date: {{date}}\n"
274
+ "author: {{author}}\n"
275
+ "tags: {{tags}}\n"
276
+ )
277
+
278
+ config = {"author": "opsdev", "default_tags": ["dev"]}
279
+ result = render_template(str(template), "2026-06-05", config)
280
+
281
+ # Lowercase placeholders left untouched
282
+ assert "{{title}}" in result
283
+ assert "{{date}}" in result
284
+ assert "{{author}}" in result
285
+ assert "{{tags}}" in result
@@ -1,46 +0,0 @@
1
- """Frontmatter and body generation for worklog entries."""
2
-
3
- from typing import Any
4
-
5
-
6
- def generate_frontmatter(
7
- config: dict[str, Any],
8
- iso_date: str,
9
- ) -> str:
10
- """Generate YAML frontmatter."""
11
- title = f"Work Log - {iso_date}"
12
- tags = "\n".join(f" - {t}" for t in config.get("default_tags", []))
13
- author = config.get("author", "unknown")
14
-
15
- return f"""---
16
- title: "{title}"
17
- date: {iso_date}
18
- author: {author}
19
- tags:
20
- {tags}
21
- draft: false
22
- ---
23
- """
24
-
25
-
26
- def generate_body(config: dict[str, Any]) -> str:
27
- """Generate section headers from config."""
28
- sections = config.get("sections", [])
29
- lines = []
30
- for section in sections:
31
- title = section.get("title", "")
32
- content = section.get("content", "")
33
- lines.append(f"## {title}\n")
34
- if content:
35
- lines.append(f"{content}\n")
36
- return "\n".join(lines)
37
-
38
-
39
- def generate_content(
40
- config: dict[str, Any],
41
- iso_date: str,
42
- ) -> str:
43
- """Generate full worklog content."""
44
- frontmatter = generate_frontmatter(config, iso_date)
45
- body = generate_body(config)
46
- return f"{frontmatter}\n{body}"
@@ -1,45 +0,0 @@
1
- """Tests for frontmatter and body generation."""
2
-
3
- from worklog_opsdevnz.template import generate_frontmatter, generate_body, generate_content
4
-
5
-
6
- def test_generate_frontmatter():
7
- config = {
8
- "author": "Test Author",
9
- "default_tags": ["internal", "test"],
10
- }
11
- fm = generate_frontmatter(config, "2026-05-23")
12
- assert "title: " in fm
13
- assert "Work Log - 2026-05-23" in fm
14
- assert "date: 2026-05-23" in fm
15
- assert "author: Test Author" in fm
16
- assert " - internal" in fm
17
- assert " - test" in fm
18
- assert "draft: false" in fm
19
- assert fm.startswith("---")
20
- assert fm.strip().endswith("---")
21
-
22
-
23
- def test_generate_body_with_sections():
24
- config = {
25
- "sections": [
26
- {"title": "Focus", "content": ""},
27
- {"title": "Notes", "content": "some note"},
28
- ]
29
- }
30
- body = generate_body(config)
31
- assert "## Focus" in body
32
- assert "## Notes" in body
33
- assert "some note" in body
34
-
35
-
36
- def test_generate_content_full():
37
- config = {
38
- "author": "opsdev",
39
- "default_tags": ["log"],
40
- "sections": [{"title": "Today", "content": ""}],
41
- }
42
- content = generate_content(config, "2026-05-23")
43
- assert content.startswith("---")
44
- assert "Work Log - 2026-05-23" in content
45
- assert "## Today" in content