@terrymooreii/sia 2.0.1 → 2.1.0

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/_config.yml CHANGED
@@ -4,6 +4,8 @@ site:
4
4
  url: "http://localhost:3000"
5
5
  author: "Terry Moore II"
6
6
 
7
+ theme: main
8
+
7
9
  input: src
8
10
  output: dist
9
11
 
@@ -7,7 +7,7 @@
7
7
  </div>
8
8
 
9
9
  <footer class="note-footer">
10
- <time datetime="{{ page.date | date('iso') }}">{{ page.date | date('full') }}</time>
10
+ <time datetime="{{ page.date | date('iso') }}">{{ page.date | date('full_time') }}</time>
11
11
  {% if page.tags and page.tags.length %}
12
12
  <span class="note-tags">
13
13
  {% for tag in page.tags %}
@@ -48,7 +48,7 @@
48
48
  <article class="note-card">
49
49
  <div class="note-card-content">{{ note.excerpt }}</div>
50
50
  <footer class="note-card-footer">
51
- <time datetime="{{ note.date | date('iso') }}">{{ note.date | date('short') }}</time>
51
+ <time datetime="{{ note.date | date('iso') }}">{{ note.date | date('full_time') }}</time>
52
52
  <a href="{{ note.url }}" class="note-card-link">View →</a>
53
53
  </footer>
54
54
  </article>
@@ -13,7 +13,7 @@
13
13
  {{ note.content | safe }}
14
14
  </div>
15
15
  <footer class="note-item-footer">
16
- <time datetime="{{ note.date | date('iso') }}">{{ note.date | date('full') }}</time>
16
+ <time datetime="{{ note.date | date('iso') }}">{{ note.date | date('full_time') }}</time>
17
17
  {% if note.tags and note.tags.length %}
18
18
  <div class="note-item-tags">
19
19
  {% for tag in note.tags %}
@@ -250,7 +250,6 @@ img {
250
250
  .hero {
251
251
  text-align: center;
252
252
  padding: var(--spacing-3xl) 0;
253
- border-bottom: 1px solid var(--color-border-light);
254
253
  margin-bottom: var(--spacing-2xl);
255
254
  }
256
255
 
@@ -0,0 +1,1033 @@
1
+ /* Sia - Minimal Theme
2
+ * A clean, simple theme with excellent readability
3
+ * Near-white light mode, near-black dark mode
4
+ */
5
+
6
+ /* ===== CSS Variables ===== */
7
+ :root {
8
+ /* Light Mode Colors (default) - Near white */
9
+ --color-bg: #fefefe;
10
+ --color-bg-alt: #ffffff;
11
+ --color-text: #1a1a1a;
12
+ --color-text-muted: #555555;
13
+ --color-text-light: #888888;
14
+ --color-primary: #0066cc;
15
+ --color-primary-hover: #004999;
16
+ --color-border: #e0e0e0;
17
+ --color-border-light: #f0f0f0;
18
+ --color-accent: #cc4400;
19
+ --color-code-bg: #f5f5f5;
20
+
21
+ /* Typography - Classic, readable fonts */
22
+ --font-sans: 'Helvetica Neue', Helvetica, Arial, sans-serif;
23
+ --font-serif: Georgia, 'Times New Roman', serif;
24
+ --font-mono: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
25
+
26
+ /* Sizing */
27
+ --container-width: 680px;
28
+ --container-wide: 960px;
29
+ --spacing-xs: 0.25rem;
30
+ --spacing-sm: 0.5rem;
31
+ --spacing-md: 1rem;
32
+ --spacing-lg: 1.5rem;
33
+ --spacing-xl: 2rem;
34
+ --spacing-2xl: 3rem;
35
+ --spacing-3xl: 4rem;
36
+
37
+ /* Border Radius - Subtle */
38
+ --radius-sm: 3px;
39
+ --radius-md: 4px;
40
+ --radius-lg: 6px;
41
+
42
+ /* Shadows - Very subtle */
43
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
44
+ --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.06);
45
+ }
46
+
47
+ /* Dark Mode Colors - Near black */
48
+ [data-theme="dark"] {
49
+ --color-bg: #0a0a0a;
50
+ --color-bg-alt: #111111;
51
+ --color-text: #e8e8e8;
52
+ --color-text-muted: #a0a0a0;
53
+ --color-text-light: #707070;
54
+ --color-primary: #4da6ff;
55
+ --color-primary-hover: #80c0ff;
56
+ --color-border: #2a2a2a;
57
+ --color-border-light: #1a1a1a;
58
+ --color-accent: #ff8844;
59
+ --color-code-bg: #151515;
60
+
61
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2);
62
+ --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.3);
63
+ }
64
+
65
+ /* ===== Reset & Base ===== */
66
+ *, *::before, *::after {
67
+ box-sizing: border-box;
68
+ }
69
+
70
+ html {
71
+ font-size: 17px;
72
+ line-height: 1.7;
73
+ -webkit-font-smoothing: antialiased;
74
+ -moz-osx-font-smoothing: grayscale;
75
+ }
76
+
77
+ body {
78
+ margin: 0;
79
+ padding: 0;
80
+ font-family: var(--font-sans);
81
+ color: var(--color-text);
82
+ background-color: var(--color-bg);
83
+ min-height: 100vh;
84
+ display: flex;
85
+ flex-direction: column;
86
+ }
87
+
88
+ a {
89
+ color: var(--color-primary);
90
+ text-decoration: none;
91
+ }
92
+
93
+ a:hover {
94
+ text-decoration: underline;
95
+ }
96
+
97
+ img {
98
+ max-width: 100%;
99
+ height: auto;
100
+ display: block;
101
+ }
102
+
103
+ /* ===== Layout ===== */
104
+ .container {
105
+ width: 100%;
106
+ max-width: var(--container-width);
107
+ margin: 0 auto;
108
+ padding: 0 var(--spacing-lg);
109
+ }
110
+
111
+ .container-wide {
112
+ max-width: var(--container-wide);
113
+ }
114
+
115
+ .main {
116
+ flex: 1;
117
+ padding: var(--spacing-2xl) 0 var(--spacing-3xl);
118
+ max-width: var(--container-width);
119
+ margin: 0 auto;
120
+ width: 100%;
121
+ padding-left: var(--spacing-lg);
122
+ padding-right: var(--spacing-lg);
123
+ }
124
+
125
+ /* ===== Header ===== */
126
+ .site-header {
127
+ border-bottom: 1px solid var(--color-border);
128
+ padding: var(--spacing-lg) 0;
129
+ }
130
+
131
+ .site-header .container {
132
+ display: flex;
133
+ align-items: center;
134
+ justify-content: space-between;
135
+ max-width: var(--container-wide);
136
+ }
137
+
138
+ .site-logo {
139
+ font-size: 1.125rem;
140
+ font-weight: 600;
141
+ color: var(--color-text);
142
+ letter-spacing: -0.01em;
143
+ }
144
+
145
+ .site-logo:hover {
146
+ color: var(--color-primary);
147
+ text-decoration: none;
148
+ }
149
+
150
+ .site-nav {
151
+ display: flex;
152
+ gap: var(--spacing-lg);
153
+ align-items: center;
154
+ }
155
+
156
+ .nav-link {
157
+ color: var(--color-text-muted);
158
+ font-size: 0.9rem;
159
+ }
160
+
161
+ .nav-link:hover {
162
+ color: var(--color-text);
163
+ text-decoration: none;
164
+ }
165
+
166
+ .nav-link.active {
167
+ color: var(--color-text);
168
+ }
169
+
170
+ /* Theme Toggle Button */
171
+ .theme-toggle {
172
+ display: flex;
173
+ align-items: center;
174
+ justify-content: center;
175
+ width: 32px;
176
+ height: 32px;
177
+ padding: 0;
178
+ background: transparent;
179
+ border: 1px solid var(--color-border);
180
+ border-radius: var(--radius-sm);
181
+ cursor: pointer;
182
+ color: var(--color-text-muted);
183
+ margin-left: var(--spacing-sm);
184
+ }
185
+
186
+ .theme-toggle:hover {
187
+ color: var(--color-text);
188
+ border-color: var(--color-text-muted);
189
+ }
190
+
191
+ /* Light mode: show moon, hide sun */
192
+ .theme-toggle .icon-sun {
193
+ display: none;
194
+ }
195
+
196
+ .theme-toggle .icon-moon {
197
+ display: block;
198
+ }
199
+
200
+ /* Dark mode: show sun, hide moon */
201
+ [data-theme="dark"] .theme-toggle .icon-sun {
202
+ display: block;
203
+ }
204
+
205
+ [data-theme="dark"] .theme-toggle .icon-moon {
206
+ display: none;
207
+ }
208
+
209
+ /* ===== Footer ===== */
210
+ .site-footer {
211
+ border-top: 1px solid var(--color-border);
212
+ padding: var(--spacing-lg) 0;
213
+ margin-top: auto;
214
+ }
215
+
216
+ .site-footer .container {
217
+ max-width: var(--container-wide);
218
+ display: flex;
219
+ align-items: center;
220
+ justify-content: space-between;
221
+ }
222
+
223
+ .footer-text {
224
+ color: var(--color-text-muted);
225
+ font-size: 0.85rem;
226
+ margin: 0;
227
+ }
228
+
229
+ .footer-nav {
230
+ display: flex;
231
+ gap: var(--spacing-lg);
232
+ }
233
+
234
+ .footer-link {
235
+ color: var(--color-text-muted);
236
+ font-size: 0.85rem;
237
+ }
238
+
239
+ .footer-link:hover {
240
+ color: var(--color-text);
241
+ }
242
+
243
+ /* ===== Hero ===== */
244
+ .hero {
245
+ text-align: center;
246
+ padding: var(--spacing-3xl) 0;
247
+ margin-bottom: var(--spacing-2xl);
248
+ }
249
+
250
+ .hero-title {
251
+ font-size: 2rem;
252
+ font-weight: 600;
253
+ letter-spacing: -0.02em;
254
+ margin: 0 0 var(--spacing-sm);
255
+ color: var(--color-text);
256
+ }
257
+
258
+ .hero-description {
259
+ font-size: 1.1rem;
260
+ color: var(--color-text-muted);
261
+ margin: 0;
262
+ }
263
+
264
+ /* ===== Sections ===== */
265
+ .section {
266
+ margin-bottom: var(--spacing-3xl);
267
+ }
268
+
269
+ .section-header {
270
+ display: flex;
271
+ align-items: baseline;
272
+ justify-content: space-between;
273
+ margin-bottom: var(--spacing-lg);
274
+ padding-bottom: var(--spacing-sm);
275
+ border-bottom: 1px solid var(--color-border-light);
276
+ }
277
+
278
+ .section-title {
279
+ font-size: 1.1rem;
280
+ font-weight: 600;
281
+ margin: 0;
282
+ color: var(--color-text);
283
+ }
284
+
285
+ .section-link {
286
+ font-size: 0.85rem;
287
+ color: var(--color-text-muted);
288
+ }
289
+
290
+ /* ===== Page Header ===== */
291
+ .page-header {
292
+ margin-bottom: var(--spacing-2xl);
293
+ }
294
+
295
+ .page-title {
296
+ font-size: 1.75rem;
297
+ font-weight: 600;
298
+ letter-spacing: -0.02em;
299
+ margin: 0 0 var(--spacing-xs);
300
+ }
301
+
302
+ .page-description {
303
+ color: var(--color-text-muted);
304
+ margin: 0;
305
+ }
306
+
307
+ /* ===== Post Card ===== */
308
+ .post-list {
309
+ display: flex;
310
+ flex-direction: column;
311
+ gap: var(--spacing-xl);
312
+ }
313
+
314
+ .post-card {
315
+ padding-bottom: var(--spacing-xl);
316
+ border-bottom: 1px solid var(--color-border-light);
317
+ }
318
+
319
+ .post-card:last-child {
320
+ border-bottom: none;
321
+ }
322
+
323
+ .post-card-title {
324
+ font-size: 1.25rem;
325
+ font-weight: 600;
326
+ margin: 0 0 var(--spacing-xs);
327
+ line-height: 1.4;
328
+ }
329
+
330
+ .post-card-title a {
331
+ color: var(--color-text);
332
+ }
333
+
334
+ .post-card-title a:hover {
335
+ color: var(--color-primary);
336
+ text-decoration: none;
337
+ }
338
+
339
+ .post-card-meta {
340
+ display: flex;
341
+ align-items: center;
342
+ gap: var(--spacing-md);
343
+ font-size: 0.85rem;
344
+ color: var(--color-text-muted);
345
+ margin-bottom: var(--spacing-sm);
346
+ }
347
+
348
+ .post-card-reading-time::before {
349
+ content: '·';
350
+ margin-right: var(--spacing-md);
351
+ }
352
+
353
+ .post-card-tags {
354
+ display: flex;
355
+ flex-wrap: wrap;
356
+ gap: var(--spacing-xs);
357
+ margin-bottom: var(--spacing-sm);
358
+ }
359
+
360
+ .post-card-excerpt {
361
+ color: var(--color-text-muted);
362
+ margin: 0 0 var(--spacing-sm);
363
+ line-height: 1.6;
364
+ }
365
+
366
+ .post-card-link {
367
+ font-size: 0.9rem;
368
+ }
369
+
370
+ /* ===== Post Detail ===== */
371
+ .post-header {
372
+ margin-bottom: var(--spacing-2xl);
373
+ }
374
+
375
+ .post-title {
376
+ font-size: 1.875rem;
377
+ font-weight: 600;
378
+ letter-spacing: -0.02em;
379
+ margin: 0 0 var(--spacing-md);
380
+ line-height: 1.3;
381
+ }
382
+
383
+ .post-meta {
384
+ display: flex;
385
+ align-items: center;
386
+ flex-wrap: wrap;
387
+ gap: var(--spacing-sm);
388
+ color: var(--color-text-muted);
389
+ font-size: 0.9rem;
390
+ }
391
+
392
+ .post-meta-divider {
393
+ color: var(--color-text-light);
394
+ }
395
+
396
+ .post-tags a {
397
+ color: var(--color-text-muted);
398
+ }
399
+
400
+ .post-tags a:hover {
401
+ color: var(--color-primary);
402
+ }
403
+
404
+ .post-content {
405
+ margin-bottom: var(--spacing-2xl);
406
+ }
407
+
408
+ .post-footer {
409
+ padding-top: var(--spacing-xl);
410
+ border-top: 1px solid var(--color-border-light);
411
+ }
412
+
413
+ .post-tags-footer {
414
+ display: flex;
415
+ align-items: center;
416
+ flex-wrap: wrap;
417
+ gap: var(--spacing-sm);
418
+ margin-bottom: var(--spacing-lg);
419
+ }
420
+
421
+ .tags-label {
422
+ color: var(--color-text-muted);
423
+ font-size: 0.85rem;
424
+ }
425
+
426
+ .post-nav {
427
+ display: flex;
428
+ gap: var(--spacing-md);
429
+ }
430
+
431
+ /* ===== Notes ===== */
432
+ .notes-grid {
433
+ display: grid;
434
+ gap: var(--spacing-lg);
435
+ }
436
+
437
+ .note-card {
438
+ background: var(--color-bg-alt);
439
+ border: 1px solid var(--color-border);
440
+ border-radius: var(--radius-md);
441
+ padding: var(--spacing-lg);
442
+ }
443
+
444
+ .note-card-content {
445
+ margin-bottom: var(--spacing-md);
446
+ color: var(--color-text);
447
+ }
448
+
449
+ .note-card-footer {
450
+ display: flex;
451
+ align-items: center;
452
+ justify-content: space-between;
453
+ font-size: 0.85rem;
454
+ color: var(--color-text-muted);
455
+ }
456
+
457
+ .notes-stream {
458
+ display: flex;
459
+ flex-direction: column;
460
+ gap: var(--spacing-xl);
461
+ }
462
+
463
+ .note-item {
464
+ padding-bottom: var(--spacing-xl);
465
+ border-bottom: 1px solid var(--color-border-light);
466
+ }
467
+
468
+ .note-item:last-child {
469
+ border-bottom: none;
470
+ }
471
+
472
+ .note-item-content {
473
+ margin-bottom: var(--spacing-md);
474
+ }
475
+
476
+ .note-item-footer {
477
+ display: flex;
478
+ align-items: center;
479
+ gap: var(--spacing-md);
480
+ font-size: 0.85rem;
481
+ color: var(--color-text-muted);
482
+ }
483
+
484
+ .note-item-permalink {
485
+ margin-left: auto;
486
+ color: var(--color-text-light);
487
+ }
488
+
489
+ .note-footer {
490
+ display: flex;
491
+ align-items: center;
492
+ gap: var(--spacing-md);
493
+ font-size: 0.85rem;
494
+ color: var(--color-text-muted);
495
+ margin-top: var(--spacing-lg);
496
+ }
497
+
498
+ .note-nav {
499
+ margin-top: var(--spacing-xl);
500
+ }
501
+
502
+ /* ===== Tags ===== */
503
+ .tag {
504
+ display: inline-flex;
505
+ align-items: center;
506
+ background: var(--color-border-light);
507
+ color: var(--color-text-muted);
508
+ padding: 2px var(--spacing-sm);
509
+ border-radius: var(--radius-sm);
510
+ font-size: 0.8rem;
511
+ }
512
+
513
+ .tag:hover {
514
+ background: var(--color-primary);
515
+ color: white;
516
+ text-decoration: none;
517
+ }
518
+
519
+ .tag.active {
520
+ background: var(--color-primary);
521
+ color: white;
522
+ }
523
+
524
+ .tag-sm {
525
+ padding: 1px var(--spacing-xs);
526
+ font-size: 0.75rem;
527
+ }
528
+
529
+ .tag-count {
530
+ opacity: 0.7;
531
+ margin-left: var(--spacing-xs);
532
+ }
533
+
534
+ .tag-cloud {
535
+ display: flex;
536
+ flex-wrap: wrap;
537
+ gap: var(--spacing-sm);
538
+ margin-bottom: var(--spacing-2xl);
539
+ }
540
+
541
+ .tag-lg {
542
+ font-size: 0.95rem;
543
+ padding: var(--spacing-xs) var(--spacing-sm);
544
+ }
545
+
546
+ .tag-md {
547
+ font-size: 0.875rem;
548
+ }
549
+
550
+ .tags-page {
551
+ /* Tags page layout */
552
+ }
553
+
554
+ .tags-detail {
555
+ /* Tag detail sections */
556
+ }
557
+
558
+ .tag-section {
559
+ margin-bottom: var(--spacing-xl);
560
+ padding-bottom: var(--spacing-lg);
561
+ border-bottom: 1px solid var(--color-border-light);
562
+ }
563
+
564
+ .tag-section:last-child {
565
+ border-bottom: none;
566
+ }
567
+
568
+ .tag-section-title {
569
+ font-size: 1.05rem;
570
+ font-weight: 600;
571
+ margin: 0 0 var(--spacing-md);
572
+ }
573
+
574
+ .tag-section-title a {
575
+ color: var(--color-text);
576
+ }
577
+
578
+ .tag-section-title a:hover {
579
+ color: var(--color-primary);
580
+ }
581
+
582
+ .tag-section-count {
583
+ color: var(--color-text-muted);
584
+ font-weight: 400;
585
+ }
586
+
587
+ .tag-posts {
588
+ list-style: none;
589
+ margin: 0;
590
+ padding: 0;
591
+ }
592
+
593
+ .tag-posts li {
594
+ display: flex;
595
+ align-items: baseline;
596
+ justify-content: space-between;
597
+ padding: var(--spacing-xs) 0;
598
+ }
599
+
600
+ .tag-posts time {
601
+ color: var(--color-text-light);
602
+ font-size: 0.85rem;
603
+ flex-shrink: 0;
604
+ margin-left: var(--spacing-md);
605
+ }
606
+
607
+ .more-link {
608
+ font-size: 0.85rem;
609
+ color: var(--color-text-muted);
610
+ }
611
+
612
+ /* ===== Pagination ===== */
613
+ .pagination {
614
+ display: flex;
615
+ align-items: center;
616
+ justify-content: space-between;
617
+ margin-top: var(--spacing-2xl);
618
+ padding-top: var(--spacing-lg);
619
+ border-top: 1px solid var(--color-border-light);
620
+ }
621
+
622
+ .pagination-info {
623
+ color: var(--color-text-muted);
624
+ font-size: 0.85rem;
625
+ }
626
+
627
+ .pagination-links {
628
+ display: flex;
629
+ gap: var(--spacing-md);
630
+ }
631
+
632
+ .pagination-link {
633
+ padding: var(--spacing-xs) var(--spacing-md);
634
+ border: 1px solid var(--color-border);
635
+ border-radius: var(--radius-sm);
636
+ font-size: 0.85rem;
637
+ color: var(--color-text);
638
+ }
639
+
640
+ .pagination-link:hover:not(.disabled) {
641
+ background: var(--color-primary);
642
+ border-color: var(--color-primary);
643
+ color: white;
644
+ text-decoration: none;
645
+ }
646
+
647
+ .pagination-link.disabled {
648
+ color: var(--color-text-light);
649
+ cursor: not-allowed;
650
+ opacity: 0.5;
651
+ }
652
+
653
+ /* ===== Buttons ===== */
654
+ .btn {
655
+ display: inline-flex;
656
+ align-items: center;
657
+ justify-content: center;
658
+ padding: var(--spacing-sm) var(--spacing-lg);
659
+ border-radius: var(--radius-sm);
660
+ font-size: 0.9rem;
661
+ cursor: pointer;
662
+ text-decoration: none;
663
+ }
664
+
665
+ .btn-primary {
666
+ background: var(--color-primary);
667
+ color: white;
668
+ border: 1px solid var(--color-primary);
669
+ }
670
+
671
+ .btn-primary:hover {
672
+ background: var(--color-primary-hover);
673
+ border-color: var(--color-primary-hover);
674
+ color: white;
675
+ text-decoration: none;
676
+ }
677
+
678
+ .btn-secondary {
679
+ background: transparent;
680
+ color: var(--color-text);
681
+ border: 1px solid var(--color-border);
682
+ }
683
+
684
+ .btn-secondary:hover {
685
+ background: var(--color-border-light);
686
+ color: var(--color-text);
687
+ text-decoration: none;
688
+ }
689
+
690
+ /* ===== Prose (Content Styling) ===== */
691
+ .prose {
692
+ line-height: 1.8;
693
+ }
694
+
695
+ .prose h1,
696
+ .prose h2,
697
+ .prose h3,
698
+ .prose h4,
699
+ .prose h5,
700
+ .prose h6 {
701
+ margin-top: 1.75em;
702
+ margin-bottom: 0.5em;
703
+ font-weight: 600;
704
+ line-height: 1.3;
705
+ }
706
+
707
+ .prose h1 { font-size: 1.75rem; }
708
+ .prose h2 { font-size: 1.4rem; }
709
+ .prose h3 { font-size: 1.15rem; }
710
+ .prose h4 { font-size: 1rem; }
711
+
712
+ .prose h1:first-child,
713
+ .prose h2:first-child,
714
+ .prose h3:first-child {
715
+ margin-top: 0;
716
+ }
717
+
718
+ .prose p {
719
+ margin: 0 0 1.25em;
720
+ }
721
+
722
+ .prose ul,
723
+ .prose ol {
724
+ margin: 0 0 1.25em;
725
+ padding-left: 1.5em;
726
+ }
727
+
728
+ .prose li {
729
+ margin-bottom: 0.35em;
730
+ }
731
+
732
+ .prose blockquote {
733
+ margin: 1.5em 0;
734
+ padding: 0 0 0 1.25em;
735
+ border-left: 2px solid var(--color-border);
736
+ color: var(--color-text-muted);
737
+ }
738
+
739
+ .prose blockquote p:last-child {
740
+ margin-bottom: 0;
741
+ }
742
+
743
+ .prose pre {
744
+ background: var(--color-code-bg);
745
+ border: 1px solid var(--color-border);
746
+ border-radius: var(--radius-md);
747
+ padding: var(--spacing-md);
748
+ overflow-x: auto;
749
+ font-family: var(--font-mono);
750
+ font-size: 0.85rem;
751
+ line-height: 1.5;
752
+ margin: 1.25em 0;
753
+ }
754
+
755
+ .prose code {
756
+ font-family: var(--font-mono);
757
+ font-size: 0.9em;
758
+ background: var(--color-code-bg);
759
+ padding: 0.15em 0.35em;
760
+ border-radius: var(--radius-sm);
761
+ }
762
+
763
+ .prose pre code {
764
+ background: none;
765
+ padding: 0;
766
+ font-size: inherit;
767
+ }
768
+
769
+ .prose img {
770
+ margin: 1.25em 0;
771
+ border-radius: var(--radius-md);
772
+ }
773
+
774
+ .prose a {
775
+ text-decoration: underline;
776
+ text-decoration-color: var(--color-border);
777
+ text-underline-offset: 2px;
778
+ }
779
+
780
+ .prose a:hover {
781
+ text-decoration-color: var(--color-primary);
782
+ }
783
+
784
+ .prose hr {
785
+ border: none;
786
+ border-top: 1px solid var(--color-border);
787
+ margin: 2em 0;
788
+ }
789
+
790
+ .prose table {
791
+ width: 100%;
792
+ border-collapse: collapse;
793
+ margin: 1.25em 0;
794
+ font-size: 0.9rem;
795
+ }
796
+
797
+ .prose th,
798
+ .prose td {
799
+ padding: var(--spacing-sm) var(--spacing-md);
800
+ border: 1px solid var(--color-border);
801
+ text-align: left;
802
+ }
803
+
804
+ .prose th {
805
+ background: var(--color-border-light);
806
+ font-weight: 600;
807
+ }
808
+
809
+ /* ===== Empty State ===== */
810
+ .empty-message {
811
+ text-align: center;
812
+ padding: var(--spacing-2xl) var(--spacing-lg);
813
+ color: var(--color-text-muted);
814
+ background: var(--color-code-bg);
815
+ border: 1px solid var(--color-border);
816
+ border-radius: var(--radius-md);
817
+ }
818
+
819
+ .empty-message code {
820
+ background: var(--color-bg-alt);
821
+ padding: 0.15em 0.35em;
822
+ border-radius: var(--radius-sm);
823
+ font-size: 0.9em;
824
+ }
825
+
826
+ /* ===== Responsive ===== */
827
+ @media (max-width: 768px) {
828
+ html {
829
+ font-size: 16px;
830
+ }
831
+
832
+ .site-header .container {
833
+ flex-direction: column;
834
+ gap: var(--spacing-md);
835
+ }
836
+
837
+ .site-nav {
838
+ gap: var(--spacing-md);
839
+ flex-wrap: wrap;
840
+ justify-content: center;
841
+ }
842
+
843
+ .theme-toggle {
844
+ margin-left: 0;
845
+ }
846
+
847
+ .site-footer .container {
848
+ flex-direction: column;
849
+ gap: var(--spacing-md);
850
+ text-align: center;
851
+ }
852
+
853
+ .hero {
854
+ padding: var(--spacing-2xl) 0;
855
+ }
856
+
857
+ .hero-title {
858
+ font-size: 1.75rem;
859
+ }
860
+
861
+ .post-title {
862
+ font-size: 1.5rem;
863
+ }
864
+
865
+ .pagination {
866
+ flex-direction: column;
867
+ gap: var(--spacing-md);
868
+ }
869
+ }
870
+
871
+ /* ===== Syntax Highlighting (Light Mode) ===== */
872
+ .hljs {
873
+ color: #1a1a1a;
874
+ background: var(--color-code-bg);
875
+ }
876
+
877
+ .hljs-comment,
878
+ .hljs-quote {
879
+ color: #6a6a6a;
880
+ font-style: italic;
881
+ }
882
+
883
+ .hljs-keyword,
884
+ .hljs-selector-tag,
885
+ .hljs-subst {
886
+ color: #9d0006;
887
+ }
888
+
889
+ .hljs-number,
890
+ .hljs-literal,
891
+ .hljs-variable,
892
+ .hljs-template-variable,
893
+ .hljs-tag .hljs-attr {
894
+ color: #0066cc;
895
+ }
896
+
897
+ .hljs-string,
898
+ .hljs-doctag {
899
+ color: #0a5c0a;
900
+ }
901
+
902
+ .hljs-title,
903
+ .hljs-section,
904
+ .hljs-selector-id {
905
+ color: #6c3fc1;
906
+ font-weight: 600;
907
+ }
908
+
909
+ .hljs-type,
910
+ .hljs-class .hljs-title {
911
+ color: #6c3fc1;
912
+ }
913
+
914
+ .hljs-tag,
915
+ .hljs-name,
916
+ .hljs-attribute {
917
+ color: #0066cc;
918
+ }
919
+
920
+ .hljs-regexp,
921
+ .hljs-link {
922
+ color: #0a5c0a;
923
+ }
924
+
925
+ .hljs-symbol,
926
+ .hljs-bullet {
927
+ color: #cc4400;
928
+ }
929
+
930
+ .hljs-built_in,
931
+ .hljs-builtin-name {
932
+ color: #0066cc;
933
+ }
934
+
935
+ .hljs-meta {
936
+ color: #6a6a6a;
937
+ }
938
+
939
+ .hljs-deletion {
940
+ color: #9d0006;
941
+ background-color: #ffeef0;
942
+ }
943
+
944
+ .hljs-addition {
945
+ color: #0a5c0a;
946
+ background-color: #e6ffed;
947
+ }
948
+
949
+ .hljs-emphasis {
950
+ font-style: italic;
951
+ }
952
+
953
+ .hljs-strong {
954
+ font-weight: 600;
955
+ }
956
+
957
+ /* ===== Syntax Highlighting (Dark Mode) ===== */
958
+ [data-theme="dark"] .hljs {
959
+ color: #e8e8e8;
960
+ background: var(--color-code-bg);
961
+ }
962
+
963
+ [data-theme="dark"] .hljs-comment,
964
+ [data-theme="dark"] .hljs-quote {
965
+ color: #808080;
966
+ }
967
+
968
+ [data-theme="dark"] .hljs-keyword,
969
+ [data-theme="dark"] .hljs-selector-tag,
970
+ [data-theme="dark"] .hljs-subst {
971
+ color: #ff6b6b;
972
+ }
973
+
974
+ [data-theme="dark"] .hljs-number,
975
+ [data-theme="dark"] .hljs-literal,
976
+ [data-theme="dark"] .hljs-variable,
977
+ [data-theme="dark"] .hljs-template-variable,
978
+ [data-theme="dark"] .hljs-tag .hljs-attr {
979
+ color: #4da6ff;
980
+ }
981
+
982
+ [data-theme="dark"] .hljs-string,
983
+ [data-theme="dark"] .hljs-doctag {
984
+ color: #98c379;
985
+ }
986
+
987
+ [data-theme="dark"] .hljs-title,
988
+ [data-theme="dark"] .hljs-section,
989
+ [data-theme="dark"] .hljs-selector-id {
990
+ color: #c792ea;
991
+ font-weight: 600;
992
+ }
993
+
994
+ [data-theme="dark"] .hljs-type,
995
+ [data-theme="dark"] .hljs-class .hljs-title {
996
+ color: #c792ea;
997
+ }
998
+
999
+ [data-theme="dark"] .hljs-tag,
1000
+ [data-theme="dark"] .hljs-name,
1001
+ [data-theme="dark"] .hljs-attribute {
1002
+ color: #4da6ff;
1003
+ }
1004
+
1005
+ [data-theme="dark"] .hljs-regexp,
1006
+ [data-theme="dark"] .hljs-link {
1007
+ color: #98c379;
1008
+ }
1009
+
1010
+ [data-theme="dark"] .hljs-symbol,
1011
+ [data-theme="dark"] .hljs-bullet {
1012
+ color: #ff8844;
1013
+ }
1014
+
1015
+ [data-theme="dark"] .hljs-built_in,
1016
+ [data-theme="dark"] .hljs-builtin-name {
1017
+ color: #4da6ff;
1018
+ }
1019
+
1020
+ [data-theme="dark"] .hljs-meta {
1021
+ color: #808080;
1022
+ }
1023
+
1024
+ [data-theme="dark"] .hljs-deletion {
1025
+ color: #ffc0c0;
1026
+ background-color: #400000;
1027
+ }
1028
+
1029
+ [data-theme="dark"] .hljs-addition {
1030
+ color: #b5f5b5;
1031
+ background-color: #003000;
1032
+ }
1033
+
package/lib/assets.js CHANGED
@@ -141,11 +141,24 @@ export function copyDefaultStyles(config, defaultsDir) {
141
141
  return copied;
142
142
  }
143
143
 
144
- // Copy default styles from the package
144
+ // Copy selected theme from the package
145
145
  if (existsSync(defaultStylesDir)) {
146
- const copied = copyAssets(defaultStylesDir, outputStylesDir);
147
- console.log(`🎨 Copied ${copied.length} default style files`);
148
- return copied;
146
+ const themeName = config.theme || 'main';
147
+ const themeFile = join(defaultStylesDir, `${themeName}.css`);
148
+
149
+ if (existsSync(themeFile)) {
150
+ // Copy the selected theme as main.css so templates don't need to change
151
+ ensureDir(outputStylesDir);
152
+ copyFileSync(themeFile, join(outputStylesDir, 'main.css'));
153
+ console.log(`🎨 Using "${themeName}" theme`);
154
+ return ['main.css'];
155
+ } else {
156
+ // Fallback to copying all styles if theme not found
157
+ console.log(`⚠️ Theme "${themeName}" not found, using default`);
158
+ const copied = copyAssets(defaultStylesDir, outputStylesDir);
159
+ console.log(`🎨 Copied ${copied.length} default style files`);
160
+ return copied;
161
+ }
149
162
  }
150
163
 
151
164
  console.log('⚠️ No styles found');
package/lib/config.js CHANGED
@@ -10,6 +10,7 @@ const defaultConfig = {
10
10
  url: 'http://localhost:3000',
11
11
  author: 'Anonymous'
12
12
  },
13
+ theme: 'main', // Theme CSS file to use: 'main' or 'minimal'
13
14
  input: 'src',
14
15
  output: 'dist',
15
16
  layouts: '_layouts',
package/lib/content.js CHANGED
@@ -4,6 +4,11 @@ import matter from 'gray-matter';
4
4
  import { Marked } from 'marked';
5
5
  import { markedHighlight } from 'marked-highlight';
6
6
  import { markedEmoji } from 'marked-emoji';
7
+ import { gfmHeadingId } from 'marked-gfm-heading-id';
8
+ import footnote from 'marked-footnote';
9
+ import { markedSmartypants } from 'marked-smartypants';
10
+ import markedAlert from 'marked-alert';
11
+ import markedLinkifyIt from 'marked-linkify-it';
7
12
  import hljs from 'highlight.js';
8
13
 
9
14
  /**
@@ -77,7 +82,7 @@ const emojis = {
77
82
  };
78
83
 
79
84
  /**
80
- * Configure marked with syntax highlighting and emoji support
85
+ * Configure marked with syntax highlighting, emoji support, and enhanced markdown features
81
86
  */
82
87
  const marked = new Marked(
83
88
  markedHighlight({
@@ -101,7 +106,12 @@ const marked = new Marked(
101
106
  markedEmoji({
102
107
  emojis,
103
108
  renderer: (token) => token.emoji
104
- })
109
+ }),
110
+ gfmHeadingId(),
111
+ footnote(),
112
+ markedSmartypants(),
113
+ markedAlert(),
114
+ markedLinkifyIt()
105
115
  );
106
116
 
107
117
  // Configure marked options
package/lib/server.js CHANGED
@@ -64,10 +64,17 @@ function injectLiveReload(html, wsPort) {
64
64
  * Create the HTTP server
65
65
  */
66
66
  function createHttpServer(config, wsPort) {
67
+ const basePath = config.site.basePath || '';
68
+
67
69
  const server = createServer((req, res) => {
68
70
  // Parse URL
69
71
  let urlPath = req.url.split('?')[0];
70
72
 
73
+ // Strip basePath from the URL if present (for local dev with subpath hosting)
74
+ if (basePath && urlPath.startsWith(basePath)) {
75
+ urlPath = urlPath.slice(basePath.length) || '/';
76
+ }
77
+
71
78
  // Handle root and trailing slashes
72
79
  if (urlPath.endsWith('/')) {
73
80
  urlPath += 'index.html';
@@ -215,7 +222,8 @@ export async function startServer(options = {}) {
215
222
 
216
223
  // Start HTTP server
217
224
  httpServer.listen(httpPort, () => {
218
- console.log(`\n🚀 Server running at http://localhost:${httpPort}`);
225
+ const basePath = config.site.basePath || '';
226
+ console.log(`\n🚀 Server running at http://localhost:${httpPort}${basePath}/`);
219
227
  console.log(`🔄 Live reload on ws://localhost:${wsPort}`);
220
228
  console.log('\n👀 Watching for changes...\n');
221
229
  });
package/lib/templates.js CHANGED
@@ -24,7 +24,8 @@ function dateFilter(date, format = 'long') {
24
24
  year: { year: 'numeric' },
25
25
  month: { month: 'long', year: 'numeric' },
26
26
  time: { hour: 'numeric', minute: '2-digit' },
27
- full: { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' }
27
+ full: { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' },
28
+ full_time: { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit' }
28
29
  };
29
30
 
30
31
  if (format === 'iso') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@terrymooreii/sia",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
4
  "description": "A simple, powerful static site generator with markdown, front matter, and Nunjucks templates",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -19,7 +19,15 @@
19
19
  "nunjucks",
20
20
  "blog"
21
21
  ],
22
- "author": "",
22
+ "author": "Terry Moore II",
23
+ "homepage": "https://github.com/terrymooreii/sia",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/terrymooreii/sia.git"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/terrymooreii/sia/issues"
30
+ },
23
31
  "license": "MIT",
24
32
  "dependencies": {
25
33
  "chalk": "^5.3.0",
@@ -29,8 +37,13 @@
29
37
  "highlight.js": "^11.9.0",
30
38
  "js-yaml": "^4.1.0",
31
39
  "marked": "^11.1.1",
40
+ "marked-alert": "^2.1.2",
32
41
  "marked-emoji": "^2.0.2",
42
+ "marked-footnote": "^1.4.0",
43
+ "marked-gfm-heading-id": "^3.1.3",
33
44
  "marked-highlight": "^2.1.0",
45
+ "marked-linkify-it": "^3.1.14",
46
+ "marked-smartypants": "^1.1.11",
34
47
  "nunjucks": "^3.2.4",
35
48
  "prompts": "^2.4.2",
36
49
  "ws": "^8.16.0"
package/readme.md CHANGED
@@ -4,6 +4,7 @@ A simple, powerful static site generator built with JavaScript. Similar to Eleve
4
4
 
5
5
  ## Features
6
6
 
7
+ - **Enhanced Markdown** - Syntax highlighting, emoji support, footnotes, alert boxes, auto-linkify, and more
7
8
  - **Markdown & Front Matter** - Write content in markdown with YAML front matter
8
9
  - **Nunjucks Templates** - Flexible templating with includes and layouts
9
10
  - **Multiple Content Types** - Blog posts, pages, and notes (tweet-like short posts)
@@ -11,7 +12,7 @@ A simple, powerful static site generator built with JavaScript. Similar to Eleve
11
12
  - **Pagination** - Built-in pagination for listing pages
12
13
  - **Image Support** - Automatic image copying and organization
13
14
  - **Live Reload** - Development server with hot reloading
14
- - **Dark Mode** - Built-in light/dark theme with toggle
15
+ - **Themes** - Built-in themes (main, minimal) with light/dark mode toggle
15
16
  - **RSS Feed** - Automatic RSS feed generation
16
17
  - **YAML/JSON Config** - Flexible configuration options
17
18
 
@@ -104,6 +105,8 @@ site:
104
105
  url: "https://example.com"
105
106
  author: "Your Name"
106
107
 
108
+ theme: main # 'main' or 'minimal'
109
+
107
110
  input: src
108
111
  output: dist
109
112
 
@@ -158,6 +161,102 @@ excerpt: "Custom excerpt text"
158
161
  | `draft` | If true, excluded from build |
159
162
  | `excerpt` | Custom excerpt |
160
163
 
164
+ ## Markdown Features
165
+
166
+ Sia supports enhanced markdown features beyond standard markdown:
167
+
168
+ ### Syntax Highlighting
169
+
170
+ Code blocks are automatically highlighted using Highlight.js:
171
+
172
+ ````markdown
173
+ ```javascript
174
+ function hello() {
175
+ console.log("Hello, world!");
176
+ }
177
+ ```
178
+ ````
179
+
180
+ ### Emoji Support
181
+
182
+ Use emoji shortcodes in your markdown:
183
+
184
+ ```markdown
185
+ :smile: :rocket: :heart: :thumbsup:
186
+ ```
187
+
188
+ Common emojis: `:smile:`, `:heart:`, `:thumbsup:`, `:fire:`, `:rocket:`, `:star:`, `:check:`, `:warning:`, and many more.
189
+
190
+ ### Heading IDs
191
+
192
+ All headings automatically get ID attributes for anchor links:
193
+
194
+ ```markdown
195
+ ## My Heading
196
+ ```
197
+
198
+ Becomes: `<h2 id="my-heading">My Heading</h2>`
199
+
200
+ You can link to headings within the same document:
201
+
202
+ ```markdown
203
+ [Link to My Heading](#my-heading)
204
+ ```
205
+
206
+ ### Footnotes
207
+
208
+ Add footnotes to your content:
209
+
210
+ ```markdown
211
+ This is a sentence with a footnote[^1].
212
+
213
+ [^1]: This is the footnote content.
214
+ ```
215
+
216
+ ### Typography Enhancements
217
+
218
+ Smart typography automatically converts:
219
+
220
+ - Straight quotes (`"` and `'`) to curly quotes (`"` `"` `'` `'`)
221
+ - Double hyphens (`--`) to en-dash (`–`)
222
+ - Triple hyphens (`---`) to em-dash (`—`)
223
+ - Three dots (`...`) to ellipsis (`…`)
224
+
225
+ ### Alert Boxes
226
+
227
+ Create GitHub Flavored Markdown-style alert boxes:
228
+
229
+ ```markdown
230
+ > [!NOTE]
231
+ > This is a note alert.
232
+
233
+ > [!TIP]
234
+ > This is a tip alert.
235
+
236
+ > [!WARNING]
237
+ > This is a warning alert.
238
+
239
+ > [!CAUTION]
240
+ > This is a caution alert.
241
+ ```
242
+
243
+ ### Auto-Linkify
244
+
245
+ Plain URLs are automatically converted to clickable links:
246
+
247
+ ```markdown
248
+ Visit https://example.com for more info.
249
+ ```
250
+
251
+ ### GitHub Flavored Markdown
252
+
253
+ Full GFM support including:
254
+
255
+ - Tables
256
+ - Task lists (`- [ ]` and `- [x]`)
257
+ - Strikethrough (`~~text~~`)
258
+ - And more
259
+
161
260
  ## Templates
162
261
 
163
262
  Sia uses Nunjucks for templating. Templates are loaded from:
@@ -23,7 +23,7 @@ You can reach me at:
23
23
 
24
24
  This site is:
25
25
 
26
- - Generated with [Sia](https://github.com/sia/sia)
26
+ - Generated with [Sia](https://github.com/terrymooreii/sia)
27
27
  - Written in Markdown
28
28
  - Styled with CSS
29
29
  - Hosted on [your hosting provider]