@heripo/research-radar 1.1.0 → 1.2.1

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.
package/NOTICE CHANGED
@@ -48,7 +48,7 @@ Example implementations are welcome to use this code, but should establish
48
48
  their own brand identity.
49
49
 
50
50
  For permission to use the "heripo" trademark, contact the project maintainer
51
- via GitHub: https://github.com/kimhongyeon/heripo-research-radar/issues
51
+ via GitHub: https://github.com/heripo-lab/heripo-research-radar/issues
52
52
 
53
53
  ===============================================================================
54
54
 
package/README.md CHANGED
@@ -1,19 +1,19 @@
1
- # Heripo Research Radar
1
+ # heripo Research Radar
2
2
 
3
3
  English | [한국어](./README-ko.md)
4
4
 
5
- [![CI](https://github.com/kimhongyeon/heripo-research-radar/actions/workflows/ci.yml/badge.svg)](https://github.com/kimhongyeon/heripo-research-radar/actions/workflows/ci.yml)
5
+ [![CI](https://github.com/heripo-lab/heripo-research-radar/actions/workflows/ci.yml/badge.svg)](https://github.com/heripo-lab/heripo-research-radar/actions/workflows/ci.yml)
6
6
  [
7
7
  ![npm version](https://img.shields.io/npm/v/%40heripo%2Fresearch-radar?logo=npm&color=cb0000)
8
8
  ](https://www.npmjs.com/package/@heripo/research-radar)
9
- ![license](https://img.shields.io/github/license/kimhongyeon/heripo-research-radar)
9
+ ![license](https://img.shields.io/github/license/heripo-lab/heripo-research-radar)
10
10
  ![node](https://img.shields.io/badge/node-%3E%3D22-brightgreen)
11
11
 
12
12
  [Code of Conduct](./CODE_OF_CONDUCT.md) • [Security Policy](./SECURITY.md) • [Contributing](./CONTRIBUTING.md)
13
13
 
14
14
  ## What is this?
15
15
 
16
- An AI-powered newsletter service for Korean cultural heritage. Built on [`@llm-newsletter-kit/core`](https://github.com/kimhongyeon/llm-newsletter-kit-core), it's both a production service ([live at heripo.com](https://heripo.com/research-radar/subscribe)) and a reference implementation showing how to build automated newsletters with LLMs.
16
+ An AI-powered newsletter service for Korean cultural heritage. Built on [`@llm-newsletter-kit/core`](https://github.com/heripo-lab/llm-newsletter-kit-core), it's both a production service ([live at heripo.com](https://heripo.com/research-radar/subscribe)) and a reference implementation showing how to build automated newsletters with LLMs.
17
17
 
18
18
  **Production metrics**:
19
19
  - **Cost**: $0.2-1 USD per issue
@@ -23,11 +23,11 @@ An AI-powered newsletter service for Korean cultural heritage. Built on [`@llm-n
23
23
  **Technical highlights**:
24
24
  - Type-safe TypeScript with strict interfaces
25
25
  - Provider pattern for swapping components (Crawling/Analysis/Content/Email)
26
- - 62 crawling targets across heritage agencies, museums, academic societies
26
+ - 66 crawling targets across heritage agencies, museums, academic societies
27
27
  - LLM-driven analysis (GPT-5 models)
28
28
  - Built-in retries, chain options, preview emails
29
29
 
30
- **Links**: [Live service](https://heripo.com/research-radar/subscribe) • [Newsletter example](https://heripo.com/research-radar-newsletter-example.html) • [Core engine](https://github.com/kimhongyeon/llm-newsletter-kit-core)
30
+ **Links**: [Live service](https://heripo.com/research-radar/subscribe) • [Newsletter example](https://heripo.com/research-radar-newsletter-example.html) • [Core engine](https://github.com/heripo-lab/llm-newsletter-kit-core)
31
31
 
32
32
  ## Background
33
33
 
@@ -54,11 +54,11 @@ We recommend adding this notice to your newsletter template footer or service do
54
54
  For academic publications:
55
55
 
56
56
  ```bibtex
57
- @software{llm_newsletter_kit,
57
+ @software{heripo research radar,
58
58
  author = {Kim, Hongyeon},
59
- title = {LLM Newsletter Kit: AI-Powered Newsletter Automation Framework},
59
+ title = {heripo research radar},
60
60
  year = {2025},
61
- url = {https://github.com/kimhongyeon/heripo-research-radar},
61
+ url = {https://github.com/heripo-lab/heripo-research-radar},
62
62
  note = {Apache License 2.0}
63
63
  }
64
64
  ```
@@ -125,13 +125,13 @@ const newsletterId = await generateNewsletter({
125
125
  3. **Generation**: Create newsletter from top-scoring articles
126
126
  4. **Save**: Store and optionally send preview email
127
127
 
128
- Uses the **Provider-Service pattern** from `@llm-newsletter-kit/core`. See [core docs](https://github.com/kimhongyeon/llm-newsletter-kit-core#architecture--flow) for flow diagrams.
128
+ Uses the **Provider-Service pattern** from `@llm-newsletter-kit/core`. See [core docs](https://github.com/heripo-lab/llm-newsletter-kit-core#architecture--flow) for flow diagrams.
129
129
 
130
130
  ## Components
131
131
 
132
132
  **Config** (`src/config/`): Brand, language, LLM settings
133
133
 
134
- **Targets** (`src/config/crawling-targets.ts`): 62 sources (News 49, Business 4, Employment 9)
134
+ **Targets** (`src/config/crawling-targets.ts`): 66 sources (News 52, Business 4, Employment 10)
135
135
 
136
136
  **Parsers** (`src/parsers/`): Custom extractors per organization
137
137
 
@@ -152,6 +152,21 @@ npm run typecheck # TypeScript type-check
152
152
  npm run format # Prettier formatting
153
153
  ```
154
154
 
155
+ ### Crawler Debugger
156
+
157
+ A web-based tool for testing crawling parsers during development. Built with Express.js and vanilla HTML/CSS/JS to minimize dependencies.
158
+
159
+ ```bash
160
+ npm run dev:crawler # Start at http://localhost:3333
161
+ ```
162
+
163
+ **Features**:
164
+ - Test `parseList()` and `parseDetail()` parsers via web UI
165
+ - View raw HTML source for debugging
166
+ - Copy parsed results as JSON
167
+ - 5-minute response cache (with skip/clear options)
168
+ - Timing info for fetch and parse operations
169
+
155
170
  ## 🤝 Contributing
156
171
 
157
172
  You can use this project in two ways:
@@ -212,5 +227,5 @@ Code-based automation delivers **superior output quality** through advanced AI t
212
227
 
213
228
  ## Related Projects
214
229
 
215
- - [`@llm-newsletter-kit/core`](https://github.com/kimhongyeon/llm-newsletter-kit-core) — Domain-agnostic newsletter engine
230
+ - [`@llm-newsletter-kit/core`](https://github.com/heripo-lab/llm-newsletter-kit-core) — Domain-agnostic newsletter engine
216
231
  - [Archaeological Informatization Using LLMs](https://poc.heripo.com) — Academic research (Korean)
package/dist/index.cjs CHANGED
@@ -970,6 +970,135 @@ function getUniqIdFromNrichMajorEvent(element) {
970
970
  return ((element.attr('onclick') ?? '').match(/fnViewPage\('(.*)'\)/)?.[1] ?? '');
971
971
  }
972
972
 
973
+ const LIST_API_URL = 'http://www.yngogo.or.kr/module/ntt/unity/selectNttListAjax.ink';
974
+ const DETAIL_API_URL = 'http://www.yngogo.or.kr/module/ntt/unity/selectNttDetailAjax.ink';
975
+ const BASE_URL = 'http://www.yngogo.or.kr';
976
+ // User-Agent list used by real browsers
977
+ const USER_AGENTS = [
978
+ // Windows - Chrome, Edge, Firefox
979
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
980
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0',
981
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0',
982
+ // macOS - Chrome, Safari, Firefox
983
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
984
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Safari/605.1.15',
985
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:126.0) Gecko/20100101 Firefox/126.0',
986
+ // Linux - Chrome, Firefox
987
+ 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
988
+ 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:126.0) Gecko/20100101 Firefox/126.0',
989
+ // Additional common combinations
990
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
991
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
992
+ ];
993
+ // Pick a random User-Agent
994
+ const getRandomUserAgent = () => USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)];
995
+ /**
996
+ * Parse list page from 영남고고학회 (Yeongnam Archaeological Society)
997
+ * Uses internal API since the table is rendered via CSR
998
+ * @see https://www.yngogo.or.kr
999
+ */
1000
+ const parseYngogoList = async (_html, menuSeq, bbsSeq, sitecntntsSeq) => {
1001
+ // Fetch from internal API (CSR workaround)
1002
+ const response = await fetch(LIST_API_URL, {
1003
+ method: 'POST',
1004
+ headers: {
1005
+ 'Content-Type': 'application/x-www-form-urlencoded',
1006
+ 'User-Agent': getRandomUserAgent(),
1007
+ },
1008
+ body: new URLSearchParams({
1009
+ siteSeq: '32000001030',
1010
+ bbsSeq,
1011
+ pageIndex: '1',
1012
+ menuSeq,
1013
+ pageMode: 'B',
1014
+ sitecntntsSeq,
1015
+ tabTyCode: 'dataManage',
1016
+ mngrAt: 'N',
1017
+ searchCondition: '',
1018
+ searchKeyword: '',
1019
+ nttSeq: '',
1020
+ }),
1021
+ });
1022
+ const html = await response.text();
1023
+ const $ = cheerio__namespace.load(html);
1024
+ const posts = [];
1025
+ $('.basic-table01 tr').each((_index, element) => {
1026
+ const columns = $(element).find('td');
1027
+ if (columns.length === 0) {
1028
+ return;
1029
+ }
1030
+ const titleElement = columns.eq(1).find('a');
1031
+ const uniqId = getUniqId(titleElement);
1032
+ const detailUrl = `${BASE_URL}/subList/${menuSeq}?pmode=detail&nttSeq=${uniqId}&bbsSeq=${bbsSeq}&sitecntntsSeq=${sitecntntsSeq}`;
1033
+ const title = titleElement.text()?.trim() ?? '';
1034
+ const date = getDate(columns.eq(3).text().trim());
1035
+ posts.push({
1036
+ uniqId,
1037
+ title,
1038
+ date,
1039
+ detailUrl: cleanUrl(detailUrl),
1040
+ dateType: core.DateType.REGISTERED,
1041
+ });
1042
+ });
1043
+ return posts;
1044
+ };
1045
+ /**
1046
+ * Parse detail page from 영남고고학회 (Yeongnam Archaeological Society)
1047
+ * Uses internal API since the detail page is rendered via CSR
1048
+ */
1049
+ const parseYngogoDetail = async (_html, menuSeq, bbsSeq, nttSeq, sitecntntsSeq) => {
1050
+ // Fetch from internal API (CSR workaround)
1051
+ const response = await fetch(DETAIL_API_URL, {
1052
+ method: 'POST',
1053
+ headers: {
1054
+ 'Content-Type': 'application/x-www-form-urlencoded',
1055
+ 'User-Agent': getRandomUserAgent(),
1056
+ },
1057
+ body: new URLSearchParams({
1058
+ siteSeq: '32000001030',
1059
+ bbsSeq,
1060
+ nttSeq,
1061
+ pageIndex: '1',
1062
+ ordrSe: 'D',
1063
+ searchCnd: 'frstRegistPnttm',
1064
+ checkNttSeq: '',
1065
+ menuSeq,
1066
+ mngrAt: 'N',
1067
+ parntsNttSeq: '',
1068
+ secretAt: '',
1069
+ searchAt: '',
1070
+ sitecntntsSeq,
1071
+ cmntUseAt: 'N',
1072
+ atchFilePosblAt: 'Y',
1073
+ atchFilePosblCo: '3',
1074
+ listCount: '10',
1075
+ searchCondition: '1',
1076
+ searchKeyword: '',
1077
+ }),
1078
+ });
1079
+ const html = await response.text();
1080
+ const $ = cheerio__namespace.load(html);
1081
+ const content = $('.conM_txt');
1082
+ return {
1083
+ detailContent: new TurndownService().turndown(content.html() ?? ''),
1084
+ hasAttachedFile: $('#atchFile_div').length > 0,
1085
+ hasAttachedImage: content.find('img').length > 0,
1086
+ };
1087
+ };
1088
+ function getUniqId(element) {
1089
+ // fnView('1005200642', 'admin', '', '',''); - extract first param
1090
+ return (element.attr('onclick') ?? '').match(/fnView\('([^']*)'/)?.[1] ?? '';
1091
+ }
1092
+ /**
1093
+ * Extract nttSeq from CSR page HTML
1094
+ * The URL query parameter is embedded in the page script
1095
+ */
1096
+ function extractNttSeq(html) {
1097
+ // Pattern: nttSeq=1005200644 or nttSeq='1005200644'
1098
+ const match = html.match(/nttSeq[=:]['"]?(\d+)/);
1099
+ return match?.[1] ?? '';
1100
+ }
1101
+
973
1102
  const crawlingTargetGroups = [
974
1103
  {
975
1104
  id: 'news',
@@ -1200,6 +1329,27 @@ const crawlingTargetGroups = [
1200
1329
  parseList: parseHsasList,
1201
1330
  parseDetail: parseHsasDetail,
1202
1331
  },
1332
+ {
1333
+ id: '영남고고학회_공지사항',
1334
+ name: '영남고고학회 공지사항',
1335
+ url: 'http://www.yngogo.or.kr/subList/32000001120',
1336
+ parseList: (html) => parseYngogoList(html, '32000001120', '32000001157', '32000001711'),
1337
+ parseDetail: (html) => parseYngogoDetail(html, '32000001120', '32000001157', extractNttSeq(html), '32000001711'),
1338
+ },
1339
+ {
1340
+ id: '영남고고학회_학계소식',
1341
+ name: '영남고고학회 학계소식',
1342
+ url: 'http://www.yngogo.or.kr/subList/32000001133',
1343
+ parseList: (html) => parseYngogoList(html, '32000001133', '32000001161', '32000001715'),
1344
+ parseDetail: (html) => parseYngogoDetail(html, '32000001133', '32000001161', extractNttSeq(html), '32000001715'),
1345
+ },
1346
+ {
1347
+ id: '영남고고학회_현장소식',
1348
+ name: '영남고고학회 현장소식',
1349
+ url: 'http://www.yngogo.or.kr/subList/32000001135',
1350
+ parseList: (html) => parseYngogoList(html, '32000001135', '32000001163', '32000001717'),
1351
+ parseDetail: (html) => parseYngogoDetail(html, '32000001135', '32000001163', extractNttSeq(html), '32000001717'),
1352
+ },
1203
1353
  {
1204
1354
  id: '국립중앙박물관_알림',
1205
1355
  name: '국립중앙박물관 알림',
@@ -1385,6 +1535,13 @@ const crawlingTargetGroups = [
1385
1535
  parseList: parseKaahList,
1386
1536
  parseDetail: parseKaahDetail,
1387
1537
  },
1538
+ {
1539
+ id: '영남고고학회_채용공고',
1540
+ name: '영남고고학회 채용공고',
1541
+ url: 'http://www.yngogo.or.kr/subList/32000001136',
1542
+ parseList: (html) => parseYngogoList(html, '32000001136', '32000001164', '32000001718'),
1543
+ parseDetail: (html) => parseYngogoDetail(html, '32000001136', '32000001164', extractNttSeq(html), '32000001718'),
1544
+ },
1388
1545
  {
1389
1546
  id: '국립중앙박물관_채용안내',
1390
1547
  name: '국립중앙박물관 채용 안내',
@@ -2027,7 +2184,7 @@ const createNewsletterHtmlTemplate = (targets) => `<!DOCTYPE html>
2027
2184
  <p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.7; color: #444444; margin: 0 0 18px 0;">이 뉴스레터는 heripo의 선공개 버전으로 플랫폼의 일부 기능 중 하나입니다.</p>
2028
2185
  <p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.7; color: #444444; margin: 0 0 18px 0;">2026년 중 플랫폼 출시를 목표로 개발 중이며, 핵심 로직 또한 오픈소스 프로젝트로 공개할 예정입니다.</p>
2029
2186
  <p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.7; color: #444444; margin: 0 0 18px 0;">플랫폼 프로토타입 출시 시 구독자분들께 우선 안내해 드리겠습니다.</p>
2030
- <p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.7; color: #444444; margin: 0 0 18px 0;">뉴스레터 소스 추가를 원하시거나 기타 궁금한 점이 있다면 <a href="https://github.com/kimhongyeon/heripo-research-radar/issues" target="_blank">GitHub 이슈</a>를 통해 요청해 주세요.</p>
2187
+ <p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.7; color: #444444; margin: 0 0 18px 0;">뉴스레터 소스 추가를 원하시거나 기타 궁금한 점이 있다면 <a href="https://github.com/heripo-lab/heripo-research-radar/issues" target="_blank">GitHub 이슈</a>를 통해 요청해 주세요.</p>
2031
2188
  <hr style="border: 0; border-top: 2px solid #D2691E; margin: 32px 0;">
2032
2189
  <h2 style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 24px; font-weight: bold; line-height: 1.3; color: #D2691E; margin: 0 0 16px 0; letter-spacing: -0.2px; border-left: 5px solid #D2691E; padding-left: 12px; background: none;">⚠️ 중요 안내</h2>
2033
2190
  <p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.7; color: #444444; margin: 0 0 18px 0;">본 뉴스레터는 국가유산청 공지사항, 관련 기관 입찰 정보 등 특정 웹 게시판의 모든 신규 소식을 빠짐없이 수집하여 제공합니다. 수집된 모든 정보는 정확한 크롤링 로직에 기반하므로 원본과 일치하여 신뢰할 수 있습니다.</p>
@@ -2041,8 +2198,8 @@ const createNewsletterHtmlTemplate = (targets) => `<!DOCTYPE html>
2041
2198
  <p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.7; color: #444444; margin: 0 0 10px 0;" class="footer-text">이 메일은 heripo.com에서 리서치 레이더를 구독하신 분들에게 발송됩니다.<br>
2042
2199
  더 이상 이메일을 받고 싶지 않으시면 <a href="{{{RESEND_UNSUBSCRIBE_URL}}}" target="_blank" style="-webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; font-weight: bold; transition: color 0.2s; color: #888888; text-decoration: underline;" class="footer-link">여기에서 수신 거부</a>하세요.</p>
2043
2200
  <p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 1.5; color: #999999; margin: 0;" class="footer-text">
2044
- Powered by <a href="https://github.com/kimhongyeon/llm-newsletter-kit-core" target="_blank" style="-webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; transition: color 0.2s; color: #999999; text-decoration: underline;" class="footer-link">LLM Newsletter Kit</a> ·
2045
- <a href="https://github.com/kimhongyeon/heripo-research-radar" target="_blank" style="-webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; transition: color 0.2s; color: #999999; text-decoration: underline;" class="footer-link">View Source</a>
2201
+ Powered by <a href="https://github.com/heripo-lab/llm-newsletter-kit-core" target="_blank" style="-webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; transition: color 0.2s; color: #999999; text-decoration: underline;" class="footer-link">LLM Newsletter Kit</a> ·
2202
+ <a href="https://github.com/heripo-lab/heripo-research-radar" target="_blank" style="-webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; transition: color 0.2s; color: #999999; text-decoration: underline;" class="footer-link">View Source</a>
2046
2203
  </p>
2047
2204
  </td>
2048
2205
  </tr>
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/index.js CHANGED
@@ -949,6 +949,135 @@ function getUniqIdFromNrichMajorEvent(element) {
949
949
  return ((element.attr('onclick') ?? '').match(/fnViewPage\('(.*)'\)/)?.[1] ?? '');
950
950
  }
951
951
 
952
+ const LIST_API_URL = 'http://www.yngogo.or.kr/module/ntt/unity/selectNttListAjax.ink';
953
+ const DETAIL_API_URL = 'http://www.yngogo.or.kr/module/ntt/unity/selectNttDetailAjax.ink';
954
+ const BASE_URL = 'http://www.yngogo.or.kr';
955
+ // User-Agent list used by real browsers
956
+ const USER_AGENTS = [
957
+ // Windows - Chrome, Edge, Firefox
958
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
959
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0',
960
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0',
961
+ // macOS - Chrome, Safari, Firefox
962
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
963
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Safari/605.1.15',
964
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:126.0) Gecko/20100101 Firefox/126.0',
965
+ // Linux - Chrome, Firefox
966
+ 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
967
+ 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:126.0) Gecko/20100101 Firefox/126.0',
968
+ // Additional common combinations
969
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
970
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
971
+ ];
972
+ // Pick a random User-Agent
973
+ const getRandomUserAgent = () => USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)];
974
+ /**
975
+ * Parse list page from 영남고고학회 (Yeongnam Archaeological Society)
976
+ * Uses internal API since the table is rendered via CSR
977
+ * @see https://www.yngogo.or.kr
978
+ */
979
+ const parseYngogoList = async (_html, menuSeq, bbsSeq, sitecntntsSeq) => {
980
+ // Fetch from internal API (CSR workaround)
981
+ const response = await fetch(LIST_API_URL, {
982
+ method: 'POST',
983
+ headers: {
984
+ 'Content-Type': 'application/x-www-form-urlencoded',
985
+ 'User-Agent': getRandomUserAgent(),
986
+ },
987
+ body: new URLSearchParams({
988
+ siteSeq: '32000001030',
989
+ bbsSeq,
990
+ pageIndex: '1',
991
+ menuSeq,
992
+ pageMode: 'B',
993
+ sitecntntsSeq,
994
+ tabTyCode: 'dataManage',
995
+ mngrAt: 'N',
996
+ searchCondition: '',
997
+ searchKeyword: '',
998
+ nttSeq: '',
999
+ }),
1000
+ });
1001
+ const html = await response.text();
1002
+ const $ = cheerio.load(html);
1003
+ const posts = [];
1004
+ $('.basic-table01 tr').each((_index, element) => {
1005
+ const columns = $(element).find('td');
1006
+ if (columns.length === 0) {
1007
+ return;
1008
+ }
1009
+ const titleElement = columns.eq(1).find('a');
1010
+ const uniqId = getUniqId(titleElement);
1011
+ const detailUrl = `${BASE_URL}/subList/${menuSeq}?pmode=detail&nttSeq=${uniqId}&bbsSeq=${bbsSeq}&sitecntntsSeq=${sitecntntsSeq}`;
1012
+ const title = titleElement.text()?.trim() ?? '';
1013
+ const date = getDate(columns.eq(3).text().trim());
1014
+ posts.push({
1015
+ uniqId,
1016
+ title,
1017
+ date,
1018
+ detailUrl: cleanUrl(detailUrl),
1019
+ dateType: DateType.REGISTERED,
1020
+ });
1021
+ });
1022
+ return posts;
1023
+ };
1024
+ /**
1025
+ * Parse detail page from 영남고고학회 (Yeongnam Archaeological Society)
1026
+ * Uses internal API since the detail page is rendered via CSR
1027
+ */
1028
+ const parseYngogoDetail = async (_html, menuSeq, bbsSeq, nttSeq, sitecntntsSeq) => {
1029
+ // Fetch from internal API (CSR workaround)
1030
+ const response = await fetch(DETAIL_API_URL, {
1031
+ method: 'POST',
1032
+ headers: {
1033
+ 'Content-Type': 'application/x-www-form-urlencoded',
1034
+ 'User-Agent': getRandomUserAgent(),
1035
+ },
1036
+ body: new URLSearchParams({
1037
+ siteSeq: '32000001030',
1038
+ bbsSeq,
1039
+ nttSeq,
1040
+ pageIndex: '1',
1041
+ ordrSe: 'D',
1042
+ searchCnd: 'frstRegistPnttm',
1043
+ checkNttSeq: '',
1044
+ menuSeq,
1045
+ mngrAt: 'N',
1046
+ parntsNttSeq: '',
1047
+ secretAt: '',
1048
+ searchAt: '',
1049
+ sitecntntsSeq,
1050
+ cmntUseAt: 'N',
1051
+ atchFilePosblAt: 'Y',
1052
+ atchFilePosblCo: '3',
1053
+ listCount: '10',
1054
+ searchCondition: '1',
1055
+ searchKeyword: '',
1056
+ }),
1057
+ });
1058
+ const html = await response.text();
1059
+ const $ = cheerio.load(html);
1060
+ const content = $('.conM_txt');
1061
+ return {
1062
+ detailContent: new TurndownService().turndown(content.html() ?? ''),
1063
+ hasAttachedFile: $('#atchFile_div').length > 0,
1064
+ hasAttachedImage: content.find('img').length > 0,
1065
+ };
1066
+ };
1067
+ function getUniqId(element) {
1068
+ // fnView('1005200642', 'admin', '', '',''); - extract first param
1069
+ return (element.attr('onclick') ?? '').match(/fnView\('([^']*)'/)?.[1] ?? '';
1070
+ }
1071
+ /**
1072
+ * Extract nttSeq from CSR page HTML
1073
+ * The URL query parameter is embedded in the page script
1074
+ */
1075
+ function extractNttSeq(html) {
1076
+ // Pattern: nttSeq=1005200644 or nttSeq='1005200644'
1077
+ const match = html.match(/nttSeq[=:]['"]?(\d+)/);
1078
+ return match?.[1] ?? '';
1079
+ }
1080
+
952
1081
  const crawlingTargetGroups = [
953
1082
  {
954
1083
  id: 'news',
@@ -1179,6 +1308,27 @@ const crawlingTargetGroups = [
1179
1308
  parseList: parseHsasList,
1180
1309
  parseDetail: parseHsasDetail,
1181
1310
  },
1311
+ {
1312
+ id: '영남고고학회_공지사항',
1313
+ name: '영남고고학회 공지사항',
1314
+ url: 'http://www.yngogo.or.kr/subList/32000001120',
1315
+ parseList: (html) => parseYngogoList(html, '32000001120', '32000001157', '32000001711'),
1316
+ parseDetail: (html) => parseYngogoDetail(html, '32000001120', '32000001157', extractNttSeq(html), '32000001711'),
1317
+ },
1318
+ {
1319
+ id: '영남고고학회_학계소식',
1320
+ name: '영남고고학회 학계소식',
1321
+ url: 'http://www.yngogo.or.kr/subList/32000001133',
1322
+ parseList: (html) => parseYngogoList(html, '32000001133', '32000001161', '32000001715'),
1323
+ parseDetail: (html) => parseYngogoDetail(html, '32000001133', '32000001161', extractNttSeq(html), '32000001715'),
1324
+ },
1325
+ {
1326
+ id: '영남고고학회_현장소식',
1327
+ name: '영남고고학회 현장소식',
1328
+ url: 'http://www.yngogo.or.kr/subList/32000001135',
1329
+ parseList: (html) => parseYngogoList(html, '32000001135', '32000001163', '32000001717'),
1330
+ parseDetail: (html) => parseYngogoDetail(html, '32000001135', '32000001163', extractNttSeq(html), '32000001717'),
1331
+ },
1182
1332
  {
1183
1333
  id: '국립중앙박물관_알림',
1184
1334
  name: '국립중앙박물관 알림',
@@ -1364,6 +1514,13 @@ const crawlingTargetGroups = [
1364
1514
  parseList: parseKaahList,
1365
1515
  parseDetail: parseKaahDetail,
1366
1516
  },
1517
+ {
1518
+ id: '영남고고학회_채용공고',
1519
+ name: '영남고고학회 채용공고',
1520
+ url: 'http://www.yngogo.or.kr/subList/32000001136',
1521
+ parseList: (html) => parseYngogoList(html, '32000001136', '32000001164', '32000001718'),
1522
+ parseDetail: (html) => parseYngogoDetail(html, '32000001136', '32000001164', extractNttSeq(html), '32000001718'),
1523
+ },
1367
1524
  {
1368
1525
  id: '국립중앙박물관_채용안내',
1369
1526
  name: '국립중앙박물관 채용 안내',
@@ -2006,7 +2163,7 @@ const createNewsletterHtmlTemplate = (targets) => `<!DOCTYPE html>
2006
2163
  <p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.7; color: #444444; margin: 0 0 18px 0;">이 뉴스레터는 heripo의 선공개 버전으로 플랫폼의 일부 기능 중 하나입니다.</p>
2007
2164
  <p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.7; color: #444444; margin: 0 0 18px 0;">2026년 중 플랫폼 출시를 목표로 개발 중이며, 핵심 로직 또한 오픈소스 프로젝트로 공개할 예정입니다.</p>
2008
2165
  <p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.7; color: #444444; margin: 0 0 18px 0;">플랫폼 프로토타입 출시 시 구독자분들께 우선 안내해 드리겠습니다.</p>
2009
- <p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.7; color: #444444; margin: 0 0 18px 0;">뉴스레터 소스 추가를 원하시거나 기타 궁금한 점이 있다면 <a href="https://github.com/kimhongyeon/heripo-research-radar/issues" target="_blank">GitHub 이슈</a>를 통해 요청해 주세요.</p>
2166
+ <p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.7; color: #444444; margin: 0 0 18px 0;">뉴스레터 소스 추가를 원하시거나 기타 궁금한 점이 있다면 <a href="https://github.com/heripo-lab/heripo-research-radar/issues" target="_blank">GitHub 이슈</a>를 통해 요청해 주세요.</p>
2010
2167
  <hr style="border: 0; border-top: 2px solid #D2691E; margin: 32px 0;">
2011
2168
  <h2 style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 24px; font-weight: bold; line-height: 1.3; color: #D2691E; margin: 0 0 16px 0; letter-spacing: -0.2px; border-left: 5px solid #D2691E; padding-left: 12px; background: none;">⚠️ 중요 안내</h2>
2012
2169
  <p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.7; color: #444444; margin: 0 0 18px 0;">본 뉴스레터는 국가유산청 공지사항, 관련 기관 입찰 정보 등 특정 웹 게시판의 모든 신규 소식을 빠짐없이 수집하여 제공합니다. 수집된 모든 정보는 정확한 크롤링 로직에 기반하므로 원본과 일치하여 신뢰할 수 있습니다.</p>
@@ -2020,8 +2177,8 @@ const createNewsletterHtmlTemplate = (targets) => `<!DOCTYPE html>
2020
2177
  <p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.7; color: #444444; margin: 0 0 10px 0;" class="footer-text">이 메일은 heripo.com에서 리서치 레이더를 구독하신 분들에게 발송됩니다.<br>
2021
2178
  더 이상 이메일을 받고 싶지 않으시면 <a href="{{{RESEND_UNSUBSCRIBE_URL}}}" target="_blank" style="-webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; font-weight: bold; transition: color 0.2s; color: #888888; text-decoration: underline;" class="footer-link">여기에서 수신 거부</a>하세요.</p>
2022
2179
  <p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 1.5; color: #999999; margin: 0;" class="footer-text">
2023
- Powered by <a href="https://github.com/kimhongyeon/llm-newsletter-kit-core" target="_blank" style="-webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; transition: color 0.2s; color: #999999; text-decoration: underline;" class="footer-link">LLM Newsletter Kit</a> ·
2024
- <a href="https://github.com/kimhongyeon/heripo-research-radar" target="_blank" style="-webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; transition: color 0.2s; color: #999999; text-decoration: underline;" class="footer-link">View Source</a>
2180
+ Powered by <a href="https://github.com/heripo-lab/llm-newsletter-kit-core" target="_blank" style="-webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; transition: color 0.2s; color: #999999; text-decoration: underline;" class="footer-link">LLM Newsletter Kit</a> ·
2181
+ <a href="https://github.com/heripo-lab/heripo-research-radar" target="_blank" style="-webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; transition: color 0.2s; color: #999999; text-decoration: underline;" class="footer-link">View Source</a>
2025
2182
  </p>
2026
2183
  </td>
2027
2184
  </tr>
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@heripo/research-radar",
3
3
  "private": false,
4
4
  "type": "module",
5
- "version": "1.1.0",
5
+ "version": "1.2.1",
6
6
  "description": "AI-driven intelligence for Korean cultural heritage. This package serves as both a ready-to-use newsletter service and a practical implementation example for the LLM-Newsletter-Kit.",
7
7
  "main": "dist/index.cjs",
8
8
  "module": "dist/index.js",
@@ -36,7 +36,8 @@
36
36
  "lint:fix": "eslint --fix ./src",
37
37
  "lint:ci": "eslint --quiet ./src",
38
38
  "typecheck": "tsc --noEmit",
39
- "format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css,md,mdx}\""
39
+ "format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,css,md,mdx}\"",
40
+ "dev:crawler": "tsx watch dev-tools/crawler-debugger/server.ts"
40
41
  },
41
42
  "author": "kimhongyeon",
42
43
  "license": "Apache-2.0",
@@ -52,24 +53,27 @@
52
53
  "@eslint/js": "^9.39.2",
53
54
  "@llm-newsletter-kit/core": "^1.1.0",
54
55
  "@trivago/prettier-plugin-sort-imports": "^6.0.1",
56
+ "@types/express": "^5.0.6",
55
57
  "@types/node": "^25.0.3",
56
58
  "@types/turndown": "^5.0.6",
57
59
  "eslint": "^9.39.2",
58
60
  "eslint-plugin-unused-imports": "^4.3.0",
61
+ "express": "^5.2.1",
59
62
  "prettier": "^3.7.4",
60
63
  "rimraf": "^6.1.2",
61
64
  "rollup": "^4.55.1",
62
65
  "rollup-plugin-dts": "^6.3.0",
63
66
  "rollup-plugin-typescript2": "^0.36.0",
67
+ "tsx": "^4.21.0",
64
68
  "typescript": "^5.9.3",
65
69
  "typescript-eslint": "^8.52.0"
66
70
  },
67
71
  "repository": {
68
72
  "type": "git",
69
- "url": "https://github.com/kimhongyeon/heripo-research-radar"
73
+ "url": "https://github.com/heripo-lab/heripo-research-radar"
70
74
  },
71
75
  "bugs": {
72
- "url": "https://github.com/kimhongyeon/heripo-research-radar/issues"
76
+ "url": "https://github.com/heripo-lab/heripo-research-radar/issues"
73
77
  },
74
78
  "homepage": "https://heripo.com",
75
79
  "keywords": [