Compare commits

..

No commits in common. "master" and "gh-actions" have entirely different histories.

70 changed files with 1185 additions and 13890 deletions

View File

@ -1,24 +0,0 @@
kind: pipeline
type: docker
name: default
steps:
- name: Build and push
image: plugins/docker
settings:
repo: u8.pub/uetchy/uechi.io
tags: latest
registry: u8.pub
username:
from_secret: docker_username
password:
from_secret: docker_password
- name: Trigger Watchtower Update
image: alpine/curl
commands:
- |
curl -s -H "Authorization: Bearer $WATCHTOWER_TOKEN" https://wt.uechi.io/v1/update
environment:
WATCHTOWER_TOKEN:
from_secret: watchtower_token

View File

@ -0,0 +1,19 @@
---
label: Blog post
hide_body: false
fields:
- type: text
name: title
label: title
config:
required: false
- type: datetime
name: date
label: date
default: now
config:
required: true
pages:
- _posts/2019-10-25-bose-noise-cancelling-headphones-700レビュー.md
- _posts/pixiv-spring-boot-camp-2020.md
- _posts/静寂を得る方法.md

28
.forestry/settings.yml Normal file
View File

@ -0,0 +1,28 @@
---
new_page_extension: md
auto_deploy: false
admin_path: ""
webhook_url:
sections:
- type: directory
path: source/_posts
label: Posts
create: documents
match: "**/*"
- type: directory
path: source/_pages
label: Pages
create: documents
match: "**/*"
upload_dir: source/uploads
public_path: "/uploads"
front_matter_path: ""
use_front_matter_path: false
file_template: ":filename:"
build:
preview_output_directory: public
install_dependencies_command: npm i
preview_docker_image: forestryio/ruby:2.6
mount_path: "/srv"
working_dir: "/srv"
instant_preview_command: yarn server

17
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,17 @@
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: monthly
time: "20:00"
timezone: Asia/Tokyo
open-pull-requests-limit: 10
ignore:
- dependency-name: textlint
versions:
- 11.7.7
- 11.8.1
- dependency-name: textlint-rule-no-dropping-the-ra
versions:
- 2.0.0

45
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,45 @@
# https://hexo.io/docs/github-pages.html
# https://github.com/docker/build-push-action/blob/master/docs/advanced/cache.md#github-cache
name: ci
on:
push:
branches:
- master
jobs:
buildAndPush:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
# - name: Set up QEMU
# uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: ghcr.io/uetchy/uechi.io:latest
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
- name: Trigger Watchtower Update
run: |
curl -s -H "Authorization: Bearer ${{ secrets.WATCHTOWER_TOKEN }}" https://watchtower.uechi.dev/v1/update

20
.gitignore vendored
View File

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

79
.vscode/settings.json vendored
View File

@ -1,79 +0,0 @@
{
"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

@ -1,19 +1,17 @@
FROM node:16 as build FROM node:15 as build
# https://github.com/jgm/pandoc/releases # https://github.com/jgm/pandoc/releases
RUN curl -LO https://github.com/jgm/pandoc/releases/download/2.14.0.1/pandoc-2.14.0.1-1-amd64.deb RUN curl -LO https://github.com/jgm/pandoc/releases/download/2.14.0.1/pandoc-2.14.0.1-1-amd64.deb
RUN dpkg -i pandoc-2.14.0.1-1-amd64.deb RUN dpkg -i pandoc-2.14.0.1-1-amd64.deb
WORKDIR /app WORKDIR /app
COPY package.json /app/
RUN yarn install
COPY plugins plugins COPY themes /app/themes
COPY package.json package-lock.json ./ COPY source /app/source
RUN npm ci COPY _config.yml /app/
RUN yarn build
COPY themes themes
COPY source source
COPY _config.yml ./
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) 2013-2022 Yasuaki Uechi (https://uechi.io) Copyright (c) 2021 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,8 @@
deploy: build
docker rm -f uechiio uechiio-cron
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
deploy: build
docker-compose -f docker-compose.production.yml up -d

View File

@ -1,16 +1,17 @@
# uechi.io # uechi.io
[![Build Status](https://build.u8.pub/api/badges/uetchy/uechi.io/status.svg)](https://build.u8.pub/uetchy/uechi.io) [![Actions Status: pages](https://github.com/uetchy/uechi.io/workflows/Pages/badge.svg)](https://github.com/uetchy/uechi.io/actions?query=pages)
## Dev ## Build
```bash ```
npm start n 15
yarn build
``` ```
## Publish ## Publish
```bash ```
git commit -m "New article" git commit -m "New article"
git push git push
``` ```

View File

@ -5,7 +5,7 @@
# Site # Site
title: uechi.io title: uechi.io
subtitle: "" subtitle: ""
description: "Random posts from uetchy" description: "Random posts from U"
keywords: keywords:
author: Yasuaki Uechi author: Yasuaki Uechi
language: en language: en
@ -28,9 +28,6 @@ node_sass:
precision: 5 precision: 5
sourceComments: false sourceComments: false
sass:
outputStyle: expanded
# URL # URL
## If your site is put in a subdirectory, set url as 'http://example.com/child' and root as '/child/' ## If your site is put in a subdirectory, set url as 'http://example.com/child' and root as '/child/'
url: https://uechi.io url: https://uechi.io
@ -145,3 +142,4 @@ feed:
atom: atom:
enable: true enable: true
output: "feed.xml" output: "feed.xml"

View File

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

View File

@ -2,9 +2,7 @@ version: "3.0"
services: services:
web: web:
image: u8.pub/uetchy/uechi.io image: ghcr.io/uetchy/uechi.io
build: . build: .
ports: ports:
- "8080:80" - "8080:80"
volumes:
- "./data:/var/www/html/_:ro"

View File

@ -17,44 +17,11 @@ http {
keepalive_timeout 65; keepalive_timeout 65;
server { server {
server_name uechi.io;
listen 80; listen 80;
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;
} }
@ -67,7 +34,7 @@ http {
location / { location / {
index index.html; index index.html;
try_files $uri $uri.html $uri/index.html @fallback; try_files $uri $uri.html $uri/index.html =404;
} }
location = / { location = / {
@ -75,16 +42,5 @@ http {
rewrite / /TERMINAL last; rewrite / /TERMINAL last;
} }
} }
location @fallback {
root /var/www/html/_;
try_files $uri $uri.html $uri/index.html =404;
}
}
server {
listen 80;
server_name www.uechi.io;
return 301 $scheme://uechi.io$request_uri;
} }
} }

10491
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,34 +5,38 @@
"build": "hexo generate", "build": "hexo generate",
"clean": "hexo clean", "clean": "hexo clean",
"deploy": "hexo deploy", "deploy": "hexo deploy",
"start": "npm run clean && hexo server --debug", "start": "yarn clean && hexo server --debug",
"test": "lint-staged" "test": "lint-staged"
}, },
"dependencies": { "dependencies": {
"hexo": "^6.3.0", "hexo": "^6.0.0",
"hexo-excerpt": "^1.3.0", "hexo-excerpt": "^1.2.1",
"hexo-feed": "^1.1.1", "hexo-feed": "^1.1.0",
"hexo-filter-mathjax": "^0.9.0", "hexo-filter-mathjax": "^0.8.0",
"hexo-generator-archive": "^2.0.0", "hexo-generator-archive": "^1.0.0",
"hexo-generator-category": "^2.0.0", "hexo-generator-category": "^1.0.0",
"hexo-generator-index": "^3.0.0", "hexo-generator-index": "^2.0.0",
"hexo-generator-tag": "^2.0.0", "hexo-generator-tag": "^1.0.0",
"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.0",
"hexo-renderer-sass": "^0.4.0",
"hexo-renderer-stylus": "^2.0.0",
"hexo-server": "^3.0.0", "hexo-server": "^3.0.0",
"hexo-simple-toc": "file:plugins/hexo-simple-toc", "hexo-theme-landscape": "^0.0.3"
"js-yaml": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {
"textlint": "^12.2.4", "lint-staged": "^10.5.4",
"textlint": "^11.9.0",
"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": "^6.0.1"
},
"lint-staged": {
"*.md": "textlint"
}, },
"hexo": { "hexo": {
"version": "6.3.0" "version": "5.4.0"
}, },
"private": true "private": true
} }

View File

@ -1,11 +0,0 @@
#!/bin/sh
echo "Updating 280blocker filter..."
ROOT_DIR="/var/www/html/_"
FILTER_PATH="$ROOT_DIR/280blocker.txt"
DOMAIN_PATH="$ROOT_DIR/280blocker_domain.txt"
DATE=$(date +"%Y%m")
curl -sL "https://280blocker.net/files/280blocker_adblock_${DATE}.txt" -o "$FILTER_PATH"
curl -sL "https://280blocker.net/files/280blocker_domain_${DATE}.txt" -o "$DOMAIN_PATH"

View File

@ -1,144 +0,0 @@
# 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

@ -1,21 +0,0 @@
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

@ -1,3 +0,0 @@
# 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

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

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +0,0 @@
{
"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

@ -1,48 +0,0 @@
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,46 +4,54 @@ 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-nlp](https://github.com/uetchy/homebrew-nlp) を tap する。 デフォルトの Homebrew リポジトリに Julius は含まれていないので
、[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**と **am-gmm.jconf** のパスを調べて `julius` に渡すことで音声認識が出来るようになる。 後は、上記の `brew --prefix` コマンドでディクテーションキット内の **main.jconf**
**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**を **am-dnn.jconf** に変更するだけだ。 Julius をより精密な DNN モードで起動したい場合は以下のように、**am-gmm.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
``` ```
@ -51,9 +59,9 @@ julius \
ディクテーションキットに関するドキュメントは下記のコマンドから参照可能だ。 ディクテーションキットに関するドキュメントは下記のコマンドから参照可能だ。
```bash ```bash
open `brew --prefix julius-dictation-kit`/share/doc $ open `brew --prefix julius-dictation-kit`/share/doc
``` ```
### 実行中の様子 ### 実行中の様子
![](/uploads/install-julius-with-homebrew.png) ![install-julius-with-homebrew](/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,12 +83,13 @@ 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)に、ストックした投稿を検索するコマンドを追加した。
![](/uploads/alfred-qiita-workflow.png) ![s1.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"
--- ---
![](/uploads/brew-cask-downloader.png) ![image](/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-asset
### シェルスクリプト ### シェルスクリプト
```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,8 +29,9 @@ gem search $1 $2 --source https://rails-assets.org | grep "^rails-assets-"
もっと簡単に、シェル関数を定義することも出来る。 もっと簡単に、シェル関数を定義することも出来る。
```bash ~/.zshrc ```bash:~/.zshrc rails-assets(){ gem search $1 $2 --source
rails-assets(){ https://rails-assets.org | grep "^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"
--- ---
![](/uploads/alfred-qiita-workflow.png) ![Cover](/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,8 +50,7 @@ gulp.task("styles", function () {
続けて SASS を書こう。 続けて SASS を書こう。
```scss ```scss
@import normalize.sass; @import normalize.sass @import styles/font body font-family: $ff-gothic;
@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

@ -2,30 +2,30 @@
title: アップルパイ title: アップルパイ
date: 2017-04-23T05:48:00.000+00:00 date: 2017-04-23T05:48:00.000+00:00
categories: 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 回目から好みで変化させること
- 焼きあがったらただちにパイ皿を取り除くこと。冷めてからではより困難になる * 焼きあがったらただちにパイ皿を取り除くこと。冷めてからではより困難になる
# 手順 # 手順
1. **富士りんご(直径 8cm)**3 個の皮を剥いて 2-3 ㎠ に切って鍋に入れる 1. **富士りんご(直径 8cm)**3 個の皮を剥いて 2-3 ㎠ に切って鍋に入れる
2. **砂糖**60g・**レモン汁**大さじ 2 を鍋に入れて、汁気が無くなるまで中火で 10-15 分煮る 2. **砂糖**60g・**レモン汁**大さじ2 を鍋に入れて、汁気が無くなるまで中火で 10-15 分煮る
3. 火を止めて、**切れてるバター**2 個 (= 20g)・**シナモン**を好きなだけ混ぜる 3. 火を止めて、**切れてるバター**2 個 (= 20g)・**シナモン**を好きなだけ混ぜる
4. **冷凍パイシート**を冷蔵庫に移動し 30 分おく 4. **冷凍パイシート**を冷蔵庫に移動し 30 分おく
5. 18cm パイ皿 (パイシートに合う皿であれば何でも良い) にシートを敷き、よく密着させる 5. 18cm パイ皿 (パイシートに合う皿であれば何でも良い) にシートを敷き、よく密着させる
6. 鍋の中身の熱が扱える程度に取れたらパイ皿に流し込んで広げる 6. 鍋の中身の熱が扱える程度に取れたらパイ皿に流し込んで広げる
7. 残りのパイシートをカットして格子状にのせる 7. 残りのパイシートをカットして格子状にのせる
8. **卵黄**に**水・塩**を少し混ぜ卵液を作り、シートに塗る(塗るほど焼けやすくなる) 8. **卵黄**に**水・塩**を少し混ぜ卵液を作り、シートに塗る(塗るほど焼けやすくなる)
9. 余りのシートをパイの縁にのせて卵液を薄く塗る 9. 余りのシートをパイの縁にのせて卵液を薄く塗る
10. 200℃ のオーブンで 40 分焼く(15 分で 180℃ に落とす; でないと表面だけ焼けて中は生焼けになる) 10. 200℃ のオーブンで 40 分焼く(15 分で 180℃ に落とす; でないと表面だけ焼けて中は生焼けになる)

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,45 +4,40 @@ 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 種類がある。Notes のようにノートを一箇所にまとめて管理するシングルトンタイプと、TextEdit のようにファイル毎にウィンドウが開くタイプだ。 ノートアプリには大きく分けて 2 種類があります。
この記事では、前者を 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>
サンフランシスコ発の多機能ノートアプリ。Web 版、iOS/Android 版と Mac 版が用意されており、Markdown ライクな記法で自由度の高いノートテイキングが出来る。起動に時間がかかるのがかなり痛い サンフランシスコの Notion Lab 社が開発する多機能ノートアプリです。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 タイプ
@ -50,4 +45,4 @@ iCloud を使って、macOS と iOS アプリの間でノートを同期する
<https://typora.io> <https://typora.io>
エディタとプレビューが一体化したタイプのエディタ。左右分割よりも WYSIWYG エディタの方が体験が良い エディタとプレビューが一体化したタイプのエディタです。左右分割よりも WYSIWYG エディタの方がわかりやすい派なので、これ一択です

View File

@ -11,15 +11,22 @@ 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 python brew install python3
``` ```
If you still need Python 2, run `brew install python@2`. If you still need Python 2, run `brew install python`.
## Install Jupyter Notebook ## Install Jupyter Notebook
``` ```
pip install jupyter pip3 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
``` ```
@ -27,12 +34,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`. 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.
If you want a virtual envs on your project, run: If you want a virtual envs on your project, run:
``` ```
python -m venv venv python3 -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,26 +2,28 @@
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/)の例では、アイコンの改善案を思いつき、[Pull-request](https://github.com/iMasanari/cmd-eikana/pull/5)を送ったところ、驚くほどすぐにマージしてくれた。 macOS のキーバインドを変更するアプリである[⌘ 英かな](https://ei-kana.appspot.com/)の例では、アイコンの Enhancement を思いつき、[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
![](/uploads/screencast.gif) ![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,9 +27,9 @@ npm install -g gh-compare
gh-compare facebook/react vuejs/vue riot/riot gh-compare facebook/react vuejs/vue riot/riot
``` ```
![](/uploads/1xfd1gcrfntpft5bbu5s.png.jpeg) ![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!
Warmly welcome to any comments/ideas to improve `gh-compare`! Warmly welcome to any comments/ideas to improve `gh-compare`!

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.
![](/uploads/screen-1.png.jpeg) ![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/nature-remo/nature-remo)を作ったので是非触ってみてほしい。ライブラリ経由で温度・湿度・明度のセンサー値を取得したり、指定したモードにエアコンを切り替えることができ [Nature Remo を NodeJS で操作するライブラリ](https://github.com/uetchy/nature-remo)を作ったので触ってみてください。ライブラリ経由で温度・湿度・明度のセンサー値を取得したり、指定したモードにエアコンを切り替えることができます
# 自動施錠・自動開錠 # 自動施錠・自動開錠
Qrio Lock をドアに取り付けることでオートロック・アンロックができるようになた。 Qrio Lock をドアに取り付けることでオートロック・アンロックができるようになりました。
エントランスのドアに関しては、インターホンに Switch Bot を貼り付けて Shortcuts で解錠できるようにしておき、それを iPhone の背面トリプルタップで呼び出せるよう設定することでキーレスエントリー化している。少し Hacky だが、動けばなんでも良い エントランスのドアに関しては、インターホンに Switch Bot を貼り付けて Shortcuts で解錠できるようにしておき、それを iPhone の背面トリプルタップで呼び出せるよう設定することでキーレスエントリー化しています
# ホームアシスタント # ホームアシスタント
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,22 +9,25 @@ 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
![](/uploads/fqea9nq2wv9in15lqlf3.png.jpeg) ![fqea9nq2wv9in15lqlf3.png.jpeg](/uploads/fqea9nq2wv9in15lqlf3.png.jpeg)
![](/uploads/43slt0h6dfhox1xwmuti.png.jpeg) ![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`.
@ -36,9 +39,9 @@ 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.
![](/uploads/gg2wil3exu9lyj7ppuoy.png) ![gg2wil3exu9lyj7ppuoy.png](/uploads/gg2wil3exu9lyj7ppuoy.png)
# Conclusion # Conclusion
The source code is available on [GitHub](https://github.com/uetchy/math-api). The source code is available on [GitHub](https://github.com/uetchy/math-api).
Give it a try and leave a comment/idea for a new feature. Give it a try and leave a comment/idea for a new feature.

View File

@ -2,22 +2,38 @@
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 Pro 15 インチ ## [MacBook 12"](http://www.apple.com/jp/shop/buy-mac/macbook/%E3%82%B4%E3%83%BC%E3%83%AB%E3%83%89-512gb)
Thunderbolt ディスプレイと Roost を合わせて使うと QoL が高まる スペックを犠牲にして持ち運びに極振りした超コンパクトな MacBook
## [WF-1000XM4](https://www.sony.jp/headphone/products/WF-1000XM4/) ## [EARIN M-2](https://earin.com)
EARIN M-2 と BOSE から移行した。良い意味で Sony らしからぬ UX の良さに驚く。 EARIN M-1 から買い替えた。
コンパクトさに極振りした完全無線イヤホン。万人受けしないプロダクトではあるが、その特性を理解して使えば手放せないギアになる。
[レビュー記事](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)
@ -31,36 +47,93 @@ EARIN M-2 と BOSE から移行した。良い意味で Sony らしからぬ UX
## [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 12.9 インチ](http://www.apple.com/jp/ipad-pro/) ## [iPad Pro 10.5 インチ](http://www.apple.com/jp/ipad-pro/)
Apple Pencil との組み合わせがとても良い。ノートを書いたり、絵を描くのに使っている。 [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)との組み合わせがとても良い。ノートを書いたり、絵を描くのに使っている。
スタンドは、Twelve South の[Compass 2](http://www.apple.com/jp/shop/product/HF022ZM/B/twelve-south-compass-2-stand-for-ipad)を使っている。折りたたむと Apple Pencil2 本分くらいに小さくなる。
# サブスクリプションサービス # サブスクリプションサービス
> Google Workspace、Dropbox Pro、iTunes Match は解約してセルフホストに移行した。 ## G Suite
## Apple One 月 540 円。
好きなドメインで Google サービスを利用出来るので使っている。Gmail にも y@uechi.io でログイン出来る。
今まで契約していた Apple Music と iCloud 50GB プラン(バックアップ用)を合わせた額とほとんど同じなので Apple One に切り替えた。 ## Apple Music
学割で月 480 円。普段の音楽ソースはこれに統一している。
## iTunes Match
CD からインポートした曲をクラウド同期するために有効化。
## iCloud Drive
写真やクラウド同期のために容量を購入した。
## Dropbox Pro
あらゆる作業データを保存しているため容量を増やした。
## Amazon Student
Prime の学割版。年間 1400 円。
## Sketch
コンピューター 1 台ごとに課金されるため非常に割高。やめたい。
## Adobe Creative Cloud
学割で月 3000 円。
## Apple Developer Program ## Apple Developer Program
税金。 税金。
## [Porkbun](https://porkbun.com/) ## MoneyForward
ドメインレジストラ。お名前.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,36 +2,35 @@
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 台までのマルチペアリング * デザイン
- 2 台までのマルチポイント * 8台までのマルチペアリング
- タッチコントロール * 2台までのマルチポイント
- 3 段階ノイズキャンセリングレベルコントロール * タッチコントロール
- 10 段階の内 3 つをあらかじめ選んでおき、ボタンを押してローテーションできる * 3段階ノイズキャンセリングレベルコントロール
- QC30 は 1 段階ずつしか変更出来ずボタンを連打させられる仕様だったので、大きな改善 * 10段階の内3つをあらかじめ選んでおき、ボタンを押してローテーションできる
- バッテリーの持ちの良さ * QC30は1段階ずつしか変更出来ずボタンを連打させられる仕様だったので、大きな改善
- 15 時間くらいは動く * バッテリーの持ちの良さ
- 有線対応 * 15時間くらいは動く
- 有線時も ANC が働く * 有線対応
- USB-C 充電対応 * 有線時もANCが働く
* USB-C充電対応
## Cons ## Cons
- マルチポイント時の混線ノイズ * マルチポイント時の混線ノイズ
- 音楽再生中にもう一方のデバイスで何か通知音が鳴るとストリームに対して「プツプツ」ノイズが入る * 音楽再生中にもう一方のデバイスで何か通知音が鳴るとストリームに対して「プツプツ」ノイズが入る
- システムサウンドが大きすぎる(変更不可) * システムサウンドが大きすぎる(変更不可)
- 公式英語フォーラムで多くのユーザーが苦情を書き込んでいるが、完全に無視されている * 消耗部品の多さ
- 消耗部品の多さ * ヒンジ部分はケースに仕舞う度に動かなさいといけないため消耗が心配
- ヒンジ部分はケースに仕舞う度に動かなさいといけないため消耗が心配 * 可動部が多いほど故障率は上がる
- 一般論として、可動部が多いほど故障率が上がる * 本体側での接続先選択が不可能
- 本体側での接続先選択が不可能 * QC30では出来ていた本体側のボタンで接続先を選択できる機能が無くなっていた
- QC30 では出来ていた本体側のボタンで接続先を選択できる機能が無くなっていた * ボタン配置のミス
- ボタン配置のミス * ボタンが手に触れやすい位置にあるため、ヘッドホンを外す度に間違って押してしまう
- ボタンが手に触れやすい位置にあるため、ヘッドホンを外す度に間違って押してしまう * ストリーム元とボタンの送信先が異なるバグ
- ストリーム元とボタンの送信先が異なるバグ * マルチポイント接続で一方のデバイスで音楽を流している際に、再生ボタンの信号が音楽を流していない方のデバイスに送信されてしまうバグがある
- マルチポイント接続で一方のデバイスで音楽を流している際に、再生ボタンの信号が音楽を流していない方のデバイスに送信されてしまうバグがある

View File

@ -9,12 +9,12 @@ That's why I created [namae](https://namae.dev).
# namae # namae
![](/uploads/np1a40lrch9m10b1s7nz.gif) ![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.
![](/uploads/pww3x6ycshadfiiotep9.png) ![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.
![](/uploads/aas52pwbrueyzrulfiae.png) ![aas52pwbrueyzrulfiae.png](/uploads/aas52pwbrueyzrulfiae.png)
![](/uploads/j6jv0rq4gin28hks1ika.png) ![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.
@ -56,4 +56,4 @@ namae is completely open-sourced and the entire source code is available at [Git
namae saves your time searching for a universally available name around a set of hosting providers and package registries. namae saves your time searching for a universally available name around a set of hosting providers and package registries.
Go to [namae.dev](https://namae.dev/) and grab a report for the availability of your future product name. If you have any suggestion, poke me on Twitter ([@uechz](https://twitter.com/uechz)). Go to [namae.dev](https://namae.dev/) and grab a report for the availability of your future product name. If you have any suggestion, poke me on Twitter ([@uechz](https://twitter.com/uechz)).

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`に Entitlement が記述された plist のファイルパスを指定す `package.json``entitlements`及び`entitlementsInherit`に Entitlment が記述された 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 uetchy, Dear Yasuaki,
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,55 +3,45 @@ title: Distill Thumbnail from .afphoto and .afdesign
date: 2021-02-14T13:30:00 date: 2021-02-14T13:30:00
--- ---
[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! Nextcloud does not have support for generating thumbnails from Affinity Photo and Affinity Design. 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. 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. 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.
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. 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.
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. ```js afthumb.js
> 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 extractPngBlob(buf) { function extractThumbnail(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 extractThumbnail(input, output) { function generateThumbnail(input, output) {
const buf = fs.readFileSync(input); const buf = fs.readFileSync(input);
const pngBlob = extractPngBlob(buf); const thumbBuf = extractThumbnail(buf);
fs.writeFileSync(output, pngBlob); fs.writeFileSync(output, thumbBuf);
} }
extractThumbnail(process.argv[2], process.argv[3] || "output.png"); generateThumbnail(process.argv[2], process.argv[3] || "output.png");
``` ```
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). That's right. This script just scrapes a binary file and distill a portion of which starts with `PNG` signature and ends with `IEND`.
# 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
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. 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.
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
@ -89,8 +79,6 @@ 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/');
@ -126,13 +114,7 @@ Also make sure my component to be auto-loaded on startup.
![](afphoto.png) ![](afphoto.png)
Voilà! Now I can see beautiful thumbnails for my drawings in Nextcloud web interface. Easy-peasy!
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)
## [OIDC](https://openid.net/specs/openid-connect-core-1_0.html) — OpenID Connect Core 1.0 ## [OICD](https://openid.net/specs/openid-connect-core-1_0.html) — OpenID Connect Core 1.0
2014 年 11 月 2014 年 11 月
OAuth 2.0 の上にいくつか仕様を足したサブセットで、OAuth (Authorization)に Authentication の機能を付与した画期的なプロトコル OAuth 2.0 の上にいくつか仕様を足したサブセット。
## [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,39 +8,24 @@ date: 2021-02-13T00:00:00
# 用途 # 用途
- 各種セルフホスト (Docker) - 各種セルフホスト (Docker)
- Docker Swarm クラスターのマスターノード - Docker Swarm / K8s のマスター
- 計算実験 - 計算実験
- 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 メモリを選ぼう。
> 追記 2: 結果から言うとメモリは 64GB では足りなかった。巨大な Pandas データフレームを弄ったり、10 億レコード以上ある MongoDB を走査したりするたびに OOM が発動してしまう。最終的に 128GB まで増やす羽目になった GPU は古いサーバーに突っ込んでいた NVIDIA GeForce GTX TITAN X (Maxwell)を流用した。グラフィックメモリが 12GB ちょっとしかないが、最大ワークロード時でも 5GB は残るので今のところ十分
> 追記 3: 結局 128GB でも OOM になる場面が出てきたが、スロットが埋まっていてもうこれ以上増設できないし、できたとしても Ryzen シリーズが 128GB までしかサポートしてないのでどちらにしろ詰みである。 > 結果から言うと GPT-J や Megatron-LM を始めとした億パラメータ級のモデルを学習・推論させるには、DeepSpeed の助けがあったとしても最低 16GB の VRAM が必要だった。
>
> これから機械学習/OLAP サーバーを構築しようと考えている読者は、最初から DIMM スロットが豊富な Dual-socket (CPU が 2 つ挿せる) マザーボードと、サーバー向け CPU (EPYC または Xeon)の組み合わせを検討すべきだ。サーバー向け CPU に関しては、EOL を迎えてデータセンターから放出された 5 年ほど前のモデルが eBay で安く手に入るはず。
> 追記 4: eBay で良いパーツを探すコツ 記憶装置は WD HDD 3TB 2 台と Samsung 970 EVO Plus 500GB M.2 PCIe、そして古いサーバーから引っこ抜いた Samsung 870 EVO Plus 500GB SSD 。NVMe メモリは OS 用、SSD/HDD はデータとバックアップ用にする。
>
> 1. 発送時期が異様に長くない (所有しているものを出品している)
> 2. シリアル番号が写っている現物の写真がある (偽物や Engineering Sample の可能性が低い)
> 3. 通電に加えて正常な動作確認を行っている (疑問点があれば出品者に質問を送ってしっかり言質をとっておくこと)
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/) にした。
@ -56,7 +41,6 @@ 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 の組み合わせを選び、そのうちどちらが性能のボトルネックになるか調べる
@ -74,7 +58,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 カーネルのバージョンを上げると(デバイスドライバーも新しくなり)直る
@ -83,4 +67,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,8 +145,4 @@ 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

@ -1,37 +0,0 @@
---
title: Building mozc for macOS
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.
## Build environment
```
$ sw_vers
ProductName: macOS
ProductVersion: 12.6.1
BuildVersion: 21G217
$ xcodebuild -version
Xcode 14.1
Build version 14B47b
```
## Build mozc
```bash
# 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
MOZC_QT_PATH=/usr/local/opt/qt@5 ANDROID_NDK_HOME= bazel build package --config macos -c opt
# Install
open bazel-bin/mac/Mozc.pkg
reboot
```

View File

@ -1,97 +0,0 @@
---
title: 国内のルート認証局とACME対応状況
date: 2022-03-04T15:00:00
---
> 本記事と関係ないが在日ウクライナ大使館に寄付をした。なぜかというと、非常にお世話になっている[FSNotes](https://fsnot.es)の開発者が先月末から続いているウクライナ侵攻によって [OSS 活動を無期限停止せざるを得ない状況](https://twitter.com/FSNotesApp/status/1496865592242016259)に追い込まれており、少しでも支援をしたかったからだ。[在日ウクライナ大使館のサイト](https://japan.mfa.gov.ua/ja)にアクセスできない状態が続いているため、[公式ツイートから寄付先を参照](https://twitter.com/UKRinJPN/status/1497100158693416961)すると良い。
## 概要
まず断っておきたいが、ルート認証局のせいで子孫 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 が所有
- Security Communication RootCA1 ([crt.sh](https://crt.sh/?caid=53))
- Security Communication RootCA2 ([crt.sh](https://crt.sh/?caid=1160))
## 個人が取得可能かつ自動更新に対応しているワイルドカード証明書の年間料金
金額は 2022 年 3 月現在。
- FujiSSL (SSLStore) 19,800 円
- FujiSSL 20,350 円
- JPRS (Gonbei Domain) 16,500 円
- JPRS (さくらの SSL) 18,150 円 クレカ不可(請求書払いのみ)
- JPRS (ラット) 15,000 円
- JPRS (JPDirect) 47,960 円
FujiSSL、JPRS のルート認証局はどちらも Security Communication RootCA2 だ。
FujiSSL は独自の自動更新ツールを提供しているが、ホストに PHP や Apache をセットアップしなければならず、HTTP サーバーを内蔵している lego や certbot と比べてやや煩雑な印象は拭えない。独自方式なので、当然 ACME 対応クライアントは使えない。
## ACME
[RFC 8555 - Automatic Certificate Management Environment (ACME)](https://tex2e.github.io/rfc-translater/html/rfc8555.html) は自動化されたドメイン認証 SSL 証明書発行手続きを標準化しようとする一連の努力の成果である。
## JPRS が ACME に対応
タイミングの良いことに、JPRS が 2022/3/2 から ACME に対応した。
- [ACME について | JPRS](https://jprs.jp/pubcert/about/ACME/)
- [JPRS サーバー証明書発行サービス ACME 対応版ご利用条件 (PDF)](https://jprs.jp/pubcert/info/repository/acme-agreement.pdf)
[JPRS サーバー証明書認証局証明書ポリシー](https://jprs.jp/pubcert/info/repository/JPRS-CP.pdf)に目を通してどの認証方式に対応しているのか確認しよう。
### 3.2.2.4.7 DNS Change
DNS ゾーンに`_acme-challenge` TXT レコードを置いてドメインの所有権を確認する方式。一番簡単で制約が少ない。
### 3.2.2.4.18 Agreed-Upon Change to Website v2
HTTP/HTTPS サーバーを立ち上げて`.well-known/pki-validation`以下に置いたチャレンジトークンを PKI 側が確認する方式。しかし、
> 2021 年 11 月 18 日以降に発行する証明書について、先頭ラベルが"\*"(ワイルドカード)の FQDN に対してこの方法を適用外とする。
ワイルドカード証明書の場合この方式が使えない。
### 3.2.2.4.19 Agreed-Upon Change to Website - ACME
> 先頭ラベルが"\*"(ワイルドカード)の FQDN に対してこの方法を適用外とする
同上
### 4.2.4 CAA レコードの確認
> 本 CA は、RFC 6844 に従い、申請情報の審査時に CAA レコードを確認する。CAA レコードに記載する本 CA のドメインは「jprs.jp」とする。
DNS ゾーンに CAA レコードを置いて内容を`jprs.jp`にする必要がある。
## ACME クライアント
Go 製の ACME クライアント[lego](https://github.com/go-acme/lego)は DNS-01 認証に対応しているため、JPRS ACME 証明書の発行がスムーズにできる可能性がある。
```bash コマンド例(執筆時点では動作しない)
CLOUDFLARE_DNS_API_TOKEN=<token> \
lego \
--server 'https://acme.amecert.jprs.jp/DV/getDirectory' \
--eab --kid 'NUtfiBgcWr9oGCWmF8PQd2d499T7WrgqsnkxIOAPASE' --hmac 'Shn8-aYwhUw0esMLnqJL_o9Fg_BszfAgrRJjOtGQGGY' \
--accept-tos \
--path ./certs \
--dns cloudflare \
--email 'mail@example.jp' \
--domains '*.example.jp' \
run
```
[nginx-proxy/acme-companion](https://github.com/nginx-proxy/acme-companion/wiki)は、`ACME_CA_URI`環境変数を指定することで JPRS に対応できるが、HTTP-01 認証に依存しているため ワイルドカード証明書は発行できないだろう。[今後対応する可能性](https://github.com/nginx-proxy/acme-companion/issues/319)はある。
```bash
docker run -d \
--name your-proxied-app \
-e "VIRTUAL_HOST=subdomain.example.jp" \
-e "LETSENCRYPT_HOST=subdomain.example.jp" \
-e "ACME_CA_URI=https://acme.amecert.jprs.jp/DV/getDirectory" \
nginx
```
JPRS に問い合わせたところ、ACME の利用には JPRS と指定事業者両方の対応が必要になるそうだ。現在どの指定事業者も対応していないため、残念ながらもう少し待たなくてはならない。今後 ACME 経由で証明書の発行を試す機会があれば記事を更新する。

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,9 +16,6 @@ permalink: "/email"
} }
</style> </style>
<h1>Email</h1> <h1>Email</h1>
<p> <p>You can reach me at <a href="mailto:y@uechi.io"><code>y@uechi.io</code></a></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: README title: about me
--- ---
<style> <style>
@ -10,46 +10,27 @@ img {
# README # README
> I'm **uetchy**. I was born in Okinawa, Japan and have been living in Kanagawa.
# Contact
Reach me at `y@uechi.io`.
# Facts
- interests: webdev, nlp, ml, ux, coffee, gardening
- have confidence in: js (incl. nodejs, typescript and react), ui design
- have no confidence in: normal life stuff
- have some experience in: python, go, ruby, swift, rust, pytorch, docker swarm
- language:
- Japanese: native
- English: TOEIC 945, TOEFL 78
- play tin whistle and violin for fun
# Links
- [Open Source @ GitHub](https://github.com/uetchy) - [Open Source @ GitHub](https://github.com/uetchy)
- [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
Reach me at `y@uechi.io`. Should you need extra security for your message or attachments, pick an appropriate encryption method from the list below.
**[GPG](https://gnupg.org/)**
```bash
curl https://uechi.io/uetchy.asc | gpg --import
gpg -er y@uechi.io confidential.zip
# attach `confidential.zip.gpg` to your email
```
Alternatively, download [public key](https://uechi.io/uetchy.asc) for [GPG Keychain](https://gpgtools.org/) (macOS).
**[age](https://github.com/FiloSottile/age#encrypting-to-a-github-user)**
```bash
curl https://github.com/uetchy.keys | age -R - confidential.zip > confidential.zip.age
# attach `confidential.zip.age` to your email
```
## Facts
```yaml
- Interests:
- Webdev, NLP, Reverse-engineering, Category theory, UI design, Coffee
- Machine languages:
- TypeScript, Python, Rust, Go, Ruby, Swift
- Human languages:
- Japanese: native
- English: TOEIC 985
- Korean: r/w hangul
- Indonesian: baby
- Hobby:
- Play tin whistle and fiddle for fun
```

View File

@ -1,11 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBkzCCATqgAwIBAgIRAPer37r9Ln00pxiGmKNcbKEwCgYIKoZIzj0EAwIwKDEO
MAwGA1UEChMFVWNlcnQxFjAUBgNVBAMTDVVjZXJ0IFJvb3QgQ0EwHhcNMjIwMzI1
MDkwNDM3WhcNMzIwMzIyMDkwNDM3WjAoMQ4wDAYDVQQKEwVVY2VydDEWMBQGA1UE
AxMNVWNlcnQgUm9vdCBDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABMpJyIE4
PmaRUAaUWEU2sD8ZZ1TbgtZ2hTZNMseKpv7qQ6uWruTj79nt3QoIxIzar9GpFfCI
RQ2+2X4rGhU58kOjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/
AgEBMB0GA1UdDgQWBBRWW0Facm4mXotUh+mdmB9fGGC1ZTAKBggqhkjOPQQDAgNH
ADBEAiBxX/wDOABgmEW8S/tnhxilRdL/ljdWHhpo6CiUJlwLXwIgC+tDIa/E6uVa
S1XKW+43dFk6cmL/VK/qZSU2yGtf4uM=
-----END CERTIFICATE-----

View File

@ -53,11 +53,11 @@
/> />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/tokyo-night-dark.min.css" href="https://unpkg.com/highlight.js@9.18.1/styles/night-owl.css"
/> />
<%- css('css/index') %> <%- css('css/index') %>
<!-- Feed --> <!-- Feed -->
<link rel="alternate" type="application/atom+xml" title="<%= config.title %>" href="<%= full_url_for(`/feed.xml`) %>" /> <link rel="alternate" type="application/atom+xml" title="<%= config.title %>" href="<%= full_url_for(`/feed.xml`) %>" />
<link rel="alternate" type="application/json" title="<%= config.title %>" href="<%= full_url_for(`/feed.json`) %>" /> <link rel="alternate" type="application/json" title="<%= config.title %>" href="<%= full_url_for(`/feed.json`) %>" />
</head> </head>

View File

@ -4,18 +4,15 @@
/></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="/me">Readme</a>
</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> <a href="https://twitter.com/<%- config.twitter.username %>">Twitter</a>
</li> --> </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 class="article-list"> <section>
<% 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">
@ -32,4 +32,4 @@
</article> </article>
<% }) %> <% }) %>
<%- partial('_partial/paginator') %> <%- partial('_partial/paginator') %>
</section> </section>

View File

@ -1,31 +1,27 @@
<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) { %>
<div class="article__pubdate"> <h3 class="article__pubdate">
<time pubdate><%- date(page.date, "<b>YYYY</b> / MM") %></time> <time pubdate><%- date(page.date, "YYYY / <b>MM</b>") %></time>
</div> </h3>
<% } %> <% } %>
<div class="article__updated"> <h2 class="article__title"><%- page.title %></h2>
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"> <div class="article__content"><%- page.content %></div>
<!-- <%- 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"
@ -33,6 +29,14 @@
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>
@ -48,4 +52,4 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.18.1/languages/lua.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.18.1/languages/lua.min.js"></script>
<script> <script>
hljs.initHighlightingOnLoad() hljs.initHighlightingOnLoad()
</script> --> </script> -->

View File

@ -1,136 +1,69 @@
.article { .article,
font-feature-settings: "kern"; .article-list__item {
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,
text-rendering: geometricprecision; h5 {
font-feature-settings: "kern", "palt"; font-feature-settings: "kern", "palt";
} }
}
h1 { .article {
margin: 2em 0 0; margin-bottom: 60px;
font-size: 2.5rem; }
font-family: "Lora", serif;
@media screen and (max-width: $break-small) { .article-list__item {
margin: 1.5em 0 0.7em; margin: 0 0 60px;
font-size: 2.4rem;
text-align: center;
}
}
h2 {
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;
}
}
h3 {
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 {
margin: 0 0 2px;
font-size: 40px;
}
.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);
} }
blockquote { @media screen and (max-width: $break-small) {
border-left: 5px solid var(--accent); display: block;
padding-left: 20px; text-align: center;
margin: 0; font-size: 17px;
padding: 15px;
&:hover {
background-color: var(--background);
color: var(--tone);
}
} }
} }
@ -145,97 +78,135 @@
margin-right: 4px; margin-right: 4px;
} }
.article-list { .article__metadata {
text-rendering: optimizeLegibility; margin: 40px 0 40px;
font-feature-settings: "kern";
@media screen and (max-width: $break-small) {
margin: 25px 0 25px;
text-align: left;
}
} }
.article-list__item { .article__title {
margin: 0 0 4em; font-size: 4rem;
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;
} }
.article-list__item__title { blockquote {
margin: 0 0 2px; border-left: 5px solid var(--accent);
font-size: 2.5rem; padding-left: 20px;
font-family: "Montserrat", "Noto Sans JP", sans-serif; margin: 0;
text-rendering: geometricprecision; }
font-feature-settings: "kern", "palt";
@media screen and (max-width: $break-small) { pre .caption {
font-size: 2rem; padding: 10px 0;
font-size: 0.8rem;
font-style: italic;
opacity: 0.7;
span {
white-space: break-spaces;
} }
} }
.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;
@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 {
padding: 10px 0;
font-family: monospace;
font-size: 0.8rem;
opacity: 0.7;
span {
white-space: break-spaces;
}
} }
// Pay // Pay

View File

@ -1,4 +1,4 @@
@import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@700&family=Noto+Sans+JP:wght@700&family=Lora&display=swap"); @import url("https://fonts.googleapis.com/css?family=PT+Sans:400,700");
$break-small: 500px; $break-small: 500px;
$break-large: 840px; $break-large: 840px;
@ -10,18 +10,16 @@ $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: #231a37; --background: #261e3a;
--text: #d9d5e1; --text: #e2dfea;
--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;
} }
} }
@ -30,17 +28,14 @@ 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);
@ -50,10 +45,28 @@ body {
} }
} }
a { // Highlight.js
word-break: break-word; .hljs {
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,
@ -61,7 +74,6 @@ a:visited {
color: var(--text); color: var(--text);
text-decoration: none; text-decoration: none;
} }
h1, h1,
h2, h2,
h3, h3,
@ -71,7 +83,6 @@ p {
padding: 0; padding: 0;
line-height: 1.333em; line-height: 1.333em;
} }
hr { hr {
display: block; display: block;
width: 100%; width: 100%;
@ -81,18 +92,19 @@ hr {
margin: 40px 0; margin: 40px 0;
} }
// Header
header.header { header.header {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
margin: 70px 0 70px; margin-top: 60px;
margin-bottom: 80px;
flex-direction: row; flex-direction: row;
justify-content: center; justify-content: flex-start;
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 {
@ -112,18 +124,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: 2px 0; margin: 5px 0;
} }
} }
} }
// Pagination
.page-nav { .page-nav {
display: flex; display: flex;
justify-content: center; justify-content: center;