spectrum-er 1.0.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.
data/_config.yml ADDED
@@ -0,0 +1,340 @@
1
+ # ===========================================
2
+ # SPECTRUM JEKYLL THEME - MAIN CONFIGURATION
3
+ # ===========================================
4
+
5
+ # Jekyll Core Settings
6
+ markdown: kramdown
7
+ highlighter: rouge
8
+ permalink: pretty
9
+ timezone: UTC
10
+
11
+ # Site Identity
12
+ site:
13
+ title: "Duhyeon Kim"
14
+ description: "Personal website showcasing tech insights and development journey"
15
+ url: "https://yoursite.com"
16
+ baseurl: ""
17
+ author: "Duhyeon Kim"
18
+ email: "your@email.com"
19
+
20
+ # Personal Information
21
+ personal:
22
+ name: "Duhyeon Kim"
23
+ tagline: "spectrum jekyll owner"
24
+ bio: "Developer passionate about technology, design, and continuous learning"
25
+ location: "Seoul, Korea"
26
+
27
+ # Social Media Links
28
+ social:
29
+ enabled: true
30
+ platforms:
31
+ email:
32
+ enabled: true
33
+ url: "kdhluck@naver.com"
34
+ label: "Email"
35
+ icon: "fa-solid fa-envelope"
36
+ github:
37
+ enabled: true
38
+ url: "https://github.com/dudududukim"
39
+ label: "GitHub"
40
+ icon: "fa-brands fa-github"
41
+ linkedin:
42
+ enabled: true
43
+ url: "https://www.linkedin.com/in/duhyeon-kim-6623082b1/"
44
+ label: "LinkedIn"
45
+ icon: "fa-brands fa-linkedin"
46
+ twitter:
47
+ enabled: false
48
+ url: "https://twitter.com/username"
49
+ label: "Twitter"
50
+ icon: "fa-brands fa-twitter"
51
+ instagram:
52
+ enabled: false
53
+ url: "https://instagram.com/username"
54
+ label: "Instagram"
55
+ icon: "fa-brands fa-instagram"
56
+
57
+ # Accessibility Configuration
58
+ accessibility:
59
+ skip_links: true
60
+ focus_indicators: true
61
+ screen_reader_text: "Skip to main content"
62
+ high_contrast_mode: false
63
+ reduced_motion: false
64
+
65
+ # Navigation Configuration
66
+ navigation:
67
+ home_text: "Home"
68
+ show_social: true
69
+ social_position: "right"
70
+
71
+ # Footer Configuration
72
+ footer:
73
+ copyright_text: "All rights reserved."
74
+ show_theme_credit: true
75
+ theme_name: "Spectrum"
76
+ theme_url: "https://github.com/dudududukim/spectrum"
77
+
78
+ # Content Configuration
79
+ content:
80
+ pages:
81
+ about:
82
+ title: "About"
83
+ welcome_message: "Welcome 🤗"
84
+ intro_text: "I'm Duhyeon Kim, an Electrical and Electronic Engineering major from Korea University. I have a broad curiosity about all things AI, and I enjoy diving deep into areas where I can focus and grow."
85
+ main_description: "My hope is that, even if just a little, the path I take will leave something valuable for humanity. My dreams are big, but I'm still figuring out how to make them a reality."
86
+ sections:
87
+ - title: "Areas of Study & Work"
88
+ content: "Here are a few topics I've studied or worked on:\n\n- Computer vision / NLP\n- FPGA & VLSI\n- Computer architecture"
89
+ closing_text: "🌈 Wishing everyone a wonderful day!"
90
+
91
+ tech_bites:
92
+ title: "Tech Bites"
93
+ description: "Daily tech insights and discoveries"
94
+ list_page:
95
+ welcome_message: "Welcome to my collection of tech insights!"
96
+ intro_text: "Here you'll find bite-sized posts covering everything from JavaScript tips to performance optimization techniques, accessibility best practices, and modern web development workflows."
97
+ description: "Each post is designed to be a quick read while providing practical, actionable information that you can apply to your own projects. Whether you're a seasoned developer or just starting out, there's something here for everyone."
98
+ categories_title: "Categories"
99
+ categories:
100
+ - name: "JavaScript"
101
+ description: "Modern ES6+ features, frameworks, and best practices"
102
+ - name: "CSS"
103
+ description: "Layout techniques, animations, and responsive design"
104
+ - name: "Performance"
105
+ description: "Optimization strategies and Core Web Vitals"
106
+ - name: "Accessibility"
107
+ description: "Building inclusive web experiences"
108
+ - name: "Development"
109
+ description: "Workflows, tools, and productivity tips"
110
+ closing_text: "Browse through the posts below, or use the category filter to find content that interests you most."
111
+ card:
112
+ read_more_text: "Read More"
113
+ min_read_text: "min read"
114
+ navigation:
115
+ previous_text: "← Previous"
116
+ next_text: "Next →"
117
+
118
+ films:
119
+ title: "Films"
120
+ description: "Photography collection showcasing moments captured through the lens"
121
+
122
+ ui:
123
+ buttons:
124
+ view_all_tech_bites: "View All Tech Bites"
125
+ read_more: "Read More"
126
+
127
+ pagination:
128
+ showing_text: "Showing"
129
+ of_text: "of"
130
+ tech_bites_text: "tech bites"
131
+ page_text: "Page"
132
+ previous_text: "Previous"
133
+ next_text: "Next"
134
+
135
+ error:
136
+ 404:
137
+ title: "Page Not Found"
138
+ message: "Sorry, the page you're looking for doesn't exist."
139
+ suggestion: "You might want to go back to the homepage or check out our tech bites."
140
+ back_home_text: "Back to Home"
141
+
142
+ # Theme Configuration (consolidated from theme.yml)
143
+ site_theme:
144
+ colors:
145
+ primary: "#3498db"
146
+ secondary: "#2c3e50"
147
+ accent: "#e74c3c"
148
+ background: "#ffffff"
149
+ text: "#2c3e50"
150
+ light_text: "#7f8c8d"
151
+ success: "#27ae60"
152
+ warning: "#f39c12"
153
+ error: "#e74c3c"
154
+ info: "#3498db"
155
+
156
+ typography:
157
+ font_family: "Lato"
158
+ font_weights:
159
+ light: 300
160
+ normal: 400
161
+ medium: 500
162
+ bold: 700
163
+ font_sizes:
164
+ xs: "0.75rem"
165
+ sm: "0.875rem"
166
+ base: "1rem"
167
+ lg: "1.125rem"
168
+ xl: "1.25rem"
169
+ "2xl": "1.5rem"
170
+ "3xl": "1.875rem"
171
+ "4xl": "2.25rem"
172
+
173
+ layout:
174
+ max_width: "1125px"
175
+ content_width: "875px"
176
+ breakpoints:
177
+ mobile: "768px"
178
+ tablet: "1024px"
179
+ desktop: "1200px"
180
+
181
+ animations:
182
+ enabled: true
183
+ duration: "0.3s"
184
+ easing: "ease"
185
+ reduced_motion: false
186
+
187
+ dark_mode:
188
+ enabled: true
189
+ auto_detect: true
190
+ toggle_enabled: true
191
+
192
+ components:
193
+ cards:
194
+ border_radius: "0.75rem"
195
+ shadow: "0 4px 6px rgba(0, 0, 0, 0.1)"
196
+ hover_shadow: "0 8px 25px rgba(0, 0, 0, 0.15)"
197
+ buttons:
198
+ border_radius: "0.5rem"
199
+ padding: "0.75rem 1.5rem"
200
+ transition: "all 0.3s ease"
201
+ navigation:
202
+ height: "4rem"
203
+ background: "var(--bg-color)"
204
+ border_bottom: "1px solid var(--border-light)"
205
+ footer:
206
+ padding: "0.75rem 0"
207
+ background: "var(--bg-color)"
208
+ border_top: "1px solid var(--border-light)"
209
+
210
+ accessibility:
211
+ focus_ring: "2px solid var(--primary-color)"
212
+ focus_offset: "2px"
213
+ high_contrast: false
214
+ reduced_motion: false
215
+ skip_links: true
216
+
217
+ # Homepage Section Controls
218
+ homepage_sections:
219
+ tech_bites_preview:
220
+ enabled: true
221
+ show_count: 5
222
+ show_read_more_button: true
223
+ custom_title: "Recent Tech Bites" # Optional override
224
+
225
+ films_preview:
226
+ enabled: true
227
+ show_count: 6
228
+ show_view_all_button: true
229
+ custom_title: "Recent Films" # Optional override
230
+ animation_duration: 60
231
+
232
+ # Future extensibility
233
+ papers_preview:
234
+ enabled: false
235
+ show_count: 3
236
+
237
+ gallery_preview:
238
+ enabled: false
239
+ show_count: 8
240
+
241
+ # Design Customization (maintain current defaults)
242
+ design_options:
243
+ tech_bite_cards:
244
+ compact_mode: true # Current ultra-compact design
245
+ show_excerpts: true
246
+ show_reading_time: true
247
+ max_excerpt_length: 150
248
+
249
+ gallery_track:
250
+ auto_scroll: true
251
+ scroll_speed: 60 # Current animation duration
252
+ show_overlay_on_hover: true
253
+
254
+ navigation:
255
+ fixed_position: true
256
+ show_breadcrumbs: true
257
+ social_position: "right" # Current position
258
+
259
+ footer:
260
+ show_theme_credit: true # Current setting
261
+ compact_layout: true # Current design
262
+
263
+ # Section Configuration
264
+ sections:
265
+ tech_bite:
266
+ enabled: true
267
+ main_page_count: 5
268
+ show_categories: true
269
+ show_dates: true
270
+ pagination: 10
271
+
272
+ gallery_track:
273
+ enabled: true
274
+ image_count: 6
275
+ animation_duration: 60
276
+
277
+ # Collections
278
+ collections:
279
+ tech-bites:
280
+ output: true
281
+ permalink: /tech-bites/:name/
282
+ papers:
283
+ output: true
284
+ permalink: /papers/:name/
285
+ gallery:
286
+ output: true
287
+ permalink: /gallery/:name/
288
+
289
+ # Default Front Matter
290
+ defaults:
291
+ - scope:
292
+ path: ""
293
+ type: "pages"
294
+ values:
295
+ layout: "default"
296
+ - scope:
297
+ path: ""
298
+ type: "tech-bites"
299
+ values:
300
+ layout: "tech-bite"
301
+ show_sidebar: true
302
+
303
+ # Plugins
304
+ plugins:
305
+ - jekyll-feed
306
+ - jekyll-sitemap
307
+ - jekyll-seo-tag
308
+
309
+ # Build Settings
310
+ exclude:
311
+ - Gemfile
312
+ - Gemfile.lock
313
+ - node_modules
314
+ - vendor/bundle/
315
+ - vendor/cache/
316
+ - vendor/gems/
317
+ - vendor/ruby/
318
+ - README.md
319
+ - .gitignore
320
+ - .sass-cache/
321
+ - .jekyll-cache/
322
+ - .jekyll-metadata
323
+
324
+ # Sass Configuration
325
+ sass:
326
+ style: compressed
327
+ sass_dir: _sass
328
+ load_paths:
329
+ - assets/css
330
+
331
+ # Kramdown Configuration
332
+ kramdown:
333
+ input: GFM
334
+ syntax_highlighter: rouge
335
+ syntax_highlighter_opts:
336
+ css_class: 'highlight'
337
+ span:
338
+ line_numbers: false
339
+ block:
340
+ line_numbers: false
@@ -0,0 +1,38 @@
1
+ # Navigation Configuration
2
+ # =======================
3
+
4
+ primary:
5
+ - title: "Home"
6
+ url: "/"
7
+ icon: "fa-solid fa-home"
8
+ - title: "Tech Bites"
9
+ url: "/tech-bites/"
10
+ icon: "fa-solid fa-code"
11
+ - title: "Films"
12
+ url: "/films/"
13
+ icon: "fa-solid fa-camera"
14
+ - title: "Papers"
15
+ url: "/papers/"
16
+ icon: "fa-solid fa-file-text"
17
+ enabled: false # Disabled until implemented
18
+ - title: "About"
19
+ url: "/about/"
20
+ icon: "fa-solid fa-user"
21
+ - title: "Gallery"
22
+ url: "/gallery/"
23
+ icon: "fa-solid fa-images"
24
+ enabled: false # Disabled until implemented
25
+
26
+ # Footer navigation
27
+ footer:
28
+ - title: "Privacy Policy"
29
+ url: "/privacy/"
30
+ enabled: false
31
+ - title: "Terms of Service"
32
+ url: "/terms/"
33
+ enabled: false
34
+ - title: "Contact"
35
+ url: "/contact/"
36
+ enabled: false
37
+
38
+ # Social navigation references main config social settings
@@ -0,0 +1,30 @@
1
+ <!-- Content Card Component -->
2
+ <!-- Usage: {% include content-card.html title="Card Title" meta="Meta info" content="Card content" %} -->
3
+
4
+ <article class="content-card card">
5
+ {% if include.title %}
6
+ <div class="card-header">
7
+ <h3 class="card-title">
8
+ {% if include.url %}
9
+ <a href="{{ include.url }}">{{ include.title }}</a>
10
+ {% else %}
11
+ {{ include.title }}
12
+ {% endif %}
13
+ </h3>
14
+ </div>
15
+ {% endif %}
16
+
17
+ {% if include.meta %}
18
+ <div class="card-meta">{{ include.meta }}</div>
19
+ {% endif %}
20
+
21
+ {% if include.content %}
22
+ <div class="card-body">
23
+ <div class="card-content">{{ include.content }}</div>
24
+ </div>
25
+ {% endif %}
26
+
27
+ {% if include.footer %}
28
+ <div class="card-footer">{{ include.footer }}</div>
29
+ {% endif %}
30
+ </article>
@@ -0,0 +1,97 @@
1
+ <!-- Gallery Track Component -->
2
+ <!-- Horizontal scrolling gallery showing recent films -->
3
+ {% assign animation_duration = site.sections.gallery_track.animation_duration | default: 45 %}
4
+
5
+ <style>
6
+ .gallery-track {
7
+ animation: scroll-left {{ animation_duration }}s linear infinite !important;
8
+ }
9
+ </style>
10
+
11
+ <section class="gallery-track-preview">
12
+ <div class="section-header">
13
+ <h2 class="section-title">Recent Films</h2>
14
+ <p class="section-description">Latest photography from my collection</p>
15
+ </div>
16
+
17
+ <div class="section-content">
18
+ <div class="gallery-track-container">
19
+ <div class="gallery-track" id="gallery-track">
20
+ {% assign image_extensions = "jpg,jpeg,png,webp,JPG,JPEG,PNG,WEBP" | split: "," %}
21
+ {% assign films_images = site.static_files | where_exp: "file", "file.path contains '/assets/images/films/'" %}
22
+ {% assign image_count = site.sections.gallery_track.image_count | default: 6 %}
23
+ {% assign recent_films = films_images | limit: image_count %}
24
+
25
+ <!-- Generate gallery items with seamless loop duplication -->
26
+ {% for i in (1..2) %}
27
+ {% for file in recent_films %}
28
+ {% assign file_ext = file.extname | remove: '.' %}
29
+ {% if image_extensions contains file_ext %}
30
+ {% assign image_name = file.name | remove: file.extname %}
31
+ {% assign image_path = file.path | relative_url %}
32
+
33
+ <div class="gallery-item">
34
+ <a href="{{ '/films/' | relative_url }}" class="gallery-link" aria-label="View {{ image_name | replace: '-', ' ' | capitalize }} in gallery">
35
+ <img
36
+ src="{{ image_path }}"
37
+ alt="{{ image_name | replace: '-', ' ' | capitalize }}"
38
+ class="gallery-image"
39
+ loading="lazy"
40
+ decoding="async"
41
+ />
42
+ <div class="gallery-overlay">
43
+ <div class="gallery-info">
44
+ <span class="gallery-title">{{ image_name | replace: '-', ' ' | capitalize }}</span>
45
+ </div>
46
+ </div>
47
+ </a>
48
+ </div>
49
+ {% endif %}
50
+ {% endfor %}
51
+ {% endfor %}
52
+ </div>
53
+ </div>
54
+
55
+ <div class="section-footer">
56
+ <a href="{{ '/films/' | relative_url }}" class="section-button">
57
+ View All Films
58
+ <span class="btn-icon">→</span>
59
+ </a>
60
+ </div>
61
+ </div>
62
+ </section>
63
+
64
+ <script>
65
+ document.addEventListener('DOMContentLoaded', function() {
66
+ const galleryTrack = document.getElementById('gallery-track');
67
+ if (!galleryTrack) return;
68
+
69
+ let isPaused = false;
70
+
71
+ // Pause animation on hover
72
+ galleryTrack.addEventListener('mouseenter', function() {
73
+ isPaused = true;
74
+ galleryTrack.style.animationPlayState = 'paused';
75
+ });
76
+
77
+ // Resume animation on mouse leave
78
+ galleryTrack.addEventListener('mouseleave', function() {
79
+ isPaused = false;
80
+ galleryTrack.style.animationPlayState = 'running';
81
+ });
82
+
83
+ // Pause animation when any gallery item is hovered
84
+ const galleryItems = galleryTrack.querySelectorAll('.gallery-item');
85
+ galleryItems.forEach(item => {
86
+ item.addEventListener('mouseenter', function() {
87
+ isPaused = true;
88
+ galleryTrack.style.animationPlayState = 'paused';
89
+ });
90
+
91
+ item.addEventListener('mouseleave', function() {
92
+ isPaused = false;
93
+ galleryTrack.style.animationPlayState = 'running';
94
+ });
95
+ });
96
+ });
97
+ </script>
@@ -0,0 +1,23 @@
1
+ {% assign image = include.image %}
2
+ {% assign image_name = image.name | remove: image.extname %}
3
+ {% assign image_path = image.path | relative_url %}
4
+
5
+ <article class="photo-card card" data-image="{{ image_name }}">
6
+ <div class="photo-container">
7
+ <a href="{{ image_path }}" class="photo-link" data-lightbox="films" data-title="{{ image_name | replace: '-', ' ' | capitalize }}">
8
+ <img
9
+ src="{{ image_path }}"
10
+ alt="{{ image_name | replace: '-', ' ' | capitalize }}"
11
+ class="photo-image"
12
+ loading="lazy"
13
+ decoding="async"
14
+ />
15
+ <div class="photo-overlay">
16
+ <div class="photo-info">
17
+ <h3 class="photo-title">{{ image_name | replace: '-', ' ' | capitalize }}</h3>
18
+ <span class="photo-meta">{{ image.extname | remove: '.' | upcase }}</span>
19
+ </div>
20
+ </div>
21
+ </a>
22
+ </div>
23
+ </article>
@@ -0,0 +1,12 @@
1
+ <!-- Section Header Component -->
2
+ <!-- Usage: {% include section-header.html title="Section Title" description="Section description" %} -->
3
+
4
+ <div class="section-header">
5
+ {% if include.title %}
6
+ <h2 class="section-title">{{ include.title }}</h2>
7
+ {% endif %}
8
+
9
+ {% if include.description %}
10
+ <p class="section-description">{{ include.description }}</p>
11
+ {% endif %}
12
+ </div>
@@ -0,0 +1,33 @@
1
+ <nav class="site-navigation" role="navigation" aria-label="Site navigation">
2
+ <div class="nav-container">
3
+ <div class="nav-path">
4
+ <a href="{{ '/' | relative_url }}" class="nav-home">{{ site.navigation.home_text | default: "Home" }}</a>
5
+ {% unless page.url == "/" %}
6
+ <span class="nav-separator">/</span>
7
+ {% if page.layout == 'tech-bite-list' %}
8
+ <span class="nav-current">{{ site.content.pages.tech_bites.title | default: "Tech Bites" }}</span>
9
+ {% elsif page.layout == 'tech-bite' %}
10
+ <a href="{{ '/tech-bites/' | relative_url }}" class="nav-link">{{ site.content.pages.tech_bites.title | default: "Tech Bites" }}</a>
11
+ <span class="nav-separator">/</span>
12
+ <span class="nav-current">{{ page.title }}</span>
13
+ {% elsif page.layout == 'about' %}
14
+ <span class="nav-current">{{ site.content.pages.about.title | default: "About" }}</span>
15
+ {% else %}
16
+ <span class="nav-current">{{ page.title | default: 'Page' }}</span>
17
+ {% endif %}
18
+ {% endunless %}
19
+ </div>
20
+
21
+ {% if site.navigation.show_social and site.social.enabled %}
22
+ <div class="nav-social">
23
+ {% for platform in site.social.platforms %}
24
+ {% if platform[1].enabled and platform[1].url %}
25
+ <a href="{{ platform[1].url }}" target="_blank" rel="noopener noreferrer" class="nav-social-link" title="{{ platform[1].label }}">
26
+ <i class="{{ platform[1].icon }}"></i>
27
+ </a>
28
+ {% endif %}
29
+ {% endfor %}
30
+ </div>
31
+ {% endif %}
32
+ </div>
33
+ </nav>
@@ -0,0 +1,22 @@
1
+ <!-- Structured Data for SEO -->
2
+ <script type="application/ld+json">
3
+ {
4
+ "@context": "https://schema.org",
5
+ "@type": "Person",
6
+ "name": "{{ site.personal.name | default: site.title }}",
7
+ "url": "{{ site.url }}{{ site.baseurl }}",
8
+ "description": "{{ site.description }}",
9
+ {% if site.personal.social_links %}
10
+ "sameAs": [
11
+ {% if site.personal.social_links.github %}"https://github.com/{{ site.personal.social_links.github }}"{% unless forloop.last %},{% endunless %}{% endif %}
12
+ {% if site.personal.social_links.linkedin %}"https://linkedin.com/in/{{ site.personal.social_links.linkedin }}"{% unless forloop.last %},{% endunless %}{% endif %}
13
+ {% if site.personal.social_links.twitter %}"https://twitter.com/{{ site.personal.social_links.twitter }}"{% unless forloop.last %},{% endunless %}{% endif %}
14
+ ],
15
+ {% endif %}
16
+ "jobTitle": "{{ site.personal.title | default: 'Developer' }}",
17
+ "worksFor": {
18
+ "@type": "Organization",
19
+ "name": "{{ site.personal.company | default: 'Freelance' }}"
20
+ }
21
+ }
22
+ </script>
@@ -0,0 +1,52 @@
1
+ {% assign tech_bite = include.tech_bite %}
2
+ <article class="tech-bite-card"
3
+ data-date="{{ tech_bite.date | date: '%Y-%m-%d' }}">
4
+ <div class="card-content">
5
+ <header class="card-header">
6
+ <h3 class="card-title">
7
+ <a href="{{ tech_bite.url | relative_url }}" class="card-link">
8
+ {{ tech_bite.title }}
9
+ </a>
10
+ </h3>
11
+
12
+ <div class="card-meta">
13
+ {% if site.sections.tech_bite.show_dates and tech_bite.date %}
14
+ <time class="card-date" datetime="{{ tech_bite.date | date_to_xmlschema }}">
15
+ {{ tech_bite.date | date: "%b %d, %Y" }}
16
+ </time>
17
+ {% endif %}
18
+
19
+ {% if site.sections.tech_bite.show_categories and tech_bite.categories %}
20
+ <div class="card-categories">
21
+ {% for category in tech_bite.categories limit: 2 %}
22
+ <span class="category-tag">{{ category }}</span>
23
+ {% endfor %}
24
+ {% if tech_bite.categories.size > 2 %}
25
+ <span class="category-more">+{{ tech_bite.categories.size | minus: 2 }}</span>
26
+ {% endif %}
27
+ </div>
28
+ {% endif %}
29
+ </div>
30
+ </header>
31
+
32
+ <div class="card-body">
33
+ {% if tech_bite.excerpt %}
34
+ <p class="card-excerpt">{{ tech_bite.excerpt | strip_html | truncate: 150 }}</p>
35
+ {% elsif tech_bite.description %}
36
+ <p class="card-excerpt">{{ tech_bite.description | strip_html | truncate: 150 }}</p>
37
+ {% endif %}
38
+
39
+ </div>
40
+
41
+ <footer class="card-footer">
42
+ <a href="{{ tech_bite.url | relative_url }}" class="read-more">
43
+ {{ site.content.pages.tech_bites.card.read_more_text | default: "Read More" }}
44
+ <span class="read-more-icon">→</span>
45
+ </a>
46
+
47
+ {% if tech_bite.reading_time %}
48
+ <span class="reading-time">{{ tech_bite.reading_time }} {{ site.content.pages.tech_bites.card.min_read_text | default: "min read" }}</span>
49
+ {% endif %}
50
+ </footer>
51
+ </div>
52
+ </article>