netscape-bookmark-parser 0.0.1-pre2 → 1.0.0-pre
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-ja.md +550 -0
- package/README.md +381 -48
- package/esm/mod.d.ts +1 -1
- package/esm/mod.d.ts.map +1 -1
- package/esm/mod.js +1 -1
- package/esm/src/{Parser/Parser.d.ts → BookmarksParser/BookmarksParser.d.ts} +2 -2
- package/esm/src/BookmarksParser/BookmarksParser.d.ts.map +1 -0
- package/esm/src/{Parser/Parser.js → BookmarksParser/BookmarksParser.js} +1 -1
- package/esm/src/{Parser → BookmarksParser}/index.d.ts +1 -1
- package/esm/src/BookmarksParser/index.d.ts.map +1 -0
- package/esm/src/{Parser → BookmarksParser}/index.js +1 -1
- package/esm/src/BookmarksTree/BookmarksTree.d.ts.map +1 -1
- package/package.json +2 -1
- package/esm/src/Parser/Parser.d.ts.map +0 -1
- package/esm/src/Parser/index.d.ts.map +0 -1
package/README-ja.md
ADDED
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Copyright (c) 2025 grakeice
|
|
3
|
+
|
|
4
|
+
This software is released under the MIT License.
|
|
5
|
+
https://opensource.org/licenses/MIT
|
|
6
|
+
-->
|
|
7
|
+
|
|
8
|
+
# Netscape Bookmark Parser
|
|
9
|
+
|
|
10
|
+
> **注意:**
|
|
11
|
+
> この README は AI 生成されたドキュメントです。詳細はほぼ正確ですが、不正確な説明が含まれる可能性があります。
|
|
12
|
+
|
|
13
|
+
ブラウザのブックマークファイル(HTML 形式)を解析し、構造化データとして操作するための TypeScript/JavaScript ライブラリです。Deno と Node.js の両方のランタイムに対応しています。
|
|
14
|
+
|
|
15
|
+
## 機能
|
|
16
|
+
|
|
17
|
+
- **HTML ブックマークファイルの解析**: Chrome、Firefox、Safari、その他のブラウザからエクスポートされた HTML ブックマークファイルを解析
|
|
18
|
+
- **階層構造の保持**: フォルダとブックマークの階層構造を完全に保持
|
|
19
|
+
- **双方向変換**: HTML からデータ構造への変換とその逆の変換をサポート
|
|
20
|
+
- **JSON シリアライゼーション**: ブックマークツリーを JSON として保存・復元
|
|
21
|
+
- **Deno & Node.js 対応**: Deno と Node.js の両方のランタイムで動作
|
|
22
|
+
- **型安全性**: 包括的な型定義によるフル TypeScript サポート
|
|
23
|
+
|
|
24
|
+
## インストール
|
|
25
|
+
|
|
26
|
+
### Node.js/npm
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install netscape-bookmark-parser
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Deno
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import {
|
|
36
|
+
BookmarksParser,
|
|
37
|
+
BookmarksTree,
|
|
38
|
+
} from "jsr:@grakeice/netscape-bookmark-parser";
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 使用方法
|
|
42
|
+
|
|
43
|
+
### 基本的な例
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import { BookmarksParser, BookmarksTree } from "netscape-bookmark-parser";
|
|
47
|
+
|
|
48
|
+
// HTMLブックマークファイルを読み込み
|
|
49
|
+
const htmlContent = `<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
|
50
|
+
<HTML>
|
|
51
|
+
<BODY>
|
|
52
|
+
<DL><p>
|
|
53
|
+
<DT><H3>フォルダ 1</H3>
|
|
54
|
+
<DL><p>
|
|
55
|
+
<DT><A HREF="https://example.com">例</A>
|
|
56
|
+
</DL><p>
|
|
57
|
+
<DT><A HREF="https://google.com">Google</A>
|
|
58
|
+
</DL><p>
|
|
59
|
+
</BODY>
|
|
60
|
+
</HTML>`;
|
|
61
|
+
|
|
62
|
+
// HTMLを解析してBookmarksTreeに変換
|
|
63
|
+
const bookmarksTree = BookmarksParser.parse(htmlContent);
|
|
64
|
+
|
|
65
|
+
// JSONとして出力
|
|
66
|
+
console.log(JSON.stringify(bookmarksTree.toJSON(), null, 2));
|
|
67
|
+
|
|
68
|
+
// HTMLに戻す
|
|
69
|
+
const htmlDocument = bookmarksTree.toDOM();
|
|
70
|
+
console.log(bookmarksTree.HTMLText);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### BookmarksTree の操作
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
// 新しいブックマークツリーを作成
|
|
77
|
+
const tree = new BookmarksTree();
|
|
78
|
+
|
|
79
|
+
// ブックマークを追加
|
|
80
|
+
tree.set("Google", "https://google.com");
|
|
81
|
+
tree.set("GitHub", "https://github.com");
|
|
82
|
+
|
|
83
|
+
// フォルダ構造を作成
|
|
84
|
+
const devFolder = new BookmarksTree();
|
|
85
|
+
devFolder.set("MDN", "https://developer.mozilla.org");
|
|
86
|
+
devFolder.set("Stack Overflow", "https://stackoverflow.com");
|
|
87
|
+
|
|
88
|
+
const toolsFolder = new BookmarksTree();
|
|
89
|
+
toolsFolder.set("GitHub", "https://github.com");
|
|
90
|
+
toolsFolder.set("VS Code", "https://code.visualstudio.com");
|
|
91
|
+
|
|
92
|
+
devFolder.set("ツール", toolsFolder);
|
|
93
|
+
tree.set("開発", devFolder);
|
|
94
|
+
|
|
95
|
+
// JSONに変換
|
|
96
|
+
const json = tree.toJSON();
|
|
97
|
+
|
|
98
|
+
// JSONから復元
|
|
99
|
+
const restoredTree = BookmarksTree.fromJSON(json);
|
|
100
|
+
|
|
101
|
+
// ツリー構造を確認
|
|
102
|
+
console.log(tree.size); // トップレベルアイテムの数
|
|
103
|
+
console.log(tree.has("開発")); // true
|
|
104
|
+
console.log(tree.get("開発") instanceof BookmarksTree); // true
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 複雑な構造の処理
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// 複雑なブックマークファイルを解析
|
|
111
|
+
const complexHtml = `<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
|
112
|
+
<HTML>
|
|
113
|
+
<BODY>
|
|
114
|
+
<DL><p>
|
|
115
|
+
<DT><H3>仕事</H3>
|
|
116
|
+
<DL><p>
|
|
117
|
+
<DT><H3>開発</H3>
|
|
118
|
+
<DL><p>
|
|
119
|
+
<DT><A HREF="https://github.com">GitHub</A>
|
|
120
|
+
<DT><A HREF="https://stackoverflow.com">Stack Overflow</A>
|
|
121
|
+
</DL><p>
|
|
122
|
+
<DT><A HREF="https://docs.google.com">Google Docs</A>
|
|
123
|
+
</DL><p>
|
|
124
|
+
<DT><H3>個人</H3>
|
|
125
|
+
<DL><p>
|
|
126
|
+
<DT><A HREF="https://youtube.com">YouTube</A>
|
|
127
|
+
<DT><A HREF="https://twitter.com">Twitter</A>
|
|
128
|
+
</DL><p>
|
|
129
|
+
<DT><A HREF="https://google.com">Google</A>
|
|
130
|
+
</DL><p>
|
|
131
|
+
</BODY>
|
|
132
|
+
</HTML>`;
|
|
133
|
+
|
|
134
|
+
const tree = BookmarksParser.parse(complexHtml);
|
|
135
|
+
|
|
136
|
+
// ツリー構造をナビゲート
|
|
137
|
+
const workFolder = tree.get("仕事") as BookmarksTree;
|
|
138
|
+
const devFolder = workFolder.get("開発") as BookmarksTree;
|
|
139
|
+
console.log(devFolder.get("GitHub")); // "https://github.com"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## API リファレンス
|
|
143
|
+
|
|
144
|
+
### BookmarksParser クラス
|
|
145
|
+
|
|
146
|
+
[`BookmarksParser`](src/BookmarksParser/BookmarksParser.ts)クラスは、HTML ブックマークファイルを解析するための静的メソッドを提供します。
|
|
147
|
+
|
|
148
|
+
#### `BookmarksParser.parse(htmlContent: string): BookmarksTree`
|
|
149
|
+
|
|
150
|
+
HTML ブックマークファイルのコンテンツを解析し、[`BookmarksTree`](src/BookmarksTree/BookmarksTree.ts)インスタンスを返します。
|
|
151
|
+
|
|
152
|
+
- **パラメータ**: `htmlContent` - 文字列としての HTML ブックマークファイル
|
|
153
|
+
- **戻り値**: 解析されたブックマークツリー
|
|
154
|
+
|
|
155
|
+
**例:**
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
const htmlContent = "<!DOCTYPE NETSCAPE-Bookmark-file-1>...";
|
|
159
|
+
const tree = BookmarksParser.parse(htmlContent);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### BookmarksTree クラス
|
|
163
|
+
|
|
164
|
+
[`BookmarksTree`](src/BookmarksTree/BookmarksTree.ts)は、`Map<string, string | BookmarksTree>`を拡張してブックマークの階層構造を表現するクラスです。
|
|
165
|
+
|
|
166
|
+
#### コンストラクタ
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
const tree = new BookmarksTree();
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
#### インスタンスメソッド
|
|
173
|
+
|
|
174
|
+
##### `toJSON(): Record<string, unknown>`
|
|
175
|
+
|
|
176
|
+
ツリーを JSON オブジェクト表現に変換します。
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
const json = tree.toJSON();
|
|
180
|
+
console.log(JSON.stringify(json, null, 2));
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
##### `toDOM(): HTMLDocument`
|
|
184
|
+
|
|
185
|
+
ツリーを HTML ドキュメントオブジェクトに変換します。
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
const htmlDocument = tree.toDOM();
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
##### `get HTMLText(): string`
|
|
192
|
+
|
|
193
|
+
ブックマークツリーの HTML 文字列表現を取得します。
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
const htmlString = tree.HTMLText;
|
|
197
|
+
console.log(htmlString); // 完全なHTMLブックマークファイル
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
#### 静的メソッド
|
|
201
|
+
|
|
202
|
+
##### `fromJSON(json: Record<string, unknown>): BookmarksTree`
|
|
203
|
+
|
|
204
|
+
JSON オブジェクトからツリーを復元します。
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
const json = { Google: "https://google.com" };
|
|
208
|
+
const tree = BookmarksTree.fromJSON(json);
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
##### `fromDOM(dom: HTMLDocument): BookmarksTree`
|
|
212
|
+
|
|
213
|
+
DOM ドキュメントからツリーを作成します。
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
const dom = new DOMParser().parseFromString(htmlContent, "text/html");
|
|
217
|
+
const tree = BookmarksTree.fromDOM(dom);
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
#### Map インターフェース
|
|
221
|
+
|
|
222
|
+
`BookmarksTree`は`Map`を拡張しているため、すべての標準 Map メソッドを使用できます:
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
// ブックマークとフォルダを設定
|
|
226
|
+
tree.set("bookmark", "https://example.com");
|
|
227
|
+
tree.set("folder", new BookmarksTree());
|
|
228
|
+
|
|
229
|
+
// 値を取得
|
|
230
|
+
const url = tree.get("bookmark"); // string
|
|
231
|
+
const folder = tree.get("folder"); // BookmarksTree
|
|
232
|
+
|
|
233
|
+
// 存在確認
|
|
234
|
+
tree.has("bookmark"); // true
|
|
235
|
+
|
|
236
|
+
// アイテムを削除
|
|
237
|
+
tree.delete("bookmark");
|
|
238
|
+
|
|
239
|
+
// 繰り返し処理
|
|
240
|
+
for (const [name, value] of tree) {
|
|
241
|
+
if (typeof value === "string") {
|
|
242
|
+
console.log(`ブックマーク: ${name} -> ${value}`);
|
|
243
|
+
} else {
|
|
244
|
+
console.log(`フォルダ: ${name} (${value.size} アイテム)`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## プロジェクト構造
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
src/
|
|
253
|
+
├── BookmarksTree/
|
|
254
|
+
│ ├── BookmarksTree.ts # メインブックマークツリークラス
|
|
255
|
+
│ ├── BookmarksTree.test.ts # 包括的テスト
|
|
256
|
+
│ └── index.ts # エクスポート定義
|
|
257
|
+
└── BookmarksParser/
|
|
258
|
+
├── BookmarksParser.ts # HTMLパーサー
|
|
259
|
+
├── BookmarksParser.test.ts # パーサーテスト
|
|
260
|
+
└── index.ts # エクスポート定義
|
|
261
|
+
scripts/
|
|
262
|
+
└── build_npm.ts # NPMビルドスクリプト
|
|
263
|
+
.github/
|
|
264
|
+
└── workflows/
|
|
265
|
+
└── release.yml # CI/CDパイプライン
|
|
266
|
+
npm/ # Node.jsビルド成果物
|
|
267
|
+
├── esm/ # ESモジュール
|
|
268
|
+
├── package.json
|
|
269
|
+
└── README.md
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## サポート形式
|
|
273
|
+
|
|
274
|
+
### 入力形式
|
|
275
|
+
|
|
276
|
+
- **Netscape Bookmark File Format**: 標準 HTML ブックマークファイル形式
|
|
277
|
+
- **Chrome エクスポート形式**: Chrome ブラウザからエクスポートされた HTML ファイル
|
|
278
|
+
- **Firefox エクスポート形式**: Firefox ブラウザからエクスポートされた HTML ファイル
|
|
279
|
+
- **Safari エクスポート形式**: Safari ブラウザからエクスポートされた HTML ファイル
|
|
280
|
+
- **Edge エクスポート形式**: Microsoft Edge からエクスポートされた HTML ファイル
|
|
281
|
+
- **汎用 HTML**: Netscape ブックマーク構造に従った任意の HTML
|
|
282
|
+
|
|
283
|
+
### 出力形式
|
|
284
|
+
|
|
285
|
+
- **JSON**: プログラムからの簡単なアクセスのための構造化 JSON データ
|
|
286
|
+
- **HTML**: 全ブラウザ互換の標準 Netscape Bookmark File Format
|
|
287
|
+
- **DOM**: ブラウザ互換の HTMLDocument オブジェクト
|
|
288
|
+
|
|
289
|
+
### 特別な機能
|
|
290
|
+
|
|
291
|
+
- **Unicode 対応**: 国際文字と絵文字のフルサポート
|
|
292
|
+
- **URL 検証**: 様々な URL 形式(http、https、ftp、file、相対)の処理
|
|
293
|
+
- **HTML エンティティ処理**: HTML エンティティの適切なエスケープ・アンエスケープ
|
|
294
|
+
- **空フォルダサポート**: ブックマーク構造内の空フォルダを保持
|
|
295
|
+
- **重複処理**: 重複するブックマーク名は最後の値が優先
|
|
296
|
+
|
|
297
|
+
## 出力例
|
|
298
|
+
|
|
299
|
+
### JSON 形式
|
|
300
|
+
|
|
301
|
+
```json
|
|
302
|
+
{
|
|
303
|
+
"開発": {
|
|
304
|
+
"MDN": "https://developer.mozilla.org",
|
|
305
|
+
"ツール": {
|
|
306
|
+
"GitHub": "https://github.com",
|
|
307
|
+
"Stack Overflow": "https://stackoverflow.com"
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
"Google": "https://google.com"
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### HTML 形式
|
|
315
|
+
|
|
316
|
+
```html
|
|
317
|
+
<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
|
318
|
+
<HTML>
|
|
319
|
+
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
|
|
320
|
+
<TITLE>Bookmark</TITLE>
|
|
321
|
+
<H1>Bookmark</H1>
|
|
322
|
+
<BODY>
|
|
323
|
+
<DL><p>
|
|
324
|
+
<DT><H3>開発</H3>
|
|
325
|
+
<DL><p>
|
|
326
|
+
<DT><A HREF="https://developer.mozilla.org">MDN</A>
|
|
327
|
+
<DT><H3>ツール</H3>
|
|
328
|
+
<DL><p>
|
|
329
|
+
<DT><A HREF="https://github.com">GitHub</A>
|
|
330
|
+
<DT><A HREF="https://stackoverflow.com">Stack Overflow</A>
|
|
331
|
+
</DL><p>
|
|
332
|
+
</DL><p>
|
|
333
|
+
<DT><A HREF="https://google.com">Google</A>
|
|
334
|
+
</DL>
|
|
335
|
+
</BODY>
|
|
336
|
+
</HTML>
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
## 依存関係
|
|
340
|
+
|
|
341
|
+
- [`@b-fuze/deno-dom`](https://jsr.io/@b-fuze/deno-dom): Deno と Node.js 環境の両方での DOM 解析・操作
|
|
342
|
+
|
|
343
|
+
## 開発
|
|
344
|
+
|
|
345
|
+
### 前提条件
|
|
346
|
+
|
|
347
|
+
- [Deno](https://deno.land/) 1.x 以降
|
|
348
|
+
|
|
349
|
+
### セットアップ
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
git clone https://github.com/grakeice/netscape-bookmark-parser.git
|
|
353
|
+
cd netscape-bookmark-parser
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### 開発コマンド
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
# ファイル監視付きの開発サーバーを実行
|
|
360
|
+
deno task dev
|
|
361
|
+
|
|
362
|
+
# 全テストを実行
|
|
363
|
+
deno test
|
|
364
|
+
|
|
365
|
+
# カバレッジ付きテストを実行
|
|
366
|
+
deno test --coverage
|
|
367
|
+
|
|
368
|
+
# コードをフォーマット
|
|
369
|
+
deno fmt
|
|
370
|
+
|
|
371
|
+
# コードをリント
|
|
372
|
+
deno lint
|
|
373
|
+
|
|
374
|
+
# Node.js用にビルド
|
|
375
|
+
deno task build:npm
|
|
376
|
+
|
|
377
|
+
# 特定のバージョンでビルド
|
|
378
|
+
deno task build:npm 1.0.0
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### テストの実行
|
|
382
|
+
|
|
383
|
+
プロジェクトには全機能の包括的なテストスイートが含まれています:
|
|
384
|
+
|
|
385
|
+
```bash
|
|
386
|
+
# 全テストを実行
|
|
387
|
+
deno test
|
|
388
|
+
|
|
389
|
+
# 特定のテストファイルを実行
|
|
390
|
+
deno test src/BookmarksTree/BookmarksTree.test.ts
|
|
391
|
+
|
|
392
|
+
# 詳細出力でテストを実行
|
|
393
|
+
deno test --verbose
|
|
394
|
+
|
|
395
|
+
# テストを実行してカバレッジレポートを生成
|
|
396
|
+
deno test --coverage=coverage_dir
|
|
397
|
+
deno coverage coverage_dir
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### パブリッシュ
|
|
401
|
+
|
|
402
|
+
プロジェクトは GitHub Actions による自動パブリッシュを使用しています:
|
|
403
|
+
|
|
404
|
+
1. バージョンタグを作成: `git tag v1.0.0`
|
|
405
|
+
2. タグをプッシュ: `git push origin v1.0.0`
|
|
406
|
+
3. GitHub Actions が自動的にビルドして NPM と JSR の両方にパブリッシュ
|
|
407
|
+
|
|
408
|
+
## ブラウザ互換性
|
|
409
|
+
|
|
410
|
+
### エクスポートファイル対応ブラウザ
|
|
411
|
+
|
|
412
|
+
- **Chrome/Chromium**: 全バージョン
|
|
413
|
+
- **Firefox**: 全バージョン
|
|
414
|
+
- **Safari**: 全バージョン
|
|
415
|
+
- **Microsoft Edge**: 全バージョン
|
|
416
|
+
- **Opera**: 全バージョン
|
|
417
|
+
- **Internet Explorer**: 6+(レガシーサポート)
|
|
418
|
+
|
|
419
|
+
### エクスポートファイルの例
|
|
420
|
+
|
|
421
|
+
ライブラリは以下からエクスポートされたブックマークファイルを解析できます:
|
|
422
|
+
|
|
423
|
+
```html
|
|
424
|
+
<!-- Chrome/Edge形式 -->
|
|
425
|
+
<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
|
426
|
+
<!--This is an automatically generated file.-->
|
|
427
|
+
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
|
|
428
|
+
<TITLE>Bookmarks</TITLE>
|
|
429
|
+
<H1>Bookmarks</H1>
|
|
430
|
+
<DL><p>
|
|
431
|
+
<DT><H3 ADD_DATE="1640995200">ブックマークバー</H3>
|
|
432
|
+
<DL><p>
|
|
433
|
+
<DT><A HREF="https://example.com" ADD_DATE="1640995200">例</A>
|
|
434
|
+
</DL><p>
|
|
435
|
+
</DL>
|
|
436
|
+
|
|
437
|
+
<!-- Firefox形式 -->
|
|
438
|
+
<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
|
439
|
+
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
|
|
440
|
+
<TITLE>Bookmarks</TITLE>
|
|
441
|
+
<H1>ブックマークメニュー</H1>
|
|
442
|
+
<DL><p>
|
|
443
|
+
<DT><H3>ブックマークツールバー</H3>
|
|
444
|
+
<DL><p>
|
|
445
|
+
<DT><A HREF="https://example.com">例のサイト</A>
|
|
446
|
+
</DL><p>
|
|
447
|
+
</DL>
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
## エラーハンドリング
|
|
451
|
+
|
|
452
|
+
ライブラリは様々なエラー条件を適切に処理します:
|
|
453
|
+
|
|
454
|
+
```typescript
|
|
455
|
+
// 無効なHTML
|
|
456
|
+
const invalidHtml =
|
|
457
|
+
"<html><body>ブックマークファイルではありません</body></html>";
|
|
458
|
+
const tree = BookmarksParser.parse(invalidHtml);
|
|
459
|
+
console.log(tree.size); // 0 - 空のツリー
|
|
460
|
+
|
|
461
|
+
// 空のコンテンツ
|
|
462
|
+
const emptyTree = BookmarksParser.parse("");
|
|
463
|
+
console.log(emptyTree.size); // 0
|
|
464
|
+
|
|
465
|
+
// 不正なURLはスキップされる
|
|
466
|
+
const htmlWithBadUrls = `<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
|
467
|
+
<HTML><BODY><DL><p>
|
|
468
|
+
<DT><A HREF="">空のURL</A>
|
|
469
|
+
<DT><A>HREF属性なし</A>
|
|
470
|
+
<DT><A HREF="https://valid.com">有効なリンク</A>
|
|
471
|
+
</DL><p></BODY></HTML>`;
|
|
472
|
+
|
|
473
|
+
const parsedTree = BookmarksParser.parse(htmlWithBadUrls);
|
|
474
|
+
console.log(parsedTree.size); // 1 - 有効なリンクのみ含まれる
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
## パフォーマンス
|
|
478
|
+
|
|
479
|
+
ライブラリはパフォーマンスに最適化されています:
|
|
480
|
+
|
|
481
|
+
- **メモリ効率**: O(1)検索のためのネイティブ Map 構造を使用
|
|
482
|
+
- **ストリーミング対応**: 大きなブックマークファイル(1000+ブックマーク)を処理可能
|
|
483
|
+
- **高速解析**: 効率的なツリー走査を伴う DOM ベース解析
|
|
484
|
+
- **JSON 変換**: 最適化されたシリアライゼーション/デシリアライゼーション
|
|
485
|
+
|
|
486
|
+
## TypeScript サポート
|
|
487
|
+
|
|
488
|
+
完全な TypeScript 定義が含まれています:
|
|
489
|
+
|
|
490
|
+
```typescript
|
|
491
|
+
interface BookmarkValue extends Map<string, string | BookmarksTree> {
|
|
492
|
+
toJSON(): Record<string, unknown>;
|
|
493
|
+
toDOM(): HTMLDocument;
|
|
494
|
+
readonly HTMLText: string;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
class BookmarksParser {
|
|
498
|
+
static parse(htmlContent: string): BookmarksTree;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
class BookmarksTree extends Map<string, string | BookmarksTree> {
|
|
502
|
+
toJSON(): Record<string, unknown>;
|
|
503
|
+
static fromJSON(json: Record<string, unknown>): BookmarksTree;
|
|
504
|
+
static fromDOM(dom: HTMLDocument): BookmarksTree;
|
|
505
|
+
toDOM(): HTMLDocument;
|
|
506
|
+
get HTMLText(): string;
|
|
507
|
+
}
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
## ライセンス
|
|
511
|
+
|
|
512
|
+
MIT License - 詳細は[LICENSE](LICENSE)ファイルを参照してください。
|
|
513
|
+
|
|
514
|
+
## コントリビューション
|
|
515
|
+
|
|
516
|
+
プルリクエストとイシューレポートを歓迎します!
|
|
517
|
+
|
|
518
|
+
### コントリビューション方法
|
|
519
|
+
|
|
520
|
+
1. このリポジトリをフォーク
|
|
521
|
+
2. 機能ブランチを作成(`git checkout -b feature/amazing-feature`)
|
|
522
|
+
3. テストと共に変更を実装
|
|
523
|
+
4. 全テストが通ることを確認(`deno test`)
|
|
524
|
+
5. コードをフォーマット(`deno fmt`)
|
|
525
|
+
6. 変更をコミット(`git commit -m 'Add some amazing feature'`)
|
|
526
|
+
7. ブランチにプッシュ(`git push origin feature/amazing-feature`)
|
|
527
|
+
8. プルリクエストを作成
|
|
528
|
+
|
|
529
|
+
### イシューの報告
|
|
530
|
+
|
|
531
|
+
イシューを報告する際は、以下を含めてください:
|
|
532
|
+
|
|
533
|
+
- ブラウザ/環境情報
|
|
534
|
+
- サンプルブックマーク HTML(該当する場合)
|
|
535
|
+
- 期待される動作と実際の動作
|
|
536
|
+
- 再現手順
|
|
537
|
+
|
|
538
|
+
## 作者
|
|
539
|
+
|
|
540
|
+
**grakeice**
|
|
541
|
+
|
|
542
|
+
- GitHub: [@grakeice](https://github.com/grakeice)
|
|
543
|
+
|
|
544
|
+
## 変更履歴
|
|
545
|
+
|
|
546
|
+
### v1.0.0-pre(最新)
|
|
547
|
+
|
|
548
|
+
- 🚀 **プレリリース版**: 安定版 1.0.0 リリースに向けた準備
|
|
549
|
+
- ✨ **コア機能**: 完全な HTML ブックマークファイル解析機能
|
|
550
|
+
- 🏗️ **BookmarksTree クラス**: Map インターフェースを持つ階層
|
package/README.md
CHANGED
|
@@ -7,8 +7,13 @@
|
|
|
7
7
|
|
|
8
8
|
# Netscape Bookmark Parser
|
|
9
9
|
|
|
10
|
+
> **Note:**
|
|
11
|
+
> This README is an AI-generated document. Details are mostly accurate but might include inaccurate description.
|
|
12
|
+
|
|
10
13
|
A TypeScript/JavaScript library for parsing browser bookmark files (HTML format) and manipulating them as structured data. Compatible with both Deno and Node.js runtimes.
|
|
11
14
|
|
|
15
|
+
日本語ドキュメント: [`./README-ja.md`](./README-ja.md)
|
|
16
|
+
|
|
12
17
|
## Features
|
|
13
18
|
|
|
14
19
|
- **HTML Bookmark File Parsing**: Parse exported HTML bookmark files from Chrome, Firefox, Safari, and other browsers
|
|
@@ -16,6 +21,7 @@ A TypeScript/JavaScript library for parsing browser bookmark files (HTML format)
|
|
|
16
21
|
- **Bidirectional Conversion**: Support conversion from HTML to data structure and vice versa
|
|
17
22
|
- **JSON Serialization**: Save and restore bookmark trees as JSON
|
|
18
23
|
- **Deno & Node.js Support**: Works with both Deno and Node.js runtimes
|
|
24
|
+
- **Type Safety**: Full TypeScript support with comprehensive type definitions
|
|
19
25
|
|
|
20
26
|
## Installation
|
|
21
27
|
|
|
@@ -28,7 +34,10 @@ npm install netscape-bookmark-parser
|
|
|
28
34
|
### Deno
|
|
29
35
|
|
|
30
36
|
```typescript
|
|
31
|
-
import {
|
|
37
|
+
import {
|
|
38
|
+
BookmarksParser,
|
|
39
|
+
BookmarksTree,
|
|
40
|
+
} from "jsr:@grakeice/netscape-bookmark-parser";
|
|
32
41
|
```
|
|
33
42
|
|
|
34
43
|
## Usage
|
|
@@ -36,11 +45,12 @@ import { Parser, BookmarksTree } from "jsr:@grakeice/netscape-bookmark-parser";
|
|
|
36
45
|
### Basic Example
|
|
37
46
|
|
|
38
47
|
```typescript
|
|
39
|
-
import {
|
|
48
|
+
import { BookmarksParser, BookmarksTree } from "netscape-bookmark-parser";
|
|
40
49
|
|
|
41
50
|
// Read HTML bookmark file
|
|
42
51
|
const htmlContent = `<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
|
43
52
|
<HTML>
|
|
53
|
+
<BODY>
|
|
44
54
|
<DL><p>
|
|
45
55
|
<DT><H3>Folder 1</H3>
|
|
46
56
|
<DL><p>
|
|
@@ -48,16 +58,18 @@ const htmlContent = `<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
|
|
48
58
|
</DL><p>
|
|
49
59
|
<DT><A HREF="https://google.com">Google</A>
|
|
50
60
|
</DL><p>
|
|
61
|
+
</BODY>
|
|
51
62
|
</HTML>`;
|
|
52
63
|
|
|
53
64
|
// Parse HTML and convert to BookmarksTree
|
|
54
|
-
const bookmarksTree =
|
|
65
|
+
const bookmarksTree = BookmarksParser.parse(htmlContent);
|
|
55
66
|
|
|
56
67
|
// Output as JSON
|
|
57
68
|
console.log(JSON.stringify(bookmarksTree.toJSON(), null, 2));
|
|
58
69
|
|
|
59
70
|
// Convert back to HTML
|
|
60
71
|
const htmlDocument = bookmarksTree.toDOM();
|
|
72
|
+
console.log(bookmarksTree.HTMLText);
|
|
61
73
|
```
|
|
62
74
|
|
|
63
75
|
### BookmarksTree Operations
|
|
@@ -70,10 +82,16 @@ const tree = new BookmarksTree();
|
|
|
70
82
|
tree.set("Google", "https://google.com");
|
|
71
83
|
tree.set("GitHub", "https://github.com");
|
|
72
84
|
|
|
73
|
-
// Create a folder
|
|
85
|
+
// Create a folder structure
|
|
74
86
|
const devFolder = new BookmarksTree();
|
|
75
87
|
devFolder.set("MDN", "https://developer.mozilla.org");
|
|
76
88
|
devFolder.set("Stack Overflow", "https://stackoverflow.com");
|
|
89
|
+
|
|
90
|
+
const toolsFolder = new BookmarksTree();
|
|
91
|
+
toolsFolder.set("GitHub", "https://github.com");
|
|
92
|
+
toolsFolder.set("VS Code", "https://code.visualstudio.com");
|
|
93
|
+
|
|
94
|
+
devFolder.set("Tools", toolsFolder);
|
|
77
95
|
tree.set("Development", devFolder);
|
|
78
96
|
|
|
79
97
|
// Convert to JSON
|
|
@@ -81,45 +99,174 @@ const json = tree.toJSON();
|
|
|
81
99
|
|
|
82
100
|
// Restore from JSON
|
|
83
101
|
const restoredTree = BookmarksTree.fromJSON(json);
|
|
102
|
+
|
|
103
|
+
// Check tree structure
|
|
104
|
+
console.log(tree.size); // Number of top-level items
|
|
105
|
+
console.log(tree.has("Development")); // true
|
|
106
|
+
console.log(tree.get("Development") instanceof BookmarksTree); // true
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Working with Complex Structures
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
// Parse a complex bookmark file
|
|
113
|
+
const complexHtml = `<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
|
114
|
+
<HTML>
|
|
115
|
+
<BODY>
|
|
116
|
+
<DL><p>
|
|
117
|
+
<DT><H3>Work</H3>
|
|
118
|
+
<DL><p>
|
|
119
|
+
<DT><H3>Development</H3>
|
|
120
|
+
<DL><p>
|
|
121
|
+
<DT><A HREF="https://github.com">GitHub</A>
|
|
122
|
+
<DT><A HREF="https://stackoverflow.com">Stack Overflow</A>
|
|
123
|
+
</DL><p>
|
|
124
|
+
<DT><A HREF="https://docs.google.com">Google Docs</A>
|
|
125
|
+
</DL><p>
|
|
126
|
+
<DT><H3>Personal</H3>
|
|
127
|
+
<DL><p>
|
|
128
|
+
<DT><A HREF="https://youtube.com">YouTube</A>
|
|
129
|
+
<DT><A HREF="https://twitter.com">Twitter</A>
|
|
130
|
+
</DL><p>
|
|
131
|
+
<DT><A HREF="https://google.com">Google</A>
|
|
132
|
+
</DL><p>
|
|
133
|
+
</BODY>
|
|
134
|
+
</HTML>`;
|
|
135
|
+
|
|
136
|
+
const tree = BookmarksParser.parse(complexHtml);
|
|
137
|
+
|
|
138
|
+
// Navigate the tree structure
|
|
139
|
+
const workFolder = tree.get("Work") as BookmarksTree;
|
|
140
|
+
const devFolder = workFolder.get("Development") as BookmarksTree;
|
|
141
|
+
console.log(devFolder.get("GitHub")); // "https://github.com"
|
|
84
142
|
```
|
|
85
143
|
|
|
86
144
|
## API Reference
|
|
87
145
|
|
|
88
|
-
###
|
|
146
|
+
### BookmarksParser Class
|
|
89
147
|
|
|
90
|
-
The [`
|
|
148
|
+
The [`BookmarksParser`](src/BookmarksParser/BookmarksParser.ts) class provides static methods for parsing HTML bookmark files.
|
|
91
149
|
|
|
92
|
-
#### `
|
|
150
|
+
#### `BookmarksParser.parse(htmlContent: string): BookmarksTree`
|
|
93
151
|
|
|
94
152
|
Parses HTML bookmark file content and returns a [`BookmarksTree`](src/BookmarksTree/BookmarksTree.ts) instance.
|
|
95
153
|
|
|
96
154
|
- **Parameter**: `htmlContent` - HTML bookmark file as string
|
|
97
155
|
- **Returns**: Parsed bookmark tree
|
|
98
156
|
|
|
157
|
+
**Example:**
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
const htmlContent = "<!DOCTYPE NETSCAPE-Bookmark-file-1>...";
|
|
161
|
+
const tree = BookmarksParser.parse(htmlContent);
|
|
162
|
+
```
|
|
163
|
+
|
|
99
164
|
### BookmarksTree Class
|
|
100
165
|
|
|
101
166
|
[`BookmarksTree`](src/BookmarksTree/BookmarksTree.ts) is a class that extends `Map<string, string | BookmarksTree>` to represent the hierarchical structure of bookmarks.
|
|
102
167
|
|
|
103
|
-
####
|
|
168
|
+
#### Constructor
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
const tree = new BookmarksTree();
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
#### Instance Methods
|
|
104
175
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
176
|
+
##### `toJSON(): Record<string, unknown>`
|
|
177
|
+
|
|
178
|
+
Convert tree to JSON object representation.
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
const json = tree.toJSON();
|
|
182
|
+
console.log(JSON.stringify(json, null, 2));
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
##### `toDOM(): HTMLDocument`
|
|
186
|
+
|
|
187
|
+
Convert tree to HTML document object.
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
const htmlDocument = tree.toDOM();
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
##### `get HTMLText(): string`
|
|
194
|
+
|
|
195
|
+
Get HTML string representation of the bookmark tree.
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
const htmlString = tree.HTMLText;
|
|
199
|
+
console.log(htmlString); // Complete HTML bookmark file
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
#### Static Methods
|
|
203
|
+
|
|
204
|
+
##### `fromJSON(json: Record<string, unknown>): BookmarksTree`
|
|
205
|
+
|
|
206
|
+
Restore tree from JSON object.
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
const json = { Google: "https://google.com" };
|
|
210
|
+
const tree = BookmarksTree.fromJSON(json);
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
##### `fromDOM(dom: HTMLDocument): BookmarksTree`
|
|
214
|
+
|
|
215
|
+
Create tree from DOM document.
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
const dom = new DOMParser().parseFromString(htmlContent, "text/html");
|
|
219
|
+
const tree = BookmarksTree.fromDOM(dom);
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
#### Map Interface
|
|
223
|
+
|
|
224
|
+
Since `BookmarksTree` extends `Map`, you can use all standard Map methods:
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
// Set bookmarks and folders
|
|
228
|
+
tree.set("bookmark", "https://example.com");
|
|
229
|
+
tree.set("folder", new BookmarksTree());
|
|
230
|
+
|
|
231
|
+
// Get values
|
|
232
|
+
const url = tree.get("bookmark"); // string
|
|
233
|
+
const folder = tree.get("folder"); // BookmarksTree
|
|
234
|
+
|
|
235
|
+
// Check existence
|
|
236
|
+
tree.has("bookmark"); // true
|
|
237
|
+
|
|
238
|
+
// Delete items
|
|
239
|
+
tree.delete("bookmark");
|
|
240
|
+
|
|
241
|
+
// Iterate
|
|
242
|
+
for (const [name, value] of tree) {
|
|
243
|
+
if (typeof value === "string") {
|
|
244
|
+
console.log(`Bookmark: ${name} -> ${value}`);
|
|
245
|
+
} else {
|
|
246
|
+
console.log(`Folder: ${name} (${value.size} items)`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
110
250
|
|
|
111
251
|
## Project Structure
|
|
112
252
|
|
|
113
253
|
```
|
|
114
254
|
src/
|
|
115
255
|
├── BookmarksTree/
|
|
116
|
-
│ ├── BookmarksTree.ts
|
|
117
|
-
│
|
|
118
|
-
└──
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
256
|
+
│ ├── BookmarksTree.ts # Main bookmark tree class
|
|
257
|
+
│ ├── BookmarksTree.test.ts # Comprehensive tests
|
|
258
|
+
│ └── index.ts # Export definitions
|
|
259
|
+
└── BookmarksParser/
|
|
260
|
+
├── BookmarksParser.ts # HTML parser
|
|
261
|
+
├── BookmarksParser.test.ts # Parser tests
|
|
262
|
+
└── index.ts # Export definitions
|
|
263
|
+
scripts/
|
|
264
|
+
└── build_npm.ts # NPM build script
|
|
265
|
+
.github/
|
|
266
|
+
└── workflows/
|
|
267
|
+
└── release.yml # CI/CD pipeline
|
|
268
|
+
npm/ # Node.js build artifacts
|
|
269
|
+
├── esm/ # ES modules
|
|
123
270
|
├── package.json
|
|
124
271
|
└── README.md
|
|
125
272
|
```
|
|
@@ -129,12 +276,25 @@ npm/ # Node.js build artifacts
|
|
|
129
276
|
### Input Formats
|
|
130
277
|
|
|
131
278
|
- **Netscape Bookmark File Format**: Standard HTML bookmark file format
|
|
132
|
-
- HTML files exported from Chrome
|
|
279
|
+
- **Chrome Export Format**: HTML files exported from Chrome browser
|
|
280
|
+
- **Firefox Export Format**: HTML files exported from Firefox browser
|
|
281
|
+
- **Safari Export Format**: HTML files exported from Safari browser
|
|
282
|
+
- **Edge Export Format**: HTML files exported from Microsoft Edge
|
|
283
|
+
- **Generic HTML**: Any HTML following the Netscape bookmark structure
|
|
133
284
|
|
|
134
285
|
### Output Formats
|
|
135
286
|
|
|
136
|
-
- **JSON**: Structured JSON data
|
|
137
|
-
- **HTML**: Standard Netscape Bookmark File Format
|
|
287
|
+
- **JSON**: Structured JSON data for easy programmatic access
|
|
288
|
+
- **HTML**: Standard Netscape Bookmark File Format compatible with all browsers
|
|
289
|
+
- **DOM**: Browser-compatible HTMLDocument objects
|
|
290
|
+
|
|
291
|
+
### Special Features
|
|
292
|
+
|
|
293
|
+
- **Unicode Support**: Full support for international characters and emojis
|
|
294
|
+
- **URL Validation**: Handles various URL formats (http, https, ftp, file, relative)
|
|
295
|
+
- **HTML Entity Handling**: Proper escaping and unescaping of HTML entities
|
|
296
|
+
- **Empty Folder Support**: Preserves empty folders in the bookmark structure
|
|
297
|
+
- **Duplicate Handling**: Last value wins for duplicate bookmark names
|
|
138
298
|
|
|
139
299
|
## Output Examples
|
|
140
300
|
|
|
@@ -142,8 +302,12 @@ npm/ # Node.js build artifacts
|
|
|
142
302
|
|
|
143
303
|
```json
|
|
144
304
|
{
|
|
145
|
-
"
|
|
146
|
-
"
|
|
305
|
+
"Development": {
|
|
306
|
+
"MDN": "https://developer.mozilla.org",
|
|
307
|
+
"Tools": {
|
|
308
|
+
"GitHub": "https://github.com",
|
|
309
|
+
"Stack Overflow": "https://stackoverflow.com"
|
|
310
|
+
}
|
|
147
311
|
},
|
|
148
312
|
"Google": "https://google.com"
|
|
149
313
|
}
|
|
@@ -159,12 +323,16 @@ npm/ # Node.js build artifacts
|
|
|
159
323
|
<H1>Bookmark</H1>
|
|
160
324
|
<BODY>
|
|
161
325
|
<DL><p>
|
|
162
|
-
<DT><H3>
|
|
326
|
+
<DT><H3>Development</H3>
|
|
163
327
|
<DL><p>
|
|
164
|
-
<DT><A HREF="https://
|
|
328
|
+
<DT><A HREF="https://developer.mozilla.org">MDN</A>
|
|
329
|
+
<DT><H3>Tools</H3>
|
|
330
|
+
<DL><p>
|
|
331
|
+
<DT><A HREF="https://github.com">GitHub</A>
|
|
332
|
+
<DT><A HREF="https://stackoverflow.com">Stack Overflow</A>
|
|
333
|
+
</DL><p>
|
|
165
334
|
</DL><p>
|
|
166
335
|
<DT><A HREF="https://google.com">Google</A>
|
|
167
|
-
<p>
|
|
168
336
|
</DL>
|
|
169
337
|
</BODY>
|
|
170
338
|
</HTML>
|
|
@@ -172,10 +340,14 @@ npm/ # Node.js build artifacts
|
|
|
172
340
|
|
|
173
341
|
## Dependencies
|
|
174
342
|
|
|
175
|
-
- [`@b-fuze/deno-dom`](https://jsr.io/@b-fuze/deno-dom): DOM parser and manipulation
|
|
343
|
+
- [`@b-fuze/deno-dom`](https://jsr.io/@b-fuze/deno-dom): DOM parser and manipulation for both Deno and Node.js environments
|
|
176
344
|
|
|
177
345
|
## Development
|
|
178
346
|
|
|
347
|
+
### Prerequisites
|
|
348
|
+
|
|
349
|
+
- [Deno](https://deno.land/) 1.x or later
|
|
350
|
+
|
|
179
351
|
### Setup
|
|
180
352
|
|
|
181
353
|
```bash
|
|
@@ -183,28 +355,157 @@ git clone https://github.com/grakeice/netscape-bookmark-parser.git
|
|
|
183
355
|
cd netscape-bookmark-parser
|
|
184
356
|
```
|
|
185
357
|
|
|
186
|
-
###
|
|
358
|
+
### Development Commands
|
|
187
359
|
|
|
188
360
|
```bash
|
|
361
|
+
# Run development server with file watching
|
|
362
|
+
deno task dev
|
|
363
|
+
|
|
364
|
+
# Run all tests
|
|
189
365
|
deno test
|
|
190
|
-
```
|
|
191
366
|
|
|
192
|
-
|
|
367
|
+
# Run tests with coverage
|
|
368
|
+
deno test --coverage
|
|
193
369
|
|
|
194
|
-
|
|
370
|
+
# Format code
|
|
371
|
+
deno fmt
|
|
372
|
+
|
|
373
|
+
# Lint code
|
|
374
|
+
deno lint
|
|
375
|
+
|
|
376
|
+
# Build for Node.js
|
|
195
377
|
deno task build:npm
|
|
378
|
+
|
|
379
|
+
# Build with specific version
|
|
380
|
+
deno task build:npm 1.0.0
|
|
196
381
|
```
|
|
197
382
|
|
|
198
|
-
###
|
|
383
|
+
### Running Tests
|
|
384
|
+
|
|
385
|
+
The project includes comprehensive test suites for all functionality:
|
|
199
386
|
|
|
200
387
|
```bash
|
|
201
|
-
|
|
388
|
+
# Run all tests
|
|
389
|
+
deno test
|
|
390
|
+
|
|
391
|
+
# Run specific test file
|
|
392
|
+
deno test src/BookmarksTree/BookmarksTree.test.ts
|
|
393
|
+
|
|
394
|
+
# Run tests with detailed output
|
|
395
|
+
deno test --verbose
|
|
396
|
+
|
|
397
|
+
# Run tests and generate coverage report
|
|
398
|
+
deno test --coverage=coverage_dir
|
|
399
|
+
deno coverage coverage_dir
|
|
202
400
|
```
|
|
203
401
|
|
|
204
|
-
###
|
|
402
|
+
### Publishing
|
|
205
403
|
|
|
206
|
-
|
|
207
|
-
|
|
404
|
+
The project uses automated publishing via GitHub Actions:
|
|
405
|
+
|
|
406
|
+
1. Create a version tag: `git tag v1.0.0`
|
|
407
|
+
2. Push the tag: `git push origin v1.0.0`
|
|
408
|
+
3. GitHub Actions will automatically build and publish to both NPM and JSR
|
|
409
|
+
|
|
410
|
+
## Browser Compatibility
|
|
411
|
+
|
|
412
|
+
### Supported Browsers for Export Files
|
|
413
|
+
|
|
414
|
+
- **Chrome/Chromium**: All versions
|
|
415
|
+
- **Firefox**: All versions
|
|
416
|
+
- **Safari**: All versions
|
|
417
|
+
- **Microsoft Edge**: All versions
|
|
418
|
+
- **Opera**: All versions
|
|
419
|
+
- **Internet Explorer**: 6+ (legacy support)
|
|
420
|
+
|
|
421
|
+
### Exported File Examples
|
|
422
|
+
|
|
423
|
+
The library can parse bookmark files exported from:
|
|
424
|
+
|
|
425
|
+
```html
|
|
426
|
+
<!-- Chrome/Edge format -->
|
|
427
|
+
<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
|
428
|
+
<!--This is an automatically generated file.-->
|
|
429
|
+
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
|
|
430
|
+
<TITLE>Bookmarks</TITLE>
|
|
431
|
+
<H1>Bookmarks</H1>
|
|
432
|
+
<DL><p>
|
|
433
|
+
<DT><H3 ADD_DATE="1640995200">Bookmarks bar</H3>
|
|
434
|
+
<DL><p>
|
|
435
|
+
<DT><A HREF="https://example.com" ADD_DATE="1640995200">Example</A>
|
|
436
|
+
</DL><p>
|
|
437
|
+
</DL>
|
|
438
|
+
|
|
439
|
+
<!-- Firefox format -->
|
|
440
|
+
<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
|
441
|
+
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
|
|
442
|
+
<TITLE>Bookmarks</TITLE>
|
|
443
|
+
<H1>Bookmarks Menu</H1>
|
|
444
|
+
<DL><p>
|
|
445
|
+
<DT><H3>Bookmarks Toolbar</H3>
|
|
446
|
+
<DL><p>
|
|
447
|
+
<DT><A HREF="https://example.com">Example Site</A>
|
|
448
|
+
</DL><p>
|
|
449
|
+
</DL>
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
## Error Handling
|
|
453
|
+
|
|
454
|
+
The library gracefully handles various error conditions:
|
|
455
|
+
|
|
456
|
+
```typescript
|
|
457
|
+
// Invalid HTML
|
|
458
|
+
const invalidHtml = "<html><body>Not a bookmark file</body></html>";
|
|
459
|
+
const tree = BookmarksParser.parse(invalidHtml);
|
|
460
|
+
console.log(tree.size); // 0 - empty tree
|
|
461
|
+
|
|
462
|
+
// Empty content
|
|
463
|
+
const emptyTree = BookmarksParser.parse("");
|
|
464
|
+
console.log(emptyTree.size); // 0
|
|
465
|
+
|
|
466
|
+
// Malformed URLs are skipped
|
|
467
|
+
const htmlWithBadUrls = `<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
|
468
|
+
<HTML><BODY><DL><p>
|
|
469
|
+
<DT><A HREF="">Empty URL</A>
|
|
470
|
+
<DT><A>No HREF attribute</A>
|
|
471
|
+
<DT><A HREF="https://valid.com">Valid Link</A>
|
|
472
|
+
</DL><p></BODY></HTML>`;
|
|
473
|
+
|
|
474
|
+
const parsedTree = BookmarksParser.parse(htmlWithBadUrls);
|
|
475
|
+
console.log(parsedTree.size); // 1 - only valid link included
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
## Performance
|
|
479
|
+
|
|
480
|
+
The library is optimized for performance:
|
|
481
|
+
|
|
482
|
+
- **Memory Efficient**: Uses native Map structure for O(1) lookups
|
|
483
|
+
- **Streaming Capable**: Can handle large bookmark files (1000+ bookmarks)
|
|
484
|
+
- **Fast Parsing**: DOM-based parsing with efficient tree traversal
|
|
485
|
+
- **JSON Conversion**: Optimized serialization/deserialization
|
|
486
|
+
|
|
487
|
+
## TypeScript Support
|
|
488
|
+
|
|
489
|
+
Full TypeScript definitions included:
|
|
490
|
+
|
|
491
|
+
```typescript
|
|
492
|
+
interface BookmarkValue extends Map<string, string | BookmarksTree> {
|
|
493
|
+
toJSON(): Record<string, unknown>;
|
|
494
|
+
toDOM(): HTMLDocument;
|
|
495
|
+
readonly HTMLText: string;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
class BookmarksParser {
|
|
499
|
+
static parse(htmlContent: string): BookmarksTree;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
class BookmarksTree extends Map<string, string | BookmarksTree> {
|
|
503
|
+
toJSON(): Record<string, unknown>;
|
|
504
|
+
static fromJSON(json: Record<string, unknown>): BookmarksTree;
|
|
505
|
+
static fromDOM(dom: HTMLDocument): BookmarksTree;
|
|
506
|
+
toDOM(): HTMLDocument;
|
|
507
|
+
get HTMLText(): string;
|
|
508
|
+
}
|
|
208
509
|
```
|
|
209
510
|
|
|
210
511
|
## License
|
|
@@ -213,22 +514,54 @@ MIT License - See [LICENSE](LICENSE) file for details.
|
|
|
213
514
|
|
|
214
515
|
## Contributing
|
|
215
516
|
|
|
216
|
-
Pull requests and issue reports are welcome
|
|
517
|
+
Pull requests and issue reports are welcome!
|
|
518
|
+
|
|
519
|
+
### How to Contribute
|
|
217
520
|
|
|
218
521
|
1. Fork this repository
|
|
219
522
|
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
220
|
-
3.
|
|
221
|
-
4.
|
|
222
|
-
5.
|
|
523
|
+
3. Make your changes with tests
|
|
524
|
+
4. Ensure all tests pass (`deno test`)
|
|
525
|
+
5. Format your code (`deno fmt`)
|
|
526
|
+
6. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
527
|
+
7. Push to the branch (`git push origin feature/amazing-feature`)
|
|
528
|
+
8. Create a pull request
|
|
529
|
+
|
|
530
|
+
### Reporting Issues
|
|
531
|
+
|
|
532
|
+
When reporting issues, please include:
|
|
533
|
+
|
|
534
|
+
- Browser/environment information
|
|
535
|
+
- Sample bookmark HTML (if applicable)
|
|
536
|
+
- Expected vs actual behavior
|
|
537
|
+
- Steps to reproduce
|
|
223
538
|
|
|
224
539
|
## Author
|
|
225
540
|
|
|
226
|
-
grakeice
|
|
541
|
+
**grakeice**
|
|
542
|
+
|
|
543
|
+
- GitHub: [@grakeice](https://github.com/grakeice)
|
|
227
544
|
|
|
228
545
|
## Changelog
|
|
229
546
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
547
|
+
### v1.0.0-pre (Latest)
|
|
548
|
+
|
|
549
|
+
- 🚀 **Pre-release Version**: Preparing for stable 1.0.0 release
|
|
550
|
+
- ✨ **Core Features**: Complete HTML bookmark file parsing functionality
|
|
551
|
+
- 🏗️ **BookmarksTree Class**: Hierarchical structure management with Map interface
|
|
552
|
+
- 🔄 **Bidirectional Conversion**: JSON ↔ HTML ↔ DOM conversion support
|
|
553
|
+
- 🧪 **Comprehensive Testing**: Full test coverage with edge case handling
|
|
554
|
+
- 📦 **Multi-Runtime Support**: Native Deno and Node.js compatibility
|
|
555
|
+
- 🔧 **TypeScript Support**: Complete type definitions and IntelliSense
|
|
556
|
+
- 🤖 **CI/CD Pipeline**: Automated testing and publishing via GitHub Actions
|
|
557
|
+
- 📚 **Documentation**: Comprehensive README with examples and API reference
|
|
558
|
+
- 🌐 **International Support**: Unicode and multi-language bookmark handling
|
|
559
|
+
- ⚡ **Performance Optimized**: Efficient parsing for large bookmark collections
|
|
560
|
+
- 🛡️ **Error Handling**: Graceful handling of malformed HTML and invalid URLs
|
|
561
|
+
|
|
562
|
+
### v0.0.1-pre4
|
|
563
|
+
|
|
564
|
+
- Early pre-release version
|
|
565
|
+
- Core functionality proof of concept
|
|
566
|
+
- Basic parsing implementation
|
|
567
|
+
- Initial testing setup
|
package/esm/mod.d.ts
CHANGED
package/esm/mod.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,qBAAqB,CAAC;AAG7B,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,qBAAqB,CAAC;AAG7B,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC"}
|
package/esm/mod.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* https://opensource.org/licenses/MIT
|
|
6
6
|
*/
|
|
7
7
|
import { BookmarksTree } from "../BookmarksTree/index.js";
|
|
8
|
-
export declare class
|
|
8
|
+
export declare class BookmarksParser {
|
|
9
9
|
static parse(data: string): BookmarksTree;
|
|
10
10
|
}
|
|
11
|
-
//# sourceMappingURL=
|
|
11
|
+
//# sourceMappingURL=BookmarksParser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BookmarksParser.d.ts","sourceRoot":"","sources":["../../../src/src/BookmarksParser/BookmarksParser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE1D,qBAAa,eAAe;IAC3B,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa;CAKzC"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { DOMParser } from "../../deps/jsr.io/@b-fuze/deno-dom/0.1.49/deno-dom-wasm.js";
|
|
8
8
|
import { BookmarksTree } from "../BookmarksTree/index.js";
|
|
9
|
-
export class
|
|
9
|
+
export class BookmarksParser {
|
|
10
10
|
static parse(data) {
|
|
11
11
|
const dom = new DOMParser().parseFromString(data, "text/html");
|
|
12
12
|
const tree = BookmarksTree.fromDOM(dom);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/BookmarksParser/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BookmarksTree.d.ts","sourceRoot":"","sources":["../../../src/src/BookmarksTree/BookmarksTree.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"BookmarksTree.d.ts","sourceRoot":"","sources":["../../../src/src/BookmarksTree/BookmarksTree.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAA2B,KAAK,YAAY,EAAE,MAAM,4DAA4D,CAAC;AAExH,qBAAa,aAAc,SAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC;;IAKrE,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAcjC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa;IAmB7D,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,YAAY,GAAG,aAAa;IA8ChD,KAAK,IAAI,YAAY;IAIrB,IAAI,QAAQ,IAAI,MAAM,CAoCrB;CACD"}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Parser.d.ts","sourceRoot":"","sources":["../../../src/src/Parser/Parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE1D,qBAAa,MAAM;IAClB,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa;CAKzC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/Parser/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
|