投稿日:
文字コードはiso-2022-jp
SMTPの設定例
export EMAIL_SENDER_TRANSPORT=SMTP
export EMAIL_SENDER_TRANSPORT_host=smtp.example.com
export EMAIL_SENDER_TRANSPORT_port=1025
サンプルコード
use strict;
use Email::MIME;
use Email::MIME::Creator;
use Email::Sender::Simple qw(sendmail);
my $subject = Encode::encode('MIME-Header-ISO_2022_JP', 'さぶじぇくと');
my $mail = Email::MIME->create(
'header' => [
'From' => Encode::encode('MIME-Header-ISO_2022_JP', 'foo@example.com'),
'To' => Encode::encode('MIME-Header-ISO_2022_JP', 'to@example.com'),
'Subject' => $subject,
],
'attributes' => {
'content_type' => 'text/plain',
'charset' => 'ISO-2022-JP',
'encoding' => '7bit',
},
'body' => Encode::encode('iso-2022-jp', 'ほんぶん!'),
);
投稿日:
iOS Safari向けのinputやtextareaを実装するときにmaxlengthが効かない問題のメモ
maxlength
- 古いiOS Safariでは効かない模様
- iOS 18.6.2のSafari 18.6では効いていることを確認
onInput()でstring.slice(0, maxlength)するとIMEの挙動が可笑しくなるtype="tel"など日本語が入力できない場合であれば有効
- オートコンプリートやコピペ入力での字切れなどもあるため、根本的に使わないことが望ましい
type="number"
- iOS Safariでは期待した動作にはならない
- IMEが有効になり、全角入力が発生する
- iOS 18.6.2, Safari 18.6でも挙動は変わらず
- 使うなら
type="tel"を使い、JSで数字以外の入力を弾くのが無難 - 恐らく普及ブラウザの全てで半角入力を強制出来、スマホなどではNumPadが出てくる
- アルファベットやハイフンなどの記号も打てるので必要に応じた入力制御が必要
あとがき
iOS SafariのバージョンはiOS側に一定の依存があるらしく調べるのが手間だった。とりあえずUserAgentから抜いた値で確認している。
参考
"maxlength" | Can I use... Support tables for HTML5, CSS3, etc
投稿日:
ReactでSPAを組んでいてブラウザバックしたときのフォームの入力内容が消し飛んで気になったので、ブラウザバックした時にどうなるのかというのを軽く調査した結果
確認したパターンとしては次の2つ
- フォームの入力値をDOMに保持させるステートレスな方式
- フォームの入力値をJSに保持させるステートフルな方式
LocalStorageに画面情報を保存して復元するとか、条件分岐を使ってDOMを隠して保持させるとか、そういう系は考慮しない
結果
| DOM 保持 | JS 保持 | |
|---|---|---|
| SPA 内ブラウザバック | 消える | 保持される |
| SPA 外ブラウザバック | 保持される | 消える |
| コード記述量 | 少ない | 多い |
1. フォームの入力値をDOMに保持させるステートレスな方式
この方式だとhistory.push()でDOMが消し飛ぶのでSPA内でのブラウザバックで入力したデータが保持されません
その代わりSPAの外、別のサイトに遷移してからブラウザバックしたときは、DOMが残っているので入力したデータが保持されます
2. フォームの入力値をJSに保持させるステートフルな方式
この方式だとJSでステート管理をしているため、history.push()で遷移してDOMが消し飛んでも、 defaultValueに持ってる値を突っ込んであげれば、取り敢えず入力したデータを保持することが出来ます
反対にSPAの外、別のサイトに遷移してからブラウザバックしたときは、メモリの中身が飛んでるので入力したデータが保持されません
各手法の実装方式
ちゃちゃっと書いたのでコードは超雑です
確認環境
| Env | Ver |
|---|---|
| react | 17.0.2 |
| react-dom | 17.0.2 |
| react-router-dom | 5.2.0 |
1. フォームの入力値をDOMに保持させるステートレスな方式
大正義ステートレスです
Function Componentはステートレスなので、こうあってほしいですよね~
コードもシンプルで管理しやすいのが素敵なところです
export const StatelessPage = () => {
const history = useHistory();
return (
<div>
<form>
<input type="text" />
<button onClick={() => history.push(AppRoute.dom2.path)}>submit</button>
</form>
</div>
);
};
2. フォームの入力値をJSに保持させるステートフルな方式
ギルティなステートフル方式です
Class Componentを捨てたはずなのにどうしてこうなった…
コードが煩雑で管理が大変です
export const StatefullPage = () => {
const ctx = useContext(ExampleContext);
const history = useHistory();
const onChange = (ev: React.ChangeEvent<HTMLInputElement>) => {
ctx.text = ev.target.value;
};
return (
<div>
<form>
<input
type="text"
defaultValue={ctx.text}
onChange={(ev) => onChange(ev)}
/>
<button onClick={() => history.push(AppRoute.ctx2.path)}>submit</button>
</form>
</div>
);
};
投稿日:
CentOS 6.6で確認
install
パッケージマネージャーで入れられるならそれに越したことはない
wget https://storage.googleapis.com/golang/go1.9.linux-amd64.tar.gz
tar vzfx go1.9.linux-amd64.tar.gz
sudo mv go /usr/local/
PATHを通す
# goの実行パスとGOPATH(~/go/bin)をPATHに指定する
# GOPATHはglobalなnpm_modulesみたいなもんだと思う
export PATH=$PATH:/usr/local/go/bin:~/go/bin
投稿日:
substring
確認環境
| Env | Ver |
|---|---|
| Jinja | 2.11.0 |
| Python | 3.8.5 |
サンプルコード
- 変数名[begin:end]で指定する
{% set some_variable = string_variable[0:100] %}
ループ処理で変数代入を行う
確認環境
| Env | Ver |
|---|---|
| Jinja | 2.11.0 |
| Python | 3.8.5 |
- Jinja2でループ処理の中で変数の足しこみとかをするやつ
- 代入先の変数宣言は
{% set ns = namespace(title = "") %}のようにしてやる必要がある - 後はループの中で
setしてやれば上手くいく - 変数は宣言したブロックがスコープになるので、スコープを広げたいときは適当にブロックを上げてやると良い
- 代入先の変数宣言は
サンプルコード
- MkDocsのテンプレートでパンくずリストを生成するコード
[A] [B] [C]みたいな感じ
{% set ns = namespace(title = "") %}
{% for doc in page.ancestors %}
{% set ns.title = "[" + doc.title + "] " + ns.title %}
{% endfor %}
テンプレートファイルを読み込む
確認環境
| Env | Ver |
|---|---|
| Jinja | 2.11.0 |
| Python | 3.8.5 |
サンプルコード
- フォルダ構成
─src
├─app
│ ├─configs
│ │ └config.yaml
│ ├─templates
│ │ └─main.html
│ └─__init__.py
└─main.py
- コード
from jinja2 import Environment, PackageLoader, select_autoescape
env = Environment(
# appはフォルダ構成のappフォルダを指す
loader=PackageLoader('app', 'templates'),
autoescape=select_autoescape(['html', 'xml'])
)
template = env.get_template('main.html')
# `render()` の引数は埋め込み変数を KeyValue 形式で指定
print(template.render(the='variables', go='here'))
yamlファイルから設定をロードする
確認環境
| Env | Ver |
|---|---|
| Jinja | 2.11.0 |
| Python | 3.8.5 |
サンプルコード
- フォルダ構成
─src
├─app
│ ├─configs
│ │ └config.yaml
│ ├─templates
│ │ └─main.html
│ └─__init__.py
└─main.py
- コード
from yaml import safe_load as yamlLoad
from jinja2 import Environment, PackageLoader, select_autoescape
env = Environment(
loader=PackageLoader('app', 'templates'),
autoescape=select_autoescape(['html', 'xml'])
)
template = env.get_template('main.html')
with open('app/configs/config.yaml') as fYaml:
print(template.render(yamlLoad(fYaml)))