Files
ai_platform/lib/meeting-minutes-summary.js

79 lines
2.2 KiB
JavaScript

/**
* 회의록 Markdown에서 업무 체크리스트 툴팁용 짧은 요약 추출 (저장 시 summary_text 보조용)
*/
function stripMd(s) {
if (!s) return "";
return s
.replace(/\r\n/g, "\n")
.replace(/\*\*([^*]+)\*\*/g, "$1")
.replace(/__([^_]+)__/g, "$1")
.replace(/^[-*•]\s+/gm, "")
.replace(/^\d+\.\s+/gm, "")
.replace(/\s+/g, " ")
.trim();
}
function truncate(s, maxLen) {
const t = (s || "").trim();
if (t.length <= maxLen) return t;
return t.slice(0, maxLen - 1).trim() + "…";
}
/** 체크리스트/액션 등 툴팁에 부적합한 섹션 제목 */
const SKIP_SECTION = /체크리스트|액션|후속\s*확인|참석|결정\s*사항|action\s*items/i;
/** 요약으로 쓰기 좋은 섹션 제목 */
const PREFERRED = /요약|개요|핵심|summary|논의\s*안건|회의\s*내용|discussion/i;
/**
* @param {string} markdown
* @param {number} [maxLen]
* @returns {string}
*/
function extractMeetingSummary(markdown, maxLen = 800) {
const md = (markdown || "").trim();
if (!md) return "";
const lines = md.split(/\r?\n/);
/** @type {{ h: string, body: string }[]} */
const sections = [];
for (let i = 0; i < lines.length; ) {
const line = lines[i];
const hm = line.match(/^#{1,6}\s+(.+)$/);
if (!hm) {
i++;
continue;
}
const heading = hm[1].replace(/\*\*/g, "").trim();
const body = [];
let j = i + 1;
while (j < lines.length) {
const tj = lines[j].trim();
if (/^#{1,6}\s+/.test(tj)) break;
body.push(lines[j]);
j++;
}
const joined = body.join("\n").trim();
if (joined.length >= 4) sections.push({ h: heading, body: joined });
i = j;
}
const preferred = sections.find((s) => PREFERRED.test(s.h) && !SKIP_SECTION.test(s.h));
if (preferred) return truncate(stripMd(preferred.body), maxLen);
const firstOk = sections.find((s) => !SKIP_SECTION.test(s.h) && s.body.length >= 12);
if (firstOk) return truncate(stripMd(firstOk.body), maxLen);
let plain = md.replace(/^#{1,6}\s+.*$/gm, "").trim();
plain = plain.replace(/^[-*•]\s+.*$/gm, "").trim();
if (plain.length < 30) plain = stripMd(md);
return truncate(stripMd(plain), maxLen);
}
module.exports = {
extractMeetingSummary,
stripMd,
truncate,
};