趣味で書いていっているPythonフロントエンドライブラリの1年の活動をまとめて振り返ってみる（2023年版）

のんびりとした進捗ですが今年も趣味で書いていっている自作のライブラリで対応したことなどの1年の振り返りをしておきます（GitHubのissueで今年1年でClosedになったもをissue番号を絡めて振り返っていこうと思います）。

※去年の振り返り記事 :

https://qiita.com/simonritchie/items/8d135e9350c68174870b

# ライブラリの概要と記事の事前情報

- [apysc](https://github.com/simon-ritchie/apysc)というPythonの簡易のフロントエンド用のライブラリです（ライトで機能の少ないAltJS風味なライブラリと考えていただければと）。
- Pythonで書いてHTMLとjsで出力したり、Jupyter (notebook / Lab)やColaboratory上で表示したり・・・といった制御を行うことができます（VS Code上のJupyterは現在未サポート）。
- 今まではSVG要素がメインでしたが段々とその他の要素も追加していっています。
- 型をしっかりと定義していっているのでmypyやPylance（Pyright）などによってTypeScriptのように型の恩恵を受けることができます。
- マウスイベントやアニメーションなどもある程度サポートしています。
- pipでさくっと入れられてそれだけで使えるようになるのでインストールや環境設定がお手軽です。

コードの雰囲気のサンプルとして、例えばシンプルなシアンの四角を表示したければ以下のようなコードになります。

```py
import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=150,
    stage_height=150,
    stage_elem_id="stage",
)
rectangle: ap.Rectangle = ap.Rectangle(
    x=50,
    y=50,
    width=50,
    height=50,
    fill_color=ap.Colors.CYAN_00AAFF,
)

ap.display_on_colaboratory(html_file_name="rectangle_example.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/b5777262-7b3b-3728-8e1f-cb38cbbc4717.png)

## 本記事のサンプルコードに関して

本記事でのサンプルコードなどはColaboratoryの公開ノートブックで進めます。必要に応じてご参照ください。

https://colab.research.google.com/drive/1d8E89blGtOVy-s5M8Tnk6Yq1m38U_DzV?usp=sharing

## 使うバージョンとインストール方法

本記事執筆時点で最新のv4.0.67を使用します。

pipコマンドに対応しているためColaboratory上では以下のようにインストールすることができます。

```
!pip install apysc==4.0.67
```

## ライブラリのドキュメントについて

ライブラリのドキュメントは英語と日本語のみ現在はサポートしています。本記事執筆時点で現在1つの言語に付き233ページくらいあるようです（たくさん書いたなぁと思いつつ・・・）。

英語版 :

https://simon-ritchie.github.io/apysc/en/index.html

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/c2da1f53-1631-85a2-0ca7-0a1e5fa6b0a4.png)](https://simon-ritchie.github.io/apysc/en/index.html)

日本語版 :

https://simon-ritchie.github.io/apysc/jp/jp_index.html

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/1eb77e8c-34ca-fe62-1cee-07437c10b370.png)](https://simon-ritchie.github.io/apysc/jp/jp_index.html)

ドキュメント上のコードは実際に実行され、出力されたHTMLとjsがドキュメント上に表示されていたりずるためドキュメント上でアニメーションしたりマウスイベントを受け付けたりしてくれます。

また、基本的に全ての各関数やメソッドへはdocstringをNumPyスタイルで記述するようにしています。引数や返却値情報などの他にもドキュメントへのリンクやコード例なども記載してあるため、その辺もエディタ上でのマウスオーバーなどでご利用いただけるようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/e9ea5118-5a54-8ef6-5b3d-0d1ed9a22f1b.png)

※docstringについては以前記事にしているので必要に応じてそちらをご参照ください。

https://qiita.com/simonritchie/items/49e0813508cad4876b5a

※NumPyスタイルでのdocstringチェック用の自作LintライブラリもGitHub Actionsに組み込んで活用しています。

https://qiita.com/simonritchie/items/84c4d4b2528309c30359

# 今年消化した各issue

## jsのrequestAnimationFrameのようなFPS依存のアニメーションが設定できるenter_frameのインターフェイスを追加（[#702](https://github.com/simon-ritchie/apysc/issues/702)、[#794](https://github.com/simon-ritchie/apysc/issues/794)、[#822](https://github.com/simon-ritchie/apysc/issues/822)、[846](https://github.com/simon-ritchie/apysc/issues/846)）

jsでの再描画用の処理でのrequestAnimationFrameを使いつつFPSを調整する形ができる形にしたenter_frameというメソッドを各クラスに追加しました。

参考 :

https://blog.oimo.io/2021/06/06/adjust-fps/

ドキュメント :

https://simon-ritchie.github.io/apysc/en/enter_frame.html

https://simon-ritchie.github.io/apysc/en/unbind_enter_frame_and_unbind_enter_frame_all.html

```py
import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=800,
    stage_height=150,
    stage_elem_id="stage",
)
rectangle: ap.Rectangle = ap.Rectangle(
    x=50,
    y=50,
    width=50,
    height=50,
    fill_color=ap.Colors.CYAN_00AAFF,
)


def on_enter_frame(e: ap.EnterFrameEvent, options: dict) -> None:
    rectangle.x += 1


stage.enter_frame(handler=on_enter_frame, fps=ap.FPS.FPS_60)
ap.display_on_colaboratory(html_file_name="enter_frame.html")
```

![apysc_enter_frame.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/364d0557-85e0-b3f7-653f-f83e80fcbafb.gif)

## StringクラスのエイリアスとしてのStrクラスを追加（[#570](https://github.com/simon-ritchie/apysc/issues/570)）

apyscではフロント用に変換するための独自の整数(`ap.Int`)や文字列(`ap.String`)などのクラスを設けています。一方でPython風味にする場合`String`よりも`Str`の方が違和感が少ないか・・・ということで`ap.Str`の方もエイリアスとして使えるようにしておきました。

※サンプルコードで使っている`ap.assert_equal`などはブラウザ上のコンソールで結果を確認できます。

```py
import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=150,
    stage_height=150,
    stage_elem_id="stage",
)

str_1: ap.String = ap.String(value="test string 1")
ap.assert_equal(str_1, "test string 1")

str_2: ap.Str = ap.Str(value="test string 2")
ap.assert_equal(str_2, "test string 2")

ap.display_on_colaboratory(html_file_name="str_alias.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/12cc9f86-7d1b-7b90-b480-985951a0a933.png)

## 三角形描画用のTriangleクラスとdraw_triangleメソッドを追加（[#834](https://github.com/simon-ritchie/apysc/issues/834)、[#824](https://github.com/simon-ritchie/apysc/issues/824)、[#577](https://github.com/simon-ritchie/apysc/issues/577)、[#825](https://github.com/simon-ritchie/apysc/issues/825)、[#835](https://github.com/simon-ritchie/apysc/issues/835)）

今までも多角形のクラス（`ap.Polygon`）もあったのでそちらでも三角形は描画できていたのですが、よりシンプルなインターフェイス（引数設定）で書けるように別途`ap.Triangle`クラスと`draw_triangle`メソッドの追加を対応しました。

ドキュメント :

https://simon-ritchie.github.io/apysc/en/triangle.html

https://simon-ritchie.github.io/apysc/en/graphics_draw_triangle.html

```py
import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=250,
    stage_height=150,
    stage_elem_id="stage",
)

left_triangle: ap.Triangle = ap.Triangle(
    x1=75,
    y1=50,
    x2=50,
    y2=100,
    x3=100,
    y3=100,
    fill_color=ap.Colors.CYAN_00FFFF,
)

sprite: ap.Sprite = ap.Sprite()
sprite.graphics.begin_fill(color=ap.Colors.MAGENTA_FF00FF)
right_triangle: ap.Triangle = sprite.graphics.draw_triangle(
    x1=175,
    y1=50,
    x2=150,
    y2=100,
    x3=200,
    y3=100,
)

ap.display_on_colaboratory(html_file_name="triangle.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/bcff2395-2158-f119-aeaa-e0fce0468a69.png)

## 座標制御用のクラスのリネーム（[#837](https://github.com/simon-ritchie/apysc/issues/837)）

内部で使っているXやY座標制御用のミックスインの基底クラスを`XMixInBase`や`YMixInBase`といった名前を付けていたのですがそもそもそれって抽象クラス的にInterfaceの方が合っているよなぁ・・・と途中で思い始めて`XInterface`や`YInterface`といった名前に調整しました。

## 真偽値用のクラスのコンストラクタで整数を指定する場合の型アノテーションをintなどからLiteralに移行（[#839](https://github.com/simon-ritchie/apysc/issues/839)）

apysc用の真偽値のクラス（`ap.Boolean`もしくは`ap.Bool`）のコンストラクタでは通常の真偽値などに加えて0か1かの整数値も受け付けることができるようになっていました。

今まではこの型の指定は整数の型で型アノテーションをしていたのですが、これを今後はLiteral型で0もしくは1の整数のみに制限するようにしました（mypyやPylanceなどでの型チェックで気付きやすくするため）。

※Literal型については以前記事にしているので必要に応じてそちらをご参照ください。

https://qiita.com/simonritchie/items/04832ab86c962b3e51cd

```py
import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=150,
    stage_height=150,
    stage_elem_id="stage",
)

bool_1: ap.Boolean = ap.Boolean(0)
ap.assert_false(bool_1)

bool_2: ap.Boolean = ap.Boolean(1)
ap.assert_true(bool_2)

ap.display_on_colaboratory(html_file_name="bool_constructor_literal.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/9c21c591-89c9-7174-dbbd-5b86b506502d.png)

## maxとminメソッドのMathクラスへの追加（[#840](https://github.com/simon-ritchie/apysc/issues/840)、[#849](https://github.com/simon-ritchie/apysc/issues/849)）

集計関係などのためのメソッド（Pythonで言うところのビルトインのminやmax関数など）も内部制御的に必要になったタイミングで追加し始めているのですが、その辺に絡んで`ap.Math`クラスに`max`と`min`メソッドを追加しました。

```py
import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=150,
    stage_height=150,
    stage_elem_id="stage",
)

max_value: ap.Number = ap.Math.max(
    ap.Array([ap.Int(10), ap.Int(15), ap.Int(5), ap.Int(20)])
)
ap.assert_equal(max_value, 20)

min_value: ap.Number = ap.Math.min(
    ap.Array([ap.Number(10.5), ap.Number(10.2), ap.Number(20.8)])
)
ap.assert_equal(min_value, 10.2)

ap.display_on_colaboratory(html_file_name="math_max_and_min.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/cd260786-68c2-eed7-cf81-57c2b4db6b3f.png)

## ArrayやDictionary型のループでPython自体のループをうっかり指定した時にエラーになるように調整（[#841](https://github.com/simon-ritchie/apysc/issues/841)）

前節までで振れた通りapyscではjs変換用にリストや辞書なども`ap.Array`や`ap.Dictionary`といったように独自のクラスをもっており、ループに関してはwithステートメントを使う形にしてあります（この辺はいつかもっと分かりやすくするかもしれませんが・・・）。

そのため、Python自体のforをそれらのクラスに対して使ってしまった場合にはミスに気付きやすくなるようにエラーになるように調整しました。

正常な例 :

```py
import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=150,
    stage_height=150,
    stage_elem_id="stage",
)

arr: ap.Array = ap.Array([10, 20, 30])
with ap.ForArrayIndices(arr=arr) as i:
    ap.trace("Array index is:", i)

ap.display_on_colaboratory(
    html_file_name="array_and_dictionary_for_loop_disabling.html"
)
```

※コード中で使っているtrace関数はPythonのprintのような感じでブラウザのコンソール上に任意の値などを表示する関数です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/cc680dfc-2358-98db-d75c-291f0fc8c536.png)

エラーになる例 :

```py
import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=150,
    stage_height=150,
    stage_elem_id="stage",
)

arr: ap.Array = ap.Array([10, 20, 30])
for i in arr:
    ap.trace("Array index is:", i)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/d9378cba-8a95-2e0b-c19b-ba49ba0bca61.png)

## 古いブランチの自動削除用のGitHub Actionsのライブラリの切り替え（[#850](https://github.com/simon-ritchie/apysc/issues/850)）

以前からプルリクマージ時のブランチ削除や残った古いブランチの自動削除用のGitHub Actionsのワークフロー設定はしていたのですが、その自動削除で使っていたライブラリがなんだか調子が悪くなってきてしまったのでライブラリの切り替えを実施しました。

現在は以下のもので落ち着いています。

https://github.com/beatlabs/delete-old-branches-action

## 小数点以下切り捨て処理用のMath.truncメソッドへのdoctestを追加（[#848](https://github.com/simon-ritchie/apysc/issues/848)）

小数点以下切り捨て処理用の`ap.Math.trunc`メソッドのdocstringにdoctestが未追加だったのでExamplesセクションを追加しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/73520de8-b8f1-9443-263b-ec0994c0a9bc.png)

https://github.com/simon-ritchie/apysc/blob/main/apysc/_math/trunc_mixin.py

## Python 3.11系のサポートの追加（[#844](https://github.com/simon-ritchie/apysc/issues/844)）

今年は3.12系のサポートの追加も対応していますが、Pythonの3.11系のサポートの追加も今年の対応だったようです。GitHub Actions上のCI/CDで動いている各種チェックなども3.11系が追加になっています。

## 共通のテスト設定用のデコレーターを追加（[#847](https://github.com/simon-ritchie/apysc/issues/847)）

apyscでは基本的に利用の前に描画領域となるステージ（`ap.Stage`クラス）と呼ばれるものを事前に作成する必要がある・・・といった形にしてあるのですが、それらの作成であったりリトライ設定などをテスト側で毎回行ったりが少々手間だったため共通設定をしてくれる（且つ必要に応じて個別に設定を微調整出来る）デコレーターを追加しています。

※テストは並列実行しておりたまにフレーキーテストで引っかかることがありますが気にせずスピード重視でリトライする形で運用しています。

## 初期のころから設けていたSVG関係の基底クラスの各処理をミックスインに分割して処理の取り外しや追加・使いまわしなどがしやすい形に調整（[#838](https://github.com/simon-ritchie/apysc/issues/838)）

よくある話ではありますが基底クラスが大きくなっていたり他でも使いまわしたいとか、もしくはサブクラス側で不要な機能まで含まれてしまう・・・といった問題が出てきていたため各処理を細かくミックスインに分割して気軽に追加・取り外し・使いまわしなどがしやすいように調整しました。

## SVGのパス描画に関するドキュメントの追加（[#489](https://github.com/simon-ritchie/apysc/issues/489)）

SVGのパス描画関係の各種ドキュメントが未追加だったので諸々の執筆作業を行いました。

例 :

https://simon-ritchie.github.io/apysc/en/path.html

https://simon-ritchie.github.io/apysc/en/graphics_draw_path.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/7b252c8f-402c-d6a8-3495-6421f1707c6e.png)

## X座標とY座標を扱うインターフェイスの型を整数から浮動小数点数に変更（[#827](https://github.com/simon-ritchie/apysc/issues/827)）

最初何も考えずにX座標とY座標の位置設定のインターフェイスの型を整数（`ap.Int`）で扱っていたのですが、js側は浮動小数点数も普通に扱いますしアニメーションとか含め色々と好ましくない点が出てきたため影響範囲が広く割と変更が面倒な作業ではありましたが浮動小数点数（`ap.Number`）の型に切り替えました。

## ステージのインスタンスをグローバルに取得するための関数に対するドキュメントを追加（[#553](https://github.com/simon-ritchie/apysc/issues/553)）

全体の描画領域を扱うステージ（`ap.Stage`）というものを使っており、1回のHTMLなどの出力ではシングルトン的に1つのみ生成される形となりますが、そちらをグローバルに取得するための`get_stage`という関数を設けていたもののドキュメントを書いていなかったのでステージのドキュメントに加筆しました。

追加したドキュメント部分 :

https://simon-ritchie.github.io/apysc/en/stage.html#get-stage-function-interface

## カスタムイベントの解除用のインターフェイスに対するドキュメントを追加（[#367](https://github.com/simon-ritchie/apysc/issues/367)）

apyscでは最初から定義されている各種イベント設定に加えてカスタムイベントも設定できるようになっているのですが、それらの解除用のインターフェイスのドキュメントを追加していなかったので追加しました。

追加したドキュメント部分 :

https://simon-ritchie.github.io/apysc/en/bind_and_trigger_custom_event.html#unbind-custom-event-api

## SVGのテキストの実装（[#124](https://github.com/simon-ritchie/apysc/issues/124)、[#856](https://github.com/simon-ritchie/apysc/issues/856)、[#857](https://github.com/simon-ritchie/apysc/issues/857)、[#875](https://github.com/simon-ritchie/apysc/issues/875)）

通常のテキストに対してパスに沿う形の変形をしたりなどが可能なSVGのテキスト用のクラスを追加しました（Issueの番号的に長期間放置していた模様・・・）。

ただ指定幅での改行だったりの挙動が普通のテキストと比べてストレートに行かないなどの面があり、別途普通のテキストも対応中です。

ドキュメント :

https://simon-ritchie.github.io/apysc/en/svg_text.html

```py
import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=200,
    stage_height=100,
    stage_elem_id="stage",
)

svg_text_1: ap.SvgText = ap.SvgText(
    text="Hello, world!",
    x=20,
    y=32,
    fill_color=ap.Colors.GRAY_AAAAAA,
)

svg_text_2: ap.SvgText = ap.SvgText(
    text="Hello, world!",
    x=20,
    y=72,
    fill_color=ap.Colors.GRAY_AAAAAA,
    font_size=24,
)
svg_text_2.bold = ap.True_
svg_text_2.italic = ap.True_

ap.display_on_colaboratory(html_file_name="svg_text.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/295bb27d-0988-843e-a713-d3f0a4d6ed41.png)

本記事執筆時点では主に以下のような設定をサポートしています。

- X座標
- Y座標
- 中央座標による回転
- 指定座標による回転
- 中央座標による拡縮
- 指定座標による拡縮
- 反転
- 塗りの色
- 塗りの透明度
- 線の色
- 線の透明度
- 線幅
- テキスト
- フォント設定
- フォントサイズ
- 行間
- 行揃え
- 斜体設定
- 太字設定

## `__repr__`など経由で出力される文字列のクォーテーションをシングルからダブルクォーテーションに調整（[#865](https://github.com/simon-ritchie/apysc/issues/865)）

細かいですがプロジェクトのスタイルをBlackに移行したためそちらに合わせて値の出力などをした際のクォーテーションをシングルクォーテーションからダブルクォーテーションに調整しました。Jupyter上などで値を表示した時のものなどが変更になります（例 : `String("Test text")`といったようにダブルクォーテーションで表示されます）。

```py
import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=200,
    stage_height=100,
    stage_elem_id="stage",
)

string: ap.String = ap.String("Test text")
string
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/ec79ee60-3a59-c17e-3e3d-6e8212c43234.png)

## 特定のSVGテキストの範囲の設定用のクラスを追加（[#860](https://github.com/simon-ritchie/apysc/issues/860)）

SVGテキストの内部で特定の文字列範囲のスタイルなどを設定するために、`SvgTextSpan`というクラスを追加しました。HTMLタグの`<span>`タグみたいな感じで使えるインライン要素となります。

設定できるスタイルの指定などは前節までで触れた`SvgText`クラスと同じような感じになっています。

ドキュメント :

https://simon-ritchie.github.io/apysc/en/svg_text_span.html
SvgTextの`create_with_svg_text_spans`静的メソッドでリストなどで`SVGTextSpan`のインスタンスを複数指定する形で使います。

テキストの途中だけ文字色を変更する例 :

```py
import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=200,
    stage_height=50,
    stage_elem_id="stage",
)
svg_text: ap.SvgText = ap.SvgText.create_with_svg_text_spans(
    text_spans=[
        ap.SvgTextSpan(text="Lorem "),
        ap.SvgTextSpan(text="ipsum ", font_size=20, fill_color=ap.Color("#0af")),
        ap.SvgTextSpan(text="dolor ", font_size=12),
    ],
    fill_color=ap.Color("#aaa"),
    font_size=16,
    x=20,
    y=32,
)

ap.display_on_colaboratory(html_file_name="svg_text_span.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/be005d01-e20e-643c-93e3-5021b4b77918.png)

## 線などの接続部分のスタイル設定を円や楕円のクラスから切り落とし（[#867](https://github.com/simon-ritchie/apysc/issues/867)）

他の描画用のクラスと同様に深く考えずに円（`ap.Circle`）や楕円（`ap.Ellipse`）のクラスで線などの接続部分（joints）のスタイル設定のインターフェイスを設けていたものの円とかではまったく影響しないのでリファクタリング的にその辺りを取り除きました。

## 文字列のクラスへ追加したsplitメソッドへのドキュメントとdoctestの追加（[#862](https://github.com/simon-ritchie/apysc/issues/862)）

文字列用のクラス（`ap.String`）に`split`メソッドを以前追加したりしていたのですが、`split`メソッドに対するドキュメントやdoctestなどを追加していなかったので執筆しました。

追加したドキュメント :

https://simon-ritchie.github.io/apysc/en/string_split.html

## 整数や真偽値などを文字列化するためのto_stringメソッドの追加（[#876](https://github.com/simon-ritchie/apysc/issues/876)、[#877](https://github.com/simon-ritchie/apysc/issues/877)）

整数（`ap.Int`）や浮動小数点数（`ap.Number`もしくは`ap.Float`）、真偽値（`ap.Boolean`）や配列（`ap.Array`）などを文字列変換するためのto_stringメソッドを各データ型に追加しました。

ドキュメント :

https://simon-ritchie.github.io/apysc/en/to_string.html

```py
import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=50,
    stage_height=50,
    stage_elem_id="stage",
)
int_value: ap.Int = ap.Int(value=100)
string: ap.String = int_value.to_string()
ap.assert_not_equal(int_value, "100")
ap.assert_equal(string, "100")

ap.display_on_colaboratory(html_file_name="to_string.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/79a4036a-3732-daba-4bd1-8608d2d4f5b3.png)

## バウンディングボックス風な座標とサイズの取得用のインターフェイスやクラスなどを追加（[#855](https://github.com/simon-ritchie/apysc/issues/855)、[#874](https://github.com/simon-ritchie/apysc/issues/874)、[#883](https://github.com/simon-ritchie/apysc/issues/883)）

バウンディングボックス的にオブジェクトのX座標、Y座標、幅と高さを取得するできるインターフェイス（`get_bounds`など）を追加しました。

ただ、まだステージ基準にしか対応していないので任意の親のオブジェクトなども基準にできるように将来オプション引数を追加する予定でいます。

ドキュメント :

https://simon-ritchie.github.io/apysc/en/get_bounds.html

https://simon-ritchie.github.io/apysc/en/rectangle_geom.html

```py
import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=500,
    stage_height=440,
    stage_elem_id="stage",
)
circle: ap.Circle = ap.Circle(
    x=250,
    y=220,
    radius=150,
    fill_color=ap.Color("#0af"),
)
bounding_box: ap.RectangleGeom = circle.get_bounds()

box_rectangle: ap.Rectangle = ap.Rectangle(
    x=bounding_box.left_x,
    y=bounding_box.top_y,
    width=bounding_box.width,
    height=bounding_box.height,
    line_color=ap.Color("#aaa"),
)

fill_color: ap.Color = ap.Color("#fd63c3")
left_x_and_top_y_circle: ap.Circle = ap.Circle(
    x=bounding_box.left_x,
    y=bounding_box.top_y,
    radius=10,
    fill_color=fill_color,
)
left_x_and_top_y_text: ap.SvgText = ap.SvgText(
    text="left_x and top_y",
    x=bounding_box.left_x,
    y=bounding_box.top_y - 15,
    fill_color=fill_color,
)

ap.display_on_colaboratory(html_file_name="get_bounds.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/483b9920-ce8f-6646-fefd-08c37ea4fa6b.png)

## 自動のHTML再出力設定用のデコレーターを追加（[#878](https://github.com/simon-ritchie/apysc/issues/878)）

Flutterのホットリロード的なものは技術的に難しすぎるのですが、一方でDjangoみたいにファイルを更新したらサーバー再起動してくれる・・・みたいな機能が欲しくなったため、エントリーポイントのmain関数などにデコレーターを設定するとコードが更新になったら再実行してHTMLをもう一度出力してくれる・・・みたいなものが有った方が作業面とかで楽か・・・と思いその辺の実装を進めてあります。

ただ、まだ調整用のissueがOpenになったままだったりドキュメントとかは書けていない・・・という状態になります（その内着手したいところです・・・）。

## 基底クラスの実装のミックスインなどへの分割（[#884](https://github.com/simon-ritchie/apysc/issues/884)、[#885](https://github.com/simon-ritchie/apysc/issues/885)）

描画などのためのオブジェクトの各基底クラス（表示用の`ap.DisplayObject`など）内での実装をミックスインなどへ分割し基底クラスの動かしづらい実装分などを減らす対応を入れました。

## for文などの制御のためのクラスを分割（[#891](https://github.com/simon-ritchie/apysc/issues/891)）

今まではapyscではループ制御をwithステートメントと`ap.For`などを使っていたのですが、その辺をクラスを分割しました（ジェネリックとかで色々と内部でやっていたのですが、内部実装がシンプルになるのと型判定的にも色々とやりやすかったため）。

Pythonビルトインでもループのインデックスが欲しければenumerateとか使ったり、辞書であればkeysやvalues、itemsとかといったようにメソッドが分かれていますがそれと同じような感じで用途に合わせてクラスを以下のように別にしてあります。

- `ap.ForArrayIndices` -> 配列のインデックスをループ中に返却（Pythonビルトインのrangeへのループと似たような挙動になります）。
- `ap.ForArrayValues` -> 配列の値をループ中に返却（Pythonビルトインのリストのループと似たような挙動となります）。
- `ap.ForArrayIndicesAndValues` -> 配列のインデックスと値をループ中に返却（Pythonビルトインのリストへのenumerateと似たような挙動になります）。
- `ap.ForDictKeys` -> 辞書のキーをループ中に返却（Pythonの辞書のkeysメソッドと似たような挙動となります）。
- `ap.ForDictValues` -> 辞書の値をループ中に返却（Pythonの辞書のvaluesメソッドと似たような挙動となります）。
- `ap.ForDictKeysAndValues` -> 辞書のキーと値をループ中に返却（Pythonの辞書のitemsメソッドと似たような挙動になります）。

ドキュメント :

https://simon-ritchie.github.io/apysc/en/for_array_indices.html

https://simon-ritchie.github.io/apysc/en/for_array_values.html

https://simon-ritchie.github.io/apysc/en/for_array_indices_and_values.html

https://simon-ritchie.github.io/apysc/en/for_dict_keys.html

https://simon-ritchie.github.io/apysc/en/for_dict_values.html

https://simon-ritchie.github.io/apysc/en/for_dict_keys_and_values.html

X座標を3つ格納した配列に対してループを回して円を3つ描画する例 :

```py
import apysc as ap

ap.Stage(
    stage_width=350,
    stage_height=150,
    background_color=ap.Color("#333"),
    stage_elem_id="stage",
)

x_arr: ap.Array[ap.Number] = ap.Array([ap.Number(75), ap.Number(175), ap.Number(275)])
with ap.ForArrayValues(arr=x_arr, arr_value_type=ap.Number) as value:
    circle: ap.Circle = ap.Circle(
        x=value,
        y=75,
        radius=25,
        fill_color=ap.Color("#0af"),
    )

ap.display_on_colaboratory(html_file_name="for_array_values.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/38724c58-1d07-3de8-2df2-d9ca4f24799c.png)

## DependabotでPythonライブラリとnpmの依存関係のプルリクを自動で作成してくれるように設定（[#888](https://github.com/simon-ritchie/apysc/issues/888)、[#933](https://github.com/simon-ritchie/apysc/issues/933)）

長いこと設定しておらず今更感はありましたがDependabotで開発用のDockerコンテナで使用しているPythonのライブラリの依存関係とnpmのアップデート用のプルリク自動作成用の設定を行いました（やはり便利に思います）。

## Python 3.7系のサポートの終了（[#902](https://github.com/simon-ritchie/apysc/issues/902)）

Python 3.7系がEoLになってしばらく経ったということもありapyscでもサポートを終了しました。

## 文字列へのlength属性の追加（[#910](https://github.com/simon-ritchie/apysc/issues/910)）

文字列（`ap.String`）の文字数を取得するための`length`属性を追加しました。

英語や日本語などでも使えますが、一部の絵文字は正確に文字数カウントはできません（正確にカウントできる絵文字も多くあります）。この辺りはPythonのビルトインと似たような挙動になります。

ドキュメント :

https://simon-ritchie.github.io/apysc/en/string_length.html#basic-usage

```py
import apysc as ap

ap.Stage(
    stage_width=50,
    stage_height=50,
    background_color=ap.Color("#333"),
    stage_elem_id="stage",
)

string: ap.String = ap.String("ABCDEF")
length: ap.Int = string.length
ap.assert_equal(length, 6)

string = ap.String("あいうえお")
length = string.length
ap.assert_equal(length, 5)

string = ap.String("🥳🌟🍻")
length = string.length
ap.assert_equal(length, 3)

ap.display_on_colaboratory(html_file_name="string_length.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/1fdbed9a-c295-559e-9a72-68bf9e722a73.png)

## pytestの並列実行用のライブラリをpytest-parallelからpytest-xdistへ移行（[#919](https://github.com/simon-ritchie/apysc/issues/919)、[#922](https://github.com/simon-ritchie/apysc/issues/922)）

Pythonのアップデートだったか原因は記憶が曖昧ですが、pytestのテストの並列実行用に使っていたpytest-parallelのライブラリがなんだかエラーが出るようになってしまったのでpytest-xdistへと移行しています。

## 文字列に浮動小数点数の部分の最大桁数を反映ずるapply_max_num_of_decimal_placesメソッドを追加（[#917](https://github.com/simon-ritchie/apysc/issues/917)）

例えば`123.4567`という浮動小数点数の形式の文字列があったとして、浮動小数点数の最大桁数を制限したい場合のための`apply_max_num_of_decimal_places`というメソッドを文字列（`ap.String`）に追加しました。

例として2桁までと指定すれば`123.45`といった文字列を取得することができます。

ドキュメント :

https://simon-ritchie.github.io/apysc/en/string_apply_max_num_of_decimal_places.html

```py
import apysc as ap

ap.Stage(
    stage_width=50,
    stage_height=50,
    background_color=ap.Color("#333"),
    stage_elem_id="stage",
)

string = ap.String("123.4567")
string = string.apply_max_num_of_decimal_places(max_num_of_decimal_places=2)
ap.assert_equal(string, "123.45")

ap.display_on_colaboratory(
    html_file_name="string_apply_max_num_of_decimal_places.html"
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/7894ea44-f2d4-0309-7748-69fbd73c854a.png)

## 真と偽の値のための定義を追加（[#921](https://github.com/simon-ritchie/apysc/issues/921)）

PythonのビルトインのTrueとFalseのように最初から真の値（`ap.True_`）と偽の値（`ap.False_`）を追加しました。

細かいですが今までは`ap.Boolean(True)`もしくは`ap.Boolean(False)`といった書き方をしていたので利用時の記述が短くなります。

ドキュメント :

https://simon-ritchie.github.io/apysc/en/true_and_false.html

```py
import apysc as ap

ap.Stage(
    stage_width=100,
    stage_height=50,
    background_color=ap.Color("#333"),
    stage_elem_id="stage",
)
text: ap.SvgText = ap.SvgText(
    text="Hello!",
    x=10,
    y=31,
    fill_color=ap.Color("#aaa"),
    bold=ap.True_,
    italic=ap.False_,
)

ap.display_on_colaboratory(html_file_name="true_and_false.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/3b85919f-6809-81d3-966e-7fa9688e42c6.png)

## GitHub Actionsのワークフロー設定のチェック用のactionlintの導入（[#934](https://github.com/simon-ritchie/apysc/issues/934)）

Actionsのワークフロー設定のチェック用のactionlintのワークフローを追加しました。

参考 :

https://rhysd.hatenablog.com/entry/2021/07/11/214313

さくっと導入できて素敵でした。

## 配列の値の型を固定するオプションを追加（[#943](https://github.com/simon-ritchie/apysc/issues/943)）

今までは配列の値の型をジェネリックで指定していた（例 : `ap.Array[ap.Int]`）のですが、一部のインターフェイスでそれだと値の型の固定化が難しいところが出てきたのでコンストラクタで`fixed_value_type`という引数を追加しました（jsへの変換上の内部の都合という側面が強めです）。

## 配列のクラスに最後の値を取得するlast_value属性を追加（[#944](https://github.com/simon-ritchie/apysc/issues/944)）

作業していて個人的に欲しくなったため配列の最後の値を取得する`last_value`という属性を追加しました。

```py
import apysc as ap

ap.Stage(
    stage_width=50,
    stage_height=50,
    background_color=ap.Color("#333"),
    stage_elem_id="stage",
)
arr: ap.Array[int] = ap.Array([10, 20, 30])
last_value: int = arr.last_value
ap.assert_equal(last_value, 30)

ap.display_on_colaboratory(html_file_name="array_last_value.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/d7fb4e79-d1cb-e92e-1a78-afcf01118d44.png)

## 色を扱うためのColorクラスを追加（[#947](https://github.com/simon-ritchie/apysc/issues/947)）

今まではapyscでは色の指定を`ap.String("#00aaff")`といったように文字列を指定する形で指定していました。

内部で値が色のフォーマットになっていない場合を弾くためのバリデーションはしていたのですが、一方で普段お仕事でFlutterとかを触っていて「やっぱり色は色専用のクラスで扱った方がいいよなぁ・・・」という気持ちが日に日に強くなり、影響範囲が大分大きかったのですが新たに`ap.Color`のクラスを追加して色関係の引数や返却値・属性などを一通りこちらのクラスで統一しました。

ドキュメント :

https://simon-ritchie.github.io/apysc/en/color.html

```py
import apysc as ap

stage: ap.Stage = ap.Stage(
    stage_width=250,
    stage_height=150,
    background_color=ap.Color("#333"),
    stage_elem_id="stage",
)

left_rectangle: ap.Rectangle = ap.Rectangle(
    x=50,
    y=50,
    width=50,
    height=50,
    fill_color=ap.Color("#00aaff"),
)

right_rectangle: ap.Rectangle = ap.Rectangle(
    x=150,
    y=50,
    width=50,
    height=50,
    line_color=ap.Color("#ffffff"),
    line_thickness=3,
)

ap.display_on_colaboratory(html_file_name="color.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/b25e63cb-b6f3-b274-a34e-0fc1ed7363a6.png)

## 色の定数定義を追加（[#971](https://github.com/simon-ritchie/apysc/issues/971)）

Flutterとかも`Colors`クラスでマテリアルデザインとかをベースとした色の定数定義が色々ありますが、似たような感じで`ap.Colors`クラスを追加しました。

定数名は色の名前と16進数のカラーコードのセットになっています（例 : `RED_FF0000`）。

ドキュメント :

https://simon-ritchie.github.io/apysc/en/colors.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/ce763bf6-ebc6-ed6c-d49b-207abf223e5c.png)

```py
import apysc as ap

stage: ap.Stage = ap.Stage(
    stage_width=250,
    stage_height=150,
    background_color=ap.Colors.GRAY_333333,
    stage_elem_id="stage",
)

left_rectangle: ap.Rectangle = ap.Rectangle(
    x=50,
    y=50,
    width=50,
    height=50,
    fill_color=ap.Colors.CYAN_00FFFF,
)

right_rectangle: ap.Rectangle = ap.Rectangle(
    x=150,
    y=50,
    width=50,
    height=50,
    line_color=ap.Colors.MAGENTA_FF00FF,
    line_thickness=3,
)

ap.display_on_colaboratory(html_file_name="colors.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/bb12ffa4-1245-51fe-7948-ef8b7b0dc6fb.png)

## ドキュメントのコードブロックのチェックの並列数を増やして処理時間が短くなるように調整（[#993](https://github.com/simon-ritchie/apysc/issues/993)）

ドキュメントのコードブロックがデグレして動かなくなるといったことを減らすためにGitHub ActionsによるCI/CDで日々チェックしているのですが、そのチェック処理が結構時間がかかるようになっていたので並列での実行数を増やしたりしてチェックの時間が短くなるように調整しました。

## SVGテキストで改行でデグレしていたので修正（[#984](https://github.com/simon-ritchie/apysc/issues/984)）

別件でjs変換する際の文字列処理でのエスケープを調整したりしていたのですが、js上で`\n`などの文字列が改行されない形にデグレしていたので修正を実施しました。

## マテリアルデザインの色の定数定義を追加（[#972](https://github.com/simon-ritchie/apysc/issues/972)）

Flutterとかを触っていて学んだマテリアルデザインの要素も少しずつ入れていこうか・・・という感じで考えており、その一環でFlutterのColorsクラスのようにマテリアルデザインの色の定数定義も追加しました。

対象の各色は`ap.MaterialDesignColors`というクラスに設定されています。通常の`ap.Colors`と似たような感じで定数名は色の名前 + マテリアルデザインの色の番号（無いものは省略） + 16進数のカラーコードになっています（例 : `CYAN_200_80DEEA`や`WHITE_FFFFFF`など）。

ドキュメント :

https://simon-ritchie.github.io/apysc/en/material_design_colors.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/a874ed7a-1ba2-869c-386d-1f58adab6d58.png)

```py
import apysc as ap

stage: ap.Stage = ap.Stage(
    stage_width=150,
    stage_height=150,
    background_color=ap.MaterialDesignColors.GRAY_800_424242,
    stage_elem_id="stage",
)

rectangle: ap.Rectangle = ap.Rectangle(
    x=50,
    y=50,
    width=50,
    height=50,
    fill_color=ap.MaterialDesignColors.CYAN_200_80DEEA,
    line_color=ap.MaterialDesignColors.WHITE_FFFFFF,
    line_thickness=3,
)

ap.display_on_colaboratory(html_file_name="material_design_colors.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/0bb51399-3cde-a04a-d289-05da656ac3f8.png)

## docstring中のデフォルト値の文字列表記をシングルクォーテーションからダブルクオーテーションに調整（[#1007](https://github.com/simon-ritchie/apysc/issues/1007)）

とても細かいのですがコーディングスタイルをblackに移行したのに合わせてdocstringのデフォルト値の空文字などを`default ''`といったようにシングルクォーテーションで記述していた箇所を`default ""`といったようにダブルクォーテーションで統一しました。

## 色のクラスに`from_rbg`の静的メソッドを追加（[#973](https://github.com/simon-ritchie/apysc/issues/973)）

色のクラス（`ap.Color`）に`from_rgb`という静的メソッドを追加し、赤緑青の各値を0～255で指定して色の値を作成できるようにしました。

ドキュメント :

https://simon-ritchie.github.io/apysc/en/color_from_rgb.html

```py
import apysc as ap

ap.Stage(
    stage_width=350,
    stage_height=150,
    background_color=ap.Color("#333"),
    stage_elem_id="stage",
)

black_color: ap.Color = ap.Color.from_rgb(red=0, green=0, blue=0)
black_rectangle: ap.Rectangle = ap.Rectangle(
    x=50,
    y=50,
    width=50,
    height=50,
    fill_color=black_color,
)

white_color: ap.Color = ap.Color.from_rgb(red=255, green=255, blue=255)
white_rectangle: ap.Rectangle = ap.Rectangle(
    x=150,
    y=50,
    width=50,
    height=50,
    fill_color=white_color,
)

cyan_color: ap.Color = ap.Color.from_rgb(red=0, green=128, blue=255)
cyan_rectangle: ap.Rectangle = ap.Rectangle(
    x=250,
    y=50,
    width=50,
    height=50,
    fill_color=cyan_color,
)

ap.display_on_colaboratory(html_file_name="color_from_rgb.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/fcc3fd68-8236-f33c-ded3-4b0399964a07.png)

## 色のクラスにred_color、green_color、blue_color属性を追加（[#1016](https://github.com/simon-ritchie/apysc/issues/1016)、[#1015](https://github.com/simon-ritchie/apysc/issues/1015)、[#976](https://github.com/simon-ritchie/apysc/issues/976)、[#1002](https://github.com/simon-ritchie/apysc/issues/1002)、[#1014](https://github.com/simon-ritchie/apysc/issues/1014)）

赤緑青の各色の値を個別に操作できるようにするための`red_color`、`green_color`、`blue_color`属性を追加しました。

ドキュメント :

https://simon-ritchie.github.io/apysc/en/red_color.html

https://simon-ritchie.github.io/apysc/en/green_color.html

https://simon-ritchie.github.io/apysc/en/blue_color.html

```py
import apysc as ap

stage: ap.Stage = ap.Stage(
    stage_width=50,
    stage_height=50,
    background_color=ap.Color("#333"),
    stage_elem_id="stage",
)

color: ap.Color = ap.Color("#00aaff")
red_color: ap.Int = color.red_color
ap.assert_equal(red_color, 0)

color = ap.Color("#ff00aa")
red_color = color.red_color
ap.assert_equal(red_color, 255)

color.red_color = ap.Int(0)
red_color = color.red_color
ap.assert_equal(red_color, 0)

color.red_color = ap.Int(255)
red_color = color.red_color
ap.assert_equal(red_color, 255)

ap.display_on_colaboratory(html_file_name="red_color.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/763a06af-050e-0e03-b755-04bf2e47444b.png)

## プルリク作成時にGitHub Actionsでmypy、Pyright、numdoclint、flake8、actionlint、Secretlint、pytestのワークフローが走るように調整（[#1027](https://github.com/simon-ritchie/apysc/issues/1027)、[#1028](https://github.com/simon-ritchie/apysc/issues/1028)、[#1029](https://github.com/simon-ritchie/apysc/issues/1029)、[#1031](https://github.com/simon-ritchie/apysc/issues/1031)、[#1034](https://github.com/simon-ritchie/apysc/issues/1034)、[#1035](https://github.com/simon-ritchie/apysc/issues/1035)、[#1046](https://github.com/simon-ritchie/apysc/issues/1046)）

今まではmainブランチにpushした時に各種Lintやテストなどが走り、諸々が通ればPyPIに新しいバージョンのパッケージアップロードされるという形にしてありました。

ほぼ1人で作業しているのでこれでもまあ特に困らず・・・という感じだったのですが、これらのチェックをプルリクを出した時にも実行されるように調整しました（将来どなたかがプルリクを出されることがあれば便利かなと思ったのと、個人で扱う時にもプルリクを経由した方が便利に思える時も出てきているため）。

## Python 3.12系のサポートの追加（[#1019](https://github.com/simon-ritchie/apysc/issues/1019)）

Python 3.12がリリースしてしばらく経っていたのと依存関係の各ライブラリでもサポートされてきていたのでapyscでもサポートを開始しました。

## 固定幅で改行してくれる形のテキスト関係を追加（[#1003](https://github.com/simon-ritchie/apysc/issues/1003)、[#1071](https://github.com/simon-ritchie/apysc/issues/1071)、[#1072](https://github.com/simon-ritchie/apysc/issues/1072)、[#1073](https://github.com/simon-ritchie/apysc/issues/1073)、[#1074](https://github.com/simon-ritchie/apysc/issues/1074)、[#1081](https://github.com/simon-ritchie/apysc/issues/1081)、[#1075](https://github.com/simon-ritchie/apysc/issues/1075)、[#1076](https://github.com/simon-ritchie/apysc/issues/1076)、[#1077](https://github.com/simon-ritchie/apysc/issues/1077)、[#1078](https://github.com/simon-ritchie/apysc/issues/1078)、）

今まででもSVG用のテキストの機能はありましたが仕様的に固定幅で改行（折り返し）がしづらい・・・ということで固定幅で折り返してくれる`ap.MultiLineText`という（SVGではない）通常のテキストのクラスを追加中です。

直近ではこの辺を拡充していっており、色々ドキュメントとかも含め未対応で作業中となります（とりあえずフォントサイズ、塗りの色、塗りの透明度、太字、斜体、行揃え関係には現時点で対応済み）。

ドキュメント :

https://simon-ritchie.github.io/apysc/en/multi_line_text.html

https://simon-ritchie.github.io/apysc/en/text_font_size.html

https://simon-ritchie.github.io/apysc/en/text_fill_color.html

https://simon-ritchie.github.io/apysc/en/text_fill_alpha.html

https://simon-ritchie.github.io/apysc/en/text_bold.html

https://simon-ritchie.github.io/apysc/en/text_italic.html

https://simon-ritchie.github.io/apysc/en/text_align.html

https://simon-ritchie.github.io/apysc/en/text_align_last.html

```py
import apysc as ap

stage: ap.Stage = ap.Stage(
    background_color=ap.Color("#333"),
    stage_width=300,
    stage_height=200,
    stage_elem_id="stage",
)

multi_line_text: ap.MultiLineText = ap.MultiLineText(
    text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, "
    "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "
    "Ut enim ad minim veniam",
    width=250,
    font_size=16,
    fill_color=ap.Colors.CYAN_00AAFF,
    x=25,
    y=25,
)

ap.display_on_colaboratory(html_file_name="multi_line_text.html")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/228778/12f226c6-5d5a-628a-96d5-8fe2e92a08ca.png)

# 振り返りのまとめ

プライベートで趣味で少しずつ実装しているのと今年はプライベートの都合でそんなにアップデート出来ていない・・・という黄もしていましたがそれでもまとめてみると1年で結構色々やっていた・・・という印象に今年もなり良かったです。

飽きっぽい性格な一方で今年も継続出来たので是非来年も途中放棄せずに続けていきたい・・・ところです笑