Closed20

Chrome拡張機能 notion-tweaks 作成日記

💡アイデア集

実装するとは言ってない.

  • Vivaldiのウェブパネルに表示するぐらいの幅のときは,左右の余白を小さくする
  • キーバインド
    • デイリーノートへ
    • 新しいノートの生成
    • 時間をすぐに入力
    • タイトルをコピー
      • @を使ったページリンクのために実装しようと思ったけど,@を使わなくても普通にNotionのページのURLを貼り付けたらMention Pageボタンから変換できることがわかったので実装しない
      • 出てきたスラッシュコマンドのメニューを閉じる
  • 検索結果を横に表示
  • リスト表示の階層を見やすく
  • コードブロック
    • 余白を狭くする
  • 言語を常に表示
  • ※の後の背景色や文字色を変更
  • Titleやaliasプロパティがあればリンク化するボタン
    • 論文名をいちいちフルで書きたくない
    • 表記ブレ気にせず使える
  • スラッシュコマンドのポップアップ
    • もう必要ないなら閉じる
    • emojiで no resultなら非表示
      • 厳密に取得するのが面倒なので一旦保留
  • `を入力するときに前後に半角スペース無しでもインラインコードになってほしい
  • 現在ブラウザで開いているタブの中からNotionだけを抜き出してfzf的に移動
  • Notion内の検索の結果からタイトルをコピー
  • 特定のページにすぐノートを作れるようにしたい
    • Obsidianの選択中のテキストを差し込むやつも真似できたら嬉しい

Zennって- [ ]とか- [x]でチェックリスト表示できるのか.

VivaldiのChrome拡張機能を開発するときにservice worker周りのエラーが出る

問題点

自作拡張機能を自動リロードさせようとservice workerを使おうとしたら, An unknown error occurred when fetching the script.Service worker registration failed といったエラーがVivaldiで出る.

調査

Chromeでは出ない.
Can't get started with developing an extension in Vivaldi | Vivaldi Forum
どうやら,Vivaldiではダメそう.

解決

拡張機能の開発はChromeで行う.開発中のものをVivaldiで使いたい場合は,ビルドしたもの(=service workerを使わないもの)を読み込む

確定ではないけどメモ.

とりあえずできたところまでは普段使いしているVivaldiで動かしたいと思って,以下の手順なら動くっぽい.
自作拡張機能を動かせる.

  1. ビルド
  2. 「拡張機能をパッケージ化」
    この段階でService Workerのエラーは消える
  3. パッケージ化した拡張機能のファイル(拡張子crx)を拡張機能一覧にD&D
    ファイル名は拡張機能のビルドしたディレクトリ名で,そのディレクトリよりも上の階層に保存されていた
    このままだとService Workerが起動しない
  4. ブラウザを再起動
    これでService Workerが起動する

現時点でのVivaldi安定最新版 4.3.2439.44 では,このService Worker周りのエラーは解消されたっぽい!やったね!

ページ幅が狭いときは左右の余白を小さくする

単純にウィンドウサイズが小さいときだけではなく,Vivaldiのウェブパネルやタイリングのためでもある.
↓通常の例(ウェブパネルで表示)
余白がすごい

↓CSSを挿入してページを狭くした例(ウェブパネルで表示)
余白を小さくした

左側はドラッグはできるくらいの幅にした.「+」の位置までカーソルを持ってくるとサイドバーが表示されるけど,とりあえず無くても今の所良さそう.
改善するとしたら,サイドバーの表示をいじる.

NotionのAPIで連携したいデータベースは,画面右上からintegrationを許可する必要がある.
Share画面

Chrome拡張機能にキーボードショートカットを追加

"global": trueはChromeにフォーカスが無い時でも有効にしたい場合のみ加える.

manifest.json
{
  "name": "extension name",
  ...
  "commands": {
    "feature_name": {
      "suggested_key": {
        "default": "Ctrl+Shift+1"
      },
      "description": "hgoehgoe",
      "global": true
    }
  },
  ...
}
background.js
chrome.commands.onCommand.addListener(function(command) {
  if (command == "feature_name") {
    console.log("Hoge!");
  }
});

Chrome ExtensionとGoogle Apps Script(GAS)を連携する

拡張機能のコードやstorageにAPIキーを保存したくないため,GASと連携させる.

GASで最初にやってもらうこと

  1. コードの貼り付け
  2. スクリプトプロパティにAPIキーを保存する関数のみ実行
  3. ↑の関数のみ削除

実際の流れは

  1. 拡張機能からGASを呼び出す
  2. GASでAPIを叩く
  3. GASから拡張機能へ結果を返す

GASのURLは「デプロイをテスト」でできた.
GASのURLがリダイレクトされるため,manifest.jsonのパーミッションは2つ書く.

manifest.json
{
  "manifest_version": 3,
  ...
  "host_permissions": [
    "https://script.google.com/",
    "https://script.googleusercontent.com/"
  ],
  ...
}

Update databaseはデータベースそのもののタイトルやプロパティのUpdate.
Create a pageでデータベースにアイテムを追加できる.
ドキュメントにも,

Creates a new page in the specified database or as a child of an existing page.

と書いてある.

すごい勘違いしてた.

進捗報告2021-10-03

今日のページを開く

拡張機能のstorageに今日のページがあるか確認し,
あればそのページを開く.なければ,↓

GAS経由で今日のページが作成されたか確認し,
作成済みであれば

  1. そのページを拡張機能のstorageに保存
  2. そのページを開く

作成していなければ

  1. GAS経由でページを作成
  2. そのページを拡張機能のstorageに保存
  3. そのページを開く

今日のページの作成

  • タイトルは今日の日付でフォーマットは YYYY-MM-DD
  • Dateプロパティに今日の日付を指定
  • 本文として heading_1を2つ挿入

進捗報告2021-10-09

options_pageの作成

デザインてきなものは後で直す.
やばい画面

初めてちゃんとReactとTypeScriptを使ってみた.
FormにはReact Hook Form と MUIを使っている.

chrome.storage.localのラッパー

chrome.storage.local系のものを,JSONに直したりパースするのを忘れがちだったり,awaitとかを使いたいので書いた.

export const getStorage = (key: string) => new Promise(resolve => {
  chrome.storage.local.get(key, (data: any) => {
    if (typeof data[key] === "undefined") {
      resolve(null);
      return;
    }
    resolve(JSON.parse(data[key]));
    return;
  });
});


interface storageType {
  [key: string]: any;
}

export const setStorage = (key: string, value: any) => new Promise(resolve => {
  const setObj: storageType = {[key]: JSON.stringify(value)}
  chrome.storage.local.set(setObj, () => {
    resolve(true);
  });
});

export const clearStorage = () => new Promise(resolve => {
  chrome.storage.local.clear(() => resolve(true));
});

まだTypeScript使い始めたばかりなので,書き直すかも.

非同期処理 — 仕事ですぐに使えるTypeScript ドキュメント

進捗報告2021-10-10

ページ幅が狭いときのタイトルの右の余白を小さくする

続き.
タイトルの右側の余白を小さくした.
左側の「+」の位置までカーソルを持ってくるとサイドバーが表示されてしまう問題を無視していたけど,その余白も残しておくことにした

↓前回までの改善(ウェブパネルで表示)
Before

↓今回までの改善(ウェブパネルで表示)
After

もう少し微調整したいけど,CSSと格闘するのは飽きたので今はやらない.

進捗報告 2021-10-14

タイムスタンプ

フォーマットHH:mmでタイムスタンプをショートカットキーからすぐに挿入できるようにした.これで,どのOSからでもIMEとか他のツールの設定無しにすぐタイムスタンプを挿入できる!
タイムスタンプはNotionのデイリーログページに使っている.

あとでフォーマットを変えたくなるかもしれない&&自分でフォーマットを変換するのは面倒なので,Day.jsでフォーマット変換を行っている.

webpackの設定とmanifest.json

webpackの設定で,

webpack.common.js
module.exports = {
 ...
  optimization: {
    splitChunks: {
      name: 'chunk',
      chunks(chunk) {
        return chunk.name !== 'background';
      },
    }
  },
  ...
}

のようにchunk.jsでバンドルしているため,以下のように2つのファイルを指定することを忘れないこと(ここでめっちゃ詰まった).

manifest.json
  ...
  "content_scripts": [
    {
      "matches": ["https://www.notion.so/*"],
      "css": ["content.css"],
      "js": ["content.js", "chunk.js"]
    }
  ],
  ...

ショートカットキーにprefixを実装

ショートカットキーをこの拡張機能でたくさん設定するわけにはいかないので,ctrl + qをprefixとした.
たとえば,ctrl + qを押したあとにaを押せば機能A,ctrl + qを押したあとにbを押せば機能Bという感じで呼び出せる!
参考: キーボード: keydown と keyup

進捗報告2021-10-15

コードブロックの調整

  • 言語を常時表示化
  • 「1行空行がある?」「エンター押しすぎた?」って自分はよく勘違いするので,下のパディングを狭くした

コードブロック

メニューを閉じる

スラッシュコマンドと絵文字の入力中に表示されるメニューを,ショートカットキーで閉じることができるようにした.
本当はemojiで no resultなら自動で非表示にしたかったけど,厳密に取得するのが面倒なので一旦保留.

進捗報告2021-10-24

オプション画面の変更

MUIとReact Hook Formをちゃんと使ってそれっぽい画面に変更した.
オプション画面

APIを直接叩く選択肢も用意した

GAS経由だとどうしても嫌な人いるかも知れないので,NotionのAPIキーを直接chrome.storageに保存する選択肢も用意した(良いことではない).
NotionのAPIキーの使用注意はドキュメントに記載することにする.

特定のデータベースにすぐページを作成

特定のデータベースのidを設定しておけば,すぐにページが作成され,開いているページにリンクを差し込めるようにした.
もし文字列を選択していた場合は,その文字列がタイトルに置き換わる.
現時点では,ctrl + q + zに割り当てている.

その他メモ

自分の普段使いにはほどんど困らないようになった!
とりあえずこの時点でのデモ付きのドキュメントをさっさと作ることにする.
ドキュメント(というかREADME)の変更はすぐに適用したいので,GitHubのREADME.mdに書いておき,Chrome Extension内にはそのリンクのみ貼ることにする.

進捗報告

設定画面で機能のオンオフの切り替えをできるようにした.
オプション画面

このスクラップは28日前にクローズされました
作成者以外のコメントは許可されていません