Mercari Markdown Preview Technical Specification
Mercari Markdown Preview Technical Specification
1. Overview
Purpose
The Mercari Markdown Previewer provides real-time visual preview of product listings before they are uploaded to Mercari Shops. It processes markdown files with frontmatter metadata to display product information exactly as it will appear in the marketplace.
Core Requirements
The previewer must handle:
- Frontmatter parsing for product metadata
- Image URL generation from slugs
- Real-time file watching and hot reload
- Character limit validation for Mercari constraints
- Markdown content rendering with proper formatting
2. Frontmatter Processing
Title Field
title: "OXI Instruments ONE MKⅡ Black モジュラーシンセ シーケンサー"
Processing Requirements:
- Extract title from frontmatter YAML
- Display as primary page heading
- Validate character count (max 100 characters for Mercari)
- Show real-time character count indicator
- Apply warning styling when approaching or exceeding limit
Image Fields (image1 to image20)
image1: "oxi-one-mk2-black"
image2: "oxi-one-mk2-black-2"
image3: "oxi-one-mk2-black-3 R" # R flag = replacement pending
image4: "" # Empty = no image
image5: "D" # D flag = marked for deletion
Processing Logic:
- Parse all image fields (image1 through image20)
- Extract base slug by removing temporary flags (R, D)
- Treat D flag as deletion indicator (display as empty)
- Ignore R flag for URL generation (use base slug)
- Skip empty string fields
3. Image URL Generation
Conversion Logic
Base Pattern:
const generateImageUrl = (slug) => {
if (!slug || slug === 'D') return null;
// Remove temporary flags
const cleanSlug = slug.replace(/ [RD]$/, '');
// Generate full URL
return `https://takazudomodular.com/images/p/${cleanSlug}/mercari.png`;
};
URL Pattern Structure
https://takazudomodular.com/images/p/{slug}/mercari.png
│ │ │ │
└── Base domain │ │ └── Fixed filename
│ └── Product slug
└── Image path prefix
Special Cases
Empty Strings
image4: ""
- Result: No image displayed
- UI: Show empty slot indicator
R Flag (Replacement)
image3: "oxi-one-mk2-black-3 R"
- Processing: Remove ’ R’, use
oxi-one-mk2-black-3 - URL:
https://takazudomodular.com/images/p/oxi-one-mk2-black-3/mercari.png - UI: Optional indicator showing “replacement pending”
D Flag (Deletion)
image5: "D"
- Processing: Treat as empty
- Result: No image displayed
- UI: Show “marked for deletion” indicator
Example Transformations
| Frontmatter Value | Generated URL | Display Status |
|---|---|---|
"oxi-one-mk2-black" | https://takazudomodular.com/images/p/oxi-one-mk2-black/mercari.png | Normal |
"oxi-one-mk2-black-2 R" | https://takazudomodular.com/images/p/oxi-one-mk2-black-2/mercari.png | Normal (R ignored) |
"D" | None | Empty (deletion) |
"" | None | Empty |
4. Display Implementation
Image Gallery
interface ImageGalleryProps {
images: Array<{
position: number;
slug: string;
url: string | null;
status: 'normal' | 'replacement' | 'deletion' | 'empty';
}>;
}
Display Requirements:
- Grid layout showing all 20 image positions
- Filled positions show actual images
- Empty positions show placeholder with position number
- Lazy loading for performance
- Click to view full size
- Drag-and-drop reordering capability
Title Display
<div className="title-container">
<h1 className="product-title">{title}</h1>
<div className="char-count">
<span className={charCount > 100 ? 'over-limit' : 'within-limit'}>
{charCount} / 100
</span>
</div>
</div>
Visual Specifications:
- Font size: 24px bold
- Character counter: Always visible
- Color coding:
- Green: 0-80 characters
- Yellow: 81-100 characters
- Red: Over 100 characters
Content Display
interface ContentRenderer {
markdown: string;
maxCharacters: 5000;
preserveFormatting: boolean;
supportedElements: [
'headings',
'lists',
'bold',
'italic',
'linebreaks'
];
}
Rendering Requirements:
- Parse markdown to HTML
- Preserve line breaks and spacing
- Show character count for entire description
- Highlight when approaching 5000 character limit
- Support basic Mercari-compatible formatting only
5. Live Preview Features
Real-time Updates
// File watching configuration
const watchConfig = {
paths: ['*.md'],
events: ['change', 'add'],
debounce: 300, // ms
preserveState: {
scrollPosition: true,
expandedSections: true,
selectedTab: true
}
};
Update Flow:
- Detect file system change
- Debounce rapid changes (300ms)
- Parse updated frontmatter
- Regenerate image URLs
- Update preview without full reload
- Preserve user’s scroll position
Visual Indicators
/* Image slot states */
.image-slot.filled { border: 2px solid #4CAF50; }
.image-slot.empty { border: 2px dashed #ccc; }
.image-slot.replacement { border: 2px solid #FF9800; }
.image-slot.deletion { border: 2px solid #f44336; opacity: 0.5; }
Indicator System:
- Green border: Active image
- Gray dashed: Empty slot
- Orange border: Replacement pending (R flag)
- Red translucent: Marked for deletion (D flag)
- Position numbers: Always visible for reference
6. Example Rendering
Input Example
---
title: "OXI Instruments ONE MKⅡ Black モジュラーシンセ シーケンサー"
image1: "oxi-one-mk2-black"
image2: "oxi-one-mk2-black-2"
image3: "oxi-one-mk2-black-3 R"
image4: ""
image5: "D"
image6: "oxi-one-mk2-black-6"
---
# 商品説明
OXI ONE MKⅡは、革新的なシーケンサーモジュールです。
## 特徴
- 8トラックシーケンサー
- 高精度クロック
- 直感的なインターフェース
Output Visualization
┌─────────────────────────────────────────────┐
│ OXI Instruments ONE MKⅡ Black モジュラー... │ [92/100]
├─────────────────────────────────────────────┤
│ Images │
│ ┌───┬───┬───┬───┬───┐ │
│ │ 1 │ 2 │3⚠│ 4 │5✗│ (1: image) │
│ │IMG│IMG│IMG│[ ]│[D]│ (2: image) │
│ └───┴───┴───┴───┴───┘ (3: image + R flag) │
│ ┌───┬───┬───┬───┬───┐ (4: empty) │
│ │ 6 │ 7 │ 8 │ 9 │10 │ (5: deletion) │
│ │IMG│[ ]│[ ]│[ ]│[ ]│ (6: image) │
│ └───┴───┴───┴───┴───┘ │
├─────────────────────────────────────────────┤
│ Description [248/5000] │
│ │
│ 商品説明 │
│ OXI ONE MKⅡは、革新的なシーケンサー... │
│ │
│ 特徴 │
│ • 8トラックシーケンサー │
│ • 高精度クロック │
│ • 直感的なインターフェース │
└─────────────────────────────────────────────┘
7. Error Handling
Invalid Image Slugs
const handleImageError = (slug, position) => {
console.error(`Failed to load image ${position}: ${slug}`);
return {
fallback: '/placeholder-error.png',
errorMessage: `Image not found: ${slug}`,
retryable: true,
retryDelay: 5000
};
};
Missing Images
Handling Strategy:
- Attempt to load image from generated URL
- On 404, show error placeholder
- Log error with position and slug
- Provide manual refresh option
- Cache failure to avoid repeated requests
Malformed Frontmatter
try {
const frontmatter = parseFrontmatter(content);
} catch (error) {
return {
error: 'Invalid frontmatter format',
details: error.message,
fallbackToRawDisplay: true
};
}
Recovery Actions:
- Display error message with details
- Show raw markdown content as fallback
- Highlight problematic lines if possible
- Provide syntax validation hints
8. Integration Points
File Watching System
// Chokidar configuration for file watching
const watcher = chokidar.watch('*.md', {
persistent: true,
ignoreInitial: false,
awaitWriteFinish: {
stabilityThreshold: 300,
pollInterval: 100
}
});
Docusaurus Plugin Architecture
// Plugin structure
module.exports = function mercariPreviewPlugin(context, options) {
return {
name: 'docusaurus-plugin-mercari-preview',
async contentLoaded({content, actions}) {
// Process markdown files
// Generate preview pages
},
configureWebpack(config, isServer) {
return {
module: {
rules: [
{
test: /\.md$/,
use: ['raw-loader', 'frontmatter-loader']
}
]
}
};
}
};
};
Performance Optimization
Optimization Strategies:
- Image Loading
- Lazy load images below fold
- Progressive loading with blur placeholders
- Cache processed URLs
- Markdown Rendering
- Memoize parsed markdown
- Virtual scrolling for long content
- Debounce re-renders
- File Watching
- Batch multiple rapid changes
- Incremental updates only
- Avoid full page reloads
- Memory Management
- Limit cached preview history
- Clean up old watchers
- Dispose unused image objects
// Performance monitoring
const performanceMetrics = {
imageLoadTime: [],
markdownParseTime: [],
renderTime: [],
report() {
return {
avgImageLoad: average(this.imageLoadTime),
avgParse: average(this.markdownParseTime),
avgRender: average(this.renderTime)
};
}
};
Implementation Checklist
- Frontmatter parser with YAML support
- Image URL generator with flag handling
- Live file watching system
- Character count validators
- Markdown renderer with Mercari formatting
- Image gallery with drag-and-drop
- Error handling and fallbacks
- Performance monitoring
- Docusaurus plugin integration
- Hot reload without scroll loss