eetann's til
目的
Today I Learned の名の通り、学んだことを雑にメモしていく
Python の 判定文
当たり前だけどNone
が入る可能性のある文では
if hoge is not None:
print("if hoge is not None:")
のようにis
やis not
を使って判定する。
また、if 0
はFalse
になることを忘れてはいけない。
JavaScriptの正規表現のメタ文字エスケープ
JavaScriptの正規表現のメタ文字エスケープを一括で行うには、以下の関数でOK
function escapeRegExp(string) {
return string.replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&');
}
$&
はマッチした部分文字列全体を表す。
参考
ロジスティック回帰
配列のshapeを変更
以下のような警告が表示された。1次元のデータ(例(50,)
)が期待されているときに、行や列のベクトルになってしまっている(例(50,1)
)。
DataConversionWarning: A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel(). y = column_or_1d(y, warn=True)
以下のようにデータそのものを1次元に直せば良い。
y = y.values.ravel()
反復回数の指定
以下のような警告が表示された。要するに、指定した反復回数内では収束しなかったらしい。
ConvergenceWarning: lbfgs failed to converge (status=1): STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.
以下のようにmax_iter
を引数で指定してやる。
max_iter
はデフォルトでは100と指定されている。
model = LogisticRegression(max_iter=2000)
model.fit(X_train, y_train)
Pandasの指定行の型変換
指定した行に対して、numpyと同じようにastypeを使う
df['i'].astype(str)
データ分析
最初のうちはKaggleのノートブックを参考にすべき。英語で書かれているものの、頑張れば読める。Chrome拡張機能「Mouse Dictionary」と「Mouse Dictionary Kaggle support」を使えば頑張れる。
skimage.transform.resize
skimage.transform.resize
を使うと、リサイズされた返り値のnumpyの型はfloatになってしまう。
元の型を維持したい場合は、引数preserve_range=True
を指定する。
例
image = skimage.transform.resize(image, (height, width), preserve_range=True)
なお、次元(RGB方向)の指定はしなくても同じ数で埋めてくれる。
公式ドキュメント:skimage.transform.resize
Vimの挿入モードのCTRL-Hが効かなかった問題
試したこと
- ターミナルのせいだと思って別のターミナルに切り替え
- tmuxのせいだと思ってtmuxではなく普通に起動
- vimのせいだと思ってぐぐった(当たり)
:set backspace?
で確認したら空だったので以下を実行したら直った。
set backspace=indent,eol,start
ディレクトリの役割
今までよくわからなかったbinの違いがわかった
WSL2でzenn-cliのホットリロード効かない問題
作業場所を/mnt/c
以下から~
以下のどこかへ移して直った。
JavaScript importとrequireの違い
import : IEなどでは動かない
require: Node.jsのやつ
jsのimportとrequireの違い - Qiita
JavaScript async await と thenなど
asyncをつけた関数の中でawaitを使えば、thenを代用できる。
JavaScriptのasync/awaitを完全に理解する
環境情報確認コマンド
npx envinfo
実行例
System:
OS: Linux 4.19 Ubuntu 20.04.1 LTS (Focal Fossa)
CPU: (8) x64 Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz
Memory: 4.29 GB / 6.11 GB
Container: Yes
Shell: 5.8 - /usr/bin/zsh
Binaries:
Node: 12.18.3 - ~/.anyenv/envs/nodenv/versions/12.18.3/bin/node
Yarn: 1.22.5 - ~/.yarn/bin/yarn
npm: 6.14.10 - ~/.anyenv/envs/nodenv/versions/12.18.3/bin/npm
Managers:
Apt: 2.0.2 - /usr/bin/apt
pip3: 20.0.2 - /usr/bin/pip3
RubyGems: 3.1.2 - /usr/bin/gem
Utilities:
Make: 4.2.1 - /usr/bin/make
GCC: 9.3.0 - /usr/bin/gcc
Git: 2.25.1 - /usr/bin/git
IDEs:
Nano: 4.8 - /usr/bin/nano
Vim: 8.2 - /usr/local/bin/vim
Languages:
Bash: 5.0.17 - /usr/bin/bash
Go: 1.13.8 - /usr/bin/go
Perl: 5.32.0 - /home/linuxbrew/.linuxbrew/bin/perl
Python: 3.8.5 - /usr/bin/python
Python3: 3.8.5 - /usr/bin/python3
Ruby: 2.7.0 - /usr/bin/ruby
プログラム実行環境のメモだけではなく、プログラムそのものにも使えるそう。
もう少し踏み込んで使い始めたら記事にするかも。
Vimの起動が遅くなった(WSL2)
vim --startuptime startuptime.txt
で確かめたら、
069.149 000.070: loading after plugins
069.157 000.008: inits 3
069.260 000.103: reading viminfo
32414.768 32345.508: setup clipboard
32414.850 000.082: setting raw mode
32414.864 000.014: start termcap
クリップボードが怪しいらしい。
VcXsrcのアイコンにカーソルを持ってきたときの表示がCygwin/X なんちゃら
みたいにいつもと違った。
VcXsrcの設定いろいろいじったけど、結局はVcXsrcのアンスト&インストでもとに戻って、Vimの起動速度も元通り。
Bash テンプレ
読むだけでもめっちゃ参考になる。
説明だけ加えて dotfiles のテンプレに加えた。
Vim で特定の文字に挟まれている部分を選択する
ずっと使ってるmachakann/vim-sandwichにこの機能があることを忘れていたのでメモ。
<Plug>(textobj-sandwich-query-i)
がis
、
<Plug>(textobj-sandwich-query-a)
がas
に割り当てられている。
たとえば、以下で1
にカーソルがあってノーマルモードの場合、
hoge $\frac{1}{3}$ fuga
vis$
と入力すれば、
選択モードになって(v
)、
囲み文字入力待機状態になって(is
)、
囲み文字を指定すると($
)、
\frac{1}{3}
が選択された状態になる。
vas$
だと、囲み文字も入るので$\frac{1}{3}$
が選択される。
Figma でフォントスタイルが適用できないとき
フォントスタイルのフォントが使えないものだと適用できない。その場合はフォントを入れ替える。警告が出ているからわかると思う。
UbuntuでSuper-pの入力でディスプレイ設定が戻ってしまう問題
sudo apt install dconf-editor
dconf-editor
dconf-editor の
/org/gnome/mutter/keybindings/switch-monitor
で
デフォルト設定を無効にして、['<Super>p', 'XF86Display']
を[]
に変更
もし/org/gnome/settings-daemon/plugins/media-keys/video-out
もあったら同様にカスタマイズ
参考
gnome - How to disable global Super-p shortcut? - Ask Ubuntu
React 入門
すごくわかりやすかった。Vueと比べると、本当にJavaScriptが中心になっているのがよく分かる。
React Toutesのチュートリアルをやる
Nest
URL遷移時に今のページの指定した場所に表示させるなら、Route
をネストし、親側にOutlet
を追加する。
URLが定義されていないとき
path="*"
で設定できる。
URLが固定じゃないとき
/foo/hoge
のように固定ではなく、/foo/001
/foo/092
のように渡したパラメータによって変えたいときは、
path="hoge"
ではなく、path=":hoge"
とする。
パラメータ自体は、そのパラメータを使ったコンポーネントでlet params = useParams()
¶ms.hoge
のように取得する。
↑のパラメータを選択していない状態のとき=その親ルート に表示させたい内容は、同階層にindex
の属性をつけたRoute
を書いておく。
どのリンクがアクティブなのか
Link
ではなくNavLink
を使い、style属性またはclassName属性の引数としてisActive
を使って色とかを変える。
URLのSearch paramsとして扱う
let [searchParams, setSearchParams] = useSearchParams();
のようにして設定する。searchParams.get("hoge")
で?hoge=
の値を取得できる。
setSearchParams
をonChange
などに書いておけば、入力した時点で、URLのパラメータを随時変化させてくれる。
ただし、そのままだと遷移時に消えてしまう。そこで、NavLink
のラッパーとなるコンポーネントを作成し、let location = useLocation();
&location.search
を使うことで、遷移時にもURLのパラメータが維持できる。
NavLink
を使わずSearch paramsでisActive
let isActive = params.getAll("brand").includes(brand);
のようにすれば可能。
複数選択のパラメータにしたい時
searchParams
の append
メソッドや、filterを使って新しい URLSearchParams
を代入する。
自動で遷移させたい時
リンククリックなどの手動ではなく、ボタンクリック時に処理をしてから遷移させたいときにはuseNavigate
を使う。
Chrome拡張機能
v3
service worker
service workerとmanifest.jsonは同じディレクトリに置く。
The script used for "service_worker" must be located in your extension's root directory.
Manage events with service workers - Chrome Developers
現在のタブについて情報を取得
backgroundだとchrome.tabs.getCurrent
では取得できないため、 chrome.tabs.query
を使う。
Gets the tab that this script call is being made from. May be undefined if called from a non-tab context (for example, a background page or popup view).
Redux Tutorial
このメモは途中から。
- Redux storeを使えばいろんなコンポーネントからデータにアクセスできる
- ただし、すべてのデータをReduxに管理させなくても良い
- 必要に応じてReactのstateと使い分けるべき
-
reducer
の中ではidの生成のような予測できないランダムなことはしない。そのかわり、prepare
が使える
selectorロジックの使いまわし
useSelector
の中で特定のデータがほしいときに書いているstate => state.hoge
が何回も使うロジックになってきたら、createSlice
を書いているファイルにselectAllHoge
,selectHogeById
のような関数として書いておくと便利。
リクエストの状態について
状態をisLoading: true
みたいに書くこともできるけど、どうせ4つの状態が存在するならはじめから以下のように定義しておくと良いかも。
{
// Multiple possible status enum values
status: 'idle' | 'loading' | 'succeeded' | 'failed',
error: string | null
}
createAsyncThunk
第一引数はaction typeのprefixになる。
第二引数は実際にAPIのデータをとってくる処理を書く。
extraReducers
reducer
に定義していないcreateAsyncThunk
のようなものを書いておく???
createAsyncThunk
のリクエストが〇〇になったら、Aする。みたいな???
reducers と extraReducers の違い
reducers
は "action creater"を作り、アクションに対して応答するもの。
extraReducers
は 応答だけするもの。 createAsyncThunk
自体が"action creator"を使っているっぽい。
reactjs - What is difference between reducers and extrareducers in redux toolkit? - Stack Overflow
Redux Tutorial Part6
userページで何も表示されない
最初、以下のように書いていた。
export const selectUserById = (state, userId) => {
state.users.find((user) => user.id === userId)
}
これだと、何も返してないことになるので、括弧無しで一行にしたり、returnつけたり、括弧は外したりしてちゃんと返す。
export const selectUserById = (state, userId) =>
state.users.find((user) => user.id === userId)
notificationページで何も表示されない
エラー内容は以下。
Uncaught TypeError: Cannot read properties of undefined (reading 'map')
単純にconfigureStore
にreducerを登録していなかっただけだった。
useLayoutEffect
useEffect
は一回描画してから実行されるけど、useLayoutEffect
は描画される前に実行される。
- フック API リファレンス – React
- 初心者でも簡単にわかるReact useEffect, useLayoutEffectの使い方 | アールエフェクト
- useEffectのちらつきを無くしたいときの対処法【useLayoutEffect】
classnames
className
で複雑になってきたら使う。
React DevTools Profiler
以下の手順でどこが再レンダリングされたのかがわかる。
-
Start profiling
を押す - クリックとかする
-
Stop profiling
を押す
メモ化
Reactの用語かと思ったら違った。
以下はメモ化 - Wikipediaから引用。
メモ化された関数は、以前の呼び出しの際の結果をそのときの引数と共に記憶しておき、後で同じ引数で呼び出されたとき、計算せずにその格納されている結果を返す
一回実行したらそれをメモしておいて計算回数が減らせる。
たとえば、useSelector
の中でhogeArray.filter`を返すと、Array.prototype.filter()は毎回新しい配列を返すので、hogeArrayに関わる内容を変更していなくても各actionで再レンダリングが発生してしまう。
これをメモ化で解決できる。
Reselect
selectorをメモ化するライブラリ。createSelectorを使う。
まず、第一引数はinput selectorと呼ばれるもの。
input selector は「state を引数に受け取り、関心のある部分を返すだけの関数」
だからチュートリアルではAll系が書かれていた。
そして、第二引数はoutput selectorと呼ばれるもの。
「第一引数であるinput selector の返り値」を引数として受け取り、値を返す処理。
reselect - npmに書かれている例を見たら引数の対応がわかりやすかった。
分割代入で別名をつける
const {元の変数名: 新しい変数名} = オブジェクト
const o = {p: 42, q: true};
const {p: foo, q: bar} = o;
console.log(foo); // 42
console.log(bar); // true
Normalized State Structure
state構成の正規化?
idとかを配列でfindしてループになっちゃうよりも、オブジェクトのキーにしたほうが探すの楽。
- データを複製しない
- itemのIDをキー、内容を値とするルックアップテーブルでデータを保つ
createEntityAdapter
createEntityAdapter
で{ ids: [], entities: {} }
の形で実体を操作できる。データの保存先とかは変わらずstateで管理できる。
それ以外の値はgetInitialState
メソッドに渡す。
getSelectors
を分割代入すれば、selectAll
などが使える。ここで、別の変数名を割り当てておかないと、複数のcreateEntitiyAdapter
を使うときに面倒になる。
hogeAdapter.upsertMany(state, action.payload)
では一括で追加数rだけではなく、存在するitemをidに基づいてマージすることができる。
sliceで正規化したデータを扱うときに便利な関数が詰まったもの。
GraphQL
公式ドキュメントだと、手を動かそう、みたいなチュートリアルではないので以下の記事で学ぶ。
GraphQLは、過不足なくとってこれるAPIのためのクエリ言語。
一旦公式読む
公式の(Queries and Mutations | GraphQL)読んだ。
クエリと結果の対応がわかりやすい。
task(id: "10000")
で単体の取り出せるし、同じフィールドに対して別の引数を渡すときもAliases一緒に書ける。繰り返しになる部分はFragmentを使って二度書かなくていいようになる。
{}
じゃなくてquery Hoge
で名前をつけられる。前者は、operation typeがquery
であるときの省略記法。
$hoge
で変数が書ける。
directiveを使えば条件分岐も可能。
チュートリアルに戻る
スキーマのタイプ
- query
- Read Operation
- 問い合わせ
- mutation
- Write Operations
- 作成、更新、削除
- subscription
- リアルタイムのRead Operation?
ID型は一意の文字列。
続き
resolversの設定
(DNSにおける)リゾルバ (resolver)とは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
ApolloServer
では、gql
関数で定義したスキーマやどんな値が戻ってくるのかを書くresolversに書く。
以下のように自分で書いたオブジェクトが入れ子になっている場合、
type User {
id: ID!
myPosts: [Post]
}
resolversでもQuery
と同じ階層にUser:{ myPosts: hoge}
のように書けば良い。この時、myPosts
はparent
引数を使って親User
の結果を取得できる。
Prisma
Prisma - Next-generation Node.js and TypeScript ORM for Databases
ORM: Object Relational Mapping。SQLじゃなくてオブジェクトで操作できるように対応付け。
ORMとは?|SQLAlchemy 概要と基本の使い方
今はPrismaへ寄り道はしない。
TablePlus
エレガントなUIでデータベースを管理するツール
AURにはあるっぽいけど公式のインストール方法に掲載されてないから試すのはやめる。Prismaの続き
↓で使用感がわかった。
prisma.user.update({
where: { id: args.id },
data: { name: args.name },
});
Apolloのメモ
useQuery
を使うことで、データだけじゃなくてローディングやエラーもわかる。
完
宣言的とは
一言だけであとは勝手にやってくれる、ということ?
逆の「命令的」は順番に細かく指示する感じ?
- 命令的
- Imperative
- How
- 何をするか記述
- 命令を順番に処理するので、最終的な結果が前回の実行結果に依存する
- 宣言的
- Declarative
- What
- どんな状態か記述
- 状態そのものを記述するので、最終的な結果=状態が前回の実行結果に依存しない
参考
Apollo GraphQL チュートリアル
gqlテンプレートリテラルの中では、"
で囲った部分や"""
で囲って改行を含むdescriptionsが書ける。
ApolloServer
にはmocks
にモックデータを指定することができる。
React Context
コンテクスト – React
propsで親子間で渡していくのではなく、予めProviderで包んでおいてどこでも渡せるようにする。
Apollo Studio Explorer
GraphQLの管理、実行、作成ができるweb IDE。
The Apollo Studio Explorer - Apollo GraphQL Docs
クエリはポチポチしてくだけでできるし、コピーボタンもある。
data sources
GraphQLのAPIは複数のデータソースと接続できる。
REST API から取ってくるなら、 RESTDataSource
クラスを継承すれば良い。コンストラクタで baseURL
を設定できる。
resolvers
- parent
- 親のリゾルバの返り値
- args
- GraphQLの引数
- idとかはまずここから
- オブジェクトの中にオブジェクトとかなら ここからparentに渡る
- context
- authentication情報、データベース接続など
- 今回のチュートリアルなら
RESTDataSource
- info
- フィールドネーム、ルートからフィールドまでのパス?
- そんな使わない
Resolver Chains
分かりやすすぎるwww
parentの流れも分かりやすい
Explorer
responseはjsonだけじゃなくて表形式でも見れる。
Variable
client側でクエリの変数は useQuery
の引数でvariables
オブジェクトの中に渡す。
const {loading, error, data} = useQuery(GET_TRACK, {
variables: {trackId}
});
sever側ではschemaのtype Query{}
の中でクエリ名のあとの括弧の中に書く。
Mutationのresponseにcode
, success
, message
が含まれることは共通。
resolversではasync
, await
と を使ってこれらを含むようにreturnしないとだめ。 resolverで try/catch
を使うとエラーハンドリングしてreturnできる。
書く流れ
- server
- schema
- data source
- resolvers
- test @ Apollo Studio Explorer
- client
- query, mutation
- useHoge
- useQueryはその時点で実行されるけど、useMutationはその返り値である mutate function を実行しないとmutationされない
manifest v3 で HMR できるChrome拡張機能開発のためのプラグインを使った例
isolateModules
を false
にして、export も import もしていないファイルで警告が出るのを防ぐ。
インデックス型はRecordを使っても書ける
{[idx: string]: number}
と Record<string, number>
は同じ。
インデックス型 (index signature) | TypeScript入門『サバイバルTypeScript』
Numberじゃなくてnumberらしい
createEntityAdapterのsetAll
setAll
: accepts an array of entities or an object in the shape ofRecord<EntityId, T>
, and replaces all existing entities with the values in the array.
setAll
やsetMany
は配列だけではなくオブジェクトでも可。
Luaでは引数が1つの場合、関数呼び出しの括弧を省略することができます。
だから require("hoge")
と require"hoge"
どっちでも良かったんだね
clip-path
作ってくれる。
clip-path: polygon(70% 0, 100% 30%, 100% 0);
今作ってるChrome拡張機能ではRedux Toolkitを使ってるのでこの記事参考にテスト書きたい
メモ
npm install --save-dev\
typescript \
ts-node \
eslint \
prettier \
eslint-config-prettier \
eslint-import-resolver-typescript \
eslint-plugin-{import,prettier,react,react-hooks,unused-imports} \
@trivago/prettier-plugin-sort-imports \
@typescript-eslint/parser \
@typescript-eslint/eslint-plugin
場合による
npx tsc --init --rootDir src --outDir dist --module commonjs
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: "latest",
sourceType: "module",
},
plugins: ["react", "@typescript-eslint", "unused-imports", "react-hooks"],
rules: {
"react/jsx-uses-vars": 1,
"react/jsx-uses-react": 1,
"react/react-in-jsx-scope": "off",
"@typescript-eslint/no-unused-vars": "off",
"unused-imports/no-unused-imports": "error",
"unused-imports/no-unused-vars": [
"warn",
{
vars: "all",
varsIgnorePattern: "^_",
args: "after-used",
argsIgnorePattern: "^_",
},
],
"react-hooks/rules-of-hooks": "error", // Checks rules of Hooks
"react-hooks/exhaustive-deps": "warn", // Checks effect dependencies
},
settings: {
react: {
version: "detect",
},
},
};
module.exports = {
importOrder: ["^@core/(.*)$", "^@server/(.*)$", "^@ui/(.*)$", "^[./]"],
importOrderCaseInsensitive: true,
importOrderSortSpecifiers: true,
importOrderSeparation: true,
}
現在のブランチ名にissue番号があればコミットメッセージに含める
#!/bin/sh
# $1 COMMIT_MSG_FILE
# $2 COMMIT_SOURCE --ammend 判定に使用
if [ "$2" == "" ] ; then
ISSUE_NUM=`git rev-parse --abbrev-ref HEAD | sed -E "s/.*#([0-9]+).*/\1/g"`
sed -i "1i #$ISSUE_NUM" $1
fi
$ chmod +x .git/hooks/prepare-commit-msg
参考
プルリクがマージされたときに自動でブランチ削除したり、特定のブランチは削除されないようにする方法。
ポチポチするのとブランチ名タイプするだけでできた。
GitHub Actions
echo
とかのコマンドを実行するだけなら該当するリポジトリの情報はいらないけど、普通にlintとかformatするときはリポジトリの情報が必要になるため、actions/checkout@v3
を使う。
nodeを準備。
npm ci
を使うほうが良さそう。
npmにおけるキャッシュについて
Squoosh で画像をリサイズできるが、これはCLIもある。CLIでリサイズするときに指定するオプションは7つぐらい必要。ただし、全部指定しなくてもエラーにはならず、正常終了して何も起こらないので分かりづらい。
オプションを指定するのが面倒な場合は一旦Webで試してCLIコマンドとしてコピーするボタンを押してから実行するといいかも。
CLIだと一括実行とか書きやすい。
Chrome Extension icon用
まず、Web版でコピーできるコマンドにファイルしていを加えたもの。
npx @squoosh/cli --resize '{"enabled":true,"width":128,"height":128,"method":"lanczos3","fitMethod":"stretch","premultiply":true,"linearRGB":true}' --oxipng '{"level":2,"interlace":false}' -d hoge --suffix '-128x128' ./foo.png
次に、ファイルサイズを変数で指定するもの。
書き換え箇所が1つで済む。
zsh(ZLE?)のedit-command-line
を使うと更に書き換えやすくなる。
size=128;npx @squoosh/cli --resize '{"enabled":true,"width":'$size',"height":'$size',"method":"lanczos3","fitMethod":"stretch","premultiply":true,"linearRGB":true}' --oxipng '{"level":2,"interlace":false}' -d hoge --suffix '-'$size'x'$size ./foo.png
改行入れて見やすくしたもの。
size=48;\
npx @squoosh/cli \
--resize '{"enabled":true,"width":'$size',"height":'$size',"method":"lanczos3","fitMethod":"stretch","premultiply":true,"linearRGB":true}' \
--oxipng '{"level":2,"interlace":false}' \
-d hoge \
--suffix '-'$size'x'$size \
./foo.png
Chrome Extension の画像関連ここにまとまってたの知らなかった
CRXJS Vite Plugin のmanifestで怒られる
import manifest from './src/manifest.json'
で、resolveJsonModuleをtrueにしようねなどと怒られる。
Cannot find module './src/manifest.json'. Consider using '--resolveJsonModule' to import module with '.json' extension.
Module '"src/manifest"' can only be default-imported using the 'allowSyntheticDefaultImports' flag
File 'src/manifest.json' is not listed within the file list of project 'tsconfig.node.json'. Projects must list all files or use an 'include' pattern.
tsconfig.node.json
に手を加えれば解決。
{
"compilerOptions": {
"composite": true,
"module": "esnext",
+ "resolveJsonModule": true,
+ "allowSyntheticDefaultImports": true,
"moduleResolution": "node"
},
+ "include": ["vite.config.ts", "./src/manifest.json"]
}
拡張機能の更新をCLIで行う
chrome-webstore-upload-cliを使う。
Chrome Web StoreのAPIを用いて拡張機能のzipファイルをアップロード&公開してくれる。
最初に、Google APIのclientId
, clientSecret
, refreshToken
が必要になる。取得方法は以下。
How to generate Google API keys.md
コマンドは以下。
EXTENSION_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; \
CLIENT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; \
CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; \
REFRESH_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; \
npx chrome-webstore-upload-cli upload --source extension.zip --extension-id $EXTENSION_ID --client-id $CLIENT_ID --client-secret $CLIENT_SECRET --refresh-token $REFRESH_TOKEN --auto-publish
GitHub Actionsでできそう。
↓参考になりそうな情報
GitHubでブランチ名変えたら表示された。
git branch -m master main
git fetch origin
git branch -u origin/main main
git remote set-head origin -a
LinuxでMac風のキーバインドにする
k0kubun/xremapを使った。
環境は以下。
npx envinfo
以下が出力(長いのでちょっと削った)。
System:
OS: Linux 5.15 Manjaro Linux
CPU: (8) x64 Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz
Shell: 5.9 - /usr/bin/zsh
Binaries:
Node: 16.14.0 - ~/.volta/tools/image/node/16.14.0/bin/node
npm: 8.3.1 - ~/.volta/tools/image/node/16.14.0/bin/npm
Managers:
Cargo: 1.62.1 - /usr/bin/cargo
Utilities:
Make: 4.3 - /usr/bin/make
GCC: 12.1.0 - /usr/bin/gcc
Git: 2.37.1 - /usr/bin/git
Clang: 14.0.6 - /usr/bin/clang
Languages:
Bash: 5.1.16 - /usr/bin/bash
Rust: 1.62.1 - /usr/bin/rustc
物理キー | 入れ替え後 | mod | 役割 | i3 | Wezterm |
---|---|---|---|---|---|
ALT_L | SUPER_R | mod4 | Win | mod4 | Alt |
Ctrl_L | ALT_L | mod1 | Alt | mod1 | Alt |
CapsLock | SUPER_L | mod3 | MacのCtrl | なし | Ctrl |
SUPER_L | CTRL_L | control | CTRL | なし | Ctrl |
まず、公式のREADMEどおりにインストール。
AURのxremap-x11-bin
だとなぜかエラーが出るので、cargo install xremap --features x11
のほうにした。
nvim /etc/modules-load.d/uinput.conf
uinput
echo 'KERNEL=="uinput", GROUP="input", MODE="0660"' | sudo tee /etc/udev/rules.d/99-input.rules
設定ファイルを書く。
modmap:
- name: Except Wezterm
application:
not: org.wezfurlong.wezterm
remap:
ALT_L: SUPER_R
CTRL_L: ALT_L
CapsLock: SUPER_L
SUPER_L: CTRL_L
- name: Only Wezterm
application:
only: org.wezfurlong.wezterm
remap:
ALT_L: SUPER_R
CTRL_L: ALT_L
CapsLock: CTRL_L
SUPER_L: CTRL_L
keymap:
- name: Except Wezterm
application:
not: org.wezfurlong.wezterm
remap:
SUPER_L-a: home
SUPER_L-e: end
SUPER_L-h: backspace
SUPER_L-d: delete
SUPER_L-f: right
SUPER_L-b: left
SUPER_L-p: up
SUPER_L-n: down
SUPER_L-k: [Shift-end, backspace]
SUPER_L-Tab: CTRL-Tab
SUPER_L-Shift-Tab: CTRL-Shift-Tab
さらに、以下の記事を参考にして自動起動。
xremapをsystemctlで自動起動するメモ | hyoshi(hara) log
nvim ~/.config/systemd/user/xremap.service
[Unit]
Description=xremap
[Service]
KillMode=process
ExecStart=/home/eetann/.cargo/bin/xremap /home/eetann/dotfiles/etc/xremap.yaml
ExecStop=/usr/bin/killall xremap
Restart=always
Environment=DISPLAY=:0.0
[Install]
WantedBy=default.target
systemctl --user daemon-reload
systemctl --user start xremap
systemctl --user enable xremap
# 以下は不要かもしれない
sudo chown -R $(whoami) /home/eetann/.cargo/
modの割当も変える。
nvim ~/.Xmodmap
clear mod3
clear mod4
add mod3 = Super_L
add mod4 = Super_R
luaのコロンとドットの呼び出しの違い
function tablename:fn(...) is the same as function tablename.fn(self, ...)
ドットの方はself
が必要になる。
Luaの早期リターン
ただのreturn
じゃなくてdo return end
を使う。
function foo ()
do return end
end
問題
chrome.storage.local.set
を使っているときに、以下のエラーが出た。
Error handling response: TypeError: Cannot read properties of undefined (reading 'local')
原因
permissionsに"storage"を指定しなかったため。
対策
manifestのpermissionsに"storage"を加える。
permissions: ["bookmarks", "storage"],
CRXJS Vite Pluginを使ってビルドしたmanifest.json
を見てみると、以下のようにtype
にmodule
が指定されている。
"background": {
"service_worker": "src/background.ts",
"type": "module"
}
これでES modules仕様であるimport文を使えるようになるっぽい。
CRXJSはリロードする都合で、勝手に追加してくれてる。
Zennの記事のタイトルを更新したときにTwitterのカード?も更新したかったので、これを参考にした。
man -k hoge
の検索ができなくなったときの対策
Arch Linuxで現象
man -k hoge
を実行すると、以下のようになった。
nothing appropriate.
対策
man page - ArchWikiに書いてあった。
If you are getting a "nothing appropriate" message for every search, try manually regenerating the cache by running mandb as root.
sudo mandb
このスクラップについての記事を書いてみた。
daisyuiと使ってるときに、formatかけると出力がおかしくなる
問題
prettier-plugin-tailwindcss と daisyuiを一緒に使っていると、以下のように変な出力になる。
急に花が咲いたのでビビったw
対策
tailwind.config.js
でdaisyuiのログをオフにする。
module.exports = {
//...
daisyui: {
logs: false,
//...
},
}
👇参考
疑問
@extend-chrome/storageのgetした時に、未登録のキーを指定したらどうなるのか?
調査
適当な箇所に以下を挿入して調査した。
getBucket("times")
.get()
.then((v) => console.log("times", v, Object.keys(v).length === 0));
getBucket("times")
.get("hoge")
.then((v) => console.log("times:hoge", v, Object.keys(v).length === 0));
getBucket("foo")
.get("bar")
.then((v) => console.log("foo:bar", v, Object.keys(v).length === 0));
以下、出力の例
times:hoge {} true
foo:bar {} true
times {なんか適当な値, …} false
結論
存在しないキーを指定すると、空のオブジェクトが返ってくることが分かった。
問題
Redux ToolkitのuseSelectorで引っ張ってきた値をuseEffectの依存配列に入れても、1回しか呼ばれない
↓WIP違うので要調査
# 原因
更新しているのはappearanceなのにそのキーのbucketを指定していた。
const appearance = useSelector((state: RootState) => state.appearance.bucket);
# 対策
useSelectorの指定を変える。
const appearance = useSelector((state: RootState) => state.appearance);
取得した値を見てみる。
以下で取得
const appearance = useSelector((state: RootState) => state.appearance);
以下で表示
{JSON.stringify(appearance)}
以下が結果。
{"appearance":{"location":"top-right"},"status":"idle"}
自分が想定してた出力は以下。
{"bucket":{"location":"top-right"},"status":"idle"}
npm run dev
=vite
を再実行したらできたw
Reactで挟むときのコンポーネントの書き方
しばらく触ってなかったら書き方を忘れてしまったのでメモ。
type Props = {
children: React.ReactNode;
};
const Foo: React.FC<Props> = ({ children }) => {
// ...
return <Hoge>{children}</Hoge>
↓参考
useContextでいろんなコンポーネントから値を更新する。
- AppのuseSateの返り値をProviderに渡す
createContextの引数は{} as Hoge
で良さそう
サンプルのChrome拡張機能作るときの手順
随時更新する
npm create vite@latest
cd hoge
npm install
git init
touch README.md
npm create vite@latest
の時点で.gitignore
は作成される。
ここらへんで一旦pushすると良さそう。
npm i @crxjs/vite-plugin@2.0.0-beta.4 -D
2022-11-06現在、crxjs/vite-pluginはlatestだとviteのバージョンと干渉するので、betaを使っている。
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { crx } from '@crxjs/vite-plugin'
import manifest from './src/manifest'
export default defineConfig({
plugins: [
react(),
crx({ manifest }),
],
})
import { defineManifest } from "@crxjs/vite-plugin";
export default defineManifest({
manifest_version: 3,
name: "Extend Storage Sample",
version: "1.0.0",
permissions: ["storage"],
action: {
default_popup: "index.html",
},
});
tsconfig.node.json
にmanifestを追加
"include": ["vite.config.ts", "./src/manifest.ts"]
npm i -D @types/chrome
npx eslint --init
npm i -D eslint-config-prettier \
eslint-plugin-{react-hooks,unused-imports}
env:
browser: true
es2021: true
extends:
- eslint:recommended
- plugin:react/recommended
- plugin:@typescript-eslint/recommended
- plugin:react-hooks/recommended
- prettier
parser: "@typescript-eslint/parser"
parserOptions:
ecmaFeatures:
jsx: true
ecmaVersion: latest
sourceType: module
plugins:
- react
- "@typescript-eslint"
- unused-imports
rules:
react/jsx-uses-react: off
react/jsx-uses-vars: off
react/react-in-jsx-scope: off
npm install --save-dev --save-exact prettier
echo {}> .prettierrc.json
拡張機能のoption pageのuseEffect内でfetch APIを実行したやつのメモ
(async () => {
const response = await fetch(
"https://www.jma.go.jp/bosai/forecast/data/overview_forecast/130000.json"
);
const result = await response.json();
console.log(result);
})();
Zod
Zodを使ってみる。
z.string().url()
のようなバリデーションもできる。
↓www
z.number().lte(5, { message: "this👏is👏too👏big" });
自分でバリデーションを定義したい時は.refine
を使う。
vitestのtoThrowErrorを使う時、expect
は以下のように関数で囲まないとだめ。
expect(() => getFruitStock('pineapples')).toThrowError(/diabetes/)
DynamoDBのBlack Belt読む
知らなかった単語などをまとめておく
2017年8月の公開であり、古いことに注意。
2022-11-29
-
SPOF(単一障害点 / シングルポイント障害)とは - 意味をわかりやすく - IT用語辞典 e-Words
- DynamoDBは単一障害点を持たない
- キャパシティユニット
- 1秒あたりに何回読み書きできるか、という単位
- 書き込みの1ユニット = 1KBまでを1秒に1回書き込みできる
- 読み込み(結果整合性)の1ユニット = 4KBまでを1秒に2回読み込みできる
- 読み込み(強い整合性)の1ユニット = 4KBまでを1秒に1回読み込みできる
- プロビジョンドスループット
- Read・Writeはそれぞれ25キャパシティユニットまで無料
*
- Read・Writeはそれぞれ25キャパシティユニットまで無料
気になったところは紙のノートにメモしていくことにしたのでここには追加で読んだ記事を貼っていく。
↓Consistent Readオプションって強い整合性のことだよね?と改めて確認したかったので読んだ
DynamoDBの料金の詳細が知りたくて読んだ。用語についても書かれてる!
DynamoDBの時系列データの例について知りたくて読んだ(Black BeltのP60 Time Series Tablesと関連)。
Black Beltの大小のデータが混在するとクエリのコストが高くなる、の意味が分からなかったので読んだ。「xKBごとにyCUを消費」が理由だったのが分かった!
Auto Scalingの仕組みが知りたくて読んだ(Black Beltには図が載っていただけだったため)
DAXのユースケースが知りたくて読んだ
DAXの対応言語も載ってる
DynamoDB StreamsのStreamViewTypeがよく分からなかったので読んだ
DynamoDB LocalのDockerがあるのか知りたくて読んだ
DynamoDBのグラレコ解説を読む
2022年6月1日の時点での情報。
- RCU = Read Capacity Unit
- WCU = Write Capacity Unit
- パーティションが自動で増えて負荷分散されるので、角ななクセスの集中を防げる
- テーブルサイズの超過で増える
- プロビジョンドモードなら、
(RCU / 3000) + (WCU / 3000)
の繰り上げ
-
水平スケールとは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
- 台数とかを増やす方。スケールアウト
CRXJSのバージョンアップで以下のようなエラーが出た。
The plugin "externalize-deps" was triggered by this import { crx } from '@crxjs/vite-plugin'
以下のリンクを見て、package.json
に"type": "module"
を加えたら直った。
現象
Chrome拡張機能でPlaywrightを使ってE2Eテストを書いたけど、なぜかうまく動かない
原因
npm run dev
(=npx vite
)の実行をやめてからnpx playwright test
を実行していたことが原因で、コードの変更が反映されていなかったため。
解決法
npm run dev
しつつテストする。tmuxのウィンドウをケチらない。
ちなみにheadlessをtrueにすると動かない。これは公式ドキュメントにも書いてあった。
Extensions only work in Chrome / Chromium in non-headless mode, launched with a persistent context.
以下のようにgオプションを使ってテストのタイトルからgrepして実行できる。
npx playwright test -g "Languages test" --reporter=list
問題
PlaywrightでChakra UIの要素を指定しようとしたらうまくいなかい
原因
Chakra UIのコンポーネント名は_react=Hoge
のように指定できないっぽい?
また、モーダルだと親子関係が変わるのでABC >> DEF
のような指定だとうまくいかない。
対策
DevtoolsでElementsをよく確認すること。
createAsyncThunkの中で他の関数をdispatchしたい
Redux ToolkitのcreateAsyncThunkの中で他の関数をdispatchしたい時は、以下のように第2引数(thunkAPI
)の中のdispatch
を取り出して使えば良い。
const addHoge = createAsyncThunk("hoge/foo",
async (arg: string[], { dispatch }) => {
dispatch(addManyHoge(arg))
// ...
}
問題
Playwrightで、E2Eを書いていたファイルを分割したら動かなくなった。
原因
分割後のファイル名がhoge.spec.ts
ではなかったため(specが無かった)。