Skip to content

Commit 4b2ee58

Browse files
Merge pull request #56 from mhakash/feature/yaml-frontmatter
Add support for github style yaml frontmatter
2 parents f8b70ec + f145135 commit 4b2ee58

3 files changed

Lines changed: 125 additions & 4 deletions

File tree

index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,10 @@
5151
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
5252
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
5353

54-
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/pdfmake.min.js"></script>
54+
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/pdfmake.min.js"></script>
5555
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/vfs_fonts.js"></script>
5656
<script src="https://cdnjs.cloudflare.com/ajax/libs/pako/2.1.0/pako.min.js" integrity="sha384-rNlaE5fs9dGIjmxWDALQh/RBAaGRYT5ChrzHo6tRfgrZ36iRFAiquP5g41Jsv+0j" crossorigin="anonymous"></script>
57+
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.min.js"></script>
5758
</head>
5859
<body>
5960
<div class="app-container">

script.js

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,64 @@ document.addEventListener("DOMContentLoaded", function () {
220220
});
221221
}
222222

223-
const sampleMarkdown = `# Welcome to Markdown Viewer
223+
function parseFrontmatter(markdown) {
224+
const match = markdown.match(/^---\r?\n([\s\S]*?)\r?\n---(\r?\n|$)/);
225+
if (!match) return { frontmatter: null, body: markdown };
226+
try {
227+
const data = jsyaml.load(match[1]) || {};
228+
return { frontmatter: data, body: markdown.slice(match[0].length) };
229+
} catch (e) {
230+
console.warn('Frontmatter YAML parse error:', e);
231+
return { frontmatter: null, body: markdown };
232+
}
233+
}
234+
235+
function renderFrontmatterValue(value) {
236+
if (value === null || value === undefined) return '';
237+
if (value instanceof Date) {
238+
const y = value.getUTCFullYear();
239+
const m = String(value.getUTCMonth() + 1).padStart(2, '0');
240+
const d = String(value.getUTCDate()).padStart(2, '0');
241+
return `${y}-${m}-${d}`;
242+
}
243+
if (Array.isArray(value)) {
244+
const allPrimitive = value.every(v => v === null || typeof v !== 'object');
245+
if (allPrimitive) {
246+
return value
247+
.map(v => `<span class="fm-tag">${escapeHtml(String(v ?? ''))}</span>`)
248+
.join('');
249+
}
250+
return `<pre class="fm-complex">${escapeHtml(jsyaml.dump(value).trimEnd())}</pre>`;
251+
}
252+
if (typeof value === 'object') {
253+
return `<pre class="fm-complex">${escapeHtml(jsyaml.dump(value).trimEnd())}</pre>`;
254+
}
255+
return escapeHtml(String(value));
256+
}
257+
258+
function renderFrontmatterTable(data) {
259+
const rows = Object.entries(data).map(([key, value]) =>
260+
`<tr><th>${escapeHtml(key)}</th><td>${renderFrontmatterValue(value)}</td></tr>`
261+
);
262+
return `<table class="frontmatter-table"><tbody>${rows.join('')}</tbody></table>`;
263+
}
264+
265+
function escapeHtml(str) {
266+
return str
267+
.replace(/&/g, '&amp;')
268+
.replace(/</g, '&lt;')
269+
.replace(/>/g, '&gt;')
270+
.replace(/"/g, '&quot;');
271+
}
272+
273+
const sampleMarkdown = `---
274+
title: Welcome to Markdown Viewer
275+
description: A GitHub-style Markdown renderer with live preview, math, diagrams, and export support.
276+
author: ThisIs-Developer
277+
tags: ["markdown", "preview", "mermaid", "latex", "open-source"]
278+
---
279+
280+
# Welcome to Markdown Viewer
224281
225282
## ✨ Key Features
226283
- **Live Preview** with GitHub styling
@@ -853,8 +910,9 @@ This is a fully client-side application. Your content never leaves your browser
853910

854911
function renderMarkdown() {
855912
try {
856-
const markdown = markdownEditor.value;
857-
const html = marked.parse(markdown);
913+
const { frontmatter, body } = parseFrontmatter(markdownEditor.value);
914+
const tableHtml = frontmatter ? renderFrontmatterTable(frontmatter) : '';
915+
const html = tableHtml + marked.parse(body);
858916
const sanitizedHtml = DOMPurify.sanitize(html, {
859917
ADD_TAGS: ['mjx-container'],
860918
ADD_ATTR: ['id', 'class', 'style']

styles.css

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1883,3 +1883,65 @@ a:focus {
18831883
width: 100%;
18841884
}
18851885
}
1886+
1887+
.frontmatter-table {
1888+
border-collapse: collapse;
1889+
margin-bottom: 1.5em;
1890+
font-size: 0.9em;
1891+
width: auto;
1892+
max-width: 100%;
1893+
}
1894+
1895+
.frontmatter-table th,
1896+
.frontmatter-table td {
1897+
border: 1px solid var(--border-color);
1898+
padding: 6px 13px;
1899+
vertical-align: top;
1900+
color: var(--text-color);
1901+
}
1902+
1903+
.frontmatter-table tr:nth-child(odd) th,
1904+
.frontmatter-table tr:nth-child(odd) td {
1905+
background-color: var(--table-bg);
1906+
}
1907+
1908+
.frontmatter-table tr:nth-child(even) th,
1909+
.frontmatter-table tr:nth-child(even) td {
1910+
background-color: var(--editor-bg);
1911+
}
1912+
1913+
.frontmatter-table th {
1914+
font-weight: 600;
1915+
text-align: right;
1916+
white-space: nowrap;
1917+
vertical-align: middle;
1918+
}
1919+
1920+
.frontmatter-table td {
1921+
text-align: left;
1922+
}
1923+
1924+
.fm-complex {
1925+
margin: 0;
1926+
padding: 4px 6px;
1927+
font-size: 0.8em;
1928+
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
1929+
white-space: pre-wrap;
1930+
word-break: break-word;
1931+
background: transparent;
1932+
border: none;
1933+
color: var(--text-color);
1934+
}
1935+
1936+
.fm-tag {
1937+
display: inline-block;
1938+
padding: 2px 8px;
1939+
margin: 2px 3px 2px 0;
1940+
border: 1px solid var(--border-color);
1941+
border-radius: 2em;
1942+
font-size: 0.8em;
1943+
font-weight: 500;
1944+
color: var(--accent-color);
1945+
background-color: var(--button-bg);
1946+
white-space: nowrap;
1947+
}

0 commit comments

Comments
 (0)