Skip to content

Commit 1cb74d5

Browse files
authored
dev to main (#11)
* Update README.md * added tests to husky pre-commit * false test * useless space to test pre commit hook * updated pre-commit * math works now * Update build-and-deploy.yml * added rich text support * css yay
1 parent 58721c5 commit 1cb74d5

File tree

3 files changed

+245
-28
lines changed

3 files changed

+245
-28
lines changed

bun.lock

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"@contentful/rich-text-html-renderer": "^17.0.0",
88
"contentful": "^11.4.4",
99
"figlet": "^1.8.0",
10+
"fs": "^0.0.1-security",
1011
},
1112
"devDependencies": {
1213
"@types/bun": "^1.2.0",
@@ -111,6 +112,8 @@
111112

112113
"form-data": ["[email protected]", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "mime-types": "^2.1.12" } }, "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw=="],
113114

115+
"fs": ["[email protected]", "", {}, "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w=="],
116+
114117
"function-bind": ["[email protected]", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
115118

116119
"get-east-asian-width": ["[email protected]", "", {}, "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ=="],

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"dependencies": {
2525
"@contentful/rich-text-html-renderer": "^17.0.0",
2626
"contentful": "^11.4.4",
27-
"figlet": "^1.8.0"
27+
"figlet": "^1.8.0",
28+
"fs": "^0.0.1-security"
2829
}
2930
}

src/index.ts

+240-27
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,266 @@
11
import { mkdirSync, existsSync, writeFileSync } from 'fs';
22
import { fetchEntries } from './contentful';
33
import { documentToHtmlString } from '@contentful/rich-text-html-renderer';
4+
import { promises } from 'fs';
5+
46

57
// Ensure the 'dist' directory exists
68
if (!existsSync('dist')) {
79
mkdirSync('dist');
810
}
911

10-
// Fetch data from Contentful
11-
async function buildSite() {
12-
const entries = await fetchEntries('exampleContentModel');
12+
// Generate the main index.html with a navbar and links to individual blog posts
13+
async function buildMainPage(entries: any[]) {
14+
const navbarLinks = entries
15+
.map(
16+
(entry: any) => `
17+
<option value="post-${entry.sys.id}">${entry.fields.title}</option>
18+
`,
19+
)
20+
.join('');
21+
const css = `
22+
/* src/styles.css */
23+
24+
/* Mobile-first styles */
25+
body {
26+
font-family: 'Arial', sans-serif;
27+
padding: 20px;
28+
margin: 0;
29+
background-color: #f5f5f5;
30+
color: #333;
31+
}
32+
33+
h1 {
34+
font-size: 2.5rem;
35+
text-align: center;
36+
color: #007BFF;
37+
margin-bottom: 20px;
38+
}
39+
40+
header {
41+
margin-bottom: 30px;
42+
}
43+
44+
nav {
45+
text-align: center;
46+
margin-top: 10px;
47+
}
48+
49+
select {
50+
padding: 10px;
51+
font-size: 1rem;
52+
border: 2px solid #007BFF;
53+
border-radius: 5px;
54+
background-color: #fff;
55+
color: #333;
56+
cursor: pointer;
57+
transition: background-color 0.3s ease;
58+
}
59+
60+
select:hover {
61+
background-color: #f0f0f0;
62+
}
63+
64+
.entry {
65+
margin-bottom: 20px;
66+
padding: 20px;
67+
background-color: #fff;
68+
border-radius: 10px;
69+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
70+
transition: transform 0.3s ease;
71+
}
72+
73+
.entry:hover {
74+
transform: translateY(-5px);
75+
}
76+
77+
.entry h2 {
78+
font-size: 1.75rem;
79+
color: #007BFF;
80+
margin-bottom: 10px;
81+
}
82+
83+
.description {
84+
font-size: 1.1rem;
85+
color: #555;
86+
}
87+
88+
.entry a {
89+
text-decoration: none;
90+
color: inherit;
91+
transition: color 0.3s ease;
92+
}
93+
94+
.entry a:hover {
95+
color: #0056b3;
96+
}
97+
98+
/* Tablet and up */
99+
@media (min-width: 600px) {
100+
.entry {
101+
padding: 25px;
102+
}
103+
104+
.entry h2 {
105+
font-size: 2rem;
106+
}
107+
108+
.description {
109+
font-size: 1.2rem;
110+
}
111+
}
112+
113+
/* Desktop and up */
114+
@media (min-width: 1024px) {
115+
body {
116+
max-width: 1200px;
117+
margin: 0 auto;
118+
}
119+
120+
.entry {
121+
display: flex;
122+
flex-direction: row;
123+
justify-content: space-between;
124+
padding: 30px;
125+
}
126+
127+
.description {
128+
font-size: 1.3rem;
129+
}
130+
}
131+
132+
/* Post page styles */
133+
article {
134+
max-width: 800px;
135+
margin: 0 auto;
136+
padding: 20px;
137+
background-color: #fff;
138+
border-radius: 10px;
139+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
140+
}
141+
142+
article h2 {
143+
font-size: 2.5rem;
144+
color: #007BFF;
145+
margin-bottom: 20px;
146+
}
13147
148+
article .description {
149+
font-size: 1.2rem;
150+
line-height: 1.8;
151+
color: #555;
152+
}
153+
154+
a {
155+
color: #007BFF;
156+
text-decoration: none;
157+
font-weight: bold;
158+
transition: color 0.3s ease;
159+
}
160+
a:hover {
161+
color: #0056b3;
162+
}
163+
164+
`;
14165
// Generate simple HTML with Rich Text parsed to HTML
15166
const html = `
16167
<!DOCTYPE html>
17168
<html lang="en">
18169
<head>
19170
<meta charset="UTF-8" />
20171
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
21-
<title>Static Site</title>
22-
<style>
23-
body { font-family: Arial, sans-serif; padding: 20px; }
24-
.entry { margin-bottom: 20px; }
25-
.entry h2 { color: #333; }
26-
</style>
172+
<title>${Bun.env['DOMAIN']}</title>
173+
<link rel="stylesheet" href="styles.css" />
27174
</head>
28175
<body>
29-
<h1>My Static Site</h1>
30-
${entries
31-
.map((entry: any) => {
32-
const { title, description } = entry.fields;
33-
// Convert the rich text description to HTML
34-
const richTextHtml = documentToHtmlString(description);
35-
36-
return `
37-
<div class="entry">
38-
<h2>${title}</h2>
39-
<div class="description">${richTextHtml}</div>
40-
</div>
41-
`;
42-
})
43-
.join('')}
176+
<header>
177+
<h1>${Bun.env['DOMAIN']}</h1>
178+
<nav>
179+
<select onchange="window.location.href=this.value;">
180+
<option value="#">Select a Blog Post</option>
181+
${navbarLinks}
182+
</select>
183+
</nav>
184+
</header>
185+
<main>
186+
${entries
187+
.map((entry: any) => {
188+
const { title, description } = entry.fields;
189+
const postLink = `post-${entry.sys.id}.html`; // link to the individual post page
190+
// Convert the rich text description to HTML
191+
const richTextHtml = documentToHtmlString(description);
192+
193+
return `
194+
<div class="entry">
195+
<h2><a href="${postLink}">${title}</a></h2>
196+
<div class="description">${richTextHtml}</div>
197+
</div>
198+
`;
199+
})
200+
.join('')}
201+
</main>
44202
</body>
45203
</html>
46204
`;
47205

48-
// Write HTML to the output directory
206+
// Write the main page HTML to the output directory
49207
writeFileSync('dist/index.html', html);
50-
console.log('Static site built: dist/index.html');
208+
writeFileSync('dist/styles.css', css);
209+
console.log('Main page built: dist/index.html');
210+
}
211+
212+
// Generate a separate HTML page for each blog post
213+
async function buildPostPage(entry: any) {
214+
const { title, description } = entry.fields;
215+
const richTextHtml = documentToHtmlString(description);
216+
217+
const postHtml = `
218+
<!DOCTYPE html>
219+
<html lang="en">
220+
<head>
221+
<meta charset="UTF-8" />
222+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
223+
<title>${title}</title>
224+
<link rel="stylesheet" href="styles.css" />
225+
</head>
226+
<body>
227+
<header>
228+
<h1>${Bun.env['DOMAIN']}</h1>
229+
<nav>
230+
<a href="index.html">Home</a>
231+
</nav>
232+
</header>
233+
<main>
234+
<article>
235+
<h2>${title}</h2>
236+
<div class="description">${richTextHtml}</div>
237+
</article>
238+
</main>
239+
</body>
240+
</html>
241+
`;
242+
243+
// Write the individual blog post page to the output directory
244+
writeFileSync(`dist/post-${entry.sys.id}.html`, postHtml);
245+
console.log(`Post page built: dist/post-${entry.sys.id}.html`);
246+
}
247+
248+
// Fetch data from Contentful and generate the pages
249+
async function buildSite() {
250+
const entries = await fetchEntries('exampleContentModel');
251+
252+
// Build the main page with the navbar
253+
await buildMainPage(entries);
254+
255+
// Build individual pages for each blog post
256+
for (const entry of entries) {
257+
await buildPostPage(entry);
258+
}
259+
}
260+
261+
// Run the build process
262+
async function build() {
263+
await buildSite(); // Build the site
51264
}
52265

53-
buildSite().catch(console.error);
266+
build().catch(console.error);

0 commit comments

Comments
 (0)