Accessbility is hard to say, minimize A11y.
ChromeVox Lite
http://www.chromevox.com/
watch out screen reader
https://ja.osdn.net/projects/nvdajp/
ソフトウェアエンジニアの技術ブログ:Software engineer tech blog
随机应变 ABCD: Always Be Coding and … : хороший
Accessbility is hard to say, minimize A11y.
ChromeVox Lite
http://www.chromevox.com/
watch out screen reader
https://ja.osdn.net/projects/nvdajp/
watch out image compression level and natural width.
should be less pixels.
Total bits = pixel x bit per pixel
body { margin: 0; } img { float: left; margin-right: 10px; width: calc((100% - 20px)/3); } img:last-of-type { margin-right: 0; }
Vector scales without quality degradation.
$0.naturalWidth 601 $0.naturalWidth 1202
db-read() -> 100ms
if request in cache,
return cache[request]
cashe is a hashtable
basic cache algorithm is below
import time def complex_computation(a, b): time.sleep(.5) return a + b cache = {} def cached_computation(a, b): key = (a, b) if key in cache: r = cache[key] else: r = complex_computation(a, b) cache[key] = r return r start_time = time.time() print cached_computation(5, 3) print "the first computation took %f second" % (time.time() - start_time)
when db query can be cashed in serverside as dictionary like below.
CACHE = {} def top_arts(); key = 'top' if key in CACHE: arts = CHACHE[key] else: loggin.error("DB QUERY") art = db.GqlQuery("SELECT * From Art " "WHERE ancestor is :1" "ORDER BY DESC") arts = list(arts) CACHE[key] = arts return arts
when posted, cache cleared.
CACHE = {} def top_arts(update = False); key = 'top' if not update and key in CACHE: arts = CHACHE[key] else: loggin.error("DB QUERY") art = db.GqlQuery("SELECT * From Art " "WHERE ancestor is :1" "ORDER BY DESC") arts = list(arts) CACHE[key] = arts return arts
DB read should be only submission.
loadbalancer also can handle large traffic.
load balancere
n = -1 def get_server(): global n n += 1 return SERVERS[n % len(SERVERS)]
handler, url mapping DBmodel
Set-Cookie: name=steve; Domain=www.rddit.com; Path=/
domain is restricted wwww.
Third party set cookie such as google analytics
ad network also set cookie
Set-Cookie: user=123; Expire= Ture, 1 Jan "session" cookie = no Expire
session cookie delete when close the browser.
def get(self): self.response.headers['Content-Type'] = 'text/plain' visits = self.request.cookies.get('visits', 0) if visits.isdigit(); visits = int(visits) + 1 else: visits = 0 self.response.headers.add_header('Set-Cookie', 'visits=%s' % visits) if visits > 100: self.write("you are the best ever") else: self.write("you've been here %s times!" % visits)
write document.cookie in console.
we can rewrite cookie.
document.cookie
"wordpress_test_cookie=WP+Cookie+check; wp-settings-1=editor%3Dhtml%26libraryContent%3Dbrowse%26imgsize%3Dmedium; wp-settings-time-1=1482994300; _ga=GA1.2.511761152.1479929467"
document.cookie="wp-settings-tims-1=1482994301"
"wp-settings-tims-1=1482994301"
Order Allow,Deny Allow from all Deny from .abcde.com Deny from 111.122.133. Deny from 111.122.133.192/26
referer
SetEnvlf Referer "http://hogehoge.com" Ref1 SetEnvlf Referer "http://hogeweb.com" Ref2 Order Deny, Allow Deny from all Allow from env=Ref1 Allow from env=Ref2
files match
<FilesMatch "\.(gif|.jpg?g|png)$"> SetEnvlf Referer "http://hogehoge.com" Ref1 Order Deny, Allow Deny from all Allow from env=Ref1 </FilesMatch>
SetEnvIf REFERER "sample.com" Ref1 Order Deny,Allow Deny from all Allow from env=Ref1
ip
SetEnvIf REFERER "sample.com" Ref1 Order Deny,Allow Deny from all Allow from env=Ref1 <Files ~"\.log$"> Deny from all </Files>
DOSS
tmux is a terminal multiplexer
What is a terminal multiplexer? It lets you switch easily between several programs in one terminal, detach them (they keep running in the background) and reattach them to a different terminal. And do a lot more.
[vagrant@localhost ~]$ sudo yum -y install tmux インストール: tmux.x86_64 0:1.6-3.el6 完了しました!
tmuxの起動
[vagrant@localhost ~]$ tmux new -s ProjectA
Ctrl+Bがデフォルトのコマンドプレフィックスキー
$ top $ ctl + b + d ->[detached]
attach
$tmux a -t ProjectA
session rename
Ctrl+b $
session list
[vagrant@localhost ~]$ tmux ls ProjectA: 1 windows (created Thu Nov 24 13:43:46 2016) [80x23]
session delete : tmux kill-serverで全て削除
[vagrant@localhost ~]$ tmux kill-session -t ProjectB [vagrant@localhost ~]$ tmux ls ProjectA: 1 windows (created Thu Nov 24 13:43:46 2016) [80x23] ProjectC: 1 windows (created Thu Nov 24 13:51:07 2016) [80x23]
ctl + b + ? コマンドキー一覧表示
ctl + b + : コマンドライン表示
ctl + b + t 時計モード
ctl + b + c 新しいwindow(bash)の起動、 ctl + b + 番号、もしくは、n(next), p(previous)でwindow変更
ctl + b + . window名をつける
ctl + b + w window一覧
ctl + b + f window検索
ctl + b + & window削除
ctl + b + ” 水平分割
ctl + b + % 横分割
ctl + b + o pane移動
ctl + b + q 番号指定で移動
clt + b + {} paneの位置移動
ctl + b + x paneの解除
ctl + b + ! windowを開く
paneのサイズ変更
ctl + b : -> :resize-pane -U 5
vi ~/.tmux.conf ファイルにショートカットキーの設定、prefix keyも変更可
set -g C-t unbind C-b bind C-t send-prefix \; display "configuration reloaded" bind r source-file ~/.tmux.conf set -g mode-keys vi bind -r H resize-pane -L 5 bind -r J resize-pane -D 5 bind -r K resize-pane -U 5 bind -r L resize-pane -R 5
web storageは同一オリジンでデータを保存しています。同階層、下ディレクトでも使えます。sessionStorage(タブが閉じられるまで)とloacalStorage(ブラウザ自体に保存)の二種類があります。chrome developer toolのapplicationパネルで確認できます。
<script> (function(){ if (typeof(Storage) === "undefined"){ alert("web storage not supported"); } else { // console.log("supported"); // var s = sessionStorage; var s = localStorage; s.setItem('name', 'okada'); console.log(s.getItem('name')); } })(); </script>
setItemと削除
<script> (function(){ if (typeof(Storage) === "undefined"){ alert("web storage not supported"); } else { var ls = localStorage; var ss = sessionStorage; ls.setItem('yamada', 20); ls.setItem('kimura', 69); ss.setItem('color', 'pink'); ss.setItem('shape', 'cube'); // removeItem(key) // clear() ls.removeItem('yamada'); ss.clear(); } })(); </script>
lengthとkey
<script> (function(){ if (typeof(Storage) === "undefined"){ alert("web storage not supported"); } else { var s = localStorage; s.setItem('okamoto', 90) s.setItem('murata', 60) s.setItem('ito', 50) for (var i = 0; i < s.length; i++){ console.log(s.key(i) + ':' + s.getItem(s.key(i))); } } })(); </script>
JSON(javascript object nation)
<script> (function(){ if (typeof(Storage) === "undefined"){ alert("web storage not supported"); } else { var s = localStorage; var user = { name: 'yoshida', score: 50 }; s.setItem('user', JSON.stringify(user)); console.dir(JSON.parse(s.getItem('user'))); } })(); </script>
データの整合性
<script> (function(){ if (typeof(Storage) === "undefined"){ alert("web storage not supported"); } else { var s = localStorage; s.setItem('name','kurumada'); window.addEventListener('storage', function(e){ console.log(e.key + ':' + e.oldValue + '->' + e.newValue); }); } })(); </script>
<script> var s = '@yamada, @sato, @ito'; var rs = s.match(/yamada/); if (rs){ console.log('マッチしました!'); } </script>
キャレットを使うと、否定、下の例だと、abc以外となります。
[abc]:abc
[a-z]:a~z
[^abc]:abc以外
. :任意の一文字 /y…da/
^ :行頭 /^@yamada/
$ :行末 /@yamada$/
{} :直前の文字の繰り返し回数 0{2} ->00 0{2,}->00以上 0{2,4}->00,000,0000
[a-z]{5} ->a-zの五文字以内
[a-z]{3,6} ->a-zの3~6文字以内
a? : 0or1-> ,a
a* : 0 or more ->, a, aa, aaa
a* : 1 or more -> a, aa, aaa
() :(abc)* -> abc, abcabac
| :or ->(abc|def)
\: \n ->改行, \t ->タブ, \d ->[0-9],\w -> [a-zA-Z0-9_], \s -> スペース \メタ文字 ->メタ文字
i : 大文字小文字を区別しない -> (/yamada/i)
g : 全てのマッチした要素を配列で解す -> s.match(/a/g)
m : 複数行に対応させる -> ^$は一行のみだが、mオプションは複数行
* or + の後の?: 最小マッチ +?, *?
()RegExp s.match(/(.+?)@yamada) , RegExp.$1
例
<script> var s = '@yamada'; var rs = s.match(/(@[A-Za-z0-9_]{1,15})/); console.log(RegExp.$1); </script> <script> var s = '<title>google.com</title>'; var rs = s.match(/<title>([^<]+)<\/title>/); console.log(RegExp.$1); </script>
日付の取得
<script> var s = '2016-12-01'; var rs = s.match(/(\d{4})[-\/](\d{2})[-\/](\d{2})/); console.log(RegExp.$1+'年'+RegExp.$2+'月'+RegExp.$3+'日'); </script>
sublime text3のコンソールに以下のコードを貼り付け、ctl + shift + pでパッケージコントロールをインストールします。
import urllib.request,os,hashlib; h = 'df21e130d211cfc94d9b0905775a7c0f' + '1e3d39e33b79698005270310898eea76'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); by = urllib.request.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); print('Error validating download (got %s instead of %s), please try manual install' % (dh, h)) if dh != h else open(os.path.join( ipp, pf), 'wb' ).write(by)
# Title 1 ## Title 2 ### Title 3
hr,強調、blockquote,コード、インデント
こんにちは --- こんにちは --- こんにちは **strong** > strong 'var = x' var = x var = 7
リスト、リンク、メール、画像
- item 1 - item 2 - item 3 1. item 1 2. item 2 3. item 3 <http://google.com> <hogehoge@gmail.com> [google][1] [1]:http:/google.com ![book](book.jpg)
なお、マークダウン記法の中にhtmlを書くことも許されています。
github https://github.com/revolunet/sublimetext-markdown-preview
hostファイル編集により、下記のように、アドレスバーのhttp://192.168.33.10:8000/を任意のパスに変更する方法です。
まず、Windowsキー + r のショートカットで、「drivers」のフォルダを検索します。
そうしたら、driversのフォルダの中からetcのフォルダを開き、その中にある、hostファイルを開きます。
一番下に 192.168.33.10 dev.hogehoge.com を追加して保存します。「dev.hogehoge.com」は任意のパスを設定してください。
# Copyright (c) 1993-2009 Microsoft Corp. # # This is a sample HOSTS file used by Microsoft TCP/IP for Windows. # # This file contains the mappings of IP addresses to host names. Each # entry should be kept on an individual line. The IP address should # be placed in the first column followed by the corresponding host name. # The IP address and the host name should be separated by at least one # space. # # Additionally, comments (such as these) may be inserted on individual # lines or following the machine name denoted by a '#' symbol. # # For example: # # 102.54.94.97 rhino.acme.com # source server # 38.25.63.10 x.acme.com # x client host # localhost name resolution is handled within DNS itself. # 127.0.0.1 localhost # ::1 localhost 192.168.33.10 dev.hogehoge.com
すると、以降、192.168.33.10でたたいた時は、dev.hogehoge.comに変換されるようになります。