79 lines
2.2 KiB
JavaScript
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,
|
|
};
|