Teruhiro Komaki's Diary (Archive)

2024年04月

author
Teruhiro Komaki komaki.dev
2024年 04月 05日 金曜日
08時00分

Eleventy(11ty)のCanaryバージョンのインストール

Eleventy(11ty)公式のImageプラグインを確認したところ、非常に便利そうなので、この日記サイトに導入をしようと思い、早速インストールしました。

npm i -D @11ty/eleventy-img

.eleventy.jsを編集し、buildしたら、エラーが表示されました。

ドキュメントをみると、Canaryバージョンのインストールが必要とのことで、v3.0.0-alpha.5をインストールしました。

npm i @11ty/eleventy@canary --save-exact -D

Calling all courageous canary testers for Eleventy v3.0 — Eleventy

公式のImageプラグインについて

Low level utility to perform build-time image transformations for both vector and raster images.
Output multiple sizes, save multiple formats, cache remote images locally.
Uses the sharp image processor.

Google翻訳
ベクター画像とラスター画像の両方に対してビルド時の画像変換を実行する低レベルのユーティリティ。
複数のサイズを出力し、複数の形式で保存し、リモート画像をローカルにキャッシュします。
シャープ製画像処理エンジンを採用。

Image — Eleventy

どのように便利になったのか?

導入前

<figure>
  <img src="{{ page.url }}2024-04-05_03-51-38.png" alt="Snagit 2024 の新機能" width="2400" height="3138">
  <figcaption>Snagit 2024 の新機能</figcaption>
</figure>

導入後

<figure>
  {% image page , "2024-04-05_03-51-38.png", "Snagit 2024 の新機能" %}
  <figcaption>Snagit 2024 の新機能</figcaption>
</figure>

build後のHTML

<figure>
  <picture>
    <source type="image/webp" srcset="/2024/04/04/1500/2024-04-05_03-51-38-400w.webp 400w, /2024/04/04/1500/2024-04-05_03-51-38-800w.webp 800w, /2024/04/04/1500/2024-04-05_03-51-38-1280w.webp 1280w, /2024/04/04/1500/2024-04-05_03-51-38-1500w.webp 1500w, /2024/04/04/1500/2024-04-05_03-51-38-2000w.webp 2000w, /2024/04/04/1500/2024-04-05_03-51-38-2400w.webp 2400w" sizes="100vw">
    <img alt="Snagit 2024 の新機能" loading="lazy" decoding="async" src="/2024/04/04/1500/2024-04-05_03-51-38-400w.png" width="2400" height="3138" srcset="/2024/04/04/1500/2024-04-05_03-51-38-400w.png 400w, /2024/04/04/1500/2024-04-05_03-51-38-800w.png 800w, /2024/04/04/1500/2024-04-05_03-51-38-1280w.png 1280w, /2024/04/04/1500/2024-04-05_03-51-38-1500w.png 1500w, /2024/04/04/1500/2024-04-05_03-51-38-2000w.png 2000w, /2024/04/04/1500/2024-04-05_03-51-38-2400w.png 2400w" sizes="100vw">
  </picture>
  <figcaption>Snagit 2024 の新機能</figcaption>
</figure>

Shortcodeについては、別で投稿したいと思います。

author
Teruhiro Komaki komaki.dev
2024年 04月 04日 木曜日
01時00分

Snagit 2024 (24.2.3)にアップデートしたらクラッシュするようになってしまった

以下のスクリーンショットのように、#Snagitが起動できなくなってしまった。

Snagit クラッシュレポート
Snagit クラッシュレポート
Snagit 異常終了
Snagit 異常終了

私は、スクリーンショットを管理したり、編集するツールとして#Snagitを使っています。

以下の通り、2024-04-02にリリースされたバージョンの24.2.3をインストールしました。

Snagit (Mac)
Version: 24.2.3
Released: 2024 Apr 02
Operating System Compatibility: Check Now
File Size: 261.74 MB

ダウンロードリンクを確認すると、24.2.3の場合は、以下のようなので、一つ前のバージョンを指定してダウンロードできるか試みます。

ダウンロードリンク

https://download.techsmith.com/snagitmac/releases/2423/Snagit.dmg

一つ前のバージョンを確認しようと、サポートを見たらバージョン履歴というページがありましが、2024年分のバージョンについては、反映されていないようです。

Snagit(Mac)バージョン履歴 – TechSmith サポート

Snagit バージョン履歴
Snagit バージョン履歴

ひとつ前のバージョンが何だったのか、覚えていないため、分かりませんが、2423から推測し、2422を指定して、ダウンロードしてみることにしました。

無事ダウンロードでき、一つ前のバージョン24.2.2でアプリを置き換えました。

しばらく様子をみて、アップデートを試みたいと思います。

author
Teruhiro Komaki komaki.dev
2024年 04月 03日 水曜日
16時00分

AWS Lambdaの`event`を確認

API GatewayのGETメソッドでAWS Lambda関数を統合している場合に、eventで受け取る値を確認しました。

以下のような#AWS Lambdaを実行しました。

export const handler = async (event) => {

  console.log(JSON.stringify(event));

  const response = {
    statusCode: 200,
    body: JSON.stringify('Hello from Lambda!'),
  };
  return response;
};

API Gatewayからテスト

実行結果

API Gatewayからテスト
API Gatewayからテスト
{
  "resource": "/",
  "path": "/",
  "httpMethod": "GET",
  "headers": {
    "header2": "value2",
    "header1": "value1"
  },
  "multiValueHeaders": {
    "header2": [
      "value2"
    ],
    "header1": [
      "value1"
    ]
  },
  "queryStringParameters": {
    "param1": "value1",
    "param2": "value2"
  },
  "multiValueQueryStringParameters": {
    "param1": [
      "value1"
    ],
    "param2": [
      "value2"
    ]
  },
  "pathParameters": null,
  "stageVariables": null,
  "requestContext": {
    "resourceId": "zbkgq2150i",
    "resourcePath": "/",
    "httpMethod": "GET",
    "extendedRequestId": "Vo6HgFCYoAMFchg=",
    "requestTime": "03/Apr/2024:07:50:07 +0000",
    "path": "/",
    "accountId": "123456789123",
    "protocol": "HTTP/1.1",
    "stage": "test-invoke-stage",
    "domainPrefix": "testPrefix",
    "requestTimeEpoch": 1712130607770,
    "requestId": "05f4bb29-e600-4968-aeb8-12e062caa698",
    "identity": {
      "cognitoIdentityPoolId": null,
      "cognitoIdentityId": null,
      "apiKey": "test-invoke-api-key",
      "principalOrgId": null,
      "cognitoAuthenticationType": null,
      "userArn": "arn:aws:iam::123456789123:user/xxx-xxx",
      "apiKeyId": "test-invoke-api-key-id",
      "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",
      "accountId": "123456789123",
      "caller": "AIDAQGIBVCFDQW6HXLIGK",
      "sourceIp": "test-invoke-source-ip",
      "accessKey": "ASIAQGIBVCFDRFRRWRO5",
      "cognitoAuthenticationProvider": null,
      "user": "AIDAQGIBVCFDQW6HXLIGK"
    },
    "domainName": "testPrefix.testDomainName",
    "apiId": "vjs9lsoti0"
  },
  "body": null,
  "isBase64Encoded": false
}

自分用のメモでした。

author
Teruhiro Komaki komaki.dev
2024年 04月 03日 水曜日
14時00分

AWS Lambdaの`process.env`を確認

以下のような#AWS Lambdaを実行しました。

export const handler = async (event) => {

  console.log(JSON.stringify(process.env));

  const response = {
    statusCode: 200,
    body: JSON.stringify('Hello from Lambda!'),
  };
  return response;
};

実行結果

{
  "AWS_LAMBDA_FUNCTION_VERSION": "$LATEST",
  "AWS_EXECUTION_ENV": "AWS_Lambda_nodejs20.x",
  "AWS_DEFAULT_REGION": "us-east-1",
  "AWS_LAMBDA_LOG_STREAM_NAME": "2024/04/03/[$LATEST]066a5738b9ba4cc09d6e0c0a70f7e466",
  "AWS_REGION": "us-east-1",
  "PWD": "/var/task",
  "_HANDLER": "index.handler",
  "TZ": ":UTC",
  "LAMBDA_TASK_ROOT": "/var/task",
  "LANG": "en_US.UTF-8",
  "AWS_SECRET_ACCESS_KEY": "DZQ9rrfVi0oz9Nn4/iyZr81r4P3U9jH6K9bVt75q",
  "AWS_LAMBDA_LOG_GROUP_NAME": "/aws/lambda/tmp-20240403_143239",
  "AWS_LAMBDA_RUNTIME_API": "127.0.0.1:9001",
  "AWS_LAMBDA_FUNCTION_MEMORY_SIZE": "128",
  "LAMBDA_RUNTIME_DIR": "/var/runtime",
  "_AWS_XRAY_DAEMON_ADDRESS": "169.254.79.129",
  "AWS_XRAY_DAEMON_ADDRESS": "169.254.79.129:2000",
  "SHLVL": "0",
  "AWS_ACCESS_KEY_ID": "ASIAQGIBVCFD7EZXTHMZ",
  "LD_LIBRARY_PATH": "/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib:/opt/lib",
  "NODE_PATH": "/opt/nodejs/node20/node_modules:/opt/nodejs/node_modules:/var/runtime/node_modules:/var/runtime:/var/task",
  "AWS_LAMBDA_FUNCTION_NAME": "tmp-20240403_143239",
  "PATH": "/var/lang/bin:/usr/local/bin:/usr/bin/:/bin:/opt/bin",
  "AWS_LAMBDA_INITIALIZATION_TYPE": "on-demand",
  "AWS_SESSION_TOKEN": "IQoJb3JpZ2luX2VjEEYaCXVzLWVhc3QtMSJHMEUCIHaOAVEBa8742bDc8NqIX1ecHNJi3rTajSttzvVk4XvaAiEAvFoY1nR+GX3DuMgtRYEZ0QRyLbgG8lRCo/pvMbz2WMYq+gIIbxADGgwwMTM0MjUyNTA2MzEiDFYK7zAtz02PVUTQ5yrXAjp2DzTSnmE7mljD2vvM92SKKAVkGz4UtWfCsCbLaGIwPGsf/WHPTcMV/vJRF1VbOiMlEtbYOh4FVfn7Vhr/+GoiV9lIsOf7aILN7R/bvHVSTjZ0TdoraYLr6b5unKImPWMwwvTnbxQ4HyNitcc/DzfyGxbbtRsyAru8OUZJAc4knxhX7+M7yOe4Ula8678RoOD6RTQ4yyeH6zA6E/OrgReMJBG+hfthSRWeP1UACesfjiUOZMwvvSLUZHwuESgpbsvq8sBsv+UQ+Lc0tc8l9g6+bOijtQgDwITEerHmxQCf5qRTEirQbitkFxmMlOjyKGtZ8THbztV4/gc9XOyhXOrw0LpX6MywCr+xHhC3PD7ValT882pNRQ8I+5twQpfjVzVZybHlvU7VlL9B96DsmQfbzxEKz883MNb9yjqrNX9tJ5k0ofCfKfVPQ1QAR47phy5wAvDXqMYw3NSzsAY6ngGoft73ap2zAoTMCEvIxGP6eLyZQdcBhzKrSzFURSU9o3oZ5qTrP6huGuNKC+2P49rvsqp1Djqu3WtniNSXpBOFPWz4FnleByQOz6+x64SuXqKKtqTG2n1KIBZ9Yu5uUHSC8eaK4YyGY00AqRex/kpA5yN7wSGghvAOyPXlUo7pyZQ7uWNHiybypN9+zpnjY2Gl+aSCLPwEZThzUV4n9g==",
  "AWS_XRAY_CONTEXT_MISSING": "LOG_ERROR",
  "_AWS_XRAY_DAEMON_PORT": "2000",
  "_X_AMZN_TRACE_ID": "Root=1-660cea5c-31b5dc97257d60084e97c6d4;Parent=1dd3fa1526589d56;Sampled=0;Lineage=bf0b63a4:0"
}

自分用のメモでした。

author
Teruhiro Komaki komaki.dev
2024年 04月 03日 水曜日
01時00分

Webstormの文法(Grammar)の間違い

#Webstormが好きで、コードを書くときはもちろん、マークダウンを始め色々なケースで便利に使っています。

ふとしたときに、スクリーンショットのように、テキスト(確認することができます。)に下線(ハイライト)が表示されていることに気づきました。

文法 | WebStorm ドキュメント

テキストに下線(ハイライト)
テキストに下線(ハイライト)

選択肢のignoreを選択すると、次回から無視してくれるようになります。

なにかの拍子で、ignoreを選択してしまったのですが、その後、どこでignoreしたリストを管理しているのか気になったので、確認しました。

文法間違いをignoreしたリスト(Exceptions)

Settings->Editor->Natural Languages->Grammar and Style

文法間違いをignoreしたリスト(Exceptions)
文法間違いをignoreしたリスト(Exceptions)

万が一、間違ってignoreした場合もExceptionsのリストから削除することで、改めて文法間違いの設定を元に戻せます。

Cloudflare D1 Database GA: Production Ready

#CloudflareのD1が、GAになりました。D1をあまり素振りできていませんが、隙間を見つけて、素振りしたいと思います。

author
Teruhiro Komaki komaki.dev
2024年 04月 02日 火曜日
01時00分

<code>タグにコードを貼り付けるためのミニアプリを作りました

個人の日記や、会社のブログを投稿するうえで、<code>タグにHTMLや、様々なコードを貼り付けるケースが多く、適切にエスケープする必要があります。

今までは、以下のサイトのように、文字列をエスケープしてくれるサイトを使っていました。

マークアップとして間違って評価されないように、文字列をエスケープしてくれるサイトです。

Free Online HTML Escape / Unescape Tool - FreeFormatter.com

HTMLのエスケープをしてくれるサイト
エスケープをしてくれるサイト

しかし、このようなサイトは、バックグラウンドでどのようなことが起こっているか分からないので、あまり積極的に使いたくないな…と思っていました。

そこで、隙間時間を使い、上記のサイトの代替となりうる自分専用のミニアプリを作りました。

Code Escape for <code> tag

リリースしたミニアプリ
リリースしたミニアプリ

自分がほしいミニアプリが作れて、満足しています。

今回、初めてVite(Vite + Bootstrap + PostCSS)を使いました。

以下のコードを貼る際に、早速ミニアプリを使っています。

自分のメモのために、コードを貼っておきます。

vite.config.js

const path = require('node:path');
import viteCompression from 'vite-plugin-compression';
import {defineConfig} from 'vite';

/** @type {import('vite').UserConfig} */
export default defineConfig({
  root: path.resolve(__dirname, 'src'),
  base: '/',
  build: {
    outDir: '../dist',
  },
  server: {
    port: 8080,
  },
  plugins: [viteCompression()],
});

postcss.config.js

const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');
const purgeCss = require('@fullhuman/postcss-purgecss');

/** @type {import('postcss-load-config').Config} */
const config = {
  plugins: [
    autoprefixer(),
    purgeCss({
      content: ['src/**/*.html'],
      variables: true,
    }),
    cssnano(),
  ],
};
module.exports = config;

src/js/main.js

// Import our custom CSS
import '../scss/styles.scss';

const DEFAULT_PATTERN = `&<>"{}#$%'()*+-\/`;

const CodeElement = document.getElementById('code');
const PatternElement = document.getElementById('pattern');
const EscapedElement = document.getElementById('escaped');
const CopyButtonElement = document.getElementById('copy');

// CodeElement
CodeElement.placeholder = `For example...\n<tag></tag>\n{{ template }}`;
CodeElement.addEventListener('input', (e) => {
  updateEscapedElement();
});
CodeElement.addEventListener('input', (e) => {
  EscapedElement.value = escapeHtml(CodeElement.value);
  CopyButtonElement.disabled = !Boolean(CodeElement.value);
});

function updateEscapedElement() {
  EscapedElement.value = escapeHtml(CodeElement.value);
  CopyButtonElement.disabled = !Boolean(CodeElement.value);
}

// PatternElement
PatternElement.value = getPattern() ? getPattern() : DEFAULT_PATTERN;
PatternElement.placeholder = DEFAULT_PATTERN;
PatternElement.addEventListener('input', (e) => {
  setPattern(PatternElement.value);
  updateEscapedElement();
});

// CopyButtonElement
CopyButtonElement.addEventListener('click', (e) => {
  onClickCopy();
});

export function onClickCopy() {
  if (EscapedElement.value) {
    navigator.clipboard.writeText(EscapedElement.value);
  }
}

function escapeHtml(text) {
  const pattern = `[${PatternElement.value}]`;
  const regexPattern = new RegExp(pattern, 'g');
  return text.replace(regexPattern, (character) => {
    return '&#' + character.charCodeAt(0) + ';';
  });

}

function getPattern() {
  return window.localStorage.getItem('pattern');
}

function setPattern(value) {
  return window.localStorage.setItem('pattern', value);
}
よろしければ、使ってみてください。