kakaotalk-chat-analyzer 0.13.1 → 0.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ import type { DailyCount, ReportTopic } from "./types.js";
2
+ /** 활동일 < 90일·활동 월 ≤ 2 — 월별 period 카드/차트는 기간 비교로 안내 */
3
+ export declare function isShortActivitySpan(daily: DailyCount[]): boolean;
4
+ export declare function topicsForDisplay(topics: ReportTopic[], daily: DailyCount[]): ReportTopic[];
5
+ export declare function topicsThemesOnly(topics: ReportTopic[]): ReportTopic[];
@@ -0,0 +1,17 @@
1
+ /** 활동일 < 90일·활동 월 ≤ 2 — 월별 period 카드/차트는 기간 비교로 안내 */
2
+ export function isShortActivitySpan(daily) {
3
+ const active = daily.filter((d) => d.count > 0);
4
+ if (active.length === 0 || active.length >= 90)
5
+ return false;
6
+ const months = new Set(active.map((d) => d.date.slice(0, 7)));
7
+ return months.size <= 2;
8
+ }
9
+ export function topicsForDisplay(topics, daily) {
10
+ if (!isShortActivitySpan(daily))
11
+ return topics;
12
+ return topics.filter((t) => t.kind === "theme");
13
+ }
14
+ export function topicsThemesOnly(topics) {
15
+ return topics.filter((t) => t.kind === "theme");
16
+ }
17
+ //# sourceMappingURL=report-chart-util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-chart-util.js","sourceRoot":"","sources":["../../src/report-chart-util.ts"],"names":[],"mappings":"AAEA,sDAAsD;AACtD,MAAM,UAAU,mBAAmB,CAAC,KAAmB;IACrD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IAChD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,IAAI,EAAE;QAAE,OAAO,KAAK,CAAC;IAC7D,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9D,OAAO,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAqB,EAAE,KAAmB;IACzE,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC;IAC/C,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAqB;IACpD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;AAClD,CAAC"}
@@ -37,11 +37,16 @@ export interface ChartPayload {
37
37
  }[];
38
38
  burstDates: string[];
39
39
  totalParticipants: number;
40
- topics: {
40
+ topicsThemes: {
41
41
  title: string;
42
42
  terms: string[];
43
43
  messagePercent: number;
44
- kind: string;
44
+ }[];
45
+ topicsPeriods: {
46
+ title: string;
47
+ terms: string[];
48
+ messagePercent: number;
49
+ periodLabel?: string;
45
50
  }[];
46
51
  interaction: {
47
52
  aliases: string[];
@@ -53,4 +58,4 @@ export declare function serializeChartPayload(data: ReportData): string;
53
58
  export declare function buildChartPayload(data: ReportData): ChartPayload;
54
59
  export declare function serializeExplorerPayload(data: ReportData): string;
55
60
  export declare function renderChartDeck(data: ReportData): string;
56
- export declare const CHARTS_INIT_SCRIPT = "\n (function () {\n function run() {\n var dataEl = document.getElementById(\"kca-chart-data\");\n if (!dataEl) return;\n if (typeof echarts === \"undefined\") return;\n var data;\n try { data = JSON.parse(dataEl.textContent || \"{}\"); } catch (e) { return; }\n\n var dark = document.documentElement.getAttribute(\"data-theme\") === \"dark\" ||\n (!document.documentElement.getAttribute(\"data-theme\") &&\n window.matchMedia && window.matchMedia(\"(prefers-color-scheme: dark)\").matches);\n var text = dark ? \"#e9eef5\" : \"#141a1f\";\n var muted = dark ? \"#8b98a8\" : \"#5c6670\";\n var accent = dark ? \"#3ee8c5\" : \"#0f6b5c\";\n var accent2 = dark ? \"#818cf8\" : \"#4f46e5\";\n\n function baseOpt() {\n return {\n textStyle: { color: text, fontFamily: \"Pretendard, Apple SD Gothic Neo, sans-serif\" },\n tooltip: { trigger: \"axis\", backgroundColor: dark ? \"#1c2128\" : \"#fff\", borderColor: \"transparent\" },\n };\n }\n\n var charts = [];\n function resizeAll() {\n charts.forEach(function (c) {\n try { c.resize(); } catch (e) {}\n });\n }\n function layout(el) {\n var w = (el && el.clientWidth) || 400;\n if (w < 380) {\n return { w: w, left: 28, right: 8, top: 14, bottom: 44, fs: 9, rot: 40, leftCat: 56, bottomRot: 42 };\n }\n if (w < 640) {\n return { w: w, left: 40, right: 10, top: 18, bottom: 34, fs: 10, rot: 26, leftCat: 72, bottomRot: 32 };\n }\n return { w: w, left: 48, right: 14, top: 22, bottom: 28, fs: 11, rot: 0, leftCat: 96, bottomRot: 28 };\n }\n function init(id, opt) {\n var el = document.getElementById(id);\n if (!el) return null;\n try {\n var chart = echarts.init(el, null, { renderer: \"canvas\" });\n chart.setOption(opt);\n charts.push(chart);\n if (typeof ResizeObserver !== \"undefined\") {\n var ro = new ResizeObserver(function () {\n requestAnimationFrame(function () {\n try { chart.resize(); } catch (e) {}\n });\n });\n ro.observe(el);\n }\n return chart;\n } catch (err) {\n console.error(\"[kca-chart]\", id, err);\n el.setAttribute(\"data-chart-failed\", \"1\");\n el.innerHTML = '<p style=\"margin:0;padding:12px;font-size:12px;color:var(--muted);text-align:center\">\uCC28\uD2B8\uB97C \uBD88\uB7EC\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694. \uC0C8\uB85C\uACE0\uCE68\uD558\uAC70\uB098 \uB124\uD2B8\uC6CC\uD06C(CDN)\uB97C \uD655\uC778\uD574 \uC8FC\uC138\uC694.</p>';\n return null;\n }\n }\n var mqWide = window.matchMedia && window.matchMedia(\"(min-width: 900px)\");\n if (mqWide && mqWide.addEventListener) {\n mqWide.addEventListener(\"change\", function () { setTimeout(resizeAll, 80); });\n } else if (mqWide && mqWide.addListener) {\n mqWide.addListener(function () { setTimeout(resizeAll, 80); });\n }\n var themeObs = new MutationObserver(function () { setTimeout(resizeAll, 60); });\n themeObs.observe(document.documentElement, { attributes: true, attributeFilter: [\"data-theme\"] });\n\n function hourBarColor(h) {\n if (h <= 5) return dark ? \"#6366f1\" : \"#4f46e5\";\n if (h <= 11) return dark ? \"#3ee8c5\" : \"#0f6b5c\";\n if (h <= 17) return dark ? \"#fbbf24\" : \"#d97706\";\n return dark ? \"#3b82f6\" : \"#1d4ed8\";\n }\n if (data.hourly && document.getElementById(\"chart-hours\")) {\n var hoursEl = document.getElementById(\"chart-hours\");\n var hg = layout(hoursEl);\n init(\"chart-hours\", Object.assign(baseOpt(), {\n grid: { left: hg.left, right: hg.right, top: hg.top, bottom: hg.bottom },\n xAxis: { type: \"category\", data: data.hourly.map(function (_, h) { return h + \"\uC2DC\"; }), axisLabel: { color: muted, fontSize: hg.fs, rotate: hg.rot } },\n yAxis: { type: \"value\", axisLabel: { color: muted }, splitLine: { lineStyle: { color: dark ? \"rgba(255,255,255,0.06)\" : \"rgba(0,0,0,0.06)\" } } },\n series: [{\n type: \"bar\",\n data: data.hourly.map(function (v, h) {\n return { value: v, itemStyle: { color: hourBarColor(h), borderRadius: [4, 4, 0, 0] } };\n }),\n markArea: {\n silent: true,\n itemStyle: { color: dark ? \"rgba(99,102,241,0.12)\" : \"rgba(79,70,229,0.08)\" },\n data: [[{ xAxis: \"0\uC2DC\" }, { xAxis: \"5\uC2DC\" }], [{ xAxis: \"22\uC2DC\" }, { xAxis: \"23\uC2DC\" }]],\n },\n }],\n }));\n }\n\n if (data.weekdays && document.getElementById(\"chart-weekday\")) {\n var wdEl = document.getElementById(\"chart-weekday\");\n var wg = layout(wdEl);\n init(\"chart-weekday\", Object.assign(baseOpt(), {\n grid: { left: wg.leftCat, right: wg.right, top: wg.top, bottom: wg.bottom },\n xAxis: { type: \"value\", axisLabel: { color: muted, fontSize: wg.fs } },\n yAxis: { type: \"category\", data: data.weekdays.map(function (w) { return w.label; }), axisLabel: { color: muted, fontSize: wg.fs } },\n series: [{ type: \"bar\", data: data.weekdays.map(function (w) { return w.count; }), itemStyle: { color: accent, borderRadius: [0, 6, 6, 0] } }],\n }));\n }\n\n if (data.monthly && document.getElementById(\"chart-monthly\")) {\n var moEl = document.getElementById(\"chart-monthly\");\n var mg = layout(moEl);\n init(\"chart-monthly\", Object.assign(baseOpt(), {\n grid: { left: mg.left, right: mg.right, top: mg.top, bottom: mg.bottom },\n xAxis: { type: \"category\", data: data.monthly.map(function (m) { return m.label; }), axisLabel: { color: muted, fontSize: mg.fs, rotate: mg.bottomRot } },\n yAxis: { type: \"value\", axisLabel: { color: muted, fontSize: mg.fs }, splitLine: { lineStyle: { color: dark ? \"rgba(255,255,255,0.06)\" : \"rgba(0,0,0,0.06)\" } } },\n series: [{ type: \"line\", smooth: true, data: data.monthly.map(function (m) { return m.count; }), areaStyle: { opacity: 0.12 }, lineStyle: { width: 2, color: accent2 }, itemStyle: { color: accent2 } }],\n }));\n }\n\n if (data.daily && document.getElementById(\"chart-daily-heat\")) {\n var heatEl = document.getElementById(\"chart-daily-heat\");\n var dg = layout(heatEl);\n var heatMax = Math.max.apply(null, data.daily.map(function (d) { return d.count; }).concat([1]));\n var heat = data.daily.map(function (d) { return [d.date, d.count]; });\n var burstSet = {};\n (data.burstDates || []).forEach(function (d) { burstSet[d] = true; });\n var daySpan = data.daily.length;\n var useBarFallback = daySpan > 0 && daySpan < 90;\n if (useBarFallback) {\n var labels = data.daily.map(function (d) {\n var p = d.date.split(\"-\");\n return p.length === 3 ? Number(p[1]) + \"/\" + Number(p[2]) : d.date;\n });\n init(\"chart-daily-heat\", Object.assign(baseOpt(), {\n grid: { left: dg.left, right: dg.right, top: dg.top, bottom: Math.max(dg.bottom, 52), containLabel: true },\n tooltip: { trigger: \"axis\" },\n xAxis: { type: \"category\", data: labels, axisLabel: { color: muted, fontSize: dg.fs, rotate: labels.length > 20 ? 40 : 0, interval: labels.length > 40 ? Math.floor(labels.length / 20) : 0 } },\n yAxis: { type: \"value\", axisLabel: { color: muted }, splitLine: { lineStyle: { color: dark ? \"rgba(255,255,255,0.06)\" : \"rgba(0,0,0,0.06)\" } } },\n visualMap: { show: false, min: 0, max: heatMax, inRange: { color: dark ? [\"#161b22\", \"#0e4429\", \"#006d32\", \"#26a641\", \"#39d353\"] : [\"#ebedf0\", \"#9be9a8\", \"#40c463\", \"#30a14e\", \"#216e39\"] } },\n series: [{\n type: \"bar\",\n data: data.daily.map(function (d) { return d.count; }),\n itemStyle: { borderRadius: [3, 3, 0, 0], borderWidth: 0 },\n emphasis: { itemStyle: { shadowBlur: 10, shadowColor: dark ? \"rgba(62,232,197,0.45)\" : \"rgba(15,107,92,0.35)\" } },\n }],\n }));\n } else {\n var cellH = dg.w < 380 ? 12 : dg.w < 640 ? 14 : 16;\n var cellW = dg.w < 380 ? 12 : 14;\n init(\"chart-daily-heat\", Object.assign(baseOpt(), {\n tooltip: { position: \"top\" },\n visualMap: { min: 0, max: heatMax, calculable: true, orient: \"horizontal\", left: \"center\", bottom: 0, textStyle: { color: muted, fontSize: dg.fs }, itemWidth: dg.w < 380 ? 10 : 14, itemHeight: dg.w < 380 ? 60 : 80, inRange: { color: dark ? [\"#161b22\", \"#0e4429\", \"#006d32\", \"#26a641\", \"#39d353\"] : [\"#ebedf0\", \"#9be9a8\", \"#40c463\", \"#30a14e\", \"#216e39\"] } },\n calendar: { top: dg.w < 380 ? 28 : 36, left: dg.left, right: dg.right, cellSize: [cellW, cellH], range: data.daily.length ? [data.daily[0].date, data.daily[data.daily.length - 1].date] : undefined, itemStyle: { borderWidth: 0, borderColor: \"transparent\" }, dayLabel: { color: muted, fontSize: dg.fs }, monthLabel: { color: muted, fontSize: dg.fs } },\n series: [{ type: \"heatmap\", coordinateSystem: \"calendar\", data: heat, emphasis: { itemStyle: { shadowBlur: 8, shadowColor: dark ? \"rgba(62,232,197,0.5)\" : \"rgba(33,110,57,0.45)\" } } }],\n }));\n }\n }\n\n if (data.keywords && document.getElementById(\"chart-kw-bar\")) {\n var kwEl = document.getElementById(\"chart-kw-bar\");\n var kg = layout(kwEl);\n var topBar = data.keywords.slice(0, kg.w < 380 ? 24 : 80);\n var maxLabelLen = 0;\n topBar.forEach(function (k) { if (k.label.length > maxLabelLen) maxLabelLen = k.label.length; });\n var kwLeft = Math.max(kg.leftCat, Math.min(kg.w * 0.42, 24 + maxLabelLen * (kg.fs + 1)));\n init(\"chart-kw-bar\", Object.assign(baseOpt(), {\n grid: { left: kwLeft, right: kg.right, top: kg.top, bottom: kg.bottom, containLabel: true },\n xAxis: { type: \"value\", axisLabel: { color: muted, fontSize: kg.fs } },\n yAxis: { type: \"category\", data: topBar.map(function (k) { return k.label; }).reverse(), axisLabel: { color: text, fontSize: kg.fs, width: kwLeft - 12, overflow: \"truncate\" } },\n series: [{ type: \"bar\", data: topBar.map(function (k) { return k.count; }).reverse(), itemStyle: { color: accent2, borderRadius: [0, 4, 4, 0] }, label: { show: true, position: \"right\", color: muted, fontSize: kg.fs, formatter: function (p) { return p.value; } } }],\n }));\n }\n\n if (data.keywords && document.getElementById(\"chart-kw-cloud\")) {\n var cloudEl = document.getElementById(\"chart-kw-cloud\");\n var cg = layout(cloudEl);\n var cloud = data.keywords.slice(0, 100).map(function (k) {\n return { name: k.label, value: k.count };\n });\n var sizeLo = cg.w < 380 ? 10 : 12;\n var sizeHi = cg.w < 380 ? 34 : cg.w < 640 ? 46 : 56;\n init(\"chart-kw-cloud\", {\n textStyle: baseOpt().textStyle,\n tooltip: { show: true },\n series: [{\n type: \"wordCloud\",\n shape: \"circle\",\n gridSize: cg.w < 380 ? 8 : 6,\n sizeRange: [sizeLo, sizeHi],\n rotationRange: [-45, 45],\n textStyle: {\n fontFamily: \"Pretendard, Apple SD Gothic Neo, sans-serif\",\n color: function () {\n var palette = dark ? [\"#3ee8c5\", \"#818cf8\", \"#fbbf24\", \"#fb923c\", \"#f472b6\"] : [\"#0f6b5c\", \"#4f46e5\", \"#b8860b\", \"#c45c2a\", \"#be185d\"];\n return palette[Math.floor(Math.random() * palette.length)];\n },\n },\n data: cloud,\n }],\n });\n }\n\n if (data.participants && document.getElementById(\"chart-participants\")) {\n var pieEl = document.getElementById(\"chart-participants\");\n var pg = layout(pieEl);\n var topN = 10;\n var ranked = data.participants.slice().sort(function (a, b) { return b.messages - a.messages; });\n var topSlice = ranked.slice(0, topN);\n var otherSum = ranked.slice(topN).reduce(function (s, x) { return s + x.messages; }, 0);\n var pieData = topSlice.map(function (x) { return { name: x.alias, value: x.messages }; });\n if (otherSum > 0) pieData.push({ name: \"\uAE30\uD0C0\", value: otherSum });\n var pieR = pg.w < 380 ? [\"40%\", \"68%\"] : [\"38%\", \"66%\"];\n init(\"chart-participants\", Object.assign(baseOpt(), {\n tooltip: { trigger: \"item\", formatter: \"{b}: {c} ({d}%)\" },\n legend: { show: false },\n series: [{\n type: \"pie\",\n radius: pieR,\n center: [\"50%\", \"48%\"],\n avoidLabelOverlap: true,\n minShowLabelAngle: 10,\n data: pieData,\n label: {\n show: true,\n position: \"outside\",\n color: text,\n fontSize: pg.fs,\n formatter: function (params) {\n var n = params.name || \"\";\n return n.length > 8 ? n.slice(0, 7) + \"\u2026\" : n;\n },\n },\n labelLine: { show: true, length: 8, length2: 6, lineStyle: { color: muted } },\n itemStyle: { borderRadius: 4, borderWidth: 0 },\n }],\n }));\n }\n\n if (data.topics && data.topics.length && document.getElementById(\"chart-topics\")) {\n var topEl = document.getElementById(\"chart-topics\");\n var tg = layout(topEl);\n var topics = data.topics.slice(0, 8);\n init(\"chart-topics\", Object.assign(baseOpt(), {\n grid: { left: Math.max(tg.leftCat, tg.w < 380 ? 72 : 96), right: tg.right, top: tg.top, bottom: tg.bottom },\n xAxis: { type: \"value\", axisLabel: { color: muted, fontSize: tg.fs, formatter: \"{value}%\" } },\n yAxis: {\n type: \"category\",\n data: topics.map(function (t) { return t.title; }).reverse(),\n axisLabel: { color: text, fontSize: tg.fs },\n },\n series: [{\n type: \"bar\",\n data: topics.map(function (t) { return t.messagePercent; }).reverse(),\n itemStyle: {\n borderRadius: [0, 6, 6, 0],\n color: function (p) { return p.dataIndex % 2 === 0 ? accent : accent2; },\n },\n }],\n }));\n }\n\n if (data.domains && document.getElementById(\"chart-domains\")) {\n init(\"chart-domains\", Object.assign(baseOpt(), {\n tooltip: { trigger: \"item\" },\n series: [{\n type: \"treemap\",\n data: data.domains.map(function (d) { return { name: d.label, value: d.count }; }),\n label: { color: text, fontSize: 11 },\n itemStyle: { borderColor: dark ? \"#0d1117\" : \"#fff\", gapWidth: 2 },\n }],\n }));\n }\n\n if (data.interaction && data.interaction.aliases.length && document.getElementById(\"chart-dyad\")) {\n var ix = data.interaction;\n var heat = [];\n var maxV = 1;\n for (var ri = 0; ri < ix.matrix.length; ri += 1) {\n for (var ci = 0; ci < ix.matrix[ri].length; ci += 1) {\n var v = ix.matrix[ri][ci];\n if (v > maxV) maxV = v;\n if (v > 0) heat.push([ci, ri, v]);\n }\n }\n var dyEl = document.getElementById(\"chart-dyad\");\n var dg = layout(dyEl);\n init(\"chart-dyad\", Object.assign(baseOpt(), {\n tooltip: { position: \"top\" },\n grid: { left: Math.max(dg.leftCat, 72), right: dg.right, top: dg.top, bottom: 56 },\n xAxis: { type: \"category\", data: ix.aliases, axisLabel: { color: muted, fontSize: dg.fs, rotate: 32 }, splitArea: { show: true } },\n yAxis: { type: \"category\", data: ix.aliases, axisLabel: { color: muted, fontSize: dg.fs }, splitArea: { show: true } },\n visualMap: { min: 0, max: maxV, calculable: true, orient: \"horizontal\", left: \"center\", bottom: 4, inRange: { color: [dark ? \"#0d1117\" : \"#f0f4f8\", accent, accent2] } },\n series: [{ type: \"heatmap\", data: heat, emphasis: { itemStyle: { shadowBlur: 12, shadowColor: \"rgba(0,0,0,0.35)\" } } }],\n }));\n }\n requestAnimationFrame(resizeAll);\n setTimeout(resizeAll, 150);\n window.addEventListener(\"resize\", resizeAll);\n window.addEventListener(\"load\", resizeAll);\n }\n function whenVisible() {\n var anchor = document.getElementById(\"s-viz\") || document.querySelector(\".chart-box\");\n if (!anchor || typeof IntersectionObserver === \"undefined\") {\n run();\n return;\n }\n var started = false;\n var io = new IntersectionObserver(function (entries) {\n if (started) return;\n if (entries.some(function (e) { return e.isIntersecting; })) {\n started = true;\n io.disconnect();\n run();\n }\n }, { rootMargin: \"480px 0px\", threshold: 0.01 });\n io.observe(anchor);\n setTimeout(function () {\n if (started) return;\n var r = anchor.getBoundingClientRect();\n if (r.top < window.innerHeight + 320) {\n started = true;\n io.disconnect();\n run();\n }\n }, 200);\n }\n function bootCharts() {\n if (typeof echarts === \"undefined\") return false;\n whenVisible();\n return true;\n }\n if (!bootCharts()) {\n window.addEventListener(\"load\", function () {\n var tries = 0;\n (function wait() {\n if (bootCharts()) return;\n if (++tries > 120) {\n document.querySelectorAll(\".chart-box\").forEach(function (el) {\n if (!el.querySelector(\"canvas\")) {\n el.innerHTML = '<p style=\"margin:0;padding:12px;font-size:12px;color:var(--muted);text-align:center\">ECharts CDN\uC744 \uBD88\uB7EC\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.</p>';\n }\n });\n return;\n }\n setTimeout(wait, 50);\n })();\n });\n }\n })();\n";
61
+ export declare const CHARTS_INIT_SCRIPT = "\n (function () {\n function run() {\n var dataEl = document.getElementById(\"kca-chart-data\");\n if (!dataEl) return;\n if (typeof echarts === \"undefined\") return;\n var data;\n try { data = JSON.parse(dataEl.textContent || \"{}\"); } catch (e) { return; }\n\n var dark = document.documentElement.getAttribute(\"data-theme\") === \"dark\" ||\n (!document.documentElement.getAttribute(\"data-theme\") &&\n window.matchMedia && window.matchMedia(\"(prefers-color-scheme: dark)\").matches);\n var text = dark ? \"#e9eef5\" : \"#141a1f\";\n var muted = dark ? \"#8b98a8\" : \"#5c6670\";\n var accent = dark ? \"#3ee8c5\" : \"#0f6b5c\";\n var accent2 = dark ? \"#818cf8\" : \"#4f46e5\";\n function cssVar(name, fallback) {\n try {\n var v = getComputedStyle(document.body).getPropertyValue(name).trim();\n return v || fallback;\n } catch (e) { return fallback; }\n }\n var heatLo = cssVar(\"--chart-heat-lo\", dark ? \"#1a2744\" : \"#d4e4f4\");\n var heatHi = cssVar(\"--chart-heat-hi\", dark ? \"#5ee8ff\" : \"#1e4fd6\");\n var wdColors = [\n cssVar(\"--chart-wd-0\", dark ? \"#818cf8\" : \"#4f46e5\"),\n cssVar(\"--chart-wd-1\", dark ? \"#3ee8c5\" : \"#0f6b5c\"),\n cssVar(\"--chart-wd-2\", dark ? \"#34d399\" : \"#059669\"),\n cssVar(\"--chart-wd-3\", dark ? \"#2dd4bf\" : \"#0d9488\"),\n cssVar(\"--chart-wd-4\", dark ? \"#38bdf8\" : \"#0284c7\"),\n cssVar(\"--chart-wd-5\", dark ? \"#fbbf24\" : \"#d97706\"),\n cssVar(\"--chart-wd-6\", dark ? \"#fb923c\" : \"#ea580c\"),\n ];\n\n function baseOpt() {\n return {\n textStyle: { color: text, fontFamily: \"Pretendard, Apple SD Gothic Neo, sans-serif\" },\n tooltip: { trigger: \"axis\", backgroundColor: dark ? \"#1c2128\" : \"#fff\", borderColor: \"transparent\" },\n };\n }\n\n var charts = [];\n function resizeAll() {\n charts.forEach(function (c) {\n try { c.resize(); } catch (e) {}\n });\n }\n function layout(el) {\n var w = (el && el.clientWidth) || 400;\n if (w < 380) {\n return { w: w, left: 28, right: 8, top: 14, bottom: 44, fs: 9, rot: 40, leftCat: 56, bottomRot: 42 };\n }\n if (w < 640) {\n return { w: w, left: 40, right: 10, top: 18, bottom: 34, fs: 10, rot: 26, leftCat: 72, bottomRot: 32 };\n }\n return { w: w, left: 48, right: 14, top: 22, bottom: 28, fs: 11, rot: 0, leftCat: 96, bottomRot: 28 };\n }\n function init(id, opt) {\n var el = document.getElementById(id);\n if (!el) return null;\n try {\n var chart = echarts.init(el, null, { renderer: \"canvas\" });\n chart.setOption(opt);\n charts.push(chart);\n if (typeof ResizeObserver !== \"undefined\") {\n var ro = new ResizeObserver(function () {\n requestAnimationFrame(function () {\n try { chart.resize(); } catch (e) {}\n });\n });\n ro.observe(el);\n }\n return chart;\n } catch (err) {\n console.error(\"[kca-chart]\", id, err);\n el.setAttribute(\"data-chart-failed\", \"1\");\n el.innerHTML = '<p style=\"margin:0;padding:12px;font-size:12px;color:var(--muted);text-align:center\">\uCC28\uD2B8\uB97C \uBD88\uB7EC\uC624\uC9C0 \uBABB\uD588\uC5B4\uC694. \uC0C8\uB85C\uACE0\uCE68\uD558\uAC70\uB098 \uB124\uD2B8\uC6CC\uD06C(CDN)\uB97C \uD655\uC778\uD574 \uC8FC\uC138\uC694.</p>';\n return null;\n }\n }\n var mqWide = window.matchMedia && window.matchMedia(\"(min-width: 900px)\");\n if (mqWide && mqWide.addEventListener) {\n mqWide.addEventListener(\"change\", function () { setTimeout(resizeAll, 80); });\n } else if (mqWide && mqWide.addListener) {\n mqWide.addListener(function () { setTimeout(resizeAll, 80); });\n }\n var themeObs = new MutationObserver(function () { setTimeout(resizeAll, 60); });\n themeObs.observe(document.documentElement, { attributes: true, attributeFilter: [\"data-theme\"] });\n\n function hourBarColor(h) {\n if (h <= 5) return dark ? \"#6366f1\" : \"#4f46e5\";\n if (h <= 11) return dark ? \"#3ee8c5\" : \"#0f6b5c\";\n if (h <= 17) return dark ? \"#fbbf24\" : \"#d97706\";\n return dark ? \"#3b82f6\" : \"#1d4ed8\";\n }\n if (data.hourly && document.getElementById(\"chart-hours\")) {\n var hoursEl = document.getElementById(\"chart-hours\");\n var hg = layout(hoursEl);\n init(\"chart-hours\", Object.assign(baseOpt(), {\n grid: { left: hg.left, right: hg.right, top: hg.top, bottom: hg.bottom },\n xAxis: { type: \"category\", data: data.hourly.map(function (_, h) { return h + \"\uC2DC\"; }), axisLabel: { color: muted, fontSize: hg.fs, rotate: hg.rot } },\n yAxis: { type: \"value\", axisLabel: { color: muted }, splitLine: { lineStyle: { color: dark ? \"rgba(255,255,255,0.06)\" : \"rgba(0,0,0,0.06)\" } } },\n series: [{\n type: \"bar\",\n data: data.hourly.map(function (v, h) {\n return { value: v, itemStyle: { color: hourBarColor(h), borderRadius: [4, 4, 0, 0] } };\n }),\n markArea: {\n silent: true,\n itemStyle: { color: dark ? \"rgba(99,102,241,0.12)\" : \"rgba(79,70,229,0.08)\" },\n data: [[{ xAxis: \"0\uC2DC\" }, { xAxis: \"5\uC2DC\" }], [{ xAxis: \"22\uC2DC\" }, { xAxis: \"23\uC2DC\" }]],\n },\n }],\n }));\n }\n\n if (data.weekdays && document.getElementById(\"chart-weekday\")) {\n var wdEl = document.getElementById(\"chart-weekday\");\n var wg = layout(wdEl);\n var wdCounts = data.weekdays.map(function (w) { return w.count; });\n var wdMax = Math.max.apply(null, wdCounts.concat([1]));\n init(\"chart-weekday\", Object.assign(baseOpt(), {\n grid: { left: wg.leftCat, right: wg.right, top: wg.top, bottom: wg.bottom },\n xAxis: { type: \"value\", axisLabel: { color: muted, fontSize: wg.fs } },\n yAxis: { type: \"category\", data: data.weekdays.map(function (w) { return w.label; }), axisLabel: { color: muted, fontSize: wg.fs } },\n series: [{\n type: \"bar\",\n data: data.weekdays.map(function (w, i) {\n var c = wdColors[i % 7];\n return {\n value: w.count,\n itemStyle: {\n color: c,\n borderRadius: [0, 6, 6, 0],\n shadowBlur: w.count >= wdMax ? 10 : 0,\n shadowColor: w.count >= wdMax ? (dark ? \"rgba(62,232,197,0.45)\" : \"rgba(15,107,92,0.35)\") : \"transparent\",\n },\n };\n }),\n }],\n }));\n }\n\n if (data.monthly && document.getElementById(\"chart-monthly\")) {\n var moEl = document.getElementById(\"chart-monthly\");\n var mg = layout(moEl);\n init(\"chart-monthly\", Object.assign(baseOpt(), {\n grid: { left: mg.left, right: mg.right, top: mg.top, bottom: mg.bottom },\n xAxis: { type: \"category\", data: data.monthly.map(function (m) { return m.label; }), axisLabel: { color: muted, fontSize: mg.fs, rotate: mg.bottomRot } },\n yAxis: { type: \"value\", axisLabel: { color: muted, fontSize: mg.fs }, splitLine: { lineStyle: { color: dark ? \"rgba(255,255,255,0.06)\" : \"rgba(0,0,0,0.06)\" } } },\n series: [{ type: \"line\", smooth: true, data: data.monthly.map(function (m) { return m.count; }), areaStyle: { opacity: 0.12 }, lineStyle: { width: 2, color: accent2 }, itemStyle: { color: accent2 } }],\n }));\n }\n\n if (data.daily && document.getElementById(\"chart-daily-heat\")) {\n var heatEl = document.getElementById(\"chart-daily-heat\");\n var dg = layout(heatEl);\n var heatMax = Math.max.apply(null, data.daily.map(function (d) { return d.count; }).concat([1]));\n var heat = data.daily.map(function (d) { return [d.date, d.count]; });\n var burstSet = {};\n (data.burstDates || []).forEach(function (d) { burstSet[d] = true; });\n var daySpan = data.daily.length;\n var useBarFallback = daySpan > 0 && daySpan < 90;\n if (useBarFallback) {\n var labels = data.daily.map(function (d) {\n var p = d.date.split(\"-\");\n return p.length === 3 ? Number(p[1]) + \"/\" + Number(p[2]) : d.date;\n });\n init(\"chart-daily-heat\", Object.assign(baseOpt(), {\n grid: { left: dg.left, right: dg.right, top: dg.top, bottom: Math.max(dg.bottom, 52), containLabel: true },\n tooltip: { trigger: \"axis\" },\n xAxis: { type: \"category\", data: labels, axisLabel: { color: muted, fontSize: dg.fs, rotate: labels.length > 20 ? 40 : 0, interval: labels.length > 40 ? Math.floor(labels.length / 20) : 0 } },\n yAxis: { type: \"value\", axisLabel: { color: muted }, splitLine: { lineStyle: { color: dark ? \"rgba(255,255,255,0.06)\" : \"rgba(0,0,0,0.06)\" } } },\n visualMap: { show: false, min: 0, max: heatMax, inRange: { color: dark ? [\"#161b22\", \"#0e4429\", \"#006d32\", \"#26a641\", \"#39d353\"] : [\"#ebedf0\", \"#9be9a8\", \"#40c463\", \"#30a14e\", \"#216e39\"] } },\n series: [{\n type: \"bar\",\n data: data.daily.map(function (d) { return d.count; }),\n itemStyle: { borderRadius: [3, 3, 0, 0], borderWidth: 0 },\n emphasis: { itemStyle: { shadowBlur: 10, shadowColor: dark ? \"rgba(62,232,197,0.45)\" : \"rgba(15,107,92,0.35)\" } },\n }],\n }));\n } else {\n var cellH = dg.w < 380 ? 12 : dg.w < 640 ? 14 : 16;\n var cellW = dg.w < 380 ? 12 : 14;\n init(\"chart-daily-heat\", Object.assign(baseOpt(), {\n tooltip: { position: \"top\" },\n visualMap: { min: 0, max: heatMax, calculable: true, orient: \"horizontal\", left: \"center\", bottom: 0, textStyle: { color: muted, fontSize: dg.fs }, itemWidth: dg.w < 380 ? 10 : 14, itemHeight: dg.w < 380 ? 60 : 80, inRange: { color: dark ? [\"#161b22\", \"#0e4429\", \"#006d32\", \"#26a641\", \"#39d353\"] : [\"#ebedf0\", \"#9be9a8\", \"#40c463\", \"#30a14e\", \"#216e39\"] } },\n calendar: { top: dg.w < 380 ? 28 : 36, left: dg.left, right: dg.right, cellSize: [cellW, cellH], range: data.daily.length ? [data.daily[0].date, data.daily[data.daily.length - 1].date] : undefined, itemStyle: { borderWidth: 0, borderColor: \"transparent\" }, dayLabel: { color: muted, fontSize: dg.fs }, monthLabel: { color: muted, fontSize: dg.fs } },\n series: [{ type: \"heatmap\", coordinateSystem: \"calendar\", data: heat, emphasis: { itemStyle: { shadowBlur: 8, shadowColor: dark ? \"rgba(62,232,197,0.5)\" : \"rgba(33,110,57,0.45)\" } } }],\n }));\n }\n }\n\n if (data.keywords && document.getElementById(\"chart-kw-bar\")) {\n var kwEl = document.getElementById(\"chart-kw-bar\");\n var kg = layout(kwEl);\n var kwLimit = kg.w < 380 ? 20 : 30;\n var topBar = data.keywords.slice(0, kwLimit);\n var nKw = topBar.length;\n var padY = Math.min(48, 8 + nKw * 0.4);\n function kwBarColor(rankFromTop) {\n if (rankFromTop === 0) return dark ? \"#a78bfa\" : \"#6366f1\";\n if (rankFromTop === 1) return dark ? \"#818cf8\" : \"#4f46e5\";\n if (rankFromTop === 2) return dark ? \"#5b9bd5\" : \"#3b82f6\";\n return dark ? \"rgba(129,140,248,0.55)\" : \"rgba(79,70,229,0.45)\";\n }\n var kwSeries = topBar.map(function (k, i) {\n return {\n value: k.count,\n name: k.label,\n itemStyle: { color: kwBarColor(i), borderRadius: [0, 4, 4, 0] },\n };\n }).reverse();\n init(\"chart-kw-bar\", Object.assign(baseOpt(), {\n grid: { left: 8, right: kg.right, top: padY, bottom: padY, containLabel: false },\n xAxis: { type: \"value\", axisLabel: { color: muted, fontSize: kg.fs } },\n yAxis: {\n type: \"category\",\n data: topBar.map(function (k) { return k.label; }).reverse(),\n axisLabel: { show: false },\n axisTick: { show: false },\n axisLine: { show: false },\n },\n series: [{\n type: \"bar\",\n data: kwSeries,\n label: [\n {\n show: true,\n position: \"insideLeft\",\n color: text,\n fontSize: kg.fs,\n fontWeight: 600,\n formatter: \"{b}\",\n padding: [0, 0, 0, 6],\n },\n {\n show: true,\n position: \"right\",\n color: muted,\n fontSize: kg.fs,\n formatter: \"{c}\",\n },\n ],\n }],\n }));\n }\n\n if (data.keywords && document.getElementById(\"chart-kw-cloud\")) {\n var cloudEl = document.getElementById(\"chart-kw-cloud\");\n var cg = layout(cloudEl);\n var cloud = data.keywords.slice(0, 100).map(function (k) {\n return { name: k.label, value: k.count };\n });\n var sizeLo = cg.w < 380 ? 10 : 12;\n var sizeHi = cg.w < 380 ? 34 : cg.w < 640 ? 46 : 56;\n init(\"chart-kw-cloud\", {\n textStyle: baseOpt().textStyle,\n tooltip: { show: true },\n series: [{\n type: \"wordCloud\",\n shape: \"circle\",\n gridSize: cg.w < 380 ? 8 : 6,\n sizeRange: [sizeLo, sizeHi],\n rotationRange: [-45, 45],\n textStyle: {\n fontFamily: \"Pretendard, Apple SD Gothic Neo, sans-serif\",\n color: function () {\n var palette = dark ? [\"#3ee8c5\", \"#818cf8\", \"#fbbf24\", \"#fb923c\", \"#f472b6\"] : [\"#0f6b5c\", \"#4f46e5\", \"#b8860b\", \"#c45c2a\", \"#be185d\"];\n return palette[Math.floor(Math.random() * palette.length)];\n },\n },\n data: cloud,\n }],\n });\n }\n\n if (data.participants && document.getElementById(\"chart-participants\")) {\n var pieEl = document.getElementById(\"chart-participants\");\n var pg = layout(pieEl);\n var topN = 10;\n var ranked = data.participants.slice().sort(function (a, b) { return b.messages - a.messages; });\n var topSlice = ranked.slice(0, topN);\n var otherSum = ranked.slice(topN).reduce(function (s, x) { return s + x.messages; }, 0);\n var pieData = topSlice.map(function (x) { return { name: x.alias, value: x.messages }; });\n if (otherSum > 0) pieData.push({ name: \"\uAE30\uD0C0\", value: otherSum });\n var pieR = pg.w < 380 ? [\"40%\", \"68%\"] : [\"38%\", \"66%\"];\n init(\"chart-participants\", Object.assign(baseOpt(), {\n tooltip: { trigger: \"item\", formatter: \"{b}: {c} ({d}%)\" },\n legend: { show: false },\n series: [{\n type: \"pie\",\n radius: pieR,\n center: [\"50%\", \"48%\"],\n avoidLabelOverlap: true,\n minShowLabelAngle: 10,\n data: pieData,\n label: {\n show: true,\n position: \"outside\",\n color: text,\n fontSize: pg.fs,\n formatter: function (params) {\n var n = params.name || \"\";\n return n.length > 8 ? n.slice(0, 7) + \"\u2026\" : n;\n },\n },\n labelLine: { show: true, length: 8, length2: 6, lineStyle: { color: muted } },\n itemStyle: { borderRadius: 4, borderWidth: 0 },\n }],\n }));\n }\n\n if (data.topicsThemes && data.topicsThemes.length && document.getElementById(\"chart-topics\")) {\n var topEl = document.getElementById(\"chart-topics\");\n var tg = layout(topEl);\n var topics = data.topicsThemes.slice(0, 8);\n init(\"chart-topics\", Object.assign(baseOpt(), {\n grid: { left: Math.max(tg.leftCat, tg.w < 380 ? 72 : 96), right: tg.right, top: tg.top, bottom: tg.bottom },\n xAxis: { type: \"value\", axisLabel: { color: muted, fontSize: tg.fs, formatter: \"{value}%\" } },\n yAxis: {\n type: \"category\",\n data: topics.map(function (t) { return t.title; }).reverse(),\n axisLabel: { color: text, fontSize: tg.fs },\n },\n series: [{\n type: \"bar\",\n data: topics.map(function (t) { return t.messagePercent; }).reverse(),\n itemStyle: {\n borderRadius: [0, 6, 6, 0],\n color: function (p) { return p.dataIndex % 2 === 0 ? accent : accent2; },\n },\n }],\n }));\n }\n\n if (data.domains && document.getElementById(\"chart-domains\")) {\n init(\"chart-domains\", Object.assign(baseOpt(), {\n tooltip: { trigger: \"item\" },\n series: [{\n type: \"treemap\",\n data: data.domains.map(function (d) { return { name: d.label, value: d.count }; }),\n label: { color: text, fontSize: 11 },\n itemStyle: { borderColor: dark ? \"#0d1117\" : \"#fff\", gapWidth: 2 },\n }],\n }));\n }\n\n if (data.interaction && data.interaction.aliases.length && document.getElementById(\"chart-dyad\")) {\n var ix = data.interaction;\n var heat = [];\n var maxV = 1;\n for (var ri = 0; ri < ix.matrix.length; ri += 1) {\n for (var ci = 0; ci < ix.matrix[ri].length; ci += 1) {\n var v = ix.matrix[ri][ci];\n if (v > maxV) maxV = v;\n if (v > 0) heat.push({ value: [ci, ri, v], label: { show: v >= maxV * 0.15, formatter: String(v), color: text, fontSize: 9 } });\n }\n }\n var dyEl = document.getElementById(\"chart-dyad\");\n var dg = layout(dyEl);\n var splitFill = dark ? [\"rgba(255,255,255,0.03)\", \"rgba(255,255,255,0.06)\"] : [\"rgba(0,0,0,0.02)\", \"rgba(0,0,0,0.05)\"];\n init(\"chart-dyad\", Object.assign(baseOpt(), {\n tooltip: { position: \"top\", formatter: function (p) { var v = p.value[2]; return ix.aliases[p.value[1]] + \" \u2192 \" + ix.aliases[p.value[0]] + \": \" + v; } },\n grid: { left: Math.max(dg.leftCat, 72), right: dg.right, top: dg.top, bottom: 56 },\n xAxis: {\n type: \"category\",\n data: ix.aliases,\n axisLabel: { color: muted, fontSize: dg.fs, rotate: 32 },\n splitArea: { show: true, areaStyle: { color: splitFill } },\n },\n yAxis: {\n type: \"category\",\n data: ix.aliases,\n axisLabel: { color: muted, fontSize: dg.fs },\n splitArea: { show: true, areaStyle: { color: splitFill } },\n },\n visualMap: {\n min: 0,\n max: maxV,\n calculable: true,\n orient: \"horizontal\",\n left: \"center\",\n bottom: 4,\n inRange: { color: [heatLo, dark ? \"#2a9d8f\" : \"#7ecfc2\", dark ? \"#3ee8c5\" : \"#0f6b5c\", heatHi] },\n },\n series: [{\n type: \"heatmap\",\n data: heat,\n itemStyle: { borderWidth: 0 },\n emphasis: { itemStyle: { shadowBlur: 12, shadowColor: dark ? \"rgba(62,232,197,0.5)\" : \"rgba(15,107,92,0.35)\" } },\n }],\n }));\n }\n requestAnimationFrame(resizeAll);\n setTimeout(resizeAll, 150);\n window.addEventListener(\"resize\", resizeAll);\n window.addEventListener(\"load\", resizeAll);\n }\n function whenVisible() {\n var anchor = document.getElementById(\"s-viz\") || document.querySelector(\".chart-box\");\n if (!anchor || typeof IntersectionObserver === \"undefined\") {\n run();\n return;\n }\n var started = false;\n var io = new IntersectionObserver(function (entries) {\n if (started) return;\n if (entries.some(function (e) { return e.isIntersecting; })) {\n started = true;\n io.disconnect();\n run();\n }\n }, { rootMargin: \"480px 0px\", threshold: 0.01 });\n io.observe(anchor);\n setTimeout(function () {\n if (started) return;\n var r = anchor.getBoundingClientRect();\n if (r.top < window.innerHeight + 320) {\n started = true;\n io.disconnect();\n run();\n }\n }, 200);\n }\n function bootCharts() {\n if (typeof echarts === \"undefined\") return false;\n whenVisible();\n return true;\n }\n if (!bootCharts()) {\n window.addEventListener(\"load\", function () {\n var tries = 0;\n (function wait() {\n if (bootCharts()) return;\n if (++tries > 120) {\n document.querySelectorAll(\".chart-box\").forEach(function (el) {\n if (!el.querySelector(\"canvas\")) {\n el.innerHTML = '<p style=\"margin:0;padding:12px;font-size:12px;color:var(--muted);text-align:center\">ECharts CDN\uC744 \uBD88\uB7EC\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.</p>';\n }\n });\n return;\n }\n setTimeout(wait, 50);\n })();\n });\n }\n })();\n";
@@ -1,4 +1,6 @@
1
+ import { isShortActivitySpan, topicsThemesOnly } from "./report-chart-util.js";
1
2
  import { escapeHtml, formatNumber } from "./report-util.js";
3
+ const KW_BAR_CHART_LIMIT = 30;
2
4
  /** @deprecated preconnect는 report-head.ts REPORT_HEAD_LINKS 사용 */
3
5
  export const CHART_CDN_HEAD = ``;
4
6
  /** body 끝: 차트 라이브러리 — defer 금지(인라인 init보다 반드시 먼저 실행) */
@@ -31,12 +33,20 @@ export function buildChartPayload(data) {
31
33
  .map((c) => ({ date: c.date, count: c.count })),
32
34
  burstDates: data.burstDays.map((b) => b.date),
33
35
  totalParticipants: data.participants.length,
34
- topics: data.topics.slice(0, 8).map((t) => ({
35
- title: t.title,
36
- terms: t.terms,
37
- messagePercent: t.messagePercent,
38
- kind: t.kind,
39
- })),
36
+ topicsThemes: topicsThemesOnly(data.topics)
37
+ .slice(0, 8)
38
+ .map((t) => ({ title: t.title, terms: t.terms, messagePercent: t.messagePercent })),
39
+ topicsPeriods: isShortActivitySpan(data.daily)
40
+ ? []
41
+ : data.topics
42
+ .filter((t) => t.kind === "period")
43
+ .slice(0, 4)
44
+ .map((t) => ({
45
+ title: t.title,
46
+ terms: t.terms,
47
+ messagePercent: t.messagePercent,
48
+ periodLabel: t.periodLabel,
49
+ })),
40
50
  interaction: data.interaction
41
51
  ? {
42
52
  aliases: data.interaction.aliases,
@@ -54,13 +64,13 @@ export function serializeExplorerPayload(data) {
54
64
  }
55
65
  export function renderChartDeck(data) {
56
66
  const kw = data.keywords.length;
57
- const topicCount = data.topics.length;
67
+ const themeCount = topicsThemesOnly(data.topics).length;
58
68
  const showLegacyDaily = data.story.calendarWeeks.length === 0 && data.daily.length > 0;
59
- const topicChart = topicCount > 0
69
+ const topicChart = themeCount > 0
60
70
  ? `<article class="viz-card span-12">
61
- <h3>주제 · c-TF-IDF</h3>
62
- <p class="viz-hint">막대 = 해당 주제 신호가 잡힌 메시지 비중(근사 %). 테마·월별 화제를 함께 봅니다.</p>
63
- <div id="chart-topics" class="chart-box" role="img" aria-label="주제 차트"></div>
71
+ <h3>대화 테마 · c-TF-IDF</h3>
72
+ <p class="viz-hint">막대 = <strong>의미 주제</strong> 신호 비중(근사 %). 월별 메시지량은 「기간 비교」·아래 주제 카드의 월별 화제를 보세요.</p>
73
+ <div id="chart-topics" class="chart-box" role="img" aria-label="주제 테마 차트"></div>
64
74
  </article>`
65
75
  : "";
66
76
  return `<section id="s-viz" class="viz-hero anim-enter" style="--enter-delay:0.055s" aria-label="인터랙티브 차트">
@@ -92,8 +102,8 @@ export function renderChartDeck(data) {
92
102
  <div id="chart-monthly" class="chart-box compact" role="img" aria-label="월별 차트"></div>
93
103
  </article>
94
104
  <article class="viz-card span-12">
95
- <h3>키워드 상위 ${formatNumber(Math.min(kw, 80))} · 메시지 등장 횟수</h3>
96
- <p class="viz-hint">막대는 실제로 해당 단어가 포함된 메시지 수입니다. 아래 표에서 전체 ${formatNumber(kw)}개를 볼 수 있어요.</p>
105
+ <h3>키워드 상위 ${formatNumber(Math.min(kw, KW_BAR_CHART_LIMIT))} · 메시지 등장 횟수</h3>
106
+ <p class="viz-hint">차트는 상위 ${KW_BAR_CHART_LIMIT}개(막대 안에 키워드 표시). 아래 표에서 전체 ${formatNumber(kw)}개를 볼 수 있어요.</p>
97
107
  <div id="chart-kw-bar" class="chart-box tall" role="img" aria-label="키워드 막대 차트"></div>
98
108
  ${renderKeywordTable(data.keywords)}
99
109
  </article>
@@ -145,6 +155,23 @@ export const CHARTS_INIT_SCRIPT = `
145
155
  var muted = dark ? "#8b98a8" : "#5c6670";
146
156
  var accent = dark ? "#3ee8c5" : "#0f6b5c";
147
157
  var accent2 = dark ? "#818cf8" : "#4f46e5";
158
+ function cssVar(name, fallback) {
159
+ try {
160
+ var v = getComputedStyle(document.body).getPropertyValue(name).trim();
161
+ return v || fallback;
162
+ } catch (e) { return fallback; }
163
+ }
164
+ var heatLo = cssVar("--chart-heat-lo", dark ? "#1a2744" : "#d4e4f4");
165
+ var heatHi = cssVar("--chart-heat-hi", dark ? "#5ee8ff" : "#1e4fd6");
166
+ var wdColors = [
167
+ cssVar("--chart-wd-0", dark ? "#818cf8" : "#4f46e5"),
168
+ cssVar("--chart-wd-1", dark ? "#3ee8c5" : "#0f6b5c"),
169
+ cssVar("--chart-wd-2", dark ? "#34d399" : "#059669"),
170
+ cssVar("--chart-wd-3", dark ? "#2dd4bf" : "#0d9488"),
171
+ cssVar("--chart-wd-4", dark ? "#38bdf8" : "#0284c7"),
172
+ cssVar("--chart-wd-5", dark ? "#fbbf24" : "#d97706"),
173
+ cssVar("--chart-wd-6", dark ? "#fb923c" : "#ea580c"),
174
+ ];
148
175
 
149
176
  function baseOpt() {
150
177
  return {
@@ -231,11 +258,27 @@ export const CHARTS_INIT_SCRIPT = `
231
258
  if (data.weekdays && document.getElementById("chart-weekday")) {
232
259
  var wdEl = document.getElementById("chart-weekday");
233
260
  var wg = layout(wdEl);
261
+ var wdCounts = data.weekdays.map(function (w) { return w.count; });
262
+ var wdMax = Math.max.apply(null, wdCounts.concat([1]));
234
263
  init("chart-weekday", Object.assign(baseOpt(), {
235
264
  grid: { left: wg.leftCat, right: wg.right, top: wg.top, bottom: wg.bottom },
236
265
  xAxis: { type: "value", axisLabel: { color: muted, fontSize: wg.fs } },
237
266
  yAxis: { type: "category", data: data.weekdays.map(function (w) { return w.label; }), axisLabel: { color: muted, fontSize: wg.fs } },
238
- series: [{ type: "bar", data: data.weekdays.map(function (w) { return w.count; }), itemStyle: { color: accent, borderRadius: [0, 6, 6, 0] } }],
267
+ series: [{
268
+ type: "bar",
269
+ data: data.weekdays.map(function (w, i) {
270
+ var c = wdColors[i % 7];
271
+ return {
272
+ value: w.count,
273
+ itemStyle: {
274
+ color: c,
275
+ borderRadius: [0, 6, 6, 0],
276
+ shadowBlur: w.count >= wdMax ? 10 : 0,
277
+ shadowColor: w.count >= wdMax ? (dark ? "rgba(62,232,197,0.45)" : "rgba(15,107,92,0.35)") : "transparent",
278
+ },
279
+ };
280
+ }),
281
+ }],
239
282
  }));
240
283
  }
241
284
 
@@ -292,15 +335,55 @@ export const CHARTS_INIT_SCRIPT = `
292
335
  if (data.keywords && document.getElementById("chart-kw-bar")) {
293
336
  var kwEl = document.getElementById("chart-kw-bar");
294
337
  var kg = layout(kwEl);
295
- var topBar = data.keywords.slice(0, kg.w < 380 ? 24 : 80);
296
- var maxLabelLen = 0;
297
- topBar.forEach(function (k) { if (k.label.length > maxLabelLen) maxLabelLen = k.label.length; });
298
- var kwLeft = Math.max(kg.leftCat, Math.min(kg.w * 0.42, 24 + maxLabelLen * (kg.fs + 1)));
338
+ var kwLimit = kg.w < 380 ? 20 : 30;
339
+ var topBar = data.keywords.slice(0, kwLimit);
340
+ var nKw = topBar.length;
341
+ var padY = Math.min(48, 8 + nKw * 0.4);
342
+ function kwBarColor(rankFromTop) {
343
+ if (rankFromTop === 0) return dark ? "#a78bfa" : "#6366f1";
344
+ if (rankFromTop === 1) return dark ? "#818cf8" : "#4f46e5";
345
+ if (rankFromTop === 2) return dark ? "#5b9bd5" : "#3b82f6";
346
+ return dark ? "rgba(129,140,248,0.55)" : "rgba(79,70,229,0.45)";
347
+ }
348
+ var kwSeries = topBar.map(function (k, i) {
349
+ return {
350
+ value: k.count,
351
+ name: k.label,
352
+ itemStyle: { color: kwBarColor(i), borderRadius: [0, 4, 4, 0] },
353
+ };
354
+ }).reverse();
299
355
  init("chart-kw-bar", Object.assign(baseOpt(), {
300
- grid: { left: kwLeft, right: kg.right, top: kg.top, bottom: kg.bottom, containLabel: true },
356
+ grid: { left: 8, right: kg.right, top: padY, bottom: padY, containLabel: false },
301
357
  xAxis: { type: "value", axisLabel: { color: muted, fontSize: kg.fs } },
302
- yAxis: { type: "category", data: topBar.map(function (k) { return k.label; }).reverse(), axisLabel: { color: text, fontSize: kg.fs, width: kwLeft - 12, overflow: "truncate" } },
303
- series: [{ type: "bar", data: topBar.map(function (k) { return k.count; }).reverse(), itemStyle: { color: accent2, borderRadius: [0, 4, 4, 0] }, label: { show: true, position: "right", color: muted, fontSize: kg.fs, formatter: function (p) { return p.value; } } }],
358
+ yAxis: {
359
+ type: "category",
360
+ data: topBar.map(function (k) { return k.label; }).reverse(),
361
+ axisLabel: { show: false },
362
+ axisTick: { show: false },
363
+ axisLine: { show: false },
364
+ },
365
+ series: [{
366
+ type: "bar",
367
+ data: kwSeries,
368
+ label: [
369
+ {
370
+ show: true,
371
+ position: "insideLeft",
372
+ color: text,
373
+ fontSize: kg.fs,
374
+ fontWeight: 600,
375
+ formatter: "{b}",
376
+ padding: [0, 0, 0, 6],
377
+ },
378
+ {
379
+ show: true,
380
+ position: "right",
381
+ color: muted,
382
+ fontSize: kg.fs,
383
+ formatter: "{c}",
384
+ },
385
+ ],
386
+ }],
304
387
  }));
305
388
  }
306
389
 
@@ -369,10 +452,10 @@ export const CHARTS_INIT_SCRIPT = `
369
452
  }));
370
453
  }
371
454
 
372
- if (data.topics && data.topics.length && document.getElementById("chart-topics")) {
455
+ if (data.topicsThemes && data.topicsThemes.length && document.getElementById("chart-topics")) {
373
456
  var topEl = document.getElementById("chart-topics");
374
457
  var tg = layout(topEl);
375
- var topics = data.topics.slice(0, 8);
458
+ var topics = data.topicsThemes.slice(0, 8);
376
459
  init("chart-topics", Object.assign(baseOpt(), {
377
460
  grid: { left: Math.max(tg.leftCat, tg.w < 380 ? 72 : 96), right: tg.right, top: tg.top, bottom: tg.bottom },
378
461
  xAxis: { type: "value", axisLabel: { color: muted, fontSize: tg.fs, formatter: "{value}%" } },
@@ -412,18 +495,42 @@ export const CHARTS_INIT_SCRIPT = `
412
495
  for (var ci = 0; ci < ix.matrix[ri].length; ci += 1) {
413
496
  var v = ix.matrix[ri][ci];
414
497
  if (v > maxV) maxV = v;
415
- if (v > 0) heat.push([ci, ri, v]);
498
+ if (v > 0) heat.push({ value: [ci, ri, v], label: { show: v >= maxV * 0.15, formatter: String(v), color: text, fontSize: 9 } });
416
499
  }
417
500
  }
418
501
  var dyEl = document.getElementById("chart-dyad");
419
502
  var dg = layout(dyEl);
503
+ var splitFill = dark ? ["rgba(255,255,255,0.03)", "rgba(255,255,255,0.06)"] : ["rgba(0,0,0,0.02)", "rgba(0,0,0,0.05)"];
420
504
  init("chart-dyad", Object.assign(baseOpt(), {
421
- tooltip: { position: "top" },
505
+ tooltip: { position: "top", formatter: function (p) { var v = p.value[2]; return ix.aliases[p.value[1]] + " → " + ix.aliases[p.value[0]] + ": " + v; } },
422
506
  grid: { left: Math.max(dg.leftCat, 72), right: dg.right, top: dg.top, bottom: 56 },
423
- xAxis: { type: "category", data: ix.aliases, axisLabel: { color: muted, fontSize: dg.fs, rotate: 32 }, splitArea: { show: true } },
424
- yAxis: { type: "category", data: ix.aliases, axisLabel: { color: muted, fontSize: dg.fs }, splitArea: { show: true } },
425
- visualMap: { min: 0, max: maxV, calculable: true, orient: "horizontal", left: "center", bottom: 4, inRange: { color: [dark ? "#0d1117" : "#f0f4f8", accent, accent2] } },
426
- series: [{ type: "heatmap", data: heat, emphasis: { itemStyle: { shadowBlur: 12, shadowColor: "rgba(0,0,0,0.35)" } } }],
507
+ xAxis: {
508
+ type: "category",
509
+ data: ix.aliases,
510
+ axisLabel: { color: muted, fontSize: dg.fs, rotate: 32 },
511
+ splitArea: { show: true, areaStyle: { color: splitFill } },
512
+ },
513
+ yAxis: {
514
+ type: "category",
515
+ data: ix.aliases,
516
+ axisLabel: { color: muted, fontSize: dg.fs },
517
+ splitArea: { show: true, areaStyle: { color: splitFill } },
518
+ },
519
+ visualMap: {
520
+ min: 0,
521
+ max: maxV,
522
+ calculable: true,
523
+ orient: "horizontal",
524
+ left: "center",
525
+ bottom: 4,
526
+ inRange: { color: [heatLo, dark ? "#2a9d8f" : "#7ecfc2", dark ? "#3ee8c5" : "#0f6b5c", heatHi] },
527
+ },
528
+ series: [{
529
+ type: "heatmap",
530
+ data: heat,
531
+ itemStyle: { borderWidth: 0 },
532
+ emphasis: { itemStyle: { shadowBlur: 12, shadowColor: dark ? "rgba(62,232,197,0.5)" : "rgba(15,107,92,0.35)" } },
533
+ }],
427
534
  }));
428
535
  }
429
536
  requestAnimationFrame(resizeAll);
@@ -1 +1 @@
1
- {"version":3,"file":"report-charts.js","sourceRoot":"","sources":["../../src/report-charts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"report-charts.js","sourceRoot":"","sources":["../../src/report-charts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/E,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE5D,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAE9B,kEAAkE;AAClE,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AAEjC,wDAAwD;AACxD,MAAM,CAAC,MAAM,cAAc,GAAG;;;CAG7B,CAAC;AAwBF,MAAM,UAAU,qBAAqB,CAAC,IAAgB;IACpD,OAAO,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;SAC3C,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC;SACxB,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC;SAC7B,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAgB;IAChD,OAAO;QACL,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QACrE,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QAClC,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACvD,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,YAAY,EAAE,CAAC,CAAC,YAAY;SAC7B,CAAC,CAAC;QACH,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,aAAa;aACpC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;aACvB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;aACpC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAK,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QAClD,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAC7C,iBAAiB,EAAE,IAAI,CAAC,YAAY,CAAC,MAAM;QAC3C,YAAY,EAAE,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC;aACxC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;aACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC;QACrF,aAAa,EAAE,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC;YAC5C,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,IAAI,CAAC,MAAM;iBACR,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC;iBAClC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;iBACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACX,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,cAAc,EAAE,CAAC,CAAC,cAAc;gBAChC,WAAW,EAAE,CAAC,CAAC,WAAW;aAC3B,CAAC,CAAC;QACT,WAAW,EAAE,IAAI,CAAC,WAAW;YAC3B,CAAC,CAAC;gBACE,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,OAAO;gBACjC,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM;gBAC/B,YAAY,EAAE,IAAI,CAAC,WAAW,CAAC,YAAY;aAC5C;YACH,CAAC,CAAC,IAAI;KACT,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,IAAgB;IACvD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC;SACjC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC;SACxB,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC;SAC7B,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAgB;IAC9C,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;IAChC,MAAM,UAAU,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;IACxD,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IACvF,MAAM,UAAU,GACd,UAAU,GAAG,CAAC;QACZ,CAAC,CAAC;;;;eAIO;QACT,CAAC,CAAC,EAAE,CAAC;IAET,OAAO;;yEAEgE,YAAY,CAAC,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;mBA2BtE,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,kBAAkB,CAAC,CAAC;mCAC9B,kBAAkB,8BAA8B,YAAY,CAAC,EAAE,CAAC;;QAE3F,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC;;;;+BAIV,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;;QAE7D,uBAAuB,CAAC,IAAI,CAAC,YAAY,CAAC;;;;;;;MAO5C,UAAU;;IAEZ,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kEAAkE,EAAE,CAAC;AAChG,CAAC;AAED,SAAS,uBAAuB,CAC9B,YAAyE;IAEzE,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,YAAY;SACtB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SACZ,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CACJ,4CAA4C,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,uCAAuC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,YAAY,eAAe,CAC5L;SACA,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO,8CAA8C,IAAI,OAAO,CAAC;AACnE,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAyC;IACnE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,KAAK;SACf,GAAG,CACF,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CACV,+BAA+B,CAAC,GAAG,CAAC,YAAY,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,wBAAwB,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CACrI;SACA,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO,6JAA6J,IAAI,wBAAwB,CAAC;AACnM,CAAC;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgcjC,CAAC"}
@@ -71,7 +71,8 @@ function renderGitHubCalendar(data) {
71
71
  const summary = s.calendarTotalMessages > 0
72
72
  ? `<p class="gh-contrib-summary">이 기간 메시지 <strong>${formatNumber(s.calendarTotalMessages)}</strong>건<span class="gh-contrib-span">${escapeHtml(s.calendarSpanLabel)}</span></p>`
73
73
  : `<p class="gh-contrib-summary">이 기간 활동 없음<span class="gh-contrib-span">${escapeHtml(s.calendarSpanLabel)}</span></p>`;
74
- return `<div class="gh-contrib">
74
+ const compactClass = weekCount <= 14 ? " gh-contrib--compact" : "";
75
+ return `<div class="gh-contrib${compactClass}">
75
76
  <div class="gh-cal-tooltip" data-gh-tip hidden><span data-gh-tip-text></span></div>
76
77
  ${summary}
77
78
  <div class="gh-cal-scroll">
@@ -140,8 +141,10 @@ export function renderStorySections(data) {
140
141
  </section>`);
141
142
  }
142
143
  if (s.calendarWeeks.length > 0) {
144
+ const calWeeks = s.calendarWeeks.length;
145
+ const calTitle = calWeeks <= 14 ? "활동 기간 그리드" : "연간 활동 그리드";
143
146
  parts.push(`<section id="s-calendar" class="anim-enter" style="margin-bottom:14px;--enter-delay:0.05s">
144
- <h2 style="margin:0 0 6px;font-size:20px;font-weight:800;letter-spacing:-0.02em">연간 활동 그리드</h2>
147
+ <h2 style="margin:0 0 6px;font-size:20px;font-weight:800;letter-spacing:-0.02em">${calTitle}</h2>
145
148
  <p class="chart-hint" style="margin-bottom:12px">GitHub 프로필 <strong>Contributions</strong>와 같은 레이아웃·색 단계예요. 셀에 마우스를 올리거나 탭하면 날짜와 건수가 표시됩니다.</p>
146
149
  ${renderGitHubCalendar(data)}
147
150
  </section>`);
@@ -1 +1 @@
1
- {"version":3,"file":"report-story.js","sourceRoot":"","sources":["../../src/report-story.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"report-story.js","sourceRoot":"","sources":["../../src/report-story.ts"],"names":[],"mappings":"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"}