Skip to content

Commit c734119

Browse files
authored
feat: implement word-editor script (#18)
This Pull request implement the `word-editor` script; the primary functionality of this script is to allowing adding new word, retrieve and update existing word which are individual `.mdx` files residing in the `src/pages/browse` directory of the project. This script avails us of all the helper functions required to perform this operations. ### Changes Made - Implemented the `writeNewWord` function - this function takes 3 params namely the `userOctokit`, `forkedRepoDetails`, and the `word`; it leverages the `userOctokit` instance to perform a write operation i.e. writing a new file (newWord.mdx) to a fork of our project on the user's account on behalf of the user through the `"PUT /repos/{owner}/{repo}/contents/{path}"` endpoint - Impelemented the `getExistingWord` function - this function helps retrieve data of existing words in the fork of our project on the user's account by calling the `"GET /repos/{owner}/{repo}/contents/{path}"` endpoint; it returns an object which carries the following properties that we are mostly interested in... - `title` - title of the the existing word - this infact is a custom appended data to the `response.data` from the call made to the endpoint - `path` - path to the existing word file - `sha` - unique SHA of the existing word - Implemented the `editExistingWord` function - this function takes 3 params namely the `userOctokit`, `forkedRepoDetails`, and the `word` (holds the properties: `path`, `sha`, `title` and `content`); it leverages the `userOctokit` instance to perform a edit operation i.e. updating the existing file on a fork of our project on the user's account on behalf of the user through thesame `"PUT /repos/{owner}/{repo}/contents/{path}"` endpoint - Implemented `writeFileContent` helper function - this function help write a content for our dictionary word file generating them from another added constant in the `src/lib/template/word.md.js` ### Screencast/Screenshot _too lazy to record a screencast for this one_ 😜, _but trust me_ 🤞 _the shit works_ 😮‍💨
1 parent 07f6f9d commit c734119

3 files changed

Lines changed: 116 additions & 0 deletions

File tree

src/lib/template/word.md.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default `---
2+
layout: ../../layouts/word.astro
3+
title: $title
4+
---
5+
6+
$content`

src/lib/utils/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,13 @@ export function getRepoParts(repoFullname) {
2121
repoOwner,
2222
repoName
2323
}
24+
}
25+
26+
/**
27+
* Normalize a string to something usable in url
28+
* @param {string} string
29+
* @returns {string}
30+
*/
31+
export function normalizeAsUrl(string) {
32+
return string.toLowerCase().replace(/\s+/g, "-");
2433
}

src/lib/word-editor.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import { getRepoParts, normalizeAsUrl } from "./utils/index.js";
2+
import wordFileTemplate from "./template/word.md.js";
3+
4+
/**
5+
* Write and add a new word to user's forked dictionary
6+
* @param {import("octokit").Octokit} userOctokit
7+
* @param {{ repoFullname: string, repoBranchRef: string }} forkedRepoDetails
8+
* @param {{ title: string, content: string }} word
9+
*/
10+
export async function writeNewWord(userOctokit, forkedRepoDetails, { title, content }) {
11+
const { repoFullname, repoBranchRef } = forkedRepoDetails;
12+
const { repoOwner, repoName } = getRepoParts(repoFullname);
13+
const branch = repoBranchRef.split("/").slice(2).join("/");
14+
const wordFileContent = writeWordFileContent(title, content);
15+
16+
try {
17+
const response = await userOctokit.request("PUT /repos/{owner}/{repo}/contents/{path}", {
18+
owner: repoOwner,
19+
repo: repoName,
20+
branch,
21+
path: `src/pages/browse/${normalizeAsUrl(title)}.mdx`,
22+
content: Buffer.from(wordFileContent).toString("base64"),
23+
message: `word: commit to "${title}"`
24+
});
25+
26+
return response.data
27+
} catch (error) {
28+
throw new Error(`error committing new word ${title} to dictionary`, { cause: error.message })
29+
}
30+
}
31+
32+
/**
33+
* Edit and update an existing word in user's forked dictionary
34+
* @param {import("octokit").Octokit} userOctokit
35+
* @param {{ repoFullname: string, repoBranchRef: string }} forkedRepoDetails
36+
* @param {{ path: string, sha: string, title: string, content: string }} word enter new content as value to `content` property
37+
*/
38+
export async function editExistingWord(userOctokit, forkedRepoDetails, { path, sha, title, content }) {
39+
const { repoFullname, repoBranchRef } = forkedRepoDetails;
40+
const { repoOwner, repoName } = getRepoParts(repoFullname);
41+
const branch = repoBranchRef.split("/").slice(2).join("/");
42+
const wordFileContent = writeWordFileContent(title, content);
43+
44+
try {
45+
const response = await userOctokit.request("PUT /repos/{owner}/{repo}/contents/{path}", {
46+
owner: repoOwner,
47+
repo: repoName,
48+
branch,
49+
path,
50+
content: Buffer.from(wordFileContent).toString("base64"),
51+
message: `word: edit commit to "${title}"`,
52+
sha
53+
});
54+
55+
return response.data;
56+
} catch (error) {
57+
throw new Error(`error committing edit to "${title}"`, { cause: error.message })
58+
}
59+
}
60+
61+
/**
62+
* Retrieve data for already existing word
63+
* @param {import("octokit").Octokit} userOctokit
64+
* @param {{ repoFullname: string, repoBranchRef: string }} forkedRepoDetails
65+
* @param {string} wordTitle
66+
*/
67+
export async function getExistingWord(userOctokit, forkedRepoDetails, wordTitle) {
68+
const { repoFullname, repoBranchRef } = forkedRepoDetails;
69+
const { repoOwner, repoName } = getRepoParts(repoFullname);
70+
71+
try {
72+
const response = await userOctokit.request("GET /repos/{owner}/{repo}/contents/{path}", {
73+
owner: repoOwner,
74+
repo: repoName,
75+
ref: repoBranchRef,
76+
path: `src/pages/browse/${normalizeAsUrl(wordTitle)}.mdx`,
77+
});
78+
79+
const { content, ...responseData } = response.data;
80+
81+
return {
82+
title: wordTitle,
83+
content,
84+
content_decoded: Buffer.from(content, "base64").toString("utf-8"),
85+
...responseData
86+
};
87+
} catch (error) {
88+
throw new Error(`error getting "${wordTitle}" from dictionary`, { cause: error.message })
89+
}
90+
}
91+
92+
/**
93+
* Write word file content using pre-defined template
94+
* @param {string} title
95+
* @param {string} content
96+
* @returns {string}
97+
*/
98+
function writeWordFileContent(title, content) {
99+
const file = wordFileTemplate;
100+
return file.replace("$title", title).replace("$content", content);
101+
}

0 commit comments

Comments
 (0)