前言#
RSS(RDF Site Summary)
は、複数のウェブサイトの更新内容を集約し、ウェブサイトの購読者に自動的に通知するためのメッセージソースフォーマット規格で、24 年の歴史があります。RSS はさまざまなブログでも使用されており、便利に購読できますが、RSS リーダーを選ぶ際に悩むことがよくあります。どれを選べばよいかわからず、いくつかの有名な RSS リーダーを試した後でも、まだ少し不満が残ります。タスクバーに横たわる VScode を見て、面白いアイデアが生まれました ——VScode を自分の RSS リーダーにすることです。
💡需求分析#
このニーズがあるので、分析を行う必要があります:
- RSS リンクの追加: ユーザーが RSS リンクを入力または選択し、プラグインの設定に保存します。
- RSS の解析: RSS 解析ライブラリを使用して保存された RSS リンクを解析し、ブログ情報を抽出します。
- ブログリストの表示: プラグイン内にブログリストを表示し、ユーザーが閲覧したいブログを選択できるようにします。
- 記事の選択: ユーザーがブログ内の 1 つの記事を選択できるようにします。
- 記事内容の表示: 選択した記事の内容を表示します。
🛠️開発プロセス#
プロジェクト初期化#
VScode プラグイン開発文書によれば、最初の VScode プラグインを開発するには、YeomanとVS Code Extension Generatorをインストールする必要があります:
npm install -g yo generator-code
コマンドを実行します:yo code
ここで新しいプラグイン(JavaScript)を選択し、拡張名を選択します(後で変更可能です)。このコマンドを実行すると、プラグインの初期化が完了します。
プロジェクト構造は以下の通りです:
.
├── .vscode
│ ├── launch.json // 拡張の起動とデバッグの設定
│ └── tasks.json // JavaScriptのビルドタスク設定
├── .gitignore // ビルド出力とnode_modulesを無視
├── README.md // プラグイン機能の可読な説明
├── src
│ └── extension.js // プラグインのソースコード
├── package.json // プラグインマニフェスト
├── jsconfig.json // JavaScript設定
プロジェクトの実行#
extension.js
を開くと、コメントがたくさんあるコードが見えます。ここで注意すべき関数は 2 つです:
- activate
プラグインがアクティブになるときに実行される関数です。
- deactivate
プラグインが破棄されるときに呼び出されるメソッドです。例えば、メモリを解放するなどです。
今回の開発は主にactivate
関数内で行います。では、このプロジェクトを実行してみましょう。extension.js
ページで F5 を押し、VScode プラグイン開発を選択します。すると、新しい VScode ウィンドウが開き、ここで開いたウィンドウで開発中のプラグインを実行できます。ctrl+Shift+P
を押し、プラグインのデフォルトの実行コマンドHello world
を入力すると、右下に小さなポップアップが表示されます。
これがプラグインを実行するためのデフォルトのコマンドです。
プラグインをより良く実行するために、package.json
に入り、設定を変更します:
"activationEvents": [
"onCommand:allblog.searchBlog"
],
"main": "./extension.js",
"contributes": {
"commands": [
{
"command": "allblog.searchBlog",
"title": "searchBlog"
}
]
},
ここを変更した後、プラグインの実行コマンドも同期して変更する必要があります:vscode.commands.registerCommand
でコマンド ID を拡張内の処理関数にバインドします。
今、新しく開いた VScode ウィンドウでReload window
コマンドを実行し、ウィンドウを再読み込みすると、再度プラグインを実行する際に、自分で定義したコマンドsearchBlog
を使用できるようになります。
基本機能の実装#
普段 RSS を購読する際、基本的に XML(拡張可能なマークアップ言語)形式であることに気づくでしょう。私たちの機能を実現するためには、これを解析して使用可能な Js コードで呼び出せる形式にする必要があります。ツールライブラリfast-xml-parser
を導入し、antfu 先生のブログをテスト例として使用します:
const vscode = require("vscode");
const xmlParser = require("fast-xml-parser");
async function activate(context) {
// RSSフィードを取得して解析
const response = await axios.get("https://antfu.me/feed.xml");
const articles = xmlParser.parse(response.data).rss.channel.item;
// 記事リストを保存
const articleList = articles.map((item, index) => ({
label: item.title,
description: item.description,
index
}));
...
ユーザーが自由に記事のリストを選択できるように、記事のリストを表示する必要があります。この時点で基本的な表示が実現しました:
しかし、この時点では記事をクリックしても何の反応もありません。結局、表示方法がまだ書かれていないからです😂
ここで VScode が提供する API を確認し、Webview APIがこの機能の実現に非常に適していることがわかりました。webview
を VScode 内で拡張が制御するiframe
として考え、以下のようにコードを修正します:
if (selectedArticle) {
const { link } = selectedArticle;
const webViewPanel = vscode.window.createWebviewPanel(
'blogWebView',
'Blog Article',
vscode.ViewColumn.One,
{
enableScripts: true,
retainContextWhenHidden: true
}
);
// WebviewのHTML内容を設定
webViewPanel.webview.html = `
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: Arial, sans-serif;
}
</style>
</head>
<body>
<iframe src="${link}" width="100%" height="100%"></iframe>
</body>
</html>
`;
}
}
成功して開きました!
もう少し最適化して、ウィンドウの高さを自由に設定できるようにしましょう:
if (selectedArticle) {
const { link } = selectedArticle;
const heightInput = await vscode.window.showInputBox({
prompt: 'ウィンドウの高さを入力してください(px単位)',
placeHolder: '500'
});
const webViewPanel = vscode.window.createWebviewPanel(
'blogWebView',
customName, // カスタム名をタイトルとして使用
vscode.ViewColumn.One,
{
enableScripts: true,
retainContextWhenHidden: true
}
);
let height = parseInt(heightInput) || 500;
webViewPanel.webview.html = `
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: Arial, sans-serif;
}
</style>
</head>
<body>
<iframe src="${link}" width="100%" height="${height}px"></iframe>
</body>
</html>
`;
}
これで基本的な機能が完成しました。
最適化?#
この時点でコマンドを再度実行すると、すでに購読した RSS が以前のリンクとして表示されることに気づきます。これは非常に厄介です。購読する RSS が増えると、リンクだけでは記憶しきれないかもしれません。この時、カスタム名を追加して、購読した RSS を自分の習慣に合わせて記憶できるようにするのが良いでしょう。コードを修正します:
...
if (customName) {
// 重複するカスタム名をチェック
const duplicateCustomName = Object.values(rssLinks).includes(customName);
if (duplicateCustomName) {
vscode.window.showErrorMessage('このカスタム名はすでに使用されています。別の名前を選択してください。');
return;
}
// 新しいRSSリンクと対応するカスタム名を追加
rssLinks[newLink] = customName;
vscode.workspace.getConfiguration().update(RSS_LINKS_CONFIG_KEY, rssLinks, vscode.ConfigurationTarget.Global);
await getArticleContent(newLink, customName);
}
これでカスタム名が追加されました。
🧐問題を発見し解決する#
次にプラグインを公開する段階です。ここでは関連する記事を自分で調べることができますので、詳しく説明することはありません。プラグインが成功裏に公開された後、プラグインをダウンロードし、自分の興味のある RSS ブログを追加しましたが、閉じて再度開いたときに、なんと!以前に購読した RSS が消えてしまいました!😭
問題は大したことではありません。問題を発見したら解決すれば良いのです。以前のコードを確認すると、すでに購読した RSS のデータ永続化処理を忘れていたことに気づきました。VScode の文書を調べると、データ保存の方法が 4 つあることがわかりました:
ここではExtensionContext.globalState
を使用してグローバルに保存し、データをユーザーのローカル設定ファイルに保存します。これにより、VScode を閉じても再度開いてもデータが失われることはありません。コードを修正します:
...
// 新しいRSSリンクと対応するカスタム名を追加
rssLinks[newLink] = customName;
// 購読情報をユーザーのローカルに保存
context.globalState.update(RSS_LINKS_CONFIG_KEY, rssLinks);
await getArticleContent(newLink, customName);
...
再度プラグインを公開し、完了です!これで簡素な RSS リーダープラグインが完成しました!
🐱まとめ#
現在、プラグインはすでにオンラインになっています(まだ正式版ではありません)。VScode でダウンロードできます:ダウンロードリンク、または VScode の拡張機能でRSS-searchBlogを検索してください。現在の機能はまだ不十分で、たとえば、購読後に更新があった場合に小さなポップアップで通知することができません。今後の更新でこのプラグインを改善していく予定です。以前、面白いオープンソースプロジェクトRSSHubを見たことがあり、奇妙な内容の RSS 購読源を生成できるものです。今後、このプラグインを RSSHub に接続し、機能を継続的に改善していくつもりです。正式版のプラグインが皆さんに満足してもらえることを信じています。ご覧いただきありがとうございます。このプロジェクトのソースコード:RSS-searchBlog