complete revamps
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
uetchy 2022-12-24 03:20:02 +09:00
parent aca29317c6
commit 9a9c2343d1
66 changed files with 13682 additions and 4599 deletions

View File

@ -6,9 +6,9 @@ steps:
- name: Build and push - name: Build and push
image: plugins/docker image: plugins/docker
settings: settings:
repo: ghcr.io/uetchy/uechi.io repo: u8.pub/uetchy/uechi.io
tags: latest tags: latest
registry: ghcr.io registry: u8.pub
username: username:
from_secret: docker_username from_secret: docker_username
password: password:

24
.gitignore vendored
View File

@ -1,13 +1,13 @@
/data/ .deploy*
/.vscode
/.sass-cache
/node_modules/
/npm-debug.log
.DS_Store
Thumbs.db
db.json
*.log
public/
.deploy*/
.drone.secrets .drone.secrets
.DS_Store
.obsidian
.sass-cache
*.log
/data
/public
db.json
node_modules
npm-debug.log
Thumbs.db
TODO

79
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,79 @@
{
"favorites.sortDirection": "ASC",
"cSpell.words": [
"actionunban",
"afdesign",
"afphoto",
"alsa",
"alsamixer",
"aplay",
"ARGF",
"asdeps",
"asound",
"Asoundrc",
"asym",
"aufs",
"authsucc",
"BALMUDA",
"bootctl",
"BROMPTON",
"bvolume",
"chsh",
"devfs",
"devtmpfs",
"diskio",
"dmsetup",
"dports",
"EARIN",
"eate",
"fdisk",
"fstrim",
"genfstab",
"genpsk",
"gptfdisk",
"hljs",
"hwclock",
"ignoreip",
"JPRS",
"krita",
"lshw",
"lsinitcpio",
"mailu",
"mkinitcpio",
"MOTIV",
"Mycroft",
"ncdu",
"netdev",
"noauto",
"NOEXEC",
"nofail",
"NOPASSWD",
"nullok",
"nvidiactl",
"pacmd",
"pqrs",
"pygmentize",
"pygments",
"Remo",
"resolv",
"resolvectl",
"SECOM",
"Sectigo",
"setenv",
"Shure",
"smartctl",
"smartd",
"squashfs",
"STEPCA",
"sysroot",
"systohc",
"timedatectl",
"timesyncd",
"tinysshd",
"tsched",
"userdbctl",
"vcckp",
"wipefs",
"xfsprogs"
]
}

View File

@ -6,13 +6,14 @@ RUN dpkg -i pandoc-2.14.0.1-1-amd64.deb
WORKDIR /app WORKDIR /app
COPY package.json yarn.lock ./ COPY plugins plugins
RUN yarn install --frozen-lockfile COPY package.json package-lock.json ./
RUN npm ci
COPY themes themes COPY themes themes
COPY source source COPY source source
COPY _config.yml ./ COPY _config.yml ./
RUN yarn build RUN npm run build
FROM nginx:stable-alpine as runtime FROM nginx:stable-alpine as runtime

View File

@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2021 Yasuaki Uechi (https://uechi.io) Copyright (c) 2013-2022 Yasuaki Uechi (https://uechi.io)
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -1,10 +1,10 @@
deploy: build deploy: build
docker rm -f uechi.io uechi.io-cron docker rm -f uechiio uechiio-cron
docker-compose -f docker-compose.production.yml up -d docker compose -f docker-compose.production.yml up -d
build: build:
docker-compose build --pull docker compose build --pull
push: push:
docker-compose push docker compose push

View File

@ -1,11 +1,11 @@
# uechi.io # uechi.io
[![Build Status](https://ci.uechi.io/api/badges/uetchy/uechi.io/status.svg)](https://ci.uechi.io/uetchy/uechi.io) [![Build Status](https://build.u8.pub/api/badges/uetchy/uechi.io/status.svg)](https://build.u8.pub/uetchy/uechi.io)
## Build ## Dev
```bash ```bash
yarn build npm start
``` ```
## Publish ## Publish

View File

@ -5,7 +5,7 @@
# Site # Site
title: uechi.io title: uechi.io
subtitle: "" subtitle: ""
description: "Random posts from U" description: "Random posts from uetchy"
keywords: keywords:
author: Yasuaki Uechi author: Yasuaki Uechi
language: en language: en

View File

@ -2,9 +2,9 @@ version: "3.0"
services: services:
web: web:
image: ghcr.io/uetchy/uechi.io image: u8.pub/uetchy/uechi.io
restart: unless-stopped restart: unless-stopped
container_name: uechi.io container_name: uechiio
environment: environment:
VIRTUAL_HOST: uechi.io,www.uechi.io VIRTUAL_HOST: uechi.io,www.uechi.io
LETSENCRYPT_HOST: uechi.io,www.uechi.io LETSENCRYPT_HOST: uechi.io,www.uechi.io
@ -14,10 +14,10 @@ services:
com.centurylinklabs.watchtower.enable: "true" com.centurylinklabs.watchtower.enable: "true"
cron: cron:
image: ghcr.io/uetchy/uechi.io image: u8.pub/uetchy/uechi.io
command: /usr/sbin/crond -d 8 -f command: /usr/sbin/crond -d 8 -f
restart: unless-stopped restart: unless-stopped
container_name: uechi.io-cron container_name: uechiio-cron
volumes: volumes:
- "./data:/var/www/html/_" - "./data:/var/www/html/_"
- "./periodic/daily:/etc/periodic/daily:ro" - "./periodic/daily:/etc/periodic/daily:ro"

View File

@ -2,7 +2,7 @@ version: "3.0"
services: services:
web: web:
image: ghcr.io/uetchy/uechi.io image: u8.pub/uetchy/uechi.io
build: . build: .
ports: ports:
- "8080:80" - "8080:80"

View File

@ -23,6 +23,38 @@ http {
root /var/www/html; root /var/www/html;
error_page 404 /404.html; error_page 404 /404.html;
# Matix/Synapse
# https://matrix-org.github.io/synapse/develop/reverse_proxy.html
# https://matrix-org.github.io/synapse/latest/setup/installation.html#client-well-known-uri
location ~ ^(/_matrix|/_synapse/client) {
# note: do not add a path (even a single /) after the port in `proxy_pass`,
# otherwise nginx will canonicalise the URI and cause signature verification
# errors.
# https://stackoverflow.com/a/54719226/2276646
resolver 127.0.0.11 valid=30s;
set $upstream_synapse synapse;
proxy_pass http://$upstream_synapse:8008;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
# Nginx by default only allows file uploads up to 1M in size
# Increase client_max_body_size to match max_upload_size defined in homeserver.yaml
client_max_body_size 50M;
}
location /.well-known/matrix/client {
return 200 '{"m.homeserver": {"base_url": "https://matrix.uechi.io"}}';
default_type application/json;
add_header Access-Control-Allow-Origin *;
}
location /.well-known/matrix/server {
return 200 '{"m.server": "matrix.uechi.io:443"}';
default_type application/json;
add_header Access-Control-Allow-Origin *;
}
location /404.html { location /404.html {
internal; internal;
} }

10491
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -5,34 +5,34 @@
"build": "hexo generate", "build": "hexo generate",
"clean": "hexo clean", "clean": "hexo clean",
"deploy": "hexo deploy", "deploy": "hexo deploy",
"start": "yarn clean && hexo server --debug", "start": "npm run clean && hexo server --debug",
"test": "lint-staged" "test": "lint-staged"
}, },
"dependencies": { "dependencies": {
"hexo": "6.0.0", "hexo": "^6.3.0",
"hexo-excerpt": "^1.3.0", "hexo-excerpt": "^1.3.0",
"hexo-feed": "^1.1.0", "hexo-feed": "^1.1.1",
"hexo-filter-mathjax": "^0.8.1", "hexo-filter-mathjax": "^0.9.0",
"hexo-generator-archive": "^1.0.0", "hexo-generator-archive": "^2.0.0",
"hexo-generator-category": "^1.0.0", "hexo-generator-category": "^2.0.0",
"hexo-generator-index": "^2.0.0", "hexo-generator-index": "^3.0.0",
"hexo-generator-tag": "^1.0.0", "hexo-generator-tag": "^2.0.0",
"hexo-renderer-dartsass": "^0.1.2", "hexo-renderer-dartsass": "^0.1.2",
"hexo-renderer-ejs": "^2.0.0", "hexo-renderer-ejs": "^2.0.0",
"hexo-renderer-pandoc": "^0.3.1", "hexo-renderer-pandoc": "^0.3.1",
"hexo-renderer-stylus": "^2.1.0",
"hexo-server": "^3.0.0", "hexo-server": "^3.0.0",
"hexo-theme-landscape": "^0.0.3" "hexo-simple-toc": "file:plugins/hexo-simple-toc",
"js-yaml": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {
"textlint": "^12.1.1", "textlint": "^12.2.4",
"textlint-filter-rule-whitelist": "^2.0.0", "textlint-filter-rule-whitelist": "^2.0.0",
"textlint-rule-common-misspellings": "^1.0.1", "textlint-rule-common-misspellings": "^1.0.1",
"textlint-rule-no-start-duplicated-conjunction": "^2.0.2", "textlint-rule-no-start-duplicated-conjunction": "^2.0.2",
"textlint-rule-preset-japanese": "^7.0.0" "textlint-rule-preset-japanese": "^7.0.0"
}, },
"hexo": { "hexo": {
"version": "6.0.0" "version": "6.3.0"
}, },
"private": true "private": true
} }

144
plugins/hexo-simple-toc/.gitignore vendored Normal file
View File

@ -0,0 +1,144 @@
# Created by https://www.toptal.com/developers/gitignore/api/node
# Edit at https://www.toptal.com/developers/gitignore?templates=node
### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
### Node Patch ###
# Serverless Webpack directories
.webpack/
# Optional stylelint cache
# SvelteKit build / generate output
.svelte-kit
# End of https://www.toptal.com/developers/gitignore/api/node

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2022 uetchy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,3 @@
# hexo-simple-toc
This plugin aggregates Hexo native `id` from rendered HTML's headings and generate ToC from it. No `markdown-toc` dependency required.

View File

@ -0,0 +1,4 @@
/* globals hexo: true */
const toc = require("./toc");
hexo.extend.filter.register("after_post_render", toc.after_post_render);

1045
plugins/hexo-simple-toc/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
{
"name": "hexo-simple-toc",
"description": "Lightweight ToC generator for Hexo",
"version": "1.0.0",
"author": "uetchy <y@uechi.io>",
"scripts": {},
"main": "index.js",
"files": [
"index.js",
"handler.js"
],
"dependencies": {
"jsdom": "^20.0.3"
},
"homepage": "https://github.com/uetchy/hexo-simple-toc",
"repository": {
"type": "git",
"url": "https://github.com/uetchy/hexo-simple-toc.git"
},
"bugs": {
"url": "https://github.com/uetchy/hexo-simple-toc/issues"
},
"license": "MIT",
"keywords": [
"hexo",
"toc"
]
}

View File

@ -0,0 +1,48 @@
const JSDOM = require("jsdom").JSDOM;
function generateToC(html) {
const dom = JSDOM.fragment(html);
const headings = Array.from(dom.querySelectorAll("h1, h2, h3, h4, h5, h6"))
// Filter headings with ids
.filter((el) => el && el.id)
// {id: string, content: string|null, depth: number}
.map((el) => ({
id: el.id,
content: el.textContent,
depth: Number(el.nodeName.replace("H", "")), // H1 -> 1
}));
let pos = 0;
function genToC(arr, lastDepth) {
const stack = [];
while (pos < arr.length) {
const { depth, id, content } = arr[pos];
if (depth < lastDepth) {
// unwind
pos -= 1;
break;
} else if (depth > lastDepth) {
// nested ToC
stack.push(stack.pop() + genToC(arr, depth));
} else {
// same depth
stack.push(`<a href="#${id}">${content}</a>`);
}
pos += 1;
}
return "<ul>" + stack.map((s) => `<li>${s}</li>`).join("") + "</ul>";
}
return genToC(headings, 1);
}
exports.after_post_render = function (data) {
data.content = data.content.replace("<!-- toc -->", () =>
generateToC(data.content)
);
return data;
};

View File

@ -4,54 +4,46 @@ date: 2013-07-07 09:00:00 +09:00
redirect_from: "/blog/2013/07/07/install-julius-with-homebrew" redirect_from: "/blog/2013/07/07/install-julius-with-homebrew"
--- ---
Homebrew を使って macOS に音声解析エンジン Julius をインストールします。 Homebrew を使って macOS に音声解析エンジン Julius をインストールす
# 前提 # 前提
OS X 用のパッケージ管理ツール Homebrew がインストールされている必要がある。 OS X 用のパッケージ管理ツール Homebrew がインストールされている必要がある。
インストール方法 インストール方法は[こちら](http://www.engineyard.co.jp/blog/2012/homebrew-os-xs-missing-package-manager/)を参照。
は[こちら](http://www.engineyard.co.jp/blog/2012/homebrew-os-xs-missing-package-manager/)を
参照。
# インストール # インストール
デフォルトの Homebrew リポジトリに Julius は含まれていないので デフォルトの Homebrew リポジトリに Julius は含まれていないので、[homebrew-nlp](https://github.com/uetchy/homebrew-nlp) を tap する。
、[homebrew-nlp](https://github.com/uetchy/homebrew-nlp) を tap する。
```bash ```bash
$ brew tap uetchy/nlp brew tap uetchy/nlp
``` ```
Tap し終わったら、`julius``julius-dictation-kit`をインストールする。 Tap し終わったら、`julius``julius-dictation-kit`をインストールする。
```bash ```bash
$ brew install julius julius-dictation-kit brew install julius julius-dictation-kit
``` ```
これで Julius と Julius ディクテーションキットがインストールされた。 これで Julius と Julius ディクテーションキットがインストールされた。
ディクテーションキットの場所は `brew --prefix julius-dictation-kit` コマンドで調 ディクテーションキットの場所は `brew --prefix julius-dictation-kit` コマンドで調べられる。
べられる。
後は、上記の `brew --prefix` コマンドでディクテーションキット内の **main.jconf** 後は、上記の `brew --prefix` コマンドでディクテーションキット内の **main.jconf**と **am-gmm.jconf** のパスを調べて `julius` に渡すことで音声認識が出来るようになる。
**am-gmm.jconf** のパスを調べて `julius` に渡すことで音声認識が出来るようにな
る。
```bash ```bash
$ julius \ julius \
-C `brew --prefix julius-dictation-kit`/share/main.jconf \ -C `brew --prefix julius-dictation-kit`/share/main.jconf \
-C `brew --prefix julius-dictation-kit`/share/am-gmm.jconf -C `brew --prefix julius-dictation-kit`/share/am-gmm.jconf
``` ```
上記のコマンドで Julius は GMM モードで待機状態になり、喋った内容をリアルタイム 上記のコマンドで Julius は GMM モードで待機状態になり、喋った内容をリアルタイムで音声認識してくれるようになる。
で音声認識してくれるようになる。
Julius をより精密な DNN モードで起動したい場合は以下のように、**am-gmm.jconf** Julius をより精密な DNN モードで起動したい場合は以下のように、**am-gmm.jconf**を **am-dnn.jconf** に変更するだけだ。
**am-dnn.jconf** に変更するだけだ。
```bash ```bash
$ julius \ julius \
-C `brew --prefix julius-dictation-kit`/share/main.jconf \ -C `brew --prefix julius-dictation-kit`/share/main.jconf \
-C `brew --prefix julius-dictation-kit`/share/am-dnn.jconf -C `brew --prefix julius-dictation-kit`/share/am-dnn.jconf
``` ```
@ -59,9 +51,9 @@ $ julius \
ディクテーションキットに関するドキュメントは下記のコマンドから参照可能だ。 ディクテーションキットに関するドキュメントは下記のコマンドから参照可能だ。
```bash ```bash
$ open `brew --prefix julius-dictation-kit`/share/doc open `brew --prefix julius-dictation-kit`/share/doc
``` ```
### 実行中の様子 ### 実行中の様子
![install-julius-with-homebrew](/uploads/install-julius-with-homebrew.png) ![](/uploads/install-julius-with-homebrew.png)

View File

@ -10,7 +10,7 @@ redirect_from: "/blog/2013/11/05/osx-http-proxy"
Mac のネットワーク環境は`networksetup -getcurrentlocation`コマンドで取得することが出来るので、 Mac のネットワーク環境は`networksetup -getcurrentlocation`コマンドで取得することが出来るので、
**.zshrc** 辺りに以下のシェルスクリプトを書いておけば Terminal で新しいタブを開いた時に自動でプロキシを設定してくれるはずである **.zshrc** 辺りに以下のシェルスクリプトを書いておけば Terminal で新しいタブを開いた時に自動でプロキシを設定してくれる。
```bash ```bash
proxy=proxy.hogehoge.ac.jp proxy=proxy.hogehoge.ac.jp
@ -39,7 +39,7 @@ git config --global url."https://".insteadOf git://
先ほどのコマンドと組み合わせることで最終的なコードは以下のようになる。 先ほどのコマンドと組み合わせることで最終的なコードは以下のようになる。
```bash:switch_proxy.sh ```bash switch_proxy.sh
proxy=proxy.hogehoge.ac.jp:80 proxy=proxy.hogehoge.ac.jp:80
switch_trigger=大学 switch_trigger=大学
@ -83,13 +83,12 @@ fi
このコードを **.zshrc** に保存して適当なターミナルで新しいセッションを開くと、`switch_trigger`で指定されたネットワーク環境下にいる時だけプロキシを通すことが出来る。 このコードを **.zshrc** に保存して適当なターミナルで新しいセッションを開くと、`switch_trigger`で指定されたネットワーク環境下にいる時だけプロキシを通すことが出来る。
既に開いているセッションに対してプロキシを適用する方法わからなかった。 しかし既に開いているセッションに対してプロキシを適用する方法わからなかった。
Workaround として、コードを **~/.switch_proxy** 辺りに置いて、 Workaround として、コードを **~/.switch_proxy** 辺りに置いて、
```bash:~/.zshrc ```bash ~/.zshrc
alias nswitch=~/.switch_proxy alias nswitch=~/.switch_proxy
```
```
`.zshrc`に書いておくことで、`nswitch`とタイプしてプロキシを切り替えられるようになる。 `.zshrc`に書いておくことで、`nswitch`とタイプしてプロキシを切り替えられるようになる。
```

View File

@ -8,7 +8,7 @@ redirect_from: "/blog/2013/12/05/qiita-alfred-workflow"
そこで、以前作った[Qiita の記事をインクリメンタルサーチする Alfred 2 Workflow](http://qiita.com/o_ame/items/f23e75bfc11e9e7b3a08)に、ストックした投稿を検索するコマンドを追加した。 そこで、以前作った[Qiita の記事をインクリメンタルサーチする Alfred 2 Workflow](http://qiita.com/o_ame/items/f23e75bfc11e9e7b3a08)に、ストックした投稿を検索するコマンドを追加した。
![s1.png](/uploads/alfred-qiita-workflow.png) ![](/uploads/alfred-qiita-workflow.png)
> [Github リポジトリ](https://github.com/uetchy/alfred-qiita-workflow)から[ダウンロード](https://github.com/uetchy/alfred-qiita-workflow/archive/master.zip) > [Github リポジトリ](https://github.com/uetchy/alfred-qiita-workflow)から[ダウンロード](https://github.com/uetchy/alfred-qiita-workflow/archive/master.zip)

View File

@ -4,7 +4,7 @@ date: 2014-10-27 09:00:00 +09:00
redirect_from: "/blog/2014/10/27/brew-cask-downloader" redirect_from: "/blog/2014/10/27/brew-cask-downloader"
--- ---
![image](/uploads/brew-cask-downloader.png) ![](/uploads/brew-cask-downloader.png)
homebrew-cask を単純なダウンローダーとして使う。 homebrew-cask を単純なダウンローダーとして使う。
@ -49,8 +49,8 @@ fi
もしくは直接ダウンロードしても良い。 もしくは直接ダウンロードしても良い。
```bash ```bash
$ curl https://gist.githubusercontent.com/uetchy/eb625f922eff16eb404b/raw/brew-smash.sh -o /usr/local/bin/brew-smash curl https://gist.githubusercontent.com/uetchy/eb625f922eff16eb404b/raw/brew-smash.sh -o /usr/local/bin/brew-smash
$ chmod +x /usr/local/bin/brew-smash chmod +x /usr/local/bin/brew-smash
``` ```
## 実際に使う ## 実際に使う
@ -58,7 +58,7 @@ $ chmod +x /usr/local/bin/brew-smash
以下のように`brew smash`コマンドを叩く 以下のように`brew smash`コマンドを叩く
```bash ```bash
$ brew smash send-to-kindle brew smash send-to-kindle
==> Fetching resources for Cask send-to-kindle ==> Fetching resources for Cask send-to-kindle
==> Downloading https://s3.amazonaws.com/sendtokindle/SendToKindleForMac-installer-v1.0.0.220.pkg ==> Downloading https://s3.amazonaws.com/sendtokindle/SendToKindleForMac-installer-v1.0.0.220.pkg
######################################################################## 100.0% ######################################################################## 100.0%
@ -77,7 +77,7 @@ Casks という名前のディレクトリがある場合、それを削除し
こういう機能いれてくれ こういう機能いれてくれ
```bash ```bash
$ brew cask install virtualbox brew cask install virtualbox
==> Fetching resources for Cask virtualbox ==> Fetching resources for Cask virtualbox

View File

@ -68,8 +68,8 @@ alias dokku='dockland'
という具合に alias を張っておけば、まるでリモートで`dokku`を実行している感覚でローカルから`dokku`コマンドを触ることが出来る。 という具合に alias を張っておけば、まるでリモートで`dokku`を実行している感覚でローカルから`dokku`コマンドを触ることが出来る。
```bash ```bash
$ cd rails-app cd rails-app
$ dokku logs dokku logs
[2014-05-29 15:38:56] INFO WEBrick 1.3.1 [2014-05-29 15:38:56] INFO WEBrick 1.3.1
[2014-05-29 15:38:56] INFO ruby 2.1.2 (2014-05-08) [x86_64-linux] [2014-05-29 15:38:56] INFO ruby 2.1.2 (2014-05-08) [x86_64-linux]
[2014-05-29 15:38:56] INFO WEBrick::HTTPServer#start: pid=10 port=5000 [2014-05-29 15:38:56] INFO WEBrick::HTTPServer#start: pid=10 port=5000

View File

@ -39,7 +39,7 @@ KNP のインストールにはありえないくらい時間が掛かる。
インストールが終わったら動作チェックをする。 インストールが終わったら動作チェックをする。
```bash ```bash
$ juman < test.txt | knp juman < test.txt | knp
# S-ID:1 KNP:4.11-CF1.1 DATE:2014/09/23 SCORE:-19.04210 # S-ID:1 KNP:4.11-CF1.1 DATE:2014/09/23 SCORE:-19.04210
今日は──┐ 今日は──┐
良い──┤ 良い──┤

View File

@ -12,7 +12,7 @@ redirect_from: "/blog/2014/03/14/rails-assets-cli"
ンを利用したら良い。 ンを利用したら良い。
```bash ```bash
$ gem search {package-name} --source https://rails-assets.org | grep "^rails-assets-" gem search {package-name} --source https://rails-assets.org | grep "^rails-assets-"
``` ```
`gem search` は source を指定しているにも関わらず RubyGems.org のパッケージも引 `gem search` は source を指定しているにも関わらず RubyGems.org のパッケージも引
@ -20,7 +20,7 @@ $ gem search {package-name} --source https://rails-assets.org | grep "^rails-ass
### シェルスクリプト ### シェルスクリプト
```bash:rails-assets.sh ```bash rails-assets.sh
#!/bin/sh #!/bin/sh
# Usage: rails-assets [package-name] [-a] # Usage: rails-assets [package-name] [-a]
@ -29,9 +29,8 @@ gem search $1 $2 --source https://rails-assets.org | grep "^rails-assets-"
もっと簡単に、シェル関数を定義することも出来る。 もっと簡単に、シェル関数を定義することも出来る。
```bash:~/.zshrc rails-assets(){ gem search $1 $2 --source ```bash ~/.zshrc
https://rails-assets.org | grep "^rails-assets-" } rails-assets(){
gem search $1 $2 --source https://rails-assets.org | grep "^rails-assets-"
``` }
``` ```

View File

@ -40,7 +40,7 @@ git clone https://github.com/uetchy/Sketch-StickyGrid.git
スクリプト内で`log`関数を呼び出すと、Console.app にログが出力される。 スクリプト内で`log`関数を呼び出すと、Console.app にログが出力される。
```js ```js
log(context.document.gridSize) log(context.document.gridSize);
``` ```
## ドキュメントの情報源 ## ドキュメントの情報源

View File

@ -4,7 +4,7 @@ date: 2015-09-07 09:00:00 +09:00
redirect_from: "/blog/2015/09/07/alfred-qiita-workflow-in-go" redirect_from: "/blog/2015/09/07/alfred-qiita-workflow-in-go"
--- ---
![Cover](/uploads/alfred-qiita-workflow.png) ![](/uploads/alfred-qiita-workflow.png)
Ruby で書かれている [Alfred Qiita Workflow](https://github.com/uetchy/alfred-qiita-workflow) を[バグ修正](https://github.com/uetchy/alfred-qiita-workflow/issues/3)のついでに Go で書き直した。 Ruby で書かれている [Alfred Qiita Workflow](https://github.com/uetchy/alfred-qiita-workflow) を[バグ修正](https://github.com/uetchy/alfred-qiita-workflow/issues/3)のついでに Go で書き直した。

View File

@ -11,7 +11,7 @@ Atom にインストールしているパッケージと[Atom.io](https://atom.i
npm 経由でインストールする。 npm 経由でインストールする。
```bash ```bash
$ npm install -g atom-package-diff npm install -g atom-package-diff
``` ```
# インストール済みパッケージとスターの diff # インストール済みパッケージとスターの diff
@ -19,7 +19,7 @@ $ npm install -g atom-package-diff
`apd status`コマンドでインストール済みパッケージとスターしているパッケージの diff を見ることができる。 `apd status`コマンドでインストール済みパッケージとスターしているパッケージの diff を見ることができる。
```bash ```bash
$ apd status apd status
36 packages installed 36 packages installed
30 packages starred 30 packages starred
@ -37,7 +37,7 @@ Sublime-Style-Column-Selection atom-fuzzy-grep douglas language-babel language-i
`apd sync --remote`でその逆の処理を行う。つまり、スターされているパッケージを全部インストールし、それ以外をアンインストールする。 `apd sync --remote`でその逆の処理を行う。つまり、スターされているパッケージを全部インストールし、それ以外をアンインストールする。
```bash ```bash
$ apd sync --local apd sync --local
Unstaring ... project-manager Unstaring ... project-manager
Unstaring ... react Unstaring ... react
Staring ... Sublime-Style-Column-Selection Staring ... Sublime-Style-Column-Selection

View File

@ -1,5 +1,5 @@
--- ---
title: 'gulp + decomposer: Best way to sassy-@import bower components' title: "gulp + decomposer: Best way to sassy-@import bower components"
date: 2015-02-26 09:00:00 +09:00 date: 2015-02-26 09:00:00 +09:00
redirect_from: "/blog/2015/02/26/gulp-decomposer-bower-import" redirect_from: "/blog/2015/02/26/gulp-decomposer-bower-import"
--- ---
@ -9,13 +9,13 @@ gulp + Browserify(+ debowerify)という構成で Web サイトを作ってい
ちなみに、**debowerify** というのは、 ちなみに、**debowerify** というのは、
```js ```js
var Velocity = require('velocity') var Velocity = require("velocity");
``` ```
という JavaScript を、 という JavaScript を、
```js ```js
var Velocity = require('./../../bower_components/velocity/velocity.js') var Velocity = require("./../../bower_components/velocity/velocity.js");
``` ```
という風に、bower_components 内のパスに解決してくれる Browserify transform だ。 という風に、bower_components 内のパスに解決してくれる Browserify transform だ。
@ -32,17 +32,17 @@ var Velocity = require('./../../bower_components/velocity/velocity.js')
**gulpfile.js** はこのように定義しておく。 **gulpfile.js** はこのように定義しておく。
```js ```js
var gulp = require('gulp') var gulp = require("gulp");
var sass = require('gulp-sass') var sass = require("gulp-sass");
var decomposer = require('decomposer') var decomposer = require("decomposer");
gulp.task('styles', function() { gulp.task("styles", function () {
gulp gulp
.src('src/styles/**/*.sass') .src("src/styles/**/*.sass")
.pipe(decomposer()) .pipe(decomposer())
.pipe(sass({ indentedSyntax: true })) .pipe(sass({ indentedSyntax: true }))
.pipe(gulp.dest('dist/css')) .pipe(gulp.dest("dist/css"));
}) });
``` ```
ポイントは`sass` **よりも前**`decomposer`を挟むこと。なぜなら、外部から@import した mix-ins や変数は SASS コンパイル時に解決されるからだ。`sass`よりも後に置くと、SASS が@import を解決出来ずにエラーが発生する。 ポイントは`sass` **よりも前**`decomposer`を挟むこと。なぜなら、外部から@import した mix-ins や変数は SASS コンパイル時に解決されるからだ。`sass`よりも後に置くと、SASS が@import を解決出来ずにエラーが発生する。
@ -50,7 +50,8 @@ gulp.task('styles', function() {
続けて SASS を書こう。 続けて SASS を書こう。
```scss ```scss
@import normalize.sass @import styles/font body font-family: $ff-gothic; @import normalize.sass;
@import styles/font body font-family: $ff-gothic;
``` ```
> `$ff-gothic`は [uetchy/styles](https://github.com/uetchy/styles) の _font.sass_ で定義されている font-family だ。 > `$ff-gothic`は [uetchy/styles](https://github.com/uetchy/styles) の _font.sass_ で定義されている font-family だ。

View File

@ -1,5 +1,5 @@
--- ---
title: 'Hugo Paper: well-simplified theme for Hugo' title: "Hugo Paper: well-simplified theme for Hugo"
date: 2015-07-05 09:00:00 +09:00 date: 2015-07-05 09:00:00 +09:00
redirect_from: "/blog/2015/07/05/hugo-paper" redirect_from: "/blog/2015/07/05/hugo-paper"
--- ---
@ -11,5 +11,5 @@ When I created my blog, there are no well simplified [Hugo](http://gohugo.io) th
Just run following oneliner and you will be ready to start using Hugo Paper. Just run following oneliner and you will be ready to start using Hugo Paper.
```bash ```bash
$ git submodule add https://github.com/uetchy/hugo-paper.git themes/hugo-paper && git submodule update git submodule add https://github.com/uetchy/hugo-paper.git themes/hugo-paper && git submodule update
``` ```

View File

@ -5,17 +5,17 @@ categories:
- recipe - recipe
redirect_from: "/blog/2017/04/23/apple-pie" redirect_from: "/blog/2017/04/23/apple-pie"
image: "/uploads/apple-pie.jpg" image: "/uploads/apple-pie.jpg"
--- ---
![apple-pie.jpg](/uploads/apple-pie.jpg)
再現性の高いアップルパイの作り方です。材料は初出時に太字にしました。 ![](/uploads/apple-pie.jpg)
再現性の高いアップルパイのレシピが完成したので共有する。材料は初出時に太字にした。
# 注意事項 # 注意事項
* レモン汁はポッカレモンで代用可 - レモン汁はポッカレモンで代用可
* 範囲指定されている値は 2 回目から好みで変化させること - 範囲指定されている値は 2 回目から好みで変化させること
* 焼きあがったらただちにパイ皿を取り除くこと。冷めてからではより困難になる - 焼きあがったらただちにパイ皿を取り除くこと。冷めてからではより困難になる
# 手順 # 手順

View File

@ -9,15 +9,15 @@ image: http://uechi-public.s3.amazonaws.com/github/gh-compare.gif
![](http://uechi-public.s3.amazonaws.com/github/gh-compare.gif) ![](http://uechi-public.s3.amazonaws.com/github/gh-compare.gif)
[gh-compare](https://github.com/uetchy/gh-compare) を作りました。この小さなツールを使って、導入を検討しているライブラリ群の比較表をコマンド1つで作ることが出来ます [gh-compare](https://github.com/uetchy/gh-compare) を作た。この小さなツールを使って、導入を検討しているライブラリ群の比較表をコマンド1つで作ることが出来
ライブラリのリポジトリが GitHub にあることが前提になりますが、プロジェクトの勢いからサイズまで俯瞰することが出来ます ライブラリのリポジトリが GitHub にあることが前提になるが、プロジェクトの勢いからサイズまで俯瞰することが出来る
最高と最悪の値はそれぞれ緑色と赤色に着色されるので、違いが一目瞭然でわかります 最高と最悪の値はそれぞれ緑色と赤色に着色されるので、違いが一目瞭然でわか
## インストール ## インストール
`gh-compare`モジュールは`npm`からインストール出来ます `gh-compare`モジュールは`npm`からインストール出来
```bash ```bash
npm install --global gh-compare npm install --global gh-compare
@ -25,10 +25,10 @@ npm install --global gh-compare
## 使い方 ## 使い方
`gh-compare`の後にスペース区切りで比較したいリポジトリを書きます `gh-compare`の後にスペース区切りで比較したいリポジトリを書
```bash ```bash
gh-compare facebook/react vuejs/vue riot/riot angular/angular gh-compare facebook/react vuejs/vue riot/riot angular/angular
``` ```
もし変な挙動を見つけたら、プロジェクトの [Issues](https://github.com/uetchy/gh-compare/issues/new) に是非書いてください。 もし変な挙動を見つけたら、プロジェクトの [Issues](https://github.com/uetchy/gh-compare/issues/new) に是非書いてほしい。

View File

@ -4,40 +4,45 @@ date: 2017-02-13 21:52:00 +09:00
redirect_from: "/blog/2017/02/13/markdown-friendly-note-taking-apps" redirect_from: "/blog/2017/02/13/markdown-friendly-note-taking-apps"
--- ---
UI が秀逸な Markdown ノートアプリを紹介します。 UI が秀逸な Markdown ノートアプリを紹介す
# ノートアプリの種類 # ノートアプリの種類
ノートアプリには大きく分けて 2 種類があります。 ノートアプリには大きく分けて 2 種類がある。Notes のようにノートを一箇所にまとめて管理するシングルトンタイプと、TextEdit のようにファイル毎にウィンドウが開くタイプだ。
Notes のようにノートを一箇所にまとめて管理するシングルトンタイプと、TextEdit のようにファイル毎にウィンドウが開くタイプです。 この記事では、前者を Notes タイプ、後者を TextEdit タイプと呼称し区別する。
この記事では、前者を Notes タイプ、後者を TextEdit タイプと呼称し区別します。
# Notes タイプ # Notes タイプ
## Obsidian
<https://obsidian.md>
機能性・自由度双方で最強のエディター。僕もすでにいくつかプラグインを書いた。
## FSNotes
<https://fsnot.es>
オープンソースかつ Swift ネイティブでサクサク動くウクライナ産のエディター。僕もいくらかコミットしている。
## Notion ## Notion
<https://notion.so> <https://notion.so>
サンフランシスコの Notion Lab 社が開発する多機能ノートアプリです。Web 版、iOS/Android 版と Mac 版が用意されており、Markdown ライクな記法で自由度の高いノートテイキングが出来ます。 サンフランシスコの多機能ノートアプリ。Web 版、iOS/Android 版と Mac 版が用意されており、Markdown ライクな記法で自由度の高いノートテイキングが出来る。起動に時間がかかるのがかなり痛い
## Bear ## Bear
<http://www.bear-writer.com> <http://www.bear-writer.com>
北イタリア産のノートアプリです。記事中に **ハッシュタグ** を書き込むと、リストでまとめてくれる機能が秀逸です。 北イタリア発のノートアプリ。記事中に **ハッシュタグ** を書き込むと、リストでまとめてくれる機能が秀逸。
iCloud を使って、macOS と iOS アプリの間でノートを同期することが出来ます。 iCloud を使って、macOS と iOS アプリの間でノートを同期することが出来る。
## SnippetsLab
<https://www.renfei.org/snippets-lab/>
正確にはスニペット管理アプリですが、Markdown+MathJax をサポートしており、数式を使ったメモを書くことが出来ます。
## Inkdrop ## Inkdrop
<https://www.inkdrop.info> <https://www.inkdrop.info>
個人開発のノートアプリです。プラグインにより多くの機能を追加することが出来ます 日本発のノートアプリ。プラグインにより多くの機能を追加することが出来る。
# TextEdit タイプ # TextEdit タイプ
@ -45,4 +50,4 @@ iCloud を使って、macOS と iOS アプリの間でノートを同期する
<https://typora.io> <https://typora.io>
エディタとプレビューが一体化したタイプのエディタです。左右分割よりも WYSIWYG エディタの方がわかりやすい派なので、これ一択です エディタとプレビューが一体化したタイプのエディタ。左右分割よりも WYSIWYG エディタの方が体験が良い

View File

@ -11,22 +11,15 @@ Maybe you don't need `pyenv` and/or `virtualenv` in most cases.
> Don't have `brew`? Go to <https://brew.sh>. > Don't have `brew`? Go to <https://brew.sh>.
``` ```
brew install python3 brew install python
``` ```
If you still need Python 2, run `brew install python`. If you still need Python 2, run `brew install python@2`.
## Install Jupyter Notebook ## Install Jupyter Notebook
``` ```
pip3 install jupyter pip install jupyter
python3 -m ipykernel install --user
```
You also want Python 2 kernel, so then:
```
pip install ipykernel
python -m ipykernel install --user python -m ipykernel install --user
``` ```
@ -34,12 +27,12 @@ That's all.
# How about `virtualenv`? # How about `virtualenv`?
Since Python 3 got its own virtual environment tool called [venv](https://docs.python.org/3/library/venv.html), You no longer need `virtualenv` itself. Since Python 3 got its own virtual environment tool called [venv](https://docs.python.org/3/library/venv.html), You no longer need `virtualenv`.
If you want a virtual envs on your project, run: If you want a virtual envs on your project, run:
``` ```
python3 -m venv venv python -m venv venv
source ./venv/bin/activate source ./venv/bin/activate
``` ```

View File

@ -4,17 +4,17 @@ date: 2017-02-13 14:20:00 +09:00
redirect_from: "/blog/2017/02/13/nvidia-titan-x-macpro-early-2008" redirect_from: "/blog/2017/02/13/nvidia-titan-x-macpro-early-2008"
--- ---
MacPro Early 2008 という骨董品に NVIDIA Titan X (Maxwell)を積んだところ、いくつかの問題にぶつかりました。この記事でそれらの問題と解決策について書きます MacPro Early 2008 という骨董品に NVIDIA Titan X (Maxwell)を積んだところ、いくつかの問題にぶつかった。この記事でそれらの問題と解決策について書く
# NVIDIA ドライバーが非対応 # NVIDIA ドライバーが非対応
あまりにも古いアーキテクチャの MacPro に対して NVIDIA のグラフィックドライバーが対応していません あまりにも古いアーキテクチャの MacPro に対して NVIDIA のグラフィックドライバーが対応していない
そこで、適切なバージョンの[NVIDIA Web Driver](http://www.macvidcards.com/drivers.html)をインストールすることでこれを解決しました。 そこで、適切なバージョンの[NVIDIA Web Driver](http://www.macvidcards.com/drivers.html)をインストールすることでこれを解決した。
これには問題もあります。macOS のアップデートをインストールするたびに、それに対応したドライバーを都度インストールする必要がありました ただし、macOS アップデートをインストールするたびに、それに対応したドライバーを都度インストールする必要があ
ドライバーをインストールするまでは画面に何も映りません。そこで、pkg 形式のドライバーを`scp`で MacPro に転送して、`installer`を使ってドライバーをインストールすることにしました。 ドライバーをインストールするまでは画面に何も映らない。そこで、pkg 形式のドライバーを`scp`で MacPro に転送して、`installer`を使ってドライバーをインストールすることにした。
``` ```bash
scp driver.pkg MacPro.local:~ scp driver.pkg MacPro.local:~
ssh MacPro.local ssh MacPro.local
sudo installer -pkg ./driver.pkg -target / sudo installer -pkg ./driver.pkg -target /
@ -22,7 +22,7 @@ sudo installer -pkg ./driver.pkg -target /
# 電源ユニット(PSU)のパワー不足 # 電源ユニット(PSU)のパワー不足
TITAN X(Maxwell)が要求するパワーを MacPro の PSU は提供することが出来ません TITAN X(Maxwell)が要求するパワーを MacPro の PSU は提供することが出来ない
そこで、秋葉原の PC パーツショップで追加の PSU を購入して、GPU 専用の電源として使いました。 そこで、PC パーツショップで追加の PSU を購入して、GPU 専用の電源として使た。
ここで新たな問題が生まれます。正しくパワーを提供するためには MacPro の PSU と追加の PSU を同期させる必要があり、またそれを実現するパーツもあるのですが、場合によっては GPU を破損してしまう危険性がありました。 ここで新たな問題が生まれ。正しくパワーを提供するためには MacPro の PSU と追加の PSU を同期させる必要があり、またそれを実現するパーツもあるが、場合によっては GPU を破損してしまう危険性があた。
今回は電源を同期することは見送り、個別にスイッチを入れることで解決しました。 今回は電源を同期することは見送り、個別にスイッチを入れることで解決した。

View File

@ -2,28 +2,26 @@
title: デザイナーとしてOSSに貢献できること title: デザイナーとしてOSSに貢献できること
date: 2017-12-26T15:24:00.000+00:00 date: 2017-12-26T15:24:00.000+00:00
redirect_from: "/blog/2017/12/27/oss-for-designers" redirect_from: "/blog/2017/12/27/oss-for-designers"
--- ---
GitHub で公開されている OSS にちょっとした Pull-request を送るのが私の趣味です。
そのような Pull-request の中にはコードだけでは無く、時にロゴデザインが含まれていることもあります。 GitHub で公開されている OSS に Pull-request を送るのが僕の趣味だ。
そのような Pull-request の中にはコードだけでは無く、時にロゴデザインが含まれていることもある。
## textlint ## textlint
文章校正ツールである[textlint](https://textlint.github.io/)プロジェクトの例では、作者の azu 氏が[ロゴの募集をされている Issue](https://github.com/textlint/textlint/issues/56)を見かけ、[ちょっとしたアイディア](https://github.com/textlint/textlint/issues/56#issuecomment-160050653)をコメントしたことから始まりました。 文章校正ツールである[textlint](https://textlint.github.io/)プロジェクトの例では、作者の azu 氏が[ロゴを募集している Issue](https://github.com/textlint/textlint/issues/56)を見かけ、[ちょっとしたアイディア](https://github.com/textlint/textlint/issues/56#issuecomment-160050653)をコメントしたことから始また。
その後、[より詳細な検討](https://github.com/textlint/media/pull/1)を重ねた結果、私がデザインした textlint のロゴは無事プロジェクトに受け入れられました。 その後、[より詳細な検討](https://github.com/textlint/media/pull/1)を重ねた結果、僕がデザインした textlint のロゴが無事プロジェクトに受け入れられた。
このようにプロジェクトの作者が Issue 等でロゴを募集することは一般的であり、WebAssembly のロゴも[公募のコンペティション](https://github.com/WebAssembly/design/issues/112)で決まっています このようにプロジェクトの作者が Issue 等でロゴを募集することは、実は思っているより一般的だ。WebAssembly のロゴも[公募のコンペティション](https://github.com/WebAssembly/design/issues/112)で決まってい
一方で自らロゴの提案をすることもあります 一方で自らロゴの提案をすることもあ
## ⌘ 英かな ## ⌘ 英かな
macOS のキーバインドを変更するアプリである[⌘ 英かな](https://ei-kana.appspot.com/)の例では、アイコンの Enhancement を思いつき、[Pull-request](https://github.com/iMasanari/cmd-eikana/pull/5)を送ったところ、本当にすぐにマージしてくれました。 macOS のキーバインドを変更するアプリである[⌘ 英かな](https://ei-kana.appspot.com/)の例では、アイコンの改善案を思いつき、[Pull-request](https://github.com/iMasanari/cmd-eikana/pull/5)を送ったところ、驚くほどすぐにマージしてくれた。
他の方の例では、[Annict](https://github.com/annict/annict/issues/120)などがあります。
## 結論 ## 結論
以上のように、OSS コミュニティではコードだけでなくデザインワークに対してもオープンにコミットすることが出来ます OSS コミュニティではコードだけでなくデザインワークに対してもオープンにコミットすることが出来
デザイナーの皆さんが OSS への貢献に関わる機会がますます増えることを楽しみにしています(そして OSS 開発者の多くは、クールなロゴが提案されることを心から待ち望んでいます!) デザイナー諸氏は機会があれば興味のある OSS に貢献してみることをオススメする(実際 OSS 開発者の多くは、口にせずともクールなロゴが提案されることを心から待ち望んでいる!)

View File

@ -4,12 +4,12 @@ date: 2017-02-02 00:20:00 +09:00
redirect_from: "/blog/2017/02/02/sim-card-travel" redirect_from: "/blog/2017/02/02/sim-card-travel"
--- ---
世界中で 3G 通信が出来る[GigSky](http://www.gigsky.jp)の SIM を 3 日間の台湾旅行で使ってみました。 世界中で 3G 通信が出来る[GigSky](http://www.gigsky.jp)の SIM を 3 日間の台湾旅行で使ってみた。
GigSky では、その国の最初のアクティベーションに限り、3 日・100MB 分が無料で使えるので、今回の旅行では課金をせずに SIM を使うことが出来ました。 GigSky では、その国の最初のアクティベーションに限り、3 日・100MB 分が無料で使えるので、今回の旅行では課金をせずに SIM を使うことが出来た。
料金設定は現地で購入できる SIM と比べてかなり高く、旅行先で都度 SIM を購入する手間とのトレードオフとなります 料金設定は現地で購入できる SIM と比べてかなり高く、旅行先で都度 SIM を購入する手間とのトレードオフとな
GigSky アプリをインストールしておくと、データ残量が半分以下になったタイミングでプッシュ通知を飛ばしてくれます。また、データ通信枠をトップアップする仕組みなので、追加データ枠の購入さえしなければ余計な課金をせずに済むという利点があります GigSky アプリをインストールしておくと、データ残量が半分以下になったタイミングでプッシュ通知を飛ばしてくれ。また、データ通信枠をトップアップする仕組みなので、追加データ枠の購入さえしなければ余計な課金をせずに済むという利点もある
ただ、やはり価格設定が高めなのに加えて現地での SIM 購入はそこまで苦ではないので、3 日以上の旅行で使う機会は無いでしょう。 ただ、やはり価格設定が高めなのに加えて現地での SIM 購入はそこまで苦ではないので、3 日以上の旅行で使う機会は無いだろう。

View File

@ -18,7 +18,7 @@ I made a simple tool to get you covered with the above guidelines.
# gh-compare # gh-compare
![screencast.gif](/uploads/screencast.gif) ![](/uploads/screencast.gif)
[gh-compare](https://github.com/uetchy/gh-compare) is a simple terminal app to explore your candidates and aggregate a result into a nice-looking report. [gh-compare](https://github.com/uetchy/gh-compare) is a simple terminal app to explore your candidates and aggregate a result into a nice-looking report.
@ -27,7 +27,7 @@ npm install -g gh-compare
gh-compare facebook/react vuejs/vue riot/riot gh-compare facebook/react vuejs/vue riot/riot
``` ```
![1xfd1gcrfntpft5bbu5s.png.jpeg](/uploads/1xfd1gcrfntpft5bbu5s.png.jpeg) ![](/uploads/1xfd1gcrfntpft5bbu5s.png.jpeg)
You will see the GitHub activities for each candidate at once. You will see the GitHub activities for each candidate at once.
It could help you to decide which library you would adopt! It could help you to decide which library you would adopt!

View File

@ -6,7 +6,7 @@ date: 2018-09-02 03:23:00 +09:00
How do you know what packages that project/library depend on and what exactly are that packages doing for? How do you know what packages that project/library depend on and what exactly are that packages doing for?
You'll want to quickly survey on them. So [npm-deps-list](https://github.com/uetchy/npm-deps-list) is here for. You'll want to quickly survey on them. So [npm-deps-list](https://github.com/uetchy/npm-deps-list) is here for.
![screen-1.png.jpeg](/uploads/screen-1.png.jpeg) ![](/uploads/screen-1.png.jpeg)
You can install them using `npm` or `yarn`. You can install them using `npm` or `yarn`.

View File

@ -4,81 +4,81 @@ date: 2018-08-05 00:00:00 +09:00
redirect_from: "/blog/2018/08/05/life-automation" redirect_from: "/blog/2018/08/05/life-automation"
--- ---
生活にオートメーションを上手く取り入れ、本当にやりたいことに集中できる環境をつくりましょう。 生活にオートメーションを上手く取り入れ、本当にやりたいことに集中できる環境をつくう。
# 洗濯の自動化 # 洗濯の自動化
Panasonic のドラム洗濯乾燥機を使っています。威力を最大限に享受するため、タンブラー乾燥向けの普段着を揃えておくことも重要です Panasonic のドラム洗濯乾燥機を使ってい。威力を最大限に享受するため、タンブラー乾燥向けの普段着を揃えておくことも重要
洗剤は粉と液体とが一体化したジェルボール洗剤が便利です。ドラムの底にひとつ置くだけでよく、計量する必要がありません 洗剤は粉と液体とが一体化したジェルボール洗剤が便利だ。ドラムの底にひとつ置くだけでよく、計量する必要がない
# 食器洗いの自動化 # 食器洗いの自動化
Panasonic の一人暮らし用コンパクト食洗乾燥機を使っています Panasonic の一人暮らし用コンパクト食洗乾燥機を使ってい
洗濯機と同じく、食洗機専用のジェルボール洗剤を使えば計量する手間を省けます 洗濯機と同じく、食洗機専用のジェルボール洗剤を使えば計量する手間を省け
# 照明の自動化 # 照明の自動化
Philips Hue はインターネット経由で明るさや色相をコントロールすることができる電球です Philips Hue はインターネット経由で明るさや色相をコントロールすることができる電球
- 「家から離れたら消灯」 - 「家から離れたら消灯」
- 「家に近付いたら点灯」 - 「家に近付いたら点灯」
- 「日が暮れたら暖色系に切り替える」 - 「日が暮れたら暖色系に切り替える」
- 「23 時になったら消灯」 - 「23 時になったら消灯」
など多様なルールを作ることができます。外の明るさに合わせて照明の明るさを調整して、概日リズムが崩れにくいようルールを決めています など多様なルールを作ることができ。外の明るさに合わせて照明の明るさを調整して、概日リズムが崩れにくいようルールを決めてい
# 空調の自動化 # 空調の自動化
Nature Remo でエアコンの操作を自動化しました。 Nature Remo でエアコンの操作を自動化した。
- 「湿度が高ければドライに変更」 - 「湿度が高ければドライに変更」
- 「家から離れたら電源オフ」 - 「家から離れたら電源オフ」
- 「朝になったら冷房へ切り替え」 - 「朝になったら冷房へ切り替え」
など多様なルールを作ることができます など多様なルールを作ることができ
Nature Remo 自体はエアコン専用ではなく、赤外線で操作出来るデバイスであればなんでも操作できます。家ではテレビの電源・音量もこれで操作しています。 Nature Remo 自体はエアコン専用ではなく、赤外線で操作出来るデバイスであればなんでも操作できる(例えばシーリングファンやテレビの電源・音量など)
[Nature Remo を NodeJS で操作するライブラリ](https://github.com/uetchy/nature-remo)を作ったので触ってみてください。ライブラリ経由で温度・湿度・明度のセンサー値を取得したり、指定したモードにエアコンを切り替えることができます [Nature Remo を NodeJS で操作するライブラリ](https://github.com/nature-remo/nature-remo)を作ったので是非触ってみてほしい。ライブラリ経由で温度・湿度・明度のセンサー値を取得したり、指定したモードにエアコンを切り替えることができ
# 自動施錠・自動開錠 # 自動施錠・自動開錠
Qrio Lock をドアに取り付けることでオートロック・アンロックができるようになりました。 Qrio Lock をドアに取り付けることでオートロック・アンロックができるようになた。
エントランスのドアに関しては、インターホンに Switch Bot を貼り付けて Shortcuts で解錠できるようにしておき、それを iPhone の背面トリプルタップで呼び出せるよう設定することでキーレスエントリー化しています エントランスのドアに関しては、インターホンに Switch Bot を貼り付けて Shortcuts で解錠できるようにしておき、それを iPhone の背面トリプルタップで呼び出せるよう設定することでキーレスエントリー化している。少し Hacky だが、動けばなんでも良い
# ホームアシスタント # ホームアシスタント
Raspberry Pi に Home Assistant をインストールし、スマート家電を取りまとめるアシスタントとして使っています。Nature Remo や Hue、Switch Bot に紐づいているデバイスを Home Assistant のアプリからまとめて操作できます Raspberry Pi に Home Assistant をインストールし、スマート家電を取りまとめるアシスタントとして使ってい。Nature Remo や Hue、Switch Bot に紐づいているデバイスを Home Assistant のアプリからまとめて操作でき
Apple Home より柔軟な自動化ルールを作ることができ、例えば「朝になったら照明とエアコンをつける(気温が高くかつ誰かが家にいる場合のみ)」といった気の利いた自動化ができます Apple Home より柔軟な自動化ルールを作ることができ、例えば「朝になったら照明とエアコンをつける(気温が高くかつ誰かが家にいる場合のみ)」といった気の利いた自動化ができ
# 睡眠記録の自動化 # 睡眠記録の自動化
Withings 改め Nokia 改め Withings の Sleep を使っています Withings 改め Nokia 改め Withings の Sleep を使ってい
寝るとき身体にウェアラブルデバイスを身につけたくないので、マットレスの下に敷いておくだけで自動計測してくれるのはありがたいです 寝るときにウェアラブルデバイスを身に付けたくない派としては、マットレスの下に敷いておくだけで睡眠を自動計測してくれるのはありがたい。
機能としては、入眠・起床検知、心拍数記録、睡眠深度解析、いびき検出等があります 機能としては、入眠・起床検知、心拍数記録、睡眠深度解析、いびき検出等があ
# 体重記録の自動化 # 体重記録の自動化
Withings の Wi-Fi Scale を使っています。体重と体脂肪率、心拍数、BMI を Wi-Fi 経由でクラウドに自動記録し、アプリで推移を確認できます Withings の Wi-Fi Scale を使ってい。体重と体脂肪率、心拍数、BMI を Wi-Fi 経由でクラウドに自動記録し、アプリで推移を確認でき
Wi-Fi Scale には CO2 センサーもついており、部屋の二酸化炭素濃度を記録してくれます Wi-Fi Scale には CO2 センサーもついており、部屋の二酸化炭素濃度を記録してくれ
# オンラインスーパー # オンラインスーパー
普段は業務スーパーを使いつつ、重くて量のある商品に関してはイトーヨーカドーのオンラインスーパーに頼っています 普段は業務スーパーを使いつつ、重くて運ぶのが大変な商品に関してはイトーヨーカドーのオンラインスーパーを頼っている
お気に入りリストへ水、米、卵、かぼちゃなど毎回買うものを登録しておくことで、慣れれば 5 分程度で注文が完了します。あとは指定した時間に家へ商品を届けてくれます お気に入りリストへ水、米、卵、かぼちゃなど毎回買うものを登録しておくことで、慣れれば 5 分程度で注文が完了す。あとは指定した時間に家へ商品を届けてくれ
# 自動家計簿 # 自動家計簿
Moneytree を使っています。支出を自動で食費、趣味、日用品などに仕分けてくれるため、使いすぎに気付きやすいです。無現金縛りプレイと相性が良いです Moneytree を使ってい。支出を自動で食費、趣味、日用品などに仕分けてくれるため、使いすぎに気付きやすい。無現金縛りプレイと相性が良い。
# 気になる製品 # 気になる製品
## ルンバ ## ルンバ
絨毯を取り除くわけにもいかないので二の足を踏んでいます。ルンバについては[KainokiKaede's diary](http://kainokikaede.hatenablog.com/entry/2018/07/24/185452)の記事を読んでください 絨毯を取り除くわけにもいかないので二の足を踏んでいる。使用感については[KainokiKaede's diary](http://kainokikaede.hatenablog.com/entry/2018/07/24/185452)の素晴らしい記事を共有しておく

View File

@ -1,5 +1,5 @@
--- ---
title: 'Math API: LaTeX Math as SVG image' title: "Math API: LaTeX Math as SVG image"
date: 2018-10-23 03:19:00 +09:00 date: 2018-10-23 03:19:00 +09:00
--- ---
@ -9,25 +9,22 @@ Spending some time, I made [Math API](https://math.now.sh), that renders LaTeX M
So you can place your equation on almost everywhere on which you could put `<img>` or Markdown (`![]()`), such as GitHub, Jupyter Notebook or dev.to (here!). So you can place your equation on almost everywhere on which you could put `<img>` or Markdown (`![]()`), such as GitHub, Jupyter Notebook or dev.to (here!).
```markdown ```markdown
![](https://math.now.sh?from=\LaTeX) ![](https://math.now.sh?from=\LaTeX)
``` ```
![Equation](https://math.now.sh?from=%5CLaTeX) ![Equation](https://math.now.sh?from=%5CLaTeX)
```markdown ```markdown
![](https://math.now.sh?from=\log\prod^N_{i}x_{i}=\sum^N_i\log{x_i}) ![](https://math.now.sh?from=\log\prod^N_{i}x_{i}=\sum^N_i\log{x_i})
``` ```
![Equation](https://math.now.sh?from=%5Clog%5Cprod%5EN_%7Bi%7Dx_%7Bi%7D%3D%5Csum%5EN_i%5Clog%7Bx_i%7D) ![Equation](https://math.now.sh?from=%5Clog%5Cprod%5EN_%7Bi%7Dx_%7Bi%7D%3D%5Csum%5EN_i%5Clog%7Bx_i%7D)
# Inline image # Inline image
![fqea9nq2wv9in15lqlf3.png.jpeg](/uploads/fqea9nq2wv9in15lqlf3.png.jpeg) ![](/uploads/fqea9nq2wv9in15lqlf3.png.jpeg)
![43slt0h6dfhox1xwmuti.png.jpeg](/uploads/43slt0h6dfhox1xwmuti.png.jpeg) ![](/uploads/43slt0h6dfhox1xwmuti.png.jpeg)
It is possible to generate an inline equation by changing the query from `from` to `inline`. It is possible to generate an inline equation by changing the query from `from` to `inline`.
@ -39,7 +36,7 @@ It is possible to generate an inline equation by changing the query from `from`
Also, there is the online editor available at https://math.now.sh. Also, there is the online editor available at https://math.now.sh.
![gg2wil3exu9lyj7ppuoy.png](/uploads/gg2wil3exu9lyj7ppuoy.png) ![](/uploads/gg2wil3exu9lyj7ppuoy.png)
# Conclusion # Conclusion

View File

@ -2,38 +2,22 @@
title: 普段使いしているもの title: 普段使いしているもの
date: 2018-03-29 22:33:00 +09:00 date: 2018-03-29 22:33:00 +09:00
redirect_from: "/blog/2018/03/29/products-guide" redirect_from: "/blog/2018/03/29/products-guide"
updated: 2018-08-03 09:00:00 +09:00
--- ---
普段使いしているプロダクトを紹介する。 普段使いしているプロダクトを紹介する。
「20XX 年に買ってよかったもの」を毎年書くのではなく、この記事を定期的に更新しようと思う。 「20XX 年に買ってよかったもの」を毎年書くのではなく、この記事を定期的に更新していく。
<!-- toc -->
# ハードウェア # ハードウェア
## [MacBook 12"](http://www.apple.com/jp/shop/buy-mac/macbook/%E3%82%B4%E3%83%BC%E3%83%AB%E3%83%89-512gb) ## MacBook Pro 15 インチ
スペックを犠牲にして持ち運びに極振りした超コンパクトな MacBook Thunderbolt ディスプレイと Roost を合わせて使うと QoL が高まる
## [EARIN M-2](https://earin.com) ## [WF-1000XM4](https://www.sony.jp/headphone/products/WF-1000XM4/)
EARIN M-1 から買い替えた。 EARIN M-2 と BOSE から移行した。良い意味で Sony らしからぬ UX の良さに驚く。
コンパクトさに極振りした完全無線イヤホン。万人受けしないプロダクトではあるが、その特性を理解して使えば手放せないギアになる。
[レビュー記事](https://uechi.io/blog/2018/03/24/earin-m2-first-look)
## [Bose QuietControl 30](https://www.bose.co.jp/ja_jp/products/headphones/earphones/quietcontrol-30.html)
ノイズキャンセラーイヤホン QuietComfort 20 の後継機種。ワイヤレス化して、取り回しがよくなった。QuietControl の名の通り、ノイズキャンセリングの度合いを調整するボタンが搭載されている。しかし、実際のところ最大と最小しか使わないので、ボタンを押す手間がかえって不便に感じる。
ノイズ除去能は随一なので、旅行には必ず持っていく。
## [Apple Watch series 2 Nike+](http://www.apple.com/jp/shop/buy-watch/apple-watch-nike/%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%82%B0%E3%83%AC%E3%82%A4-%E3%82%A2%E3%83%AB%E3%83%9F%E3%83%8B%E3%82%A6%E3%83%A0-%E3%83%96%E3%83%A9%E3%83%83%E3%82%AF-%E3%83%9C%E3%83%AB%E3%83%88-%E3%82%B9%E3%83%9D%E3%83%BC%E3%83%84%E3%83%90%E3%83%B3%E3%83%89?preSelect=false&product=MP0J2J/A&step=detail#)
最終的に以下の機能しか使わなくなった。
- 時計
- タイマー
- 運動中の心拍数や歩数の計測
- Suica
- メッセージの閲覧・返信
## [M-Audio Keystation 88](http://m-audio.com/products/view/keystation-88) ## [M-Audio Keystation 88](http://m-audio.com/products/view/keystation-88)
@ -47,93 +31,36 @@ EARIN M-1 から買い替えた。
## [Nature Remo](https://nature.global/) ## [Nature Remo](https://nature.global/)
スマートな赤外線リモコン。 スマートな赤外線リモコン。Home Assistant と組み合わせて使っている。
Google Home や Alexa、IFTTT と連携して使っている。
## [Knirps Big Duomatic Safety](http://www.knirps.jp/product.html) ## [Knirps Big Duomatic Safety](http://www.knirps.jp/product.html)
知りうる中で最も大きなサイズの自動開閉折りたたみ傘。コンビニで売っている傘よりも大きいので安心感が違う 知りうる中で最も大きなサイズの自動開閉折りたたみ傘。コンビニで売っている傘よりも大きいので安心感が凄い
## [Shure MOTIV MV88](https://www.shure.co.jp/go/motiv-mic/jp/mv88/) ## [Shure MOTIV MV88](https://www.shure.co.jp/go/motiv-mic/jp/mv88/)
非常にコンパクトなコンデンサーマイク。Lightning 端子を備えており、iPhone/iPad に繋いで録音できる。 非常にコンパクトなコンデンサーマイク。Lightning 端子を備えており、iPhone/iPad に繋いで録音できる。
## [LEZYNE CNC Floor Drive ABS2](http://www.wiggle.jp/lezyne-cnc-floor-drive-abs2-%E3%83%95%E3%83%AD%E3%82%A2%E3%83%9D%E3%83%B3%E3%83%97/) ## [LEZYNE CNC Floor Drive ABS2](http://www.wiggle.jp/lezyne-cnc-floor-drive-abs2-%E3%83%95%E3%83%AD%E3%82%A2%E3%83%9D%E3%83%B3%E3%83%97/)
デザインと機能性が両立した自転車の空気入れ。仏式と米式バルブに対応している。回転するねじ込みノズルが特徴的で、BROMPTON のような小口径タイヤを持つ自転車でも問題なく使える。 デザインと機能性が両立した自転車の空気入れ。仏式と米式バルブに対応している。回転するねじ込みノズルが特徴的で、BROMPTON のような小口径タイヤを持つ自転車でも問題なく使える。
## [iPad Pro 10.5 インチ](http://www.apple.com/jp/ipad-pro/) ## [iPad Pro 12.9 インチ](http://www.apple.com/jp/ipad-pro/)
[Apple Pencil](http://www.apple.com/jp/shop/product/MK0C2J/A/ipad-pro%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AEapple-pencil)との組み合わせがとても良い。ノートを書いたり、絵を描くのに使っている。 Apple Pencil との組み合わせがとても良い。ノートを書いたり、絵を描くのに使っている。
スタンドは、Twelve South の[Compass 2](http://www.apple.com/jp/shop/product/HF022ZM/B/twelve-south-compass-2-stand-for-ipad)を使っている。折りたたむと Apple Pencil2 本分くらいに小さくなる。
# サブスクリプションサービス # サブスクリプションサービス
## G Suite > Google Workspace、Dropbox Pro、iTunes Match は解約してセルフホストに移行した。
月 540 円。 ## Apple One
好きなドメインで Google サービスを利用出来るので使っている。Gmail にも y@uechi.io でログイン出来る。
## Apple Music 今まで契約していた Apple Music と iCloud 50GB プラン(バックアップ用)を合わせた額とほとんど同じなので Apple One に切り替えた。
学割で月 480 円。普段の音楽ソースはこれに統一している。
## iTunes Match
CD からインポートした曲をクラウド同期するために有効化。
## iCloud Drive
写真やクラウド同期のために容量を購入した。
## Dropbox Pro
あらゆる作業データを保存しているため容量を増やした。
## Amazon Student
Prime の学割版。年間 1400 円。
## Sketch
コンピューター 1 台ごとに課金されるため非常に割高。やめたい。
## Adobe Creative Cloud
学割で月 3000 円。
## Apple Developer Program ## Apple Developer Program
税金。 税金。
## MoneyForward ## [Porkbun](https://porkbun.com/)
オンライン家計簿。電子決済縛りプレイと相性が良い。 ドメインレジストラ。お名前.com、iwantmyname、Google Domains、Namecheap といろいろ使ってきたが、最終的にここに落ち着いた。この手のサービスにしては良くデザインされており使いやすい。
## [Namecheap](https://www.namecheap.com/)
ドメインレジストラ。お名前.com から iwantmyname、そして Namecheap へと移行してきた。この手のサービスにしては良くデザインされており、使いやすい。
一度転送でトラブルがあり、カスタマーサポートのお世話になったことがあったが、しっかりとした仕事をしてくれた。
## [Netflix](https://www.netflix.com/jp/)
既存コンテンツの配信だけに留まらず、オリジナル作品の制作にも意欲的に取り組んでいる。
観たい作品が無くなったら購読をキャンセルし、必要に応じて再購読している。
## 珈琲きゃろっと
珈琲豆の定期宅配サービス。配送日の直前に焙煎をするため豆が新鮮なのが特徴。他にも土井珈琲が同様のサービスを提供しているので比べてみて自分に合った方を選ぼう。
## TastyTable
使い切りの食材とレシピを定期的に、または都度注文で宅配してくれるサービス。
普段なら絶対に作らないような献立が提案されてくるので、週末に普段とは一風変わった食事を楽しみたい人にオススメのサービス。
## TENTAL
テントや焚き火グッズのようなキャンプ用品をレンタル出来るサービス。
テントは高価な上にほとんど買い換えないタイプの製品なので、このようなサービスを通じて様々な種類のテントを借りて実地で試して、眼を肥やしてから購入した方が良いと感じた。
3 シーズン用を買い揃えて、やる頻度の低い冬用の装備だけレンタルするという戦術もある。

View File

@ -2,35 +2,36 @@
date: 2019-10-25 19:49:01 +0900 date: 2019-10-25 19:49:01 +0900
title: Bose Noise Cancelling Headphones 700レビュー title: Bose Noise Cancelling Headphones 700レビュー
--- ---
Bose Noise Cancelling Headphones 700 を使い始めて一ヶ月が経ったので、現時点での印象をまとめる。 Bose Noise Cancelling Headphones 700 を使い始めて一ヶ月が経ったので、現時点での印象をまとめる。
## Pros ## Pros
* ノイズキャンセリング性能の高さ - ノイズキャンセリング性能の高さ
* デザイン - 8 台までのマルチペアリング
* 8台までのマルチペアリング - 2 台までのマルチポイント
* 2台までのマルチポイント - タッチコントロール
* タッチコントロール - 3 段階ノイズキャンセリングレベルコントロール
* 3段階ノイズキャンセリングレベルコントロール - 10 段階の内 3 つをあらかじめ選んでおき、ボタンを押してローテーションできる
* 10段階の内3つをあらかじめ選んでおき、ボタンを押してローテーションできる - QC30 は 1 段階ずつしか変更出来ずボタンを連打させられる仕様だったので、大きな改善
* QC30は1段階ずつしか変更出来ずボタンを連打させられる仕様だったので、大きな改善 - バッテリーの持ちの良さ
* バッテリーの持ちの良さ - 15 時間くらいは動く
* 15時間くらいは動く - 有線対応
* 有線対応 - 有線時も ANC が働く
* 有線時もANCが働く - USB-C 充電対応
* USB-C充電対応
## Cons ## Cons
* マルチポイント時の混線ノイズ - マルチポイント時の混線ノイズ
* 音楽再生中にもう一方のデバイスで何か通知音が鳴るとストリームに対して「プツプツ」ノイズが入る - 音楽再生中にもう一方のデバイスで何か通知音が鳴るとストリームに対して「プツプツ」ノイズが入る
* システムサウンドが大きすぎる(変更不可) - システムサウンドが大きすぎる(変更不可)
* 消耗部品の多さ - 公式英語フォーラムで多くのユーザーが苦情を書き込んでいるが、完全に無視されている
* ヒンジ部分はケースに仕舞う度に動かなさいといけないため消耗が心配 - 消耗部品の多さ
* 可動部が多いほど故障率は上がる - ヒンジ部分はケースに仕舞う度に動かなさいといけないため消耗が心配
* 本体側での接続先選択が不可能 - 一般論として、可動部が多いほど故障率が上がる
* QC30では出来ていた本体側のボタンで接続先を選択できる機能が無くなっていた - 本体側での接続先選択が不可能
* ボタン配置のミス - QC30 では出来ていた本体側のボタンで接続先を選択できる機能が無くなっていた
* ボタンが手に触れやすい位置にあるため、ヘッドホンを外す度に間違って押してしまう - ボタン配置のミス
* ストリーム元とボタンの送信先が異なるバグ - ボタンが手に触れやすい位置にあるため、ヘッドホンを外す度に間違って押してしまう
* マルチポイント接続で一方のデバイスで音楽を流している際に、再生ボタンの信号が音楽を流していない方のデバイスに送信されてしまうバグがある - ストリーム元とボタンの送信先が異なるバグ
- マルチポイント接続で一方のデバイスで音楽を流している際に、再生ボタンの信号が音楽を流していない方のデバイスに送信されてしまうバグがある

View File

@ -9,12 +9,12 @@ That's why I created [namae](https://namae.dev).
# namae # namae
![np1a40lrch9m10b1s7nz.gif](/uploads/np1a40lrch9m10b1s7nz.gif) ![](/uploads/np1a40lrch9m10b1s7nz.gif)
[namae](https://namae.dev) is an inter-platform name availability checker for developers and entrepreneurs. [namae](https://namae.dev) is an inter-platform name availability checker for developers and entrepreneurs.
Once you fill out a form with a name you want to use, namae will check through various registries and check if the name is already in use or not. Once you fill out a form with a name you want to use, namae will check through various registries and check if the name is already in use or not.
![pww3x6ycshadfiiotep9.png](/uploads/pww3x6ycshadfiiotep9.png) ![](/uploads/pww3x6ycshadfiiotep9.png)
# Supported Platforms # Supported Platforms
@ -40,11 +40,11 @@ Additionally, the search result comes with a list of projects which has a simila
# Name Suggestion # Name Suggestion
namae also has a unique feature called __Name Suggestion__. It suggests auto-generated names made up of common prefix/suffix and synonyms. Take look at some examples. namae also has a unique feature called **Name Suggestion**. It suggests auto-generated names made up of common prefix/suffix and synonyms. Take look at some examples.
![aas52pwbrueyzrulfiae.png](/uploads/aas52pwbrueyzrulfiae.png) ![](/uploads/aas52pwbrueyzrulfiae.png)
![j6jv0rq4gin28hks1ika.png](/uploads/j6jv0rq4gin28hks1ika.png) ![](/uploads/j6jv0rq4gin28hks1ika.png)
Clicking the suggestion, namae completes the form with it and start searching around the registries. Clicking the suggestion, namae completes the form with it and start searching around the registries.

View File

@ -4,7 +4,7 @@ date: 2019-01-14 00:00:00 +09:00
redirect_from: "/blog/2019/01/14/padsize" redirect_from: "/blog/2019/01/14/padsize"
--- ---
padStart における padSize の求め方です `padStart` における適切な `padSize` の求め方。
$$ $$
\textrm{padSize} = \lceil \log_{10}(\mathbf{arraySize} + 1) \rceil \textrm{padSize} = \lceil \log_{10}(\mathbf{arraySize} + 1) \rceil

View File

@ -4,21 +4,21 @@ date: 2019-06-05 00:00:00 +09:00
redirect_from: "/blog/2019/06/05/sign-and-notarize-electron-app" redirect_from: "/blog/2019/06/05/sign-and-notarize-electron-app"
--- ---
electron-builder を利用して macOS 向け Electron アプリをコード署名し、公証を通過させます electron-builder を利用して macOS 向け Electron アプリをコード署名し、公証を通過させ
> **tl;dr**: コード署名と公証に対応した macOS アプリ Juno のリポジトリを[GitHub で公開](https://github.com/uetchy/juno)しています > **tl;dr**: コード署名と公証に対応した macOS アプリ Juno のリポジトリを[GitHub で公開](https://github.com/uetchy/juno)している。
# Code Sign # Code Sign
アプリのコード署名は`electron-builder`によって自動で行われます。内部的には[electron-osx-sign](https://github.com/electron-userland/electron-osx-sign)が使用されます アプリのコード署名は`electron-builder`によって自動で行われ。内部的には[electron-osx-sign](https://github.com/electron-userland/electron-osx-sign)が使用され
リリース用のアプリにコード署名をするには、Keychain に有効な Developer ID Certificate が格納されている必要があります。macOS Developer Certificate は開発用のコード署名のみ可能なので、リリース用としては不十分です リリース用のアプリにコード署名をするには、Keychain に有効な Developer ID Certificate が格納されている必要がある。macOS Developer Certificate は開発用のコード署名にしか使えないため、リリース用としては不十分だ
まだ証明書を発行していない場合は、[Apple Developer](https://developer.apple.com/account/resources/certificates/list)で証明書の追加ウィザードに進み、**Developer ID Application**を選択して証明書を発行してください まだ証明書を発行していない場合は、[Apple Developer](https://developer.apple.com/account/resources/certificates/list)で証明書の追加ウィザードに進み、**Developer ID Application**を選択して証明書を発行する
# Notarize # Notarize
コード署名済みのアプリを[electron-notarize](https://github.com/electron-userland/electron-notarize)を使用して Apple Notary Service に提出します。 コード署名済みのアプリを[electron-notarize](https://github.com/electron-userland/electron-notarize)を使用して Apple Notary Service に提出す
```js ```js
const { notarize } = require("electron-notarize"); const { notarize } = require("electron-notarize");
@ -31,17 +31,17 @@ notarize({
}); });
``` ```
- **appBundleId**: アプリの Bundle ID です`package.json``build.appId`と同じものを使います - **appBundleId**: アプリの Bundle ID 。`package.json``build.appId`と同じものを使
- **appPath**: `.app`の絶対パスを指定します。 - **appPath**: `.app`の絶対パスを指定す
- **appleId**: Apple Developer として登録している Apple ID を指定します。 - **appleId**: Apple Developer として登録している Apple ID を指定す
- **appleIdPassword**: Apple ID のパスワードです。2 要素認証を必要としないパスワードが必要なので、[Apple ID](https://appleid.apple.com/#!&page=signin)にアクセスして**App-specific Password**を発行してください - **appleIdPassword**: Apple ID のパスワード。2 要素認証を必要としないパスワードが必要なので、[Apple ID](https://appleid.apple.com/#!&page=signin)にアクセスして**App-specific Password**を発行する
- **ascProvider**: Apple Developer の Membership に記載されている**Team ID**を指定します。 - **ascProvider**: Apple Developer の Membership に記載されている**Team ID**を指定す
## electron-builder の afterSign フック ## electron-builder の afterSign フック
electron-builder の afterSign フックを使用して、コード署名が済んだアプリを自動で Notary に提出します。 electron-builder の afterSign フックを使用して、コード署名が済んだアプリを自動で Notary に提出す
フックスクリプトを`./scripts/after-sign-mac.js`に置きます フックスクリプトを`./scripts/after-sign-mac.js`に置
```js ```js
const path = require("path"); const path = require("path");
@ -73,7 +73,7 @@ exports.default = async () => {
}; };
``` ```
`package.json``build``afterSign`を追加してコード署名が終わった後にスクリプトが実行されるようにします。 `package.json``build``afterSign`を追加してコード署名が終わった後にスクリプトが実行されるようにす
```json ```json
"build": { "build": {
@ -83,7 +83,7 @@ exports.default = async () => {
## Hardened Runtime and Entitlements ## Hardened Runtime and Entitlements
このままでは公証に失敗します。デフォルトで書き出されるバイナリでは、セキュリティの強化された[Hardened Runtime](https://developer.apple.com/documentation/security/hardened_runtime_entitlements)が有効になっていないためです。以下のようなエラーメッセージを貰います このままでは公証に失敗す。デフォルトで書き出されるバイナリでは、セキュリティの強化された[Hardened Runtime](https://developer.apple.com/documentation/security/hardened_runtime_entitlements)が有効になっていないためだ。以下のようなエラーメッセージが帰ってくる
```json ```json
{ {
@ -103,7 +103,7 @@ exports.default = async () => {
} }
``` ```
`package.json``build.mac.hardenedRuntime``true`にして Hardened Runtime を有効にします。 そこで、`package.json``build.mac.hardenedRuntime``true`にして Hardened Runtime を有効にす
```json ```json
"build": { "build": {
@ -113,7 +113,7 @@ exports.default = async () => {
} }
``` ```
Hardened Runtime 下では、必要に応じて Entitlement を指定しなくてはなりません。Electron の実行には`allow-unsigned-executable-memory`という Entitlement が必要なので、`entitlement.plist`ファイルを`build`フォルダに作成し、以下のような plist を記述します。 Hardened Runtime 下では、必要に応じて Entitlement を指定しなければならない。Electron の実行には`allow-unsigned-executable-memory` Entitlement が必要だ。そこで、`entitlement.plist`ファイルを`build`フォルダに作成し、以下のような plist を記述す
```xml ```xml
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
@ -126,7 +126,7 @@ Hardened Runtime 下では、必要に応じて Entitlement を指定しなく
</plist> </plist>
``` ```
`package.json``entitlements`及び`entitlementsInherit`に Entitlment が記述された plist のファイルパスを指定します。 `package.json``entitlements`及び`entitlementsInherit`に Entitlement が記述された plist のファイルパスを指定す
```json ```json
"build": { "build": {
@ -138,18 +138,18 @@ Hardened Runtime 下では、必要に応じて Entitlement を指定しなく
} }
``` ```
Hardened Runtime で Electron を実行することができるようになったので、Notary を通過できる状態になりました。 Hardened Runtime で Electron を実行することができるようになったので、Notary を通過できる状態になた。
実際に`electron-builder`を実行してすべてのプロセスが上手く動作することを確かめてください 実際に`electron-builder`を実行して、すべてのプロセスが滞りなく動作することを確かめよう
# Verify Notary Status # Verify Notary Status
ただしく公証を得られたかどうかは`altool`で調べることができます ただしく公証を得られたかどうかは`altool`で調べることができ
公証通過後に送られてくるメールに`Request Identifier`が記載されているのでメモします。 公証通過後に送られてくるメールに`Request Identifier`が記載されているのでメモす
``` ```
Dear Yasuaki, Dear uetchy,
Your Mac software has been notarized. You can now export this software and distribute it directly to users. Your Mac software has been notarized. You can now export this software and distribute it directly to users.
@ -161,13 +161,13 @@ Best Regards,
Apple Developer Relations Apple Developer Relations
``` ```
`xcrun altool --notarization-info`コマンドに UUID と Apple ID、パスワードを指定して公証ステータスを確認します。 `xcrun altool --notarization-info`コマンドに UUID と Apple ID、パスワードを指定して公証ステータスを確認す
``` ```
xcrun altool --notarization-info <UUID> -u $APPLE_ID -p $APPLE_PASSWORD xcrun altool --notarization-info <UUID> -u $APPLE_ID -p $APPLE_PASSWORD
``` ```
正しく公証が得られている場合は以下のようなメッセージが表示されます。おめでとうございます 正しく公証が得られている場合は以下のようなメッセージが表示される。おめでとう
``` ```
2019-06-05 13:51:18.236 altool[5944:261201] No errors getting notarization info. 2019-06-05 13:51:18.236 altool[5944:261201] No errors getting notarization info.

View File

@ -3,9 +3,9 @@ title: プログラムの速度改善が誤差かどうかを統計的に調べ
date: 2019-10-03 17:21:00 +09:00 date: 2019-10-03 17:21:00 +09:00
--- ---
**Welch の t 検定**を用いて 2 つのベンチマークの分布の平均が等しい(速度差は誤差の範疇)か、あるいは異なる(=有意な速度改善が成されている)かどうかを判定します **Welch の t 検定**を用いて 2 つのベンチマークの分布の平均が等しい(速度差は誤差の範疇)か、あるいは異なる(=有意な速度改善が成されている)かどうかを判定したい
ベンチマーク用の TypeScript プログラムを用意します ベンチマーク用に TypeScript プログラムを用意した
```ts a.ts ```ts a.ts
function a() { function a() {
@ -27,13 +27,13 @@ function b() {
b(); b();
``` ```
まず[hyperfine](https://github.com/sharkdp/hyperfine)で 2 つの プログラムのベンチマークを取り、`result.json`に保存します。 まず[hyperfine](https://github.com/sharkdp/hyperfine)で 2 つの プログラムのベンチマークを取り、`result.json`に保存す
```shell ```shell
hyperfine 'ts-node a.ts' 'ts-node b.ts' -r 50 --warmup 3 --export-json ab.json hyperfine 'ts-node a.ts' 'ts-node b.ts' -r 50 --warmup 3 --export-json ab.json
``` ```
`result.json`の中身は以下のようになります `result.json`の中身は以下のようにな
```json result.json ```json result.json
{ {
@ -78,9 +78,9 @@ hyperfine 'ts-node a.ts' 'ts-node b.ts' -r 50 --warmup 3 --export-json ab.json
} }
``` ```
> t 検定はサンプルが正規分布に従っているという仮定を置いているので、大数の法則から本当はもっと試行回数を増やした方が良いです > t 検定はサンプルが正規分布に従っているという仮定を置いているため、大数の法則から本当はもっと試行回数を増やした方が良い。
この`result.json``times`配列を受け取り、2 つの分布間に有意差があるかどうかを判定します。 この`result.json``times`配列を受け取り、2 つの分布間に有意差があるかどうかを判定す
```ts ```ts
import fs from "fs"; import fs from "fs";
@ -126,7 +126,7 @@ log(`p < 0.05 = ${p < 0.05}`);
log(p < 0.05 ? "Possibly some difference there" : "No difference"); log(p < 0.05 ? "Possibly some difference there" : "No difference");
``` ```
ここで`X_mu`は分布 X の平均、`X_sigma`は分布 X の不偏分散です ここで`X_mu`は分布 X の平均、`X_sigma`は分布 X の不偏分散
$$ $$
\begin{eqnarray} \begin{eqnarray}
@ -135,26 +135,26 @@ $$
\end{eqnarray} \end{eqnarray}
$$ $$
これを X と Y 両方に対して求めます。さらに以下のようにして t を求めます これを X と Y 両方に対して求めます。さらに以下のようにして t を求め
$$ $$
t = \frac{\mu_X - \mu_Y}{\sqrt{\frac{\sigma_X}{n_X} + \frac{\sigma_Y}{n_Y}}} t = \frac{\mu_X - \mu_Y}{\sqrt{\frac{\sigma_X}{n_X} + \frac{\sigma_Y}{n_Y}}}
$$ $$
t 分布の累積密度関数 (Cumlative Distribution Function; CDF) を定義します。面倒すぎたので[jstat](https://github.com/jstat/jstat)の`studentt.cdf`を使ってます。コードを見ると、分子の積分は[シンプソンの公式](https://ja.wikipedia.org/wiki/シンプソンの公式)を使って近似していました。 t 分布の累積密度関数 (Cumlative Distribution Function; CDF) を定義す。面倒すぎたので[jstat](https://github.com/jstat/jstat)の`studentt.cdf`を使っ。コードを見ると、分子の積分は[シンプソンの公式](https://ja.wikipedia.org/wiki/シンプソンの公式)を使って近似していた。
$$ $$
\text{CDF} =\frac{\int_0^{\frac{v}{t^2+v}}\frac{r^{\frac{v}{2}-1}}{\sqrt{1-r}}dr{}}{\text{exp}(\ln(\Gamma(\frac{v}{2}))+\ln(\Gamma(0.5))+\ln(\Gamma(\frac{v}{2}+0.5)))} \text{CDF} =\frac{\int_0^{\frac{v}{t^2+v}}\frac{r^{\frac{v}{2}-1}}{\sqrt{1-r}}dr{}}{\text{exp}(\ln(\Gamma(\frac{v}{2}))+\ln(\Gamma(0.5))+\ln(\Gamma(\frac{v}{2}+0.5)))}
$$ $$
CDF を用いて p 値を求めます。両側検定をするので 2 を掛けます。t 分布の自由度 (degree of freedom; df) は$n-1$なので、両分布の自由度を$n_X+n_Y-2$で与えます。本当は CDF を用いて p 値を求める。両側検定をするので 2 を掛ける。t 分布の自由度 (degree of freedom; df) は$n-1$なので、両分布の自由度を$n_X+n_Y-2$で与え。本当は
$$ $$
\text{df} = \frac{(\sigma_X + \sigma_Y)^2}{ \text{df} = \frac{(\sigma_X + \sigma_Y)^2}{
\frac{\sigma_X^2}{n_X - 1} + \frac{\sigma_Y^2}{n_Y - 1}} \frac{\sigma_X^2}{n_X - 1} + \frac{\sigma_Y^2}{n_Y - 1}}
$$ $$
で求める必要がありますが、さぼって近似しました。 で求める必要があるが、さぼって近似した。
$$ $$
p = \text{CDF}(-|t|, n_X+n_Y-2) \times2 p = \text{CDF}(-|t|, n_X+n_Y-2) \times2
@ -162,7 +162,7 @@ $$
## 結果 ## 結果
異なる実行時間を示すプログラム`a`,`b`を比較すると、2 つの分布の平均が異なることが示唆されました。 異なる実行時間を示すプログラム`a`,`b`を比較すると、2 つの分布の平均が異なることが示唆された。
``` ```
❯ ts-node test.ts ab.json ❯ ts-node test.ts ab.json
@ -180,7 +180,7 @@ p < 0.05 = true
Possibly some difference there Possibly some difference there
``` ```
p 値が 0.05 未満となり、帰無仮説「2つの分布は等しい」が棄却されたので「2つの分布は等しくない」ことがわかりました。同じプログラム同士でベンチマークを取るとどうなるでしょうか。 p 値が 0.05 未満となり、帰無仮説「2つの分布は等しい」が棄却されたので「2つの分布は等しくない」ことがわかった。では、同じプログラム同士でベンチマークを取るとどうなるか?
``` ```
❯ ts-node test.ts aa.json ❯ ts-node test.ts aa.json
@ -198,9 +198,9 @@ p < 0.05 = false
No difference No difference
``` ```
p 値が 0.05 未満ではないので、帰無仮説は棄却されず、つまり「2つの分布は等しい」ことがわかりました。 p 値が 0.05 未満ではないため、帰無仮説は棄却されず、つまり「2つの分布は等しい」ことがわかった。
ウェルチの t 検定はスチューデントの t 検定と違って等分散性(2つの分布の分散が等しいこと)を仮定しないので、とても取り扱いやすい検定です。もちろん等分散性のある分布でも使用できるので、基本的にはウェルチの方法を使う方針で良さそうです ウェルチの t 検定はスチューデントの t 検定と違って等分散性(2つの分布の分散が等しいこと)を仮定しないため、とても取り扱いやすい検定だ。もちろん等分散性のある分布でも使用できるので、基本的にはウェルチの方法を使う方針で良さそう
## 参考文献 ## 参考文献

View File

@ -3,45 +3,55 @@ title: Distill Thumbnail from .afphoto and .afdesign
date: 2021-02-14T13:30:00 date: 2021-02-14T13:30:00
--- ---
Nextcloud does not have support for generating thumbnails from Affinity Photo and Affinity Design. Fine, I'll do it myself. [Nextcloud](https://en.wikipedia.org/wiki/Nextcloud) does not support generating thumbnails from [Affinity Photo](https://en.wikipedia.org/wiki/Affinity_Photo) and [Affinity Designer](https://en.wikipedia.org/wiki/Affinity_Designer). Fine, I'll do it myself!
# Digging Binary # Digging Binary
Glancing at `.afphoto` and `.afdesign` in Finder, I noticed that it has a QuickLook support and an ability to show the thumbnail image. So these files should have thumbnail image somewhere inside its binary. Glancing at `.afphoto` and `.afdesign` in Finder, I noticed that it has a QuickLook support and an ability to show the thumbnail image. Meaning there's a chance that these files contain **pre-generated thumbnail images** somewhere inside its binaries, meaning I don't have to reverse-engineer their format from ground up.
I wrote a piece of Node.js script to seek for [PNG signature](https://www.w3.org/TR/PNG/) inside a binary and save it as an image file. To verify this, I wrote a piece of Node.js script to seek for [PNG blob](https://www.w3.org/TR/PNG/) inside an .afphoto/.afdesign file and save it as a normal PNG file.
```js afthumb.js In the [11.2.1 General](https://www.w3.org/TR/PNG/#11Chunks) of the PNG spec, they stated a valid PNG image should begin with a PNG signature and end with an `IEND` chunk.
> A valid PNG datastream shall begin with a PNG signature, immediately followed by an `IHDR` chunk, then one or more `IDAT` chunks, and shall end with an `IEND` chunk. Only one `IHDR` chunk and one `IEND` chunk are allowed in a PNG datastream.
Conveniently, it is also guaranteed that there should be **only one IEND chunk** in a PNG file, so greedy search would just work.
```js gen_thumbnail.js
const fs = require("fs"); const fs = require("fs");
// png spec: https://www.w3.org/TR/PNG/ // png spec: https://www.w3.org/TR/PNG/
const PNG_SIG = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]); const PNG_SIG = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
const IEND_SIG = Buffer.from([73, 69, 78, 68]); const IEND_SIG = Buffer.from([73, 69, 78, 68]);
function extractThumbnail(buf) { function extractPngBlob(buf) {
const start = buf.indexOf(PNG_SIG); const start = buf.indexOf(PNG_SIG);
const end = buf.indexOf(IEND_SIG, start) + IEND_SIG.length * 2; // IEND + CRC const end = buf.indexOf(IEND_SIG, start) + IEND_SIG.length * 2; // IEND + CRC
return buf.subarray(start, end); return buf.subarray(start, end);
} }
function generateThumbnail(input, output) { function extractThumbnail(input, output) {
const buf = fs.readFileSync(input); const buf = fs.readFileSync(input);
const thumbBuf = extractThumbnail(buf); const pngBlob = extractPngBlob(buf);
fs.writeFileSync(output, thumbBuf); fs.writeFileSync(output, pngBlob);
} }
generateThumbnail(process.argv[2], process.argv[3] || "output.png"); extractThumbnail(process.argv[2], process.argv[3] || "output.png");
``` ```
That's right. This script just scrapes a binary file and distill a portion of which starts with `PNG` signature and ends with `IEND`. That's right. This script just do `indexOf` on a `Buffer` and distill a portion of which starts with `PNG` signature and ends with `IEND` (+ CRC checksum).
# CRC (Cyclic Redundancy Code)
You may have wondered about `IEND_SIG.length * 2` part. It was to include [32-bit CRC](https://en.wikipedia.org/wiki/Cyclic_redundancy_check#CRC-32_algorithm) (Cyclic Redundancy Code) for `IEND` to the resulting blob.
Here, the byte-length of `IEND` chunk and its `CRC` checksum are coincidentally the same (4 bytes), so I just went with that code.
Now I can generate a thumbnail image from arbitrary `.afphoto` and `.afdesign` file. Let's move on delving into Nextcloud source code. Now I can generate a thumbnail image from arbitrary `.afphoto` and `.afdesign` file. Let's move on delving into Nextcloud source code.
# Tweaking Nextcloud # Tweaking Nextcloud
I have a bit of experience in tweaking Nextcloud source code before, where I implemented thumbnail generator for PDFs, so it should be easier this time, hopefully. At this point, all I have to do is to rewrite the above code in PHP and make them to behave as a Nextcloud Preview Provider.
Long story short, I got Nextcloud generates thumbnail images for Affinity files by implementing `ProviderV2` class.
```php lib/private/Preview/Affinity.php ```php lib/private/Preview/Affinity.php
<?php <?php
@ -79,6 +89,8 @@ class Affinity extends ProviderV2 {
} }
``` ```
Also make sure my component to be auto-loaded on startup.
```patch lib/private/PreviewManager.php ```patch lib/private/PreviewManager.php
@@ -363,6 +365,8 @@ @@ -363,6 +365,8 @@
$this->registerCoreProvider(Preview\Krita::class, '/application\/x-krita/'); $this->registerCoreProvider(Preview\Krita::class, '/application\/x-krita/');
@ -114,7 +126,13 @@ class Affinity extends ProviderV2 {
![](afphoto.png) ![](afphoto.png)
Easy-peasy! Voilà! Now I can see beautiful thumbnails for my drawings in Nextcloud web interface.
This is exactly why I love FOSS. It allows me to materialize **any niche things** I want in the FOSS without bothering its developers. This fact not only gives me confidence that I can control the functionality of the software, but it also makes me have more trust in the developers for giving me such freedom to make changes to their software.
# Finalized Solution
Enough talking, I've pushed my Nextcloud Docker setup with the above patches included on [GitHub](https://github.com/uetchy/docker-nextcloud). You can see the actual patch [here](https://github.com/uetchy/docker-nextcloud/blob/master/patches/lib.patch). Note that it also contains the patches for PDF thumbnail generator described below, and this particular patch _may_ pose security implications because of the usage of Ghostscript against PDF.
# Bonus: PDF thumbnail generator # Bonus: PDF thumbnail generator

File diff suppressed because it is too large Load Diff

View File

@ -44,11 +44,11 @@ OAuth 2.0 において、`access_token`をリソースサーバーに渡す手
2. Form Encoded Parameters (SHOULD NOT) 2. Form Encoded Parameters (SHOULD NOT)
3. URI Query Parameters (SHOULD NOT) 3. URI Query Parameters (SHOULD NOT)
## [OICD](https://openid.net/specs/openid-connect-core-1_0.html) — OpenID Connect Core 1.0 ## [OIDC](https://openid.net/specs/openid-connect-core-1_0.html) — OpenID Connect Core 1.0
2014 年 11 月 2014 年 11 月
OAuth 2.0 の上にいくつか仕様を足したサブセット。 OAuth 2.0 の上にいくつか仕様を足したサブセットで、OAuth (Authorization)に Authentication の機能を付与した画期的なプロトコル
## [RFC7515](https://tools.ietf.org/html/rfc7515) — JSON Web Signature (JWS) ## [RFC7515](https://tools.ietf.org/html/rfc7515) — JSON Web Signature (JWS)

View File

@ -8,26 +8,39 @@ date: 2021-02-13T00:00:00
# 用途 # 用途
- 各種セルフホスト (Docker) - 各種セルフホスト (Docker)
- Docker Swarm / K8s のマスター - Docker Swarm クラスターのマスターノード
- 計算実験 - 計算実験
- VS Code Remote SSH のホストマシン - VS Code Remote SSH のホストマシン
- VPN 他
# スペック # スペック
重いタスクを並列してやらせたいので最優先は CPU とメモリ。メモリは[DDR4-3200 32GBx2](https://shop.tsukumo.co.jp/goods/4582353591719/) を、CPU は昨今のライブラリのマルチコア対応を勘案して [Ryzen 9 3950X](https://www.amd.com/en/products/cpu/amd-ryzen-9-3950x) を選んだ。CPU クーラーは静音性を考えて Noctua の [NH-D15 Black](https://noctua.at/en/nh-d15) 。 重いタスクを並列してやらせたいので最優先は CPU とメモリ。メモリは[DDR4-3200 32GBx2](https://shop.tsukumo.co.jp/goods/4582353591719/) を、CPU は昨今のライブラリのマルチコア対応を勘案して [Ryzen 9 3950X](https://www.amd.com/en/products/cpu/amd-ryzen-9-3950x) を選んだ。CPU クーラーは静音性を考えて Noctua の [NH-D15 Black](https://noctua.at/en/nh-d15) 。
> 結果から言うとメモリは 64GB では足りなかった。巨大な Pandas データフレームを並列処理したり、DeepSpeed でモデルの重みをオフロードするたびに OOM が発動してしまう。最終的に 128GB まで増やす羽目になった。
> 追記: メモリ異常を起因とするシステム誤動作により、`/sbin` 以下がゼロ上書きされカーネルが起動しなくなる災害が起きた。後日 ECC 付きのメモリに交換してからは、現在に至るまでメモリ関連の異常は発生していない。常時稼働するサーバーには最初から ECC メモリを選ぼう。 > 追記: メモリ異常を起因とするシステム誤動作により、`/sbin` 以下がゼロ上書きされカーネルが起動しなくなる災害が起きた。後日 ECC 付きのメモリに交換してからは、現在に至るまでメモリ関連の異常は発生していない。常時稼働するサーバーには最初から ECC メモリを選ぼう。
> 追記: 結局 128GB でも OOM になる場面が出てきたが、もうこれ以上増設できない。最初から DIMM を 8 枚挿せるマザーボードを選ぶべきだった。 > 追記 2: 結果から言うとメモリは 64GB では足りなかった。巨大な Pandas データフレームを弄ったり、10 億レコード以上ある MongoDB を走査したりするたびに OOM が発動してしまう。最終的に 128GB まで増やす羽目になった。
GPU は古いサーバーに突っ込んでいた NVIDIA GeForce GTX TITAN X (Maxwell)を流用した。グラフィックメモリが 12GB ちょっとしかないが、最大ワークロード時でも 5GB は残るので今のところ十分。 > 追記 3: 結局 128GB でも OOM になる場面が出てきたが、スロットが埋まっていてもうこれ以上増設できないし、できたとしても Ryzen シリーズが 128GB までしかサポートしてないのでどちらにしろ詰みである。
>
> これから機械学習/OLAP サーバーを構築しようと考えている読者は、最初から DIMM スロットが豊富な Dual-socket (CPU が 2 つ挿せる) マザーボードと、サーバー向け CPU (EPYC または Xeon)の組み合わせを検討すべきだ。サーバー向け CPU に関しては、EOL を迎えてデータセンターから放出された 5 年ほど前のモデルが eBay で安く手に入るはず。
> 結果から言うと GPT-J や Megatron-LM を始めとした億パラメータ級のモデルを学習・推論させるには、DeepSpeed の助けがあったとしても最低 16GB の VRAM が必要だった。 > 追記 4: eBay で良いパーツを探すコツ
>
> 1. 発送時期が異様に長くない (所有しているものを出品している)
> 2. シリアル番号が写っている現物の写真がある (偽物や Engineering Sample の可能性が低い)
> 3. 通電に加えて正常な動作確認を行っている (疑問点があれば出品者に質問を送ってしっかり言質をとっておくこと)
記憶装置は WD HDD 3TB 2 台と Samsung 970 EVO Plus 500GB M.2 PCIe、そして古いサーバーから引っこ抜いた Samsung 870 EVO Plus 500GB SSD 。NVMe メモリは OS 用、SSD/HDD はデータとバックアップ用にする。 GPU は古いサーバーに突っ込んでいた NVIDIA GeForce GTX TITAN X (Maxwell)を流用した。VRAM が 12GB ちょっとしかないが、最大ワークロード時でも 5GB は残るので今のところ十分。
> 追記: 結果から言うと GPT-J や Megatron-LM を始めとした億パラメータ級のモデルを学習・推論させるには、DeepSpeed の助けがあったとしても最低 16GB の VRAM が必要だった。他の例を挙げると、Stable Diffusion の Fine-tuning には最低 30GB 前後の VRAM が必要になるし、OpenAI Whisper の large モデルを動かす際にも 13GB は見ておく必要がある。
>
> 今から GPU を買うなら、2022 年 10 月現在中古市場で 10 万前後で推移している RTX 3090 (24GB)を 2 枚買う戦略が筋が良いだろう。お金持ちなら A100 を買えば良い。
> 追記 2: RTX 3090 を安く仕入れることができたが、サイズが大きすぎて Meshify 2 ケースの HDD ベイに干渉してしまった。いくつか HDD を移動させることで上手く挿入できたが、かわりに 3 つ分のベイが使用できなくなった。
>
> これからケースを買おうとしている読者は、最初から ATX ケースを通り越して Meshify 2 XL など、E-ATX/EE-ATX 対応ケースを選ぶことをおすすめする。どちらにせよそのようなケースでないと上記の Dual-socket マザーボードは挿せないし、十分な冷却環境を確保できない。
記憶装置は WD HDD 3TB 2 台と Samsung 970 EVO Plus 500GB M.2 PCIe、そして古いサーバーから引っこ抜いた Samsung 870 EVO Plus 500GB SSD 。NVMe メモリは OS とキャッシュ用、SSD/HDD はデータ用にする。
マザーボードは、X570 と比較して実装されているコンデンサーやパーツがサーバー向きだと感じた[ASRock B550 Taichi](https://www.asrock.com/mb/AMD/B550%20Taichi/) にした。 マザーボードは、X570 と比較して実装されているコンデンサーやパーツがサーバー向きだと感じた[ASRock B550 Taichi](https://www.asrock.com/mb/AMD/B550%20Taichi/) にした。
@ -43,6 +56,7 @@ Arch Linux のセットアップは[個別に記事](https://uechi.io/blog/insta
# パーツ選定時のポイント # パーツ選定時のポイント
- [Disk Prices](https://diskprices.com/?locale=us) でディスクの値段チェック
- [WikiChip](https://en.wikichip.org/wiki/WikiChip)で CPU のモデルやスペックを調査する - [WikiChip](https://en.wikichip.org/wiki/WikiChip)で CPU のモデルやスペックを調査する
- [PCPartPicker](https://jp.pcpartpicker.com/)でパーツのコスト計算をする - [PCPartPicker](https://jp.pcpartpicker.com/)でパーツのコスト計算をする
- [Bottleneck Calculator](https://pc-builds.com/calculator/)で CPU と GPU の組み合わせを選び、そのうちどちらが性能のボトルネックになるか調べる - [Bottleneck Calculator](https://pc-builds.com/calculator/)で CPU と GPU の組み合わせを選び、そのうちどちらが性能のボトルネックになるか調べる
@ -60,7 +74,7 @@ Arch Linux のセットアップは[個別に記事](https://uechi.io/blog/insta
- 少なくとも 1 年間はすべての箱・書類を取っておく(特にメモリは箱自体が保証書代わりになっている場合がある) - 少なくとも 1 年間はすべての箱・書類を取っておく(特にメモリは箱自体が保証書代わりになっている場合がある)
- 筐体は無視してまずマザボ、CPU、クーラー、(オンボードグラフィックが無い CPU なら)グラボ、そして電源を繋いで通電・動作テストをする - 筐体は無視してまずマザボ、CPU、クーラー、(オンボードグラフィックが無い CPU なら)グラボ、そして電源を繋いで通電・動作テストをする
- [MemTest86](https://www.memtest86.com/)でメモリの動作テストを最後までやる(エラーが出たら交換依頼) - [MemTest86](https://www.memtest86.com/)でメモリのテストを最後までやる(エラーが出たら交換依頼)
- USB ブートで OS の起動確認 - USB ブートで OS の起動確認
- Ethernet が死んでいる場合は USB-Ethernet アダプターでまずネットを確保する - Ethernet が死んでいる場合は USB-Ethernet アダプターでまずネットを確保する
- ほとんどの場合 Linux カーネルのバージョンを上げると(デバイスドライバーも新しくなり)直る - ほとんどの場合 Linux カーネルのバージョンを上げると(デバイスドライバーも新しくなり)直る
@ -69,4 +83,4 @@ Arch Linux のセットアップは[個別に記事](https://uechi.io/blog/insta
- 駄目ならマザボまたはアダプターメーカーからアップデートを探す - 駄目ならマザボまたはアダプターメーカーからアップデートを探す
- 安い筐体のネジは柔いことがあるため、強く押し込みながら少しずつ回す - 安い筐体のネジは柔いことがあるため、強く押し込みながら少しずつ回す
- 山が潰れてきたらゴムシートを挟む - 山が潰れてきたらゴムシートを挟む
- すべて動いたら、[Linux Hardware Database に Probe を送信](https://linux-hardware.org/index.php?view=howto)して貢献 - すべて動いたら、[Linux Hardware Database に Probe を送信](https://linux-hardware.org/index.php?view=howto)して貢献する

View File

@ -12,7 +12,7 @@ date: 2021-02-14T00:00:00
1. 全員の出費を算出(払い過ぎは正、払わなさすぎは負の数) 1. 全員の出費を算出(払い過ぎは正、払わなさすぎは負の数)
2. 降順でソート(出費過多が先頭) 2. 降順でソート(出費過多が先頭)
3. リストの最後(最大債務者, 出費=L)がリストの最初(最大債権者, F)に $\min(F, |L|)$ を支払ってバランスを再計算 3. リストの最後(最大債務者, 出費=L)がリストの最初(最大債権者, F)に $\min(F, |L|)$ を支払ってバランス(負債)を再計算
4. 全員のバランスが 0 になるまで 2-3 を繰り返す 4. 全員のバランスが 0 になるまで 2-3 を繰り返す
# 実験 # 実験
@ -145,4 +145,8 @@ B virtually paid ¥81 in total
C virtually paid ¥76 in total C virtually paid ¥76 in total
``` ```
プログラムに落とし込むことができたら、あとはスプレッドシートのマクロにするなり自由だ。面倒なことは全部コンピューターにやらせよう! 旅行中、A と B は 1 回、C は 3 回支払いを建て替えた。そのうち 3 回は普通の割り勘だが、他 2 回はそれぞれ「C が A と B の分を建て替えた」「C が A の分を建て替えた(=C が A に金を貸した)」である。
このようなケースで一件ずつナイーブに精算しようとすると、合計 12 回のお金のやり取りが発生することになる。しかし負債を同額の債権で打ち消す操作を繰り返して最適化した結果、たった 2 回お金のやり取りをするだけで全員分の精算を完了できることがわかった。
プログラムに落とし込むことができたら、あとはスプレッドシートのマクロにするなりスマホのアプリにするなり自由だ。面倒なことは全部コンピューターにやらせよう!

View File

@ -5,60 +5,33 @@ date: 2022-05-20T00:00:00
[Mozc](https://github.com/google/mozc) is an open-source counterpart of Google Japanese Input, a Japanese input method developed by Google. [Mozc](https://github.com/google/mozc) is an open-source counterpart of Google Japanese Input, a Japanese input method developed by Google.
## Setup build environment ## Build environment
``` ```
$ sw_vers $ sw_vers
ProductName: macOS ProductName: macOS
ProductVersion: 12.2.1 ProductVersion: 12.6.1
BuildVersion: 21D62 BuildVersion: 21G217
$ xcodebuild -version $ xcodebuild -version
Xcode 13.3 Xcode 14.1
Build version 13E113 Build version 14B47b
```
```bash
# Install dependencies
brew install python3 ninja qt@5
# Clone the repository
git clone https://github.com/google/mozc -b master --single-branch --recursive
``` ```
## Build mozc ## Build mozc
```bash ```bash
# Move to the source directory # Install dependencies
brew install qt@5 bazel packages
# Clone the repository
git clone https://github.com/google/mozc -b master --single-branch --recursive
# Build
cd mozc/src cd mozc/src
MOZC_QT_PATH=/usr/local/opt/qt@5 ANDROID_NDK_HOME= bazel build package --config macos -c opt
# Expose necessary variable
MAC_SDK=$(xcodebuild -showsdks 2>/dev/null | grep '\tmacOS' | awk '{print $2}')
MAC_DEPLOYMENT_TARGET=$(sw_vers -productVersion | sed -E 's/\.[^.]+$//')
export GYP_DEFINES="mac_sdk=${MAC_SDK} mac_deployment_target=${MAC_DEPLOYMENT_TARGET}"
# Apply hotfix to third party libs
cd third_party
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH="$PATH:$PWD/depot_tools"
python3 -m pip install six
cd gyp
git apply ../../gyp/gyp.patch
cd ../..
# Configure
python3 build_mozc.py gyp --qtdir=/usr/local/opt/qt@5
# Build main converter and GUI tools
python3 build_mozc.py build -c Release mac/mac.gyp:GoogleJapaneseInput gui/gui.gyp:config_dialog_main
# Install # Install
sudo cp -r out_mac/Release/Mozc.app /Library/Input\ Methods/ open bazel-bin/mac/Mozc.pkg
sudo cp mac/installer/LaunchAgents/org.mozc.inputmethod.Japanese.Converter.plist /Library/LaunchAgents
sudo cp mac/installer/LaunchAgents/org.mozc.inputmethod.Japanese.Renderer.plist /Library/LaunchAgents
# Clean up the tree
python3 build_mozc.py clean
reboot reboot
``` ```

View File

@ -1,5 +1,5 @@
--- ---
title: 日本のルート認証局を戴く中間認証局のACME対応状況 title: 国内のルート認証局とACME対応状況
date: 2022-03-04T15:00:00 date: 2022-03-04T15:00:00
--- ---
@ -7,7 +7,7 @@ date: 2022-03-04T15:00:00
## 概要 ## 概要
まず断っておきたいが、ルート認証局によって子孫 SSL 証明書の安全性に問題が生じたことは[WoSign の例](https://wiki.mozilla.org/CA/WoSign_Issues)を除いてほとんどない。わざわざ高額な手数料を支払うより、同じセキュリティ強度の証明書を無料で提供してくれる Let's Encrypt (ISRG)や ZeroSSL (Sectigo) をありがたく使わせていただく、そういう意識で問題ないのである。 まず断っておきたいが、ルート認証局のせいで子孫 SSL 証明書の運用に問題が生じたことは[WoSign](https://wiki.mozilla.org/CA/WoSign_Issues)や[TrustCor](https://www.techtarget.com/searchsecurity/news/252527174/TrustCor-under-fire-over-certificate-authority-concerns)(TrustCor は少し毛色が違うが)の例を除いてほとんどない。わざわざ高額な手数料を支払うより、同じセキュリティ強度の証明書を無料で提供してくれる Let's Encrypt (ISRG)や ZeroSSL (Sectigo) をありがたく使わせていただく、そういう意識で問題ないのである。
## 国内唯一のルート認証局は SECOM が所有 ## 国内唯一のルート認証局は SECOM が所有
@ -40,7 +40,7 @@ FujiSSL は独自の自動更新ツールを提供しているが、ホストに
- [ACME について | JPRS](https://jprs.jp/pubcert/about/ACME/) - [ACME について | JPRS](https://jprs.jp/pubcert/about/ACME/)
- [JPRS サーバー証明書発行サービス ACME 対応版ご利用条件 (PDF)](https://jprs.jp/pubcert/info/repository/acme-agreement.pdf) - [JPRS サーバー証明書発行サービス ACME 対応版ご利用条件 (PDF)](https://jprs.jp/pubcert/info/repository/acme-agreement.pdf)
[JPRS サーバー証明書認証局証明書ポリシー](https://jprs.jp/pubcert/info/repository/JPRS-CP.pdf)に目を通してどの認証方式に対応しているのか調べてみよう。 [JPRS サーバー証明書認証局証明書ポリシー](https://jprs.jp/pubcert/info/repository/JPRS-CP.pdf)に目を通してどの認証方式に対応しているのか確認しよう。
### 3.2.2.4.7 DNS Change ### 3.2.2.4.7 DNS Change
@ -70,7 +70,7 @@ DNS ゾーンに CAA レコードを置いて内容を`jprs.jp`にする必要
Go 製の ACME クライアント[lego](https://github.com/go-acme/lego)は DNS-01 認証に対応しているため、JPRS ACME 証明書の発行がスムーズにできる可能性がある。 Go 製の ACME クライアント[lego](https://github.com/go-acme/lego)は DNS-01 認証に対応しているため、JPRS ACME 証明書の発行がスムーズにできる可能性がある。
```bash ```bash コマンド例(執筆時点では動作しない)
CLOUDFLARE_DNS_API_TOKEN=<token> \ CLOUDFLARE_DNS_API_TOKEN=<token> \
lego \ lego \
--server 'https://acme.amecert.jprs.jp/DV/getDirectory' \ --server 'https://acme.amecert.jprs.jp/DV/getDirectory' \

View File

@ -5,9 +5,9 @@ permalink: "/email"
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<meta name="robots" content="noindex"> <meta name="robots" content="noindex" />
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta http-equiv='X-UA-Compatible' content='IE=edge'> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<body> <body>
<style> <style>
@ -16,6 +16,9 @@ permalink: "/email"
} }
</style> </style>
<h1>Email</h1> <h1>Email</h1>
<p>You can reach me at <a href="mailto:y@uechi.io"><code>y@uechi.io</code></a></p> <p>
You can reach me at
<a href="mailto:y@uechi.io"><code>y@uechi.io</code></a>
</p>
</body> </body>
</html> </html>

View File

@ -1,5 +1,5 @@
--- ---
title: about me title: README
--- ---
<style> <style>
@ -14,6 +14,7 @@ img {
- [Blog (Japanese and English)](https://uechi.io) - [Blog (Japanese and English)](https://uechi.io)
- [Technical Notes (English) @ dev.to](https://dev.to/uetchy) - [Technical Notes (English) @ dev.to](https://dev.to/uetchy)
- [Technical Notes (Japanese) @ Qiita](https://qiita.com/uetchy) - [Technical Notes (Japanese) @ Qiita](https://qiita.com/uetchy)
- [SIGVT Project](https://sigvt.org)
<!-- - [Design Portfolio @ Behance](https://www.behance.net/uechi) --> <!-- - [Design Portfolio @ Behance](https://www.behance.net/uechi) -->
## Contact ## Contact
@ -41,14 +42,14 @@ curl https://github.com/uetchy.keys | age -R - confidential.zip > confidential.z
```yaml ```yaml
- Interests: - Interests:
- Web, ML/NLP, UX, Coffee - Webdev, NLP, Reverse-engineering, Category theory, UI design, Coffee
- Have confidence: - Machine languages:
- (Java|Type)Script, React, UI design - TypeScript, Python, Rust, Go, Ruby, Swift
- Have some experience: - Human languages:
- Python, Rust, Go, Ruby, Swift, Docker Swarm
- Have no confidence: normal life stuff
- Languages:
- Japanese: native - Japanese: native
- English: TOEIC 985 - English: TOEIC 985
- Play tin whistle and violin for fun - Korean: r/w hangul
- Indonesian: baby
- Hobby:
- Play tin whistle and fiddle for fun
``` ```

View File

@ -1,52 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBFvmhvMBEADkBr92qQLufuLU4GF+DxnWXgd/JZh5H/Exve6WATynLIgBjK2b
tZHyqbe2uRP3p0O597xRRzUYfI+ZfZs2eohqnQAGtXsvHOWfxj91amZuhevNr1AA
Tm/hFFRmGnRUtEGSo+t+++a8tK70AZ1oXp5aNXshlzw/WNT0b+WAvwlPsQiAUFEr
B8EXKSMBQmItD/sH7qcbC1/41ScQ5q8X7h8JjtHmJicJhcAMqmNCEV/roRLxOMFw
tXXkVU14PZxu0lW2FQETO5d+79SFUa6XEE9Cb8IKjN+KtjQUKCLCn8HWIDimxzcU
Cj8djnn1/TyMJEkGvUUz3ztsoM91gKa5uDCkqNbJgtSQF4Xzl1xQaSleN8MHbaGs
UosPMJirAJBwqFkFyJI7uu2FiKTgFAdJY23Gx2UDUxFqXkeoGUYxKRuZHiXwLJH0
w10+HtbNNZbPZW488PQc5tAN+Msk5oIV+X4lHHxBhIb7ijZrm3+2d0VNyTga1mi7
rhsDUJ9oMeU12ZTnGsZHEjH9xb0xnIOzfyb0AnWMJkxB8YHT6jFORpx+D8aZRtkZ
ocBaHVkJXes1VkvDComumAUTF4QaQijzOq1NjIMH8lk0UOl10yIj/ROzwi+zJx5F
9avxMg/aecfXo/AlMRUnnK4sI9yCo4h9U4vif//iyONb9XnLUXQjMyBD8QARAQAB
tBpZYXN1YWtpIFVlY2hpIDx5QHVlY2hpLmlvPokCVAQTAQgAPhYhBOC/Msrh+Rsx
TVAl/XKjsw/NCqgQBQJb5obzAhsDBQkHhh+ABQsJCAcCBhUKCQgLAgQWAgMBAh4B
AheAAAoJEHKjsw/NCqgQsooP/0vX0bk94HIllNAJeOimFoVxWV2h3nGjuvMTTXpJ
rDNC+N/DuNMwtsEz6Y/5ABbFzCVlaG39qADdED3Ph2AuvEXBVzKQo8hDfIjwhC7+
2csSu4plS3IHxLIiRM86unLXPouNbroS4/x/cEe0oX98gFhEVFPsWQgU9k3TCkWa
M2t+Mg6xi/62vUFP9jYKYGQ9070j2Pa62V4IrX8t4+gBAVwcsbfOxes07SwOMjPU
H1C30l26Nmze8ITyENPHRu19NLrzdOR6DLEyKRz+wln8dcHnA7HWOr+26U3627lF
oEHBdYcsBIieQ1/UN90HjfYDekTu2K20doXDlgUrqGxkA9lBaTMzwOoXewGGxrTu
Z/I13qtza5BZ71LNOiNx96cZJrgh8iNhWAXtSswTHLuEOd/S0c9TL/k/s+y1vBo4
C4K+kupiRY80E/G3Zfug59TZ8QYCaFjcezVLRlAD63A4HDsRsug8nGjzAAA61+t8
d+ijOrMAbU8DNKIjMLoZ52rxzP2HknpwU17R17fJ9UMoAFL+ZlBrX2rzUvqCAICi
wPl25wSEInr/AnNkwGzAFaUtae7EtL9F7cD0159Zgd5R5lWP6xXNWOjByndoYr+A
cDfsD3Yjkwv1Gi9rXkvDgRFIyOfk0wf7cLH4GtluW6sytVdGPe84DlKyqDQgWhcs
BCJRuQINBFvmhvMBEACpO4WHWGqjhGbOTE/lIKwOgC3v8nkSXEqINYdy1JgSSkLs
/bVI3u37qiPobTuPdlWZBIP3ci/9B1b8vfox7Ex4Qqg/nUKS6E1MfWR3PYMdoJbb
wwAkEPH6xwPwU8kRShcOESpVU6dHSi5PYSEPOMp4QYOXphvZn/08JaJ5SQgqIAOm
fDg/xgAKwlCAWvnTgwfJSv2qFolTMYx05QQdLTATXKptkI0aNrbBQAtaVwLl6yXu
rnrjzkDCzLC5Yr1V7Gp146mTfY+1eK5Chao50mzPzURTZpBtQq24DC+n5U2CKQcf
yUeU63OZov4fmIxZKVPPE/Lxogwc5BPIL3HzKlrKVEu4U4GwhIxJln9YSTFySTuo
RNhkeB9jdeNCh7/5BbgWjP8KJaAkx6n4JVsXwxmZLsT/9xsVOj7bIYi/ysocb0dJ
JcAcZUh9YeR7fPu8TfacYcUfAu/poNyBB/FDlNjhQxhgS/P+ssA1NHL4vb4B/Yfe
BOeVIeeMolaOqTRSasD/xu0Huxk+5Ewp0yWENwGKRfwr4BWmFseVn4ziPmVxMxqC
92/IgGVseav5RkB7JA7VWr/oAx6zG+Vgl2iuH6iTaHLbRbAnsalLz39lPHySknn9
Vmm/O4AeOqsgiWYcG9u3UC7MzjQMZ/QRvZ47UpywgzOGCdYmH09j58zBAXOblQAR
AQABiQI8BBgBCAAmFiEE4L8yyuH5GzFNUCX9cqOzD80KqBAFAlvmhvMCGwwFCQeG
H4AACgkQcqOzD80KqBA0ghAAxUvHqP7G3oLed+3O0OdIZZHdEfFAwaWdym1MvAql
A2Iq6KE7S/ldgtXwcyJZc6i7IZrz64jjDdPJHWvugFBsy1z7pOeNJavgEd/bU/Bu
+4dwa2rw0ZBq3iy7VJSMlClfgLDxQmUxYvmidoTYpjERRnmX63trXtap2CeIP0ex
YWchQsw4WJGS1kWV6N7ybio4X52ieHM5TZ2EYloOkIFtcHJ5IRhZabU9Hk58FZPU
s1drCznIiJnElqXBz5jh7356xAJbM4tlIndcQW6Vszar+ojot4XX+9vbE9OK1+7T
fStwei/rMvM8f1HbuYeRKVyA2kKC/FKDkRBwLz4a0wjF++7Z8MvzqoJSdzlYM9Ad
DxxuadzUBf3TdSKnnuajOgWHqoE0Da3Hpb4Cc4fV8KdFfWjwjrZdIJcMgphTpxtF
W6uWQGntZvvYlA1NV31AMTmWTDhGImAuJ9GvxQtmvOzqqQ1AMox2ZUkQnK8p0Yxm
KPW0VKWOo19aHBZo2nxc+rKzJl9A8YPtgDeaOBX1PHLveZedTHmcQaYh6Jb1ud31
IrTl36iHcdoI5drtbxb645Ba5aW/BhDdimcybl6q2o8SB2IQl57kYq/RwhuoztYu
WQSKu5R9PlgDZrfsOmmXrW2yOpwSpY6CLgem51TFvWcT4ik8pT8agE6OJT+JL3QI
FKI=
=o3B6
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -53,7 +53,7 @@
/> />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://unpkg.com/highlight.js@9.18.1/styles/night-owl.css" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/tokyo-night-dark.min.css"
/> />
<%- css('css/index') %> <%- css('css/index') %>

View File

@ -4,15 +4,18 @@
/></a> /></a>
<nav> <nav>
<ul class="menu"> <ul class="menu">
<li class="menu__item">
<a href="/me">Me</a>
</li>
<li class="menu__item"> <li class="menu__item">
<a href="https://github.com/<%- config.github.username %>">GitHub</a> <a href="https://github.com/<%- config.github.username %>">GitHub</a>
</li> </li>
<li class="menu__item"> <li class="menu__item">
<a href="https://twitter.com/<%- config.twitter.username %>">Twitter</a> <a href="/me">Readme</a>
</li> </li>
<!-- <li class="menu__item">
<a href="https://sigvt.org">SIGVT</a>
</li> -->
<!-- <li class="menu__item">
<a href="https://twitter.com/<%- config.twitter.username %>">Twitter</a>
</li> -->
<li class="menu__item"> <li class="menu__item">
<a href="/wallpaper">Wallpaper</a> <a href="/wallpaper">Wallpaper</a>
</li> </li>

View File

@ -1,4 +1,4 @@
<section> <section class="article-list">
<% page.posts.each(function (post) { %> <% page.posts.each(function (post) { %>
<article class="article-list__item"> <article class="article-list__item">
<h2 class="article-list__item__title"> <h2 class="article-list__item__title">

View File

@ -1,27 +1,31 @@
<section> <section>
<article class="article"> <article class="article">
<h1 class="article__title"><%- page.title %></h1>
<hgroup class="article__metadata"> <hgroup class="article__metadata">
<% if (page.date) { %> <% if (page.date) { %>
<h3 class="article__pubdate"> <div class="article__pubdate">
<time pubdate><%- date(page.date, "YYYY / <b>MM</b>") %></time> <time pubdate><%- date(page.date, "<b>YYYY</b> / MM") %></time>
</h3> </div>
<% } %> <% } %>
<h2 class="article__title"><%- page.title %></h2> <div class="article__updated">
written by <b>uetchy</b>
</div>
<!-- <% if (page.updated) { %>
LAST UPDATE: <time pubdate><%- date(page.updated, "<b>YYYY</b> / MM") %></time>
</div>
<% } %> -->
</hgroup> </hgroup>
<div class="article__content"><%- page.content %></div> <div class="article__content">
<!-- <%- toc(page.content, {list_number: false}) %> -->
<%- page.content %>
</div>
<!-- Social buttons --> <!-- Social buttons -->
<script
defer
src="https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.8"
id="facebook-jssdk"
></script>
<script <script
defer defer
src="https://platform.twitter.com/widgets.js" src="https://platform.twitter.com/widgets.js"
id="twitter-wjs" id="twitter-wjs"
></script> ></script>
<div id="fb-root"></div>
<div class="article__social"> <div class="article__social">
<a <a
href="https://twitter.com/share" href="https://twitter.com/share"
@ -29,14 +33,6 @@
data-size="large" data-size="large"
>Tweet</a >Tweet</a
> >
<div
class="fb-like"
data-layout="button"
data-action="like"
data-size="large"
data-show-faces="false"
data-share="true"
></div>
</div> </div>
</article> </article>
</section> </section>

View File

@ -1,69 +1,136 @@
.article, .article {
.article-list__item { font-feature-settings: "kern";
margin-bottom: 60px;
text-rendering: optimizeLegibility;
font-feature-settings: "kern";
}
.article__title {
// margin: 0.2em 0 1.2em;
font-family: "Montserrat", "Noto Sans JP", sans-serif;
font-size: 3.5rem;
line-height: 1.2em;
text-align: center;
text-rendering: geometricprecision;
@media screen and (max-width: $break-small) {
font-size: 2.8rem;
}
}
.article__metadata {
display: flex;
justify-content: center;
margin: 1.5em 0 1em;
color: var(--tone);
font-size: 0.8rem;
font-weight: 400;
.article__pubdate,
.article__updated {
b {
font-weight: 700;
}
}
.article__pubdate {
border: 1px solid var(--tone);
border-radius: 20px;
padding: 0.5em 1.5em;
}
.article__updated {
margin-left: 1em;
padding: 0.5em 0;
}
}
.article__content {
margin: 5em 0 0;
font-size: 1.1rem;
@media screen and (max-width: $break-small) {
margin: 3em 0 0;
}
p {
line-height: 1.6em;
margin: 1.25em 0;
}
h1, h1,
h2, h2,
h3, h3,
h4, h4 {
h5 { text-rendering: geometricprecision;
font-feature-settings: "kern", "palt"; font-feature-settings: "kern", "palt";
} }
h1 {
margin: 2em 0 0;
font-size: 2.5rem;
font-family: "Lora", serif;
@media screen and (max-width: $break-small) {
margin: 1.5em 0 0.7em;
font-size: 2.4rem;
text-align: center;
}
} }
.article { h2 {
margin-bottom: 60px; margin: 2em 0 0;
font-size: 1.8rem;
font-weight: bold;
@media screen and (max-width: $break-small) {
margin: 1.5em 0 0;
font-size: 1.8rem;
}
} }
.article-list__item { h3 {
margin: 0 0 60px; margin: 2em 0 0;
font-size: 1.7rem;
font-weight: normal;
@media screen and (max-width: $break-small) {
margin: 2em 0 0;
font-size: 1.5rem;
}
}
h4 {
margin: 35px 0 0;
font-size: 1.2rem;
font-weight: bold;
@media screen and (max-width: $break-small) {
margin: 1em;
}
}
ul {
padding-left: 20px;
}
li {
line-height: 1.6em;
}
a {
color: var(--link-text);
}
img { img {
max-width: 100%; max-width: 100%;
} height: auto;
} }
.article-list__item__title { blockquote {
margin: 0 0 2px; border-left: 5px solid var(--accent);
font-size: 40px; padding-left: 20px;
} margin: 0;
.article-list__item__pubdate {
text-transform: uppercase;
}
.article-list__item__excerpt {
margin-top: 5px;
font-size: 20px;
color: var(--tone);
line-height: 1.6em;
word-break: break-all;
}
a.article-list__item__button {
border: 1px solid var(--tone);
border-radius: 3px;
color: var(--tone);
font-family: "Open Sans", sans-serif;
font-size: 14px;
display: inline-block;
margin: 10px 0;
padding: 10px 17px;
text-transform: uppercase;
&:hover {
background-color: var(--tone);
color: var(--background);
}
@media screen and (max-width: $break-small) {
display: block;
text-align: center;
font-size: 17px;
padding: 15px;
&:hover {
background-color: var(--background);
color: var(--tone);
}
} }
} }
@ -78,136 +145,98 @@ a.article-list__item__button {
margin-right: 4px; margin-right: 4px;
} }
.article__metadata { .article-list {
margin: 40px 0 40px; text-rendering: optimizeLegibility;
font-feature-settings: "kern";
@media screen and (max-width: $break-small) {
margin: 25px 0 25px;
text-align: left;
}
} }
.article__title { .article-list__item {
font-size: 4rem; margin: 0 0 4em;
letter-spacing: -0.2px;
// line-height: 1em;
@media screen and (max-width: $break-small) {
font-size: 40px;
text-align: left;
}
}
.article__pubdate {
color: var(--tone);
font-size: 18px;
font-weight: 300;
margin-bottom: 10px;
border: 1px solid var(--tone);
display: inline-block;
padding: 5px 20px;
b {
font-weight: 700;
}
@media screen and (max-width: $break-small) {
margin-bottom: 15px;
font-size: 10pt;
}
}
.article__content {
p {
font-size: 20px;
font-weight: normal;
line-height: 1.5em;
margin: 25px 0;
@media screen and (max-width: $break-small) {
font-size: 20px;
}
}
ul {
padding-left: 20px;
}
li {
font-size: 20px;
line-height: 1.6em;
}
a {
color: mediumslateblue;
}
h1 {
margin: 70px 0 0px;
font-size: 2.8em;
@media screen and (max-width: $break-small) {
margin: 30px 0 15px;
font-size: 1.7em;
}
}
h2 {
margin: 35px 0 15px;
font-weight: bold;
font-size: 2em;
@media screen and (max-width: $break-small) {
margin: 20px 0 15px;
font-weight: bold;
font-size: 1.5em;
}
}
h3 {
margin: 25px 0 15px;
font-weight: bold;
font-size: 1.3em;
@media screen and (max-width: $break-small) {
margin: 15px 0 15px;
font-weight: bold;
font-size: 1.4em;
}
}
h4 {
margin: 25px 0 15px;
font-weight: bold;
@media screen and (max-width: $break-small) {
margin: 15px 0 15px;
font-weight: bold;
}
}
img { img {
max-width: 100%; max-width: 100%;
height: auto;
} }
blockquote { .article-list__item__title {
border-left: 5px solid var(--accent); margin: 0 0 2px;
padding-left: 20px; font-size: 2.5rem;
font-family: "Montserrat", "Noto Sans JP", sans-serif;
text-rendering: geometricprecision;
font-feature-settings: "kern", "palt";
@media screen and (max-width: $break-small) {
font-size: 2rem;
}
}
.article-list__item__pubdate {
text-transform: uppercase;
}
.article-list__item__excerpt {
margin: 0.8em 0 0.3em;
color: var(--tone);
font-size: 1.1rem;
line-height: 1.6em;
word-break: break-word;
}
a.article-list__item__button {
display: inline-block;
margin: 10px 0;
padding: 0.8em 1.5em;
color: var(--tone);
font-size: 14px;
text-transform: uppercase;
border: 1px solid var(--tone);
border-radius: 3px;
&:hover {
background-color: var(--tone);
color: var(--background);
}
@media screen and (max-width: $break-small) {
display: block;
padding: 15px;
text-align: center;
&:hover {
background-color: var(--background);
color: var(--tone);
}
}
}
}
// Highlight.js
.hljs {
border-radius: 6px;
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
font-size: 0.8rem;
background: #0c031c !important;
padding: 12px 18px !important;
line-height: 1.6em !important;
margin: 0; margin: 0;
@media screen and (max-width: $break-small) {
font-size: 0.7rem;
}
}
code {
padding: 3px 10px;
background: var(--highlight);
font-size: 0.8em;
border-radius: 3px;
} }
pre .caption { pre .caption {
padding: 10px 0; padding: 10px 0;
font-family: monospace;
font-size: 0.8rem; font-size: 0.8rem;
font-style: italic;
opacity: 0.7; opacity: 0.7;
span { span {
white-space: break-spaces; white-space: break-spaces;
} }
} }
}
// Pay // Pay
#pay { #pay {

View File

@ -1,4 +1,4 @@
@import url("https://fonts.googleapis.com/css?family=PT+Sans:400,700"); @import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@700&family=Noto+Sans+JP:wght@700&family=Lora&display=swap");
$break-small: 500px; $break-small: 500px;
$break-large: 840px; $break-large: 840px;
@ -10,16 +10,18 @@ $break-large: 840px;
--highlight: #f6f6f6; --highlight: #f6f6f6;
--tone: #989898; --tone: #989898;
--dim: rgb(203, 203, 203); --dim: rgb(203, 203, 203);
--link-text: #4f33e8;
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
:root { :root {
--background: #261e3a; --background: #231a37;
--text: #e2dfea; --text: #d9d5e1;
--accent: #7033e8; --accent: #7033e8;
--highlight: #140d25; --highlight: #140d25;
--tone: #989898; --tone: #989898;
--dim: rgb(90, 83, 101); --dim: rgb(90, 83, 101);
--link-text: #af93ff;
} }
} }
@ -28,14 +30,17 @@ body {
box-sizing: border-box; box-sizing: border-box;
} }
html {
font-size: 100%;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
-webkit-font-smoothing: antialiased;
}
body { body {
width: 900px; width: 900px;
margin: 0 auto; margin: 0 auto;
padding: 0 20px; padding: 0 20px;
font-family: "PT Sans", "Hiragino Sans", "Hiragino Mincho ProN", sans-serif;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
font-feature-settings: "kern";
background: var(--background); background: var(--background);
color: var(--text); color: var(--text);
@ -45,28 +50,10 @@ body {
} }
} }
// Highlight.js a {
.hljs { word-break: break-word;
border-radius: 6px;
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
font-size: 14px;
background: #0e0127 !important;
padding: 12px 18px !important;
line-height: 1.6em !important;
margin: 0;
@media screen and (max-width: $break-small) {
font-size: 0.8em;
}
}
code {
padding: 0 12px;
}
p code {
padding: 3px 10px;
background: var(--highlight);
border-radius: 3px;
font-size: 16px;
} }
a:hover, a:hover,
a:active, a:active,
a:link, a:link,
@ -74,6 +61,7 @@ a:visited {
color: var(--text); color: var(--text);
text-decoration: none; text-decoration: none;
} }
h1, h1,
h2, h2,
h3, h3,
@ -83,6 +71,7 @@ p {
padding: 0; padding: 0;
line-height: 1.333em; line-height: 1.333em;
} }
hr { hr {
display: block; display: block;
width: 100%; width: 100%;
@ -92,19 +81,18 @@ hr {
margin: 40px 0; margin: 40px 0;
} }
// Header
header.header { header.header {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
margin-top: 60px; margin: 70px 0 70px;
margin-bottom: 80px;
flex-direction: row; flex-direction: row;
justify-content: flex-start; justify-content: center;
align-items: center; align-items: center;
@media screen and (max-width: $break-small) { @media screen and (max-width: $break-small) {
margin-top: 30px; margin-top: 30px;
margin-bottom: 60px; margin-bottom: 60px;
// justify-content: center;
} }
.logo { .logo {
@ -124,18 +112,18 @@ header.header {
text-transform: lowercase; text-transform: lowercase;
font-weight: bold; font-weight: bold;
border-left: 1px solid var(--tone); border-left: 1px solid var(--tone);
// font-family: Rockwell;
padding: 0; padding: 0;
margin: 0 0 0 30px; margin: 0 0 0 30px;
padding: 0 0 0 30px; padding: 0 0 0 30px;
.menu__item { .menu__item {
margin: 5px 0; margin: 2px 0;
} }
} }
} }
// Pagination
.page-nav { .page-nav {
display: flex; display: flex;
justify-content: center; justify-content: center;

3185
yarn.lock

File diff suppressed because it is too large Load Diff