'use strict'; // Minimal YAML front matter: flat `key: value`, inline `[a, b]` lists and `- item` lists. // Unknown keys are kept and written back, so notes from Obsidian survive a round trip. const FM = /^?---\r?\n([\s\S]*?)\r?\n---[ \t]*(?:\r?\n|$)/; function unquote(v) { v = v.trim(); if (v.length >= 2 && v.startsWith('"') && v.endsWith('"')) { try { return JSON.parse(v); } catch { return v.slice(1, -1); } } if (v.length >= 2 && v.startsWith("'") && v.endsWith("'")) return v.slice(1, -1).replace(/''/g, "'"); return v; } function parseFrontMatter(raw) { const m = raw.match(FM); if (!m) return { meta: {}, body: raw }; const meta = {}; let last = null; for (const line of m[1].split(/\r?\n/)) { const kv = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/); if (kv) { last = kv[1]; const v = kv[2].trim(); if (v.startsWith('[') && v.endsWith(']')) { meta[last] = v.slice(1, -1).split(',').map(unquote).filter(Boolean); } else { meta[last] = v === '' ? [] : unquote(v); } continue; } const item = line.match(/^\s*-\s+(.*)$/); if (item && last) { if (!Array.isArray(meta[last])) meta[last] = []; meta[last].push(unquote(item[1])); } } // An empty `key:` with no list items below it is just an empty string. for (const k of Object.keys(meta)) if (Array.isArray(meta[k]) && !meta[k].length && k !== 'tags') meta[k] = ''; return { meta, body: raw.slice(m[0].length).replace(/^\r?\n/, '') }; } function quote(s) { s = String(s); return /^[\p{L}\p{N}_ .\/@#+-]+$/u.test(s) && s.trim() === s && !/^[-#@]/.test(s) ? s : JSON.stringify(s); } const ORDER = ['icon', 'cover', 'tags', 'created']; function serializeFrontMatter(meta = {}) { const keys = Object.keys(meta).filter((k) => { const v = meta[k]; return v !== undefined && v !== null && v !== '' && !(Array.isArray(v) && !v.length); }); if (!keys.length) return ''; keys.sort((a, b) => { const ia = ORDER.indexOf(a), ib = ORDER.indexOf(b); return (ia < 0 ? 99 : ia) - (ib < 0 ? 99 : ib); }); const lines = keys.map((k) => { const v = meta[k]; return Array.isArray(v) ? `${k}: [${v.map(quote).join(', ')}]` : `${k}: ${quote(v)}`; }); return `---\n${lines.join('\n')}\n---\n\n`; } module.exports = { parseFrontMatter, serializeFrontMatter };