@edtools/cli 0.6.1 → 0.7.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.
Files changed (39) hide show
  1. package/dist/adapters/html/index.d.ts +2 -2
  2. package/dist/adapters/html/index.d.ts.map +1 -1
  3. package/dist/adapters/html/index.js +19 -2
  4. package/dist/adapters/html/index.js.map +1 -1
  5. package/dist/adapters/html/templates/base-layout.ejs +173 -0
  6. package/dist/adapters/html/templates/blog-index.html.ejs +170 -101
  7. package/dist/adapters/html/templates/blog-post-enhanced.ejs +655 -0
  8. package/dist/adapters/html/templates/blog-post-new.ejs +612 -0
  9. package/dist/adapters/html/templates/components/footer.ejs +330 -0
  10. package/dist/adapters/html/templates/components/header.ejs +208 -0
  11. package/dist/adapters/html/templates/components/social-share.ejs +202 -0
  12. package/dist/chunk-5N3D47CJ.js +823 -0
  13. package/dist/chunk-TROAGFSZ.js +824 -0
  14. package/dist/chunk-U77FH5BI.js +823 -0
  15. package/dist/cli/commands/config.d.ts +17 -0
  16. package/dist/cli/commands/config.d.ts.map +1 -0
  17. package/dist/cli/commands/config.js +140 -0
  18. package/dist/cli/commands/config.js.map +1 -0
  19. package/dist/cli/commands/generate.d.ts +1 -1
  20. package/dist/cli/commands/generate.d.ts.map +1 -1
  21. package/dist/cli/commands/generate.js +74 -17
  22. package/dist/cli/commands/generate.js.map +1 -1
  23. package/dist/cli/commands/init.d.ts.map +1 -1
  24. package/dist/cli/commands/init.js +114 -0
  25. package/dist/cli/commands/init.js.map +1 -1
  26. package/dist/cli/index.js +567 -265
  27. package/dist/cli/index.js.map +1 -1
  28. package/dist/core/generator.d.ts +4 -1
  29. package/dist/core/generator.d.ts.map +1 -1
  30. package/dist/core/generator.js +114 -3
  31. package/dist/core/generator.js.map +1 -1
  32. package/dist/index.d.ts +87 -3
  33. package/dist/index.js +1 -1
  34. package/dist/types/adapter.d.ts +17 -2
  35. package/dist/types/adapter.d.ts.map +1 -1
  36. package/dist/types/adapter.js.map +1 -1
  37. package/dist/types/content.d.ts +66 -0
  38. package/dist/types/content.d.ts.map +1 -1
  39. package/package.json +2 -2
@@ -0,0 +1,330 @@
1
+ <!-- Global Blog Footer Component -->
2
+ <footer class="blog-footer">
3
+ <div class="footer-container">
4
+ <div class="footer-content">
5
+ <!-- Brand/About Section -->
6
+ <div class="footer-section footer-brand">
7
+ <% if (blogConfig.logo) { %>
8
+ <img src="<%= blogConfig.logo %>" alt="<%= blogConfig.name %>" class="footer-logo">
9
+ <% } else { %>
10
+ <h3 class="footer-title"><%= blogConfig.name %></h3>
11
+ <% } %>
12
+ <% if (blogConfig.description) { %>
13
+ <p class="footer-description"><%= blogConfig.description %></p>
14
+ <% } %>
15
+ </div>
16
+
17
+ <!-- Navigation Links -->
18
+ <% if (blogConfig.footerLinks && blogConfig.footerLinks.length > 0) { %>
19
+ <div class="footer-section footer-links">
20
+ <h4 class="footer-section-title">Navigation</h4>
21
+ <ul class="footer-link-list">
22
+ <% blogConfig.footerLinks.forEach(link => { %>
23
+ <li>
24
+ <a href="<%= link.url %>" class="footer-link">
25
+ <%= link.label %>
26
+ </a>
27
+ </li>
28
+ <% }) %>
29
+ </ul>
30
+ </div>
31
+ <% } %>
32
+
33
+ <!-- Resources/Categories -->
34
+ <% if (blogConfig.categories && blogConfig.categories.length > 0) { %>
35
+ <div class="footer-section footer-categories">
36
+ <h4 class="footer-section-title">Categories</h4>
37
+ <ul class="footer-link-list">
38
+ <% blogConfig.categories.slice(0, 6).forEach(category => { %>
39
+ <li>
40
+ <a href="/blog/category/<%= category.slug %>/" class="footer-link">
41
+ <%= category.name %>
42
+ </a>
43
+ </li>
44
+ <% }) %>
45
+ </ul>
46
+ </div>
47
+ <% } %>
48
+
49
+ <!-- Social Media & Contact -->
50
+ <div class="footer-section footer-social">
51
+ <h4 class="footer-section-title">Connect</h4>
52
+ <% if (blogConfig.social) { %>
53
+ <div class="social-links">
54
+ <% if (blogConfig.social.twitter) { %>
55
+ <a href="<%= blogConfig.social.twitter %>"
56
+ class="social-link"
57
+ aria-label="Twitter"
58
+ target="_blank"
59
+ rel="noopener noreferrer">
60
+ <svg width="20" height="20" fill="currentColor" viewBox="0 0 24 24">
61
+ <path d="M23 3a10.9 10.9 0 01-3.14 1.53 4.48 4.48 0 00-7.86 3v1A10.66 10.66 0 013 4s-4 9 5 13a11.64 11.64 0 01-7 2c9 5 20 0 20-11.5a4.5 4.5 0 00-.08-.83A7.72 7.72 0 0023 3z"></path>
62
+ </svg>
63
+ </a>
64
+ <% } %>
65
+ <% if (blogConfig.social.linkedin) { %>
66
+ <a href="<%= blogConfig.social.linkedin %>"
67
+ class="social-link"
68
+ aria-label="LinkedIn"
69
+ target="_blank"
70
+ rel="noopener noreferrer">
71
+ <svg width="20" height="20" fill="currentColor" viewBox="0 0 24 24">
72
+ <path d="M16 8a6 6 0 016 6v7h-4v-7a2 2 0 00-2-2 2 2 0 00-2 2v7h-4v-7a6 6 0 016-6zM2 9h4v12H2z"></path>
73
+ <circle cx="4" cy="4" r="2"></circle>
74
+ </svg>
75
+ </a>
76
+ <% } %>
77
+ <% if (blogConfig.social.github) { %>
78
+ <a href="<%= blogConfig.social.github %>"
79
+ class="social-link"
80
+ aria-label="GitHub"
81
+ target="_blank"
82
+ rel="noopener noreferrer">
83
+ <svg width="20" height="20" fill="currentColor" viewBox="0 0 24 24">
84
+ <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"></path>
85
+ </svg>
86
+ </a>
87
+ <% } %>
88
+ <% if (blogConfig.social.youtube) { %>
89
+ <a href="<%= blogConfig.social.youtube %>"
90
+ class="social-link"
91
+ aria-label="YouTube"
92
+ target="_blank"
93
+ rel="noopener noreferrer">
94
+ <svg width="20" height="20" fill="currentColor" viewBox="0 0 24 24">
95
+ <path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"></path>
96
+ </svg>
97
+ </a>
98
+ <% } %>
99
+ </div>
100
+ <% } %>
101
+
102
+ <!-- RSS Feed Link -->
103
+ <div class="rss-link-container">
104
+ <a href="/blog/rss.xml" class="footer-link rss-link">
105
+ <svg width="16" height="16" fill="currentColor" viewBox="0 0 24 24" style="vertical-align: middle; margin-right: 0.5rem;">
106
+ <path d="M4 11a9 9 0 019 9M4 4a16 16 0 0116 16M6.5 17.5a1.5 1.5 0 110 3 1.5 1.5 0 010-3z"></path>
107
+ </svg>
108
+ RSS Feed
109
+ </a>
110
+ </div>
111
+ </div>
112
+ </div>
113
+
114
+ <!-- Bottom Bar -->
115
+ <div class="footer-bottom">
116
+ <div class="footer-copyright">
117
+ <p>
118
+ © <%= new Date().getFullYear() %> <%= blogConfig.name %><% if (blogConfig.companyName && blogConfig.companyName !== blogConfig.name) { %> by <%= blogConfig.companyName %><% } %>. All rights reserved.
119
+ </p>
120
+ </div>
121
+
122
+ <div class="footer-legal">
123
+ <% if (blogConfig.legalLinks && blogConfig.legalLinks.length > 0) { %>
124
+ <% blogConfig.legalLinks.forEach((link, index) => { %>
125
+ <a href="<%= link.url %>" class="footer-legal-link"><%= link.label %></a><% if (index < blogConfig.legalLinks.length - 1) { %> · <% } %>
126
+ <% }) %>
127
+ <% } else { %>
128
+ <a href="/privacy" class="footer-legal-link">Privacy</a> ·
129
+ <a href="/terms" class="footer-legal-link">Terms</a>
130
+ <% } %>
131
+ </div>
132
+ </div>
133
+
134
+ <!-- AI Crawler Notice (if enabled) -->
135
+ <% if (blogConfig.allowAICrawlers !== false) { %>
136
+ <div class="ai-notice">
137
+ <p>
138
+ This content is optimized for AI assistants (Claude, ChatGPT, etc.).
139
+ Generated with <a href="https://www.npmjs.com/package/@edtools/cli" target="_blank" rel="noopener noreferrer">@edtools/cli</a>
140
+ </p>
141
+ </div>
142
+ <% } %>
143
+ </div>
144
+ </footer>
145
+
146
+ <style>
147
+ .blog-footer {
148
+ background: var(--bg-light);
149
+ border-top: 1px solid var(--border-color);
150
+ margin-top: 4rem;
151
+ padding: 3rem 0 2rem;
152
+ }
153
+
154
+ .footer-container {
155
+ max-width: 1200px;
156
+ margin: 0 auto;
157
+ padding: 0 1.5rem;
158
+ }
159
+
160
+ .footer-content {
161
+ display: grid;
162
+ grid-template-columns: 2fr 1fr 1fr 1fr;
163
+ gap: 2rem;
164
+ margin-bottom: 3rem;
165
+ }
166
+
167
+ .footer-section-title {
168
+ font-size: 0.875rem;
169
+ font-weight: 600;
170
+ text-transform: uppercase;
171
+ letter-spacing: 0.05em;
172
+ color: var(--text-color);
173
+ margin-bottom: 1rem;
174
+ }
175
+
176
+ .footer-brand .footer-logo {
177
+ height: 32px;
178
+ width: auto;
179
+ margin-bottom: 1rem;
180
+ }
181
+
182
+ .footer-brand .footer-title {
183
+ font-size: 1.25rem;
184
+ font-weight: 700;
185
+ color: var(--text-color);
186
+ margin-bottom: 0.75rem;
187
+ }
188
+
189
+ .footer-brand .footer-description {
190
+ color: var(--text-light);
191
+ font-size: 0.9375rem;
192
+ line-height: 1.6;
193
+ max-width: 300px;
194
+ }
195
+
196
+ .footer-link-list {
197
+ list-style: none;
198
+ padding: 0;
199
+ margin: 0;
200
+ }
201
+
202
+ .footer-link-list li {
203
+ margin-bottom: 0.75rem;
204
+ }
205
+
206
+ .footer-link {
207
+ color: var(--text-light);
208
+ text-decoration: none;
209
+ font-size: 0.9375rem;
210
+ transition: color 0.2s;
211
+ }
212
+
213
+ .footer-link:hover {
214
+ color: var(--primary-color);
215
+ text-decoration: none;
216
+ }
217
+
218
+ .social-links {
219
+ display: flex;
220
+ gap: 1rem;
221
+ margin-bottom: 1.5rem;
222
+ }
223
+
224
+ .social-link {
225
+ display: flex;
226
+ align-items: center;
227
+ justify-content: center;
228
+ width: 40px;
229
+ height: 40px;
230
+ border-radius: 50%;
231
+ background: white;
232
+ color: var(--text-light);
233
+ transition: all 0.2s;
234
+ text-decoration: none;
235
+ }
236
+
237
+ .social-link:hover {
238
+ background: var(--primary-color);
239
+ color: white;
240
+ transform: translateY(-2px);
241
+ }
242
+
243
+ .rss-link-container {
244
+ margin-top: 0.5rem;
245
+ }
246
+
247
+ .rss-link {
248
+ display: inline-flex;
249
+ align-items: center;
250
+ }
251
+
252
+ .footer-bottom {
253
+ display: flex;
254
+ justify-content: space-between;
255
+ align-items: center;
256
+ padding-top: 2rem;
257
+ border-top: 1px solid var(--border-color);
258
+ flex-wrap: wrap;
259
+ gap: 1rem;
260
+ }
261
+
262
+ .footer-copyright p {
263
+ color: var(--text-light);
264
+ font-size: 0.875rem;
265
+ margin: 0;
266
+ }
267
+
268
+ .footer-legal {
269
+ display: flex;
270
+ gap: 0.5rem;
271
+ align-items: center;
272
+ }
273
+
274
+ .footer-legal-link {
275
+ color: var(--text-light);
276
+ text-decoration: none;
277
+ font-size: 0.875rem;
278
+ transition: color 0.2s;
279
+ }
280
+
281
+ .footer-legal-link:hover {
282
+ color: var(--primary-color);
283
+ text-decoration: none;
284
+ }
285
+
286
+ .ai-notice {
287
+ margin-top: 2rem;
288
+ padding-top: 1.5rem;
289
+ border-top: 1px solid var(--border-color);
290
+ text-align: center;
291
+ }
292
+
293
+ .ai-notice p {
294
+ color: var(--text-light);
295
+ font-size: 0.8125rem;
296
+ margin: 0;
297
+ }
298
+
299
+ .ai-notice a {
300
+ color: var(--primary-color);
301
+ text-decoration: none;
302
+ }
303
+
304
+ .ai-notice a:hover {
305
+ text-decoration: underline;
306
+ }
307
+
308
+ /* Mobile responsive */
309
+ @media (max-width: 1024px) {
310
+ .footer-content {
311
+ grid-template-columns: 1fr 1fr;
312
+ }
313
+ }
314
+
315
+ @media (max-width: 640px) {
316
+ .footer-content {
317
+ grid-template-columns: 1fr;
318
+ }
319
+
320
+ .footer-bottom {
321
+ flex-direction: column;
322
+ text-align: center;
323
+ }
324
+
325
+ .footer-legal {
326
+ flex-wrap: wrap;
327
+ justify-content: center;
328
+ }
329
+ }
330
+ </style>
@@ -0,0 +1,208 @@
1
+ <!-- Global Blog Header Component -->
2
+ <header class="blog-header">
3
+ <div class="header-container">
4
+ <div class="header-logo">
5
+ <% if (blogConfig.logo) { %>
6
+ <a href="<%= blogConfig.websiteUrl || '/' %>">
7
+ <img src="<%= blogConfig.logo %>" alt="<%= blogConfig.name %>" class="logo-image">
8
+ </a>
9
+ <% } else { %>
10
+ <a href="<%= blogConfig.websiteUrl || '/' %>" class="logo-text">
11
+ <%= blogConfig.name %>
12
+ </a>
13
+ <% } %>
14
+ </div>
15
+
16
+ <nav class="header-nav" aria-label="Main navigation">
17
+ <% if (blogConfig.navigation && blogConfig.navigation.length > 0) { %>
18
+ <% blogConfig.navigation.forEach(item => { %>
19
+ <a href="<%= item.url %>" class="nav-link <%= item.active ? 'active' : '' %>">
20
+ <%= item.label %>
21
+ </a>
22
+ <% }) %>
23
+ <% } else { %>
24
+ <!-- Default navigation if not configured -->
25
+ <a href="<%= blogConfig.websiteUrl || '/' %>" class="nav-link">Home</a>
26
+ <a href="/blog/" class="nav-link active">Blog</a>
27
+ <% } %>
28
+ </nav>
29
+
30
+ <% if (blogConfig.cta) { %>
31
+ <div class="header-cta">
32
+ <a href="<%= blogConfig.cta.url %>" class="cta-button">
33
+ <%= blogConfig.cta.text %>
34
+ </a>
35
+ </div>
36
+ <% } %>
37
+
38
+ <!-- Mobile Menu Toggle -->
39
+ <button class="mobile-menu-toggle" aria-label="Toggle menu" onclick="toggleMobileMenu()">
40
+ <svg width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
41
+ <line x1="3" y1="12" x2="21" y2="12"></line>
42
+ <line x1="3" y1="6" x2="21" y2="6"></line>
43
+ <line x1="3" y1="18" x2="21" y2="18"></line>
44
+ </svg>
45
+ </button>
46
+ </div>
47
+
48
+ <!-- Mobile Menu (hidden by default) -->
49
+ <div class="mobile-menu" id="mobile-menu">
50
+ <% if (blogConfig.navigation && blogConfig.navigation.length > 0) { %>
51
+ <% blogConfig.navigation.forEach(item => { %>
52
+ <a href="<%= item.url %>" class="mobile-nav-link <%= item.active ? 'active' : '' %>">
53
+ <%= item.label %>
54
+ </a>
55
+ <% }) %>
56
+ <% } %>
57
+ <% if (blogConfig.cta) { %>
58
+ <a href="<%= blogConfig.cta.url %>" class="mobile-cta-button">
59
+ <%= blogConfig.cta.text %>
60
+ </a>
61
+ <% } %>
62
+ </div>
63
+ </header>
64
+
65
+ <style>
66
+ .blog-header {
67
+ background: white;
68
+ border-bottom: 1px solid var(--border-color);
69
+ position: sticky;
70
+ top: 0;
71
+ z-index: 1000;
72
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
73
+ }
74
+
75
+ .header-container {
76
+ max-width: 1200px;
77
+ margin: 0 auto;
78
+ padding: 1rem 1.5rem;
79
+ display: flex;
80
+ align-items: center;
81
+ justify-content: space-between;
82
+ gap: 2rem;
83
+ }
84
+
85
+ .header-logo .logo-image {
86
+ height: 40px;
87
+ width: auto;
88
+ }
89
+
90
+ .header-logo .logo-text {
91
+ font-size: 1.5rem;
92
+ font-weight: 700;
93
+ color: var(--text-color);
94
+ text-decoration: none;
95
+ }
96
+
97
+ .header-logo .logo-text:hover {
98
+ color: var(--primary-color);
99
+ }
100
+
101
+ .header-nav {
102
+ display: flex;
103
+ align-items: center;
104
+ gap: 2rem;
105
+ flex: 1;
106
+ }
107
+
108
+ .nav-link {
109
+ color: var(--text-color);
110
+ text-decoration: none;
111
+ font-weight: 500;
112
+ font-size: 0.9375rem;
113
+ transition: color 0.2s;
114
+ }
115
+
116
+ .nav-link:hover,
117
+ .nav-link.active {
118
+ color: var(--primary-color);
119
+ text-decoration: none;
120
+ }
121
+
122
+ .header-cta .cta-button {
123
+ display: inline-block;
124
+ padding: 0.5rem 1.25rem;
125
+ background: var(--primary-color);
126
+ color: white;
127
+ font-weight: 600;
128
+ font-size: 0.9375rem;
129
+ border-radius: 0.375rem;
130
+ text-decoration: none;
131
+ transition: transform 0.2s, box-shadow 0.2s;
132
+ }
133
+
134
+ .header-cta .cta-button:hover {
135
+ transform: translateY(-1px);
136
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
137
+ text-decoration: none;
138
+ }
139
+
140
+ .mobile-menu-toggle {
141
+ display: none;
142
+ background: none;
143
+ border: none;
144
+ cursor: pointer;
145
+ color: var(--text-color);
146
+ padding: 0.5rem;
147
+ }
148
+
149
+ .mobile-menu {
150
+ display: none;
151
+ flex-direction: column;
152
+ gap: 0.5rem;
153
+ padding: 1rem 1.5rem;
154
+ border-top: 1px solid var(--border-color);
155
+ background: white;
156
+ }
157
+
158
+ .mobile-menu.active {
159
+ display: flex;
160
+ }
161
+
162
+ .mobile-nav-link {
163
+ color: var(--text-color);
164
+ text-decoration: none;
165
+ font-weight: 500;
166
+ padding: 0.75rem;
167
+ border-radius: 0.375rem;
168
+ transition: background 0.2s;
169
+ }
170
+
171
+ .mobile-nav-link:hover,
172
+ .mobile-nav-link.active {
173
+ background: var(--bg-light);
174
+ color: var(--primary-color);
175
+ text-decoration: none;
176
+ }
177
+
178
+ .mobile-cta-button {
179
+ display: inline-block;
180
+ padding: 0.75rem 1.25rem;
181
+ background: var(--primary-color);
182
+ color: white;
183
+ font-weight: 600;
184
+ text-align: center;
185
+ border-radius: 0.375rem;
186
+ text-decoration: none;
187
+ margin-top: 0.5rem;
188
+ }
189
+
190
+ /* Mobile responsive */
191
+ @media (max-width: 768px) {
192
+ .header-nav,
193
+ .header-cta {
194
+ display: none;
195
+ }
196
+
197
+ .mobile-menu-toggle {
198
+ display: block;
199
+ }
200
+ }
201
+ </style>
202
+
203
+ <script>
204
+ function toggleMobileMenu() {
205
+ const menu = document.getElementById('mobile-menu');
206
+ menu.classList.toggle('active');
207
+ }
208
+ </script>