OmniAICreator/Qiita-1.07M huggingface dataset:
seabornやmatplotlibで2つ以上のグラフを重ねて描く（いずれかのグラフが一意の値しか持たない場合）

先日`seaborn`や`matplotlib`でヒストグラムを書こうと思った時に苦戦したので、備忘録と併せて記事を書きます。

具体的には以下のような状況に陥りました。
・2つ以上のグラフを重ねて書きたい（2群以上あるデータを合わせてplotしたい）
・いずれかのグラフが一意の値しか持たない（ex. 0しか持たない）ためうまく表示されない

要するに右図のようなグラフを描きたかったのに、左図のようなグラフしか書けずに苦戦した、という訳です。
<p align="center">
    <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3891949/f0d811dd-23a2-5f73-c454-7f63ab1cd5b5.png" width=45%>
    <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3891949/1618f8f6-39ef-5d0e-f0b8-9132646e611b.png" width=46%>
</p>

## 環境
- google colab
    `matplotlib`== 3.8.0
    `seaborn`== 0.13.2


## うまくいかなかった実装例
```python:1群目を乱数で生成
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

# 1群目を乱数で生成
x1 = np.random.normal(loc=0, scale=10, size=100)
sns.histplot(x1, bins=10, kde=True)
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3891949/03dc09a1-c158-c683-4c12-e0fa136b6dc5.png" width=80%>


```python:2群目を乱数で生成
# 2群目は1つの値しか持たないのでnp.zerosで生成
x2 = np.zeros(20)
sns.histplot(x2, bins=10, kde=True)
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3891949/97dd43c6-d5c3-7843-1ca9-b062ca68965e.png" width=80%>

このように、それぞれ別々にグラフにすると表示されるのですが

```python:2群を重ねて描画
sns.histplot(x1, bins=10, kde=True)
sns.histplot(x2)
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3891949/f0d811dd-23a2-5f73-c454-7f63ab1cd5b5.png" width=80%>


重ねて表示すると太さが合わず、見た目が綺麗ではないです。
`bins`を調整するという手もありそうですが、細いグラフの集合体になってしまいました。
何より、`jupyter lab`ではオレンジの群が表示すらされませんでした。

※`matplotlib`を使って`plt.hist()`で実装しても同じ結果となりました


## 解決策
ここで考えたのが
・グラフに表示させなくていいくらい大きい値、もしくは小さい値を任意で追加する
・グラフの表示領域を指定し、任意で追加したグラフは見えないようにする
という方法です。
実装例は以下の通りです。

```python:2群を重ねて描画
# 2群目に任意の大きい値を追加
x2 = np.append(x2, 40)

# 重ねてヒストグラムを描く
sns.histplot(x1, bins=10, kde=True)
sns.histplot(x2, bins=10)
# グラフの表示領域を指定する
plt.xlim(x1.min()-2, x1.max()+2) # グラフの横に余白を持たせるため±2を追加
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3891949/1618f8f6-39ef-5d0e-f0b8-9132646e611b.png" width=80%>

このようにすれば見た目に違和感のない重ねたヒストグラムを描くことができました。


## 終わりに
もしもっといい方法があるよ、などあったら教えていただけると幸いです。
インタプリタとは

>インタプリタ（interpreter）は、コンピュータでプログラムを処理する方法の一つです。`プログラムの実行時にソースコードを1行ずつ機械語プログラムに変換するプログラム`のことでもあり、コードを読み込みながらその場で処理・実行していきます。インタプリタには日本語で「通訳者」という意味があります。
インタプリタに対応したプログラミング言語を「インタプリタ言語」と呼びます。インタプリタ言語には、JavaScript、Python、Ruby、PHP、BASIC、Lispなどがあります。
>
>インタプリタはプログラムを1行ずつ解釈・実行できるため、`プログラムが完成していない状態でも実行結果を確認することができます`。`プログラムの動作を確認しながら開発を進めることができるため、エラー箇所を特定しやすい`というメリットがあります。しかし、`1行ずつコードを読み実行していくことを繰り返すため、プログラムの実行速度が遅い`という課題もあります。
>
>インタプリタを使用するためには、`ソースコードのプログラミング言語に対応したインタプリタが、実行環境のコンピュータにインストールされている必要`があります。

https://www.ntt-west.co.jp/business/glossary/words-00246.html

* 機械語に変換するプログラム
* エラー箇所が発見しやすい
* プログラムが完成していなくても実行結果を確認できる
* プログラム実行速度が遅い
* 使用にはインストールが必要
Databricks Dashboard HTML埋め込み機能を試してみる


## はじめに

Databricks Dashboard に埋め込み機能が搭載されましたので実際に検証してみようと思います。

#### AI/BI ダッシュボード埋め込み機能とは

Databricks AI/BI ダッシュボードを外部の Web サイトやアプリケーションに埋め込む機能です。詳細は[こちらのドキュメント](https://docs.databricks.com/ja/dashboards/embed.html)をご覧ください。

## 機能を利用するには
### 1. ワークスペース管理者設定
まずは管理者の設定画面で、共有できるドメインの範囲を指定します。
[設定] - [セキュリティ] - [外部アクセス]に移動し、[埋め込みダッシュボード]で公開する範囲を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2206424/a45f51b4-24ef-5a5f-7f86-542f9660b8c4.png)

- 許可：ドメイン制限なく、どこにでも公開できます
- 承認済みドメインを許可：左の[管理]ボタンで公開可能なドメインを指定できます
- 拒否：埋め込み機能は利用できません

### 2. ダッシュボードの共有設定を行う

ダッシュボードの「共有」ボタンより、アクセスできるユーザーを指定できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2206424/51649153-08b9-1ca9-c130-ab1d5073d9ee.png)

- 個々のユーザーやグループを指定する場合は、上の[Only people with access can view]を選択します
- 同じアカウント内（このワークスペースに限らず、アカウントコンソールに登録されているユーザー)であれば誰でもアクセス可能にする場合は、[Anyone in my account can view]を選択します


下の [Embed dashboard]ボタンをクリックすると、共有可能な embed codeが表示されるのでコピーします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2206424/318b687b-c937-0b92-e6b6-47ebc678b2f1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2206424/ab7666a2-6442-9ffa-2647-03d86951480d.png)

## 実際にhtmlファイルを作成しアクセスしてみる。

始めは一番シンプルに iframeだけ入力したものを作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2206424/a5214365-929d-e51a-cb02-8fadbce94eda.png)

Chromeでこのファイルにアクセスすると、なぜかエラーに。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2206424/c91c9a69-cc88-56cc-c606-b78a28207850.png)

どうやら、Chromeではセキュリティ対策として、ローカルファイルから開いたHtmlファイルだと、iFrameでの外部接続がエラーになる模様。（[参考](https://ja.stackoverflow.com/questions/99529/%E4%B8%80%E9%83%A8%E3%82%B5%E3%82%A4%E3%83%88%E3%81%8Ciframe%E3%81%A7%E8%A1%A8%E7%A4%BA%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84)）


ということで、ローカルにWebServerを立ち上げて再度チャレンジ

### 簡易的なWeb Serverを立ち上げる

今回はこちらの Mongoose Web Serverを利用しました。
https://mongoose.ws/binary/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2206424/d55cd45c-52b6-fb6e-051e-f3fb45487423.png)

binaryをダウンロードして、権限を付与して、先ほどのhtmlファイルをこちらのディレクトリに置いて、起動するだけ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2206424/cb82841a-51c2-75fa-e91e-4d337bebf84c.png)

こちらの http://0.0.0.0:8000 (もしくは http://localhost:8000) にアクセスします。

認証画面が出てきました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2206424/32c4c868-8a42-4f08-0939-d32964cc7fae.png)

ログインすると、以下のように表示されました。（サイズはiframeの中で調整可能です）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2206424/c44dca3c-e30e-0074-bed1-780f65c1abb1.png)

## 参考

こちらに詳しい公式ブログが公開されてました。
https://www.databricks.com/jp/blog/how-embed-aibi-dashboards-your-websites-and-applications

Sharepoint , Confluence, Salesforce などにも共有できます。
ぜひトライしてみてください。
【Ruby】論理演算子

# はじめに
こんにちは！アメリカの大学で語学を学びながら、独学でソフトウェアエンジニアを目指している者です。
今回は、演算子の中でも論理演算子について触れたいと思います。
これまで学習してきた中でなんとなく使ってきましたが、しっかり理解できていなかった部分があったので、まとめてみました。

# 論理演算子
演算子は、`&` や `+=` のように、値の計算や操作に使われる記号や機能のことです。
今回はその中でも、論理演算子 `||` と `&&` に注目して解説していきます。
この2つの演算子は条件式で使われ、次のような特徴があります

* 左の式から順に評価される
* 論理式の真偽が決定すると、残りの式は評価されない
* 最後に評価された式の値が論理式の全体の値になる

### `||`を論理演算子として使う場合
まずは`||`についてみていきます。
```ruby
language || "Ruby"
```
`||` は、どちらか一方が真であればその値が返ります。
ここで、`language` が真であれば、次の `"Ruby"` は評価されません。
`language` が返り値となり、全体の結果になります。
反対に、`language` が偽なら `"Ruby"` が返されます。

では、この論理演算子の特徴をどのように生かすことができるのでしょうか。
まずは以下の例を見てください
```ruby:ifsentense.rb
name = "Ruby"
if language
  name = language
end
```
`if`の代わりに論理演算子 `||` を使うと、同じ処理を次のように1行で書けます

```ruby:ronri.rb
name = language || "Ruby"
```
わたしからしたら、さっきの式のほうがシンプルで見やすいですが、エンジニアの方はどうなんでしょうかね。
4行が1行に減るのはだいぶ少なくなったのではないでしょうか。


### `&&`を論理演算子で使う場合
上記同様にコードを見ていきましょう
```ruby
language && "Ruby"
```
`&&`は日本語でいうと「かつ」なので上記の`||`とは勝手が変わってきます。
`language`が真であれば、`Ruby`が評価されて、`language`が偽だった場合は最後に評価されたのが`language`なのでそれが返り値となります。

上記同様にif文で見てみましょう
```ruby
name = nil
if language
  name = "Ruby"
end
```
`name`に初期値として`nil`を代入しています。
`language`が真であれば、`name`に`Ruby`が代入されて、`language`が偽だった場合は`name`が`nil`のままということです。
これも論理演算子を利用して1行で書くことができます
```ruby
name = language && "Ruby"
```
1行なのでとてもすっきりしてますがやはりまだ経験が浅いと直観的にわからないですねｗ
もし、どっちが使われるかわかる方がいれば教えてください
ジョブカンのまとめ

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめA～M](https://qiita.com/Keiji_otsubo/items/f3ddedee6793bf1576f8)

--------------------

+ [ジョブカン経費精算/ワークフローAPI（β版）を使ってみる](https://qiita.com/Keiji_otsubo/items/7805d3fdc976178e2114)
+ [フローを使ってジョブカン経費精算/ワークフローAPI（β版）を呼び出す](https://qiita.com/Keiji_otsubo/items/7925dfad968c5a65b2fc)
+ [yoomを使ってジョブカンと連携する](https://qiita.com/Keiji_otsubo/items/e4f18fd155af5c6925b7)
+ [ジョブカンのフォームID](https://qiita.com/Keiji_otsubo/items/512786811d7f3fe502f6)
+ [ジョブカンに登録しているフォームの一覧を取得](https://qiita.com/Keiji_otsubo/items/458f6eb31251b93caa50)
【ChatGPT】深津式プロンプト・システム２をご紹介


　どうも、カーブミラーです。

　今回は、深津式プロンプト・システム２をご紹介します。

:::note info
本記事は、ChatGPT（有料版）
で行なっております。画像は
ありません。　あしからず。
:::
　まずは、ニュース。

　OpenAI o1正式版がリリース？

　海外のユーザーの一部では、
　　o1が来た、と話題に
　　　なっているそうです。

　[田中義弘さんポスト](https://x.com/taziku_co/status/1853216650293899690?t=lhck3XjyE5DTg2lOivBZug&s=19)

　少し調べてみましたが、
　　GitHub Copilotが
　　　OpenAI o1を組み込んだデモを
　　　　公開して、ウェイトリスト登録
　　　　　をしていました。
　　　　　　[GitHub公式ポスト](https://x.com/github/status/1853221709127520724?t=DYwpIoyMa2yAhi_AKx0rcg&s=19)

　これ以外に
　　これといったポスト等はなく、
　　　おそらく一部のユーザーに
　　　　期間限定のテスト目的で
　　　　　公開したのでしょう。

　課金ユーザーへの開放は
　　早くても、今月末ではないかと
　　　私は予想しています。

　根拠は、
　　ChatGPT公開２周年目に
　　　なるから、です。

　まぁ、
　　当るも八卦当たらぬも八卦な
　　　予想ですけどね😅
***
　さて、本題です。

　今回は、
　　深津式プロンプトの
　　　新たなバージョン、
　　　　“深津式プロンプト2”を
　　　　　ご紹介します。

　まぁ、
　　真新しくはないのですよ😅
　　　去年（2023年）の２月には
　　　　ほかの方が引用されて
　　　　　いましたからね。

　そういえば書いていなかったなぁ、と
　　気付いての記事化です。

　深津式プロンプトは
　　有名ですよね。

　私もこれを
　　一時期使っていました。
　　　少し変更してですが。

　ではまずは
　　深津式プロンプトのおさらい。
```Text:深津式プロンプト・システム１
# 命令書:
あなたは[プロの〇〇]です。
以下の制約条件と入力文をもとに[最高の〇〇]を出力してください。

# 制約条件:　[箇条書きで書いてください]

# 入力文：　[入力文章]

# 出力文：
```

　このPromptに必要事項を
　　書き込んで、送信すると、
　　　端的な指示よりも
　　　　良い出力が得られます。

　しかし、
　　書き込み事項が少ない場合、
　　　ChatGPTが勝手に盛ってくる
　　　　ことがあり、内容に納得
　　　　　できない場合が発生します。

　そこで
　　システム２を使うことで、
　　　納得できる内容に
　　　　近付けることが
　　　　　可能になります。

```Text:深津式プロンプト・システム２
# 命令書:
あなたは[プロの〇〇]です。
以下の制約条件と入力文をもとに[最高の〇〇]を出力してください。

# 制約条件:　[箇条書きで書いてください]

# 入力文：　[入力文章]

# 出力文：

このタスクで最高の結果を出すために、
追加の情報が必要な場合は質問をしてください。
```
　見ればわかりますが、
　　最後の一文を追記しただけです。

　これは
　　足らない情報を
　　　ユーザーに質問して
　　　　必要な回答を得ることで、
　　　　　より良い結果を
　　　　　　出力するものです。

　ただし、
　　必ずしも
　　　質問してくるわけでは
　　　　ありません。

　　書き込み内容が
　　　充分な場合や
　　　　穴埋めが可能だと
　　　　　質問をすることを
　　　　　　しません。

　　この点には
　　　注意が必要です。

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
colgroupについて理解する

:::note
### 概要
table内の列のグループを定義します。
子要素であるcol要素のspan属性の値によりスタイルを当てる列を決められます。
:::

# 背景
業務でcolgroupのスタイルを変更することでtable要素のセルの幅を変更しました。

```html
<colgroup>
    <col class="pct76">
    <col class="pct21">
    <col class="pct21">
    <col class="pct21">
    <col class="pct21">
</colgroup>
```

復習のため、colgroupについて勉強します。

# colgroupとは

https://developer.mozilla.org/ja/docs/Web/HTML/Element/colgroup

> 表内の列のグループを定義します

# サンプルコード

<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="wvVxgoY" data-pen-title="Untitled" data-user="uuylkesg-the-styleful" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/uuylkesg-the-styleful/pen/wvVxgoY">
  Untitled</a> by 山根大生 (<a href="https://codepen.io/uuylkesg-the-styleful">@uuylkesg-the-styleful</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# colとは

https://developer.mozilla.org/ja/docs/Web/HTML/Element/col

>表内の列を定義して、すべての一般セルに共通の意味を定義するために使用します。この要素は通常、`<colgroup>`要素内にみられます

`<col>` ではCSSを使用して列にスタイルを設定できます。以下が使用できるプロパティです。

https://www.w3.org/TR/CSS21/tables.html#columns

- border
- background
- width
- visivility

## span属性とは
`<col>`要素がまたがる列の数を示します。存在しない場合、既定値は`1`です。

<p class="codepen" data-height="300" data-default-tab="js,result" data-slug-hash="wvVxgmO" data-pen-title="Untitled" data-user="uuylkesg-the-styleful" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/uuylkesg-the-styleful/pen/wvVxgmO">
  Untitled</a> by 山根大生 (<a href="https://codepen.io/uuylkesg-the-styleful">@uuylkesg-the-styleful</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

理解する為に先ほどのサンプルコードのspan属性を試しに修正します。
１つ目のcol要素によって左から1番目の列は管理されています。
上から2つ目のcol要素は左から2列目以降の列が対象です。
上から2つ目のcol要素のspan属性を3,上から3つ目のcol要素のspan属性を1にします。

```html
<colgroup>
    <col /> //左から1列目
    <col span="3" class="batman" /> //左から2列〜4列目
    <col span="1" class="flash" />　//左から5列目
</colgroup>
```

すると、列の色が変わります。
The Flashの列も青色になりました。
class属性batmanは上から2番目のcol要素で指定されていて、これにより左から１列飛ばして、3列分スタイルが当てられています。

```css
.batman {
  background-color: #d7d9f2;
}

.flash {
  background-color: #ffe8d4;
}
```

# th要素のscope属性とは（おまけ）

https://developer.mozilla.org/ja/docs/Web/HTML/Element/th#scope

>この (`<th>`で定義されている) 見出し要素が関連するセルを定義します。次の値を取ることができます。
>- row: この見出しはその行に属するすべてのセルに関連します
>- col: この見出しはその列に属するすべてのセルに関連します
>- rowgroup: この見出しは行グループに属し、その中のすべてのセルに関連します
>- colgroup: この見出しは列グループに属し、その中のすべてのセルに関連します
>
>もし scope 属性が指定されていないか、その値が row, col, rowgroup, colgroup でない場合は、ブラウザーは自動的に見出しセルが適用されるセルの集合を選択します

今回のサンプルコードだと以下のth要素は列に関連しています
```html
<th scope="col">Batman</th>
```
以下のth要素は行に関連しています

```html
<th scope="row">Skill</th>
```

# 最後に
colgroupで列のスタイルを管理できることを手を動かして学べました。
引き続き業務から復習してキャッチアップしていきます。
USB to LAN アダプターを VLAN のトランクポートにしようとして失敗した

## やりたいこと

サーバー機では、ホストOSとゲストOS群とでネットワークを分けたいことがしばしばある。
ゲストOSが提供するサービスをユーザーから到達可能にしつつ、ハイパーバイザー管理であるホストOSにはユーザーから到達不可能にしておきたいケースなどが典型的だ。
その際、さらにゲストOS間のネットワークも分離したいケースでは、VLANのトランクリンクをハイパーバイザーの仮想スイッチに通し、それぞれのゲストOSは仮想スイッチのアクセスポートを通して独立のネットワークに接続させる。このような構成にしておくと、特定の部署向けのネットワークにのみ公開したいサービスを提供する仮想マシン（ゲストOS）をどのハイパーバイザー上で動作させるべきか、ということを、VLANのID以外で意識しなくて済む。

![VLANonHypervisor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186214/9d34d6cb-97d1-b35f-4d41-9528e49835e1.png)


ホストOSでハイパーバイザーとして Hyper-V を利用するケースでこれをどのように実現するのか経験が無かったため、事前に実験して作業手順を確立しておきたい。しかし、実験に利用できるのはごくふつうのオフィスマシンで、 Hyper-V は導入できるもののネットワークインターフェースカード (NIC) が1枚しか挿さっていない。
このマシンに USB to LAN アダプターを挿し、 NIC が 2 枚の状況を作成して前述の実験を試みたい、と考えた。

# 実験内容

* NIC1 として Realtek PCIe GBE Family Controller
  * 192.168.0.0/24
* NIC2 として ASIX AX88179 USB 3.0 to Gigabit Ethernet Adapter
* NIC2 のトランクリンクには VLAN タグ 10, 20 のフレームを流す
  * 10: 192.168.10.0/24
  * 20: 192.168.20.0/24
* 仮想スイッチはホストOSの Hyper-V 上から作成
  * [管理オペレーティングシステムにこのネットワーク アダプターの共有を許可する] はチェックを外す
* 仮想マシン1は仮想スイッチに VLAN ID 10 で接続。 IP アドレスは DHCP に任せる
* 仮想マシン2は仮想スイッチに VLAN ID 20 で接続。 DHCP サーバーを立てていないので IP アドレスは手動で固定

この手順で間違えることもなく設定完了。
何も問題なさそう……
と思っていたが、仮想マシンから上流に疎通が取れない。

一時的に [管理オペレーティングシステムにこのネットワーク アダプターの共有を許可する] にチェックを入れて、ホストOSから NIC2 のパケットをキャプチャしてみたが、タグ付きフレームが流れてきていないように見える。

トランクリンクの上流と NIC2 の間に挟んでいるスイッチングハブを外して直接接続にしてみたり、ネットワークアダプターの設定を見直してみたり、いろいろ試したのだが、どうにもうまくいかない。

# 解決

検索していて以下の情報を発見した。

https://hardwarerecs.stackexchange.com/questions/2422/usb-to-ethernet-adapter-supporting-multiple-virtual-lans

この記事によれば

> No known USB-to-Ethernet adapters that provides a Windows driver (for any version of Windows) with multiple VLAN support.

ということで、 USB to Ethernet には複数 VLAN をサポートするドライバーが無いらしい。

これを受けて NIC1, NIC2 を交換し

* NIC1 として ASIX AX88179 USB 3.0 to Gigabit Ethernet Adapter
* NIC2 として Realtek PCIe GBE Family Controller

としたところ、無事仮想マシンから上流に疎通が取れるようになった。

トランクリンクの上流と NIC2 の間にスイッチングハブを挟んでも問題なかった。
（デフォルトの挙動が「すべての VLAN タグを通す」ではなく「選択した VLAN タグのみを通す」というスイッチングハブも存在するので、これ自体は注意すべきポイントの一つであると思っている）

IEEE 802.1q はデフォルトでサポートされているものだと思い込んでいたが、今回のケースでそうではないと分かったのが学びであった。
CSSを学びたい Step24 flexbox-order

## はじめに
CSSを学びたいのStep24です。FlexBoxのorderについて学んでいきます！！

## 成果物
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/3f12d6ff-6190-d2e3-07a2-f71961a7d085.png)

## ソースコード
```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Flexbox Orderの例</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <h2>Flexbox Orderの例</h2>
  <div class="flex-container">
    <div class="flex-item" style="order: 3;">アイテム1</div>
    <div class="flex-item" style="order: 1;">アイテム2</div>
    <div class="flex-item" style="order: 2;">アイテム3</div>
  </div>
</body>
</html>
```

```css:styles.css
body {
  font-family: Arial, sans-serif;
  background-color: #f4f4f4;
  margin: 0;
  padding: 20px;
  text-align: center;
}

h2 {
  margin-bottom: 20px;
}

.flex-container {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
  background-color: #ddd;
  padding: 20px;
  border-radius: 10px;
}

.flex-item {
  background-color: #007BFF;
  color: #fff;
  padding: 20px;
  border-radius: 5px;
  flex: 1;
  text-align: center;
}

```

:::note info
htmlの記載順でなく、orderで定義した順番に適用されるようになりましたね！！ 
:::
Blink には WebKit からフォークしたときのソースコードがどれぐらい残っているのか？

いまだに「（レンダリングエンジンの） Blink は WebKit からフォークしたものだから、どちらも同じもので〜」という話を見かけます。

でも、Blink が WebKit からフォークしたのはもう10年以上も前[^fork]です。
それだけの期間が経過しているのだから、WebKit のコードはだいぶ減っているのでは？と思ったので調査してみました。

[^fork]: フォークしたのは2013年4月3日です。
[Chromium Blog: Blink: A rendering engine for the Chromium project](https://blog.chromium.org/2013/04/blink-rendering-engine-for-chromium.html)

# 調査結果

Blink のソースコードのうち、WebKit からフォークしたときのままの**コード行数**はたったの 6.81% でした。
逆に言うと、93.19% の行はフォーク後に手が入っていました。


# 調査方法

[Chromium のリポジトリ](https://chromium.googlesource.com/chromium/src/)を clone して、その中の Blink（`third_party/blink`） の各ファイルに対し `git balme --follow -w` （ファイル名変更を追跡、空白の差異を無視）で行ごとの変更履歴を追いかけました。
そのうえで、Blink フォーク前から変更のない行を確認しました。
（テストファイル[^test]と画像などのバイナリファイル[^binary]は、集計から除外しています）

結果、対象となった16,016ファイル・2,494,063行のうち、WebKit から変更のまま変更のない行が 169,931行でした。

調査プログラム：https://gist.github.com/YujiSoftware/0a3adc5030918469b13894b33c7344e7

[^test]: パスの一部に `test` を含むものをテストファイルと判定

[^binary]: ファイルの中に `0x00` が含まれているものをバイナリファイルと判定

# 注意点

あくまで `git blame` は行単位のコミット履歴を追ったものです。
そのため、ちょっとした修正であっても WebKit と異なると判定している点に注意が必要です。
例えば、メソッド名の `IsEmpty()` → `empty()` というリネームがされただけの行でも変更があったと判定しています。

現在の WebKit と Blink で diff を取るほうが正確かなとも考えたのですが、ディレクトリ構造が大きく変わっていてうまくいきそうにありませんでした。

# 結論

WebKit と Blink は別れたの！いつまでも昔のままだと思わないで！
Jestのテストでハマったので調べてまとめる

jestの環境構築をしていて、`import/export`が使えなかったり、`.jsx`の取り扱いでハマったので調べたことをまとめる。

## CommonJSとESModule
JavaScriptには、モジュールの取り扱いのための仕様が2つ存在する。
jestでそのままimport/exportが使用できないのはここに起因する。

### CommonJS
>CommonJSとは、サーバーサイドなどのウェブブラウザ環境外におけるJavaScriptの各種仕様を定めることを目標としたプロジェクトである。

Node.jsが標準で採用している。jestも同様。
モジュールの読み込みは`require`、モジュールの公開は`module.exports`などを使用する。
ファイルの拡張子を`.js`とするとCommonJSで扱われる。

### ESModule
>ECMAScript（エクマスクリプト）は、Ecma Internationalのもとで標準化手続きが行われているJavaScriptの規格

最近の主流はこっちらしい。
モジュールの読み込みは`import`、モジュールの公開は`export`を使用する。
ESModuleとして実行するためには、`package.json`に設定を追加するか、ファイルの拡張子を`.mjs`とする。

```json: package.json
{
  "type": "module",
  "main": "./main.js"
}
```

jestはcommonJSを採用しているので、ESModuleの記法である`import/export`はそのままでは使用できないということらしい。
また、`.jsx`もそのままでは取り扱えない様子。
そのため、Babelを導入して各種変換をかます必要があるらしい。

## Babelの導入
必要なのは以下の4つ。

1. Babelの導入
1. `@babel/preset-react`の導入
`.jsx`から`.js`への変換のために必要。
1. `@babel/preset-env`の導入
ESModuleからCommonJSへの変換に必要。
1. jestのtestEnvironmentを`jsdom`に変更
ブラウザ環境でのテストに必要。デフォルトは`node`。

babelと`.jsx`から`.js`へ変換するためのパッケージをインストールする。
```
npm install babel @babel/preset-react --save-dev
```

`babel.config.json`というファイルを以下の内容で作成する。
このファイルがないと、babelは何も変換処理を実施しない。
```json: babel.config.json
{
  "presets": ["@babel/preset-react"]
}
```

次に、ESModuleからCommonJSへの変換をするためのパッケージをインストールする。
```
npm install @babel/preset-env --save-dev
```
その後、`babel.config.json`を以下のように変更する。
```json: babel.config.json
{
 "presets": [
   ["@babel/preset-react", { "runtime": "automatic" }],
   ["@babel/preset-env", { "targets": { "node": "current" } }]
 ]
}
```

ブラウザでの実行を想定しているテストの場合、テスト実行環境を`node`から`jsdom`に変更する必要がある。
`jsdom`を利用可能とするため、下記パッケージをインストールする。
```
npm install jest-environment-jsdom --save-dev
```

その後、`jest.config.json`を以下の内容で作成する。
```json: jest.config.json
{
  "testEnvironment": "jest-environment-jsdom"
}
```

`expect(...).toBeInTheDocument is not a function`が出る場合は、`@testing-library/jest-dom`をインストールし、
```
npm install @testing-library/jest-dom --save-dev
```

テストファイルに`import '@testing-library/jest-dom'`を記載する。

## 参考
https://jestjs.io/ja/docs/configuration

https://zenn.dev/yodaka/articles/596f441acf1cf3

https://qiita.com/irico/items/0fa0cde39b1305c4b508

https://qiita.com/skanno/items/cd57fa5a7e78d2d5ebd5

https://zenn.dev/ikkyu_3/articles/264173544aad8c

https://zenn.dev/crsc1206/articles/de79af226d0c69
CSSを学びたい Step23 三角関数を利用する

## はじめに
CSSを学びたいのStep23です。今回は三角関数の**sin**,**cos**を学んでいきます。
※CSSって三角関数使えたんですね。。知らんかった😅

## 成果物
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/99a7d814-78ca-f295-9798-d2459009f376.png)

## ソースコード

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSSで三角関数を使用する例</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <h2>CSSで三角関数を使用する例</h2>
  <div class="circle-container">
    <div class="circle"></div>
  </div>
</body>
</html>
```

```css:styles.css
body {
  font-family: Arial, sans-serif;
  background-color: #f4f4f4;
  margin: 0;
  padding: 20px;
}

h2 {
  text-align: center;
  color: #333;
}

.circle-container {
  position: relative;
  width: 200px;
  height: 200px;
  margin: 0 auto;
  background-color: #ddd;
  border-radius: 50%;
}

.circle {
  position: absolute;
  width: 20px;
  height: 20px;
  background-color: #007BFF;
  border-radius: 50%;
  top: calc(50% - 10px); /* 中心に配置 */
  left: calc(50% - 10px); /* 中心に配置 */
  transform: translate(calc(100px * cos(45deg)), calc(100px * sin(45deg)));
}
```
システムトレイに常駐するプログラムのサンプルコード

Javaでシステムトレイに常駐するプログラムを作成する機会があったので、サンプルコードを紹介します。

# サンプルコードの概要

- システムトレイに常駐するプログラムを作成する
- アイコンには指定のpngファイルを利用する
    - https://www.irasutoya.com/2017/06/blog-post_572.html
- アイコンを右クリックするとポップアップメニューが表示される
    - Helloメニューを押下すると、通知を表示する
    - Exitメニューを押下すると、プログラムが終了し、システムトレイからアイコンが削除される

# サンプルコード

```Main.java
import java.awt.AWTException;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.TrayIcon.MessageType;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;

public class Main {
    public static void main(String[] args) {
        try (InputStream is = Main.class.getResourceAsStream("icon.png")) {
            TrayIcon trayIcon = new TrayIcon(ImageIO.read(is), "Sample App");
            trayIcon.setImageAutoSize(true);
            
            MenuItem menuItem1 = new MenuItem("Hello");
            menuItem1.addActionListener(e -> {
                trayIcon.displayMessage("Press Hello Button", "Hello World!", MessageType.INFO);
            });
            
            MenuItem menuItem2 = new MenuItem("Exit");
            menuItem2.addActionListener(e -> {
                System.exit(0);
            });
            
            PopupMenu popupMenu = new PopupMenu();
            popupMenu.add(menuItem1);
            popupMenu.add(menuItem2);
            trayIcon.setPopupMenu(popupMenu);
            SystemTray.getSystemTray().add(trayIcon);
        } catch (IOException | AWTException e) {
            e.printStackTrace();
        }
        
    }
}
```

 # 実行例

 このサンプルコードを実行すると、システムトレイにアイコンが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105859/c5aa241e-bf4a-71fe-07cf-57ac83230421.png)

アイコンを右クリックすると、ポップアップメニューが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105859/992b7eec-4527-1614-4cbf-b7ee7afc9c22.png)

Helloメニューを押下すると、通知が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105859/b02d84e2-d00f-f36b-e1ae-c9d820fddad5.png)

Exitメニューを押下すると、プログラムが終了します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105859/18bfba2a-ea88-feba-deb8-33448b9f5701.png)


# 環境情報

```
D:\>java -version
openjdk version "21.0.3" 2024-04-16 LTS
OpenJDK Runtime Environment Temurin-21.0.3+9 (build 21.0.3+9-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.3+9 (build 21.0.3+9-LTS, mixed mode, sharing)

D:\>javac -version
javac 21.0.3

D:\>ver

Microsoft Windows [Version 10.0.22631.3880]
```
2025 年 6 月 1 日までに Lightning Knowledge 移行ツールを実行してください 


+ [Attention Admins: Run the Lightning Knowledge Migration Tool before June 1, 2025 ](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX000000lsCA)

Classic Knowledge データモデルの廃止が進行中であるため、2025 年 6 月 1 日までに Lightning Knowledge に移行する必要があります。移行後も Classic Knowledge ユーザインターフェースを引き続き使用できますが、以下に示すいくつかの制限があります。

**Lightning Knowledge に移行する必要があるのはなぜですか? **

Classic Knowledge データモデルは、2025 年 6 月 1 日に無効になります。Summer '25 リリースの一部として、今後のすべての開発は Lightning Knowledge でのみ利用可能になります。最新の Knowledge 機能にアクセスするには、Classic Knowledge から Lightning Knowledge に移行する必要があります。移行すると、組織は Einstein 記事の推奨、Einstein Search for Knowledge、フロー サポート、Agentforce などの機能にアクセスできるようになります。

移行ツールを実行した後でも、Salesforce Classic インターフェースで Lightning Knowledge を引き続き使用できます。 

**Lightning Knowledge に移行するにはどうすればよいですか?**

[Lightning Knowledge 移行ツール](https://help.salesforce.com/s/articleView?id=release-notes.rn_knowledge_classic_migration_release_update.htm&release=252&type=5)を使用して Lightning Knowledge に移行し、Knowledge Classic の廃止に向けた準備を今日から始めましょう。 

Lightning Knowledge への移行は複数のフェーズから成るプロセスであり、各ステップは前のステップの成功に基づいて構築されます。Lightning Knowledge の移行は、本番環境で移行する前に、フルコピー サンドボックスでテストする必要があります。 

Lightning Knowledge への移行に関する追加情報については、[この記事](https://help.salesforce.com/s/articleView?id=sf.knowledge_migration_tool.htm&type=5)をご覧ください。
INVALID_MARKUP

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめA～M](https://qiita.com/Keiji_otsubo/items/f3ddedee6793bf1576f8)




+ [Chatterの文面に電話発信リンクを設置したい](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX000000lqHz)

アクションのChatter投稿はプレーンテキストしか不可能でした。
そこでフィード項目にてリッチテキストで試そうかと考えております。
しかし、ご教示いただいた「テキストテンプレート（リッチテキスト）のリンクには以下のタグが保存できました。」に関してフローは有効化できたのですが、レコード上試すと下記エラーが発生します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/e2c3c12b-6d6c-330f-9363-c7d6eb273cd4.png)


+ [リッチ テキスト テンプレートを使用して Chatter に投稿すると、INVALID_MARKUP: リッチ テキスト コンテンツの解析中にエラーが発生しました: サポートされていない HTML タグまたは属性が検出されました - strong
](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007T43JQSAZ)

:::note alert
NVALID_MARKUP: Error while parsing Rich Text Content: Unsupported HTML tag or attribute encountered - strong.
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/f0a3decd-6ca4-e0dc-e957-c61281efc690.png)


+ [Flow の HTML タグ](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000A91FkSAJ)
フィボナッチ数列をプログラムで生成（C言語・Python）

# フィボナッチ数列とは

フィボナッチ数列とは、
$$1,1,2,3,5,8,13,21,\cdots$$のように、一つ前の数字と足し合わせていく数列のことです。
最初に「1」が２つあると思いますが、次のように考えてみてください。
$$0,1,1,2,3,5,8,13,21,\cdots$$

例えば今$n$番目の数に居るとき、次の数にするには、

```math
a_{n+1} = a_n + a_{n-1}\;(n\geqq0)\quad\cdots\quad{\color{red}\clubsuit}
```

という計算式を立てればプログラムでも組めそうですよね！

例）3 = 2 + 1
例）5 = 3 + 2

今回は今立てたこの式を元にC言語でフィボナッチ数列生成プログラムを組んでいこうと思います。

参考 : [フィボナッチ数列とは？黄金比と一致する証明や一般項の求め方をわかりやすく解説](https://terakoya.ameba.jp/a000001464/)

# C言語でプログラミング

まず、C言語の書き方を知っている必要がありますが、そこに関しては今回説明しませんのでご了承ください。
コードを次のように書いてみました。

```c:fib.c
#include <stdio.h>
int main(void){
    // n番目までのフィボナッチ数を表示
    int n;
    printf("フィボナッチ数列を何番目まで表示しますか？ > ");
    scanf("%d", &n);
    
    // フィボナッチ数列の作成
    int arr[n], i;
    arr[0] = 0;
    arr[1] = 1;

    for(i=1; i<=n; i++){
        arr[i+1] = arr[i] + arr[i-1];
        printf("%d, ", arr[i]);
    }
    printf("\n");
    return 0;
}
```

完成したこのコードをGCCコンパイルして実行してみます。
実行すると...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3925398/8c644d95-2cb4-ff16-ca7e-89c4bdfd02b5.png)

このように表示されました！
「5」と入力したから最後が「5」で終わったわけではありません。
5番目のフィボナッチ数で終わるという意味です。

コード（fib.c）で言うと、6行目で変数$n$に入力した値が代入されているわけです。
そして、$\color{red}{\clubsuit}$のように次の数、次の数と計算するには繰り返す必要があるので、今回はfor文を使ってループさせていきます。
このとき、何番目まで表示するかを入力した変数$n$を使って、ループさせる区間を決めます。

さて、これでフィボナッチ数列を生成するC言語のコードが書けました！！

<font color="red">**と思うのはまだ早い！！**</font>

C言語の特徴として、計算は速いが**膨大な数を扱うとオーバーフローする可能性がある**ことがあげられます。

そうなんです。試しに入力の際に「100」を入力してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3925398/6aee8c5c-0368-dbb8-3f04-50f0deb9fa3c.png)

実行するとこのようになってしまいました。
おかしいですよね、フィボナッチ数列は自然数になるはずです。
それなのに負の数が出てきてしまいました。誰がどう見ようと、明らかにこれは不正確です。

ということでC言語でも対処をすれば大きい数を扱えるようになりますが、今回はここでC言語を扱うのはやめてPythonに切り替えてみようと思います。

# Pythonでプログラミング
ここからはPythonでフィボナッチ数列を生成していきます。
「<font color="red">**いや、あまえんなよ！！**</font>」と思う方も居るでしょう。
はい、あまえてしまいました...

Pythonの特徴として、処理速度はC言語に比べると遅いが、膨大な数を取り扱えるという利点があります。

### 【比較表】
|  | 処理速度 | オーバーフロー |
|:--|:--|:--|
| C言語 | <font color="red">速い</font> | しやすい |
| Python | 遅い | <font color="red">しづらい</font> |

というわけで、Pythonで書いたコードがこちらです。

```python:fib.py
n = int(input("フィボナッチ数列を何番目まで表示しますか？ > "))

i=1
arr = [0,1]
while i<n:
    arr.append(arr[i]+arr[i-1])
    i += 1
print(arr[1:])
```

Pythonの場合はリストを活用します。
やっぱり簡潔に書けて良いですね！（主Python好き）

このコード（fib.py）を実行すると、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3925398/20901d23-dcd0-b470-ce54-522a08d21d27.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3925398/03891fde-69ce-345b-9d54-33262fc0ef2e.png)

はい！！**100番目のフィボナッチ数を表示しても全く問題ありません！！**

こちらのサイトで合っているか確認してみましょう！
参考 : [フィボナッチ数列一覧表](https://fibonnacci.aimary.com)
【AWS】NATゲートウェイについて勉強する

# はじめに
<!-- 発端や概要を記載 -->
本記事ではインフラ初学者がVPCを触りつつ、NATゲートウェイについて学んでいく内容になります。

既存の環境として、以下のような構成があります。
![sampe.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3857754/12b46a20-0484-bd95-8ace-37267740e5e1.png)

上記構成を元に、色々リソースを付け加えていく形で勉強を進めていけたらと思います。

# 目次
<!-- タイトルとアンカー名を編集 -->
1. NATゲートウェイとは？
2. NATゲートウェイを構築する
3. NATゲートウェイを通じた疎通確認をする
4. まとめ
5. 参考文献

<!-- 各チャプター -->
# NATゲートウェイとは？
NATゲートウェイとは、プライベートサブネット内のインスタンスがVPC外部ネットワークへ接続するために必要なサービスです。

現状の構成では、プライベートサブネット内にあるEC2（DBサーバー）はインターネットにアクセスできません。

踏み台サーバーを経由して必要なソフトウエアをひとつずつscpコマンドでコピーすることもできますが、手間がかかりぎてしまいます。

この問題を解決するソリューションのひとつが「NAT」です。
NATは、IPアドレスを変換する装置で、２つのネットワークインターフェースを持ちます。

片方のインタフェースは、パブリックIPアドレスを設定し、インターネットに接続可能な構成にしておきます。
もう片方のインタフェースは、プライベートIPアドレスを設定し、プライベートサブネットに接続します。

プライベートサブネット内にあるDBサーバーがインターネットにパケットを送信する時、NATはパケットの送信元IPアドレスを自身のパブリックIPアドレスに置換します。
こうすることで、送信元がパブリックIPアドレスに変わるため、インターネットに出ていくことができます。

パケットの送信元IPアドレスが置換されているため、接続先からはNATが接続してきているように見えます。

また、NATは戻ってきた応答パケットの宛先を、元のホストのIPアドレスに置換してプライベートサブネットに転送します。

このように、NATがIPアドレスを置換することによって、プライベートサブネットに存在するホストはインターネットと通信できるようになります。

# NATゲートウェイを構築する
前知識をある程度取り入れたので、アウトプットしていこうと思います。

今回はこのような構成を作ろうと思います。
![sampe.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3857754/6eb3f8b0-7da3-b0e7-12ec-da5427514da5.png)

### NATゲートウェイを作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3857754/26f7d7a2-1517-8bb1-d9bd-c8704fb7d280.png)

注意する点としては以下項目になります。
- サブネット：パブリックサブネットを選択
- 接続タイプ：public
- Elastic IPアドレスを割り当てる

### ルートテーブルを更新する
プライベートサブネットのルートテーブルを更新しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3857754/48cd7c0f-b272-c336-2bab-7ad56d111891.png)

これでNATゲートウェイの構築は完了になります。

# NATゲートウェイを通じた疎通確認をする
では、NATゲートウェイの動作確認するためにDBサーバーからcurlコマンドを実行してみましょう！

```terminal:DBサーバー
curl https://qiita.com
```

HTMLを表示されていれば、HTTP通信ができていることになります！

# まとめ
今回はNATゲートウェイについて座学/ハンズオン形式で学習しました！
ハンズオンで学習していると、ルートテーブルやcurlコマンドの理解が進んだりと副産物を得られるのが良いメリットだと思いますね。

Elastic IPとNATゲートウェイはお金がかかっちゃうので、用がなければ早めに削除しちゃいましょう！

# 参考文献
- [Amazon Web Services基礎からのネットワーク＆サーバー構築改訂４版](https://amzn.asia/d/5QleEvq)
CloudFrontを使用してS3オリジンへのアクセスで403エラーが発生する原因を調べた

# 403とは
Webサイトの閲覧禁止を意味するコード

# 考えられる原因
### オブジェクトの公開設定
S3バケット内のオブジェクトが「パブリックにアクセス可能」となっているか確認してください。オブジェクトが非公開の場合、CloudFront経由でのアクセスが制限される可能性があります。

### AWS KMSによる暗号化
S3のオブジェクトがAWS Key Management Service (KMS) で暗号化されていないことを確認してください。KMSで暗号化されたオブジェクトにはCloudFrontからアクセスできません。

### S3バケットポリシー
S3バケットポリシーで"s3:GetObject"のアクセス許可が設定されているか確認してください。特にCloudFrontのオリジンアクセスアイデンティティ（OAI）またはオリジンアクセスコントロール（OAC）が使用されている場合、それらが適切に許可されている必要があります。

```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<CloudFront OAI ID>:root"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::<your-bucket-name>/*"
    }
  ]
}

```

### オブジェクトの所有権
S3バケットが「パブリックリードアクセス」を許可している場合、バケットとオブジェクトが同じAWSアカウントによって所有されている必要があります。オブジェクトが他のアカウントでアップロードされた場合、403エラーが発生する可能性があります。

### オブジェクトの存在
CloudFront経由でリクエストしているオブジェクトがバケット内に実際に存在しているか確認してください。存在しないオブジェクトへのリクエストは403または404エラーを引き起こします。

### Amazon S3 Block Public Access設定
S3バケットで「パブリックアクセスをブロックする」設定が有効になっている場合、バケットやオブジェクトへのパブリックアクセスがブロックされます。この設定を無効にすることで、CloudFront経由でのアクセスを許可する必要があります。

### Requester Pays設定
バケットで「Requester Pays」が有効になっている場合、リクエストにrequest-payerパラメータを含める必要があります。この設定があると、リクエストを行う側が料金を支払う形になるため、適切なパラメータが必要です。

### Refererヘッダーの確認
RefererヘッダーでCloudFrontからのアクセスを制限している場合、カスタムヘッダー設定を確認してください。Refererヘッダーが不一致の場合、403エラーが発生します。

### CloudFront キャッシュの確認
CloudFrontでキャッシュが残っている場合、キャッシュのクリアを試みてください。設定変更が反映されていないことが403エラーの原因となる場合もあります。

### CloudFrontディストリビューション設定の変更が反映されていない
CloudFrontのディストリビューション設定に変更を加えた場合、設定の反映に時間がかかることがあります。ステータスが「Deployed」となるまで待ってから再確認してみてください。

# 参考サイト
https://repost.aws/ja/knowledge-center/s3-website-cloudfront-error-403

https://rank-quest.jp/column/column/403-forbidden/
【Next.js】FullCalenderでBootstrap 5 Themingを使用してスタイルを適用する方法

# はじめに
アプリ開発で初めてFullCalenderを使用しているのですが、**デフォルトデザインだと味気ないので、Bootstrap 5 Themingを使用してスタイルを適用**したいと思います。
案外やり方が載っていなかったので備忘録としてまとめました。

https://fullcalendar.io/docs/bootstrap5

**【各バージョン】**
TypeScript：v5
React：v18
Next.js：v14.2.3
tailwindcss：v3.4.1
fullcalender：v6.1.15

# 方法
１．@fullcalendar 関連のパッケージと Bootstrap のスタイルを適用するために必要なパッケージをインストールします。
```
npm install @fullcalendar/react @fullcalendar/daygrid @fullcalendar/timegrid @fullcalendar/interaction @fullcalendar/bootstrap
npm install bootstrap
```

２．Bootstrap のスタイルは複数種類あるので、好きなものを選択。
今回は`Minty`を選択しました。
下記のデモでデザインを確認できます。

https://fullcalendar.io/docs/theme-chooser-demo

bootswatchのHPでもスタイル確認できます。

https://bootswatch.com/

３．cdnjs から提供されているURLを使って、自分の選択したテーマを Next.js プロジェクトの`globals.css`にインポートします。

https://cdnjs.com/libraries/bootswatch/5.3.3

※`Minty`テーマインポート時
```css:globals.css
@import url("https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.3/minty/bootstrap.min.css");

@tailwind base;
@tailwind components;
@tailwind utilities;
```

**※インポートしたテーマが適用されない場合**

`global.css` に記載されている `--background`や `--foreground` の変数に上書きされている可能性があります。
各変数の冒頭に` --custom-`を付け足すと解消されるかもしれません
```css:globals.css
/* fullcarender-Mintyテーマが持つ変数名と競合しないようにする */
:root {
  --custom-background: #ffffff;
  --custom-foreground: #171717;
}

@media (prefers-color-scheme: dark) {
  :root {
    --custom-background: #0a0a0a;
    --custom-foreground: #ededed;
  }
}

body {
  color: var(--custom-foreground);
  background: var(--custom-background);
}
```
**※おまけ**
**テーマ設定後、カレンダーの各要素をさらにカスタマイズしたい場合**は下記のように明示的に設定ができます。

例えば下記の場合、カレンダー内のボタンにはMintyテーマをそのまま適用し、イベントタグでは自分の好きなカラーを設定しています。
```css:globals.css
/* カレンダー内の各要素設定 */
.fc-button {
  background-color: var(
    --bs-primary
  ) !important; /* Bootswatchテーマ（Minty）のデフォルト設定使用 */
}
.fc-event {
  background-color: #ffffff !important; /* イベントの背景色を白にカスタマイズ */
  color: #000000 !important; /* イベントのテキスト色を黒に */
  border: none !important; /* イベント枠線があれば消す */
}
```


ちなみに`Minty`テーマ適用後のカレンダーはこんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3675500/ecde956a-6fb2-e40c-ff5a-00bd22eda3ca.png)

# おわりに
bootswatchやcdnjsの存在を初めて知った＆cssの設定をいじるいい機会になったと思っています。
また、テーマを適用するだけでデザインもいい感じになってくれるのでありがたいです。
日本語プログラミング言語「プロデル」をビルドできる環境をVSCodeで構築（シンタックスハイライト編）

# はじめに
先日、日本語プログラミング言語「プロデル」の公式サイトをウォッチさせていただきましたところ、下記の記事を発見しました。記事の投稿は2024/9/4でしたのでまだ2か月前です。さっそく使わせていただくことといたしました。

https://produ.irelang.jp/blog/2024/09/4786/


# 前提条件
Windows11 Pro 22H2
VSCode(Visual Studo Code)　1.95.1
Produire Version 2.0.1197 for Windows


## VSCodeの拡張機能
日本語プログラミング言語「プロデル」拡張機能 0.1.0


# 「プロデル」拡張機能 0.1.0のインストール

VSCodeの拡張機能の検索で、「プロデル」とタイプすると下図のような検索結果が表示されます。検索結果ペインで「プロデル」をダブルクリックするとエディタウィンドウにドキュメントが展開します。

![prodel1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118036/47d5fb38-4ecc-9393-660d-9dc0ae6e3527.png)

検索結果ペインまたはドキュメントウィンドウの「インストール」ボタンをクリックするとインストールは完了です。

# シンタックスハイライトの様子

さっそくプロデルのソースコードを開いてみます。今回はプロデルデザイナで編集作成したファイルを開きます。VSCodeの環境設定によりますが、わたしの環境では最初SHIFT_JISで開きましたので文字化けしました。VSCodeの一番下のステータスバーの文字コードをクリックしてUTF-8で開きなおすと下図のようになりました。

![prodel2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118036/8a22954c-82da-4420-9797-4773855434fa.png)

プロデルの場合は分かち書きではないので、トークンとなっている字句が強調表示されるのはたいへんありがたいです。それにこんなすごい機能を自力でつくってしまう@jpl_produireさんの尽力に敬服してしまいます。

# 定義へ移動する

ソースファイル内で定義されている単語でとりあえず検証してみました。上図で定義部を展開した状態を図示しております「トランザクションを開始する」の実行コードにフォーカスをあてると下図のようなツールチップのような吹き出しが表示されました。

![prodel3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118036/25b840a4-9273-cc72-f95c-b33a25b146f8.png)

この吹き出しをクリックすると、「トランザクションを開始する」の定義部にジャンプして、定義部のソースコード全体がハイライトされました。

# おわりに
次回は「プロデル」をビルドできるようにtasks.jsonとlaunch.jsonを構成してみます。デバッガエクステンションはないかもしれませんので、その場合はとりあえずMindと同じ方法でやってみます。

公式サイト2024/9/4記事より
できないこと
・デバッガ
Tauri（V2）は滅茶苦茶いいぞ！という布教をしていきたい

## 概要 
[Elin Custom Portrait Editor](https://www.nexusmods.com/elin/mods/6)というツールをTauriとSveltekitを使って製作したんですが、
制作にあたって「Tauri、良すぎない？」と感じたのでその魅力を伝えていきます。

### 1.ビルドしたファイルサイズが本当に小さくコンパクトな構成
元々別のツールをElectronで制作していたんですが、いざビルドしてみると本体exeだけで200MBを軽く超える超巨大アプリになってしまうのが困りものでした。
(インストーラーで配布する前提の仕様だろうし開発もそこまで気にしてないんだろうけど、私はインストーラー不要のポータブルアプリ派なので…)
Electron BuilderでPortable設定にすれば単一.exeとして出力も出来るけど、今度は実行速度が犠牲になってしまうという特大の罠が待ち受けています。

対するTauriはビルドサイズがだいたい10MB前後と非常に小さいです
(同じ機能のアプリをElectronで作ると200MB超えてました)

ビルドされるファイルも本体exe一つだけと非常にコンパクト、パス周りの指定など多少考えてあげる必要もありますが、大体どこに置いても同じように動作してくれるので配布もしやすいです。

下記コマンドでインストーラーを作らず本体exeだけ作れるのも個人的には好みです。
```Powershell:お好きなコマンドラインツール
bun tauri build --no-bundle
```
※この記事ではコマンド実行にbunを使用していますがTauriはnpmやyarn、pnpmでも動作します


### 2. V2からはそんなにrustの知識が無くても開発が容易になった
先日公開されたTauri V2ではプラグインシステムが採用されており、fsやdialogといったTauriの基本機能を個別にインストールし、rustのコードを全く書かなくてもJapascript/Typescriptから任意で呼び出せるようになっています。

例えばfs(ファイル読み書き)の機能が使いたい場合はコマンドでインストールし、
```Powershell:お好きなコマンドラインツール
bun tauri add fs
```
コマンド実行権限のスコープ範囲をtauriの設定ファイルに追加
***※自分はそんなに複雑なツールではないためスコープ範囲無制限にしてます、
　ツールの用途に合わせて適時調整してね。***
```json:capabilities/default.json
"permissions": [
    {
      "identifier": "fs:allow-write-text-file",
      "allow": [
        {
          "path": "**"
        }
      ]
    }
  ]
```



それをjs/tsのソース上からimportして呼び出してあげるだけで簡単に使えます。

```typescript:honyarara.ts
import { writeTextFile } from '@tauri-apps/plugin-fs';

await writeTextFile("honyarara.txt", "ほにゃらら")
```

Portrait Editorでも一部を除いてほとんどの機能はpluginで実装しています。

### 3.Rust処理の呼び出しも簡単
プラグインで足りない機能を補うにはどうしてもrustを書く必要がありますが、その場合でも比較的実装は簡単です。
以下は指定したパスをエクスプローラーで表示する処理、

```rust
use std::path::Path;
#[tauri::command]//フロントから呼び出したい関数には#[tauri::command]を行頭に付ける
fn open_folder(path: String) {
    let path = Path::new(&path);
    showfile::show_path_in_file_manager(path);
}
```
呼び出すにはTauriのウィンドウ呼び出し処理にinvoke_handlerで設定するだけ
```rust:lib.rs
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_dialog::init())
        .plugin(tauri_plugin_fs::init())
        .invoke_handler(tauri::generate_handler![open_folder]) //作成した関数を呼び出し
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
```

あとはフロント側でinvokeして関数名と引数を渡してあげればrust側で処理してくれます。

```typescript:honyarara.ts
import { invoke } from '@tauri-apps/api/core';

await invoke("open_folder", {path:"path/to/path"})
```

Electronでnode側の処理を呼び出すときは関数を呼び出すためのipcMainでリスナーを作り、
更にContextBridgeでプロセス間通信の許可設定をして…と色々と面倒だったのでTauriのシンプルさは非常に嬉しい


## まとめ
元々Rustを書くのがやや苦手で、Tauriは取っつきにくそうなイメージがあって長年敬遠していたのですが、V2のプラグイン機能で比較的導入が簡単なフレームワークになりました。
ファイルサイズが小さい高速なアプリを作成したい人は是非とも検討してはいかがでしょうか？
【SSv5】コンパイル時に'--no-warn-rwx-segments'のオプションエラーが発生する場合

## 環境
OS：Windows 11  
IDE：Simplicity Studio Version: SV5.9.3.1  
コンパイラ：GNU ARM v10.2.1
SDK：Gecko SDK Suite 4.4.5  
マイコンボード：PCB4001 Rev A03  
アンテナ：BRD4191A Rev A02  


## 背景
サンプルの「bt_aoa_ncp_locator」を新規作成して、そのままbuildしようとしたら`'--no-warn-rwx-segments'`が出ましたので、その解決方法を記録しておきます。  
```sh
c:/siliconlabs/simplicitystudio/v5/developer/toolchains/gnu_arm/10.2_2020q4/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: unrecognized option '--no-warn-rwx-segments'
c:/siliconlabs/simplicitystudio/v5/developer/toolchains/gnu_arm/10.2_2020q4/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld.exe: use the --help option for usage information
```
  

## 原因
コンパイラとSDKのバージョン不整合。  
Gecko SDK Suite 4.0.0以降はGNU ARM v12.2.1を使用する必要があります。  

https://community.silabs.com/s/article/Notes-on-Simplicity-Studio-SV5-8-0-0-and-Gecko-SDK-4-4-0-0-release?language=ja  


## 解決方法  
プロジェクトを右クリック後、`properties`を選択する。  
以下の①～③の手順でコンパイラを変更する。  
もし対象のコンパイラが存在しない場合は、`install`から新たに追加してから以下の手順を実行する。  

![compiler_select.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295695/8cce52ab-c8c2-610d-f830-ad5daa430b26.png)  
※最後に`Set Active`することを忘れずに
【2024年11月版】「この接続ではプライバシーが保護されません」をスルーする方法【Google Chrome】

# はじめに

トラブってるときや、急いでいるときほど遭遇する

「この接続ではプライバシーが保護されません」

を回避する方法です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143127/d1457120-e5c8-e399-7100-70cf6db5b5a8.png)

# やり方

`thisisunsafe` とキーボードから入力します。
テキストボックスやフォーカスなどが必要ではなく、
「この接続ではプライバシーが保護されません」画面で、単に、`thisisunsafe` と入力するだけです。

「この接続ではプライバシーが保護されません」がスルーされ、表示されなくなります。

証明書が日付などで無効になっているなど、サーバ側の設定をどうこうできないときに重宝します。

# さいごに

かんたんでしたね
特定の文字列を含む全てのファイルをゴミ箱に移動する

## 経緯
##### 制作中に特定の文字列を含む全てのファイルが要らなかったので、手軽に使えるものを作った。

## 使い方
##### 1: メモ帳を開き下記のコードをコピペ
##### 2: 「target_dir=」と「target_string=」を書き換える
##### 3: 拡張子を.txtから.batに変更し実行

```moveToTrashCan.bat

@echo off
setlocal

:: 削除対象のディレクトリを指定
set "target_dir=C:\PASS\FolderName"
:: ファイル名に含まれる特定の文字列
set "target_string=ExampleMoveFileName"

:: ファイル検出
echo 検出されたファイル:
for %%f in ("%target_dir%\*%target_string%*") do (
    echo %%f
)

:: 削除確認を求める
set /p "confirm=これらのファイルを削除してもいいですか？ (y/n): "

if /i "%confirm%" neq "y" (
    echo 処理をキャンセルしました。
    exit /b
)

:: ファイルをごみ箱に移動（PowerShellを使用）
for %%f in ("%target_dir%\*%target_string%*") do (
    echo %%f をごみ箱に移動しています...
    powershell.exe -Command "Add-Type -AssemblyName Microsoft.VisualBasic; [Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile('%%f', 'OnlyErrorDialogs', 'SendToRecycleBin')"
)

echo 完了しました！
pause


```
AWS IoT CoreのMQTTテストクライアントに対して、Windowsのコマンドプロンプトからメッセージをパブリッシュする

#AWS CLIを使う方法
```
aws --region us-east-1 iot-data publish --topic "YOUR_TOPIC" --cli-binary-format raw-in-base64-out --payload "{\"key\": \"value\"}"
```
https://www.amazon.co.jp/gp/product/B0B9P325F7/ref=ppx_yo_dt_b_d_asin_title_351_o05?ie=UTF8&psc=1
のChap1 step5に書いてあった。

```
aws configure
```
と
```
aws iot describe-endpoint --endpoint-type iot:Data-ATS
```
でhome regionに設定してあれば--regionの記載も不要です。
```
aws iot-data publish --topic "YOUR_TOPIC" --cli-binary-format raw-in-base64-out --payload "{\"key\": \"value\"}"
```
jsonファイルを指定する場合は、
```
aws iot-data publish --topic "YOUR_TOPIC" --cli-binary-format raw-in-base64-out --payload file://sample.json
```
ちなみにBashで連続したFake messageを送信する場合の例
https://aws.amazon.com/blogs/iot/integrating-iot-data-with-your-data-lake-with-new-aws-iot-analytics-features/
Case項目：社内コメント（Comments）（ケースコメント関連リスト）

### ケースには特殊な項目社内コメント（Comments）が存在している。

入力して保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/04a174ba-9896-9594-9f98-71e71b488440.png)

空です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/a84592d4-7278-1c88-c879-d35d70953fa8.png)

もう一度編集しても空です。
前回入力値はないです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/6761afff-ae51-057e-9273-0550d5382326.png)

２回目のコメントを入力し保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/0a4bd46b-b1ce-bebe-20a2-46c47580beca.png)

相変わらず空です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/64cf0b22-e3ff-6220-acc8-6a629299c8c2.png)

実は関連リスト：ケースコメントに登録されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894299/9cae6d8c-28e3-08b4-3093-1cd5c358ba98.png)
Rye vs uv どっちを使うべき？

## 対象読者

- モダンなpythonプロジェクト管理ツールを検討している人
- Ryeとuvをなんとなく知っている人

## 書かないこと

- Ryeやuvの導入方法・使い方

## Rye vs uv

先日書いた記事でpythonのプロジェクト管理ツールとその中でもモダンなRyeとuvの導入と基本的な使い方について書きました。その時点で、私自身「Ryeとuvはどう違って、どっちが良いんだ？」と疑問を感じたまま書いていました。
そこでuvとRyeの関係性やどっちを使うべきかを調べてみました。

### そもそも現在は同じ会社が管理している

Ryeとuvは現在、Astralという企業が開発主体になっています。Astral社はFastAPIなどでよく使われるuvicornなどの開発も行っている会社だそうです。
また現在幅広く使用されているPython用フォーマッターであるRuffの開発も行っています。

元々、Ryeは別の開発者がやっていましたが、非常に興味深いアプローチだったのでAstral社がその開発を引き継いだそうです。
uvはこれとは別の文脈で、高速な仮想環境構築を目指してRustで開発されているそうです。uvはpipやpip-toolsの代替として設計されています。

"Ryeはさまざまなツールを寄せ集めたため、かなり脆弱で最終的なソリューションにはなりそうにありません。"(意訳)
という状態なので、現状ではRyeが正式なツールとしてはリリースされる予定はないようです。
しかしRyeが無意味であるということではなく、"Ryeとuvが統合したツールが一番"(意訳)と考えられているようなので、何かしらの形で統合されていくのだと思います。

## 結局どうするべきか

Ryeの公式ページを真面目に見返したら、こんな注意書きがありました。

>If you're getting started with Rye, consider uv, the successor project from the same maintainers.
>While Rye is actively maintained, uv offers a more stable and feature-complete experience, and is the recommended choice for new projects.
>日本語訳
>Ryeを使い始めるのであれば、同じメンテナによる後継プロジェクトであるuvを検討してみてください。 Ryeは活発にメンテナンスされていますが、uvはより安定した完全な機能を提供しており、新規プロジェクトにはお勧めの選択肢です。(翻訳：DeepL.com)

Ryeを使い始めた途端に、uvに移行することになりました。

Ryeの公式ページは見ていましたが、home画面ではなくUser GuideのIntroductionからしか見ていなかったので、大切なページを見逃していました。
ちなみに、イントロダクションのページにも実験的なツールだとの記載はありました。

> Rye is still a very experimental tool, but this guide is here to help you get started. 
> 日本語訳
> 「Ryeはまだ非常に実験的なツールだが、このガイドを読めば始めることができる。」

しかし、これから正式版になるのかなと買っていに持っていましたが、すでにuvが推奨されていました。
致命的な見逃しでした。

ということで、Rye vs uv　は、基本的にuvを使いましょう。

## 参照資料

https://rye.astral.sh/
https://docs.astral.sh/uv/#highlights
https://lucumr.pocoo.org/2024/2/15/rye-grows-with-uv/
https://astral.sh/blog/uv
CSSを学びたい Step22 空コンテンツの制御

## はじめに
CSSを学びたいStep22です！！空コンテンツの制御をCSSで実施していこうと思います！

## 成果物

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/d2c66aa0-3f1e-bd1e-a2f9-45c313e85432.png)

## ソースコード

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>空コンテンツの制御</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <h2>空コンテンツの制御の例</h2>
  <div class="container">
    <div class="empty-element"> </div> <!-- 空白文字が含まれているが、視覚的には空 -->
    <div class="non-empty-element">コンテンツがあります。</div>
    <div class="parent-element">
      <p>子要素があります。</p>
    </div>
    <div class="parent-element"></div>
    <div class="empty-element"></div> <!-- 完全に空の要素 -->
    <div class="parent-element">
      <span>別の子要素があります。</span>
    </div>
  </div>
</body>
</html>
```

```css:styles.css
body {
  font-family: Arial, sans-serif;
  background-color: #f4f4f4;
  margin: 0;
  padding: 20px;
}

h2 {
  text-align: center;
  color: #333;
}

.container {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.container > div {
  background-color: #ddd;
  padding: 20px;
  text-align: center;
}

/* 空の要素を非表示にする */
.container > div:empty {
  display: none;
}

/* 子要素として <p> を持つ親要素を非表示にする */
.container > div:has(p) {
  display: none;
}
```

## おまけ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/27e2cac9-eb09-b81f-5220-df5870f90f7e.png)

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>空コンテンツの例</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <h2>空コンテンツの例</h2>

  <div class="container">
    <div class="empty-element"> </div> <!-- 空白文字が含まれているが、視覚的には空 -->
    <div class="non-empty-element">コンテンツがあります。</div>
    <div class="parent-element">
      <p>子要素があります。</p>
    </div>
    <div class="parent-element"></div>
    <div class="empty-element"></div> <!-- 完全に空の要素 -->
    <div class="parent-element">
      <span>別の子要素があります。</span>
    </div>
  </div>

  <script src="script.js"></script>
</body>
</html>
```

```css:styles.css
body {
  font-family: Arial, sans-serif;
  background-color: #f4f4f4;
  margin: 0;
  padding: 20px;
}

h2 {
  text-align: center;
  color: #333;
}

.container {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.container > div {
  background-color: #ddd;
  padding: 20px;
  text-align: center;
}

/* 空の要素を非表示にする */
.container > div:empty {
  display: none;
}

/* 子要素として <p> を持つ親要素を非表示にする */
.container > div:has(p) {
  display: none;
}
```