v0.1.4 개발 실행 별칭 및 샘플 콘텐츠 추가
This commit is contained in:
143
scripts/build-sample-content.js
Normal file
143
scripts/build-sample-content.js
Normal file
@@ -0,0 +1,143 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const outputDir = path.join(__dirname, '..', 'seed');
|
||||
const outputFile = path.join(outputDir, 'thred-inspired-sample-content.ghost.json');
|
||||
|
||||
const tags = [
|
||||
{id: 'tag-books', name: 'Books', slug: 'books'},
|
||||
{id: 'tag-business', name: 'Business', slug: 'business'},
|
||||
{id: 'tag-tech', name: 'Tech', slug: 'tech'},
|
||||
{id: 'tag-science', name: 'Science', slug: 'science'},
|
||||
{id: 'tag-design', name: 'Design', slug: 'design'},
|
||||
{id: 'tag-music', name: 'Music', slug: 'music'},
|
||||
{id: 'tag-health', name: 'Health', slug: 'health'},
|
||||
{id: 'tag-gaming', name: 'Gaming', slug: 'gaming'},
|
||||
{id: 'tag-travel', name: 'Travel', slug: 'travel'},
|
||||
{id: 'tag-diy', name: 'DIY', slug: 'diy'}
|
||||
];
|
||||
|
||||
const postBlueprints = [
|
||||
['books', 'Independent bookstores worth planning a full afternoon around', 'A short guide to cozy stores, smart curation, and how to browse without rushing the experience.'],
|
||||
['books', 'How to build a reading routine when your schedule is a mess', 'Simple habits for reading more consistently without turning books into another productivity task.'],
|
||||
['business', 'Pricing freelance design work without undercutting your future self', 'A practical framework for deciding rates, packaging work, and handling client expectations early.'],
|
||||
['business', 'What small teams should document before they scale too fast', 'The lightweight systems that reduce chaos before hiring and handoff complexity grow.'],
|
||||
['tech', 'Setting up your first home server without making it too complicated', 'A beginner-friendly overview of hardware choices, storage planning, and sensible first services.'],
|
||||
['tech', 'AI tools that feel genuinely useful in a daily workflow', 'A grounded look at where automation helps, where it interrupts, and how to evaluate tradeoffs.'],
|
||||
['science', 'Climate reporting habits that make difficult research easier to follow', 'How to read scientific updates with context, avoid hype, and keep track of what changed.'],
|
||||
['science', 'What makes a good science explainer feel trustworthy', 'Clarity, framing, and citation habits that help complex ideas stay readable without becoming shallow.'],
|
||||
['design', 'Portfolio case studies that show thinking instead of decoration', 'How to structure project stories so decisions, constraints, and outcomes are easy to understand.'],
|
||||
['design', 'Why some interfaces feel calm even when they are information dense', 'Spacing, hierarchy, rhythm, and restraint working together to reduce visual stress.'],
|
||||
['music', 'Starter listening setups that make home music sessions more enjoyable', 'A realistic guide to headphones, speakers, and desk setups for focused everyday listening.'],
|
||||
['music', 'Beginner friendly ways to organize samples before a project gets messy', 'Folder structures, naming patterns, and curation habits that save time later.'],
|
||||
['health', 'Morning routines that support energy without pretending every day is perfect', 'Flexible routines for sleep, movement, hydration, and focus that can survive real schedules.'],
|
||||
['health', 'Meal prep ideas for people who get bored of repeating the same lunch', 'Modular ingredients and simple flavor changes that keep weekday meals easier to sustain.'],
|
||||
['gaming', 'Games that are easy to recommend when friends like different genres', 'A list of accessible picks that still feel distinct in pacing, tone, and challenge.'],
|
||||
['gaming', 'What actually matters most in a first gaming PC build', 'The parts worth prioritizing, where to save money, and how to avoid lopsided builds.'],
|
||||
['travel', 'A slower approach to city travel for people who hate checklist tourism', 'How to shape a trip around neighborhoods, cafés, bookstores, and repeated visits instead of rushing.'],
|
||||
['travel', 'Packing for a week with one bag without feeling underprepared', 'A calm, repeatable packing system focused on layering, daily use, and fewer just-in-case items.'],
|
||||
['diy', 'Home workshop basics for makers who only have a small corner to work in', 'The compact tools and storage habits that make limited spaces feel surprisingly capable.'],
|
||||
['diy', 'Simple repair projects that build confidence before bigger DIY upgrades', 'Low-risk weekend fixes that teach useful fundamentals without requiring specialist equipment.']
|
||||
];
|
||||
|
||||
const featureImages = {
|
||||
books: 'https://images.unsplash.com/photo-1521587760476-6c12a4b040da?auto=format&fit=crop&w=1200&q=80',
|
||||
business: 'https://images.unsplash.com/photo-1552664730-d307ca884978?auto=format&fit=crop&w=1200&q=80',
|
||||
tech: 'https://images.unsplash.com/photo-1518770660439-4636190af475?auto=format&fit=crop&w=1200&q=80',
|
||||
science: 'https://images.unsplash.com/photo-1532187863486-abf9dbad1b69?auto=format&fit=crop&w=1200&q=80',
|
||||
design: 'https://images.unsplash.com/photo-1498050108023-c5249f4df085?auto=format&fit=crop&w=1200&q=80',
|
||||
music: 'https://images.unsplash.com/photo-1511379938547-c1f69419868d?auto=format&fit=crop&w=1200&q=80',
|
||||
health: 'https://images.unsplash.com/photo-1517836357463-d25dfeac3438?auto=format&fit=crop&w=1200&q=80',
|
||||
gaming: 'https://images.unsplash.com/photo-1542751371-adc38448a05e?auto=format&fit=crop&w=1200&q=80',
|
||||
travel: 'https://images.unsplash.com/photo-1500530855697-b586d89ba3ee?auto=format&fit=crop&w=1200&q=80',
|
||||
diy: 'https://images.unsplash.com/photo-1504148455328-c376907d081c?auto=format&fit=crop&w=1200&q=80'
|
||||
};
|
||||
|
||||
function toMobiledoc(paragraphs) {
|
||||
return JSON.stringify({
|
||||
version: '0.3.1',
|
||||
atoms: [],
|
||||
cards: [],
|
||||
markups: [],
|
||||
sections: paragraphs.map((text) => [1, 'p', [[0, [], 0, text]]])
|
||||
});
|
||||
}
|
||||
|
||||
function toSlug(text) {
|
||||
return text
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9\s-]/g, '')
|
||||
.trim()
|
||||
.replace(/\s+/g, '-');
|
||||
}
|
||||
|
||||
function dateString(offsetDays) {
|
||||
const date = new Date(Date.UTC(2026, 1, 1, 3, 0, 0));
|
||||
date.setUTCDate(date.getUTCDate() - offsetDays);
|
||||
return date.toISOString().slice(0, 19).replace('T', ' ');
|
||||
}
|
||||
|
||||
const posts = [];
|
||||
const postsMeta = [];
|
||||
const postsTags = [];
|
||||
|
||||
postBlueprints.forEach(([tagSlug, title, excerpt], index) => {
|
||||
const postId = `post-${index + 1}`;
|
||||
const tag = tags.find((item) => item.slug === tagSlug);
|
||||
const body = [
|
||||
excerpt,
|
||||
'This sample post exists to help preview archive lists, tag pages, and reading layouts while the theme is being refined.',
|
||||
'Once the structure and styling feel right, these placeholders can be replaced with real editorial content inside Ghost Admin.'
|
||||
];
|
||||
|
||||
posts.push({
|
||||
id: postId,
|
||||
title,
|
||||
slug: toSlug(title),
|
||||
status: 'published',
|
||||
visibility: 'public',
|
||||
type: 'post',
|
||||
featured: index % 5 === 0,
|
||||
custom_excerpt: excerpt,
|
||||
feature_image: featureImages[tagSlug],
|
||||
mobiledoc: toMobiledoc(body),
|
||||
created_at: dateString(index + 3),
|
||||
updated_at: dateString(index + 2),
|
||||
published_at: dateString(index + 3)
|
||||
});
|
||||
|
||||
postsMeta.push({
|
||||
post_id: postId,
|
||||
feature_image_alt: `${tag.name} sample article cover image`,
|
||||
feature_image_caption: `${tag.name} category sample content`
|
||||
});
|
||||
|
||||
postsTags.push({
|
||||
post_id: postId,
|
||||
tag_id: tag.id
|
||||
});
|
||||
});
|
||||
|
||||
const payload = {
|
||||
db: [
|
||||
{
|
||||
meta: {
|
||||
exported_on: Date.now(),
|
||||
version: '6.28.0'
|
||||
},
|
||||
data: {
|
||||
posts,
|
||||
posts_meta: postsMeta,
|
||||
tags,
|
||||
posts_tags: postsTags,
|
||||
users: [],
|
||||
posts_authors: []
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
fs.mkdirSync(outputDir, {recursive: true});
|
||||
fs.writeFileSync(outputFile, JSON.stringify(payload, null, 2));
|
||||
|
||||
console.log(`Sample Ghost import written to ${outputFile}`);
|
||||
@@ -14,6 +14,7 @@ rsync -a --delete \
|
||||
--exclude='.docker/' \
|
||||
--exclude='docs/' \
|
||||
--exclude='local-ghost/' \
|
||||
--exclude='seed/' \
|
||||
--exclude='theme-export/' \
|
||||
--exclude='scripts/' \
|
||||
--exclude='*.zip' \
|
||||
|
||||
Reference in New Issue
Block a user