@web-readable/core 0.1.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.
package/README.md ADDED
@@ -0,0 +1,181 @@
1
+ # web-readable
2
+
3
+ `web-readable` は、Web ページから本文本体を抽出して Markdown に変換する Rust ライブラリです。
4
+ 現時点では以下が実装済みです。
5
+
6
+ - `html5ever` による HTML 解析
7
+ - HTML5 のセマンティクスを重視したスコアリング抽出
8
+ - `main` / `article` / `section` などを優先する候補選定
9
+ - 低品質なナビゲーション・サイドバー・リンク集の抑制
10
+ - CommonMark / GFM 系の Markdown への変換サブセット
11
+ - MathML から TeX への変換
12
+ - `chromiumoxide` を使った動的取得(`dynamic` feature)
13
+ - 既存 CDP endpoint への接続によるレンダリング HTML 取得
14
+ - Lightpanda endpoint 検出時の `lightpanda fetch` フォールバックによる安定取得
15
+
16
+ ## Node.js / npm
17
+
18
+ ```bash
19
+ npm install @web-readable/core
20
+ ```
21
+
22
+ ```js
23
+ const { extract, extractToMarkdown, htmlFragmentToMarkdown } = require('@web-readable/core')
24
+
25
+ const article = extract('<main><article><h1>タイトル</h1><p>本文です。</p></article></main>')
26
+ console.log(article.text_content)
27
+ console.log(extractToMarkdown('<article><p>Hello <strong>world</strong></p></article>'))
28
+ console.log(htmlFragmentToMarkdown('<p>Hello <strong>world</strong></p>'))
29
+ ```
30
+
31
+ ## 現在の公開API
32
+
33
+ - `extract(html)`
34
+ 静的 HTML を抽出
35
+ - `extract_with_options(html, &ExtractOptions)`
36
+ オプション付きで静的 HTML を抽出
37
+ - `html_fragment_to_markdown(html)`
38
+ HTML フラグメントを Markdown に変換
39
+ - `html_fragment_to_markdown_with_options(html, &MarkdownOptions)`
40
+ 埋め込みカードを URL に展開しつつ Markdown に変換
41
+ - `extract_to_markdown(html)` / `extract_to_markdown_with_options(html, &ExtractOptions)`
42
+ 抽出結果を Markdown で取得
43
+ - `extract_to_markdown_with_markdown_options(html, &ExtractOptions, &MarkdownOptions)`
44
+ 抽出と Markdown 変換の両方にオプションを指定
45
+ - `extract_from_url(url, &DynamicOptions, &ExtractOptions)`
46
+ CDP 経由で取得したページを抽出(`dynamic` feature 必須、`merge_paginated_content` で次ページ統合)
47
+ - `extract_to_markdown_from_url(url, &DynamicOptions, &ExtractOptions)`
48
+ CDP 経由で取得したページを Markdown で取得(`dynamic` feature 必須)
49
+ - `extract_to_markdown_from_url_with_markdown_options(url, &DynamicOptions, &ExtractOptions, &MarkdownOptions)`
50
+ CDP 取得 + Markdown 埋め込み展開
51
+
52
+ 返却値は `ExtractedContent` で、主に以下を含みます。
53
+
54
+ - `title`
55
+ - `content_html`
56
+ - `text_content`
57
+ - `length`
58
+ - `score`
59
+ - `metadata`(`byline`, `excerpt`, `site_name`, `lang`, `published_time`)
60
+
61
+ ## インストール
62
+
63
+ ```toml
64
+ [dependencies]
65
+ web_readable = "0.1.0"
66
+ ```
67
+
68
+ 動的取得を使う場合:
69
+
70
+ ```toml
71
+ [dependencies]
72
+ web_readable = { version = "0.1.0", features = ["dynamic"] }
73
+ ```
74
+
75
+ ## 静的HTMLの抽出
76
+
77
+ ```rust
78
+ use web_readable::extract;
79
+
80
+ fn main() -> Result<(), Box<dyn std::error::Error>> {
81
+ let html = r#"
82
+ <html>
83
+ <body>
84
+ <main>
85
+ <article>
86
+ <h1>記事タイトル</h1>
87
+ <p>本文です。</p>
88
+ </article>
89
+ </main>
90
+ </body>
91
+ </html>
92
+ "#;
93
+
94
+ let article = extract(html)?;
95
+ println!("{}", article.text_content);
96
+ Ok(())
97
+ }
98
+ ```
99
+
100
+ ## オプション付きの抽出
101
+
102
+ ```rust
103
+ use web_readable::{extract_with_options, ExtractOptions};
104
+
105
+ let options = ExtractOptions {
106
+ include_images: true,
107
+ merge_paginated_content: true,
108
+ ..ExtractOptions::default()
109
+ };
110
+
111
+ let article = extract_with_options(html, &options)?;
112
+ ```
113
+
114
+ ```rust
115
+ use web_readable::{html_fragment_to_markdown_with_options, MarkdownOptions};
116
+
117
+ let markdown = html_fragment_to_markdown_with_options(
118
+ html,
119
+ &MarkdownOptions {
120
+ decode_embeds_as_urls: true,
121
+ },
122
+ );
123
+ ```
124
+
125
+ ## 動的ページの抽出
126
+
127
+ このモードは、すでに起動済みの Chromium / Chrome の CDP endpoint に接続します。
128
+ Lightpanda endpoint を使う場合は自動で `lightpanda fetch` に切り替わります。
129
+
130
+ ```rust
131
+ use web_readable::{extract_from_url, DynamicOptions, ExtractOptions};
132
+
133
+ #[tokio::main(flavor = "current_thread")]
134
+ async fn main() -> Result<(), Box<dyn std::error::Error>> {
135
+ let dynamic = DynamicOptions::new("ws://127.0.0.1:9222/devtools/browser/<id>");
136
+ let article = extract_from_url(
137
+ "https://example.com/article",
138
+ &dynamic,
139
+ &ExtractOptions::default(),
140
+ )
141
+ .await?;
142
+
143
+ println!("{}", article.text_content);
144
+ Ok(())
145
+ }
146
+ ```
147
+
148
+ Lightpanda を使うときは、別プロセスで CDP サーバーを立てます。
149
+
150
+ ```bash
151
+ lightpanda serve --host 127.0.0.1 --port 9222
152
+ cargo run --features dynamic --bin web_readable -- https://example.com 127.0.0.1:9222
153
+ ```
154
+
155
+ ## Markdown 変換
156
+
157
+ ```rust
158
+ use web_readable::html_fragment_to_markdown;
159
+
160
+ let markdown = html_fragment_to_markdown(r#"<p>Hello <strong>world</strong></p>"#);
161
+ ```
162
+
163
+ ## CLI
164
+
165
+ 簡易 CLI は `web_readable` バイナリとして用意しています。第一引数に URL、第二引数に CDP endpoint、第三引数に期待 Markdown ファイルを渡せます。
166
+
167
+ ```bash
168
+ cargo run --features dynamic --bin web_readable -- https://example.com 127.0.0.1:9222
169
+ cargo run --features dynamic --bin web_readable -- https://example.com 127.0.0.1:9222 expected.md
170
+ ```
171
+
172
+ ## ルール詳細
173
+
174
+ - [contentRule.md](contentRule.md)
175
+ - [markdownRule.md](markdownRule.md)
176
+
177
+ ## 実装メモ
178
+
179
+ - 旧 Readability 実装は参考にしているが、古い class/id 依存のルールはそのまま使っていない
180
+ - スコアリングは HTML5 時代の構造を優先する
181
+ - `dynamic` feature は optional で、通常利用時の依存を軽く保つ
package/index.d.ts ADDED
File without changes
package/index.js ADDED
@@ -0,0 +1,11 @@
1
+ const names = {
2
+ 'darwin-arm64': 'web-readable.darwin-arm64.node',
3
+ 'darwin-x64': 'web-readable.darwin-x64.node',
4
+ 'linux-arm64': 'web-readable.linux-arm64-gnu.node',
5
+ 'linux-x64': 'web-readable.linux-x64-gnu.node',
6
+ 'win32-arm64': 'web-readable.win32-arm64-msvc.node',
7
+ 'win32-x64': 'web-readable.win32-x64-msvc.node'
8
+ }
9
+ const binary = names[`${process.platform}-${process.arch}`]
10
+ if (!binary) throw new Error(`Unsupported platform: ${process.platform}-${process.arch}`)
11
+ module.exports = require(`./${binary}`)
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@web-readable/core",
3
+ "version": "0.1.0",
4
+ "description": "Fast article extraction and HTML-to-Markdown conversion powered by Rust.",
5
+ "license": "MIT",
6
+ "repository": "https://github.com/taisan11/web-readable",
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
10
+ "main": "index.js",
11
+ "types": "index.d.ts",
12
+ "packageManager": "bun@1.3.14",
13
+ "files": [
14
+ "index.js",
15
+ "index.d.ts",
16
+ "*.node"
17
+ ],
18
+ "engines": {
19
+ "node": ">= 16"
20
+ },
21
+ "scripts": {
22
+ "build": "napi build --release",
23
+ "test": "cargo test",
24
+ "prepublishOnly": "napi prepublish -t npm"
25
+ },
26
+ "devDependencies": {
27
+ "@napi-rs/cli": "^3.7.2"
28
+ },
29
+ "napi": {
30
+ "binaryName": "web-readable",
31
+ "targets": [
32
+ "x86_64-unknown-linux-gnu",
33
+ "x86_64-unknown-linux-musl",
34
+ "aarch64-unknown-linux-gnu",
35
+ "aarch64-apple-darwin",
36
+ "x86_64-apple-darwin",
37
+ "x86_64-pc-windows-msvc",
38
+ "aarch64-pc-windows-msvc"
39
+ ]
40
+ },
41
+ "optionalDependencies": {
42
+ "@web-readable/core-linux-x64-gnu": "0.1.0",
43
+ "@web-readable/core-linux-x64-musl": "0.1.0",
44
+ "@web-readable/core-linux-arm64-gnu": "0.1.0",
45
+ "@web-readable/core-darwin-arm64": "0.1.0",
46
+ "@web-readable/core-darwin-x64": "0.1.0",
47
+ "@web-readable/core-win32-x64-msvc": "0.1.0",
48
+ "@web-readable/core-win32-arm64-msvc": "0.1.0"
49
+ }
50
+ }
Binary file