Skip to content

Commit 35663c8

Browse files
committed
create: ewTools.js — local article creation and deletion
usage: `node ./bin/ewTools.js`
1 parent af42589 commit 35663c8

1 file changed

Lines changed: 180 additions & 0 deletions

File tree

bin/ewTools.js

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
import fs from "fs"
2+
import path from "path"
3+
import dotenv from "dotenv"
4+
5+
dotenv.config()
6+
const isDevelopment = process.env.TOOLS_ENV === "development"
7+
const LoggerType = Object.freeze({
8+
INFO: "Info",
9+
WARN: "Warning",
10+
ERROR: "Error",
11+
EMPTY: ""
12+
})
13+
const Logger = (text, type = LoggerType.EMPTY) => {
14+
const typeFormatted = (type === LoggerType.EMPTY) ? `${type}` : `${type}:`
15+
if (isDevelopment) console.log(`${typeFormatted}`, text)
16+
}
17+
18+
const formatFlagsString = (args) => {
19+
if (!Array.isArray(args) || args.length === 0) return "";
20+
21+
return args.map((token, index) => {
22+
if (index === args.length - 1) return token;
23+
return (index % 2 == 0) ? `${token};` : `${token}+`
24+
}).join("")
25+
}
26+
27+
const flagsHandler = (flags) => {
28+
const paramWithValue = flags.split("+")
29+
const flagsObject = new Object();
30+
paramWithValue.forEach(token => {
31+
const [attr, value] = token.split(";")
32+
flagsObject[attr[1]] = value
33+
})
34+
return flagsObject
35+
}
36+
37+
const args = process.argv.slice(2)
38+
if (args.length <= 0) {
39+
console.log("Usage: ./ewtools.bat make:blog \"title\"")
40+
process.exit()
41+
}
42+
const [command, title, ...restArgs] = args
43+
const [action, type] = command.split(':')
44+
const formattedFlags = formatFlagsString(restArgs)
45+
const flagsObject = flagsHandler(formattedFlags)
46+
Logger(args, LoggerType.INFO)
47+
Logger(flagsObject, LoggerType.INFO)
48+
49+
const ActionTypes = Object.freeze({
50+
MAKE: "make",
51+
DELETE: "delete",
52+
REMOVE: "remove"
53+
})
54+
55+
const EntityTypes = Object.freeze({
56+
BLOG: "blog",
57+
PROJECT: "project",
58+
PROTOTYPE: "prototype"
59+
})
60+
61+
if (args.length < 2) {
62+
console.log("Usage: ./ewtools.bat make:blog \"title\"")
63+
process.exit(1)
64+
}
65+
66+
const handleError = (error, filename, action = ActionTypes.MAKE) => {
67+
if (error) return console.error(`Error creating file: ${error.message}`)
68+
const currentAction = (action === ActionTypes.MAKE) ? "created" : "removed"
69+
console.log(`File "${filename}" ${currentAction} successfully.`)
70+
}
71+
72+
const generateFile = (title, entityType, getContent) => {
73+
const { filename, filepath } = generateFilePath(title, entityType);
74+
const content = getContent(title, flagsObject);
75+
fs.writeFile(filepath, content, error => handleError(error, filename));
76+
};
77+
78+
const generateBlogFile = (title) => generateFile(title, EntityTypes.BLOG, getDefaultBlogContent)
79+
80+
const generateProjectFile = (title) => generateFile(title, EntityTypes.PROJECT, getDefaultProjectContent)
81+
82+
const generatePrototypeFile = (title) => generateFile(title, EntityTypes.PROTOTYPE, getDefaultPrototypeContent)
83+
84+
const removeFile = (title, type) => {
85+
const { filename, filepath } = generateFilePath(title, type)
86+
fs.rm(filepath, (error) => handleError(error, filename, ActionTypes.DELETE))
87+
}
88+
89+
const generateFilePath = (title, type) => {
90+
let date = flagsObject.d || new Date().toISOString()
91+
const [year, month, day] = date.split("T")[0].split("-")
92+
if (!(year && month && day)) {
93+
console.log("Invalid date format. Please provide -d yyyy-mm-dd")
94+
process.exit(1)
95+
}
96+
const formattedDate = type === EntityTypes.PROTOTYPE ? year : `${year}-${month}-${day}`
97+
const filename = `${formattedDate}-${title.replace(/\s+/g, "-").toLowerCase()}.md`.replace(/[<>:"\/\\|?*]+/g, "")
98+
const filepath = path.join(process.cwd(), `src/articles/${type}`, filename)
99+
100+
return { filename, filepath }
101+
}
102+
103+
const getDefaultBlogContent = (title, flags = {}) => `---
104+
title: ${title}
105+
description:
106+
author:
107+
draft: true
108+
date: ${new Date().toISOString()}
109+
tags:
110+
- post
111+
${typeof flags.t === "string" ? flags.t.split(",").map(tag => ` - ${tag}`).join("\n") : ""}---
112+
113+
`
114+
const getDefaultProjectContent = (title, flags = {}) => `---
115+
title: ${title}
116+
description:
117+
date:
118+
endDate:
119+
image:
120+
linkDemo:
121+
linkCode:
122+
tags:
123+
- project
124+
${typeof flags.t === "string" ? flags.t.split(",").map(tag => ` - ${tag}`).join("\n") : ""}---`;
125+
const getDefaultPrototypeContent = (title, flags = {}) => `---
126+
title: ${title}
127+
status: 1
128+
description:
129+
date:
130+
linkDemo:
131+
language:
132+
code: |-
133+
tags:
134+
- prototype
135+
${typeof flags.t === "string" ? flags.t.split(",").map(tag => ` - ${tag}`).join("\n") : ""}---
136+
`
137+
138+
const handleMake = (type, title) => {
139+
switch (type) {
140+
case EntityTypes.BLOG:
141+
generateBlogFile(title)
142+
break
143+
case EntityTypes.PROJECT:
144+
generateProjectFile(title)
145+
break
146+
case EntityTypes.PROTOTYPE:
147+
generatePrototypeFile(title)
148+
break
149+
default:
150+
console.log("Invalid Type")
151+
}
152+
}
153+
154+
const handleDelete = (type, title) => {
155+
switch (type) {
156+
case EntityTypes.BLOG:
157+
removeFile(title, EntityTypes.BLOG)
158+
break
159+
case EntityTypes.PROJECT:
160+
removeFile(title, EntityTypes.PROJECT)
161+
break
162+
case EntityTypes.PROTOTYPE:
163+
removeFile(title, EntityTypes.PROTOTYPE)
164+
break
165+
default:
166+
console.log("Invalid Type")
167+
}
168+
}
169+
170+
switch (action) {
171+
case ActionTypes.MAKE:
172+
handleMake(type, title)
173+
break
174+
case ActionTypes.DELETE:
175+
case ActionTypes.REMOVE:
176+
handleDelete(type, title)
177+
break
178+
default:
179+
console.log("Invalid Action")
180+
}

0 commit comments

Comments
 (0)