@plttn/mkd 0.1.4 → 0.1.5

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/dist/index.js CHANGED
@@ -1,30 +1,405 @@
1
1
  #!/usr/bin/env node
2
+
3
+ // src/index.ts
2
4
  import { run, subcommands } from "cmd-ts";
3
5
  import { PoweredFileSystem } from "pwd-fs";
4
- import { loadConfig } from "./lib/deps";
5
- import { makeNewCommand } from "./commands/new";
6
- import { makePublishCommand } from "./commands/publish";
7
- import { makeUpdateCommand } from "./commands/update";
8
- import { makeUnPublishCommand } from "./commands/unpublish";
9
- import { makeInitCommand } from "./commands/init";
6
+
7
+ // src/lib/deps.ts
8
+ var defaultConfig = {
9
+ blogDir: "./src/blog",
10
+ titleKey: "title",
11
+ author: "",
12
+ publishedAtKey: "publishedAt",
13
+ modifiedAtKey: "updatedAt",
14
+ authorKey: "author",
15
+ draftKey: "draft",
16
+ descriptionKey: "description",
17
+ tagsKey: "tags"
18
+ };
19
+ async function loadConfig(pfs) {
20
+ try {
21
+ const raw = await pfs.read("./mkd.json");
22
+ if (!raw.trim()) {
23
+ return defaultConfig;
24
+ }
25
+ const parsed = JSON.parse(raw);
26
+ if (!isRecord(parsed)) {
27
+ return defaultConfig;
28
+ }
29
+ const { $schema: _schema, ...config } = parsed;
30
+ return {
31
+ ...defaultConfig,
32
+ ...config
33
+ };
34
+ } catch {
35
+ return defaultConfig;
36
+ }
37
+ }
38
+ function isRecord(value) {
39
+ return typeof value === "object" && value !== null && !Array.isArray(value);
40
+ }
41
+
42
+ // src/commands/new.ts
43
+ import { command, restPositionals, string } from "cmd-ts";
44
+ import path from "path";
45
+ import slugify from "@sindresorhus/slugify";
46
+ import filenamify from "filenamify";
47
+ import matter from "gray-matter";
48
+ import { isCancel, text, intro } from "@clack/prompts";
49
+ function makeNewCommand({ config, pfs }) {
50
+ return command({
51
+ name: "new",
52
+ description: "Create a new post",
53
+ args: {
54
+ new: restPositionals({
55
+ type: string,
56
+ displayName: "file",
57
+ description: "name of the new post"
58
+ })
59
+ },
60
+ handler: async ({ new: titleArray }) => {
61
+ intro("Create a new post");
62
+ let title;
63
+ if (titleArray.length === 0) {
64
+ title = await generateTitle();
65
+ if (title === "") {
66
+ return;
67
+ }
68
+ } else {
69
+ title = titleArray.join(" ");
70
+ }
71
+ const slug = slugify(title);
72
+ const fileName = filenamify(slug);
73
+ const frontmatter = await generateFrontmatter(title, config);
74
+ const filePath = path.join(config.blogDir, `${fileName}.md`);
75
+ await pfs.write(filePath, frontmatter);
76
+ }
77
+ });
78
+ }
79
+ async function generateFrontmatter(title, config) {
80
+ const description = await makeDescription(title);
81
+ const now = /* @__PURE__ */ new Date();
82
+ const data = {
83
+ [config.titleKey]: title,
84
+ [config.publishedAtKey]: now,
85
+ [config.authorKey]: config.author,
86
+ [config.draftKey]: true,
87
+ [config.descriptionKey]: description,
88
+ [config.tagsKey]: []
89
+ };
90
+ return matter.stringify("", data);
91
+ }
92
+ async function makeDescription(title) {
93
+ const description = await text({
94
+ message: "Enter a description for the post:",
95
+ defaultValue: title
96
+ });
97
+ if (isCancel(description)) {
98
+ return "";
99
+ }
100
+ return description;
101
+ }
102
+ async function generateTitle() {
103
+ const title = await text({
104
+ message: "Enter a title for the post:",
105
+ validate: (value) => {
106
+ if (!value) {
107
+ return "Title required";
108
+ }
109
+ return void 0;
110
+ }
111
+ });
112
+ if (isCancel(title)) {
113
+ return "";
114
+ }
115
+ return title;
116
+ }
117
+
118
+ // src/commands/publish.ts
119
+ import { command as command2 } from "cmd-ts";
120
+ import {
121
+ autocompleteMultiselect,
122
+ isCancel as isCancel2,
123
+ intro as intro2,
124
+ outro as outro2
125
+ } from "@clack/prompts";
126
+ import matter3 from "gray-matter";
127
+
128
+ // src/lib/commands.ts
129
+ import matter2 from "gray-matter";
130
+ async function readPosts(pfs, config) {
131
+ const files = await pfs.readdir(config.blogDir);
132
+ const posts = [];
133
+ for (const file of files) {
134
+ const content = await pfs.read(`${config.blogDir}/${file}`);
135
+ posts.push({ file, content });
136
+ }
137
+ return posts;
138
+ }
139
+ function parseFrontmatter(post) {
140
+ const { data } = matter2(post.content);
141
+ return data;
142
+ }
143
+ function postsToOptions(posts, config) {
144
+ return posts.map((post) => {
145
+ const fm = parseFrontmatter(post);
146
+ const title = String(fm[config.titleKey] ?? post.file);
147
+ return {
148
+ value: post.file,
149
+ label: title,
150
+ hint: post.file
151
+ };
152
+ });
153
+ }
154
+ function selectedValuesToPosts(selected, posts) {
155
+ if (typeof selected === "symbol") return [];
156
+ return posts.filter((p) => selected.includes(p.file));
157
+ }
158
+ function findPostByFile(posts, fileName) {
159
+ return posts.find((p) => p.file === fileName);
160
+ }
161
+
162
+ // src/commands/publish.ts
163
+ function makePublishCommand({ config, pfs }) {
164
+ return command2({
165
+ name: "publish",
166
+ description: "Undraft a post",
167
+ args: {},
168
+ handler: async () => {
169
+ const posts = await readPosts(pfs, config);
170
+ const drafts = posts.filter(
171
+ (post) => parseFrontmatter(post)[config.draftKey] === true
172
+ );
173
+ const selected = await getPostsToPublish(drafts, config);
174
+ for (const draft of selected) {
175
+ await updateDraftFrontMatter(draft, { config, pfs });
176
+ }
177
+ }
178
+ });
179
+ }
180
+ async function getPostsToPublish(drafts, config) {
181
+ const options = postsToOptions(drafts, config);
182
+ intro2("Publishing posts");
183
+ const selected = await autocompleteMultiselect({
184
+ message: "Select posts to publish",
185
+ options
186
+ });
187
+ if (isCancel2(selected)) {
188
+ outro2("Publishing cancelled.");
189
+ return [];
190
+ }
191
+ outro2("Posts undrafted...");
192
+ return selectedValuesToPosts(selected, drafts);
193
+ }
194
+ async function updateDraftFrontMatter(draft, deps) {
195
+ const parsed = matter3(draft.content);
196
+ const fm = parsed.data;
197
+ fm[deps.config.draftKey] = false;
198
+ const updatedContent = matter3.stringify(parsed.content, fm);
199
+ await deps.pfs.write(`${deps.config.blogDir}/${draft.file}`, updatedContent);
200
+ return { ...draft, content: updatedContent };
201
+ }
202
+
203
+ // src/commands/update.ts
204
+ import { command as command3 } from "cmd-ts";
205
+ import { autocomplete, isCancel as isCancel3, intro as intro3, outro as outro3 } from "@clack/prompts";
206
+ import matter4 from "gray-matter";
207
+ function makeUpdateCommand({ config, pfs }) {
208
+ return command3({
209
+ name: "update",
210
+ description: "Update a post's modified date",
211
+ args: {},
212
+ handler: async () => {
213
+ const posts = await readPosts(pfs, config);
214
+ const post = await getPostToUpdate(posts, config);
215
+ if (!post) return;
216
+ await updatePostDate(post, { config, pfs });
217
+ }
218
+ });
219
+ }
220
+ async function getPostToUpdate(posts, config) {
221
+ const options = postsToOptions(posts, config);
222
+ intro3("Update a post");
223
+ const selected = await autocomplete({
224
+ message: "Select post to update",
225
+ options
226
+ });
227
+ if (isCancel3(selected)) {
228
+ outro3("Update cancelled.");
229
+ return null;
230
+ }
231
+ outro3("Post updated.");
232
+ const found = findPostByFile(posts, selected);
233
+ return found ?? null;
234
+ }
235
+ async function updatePostDate(post, deps) {
236
+ const parsed = matter4(post.content);
237
+ const fm = parsed.data;
238
+ fm[deps.config.modifiedAtKey] = /* @__PURE__ */ new Date();
239
+ const updatedContent = matter4.stringify(parsed.content, fm);
240
+ await deps.pfs.write(`${deps.config.blogDir}/${post.file}`, updatedContent);
241
+ return { ...post, content: updatedContent };
242
+ }
243
+
244
+ // src/commands/unpublish.ts
245
+ import { command as command4 } from "cmd-ts";
246
+ import { autocomplete as autocomplete2, isCancel as isCancel4, intro as intro4, outro as outro4 } from "@clack/prompts";
247
+ import matter5 from "gray-matter";
248
+ function makeUnPublishCommand({ config, pfs }) {
249
+ return command4({
250
+ name: "unpublish",
251
+ description: "Unpublish a post",
252
+ args: {},
253
+ handler: async () => {
254
+ const posts = await readPosts(pfs, config);
255
+ const post = await getPostToUnpub(posts, config);
256
+ if (!post) return;
257
+ await unpubPost(post, { config, pfs });
258
+ }
259
+ });
260
+ }
261
+ async function getPostToUnpub(posts, config) {
262
+ const options = postsToOptions(posts, config);
263
+ intro4("Unpublish a post");
264
+ const selected = await autocomplete2({
265
+ message: "Select post to unpublish",
266
+ options
267
+ });
268
+ if (isCancel4(selected)) {
269
+ outro4("Unpublish cancelled.");
270
+ return null;
271
+ }
272
+ outro4("Post unpublished.");
273
+ const found = findPostByFile(posts, selected);
274
+ return found ?? null;
275
+ }
276
+ async function unpubPost(post, deps) {
277
+ const parsed = matter5(post.content);
278
+ const fm = parsed.data;
279
+ fm[deps.config.draftKey] = true;
280
+ const updatedContent = matter5.stringify(parsed.content, fm);
281
+ await deps.pfs.write(`${deps.config.blogDir}/${post.file}`, updatedContent);
282
+ return { ...post, content: updatedContent };
283
+ }
284
+
285
+ // src/commands/init.ts
286
+ import { command as command5 } from "cmd-ts";
287
+ import { text as text2, isCancel as isCancel5, intro as intro5, outro as outro5 } from "@clack/prompts";
288
+ function makeInitCommand({ config, pfs }) {
289
+ return command5({
290
+ name: "init",
291
+ description: "Create or update mkd.json configuration",
292
+ args: {},
293
+ handler: async () => {
294
+ intro5("Initialize mkd configuration");
295
+ const blogDir = await text2({
296
+ message: "Directory where generated posts are written",
297
+ defaultValue: String(config.blogDir ?? "./src/blog")
298
+ });
299
+ if (isCancel5(blogDir)) {
300
+ outro5("Init cancelled");
301
+ return;
302
+ }
303
+ const author = await text2({
304
+ message: "Default author",
305
+ defaultValue: String(config.author ?? "")
306
+ });
307
+ if (isCancel5(author)) {
308
+ outro5("Init cancelled");
309
+ return;
310
+ }
311
+ const titleKey = await text2({
312
+ message: "Title frontmatter key",
313
+ defaultValue: String(config.titleKey ?? "title")
314
+ });
315
+ if (isCancel5(titleKey)) {
316
+ outro5("Init cancelled");
317
+ return;
318
+ }
319
+ const publishedAtKey = await text2({
320
+ message: "Published date frontmatter key",
321
+ defaultValue: String(config.publishedAtKey ?? "publishedAt")
322
+ });
323
+ if (isCancel5(publishedAtKey)) {
324
+ outro5("Init cancelled");
325
+ return;
326
+ }
327
+ const modifiedAtKey = await text2({
328
+ message: "Modified date frontmatter key",
329
+ defaultValue: String(config.modifiedAtKey ?? "updatedAt")
330
+ });
331
+ if (isCancel5(modifiedAtKey)) {
332
+ outro5("Init cancelled");
333
+ return;
334
+ }
335
+ const authorKey = await text2({
336
+ message: "Author frontmatter key",
337
+ defaultValue: String(config.authorKey ?? "author")
338
+ });
339
+ if (isCancel5(authorKey)) {
340
+ outro5("Init cancelled");
341
+ return;
342
+ }
343
+ const draftKey = await text2({
344
+ message: "Draft frontmatter key",
345
+ defaultValue: String(config.draftKey ?? "draft")
346
+ });
347
+ if (isCancel5(draftKey)) {
348
+ outro5("Init cancelled");
349
+ return;
350
+ }
351
+ const descriptionKey = await text2({
352
+ message: "Description frontmatter key",
353
+ defaultValue: String(config.descriptionKey ?? "description")
354
+ });
355
+ if (isCancel5(descriptionKey)) {
356
+ outro5("Init cancelled");
357
+ return;
358
+ }
359
+ const tagsKey = await text2({
360
+ message: "Tags frontmatter key",
361
+ defaultValue: String(config.tagsKey ?? "tags")
362
+ });
363
+ if (isCancel5(tagsKey)) {
364
+ outro5("Init cancelled");
365
+ return;
366
+ }
367
+ const newConfig = {
368
+ blogDir: String(blogDir),
369
+ author: String(author),
370
+ publishedAtKey: String(publishedAtKey),
371
+ modifiedAtKey: String(modifiedAtKey),
372
+ authorKey: String(authorKey),
373
+ draftKey: String(draftKey),
374
+ descriptionKey: String(descriptionKey),
375
+ tagsKey: String(tagsKey),
376
+ titleKey: String(titleKey)
377
+ };
378
+ await pfs.write("./mkd.json", JSON.stringify(newConfig, null, 2) + "\n");
379
+ outro5("Configuration saved to mkd.json");
380
+ }
381
+ });
382
+ }
383
+
384
+ // src/index.ts
10
385
  async function main() {
11
- const pfs = new PoweredFileSystem();
12
- const config = await loadConfig(pfs);
13
- const deps = { config, pfs };
14
- const app = subcommands({
15
- name: "mkd",
16
- cmds: {
17
- new: makeNewCommand(deps),
18
- publish: makePublishCommand(deps),
19
- update: makeUpdateCommand(deps),
20
- unpublish: makeUnPublishCommand(deps),
21
- init: makeInitCommand(deps),
22
- },
23
- });
24
- await run(app, process.argv.slice(2));
386
+ const pfs = new PoweredFileSystem();
387
+ const config = await loadConfig(pfs);
388
+ const deps = { config, pfs };
389
+ const app = subcommands({
390
+ name: "mkd",
391
+ cmds: {
392
+ new: makeNewCommand(deps),
393
+ publish: makePublishCommand(deps),
394
+ update: makeUpdateCommand(deps),
395
+ unpublish: makeUnPublishCommand(deps),
396
+ init: makeInitCommand(deps)
397
+ }
398
+ });
399
+ await run(app, process.argv.slice(2));
25
400
  }
26
401
  main().catch((error) => {
27
- console.error(error);
28
- process.exit(1);
402
+ console.error(error);
403
+ process.exit(1);
29
404
  });
30
405
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,KAAK,UAAU,IAAI;IACjB,MAAM,GAAG,GAAG,IAAI,iBAAiB,EAAE,CAAC;IACpC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IAE7B,MAAM,GAAG,GAAG,WAAW,CAAC;QACtB,IAAI,EAAE,KAAK;QACX,IAAI,EAAE;YACJ,GAAG,EAAE,cAAc,CAAC,IAAI,CAAC;YACzB,OAAO,EAAE,kBAAkB,CAAC,IAAI,CAAC;YACjC,MAAM,EAAE,iBAAiB,CAAC,IAAI,CAAC;YAC/B,SAAS,EAAE,oBAAoB,CAAC,IAAI,CAAC;YACrC,IAAI,EAAE,eAAe,CAAC,IAAI,CAAC;SAC5B;KACF,CAAC,CAAC;IAEH,MAAM,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACxC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"sources":["../src/index.ts","../src/lib/deps.ts","../src/commands/new.ts","../src/commands/publish.ts","../src/lib/commands.ts","../src/commands/update.ts","../src/commands/unpublish.ts","../src/commands/init.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { run, subcommands } from \"cmd-ts\";\nimport { PoweredFileSystem } from \"pwd-fs\";\nimport { loadConfig } from \"./lib/deps\";\nimport { makeNewCommand } from \"./commands/new\";\nimport { makePublishCommand } from \"./commands/publish\";\nimport { makeUpdateCommand } from \"./commands/update\";\nimport { makeUnPublishCommand } from \"./commands/unpublish\";\nimport { makeInitCommand } from \"./commands/init\";\n\nasync function main() {\n const pfs = new PoweredFileSystem();\n const config = await loadConfig(pfs);\n const deps = { config, pfs };\n\n const app = subcommands({\n name: \"mkd\",\n cmds: {\n new: makeNewCommand(deps),\n publish: makePublishCommand(deps),\n update: makeUpdateCommand(deps),\n unpublish: makeUnPublishCommand(deps),\n init: makeInitCommand(deps),\n },\n });\n\n await run(app, process.argv.slice(2));\n}\n\nmain().catch((error) => {\n console.error(error);\n process.exit(1);\n});\n","import type { PoweredFileSystem } from \"pwd-fs\";\n\nexport type Config = {\n blogDir: string;\n titleKey: string;\n author: string;\n publishedAtKey: string;\n modifiedAtKey: string;\n authorKey: string;\n draftKey: string;\n descriptionKey: string;\n tagsKey: string;\n};\n\nexport type Deps = {\n config: Config;\n pfs: PoweredFileSystem;\n};\n\nconst defaultConfig: Config = {\n blogDir: \"./src/blog\",\n titleKey: \"title\",\n author: \"\",\n publishedAtKey: \"publishedAt\",\n modifiedAtKey: \"updatedAt\",\n authorKey: \"author\",\n draftKey: \"draft\",\n descriptionKey: \"description\",\n tagsKey: \"tags\",\n};\n\nexport async function loadConfig(pfs: PoweredFileSystem): Promise<Config> {\n try {\n const raw = await pfs.read(\"./mkd.json\");\n\n if (!raw.trim()) {\n return defaultConfig;\n }\n\n const parsed = JSON.parse(raw);\n\n if (!isRecord(parsed)) {\n return defaultConfig;\n }\n\n const { $schema: _schema, ...config } = parsed;\n\n return {\n ...defaultConfig,\n ...config,\n };\n } catch {\n return defaultConfig;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { command, restPositionals, string } from \"cmd-ts\";\nimport path from \"node:path\";\nimport slugify from \"@sindresorhus/slugify\";\nimport filenamify from \"filenamify\";\nimport matter from \"gray-matter\";\nimport { isCancel, text, intro, outro } from \"@clack/prompts\";\nimport type { Config, Deps } from \"../lib/deps\";\n\nexport function makeNewCommand({ config, pfs }: Deps) {\n return command({\n name: \"new\",\n description: \"Create a new post\",\n args: {\n new: restPositionals({\n type: string,\n displayName: \"file\",\n description: \"name of the new post\",\n }),\n },\n handler: async ({ new: titleArray }) => {\n intro(\"Create a new post\");\n let title: string;\n if (titleArray.length === 0) {\n title = await generateTitle();\n if (title === \"\") {\n return;\n }\n } else {\n title = titleArray.join(\" \");\n }\n const slug = slugify(title);\n const fileName = filenamify(slug);\n const frontmatter = await generateFrontmatter(title, config);\n const filePath = path.join(config.blogDir, `${fileName}.md`);\n\n await pfs.write(filePath, frontmatter);\n },\n });\n}\n\nasync function generateFrontmatter(\n title: string,\n config: Config,\n): Promise<string> {\n const description = await makeDescription(title);\n const now = new Date();\n\n const data = {\n [config.titleKey]: title,\n [config.publishedAtKey]: now,\n [config.authorKey]: config.author,\n [config.draftKey]: true,\n [config.descriptionKey]: description,\n [config.tagsKey]: [],\n };\n\n return matter.stringify(\"\", data);\n}\n\nasync function makeDescription(title: string): Promise<string> {\n const description = await text({\n message: \"Enter a description for the post:\",\n defaultValue: title,\n });\n\n if (isCancel(description)) {\n return \"\";\n }\n\n return description;\n}\n\nasync function generateTitle(): Promise<string> {\n const title = await text({\n message: \"Enter a title for the post:\",\n validate: (value) => {\n if (!value) {\n return \"Title required\";\n }\n return undefined;\n },\n });\n\n if (isCancel(title)) {\n return \"\";\n }\n\n return title;\n}\n","import { command } from \"cmd-ts\";\nimport {\n autocompleteMultiselect,\n isCancel,\n intro,\n outro,\n} from \"@clack/prompts\";\nimport matter from \"gray-matter\";\nimport type { Config, Deps } from \"../lib/deps\";\nimport {\n readPosts,\n parseFrontmatter,\n postsToOptions,\n selectedValuesToPosts,\n Post,\n} from \"../lib/commands\";\n\nexport function makePublishCommand({ config, pfs }: Deps) {\n return command({\n name: \"publish\",\n description: \"Undraft a post\",\n args: {},\n handler: async () => {\n const posts = await readPosts(pfs, config);\n const drafts = posts.filter(\n (post) => parseFrontmatter(post)[config.draftKey] === true,\n );\n const selected = await getPostsToPublish(drafts, config);\n\n for (const draft of selected) {\n await updateDraftFrontMatter(draft, { config, pfs });\n }\n },\n });\n}\n\nasync function getPostsToPublish(\n drafts: Post[],\n config: Config,\n): Promise<Post[]> {\n const options = postsToOptions(drafts, config);\n intro(\"Publishing posts\");\n\n const selected = await autocompleteMultiselect({\n message: \"Select posts to publish\",\n options,\n });\n\n if (isCancel(selected)) {\n outro(\"Publishing cancelled.\");\n return [];\n }\n\n outro(\"Posts undrafted...\");\n\n return selectedValuesToPosts(selected, drafts);\n}\n\nasync function updateDraftFrontMatter(draft: Post, deps: Deps) {\n const parsed = matter(draft.content);\n const fm = parsed.data as Record<string, unknown>;\n fm[deps.config.draftKey] = false;\n const updatedContent = matter.stringify(parsed.content, fm);\n await deps.pfs.write(`${deps.config.blogDir}/${draft.file}`, updatedContent);\n return { ...draft, content: updatedContent };\n}\n","import matter from \"gray-matter\";\nimport type { Config, Deps } from \"./deps\";\n\nexport type Post = {\n file: string;\n content: string;\n};\n\nexport type Frontmatter = Record<string, unknown>;\n\n/** Read all files from the blog directory and return them as Post objects */\nexport async function readPosts(pfs: Deps[\"pfs\"], config: Config): Promise<Post[]> {\n const files = (await pfs.readdir(config.blogDir)) as string[];\n const posts: Post[] = [];\n\n for (const file of files) {\n const content = await pfs.read(`${config.blogDir}/${file}`);\n posts.push({ file, content });\n }\n\n return posts;\n}\n\n/** Parse frontmatter from a Post */\nexport function parseFrontmatter(post: Post): Frontmatter {\n const { data } = matter(post.content);\n return data as Frontmatter;\n}\n\n/** Convert Posts to prompt option objects (value/label/hint) */\nexport function postsToOptions(posts: Post[], config: Config) {\n return posts.map((post) => {\n const fm = parseFrontmatter(post);\n const title = String(fm[config.titleKey] ?? post.file);\n\n return {\n value: post.file,\n label: title,\n hint: post.file,\n };\n });\n}\n\n/** Take the raw selected values returned by the prompt and return matching Post[] */\nexport function selectedValuesToPosts(selected: string[] | symbol, posts: Post[]): Post[] {\n if (typeof selected === \"symbol\") return [];\n return posts.filter((p) => selected.includes(p.file));\n}\n\nexport function findPostByFile(posts: Post[], fileName: string): Post | undefined {\n return posts.find((p) => p.file === fileName);\n}\n","import { command } from \"cmd-ts\";\nimport { autocomplete, isCancel, intro, outro } from \"@clack/prompts\";\nimport matter from \"gray-matter\";\nimport type { Config, Deps } from \"../lib/deps\";\nimport {\n readPosts,\n postsToOptions,\n findPostByFile,\n Post,\n} from \"../lib/commands\";\n\ntype Frontmatter = Record<string, unknown>;\n\nexport function makeUpdateCommand({ config, pfs }: Deps) {\n return command({\n name: \"update\",\n description: \"Update a post's modified date\",\n args: {},\n handler: async () => {\n const posts = await readPosts(pfs, config);\n const post = await getPostToUpdate(posts, config);\n if (!post) return;\n\n await updatePostDate(post, { config, pfs });\n },\n });\n}\n\nasync function getPostToUpdate(\n posts: Post[],\n config: Config,\n): Promise<Post | null> {\n const options = postsToOptions(posts, config);\n\n intro(\"Update a post\");\n\n const selected = await autocomplete({\n message: \"Select post to update\",\n options,\n });\n\n if (isCancel(selected)) {\n outro(\"Update cancelled.\");\n return null;\n }\n outro(\"Post updated.\");\n\n const found = findPostByFile(posts, selected as string);\n return found ?? null;\n}\n\nasync function updatePostDate(post: Post, deps: Deps) {\n const parsed = matter(post.content);\n const fm = parsed.data as Record<string, unknown>;\n fm[deps.config.modifiedAtKey] = new Date();\n const updatedContent = matter.stringify(parsed.content, fm);\n await deps.pfs.write(`${deps.config.blogDir}/${post.file}`, updatedContent);\n return { ...post, content: updatedContent };\n}\n","import { command } from \"cmd-ts\";\nimport { autocomplete, isCancel, intro, outro } from \"@clack/prompts\";\nimport matter from \"gray-matter\";\nimport type { Config, Deps } from \"../lib/deps\";\nimport {\n readPosts,\n postsToOptions,\n findPostByFile,\n Post,\n} from \"../lib/commands\";\n\ntype Frontmatter = Record<string, unknown>;\n\nexport function makeUnPublishCommand({ config, pfs }: Deps) {\n return command({\n name: \"unpublish\",\n description: \"Unpublish a post\",\n args: {},\n handler: async () => {\n const posts = await readPosts(pfs, config);\n const post = await getPostToUnpub(posts, config);\n if (!post) return;\n\n await unpubPost(post, { config, pfs });\n },\n });\n}\n\nasync function getPostToUnpub(\n posts: Post[],\n config: Config,\n): Promise<Post | null> {\n const options = postsToOptions(posts, config);\n\n intro(\"Unpublish a post\");\n\n const selected = await autocomplete({\n message: \"Select post to unpublish\",\n options,\n });\n\n if (isCancel(selected)) {\n outro(\"Unpublish cancelled.\");\n return null;\n }\n outro(\"Post unpublished.\");\n\n const found = findPostByFile(posts, selected as string);\n return found ?? null;\n}\n\nasync function unpubPost(post: Post, deps: Deps) {\n const parsed = matter(post.content);\n const fm = parsed.data as Record<string, unknown>;\n fm[deps.config.draftKey] = true;\n const updatedContent = matter.stringify(parsed.content, fm);\n await deps.pfs.write(`${deps.config.blogDir}/${post.file}`, updatedContent);\n return { ...post, content: updatedContent };\n}\n","import { command } from \"cmd-ts\";\nimport { text, isCancel, intro, outro } from \"@clack/prompts\";\nimport type { Deps } from \"../lib/deps\";\n\nexport function makeInitCommand({ config, pfs }: Deps) {\n return command({\n name: \"init\",\n description: \"Create or update mkd.json configuration\",\n args: {},\n handler: async () => {\n intro(\"Initialize mkd configuration\");\n\n const blogDir = await text({\n message: \"Directory where generated posts are written\",\n defaultValue: String(config.blogDir ?? \"./src/blog\"),\n });\n if (isCancel(blogDir)) {\n outro(\"Init cancelled\");\n return;\n }\n\n const author = await text({\n message: \"Default author\",\n defaultValue: String(config.author ?? \"\"),\n });\n if (isCancel(author)) {\n outro(\"Init cancelled\");\n return;\n }\n\n const titleKey = await text({\n message: \"Title frontmatter key\",\n defaultValue: String(config.titleKey ?? \"title\"),\n });\n if (isCancel(titleKey)) {\n outro(\"Init cancelled\");\n return;\n }\n\n const publishedAtKey = await text({\n message: \"Published date frontmatter key\",\n defaultValue: String(config.publishedAtKey ?? \"publishedAt\"),\n });\n if (isCancel(publishedAtKey)) {\n outro(\"Init cancelled\");\n return;\n }\n\n const modifiedAtKey = await text({\n message: \"Modified date frontmatter key\",\n defaultValue: String(config.modifiedAtKey ?? \"updatedAt\"),\n });\n if (isCancel(modifiedAtKey)) {\n outro(\"Init cancelled\");\n return;\n }\n\n const authorKey = await text({\n message: \"Author frontmatter key\",\n defaultValue: String(config.authorKey ?? \"author\"),\n });\n if (isCancel(authorKey)) {\n outro(\"Init cancelled\");\n return;\n }\n\n const draftKey = await text({\n message: \"Draft frontmatter key\",\n defaultValue: String(config.draftKey ?? \"draft\"),\n });\n if (isCancel(draftKey)) {\n outro(\"Init cancelled\");\n return;\n }\n\n const descriptionKey = await text({\n message: \"Description frontmatter key\",\n defaultValue: String(config.descriptionKey ?? \"description\"),\n });\n if (isCancel(descriptionKey)) {\n outro(\"Init cancelled\");\n return;\n }\n\n const tagsKey = await text({\n message: \"Tags frontmatter key\",\n defaultValue: String(config.tagsKey ?? \"tags\"),\n });\n if (isCancel(tagsKey)) {\n outro(\"Init cancelled\");\n return;\n }\n\n const newConfig = {\n blogDir: String(blogDir),\n author: String(author),\n publishedAtKey: String(publishedAtKey),\n modifiedAtKey: String(modifiedAtKey),\n authorKey: String(authorKey),\n draftKey: String(draftKey),\n descriptionKey: String(descriptionKey),\n tagsKey: String(tagsKey),\n titleKey: String(titleKey),\n };\n\n await pfs.write(\"./mkd.json\", JSON.stringify(newConfig, null, 2) + \"\\n\");\n\n outro(\"Configuration saved to mkd.json\");\n },\n });\n}\n"],"mappings":"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","names":["command","isCancel","intro","outro","matter","matter","command","intro","isCancel","outro","matter","command","isCancel","intro","outro","matter","command","intro","isCancel","outro","matter","command","autocomplete","isCancel","intro","outro","matter","command","intro","autocomplete","isCancel","outro","matter","command","text","isCancel","intro","outro"]}
package/package.json CHANGED
@@ -1,23 +1,23 @@
1
1
  {
2
2
  "name": "@plttn/mkd",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "mkd": "dist/index.js"
8
8
  },
9
9
  "files": [
10
- "dist/**/**",
11
- "docs/**/**",
12
- "!**/*.spec.*",
13
- "!**/*.json",
14
- "!**/*.tsbuildinfo",
15
- "LICENSE",
16
- "README.md"
10
+ "dist"
17
11
  ],
18
- "main": "./dist/index.js",
12
+ "main": "./dist/index.cjs",
13
+ "module": "dist/index.js",
14
+ "types": "dist/index.d.ts",
19
15
  "exports": {
20
- ".": "./dist/index.js"
16
+ ".": {
17
+ "import": "./dist/index.js",
18
+ "require": "./dist/index.cjs"
19
+ },
20
+ "./package.json": "./package.json"
21
21
  },
22
22
  "keywords": [],
23
23
  "author": "",
@@ -25,6 +25,7 @@
25
25
  "devDependencies": {
26
26
  "@types/node": "^25.9.1",
27
27
  "prettier": "3.8.3",
28
+ "tsup": "^8.5.1",
28
29
  "tsx": "^4.22.3",
29
30
  "typescript": "^6.0.3"
30
31
  },
@@ -42,6 +43,6 @@
42
43
  },
43
44
  "scripts": {
44
45
  "dev": "tsx ./src/index.ts",
45
- "build": "tsc --build --clean && tsc --build"
46
+ "build": "tsup"
46
47
  }
47
48
  }
@@ -1,6 +0,0 @@
1
- import type { Deps } from "../lib/deps";
2
- export declare function makeInitCommand({ config, pfs }: Deps): Partial<import("cmd-ts/dist/cjs/argparser").Register> & {
3
- parse(context: import("cmd-ts/dist/cjs/argparser").ParseContext): Promise<import("cmd-ts/dist/cjs/argparser").ParsingResult<{}>>;
4
- } & import("cmd-ts/dist/cjs/helpdoc").PrintHelp & import("cmd-ts/dist/cjs/helpdoc").ProvidesHelp & import("cmd-ts/dist/cjs/helpdoc").Named & Partial<import("cmd-ts/dist/cjs/helpdoc").Versioned> & import("cmd-ts/dist/cjs/argparser").Register & import("cmd-ts/dist/cjs/runner").Handling<{}, Promise<void>> & {
5
- run(context: import("cmd-ts/dist/cjs/argparser").ParseContext): Promise<import("cmd-ts/dist/cjs/argparser").ParsingResult<Promise<void>>>;
6
- } & Partial<import("cmd-ts/dist/cjs/helpdoc").Versioned & import("cmd-ts/dist/cjs/helpdoc").Descriptive & import("cmd-ts/dist/cjs/helpdoc").Aliased>;
@@ -1,98 +0,0 @@
1
- import { command } from "cmd-ts";
2
- import { text, isCancel, intro, outro } from "@clack/prompts";
3
- export function makeInitCommand({ config, pfs }) {
4
- return command({
5
- name: "init",
6
- description: "Create or update mkd.json configuration",
7
- args: {},
8
- handler: async () => {
9
- intro("Initialize mkd configuration");
10
- const blogDir = await text({
11
- message: "Directory where generated posts are written",
12
- defaultValue: String(config.blogDir ?? "./src/blog"),
13
- });
14
- if (isCancel(blogDir)) {
15
- outro("Init cancelled");
16
- return;
17
- }
18
- const author = await text({
19
- message: "Default author",
20
- defaultValue: String(config.author ?? ""),
21
- });
22
- if (isCancel(author)) {
23
- outro("Init cancelled");
24
- return;
25
- }
26
- const titleKey = await text({
27
- message: "Title frontmatter key",
28
- defaultValue: String(config.titleKey ?? "title"),
29
- });
30
- if (isCancel(titleKey)) {
31
- outro("Init cancelled");
32
- return;
33
- }
34
- const publishedAtKey = await text({
35
- message: "Published date frontmatter key",
36
- defaultValue: String(config.publishedAtKey ?? "publishedAt"),
37
- });
38
- if (isCancel(publishedAtKey)) {
39
- outro("Init cancelled");
40
- return;
41
- }
42
- const modifiedAtKey = await text({
43
- message: "Modified date frontmatter key",
44
- defaultValue: String(config.modifiedAtKey ?? "updatedAt"),
45
- });
46
- if (isCancel(modifiedAtKey)) {
47
- outro("Init cancelled");
48
- return;
49
- }
50
- const authorKey = await text({
51
- message: "Author frontmatter key",
52
- defaultValue: String(config.authorKey ?? "author"),
53
- });
54
- if (isCancel(authorKey)) {
55
- outro("Init cancelled");
56
- return;
57
- }
58
- const draftKey = await text({
59
- message: "Draft frontmatter key",
60
- defaultValue: String(config.draftKey ?? "draft"),
61
- });
62
- if (isCancel(draftKey)) {
63
- outro("Init cancelled");
64
- return;
65
- }
66
- const descriptionKey = await text({
67
- message: "Description frontmatter key",
68
- defaultValue: String(config.descriptionKey ?? "description"),
69
- });
70
- if (isCancel(descriptionKey)) {
71
- outro("Init cancelled");
72
- return;
73
- }
74
- const tagsKey = await text({
75
- message: "Tags frontmatter key",
76
- defaultValue: String(config.tagsKey ?? "tags"),
77
- });
78
- if (isCancel(tagsKey)) {
79
- outro("Init cancelled");
80
- return;
81
- }
82
- const newConfig = {
83
- blogDir: String(blogDir),
84
- author: String(author),
85
- publishedAtKey: String(publishedAtKey),
86
- modifiedAtKey: String(modifiedAtKey),
87
- authorKey: String(authorKey),
88
- draftKey: String(draftKey),
89
- descriptionKey: String(descriptionKey),
90
- tagsKey: String(tagsKey),
91
- titleKey: String(titleKey),
92
- };
93
- await pfs.write("./mkd.json", JSON.stringify(newConfig, null, 2) + "\n");
94
- outro("Configuration saved to mkd.json");
95
- },
96
- });
97
- }
98
- //# sourceMappingURL=init.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -1,10 +0,0 @@
1
- import type { Deps } from "../lib/deps";
2
- export declare function makeNewCommand({ config, pfs }: Deps): Partial<import("cmd-ts/dist/cjs/argparser").Register> & {
3
- parse(context: import("cmd-ts/dist/cjs/argparser").ParseContext): Promise<import("cmd-ts/dist/cjs/argparser").ParsingResult<{
4
- new: string[];
5
- }>>;
6
- } & import("cmd-ts/dist/cjs/helpdoc").PrintHelp & import("cmd-ts/dist/cjs/helpdoc").ProvidesHelp & import("cmd-ts/dist/cjs/helpdoc").Named & Partial<import("cmd-ts/dist/cjs/helpdoc").Versioned> & import("cmd-ts/dist/cjs/argparser").Register & import("cmd-ts/dist/cjs/runner").Handling<{
7
- new: string[];
8
- }, Promise<void>> & {
9
- run(context: import("cmd-ts/dist/cjs/argparser").ParseContext): Promise<import("cmd-ts/dist/cjs/argparser").ParsingResult<Promise<void>>>;
10
- } & Partial<import("cmd-ts/dist/cjs/helpdoc").Versioned & import("cmd-ts/dist/cjs/helpdoc").Descriptive & import("cmd-ts/dist/cjs/helpdoc").Aliased>;