src/lib/org/parseDocument.js (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
import { getSettings, parse } from 'orga';
import { normalizeOrgContent } from './normalize.js';
function headlineTitle(headline) {
const parts = [];
for (const child of headline.children ?? []) {
if (child.type === 'text' && child.value) {
parts.push(child.value);
}
}
return parts.join('').trim() || 'Untitled section';
}
function headlineLevel(headline) {
const stars = headline.children?.find((child) => child.type === 'stars');
if (stars?.level) return stars.level;
if (stars?.value) return stars.value.length;
return 1;
}
function headlineTodo(headline) {
const todoNode = headline.children?.find((child) => child.type === 'todo');
return todoNode?.keyword ?? null;
}
function headlineTags(headline) {
const tagsNode = headline.children?.find((child) => child.type === 'tags');
if (!tagsNode?.tags?.length) return [];
return tagsNode.tags;
}
function walkSection(section, headings) {
if (!section?.children) return;
for (const child of section.children) {
if (child.type === 'headline') {
headings.push({
level: headlineLevel(child),
title: headlineTitle(child),
todo: headlineTodo(child),
tags: headlineTags(child),
line: child.position?.start?.line ?? 1,
});
}
if (child.type === 'section') {
walkSection(child, headings);
}
}
}
export function parseOrgDocument(content) {
if (!content?.trim()) {
return {
keywords: {},
headings: [],
title: null,
author: null,
todoKeywords: ['TODO', 'DONE'],
};
}
const normalized = normalizeOrgContent(content);
const settings = getSettings(normalized);
const doc = parse(normalized);
const headings = [];
for (const child of doc.children ?? []) {
if (child.type === 'section') {
walkSection(child, headings);
}
}
const titleSetting = settings.title;
const authorSetting = settings.author;
const todoSetting = settings.todo;
let todoKeywords = ['TODO', 'DONE'];
if (typeof todoSetting === 'string') {
todoKeywords = todoSetting.split(/\s+/).filter(Boolean);
} else if (Array.isArray(todoSetting)) {
todoKeywords = todoSetting.flatMap((entry) => entry.split(/\s+/)).filter(Boolean);
}
return {
keywords: settings,
headings,
title: typeof titleSetting === 'string' ? titleSetting : null,
author: typeof authorSetting === 'string' ? authorSetting : null,
todoKeywords,
};
}
|