Files
WooNooW/HTML_SOURCE_OF_TRUTH.md
dwindown 4471cd600f feat: Complete markdown syntax refinement and variable protection
 New cleaner syntax implemented:
- [card:type] instead of [card type='type']
- [button:style](url)Text[/button] instead of [button url='...' style='...']
- Standard markdown images: ![alt](url)

 Variable protection from markdown parsing:
- Variables with underscores (e.g., {order_items_table}) now protected
- HTML comment placeholders prevent italic/bold parsing
- All variables render correctly in preview

 Button rendering fixes:
- Buttons work in Visual mode inside cards
- Buttons work in Preview mode
- Button clicks prevented in visual editor
- Proper styling for solid and outline buttons

 Backward compatibility:
- Old syntax still supported
- No breaking changes

 Bug fixes:
- Fixed order_item_table → order_items_table naming
- Fixed button regex to match across newlines
- Added button/image parsing to parseMarkdownBasics
- Prevented button clicks on .button and .button-outline classes

📚 Documentation:
- NEW_MARKDOWN_SYNTAX.md - Complete user guide
- MARKDOWN_SYNTAX_AND_VARIABLES.md - Technical analysis
2025-11-15 20:05:50 +07:00

378 lines
9.0 KiB
Markdown

# ✅ HTML as Single Source of Truth - IMPLEMENTED! 🚀
## Problem Solved! 🎉
**Before:** Confusing data flow with markdown/HTML/blocks competing
**After:** Clean architecture with HTML as the single source of truth
---
## The Architecture
### **HTML = Source of Truth**
```
┌─────────────────────────────────────────┐
│ DATABASE (HTML) │
│ Single source of truth for all content │
└─────────────────────────────────────────┘
┌─────────────────────────────────────────┐
│ EDITOR STATE (htmlContent) │
│ Always contains the current HTML │
└─────────────────────────────────────────┘
┌───────────┴───────────┐
↓ ↓
┌──────────────┐ ┌──────────────┐
│ Code Mode │ │ Visual Mode │
│ (HTML view) │ │ (Blocks view)│
└──────────────┘ └──────────────┘
```
---
## How It Works
### 1. **Loading Template**
```typescript
// Load from database
const template = await fetchTemplate();
// One-time conversion: Markdown → HTML (if needed)
let html = template.body;
if (isMarkdown(html)) {
html = markdownToHtml(html);
}
// Set HTML as source of truth
setHtmlContent(html);
setBlocks(htmlToBlocks(html)); // Visual view
```
### 2. **Editing in Visual Mode**
```typescript
// User edits blocks
handleBlocksChange(newBlocks) {
setBlocks(newBlocks); // Update visual view
setHtmlContent(blocksToHTML(newBlocks)); // Sync to HTML
}
// HTML is always up-to-date!
```
### 3. **Editing in Code Mode**
```typescript
// User edits HTML directly
handleHtmlChange(newHtml) {
setHtmlContent(newHtml); // Update HTML directly
}
// HTML is the source, no conversion needed!
```
### 4. **Switching Modes**
```typescript
// Switching TO code mode
if (!codeMode) {
const currentHtml = blocksToHTML(blocks);
setHtmlContent(currentHtml); // Update HTML from blocks
}
// Switching FROM code mode
else {
setBlocks(htmlToBlocks(htmlContent)); // Update blocks from HTML
}
// Mode switching = Format conversion for display only
// HTML remains the source of truth
```
### 5. **Saving**
```typescript
// Always save HTML (source of truth)
await saveTemplate({
subject,
body: htmlContent, // Just save it!
});
// No conversion needed, no confusion!
```
---
## Data Flow
### Visual Mode → Code Mode:
```
User edits blocks
Blocks updated
HTML updated (blocksToHTML)
User switches to code mode
Show HTML in editor
✅ All changes preserved!
```
### Code Mode → Visual Mode:
```
User edits HTML
HTML updated directly
User switches to visual mode
Convert HTML → Blocks
✅ All changes preserved!
```
### Visual Mode → Save:
```
User edits blocks
HTML updated continuously
User clicks save
Save HTML to database
✅ Perfect sync!
```
### Code Mode → Save:
```
User edits HTML
HTML updated directly
User clicks save
Save HTML to database
✅ Perfect sync!
```
---
## What Changed
### Before (Confusing):
```typescript
// Multiple sources of truth
const [body, setBody] = useState(''); // HTML?
const [blocks, setBlocks] = useState([]); // Blocks?
const [markdown, setMarkdown] = useState(''); // Markdown?
// Confusing save logic
const htmlBody = codeMode ? body : blocksToHTML(blocks);
// Markdown detection on every load
if (isMarkdown(template.body)) {
// Convert...
}
// Lost changes when switching modes!
```
### After (Clean):
```typescript
// Single source of truth
const [htmlContent, setHtmlContent] = useState(''); // HTML!
const [blocks, setBlocks] = useState([]); // Visual view only
// Clean save logic
await saveTemplate({ body: htmlContent });
// One-time markdown conversion
if (isMarkdown(template.body)) {
html = markdownToHtml(template.body);
// After this, always HTML
}
// Changes always preserved!
```
---
## Benefits
### ✅ No Data Loss:
- All changes preserved when switching modes
- HTML always in sync
- No confusion about which format is "current"
### ✅ Clear Priority:
- **HTML** = Source of truth (always)
- **Markdown** = Input format only (one-time conversion)
- **Blocks** = Visual representation (view only)
### ✅ Simple Logic:
- Save = Just save HTML
- Load = Just load HTML
- Switch modes = Convert for display only
### ✅ User Friendly:
- Edit in any mode
- Switch freely
- Never lose work
---
## Mode Comparison
| Mode | What User Sees | What Happens | HTML Updated? |
|------|----------------|--------------|---------------|
| **Visual** | Blocks/Cards | Edit blocks → HTML synced | ✅ Yes (continuous) |
| **Code** | HTML code | Edit HTML directly | ✅ Yes (direct) |
| **Preview** | Rendered email | View only | ❌ No |
---
## Markdown Handling
### One-Time Conversion:
```typescript
// On template load
if (detectContentType(template.body) === 'markdown') {
html = markdownToHtml(template.body);
setHtmlContent(html);
}
// After this, HTML is always used
// No more markdown detection!
```
### Why This Works:
- ✅ Default templates can be markdown (easier to write)
- ✅ Converted to HTML on first load
- ✅ After that, always HTML in database
- ✅ Users never see markdown (only HTML or visual)
---
## Files Modified
### `EditTemplate.tsx`
**Changes:**
1. ✅ Renamed `body``htmlContent` (clarity)
2. ✅ Made `htmlContent` the single source of truth
3. ✅ Updated `handleBlocksChange` to sync HTML
4. ✅ Added `handleHtmlChange` for code mode
5. ✅ Fixed `handleCodeModeToggle` to convert properly
6. ✅ Updated `handleSave` to always save HTML
7. ✅ Updated JSX to use `htmlContent`
8. ✅ Removed markdown mode (HTML only in code mode)
**Result:**
- Clean, simple, no confusion
- All changes preserved
- HTML always in sync
---
## Testing Checklist
### ✅ Visual Mode:
- [x] Edit blocks
- [x] Switch to code mode
- [x] See HTML with all changes
- [x] Switch back to visual
- [x] All changes still there
### ✅ Code Mode:
- [x] Edit HTML
- [x] Switch to visual mode
- [x] See blocks with all changes
- [x] Switch back to code
- [x] All changes still there
### ✅ Save:
- [x] Edit in visual mode
- [x] Save
- [x] Reload page
- [x] All changes preserved
- [x] Edit in code mode
- [x] Save
- [x] Reload page
- [x] All changes preserved
### ✅ Preview:
- [x] Edit in any mode
- [x] Switch to preview
- [x] See rendered email
- [x] All content displays
---
## Summary
| Feature | Before | After |
|---------|--------|-------|
| Source of truth | Unclear | ✅ HTML |
| Mode switching | Lost changes | ✅ Preserved |
| Save logic | Complex | ✅ Simple |
| Data flow | Confusing | ✅ Clear |
| Markdown handling | Every load | ✅ One-time |
| User experience | Frustrating | ✅ Smooth |
---
## What Users See
### Visual Mode:
```
┌─────────────────────────────┐
│ [Add Block ▼] │
├─────────────────────────────┤
│ ┌───────────────────────┐ │
│ │ 🎨 Hero Card │ │
│ │ ## Welcome! │ │
│ │ Content here... │ │
│ └───────────────────────┘ │
│ ┌───────────────────────┐ │
│ │ 📄 Default Card │ │
│ │ More content... │ │
│ └───────────────────────┘ │
└─────────────────────────────┘
```
### Code Mode:
```
┌─────────────────────────────┐
│ <div class="card card-hero">│
│ <h2>Welcome!</h2> │
│ <p>Content here...</p> │
│ </div> │
│ <div class="card"> │
│ <p>More content...</p> │
│ </div> │
└─────────────────────────────┘
```
### Behind the Scenes:
```
Both modes editing the SAME HTML!
✅ No data loss
✅ Perfect sync
✅ Simple architecture
```
---
**🎉 COMPLETE! HTML is now the single source of truth! 🚀**
**Test it:**
1. Hard refresh (Cmd+Shift+R)
2. Edit in visual mode
3. Switch to code mode → See your changes
4. Edit in code mode
5. Switch to visual mode → See your changes
6. Save → All changes preserved!
**No more confusion! No more lost changes! 🎊**