Emacs でグローバル IP を取得してクリップボードにコピーする

(leaf request :ensure t :leaf-defer t) (defun globalip-me () (interactive) (request "https://globalip.me" :parser 'buffer-string :success (cl-function (lambda (&key data &allow-other-keys) (let ((globalip (substring data 0 (- (length data) 1)))) (kill-new globalip) (message globalip))))))
Read more →

Emacs の関数で文字列をコピーする

kill-new で文字列をコピーできる。 https://www.gnu.org/software/emacs/manual/html_node/eintr/kill_002dnew-function.html
Read more →

Stimulus の target に型をつける

https://stimulus.hotwired.dev/reference/using-typescript#define-target-properties import { Controller } from "@hotwired/stimulus" export default class MyController extends Controller { static targets = [ "input" ] declare readonly hasInputTarget: boolean declare readonly inputTarget: HTMLInputElement declare readonly inputTargets: HTMLInputElement[] }
Read more →

Rails の force_ssl を有効にしたまま Nginx から Strict-Transport-Security ヘッダーを追加する

force_ssl: true の際に ActionDispatch::SSL は必ず Strict-Transport-Security を付与する。 ssl_options の hsts に false を設定した場合にも max-age=0 でつけてくる。 Nginx のみで Strict-Transport-Security をつけるようにしたかった。 以下の issue で ssl_options の設定で HSTS ヘッダーを無効にする提案があった。 https://github.com/rails/rails/issues/48609 結果としては、Rails では HSTS ヘッダーを必ずつけるようにして安全側に倒す。 リーバスプロキシで HSTS ヘッダーを設定したい場合はリバースプロキシで Rails がつけた HSTS ヘッダーを削除せよとのこと。 削除コマンドも提示されていた。 https://github.com/rails/rails/issues/48609#issuecomment-1662511786 location @app { # … proxy_hide_header Strict-Transport-Security; add_header Strict-Transport-Security "max-age=31536000;"; # … } http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_hide_header ちなみに同じ値であっても重複してつけた場合は https://hstspreload.org/ で以下のようにエラーが出る Error: Multiple HSTS headersResponse error: Multiple HSTS headers (number of HSTS headers: 2).
Read more →

Strict-Transport-Security ヘッダーの max-age は 2 年が推奨

hstspreload.org で2年が推奨されている https://hstspreload.org/#deployment-recommendations また、Mozilla でも 2 年を推奨 https://wiki.mozilla.org/Security/Server_Side_TLS これらを受けて Rails も 2 年がデフォルトになっている。 https://github.com/rails/rails/pull/38345
Read more →

cURLコマンドでヘッダー情報のみ出力する

-I または –head オプションでできる。 $ curl -I https://example.com HTTP/2 200 content-encoding: gzip accept-ranges: bytes age: 500505 cache-control: max-age=604800 content-type: text/html; charset=UTF-8 date: Fri, 01 Mar 2024 05:28:20 GMT etag: "3147526947" expires: Fri, 08 Mar 2024 05:28:20 GMT last-modified: Thu, 17 Oct 2019 07:18:26 GMT server: ECS (sac/257F) x-cache: HIT content-length: 648 curl –head https://example.com HTTP/2 200 content-encoding: gzip accept-ranges: bytes age: 59493 cache-control: max-age=604800 content-type: text/html; charset=UTF-8 date: Fri, 01 Mar 2024 05:28:50 GMT etag: "3147526947" expires: Fri, 08 Mar 2024 05:28:50 GMT last-modified: Thu, 17 Oct 2019 07:18:26 GMT server: ECS (sac/2520) x-cache: HIT content-length: 648 cURL の man を抜粋
Read more →

routes.rb でリダイレクト

get '/stories', to: redirect('/articles') https://railsguides.jp/routing.html#%E3%83%AA%E3%83%80%E3%82%A4%E3%83%AC%E3%82%AF%E3%83%88
Read more →

Arch Linux で Kernel をダウングレードする

起動しなくなったためダウングレードする。 6.7.5 から起動しなくなったので 6.7.4 に下げたい。 Live USB から起動して以下のコマンドでダウングレードした。 mount /dev/nvme0n1p3 /mnt mount /dev/nvme0n1p1 /mnt/boot arch-chroot /mnt cd /var/cache/pacman/pkg ls -al | grep linux-6.7 pacman -U linux-6.7.XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Read more →

パスワード入力フォームのautocomplete

https://developer.mozilla.org/ja/docs/Web/HTML/Element/input/password https://developer.mozilla.org/ja/docs/Web/HTML/Attributes/autocomplete input type="pasword" の autocomplete は 2 種類ある new-password current-password サインアップとパスワードリセットでは new-password パスワードの Confirmation も new-password サインインでは current-password サインアップとパスワードリセットで、メールアドレスやユーザ名の入力とパスワードの入力が別ページになっている場合も ユーザ名・パスワードのフィールドはパスワードのフィールドと同じページに表示しないとパスワードマネージャがユーザ名・メールアドレスを保存できない。 入力の必要がないフィールドは CSS で表示しないようにしてもよい。 https://www.chromium.org/developers/design-documents/form-styles-that-chromium-understands/
Read more →

ローカルでRustの標準ライブラリのAPIリファレンスを見る

以下のコマンドを実行るうとブラウザが開き std の APIリファレンスを確認できる rustup doc –std std の API リファレンス以外にも Rust By Example や Rustlings などへのリンクが書かれている Rust Documentation を rustup doc で開くことができる
Read more →

input タグのプレイスホルダーの使用は避けよう

https://developer.mozilla.org/ja/docs/Web/HTML/Element/input メモ: placeholder 属性は、フォームを説明するためには他の方法ほど意味的に有用ではなく、コンテンツに予期せぬ技術的な問題を引き起こす可能性があります とあった。同じページ内の詳細を確認してみると どのように見えるかのヒントを提供するために使用されるもので、説明やプロンプトではない スクリーンリーダーがアクセスできない ユーザが入力していると非表示になる 自動ページ翻訳機能で翻訳されない が理由として挙げられていた。 c.f. : 入力欄(フォーム入力)要素 - HTML: ハイパーテキストマークアップ言語 | MDN #プレイスホルダーはアクセシブルではない メモ: 避けることができるのであれば、placeholder 属性を使用しないでください。 要素にラベルを付ける必要があるのであれば、 属性を使用してください。 とまで書かれているため使用は避けよう
Read more →

word-break: break-word は非推奨

https://developer.mozilla.org/ja/docs/Web/CSS/word-break メモ: word-break: break-word は非推奨ですが、指定した場合は overflow-wrap プロパティの値とは関係なく、 word-break: normal や overflow-wrap: anywhere と同じ効果になります。 break-word を使った場合 overflow-wrap プロパティの値とは関係なく、 word-break: normal や overflow-wrap: anywhere と同じ効果になります。 ということなので break-word のかわりに overflow: anywhere を使うことにする。 https://developer.mozilla.org/ja/docs/Web/CSS/overflow-wrap
Read more →

GNOME Keyring から SSH の機能が無効化されたので gcr-ssh-agent を導入する

GNOME Keyring パッケージを更新したところ、Git 操作で SSH 鍵のパスフレーズを求められるようになった。 1:46 から SSH の機能がデフォルトで無効化された。 ArchWiki に書かれている通り gcr-4 パッケージに含まれる /usr/lib/gcr-ssh-agent を有効化する。 yay -S gcr-4 systemctl enable –user gcr-ssh-agent 後は SSH_AUTH_SOCK 環境変数 に $XDG_RUNTIME_DIR/gcr/ssh を設定する。 VSCode や Emacs を GUI で使っているため .xprofile に設定した。 export SSH_AUTH_SOCK=$XDG_RUNTIME_DIR/gcr/ssh と設定した。
Read more →

keyword_init on Struct.new Is No Longer Needed in Some Cases

I occasionally use Struct class when I am programming with Ruby. From Ruby 2.5, objects can be initialized with keyword arguments if keyword_init: ture is passed to Struct.new. I had used this since then because it is more readable and flexible in most cases. From Ruby 3.2, keyword arguments are accepted by default. Film = Struct.new(:title, :director) # keyword_init: true is no longer needed from Ruby 3.2 Film.new(title: 'Inception', director: 'Christopher Nolan') # => #<struct Film title="Inception", director="Christopher Nolan"> It’s not such a gorgeous update but it definitely became more natural and convenient!
Read more →

Git のバンドルファイル

git clone でホスティング先から clone できないような場合にバンドルファイルを作成して共有することができる。 git bundle create repo.bundle HEAD main でバンドルファイルを作成する。 ファイルをもらった側は git clone repo.bundle repo でホスティング先から clone したのと同じように Git リポジトリを復元できる。 c.f. Git のさまざまなツール - バンドルファイルの作成
Read more →

Custom Scalars Should Have Spec URL in GraphQL October 2021 Edition

Today I learned that in the latest GraphQL specification (October 2021 Edition), when defining a custom scalar type, the GraphQL service should provide a URL of a human-readable specification. It can be provided via either the new built-in @specifiedBy directive or the specifiedByURL introspection field. The @specifiedBy directive takes the URL as its argument like this: scalar DateTime @specifiedBy(url: "https://tools.ietf.org/html/rfc3339") See Also https://spec.graphql.org/October2021/ https://github.com/graphql/graphql-spec/issues/635
Read more →

ESLint no-unused-vars Rule for TypeScript

The default no-unused-vars complains even for parameters in interface declarations. It does not mean you have to write an eslint-disable comment or put a _ prefix for these parameters every time. There’s an extended version of this rule for TypeScript. With disabling the default no-unused-vars and enabling @typescript-eslint/no-unused-vars, the problem mentioned here disappears. By the way, there’s an ESLint plugin that makes unused imports auto-fixable. This plugin uses either the default no-unused-vars or the other one.
Read more →

Better Use classnames

Merging two or more className could be a troublesome text processing. For instance, if you are not used to JavaScript’s undefined, and are not careful enough, you could end up embedding an unexpected “undefined” class without knowing. function Foo({ className }: { className?: string }) { return <div className={default-class ${className}}>foo</div> } // <Foo /> will be rendered as <div class="default-class undefined">foo</div> It can be avoided by setting its default value as an empty string, but still, there’s another minor problem.
Read more →

Generics and Arrow Functions in TSX Files

When a function needs a generic type as its return value, it can be written like this: const Foo = <T>(a: T) => a Of course, the same thing can be done in .tsx files but the syntax has to be slightly different. Since <T> could be interpreted as a JSX tag, the example above will cause a syntax error like JSX element ‘T’ has no corresponding closing tag.ts(17008). A trailing comma helps to avoid this ambiguity and make it clear as a list of generic types in TSX files.
Read more →

GraphQL Description in Markdown

Today I learned that GraphQL description allows Markdown syntax (CommonMark). Here’s an example GraphQL schema: type Query { """ The description will be interpreted as Markdown. Good to know :) * Hello * Hola * こんにちは """ whatever: String } Of course, GraphiQL will render the description as Markdown like this: See Also https://spec.graphql.org/June2018/#sec-Descriptions
Read more →

AWS CLIで指定したプロファイルを使う

–profile で指定するか、環境変数 AWS_PROFILE で指定できる。 シェルスクリプトでラップしていることが多いので AWS_PROFILE を使うのがよさそう。 cf. https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-profiles.html#using-profiles
Read more →

プロジェクト内の特定のファイルを自分だけgitignoreする

自分だけ EditorConfig や Language Server を使いたいときなど、ファイルを追加したいが他のメンバーに影響がでないようコミットはしたくない場合がある。 {PROJECT_ROOT}/.gitignore では差分が出てしまい、~/.gitignore では他のプロジェクトでgit管理している場合に困る。 プロジェクト内の特定のファイルを自分だけgitignoreするには、プロジェクトの .git/info/exclude に .gitignore と同じように除外ファイルを指定すればよい。。 cf. https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files#excluding-local-files-without-creating-a-gitignore-file
Read more →

YAML Anchors Do Not Have to Be Unique

Believe it or not, according to the YAML specification, anchors do not have to be unique. In other words, an anchor name can be reused like this: alpha: &foo # first one repeat: me bravo: *foo charlie: &foo # second one another: one delta: *foo Let’s say the YAML file name is a.yaml. Here’s an example result with Ruby’s YAML library: require 'yaml' yaml = YAML.load_file('a.yaml', aliases: true) p yaml['bravo'] # => {"repeat"=>"me"} p yaml['delta'] # => {"another"=>"one"} For what?
Read more →

Pathname#join ignores previous paths when absolute path passed

irb(main):009:0> Pathname('/foo').join('bar', 'baz') => #<Pathname:/foo/bar/baz> irb(main):010:0> Pathname('/foo').join('bar', '/baz') => #<Pathname:/baz> In second, join ignores first string because of second sring has absolute path format.
Read more →

GTMの同意の設定

GTM では Cookie の利用について同意をとったかどうかを設定できる。 https://support.google.com/tagmanager/answer/10718549?hl=ja GA において Cookie の利用について同意を取っていない場合は ping を送信することで Cookie とは関係なくアクセス数やコンバージョンを集計できる。
Read more →

Use SSH Agent Forwarding in Docker

version: "3.7" services: app: build: context: . environment: - SSH_AUTH_SOCK=/tmp/ssh-agent.sock volumes: - .:/usr/src/app - "$SSH_AUTH_SOCK:/tmp/ssh-agent.sock"
Read more →

Javascript Destructuring Assignment With Default Value

Destructuring assignments can have default values. const [one, two, three = "tres"] = ["uno", "dos"] console.log(three) // "tres" const { uno, dos = "two", tres } = { uno: "one", tres: "three" } console.log(dos) // "two" The same goes for function parameters. function foo({ uno, dos = "two", tres }) { console.log(dos) // "two" } foo({ uno: "one", tres: "three" }) See Also https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters#destructured_parameter_with_default_value_assignment
Read more →

Use ES Modules in your HTML files

Do you want to use ES Modules in your HTML files? It’s easy! Just specify type="module" for the script element. ./lib/hello.js const hello = () => alert("Hello!") export default hello ./index.html <script type="module"> import hello from "./lib/hello.js" hello() </script> You also want to import and use React, right? In that case, you need to find the URL for React distributed as ES Modules. Hmmm… resolving dependencies seems to be a challenge too.
Read more →

Disabling bin/rails console Autocomplete Feature

IRB provides an autocomplete feature today. It’s really great but since it makes full use of escape sequences, sometimes could cause trouble when sharing a terminal with others over the internet (using Visual Studio Code Live Share, tmate, or some such). Today I learned that the autocomplete feature can be disabled temporarily by passing –noautocomplete option. irb: irb –noautocomplete bin/rails console: bin/rails c – –noautocomplete See Also https://www.ruby-lang.org/en/news/2021/12/25/ruby-3-1-0-released/ https://ruby-doc.org/stdlib-3.1.2/libdoc/irb/rdoc/IRB.html#module-IRB-label-Command+line+options https://docs.ruby-lang.org/en/master/IRB.html
Read more →

Apollo Client useMutation Takes onCompleted Callback

Today I learned that the useMutation API which Apollo Client provides takes onCompleted callback function. The callback will be called when the mutation successfully completes. const MyPage: NextPage = () => { const router = useRouter() const [theMutation, { loading, error }] = useMutation(THE_MUTATION, { onCompleted() { router.push('/transition-to-here-after-the-mutation') }, }) // the rest of the component implementation goes here… } The onCompleted option is listed in the document for sure and I should have known it but somehow been overlooking it.
Read more →

Crash Course Supervisord on Docker

Want to run multiple processes on a single container? That’s where Supervisord comes into play. Supervisord is a process management tool and it is easy to set up on top of Docker images. Originally, I wanted to set up a VNC server on an Ubuntu-based image (Playwright). To that end, I had to run the following commands on the same container: Xvfb: display server x11vnc: VNC server fluxbox: window manager websockify: proxy to serve noVNC client Since Docker’s entrypoint runs only one process I needed something that invokes and takes care of these 4 processes.
Read more →

Docker Entrypoint That Takes Args Needs to Be Array

Dockerfile’s ENTRYPOINT instruction accepts both string or array as its argument. However, the specified entrypoint won’t take any argument if it is passed as a string. Because of that, it should be an array if the entrypoint is intended to take arguments. For example, images created by the Dockerfile below do not take any arguments: FROM debian:11-slim ENTRYPOINT "/bin/bash" # passing as a string That’s why the following docker run command does not output anything.
Read more →

Proxy HTTP Requests for localhost

Let’s say you want to proxy http://localhost:4000 to somewhere else like http://another-host:4000. Then you can simply do that with socat(1).

socat TCP-LISTEN:4000,fork,reuseaddr TCP:another-host:4000