BEST FORMAT FOR HINDI/ENGLISH FONTS ON WEBSIE
Complete typography specification and CSS setup for seamless bilingual Hindi and English web layouts, editor fonts, and editorial styling.
Web Design
Rendered Blueprint Specification
Viewed markdown.ts:1-207
Aapke blog fonts, text layout, editor aur sanitizer ka complete current active setup niche diya gaya hai. Aap ise copy karke safe jagah save kar sakte hain:
1. Global Stylesheet CSS (Fonts & Sizing Layout)
File Path: src/app/globals.css
/* ==========================================
Base Typographic Scale for Prose & Reading
========================================== */
.prose h1,
.prose h2,
.prose h3,
.prose h4,
.prose [role="heading"] {
font-family: var(--font-serif), var(--font-devanagari), Georgia, serif;
color: var(--foreground);
margin-top: 1.5rem;
margin-bottom: 0.5rem;
line-height: 1.35;
display: block;
}
.prose h1,
.prose [role="heading"][aria-level="1"] {
font-size: 2.25rem;
font-weight: 700;
letter-spacing: -0.025em;
}
.prose h2,
.prose [role="heading"][aria-level="2"] {
font-size: 1.75rem;
font-weight: 700;
letter-spacing: -0.02em;
}
.prose h3,
.prose [role="heading"][aria-level="3"] {
font-size: 1.375rem;
font-weight: 600;
letter-spacing: -0.015em;
}
.prose [role="heading"]:not([aria-level]) {
font-size: 1.375rem;
font-weight: 600;
letter-spacing: -0.015em;
}
/* Force spans inside headings to inherit parent heading styles (CRITICAL FOR HINDI) */
.prose h1 span,
.prose h2 span,
.prose h3 span,
.prose h4 span,
.prose [role="heading"] span {
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
letter-spacing: inherit !important;
}
.prose p {
margin-bottom: 0.85rem;
}
/* ==========================================
Light Mode Typography Overrides
========================================== */
.light .prose h1,
.light .prose h2,
.light .prose h3,
.light .prose h4,
.light .prose [role="heading"] {
color: #1d1d1f !important;
}
/* ==========================================
Dark Mode Typography Overrides
========================================== */
:root:not(.light) .prose h1,
:root:not(.light) .prose h2,
:root:not(.light) .prose h3,
:root:not(.light) .prose [role="heading"],
:root:not(.light) .prose p,
:root:not(.light) .prose li {
color: inherit !important;
}
2. Client-Side Content Parser Script (HTML & Markdown Routing)
File Path: src/lib/markdown.ts
export function parseMarkdownToHtml(markdown: string): string {
if (!markdown) return '';
const tokens: { [key: string]: string } = {};
let tokenCounter = 0;
let workingText = markdown;
// Code & HTML blocks placeholders (tokens) extraction is done here...
const parseInlineStyles = (text: string): string => {
let res = text;
res = res.replace(/\*\*([^*]+)\*\*/g, '<strong class="font-bold text-foreground">$1</strong>');
res = res.replace(/\*([^*]+)\*/g, '<em class="italic text-foreground/75">$1</em>');
res = res.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" class="text-indigo-400 hover:text-indigo-300 font-semibold underline underline-offset-4 decoration-indigo-500/30 hover:decoration-indigo-500/80 transition-all">$1</a>');
return res;
};
// Check if content is already structured HTML (from rich text editors)
const isHtml = /<p\b|<div\b|<h[1-6]\b|<ul\b|<ol\b|<li\b|<blockquote\b/i.test(workingText);
if (isHtml) {
let htmlContent = workingText;
// Inject typography classes into standard HTML tags
htmlContent = htmlContent.replace(/<p>/gi, '<p class="mb-3 text-foreground/80 leading-relaxed text-sm sm:text-base">');
htmlContent = htmlContent.replace(/<h2>/gi, '<h2 class="text-xl sm:text-2xl font-black text-foreground mt-8 mb-4 scroll-mt-24">');
htmlContent = htmlContent.replace(/<h3>/gi, '<h3 class="text-lg sm:text-xl font-extrabold text-foreground mt-7 mb-3 border-b border-foreground/10 pb-2 scroll-mt-24">');
htmlContent = htmlContent.replace(/<h4>/gi, '<h4 class="text-md sm:text-lg font-bold text-foreground mt-5 mb-2.5 scroll-mt-24">');
htmlContent = htmlContent.replace(/<ul>/gi, '<ul class="my-2.5 pl-5 space-y-1 text-foreground/85">');
htmlContent = htmlContent.replace(/<ol>/gi, '<ol class="my-2.5 pl-5 space-y-1 text-foreground/85">');
htmlContent = htmlContent.replace(/<li>/gi, '<li class="ml-5 list-disc text-foreground/85 my-0.5 leading-relaxed">');
htmlContent = parseInlineStyles(htmlContent);
Object.keys(tokens).forEach(tokenId => {
htmlContent = htmlContent.replace(tokenId, tokens[tokenId]);
});
return htmlContent;
}
// Normal markdown parser blocks parsing fallback runs here...
}
3. Editor Format Controller (Angled Bracket Stripper)
File Path: src/components/admin/block-editor.tsx
const execCommand = (command: string, value: string = '') => {
let cleanVal = value;
if (command === 'formatBlock' && value) {
// Strip angle brackets to support modern browsers (e.g., '<h2>' -> 'h2')
cleanVal = value.replace(/[<>]/g, '');
}
document.execCommand(command, false, cleanVal);
if (editorRef.current) {
const html = editorRef.current.innerHTML;
onChange(html);
pushToHistory(html);
}
};
4. Backend HTML Sanitizer Script (Bold & Italic tag preserver)
File Path: src/app/api/admin/crud/route.ts
function sanitizeHtmlContent(html: string): string {
if (!html) return '';
let cleaned = html;
// 1. Convert spans with inline bold/italic styles to semantic tags before stripping styles
cleaned = cleaned.replace(/<span\b[^>]*?style="[^"]*font-weight:\s*(?:bold|700|800|900)[^"]*"[^>]*>([\s\S]*?)<\/span>/gi, '<strong>$1</strong>');
cleaned = cleaned.replace(/<span\b[^>]*?style='[^']*font-weight:\s*(?:bold|700|800|900)[^']*'[^>]*>([\s\S]*?)<\/span>/gi, '<strong>$1</strong>');
cleaned = cleaned.replace(/<span\b[^>]*?style="[^"]*font-style:\s*italic[^"]*"[^>]*>([\s\S]*?)<\/span>/gi, '<em>$1</em>');
cleaned = cleaned.replace(/<span\b[^>]*?style='[^']*font-style:\s*italic[^']*'[^>]*>([\s\S]*?)<\/span>/gi, '<em>$1</em>');
// 2. Remove style and style-related attributes from text formatting tags
const tagsToStrip = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ul', 'ol', 'li', 'span', 'div'];
tagsToStrip.forEach(tag => {
const tagRegex = new RegExp(`<(${tag})\\b([^>]*?)>`, 'gi');
cleaned = cleaned.replace(tagRegex, (match, tagName, attrs) => {
let cleanedAttrs = attrs.replace(/\s*style=(?:"[^"]*"|'[^']*')/gi, '');
cleanedAttrs = cleanedAttrs.replace(/\s*face=(?:"[^"]*"|'[^']*')/gi, '');
cleanedAttrs = cleanedAttrs.replace(/\s*size=(?:"[^"]*"|'[^']*')/gi, '');
cleanedAttrs = cleanedAttrs.replace(/\s*color=(?:"[^"]*"|'[^']*')/gi, '');
cleanedAttrs = cleanedAttrs.replace(/\s*align=(?:"[^"]*"|'[^']*')/gi, '');
return `<${tagName}${cleanedAttrs}>`;
});
});
// 3. Remove repeated consecutive <br> tags
cleaned = cleaned.replace(/(?:<br\s*\/?>\s*){2,}/gi, '<br />');
// 4. Remove empty tags (do this in a loop to handle nested empty elements)
let prevLength;
do {
prevLength = cleaned.length;
cleaned = cleaned.replace(/<(p|div|span|h1|h2|h3|h4|h5|h6|ul|ol|li)\b[^>]*?>\s*(?: |<br\s*\/?>)?\s*<\/\1>/gi, '');
} while (cleaned.length < prevLength);
return cleaned.trim();
}
| 1 | Viewed markdown.ts:1-207 |
| 2 | |
| 3 | Aapke blog fonts, text layout, editor aur sanitizer ka **complete current active setup** niche diya gaya hai. Aap ise copy karke safe jagah save kar sakte hain: |
| 4 | |
| 5 | --- |
| 6 | |
| 7 | ### 1. Global Stylesheet CSS (Fonts & Sizing Layout) |
| 8 | **File Path:** `src/app/globals.css` |
| 9 | ```css |
| 10 | /* ========================================== |
| 11 | Base Typographic Scale for Prose & Reading |
| 12 | ========================================== */ |
| 13 | .prose h1, |
| 14 | .prose h2, |
| 15 | .prose h3, |
| 16 | .prose h4, |
| 17 | .prose [role="heading"] { |
| 18 | font-family: var(--font-serif), var(--font-devanagari), Georgia, serif; |
| 19 | color: var(--foreground); |
| 20 | margin-top: 1.5rem; |
| 21 | margin-bottom: 0.5rem; |
| 22 | line-height: 1.35; |
| 23 | display: block; |
| 24 | } |
| 25 | |
| 26 | .prose h1, |
| 27 | .prose [role="heading"][aria-level="1"] { |
| 28 | font-size: 2.25rem; |
| 29 | font-weight: 700; |
| 30 | letter-spacing: -0.025em; |
| 31 | } |
| 32 | |
| 33 | .prose h2, |
| 34 | .prose [role="heading"][aria-level="2"] { |
| 35 | font-size: 1.75rem; |
| 36 | font-weight: 700; |
| 37 | letter-spacing: -0.02em; |
| 38 | } |
| 39 | |
| 40 | .prose h3, |
| 41 | .prose [role="heading"][aria-level="3"] { |
| 42 | font-size: 1.375rem; |
| 43 | font-weight: 600; |
| 44 | letter-spacing: -0.015em; |
| 45 | } |
| 46 | |
| 47 | .prose [role="heading"]:not([aria-level]) { |
| 48 | font-size: 1.375rem; |
| 49 | font-weight: 600; |
| 50 | letter-spacing: -0.015em; |
| 51 | } |
| 52 | |
| 53 | /* Force spans inside headings to inherit parent heading styles (CRITICAL FOR HINDI) */ |
| 54 | .prose h1 span, |
| 55 | .prose h2 span, |
| 56 | .prose h3 span, |
| 57 | .prose h4 span, |
| 58 | .prose [role="heading"] span { |
| 59 | font-family: inherit !important; |
| 60 | font-size: inherit !important; |
| 61 | font-weight: inherit !important; |
| 62 | line-height: inherit !important; |
| 63 | letter-spacing: inherit !important; |
| 64 | } |
| 65 | |
| 66 | .prose p { |
| 67 | margin-bottom: 0.85rem; |
| 68 | } |
| 69 | |
| 70 | /* ========================================== |
| 71 | Light Mode Typography Overrides |
| 72 | ========================================== */ |
| 73 | .light .prose h1, |
| 74 | .light .prose h2, |
| 75 | .light .prose h3, |
| 76 | .light .prose h4, |
| 77 | .light .prose [role="heading"] { |
| 78 | color: #1d1d1f !important; |
| 79 | } |
| 80 | |
| 81 | /* ========================================== |
| 82 | Dark Mode Typography Overrides |
| 83 | ========================================== */ |
| 84 | :root:not(.light) .prose h1, |
| 85 | :root:not(.light) .prose h2, |
| 86 | :root:not(.light) .prose h3, |
| 87 | :root:not(.light) .prose [role="heading"], |
| 88 | :root:not(.light) .prose p, |
| 89 | :root:not(.light) .prose li { |
| 90 | color: inherit !important; |
| 91 | } |
| 92 | ``` |
| 93 | |
| 94 | --- |
| 95 | |
| 96 | ### 2. Client-Side Content Parser Script (HTML & Markdown Routing) |
| 97 | **File Path:** `src/lib/markdown.ts` |
| 98 | ```typescript |
| 99 | export function parseMarkdownToHtml(markdown: string): string { |
| 100 | if (!markdown) return ''; |
| 101 | |
| 102 | const tokens: { [key: string]: string } = {}; |
| 103 | let tokenCounter = 0; |
| 104 | let workingText = markdown; |
| 105 | |
| 106 | // Code & HTML blocks placeholders (tokens) extraction is done here... |
| 107 | |
| 108 | const parseInlineStyles = (text: string): string => { |
| 109 | let res = text; |
| 110 | res = res.replace(/\*\*([^*]+)\*\*/g, '<strong class="font-bold text-foreground">$1</strong>'); |
| 111 | res = res.replace(/\*([^*]+)\*/g, '<em class="italic text-foreground/75">$1</em>'); |
| 112 | res = res.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" class="text-indigo-400 hover:text-indigo-300 font-semibold underline underline-offset-4 decoration-indigo-500/30 hover:decoration-indigo-500/80 transition-all">$1</a>'); |
| 113 | return res; |
| 114 | }; |
| 115 | |
| 116 | // Check if content is already structured HTML (from rich text editors) |
| 117 | const isHtml = /<p\b|<div\b|<h[1-6]\b|<ul\b|<ol\b|<li\b|<blockquote\b/i.test(workingText); |
| 118 | if (isHtml) { |
| 119 | let htmlContent = workingText; |
| 120 | |
| 121 | // Inject typography classes into standard HTML tags |
| 122 | htmlContent = htmlContent.replace(/<p>/gi, '<p class="mb-3 text-foreground/80 leading-relaxed text-sm sm:text-base">'); |
| 123 | htmlContent = htmlContent.replace(/<h2>/gi, '<h2 class="text-xl sm:text-2xl font-black text-foreground mt-8 mb-4 scroll-mt-24">'); |
| 124 | htmlContent = htmlContent.replace(/<h3>/gi, '<h3 class="text-lg sm:text-xl font-extrabold text-foreground mt-7 mb-3 border-b border-foreground/10 pb-2 scroll-mt-24">'); |
| 125 | htmlContent = htmlContent.replace(/<h4>/gi, '<h4 class="text-md sm:text-lg font-bold text-foreground mt-5 mb-2.5 scroll-mt-24">'); |
| 126 | htmlContent = htmlContent.replace(/<ul>/gi, '<ul class="my-2.5 pl-5 space-y-1 text-foreground/85">'); |
| 127 | htmlContent = htmlContent.replace(/<ol>/gi, '<ol class="my-2.5 pl-5 space-y-1 text-foreground/85">'); |
| 128 | htmlContent = htmlContent.replace(/<li>/gi, '<li class="ml-5 list-disc text-foreground/85 my-0.5 leading-relaxed">'); |
| 129 | |
| 130 | htmlContent = parseInlineStyles(htmlContent); |
| 131 | |
| 132 | Object.keys(tokens).forEach(tokenId => { |
| 133 | htmlContent = htmlContent.replace(tokenId, tokens[tokenId]); |
| 134 | }); |
| 135 | |
| 136 | return htmlContent; |
| 137 | } |
| 138 | |
| 139 | // Normal markdown parser blocks parsing fallback runs here... |
| 140 | } |
| 141 | ``` |
| 142 | |
| 143 | --- |
| 144 | |
| 145 | ### 3. Editor Format Controller (Angled Bracket Stripper) |
| 146 | **File Path:** `src/components/admin/block-editor.tsx` |
| 147 | ```typescript |
| 148 | const execCommand = (command: string, value: string = '') => { |
| 149 | let cleanVal = value; |
| 150 | if (command === 'formatBlock' && value) { |
| 151 | // Strip angle brackets to support modern browsers (e.g., '<h2>' -> 'h2') |
| 152 | cleanVal = value.replace(/[<>]/g, ''); |
| 153 | } |
| 154 | document.execCommand(command, false, cleanVal); |
| 155 | if (editorRef.current) { |
| 156 | const html = editorRef.current.innerHTML; |
| 157 | onChange(html); |
| 158 | pushToHistory(html); |
| 159 | } |
| 160 | }; |
| 161 | ``` |
| 162 | |
| 163 | --- |
| 164 | |
| 165 | ### 4. Backend HTML Sanitizer Script (Bold & Italic tag preserver) |
| 166 | **File Path:** `src/app/api/admin/crud/route.ts` |
| 167 | ```typescript |
| 168 | function sanitizeHtmlContent(html: string): string { |
| 169 | if (!html) return ''; |
| 170 | |
| 171 | let cleaned = html; |
| 172 | |
| 173 | // 1. Convert spans with inline bold/italic styles to semantic tags before stripping styles |
| 174 | cleaned = cleaned.replace(/<span\b[^>]*?style="[^"]*font-weight:\s*(?:bold|700|800|900)[^"]*"[^>]*>([\s\S]*?)<\/span>/gi, '<strong>$1</strong>'); |
| 175 | cleaned = cleaned.replace(/<span\b[^>]*?style='[^']*font-weight:\s*(?:bold|700|800|900)[^']*'[^>]*>([\s\S]*?)<\/span>/gi, '<strong>$1</strong>'); |
| 176 | cleaned = cleaned.replace(/<span\b[^>]*?style="[^"]*font-style:\s*italic[^"]*"[^>]*>([\s\S]*?)<\/span>/gi, '<em>$1</em>'); |
| 177 | cleaned = cleaned.replace(/<span\b[^>]*?style='[^']*font-style:\s*italic[^']*'[^>]*>([\s\S]*?)<\/span>/gi, '<em>$1</em>'); |
| 178 | |
| 179 | // 2. Remove style and style-related attributes from text formatting tags |
| 180 | const tagsToStrip = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ul', 'ol', 'li', 'span', 'div']; |
| 181 | tagsToStrip.forEach(tag => { |
| 182 | const tagRegex = new RegExp(`<(${tag})\\b([^>]*?)>`, 'gi'); |
| 183 | cleaned = cleaned.replace(tagRegex, (match, tagName, attrs) => { |
| 184 | let cleanedAttrs = attrs.replace(/\s*style=(?:"[^"]*"|'[^']*')/gi, ''); |
| 185 | cleanedAttrs = cleanedAttrs.replace(/\s*face=(?:"[^"]*"|'[^']*')/gi, ''); |
| 186 | cleanedAttrs = cleanedAttrs.replace(/\s*size=(?:"[^"]*"|'[^']*')/gi, ''); |
| 187 | cleanedAttrs = cleanedAttrs.replace(/\s*color=(?:"[^"]*"|'[^']*')/gi, ''); |
| 188 | cleanedAttrs = cleanedAttrs.replace(/\s*align=(?:"[^"]*"|'[^']*')/gi, ''); |
| 189 | return `<${tagName}${cleanedAttrs}>`; |
| 190 | }); |
| 191 | }); |
| 192 | |
| 193 | // 3. Remove repeated consecutive <br> tags |
| 194 | cleaned = cleaned.replace(/(?:<br\s*\/?>\s*){2,}/gi, '<br />'); |
| 195 | |
| 196 | // 4. Remove empty tags (do this in a loop to handle nested empty elements) |
| 197 | let prevLength; |
| 198 | do { |
| 199 | prevLength = cleaned.length; |
| 200 | cleaned = cleaned.replace(/<(p|div|span|h1|h2|h3|h4|h5|h6|ul|ol|li)\b[^>]*?>\s*(?: |<br\s*\/?>)?\s*<\/\1>/gi, ''); |
| 201 | } while (cleaned.length < prevLength); |
| 202 | |
| 203 | return cleaned.trim(); |
| 204 | } |
| 205 | ``` |
More web dev Prompts
Universal Next.js Performance & Edge Architecture
Universal Next.js App Router system prompt for sub-millisecond edge delivery, static-first rendering, deterministic caching, and optimal Core Web Vitals.
Architect, optimize, and verify Next.js App Router applications for static-first rendering, aggressive edge caching, fast navigation, efficient data fetching, and minimal unnecessary server round-trips.
Detailed Security Audit + Hardening (Web Project)
Comprehensive security hardening and SEO audit system instructions covering auth bypass, SQL injection prevention, rate limiting, and security headers.
Complete security audit aur fix — auth bypass, SQL injection, rate limiting, HttpOnly cookies, security headers, aur SEO metadata sab cover karta hai.
GET PERFECT BLOG FORMAT
Senior editor system prompt to transform raw technical notes into professional, high-clarity publication articles with structured formatting.
BLOG FORMAT ONE2TECH STYLE
Subscribe to One2Tech
Get direct notifications on new macOS automation workflows.