demos/generate-site.lua
1#!/usr/bin/env lua
2
3-- Generate complete HTML site demonstration
4-- Creates a functional poetry website with actual content
5
6package.path = package.path .. ';./?.lua;./libs/?.lua;./src/html-generator/?.lua'
7
8local utils = require("libs.utils")
9local golden_collection = require("src.html-generator.golden-collection-generator")
10
11local DIR = "/mnt/mtwo/programming/ai-stuff/neocities-modernization"
12
13-- {{{ function create_sample_poems
14function create_sample_poems()
15 -- Create sample poems with proper golden poem flags
16 local poems_data = {
17 poems = {}
18 }
19
20 -- Add some regular poems
21 for i = 1, 10 do
22 local content = string.format("This is poem number %d. It contains meaningful poetry content that demonstrates the website functionality. Each poem tells a unique story and connects to the overall collection through similarity-based recommendations.", i)
23
24 poems_data.poems[i] = {
25 id = i,
26 title = string.format("Sample Poem %d", i),
27 content = content,
28 category = "fediverse",
29 character_count = string.len(content),
30 is_fediverse_golden = false
31 }
32 end
33
34 -- Add golden poems (exactly 1024 characters)
35 local golden_content_1 = "This is a golden poem designed to be exactly 1024 characters long for perfect fediverse sharing. It tells of morning light that dances through the trees, awakening the world with gentle grace. Each line flows like honey through time, carrying messages of hope and wonder. The characters count perfectly to the limit, showcasing the artistry of constrained writing. Golden words for golden moments, crafted with care for those who seek beauty in brevity. This poem represents the harmony between form and content, where every letter serves a purpose. The dawn breaks with promises of new beginnings, and through these verses we find connection across digital spaces. May this golden creation spark joy in hearts that read it, bridging distances with shared appreciation for poetry that fits precisely within the bounds we've chosen. Perfect length achieved through thoughtful selection of each word, each phrase, each moment of expression that builds toward completion."
36
37 local golden_content_2 = "Another golden poem reaching exactly 1024 characters, exploring digital landscapes where creativity meets constraint. In virtual realms we find new ways to express ancient truths about human experience. These golden verses represent the intersection of technology and art, where precise character limits become opportunities for innovation rather than restrictions. Through careful word choice and rhythmic flow, we craft messages that resonate across platforms and communities. The fediverse welcomes these perfectly sized creations, enabling seamless sharing of poetic content that respects both artistic integrity and technical requirements. Each poem becomes a bridge between individual expression and collective experience, fostering connections through shared appreciation of language and form. These digital dreams manifest as golden opportunities to practice the ancient art of constrained writing, where limitations inspire rather than limit creativity."
38
39 local golden_content_3 = "A third golden poem crafted with precision to meet the 1024 character requirement for optimal fediverse distribution. These network verses explore how poetry adapts to modern communication channels while maintaining its essential power to move hearts and minds. Through digital networks we share fragments of our inner lives, creating moments of connection that transcend physical boundaries. The golden constraint challenges poets to distill their thoughts into concentrated essences, where every word carries weight and meaning. This compression of language mirrors the way social networks compress human experience into manageable fragments, yet somehow retain the capacity to convey profound emotion and insight. In these perfectly sized verses we find the continuation of an ancient tradition in new forms, proving that poetry evolves with technology while preserving its core mission to illuminate the human condition with beauty and truth."
40
41 -- Add the golden poems
42 poems_data.poems[11] = {
43 id = 11,
44 title = "Golden Sunrise",
45 content = golden_content_1,
46 category = "fediverse",
47 character_count = 1024,
48 is_fediverse_golden = true,
49 similarity_score = 0.9
50 }
51
52 poems_data.poems[12] = {
53 id = 12,
54 title = "Digital Dreams",
55 content = golden_content_2,
56 category = "fediverse",
57 character_count = 1024,
58 is_fediverse_golden = true,
59 similarity_score = 0.8
60 }
61
62 poems_data.poems[13] = {
63 id = 13,
64 title = "Network Verses",
65 content = golden_content_3,
66 category = "messages",
67 character_count = 1024,
68 is_fediverse_golden = true,
69 similarity_score = 0.7
70 }
71
72 -- Add some poems from other categories
73 for i = 14, 20 do
74 local content = string.format("This is a %s poem number %d with interesting content that shows cross-category navigation.", i > 17 and "notes" or "messages", i)
75
76 poems_data.poems[i] = {
77 id = i,
78 title = string.format("Sample %s Poem %d", i > 17 and "Notes" or "Messages", i),
79 content = content,
80 category = i > 17 and "notes" or "messages",
81 character_count = string.len(content),
82 is_fediverse_golden = false
83 }
84 end
85
86 return poems_data
87end
88-- }}}
89
90-- {{{ function create_sample_similarity_data
91function create_sample_similarity_data(poems_data)
92 -- Create basic similarity data for demonstration
93 local similarity_data = {}
94
95 for poem_id, poem in pairs(poems_data.poems) do
96 similarity_data[tostring(poem_id)] = {}
97
98 -- Create similarity connections to other poems
99 for other_id, other_poem in pairs(poems_data.poems) do
100 if poem_id ~= other_id then
101 -- Golden poems get higher similarity scores with each other
102 local base_similarity = math.random() * 0.5 + 0.2
103
104 if poem.is_fediverse_golden and other_poem.is_fediverse_golden then
105 base_similarity = base_similarity + 0.3
106 elseif poem.category == other_poem.category then
107 base_similarity = base_similarity + 0.2
108 end
109
110 similarity_data[tostring(poem_id)][tostring(other_id)] = base_similarity
111 end
112 end
113 end
114
115 return similarity_data
116end
117-- }}}
118
119-- {{{ function generate_individual_poem_pages
120function generate_individual_poem_pages(poems_data, similarity_data, output_dir)
121 utils.log_info("Generating individual poem pages...")
122
123 local count = 0
124 for poem_id, poem in pairs(poems_data.poems) do
125 if poem and poem.content and poem.category then
126 -- Create poem page directory
127 local category_dir = string.format("%s/poems/%s", output_dir, poem.category)
128 os.execute("mkdir -p " .. category_dir)
129
130 -- Get similarity recommendations
131 local similar_poems = {}
132 local poem_similarities = similarity_data[tostring(poem_id)] or {}
133
134 -- Sort by similarity score
135 local sorted_similarities = {}
136 for other_id, score in pairs(poem_similarities) do
137 local other_poem = poems_data.poems[tonumber(other_id)]
138 if other_poem then
139 table.insert(sorted_similarities, {
140 id = tonumber(other_id),
141 poem = other_poem,
142 score = score
143 })
144 end
145 end
146
147 table.sort(sorted_similarities, function(a, b) return a.score > b.score end)
148
149 -- Take top 5 similar poems
150 for i = 1, math.min(5, #sorted_similarities) do
151 table.insert(similar_poems, sorted_similarities[i])
152 end
153
154 -- Generate poem page HTML
155 local template = [[<!DOCTYPE html>
156<html lang="en">
157<head>
158 <meta charset="UTF-8">
159 <meta name="viewport" content="width=device-width, initial-scale=1.0">
160 <title>{TITLE} - Poetry Collection</title>
161 <style>
162 body {
163 font-family: Georgia, serif;
164 line-height: 1.6;
165 margin: 0;
166 padding: 1rem;
167 max-width: 800px;
168 margin: 0 auto;
169 }
170
171 .poem-header {
172 text-align: center;
173 margin-bottom: 2rem;
174 padding-bottom: 1rem;
175 border-bottom: 2px solid #8b4513;
176 }
177
178 .poem-content {
179 background: #f9f9f9;
180 padding: 2rem;
181 border-radius: 8px;
182 margin: 2rem 0;
183 border-left: 4px solid #8b4513;
184 }
185
186 .golden-badge {
187 background: #ffd700;
188 color: #8b4513;
189 padding: 0.25rem 0.75rem;
190 border-radius: 20px;
191 font-size: 0.8rem;
192 font-weight: bold;
193 margin-left: 1rem;
194 }
195
196 .similar-poems {
197 margin-top: 3rem;
198 padding: 1.5rem;
199 background: #f0f8ff;
200 border-radius: 8px;
201 }
202
203 .similar-poems h3 {
204 color: #2c5282;
205 margin-bottom: 1rem;
206 }
207
208 .similar-poem-link {
209 display: block;
210 margin: 0.5rem 0;
211 padding: 0.5rem;
212 background: white;
213 border: 1px solid #e2e8f0;
214 border-radius: 4px;
215 text-decoration: none;
216 color: #333;
217 }
218
219 .similar-poem-link:hover {
220 background: #e6f3ff;
221 border-color: #8b4513;
222 }
223
224 .breadcrumb {
225 margin-bottom: 2rem;
226 color: #666;
227 }
228
229 .breadcrumb a {
230 color: #8b4513;
231 text-decoration: none;
232 }
233
234 @media (max-width: 768px) {
235 body { padding: 0.5rem; }
236 .poem-content { padding: 1rem; }
237 }
238 </style>
239</head>
240<body>
241 <nav class="breadcrumb">
242 <a href="../../index.html">Poetry Collection</a> >
243 <a href="../index.html">{CATEGORY_TITLE}</a> >
244 <span>{TITLE}</span>
245 </nav>
246
247 <div class="poem-header">
248 <h1>{TITLE}</h1>
249 {GOLDEN_BADGE}
250 <p>Category: <strong>{CATEGORY_TITLE}</strong> | Length: <strong>{CHARACTER_COUNT} characters</strong></p>
251 </div>
252
253 <div class="poem-content">
254 <p>{CONTENT}</p>
255 </div>
256
257 <div class="similar-poems">
258 <h3>🔗 Similar Poems</h3>
259 {SIMILAR_POEMS_HTML}
260 </div>
261</body>
262</html>]]
263
264 -- Build similar poems HTML
265 local similar_html = ""
266 for _, similar in ipairs(similar_poems) do
267 similar_html = similar_html .. string.format([[
268<a href="../%s/poem-%03d.html" class="similar-poem-link">
269 <strong>%s</strong><br>
270 <small>%s category • Similarity: %.1f%%</small>
271</a>]],
272 similar.poem.category,
273 similar.id,
274 similar.poem.title or ("Poem " .. similar.id),
275 similar.poem.category,
276 similar.score * 100
277 )
278 end
279
280 -- Substitute template variables (escape percent signs for safe gsub replacement)
281 local html = template
282 local safe_title = (poem.title or ("Poem " .. poem_id)):gsub("%%", "%%%%")
283 local safe_category = string.upper(string.sub(poem.category, 1, 1)) .. string.sub(poem.category, 2)
284 local safe_content = (poem.content or ""):gsub("%%", "%%%%")
285 local safe_similar_html = similar_html:gsub("%%", "%%%%")
286
287 html = html:gsub("{TITLE}", safe_title)
288 html = html:gsub("{CATEGORY_TITLE}", safe_category)
289 html = html:gsub("{CHARACTER_COUNT}", tostring(poem.character_count or 0))
290 html = html:gsub("{CONTENT}", safe_content)
291 html = html:gsub("{SIMILAR_POEMS_HTML}", safe_similar_html)
292
293 if poem.is_fediverse_golden then
294 html = html:gsub("{GOLDEN_BADGE}", '<span class="golden-badge">✨ Golden Poem</span>')
295 else
296 html = html:gsub("{GOLDEN_BADGE}", "")
297 end
298
299 -- Write poem page
300 local output_file = string.format("%s/poem-%03d.html", category_dir, poem_id)
301 local file = io.open(output_file, "w")
302 if file then
303 file:write(html)
304 file:close()
305 count = count + 1
306 end
307 end
308 end
309
310 utils.log_info(string.format("Generated %d individual poem pages", count))
311 return count
312end
313-- }}}
314
315-- {{{ Main execution
316function main()
317 utils.log_info("Generating complete HTML poetry website...")
318
319 local output_dir = DIR .. "/generated-site"
320
321 -- Create sample data
322 utils.log_info("Creating sample poem data...")
323 local poems_data = create_sample_poems()
324 local similarity_data = create_sample_similarity_data(poems_data)
325
326 -- Generate golden collection pages
327 utils.log_info("Generating golden poem collection pages...")
328 local results = golden_collection.generate_all_golden_collection_pages(
329 poems_data,
330 similarity_data,
331 output_dir
332 )
333
334 -- Generate individual poem pages
335 local poem_count = generate_individual_poem_pages(poems_data, similarity_data, output_dir)
336
337 -- Generate category index pages
338 local categories = {"fediverse", "messages", "notes"}
339 for _, category in ipairs(categories) do
340 local category_dir = string.format("%s/poems/%s", output_dir, category)
341 local index_file = category_dir .. "/index.html"
342
343 local category_poems = {}
344 for _, poem in pairs(poems_data.poems) do
345 if poem.category == category then
346 table.insert(category_poems, poem)
347 end
348 end
349
350 local index_html = string.format([[<!DOCTYPE html>
351<html lang="en">
352<head>
353 <meta charset="UTF-8">
354 <meta name="viewport" content="width=device-width, initial-scale=1.0">
355 <title>%s Poems - Poetry Collection</title>
356</head>
357<body>
358 <h1>%s Poetry Collection</h1>
359 <p>%d poems in this category</p>
360 <ul>]],
361 string.upper(string.sub(category, 1, 1)) .. string.sub(category, 2),
362 string.upper(string.sub(category, 1, 1)) .. string.sub(category, 2),
363 #category_poems
364 )
365
366 for _, poem in ipairs(category_poems) do
367 index_html = index_html .. string.format([[
368 <li><a href="poem-%03d.html">%s</a>%s</li>]],
369 poem.id,
370 poem.title or ("Poem " .. poem.id),
371 poem.is_fediverse_golden and " ✨" or ""
372 )
373 end
374
375 index_html = index_html .. [[
376 </ul>
377 <p><a href="../golden/">View Golden Poems Collection →</a></p>
378</body>
379</html>]]
380
381 local file = io.open(index_file, "w")
382 if file then
383 file:write(index_html)
384 file:close()
385 end
386 end
387
388 -- Generate main index
389 local main_index = output_dir .. "/index.html"
390 local main_html = [[<!DOCTYPE html>
391<html lang="en">
392<head>
393 <meta charset="UTF-8">
394 <meta name="viewport" content="width=device-width, initial-scale=1.0">
395 <title>Poetry Collection - Phase 3 Demo</title>
396 <style>
397 body {
398 font-family: Georgia, serif;
399 line-height: 1.6;
400 max-width: 800px;
401 margin: 0 auto;
402 padding: 1rem;
403 }
404
405 .hero {
406 text-align: center;
407 background: linear-gradient(135deg, #f0f8ff, #e6f3ff);
408 padding: 3rem 2rem;
409 border-radius: 12px;
410 margin: 2rem 0;
411 }
412
413 .categories {
414 display: grid;
415 grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
416 gap: 2rem;
417 margin: 2rem 0;
418 }
419
420 .category-card {
421 border: 2px solid #8b4513;
422 border-radius: 8px;
423 padding: 1.5rem;
424 text-align: center;
425 background: white;
426 transition: transform 0.3s ease;
427 }
428
429 .category-card:hover {
430 transform: translateY(-2px);
431 }
432
433 .category-card a {
434 color: #8b4513;
435 text-decoration: none;
436 font-weight: bold;
437 }
438 </style>
439</head>
440<body>
441 <div class="hero">
442 <h1>🎭 Poetry Collection</h1>
443 <p>Phase 3 Demonstration - Complete HTML Generation System</p>
444 <p><strong>20 sample poems</strong> with <strong>3 golden poems</strong> optimized for fediverse sharing</p>
445 </div>
446
447 <div class="categories">
448 <div class="category-card">
449 <h3><a href="poems/fediverse/">📱 Fediverse Poems</a></h3>
450 <p>13 poems including 2 golden poems</p>
451 </div>
452
453 <div class="category-card">
454 <h3><a href="poems/messages/">💬 Messages</a></h3>
455 <p>4 poems including 1 golden poem</p>
456 </div>
457
458 <div class="category-card">
459 <h3><a href="poems/notes/">📝 Notes</a></h3>
460 <p>3 poems</p>
461 </div>
462
463 <div class="category-card">
464 <h3><a href="poems/golden/">✨ Golden Collection</a></h3>
465 <p>3 poems exactly 1024 characters</p>
466 </div>
467 </div>
468
469 <footer style="margin-top: 3rem; text-align: center; color: #666;">
470 <p>Generated by Phase 3 HTML Generation System</p>
471 <p>Features: JavaScript-free, responsive design, similarity navigation</p>
472 </footer>
473</body>
474</html>]]
475
476 local file = io.open(main_index, "w")
477 if file then
478 file:write(main_html)
479 file:close()
480 end
481
482 -- Final summary
483 utils.log_info("HTML generation complete!")
484 utils.log_info(string.format("Generated site location: %s", output_dir))
485 utils.log_info(string.format("Total poem pages: %d", poem_count))
486 utils.log_info("Golden collection pages: 4")
487 utils.log_info("Category index pages: 3")
488 utils.log_info("Main index page: 1")
489
490 local total_files = poem_count + 4 + 3 + 1
491 utils.log_info(string.format("Total HTML files: %d", total_files))
492
493 return output_dir
494end
495
496main()
497-- }}}