前言#
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