@terrymooreii/sia 1.0.2 → 2.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.
- package/_config.yml +33 -0
- package/bin/cli.js +51 -0
- package/defaults/includes/footer.njk +14 -0
- package/defaults/includes/header.njk +71 -0
- package/defaults/includes/pagination.njk +26 -0
- package/defaults/includes/tag-list.njk +11 -0
- package/defaults/layouts/base.njk +41 -0
- package/defaults/layouts/note.njk +25 -0
- package/defaults/layouts/page.njk +14 -0
- package/defaults/layouts/post.njk +43 -0
- package/defaults/pages/blog.njk +36 -0
- package/defaults/pages/feed.njk +28 -0
- package/defaults/pages/index.njk +60 -0
- package/defaults/pages/notes.njk +34 -0
- package/defaults/pages/tag.njk +41 -0
- package/defaults/pages/tags.njk +39 -0
- package/defaults/styles/main.css +1074 -0
- package/lib/assets.js +234 -0
- package/lib/build.js +260 -19
- package/lib/collections.js +191 -0
- package/lib/config.js +114 -0
- package/lib/content.js +323 -0
- package/lib/index.js +53 -18
- package/lib/init.js +555 -6
- package/lib/new.js +379 -41
- package/lib/server.js +257 -0
- package/lib/templates.js +249 -0
- package/package.json +30 -15
- package/readme.md +212 -63
- package/src/images/.gitkeep +3 -0
- package/src/notes/2024-12-17-first-note.md +6 -0
- package/src/pages/about.md +29 -0
- package/src/posts/2024-12-16-markdown-features.md +76 -0
- package/src/posts/2024-12-17-welcome-to-sia.md +78 -0
- package/src/posts/2024-12-17-welcome-to-static-forge.md +78 -0
- package/.prettierignore +0 -3
- package/.prettierrc +0 -8
- package/lib/helpers.js +0 -37
- package/lib/markdown.js +0 -33
- package/lib/parse.js +0 -100
- package/lib/readconfig.js +0 -18
- package/lib/rss.js +0 -63
- package/templates/siarc-template.js +0 -53
- package/templates/src/_partials/_footer.njk +0 -1
- package/templates/src/_partials/_head.njk +0 -35
- package/templates/src/_partials/_header.njk +0 -1
- package/templates/src/_partials/_layout.njk +0 -12
- package/templates/src/_partials/_nav.njk +0 -12
- package/templates/src/_partials/page.njk +0 -5
- package/templates/src/_partials/post.njk +0 -13
- package/templates/src/_partials/posts.njk +0 -19
- package/templates/src/assets/android-chrome-192x192.png +0 -0
- package/templates/src/assets/android-chrome-512x512.png +0 -0
- package/templates/src/assets/apple-touch-icon.png +0 -0
- package/templates/src/assets/favicon-16x16.png +0 -0
- package/templates/src/assets/favicon-32x32.png +0 -0
- package/templates/src/assets/favicon.ico +0 -0
- package/templates/src/assets/site.webmanifest +0 -19
- package/templates/src/content/index.md +0 -7
- package/templates/src/css/markdown.css +0 -1210
- package/templates/src/css/theme.css +0 -120
package/lib/config.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import yaml from 'js-yaml';
|
|
4
|
+
|
|
5
|
+
// Default configuration
|
|
6
|
+
const defaultConfig = {
|
|
7
|
+
site: {
|
|
8
|
+
title: 'My Site',
|
|
9
|
+
description: 'A static site built with Static Forge',
|
|
10
|
+
url: 'http://localhost:3000',
|
|
11
|
+
author: 'Anonymous'
|
|
12
|
+
},
|
|
13
|
+
input: 'src',
|
|
14
|
+
output: 'dist',
|
|
15
|
+
layouts: '_layouts',
|
|
16
|
+
includes: '_includes',
|
|
17
|
+
collections: {
|
|
18
|
+
posts: {
|
|
19
|
+
path: 'posts',
|
|
20
|
+
layout: 'post',
|
|
21
|
+
permalink: '/blog/:slug/',
|
|
22
|
+
sortBy: 'date',
|
|
23
|
+
sortOrder: 'desc'
|
|
24
|
+
},
|
|
25
|
+
pages: {
|
|
26
|
+
path: 'pages',
|
|
27
|
+
layout: 'page',
|
|
28
|
+
permalink: '/:slug/'
|
|
29
|
+
},
|
|
30
|
+
notes: {
|
|
31
|
+
path: 'notes',
|
|
32
|
+
layout: 'note',
|
|
33
|
+
permalink: '/notes/:slug/',
|
|
34
|
+
sortBy: 'date',
|
|
35
|
+
sortOrder: 'desc'
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
pagination: {
|
|
39
|
+
size: 10
|
|
40
|
+
},
|
|
41
|
+
server: {
|
|
42
|
+
port: 3000
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Deep merge two objects
|
|
48
|
+
*/
|
|
49
|
+
function deepMerge(target, source) {
|
|
50
|
+
const result = { ...target };
|
|
51
|
+
|
|
52
|
+
for (const key in source) {
|
|
53
|
+
if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
|
|
54
|
+
result[key] = deepMerge(result[key] || {}, source[key]);
|
|
55
|
+
} else {
|
|
56
|
+
result[key] = source[key];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Load configuration from YAML or JSON file
|
|
65
|
+
*/
|
|
66
|
+
export function loadConfig(rootDir = process.cwd()) {
|
|
67
|
+
let userConfig = {};
|
|
68
|
+
|
|
69
|
+
// Try to load _config.yml first, then _config.json
|
|
70
|
+
const yamlPath = join(rootDir, '_config.yml');
|
|
71
|
+
const jsonPath = join(rootDir, '_config.json');
|
|
72
|
+
|
|
73
|
+
if (existsSync(yamlPath)) {
|
|
74
|
+
try {
|
|
75
|
+
const content = readFileSync(yamlPath, 'utf-8');
|
|
76
|
+
userConfig = yaml.load(content) || {};
|
|
77
|
+
console.log('📄 Loaded configuration from _config.yml');
|
|
78
|
+
} catch (err) {
|
|
79
|
+
console.error('Error parsing _config.yml:', err.message);
|
|
80
|
+
}
|
|
81
|
+
} else if (existsSync(jsonPath)) {
|
|
82
|
+
try {
|
|
83
|
+
const content = readFileSync(jsonPath, 'utf-8');
|
|
84
|
+
userConfig = JSON.parse(content);
|
|
85
|
+
console.log('📄 Loaded configuration from _config.json');
|
|
86
|
+
} catch (err) {
|
|
87
|
+
console.error('Error parsing _config.json:', err.message);
|
|
88
|
+
}
|
|
89
|
+
} else {
|
|
90
|
+
console.log('⚠️ No config file found, using defaults');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Merge user config with defaults
|
|
94
|
+
const config = deepMerge(defaultConfig, userConfig);
|
|
95
|
+
|
|
96
|
+
// Add computed paths
|
|
97
|
+
config.rootDir = rootDir;
|
|
98
|
+
config.inputDir = join(rootDir, config.input);
|
|
99
|
+
config.outputDir = join(rootDir, config.output);
|
|
100
|
+
config.layoutsDir = join(rootDir, config.layouts);
|
|
101
|
+
config.includesDir = join(rootDir, config.includes);
|
|
102
|
+
|
|
103
|
+
return config;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Get the default configuration
|
|
108
|
+
*/
|
|
109
|
+
export function getDefaultConfig() {
|
|
110
|
+
return { ...defaultConfig };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export default { loadConfig, getDefaultConfig };
|
|
114
|
+
|
package/lib/content.js
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import { readFileSync, readdirSync, statSync, existsSync } from 'fs';
|
|
2
|
+
import { join, basename, extname, relative } from 'path';
|
|
3
|
+
import matter from 'gray-matter';
|
|
4
|
+
import { Marked } from 'marked';
|
|
5
|
+
import { markedHighlight } from 'marked-highlight';
|
|
6
|
+
import { markedEmoji } from 'marked-emoji';
|
|
7
|
+
import hljs from 'highlight.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Default emoji map for shortcode support
|
|
11
|
+
* Common emojis - extend as needed
|
|
12
|
+
*/
|
|
13
|
+
const emojis = {
|
|
14
|
+
smile: '😄',
|
|
15
|
+
grinning: '😀',
|
|
16
|
+
joy: '😂',
|
|
17
|
+
heart: '❤️',
|
|
18
|
+
thumbsup: '👍',
|
|
19
|
+
thumbsdown: '👎',
|
|
20
|
+
clap: '👏',
|
|
21
|
+
fire: '🔥',
|
|
22
|
+
rocket: '🚀',
|
|
23
|
+
star: '⭐',
|
|
24
|
+
sparkles: '✨',
|
|
25
|
+
check: '✅',
|
|
26
|
+
x: '❌',
|
|
27
|
+
warning: '⚠️',
|
|
28
|
+
bulb: '💡',
|
|
29
|
+
memo: '📝',
|
|
30
|
+
book: '📖',
|
|
31
|
+
link: '🔗',
|
|
32
|
+
eyes: '👀',
|
|
33
|
+
thinking: '🤔',
|
|
34
|
+
wave: '👋',
|
|
35
|
+
pray: '🙏',
|
|
36
|
+
muscle: '💪',
|
|
37
|
+
tada: '🎉',
|
|
38
|
+
party: '🥳',
|
|
39
|
+
coffee: '☕',
|
|
40
|
+
bug: '🐛',
|
|
41
|
+
wrench: '🔧',
|
|
42
|
+
hammer: '🔨',
|
|
43
|
+
gear: '⚙️',
|
|
44
|
+
lock: '🔒',
|
|
45
|
+
key: '🔑',
|
|
46
|
+
zap: '⚡',
|
|
47
|
+
bomb: '💣',
|
|
48
|
+
gem: '💎',
|
|
49
|
+
trophy: '🏆',
|
|
50
|
+
medal: '🏅',
|
|
51
|
+
crown: '👑',
|
|
52
|
+
sun: '☀️',
|
|
53
|
+
moon: '🌙',
|
|
54
|
+
cloud: '☁️',
|
|
55
|
+
rain: '🌧️',
|
|
56
|
+
snow: '❄️',
|
|
57
|
+
earth: '🌍',
|
|
58
|
+
tree: '🌳',
|
|
59
|
+
flower: '🌸',
|
|
60
|
+
apple: '🍎',
|
|
61
|
+
pizza: '🍕',
|
|
62
|
+
beer: '🍺',
|
|
63
|
+
wine: '🍷',
|
|
64
|
+
cat: '🐱',
|
|
65
|
+
dog: '🐶',
|
|
66
|
+
bird: '🐦',
|
|
67
|
+
fish: '🐟',
|
|
68
|
+
whale: '🐳',
|
|
69
|
+
snake: '🐍',
|
|
70
|
+
turtle: '🐢',
|
|
71
|
+
octopus: '🐙',
|
|
72
|
+
crab: '🦀',
|
|
73
|
+
shrimp: '🦐',
|
|
74
|
+
100: '💯',
|
|
75
|
+
'+1': '👍',
|
|
76
|
+
'-1': '👎',
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Configure marked with syntax highlighting and emoji support
|
|
81
|
+
*/
|
|
82
|
+
const marked = new Marked(
|
|
83
|
+
markedHighlight({
|
|
84
|
+
langPrefix: 'hljs language-',
|
|
85
|
+
highlight(code, lang) {
|
|
86
|
+
if (lang && hljs.getLanguage(lang)) {
|
|
87
|
+
try {
|
|
88
|
+
return hljs.highlight(code, { language: lang }).value;
|
|
89
|
+
} catch (err) {
|
|
90
|
+
console.warn(`Highlight.js error for language "${lang}":`, err.message);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Auto-detect language if not specified
|
|
94
|
+
try {
|
|
95
|
+
return hljs.highlightAuto(code).value;
|
|
96
|
+
} catch (err) {
|
|
97
|
+
return code;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}),
|
|
101
|
+
markedEmoji({
|
|
102
|
+
emojis,
|
|
103
|
+
renderer: (token) => token.emoji
|
|
104
|
+
})
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// Configure marked options
|
|
108
|
+
marked.setOptions({
|
|
109
|
+
gfm: true,
|
|
110
|
+
breaks: false
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Generate a URL-friendly slug from a string
|
|
115
|
+
*/
|
|
116
|
+
export function slugify(str) {
|
|
117
|
+
return str
|
|
118
|
+
.toLowerCase()
|
|
119
|
+
.replace(/[^\w\s-]/g, '')
|
|
120
|
+
.replace(/[\s_-]+/g, '-')
|
|
121
|
+
.replace(/^-+|-+$/g, '');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Extract slug from filename (removes date prefix if present)
|
|
126
|
+
*/
|
|
127
|
+
export function getSlugFromFilename(filename) {
|
|
128
|
+
// Remove extension
|
|
129
|
+
const name = basename(filename, extname(filename));
|
|
130
|
+
|
|
131
|
+
// Check for date prefix pattern: YYYY-MM-DD-slug
|
|
132
|
+
const datePattern = /^\d{4}-\d{2}-\d{2}-(.+)$/;
|
|
133
|
+
const match = name.match(datePattern);
|
|
134
|
+
|
|
135
|
+
if (match) {
|
|
136
|
+
return match[1];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return slugify(name);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Extract date from filename if present
|
|
144
|
+
*/
|
|
145
|
+
export function getDateFromFilename(filename) {
|
|
146
|
+
const name = basename(filename, extname(filename));
|
|
147
|
+
const datePattern = /^(\d{4}-\d{2}-\d{2})/;
|
|
148
|
+
const match = name.match(datePattern);
|
|
149
|
+
|
|
150
|
+
if (match) {
|
|
151
|
+
return new Date(match[1]);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Parse a markdown file with front matter
|
|
159
|
+
*/
|
|
160
|
+
export function parseContent(filePath) {
|
|
161
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
162
|
+
const { data: frontMatter, content: markdown } = matter(content);
|
|
163
|
+
|
|
164
|
+
// Parse markdown to HTML
|
|
165
|
+
const html = marked.parse(markdown);
|
|
166
|
+
|
|
167
|
+
// Get slug from front matter or filename
|
|
168
|
+
const slug = frontMatter.slug || getSlugFromFilename(filePath);
|
|
169
|
+
|
|
170
|
+
// Get date from front matter or filename
|
|
171
|
+
let date = frontMatter.date;
|
|
172
|
+
if (date) {
|
|
173
|
+
date = new Date(date);
|
|
174
|
+
} else {
|
|
175
|
+
date = getDateFromFilename(filePath) || new Date();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Extract excerpt (first paragraph or custom excerpt)
|
|
179
|
+
let excerpt = frontMatter.excerpt;
|
|
180
|
+
if (!excerpt) {
|
|
181
|
+
const firstParagraph = markdown.split('\n\n')[0];
|
|
182
|
+
excerpt = firstParagraph.replace(/^#+\s+.+\n?/, '').trim();
|
|
183
|
+
// Limit excerpt length
|
|
184
|
+
if (excerpt.length > 200) {
|
|
185
|
+
excerpt = excerpt.substring(0, 197) + '...';
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Normalize tags to array
|
|
190
|
+
let tags = frontMatter.tags || [];
|
|
191
|
+
if (typeof tags === 'string') {
|
|
192
|
+
tags = tags.split(',').map(t => t.trim());
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
...frontMatter,
|
|
197
|
+
slug,
|
|
198
|
+
date,
|
|
199
|
+
excerpt,
|
|
200
|
+
tags,
|
|
201
|
+
content: html,
|
|
202
|
+
rawContent: markdown,
|
|
203
|
+
filePath,
|
|
204
|
+
draft: frontMatter.draft || false
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Recursively get all markdown files in a directory
|
|
210
|
+
*/
|
|
211
|
+
export function getMarkdownFiles(dir) {
|
|
212
|
+
const files = [];
|
|
213
|
+
|
|
214
|
+
if (!existsSync(dir)) {
|
|
215
|
+
return files;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const items = readdirSync(dir);
|
|
219
|
+
|
|
220
|
+
for (const item of items) {
|
|
221
|
+
const fullPath = join(dir, item);
|
|
222
|
+
const stat = statSync(fullPath);
|
|
223
|
+
|
|
224
|
+
if (stat.isDirectory()) {
|
|
225
|
+
files.push(...getMarkdownFiles(fullPath));
|
|
226
|
+
} else if (item.endsWith('.md') || item.endsWith('.markdown')) {
|
|
227
|
+
files.push(fullPath);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return files;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Load all content from a collection directory
|
|
236
|
+
*/
|
|
237
|
+
export function loadCollection(config, collectionName) {
|
|
238
|
+
const collectionConfig = config.collections[collectionName];
|
|
239
|
+
|
|
240
|
+
if (!collectionConfig) {
|
|
241
|
+
console.warn(`Collection "${collectionName}" not found in config`);
|
|
242
|
+
return [];
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const collectionDir = join(config.inputDir, collectionConfig.path);
|
|
246
|
+
const files = getMarkdownFiles(collectionDir);
|
|
247
|
+
|
|
248
|
+
const items = files
|
|
249
|
+
.map(filePath => {
|
|
250
|
+
try {
|
|
251
|
+
const item = parseContent(filePath);
|
|
252
|
+
|
|
253
|
+
// Add collection-specific metadata
|
|
254
|
+
item.collection = collectionName;
|
|
255
|
+
item.layout = item.layout || collectionConfig.layout;
|
|
256
|
+
|
|
257
|
+
// Generate permalink
|
|
258
|
+
let permalink = item.permalink || collectionConfig.permalink || '/:slug/';
|
|
259
|
+
permalink = permalink
|
|
260
|
+
.replace(':slug', item.slug)
|
|
261
|
+
.replace(':year', item.date.getFullYear())
|
|
262
|
+
.replace(':month', String(item.date.getMonth() + 1).padStart(2, '0'))
|
|
263
|
+
.replace(':day', String(item.date.getDate()).padStart(2, '0'));
|
|
264
|
+
|
|
265
|
+
item.url = permalink;
|
|
266
|
+
item.outputPath = join(config.outputDir, permalink, 'index.html');
|
|
267
|
+
|
|
268
|
+
return item;
|
|
269
|
+
} catch (err) {
|
|
270
|
+
console.error(`Error parsing ${filePath}:`, err.message);
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
})
|
|
274
|
+
.filter(item => item !== null && !item.draft);
|
|
275
|
+
|
|
276
|
+
// Sort items
|
|
277
|
+
const sortBy = collectionConfig.sortBy || 'date';
|
|
278
|
+
const sortOrder = collectionConfig.sortOrder || 'desc';
|
|
279
|
+
|
|
280
|
+
items.sort((a, b) => {
|
|
281
|
+
const aVal = a[sortBy];
|
|
282
|
+
const bVal = b[sortBy];
|
|
283
|
+
|
|
284
|
+
if (aVal instanceof Date && bVal instanceof Date) {
|
|
285
|
+
return sortOrder === 'desc' ? bVal - aVal : aVal - bVal;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (typeof aVal === 'string' && typeof bVal === 'string') {
|
|
289
|
+
return sortOrder === 'desc'
|
|
290
|
+
? bVal.localeCompare(aVal)
|
|
291
|
+
: aVal.localeCompare(bVal);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return 0;
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
return items;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Load all collections defined in config
|
|
302
|
+
*/
|
|
303
|
+
export function loadAllCollections(config) {
|
|
304
|
+
const collections = {};
|
|
305
|
+
|
|
306
|
+
for (const name of Object.keys(config.collections)) {
|
|
307
|
+
collections[name] = loadCollection(config, name);
|
|
308
|
+
console.log(`📚 Loaded ${collections[name].length} items from "${name}" collection`);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return collections;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export default {
|
|
315
|
+
parseContent,
|
|
316
|
+
slugify,
|
|
317
|
+
getSlugFromFilename,
|
|
318
|
+
getDateFromFilename,
|
|
319
|
+
getMarkdownFiles,
|
|
320
|
+
loadCollection,
|
|
321
|
+
loadAllCollections
|
|
322
|
+
};
|
|
323
|
+
|
package/lib/index.js
CHANGED
|
@@ -1,22 +1,57 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Sia - A simple, powerful static site generator
|
|
3
|
+
*/
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
export { loadConfig, getDefaultConfig } from './config.js';
|
|
6
|
+
export {
|
|
7
|
+
parseContent,
|
|
8
|
+
slugify,
|
|
9
|
+
getSlugFromFilename,
|
|
10
|
+
loadCollection,
|
|
11
|
+
loadAllCollections
|
|
12
|
+
} from './content.js';
|
|
13
|
+
export {
|
|
14
|
+
buildTagCollections,
|
|
15
|
+
getAllTags,
|
|
16
|
+
paginate,
|
|
17
|
+
buildSiteData,
|
|
18
|
+
getRecentItems,
|
|
19
|
+
getRelatedItems
|
|
20
|
+
} from './collections.js';
|
|
21
|
+
export {
|
|
22
|
+
createTemplateEngine,
|
|
23
|
+
renderTemplate,
|
|
24
|
+
renderString
|
|
25
|
+
} from './templates.js';
|
|
26
|
+
export {
|
|
27
|
+
copyImages,
|
|
28
|
+
copyAssets,
|
|
29
|
+
copyStaticAssets,
|
|
30
|
+
writeFile,
|
|
31
|
+
ensureDir
|
|
32
|
+
} from './assets.js';
|
|
33
|
+
export { build, buildCommand } from './build.js';
|
|
34
|
+
export { startServer, devCommand } from './server.js';
|
|
35
|
+
export { newCommand } from './new.js';
|
|
36
|
+
export { initSite, initCommand } from './init.js';
|
|
6
37
|
|
|
7
|
-
|
|
38
|
+
// Default export with version
|
|
39
|
+
import { readFileSync } from 'fs';
|
|
40
|
+
import { join, dirname } from 'path';
|
|
41
|
+
import { fileURLToPath } from 'url';
|
|
8
42
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
break
|
|
19
|
-
default:
|
|
20
|
-
console.log('Missing command')
|
|
21
|
-
break
|
|
43
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
44
|
+
const __dirname = dirname(__filename);
|
|
45
|
+
|
|
46
|
+
let version = '1.0.0';
|
|
47
|
+
try {
|
|
48
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
49
|
+
version = pkg.version;
|
|
50
|
+
} catch (e) {
|
|
51
|
+
// Ignore error
|
|
22
52
|
}
|
|
53
|
+
|
|
54
|
+
export default {
|
|
55
|
+
version
|
|
56
|
+
};
|
|
57
|
+
|