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
This commit is contained in:
dwindown
2025-11-15 20:05:50 +07:00
parent 550b3b69ef
commit 4471cd600f
45 changed files with 9194 additions and 508 deletions

View File

@@ -1,6 +1,7 @@
import React, { useState, useEffect } from 'react';
import { __ } from '@/lib/i18n';
import { Crown, Info, Save } from 'lucide-react';
import { Crown, Info } from 'lucide-react';
import { SettingsLayout } from './components/SettingsLayout';
import { SettingsCard } from './components/SettingsCard';
import { ToggleField } from './components/ToggleField';
import { Button } from '@/components/ui/button';
@@ -89,27 +90,23 @@ export default function CustomersSettings() {
if (isLoading) {
return (
<div className="space-y-6">
<div>
<h1 className="text-2xl font-bold">{__('Customer Settings')}</h1>
<p className="text-sm text-muted-foreground">
{__('Configure VIP customer qualification')}
</p>
</div>
<SettingsLayout
title={__('Customer Settings')}
description={__('Configure VIP customer qualification')}
isLoading={true}
>
<div className="animate-pulse h-64 bg-muted rounded-lg"></div>
</div>
</SettingsLayout>
);
}
return (
<div className="space-y-6">
<div>
<h1 className="text-2xl font-bold">{__('Customer Settings')}</h1>
<p className="text-sm text-muted-foreground">
{__('Configure VIP customer qualification criteria')}
</p>
</div>
<SettingsLayout
title={__('Customer Settings')}
description={__('Configure VIP customer qualification criteria')}
onSave={handleSave}
saveLabel={__('Save Changes')}
>
{message && (
<div className={`p-4 rounded-lg ${message.includes('success') ? 'bg-green-50 text-green-900' : 'bg-red-50 text-red-900'}`}>
{message}
@@ -227,16 +224,6 @@ export default function CustomersSettings() {
</div>
</div>
</SettingsCard>
<div className="flex justify-end gap-3">
<Button variant="outline" onClick={fetchSettings} disabled={isSaving}>
{__('Reset')}
</Button>
<Button onClick={handleSave} disabled={isSaving}>
<Save className="w-4 h-4 mr-2" />
{isSaving ? __('Saving...') : __('Save Changes')}
</Button>
</div>
</div>
</SettingsLayout>
);
}