@zonuexe/techbook-mcp 0.1.0 → 0.2.0

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.
Files changed (122) hide show
  1. package/.claude/settings.local.json +13 -1
  2. package/.codex/skills/techbook-mcp-release-prep/SKILL.md +105 -0
  3. package/.github/workflows/test.yml +36 -0
  4. package/.oxlintrc.json +12 -0
  5. package/AGENTS.md +29 -1
  6. package/CHANGELOG.md +27 -0
  7. package/deno.json +3 -0
  8. package/dist/adapters/html/cheerio-parser.d.ts.map +1 -1
  9. package/dist/adapters/html/cheerio-parser.js.map +1 -1
  10. package/dist/adapters/publishers/base.d.ts +22 -1
  11. package/dist/adapters/publishers/base.d.ts.map +1 -1
  12. package/dist/adapters/publishers/base.js +142 -2
  13. package/dist/adapters/publishers/base.js.map +1 -1
  14. package/dist/adapters/publishers/book-tech.d.ts +3 -0
  15. package/dist/adapters/publishers/book-tech.d.ts.map +1 -0
  16. package/dist/adapters/publishers/book-tech.js +95 -0
  17. package/dist/adapters/publishers/book-tech.js.map +1 -0
  18. package/dist/adapters/publishers/born-digital.d.ts +3 -0
  19. package/dist/adapters/publishers/born-digital.d.ts.map +1 -0
  20. package/dist/adapters/publishers/born-digital.js +122 -0
  21. package/dist/adapters/publishers/born-digital.js.map +1 -0
  22. package/dist/adapters/publishers/coronasha.d.ts +3 -0
  23. package/dist/adapters/publishers/coronasha.d.ts.map +1 -0
  24. package/dist/adapters/publishers/coronasha.js +119 -0
  25. package/dist/adapters/publishers/coronasha.js.map +1 -0
  26. package/dist/adapters/publishers/impress.d.ts +3 -0
  27. package/dist/adapters/publishers/impress.d.ts.map +1 -0
  28. package/dist/adapters/publishers/impress.js +92 -0
  29. package/dist/adapters/publishers/impress.js.map +1 -0
  30. package/dist/adapters/publishers/manatee.d.ts +3 -0
  31. package/dist/adapters/publishers/manatee.d.ts.map +1 -0
  32. package/dist/adapters/publishers/manatee.js +93 -0
  33. package/dist/adapters/publishers/manatee.js.map +1 -0
  34. package/dist/adapters/publishers/maruzen-publishing.d.ts +3 -0
  35. package/dist/adapters/publishers/maruzen-publishing.d.ts.map +1 -0
  36. package/dist/adapters/publishers/maruzen-publishing.js +108 -0
  37. package/dist/adapters/publishers/maruzen-publishing.js.map +1 -0
  38. package/dist/adapters/publishers/optronics.d.ts +3 -0
  39. package/dist/adapters/publishers/optronics.d.ts.map +1 -0
  40. package/dist/adapters/publishers/optronics.js +92 -0
  41. package/dist/adapters/publishers/optronics.js.map +1 -0
  42. package/dist/adapters/publishers/oreilly-japan.d.ts +3 -0
  43. package/dist/adapters/publishers/oreilly-japan.d.ts.map +1 -0
  44. package/dist/adapters/publishers/oreilly-japan.js +112 -0
  45. package/dist/adapters/publishers/oreilly-japan.js.map +1 -0
  46. package/dist/adapters/publishers/peaks.d.ts +3 -0
  47. package/dist/adapters/publishers/peaks.d.ts.map +1 -0
  48. package/dist/adapters/publishers/peaks.js +80 -0
  49. package/dist/adapters/publishers/peaks.js.map +1 -0
  50. package/dist/adapters/publishers/personal-media.d.ts +3 -0
  51. package/dist/adapters/publishers/personal-media.d.ts.map +1 -0
  52. package/dist/adapters/publishers/personal-media.js +144 -0
  53. package/dist/adapters/publishers/personal-media.js.map +1 -0
  54. package/dist/adapters/publishers/registry.d.ts.map +1 -1
  55. package/dist/adapters/publishers/registry.js +26 -0
  56. package/dist/adapters/publishers/registry.js.map +1 -1
  57. package/dist/adapters/publishers/rutles.d.ts +3 -0
  58. package/dist/adapters/publishers/rutles.d.ts.map +1 -0
  59. package/dist/adapters/publishers/rutles.js +128 -0
  60. package/dist/adapters/publishers/rutles.js.map +1 -0
  61. package/dist/adapters/publishers/saiensu.d.ts +3 -0
  62. package/dist/adapters/publishers/saiensu.d.ts.map +1 -0
  63. package/dist/adapters/publishers/saiensu.js +109 -0
  64. package/dist/adapters/publishers/saiensu.js.map +1 -0
  65. package/dist/adapters/publishers/seshop.d.ts +3 -0
  66. package/dist/adapters/publishers/seshop.d.ts.map +1 -0
  67. package/dist/adapters/publishers/seshop.js +98 -0
  68. package/dist/adapters/publishers/seshop.js.map +1 -0
  69. package/dist/application/get-book-detail.d.ts.map +1 -1
  70. package/dist/application/get-book-detail.js +5 -0
  71. package/dist/application/get-book-detail.js.map +1 -1
  72. package/dist/application/search-books.d.ts.map +1 -1
  73. package/dist/application/search-books.js +7 -1
  74. package/dist/application/search-books.js.map +1 -1
  75. package/dist/domain/book.d.ts +5 -4
  76. package/dist/domain/book.d.ts.map +1 -1
  77. package/dist/main.d.ts +1 -0
  78. package/dist/main.js +1 -0
  79. package/dist/main.js.map +1 -1
  80. package/dist/mcp/server.d.ts.map +1 -1
  81. package/dist/mcp/server.js +1 -0
  82. package/dist/mcp/server.js.map +1 -1
  83. package/flake.nix +1 -1
  84. package/package.json +7 -5
  85. package/src/adapters/html/cheerio-parser.ts +4 -3
  86. package/src/adapters/publishers/base.ts +150 -0
  87. package/src/adapters/publishers/born-digital.ts +2 -17
  88. package/src/adapters/publishers/impress.ts +103 -0
  89. package/src/adapters/publishers/manatee.ts +2 -1
  90. package/src/adapters/publishers/maruzen-publishing.ts +4 -16
  91. package/src/adapters/publishers/oreilly-japan.ts +5 -10
  92. package/src/adapters/publishers/registry.ts +2 -0
  93. package/src/adapters/publishers/rutles.ts +1 -13
  94. package/src/adapters/publishers/saiensu.ts +5 -18
  95. package/src/adapters/publishers/seshop.ts +1 -1
  96. package/src/application/get-book-detail.ts +7 -0
  97. package/src/application/search-books.ts +6 -1
  98. package/src/main.ts +1 -0
  99. package/tests/fixtures/impress-detail-epub.html +746 -0
  100. package/tests/fixtures/impress-detail-social.html +689 -0
  101. package/tests/unit/adapters/base.test.ts +441 -0
  102. package/tests/unit/adapters/publishers/book-tech.test.ts +18 -15
  103. package/tests/unit/adapters/publishers/born-digital.test.ts +18 -15
  104. package/tests/unit/adapters/publishers/coronasha.test.ts +26 -20
  105. package/tests/unit/adapters/publishers/gihyo.test.ts +21 -19
  106. package/tests/unit/adapters/publishers/impress.test.ts +129 -0
  107. package/tests/unit/adapters/publishers/lambdanote.test.ts +12 -11
  108. package/tests/unit/adapters/publishers/manatee.test.ts +14 -12
  109. package/tests/unit/adapters/publishers/maruzen-publishing.test.ts +19 -17
  110. package/tests/unit/adapters/publishers/optronics.test.ts +19 -16
  111. package/tests/unit/adapters/publishers/oreilly-japan.test.ts +19 -16
  112. package/tests/unit/adapters/publishers/peaks.test.ts +17 -14
  113. package/tests/unit/adapters/publishers/personal-media.test.ts +18 -15
  114. package/tests/unit/adapters/publishers/rutles.test.ts +15 -12
  115. package/tests/unit/adapters/publishers/saiensu.test.ts +14 -12
  116. package/tests/unit/adapters/publishers/seshop.test.ts +16 -13
  117. package/tests/unit/adapters/publishers/tatsu-zine.test.ts +13 -12
  118. package/tests/unit/adapters/publishers/techbookfest.test.ts +12 -11
  119. package/tests/unit/adapters/registry.test.ts +37 -0
  120. package/tests/unit/application/get-book-detail.test.ts +102 -0
  121. package/tests/unit/application/search-books.test.ts +137 -0
  122. package/vitest.config.ts +0 -8
@@ -0,0 +1,3 @@
1
+ import type { PublisherAdapter } from "../../domain/publisher.js";
2
+ export declare const bornDigitalAdapter: PublisherAdapter;
3
+ //# sourceMappingURL=born-digital.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"born-digital.d.ts","sourceRoot":"","sources":["../../../src/adapters/publishers/born-digital.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,2BAA2B,CAAC;AA4DjF,eAAO,MAAM,kBAAkB,EAAE,gBAkFhC,CAAC"}
@@ -0,0 +1,122 @@
1
+ import { fetchText, parseJapanesePrice, resolveUrl, encodeEucJp, parseJapaneseDateToISO } from "./base.js";
2
+ const BASE_URL = "https://wgn-obs.shop-pro.jp";
3
+ /**
4
+ * 商品説明テキストから著者・出版社・発売日を取得する。
5
+ * 以下の2形式に対応:
6
+ * - "著者\tヘイドン・ピカリング<br />" (タブ区切り)
7
+ * - "著者:太田 良典、中村 直樹<br />" (全角コロン区切り)
8
+ */
9
+ function parseDescription(text) {
10
+ const authors = [];
11
+ let publisher = "ボーンデジタル";
12
+ let publishedAt;
13
+ for (const rawLine of text.split(/\r?\n/)) {
14
+ const line = rawLine.trim();
15
+ const m = line.match(/^(.+?)[\t:]\s*(.+)$/);
16
+ if (!m)
17
+ continue;
18
+ const key = m[1].trim();
19
+ const value = m[2].trim();
20
+ if (key === "著者" || key === "著") {
21
+ authors.push(...value.split(/[、,,]/).map(s => s.trim()).filter(Boolean));
22
+ }
23
+ else if (key === "翻訳" || key === "翻訳者" || key === "訳者" || key === "訳") {
24
+ authors.push(...value.split(/[、,,]/).map(s => s.trim()).filter(Boolean));
25
+ }
26
+ else if (key.startsWith("発行") || key === "発売") {
27
+ publisher = value.replace(/^株式会社\s*/, "").replace(/\s*株式会社$/, "").trim();
28
+ }
29
+ else if (key === "発売日") {
30
+ publishedAt = parseJapaneseDateToISO(value);
31
+ }
32
+ }
33
+ return { authors, publisher, publishedAt };
34
+ }
35
+ /**
36
+ * ページ埋め込みの Colorme JSON から商品情報を取得する。
37
+ * `var Colorme = {...};` 形式。
38
+ */
39
+ function extractColormeProduct(html) {
40
+ const m = html.match(/var Colorme = (\{[^\n]+\});/);
41
+ if (!m)
42
+ return {};
43
+ try {
44
+ const data = JSON.parse(m[1]);
45
+ const price = data.product?.sales_price_including_tax;
46
+ return { price };
47
+ }
48
+ catch {
49
+ return {};
50
+ }
51
+ }
52
+ export const bornDigitalAdapter = {
53
+ id: "born-digital",
54
+ name: "ボーンデジタル",
55
+ baseUrl: BASE_URL,
56
+ async search(query, deps) {
57
+ const word = [query.title, query.author].filter(Boolean).join(" ");
58
+ if (!word)
59
+ return [];
60
+ const url = `${BASE_URL}/?mode=srh&keyword=${encodeEucJp(word)}`;
61
+ const html = await fetchText(url, deps);
62
+ const doc = deps.parser.parse(html);
63
+ const results = [];
64
+ const limit = query.limit ?? 10;
65
+ for (const item of doc.select("li.c-product-list__item")) {
66
+ const titleEl = item.find("a.c-product-list__name")[0];
67
+ const title = titleEl?.text().trim();
68
+ if (!title)
69
+ continue;
70
+ // 電子書籍のみ: タイトルが【電子書籍版】または【PDFダウンロード版】で始まる
71
+ if (!title.startsWith("【"))
72
+ continue;
73
+ const href = item.find("a.c-product-list__image-wrap")[0]?.attr("href")
74
+ ?? titleEl?.attr("href");
75
+ if (!href)
76
+ continue;
77
+ const bookUrl = resolveUrl(BASE_URL + "/", href);
78
+ const priceText = item.find(".c-product-list__price")[0]?.text();
79
+ const price = priceText ? parseJapanesePrice(priceText) : undefined;
80
+ const imgEl = item.find("a.c-product-list__image-wrap img.c-image-box__image")[0];
81
+ const coverImageUrl = imgEl?.attr("src") ?? undefined;
82
+ results.push({
83
+ title,
84
+ authors: [],
85
+ publisher: "ボーンデジタル",
86
+ url: bookUrl,
87
+ price,
88
+ coverImageUrl,
89
+ ebookStores: [{ name: "ボーンデジタル", url: bookUrl, drm: "social" }],
90
+ });
91
+ if (results.length >= limit)
92
+ break;
93
+ }
94
+ return results;
95
+ },
96
+ async getDetail(url, deps) {
97
+ const html = await fetchText(url, deps);
98
+ const doc = deps.parser.parse(html);
99
+ // Colorme JSON から価格を取得
100
+ const { price: colormePrice } = extractColormeProduct(html);
101
+ const title = doc.selectOne(".p-cart-form__name")?.text().trim()
102
+ ?? doc.selectOne(".p-product-body__name")?.text().trim()
103
+ ?? "";
104
+ const priceText = doc.selectOne(".c-product-info__price")?.text();
105
+ const price = colormePrice ?? (priceText ? parseJapanesePrice(priceText) : undefined);
106
+ const descText = doc.selectOne(".p-product-body__description")?.text() ?? "";
107
+ const { authors, publisher, publishedAt } = parseDescription(descText);
108
+ const imgEl = doc.selectOne(".p-large-image img");
109
+ const coverImageUrl = imgEl?.attr("src") ?? undefined;
110
+ return {
111
+ title,
112
+ authors,
113
+ publisher,
114
+ url,
115
+ price,
116
+ publishedAt,
117
+ coverImageUrl,
118
+ ebookStores: [{ name: "ボーンデジタル", url, drm: "social" }],
119
+ };
120
+ },
121
+ };
122
+ //# sourceMappingURL=born-digital.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"born-digital.js","sourceRoot":"","sources":["../../../src/adapters/publishers/born-digital.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { PublisherAdapter } from "../../domain/publisher.js";
2
+ export declare const coronashaAdapter: PublisherAdapter;
3
+ //# sourceMappingURL=coronasha.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coronasha.d.ts","sourceRoot":"","sources":["../../../src/adapters/publishers/coronasha.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,2BAA2B,CAAC;AAuCjF,eAAO,MAAM,gBAAgB,EAAE,gBAmG9B,CAAC"}
@@ -0,0 +1,119 @@
1
+ import { fetchText, parseJapanesePrice, resolveUrl, extractEbookStoresFromDoc } from "./base.js";
2
+ const BASE_URL = "https://www.coronasha.co.jp";
3
+ const SEARCH_URL = `${BASE_URL}/np/result.html`;
4
+ /** "2023/05/01" → "2023-05-01" */
5
+ function parseDate(text) {
6
+ const m = text.match(/(\d{4})\/(\d{2})\/(\d{2})/);
7
+ if (!m)
8
+ return undefined;
9
+ return `${m[1]}-${m[2]}-${m[3]}`;
10
+ }
11
+ /**
12
+ * `.tunogaki` と `.book-title` からタイトルを組み立てる。
13
+ * "1から始める" + "Juliaプログラミング" → "1から始める Juliaプログラミング"
14
+ */
15
+ function buildTitle(container) {
16
+ const tunogaki = container.find(".tunogaki")[0]?.text().trim();
17
+ const bookTitle = container.find(".book-title")[0]?.text().trim() ?? "";
18
+ return tunogaki ? `${tunogaki} ${bookTitle}` : bookTitle;
19
+ }
20
+ /**
21
+ * `dl` 要素の配列から `dt` をキー、`dd` をバリューとするマップを返す。
22
+ * 価格・ISBN・発行年月日などの取得に使う。
23
+ */
24
+ function parseDlMap(dls) {
25
+ const map = new Map();
26
+ for (const dl of dls) {
27
+ const key = dl.find("dt")[0]?.text().trim();
28
+ const val = dl.find("dd")[0]?.text().trim();
29
+ if (key && val)
30
+ map.set(key, val);
31
+ }
32
+ return map;
33
+ }
34
+ export const coronashaAdapter = {
35
+ id: "coronasha",
36
+ name: "コロナ社",
37
+ baseUrl: BASE_URL,
38
+ async search(query, deps) {
39
+ const word = [query.title, query.author].filter(Boolean).join(" ");
40
+ if (!word)
41
+ return [];
42
+ const url = `${SEARCH_URL}?q=${encodeURIComponent(word)}`;
43
+ const html = await fetchText(url, deps);
44
+ const doc = deps.parser.parse(html);
45
+ const results = [];
46
+ const limit = query.limit ?? 10;
47
+ for (const item of doc.select("article.item")) {
48
+ // 電子版があるものだけ対象
49
+ const hasEbook = item.find("ul.status-list li")
50
+ .some(el => el.text().trim() === "電子版あり");
51
+ if (!hasEbook)
52
+ continue;
53
+ const linkEl = item.find("dl.col1 dt a")[0];
54
+ const href = linkEl?.attr("href");
55
+ if (!href)
56
+ continue;
57
+ const bookUrl = resolveUrl(BASE_URL, href);
58
+ const title = buildTitle(item);
59
+ if (!title)
60
+ continue;
61
+ const authors = item.find("ul.authors li a")
62
+ .map(el => el.text().trim())
63
+ .filter(Boolean);
64
+ const info = parseDlMap(item.find(".book-info dl"));
65
+ const price = parseJapanesePrice(info.get("定価") ?? "");
66
+ const publishedAt = parseDate(info.get("発行年月日") ?? "");
67
+ const isbn = info.get("ISBN")?.replace(/-/g, "") || undefined;
68
+ const imgEl = item.find("img.cover")[0];
69
+ const coverSrc = imgEl?.attr("src");
70
+ const coverImageUrl = coverSrc ? resolveUrl(BASE_URL, coverSrc) : undefined;
71
+ results.push({
72
+ title,
73
+ authors,
74
+ publisher: "コロナ社",
75
+ url: bookUrl,
76
+ isbn,
77
+ price,
78
+ publishedAt,
79
+ coverImageUrl,
80
+ ebookStores: [],
81
+ });
82
+ if (results.length >= limit)
83
+ break;
84
+ }
85
+ return results;
86
+ },
87
+ async getDetail(url, deps) {
88
+ const html = await fetchText(url, deps);
89
+ const doc = deps.parser.parse(html);
90
+ const h2 = doc.selectOne("h2.title");
91
+ const title = h2 ? buildTitle(h2) : "";
92
+ const authors = doc.select("ul.authors li a")
93
+ .map(el => el.text().trim())
94
+ .filter(Boolean);
95
+ const info = parseDlMap(doc.select(".book-info dl"));
96
+ const publishedAt = parseDate(info.get("発行年月日") ?? "");
97
+ const isbn = info.get("ISBN")?.replace(/-/g, "") || undefined;
98
+ // 価格はサイドバーの .price に表示される(book-info dl には含まれない)
99
+ const priceText = doc.selectOne(".price")?.text();
100
+ const price = priceText ? parseJapanesePrice(priceText) : undefined;
101
+ const imgEl = doc.selectOne("img.cover");
102
+ const coverSrc = imgEl?.attr("src");
103
+ const coverImageUrl = coverSrc ? resolveUrl(BASE_URL, coverSrc) : undefined;
104
+ // 電子版購入ポップアップのリンクから電子書籍ストアを自動検出
105
+ const ebookStores = extractEbookStoresFromDoc(doc);
106
+ return {
107
+ title,
108
+ authors,
109
+ publisher: "コロナ社",
110
+ url,
111
+ isbn,
112
+ price,
113
+ publishedAt,
114
+ coverImageUrl,
115
+ ebookStores,
116
+ };
117
+ },
118
+ };
119
+ //# sourceMappingURL=coronasha.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coronasha.js","sourceRoot":"","sources":["../../../src/adapters/publishers/coronasha.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { PublisherAdapter } from "../../domain/publisher.js";
2
+ export declare const impressBooksAdapter: PublisherAdapter;
3
+ //# sourceMappingURL=impress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impress.d.ts","sourceRoot":"","sources":["../../../src/adapters/publishers/impress.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,2BAA2B,CAAC;AAoCjF,eAAO,MAAM,mBAAmB,EAAE,gBAkEjC,CAAC"}
@@ -0,0 +1,92 @@
1
+ import { fetchText, parseJapanesePrice, stripAuthorRole } from "./base.js";
2
+ const BASE_URL = "https://book.impress.co.jp";
3
+ /** "2026/1/22" → "2026-01-22" */
4
+ function parseImpressDate(text) {
5
+ const m = text.trim().match(/(\d{4})\/(\d{1,2})\/(\d{1,2})/);
6
+ if (!m)
7
+ return undefined;
8
+ return `${m[1]}-${m[2].padStart(2, "0")}-${m[3].padStart(2, "0")}`;
9
+ }
10
+ /**
11
+ * 著者文字列から著者名配列を返す。
12
+ * 例: "山本康太 著" → ["山本康太"]
13
+ * 複数著者は「、」または改行で区切られる。
14
+ */
15
+ function parseAuthors(text) {
16
+ return text
17
+ .split(/[、,\n]/)
18
+ .map(s => stripAuthorRole(s.trim()))
19
+ .filter(Boolean);
20
+ }
21
+ /**
22
+ * 電子書籍ガイドのテキストから DRM 種別を判定する。
23
+ * 明示されていない場合はインプレスの公式方針に基づき social を返す。
24
+ */
25
+ function parseDrmType(text) {
26
+ if (/ソーシャルDRM/i.test(text))
27
+ return "social";
28
+ if (/DRM-?free|DRMフリー/i.test(text))
29
+ return "free";
30
+ if (/パスワード/i.test(text))
31
+ return "password_pdf";
32
+ return "social";
33
+ }
34
+ export const impressBooksAdapter = {
35
+ id: "impress-books",
36
+ name: "インプレスブックス",
37
+ baseUrl: BASE_URL,
38
+ async search(_query, _deps) {
39
+ // 検索ページは Google Custom Search Engine による JavaScript レンダリングのためスクレイピング不可
40
+ return [];
41
+ },
42
+ async getDetail(url, deps) {
43
+ const html = await fetchText(url, deps);
44
+ const doc = deps.parser.parse(html);
45
+ // タイトル(ページ内最初の h2)
46
+ const title = doc.selectOne("h2")?.text().trim() ?? "";
47
+ // dl.module-book-data の dt/dd を順序でペアリング
48
+ const dts = doc.select("dl.module-book-data dt");
49
+ const dds = doc.select("dl.module-book-data dd");
50
+ const bookDataMap = new Map();
51
+ for (let i = 0; i < dts.length; i++) {
52
+ const key = dts[i].text().trim();
53
+ const val = dds[i]?.text().trim() ?? "";
54
+ if (key)
55
+ bookDataMap.set(key, val);
56
+ }
57
+ const authors = parseAuthors(bookDataMap.get("著者") ?? "");
58
+ const isbn = bookDataMap.get("ISBN")?.replace(/\s/g, "") || undefined;
59
+ const publishedAt = parseImpressDate(bookDataMap.get("発売日") ?? "");
60
+ // カバー画像(img.ips.co.jp のプロトコル相対URLに https: を補完)
61
+ const coverSrc = doc.selectOne(".block-book-detail-img img")?.attr("src");
62
+ const coverImageUrl = coverSrc
63
+ ? (coverSrc.startsWith("//") ? `https:${coverSrc}` : coverSrc)
64
+ : undefined;
65
+ // 電子版価格・DRM
66
+ const ebookGuide = doc.selectOne(".module-e-book-buy-guide-txt");
67
+ const ebookBuyBtn = doc.selectOne(".module-e-book-buy-guide-btn a");
68
+ let price;
69
+ let drm = "social";
70
+ if (ebookGuide) {
71
+ const priceText = ebookGuide.find(".module-e-book-price")[0]?.text();
72
+ if (priceText)
73
+ price = parseJapanesePrice(priceText);
74
+ drm = parseDrmType(ebookGuide.text());
75
+ }
76
+ const ebookStores = ebookBuyBtn
77
+ ? [{ name: "インプレスブックス", url, drm }]
78
+ : [];
79
+ return {
80
+ title,
81
+ authors,
82
+ publisher: "インプレスブックス",
83
+ url,
84
+ isbn,
85
+ price,
86
+ publishedAt,
87
+ coverImageUrl,
88
+ ebookStores,
89
+ };
90
+ },
91
+ };
92
+ //# sourceMappingURL=impress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"impress.js","sourceRoot":"","sources":["../../../src/adapters/publishers/impress.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { PublisherAdapter } from "../../domain/publisher.js";
2
+ export declare const manateeAdapter: PublisherAdapter;
3
+ //# sourceMappingURL=manatee.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manatee.d.ts","sourceRoot":"","sources":["../../../src/adapters/publishers/manatee.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,2BAA2B,CAAC;AAmBjF,eAAO,MAAM,cAAc,EAAE,gBA6F5B,CAAC"}
@@ -0,0 +1,93 @@
1
+ import { fetchText, parseJapanesePrice, resolveUrl } from "./base.js";
2
+ const BASE_URL = "https://book.mynavi.jp/manatee";
3
+ const BOOKS_URL = `${BASE_URL}/books/`;
4
+ /**
5
+ * `.attribute li` 内の著者リンクを配列にする。
6
+ * 各 <a> のテキストが著者名(役割は括弧内テキストで付記されているが名前は <a> 内)。
7
+ */
8
+ function parseAuthors(doc) {
9
+ return doc
10
+ .select(".attribute li a")
11
+ .map(el => el.text().trim())
12
+ .filter(Boolean);
13
+ }
14
+ export const manateeAdapter = {
15
+ id: "manatee",
16
+ name: "マナティ",
17
+ baseUrl: BASE_URL,
18
+ async search(query, deps) {
19
+ const word = [query.title, query.author].filter(Boolean).join(" ");
20
+ if (!word)
21
+ return [];
22
+ const url = `${BOOKS_URL}?topics_keyword=${encodeURIComponent(word)}`;
23
+ const html = await fetchText(url, deps);
24
+ const doc = deps.parser.parse(html);
25
+ const results = [];
26
+ const limit = query.limit ?? 10;
27
+ // 書籍アイテムは <!-- item --> コメントで区切られた <li> 内
28
+ for (const li of doc.select("ul.category_list li")) {
29
+ const titleEl = li.find("dl.detail dt a")[0];
30
+ if (!titleEl)
31
+ continue;
32
+ const title = titleEl.text().trim();
33
+ if (!title)
34
+ continue;
35
+ const href = titleEl.attr("href");
36
+ if (!href)
37
+ continue;
38
+ const bookUrl = href.startsWith("http") ? href : resolveUrl(BASE_URL, href);
39
+ const priceText = li.find(".detail__price")[0]?.text().trim();
40
+ const price = priceText ? parseJapanesePrice(priceText) : undefined;
41
+ const imgEl = li.find(".image img")[0];
42
+ const imgSrc = imgEl?.attr("src");
43
+ const coverImageUrl = imgSrc ? resolveUrl(BASE_URL, imgSrc) : undefined;
44
+ results.push({
45
+ title,
46
+ authors: [],
47
+ publisher: "マナティ",
48
+ url: bookUrl,
49
+ price,
50
+ coverImageUrl,
51
+ ebookStores: [{ name: "マナティ", url: bookUrl, drm: "social" }],
52
+ });
53
+ if (results.length >= limit)
54
+ break;
55
+ }
56
+ return results;
57
+ },
58
+ async getDetail(url, deps) {
59
+ const html = await fetchText(url, deps);
60
+ const doc = deps.parser.parse(html);
61
+ const title = doc.selectOne("h1.title")?.text().trim() ?? "";
62
+ // `.intro` の最初の <p> が出版社名
63
+ const publisher = doc.selectOne(".intro p")?.text().trim() ?? "マナティ";
64
+ const authors = parseAuthors(doc);
65
+ // 購入形態テーブルの最初の行から価格取得
66
+ const priceText = doc.selectOne("#item_selectlist table .price")?.text().trim();
67
+ const price = priceText ? parseJapanesePrice(priceText) : undefined;
68
+ // 表紙画像の alt 属性が "ISBN.jpg" 形式(例: "9784839984274.jpg")
69
+ const imgEl = doc.selectOne("div.item_meta_image img");
70
+ const imgSrc = imgEl?.attr("src");
71
+ const coverImageUrl = imgSrc ? resolveUrl(BASE_URL, imgSrc) : undefined;
72
+ const imgAlt = imgEl?.attr("alt") ?? "";
73
+ const isbn = imgAlt.replace(/\.jpg$/i, "").replace(/-/g, "") || undefined;
74
+ // 発売日: "発売日:2024-03-22"
75
+ const dateText = doc.selectOne("p.date")?.text().trim();
76
+ const publishedAt = dateText?.match(/(\d{4}-\d{2}-\d{2})/)?.[1] ?? undefined;
77
+ const descEl = doc.selectOne(".item_desc p:not(.date):not(.pages)");
78
+ const description = descEl?.text().trim() || undefined;
79
+ return {
80
+ title,
81
+ authors,
82
+ publisher,
83
+ url,
84
+ isbn,
85
+ price,
86
+ publishedAt,
87
+ description,
88
+ coverImageUrl,
89
+ ebookStores: [{ name: "マナティ", url, drm: "social" }],
90
+ };
91
+ },
92
+ };
93
+ //# sourceMappingURL=manatee.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manatee.js","sourceRoot":"","sources":["../../../src/adapters/publishers/manatee.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { PublisherAdapter } from "../../domain/publisher.js";
2
+ export declare const maruzenPublishingAdapter: PublisherAdapter;
3
+ //# sourceMappingURL=maruzen-publishing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maruzen-publishing.d.ts","sourceRoot":"","sources":["../../../src/adapters/publishers/maruzen-publishing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,2BAA2B,CAAC;AAqCjF,eAAO,MAAM,wBAAwB,EAAE,gBA2FtC,CAAC"}
@@ -0,0 +1,108 @@
1
+ import { fetchText, resolveUrl, extractEbookStoresFromDoc, parseJapaneseDateToISO, stripAuthorRole } from "./base.js";
2
+ const BASE_URL = "https://www.maruzen-publishing.co.jp";
3
+ const SEARCH_URL = `${BASE_URL}/search/`;
4
+ /** 403回避のために自サイトをRefererとして付与する必要がある */
5
+ const EXTRA_HEADERS = { Referer: `${BASE_URL}/` };
6
+ /**
7
+ * "ボリス・チェルニー 著 折山文哉 訳" → ["ボリス・チェルニー", "折山文哉"]
8
+ * 役割語(著・訳・編・監訳・監修など)を除去する。
9
+ */
10
+ function parseAuthorsFromText(text) {
11
+ return text.split(/[ \s]+(?=\S)/).map(stripAuthorRole).filter(Boolean);
12
+ }
13
+ /**
14
+ * div.author 内の各リンクから役割語を除去して著者名のみ返す。
15
+ */
16
+ function parseAuthorLinks(authors) {
17
+ return authors.map(stripAuthorRole).filter(Boolean);
18
+ }
19
+ /**
20
+ * "2020/03/31" → "2020-03-31"
21
+ * "2020年3月31日" → "2020-03-31"
22
+ */
23
+ function parseDate(text) {
24
+ const m1 = text.match(/(\d{4})\/(\d{1,2})\/(\d{1,2})/);
25
+ if (m1) {
26
+ return `${m1[1]}-${m1[2].padStart(2, "0")}-${m1[3].padStart(2, "0")}`;
27
+ }
28
+ return parseJapaneseDateToISO(text);
29
+ }
30
+ export const maruzenPublishingAdapter = {
31
+ id: "maruzen-publishing",
32
+ name: "丸善出版",
33
+ baseUrl: BASE_URL,
34
+ async search(query, deps) {
35
+ const word = [query.title, query.author].filter(Boolean).join(" ");
36
+ if (!word)
37
+ return [];
38
+ const url = `${SEARCH_URL}?search_keyword=${encodeURIComponent(word)}&format=1`;
39
+ const html = await fetchText(url, deps, EXTRA_HEADERS);
40
+ const doc = deps.parser.parse(html);
41
+ const results = [];
42
+ const limit = query.limit ?? 10;
43
+ for (const item of doc.select("div.booklist div.item")) {
44
+ const linkEl = item.find("div.ttl a")[0];
45
+ if (!linkEl)
46
+ continue;
47
+ const title = linkEl.text().trim();
48
+ const href = linkEl.attr("href");
49
+ if (!title || !href)
50
+ continue;
51
+ const bookUrl = href.startsWith("http") ? href : `${BASE_URL}${href}`;
52
+ const authorLinks = item.find("div.author a").map(el => el.text().trim());
53
+ const authors = parseAuthorLinks(authorLinks);
54
+ const imgEl = item.find("div.image img")[0];
55
+ const imgSrc = imgEl?.attr("src");
56
+ const coverImageUrl = imgSrc ? resolveUrl(BASE_URL, imgSrc) : undefined;
57
+ results.push({
58
+ title,
59
+ authors,
60
+ publisher: "丸善出版",
61
+ url: bookUrl,
62
+ coverImageUrl,
63
+ });
64
+ if (results.length >= limit)
65
+ break;
66
+ }
67
+ return results;
68
+ },
69
+ async getDetail(url, deps) {
70
+ const html = await fetchText(url, deps, EXTRA_HEADERS);
71
+ const doc = deps.parser.parse(html);
72
+ // タイトルは <title> タグ、またはh1など(サイト構造に依存)
73
+ // div#bookData table の th/td からメタデータを取得
74
+ const table = doc.selectOne("div#bookData table");
75
+ let authors = [];
76
+ let publisher = "丸善出版";
77
+ let publishedAt;
78
+ if (table) {
79
+ for (const row of table.find("tr")) {
80
+ const th = row.find("th")[0]?.text().trim() ?? "";
81
+ const tdText = row.find("td")[0]?.text().trim() ?? "";
82
+ if (th === "著者") {
83
+ authors = parseAuthorsFromText(tdText);
84
+ }
85
+ else if (th === "発行元") {
86
+ publisher = tdText || "丸善出版";
87
+ }
88
+ else if (th === "出版年月日") {
89
+ publishedAt = parseDate(tdText);
90
+ }
91
+ }
92
+ }
93
+ // ページタイトルから書籍タイトルを取得(" | 丸善出版" を除去)
94
+ const pageTitle = doc.selectOne("title")?.text().trim() ?? "";
95
+ const title = pageTitle.replace(/\s*[||]\s*丸善出版.*$/, "").trim();
96
+ // 電子書籍ストア(kw.maruzen.co.jp は機関向けなので除外)
97
+ const ebookStores = extractEbookStoresFromDoc(doc).filter(store => !store.url.includes("kw.maruzen.co.jp"));
98
+ return {
99
+ title,
100
+ authors,
101
+ publisher,
102
+ url,
103
+ publishedAt,
104
+ ebookStores: ebookStores.length > 0 ? ebookStores : undefined,
105
+ };
106
+ },
107
+ };
108
+ //# sourceMappingURL=maruzen-publishing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maruzen-publishing.js","sourceRoot":"","sources":["../../../src/adapters/publishers/maruzen-publishing.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEtH,MAAM,QAAQ,GAAG,sCAAsC,CAAC;AACxD,MAAM,UAAU,GAAG,GAAG,QAAQ,UAAU,CAAC;AAEzC,wCAAwC;AACxC,MAAM,aAAa,GAAG,EAAE,OAAO,EAAE,GAAG,QAAQ,GAAG,EAAE,CAAC;AAElD;;;GAGG;AACH,SAAS,oBAAoB,CAAC,IAAY;IACxC,OAAO,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACzE,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,OAAiB;IACzC,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACtD,CAAC;AAED;;;GAGG;AACH,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACvD,IAAI,EAAE,EAAE,CAAC;QACP,OAAO,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;IACxE,CAAC;IACD,OAAO,sBAAsB,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,MAAM,wBAAwB,GAAqB;IACxD,EAAE,EAAE,oBAAoB;IACxB,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,QAAQ;IAEjB,KAAK,CAAC,MAAM,CAAC,KAAkB,EAAE,IAAmB;QAClD,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnE,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,CAAC;QAErB,MAAM,GAAG,GAAG,GAAG,UAAU,mBAAmB,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC;QAChF,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;QACvD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEpC,MAAM,OAAO,GAAiB,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;QAEhC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,uBAAuB,CAAC,EAAE,CAAC;YACvD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;YACzC,IAAI,CAAC,MAAM;gBAAE,SAAS;YAEtB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACjC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI;gBAAE,SAAS;YAE9B,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,QAAQ,GAAG,IAAI,EAAE,CAAC;YAEtE,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1E,MAAM,OAAO,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;YAE9C,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5C,MAAM,MAAM,GAAG,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YAClC,MAAM,aAAa,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAExE,OAAO,CAAC,IAAI,CAAC;gBACX,KAAK;gBACL,OAAO;gBACP,SAAS,EAAE,MAAM;gBACjB,GAAG,EAAE,OAAO;gBACZ,aAAa;aACd,CAAC,CAAC;YAEH,IAAI,OAAO,CAAC,MAAM,IAAI,KAAK;gBAAE,MAAM;QACrC,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,GAAW,EAAE,IAAmB;QAC9C,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;QACvD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEpC,qCAAqC;QACrC,wCAAwC;QACxC,MAAM,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;QAClD,IAAI,OAAO,GAAa,EAAE,CAAC;QAC3B,IAAI,SAAS,GAAG,MAAM,CAAC;QACvB,IAAI,WAA+B,CAAC;QAEpC,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnC,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;gBAClD,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;gBAEtD,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;oBAChB,OAAO,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;gBACzC,CAAC;qBAAM,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;oBACxB,SAAS,GAAG,MAAM,IAAI,MAAM,CAAC;gBAC/B,CAAC;qBAAM,IAAI,EAAE,KAAK,OAAO,EAAE,CAAC;oBAC1B,WAAW,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;gBAClC,CAAC;YACH,CAAC;QACH,CAAC;QAED,oCAAoC;QACpC,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;QAC9D,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAEhE,uCAAuC;QACvC,MAAM,WAAW,GAAG,yBAAyB,CAAC,GAAG,CAAC,CAAC,MAAM,CACvD,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CACjD,CAAC;QAEF,OAAO;YACL,KAAK;YACL,OAAO;YACP,SAAS;YACT,GAAG;YACH,WAAW;YACX,WAAW,EAAE,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;SAC9D,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { PublisherAdapter } from "../../domain/publisher.js";
2
+ export declare const optronicsAdapter: PublisherAdapter;
3
+ //# sourceMappingURL=optronics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optronics.d.ts","sourceRoot":"","sources":["../../../src/adapters/publishers/optronics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,2BAA2B,CAAC;AA6BjF,eAAO,MAAM,gBAAgB,EAAE,gBAmF9B,CAAC"}