Various AT Protocol integrations with obsidian
20
fork

Configure Feed

Select the types of activity you want to include in your feed.

publishing: Pull title from H1

Allows the title to be sourced from the published document's first H1
header. The order of precedence for determining the document's title is
now:

- `title` frontmatter field
- First present H1 header
- Filename

+70
+70
src/commands/publishDocument.ts
··· 74 74 }); 75 75 } 76 76 77 + function extractFirstH1(markdown: string): string | undefined { 78 + const lines = markdown.split(/\r?\n/); 79 + let inFence = false; 80 + let fenceMarker: string | null = null; 81 + 82 + for (const line of lines) { 83 + const trimmed = line.trim(); 84 + const fence = trimmed.match(/^(```+|~~~+)/); 85 + if (fence && fence[1]) { 86 + const marker = fence[1].charAt(0); 87 + if (!inFence) { 88 + inFence = true; 89 + fenceMarker = marker; 90 + } else if (fenceMarker === marker) { 91 + inFence = false; 92 + fenceMarker = null; 93 + } 94 + continue; 95 + } 96 + 97 + if (inFence) { 98 + continue; 99 + } 100 + 101 + const atxMatch = line.match(/^\s*#\s+(.+?)\s*$/); 102 + if (atxMatch?.[1]) { 103 + return atxMatch[1].trim(); 104 + } 105 + } 106 + 107 + for (let i = 0; i < lines.length - 1; i++) { 108 + const line = lines[i]; 109 + const next = lines[i + 1]; 110 + if (!line || !next) { 111 + continue; 112 + } 113 + const trimmed = line.trim(); 114 + 115 + const fence = trimmed.match(/^(```+|~~~+)/); 116 + if (fence && fence[1]) { 117 + const marker = fence[1].charAt(0); 118 + if (!inFence) { 119 + inFence = true; 120 + fenceMarker = marker; 121 + } else if (fenceMarker === marker) { 122 + inFence = false; 123 + fenceMarker = null; 124 + } 125 + continue; 126 + } 127 + 128 + if (inFence) { 129 + continue; 130 + } 131 + 132 + if (!trimmed) { 133 + continue; 134 + } 135 + 136 + if (/^\s*=+\s*$/.test(next)) { 137 + return trimmed; 138 + } 139 + } 140 + 141 + return undefined; 142 + } 77 143 78 144 async function buildDocumentRecord(plugin: AtmospherePlugin, file: TFile): Promise<{ record: SiteStandardDocument.Main; docUri?: ResourceUri }> { 79 145 const full = await plugin.app.vault.read(file); ··· 99 165 title = fm["title"]; 100 166 tags = fm["tags"] && Array.isArray(fm["tags"]) ? fm["tags"] : undefined; 101 167 publishedAt = fm["publishedAt"]; // Preserve existing if updating 168 + } 169 + 170 + if (!title) { 171 + title = extractFirstH1(content); 102 172 } 103 173 104 174 if (!title) {